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.
Files changed (133) hide show
  1. package/AGENT.md +792 -0
  2. package/LICENSE +21 -0
  3. package/README.md +210 -0
  4. package/bin/cli.js +51 -0
  5. package/bin/export.js +137 -0
  6. package/bin/init.js +52 -0
  7. package/bin/lib/edit-ops.js +405 -0
  8. package/bin/serve.js +278 -0
  9. package/dist/stagecraft.bundle.css +4443 -0
  10. package/dist/stagecraft.bundle.js +7621 -0
  11. package/dist/themes/brand.bundle.css +5262 -0
  12. package/dist/themes/neon.bundle.css +5289 -0
  13. package/dist/themes/paper.bundle.css +5276 -0
  14. package/dist/themes/phosphor.bundle.css +4443 -0
  15. package/dist/themes/shopware.bundle.css +5850 -0
  16. package/examples/closing-card.js +74 -0
  17. package/examples/orchestration-graph.js +156 -0
  18. package/examples/terminal-log.js +109 -0
  19. package/examples/token-stream.js +96 -0
  20. package/examples/whoami.js +90 -0
  21. package/package.json +41 -0
  22. package/src/components/activity-list.js +75 -0
  23. package/src/components/agenda.js +79 -0
  24. package/src/components/bar-chart.js +162 -0
  25. package/src/components/before-after.js +135 -0
  26. package/src/components/bento.js +73 -0
  27. package/src/components/big-number.js +87 -0
  28. package/src/components/callout.js +75 -0
  29. package/src/components/checklist.js +81 -0
  30. package/src/components/code-block.js +141 -0
  31. package/src/components/code-diff.js +98 -0
  32. package/src/components/compare.js +85 -0
  33. package/src/components/counter.js +80 -0
  34. package/src/components/cta.js +69 -0
  35. package/src/components/cycle.js +146 -0
  36. package/src/components/definition.js +96 -0
  37. package/src/components/donut-chart.js +179 -0
  38. package/src/components/full-image.js +82 -0
  39. package/src/components/funnel.js +111 -0
  40. package/src/components/gauge.js +147 -0
  41. package/src/components/heatmap.js +141 -0
  42. package/src/components/image-grid.js +80 -0
  43. package/src/components/image-text.js +96 -0
  44. package/src/components/kinetic-text.js +72 -0
  45. package/src/components/kpi.js +106 -0
  46. package/src/components/line-chart.js +215 -0
  47. package/src/components/manifesto.js +104 -0
  48. package/src/components/marquee.js +63 -0
  49. package/src/components/matrix2x2.js +151 -0
  50. package/src/components/pillars.js +80 -0
  51. package/src/components/pricing.js +90 -0
  52. package/src/components/process-flow.js +133 -0
  53. package/src/components/progress.js +136 -0
  54. package/src/components/punchline.js +82 -0
  55. package/src/components/pyramid.js +107 -0
  56. package/src/components/qanda.js +60 -0
  57. package/src/components/quote.js +70 -0
  58. package/src/components/roadmap.js +130 -0
  59. package/src/components/section-card.js +45 -0
  60. package/src/components/shift-arrow.js +41 -0
  61. package/src/components/spark-line.js +147 -0
  62. package/src/components/spotlight.js +85 -0
  63. package/src/components/statement.js +106 -0
  64. package/src/components/stats.js +91 -0
  65. package/src/components/steps.js +83 -0
  66. package/src/components/swot.js +110 -0
  67. package/src/components/team-grid.js +87 -0
  68. package/src/components/testimonial.js +99 -0
  69. package/src/components/timeline.js +91 -0
  70. package/src/components/tip.js +63 -0
  71. package/src/components/venn.js +198 -0
  72. package/src/edit-mode.js +1256 -0
  73. package/src/engine.js +823 -0
  74. package/src/helpers.js +169 -0
  75. package/src/transitions.js +101 -0
  76. package/starter/index.html +40 -0
  77. package/starter/slides/00-title.js +12 -0
  78. package/starter/stagecraft.config.js +8 -0
  79. package/themes/brand/base.css +4 -0
  80. package/themes/brand/components-business.css +173 -0
  81. package/themes/brand/components-chart.css +65 -0
  82. package/themes/brand/components-content.css +126 -0
  83. package/themes/brand/components-data.css +162 -0
  84. package/themes/brand/components-diagram.css +115 -0
  85. package/themes/brand/components-layout.css +112 -0
  86. package/themes/brand/components.css +46 -0
  87. package/themes/brand/manifest.json +20 -0
  88. package/themes/brand/tokens.css +20 -0
  89. package/themes/brand/transitions.css +4 -0
  90. package/themes/neon/base.css +10 -0
  91. package/themes/neon/components-business.css +189 -0
  92. package/themes/neon/components-chart.css +70 -0
  93. package/themes/neon/components-content.css +112 -0
  94. package/themes/neon/components-data.css +160 -0
  95. package/themes/neon/components-diagram.css +109 -0
  96. package/themes/neon/components-layout.css +87 -0
  97. package/themes/neon/components.css +87 -0
  98. package/themes/neon/manifest.json +21 -0
  99. package/themes/neon/tokens.css +17 -0
  100. package/themes/neon/transitions.css +13 -0
  101. package/themes/paper/base.css +9 -0
  102. package/themes/paper/components-business.css +196 -0
  103. package/themes/paper/components-chart.css +74 -0
  104. package/themes/paper/components-content.css +108 -0
  105. package/themes/paper/components-data.css +168 -0
  106. package/themes/paper/components-diagram.css +89 -0
  107. package/themes/paper/components-layout.css +105 -0
  108. package/themes/paper/components.css +60 -0
  109. package/themes/paper/manifest.json +10 -0
  110. package/themes/paper/tokens.css +21 -0
  111. package/themes/paper/transitions.css +11 -0
  112. package/themes/phosphor/base.css +511 -0
  113. package/themes/phosphor/components-business.css +818 -0
  114. package/themes/phosphor/components-chart.css +415 -0
  115. package/themes/phosphor/components-content.css +530 -0
  116. package/themes/phosphor/components-data.css +824 -0
  117. package/themes/phosphor/components-diagram.css +427 -0
  118. package/themes/phosphor/components-layout.css +450 -0
  119. package/themes/phosphor/components.css +223 -0
  120. package/themes/phosphor/manifest.json +11 -0
  121. package/themes/phosphor/tokens.css +17 -0
  122. package/themes/phosphor/transitions.css +213 -0
  123. package/themes/shopware/base.css +94 -0
  124. package/themes/shopware/components-business.css +344 -0
  125. package/themes/shopware/components-chart.css +121 -0
  126. package/themes/shopware/components-content.css +169 -0
  127. package/themes/shopware/components-data.css +219 -0
  128. package/themes/shopware/components-diagram.css +129 -0
  129. package/themes/shopware/components-layout.css +166 -0
  130. package/themes/shopware/components.css +83 -0
  131. package/themes/shopware/manifest.json +21 -0
  132. package/themes/shopware/tokens.css +68 -0
  133. 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>&nbsp;&nbsp;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,8 @@
1
+ 'use strict';
2
+
3
+ Stage.deck({
4
+ theme: 'phosphor',
5
+ slides: [
6
+ { src: 'slides/00-title.js' }
7
+ ]
8
+ });
@@ -0,0 +1,4 @@
1
+ @import url('../phosphor/base.css');
2
+
3
+ /* Brand: cleaner, no film grain */
4
+ :root[data-theme="brand"] body::after { display: none; }
@@ -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; }