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 . Install One command, no build. Pure static HTML/CSS/JS with only CDN webfonts. No network on the target machine? Point the CLI at a local copy ( ), or just copy this folder into your agent's skills directory — for Claude Code. Decks render offline; only the webfonts fall back to the system stack. See README.md. What the skill gives you - 36 themes ( ) — minimal-whi…

branch inside\n# the protocol grep. A fragment-only reference (url(#arrow), href=\"#top\")\n# collapses to an empty string once the #… is stripped, and under ugrep —\n# which ships as `grep` on some machines — '^

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 . Install One command, no build. Pure static HTML/CSS/JS with only CDN webfonts. No network on the target machine? Point the CLI at a local copy ( ), or just copy this folder into your agent's skills directory — for Claude Code. Decks render offline; only the webfonts fall back to the system stack. See README.md. What the skill gives you - 36 themes ( ) — minimal-whi…

as one branch of an ERE\n# alternation does not reliably match those empty lines (measured: 4 of 5\n# survived). The empty string then resolves to the deck directory, which\n# exists, so it was silently counted as a verified reference.\nlist_refs() {\n grep -oE \"(href|src)=(\\\"[^\\\"]*\\\"|'[^']*')|url\\([^)]*\\)\" \"$1\" \\\n | sed -E 's/^(href|src)=//; s/^url\\(//; s/\\)$//' \\\n | tr -d \"\\\"'\" \\\n | sed -E 's/[?#].*$//' \\\n | grep -vE '^[a-zA-Z][a-zA-Z0-9+.-]*:|^//' \\\n | sed '/^[[:space:]]*$/d' \\\n | sort -u\n}\n\n# Self-check: every local reference must resolve to a real file. A broken path\n# here is exactly the bug this script used to ship (#19) — fail loudly.\nMISSING=0\nCHECKED=0\nwhile IFS= read -r ref; do\n CHECKED=$((CHECKED + 1))\n if [[ ! -e \"$(lexjoin \"$OUT_DIR\" \"$ref\")\" ]]; then\n echo \"error: unresolved reference: $ref\" >&2\n MISSING=1\n fi\ndone \u003c \u003c(list_refs \"$OUT_DIR/index.html\")\n[[ $MISSING -eq 0 ]] || exit 1\n\necho \"✔ created $OUT_DIR/index.html\"\necho \" template: $TEMPLATE\"\necho \" assets: $REL/assets/\"\necho \" refs: $CHECKED local reference(s) verified\"\necho \"\"\necho \"next steps:\"\necho \" open $OUT_DIR/index.html\"\necho \" # press T to cycle themes, ← → to navigate, O for overview\"\necho \"\"\necho \" # render to PNG:\"\necho \" $HERE/scripts/render.sh $OUT_DIR/index.html all\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":7058,"content_sha256":"e98985243ba73a89656670c4c8cb8bef2ae12b47516d72060a90980b77f1c0a7"},{"filename":"scripts/render.sh","content":"#!/usr/bin/env bash\n# html-ppt :: render.sh — headless Chrome screenshot(s)\n#\n# Usage:\n# render.sh \u003chtml-file> # one PNG, slide 1\n# render.sh \u003chtml-file> \u003cN> # N PNGs, slides 1..N, via #/k\n# render.sh \u003chtml-file> all # autodetect .slide count\n# render.sh \u003chtml-file> \u003cN> \u003cout-dir> # custom output dir\n#\n# Requires: Google Chrome at /Applications/Google Chrome.app (macOS).\n\nset -euo pipefail\n\nCHROME=\"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome\"\nif [[ ! -x \"$CHROME\" ]]; then\n echo \"error: Chrome not found at $CHROME\" >&2\n exit 1\nfi\n\nFILE=\"${1:-}\"\nif [[ -z \"$FILE\" ]]; then\n echo \"usage: render.sh \u003chtml> [N|all] [out-dir]\" >&2\n exit 1\nfi\nif [[ ! -f \"$FILE\" ]]; then\n echo \"error: $FILE not found\" >&2\n exit 1\nfi\n\nCOUNT=\"${2:-1}\"\nOUT=\"${3:-}\"\n\nABS=\"$(cd \"$(dirname \"$FILE\")\" && pwd)/$(basename \"$FILE\")\"\nSTEM=\"$(basename \"${FILE%.*}\")\"\n\n# Count \u003csection> elements whose class attribute carries \"slide\" as a whole\n# token. A plain `class=\"slide\"` match misses every slide with an extra class\n# (slide is-active, slide dark, slide t-violet …), and a loose \\bslide\\b would\n# also match class=\"slide-number\".\ncount_slides() {\n grep -Eco '\u003csection[^>]*class=\"([^\"]*[[:space:]])?slide([[:space:]][^\"]*)?\"' \"$1\" || true\n}\n\nif [[ \"$COUNT\" == \"all\" ]]; then\n COUNT=\"$(count_slides \"$FILE\")\"\n if [[ -z \"$COUNT\" || \"$COUNT\" -lt 1 ]]; then\n echo \"warning: no \u003csection class=\\\"slide\\\"> found in $FILE — rendering 1 page\" >&2\n COUNT=1\n fi\nfi\n\nif ! [[ \"$COUNT\" =~ ^[0-9]+$ ]] || [[ \"$COUNT\" -lt 1 ]]; then\n echo \"error: slide count must be a positive integer or 'all' (got: $COUNT)\" >&2\n exit 1\nfi\n\nif [[ -z \"$OUT\" && \"$COUNT\" -gt 1 ]]; then\n OUT=\"$(dirname \"$FILE\")/${STEM}-png\"\nfi\n\n# Chrome does not create the target directory; without this it exits 0 having\n# written nothing.\nif [[ -n \"$OUT\" ]]; then\n if [[ \"$OUT\" == *.png ]]; then\n mkdir -p \"$(dirname \"$OUT\")\"\n else\n mkdir -p \"$OUT\"\n fi\nfi\n\nrender_one() {\n local url=\"$1\" target=\"$2\"\n \"$CHROME\" \\\n --headless=new \\\n --disable-gpu \\\n --hide-scrollbars \\\n --no-sandbox \\\n --virtual-time-budget=4000 \\\n --window-size=1920,1080 \\\n --screenshot=\"$target\" \\\n \"$url\" >/dev/null 2>&1 || true\n # Chrome reports success even when it could not write the file, so the only\n # trustworthy signal is the file itself.\n if [[ ! -s \"$target\" ]]; then\n echo \" ✗ $target — not written\" >&2\n return 1\n fi\n echo \" ✔ $target\"\n}\n\nFAILED=0\n\nif [[ \"$COUNT\" == \"1\" ]]; then\n if [[ -z \"$OUT\" ]]; then\n OUT_FILE=\"$(dirname \"$FILE\")/${STEM}.png\"\n elif [[ \"$OUT\" == *.png ]]; then\n OUT_FILE=\"$OUT\"\n else\n OUT_FILE=\"$OUT/${STEM}.png\"\n fi\n render_one \"file://$ABS\" \"$OUT_FILE\" || FAILED=$((FAILED + 1))\nelse\n for i in $(seq 1 \"$COUNT\"); do\n render_one \"file://$ABS#/$i\" \"$OUT/${STEM}_$(printf '%02d' \"$i\").png\" \\\n || FAILED=$((FAILED + 1))\n done\nfi\n\nif [[ \"$FAILED\" -gt 0 ]]; then\n echo \"error: $FAILED of $COUNT slide(s) were not written from $FILE\" >&2\n exit 1\nfi\n\necho \"done: rendered $COUNT slide(s) from $FILE\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":3116,"content_sha256":"bc049f225cdfb4e1a98cfe5aad791840c0eafd095dba8dc6bc0e341a12d4e68c"},{"filename":"templates/animation-showcase.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"en\" data-theme=\"aurora\">\n\u003chead>\n\u003cmeta charset=\"utf-8\">\u003ctitle>Animation + FX Showcase — html-ppt\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../assets/themes/aurora.css\">\n\u003clink rel=\"stylesheet\" href=\"../assets/animations/animations.css\">\n\u003cstyle>\n .fx-stage{\n position:relative;\n margin:20px auto 0;\n width:min(900px, 92%);\n height:380px;\n border-radius:var(--radius-lg, 16px);\n background:rgba(10,12,22,0.55);\n border:1px solid var(--border,#2a2a3a);\n box-shadow:var(--shadow-lg, 0 20px 60px rgba(0,0,0,.4));\n overflow:hidden;\n }\n .fx-label{\n position:absolute;top:14px;left:16px;z-index:5;\n font-family:var(--font-mono, ui-monospace,Menlo,monospace);\n font-size:11px;letter-spacing:.14em;color:var(--text-3,#a0a0b8);\n text-transform:uppercase;\n background:rgba(0,0,0,0.35);padding:4px 10px;border-radius:999px;\n border:1px solid rgba(255,255,255,0.08);\n }\n .fx-replay{\n position:absolute;top:12px;right:14px;z-index:5;\n appearance:none;cursor:pointer;\n padding:7px 14px;border-radius:999px;\n background:linear-gradient(135deg, var(--accent,#7c5cff), var(--accent-2,#22d3ee));\n color:#fff;font:600 12px system-ui,sans-serif;\n border:0;letter-spacing:.05em;\n box-shadow:0 4px 16px rgba(124,92,255,0.35);\n }\n .fx-replay:hover{ filter:brightness(1.1); transform:translateY(-1px); }\n .fx-indicator{position:absolute;top:24px;right:40px;font-family:var(--font-mono);font-size:11px;color:var(--text-3);letter-spacing:.1em}\n .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)}\n\u003c/style>\n\u003c/head>\n\u003cbody>\n\u003cdiv class=\"deck\">\u003c/div>\n\n\u003cscript>\nconst FX = [\n ['particle-burst', 'Particles explode from center, gravity + fade, re-bursts every ~2.5s.'],\n ['confetti-cannon', 'Colored rotating rects arcing from both bottom corners.'],\n ['firework', 'Rockets launch from the bottom and burst into colored sparks.'],\n ['starfield', '3D perspective starfield — infinite flythrough.'],\n ['matrix-rain', 'Classic green katakana + hex columns raining down.'],\n ['knowledge-graph', 'Force-directed graph, 28 labeled nodes, live physics + springs.'],\n ['neural-net', '4-6-6-3 feedforward net with pulses traveling along edges.'],\n ['constellation', 'Drifting points connect when close — ambient background.'],\n ['orbit-ring', '5 concentric rings with dots rotating at different speeds.'],\n ['galaxy-swirl', 'Logarithmic spiral with ~800 particles.'],\n ['word-cascade', 'Words fall from top and pile up at the bottom.'],\n ['letter-explode', 'Letters fly in from random directions, loops.'],\n ['chain-react', 'Row of 8 circles — a wave pulse dominoes across them.'],\n ['magnetic-field', 'Particles follow sine curves leaving gradient trails.'],\n ['data-stream', 'Rows of scrolling hex/binary text, cyberpunk feel.'],\n ['gradient-blob', '4 drifting blurred radial gradients (additive blending).'],\n ['sparkle-trail', 'Sparkles emit at your cursor (auto-wiggles if idle).'],\n ['shockwave', 'Expanding rings emanating from center, looping.'],\n ['typewriter-multi', 'Three lines typing concurrently with blinking block cursors.'],\n ['counter-explosion', 'Number counts 0 → 2400, bursts particles, resets.']\n];\n\nconst CSS_ANIMS = [\n ['fade-up','Translate from +32 px, fade.'],\n ['fade-down','Translate from -32 px, fade.'],\n ['fade-left','From left.'],\n ['fade-right','From right.'],\n ['rise-in','Rise + blur-off.'],\n ['drop-in','Drop from above.'],\n ['zoom-pop','Elastic scale pop.'],\n ['blur-in','Blur clears.'],\n ['glitch-in','Glitch jitter.'],\n ['typewriter','Typewriter reveal.'],\n ['neon-glow','Neon pulse.'],\n ['shimmer-sweep','Sheen sweep.'],\n ['gradient-flow','Gradient flow.'],\n ['stagger-list','Staggered children.'],\n ['counter-up','Number tick.'],\n ['path-draw','SVG strokes draw.'],\n ['parallax-tilt','3D hover tilt.'],\n ['card-flip-3d','Y-axis flip.'],\n ['cube-rotate-3d','Cube rotate.'],\n ['page-turn-3d','Page turn.'],\n ['perspective-zoom','Pull from -400 Z.'],\n ['marquee-scroll','Infinite marquee.'],\n ['kenburns','Ken Burns zoom.'],\n ['confetti-burst','Pseudo confetti.'],\n ['spotlight','Circular clip reveal.'],\n ['morph-shape','SVG d morph.'],\n ['ripple-reveal','Corner ripple.']\n];\n\nconst deck = document.querySelector('.deck');\nconst total = FX.length + CSS_ANIMS.length;\n\n// Build FX slides (1..20)\nFX.forEach((f, i) => {\n const idx = i + 1;\n const [name, desc] = f;\n const sec = document.createElement('section');\n sec.className = 'slide';\n sec.setAttribute('data-title', 'fx / ' + name);\n\n const extraAttrs = name === 'letter-explode'\n ? 'data-fx-text-value=\"' + name.toUpperCase() + '\"'\n : name === 'counter-explosion'\n ? 'data-fx-to=\"2400\"'\n : name === 'typewriter-multi'\n ? 'data-fx-line1=\"> initializing knowledge graph...\" data-fx-line2=\"> loading 28 concept nodes\" data-fx-line3=\"> agent ready. awaiting prompt_\"'\n : '';\n\n sec.innerHTML = `\n \u003cspan class=\"fx-indicator\">${idx}/${total}\u003c/span>\n \u003cp class=\"kicker\">FX · canvas · ${String(idx).padStart(2,'0')}\u003c/p>\n \u003ch1 class=\"h1\">\u003cspan class=\"gradient-text\">${name}\u003c/span>\u003c/h1>\n \u003cp class=\"lede\">${desc}\u003c/p>\n \u003cdiv class=\"fx-stage\">\n \u003cspan class=\"fx-label\">data-fx=\"${name}\"\u003c/span>\n \u003cbutton class=\"fx-replay\" type=\"button\">Replay\u003c/button>\n \u003cdiv class=\"fx-host\" style=\"position:absolute;inset:0;\" data-fx=\"${name}\" ${extraAttrs}>\u003c/div>\n \u003c/div>\n \u003cdiv class=\"deck-footer\">\u003cspan class=\"dim2\">Press → for next slide\u003c/span>\u003cspan class=\"slide-number\" data-current=\"${idx}\" data-total=\"${total}\">\u003c/span>\u003c/div>\n `;\n deck.appendChild(sec);\n\n // Wire Replay button\n sec.querySelector('.fx-replay').addEventListener('click', () => {\n const host = sec.querySelector('.fx-host');\n const name2 = host.getAttribute('data-fx');\n const attrs = {};\n for (const a of host.attributes) attrs[a.name] = a.value;\n const parent = host.parentNode;\n // stop existing\n if (window.__hpxActive && window.__hpxActive.has(host)){\n try{ window.__hpxActive.get(host).stop(); }catch(e){}\n window.__hpxActive.delete(host);\n }\n const fresh = document.createElement('div');\n for (const k in attrs) fresh.setAttribute(k, attrs[k]);\n fresh.style.cssText = host.style.cssText;\n parent.replaceChild(fresh, host);\n if (window.__hpxReinit) window.__hpxReinit(sec);\n });\n});\n\n// Build CSS animation slides (legacy, kept for completeness)\nCSS_ANIMS.forEach((a, i) => {\n const idx = FX.length + i + 1;\n const sec = document.createElement('section');\n sec.className = 'slide';\n sec.setAttribute('data-title', a[0]);\n sec.innerHTML = `\n \u003cspan class=\"fx-indicator\">${idx}/${total}\u003c/span>\n \u003cp class=\"kicker\">CSS anim · ${String(idx).padStart(2,'0')}\u003c/p>\n \u003ch1 class=\"h1\">\u003cspan class=\"gradient-text\">${a[0]}\u003c/span>\u003c/h1>\n \u003cp class=\"lede\">${a[1]}\u003c/p>\n \u003cdiv class=\"anim-box anim-${a[0]}\" data-anim=\"${a[0]}\" data-anim-target>${a[0]}\u003c/div>\n \u003cdiv class=\"deck-footer\">\u003cspan class=\"dim2\">Press A to cycle\u003c/span>\u003cspan class=\"slide-number\" data-current=\"${idx}\" data-total=\"${total}\">\u003c/span>\u003c/div>\n `;\n deck.appendChild(sec);\n});\n\u003c/script>\n\u003cscript src=\"../assets/runtime.js\">\u003c/script>\n\u003cscript src=\"../assets/animations/fx-runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":7681,"content_sha256":"f9ea23f4488557127b41132f9ee0e5887fef44dfc95a5c1608ee345726c5fcb8"},{"filename":"templates/deck.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\" data-theme=\"minimal-white\">\n\u003chead>\n\u003cmeta charset=\"utf-8\">\u003cmeta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n\u003ctitle>html-ppt · Deck\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../assets/animations/animations.css\">\n\u003c/head>\n\u003cbody 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/\">\n\u003cdiv class=\"deck\">\n\n \u003c!-- 1. Cover -->\n \u003csection class=\"slide\" data-title=\"Cover\">\n \u003cp class=\"kicker\">html-ppt · 2026\u003c/p>\n \u003ch1 class=\"h1 anim-fade-up\" data-anim=\"fade-up\">用模板,\u003cspan class=\"gradient-text\">换主题\u003c/span>\u003cbr>讲任何事情\u003c/h1>\n \u003cp class=\"lede\">24 themes · 30 layouts · 25 animations · zero build\u003c/p>\n \u003cdiv class=\"deck-footer\">\u003cspan class=\"dim2\">lewis\u003c/span>\u003cspan class=\"slide-number\" data-current=\"1\" data-total=\"6\">\u003c/span>\u003c/div>\n \u003cdiv class=\"notes\">这是一个最小可用的 deck。你可以复制这个文件作为新 deck 的起点。\u003c/div>\n \u003c/section>\n\n \u003c!-- 2. TOC -->\n \u003csection class=\"slide\" data-title=\"目录\">\n \u003cp class=\"kicker\">Agenda\u003c/p>\n \u003ch2 class=\"h2\">我们会讲三件事\u003c/h2>\n \u003cdiv class=\"grid g3 mt-l anim-stagger-list\" data-anim-target>\n \u003cdiv class=\"card\">\u003ch4>01 · Tokens\u003c/h4>\u003cp class=\"dim\">把颜色/字体/圆角收进 CSS 变量。\u003c/p>\u003c/div>\n \u003cdiv class=\"card\">\u003ch4>02 · Layouts\u003c/h4>\u003cp class=\"dim\">30 种可复用单页。\u003c/p>\u003c/div>\n \u003cdiv class=\"card\">\u003ch4>03 · Runtime\u003c/h4>\u003cp class=\"dim\">键盘驱动、按 T 换主题。\u003c/p>\u003c/div>\n \u003c/div>\n \u003c/section>\n\n \u003c!-- 3. Stat -->\n \u003csection class=\"slide center tc\" data-title=\"Stat\">\n \u003cdiv>\n \u003cp class=\"kicker\">Result\u003c/p>\n \u003cdiv style=\"font-size:220px;font-weight:900;line-height:1\">\u003cspan class=\"counter gradient-text\" data-to=\"92\">0\u003c/span>\u003cspan class=\"gradient-text\">%\u003c/span>\u003c/div>\n \u003ch3>的准备时间被省下\u003c/h3>\n \u003c/div>\n \u003c/section>\n\n \u003c!-- 4. Two column -->\n \u003csection class=\"slide\" data-title=\"Tokens\">\n \u003cp class=\"kicker\">Under the hood\u003c/p>\n \u003ch2 class=\"h2\">换主题 = 换一组变量\u003c/h2>\n \u003cdiv class=\"grid g2 mt-l\">\n \u003cdiv class=\"card\">\u003ch4>语义变量\u003c/h4>\u003cp class=\"dim\">写 \u003ccode>var(--surface)\u003c/code>,不写具体色值。\u003c/p>\u003c/div>\n \u003cdiv class=\"card\">\u003ch4>一键切换\u003c/h4>\u003cp class=\"dim\">按 T 循环所有主题——所有 slide 同步更新。\u003c/p>\u003c/div>\n \u003c/div>\n \u003c/section>\n\n \u003c!-- 5. CTA -->\n \u003csection class=\"slide center tc\" data-title=\"CTA\">\n \u003cdiv>\n \u003cp class=\"kicker\">Your turn\u003c/p>\n \u003ch1 class=\"h1 anim-rise-in\" data-anim=\"rise-in\">开始做你的 deck\u003c/h1>\n \u003cp class=\"lede\" style=\"margin:16px auto\">按 ← → 翻页 · T 切主题 · A 切动效 · F 全屏 · O 概览 · S 备注\u003c/p>\n \u003c/div>\n \u003c/section>\n\n \u003c!-- 6. Thanks -->\n \u003csection class=\"slide center tc\" data-title=\"Thanks\">\n \u003ch1 class=\"h1\" style=\"font-size:160px;line-height:1\">\u003cspan class=\"gradient-text\">Thanks\u003c/span>\u003c/h1>\n \u003cp class=\"lede\">lewis · [email protected]\u003c/p>\n \u003c/section>\n\u003c/div>\n\u003cscript src=\"../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":3293,"content_sha256":"51cc424b4672a1187a64a66083d55ae6bebcedd73f55f15e3adf2e826d6bcdf3"},{"filename":"templates/full-decks-index.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\n\u003chead>\n\u003cmeta charset=\"utf-8\">\u003ctitle>Full-Deck Gallery — html-ppt v2\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../assets/base.css\">\n\u003cstyle>\n html,body{background:#0b0c10;color:#e8ebf4;font-family:var(--font-sans)}\n .deck{background:#0b0c10}\n .slide{padding:60px 80px;color:#e8ebf4;background:transparent;display:flex;flex-direction:column}\n .slide h1{color:#fff;font-size:48px;margin:0 0 6px;letter-spacing:-.02em}\n .slide .sub{color:#aab0c0;font-size:18px;margin:0 0 22px}\n .frame-wrap{flex:1;border-radius:14px;overflow:hidden;border:1px solid rgba(255,255,255,.12);\n box-shadow:0 30px 80px rgba(0,0,0,.5);position:relative;background:#fff}\n iframe.tpl{position:absolute;inset:0;width:200%;height:200%;border:0;\n transform:scale(.5);transform-origin:top left}\n .meta{position:absolute;top:24px;right:40px;font-family:'JetBrains Mono',monospace;\n font-size:12px;color:#6a7086;letter-spacing:.14em;text-transform:uppercase;z-index:30}\n .tag{display:inline-block;padding:4px 10px;border-radius:999px;background:rgba(255,255,255,.08);\n color:#cfd3dc;font-size:11px;margin-right:6px}\n .cover{align-items:center;justify-content:center;text-align:center}\n .cover h1{font-size:84px;background:linear-gradient(135deg,#60a5fa,#a78bfa,#f472b6);\n -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}\n .cover p{color:#aab0c0;max-width:60ch;font-size:20px}\n .legend{display:flex;gap:10px;flex-wrap:wrap;margin-top:18px}\n\u003c/style>\n\u003c/head>\n\u003cbody>\n\u003cdiv class=\"deck\">\n\n\u003csection class=\"slide cover\">\n \u003cp class=\"kicker\" style=\"color:#a78bfa\">HTML-PPT v2 · Full-Deck Gallery\u003c/p>\n \u003ch1>15 full-deck templates\u003c/h1>\n \u003cp>Press → to browse. Each slide is a live iframe preview of a complete, multi-slide deck template. Open any \u003ccode>templates/full-decks/<name>/index.html\u003c/code> to see the full deck, or copy the folder to scaffold your own.\u003c/p>\n \u003cdiv class=\"legend\">\n \u003cspan class=\"tag\">8 extracted from real decks\u003c/span>\n \u003cspan class=\"tag\">6 scenario scaffolds\u003c/span>\n \u003cspan class=\"tag\">scoped .tpl-<name> CSS\u003c/span>\n \u003cspan class=\"tag\">36 themes compatible\u003c/span>\n \u003c/div>\n\u003c/section>\n\n\u003c!-- Template preview slides generated via JS below -->\n\n\u003c/div>\n\n\u003cscript>\nconst TPLS = [\n ['xhs-white-editorial', '白底杂志风', 'extracted', 'xhs posts, editorial lifestyle'],\n ['graphify-dark-graph', '暗底知识图谱', 'extracted', 'AI/graph/data products'],\n ['knowledge-arch-blueprint', '奶油蓝图架构', 'extracted', 'architecture, systems thinking'],\n ['hermes-cyber-terminal', '暗终端 cyber', 'extracted', 'devtool, honest-review, agent demos'],\n ['obsidian-claude-gradient', 'GitHub 暗紫渐变', 'extracted', 'tool walkthroughs, LLM product'],\n ['testing-safety-alert', '红琥珀警示', 'extracted', 'security, incident review, AI safety'],\n ['xhs-pastel-card', '柔和马卡龙', 'extracted', 'lifestyle, soft emotional'],\n ['dir-key-nav-minimal', '方向键 8 色极简', 'extracted', 'keynote, one-idea-per-slide'],\n ['pitch-deck', 'Pitch Deck YC 风', 'scenario', 'fundraising, startup pitch'],\n ['product-launch', 'Product Launch', 'scenario', 'product announcement, launch keynote'],\n ['tech-sharing', 'Tech Sharing 技术分享','scenario','internal tech talk, conference talk'],\n ['weekly-report', 'Weekly Report 周报','scenario', 'status update, business review'],\n ['xhs-post', '小红书 图文 9 屏 3:4','scenario', 'xiaohongshu / ig carousel'],\n ['course-module', 'Course Module 教学模块','scenario','online course, workshop module'],\n ['presenter-mode-reveal', '🎤 Presenter Mode 演讲者模式','scenario','tech sharing, talk with 逐字稿, speaker view']\n];\n\nconst deck = document.querySelector('.deck');\nTPLS.forEach((t,i)=>{\n const s = document.createElement('section');\n s.className = 'slide';\n s.setAttribute('data-title',t[0]);\n s.innerHTML = `\n \u003cspan class=\"meta\">${i+1}/${TPLS.length+1}\u003c/span>\n \u003ch1>${t[0]}\u003c/h1>\n \u003cp class=\"sub\">${t[1]} · \u003cspan class=\"tag\">${t[2]}\u003c/span> ${t[3]}\u003c/p>\n \u003cdiv class=\"frame-wrap\">\n \u003ciframe class=\"tpl\" src=\"full-decks/${t[0]}/index.html\" loading=\"eager\" title=\"${t[0]}\">\u003c/iframe>\n \u003c/div>`;\n deck.appendChild(s);\n});\n\u003c/script>\n\u003cscript src=\"../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":4508,"content_sha256":"78537bc67e52d798bcb1eda543b201f17d254afc899601208c6efa0c34c88397"},{"filename":"templates/layout-showcase.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\n\u003chead>\n\u003cmeta charset=\"utf-8\">\u003ctitle>Layout Showcase — html-ppt\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../assets/animations/animations.css\">\n\u003cstyle>\n.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}\n.layout-nav a{color:var(--text-2);text-decoration:none;padding:4px 10px;border-radius:999px}\n.layout-nav a:hover{background:var(--surface-2)}\niframe{width:100%;height:100vh;border:0;display:block;background:var(--bg)}\nbody{margin:0;overflow:hidden}\n\u003c/style>\n\u003c/head>\n\u003cbody>\n\u003cdiv class=\"layout-nav\">\n \u003cb>layouts\u003c/b>\n \u003ca href=\"#\" data-go=\"-1\">←\u003c/a>\n \u003cspan id=\"cur\">cover\u003c/span>\n \u003ca href=\"#\" data-go=\"+1\">→\u003c/a>\n\u003c/div>\n\u003ciframe id=\"frame\" src=\"single-page/cover.html\">\u003c/iframe>\n\u003cscript>\nconst list=['cover','toc','section-divider','bullets','two-column','three-column','big-quote',\n 'stat-highlight','kpi-grid','table','code','diff','terminal','flow-diagram','timeline',\n 'roadmap','mindmap','comparison','pros-cons','todo-checklist','gantt',\n 'image-single','image-full-bleed','image-text-split','image-gallery','image-compare','image-hero','image-grid',\n 'chart-bar','chart-line','chart-pie','chart-radar','arch-diagram','process-steps','cta','thanks'];\nlet i=0;\nconst frame=document.getElementById('frame');\nconst cur=document.getElementById('cur');\nfunction go(n){\n i=(n+list.length)%list.length;\n frame.src='single-page/'+list[i]+'.html';\n cur.textContent=list[i]+' · '+(i+1)+'/'+list.length;\n history.replaceState(null,'','#/'+(i+1));\n}\ndocument.querySelectorAll('[data-go]').forEach(a=>a.addEventListener('click',e=>{e.preventDefault();go(i+parseInt(a.dataset.go,10))}));\ndocument.addEventListener('keydown',e=>{\n if(e.key==='ArrowRight'||e.key===' '){go(i+1);e.preventDefault()}\n if(e.key==='ArrowLeft'){go(i-1);e.preventDefault()}\n});\nconst m=/^#\\/(\\d+)/.exec(location.hash||'');\nif(m)go(parseInt(m[1],10)-1);else go(0);\n\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":2343,"content_sha256":"07c9dad19310656bf44f0c6e67d07fb1245c9b76e419c465b1e0448eca93d5cc"},{"filename":"templates/single-page/arch-diagram.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Architecture\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.arch{margin-top:20px;display:grid;grid-template-rows:auto auto auto;gap:22px}\n.arch .tier{display:grid;grid-template-columns:120px 1fr;align-items:stretch;gap:22px}\n.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}\n.arch .cells{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}\n.arch .cells.three{grid-template-columns:repeat(3,1fr)}\n.arch .cell{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:16px;text-align:center;box-shadow:var(--shadow)}\n.arch .cell .ic{font-size:24px}\n.arch .cell h4{font-size:14px;margin:6px 0 2px}\n.arch .cell p{font-size:11px;color:var(--text-3);margin:0}\n.arch .tier.hl .cell{border-top:3px solid var(--accent)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Architecture\">\n \u003cp class=\"kicker\">Architecture · 系统总览\u003c/p>\n \u003ch2 class=\"h2\">一套三层栈\u003c/h2>\n \u003cdiv class=\"arch anim-stagger-list\" data-anim-target>\n \u003cdiv class=\"tier\">\u003cdiv class=\"tname\">UI Layer\u003c/div>\n \u003cdiv class=\"cells\">\u003cdiv class=\"cell\">\u003cdiv class=\"ic\">🧱\u003c/div>\u003ch4>Layouts\u003c/h4>\u003cp>30 个单页\u003c/p>\u003c/div>\n \u003cdiv class=\"cell\">\u003cdiv class=\"ic\">🎨\u003c/div>\u003ch4>Themes\u003c/h4>\u003cp>24 tokens 主题\u003c/p>\u003c/div>\n \u003cdiv class=\"cell\">\u003cdiv class=\"ic\">✨\u003c/div>\u003ch4>Animations\u003c/h4>\u003cp>25 个命名动效\u003c/p>\u003c/div>\n \u003cdiv class=\"cell\">\u003cdiv class=\"ic\">⌨️\u003c/div>\u003ch4>Runtime\u003c/h4>\u003cp>键盘导航\u003c/p>\u003c/div>\n \u003c/div>\n \u003c/div>\n \u003cdiv class=\"tier hl\">\u003cdiv class=\"tname\">Core · tokens\u003c/div>\n \u003cdiv class=\"cells three\">\u003cdiv class=\"cell\">\u003cdiv class=\"ic\">🎯\u003c/div>\u003ch4>base.css\u003c/h4>\u003cp>排版 + 网格\u003c/p>\u003c/div>\n \u003cdiv class=\"cell\">\u003cdiv class=\"ic\">🔤\u003c/div>\u003ch4>fonts.css\u003c/h4>\u003cp>中英字体\u003c/p>\u003c/div>\n \u003cdiv class=\"cell\">\u003cdiv class=\"ic\">🪞\u003c/div>\u003ch4>:root vars\u003c/h4>\u003cp>语义颜色\u003c/p>\u003c/div>\n \u003c/div>\n \u003c/div>\n \u003cdiv class=\"tier\">\u003cdiv class=\"tname\">Tooling\u003c/div>\n \u003cdiv class=\"cells three\">\u003cdiv class=\"cell\">\u003cdiv class=\"ic\">🧪\u003c/div>\u003ch4>render.sh\u003c/h4>\u003cp>headless Chrome\u003c/p>\u003c/div>\n \u003cdiv class=\"cell\">\u003cdiv class=\"ic\">🆕\u003c/div>\u003ch4>new-deck.sh\u003c/h4>\u003cp>脚手架\u003c/p>\u003c/div>\n \u003cdiv class=\"cell\">\u003cdiv class=\"ic\">📦\u003c/div>\u003ch4>AgentSkill\u003c/h4>\u003cp>Claude 接入点\u003c/p>\u003c/div>\n \u003c/div>\n \u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":2895,"content_sha256":"555d00db06b720212357ab5c59039f5f3fca1595452c2c330ccc5998e8f0bb1b"},{"filename":"templates/single-page/big-quote.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Big Quote\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/editorial-serif.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active center tc\" data-title=\"Quote\">\n \u003cdiv style=\"max-width:1040px\">\n \u003cdiv class=\"serif\" style=\"font-size:140px;line-height:.9;color:var(--accent);opacity:.6\">\"\u003c/div>\n \u003cblockquote 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\">\n 好的设计不是把东西加得更多,\u003cbr>而是把一切不需要的东西拿掉。\n \u003c/blockquote>\n \u003cp class=\"dim\" style=\"font-size:20px;letter-spacing:.08em\">— Dieter Rams\u003c/p>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1039,"content_sha256":"b4cc71b66192ed844457b88e7093534e79977b0e8da6c4a8ef3d292df6c0a792"},{"filename":"templates/single-page/bullets.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Bullets\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Why\">\n \u003cp class=\"kicker\">Why · 为什么\u003c/p>\n \u003ch2 class=\"h2\">好的演讲系统,帮你做三件事\u003c/h2>\n \u003cp class=\"lede mb-l\">不是做不出漂亮的 slide,是每次都要重新做。\u003c/p>\n \u003cul class=\"grid g1 anim-stagger-list\" style=\"list-style:none;padding:0;margin:0;gap:14px\" data-anim-target>\n \u003cli class=\"card card-accent\">\u003ch4>① 统一设计语言\u003c/h4>\u003cp class=\"dim\">所有页共用同一套 tokens,字号、颜色、阴影不会跑偏。\u003c/p>\u003c/li>\n \u003cli class=\"card card-accent\">\u003ch4>② 降低复用成本\u003c/h4>\u003cp class=\"dim\">下一次讲同类话题,复制 deck、换数据、换主题即可。\u003c/p>\u003c/li>\n \u003cli class=\"card card-accent\">\u003ch4>③ 可切换,可演示\u003c/h4>\u003cp class=\"dim\">按 T 即可循环切主题、按 A 可切动效,汇报现场加分。\u003c/p>\u003c/li>\n \u003c/ul>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1321,"content_sha256":"f1bee00e539c75373f7a78ec7c487a68ccba8e54b00d77e97e19f5fa0f39899f"},{"filename":"templates/single-page/chart-bar.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Chart · Bar\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js\">\u003c/script>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Bar chart\">\n \u003cp class=\"kicker\">Chart · 柱状图\u003c/p>\n \u003ch2 class=\"h2\">季度 MRR 趋势\u003c/h2>\n \u003cdiv class=\"card mt-l\" style=\"height:520px;padding:28px\">\u003ccanvas id=\"c\">\u003c/canvas>\u003c/div>\n \u003cscript>\n addEventListener('DOMContentLoaded',()=>{\n const css=getComputedStyle(document.documentElement);\n const accent=css.getPropertyValue('--accent').trim();\n const text2=css.getPropertyValue('--text-2').trim();\n const border=css.getPropertyValue('--border').trim();\n new Chart(document.getElementById('c'),{type:'bar',\n data:{labels:['Q1','Q2','Q3','Q4','Q1 +1','Q2 +1','Q3 +1','Q4 +1'],\n datasets:[{label:'MRR (K)',data:[42,58,73,96,124,158,204,261],\n backgroundColor:accent,borderRadius:8,barThickness:36}]},\n options:{plugins:{legend:{labels:{color:text2}}},\n scales:{x:{ticks:{color:text2},grid:{color:border}},\n y:{ticks:{color:text2},grid:{color:border}}}}});\n });\n \u003c/script>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1581,"content_sha256":"4f3510567d46fac93b3e14f50fc4ee376edb25a1ff2834293c6964984f32542d"},{"filename":"templates/single-page/chart-line.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Chart · Line\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js\">\u003c/script>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Line chart\">\n \u003cp class=\"kicker\">Chart · 折线图\u003c/p>\n \u003ch2 class=\"h2\">日活与留存并排看\u003c/h2>\n \u003cdiv class=\"card mt-l\" style=\"height:520px;padding:28px\">\u003ccanvas id=\"c\">\u003c/canvas>\u003c/div>\n \u003cscript>\n addEventListener('DOMContentLoaded',()=>{\n const css=getComputedStyle(document.documentElement);\n const accent=css.getPropertyValue('--accent').trim();\n const acc2=css.getPropertyValue('--accent-2').trim();\n const text2=css.getPropertyValue('--text-2').trim();\n const border=css.getPropertyValue('--border').trim();\n new Chart(document.getElementById('c'),{type:'line',\n data:{labels:['W1','W2','W3','W4','W5','W6','W7','W8','W9','W10','W11','W12'],\n datasets:[\n {label:'DAU (K)',data:[12,14,15,19,24,28,33,38,45,51,58,66],\n borderColor:accent,backgroundColor:accent+'22',fill:true,tension:.4,borderWidth:3,pointRadius:4},\n {label:'Retention %',data:[38,40,42,45,48,50,53,55,58,60,62,64],\n borderColor:acc2,backgroundColor:acc2+'22',fill:true,tension:.4,borderWidth:3,pointRadius:4}\n ]},\n options:{plugins:{legend:{labels:{color:text2}}},\n scales:{x:{ticks:{color:text2},grid:{color:border}},\n y:{ticks:{color:text2},grid:{color:border}}}}});\n });\n \u003c/script>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1923,"content_sha256":"7d88cb3459e019317d757e766f6508916f9055f86faf89faf7af4e7c0fef39c1"},{"filename":"templates/single-page/chart-pie.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Chart · Pie\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js\">\u003c/script>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Pie chart\">\n \u003cp class=\"kicker\">Chart · 环形图\u003c/p>\n \u003ch2 class=\"h2\">时间都花在了哪里\u003c/h2>\n \u003cdiv class=\"grid g2 mt-l\" style=\"align-items:center\">\n \u003cdiv class=\"card\" style=\"height:460px;padding:28px\">\u003ccanvas id=\"c\">\u003c/canvas>\u003c/div>\n \u003cdiv class=\"card\">\n \u003ch4>Takeaways\u003c/h4>\n \u003cp class=\"dim\">超过一半的时间都在写内容,动效只占 5%。说明值得把动效做成可复用模板。\u003c/p>\n \u003cul class=\"mt-m dim\">\n \u003cli>✍️ 写内容   55%\u003c/li>\u003cli>🧩 挑版式   18%\u003c/li>\u003cli>🎨 调样式   14%\u003c/li>\n \u003cli>📸 出图   8%\u003c/li>\u003cli>✨ 动效   5%\u003c/li>\n \u003c/ul>\n \u003c/div>\n \u003c/div>\n \u003cscript>\n addEventListener('DOMContentLoaded',()=>{\n const css=getComputedStyle(document.documentElement);\n const colors=['--accent','--accent-2','--accent-3','--good','--warn'].map(k=>css.getPropertyValue(k).trim());\n const text2=css.getPropertyValue('--text-2').trim();\n new Chart(document.getElementById('c'),{type:'doughnut',\n data:{labels:['写内容','挑版式','调样式','出图','动效'],\n datasets:[{data:[55,18,14,8,5],backgroundColor:colors,borderWidth:0}]},\n options:{cutout:'62%',plugins:{legend:{position:'right',labels:{color:text2}}}}});\n });\n \u003c/script>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1903,"content_sha256":"5205625652efc782136f131e06586b35df888a0cdc6dbe8e998c70dff6f26b72"},{"filename":"templates/single-page/chart-radar.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Chart · Radar\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js\">\u003c/script>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Radar chart\">\n \u003cp class=\"kicker\">Chart · 雷达图\u003c/p>\n \u003ch2 class=\"h2\">把 html-ppt 和竞品放一张图\u003c/h2>\n \u003cdiv class=\"card mt-l\" style=\"height:520px;padding:28px\">\u003ccanvas id=\"c\">\u003c/canvas>\u003c/div>\n \u003cscript>\n addEventListener('DOMContentLoaded',()=>{\n const css=getComputedStyle(document.documentElement);\n const a1=css.getPropertyValue('--accent').trim();\n const a2=css.getPropertyValue('--accent-2').trim();\n const text2=css.getPropertyValue('--text-2').trim();\n new Chart(document.getElementById('c'),{type:'radar',\n data:{labels:['上手','美观','自定义','性能','导出','生态'],\n datasets:[\n {label:'html-ppt',data:[9,9,10,10,9,6],borderColor:a1,backgroundColor:a1+'33',borderWidth:3,pointRadius:5},\n {label:'reveal.js',data:[8,7,9,8,8,10],borderColor:a2,backgroundColor:a2+'22',borderWidth:3,pointRadius:5}]},\n options:{plugins:{legend:{labels:{color:text2}}},\n scales:{r:{suggestedMin:0,suggestedMax:10,ticks:{color:text2,backdropColor:'transparent'},\n pointLabels:{color:text2,font:{size:14}},grid:{color:'rgba(0,0,0,.08)'},angleLines:{color:'rgba(0,0,0,.08)'}}}}});\n });\n \u003c/script>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1830,"content_sha256":"4890a9018a5ce648daf42ee0f7f41790998a3b7befeb5cf003582fb49a6fb426"},{"filename":"templates/single-page/code.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Code\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/tokyo-night.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003clink rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/[email protected]/styles/tokyo-night-dark.min.css\">\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/[email protected]/lib/core.min.js\">\u003c/script>\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/[email protected]/lib/languages/javascript.min.js\">\u003c/script>\n\u003cscript>addEventListener('DOMContentLoaded',()=>{hljs.registerLanguage('javascript',window.hljsLangJavascript||window.hljs.getLanguage('javascript'));document.querySelectorAll('pre code').forEach(el=>hljs.highlightElement(el))})\u003c/script>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Code\">\n \u003cp class=\"kicker\">Snippet · 运行时核心\u003c/p>\n \u003ch2 class=\"h2\">按一下键盘,幻灯片就跑起来了\u003c/h2>\n\u003cpre class=\"card mt-m\" style=\"padding:24px\">\u003ccode class=\"language-javascript\">// runtime.js — keyboard-driven deck\nfunction go(n) {\n n = Math.max(0, Math.min(total - 1, n));\n slides.forEach((s, i) => {\n s.classList.toggle('is-active', i === n);\n });\n idx = n;\n barFill.style.width = ((n + 1) / total * 100) + '%';\n history.replaceState(null, '', '#/' + (n + 1));\n}\n\ndocument.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowRight' || e.key === ' ') go(idx + 1);\n if (e.key === 'ArrowLeft') go(idx - 1);\n if (e.key === 't') cycleTheme();\n});\u003c/code>\u003c/pre>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1765,"content_sha256":"02d1a0a1e6d71ec9a547d46f6e16f1ded4ab090d82c4435a9e68047d04ac222a"},{"filename":"templates/single-page/comparison.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Comparison\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.vs{display:grid;grid-template-columns:1fr 90px 1fr;gap:28px;align-items:stretch;margin-top:30px}\n.vs .side{padding:30px}\n.vs .mid{font-size:56px;font-weight:800;color:var(--text-3);display:flex;align-items:center;justify-content:center}\n.vs .bad-side{border-top:3px solid var(--bad)}\n.vs .good-side{border-top:3px solid var(--good)}\n.vs h3{font-size:24px}\n.vs ul{padding-left:20px;font-size:15px;line-height:1.8;color:var(--text-2)}\n.vs li::marker{color:var(--bad)}\n.vs .good-side li::marker{color:var(--good)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Comparison\">\n \u003cp class=\"kicker\">Before vs After · 对比\u003c/p>\n \u003ch2 class=\"h2\">从「每次重做」到「一键起稿」\u003c/h2>\n \u003cdiv class=\"vs\">\n \u003cdiv class=\"card bad-side side anim-fade-left\" data-anim=\"fade-left\">\n \u003ch3>📉 过去\u003c/h3>\n \u003cul>\n \u003cli>每次都要重新做封面、目录、结语\u003c/li>\n \u003cli>颜色、字号跨 slide 不一致\u003c/li>\n \u003cli>想换主题?手动改每一页\u003c/li>\n \u003cli>动效全靠 transition 硬写\u003c/li>\n \u003cli>截图导出还要一张一张截\u003c/li>\n \u003c/ul>\n \u003c/div>\n \u003cdiv class=\"mid\">→\u003c/div>\n \u003cdiv class=\"card good-side side anim-fade-right\" data-anim=\"fade-right\">\n \u003ch3>📈 现在\u003c/h3>\n \u003cul>\n \u003cli>复制模板、换数据、完事\u003c/li>\n \u003cli>所有页共享 tokens\u003c/li>\n \u003cli>按 \u003cb>T\u003c/b> 循环切主题\u003c/li>\n \u003cli>25 个命名动效直接挑\u003c/li>\n \u003cli>一条 render.sh 全部出图\u003c/li>\n \u003c/ul>\n \u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":2006,"content_sha256":"18fc03519e9b0ed036444677972317eb53d970f530d8bceb0e30a591686ac49b"},{"filename":"templates/single-page/cover.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\" data-theme=\"minimal-white\">\n\u003chead>\n\u003cmeta charset=\"utf-8\">\u003ctitle>Cover — html-ppt\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003c/head>\n\u003cbody class=\"single\">\n\u003cdiv class=\"deck\" data-themes=\"minimal-white,aurora,catppuccin-mocha,tokyo-night,xiaohongshu-white,neo-brutalism\" data-theme-base=\"../../assets/themes/\">\n \u003csection class=\"slide is-active\" data-title=\"Cover\">\n \u003cdiv class=\"deck-header\">\u003cspan class=\"eyebrow\">Keynote · 2026\u003c/span>\u003cspan class=\"eyebrow\">html-ppt\u003c/span>\u003c/div>\n \u003cdiv class=\"anim-stagger-list\">\n \u003cp class=\"kicker\">Tech Sharing · 纯干货\u003c/p>\n \u003ch1 class=\"h1 anim-fade-up\" data-anim=\"fade-up\">\n 设计一套\u003cspan class=\"gradient-text\">属于你\u003c/span>的\u003cbr>HTML 演讲系统\n \u003c/h1>\n \u003cp class=\"lede\">从主题、版式到动效,全部由模板驱动。一行命令即可开场。\u003c/p>\n \u003cdiv class=\"row wrap mt-l\">\n \u003cspan class=\"pill pill-accent\">24 themes\u003c/span>\n \u003cspan class=\"pill\">30 layouts\u003c/span>\n \u003cspan class=\"pill\">25 animations\u003c/span>\n \u003cspan class=\"pill\">零构建\u003c/span>\n \u003c/div>\n \u003c/div>\n \u003cdiv class=\"deck-footer\">\u003cspan class=\"dim2\">lewis · 2026-04-15\u003c/span>\u003cspan class=\"slide-number\" data-current=\"1\" data-total=\"1\">\u003c/span>\u003c/div>\n \u003cdiv class=\"notes\">封面页口播:大家好,今天给大家带来一套开箱即用的 HTML 演讲系统。\u003c/div>\n \u003c/section>\n\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1702,"content_sha256":"a573ccf02a15d13d4514424aad1afbdbbeab6cd1cc61ccbb935b4f370421832a"},{"filename":"templates/single-page/cta.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>CTA\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/aurora.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.cta .btn{display:inline-flex;align-items:center;gap:10px;padding:20px 32px;border-radius:999px;background:var(--accent);color:var(--accent-ink);font-weight:700;font-size:20px;box-shadow:var(--shadow-lg);text-decoration:none;border:none;cursor:pointer}\n.cta .btn.outline{background:transparent;color:var(--text-1);border:1.5px solid var(--border-strong)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active center tc cta\" data-title=\"CTA\">\n \u003cdiv style=\"max-width:900px\">\n \u003cp class=\"kicker\">Call to action\u003c/p>\n \u003ch1 class=\"h1 anim-rise-in\" data-anim=\"rise-in\" style=\"font-size:96px\">\n \u003cspan class=\"gradient-text\">动手做你的\u003c/span>\u003cbr>第一份 html-ppt\n \u003c/h1>\n \u003cp class=\"lede\" style=\"margin:16px auto 30px\">复制模板、换上你的内容、按 \u003cb>T\u003c/b> 挑一个最对味的主题,讲完还能一键导出 PNG。\u003c/p>\n \u003cdiv class=\"row\" style=\"justify-content:center\">\n \u003ca class=\"btn\" href=\"#\">🚀 ./new-deck.sh my-talk\u003c/a>\n \u003ca class=\"btn outline\" href=\"#\">查看 SKILL.md\u003c/a>\n \u003c/div>\n \u003cp class=\"dim mt-l\" style=\"font-size:14px\">键盘: ← → 翻页 · T 主题 · A 动效 · F 全屏 · O 概览 · S 备注\u003c/p>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1632,"content_sha256":"e99d76d98cc59f9d29e273ee7b08a5cf598df6b0c2eaaf84e91679b00c5880b7"},{"filename":"templates/single-page/diff.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Diff\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.diff{font-family:var(--font-mono);font-size:14px;line-height:1.6;border-radius:var(--radius);overflow:hidden;border:1px solid var(--border)}\n.diff .ln{display:block;padding:2px 16px;white-space:pre}\n.diff .add{background:rgba(26,175,108,.12);color:var(--good)}\n.diff .del{background:rgba(224,68,90,.12);color:var(--bad)}\n.diff .ctx{color:var(--text-2)}\n.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)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Diff\">\n \u003cp class=\"kicker\">Before / After\u003c/p>\n \u003ch2 class=\"h2\">一次迁移到 tokens 后\u003c/h2>\n \u003cdiv class=\"card diff mt-l\" style=\"padding:0\">\n \u003cdiv class=\"hd\">assets/components/card.css\u003c/div>\n \u003cspan class=\"ln ctx\">.card {\u003c/span>\n \u003cspan class=\"ln del\">- background: #ffffff;\u003c/span>\n \u003cspan class=\"ln del\">- color: #0c0d10;\u003c/span>\n \u003cspan class=\"ln del\">- border-radius: 18px;\u003c/span>\n \u003cspan class=\"ln del\">- box-shadow: 0 10px 30px rgba(18,24,40,.08);\u003c/span>\n \u003cspan class=\"ln add\">+ background: var(--surface);\u003c/span>\n \u003cspan class=\"ln add\">+ color: var(--text-1);\u003c/span>\n \u003cspan class=\"ln add\">+ border-radius: var(--radius);\u003c/span>\n \u003cspan class=\"ln add\">+ box-shadow: var(--shadow);\u003c/span>\n \u003cspan class=\"ln ctx\">}\u003c/span>\n \u003c/div>\n \u003cp class=\"dim mt-m\">24 个主题从此只需改 variables——其他 0 改动。\u003c/p>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1920,"content_sha256":"a07bc6f7114b19439b9212500e4231d19de1683f7aceaf17097bb1c41e74245e"},{"filename":"templates/single-page/flow-diagram.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Flow Diagram\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.flow{display:flex;align-items:center;gap:16px;margin-top:40px;max-width:1200px}\n.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}\n.flow .node .ic{font-size:32px;margin-bottom:6px}\n.flow .node h4{font-size:16px}\n.flow .node p{font-size:12px;color:var(--text-3);margin:0}\n.flow .arr{color:var(--text-3);font-size:28px;flex-shrink:0}\n.flow .node.hl{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 18%,transparent),var(--shadow)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Flow\">\n \u003cp class=\"kicker\">Pipeline · 渲染管线\u003c/p>\n \u003ch2 class=\"h2\">从 Markdown 到 PNG,共 5 步\u003c/h2>\n \u003cdiv class=\"flow anim-stagger-list\" data-anim-target>\n \u003cdiv class=\"node\">\u003cdiv class=\"ic\">📝\u003c/div>\u003ch4>Markdown\u003c/h4>\u003cp>你的内容源\u003c/p>\u003c/div>\n \u003cdiv class=\"arr\">→\u003c/div>\n \u003cdiv class=\"node\">\u003cdiv class=\"ic\">🧩\u003c/div>\u003ch4>Layouts\u003c/h4>\u003cp>选择页型\u003c/p>\u003c/div>\n \u003cdiv class=\"arr\">→\u003c/div>\n \u003cdiv class=\"node hl\">\u003cdiv class=\"ic\">🎨\u003c/div>\u003ch4>Theme\u003c/h4>\u003cp>换装\u003c/p>\u003c/div>\n \u003cdiv class=\"arr\">→\u003c/div>\n \u003cdiv class=\"node\">\u003cdiv class=\"ic\">🌐\u003c/div>\u003ch4>HTML\u003c/h4>\u003cp>运行时接管\u003c/p>\u003c/div>\n \u003cdiv class=\"arr\">→\u003c/div>\n \u003cdiv class=\"node\">\u003cdiv class=\"ic\">📸\u003c/div>\u003ch4>PNG\u003c/h4>\u003cp>headless Chrome\u003c/p>\u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1878,"content_sha256":"3691ce0b2d465b6ac409a5909990d55be7a399ad649614ccb83b24397aa69391"},{"filename":"templates/single-page/gantt.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Gantt\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.gantt{margin-top:24px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:24px}\n.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)}\n.gantt .row{display:grid;grid-template-columns:200px repeat(12,1fr);gap:4px;align-items:center;height:40px}\n.gantt .lbl{font-size:14px;font-weight:500}\n.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%}\n.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)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Gantt\">\n \u003cp class=\"kicker\">Plan · Q2 甘特图\u003c/p>\n \u003ch2 class=\"h2\">四个月,五条线并行\u003c/h2>\n \u003cdiv class=\"gantt\">\n \u003cdiv class=\"hd\">\u003cdiv>任务\u003c/div>\u003cdiv>W1\u003c/div>\u003cdiv>W2\u003c/div>\u003cdiv>W3\u003c/div>\u003cdiv>W4\u003c/div>\u003cdiv>W5\u003c/div>\u003cdiv>W6\u003c/div>\u003cdiv>W7\u003c/div>\u003cdiv>W8\u003c/div>\u003cdiv>W9\u003c/div>\u003cdiv>W10\u003c/div>\u003cdiv>W11\u003c/div>\u003cdiv>W12\u003c/div>\u003c/div>\n \u003cdiv class=\"row\">\u003cdiv class=\"lbl\">主题系统 (tokens)\u003c/div>\u003cdiv class=\"cells\">\u003cdiv class=\"bar\" style=\"left:0;width:25%\">tokens + 24 themes\u003c/div>\u003c/div>\u003c/div>\n \u003cdiv class=\"row\">\u003cdiv class=\"lbl\">layouts 目录\u003c/div>\u003cdiv class=\"cells\">\u003cdiv class=\"bar\" style=\"left:17%;width:33%\">30 个单页模板\u003c/div>\u003c/div>\u003c/div>\n \u003cdiv class=\"row\">\u003cdiv class=\"lbl\">动画系统\u003c/div>\u003cdiv class=\"cells\">\u003cdiv class=\"bar\" style=\"left:42%;width:25%\">25 个命名动效\u003c/div>\u003c/div>\u003c/div>\n \u003cdiv class=\"row\">\u003cdiv class=\"lbl\">渲染 / CI\u003c/div>\u003cdiv class=\"cells\">\u003cdiv class=\"bar\" style=\"left:58%;width:25%\">render.sh\u003c/div>\u003c/div>\u003c/div>\n \u003cdiv class=\"row\">\u003cdiv class=\"lbl\">发布 & 文档\u003c/div>\u003cdiv class=\"cells\">\u003cdiv class=\"bar\" style=\"left:75%;width:25%\">v1.0\u003c/div>\u003c/div>\u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":2510,"content_sha256":"308c28ae552d90f59c957a033d61b3a37fe5a5cdf9b25940665c291f78e5425a"},{"filename":"templates/single-page/image-compare.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Image Compare\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.cmp{display:grid;grid-template-columns:1fr 1fr;gap:30px;margin-top:26px;flex:1;min-height:0}\n.cmp > div{display:flex;flex-direction:column;min-height:0}\n/* Both sides share the leftover height, so the two shots stay exactly the same\n size — a size difference would read as part of the before/after story. */\n.cmp .img-frame{aspect-ratio:auto;flex:1;min-height:0}\n.cmp .lbl{display:flex;align-items:center;gap:10px;margin:0 0 12px;font-size:15px;font-weight:600;letter-spacing:.02em}\n.cmp .dot{width:10px;height:10px;border-radius:50%}\n.cmp .before .dot{background:var(--text-3)}\n.cmp .after .dot{background:var(--good)}\n.cmp .after .img-frame{box-shadow:var(--shadow-lg)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Image Compare\">\n \u003cp class=\"kicker\">Before / After · 07\u003c/p>\n \u003ch2 class=\"h2\">改版前后,一眼看见差别\u003c/h2>\n \u003cdiv class=\"cmp anim-stagger-list\" data-anim-target>\n \u003cdiv class=\"before\">\n \u003cp class=\"lbl\">\u003cspan class=\"dot\">\u003c/span>改版前 · v2.4\u003c/p>\n \u003cfigure class=\"img-frame\">\u003cimg src=\"../../assets/demo-images/shot-before.svg\" alt=\"改版前界面\">\u003c/figure>\n \u003cp class=\"img-cap\">信息密度高,重点不突出,首屏要滚动两屏才看到指标。\u003c/p>\n \u003c/div>\n \u003cdiv class=\"after\">\n \u003cp class=\"lbl\">\u003cspan class=\"dot\">\u003c/span>改版后 · v3.0\u003c/p>\n \u003cfigure class=\"img-frame\">\u003cimg src=\"../../assets/demo-images/shot-after.svg\" alt=\"改版后界面\">\u003c/figure>\n \u003cp class=\"img-cap\">指标提到首屏,次要信息折叠,平均完成时长下降 38%。\u003c/p>\n \u003c/div>\n \u003c/div>\n \u003cdiv class=\"notes\">两图对照。两侧务必用同一比例、同一拍摄/截图尺寸,否则观众看到的差别里混进了版式差别。结论写在图下一行,不要留给观众猜。\u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":2254,"content_sha256":"7bcf5b41806651f71442923dd9458e8d324b4df8aa9e79813e14f0acbf8dc9a8"},{"filename":"templates/single-page/image-full-bleed.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Image Full Bleed\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.bleed{position:absolute;inset:0}\n.bleed .img-frame{border-radius:0;box-shadow:none;height:100%;aspect-ratio:auto}\n.bleed .cap{position:absolute;left:96px;right:96px;bottom:88px;color:#fff;z-index:2}\n.bleed .cap h1{font-size:84px;line-height:1.02;font-weight:800;letter-spacing:-.03em;margin:0}\n.bleed .cap p{font-size:21px;opacity:.88;margin:16px 0 0;max-width:62ch}\n.bleed .pill{background:rgba(255,255,255,.14);color:#fff;border:1px solid rgba(255,255,255,.24)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Image Full Bleed\" style=\"padding:0\">\n \u003cdiv class=\"bleed\">\n \u003cfigure class=\"img-frame\">\n \u003cimg src=\"../../assets/demo-images/photo-landscape.svg\" alt=\"发布会现场\">\n \u003cdiv class=\"img-scrim\">\u003c/div>\n \u003c/figure>\n \u003cdiv class=\"cap\">\n \u003cspan class=\"pill\">Keynote · 2026\u003c/span>\n \u003ch1 class=\"mt-s anim-rise-in\" data-anim=\"rise-in\">让画面先说话\u003c/h1>\n \u003cp>整页一张图 + 底部渐变压暗,文字永远读得清 —— 换成你自己的照片,版式不用改。\u003c/p>\n \u003c/div>\n \u003c/div>\n \u003cdiv class=\"notes\">整页图:\u003ccode>.img-frame\u003c/code> 不设比例、高度撑满,配 \u003ccode>.img-scrim\u003c/code> 压暗底部保证白字可读。图片主体偏上时加 \u003ccode>style=\"--img-pos:top\"\u003c/code>。\u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1750,"content_sha256":"6982b509b61f8e84fbe8d84fa49eb0ff39e157cf4988528fa88db57f91b05baa"},{"filename":"templates/single-page/image-gallery.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Image Gallery\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.gal{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:22px}\n/* The grid takes the space left over from the title and splits it between two\n equal rows. A fixed ratio (4:3, 16:9…) pushes the bottom row's captions off\n the slide as soon as the window is shorter than 16:9. */\n.gal{flex:1;min-height:0;grid-template-rows:1fr 1fr}\n.gal > div{display:flex;flex-direction:column;min-height:0}\n.gal .img-frame{aspect-ratio:auto;flex:1;min-height:0}\n.gal figcaption{margin:10px 2px 0;font-size:14px;color:var(--text-3)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Image Gallery\">\n \u003cp class=\"kicker\">Gallery · 06\u003c/p>\n \u003ch2 class=\"h2\">多张图并列,每张一句话\u003c/h2>\n \u003cdiv class=\"gal anim-stagger-list\" data-anim-target>\n \u003cdiv>\u003cfigure class=\"img-frame\">\u003cimg src=\"../../assets/demo-images/photo-landscape.svg\" alt=\"场景一\">\u003c/figure>\u003cfigcaption>01 · 现场\u003c/figcaption>\u003c/div>\n \u003cdiv>\u003cfigure class=\"img-frame\">\u003cimg src=\"../../assets/demo-images/photo-square.svg\" alt=\"场景二\">\u003c/figure>\u003cfigcaption>02 · 细节\u003c/figcaption>\u003c/div>\n \u003cdiv>\u003cfigure class=\"img-frame\">\u003cimg src=\"../../assets/demo-images/photo-portrait.svg\" alt=\"场景三\">\u003c/figure>\u003cfigcaption>03 · 人物\u003c/figcaption>\u003c/div>\n \u003cdiv>\u003cfigure class=\"img-frame\">\u003cimg src=\"../../assets/demo-images/photo-wide.svg\" alt=\"场景四\">\u003c/figure>\u003cfigcaption>04 · 远景\u003c/figcaption>\u003c/div>\n \u003cdiv>\u003cfigure class=\"img-frame\">\u003cimg src=\"../../assets/demo-images/shot-ui.svg\" alt=\"场景五\">\u003c/figure>\u003cfigcaption>05 · 界面\u003c/figcaption>\u003c/div>\n \u003cdiv>\u003cfigure class=\"img-frame\">\u003cimg src=\"../../assets/demo-images/shot-after.svg\" alt=\"场景六\">\u003c/figure>\u003cfigcaption>06 · 数据\u003c/figcaption>\u003c/div>\n \u003c/div>\n \u003cdiv class=\"notes\">2–6 张等大并列。六张原始比例各不相同(16:10 / 1:1 / 3:4 / 21:9),靠 \u003ccode>.img-frame\u003c/code> 统一成 4:3 —— 这正是网格版式最容易翻车的地方。少于 6 张就删格子,列数改 \u003ccode>repeat(2,1fr)\u003c/code>。\u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":2471,"content_sha256":"6a943baacb3e8f1a2c1b60e71c503a42b1d4c777db405b1a970f26792d62b186"},{"filename":"templates/single-page/image-grid.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Image Grid\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.gg{display:grid;grid-template-columns:repeat(4,1fr);grid-auto-rows:180px;gap:14px;margin-top:24px}\n.gg .cell{border-radius:var(--radius);overflow:hidden;position:relative;box-shadow:var(--shadow)}\n.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))}\n.gg .c1{background:linear-gradient(135deg,#3b6cff,#7a5cff);grid-column:span 2;grid-row:span 2}\n.gg .c2{background:linear-gradient(135deg,#ff7a90,#ff2742)}\n.gg .c3{background:linear-gradient(135deg,#5ef2c6,#7aa2ff)}\n.gg .c4{background:linear-gradient(135deg,#ffd27a,#f2a341)}\n.gg .c5{background:linear-gradient(135deg,#c984ff,#ff5c8a)}\n.gg .c6{background:linear-gradient(135deg,#0e1530,#24283b)}\n.gg .c7{background:linear-gradient(135deg,#88c0d0,#5ef2c6);grid-column:span 2}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Image Grid\">\n \u003cp class=\"kicker\">Gallery · 作品集\u003c/p>\n \u003ch2 class=\"h2\">一次 bento grid,六张要点图\u003c/h2>\n \u003cdiv class=\"gg anim-stagger-list\" data-anim-target>\n \u003cdiv class=\"cell c1\">\u003cspan>主视觉 · Keynote 封面\u003c/span>\u003c/div>\n \u003cdiv class=\"cell c2\">\u003cspan>暖色 · Stat\u003c/span>\u003c/div>\n \u003cdiv class=\"cell c3\">\u003cspan>冷色 · Flow\u003c/span>\u003c/div>\n \u003cdiv class=\"cell c4\">\u003cspan>日落 · Code\u003c/span>\u003c/div>\n \u003cdiv class=\"cell c5\">\u003cspan>渐变 · Quote\u003c/span>\u003c/div>\n \u003cdiv class=\"cell c6\">\u003cspan>暗色 · Terminal\u003c/span>\u003c/div>\n \u003cdiv class=\"cell c7\">\u003cspan>极光 · CTA\u003c/span>\u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1988,"content_sha256":"6fcf1d7e35151fbb96ae794a9ed11513fb38f9b29758c74550d4fef149bd5544"},{"filename":"templates/single-page/image-hero.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Image Hero\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.hero{position:relative;height:calc(100vh - 144px);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-lg)}\n.hero .bg{position:absolute;inset:0;background:\n radial-gradient(80% 60% at 30% 40%,#ffb38a,transparent 70%),\n radial-gradient(70% 50% at 75% 60%,#c084fc,transparent 70%),\n linear-gradient(135deg,#0b1024,#1a2238)}\n.hero .bg.kb{animation:kf-kenburns 12s ease-in-out infinite alternate}\n.hero .overlay{position:absolute;inset:0;background:linear-gradient(180deg,transparent 40%,rgba(10,12,20,.65));}\n.hero .caption{position:absolute;bottom:48px;left:56px;right:56px;color:#fff;z-index:2}\n.hero h1{font-size:72px;line-height:1;font-weight:800;letter-spacing:-.03em;margin:0}\n.hero p{font-size:20px;opacity:.85;margin:14px 0 0;max-width:60ch}\n.hero .pill{background:rgba(255,255,255,.12);color:#fff;border:1px solid rgba(255,255,255,.2)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Image Hero\" style=\"padding:56px\">\n \u003cdiv class=\"hero\">\n \u003cdiv class=\"bg kb\">\u003c/div>\n \u003cdiv class=\"overlay\">\u003c/div>\n \u003cdiv class=\"caption\">\n \u003cspan class=\"pill\">Cover · 04\u003c/span>\n \u003ch1 class=\"mt-s anim-rise-in\" data-anim=\"rise-in\">像杂志一样的\u003cbr>封面画面感\u003c/h1>\n \u003cp>Ken Burns 缓慢推拉 + 径向渐变 + 中灰叠加。无须真实图片,也能做出高级感。\u003c/p>\n \u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1824,"content_sha256":"c5043568162dd90f8696cd12fddc59a2b2168a07c075d466fc5ce9c6f1cf21a3"},{"filename":"templates/single-page/image-single.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Image Single\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n/* The figure takes whatever height is left after the title — so the slide\n holds together at any window height instead of only at 16:9. */\n.fig{display:flex;flex-direction:column;align-items:center;margin-top:22px;flex:1;min-height:0}\n.fig .img-frame{aspect-ratio:auto;flex:1;min-height:0;width:min(1040px,100%)}\n.fig .img-cap{text-align:center;max-width:70ch}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Image Single\">\n \u003cp class=\"kicker\">Figure · 01\u003c/p>\n \u003ch2 class=\"h2\">一张图讲清楚一件事\u003c/h2>\n \u003cdiv class=\"fig anim-fade-up\" data-anim=\"fade-up\">\n \u003cfigure class=\"img-frame contain\">\n \u003cimg src=\"../../assets/demo-images/shot-ui.svg\" alt=\"产品主界面截图\">\n \u003c/figure>\n \u003cp class=\"img-cap\">图 1 · 新版工作台。左侧是任务流,右侧是实时指标 —— 截图、图表、架构图都用这个版式。\u003c/p>\n \u003c/div>\n \u003cdiv class=\"notes\">单图版式用 \u003ccode>.img-frame.contain\u003c/code>:不裁剪,整张图完整可见。截图 / 示意图 / 图表一律用这个,不要用 cover。\u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1538,"content_sha256":"b0651c55252371fb27ea76ea760d9a1a71d15a0c059b9467dfb61d49b790bad9"},{"filename":"templates/single-page/image-text-split.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Image + Text\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.split{display:grid;grid-template-columns:1fr 1fr;gap:56px;margin-top:18px;flex:1;min-height:0}\n.split.flip > .col-img{order:2}\n.split > div{display:flex;flex-direction:column;justify-content:center;min-height:0}\n/* Height first, width follows the ratio. A tall image can then never push past\n the slide's padding box, whatever its natural aspect ratio is. */\n.split .img-frame{--img-ratio:4/5;height:100%;width:auto;max-width:100%;align-self:center}\n.split ul{margin:18px 0 0;padding-left:20px}\n.split li{margin:10px 0;color:var(--text-2);font-size:19px}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Image + Text\">\n \u003cdiv class=\"split\">\n \u003cdiv class=\"col-img anim-fade-right\" data-anim=\"fade-right\">\n \u003cfigure class=\"img-frame\">\n \u003cimg src=\"../../assets/demo-images/photo-portrait.svg\" alt=\"产品实拍\">\n \u003cspan class=\"img-tag\">Product\u003c/span>\n \u003c/figure>\n \u003c/div>\n \u003cdiv class=\"col-text\">\n \u003cp class=\"kicker\">Product · 03\u003c/p>\n \u003ch2 class=\"h2\">左图右文,最常用的一页\u003c/h2>\n \u003cul class=\"anim-stagger-list\" data-anim-target>\n \u003cli>图占一半,说明占一半 —— 视觉与论述各不抢戏\u003c/li>\n \u003cli>竖图、方图、横图都能放:框决定比例,图自己 \u003ccode>cover\u003c/code>\u003c/li>\n \u003cli>想把图放右边:给 \u003ccode>.split\u003c/code> 加 \u003ccode>flip\u003c/code>\u003c/li>\n \u003c/ul>\n \u003c/div>\n \u003c/div>\n \u003cdiv class=\"notes\">图文各半。框比例由 \u003ccode>--img-ratio\u003c/code> 控制,这里用 4/5 竖构图;图片换成横图也不会破版。\u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":2024,"content_sha256":"457cf77828fbc3ee3f7a1356a83d413f6f7c9cc94bf8165c41e4627f07eec48f"},{"filename":"templates/single-page/kpi-grid.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>KPI Grid\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"KPIs\">\n \u003cp class=\"kicker\">Metrics · 关键数字\u003c/p>\n \u003ch2 class=\"h2\">这一季度,我们做到了什么\u003c/h2>\n \u003cdiv class=\"grid g4 mt-l anim-stagger-list\" data-anim-target>\n \u003cdiv class=\"card\">\u003cp class=\"eyebrow\">Revenue\u003c/p>\u003cdiv style=\"font-size:56px;font-weight:800\">\u003cspan class=\"counter\" data-to=\"1248\">0\u003c/span>K\u003c/div>\u003cp class=\"dim\" style=\"color:var(--good)\">↑ 38% YoY\u003c/p>\u003c/div>\n \u003cdiv class=\"card\">\u003cp class=\"eyebrow\">Active users\u003c/p>\u003cdiv style=\"font-size:56px;font-weight:800\">\u003cspan class=\"counter\" data-to=\"82\">0\u003c/span>K\u003c/div>\u003cp class=\"dim\" style=\"color:var(--good)\">↑ 12% QoQ\u003c/p>\u003c/div>\n \u003cdiv class=\"card\">\u003cp class=\"eyebrow\">Retention\u003c/p>\u003cdiv style=\"font-size:56px;font-weight:800\">\u003cspan class=\"counter\" data-to=\"74\">0\u003c/span>%\u003c/div>\u003cp class=\"dim\" style=\"color:var(--good)\">↑ 3 pts\u003c/p>\u003c/div>\n \u003cdiv class=\"card\">\u003cp class=\"eyebrow\">NPS\u003c/p>\u003cdiv style=\"font-size:56px;font-weight:800\">\u003cspan class=\"counter\" data-to=\"61\">0\u003c/span>\u003c/div>\u003cp class=\"dim\" style=\"color:var(--warn)\">→ 持平\u003c/p>\u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1545,"content_sha256":"c001e9e0bb548b8c6357cd3c353a243353e35bc2e44b36b3b62e6d8ef9252c69"},{"filename":"templates/single-page/mindmap.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Mindmap\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.mm{position:relative;margin:30px auto 0;max-width:1200px;height:520px}\n.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}\n.mm .root{top:calc(50% - 34px);left:calc(50% - 100px);width:200px;padding:22px;background:var(--accent);color:var(--accent-ink);border:none;text-align:center;font-size:20px;border-radius:24px}\n.mm .n.sm{font-size:13px}\n.mm svg{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}\n.mm svg path{stroke:var(--border-strong);stroke-width:1.5;fill:none}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Mindmap\">\n \u003cp class=\"kicker\">Concept map · 心智图\u003c/p>\n \u003ch2 class=\"h2\">html-ppt 的知识地图\u003c/h2>\n \u003cdiv class=\"mm\">\n \u003csvg class=\"anim-path-draw\" viewBox=\"0 0 1200 520\" preserveAspectRatio=\"none\">\n \u003cpath d=\"M600,260 C400,140 280,100 160,90\"/>\n \u003cpath d=\"M600,260 C400,380 280,420 160,430\"/>\n \u003cpath d=\"M600,260 C800,140 920,100 1040,90\"/>\n \u003cpath d=\"M600,260 C800,380 920,420 1040,430\"/>\n \u003cpath d=\"M600,260 C600,140 600,100 600,60\"/>\n \u003cpath d=\"M600,260 C600,380 600,420 600,460\"/>\n \u003c/svg>\n \u003cdiv class=\"n root\">html-ppt\u003c/div>\n \u003cdiv class=\"n\" style=\"top:60px;left:40px\">Themes\u003c/div>\n \u003cdiv class=\"n sm\" style=\"top:410px;left:40px\">Layouts\u003c/div>\n \u003cdiv class=\"n sm\" style=\"top:60px;right:40px\">Animations\u003c/div>\n \u003cdiv class=\"n sm\" style=\"top:410px;right:40px\">Runtime\u003c/div>\n \u003cdiv class=\"n sm\" style=\"top:30px;left:calc(50% - 50px)\">Tokens\u003c/div>\n \u003cdiv class=\"n sm\" style=\"top:450px;left:calc(50% - 60px)\">Render.sh\u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":2130,"content_sha256":"15d2ad1f86719251e0dde87a2645afe10d3260b133f532a565f6c283439c6fac"},{"filename":"templates/single-page/process-steps.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Process Steps\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:22px;margin-top:24px}\n.step{position:relative;padding:24px 26px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);box-shadow:var(--shadow)}\n.step .num{position:absolute;top:-24px;left:22px;width:48px;height:48px;border-radius:50%;background:var(--accent);color:var(--accent-ink);display:flex;align-items:center;justify-content:center;font-weight:800;font-size:20px;box-shadow:var(--shadow)}\n.step h4{margin:18px 0 8px;font-size:17px}\n.step p{font-size:13px;color:var(--text-2);line-height:1.6}\n.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)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Process\">\n \u003cp class=\"kicker\">How-to · 四步做一个 deck\u003c/p>\n \u003ch2 class=\"h2\">从零到一,只需要十分钟\u003c/h2>\n \u003cdiv class=\"steps anim-stagger-list\" data-anim-target>\n \u003cdiv class=\"step\">\u003cdiv class=\"num\">1\u003c/div>\u003ch4>起稿\u003c/h4>\u003cp>运行 \u003ccode>new-deck.sh\u003c/code> 创建脚手架,默认 6 页。\u003c/p>\u003cspan class=\"tag\">~30s\u003c/span>\u003c/div>\n \u003cdiv class=\"step\">\u003cdiv class=\"num\">2\u003c/div>\u003ch4>选版式\u003c/h4>\u003cp>从 \u003ccode>templates/single-page/\u003c/code> 里复制你需要的页型。\u003c/p>\u003cspan class=\"tag\">~2min\u003c/span>\u003c/div>\n \u003cdiv class=\"step\">\u003cdiv class=\"num\">3\u003c/div>\u003ch4>写内容\u003c/h4>\u003cp>替换 demo 数据,保留结构。\u003c/p>\u003cspan class=\"tag\">~6min\u003c/span>\u003c/div>\n \u003cdiv class=\"step\">\u003cdiv class=\"num\">4\u003c/div>\u003ch4>换主题\u003c/h4>\u003cp>按 \u003cb>T\u003c/b> 循环看 24 个主题,挑一个定稿。\u003c/p>\u003cspan class=\"tag\">~1min\u003c/span>\u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":2123,"content_sha256":"00d6ead33799d249ddb67b3f5306599efc38d20309e6c672fab04e226ccf8240"},{"filename":"templates/single-page/pros-cons.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Pros / Cons\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.pc{display:grid;grid-template-columns:1fr 1fr;gap:28px;margin-top:30px}\n.pc .card h3{display:flex;align-items:center;gap:10px}\n.pc .card h3 .b{display:inline-flex;width:36px;height:36px;border-radius:10px;align-items:center;justify-content:center;font-size:20px}\n.pc .pro h3 .b{background:color-mix(in srgb,var(--good) 18%,transparent);color:var(--good)}\n.pc .con h3 .b{background:color-mix(in srgb,var(--bad) 18%,transparent);color:var(--bad)}\n.pc ul{padding-left:22px;line-height:1.8;color:var(--text-2)}\n.pc .pro{border-top:3px solid var(--good)}\n.pc .con{border-top:3px solid var(--bad)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Pros Cons\">\n \u003cp class=\"kicker\">Trade-offs · 诚实的取舍\u003c/p>\n \u003ch2 class=\"h2\">纯 HTML 演讲:好在哪里,痛在哪里\u003c/h2>\n \u003cdiv class=\"pc\">\n \u003cdiv class=\"card pro anim-fade-up\" data-anim=\"fade-up\">\u003ch3>\u003cspan class=\"b\">✓\u003c/span> 好处\u003c/h3>\n \u003cul>\u003cli>零构建:一个文件就能跑\u003c/li>\u003cli>可 diff:Git 友好,好 review\u003c/li>\u003cli>可编程:动效自由定制\u003c/li>\u003cli>可分发:URL / PDF / PNG 都行\u003c/li>\u003c/ul>\n \u003c/div>\n \u003cdiv class=\"card con anim-fade-up\" data-anim=\"fade-up\">\u003ch3>\u003cspan class=\"b\">✗\u003c/span> 痛点\u003c/h3>\n \u003cul>\u003cli>协作不像 Keynote 那样实时\u003c/li>\u003cli>非程序员上手稍陡\u003c/li>\u003cli>复杂动效仍需写 JS\u003c/li>\u003cli>部分字体在离线环境缺失\u003c/li>\u003c/ul>\n \u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1871,"content_sha256":"3b79df7ac312598d460c48a80bc6e8accf27f350ecfb8e5a779f0c5f9de3da9d"},{"filename":"templates/single-page/roadmap.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Roadmap\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.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}\n.rm .col{padding:20px 22px;border-right:1px solid var(--border);background:var(--surface);position:relative}\n.rm .col:last-child{border-right:none}\n.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}\n.rm .col.now{background:color-mix(in srgb,var(--accent) 6%,var(--surface))}\n.rm .col.now .tag{background:var(--accent);color:var(--accent-ink)}\n.rm h4{font-size:15px;margin:8px 0 4px}\n.rm ul{padding-left:18px;margin:8px 0 0;font-size:13px;color:var(--text-2)}\n.rm li{margin-bottom:6px;line-height:1.5}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Roadmap\">\n \u003cp class=\"kicker\">Roadmap · 2026\u003c/p>\n \u003ch2 class=\"h2\">接下来四个季度,我们会做什么\u003c/h2>\n \u003cdiv class=\"rm\">\n \u003cdiv class=\"col now\">\n \u003cspan class=\"tag\">NOW · Q2\u003c/span>\n \u003ch4>主题系统\u003c/h4>\n \u003cul>\u003cli>24 个官方主题\u003c/li>\u003cli>tokens 语义文档\u003c/li>\u003cli>T 键循环切换\u003c/li>\u003c/ul>\n \u003c/div>\n \u003cdiv class=\"col\">\n \u003cspan class=\"tag\">NEXT · Q3\u003c/span>\n \u003ch4>导出\u003c/h4>\n \u003cul>\u003cli>PNG 批量\u003c/li>\u003cli>PDF 打包\u003c/li>\u003cli>小红书 3:4 切片\u003c/li>\u003c/ul>\n \u003c/div>\n \u003cdiv class=\"col\">\n \u003cspan class=\"tag\">LATER · Q4\u003c/span>\n \u003ch4>交互\u003c/h4>\n \u003cul>\u003cli>Presenter 模式\u003c/li>\u003cli>Notes 同屏\u003c/li>\u003cli>遥控器配对\u003c/li>\u003c/ul>\n \u003c/div>\n \u003cdiv class=\"col\">\n \u003cspan class=\"tag\">VISION\u003c/span>\n \u003ch4>AI 写稿\u003c/h4>\n \u003cul>\u003cli>从 md 自动分页\u003c/li>\u003cli>智能选版式\u003c/li>\u003cli>智能选主题\u003c/li>\u003c/ul>\n \u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":2191,"content_sha256":"84b9970bca1948a933e35294dac99052eb2d6e355ce62a84415f3ac503e0961c"},{"filename":"templates/single-page/section-divider.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Section Divider\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active tc center\" data-title=\"Section 02\">\n \u003cdiv style=\"max-width:780px;margin:0 auto\">\n \u003cp class=\"kicker anim-fade-down\" data-anim=\"fade-down\">Section · 02\u003c/p>\n \u003ch1 class=\"h1 anim-rise-in\" data-anim=\"rise-in\" style=\"font-size:112px\">主题与 \u003cspan class=\"gradient-text\">Tokens\u003c/span>\u003c/h1>\n \u003cdiv class=\"divider-accent\" style=\"margin:24px auto\">\u003c/div>\n \u003cp class=\"lede\" style=\"margin:0 auto\">换主题 = 换一份 CSS 变量。其他一切保持不变。\u003c/p>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":989,"content_sha256":"3fefdd2240707a1a6cda7f875456108ed93cb55359dcf00d92c556656688ade7"},{"filename":"templates/single-page/stat-highlight.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Stat Highlight\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active center tc\" data-title=\"Stat\">\n \u003cp class=\"kicker\">Impact · 一个数字\u003c/p>\n \u003cdiv style=\"font-size:260px;line-height:1;font-weight:900;letter-spacing:-.05em\">\n \u003cspan class=\"counter gradient-text\" data-to=\"92\">0\u003c/span>\u003cspan class=\"gradient-text\">%\u003c/span>\n \u003c/div>\n \u003ch3 class=\"mt-s\">的准备时间被你省下\u003c/h3>\n \u003cp class=\"lede\" style=\"margin:16px auto 0\">在 10 个真实项目中,使用 html-ppt 的平均 deck 制作时间从 4 小时降到了 20 分钟。\u003c/p>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":989,"content_sha256":"b638b0fbf09221ad7d39ba338560f6ea037d9e6fdc9ab0a93757ddadb277d9dd"},{"filename":"templates/single-page/table.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Table\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.t{width:100%;border-collapse:collapse;font-size:16px}\n.t th,.t td{padding:14px 16px;text-align:left;border-bottom:1px solid var(--border)}\n.t th{font-size:12px;text-transform:uppercase;letter-spacing:.1em;color:var(--text-3);font-weight:600}\n.t tr:hover td{background:var(--surface-2)}\n.t td.num{font-variant-numeric:tabular-nums;text-align:right}\n.up{color:var(--good)}.dn{color:var(--bad)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Table\">\n \u003cp class=\"kicker\">Comparison · 数据表\u003c/p>\n \u003ch2 class=\"h2\">主流 HTML 演讲框架对比\u003c/h2>\n \u003cdiv class=\"card mt-l\" style=\"padding:4px 12px\">\n \u003ctable class=\"t\">\n \u003cthead>\u003ctr>\u003cth>框架\u003c/th>\u003cth>学习曲线\u003c/th>\u003cth>自定义\u003c/th>\u003cth class=\"num\">体积\u003c/th>\u003cth class=\"num\">GitHub ⭐\u003c/th>\u003cth>适合\u003c/th>\u003c/tr>\u003c/thead>\n \u003ctbody>\n \u003ctr>\u003ctd>\u003cb>html-ppt\u003c/b>\u003c/td>\u003ctd>极低\u003c/td>\u003ctd>★★★★★\u003c/td>\u003ctd class=\"num\">~80 KB\u003c/td>\u003ctd class=\"num\">—\u003c/td>\u003ctd>快速出稿、换主题\u003c/td>\u003c/tr>\n \u003ctr>\u003ctd>reveal.js\u003c/td>\u003ctd>低\u003c/td>\u003ctd>★★★★\u003c/td>\u003ctd class=\"num\">~450 KB\u003c/td>\u003ctd class=\"num\">67k\u003c/td>\u003ctd>长讲座、互动\u003c/td>\u003c/tr>\n \u003ctr>\u003ctd>Slidev\u003c/td>\u003ctd>中\u003c/td>\u003ctd>★★★★★\u003c/td>\u003ctd class=\"num\">需构建\u003c/td>\u003ctd class=\"num\">31k\u003c/td>\u003ctd>开发者、技术分享\u003c/td>\u003c/tr>\n \u003ctr>\u003ctd>Marp\u003c/td>\u003ctd>极低\u003c/td>\u003ctd>★★\u003c/td>\u003ctd class=\"num\">~10 MB\u003c/td>\u003ctd class=\"num\">13k\u003c/td>\u003ctd>Markdown 出稿\u003c/td>\u003c/tr>\n \u003ctr>\u003ctd>Impress.js\u003c/td>\u003ctd>中\u003c/td>\u003ctd>★★★\u003c/td>\u003ctd class=\"num\">~60 KB\u003c/td>\u003ctd class=\"num\">38k\u003c/td>\u003ctd>3D 展示\u003c/td>\u003c/tr>\n \u003c/tbody>\n \u003c/table>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":2040,"content_sha256":"ae31373b9457d2776c6807ad87b602155b39296749c3c59a37ba98b14f008229"},{"filename":"templates/single-page/terminal.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Terminal\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/terminal-green.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.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}\n.term .bar{display:flex;gap:6px;margin-bottom:16px}\n.term .bar span{width:12px;height:12px;border-radius:50%;background:#222;border:1px solid rgba(0,255,136,.3)}\n.term .p{color:var(--accent)}\n.term .c{color:var(--text-1)}\n.term .o{color:var(--text-2)}\n.term .caret{display:inline-block;width:9px;height:18px;background:var(--accent);vertical-align:middle;animation:blink 1s step-end infinite}\n@keyframes blink{50%{opacity:0}}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Terminal\">\n \u003cp class=\"kicker\">CLI · 一行命令起一个 deck\u003c/p>\n \u003ch2 class=\"h2\" style=\"color:var(--text-1)\">你需要的就是一个终端\u003c/h2>\n \u003cdiv class=\"term mt-l\">\n \u003cdiv class=\"bar\">\u003cspan>\u003c/span>\u003cspan>\u003c/span>\u003cspan>\u003c/span>\u003c/div>\n \u003cdiv>\u003cspan class=\"p\">$ \u003c/span>\u003cspan class=\"c\">./scripts/new-deck.sh graphify-talk\u003c/span>\u003c/div>\n \u003cdiv class=\"o\"> ✔ created decks/graphify-talk/index.html\u003c/div>\n \u003cdiv class=\"o\"> ✔ linked theme → aurora\u003c/div>\n \u003cdiv class=\"o\"> ✔ 12 slides scaffolded from templates/single-page/*\u003c/div>\n \u003cdiv style=\"margin-top:12px\">\u003cspan class=\"p\">$ \u003c/span>\u003cspan class=\"c\">open decks/graphify-talk/index.html\u003c/span>\u003c/div>\n \u003cdiv class=\"o\"> ↗ launched in Chrome\u003c/div>\n \u003cdiv style=\"margin-top:12px\">\u003cspan class=\"p\">$ \u003c/span>\u003cspan class=\"c\">./scripts/render.sh decks/graphify-talk/index.html\u003c/span>\u003c/div>\n \u003cdiv class=\"o\"> ✔ wrote graphify-talk.png (1920×1080)\u003c/div>\n \u003cdiv style=\"margin-top:12px\">\u003cspan class=\"p\">$ \u003c/span>\u003cspan class=\"caret\">\u003c/span>\u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":2182,"content_sha256":"1cd7ecaae72f096e89b38611232163c48fb12ff1fc7131a1326858d3fa6ed39a"},{"filename":"templates/single-page/thanks.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Thanks\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active center tc\" data-title=\"Thanks\">\n \u003cdiv>\n \u003cdiv class=\"anim-confetti-burst\" style=\"display:inline-block;padding:40px\">\u003c/div>\n \u003ch1 class=\"h1 anim-fade-up\" data-anim=\"fade-up\" style=\"font-size:180px;line-height:1\">\u003cspan class=\"gradient-text\">Thanks\u003c/span>\u003c/h1>\n \u003cp class=\"lede\" style=\"margin:18px auto 0\">愿你每一次上台,都少一点紧张,多一点从容。\u003c/p>\n \u003cdiv class=\"row mt-l\" style=\"justify-content:center;gap:32px\">\n \u003cdiv class=\"dim\">\u003cb>lewis\u003c/b> · [email protected]\u003c/div>\n \u003cdiv class=\"dim\">github.com/lewis/html-ppt\u003c/div>\n \u003cdiv class=\"dim\">2026 · MIT\u003c/div>\n \u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1132,"content_sha256":"a1deed0b8122b72cb14dd0d5cbfaf2dbb58ea6524688072b926fd19bc999076a"},{"filename":"templates/single-page/three-column.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Three Column\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Three column\">\n \u003cp class=\"kicker\">Pillars · 三根支柱\u003c/p>\n \u003ch2 class=\"h2\">一个 html-ppt,三件装备\u003c/h2>\n \u003cdiv class=\"grid g3 mt-l anim-stagger-list\" data-anim-target>\n \u003cdiv class=\"card\">\u003cdiv style=\"font-size:40px\">🎨\u003c/div>\u003ch4 class=\"mt-s\">Themes\u003c/h4>\u003cp class=\"dim\">克制 · 编辑 · 霓虹 · 终端 …… 随场景换装。\u003c/p>\u003c/div>\n \u003cdiv class=\"card\">\u003cdiv style=\"font-size:40px\">🧱\u003c/div>\u003ch4 class=\"mt-s\">Layouts\u003c/h4>\u003cp class=\"dim\">30 种页型,从封面到结语一次给齐。\u003c/p>\u003c/div>\n \u003cdiv class=\"card\">\u003cdiv style=\"font-size:40px\">✨\u003c/div>\u003ch4 class=\"mt-s\">Animations\u003c/h4>\u003cp class=\"dim\">25 个命名动效,每一个都克制、每一个都上台。\u003c/p>\u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1233,"content_sha256":"6c751cb3fa639928df442e1cccab91d9565168d2e76244c562802145503b1e87"},{"filename":"templates/single-page/timeline.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Timeline\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.tl{position:relative;margin-top:40px}\n.tl::before{content:\"\";position:absolute;left:0;right:0;top:48px;height:2px;background:var(--border)}\n.tl .row{display:grid;grid-template-columns:repeat(5,1fr);gap:22px;align-items:start}\n.tl .item{position:relative;padding-top:80px;text-align:center}\n.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)}\n.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}\n.tl h4{font-size:18px}\n.tl p{font-size:13px;color:var(--text-2)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Timeline\">\n \u003cp class=\"kicker\">Roadmap · 时间线\u003c/p>\n \u003ch2 class=\"h2\">html-ppt 是怎么长大的\u003c/h2>\n \u003cdiv class=\"tl\">\n \u003cdiv class=\"row anim-stagger-list\" data-anim-target>\n \u003cdiv class=\"item\">\u003cdiv class=\"year\">2025 Q3\u003c/div>\u003cdiv class=\"dot\">\u003c/div>\u003ch4>起源\u003c/h4>\u003cp>一套个人 reveal.js 模板\u003c/p>\u003c/div>\n \u003cdiv class=\"item\">\u003cdiv class=\"year\">2025 Q4\u003c/div>\u003cdiv class=\"dot\">\u003c/div>\u003ch4>tokens 化\u003c/h4>\u003cp>把颜色全部收进 :root\u003c/p>\u003c/div>\n \u003cdiv class=\"item\">\u003cdiv class=\"year\">2026 Q1\u003c/div>\u003cdiv class=\"dot\">\u003c/div>\u003ch4>Agent 接入\u003c/h4>\u003cp>开放为 AgentSkill\u003c/p>\u003c/div>\n \u003cdiv class=\"item\">\u003cdiv class=\"year\">2026 Q2\u003c/div>\u003cdiv class=\"dot\">\u003c/div>\u003ch4>24 themes\u003c/h4>\u003cp>从克制到霓虹一应俱全\u003c/p>\u003c/div>\n \u003cdiv class=\"item\">\u003cdiv class=\"year\">2026 Q3\u003c/div>\u003cdiv class=\"dot\">\u003c/div>\u003ch4>渲染管线\u003c/h4>\u003cp>headless Chrome PNG 出稿\u003c/p>\u003c/div>\n \u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":2130,"content_sha256":"5e424003fb97bb59fe732768c2bc40451902cd6800bbc4dd49f84c6e95e02652"},{"filename":"templates/single-page/toc.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\" data-theme=\"minimal-white\">\n\u003chead>\n\u003cmeta charset=\"utf-8\">\u003ctitle>Table of Contents\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003c/head>\n\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\n\u003csection class=\"slide is-active\" data-title=\"Contents\">\n \u003cp class=\"eyebrow\">Contents · 目录\u003c/p>\n \u003ch2 class=\"h2\">今天的五件事\u003c/h2>\n \u003cdiv class=\"grid g2 mt-l anim-stagger-list\" data-anim-target>\n \u003cdiv class=\"card\">\u003cdiv class=\"row\">\u003cdiv class=\"h3 dim2\" style=\"width:56px\">01\u003c/div>\u003cdiv>\u003ch4>为什么需要设计系统\u003c/h4>\u003cp class=\"dim\">从模板到 token,减少重复。\u003c/p>\u003c/div>\u003c/div>\u003c/div>\n \u003cdiv class=\"card\">\u003cdiv class=\"row\">\u003cdiv class=\"h3 dim2\" style=\"width:56px\">02\u003c/div>\u003cdiv>\u003ch4>主题与 tokens\u003c/h4>\u003cp class=\"dim\">24 个可切换的主题,一键换装。\u003c/p>\u003c/div>\u003c/div>\u003c/div>\n \u003cdiv class=\"card\">\u003cdiv class=\"row\">\u003cdiv class=\"h3 dim2\" style=\"width:56px\">03\u003c/div>\u003cdiv>\u003ch4>版式目录\u003c/h4>\u003cp class=\"dim\">30 种单页类型,覆盖 95% 场景。\u003c/p>\u003c/div>\u003c/div>\u003c/div>\n \u003cdiv class=\"card\">\u003cdiv class=\"row\">\u003cdiv class=\"h3 dim2\" style=\"width:56px\">04\u003c/div>\u003cdiv>\u003ch4>入场动效\u003c/h4>\u003cp class=\"dim\">25 种命名动画,可挑可组合。\u003c/p>\u003c/div>\u003c/div>\u003c/div>\n \u003cdiv class=\"card\" style=\"grid-column:span 2\">\u003cdiv class=\"row\">\u003cdiv class=\"h3 dim2\" style=\"width:56px\">05\u003c/div>\u003cdiv>\u003ch4>现场演示 & 问答\u003c/h4>\u003cp class=\"dim\">打开模板就能讲。\u003c/p>\u003c/div>\u003c/div>\u003c/div>\n \u003c/div>\n \u003cdiv class=\"deck-footer\">\u003cspan class=\"dim2\">html-ppt\u003c/span>\u003cspan>目录\u003c/span>\u003c/div>\n\u003c/section>\n\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1814,"content_sha256":"ddddd908a2014424a4cd032cd39c202583a7cadcc1e4b223491969eeacdd6bda"},{"filename":"templates/single-page/todo-checklist.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Checklist\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003cstyle>\n.todo{max-width:820px;margin-top:26px}\n.todo li{list-style:none;display:flex;align-items:flex-start;gap:14px;padding:14px 18px;border-bottom:1px solid var(--border)}\n.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}\n.todo li.done .b{background:var(--good);border-color:var(--good);color:#fff}\n.todo li.done .b::after{content:\"✓\";font-weight:900}\n.todo li.done .t{text-decoration:line-through;color:var(--text-3)}\n.todo li .t{font-size:18px}\n.todo li .tag{margin-left:auto;font-size:12px;color:var(--text-3)}\n\u003c/style>\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Checklist\">\n \u003cp class=\"kicker\">Launch · 上线前检查清单\u003c/p>\n \u003ch2 class=\"h2\">发版前必过的 8 件事\u003c/h2>\n \u003cul class=\"todo anim-stagger-list\" data-anim-target>\n \u003cli class=\"done\">\u003cspan class=\"b\">\u003c/span>\u003cspan class=\"t\">所有 slide 在 Chrome 打开无控制台报错\u003c/span>\u003cspan class=\"tag\">#sanity\u003c/span>\u003c/li>\n \u003cli class=\"done\">\u003cspan class=\"b\">\u003c/span>\u003cspan class=\"t\">字体回退链路正确(Noto Sans SC)\u003c/span>\u003cspan class=\"tag\">#fonts\u003c/span>\u003c/li>\n \u003cli class=\"done\">\u003cspan class=\"b\">\u003c/span>\u003cspan class=\"t\">24 个主题各选一页截图比对\u003c/span>\u003cspan class=\"tag\">#themes\u003c/span>\u003c/li>\n \u003cli class=\"done\">\u003cspan class=\"b\">\u003c/span>\u003cspan class=\"t\">键盘导航全键通\u003c/span>\u003cspan class=\"tag\">#runtime\u003c/span>\u003c/li>\n \u003cli>\u003cspan class=\"b\">\u003c/span>\u003cspan class=\"t\">PDF 打印不跨页裁切\u003c/span>\u003cspan class=\"tag\">#print\u003c/span>\u003c/li>\n \u003cli>\u003cspan class=\"b\">\u003c/span>\u003cspan class=\"t\">render.sh 对每个 showcase 跑通\u003c/span>\u003cspan class=\"tag\">#ci\u003c/span>\u003c/li>\n \u003cli>\u003cspan class=\"b\">\u003c/span>\u003cspan class=\"t\">references/*.md 通读一遍\u003c/span>\u003cspan class=\"tag\">#docs\u003c/span>\u003c/li>\n \u003cli>\u003cspan class=\"b\">\u003c/span>\u003cspan class=\"t\">LICENSE / README 作者信息核对\u003c/span>\u003cspan class=\"tag\">#legal\u003c/span>\u003c/li>\n \u003c/ul>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":2406,"content_sha256":"434559de5f083491fdaff601f8fcaadb65fb601d0ec065c045b532f1eaac9314"},{"filename":"templates/single-page/two-column.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\u003chead>\u003cmeta charset=\"utf-8\">\u003ctitle>Two Column\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/base.css\">\n\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../../assets/themes/minimal-white.css\">\n\u003clink rel=\"stylesheet\" href=\"../../assets/animations/animations.css\">\n\u003c/head>\u003cbody class=\"single\">\n\u003cdiv class=\"deck\">\u003csection class=\"slide is-active\" data-title=\"Two column\">\n \u003cp class=\"kicker\">Pattern · 双栏\u003c/p>\n \u003ch2 class=\"h2\">概念 \u003cspan class=\"dim2\">⟷\u003c/span> 示例\u003c/h2>\n \u003cdiv class=\"grid g2 mt-l\" style=\"align-items:start\">\n \u003cdiv class=\"card anim-fade-left\" data-anim=\"fade-left\">\n \u003ch3>左栏 · 概念\u003c/h3>\n \u003cp class=\"dim\">一个主题 = 一组 CSS 变量。把颜色、字体、圆角、阴影全部收到 \u003ccode>:root\u003c/code> 里。\u003c/p>\n \u003cul class=\"mt-m\">\n \u003cli>— tokens 定义语义,不写具体色值\u003c/li>\n \u003cli>— base.css 用 tokens 排版\u003c/li>\n \u003cli>— 每个主题只改变量\u003c/li>\n \u003c/ul>\n \u003c/div>\n \u003cdiv class=\"card anim-fade-right\" data-anim=\"fade-right\">\n \u003ch3>右栏 · 示例\u003c/h3>\n\u003cpre class=\"mono\" style=\"font-size:13px;background:var(--surface-2);padding:14px;border-radius:var(--radius-sm);overflow:auto\">\n:root {\n --bg: #fff;\n --text-1: #0c0d10;\n --accent: #3b6cff;\n --radius: 18px;\n}\n.card {\n background: var(--bg);\n color: var(--text-1);\n border-radius: var(--radius);\n}\u003c/pre>\n \u003c/div>\n \u003c/div>\n\u003c/section>\u003c/div>\n\u003cscript src=\"../../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":1552,"content_sha256":"8246257fc2866d35f2113a3ec4eb0c329fe3d4ab5908c613ff2e801fde638267"},{"filename":"templates/theme-showcase.html","content":"\u003c!DOCTYPE html>\n\u003chtml lang=\"zh-CN\">\n\u003chead>\n\u003cmeta charset=\"utf-8\">\u003ctitle>Theme Showcase — html-ppt v2\u003c/title>\n\u003clink rel=\"stylesheet\" href=\"../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../assets/base.css\">\n\u003clink rel=\"stylesheet\" href=\"../assets/animations/animations.css\">\n\u003cstyle>\n /* NOTE: theme isolation via \u003ciframe srcdoc> per slide. Each slide loads base.css\n + its OWN theme.css, so pressing → actually shows a different look. */\n html,body{background:#0b0c10;color:#e8ebf4}\n .deck{background:#0b0c10}\n .slide{padding:0;background:transparent}\n .theme-frame{\n position:absolute;inset:0;width:100%;height:100%;\n border:0;background:#fff;\n }\n .theme-chrome{\n position:absolute;top:22px;left:40px;right:40px;display:flex;justify-content:space-between;\n font-family:'JetBrains Mono',monospace;font-size:12px;color:#aab0c0;letter-spacing:.12em;\n text-transform:uppercase;z-index:20;pointer-events:none;mix-blend-mode:difference;\n }\n .theme-chrome .name{color:#fff;font-weight:700}\n\u003c/style>\n\u003c/head>\n\u003cbody>\n\u003cdiv class=\"deck\">\u003c/div>\n\n\u003cscript>\n/* 36 themes total (24 v1 + 12 v2). Each rendered in its OWN iframe so CSS is isolated. */\nconst THEMES = [\n ['minimal-white', '极简白 · clean restraint'],\n ['editorial-serif', '杂志衬线 · high editorial'],\n ['soft-pastel', '马卡龙 · soft pastel'],\n ['sharp-mono', '黑白高对比 · sharp mono'],\n ['arctic-cool', '冷色调 · arctic'],\n ['sunset-warm', '暖色调 · sunset'],\n ['catppuccin-latte', 'Catppuccin Latte'],\n ['catppuccin-mocha', 'Catppuccin Mocha'],\n ['dracula', 'Dracula'],\n ['tokyo-night', 'Tokyo Night'],\n ['nord', 'Nord · nordic cool'],\n ['solarized-light', 'Solarized Light'],\n ['gruvbox-dark', 'Gruvbox Dark'],\n ['rose-pine', 'Rose Pine'],\n ['neo-brutalism', 'Neo-Brutalism'],\n ['glassmorphism', 'Glassmorphism'],\n ['bauhaus', 'Bauhaus 几何原色'],\n ['swiss-grid', 'Swiss Grid'],\n ['terminal-green', 'Terminal Green'],\n ['xiaohongshu-white', '小红书白底'],\n ['rainbow-gradient', 'Rainbow Gradient'],\n ['aurora', 'Aurora 极光'],\n ['blueprint', 'Blueprint 蓝图'],\n ['memphis-pop', 'Memphis Pop'],\n /* v2 additions */\n ['cyberpunk-neon', 'Cyberpunk Neon 霓虹'],\n ['y2k-chrome', 'Y2K Chrome 镜面'],\n ['retro-tv', 'Retro TV CRT 扫描线'],\n ['japanese-minimal', '和风极简 · 朱红'],\n ['vaporwave', 'Vaporwave 蒸汽波'],\n ['midcentury', 'Mid-Century Modern'],\n ['corporate-clean', 'Corporate Clean 商务'],\n ['academic-paper', '学术白皮书'],\n ['news-broadcast', 'News Broadcast 新闻'],\n ['pitch-deck-vc', 'Pitch Deck VC / YC'],\n ['magazine-bold', 'Magazine Bold 大字杂志'],\n ['engineering-whiteprint','Engineering Whiteprint']\n];\n\n/* The demo content that each iframe will render. Uses tokens only, so it picks up\n whatever theme the iframe loads. Self-contained — no external references. */\nfunction demoHTML(themeName, label){\n return `\u003c!doctype html>\u003chtml>\u003chead>\u003cmeta charset=\"utf-8\">\n\u003clink rel=\"stylesheet\" href=\"../assets/fonts.css\">\n\u003clink rel=\"stylesheet\" href=\"../assets/base.css\">\n\u003clink rel=\"stylesheet\" href=\"../assets/themes/${themeName}.css\">\n\u003clink rel=\"stylesheet\" href=\"../assets/animations/animations.css\">\n\u003cstyle>\n html,body{height:100%}\n .wrap{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;\n padding:72px 96px;box-sizing:border-box;background:var(--bg);color:var(--text-1);\n font-family:var(--font-sans)}\n .swatch{display:flex;gap:10px;margin-top:18px}\n .swatch div{width:44px;height:44px;border-radius:10px;border:1px solid var(--border)}\n .kpi{font-size:54px;font-weight:800;letter-spacing:-.02em}\n .mini-code{font-family:var(--font-mono);font-size:11px;background:var(--surface-2);\n padding:10px 12px;border-radius:8px;margin:6px 0 0;white-space:pre;color:var(--text-1);\n border:1px solid var(--border)}\n\u003c/style>\n\u003c/head>\u003cbody>\u003cdiv class=\"wrap\">\n \u003cp class=\"kicker\">Theme · ${themeName}\u003c/p>\n \u003ch1 class=\"h1\">${label}\u003c/h1>\n \u003cp class=\"lede\">Same demo slide, different tokens. Background, type, accent, radius, shadow all come from \u003ccode>assets/themes/${themeName}.css\u003c/code>.\u003c/p>\n \u003cdiv class=\"grid g3 mt-l\">\n \u003cdiv class=\"card\">\n \u003ch4>Palette · 调色盘\u003c/h4>\n \u003cp class=\"dim\">accent / accent-2 / accent-3 / text / surface-2\u003c/p>\n \u003cdiv class=\"swatch\">\n \u003cdiv style=\"background:var(--accent)\">\u003c/div>\n \u003cdiv style=\"background:var(--accent-2)\">\u003c/div>\n \u003cdiv style=\"background:var(--accent-3)\">\u003c/div>\n \u003cdiv style=\"background:var(--text-1)\">\u003c/div>\n \u003cdiv style=\"background:var(--surface-2)\">\u003c/div>\n \u003c/div>\n \u003c/div>\n \u003cdiv class=\"card\">\n \u003ch4>KPI\u003c/h4>\n \u003cdiv class=\"kpi gradient-text\">2.4K\u003c/div>\n \u003cp class=\"dim\">上周月活 · weekly active\u003c/p>\n \u003c/div>\n \u003cdiv class=\"card\">\n \u003ch4>Code · 令牌\u003c/h4>\n \u003cpre class=\"mini-code\">:root {\n --accent: /* theme */;\n --radius: /* theme */;\n}\u003c/pre>\n \u003c/div>\n \u003c/div>\n \u003cdiv class=\"row mt-m\" style=\"gap:10px;flex-wrap:wrap\">\n \u003cspan class=\"pill\">#tokens\u003c/span>\n \u003cspan class=\"pill pill-accent\">primary\u003c/span>\n \u003cspan class=\"pill\">#radius\u003c/span>\n \u003cspan class=\"pill\">#shadow\u003c/span>\n \u003cspan class=\"pill\">#type\u003c/span>\n \u003c/div>\n\u003c/div>\u003c/body>\u003c/html>`;\n}\n\n(function(){\n const deck = document.querySelector('.deck');\n THEMES.forEach((t,i)=>{\n const s = document.createElement('section');\n s.className = 'slide';\n s.setAttribute('data-title', t[0]);\n const chrome = `\u003cdiv class=\"theme-chrome\">\u003cspan class=\"name\">${String(i+1).padStart(2,'0')} · ${t[0]}\u003c/span>\u003cspan>${i+1}/${THEMES.length}\u003c/span>\u003c/div>`;\n const iframe = document.createElement('iframe');\n iframe.className = 'theme-frame';\n iframe.setAttribute('loading','eager');\n // Use src via data URL for the inline demo HTML so relative paths still resolve from the templates/ dir.\n // Easier: use srcdoc but set \u003cbase href> to the templates dir so relative ../assets paths work.\n const base = `\u003cbase href=\"${location.href}\">`;\n iframe.srcdoc = demoHTML(t[0], t[1]).replace('\u003chead>','\u003chead>'+base);\n s.innerHTML = chrome;\n s.appendChild(iframe);\n deck.appendChild(s);\n });\n})();\n\u003c/script>\n\u003cscript src=\"../assets/runtime.js\">\u003c/script>\n\u003c/body>\u003c/html>\n","content_type":"text/html; charset=utf-8","language":"markup","size":6456,"content_sha256":"6068323b3d82e1994370d86c20a76a9b76fda2bd5fad1e3e32367fd15c6fb4e1"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"html-ppt — HTML PPT Studio","type":"text"}]},{"type":"paragraph","content":[{"text":"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 ","type":"text"},{"text":"assets/base.css","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Install","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"npx skills add https://github.com/lewislulu/html-ppt-skill","type":"text"}]},{"type":"paragraph","content":[{"text":"One command, no build. Pure static HTML/CSS/JS with only CDN webfonts.","type":"text"}]},{"type":"paragraph","content":[{"text":"No network on the target machine? Point the CLI at a local copy (","type":"text"},{"text":"npx skills add ./html-ppt-skill","type":"text","marks":[{"type":"code_inline"}]},{"text":"), or just copy this folder into your agent's skills directory — ","type":"text"},{"text":"~/.claude/skills/html-ppt/","type":"text","marks":[{"type":"code_inline"}]},{"text":" for Claude Code. Decks render offline; only the webfonts fall back to the system stack. See ","type":"text"},{"text":"README.md","type":"text","marks":[{"type":"link","attrs":{"href":"README.md#offline--manual-install","title":null}}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"What the skill gives you","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"36 themes","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"assets/themes/*.css","type":"text","marks":[{"type":"code_inline"}]},{"text":") — 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, cyberpunk-neon, y2k-chrome, retro-tv, japanese-minimal, vaporwave, midcentury, corporate-clean, academic-paper, news-broadcast, pitch-deck-vc, magazine-bold, engineering-whiteprint","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"15 full-deck templates","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"templates/full-decks/\u003cname>/","type":"text","marks":[{"type":"code_inline"}]},{"text":") — complete multi-slide decks with scoped ","type":"text"},{"text":".tpl-\u003cname>","type":"text","marks":[{"type":"code_inline"}]},{"text":" CSS. 8 extracted from real-world decks (xhs-white-editorial, graphify-dark-graph, knowledge-arch-blueprint, hermes-cyber-terminal, obsidian-claude-gradient, testing-safety-alert, xhs-pastel-card, dir-key-nav-minimal), 7 scenario scaffolds (pitch-deck, product-launch, tech-sharing, weekly-report, xhs-post 3:4, course-module, ","type":"text"},{"text":"presenter-mode-reveal","type":"text","marks":[{"type":"strong"}]},{"text":" — 演讲者模式专用)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"36 layouts","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"templates/single-page/*.html","type":"text","marks":[{"type":"code_inline"}]},{"text":") with realistic demo data, including ","type":"text"},{"text":"5 real-image layouts","type":"text","marks":[{"type":"strong"}]},{"text":" (single / full-bleed / image+text / gallery / before-after)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"27 CSS animations","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"assets/animations/animations.css","type":"text","marks":[{"type":"code_inline"}]},{"text":") via ","type":"text"},{"text":"data-anim","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"20 canvas FX animations","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"assets/animations/fx/*.js","type":"text","marks":[{"type":"code_inline"}]},{"text":") via ","type":"text"},{"text":"data-fx","type":"text","marks":[{"type":"code_inline"}]},{"text":" — particle-burst, confetti-cannon, firework, starfield, matrix-rain, knowledge-graph (force-directed), neural-net (pulses), constellation, orbit-ring, galaxy-swirl, word-cascade, letter-explode, chain-react, magnetic-field, data-stream, gradient-blob, sparkle-trail, shockwave, typewriter-multi, counter-explosion","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Keyboard runtime","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"assets/runtime.js","type":"text","marks":[{"type":"code_inline"}]},{"text":") — arrows, T (theme), A (anim), F/O, ","type":"text"},{"text":"S (presenter mode: magnetic-card popup with CURRENT / NEXT / SCRIPT / TIMER cards)","type":"text","marks":[{"type":"strong"}]},{"text":", N (notes drawer), R (reset timer in presenter)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Touch navigation","type":"text","marks":[{"type":"strong"}]},{"text":" — swipe left/right to change slides on phones and tablets","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"FX runtime","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"assets/animations/fx-runtime.js","type":"text","marks":[{"type":"code_inline"}]},{"text":") — auto-inits ","type":"text"},{"text":"[data-fx]","type":"text","marks":[{"type":"code_inline"}]},{"text":" on slide enter, cleans up on leave","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Showcase decks","type":"text","marks":[{"type":"strong"}]},{"text":" for themes / layouts / animations / full-decks gallery","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Headless Chrome render script","type":"text","marks":[{"type":"strong"}]},{"text":" for PNG export","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When to use","type":"text"}]},{"type":"paragraph","content":[{"text":"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.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"🎤 Presenter Mode (演讲者模式 + 逐字稿)","type":"text"}]},{"type":"paragraph","content":[{"text":"If the user mentions any of: ","type":"text"},{"text":"演讲 / 分享 / 讲稿 / 逐字稿 / speaker notes / presenter view / 演讲者视图 / 提词器","type":"text","marks":[{"type":"strong"}]},{"text":", or says things like \"我要去给团队讲 xxx\", \"要做一场技术分享\", \"怕讲不流畅\", \"想要一份带逐字稿的 PPT\" — ","type":"text"},{"text":"use the ","type":"text","marks":[{"type":"strong"}]},{"text":"presenter-mode-reveal","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" full-deck template","type":"text","marks":[{"type":"strong"}]},{"text":" and write 150–300 words of 逐字稿 in each slide's ","type":"text"},{"text":"\u003caside class=\"notes\">","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/presenter-mode.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/presenter-mode.md","title":null}}]},{"text":" for the full authoring guide including the 3 rules of speaker script writing:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"不是讲稿,是提示信号","type":"text","marks":[{"type":"strong"}]},{"text":" — 加粗核心词 + 过渡句独立成段","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"每页 150–300 字","type":"text","marks":[{"type":"strong"}]},{"text":" — 2–3 分钟/页的节奏","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"用口语,不用书面语","type":"text","marks":[{"type":"strong"}]},{"text":" — \"因此\"→\"所以\",\"该方案\"→\"这个方案\"","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"All full-deck templates support the S key presenter mode (it's built into ","type":"text"},{"text":"runtime.js","type":"text","marks":[{"type":"code_inline"}]},{"text":"). ","type":"text"},{"text":"S opens a new popup window with 4 magnetic cards","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"🔵 ","type":"text"},{"text":"CURRENT","type":"text","marks":[{"type":"strong"}]},{"text":" — pixel-perfect iframe preview of the current slide","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"🟣 ","type":"text"},{"text":"NEXT","type":"text","marks":[{"type":"strong"}]},{"text":" — pixel-perfect iframe preview of the next slide","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"🟠 ","type":"text"},{"text":"SPEAKER SCRIPT","type":"text","marks":[{"type":"strong"}]},{"text":" — large-font 逐字稿 (scrollable)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"🟢 ","type":"text"},{"text":"TIMER","type":"text","marks":[{"type":"strong"}]},{"text":" — elapsed time + slide counter + prev/next/reset buttons","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Each card is ","type":"text"},{"text":"draggable by its header","type":"text","marks":[{"type":"strong"}]},{"text":" and ","type":"text"},{"text":"resizable by the bottom-right corner handle","type":"text","marks":[{"type":"strong"}]},{"text":". Card positions/sizes persist to ","type":"text"},{"text":"localStorage","type":"text","marks":[{"type":"code_inline"}]},{"text":" per deck. A \"Reset layout\" button restores the default arrangement.","type":"text"}]},{"type":"paragraph","content":[{"text":"Why the previews are pixel-perfect","type":"text","marks":[{"type":"strong"}]},{"text":": each preview is an ","type":"text"},{"text":"\u003ciframe>","type":"text","marks":[{"type":"code_inline"}]},{"text":" that loads the actual deck HTML with a ","type":"text"},{"text":"?preview=N","type":"text","marks":[{"type":"code_inline"}]},{"text":" query param; ","type":"text"},{"text":"runtime.js","type":"text","marks":[{"type":"code_inline"}]},{"text":" detects this and renders only slide N with no chrome. So the preview uses the ","type":"text"},{"text":"same CSS, theme, fonts, and viewport as the audience view","type":"text","marks":[{"type":"strong"}]},{"text":" — colors and layout are guaranteed identical.","type":"text"}]},{"type":"paragraph","content":[{"text":"Smooth navigation","type":"text","marks":[{"type":"strong"}]},{"text":": on slide change, the presenter window sends ","type":"text"},{"text":"postMessage({type:'preview-goto', idx:N})","type":"text","marks":[{"type":"code_inline"}]},{"text":" to each iframe. The iframe just toggles ","type":"text"},{"text":".is-active","type":"text","marks":[{"type":"code_inline"}]},{"text":" between slides — ","type":"text"},{"text":"no reload, no flicker","type":"text","marks":[{"type":"strong"}]},{"text":". The two windows also stay in sync via ","type":"text"},{"text":"BroadcastChannel","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"Only ","type":"text"},{"text":"presenter-mode-reveal","type":"text","marks":[{"type":"code_inline"}]},{"text":" is designed from the ground up around the feature with proper example 逐字稿 on every slide.","type":"text"}]},{"type":"paragraph","content":[{"text":"Keyboard in presenter window: ","type":"text"},{"text":"← →","type":"text","marks":[{"type":"code_inline"}]},{"text":" navigate (syncs audience) · ","type":"text"},{"text":"R","type":"text","marks":[{"type":"code_inline"}]},{"text":" reset timer · ","type":"text"},{"text":"Esc","type":"text","marks":[{"type":"code_inline"}]},{"text":" close popup. Keyboard in audience window: ","type":"text"},{"text":"S","type":"text","marks":[{"type":"code_inline"}]},{"text":" open presenter · ","type":"text"},{"text":"T","type":"text","marks":[{"type":"code_inline"}]},{"text":" cycle theme · ","type":"text"},{"text":"← →","type":"text","marks":[{"type":"code_inline"}]},{"text":" navigate (syncs presenter) · ","type":"text"},{"text":"F","type":"text","marks":[{"type":"code_inline"}]},{"text":" fullscreen · ","type":"text"},{"text":"O","type":"text","marks":[{"type":"code_inline"}]},{"text":" overview.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Before you author anything — ALWAYS ask or recommend","type":"text"}]},{"type":"paragraph","content":[{"text":"Do not start writing slides until you understand three things.","type":"text","marks":[{"type":"strong"}]},{"text":" Either ask the user directly, or — if they already handed you rich content — propose a tasteful default and confirm.","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Content & audience.","type":"text","marks":[{"type":"strong"}]},{"text":" What's the deck about, how many slides, who's watching (engineers / execs / 小红书读者 / 学生 / VC)?","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Style / theme.","type":"text","marks":[{"type":"strong"}]},{"text":" Which of the 36 themes fits? If unsure, recommend 2-3 candidates based on tone:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Business / investor pitch → ","type":"text"},{"text":"pitch-deck-vc","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"corporate-clean","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"swiss-grid","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tech sharing / engineering → ","type":"text"},{"text":"tokyo-night","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"dracula","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"catppuccin-mocha","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"terminal-green","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"blueprint","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"小红书图文 → ","type":"text"},{"text":"xiaohongshu-white","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"soft-pastel","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"rainbow-gradient","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"magazine-bold","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Academic / report → ","type":"text"},{"text":"academic-paper","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"editorial-serif","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"minimal-white","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Edgy / cyber / launch → ","type":"text"},{"text":"cyberpunk-neon","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"vaporwave","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"y2k-chrome","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"neo-brutalism","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Starting point.","type":"text","marks":[{"type":"strong"}]},{"text":" One of the 15 full-deck templates, or scratch? Point to the closest ","type":"text"},{"text":"templates/full-decks/\u003cname>/","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ask if it fits. If the user's content suggests something obvious (e.g. \"我要做产品发布会\" → ","type":"text"},{"text":"product-launch","type":"text","marks":[{"type":"code_inline"}]},{"text":"), propose it confidently instead of asking blindly.","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"A good opening message looks like:","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"我可以给你做这份 PPT!先确认三件事:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"大致内容 / 页数 / 观众是谁?","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"风格偏好?我建议从这 3 个主题里选一个:","type":"text"},{"text":"tokyo-night","type":"text","marks":[{"type":"code_inline"}]},{"text":"(技术分享默认好看)、","type":"text"},{"text":"xiaohongshu-white","type":"text","marks":[{"type":"code_inline"}]},{"text":"(小红书风)、","type":"text"},{"text":"corporate-clean","type":"text","marks":[{"type":"code_inline"}]},{"text":"(正式汇报)。","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"要不要用我现成的 ","type":"text"},{"text":"tech-sharing","type":"text","marks":[{"type":"code_inline"}]},{"text":" 全 deck 模板打底?","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Only after those are clear, scaffold the deck and start writing.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Quick start","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Scaffold a new deck.","type":"text","marks":[{"type":"strong"}]},{"text":" From the repo root:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"./scripts/new-deck.sh my-talk\nopen examples/my-talk/index.html","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Pick a theme.","type":"text","marks":[{"type":"strong"}]},{"text":" Open the deck and press ","type":"text"},{"text":"T","type":"text","marks":[{"type":"code_inline"}]},{"text":" to cycle. Or hard-code it (","type":"text"},{"text":"../assets/","type":"text","marks":[{"type":"code_inline"}]},{"text":" here is a placeholder — use whatever prefix the rest of the file already uses; ","type":"text"},{"text":"new-deck.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" has set it to the right depth):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"html"},"content":[{"text":"\u003clink rel=\"stylesheet\" id=\"theme-link\" href=\"../assets/themes/aurora.css\">","type":"text"}]},{"type":"paragraph","content":[{"text":"Catalog in ","type":"text"},{"text":"references/themes.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/themes.md","title":null}}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Pick layouts.","type":"text","marks":[{"type":"strong"}]},{"text":" Copy ","type":"text"},{"text":"\u003csection class=\"slide\">...\u003c/section>","type":"text","marks":[{"type":"code_inline"}]},{"text":" blocks out of files in ","type":"text"},{"text":"templates/single-page/","type":"text","marks":[{"type":"code_inline"}]},{"text":" into your deck. Replace the demo data. Catalog in ","type":"text"},{"text":"references/layouts.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/layouts.md","title":null}}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Add animations.","type":"text","marks":[{"type":"strong"}]},{"text":" Put ","type":"text"},{"text":"data-anim=\"fade-up\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" (or ","type":"text"},{"text":"class=\"anim-fade-up\"","type":"text","marks":[{"type":"code_inline"}]},{"text":") on any element. On ","type":"text"},{"text":"\u003cul>","type":"text","marks":[{"type":"code_inline"}]},{"text":"/grids, use ","type":"text"},{"text":"anim-stagger-list","type":"text","marks":[{"type":"code_inline"}]},{"text":" for sequenced reveals. For canvas FX, use ","type":"text"},{"text":"\u003cdiv data-fx=\"knowledge-graph\">...\u003c/div>","type":"text","marks":[{"type":"code_inline"}]},{"text":" and include ","type":"text"},{"text":"\u003cscript src=\"../assets/animations/fx-runtime.js\">\u003c/script>","type":"text","marks":[{"type":"code_inline"}]},{"text":". Catalog in ","type":"text"},{"text":"references/animations.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/animations.md","title":null}}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use a full-deck template.","type":"text","marks":[{"type":"strong"}]},{"text":" Scaffold from it, don't copy it by hand — the template's ","type":"text"},{"text":"../../../assets/","type":"text","marks":[{"type":"code_inline"}]},{"text":" is relative to ","type":"text"},{"text":"its own","type":"text","marks":[{"type":"em"}]},{"text":" location, so a manual copy lands the paths at the wrong depth:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"./scripts/new-deck.sh my-talk -t pitch-deck","type":"text"}]},{"type":"paragraph","content":[{"text":"Each folder is self-contained with scoped CSS. Catalog in ","type":"text"},{"text":"references/full-decks.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/full-decks.md","title":null}}]},{"text":" and gallery at ","type":"text"},{"text":"templates/full-decks-index.html","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Render to PNG.","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"./scripts/render.sh templates/theme-showcase.html # one shot\n./scripts/render.sh examples/my-talk/index.html 12 # 12 slides","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Authoring rules (important)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Always start from a template.","type":"text","marks":[{"type":"strong"}]},{"text":" Don't author slides from scratch — copy the closest layout from ","type":"text"},{"text":"templates/single-page/","type":"text","marks":[{"type":"code_inline"}]},{"text":" first, then replace content.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use tokens, not literal colors.","type":"text","marks":[{"type":"strong"}]},{"text":" Every color, radius, shadow should come from CSS variables defined in ","type":"text"},{"text":"assets/base.css","type":"text","marks":[{"type":"code_inline"}]},{"text":" and overridden by a theme. Good: ","type":"text"},{"text":"color: var(--text-1)","type":"text","marks":[{"type":"code_inline"}]},{"text":". Bad: ","type":"text"},{"text":"color: #111","type":"text","marks":[{"type":"code_inline"}]},{"text":". Text on top of an ","type":"text"},{"text":"--accent","type":"text","marks":[{"type":"code_inline"}]},{"text":" fill is the one people get wrong: it needs ","type":"text"},{"text":"color: var(--accent-ink)","type":"text","marks":[{"type":"code_inline"}]},{"text":", because accents here run from ","type":"text"},{"text":"#ffffff","type":"text","marks":[{"type":"code_inline"}]},{"text":" to ","type":"text"},{"text":"#000000","type":"text","marks":[{"type":"code_inline"}]},{"text":" and no literal ink is readable on all of them.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Don't invent new layout files.","type":"text","marks":[{"type":"strong"}]},{"text":" Prefer composing existing ones. Only add a new ","type":"text"},{"text":"templates/single-page/*.html","type":"text","marks":[{"type":"code_inline"}]},{"text":" if none of the 36 fit.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Putting images on a slide?","type":"text","marks":[{"type":"strong"}]},{"text":" Start from one of the five ","type":"text"},{"text":"image-*","type":"text","marks":[{"type":"code_inline"}]},{"text":" layouts and use ","type":"text"},{"text":".img-frame","type":"text","marks":[{"type":"code_inline"}]},{"text":" — see ","type":"text"},{"text":"Images","type":"text","marks":[{"type":"em"}]},{"text":" below. Never drop a bare ","type":"text"},{"text":"\u003cimg>","type":"text","marks":[{"type":"code_inline"}]},{"text":" into a slide: an unframed image ignores the slide's height and pushes the rest off the page.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Respect chrome slots.","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":".deck-header","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":".deck-footer","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":".slide-number","type":"text","marks":[{"type":"code_inline"}]},{"text":" and the progress bar are provided by ","type":"text"},{"text":"assets/base.css","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"runtime.js","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Add a logo declaratively, once.","type":"text","marks":[{"type":"strong"}]},{"text":" Put ","type":"text"},{"text":"data-logo","type":"text","marks":[{"type":"code_inline"}]},{"text":" on ","type":"text"},{"text":"\u003cbody>","type":"text","marks":[{"type":"code_inline"}]},{"text":" — don't paste an ","type":"text"},{"text":"\u003cimg>","type":"text","marks":[{"type":"code_inline"}]},{"text":" into every slide. See ","type":"text"},{"text":"Custom logo","type":"text","marks":[{"type":"em"}]},{"text":" below.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Keyboard-first.","type":"text","marks":[{"type":"strong"}]},{"text":" Always include the runtime, e.g. ","type":"text"},{"text":"\u003cscript src=\"../assets/runtime.js\">\u003c/script>","type":"text","marks":[{"type":"code_inline"}]},{"text":", so the deck supports ← → / T / A / F / S / O / hash deep-links.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never hand-edit the ","type":"text","marks":[{"type":"strong"}]},{"text":"../","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" depth in asset paths.","type":"text","marks":[{"type":"strong"}]},{"text":" Every ","type":"text"},{"text":"assets/","type":"text","marks":[{"type":"code_inline"}]},{"text":" reference is relative to the file that holds it: ","type":"text"},{"text":"templates/deck.html","type":"text","marks":[{"type":"code_inline"}]},{"text":" uses ","type":"text"},{"text":"../assets/","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"templates/single-page/*.html","type":"text","marks":[{"type":"code_inline"}]},{"text":" use ","type":"text"},{"text":"../../assets/","type":"text","marks":[{"type":"code_inline"}]},{"text":", and ","type":"text"},{"text":"templates/full-decks/*/index.html","type":"text","marks":[{"type":"code_inline"}]},{"text":" use ","type":"text"},{"text":"../../../assets/","type":"text","marks":[{"type":"code_inline"}]},{"text":". Copying a file to a new depth silently breaks all of them. Scaffold with ","type":"text"},{"text":"./scripts/new-deck.sh \u003cname> [parent] [-t \u003ctemplate>]","type":"text","marks":[{"type":"code_inline"}]},{"text":", which computes the prefix for wherever the deck lands and verifies every reference resolves.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"One ","type":"text","marks":[{"type":"strong"}]},{"text":".slide","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" per logical page.","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"runtime.js","type":"text","marks":[{"type":"code_inline"}]},{"text":" makes ","type":"text"},{"text":".slide.is-active","type":"text","marks":[{"type":"code_inline"}]},{"text":" visible; all others are hidden.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Supply notes.","type":"text","marks":[{"type":"strong"}]},{"text":" Wrap speaker notes in ","type":"text"},{"text":"\u003cdiv class=\"notes\">…\u003c/div>","type":"text","marks":[{"type":"code_inline"}]},{"text":" inside each slide. Press S to open the overlay.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"NEVER put presenter-only text on the slide itself.","type":"text","marks":[{"type":"strong"}]},{"text":" Descriptive text like \"这一页展示了……\" or \"Speaker: 这里可以补充……\" or small explanatory captions aimed at the presenter MUST go inside ","type":"text"},{"text":"\u003cdiv class=\"notes\">","type":"text","marks":[{"type":"code_inline"}]},{"text":", NOT as visible ","type":"text"},{"text":"\u003cp>","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"\u003cspan>","type":"text","marks":[{"type":"code_inline"}]},{"text":" elements on the slide. The ","type":"text"},{"text":".notes","type":"text","marks":[{"type":"code_inline"}]},{"text":" class is ","type":"text"},{"text":"display:none","type":"text","marks":[{"type":"code_inline"}]},{"text":" by default — it only appears in the S overlay. Slides should contain ONLY audience-facing content (titles, bullet points, data, charts, images).","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Images","type":"text"}]},{"type":"paragraph","content":[{"text":"Five layouts in ","type":"text"},{"text":"templates/single-page/","type":"text","marks":[{"type":"code_inline"}]},{"text":" take real images. Pick by how many images the page has to carry:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"I have…","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Why","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"one screenshot / diagram / chart","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"image-single.html","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":".img-frame.contain","type":"text","marks":[{"type":"code_inline"}]},{"text":" — letterboxed, ","type":"text"},{"text":"never cropped","type":"text","marks":[{"type":"strong"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"one photo that should carry the page","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"image-full-bleed.html","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"fills the slide, gradient scrim keeps the title readable","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"one image plus an argument","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"image-text-split.html","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"50/50; add ","type":"text"},{"text":"flip","type":"text","marks":[{"type":"code_inline"}]},{"text":" to ","type":"text"},{"text":".split","type":"text","marks":[{"type":"code_inline"}]},{"text":" to move the image right","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"3–6 images","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"image-gallery.html","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"uniform grid; mixed source ratios are normalised by the frame","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"a before and an after","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"image-compare.html","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"both sides identical size, conclusion under each","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"image-grid.html","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"image-hero.html","type":"text","marks":[{"type":"code_inline"}]},{"text":" are ","type":"text"},{"text":"not","type":"text","marks":[{"type":"strong"}]},{"text":" in this list: they are gradient-placeholder layouts with no ","type":"text"},{"text":"\u003cimg>","type":"text","marks":[{"type":"code_inline"}]},{"text":" at all. Reach for them when you want the shape of a bento wall without supplying pictures.","type":"text"}]},{"type":"paragraph","content":[{"text":"All five are built on one primitive from ","type":"text"},{"text":"assets/base.css","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"html"},"content":[{"text":"\u003cfigure class=\"img-frame\">\u003cimg src=\"shot.png\" alt=\"\">\u003c/figure>\n\u003cfigure class=\"img-frame contain\" style=\"--img-ratio:4/3\">\u003cimg src=\"diagram.svg\" alt=\"\">\u003c/figure>","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":".img-frame","type":"text","marks":[{"type":"code_inline"}]},{"text":" owns the ","type":"text"},{"text":"aspect ratio and the crop","type":"text","marks":[{"type":"strong"}]},{"text":"; the ","type":"text"},{"text":"\u003cimg>","type":"text","marks":[{"type":"code_inline"}]},{"text":" fills it with ","type":"text"},{"text":"object-fit: cover","type":"text","marks":[{"type":"code_inline"}]},{"text":". That's what lets a user swap in a photo of any shape without the layout breaking.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":".img-frame.contain","type":"text","marks":[{"type":"code_inline"}]},{"text":" letterboxes instead of cropping — ","type":"text"},{"text":"always use it for screenshots, diagrams and logos.","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"--img-ratio","type":"text","marks":[{"type":"code_inline"}]},{"text":" (default ","type":"text"},{"text":"16/10","type":"text","marks":[{"type":"code_inline"}]},{"text":") and ","type":"text"},{"text":"--img-pos","type":"text","marks":[{"type":"code_inline"}]},{"text":" (","type":"text"},{"text":"object-position","type":"text","marks":[{"type":"code_inline"}]},{"text":") tune it.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":".img-scrim","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":".img-cap","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":".img-tag","type":"text","marks":[{"type":"code_inline"}]},{"text":" are the scrim, caption and corner pill.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Images referenced from a deck are resolved relative to the deck's own ","type":"text"},{"text":"index.html","type":"text","marks":[{"type":"code_inline"}]},{"text":" — keep them in the deck folder, e.g. ","type":"text"},{"text":"examples/my-talk/shot.png","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"assets/demo-images/","type":"text","marks":[{"type":"code_inline"}]},{"text":" holds the placeholder artwork used by these layouts: hand-written SVG, ~1 KB each, ","type":"text"},{"text":"no network needed","type":"text","marks":[{"type":"strong"}]},{"text":".","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Custom logo","type":"text"}]},{"type":"paragraph","content":[{"text":"To brand a deck with a company / product logo, declare it once on ","type":"text"},{"text":"\u003cbody>","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"html"},"content":[{"text":"\u003cbody data-logo=\"logo.svg\"\n data-logo-position=\"bottom-right\"\n data-logo-size=\"40px\">","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Attribute","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Default","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Notes","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"data-logo","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"—","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Image URL, relative to the deck's own HTML file. Required.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"data-logo-position","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"top-right","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"top-left","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"top-right","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"bottom-left","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"bottom-right","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"data-logo-size","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"44px","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Any CSS length; sets the logo's ","type":"text"},{"text":"height","type":"text","marks":[{"type":"strong"}]},{"text":", width follows the aspect ratio","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"data-logo-opacity","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":".9","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"1","type":"text","marks":[{"type":"code_inline"}]},{"text":" for full strength","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"data-logo-alt","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"\"","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Alt text","type":"text"}]}]}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Skip it on one slide","type":"text","marks":[{"type":"strong"}]},{"text":" with ","type":"text"},{"text":"\u003csection class=\"slide\" data-no-logo>","type":"text","marks":[{"type":"code_inline"}]},{"text":" — usually the cover and any full-bleed image slide that carries its own branding.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Fine-tune the inset","type":"text","marks":[{"type":"strong"}]},{"text":" with ","type":"text"},{"text":"--logo-inset-x","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"--logo-inset-y","type":"text","marks":[{"type":"code_inline"}]},{"text":" on ","type":"text"},{"text":".deck-logo","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Place it by hand","type":"text","marks":[{"type":"strong"}]},{"text":" instead, if you want it inside the chrome slots or in a spot the four presets don't cover:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"html"},"content":[{"text":"\u003cdiv class=\"deck\">\n \u003cimg class=\"deck-logo\" data-pos=\"bottom-left\" src=\"logo.svg\" alt=\"\">","type":"text"}]},{"type":"paragraph","content":[{"text":"This path needs no JS at all — ","type":"text"},{"text":"base.css","type":"text","marks":[{"type":"code_inline"}]},{"text":" styles both the same way.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"The logo shows in the ","type":"text"},{"text":"presenter preview","type":"text","marks":[{"type":"strong"}]},{"text":", and on ","type":"text"},{"text":"every page of a print/PDF export","type":"text","marks":[{"type":"strong"}]},{"text":" (unlike the header/footer/progress chrome, which print hides). ","type":"text"},{"text":"data-no-logo","type":"text","marks":[{"type":"code_inline"}]},{"text":" slides are skipped there too. Per-page printing is painted by ","type":"text"},{"text":"runtime.js","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"@media print","type":"text","marks":[{"type":"code_inline"}]},{"text":"; a deck that omits the runtime still gets the logo on screen, but only on one page of a PDF.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Writing guide","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/authoring-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/authoring-guide.md","title":null}}]},{"text":" 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.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Catalogs (load when needed)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/themes.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/themes.md","title":null}}]},{"text":" — all 36 themes with when-to-use.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/layouts.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/layouts.md","title":null}}]},{"text":" — all 36 layout types.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/animations.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/animations.md","title":null}}]},{"text":" — 27 CSS + 20 canvas FX animations.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/full-decks.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/full-decks.md","title":null}}]},{"text":" — all 15 full-deck templates.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/presenter-mode.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/presenter-mode.md","title":null}}]},{"text":" — ","type":"text"},{"text":"演讲者模式 + 逐字稿编写指南(技术分享/演讲必看)","type":"text","marks":[{"type":"strong"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/authoring-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/authoring-guide.md","title":null}}]},{"text":" — full workflow.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"File structure","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"html-ppt/\n├── SKILL.md (this file)\n├── references/ (detailed catalogs, load as needed)\n├── assets/\n│ ├── base.css (tokens + primitives — do not edit per deck)\n│ ├── demo-images/*.svg (tiny offline placeholders for the image-* layouts)\n│ ├── fonts.css (webfont imports)\n│ ├── runtime.js (keyboard + presenter + overview + theme cycle)\n│ ├── themes/*.css (36 token overrides, one per theme)\n│ └── animations/\n│ ├── animations.css (27 named CSS entry animations)\n│ ├── fx-runtime.js (auto-init [data-fx] on slide enter)\n│ └── fx/*.js (20 canvas FX modules: particles/graph/fireworks…)\n├── templates/\n│ ├── deck.html (minimal 6-slide starter)\n│ ├── theme-showcase.html (36 slides, iframe-isolated per theme)\n│ ├── layout-showcase.html (iframe tour of all 36 layouts)\n│ ├── animation-showcase.html (20 FX + 27 CSS animation slides)\n│ ├── full-decks-index.html (gallery of all 15 full-deck templates)\n│ ├── full-decks/\u003cname>/ (15 scoped multi-slide deck templates)\n│ └── single-page/*.html (36 layout files with demo data)\n├── scripts/\n│ ├── new-deck.sh (scaffold a deck from deck.html)\n│ └── render.sh (headless Chrome → PNG)\n└── examples/demo-deck/ (complete working deck)","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Rendering to PNG","type":"text"}]},{"type":"paragraph","content":[{"text":"scripts/render.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" wraps headless Chrome at ","type":"text"},{"text":"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","type":"text","marks":[{"type":"code_inline"}]},{"text":". For multi-slide capture, runtime.js exposes ","type":"text"},{"text":"#/N","type":"text","marks":[{"type":"code_inline"}]},{"text":" deep-links, and render.sh iterates 1..N.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"./scripts/render.sh templates/single-page/kpi-grid.html # single page\n./scripts/render.sh examples/demo-deck/index.html 8 out-dir # 8 slides, custom dir","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Keyboard cheat sheet","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"← → Space PgUp PgDn Home End navigate\nswipe left / right (touch) navigate — phones and tablets, no keyboard needed\nF fullscreen\nS open presenter window (magnetic cards: current/next/script/timer)\nN quick notes drawer (bottom overlay)\nR reset timer (in presenter window)\n?preview=N URL param — force preview-only mode (single slide, no chrome)\nO slide overview grid\nT cycle themes (reads data-themes attr)\nA cycle demo animation on current slide\n#/N in URL deep-link to slide N\nEsc close all overlays","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"License & author","type":"text"}]},{"type":"paragraph","content":[{"text":"MIT. Copyright (c) 2026 lewis \[email protected]>.","type":"text"}]}]},"metadata":{"date":"2026-11-02","name":"html-ppt","author":"@skillopedia","source":{"stars":8952,"repo_name":"html-ppt-skill","origin_url":"https://github.com/lewislulu/html-ppt-skill/blob/HEAD/SKILL.md","repo_owner":"lewislulu","body_sha256":"d30ff36b80424e2d19df9bf99f0bd4c9573335740ae8674f046b876c74193d86","cluster_key":"65bae2fac2ebcf9c6ba4f3b4d0d4aaa868f1256531521aeb0752dda6f4dab4ec","clean_bundle":{"format":"clean-skill-bundle-v1","source":"lewislulu/html-ppt-skill/SKILL.md","text_bytes":286196,"source_commit":"fd1629067909ff55b36b905476de4e5f26062a1f","skills_sh_rank":1448,"attachment_count":100,"text_attachments":100,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"documents-office","category_label":"Documents"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"documents-office","import_tag":"skills-sh-top20k-2026-11","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\"."}},"renderedAt":1793676229276}

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 . Install One command, no build. Pure static HTML/CSS/JS with only CDN webfonts. No network on the target machine? Point the CLI at a local copy ( ), or just copy this folder into your agent's skills directory — for Claude Code. Decks render offline; only the webfonts fall back to the system stack. See README.md. What the skill gives you - 36 themes ( ) — minimal-whi…