@scenar/cli 0.4.0 → 0.6.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.
@@ -21,6 +21,12 @@ export interface EmbedEntryInput {
21
21
  canonicalWidth: number;
22
22
  /** Shell height in px, exposed as --scenar-shell-height. */
23
23
  shellHeight: number;
24
+ /**
25
+ * Wrap each step's content in `<ScenarioStage>` (backdrop + window shadow),
26
+ * and paint the backdrop in the static HTML so it shows before the entry
27
+ * script runs. Opt-in: staged embeds give up the transparent canvas.
28
+ */
29
+ stage?: boolean;
24
30
  }
25
31
 
26
32
  /**
@@ -69,6 +75,7 @@ export function generateEmbedEntry(input: EmbedEntryInput): string {
69
75
  "ViewportTransformLayer",
70
76
  "VIEWPORT_TRANSFORM_IDENTITY",
71
77
  ];
78
+ if (input.stage) reactImports.push("ScenarioStage");
72
79
  if (input.hasNarration) reactImports.push("useNarrationManifest");
73
80
  lines.push(`import { ${reactImports.join(", ")} } from "@scenar/react";`);
74
81
  lines.push(`import "@scenar/react/theme.css";`);
@@ -120,13 +127,37 @@ export function generateEmbedEntry(input: EmbedEntryInput): string {
120
127
  lines.push(`})();`);
121
128
  lines.push(`const _rootClass = _theme === "dark" ? SCENAR_CLASS + " dark" : SCENAR_CLASS;`);
122
129
 
130
+ // --- Page canvas: transparent when framed, theme surface when top-level ---
131
+ // The static HTML keeps html/body transparent (see generateEmbedHtml): a
132
+ // framed embed's canvas then shows the *host page's* background through any
133
+ // pixel the tour doesn't paint (aspect-ratio rounding slivers, load-in), so
134
+ // an embed can never flash a white band on a dark docs page. Do NOT pin
135
+ // `document.documentElement.style.colorScheme` to the resolved theme here —
136
+ // the `light dark` meta must stay authoritative, because a scheme mismatch
137
+ // with the framing document is exactly what makes browsers force an opaque
138
+ // white canvas. Top-level (scenar serve verification, direct bundle links)
139
+ // has no host background to show through, so paint the theme surface token
140
+ // for an intentional-looking page instead of the browser's default white.
141
+ // The body gets the scenar root class so `--scenar-surface` resolves there —
142
+ // referencing the token keeps this in lockstep with the palette instead of
143
+ // duplicating hex values that would drift.
144
+ lines.push(``);
145
+ lines.push(`if (window.parent === window) {`);
146
+ lines.push(` document.body.classList.add(..._rootClass.split(" "));`);
147
+ lines.push(` document.body.style.background = "var(--scenar-surface)";`);
148
+ lines.push(`}`);
149
+
123
150
  // --- App tree ---
124
151
  // The structure mirrors the in-app demo wiring exactly (see DemoViewport's
125
- // contract and ViewportTransformLayer's "Cursor must be a sibling" invariant):
152
+ // and ViewportTransformLayer's contracts):
126
153
  // DemoViewport(containerRef)
127
- // └ ViewportTransformLayer(transform)
154
+ // └ ViewportTransformLayer(transform, contentRef=cameraRef)
128
155
  // └ ScenarioPlayer(embed, onStepChange)
129
- // └ Cursor(target, containerRef) ← sibling, not a child
156
+ // └ Cursor(target, containerRef=cameraRef) ← child of the camera
157
+ // The cursor lives INSIDE the camera so it scales and pans with the content
158
+ // during viewport transitions — like a recorded pointer under a camera zoom.
159
+ // Both the cursor and the viewport-transition target math take the camera's
160
+ // contentRef so canonical coordinates stay correct at any camera state.
130
161
  // `useStepInteractions` reads the current step's `interactions` and drives the
131
162
  // cursor / ripple / drag / viewport state, synced to narration duration.
132
163
  const manifestExpr = input.hasNarration ? "_manifest" : "undefined";
@@ -136,6 +167,7 @@ export function generateEmbedEntry(input: EmbedEntryInput): string {
136
167
  lines.push(` const _manifest = useNarrationManifest(${JSON.stringify(input.scenarioId)}, _resolveManifestUrl);`);
137
168
  }
138
169
  lines.push(` const _containerRef = useRef<HTMLDivElement>(null);`);
170
+ lines.push(` const _cameraRef = useRef<HTMLDivElement>(null);`);
139
171
  lines.push(` const [_stepIndex, _setStepIndex] = useState(0);`);
140
172
  lines.push(` const [_cursorTarget, _setCursorTarget] = useState<string | undefined>(undefined);`);
141
173
  lines.push(` const [_showRipple, _setShowRipple] = useState(true);`);
@@ -153,6 +185,7 @@ export function generateEmbedEntry(input: EmbedEntryInput): string {
153
185
  lines.push(` stepIndex: _stepIndex,`);
154
186
  lines.push(` narrationManifest: ${manifestExpr},`);
155
187
  lines.push(` containerRef: _containerRef,`);
188
+ lines.push(` cameraRef: _cameraRef,`);
156
189
  lines.push(` setCursorTarget: _setCursorTarget,`);
157
190
  lines.push(` setShowRipple: _setShowRipple,`);
158
191
  lines.push(` setDragging: _setDragging,`);
@@ -170,13 +203,19 @@ export function generateEmbedEntry(input: EmbedEntryInput): string {
170
203
  lines.push(` return (`);
171
204
  lines.push(` <div className={_rootClass}>`);
172
205
  lines.push(` ${open}`);
206
+ // Staged embeds wrap each step's content — not the player chrome — in the
207
+ // stage, inside the camera, so a zoom scales the whole recording, backdrop
208
+ // included, while controls keep overlaying the stable content box.
209
+ const stepRender = input.stage
210
+ ? `{(data: any, stepIndex: number) => <ScenarioStage>{renderStep(data, stepIndex)}</ScenarioStage>}`
211
+ : `{(data: any, stepIndex: number) => renderStep(data, stepIndex)}`;
173
212
  lines.push(` <DemoViewport containerRef={_containerRef} canonicalWidth={${input.canonicalWidth}} shellHeight={${input.shellHeight}}>`);
174
- lines.push(` <ViewportTransformLayer transform={_viewport}>`);
213
+ lines.push(` <ViewportTransformLayer transform={_viewport} contentRef={_cameraRef}>`);
175
214
  lines.push(` <ScenarioPlayer bundle={_bundle} embed onStepChange={_handleStepChange}>`);
176
- lines.push(` {(data: any, stepIndex: number) => renderStep(data, stepIndex)}`);
215
+ lines.push(` ${stepRender}`);
177
216
  lines.push(` </ScenarioPlayer>`);
217
+ lines.push(` <Cursor target={_cursorTarget} containerRef={_cameraRef} showRipple={_showRipple} isDragging={_dragging} />`);
178
218
  lines.push(` </ViewportTransformLayer>`);
179
- lines.push(` <Cursor target={_cursorTarget} containerRef={_containerRef} showRipple={_showRipple} isDragging={_dragging} />`);
180
219
  lines.push(` </DemoViewport>`);
181
220
  lines.push(` ${close}`);
182
221
  lines.push(` </div>`);
@@ -197,15 +236,54 @@ export function generateEmbedEntry(input: EmbedEntryInput): string {
197
236
  * Produce the index.html that boots the embed. The entry is referenced as an
198
237
  * external module script (`<script type="module" src>`) — never inline — so the
199
238
  * server CSP (`script-src 'self'`) is satisfied without loosening.
239
+ *
240
+ * Canvas contract: the page declares `color-scheme: light dark` and keeps
241
+ * html/body transparent. When the embed is framed by a same-origin host (the
242
+ * shipped stigmer.ai layout), the browser propagates the host's color scheme
243
+ * into the frame; because the embed supports both schemes they always match,
244
+ * so the iframe canvas stays *transparent* — every pixel the tour doesn't
245
+ * paint shows the host page's own background, in both themes, even before the
246
+ * entry script loads. (A scheme mismatch is what makes browsers force an
247
+ * opaque white canvas — the historical "white band under the embed".) The
248
+ * margin reset guards against a host stylesheet-less load; the entry paints a
249
+ * theme surface only when the page is top-level (see generateEmbedEntry).
250
+ *
251
+ * Staged embeds (`--stage`) deliberately trade that transparency away: the
252
+ * scenario floats on a backdrop, so the page pre-paints the same backdrop in
253
+ * static CSS — before the entry script runs — and there is no flash when the
254
+ * React-rendered stage takes over. `light-dark()` keys the pre-paint to the
255
+ * propagated color scheme; the values mirror `--scenar-backdrop` in
256
+ * @scenar/react's theme/tokens.css (the token itself is not loadable before
257
+ * the script, so keep the two in sync when retuning the backdrop). Do NOT
258
+ * pin `colorScheme` here either — the `light dark` meta stays authoritative.
200
259
  */
