first-commit
ci / Validate workspace (push) Has been cancelled
landing-page-ci / Validate landing page (push) Has been cancelled
landing-page-deploy / Deploy landing page (push) Has been cancelled
github-metrics / Generate repository metrics SVG (push) Has been cancelled
refresh-contributors-wall / Refresh contributors wall cache bust (push) Waiting to run
ci / Validate workspace (push) Has been cancelled
landing-page-ci / Validate landing page (push) Has been cancelled
landing-page-deploy / Deploy landing page (push) Has been cancelled
github-metrics / Generate repository metrics SVG (push) Has been cancelled
refresh-contributors-wall / Refresh contributors wall cache bust (push) Waiting to run
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-theme="aurora">
|
||||
<head>
|
||||
<meta charset="utf-8"><title>Animation + FX Showcase — html-ppt</title>
|
||||
<link rel="stylesheet" href="../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../assets/themes/aurora.css">
|
||||
<link rel="stylesheet" href="../assets/animations/animations.css">
|
||||
<style>
|
||||
.fx-stage{
|
||||
position:relative;
|
||||
margin:20px auto 0;
|
||||
width:min(900px, 92%);
|
||||
height:380px;
|
||||
border-radius:var(--radius-lg, 16px);
|
||||
background:rgba(10,12,22,0.55);
|
||||
border:1px solid var(--border,#2a2a3a);
|
||||
box-shadow:var(--shadow-lg, 0 20px 60px rgba(0,0,0,.4));
|
||||
overflow:hidden;
|
||||
}
|
||||
.fx-label{
|
||||
position:absolute;top:14px;left:16px;z-index:5;
|
||||
font-family:var(--font-mono, ui-monospace,Menlo,monospace);
|
||||
font-size:11px;letter-spacing:.14em;color:var(--text-3,#a0a0b8);
|
||||
text-transform:uppercase;
|
||||
background:rgba(0,0,0,0.35);padding:4px 10px;border-radius:999px;
|
||||
border:1px solid rgba(255,255,255,0.08);
|
||||
}
|
||||
.fx-replay{
|
||||
position:absolute;top:12px;right:14px;z-index:5;
|
||||
appearance:none;cursor:pointer;
|
||||
padding:7px 14px;border-radius:999px;
|
||||
background:linear-gradient(135deg, var(--accent,#7c5cff), var(--accent-2,#22d3ee));
|
||||
color:#fff;font:600 12px system-ui,sans-serif;
|
||||
border:0;letter-spacing:.05em;
|
||||
box-shadow:0 4px 16px rgba(124,92,255,0.35);
|
||||
}
|
||||
.fx-replay:hover{ filter:brightness(1.1); transform:translateY(-1px); }
|
||||
.fx-indicator{position:absolute;top:24px;right:40px;font-family:var(--font-mono);font-size:11px;color:var(--text-3);letter-spacing:.1em}
|
||||
.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)}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="deck"></div>
|
||||
|
||||
<script>
|
||||
const FX = [
|
||||
['particle-burst', 'Particles explode from center, gravity + fade, re-bursts every ~2.5s.'],
|
||||
['confetti-cannon', 'Colored rotating rects arcing from both bottom corners.'],
|
||||
['firework', 'Rockets launch from the bottom and burst into colored sparks.'],
|
||||
['starfield', '3D perspective starfield — infinite flythrough.'],
|
||||
['matrix-rain', 'Classic green katakana + hex columns raining down.'],
|
||||
['knowledge-graph', 'Force-directed graph, 28 labeled nodes, live physics + springs.'],
|
||||
['neural-net', '4-6-6-3 feedforward net with pulses traveling along edges.'],
|
||||
['constellation', 'Drifting points connect when close — ambient background.'],
|
||||
['orbit-ring', '5 concentric rings with dots rotating at different speeds.'],
|
||||
['galaxy-swirl', 'Logarithmic spiral with ~800 particles.'],
|
||||
['word-cascade', 'Words fall from top and pile up at the bottom.'],
|
||||
['letter-explode', 'Letters fly in from random directions, loops.'],
|
||||
['chain-react', 'Row of 8 circles — a wave pulse dominoes across them.'],
|
||||
['magnetic-field', 'Particles follow sine curves leaving gradient trails.'],
|
||||
['data-stream', 'Rows of scrolling hex/binary text, cyberpunk feel.'],
|
||||
['gradient-blob', '4 drifting blurred radial gradients (additive blending).'],
|
||||
['sparkle-trail', 'Sparkles emit at your cursor (auto-wiggles if idle).'],
|
||||
['shockwave', 'Expanding rings emanating from center, looping.'],
|
||||
['typewriter-multi', 'Three lines typing concurrently with blinking block cursors.'],
|
||||
['counter-explosion', 'Number counts 0 → 2400, bursts particles, resets.']
|
||||
];
|
||||
|
||||
const CSS_ANIMS = [
|
||||
['fade-up','Translate from +32 px, fade.'],
|
||||
['fade-down','Translate from -32 px, fade.'],
|
||||
['fade-left','From left.'],
|
||||
['fade-right','From right.'],
|
||||
['rise-in','Rise + blur-off.'],
|
||||
['drop-in','Drop from above.'],
|
||||
['zoom-pop','Elastic scale pop.'],
|
||||
['blur-in','Blur clears.'],
|
||||
['glitch-in','Glitch jitter.'],
|
||||
['typewriter','Typewriter reveal.'],
|
||||
['neon-glow','Neon pulse.'],
|
||||
['shimmer-sweep','Sheen sweep.'],
|
||||
['gradient-flow','Gradient flow.'],
|
||||
['stagger-list','Staggered children.'],
|
||||
['counter-up','Number tick.'],
|
||||
['path-draw','SVG strokes draw.'],
|
||||
['parallax-tilt','3D hover tilt.'],
|
||||
['card-flip-3d','Y-axis flip.'],
|
||||
['cube-rotate-3d','Cube rotate.'],
|
||||
['page-turn-3d','Page turn.'],
|
||||
['perspective-zoom','Pull from -400 Z.'],
|
||||
['marquee-scroll','Infinite marquee.'],
|
||||
['kenburns','Ken Burns zoom.'],
|
||||
['confetti-burst','Pseudo confetti.'],
|
||||
['spotlight','Circular clip reveal.'],
|
||||
['morph-shape','SVG d morph.'],
|
||||
['ripple-reveal','Corner ripple.']
|
||||
];
|
||||
|
||||
const deck = document.querySelector('.deck');
|
||||
const total = FX.length + CSS_ANIMS.length;
|
||||
|
||||
// Build FX slides (1..20)
|
||||
FX.forEach((f, i) => {
|
||||
const idx = i + 1;
|
||||
const [name, desc] = f;
|
||||
const sec = document.createElement('section');
|
||||
sec.className = 'slide';
|
||||
sec.setAttribute('data-title', 'fx / ' + name);
|
||||
|
||||
const extraAttrs = name === 'letter-explode'
|
||||
? 'data-fx-text-value="' + name.toUpperCase() + '"'
|
||||
: name === 'counter-explosion'
|
||||
? 'data-fx-to="2400"'
|
||||
: name === 'typewriter-multi'
|
||||
? 'data-fx-line1="> initializing knowledge graph..." data-fx-line2="> loading 28 concept nodes" data-fx-line3="> agent ready. awaiting prompt_"'
|
||||
: '';
|
||||
|
||||
sec.innerHTML = `
|
||||
<span class="fx-indicator">${idx}/${total}</span>
|
||||
<p class="kicker">FX · canvas · ${String(idx).padStart(2,'0')}</p>
|
||||
<h1 class="h1"><span class="gradient-text">${name}</span></h1>
|
||||
<p class="lede">${desc}</p>
|
||||
<div class="fx-stage">
|
||||
<span class="fx-label">data-fx="${name}"</span>
|
||||
<button class="fx-replay" type="button">Replay</button>
|
||||
<div class="fx-host" style="position:absolute;inset:0;" data-fx="${name}" ${extraAttrs}></div>
|
||||
</div>
|
||||
<div class="deck-footer"><span class="dim2">Press → for next slide</span><span class="slide-number" data-current="${idx}" data-total="${total}"></span></div>
|
||||
`;
|
||||
deck.appendChild(sec);
|
||||
|
||||
// Wire Replay button
|
||||
sec.querySelector('.fx-replay').addEventListener('click', () => {
|
||||
const host = sec.querySelector('.fx-host');
|
||||
const name2 = host.getAttribute('data-fx');
|
||||
const attrs = {};
|
||||
for (const a of host.attributes) attrs[a.name] = a.value;
|
||||
const parent = host.parentNode;
|
||||
// stop existing
|
||||
if (window.__hpxActive && window.__hpxActive.has(host)){
|
||||
try{ window.__hpxActive.get(host).stop(); }catch(e){}
|
||||
window.__hpxActive.delete(host);
|
||||
}
|
||||
const fresh = document.createElement('div');
|
||||
for (const k in attrs) fresh.setAttribute(k, attrs[k]);
|
||||
fresh.style.cssText = host.style.cssText;
|
||||
parent.replaceChild(fresh, host);
|
||||
if (window.__hpxReinit) window.__hpxReinit(sec);
|
||||
});
|
||||
});
|
||||
|
||||
// Build CSS animation slides (legacy, kept for completeness)
|
||||
CSS_ANIMS.forEach((a, i) => {
|
||||
const idx = FX.length + i + 1;
|
||||
const sec = document.createElement('section');
|
||||
sec.className = 'slide';
|
||||
sec.setAttribute('data-title', a[0]);
|
||||
sec.innerHTML = `
|
||||
<span class="fx-indicator">${idx}/${total}</span>
|
||||
<p class="kicker">CSS anim · ${String(idx).padStart(2,'0')}</p>
|
||||
<h1 class="h1"><span class="gradient-text">${a[0]}</span></h1>
|
||||
<p class="lede">${a[1]}</p>
|
||||
<div class="anim-box anim-${a[0]}" data-anim="${a[0]}" data-anim-target>${a[0]}</div>
|
||||
<div class="deck-footer"><span class="dim2">Press A to cycle</span><span class="slide-number" data-current="${idx}" data-total="${total}"></span></div>
|
||||
`;
|
||||
deck.appendChild(sec);
|
||||
});
|
||||
</script>
|
||||
<script src="../assets/runtime.js"></script>
|
||||
<script src="../assets/animations/fx-runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN" data-theme="minimal-white">
|
||||
<head>
|
||||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>html-ppt · Deck</title>
|
||||
<link rel="stylesheet" href="../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../assets/animations/animations.css">
|
||||
</head>
|
||||
<body data-themes="minimal-white,editorial-serif,soft-pastel,arctic-cool,sunset-warm,catppuccin-mocha,tokyo-night,aurora,xiaohongshu-white,neo-brutalism" data-theme-base="../assets/themes/">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. Cover -->
|
||||
<section class="slide" data-title="Cover">
|
||||
<p class="kicker">html-ppt · 2026</p>
|
||||
<h1 class="h1 anim-fade-up" data-anim="fade-up">用模板,<span class="gradient-text">换主题</span><br>讲任何事情</h1>
|
||||
<p class="lede">24 themes · 30 layouts · 25 animations · zero build</p>
|
||||
<div class="deck-footer"><span class="dim2">lewis</span><span class="slide-number" data-current="1" data-total="6"></span></div>
|
||||
<div class="notes">这是一个最小可用的 deck。你可以复制这个文件作为新 deck 的起点。</div>
|
||||
</section>
|
||||
|
||||
<!-- 2. TOC -->
|
||||
<section class="slide" data-title="目录">
|
||||
<p class="kicker">Agenda</p>
|
||||
<h2 class="h2">我们会讲三件事</h2>
|
||||
<div class="grid g3 mt-l anim-stagger-list" data-anim-target>
|
||||
<div class="card"><h4>01 · Tokens</h4><p class="dim">把颜色/字体/圆角收进 CSS 变量。</p></div>
|
||||
<div class="card"><h4>02 · Layouts</h4><p class="dim">30 种可复用单页。</p></div>
|
||||
<div class="card"><h4>03 · Runtime</h4><p class="dim">键盘驱动、按 T 换主题。</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 3. Stat -->
|
||||
<section class="slide center tc" data-title="Stat">
|
||||
<div>
|
||||
<p class="kicker">Result</p>
|
||||
<div style="font-size:220px;font-weight:900;line-height:1"><span class="counter gradient-text" data-to="92">0</span><span class="gradient-text">%</span></div>
|
||||
<h3>的准备时间被省下</h3>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 4. Two column -->
|
||||
<section class="slide" data-title="Tokens">
|
||||
<p class="kicker">Under the hood</p>
|
||||
<h2 class="h2">换主题 = 换一组变量</h2>
|
||||
<div class="grid g2 mt-l">
|
||||
<div class="card"><h4>语义变量</h4><p class="dim">写 <code>var(--surface)</code>,不写具体色值。</p></div>
|
||||
<div class="card"><h4>一键切换</h4><p class="dim">按 T 循环所有主题——所有 slide 同步更新。</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 5. CTA -->
|
||||
<section class="slide center tc" data-title="CTA">
|
||||
<div>
|
||||
<p class="kicker">Your turn</p>
|
||||
<h1 class="h1 anim-rise-in" data-anim="rise-in">开始做你的 deck</h1>
|
||||
<p class="lede" style="margin:16px auto">按 ← → 翻页 · T 切主题 · A 切动效 · F 全屏 · O 概览 · S 备注</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 6. Thanks -->
|
||||
<section class="slide center tc" data-title="Thanks">
|
||||
<h1 class="h1" style="font-size:160px;line-height:1"><span class="gradient-text">Thanks</span></h1>
|
||||
<p class="lede">lewis · sudolewis@gmail.com</p>
|
||||
</section>
|
||||
</div>
|
||||
<script src="../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,82 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8"><title>Full-Deck Gallery — html-ppt v2</title>
|
||||
<link rel="stylesheet" href="../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../assets/base.css">
|
||||
<style>
|
||||
html,body{background:#0b0c10;color:#e8ebf4;font-family:var(--font-sans)}
|
||||
.deck{background:#0b0c10}
|
||||
.slide{padding:60px 80px;color:#e8ebf4;background:transparent;display:flex;flex-direction:column}
|
||||
.slide h1{color:#fff;font-size:48px;margin:0 0 6px;letter-spacing:-.02em}
|
||||
.slide .sub{color:#aab0c0;font-size:18px;margin:0 0 22px}
|
||||
.frame-wrap{flex:1;border-radius:14px;overflow:hidden;border:1px solid rgba(255,255,255,.12);
|
||||
box-shadow:0 30px 80px rgba(0,0,0,.5);position:relative;background:#fff}
|
||||
iframe.tpl{position:absolute;inset:0;width:200%;height:200%;border:0;
|
||||
transform:scale(.5);transform-origin:top left}
|
||||
.meta{position:absolute;top:24px;right:40px;font-family:'JetBrains Mono',monospace;
|
||||
font-size:12px;color:#6a7086;letter-spacing:.14em;text-transform:uppercase;z-index:30}
|
||||
.tag{display:inline-block;padding:4px 10px;border-radius:999px;background:rgba(255,255,255,.08);
|
||||
color:#cfd3dc;font-size:11px;margin-right:6px}
|
||||
.cover{align-items:center;justify-content:center;text-align:center}
|
||||
.cover h1{font-size:84px;background:linear-gradient(135deg,#60a5fa,#a78bfa,#f472b6);
|
||||
-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
|
||||
.cover p{color:#aab0c0;max-width:60ch;font-size:20px}
|
||||
.legend{display:flex;gap:10px;flex-wrap:wrap;margin-top:18px}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="deck">
|
||||
|
||||
<section class="slide cover">
|
||||
<p class="kicker" style="color:#a78bfa">HTML-PPT v2 · Full-Deck Gallery</p>
|
||||
<h1>14 full-deck templates</h1>
|
||||
<p>Press → to browse. Each slide is a live iframe preview of a complete, multi-slide deck template. Open any <code>templates/full-decks/<name>/index.html</code> to see the full deck, or copy the folder to scaffold your own.</p>
|
||||
<div class="legend">
|
||||
<span class="tag">8 extracted from real decks</span>
|
||||
<span class="tag">6 scenario scaffolds</span>
|
||||
<span class="tag">scoped .tpl-<name> CSS</span>
|
||||
<span class="tag">36 themes compatible</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Template preview slides generated via JS below -->
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const TPLS = [
|
||||
['xhs-white-editorial', '白底杂志风', 'extracted', 'xhs posts, editorial lifestyle'],
|
||||
['graphify-dark-graph', '暗底知识图谱', 'extracted', 'AI/graph/data products'],
|
||||
['knowledge-arch-blueprint', '奶油蓝图架构', 'extracted', 'architecture, systems thinking'],
|
||||
['hermes-cyber-terminal', '暗终端 cyber', 'extracted', 'devtool, honest-review, agent demos'],
|
||||
['obsidian-claude-gradient', 'GitHub 暗紫渐变', 'extracted', 'tool walkthroughs, LLM product'],
|
||||
['testing-safety-alert', '红琥珀警示', 'extracted', 'security, incident review, AI safety'],
|
||||
['xhs-pastel-card', '柔和马卡龙', 'extracted', 'lifestyle, soft emotional'],
|
||||
['dir-key-nav-minimal', '方向键 8 色极简', 'extracted', 'keynote, one-idea-per-slide'],
|
||||
['pitch-deck', 'Pitch Deck YC 风', 'scenario', 'fundraising, startup pitch'],
|
||||
['product-launch', 'Product Launch', 'scenario', 'product announcement, launch keynote'],
|
||||
['tech-sharing', 'Tech Sharing 技术分享','scenario','internal tech talk, conference talk'],
|
||||
['weekly-report', 'Weekly Report 周报','scenario', 'status update, business review'],
|
||||
['xhs-post', '小红书 图文 9 屏 3:4','scenario', 'xiaohongshu / ig carousel'],
|
||||
['course-module', 'Course Module 教学模块','scenario','online course, workshop module'],
|
||||
['presenter-mode-reveal', '🎤 Presenter Mode 演讲者模式','scenario','tech sharing, talk with 逐字稿, speaker view']
|
||||
];
|
||||
|
||||
const deck = document.querySelector('.deck');
|
||||
TPLS.forEach((t,i)=>{
|
||||
const s = document.createElement('section');
|
||||
s.className = 'slide';
|
||||
s.setAttribute('data-title',t[0]);
|
||||
s.innerHTML = `
|
||||
<span class="meta">${i+1}/${TPLS.length+1}</span>
|
||||
<h1>${t[0]}</h1>
|
||||
<p class="sub">${t[1]} · <span class="tag">${t[2]}</span> ${t[3]}</p>
|
||||
<div class="frame-wrap">
|
||||
<iframe class="tpl" src="full-decks/${t[0]}/index.html" loading="eager" title="${t[0]}"></iframe>
|
||||
</div>`;
|
||||
deck.appendChild(s);
|
||||
});
|
||||
</script>
|
||||
<script src="../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,8 @@
|
||||
# course-module · 教学模块
|
||||
|
||||
7-slide teaching module: cover (title + meta), objectives, core concept, worked example, exercise, check-your-understanding (MCQ), summary.
|
||||
|
||||
Academic but friendly look: warm off-white paper, Playfair Display display type, a green/terracotta accent pair. A persistent **left sidebar** on content slides lists the module's learning objectives and checks them off as you progress — students always know where they are.
|
||||
|
||||
**Use when:** online course modules, lecture handouts, onboarding curricula, workshop units.
|
||||
**Feel:** a good textbook opened to a chapter — structured, quiet, encouraging.
|
||||
@@ -0,0 +1,189 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Module 04 · Recursion · CS101</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" href="../../../assets/animations/animations.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-course-module">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. Cover -->
|
||||
<section class="slide full" data-title="Cover">
|
||||
<p class="kicker">CS 101 · MODULE 04</p>
|
||||
<h1 class="h1 mt-s">Recursion: solving<br>problems by <em>calling yourself</em>.</h1>
|
||||
<p class="lede mt-l" style="max-width:62ch">In this module you'll learn why a function that calls itself is not a trick, but the most natural way to describe problems that contain smaller copies of themselves.</p>
|
||||
<div class="row mt-l" style="gap:16px">
|
||||
<span class="pill-academic">~ 45 min read</span>
|
||||
<span class="pill-academic">prereq · functions, if/else</span>
|
||||
<span class="pill-academic">lang · Python</span>
|
||||
</div>
|
||||
<div class="deck-footer"><span>Dr. A. Rivera · Spring 2026</span><span class="slide-number" data-current="1" data-total="7"></span></div>
|
||||
</section>
|
||||
|
||||
<!-- 2. Objectives -->
|
||||
<section class="slide" data-title="Objectives">
|
||||
<aside class="sidebar">
|
||||
<div class="brand">CS 101 · M04</div>
|
||||
<h5>Learning objectives</h5>
|
||||
<ul class="obj-list">
|
||||
<li class="current">Define recursion</li>
|
||||
<li>Identify a base case</li>
|
||||
<li>Trace a recursive call</li>
|
||||
<li>Convert loop ↔ recursion</li>
|
||||
<li>Recognize when recursion helps</li>
|
||||
</ul>
|
||||
<h5>Module progress</h5>
|
||||
<p class="dim" style="font-size:13px">Page 2 of 7 · ~5 min in</p>
|
||||
</aside>
|
||||
<div class="main">
|
||||
<p class="kicker">OBJECTIVES</p>
|
||||
<h2 class="h2 mt-s">By the end, you will be able to…</h2>
|
||||
<div class="stack mt-l">
|
||||
<div class="concept-box"><h4>① Explain recursion in one sentence.</h4><p class="dim">"A function that solves a problem by calling itself on a smaller version of that problem."</p></div>
|
||||
<div class="concept-box"><h4>② Write a base case that always terminates.</h4><p class="dim">Every recursive function must have an exit door, or it runs forever.</p></div>
|
||||
<div class="concept-box"><h4>③ Trace a call stack on paper.</h4><p class="dim">Given <code>fact(4)</code>, draw the stack frames top-to-bottom.</p></div>
|
||||
<div class="concept-box"><h4>④ Convert a while-loop to a recursive equivalent.</h4><p class="dim">And explain when one is clearer than the other.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 3. Concept -->
|
||||
<section class="slide" data-title="Concept">
|
||||
<aside class="sidebar">
|
||||
<div class="brand">CS 101 · M04</div>
|
||||
<h5>Learning objectives</h5>
|
||||
<ul class="obj-list">
|
||||
<li class="done">Define recursion</li>
|
||||
<li class="current">Identify a base case</li>
|
||||
<li>Trace a recursive call</li>
|
||||
<li>Convert loop ↔ recursion</li>
|
||||
<li>Recognize when recursion helps</li>
|
||||
</ul>
|
||||
<h5>Key terms</h5>
|
||||
<p class="dim" style="font-size:13px">base case · recursive case · call stack · tail call</p>
|
||||
</aside>
|
||||
<div class="main">
|
||||
<p class="kicker">CORE CONCEPT</p>
|
||||
<h2 class="h2 mt-s">Two parts, always.</h2>
|
||||
<p class="lede mt-m">A recursive function has exactly two things inside it: a <b>base case</b> (when to stop) and a <b>recursive case</b> (how to shrink the problem before calling yourself).</p>
|
||||
<div class="callout">
|
||||
<b>Rule of thumb.</b> If you can't name the base case out loud, don't write the recursion yet. Draw it on paper first.
|
||||
</div>
|
||||
<div class="grid g2 mt-l">
|
||||
<div class="concept-box"><h4>Base case</h4><p class="dim">The smallest possible input — one the function answers directly, without calling itself.</p><p class="pill-academic">e.g. <b>n == 0</b></p></div>
|
||||
<div class="concept-box"><h4>Recursive case</h4><p class="dim">Every other input — delegate to a smaller version of the same problem.</p><p class="pill-academic">e.g. <b>n × fact(n-1)</b></p></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 4. Example -->
|
||||
<section class="slide" data-title="Example">
|
||||
<aside class="sidebar">
|
||||
<div class="brand">CS 101 · M04</div>
|
||||
<h5>Learning objectives</h5>
|
||||
<ul class="obj-list">
|
||||
<li class="done">Define recursion</li>
|
||||
<li class="done">Identify a base case</li>
|
||||
<li class="current">Trace a recursive call</li>
|
||||
<li>Convert loop ↔ recursion</li>
|
||||
<li>Recognize when recursion helps</li>
|
||||
</ul>
|
||||
<h5>Try it yourself</h5>
|
||||
<p class="dim" style="font-size:13px">Open repl.it and run the code on the right. Then try <code>fact(10)</code>.</p>
|
||||
</aside>
|
||||
<div class="main">
|
||||
<p class="kicker">WORKED EXAMPLE</p>
|
||||
<h2 class="h2 mt-s">Factorial, 7 lines.</h2>
|
||||
<div class="code mt-m"><pre style="margin:0"><span class="cmt"># fact(n) = n × (n-1) × … × 1, and fact(0) = 1</span>
|
||||
<span class="kw">def</span> fact(n):
|
||||
<span class="kw">if</span> n == <span class="str">0</span>: <span class="cmt"># base case</span>
|
||||
<span class="kw">return</span> <span class="str">1</span>
|
||||
<span class="kw">return</span> n * fact(n - <span class="str">1</span>) <span class="cmt"># recursive case</span>
|
||||
|
||||
<span class="kw">print</span>(fact(<span class="str">4</span>)) <span class="cmt"># → 24</span></pre></div>
|
||||
<div class="callout">
|
||||
<b>Trace fact(4).</b> 4 × fact(3) → 4 × (3 × fact(2)) → 4 × 3 × (2 × fact(1)) → 4 × 3 × 2 × 1 × fact(0) → 4 × 3 × 2 × 1 × 1 = <b>24</b>.
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 5. Exercise -->
|
||||
<section class="slide" data-title="Exercise">
|
||||
<aside class="sidebar">
|
||||
<div class="brand">CS 101 · M04</div>
|
||||
<h5>Learning objectives</h5>
|
||||
<ul class="obj-list">
|
||||
<li class="done">Define recursion</li>
|
||||
<li class="done">Identify a base case</li>
|
||||
<li class="done">Trace a recursive call</li>
|
||||
<li class="current">Convert loop ↔ recursion</li>
|
||||
<li>Recognize when recursion helps</li>
|
||||
</ul>
|
||||
<h5>Time</h5>
|
||||
<p class="dim" style="font-size:13px">~10 minutes · solo</p>
|
||||
</aside>
|
||||
<div class="main">
|
||||
<p class="kicker">EXERCISE 4.1</p>
|
||||
<h2 class="h2 mt-s">Write <em>sum_to(n)</em>.</h2>
|
||||
<p class="lede mt-m">Return <code>1 + 2 + … + n</code> using recursion — no loops allowed.</p>
|
||||
<div class="exercise mt-l">
|
||||
<p style="margin:0;font-size:18px;color:var(--text-1)"><b>Your task</b></p>
|
||||
<ol style="color:var(--text-2);line-height:1.8;margin:10px 0 0">
|
||||
<li>Write the base case. What does <code>sum_to(0)</code> return?</li>
|
||||
<li>Write the recursive case in terms of <code>sum_to(n - 1)</code>.</li>
|
||||
<li>Test it: <code>sum_to(5) == 15</code>, <code>sum_to(10) == 55</code>.</li>
|
||||
<li>Bonus: what happens if you call <code>sum_to(-3)</code>? Fix it.</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p class="dim mt-m" style="font-size:14px">Stuck? Remember: a base case is the smallest input you already know the answer to.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 6. Check understanding -->
|
||||
<section class="slide" data-title="Check">
|
||||
<aside class="sidebar">
|
||||
<div class="brand">CS 101 · M04</div>
|
||||
<h5>Learning objectives</h5>
|
||||
<ul class="obj-list">
|
||||
<li class="done">Define recursion</li>
|
||||
<li class="done">Identify a base case</li>
|
||||
<li class="done">Trace a recursive call</li>
|
||||
<li class="done">Convert loop ↔ recursion</li>
|
||||
<li class="current">Recognize when recursion helps</li>
|
||||
</ul>
|
||||
<h5>Self-assess</h5>
|
||||
<p class="dim" style="font-size:13px">You should get 3/3.</p>
|
||||
</aside>
|
||||
<div class="main">
|
||||
<p class="kicker">CHECK YOUR UNDERSTANDING</p>
|
||||
<h2 class="h2 mt-s">Which function will recurse forever?</h2>
|
||||
<div class="mt-l">
|
||||
<div class="mcq"><div class="letter">A</div><div><b>def f(n): return 1 if n == 0 else n * f(n - 1)</b><p class="dim" style="font-size:13px;margin:4px 0 0">Base case <code>n == 0</code>, shrinks toward it. Terminates.</p></div></div>
|
||||
<div class="mcq correct"><div class="letter">B</div><div><b>def f(n): return n + f(n + 1)</b><p class="dim" style="font-size:13px;margin:4px 0 0"><b style="color:var(--accent)">✓ Correct.</b> No base case, and <code>n</code> grows — infinite recursion.</p></div></div>
|
||||
<div class="mcq"><div class="letter">C</div><div><b>def f(n): return n if n < 2 else f(n - 1) + f(n - 2)</b><p class="dim" style="font-size:13px;margin:4px 0 0">Classic Fibonacci. Base case on <code>n < 2</code>. Terminates.</p></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 7. Summary -->
|
||||
<section class="slide full" data-title="Summary">
|
||||
<p class="kicker">SUMMARY · MODULE 04</p>
|
||||
<h1 class="h1 mt-s">You can now…</h1>
|
||||
<div class="grid g2 mt-l">
|
||||
<div class="concept-box"><h4>✓ Define recursion</h4><p class="dim">A function that calls itself on a smaller input.</p></div>
|
||||
<div class="concept-box"><h4>✓ Write a safe base case</h4><p class="dim">Every recursion needs an exit door.</p></div>
|
||||
<div class="concept-box"><h4>✓ Trace a call stack</h4><p class="dim">You can unwind <code>fact(4)</code> by hand.</p></div>
|
||||
<div class="concept-box"><h4>✓ Judge when to use it</h4><p class="dim">Trees and self-similar problems → recursion. Flat iteration → loop.</p></div>
|
||||
</div>
|
||||
<div class="callout mt-l">
|
||||
<b>Up next · Module 05.</b> Divide & conquer: merge sort. We'll use everything you just learned — but on lists, not numbers.
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,46 @@
|
||||
/* course-module — academic but friendly */
|
||||
.tpl-course-module{
|
||||
--bg:#fbfaf6;--bg-soft:#f4f1e8;--surface:#ffffff;--surface-2:#f6f3ea;
|
||||
--border:rgba(60,45,20,.12);--border-strong:rgba(60,45,20,.24);
|
||||
--text-1:#2a2418;--text-2:#5a5140;--text-3:#8a7f68;
|
||||
--accent:#2d7d6e;--accent-2:#d88a3a;--accent-3:#c4593f;
|
||||
--grad:linear-gradient(135deg,#2d7d6e,#4ea893);
|
||||
--radius:14px;--radius-lg:20px;
|
||||
--shadow:0 12px 30px rgba(60,45,20,.07);
|
||||
font-family:'Inter','Noto Sans SC',sans-serif;
|
||||
}
|
||||
.tpl-course-module .slide{padding:64px 80px;background:var(--bg);display:grid;grid-template-columns:260px 1fr;gap:56px;align-content:start}
|
||||
.tpl-course-module .slide.full{grid-template-columns:1fr;display:flex;flex-direction:column;justify-content:center}
|
||||
.tpl-course-module .sidebar{border-right:1px solid var(--border);padding-right:32px;position:relative}
|
||||
.tpl-course-module .sidebar .brand{font-family:'Playfair Display',serif;font-size:22px;font-weight:700;color:var(--accent)}
|
||||
.tpl-course-module .sidebar .brand::before{content:"✦ ";color:var(--accent-2)}
|
||||
.tpl-course-module .sidebar h5{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.12em;color:var(--text-3);margin:32px 0 12px}
|
||||
.tpl-course-module .obj-list{list-style:none;padding:0;margin:0;font-size:13px;color:var(--text-2);line-height:1.5}
|
||||
.tpl-course-module .obj-list li{padding:8px 0 8px 22px;position:relative;border-bottom:1px dashed var(--border)}
|
||||
.tpl-course-module .obj-list li::before{content:"○";position:absolute;left:0;top:8px;color:var(--accent)}
|
||||
.tpl-course-module .obj-list li.done::before{content:"●";color:var(--accent)}
|
||||
.tpl-course-module .obj-list li.current{color:var(--text-1);font-weight:700}
|
||||
.tpl-course-module .obj-list li.current::before{content:"▸";color:var(--accent-2)}
|
||||
.tpl-course-module .main{min-width:0}
|
||||
.tpl-course-module .h1{font-family:'Playfair Display',serif;font-size:72px;line-height:1.02;font-weight:800;letter-spacing:-.02em;color:var(--text-1)}
|
||||
.tpl-course-module .h2{font-family:'Playfair Display',serif;font-size:48px;line-height:1.1;font-weight:700;letter-spacing:-.015em;color:var(--text-1)}
|
||||
.tpl-course-module h3,.tpl-course-module h4{color:var(--text-1)}
|
||||
.tpl-course-module .kicker{color:var(--accent-2);font-size:12px;font-weight:700;letter-spacing:.14em}
|
||||
.tpl-course-module .lede{font-size:20px;color:var(--text-2);line-height:1.7}
|
||||
.tpl-course-module .callout{border-left:4px solid var(--accent-2);background:var(--surface-2);padding:20px 24px;border-radius:0 var(--radius) var(--radius) 0;margin-top:24px}
|
||||
.tpl-course-module .callout b{color:var(--accent-2)}
|
||||
.tpl-course-module .concept-box{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:24px 26px;box-shadow:var(--shadow)}
|
||||
.tpl-course-module .concept-box h4{margin-top:0;color:var(--accent)}
|
||||
.tpl-course-module .exercise{background:#fff8ed;border:1.5px dashed var(--accent-2);border-radius:var(--radius);padding:24px 28px}
|
||||
.tpl-course-module .exercise::before{content:"✎ Exercise";display:block;font-size:12px;font-weight:700;letter-spacing:.12em;color:var(--accent-2);margin-bottom:10px;text-transform:uppercase}
|
||||
.tpl-course-module .code{background:#2a2418;color:#f4f1e8;border-radius:var(--radius);padding:20px 24px;font-family:'JetBrains Mono',monospace;font-size:14px;line-height:1.7;overflow:auto}
|
||||
.tpl-course-module .code .cmt{color:#8a7f68;font-style:italic}
|
||||
.tpl-course-module .code .kw{color:#e8a770}
|
||||
.tpl-course-module .code .str{color:#8ec6b2}
|
||||
.tpl-course-module .mcq{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:18px 22px;margin-bottom:10px;display:flex;gap:14px;align-items:flex-start;cursor:pointer}
|
||||
.tpl-course-module .mcq .letter{flex:none;width:28px;height:28px;border-radius:50%;border:2px solid var(--text-3);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px;color:var(--text-2)}
|
||||
.tpl-course-module .mcq.correct{border-color:var(--accent);background:rgba(45,125,110,.06)}
|
||||
.tpl-course-module .mcq.correct .letter{border-color:var(--accent);background:var(--accent);color:#fff}
|
||||
.tpl-course-module .pill-academic{display:inline-block;padding:4px 12px;border-radius:4px;background:var(--surface-2);border:1px solid var(--border);font-size:12px;color:var(--text-2);font-family:'JetBrains Mono',monospace}
|
||||
.tpl-course-module .slide.full .h1{font-size:88px}
|
||||
.tpl-course-module .deck-footer{color:var(--text-3)}
|
||||
@@ -0,0 +1,11 @@
|
||||
# dir-key-nav-minimal
|
||||
|
||||
8 张幻灯片,每张一个纯色/渐变 mono-background(indigo / cream / crimson / emerald / slate / violet / white / charcoal)。灵感直接来自 `20260405 演示幻灯片【方向键版】.html` —— 八个 `t-*` 主题类,每张幻灯一个背景,方向键切换,极简 editorial 气质。
|
||||
|
||||
**Visual traits:** 每张独立背景色 + 单一 accent、巨大 160px 标题无副图、4px 短粗 accent line divider、arrow-prefixed mono list、左下 `← →` 键盘提示 + 右下 page label、全屏 breathing negative space、JetBrains Mono 做数字 / 代码 / 键盘 hint、每个背景有自己的 `.dk-accent` 色。
|
||||
|
||||
**Use when:** 有话要说、没太多图、希望用排版节奏推进观众注意力;keynote 式的极简讲稿;每张幻灯只讲一件事;公开分享 / keynote / 演讲稿。
|
||||
|
||||
**Source inspiration:** `20260405-Karpathy-知识库/20260405 演示幻灯片【方向键版】.html`.
|
||||
|
||||
**Path:** `templates/full-decks/dir-key-nav-minimal/index.html`
|
||||
@@ -0,0 +1,138 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Dir-Key Nav Minimal</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-dir-key-nav-minimal">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. COVER · indigo -->
|
||||
<section class="slide t-indigo is-active">
|
||||
<div class="dk-snum">01 / 08</div>
|
||||
<div style="margin:auto 0">
|
||||
<div class="dk-eyebrow">Karpathy LLM Wiki</div>
|
||||
<h1 class="dk-h0">为什么笔记<br>治不了 <span class="dk-accent">LLM</span></h1>
|
||||
<span class="dk-line"></span>
|
||||
<p class="dk-lede">8 种背景、8 张幻灯,一个关于如何把 AI 变成「长期记忆外挂」的最短陈述。<strong>按 → 继续。</strong></p>
|
||||
</div>
|
||||
<div class="dk-keyhint">nav · <kbd>←</kbd> <kbd>→</kbd> · <kbd>space</kbd></div>
|
||||
<div class="dk-page">cover</div>
|
||||
</section>
|
||||
|
||||
<!-- 2. SECTION · cream -->
|
||||
<section class="slide t-cream">
|
||||
<div class="dk-snum">02 / 08</div>
|
||||
<div style="margin:auto 0">
|
||||
<div class="dk-eyebrow">Chapter 01</div>
|
||||
<h1 class="dk-h0">The <span class="dk-accent">Problem</span>.</h1>
|
||||
<span class="dk-line"></span>
|
||||
<p class="dk-lede">Token 上限是一个物理事实。你每次和 LLM 说话,它都是一个失忆症患者。</p>
|
||||
</div>
|
||||
<div class="dk-keyhint">chapter · 01 / 04</div>
|
||||
<div class="dk-page">section</div>
|
||||
</section>
|
||||
|
||||
<!-- 3. CONTENT · crimson -->
|
||||
<section class="slide t-crimson">
|
||||
<div class="dk-snum">03 / 08</div>
|
||||
<div style="margin:auto 0">
|
||||
<div class="dk-eyebrow">Symptoms</div>
|
||||
<h2 class="dk-h1">四种你已经<br>受够的<br><span class="dk-accent">遗忘</span>。</h2>
|
||||
<ul class="dk-list">
|
||||
<li>昨天聊过的项目,今天重新解释一遍</li>
|
||||
<li>上下文窗口一到,它开始「编造记忆」</li>
|
||||
<li>不同 session 之间毫无关联,就像第一次见</li>
|
||||
<li>你的真正偏好从未被记住,每次都要 re-prompt</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="dk-keyhint">content · list</div>
|
||||
<div class="dk-page">03</div>
|
||||
</section>
|
||||
|
||||
<!-- 4. CONTENT · emerald -->
|
||||
<section class="slide t-emerald">
|
||||
<div class="dk-snum">04 / 08</div>
|
||||
<div style="margin:auto 0">
|
||||
<div class="dk-eyebrow">The Fix</div>
|
||||
<h2 class="dk-h1">答案不是<br><span class="dk-accent">更大</span> 的窗口。</h2>
|
||||
<p class="dk-lede" style="margin-top:10px">而是:把你的知识、偏好、历史都<strong>写进文件系统</strong>。<br>让 LLM 每次对话前,先去读那个系统。</p>
|
||||
<div class="dk-grid-2">
|
||||
<div class="dk-col"><h3>× 窗口 stuffing</h3><p>把所有东西塞 prompt,贵、慢、最终溢出。</p></div>
|
||||
<div class="dk-col"><h3>✓ 文件 + 检索</h3><p>按需加载,永远不溢出,结构化可 diff。</p></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dk-keyhint">content · compare</div>
|
||||
<div class="dk-page">04</div>
|
||||
</section>
|
||||
|
||||
<!-- 5. CODE · slate -->
|
||||
<section class="slide t-slate">
|
||||
<div class="dk-snum">05 / 08</div>
|
||||
<div style="margin:auto 0">
|
||||
<div class="dk-eyebrow">Minimal Setup</div>
|
||||
<h2 class="dk-h2"><span class="dk-accent">4 行</span> YAML<br>就能开始。</h2>
|
||||
<pre class="dk-code">memory:
|
||||
root: ~/.llm-wiki
|
||||
format: markdown
|
||||
retrieval: hybrid # embedding + bm25</pre>
|
||||
<p class="dk-lede" style="margin-top:16px;font-size:20px">你现在拥有一个会随时间增长的 <strong>第二大脑</strong>。每次对话它都会被读、被更新。</p>
|
||||
</div>
|
||||
<div class="dk-keyhint">content · code</div>
|
||||
<div class="dk-page">05</div>
|
||||
</section>
|
||||
|
||||
<!-- 6. CHART · violet — big number with bar -->
|
||||
<section class="slide t-violet">
|
||||
<div class="dk-snum">06 / 08</div>
|
||||
<div style="margin:auto 0">
|
||||
<div class="dk-eyebrow">30-day result</div>
|
||||
<div class="dk-big dk-accent">87%</div>
|
||||
<p class="dk-lede" style="margin-top:14px;font-size:26px">的 re-explain 被消除。平均每次对话节省 <strong>4.2 分钟</strong> 的 re-context。</p>
|
||||
<svg viewBox="0 0 900 80" style="width:100%;max-width:900px;margin-top:30px">
|
||||
<rect x="0" y="30" width="900" height="22" rx="11" fill="rgba(255,255,255,.12)"/>
|
||||
<rect x="0" y="30" width="783" height="22" rx="11" fill="#c4b5fd"/>
|
||||
<text x="792" y="47" font-family="JetBrains Mono" font-size="16" fill="#c4b5fd" font-weight="700">87%</text>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="dk-keyhint">chart · big-num</div>
|
||||
<div class="dk-page">06</div>
|
||||
</section>
|
||||
|
||||
<!-- 7. CTA · white -->
|
||||
<section class="slide t-white">
|
||||
<div class="dk-snum">07 / 08</div>
|
||||
<div style="margin:auto 0">
|
||||
<div class="dk-eyebrow">Start tonight</div>
|
||||
<h2 class="dk-h1">开始<br>你的 <span class="dk-accent">wiki</span>。</h2>
|
||||
<span class="dk-line"></span>
|
||||
<p class="dk-lede">不是装又一个插件。是决定:从今晚起,<strong>你的所有 AI 对话都要有一个共同的 vault</strong>。</p>
|
||||
<pre class="dk-code" style="font-size:18px">$ mkdir ~/llm-wiki && cd ~/llm-wiki
|
||||
$ git init
|
||||
$ echo "# my brain" > README.md</pre>
|
||||
</div>
|
||||
<div class="dk-keyhint">cta · three-commands</div>
|
||||
<div class="dk-page">07</div>
|
||||
</section>
|
||||
|
||||
<!-- 8. THANKS · charcoal -->
|
||||
<section class="slide t-charcoal">
|
||||
<div class="dk-snum">08 / 08</div>
|
||||
<div style="margin:auto 0">
|
||||
<div class="dk-eyebrow">End · thanks for staying</div>
|
||||
<h1 class="dk-h0"><span class="dk-accent">謝謝</span>。</h1>
|
||||
<span class="dk-line"></span>
|
||||
<p class="dk-lede">Karpathy 的原始 thread + 我的 vault 结构都在 <strong>github.com/lewis/llm-wiki</strong>。欢迎按 ← 再看一遍。</p>
|
||||
</div>
|
||||
<div class="dk-keyhint">press <kbd>←</kbd> to rewind · <kbd>F</kbd> for fullscreen</div>
|
||||
<div class="dk-page">fin</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,60 @@
|
||||
/* dir-key-nav-minimal — 方向键极简 · 8 种 mono-background 切换 */
|
||||
.tpl-dir-key-nav-minimal{
|
||||
--dk-font:'Inter','Noto Sans SC','PingFang SC',-apple-system,sans-serif;
|
||||
--dk-mono:'JetBrains Mono',monospace;
|
||||
background:#000;
|
||||
color:#fff;
|
||||
font-family:var(--dk-font);
|
||||
}
|
||||
.tpl-dir-key-nav-minimal .slide{padding:80px 104px;overflow:hidden;position:absolute;inset:0}
|
||||
/* 8 background themes */
|
||||
.tpl-dir-key-nav-minimal .t-indigo{background:linear-gradient(135deg,#0f172a 0%,#1e1b4b 100%);color:#fff}
|
||||
.tpl-dir-key-nav-minimal .t-cream{background:#F5F0E8;color:#1a1a1a}
|
||||
.tpl-dir-key-nav-minimal .t-crimson{background:linear-gradient(135deg,#7f1d1d 0%,#991b1b 100%);color:#fff}
|
||||
.tpl-dir-key-nav-minimal .t-emerald{background:linear-gradient(135deg,#052e16 0%,#064e3b 100%);color:#ecfdf5}
|
||||
.tpl-dir-key-nav-minimal .t-slate{background:linear-gradient(135deg,#0f1923 0%,#1a2942 100%);color:#e6edf3}
|
||||
.tpl-dir-key-nav-minimal .t-violet{background:linear-gradient(135deg,#1e0a2e 0%,#2e1065 100%);color:#f5f3ff}
|
||||
.tpl-dir-key-nav-minimal .t-white{background:#ffffff;color:#111216}
|
||||
.tpl-dir-key-nav-minimal .t-charcoal{background:linear-gradient(135deg,#111827 0%,#1f2937 100%);color:#f3f4f6}
|
||||
|
||||
.tpl-dir-key-nav-minimal .dk-snum{position:absolute;top:30px;right:48px;font-size:11px;font-weight:700;letter-spacing:3px;text-transform:uppercase;font-family:var(--dk-mono)}
|
||||
.tpl-dir-key-nav-minimal .t-cream .dk-snum,
|
||||
.tpl-dir-key-nav-minimal .t-white .dk-snum{color:#999}
|
||||
.tpl-dir-key-nav-minimal .t-indigo .dk-snum,
|
||||
.tpl-dir-key-nav-minimal .t-crimson .dk-snum,
|
||||
.tpl-dir-key-nav-minimal .t-emerald .dk-snum,
|
||||
.tpl-dir-key-nav-minimal .t-slate .dk-snum,
|
||||
.tpl-dir-key-nav-minimal .t-violet .dk-snum,
|
||||
.tpl-dir-key-nav-minimal .t-charcoal .dk-snum{color:rgba(255,255,255,.38)}
|
||||
|
||||
.tpl-dir-key-nav-minimal .dk-eyebrow{font-size:12px;font-weight:700;letter-spacing:3.5px;text-transform:uppercase;opacity:.55;margin-bottom:22px;display:flex;align-items:center;gap:14px}
|
||||
.tpl-dir-key-nav-minimal .dk-eyebrow::after{content:'';flex:1;max-width:120px;height:1px;background:currentColor;opacity:.3}
|
||||
.tpl-dir-key-nav-minimal .dk-h0{font-size:160px;font-weight:900;line-height:.9;letter-spacing:-5px;margin:0 0 20px}
|
||||
.tpl-dir-key-nav-minimal .dk-h1{font-size:100px;font-weight:900;line-height:.98;letter-spacing:-3px;margin:0 0 18px}
|
||||
.tpl-dir-key-nav-minimal .dk-h2{font-size:72px;font-weight:800;line-height:1.05;letter-spacing:-2px;margin:0 0 16px}
|
||||
.tpl-dir-key-nav-minimal .dk-lede{font-size:26px;line-height:1.45;opacity:.72;max-width:900px;font-weight:300}
|
||||
.tpl-dir-key-nav-minimal .dk-lede strong{font-weight:700;opacity:1}
|
||||
.tpl-dir-key-nav-minimal .dk-big{font-family:var(--dk-mono);font-size:240px;font-weight:800;line-height:.9;letter-spacing:-10px}
|
||||
|
||||
.tpl-dir-key-nav-minimal .dk-line{display:block;width:90px;height:4px;background:currentColor;margin:30px 0;opacity:.85}
|
||||
.tpl-dir-key-nav-minimal .t-indigo .dk-accent{color:#a5b4fc}
|
||||
.tpl-dir-key-nav-minimal .t-cream .dk-accent{color:#B5392A}
|
||||
.tpl-dir-key-nav-minimal .t-crimson .dk-accent{color:#fecaca}
|
||||
.tpl-dir-key-nav-minimal .t-emerald .dk-accent{color:#6ee7b7}
|
||||
.tpl-dir-key-nav-minimal .t-slate .dk-accent{color:#7dd3fc}
|
||||
.tpl-dir-key-nav-minimal .t-violet .dk-accent{color:#c4b5fd}
|
||||
.tpl-dir-key-nav-minimal .t-white .dk-accent{color:#6366f1}
|
||||
.tpl-dir-key-nav-minimal .t-charcoal .dk-accent{color:#fbbf24}
|
||||
|
||||
.tpl-dir-key-nav-minimal .dk-list{list-style:none;padding:0;margin:28px 0 0;font-family:var(--dk-mono);font-size:22px;line-height:2}
|
||||
.tpl-dir-key-nav-minimal .dk-list li{padding-left:30px;position:relative;font-weight:400;opacity:.85}
|
||||
.tpl-dir-key-nav-minimal .dk-list li::before{content:'→';position:absolute;left:0;opacity:.5}
|
||||
.tpl-dir-key-nav-minimal .dk-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:56px;margin-top:36px}
|
||||
.tpl-dir-key-nav-minimal .dk-col h3{font-size:28px;font-weight:700;margin-bottom:10px}
|
||||
.tpl-dir-key-nav-minimal .dk-col p{font-size:19px;line-height:1.55;opacity:.72;font-weight:300}
|
||||
.tpl-dir-key-nav-minimal .dk-code{font-family:var(--dk-mono);font-size:16px;line-height:1.9;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.12);border-radius:10px;padding:24px 28px;margin-top:24px;white-space:pre}
|
||||
.tpl-dir-key-nav-minimal .t-cream .dk-code,
|
||||
.tpl-dir-key-nav-minimal .t-white .dk-code{background:rgba(0,0,0,.05);border-color:rgba(0,0,0,.1)}
|
||||
.tpl-dir-key-nav-minimal .dk-keyhint{position:absolute;bottom:34px;left:104px;font-family:var(--dk-mono);font-size:12px;letter-spacing:2px;text-transform:uppercase;opacity:.45}
|
||||
.tpl-dir-key-nav-minimal .dk-keyhint kbd{display:inline-block;padding:2px 10px;margin:0 3px;border:1px solid currentColor;border-radius:4px;font-size:12px}
|
||||
.tpl-dir-key-nav-minimal .dk-page{position:absolute;bottom:34px;right:48px;font-family:var(--dk-mono);font-size:12px;letter-spacing:2px;opacity:.45}
|
||||
@@ -0,0 +1,11 @@
|
||||
# graphify-dark-graph
|
||||
|
||||
Deep-night 暗底 + 力导向知识图谱覆盖层 + 温暖玻璃拟态卡片。灵感来自 `20260413-graphify/ppt/graphify.html` 的 `#06060c` 渐变底、飘移 orb 光晕、glass 卡片(warm/blue/green/purple 五变体)和 rainbow-text 标题。
|
||||
|
||||
**Visual traits:** `#06060c → #0e1020` 斜向渐变、三颗 400-520px blur orb 慢飘动、cover SVG 力导向图谱作为背景、rainbow shift 渐变标题、JetBrains Mono 的 `.cmd-glow` 命令行、玻璃拟态卡片带顶部高光和微妙内阴影、温暖色系 accent (#e8a87c 琥珀 / #7ed3a4 薄荷 / #7eb8da 雾蓝 / #b8a4d6 丁香).
|
||||
|
||||
**Use when:** 介绍一个开发者工具、命令行产品、知识图谱 / 数据可视化相关项目;你希望现场演示时视觉有「AI native + 科技感 + 温度」。
|
||||
|
||||
**Source inspiration:** `20260413-graphify/ppt/graphify.html`.
|
||||
|
||||
**Path:** `templates/full-decks/graphify-dark-graph/index.html`
|
||||
@@ -0,0 +1,180 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Graphify Dark Graph</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-graphify-dark-graph">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. COVER -->
|
||||
<section class="slide is-active">
|
||||
<div class="gd-ambient"><div class="gd-orb gd-orb-1"></div><div class="gd-orb gd-orb-2"></div><div class="gd-orb gd-orb-3"></div></div>
|
||||
<!-- live force-directed graph bg -->
|
||||
<svg viewBox="0 0 1600 900" style="position:absolute;inset:0;width:100%;height:100%;opacity:.38;z-index:1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g stroke="#7eb8da" stroke-width="1" stroke-opacity=".5" fill="none">
|
||||
<line x1="300" y1="200" x2="520" y2="340"/>
|
||||
<line x1="520" y1="340" x2="780" y2="260"/>
|
||||
<line x1="780" y1="260" x2="1040" y2="420"/>
|
||||
<line x1="520" y1="340" x2="640" y2="560"/>
|
||||
<line x1="640" y1="560" x2="900" y2="620"/>
|
||||
<line x1="900" y1="620" x2="1040" y2="420"/>
|
||||
<line x1="1040" y1="420" x2="1260" y2="300"/>
|
||||
<line x1="1260" y1="300" x2="1380" y2="500"/>
|
||||
<line x1="900" y1="620" x2="1120" y2="720"/>
|
||||
<line x1="300" y1="200" x2="200" y2="420"/>
|
||||
<line x1="200" y1="420" x2="360" y2="640"/>
|
||||
<line x1="360" y1="640" x2="640" y2="560"/>
|
||||
</g>
|
||||
<g>
|
||||
<circle cx="300" cy="200" r="10" fill="#e8a87c"/>
|
||||
<circle cx="520" cy="340" r="14" fill="#7eb8da"/>
|
||||
<circle cx="780" cy="260" r="9" fill="#7ed3a4"/>
|
||||
<circle cx="1040" cy="420" r="18" fill="#b8a4d6"/>
|
||||
<circle cx="640" cy="560" r="11" fill="#d4a0b9"/>
|
||||
<circle cx="900" cy="620" r="12" fill="#e8a87c"/>
|
||||
<circle cx="1260" cy="300" r="8" fill="#7ed3a4"/>
|
||||
<circle cx="1380" cy="500" r="10" fill="#7eb8da"/>
|
||||
<circle cx="1120" cy="720" r="9" fill="#d4a0b9"/>
|
||||
<circle cx="200" cy="420" r="8" fill="#b8a4d6"/>
|
||||
<circle cx="360" cy="640" r="11" fill="#7eb8da"/>
|
||||
</g>
|
||||
</svg>
|
||||
<div class="gd-snum">01 / 08</div>
|
||||
<div style="margin-top:auto">
|
||||
<p class="gd-eyebrow">Tech Sharing · 纯干货</p>
|
||||
<h1 class="gd-h1" style="font-size:88px"><span class="gd-rainbow">手把手用 Graphify<br>搭建个人知识图谱</span></h1>
|
||||
<p class="gd-lede" style="margin-top:20px">一行命令 · 全多模态 · 诚实审计 —— <span class="gd-accent">把任何文件夹变成可导航的知识网络。</span></p>
|
||||
<p class="gd-eyebrow" style="margin-top:26px">↑ 背景就是 Graphify 真实跑出来的知识图谱</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 2. SECTION DIVIDER -->
|
||||
<section class="slide">
|
||||
<div class="gd-ambient"><div class="gd-orb gd-orb-1"></div><div class="gd-orb gd-orb-2"></div></div>
|
||||
<div class="gd-snum">02 / 08</div>
|
||||
<div style="margin:auto 0">
|
||||
<div class="gd-eyebrow">Part 01</div>
|
||||
<h1 class="gd-h1" style="font-size:120px">Why <span class="gd-grad">Graph</span>?</h1>
|
||||
<p class="gd-lede">folder → tree → graph,人类认知的下一步</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 3. CONTENT — plugin grid -->
|
||||
<section class="slide">
|
||||
<div class="gd-ambient"><div class="gd-orb gd-orb-2"></div><div class="gd-orb gd-orb-3"></div></div>
|
||||
<div class="gd-snum">03 / 08</div>
|
||||
<p class="gd-eyebrow">Feature Map</p>
|
||||
<h2 class="gd-h2">一个工具,<span class="gd-grad">四件事</span></h2>
|
||||
<div class="gd-grid-4">
|
||||
<div class="gd-glass gd-glass-warm"><div style="font-size:30px">📂</div><h4 style="margin:10px 0 6px">Folder Ingest</h4><p class="gd-dim" style="font-size:13px;line-height:1.55">递归扫描任意路径,支持 md / pdf / 代码 / 图片</p></div>
|
||||
<div class="gd-glass gd-glass-blue"><div style="font-size:30px">🧠</div><h4 style="margin:10px 0 6px">Entity Extract</h4><p class="gd-dim" style="font-size:13px;line-height:1.55">用 LLM 抽概念、人物、事件、关系</p></div>
|
||||
<div class="gd-glass gd-glass-green"><div style="font-size:30px">🕸️</div><h4 style="margin:10px 0 6px">Force Graph</h4><p class="gd-dim" style="font-size:13px;line-height:1.55">D3 力导向,点击即跳转原文</p></div>
|
||||
<div class="gd-glass"><div style="font-size:30px">🔍</div><h4 style="margin:10px 0 6px">Audit Trail</h4><p class="gd-dim" style="font-size:13px;line-height:1.55">每条边都能追溯到 source span</p></div>
|
||||
</div>
|
||||
<div class="gd-glass gd-glass-warm" style="margin-top:24px"><p style="font-size:18px;line-height:1.6">它不是「又一个 RAG」—— 它是 <span class="gd-accent">把检索结果画出来,让你一眼就知道信息长什么样</span>。</p></div>
|
||||
</section>
|
||||
|
||||
<!-- 4. CODE -->
|
||||
<section class="slide">
|
||||
<div class="gd-ambient"><div class="gd-orb gd-orb-1"></div></div>
|
||||
<div class="gd-snum">04 / 08</div>
|
||||
<p class="gd-eyebrow">One command</p>
|
||||
<h2 class="gd-h2">从 0 到图谱,<span class="gd-grad">大概 90 秒</span></h2>
|
||||
<p class="gd-cmd" style="margin:16px 0 22px">$ graphify ~/notes --out ./graph</p>
|
||||
<pre class="gd-codebox"><span class="cm"># graphify.config.yaml</span>
|
||||
<span class="kw">ingest</span>:
|
||||
paths: [<span class="st">~/notes</span>, <span class="st">~/code/docs</span>]
|
||||
include: [<span class="st">"*.md"</span>, <span class="st">"*.pdf"</span>, <span class="st">"*.py"</span>]
|
||||
|
||||
<span class="kw">extract</span>:
|
||||
model: <span class="st">claude-opus-4-6</span>
|
||||
schema: [<span class="st">concept</span>, <span class="st">person</span>, <span class="st">event</span>, <span class="st">relation</span>]
|
||||
|
||||
<span class="kw">render</span>:
|
||||
engine: <span class="st">d3-force</span>
|
||||
audit: <span class="fn">true</span> <span class="cm"># 每条边带 source span</span></pre>
|
||||
</section>
|
||||
|
||||
<!-- 5. CHART — race diagram -->
|
||||
<section class="slide">
|
||||
<div class="gd-ambient"><div class="gd-orb gd-orb-3"></div></div>
|
||||
<div class="gd-snum">05 / 08</div>
|
||||
<p class="gd-eyebrow">Efficiency Race</p>
|
||||
<h2 class="gd-h2">没有知识库 vs 有知识库</h2>
|
||||
<div style="max-width:900px;margin-top:30px">
|
||||
<div style="display:flex;align-items:center;gap:16px;margin-bottom:20px">
|
||||
<div style="width:110px;text-align:right;font-weight:700;color:var(--gd-danger)">没有<br>知识库</div>
|
||||
<div style="flex:1;position:relative;height:70px;background:rgba(224,112,112,.06);border:1px solid rgba(224,112,112,.2);border-radius:16px">
|
||||
<div style="position:absolute;left:16px;top:50%;transform:translateY(-50%);font-size:32px">🛵</div>
|
||||
<div style="position:absolute;left:72px;top:50%;transform:translateY(-50%);color:var(--gd-danger);font-size:14px">反复喂信息…整理…又忘了…</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex;align-items:center;gap:16px">
|
||||
<div style="width:110px;text-align:right;font-weight:700;color:var(--gd-green)">有<br>知识库</div>
|
||||
<div style="flex:1;position:relative;height:70px;background:rgba(126,211,164,.06);border:1px solid rgba(126,211,164,.25);border-radius:16px">
|
||||
<div style="position:absolute;right:16px;top:50%;transform:translateY(-50%);font-size:32px">🏎️</div>
|
||||
<div style="position:absolute;right:72px;top:50%;transform:translateY(-50%);color:var(--gd-green);font-size:14px">AI 自己找 → 确认 → 干活!</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gd-grid-3" style="margin-top:36px">
|
||||
<div class="gd-glass gd-glass-warm"><div class="gd-big gd-grad">5×</div><p class="gd-dim" style="margin-top:6px">速度提升</p></div>
|
||||
<div class="gd-glass gd-glass-green"><div class="gd-big gd-grad">-80%</div><p class="gd-dim" style="margin-top:6px">重复喂信息</p></div>
|
||||
<div class="gd-glass gd-glass-blue"><div class="gd-big gd-grad">∞</div><p class="gd-dim" style="margin-top:6px">记忆持久化</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 6. PIPELINE -->
|
||||
<section class="slide">
|
||||
<div class="gd-ambient"><div class="gd-orb gd-orb-2"></div></div>
|
||||
<div class="gd-snum">06 / 08</div>
|
||||
<p class="gd-eyebrow">Pipeline</p>
|
||||
<h2 class="gd-h2">端到端 <span class="gd-grad">4 步走</span></h2>
|
||||
<div style="display:flex;align-items:center;justify-content:center;gap:8px;margin-top:36px">
|
||||
<div class="gd-glass" style="flex:1;text-align:center"><div style="font-size:34px">📂</div><div style="font-weight:600;margin-top:8px">Scan</div><div class="gd-dim" style="font-size:13px">递归读文件</div></div>
|
||||
<div style="color:var(--gd-text3);font-size:24px">→</div>
|
||||
<div class="gd-glass gd-glass-blue" style="flex:1;text-align:center"><div style="font-size:34px">🔬</div><div style="font-weight:600;margin-top:8px">Extract</div><div class="gd-dim" style="font-size:13px">LLM 抽实体</div></div>
|
||||
<div style="color:var(--gd-text3);font-size:24px">→</div>
|
||||
<div class="gd-glass gd-glass-green" style="flex:1;text-align:center"><div style="font-size:34px">🕸️</div><div style="font-weight:600;margin-top:8px">Build</div><div class="gd-dim" style="font-size:13px">构图 + 去重</div></div>
|
||||
<div style="color:var(--gd-text3);font-size:24px">→</div>
|
||||
<div class="gd-glass gd-glass-warm" style="flex:1;text-align:center"><div style="font-size:34px">🎨</div><div style="font-weight:600;margin-top:8px">Render</div><div class="gd-dim" style="font-size:13px">D3 交互图</div></div>
|
||||
</div>
|
||||
<div class="gd-glass" style="margin-top:32px"><p style="font-size:16px;line-height:1.6;color:var(--gd-text2)">每一步都有 audit log:你永远知道某个节点为什么存在、它来自哪个文件的哪一行。</p></div>
|
||||
</section>
|
||||
|
||||
<!-- 7. CTA -->
|
||||
<section class="slide">
|
||||
<div class="gd-ambient"><div class="gd-orb gd-orb-1"></div><div class="gd-orb gd-orb-3"></div></div>
|
||||
<div class="gd-snum">07 / 08</div>
|
||||
<p class="gd-eyebrow">Try it tonight</p>
|
||||
<h2 class="gd-h1" style="font-size:80px">Graphify <span class="gd-grad">your folders</span></h2>
|
||||
<p class="gd-cmd" style="margin-top:22px">$ npm i -g @lewis/graphify</p>
|
||||
<p class="gd-cmd" style="margin-top:10px;color:var(--gd-warm);text-shadow:0 0 30px rgba(232,168,124,.45)">$ graphify ~/obsidian-vault</p>
|
||||
<div style="margin-top:32px">
|
||||
<span class="gd-tag">#knowledge-graph</span>
|
||||
<span class="gd-tag">#open-source</span>
|
||||
<span class="gd-tag">#claude-agent</span>
|
||||
<span class="gd-tag">#obsidian</span>
|
||||
<span class="gd-tag">#d3-force</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 8. THANKS -->
|
||||
<section class="slide">
|
||||
<div class="gd-ambient"><div class="gd-orb gd-orb-2"></div></div>
|
||||
<div class="gd-snum">08 / 08</div>
|
||||
<div style="margin:auto 0;text-align:center">
|
||||
<div class="gd-big gd-rainbow" style="font-size:180px">Thanks.</div>
|
||||
<p class="gd-lede" style="margin:28px auto 0">github.com/lewis/graphify · 欢迎 star / issue / PR</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,54 @@
|
||||
/* graphify-dark-graph — 暗底玻璃 + 力导向知识图谱 */
|
||||
.tpl-graphify-dark-graph{
|
||||
--gd-bg:#06060c;
|
||||
--gd-bg2:#0e1020;
|
||||
--gd-text:#f0ece4;
|
||||
--gd-text2:#b0a99e;
|
||||
--gd-text3:#7a746c;
|
||||
--gd-warm:#e8a87c;
|
||||
--gd-blue:#7eb8da;
|
||||
--gd-green:#7ed3a4;
|
||||
--gd-rose:#d4a0b9;
|
||||
--gd-purple:#b8a4d6;
|
||||
--gd-danger:#e07070;
|
||||
background:var(--gd-bg);
|
||||
color:var(--gd-text);
|
||||
font-family:'Inter','Noto Sans SC',-apple-system,sans-serif;
|
||||
letter-spacing:-.01em;
|
||||
}
|
||||
.tpl-graphify-dark-graph .slide{background:linear-gradient(160deg,#08080f,#0e1020 50%,#08080f);color:var(--gd-text);padding:64px 88px;overflow:hidden}
|
||||
.tpl-graphify-dark-graph .gd-ambient{position:absolute;inset:0;pointer-events:none;z-index:0;overflow:hidden}
|
||||
.tpl-graphify-dark-graph .gd-orb{position:absolute;border-radius:50%;filter:blur(110px);opacity:.35;animation:gdDrift 22s ease-in-out infinite alternate}
|
||||
.tpl-graphify-dark-graph .gd-orb-1{width:520px;height:520px;background:radial-gradient(circle,rgba(126,184,218,.55),transparent 70%);top:-12%;left:-6%}
|
||||
.tpl-graphify-dark-graph .gd-orb-2{width:460px;height:460px;background:radial-gradient(circle,rgba(232,168,124,.45),transparent 70%);top:55%;right:-8%;animation-delay:-6s}
|
||||
.tpl-graphify-dark-graph .gd-orb-3{width:420px;height:420px;background:radial-gradient(circle,rgba(184,164,214,.4),transparent 70%);bottom:-8%;left:30%;animation-delay:-11s}
|
||||
@keyframes gdDrift{0%{transform:translate(0,0) scale(1)}100%{transform:translate(25px,-20px) scale(1.08)}}
|
||||
.tpl-graphify-dark-graph .slide > *{position:relative;z-index:2}
|
||||
.tpl-graphify-dark-graph .gd-snum{position:absolute;top:28px;right:40px;font-size:12px;letter-spacing:.25em;color:var(--gd-text3);z-index:3}
|
||||
.tpl-graphify-dark-graph .gd-eyebrow{font-size:13px;letter-spacing:.2em;text-transform:uppercase;color:var(--gd-text3);font-weight:500}
|
||||
.tpl-graphify-dark-graph .gd-h1{font-size:74px;font-weight:800;line-height:1.08;letter-spacing:-.02em;margin:16px 0 10px;color:var(--gd-text)}
|
||||
.tpl-graphify-dark-graph .gd-h2{font-size:52px;font-weight:700;line-height:1.12;margin:0 0 14px}
|
||||
.tpl-graphify-dark-graph .gd-lede{font-size:22px;line-height:1.65;font-weight:300;color:var(--gd-text2);max-width:850px}
|
||||
.tpl-graphify-dark-graph .gd-rainbow{background:linear-gradient(90deg,#ff0080,#ff4d00,#ff9900,#ffe600,#00c853,#0091ea,#6200ea,#ff0080);background-size:200% auto;-webkit-background-clip:text;-webkit-text-fill-color:transparent;animation:gdRainbow 4s linear infinite}
|
||||
@keyframes gdRainbow{0%{background-position:0% center}100%{background-position:200% center}}
|
||||
.tpl-graphify-dark-graph .gd-grad{background:linear-gradient(135deg,var(--gd-warm),var(--gd-rose),var(--gd-purple));-webkit-background-clip:text;-webkit-text-fill-color:transparent}
|
||||
.tpl-graphify-dark-graph .gd-accent{color:var(--gd-warm);font-weight:500}
|
||||
.tpl-graphify-dark-graph .gd-green{color:var(--gd-green)}
|
||||
.tpl-graphify-dark-graph .gd-blue{color:var(--gd-blue)}
|
||||
.tpl-graphify-dark-graph .gd-dim{color:var(--gd-text2)}
|
||||
.tpl-graphify-dark-graph .gd-mono{font-family:'JetBrains Mono',monospace}
|
||||
.tpl-graphify-dark-graph .gd-glass{position:relative;overflow:hidden;border-radius:20px;padding:22px 26px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.1);backdrop-filter:blur(20px) saturate(160%);box-shadow:0 8px 32px rgba(0,0,0,.3),inset 0 1px 0 rgba(255,255,255,.08)}
|
||||
.tpl-graphify-dark-graph .gd-glass::before{content:'';position:absolute;top:0;left:0;right:0;height:50%;background:linear-gradient(180deg,rgba(255,255,255,.05),transparent);pointer-events:none}
|
||||
.tpl-graphify-dark-graph .gd-glass-warm{background:rgba(232,168,124,.06);border-color:rgba(232,168,124,.2)}
|
||||
.tpl-graphify-dark-graph .gd-glass-green{background:rgba(126,211,164,.06);border-color:rgba(126,211,164,.2)}
|
||||
.tpl-graphify-dark-graph .gd-glass-blue{background:rgba(126,184,218,.06);border-color:rgba(126,184,218,.2)}
|
||||
.tpl-graphify-dark-graph .gd-grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:24px}
|
||||
.tpl-graphify-dark-graph .gd-grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-top:24px}
|
||||
.tpl-graphify-dark-graph .gd-tag{display:inline-block;border-radius:999px;padding:5px 14px;font-size:12px;font-weight:500;margin:2px 4px 2px 0;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.1);color:var(--gd-text2)}
|
||||
.tpl-graphify-dark-graph .gd-cmd{font-family:'JetBrains Mono',monospace;font-size:32px;font-weight:700;color:var(--gd-green);text-shadow:0 0 30px rgba(126,211,164,.45),0 0 60px rgba(126,211,164,.15);letter-spacing:-.01em}
|
||||
.tpl-graphify-dark-graph .gd-big{font-size:120px;font-weight:900;letter-spacing:-.04em;line-height:1}
|
||||
.tpl-graphify-dark-graph .gd-codebox{background:rgba(0,0,0,.55);border:1px solid rgba(255,255,255,.08);border-radius:14px;padding:22px 26px;font-family:'JetBrains Mono',monospace;font-size:14px;line-height:1.8;color:#d8d4c8}
|
||||
.tpl-graphify-dark-graph .gd-codebox .cm{color:#6b6a62}
|
||||
.tpl-graphify-dark-graph .gd-codebox .kw{color:var(--gd-warm)}
|
||||
.tpl-graphify-dark-graph .gd-codebox .st{color:var(--gd-green)}
|
||||
.tpl-graphify-dark-graph .gd-codebox .fn{color:var(--gd-blue)}
|
||||
@@ -0,0 +1,11 @@
|
||||
# hermes-cyber-terminal
|
||||
|
||||
黑底 (`#0a0c10`) + 终端 chrome + 扫描线 + 薄荷绿 glow 大字 + JetBrains Mono 全文打字机感。灵感来自 `20260414-hermes-agent/ppt/hermes-record.html` 的 `codebox #15151b` 深色代码盒和 `hermes-vs-openclaw.html` 的实测对比气质 —— 把两者合成一份「honest cyber review」。
|
||||
|
||||
**Visual traits:** 56px cyber 网格 + CRT vignette + 半透明 scanlines 叠层、窗口 traffic-light chrome、`$ prompt` 开头的 command-line 标题、薄荷绿 text-shadow glow `#7ed3a4`、monospace 全局、虚拟 bar chart 用 stroke-only 呈现、blinking cursor、amber/green/red 分级标签。
|
||||
|
||||
**Use when:** 评测一个开发者工具 / CLI / agent,展示跑分数据、trace、diff;想要即刻给出「技术人 honest review」的视觉语气;适合长 trace / long code 的场景。
|
||||
|
||||
**Source inspiration:** `20260414-hermes-agent/ppt/hermes-record.html` + `hermes-vs-openclaw.html`.
|
||||
|
||||
**Path:** `templates/full-decks/hermes-cyber-terminal/index.html`
|
||||
@@ -0,0 +1,199 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Hermes Cyber Terminal</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-hermes-cyber-terminal">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. COVER -->
|
||||
<section class="slide is-active">
|
||||
<div class="hc-grid"></div>
|
||||
<div class="hc-vignette"></div>
|
||||
<div class="hc-scanlines"></div>
|
||||
<div class="hc-chrome"><div class="dots"><span></span><span></span><span></span></div><div>~/hermes · zsh · 118x42 · 01:37:04</div></div>
|
||||
<div style="margin:auto 0">
|
||||
<p class="hc-prompt">whoami --hermes</p>
|
||||
<h1 class="hc-h1">HERMES<br>AGENT / v0.9.2<span class="hc-cursor"></span></h1>
|
||||
<p class="hc-lede">一个号称能「自主跑完整软件工程任务」的命令行 agent。<br>真的好用?还是又一轮营销?—— 我连续跑了 72 小时,告诉你答案。</p>
|
||||
<div style="margin-top:26px">
|
||||
<span class="hc-tag">rust-core</span>
|
||||
<span class="hc-tag">mcp-native</span>
|
||||
<span class="hc-tag amber">72h-benchmark</span>
|
||||
<span class="hc-tag red">honest-review</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hc-footer"><span>hermes-review · lewis · 2026</span><span>01 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 2. SECTION DIVIDER -->
|
||||
<section class="slide">
|
||||
<div class="hc-grid"></div>
|
||||
<div class="hc-scanlines"></div>
|
||||
<div class="hc-chrome"><div class="dots"><span></span><span></span><span></span></div><div>section · 01/04</div></div>
|
||||
<div style="margin:auto 0">
|
||||
<p class="hc-prompt">cat chapter_01.md</p>
|
||||
<h1 class="hc-h1" style="font-size:110px">// Setup</h1>
|
||||
<p class="hc-lede">从 <code style="color:var(--hc-amber)">brew install hermes</code> 到第一次 prompt —— 一共 4 分 22 秒。</p>
|
||||
</div>
|
||||
<div class="hc-footer"><span>section · setup</span><span>02 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 3. CONTENT — spec cards -->
|
||||
<section class="slide">
|
||||
<div class="hc-grid"></div>
|
||||
<div class="hc-scanlines"></div>
|
||||
<div class="hc-chrome"><div class="dots"><span></span><span></span><span></span></div><div>benchmark · cold-start</div></div>
|
||||
<h2 class="hc-h2">开箱数据</h2>
|
||||
<p class="hc-lede">cold start → first-successful-task 三次平均</p>
|
||||
<div class="hc-grid-3">
|
||||
<div class="hc-card"><div class="lbl">install time</div><div class="val">42s</div><div class="desc">单 binary,无 docker,无 python env。</div></div>
|
||||
<div class="hc-card"><div class="lbl">first token</div><div class="val">1.8s</div><div class="desc">接入 claude-opus-4-6,无预热。</div></div>
|
||||
<div class="hc-card"><div class="lbl">first PR merged</div><div class="val">4m22s</div><div class="desc">跑的是 fix-a-typo 级别的低难度任务。</div></div>
|
||||
</div>
|
||||
<div class="hc-grid-2">
|
||||
<div class="hc-card"><div class="lbl">// verdict +</div><div class="val" style="color:var(--hc-green);font-size:18px">冷启动是真的快</div><div class="desc">和 OpenClaw 的 docker + pip 流程比,快不止一个数量级。</div></div>
|
||||
<div class="hc-card"><div class="lbl">// verdict -</div><div class="val" style="color:var(--hc-red);font-size:18px">MCP 服务器配置不够友好</div><div class="desc">env 变量需要手动塞进 ~/.hermes/env,文档几乎没写。</div></div>
|
||||
</div>
|
||||
<div class="hc-footer"><span>data · verified 3 runs</span><span>03 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 4. CODE -->
|
||||
<section class="slide">
|
||||
<div class="hc-grid"></div>
|
||||
<div class="hc-scanlines"></div>
|
||||
<div class="hc-chrome"><div class="dots"><span></span><span></span><span></span></div><div>trace · hermes run</div></div>
|
||||
<p class="hc-prompt">hermes run "refactor auth module to use pkce"</p>
|
||||
<h3 class="hc-h3" style="margin-top:12px">↓ 真实 trace (节选)</h3>
|
||||
<pre class="hc-codebox" style="margin-top:10px"><span class="cm"># hermes v0.9.2 · session 42a1</span>
|
||||
[<span class="fn">plan</span>] <span class="st">"分析 src/auth/*.ts → 找 oauth flow → 抽成 pkce"</span>
|
||||
[<span class="fn">read</span>] src/auth/oauth.ts <span class="cm">// 214 lines</span>
|
||||
[<span class="fn">read</span>] src/auth/token.ts <span class="cm">// 88 lines</span>
|
||||
[<span class="kw">think</span>] <span class="st">"发现 implicit flow,改为 code+pkce,需新 state param"</span>
|
||||
[<span class="fn">edit</span>] src/auth/oauth.ts <span class="hl">+43 -17</span>
|
||||
[<span class="fn">edit</span>] src/auth/token.ts <span class="hl">+12 -4</span>
|
||||
[<span class="fn">test</span>] pnpm vitest auth <span class="st">PASS 18/18</span>
|
||||
[<span class="fn">commit</span>] <span class="var">"feat(auth): migrate to oauth2 code+pkce"</span>
|
||||
[<span class="fn">push</span>] origin feat/pkce-auth <span class="st">ok</span>
|
||||
|
||||
<span class="cm"># 总耗时 3m 14s · 14k tokens · $0.21</span></pre>
|
||||
<div class="hc-footer"><span>trace · live</span><span>04 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 5. CHART -->
|
||||
<section class="slide">
|
||||
<div class="hc-grid"></div>
|
||||
<div class="hc-scanlines"></div>
|
||||
<div class="hc-chrome"><div class="dots"><span></span><span></span><span></span></div><div>benchmark · hermes vs openclaw</div></div>
|
||||
<h2 class="hc-h2">72 小时对比</h2>
|
||||
<p class="hc-lede">同一组 48 个 GitHub issue,两个 agent 各跑一遍</p>
|
||||
<svg viewBox="0 0 1000 380" style="width:100%;max-width:1040px;margin-top:24px" xmlns="http://www.w3.org/2000/svg">
|
||||
<g font-family="JetBrains Mono, monospace" font-size="13" fill="#8a8892">
|
||||
<!-- axis -->
|
||||
<line x1="80" y1="40" x2="80" y2="320" stroke="rgba(126,211,164,.2)"/>
|
||||
<line x1="80" y1="320" x2="960" y2="320" stroke="rgba(126,211,164,.2)"/>
|
||||
<!-- y labels -->
|
||||
<text x="70" y="46" text-anchor="end">100%</text>
|
||||
<text x="70" y="116" text-anchor="end">75%</text>
|
||||
<text x="70" y="186" text-anchor="end">50%</text>
|
||||
<text x="70" y="256" text-anchor="end">25%</text>
|
||||
<text x="70" y="324" text-anchor="end">0</text>
|
||||
<!-- bars: hermes -->
|
||||
<g>
|
||||
<rect x="130" y="80" width="80" height="240" fill="rgba(126,211,164,.15)" stroke="#7ed3a4" stroke-width="1.5"/>
|
||||
<text x="170" y="76" text-anchor="middle" fill="#7ed3a4" font-weight="700">82%</text>
|
||||
<text x="170" y="345" text-anchor="middle">resolved</text>
|
||||
<rect x="240" y="146" width="80" height="174" fill="rgba(126,211,164,.15)" stroke="#7ed3a4" stroke-width="1.5"/>
|
||||
<text x="280" y="142" text-anchor="middle" fill="#7ed3a4" font-weight="700">58%</text>
|
||||
<text x="280" y="345" text-anchor="middle">one-shot</text>
|
||||
<rect x="350" y="60" width="80" height="260" fill="rgba(126,211,164,.15)" stroke="#7ed3a4" stroke-width="1.5"/>
|
||||
<text x="390" y="56" text-anchor="middle" fill="#7ed3a4" font-weight="700">89%</text>
|
||||
<text x="390" y="345" text-anchor="middle">test-pass</text>
|
||||
<rect x="460" y="110" width="80" height="210" fill="rgba(126,211,164,.15)" stroke="#7ed3a4" stroke-width="1.5"/>
|
||||
<text x="500" y="106" text-anchor="middle" fill="#7ed3a4" font-weight="700">71%</text>
|
||||
<text x="500" y="345" text-anchor="middle">pr-merged</text>
|
||||
</g>
|
||||
<!-- bars: openclaw -->
|
||||
<g>
|
||||
<rect x="570" y="150" width="80" height="170" fill="rgba(233,197,138,.12)" stroke="#e9c58a" stroke-width="1.5"/>
|
||||
<text x="610" y="146" text-anchor="middle" fill="#e9c58a" font-weight="700">60%</text>
|
||||
<text x="610" y="345" text-anchor="middle">resolved</text>
|
||||
<rect x="680" y="212" width="80" height="108" fill="rgba(233,197,138,.12)" stroke="#e9c58a" stroke-width="1.5"/>
|
||||
<text x="720" y="208" text-anchor="middle" fill="#e9c58a" font-weight="700">38%</text>
|
||||
<text x="720" y="345" text-anchor="middle">one-shot</text>
|
||||
<rect x="790" y="130" width="80" height="190" fill="rgba(233,197,138,.12)" stroke="#e9c58a" stroke-width="1.5"/>
|
||||
<text x="830" y="126" text-anchor="middle" fill="#e9c58a" font-weight="700">67%</text>
|
||||
<text x="830" y="345" text-anchor="middle">test-pass</text>
|
||||
</g>
|
||||
<!-- legend -->
|
||||
<g transform="translate(820,50)">
|
||||
<rect x="0" y="0" width="14" height="14" fill="rgba(126,211,164,.15)" stroke="#7ed3a4"/>
|
||||
<text x="22" y="12" fill="#7ed3a4">hermes 0.9.2</text>
|
||||
<rect x="0" y="22" width="14" height="14" fill="rgba(233,197,138,.12)" stroke="#e9c58a"/>
|
||||
<text x="22" y="34" fill="#e9c58a">openclaw 2.1</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<div class="hc-footer"><span>benchmark · n=48</span><span>05 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 6. STATS -->
|
||||
<section class="slide">
|
||||
<div class="hc-grid"></div>
|
||||
<div class="hc-scanlines"></div>
|
||||
<div class="hc-chrome"><div class="dots"><span></span><span></span><span></span></div><div>tldr</div></div>
|
||||
<p class="hc-prompt">echo $VERDICT</p>
|
||||
<div class="hc-big">7.8<span style="font-size:60px;color:var(--hc-ink2)">/ 10</span></div>
|
||||
<p class="hc-lede" style="margin-top:14px">值得装,还不值得完全依赖。</p>
|
||||
<div class="hc-grid-2" style="margin-top:24px">
|
||||
<div class="hc-card"><div class="lbl">+ strong points</div><div class="desc">• rust 本体冷启快<br>• trace 可读性极强<br>• diff 审核友好,commit message 也写得合格</div></div>
|
||||
<div class="hc-card"><div class="lbl">- weak points</div><div class="desc">• plan 阶段偶尔跳步<br>• 超 50k LoC 仓库会 OOM<br>• MCP 配置需要手动塞 env</div></div>
|
||||
</div>
|
||||
<div class="hc-footer"><span>verdict · honest</span><span>06 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 7. CTA -->
|
||||
<section class="slide">
|
||||
<div class="hc-grid"></div>
|
||||
<div class="hc-scanlines"></div>
|
||||
<div class="hc-chrome"><div class="dots"><span></span><span></span><span></span></div><div>install</div></div>
|
||||
<h2 class="hc-h2">想自己跑一遍?</h2>
|
||||
<p class="hc-lede">三条命令,不到 5 分钟就能看见它干第一件事。</p>
|
||||
<pre class="hc-codebox" style="margin-top:22px"><span class="cm"># 1. install</span>
|
||||
<span class="kw">$</span> brew install hermes-agent/tap/hermes
|
||||
|
||||
<span class="cm"># 2. auth (先准备好 anthropic api key)</span>
|
||||
<span class="kw">$</span> hermes auth login
|
||||
|
||||
<span class="cm"># 3. first task</span>
|
||||
<span class="kw">$</span> cd ~/your-repo && hermes run <span class="st">"add a CHANGELOG.md from git log"</span></pre>
|
||||
<div style="margin-top:26px">
|
||||
<span class="hc-tag">brew-ready</span>
|
||||
<span class="hc-tag">opus-4.6</span>
|
||||
<span class="hc-tag amber">needs-api-key</span>
|
||||
</div>
|
||||
<div class="hc-footer"><span>try-it-now</span><span>07 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 8. THANKS -->
|
||||
<section class="slide">
|
||||
<div class="hc-grid"></div>
|
||||
<div class="hc-scanlines"></div>
|
||||
<div class="hc-chrome"><div class="dots"><span></span><span></span><span></span></div><div>EOF</div></div>
|
||||
<div style="margin:auto 0">
|
||||
<p class="hc-prompt">exit 0</p>
|
||||
<h1 class="hc-h1" style="font-size:120px">// thanks<span class="hc-cursor"></span></h1>
|
||||
<p class="hc-lede">完整 trace、48 个任务的 PR 列表、benchmark 脚本都在 <span style="color:var(--hc-amber)">github.com/lewis/hermes-review</span></p>
|
||||
</div>
|
||||
<div class="hc-footer"><span>session closed</span><span>08 / 08</span></div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,55 @@
|
||||
/* hermes-cyber-terminal — 暗终端 + 霓虹绿青 + 扫描线 */
|
||||
.tpl-hermes-cyber-terminal{
|
||||
--hc-bg:#0a0c10;
|
||||
--hc-bg2:#15151b;
|
||||
--hc-surface:#12141a;
|
||||
--hc-border:rgba(126,211,164,.18);
|
||||
--hc-ink:#e4e2d8;
|
||||
--hc-ink2:#8a8892;
|
||||
--hc-green:#7ed3a4;
|
||||
--hc-cyan:#64dfdf;
|
||||
--hc-amber:#e9c58a;
|
||||
--hc-rose:#d4a0b9;
|
||||
--hc-red:#ff6b6b;
|
||||
background:var(--hc-bg);
|
||||
color:var(--hc-ink);
|
||||
font-family:'JetBrains Mono','SF Mono','Inter','Noto Sans SC',monospace;
|
||||
}
|
||||
.tpl-hermes-cyber-terminal .slide{background:var(--hc-bg);color:var(--hc-ink);padding:60px 84px;overflow:hidden}
|
||||
.tpl-hermes-cyber-terminal .hc-scanlines{position:absolute;inset:0;pointer-events:none;z-index:3;background:repeating-linear-gradient(180deg,transparent 0,transparent 3px,rgba(126,211,164,.025) 3px,rgba(126,211,164,.025) 4px);mix-blend-mode:screen}
|
||||
.tpl-hermes-cyber-terminal .hc-grid{position:absolute;inset:0;pointer-events:none;opacity:.35;background-image:linear-gradient(rgba(126,211,164,.08) 1px,transparent 1px),linear-gradient(90deg,rgba(126,211,164,.08) 1px,transparent 1px);background-size:56px 56px;mask-image:radial-gradient(ellipse at 50% 50%,black 30%,transparent 80%)}
|
||||
.tpl-hermes-cyber-terminal .hc-vignette{position:absolute;inset:0;pointer-events:none;background:radial-gradient(ellipse at 50% 50%,transparent 50%,rgba(0,0,0,.6) 100%)}
|
||||
.tpl-hermes-cyber-terminal .slide > *{position:relative;z-index:2}
|
||||
.tpl-hermes-cyber-terminal .hc-chrome{display:flex;align-items:center;justify-content:space-between;margin-bottom:18px;font-size:11px;color:var(--hc-ink2);letter-spacing:.18em;text-transform:uppercase}
|
||||
.tpl-hermes-cyber-terminal .hc-chrome .dots{display:flex;gap:8px}
|
||||
.tpl-hermes-cyber-terminal .hc-chrome .dots span{width:11px;height:11px;border-radius:50%;background:#2a2d33}
|
||||
.tpl-hermes-cyber-terminal .hc-chrome .dots span:nth-child(1){background:#ff5f57}
|
||||
.tpl-hermes-cyber-terminal .hc-chrome .dots span:nth-child(2){background:#febc2e}
|
||||
.tpl-hermes-cyber-terminal .hc-chrome .dots span:nth-child(3){background:var(--hc-green)}
|
||||
.tpl-hermes-cyber-terminal .hc-prompt{color:var(--hc-green);font-weight:500}
|
||||
.tpl-hermes-cyber-terminal .hc-prompt::before{content:'$ ';color:var(--hc-cyan)}
|
||||
.tpl-hermes-cyber-terminal .hc-h1{font-family:'JetBrains Mono',monospace;font-size:72px;font-weight:700;line-height:1.05;letter-spacing:-.02em;color:var(--hc-green);text-shadow:0 0 30px rgba(126,211,164,.35),0 0 60px rgba(126,211,164,.1);margin:14px 0 12px}
|
||||
.tpl-hermes-cyber-terminal .hc-h2{font-size:46px;font-weight:600;color:var(--hc-ink);margin:0 0 10px;letter-spacing:-.015em}
|
||||
.tpl-hermes-cyber-terminal .hc-h3{font-size:22px;font-weight:600;color:var(--hc-amber);margin:0 0 10px}
|
||||
.tpl-hermes-cyber-terminal .hc-lede{font-size:18px;line-height:1.7;color:var(--hc-ink2);max-width:780px;font-family:'Inter','Noto Sans SC',sans-serif}
|
||||
.tpl-hermes-cyber-terminal .hc-cursor{display:inline-block;width:12px;height:1em;background:var(--hc-green);vertical-align:middle;margin-left:6px;animation:hcBlink 1s steps(2) infinite}
|
||||
@keyframes hcBlink{50%{opacity:0}}
|
||||
.tpl-hermes-cyber-terminal .hc-card{background:var(--hc-surface);border:1px solid var(--hc-border);border-radius:10px;padding:20px 24px;position:relative}
|
||||
.tpl-hermes-cyber-terminal .hc-card::before{content:'';position:absolute;top:-1px;left:12px;right:12px;height:2px;background:linear-gradient(90deg,transparent,var(--hc-green),transparent)}
|
||||
.tpl-hermes-cyber-terminal .hc-card .lbl{font-size:10px;letter-spacing:.22em;text-transform:uppercase;color:var(--hc-ink2);margin-bottom:8px}
|
||||
.tpl-hermes-cyber-terminal .hc-card .val{font-size:22px;font-weight:700;color:var(--hc-green);font-family:'JetBrains Mono',monospace}
|
||||
.tpl-hermes-cyber-terminal .hc-card .desc{font-size:13px;color:var(--hc-ink2);margin-top:10px;line-height:1.55;font-family:'Inter',sans-serif}
|
||||
.tpl-hermes-cyber-terminal .hc-grid-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px;margin-top:24px}
|
||||
.tpl-hermes-cyber-terminal .hc-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-top:24px}
|
||||
.tpl-hermes-cyber-terminal .hc-codebox{background:#0c0d12;border:1px solid var(--hc-border);border-radius:10px;padding:22px 26px;font-family:'JetBrains Mono',monospace;font-size:14px;line-height:1.85;color:#d8d4c8;box-shadow:inset 0 0 60px rgba(126,211,164,.04)}
|
||||
.tpl-hermes-cyber-terminal .hc-codebox .cm{color:#5a6068}
|
||||
.tpl-hermes-cyber-terminal .hc-codebox .kw{color:var(--hc-amber)}
|
||||
.tpl-hermes-cyber-terminal .hc-codebox .st{color:var(--hc-green)}
|
||||
.tpl-hermes-cyber-terminal .hc-codebox .fn{color:var(--hc-cyan)}
|
||||
.tpl-hermes-cyber-terminal .hc-codebox .var{color:var(--hc-rose)}
|
||||
.tpl-hermes-cyber-terminal .hc-codebox .hl{color:#fff;background:rgba(126,211,164,.15);padding:0 4px;border-radius:3px}
|
||||
.tpl-hermes-cyber-terminal .hc-tag{display:inline-block;font-family:'JetBrains Mono',monospace;font-size:11px;padding:3px 10px;border:1px solid var(--hc-border);border-radius:4px;color:var(--hc-green);background:rgba(126,211,164,.04);margin:2px 6px 2px 0;text-transform:uppercase;letter-spacing:.1em}
|
||||
.tpl-hermes-cyber-terminal .hc-tag.amber{color:var(--hc-amber);border-color:rgba(233,197,138,.2);background:rgba(233,197,138,.04)}
|
||||
.tpl-hermes-cyber-terminal .hc-tag.red{color:var(--hc-red);border-color:rgba(255,107,107,.25);background:rgba(255,107,107,.05)}
|
||||
.tpl-hermes-cyber-terminal .hc-big{font-family:'JetBrains Mono',monospace;font-size:140px;font-weight:700;line-height:1;color:var(--hc-green);text-shadow:0 0 40px rgba(126,211,164,.4),0 0 80px rgba(126,211,164,.15);letter-spacing:-.04em}
|
||||
.tpl-hermes-cyber-terminal .hc-footer{position:absolute;left:84px;right:84px;bottom:32px;display:flex;justify-content:space-between;font-size:10px;color:var(--hc-ink2);letter-spacing:.2em;text-transform:uppercase;border-top:1px solid rgba(126,211,164,.1);padding-top:14px}
|
||||
@@ -0,0 +1,11 @@
|
||||
# knowledge-arch-blueprint
|
||||
|
||||
奶油纸 (`#F0EAE0`) 底 + 锈红 (`#B5392A`) 单一 accent + 硬黑描边卡片 + 虚线反馈回路箭头。灵感来自 `20260405 架构图v2.html` —— 那是一张真正的「技术白皮书架构图」,像建筑蓝图。
|
||||
|
||||
**Visual traits:** 暖米色纸底、微弱 48px 网格做 blueprint 感、硬朗 2px 黑边卡片、pipeline step-box 一字排开配 hero box 凸起、右上 insight 红色 callout、大小写 kicker 2.5-4px 字距、SVG 反馈回路虚线 + 箭头、Playfair 大字号衬线数据、无渐变无阴影极度克制。
|
||||
|
||||
**Use when:** 讲系统架构、数据流向、流程拆解;你想让内容看起来像一份正经技术白皮书而不是营销贴;需要严肃感、印刷感、可直接截图塞进 README。
|
||||
|
||||
**Source inspiration:** `20260405-Karpathy-知识库/20260405 架构图v2.html`.
|
||||
|
||||
**Path:** `templates/full-decks/knowledge-arch-blueprint/index.html`
|
||||
@@ -0,0 +1,190 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Knowledge Arch Blueprint</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-knowledge-arch-blueprint">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. COVER -->
|
||||
<section class="slide is-active">
|
||||
<div class="kb-grid-bg"></div>
|
||||
<div style="display:flex;justify-content:space-between;align-items:flex-start;gap:40px;margin-bottom:44px">
|
||||
<div>
|
||||
<div class="kb-kicker">Karpathy Stack · 架构图 v2</div>
|
||||
<h1 class="kb-h1">LLM <span class="rust">知识库</span> 的<br>工程化蓝图</h1>
|
||||
<p class="kb-sub">从「乱贴笔记」到「可审计、可纠错、可复用」的第二大脑 —— 这是我读完 Karpathy 的分享后画的一张系统图。</p>
|
||||
</div>
|
||||
<div class="kb-insight"><span class="kk">KEY INSIGHT</span>Karpathy 原版缺一块:<br>反馈闭环让错误能回流纠正。</div>
|
||||
</div>
|
||||
<div class="kb-section-label">Pipeline · End-to-end</div>
|
||||
<div class="kb-pipeline">
|
||||
<div class="kb-step"><div class="kb-step-num">STEP 01</div><div class="kb-step-title">采集</div><div class="kb-step-body">浏览器剪藏、PDF、Podcast 转写、聊天记录</div></div>
|
||||
<div class="kb-step"><div class="kb-step-num">STEP 02</div><div class="kb-step-title">去噪</div><div class="kb-step-body">清洗导航栏、广告、重复段落、低信噪素材</div></div>
|
||||
<div class="kb-step hero"><div class="kb-step-num">STEP 03 · CORE</div><div class="kb-step-title">Wiki 化</div><div class="kb-step-body">结构化成双链笔记,实体、关系、属性全在一起</div></div>
|
||||
<div class="kb-step"><div class="kb-step-num">STEP 04</div><div class="kb-step-title">使用</div><div class="kb-step-body">Agent 随时检索、回答、再写入</div></div>
|
||||
</div>
|
||||
<div class="kb-footer"><span>Blueprint · v2 · 2026.04</span><span>01 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 2. SECTION DIVIDER -->
|
||||
<section class="slide">
|
||||
<div class="kb-grid-bg"></div>
|
||||
<div style="margin:auto 0">
|
||||
<div class="kb-kicker">Chapter One</div>
|
||||
<h1 class="kb-h1" style="font-size:120px">为什么 <span class="rust">笔记</span><br>不够用了</h1>
|
||||
<p class="kb-sub" style="font-size:24px;margin-top:20px">当你的知识量超过记忆容量,<br>你需要的不是更多文件,而是一张<b>可导航的图</b>。</p>
|
||||
</div>
|
||||
<div class="kb-footer"><span>Section · Chapter 1</span><span>02 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 3. CONTENT 2-col -->
|
||||
<section class="slide">
|
||||
<div class="kb-grid-bg"></div>
|
||||
<div class="kb-kicker">Problem · Solution</div>
|
||||
<h1 class="kb-h1" style="font-size:48px">原版 vs <span class="rust">升级版</span></h1>
|
||||
<div class="kb-grid-2">
|
||||
<div class="kb-card">
|
||||
<div class="kb-kicker" style="color:#888">原版 Karpathy</div>
|
||||
<h4>一次性写入</h4>
|
||||
<p>采集 → 转写 → 存档,错了就错了。没有回路,没有修正机制,笔记越多越混乱。</p>
|
||||
</div>
|
||||
<div class="kb-card" style="background:var(--kb-rust-soft);border-color:var(--kb-rust)">
|
||||
<div class="kb-kicker">升级 v2</div>
|
||||
<h4>反馈闭环</h4>
|
||||
<p>AI 使用知识库时记录每次 miss / 幻觉 / 过期事实,自动回灌到源文件,让笔记会自我修正。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kb-legend">
|
||||
<div class="d"><span class="b"></span>普通节点</div>
|
||||
<div class="d"><span class="b rust"></span>核心节点 · 反馈回路入口</div>
|
||||
<div class="d">—— 数据流 ┈┈ 反馈回路</div>
|
||||
</div>
|
||||
<div class="kb-footer"><span>Content · Compare</span><span>03 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 4. CODE -->
|
||||
<section class="slide">
|
||||
<div class="kb-grid-bg"></div>
|
||||
<div class="kb-kicker">Implementation · Skill Manifest</div>
|
||||
<h1 class="kb-h1" style="font-size:48px">反馈回路 <span class="rust">怎么实现</span></h1>
|
||||
<p class="kb-sub">一个 100 行的 Agent Skill,把「AI 用得顺不顺」回写成 vault 的一条条修订记录。</p>
|
||||
<pre class="kb-codebox"><span class="cm"># skills/wiki-feedback/SKILL.md</span>
|
||||
<span class="kw">name</span>: wiki-feedback
|
||||
<span class="kw">trigger</span>: <span class="st">"after every retrieval"</span>
|
||||
|
||||
<span class="kw">on_hit</span>: record(<span class="st">query, path, used=true</span>)
|
||||
<span class="kw">on_miss</span>: record(<span class="st">query, reason=</span><span class="hl">"not-in-vault"</span>)
|
||||
<span class="kw">on_wrong</span>: record(<span class="st">query, correction, path</span>)
|
||||
|
||||
<span class="kw">nightly</span>:
|
||||
- <span class="st">aggregate misses → suggest new notes</span>
|
||||
- <span class="st">aggregate wrongs → diff-patch old notes</span>
|
||||
- <span class="st">commit to git, open PR for human review</span></pre>
|
||||
<div class="kb-footer"><span>Content · Code</span><span>04 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 5. DIAGRAM - SVG feedback loop -->
|
||||
<section class="slide">
|
||||
<div class="kb-grid-bg"></div>
|
||||
<div class="kb-kicker">System Diagram</div>
|
||||
<h1 class="kb-h1" style="font-size:44px">反馈回路全貌</h1>
|
||||
<svg viewBox="0 0 1200 520" style="width:100%;max-width:1200px;margin-top:20px" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
|
||||
<path d="M0,0 L10,5 L0,10 z" fill="#1a1a1a"/>
|
||||
</marker>
|
||||
<marker id="arrow-r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
|
||||
<path d="M0,0 L10,5 L0,10 z" fill="#B5392A"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<g font-family="Inter, sans-serif" font-size="16" font-weight="700">
|
||||
<!-- boxes -->
|
||||
<rect x="40" y="180" width="200" height="120" rx="10" fill="#fff" stroke="#1a1a1a" stroke-width="2"/>
|
||||
<text x="140" y="220" text-anchor="middle">Sources</text>
|
||||
<text x="140" y="250" text-anchor="middle" font-size="12" font-weight="400" fill="#666">web · pdf · chat</text>
|
||||
|
||||
<rect x="300" y="180" width="200" height="120" rx="10" fill="#fff" stroke="#1a1a1a" stroke-width="2"/>
|
||||
<text x="400" y="220" text-anchor="middle">Clean + Split</text>
|
||||
<text x="400" y="250" text-anchor="middle" font-size="12" font-weight="400" fill="#666">defuddle / chunker</text>
|
||||
|
||||
<rect x="560" y="160" width="220" height="160" rx="10" fill="#B5392A" stroke="#B5392A" stroke-width="2"/>
|
||||
<text x="670" y="210" text-anchor="middle" fill="#fff" font-size="20">Vault (Wiki)</text>
|
||||
<text x="670" y="240" text-anchor="middle" font-size="12" font-weight="400" fill="rgba(255,255,255,.8)">markdown · links</text>
|
||||
<text x="670" y="262" text-anchor="middle" font-size="12" font-weight="400" fill="rgba(255,255,255,.8)">bases · canvas</text>
|
||||
|
||||
<rect x="840" y="180" width="200" height="120" rx="10" fill="#fff" stroke="#1a1a1a" stroke-width="2"/>
|
||||
<text x="940" y="220" text-anchor="middle">Agent Use</text>
|
||||
<text x="940" y="250" text-anchor="middle" font-size="12" font-weight="400" fill="#666">retrieve / answer</text>
|
||||
|
||||
<!-- forward arrows -->
|
||||
<line x1="245" y1="240" x2="295" y2="240" stroke="#1a1a1a" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<line x1="505" y1="240" x2="555" y2="240" stroke="#1a1a1a" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
<line x1="785" y1="240" x2="835" y2="240" stroke="#1a1a1a" stroke-width="2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- feedback dashed -->
|
||||
<path d="M 940 180 Q 940 80, 670 80 Q 400 80, 400 180" fill="none" stroke="#B5392A" stroke-width="2" stroke-dasharray="6 6" marker-end="url(#arrow-r)"/>
|
||||
<rect x="580" y="58" width="180" height="30" rx="6" fill="#F0EAE0" stroke="#B5392A" stroke-width="1"/>
|
||||
<text x="670" y="78" text-anchor="middle" fill="#B5392A" font-size="12">FEEDBACK · wrong / miss</text>
|
||||
|
||||
<!-- bottom feedback to sources -->
|
||||
<path d="M 940 300 Q 940 420, 670 420 Q 140 420, 140 300" fill="none" stroke="#B5392A" stroke-width="2" stroke-dasharray="6 6" marker-end="url(#arrow-r)"/>
|
||||
<rect x="560" y="400" width="220" height="30" rx="6" fill="#F0EAE0" stroke="#B5392A" stroke-width="1"/>
|
||||
<text x="670" y="420" text-anchor="middle" fill="#B5392A" font-size="12">NIGHTLY · suggest new sources</text>
|
||||
</g>
|
||||
</svg>
|
||||
<div class="kb-footer"><span>Diagram · Feedback Loop</span><span>05 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 6. STATS -->
|
||||
<section class="slide">
|
||||
<div class="kb-grid-bg"></div>
|
||||
<div class="kb-kicker">After 6 Months</div>
|
||||
<h1 class="kb-h1" style="font-size:44px">升级版 <span class="rust">跑了半年</span> 的数据</h1>
|
||||
<div style="display:grid;grid-template-columns:1.3fr 1fr 1fr;gap:24px;margin-top:28px;align-items:center">
|
||||
<div style="text-align:center"><div class="kb-big-num">13</div><p style="font-size:14px;color:#666;margin-top:6px;letter-spacing:.1em;text-transform:uppercase">关键优化项 · 全部落地</p></div>
|
||||
<div class="kb-card"><h4 style="color:var(--kb-rust)">-62%</h4><p>幻觉率(相比无反馈回路版本)</p></div>
|
||||
<div class="kb-card"><h4 style="color:var(--kb-rust)">+4.1×</h4><p>单次检索命中率</p></div>
|
||||
</div>
|
||||
<div class="kb-grid-2" style="margin-top:18px">
|
||||
<div class="kb-card"><h4>自动修订 227 条</h4><p>其中 189 条被人工批准合并,38 条被拒绝(数据已归档)。</p></div>
|
||||
<div class="kb-card"><h4>新增笔记 412 篇</h4><p>从 miss 日志聚类而来,每篇都有来源追溯。</p></div>
|
||||
</div>
|
||||
<div class="kb-footer"><span>Content · Stats</span><span>06 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 7. CTA -->
|
||||
<section class="slide">
|
||||
<div class="kb-grid-bg"></div>
|
||||
<div class="kb-kicker">Next Step</div>
|
||||
<h1 class="kb-h1" style="font-size:60px">开始你的 <span class="rust">Wiki v2</span></h1>
|
||||
<p class="kb-sub">不用重写所有笔记。先接一条回路,让 AI 的每次使用都在「改好」你的 vault。</p>
|
||||
<div class="kb-pipeline">
|
||||
<div class="kb-step"><div class="kb-step-num">TONIGHT</div><div class="kb-step-title">装 Skill</div><div class="kb-step-body">pnpm i -g @lewis/wiki-feedback</div></div>
|
||||
<div class="kb-step"><div class="kb-step-num">DAY 2</div><div class="kb-step-title">跑 7 天</div><div class="kb-step-body">观察 miss log 自动累积</div></div>
|
||||
<div class="kb-step hero"><div class="kb-step-num">DAY 8 · CORE</div><div class="kb-step-title">第一次审 PR</div><div class="kb-step-body">花 15 分钟 review 自动生成的修订</div></div>
|
||||
<div class="kb-step"><div class="kb-step-num">MONTH 1</div><div class="kb-step-title">开始信它</div><div class="kb-step-body">你的 vault 会变成活的</div></div>
|
||||
</div>
|
||||
<div class="kb-footer"><span>CTA</span><span>07 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 8. THANKS -->
|
||||
<section class="slide">
|
||||
<div class="kb-grid-bg"></div>
|
||||
<div style="margin:auto 0;text-align:center">
|
||||
<div class="kb-kicker">END · blueprint v2</div>
|
||||
<h1 class="kb-h1" style="font-size:140px;margin-top:24px">谢谢 <span class="rust">·</span> thanks</h1>
|
||||
<p class="kb-sub" style="margin:0 auto;font-size:22px">图纸、Skill、笔记模板都在 <b>github.com/lewis/karpathy-wiki-v2</b></p>
|
||||
</div>
|
||||
<div class="kb-footer"><span>End of deck</span><span>08 / 08</span></div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,49 @@
|
||||
/* knowledge-arch-blueprint — 奶油纸 + 建筑蓝图风 */
|
||||
.tpl-knowledge-arch-blueprint{
|
||||
--kb-bg:#F0EAE0;
|
||||
--kb-ink:#1a1a1a;
|
||||
--kb-ink2:#555;
|
||||
--kb-ink3:#aaa;
|
||||
--kb-rust:#B5392A;
|
||||
--kb-rust-soft:rgba(181,57,42,.08);
|
||||
--kb-line:#cec8be;
|
||||
background:var(--kb-bg);
|
||||
color:var(--kb-ink);
|
||||
font-family:'Inter','Noto Sans SC',-apple-system,sans-serif;
|
||||
}
|
||||
.tpl-knowledge-arch-blueprint .slide{background:var(--kb-bg);color:var(--kb-ink);padding:64px 80px}
|
||||
.tpl-knowledge-arch-blueprint .kb-grid-bg{position:absolute;inset:0;pointer-events:none;opacity:.35;background-image:linear-gradient(rgba(26,26,26,.06) 1px,transparent 1px),linear-gradient(90deg,rgba(26,26,26,.06) 1px,transparent 1px);background-size:48px 48px;mask-image:radial-gradient(ellipse at center,black 40%,transparent 85%)}
|
||||
.tpl-knowledge-arch-blueprint .slide > *{position:relative;z-index:2}
|
||||
.tpl-knowledge-arch-blueprint .kb-kicker{font-size:13px;font-weight:800;letter-spacing:4px;text-transform:uppercase;color:var(--kb-rust);margin-bottom:12px}
|
||||
.tpl-knowledge-arch-blueprint .kb-h1{font-size:66px;font-weight:900;line-height:1.08;color:#111;margin:0 0 14px;letter-spacing:-.02em}
|
||||
.tpl-knowledge-arch-blueprint .kb-h1 span.rust{color:var(--kb-rust)}
|
||||
.tpl-knowledge-arch-blueprint .kb-sub{font-size:20px;color:#666;line-height:1.55;max-width:780px}
|
||||
.tpl-knowledge-arch-blueprint .kb-insight{display:inline-block;background:var(--kb-rust);color:#fff;border-radius:10px;padding:16px 22px;font-size:14px;font-weight:700;line-height:1.5;max-width:340px;box-shadow:0 8px 24px rgba(181,57,42,.22)}
|
||||
.tpl-knowledge-arch-blueprint .kb-insight .kk{font-size:10px;letter-spacing:2px;opacity:.7;display:block;margin-bottom:6px;font-weight:800}
|
||||
.tpl-knowledge-arch-blueprint .kb-section-label{font-size:11px;font-weight:800;letter-spacing:3.5px;text-transform:uppercase;color:#aaa;margin:30px 0 12px;display:flex;align-items:center;gap:14px}
|
||||
.tpl-knowledge-arch-blueprint .kb-section-label::after{content:'';flex:1;height:1px;background:var(--kb-line)}
|
||||
.tpl-knowledge-arch-blueprint .kb-pipeline{display:flex;align-items:stretch;gap:14px;margin-top:24px}
|
||||
.tpl-knowledge-arch-blueprint .kb-step{flex:1;border:2px solid #1a1a1a;border-radius:12px;padding:22px 18px;background:#fff;position:relative;min-height:200px;display:flex;flex-direction:column}
|
||||
.tpl-knowledge-arch-blueprint .kb-step.hero{background:var(--kb-rust);border-color:var(--kb-rust);color:#fff;flex:1.25;box-shadow:0 10px 32px rgba(181,57,42,.28);transform:translateY(-10px)}
|
||||
.tpl-knowledge-arch-blueprint .kb-step-num{font-size:10px;font-weight:800;letter-spacing:2.5px;color:#bbb;margin-bottom:8px;text-transform:uppercase}
|
||||
.tpl-knowledge-arch-blueprint .kb-step.hero .kb-step-num{color:rgba(255,255,255,.6)}
|
||||
.tpl-knowledge-arch-blueprint .kb-step-title{font-size:22px;font-weight:900;line-height:1.15;color:#111;margin-bottom:8px}
|
||||
.tpl-knowledge-arch-blueprint .kb-step.hero .kb-step-title{color:#fff}
|
||||
.tpl-knowledge-arch-blueprint .kb-step-body{font-size:13px;line-height:1.55;color:#555;margin-top:auto}
|
||||
.tpl-knowledge-arch-blueprint .kb-step.hero .kb-step-body{color:rgba(255,255,255,.88)}
|
||||
.tpl-knowledge-arch-blueprint .kb-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-top:24px}
|
||||
.tpl-knowledge-arch-blueprint .kb-card{background:#fff;border:2px solid #1a1a1a;border-radius:12px;padding:22px 24px}
|
||||
.tpl-knowledge-arch-blueprint .kb-card h4{font-size:20px;font-weight:900;margin-bottom:6px}
|
||||
.tpl-knowledge-arch-blueprint .kb-card p{font-size:14px;color:#555;line-height:1.55}
|
||||
.tpl-knowledge-arch-blueprint .kb-legend{display:flex;gap:18px;flex-wrap:wrap;margin-top:22px;font-size:12px;color:#666}
|
||||
.tpl-knowledge-arch-blueprint .kb-legend .d{display:flex;align-items:center;gap:8px}
|
||||
.tpl-knowledge-arch-blueprint .kb-legend .b{width:14px;height:14px;border:2px solid #1a1a1a;border-radius:3px}
|
||||
.tpl-knowledge-arch-blueprint .kb-legend .b.rust{background:var(--kb-rust);border-color:var(--kb-rust)}
|
||||
.tpl-knowledge-arch-blueprint .kb-footer{position:absolute;left:80px;right:80px;bottom:36px;display:flex;justify-content:space-between;font-size:11px;color:#999;letter-spacing:.15em;text-transform:uppercase;border-top:1px solid var(--kb-line);padding-top:16px}
|
||||
.tpl-knowledge-arch-blueprint .kb-mono{font-family:'JetBrains Mono',monospace}
|
||||
.tpl-knowledge-arch-blueprint .kb-codebox{background:#1a1a1a;color:#f0eae0;border-radius:12px;padding:22px 26px;font-family:'JetBrains Mono',monospace;font-size:14px;line-height:1.8;margin-top:20px;border:2px solid #1a1a1a}
|
||||
.tpl-knowledge-arch-blueprint .kb-codebox .cm{color:#7a766c}
|
||||
.tpl-knowledge-arch-blueprint .kb-codebox .kw{color:#e8a87c}
|
||||
.tpl-knowledge-arch-blueprint .kb-codebox .st{color:#b3d1bc}
|
||||
.tpl-knowledge-arch-blueprint .kb-codebox .hl{color:var(--kb-rust);background:rgba(255,255,255,.08);padding:0 4px;border-radius:3px}
|
||||
.tpl-knowledge-arch-blueprint .kb-big-num{font-family:'Playfair Display',Georgia,serif;font-size:200px;font-weight:900;line-height:.9;color:var(--kb-rust);letter-spacing:-.04em}
|
||||
@@ -0,0 +1,11 @@
|
||||
# obsidian-claude-gradient
|
||||
|
||||
GitHub-dark (`#0d1117`) + 紫色 ambient radial + 60px 遮罩网格 + 紫→蓝→绿渐变文字。灵感来自 `20260406-obsidian-claude/slides.html` 的 `--accent #7c3aed`、`.cbg` 双 radial cover、`.cgrid` 60px 遮罩网格以及 `.g` 三停渐变。
|
||||
|
||||
**Visual traits:** 深灰蓝底 + 紫蓝 radial 晕染 + 暗网格遮罩、居中对齐的标题/正文、圆角紫色 pill tag、linear `#a855f7→#60a5fa→#34d399` 渐变字、GitHub-ish 代码色 (`#010409` 背景 + 紫/蓝/橙/绿 token)、紫色左边框 highlight 块、简洁 step 列表。
|
||||
|
||||
**Use when:** 讲一个开发者友好的工作流、MCP / Agent / Dev tool 教程;你希望气质接近 GitHub Blog / Linear Changelog;内容以配置文件 + 步骤为主。
|
||||
|
||||
**Source inspiration:** `20260406-obsidian-claude/slides.html`.
|
||||
|
||||
**Path:** `templates/full-decks/obsidian-claude-gradient/index.html`
|
||||
@@ -0,0 +1,144 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Obsidian × Claude Gradient</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-obsidian-claude-gradient">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. COVER -->
|
||||
<section class="slide is-active">
|
||||
<div class="oc-cbg"></div>
|
||||
<div class="oc-cgrid"></div>
|
||||
<div class="oc-snum">01 / 08</div>
|
||||
<div class="oc-tag">● OBSIDIAN × CLAUDE · 第二大脑</div>
|
||||
<h1 class="oc-h1">把 Obsidian 和 Claude<br>拧成 <span class="oc-g">一条神经</span></h1>
|
||||
<p class="oc-sub">不是又一个 AI 笔记插件 —— 是让 Claude 真正理解你 vault 的结构、链接、双向引用,<br>然后在你想写东西之前就把资料准备好。</p>
|
||||
<div style="margin-top:32px">
|
||||
<span class="oc-pill">🧠 Markdown-native</span>
|
||||
<span class="oc-pill">⚡ MCP-ready</span>
|
||||
<span class="oc-pill">🔗 双链理解</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 2. SECTION -->
|
||||
<section class="slide">
|
||||
<div class="oc-cbg"></div>
|
||||
<div class="oc-cgrid"></div>
|
||||
<div class="oc-snum">02 / 08</div>
|
||||
<div class="oc-tag">● CHAPTER 01</div>
|
||||
<h1 class="oc-h1" style="font-size:110px">Why <span class="oc-g">not</span> Notion?</h1>
|
||||
<p class="oc-sub">当你的知识多到会互相引用时,<br>「文件夹」就不够了,「数据库」也不是答案。</p>
|
||||
</section>
|
||||
|
||||
<!-- 3. CONTENT — compare cards -->
|
||||
<section class="slide">
|
||||
<div class="oc-cbg"></div>
|
||||
<div class="oc-cgrid"></div>
|
||||
<div class="oc-snum">03 / 08</div>
|
||||
<div class="oc-tag">● COMPARE</div>
|
||||
<h2 class="oc-h2">Notion vs <span class="oc-g">Obsidian</span> · 对 AI 友好度</h2>
|
||||
<div class="oc-grid-2">
|
||||
<div class="oc-card">
|
||||
<span class="oc-badge oc-bb">NOTION</span>
|
||||
<h4 style="font-size:20px;margin-bottom:10px">数据库原生</h4>
|
||||
<p style="color:var(--oc-dim);font-size:14px;line-height:1.65">适合结构化任务、团队协作,但是——<br>• AI 要走 API,拿不到实时全文<br>• 嵌套块结构复杂,token 成本高<br>• 本地化差,没法当长期记忆</p>
|
||||
</div>
|
||||
<div class="oc-card" style="border-color:rgba(168,85,247,.35);background:rgba(124,58,237,.05)">
|
||||
<span class="oc-badge oc-bp">OBSIDIAN</span>
|
||||
<h4 style="font-size:20px;margin-bottom:10px">纯 Markdown + 双链</h4>
|
||||
<p style="color:var(--oc-dim);font-size:14px;line-height:1.65">对 AI 天生友好 ——<br>• 所有东西就是文件,Claude 直接读<br>• 双链 = 天然 graph,抽实体几乎零成本<br>• 离线、可 git、可 diff、可回滚</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oc-hl" style="margin-top:26px">💡 <b>关键洞察:</b>AI 不需要「更聪明的数据库」,它需要「能被它自己读懂的文件系统」。</div>
|
||||
</section>
|
||||
|
||||
<!-- 4. STEPS -->
|
||||
<section class="slide">
|
||||
<div class="oc-cbg"></div>
|
||||
<div class="oc-cgrid"></div>
|
||||
<div class="oc-snum">04 / 08</div>
|
||||
<div class="oc-tag">● SETUP · 4 STEPS</div>
|
||||
<h2 class="oc-h2">从 0 到第一次「AI 写笔记」</h2>
|
||||
<div class="oc-steps">
|
||||
<div class="oc-step"><div class="oc-sn">1</div><div class="oc-sc"><h4>装 Obsidian + 开 Local REST API 插件</h4><p>社区插件,一个勾就开。它让外部进程能 read/write 你的 vault。</p></div></div>
|
||||
<div class="oc-step"><div class="oc-sn">2</div><div class="oc-sc"><h4>接 Claude Desktop + obsidian-mcp server</h4><p>MCP 一个配置文件就能接,token 填 vault 的 api key。</p></div></div>
|
||||
<div class="oc-step"><div class="oc-sn">3</div><div class="oc-sc"><h4>装 5 个 obsidian-skills</h4><p>markdown / bases / canvas / cli / defuddle —— 让 Claude 知道怎么正确使用 Obsidian。</p></div></div>
|
||||
<div class="oc-step"><div class="oc-sn">4</div><div class="oc-sc"><h4>让 Claude 自己整理一次</h4><p>「帮我把最近 10 篇笔记里的重复概念合并,生成一张新的 MOC」—— 90 秒出结果。</p></div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 5. CODE -->
|
||||
<section class="slide">
|
||||
<div class="oc-cbg"></div>
|
||||
<div class="oc-cgrid"></div>
|
||||
<div class="oc-snum">05 / 08</div>
|
||||
<div class="oc-tag">● MCP CONFIG</div>
|
||||
<h2 class="oc-h2">claude_desktop_config.json</h2>
|
||||
<pre class="oc-code"><span class="cm">// ~/Library/Application Support/Claude/claude_desktop_config.json</span>
|
||||
{
|
||||
<span class="cc">"mcpServers"</span>: {
|
||||
<span class="cc">"obsidian"</span>: {
|
||||
<span class="cc">"command"</span>: <span class="cs">"npx"</span>,
|
||||
<span class="cc">"args"</span>: [<span class="cs">"-y"</span>, <span class="cs">"@modelcontextprotocol/server-obsidian"</span>],
|
||||
<span class="cc">"env"</span>: {
|
||||
<span class="cc">"OBSIDIAN_API_KEY"</span>: <span class="cs">"xxxxxxxxxxxxxxxx"</span>,
|
||||
<span class="cc">"OBSIDIAN_HOST"</span>: <span class="cs">"http://127.0.0.1:27123"</span>
|
||||
}
|
||||
}
|
||||
}
|
||||
}</pre>
|
||||
<p class="oc-sub" style="margin-top:18px">重启 Claude Desktop,输入 <b style="color:var(--oc-accent3)">/mcp</b>,你会看到 obsidian 已连。</p>
|
||||
</section>
|
||||
|
||||
<!-- 6. STATS -->
|
||||
<section class="slide">
|
||||
<div class="oc-cbg"></div>
|
||||
<div class="oc-cgrid"></div>
|
||||
<div class="oc-snum">06 / 08</div>
|
||||
<div class="oc-tag">● 3 MONTHS IN</div>
|
||||
<h2 class="oc-h2">跑了 90 天,我的 <span class="oc-g">vault 数据</span></h2>
|
||||
<div class="oc-grid-3" style="margin-top:28px">
|
||||
<div class="oc-card" style="text-align:center"><div class="oc-big oc-g" style="font-size:80px">1,842</div><p style="color:var(--oc-dim);margin-top:8px;font-size:13px">notes in vault</p></div>
|
||||
<div class="oc-card" style="text-align:center"><div class="oc-big oc-g" style="font-size:80px">6.3k</div><p style="color:var(--oc-dim);margin-top:8px;font-size:13px">backlinks (由 AI 自动补)</p></div>
|
||||
<div class="oc-card" style="text-align:center"><div class="oc-big oc-g" style="font-size:80px">-74%</div><p style="color:var(--oc-dim);margin-top:8px;font-size:13px">找资料平均耗时</p></div>
|
||||
</div>
|
||||
<div class="oc-hl" style="margin-top:26px">最大收益不是「AI 帮我写」,而是「AI 帮我把旧笔记重新连起来」—— 每周 30 分钟,vault 就会主动生长。</div>
|
||||
</section>
|
||||
|
||||
<!-- 7. QUOTE / CTA -->
|
||||
<section class="slide">
|
||||
<div class="oc-cbg"></div>
|
||||
<div class="oc-cgrid"></div>
|
||||
<div class="oc-snum">07 / 08</div>
|
||||
<div class="oc-tag">● CTA · 今晚可以做</div>
|
||||
<div class="oc-quote">
|
||||
<blockquote>不要再找「AI 笔记应用」了。<br>你要的是一个 <span class="oc-g">文件夹 + 一条神经</span>。</blockquote>
|
||||
<div class="attr">— 我自己,用了 90 天后</div>
|
||||
</div>
|
||||
<div style="margin-top:36px">
|
||||
<span class="oc-pill">⬇ obsidian.md</span>
|
||||
<span class="oc-pill">⬇ Claude Desktop</span>
|
||||
<span class="oc-pill">⬇ obsidian-mcp</span>
|
||||
<span class="oc-pill">⬇ obsidian-skills × 5</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 8. THANKS -->
|
||||
<section class="slide">
|
||||
<div class="oc-cbg"></div>
|
||||
<div class="oc-cgrid"></div>
|
||||
<div class="oc-snum">08 / 08</div>
|
||||
<div class="oc-big oc-g">Thanks.</div>
|
||||
<p class="oc-sub" style="margin-top:26px">配置模板、skill manifest、我的 vault 结构图都在 <b style="color:var(--oc-accent3)">github.com/lewis/obsidian-claude</b></p>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,59 @@
|
||||
/* obsidian-claude-gradient — 紫色暗底 + GitHub-ish 渐变卡 */
|
||||
.tpl-obsidian-claude-gradient{
|
||||
--oc-bg:#0d1117;
|
||||
--oc-surface:#161b22;
|
||||
--oc-surface2:#21262d;
|
||||
--oc-border:#30363d;
|
||||
--oc-accent:#7c3aed;
|
||||
--oc-accent2:#a855f7;
|
||||
--oc-accent3:#c084fc;
|
||||
--oc-green:#3fb950;
|
||||
--oc-blue:#58a6ff;
|
||||
--oc-orange:#f97316;
|
||||
--oc-yellow:#fbbf24;
|
||||
--oc-red:#f87171;
|
||||
--oc-text:#e6edf3;
|
||||
--oc-dim:#8b949e;
|
||||
--oc-dimmer:#484f58;
|
||||
background:var(--oc-bg);
|
||||
color:var(--oc-text);
|
||||
font-family:'Inter','Noto Sans SC','PingFang SC',-apple-system,sans-serif;
|
||||
}
|
||||
.tpl-obsidian-claude-gradient .slide{background:var(--oc-bg);color:var(--oc-text);padding:64px 88px;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;overflow:hidden}
|
||||
.tpl-obsidian-claude-gradient .oc-cbg{position:absolute;inset:0;pointer-events:none;background:radial-gradient(ellipse at 28% 38%,rgba(124,58,237,.25) 0%,transparent 60%),radial-gradient(ellipse at 72% 62%,rgba(88,166,255,.18) 0%,transparent 60%)}
|
||||
.tpl-obsidian-claude-gradient .oc-cgrid{position:absolute;inset:0;pointer-events:none;background-image:linear-gradient(rgba(48,54,61,.4) 1px,transparent 1px),linear-gradient(90deg,rgba(48,54,61,.4) 1px,transparent 1px);background-size:60px 60px;mask-image:radial-gradient(ellipse at center,black 35%,transparent 80%)}
|
||||
.tpl-obsidian-claude-gradient .slide > *{position:relative;z-index:2}
|
||||
.tpl-obsidian-claude-gradient .oc-snum{position:absolute;top:24px;right:36px;color:var(--oc-dimmer);font-size:12px;letter-spacing:.1em;z-index:3}
|
||||
.tpl-obsidian-claude-gradient .oc-tag{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--oc-accent3);background:rgba(124,58,237,.14);border:1px solid rgba(168,85,247,.3);padding:5px 16px;border-radius:999px;margin-bottom:22px}
|
||||
.tpl-obsidian-claude-gradient .oc-h1{font-size:72px;font-weight:800;line-height:1.08;letter-spacing:-.02em;margin:0 0 10px;color:var(--oc-text)}
|
||||
.tpl-obsidian-claude-gradient .oc-h2{font-size:44px;font-weight:700;line-height:1.18;letter-spacing:-.015em;margin:0 0 14px}
|
||||
.tpl-obsidian-claude-gradient .oc-sub{font-size:19px;color:var(--oc-dim);line-height:1.65;max-width:720px;margin-top:14px}
|
||||
.tpl-obsidian-claude-gradient .oc-g{background:linear-gradient(135deg,#a855f7 0%,#60a5fa 55%,#34d399 100%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
|
||||
.tpl-obsidian-claude-gradient .oc-card{background:var(--oc-surface);border:1px solid var(--oc-border);border-radius:14px;padding:22px 26px;text-align:left;position:relative;overflow:hidden}
|
||||
.tpl-obsidian-claude-gradient .oc-card::before{content:'';position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(168,85,247,.4),transparent)}
|
||||
.tpl-obsidian-claude-gradient .oc-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:18px;width:100%;max-width:1000px;margin-top:24px}
|
||||
.tpl-obsidian-claude-gradient .oc-grid-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px;width:100%;max-width:1080px;margin-top:24px}
|
||||
.tpl-obsidian-claude-gradient .oc-badge{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:600;padding:3px 11px;border-radius:999px;margin-bottom:10px}
|
||||
.tpl-obsidian-claude-gradient .oc-bp{background:rgba(168,85,247,.15);color:var(--oc-accent3)}
|
||||
.tpl-obsidian-claude-gradient .oc-bb{background:rgba(88,166,255,.15);color:var(--oc-blue)}
|
||||
.tpl-obsidian-claude-gradient .oc-bg{background:rgba(63,185,80,.15);color:var(--oc-green)}
|
||||
.tpl-obsidian-claude-gradient .oc-bo{background:rgba(249,115,22,.15);color:var(--oc-orange)}
|
||||
.tpl-obsidian-claude-gradient .oc-code{background:#010409;border:1px solid var(--oc-border);border-radius:12px;padding:20px 24px;font-family:'JetBrains Mono',monospace;font-size:14px;line-height:1.85;width:100%;max-width:860px;text-align:left;color:#e6edf3}
|
||||
.tpl-obsidian-claude-gradient .oc-code .cp{color:var(--oc-green)}
|
||||
.tpl-obsidian-claude-gradient .oc-code .cc{color:var(--oc-blue)}
|
||||
.tpl-obsidian-claude-gradient .oc-code .ca{color:var(--oc-accent3)}
|
||||
.tpl-obsidian-claude-gradient .oc-code .cm{color:var(--oc-dimmer)}
|
||||
.tpl-obsidian-claude-gradient .oc-code .cs{color:var(--oc-orange)}
|
||||
.tpl-obsidian-claude-gradient .oc-hl{background:rgba(124,58,237,.1);border:1px solid rgba(168,85,247,.3);border-left:4px solid var(--oc-accent2);border-radius:0 12px 12px 0;padding:16px 22px;font-size:16px;line-height:1.7;max-width:860px;text-align:left}
|
||||
.tpl-obsidian-claude-gradient .oc-steps{display:flex;flex-direction:column;gap:0;width:100%;max-width:820px;text-align:left}
|
||||
.tpl-obsidian-claude-gradient .oc-step{display:flex;gap:20px;align-items:flex-start;padding:18px 0;border-bottom:1px solid var(--oc-border)}
|
||||
.tpl-obsidian-claude-gradient .oc-step:last-child{border-bottom:none}
|
||||
.tpl-obsidian-claude-gradient .oc-sn{width:36px;height:36px;flex-shrink:0;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:15px;background:linear-gradient(135deg,var(--oc-accent),var(--oc-blue));color:#fff}
|
||||
.tpl-obsidian-claude-gradient .oc-sc h4{font-size:17px;font-weight:600;margin-bottom:6px;color:var(--oc-text)}
|
||||
.tpl-obsidian-claude-gradient .oc-sc p{font-size:14px;color:var(--oc-dim);line-height:1.6}
|
||||
.tpl-obsidian-claude-gradient .oc-pill{display:inline-flex;align-items:center;gap:8px;background:var(--oc-surface2);border:1px solid var(--oc-border);border-radius:999px;padding:7px 18px;font-size:14px;font-weight:500;color:var(--oc-text);margin:4px 6px 4px 0}
|
||||
.tpl-obsidian-claude-gradient .oc-quote{max-width:800px}
|
||||
.tpl-obsidian-claude-gradient .oc-quote blockquote{font-size:26px;font-weight:500;line-height:1.6;position:relative;padding:0 36px;margin:0;color:var(--oc-text)}
|
||||
.tpl-obsidian-claude-gradient .oc-quote blockquote::before{content:'"';position:absolute;left:-6px;top:-22px;font-size:78px;color:var(--oc-accent);opacity:.4;font-family:Georgia,serif;line-height:1}
|
||||
.tpl-obsidian-claude-gradient .oc-quote .attr{margin-top:20px;font-size:13px;color:var(--oc-dim)}
|
||||
.tpl-obsidian-claude-gradient .oc-big{font-size:140px;font-weight:900;line-height:.95;letter-spacing:-.04em}
|
||||
@@ -0,0 +1,9 @@
|
||||
# pitch-deck
|
||||
|
||||
Classic 10-slide YC/VC seed pitch: cover, problem, solution, product, market, business model, traction, team, ask, thanks.
|
||||
|
||||
Clean white background, bold blue→purple gradient accent, oversized headlines and big numbers — the look investors expect when they skim 40 decks a day.
|
||||
|
||||
**Use when:** pitching a fundraise, office hours, or a "state of the company" update. Swap copy, keep structure.
|
||||
**Feel:** confident, data-forward, founder-friendly.
|
||||
**Brand color:** override `--grad` in `style.css` to re-skin.
|
||||
@@ -0,0 +1,148 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Lumen · Pitch Deck</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" href="../../../assets/animations/animations.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-pitch-deck">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. Cover -->
|
||||
<section class="slide" data-title="Cover">
|
||||
<div class="cover-bg"></div>
|
||||
<div class="cover-blob"></div>
|
||||
<div style="position:absolute;top:56px;left:112px"><span class="brand-dot"></span><span class="brand">Lumen</span></div>
|
||||
<p class="kicker">Seed round · 2026</p>
|
||||
<h1 class="h1 anim-fade-up" data-anim="fade-up">The operating system<br>for <span class="gradient-text">solo founders</span>.</h1>
|
||||
<p class="lede mt-m">One workspace for billing, CRM, contracts and taxes — built for the 70M people running a business of one.</p>
|
||||
<div class="deck-footer"><span>Maya Chen · CEO</span><span class="slide-number" data-current="1" data-total="10"></span></div>
|
||||
</section>
|
||||
|
||||
<!-- 2. Problem -->
|
||||
<section class="slide" data-title="Problem">
|
||||
<span class="section-num">01</span>
|
||||
<p class="num-tag">PROBLEM</p>
|
||||
<h2 class="h2 mt-s">Solo founders duct-tape<br>7+ tools to stay alive.</h2>
|
||||
<div class="grid g3 mt-l">
|
||||
<div class="card"><h4>Fragmentation</h4><p class="dim">Stripe, QuickBooks, HubSpot, DocuSign, Notion, Gusto, a spreadsheet. Nothing talks.</p></div>
|
||||
<div class="card"><h4>$480/mo wasted</h4><p class="dim">Average solo founder pays for 9 SaaS seats they only half-use.</p></div>
|
||||
<div class="card"><h4>14 hrs / week lost</h4><p class="dim">Copy-pasting between tools instead of selling.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 3. Solution -->
|
||||
<section class="slide" data-title="Solution">
|
||||
<span class="section-num">02</span>
|
||||
<p class="num-tag">SOLUTION</p>
|
||||
<h2 class="h2 mt-s">Lumen is <span class="gradient-text">one spine</span><br>for the business of one.</h2>
|
||||
<p class="lede mt-m">Invoice a client → the payment lands → the tax is reserved → the contract is filed → your dashboard updates. In one app. Without plumbing.</p>
|
||||
<div class="row mt-l">
|
||||
<span class="pill pill-accent">Billing</span>
|
||||
<span class="pill pill-accent">CRM</span>
|
||||
<span class="pill pill-accent">Contracts</span>
|
||||
<span class="pill pill-accent">Taxes</span>
|
||||
<span class="pill pill-accent">Banking</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 4. Product -->
|
||||
<section class="slide" data-title="Product">
|
||||
<span class="section-num">03</span>
|
||||
<p class="num-tag">PRODUCT</p>
|
||||
<h2 class="h2 mt-s">Built around "jobs to be done".</h2>
|
||||
<div class="grid g2 mt-l">
|
||||
<div class="card card-hover"><h4>Get paid</h4><p class="dim">Invoices, subscriptions and Stripe/Wise payouts with a single click. ACH, card, wire, crypto.</p></div>
|
||||
<div class="card card-hover"><h4>Stay legal</h4><p class="dim">E-sign contracts from templates. Auto-file 1099s and quarterly estimates.</p></div>
|
||||
<div class="card card-hover"><h4>Sell smarter</h4><p class="dim">Lead inbox, pipeline, email sequences. No separate CRM.</p></div>
|
||||
<div class="card card-hover"><h4>See the business</h4><p class="dim">Live P&L, runway, top customers, churn. One dashboard, zero spreadsheets.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 5. Market -->
|
||||
<section class="slide" data-title="Market">
|
||||
<span class="section-num">04</span>
|
||||
<p class="num-tag">MARKET</p>
|
||||
<h2 class="h2 mt-s">A very big small business.</h2>
|
||||
<div class="grid g3 mt-l">
|
||||
<div class="metric"><div class="n">73M</div><div class="l">solo businesses in the US + EU</div></div>
|
||||
<div class="metric"><div class="n">$186B</div><div class="l">TAM · horizontal SaaS spend</div></div>
|
||||
<div class="metric"><div class="n">9.4%</div><div class="l">CAGR through 2030</div></div>
|
||||
</div>
|
||||
<p class="lede mt-l">Creators, consultants, indie devs, coaches, freelancers — the fastest-growing segment of the workforce, and the most under-served by tooling.</p>
|
||||
</section>
|
||||
|
||||
<!-- 6. Business model -->
|
||||
<section class="slide" data-title="Business Model">
|
||||
<span class="section-num">05</span>
|
||||
<p class="num-tag">BUSINESS MODEL</p>
|
||||
<h2 class="h2 mt-s">Flat SaaS + payment rake.</h2>
|
||||
<div class="grid g3 mt-l">
|
||||
<div class="card"><h4>Starter</h4><div class="metric mt-s"><div class="n" style="font-size:56px">$29</div><div class="l">/ month · core billing + CRM</div></div></div>
|
||||
<div class="card card-accent"><h4>Pro</h4><div class="metric mt-s"><div class="n" style="font-size:56px">$79</div><div class="l">/ month · contracts, taxes, banking</div></div></div>
|
||||
<div class="card"><h4>+ Payments</h4><div class="metric mt-s"><div class="n" style="font-size:56px">0.4%</div><div class="l">interchange rake on processed volume</div></div></div>
|
||||
</div>
|
||||
<p class="dim mt-l">Blended LTV $1,920 · CAC payback 5 months at current funnel.</p>
|
||||
</section>
|
||||
|
||||
<!-- 7. Traction -->
|
||||
<section class="slide" data-title="Traction">
|
||||
<span class="section-num">06</span>
|
||||
<p class="num-tag">TRACTION</p>
|
||||
<h2 class="h2 mt-s">6 months, growing 38% MoM.</h2>
|
||||
<div class="traction-bar mt-l">
|
||||
<div class="bar" style="height:18%"><em>$6k</em><span>Oct</span></div>
|
||||
<div class="bar" style="height:30%"><em>$11k</em><span>Nov</span></div>
|
||||
<div class="bar" style="height:44%"><em>$17k</em><span>Dec</span></div>
|
||||
<div class="bar" style="height:62%"><em>$26k</em><span>Jan</span></div>
|
||||
<div class="bar" style="height:82%"><em>$38k</em><span>Feb</span></div>
|
||||
<div class="bar" style="height:100%"><em>$54k</em><span>Mar</span></div>
|
||||
</div>
|
||||
<p class="dim mt-l" style="margin-top:48px">2,140 paying customers · NPS 72 · Net retention 118%</p>
|
||||
</section>
|
||||
|
||||
<!-- 8. Team -->
|
||||
<section class="slide" data-title="Team">
|
||||
<span class="section-num">07</span>
|
||||
<p class="num-tag">TEAM</p>
|
||||
<h2 class="h2 mt-s">Shipped at scale before.</h2>
|
||||
<div class="grid g3 mt-l">
|
||||
<div class="card team-card"><div class="avatar">MC</div><h4>Maya Chen</h4><p class="dim">CEO · ex-Stripe billing lead. 8 yrs in payments.</p></div>
|
||||
<div class="card team-card"><div class="avatar">RP</div><h4>Raj Patel</h4><p class="dim">CTO · ex-Linear. Built multiplayer sync at 10M users.</p></div>
|
||||
<div class="card team-card"><div class="avatar">EK</div><h4>Elena Kim</h4><p class="dim">Head of Design · ex-Notion. Shipped the mobile relaunch.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 9. Ask -->
|
||||
<section class="slide" data-title="The Ask">
|
||||
<p class="num-tag">THE ASK</p>
|
||||
<div class="ask-box mt-m">
|
||||
<h2 class="h2">Raising $4.5M seed.</h2>
|
||||
<p class="lede" style="color:rgba(255,255,255,.9);max-width:60ch">18 months of runway to reach $3M ARR. 40% engineering, 35% growth, 15% compliance/banking licenses, 10% runway buffer.</p>
|
||||
<div class="row mt-l" style="gap:40px">
|
||||
<div><div style="font-size:44px;font-weight:900">$4.5M</div><div class="dim">SAFE · post-money cap $28M</div></div>
|
||||
<div><div style="font-size:44px;font-weight:900">18 mo</div><div class="dim">runway to Series A</div></div>
|
||||
<div><div style="font-size:44px;font-weight:900">$3M</div><div class="dim">ARR target by close</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 10. Thanks -->
|
||||
<section class="slide center tc" data-title="Thanks">
|
||||
<div class="cover-bg"></div>
|
||||
<div>
|
||||
<div class="mega">Thanks.</div>
|
||||
<p class="mega-sub">maya@lumen.app · lumen.app/investors</p>
|
||||
<div class="row mt-l" style="justify-content:center;gap:24px">
|
||||
<span class="pill pill-accent">Let's talk</span>
|
||||
<span class="pill">Deck v4.2 · Apr 2026</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,40 @@
|
||||
/* pitch-deck — classic YC/VC pitch */
|
||||
.tpl-pitch-deck{
|
||||
--bg:#ffffff;--bg-soft:#f6f7fb;--surface:#ffffff;--surface-2:#f2f4fa;
|
||||
--border:rgba(20,25,60,.08);--border-strong:rgba(20,25,60,.18);
|
||||
--text-1:#0d1130;--text-2:#4a5070;--text-3:#8a90ad;
|
||||
--accent:#3b5bff;--accent-2:#7a46ff;--accent-3:#d94cff;
|
||||
--grad:linear-gradient(135deg,#3b5bff 0%,#7a46ff 55%,#d94cff 100%);
|
||||
--grad-soft:linear-gradient(135deg,#eef1ff,#f4edff 55%,#fbedff);
|
||||
--radius:20px;--radius-lg:28px;
|
||||
--shadow:0 14px 40px rgba(20,25,60,.08),0 2px 8px rgba(20,25,60,.04);
|
||||
font-family:'Inter','Noto Sans SC',sans-serif;
|
||||
}
|
||||
.tpl-pitch-deck .slide{padding:88px 112px}
|
||||
.tpl-pitch-deck .kicker{color:var(--accent);font-weight:700}
|
||||
.tpl-pitch-deck .h1{font-size:86px;line-height:1.02;font-weight:900;letter-spacing:-.035em}
|
||||
.tpl-pitch-deck .h2{font-size:62px;font-weight:800;letter-spacing:-.03em}
|
||||
.tpl-pitch-deck .mega{font-size:180px;font-weight:900;line-height:.95;letter-spacing:-.05em;background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent}
|
||||
.tpl-pitch-deck .mega-sub{font-size:28px;color:var(--text-2);margin-top:18px}
|
||||
.tpl-pitch-deck .cover-bg{position:absolute;inset:0;background:var(--grad-soft);z-index:-1}
|
||||
.tpl-pitch-deck .cover-blob{position:absolute;right:-140px;top:-140px;width:560px;height:560px;border-radius:50%;background:var(--grad);filter:blur(8px);opacity:.35;z-index:-1}
|
||||
.tpl-pitch-deck .brand-dot{display:inline-block;width:14px;height:14px;border-radius:50%;background:var(--grad);margin-right:10px;vertical-align:middle}
|
||||
.tpl-pitch-deck .brand{font-weight:800;font-size:22px;letter-spacing:-.02em}
|
||||
.tpl-pitch-deck .card{border-radius:var(--radius)}
|
||||
.tpl-pitch-deck .num-tag{font-family:'Inter',sans-serif;font-size:14px;font-weight:700;color:var(--accent);letter-spacing:.12em}
|
||||
.tpl-pitch-deck .big-q{font-family:'Playfair Display',serif;font-size:56px;line-height:1.15;font-weight:700;letter-spacing:-.02em;max-width:22ch}
|
||||
.tpl-pitch-deck .metric{display:flex;flex-direction:column;gap:6px}
|
||||
.tpl-pitch-deck .metric .n{font-size:72px;font-weight:900;letter-spacing:-.035em;background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent;line-height:1}
|
||||
.tpl-pitch-deck .metric .l{color:var(--text-2);font-size:16px}
|
||||
.tpl-pitch-deck .team-card{text-align:center;padding:32px 20px}
|
||||
.tpl-pitch-deck .avatar{width:96px;height:96px;border-radius:50%;margin:0 auto 14px;background:var(--grad);display:flex;align-items:center;justify-content:center;color:#fff;font-weight:800;font-size:32px}
|
||||
.tpl-pitch-deck .ask-box{background:var(--grad);color:#fff;padding:56px 64px;border-radius:var(--radius-lg);box-shadow:0 30px 70px rgba(59,91,255,.35)}
|
||||
.tpl-pitch-deck .ask-box .h2{color:#fff}
|
||||
.tpl-pitch-deck .ask-box .dim{color:rgba(255,255,255,.85)}
|
||||
.tpl-pitch-deck .traction-bar{display:flex;align-items:flex-end;gap:14px;height:240px;margin-top:24px}
|
||||
.tpl-pitch-deck .traction-bar .bar{flex:1;background:var(--grad);border-radius:8px 8px 0 0;position:relative;min-height:20px}
|
||||
.tpl-pitch-deck .traction-bar .bar span{position:absolute;bottom:-28px;left:0;right:0;text-align:center;font-size:13px;color:var(--text-3)}
|
||||
.tpl-pitch-deck .traction-bar .bar em{position:absolute;top:-28px;left:0;right:0;text-align:center;font-size:14px;font-weight:700;font-style:normal;color:var(--text-1)}
|
||||
.tpl-pitch-deck .section-num{font-size:220px;font-weight:900;line-height:.9;color:var(--surface-2);position:absolute;right:72px;bottom:40px;z-index:0;letter-spacing:-.05em}
|
||||
.tpl-pitch-deck .slide > *{position:relative;z-index:1}
|
||||
.tpl-pitch-deck .deck-footer{color:var(--text-3)}
|
||||
@@ -0,0 +1,102 @@
|
||||
# presenter-mode-reveal · 演讲者模式模板
|
||||
|
||||
一份专为**带逐字稿的技术分享**设计的 full-deck 模板。核心卖点是真正可用的**磁吸卡片式演讲者视图**:当前页 iframe 预览 + 下页 iframe 预览 + 大字号逐字稿 + 计时器,4 个卡片可任意拖拽/缩放,全部集成在 `runtime.js` 里,零依赖。
|
||||
|
||||
## 使用场景
|
||||
|
||||
- 技术分享 / tech talk(30-60 min)
|
||||
- 产品发布会主讲
|
||||
- 课程讲授
|
||||
- 任何**需要照着讲、但不能念稿**的正式演讲
|
||||
|
||||
## 快速开始
|
||||
|
||||
```bash
|
||||
cp -r templates/full-decks/presenter-mode-reveal examples/my-talk
|
||||
open examples/my-talk/index.html
|
||||
```
|
||||
|
||||
## 键盘操作
|
||||
|
||||
| 键 | 动作 |
|
||||
|---|---|
|
||||
| `S` | 打开演讲者窗口(弹出新窗口,原页面不动) |
|
||||
| `T` | 切换主题(5 种预设) |
|
||||
| `←` `→` | 翻页 |
|
||||
| `Space` / `PgDn` | 下一页 |
|
||||
| `F` | 全屏 |
|
||||
| `O` | 总览缩略图 |
|
||||
| `R` | 重置计时器(仅演讲者视图下) |
|
||||
| `Esc` | 关闭所有浮层 |
|
||||
|
||||
## 主题切换
|
||||
|
||||
模板预设了 5 个适配演讲场景的主题,在 `<html data-themes="...">` 属性里:
|
||||
|
||||
```html
|
||||
<html lang="zh-CN" data-themes="tokyo-night,dracula,catppuccin-mocha,nord,corporate-clean">
|
||||
```
|
||||
|
||||
按 `T` 循环切换。可以改成任何 `assets/themes/*.css` 里的主题。
|
||||
|
||||
## 写逐字稿的规范
|
||||
|
||||
**每一页的 `<aside class="notes">` 里写 150–300 字**。三条铁律:
|
||||
|
||||
1. **不是讲稿,是提示信号** — 核心点加粗、过渡句成段、数据列清楚
|
||||
2. **150–300 字/页** — 按 2–3 分钟/页的节奏
|
||||
3. **用口语写** — "因此" → "所以";"该方案" → "这个方案";读一遍不拗口才对
|
||||
|
||||
示例:
|
||||
```html
|
||||
<aside class="notes">
|
||||
<p>大家好,今天跟大家聊一个 <strong>很多人忽略的问题</strong>——...</p>
|
||||
<p>我先抛一个观点:<em>做 PPT 和讲 PPT 是两件事</em>。</p>
|
||||
<p>接下来我会用 3 个例子证明这个观点...</p>
|
||||
</aside>
|
||||
```
|
||||
|
||||
支持的 inline 标签:
|
||||
- `<strong>` — 高亮(橘色)
|
||||
- `<em>` — 斜体强调(蓝色)
|
||||
- `<code>` — 等宽字体
|
||||
- `<p>` — 分段(推荐每段讲 30-60 秒的内容)
|
||||
|
||||
## 文件结构
|
||||
|
||||
```
|
||||
presenter-mode-reveal/
|
||||
├── index.html # 6 张示例 slide,每页都有完整逐字稿
|
||||
├── style.css # scoped .tpl-presenter-mode-reveal 样式
|
||||
└── README.md # 本文件
|
||||
```
|
||||
|
||||
## 修改 / 扩展
|
||||
|
||||
- **加页**:复制任意 `<section class="slide">` 块,改内容和 `<aside class="notes">`
|
||||
- **换主题**:改 `data-themes` 列表,或直接改 `<link id="theme-link" href="...">`
|
||||
- **改样式**:只动 `style.css`,不要碰根目录的 `assets/base.css`
|
||||
- **加动效**:在元素上加 `data-anim="fade-up"` 等(参考 `references/animations.md`)
|
||||
|
||||
## 演讲者窗口的 4 个卡片
|
||||
|
||||
按 `S` 后弹出的窗口里有:
|
||||
|
||||
- 🔵 **CURRENT** — 当前页 iframe 预览(加载 `?preview=N` 模式,像素级完美,与观众端同 CSS/主题/字体)
|
||||
- 🟣 **NEXT** — 下一页预览,帮助准备过渡
|
||||
- 🟠 **SPEAKER SCRIPT** — 大字号逐字稿,可滚动
|
||||
- 🟢 **TIMER** — 经过时间 + 页码 + Prev/Next/Reset 按钮
|
||||
|
||||
卡片操作:
|
||||
- **拖卡片头**(彩色圆点 + 标题的顶部条)→ 移动卡片
|
||||
- **拖卡片右下角** → 调整大小
|
||||
- 位置 + 尺寸自动存 localStorage,下次打开恢复
|
||||
- 底部 "重置布局" 按钮可恢复默认卡片排列
|
||||
|
||||
翻页丝滑:iframe 只加载一次,后续翻页通过 `postMessage` 切换内部 slide,**不重新加载不闪烁**。两窗口通过 `BroadcastChannel` 双向同步。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- **观众永远看不到 `.notes` 内容** — CSS 默认 `display:none`,只在演讲者视图里可见
|
||||
- **别把只给自己看的话写在 slide 本体上** — 所有提词必须在 `<aside class="notes">` 里
|
||||
- **双屏演讲**:打开 `index.html` 按 S 弹出演讲者窗口,把观众窗口拖到投影/外接屏 F 全屏,演讲者窗口留在自己屏幕
|
||||
@@ -0,0 +1,187 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN" data-themes="tokyo-night,dracula,catppuccin-mocha,nord,corporate-clean">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>演讲者模式示例 · Presenter Mode Deck</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../../assets/themes/tokyo-night.css">
|
||||
<link rel="stylesheet" href="../../../assets/animations/animations.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-presenter-mode-reveal">
|
||||
<div class="deck">
|
||||
|
||||
<!-- ============ 1. COVER ============ -->
|
||||
<section class="slide" data-title="Cover">
|
||||
<p class="kicker">presenter-mode / demo</p>
|
||||
<h1 class="h1 anim-fade-up" data-anim="fade-up">如何做一场<br><span style="background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent">有逐字稿</span>的技术分享</h1>
|
||||
<p class="lede mt-m">按 <span class="mono">S</span> 进入演讲者视图 · <span class="mono">T</span> 切换主题 · <span class="mono">← →</span> 翻页</p>
|
||||
<div class="speaker">
|
||||
<div class="av"></div>
|
||||
<div><b>@lewis</b><span>sharing talk · 30 min</span></div>
|
||||
</div>
|
||||
<div class="deck-footer">
|
||||
<span class="mono">#presenter #逐字稿 #tech-talk</span>
|
||||
<span class="slide-number" data-current="1" data-total="6"></span>
|
||||
</div>
|
||||
<aside class="notes">
|
||||
<p>大家好,欢迎来到今天的技术分享。我是 lewis,今天想跟大家聊一个很多人忽略但其实非常影响演讲效果的话题——<strong>如何让一场技术分享既有深度,又讲得不卡壳</strong>。</p>
|
||||
<p>在正式开始之前,先跟大家介绍一下这份 deck 本身:这是一个支持<em>演讲者模式</em>的 HTML 幻灯片模板。现在你们看到的是观众视图,但我自己的屏幕上看到的是完全不一样的东西——当前页、下一页、完整逐字稿、计时器,全在一块屏幕上。</p>
|
||||
<p>为什么我要专门做这个?因为我发现自己做技术分享时最大的痛点不是 PPT 不够好看,而是<strong>讲到某一页突然不知道该说什么,或者忘了过渡怎么接</strong>。今天这份分享既是内容本身,也是个演示——我会一直开着演讲者模式讲,你们可以观察我讲得有多流畅。</p>
|
||||
<p>今天分享大概 30 分钟,分 5 个部分。有问题随时打断。Let's go.</p>
|
||||
</aside>
|
||||
</section>
|
||||
|
||||
<!-- ============ 2. AGENDA ============ -->
|
||||
<section class="slide" data-title="Agenda">
|
||||
<p class="kicker">agenda</p>
|
||||
<h2 class="h2">今天要讲的 5 件事</h2>
|
||||
<div class="stack mt-l">
|
||||
<div class="agenda-row"><span class="num">01</span><span class="t">为什么 PPT 本身做得好还不够</span><span class="d">~5min</span></div>
|
||||
<div class="agenda-row"><span class="num">02</span><span class="t">演讲者模式到底该有哪些信息</span><span class="d">~6min</span></div>
|
||||
<div class="agenda-row"><span class="num">03</span><span class="t">逐字稿怎么写才不像念稿</span><span class="d">~8min</span></div>
|
||||
<div class="agenda-row"><span class="num">04</span><span class="t">Live demo · html-ppt skill 怎么用</span><span class="d">~8min</span></div>
|
||||
<div class="agenda-row"><span class="num">05</span><span class="t">Takeaways + Q&A</span><span class="d">~3min</span></div>
|
||||
</div>
|
||||
<aside class="notes">
|
||||
<p>先过一下今天的议程。</p>
|
||||
<p>第一部分我想先说服你们<strong>"PPT 做得漂亮≠讲得好"</strong>。我见过太多很精致的 deck,但讲的人一上去就开始 "嗯…这个…就是…"。</p>
|
||||
<p>第二部分聊演讲者视图。业界的产品其实差别蛮大的,Keynote、PowerPoint、reveal.js 都有各自的方案,但真正好用的设计逻辑是什么,我会给出我的答案。</p>
|
||||
<p>第三部分是今天的<em>核心</em>——逐字稿。很多人以为逐字稿就是把要说的话一字不差写下来,错。逐字稿的目的是让你<strong>"看一眼就接得上"</strong>,写法完全不一样。</p>
|
||||
<p>第四部分会现场 demo 我自己用的 html-ppt skill,展示如何 30 分钟出一份带逐字稿的 deck。</p>
|
||||
<p>最后收尾 + 答疑。</p>
|
||||
<p>OK,进入第一部分。</p>
|
||||
</aside>
|
||||
</section>
|
||||
|
||||
<!-- ============ 3. PROBLEM ============ -->
|
||||
<section class="slide" data-title="Problem">
|
||||
<p class="kicker">// part 01 · problem</p>
|
||||
<h2 class="h2">做 PPT 和讲 PPT,<br>是<span class="accent">两件事</span>。</h2>
|
||||
<div class="grid g3 mt-l">
|
||||
<div class="card card-accent">
|
||||
<h4>✅ PPT 做得好</h4>
|
||||
<p class="dim">主题统一、排版干净、图表清晰、动效克制。这些是"静态作品"的质量。</p>
|
||||
</div>
|
||||
<div class="card card-accent">
|
||||
<h4>❌ 讲得好</h4>
|
||||
<p class="dim">逻辑连贯、语速稳定、不 "嗯啊"、能接住问题、能当场调整节奏。</p>
|
||||
</div>
|
||||
<div class="card card-accent">
|
||||
<h4>💡 差别在哪</h4>
|
||||
<p class="dim">前者是<strong>纸上功夫</strong>,后者需要你<strong>"看一眼幻灯片就知道下句话说什么"</strong>。</p>
|
||||
</div>
|
||||
</div>
|
||||
<aside class="notes">
|
||||
<p>我先抛一个可能有争议的观点——<strong>做 PPT 和讲 PPT 是两件完全不同的事</strong>。</p>
|
||||
<p>大家看左边这张卡片,"PPT 做得好" 意味着什么?主题统一、排版干净、图表清晰、动效克制——这些都是<em>静态作品</em>的质量标准,可以离线评判。</p>
|
||||
<p>但中间这张卡片就不一样了:"讲得好" 意味着逻辑连贯、语速稳定、不卡壳、能接住提问、能根据现场反应调整节奏——这些是<strong>临场能力</strong>,跟 PPT 好不好看基本没关系。</p>
|
||||
<p>最关键的是右边这句话——讲得好的人,本质上是"<strong>看一眼幻灯片就知道下句话说什么</strong>"。这个能力靠什么?不是背稿,也不是即兴发挥,而是靠<em>合理设计的提词器系统</em>。</p>
|
||||
<p>今天接下来 25 分钟,我就是围绕这个核心问题展开的。</p>
|
||||
</aside>
|
||||
</section>
|
||||
|
||||
<!-- ============ 4. SOLUTION ============ -->
|
||||
<section class="slide" data-title="Presenter View">
|
||||
<p class="kicker">// part 02 · presenter view</p>
|
||||
<h2 class="h2">演讲者视图应该有<span class="accent">四块信息</span></h2>
|
||||
<div class="grid g2 mt-l">
|
||||
<div>
|
||||
<div class="feature-row"><span class="num blue">①</span><div><b>当前页大图</b><p class="dim">占视图一半以上,保证你能扫一眼就知道观众现在看到什么。</p></div></div>
|
||||
<div class="feature-row"><span class="num green">②</span><div><b>下一页预览</b><p class="dim">帮你提前准备过渡句,避免"下一页我忘了讲什么了"。</p></div></div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="feature-row"><span class="num orange">③</span><div><b>逐字稿区域</b><p class="dim">大字号、高对比度、支持滚动,这才是演讲者真正在看的东西。</p></div></div>
|
||||
<div class="feature-row"><span class="num purple">④</span><div><b>计时器 + 页码</b><p class="dim">知道自己讲了多久、还剩几页,节奏全凭这个。</p></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<aside class="notes">
|
||||
<p>演讲者模式应该给你四块信息。我按重要性排序。</p>
|
||||
<p>第一块,<strong>当前页大图</strong>。这个必须占据视图一半以上空间,因为它是你跟观众的"同步锚"——观众看到什么,你脑子里也得是什么。</p>
|
||||
<p>第二块,<strong>下一页预览</strong>。这个很多人不理解为什么要放,我解释一下:演讲最卡的瞬间不是讲某一页,而是<em>翻到下一页的那 2 秒</em>。如果你提前看到下一页长什么样,过渡句自然就有了。</p>
|
||||
<p>第三块,<strong>逐字稿区域</strong>——这是今天的重点,下一部分我会专门讲。这里先说一个硬性要求:字号必须大、对比度必须高、必须能滚动。因为你讲的时候<em>只有余光瞄一下</em>,字小了根本来不及读。</p>
|
||||
<p>第四块,<strong>计时器和页码</strong>。知道自己讲了多久、还剩几页——节奏感全靠它。Keynote 做得最好,reveal.js 默认不够清楚。</p>
|
||||
<p>这四块缺一不可。今天这个 deck 我把这四块都做出来了,按 S 大家可以试试。</p>
|
||||
</aside>
|
||||
</section>
|
||||
|
||||
<!-- ============ 5. SCRIPT ============ -->
|
||||
<section class="slide" data-title="Script">
|
||||
<p class="kicker">// part 03 · script</p>
|
||||
<h2 class="h2">逐字稿的<span class="accent">3 条铁律</span></h2>
|
||||
<div class="stack mt-l">
|
||||
<div class="rule-row">
|
||||
<span class="num red">01</span>
|
||||
<div>
|
||||
<b>不是一字不差的讲稿,是<span class="accent">"提示信号"</span></b>
|
||||
<p class="dim">把要讲的核心点加粗,把过渡句单独成段,把数据和名字列清楚——<em>让你看一眼就接得上</em>。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rule-row">
|
||||
<span class="num red">02</span>
|
||||
<div>
|
||||
<b>每页 <span class="accent">150–300 字</span>,不多不少</b>
|
||||
<p class="dim">少于 150 字提示不够,多于 300 字你没时间读。按 2–3 分钟/页的节奏控制。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rule-row">
|
||||
<span class="num red">03</span>
|
||||
<div>
|
||||
<b>用<span class="accent">口语</span>写,不用书面语</b>
|
||||
<p class="dim">"因此" → "所以";"该方案" → "这个方案"。写的时候读一遍,听起来像说话才对。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<aside class="notes">
|
||||
<p>进入最核心的一部分——逐字稿怎么写。我总结了 3 条铁律。</p>
|
||||
<p><strong>第一条,逐字稿不是讲稿</strong>。很多人一听"逐字稿"就以为要把每句话一字不差写下来。错。如果你照着稿念,观众会立刻看出来,信任感瞬间崩塌。</p>
|
||||
<p>逐字稿的真实作用是<em>"提示信号"</em>——把核心要点加粗,把过渡句单独成段,把数据和专有名词列清楚。这样你讲的时候<strong>瞄一眼就能接得上</strong>,但说出来的还是你自己的话。</p>
|
||||
<p><strong>第二条,每页控制在 150 到 300 字</strong>。这个是我做了十几场分享摸出来的经验值。少于 150 字提示不够,讲到一半卡住;多于 300 字你根本来不及扫完。按一页讲 2 到 3 分钟算,这个字数刚好。</p>
|
||||
<p><strong>第三条,用口语写</strong>。这条最多人栽跟头。你写"因此",讲出来会变成"所以";你写"该方案",讲出来会变成"这个方案"。<em>写的时候读一遍</em>,不拗口才对。</p>
|
||||
<p>这三条配合起来,你会发现讲 PPT 突然变成了一件很舒服的事。</p>
|
||||
</aside>
|
||||
</section>
|
||||
|
||||
<!-- ============ 6. DEMO + CLOSING ============ -->
|
||||
<section class="slide" data-title="Demo & Close">
|
||||
<p class="kicker">// part 04-05 · demo + close</p>
|
||||
<h2 class="h2">现在<span class="accent">你也能做到</span></h2>
|
||||
<div class="code-block mt-m">
|
||||
<span class="comment"># 安装 html-ppt skill</span>
|
||||
<span class="cmd">npx</span> skills add <span class="flag">https://github.com/lewislulu/html-ppt-skill</span>
|
||||
|
||||
<span class="comment"># 复制演讲者模式模板</span>
|
||||
<span class="cmd">cp -r</span> templates/full-decks/presenter-mode-reveal examples/my-talk
|
||||
<span class="cmd">open</span> examples/my-talk/index.html
|
||||
|
||||
<span class="comment"># 键盘操作</span>
|
||||
<span class="flag">S</span> <span class="comment">→ 进入演讲者视图</span>
|
||||
<span class="flag">T</span> <span class="comment">→ 切换主题(5 种预设)</span>
|
||||
<span class="flag">← →</span> <span class="comment">→ 翻页</span>
|
||||
<span class="flag">R</span> <span class="comment">→ 重置计时器</span>
|
||||
</div>
|
||||
<p class="lede mt-m tc">关键是:<strong>每一页 <aside class="notes"> 里写 150–300 字逐字稿</strong>。</p>
|
||||
<div class="deck-footer">
|
||||
<span class="mono">#thanks · Q&A</span>
|
||||
<span class="slide-number" data-current="6" data-total="6"></span>
|
||||
</div>
|
||||
<aside class="notes">
|
||||
<p>最后我演示一下这个 skill 怎么用,给大家省点时间自己摸索。</p>
|
||||
<p>第一步,装 html-ppt skill,一行命令。第二步,把我这个 <code>presenter-mode-reveal</code> 模板复制到你自己的 examples 目录。第三步,打开 html,按 S。</p>
|
||||
<p>键盘操作我列在这里了。<strong>S 进入演讲者视图、T 切换主题、左右键翻页、R 重置计时器</strong>。主题默认带 5 个——tokyo-night、dracula、catppuccin-mocha、nord、corporate-clean——基本覆盖了深色技术分享、浅色商务汇报两种常见场景。</p>
|
||||
<p>最关键的一步——<em>每一页底部的 <code><aside class="notes"></code> 里,老老实实写 150 到 300 字的逐字稿</em>。这是整个方法论的交付物。AI 可以帮你写初稿,但你一定要自己过一遍,读出来听听是不是你会说的话。</p>
|
||||
<p>好,我今天就讲到这里。如果你做下一场分享的时候想起了这个"演讲者视图 + 逐字稿"的组合,并且觉得讲得比以前顺——那就是我最大的收获。谢谢大家,有问题现在开始。</p>
|
||||
</aside>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
<div style="position:fixed;bottom:12px;left:12px;font-size:11px;color:#484f5866;z-index:100;pointer-events:none">
|
||||
S 演讲者视图 · T 切换主题 · ← → 翻页 · F 全屏 · O 总览 · R 重置计时
|
||||
</div>
|
||||
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,216 @@
|
||||
/* tpl-presenter-mode-reveal · scoped styles
|
||||
* Presenter-mode demo deck. Inherits tokens from active theme.
|
||||
* Minimal overrides — focus is on content + notes structure.
|
||||
*/
|
||||
|
||||
.tpl-presenter-mode-reveal .slide {
|
||||
padding: 72px 96px;
|
||||
}
|
||||
|
||||
.tpl-presenter-mode-reveal .kicker {
|
||||
font-family: var(--font-mono, monospace);
|
||||
font-size: 13px;
|
||||
color: var(--text-3);
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
margin: 0 0 18px 0;
|
||||
}
|
||||
|
||||
.tpl-presenter-mode-reveal .h1 {
|
||||
font-size: clamp(44px, 5.6vw, 76px);
|
||||
line-height: 1.12;
|
||||
letter-spacing: -0.02em;
|
||||
margin: 0 0 24px 0;
|
||||
}
|
||||
|
||||
.tpl-presenter-mode-reveal .h2 {
|
||||
font-size: clamp(32px, 3.6vw, 48px);
|
||||
line-height: 1.22;
|
||||
letter-spacing: -0.01em;
|
||||
margin: 0 0 28px 0;
|
||||
}
|
||||
|
||||
.tpl-presenter-mode-reveal .lede {
|
||||
font-size: 20px;
|
||||
line-height: 1.55;
|
||||
color: var(--text-2);
|
||||
}
|
||||
|
||||
.tpl-presenter-mode-reveal .mono {
|
||||
font-family: var(--font-mono, monospace);
|
||||
font-size: 0.9em;
|
||||
padding: 2px 8px;
|
||||
border-radius: 6px;
|
||||
background: rgba(255,255,255,0.08);
|
||||
color: var(--accent, #58a6ff);
|
||||
}
|
||||
|
||||
.tpl-presenter-mode-reveal .accent {
|
||||
color: var(--accent, #f0883e);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.tpl-presenter-mode-reveal .speaker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-top: 32px;
|
||||
}
|
||||
.tpl-presenter-mode-reveal .speaker .av {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, var(--accent, #58a6ff), #bc8cff);
|
||||
}
|
||||
.tpl-presenter-mode-reveal .speaker b {
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
}
|
||||
.tpl-presenter-mode-reveal .speaker span {
|
||||
font-size: 13px;
|
||||
color: var(--text-3);
|
||||
}
|
||||
|
||||
/* Agenda rows */
|
||||
.tpl-presenter-mode-reveal .agenda-row {
|
||||
display: grid;
|
||||
grid-template-columns: 48px 1fr auto;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
padding: 14px 18px;
|
||||
border: 1px solid var(--border, rgba(255,255,255,0.1));
|
||||
border-radius: 10px;
|
||||
margin-bottom: 10px;
|
||||
background: var(--surface, rgba(255,255,255,0.03));
|
||||
}
|
||||
.tpl-presenter-mode-reveal .agenda-row .num {
|
||||
font-family: var(--font-mono, monospace);
|
||||
font-size: 14px;
|
||||
color: var(--accent, #58a6ff);
|
||||
font-weight: 700;
|
||||
}
|
||||
.tpl-presenter-mode-reveal .agenda-row .t {
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
color: var(--text-1);
|
||||
}
|
||||
.tpl-presenter-mode-reveal .agenda-row .d {
|
||||
font-family: var(--font-mono, monospace);
|
||||
font-size: 12px;
|
||||
color: var(--text-3);
|
||||
}
|
||||
|
||||
/* Cards */
|
||||
.tpl-presenter-mode-reveal .card {
|
||||
background: var(--surface, rgba(255,255,255,0.03));
|
||||
border: 1px solid var(--border, rgba(255,255,255,0.1));
|
||||
border-radius: 12px;
|
||||
padding: 22px 24px;
|
||||
}
|
||||
.tpl-presenter-mode-reveal .card-accent {
|
||||
border-top: 3px solid var(--accent, #58a6ff);
|
||||
}
|
||||
.tpl-presenter-mode-reveal .card h4 {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 18px;
|
||||
color: var(--text-1);
|
||||
}
|
||||
.tpl-presenter-mode-reveal .card .dim {
|
||||
color: var(--text-2);
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Feature rows (presenter view features) */
|
||||
.tpl-presenter-mode-reveal .feature-row {
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
padding: 14px 0;
|
||||
border-bottom: 1px solid var(--border, rgba(255,255,255,0.08));
|
||||
}
|
||||
.tpl-presenter-mode-reveal .feature-row:last-child { border-bottom: none; }
|
||||
.tpl-presenter-mode-reveal .feature-row .num {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.tpl-presenter-mode-reveal .feature-row b {
|
||||
display: block;
|
||||
font-size: 17px;
|
||||
margin-bottom: 4px;
|
||||
color: var(--text-1);
|
||||
}
|
||||
.tpl-presenter-mode-reveal .feature-row .dim {
|
||||
font-size: 14px;
|
||||
color: var(--text-2);
|
||||
line-height: 1.55;
|
||||
margin: 0;
|
||||
}
|
||||
.tpl-presenter-mode-reveal .blue { color: #58a6ff; }
|
||||
.tpl-presenter-mode-reveal .green { color: #3fb950; }
|
||||
.tpl-presenter-mode-reveal .orange { color: #f0883e; }
|
||||
.tpl-presenter-mode-reveal .purple { color: #bc8cff; }
|
||||
.tpl-presenter-mode-reveal .red { color: #f85149; }
|
||||
|
||||
/* Rule rows (3 铁律) */
|
||||
.tpl-presenter-mode-reveal .rule-row {
|
||||
display: grid;
|
||||
grid-template-columns: 56px 1fr;
|
||||
gap: 20px;
|
||||
align-items: start;
|
||||
padding: 18px 22px;
|
||||
border: 1px solid var(--border, rgba(255,255,255,0.1));
|
||||
border-radius: 12px;
|
||||
margin-bottom: 14px;
|
||||
background: var(--surface, rgba(255,255,255,0.03));
|
||||
}
|
||||
.tpl-presenter-mode-reveal .rule-row .num {
|
||||
font-size: 28px;
|
||||
font-weight: 800;
|
||||
font-family: var(--font-mono, monospace);
|
||||
line-height: 1;
|
||||
}
|
||||
.tpl-presenter-mode-reveal .rule-row b {
|
||||
display: block;
|
||||
font-size: 18px;
|
||||
margin-bottom: 6px;
|
||||
color: var(--text-1);
|
||||
}
|
||||
.tpl-presenter-mode-reveal .rule-row .dim {
|
||||
font-size: 15px;
|
||||
color: var(--text-2);
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Code block */
|
||||
.tpl-presenter-mode-reveal .code-block {
|
||||
background: #0d1117;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
border-radius: 12px;
|
||||
padding: 20px 26px;
|
||||
font-family: var(--font-mono, "SF Mono", monospace);
|
||||
font-size: 15px;
|
||||
line-height: 1.8;
|
||||
color: #e6edf3;
|
||||
white-space: pre-wrap;
|
||||
text-align: left;
|
||||
}
|
||||
.tpl-presenter-mode-reveal .code-block .comment { color: #8b949e; }
|
||||
.tpl-presenter-mode-reveal .code-block .cmd { color: #3fb950; font-weight: 600; }
|
||||
.tpl-presenter-mode-reveal .code-block .flag { color: #f0883e; }
|
||||
|
||||
/* Stack helper */
|
||||
.tpl-presenter-mode-reveal .stack > * + * { margin-top: 0; }
|
||||
|
||||
/* Grid helpers */
|
||||
.tpl-presenter-mode-reveal .grid { display: grid; gap: 20px; }
|
||||
.tpl-presenter-mode-reveal .grid.g2 { grid-template-columns: 1fr 1fr; }
|
||||
.tpl-presenter-mode-reveal .grid.g3 { grid-template-columns: repeat(3, 1fr); }
|
||||
|
||||
.tpl-presenter-mode-reveal .mt-m { margin-top: 20px; }
|
||||
.tpl-presenter-mode-reveal .mt-l { margin-top: 32px; }
|
||||
.tpl-presenter-mode-reveal .mt-s { margin-top: 10px; }
|
||||
.tpl-presenter-mode-reveal .tc { text-align: center; }
|
||||
@@ -0,0 +1,8 @@
|
||||
# product-launch
|
||||
|
||||
8-slide consumer product announcement deck: hero cover, "introducing" moment, three feature slides, how-it-works, pricing tiers, and a closing testimonial + pre-order CTA.
|
||||
|
||||
Mixes dark hero slides (for show-off moments) with light slides (for details and pricing). Warm orange→peach gradient accent feels confident and human; easy to re-skin for any brand.
|
||||
|
||||
**Use when:** launching a product, announcing a v2, internal all-hands reveals, press kit decks.
|
||||
**Feel:** Apple-event-on-a-budget — confident, tactile, uncluttered.
|
||||
@@ -0,0 +1,121 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Halo v2 · Launch</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" href="../../../assets/animations/animations.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-product-launch">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. Cover / hero -->
|
||||
<section class="slide dark" data-title="Cover">
|
||||
<div class="hero-shot"></div>
|
||||
<div style="position:absolute;top:56px;left:112px" class="brand">◎ Halo</div>
|
||||
<p class="kicker">Launch · April 2026</p>
|
||||
<h1 class="h1 anim-fade-up" data-anim="fade-up">Meet Halo v2.<br>Your ears,<br><span style="background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent">rewritten.</span></h1>
|
||||
<p class="lede mt-m" style="max-width:42ch">Studio-grade spatial audio in the lightest open-ear earbuds ever made.</p>
|
||||
<div class="deck-footer"><span>halo.audio</span><span class="slide-number" data-current="1" data-total="8"></span></div>
|
||||
</section>
|
||||
|
||||
<!-- 2. Introducing -->
|
||||
<section class="slide center tc" data-title="Introducing">
|
||||
<div>
|
||||
<p class="kicker">Introducing</p>
|
||||
<h1 class="h1" style="font-size:140px">Halo v2</h1>
|
||||
<p class="lede" style="margin:24px auto;max-width:56ch">Four years of research. Three generations of silicon. One product you'll forget you're wearing.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 3. Feature 1 -->
|
||||
<section class="slide" data-title="Sound">
|
||||
<p class="kicker">01 · The sound</p>
|
||||
<h2 class="h2">Hear the room<br>around the music.</h2>
|
||||
<div class="grid g3 mt-l">
|
||||
<div class="feature-card"><div class="icon">♪</div><h4>Open-ear spatial</h4><p class="dim">16mm titanium drivers angled into the ear canal. You hear the song and the world at once.</p></div>
|
||||
<div class="feature-card"><div class="icon">◈</div><h4>Lossless 24-bit</h4><p class="dim">aptX Lossless and Hi-Res LDAC over Bluetooth 5.4. No dongles, no compromises.</p></div>
|
||||
<div class="feature-card"><div class="icon">◐</div><h4>Adaptive EQ</h4><p class="dim">Tunes itself to the shape of your ear every 120 seconds.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 4. Feature 2 -->
|
||||
<section class="slide dark" data-title="Fit">
|
||||
<p class="kicker">02 · The fit</p>
|
||||
<h2 class="h2">4.9 grams.<br>All-day forgettable.</h2>
|
||||
<div class="grid g3 mt-l">
|
||||
<div class="card"><h4>Liquid-silicone hook</h4><p>Wraps behind the ear like a glasses arm. Never falls out on a run.</p></div>
|
||||
<div class="card"><h4>IP57 sweat + rain</h4><p>Take them in the ocean. Rinse them under the tap. We dare you.</p></div>
|
||||
<div class="card"><h4>14h + 42h case</h4><p>A full workweek of commutes on one charge of the case.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 5. Feature 3 -->
|
||||
<section class="slide" data-title="Intelligence">
|
||||
<p class="kicker">03 · The intelligence</p>
|
||||
<h2 class="h2">An AI that listens<br>so you don't have to.</h2>
|
||||
<div class="grid g2 mt-l">
|
||||
<div class="feature-card"><div class="icon">✦</div><h4>Live translate</h4><p class="dim">Real-time translation in 41 languages. Whispered directly into your ear, with a 380ms lag.</p></div>
|
||||
<div class="feature-card"><div class="icon">✧</div><h4>Meeting recap</h4><p class="dim">Double-tap to record. Walk away with a summary, action items, and a searchable transcript.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 6. How it works -->
|
||||
<section class="slide" data-title="How it works">
|
||||
<p class="kicker">How it works</p>
|
||||
<h2 class="h2">Three taps. You're in.</h2>
|
||||
<div class="stack mt-l" style="max-width:900px">
|
||||
<div class="step"><div class="n">1</div><div><h4>Open the case near your phone</h4><p class="dim">iOS and Android pair automatically over Bluetooth LE. No app downloads required.</p></div></div>
|
||||
<div class="step"><div class="n">2</div><div><h4>Pick your profile</h4><p class="dim">Commute, Focus, Workout, Cinema. Each is a complete audio + transparency recipe.</p></div></div>
|
||||
<div class="step"><div class="n">3</div><div><h4>Just listen</h4><p class="dim">Halo adapts to your ear shape, your environment, and your hearing profile — continuously.</p></div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 7. Pricing -->
|
||||
<section class="slide" data-title="Pricing">
|
||||
<p class="kicker">Pricing</p>
|
||||
<h2 class="h2">Pick your Halo.</h2>
|
||||
<div class="grid g3 mt-l" style="align-items:start">
|
||||
<div class="price-card">
|
||||
<h4>Halo Lite</h4>
|
||||
<div class="amount">$179</div>
|
||||
<p class="dim">Open-ear audio, IP57, 12h battery.</p>
|
||||
<ul><li>AAC + SBC</li><li>Single-tap controls</li><li>USB-C charging</li></ul>
|
||||
</div>
|
||||
<div class="price-card pro">
|
||||
<h4>Halo v2 · Pro</h4>
|
||||
<div class="amount">$279</div>
|
||||
<p class="dim">Everything, in its best form.</p>
|
||||
<ul><li>Hi-Res Lossless</li><li>Live translate · 41 lang</li><li>Wireless + MagSafe charging</li><li>Adaptive EQ</li></ul>
|
||||
</div>
|
||||
<div class="price-card">
|
||||
<h4>Halo Studio</h4>
|
||||
<div class="amount">$399</div>
|
||||
<p class="dim">For creators and field recorders.</p>
|
||||
<ul><li>32-bit binaural capture</li><li>XLR dongle included</li><li>Lifetime firmware</li></ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 8. Testimonial + CTA combined? Task says 8 slides w/ testimonial + CTA as separate. Keep 8: testimonial on 7, but we've used 7 already. Re-plan: cover(1) intro(2) f1(3) f2(4) f3(5) how(6) pricing(7) testimonial+CTA(8) -->
|
||||
<section class="slide dark" data-title="Ship">
|
||||
<p class="kicker">One more thing</p>
|
||||
<div class="row" style="gap:80px;align-items:center">
|
||||
<div style="flex:1">
|
||||
<p class="testimonial">"I forgot I was wearing them. Then I remembered, and I didn't want to take them off."</p>
|
||||
<p class="dim mt-m">— Marques Lin, The Verge · early review</p>
|
||||
</div>
|
||||
<div style="flex:0 0 auto;text-align:center">
|
||||
<p class="dim mb-m">Ships May 14 · from</p>
|
||||
<div style="font-size:96px;font-weight:900;letter-spacing:-.04em">$279</div>
|
||||
<a class="cta-btn mt-l" href="#">Pre-order Halo v2 →</a>
|
||||
<p class="dim mt-m" style="font-size:13px">Free shipping · 45-day return · 2-year warranty</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,39 @@
|
||||
/* product-launch — modern announcement deck */
|
||||
.tpl-product-launch{
|
||||
--bg:#ffffff;--bg-soft:#f5f5f7;--surface:#ffffff;--surface-2:#f2f2f6;
|
||||
--ink:#0a0a12;--ink-2:#3a3a44;
|
||||
--border:rgba(10,10,18,.08);--border-strong:rgba(10,10,18,.18);
|
||||
--text-1:#0a0a12;--text-2:#4a4a58;--text-3:#8a8a96;
|
||||
--accent:#ff5a36;--accent-2:#ff8c5a;--accent-3:#ffb36b;
|
||||
--grad:linear-gradient(120deg,#ff5a36 0%,#ff8c5a 60%,#ffb36b 100%);
|
||||
--radius:22px;--radius-lg:32px;
|
||||
--shadow:0 20px 60px rgba(10,10,18,.1);
|
||||
font-family:'Inter','Noto Sans SC',sans-serif;
|
||||
}
|
||||
.tpl-product-launch .slide{padding:80px 112px}
|
||||
.tpl-product-launch .slide.dark{background:#0a0a12;color:#f5f5f7}
|
||||
.tpl-product-launch .slide.dark .h1,.tpl-product-launch .slide.dark .h2,.tpl-product-launch .slide.dark h3,.tpl-product-launch .slide.dark h4{color:#fff}
|
||||
.tpl-product-launch .slide.dark .lede,.tpl-product-launch .slide.dark .dim{color:rgba(245,245,247,.72)}
|
||||
.tpl-product-launch .slide.dark .card{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.12);box-shadow:none;backdrop-filter:blur(20px)}
|
||||
.tpl-product-launch .slide.dark .kicker{color:var(--accent-2)}
|
||||
.tpl-product-launch .h1{font-size:96px;line-height:.98;font-weight:900;letter-spacing:-.045em}
|
||||
.tpl-product-launch .h2{font-size:64px;font-weight:800;letter-spacing:-.035em}
|
||||
.tpl-product-launch .hero-shot{position:absolute;right:-60px;top:50%;transform:translateY(-50%);width:640px;height:640px;border-radius:50%;background:var(--grad);filter:blur(2px);opacity:.85}
|
||||
.tpl-product-launch .hero-shot::after{content:"";position:absolute;inset:80px;border-radius:40px;background:linear-gradient(160deg,rgba(255,255,255,.3),transparent 60%),#1a1a28;box-shadow:inset 0 2px 0 rgba(255,255,255,.2)}
|
||||
.tpl-product-launch .hero-shot::before{content:"Halo v2";position:absolute;inset:80px;display:flex;align-items:center;justify-content:center;color:#fff;font-size:44px;font-weight:900;letter-spacing:-.02em;z-index:2;border-radius:40px}
|
||||
.tpl-product-launch .brand{font-size:18px;font-weight:800;letter-spacing:-.02em}
|
||||
.tpl-product-launch .feature-card{padding:40px 36px;border-radius:var(--radius-lg);background:var(--surface);border:1px solid var(--border);position:relative;overflow:hidden}
|
||||
.tpl-product-launch .feature-card .icon{width:60px;height:60px;border-radius:18px;background:var(--grad);display:flex;align-items:center;justify-content:center;color:#fff;font-size:28px;font-weight:900;margin-bottom:20px}
|
||||
.tpl-product-launch .step{display:flex;gap:24px;align-items:flex-start}
|
||||
.tpl-product-launch .step .n{flex:none;width:56px;height:56px;border-radius:50%;background:var(--grad);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:900;font-size:22px}
|
||||
.tpl-product-launch .price-card{padding:40px 32px;border-radius:var(--radius-lg);border:1.5px solid var(--border);background:var(--surface);text-align:left}
|
||||
.tpl-product-launch .price-card.pro{background:#0a0a12;color:#fff;border-color:#0a0a12;transform:scale(1.04);box-shadow:0 30px 80px rgba(255,90,54,.25)}
|
||||
.tpl-product-launch .price-card.pro .dim{color:rgba(255,255,255,.7)}
|
||||
.tpl-product-launch .price-card h4{font-size:16px;text-transform:uppercase;letter-spacing:.1em;color:var(--accent)}
|
||||
.tpl-product-launch .price-card.pro h4{color:var(--accent-2)}
|
||||
.tpl-product-launch .price-card .amount{font-size:64px;font-weight:900;letter-spacing:-.035em;margin:14px 0}
|
||||
.tpl-product-launch .price-card ul{list-style:none;padding:0;margin:20px 0 0}
|
||||
.tpl-product-launch .price-card li{padding:8px 0;font-size:15px;color:var(--text-2);border-top:1px solid var(--border)}
|
||||
.tpl-product-launch .price-card.pro li{color:rgba(255,255,255,.8);border-color:rgba(255,255,255,.12)}
|
||||
.tpl-product-launch .cta-btn{display:inline-block;padding:20px 40px;border-radius:999px;background:var(--grad);color:#fff;font-weight:700;font-size:20px;box-shadow:0 20px 50px rgba(255,90,54,.4)}
|
||||
.tpl-product-launch .testimonial{max-width:44ch;font-family:'Playfair Display',serif;font-size:44px;line-height:1.25;font-weight:500;letter-spacing:-.01em}
|
||||
@@ -0,0 +1,8 @@
|
||||
# tech-sharing · 技术分享
|
||||
|
||||
8-slide engineering talk deck: cover (topic + speaker), agenda, context, two deep-dive slides, a code example, takeaways, Q&A.
|
||||
|
||||
Dark GitHub-ish palette (`#0d1117`) with JetBrains Mono accents and syntax-highlighted terminal blocks. Built to be screenshotted and shared on an internal wiki or Twitter.
|
||||
|
||||
**Use when:** tech-sharing Fridays, brown-bag talks, lunch & learns, conference submissions.
|
||||
**Feel:** GitHub README meets a good conference talk — dark, monospaced, dense but readable.
|
||||
@@ -0,0 +1,156 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Rust 异步运行时内部机制 · Tech Sharing</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" href="../../../assets/animations/animations.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-tech-sharing">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. Cover -->
|
||||
<section class="slide" data-title="Cover">
|
||||
<p class="kicker">tech-sharing / 2026-04-15</p>
|
||||
<h1 class="h1 anim-fade-up" data-anim="fade-up">Rust 异步运行时<br>到底在<span style="background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent">调度什么</span>?</h1>
|
||||
<p class="lede mt-m">从 <span class="mono">Future::poll</span> 到 tokio 的 work-stealing,一次讲清楚。</p>
|
||||
<div class="speaker"><div class="av"></div><div><b>@lewis</b><span>platform infra · 45 min + Q&A</span></div></div>
|
||||
<div class="deck-footer"><span class="mono">#async #rust #tokio</span><span class="slide-number" data-current="1" data-total="8"></span></div>
|
||||
</section>
|
||||
|
||||
<!-- 2. Agenda -->
|
||||
<section class="slide" data-title="Agenda">
|
||||
<p class="kicker">agenda.toml</p>
|
||||
<h2 class="h2">今天的路线图</h2>
|
||||
<div class="stack mt-l">
|
||||
<div class="agenda-row"><span class="num">01</span><span class="t">Context: 为什么需要 async</span><span class="d">~5min</span></div>
|
||||
<div class="agenda-row"><span class="num">02</span><span class="t">Deep dive 1: Future & Waker</span><span class="d">~12min</span></div>
|
||||
<div class="agenda-row"><span class="num">03</span><span class="t">Deep dive 2: Tokio scheduler</span><span class="d">~15min</span></div>
|
||||
<div class="agenda-row"><span class="num">04</span><span class="t">Code: 手写一个 mini-runtime</span><span class="d">~8min</span></div>
|
||||
<div class="agenda-row"><span class="num">05</span><span class="t">Takeaways + Q&A</span><span class="d">~5min</span></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 3. Context -->
|
||||
<section class="slide" data-title="Context">
|
||||
<p class="kicker">// context</p>
|
||||
<h2 class="h2">问题:一个线程一个连接,<br>撑不住 10 万并发。</h2>
|
||||
<div class="grid g3 mt-l">
|
||||
<div class="card card-accent"><h4>Thread-per-conn</h4><p class="dim">每条连接一根 OS 线程,栈 2–8MB。10 万连接 = 几百 GB RAM。</p><span class="tag mt-s">❌ 不现实</span></div>
|
||||
<div class="card card-accent"><h4>Event loop (C)</h4><p class="dim">epoll/kqueue + 回调地狱。快,但写起来痛苦且容易出 bug。</p><span class="tag mt-s">😩 callback hell</span></div>
|
||||
<div class="card card-accent"><h4>Async / await</h4><p class="dim">看起来像同步代码,编译成状态机。一根线程跑几千任务。</p><span class="tag mt-s">✅ Rust 选这个</span></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 4. Deep dive 1 -->
|
||||
<section class="slide" data-title="Deep Dive 1">
|
||||
<p class="kicker">deep-dive · 1 / 2</p>
|
||||
<h2 class="h2">Future 其实只有一个方法。</h2>
|
||||
<div class="grid g2 mt-l" style="align-items:start">
|
||||
<div>
|
||||
<p class="lede">编译器把 <span class="mono">async fn</span> 变成一个实现了 <span class="mono">Future</span> trait 的匿名状态机。运行时只做一件事:反复 <span class="mono">poll</span> 它,直到返回 <span class="mono">Ready</span>。</p>
|
||||
<div class="mt-l">
|
||||
<span class="tag">Pending</span> <span class="tag">Ready(T)</span> <span class="tag">Waker.wake()</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="terminal">
|
||||
<div class="bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span><span>future.rs</span></div>
|
||||
<pre><span class="kw">pub trait</span> <span class="fn">Future</span> {
|
||||
<span class="kw">type</span> Output;
|
||||
<span class="kw">fn</span> <span class="fn">poll</span>(
|
||||
<span class="kw">self</span>: Pin<&<span class="kw">mut Self</span>>,
|
||||
cx: &<span class="kw">mut</span> Context<<span class="str">'_</span>>,
|
||||
) -> Poll<<span class="kw">Self</span>::Output>;
|
||||
}
|
||||
|
||||
<span class="cmt">// Poll::Pending → 挂起,等 waker 唤醒</span>
|
||||
<span class="cmt">// Poll::Ready(v) → 完成,产出 v</span></pre>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 5. Deep dive 2 -->
|
||||
<section class="slide" data-title="Deep Dive 2">
|
||||
<p class="kicker">deep-dive · 2 / 2</p>
|
||||
<h2 class="h2">Tokio 是一个偷任务的小工。</h2>
|
||||
<div class="grid g2 mt-l" style="align-items:start">
|
||||
<div>
|
||||
<p class="lede">Multi-thread runtime = N 个 worker,每个 worker 有自己的本地队列。空闲的 worker 会去别人队列里"偷"任务。</p>
|
||||
<div class="stack mt-m">
|
||||
<div class="tag">✦ local queue · 256 slots</div>
|
||||
<div class="tag">✦ global injection queue</div>
|
||||
<div class="tag">✦ work-stealing @ 50% steal ratio</div>
|
||||
<div class="tag">✦ LIFO slot for cache locality</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" style="padding:32px">
|
||||
<h4 class="mono" style="color:var(--accent-2)">scheduler tick loop</h4>
|
||||
<div class="stack mt-m" style="font-family:'JetBrains Mono',monospace;font-size:14px;line-height:1.9;color:var(--text-2)">
|
||||
<div><span style="color:var(--accent)">1.</span> pop from LIFO slot</div>
|
||||
<div><span style="color:var(--accent)">2.</span> else pop from local queue</div>
|
||||
<div><span style="color:var(--accent)">3.</span> else drain global queue (every 61 ticks)</div>
|
||||
<div><span style="color:var(--accent)">4.</span> else steal from random victim</div>
|
||||
<div><span style="color:var(--accent)">5.</span> else park the thread</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 6. Code example -->
|
||||
<section class="slide" data-title="Code">
|
||||
<p class="kicker">mini-runtime.rs · ~40 LOC</p>
|
||||
<h2 class="h2">手写一个最小 runtime。</h2>
|
||||
<div class="terminal mt-m">
|
||||
<div class="bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span><span>src/main.rs</span></div>
|
||||
<pre><span class="kw">use</span> std::collections::VecDeque;
|
||||
<span class="kw">use</span> std::sync::{Arc, Mutex};
|
||||
<span class="kw">use</span> std::task::{Context, Poll, Wake, Waker};
|
||||
|
||||
<span class="kw">struct</span> Task(Mutex<Pin<Box<<span class="kw">dyn</span> Future<Output = ()> + Send>>>);
|
||||
|
||||
<span class="kw">impl</span> Wake <span class="kw">for</span> Task {
|
||||
<span class="kw">fn</span> <span class="fn">wake</span>(<span class="kw">self</span>: Arc<<span class="kw">Self</span>>) { QUEUE.lock().unwrap().push_back(<span class="kw">self</span>); }
|
||||
}
|
||||
|
||||
<span class="kw">fn</span> <span class="fn">block_on</span><F: Future<Output = ()> + Send + <span class="str">'static</span>>(fut: F) {
|
||||
<span class="fn">spawn</span>(fut);
|
||||
<span class="kw">while let Some</span>(task) = QUEUE.lock().unwrap().pop_front() {
|
||||
<span class="kw">let</span> waker = Waker::from(task.clone());
|
||||
<span class="kw">let mut</span> cx = Context::from_waker(&waker);
|
||||
<span class="kw">let mut</span> fut = task.<span class="num">0</span>.lock().unwrap();
|
||||
<span class="kw">let</span> _ = fut.as_mut().<span class="fn">poll</span>(&<span class="kw">mut</span> cx); <span class="cmt">// 就是这一行</span>
|
||||
}
|
||||
}</pre>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 7. Takeaways -->
|
||||
<section class="slide" data-title="Takeaways">
|
||||
<p class="kicker">// takeaways</p>
|
||||
<h2 class="h2">三件事带回去。</h2>
|
||||
<div class="grid g3 mt-l">
|
||||
<div class="card card-accent"><h4>1 · async 是零成本抽象</h4><p class="dim">编译成状态机,没有运行时虚表,没有 GC。</p></div>
|
||||
<div class="card card-accent"><h4>2 · Waker 是脉搏</h4><p class="dim">Future 不主动做事,运行时靠 waker 决定"什么时候再 poll"。</p></div>
|
||||
<div class="card card-accent"><h4>3 · 别在 async 里阻塞</h4><p class="dim">一行 <span class="mono">std::fs::read</span> 能让整个 worker 停摆。用 <span class="mono">spawn_blocking</span>。</p></div>
|
||||
</div>
|
||||
<p class="lede mt-l">延伸阅读:<span class="mono">tokio.rs/blog/2019-10-scheduler</span> · <span class="mono">rust-lang.github.io/async-book</span></p>
|
||||
</section>
|
||||
|
||||
<!-- 8. Q&A -->
|
||||
<section class="slide center tc" data-title="Q and A">
|
||||
<div>
|
||||
<div class="mono" style="font-size:120px;color:var(--accent);font-weight:800;letter-spacing:-.04em">?</div>
|
||||
<h2 class="h2">Questions?</h2>
|
||||
<p class="lede" style="margin:14px auto">github.com/lewis · @lewis on slack</p>
|
||||
<div class="row mt-l" style="justify-content:center">
|
||||
<span class="tag">slides: git.co/rt-deck</span>
|
||||
<span class="tag">code: git.co/mini-rt</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,49 @@
|
||||
/* tech-sharing — 技术分享 dark, code-forward */
|
||||
.tpl-tech-sharing{
|
||||
--bg:#0d1117;--bg-soft:#161b22;--surface:#161b22;--surface-2:#1c2230;
|
||||
--border:rgba(139,148,158,.22);--border-strong:rgba(139,148,158,.4);
|
||||
--text-1:#e6edf3;--text-2:#8b949e;--text-3:#6e7681;
|
||||
--accent:#7ee787;--accent-2:#79c0ff;--accent-3:#ff7b72;
|
||||
--grad:linear-gradient(120deg,#7ee787 0%,#79c0ff 60%,#d2a8ff 100%);
|
||||
--radius:14px;--radius-lg:20px;
|
||||
--shadow:0 20px 60px rgba(0,0,0,.5);
|
||||
font-family:'Inter','Noto Sans SC',sans-serif;
|
||||
}
|
||||
.tpl-tech-sharing{background:#0d1117;color:var(--text-1)}
|
||||
.tpl-tech-sharing .slide{padding:72px 96px;background:#0d1117;color:var(--text-1)}
|
||||
.tpl-tech-sharing .slide::before{content:"";position:absolute;inset:0;background:
|
||||
radial-gradient(60% 50% at 90% 10%,rgba(121,192,255,.12),transparent 60%),
|
||||
radial-gradient(50% 50% at 10% 90%,rgba(126,231,135,.08),transparent 60%);
|
||||
pointer-events:none;z-index:0}
|
||||
.tpl-tech-sharing .slide>*{position:relative;z-index:1}
|
||||
.tpl-tech-sharing .h1{font-size:78px;line-height:1.03;font-weight:800;letter-spacing:-.03em;color:#fff}
|
||||
.tpl-tech-sharing .h2{font-size:54px;font-weight:700;letter-spacing:-.025em;color:#fff}
|
||||
.tpl-tech-sharing h3,.tpl-tech-sharing h4{color:#fff}
|
||||
.tpl-tech-sharing .kicker{color:var(--accent);font-family:'JetBrains Mono',monospace;font-size:13px;font-weight:600;text-transform:none;letter-spacing:.02em}
|
||||
.tpl-tech-sharing .kicker::before{content:"> "}
|
||||
.tpl-tech-sharing .mono{font-family:'JetBrains Mono','IBM Plex Mono',monospace}
|
||||
.tpl-tech-sharing .terminal{background:#010409;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;box-shadow:0 30px 80px rgba(0,0,0,.6);font-family:'JetBrains Mono',monospace;font-size:15px;line-height:1.65}
|
||||
.tpl-tech-sharing .terminal .bar{display:flex;align-items:center;gap:8px;padding:12px 16px;background:#161b22;border-bottom:1px solid var(--border);font-size:12px;color:var(--text-3)}
|
||||
.tpl-tech-sharing .terminal .dot{width:12px;height:12px;border-radius:50%;background:#ff5f56}
|
||||
.tpl-tech-sharing .terminal .dot:nth-child(2){background:#ffbd2e}
|
||||
.tpl-tech-sharing .terminal .dot:nth-child(3){background:#27c93f}
|
||||
.tpl-tech-sharing .terminal pre{margin:0;padding:24px 28px;color:#e6edf3;overflow:auto;max-height:440px}
|
||||
.tpl-tech-sharing .kw{color:#ff7b72}
|
||||
.tpl-tech-sharing .fn{color:#d2a8ff}
|
||||
.tpl-tech-sharing .str{color:#a5d6ff}
|
||||
.tpl-tech-sharing .cmt{color:#8b949e;font-style:italic}
|
||||
.tpl-tech-sharing .num{color:#79c0ff}
|
||||
.tpl-tech-sharing .card{background:var(--surface);border:1px solid var(--border);box-shadow:none}
|
||||
.tpl-tech-sharing .card-accent{border-top:3px solid var(--accent)}
|
||||
.tpl-tech-sharing .pill{background:var(--surface-2);color:var(--text-2);border-color:var(--border)}
|
||||
.tpl-tech-sharing .pill-accent{background:rgba(126,231,135,.12);color:var(--accent);border-color:rgba(126,231,135,.35)}
|
||||
.tpl-tech-sharing .tag{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:6px;font-family:'JetBrains Mono',monospace;font-size:12px;background:var(--surface-2);border:1px solid var(--border);color:var(--text-2)}
|
||||
.tpl-tech-sharing .agenda-row{display:flex;align-items:baseline;gap:24px;padding:18px 0;border-bottom:1px dashed var(--border);font-family:'JetBrains Mono',monospace}
|
||||
.tpl-tech-sharing .agenda-row .num{color:var(--accent);flex:none;width:48px}
|
||||
.tpl-tech-sharing .agenda-row .t{color:#fff;font-size:24px;flex:1;font-family:'Inter',sans-serif;font-weight:600}
|
||||
.tpl-tech-sharing .agenda-row .d{color:var(--text-3);font-size:13px}
|
||||
.tpl-tech-sharing .speaker{display:flex;align-items:center;gap:14px;margin-top:28px}
|
||||
.tpl-tech-sharing .speaker .av{width:56px;height:56px;border-radius:50%;background:var(--grad)}
|
||||
.tpl-tech-sharing .speaker b{display:block;color:#fff;font-size:18px}
|
||||
.tpl-tech-sharing .speaker span{color:var(--text-3);font-size:13px;font-family:'JetBrains Mono',monospace}
|
||||
.tpl-tech-sharing .lede{color:var(--text-2)}
|
||||
@@ -0,0 +1,11 @@
|
||||
# testing-safety-alert
|
||||
|
||||
白底 + 红琥珀警示色 + 条纹危险边 + 大红 strike 和 pill。灵感来自 `20260412-AI测试与安全/xhs-ai-testing-safety-v2.html` 的 `.focus` 黑底白字块、hero quote box 和高对比 black-on-white 气质 —— 但把语气推到「警示 / 风控 / 事故报告」层级。
|
||||
|
||||
**Visual traits:** 顶部 45° 红黑斜条纹警示带、底部副条纹、`strike-through` 红色斜切的否定大字、L1/L2/L3 三档色卡 (绿/琥珀/红)、圆形前置指示灯 alert-box、policy-yaml 深色代码块带红色左边框 + `bad` 关键词高亮、红/绿复选框 checklist、Q1 事故柱状图。
|
||||
|
||||
**Use when:** 讲安全 / 风控 / 事故复盘 / 红队测试 / AI 上线前评估 / policy as code;你需要让观众立刻感到「这事严肃,别马虎」。
|
||||
|
||||
**Source inspiration:** `20260412-AI测试与安全/html/xhs-ai-testing-safety-v2.html`.
|
||||
|
||||
**Path:** `templates/full-decks/testing-safety-alert/index.html`
|
||||
@@ -0,0 +1,183 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Testing Safety Alert</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-testing-safety-alert">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. COVER -->
|
||||
<section class="slide is-active">
|
||||
<div class="ts-stripe"></div>
|
||||
<div class="ts-chrome"><span class="ts-alert-tag">ai safety · 高优先级</span><span class="ts-page">01 / 08</span></div>
|
||||
<div class="ts-kicker">2026 年最重要的一条判断</div>
|
||||
<h1 class="ts-h1">别再追问<br><span class="strike">AI 会不会干活</span><br>开始问:<span class="red">它出事谁负责</span></h1>
|
||||
<p class="ts-sub">AI 出错的代价,不再是一次 bad response 这么简单 —— 它可能一次性写 300 份工单、提 80 个 PR、发 5000 封邮件。</p>
|
||||
<div class="ts-alert-box">
|
||||
<h3>风险已经规模化</h3>
|
||||
<p>「做错」成本 × N;「做对」收益 × N。<br>这就是为什么 <b>测试、验收、安全、风控</b> 会变成未来 3 年最贵的能力。</p>
|
||||
</div>
|
||||
<div class="ts-stripe-b"></div>
|
||||
<div class="ts-footer"><span>AI SAFETY BRIEF · LEWIS · 2026.04</span><span>01 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 2. SECTION -->
|
||||
<section class="slide">
|
||||
<div class="ts-stripe"></div>
|
||||
<div class="ts-chrome"><span class="ts-alert-tag amber">section · risk 分级</span><span class="ts-page">02 / 08</span></div>
|
||||
<div style="margin:auto 0">
|
||||
<div class="ts-kicker">Chapter One</div>
|
||||
<h1 class="ts-h1" style="font-size:130px">先分 <span class="red">等级</span></h1>
|
||||
<p class="ts-sub" style="font-size:28px">不是所有 AI 行为都同等危险。<br>先把「可撤销」和「不可撤销」分开,再谈流程。</p>
|
||||
</div>
|
||||
<div class="ts-stripe-b"></div>
|
||||
<div class="ts-footer"><span>section · level taxonomy</span><span>02 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 3. CONTENT risk levels -->
|
||||
<section class="slide">
|
||||
<div class="ts-stripe"></div>
|
||||
<div class="ts-chrome"><span class="ts-alert-tag">风险分级 · 3 levels</span><span class="ts-page">03 / 08</span></div>
|
||||
<h2 class="ts-h2">三档风险,三种处理</h2>
|
||||
<div class="ts-grid-3">
|
||||
<div class="ts-card" style="border-top:4px solid var(--ts-green)"><div class="lbl">L1 · 绿色</div><h4>可撤销</h4><p>写 draft、生成图片、起草文档。<br>错了 Ctrl+Z,零代价。<br><b style="color:var(--ts-green)">策略:放开跑</b></p></div>
|
||||
<div class="ts-card" style="border-top:4px solid var(--ts-amber)"><div class="lbl">L2 · 琥珀</div><h4>半可撤销</h4><p>发 draft 邮件、提 PR、改 staging 数据。<br>错了要道歉 / 回滚。<br><b style="color:var(--ts-amber)">策略:人工复核</b></p></div>
|
||||
<div class="ts-card" style="border-top:4px solid var(--ts-red)"><div class="lbl">L3 · 红色</div><h4>不可撤销</h4><p>发真实邮件、付款、删库、删 prod 数据。<br>错了就真错了。<br><b style="color:var(--ts-red)">策略:硬卡 + 双人审</b></p></div>
|
||||
</div>
|
||||
<div class="ts-alert-box amber">
|
||||
<h3>绝不要让 agent 自己升级</h3>
|
||||
<p>L1 的任务不能自己变成 L2。授权必须是显式的、可撤销的、带过期时间的。</p>
|
||||
</div>
|
||||
<div class="ts-stripe-b"></div>
|
||||
<div class="ts-footer"><span>risk · 3 levels</span><span>03 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 4. CODE -->
|
||||
<section class="slide">
|
||||
<div class="ts-stripe"></div>
|
||||
<div class="ts-chrome"><span class="ts-alert-tag">policy as code</span><span class="ts-page">04 / 08</span></div>
|
||||
<div class="ts-kicker">别用文档管规则 · 用代码管规则</div>
|
||||
<h2 class="ts-h2">三十行 YAML,<br><span class="ts-highlight-red">红线硬卡</span></h2>
|
||||
<pre class="ts-codebox"><span class="cm"># safety-policy.yaml · compiled → runtime guard</span>
|
||||
<span class="kw">level_1_allow</span>:
|
||||
- tools: [<span class="st">write_draft</span>, <span class="st">generate_image</span>, <span class="st">read_docs</span>]
|
||||
|
||||
<span class="kw">level_2_require_review</span>:
|
||||
- tools: [<span class="st">send_email_draft</span>, <span class="st">open_pr</span>, <span class="st">write_staging_db</span>]
|
||||
reviewer: <span class="st">human</span>
|
||||
|
||||
<span class="kw">level_3_hard_block</span>:
|
||||
- tools: [<span class="st">send_real_email</span>, <span class="st">transfer_money</span>, <span class="st">delete_prod</span>]
|
||||
unless: <span class="st">two_human_sign_off AND within_24h</span>
|
||||
|
||||
<span class="bad">forbidden_always</span>:
|
||||
- <span class="bad">"rm -rf /"</span>
|
||||
- <span class="bad">"drop table"</span>
|
||||
- <span class="bad">"force push origin main"</span></pre>
|
||||
<div class="ts-stripe-b"></div>
|
||||
<div class="ts-footer"><span>policy · yaml-as-guard</span><span>04 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 5. CHART -->
|
||||
<section class="slide">
|
||||
<div class="ts-stripe"></div>
|
||||
<div class="ts-chrome"><span class="ts-alert-tag amber">incident report · q1</span><span class="ts-page">05 / 08</span></div>
|
||||
<h2 class="ts-h2">我们 Q1 的 <span class="red">12 起 AI 事故</span></h2>
|
||||
<p class="ts-sub">幸好全部捕获在 staging。但每一起都能上生产。</p>
|
||||
<svg viewBox="0 0 1040 360" style="width:100%;max-width:1040px;margin-top:18px" xmlns="http://www.w3.org/2000/svg">
|
||||
<g font-family="Inter,sans-serif" font-size="14" fill="#4a4955">
|
||||
<line x1="70" y1="320" x2="1000" y2="320" stroke="#eaecf3" stroke-width="2"/>
|
||||
<!-- month columns: Jan Feb Mar, L1/L2/L3 stacked -->
|
||||
<g transform="translate(120,0)">
|
||||
<rect x="0" y="220" width="60" height="100" fill="#067647"/>
|
||||
<rect x="0" y="160" width="60" height="60" fill="#d97706"/>
|
||||
<rect x="0" y="130" width="60" height="30" fill="#e0314a"/>
|
||||
<text x="30" y="345" text-anchor="middle" font-weight="700">Jan</text>
|
||||
<text x="30" y="120" text-anchor="middle" font-weight="800" fill="#14141a">5</text>
|
||||
</g>
|
||||
<g transform="translate(320,0)">
|
||||
<rect x="0" y="240" width="60" height="80" fill="#067647"/>
|
||||
<rect x="0" y="200" width="60" height="40" fill="#d97706"/>
|
||||
<rect x="0" y="180" width="60" height="20" fill="#e0314a"/>
|
||||
<text x="30" y="345" text-anchor="middle" font-weight="700">Feb</text>
|
||||
<text x="30" y="170" text-anchor="middle" font-weight="800" fill="#14141a">3</text>
|
||||
</g>
|
||||
<g transform="translate(520,0)">
|
||||
<rect x="0" y="250" width="60" height="70" fill="#067647"/>
|
||||
<rect x="0" y="220" width="60" height="30" fill="#d97706"/>
|
||||
<rect x="0" y="210" width="60" height="10" fill="#e0314a"/>
|
||||
<text x="30" y="345" text-anchor="middle" font-weight="700">Mar</text>
|
||||
<text x="30" y="200" text-anchor="middle" font-weight="800" fill="#14141a">4</text>
|
||||
</g>
|
||||
<!-- legend -->
|
||||
<g transform="translate(720,60)">
|
||||
<rect x="0" y="0" width="16" height="16" fill="#e0314a"/><text x="24" y="13" font-weight="700">L3 不可撤销 (3)</text>
|
||||
<rect x="0" y="26" width="16" height="16" fill="#d97706"/><text x="24" y="39" font-weight="700">L2 需复核 (4)</text>
|
||||
<rect x="0" y="52" width="16" height="16" fill="#067647"/><text x="24" y="65" font-weight="700">L1 可恢复 (5)</text>
|
||||
<text x="0" y="100" font-size="13" fill="#8a8892">全部被 safety-policy 在 runtime 拦下,</text>
|
||||
<text x="0" y="118" font-size="13" fill="#8a8892">未进 prod。但 3 起 L3 非常惊险。</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<div class="ts-stripe-b"></div>
|
||||
<div class="ts-footer"><span>incident · q1 summary</span><span>05 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 6. CHECKLIST -->
|
||||
<section class="slide">
|
||||
<div class="ts-stripe"></div>
|
||||
<div class="ts-chrome"><span class="ts-alert-tag green">red-team checklist</span><span class="ts-page">06 / 08</span></div>
|
||||
<h2 class="ts-h2">上线前 <span class="red">必过 7 道题</span></h2>
|
||||
<div class="ts-checklist">
|
||||
<div class="ts-check ok"><div class="box">✓</div><div class="txt">它能删除东西吗?有人类 review 吗?能 60 秒内回滚吗?</div></div>
|
||||
<div class="ts-check ok"><div class="box">✓</div><div class="txt">它的 prompt 注入能让它越权吗?(跑过红队提示词)</div></div>
|
||||
<div class="ts-check"><div class="box">!</div><div class="txt">它处理 PII 吗?日志里是不是也有 PII?</div></div>
|
||||
<div class="ts-check ok"><div class="box">✓</div><div class="txt">上下游失败时,它会不会开始乱改其他资源?</div></div>
|
||||
<div class="ts-check"><div class="box">!</div><div class="txt">并发 100 个 agent 一起跑会不会死锁?</div></div>
|
||||
<div class="ts-check ok"><div class="box">✓</div><div class="txt">错了能不能 <b>立刻</b> 停?(kill switch 能 2 秒内生效吗)</div></div>
|
||||
<div class="ts-check"><div class="box">!</div><div class="txt">出事时有没有人值班?值班手册有没有 agent 专属章节?</div></div>
|
||||
</div>
|
||||
<div class="ts-stripe-b"></div>
|
||||
<div class="ts-footer"><span>checklist · pre-launch</span><span>06 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 7. CTA -->
|
||||
<section class="slide">
|
||||
<div class="ts-stripe"></div>
|
||||
<div class="ts-chrome"><span class="ts-alert-tag green">今晚就能动</span><span class="ts-page">07 / 08</span></div>
|
||||
<h2 class="ts-h2">今晚先做 <span class="ts-highlight-red">三件事</span></h2>
|
||||
<div class="ts-grid-3">
|
||||
<div class="ts-card"><div class="lbl">1 · 分级</div><h4>给你的 agent<br>写 L1/L2/L3</h4><p>把所有工具列出来,标上等级。不标的一律按 L3。</p></div>
|
||||
<div class="ts-card"><div class="lbl">2 · 写 policy</div><h4>policy.yaml<br>接 runtime</h4><p>不要信 prompt 里的 "be careful",要信执行层的硬卡。</p></div>
|
||||
<div class="ts-card"><div class="lbl">3 · kill switch</div><h4>红按钮<br>能在 2 秒内停</h4><p>CTO / on-call 都得知道怎么按。演练一次。</p></div>
|
||||
</div>
|
||||
<div class="ts-alert-box green">
|
||||
<h3>真正的安全不是 prompt,是流程</h3>
|
||||
<p>prompt 会被注入,流程不会。—— 把保护放在不可被说服的一层。</p>
|
||||
</div>
|
||||
<div class="ts-stripe-b"></div>
|
||||
<div class="ts-footer"><span>cta · tonight</span><span>07 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 8. THANKS -->
|
||||
<section class="slide">
|
||||
<div class="ts-stripe"></div>
|
||||
<div class="ts-chrome"><span class="ts-alert-tag amber">please stay safe</span><span class="ts-page">08 / 08</span></div>
|
||||
<div style="margin:auto 0">
|
||||
<div class="ts-kicker">end of brief</div>
|
||||
<h1 class="ts-h1" style="font-size:140px">谢谢 <span class="red">·</span> thanks</h1>
|
||||
<p class="ts-sub" style="font-size:24px">policy.yaml 模板、红队 prompt 清单、事故复盘模板 —— 评论区扣「安全」。</p>
|
||||
</div>
|
||||
<div class="ts-stripe-b"></div>
|
||||
<div class="ts-footer"><span>end of brief</span><span>08 / 08</span></div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,62 @@
|
||||
/* testing-safety-alert — 红/琥珀 警示风 · 白底高对比 */
|
||||
.tpl-testing-safety-alert{
|
||||
--ts-bg:#fffaf7;
|
||||
--ts-ink:#14141a;
|
||||
--ts-ink2:#4a4955;
|
||||
--ts-muted:#8a8892;
|
||||
--ts-line:rgba(20,20,26,.08);
|
||||
--ts-red:#e0314a;
|
||||
--ts-red-soft:#ffecee;
|
||||
--ts-amber:#d97706;
|
||||
--ts-amber-soft:#fff5e6;
|
||||
--ts-green:#067647;
|
||||
--ts-green-soft:#e8f8ee;
|
||||
background:var(--ts-bg);
|
||||
color:var(--ts-ink);
|
||||
font-family:'Inter','Noto Sans SC','PingFang SC',-apple-system,sans-serif;
|
||||
}
|
||||
.tpl-testing-safety-alert .slide{background:var(--ts-bg);color:var(--ts-ink);padding:64px 84px}
|
||||
.tpl-testing-safety-alert .ts-stripe{position:absolute;top:0;left:0;right:0;height:14px;background:repeating-linear-gradient(45deg,var(--ts-red) 0 18px,#111318 18px 36px)}
|
||||
.tpl-testing-safety-alert .ts-stripe-b{position:absolute;bottom:0;left:0;right:0;height:6px;background:repeating-linear-gradient(45deg,var(--ts-red) 0 10px,#111318 10px 20px);opacity:.6}
|
||||
.tpl-testing-safety-alert .ts-chrome{display:flex;justify-content:space-between;align-items:center;margin:22px 0 16px}
|
||||
.tpl-testing-safety-alert .ts-alert-tag{display:inline-flex;align-items:center;gap:10px;padding:8px 18px;border-radius:10px;font-size:13px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;background:var(--ts-red);color:#fff;box-shadow:0 6px 18px rgba(224,49,74,.28)}
|
||||
.tpl-testing-safety-alert .ts-alert-tag::before{content:'⚠';font-size:16px}
|
||||
.tpl-testing-safety-alert .ts-alert-tag.amber{background:var(--ts-amber);box-shadow:0 6px 18px rgba(217,119,6,.25)}
|
||||
.tpl-testing-safety-alert .ts-alert-tag.green{background:var(--ts-green);box-shadow:0 6px 18px rgba(6,118,71,.22)}
|
||||
.tpl-testing-safety-alert .ts-alert-tag.green::before{content:'✓'}
|
||||
.tpl-testing-safety-alert .ts-page{font-size:13px;color:var(--ts-muted);letter-spacing:.15em;font-weight:700}
|
||||
.tpl-testing-safety-alert .ts-kicker{font-size:15px;font-weight:700;color:var(--ts-red);letter-spacing:.06em;margin-bottom:10px;text-transform:uppercase}
|
||||
.tpl-testing-safety-alert .ts-h1{font-size:88px;font-weight:900;line-height:1.04;letter-spacing:-2px;margin:10px 0 16px;color:var(--ts-ink)}
|
||||
.tpl-testing-safety-alert .ts-h1 .red{color:var(--ts-red)}
|
||||
.tpl-testing-safety-alert .ts-h1 .strike{position:relative;display:inline-block}
|
||||
.tpl-testing-safety-alert .ts-h1 .strike::after{content:'';position:absolute;left:-4%;right:-4%;top:50%;height:10px;background:var(--ts-red);transform:skewX(-12deg);opacity:.85}
|
||||
.tpl-testing-safety-alert .ts-h2{font-size:54px;font-weight:900;line-height:1.1;letter-spacing:-1px;margin:0 0 14px}
|
||||
.tpl-testing-safety-alert .ts-sub{font-size:22px;line-height:1.5;color:var(--ts-ink2);max-width:880px;margin-top:10px}
|
||||
.tpl-testing-safety-alert .ts-highlight-red{display:inline-block;padding:4px 14px;background:var(--ts-red);color:#fff;border-radius:8px;font-weight:800}
|
||||
.tpl-testing-safety-alert .ts-highlight-amber{display:inline-block;padding:4px 14px;background:var(--ts-amber-soft);color:var(--ts-amber);border-radius:8px;font-weight:800;border:1px solid rgba(217,119,6,.2)}
|
||||
.tpl-testing-safety-alert .ts-highlight-green{display:inline-block;padding:4px 14px;background:var(--ts-green-soft);color:var(--ts-green);border-radius:8px;font-weight:800;border:1px solid rgba(6,118,71,.2)}
|
||||
.tpl-testing-safety-alert .ts-alert-box{border:2px solid var(--ts-red);border-radius:18px;padding:26px 30px;background:linear-gradient(180deg,#fff 0%,var(--ts-red-soft) 100%);box-shadow:0 14px 36px rgba(224,49,74,.14);margin-top:24px;position:relative}
|
||||
.tpl-testing-safety-alert .ts-alert-box::before{content:'';position:absolute;top:-11px;left:24px;width:22px;height:22px;background:var(--ts-red);border-radius:50%;box-shadow:0 0 0 6px rgba(224,49,74,.2)}
|
||||
.tpl-testing-safety-alert .ts-alert-box.amber{border-color:var(--ts-amber);background:linear-gradient(180deg,#fff 0%,var(--ts-amber-soft) 100%);box-shadow:0 14px 36px rgba(217,119,6,.14)}
|
||||
.tpl-testing-safety-alert .ts-alert-box.amber::before{background:var(--ts-amber);box-shadow:0 0 0 6px rgba(217,119,6,.2)}
|
||||
.tpl-testing-safety-alert .ts-alert-box.green{border-color:var(--ts-green);background:linear-gradient(180deg,#fff 0%,var(--ts-green-soft) 100%);box-shadow:0 14px 36px rgba(6,118,71,.14)}
|
||||
.tpl-testing-safety-alert .ts-alert-box.green::before{background:var(--ts-green);box-shadow:0 0 0 6px rgba(6,118,71,.2)}
|
||||
.tpl-testing-safety-alert .ts-alert-box h3{font-size:34px;font-weight:900;margin:0 0 10px}
|
||||
.tpl-testing-safety-alert .ts-alert-box p{font-size:17px;line-height:1.6;color:var(--ts-ink2);margin:0}
|
||||
.tpl-testing-safety-alert .ts-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-top:20px}
|
||||
.tpl-testing-safety-alert .ts-grid-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px;margin-top:20px}
|
||||
.tpl-testing-safety-alert .ts-card{border:1px solid var(--ts-line);border-radius:16px;padding:22px 24px;background:#fff;box-shadow:0 6px 20px rgba(17,19,24,.04)}
|
||||
.tpl-testing-safety-alert .ts-card .lbl{font-size:12px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--ts-muted);margin-bottom:8px}
|
||||
.tpl-testing-safety-alert .ts-card h4{font-size:26px;font-weight:900;line-height:1.2;margin-bottom:8px}
|
||||
.tpl-testing-safety-alert .ts-card p{font-size:14px;color:var(--ts-ink2);line-height:1.55}
|
||||
.tpl-testing-safety-alert .ts-checklist{display:flex;flex-direction:column;gap:12px;margin-top:20px;max-width:880px}
|
||||
.tpl-testing-safety-alert .ts-check{display:flex;gap:16px;align-items:flex-start;padding:16px 20px;border:1px solid var(--ts-line);border-radius:14px;background:#fff}
|
||||
.tpl-testing-safety-alert .ts-check .box{flex:0 0 32px;height:32px;border-radius:8px;border:2px solid var(--ts-red);display:grid;place-items:center;font-weight:900;color:var(--ts-red);background:var(--ts-red-soft)}
|
||||
.tpl-testing-safety-alert .ts-check.ok .box{border-color:var(--ts-green);color:var(--ts-green);background:var(--ts-green-soft)}
|
||||
.tpl-testing-safety-alert .ts-check .txt{font-size:18px;line-height:1.5;font-weight:600}
|
||||
.tpl-testing-safety-alert .ts-codebox{background:#141418;color:#fff5ea;border-radius:14px;padding:22px 26px;font-family:'JetBrains Mono',monospace;font-size:14px;line-height:1.85;margin-top:20px;border-left:6px solid var(--ts-red)}
|
||||
.tpl-testing-safety-alert .ts-codebox .cm{color:#7a756d}
|
||||
.tpl-testing-safety-alert .ts-codebox .kw{color:#ffb38a}
|
||||
.tpl-testing-safety-alert .ts-codebox .st{color:#b3e6c2}
|
||||
.tpl-testing-safety-alert .ts-codebox .bad{color:#ff9aa8;font-weight:700}
|
||||
.tpl-testing-safety-alert .ts-footer{position:absolute;left:84px;right:84px;bottom:36px;display:flex;justify-content:space-between;font-size:12px;color:var(--ts-muted);letter-spacing:.1em}
|
||||
@@ -0,0 +1,8 @@
|
||||
# weekly-report · 周报
|
||||
|
||||
7-slide team weekly report: cover (week range), KPI grid, shipped items, a metric trend chart, blockers, next-week plan, thanks.
|
||||
|
||||
Corporate-clarity palette: near-white background, blue→teal accent, ruled dividers and tiny mono tags (`FEAT`, `FIX`, `EXP`, `INFRA`). Data-dense, readable at a glance, and easy to skim in a standup.
|
||||
|
||||
**Use when:** team weekly readouts, squad reviews, skip-level updates, cross-team "what shipped this week" mails.
|
||||
**Feel:** Linear changelog meets a McKinsey KPI deck — serious, measured, actionable.
|
||||
@@ -0,0 +1,127 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Growth Squad · Weekly W15</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" href="../../../assets/animations/animations.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-weekly-report">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. Cover -->
|
||||
<section class="slide" data-title="Cover">
|
||||
<div class="cover-head">
|
||||
<div class="logo">Growth Squad</div>
|
||||
<div class="week-chip">W15 · 2026-04-07 → 2026-04-13</div>
|
||||
</div>
|
||||
<p class="kicker">WEEKLY REPORT</p>
|
||||
<h1 class="h1 mt-s">本周:付费转化率<br>回到了 <span style="color:var(--accent)">3.8%</span>。</h1>
|
||||
<p class="lede mt-m">6 个发布,3 个实验收敛,1 个阻塞项升级。整体健康。</p>
|
||||
<div class="deck-footer"><span>Prepared by @lewis · reviewed by @may</span><span class="slide-number" data-current="1" data-total="7"></span></div>
|
||||
</section>
|
||||
|
||||
<!-- 2. KPI -->
|
||||
<section class="slide" data-title="KPIs">
|
||||
<p class="kicker">HIGHLIGHTS · KPIs</p>
|
||||
<h2 class="h2">本周核心指标</h2>
|
||||
<div class="grid g4 mt-l">
|
||||
<div class="kpi good"><div class="label">Paid conv.</div><div class="value">3.82%</div><div class="delta up">▲ +0.4 pts WoW</div></div>
|
||||
<div class="kpi good"><div class="label">MRR</div><div class="value">$148k</div><div class="delta up">▲ +6.1%</div></div>
|
||||
<div class="kpi"><div class="label">Signups</div><div class="value">12,430</div><div class="delta flat">— +0.3%</div></div>
|
||||
<div class="kpi bad"><div class="label">D7 retention</div><div class="value">41%</div><div class="delta down">▼ -1.8 pts</div></div>
|
||||
<div class="kpi good"><div class="label">NPS</div><div class="value">64</div><div class="delta up">▲ +3</div></div>
|
||||
<div class="kpi"><div class="label">Support tickets</div><div class="value">318</div><div class="delta flat">— -12</div></div>
|
||||
<div class="kpi warn"><div class="label">p95 latency</div><div class="value">412ms</div><div class="delta down">▼ +38ms</div></div>
|
||||
<div class="kpi good"><div class="label">Deploys</div><div class="value">37</div><div class="delta up">▲ +9</div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 3. Shipped -->
|
||||
<section class="slide" data-title="Shipped">
|
||||
<p class="kicker">SHIPPED THIS WEEK · 6 items</p>
|
||||
<h2 class="h2">Shipped</h2>
|
||||
<div class="mt-l" style="max-width:980px">
|
||||
<div class="ship-item"><span class="tag feat">FEAT</span><div><b>New onboarding checklist v3</b><p class="dim" style="font-size:13px;margin:2px 0 0">4-step checklist replaces the old 7-step modal. A/B won +18% activation.</p></div><span class="owner">@may</span></div>
|
||||
<div class="ship-item"><span class="tag feat">FEAT</span><div><b>Stripe Tax auto-filing</b><p class="dim" style="font-size:13px;margin:2px 0 0">Quarterly filings now handled for 12 US states via Stripe Tax API.</p></div><span class="owner">@raj</span></div>
|
||||
<div class="ship-item"><span class="tag exp">EXP</span><div><b>Pricing page hero test</b><p class="dim" style="font-size:13px;margin:2px 0 0">"From $29" vs "Free trial" headline. Free-trial wins +22% click-through.</p></div><span class="owner">@lewis</span></div>
|
||||
<div class="ship-item"><span class="tag fix">FIX</span><div><b>Edge case in SSO redirect</b><p class="dim" style="font-size:13px;margin:2px 0 0">Google Workspace users with custom domains now land on the correct workspace.</p></div><span class="owner">@eli</span></div>
|
||||
<div class="ship-item"><span class="tag infra">INFRA</span><div><b>Postgres 16 upgrade</b><p class="dim" style="font-size:13px;margin:2px 0 0">Zero-downtime migration. Query p50 down 14%, p95 down 9%.</p></div><span class="owner">@raj</span></div>
|
||||
<div class="ship-item"><span class="tag feat">FEAT</span><div><b>Referral rewards v1</b><p class="dim" style="font-size:13px;margin:2px 0 0">Both sides get 1 month free. Dashboard + email flow live behind flag.</p></div><span class="owner">@may</span></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 4. Metrics chart -->
|
||||
<section class="slide" data-title="Metrics">
|
||||
<p class="kicker">METRIC DEEP-DIVE</p>
|
||||
<h2 class="h2">Paid conversion, last 8 weeks</h2>
|
||||
<div class="chart mt-l">
|
||||
<div class="row" style="justify-content:space-between"><h4>Paid conv. rate · weekly</h4><span class="pill" style="background:var(--surface-2);color:var(--text-2)">target: 4.0%</span></div>
|
||||
<div class="chart-bars">
|
||||
<div class="col"><div class="b" data-v="3.1%" style="height:58%"></div><div class="lbl">W08</div></div>
|
||||
<div class="col"><div class="b" data-v="3.3%" style="height:64%"></div><div class="lbl">W09</div></div>
|
||||
<div class="col"><div class="b" data-v="3.5%" style="height:72%"></div><div class="lbl">W10</div></div>
|
||||
<div class="col"><div class="b" data-v="3.6%" style="height:75%"></div><div class="lbl">W11</div></div>
|
||||
<div class="col"><div class="b" data-v="3.4%" style="height:68%"></div><div class="lbl">W12</div></div>
|
||||
<div class="col"><div class="b" data-v="3.0%" style="height:55%"></div><div class="lbl">W13</div></div>
|
||||
<div class="col"><div class="b" data-v="3.4%" style="height:68%"></div><div class="lbl">W14</div></div>
|
||||
<div class="col"><div class="b" data-v="3.8%" style="height:88%"></div><div class="lbl">W15</div></div>
|
||||
</div>
|
||||
<p class="dim mt-m" style="font-size:13px;margin-top:36px">Drop in W13 tracked to a broken Stripe webhook (fixed W14). Rebound in W15 is driven by the new onboarding checklist.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 5. Blockers -->
|
||||
<section class="slide" data-title="Blockers">
|
||||
<p class="kicker">BLOCKERS · 3 items</p>
|
||||
<h2 class="h2">Needs attention</h2>
|
||||
<div class="mt-l" style="max-width:900px">
|
||||
<div class="blocker">
|
||||
<h4>p95 latency regressed to 412ms (+38ms)</h4>
|
||||
<p>Traced to the new recommender service under load. Adding caching layer + connection pooling.</p>
|
||||
<div class="meta">owner: @raj · ETA: W16 Wed · severity: medium</div>
|
||||
</div>
|
||||
<div class="blocker">
|
||||
<h4>Apple Pay disabled in EU for 3 days</h4>
|
||||
<p>Stripe credential rotation wasn't synced to the EU account. Fixed, but cost ~$4.2k in lost checkouts.</p>
|
||||
<div class="meta">owner: @eli · severity: high · postmortem in progress</div>
|
||||
</div>
|
||||
<div class="blocker">
|
||||
<h4>D7 retention down 1.8 points</h4>
|
||||
<p>Cohort analysis shows it's isolated to the free-trial pricing test. Need to decide: kill test, or push through W16.</p>
|
||||
<div class="meta">owner: @lewis · needs decision from @may by Monday</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 6. Next week -->
|
||||
<section class="slide" data-title="Next Week">
|
||||
<p class="kicker">NEXT WEEK · W16 plan</p>
|
||||
<h2 class="h2">下周重点</h2>
|
||||
<div class="mt-l" style="max-width:960px">
|
||||
<div class="next-row"><div class="owner">@raj</div><div class="task"><b>Ship recommender cache layer</b><span>blocker · must land Wed</span></div></div>
|
||||
<div class="next-row"><div class="owner">@may</div><div class="task"><b>Referral rewards · flag rollout to 100%</b><span>milestone · targets +3% WoW signups</span></div></div>
|
||||
<div class="next-row"><div class="owner">@lewis</div><div class="task"><b>Pricing test: decision doc + readout</b><span>deadline Mon noon</span></div></div>
|
||||
<div class="next-row"><div class="owner">@eli</div><div class="task"><b>Apple Pay postmortem + runbook update</b><span>include in W16 eng review</span></div></div>
|
||||
<div class="next-row"><div class="owner">squad</div><div class="task"><b>Q2 OKR planning offsite</b><span>Thu 2–5pm · async pre-reads Wed</span></div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 7. Thanks -->
|
||||
<section class="slide center tc" data-title="Thanks">
|
||||
<div>
|
||||
<p class="kicker">FIN · week 15</p>
|
||||
<h1 class="h1" style="font-size:100px">Thanks, team 🫶</h1>
|
||||
<p class="lede" style="margin:16px auto">Solid week. Rebound earned, not luck.</p>
|
||||
<div class="row mt-l" style="justify-content:center;gap:16px">
|
||||
<span class="week-chip">Next report: Mon W16</span>
|
||||
<span class="week-chip">questions → #growth-squad</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,55 @@
|
||||
/* weekly-report — corporate clarity */
|
||||
.tpl-weekly-report{
|
||||
--bg:#fafbfc;--bg-soft:#f3f5f9;--surface:#ffffff;--surface-2:#f3f5f9;
|
||||
--border:rgba(22,30,55,.09);--border-strong:rgba(22,30,55,.2);
|
||||
--text-1:#161e37;--text-2:#50586b;--text-3:#8b92a5;
|
||||
--accent:#2e63eb;--accent-2:#0ea5b5;--accent-3:#f59e0b;
|
||||
--good:#10b981;--warn:#f59e0b;--bad:#ef4444;
|
||||
--grad:linear-gradient(120deg,#2e63eb,#0ea5b5);
|
||||
--radius:14px;--radius-lg:18px;
|
||||
--shadow:0 6px 20px rgba(22,30,55,.06),0 1px 3px rgba(22,30,55,.04);
|
||||
font-family:'Inter','Noto Sans SC',sans-serif;
|
||||
}
|
||||
.tpl-weekly-report .slide{padding:64px 88px;background:var(--bg)}
|
||||
.tpl-weekly-report .h1{font-size:64px;line-height:1.05;font-weight:800;letter-spacing:-.025em}
|
||||
.tpl-weekly-report .h2{font-size:42px;font-weight:700;letter-spacing:-.02em}
|
||||
.tpl-weekly-report .kicker{color:var(--accent);font-size:12px;font-weight:700}
|
||||
.tpl-weekly-report .cover-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:48px}
|
||||
.tpl-weekly-report .logo{font-weight:800;font-size:18px;letter-spacing:-.01em}
|
||||
.tpl-weekly-report .logo::before{content:"■";color:var(--accent);margin-right:8px}
|
||||
.tpl-weekly-report .week-chip{display:inline-block;padding:8px 18px;border-radius:8px;background:var(--surface);border:1px solid var(--border);font-family:'JetBrains Mono',monospace;font-size:13px;color:var(--text-2)}
|
||||
.tpl-weekly-report .kpi{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:24px 26px;position:relative;overflow:hidden}
|
||||
.tpl-weekly-report .kpi .label{font-size:12px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-3);font-weight:600}
|
||||
.tpl-weekly-report .kpi .value{font-size:48px;font-weight:800;letter-spacing:-.03em;margin-top:8px;line-height:1}
|
||||
.tpl-weekly-report .kpi .delta{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border-radius:6px;font-size:12px;font-weight:700;margin-top:10px}
|
||||
.tpl-weekly-report .kpi .delta.up{background:rgba(16,185,129,.12);color:var(--good)}
|
||||
.tpl-weekly-report .kpi .delta.down{background:rgba(239,68,68,.12);color:var(--bad)}
|
||||
.tpl-weekly-report .kpi .delta.flat{background:rgba(139,146,165,.14);color:var(--text-2)}
|
||||
.tpl-weekly-report .kpi::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--accent)}
|
||||
.tpl-weekly-report .kpi.good::before{background:var(--good)}
|
||||
.tpl-weekly-report .kpi.warn::before{background:var(--warn)}
|
||||
.tpl-weekly-report .kpi.bad::before{background:var(--bad)}
|
||||
.tpl-weekly-report .ship-item{display:flex;gap:14px;padding:14px 0;border-bottom:1px solid var(--border)}
|
||||
.tpl-weekly-report .ship-item .tag{flex:none;padding:3px 10px;border-radius:6px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;height:22px;display:inline-flex;align-items:center}
|
||||
.tpl-weekly-report .tag.feat{background:rgba(46,99,235,.12);color:var(--accent)}
|
||||
.tpl-weekly-report .tag.fix{background:rgba(16,185,129,.12);color:var(--good)}
|
||||
.tpl-weekly-report .tag.exp{background:rgba(245,158,11,.14);color:var(--warn)}
|
||||
.tpl-weekly-report .tag.infra{background:rgba(14,165,181,.12);color:var(--accent-2)}
|
||||
.tpl-weekly-report .ship-item b{color:var(--text-1);font-weight:600}
|
||||
.tpl-weekly-report .ship-item span.owner{margin-left:auto;color:var(--text-3);font-size:12px;font-family:'JetBrains Mono',monospace}
|
||||
.tpl-weekly-report .chart{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:28px}
|
||||
.tpl-weekly-report .chart-bars{display:flex;align-items:flex-end;gap:16px;height:220px;margin-top:20px}
|
||||
.tpl-weekly-report .chart-bars .col{flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;position:relative}
|
||||
.tpl-weekly-report .chart-bars .col .b{width:100%;background:var(--grad);border-radius:6px 6px 0 0;min-height:6px;position:relative}
|
||||
.tpl-weekly-report .chart-bars .col .b::after{content:attr(data-v);position:absolute;top:-22px;left:0;right:0;text-align:center;font-size:12px;font-weight:700;color:var(--text-1)}
|
||||
.tpl-weekly-report .chart-bars .col .lbl{font-size:11px;color:var(--text-3);font-family:'JetBrains Mono',monospace}
|
||||
.tpl-weekly-report .blocker{background:var(--surface);border-left:3px solid var(--bad);padding:16px 20px;border-radius:8px;margin-bottom:12px}
|
||||
.tpl-weekly-report .blocker h4{font-size:16px;margin-bottom:4px}
|
||||
.tpl-weekly-report .blocker p{font-size:13px;color:var(--text-2);margin:0}
|
||||
.tpl-weekly-report .blocker .meta{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--text-3);margin-top:6px}
|
||||
.tpl-weekly-report .next-row{display:grid;grid-template-columns:110px 1fr;gap:16px;padding:14px 0;border-bottom:1px dashed var(--border);align-items:baseline}
|
||||
.tpl-weekly-report .next-row .owner{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--accent)}
|
||||
.tpl-weekly-report .next-row .task{color:var(--text-1);font-weight:500}
|
||||
.tpl-weekly-report .next-row .task span{color:var(--text-3);font-size:12px;margin-left:8px}
|
||||
.tpl-weekly-report .lede{color:var(--text-2)}
|
||||
.tpl-weekly-report .card{background:var(--surface)}
|
||||
@@ -0,0 +1,11 @@
|
||||
# xhs-pastel-card
|
||||
|
||||
暖奶油 `#fef8f1` 底 + 模糊彩色 blob + Playfair italic 衬线大字 + 整色马卡龙卡片(桃 / 薄荷 / 天 / 丁香 / 柠檬 / 玫瑰)。共性提取自 `20260412-obsidian-skills/html/xhs-obsidian-skills.html` 的 `soft-purple/pink/blue/green/orange/teal` 软色卡系统,以及 `20260409 v2-白底版` 的胶囊 chip 顶部条。
|
||||
|
||||
**Visual traits:** 三颗柔光 blob 作背景、顶部 chip+page 组合、Playfair italic 做 accent 词(em / rose / mint)、整色圆角 28px 大卡片、italic Playfair 序号 01-04、donut SVG 图、小 divider 条 + 渐变、衬线正文做标题 / sans 做正文混排。
|
||||
|
||||
**Use when:** 生活方式 / 个人成长 / 轻内容 / 情感向的小红书贴或个人演讲;你想要一种「不那么科技感、偏杂志偏手作」的气质;适合讲「慢」「休息」「温柔」主题。
|
||||
|
||||
**Source inspiration:** `20260412-obsidian-skills/html/xhs-obsidian-skills.html` + `20260409` v2-白底版(共性 pastel 系统)。
|
||||
|
||||
**Path:** `templates/full-decks/xhs-pastel-card/index.html`
|
||||
@@ -0,0 +1,147 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>XHS Pastel Card</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-xhs-pastel-card">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. COVER -->
|
||||
<section class="slide is-active">
|
||||
<div class="xp-blob b1"></div>
|
||||
<div class="xp-blob b2"></div>
|
||||
<div class="xp-blob b3"></div>
|
||||
<div class="xp-topbar"><div class="xp-chip">A soft manifesto</div><div class="xp-page">01 · 08</div></div>
|
||||
<div class="xp-kicker">Living With AI · 2026</div>
|
||||
<h1 class="xp-h1">放慢一点,<br>让 <em>AI</em> 帮你<br>过一种 <span class="rose">更温柔</span><br>的生活</h1>
|
||||
<div class="xp-divider"></div>
|
||||
<p class="xp-sub">这不是一份效率指南。这是一份「怎么用 AI 少做一些事」的清单 —— 把挤出来的 4 小时还给你自己。</p>
|
||||
<div class="xp-footer"><span>by lewis · pastel edition</span><span>cover</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 2. SECTION -->
|
||||
<section class="slide">
|
||||
<div class="xp-blob b2"></div>
|
||||
<div class="xp-blob b3"></div>
|
||||
<div class="xp-topbar"><div class="xp-chip mint">Chapter one</div><div class="xp-page">02 · 08</div></div>
|
||||
<div style="margin:auto 0">
|
||||
<div class="xp-kicker">先问自己</div>
|
||||
<h1 class="xp-h1" style="font-size:120px">什么事<br>是你 <span class="mint">其实不想做</span> 的?</h1>
|
||||
<p class="xp-sub">不是「不得不做」,是「做的时候灵魂在叹气」。</p>
|
||||
</div>
|
||||
<div class="xp-footer"><span>section · chapter 1</span><span>02 · 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 3. CONTENT 2x2 pastel cards -->
|
||||
<section class="slide">
|
||||
<div class="xp-blob b1"></div>
|
||||
<div class="xp-topbar"><div class="xp-chip rose">Four little escapes</div><div class="xp-page">03 · 08</div></div>
|
||||
<h2 class="xp-h2">四件可以<br>完全交给 <em>AI</em> 的小事</h2>
|
||||
<div class="xp-grid-2">
|
||||
<div class="xp-card peach"><div class="xp-num">01</div><h4>回复那种「收到」邮件</h4><p>它们不需要你思考。让 AI 按你的语气自动处理,一周省 40 分钟。</p></div>
|
||||
<div class="xp-card mint"><div class="xp-num">02</div><h4>订餐厅、改签、查路线</h4><p>一句话外包出去。你只负责选最后选项,不负责翻十个 app。</p></div>
|
||||
<div class="xp-card sky"><div class="xp-num">03</div><h4>把会议录音变成行动项</h4><p>录音 → 摘要 → todo 一键完成。你只需要确认和签字。</p></div>
|
||||
<div class="xp-card lilac"><div class="xp-num">04</div><h4>整理上周拍的 300 张照片</h4><p>按事件分类、挑 10 张精选、写图说。整理档案这件事终于被自动化了。</p></div>
|
||||
</div>
|
||||
<div class="xp-footer"><span>content · 2x2</span><span>03 · 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 4. QUOTE -->
|
||||
<section class="slide">
|
||||
<div class="xp-blob b3"></div>
|
||||
<div class="xp-blob b2"></div>
|
||||
<div class="xp-topbar"><div class="xp-chip lilac">A small pause</div><div class="xp-page">04 · 08</div></div>
|
||||
<div class="xp-hero-card">
|
||||
<p class="xp-quote">效率工具的终点,不是<em> 做更多</em>,<br>而是 <em>有资格做更少</em>。</p>
|
||||
<div class="xp-divider"></div>
|
||||
<p class="xp-sub">当你把「收到」邮件、订餐、行程、照片整理都交出去,你才会惊讶地发现 —— 原来一周有 4 个小时是空的。</p>
|
||||
</div>
|
||||
<div class="xp-footer"><span>quote</span><span>04 · 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 5. CODE / PROMPT -->
|
||||
<section class="slide">
|
||||
<div class="xp-blob b1"></div>
|
||||
<div class="xp-topbar"><div class="xp-chip">My auto-reply prompt</div><div class="xp-page">05 · 08</div></div>
|
||||
<h2 class="xp-h2">把「<em>收到邮件</em>」<br>自动化的 <span class="rose">一段 prompt</span></h2>
|
||||
<pre class="xp-codebox"><span class="cm"># auto-reply skill</span>
|
||||
<span class="kw">when</span> email matches <span class="st">"收到 / 好的 / 确认 / 收到谢谢"</span>:
|
||||
reply:
|
||||
tone: <span class="st">"温柔,简短,不要太商业"</span>
|
||||
max_lines: <span class="hl">2</span>
|
||||
sign_with: <span class="st">"— Lewis"</span>
|
||||
|
||||
<span class="kw">always_skip</span>:
|
||||
- from: [<span class="st">"家人"</span>, <span class="st">"伴侣"</span>, <span class="st">"亲密朋友"</span>]
|
||||
- contains: [<span class="st">"紧急"</span>, <span class="st">"合同"</span>, <span class="st">"付款"</span>]
|
||||
|
||||
<span class="cm"># 一周省 38 分钟,测过</span></pre>
|
||||
<div class="xp-footer"><span>content · prompt</span><span>05 · 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 6. CHART — time donut -->
|
||||
<section class="slide">
|
||||
<div class="xp-blob b2"></div>
|
||||
<div class="xp-topbar"><div class="xp-chip mint">Your week, rebuilt</div><div class="xp-page">06 · 08</div></div>
|
||||
<h2 class="xp-h2">一周 4 小时 <span class="mint">还给自己</span></h2>
|
||||
<div style="display:flex;align-items:center;gap:60px;margin-top:30px">
|
||||
<svg viewBox="0 0 260 260" style="width:300px;flex-shrink:0">
|
||||
<circle cx="130" cy="130" r="100" fill="none" stroke="#fef0e4" stroke-width="40"/>
|
||||
<!-- email 12% -->
|
||||
<circle cx="130" cy="130" r="100" fill="none" stroke="#f48b5c" stroke-width="40" stroke-dasharray="75 628" stroke-dashoffset="0" transform="rotate(-90 130 130)"/>
|
||||
<!-- logistics 18% -->
|
||||
<circle cx="130" cy="130" r="100" fill="none" stroke="#2e9d70" stroke-width="40" stroke-dasharray="113 628" stroke-dashoffset="-75" transform="rotate(-90 130 130)"/>
|
||||
<!-- meetings 14% -->
|
||||
<circle cx="130" cy="130" r="100" fill="none" stroke="#4e7ed6" stroke-width="40" stroke-dasharray="88 628" stroke-dashoffset="-188" transform="rotate(-90 130 130)"/>
|
||||
<!-- photos 6% -->
|
||||
<circle cx="130" cy="130" r="100" fill="none" stroke="#7b5dc4" stroke-width="40" stroke-dasharray="38 628" stroke-dashoffset="-276" transform="rotate(-90 130 130)"/>
|
||||
<text x="130" y="130" text-anchor="middle" font-family="Playfair Display" font-size="44" font-weight="900" fill="#2a2340">4h</text>
|
||||
<text x="130" y="156" text-anchor="middle" font-family="Inter" font-size="12" fill="#9089a8">per week saved</text>
|
||||
</svg>
|
||||
<div style="flex:1">
|
||||
<div class="xp-grid-2" style="grid-template-columns:1fr;gap:12px;margin-top:0">
|
||||
<div class="xp-card peach" style="padding:14px 20px;display:flex;align-items:center;gap:14px"><div style="width:14px;height:14px;border-radius:50%;background:var(--xp-peach-d)"></div><div><h4 style="margin:0;font-size:17px">48 min · 邮件</h4></div></div>
|
||||
<div class="xp-card mint" style="padding:14px 20px;display:flex;align-items:center;gap:14px"><div style="width:14px;height:14px;border-radius:50%;background:var(--xp-mint-d)"></div><div><h4 style="margin:0;font-size:17px">72 min · 订/改/查</h4></div></div>
|
||||
<div class="xp-card sky" style="padding:14px 20px;display:flex;align-items:center;gap:14px"><div style="width:14px;height:14px;border-radius:50%;background:var(--xp-sky-d)"></div><div><h4 style="margin:0;font-size:17px">56 min · 会议摘要</h4></div></div>
|
||||
<div class="xp-card lilac" style="padding:14px 20px;display:flex;align-items:center;gap:14px"><div style="width:14px;height:14px;border-radius:50%;background:var(--xp-lilac-d)"></div><div><h4 style="margin:0;font-size:17px">24 min · 照片整理</h4></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="xp-footer"><span>chart · donut</span><span>06 · 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 7. CTA -->
|
||||
<section class="slide">
|
||||
<div class="xp-blob b1"></div>
|
||||
<div class="xp-blob b3"></div>
|
||||
<div class="xp-topbar"><div class="xp-chip rose">This weekend</div><div class="xp-page">07 · 08</div></div>
|
||||
<h2 class="xp-h2">这周末,<br>先给自己 <em>放一个小假</em></h2>
|
||||
<div class="xp-grid-3">
|
||||
<div class="xp-card lemon"><div class="xp-num">☕</div><h4>Saturday morning</h4><p>挑一个你最烦的小事,写 prompt,让它从此不再烦你。</p></div>
|
||||
<div class="xp-card peach"><div class="xp-num">🌸</div><h4>Saturday afternoon</h4><p>去散步。什么都不带。AI 在家帮你看着消息。</p></div>
|
||||
<div class="xp-card sky"><div class="xp-num">🌙</div><h4>Sunday night</h4><p>复盘:哪 4 小时是真的空的?下周继续。</p></div>
|
||||
</div>
|
||||
<div class="xp-footer"><span>cta</span><span>07 · 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 8. THANKS -->
|
||||
<section class="slide">
|
||||
<div class="xp-blob b2"></div>
|
||||
<div style="margin:auto 0;text-align:center">
|
||||
<div class="xp-kicker" style="text-align:center">thanks for reading</div>
|
||||
<h1 class="xp-h1" style="font-size:160px;text-align:center">谢谢 <em>·</em> thanks</h1>
|
||||
<div class="xp-divider" style="margin:24px auto"></div>
|
||||
<p class="xp-sub" style="margin:0 auto">如果你也想过更温柔的一周,评论区跟我说说你打算把哪一件事先交出去 ♡</p>
|
||||
</div>
|
||||
<div class="xp-footer"><span>end</span><span>08 · 08</span></div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,66 @@
|
||||
/* xhs-pastel-card — 柔和马卡龙大色块封面风 */
|
||||
.tpl-xhs-pastel-card{
|
||||
--xp-bg:#fef8f1;
|
||||
--xp-ink:#2a2340;
|
||||
--xp-ink2:#5b5470;
|
||||
--xp-muted:#9089a8;
|
||||
--xp-peach:#ffd8c2;
|
||||
--xp-peach-d:#f48b5c;
|
||||
--xp-mint:#c8ecd8;
|
||||
--xp-mint-d:#2e9d70;
|
||||
--xp-sky:#c9dcfb;
|
||||
--xp-sky-d:#4e7ed6;
|
||||
--xp-lilac:#ddd0f5;
|
||||
--xp-lilac-d:#7b5dc4;
|
||||
--xp-lemon:#fdf0b2;
|
||||
--xp-lemon-d:#c8910a;
|
||||
--xp-rose:#fcd0dd;
|
||||
--xp-rose-d:#c94673;
|
||||
background:var(--xp-bg);
|
||||
color:var(--xp-ink);
|
||||
font-family:'Playfair Display','Noto Serif SC','Inter','Noto Sans SC',Georgia,serif;
|
||||
}
|
||||
.tpl-xhs-pastel-card .slide{background:var(--xp-bg);color:var(--xp-ink);padding:76px 90px}
|
||||
.tpl-xhs-pastel-card .xp-blob{position:absolute;border-radius:50%;filter:blur(2px);opacity:.85;z-index:0}
|
||||
.tpl-xhs-pastel-card .xp-blob.b1{width:420px;height:420px;background:radial-gradient(circle,var(--xp-peach),transparent 70%);top:-8%;right:-6%}
|
||||
.tpl-xhs-pastel-card .xp-blob.b2{width:360px;height:360px;background:radial-gradient(circle,var(--xp-lilac),transparent 72%);bottom:-10%;left:-8%}
|
||||
.tpl-xhs-pastel-card .xp-blob.b3{width:260px;height:260px;background:radial-gradient(circle,var(--xp-mint),transparent 72%);top:40%;right:20%}
|
||||
.tpl-xhs-pastel-card .slide > *{position:relative;z-index:2}
|
||||
.tpl-xhs-pastel-card .xp-topbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:22px;font-family:'Inter','Noto Sans SC',sans-serif}
|
||||
.tpl-xhs-pastel-card .xp-chip{display:inline-flex;align-items:center;gap:10px;padding:8px 18px;border-radius:999px;background:#fff;border:1.5px solid rgba(42,35,64,.1);font-size:13px;font-weight:600;letter-spacing:.08em;color:var(--xp-ink2);text-transform:uppercase}
|
||||
.tpl-xhs-pastel-card .xp-chip::before{content:'';width:9px;height:9px;border-radius:50%;background:var(--xp-peach-d)}
|
||||
.tpl-xhs-pastel-card .xp-chip.mint::before{background:var(--xp-mint-d)}
|
||||
.tpl-xhs-pastel-card .xp-chip.sky::before{background:var(--xp-sky-d)}
|
||||
.tpl-xhs-pastel-card .xp-chip.lilac::before{background:var(--xp-lilac-d)}
|
||||
.tpl-xhs-pastel-card .xp-chip.rose::before{background:var(--xp-rose-d)}
|
||||
.tpl-xhs-pastel-card .xp-page{font-family:'Inter',sans-serif;font-size:13px;color:var(--xp-muted);letter-spacing:.12em;font-weight:600}
|
||||
.tpl-xhs-pastel-card .xp-kicker{font-family:'Inter',sans-serif;font-size:14px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--xp-peach-d);margin-bottom:14px}
|
||||
.tpl-xhs-pastel-card .xp-h1{font-size:96px;font-weight:900;line-height:1.05;letter-spacing:-2px;margin:0 0 18px;color:var(--xp-ink);font-family:'Playfair Display','Noto Serif SC',serif}
|
||||
.tpl-xhs-pastel-card .xp-h1 em{font-style:italic;color:var(--xp-peach-d);font-family:'Playfair Display',serif}
|
||||
.tpl-xhs-pastel-card .xp-h1 .rose{color:var(--xp-rose-d);font-style:italic}
|
||||
.tpl-xhs-pastel-card .xp-h1 .mint{color:var(--xp-mint-d);font-style:italic}
|
||||
.tpl-xhs-pastel-card .xp-h2{font-size:60px;font-weight:800;line-height:1.1;letter-spacing:-1px;margin:0 0 14px;font-family:'Playfair Display','Noto Serif SC',serif}
|
||||
.tpl-xhs-pastel-card .xp-sub{font-family:'Inter','Noto Sans SC',sans-serif;font-size:21px;line-height:1.6;color:var(--xp-ink2);max-width:800px;font-weight:400}
|
||||
.tpl-xhs-pastel-card .xp-card{border-radius:28px;padding:30px 34px;background:#fff;box-shadow:0 14px 40px rgba(42,35,64,.08);position:relative;overflow:hidden}
|
||||
.tpl-xhs-pastel-card .xp-card.peach{background:var(--xp-peach)}
|
||||
.tpl-xhs-pastel-card .xp-card.mint{background:var(--xp-mint)}
|
||||
.tpl-xhs-pastel-card .xp-card.sky{background:var(--xp-sky)}
|
||||
.tpl-xhs-pastel-card .xp-card.lilac{background:var(--xp-lilac)}
|
||||
.tpl-xhs-pastel-card .xp-card.lemon{background:var(--xp-lemon)}
|
||||
.tpl-xhs-pastel-card .xp-card.rose{background:var(--xp-rose)}
|
||||
.tpl-xhs-pastel-card .xp-card .xp-num{font-family:'Playfair Display',serif;font-size:68px;font-weight:900;font-style:italic;line-height:1;opacity:.85}
|
||||
.tpl-xhs-pastel-card .xp-card h4{font-size:22px;font-weight:800;margin:8px 0;font-family:'Inter','Noto Sans SC',sans-serif}
|
||||
.tpl-xhs-pastel-card .xp-card p{font-family:'Inter','Noto Sans SC',sans-serif;font-size:15px;line-height:1.55;color:var(--xp-ink2)}
|
||||
.tpl-xhs-pastel-card .xp-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-top:26px}
|
||||
.tpl-xhs-pastel-card .xp-grid-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:18px;margin-top:26px}
|
||||
.tpl-xhs-pastel-card .xp-grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-top:24px}
|
||||
.tpl-xhs-pastel-card .xp-hero-card{background:#fff;border-radius:36px;padding:40px 46px;margin-top:28px;box-shadow:0 20px 50px rgba(42,35,64,.1)}
|
||||
.tpl-xhs-pastel-card .xp-quote{font-family:'Playfair Display','Noto Serif SC',serif;font-size:40px;font-weight:800;font-style:italic;line-height:1.3;color:var(--xp-ink)}
|
||||
.tpl-xhs-pastel-card .xp-quote::before{content:'“';font-size:100px;line-height:.8;display:block;color:var(--xp-peach-d);opacity:.7}
|
||||
.tpl-xhs-pastel-card .xp-footer{position:absolute;left:90px;right:90px;bottom:40px;display:flex;justify-content:space-between;font-family:'Inter',sans-serif;font-size:12px;color:var(--xp-muted);letter-spacing:.1em}
|
||||
.tpl-xhs-pastel-card .xp-divider{width:90px;height:4px;background:linear-gradient(90deg,var(--xp-peach-d),var(--xp-rose-d));border-radius:2px;margin:20px 0}
|
||||
.tpl-xhs-pastel-card .xp-codebox{background:#2a2340;color:#fef8f1;border-radius:24px;padding:26px 30px;font-family:'JetBrains Mono',monospace;font-size:14px;line-height:1.85;margin-top:22px}
|
||||
.tpl-xhs-pastel-card .xp-codebox .cm{color:#9089a8}
|
||||
.tpl-xhs-pastel-card .xp-codebox .kw{color:#ffc6a0}
|
||||
.tpl-xhs-pastel-card .xp-codebox .st{color:#c8ecd8}
|
||||
.tpl-xhs-pastel-card .xp-codebox .hl{color:#fcd0dd;font-weight:700}
|
||||
@@ -0,0 +1,9 @@
|
||||
# xhs-post · 小红书 9 图
|
||||
|
||||
小红书 3:4 图文格式,9 张图(810 × 1080)。结构:封面 → hook → 痛点 → aha moment → 步骤 1-3 → 效果 → CTA 关注。
|
||||
|
||||
手写便签 + 贴纸 + 圆角硬阴影的 MUJI/风格,暖米色背景 + 粉橘黄柔和渐变。每页右上角有 `N / 9` 页码贴纸,最后一页有话题 tag。
|
||||
|
||||
**适用场景:** 小红书 / 微博九宫格 / 公众号图文首图 / 抖音图文卡片。
|
||||
**使用方式:** 每张 `.slide` 直接截图导出即可,保持 810×1080 比例。按 → 依次浏览。
|
||||
**Feel:** 手帐、贴纸、闺蜜跟你分享干货的 vibe。
|
||||
@@ -0,0 +1,133 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>每天只睡 6h 还精神?· 小红书图文</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" href="../../../assets/animations/animations.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-xhs-post">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. Cover -->
|
||||
<section class="slide" data-title="Cover">
|
||||
<div class="page-dot">1 / 9</div>
|
||||
<div class="sticker pink" style="top:120px;left:48px;transform:rotate(-6deg)">💤 救命</div>
|
||||
<div class="sticker yellow" style="top:140px;right:64px;transform:rotate(5deg)">亲测 7 天</div>
|
||||
<div style="margin-top:200px">
|
||||
<p class="lede" style="font-size:24px;color:var(--text-1);font-weight:600">打工人深夜自救手册</p>
|
||||
<h1 class="h1 mt-s">每天只睡 <span class="cover-title">6h</span><br>还能<span class="cover-title">精神一整天</span><br>的 3 个小习惯</h1>
|
||||
</div>
|
||||
<div class="bottom-bar"><div><span class="avatar">小</span> <b style="color:var(--text-1);margin-left:8px">@小熊不困了</b></div><div>← 左滑 查看</div></div>
|
||||
</section>
|
||||
|
||||
<!-- 2. Hook -->
|
||||
<section class="slide" data-title="Hook">
|
||||
<div class="page-dot">2 / 9</div>
|
||||
<div class="big-emoji" style="margin-top:80px">👀</div>
|
||||
<h2 class="h2 tc mt-l">等等先别划走!</h2>
|
||||
<p class="lede tc mt-m" style="padding:0 20px">我也曾是那个<br>早上起来像被卡车撞过的人。<br><br>直到我发现了<br><b style="color:var(--accent)">1 件事</b>比睡够 8 小时还重要。</p>
|
||||
<div class="sticker blue" style="bottom:160px;left:50%;transform:translateX(-50%) rotate(-2deg)">真 · 转折点 ↓</div>
|
||||
</section>
|
||||
|
||||
<!-- 3. Pain -->
|
||||
<section class="slide" data-title="Pain">
|
||||
<div class="page-dot">3 / 9</div>
|
||||
<p class="lede" style="font-weight:700;color:var(--accent)">❌ 你是不是也这样</p>
|
||||
<h2 class="h2 mt-s">越睡越累</h2>
|
||||
<div class="stack mt-l">
|
||||
<div class="hand-box"><b style="font-size:22px">😵💫 周末补觉到中午</b><p class="dim" style="font-size:16px;margin-top:4px">起来头更晕,一整天废掉</p></div>
|
||||
<div class="hand-box"><b style="font-size:22px">☕️ 咖啡续三杯</b><p class="dim" style="font-size:16px;margin-top:4px">下午 3 点照样困到扶墙</p></div>
|
||||
<div class="hand-box"><b style="font-size:22px">📱 睡前刷到凌晨</b><p class="dim" style="font-size:16px;margin-top:4px">明明很困就是不舍得睡</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 4. Aha -->
|
||||
<section class="slide" data-title="Aha">
|
||||
<div class="page-dot">4 / 9</div>
|
||||
<div class="sticker green" style="top:100px;right:48px;transform:rotate(4deg)">✨ aha moment</div>
|
||||
<p class="lede mt-l" style="color:var(--accent);font-weight:700">💡 真相是</p>
|
||||
<h2 class="h2 mt-s">不是睡得少,<br>是<span style="background:var(--accent-3);padding:0 8px">醒得不对</span>。</h2>
|
||||
<p class="lede mt-l">身体有 90 分钟一个周期。<br>在"深睡"里被闹钟拽起来,<br>就算睡 9 小时也跟没睡一样。</p>
|
||||
<p class="lede mt-m" style="color:var(--text-1);font-weight:700">关键是:<span style="color:var(--accent)">卡着周期醒</span>。</p>
|
||||
</section>
|
||||
|
||||
<!-- 5. Step 1 -->
|
||||
<section class="slide" data-title="Step 1">
|
||||
<div class="page-dot">5 / 9</div>
|
||||
<div class="num-circle">1</div>
|
||||
<h2 class="h2 mt-m">倒推睡眠时间</h2>
|
||||
<div class="hand-box mt-l">
|
||||
<p style="font-size:22px;margin:0;color:var(--text-1);font-weight:700">👉 公式</p>
|
||||
<p style="font-size:20px;margin:10px 0 0;color:var(--text-2);line-height:1.7">起床时间 − <b style="color:var(--accent)">90min × N</b> − 15min 入睡<br>= 你今晚该上床的点</p>
|
||||
</div>
|
||||
<div class="hand-box mt-m" style="background:#fff5ef">
|
||||
<p style="font-size:18px;margin:0;color:var(--text-2)">举例:要 7 点起</p>
|
||||
<p style="font-size:24px;margin:8px 0 0;color:var(--text-1);font-weight:800">→ 23:15 上床 (4 个周期)<br>→ 00:45 上床 (3 个周期)</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 6. Step 2 -->
|
||||
<section class="slide" data-title="Step 2">
|
||||
<div class="page-dot">6 / 9</div>
|
||||
<div class="num-circle" style="background:var(--accent-2)">2</div>
|
||||
<h2 class="h2 mt-m">早晨 10 分钟光</h2>
|
||||
<div class="hand-box mt-l">
|
||||
<p style="font-size:22px;margin:0;color:var(--text-1);font-weight:700">☀️ 打开窗帘 / 下楼遛弯</p>
|
||||
<p style="font-size:18px;margin:8px 0 0;color:var(--text-2);line-height:1.6">自然光一照,褪黑素立刻被掐停,人就真的醒了。阴天也有效,别偷懒。</p>
|
||||
</div>
|
||||
<div class="sticker yellow" style="bottom:200px;right:60px;transform:rotate(8deg)">⏰ 比咖啡还猛</div>
|
||||
<div class="hand-box mt-m" style="background:#fff5ef">
|
||||
<p style="font-size:18px;margin:0;color:var(--text-2)">懒人方案:</p>
|
||||
<p style="font-size:22px;margin:6px 0 0;color:var(--text-1);font-weight:700">刷牙的时候站在窗边 🪥</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 7. Step 3 -->
|
||||
<section class="slide" data-title="Step 3">
|
||||
<div class="page-dot">7 / 9</div>
|
||||
<div class="num-circle" style="background:var(--accent-3);color:var(--text-1)">3</div>
|
||||
<h2 class="h2 mt-m">下午 3 点<br>20 分钟小睡</h2>
|
||||
<div class="hand-box mt-l">
|
||||
<p style="font-size:20px;margin:0;color:var(--text-2);line-height:1.6"><b style="color:var(--text-1)">⏱️ 最多 20 分钟。</b>超过 30 就会进入深睡,醒来会更累。</p>
|
||||
</div>
|
||||
<div class="hand-box mt-m" style="background:#fff5ef">
|
||||
<p style="font-size:20px;margin:0;color:var(--text-2);line-height:1.6"><b style="color:var(--text-1)">💡 小 tip:</b>睡前喝一口咖啡。20 分钟后咖啡因正好起效,和小睡的清醒 buff 叠加。</p>
|
||||
</div>
|
||||
<div class="sticker pink" style="bottom:140px;left:50%;transform:translateX(-50%) rotate(-3deg)">打工人作弊技</div>
|
||||
</section>
|
||||
|
||||
<!-- 8. Result -->
|
||||
<section class="slide" data-title="Result">
|
||||
<div class="page-dot">8 / 9</div>
|
||||
<p class="lede" style="color:var(--good);font-weight:700">✅ 我坚持 7 天后</p>
|
||||
<h2 class="h2 mt-s">结果是……</h2>
|
||||
<div class="stack mt-l">
|
||||
<div class="hand-box"><b style="font-size:22px">😌 早上闹钟响之前就自然醒</b></div>
|
||||
<div class="hand-box"><b style="font-size:22px">💪 下午不再崩溃</b></div>
|
||||
<div class="hand-box"><b style="font-size:22px">☕️ 咖啡从 3 杯 → 1 杯</b></div>
|
||||
<div class="hand-box" style="background:var(--accent-3);border-color:var(--text-1)"><b style="font-size:24px">✨ 最重要:脾气变好了</b></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 9. CTA -->
|
||||
<section class="slide" data-title="CTA">
|
||||
<div class="page-dot">9 / 9</div>
|
||||
<div class="big-emoji" style="margin-top:60px">💌</div>
|
||||
<h2 class="h2 tc mt-l">觉得有用的话</h2>
|
||||
<h1 class="h1 tc mt-s" style="color:var(--accent)">收藏 + 关注 🧡</h1>
|
||||
<p class="lede tc mt-l" style="padding:0 30px">下期讲<br><b style="color:var(--text-1)">「打工人脊椎急救 5 式」</b><br>办公室也能做</p>
|
||||
<div class="tag-row" style="justify-content:center;margin-top:36px">
|
||||
<span class="ht">#睡眠</span>
|
||||
<span class="ht">#打工人日常</span>
|
||||
<span class="ht">#自律</span>
|
||||
<span class="ht">#健康生活</span>
|
||||
</div>
|
||||
<div class="bottom-bar"><div><span class="avatar">小</span> <b style="color:var(--text-1);margin-left:8px">@小熊不困了</b></div><div>❤️ 5.2w</div></div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,47 @@
|
||||
/* xhs-post — 小红书 3:4 九宫格 */
|
||||
.tpl-xhs-post{
|
||||
--bg:#fef7f3;--bg-soft:#fff1ea;--surface:#ffffff;--surface-2:#fff5ef;
|
||||
--border:rgba(90,40,30,.12);--border-strong:rgba(90,40,30,.24);
|
||||
--text-1:#3a1f18;--text-2:#6f4a3e;--text-3:#a68676;
|
||||
--accent:#ff6b8b;--accent-2:#ffa94d;--accent-3:#ffd166;
|
||||
--grad:linear-gradient(135deg,#ffd3e0,#ffe5c7 50%,#d6f0ff);
|
||||
--good:#7bc67b;--warn:#ffb547;--bad:#ff6b6b;
|
||||
--radius:24px;--radius-lg:32px;
|
||||
--shadow:0 14px 36px rgba(90,40,30,.08);
|
||||
font-family:'Inter','Noto Sans SC','PingFang SC',sans-serif;
|
||||
}
|
||||
.tpl-xhs-post{background:#f0eae2;display:flex;align-items:center;justify-content:center;min-height:100vh}
|
||||
.tpl-xhs-post .deck{width:810px;height:1080px;position:relative;background:transparent}
|
||||
.tpl-xhs-post .slide{
|
||||
position:absolute;inset:0;width:810px;height:1080px;aspect-ratio:3/4;
|
||||
padding:70px 64px;border-radius:28px;overflow:hidden;
|
||||
background:var(--bg);
|
||||
}
|
||||
.tpl-xhs-post .slide::before{content:"";position:absolute;inset:0;background:
|
||||
radial-gradient(45% 30% at 80% 10%,rgba(255,209,102,.35),transparent 70%),
|
||||
radial-gradient(50% 35% at 10% 95%,rgba(255,107,139,.22),transparent 70%),
|
||||
radial-gradient(40% 30% at 90% 85%,rgba(122,200,255,.18),transparent 70%);
|
||||
pointer-events:none;z-index:0}
|
||||
.tpl-xhs-post .slide > *{position:relative;z-index:1}
|
||||
.tpl-xhs-post .h1{font-size:72px;line-height:1.1;font-weight:900;letter-spacing:-.02em;color:var(--text-1)}
|
||||
.tpl-xhs-post .h2{font-size:54px;line-height:1.15;font-weight:800;letter-spacing:-.015em;color:var(--text-1)}
|
||||
.tpl-xhs-post .h3{font-size:36px;font-weight:800;color:var(--text-1)}
|
||||
.tpl-xhs-post .page-dot{position:absolute;top:40px;right:48px;background:var(--text-1);color:#fff;border-radius:999px;padding:6px 14px;font-family:'JetBrains Mono',monospace;font-size:14px;font-weight:700;z-index:2}
|
||||
.tpl-xhs-post .sticker{position:absolute;padding:10px 18px;background:#fff;border:2.5px dashed var(--text-1);border-radius:18px;font-weight:800;font-size:18px;color:var(--text-1);transform:rotate(-3deg);box-shadow:4px 4px 0 var(--text-1)}
|
||||
.tpl-xhs-post .sticker.pink{background:#ffd3e0}
|
||||
.tpl-xhs-post .sticker.yellow{background:#ffe788}
|
||||
.tpl-xhs-post .sticker.blue{background:#cfeaff}
|
||||
.tpl-xhs-post .sticker.green{background:#d4f2c8}
|
||||
.tpl-xhs-post .hand-box{background:#fff;border:2.5px solid var(--text-1);border-radius:22px;padding:24px 28px;box-shadow:5px 5px 0 var(--text-1)}
|
||||
.tpl-xhs-post .lede{color:var(--text-2);font-size:26px;line-height:1.55}
|
||||
.tpl-xhs-post .big-emoji{font-size:180px;line-height:1;text-align:center}
|
||||
.tpl-xhs-post .num-circle{display:inline-flex;align-items:center;justify-content:center;width:72px;height:72px;border-radius:50%;background:var(--accent);color:#fff;font-weight:900;font-size:36px;border:3px solid var(--text-1);box-shadow:4px 4px 0 var(--text-1)}
|
||||
.tpl-xhs-post .step-card{background:#fff;border:2.5px solid var(--text-1);border-radius:22px;padding:26px 28px;box-shadow:5px 5px 0 var(--text-1);margin-bottom:24px}
|
||||
.tpl-xhs-post .step-card h4{font-size:28px;font-weight:800;margin:0 0 6px}
|
||||
.tpl-xhs-post .step-card p{font-size:18px;color:var(--text-2);margin:0}
|
||||
.tpl-xhs-post .tag-row{display:flex;flex-wrap:wrap;gap:10px;margin-top:24px}
|
||||
.tpl-xhs-post .ht{background:#fff;color:var(--accent);border:2px solid var(--text-1);padding:6px 14px;border-radius:999px;font-weight:700;font-size:16px}
|
||||
.tpl-xhs-post .cover-title{background:linear-gradient(180deg,transparent 60%,var(--accent-3) 60%,var(--accent-3) 92%,transparent 92%);padding:0 10px}
|
||||
.tpl-xhs-post .heart{color:var(--accent);font-size:28px}
|
||||
.tpl-xhs-post .bottom-bar{position:absolute;bottom:40px;left:64px;right:64px;display:flex;justify-content:space-between;align-items:center;font-size:15px;color:var(--text-3);font-family:'JetBrains Mono',monospace;z-index:2}
|
||||
.tpl-xhs-post .avatar{width:54px;height:54px;border-radius:50%;background:var(--grad);border:2.5px solid var(--text-1);box-shadow:3px 3px 0 var(--text-1);display:inline-flex;align-items:center;justify-content:center;font-weight:900;font-size:20px;color:var(--text-1)}
|
||||
@@ -0,0 +1,11 @@
|
||||
# xhs-white-editorial
|
||||
|
||||
白底杂志风、强调重点块、macaron soft-card 分组。灵感来自 `20260409 升级版知识库/小红书图文/v2-白底版/slide_01_cover.html` 的顶部彩虹条 + 大字标题,以及 `20260412-AI测试与安全/xhs-ai-testing-safety-v2.html` 的 `.focus` 黑底白字强重点和 macaron 软色卡片系统。
|
||||
|
||||
**Visual traits:** 纯白背景、顶部 10 色彩虹条、巨型 80-110px 标题配轻微负字距、渐变 brand 文字(紫→蓝→绿→橙→粉)、macaron 软色卡(soft-purple / pink / blue / green / orange)、胶囊 tag + dot、黑底 `.focus` 强调框、hero quote box 带淡阴影。
|
||||
|
||||
**Use when:** 你需要一份能当小红书图文、也能当横屏 deck 用的白底内容帖;文字多、重点密集、需要一眼抓住关键词;面向中文读者为主。
|
||||
|
||||
**Source inspiration:** `20260409` xhs v2 白底封面 + `20260412` AI 测试与安全 v2。
|
||||
|
||||
**Path:** `templates/full-decks/xhs-white-editorial/index.html`
|
||||
@@ -0,0 +1,187 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>白底杂志风 · XHS Editorial</title>
|
||||
<link rel="stylesheet" href="../../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../../assets/base.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body class="tpl-xhs-white-editorial">
|
||||
<div class="deck">
|
||||
|
||||
<!-- 1. COVER -->
|
||||
<section class="slide is-active">
|
||||
<div class="xw-topline"></div>
|
||||
<div class="xw-topbar">
|
||||
<div class="xw-tag"><span class="dot"></span>AI 时代 · 职业判断</div>
|
||||
<div class="xw-page">01 / 08</div>
|
||||
</div>
|
||||
<div class="xw-kicker">我越来越确定的一件事</div>
|
||||
<h1 class="xw-title">以后最贵的工作,<br>是 <span class="xw-grad">测试 + 安全</span></h1>
|
||||
<p class="xw-sub">AI 会越来越会做事。但谁来保证它 <span class="xw-focus">做对</span>、<span class="xw-focus">没风险</span>、<span class="xw-focus">不会出事</span>?</p>
|
||||
<div class="xw-hero">
|
||||
<div class="xw-quote">未来最值钱的,<br>不是 <span class="xw-focus-orange">生产</span>,而是 <span class="xw-focus">验收和兜底</span>。</div>
|
||||
</div>
|
||||
<div class="xw-footer"><span>白底|强重点|杂志竖排</span><span>Cover · 01</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 2. SECTION DIVIDER -->
|
||||
<section class="slide">
|
||||
<div class="xw-topline"></div>
|
||||
<div class="xw-topbar">
|
||||
<div class="xw-tag"><span class="dot"></span>Chapter · 01</div>
|
||||
<div class="xw-page">02 / 08</div>
|
||||
</div>
|
||||
<div style="margin-top:120px">
|
||||
<div class="xw-kicker" style="font-size:20px;letter-spacing:.2em;text-transform:uppercase;color:#98a2b3">第一章</div>
|
||||
<h1 class="xw-title" style="font-size:110px;margin-top:20px">先看 <span class="xw-grad">大趋势</span></h1>
|
||||
<p class="xw-sub" style="font-size:28px">当执行越来越便宜,判断就会越来越贵。</p>
|
||||
</div>
|
||||
<div class="xw-footer"><span>Section Divider</span><span>02 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 3. CONTENT — 4 card grid -->
|
||||
<section class="slide">
|
||||
<div class="xw-topline"></div>
|
||||
<div class="xw-topbar">
|
||||
<div class="xw-tag"><span class="dot"></span>越来越多的事会交给 AI</div>
|
||||
<div class="xw-page">03 / 08</div>
|
||||
</div>
|
||||
<h2 class="xw-title-md">未来 3 年,这些事都会 <span class="xw-grad">自动跑</span></h2>
|
||||
<div class="xw-grid-2">
|
||||
<div class="xw-card soft-pink"><div class="xw-label">内容</div><div class="main">写文案 · 写方案 · 写脚本</div><div class="desc">创作变成一个 prompt 的距离</div></div>
|
||||
<div class="xw-card soft-blue"><div class="xw-label">生产</div><div class="main">做图 · 搭页面 · 做表格</div><div class="desc">生产力工具集体重写一次</div></div>
|
||||
<div class="xw-card soft-green"><div class="xw-label">执行</div><div class="main">跑流程 · 写代码 · 自动操作</div><div class="desc">Agent 从 demo 走进真实工作流</div></div>
|
||||
<div class="xw-card soft-orange"><div class="xw-label">分析</div><div class="main">读数据 · 做总结 · 给建议</div><div class="desc">决策支持层彻底向下延伸</div></div>
|
||||
</div>
|
||||
<div class="xw-footer"><span>Content · Grid 2x2</span><span>03 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 4. STEPS -->
|
||||
<section class="slide">
|
||||
<div class="xw-topline"></div>
|
||||
<div class="xw-topbar">
|
||||
<div class="xw-tag"><span class="dot"></span>为什么会这样</div>
|
||||
<div class="xw-page">04 / 08</div>
|
||||
</div>
|
||||
<h2 class="xw-title-md">AI 越强,<span class="xw-grad">判断对错</span> 越值钱</h2>
|
||||
<div class="xw-steps">
|
||||
<div class="xw-step"><div class="xw-num">1</div><div class="xw-txt">生产会更便宜,边际成本接近零</div></div>
|
||||
<div class="xw-step"><div class="xw-num">2</div><div class="xw-txt">复制会更快,错误也一起被加速</div></div>
|
||||
<div class="xw-step"><div class="xw-num">3</div><div class="xw-txt">AI 一本正经地做错,人类难以察觉</div></div>
|
||||
<div class="xw-step"><div class="xw-num">4</div><div class="xw-txt">所以最贵的能力会变成 <span class="xw-focus">发现问题</span></div></div>
|
||||
</div>
|
||||
<div class="xw-hero"><div class="xw-quote" style="font-size:30px">AI 让「<span class="xw-focus-blue">做出来</span>」变便宜,<br>但让「<span class="xw-focus">做对、做稳、别出事</span>」变更贵。</div></div>
|
||||
<div class="xw-footer"><span>Content · Steps</span><span>04 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 5. CODE EXAMPLE -->
|
||||
<section class="slide">
|
||||
<div class="xw-topline"></div>
|
||||
<div class="xw-topbar">
|
||||
<div class="xw-tag"><span class="dot"></span>一段你今晚就能跑的验收 Skill</div>
|
||||
<div class="xw-page">05 / 08</div>
|
||||
</div>
|
||||
<h2 class="xw-title-md">不是写 prompt,<br>是写 <span class="xw-grad">验收清单</span></h2>
|
||||
<pre class="xw-codebox"><span class="cm"># skills/ai-acceptance/SKILL.md</span>
|
||||
<span class="kw">name</span>: <span class="st">ai-acceptance</span>
|
||||
<span class="kw">description</span>: <span class="st">"Runs AI output through a 4-gate review checklist."</span>
|
||||
|
||||
<span class="kw">gates</span>:
|
||||
- <span class="hl">functional</span>: <span class="st">"Does it actually do what the user asked?"</span>
|
||||
- <span class="hl">edge_cases</span>: <span class="st">"Empty / long / non-ASCII / concurrent?"</span>
|
||||
- <span class="hl">safety</span>: <span class="st">"PII, secrets, destructive ops — all red-flagged?"</span>
|
||||
- <span class="hl">rollback</span>: <span class="st">"If this ships and breaks, can we undo in 60s?"</span></pre>
|
||||
<div class="xw-footer"><span>Content · Code Block</span><span>05 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 6. CHART — SVG bar -->
|
||||
<section class="slide">
|
||||
<div class="xw-topline"></div>
|
||||
<div class="xw-topbar">
|
||||
<div class="xw-tag"><span class="dot"></span>岗位相对价值变化</div>
|
||||
<div class="xw-page">06 / 08</div>
|
||||
</div>
|
||||
<h2 class="xw-title-md">越来越 <span class="xw-focus-pink">便宜</span>,越来越 <span class="xw-focus-green">贵</span></h2>
|
||||
<svg viewBox="0 0 960 380" style="width:100%;max-width:1000px;margin-top:30px" xmlns="http://www.w3.org/2000/svg">
|
||||
<g font-family="Inter, sans-serif" font-size="16" fill="#475467">
|
||||
<!-- baseline -->
|
||||
<line x1="180" y1="330" x2="940" y2="330" stroke="#eaecf3" stroke-width="2"/>
|
||||
<!-- rows -->
|
||||
<g transform="translate(0,40)">
|
||||
<text x="170" y="30" text-anchor="end" font-weight="700" fill="#111">纯执行</text>
|
||||
<rect x="180" y="10" width="520" height="28" rx="14" fill="#fff0f6"/>
|
||||
<rect x="180" y="10" width="120" height="28" rx="14" fill="#ff5fa2"/>
|
||||
<text x="710" y="30" fill="#c11574" font-weight="700">-65% 价值</text>
|
||||
</g>
|
||||
<g transform="translate(0,100)">
|
||||
<text x="170" y="30" text-anchor="end" font-weight="700" fill="#111">内容生产</text>
|
||||
<rect x="180" y="10" width="520" height="28" rx="14" fill="#eef4ff"/>
|
||||
<rect x="180" y="10" width="200" height="28" rx="14" fill="#4e8cff"/>
|
||||
<text x="710" y="30" fill="#174ea6" font-weight="700">-40% 价值</text>
|
||||
</g>
|
||||
<g transform="translate(0,160)">
|
||||
<text x="170" y="30" text-anchor="end" font-weight="700" fill="#111">数据分析</text>
|
||||
<rect x="180" y="10" width="520" height="28" rx="14" fill="#fff5ea"/>
|
||||
<rect x="180" y="10" width="320" height="28" rx="14" fill="#ff9d42"/>
|
||||
<text x="710" y="30" fill="#b54708" font-weight="700">持平</text>
|
||||
</g>
|
||||
<g transform="translate(0,220)">
|
||||
<text x="170" y="30" text-anchor="end" font-weight="700" fill="#111">测试 / 验收</text>
|
||||
<rect x="180" y="10" width="520" height="28" rx="14" fill="#edfdf3"/>
|
||||
<rect x="180" y="10" width="440" height="28" rx="14" fill="#17b26a"/>
|
||||
<text x="710" y="30" fill="#067647" font-weight="700">+85% 价值</text>
|
||||
</g>
|
||||
<g transform="translate(0,280)">
|
||||
<text x="170" y="30" text-anchor="end" font-weight="700" fill="#111">安全 / 风控</text>
|
||||
<rect x="180" y="10" width="520" height="28" rx="14" fill="#f4efff"/>
|
||||
<rect x="180" y="10" width="500" height="28" rx="14" fill="#7b61ff"/>
|
||||
<text x="710" y="30" fill="#5b21b6" font-weight="700">+110% 价值</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<div class="xw-footer"><span>Chart · Horizontal Bars</span><span>06 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 7. CTA -->
|
||||
<section class="slide">
|
||||
<div class="xw-topline"></div>
|
||||
<div class="xw-topbar">
|
||||
<div class="xw-tag"><span class="dot"></span>今晚就可以做的三件事</div>
|
||||
<div class="xw-page">07 / 08</div>
|
||||
</div>
|
||||
<h2 class="xw-title-md">别再追工具,<br>开始练 <span class="xw-grad">判断力</span></h2>
|
||||
<div class="xw-grid-3">
|
||||
<div class="xw-card soft-purple"><div class="xw-label">Tonight</div><div class="main">写一份<br>验收清单</div><div class="desc">哪怕只有 5 条,开始比完美更重要</div></div>
|
||||
<div class="xw-card soft-blue"><div class="xw-label">This week</div><div class="main">跑一遍<br>红队演练</div><div class="desc">对自己的 agent 说:试着让它出事</div></div>
|
||||
<div class="xw-card soft-green"><div class="xw-label">This month</div><div class="main">加一条<br>回滚流程</div><div class="desc">60 秒内能撤销,你就敢把手放开</div></div>
|
||||
</div>
|
||||
<div class="xw-hero"><div class="xw-quote" style="font-size:32px">真正的稀缺,不是「会用 AI」,<br>而是 <span class="xw-focus">「敢为 AI 的结果签字」</span>。</div></div>
|
||||
<div class="xw-footer"><span>CTA</span><span>07 / 08</span></div>
|
||||
</section>
|
||||
|
||||
<!-- 8. THANKS -->
|
||||
<section class="slide">
|
||||
<div class="xw-topline"></div>
|
||||
<div class="xw-topbar">
|
||||
<div class="xw-tag"><span class="dot"></span>Thanks for reading</div>
|
||||
<div class="xw-page">08 / 08</div>
|
||||
</div>
|
||||
<div style="margin-top:100px">
|
||||
<div class="xw-big-stat xw-grad">谢谢<small> · thanks</small></div>
|
||||
<p class="xw-sub" style="font-size:28px;margin-top:36px">如果你也在想这些问题,欢迎在评论里告诉我——<br>你最想让 AI 帮你做什么?你最不放心它做什么?</p>
|
||||
<div style="margin-top:40px">
|
||||
<span class="xw-pill">@lewis</span>
|
||||
<span class="xw-pill">小红书 · 白底杂志风</span>
|
||||
<span class="xw-pill">html-ppt · full-deck</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="xw-footer"><span>End</span><span>08 / 08</span></div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<script src="../../../assets/runtime.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,63 @@
|
||||
/* xhs-white-editorial — 白底杂志风 */
|
||||
.tpl-xhs-white-editorial{
|
||||
--xw-bg:#ffffff;
|
||||
--xw-ink:#111318;
|
||||
--xw-ink2:#475467;
|
||||
--xw-muted:#98a2b3;
|
||||
--xw-line:#eaecf3;
|
||||
--xw-purple:#7b61ff;
|
||||
--xw-pink:#ff5fa2;
|
||||
--xw-blue:#4e8cff;
|
||||
--xw-green:#17b26a;
|
||||
--xw-orange:#ff9d42;
|
||||
--xw-soft-purple:#f4efff;
|
||||
--xw-soft-pink:#fff0f6;
|
||||
--xw-soft-blue:#eef4ff;
|
||||
--xw-soft-green:#edfdf3;
|
||||
--xw-soft-orange:#fff5ea;
|
||||
background:var(--xw-bg);
|
||||
color:var(--xw-ink);
|
||||
font-family:'Inter','Noto Sans SC','PingFang SC',-apple-system,sans-serif;
|
||||
}
|
||||
.tpl-xhs-white-editorial .slide{background:#fff;padding:72px 88px}
|
||||
.tpl-xhs-white-editorial .xw-topbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:18px}
|
||||
.tpl-xhs-white-editorial .xw-tag{display:inline-flex;align-items:center;gap:10px;padding:10px 18px;border:1px solid var(--xw-line);border-radius:999px;font-size:15px;color:var(--xw-ink2);background:#fff}
|
||||
.tpl-xhs-white-editorial .xw-tag .dot{width:10px;height:10px;border-radius:50%;background:linear-gradient(90deg,#7b61ff,#4e8cff,#17b26a,#ff9d42,#ff5fa2)}
|
||||
.tpl-xhs-white-editorial .xw-page{font-size:14px;color:var(--xw-muted);letter-spacing:.1em}
|
||||
.tpl-xhs-white-editorial .xw-kicker{font-size:18px;color:var(--xw-ink2);margin-top:6px;font-weight:500}
|
||||
.tpl-xhs-white-editorial .xw-title{font-size:84px;line-height:1.02;letter-spacing:-2px;font-weight:850;margin:18px 0 0;color:var(--xw-ink)}
|
||||
.tpl-xhs-white-editorial .xw-title-md{font-size:60px;line-height:1.05;letter-spacing:-1.5px;font-weight:800;margin:14px 0 0}
|
||||
.tpl-xhs-white-editorial .xw-grad{background:linear-gradient(90deg,#7b61ff 0%,#4e8cff 25%,#17b26a 48%,#ff9d42 72%,#ff5fa2 100%);-webkit-background-clip:text;background-clip:text;color:transparent}
|
||||
.tpl-xhs-white-editorial .xw-sub{font-size:24px;line-height:1.45;color:#1f2937;margin-top:22px;max-width:900px}
|
||||
.tpl-xhs-white-editorial .xw-focus{display:inline-block;padding:6px 14px;border-radius:14px;background:#111318;color:#fff;font-weight:700}
|
||||
.tpl-xhs-white-editorial .xw-focus-blue{display:inline-block;padding:6px 14px;border-radius:14px;background:var(--xw-soft-blue);color:#174ea6;font-weight:700}
|
||||
.tpl-xhs-white-editorial .xw-focus-pink{display:inline-block;padding:6px 14px;border-radius:14px;background:var(--xw-soft-pink);color:#c11574;font-weight:700}
|
||||
.tpl-xhs-white-editorial .xw-focus-orange{display:inline-block;padding:6px 14px;border-radius:14px;background:var(--xw-soft-orange);color:#b54708;font-weight:700}
|
||||
.tpl-xhs-white-editorial .xw-focus-green{display:inline-block;padding:6px 14px;border-radius:14px;background:var(--xw-soft-green);color:#067647;font-weight:700}
|
||||
.tpl-xhs-white-editorial .xw-hero{margin-top:28px;border:1px solid var(--xw-line);border-radius:28px;padding:30px 34px;background:linear-gradient(180deg,#fff 0%,#fcfcff 100%);box-shadow:0 18px 48px rgba(17,19,24,.08)}
|
||||
.tpl-xhs-white-editorial .xw-quote{font-size:38px;line-height:1.3;font-weight:800;letter-spacing:-.5px}
|
||||
.tpl-xhs-white-editorial .xw-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:22px}
|
||||
.tpl-xhs-white-editorial .xw-grid-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px;margin-top:22px}
|
||||
.tpl-xhs-white-editorial .xw-card{border:1px solid var(--xw-line);border-radius:24px;padding:24px 26px;box-shadow:0 10px 24px rgba(17,19,24,.04);background:#fff}
|
||||
.tpl-xhs-white-editorial .xw-card.soft-purple{background:var(--xw-soft-purple)}
|
||||
.tpl-xhs-white-editorial .xw-card.soft-pink{background:var(--xw-soft-pink)}
|
||||
.tpl-xhs-white-editorial .xw-card.soft-blue{background:var(--xw-soft-blue)}
|
||||
.tpl-xhs-white-editorial .xw-card.soft-green{background:var(--xw-soft-green)}
|
||||
.tpl-xhs-white-editorial .xw-card.soft-orange{background:var(--xw-soft-orange)}
|
||||
.tpl-xhs-white-editorial .xw-label{font-size:14px;font-weight:800;opacity:.7;margin-bottom:10px;letter-spacing:.08em;text-transform:uppercase}
|
||||
.tpl-xhs-white-editorial .xw-card .main{font-size:28px;line-height:1.22;font-weight:850;letter-spacing:-.5px}
|
||||
.tpl-xhs-white-editorial .xw-card .desc{font-size:16px;line-height:1.5;color:#475467;margin-top:12px}
|
||||
.tpl-xhs-white-editorial .xw-steps{margin-top:18px}
|
||||
.tpl-xhs-white-editorial .xw-step{display:flex;gap:18px;align-items:flex-start;margin:16px 0}
|
||||
.tpl-xhs-white-editorial .xw-num{flex:0 0 48px;height:48px;border-radius:50%;background:#111318;color:#fff;display:grid;place-items:center;font-size:20px;font-weight:900}
|
||||
.tpl-xhs-white-editorial .xw-txt{font-size:22px;line-height:1.45;font-weight:700}
|
||||
.tpl-xhs-white-editorial .xw-codebox{background:#0f1117;color:#e4e2d8;border-radius:18px;padding:22px 26px;font-family:'JetBrains Mono',monospace;font-size:15px;line-height:1.75;margin-top:20px;border:1px solid #1f222c}
|
||||
.tpl-xhs-white-editorial .xw-codebox .cm{color:#6b6a62}
|
||||
.tpl-xhs-white-editorial .xw-codebox .kw{color:#c88f64}
|
||||
.tpl-xhs-white-editorial .xw-codebox .st{color:#a8c292}
|
||||
.tpl-xhs-white-editorial .xw-codebox .hl{color:#e9c58a;font-weight:600}
|
||||
.tpl-xhs-white-editorial .xw-footer{position:absolute;left:88px;right:88px;bottom:44px;display:flex;justify-content:space-between;align-items:flex-end;font-size:13px;color:var(--xw-muted)}
|
||||
.tpl-xhs-white-editorial .xw-topline{position:absolute;top:0;left:0;right:0;height:5px;background:linear-gradient(90deg,#6366f1,#8b5cf6,#a855f7,#ec4899,#f43f5e,#f97316,#eab308,#22c55e,#06b6d4,#6366f1)}
|
||||
.tpl-xhs-white-editorial .xw-pill{display:inline-block;padding:8px 16px;border-radius:999px;font-size:14px;font-weight:700;margin:0 8px 8px 0;background:#fff;border:1px solid var(--xw-line);color:#394150}
|
||||
.tpl-xhs-white-editorial .xw-big-stat{font-size:96px;font-weight:900;letter-spacing:-4px;line-height:1}
|
||||
.tpl-xhs-white-editorial .xw-big-stat small{font-size:22px;color:var(--xw-muted);font-weight:700;letter-spacing:0;margin-left:6px}
|
||||
@@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8"><title>Layout Showcase — html-ppt</title>
|
||||
<link rel="stylesheet" href="../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../assets/animations/animations.css">
|
||||
<style>
|
||||
.layout-nav{position:fixed;top:16px;left:50%;transform:translateX(-50%);z-index:50;background:var(--surface);border:1px solid var(--border);border-radius:999px;padding:8px 20px;font-family:var(--font-mono);font-size:12px;color:var(--text-2);box-shadow:var(--shadow);display:flex;gap:14px;align-items:center}
|
||||
.layout-nav a{color:var(--text-2);text-decoration:none;padding:4px 10px;border-radius:999px}
|
||||
.layout-nav a:hover{background:var(--surface-2)}
|
||||
iframe{width:100%;height:100vh;border:0;display:block;background:var(--bg)}
|
||||
body{margin:0;overflow:hidden}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="layout-nav">
|
||||
<b>layouts</b>
|
||||
<a href="#" data-go="-1">←</a>
|
||||
<span id="cur">cover</span>
|
||||
<a href="#" data-go="+1">→</a>
|
||||
</div>
|
||||
<iframe id="frame" src="single-page/cover.html"></iframe>
|
||||
<script>
|
||||
const list=['cover','toc','section-divider','bullets','two-column','three-column','big-quote',
|
||||
'stat-highlight','kpi-grid','table','code','diff','terminal','flow-diagram','timeline',
|
||||
'roadmap','mindmap','comparison','pros-cons','todo-checklist','gantt','image-hero','image-grid',
|
||||
'chart-bar','chart-line','chart-pie','chart-radar','arch-diagram','process-steps','cta','thanks'];
|
||||
let i=0;
|
||||
const frame=document.getElementById('frame');
|
||||
const cur=document.getElementById('cur');
|
||||
function go(n){
|
||||
i=(n+list.length)%list.length;
|
||||
frame.src='single-page/'+list[i]+'.html';
|
||||
cur.textContent=list[i]+' · '+(i+1)+'/'+list.length;
|
||||
history.replaceState(null,'','#/'+(i+1));
|
||||
}
|
||||
document.querySelectorAll('[data-go]').forEach(a=>a.addEventListener('click',e=>{e.preventDefault();go(i+parseInt(a.dataset.go,10))}));
|
||||
document.addEventListener('keydown',e=>{
|
||||
if(e.key==='ArrowRight'||e.key===' '){go(i+1);e.preventDefault()}
|
||||
if(e.key==='ArrowLeft'){go(i-1);e.preventDefault()}
|
||||
});
|
||||
const m=/^#\/(\d+)/.exec(location.hash||'');
|
||||
if(m)go(parseInt(m[1],10)-1);else go(0);
|
||||
</script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Architecture</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.arch{margin-top:20px;display:grid;grid-template-rows:auto auto auto;gap:22px}
|
||||
.arch .tier{display:grid;grid-template-columns:120px 1fr;align-items:stretch;gap:22px}
|
||||
.arch .tname{display:flex;align-items:center;justify-content:center;background:var(--surface-2);border-radius:var(--radius);padding:18px;font-weight:600;font-size:13px;color:var(--text-2);text-transform:uppercase;letter-spacing:.1em;text-align:center}
|
||||
.arch .cells{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
|
||||
.arch .cells.three{grid-template-columns:repeat(3,1fr)}
|
||||
.arch .cell{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:16px;text-align:center;box-shadow:var(--shadow)}
|
||||
.arch .cell .ic{font-size:24px}
|
||||
.arch .cell h4{font-size:14px;margin:6px 0 2px}
|
||||
.arch .cell p{font-size:11px;color:var(--text-3);margin:0}
|
||||
.arch .tier.hl .cell{border-top:3px solid var(--accent)}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Architecture">
|
||||
<p class="kicker">Architecture · 系统总览</p>
|
||||
<h2 class="h2">一套三层栈</h2>
|
||||
<div class="arch anim-stagger-list" data-anim-target>
|
||||
<div class="tier"><div class="tname">UI Layer</div>
|
||||
<div class="cells"><div class="cell"><div class="ic">🧱</div><h4>Layouts</h4><p>30 个单页</p></div>
|
||||
<div class="cell"><div class="ic">🎨</div><h4>Themes</h4><p>24 tokens 主题</p></div>
|
||||
<div class="cell"><div class="ic">✨</div><h4>Animations</h4><p>25 个命名动效</p></div>
|
||||
<div class="cell"><div class="ic">⌨️</div><h4>Runtime</h4><p>键盘导航</p></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tier hl"><div class="tname">Core · tokens</div>
|
||||
<div class="cells three"><div class="cell"><div class="ic">🎯</div><h4>base.css</h4><p>排版 + 网格</p></div>
|
||||
<div class="cell"><div class="ic">🔤</div><h4>fonts.css</h4><p>中英字体</p></div>
|
||||
<div class="cell"><div class="ic">🪞</div><h4>:root vars</h4><p>语义颜色</p></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tier"><div class="tname">Tooling</div>
|
||||
<div class="cells three"><div class="cell"><div class="ic">🧪</div><h4>render.sh</h4><p>headless Chrome</p></div>
|
||||
<div class="cell"><div class="ic">🆕</div><h4>new-deck.sh</h4><p>脚手架</p></div>
|
||||
<div class="cell"><div class="ic">📦</div><h4>AgentSkill</h4><p>Claude 接入点</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Big Quote</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/editorial-serif.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active center tc" data-title="Quote">
|
||||
<div style="max-width:1040px">
|
||||
<div class="serif" style="font-size:140px;line-height:.9;color:var(--accent);opacity:.6">"</div>
|
||||
<blockquote class="serif anim-fade-up" data-anim="fade-up" style="font-size:56px;line-height:1.25;margin:-40px 0 24px;font-style:italic;font-weight:600">
|
||||
好的设计不是把东西加得更多,<br>而是把一切不需要的东西拿掉。
|
||||
</blockquote>
|
||||
<p class="dim" style="font-size:20px;letter-spacing:.08em">— Dieter Rams</p>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Bullets</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Why">
|
||||
<p class="kicker">Why · 为什么</p>
|
||||
<h2 class="h2">好的演讲系统,帮你做三件事</h2>
|
||||
<p class="lede mb-l">不是做不出漂亮的 slide,是每次都要重新做。</p>
|
||||
<ul class="grid g1 anim-stagger-list" style="list-style:none;padding:0;margin:0;gap:14px" data-anim-target>
|
||||
<li class="card card-accent"><h4>① 统一设计语言</h4><p class="dim">所有页共用同一套 tokens,字号、颜色、阴影不会跑偏。</p></li>
|
||||
<li class="card card-accent"><h4>② 降低复用成本</h4><p class="dim">下一次讲同类话题,复制 deck、换数据、换主题即可。</p></li>
|
||||
<li class="card card-accent"><h4>③ 可切换,可演示</h4><p class="dim">按 T 即可循环切主题、按 A 可切动效,汇报现场加分。</p></li>
|
||||
</ul>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Chart · Bar</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"></script>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Bar chart">
|
||||
<p class="kicker">Chart · 柱状图</p>
|
||||
<h2 class="h2">季度 MRR 趋势</h2>
|
||||
<div class="card mt-l" style="height:520px;padding:28px"><canvas id="c"></canvas></div>
|
||||
<script>
|
||||
addEventListener('DOMContentLoaded',()=>{
|
||||
const css=getComputedStyle(document.documentElement);
|
||||
const accent=css.getPropertyValue('--accent').trim();
|
||||
const text2=css.getPropertyValue('--text-2').trim();
|
||||
const border=css.getPropertyValue('--border').trim();
|
||||
new Chart(document.getElementById('c'),{type:'bar',
|
||||
data:{labels:['Q1','Q2','Q3','Q4','Q1 +1','Q2 +1','Q3 +1','Q4 +1'],
|
||||
datasets:[{label:'MRR (K)',data:[42,58,73,96,124,158,204,261],
|
||||
backgroundColor:accent,borderRadius:8,barThickness:36}]},
|
||||
options:{plugins:{legend:{labels:{color:text2}}},
|
||||
scales:{x:{ticks:{color:text2},grid:{color:border}},
|
||||
y:{ticks:{color:text2},grid:{color:border}}}}});
|
||||
});
|
||||
</script>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Chart · Line</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"></script>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Line chart">
|
||||
<p class="kicker">Chart · 折线图</p>
|
||||
<h2 class="h2">日活与留存并排看</h2>
|
||||
<div class="card mt-l" style="height:520px;padding:28px"><canvas id="c"></canvas></div>
|
||||
<script>
|
||||
addEventListener('DOMContentLoaded',()=>{
|
||||
const css=getComputedStyle(document.documentElement);
|
||||
const accent=css.getPropertyValue('--accent').trim();
|
||||
const acc2=css.getPropertyValue('--accent-2').trim();
|
||||
const text2=css.getPropertyValue('--text-2').trim();
|
||||
const border=css.getPropertyValue('--border').trim();
|
||||
new Chart(document.getElementById('c'),{type:'line',
|
||||
data:{labels:['W1','W2','W3','W4','W5','W6','W7','W8','W9','W10','W11','W12'],
|
||||
datasets:[
|
||||
{label:'DAU (K)',data:[12,14,15,19,24,28,33,38,45,51,58,66],
|
||||
borderColor:accent,backgroundColor:accent+'22',fill:true,tension:.4,borderWidth:3,pointRadius:4},
|
||||
{label:'Retention %',data:[38,40,42,45,48,50,53,55,58,60,62,64],
|
||||
borderColor:acc2,backgroundColor:acc2+'22',fill:true,tension:.4,borderWidth:3,pointRadius:4}
|
||||
]},
|
||||
options:{plugins:{legend:{labels:{color:text2}}},
|
||||
scales:{x:{ticks:{color:text2},grid:{color:border}},
|
||||
y:{ticks:{color:text2},grid:{color:border}}}}});
|
||||
});
|
||||
</script>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,36 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Chart · Pie</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"></script>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Pie chart">
|
||||
<p class="kicker">Chart · 环形图</p>
|
||||
<h2 class="h2">时间都花在了哪里</h2>
|
||||
<div class="grid g2 mt-l" style="align-items:center">
|
||||
<div class="card" style="height:460px;padding:28px"><canvas id="c"></canvas></div>
|
||||
<div class="card">
|
||||
<h4>Takeaways</h4>
|
||||
<p class="dim">超过一半的时间都在写内容,动效只占 5%。说明值得把动效做成可复用模板。</p>
|
||||
<ul class="mt-m dim">
|
||||
<li>✍️ 写内容 55%</li><li>🧩 挑版式 18%</li><li>🎨 调样式 14%</li>
|
||||
<li>📸 出图 8%</li><li>✨ 动效 5%</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
addEventListener('DOMContentLoaded',()=>{
|
||||
const css=getComputedStyle(document.documentElement);
|
||||
const colors=['--accent','--accent-2','--accent-3','--good','--warn'].map(k=>css.getPropertyValue(k).trim());
|
||||
const text2=css.getPropertyValue('--text-2').trim();
|
||||
new Chart(document.getElementById('c'),{type:'doughnut',
|
||||
data:{labels:['写内容','挑版式','调样式','出图','动效'],
|
||||
datasets:[{data:[55,18,14,8,5],backgroundColor:colors,borderWidth:0}]},
|
||||
options:{cutout:'62%',plugins:{legend:{position:'right',labels:{color:text2}}}}});
|
||||
});
|
||||
</script>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Chart · Radar</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"></script>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Radar chart">
|
||||
<p class="kicker">Chart · 雷达图</p>
|
||||
<h2 class="h2">把 html-ppt 和竞品放一张图</h2>
|
||||
<div class="card mt-l" style="height:520px;padding:28px"><canvas id="c"></canvas></div>
|
||||
<script>
|
||||
addEventListener('DOMContentLoaded',()=>{
|
||||
const css=getComputedStyle(document.documentElement);
|
||||
const a1=css.getPropertyValue('--accent').trim();
|
||||
const a2=css.getPropertyValue('--accent-2').trim();
|
||||
const text2=css.getPropertyValue('--text-2').trim();
|
||||
new Chart(document.getElementById('c'),{type:'radar',
|
||||
data:{labels:['上手','美观','自定义','性能','导出','生态'],
|
||||
datasets:[
|
||||
{label:'html-ppt',data:[9,9,10,10,9,6],borderColor:a1,backgroundColor:a1+'33',borderWidth:3,pointRadius:5},
|
||||
{label:'reveal.js',data:[8,7,9,8,8,10],borderColor:a2,backgroundColor:a2+'22',borderWidth:3,pointRadius:5}]},
|
||||
options:{plugins:{legend:{labels:{color:text2}}},
|
||||
scales:{r:{suggestedMin:0,suggestedMax:10,ticks:{color:text2,backdropColor:'transparent'},
|
||||
pointLabels:{color:text2,font:{size:14}},grid:{color:'rgba(0,0,0,.08)'},angleLines:{color:'rgba(0,0,0,.08)'}}}}});
|
||||
});
|
||||
</script>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Code</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/tokyo-night.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@11.10.0/styles/tokyo-night-dark.min.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/highlight.js@11.10.0/lib/core.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/highlight.js@11.10.0/lib/languages/javascript.min.js"></script>
|
||||
<script>addEventListener('DOMContentLoaded',()=>{hljs.registerLanguage('javascript',window.hljsLangJavascript||window.hljs.getLanguage('javascript'));document.querySelectorAll('pre code').forEach(el=>hljs.highlightElement(el))})</script>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Code">
|
||||
<p class="kicker">Snippet · 运行时核心</p>
|
||||
<h2 class="h2">按一下键盘,幻灯片就跑起来了</h2>
|
||||
<pre class="card mt-m" style="padding:24px"><code class="language-javascript">// runtime.js — keyboard-driven deck
|
||||
function go(n) {
|
||||
n = Math.max(0, Math.min(total - 1, n));
|
||||
slides.forEach((s, i) => {
|
||||
s.classList.toggle('is-active', i === n);
|
||||
});
|
||||
idx = n;
|
||||
barFill.style.width = ((n + 1) / total * 100) + '%';
|
||||
history.replaceState(null, '', '#/' + (n + 1));
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'ArrowRight' || e.key === ' ') go(idx + 1);
|
||||
if (e.key === 'ArrowLeft') go(idx - 1);
|
||||
if (e.key === 't') cycleTheme();
|
||||
});</code></pre>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Comparison</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.vs{display:grid;grid-template-columns:1fr 90px 1fr;gap:28px;align-items:stretch;margin-top:30px}
|
||||
.vs .side{padding:30px}
|
||||
.vs .mid{font-size:56px;font-weight:800;color:var(--text-3);display:flex;align-items:center;justify-content:center}
|
||||
.vs .bad-side{border-top:3px solid var(--bad)}
|
||||
.vs .good-side{border-top:3px solid var(--good)}
|
||||
.vs h3{font-size:24px}
|
||||
.vs ul{padding-left:20px;font-size:15px;line-height:1.8;color:var(--text-2)}
|
||||
.vs li::marker{color:var(--bad)}
|
||||
.vs .good-side li::marker{color:var(--good)}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Comparison">
|
||||
<p class="kicker">Before vs After · 对比</p>
|
||||
<h2 class="h2">从「每次重做」到「一键起稿」</h2>
|
||||
<div class="vs">
|
||||
<div class="card bad-side side anim-fade-left" data-anim="fade-left">
|
||||
<h3>📉 过去</h3>
|
||||
<ul>
|
||||
<li>每次都要重新做封面、目录、结语</li>
|
||||
<li>颜色、字号跨 slide 不一致</li>
|
||||
<li>想换主题?手动改每一页</li>
|
||||
<li>动效全靠 transition 硬写</li>
|
||||
<li>截图导出还要一张一张截</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mid">→</div>
|
||||
<div class="card good-side side anim-fade-right" data-anim="fade-right">
|
||||
<h3>📈 现在</h3>
|
||||
<ul>
|
||||
<li>复制模板、换数据、完事</li>
|
||||
<li>所有页共享 tokens</li>
|
||||
<li>按 <b>T</b> 循环切主题</li>
|
||||
<li>25 个命名动效直接挑</li>
|
||||
<li>一条 render.sh 全部出图</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN" data-theme="minimal-white">
|
||||
<head>
|
||||
<meta charset="utf-8"><title>Cover — html-ppt</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
</head>
|
||||
<body class="single">
|
||||
<div class="deck" data-themes="minimal-white,aurora,catppuccin-mocha,tokyo-night,xiaohongshu-white,neo-brutalism" data-theme-base="../../assets/themes/">
|
||||
<section class="slide is-active" data-title="Cover">
|
||||
<div class="deck-header"><span class="eyebrow">Keynote · 2026</span><span class="eyebrow">html-ppt</span></div>
|
||||
<div class="anim-stagger-list">
|
||||
<p class="kicker">Tech Sharing · 纯干货</p>
|
||||
<h1 class="h1 anim-fade-up" data-anim="fade-up">
|
||||
设计一套<span class="gradient-text">属于你</span>的<br>HTML 演讲系统
|
||||
</h1>
|
||||
<p class="lede">从主题、版式到动效,全部由模板驱动。一行命令即可开场。</p>
|
||||
<div class="row wrap mt-l">
|
||||
<span class="pill pill-accent">24 themes</span>
|
||||
<span class="pill">30 layouts</span>
|
||||
<span class="pill">25 animations</span>
|
||||
<span class="pill">零构建</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="deck-footer"><span class="dim2">lewis · 2026-04-15</span><span class="slide-number" data-current="1" data-total="1"></span></div>
|
||||
<div class="notes">封面页口播:大家好,今天给大家带来一套开箱即用的 HTML 演讲系统。</div>
|
||||
</section>
|
||||
</div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>CTA</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/aurora.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.cta .btn{display:inline-flex;align-items:center;gap:10px;padding:20px 32px;border-radius:999px;background:var(--accent);color:#0b1024;font-weight:700;font-size:20px;box-shadow:var(--shadow-lg);text-decoration:none;border:none;cursor:pointer}
|
||||
.cta .btn.outline{background:transparent;color:var(--text-1);border:1.5px solid var(--border-strong)}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active center tc cta" data-title="CTA">
|
||||
<div style="max-width:900px">
|
||||
<p class="kicker">Call to action</p>
|
||||
<h1 class="h1 anim-rise-in" data-anim="rise-in" style="font-size:96px">
|
||||
<span class="gradient-text">动手做你的</span><br>第一份 html-ppt
|
||||
</h1>
|
||||
<p class="lede" style="margin:16px auto 30px">复制模板、换上你的内容、按 <b>T</b> 挑一个最对味的主题,讲完还能一键导出 PNG。</p>
|
||||
<div class="row" style="justify-content:center">
|
||||
<a class="btn" href="#">🚀 ./new-deck.sh my-talk</a>
|
||||
<a class="btn outline" href="#">查看 SKILL.md</a>
|
||||
</div>
|
||||
<p class="dim mt-l" style="font-size:14px">键盘: ← → 翻页 · T 主题 · A 动效 · F 全屏 · O 概览 · S 备注</p>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Diff</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.diff{font-family:var(--font-mono);font-size:14px;line-height:1.6;border-radius:var(--radius);overflow:hidden;border:1px solid var(--border)}
|
||||
.diff .ln{display:block;padding:2px 16px;white-space:pre}
|
||||
.diff .add{background:rgba(26,175,108,.12);color:var(--good)}
|
||||
.diff .del{background:rgba(224,68,90,.12);color:var(--bad)}
|
||||
.diff .ctx{color:var(--text-2)}
|
||||
.diff .hd{background:var(--surface-2);color:var(--text-3);padding:8px 16px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;border-bottom:1px solid var(--border)}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Diff">
|
||||
<p class="kicker">Before / After</p>
|
||||
<h2 class="h2">一次迁移到 tokens 后</h2>
|
||||
<div class="card diff mt-l" style="padding:0">
|
||||
<div class="hd">assets/components/card.css</div>
|
||||
<span class="ln ctx">.card {</span>
|
||||
<span class="ln del">- background: #ffffff;</span>
|
||||
<span class="ln del">- color: #0c0d10;</span>
|
||||
<span class="ln del">- border-radius: 18px;</span>
|
||||
<span class="ln del">- box-shadow: 0 10px 30px rgba(18,24,40,.08);</span>
|
||||
<span class="ln add">+ background: var(--surface);</span>
|
||||
<span class="ln add">+ color: var(--text-1);</span>
|
||||
<span class="ln add">+ border-radius: var(--radius);</span>
|
||||
<span class="ln add">+ box-shadow: var(--shadow);</span>
|
||||
<span class="ln ctx">}</span>
|
||||
</div>
|
||||
<p class="dim mt-m">24 个主题从此只需改 variables——其他 0 改动。</p>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Flow Diagram</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.flow{display:flex;align-items:center;gap:16px;margin-top:40px;max-width:1200px}
|
||||
.flow .node{flex:1;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:22px;text-align:center;box-shadow:var(--shadow);position:relative}
|
||||
.flow .node .ic{font-size:32px;margin-bottom:6px}
|
||||
.flow .node h4{font-size:16px}
|
||||
.flow .node p{font-size:12px;color:var(--text-3);margin:0}
|
||||
.flow .arr{color:var(--text-3);font-size:28px;flex-shrink:0}
|
||||
.flow .node.hl{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 18%,transparent),var(--shadow)}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Flow">
|
||||
<p class="kicker">Pipeline · 渲染管线</p>
|
||||
<h2 class="h2">从 Markdown 到 PNG,共 5 步</h2>
|
||||
<div class="flow anim-stagger-list" data-anim-target>
|
||||
<div class="node"><div class="ic">📝</div><h4>Markdown</h4><p>你的内容源</p></div>
|
||||
<div class="arr">→</div>
|
||||
<div class="node"><div class="ic">🧩</div><h4>Layouts</h4><p>选择页型</p></div>
|
||||
<div class="arr">→</div>
|
||||
<div class="node hl"><div class="ic">🎨</div><h4>Theme</h4><p>换装</p></div>
|
||||
<div class="arr">→</div>
|
||||
<div class="node"><div class="ic">🌐</div><h4>HTML</h4><p>运行时接管</p></div>
|
||||
<div class="arr">→</div>
|
||||
<div class="node"><div class="ic">📸</div><h4>PNG</h4><p>headless Chrome</p></div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Gantt</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.gantt{margin-top:24px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:24px}
|
||||
.gantt .hd{display:grid;grid-template-columns:200px repeat(12,1fr);gap:4px;font-size:12px;color:var(--text-3);text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px;padding-bottom:10px;border-bottom:1px solid var(--border)}
|
||||
.gantt .row{display:grid;grid-template-columns:200px repeat(12,1fr);gap:4px;align-items:center;height:40px}
|
||||
.gantt .lbl{font-size:14px;font-weight:500}
|
||||
.gantt .cells{grid-column:2/-1;position:relative;height:28px;background:linear-gradient(90deg,var(--surface-2) 1px,transparent 1px) 0 0/calc(100%/12) 100%}
|
||||
.gantt .bar{position:absolute;top:4px;height:20px;border-radius:6px;background:var(--grad);display:flex;align-items:center;padding:0 10px;font-size:11px;color:#fff;font-weight:600;box-shadow:var(--shadow)}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Gantt">
|
||||
<p class="kicker">Plan · Q2 甘特图</p>
|
||||
<h2 class="h2">四个月,五条线并行</h2>
|
||||
<div class="gantt">
|
||||
<div class="hd"><div>任务</div><div>W1</div><div>W2</div><div>W3</div><div>W4</div><div>W5</div><div>W6</div><div>W7</div><div>W8</div><div>W9</div><div>W10</div><div>W11</div><div>W12</div></div>
|
||||
<div class="row"><div class="lbl">主题系统 (tokens)</div><div class="cells"><div class="bar" style="left:0;width:25%">tokens + 24 themes</div></div></div>
|
||||
<div class="row"><div class="lbl">layouts 目录</div><div class="cells"><div class="bar" style="left:17%;width:33%">30 个单页模板</div></div></div>
|
||||
<div class="row"><div class="lbl">动画系统</div><div class="cells"><div class="bar" style="left:42%;width:25%">25 个命名动效</div></div></div>
|
||||
<div class="row"><div class="lbl">渲染 / CI</div><div class="cells"><div class="bar" style="left:58%;width:25%">render.sh</div></div></div>
|
||||
<div class="row"><div class="lbl">发布 & 文档</div><div class="cells"><div class="bar" style="left:75%;width:25%">v1.0</div></div></div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Image Grid</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.gg{display:grid;grid-template-columns:repeat(4,1fr);grid-auto-rows:180px;gap:14px;margin-top:24px}
|
||||
.gg .cell{border-radius:var(--radius);overflow:hidden;position:relative;box-shadow:var(--shadow)}
|
||||
.gg .cell span{position:absolute;inset:auto 0 0 0;padding:12px 14px;color:#fff;font-size:13px;font-weight:500;background:linear-gradient(transparent,rgba(0,0,0,.55))}
|
||||
.gg .c1{background:linear-gradient(135deg,#3b6cff,#7a5cff);grid-column:span 2;grid-row:span 2}
|
||||
.gg .c2{background:linear-gradient(135deg,#ff7a90,#ff2742)}
|
||||
.gg .c3{background:linear-gradient(135deg,#5ef2c6,#7aa2ff)}
|
||||
.gg .c4{background:linear-gradient(135deg,#ffd27a,#f2a341)}
|
||||
.gg .c5{background:linear-gradient(135deg,#c984ff,#ff5c8a)}
|
||||
.gg .c6{background:linear-gradient(135deg,#0e1530,#24283b)}
|
||||
.gg .c7{background:linear-gradient(135deg,#88c0d0,#5ef2c6);grid-column:span 2}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Image Grid">
|
||||
<p class="kicker">Gallery · 作品集</p>
|
||||
<h2 class="h2">一次 bento grid,六张要点图</h2>
|
||||
<div class="gg anim-stagger-list" data-anim-target>
|
||||
<div class="cell c1"><span>主视觉 · Keynote 封面</span></div>
|
||||
<div class="cell c2"><span>暖色 · Stat</span></div>
|
||||
<div class="cell c3"><span>冷色 · Flow</span></div>
|
||||
<div class="cell c4"><span>日落 · Code</span></div>
|
||||
<div class="cell c5"><span>渐变 · Quote</span></div>
|
||||
<div class="cell c6"><span>暗色 · Terminal</span></div>
|
||||
<div class="cell c7"><span>极光 · CTA</span></div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Image Hero</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.hero{position:relative;height:calc(100vh - 144px);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-lg)}
|
||||
.hero .bg{position:absolute;inset:0;background:
|
||||
radial-gradient(80% 60% at 30% 40%,#ffb38a,transparent 70%),
|
||||
radial-gradient(70% 50% at 75% 60%,#c084fc,transparent 70%),
|
||||
linear-gradient(135deg,#0b1024,#1a2238)}
|
||||
.hero .bg.kb{animation:kf-kenburns 12s ease-in-out infinite alternate}
|
||||
.hero .overlay{position:absolute;inset:0;background:linear-gradient(180deg,transparent 40%,rgba(10,12,20,.65));}
|
||||
.hero .caption{position:absolute;bottom:48px;left:56px;right:56px;color:#fff;z-index:2}
|
||||
.hero h1{font-size:72px;line-height:1;font-weight:800;letter-spacing:-.03em;margin:0}
|
||||
.hero p{font-size:20px;opacity:.85;margin:14px 0 0;max-width:60ch}
|
||||
.hero .pill{background:rgba(255,255,255,.12);color:#fff;border:1px solid rgba(255,255,255,.2)}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Image Hero" style="padding:56px">
|
||||
<div class="hero">
|
||||
<div class="bg kb"></div>
|
||||
<div class="overlay"></div>
|
||||
<div class="caption">
|
||||
<span class="pill">Cover · 04</span>
|
||||
<h1 class="mt-s anim-rise-in" data-anim="rise-in">像杂志一样的<br>封面画面感</h1>
|
||||
<p>Ken Burns 缓慢推拉 + 径向渐变 + 中灰叠加。无须真实图片,也能做出高级感。</p>
|
||||
</div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>KPI Grid</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="KPIs">
|
||||
<p class="kicker">Metrics · 关键数字</p>
|
||||
<h2 class="h2">这一季度,我们做到了什么</h2>
|
||||
<div class="grid g4 mt-l anim-stagger-list" data-anim-target>
|
||||
<div class="card"><p class="eyebrow">Revenue</p><div style="font-size:56px;font-weight:800"><span class="counter" data-to="1248">0</span>K</div><p class="dim" style="color:var(--good)">↑ 38% YoY</p></div>
|
||||
<div class="card"><p class="eyebrow">Active users</p><div style="font-size:56px;font-weight:800"><span class="counter" data-to="82">0</span>K</div><p class="dim" style="color:var(--good)">↑ 12% QoQ</p></div>
|
||||
<div class="card"><p class="eyebrow">Retention</p><div style="font-size:56px;font-weight:800"><span class="counter" data-to="74">0</span>%</div><p class="dim" style="color:var(--good)">↑ 3 pts</p></div>
|
||||
<div class="card"><p class="eyebrow">NPS</p><div style="font-size:56px;font-weight:800"><span class="counter" data-to="61">0</span></div><p class="dim" style="color:var(--warn)">→ 持平</p></div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,38 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Mindmap</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.mm{position:relative;margin:30px auto 0;max-width:1200px;height:520px}
|
||||
.mm .n{position:absolute;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:12px 18px;box-shadow:var(--shadow);font-weight:600}
|
||||
.mm .root{top:calc(50% - 34px);left:calc(50% - 100px);width:200px;padding:22px;background:var(--accent);color:#fff;border:none;text-align:center;font-size:20px;border-radius:24px}
|
||||
.mm .n.sm{font-size:13px}
|
||||
.mm svg{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
|
||||
.mm svg path{stroke:var(--border-strong);stroke-width:1.5;fill:none}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Mindmap">
|
||||
<p class="kicker">Concept map · 心智图</p>
|
||||
<h2 class="h2">html-ppt 的知识地图</h2>
|
||||
<div class="mm">
|
||||
<svg class="anim-path-draw" viewBox="0 0 1200 520" preserveAspectRatio="none">
|
||||
<path d="M600,260 C400,140 280,100 160,90"/>
|
||||
<path d="M600,260 C400,380 280,420 160,430"/>
|
||||
<path d="M600,260 C800,140 920,100 1040,90"/>
|
||||
<path d="M600,260 C800,380 920,420 1040,430"/>
|
||||
<path d="M600,260 C600,140 600,100 600,60"/>
|
||||
<path d="M600,260 C600,380 600,420 600,460"/>
|
||||
</svg>
|
||||
<div class="n root">html-ppt</div>
|
||||
<div class="n" style="top:60px;left:40px">Themes</div>
|
||||
<div class="n sm" style="top:410px;left:40px">Layouts</div>
|
||||
<div class="n sm" style="top:60px;right:40px">Animations</div>
|
||||
<div class="n sm" style="top:410px;right:40px">Runtime</div>
|
||||
<div class="n sm" style="top:30px;left:calc(50% - 50px)">Tokens</div>
|
||||
<div class="n sm" style="top:450px;left:calc(50% - 60px)">Render.sh</div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Process Steps</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:22px;margin-top:24px}
|
||||
.step{position:relative;padding:24px 26px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);box-shadow:var(--shadow)}
|
||||
.step .num{position:absolute;top:-24px;left:22px;width:48px;height:48px;border-radius:50%;background:var(--accent);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:20px;box-shadow:var(--shadow)}
|
||||
.step h4{margin:18px 0 8px;font-size:17px}
|
||||
.step p{font-size:13px;color:var(--text-2);line-height:1.6}
|
||||
.step .tag{display:inline-block;margin-top:10px;font-size:11px;padding:3px 10px;border-radius:999px;background:var(--surface-2);color:var(--text-3)}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Process">
|
||||
<p class="kicker">How-to · 四步做一个 deck</p>
|
||||
<h2 class="h2">从零到一,只需要十分钟</h2>
|
||||
<div class="steps anim-stagger-list" data-anim-target>
|
||||
<div class="step"><div class="num">1</div><h4>起稿</h4><p>运行 <code>new-deck.sh</code> 创建脚手架,默认 6 页。</p><span class="tag">~30s</span></div>
|
||||
<div class="step"><div class="num">2</div><h4>选版式</h4><p>从 <code>templates/single-page/</code> 里复制你需要的页型。</p><span class="tag">~2min</span></div>
|
||||
<div class="step"><div class="num">3</div><h4>写内容</h4><p>替换 demo 数据,保留结构。</p><span class="tag">~6min</span></div>
|
||||
<div class="step"><div class="num">4</div><h4>换主题</h4><p>按 <b>T</b> 循环看 24 个主题,挑一个定稿。</p><span class="tag">~1min</span></div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Pros / Cons</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.pc{display:grid;grid-template-columns:1fr 1fr;gap:28px;margin-top:30px}
|
||||
.pc .card h3{display:flex;align-items:center;gap:10px}
|
||||
.pc .card h3 .b{display:inline-flex;width:36px;height:36px;border-radius:10px;align-items:center;justify-content:center;font-size:20px}
|
||||
.pc .pro h3 .b{background:color-mix(in srgb,var(--good) 18%,transparent);color:var(--good)}
|
||||
.pc .con h3 .b{background:color-mix(in srgb,var(--bad) 18%,transparent);color:var(--bad)}
|
||||
.pc ul{padding-left:22px;line-height:1.8;color:var(--text-2)}
|
||||
.pc .pro{border-top:3px solid var(--good)}
|
||||
.pc .con{border-top:3px solid var(--bad)}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Pros Cons">
|
||||
<p class="kicker">Trade-offs · 诚实的取舍</p>
|
||||
<h2 class="h2">纯 HTML 演讲:好在哪里,痛在哪里</h2>
|
||||
<div class="pc">
|
||||
<div class="card pro anim-fade-up" data-anim="fade-up"><h3><span class="b">✓</span> 好处</h3>
|
||||
<ul><li>零构建:一个文件就能跑</li><li>可 diff:Git 友好,好 review</li><li>可编程:动效自由定制</li><li>可分发:URL / PDF / PNG 都行</li></ul>
|
||||
</div>
|
||||
<div class="card con anim-fade-up" data-anim="fade-up"><h3><span class="b">✗</span> 痛点</h3>
|
||||
<ul><li>协作不像 Keynote 那样实时</li><li>非程序员上手稍陡</li><li>复杂动效仍需写 JS</li><li>部分字体在离线环境缺失</li></ul>
|
||||
</div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Roadmap</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.rm{display:grid;grid-template-columns:repeat(4,1fr);gap:0;margin-top:28px;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
|
||||
.rm .col{padding:20px 22px;border-right:1px solid var(--border);background:var(--surface);position:relative}
|
||||
.rm .col:last-child{border-right:none}
|
||||
.rm .col .tag{display:inline-block;padding:3px 12px;border-radius:999px;font-size:11px;background:var(--surface-2);color:var(--text-2);margin-bottom:10px}
|
||||
.rm .col.now{background:color-mix(in srgb,var(--accent) 6%,var(--surface))}
|
||||
.rm .col.now .tag{background:var(--accent);color:#fff}
|
||||
.rm h4{font-size:15px;margin:8px 0 4px}
|
||||
.rm ul{padding-left:18px;margin:8px 0 0;font-size:13px;color:var(--text-2)}
|
||||
.rm li{margin-bottom:6px;line-height:1.5}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Roadmap">
|
||||
<p class="kicker">Roadmap · 2026</p>
|
||||
<h2 class="h2">接下来四个季度,我们会做什么</h2>
|
||||
<div class="rm">
|
||||
<div class="col now">
|
||||
<span class="tag">NOW · Q2</span>
|
||||
<h4>主题系统</h4>
|
||||
<ul><li>24 个官方主题</li><li>tokens 语义文档</li><li>T 键循环切换</li></ul>
|
||||
</div>
|
||||
<div class="col">
|
||||
<span class="tag">NEXT · Q3</span>
|
||||
<h4>导出</h4>
|
||||
<ul><li>PNG 批量</li><li>PDF 打包</li><li>小红书 3:4 切片</li></ul>
|
||||
</div>
|
||||
<div class="col">
|
||||
<span class="tag">LATER · Q4</span>
|
||||
<h4>交互</h4>
|
||||
<ul><li>Presenter 模式</li><li>Notes 同屏</li><li>遥控器配对</li></ul>
|
||||
</div>
|
||||
<div class="col">
|
||||
<span class="tag">VISION</span>
|
||||
<h4>AI 写稿</h4>
|
||||
<ul><li>从 md 自动分页</li><li>智能选版式</li><li>智能选主题</li></ul>
|
||||
</div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Section Divider</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active tc center" data-title="Section 02">
|
||||
<div style="max-width:780px;margin:0 auto">
|
||||
<p class="kicker anim-fade-down" data-anim="fade-down">Section · 02</p>
|
||||
<h1 class="h1 anim-rise-in" data-anim="rise-in" style="font-size:112px">主题与 <span class="gradient-text">Tokens</span></h1>
|
||||
<div class="divider-accent" style="margin:24px auto"></div>
|
||||
<p class="lede" style="margin:0 auto">换主题 = 换一份 CSS 变量。其他一切保持不变。</p>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Stat Highlight</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active center tc" data-title="Stat">
|
||||
<p class="kicker">Impact · 一个数字</p>
|
||||
<div style="font-size:260px;line-height:1;font-weight:900;letter-spacing:-.05em">
|
||||
<span class="counter gradient-text" data-to="92">0</span><span class="gradient-text">%</span>
|
||||
</div>
|
||||
<h3 class="mt-s">的准备时间被你省下</h3>
|
||||
<p class="lede" style="margin:16px auto 0">在 10 个真实项目中,使用 html-ppt 的平均 deck 制作时间从 4 小时降到了 20 分钟。</p>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Table</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.t{width:100%;border-collapse:collapse;font-size:16px}
|
||||
.t th,.t td{padding:14px 16px;text-align:left;border-bottom:1px solid var(--border)}
|
||||
.t th{font-size:12px;text-transform:uppercase;letter-spacing:.1em;color:var(--text-3);font-weight:600}
|
||||
.t tr:hover td{background:var(--surface-2)}
|
||||
.t td.num{font-variant-numeric:tabular-nums;text-align:right}
|
||||
.up{color:var(--good)}.dn{color:var(--bad)}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Table">
|
||||
<p class="kicker">Comparison · 数据表</p>
|
||||
<h2 class="h2">主流 HTML 演讲框架对比</h2>
|
||||
<div class="card mt-l" style="padding:4px 12px">
|
||||
<table class="t">
|
||||
<thead><tr><th>框架</th><th>学习曲线</th><th>自定义</th><th class="num">体积</th><th class="num">GitHub ⭐</th><th>适合</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><b>html-ppt</b></td><td>极低</td><td>★★★★★</td><td class="num">~80 KB</td><td class="num">—</td><td>快速出稿、换主题</td></tr>
|
||||
<tr><td>reveal.js</td><td>低</td><td>★★★★</td><td class="num">~450 KB</td><td class="num">67k</td><td>长讲座、互动</td></tr>
|
||||
<tr><td>Slidev</td><td>中</td><td>★★★★★</td><td class="num">需构建</td><td class="num">31k</td><td>开发者、技术分享</td></tr>
|
||||
<tr><td>Marp</td><td>极低</td><td>★★</td><td class="num">~10 MB</td><td class="num">13k</td><td>Markdown 出稿</td></tr>
|
||||
<tr><td>Impress.js</td><td>中</td><td>★★★</td><td class="num">~60 KB</td><td class="num">38k</td><td>3D 展示</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Terminal</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/terminal-green.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.term{font-family:var(--font-mono);font-size:16px;background:#020803;border:1px solid rgba(0,255,120,.3);border-radius:10px;padding:24px 28px;box-shadow:0 0 60px rgba(0,255,136,.08) inset}
|
||||
.term .bar{display:flex;gap:6px;margin-bottom:16px}
|
||||
.term .bar span{width:12px;height:12px;border-radius:50%;background:#222;border:1px solid rgba(0,255,136,.3)}
|
||||
.term .p{color:var(--accent)}
|
||||
.term .c{color:var(--text-1)}
|
||||
.term .o{color:var(--text-2)}
|
||||
.term .caret{display:inline-block;width:9px;height:18px;background:var(--accent);vertical-align:middle;animation:blink 1s step-end infinite}
|
||||
@keyframes blink{50%{opacity:0}}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Terminal">
|
||||
<p class="kicker">CLI · 一行命令起一个 deck</p>
|
||||
<h2 class="h2" style="color:var(--text-1)">你需要的就是一个终端</h2>
|
||||
<div class="term mt-l">
|
||||
<div class="bar"><span></span><span></span><span></span></div>
|
||||
<div><span class="p">$ </span><span class="c">./scripts/new-deck.sh graphify-talk</span></div>
|
||||
<div class="o"> ✔ created decks/graphify-talk/index.html</div>
|
||||
<div class="o"> ✔ linked theme → aurora</div>
|
||||
<div class="o"> ✔ 12 slides scaffolded from templates/single-page/*</div>
|
||||
<div style="margin-top:12px"><span class="p">$ </span><span class="c">open decks/graphify-talk/index.html</span></div>
|
||||
<div class="o"> ↗ launched in Chrome</div>
|
||||
<div style="margin-top:12px"><span class="p">$ </span><span class="c">./scripts/render.sh decks/graphify-talk/index.html</span></div>
|
||||
<div class="o"> ✔ wrote graphify-talk.png (1920×1080)</div>
|
||||
<div style="margin-top:12px"><span class="p">$ </span><span class="caret"></span></div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Thanks</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active center tc" data-title="Thanks">
|
||||
<div>
|
||||
<div class="anim-confetti-burst" style="display:inline-block;padding:40px"></div>
|
||||
<h1 class="h1 anim-fade-up" data-anim="fade-up" style="font-size:180px;line-height:1"><span class="gradient-text">Thanks</span></h1>
|
||||
<p class="lede" style="margin:18px auto 0">愿你每一次上台,都少一点紧张,多一点从容。</p>
|
||||
<div class="row mt-l" style="justify-content:center;gap:32px">
|
||||
<div class="dim"><b>lewis</b> · sudolewis@gmail.com</div>
|
||||
<div class="dim">github.com/lewis/html-ppt</div>
|
||||
<div class="dim">2026 · MIT</div>
|
||||
</div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Three Column</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Three column">
|
||||
<p class="kicker">Pillars · 三根支柱</p>
|
||||
<h2 class="h2">一个 html-ppt,三件装备</h2>
|
||||
<div class="grid g3 mt-l anim-stagger-list" data-anim-target>
|
||||
<div class="card"><div style="font-size:40px">🎨</div><h4 class="mt-s">Themes</h4><p class="dim">克制 · 编辑 · 霓虹 · 终端 …… 随场景换装。</p></div>
|
||||
<div class="card"><div style="font-size:40px">🧱</div><h4 class="mt-s">Layouts</h4><p class="dim">30 种页型,从封面到结语一次给齐。</p></div>
|
||||
<div class="card"><div style="font-size:40px">✨</div><h4 class="mt-s">Animations</h4><p class="dim">25 个命名动效,每一个都克制、每一个都上台。</p></div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Timeline</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.tl{position:relative;margin-top:40px}
|
||||
.tl::before{content:"";position:absolute;left:0;right:0;top:48px;height:2px;background:var(--border)}
|
||||
.tl .row{display:grid;grid-template-columns:repeat(5,1fr);gap:22px;align-items:start}
|
||||
.tl .item{position:relative;padding-top:80px;text-align:center}
|
||||
.tl .dot{position:absolute;top:36px;left:50%;transform:translateX(-50%);width:24px;height:24px;border-radius:50%;background:var(--accent);border:4px solid var(--bg);box-shadow:0 0 0 2px var(--accent)}
|
||||
.tl .year{font-size:14px;color:var(--text-3);letter-spacing:.12em;text-transform:uppercase;position:absolute;top:0;left:0;right:0;font-weight:600}
|
||||
.tl h4{font-size:18px}
|
||||
.tl p{font-size:13px;color:var(--text-2)}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Timeline">
|
||||
<p class="kicker">Roadmap · 时间线</p>
|
||||
<h2 class="h2">html-ppt 是怎么长大的</h2>
|
||||
<div class="tl">
|
||||
<div class="row anim-stagger-list" data-anim-target>
|
||||
<div class="item"><div class="year">2025 Q3</div><div class="dot"></div><h4>起源</h4><p>一套个人 reveal.js 模板</p></div>
|
||||
<div class="item"><div class="year">2025 Q4</div><div class="dot"></div><h4>tokens 化</h4><p>把颜色全部收进 :root</p></div>
|
||||
<div class="item"><div class="year">2026 Q1</div><div class="dot"></div><h4>Agent 接入</h4><p>开放为 AgentSkill</p></div>
|
||||
<div class="item"><div class="year">2026 Q2</div><div class="dot"></div><h4>24 themes</h4><p>从克制到霓虹一应俱全</p></div>
|
||||
<div class="item"><div class="year">2026 Q3</div><div class="dot"></div><h4>渲染管线</h4><p>headless Chrome PNG 出稿</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN" data-theme="minimal-white">
|
||||
<head>
|
||||
<meta charset="utf-8"><title>Table of Contents</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
</head>
|
||||
<body class="single">
|
||||
<div class="deck">
|
||||
<section class="slide is-active" data-title="Contents">
|
||||
<p class="eyebrow">Contents · 目录</p>
|
||||
<h2 class="h2">今天的五件事</h2>
|
||||
<div class="grid g2 mt-l anim-stagger-list" data-anim-target>
|
||||
<div class="card"><div class="row"><div class="h3 dim2" style="width:56px">01</div><div><h4>为什么需要设计系统</h4><p class="dim">从模板到 token,减少重复。</p></div></div></div>
|
||||
<div class="card"><div class="row"><div class="h3 dim2" style="width:56px">02</div><div><h4>主题与 tokens</h4><p class="dim">24 个可切换的主题,一键换装。</p></div></div></div>
|
||||
<div class="card"><div class="row"><div class="h3 dim2" style="width:56px">03</div><div><h4>版式目录</h4><p class="dim">30 种单页类型,覆盖 95% 场景。</p></div></div></div>
|
||||
<div class="card"><div class="row"><div class="h3 dim2" style="width:56px">04</div><div><h4>入场动效</h4><p class="dim">25 种命名动画,可挑可组合。</p></div></div></div>
|
||||
<div class="card" style="grid-column:span 2"><div class="row"><div class="h3 dim2" style="width:56px">05</div><div><h4>现场演示 & 问答</h4><p class="dim">打开模板就能讲。</p></div></div></div>
|
||||
</div>
|
||||
<div class="deck-footer"><span class="dim2">html-ppt</span><span>目录</span></div>
|
||||
</section>
|
||||
</div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Checklist</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
<style>
|
||||
.todo{max-width:820px;margin-top:26px}
|
||||
.todo li{list-style:none;display:flex;align-items:flex-start;gap:14px;padding:14px 18px;border-bottom:1px solid var(--border)}
|
||||
.todo li .b{flex-shrink:0;width:22px;height:22px;border:2px solid var(--border-strong);border-radius:6px;display:flex;align-items:center;justify-content:center;margin-top:2px}
|
||||
.todo li.done .b{background:var(--good);border-color:var(--good);color:#fff}
|
||||
.todo li.done .b::after{content:"✓";font-weight:900}
|
||||
.todo li.done .t{text-decoration:line-through;color:var(--text-3)}
|
||||
.todo li .t{font-size:18px}
|
||||
.todo li .tag{margin-left:auto;font-size:12px;color:var(--text-3)}
|
||||
</style>
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Checklist">
|
||||
<p class="kicker">Launch · 上线前检查清单</p>
|
||||
<h2 class="h2">发版前必过的 8 件事</h2>
|
||||
<ul class="todo anim-stagger-list" data-anim-target>
|
||||
<li class="done"><span class="b"></span><span class="t">所有 slide 在 Chrome 打开无控制台报错</span><span class="tag">#sanity</span></li>
|
||||
<li class="done"><span class="b"></span><span class="t">字体回退链路正确(Noto Sans SC)</span><span class="tag">#fonts</span></li>
|
||||
<li class="done"><span class="b"></span><span class="t">24 个主题各选一页截图比对</span><span class="tag">#themes</span></li>
|
||||
<li class="done"><span class="b"></span><span class="t">键盘导航全键通</span><span class="tag">#runtime</span></li>
|
||||
<li><span class="b"></span><span class="t">PDF 打印不跨页裁切</span><span class="tag">#print</span></li>
|
||||
<li><span class="b"></span><span class="t">render.sh 对每个 showcase 跑通</span><span class="tag">#ci</span></li>
|
||||
<li><span class="b"></span><span class="t">references/*.md 通读一遍</span><span class="tag">#docs</span></li>
|
||||
<li><span class="b"></span><span class="t">LICENSE / README 作者信息核对</span><span class="tag">#legal</span></li>
|
||||
</ul>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><title>Two Column</title>
|
||||
<link rel="stylesheet" href="../../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../../assets/base.css">
|
||||
<link rel="stylesheet" id="theme-link" href="../../assets/themes/minimal-white.css">
|
||||
<link rel="stylesheet" href="../../assets/animations/animations.css">
|
||||
</head><body class="single">
|
||||
<div class="deck"><section class="slide is-active" data-title="Two column">
|
||||
<p class="kicker">Pattern · 双栏</p>
|
||||
<h2 class="h2">概念 <span class="dim2">⟷</span> 示例</h2>
|
||||
<div class="grid g2 mt-l" style="align-items:start">
|
||||
<div class="card anim-fade-left" data-anim="fade-left">
|
||||
<h3>左栏 · 概念</h3>
|
||||
<p class="dim">一个主题 = 一组 CSS 变量。把颜色、字体、圆角、阴影全部收到 <code>:root</code> 里。</p>
|
||||
<ul class="mt-m">
|
||||
<li>— tokens 定义语义,不写具体色值</li>
|
||||
<li>— base.css 用 tokens 排版</li>
|
||||
<li>— 每个主题只改变量</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card anim-fade-right" data-anim="fade-right">
|
||||
<h3>右栏 · 示例</h3>
|
||||
<pre class="mono" style="font-size:13px;background:var(--surface-2);padding:14px;border-radius:var(--radius-sm);overflow:auto">
|
||||
:root {
|
||||
--bg: #fff;
|
||||
--text-1: #0c0d10;
|
||||
--accent: #3b6cff;
|
||||
--radius: 18px;
|
||||
}
|
||||
.card {
|
||||
background: var(--bg);
|
||||
color: var(--text-1);
|
||||
border-radius: var(--radius);
|
||||
}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</section></div>
|
||||
<script src="../../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
@@ -0,0 +1,151 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8"><title>Theme Showcase — html-ppt v2</title>
|
||||
<link rel="stylesheet" href="../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../assets/base.css">
|
||||
<link rel="stylesheet" href="../assets/animations/animations.css">
|
||||
<style>
|
||||
/* NOTE: theme isolation via <iframe srcdoc> per slide. Each slide loads base.css
|
||||
+ its OWN theme.css, so pressing → actually shows a different look. */
|
||||
html,body{background:#0b0c10;color:#e8ebf4}
|
||||
.deck{background:#0b0c10}
|
||||
.slide{padding:0;background:transparent}
|
||||
.theme-frame{
|
||||
position:absolute;inset:0;width:100%;height:100%;
|
||||
border:0;background:#fff;
|
||||
}
|
||||
.theme-chrome{
|
||||
position:absolute;top:22px;left:40px;right:40px;display:flex;justify-content:space-between;
|
||||
font-family:'JetBrains Mono',monospace;font-size:12px;color:#aab0c0;letter-spacing:.12em;
|
||||
text-transform:uppercase;z-index:20;pointer-events:none;mix-blend-mode:difference;
|
||||
}
|
||||
.theme-chrome .name{color:#fff;font-weight:700}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="deck"></div>
|
||||
|
||||
<script>
|
||||
/* 36 themes total (24 v1 + 12 v2). Each rendered in its OWN iframe so CSS is isolated. */
|
||||
const THEMES = [
|
||||
['minimal-white', '极简白 · clean restraint'],
|
||||
['editorial-serif', '杂志衬线 · high editorial'],
|
||||
['soft-pastel', '马卡龙 · soft pastel'],
|
||||
['sharp-mono', '黑白高对比 · sharp mono'],
|
||||
['arctic-cool', '冷色调 · arctic'],
|
||||
['sunset-warm', '暖色调 · sunset'],
|
||||
['catppuccin-latte', 'Catppuccin Latte'],
|
||||
['catppuccin-mocha', 'Catppuccin Mocha'],
|
||||
['dracula', 'Dracula'],
|
||||
['tokyo-night', 'Tokyo Night'],
|
||||
['nord', 'Nord · nordic cool'],
|
||||
['solarized-light', 'Solarized Light'],
|
||||
['gruvbox-dark', 'Gruvbox Dark'],
|
||||
['rose-pine', 'Rose Pine'],
|
||||
['neo-brutalism', 'Neo-Brutalism'],
|
||||
['glassmorphism', 'Glassmorphism'],
|
||||
['bauhaus', 'Bauhaus 几何原色'],
|
||||
['swiss-grid', 'Swiss Grid'],
|
||||
['terminal-green', 'Terminal Green'],
|
||||
['xiaohongshu-white', '小红书白底'],
|
||||
['rainbow-gradient', 'Rainbow Gradient'],
|
||||
['aurora', 'Aurora 极光'],
|
||||
['blueprint', 'Blueprint 蓝图'],
|
||||
['memphis-pop', 'Memphis Pop'],
|
||||
/* v2 additions */
|
||||
['cyberpunk-neon', 'Cyberpunk Neon 霓虹'],
|
||||
['y2k-chrome', 'Y2K Chrome 镜面'],
|
||||
['retro-tv', 'Retro TV CRT 扫描线'],
|
||||
['japanese-minimal', '和风极简 · 朱红'],
|
||||
['vaporwave', 'Vaporwave 蒸汽波'],
|
||||
['midcentury', 'Mid-Century Modern'],
|
||||
['corporate-clean', 'Corporate Clean 商务'],
|
||||
['academic-paper', '学术白皮书'],
|
||||
['news-broadcast', 'News Broadcast 新闻'],
|
||||
['pitch-deck-vc', 'Pitch Deck VC / YC'],
|
||||
['magazine-bold', 'Magazine Bold 大字杂志'],
|
||||
['engineering-whiteprint','Engineering Whiteprint']
|
||||
];
|
||||
|
||||
/* The demo content that each iframe will render. Uses tokens only, so it picks up
|
||||
whatever theme the iframe loads. Self-contained — no external references. */
|
||||
function demoHTML(themeName, label){
|
||||
return `<!doctype html><html><head><meta charset="utf-8">
|
||||
<link rel="stylesheet" href="../assets/fonts.css">
|
||||
<link rel="stylesheet" href="../assets/base.css">
|
||||
<link rel="stylesheet" href="../assets/themes/${themeName}.css">
|
||||
<link rel="stylesheet" href="../assets/animations/animations.css">
|
||||
<style>
|
||||
html,body{height:100%}
|
||||
.wrap{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;
|
||||
padding:72px 96px;box-sizing:border-box;background:var(--bg);color:var(--text-1);
|
||||
font-family:var(--font-sans)}
|
||||
.swatch{display:flex;gap:10px;margin-top:18px}
|
||||
.swatch div{width:44px;height:44px;border-radius:10px;border:1px solid var(--border)}
|
||||
.kpi{font-size:54px;font-weight:800;letter-spacing:-.02em}
|
||||
.mini-code{font-family:var(--font-mono);font-size:11px;background:var(--surface-2);
|
||||
padding:10px 12px;border-radius:8px;margin:6px 0 0;white-space:pre;color:var(--text-1);
|
||||
border:1px solid var(--border)}
|
||||
</style>
|
||||
</head><body><div class="wrap">
|
||||
<p class="kicker">Theme · ${themeName}</p>
|
||||
<h1 class="h1">${label}</h1>
|
||||
<p class="lede">Same demo slide, different tokens. Background, type, accent, radius, shadow all come from <code>assets/themes/${themeName}.css</code>.</p>
|
||||
<div class="grid g3 mt-l">
|
||||
<div class="card">
|
||||
<h4>Palette · 调色盘</h4>
|
||||
<p class="dim">accent / accent-2 / accent-3 / text / surface-2</p>
|
||||
<div class="swatch">
|
||||
<div style="background:var(--accent)"></div>
|
||||
<div style="background:var(--accent-2)"></div>
|
||||
<div style="background:var(--accent-3)"></div>
|
||||
<div style="background:var(--text-1)"></div>
|
||||
<div style="background:var(--surface-2)"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h4>KPI</h4>
|
||||
<div class="kpi gradient-text">2.4K</div>
|
||||
<p class="dim">上周月活 · weekly active</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h4>Code · 令牌</h4>
|
||||
<pre class="mini-code">:root {
|
||||
--accent: /* theme */;
|
||||
--radius: /* theme */;
|
||||
}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-m" style="gap:10px;flex-wrap:wrap">
|
||||
<span class="pill">#tokens</span>
|
||||
<span class="pill pill-accent">primary</span>
|
||||
<span class="pill">#radius</span>
|
||||
<span class="pill">#shadow</span>
|
||||
<span class="pill">#type</span>
|
||||
</div>
|
||||
</div></body></html>`;
|
||||
}
|
||||
|
||||
(function(){
|
||||
const deck = document.querySelector('.deck');
|
||||
THEMES.forEach((t,i)=>{
|
||||
const s = document.createElement('section');
|
||||
s.className = 'slide';
|
||||
s.setAttribute('data-title', t[0]);
|
||||
const chrome = `<div class="theme-chrome"><span class="name">${String(i+1).padStart(2,'0')} · ${t[0]}</span><span>${i+1}/${THEMES.length}</span></div>`;
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.className = 'theme-frame';
|
||||
iframe.setAttribute('loading','eager');
|
||||
// Use src via data URL for the inline demo HTML so relative paths still resolve from the templates/ dir.
|
||||
// Easier: use srcdoc but set <base href> to the templates dir so relative ../assets paths work.
|
||||
const base = `<base href="${location.href}">`;
|
||||
iframe.srcdoc = demoHTML(t[0], t[1]).replace('<head>','<head>'+base);
|
||||
s.innerHTML = chrome;
|
||||
s.appendChild(iframe);
|
||||
deck.appendChild(s);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script src="../assets/runtime.js"></script>
|
||||
</body></html>
|
||||
Reference in New Issue
Block a user