
Damncool Html Slides
- 8 installs
- 6 repo stars
- Updated April 27, 2026
- comeonzhj/damncool-slides-skill
Turns a topic, outline, or notes into a browser-ready HTML slide deck using a bundled CSS/JS suite with themes, layouts, and 3D camera transitions.
About
This skill copies a bundled cinematic-slides suite and authors deck content with its classes, themes, and data-attribute transforms instead of rebuilding a presentation engine. A developer uses it when they need an animated, browser-openable HTML slide deck from source material.
- Five body themes (solar-pop, noir-lux, cyber-acid, editorial-fire, forest-lab) and mixed layouts like cover, bento, time
- Impress-style camera navigation with per-slide 3D transforms and a Ctrl/Cmd+G overview mode
Damncool Html Slides by the numbers
- 8 all-time installs (skills.sh)
- Ranked #1,072 of 1,335 Generative Media skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/comeonzhj/damncool-slides-skill --skill damncool-html-slidesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 8 |
|---|---|
| repo stars | ★ 6 |
| Last updated | April 27, 2026 |
| Repository | comeonzhj/damncool-slides-skill ↗ |
What it does
Turns a topic, outline, or notes into a browser-ready HTML slide deck using a bundled CSS/JS suite with themes, layouts, and 3D camera transitions.
Files
Cinematic HTML Slides
Core Rule
Copy the bundled suite first, then write deck content with its classes and data attributes. Do not rebuild the presentation engine unless the user explicitly asks.
Bundled suite:
assets/cinematic-suite/index.html- starter HTML.assets/cinematic-suite/css/cinematic-slides.css- themes, layouts, icon styling, animations.assets/cinematic-suite/js/cinematic-slides.js- impress-style camera navigation, overview, random transitions, icon packs.references/authoring-patterns.md- class patterns and examples; read when composing a new deck.
Workflow
1. Create an output folder in the user-specified path. If no path is specified, create a folder in the current workspace named from the topic, such as ai-future-slides. 2. Copy all files from assets/cinematic-suite/ into that folder. 3. Edit only index.html for deck content unless the user asks for custom behavior. 4. Choose one of five body themes:
theme-solar-popfor bright product, education, optimistic tech.theme-noir-luxfor high-stakes strategy, finance, executive stories.theme-cyber-acidfor futuristic, hacker, AI, gaming.theme-editorial-firefor opinionated reports, talks, cultural topics.theme-forest-labfor science, sustainability, research, healthcare.
5. Convert the user's topic/material into a deck with a strong narrative arc. Prefer 8-16 slides unless the user specifies length. 6. Give every slide a unique transform path using data-x, data-y, data-z, data-scale, and data-rotate. Vary coordinates so navigation feels spatial. 7. Use mixed layouts: cover, split, bento, quote, metric wall, timeline, comparison, image/visual placeholder, closing. 8. Add large visual anchors on most slides: <div class="mega-icon" data-icon="..."></div> or a large emoji/icon character. 9. Avoid default Tailwind-like blue/purple/indigo palettes. Do not use #3b82f6, #6366f1, #8b5cf6, blue-purple gradients, or an indigo-dominant scheme. 10. Verify by opening index.html in a browser or serving the folder. Use arrow keys, space, mouse wheel, click, and Ctrl/Command+G for overview. O/Backspace/Escape are fallback overview shortcuts.
Authoring Contract
Write slides as:
<section class="step layout-split transition-random" data-x="1200" data-y="0" data-scale="1" data-rotate="-8">
<div class="mega-icon" data-icon="rocket"></div>
<p class="eyebrow">Market signal</p>
<h2>One sharp slide title</h2>
<p class="lede">A concise explanation grounded in the user's material.</p>
</section>Use semantic text and the suite classes. The JavaScript reads .step elements and moves the camera around the slide map, inspired by the source project's Impress/Step implementation: each slide owns a 3D transform, navigation moves the canvas to the inverse transform, and overview calculates a scale that fits the map. Ctrl/Command+G opens a global view of all slides; clicking any slide in that view jumps into it.
Content Guidance
- Make slides content-rich, not decorative placeholders.
- Prefer concrete facts, named examples, timelines, contrasts, and metrics from the user's material.
- When source material is thin, make reasonable assumptions and label uncertain claims as framing, not facts.
- Keep slide text scannable: title plus 2-5 concise blocks is usually enough.
- Use English or Chinese to match the user.
Deliverable
Return the path to index.html. Mention the chosen theme and the main controls only briefly.
interface:
display_name: "Cinematic HTML Slides"
short_description: "Browser-ready cinematic slide decks"
default_prompt: "Use $cinematic-html-slides to create a bold browser-ready HTML deck about [topic]."
policy:
allow_implicit_invocation: true
:root {
--bg: #fff6d8;
--fg: #14110f;
--muted: #5f574c;
--panel: rgba(255, 255, 255, 0.72);
--line: rgba(20, 17, 15, 0.18);
--accent: #ff4f2e;
--accent-2: #00a896;
--accent-3: #ffc400;
--shadow: 0 24px 80px rgba(20, 17, 15, 0.22);
--font-display: Impact, Haettenschweiler, "Arial Black", sans-serif;
--font-body: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
color-scheme: light;
}
* { box-sizing: border-box; }
html,
body {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
body {
background:
radial-gradient(circle at 12% 18%, color-mix(in srgb, var(--accent-3) 42%, transparent), transparent 28rem),
linear-gradient(135deg, var(--bg), color-mix(in srgb, var(--bg) 82%, var(--accent-2)));
color: var(--fg);
font-family: var(--font-body);
}
.theme-solar-pop {
--bg: #fff2b8;
--fg: #15110c;
--muted: #655a45;
--panel: rgba(255, 252, 231, 0.76);
--line: rgba(21, 17, 12, 0.18);
--accent: #ff4f2e;
--accent-2: #008f7a;
--accent-3: #ffbf00;
}
.theme-noir-lux {
--bg: #080706;
--fg: #fff6df;
--muted: #cfbfa2;
--panel: rgba(28, 24, 19, 0.82);
--line: rgba(255, 246, 223, 0.2);
--accent: #d7a73f;
--accent-2: #b91c1c;
--accent-3: #f4e2b6;
--shadow: 0 30px 90px rgba(0, 0, 0, 0.55);
color-scheme: dark;
}
.theme-cyber-acid {
--bg: #0c0f09;
--fg: #f4ffe8;
--muted: #b7c7a0;
--panel: rgba(12, 20, 10, 0.78);
--line: rgba(215, 255, 87, 0.24);
--accent: #d7ff37;
--accent-2: #ff3d81;
--accent-3: #ff8a00;
--font-display: "Arial Black", Impact, sans-serif;
color-scheme: dark;
}
.theme-editorial-fire {
--bg: #f8ead2;
--fg: #1f1712;
--muted: #725b47;
--panel: rgba(255, 248, 236, 0.8);
--line: rgba(31, 23, 18, 0.2);
--accent: #c81e1e;
--accent-2: #d97706;
--accent-3: #111111;
--font-display: Georgia, "Times New Roman", serif;
}
.theme-forest-lab {
--bg: #eef4df;
--fg: #10251a;
--muted: #4d674f;
--panel: rgba(249, 252, 239, 0.78);
--line: rgba(16, 37, 26, 0.18);
--accent: #2f7d32;
--accent-2: #cc6b49;
--accent-3: #9fd356;
}
.deck {
position: absolute;
inset: 0;
left: 50%;
top: 50%;
transform-origin: left top;
transform-style: preserve-3d;
perspective: 1000px;
transition: transform 900ms cubic-bezier(.2, .85, .2, 1), perspective 900ms cubic-bezier(.2, .85, .2, 1);
}
.canvas {
position: absolute;
transform-origin: left top;
transform-style: preserve-3d;
transition: transform 900ms cubic-bezier(.2, .85, .2, 1);
}
.step {
position: absolute;
width: min(1120px, 88vw);
min-height: min(680px, 78vh);
padding: clamp(42px, 5vw, 76px);
border: 1px solid var(--line);
border-radius: 8px;
background: var(--panel);
box-shadow: var(--shadow);
transform-style: preserve-3d;
overflow: hidden;
opacity: 0.22;
filter: saturate(0.75);
transition: opacity 450ms ease, filter 450ms ease, box-shadow 450ms ease;
backdrop-filter: blur(18px);
}
.step::before {
content: "";
position: absolute;
inset: 0;
pointer-events: none;
background:
linear-gradient(90deg, transparent 0 96%, color-mix(in srgb, var(--accent) 30%, transparent) 96% 97%, transparent 97%),
linear-gradient(0deg, transparent 0 94%, color-mix(in srgb, var(--accent-2) 24%, transparent) 94% 95%, transparent 95%);
background-size: 64px 64px;
opacity: 0.18;
}
.step.active {
opacity: 1;
filter: saturate(1);
z-index: 10;
}
.step.overview {
opacity: 1;
filter: saturate(1);
cursor: pointer;
}
h1,
h2,
h3 {
margin: 0;
font-family: var(--font-display);
line-height: 0.92;
letter-spacing: 0;
text-wrap: balance;
}
h1 { font-size: clamp(74px, 10vw, 156px); max-width: 11ch; }
h2 { font-size: clamp(54px, 7vw, 108px); max-width: 12ch; }
h3 { font-size: clamp(34px, 4vw, 58px); }
p { margin: 0; }
.eyebrow {
display: inline-flex;
align-items: center;
width: fit-content;
margin-bottom: 22px;
padding: 8px 12px;
border: 1px solid var(--line);
border-radius: 999px;
background: color-mix(in srgb, var(--accent) 14%, transparent);
color: var(--fg);
font-size: 13px;
font-weight: 800;
letter-spacing: 0;
text-transform: uppercase;
}
.lede {
max-width: 760px;
margin-top: 28px;
color: var(--muted);
font-size: clamp(22px, 2.3vw, 34px);
line-height: 1.18;
font-weight: 650;
}
.mega-icon {
font-size: clamp(96px, 15vw, 220px);
line-height: 0.85;
color: var(--accent);
text-shadow: 10px 10px 0 color-mix(in srgb, var(--accent-2) 36%, transparent);
}
.layout-cover,
.layout-close {
display: grid;
align-content: center;
justify-items: start;
}
.layout-cover .mega-icon,
.layout-close .mega-icon {
position: absolute;
right: clamp(32px, 6vw, 90px);
bottom: clamp(24px, 4vw, 58px);
opacity: 0.9;
}
.layout-split {
display: grid;
grid-template-columns: minmax(0, 1.05fr) minmax(320px, 0.95fr);
gap: clamp(28px, 5vw, 72px);
align-items: center;
}
.layout-bento,
.layout-stack,
.layout-metrics,
.layout-comparison,
.layout-timeline,
.layout-radar {
display: grid;
gap: 28px;
align-content: center;
}
.card-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 18px;
margin-top: 22px;
}
.card,
.visual-frame,
.callout,
.event,
.compare-panel {
position: relative;
border: 1px solid var(--line);
border-radius: 8px;
background: color-mix(in srgb, var(--panel) 82%, var(--accent-3));
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.12);
}
.card {
min-height: 180px;
padding: 24px;
display: grid;
align-content: space-between;
}
.card strong {
font-size: 30px;
line-height: 1;
}
.card span,
.event span,
.compare-panel p {
color: var(--muted);
font-size: 20px;
line-height: 1.25;
}
.visual-frame {
min-height: 420px;
display: grid;
place-items: center;
overflow: hidden;
}
.badge-row {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 32px;
}
.badge {
padding: 9px 13px;
border-radius: 999px;
border: 1px solid var(--line);
background: color-mix(in srgb, var(--fg) 8%, transparent);
font-weight: 800;
}
.metric-row,
.compare-grid,
.timeline {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 18px;
}
.metric {
font-family: var(--font-display);
font-size: clamp(64px, 9vw, 128px);
line-height: 0.9;
color: var(--accent);
}
.metric-label {
margin-top: 12px;
color: var(--muted);
font-size: 22px;
font-weight: 750;
}
.event,
.compare-panel {
padding: 24px;
}
.event strong,
.compare-panel strong {
display: block;
margin-bottom: 12px;
font-size: 28px;
}
.callout {
padding: 26px 30px;
border-left: 10px solid var(--accent);
font-size: clamp(28px, 3.4vw, 48px);
line-height: 1.05;
font-weight: 900;
}
.ticker {
white-space: nowrap;
overflow: hidden;
}
.ticker > span {
display: inline-block;
padding-left: 100%;
animation: ticker 18s linear infinite;
}
.kinetic { animation: kinetic 5s ease-in-out infinite alternate; }
.glow-pulse { animation: glowPulse 2.2s ease-in-out infinite; }
.pop-in { animation: popIn 700ms cubic-bezier(.2, .9, .2, 1) both; }
.slide-up { animation: slideUp 700ms cubic-bezier(.2, .9, .2, 1) both; }
.tilt-card { transition: transform 280ms ease; }
.tilt-card:hover { transform: rotate(-2deg) translateY(-8px); }
.hud {
position: fixed;
right: 18px;
bottom: 16px;
z-index: 50;
display: flex;
gap: 12px;
align-items: center;
padding: 10px 12px;
border: 1px solid var(--line);
border-radius: 999px;
background: color-mix(in srgb, var(--panel) 86%, transparent);
color: var(--muted);
font-size: 12px;
font-weight: 800;
backdrop-filter: blur(12px);
}
body.transition-swoop .canvas { transition-timing-function: cubic-bezier(.13, .93, .17, 1); }
body.transition-spin .canvas { transition-duration: 1100ms; }
body.transition-dive .deck,
body.transition-dive .canvas { transition-duration: 1200ms; }
body.transition-snap .deck,
body.transition-snap .canvas { transition-duration: 520ms; transition-timing-function: cubic-bezier(.7, 0, .2, 1); }
body.transition-float .deck,
body.transition-float .canvas { transition-duration: 1500ms; transition-timing-function: cubic-bezier(.2, .75, .2, 1); }
body.transition-warp .canvas { transition-timing-function: cubic-bezier(.8, -.25, .16, 1.25); }
@keyframes kinetic {
from { transform: translate3d(0, 0, 0) rotate(-4deg); }
to { transform: translate3d(16px, -18px, 80px) rotate(5deg); }
}
@keyframes glowPulse {
0%, 100% { filter: drop-shadow(0 0 0 color-mix(in srgb, var(--accent) 0%, transparent)); }
50% { filter: drop-shadow(0 0 28px color-mix(in srgb, var(--accent) 70%, transparent)); }
}
@keyframes popIn {
from { opacity: 0; transform: scale(.9) translateY(24px); }
to { opacity: 1; transform: scale(1) translateY(0); }
}
@keyframes slideUp {
from { opacity: 0; transform: translateY(38px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes ticker {
to { transform: translateX(-100%); }
}
@media (max-width: 760px) {
.step {
width: 92vw;
min-height: 78vh;
padding: 34px;
}
.layout-split,
.card-grid,
.metric-row,
.compare-grid,
.timeline {
grid-template-columns: 1fr;
}
h1 { font-size: 64px; }
h2 { font-size: 48px; }
.lede { font-size: 22px; }
.visual-frame { min-height: 260px; }
.hud { left: 12px; right: 12px; justify-content: space-between; }
}
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Cinematic HTML Slides</title>
<link rel="stylesheet" href="./css/cinematic-slides.css">
</head>
<body class="theme-solar-pop">
<main id="deck" class="deck" aria-live="polite">
<div id="canvas" class="canvas">
<section class="step layout-cover" data-x="0" data-y="0" data-scale="1" data-transition="random">
<div class="mega-icon kinetic" data-icon="spark"></div>
<p class="eyebrow">Cinematic deck</p>
<h1>Replace With Your Topic</h1>
<p class="lede">Write a sharp promise for the audience. Keep it concrete and visual.</p>
<div class="badge-row">
<span class="badge">Spatial</span>
<span class="badge">Animated</span>
<span class="badge">Browser-ready</span>
</div>
</section>
<section class="step layout-split" data-x="1300" data-y="-200" data-z="-180" data-scale="0.95" data-rotate="8" data-transition="swoop">
<div>
<p class="eyebrow">Signal</p>
<h2>Turn the first major idea into a strong claim</h2>
<p class="lede">Use the user's notes, source material, or topic to build a concise narrative.</p>
</div>
<div class="visual-frame tilt-card">
<div class="mega-icon" data-icon="rocket"></div>
</div>
</section>
<section class="step layout-bento" data-x="2600" data-y="420" data-z="220" data-scale="1.08" data-rotate="-10" data-transition="dive">
<p class="eyebrow">Three-part structure</p>
<h2>Mix layouts on every few slides</h2>
<div class="card-grid">
<article class="card pop-in"><strong>Context</strong><span>What changed?</span></article>
<article class="card pop-in"><strong>Tension</strong><span>Why does it matter?</span></article>
<article class="card pop-in"><strong>Move</strong><span>What should happen next?</span></article>
</div>
</section>
<section class="step layout-close" data-x="1300" data-y="1500" data-scale="1" data-rotate="16" data-transition="spin">
<div class="mega-icon glow-pulse" data-icon="target"></div>
<p class="eyebrow">Final frame</p>
<h2>End with one memorable sentence</h2>
</section>
</div>
</main>
<div class="hud" aria-hidden="true">
<span id="slide-count">1 / 1</span>
<span>Space / Arrows / Wheel / O</span>
</div>
<script src="./js/cinematic-slides.js"></script>
</body>
</html>
(function () {
const deck = document.getElementById("deck");
const canvas = document.getElementById("canvas");
const steps = Array.from(document.querySelectorAll(".step"));
const count = document.getElementById("slide-count");
const transitionNames = ["swoop", "spin", "dive", "snap", "float", "warp"];
const icons = {
rocket: "🚀",
fire: "🔥",
spark: "✦",
brain: "🧠",
eye: "◉",
map: "🗺",
shield: "⬟",
bolt: "⚡",
seed: "🌱",
gem: "◆",
target: "◎",
wave: "≋",
lab: "⚗",
magnet: "⊓",
compass: "✺",
sun: "☀",
moon: "☾",
star: "★",
ring: "◌",
crosshair: "⌖",
node: "⌬",
signal: "≋",
pulse: "〰",
delta: "△",
infinity: "∞"
};
let activeIndex = 0;
let overviewOpen = false;
function numberAttr(node, name, fallback) {
const raw = node.dataset[name];
const value = Number(raw);
return Number.isFinite(value) ? value : fallback;
}
function applyStepTransforms() {
steps.forEach((step) => {
const x = numberAttr(step, "x", 0);
const y = numberAttr(step, "y", 0);
const z = numberAttr(step, "z", 0);
const scale = numberAttr(step, "scale", 1);
const rotate = numberAttr(step, "rotate", 0);
step.style.transform = `translate(-50%, -50%) translate3d(${x}px, ${y}px, ${z}px) scale(${scale}) rotate(${rotate}deg)`;
});
}
function hydrateIcons() {
document.querySelectorAll(".mega-icon[data-icon]").forEach((node) => {
const key = node.dataset.icon;
if (!node.textContent.trim() && icons[key]) node.textContent = icons[key];
});
window.CinematicSlides = { icons, goto, next, prev, overview };
}
function setTransition(step) {
const requested = step.dataset.transition || "random";
const name = requested === "random"
? transitionNames[Math.floor(Math.random() * transitionNames.length)]
: requested;
document.body.classList.remove(...transitionNames.map((item) => `transition-${item}`));
document.body.classList.add(`transition-${name}`);
}
function setActiveClasses() {
steps.forEach((step, index) => {
step.classList.toggle("active", index === activeIndex && !overviewOpen);
step.classList.toggle("overview", overviewOpen);
step.setAttribute("aria-hidden", overviewOpen ? "false" : String(index !== activeIndex));
});
if (count) count.textContent = `${activeIndex + 1} / ${steps.length}`;
}
function goto(index) {
if (!steps.length) return;
activeIndex = Math.max(0, Math.min(index, steps.length - 1));
overviewOpen = false;
const step = steps[activeIndex];
const x = numberAttr(step, "x", 0);
const y = numberAttr(step, "y", 0);
const z = numberAttr(step, "z", 0);
const scale = numberAttr(step, "scale", 1);
const rotate = numberAttr(step, "rotate", 0);
setTransition(step);
setActiveClasses();
deck.style.transform = `scale(${1 / scale})`;
deck.style.perspective = `${Math.max(420, scale * 1000)}px`;
canvas.style.transform = `rotate(${-rotate}deg) translate3d(${-x}px, ${-y}px, ${-z}px)`;
history.replaceState(null, "", `#${activeIndex + 1}`);
}
function next() {
goto(Math.min(activeIndex + 1, steps.length - 1));
}
function prev() {
goto(Math.max(activeIndex - 1, 0));
}
function overview() {
if (!steps.length) return;
overviewOpen = true;
const points = steps.map((step) => ({
x: numberAttr(step, "x", 0),
y: numberAttr(step, "y", 0)
}));
const xs = points.map((point) => point.x);
const ys = points.map((point) => point.y);
const minX = Math.min(...xs);
const maxX = Math.max(...xs);
const minY = Math.min(...ys);
const maxY = Math.max(...ys);
const x = (minX + maxX) / 2;
const y = (minY + maxY) / 2;
const scaleX = (maxX - minX + window.innerWidth) / window.innerWidth;
const scaleY = (maxY - minY + window.innerHeight) / window.innerHeight;
const scale = Math.max(1, scaleX, scaleY) * 1.05;
document.body.classList.remove(...transitionNames.map((item) => `transition-${item}`));
document.body.classList.add("transition-float");
setActiveClasses();
deck.style.transform = `scale(${1 / scale})`;
deck.style.perspective = `${Math.max(800, scale * 1000)}px`;
canvas.style.transform = `translate3d(${-x}px, ${-y}px, 0)`;
}
function fromHash() {
const hashIndex = Number(window.location.hash.replace("#", "")) - 1;
return Number.isFinite(hashIndex) ? hashIndex : 0;
}
function bindEvents() {
window.addEventListener("keydown", (event) => {
const key = event.key.toLowerCase();
if ((event.ctrlKey || event.metaKey) && key === "g") {
event.preventDefault();
overview();
} else if (["arrowright", "arrowdown", " ", "pagedown", "tab"].includes(key)) {
event.preventDefault();
next();
} else if (["arrowleft", "arrowup", "pageup"].includes(key)) {
event.preventDefault();
prev();
} else if (["backspace", "escape", "o"].includes(key)) {
event.preventDefault();
overview();
} else if (key === "home") {
event.preventDefault();
goto(0);
} else if (key === "end") {
event.preventDefault();
goto(steps.length - 1);
}
});
window.addEventListener("wheel", (event) => {
if (Math.abs(event.deltaY) < 12) return;
event.preventDefault();
event.deltaY > 0 ? next() : prev();
}, { passive: false });
steps.forEach((step, index) => {
step.addEventListener("click", () => {
if (overviewOpen) goto(index);
else if (index === activeIndex) next();
else goto(index);
});
});
window.addEventListener("resize", () => {
overviewOpen ? overview() : goto(activeIndex);
});
}
applyStepTransforms();
hydrateIcons();
bindEvents();
goto(fromHash());
})();
Authoring Patterns
Spatial Model
Each slide is a .step. The deck engine places steps in a large 3D canvas and navigates by transforming the canvas around the active step.
Useful attributes:
data-x,data-y,data-z: slide position.data-scale: camera scale for the active slide.data-rotate: 2D rotation in degrees.data-transition:random,swoop,spin,dive,snap,float, orwarp.
Controls: arrows, space, wheel, and click move through slides. Ctrl/Command+G opens the global overview of all slides; click a slide while in overview to jump to it. O, Backspace, and Escape also open overview.
Use a path instead of a row:
<section class="step layout-cover" data-x="0" data-y="0" data-scale="1"></section>
<section class="step layout-bento" data-x="1300" data-y="-300" data-z="-200" data-rotate="7"></section>
<section class="step layout-quote" data-x="2500" data-y="400" data-scale="0.85" data-rotate="-12"></section>
<section class="step layout-metrics" data-x="1200" data-y="1300" data-z="300" data-scale="1.15" data-rotate="18"></section>Layout Classes
layout-cover: big centered title.layout-split: two-column narrative + visual.layout-bento: dense cards.layout-quote: oversized quotation or thesis.layout-metrics: large numbers.layout-timeline: connected sequence.layout-comparison: two to three contrast panels.layout-stack: vertical argument.layout-radar: centered object with orbiting points.layout-close: final statement.
Content Components
eyebrow: short context label.lede: larger support copy.mega-icon: large icon; setdata-icon.badge-row,badge: compact tags.card-grid,card: grouped details.metric,metric-label: number and label.timeline,event: sequence.callout: highlighted claim.visual-frame: framed image/diagram placeholder.
Built-In Icon Keys
The JS fills empty .mega-icon[data-icon] nodes.
Emoji-style: rocket, fire, spark, brain, eye, map, shield, bolt, seed, gem, target, wave, lab, magnet, compass.
Symbol-style: sun, moon, star, ring, crosshair, node, signal, pulse, delta, infinity.
If no key fits, put a direct emoji or character inside .mega-icon.
Animation Classes
Add to inner elements:
kinetic: subtle floating movement.pop-in: entry scale.slide-up: entry movement.glow-pulse: pulsing emphasis.ticker: horizontal text stream.tilt-card: hover tilt.orbit-field: rotating decorative icon cluster.
Five Theme Choices
theme-solar-pop: amber, coral, teal, charcoal. Energetic and broad.theme-noir-lux: black, bone, gold, crimson. Executive and dramatic.theme-cyber-acid: black, acid green, hot pink, orange. Futuristic and intense.theme-editorial-fire: paper, ink, red, ochre. Opinionated and magazine-like.theme-forest-lab: deep green, mint, clay, cream. Research and nature.
Do not add blue-purple, indigo, or default Tailwind gradient colors.