201
- export function generateEmbedHtml(scenarioId: string, entryFileName: string): string {
260
+ export function generateEmbedHtml(
261
+ scenarioId: string,
262
+ entryFileName: string,
263
+ stage = false,
264
+ ): string {
265
+ const bodyBackground = stage
266
+ ? [
267
+ ` body {`,
268
+ ` background: light-dark(`,
269
+ ` linear-gradient(135deg, #e7ebf1 0%, #dde3ec 55%, #d3dae6 100%),`,
270
+ ` linear-gradient(135deg, #16202f 0%, #101827 55%, #0b111d 100%)`,
271
+ ` );`,
272
+ ` }`,
273
+ ]
274
+ : [];
202
275
  return [
203
276
  `<!doctype html>`,
204
277
  `<html lang="en">`,
205
278
  ` <head>`,
206
279
  ` <meta charset="utf-8" />`,
207
280
  ` <meta name="viewport" content="width=device-width, initial-scale=1" />`,
281
+ ` <meta name="color-scheme" content="light dark" />`,
208
282
  ` <title>${escapeHtml(scenarioId)}</title>`,
283
+ ` <style>`,
284
+ ` html, body { margin: 0; background: transparent; }`,
285
+ ...bodyBackground,
286
+ ` </style>`,
209
287
  ` </head>`,
210
288
  ` <body>`,
211
289
  ` <div id="root"></div>`,
@@ -9,6 +9,12 @@ export interface RunPackOptions {
9
9
  readonly width?: number;
10
10
  /** Shell/container height in px (default: {@link DEFAULT_VIEWPORT}.height). */
11
11
  readonly shellHeight?: number;
12
+ /**
13
+ * Float the scenario on a backdrop with a window shadow (screen-recording
14
+ * framing). Opt-in: a staged embed paints its own background, giving up
15
+ * the default transparent canvas that lets the host page show through.
16
+ */
17
+ readonly stage?: boolean;
12
18
  /** Keep the generated entry directory for debugging (default: false). */
13
19
  readonly keepTemp?: boolean;
14
20
  /** Progress sink for mid-operation messages. */
@@ -1 +1 @@
1
- {"version":3,"file":"run-pack.d.ts","sourceRoot":"","sources":["../../../src/pack/run-pack.ts"],"names":[],"mappings":"AAOA,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAM5B,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CAyF1E"}
1
+ {"version":3,"file":"run-pack.d.ts","sourceRoot":"","sources":["../../../src/pack/run-pack.ts"],"names":[],"mappings":"AAOA,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAM5B,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CA2F1E"}
@@ -43,6 +43,7 @@ export async function runPack(options) {
43
43
  onLog(`Narration: ${hasNarration ? "yes (manifest found)" : "none"}`);
44
44
  onLog(`Output: ${outDir}`);
45
45
  // 1. Generate the browser entry + index.html into the temp dir.
46
+ const stage = options.stage ?? false;
46
47
  const entrySource = generateEmbedEntry({
47
48
  scenarioDir,
48
49
  renderFilePath,
@@ -51,12 +52,13 @@ export async function runPack(options) {
51
52
  providersPath,
52
53
  canonicalWidth: width,
53
54
  shellHeight,
55
+ stage,
54
56
  });
55
57
  await mkdir(tempDir, { recursive: true });
56
58
  const entryFileName = "entry.tsx";
57
59
  const entryHtmlPath = join(tempDir, "index.html");
58
60
  await writeFile(join(tempDir, entryFileName), entrySource, "utf-8");
59
- await writeFile(entryHtmlPath, generateEmbedHtml(scenarioId, entryFileName), "utf-8");
61
+ await writeFile(entryHtmlPath, generateEmbedHtml(scenarioId, entryFileName, stage), "utf-8");
60
62
  // 2. Build the static bundle with Vite.
61
63
  onLog("Bundling embed with Vite...");
62
64
  await runViteBuild({ root: tempDir, outDir, entryHtmlPath });
@@ -1 +1 @@
1
- {"version":3,"file":"run-pack.js","sourceRoot":"","sources":["../../../src/pack/run-pack.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run-pack.js","sourceRoot":"","sources":["../../../src/pack/run-pack.ts"],"names":[],"mappings":"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"}
@@ -27,6 +27,12 @@ export interface RunPackOptions {
27
27
  readonly width?: number;
28
28
  /** Shell/container height in px (default: {@link DEFAULT_VIEWPORT}.height). */
29
29
  readonly shellHeight?: number;
30
+ /**
31
+ * Float the scenario on a backdrop with a window shadow (screen-recording
32
+ * framing). Opt-in: a staged embed paints its own background, giving up
33
+ * the default transparent canvas that lets the host page show through.
34
+ */
35
+ readonly stage?: boolean;
30
36
  /** Keep the generated entry directory for debugging (default: false). */
31
37
  readonly keepTemp?: boolean;
32
38
  /** Progress sink for mid-operation messages. */
@@ -86,6 +92,7 @@ export async function runPack(options: RunPackOptions): Promise<PackResult> {
86
92
  onLog(`Output: ${outDir}`);
87
93
 
88
94
  // 1. Generate the browser entry + index.html into the temp dir.
95
+ const stage = options.stage ?? false;
89
96
  const entrySource = generateEmbedEntry({
90
97
  scenarioDir,
91
98
  renderFilePath,
@@ -94,12 +101,13 @@ export async function runPack(options: RunPackOptions): Promise<PackResult> {
94
101
  providersPath,
95
102
  canonicalWidth: width,
96
103
  shellHeight,
104
+ stage,
97
105
  });
98
106
  await mkdir(tempDir, { recursive: true });
99
107
  const entryFileName = "entry.tsx";
100
108
  const entryHtmlPath = join(tempDir, "index.html");
101
109
  await writeFile(join(tempDir, entryFileName), entrySource, "utf-8");
102
- await writeFile(entryHtmlPath, generateEmbedHtml(scenarioId, entryFileName), "utf-8");
110
+ await writeFile(entryHtmlPath, generateEmbedHtml(scenarioId, entryFileName, stage), "utf-8");
103
111
 
104
112
  // 2. Build the static bundle with Vite.
105
113
  onLog("Bundling embed with Vite...");
@@ -19,7 +19,13 @@ export interface Viewport {
19
19
  /** Shell/container height in px (ViewportConfig.height; CLI `--shell-height`). */
20
20
  readonly height: number;
21
21
  }
22
- /** Defaults matching `DemoViewport`: 896 canonical width, 480 shell height. */
22
+ /**
23
+ * Pack-time defaults. The width matches `DemoViewport`'s default canonical
24
+ * width (896); the height is the CLI's own default — `DemoViewport` has no
25
+ * height default of its own, and the baked `--scenar-shell-height` variable
26
+ * overrides every per-shell fallback in `@scenar/react`'s `shells/tokens.ts`
27
+ * (380/420/460/500), so this number is what framed shells actually render at.
28
+ */
23
29
  export declare const DEFAULT_VIEWPORT: Viewport;
24
30
  /**
25
31
  * Narrow unknown JSON into a {@link Viewport}, or null if it is missing or
@@ -1 +1 @@
1
- {"version":3,"file":"viewport.d.ts","sourceRoot":"","sources":["../../../src/pack/viewport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,QAAQ;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,EAAE,QAAsC,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAK7D"}
1
+ {"version":3,"file":"viewport.d.ts","sourceRoot":"","sources":["../../../src/pack/viewport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,QAAQ;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAsC,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAK7D"}
@@ -1,4 +1,10 @@
1
- /** Defaults matching `DemoViewport`: 896 canonical width, 480 shell height. */
1
+ /**
2
+ * Pack-time defaults. The width matches `DemoViewport`'s default canonical
3
+ * width (896); the height is the CLI's own default — `DemoViewport` has no
4
+ * height default of its own, and the baked `--scenar-shell-height` variable
5
+ * overrides every per-shell fallback in `@scenar/react`'s `shells/tokens.ts`
6
+ * (380/420/460/500), so this number is what framed shells actually render at.
7
+ */
2
8
  export const DEFAULT_VIEWPORT = { width: 896, height: 480 };
3
9
  /**
4
10
  * Narrow unknown JSON into a {@link Viewport}, or null if it is missing or
@@ -1 +1 @@
1
- {"version":3,"file":"viewport.js","sourceRoot":"","sources":["../../../src/pack/viewport.ts"],"names":[],"mappings":"AAsBA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAAa,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAEtE;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAgC,CAAC;IAC3D,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACjE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC3B,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;AAC3E,CAAC"}
1
+ {"version":3,"file":"viewport.js","sourceRoot":"","sources":["../../../src/pack/viewport.ts"],"names":[],"mappings":"AAsBA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAa,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAEtE;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAgC,CAAC;IAC3D,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACjE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC3B,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;AAC3E,CAAC"}
@@ -20,7 +20,13 @@ export interface Viewport {
20
20
  readonly height: number;
21
21
  }
22
22
 
23
- /** Defaults matching `DemoViewport`: 896 canonical width, 480 shell height. */
23
+ /**
24
+ * Pack-time defaults. The width matches `DemoViewport`'s default canonical
25
+ * width (896); the height is the CLI's own default — `DemoViewport` has no
26
+ * height default of its own, and the baked `--scenar-shell-height` variable
27
+ * overrides every per-shell fallback in `@scenar/react`'s `shells/tokens.ts`
28
+ * (380/420/460/500), so this number is what framed shells actually render at.
29
+ */
24
30
  export const DEFAULT_VIEWPORT: Viewport = { width: 896, height: 480 };
25
31
 
26
32
  /**