feat: html-ppt AgentSkill — HTML PPT Studio
Token-driven static HTML presentation system. One skill directory under html-ppt/ implementing the full AgentSkills spec. - 24 themes (assets/themes/*.css): minimal-white, editorial-serif, soft-pastel, sharp-mono, arctic-cool, sunset-warm, catppuccin-latte/mocha, dracula, tokyo-night, nord, solarized-light, gruvbox-dark, rose-pine, neo-brutalism, glassmorphism, bauhaus, swiss-grid, terminal-green, xiaohongshu-white, rainbow-gradient, aurora, blueprint, memphis-pop. Each overrides only CSS custom properties consumed by base.css. - 31 single-page layout templates (templates/single-page/) with realistic demo data: cover, toc, section-divider, bullets, two/three-column, big-quote, stat-highlight, kpi-grid, table, code (highlight.js), diff, terminal, flow/arch/mindmap diagrams, timeline, roadmap, gantt, comparison, pros-cons, checklist, image-hero/grid, chart-bar/line/pie/ radar (chart.js), process-steps, cta, thanks. - 27 named animations (assets/animations/animations.css) applied via class="anim-<name>" or data-anim="<name>"; runtime re-triggers on slide enter. Respects prefers-reduced-motion. - Runtime (assets/runtime.js): ←/→/Space/PgUp/PgDn/Home/End nav, F fullscreen, S speaker notes overlay, O overview grid, T cycle themes, A cycle animations, #/N deep-link, progress bar, counter-up tick-up. - Showcase decks: theme-showcase.html (24), animation-showcase.html (27), layout-showcase.html (iframe tour of 30 layouts), deck.html starter. - Scripts: render.sh (headless Chrome at /Applications/Google Chrome.app, 1920×1080, multi-slide via #/N) and new-deck.sh (scaffold from deck.html). - References: themes.md, layouts.md, animations.md, authoring-guide.md. - examples/demo-deck/ — complete 8-slide deck using aurora theme + chart.js. - SKILL.md with trigger keywords (presentation, PPT, slides, keynote, deck, 幻灯片, 演讲稿, reveal, 小红书图文) and authoring rules. - MIT LICENSE, README.md. Author: lewis <sudolewis@gmail.com>
This commit is contained in:
commit
5554a11c85
|
|
@ -0,0 +1,197 @@
|
||||||
|
# Task: Build `html-ppt` AgentSkill
|
||||||
|
|
||||||
|
You are a world-class PPT/presentation designer. Build an AgentSkill named **`html-ppt`** (a.k.a. "HTML PPT Studio") that lets an agent produce professional HTML presentations in many styles, layouts, and animations — all driven by templates.
|
||||||
|
|
||||||
|
## Deliverables
|
||||||
|
|
||||||
|
A single skill directory at the current repo root (`~/clawspace/html-ppt-skill`), structured per the AgentSkills spec (consult the `skill-creator` skill at `~/Library/pnpm/global/5/.pnpm/openclaw@2026.4.1_@napi-rs+canvas@0.1.97/node_modules/openclaw/skills/skill-creator/SKILL.md` FIRST and follow it).
|
||||||
|
|
||||||
|
Must produce:
|
||||||
|
|
||||||
|
```
|
||||||
|
html-ppt/
|
||||||
|
SKILL.md # concise dispatcher + usage rules
|
||||||
|
references/
|
||||||
|
themes.md # every theme catalog + when to use
|
||||||
|
layouts.md # every page-layout catalog
|
||||||
|
animations.md # every animation catalog with names
|
||||||
|
authoring-guide.md # how the agent authors a new deck
|
||||||
|
assets/
|
||||||
|
themes/ # one CSS file per theme (see list below)
|
||||||
|
layouts/ # one HTML partial per layout type
|
||||||
|
animations/ # CSS/JS snippets per animation
|
||||||
|
fonts.css # shared webfont imports
|
||||||
|
base.css # reset + shared tokens
|
||||||
|
runtime.js # keyboard nav, presenter mode, theme switcher
|
||||||
|
templates/
|
||||||
|
deck.html # main multi-slide deck template (reveal-like, keyboard nav)
|
||||||
|
theme-showcase.html # single deck that demos EVERY theme (slide per theme)
|
||||||
|
animation-showcase.html # single deck that demos EVERY animation (named)
|
||||||
|
layout-showcase.html # single deck that demos EVERY layout type
|
||||||
|
single-page/ # one-slide templates per layout, with demo data
|
||||||
|
cover.html
|
||||||
|
toc.html
|
||||||
|
section-divider.html
|
||||||
|
bullets.html
|
||||||
|
two-column.html
|
||||||
|
three-column.html
|
||||||
|
big-quote.html
|
||||||
|
stat-highlight.html
|
||||||
|
kpi-grid.html
|
||||||
|
table.html
|
||||||
|
code.html
|
||||||
|
diff.html
|
||||||
|
terminal.html
|
||||||
|
flow-diagram.html
|
||||||
|
timeline.html
|
||||||
|
roadmap.html
|
||||||
|
mindmap.html
|
||||||
|
comparison.html
|
||||||
|
pros-cons.html
|
||||||
|
todo-checklist.html
|
||||||
|
gantt.html
|
||||||
|
image-hero.html
|
||||||
|
image-grid.html
|
||||||
|
chart-bar.html
|
||||||
|
chart-line.html
|
||||||
|
chart-pie.html
|
||||||
|
chart-radar.html
|
||||||
|
arch-diagram.html
|
||||||
|
process-steps.html
|
||||||
|
cta.html
|
||||||
|
thanks.html
|
||||||
|
scripts/
|
||||||
|
render.sh # headless chrome render a template to PNGs (uses /Applications/Google Chrome.app)
|
||||||
|
new-deck.sh # scaffold new deck from templates/deck.html
|
||||||
|
examples/
|
||||||
|
demo-deck/ # a complete working deck using several layouts + a chosen theme
|
||||||
|
README.md # repo-level overview (separate from SKILL.md)
|
||||||
|
LICENSE # MIT, author: lewis <sudolewis@gmail.com>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirement detail
|
||||||
|
|
||||||
|
### 1. Themes (give each a clear name + description)
|
||||||
|
|
||||||
|
Cover AT LEAST these, each a separate CSS file in `assets/themes/`:
|
||||||
|
|
||||||
|
- `minimal-white` — 极简白,克制高级
|
||||||
|
- `editorial-serif` — 杂志风衬线,高级
|
||||||
|
- `soft-pastel` — 柔和马卡龙
|
||||||
|
- `sharp-mono` — 锐利黑白高对比
|
||||||
|
- `arctic-cool` — 冷色调(蓝/青/石板灰)
|
||||||
|
- `sunset-warm` — 暖色调(橘/珊瑚/琥珀)
|
||||||
|
- `catppuccin-latte` — catppuccin 浅
|
||||||
|
- `catppuccin-mocha` — catppuccin 深
|
||||||
|
- `dracula` — dracula 深色
|
||||||
|
- `tokyo-night`
|
||||||
|
- `nord`
|
||||||
|
- `solarized-light`
|
||||||
|
- `gruvbox-dark`
|
||||||
|
- `rose-pine`
|
||||||
|
- `neo-brutalism` — 厚描边、硬阴影、明黄
|
||||||
|
- `glassmorphism` — 毛玻璃
|
||||||
|
- `bauhaus` — 几何+原色
|
||||||
|
- `swiss-grid` — 瑞士网格、Helvetica 感
|
||||||
|
- `terminal-green` — 绿屏终端
|
||||||
|
- `xiaohongshu-white` — 小红书白底高级感
|
||||||
|
- `rainbow-gradient` — 彩虹渐变点缀(白底)
|
||||||
|
- `aurora` — 极光渐变
|
||||||
|
- `blueprint` — 蓝图工程
|
||||||
|
- `memphis-pop` — 孟菲斯波普
|
||||||
|
|
||||||
|
Each theme defines CSS custom properties (color tokens, fonts, radii, shadows, accent gradients) consumed by `base.css` and every layout. Switching themes = swap one `<link>` or one `data-theme` attribute.
|
||||||
|
|
||||||
|
### 2. Layouts / page types
|
||||||
|
|
||||||
|
Must cover: cover, table of contents, section divider, bullets, two-column, three-column, big quote, stat highlight, KPI grid, table (data), code block (syntax-highlighted, use highlight.js via CDN), diff view, terminal/console, flowchart, timeline, roadmap, mindmap, comparison, pros/cons, TODO checklist, gantt, image hero, image grid, chart (bar/line/pie/radar — use chart.js via CDN), architecture diagram, process steps, CTA, thanks. One file per layout in `templates/single-page/` with realistic demo data so it's usable standalone.
|
||||||
|
|
||||||
|
Extract typography/spacing/alignment patterns from the existing decks at `/Volumes/luluDrive/作品素材/视频/**/*.html` (especially `20260409-升级版知识库/presentation.html`, `20260413-graphify/ppt/graphify.html`, `20260414-hermes-agent/ppt/*.html`, and the 小红书图文 folders). Do NOT copy content; extract typographic rhythm, spacing, gradient treatments, card patterns, footer patterns.
|
||||||
|
|
||||||
|
### 3. Animations (each named, listed in `references/animations.md`)
|
||||||
|
|
||||||
|
Provide CSS + (where needed) minimal JS (no heavy deps). Each animation should be applied by adding a class like `data-anim="rise-in"` or `class="anim-rise-in"`. At least:
|
||||||
|
|
||||||
|
- `fade-up`, `fade-down`, `fade-left`, `fade-right`
|
||||||
|
- `rise-in`, `drop-in`, `zoom-pop`, `blur-in`, `glitch-in`
|
||||||
|
- `typewriter`
|
||||||
|
- `neon-glow`, `shimmer-sweep`, `gradient-flow`
|
||||||
|
- `stagger-list` (children appear one by one)
|
||||||
|
- `counter-up` (numbers tick up)
|
||||||
|
- `path-draw` (SVG line draw)
|
||||||
|
- `parallax-tilt` (3D on hover/enter)
|
||||||
|
- `card-flip-3d`
|
||||||
|
- `cube-rotate-3d`
|
||||||
|
- `page-turn-3d`
|
||||||
|
- `perspective-zoom`
|
||||||
|
- `marquee-scroll`
|
||||||
|
- `kenburns`
|
||||||
|
- `confetti-burst` (on slide enter)
|
||||||
|
- `spotlight` (radial reveal)
|
||||||
|
- `morph-shape` (SVG morph)
|
||||||
|
- `ripple-reveal`
|
||||||
|
|
||||||
|
Give each a one-line description + recommended use case.
|
||||||
|
|
||||||
|
### 4. Runtime
|
||||||
|
|
||||||
|
`assets/runtime.js` must support:
|
||||||
|
|
||||||
|
- ← → / space / PgUp PgDn / Home End navigation
|
||||||
|
- `F` fullscreen, `S` speaker notes overlay, `O` slide overview grid
|
||||||
|
- `T` cycle themes (reads all theme CSS file names from a data attr)
|
||||||
|
- `A` cycle a demo animation on current slide
|
||||||
|
- URL hash `#/3` deep-link to slide 3
|
||||||
|
- Progress bar
|
||||||
|
- Works with zero build — pure static HTML/CSS/JS, CDN deps OK
|
||||||
|
|
||||||
|
### 5. Showcase decks
|
||||||
|
|
||||||
|
- `templates/theme-showcase.html` — one deck, one slide per theme, switchable via `T`. Each slide shows the theme name + a sample layout using that theme so user can eyeball it.
|
||||||
|
- `templates/animation-showcase.html` — one slide per animation, each auto-plays on enter, with the animation name and description visible.
|
||||||
|
- `templates/layout-showcase.html` — one slide per layout type with filled demo data.
|
||||||
|
|
||||||
|
### 6. Demo data
|
||||||
|
|
||||||
|
Everything should render with built-in demo data (fake KPIs, sample code, sample chart data, sample flow) so the user can open any template and immediately see it working.
|
||||||
|
|
||||||
|
### 7. SKILL.md rules
|
||||||
|
|
||||||
|
- Frontmatter: `name: html-ppt`, strong `description` with trigger keywords (presentation, PPT, slides, keynote, deck, 演讲稿, 幻灯片, reveal, html presentation, 小红书图文).
|
||||||
|
- Short body: when to use, how to start (`scripts/new-deck.sh <name>`), how to pick a theme, how to pick layouts, how to add animations, how to render to PNG (`scripts/render.sh <file>`).
|
||||||
|
- Link into `references/*.md` for detail; keep SKILL.md under ~200 lines.
|
||||||
|
|
||||||
|
### 8. render.sh
|
||||||
|
|
||||||
|
Use headless Chrome:
|
||||||
|
```
|
||||||
|
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --headless=new --disable-gpu --hide-scrollbars --window-size=1920,1080 --screenshot=out.png "file://$PWD/$1"
|
||||||
|
```
|
||||||
|
Support multi-slide capture by navigating `#/N` or by extracting each `.slide` region.
|
||||||
|
|
||||||
|
### 9. Author & License
|
||||||
|
|
||||||
|
`LICENSE` = MIT, Copyright (c) 2026 lewis <sudolewis@gmail.com>. `README.md` header shows author lewis <sudolewis@gmail.com>.
|
||||||
|
|
||||||
|
## Process
|
||||||
|
|
||||||
|
1. FIRST read `~/Library/pnpm/global/5/.pnpm/openclaw@2026.4.1_@napi-rs+canvas@0.1.97/node_modules/openclaw/skills/skill-creator/SKILL.md` and follow its conventions.
|
||||||
|
2. Survey the source decks under `/Volumes/luluDrive/作品素材/视频/` (read-only, just for inspiration). Take notes on typography, spacing, card styles.
|
||||||
|
3. Build the skill directory described above. Prefer small, composable CSS token files. Keep each theme CSS short (< 200 lines) — just token overrides.
|
||||||
|
4. Make sure every template renders correctly in Chrome (you can test with `scripts/render.sh` on a few samples).
|
||||||
|
5. Write a concise SKILL.md + rich references/*.md.
|
||||||
|
6. Init git (already initialized in this dir), commit everything as author `lewis <sudolewis@gmail.com>`, with a good message.
|
||||||
|
7. DO NOT push or create the GitHub repo — the user's orchestrator will handle that.
|
||||||
|
|
||||||
|
## Constraints
|
||||||
|
|
||||||
|
- Pure static HTML/CSS/JS. CDN deps allowed: highlight.js, chart.js, a webfont loader. No build step.
|
||||||
|
- Target browser: Chrome / Chromium 120+.
|
||||||
|
- Chinese + English content both supported (import Noto Sans SC).
|
||||||
|
- Keep each file focused; avoid giant monoliths.
|
||||||
|
- Be opinionated and tasteful. You're a senior designer.
|
||||||
|
|
||||||
|
When COMPLETELY finished, run:
|
||||||
|
```
|
||||||
|
openclaw system event --text "Done: html-ppt skill built — $(ls templates/single-page | wc -l | tr -d ' ') layouts, $(ls assets/themes | wc -l | tr -d ' ') themes" --mode now
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 lewis <sudolewis@gmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
# html-ppt — HTML PPT Studio
|
||||||
|
|
||||||
|
Author: **lewis** <sudolewis@gmail.com>
|
||||||
|
License: MIT
|
||||||
|
|
||||||
|
A self-contained AgentSkill for producing professional HTML presentations
|
||||||
|
("slides", "decks", "keynotes", 演讲稿, 幻灯片) in many styles, layouts, and
|
||||||
|
animations — all driven by tasteful, hand-tuned templates.
|
||||||
|
|
||||||
|
- 24 themes (`assets/themes/*.css`)
|
||||||
|
- 30 page layouts (`templates/single-page/*.html`)
|
||||||
|
- 25 named animations (`assets/animations/animations.css`)
|
||||||
|
- Keyboard-driven runtime with presenter mode, theme cycling, overview grid
|
||||||
|
- Zero build: pure static HTML/CSS/JS, CDN deps only (Noto Sans SC, Inter,
|
||||||
|
JetBrains Mono, highlight.js, chart.js)
|
||||||
|
- Showcase decks for every theme / layout / animation
|
||||||
|
- Headless-Chrome PNG renderer script
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# scaffold a new deck
|
||||||
|
./scripts/new-deck.sh my-talk
|
||||||
|
|
||||||
|
# render a template to PNG
|
||||||
|
./scripts/render.sh templates/theme-showcase.html
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `templates/theme-showcase.html` / `templates/layout-showcase.html` /
|
||||||
|
`templates/animation-showcase.html` in Chrome to browse the whole catalog.
|
||||||
|
|
||||||
|
See `SKILL.md` for the agent-facing usage guide and `references/` for the
|
||||||
|
full theme / layout / animation catalogs.
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
---
|
||||||
|
name: html-ppt
|
||||||
|
description: HTML PPT Studio — author professional static HTML presentations in many styles, layouts, and animations, all driven by templates. Use when the user asks for a presentation, PPT, slides, keynote, deck, slideshow, "幻灯片", "演讲稿", "做一份 PPT", "做一份 slides", a reveal-style HTML deck, a 小红书 图文, or any kind of multi-slide pitch/report/sharing document that should look tasteful and be usable with keyboard navigation. Triggers include keywords like "presentation", "ppt", "slides", "deck", "keynote", "reveal", "slideshow", "幻灯片", "演讲稿", "分享稿", "小红书图文", "talk slides", "pitch deck", "tech sharing", "technical presentation".
|
||||||
|
---
|
||||||
|
|
||||||
|
# html-ppt — HTML PPT Studio
|
||||||
|
|
||||||
|
Author professional HTML presentations as static files. One theme file = one
|
||||||
|
look. One layout file = one page type. One animation class = one entry effect.
|
||||||
|
All pages share a token-based design system in `assets/base.css`.
|
||||||
|
|
||||||
|
Tell the user this skill gives them:
|
||||||
|
- **24 themes** (`assets/themes/*.css`) from minimal-white to aurora
|
||||||
|
- **30 layouts** (`templates/single-page/*.html`) with realistic demo data
|
||||||
|
- **25 named animations** (`assets/animations/animations.css`) applied via `data-anim`
|
||||||
|
- **Keyboard runtime** (`assets/runtime.js`) — arrows, T (theme), A (anim), F/S/O
|
||||||
|
- **Showcase decks** for theme / layout / animation catalogs
|
||||||
|
- **Headless Chrome render script** for PNG export
|
||||||
|
|
||||||
|
## When to use
|
||||||
|
|
||||||
|
Use when the user asks for any kind of slide-based output or wants to turn
|
||||||
|
text/notes into a presentable deck. Prefer this over building from scratch.
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
1. **Scaffold a new deck.** From the repo root:
|
||||||
|
```bash
|
||||||
|
./scripts/new-deck.sh my-talk
|
||||||
|
open examples/my-talk/index.html
|
||||||
|
```
|
||||||
|
2. **Pick a theme.** Open the deck and press `T` to cycle. Or hard-code it:
|
||||||
|
```html
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../assets/themes/aurora.css">
|
||||||
|
```
|
||||||
|
Catalog in [references/themes.md](references/themes.md).
|
||||||
|
3. **Pick layouts.** Copy `<section class="slide">...</section>` blocks out of
|
||||||
|
files in `templates/single-page/` into your deck. Replace the demo data.
|
||||||
|
Catalog in [references/layouts.md](references/layouts.md).
|
||||||
|
4. **Add animations.** Put `data-anim="fade-up"` (or `class="anim-fade-up"`) on
|
||||||
|
any element. On `<ul>`/grids, use `anim-stagger-list` for sequenced reveals.
|
||||||
|
Catalog in [references/animations.md](references/animations.md).
|
||||||
|
5. **Render to PNG.**
|
||||||
|
```bash
|
||||||
|
./scripts/render.sh templates/theme-showcase.html # one shot
|
||||||
|
./scripts/render.sh examples/my-talk/index.html 12 # 12 slides
|
||||||
|
```
|
||||||
|
|
||||||
|
## Authoring rules (important)
|
||||||
|
|
||||||
|
- **Always start from a template.** Don't author slides from scratch — copy the
|
||||||
|
closest layout from `templates/single-page/` first, then replace content.
|
||||||
|
- **Use tokens, not literal colors.** Every color, radius, shadow should come
|
||||||
|
from CSS variables defined in `assets/base.css` and overridden by a theme.
|
||||||
|
Good: `color: var(--text-1)`. Bad: `color: #111`.
|
||||||
|
- **Don't invent new layout files.** Prefer composing existing ones. Only add
|
||||||
|
a new `templates/single-page/*.html` if none of the 30 fit.
|
||||||
|
- **Respect chrome slots.** `.deck-header`, `.deck-footer`, `.slide-number`
|
||||||
|
and the progress bar are provided by `assets/base.css` + `runtime.js`.
|
||||||
|
- **Keyboard-first.** Always include `<script src="../assets/runtime.js"></script>`
|
||||||
|
so the deck supports ← → / T / A / F / S / O / hash deep-links.
|
||||||
|
- **One `.slide` per logical page.** `runtime.js` makes `.slide.is-active`
|
||||||
|
visible; all others are hidden.
|
||||||
|
- **Supply notes.** Wrap speaker notes in `<div class="notes">…</div>` inside
|
||||||
|
each slide. Press S to open the overlay.
|
||||||
|
|
||||||
|
## Writing guide
|
||||||
|
|
||||||
|
See [references/authoring-guide.md](references/authoring-guide.md) for a
|
||||||
|
step-by-step walkthrough: file structure, naming, how to transform an outline
|
||||||
|
into a deck, how to choose layouts and themes per audience, how to do a
|
||||||
|
Chinese + English deck, and how to export.
|
||||||
|
|
||||||
|
## Catalogs (load when needed)
|
||||||
|
|
||||||
|
- [references/themes.md](references/themes.md) — all 24 themes with when-to-use.
|
||||||
|
- [references/layouts.md](references/layouts.md) — all 30 layout types.
|
||||||
|
- [references/animations.md](references/animations.md) — all 25 animations.
|
||||||
|
- [references/authoring-guide.md](references/authoring-guide.md) — full workflow.
|
||||||
|
|
||||||
|
## File structure
|
||||||
|
|
||||||
|
```
|
||||||
|
html-ppt/
|
||||||
|
├── SKILL.md (this file)
|
||||||
|
├── references/ (detailed catalogs, load as needed)
|
||||||
|
├── assets/
|
||||||
|
│ ├── base.css (tokens + primitives — do not edit per deck)
|
||||||
|
│ ├── fonts.css (webfont imports)
|
||||||
|
│ ├── runtime.js (keyboard + presenter + overview + theme cycle)
|
||||||
|
│ ├── themes/*.css (24 token overrides, one per theme)
|
||||||
|
│ └── animations/animations.css (25 named entry animations)
|
||||||
|
├── templates/
|
||||||
|
│ ├── deck.html (minimal 6-slide starter)
|
||||||
|
│ ├── theme-showcase.html (24 slides, one per theme)
|
||||||
|
│ ├── layout-showcase.html (iframe tour of all 30 layouts)
|
||||||
|
│ ├── animation-showcase.html (27 slides, one per animation)
|
||||||
|
│ └── single-page/*.html (30 layout files with demo data)
|
||||||
|
├── scripts/
|
||||||
|
│ ├── new-deck.sh (scaffold a deck from deck.html)
|
||||||
|
│ └── render.sh (headless Chrome → PNG)
|
||||||
|
└── examples/demo-deck/ (complete working deck)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rendering to PNG
|
||||||
|
|
||||||
|
`scripts/render.sh` wraps headless Chrome at
|
||||||
|
`/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`. For multi-slide
|
||||||
|
capture, runtime.js exposes `#/N` deep-links, and render.sh iterates 1..N.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/render.sh templates/single-page/kpi-grid.html # single page
|
||||||
|
./scripts/render.sh examples/demo-deck/index.html 8 out-dir # 8 slides, custom dir
|
||||||
|
```
|
||||||
|
|
||||||
|
## Keyboard cheat sheet
|
||||||
|
|
||||||
|
```
|
||||||
|
← → Space PgUp PgDn Home End navigate
|
||||||
|
F fullscreen
|
||||||
|
S speaker notes overlay
|
||||||
|
O slide overview grid
|
||||||
|
T cycle themes (reads data-themes attr)
|
||||||
|
A cycle demo animation on current slide
|
||||||
|
#/N in URL deep-link to slide N
|
||||||
|
```
|
||||||
|
|
||||||
|
## License & author
|
||||||
|
|
||||||
|
MIT. Copyright (c) 2026 lewis <sudolewis@gmail.com>.
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
/* html-ppt :: animations.css
|
||||||
|
* Apply by adding class="anim-<name>" or data-anim="<name>".
|
||||||
|
* Durations are deliberately snappy; tweak --anim-dur per element.
|
||||||
|
*/
|
||||||
|
:root{--anim-dur:.7s;--anim-ease:cubic-bezier(.4,0,.2,1)}
|
||||||
|
|
||||||
|
/* ---------- FADE DIRECTIONALS ---------- */
|
||||||
|
@keyframes kf-fade-up{from{opacity:0;transform:translateY(32px)}to{opacity:1;transform:none}}
|
||||||
|
@keyframes kf-fade-down{from{opacity:0;transform:translateY(-32px)}to{opacity:1;transform:none}}
|
||||||
|
@keyframes kf-fade-left{from{opacity:0;transform:translateX(-40px)}to{opacity:1;transform:none}}
|
||||||
|
@keyframes kf-fade-right{from{opacity:0;transform:translateX(40px)}to{opacity:1;transform:none}}
|
||||||
|
.anim-fade-up{animation:kf-fade-up var(--anim-dur) var(--anim-ease) both}
|
||||||
|
.anim-fade-down{animation:kf-fade-down var(--anim-dur) var(--anim-ease) both}
|
||||||
|
.anim-fade-left{animation:kf-fade-left var(--anim-dur) var(--anim-ease) both}
|
||||||
|
.anim-fade-right{animation:kf-fade-right var(--anim-dur) var(--anim-ease) both}
|
||||||
|
|
||||||
|
/* ---------- RISE / DROP / ZOOM / BLUR / GLITCH ---------- */
|
||||||
|
@keyframes kf-rise{from{opacity:0;transform:translateY(60px) scale(.97);filter:blur(6px)}to{opacity:1;transform:none;filter:none}}
|
||||||
|
@keyframes kf-drop{from{opacity:0;transform:translateY(-60px) scale(.97)}to{opacity:1;transform:none}}
|
||||||
|
@keyframes kf-zoom{0%{opacity:0;transform:scale(.6)}60%{transform:scale(1.04)}100%{opacity:1;transform:scale(1)}}
|
||||||
|
@keyframes kf-blur{from{opacity:0;filter:blur(18px)}to{opacity:1;filter:none}}
|
||||||
|
@keyframes kf-glitch{0%{opacity:0;transform:translateX(0);clip-path:inset(0 0 0 0)}
|
||||||
|
20%{opacity:1;transform:translateX(-6px);clip-path:inset(20% 0 30% 0)}
|
||||||
|
40%{transform:translateX(4px);clip-path:inset(50% 0 10% 0)}
|
||||||
|
60%{transform:translateX(-3px);clip-path:inset(10% 0 60% 0)}
|
||||||
|
80%{transform:translateX(2px);clip-path:inset(0 0 0 0)}
|
||||||
|
100%{opacity:1;transform:none}}
|
||||||
|
.anim-rise-in{animation:kf-rise .9s var(--anim-ease) both}
|
||||||
|
.anim-drop-in{animation:kf-drop .8s var(--anim-ease) both}
|
||||||
|
.anim-zoom-pop{animation:kf-zoom .7s cubic-bezier(.22,1.3,.36,1) both}
|
||||||
|
.anim-blur-in{animation:kf-blur .8s var(--anim-ease) both}
|
||||||
|
.anim-glitch-in{animation:kf-glitch .8s steps(5,end) both}
|
||||||
|
|
||||||
|
/* ---------- TYPEWRITER ---------- */
|
||||||
|
.anim-typewriter{display:inline-block;overflow:hidden;white-space:nowrap;border-right:2px solid currentColor;
|
||||||
|
width:0;animation:kf-type 2.4s steps(40,end) forwards, kf-caret 1s step-end infinite}
|
||||||
|
@keyframes kf-type{to{width:100%}}
|
||||||
|
@keyframes kf-caret{50%{border-color:transparent}}
|
||||||
|
|
||||||
|
/* ---------- GLOW / SHIMMER / GRADIENT-FLOW ---------- */
|
||||||
|
@keyframes kf-neon{0%,100%{text-shadow:0 0 8px var(--accent),0 0 20px var(--accent)}
|
||||||
|
50%{text-shadow:0 0 16px var(--accent),0 0 40px var(--accent),0 0 80px var(--accent)}}
|
||||||
|
.anim-neon-glow{animation:kf-neon 2s ease-in-out infinite}
|
||||||
|
|
||||||
|
.anim-shimmer-sweep{position:relative;overflow:hidden}
|
||||||
|
.anim-shimmer-sweep::after{content:"";position:absolute;inset:0;
|
||||||
|
background:linear-gradient(110deg,transparent 40%,rgba(255,255,255,.55) 50%,transparent 60%);
|
||||||
|
transform:translateX(-100%);animation:kf-shimmer 2.4s var(--anim-ease) infinite}
|
||||||
|
@keyframes kf-shimmer{to{transform:translateX(100%)}}
|
||||||
|
|
||||||
|
.anim-gradient-flow{background:linear-gradient(90deg,var(--accent),var(--accent-2,var(--accent)),var(--accent-3,var(--accent)),var(--accent));
|
||||||
|
background-size:300% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent;
|
||||||
|
animation:kf-gradflow 4s linear infinite}
|
||||||
|
@keyframes kf-gradflow{to{background-position:300% 0}}
|
||||||
|
|
||||||
|
/* ---------- STAGGER LIST ---------- */
|
||||||
|
.anim-stagger-list > *{opacity:0;animation:kf-rise .65s var(--anim-ease) both}
|
||||||
|
.anim-stagger-list > *:nth-child(1){animation-delay:.05s}
|
||||||
|
.anim-stagger-list > *:nth-child(2){animation-delay:.15s}
|
||||||
|
.anim-stagger-list > *:nth-child(3){animation-delay:.25s}
|
||||||
|
.anim-stagger-list > *:nth-child(4){animation-delay:.35s}
|
||||||
|
.anim-stagger-list > *:nth-child(5){animation-delay:.45s}
|
||||||
|
.anim-stagger-list > *:nth-child(6){animation-delay:.55s}
|
||||||
|
.anim-stagger-list > *:nth-child(7){animation-delay:.65s}
|
||||||
|
.anim-stagger-list > *:nth-child(8){animation-delay:.75s}
|
||||||
|
.anim-stagger-list > *:nth-child(n+9){animation-delay:.85s}
|
||||||
|
|
||||||
|
/* ---------- COUNTER-UP (JS-driven, marker class only) ---------- */
|
||||||
|
.counter{font-variant-numeric:tabular-nums}
|
||||||
|
|
||||||
|
/* ---------- SVG PATH DRAW ---------- */
|
||||||
|
.anim-path-draw path,.anim-path-draw line,.anim-path-draw polyline,.anim-path-draw circle,.anim-path-draw rect{
|
||||||
|
stroke-dasharray:1000;stroke-dashoffset:1000;animation:kf-draw 2s var(--anim-ease) forwards}
|
||||||
|
@keyframes kf-draw{to{stroke-dashoffset:0}}
|
||||||
|
|
||||||
|
/* ---------- PARALLAX TILT (hover) ---------- */
|
||||||
|
.anim-parallax-tilt{transform-style:preserve-3d;transition:transform .4s var(--anim-ease)}
|
||||||
|
.anim-parallax-tilt:hover{transform:perspective(900px) rotateX(6deg) rotateY(-8deg) translateZ(10px)}
|
||||||
|
|
||||||
|
/* ---------- CARD FLIP 3D ---------- */
|
||||||
|
@keyframes kf-flip{from{transform:perspective(1200px) rotateY(-90deg);opacity:0}
|
||||||
|
to{transform:perspective(1200px) rotateY(0);opacity:1}}
|
||||||
|
.anim-card-flip-3d{animation:kf-flip .9s var(--anim-ease) both;transform-style:preserve-3d;backface-visibility:hidden}
|
||||||
|
|
||||||
|
/* ---------- CUBE ROTATE 3D ---------- */
|
||||||
|
@keyframes kf-cube{from{transform:perspective(1200px) rotateX(20deg) rotateY(-90deg) translateZ(-200px);opacity:0}
|
||||||
|
to{transform:perspective(1200px) rotateX(0) rotateY(0) translateZ(0);opacity:1}}
|
||||||
|
.anim-cube-rotate-3d{animation:kf-cube 1s var(--anim-ease) both}
|
||||||
|
|
||||||
|
/* ---------- PAGE TURN 3D ---------- */
|
||||||
|
@keyframes kf-pageturn{from{transform:perspective(1600px) rotateY(-85deg);transform-origin:left center;opacity:0}
|
||||||
|
to{transform:perspective(1600px) rotateY(0);opacity:1}}
|
||||||
|
.anim-page-turn-3d{animation:kf-pageturn 1s var(--anim-ease) both;transform-origin:left center}
|
||||||
|
|
||||||
|
/* ---------- PERSPECTIVE ZOOM ---------- */
|
||||||
|
@keyframes kf-pzoom{from{opacity:0;transform:perspective(1400px) translateZ(-400px) rotateX(12deg)}
|
||||||
|
to{opacity:1;transform:none}}
|
||||||
|
.anim-perspective-zoom{animation:kf-pzoom 1s var(--anim-ease) both}
|
||||||
|
|
||||||
|
/* ---------- MARQUEE SCROLL ---------- */
|
||||||
|
.anim-marquee-scroll{display:flex;gap:48px;white-space:nowrap;animation:kf-marquee 20s linear infinite}
|
||||||
|
@keyframes kf-marquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
|
||||||
|
|
||||||
|
/* ---------- KEN BURNS ---------- */
|
||||||
|
@keyframes kf-kenburns{0%{transform:scale(1) translate(0,0)}100%{transform:scale(1.15) translate(-2%,-1%)}}
|
||||||
|
.anim-kenburns{animation:kf-kenburns 14s ease-in-out infinite alternate}
|
||||||
|
|
||||||
|
/* ---------- CONFETTI BURST (pseudo — pure CSS sparkles) ---------- */
|
||||||
|
.anim-confetti-burst{position:relative}
|
||||||
|
.anim-confetti-burst::before,.anim-confetti-burst::after{
|
||||||
|
content:"";position:absolute;top:50%;left:50%;width:8px;height:8px;border-radius:50%;
|
||||||
|
background:var(--accent);box-shadow:
|
||||||
|
20px -30px 0 var(--accent-2,var(--accent)),-25px -20px 0 var(--accent-3,var(--accent)),
|
||||||
|
30px 20px 0 var(--good,#1aaf6c),-30px 25px 0 var(--warn,#f5a524),
|
||||||
|
40px -10px 0 var(--bad,#e0445a),-45px 0 0 var(--accent),
|
||||||
|
10px 40px 0 var(--accent-2,var(--accent)),-15px -40px 0 var(--accent-3,var(--accent));
|
||||||
|
opacity:0;animation:kf-confetti 1.2s var(--anim-ease) forwards}
|
||||||
|
.anim-confetti-burst::after{animation-delay:.15s;transform:rotate(45deg)}
|
||||||
|
@keyframes kf-confetti{0%{opacity:0;transform:scale(.2)}30%{opacity:1}100%{opacity:0;transform:scale(2.2)}}
|
||||||
|
|
||||||
|
/* ---------- SPOTLIGHT ---------- */
|
||||||
|
@keyframes kf-spot{0%{clip-path:circle(0% at 50% 50%)}100%{clip-path:circle(140% at 50% 50%)}}
|
||||||
|
.anim-spotlight{animation:kf-spot 1.1s var(--anim-ease) both}
|
||||||
|
|
||||||
|
/* ---------- MORPH SHAPE (SVG) ---------- */
|
||||||
|
.anim-morph-shape path{animation:kf-morph 6s ease-in-out infinite alternate}
|
||||||
|
@keyframes kf-morph{0%{d:path("M60,120 Q120,20 180,120 T300,120")}
|
||||||
|
100%{d:path("M60,120 Q120,220 180,120 T300,120")}}
|
||||||
|
|
||||||
|
/* ---------- RIPPLE REVEAL ---------- */
|
||||||
|
@keyframes kf-ripple{0%{clip-path:circle(0% at 20% 80%);opacity:.4}
|
||||||
|
100%{clip-path:circle(160% at 20% 80%);opacity:1}}
|
||||||
|
.anim-ripple-reveal{animation:kf-ripple 1.2s var(--anim-ease) both}
|
||||||
|
|
||||||
|
/* reduced motion */
|
||||||
|
@media (prefers-reduced-motion: reduce){
|
||||||
|
[class*="anim-"]{animation:none!important;transition:none!important}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,143 @@
|
||||||
|
/* html-ppt :: base.css — reset + shared tokens + layout primitives */
|
||||||
|
/* Default tokens. Themes in assets/themes/*.css override the :root block. */
|
||||||
|
:root {
|
||||||
|
--bg: #ffffff;
|
||||||
|
--bg-soft: #f7f7f8;
|
||||||
|
--surface: #ffffff;
|
||||||
|
--surface-2: #f2f2f4;
|
||||||
|
--border: rgba(0,0,0,.08);
|
||||||
|
--border-strong: rgba(0,0,0,.16);
|
||||||
|
--text-1: #111216;
|
||||||
|
--text-2: #55596a;
|
||||||
|
--text-3: #8a8f9e;
|
||||||
|
--accent: #3b6cff;
|
||||||
|
--accent-2: #7a5cff;
|
||||||
|
--accent-3: #ff5c8a;
|
||||||
|
--good: #1aaf6c;
|
||||||
|
--warn: #f5a524;
|
||||||
|
--bad: #e0445a;
|
||||||
|
--grad: linear-gradient(135deg,#3b6cff,#7a5cff 55%,#ff5c8a);
|
||||||
|
--grad-soft: linear-gradient(135deg,#eef2ff,#f5ecff 55%,#ffeef5);
|
||||||
|
--radius: 18px;
|
||||||
|
--radius-sm: 12px;
|
||||||
|
--radius-lg: 26px;
|
||||||
|
--shadow: 0 10px 30px rgba(18,24,40,.08), 0 2px 6px rgba(18,24,40,.04);
|
||||||
|
--shadow-lg: 0 24px 60px rgba(18,24,40,.14), 0 6px 16px rgba(18,24,40,.06);
|
||||||
|
--font-sans: 'Inter','Noto Sans SC',-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif;
|
||||||
|
--font-serif: 'Playfair Display','Noto Serif SC',Georgia,serif;
|
||||||
|
--font-mono: 'JetBrains Mono','IBM Plex Mono',SFMono-Regular,Menlo,monospace;
|
||||||
|
--font-display: var(--font-sans);
|
||||||
|
--letter-tight: -.03em;
|
||||||
|
--letter-normal: -.01em;
|
||||||
|
--ease: cubic-bezier(.4,0,.2,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
*,*::before,*::after{box-sizing:border-box}
|
||||||
|
html,body{margin:0;padding:0;background:var(--bg);color:var(--text-1);
|
||||||
|
font-family:var(--font-sans);font-weight:400;line-height:1.6;
|
||||||
|
-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
|
||||||
|
letter-spacing:var(--letter-normal)}
|
||||||
|
img,svg,video{max-width:100%;display:block}
|
||||||
|
a{color:var(--accent);text-decoration:none}
|
||||||
|
a:hover{text-decoration:underline}
|
||||||
|
code,kbd,pre,samp{font-family:var(--font-mono)}
|
||||||
|
|
||||||
|
/* ================= SLIDE SYSTEM ================= */
|
||||||
|
.deck{position:relative;width:100vw;height:100vh;overflow:hidden;background:var(--bg)}
|
||||||
|
.slide{
|
||||||
|
position:absolute;inset:0;
|
||||||
|
display:flex;flex-direction:column;justify-content:center;
|
||||||
|
padding:72px 96px;
|
||||||
|
box-sizing:border-box;
|
||||||
|
opacity:0;pointer-events:none;
|
||||||
|
transition:opacity .5s var(--ease), transform .5s var(--ease);
|
||||||
|
transform:translateX(30px);
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
.slide.is-active{opacity:1;pointer-events:auto;transform:translateX(0);z-index:2}
|
||||||
|
.slide.is-prev{transform:translateX(-30px)}
|
||||||
|
|
||||||
|
/* single-page standalone (used when a layout file is opened directly) */
|
||||||
|
body.single .slide{position:relative;width:100vw;height:100vh;opacity:1;transform:none;pointer-events:auto}
|
||||||
|
|
||||||
|
/* ================= TYPOGRAPHY ================= */
|
||||||
|
.eyebrow{font-size:13px;font-weight:500;letter-spacing:.16em;text-transform:uppercase;color:var(--text-3)}
|
||||||
|
.kicker{font-size:14px;font-weight:600;color:var(--accent);letter-spacing:.08em;text-transform:uppercase}
|
||||||
|
h1.title,.h1{font-family:var(--font-display);font-size:72px;line-height:1.05;font-weight:800;letter-spacing:var(--letter-tight);margin:0 0 18px;color:var(--text-1)}
|
||||||
|
h2.title,.h2{font-family:var(--font-display);font-size:54px;line-height:1.1;font-weight:700;letter-spacing:var(--letter-tight);margin:0 0 14px}
|
||||||
|
h3,.h3{font-size:32px;line-height:1.2;font-weight:600;letter-spacing:var(--letter-normal);margin:0 0 10px}
|
||||||
|
h4,.h4{font-size:22px;line-height:1.3;font-weight:600;margin:0 0 8px}
|
||||||
|
.lede{font-size:22px;line-height:1.55;color:var(--text-2);font-weight:300;max-width:62ch}
|
||||||
|
.dim{color:var(--text-2)}
|
||||||
|
.dim2{color:var(--text-3)}
|
||||||
|
.mono{font-family:var(--font-mono)}
|
||||||
|
.serif{font-family:var(--font-serif)}
|
||||||
|
.gradient-text{background:var(--grad);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent}
|
||||||
|
|
||||||
|
/* ================= LAYOUT PRIMITIVES ================= */
|
||||||
|
.stack>*+*{margin-top:14px}
|
||||||
|
.row{display:flex;gap:24px;align-items:center}
|
||||||
|
.row.wrap{flex-wrap:wrap}
|
||||||
|
.grid{display:grid;gap:24px}
|
||||||
|
.g2{grid-template-columns:repeat(2,1fr)}
|
||||||
|
.g3{grid-template-columns:repeat(3,1fr)}
|
||||||
|
.g4{grid-template-columns:repeat(4,1fr)}
|
||||||
|
.center{display:flex;align-items:center;justify-content:center;text-align:center}
|
||||||
|
.fill{flex:1}
|
||||||
|
.sp-t{padding-top:24px}.sp-b{padding-bottom:24px}
|
||||||
|
.mt-s{margin-top:8px}.mt-m{margin-top:18px}.mt-l{margin-top:32px}
|
||||||
|
.mb-s{margin-bottom:8px}.mb-m{margin-bottom:18px}.mb-l{margin-bottom:32px}
|
||||||
|
|
||||||
|
/* ================= CARDS ================= */
|
||||||
|
.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
|
||||||
|
padding:26px 28px;box-shadow:var(--shadow);position:relative;overflow:hidden}
|
||||||
|
.card-soft{background:var(--surface-2);border:1px solid var(--border)}
|
||||||
|
.card-outline{background:transparent;border:1.5px solid var(--border-strong);box-shadow:none}
|
||||||
|
.card-accent{background:var(--surface);border-top:3px solid var(--accent)}
|
||||||
|
.card-hover{transition:transform .3s var(--ease),box-shadow .3s var(--ease)}
|
||||||
|
.card-hover:hover{transform:translateY(-4px);box-shadow:var(--shadow-lg)}
|
||||||
|
|
||||||
|
.pill{display:inline-block;padding:4px 12px;border-radius:999px;font-size:12px;font-weight:500;
|
||||||
|
background:var(--surface-2);color:var(--text-2);border:1px solid var(--border)}
|
||||||
|
.pill-accent{background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--accent);border-color:color-mix(in srgb,var(--accent) 28%,transparent)}
|
||||||
|
|
||||||
|
/* ================= BARS / DIVIDERS ================= */
|
||||||
|
.divider{height:1px;background:var(--border);width:100%}
|
||||||
|
.divider-accent{height:3px;width:72px;background:var(--accent);border-radius:2px}
|
||||||
|
|
||||||
|
/* ================= CHROME (header/footer/progress) ================= */
|
||||||
|
.deck-header{position:absolute;top:24px;left:40px;right:40px;display:flex;align-items:center;justify-content:space-between;
|
||||||
|
font-size:12px;color:var(--text-3);letter-spacing:.12em;text-transform:uppercase;z-index:10;pointer-events:none}
|
||||||
|
.deck-footer{position:absolute;bottom:24px;left:40px;right:40px;display:flex;align-items:center;justify-content:space-between;
|
||||||
|
font-size:12px;color:var(--text-3);z-index:10;pointer-events:none}
|
||||||
|
.slide-number::before{content:attr(data-current)}
|
||||||
|
.slide-number::after{content:" / " attr(data-total)}
|
||||||
|
.progress-bar{position:fixed;left:0;right:0;bottom:0;height:3px;background:transparent;z-index:20}
|
||||||
|
.progress-bar > span{display:block;height:100%;width:0;background:var(--accent);transition:width .3s var(--ease)}
|
||||||
|
|
||||||
|
/* ================= PRESENTER / OVERVIEW ================= */
|
||||||
|
.notes-overlay{position:fixed;inset:auto 0 0 0;max-height:42vh;background:rgba(20,22,30,.95);color:#e8ebf4;
|
||||||
|
padding:20px 32px;font-size:16px;line-height:1.6;border-top:1px solid rgba(255,255,255,.1);transform:translateY(100%);
|
||||||
|
transition:transform .3s var(--ease);z-index:40;overflow:auto;font-family:var(--font-sans)}
|
||||||
|
.notes-overlay.open{transform:translateY(0)}
|
||||||
|
.overview{position:fixed;inset:0;background:rgba(10,12,18,.92);backdrop-filter:blur(12px);z-index:50;
|
||||||
|
display:none;padding:40px;overflow:auto}
|
||||||
|
.overview.open{display:grid;grid-template-columns:repeat(4,1fr);gap:20px;align-content:start}
|
||||||
|
.overview .thumb{background:var(--surface);border:1px solid var(--border);border-radius:12px;
|
||||||
|
aspect-ratio:16/9;overflow:hidden;cursor:pointer;position:relative;color:var(--text-1);padding:16px;
|
||||||
|
font-size:11px;transition:transform .2s var(--ease)}
|
||||||
|
.overview .thumb:hover{transform:scale(1.04)}
|
||||||
|
.overview .thumb .n{position:absolute;top:8px;left:10px;font-weight:700;font-size:14px;color:var(--text-3)}
|
||||||
|
.overview .thumb .t{position:absolute;bottom:10px;left:14px;right:14px;font-weight:600;color:var(--text-1)}
|
||||||
|
|
||||||
|
/* ================= UTILITY ================= */
|
||||||
|
.hidden{display:none!important}
|
||||||
|
.nowrap{white-space:nowrap}
|
||||||
|
.tr{text-align:right}.tc{text-align:center}.tl{text-align:left}
|
||||||
|
.uppercase{text-transform:uppercase;letter-spacing:.12em}
|
||||||
|
|
||||||
|
/* ================= PRINT ================= */
|
||||||
|
@media print{
|
||||||
|
.slide{position:relative;opacity:1!important;transform:none!important;page-break-after:always;height:100vh}
|
||||||
|
.deck-header,.deck-footer,.progress-bar,.notes-overlay,.overview{display:none!important}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
/* html-ppt :: shared webfonts */
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@200;300;400;500;600;700;800;900&display=swap');
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@200;300;400;500;600;700;900&display=swap');
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@300;400;600;700&display=swap');
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap');
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,600;0,800;1,400&display=swap');
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@300;400;500;700&display=swap');
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Archivo+Black&display=swap');
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
/* html-ppt :: runtime.js
|
||||||
|
* Keyboard-driven deck runtime. Zero dependencies.
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* ← → / space / PgUp PgDn / Home End navigation
|
||||||
|
* F fullscreen
|
||||||
|
* S speaker notes overlay
|
||||||
|
* O slide overview grid
|
||||||
|
* T cycle themes (reads data-themes on <html> or <body>)
|
||||||
|
* A cycle demo animation on current slide
|
||||||
|
* URL hash #/N deep-link to slide N (1-based)
|
||||||
|
* Progress bar auto-managed
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ANIMS = ['fade-up','fade-down','fade-left','fade-right','rise-in','drop-in',
|
||||||
|
'zoom-pop','blur-in','glitch-in','typewriter','neon-glow','shimmer-sweep',
|
||||||
|
'gradient-flow','stagger-list','counter-up','path-draw','parallax-tilt',
|
||||||
|
'card-flip-3d','cube-rotate-3d','page-turn-3d','perspective-zoom',
|
||||||
|
'marquee-scroll','kenburns','confetti-burst','spotlight','morph-shape','ripple-reveal'];
|
||||||
|
|
||||||
|
function ready(fn){ if(document.readyState!='loading')fn(); else document.addEventListener('DOMContentLoaded',fn);}
|
||||||
|
|
||||||
|
ready(function () {
|
||||||
|
const deck = document.querySelector('.deck');
|
||||||
|
if (!deck) return;
|
||||||
|
const slides = Array.from(deck.querySelectorAll('.slide'));
|
||||||
|
if (!slides.length) return;
|
||||||
|
|
||||||
|
let idx = 0;
|
||||||
|
const total = slides.length;
|
||||||
|
|
||||||
|
// progress bar
|
||||||
|
let bar = document.querySelector('.progress-bar');
|
||||||
|
if (!bar) {
|
||||||
|
bar = document.createElement('div');
|
||||||
|
bar.className = 'progress-bar';
|
||||||
|
bar.innerHTML = '<span></span>';
|
||||||
|
document.body.appendChild(bar);
|
||||||
|
}
|
||||||
|
const barFill = bar.querySelector('span');
|
||||||
|
|
||||||
|
// notes overlay
|
||||||
|
let notes = document.querySelector('.notes-overlay');
|
||||||
|
if (!notes) {
|
||||||
|
notes = document.createElement('div');
|
||||||
|
notes.className = 'notes-overlay';
|
||||||
|
document.body.appendChild(notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// overview
|
||||||
|
let overview = document.querySelector('.overview');
|
||||||
|
if (!overview) {
|
||||||
|
overview = document.createElement('div');
|
||||||
|
overview.className = 'overview';
|
||||||
|
slides.forEach((s, i) => {
|
||||||
|
const t = document.createElement('div');
|
||||||
|
t.className = 'thumb';
|
||||||
|
const title = s.getAttribute('data-title') ||
|
||||||
|
(s.querySelector('h1,h2,h3')||{}).textContent || ('Slide '+(i+1));
|
||||||
|
t.innerHTML = '<div class="n">'+(i+1)+'</div><div class="t">'+title.trim().slice(0,80)+'</div>';
|
||||||
|
t.addEventListener('click', () => { go(i); toggleOverview(false); });
|
||||||
|
overview.appendChild(t);
|
||||||
|
});
|
||||||
|
document.body.appendChild(overview);
|
||||||
|
}
|
||||||
|
|
||||||
|
function go(n){
|
||||||
|
n = Math.max(0, Math.min(total-1, n));
|
||||||
|
slides.forEach((s,i) => {
|
||||||
|
s.classList.toggle('is-active', i===n);
|
||||||
|
s.classList.toggle('is-prev', i<n);
|
||||||
|
});
|
||||||
|
idx = n;
|
||||||
|
barFill.style.width = ((n+1)/total*100)+'%';
|
||||||
|
const numEl = document.querySelector('.slide-number');
|
||||||
|
if (numEl) { numEl.setAttribute('data-current', n+1); numEl.setAttribute('data-total', total); }
|
||||||
|
// notes
|
||||||
|
const note = slides[n].querySelector('.notes');
|
||||||
|
notes.innerHTML = note ? note.innerHTML : '';
|
||||||
|
// hash
|
||||||
|
if (location.hash !== '#/'+(n+1)) history.replaceState(null,'','#/'+(n+1));
|
||||||
|
// re-trigger entry animations
|
||||||
|
slides[n].querySelectorAll('[data-anim]').forEach(el => {
|
||||||
|
const a = el.getAttribute('data-anim');
|
||||||
|
el.classList.remove('anim-'+a);
|
||||||
|
void el.offsetWidth;
|
||||||
|
el.classList.add('anim-'+a);
|
||||||
|
});
|
||||||
|
// counter-up
|
||||||
|
slides[n].querySelectorAll('.counter').forEach(el => {
|
||||||
|
const target = parseFloat(el.getAttribute('data-to')||el.textContent);
|
||||||
|
const dur = parseInt(el.getAttribute('data-dur')||'1200',10);
|
||||||
|
const start = performance.now();
|
||||||
|
const from = 0;
|
||||||
|
function tick(now){
|
||||||
|
const t = Math.min(1,(now-start)/dur);
|
||||||
|
const v = from + (target-from)*(1-Math.pow(1-t,3));
|
||||||
|
el.textContent = (target % 1 === 0) ? Math.round(v) : v.toFixed(1);
|
||||||
|
if (t<1) requestAnimationFrame(tick);
|
||||||
|
}
|
||||||
|
requestAnimationFrame(tick);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleNotes(force){ notes.classList.toggle('open', force!==undefined?force:!notes.classList.contains('open')); }
|
||||||
|
function toggleOverview(force){ overview.classList.toggle('open', force!==undefined?force:!overview.classList.contains('open')); }
|
||||||
|
function fullscreen(){ const el=document.documentElement;
|
||||||
|
if (!document.fullscreenElement) el.requestFullscreen&&el.requestFullscreen();
|
||||||
|
else document.exitFullscreen&&document.exitFullscreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
// theme cycling
|
||||||
|
const root = document.documentElement;
|
||||||
|
const themesAttr = root.getAttribute('data-themes') || document.body.getAttribute('data-themes');
|
||||||
|
const themes = themesAttr ? themesAttr.split(',').map(s=>s.trim()).filter(Boolean) : [];
|
||||||
|
let themeIdx = 0;
|
||||||
|
function cycleTheme(){
|
||||||
|
if (!themes.length) return;
|
||||||
|
themeIdx = (themeIdx+1) % themes.length;
|
||||||
|
const name = themes[themeIdx];
|
||||||
|
let link = document.getElementById('theme-link');
|
||||||
|
if (!link) {
|
||||||
|
link = document.createElement('link');
|
||||||
|
link.rel = 'stylesheet';
|
||||||
|
link.id = 'theme-link';
|
||||||
|
document.head.appendChild(link);
|
||||||
|
}
|
||||||
|
// resolve relative to runtime's location
|
||||||
|
const themePath = (root.getAttribute('data-theme-base') || 'assets/themes/') + name + '.css';
|
||||||
|
link.href = themePath;
|
||||||
|
root.setAttribute('data-theme', name);
|
||||||
|
const ind = document.querySelector('.theme-indicator');
|
||||||
|
if (ind) ind.textContent = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// animation cycling on current slide
|
||||||
|
let animIdx = 0;
|
||||||
|
function cycleAnim(){
|
||||||
|
animIdx = (animIdx+1) % ANIMS.length;
|
||||||
|
const a = ANIMS[animIdx];
|
||||||
|
const target = slides[idx].querySelector('[data-anim-target]') || slides[idx];
|
||||||
|
ANIMS.forEach(x => target.classList.remove('anim-'+x));
|
||||||
|
void target.offsetWidth;
|
||||||
|
target.classList.add('anim-'+a);
|
||||||
|
target.setAttribute('data-anim', a);
|
||||||
|
const ind = document.querySelector('.anim-indicator');
|
||||||
|
if (ind) ind.textContent = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('keydown', function (e) {
|
||||||
|
if (e.metaKey||e.ctrlKey||e.altKey) return;
|
||||||
|
switch (e.key) {
|
||||||
|
case 'ArrowRight': case ' ': case 'PageDown': case 'Enter': go(idx+1); e.preventDefault(); break;
|
||||||
|
case 'ArrowLeft': case 'PageUp': case 'Backspace': go(idx-1); e.preventDefault(); break;
|
||||||
|
case 'Home': go(0); break;
|
||||||
|
case 'End': go(total-1); break;
|
||||||
|
case 'f': case 'F': fullscreen(); break;
|
||||||
|
case 's': case 'S': toggleNotes(); break;
|
||||||
|
case 'o': case 'O': toggleOverview(); break;
|
||||||
|
case 't': case 'T': cycleTheme(); break;
|
||||||
|
case 'a': case 'A': cycleAnim(); break;
|
||||||
|
case 'Escape': toggleOverview(false); toggleNotes(false); break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// hash deep-link
|
||||||
|
function fromHash(){
|
||||||
|
const m = /^#\/(\d+)/.exec(location.hash||'');
|
||||||
|
if (m) go(Math.max(0, parseInt(m[1],10)-1));
|
||||||
|
}
|
||||||
|
window.addEventListener('hashchange', fromHash);
|
||||||
|
fromHash();
|
||||||
|
go(idx);
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* theme: arctic-cool — 冷色调 蓝/青/石板灰 */
|
||||||
|
:root{
|
||||||
|
--bg:#f2f6fb;--bg-soft:#e7eef7;--surface:#ffffff;--surface-2:#edf3fa;
|
||||||
|
--border:rgba(40,70,110,.12);--border-strong:rgba(40,70,110,.24);
|
||||||
|
--text-1:#0e1f33;--text-2:#3a5778;--text-3:#6b819b;
|
||||||
|
--accent:#1e6fb0;--accent-2:#17b1b1;--accent-3:#6f8aa6;
|
||||||
|
--good:#1aaf84;--warn:#d19030;--bad:#c5485a;
|
||||||
|
--grad:linear-gradient(135deg,#1e6fb0,#17b1b1 60%,#5fb9d6);
|
||||||
|
--grad-soft:linear-gradient(135deg,#e7eef7,#dff3f3);
|
||||||
|
--radius:14px;--radius-sm:10px;--radius-lg:22px;
|
||||||
|
--shadow:0 10px 28px rgba(40,70,110,.12);
|
||||||
|
--shadow-lg:0 24px 60px rgba(40,70,110,.18);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
/* theme: aurora — 极光渐变 */
|
||||||
|
:root{
|
||||||
|
--bg:#06091c;--bg-soft:#0a1130;--surface:rgba(255,255,255,.05);--surface-2:rgba(255,255,255,.08);
|
||||||
|
--border:rgba(180,220,255,.14);--border-strong:rgba(180,220,255,.28);
|
||||||
|
--text-1:#e8f0ff;--text-2:#b4c4e4;--text-3:#6a7a9e;
|
||||||
|
--accent:#5ef2c6;--accent-2:#7aa2ff;--accent-3:#c984ff;
|
||||||
|
--good:#5ef2c6;--warn:#ffd27a;--bad:#ff8ab0;
|
||||||
|
--grad:linear-gradient(135deg,#5ef2c6,#7aa2ff 50%,#c984ff);
|
||||||
|
--grad-soft:linear-gradient(135deg,rgba(94,242,198,.2),rgba(201,132,255,.2));
|
||||||
|
--radius:20px;--radius-sm:14px;--radius-lg:28px;
|
||||||
|
--shadow:0 20px 60px rgba(0,0,0,.4),inset 0 1px 0 rgba(255,255,255,.08);
|
||||||
|
--shadow-lg:0 30px 80px rgba(0,0,0,.55);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
}
|
||||||
|
body{background:
|
||||||
|
radial-gradient(60% 50% at 20% 10%,rgba(94,242,198,.35),transparent 70%),
|
||||||
|
radial-gradient(55% 50% at 80% 20%,rgba(122,162,255,.32),transparent 70%),
|
||||||
|
radial-gradient(70% 60% at 50% 100%,rgba(201,132,255,.3),transparent 70%),
|
||||||
|
#06091c}
|
||||||
|
.card{backdrop-filter:blur(24px) saturate(160%);-webkit-backdrop-filter:blur(24px) saturate(160%)}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
/* theme: bauhaus — 几何+原色 */
|
||||||
|
:root{
|
||||||
|
--bg:#f4efe3;--bg-soft:#e8e2d1;--surface:#ffffff;--surface-2:#f4efe3;
|
||||||
|
--border:#111111;--border-strong:#111111;
|
||||||
|
--text-1:#111111;--text-2:#333333;--text-3:#666666;
|
||||||
|
--accent:#e03c27;--accent-2:#f4c430;--accent-3:#1d4eaf;
|
||||||
|
--good:#1b8c3c;--warn:#f4c430;--bad:#e03c27;
|
||||||
|
--grad:linear-gradient(135deg,#e03c27 0 33%,#f4c430 33% 66%,#1d4eaf 66% 100%);
|
||||||
|
--grad-soft:linear-gradient(135deg,#f4efe3,#e8e2d1);
|
||||||
|
--radius:0;--radius-sm:0;--radius-lg:0;
|
||||||
|
--shadow:4px 4px 0 #111;--shadow-lg:8px 8px 0 #111;
|
||||||
|
--font-sans:'Space Grotesk','Inter','Noto Sans SC',sans-serif;
|
||||||
|
--font-display:'Archivo Black',sans-serif;
|
||||||
|
--letter-tight:-.03em;
|
||||||
|
}
|
||||||
|
.card{border:2px solid #111}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
/* theme: blueprint — 蓝图工程 */
|
||||||
|
:root{
|
||||||
|
--bg:#0b3a6f;--bg-soft:#0a3260;--surface:rgba(255,255,255,.06);--surface-2:rgba(255,255,255,.1);
|
||||||
|
--border:rgba(190,220,255,.3);--border-strong:rgba(190,220,255,.55);
|
||||||
|
--text-1:#e8f3ff;--text-2:#b8d4f0;--text-3:#7da8cf;
|
||||||
|
--accent:#ffffff;--accent-2:#aee1ff;--accent-3:#ffd27a;
|
||||||
|
--good:#8ef0a6;--warn:#ffd27a;--bad:#ff8a96;
|
||||||
|
--grad:linear-gradient(135deg,#ffffff,#aee1ff);
|
||||||
|
--grad-soft:linear-gradient(135deg,#0a3260,#0b3a6f);
|
||||||
|
--radius:2px;--radius-sm:2px;--radius-lg:4px;
|
||||||
|
--shadow:none;--shadow-lg:0 16px 40px rgba(0,0,0,.3);
|
||||||
|
--font-sans:'JetBrains Mono','IBM Plex Mono',monospace;
|
||||||
|
--font-display:'JetBrains Mono',monospace;
|
||||||
|
}
|
||||||
|
body{background:
|
||||||
|
linear-gradient(rgba(255,255,255,.06) 1px,transparent 1px) 0 0/40px 40px,
|
||||||
|
linear-gradient(90deg,rgba(255,255,255,.06) 1px,transparent 1px) 0 0/40px 40px,
|
||||||
|
#0b3a6f}
|
||||||
|
.card{border:1px dashed rgba(190,220,255,.45);background:rgba(255,255,255,.04)}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* theme: catppuccin-latte — catppuccin 浅 */
|
||||||
|
:root{
|
||||||
|
--bg:#eff1f5;--bg-soft:#e6e9ef;--surface:#ffffff;--surface-2:#eef0f4;
|
||||||
|
--border:rgba(76,79,105,.14);--border-strong:rgba(76,79,105,.28);
|
||||||
|
--text-1:#4c4f69;--text-2:#6c6f85;--text-3:#9ca0b0;
|
||||||
|
--accent:#8839ef;--accent-2:#1e66f5;--accent-3:#ea76cb;
|
||||||
|
--good:#40a02b;--warn:#df8e1d;--bad:#d20f39;
|
||||||
|
--grad:linear-gradient(135deg,#8839ef,#1e66f5 50%,#04a5e5);
|
||||||
|
--grad-soft:linear-gradient(135deg,#eff1f5,#e6e9ef);
|
||||||
|
--radius:14px;--radius-sm:10px;--radius-lg:22px;
|
||||||
|
--shadow:0 8px 24px rgba(76,79,105,.1);
|
||||||
|
--shadow-lg:0 20px 56px rgba(76,79,105,.16);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* theme: catppuccin-mocha — catppuccin 深 */
|
||||||
|
:root{
|
||||||
|
--bg:#1e1e2e;--bg-soft:#181825;--surface:#313244;--surface-2:#45475a;
|
||||||
|
--border:rgba(205,214,244,.12);--border-strong:rgba(205,214,244,.24);
|
||||||
|
--text-1:#cdd6f4;--text-2:#a6adc8;--text-3:#7f849c;
|
||||||
|
--accent:#cba6f7;--accent-2:#89b4fa;--accent-3:#f5c2e7;
|
||||||
|
--good:#a6e3a1;--warn:#f9e2af;--bad:#f38ba8;
|
||||||
|
--grad:linear-gradient(135deg,#cba6f7,#89b4fa 50%,#94e2d5);
|
||||||
|
--grad-soft:linear-gradient(135deg,#313244,#45475a);
|
||||||
|
--radius:14px;--radius-sm:10px;--radius-lg:22px;
|
||||||
|
--shadow:0 10px 30px rgba(0,0,0,.35);
|
||||||
|
--shadow-lg:0 24px 60px rgba(0,0,0,.5);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* theme: dracula — dracula 深色 */
|
||||||
|
:root{
|
||||||
|
--bg:#282a36;--bg-soft:#21222c;--surface:#343746;--surface-2:#44475a;
|
||||||
|
--border:rgba(248,248,242,.12);--border-strong:rgba(248,248,242,.24);
|
||||||
|
--text-1:#f8f8f2;--text-2:#bdbde0;--text-3:#6272a4;
|
||||||
|
--accent:#bd93f9;--accent-2:#ff79c6;--accent-3:#8be9fd;
|
||||||
|
--good:#50fa7b;--warn:#f1fa8c;--bad:#ff5555;
|
||||||
|
--grad:linear-gradient(135deg,#bd93f9,#ff79c6 55%,#8be9fd);
|
||||||
|
--grad-soft:linear-gradient(135deg,#343746,#44475a);
|
||||||
|
--radius:12px;--radius-sm:8px;--radius-lg:18px;
|
||||||
|
--shadow:0 10px 30px rgba(0,0,0,.4);
|
||||||
|
--shadow-lg:0 22px 60px rgba(0,0,0,.55);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
/* theme: editorial-serif — 杂志风衬线,高级 */
|
||||||
|
:root{
|
||||||
|
--bg:#faf7f2;--bg-soft:#f3efe6;--surface:#ffffff;--surface-2:#f7f2e8;
|
||||||
|
--border:rgba(40,28,18,.12);--border-strong:rgba(40,28,18,.24);
|
||||||
|
--text-1:#1b1410;--text-2:#5c4a3e;--text-3:#8a7868;
|
||||||
|
--accent:#8a2a1c;--accent-2:#c97a4a;--accent-3:#1b1410;
|
||||||
|
--good:#3f7d4f;--warn:#b07a1f;--bad:#8a2a1c;
|
||||||
|
--grad:linear-gradient(135deg,#8a2a1c,#c97a4a);
|
||||||
|
--grad-soft:linear-gradient(135deg,#faf7f2,#f3efe6);
|
||||||
|
--radius:4px;--radius-sm:2px;--radius-lg:8px;
|
||||||
|
--shadow:0 2px 12px rgba(40,28,18,.06);
|
||||||
|
--shadow-lg:0 20px 50px rgba(40,28,18,.14);
|
||||||
|
--font-sans:'Playfair Display','Noto Serif SC',serif;
|
||||||
|
--font-display:'Playfair Display','Noto Serif SC',serif;
|
||||||
|
--font-serif:'Playfair Display','Noto Serif SC',serif;
|
||||||
|
--letter-tight:-.02em;
|
||||||
|
}
|
||||||
|
.h1,.h2,h1.title,h2.title{font-style:italic;font-weight:600}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
/* theme: glassmorphism — 毛玻璃 */
|
||||||
|
:root{
|
||||||
|
--bg:#0b1024;--bg-soft:#0e1530;--surface:rgba(255,255,255,.06);--surface-2:rgba(255,255,255,.1);
|
||||||
|
--border:rgba(255,255,255,.14);--border-strong:rgba(255,255,255,.28);
|
||||||
|
--text-1:#f2f4ff;--text-2:#c3c8e6;--text-3:#8287a8;
|
||||||
|
--accent:#7dd3fc;--accent-2:#c084fc;--accent-3:#f0abfc;
|
||||||
|
--good:#86efac;--warn:#fde68a;--bad:#fca5a5;
|
||||||
|
--grad:linear-gradient(135deg,#7dd3fc,#c084fc 55%,#f0abfc);
|
||||||
|
--grad-soft:linear-gradient(135deg,rgba(125,211,252,.18),rgba(192,132,252,.18));
|
||||||
|
--radius:22px;--radius-sm:14px;--radius-lg:30px;
|
||||||
|
--shadow:0 20px 60px rgba(0,0,0,.35),inset 0 1px 0 rgba(255,255,255,.12);
|
||||||
|
--shadow-lg:0 30px 80px rgba(0,0,0,.5);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
}
|
||||||
|
body{background:
|
||||||
|
radial-gradient(60% 60% at 20% 20%,rgba(125,211,252,.3),transparent 60%),
|
||||||
|
radial-gradient(50% 50% at 80% 30%,rgba(192,132,252,.28),transparent 60%),
|
||||||
|
radial-gradient(60% 60% at 60% 90%,rgba(240,171,252,.25),transparent 60%),
|
||||||
|
#0b1024}
|
||||||
|
.card{backdrop-filter:blur(28px) saturate(180%);-webkit-backdrop-filter:blur(28px) saturate(180%);
|
||||||
|
background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.18)}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* theme: gruvbox-dark */
|
||||||
|
:root{
|
||||||
|
--bg:#282828;--bg-soft:#1d2021;--surface:#3c3836;--surface-2:#504945;
|
||||||
|
--border:rgba(235,219,178,.14);--border-strong:rgba(235,219,178,.28);
|
||||||
|
--text-1:#ebdbb2;--text-2:#d5c4a1;--text-3:#928374;
|
||||||
|
--accent:#fabd2f;--accent-2:#fe8019;--accent-3:#b8bb26;
|
||||||
|
--good:#b8bb26;--warn:#fabd2f;--bad:#fb4934;
|
||||||
|
--grad:linear-gradient(135deg,#fe8019,#fabd2f 55%,#b8bb26);
|
||||||
|
--grad-soft:linear-gradient(135deg,#3c3836,#504945);
|
||||||
|
--radius:6px;--radius-sm:4px;--radius-lg:12px;
|
||||||
|
--shadow:0 10px 30px rgba(0,0,0,.5);
|
||||||
|
--shadow-lg:0 24px 60px rgba(0,0,0,.65);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
/* theme: memphis-pop — 孟菲斯波普 */
|
||||||
|
:root{
|
||||||
|
--bg:#fef6e8;--bg-soft:#fdebc7;--surface:#ffffff;--surface-2:#fff1d1;
|
||||||
|
--border:#111111;--border-strong:#111111;
|
||||||
|
--text-1:#111111;--text-2:#333333;--text-3:#666666;
|
||||||
|
--accent:#ff3d8b;--accent-2:#37c2d7;--accent-3:#ffcc00;
|
||||||
|
--good:#6ac04c;--warn:#ffcc00;--bad:#ff3d8b;
|
||||||
|
--grad:linear-gradient(135deg,#ff3d8b,#ffcc00 50%,#37c2d7);
|
||||||
|
--grad-soft:linear-gradient(135deg,#fdebc7,#fff1d1);
|
||||||
|
--radius:10px;--radius-sm:6px;--radius-lg:18px;
|
||||||
|
--shadow:5px 5px 0 #111;--shadow-lg:9px 9px 0 #111;
|
||||||
|
--font-sans:'Space Grotesk','Inter','Noto Sans SC',sans-serif;
|
||||||
|
--font-display:'Archivo Black',sans-serif;
|
||||||
|
}
|
||||||
|
.card{border:2.5px solid #111}
|
||||||
|
body{background-image:
|
||||||
|
radial-gradient(circle at 10% 20%,#ff3d8b 3px,transparent 4px),
|
||||||
|
radial-gradient(circle at 80% 40%,#37c2d7 3px,transparent 4px),
|
||||||
|
radial-gradient(circle at 30% 80%,#ffcc00 3px,transparent 4px);
|
||||||
|
background-size:200px 200px,220px 220px,260px 260px}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
/* theme: minimal-white — 极简白,克制高级 */
|
||||||
|
:root{
|
||||||
|
--bg:#ffffff;--bg-soft:#fafafa;--surface:#ffffff;--surface-2:#f5f5f6;
|
||||||
|
--border:rgba(17,18,22,.08);--border-strong:rgba(17,18,22,.16);
|
||||||
|
--text-1:#0c0d10;--text-2:#55596a;--text-3:#9ca1b0;
|
||||||
|
--accent:#111216;--accent-2:#3b3f4a;--accent-3:#6b6f7a;
|
||||||
|
--good:#1aaf6c;--warn:#c98500;--bad:#c13a3a;
|
||||||
|
--grad:linear-gradient(135deg,#111216,#3b3f4a);
|
||||||
|
--grad-soft:linear-gradient(135deg,#f5f5f6,#ffffff);
|
||||||
|
--radius:14px;--radius-sm:8px;--radius-lg:22px;
|
||||||
|
--shadow:0 1px 2px rgba(17,18,22,.04),0 8px 24px rgba(17,18,22,.06);
|
||||||
|
--shadow-lg:0 20px 60px rgba(17,18,22,.1);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
--font-display:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
--letter-tight:-.035em;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
/* theme: neo-brutalism — 厚描边、硬阴影、明黄 */
|
||||||
|
:root{
|
||||||
|
--bg:#fffef0;--bg-soft:#fffbd0;--surface:#ffffff;--surface-2:#fff38a;
|
||||||
|
--border:#000000;--border-strong:#000000;
|
||||||
|
--text-1:#000000;--text-2:#222222;--text-3:#555555;
|
||||||
|
--accent:#ffd400;--accent-2:#ff5ca8;--accent-3:#3a7cff;
|
||||||
|
--good:#00b36b;--warn:#ff9900;--bad:#ff3a30;
|
||||||
|
--grad:linear-gradient(135deg,#ffd400,#ff5ca8);
|
||||||
|
--grad-soft:linear-gradient(135deg,#fffbd0,#fff);
|
||||||
|
--radius:6px;--radius-sm:4px;--radius-lg:10px;
|
||||||
|
--shadow:6px 6px 0 #000;--shadow-lg:10px 10px 0 #000;
|
||||||
|
--font-sans:'Space Grotesk','Inter','Noto Sans SC',sans-serif;
|
||||||
|
--font-display:'Archivo Black','Space Grotesk',sans-serif;
|
||||||
|
--letter-tight:-.03em;
|
||||||
|
}
|
||||||
|
.card{border:3px solid #000}
|
||||||
|
.pill{border:2px solid #000;background:#ffd400;color:#000}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* theme: nord */
|
||||||
|
:root{
|
||||||
|
--bg:#2e3440;--bg-soft:#272b35;--surface:#3b4252;--surface-2:#434c5e;
|
||||||
|
--border:rgba(236,239,244,.12);--border-strong:rgba(236,239,244,.24);
|
||||||
|
--text-1:#eceff4;--text-2:#d8dee9;--text-3:#7b8394;
|
||||||
|
--accent:#88c0d0;--accent-2:#81a1c1;--accent-3:#b48ead;
|
||||||
|
--good:#a3be8c;--warn:#ebcb8b;--bad:#bf616a;
|
||||||
|
--grad:linear-gradient(135deg,#88c0d0,#81a1c1 50%,#b48ead);
|
||||||
|
--grad-soft:linear-gradient(135deg,#3b4252,#434c5e);
|
||||||
|
--radius:12px;--radius-sm:8px;--radius-lg:20px;
|
||||||
|
--shadow:0 10px 30px rgba(0,0,0,.35);
|
||||||
|
--shadow-lg:0 22px 60px rgba(0,0,0,.5);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
/* theme: rainbow-gradient — 彩虹渐变点缀(白底) */
|
||||||
|
:root{
|
||||||
|
--bg:#ffffff;--bg-soft:#f8f8fb;--surface:#ffffff;--surface-2:#f4f4f8;
|
||||||
|
--border:rgba(20,20,40,.08);--border-strong:rgba(20,20,40,.2);
|
||||||
|
--text-1:#0c0d10;--text-2:#4d5162;--text-3:#9096a8;
|
||||||
|
--accent:#ff4d8b;--accent-2:#7a5cff;--accent-3:#36b6ff;
|
||||||
|
--good:#1aaf6c;--warn:#f5a524;--bad:#e0445a;
|
||||||
|
--grad:linear-gradient(90deg,#ff0080,#ff4d00,#ff9900,#ffe600,#00c853,#0091ea,#6200ea,#ff0080);
|
||||||
|
--grad-soft:linear-gradient(135deg,#fff,#f8f8fb);
|
||||||
|
--radius:16px;--radius-sm:10px;--radius-lg:24px;
|
||||||
|
--shadow:0 12px 32px rgba(124,92,255,.1);
|
||||||
|
--shadow-lg:0 24px 60px rgba(124,92,255,.18);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
}
|
||||||
|
.gradient-text{background-size:200% auto;animation:rbflow 6s linear infinite}
|
||||||
|
@keyframes rbflow{to{background-position:200% 0}}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* theme: rose-pine */
|
||||||
|
:root{
|
||||||
|
--bg:#191724;--bg-soft:#1f1d2e;--surface:#26233a;--surface-2:#2a2740;
|
||||||
|
--border:rgba(224,222,244,.12);--border-strong:rgba(224,222,244,.24);
|
||||||
|
--text-1:#e0def4;--text-2:#c4b8d8;--text-3:#6e6a86;
|
||||||
|
--accent:#ebbcba;--accent-2:#c4a7e7;--accent-3:#9ccfd8;
|
||||||
|
--good:#31748f;--warn:#f6c177;--bad:#eb6f92;
|
||||||
|
--grad:linear-gradient(135deg,#ebbcba,#c4a7e7 55%,#9ccfd8);
|
||||||
|
--grad-soft:linear-gradient(135deg,#26233a,#2a2740);
|
||||||
|
--radius:14px;--radius-sm:10px;--radius-lg:22px;
|
||||||
|
--shadow:0 10px 30px rgba(0,0,0,.4);
|
||||||
|
--shadow-lg:0 22px 58px rgba(0,0,0,.55);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
/* theme: sharp-mono — 锐利黑白高对比 */
|
||||||
|
:root{
|
||||||
|
--bg:#ffffff;--bg-soft:#ffffff;--surface:#ffffff;--surface-2:#000000;
|
||||||
|
--border:#000000;--border-strong:#000000;
|
||||||
|
--text-1:#000000;--text-2:#1a1a1a;--text-3:#4a4a4a;
|
||||||
|
--accent:#000000;--accent-2:#000000;--accent-3:#ff2200;
|
||||||
|
--good:#008800;--warn:#ff9900;--bad:#ff0000;
|
||||||
|
--grad:linear-gradient(135deg,#000,#222);
|
||||||
|
--grad-soft:linear-gradient(135deg,#fff,#eee);
|
||||||
|
--radius:0;--radius-sm:0;--radius-lg:0;
|
||||||
|
--shadow:4px 4px 0 #000;--shadow-lg:8px 8px 0 #000;
|
||||||
|
--font-sans:'Archivo Black','Inter','Noto Sans SC',sans-serif;
|
||||||
|
--font-display:'Archivo Black',sans-serif;
|
||||||
|
--letter-tight:-.04em;
|
||||||
|
}
|
||||||
|
.h1,.h2,h1.title,h2.title{text-transform:uppercase}
|
||||||
|
.card{border:2px solid #000}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* theme: soft-pastel — 柔和马卡龙 */
|
||||||
|
:root{
|
||||||
|
--bg:#fdf7fb;--bg-soft:#fbeef3;--surface:#ffffff;--surface-2:#fdf0f5;
|
||||||
|
--border:rgba(120,70,110,.12);--border-strong:rgba(120,70,110,.22);
|
||||||
|
--text-1:#3a1f33;--text-2:#6b4d62;--text-3:#a28a99;
|
||||||
|
--accent:#f49bb8;--accent-2:#b5d5f0;--accent-3:#f7d08a;
|
||||||
|
--good:#9dd9a3;--warn:#f7d08a;--bad:#ef9a9a;
|
||||||
|
--grad:linear-gradient(135deg,#f49bb8,#b5d5f0 55%,#c4a0e8);
|
||||||
|
--grad-soft:linear-gradient(135deg,#fbeef3,#eaf4fc);
|
||||||
|
--radius:24px;--radius-sm:16px;--radius-lg:32px;
|
||||||
|
--shadow:0 8px 28px rgba(244,155,184,.18);
|
||||||
|
--shadow-lg:0 24px 70px rgba(181,213,240,.3);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* theme: solarized-light */
|
||||||
|
:root{
|
||||||
|
--bg:#fdf6e3;--bg-soft:#eee8d5;--surface:#ffffff;--surface-2:#f5efd7;
|
||||||
|
--border:rgba(88,110,117,.2);--border-strong:rgba(88,110,117,.4);
|
||||||
|
--text-1:#073642;--text-2:#586e75;--text-3:#93a1a1;
|
||||||
|
--accent:#268bd2;--accent-2:#2aa198;--accent-3:#d33682;
|
||||||
|
--good:#859900;--warn:#b58900;--bad:#dc322f;
|
||||||
|
--grad:linear-gradient(135deg,#268bd2,#2aa198 50%,#859900);
|
||||||
|
--grad-soft:linear-gradient(135deg,#fdf6e3,#eee8d5);
|
||||||
|
--radius:10px;--radius-sm:6px;--radius-lg:16px;
|
||||||
|
--shadow:0 6px 20px rgba(88,110,117,.14);
|
||||||
|
--shadow-lg:0 18px 50px rgba(88,110,117,.24);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* theme: sunset-warm — 暖色调 橘/珊瑚/琥珀 */
|
||||||
|
:root{
|
||||||
|
--bg:#fff7ef;--bg-soft:#ffeedc;--surface:#ffffff;--surface-2:#fff2e0;
|
||||||
|
--border:rgba(120,60,20,.12);--border-strong:rgba(120,60,20,.22);
|
||||||
|
--text-1:#2a160a;--text-2:#6b4630;--text-3:#a28572;
|
||||||
|
--accent:#e36a2d;--accent-2:#f2a341;--accent-3:#d94860;
|
||||||
|
--good:#5ea35a;--warn:#f2a341;--bad:#d94860;
|
||||||
|
--grad:linear-gradient(135deg,#d94860,#e36a2d 50%,#f2a341);
|
||||||
|
--grad-soft:linear-gradient(135deg,#ffeedc,#ffe0d0);
|
||||||
|
--radius:18px;--radius-sm:12px;--radius-lg:28px;
|
||||||
|
--shadow:0 12px 32px rgba(227,106,45,.16);
|
||||||
|
--shadow-lg:0 24px 64px rgba(227,106,45,.22);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
/* theme: swiss-grid — 瑞士网格,Helvetica 感 */
|
||||||
|
:root{
|
||||||
|
--bg:#ffffff;--bg-soft:#f4f4f4;--surface:#ffffff;--surface-2:#f4f4f4;
|
||||||
|
--border:#111111;--border-strong:#111111;
|
||||||
|
--text-1:#111111;--text-2:#444444;--text-3:#888888;
|
||||||
|
--accent:#d6001c;--accent-2:#111111;--accent-3:#888888;
|
||||||
|
--good:#0f8a2f;--warn:#d38a00;--bad:#d6001c;
|
||||||
|
--grad:linear-gradient(135deg,#d6001c,#111);
|
||||||
|
--grad-soft:linear-gradient(135deg,#f4f4f4,#fff);
|
||||||
|
--radius:0;--radius-sm:0;--radius-lg:0;
|
||||||
|
--shadow:none;--shadow-lg:none;
|
||||||
|
--font-sans:'Inter','Helvetica Neue',Helvetica,'Noto Sans SC',sans-serif;
|
||||||
|
--font-display:'Inter','Helvetica Neue',Helvetica,sans-serif;
|
||||||
|
--letter-tight:-.04em;
|
||||||
|
}
|
||||||
|
.card{border-top:2px solid #111;border-bottom:1px solid #111;border-left:none;border-right:none;box-shadow:none;background:#fff}
|
||||||
|
.slide{background-image:linear-gradient(90deg,rgba(0,0,0,.04) 1px,transparent 1px);background-size:calc(100%/12) 100%}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
/* theme: terminal-green — 绿屏终端 */
|
||||||
|
:root{
|
||||||
|
--bg:#030a04;--bg-soft:#041308;--surface:#0a1b10;--surface-2:#0d2614;
|
||||||
|
--border:rgba(0,255,120,.22);--border-strong:rgba(0,255,120,.42);
|
||||||
|
--text-1:#8cff9a;--text-2:#4bd17a;--text-3:#2f8a4d;
|
||||||
|
--accent:#00ff88;--accent-2:#67ffd0;--accent-3:#b6ff6b;
|
||||||
|
--good:#00ff88;--warn:#ffe066;--bad:#ff6464;
|
||||||
|
--grad:linear-gradient(135deg,#00ff88,#67ffd0);
|
||||||
|
--grad-soft:linear-gradient(135deg,#0a1b10,#0d2614);
|
||||||
|
--radius:4px;--radius-sm:2px;--radius-lg:8px;
|
||||||
|
--shadow:0 0 30px rgba(0,255,136,.15);
|
||||||
|
--shadow-lg:0 0 60px rgba(0,255,136,.28);
|
||||||
|
--font-sans:'JetBrains Mono','IBM Plex Mono',monospace;
|
||||||
|
--font-display:'JetBrains Mono',monospace;
|
||||||
|
--letter-tight:-.01em;
|
||||||
|
}
|
||||||
|
body{text-shadow:0 0 2px rgba(0,255,136,.5)}
|
||||||
|
.card{border:1px solid rgba(0,255,120,.3);background:rgba(10,27,16,.6)}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* theme: tokyo-night */
|
||||||
|
:root{
|
||||||
|
--bg:#1a1b26;--bg-soft:#16161e;--surface:#24283b;--surface-2:#2f334d;
|
||||||
|
--border:rgba(192,202,245,.12);--border-strong:rgba(192,202,245,.24);
|
||||||
|
--text-1:#c0caf5;--text-2:#a9b1d6;--text-3:#565f89;
|
||||||
|
--accent:#7aa2f7;--accent-2:#bb9af7;--accent-3:#7dcfff;
|
||||||
|
--good:#9ece6a;--warn:#e0af68;--bad:#f7768e;
|
||||||
|
--grad:linear-gradient(135deg,#7aa2f7,#bb9af7 55%,#f7768e);
|
||||||
|
--grad-soft:linear-gradient(135deg,#24283b,#2f334d);
|
||||||
|
--radius:12px;--radius-sm:8px;--radius-lg:20px;
|
||||||
|
--shadow:0 10px 30px rgba(0,0,0,.45);
|
||||||
|
--shadow-lg:0 24px 62px rgba(0,0,0,.6);
|
||||||
|
--font-sans:'Inter','Noto Sans SC',sans-serif;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
/* theme: xiaohongshu-white — 小红书白底高级感 */
|
||||||
|
:root{
|
||||||
|
--bg:#fffdfb;--bg-soft:#fff6f1;--surface:#ffffff;--surface-2:#fff1ea;
|
||||||
|
--border:rgba(60,30,20,.1);--border-strong:rgba(60,30,20,.22);
|
||||||
|
--text-1:#1a1210;--text-2:#4f3a32;--text-3:#a08d85;
|
||||||
|
--accent:#ff2742;--accent-2:#ff7a90;--accent-3:#ffb38a;
|
||||||
|
--good:#3ba55c;--warn:#f5a524;--bad:#ff2742;
|
||||||
|
--grad:linear-gradient(135deg,#ff2742,#ff7a90 55%,#ffb38a);
|
||||||
|
--grad-soft:linear-gradient(135deg,#fff6f1,#ffeae0);
|
||||||
|
--radius:20px;--radius-sm:14px;--radius-lg:28px;
|
||||||
|
--shadow:0 12px 30px rgba(255,39,66,.08);
|
||||||
|
--shadow-lg:0 24px 60px rgba(255,39,66,.14);
|
||||||
|
--font-sans:'Noto Sans SC','Inter',sans-serif;
|
||||||
|
--font-display:'Noto Serif SC','Playfair Display',serif;
|
||||||
|
--letter-tight:-.02em;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,161 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN" data-theme="aurora">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
|
<title>html-ppt · Demo Deck</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/aurora.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body data-themes="aurora,minimal-white,editorial-serif,tokyo-night,catppuccin-mocha,xiaohongshu-white,neo-brutalism,sunset-warm" data-theme-base="../../assets/themes/">
|
||||||
|
|
||||||
|
<div class="deck">
|
||||||
|
|
||||||
|
<!-- 1. Cover -->
|
||||||
|
<section class="slide" data-title="Cover">
|
||||||
|
<div class="deck-header"><span class="eyebrow">Tech sharing · 2026-04-15</span><span class="eyebrow">html-ppt</span></div>
|
||||||
|
<p class="kicker">Keynote · Demo</p>
|
||||||
|
<h1 class="h1 anim-rise-in" data-anim="rise-in">做一份<span class="gradient-text">像杂志</span>一样的<br>技术分享稿</h1>
|
||||||
|
<p class="lede">24 主题 · 30 版式 · 25 动效 · 零构建</p>
|
||||||
|
<div class="row wrap mt-l" style="gap:8px">
|
||||||
|
<span class="pill pill-accent">tokens</span>
|
||||||
|
<span class="pill">keyboard first</span>
|
||||||
|
<span class="pill">PNG export</span>
|
||||||
|
<span class="pill">CN + EN</span>
|
||||||
|
</div>
|
||||||
|
<div class="deck-footer"><span class="dim2">lewis · sudolewis@gmail.com</span><span class="slide-number" data-current="1" data-total="8"></span></div>
|
||||||
|
<div class="notes">Hi,今天我给大家演示一下 html-ppt 这套演讲系统是怎么工作的。这份 demo 本身就是用它做出来的——每一张幻灯片都只是几行 HTML + 一个 class。</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 2. TOC -->
|
||||||
|
<section class="slide" data-title="Agenda">
|
||||||
|
<p class="kicker">Agenda</p>
|
||||||
|
<h2 class="h2">今天 10 分钟,讲三件事</h2>
|
||||||
|
<div class="grid g3 mt-l anim-stagger-list" data-anim-target>
|
||||||
|
<div class="card card-accent"><h4>① 为什么</h4><p class="dim">每次做 PPT 都在重复劳动,而这件事 99% 可以模板化。</p></div>
|
||||||
|
<div class="card card-accent"><h4>② 怎么做</h4><p class="dim">tokens + layouts + animations,三层分离。</p></div>
|
||||||
|
<div class="card card-accent"><h4>③ 效果</h4><p class="dim">同一份 deck,一键切 24 种主题。</p></div>
|
||||||
|
</div>
|
||||||
|
<div class="deck-footer"><span class="dim2">agenda</span><span class="slide-number" data-current="2" data-total="8"></span></div>
|
||||||
|
<div class="notes">三段式结构——Why / How / Result。这是最稳的讲法。</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 3. Big quote -->
|
||||||
|
<section class="slide center tc" data-title="Quote">
|
||||||
|
<div style="max-width:1000px">
|
||||||
|
<div class="serif" style="font-size:120px;line-height:.9;color:var(--accent);opacity:.7">"</div>
|
||||||
|
<blockquote class="serif anim-fade-up" data-anim="fade-up" style="font-size:52px;line-height:1.3;margin:-30px 0 18px;font-weight:600;font-style:italic">
|
||||||
|
好的演讲稿是写出来的,<br>不是「做」出来的。
|
||||||
|
</blockquote>
|
||||||
|
<p class="dim" style="font-size:18px;letter-spacing:.1em">— 每一个被 PPT 折磨过的人</p>
|
||||||
|
</div>
|
||||||
|
<div class="deck-footer"><span class="dim2">quote</span><span class="slide-number" data-current="3" data-total="8"></span></div>
|
||||||
|
<div class="notes">这里停一秒。让这句话自己说话。</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 4. Stat -->
|
||||||
|
<section class="slide center tc" data-title="Stat">
|
||||||
|
<div>
|
||||||
|
<p class="kicker">The result</p>
|
||||||
|
<div style="font-size:240px;line-height:1;font-weight:900">
|
||||||
|
<span class="counter gradient-text" data-to="92">0</span><span class="gradient-text">%</span>
|
||||||
|
</div>
|
||||||
|
<h3 class="mt-s">你花在 PPT 上的时间可以被省下</h3>
|
||||||
|
<p class="lede" style="margin:14px auto 0">10 份真实 deck 的平均测试数据。</p>
|
||||||
|
</div>
|
||||||
|
<div class="deck-footer"><span class="dim2">proof</span><span class="slide-number" data-current="4" data-total="8"></span></div>
|
||||||
|
<div class="notes">强调:数据来源——自己真实的 10 个 deck。</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 5. Two column -->
|
||||||
|
<section class="slide" data-title="Tokens">
|
||||||
|
<p class="kicker">How · 核心思路</p>
|
||||||
|
<h2 class="h2">把「看起来像什么」收进 <code>:root</code></h2>
|
||||||
|
<div class="grid g2 mt-l" style="align-items:start">
|
||||||
|
<div class="card anim-fade-left" data-anim="fade-left">
|
||||||
|
<h3>概念</h3>
|
||||||
|
<p class="dim">每一种视觉属性——颜色、字体、圆角、阴影——都变成语义变量。</p>
|
||||||
|
<ul class="mt-m">
|
||||||
|
<li><code>--text-1</code> / <code>--text-2</code> / <code>--text-3</code></li>
|
||||||
|
<li><code>--surface</code> / <code>--surface-2</code></li>
|
||||||
|
<li><code>--accent</code> / <code>--accent-2</code> / <code>--accent-3</code></li>
|
||||||
|
<li><code>--radius</code> / <code>--shadow</code> / <code>--grad</code></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="card anim-fade-right" data-anim="fade-right">
|
||||||
|
<h3>示例</h3>
|
||||||
|
<pre class="mono" style="font-size:13px;background:var(--surface-2);padding:16px;border-radius:var(--radius-sm);overflow:auto;margin:0">
|
||||||
|
/* assets/themes/aurora.css */
|
||||||
|
:root {
|
||||||
|
--bg: #06091c;
|
||||||
|
--text-1: #e8f0ff;
|
||||||
|
--accent: #5ef2c6;
|
||||||
|
--accent-2: #7aa2ff;
|
||||||
|
--accent-3: #c984ff;
|
||||||
|
--radius: 20px;
|
||||||
|
}</pre>
|
||||||
|
<p class="dim mt-m" style="font-size:13px">——整个 aurora 主题就这么大。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="deck-footer"><span class="dim2">how</span><span class="slide-number" data-current="5" data-total="8"></span></div>
|
||||||
|
<div class="notes">关键是:base.css 只认变量名,不认具体色值。换主题 = 换一份变量。</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 6. Chart -->
|
||||||
|
<section class="slide" data-title="Chart">
|
||||||
|
<p class="kicker">Numbers · 实际效果</p>
|
||||||
|
<h2 class="h2">做 deck 的时间分布,使用前/使用后</h2>
|
||||||
|
<div class="card mt-l" style="height:440px;padding:24px"><canvas id="chart"></canvas></div>
|
||||||
|
<div class="deck-footer"><span class="dim2">data</span><span class="slide-number" data-current="6" data-total="8"></span></div>
|
||||||
|
<div class="notes">使用后,「写内容」时间占比大幅上升,其他一切下降——这正是我们想要的。</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 7. CTA -->
|
||||||
|
<section class="slide center tc" data-title="CTA">
|
||||||
|
<div style="max-width:920px">
|
||||||
|
<p class="kicker">Your turn</p>
|
||||||
|
<h1 class="h1 anim-rise-in" data-anim="rise-in" style="font-size:96px"><span class="gradient-text">开始</span>做你的第一份</h1>
|
||||||
|
<p class="lede" style="margin:14px auto 30px">复制一份 deck,换你的内容,按 <b>T</b> 选一个最对味的主题,讲完还能一键导 PNG。</p>
|
||||||
|
<div class="row" style="justify-content:center;gap:14px">
|
||||||
|
<div class="card" style="padding:18px 26px"><code>./scripts/new-deck.sh my-talk</code></div>
|
||||||
|
</div>
|
||||||
|
<p class="dim2 mt-l" style="font-size:14px">←/→ 翻页 · T 主题 · A 动效 · F 全屏 · O 概览 · S 备注</p>
|
||||||
|
</div>
|
||||||
|
<div class="deck-footer"><span class="dim2">cta</span><span class="slide-number" data-current="7" data-total="8"></span></div>
|
||||||
|
<div class="notes">最后给一个具体的行动:一条命令。别停留在「我回去试试」。</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 8. Thanks -->
|
||||||
|
<section class="slide center tc" data-title="Thanks">
|
||||||
|
<div>
|
||||||
|
<div class="anim-confetti-burst" style="display:inline-block;padding:20px"></div>
|
||||||
|
<h1 class="h1" style="font-size:180px;line-height:1"><span class="gradient-text">Thanks</span></h1>
|
||||||
|
<p class="lede">lewis · sudolewis@gmail.com · MIT 2026</p>
|
||||||
|
</div>
|
||||||
|
<div class="deck-footer"><span class="dim2">end</span><span class="slide-number" data-current="8" data-total="8"></span></div>
|
||||||
|
<div class="notes">谢谢大家。Q&A 时间。</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
<script>
|
||||||
|
addEventListener('DOMContentLoaded',()=>{
|
||||||
|
const css=getComputedStyle(document.documentElement);
|
||||||
|
const a1=css.getPropertyValue('--accent').trim();
|
||||||
|
const a2=css.getPropertyValue('--accent-2').trim();
|
||||||
|
const text2=css.getPropertyValue('--text-2').trim();
|
||||||
|
const border=css.getPropertyValue('--border').trim();
|
||||||
|
new Chart(document.getElementById('chart'),{type:'bar',
|
||||||
|
data:{labels:['写内容','挑版式','调样式','出图','动效'],
|
||||||
|
datasets:[
|
||||||
|
{label:'使用前 (分钟)',data:[92,48,36,22,14],backgroundColor:a2,borderRadius:6},
|
||||||
|
{label:'使用后 (分钟)',data:[18,3,2,1,1],backgroundColor:a1,borderRadius:6}]},
|
||||||
|
options:{plugins:{legend:{labels:{color:text2}}},
|
||||||
|
scales:{x:{ticks:{color:text2},grid:{color:border}},
|
||||||
|
y:{ticks:{color:text2},grid:{color:border}}}}});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
# Animations catalog
|
||||||
|
|
||||||
|
All animations live in `assets/animations/animations.css`. Apply them by
|
||||||
|
adding `class="anim-<name>"` OR `data-anim="<name>"` to any element
|
||||||
|
(`runtime.js` re-triggers `data-anim` elements whenever a slide becomes
|
||||||
|
active, so you get the entry effect every time you navigate onto the slide).
|
||||||
|
|
||||||
|
Open `templates/animation-showcase.html` to browse all of them — one slide
|
||||||
|
per animation, auto-playing on slide enter. Press **A** on any slide to cycle
|
||||||
|
a random animation on the current page.
|
||||||
|
|
||||||
|
## Directional fades
|
||||||
|
|
||||||
|
| name | effect | use for |
|
||||||
|
|---|---|---|
|
||||||
|
| `fade-up` | Translate from +32 px, fade. | Default for paragraph + card entry. |
|
||||||
|
| `fade-down` | Translate from -32 px, fade. | Headers / banners / callouts. |
|
||||||
|
| `fade-left` | Translate from -40 px. | Left column in a two-column layout. |
|
||||||
|
| `fade-right` | Translate from +40 px. | Right column in a two-column layout. |
|
||||||
|
|
||||||
|
## Dramatic entries
|
||||||
|
|
||||||
|
| name | effect | use for |
|
||||||
|
|---|---|---|
|
||||||
|
| `rise-in` | +60 px rise + blur-off. | Slide titles, hero headlines. |
|
||||||
|
| `drop-in` | -60 px drop + slight scale. | Banners, alert bars. |
|
||||||
|
| `zoom-pop` | Scale 0.6 → 1.04 → 1. | Buttons, stat numbers, CTAs. |
|
||||||
|
| `blur-in` | 18 px blur clears. | Cover page reveal. |
|
||||||
|
| `glitch-in` | Clip-path steps + jitter. | Tech / cyber / error states. |
|
||||||
|
|
||||||
|
## Text effects
|
||||||
|
|
||||||
|
| name | effect | use for |
|
||||||
|
|---|---|---|
|
||||||
|
| `typewriter` | Monospace-like type reveal. | One-liners, slogans. |
|
||||||
|
| `neon-glow` | Cyclic text-shadow pulse. | Terminal-green / dracula themes. |
|
||||||
|
| `shimmer-sweep` | White sheen passes across. | Metallic buttons, premium cards. |
|
||||||
|
| `gradient-flow` | Infinite horizontal gradient slide. | Brand wordmarks. |
|
||||||
|
|
||||||
|
## Lists & numbers
|
||||||
|
|
||||||
|
| name | effect | use for |
|
||||||
|
|---|---|---|
|
||||||
|
| `stagger-list` | Children rise-in one-by-one. | Any `<ul>` or `.grid`. |
|
||||||
|
| `counter-up` | Number ticks 0 → target. | KPI, stat-highlight pages. |
|
||||||
|
|
||||||
|
Counter markup:
|
||||||
|
```html
|
||||||
|
<span class="counter" data-to="1248">0</span>
|
||||||
|
```
|
||||||
|
|
||||||
|
## SVG / geometry
|
||||||
|
|
||||||
|
| name | effect | use for |
|
||||||
|
|---|---|---|
|
||||||
|
| `path-draw` | Strokes draw themselves. | Lines, arrows, diagrams. |
|
||||||
|
| `morph-shape` | Path `d` morph. | Background shapes. |
|
||||||
|
|
||||||
|
Put `class="anim-path-draw"` on `<svg>`; every path/line/circle inside gets drawn.
|
||||||
|
|
||||||
|
## 3D & perspective
|
||||||
|
|
||||||
|
| name | effect | use for |
|
||||||
|
|---|---|---|
|
||||||
|
| `parallax-tilt` | Hover → 3D tilt. | Hero cards, product shots. |
|
||||||
|
| `card-flip-3d` | Y-axis 90° flip. | Before/after reveal. |
|
||||||
|
| `cube-rotate-3d` | Rotate in from a cube side. | Section dividers. |
|
||||||
|
| `page-turn-3d` | Left-hinge page turn. | Editorial / story flows. |
|
||||||
|
| `perspective-zoom` | Pull from -400 Z. | Cover openings. |
|
||||||
|
|
||||||
|
## Ambient / continuous
|
||||||
|
|
||||||
|
| name | effect | use for |
|
||||||
|
|---|---|---|
|
||||||
|
| `marquee-scroll` | Infinite horizontal loop. | Client logo strips. |
|
||||||
|
| `kenburns` | 14 s slow zoom on images. | Hero backgrounds. |
|
||||||
|
| `confetti-burst` | Pseudo-element sparkle burst. | Thanks / win pages. |
|
||||||
|
| `spotlight` | Circular clip-path reveal. | Big reveal moments. |
|
||||||
|
| `ripple-reveal` | Corner-origin ripple reveal. | Section transitions. |
|
||||||
|
|
||||||
|
## Respecting motion preferences
|
||||||
|
|
||||||
|
All animations are disabled automatically when
|
||||||
|
`prefers-reduced-motion: reduce` is set. Do not override this.
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- Prefer `data-anim="..."` over `class="anim-..."` so that the runtime
|
||||||
|
re-triggers the animation whenever the slide becomes active.
|
||||||
|
- Use at most 1-2 distinct animation types on a single slide. Mixing 5 looks
|
||||||
|
messy.
|
||||||
|
- Stagger lists + a single hero entry = clean rhythm.
|
||||||
|
- For counter-up, pair with `stat-highlight.html` or `kpi-grid.html`.
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
# Authoring guide
|
||||||
|
|
||||||
|
How to turn a user request ("make me a deck about X") into a finished
|
||||||
|
html-ppt deck. Follow these steps in order.
|
||||||
|
|
||||||
|
## 1. Understand the deck
|
||||||
|
|
||||||
|
Before touching files, clarify:
|
||||||
|
|
||||||
|
1. **Audience** — engineers? designers? executives? consumers?
|
||||||
|
2. **Length** — 5 min lightning? 20 min share? 45 min talk?
|
||||||
|
3. **Language** — Chinese, English, bilingual? (Noto Sans SC is preloaded.)
|
||||||
|
4. **Format** — on-screen live, PDF export, 小红书图文?
|
||||||
|
5. **Tone** — clinical / playful / editorial / cyber?
|
||||||
|
|
||||||
|
The audience + tone map to a theme; the length maps to slide count; the
|
||||||
|
format maps to runtime features (live → notes + T-cycle; PDF → page-break
|
||||||
|
CSS, already handled in `base.css`).
|
||||||
|
|
||||||
|
## 2. Pick a theme
|
||||||
|
|
||||||
|
Use `references/themes.md`. When in doubt:
|
||||||
|
|
||||||
|
- **Engineers** → `catppuccin-mocha` / `tokyo-night` / `dracula`.
|
||||||
|
- **Designers / product** → `editorial-serif` / `aurora` / `soft-pastel`.
|
||||||
|
- **Execs** → `minimal-white` / `arctic-cool` / `swiss-grid`.
|
||||||
|
- **Consumers** → `xiaohongshu-white` / `sunset-warm` / `soft-pastel`.
|
||||||
|
- **Cyber / CLI / infra** → `terminal-green` / `blueprint` / `gruvbox-dark`.
|
||||||
|
- **Pitch / bold** → `neo-brutalism` / `sharp-mono` / `bauhaus`.
|
||||||
|
- **Launch / product reveal** → `glassmorphism` / `aurora`.
|
||||||
|
|
||||||
|
Wire the theme as `<link id="theme-link" href="../assets/themes/NAME.css">`
|
||||||
|
and list 3-5 alternatives in `data-themes` so the user can press T to audition.
|
||||||
|
|
||||||
|
## 3. Outline the deck
|
||||||
|
|
||||||
|
A solid 20-minute deck is usually:
|
||||||
|
|
||||||
|
```
|
||||||
|
cover → toc → section-divider #1 → [2-4 body pages] →
|
||||||
|
section-divider #2 → [2-4 body pages] → section-divider #3 →
|
||||||
|
[2-4 body pages] → cta → thanks
|
||||||
|
```
|
||||||
|
|
||||||
|
Pick 1 layout per page from `references/layouts.md`. Don't repeat the same
|
||||||
|
layout twice in a row.
|
||||||
|
|
||||||
|
## 4. Scaffold the deck
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/new-deck.sh my-talk
|
||||||
|
```
|
||||||
|
|
||||||
|
This copies `templates/deck.html` into `examples/my-talk/index.html` with
|
||||||
|
paths rewritten. Add/remove `<section class="slide">` blocks to match your
|
||||||
|
outline.
|
||||||
|
|
||||||
|
## 5. Author each slide
|
||||||
|
|
||||||
|
For each outline item:
|
||||||
|
|
||||||
|
1. Open the matching single-page layout, e.g. `templates/single-page/kpi-grid.html`.
|
||||||
|
2. Copy the `<section class="slide">…</section>` block.
|
||||||
|
3. Paste into your deck.
|
||||||
|
4. Replace demo data with real data. Keep the class structure intact.
|
||||||
|
5. Set `data-title="..."` (used by the Overview grid).
|
||||||
|
6. Add `<div class="notes">…</div>` with speaker notes.
|
||||||
|
|
||||||
|
## 6. Add animations sparingly
|
||||||
|
|
||||||
|
Rules of thumb:
|
||||||
|
|
||||||
|
- Cover/title: `rise-in` or `blur-in`.
|
||||||
|
- Body content: `fade-up` for the hero element, `stagger-list` for grids/lists.
|
||||||
|
- Stat pages: `counter-up`.
|
||||||
|
- Section dividers: `perspective-zoom` or `cube-rotate-3d`.
|
||||||
|
- Closer: `confetti-burst` on the "Thanks" text.
|
||||||
|
|
||||||
|
Pick **one** accent animation per slide. Everything else should be calm.
|
||||||
|
|
||||||
|
## 7. Chinese + English decks
|
||||||
|
|
||||||
|
- Fonts are already imported in `fonts.css` (Noto Sans SC + Noto Serif SC).
|
||||||
|
- Use `lang="zh-CN"` on `<html>`.
|
||||||
|
- For bilingual titles, stack lines: `<h1 class="h1">主标题<br><span class="dim">English subtitle</span></h1>`.
|
||||||
|
- Keep English subtitles in a lighter weight (300) and dim color to avoid
|
||||||
|
visual competition.
|
||||||
|
|
||||||
|
## 8. Review in-browser
|
||||||
|
|
||||||
|
```bash
|
||||||
|
open examples/my-talk/index.html
|
||||||
|
```
|
||||||
|
|
||||||
|
Walk through every slide with ← →. Press:
|
||||||
|
|
||||||
|
- **O** — overview grid; catch any layout clipping.
|
||||||
|
- **T** — cycle themes; make sure nothing looks broken in any theme.
|
||||||
|
- **S** — open speaker notes; verify every slide has notes.
|
||||||
|
|
||||||
|
## 9. Export to PNG
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# single slide
|
||||||
|
./scripts/render.sh examples/my-talk/index.html
|
||||||
|
|
||||||
|
# all slides (autodetect count by looking for .slide sections)
|
||||||
|
./scripts/render.sh examples/my-talk/index.html all
|
||||||
|
|
||||||
|
# explicit slide count + output dir
|
||||||
|
./scripts/render.sh examples/my-talk/index.html 12 out/my-talk-png
|
||||||
|
```
|
||||||
|
|
||||||
|
Output is 1920×1080 by default. Change in `render.sh` if the user wants 3:4
|
||||||
|
for 小红书图文 (1242×1660).
|
||||||
|
|
||||||
|
## 10. What to NOT do
|
||||||
|
|
||||||
|
- Don't hand-author from a blank file.
|
||||||
|
- Don't use raw hex colors in slide markup. Use tokens.
|
||||||
|
- Don't load heavy animation frameworks. Everything should stay within the
|
||||||
|
CSS/JS that already ships.
|
||||||
|
- Don't add more than one new template file unless a genuinely new layout
|
||||||
|
type is needed. Prefer composition.
|
||||||
|
- Don't delete slides from the showcase decks.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
- **Theme doesn't switch with T**: check `data-themes` on `<body>` and
|
||||||
|
`data-theme-base` pointing to the themes directory relative to the HTML
|
||||||
|
file.
|
||||||
|
- **Fonts fall back**: make sure `fonts.css` is linked before the theme.
|
||||||
|
- **Chart.js colors wrong**: charts read CSS vars in JS; make sure they run
|
||||||
|
after the DOM is ready (`addEventListener('DOMContentLoaded', …)`).
|
||||||
|
- **PNG too small**: bump `--window-size` in `scripts/render.sh`.
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
# Layouts catalog
|
||||||
|
|
||||||
|
Every layout lives in `templates/single-page/<name>.html` as a fully
|
||||||
|
functional standalone page with realistic demo data. Open any file directly
|
||||||
|
in Chrome to see it working.
|
||||||
|
|
||||||
|
To compose a new deck: open the file, copy the `<section class="slide">…</section>`
|
||||||
|
block (or multiple blocks) into your deck HTML, and replace the demo data.
|
||||||
|
Shared CSS (base, theme, animations) is already wired by `deck.html`.
|
||||||
|
|
||||||
|
## Openers & transitions
|
||||||
|
|
||||||
|
| file | purpose |
|
||||||
|
|---|---|
|
||||||
|
| `cover.html` | Deck cover. Kicker + huge title + lede + pill row. |
|
||||||
|
| `toc.html` | Table of contents. 2×3 grid of numbered cards. |
|
||||||
|
| `section-divider.html` | Big numbered section break (02 · Theme). |
|
||||||
|
|
||||||
|
## Text-centric
|
||||||
|
|
||||||
|
| file | purpose |
|
||||||
|
|---|---|
|
||||||
|
| `bullets.html` | Classic bullet list with card-wrapped items. |
|
||||||
|
| `two-column.html` | Concept + example side by side. |
|
||||||
|
| `three-column.html` | Three equal pillars with icons. |
|
||||||
|
| `big-quote.html` | Full-bleed pull quote in editorial-serif style. |
|
||||||
|
|
||||||
|
## Numbers & data
|
||||||
|
|
||||||
|
| file | purpose |
|
||||||
|
|---|---|
|
||||||
|
| `stat-highlight.html` | One giant number + subtitle (uses `.counter` animation). |
|
||||||
|
| `kpi-grid.html` | 4 KPIs in a row with up/down deltas. |
|
||||||
|
| `table.html` | Data table with hover rows, right-aligned numerics. |
|
||||||
|
| `chart-bar.html` | Chart.js bar chart, theme-aware colors. |
|
||||||
|
| `chart-line.html` | Chart.js dual-line chart with filled area. |
|
||||||
|
| `chart-pie.html` | Chart.js doughnut + takeaways card. |
|
||||||
|
| `chart-radar.html` | Chart.js radar comparing 2 products on 6 axes. |
|
||||||
|
|
||||||
|
## Code & terminal
|
||||||
|
|
||||||
|
| file | purpose |
|
||||||
|
|---|---|
|
||||||
|
| `code.html` | Syntax-highlighted code via highlight.js (JS example). |
|
||||||
|
| `diff.html` | Hand-rolled +/- diff view. |
|
||||||
|
| `terminal.html` | Terminal window mock with traffic-light header. |
|
||||||
|
|
||||||
|
## Diagrams & flows
|
||||||
|
|
||||||
|
| file | purpose |
|
||||||
|
|---|---|
|
||||||
|
| `flow-diagram.html` | 5-node pipeline with arrows and one highlighted node. |
|
||||||
|
| `arch-diagram.html` | 3-tier architecture grid. |
|
||||||
|
| `process-steps.html` | 4 numbered steps in cards. |
|
||||||
|
| `mindmap.html` | Radial mindmap with SVG path-draw animation. |
|
||||||
|
|
||||||
|
## Plans & comparisons
|
||||||
|
|
||||||
|
| file | purpose |
|
||||||
|
|---|---|
|
||||||
|
| `timeline.html` | 5-point horizontal timeline with dots. |
|
||||||
|
| `roadmap.html` | 4-column NOW / NEXT / LATER / VISION. |
|
||||||
|
| `gantt.html` | 12-week gantt chart with 5 parallel tracks. |
|
||||||
|
| `comparison.html` | Before vs After two-panel card. |
|
||||||
|
| `pros-cons.html` | Pros and cons two-card layout. |
|
||||||
|
| `todo-checklist.html` | Checklist with checked/unchecked states. |
|
||||||
|
|
||||||
|
## Visuals
|
||||||
|
|
||||||
|
| file | purpose |
|
||||||
|
|---|---|
|
||||||
|
| `image-hero.html` | Full-bleed hero with Ken Burns gradient background. |
|
||||||
|
| `image-grid.html` | 7-cell bento grid with gradient placeholders. |
|
||||||
|
|
||||||
|
## Closers
|
||||||
|
|
||||||
|
| file | purpose |
|
||||||
|
|---|---|
|
||||||
|
| `cta.html` | Call-to-action with big gradient headline + buttons. |
|
||||||
|
| `thanks.html` | Final "Thanks" page with confetti burst. |
|
||||||
|
|
||||||
|
## Picking a layout
|
||||||
|
|
||||||
|
- **Opener**: `cover.html`, often followed by `toc.html`.
|
||||||
|
- **Section break**: `section-divider.html` before every major section.
|
||||||
|
- **Core content**: `bullets.html`, `two-column.html`, `three-column.html`.
|
||||||
|
- **Show numbers**: `stat-highlight.html` (single) or `kpi-grid.html` (4-up).
|
||||||
|
- **Show plot**: `chart-bar.html` / `chart-line.html` / `chart-pie.html` / `chart-radar.html`.
|
||||||
|
- **Show a diff or change**: `comparison.html`, `diff.html`, `pros-cons.html`.
|
||||||
|
- **Show a plan**: `timeline.html`, `roadmap.html`, `gantt.html`, `process-steps.html`.
|
||||||
|
- **Show architecture**: `arch-diagram.html`, `flow-diagram.html`, `mindmap.html`.
|
||||||
|
- **Code / demo**: `code.html`, `terminal.html`.
|
||||||
|
- **Closer**: `cta.html` → `thanks.html`.
|
||||||
|
|
||||||
|
## Naming / structure conventions
|
||||||
|
|
||||||
|
- Each slide is `<section class="slide" data-title="...">`.
|
||||||
|
- Header pills: `<p class="kicker">…</p>`, eyebrow: `<p class="eyebrow">…</p>`.
|
||||||
|
- Titles: `<h1 class="h1">…</h1>` / `<h2 class="h2">…</h2>`.
|
||||||
|
- Lede: `<p class="lede">…</p>`.
|
||||||
|
- Cards: `<div class="card">…</div>` (variants: `card-soft`, `card-outline`, `card-accent`).
|
||||||
|
- Grids: `.grid.g2`, `.grid.g3`, `.grid.g4`.
|
||||||
|
- Notes: `<div class="notes">…</div>` per slide.
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Themes catalog
|
||||||
|
|
||||||
|
Every theme is a short CSS file in `assets/themes/` that overrides tokens
|
||||||
|
defined in `assets/base.css`. Switch themes by changing the `href` of
|
||||||
|
`<link id="theme-link">` or by pressing **T** if the deck has a
|
||||||
|
`data-themes="a,b,c"` attribute on `<body>` or `<html>`.
|
||||||
|
|
||||||
|
All themes define the same variables: `--bg`, `--bg-soft`, `--surface`,
|
||||||
|
`--surface-2`, `--border`, `--text-1/2/3`, `--accent`, `--accent-2/3`,
|
||||||
|
`--good`, `--warn`, `--bad`, `--grad`, `--grad-soft`, `--radius*`, `--shadow*`,
|
||||||
|
`--font-sans`, `--font-display`.
|
||||||
|
|
||||||
|
## Light & calm
|
||||||
|
|
||||||
|
| name | description | when to use |
|
||||||
|
|---|---|---|
|
||||||
|
| `minimal-white` | 极简白,克制高级。Inter,强文字层级,极低阴影。 | 内部汇报、一对一技术评审、不抢内容的严肃话题 |
|
||||||
|
| `editorial-serif` | 杂志风 Playfair 衬线 + 奶油底。 | 品牌故事、文字密度大的长文演讲 |
|
||||||
|
| `soft-pastel` | 柔和马卡龙三色渐变。 | 产品发布、面向消费者、轻松话题 |
|
||||||
|
| `xiaohongshu-white` | 小红书白底 + 暖红 accent + 衬线标题。 | 小红书图文、生活/美学类内容 |
|
||||||
|
| `solarized-light` | 经典低眩光配色。 | 长时间观看的工作坊、教学 |
|
||||||
|
| `catppuccin-latte` | catppuccin 浅色。 | 开发者、极客友好的技术分享 |
|
||||||
|
|
||||||
|
## Bold & statement
|
||||||
|
|
||||||
|
| name | description | when to use |
|
||||||
|
|---|---|---|
|
||||||
|
| `sharp-mono` | 纯黑白 + Archivo Black + 硬阴影。 | 宣言类、极具冲击力的视觉 |
|
||||||
|
| `neo-brutalism` | 厚描边、硬阴影、明黄 accent。 | 创业路演、敢说敢做的调性 |
|
||||||
|
| `bauhaus` | 几何 + 红黄蓝原色。 | 设计 talk、艺术史/产品美学主题 |
|
||||||
|
| `swiss-grid` | 瑞士网格 + Helvetica 感 + 12 栏底纹。 | 严肃排版、设计行业 |
|
||||||
|
| `memphis-pop` | 孟菲斯波普背景点 + 大字标题。 | 年轻、潮流、品牌合作 |
|
||||||
|
|
||||||
|
## Cool & dark
|
||||||
|
|
||||||
|
| name | description | when to use |
|
||||||
|
|---|---|---|
|
||||||
|
| `catppuccin-mocha` | catppuccin 深。 | 开发者内部分享、长时间观看 |
|
||||||
|
| `dracula` | 经典 Dracula 紫红主色。 | 代码密集的技术分享 |
|
||||||
|
| `tokyo-night` | Tokyo Night 蓝夜。 | 偏冷技术分享、基础设施 |
|
||||||
|
| `nord` | 北欧清冷蓝白。 | 基础设施、云产品 |
|
||||||
|
| `gruvbox-dark` | 温暖复古深色。 | Terminal / vim / *nix 社群 |
|
||||||
|
| `rose-pine` | 玫瑰松,柔和暗色。 | 设计+开发交界、审美向技术 |
|
||||||
|
| `arctic-cool` | 蓝/青/石板灰 浅色版。 | 商业分析、金融、冷静理性 |
|
||||||
|
|
||||||
|
## Warm & vibrant
|
||||||
|
|
||||||
|
| name | description | when to use |
|
||||||
|
|---|---|---|
|
||||||
|
| `sunset-warm` | 橘 / 珊瑚 / 琥珀三色渐变。 | 生活方式、奖项颁发、情绪正向 |
|
||||||
|
|
||||||
|
## Effect-heavy
|
||||||
|
|
||||||
|
| name | description | when to use |
|
||||||
|
|---|---|---|
|
||||||
|
| `glassmorphism` | 毛玻璃 + 多色光斑背景。 | Apple 式发布会、产品特性展示 |
|
||||||
|
| `aurora` | 极光渐变 + blur + saturate。 | 封面 / CTA / 结语页 |
|
||||||
|
| `rainbow-gradient` | 白底 + 彩虹流动渐变 accent。 | 欢乐向、节日、庆祝页 |
|
||||||
|
| `blueprint` | 蓝图工程 + 网格底纹 + 蒙太奇字体。 | 系统架构、工程蓝图 |
|
||||||
|
| `terminal-green` | 绿屏终端 + 等宽 + 发光文字。 | CLI/black-hat/复古朋克 |
|
||||||
|
|
||||||
|
## How to apply
|
||||||
|
|
||||||
|
```html
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../assets/themes/aurora.css">
|
||||||
|
```
|
||||||
|
|
||||||
|
Or enable `T`-cycling by listing themes on the body:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<body data-themes="minimal-white,aurora,catppuccin-mocha" data-theme-base="../assets/themes/">
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to extend
|
||||||
|
|
||||||
|
Copy an existing theme, rename it, and override only the variables you want to
|
||||||
|
change. Keep each theme under ~200 lines. Prefer adjusting tokens to adding
|
||||||
|
new selectors.
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# html-ppt :: new-deck.sh — scaffold a new deck from templates/deck.html
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# new-deck.sh <name> [output-parent-dir]
|
||||||
|
#
|
||||||
|
# Creates <parent>/<name>/index.html with paths rewritten to point at the
|
||||||
|
# skill's shared assets/themes/animations. Defaults to ./examples/.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
NAME="${1:-}"
|
||||||
|
if [[ -z "$NAME" ]]; then
|
||||||
|
echo "usage: new-deck.sh <name> [parent-dir]" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PARENT="${2:-examples}"
|
||||||
|
HERE="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
TEMPLATE="$HERE/templates/deck.html"
|
||||||
|
|
||||||
|
if [[ ! -f "$TEMPLATE" ]]; then
|
||||||
|
echo "error: template not found at $TEMPLATE" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
OUT_DIR="$HERE/$PARENT/$NAME"
|
||||||
|
if [[ -e "$OUT_DIR" ]]; then
|
||||||
|
echo "error: $OUT_DIR already exists" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mkdir -p "$OUT_DIR"
|
||||||
|
|
||||||
|
# templates/deck.html references ../assets/...; for examples/<name>/index.html
|
||||||
|
# that same relative path (../../assets/...) needs one more ../.
|
||||||
|
sed 's|href="../assets/|href="../../assets/|g; s|src="../assets/|src="../../assets/|g; s|data-theme-base="../assets/|data-theme-base="../../assets/|g' \
|
||||||
|
"$TEMPLATE" > "$OUT_DIR/index.html"
|
||||||
|
|
||||||
|
echo "✔ created $OUT_DIR/index.html"
|
||||||
|
echo ""
|
||||||
|
echo "next steps:"
|
||||||
|
echo " open $OUT_DIR/index.html"
|
||||||
|
echo " # press T to cycle themes, ← → to navigate, O for overview"
|
||||||
|
echo ""
|
||||||
|
echo " # render to PNG:"
|
||||||
|
echo " $HERE/scripts/render.sh $OUT_DIR/index.html all"
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# html-ppt :: render.sh — headless Chrome screenshot(s)
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# render.sh <html-file> # one PNG, slide 1
|
||||||
|
# render.sh <html-file> <N> # N PNGs, slides 1..N, via #/k
|
||||||
|
# render.sh <html-file> all # autodetect .slide count
|
||||||
|
# render.sh <html-file> <N> <out-dir> # custom output dir
|
||||||
|
#
|
||||||
|
# Requires: Google Chrome at /Applications/Google Chrome.app (macOS).
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
CHROME="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
||||||
|
if [[ ! -x "$CHROME" ]]; then
|
||||||
|
echo "error: Chrome not found at $CHROME" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
FILE="${1:-}"
|
||||||
|
if [[ -z "$FILE" ]]; then
|
||||||
|
echo "usage: render.sh <html> [N|all] [out-dir]" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ ! -f "$FILE" ]]; then
|
||||||
|
echo "error: $FILE not found" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
COUNT="${2:-1}"
|
||||||
|
OUT="${3:-}"
|
||||||
|
|
||||||
|
ABS="$(cd "$(dirname "$FILE")" && pwd)/$(basename "$FILE")"
|
||||||
|
STEM="$(basename "${FILE%.*}")"
|
||||||
|
|
||||||
|
if [[ "$COUNT" == "all" ]]; then
|
||||||
|
COUNT="$(grep -c 'class="slide"' "$FILE" || true)"
|
||||||
|
[[ -z "$COUNT" || "$COUNT" -lt 1 ]] && COUNT=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$OUT" ]]; then
|
||||||
|
if [[ "$COUNT" -gt 1 ]]; then
|
||||||
|
OUT="$(dirname "$FILE")/${STEM}-png"
|
||||||
|
mkdir -p "$OUT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
render_one() {
|
||||||
|
local url="$1" target="$2"
|
||||||
|
"$CHROME" \
|
||||||
|
--headless=new \
|
||||||
|
--disable-gpu \
|
||||||
|
--hide-scrollbars \
|
||||||
|
--no-sandbox \
|
||||||
|
--virtual-time-budget=4000 \
|
||||||
|
--window-size=1920,1080 \
|
||||||
|
--screenshot="$target" \
|
||||||
|
"$url" >/dev/null 2>&1
|
||||||
|
echo " ✔ $target"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "$COUNT" == "1" ]]; then
|
||||||
|
OUT_FILE="${OUT:-$(dirname "$FILE")/${STEM}.png}"
|
||||||
|
render_one "file://$ABS" "$OUT_FILE"
|
||||||
|
else
|
||||||
|
for i in $(seq 1 "$COUNT"); do
|
||||||
|
render_one "file://$ABS#/$i" "$OUT/${STEM}_$(printf '%02d' "$i").png"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "done: rendered $COUNT slide(s) from $FILE"
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN" data-theme="aurora">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"><title>Animation Showcase — html-ppt</title>
|
||||||
|
<link rel="stylesheet" href="../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../assets/themes/aurora.css">
|
||||||
|
<link rel="stylesheet" href="../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.anim-box{margin:24px auto 0;width:640px;height:240px;border-radius:var(--radius-lg);background:var(--grad-soft);display:flex;align-items:center;justify-content:center;font-size:44px;font-weight:800;color:var(--text-1);box-shadow:var(--shadow-lg);border:1px solid var(--border)}
|
||||||
|
.anim-indicator{position:absolute;top:24px;right:40px;font-family:var(--font-mono);font-size:11px;color:var(--text-3);letter-spacing:.1em}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="deck"></div>
|
||||||
|
<script>
|
||||||
|
const list=[
|
||||||
|
['fade-up','从下向上淡入。默认的万能入场。'],
|
||||||
|
['fade-down','从上向下淡入。标题行常用。'],
|
||||||
|
['fade-left','从左侧水平滑入。'],
|
||||||
|
['fade-right','从右侧水平滑入。'],
|
||||||
|
['rise-in','带轻微模糊从下方升起。高级感入场。'],
|
||||||
|
['drop-in','从上方落下。强调感。'],
|
||||||
|
['zoom-pop','弹性缩放,先过 1.04 再回到 1。按钮/数字常用。'],
|
||||||
|
['blur-in','去模糊聚焦。封面推荐。'],
|
||||||
|
['glitch-in','故障艺术抖动入场。'],
|
||||||
|
['typewriter','打字机逐字显示。'],
|
||||||
|
['neon-glow','文字周期性发光。霓虹主题推荐。'],
|
||||||
|
['shimmer-sweep','表面反光扫过。金属质感。'],
|
||||||
|
['gradient-flow','渐变文字水平流动。'],
|
||||||
|
['stagger-list','子元素错峰出现。'],
|
||||||
|
['counter-up','数字从 0 tick 到目标值。KPI 必备。'],
|
||||||
|
['path-draw','SVG 线条勾勒动效。'],
|
||||||
|
['parallax-tilt','鼠标悬浮时 3D 倾斜。'],
|
||||||
|
['card-flip-3d','卡片 Y 轴翻转。'],
|
||||||
|
['cube-rotate-3d','立方体旋转入场。'],
|
||||||
|
['page-turn-3d','页面翻页效果。'],
|
||||||
|
['perspective-zoom','远景拉近。'],
|
||||||
|
['marquee-scroll','跑马灯横向滚动。'],
|
||||||
|
['kenburns','Ken Burns 缓慢推拉。图片/封面必备。'],
|
||||||
|
['confetti-burst','彩纸爆炸。成就 / 结语页。'],
|
||||||
|
['spotlight','聚光灯圆形揭示。'],
|
||||||
|
['morph-shape','SVG 形状变形。'],
|
||||||
|
['ripple-reveal','从一角涟漪展开。']
|
||||||
|
];
|
||||||
|
const deck=document.querySelector('.deck');
|
||||||
|
list.forEach((a,i)=>{
|
||||||
|
const s=document.createElement('section');
|
||||||
|
s.className='slide';s.setAttribute('data-title',a[0]);
|
||||||
|
s.innerHTML=`
|
||||||
|
<span class="anim-indicator">${i+1}/${list.length}</span>
|
||||||
|
<p class="kicker">Animation · ${String(i+1).padStart(2,'0')}</p>
|
||||||
|
<h1 class="h1"><span class="gradient-text">${a[0]}</span></h1>
|
||||||
|
<p class="lede">${a[1]}</p>
|
||||||
|
<div class="anim-box anim-${a[0]}" data-anim="${a[0]}" data-anim-target>${a[0]}</div>
|
||||||
|
<div class="deck-footer"><span class="dim2">按 A 循环所有动效</span><span class="slide-number" data-current="${i+1}" data-total="${list.length}"></span></div>
|
||||||
|
<div class="notes">每次切换到这张 slide,runtime 会自动重新触发 [data-anim] 元素的入场动画。</div>
|
||||||
|
`;
|
||||||
|
deck.appendChild(s);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<script src="../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN" data-theme="minimal-white">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
|
<title>html-ppt · Deck</title>
|
||||||
|
<link rel="stylesheet" href="../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../assets/animations/animations.css">
|
||||||
|
</head>
|
||||||
|
<body data-themes="minimal-white,editorial-serif,soft-pastel,arctic-cool,sunset-warm,catppuccin-mocha,tokyo-night,aurora,xiaohongshu-white,neo-brutalism" data-theme-base="../assets/themes/">
|
||||||
|
<div class="deck">
|
||||||
|
|
||||||
|
<!-- 1. Cover -->
|
||||||
|
<section class="slide" data-title="Cover">
|
||||||
|
<p class="kicker">html-ppt · 2026</p>
|
||||||
|
<h1 class="h1 anim-fade-up" data-anim="fade-up">用模板,<span class="gradient-text">换主题</span><br>讲任何事情</h1>
|
||||||
|
<p class="lede">24 themes · 30 layouts · 25 animations · zero build</p>
|
||||||
|
<div class="deck-footer"><span class="dim2">lewis</span><span class="slide-number" data-current="1" data-total="6"></span></div>
|
||||||
|
<div class="notes">这是一个最小可用的 deck。你可以复制这个文件作为新 deck 的起点。</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 2. TOC -->
|
||||||
|
<section class="slide" data-title="目录">
|
||||||
|
<p class="kicker">Agenda</p>
|
||||||
|
<h2 class="h2">我们会讲三件事</h2>
|
||||||
|
<div class="grid g3 mt-l anim-stagger-list" data-anim-target>
|
||||||
|
<div class="card"><h4>01 · Tokens</h4><p class="dim">把颜色/字体/圆角收进 CSS 变量。</p></div>
|
||||||
|
<div class="card"><h4>02 · Layouts</h4><p class="dim">30 种可复用单页。</p></div>
|
||||||
|
<div class="card"><h4>03 · Runtime</h4><p class="dim">键盘驱动、按 T 换主题。</p></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 3. Stat -->
|
||||||
|
<section class="slide center tc" data-title="Stat">
|
||||||
|
<div>
|
||||||
|
<p class="kicker">Result</p>
|
||||||
|
<div style="font-size:220px;font-weight:900;line-height:1"><span class="counter gradient-text" data-to="92">0</span><span class="gradient-text">%</span></div>
|
||||||
|
<h3>的准备时间被省下</h3>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 4. Two column -->
|
||||||
|
<section class="slide" data-title="Tokens">
|
||||||
|
<p class="kicker">Under the hood</p>
|
||||||
|
<h2 class="h2">换主题 = 换一组变量</h2>
|
||||||
|
<div class="grid g2 mt-l">
|
||||||
|
<div class="card"><h4>语义变量</h4><p class="dim">写 <code>var(--surface)</code>,不写具体色值。</p></div>
|
||||||
|
<div class="card"><h4>一键切换</h4><p class="dim">按 T 循环所有主题——所有 slide 同步更新。</p></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 5. CTA -->
|
||||||
|
<section class="slide center tc" data-title="CTA">
|
||||||
|
<div>
|
||||||
|
<p class="kicker">Your turn</p>
|
||||||
|
<h1 class="h1 anim-rise-in" data-anim="rise-in">开始做你的 deck</h1>
|
||||||
|
<p class="lede" style="margin:16px auto">按 ← → 翻页 · T 切主题 · A 切动效 · F 全屏 · O 概览 · S 备注</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 6. Thanks -->
|
||||||
|
<section class="slide center tc" data-title="Thanks">
|
||||||
|
<h1 class="h1" style="font-size:160px;line-height:1"><span class="gradient-text">Thanks</span></h1>
|
||||||
|
<p class="lede">lewis · sudolewis@gmail.com</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<script src="../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"><title>Layout Showcase — html-ppt</title>
|
||||||
|
<link rel="stylesheet" href="../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.layout-nav{position:fixed;top:16px;left:50%;transform:translateX(-50%);z-index:50;background:var(--surface);border:1px solid var(--border);border-radius:999px;padding:8px 20px;font-family:var(--font-mono);font-size:12px;color:var(--text-2);box-shadow:var(--shadow);display:flex;gap:14px;align-items:center}
|
||||||
|
.layout-nav a{color:var(--text-2);text-decoration:none;padding:4px 10px;border-radius:999px}
|
||||||
|
.layout-nav a:hover{background:var(--surface-2)}
|
||||||
|
iframe{width:100%;height:100vh;border:0;display:block;background:var(--bg)}
|
||||||
|
body{margin:0;overflow:hidden}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="layout-nav">
|
||||||
|
<b>layouts</b>
|
||||||
|
<a href="#" data-go="-1">←</a>
|
||||||
|
<span id="cur">cover</span>
|
||||||
|
<a href="#" data-go="+1">→</a>
|
||||||
|
</div>
|
||||||
|
<iframe id="frame" src="single-page/cover.html"></iframe>
|
||||||
|
<script>
|
||||||
|
const list=['cover','toc','section-divider','bullets','two-column','three-column','big-quote',
|
||||||
|
'stat-highlight','kpi-grid','table','code','diff','terminal','flow-diagram','timeline',
|
||||||
|
'roadmap','mindmap','comparison','pros-cons','todo-checklist','gantt','image-hero','image-grid',
|
||||||
|
'chart-bar','chart-line','chart-pie','chart-radar','arch-diagram','process-steps','cta','thanks'];
|
||||||
|
let i=0;
|
||||||
|
const frame=document.getElementById('frame');
|
||||||
|
const cur=document.getElementById('cur');
|
||||||
|
function go(n){
|
||||||
|
i=(n+list.length)%list.length;
|
||||||
|
frame.src='single-page/'+list[i]+'.html';
|
||||||
|
cur.textContent=list[i]+' · '+(i+1)+'/'+list.length;
|
||||||
|
history.replaceState(null,'','#/'+(i+1));
|
||||||
|
}
|
||||||
|
document.querySelectorAll('[data-go]').forEach(a=>a.addEventListener('click',e=>{e.preventDefault();go(i+parseInt(a.dataset.go,10))}));
|
||||||
|
document.addEventListener('keydown',e=>{
|
||||||
|
if(e.key==='ArrowRight'||e.key===' '){go(i+1);e.preventDefault()}
|
||||||
|
if(e.key==='ArrowLeft'){go(i-1);e.preventDefault()}
|
||||||
|
});
|
||||||
|
const m=/^#\/(\d+)/.exec(location.hash||'');
|
||||||
|
if(m)go(parseInt(m[1],10)-1);else go(0);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Architecture</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.arch{margin-top:20px;display:grid;grid-template-rows:auto auto auto;gap:22px}
|
||||||
|
.arch .tier{display:grid;grid-template-columns:120px 1fr;align-items:stretch;gap:22px}
|
||||||
|
.arch .tname{display:flex;align-items:center;justify-content:center;background:var(--surface-2);border-radius:var(--radius);padding:18px;font-weight:600;font-size:13px;color:var(--text-2);text-transform:uppercase;letter-spacing:.1em;text-align:center}
|
||||||
|
.arch .cells{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
|
||||||
|
.arch .cells.three{grid-template-columns:repeat(3,1fr)}
|
||||||
|
.arch .cell{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:16px;text-align:center;box-shadow:var(--shadow)}
|
||||||
|
.arch .cell .ic{font-size:24px}
|
||||||
|
.arch .cell h4{font-size:14px;margin:6px 0 2px}
|
||||||
|
.arch .cell p{font-size:11px;color:var(--text-3);margin:0}
|
||||||
|
.arch .tier.hl .cell{border-top:3px solid var(--accent)}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Architecture">
|
||||||
|
<p class="kicker">Architecture · 系统总览</p>
|
||||||
|
<h2 class="h2">一套三层栈</h2>
|
||||||
|
<div class="arch anim-stagger-list" data-anim-target>
|
||||||
|
<div class="tier"><div class="tname">UI Layer</div>
|
||||||
|
<div class="cells"><div class="cell"><div class="ic">🧱</div><h4>Layouts</h4><p>30 个单页</p></div>
|
||||||
|
<div class="cell"><div class="ic">🎨</div><h4>Themes</h4><p>24 tokens 主题</p></div>
|
||||||
|
<div class="cell"><div class="ic">✨</div><h4>Animations</h4><p>25 个命名动效</p></div>
|
||||||
|
<div class="cell"><div class="ic">⌨️</div><h4>Runtime</h4><p>键盘导航</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tier hl"><div class="tname">Core · tokens</div>
|
||||||
|
<div class="cells three"><div class="cell"><div class="ic">🎯</div><h4>base.css</h4><p>排版 + 网格</p></div>
|
||||||
|
<div class="cell"><div class="ic">🔤</div><h4>fonts.css</h4><p>中英字体</p></div>
|
||||||
|
<div class="cell"><div class="ic">🪞</div><h4>:root vars</h4><p>语义颜色</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tier"><div class="tname">Tooling</div>
|
||||||
|
<div class="cells three"><div class="cell"><div class="ic">🧪</div><h4>render.sh</h4><p>headless Chrome</p></div>
|
||||||
|
<div class="cell"><div class="ic">🆕</div><h4>new-deck.sh</h4><p>脚手架</p></div>
|
||||||
|
<div class="cell"><div class="ic">📦</div><h4>AgentSkill</h4><p>Claude 接入点</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Big Quote</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/editorial-serif.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active center tc" data-title="Quote">
|
||||||
|
<div style="max-width:1040px">
|
||||||
|
<div class="serif" style="font-size:140px;line-height:.9;color:var(--accent);opacity:.6">"</div>
|
||||||
|
<blockquote class="serif anim-fade-up" data-anim="fade-up" style="font-size:56px;line-height:1.25;margin:-40px 0 24px;font-style:italic;font-weight:600">
|
||||||
|
好的设计不是把东西加得更多,<br>而是把一切不需要的东西拿掉。
|
||||||
|
</blockquote>
|
||||||
|
<p class="dim" style="font-size:20px;letter-spacing:.08em">— Dieter Rams</p>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Bullets</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Why">
|
||||||
|
<p class="kicker">Why · 为什么</p>
|
||||||
|
<h2 class="h2">好的演讲系统,帮你做三件事</h2>
|
||||||
|
<p class="lede mb-l">不是做不出漂亮的 slide,是每次都要重新做。</p>
|
||||||
|
<ul class="grid g1 anim-stagger-list" style="list-style:none;padding:0;margin:0;gap:14px" data-anim-target>
|
||||||
|
<li class="card card-accent"><h4>① 统一设计语言</h4><p class="dim">所有页共用同一套 tokens,字号、颜色、阴影不会跑偏。</p></li>
|
||||||
|
<li class="card card-accent"><h4>② 降低复用成本</h4><p class="dim">下一次讲同类话题,复制 deck、换数据、换主题即可。</p></li>
|
||||||
|
<li class="card card-accent"><h4>③ 可切换,可演示</h4><p class="dim">按 T 即可循环切主题、按 A 可切动效,汇报现场加分。</p></li>
|
||||||
|
</ul>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Chart · Bar</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"></script>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Bar chart">
|
||||||
|
<p class="kicker">Chart · 柱状图</p>
|
||||||
|
<h2 class="h2">季度 MRR 趋势</h2>
|
||||||
|
<div class="card mt-l" style="height:520px;padding:28px"><canvas id="c"></canvas></div>
|
||||||
|
<script>
|
||||||
|
addEventListener('DOMContentLoaded',()=>{
|
||||||
|
const css=getComputedStyle(document.documentElement);
|
||||||
|
const accent=css.getPropertyValue('--accent').trim();
|
||||||
|
const text2=css.getPropertyValue('--text-2').trim();
|
||||||
|
const border=css.getPropertyValue('--border').trim();
|
||||||
|
new Chart(document.getElementById('c'),{type:'bar',
|
||||||
|
data:{labels:['Q1','Q2','Q3','Q4','Q1 +1','Q2 +1','Q3 +1','Q4 +1'],
|
||||||
|
datasets:[{label:'MRR (K)',data:[42,58,73,96,124,158,204,261],
|
||||||
|
backgroundColor:accent,borderRadius:8,barThickness:36}]},
|
||||||
|
options:{plugins:{legend:{labels:{color:text2}}},
|
||||||
|
scales:{x:{ticks:{color:text2},grid:{color:border}},
|
||||||
|
y:{ticks:{color:text2},grid:{color:border}}}}});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Chart · Line</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"></script>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Line chart">
|
||||||
|
<p class="kicker">Chart · 折线图</p>
|
||||||
|
<h2 class="h2">日活与留存并排看</h2>
|
||||||
|
<div class="card mt-l" style="height:520px;padding:28px"><canvas id="c"></canvas></div>
|
||||||
|
<script>
|
||||||
|
addEventListener('DOMContentLoaded',()=>{
|
||||||
|
const css=getComputedStyle(document.documentElement);
|
||||||
|
const accent=css.getPropertyValue('--accent').trim();
|
||||||
|
const acc2=css.getPropertyValue('--accent-2').trim();
|
||||||
|
const text2=css.getPropertyValue('--text-2').trim();
|
||||||
|
const border=css.getPropertyValue('--border').trim();
|
||||||
|
new Chart(document.getElementById('c'),{type:'line',
|
||||||
|
data:{labels:['W1','W2','W3','W4','W5','W6','W7','W8','W9','W10','W11','W12'],
|
||||||
|
datasets:[
|
||||||
|
{label:'DAU (K)',data:[12,14,15,19,24,28,33,38,45,51,58,66],
|
||||||
|
borderColor:accent,backgroundColor:accent+'22',fill:true,tension:.4,borderWidth:3,pointRadius:4},
|
||||||
|
{label:'Retention %',data:[38,40,42,45,48,50,53,55,58,60,62,64],
|
||||||
|
borderColor:acc2,backgroundColor:acc2+'22',fill:true,tension:.4,borderWidth:3,pointRadius:4}
|
||||||
|
]},
|
||||||
|
options:{plugins:{legend:{labels:{color:text2}}},
|
||||||
|
scales:{x:{ticks:{color:text2},grid:{color:border}},
|
||||||
|
y:{ticks:{color:text2},grid:{color:border}}}}});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Chart · Pie</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"></script>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Pie chart">
|
||||||
|
<p class="kicker">Chart · 环形图</p>
|
||||||
|
<h2 class="h2">时间都花在了哪里</h2>
|
||||||
|
<div class="grid g2 mt-l" style="align-items:center">
|
||||||
|
<div class="card" style="height:460px;padding:28px"><canvas id="c"></canvas></div>
|
||||||
|
<div class="card">
|
||||||
|
<h4>Takeaways</h4>
|
||||||
|
<p class="dim">超过一半的时间都在写内容,动效只占 5%。说明值得把动效做成可复用模板。</p>
|
||||||
|
<ul class="mt-m dim">
|
||||||
|
<li>✍️ 写内容 55%</li><li>🧩 挑版式 18%</li><li>🎨 调样式 14%</li>
|
||||||
|
<li>📸 出图 8%</li><li>✨ 动效 5%</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
addEventListener('DOMContentLoaded',()=>{
|
||||||
|
const css=getComputedStyle(document.documentElement);
|
||||||
|
const colors=['--accent','--accent-2','--accent-3','--good','--warn'].map(k=>css.getPropertyValue(k).trim());
|
||||||
|
const text2=css.getPropertyValue('--text-2').trim();
|
||||||
|
new Chart(document.getElementById('c'),{type:'doughnut',
|
||||||
|
data:{labels:['写内容','挑版式','调样式','出图','动效'],
|
||||||
|
datasets:[{data:[55,18,14,8,5],backgroundColor:colors,borderWidth:0}]},
|
||||||
|
options:{cutout:'62%',plugins:{legend:{position:'right',labels:{color:text2}}}}});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Chart · Radar</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"></script>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Radar chart">
|
||||||
|
<p class="kicker">Chart · 雷达图</p>
|
||||||
|
<h2 class="h2">把 html-ppt 和竞品放一张图</h2>
|
||||||
|
<div class="card mt-l" style="height:520px;padding:28px"><canvas id="c"></canvas></div>
|
||||||
|
<script>
|
||||||
|
addEventListener('DOMContentLoaded',()=>{
|
||||||
|
const css=getComputedStyle(document.documentElement);
|
||||||
|
const a1=css.getPropertyValue('--accent').trim();
|
||||||
|
const a2=css.getPropertyValue('--accent-2').trim();
|
||||||
|
const text2=css.getPropertyValue('--text-2').trim();
|
||||||
|
new Chart(document.getElementById('c'),{type:'radar',
|
||||||
|
data:{labels:['上手','美观','自定义','性能','导出','生态'],
|
||||||
|
datasets:[
|
||||||
|
{label:'html-ppt',data:[9,9,10,10,9,6],borderColor:a1,backgroundColor:a1+'33',borderWidth:3,pointRadius:5},
|
||||||
|
{label:'reveal.js',data:[8,7,9,8,8,10],borderColor:a2,backgroundColor:a2+'22',borderWidth:3,pointRadius:5}]},
|
||||||
|
options:{plugins:{legend:{labels:{color:text2}}},
|
||||||
|
scales:{r:{suggestedMin:0,suggestedMax:10,ticks:{color:text2,backdropColor:'transparent'},
|
||||||
|
pointLabels:{color:text2,font:{size:14}},grid:{color:'rgba(0,0,0,.08)'},angleLines:{color:'rgba(0,0,0,.08)'}}}}});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Code</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/tokyo-night.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@11.10.0/styles/tokyo-night-dark.min.css">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/highlight.js@11.10.0/lib/core.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/highlight.js@11.10.0/lib/languages/javascript.min.js"></script>
|
||||||
|
<script>addEventListener('DOMContentLoaded',()=>{hljs.registerLanguage('javascript',window.hljsLangJavascript||window.hljs.getLanguage('javascript'));document.querySelectorAll('pre code').forEach(el=>hljs.highlightElement(el))})</script>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Code">
|
||||||
|
<p class="kicker">Snippet · 运行时核心</p>
|
||||||
|
<h2 class="h2">按一下键盘,幻灯片就跑起来了</h2>
|
||||||
|
<pre class="card mt-m" style="padding:24px"><code class="language-javascript">// runtime.js — keyboard-driven deck
|
||||||
|
function go(n) {
|
||||||
|
n = Math.max(0, Math.min(total - 1, n));
|
||||||
|
slides.forEach((s, i) => {
|
||||||
|
s.classList.toggle('is-active', i === n);
|
||||||
|
});
|
||||||
|
idx = n;
|
||||||
|
barFill.style.width = ((n + 1) / total * 100) + '%';
|
||||||
|
history.replaceState(null, '', '#/' + (n + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('keydown', (e) => {
|
||||||
|
if (e.key === 'ArrowRight' || e.key === ' ') go(idx + 1);
|
||||||
|
if (e.key === 'ArrowLeft') go(idx - 1);
|
||||||
|
if (e.key === 't') cycleTheme();
|
||||||
|
});</code></pre>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Comparison</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.vs{display:grid;grid-template-columns:1fr 90px 1fr;gap:28px;align-items:stretch;margin-top:30px}
|
||||||
|
.vs .side{padding:30px}
|
||||||
|
.vs .mid{font-size:56px;font-weight:800;color:var(--text-3);display:flex;align-items:center;justify-content:center}
|
||||||
|
.vs .bad-side{border-top:3px solid var(--bad)}
|
||||||
|
.vs .good-side{border-top:3px solid var(--good)}
|
||||||
|
.vs h3{font-size:24px}
|
||||||
|
.vs ul{padding-left:20px;font-size:15px;line-height:1.8;color:var(--text-2)}
|
||||||
|
.vs li::marker{color:var(--bad)}
|
||||||
|
.vs .good-side li::marker{color:var(--good)}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Comparison">
|
||||||
|
<p class="kicker">Before vs After · 对比</p>
|
||||||
|
<h2 class="h2">从「每次重做」到「一键起稿」</h2>
|
||||||
|
<div class="vs">
|
||||||
|
<div class="card bad-side side anim-fade-left" data-anim="fade-left">
|
||||||
|
<h3>📉 过去</h3>
|
||||||
|
<ul>
|
||||||
|
<li>每次都要重新做封面、目录、结语</li>
|
||||||
|
<li>颜色、字号跨 slide 不一致</li>
|
||||||
|
<li>想换主题?手动改每一页</li>
|
||||||
|
<li>动效全靠 transition 硬写</li>
|
||||||
|
<li>截图导出还要一张一张截</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="mid">→</div>
|
||||||
|
<div class="card good-side side anim-fade-right" data-anim="fade-right">
|
||||||
|
<h3>📈 现在</h3>
|
||||||
|
<ul>
|
||||||
|
<li>复制模板、换数据、完事</li>
|
||||||
|
<li>所有页共享 tokens</li>
|
||||||
|
<li>按 <b>T</b> 循环切主题</li>
|
||||||
|
<li>25 个命名动效直接挑</li>
|
||||||
|
<li>一条 render.sh 全部出图</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN" data-theme="minimal-white">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"><title>Cover — html-ppt</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
</head>
|
||||||
|
<body class="single">
|
||||||
|
<div class="deck" data-themes="minimal-white,aurora,catppuccin-mocha,tokyo-night,xiaohongshu-white,neo-brutalism" data-theme-base="../../assets/themes/">
|
||||||
|
<section class="slide is-active" data-title="Cover">
|
||||||
|
<div class="deck-header"><span class="eyebrow">Keynote · 2026</span><span class="eyebrow">html-ppt</span></div>
|
||||||
|
<div class="anim-stagger-list">
|
||||||
|
<p class="kicker">Tech Sharing · 纯干货</p>
|
||||||
|
<h1 class="h1 anim-fade-up" data-anim="fade-up">
|
||||||
|
设计一套<span class="gradient-text">属于你</span>的<br>HTML 演讲系统
|
||||||
|
</h1>
|
||||||
|
<p class="lede">从主题、版式到动效,全部由模板驱动。一行命令即可开场。</p>
|
||||||
|
<div class="row wrap mt-l">
|
||||||
|
<span class="pill pill-accent">24 themes</span>
|
||||||
|
<span class="pill">30 layouts</span>
|
||||||
|
<span class="pill">25 animations</span>
|
||||||
|
<span class="pill">零构建</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="deck-footer"><span class="dim2">lewis · 2026-04-15</span><span class="slide-number" data-current="1" data-total="1"></span></div>
|
||||||
|
<div class="notes">封面页口播:大家好,今天给大家带来一套开箱即用的 HTML 演讲系统。</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>CTA</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/aurora.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.cta .btn{display:inline-flex;align-items:center;gap:10px;padding:20px 32px;border-radius:999px;background:var(--accent);color:#0b1024;font-weight:700;font-size:20px;box-shadow:var(--shadow-lg);text-decoration:none;border:none;cursor:pointer}
|
||||||
|
.cta .btn.outline{background:transparent;color:var(--text-1);border:1.5px solid var(--border-strong)}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active center tc cta" data-title="CTA">
|
||||||
|
<div style="max-width:900px">
|
||||||
|
<p class="kicker">Call to action</p>
|
||||||
|
<h1 class="h1 anim-rise-in" data-anim="rise-in" style="font-size:96px">
|
||||||
|
<span class="gradient-text">动手做你的</span><br>第一份 html-ppt
|
||||||
|
</h1>
|
||||||
|
<p class="lede" style="margin:16px auto 30px">复制模板、换上你的内容、按 <b>T</b> 挑一个最对味的主题,讲完还能一键导出 PNG。</p>
|
||||||
|
<div class="row" style="justify-content:center">
|
||||||
|
<a class="btn" href="#">🚀 ./new-deck.sh my-talk</a>
|
||||||
|
<a class="btn outline" href="#">查看 SKILL.md</a>
|
||||||
|
</div>
|
||||||
|
<p class="dim mt-l" style="font-size:14px">键盘: ← → 翻页 · T 主题 · A 动效 · F 全屏 · O 概览 · S 备注</p>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Diff</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.diff{font-family:var(--font-mono);font-size:14px;line-height:1.6;border-radius:var(--radius);overflow:hidden;border:1px solid var(--border)}
|
||||||
|
.diff .ln{display:block;padding:2px 16px;white-space:pre}
|
||||||
|
.diff .add{background:rgba(26,175,108,.12);color:var(--good)}
|
||||||
|
.diff .del{background:rgba(224,68,90,.12);color:var(--bad)}
|
||||||
|
.diff .ctx{color:var(--text-2)}
|
||||||
|
.diff .hd{background:var(--surface-2);color:var(--text-3);padding:8px 16px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;border-bottom:1px solid var(--border)}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Diff">
|
||||||
|
<p class="kicker">Before / After</p>
|
||||||
|
<h2 class="h2">一次迁移到 tokens 后</h2>
|
||||||
|
<div class="card diff mt-l" style="padding:0">
|
||||||
|
<div class="hd">assets/components/card.css</div>
|
||||||
|
<span class="ln ctx">.card {</span>
|
||||||
|
<span class="ln del">- background: #ffffff;</span>
|
||||||
|
<span class="ln del">- color: #0c0d10;</span>
|
||||||
|
<span class="ln del">- border-radius: 18px;</span>
|
||||||
|
<span class="ln del">- box-shadow: 0 10px 30px rgba(18,24,40,.08);</span>
|
||||||
|
<span class="ln add">+ background: var(--surface);</span>
|
||||||
|
<span class="ln add">+ color: var(--text-1);</span>
|
||||||
|
<span class="ln add">+ border-radius: var(--radius);</span>
|
||||||
|
<span class="ln add">+ box-shadow: var(--shadow);</span>
|
||||||
|
<span class="ln ctx">}</span>
|
||||||
|
</div>
|
||||||
|
<p class="dim mt-m">24 个主题从此只需改 variables——其他 0 改动。</p>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Flow Diagram</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.flow{display:flex;align-items:center;gap:16px;margin-top:40px;max-width:1200px}
|
||||||
|
.flow .node{flex:1;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:22px;text-align:center;box-shadow:var(--shadow);position:relative}
|
||||||
|
.flow .node .ic{font-size:32px;margin-bottom:6px}
|
||||||
|
.flow .node h4{font-size:16px}
|
||||||
|
.flow .node p{font-size:12px;color:var(--text-3);margin:0}
|
||||||
|
.flow .arr{color:var(--text-3);font-size:28px;flex-shrink:0}
|
||||||
|
.flow .node.hl{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 18%,transparent),var(--shadow)}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Flow">
|
||||||
|
<p class="kicker">Pipeline · 渲染管线</p>
|
||||||
|
<h2 class="h2">从 Markdown 到 PNG,共 5 步</h2>
|
||||||
|
<div class="flow anim-stagger-list" data-anim-target>
|
||||||
|
<div class="node"><div class="ic">📝</div><h4>Markdown</h4><p>你的内容源</p></div>
|
||||||
|
<div class="arr">→</div>
|
||||||
|
<div class="node"><div class="ic">🧩</div><h4>Layouts</h4><p>选择页型</p></div>
|
||||||
|
<div class="arr">→</div>
|
||||||
|
<div class="node hl"><div class="ic">🎨</div><h4>Theme</h4><p>换装</p></div>
|
||||||
|
<div class="arr">→</div>
|
||||||
|
<div class="node"><div class="ic">🌐</div><h4>HTML</h4><p>运行时接管</p></div>
|
||||||
|
<div class="arr">→</div>
|
||||||
|
<div class="node"><div class="ic">📸</div><h4>PNG</h4><p>headless Chrome</p></div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Gantt</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.gantt{margin-top:24px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:24px}
|
||||||
|
.gantt .hd{display:grid;grid-template-columns:200px repeat(12,1fr);gap:4px;font-size:12px;color:var(--text-3);text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px;padding-bottom:10px;border-bottom:1px solid var(--border)}
|
||||||
|
.gantt .row{display:grid;grid-template-columns:200px repeat(12,1fr);gap:4px;align-items:center;height:40px}
|
||||||
|
.gantt .lbl{font-size:14px;font-weight:500}
|
||||||
|
.gantt .cells{grid-column:2/-1;position:relative;height:28px;background:linear-gradient(90deg,var(--surface-2) 1px,transparent 1px) 0 0/calc(100%/12) 100%}
|
||||||
|
.gantt .bar{position:absolute;top:4px;height:20px;border-radius:6px;background:var(--grad);display:flex;align-items:center;padding:0 10px;font-size:11px;color:#fff;font-weight:600;box-shadow:var(--shadow)}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Gantt">
|
||||||
|
<p class="kicker">Plan · Q2 甘特图</p>
|
||||||
|
<h2 class="h2">四个月,五条线并行</h2>
|
||||||
|
<div class="gantt">
|
||||||
|
<div class="hd"><div>任务</div><div>W1</div><div>W2</div><div>W3</div><div>W4</div><div>W5</div><div>W6</div><div>W7</div><div>W8</div><div>W9</div><div>W10</div><div>W11</div><div>W12</div></div>
|
||||||
|
<div class="row"><div class="lbl">主题系统 (tokens)</div><div class="cells"><div class="bar" style="left:0;width:25%">tokens + 24 themes</div></div></div>
|
||||||
|
<div class="row"><div class="lbl">layouts 目录</div><div class="cells"><div class="bar" style="left:17%;width:33%">30 个单页模板</div></div></div>
|
||||||
|
<div class="row"><div class="lbl">动画系统</div><div class="cells"><div class="bar" style="left:42%;width:25%">25 个命名动效</div></div></div>
|
||||||
|
<div class="row"><div class="lbl">渲染 / CI</div><div class="cells"><div class="bar" style="left:58%;width:25%">render.sh</div></div></div>
|
||||||
|
<div class="row"><div class="lbl">发布 & 文档</div><div class="cells"><div class="bar" style="left:75%;width:25%">v1.0</div></div></div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Image Grid</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.gg{display:grid;grid-template-columns:repeat(4,1fr);grid-auto-rows:180px;gap:14px;margin-top:24px}
|
||||||
|
.gg .cell{border-radius:var(--radius);overflow:hidden;position:relative;box-shadow:var(--shadow)}
|
||||||
|
.gg .cell span{position:absolute;inset:auto 0 0 0;padding:12px 14px;color:#fff;font-size:13px;font-weight:500;background:linear-gradient(transparent,rgba(0,0,0,.55))}
|
||||||
|
.gg .c1{background:linear-gradient(135deg,#3b6cff,#7a5cff);grid-column:span 2;grid-row:span 2}
|
||||||
|
.gg .c2{background:linear-gradient(135deg,#ff7a90,#ff2742)}
|
||||||
|
.gg .c3{background:linear-gradient(135deg,#5ef2c6,#7aa2ff)}
|
||||||
|
.gg .c4{background:linear-gradient(135deg,#ffd27a,#f2a341)}
|
||||||
|
.gg .c5{background:linear-gradient(135deg,#c984ff,#ff5c8a)}
|
||||||
|
.gg .c6{background:linear-gradient(135deg,#0e1530,#24283b)}
|
||||||
|
.gg .c7{background:linear-gradient(135deg,#88c0d0,#5ef2c6);grid-column:span 2}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Image Grid">
|
||||||
|
<p class="kicker">Gallery · 作品集</p>
|
||||||
|
<h2 class="h2">一次 bento grid,六张要点图</h2>
|
||||||
|
<div class="gg anim-stagger-list" data-anim-target>
|
||||||
|
<div class="cell c1"><span>主视觉 · Keynote 封面</span></div>
|
||||||
|
<div class="cell c2"><span>暖色 · Stat</span></div>
|
||||||
|
<div class="cell c3"><span>冷色 · Flow</span></div>
|
||||||
|
<div class="cell c4"><span>日落 · Code</span></div>
|
||||||
|
<div class="cell c5"><span>渐变 · Quote</span></div>
|
||||||
|
<div class="cell c6"><span>暗色 · Terminal</span></div>
|
||||||
|
<div class="cell c7"><span>极光 · CTA</span></div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Image Hero</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.hero{position:relative;height:calc(100vh - 144px);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-lg)}
|
||||||
|
.hero .bg{position:absolute;inset:0;background:
|
||||||
|
radial-gradient(80% 60% at 30% 40%,#ffb38a,transparent 70%),
|
||||||
|
radial-gradient(70% 50% at 75% 60%,#c084fc,transparent 70%),
|
||||||
|
linear-gradient(135deg,#0b1024,#1a2238)}
|
||||||
|
.hero .bg.kb{animation:kf-kenburns 12s ease-in-out infinite alternate}
|
||||||
|
.hero .overlay{position:absolute;inset:0;background:linear-gradient(180deg,transparent 40%,rgba(10,12,20,.65));}
|
||||||
|
.hero .caption{position:absolute;bottom:48px;left:56px;right:56px;color:#fff;z-index:2}
|
||||||
|
.hero h1{font-size:72px;line-height:1;font-weight:800;letter-spacing:-.03em;margin:0}
|
||||||
|
.hero p{font-size:20px;opacity:.85;margin:14px 0 0;max-width:60ch}
|
||||||
|
.hero .pill{background:rgba(255,255,255,.12);color:#fff;border:1px solid rgba(255,255,255,.2)}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Image Hero" style="padding:56px">
|
||||||
|
<div class="hero">
|
||||||
|
<div class="bg kb"></div>
|
||||||
|
<div class="overlay"></div>
|
||||||
|
<div class="caption">
|
||||||
|
<span class="pill">Cover · 04</span>
|
||||||
|
<h1 class="mt-s anim-rise-in" data-anim="rise-in">像杂志一样的<br>封面画面感</h1>
|
||||||
|
<p>Ken Burns 缓慢推拉 + 径向渐变 + 中灰叠加。无须真实图片,也能做出高级感。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>KPI Grid</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="KPIs">
|
||||||
|
<p class="kicker">Metrics · 关键数字</p>
|
||||||
|
<h2 class="h2">这一季度,我们做到了什么</h2>
|
||||||
|
<div class="grid g4 mt-l anim-stagger-list" data-anim-target>
|
||||||
|
<div class="card"><p class="eyebrow">Revenue</p><div style="font-size:56px;font-weight:800"><span class="counter" data-to="1248">0</span>K</div><p class="dim" style="color:var(--good)">↑ 38% YoY</p></div>
|
||||||
|
<div class="card"><p class="eyebrow">Active users</p><div style="font-size:56px;font-weight:800"><span class="counter" data-to="82">0</span>K</div><p class="dim" style="color:var(--good)">↑ 12% QoQ</p></div>
|
||||||
|
<div class="card"><p class="eyebrow">Retention</p><div style="font-size:56px;font-weight:800"><span class="counter" data-to="74">0</span>%</div><p class="dim" style="color:var(--good)">↑ 3 pts</p></div>
|
||||||
|
<div class="card"><p class="eyebrow">NPS</p><div style="font-size:56px;font-weight:800"><span class="counter" data-to="61">0</span></div><p class="dim" style="color:var(--warn)">→ 持平</p></div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Mindmap</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.mm{position:relative;margin:30px auto 0;max-width:1200px;height:520px}
|
||||||
|
.mm .n{position:absolute;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:12px 18px;box-shadow:var(--shadow);font-weight:600}
|
||||||
|
.mm .root{top:calc(50% - 34px);left:calc(50% - 100px);width:200px;padding:22px;background:var(--accent);color:#fff;border:none;text-align:center;font-size:20px;border-radius:24px}
|
||||||
|
.mm .n.sm{font-size:13px}
|
||||||
|
.mm svg{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
|
||||||
|
.mm svg path{stroke:var(--border-strong);stroke-width:1.5;fill:none}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Mindmap">
|
||||||
|
<p class="kicker">Concept map · 心智图</p>
|
||||||
|
<h2 class="h2">html-ppt 的知识地图</h2>
|
||||||
|
<div class="mm">
|
||||||
|
<svg class="anim-path-draw" viewBox="0 0 1200 520" preserveAspectRatio="none">
|
||||||
|
<path d="M600,260 C400,140 280,100 160,90"/>
|
||||||
|
<path d="M600,260 C400,380 280,420 160,430"/>
|
||||||
|
<path d="M600,260 C800,140 920,100 1040,90"/>
|
||||||
|
<path d="M600,260 C800,380 920,420 1040,430"/>
|
||||||
|
<path d="M600,260 C600,140 600,100 600,60"/>
|
||||||
|
<path d="M600,260 C600,380 600,420 600,460"/>
|
||||||
|
</svg>
|
||||||
|
<div class="n root">html-ppt</div>
|
||||||
|
<div class="n" style="top:60px;left:40px">Themes</div>
|
||||||
|
<div class="n sm" style="top:410px;left:40px">Layouts</div>
|
||||||
|
<div class="n sm" style="top:60px;right:40px">Animations</div>
|
||||||
|
<div class="n sm" style="top:410px;right:40px">Runtime</div>
|
||||||
|
<div class="n sm" style="top:30px;left:calc(50% - 50px)">Tokens</div>
|
||||||
|
<div class="n sm" style="top:450px;left:calc(50% - 60px)">Render.sh</div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Process Steps</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:22px;margin-top:24px}
|
||||||
|
.step{position:relative;padding:24px 26px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);box-shadow:var(--shadow)}
|
||||||
|
.step .num{position:absolute;top:-24px;left:22px;width:48px;height:48px;border-radius:50%;background:var(--accent);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:20px;box-shadow:var(--shadow)}
|
||||||
|
.step h4{margin:18px 0 8px;font-size:17px}
|
||||||
|
.step p{font-size:13px;color:var(--text-2);line-height:1.6}
|
||||||
|
.step .tag{display:inline-block;margin-top:10px;font-size:11px;padding:3px 10px;border-radius:999px;background:var(--surface-2);color:var(--text-3)}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Process">
|
||||||
|
<p class="kicker">How-to · 四步做一个 deck</p>
|
||||||
|
<h2 class="h2">从零到一,只需要十分钟</h2>
|
||||||
|
<div class="steps anim-stagger-list" data-anim-target>
|
||||||
|
<div class="step"><div class="num">1</div><h4>起稿</h4><p>运行 <code>new-deck.sh</code> 创建脚手架,默认 6 页。</p><span class="tag">~30s</span></div>
|
||||||
|
<div class="step"><div class="num">2</div><h4>选版式</h4><p>从 <code>templates/single-page/</code> 里复制你需要的页型。</p><span class="tag">~2min</span></div>
|
||||||
|
<div class="step"><div class="num">3</div><h4>写内容</h4><p>替换 demo 数据,保留结构。</p><span class="tag">~6min</span></div>
|
||||||
|
<div class="step"><div class="num">4</div><h4>换主题</h4><p>按 <b>T</b> 循环看 24 个主题,挑一个定稿。</p><span class="tag">~1min</span></div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Pros / Cons</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.pc{display:grid;grid-template-columns:1fr 1fr;gap:28px;margin-top:30px}
|
||||||
|
.pc .card h3{display:flex;align-items:center;gap:10px}
|
||||||
|
.pc .card h3 .b{display:inline-flex;width:36px;height:36px;border-radius:10px;align-items:center;justify-content:center;font-size:20px}
|
||||||
|
.pc .pro h3 .b{background:color-mix(in srgb,var(--good) 18%,transparent);color:var(--good)}
|
||||||
|
.pc .con h3 .b{background:color-mix(in srgb,var(--bad) 18%,transparent);color:var(--bad)}
|
||||||
|
.pc ul{padding-left:22px;line-height:1.8;color:var(--text-2)}
|
||||||
|
.pc .pro{border-top:3px solid var(--good)}
|
||||||
|
.pc .con{border-top:3px solid var(--bad)}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Pros Cons">
|
||||||
|
<p class="kicker">Trade-offs · 诚实的取舍</p>
|
||||||
|
<h2 class="h2">纯 HTML 演讲:好在哪里,痛在哪里</h2>
|
||||||
|
<div class="pc">
|
||||||
|
<div class="card pro anim-fade-up" data-anim="fade-up"><h3><span class="b">✓</span> 好处</h3>
|
||||||
|
<ul><li>零构建:一个文件就能跑</li><li>可 diff:Git 友好,好 review</li><li>可编程:动效自由定制</li><li>可分发:URL / PDF / PNG 都行</li></ul>
|
||||||
|
</div>
|
||||||
|
<div class="card con anim-fade-up" data-anim="fade-up"><h3><span class="b">✗</span> 痛点</h3>
|
||||||
|
<ul><li>协作不像 Keynote 那样实时</li><li>非程序员上手稍陡</li><li>复杂动效仍需写 JS</li><li>部分字体在离线环境缺失</li></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Roadmap</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.rm{display:grid;grid-template-columns:repeat(4,1fr);gap:0;margin-top:28px;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
|
||||||
|
.rm .col{padding:20px 22px;border-right:1px solid var(--border);background:var(--surface);position:relative}
|
||||||
|
.rm .col:last-child{border-right:none}
|
||||||
|
.rm .col .tag{display:inline-block;padding:3px 12px;border-radius:999px;font-size:11px;background:var(--surface-2);color:var(--text-2);margin-bottom:10px}
|
||||||
|
.rm .col.now{background:color-mix(in srgb,var(--accent) 6%,var(--surface))}
|
||||||
|
.rm .col.now .tag{background:var(--accent);color:#fff}
|
||||||
|
.rm h4{font-size:15px;margin:8px 0 4px}
|
||||||
|
.rm ul{padding-left:18px;margin:8px 0 0;font-size:13px;color:var(--text-2)}
|
||||||
|
.rm li{margin-bottom:6px;line-height:1.5}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Roadmap">
|
||||||
|
<p class="kicker">Roadmap · 2026</p>
|
||||||
|
<h2 class="h2">接下来四个季度,我们会做什么</h2>
|
||||||
|
<div class="rm">
|
||||||
|
<div class="col now">
|
||||||
|
<span class="tag">NOW · Q2</span>
|
||||||
|
<h4>主题系统</h4>
|
||||||
|
<ul><li>24 个官方主题</li><li>tokens 语义文档</li><li>T 键循环切换</li></ul>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<span class="tag">NEXT · Q3</span>
|
||||||
|
<h4>导出</h4>
|
||||||
|
<ul><li>PNG 批量</li><li>PDF 打包</li><li>小红书 3:4 切片</li></ul>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<span class="tag">LATER · Q4</span>
|
||||||
|
<h4>交互</h4>
|
||||||
|
<ul><li>Presenter 模式</li><li>Notes 同屏</li><li>遥控器配对</li></ul>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<span class="tag">VISION</span>
|
||||||
|
<h4>AI 写稿</h4>
|
||||||
|
<ul><li>从 md 自动分页</li><li>智能选版式</li><li>智能选主题</li></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Section Divider</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active tc center" data-title="Section 02">
|
||||||
|
<div style="max-width:780px;margin:0 auto">
|
||||||
|
<p class="kicker anim-fade-down" data-anim="fade-down">Section · 02</p>
|
||||||
|
<h1 class="h1 anim-rise-in" data-anim="rise-in" style="font-size:112px">主题与 <span class="gradient-text">Tokens</span></h1>
|
||||||
|
<div class="divider-accent" style="margin:24px auto"></div>
|
||||||
|
<p class="lede" style="margin:0 auto">换主题 = 换一份 CSS 变量。其他一切保持不变。</p>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Stat Highlight</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active center tc" data-title="Stat">
|
||||||
|
<p class="kicker">Impact · 一个数字</p>
|
||||||
|
<div style="font-size:260px;line-height:1;font-weight:900;letter-spacing:-.05em">
|
||||||
|
<span class="counter gradient-text" data-to="92">0</span><span class="gradient-text">%</span>
|
||||||
|
</div>
|
||||||
|
<h3 class="mt-s">的准备时间被你省下</h3>
|
||||||
|
<p class="lede" style="margin:16px auto 0">在 10 个真实项目中,使用 html-ppt 的平均 deck 制作时间从 4 小时降到了 20 分钟。</p>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Table</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.t{width:100%;border-collapse:collapse;font-size:16px}
|
||||||
|
.t th,.t td{padding:14px 16px;text-align:left;border-bottom:1px solid var(--border)}
|
||||||
|
.t th{font-size:12px;text-transform:uppercase;letter-spacing:.1em;color:var(--text-3);font-weight:600}
|
||||||
|
.t tr:hover td{background:var(--surface-2)}
|
||||||
|
.t td.num{font-variant-numeric:tabular-nums;text-align:right}
|
||||||
|
.up{color:var(--good)}.dn{color:var(--bad)}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Table">
|
||||||
|
<p class="kicker">Comparison · 数据表</p>
|
||||||
|
<h2 class="h2">主流 HTML 演讲框架对比</h2>
|
||||||
|
<div class="card mt-l" style="padding:4px 12px">
|
||||||
|
<table class="t">
|
||||||
|
<thead><tr><th>框架</th><th>学习曲线</th><th>自定义</th><th class="num">体积</th><th class="num">GitHub ⭐</th><th>适合</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td><b>html-ppt</b></td><td>极低</td><td>★★★★★</td><td class="num">~80 KB</td><td class="num">—</td><td>快速出稿、换主题</td></tr>
|
||||||
|
<tr><td>reveal.js</td><td>低</td><td>★★★★</td><td class="num">~450 KB</td><td class="num">67k</td><td>长讲座、互动</td></tr>
|
||||||
|
<tr><td>Slidev</td><td>中</td><td>★★★★★</td><td class="num">需构建</td><td class="num">31k</td><td>开发者、技术分享</td></tr>
|
||||||
|
<tr><td>Marp</td><td>极低</td><td>★★</td><td class="num">~10 MB</td><td class="num">13k</td><td>Markdown 出稿</td></tr>
|
||||||
|
<tr><td>Impress.js</td><td>中</td><td>★★★</td><td class="num">~60 KB</td><td class="num">38k</td><td>3D 展示</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Terminal</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/terminal-green.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.term{font-family:var(--font-mono);font-size:16px;background:#020803;border:1px solid rgba(0,255,120,.3);border-radius:10px;padding:24px 28px;box-shadow:0 0 60px rgba(0,255,136,.08) inset}
|
||||||
|
.term .bar{display:flex;gap:6px;margin-bottom:16px}
|
||||||
|
.term .bar span{width:12px;height:12px;border-radius:50%;background:#222;border:1px solid rgba(0,255,136,.3)}
|
||||||
|
.term .p{color:var(--accent)}
|
||||||
|
.term .c{color:var(--text-1)}
|
||||||
|
.term .o{color:var(--text-2)}
|
||||||
|
.term .caret{display:inline-block;width:9px;height:18px;background:var(--accent);vertical-align:middle;animation:blink 1s step-end infinite}
|
||||||
|
@keyframes blink{50%{opacity:0}}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Terminal">
|
||||||
|
<p class="kicker">CLI · 一行命令起一个 deck</p>
|
||||||
|
<h2 class="h2" style="color:var(--text-1)">你需要的就是一个终端</h2>
|
||||||
|
<div class="term mt-l">
|
||||||
|
<div class="bar"><span></span><span></span><span></span></div>
|
||||||
|
<div><span class="p">$ </span><span class="c">./scripts/new-deck.sh graphify-talk</span></div>
|
||||||
|
<div class="o"> ✔ created decks/graphify-talk/index.html</div>
|
||||||
|
<div class="o"> ✔ linked theme → aurora</div>
|
||||||
|
<div class="o"> ✔ 12 slides scaffolded from templates/single-page/*</div>
|
||||||
|
<div style="margin-top:12px"><span class="p">$ </span><span class="c">open decks/graphify-talk/index.html</span></div>
|
||||||
|
<div class="o"> ↗ launched in Chrome</div>
|
||||||
|
<div style="margin-top:12px"><span class="p">$ </span><span class="c">./scripts/render.sh decks/graphify-talk/index.html</span></div>
|
||||||
|
<div class="o"> ✔ wrote graphify-talk.png (1920×1080)</div>
|
||||||
|
<div style="margin-top:12px"><span class="p">$ </span><span class="caret"></span></div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Thanks</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active center tc" data-title="Thanks">
|
||||||
|
<div>
|
||||||
|
<div class="anim-confetti-burst" style="display:inline-block;padding:40px"></div>
|
||||||
|
<h1 class="h1 anim-fade-up" data-anim="fade-up" style="font-size:180px;line-height:1"><span class="gradient-text">Thanks</span></h1>
|
||||||
|
<p class="lede" style="margin:18px auto 0">愿你每一次上台,都少一点紧张,多一点从容。</p>
|
||||||
|
<div class="row mt-l" style="justify-content:center;gap:32px">
|
||||||
|
<div class="dim"><b>lewis</b> · sudolewis@gmail.com</div>
|
||||||
|
<div class="dim">github.com/lewis/html-ppt</div>
|
||||||
|
<div class="dim">2026 · MIT</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Three Column</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Three column">
|
||||||
|
<p class="kicker">Pillars · 三根支柱</p>
|
||||||
|
<h2 class="h2">一个 html-ppt,三件装备</h2>
|
||||||
|
<div class="grid g3 mt-l anim-stagger-list" data-anim-target>
|
||||||
|
<div class="card"><div style="font-size:40px">🎨</div><h4 class="mt-s">Themes</h4><p class="dim">克制 · 编辑 · 霓虹 · 终端 …… 随场景换装。</p></div>
|
||||||
|
<div class="card"><div style="font-size:40px">🧱</div><h4 class="mt-s">Layouts</h4><p class="dim">30 种页型,从封面到结语一次给齐。</p></div>
|
||||||
|
<div class="card"><div style="font-size:40px">✨</div><h4 class="mt-s">Animations</h4><p class="dim">25 个命名动效,每一个都克制、每一个都上台。</p></div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Timeline</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.tl{position:relative;margin-top:40px}
|
||||||
|
.tl::before{content:"";position:absolute;left:0;right:0;top:48px;height:2px;background:var(--border)}
|
||||||
|
.tl .row{display:grid;grid-template-columns:repeat(5,1fr);gap:22px;align-items:start}
|
||||||
|
.tl .item{position:relative;padding-top:80px;text-align:center}
|
||||||
|
.tl .dot{position:absolute;top:36px;left:50%;transform:translateX(-50%);width:24px;height:24px;border-radius:50%;background:var(--accent);border:4px solid var(--bg);box-shadow:0 0 0 2px var(--accent)}
|
||||||
|
.tl .year{font-size:14px;color:var(--text-3);letter-spacing:.12em;text-transform:uppercase;position:absolute;top:0;left:0;right:0;font-weight:600}
|
||||||
|
.tl h4{font-size:18px}
|
||||||
|
.tl p{font-size:13px;color:var(--text-2)}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Timeline">
|
||||||
|
<p class="kicker">Roadmap · 时间线</p>
|
||||||
|
<h2 class="h2">html-ppt 是怎么长大的</h2>
|
||||||
|
<div class="tl">
|
||||||
|
<div class="row anim-stagger-list" data-anim-target>
|
||||||
|
<div class="item"><div class="year">2025 Q3</div><div class="dot"></div><h4>起源</h4><p>一套个人 reveal.js 模板</p></div>
|
||||||
|
<div class="item"><div class="year">2025 Q4</div><div class="dot"></div><h4>tokens 化</h4><p>把颜色全部收进 :root</p></div>
|
||||||
|
<div class="item"><div class="year">2026 Q1</div><div class="dot"></div><h4>Agent 接入</h4><p>开放为 AgentSkill</p></div>
|
||||||
|
<div class="item"><div class="year">2026 Q2</div><div class="dot"></div><h4>24 themes</h4><p>从克制到霓虹一应俱全</p></div>
|
||||||
|
<div class="item"><div class="year">2026 Q3</div><div class="dot"></div><h4>渲染管线</h4><p>headless Chrome PNG 出稿</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN" data-theme="minimal-white">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"><title>Table of Contents</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
</head>
|
||||||
|
<body class="single">
|
||||||
|
<div class="deck">
|
||||||
|
<section class="slide is-active" data-title="Contents">
|
||||||
|
<p class="eyebrow">Contents · 目录</p>
|
||||||
|
<h2 class="h2">今天的五件事</h2>
|
||||||
|
<div class="grid g2 mt-l anim-stagger-list" data-anim-target>
|
||||||
|
<div class="card"><div class="row"><div class="h3 dim2" style="width:56px">01</div><div><h4>为什么需要设计系统</h4><p class="dim">从模板到 token,减少重复。</p></div></div></div>
|
||||||
|
<div class="card"><div class="row"><div class="h3 dim2" style="width:56px">02</div><div><h4>主题与 tokens</h4><p class="dim">24 个可切换的主题,一键换装。</p></div></div></div>
|
||||||
|
<div class="card"><div class="row"><div class="h3 dim2" style="width:56px">03</div><div><h4>版式目录</h4><p class="dim">30 种单页类型,覆盖 95% 场景。</p></div></div></div>
|
||||||
|
<div class="card"><div class="row"><div class="h3 dim2" style="width:56px">04</div><div><h4>入场动效</h4><p class="dim">25 种命名动画,可挑可组合。</p></div></div></div>
|
||||||
|
<div class="card" style="grid-column:span 2"><div class="row"><div class="h3 dim2" style="width:56px">05</div><div><h4>现场演示 & 问答</h4><p class="dim">打开模板就能讲。</p></div></div></div>
|
||||||
|
</div>
|
||||||
|
<div class="deck-footer"><span class="dim2">html-ppt</span><span>目录</span></div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Checklist</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.todo{max-width:820px;margin-top:26px}
|
||||||
|
.todo li{list-style:none;display:flex;align-items:flex-start;gap:14px;padding:14px 18px;border-bottom:1px solid var(--border)}
|
||||||
|
.todo li .b{flex-shrink:0;width:22px;height:22px;border:2px solid var(--border-strong);border-radius:6px;display:flex;align-items:center;justify-content:center;margin-top:2px}
|
||||||
|
.todo li.done .b{background:var(--good);border-color:var(--good);color:#fff}
|
||||||
|
.todo li.done .b::after{content:"✓";font-weight:900}
|
||||||
|
.todo li.done .t{text-decoration:line-through;color:var(--text-3)}
|
||||||
|
.todo li .t{font-size:18px}
|
||||||
|
.todo li .tag{margin-left:auto;font-size:12px;color:var(--text-3)}
|
||||||
|
</style>
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Checklist">
|
||||||
|
<p class="kicker">Launch · 上线前检查清单</p>
|
||||||
|
<h2 class="h2">发版前必过的 8 件事</h2>
|
||||||
|
<ul class="todo anim-stagger-list" data-anim-target>
|
||||||
|
<li class="done"><span class="b"></span><span class="t">所有 slide 在 Chrome 打开无控制台报错</span><span class="tag">#sanity</span></li>
|
||||||
|
<li class="done"><span class="b"></span><span class="t">字体回退链路正确(Noto Sans SC)</span><span class="tag">#fonts</span></li>
|
||||||
|
<li class="done"><span class="b"></span><span class="t">24 个主题各选一页截图比对</span><span class="tag">#themes</span></li>
|
||||||
|
<li class="done"><span class="b"></span><span class="t">键盘导航全键通</span><span class="tag">#runtime</span></li>
|
||||||
|
<li><span class="b"></span><span class="t">PDF 打印不跨页裁切</span><span class="tag">#print</span></li>
|
||||||
|
<li><span class="b"></span><span class="t">render.sh 对每个 showcase 跑通</span><span class="tag">#ci</span></li>
|
||||||
|
<li><span class="b"></span><span class="t">references/*.md 通读一遍</span><span class="tag">#docs</span></li>
|
||||||
|
<li><span class="b"></span><span class="t">LICENSE / README 作者信息核对</span><span class="tag">#legal</span></li>
|
||||||
|
</ul>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN"><head><meta charset="utf-8"><title>Two Column</title>
|
||||||
|
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||||
|
</head><body class="single">
|
||||||
|
<div class="deck"><section class="slide is-active" data-title="Two column">
|
||||||
|
<p class="kicker">Pattern · 双栏</p>
|
||||||
|
<h2 class="h2">概念 <span class="dim2">⟷</span> 示例</h2>
|
||||||
|
<div class="grid g2 mt-l" style="align-items:start">
|
||||||
|
<div class="card anim-fade-left" data-anim="fade-left">
|
||||||
|
<h3>左栏 · 概念</h3>
|
||||||
|
<p class="dim">一个主题 = 一组 CSS 变量。把颜色、字体、圆角、阴影全部收到 <code>:root</code> 里。</p>
|
||||||
|
<ul class="mt-m">
|
||||||
|
<li>— tokens 定义语义,不写具体色值</li>
|
||||||
|
<li>— base.css 用 tokens 排版</li>
|
||||||
|
<li>— 每个主题只改变量</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="card anim-fade-right" data-anim="fade-right">
|
||||||
|
<h3>右栏 · 示例</h3>
|
||||||
|
<pre class="mono" style="font-size:13px;background:var(--surface-2);padding:14px;border-radius:var(--radius-sm);overflow:auto">
|
||||||
|
:root {
|
||||||
|
--bg: #fff;
|
||||||
|
--text-1: #0c0d10;
|
||||||
|
--accent: #3b6cff;
|
||||||
|
--radius: 18px;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
background: var(--bg);
|
||||||
|
color: var(--text-1);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section></div>
|
||||||
|
<script src="../../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN" data-theme="minimal-white">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"><title>Theme Showcase — html-ppt</title>
|
||||||
|
<link rel="stylesheet" href="../assets/fonts.css">
|
||||||
|
<link rel="stylesheet" href="../assets/base.css">
|
||||||
|
<link rel="stylesheet" id="theme-link" href="../assets/themes/minimal-white.css">
|
||||||
|
<link rel="stylesheet" href="../assets/animations/animations.css">
|
||||||
|
<style>
|
||||||
|
.swatch{display:flex;gap:10px;margin-top:14px}
|
||||||
|
.swatch div{width:44px;height:44px;border-radius:10px;border:1px solid var(--border)}
|
||||||
|
.tname{font-family:var(--font-mono);font-size:12px;color:var(--text-3);text-transform:uppercase;letter-spacing:.1em}
|
||||||
|
.theme-indicator{position:absolute;top:24px;right:40px;font-family:var(--font-mono);font-size:11px;color:var(--text-3);letter-spacing:.1em}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body data-themes="minimal-white,editorial-serif,soft-pastel,sharp-mono,arctic-cool,sunset-warm,catppuccin-latte,catppuccin-mocha,dracula,tokyo-night,nord,solarized-light,gruvbox-dark,rose-pine,neo-brutalism,glassmorphism,bauhaus,swiss-grid,terminal-green,xiaohongshu-white,rainbow-gradient,aurora,blueprint,memphis-pop" data-theme-base="../assets/themes/">
|
||||||
|
<div class="deck">
|
||||||
|
<!-- 24 slides, one per theme. Click through; also press T to cycle the theme-link. -->
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
/* build slides dynamically so we don't hand-write 24 copies */
|
||||||
|
(function(){
|
||||||
|
const themes = [
|
||||||
|
['minimal-white','极简白,克制高级','Inter'],
|
||||||
|
['editorial-serif','杂志风衬线,高级','Playfair'],
|
||||||
|
['soft-pastel','柔和马卡龙','Inter'],
|
||||||
|
['sharp-mono','锐利黑白高对比','Archivo Black'],
|
||||||
|
['arctic-cool','冷色调 蓝/青/石板灰','Inter'],
|
||||||
|
['sunset-warm','暖色调 橘/珊瑚/琥珀','Inter'],
|
||||||
|
['catppuccin-latte','catppuccin 浅','Inter'],
|
||||||
|
['catppuccin-mocha','catppuccin 深','Inter'],
|
||||||
|
['dracula','Dracula 经典暗紫','Inter'],
|
||||||
|
['tokyo-night','Tokyo Night 蓝夜','Inter'],
|
||||||
|
['nord','Nord 北欧清冷','Inter'],
|
||||||
|
['solarized-light','Solarized Light','Inter'],
|
||||||
|
['gruvbox-dark','Gruvbox 温暖复古','Inter'],
|
||||||
|
['rose-pine','Rose Pine 玫瑰松','Inter'],
|
||||||
|
['neo-brutalism','厚描边,硬阴影,明黄','Space Grotesk'],
|
||||||
|
['glassmorphism','毛玻璃质感','Inter'],
|
||||||
|
['bauhaus','几何+原色','Space Grotesk'],
|
||||||
|
['swiss-grid','瑞士网格,Helvetica','Helvetica'],
|
||||||
|
['terminal-green','绿屏终端','JetBrains Mono'],
|
||||||
|
['xiaohongshu-white','小红书白底高级感','Noto Serif SC'],
|
||||||
|
['rainbow-gradient','彩虹渐变点缀','Inter'],
|
||||||
|
['aurora','极光渐变','Inter'],
|
||||||
|
['blueprint','蓝图工程','JetBrains Mono'],
|
||||||
|
['memphis-pop','孟菲斯波普','Archivo Black']
|
||||||
|
];
|
||||||
|
const deck = document.querySelector('.deck');
|
||||||
|
themes.forEach((t,i)=>{
|
||||||
|
const s = document.createElement('section');
|
||||||
|
s.className = 'slide';
|
||||||
|
s.setAttribute('data-title', t[0]);
|
||||||
|
s.innerHTML = `
|
||||||
|
<span class="theme-indicator">${i+1}/${themes.length} · ${t[0]}</span>
|
||||||
|
<p class="kicker">Theme · ${String(i+1).padStart(2,'0')}</p>
|
||||||
|
<h1 class="h1 anim-fade-up" data-anim="fade-up">${t[0]}</h1>
|
||||||
|
<p class="lede">${t[1]} · ${t[2]}</p>
|
||||||
|
<div class="grid g3 mt-l anim-stagger-list" data-anim-target>
|
||||||
|
<div class="card"><h4>Card · 卡片</h4><p class="dim">背景 / 边框 / 阴影 全部走 tokens。</p>
|
||||||
|
<div class="swatch"><div style="background:var(--accent)"></div><div style="background:var(--accent-2)"></div><div style="background:var(--accent-3)"></div><div style="background:var(--text-1)"></div><div style="background:var(--surface-2)"></div></div>
|
||||||
|
</div>
|
||||||
|
<div class="card"><h4>KPI</h4><div style="font-size:48px;font-weight:800" class="gradient-text">2.4K</div><p class="dim">上周月活</p></div>
|
||||||
|
<div class="card"><h4>Code</h4><pre class="mono" style="font-size:11px;background:var(--surface-2);padding:10px;border-radius:8px;margin:6px 0 0">:root {
|
||||||
|
--accent: #3b6cff;
|
||||||
|
}</pre></div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-m" style="gap:10px;flex-wrap:wrap">
|
||||||
|
<span class="pill">#tokens</span>
|
||||||
|
<span class="pill pill-accent">primary</span>
|
||||||
|
<span class="pill">#radius</span>
|
||||||
|
<span class="pill">#shadow</span>
|
||||||
|
</div>
|
||||||
|
<div class="deck-footer"><span class="tname">theme</span><span class="slide-number" data-current="${i+1}" data-total="${themes.length}"></span></div>
|
||||||
|
<div class="notes">按 <b>T</b> 继续循环主题。这张 slide 的内容没有任何变化——变的只是 tokens。</div>
|
||||||
|
`;
|
||||||
|
deck.appendChild(s);
|
||||||
|
});
|
||||||
|
// activate matching theme for each slide load - we rely on T cycling + data-themes
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<script src="../assets/runtime.js"></script>
|
||||||
|
</body></html>
|
||||||
Loading…
Reference in New Issue