stagecraft 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT.md +792 -0
- package/LICENSE +21 -0
- package/README.md +210 -0
- package/bin/cli.js +51 -0
- package/bin/export.js +137 -0
- package/bin/init.js +52 -0
- package/bin/lib/edit-ops.js +405 -0
- package/bin/serve.js +278 -0
- package/dist/stagecraft.bundle.css +4443 -0
- package/dist/stagecraft.bundle.js +7621 -0
- package/dist/themes/brand.bundle.css +5262 -0
- package/dist/themes/neon.bundle.css +5289 -0
- package/dist/themes/paper.bundle.css +5276 -0
- package/dist/themes/phosphor.bundle.css +4443 -0
- package/dist/themes/shopware.bundle.css +5850 -0
- package/examples/closing-card.js +74 -0
- package/examples/orchestration-graph.js +156 -0
- package/examples/terminal-log.js +109 -0
- package/examples/token-stream.js +96 -0
- package/examples/whoami.js +90 -0
- package/package.json +41 -0
- package/src/components/activity-list.js +75 -0
- package/src/components/agenda.js +79 -0
- package/src/components/bar-chart.js +162 -0
- package/src/components/before-after.js +135 -0
- package/src/components/bento.js +73 -0
- package/src/components/big-number.js +87 -0
- package/src/components/callout.js +75 -0
- package/src/components/checklist.js +81 -0
- package/src/components/code-block.js +141 -0
- package/src/components/code-diff.js +98 -0
- package/src/components/compare.js +85 -0
- package/src/components/counter.js +80 -0
- package/src/components/cta.js +69 -0
- package/src/components/cycle.js +146 -0
- package/src/components/definition.js +96 -0
- package/src/components/donut-chart.js +179 -0
- package/src/components/full-image.js +82 -0
- package/src/components/funnel.js +111 -0
- package/src/components/gauge.js +147 -0
- package/src/components/heatmap.js +141 -0
- package/src/components/image-grid.js +80 -0
- package/src/components/image-text.js +96 -0
- package/src/components/kinetic-text.js +72 -0
- package/src/components/kpi.js +106 -0
- package/src/components/line-chart.js +215 -0
- package/src/components/manifesto.js +104 -0
- package/src/components/marquee.js +63 -0
- package/src/components/matrix2x2.js +151 -0
- package/src/components/pillars.js +80 -0
- package/src/components/pricing.js +90 -0
- package/src/components/process-flow.js +133 -0
- package/src/components/progress.js +136 -0
- package/src/components/punchline.js +82 -0
- package/src/components/pyramid.js +107 -0
- package/src/components/qanda.js +60 -0
- package/src/components/quote.js +70 -0
- package/src/components/roadmap.js +130 -0
- package/src/components/section-card.js +45 -0
- package/src/components/shift-arrow.js +41 -0
- package/src/components/spark-line.js +147 -0
- package/src/components/spotlight.js +85 -0
- package/src/components/statement.js +106 -0
- package/src/components/stats.js +91 -0
- package/src/components/steps.js +83 -0
- package/src/components/swot.js +110 -0
- package/src/components/team-grid.js +87 -0
- package/src/components/testimonial.js +99 -0
- package/src/components/timeline.js +91 -0
- package/src/components/tip.js +63 -0
- package/src/components/venn.js +198 -0
- package/src/edit-mode.js +1256 -0
- package/src/engine.js +823 -0
- package/src/helpers.js +169 -0
- package/src/transitions.js +101 -0
- package/starter/index.html +40 -0
- package/starter/slides/00-title.js +12 -0
- package/starter/stagecraft.config.js +8 -0
- package/themes/brand/base.css +4 -0
- package/themes/brand/components-business.css +173 -0
- package/themes/brand/components-chart.css +65 -0
- package/themes/brand/components-content.css +126 -0
- package/themes/brand/components-data.css +162 -0
- package/themes/brand/components-diagram.css +115 -0
- package/themes/brand/components-layout.css +112 -0
- package/themes/brand/components.css +46 -0
- package/themes/brand/manifest.json +20 -0
- package/themes/brand/tokens.css +20 -0
- package/themes/brand/transitions.css +4 -0
- package/themes/neon/base.css +10 -0
- package/themes/neon/components-business.css +189 -0
- package/themes/neon/components-chart.css +70 -0
- package/themes/neon/components-content.css +112 -0
- package/themes/neon/components-data.css +160 -0
- package/themes/neon/components-diagram.css +109 -0
- package/themes/neon/components-layout.css +87 -0
- package/themes/neon/components.css +87 -0
- package/themes/neon/manifest.json +21 -0
- package/themes/neon/tokens.css +17 -0
- package/themes/neon/transitions.css +13 -0
- package/themes/paper/base.css +9 -0
- package/themes/paper/components-business.css +196 -0
- package/themes/paper/components-chart.css +74 -0
- package/themes/paper/components-content.css +108 -0
- package/themes/paper/components-data.css +168 -0
- package/themes/paper/components-diagram.css +89 -0
- package/themes/paper/components-layout.css +105 -0
- package/themes/paper/components.css +60 -0
- package/themes/paper/manifest.json +10 -0
- package/themes/paper/tokens.css +21 -0
- package/themes/paper/transitions.css +11 -0
- package/themes/phosphor/base.css +511 -0
- package/themes/phosphor/components-business.css +818 -0
- package/themes/phosphor/components-chart.css +415 -0
- package/themes/phosphor/components-content.css +530 -0
- package/themes/phosphor/components-data.css +824 -0
- package/themes/phosphor/components-diagram.css +427 -0
- package/themes/phosphor/components-layout.css +450 -0
- package/themes/phosphor/components.css +223 -0
- package/themes/phosphor/manifest.json +11 -0
- package/themes/phosphor/tokens.css +17 -0
- package/themes/phosphor/transitions.css +213 -0
- package/themes/shopware/base.css +94 -0
- package/themes/shopware/components-business.css +344 -0
- package/themes/shopware/components-chart.css +121 -0
- package/themes/shopware/components-content.css +169 -0
- package/themes/shopware/components-data.css +219 -0
- package/themes/shopware/components-diagram.css +129 -0
- package/themes/shopware/components-layout.css +166 -0
- package/themes/shopware/components.css +83 -0
- package/themes/shopware/manifest.json +21 -0
- package/themes/shopware/tokens.css +68 -0
- package/themes/shopware/transitions.css +22 -0
package/src/helpers.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Stagecraft — Layer 1 primitives.
|
|
5
|
+
*
|
|
6
|
+
* Small composable utilities every slide can use. Kept tiny on purpose:
|
|
7
|
+
* an agent should be able to read any one in 30 seconds.
|
|
8
|
+
*
|
|
9
|
+
* All helpers attach to the global `Stage` namespace.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
(function (root) {
|
|
13
|
+
const Stage = root.Stage = root.Stage || {};
|
|
14
|
+
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// prefersReducedMotion()
|
|
17
|
+
// Whether the OS user has requested reduced motion. JS animations
|
|
18
|
+
// (typewriter, count-up, particle emit, stagger, etc.) should consult
|
|
19
|
+
// this and shortcut to the final state.
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
Stage.prefersReducedMotion = function () {
|
|
22
|
+
return typeof matchMedia !== 'undefined' &&
|
|
23
|
+
matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// staggerIn(nodes, step, initial)
|
|
28
|
+
// Fade-in nodes one after another by adding `.in` class. Pairs with
|
|
29
|
+
// `.stagger > * { opacity: 0; transform: translateY(12px); transition: ... }`
|
|
30
|
+
// and `.stagger > *.in { opacity: 1; transform: translateY(0); }` in theme CSS.
|
|
31
|
+
// Reduced motion: snap all in at once.
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
Stage.staggerIn = function (nodes, step = 200, initial = 100) {
|
|
34
|
+
if (Stage.prefersReducedMotion()) {
|
|
35
|
+
nodes.forEach(n => n.classList.add('in'));
|
|
36
|
+
return () => {};
|
|
37
|
+
}
|
|
38
|
+
const timers = [];
|
|
39
|
+
nodes.forEach((n, i) => {
|
|
40
|
+
timers.push(setTimeout(() => n.classList.add('in'), initial + i * step));
|
|
41
|
+
});
|
|
42
|
+
return () => timers.forEach(clearTimeout);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// emitParticle(parent, x1, y1, x2, y2, duration)
|
|
47
|
+
// SVG particle traveling between two points with smooth-step easing.
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
Stage.emitParticle = function (parent, x1, y1, x2, y2, duration = 800) {
|
|
50
|
+
if (Stage.prefersReducedMotion()) {
|
|
51
|
+
// Skip the particle entirely in reduced-motion mode.
|
|
52
|
+
return () => {};
|
|
53
|
+
}
|
|
54
|
+
const NS = 'http://www.w3.org/2000/svg';
|
|
55
|
+
const c = document.createElementNS(NS, 'circle');
|
|
56
|
+
c.setAttribute('class', 'particle');
|
|
57
|
+
c.setAttribute('r', 3.5);
|
|
58
|
+
c.setAttribute('cx', x1);
|
|
59
|
+
c.setAttribute('cy', y1);
|
|
60
|
+
parent.appendChild(c);
|
|
61
|
+
const start = performance.now();
|
|
62
|
+
let rafId;
|
|
63
|
+
function step(now) {
|
|
64
|
+
const t = Math.min(1, (now - start) / duration);
|
|
65
|
+
const eased = t * t * (3 - 2 * t);
|
|
66
|
+
const x = x1 + (x2 - x1) * eased;
|
|
67
|
+
const y = y1 + (y2 - y1) * eased;
|
|
68
|
+
c.setAttribute('cx', x);
|
|
69
|
+
c.setAttribute('cy', y);
|
|
70
|
+
c.setAttribute('opacity', 1 - t * 0.3);
|
|
71
|
+
if (t < 1) rafId = requestAnimationFrame(step);
|
|
72
|
+
else c.remove();
|
|
73
|
+
}
|
|
74
|
+
rafId = requestAnimationFrame(step);
|
|
75
|
+
return () => { cancelAnimationFrame(rafId); c.remove(); };
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// typewriter(el, text, opts)
|
|
80
|
+
// Character-by-character text reveal. Returns cleanup.
|
|
81
|
+
// opts: { speed: ms per char, jitter: ms random extra, onDone: fn }
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
Stage.typewriter = function (el, text, opts = {}) {
|
|
84
|
+
if (Stage.prefersReducedMotion()) {
|
|
85
|
+
el.textContent = text;
|
|
86
|
+
opts.onDone?.();
|
|
87
|
+
return () => {};
|
|
88
|
+
}
|
|
89
|
+
const speed = opts.speed ?? 50;
|
|
90
|
+
const jitter = opts.jitter ?? 30;
|
|
91
|
+
el.textContent = '';
|
|
92
|
+
let i = 0;
|
|
93
|
+
let cancelled = false;
|
|
94
|
+
const timers = [];
|
|
95
|
+
function tick() {
|
|
96
|
+
if (cancelled) return;
|
|
97
|
+
if (i >= text.length) { opts.onDone?.(); return; }
|
|
98
|
+
el.textContent += text[i++];
|
|
99
|
+
timers.push(setTimeout(tick, speed + Math.random() * jitter));
|
|
100
|
+
}
|
|
101
|
+
timers.push(setTimeout(tick, opts.initial ?? 0));
|
|
102
|
+
return () => { cancelled = true; timers.forEach(clearTimeout); };
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
// revealByDataStep(el, step)
|
|
107
|
+
// Toggle a `.shown` class on `[data-step="n"]` elements where n <= step.
|
|
108
|
+
// Designed to be passed directly as a slide's `onStep` for trivial reveals.
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
Stage.revealByDataStep = function (el, step) {
|
|
111
|
+
el.querySelectorAll('[data-step]').forEach(n => {
|
|
112
|
+
n.classList.toggle('shown', Number(n.dataset.step) <= step);
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// blinkCaret(el)
|
|
118
|
+
// Attach a blinking caret to an element. CSS does the visual; this returns a
|
|
119
|
+
// cleanup that removes the caret span if you need it.
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
Stage.blinkCaret = function (el) {
|
|
122
|
+
const c = document.createElement('span');
|
|
123
|
+
c.className = 'caret';
|
|
124
|
+
el.appendChild(c);
|
|
125
|
+
return () => c.remove();
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
// sessionElapsedClock(opts)
|
|
130
|
+
// Live MM:SS / H:MM:SS clock that ticks every second. Returns the element
|
|
131
|
+
// plus a stop() function.
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
Stage.sessionElapsedClock = function (opts = {}) {
|
|
134
|
+
const start = opts.start ?? Date.now();
|
|
135
|
+
const el = document.createElement('span');
|
|
136
|
+
el.className = 'session-clock';
|
|
137
|
+
function format(ms) {
|
|
138
|
+
const total = Math.floor(ms / 1000);
|
|
139
|
+
const h = Math.floor(total / 3600);
|
|
140
|
+
const m = Math.floor((total % 3600) / 60);
|
|
141
|
+
const s = total % 60;
|
|
142
|
+
const pad = n => String(n).padStart(2, '0');
|
|
143
|
+
return h > 0 ? `${h}:${pad(m)}:${pad(s)}` : `${pad(m)}:${pad(s)}`;
|
|
144
|
+
}
|
|
145
|
+
function tick() { el.textContent = format(Date.now() - start); }
|
|
146
|
+
tick();
|
|
147
|
+
const id = setInterval(tick, 1000);
|
|
148
|
+
return { el, stop: () => clearInterval(id) };
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// ---------------------------------------------------------------------------
|
|
152
|
+
// assignStageKeys(root)
|
|
153
|
+
// Walk a rendered element subtree, assigning `data-stage-key` to every
|
|
154
|
+
// element via a depth-indexed path (e.g. "0", "0.1", "0.1.2").
|
|
155
|
+
// Skipped for elements that already have a key (semantic override).
|
|
156
|
+
// Used by edit mode for element-pin annotations.
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
Stage.assignStageKeys = function (root) {
|
|
159
|
+
function walk(node, prefix) {
|
|
160
|
+
Array.from(node.children).forEach((child, i) => {
|
|
161
|
+
const key = prefix ? `${prefix}.${i}` : String(i);
|
|
162
|
+
if (!child.dataset.stageKey) child.dataset.stageKey = key;
|
|
163
|
+
walk(child, key);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
walk(root, '');
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
})(typeof window !== 'undefined' ? window : globalThis);
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Stagecraft — Built-in transitions library.
|
|
5
|
+
*
|
|
6
|
+
* Six transitions: cut, fade, slide, dissolve, glitch, wipe.
|
|
7
|
+
* Themes can override or extend via Stage.registerTransition(name, config).
|
|
8
|
+
*
|
|
9
|
+
* Each transition has optional enter(el) and exit(el) hooks. CSS classes
|
|
10
|
+
* named `tx-<name>-enter` and `tx-<name>-exit` are added/removed; themes
|
|
11
|
+
* provide the actual visual via CSS.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
(function (root) {
|
|
15
|
+
const Stage = root.Stage = root.Stage || {};
|
|
16
|
+
|
|
17
|
+
function classToggle(el, cls, ms = 800) {
|
|
18
|
+
el.classList.add(cls);
|
|
19
|
+
setTimeout(() => el.classList.remove(cls), ms);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Stage.registerTransition('cut', {
|
|
23
|
+
enter(el) { /* no-op, instant */ },
|
|
24
|
+
exit(el) { /* no-op */ }
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
Stage.registerTransition('fade', {
|
|
28
|
+
enter(el) { classToggle(el, 'tx-fade-enter', 700); },
|
|
29
|
+
exit(el) { classToggle(el, 'tx-fade-exit', 400); }
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
Stage.registerTransition('slide', {
|
|
33
|
+
enter(el) { classToggle(el, 'tx-slide-enter', 700); },
|
|
34
|
+
exit(el) { classToggle(el, 'tx-slide-exit', 500); }
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
Stage.registerTransition('dissolve', {
|
|
38
|
+
enter(el) { classToggle(el, 'tx-dissolve-enter', 1200); },
|
|
39
|
+
exit(el) { classToggle(el, 'tx-dissolve-exit', 1000); }
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Glitch: a brief scanline + RGB-shift overlay, then settle.
|
|
43
|
+
Stage.registerTransition('glitch', {
|
|
44
|
+
enter(el) {
|
|
45
|
+
classToggle(el, 'tx-glitch-enter', 600);
|
|
46
|
+
const overlay = document.createElement('div');
|
|
47
|
+
overlay.className = 'tx-glitch-overlay';
|
|
48
|
+
el.appendChild(overlay);
|
|
49
|
+
setTimeout(() => overlay.remove(), 600);
|
|
50
|
+
},
|
|
51
|
+
exit(el) { classToggle(el, 'tx-glitch-exit', 200); }
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
Stage.registerTransition('wipe', {
|
|
55
|
+
enter(el) { classToggle(el, 'tx-wipe-enter', 800); },
|
|
56
|
+
exit(el) { classToggle(el, 'tx-wipe-exit', 500); }
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// -- Additional transitions (Phase 2) -- //
|
|
60
|
+
|
|
61
|
+
Stage.registerTransition('zoom-in', {
|
|
62
|
+
enter(el) { classToggle(el, 'tx-zoom-in-enter', 700); },
|
|
63
|
+
exit(el) { classToggle(el, 'tx-zoom-in-exit', 400); }
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
Stage.registerTransition('zoom-out', {
|
|
67
|
+
enter(el) { classToggle(el, 'tx-zoom-out-enter', 700); },
|
|
68
|
+
exit(el) { classToggle(el, 'tx-zoom-out-exit', 400); }
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
Stage.registerTransition('flip', {
|
|
72
|
+
enter(el) { classToggle(el, 'tx-flip-enter', 900); },
|
|
73
|
+
exit(el) { classToggle(el, 'tx-flip-exit', 500); }
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
Stage.registerTransition('iris', {
|
|
77
|
+
enter(el) { classToggle(el, 'tx-iris-enter', 900); },
|
|
78
|
+
exit(el) { classToggle(el, 'tx-iris-exit', 500); }
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
Stage.registerTransition('shutter', {
|
|
82
|
+
enter(el) { classToggle(el, 'tx-shutter-enter', 800); },
|
|
83
|
+
exit(el) { classToggle(el, 'tx-shutter-exit', 500); }
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
Stage.registerTransition('push', {
|
|
87
|
+
enter(el) { classToggle(el, 'tx-push-enter', 800); },
|
|
88
|
+
exit(el) { classToggle(el, 'tx-push-exit', 800); }
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
Stage.registerTransition('typewriter', {
|
|
92
|
+
enter(el) { classToggle(el, 'tx-typewriter-enter', 900); },
|
|
93
|
+
exit(el) { classToggle(el, 'tx-typewriter-exit', 300); }
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
Stage.registerTransition('shatter', {
|
|
97
|
+
enter(el) { classToggle(el, 'tx-shatter-enter', 900); },
|
|
98
|
+
exit(el) { classToggle(el, 'tx-shatter-exit', 500); }
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
})(typeof window !== 'undefined' ? window : globalThis);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en" data-theme="phosphor">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
6
|
+
<title>My Deck — Stagecraft</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,300;0,400;0,500;0,700;1,400&display=swap" rel="stylesheet">
|
|
10
|
+
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0&display=swap" rel="stylesheet">
|
|
11
|
+
|
|
12
|
+
<link rel="stylesheet" href="node_modules/stagecraft/dist/themes/phosphor.bundle.css">
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
|
|
16
|
+
<div class="welcome" id="welcome">
|
|
17
|
+
<div class="key-prompt"><span class="accent">●</span> Press <span class="accent">→</span> or <span class="accent">Space</span> to begin</div>
|
|
18
|
+
<h1>My Deck</h1>
|
|
19
|
+
<div class="by">Made with Stagecraft</div>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<main id="stage"></main>
|
|
23
|
+
|
|
24
|
+
<div class="ui">
|
|
25
|
+
<div class="ui-brand"><span class="br-accent">DECK</span></div>
|
|
26
|
+
<div class="ui-title" id="uiTitle"></div>
|
|
27
|
+
<div class="ui-counter">
|
|
28
|
+
<span id="curSec">00</span><span class="slash">/</span><span class="total">00</span>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="ui-dots" id="uiDots"></div>
|
|
31
|
+
<div class="ui-hint" id="uiHint">→ next · ← prev · S storyboard · F fullscreen · R replay · P presenter · E edit toggle</div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<!-- Stagecraft runtime: engine + helpers + transitions + all components + edit-mode -->
|
|
35
|
+
<script src="node_modules/stagecraft/dist/stagecraft.bundle.js"></script>
|
|
36
|
+
|
|
37
|
+
<!-- Deck manifest: order + transitions -->
|
|
38
|
+
<script src="stagecraft.config.js"></script>
|
|
39
|
+
</body>
|
|
40
|
+
</html>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Stage.register(Stage.KineticText({
|
|
4
|
+
section: 1,
|
|
5
|
+
title: '01 · Welcome',
|
|
6
|
+
pace: 700,
|
|
7
|
+
lines: [
|
|
8
|
+
{ text: 'A new deck.', color: 'fg' },
|
|
9
|
+
{ text: 'Ready to be built.', color: 'dim' },
|
|
10
|
+
{ text: 'Press → to begin.', color: 'accent', pause: 600 }
|
|
11
|
+
]
|
|
12
|
+
}));
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/* Stagecraft — Brand theme: business component overrides.
|
|
2
|
+
* Pricing · Testimonial · TeamGrid · Agenda · Checklist · Steps ·
|
|
3
|
+
* CTA · Callout · Tip · BeforeAfter */
|
|
4
|
+
|
|
5
|
+
@import url('../phosphor/components-business.css');
|
|
6
|
+
|
|
7
|
+
/* ===========================================================================
|
|
8
|
+
* Pricing — featured tier keeps the accent border but loses the halo
|
|
9
|
+
* ===========================================================================*/
|
|
10
|
+
:root[data-theme="brand"] .pricing-tier {
|
|
11
|
+
background: var(--bg-elevated);
|
|
12
|
+
border: 1px solid var(--dim-2);
|
|
13
|
+
}
|
|
14
|
+
:root[data-theme="brand"] .pricing-tier--featured {
|
|
15
|
+
border: 1px solid var(--accent);
|
|
16
|
+
box-shadow: none;
|
|
17
|
+
/* keep the slight scale lift — it's structural, not flashy */
|
|
18
|
+
}
|
|
19
|
+
:root[data-theme="brand"] .pricing-badge {
|
|
20
|
+
box-shadow: none;
|
|
21
|
+
background: var(--accent);
|
|
22
|
+
color: var(--bg);
|
|
23
|
+
font-weight: 600;
|
|
24
|
+
}
|
|
25
|
+
:root[data-theme="brand"] .pricing-name { letter-spacing: 0.1em; }
|
|
26
|
+
:root[data-theme="brand"] .pricing-price { font-weight: 600; }
|
|
27
|
+
:root[data-theme="brand"] .pricing-tier--featured .pricing-price {
|
|
28
|
+
color: var(--accent);
|
|
29
|
+
text-shadow: none;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* ===========================================================================
|
|
33
|
+
* Testimonial — round photo with thin border, no glow ring
|
|
34
|
+
* ===========================================================================*/
|
|
35
|
+
:root[data-theme="brand"] .testimonial-photo-wrap {
|
|
36
|
+
box-shadow: none;
|
|
37
|
+
border: 1px solid var(--dim-2);
|
|
38
|
+
}
|
|
39
|
+
:root[data-theme="brand"] .testimonial-mark {
|
|
40
|
+
color: var(--accent);
|
|
41
|
+
text-shadow: none;
|
|
42
|
+
font-weight: 300;
|
|
43
|
+
}
|
|
44
|
+
:root[data-theme="brand"] .testimonial-quote {
|
|
45
|
+
font-style: normal; /* schlicht */
|
|
46
|
+
font-weight: 500;
|
|
47
|
+
}
|
|
48
|
+
:root[data-theme="brand"] .testimonial-author { font-weight: 600; }
|
|
49
|
+
|
|
50
|
+
/* ===========================================================================
|
|
51
|
+
* TeamGrid — flat cards
|
|
52
|
+
* ===========================================================================*/
|
|
53
|
+
:root[data-theme="brand"] .team-card {
|
|
54
|
+
background: var(--bg-elevated);
|
|
55
|
+
border: 1px solid var(--dim-2);
|
|
56
|
+
}
|
|
57
|
+
:root[data-theme="brand"] .team-name { font-weight: 600; }
|
|
58
|
+
:root[data-theme="brand"] .team-role { letter-spacing: 0.1em; }
|
|
59
|
+
|
|
60
|
+
/* ===========================================================================
|
|
61
|
+
* Agenda — strip the dot glow ring
|
|
62
|
+
* ===========================================================================*/
|
|
63
|
+
:root[data-theme="brand"] .agenda-dot {
|
|
64
|
+
box-shadow: none;
|
|
65
|
+
border: 1px solid var(--accent);
|
|
66
|
+
background: var(--bg-elevated);
|
|
67
|
+
}
|
|
68
|
+
:root[data-theme="brand"] .agenda-label { font-weight: 600; }
|
|
69
|
+
:root[data-theme="brand"] .agenda-duration { letter-spacing: 0.1em; }
|
|
70
|
+
|
|
71
|
+
/* ===========================================================================
|
|
72
|
+
* Checklist — flat checkbox accent, no glow
|
|
73
|
+
* ===========================================================================*/
|
|
74
|
+
:root[data-theme="brand"] .checklist-item {
|
|
75
|
+
background: var(--bg-elevated);
|
|
76
|
+
border: 1px solid var(--dim-2);
|
|
77
|
+
}
|
|
78
|
+
:root[data-theme="brand"] .checklist-item.is-done {
|
|
79
|
+
border-color: color-mix(in srgb, var(--accent) 40%, var(--dim-2));
|
|
80
|
+
}
|
|
81
|
+
:root[data-theme="brand"] .checklist-item.is-done .checklist-box {
|
|
82
|
+
text-shadow: none;
|
|
83
|
+
}
|
|
84
|
+
:root[data-theme="brand"] .checklist-text { font-weight: 500; }
|
|
85
|
+
|
|
86
|
+
/* ===========================================================================
|
|
87
|
+
* Steps — flat numerals
|
|
88
|
+
* ===========================================================================*/
|
|
89
|
+
:root[data-theme="brand"] .step-card {
|
|
90
|
+
background: var(--bg-elevated);
|
|
91
|
+
border: 1px solid var(--dim-2);
|
|
92
|
+
}
|
|
93
|
+
:root[data-theme="brand"] .step-numeral {
|
|
94
|
+
color: var(--accent);
|
|
95
|
+
text-shadow: none;
|
|
96
|
+
font-weight: 600;
|
|
97
|
+
}
|
|
98
|
+
:root[data-theme="brand"] .step-label { font-weight: 600; }
|
|
99
|
+
|
|
100
|
+
/* ===========================================================================
|
|
101
|
+
* CTA — accent card without the soft gradient and halo
|
|
102
|
+
* ===========================================================================*/
|
|
103
|
+
:root[data-theme="brand"] .cta {
|
|
104
|
+
background: var(--bg-elevated);
|
|
105
|
+
border: 1px solid var(--dim-2);
|
|
106
|
+
}
|
|
107
|
+
:root[data-theme="brand"] .cta--accent {
|
|
108
|
+
border-color: var(--accent);
|
|
109
|
+
background: var(--bg-elevated);
|
|
110
|
+
box-shadow: none;
|
|
111
|
+
}
|
|
112
|
+
:root[data-theme="brand"] .cta-headline { font-weight: 600; }
|
|
113
|
+
:root[data-theme="brand"] .cta-button {
|
|
114
|
+
letter-spacing: 0.08em;
|
|
115
|
+
font-weight: 600;
|
|
116
|
+
}
|
|
117
|
+
:root[data-theme="brand"] .cta--accent .cta-button {
|
|
118
|
+
background: var(--accent);
|
|
119
|
+
color: var(--bg);
|
|
120
|
+
box-shadow: none;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* ===========================================================================
|
|
124
|
+
* Callout & Tip — keep semantic accent borders, drop colored gradients
|
|
125
|
+
* ===========================================================================*/
|
|
126
|
+
:root[data-theme="brand"] .callout {
|
|
127
|
+
background: var(--bg-elevated);
|
|
128
|
+
}
|
|
129
|
+
:root[data-theme="brand"] .callout--info,
|
|
130
|
+
:root[data-theme="brand"] .callout--tip,
|
|
131
|
+
:root[data-theme="brand"] .callout--warning,
|
|
132
|
+
:root[data-theme="brand"] .callout--danger,
|
|
133
|
+
:root[data-theme="brand"] .callout--success {
|
|
134
|
+
/* Override the linear-gradient backgrounds — too colorful for boardroom. */
|
|
135
|
+
background: var(--bg-elevated);
|
|
136
|
+
}
|
|
137
|
+
:root[data-theme="brand"] .callout--success .callout-icon {
|
|
138
|
+
text-shadow: none;
|
|
139
|
+
}
|
|
140
|
+
:root[data-theme="brand"] .callout-heading { font-weight: 600; }
|
|
141
|
+
|
|
142
|
+
:root[data-theme="brand"] .tip {
|
|
143
|
+
background: var(--bg-elevated);
|
|
144
|
+
border: 1px solid var(--dim-2);
|
|
145
|
+
}
|
|
146
|
+
:root[data-theme="brand"] .tip--success {
|
|
147
|
+
background: var(--bg-elevated);
|
|
148
|
+
border-color: var(--accent);
|
|
149
|
+
}
|
|
150
|
+
:root[data-theme="brand"] .tip--success .tip-icon { text-shadow: none; }
|
|
151
|
+
|
|
152
|
+
/* ===========================================================================
|
|
153
|
+
* BeforeAfter — clean dividers, no accent glow on arrow / divider
|
|
154
|
+
* ===========================================================================*/
|
|
155
|
+
:root[data-theme="brand"] .ba-col {
|
|
156
|
+
background: var(--bg-elevated);
|
|
157
|
+
border: 1px solid var(--dim-2);
|
|
158
|
+
}
|
|
159
|
+
:root[data-theme="brand"] .ba-col.ba-after {
|
|
160
|
+
border-color: color-mix(in srgb, var(--accent) 40%, var(--dim-2));
|
|
161
|
+
}
|
|
162
|
+
:root[data-theme="brand"] .ba-arrow {
|
|
163
|
+
color: var(--accent);
|
|
164
|
+
text-shadow: none;
|
|
165
|
+
}
|
|
166
|
+
:root[data-theme="brand"] .ba-tag--accent {
|
|
167
|
+
box-shadow: none;
|
|
168
|
+
}
|
|
169
|
+
:root[data-theme="brand"] .before-after--image .ba-divider {
|
|
170
|
+
background: var(--accent);
|
|
171
|
+
box-shadow: none;
|
|
172
|
+
transform: none; /* drop the skew — boardroom flat */
|
|
173
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/* Stagecraft — Brand theme: chart component overrides.
|
|
2
|
+
* Matrix2x2 · BarChart · Progress · ProcessFlow · Venn */
|
|
3
|
+
|
|
4
|
+
@import url('../phosphor/components-chart.css');
|
|
5
|
+
|
|
6
|
+
/* ===========================================================================
|
|
7
|
+
* Matrix2x2 — desaturated dim quadrants, active quadrant gets clean accent
|
|
8
|
+
* ===========================================================================*/
|
|
9
|
+
:root[data-theme="brand"] .matrix2x2 .quadrant.active {
|
|
10
|
+
background: color-mix(in srgb, var(--q-color, var(--accent)) 6%, var(--bg));
|
|
11
|
+
box-shadow: inset 0 0 0 1px var(--q-color, var(--accent));
|
|
12
|
+
}
|
|
13
|
+
:root[data-theme="brand"] .matrix2x2 .q-label { font-weight: 600; }
|
|
14
|
+
|
|
15
|
+
/* ===========================================================================
|
|
16
|
+
* BarChart — flat fills, no drop shadow on bars
|
|
17
|
+
* ===========================================================================*/
|
|
18
|
+
:root[data-theme="brand"] .barchart .bar-fill {
|
|
19
|
+
box-shadow: none;
|
|
20
|
+
}
|
|
21
|
+
:root[data-theme="brand"] .barchart .bar-label,
|
|
22
|
+
:root[data-theme="brand"] .barchart .bar-value {
|
|
23
|
+
font-family: var(--body);
|
|
24
|
+
font-weight: 500;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* ===========================================================================
|
|
28
|
+
* Progress — same: flat track + flat fill
|
|
29
|
+
* ===========================================================================*/
|
|
30
|
+
:root[data-theme="brand"] .progress-fill {
|
|
31
|
+
box-shadow: none;
|
|
32
|
+
}
|
|
33
|
+
:root[data-theme="brand"] .progress-track {
|
|
34
|
+
border-radius: 0; /* squarer, more corporate */
|
|
35
|
+
}
|
|
36
|
+
:root[data-theme="brand"] .progress-label,
|
|
37
|
+
:root[data-theme="brand"] .progress-value {
|
|
38
|
+
font-family: var(--body);
|
|
39
|
+
font-weight: 500;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* ===========================================================================
|
|
43
|
+
* ProcessFlow — kill the arrow text-shadow pulse glow
|
|
44
|
+
* ===========================================================================*/
|
|
45
|
+
:root[data-theme="brand"] .processflow .pf-step {
|
|
46
|
+
background: var(--bg-elevated);
|
|
47
|
+
border: 1px solid var(--dim-2);
|
|
48
|
+
}
|
|
49
|
+
:root[data-theme="brand"] .processflow .pf-step.accent { border-color: var(--accent); }
|
|
50
|
+
:root[data-theme="brand"] .processflow .pf-step.amber { border-color: color-mix(in srgb, var(--amber) 50%, var(--dim-2)); }
|
|
51
|
+
:root[data-theme="brand"] .processflow .pf-step.blue { border-color: color-mix(in srgb, var(--blue) 50%, var(--dim-2)); }
|
|
52
|
+
:root[data-theme="brand"] .processflow .pf-step.red { border-color: color-mix(in srgb, var(--red) 50%, var(--dim-2)); }
|
|
53
|
+
:root[data-theme="brand"] .processflow .pf-label { font-weight: 600; }
|
|
54
|
+
:root[data-theme="brand"] .processflow .pf-arrow.pulse {
|
|
55
|
+
animation: none; /* no flashy pulse */
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* ===========================================================================
|
|
59
|
+
* Venn — keep SVG geometry, tone fill opacity down slightly
|
|
60
|
+
* ===========================================================================*/
|
|
61
|
+
:root[data-theme="brand"] .venn .v-circle {
|
|
62
|
+
fill-opacity: 0.14;
|
|
63
|
+
stroke-width: 1.5;
|
|
64
|
+
}
|
|
65
|
+
:root[data-theme="brand"] .venn .v-label.set { font-weight: 600; }
|