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
@@ -0,0 +1,824 @@
1
+ /* Stagecraft — Phosphor theme: data-visualization component styles.
2
+ Used by KPI, DonutChart, LineChart, Gauge, SparkLine, Heatmap,
3
+ Roadmap, SWOT, CodeBlock, CodeDiff. */
4
+
5
+ /* ============================================================
6
+ * Shared color hooks (used by KPI, SparkLine, Gauge, etc.)
7
+ * ------------------------------------------------------------ */
8
+ .kpi--accent, .gauge--accent, .sparkline--accent { --data-color: var(--accent); }
9
+ .kpi--amber, .gauge--amber, .sparkline--amber { --data-color: var(--amber); }
10
+ .kpi--blue, .gauge--blue, .sparkline--blue { --data-color: var(--blue); }
11
+ .kpi--red, .gauge--red, .sparkline--red { --data-color: var(--red); }
12
+ .kpi--dim, .gauge--dim, .sparkline--dim { --data-color: var(--dim); }
13
+ .kpi--fg, .gauge--fg, .sparkline--fg { --data-color: var(--fg); }
14
+
15
+ /* ============================================================
16
+ * KPI
17
+ * ============================================================ */
18
+ .kpi {
19
+ --data-color: var(--accent);
20
+ width: min(620px, 92vw);
21
+ background: var(--bg-elevated);
22
+ border: 1px solid var(--dim-2);
23
+ padding: clamp(1.4rem, 2.6vw, 2.2rem);
24
+ display: flex;
25
+ flex-direction: column;
26
+ gap: clamp(0.6rem, 1.4vw, 1.1rem);
27
+ opacity: 0;
28
+ transform: translateY(10px);
29
+ transition: opacity 600ms ease-out, transform 600ms cubic-bezier(0.16, 1, 0.3, 1),
30
+ border-color 600ms ease-out, box-shadow 600ms ease-out;
31
+ }
32
+ .kpi.in {
33
+ opacity: 1;
34
+ transform: translateY(0);
35
+ border-color: color-mix(in srgb, var(--data-color) 35%, var(--dim-2));
36
+ box-shadow: 0 0 0 1px color-mix(in srgb, var(--data-color) 15%, transparent),
37
+ 0 0 50px color-mix(in srgb, var(--data-color) 12%, transparent);
38
+ }
39
+ .kpi-head {
40
+ display: flex;
41
+ align-items: center;
42
+ gap: 0.7rem;
43
+ font-size: clamp(0.9rem, 1.2vw, 1.05rem);
44
+ letter-spacing: 0.18em;
45
+ text-transform: uppercase;
46
+ color: var(--dim);
47
+ }
48
+ .kpi-icon {
49
+ color: var(--data-color);
50
+ font-size: 1.2em;
51
+ font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
52
+ }
53
+ .kpi-label {
54
+ letter-spacing: 0.18em;
55
+ }
56
+ .kpi-figure {
57
+ display: flex;
58
+ align-items: baseline;
59
+ gap: 0.25rem;
60
+ font-variant-numeric: tabular-nums;
61
+ line-height: 1;
62
+ }
63
+ .kpi-num {
64
+ font-size: clamp(3.4rem, 7vw, 6rem);
65
+ font-weight: 500;
66
+ color: var(--data-color);
67
+ letter-spacing: -0.03em;
68
+ text-shadow: 0 0 24px color-mix(in srgb, var(--data-color) 35%, transparent);
69
+ }
70
+ .kpi-unit {
71
+ font-size: clamp(1.4rem, 2.6vw, 2.2rem);
72
+ color: var(--data-color);
73
+ font-weight: 500;
74
+ letter-spacing: -0.01em;
75
+ }
76
+ .kpi-change {
77
+ display: inline-flex;
78
+ align-items: center;
79
+ gap: 0.5rem;
80
+ font-size: clamp(0.85rem, 1.15vw, 1rem);
81
+ font-variant-numeric: tabular-nums;
82
+ letter-spacing: 0.02em;
83
+ opacity: 0;
84
+ transform: translateY(4px);
85
+ transition: opacity 500ms ease-out, transform 500ms cubic-bezier(0.16, 1, 0.3, 1);
86
+ }
87
+ .kpi-change.in { opacity: 1; transform: translateY(0); }
88
+ .kpi-change .kpi-arrow {
89
+ font-size: 0.9em;
90
+ line-height: 1;
91
+ }
92
+ .kpi-change.up .kpi-arrow,
93
+ .kpi-change.up .kpi-change-num { color: var(--accent); }
94
+ .kpi-change.down .kpi-arrow,
95
+ .kpi-change.down .kpi-change-num { color: var(--red); }
96
+ .kpi-change .kpi-change-period { color: var(--dim); }
97
+
98
+ /* ============================================================
99
+ * DonutChart
100
+ * ============================================================ */
101
+ .donut {
102
+ display: flex;
103
+ align-items: center;
104
+ gap: clamp(1.5rem, 4vw, 3rem);
105
+ width: min(1100px, 92vw);
106
+ flex-wrap: wrap;
107
+ justify-content: center;
108
+ }
109
+ .donut-svg-wrap {
110
+ position: relative;
111
+ width: min(48vh, 36vw, 460px);
112
+ aspect-ratio: 1;
113
+ }
114
+ .donut-svg {
115
+ width: 100%;
116
+ height: 100%;
117
+ overflow: visible;
118
+ }
119
+ .donut-arc {
120
+ transition: stroke-width 300ms ease-out;
121
+ filter: drop-shadow(0 0 8px color-mix(in srgb, currentColor 0%, transparent));
122
+ }
123
+ .donut-center {
124
+ position: absolute;
125
+ inset: 0;
126
+ display: flex;
127
+ align-items: center;
128
+ justify-content: center;
129
+ font-size: clamp(1rem, 1.6vw, 1.4rem);
130
+ letter-spacing: 0.18em;
131
+ text-transform: uppercase;
132
+ color: var(--dim);
133
+ pointer-events: none;
134
+ }
135
+ .donut-legend {
136
+ display: flex;
137
+ flex-direction: column;
138
+ gap: 0.6rem;
139
+ min-width: 14rem;
140
+ }
141
+ .donut-legend-row {
142
+ display: grid;
143
+ grid-template-columns: auto 1fr auto auto;
144
+ gap: 0.8rem;
145
+ align-items: baseline;
146
+ font-size: clamp(0.85rem, 1.1vw, 1rem);
147
+ color: var(--fg);
148
+ opacity: 0;
149
+ transform: translateX(8px);
150
+ transition: opacity 500ms ease-out, transform 500ms cubic-bezier(0.16, 1, 0.3, 1);
151
+ font-variant-numeric: tabular-nums;
152
+ }
153
+ .donut-legend-row.in { opacity: 1; transform: translateX(0); }
154
+ .donut-dot {
155
+ width: 0.7rem;
156
+ height: 0.7rem;
157
+ background: var(--dc-color, var(--accent));
158
+ display: inline-block;
159
+ box-shadow: 0 0 8px color-mix(in srgb, var(--dc-color, var(--accent)) 70%, transparent);
160
+ }
161
+ .donut-leg-label {
162
+ letter-spacing: 0.02em;
163
+ }
164
+ .donut-leg-value {
165
+ color: var(--dim);
166
+ font-variant-numeric: tabular-nums;
167
+ }
168
+ .donut-leg-pct {
169
+ color: var(--fg);
170
+ min-width: 3.2ch;
171
+ text-align: right;
172
+ }
173
+
174
+ /* ============================================================
175
+ * LineChart
176
+ * ============================================================ */
177
+ .linechart {
178
+ width: min(1200px, 94vw);
179
+ display: flex;
180
+ flex-direction: column;
181
+ gap: 0.8rem;
182
+ }
183
+ .lc-svg-wrap {
184
+ width: 100%;
185
+ aspect-ratio: 2 / 1;
186
+ max-height: 60vh;
187
+ }
188
+ .lc-svg {
189
+ width: 100%;
190
+ height: 100%;
191
+ }
192
+ .lc-grid {
193
+ stroke: var(--dim-2);
194
+ stroke-width: 1;
195
+ stroke-dasharray: 2 4;
196
+ opacity: 0.7;
197
+ }
198
+ .lc-y-label,
199
+ .lc-x-label {
200
+ fill: var(--dim);
201
+ font-size: 14px;
202
+ font-family: var(--mono);
203
+ letter-spacing: 0.04em;
204
+ }
205
+ .lc-line {
206
+ fill: none;
207
+ stroke-width: 2.5;
208
+ stroke-linecap: round;
209
+ stroke-linejoin: round;
210
+ filter: drop-shadow(0 0 6px color-mix(in srgb, currentColor 40%, transparent));
211
+ }
212
+ .lc-area {
213
+ opacity: 0;
214
+ transition: opacity 700ms ease-out;
215
+ }
216
+ .lc-area.in { opacity: 1; }
217
+ .lc-dot {
218
+ opacity: 0;
219
+ transform-origin: center;
220
+ transition: opacity 400ms ease-out;
221
+ }
222
+ .lc-dot.in { opacity: 1; }
223
+ .lc-legend {
224
+ display: flex;
225
+ gap: clamp(1rem, 2vw, 1.6rem);
226
+ flex-wrap: wrap;
227
+ padding: 0.4rem 0.6rem 0;
228
+ }
229
+ .lc-leg-row {
230
+ display: inline-flex;
231
+ align-items: center;
232
+ gap: 0.5rem;
233
+ font-size: clamp(0.85rem, 1.1vw, 1rem);
234
+ color: var(--fg);
235
+ letter-spacing: 0.02em;
236
+ }
237
+ .lc-dot-leg {
238
+ width: 0.7rem;
239
+ height: 0.7rem;
240
+ background: var(--lc-color, var(--accent));
241
+ display: inline-block;
242
+ box-shadow: 0 0 8px color-mix(in srgb, var(--lc-color, var(--accent)) 70%, transparent);
243
+ }
244
+
245
+ /* ============================================================
246
+ * Gauge
247
+ * ============================================================ */
248
+ .gauge {
249
+ --data-color: var(--accent);
250
+ width: min(620px, 80vw);
251
+ display: flex;
252
+ flex-direction: column;
253
+ align-items: center;
254
+ }
255
+ .g-svg-wrap {
256
+ position: relative;
257
+ width: 100%;
258
+ aspect-ratio: 200 / 120;
259
+ }
260
+ .g-svg {
261
+ width: 100%;
262
+ height: 100%;
263
+ overflow: visible;
264
+ }
265
+ .g-fill {
266
+ filter: drop-shadow(0 0 14px color-mix(in srgb, var(--data-color) 55%, transparent));
267
+ transition: none;
268
+ }
269
+ .g-tick {
270
+ stroke: var(--dim);
271
+ stroke-width: 1.5;
272
+ opacity: 0.6;
273
+ }
274
+ .g-readout {
275
+ position: absolute;
276
+ left: 50%;
277
+ bottom: -0.6rem;
278
+ transform: translateX(-50%);
279
+ text-align: center;
280
+ display: flex;
281
+ flex-direction: column;
282
+ gap: 0.3rem;
283
+ }
284
+ .g-num {
285
+ font-variant-numeric: tabular-nums;
286
+ font-size: clamp(2.2rem, 4.4vw, 3.6rem);
287
+ font-weight: 500;
288
+ letter-spacing: -0.03em;
289
+ color: var(--data-color);
290
+ line-height: 1;
291
+ text-shadow: 0 0 18px color-mix(in srgb, var(--data-color) 40%, transparent);
292
+ display: flex;
293
+ align-items: baseline;
294
+ gap: 0.3rem;
295
+ justify-content: center;
296
+ }
297
+ .g-num-max {
298
+ font-size: 0.55em;
299
+ color: var(--dim);
300
+ font-weight: 400;
301
+ letter-spacing: 0.02em;
302
+ text-shadow: none;
303
+ }
304
+ .g-label {
305
+ font-size: clamp(0.85rem, 1.2vw, 1rem);
306
+ letter-spacing: 0.18em;
307
+ text-transform: uppercase;
308
+ color: var(--dim);
309
+ }
310
+
311
+ /* ============================================================
312
+ * SparkLine
313
+ * ============================================================ */
314
+ .sparkline {
315
+ --data-color: var(--accent);
316
+ width: min(540px, 90vw);
317
+ background: var(--bg-elevated);
318
+ border: 1px solid var(--dim-2);
319
+ padding: clamp(1.2rem, 2.2vw, 1.8rem);
320
+ display: flex;
321
+ flex-direction: column;
322
+ gap: 0.7rem;
323
+ }
324
+ .sl-figure {
325
+ display: flex;
326
+ align-items: baseline;
327
+ gap: 0.3rem;
328
+ line-height: 1;
329
+ }
330
+ .sl-num {
331
+ font-size: clamp(3rem, 6vw, 5rem);
332
+ font-weight: 500;
333
+ color: var(--data-color);
334
+ letter-spacing: -0.03em;
335
+ font-variant-numeric: tabular-nums;
336
+ text-shadow: 0 0 22px color-mix(in srgb, var(--data-color) 35%, transparent);
337
+ }
338
+ .sl-label {
339
+ font-size: clamp(0.85rem, 1.1vw, 1rem);
340
+ color: var(--dim);
341
+ letter-spacing: 0.18em;
342
+ text-transform: uppercase;
343
+ }
344
+ .sl-svg-wrap {
345
+ width: 100%;
346
+ height: clamp(60px, 8vh, 90px);
347
+ }
348
+ .sl-svg {
349
+ width: 100%;
350
+ height: 100%;
351
+ overflow: visible;
352
+ }
353
+ .sl-line {
354
+ stroke-width: 2;
355
+ fill: none;
356
+ filter: drop-shadow(0 0 6px color-mix(in srgb, currentColor 40%, transparent));
357
+ }
358
+ .sl-area {
359
+ opacity: 0;
360
+ transition: opacity 700ms ease-out;
361
+ }
362
+ .sl-area.in { opacity: 1; }
363
+ .sl-tip {
364
+ opacity: 0;
365
+ transition: opacity 400ms ease-out;
366
+ }
367
+ .sl-tip.in { opacity: 1; }
368
+ .sl-period {
369
+ font-size: clamp(0.75rem, 1vw, 0.9rem);
370
+ color: var(--dim);
371
+ letter-spacing: 0.04em;
372
+ }
373
+
374
+ /* ============================================================
375
+ * Heatmap
376
+ * ============================================================ */
377
+ .heatmap {
378
+ --hm-base: var(--accent);
379
+ --hm-cell: clamp(1.2rem, 2.2vw, 1.9rem);
380
+ width: min(1200px, 94vw);
381
+ display: flex;
382
+ flex-direction: column;
383
+ gap: 0.6rem;
384
+ }
385
+ .hm-x-labels {
386
+ display: grid;
387
+ grid-template-columns: minmax(3rem, auto) 1fr;
388
+ gap: clamp(0.4rem, 0.8vw, 0.7rem);
389
+ }
390
+ .hm-x-labels .hm-corner { /* placeholder above y-labels */ }
391
+ .hm-x-row {
392
+ display: grid;
393
+ grid-template-columns: repeat(var(--hm-cols), 1fr);
394
+ gap: clamp(2px, 0.3vw, 4px);
395
+ }
396
+ .hm-x-label {
397
+ font-size: clamp(0.7rem, 0.95vw, 0.85rem);
398
+ color: var(--dim);
399
+ letter-spacing: 0.08em;
400
+ text-transform: uppercase;
401
+ text-align: center;
402
+ font-variant-numeric: tabular-nums;
403
+ }
404
+ /* When y-labels are absent, drop the corner and stretch x-row full width */
405
+ .heatmap:not(:has(.hm-y-label)) .hm-x-labels {
406
+ grid-template-columns: 1fr;
407
+ }
408
+ .heatmap:not(:has(.hm-y-label)) .hm-x-labels .hm-corner { display: none; }
409
+ .hm-body {
410
+ display: flex;
411
+ flex-direction: column;
412
+ gap: clamp(2px, 0.3vw, 4px);
413
+ }
414
+ .hm-row {
415
+ display: grid;
416
+ grid-template-columns: minmax(3rem, auto) 1fr;
417
+ gap: clamp(0.4rem, 0.8vw, 0.7rem);
418
+ align-items: center;
419
+ }
420
+ .hm-row:only-child,
421
+ .heatmap:not(:has(.hm-y-label)) .hm-row {
422
+ grid-template-columns: 1fr;
423
+ }
424
+ .hm-y-label {
425
+ font-size: clamp(0.7rem, 0.95vw, 0.85rem);
426
+ color: var(--dim);
427
+ letter-spacing: 0.06em;
428
+ text-align: right;
429
+ font-variant-numeric: tabular-nums;
430
+ }
431
+ .hm-cells {
432
+ display: grid;
433
+ grid-template-columns: repeat(var(--hm-cols), 1fr);
434
+ gap: clamp(2px, 0.3vw, 4px);
435
+ }
436
+ .hm-cell {
437
+ aspect-ratio: 1;
438
+ background: color-mix(in srgb, var(--hm-base) calc(var(--hm-intensity) * 95%), var(--dim-2));
439
+ border: 1px solid color-mix(in srgb, var(--hm-base) calc(var(--hm-intensity) * 40%), var(--dim-2));
440
+ opacity: 0;
441
+ transform: scale(0.7);
442
+ transition: opacity 400ms ease-out, transform 400ms cubic-bezier(0.16, 1, 0.3, 1);
443
+ }
444
+ .hm-cell.in {
445
+ opacity: 1;
446
+ transform: scale(1);
447
+ }
448
+ .hm-scale {
449
+ display: inline-flex;
450
+ align-items: center;
451
+ gap: clamp(2px, 0.3vw, 4px);
452
+ align-self: flex-end;
453
+ margin-top: 0.4rem;
454
+ font-size: clamp(0.7rem, 0.9vw, 0.8rem);
455
+ color: var(--dim);
456
+ letter-spacing: 0.06em;
457
+ }
458
+ .hm-scale-label {
459
+ padding: 0 0.4rem;
460
+ }
461
+ .hm-scale-step {
462
+ width: clamp(0.9rem, 1.2vw, 1.2rem);
463
+ height: clamp(0.9rem, 1.2vw, 1.2rem);
464
+ display: inline-block;
465
+ background: color-mix(in srgb, var(--hm-base) calc(var(--hm-intensity) * 95%), var(--dim-2));
466
+ border: 1px solid color-mix(in srgb, var(--hm-base) calc(var(--hm-intensity) * 40%), var(--dim-2));
467
+ }
468
+
469
+ /* ============================================================
470
+ * Roadmap
471
+ * ============================================================ */
472
+ .roadmap {
473
+ width: min(1300px, 96vw);
474
+ display: flex;
475
+ flex-direction: column;
476
+ gap: clamp(0.5rem, 1vw, 0.8rem);
477
+ }
478
+ .rm-header {
479
+ display: grid;
480
+ grid-template-columns: 8rem 1fr;
481
+ gap: clamp(0.5rem, 1vw, 0.8rem);
482
+ }
483
+ .rm-lane-label-spacer {
484
+ /* placeholder above lane labels */
485
+ }
486
+ .rm-months {
487
+ display: grid;
488
+ grid-template-columns: repeat(var(--rm-cols), 1fr);
489
+ border-bottom: 1px solid var(--dim-2);
490
+ padding-bottom: 0.4rem;
491
+ }
492
+ .rm-month {
493
+ font-size: clamp(0.7rem, 0.95vw, 0.85rem);
494
+ letter-spacing: 0.12em;
495
+ text-transform: uppercase;
496
+ color: var(--dim);
497
+ text-align: center;
498
+ }
499
+ .rm-body {
500
+ display: flex;
501
+ flex-direction: column;
502
+ gap: clamp(0.6rem, 1vw, 1rem);
503
+ }
504
+ .rm-lane {
505
+ display: grid;
506
+ grid-template-columns: 8rem 1fr;
507
+ gap: clamp(0.5rem, 1vw, 0.8rem);
508
+ align-items: stretch;
509
+ opacity: 0;
510
+ transform: translateX(-10px);
511
+ transition: opacity 500ms ease-out, transform 500ms cubic-bezier(0.16, 1, 0.3, 1);
512
+ }
513
+ .rm-lane.in { opacity: 1; transform: translateX(0); }
514
+ .rm-lane-label {
515
+ --rm-color: var(--fg);
516
+ display: flex;
517
+ align-items: center;
518
+ font-size: clamp(0.85rem, 1.1vw, 1rem);
519
+ letter-spacing: 0.04em;
520
+ color: var(--fg);
521
+ border-left: 2px solid var(--rm-color);
522
+ padding-left: 0.8rem;
523
+ }
524
+ .rm-lane-label.rm-accent { --rm-color: var(--accent); }
525
+ .rm-lane-label.rm-amber { --rm-color: var(--amber); }
526
+ .rm-lane-label.rm-blue { --rm-color: var(--blue); }
527
+ .rm-lane-label.rm-red { --rm-color: var(--red); }
528
+ .rm-lane-label.rm-dim { --rm-color: var(--dim); }
529
+ .rm-lane-track {
530
+ position: relative;
531
+ background:
532
+ repeating-linear-gradient(
533
+ to right,
534
+ transparent 0,
535
+ transparent calc((100% / var(--rm-cols, 12)) - 1px),
536
+ var(--dim-2) calc((100% / var(--rm-cols, 12)) - 1px),
537
+ var(--dim-2) calc(100% / var(--rm-cols, 12))
538
+ ),
539
+ color-mix(in srgb, var(--bg-elevated) 60%, transparent);
540
+ border: 1px solid var(--dim-2);
541
+ min-height: clamp(2.2rem, 4vw, 3rem);
542
+ }
543
+ .rm-bar {
544
+ --rm-bar-color: var(--accent);
545
+ position: absolute;
546
+ top: 6px;
547
+ bottom: 6px;
548
+ left: var(--rm-left);
549
+ width: var(--rm-width);
550
+ background: color-mix(in srgb, var(--rm-bar-color) 22%, var(--bg-elevated));
551
+ border: 1px solid color-mix(in srgb, var(--rm-bar-color) 60%, var(--dim-2));
552
+ display: flex;
553
+ align-items: center;
554
+ padding: 0 0.7rem;
555
+ overflow: hidden;
556
+ opacity: 0;
557
+ transform: translateY(4px);
558
+ transition: opacity 600ms ease-out, transform 600ms cubic-bezier(0.16, 1, 0.3, 1),
559
+ width 800ms cubic-bezier(0.16, 1, 0.3, 1);
560
+ box-shadow: inset 3px 0 0 var(--rm-bar-color),
561
+ 0 0 20px color-mix(in srgb, var(--rm-bar-color) 18%, transparent);
562
+ }
563
+ .rm-bar.in { opacity: 1; transform: translateY(0); }
564
+ .rm-bar.rm-accent { --rm-bar-color: var(--accent); }
565
+ .rm-bar.rm-amber { --rm-bar-color: var(--amber); }
566
+ .rm-bar.rm-blue { --rm-bar-color: var(--blue); }
567
+ .rm-bar.rm-red { --rm-bar-color: var(--red); }
568
+ .rm-bar.rm-dim { --rm-bar-color: var(--dim); }
569
+ .rm-bar-label {
570
+ font-size: clamp(0.75rem, 1vw, 0.9rem);
571
+ color: var(--fg);
572
+ letter-spacing: 0.02em;
573
+ white-space: nowrap;
574
+ text-overflow: ellipsis;
575
+ overflow: hidden;
576
+ }
577
+
578
+ /* ============================================================
579
+ * SWOT
580
+ * ============================================================ */
581
+ .swot {
582
+ width: min(1100px, 94vw);
583
+ height: min(72vh, 700px);
584
+ display: grid;
585
+ grid-template-columns: 1fr 1fr;
586
+ grid-template-rows: 1fr 1fr;
587
+ gap: 1px;
588
+ background: var(--dim-2);
589
+ border: 1px solid var(--dim-2);
590
+ }
591
+ .swot-cell {
592
+ --swot-color: var(--accent);
593
+ background: var(--bg);
594
+ padding: clamp(1rem, 2.2vw, 1.8rem);
595
+ display: flex;
596
+ flex-direction: column;
597
+ gap: 0.8rem;
598
+ position: relative;
599
+ opacity: 0;
600
+ transform: scale(0.97);
601
+ transition: opacity 500ms ease-out, transform 500ms cubic-bezier(0.16, 1, 0.3, 1),
602
+ background 500ms ease-out, box-shadow 500ms ease-out;
603
+ overflow: hidden;
604
+ }
605
+ .swot-cell.in {
606
+ opacity: 1;
607
+ transform: scale(1);
608
+ background: color-mix(in srgb, var(--swot-color) 6%, var(--bg));
609
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--swot-color) 45%, var(--dim-2));
610
+ }
611
+ .swot-cell--accent { --swot-color: var(--accent); }
612
+ .swot-cell--amber { --swot-color: var(--amber); }
613
+ .swot-cell--blue { --swot-color: var(--blue); }
614
+ .swot-cell--red { --swot-color: var(--red); }
615
+ .swot-head {
616
+ display: flex;
617
+ align-items: baseline;
618
+ gap: 0.8rem;
619
+ }
620
+ .swot-letter {
621
+ font-size: clamp(2rem, 4vw, 3rem);
622
+ font-weight: 500;
623
+ color: var(--swot-color);
624
+ letter-spacing: -0.04em;
625
+ line-height: 1;
626
+ text-shadow: 0 0 20px color-mix(in srgb, var(--swot-color) 50%, transparent);
627
+ }
628
+ .swot-title {
629
+ font-size: clamp(1rem, 1.3vw, 1.2rem);
630
+ color: var(--fg);
631
+ letter-spacing: 0.18em;
632
+ text-transform: uppercase;
633
+ }
634
+ .swot-list {
635
+ list-style: none;
636
+ padding: 0;
637
+ margin: 0;
638
+ display: flex;
639
+ flex-direction: column;
640
+ gap: 0.55rem;
641
+ }
642
+ .swot-item {
643
+ font-size: clamp(0.9rem, 1.2vw, 1.05rem);
644
+ color: var(--fg);
645
+ line-height: 1.45;
646
+ padding-left: 1.2rem;
647
+ position: relative;
648
+ opacity: 0;
649
+ transform: translateX(-6px);
650
+ transition: opacity 400ms ease-out, transform 400ms cubic-bezier(0.16, 1, 0.3, 1);
651
+ }
652
+ .swot-item::before {
653
+ content: '';
654
+ position: absolute;
655
+ left: 0;
656
+ top: 0.55em;
657
+ width: 0.55rem;
658
+ height: 1px;
659
+ background: var(--swot-color);
660
+ }
661
+ .swot-item.in { opacity: 1; transform: translateX(0); }
662
+
663
+ /* ============================================================
664
+ * CodeBlock
665
+ * ============================================================ */
666
+ .codeblock {
667
+ width: min(1100px, 94vw);
668
+ background: var(--bg-elevated);
669
+ border: 1px solid var(--dim-2);
670
+ font-family: var(--mono);
671
+ overflow: hidden;
672
+ }
673
+ .cb-head {
674
+ display: flex;
675
+ align-items: center;
676
+ gap: 0.8rem;
677
+ padding: 0.7rem 1rem;
678
+ background: color-mix(in srgb, var(--bg) 60%, var(--bg-elevated));
679
+ border-bottom: 1px solid var(--dim-2);
680
+ font-size: clamp(0.8rem, 1vw, 0.9rem);
681
+ color: var(--dim);
682
+ letter-spacing: 0.04em;
683
+ }
684
+ .cb-dots {
685
+ display: inline-flex;
686
+ gap: 0.35rem;
687
+ }
688
+ .cb-dots span {
689
+ width: 0.55rem;
690
+ height: 0.55rem;
691
+ border-radius: 50%;
692
+ background: var(--dim-2);
693
+ }
694
+ .cb-dots span:nth-child(1) { background: color-mix(in srgb, var(--red) 60%, var(--dim-2)); }
695
+ .cb-dots span:nth-child(2) { background: color-mix(in srgb, var(--amber) 60%, var(--dim-2)); }
696
+ .cb-dots span:nth-child(3) { background: color-mix(in srgb, var(--accent) 60%, var(--dim-2)); }
697
+ .cb-file {
698
+ color: var(--fg);
699
+ font-weight: 500;
700
+ }
701
+ .cb-lang {
702
+ margin-left: auto;
703
+ font-size: 0.85em;
704
+ text-transform: uppercase;
705
+ letter-spacing: 0.18em;
706
+ color: var(--accent);
707
+ }
708
+ .cb-body {
709
+ margin: 0;
710
+ padding: clamp(0.8rem, 1.4vw, 1.2rem) 0;
711
+ font-size: clamp(0.85rem, 1.1vw, 1rem);
712
+ line-height: 1.55;
713
+ color: var(--fg);
714
+ background: transparent;
715
+ overflow-x: auto;
716
+ white-space: pre;
717
+ }
718
+ .cb-line {
719
+ display: grid;
720
+ grid-template-columns: 4ch 1fr;
721
+ gap: 1rem;
722
+ padding: 0 clamp(0.8rem, 1.4vw, 1.2rem);
723
+ opacity: 0;
724
+ transform: translateY(2px);
725
+ transition: opacity 400ms ease-out, transform 400ms cubic-bezier(0.16, 1, 0.3, 1),
726
+ background 300ms ease-out;
727
+ }
728
+ .cb-line.in { opacity: 1; transform: translateY(0); }
729
+ .cb-line-num {
730
+ color: var(--dim);
731
+ text-align: right;
732
+ font-variant-numeric: tabular-nums;
733
+ user-select: none;
734
+ }
735
+ .cb-line-text {
736
+ color: var(--fg);
737
+ white-space: pre;
738
+ }
739
+ .cb-line--highlight {
740
+ background: color-mix(in srgb, var(--accent) 8%, transparent);
741
+ box-shadow: inset 2px 0 0 var(--accent);
742
+ }
743
+ .cb-line--highlight .cb-line-num { color: var(--accent); }
744
+
745
+ /* ============================================================
746
+ * CodeDiff
747
+ * ============================================================ */
748
+ .codediff {
749
+ width: min(1100px, 94vw);
750
+ background: var(--bg-elevated);
751
+ border: 1px solid var(--dim-2);
752
+ font-family: var(--mono);
753
+ overflow: hidden;
754
+ }
755
+ .cd-head {
756
+ display: flex;
757
+ align-items: center;
758
+ gap: 0.8rem;
759
+ padding: 0.7rem 1rem;
760
+ background: color-mix(in srgb, var(--bg) 60%, var(--bg-elevated));
761
+ border-bottom: 1px solid var(--dim-2);
762
+ font-size: clamp(0.8rem, 1vw, 0.9rem);
763
+ color: var(--dim);
764
+ letter-spacing: 0.04em;
765
+ }
766
+ .cd-file {
767
+ color: var(--fg);
768
+ font-weight: 500;
769
+ }
770
+ .cd-lang {
771
+ font-size: 0.85em;
772
+ text-transform: uppercase;
773
+ letter-spacing: 0.18em;
774
+ color: var(--accent);
775
+ }
776
+ .cd-stats {
777
+ margin-left: auto;
778
+ display: inline-flex;
779
+ gap: 0.7rem;
780
+ font-variant-numeric: tabular-nums;
781
+ }
782
+ .cd-stats .cd-adds { color: var(--accent); }
783
+ .cd-stats .cd-removes { color: var(--red); }
784
+ .cd-body {
785
+ margin: 0;
786
+ padding: clamp(0.8rem, 1.4vw, 1.2rem) 0;
787
+ font-size: clamp(0.85rem, 1.1vw, 1rem);
788
+ line-height: 1.55;
789
+ background: transparent;
790
+ overflow-x: auto;
791
+ white-space: pre;
792
+ }
793
+ .cd-line {
794
+ display: grid;
795
+ grid-template-columns: 2ch 1fr;
796
+ gap: 1rem;
797
+ padding: 0 clamp(0.8rem, 1.4vw, 1.2rem);
798
+ opacity: 0;
799
+ transform: translateX(-4px);
800
+ transition: opacity 400ms ease-out, transform 400ms cubic-bezier(0.16, 1, 0.3, 1);
801
+ }
802
+ .cd-line.in { opacity: 1; transform: translateX(0); }
803
+ .cd-marker {
804
+ font-variant-numeric: tabular-nums;
805
+ user-select: none;
806
+ font-weight: 500;
807
+ }
808
+ .cd-text {
809
+ white-space: pre;
810
+ }
811
+ .cd-line--add {
812
+ background: color-mix(in srgb, var(--accent) 10%, transparent);
813
+ box-shadow: inset 2px 0 0 var(--accent);
814
+ }
815
+ .cd-line--add .cd-marker { color: var(--accent); }
816
+ .cd-line--add .cd-text { color: color-mix(in srgb, var(--accent) 30%, var(--fg)); }
817
+ .cd-line--remove {
818
+ background: color-mix(in srgb, var(--red) 10%, transparent);
819
+ box-shadow: inset 2px 0 0 var(--red);
820
+ }
821
+ .cd-line--remove .cd-marker { color: var(--red); }
822
+ .cd-line--remove .cd-text { color: color-mix(in srgb, var(--red) 30%, var(--fg)); text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--red) 40%, transparent); }
823
+ .cd-line--context .cd-marker { color: var(--dim); }
824
+ .cd-line--context .cd-text { color: var(--dim); }