@volter/editor-game 0.5.67 → 0.5.69

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 (173) hide show
  1. package/NOTICE +7 -7
  2. package/contributions/autoplay.service.ts +1 -1
  3. package/contributions/build-player.document.tsx +95 -0
  4. package/contributions/build-profiles.document.tsx +1 -1
  5. package/contributions/build-progress.status.tsx +2 -2
  6. package/contributions/build.header.tsx +1 -1
  7. package/contributions/connection.status.tsx +1 -1
  8. package/contributions/coverage.service.ts +2 -2
  9. package/contributions/game-eval.command.ts +6 -6
  10. package/contributions/gameplay.command.ts +2 -2
  11. package/contributions/generations.status.tsx +1 -1
  12. package/contributions/ingest.service.ts +2 -2
  13. package/contributions/play.command.ts +6 -6
  14. package/contributions/react/react-inspector.service.ts +1 -1
  15. package/package.json +9 -8
  16. package/serving/index.ts +1 -1
  17. package/src/asset-budget/AssetBudgetPanel.tsx +1 -1
  18. package/src/asset-budget/asset-budget-model.ts +14 -14
  19. package/src/asset-budget/optimize-apply.ts +8 -8
  20. package/src/bridge/call.ts +3 -3
  21. package/src/bridge/dispatch.ts +12 -12
  22. package/src/bridge/screenshot.ts +6 -6
  23. package/src/build/BuildProfilesPanel.tsx +19 -8
  24. package/src/build/build-session.ts +35 -0
  25. package/src/canvas/canvas-board/CanvasBoardDocument.tsx +78 -5
  26. package/src/canvas/canvas-board/canvas-component-board.ts +1 -1
  27. package/src/canvas/canvas-design-mount.ts +1 -1
  28. package/src/coverage/live-project-verbs.ts +3 -3
  29. package/src/coverage/native-system-coverage.ts +3 -3
  30. package/src/coverage/root-coverage.ts +2 -2
  31. package/src/coverage/session-coverage.ts +2 -2
  32. package/src/design-system-stories/InspectorNarrowBodies.stories.tsx +2 -2
  33. package/src/game-document/DevicePresetPicker.tsx +6 -6
  34. package/src/game-document/GameCaptureFrameButton.tsx +1 -1
  35. package/src/game-document/GameDocument.tsx +2 -2
  36. package/src/game-document/GamePanel.tsx +9 -9
  37. package/src/game-document/InstanceInspectorPicker.tsx +1 -1
  38. package/src/game-document/device-preview.ts +4 -4
  39. package/src/game-document/physics-debug.ts +2 -2
  40. package/src/generation/GenerationActivity.tsx +22 -22
  41. package/src/generation/GenerationGallery.css +79 -79
  42. package/src/generation/generation-documents.tsx +25 -25
  43. package/src/generation/generation-presentation.ts +1 -1
  44. package/src/host/adapter-reach.ts +1 -1
  45. package/src/host/adapter-runtime-bindings.ts +5 -5
  46. package/src/host/after-paint.ts +3 -3
  47. package/src/host/api/configurations.ts +1 -1
  48. package/src/host/authoring/canvas-runtime-recognition.ts +2 -2
  49. package/src/host/authoring/contract-hierarchy-authoring.ts +6 -6
  50. package/src/host/authoring/contract-scenes-stories.ts +5 -5
  51. package/src/host/authoring/ingest-data-writer.ts +1 -1
  52. package/src/host/authoring/ingest-source-persistence.ts +2 -2
  53. package/src/host/authoring/mount-isolated-pixi-screen.ts +1 -1
  54. package/src/host/authoring/pixi-authoring-adapter.ts +206 -28
  55. package/src/host/authoring/pixi-creatable-kinds.ts +80 -0
  56. package/src/host/authoring/pixi-live-write-target.ts +6 -5
  57. package/src/host/authoring/pixi-source-write-target.ts +118 -20
  58. package/src/host/authoring/pixi-structure-history.ts +3 -3
  59. package/src/host/binding-resolver.ts +6 -6
  60. package/src/host/browser-transpile.ts +10 -10
  61. package/src/host/canvas-preview-frames.ts +1 -1
  62. package/src/host/components/CameraAuthoringOverlay.tsx +14 -14
  63. package/src/host/components/HeaderTelemetry.tsx +11 -11
  64. package/src/host/components/PixiIsolationSceneContent.tsx +3 -3
  65. package/src/host/components/ResolutionPicker.tsx +4 -4
  66. package/src/host/components/scene-document.tsx +3 -3
  67. package/src/host/components/world-root-stage-binding.tsx +1 -1
  68. package/src/host/components/world-root-stage.ts +1 -1
  69. package/src/host/coverage/authoring-read-probe.ts +1 -1
  70. package/src/host/coverage/capability-coverage.ts +22 -22
  71. package/src/host/coverage/game-contract-seam-evidence.ts +8 -8
  72. package/src/host/coverage/project-verb-coverage.ts +1 -1
  73. package/src/host/coverage/system-adapter-coverage.ts +19 -6
  74. package/src/host/game-location-guard.ts +3 -3
  75. package/src/host/game-module-access.ts +6 -6
  76. package/src/host/game-realm-page.ts +3 -3
  77. package/src/host/game-realm-reclaim.ts +1 -1
  78. package/src/host/gameplay-recording.ts +5 -5
  79. package/src/host/gated-globals.ts +13 -13
  80. package/src/host/ingest/registry.ts +14 -14
  81. package/src/host/play-control-hook.ts +1 -1
  82. package/src/host/playwright-shim.ts +2 -2
  83. package/src/host/projection/pixi.ts +2 -2
  84. package/src/host/react-mount-runtime.ts +1 -1
  85. package/src/host/roots/canvas-root.tsx +13 -1
  86. package/src/host/roots/r3f-root.tsx +1 -1
  87. package/src/host/scene-view-drawability.ts +1 -1
  88. package/src/host/sdk/tools.ts +1 -1
  89. package/src/host/served-bundle-runtime-modules.ts +2 -0
  90. package/src/host/staged-projects.ts +1 -1
  91. package/src/host/stories/story-pixi-preview.ts +1 -1
  92. package/src/host/stories/story-three-preview.ts +1 -1
  93. package/src/host/three-ingest-runtime.ts +1 -1
  94. package/src/ingest/active-ingest.ts +1 -1
  95. package/src/ingest/authoring/ingest-dom-surface-authoring.ts +4 -4
  96. package/src/ingest/authoring/ingest-root-adapter.ts +11 -11
  97. package/src/ingest/capture-wait-report.ts +4 -4
  98. package/src/ingest/discovery-public-ingest.ts +4 -4
  99. package/src/ingest/dom-stub-mark.ts +1 -1
  100. package/src/ingest/entry-load.ts +1 -1
  101. package/src/ingest/game-contract-realm.ts +3 -3
  102. package/src/ingest/game-pointer-lock.ts +1 -1
  103. package/src/ingest/ingest-canvas-scene-document.tsx +3 -3
  104. package/src/ingest/ingest-evidence-hook.ts +6 -6
  105. package/src/ingest/ingest-frame-snapshot.ts +2 -2
  106. package/src/ingest/ingest-play-commands.ts +1 -1
  107. package/src/ingest/ingest-play-control.ts +11 -11
  108. package/src/ingest/ingest-render-debug.ts +5 -5
  109. package/src/ingest/ingest-siblings.ts +3 -3
  110. package/src/ingest/module-mode.ts +2 -2
  111. package/src/ingest/mount-canvas-ingest-root.ts +10 -10
  112. package/src/ingest/mount-coverage.ts +3 -3
  113. package/src/ingest/mount-dom-ingest-root.ts +7 -7
  114. package/src/ingest/mount-ingest-root.ts +10 -10
  115. package/src/ingest/mount-three-ingest-root.ts +5 -5
  116. package/src/ingest/resolve-three.ts +2 -2
  117. package/src/ingest/served-bundle.ts +6 -6
  118. package/src/ingest/served-html-boot.ts +8 -8
  119. package/src/ingest/surface-dom.ts +9 -9
  120. package/src/ingest/surface-three.ts +1 -1
  121. package/src/ingest/types.ts +1 -1
  122. package/src/ingest/unmount-ingest-root.ts +3 -3
  123. package/src/network/NetworkInspectorPanel.tsx +521 -54
  124. package/src/network/network-inspector-model.ts +6 -0
  125. package/src/play/play-boot-stall.ts +1 -1
  126. package/src/play/play-mode.ts +31 -30
  127. package/src/play/play-recording.ts +12 -12
  128. package/src/play-bar/PlayBar.tsx +8 -8
  129. package/src/play-bar/PlayerCountPicker.tsx +3 -3
  130. package/src/profiler/FrameDebuggerPanel.tsx +2 -2
  131. package/src/profiler/PerformancePanel.tsx +4 -4
  132. package/src/react/design-time-react-mount.ts +5 -5
  133. package/src/react/dom-authoring-adapter.ts +3 -3
  134. package/src/react/react-inspector-section.tsx +2 -2
  135. package/src/react/react-world-authoring-adapter.ts +20 -20
  136. package/src/react/story-documents/story-documents.tsx +4 -4
  137. package/src/react/ui-component-board.ts +1 -1
  138. package/src/runtime/adapter/audio-meter.ts +1 -1
  139. package/src/runtime/adapter/ingest/contract-debug-adapter.ts +4 -4
  140. package/src/runtime/adapter/ingest/contract-system-adapters.ts +9 -9
  141. package/src/runtime/adapter/ingest/merge-debug-adapters.ts +2 -2
  142. package/src/runtime/adapter/ingest/observation-debug-adapter.ts +1 -1
  143. package/src/runtime/adapter/native-debug-module.ts +5 -5
  144. package/src/runtime/audio/pose-guard.ts +1 -1
  145. package/src/runtime/core/game-scoped-slot.ts +1 -1
  146. package/src/runtime/create-runtime.ts +15 -15
  147. package/src/runtime/debug-bridge.ts +25 -25
  148. package/src/runtime/debug-registry.ts +17 -17
  149. package/src/runtime/dev/instruments.ts +1 -1
  150. package/src/runtime/dev/performance-profiler.ts +2 -2
  151. package/src/runtime/dev/register-render-vitals.ts +2 -2
  152. package/src/runtime/dev/static-batch-advisor.ts +3 -3
  153. package/src/runtime/dev-build.ts +3 -3
  154. package/src/runtime/game.ts +5 -5
  155. package/src/runtime/input-router.ts +24 -11
  156. package/src/runtime/mount-manifest.ts +9 -9
  157. package/src/runtime/pixi/authoring.ts +1 -1
  158. package/src/runtime/pixi/ingest.ts +1 -1
  159. package/src/runtime/presentation.ts +1 -1
  160. package/src/runtime/render-control.ts +21 -21
  161. package/src/runtime/render-seed.ts +3 -3
  162. package/src/runtime/run-ticks-settled.ts +1 -1
  163. package/src/services/game-audio.ts +3 -3
  164. package/src/services/game-network.ts +125 -15
  165. package/src/three/authoring/model-asset-inspector-section.css +15 -15
  166. package/src/three/authoring/model-asset-inspector-section.tsx +7 -7
  167. package/src/three/authoring/r3f-design-session.ts +10 -10
  168. package/src/three/authoring/r3f-source-authoring-adapter.ts +5 -5
  169. package/src/three/authoring/three-authoring-adapter.ts +5 -4
  170. package/src/three/authoring/typed-three-inspector.ts +1 -1
  171. package/src/three/story-documents/three-story-documents.tsx +3 -3
  172. package/src/three/three-board/board-scene.ts +9 -9
  173. package/src/three/three-board/three-component-board.ts +1 -1
@@ -138,7 +138,7 @@ export function InstanceInspectorPicker() {
138
138
  const warning = (diagnostics?.loop.firedWhileHeld ?? 0) > 0;
139
139
 
140
140
  return (
141
- <div className="vgai-playbar-popover-anchor">
141
+ <div className="volter-playbar-popover-anchor">
142
142
  <Button
143
143
  ref={ref}
144
144
  variant="ghost"
@@ -12,8 +12,8 @@
12
12
  * sets CSS custom properties on the game mount container
13
13
  * (`data-testid="game-runtime-container"`), the element game canvases and
14
14
  * react-world DOM layers mount into:
15
- * --vgai-safe-area-inset-top / -right / -bottom / -left (CSS px)
16
- * Game UI reads them with `var(--vgai-safe-area-inset-top, 0px)`.
15
+ * --volter-safe-area-inset-top / -right / -bottom / -left (CSS px)
16
+ * Game UI reads them with `var(--volter-safe-area-inset-top, 0px)`.
17
17
  * Recorded choice: real `env(safe-area-inset-*)` injection is NOT
18
18
  * possible from a same-document host (env() values come from the UA for
19
19
  * the top-level viewport only), so the overlay + CSS vars ARE the
@@ -41,7 +41,7 @@
41
41
  * event before the clone.
42
42
  *
43
43
  * Persistence: preset + touch override are the PROJECT settings layer's
44
- * `devicePreview` (`settings-store.ts` → `.vgai/settings.json`, committed):
44
+ * `devicePreview` (`settings-store.ts` → `.volter/settings.json`, committed):
45
45
  * the frame a game is designed for is a fact about the project, shared by
46
46
  * everyone who opens it.
47
47
  */
@@ -331,5 +331,5 @@ function _stateForE2E() {
331
331
  }
332
332
 
333
333
  if (typeof window !== 'undefined') {
334
- (window as unknown as Record<string, unknown>)['__vgaiDevicePreview'] = _stateForE2E;
334
+ (window as unknown as Record<string, unknown>)['__volterDevicePreview'] = _stateForE2E;
335
335
  }
@@ -136,7 +136,7 @@ function _updateContactPoints(group: THREE.Group, contacts: Float32Array | null)
136
136
  }
137
137
 
138
138
  /**
139
- * e2e hook (mirrors the world root's stage's `__vgaiViewport`): mechanical state for
139
+ * e2e hook (mirrors the world root's stage's `__volterViewport`): mechanical state for
140
140
  * The question this answers — is the Rapier debug wireframe live in the
141
141
  * game scene with real geometry, and how many contact markers are drawn.
142
142
  */
@@ -167,7 +167,7 @@ function _stateForE2E(): {
167
167
  };
168
168
  }
169
169
  if (typeof window !== 'undefined') {
170
- (window as unknown as Record<string, unknown>)['__vgaiPhysicsDebug'] = _stateForE2E;
170
+ (window as unknown as Record<string, unknown>)['__volterPhysicsDebug'] = _stateForE2E;
171
171
  }
172
172
 
173
173
  function _teardown(): void {
@@ -70,13 +70,13 @@ function OutputPreview({
70
70
 
71
71
  if (src && output.kind === 'image') {
72
72
  const preview = (
73
- <img className="vgai-generation-output-media" src={src} alt={output.name} loading="lazy" />
73
+ <img className="volter-generation-output-media" src={src} alt={output.name} loading="lazy" />
74
74
  );
75
75
  return onOpen ? (
76
76
  // The preview itself opens the asset — the gesture a gallery implies.
77
77
  <Button
78
78
  variant="ghost"
79
- className="vgai-generation-output-open"
79
+ className="volter-generation-output-open"
80
80
  onClick={onOpen}
81
81
  aria-label={`Open ${output.name}`}
82
82
  >
@@ -91,7 +91,7 @@ function OutputPreview({
91
91
  // Deliberately no autoplay and no `muted` autoplay trick: a gallery that
92
92
  // starts sound is the failure this panel is replacing.
93
93
  <video
94
- className="vgai-generation-output-media"
94
+ className="volter-generation-output-media"
95
95
  src={src}
96
96
  controls
97
97
  preload="metadata"
@@ -102,7 +102,7 @@ function OutputPreview({
102
102
  }
103
103
  if (src && output.kind === 'audio') {
104
104
  return (
105
- <div className="vgai-generation-output-audio">
105
+ <div className="volter-generation-output-audio">
106
106
  <AudioAssetThumb url={src} name={output.name} />
107
107
  <audio src={src} controls preload="metadata" title={output.name} />
108
108
  </div>
@@ -112,7 +112,7 @@ function OutputPreview({
112
112
  return <ModelThumbnail url={output.url} />;
113
113
  }
114
114
  return (
115
- <div className="vgai-generation-output-file">
115
+ <div className="volter-generation-output-file">
116
116
  <EditorIcon icon={output.kind === 'model' ? faFile : faFileLines} />
117
117
  <Text variant="caption" tone="muted">
118
118
  {output.name}
@@ -160,7 +160,7 @@ function StateMedia({ job, state }: { job: GenerationJob; state: GenerationCardS
160
160
  const pending = state === 'queued' || state === 'running' || state === 'saving';
161
161
  const failing = state === 'failed' || state === 'save-failed';
162
162
  return (
163
- <div className="vgai-generation-state-media" data-state={state}>
163
+ <div className="volter-generation-state-media" data-state={state}>
164
164
  <StateSurface
165
165
  compact
166
166
  tone={STATE_TONE[state]}
@@ -172,7 +172,7 @@ function StateMedia({ job, state }: { job: GenerationJob; state: GenerationCardS
172
172
  // Determinate ONLY when the provider reported progress; otherwise the
173
173
  // native indeterminate bar, which claims nothing.
174
174
  <progress
175
- className="vgai-generation-progress"
175
+ className="volter-generation-progress"
176
176
  aria-label={`${job.label} progress`}
177
177
  {...(state === 'running' && job.progress !== undefined
178
178
  ? { value: job.progress, max: 1 }
@@ -195,7 +195,7 @@ function CardActions({
195
195
  run: (action: () => Promise<void>) => void;
196
196
  }) {
197
197
  return (
198
- <div className="vgai-generation-card-actions">
198
+ <div className="volter-generation-card-actions">
199
199
  {generationSaveRetryable(job, error) && (
200
200
  // There is NO add-to-project gate: the server accepts a finished
201
201
  // output on its own. This appears only once a save has actually
@@ -250,7 +250,7 @@ function GenerationCard({
250
250
 
251
251
  return (
252
252
  <article
253
- className="vgai-generation-card"
253
+ className="volter-generation-card"
254
254
  data-state={state}
255
255
  aria-busy={generationJobIsActive(job)}
256
256
  aria-label={generationTitle(job)}
@@ -265,31 +265,31 @@ function GenerationCard({
265
265
  }
266
266
  }}
267
267
  >
268
- <div className="vgai-generation-card-media" data-outputs={Math.min(outputs.length, 4)}>
268
+ <div className="volter-generation-card-media" data-outputs={Math.min(outputs.length, 4)}>
269
269
  {outputs.length === 0 ? (
270
270
  <StateMedia job={job} state={state} />
271
271
  ) : (
272
272
  outputs.map((output) => (
273
- <div className="vgai-generation-output" key={output.path} title={output.path}>
273
+ <div className="volter-generation-output" key={output.path} title={output.path}>
274
274
  <OutputPreview output={output} onOpen={openOutput(output)} />
275
275
  </div>
276
276
  ))
277
277
  )}
278
278
  </div>
279
279
 
280
- <div className="vgai-generation-card-body">
281
- <div className="vgai-generation-card-heading">
280
+ <div className="volter-generation-card-body">
281
+ <div className="volter-generation-card-heading">
282
282
  <Text variant="label" truncate title={generationTitle(job)}>
283
283
  {generationTitle(job)}
284
284
  </Text>
285
- <EditorBadge className="vgai-generation-chip" data-state={state}>
285
+ <EditorBadge className="volter-generation-chip" data-state={state}>
286
286
  {GENERATION_STATE_LABEL[state]}
287
287
  {state === 'running' && job.progress !== undefined
288
288
  ? ` · ${Math.round(job.progress * 100)}%`
289
289
  : ''}
290
290
  </EditorBadge>
291
291
  {unread && (
292
- <EditorBadge className="vgai-generation-chip" data-state="new">
292
+ <EditorBadge className="volter-generation-chip" data-state="new">
293
293
  New
294
294
  </EditorBadge>
295
295
  )}
@@ -305,7 +305,7 @@ function GenerationCard({
305
305
  </Text>
306
306
 
307
307
  {prompt && (
308
- <p className="vgai-generation-card-prompt" title={prompt}>
308
+ <p className="volter-generation-card-prompt" title={prompt}>
309
309
  {prompt}
310
310
  </p>
311
311
  )}
@@ -317,7 +317,7 @@ function GenerationCard({
317
317
  // text promises nothing and the retry button carries it instead.
318
318
  <EditorBanner
319
319
  tone={error || state === 'save-failed' ? 'error' : 'warning'}
320
- className="vgai-generation-card-alert"
320
+ className="volter-generation-card-alert"
321
321
  >
322
322
  {error ??
323
323
  (state === 'save-failed'
@@ -363,8 +363,8 @@ export function GenerationActivity() {
363
363
  const storeError = generationJobsError();
364
364
 
365
365
  return (
366
- <div className="vgai-generation-gallery">
367
- <EditorToolbar label="Generations" compact className="vgai-generation-gallery-bar">
366
+ <div className="volter-generation-gallery">
367
+ <EditorToolbar label="Generations" compact className="volter-generation-gallery-bar">
368
368
  <Text variant="label">Generations</Text>
369
369
  <Text variant="caption" tone="muted">
370
370
  {jobs.length} {jobs.length === 1 ? 'generation' : 'generations'}
@@ -385,14 +385,14 @@ export function GenerationActivity() {
385
385
  </EditorToolbar>
386
386
 
387
387
  {storeError && (
388
- <EditorBanner tone="error" className="vgai-generation-gallery-alert">
388
+ <EditorBanner tone="error" className="volter-generation-gallery-alert">
389
389
  {storeError}
390
390
  </EditorBanner>
391
391
  )}
392
392
 
393
393
  {jobs.length === 0 ? (
394
394
  <StateSurface
395
- className="vgai-generation-gallery-empty"
395
+ className="volter-generation-gallery-empty"
396
396
  title="No generated assets yet"
397
397
  description="Preview generated images, video, audio and models here. Create an asset to get started."
398
398
  action={
@@ -402,7 +402,7 @@ export function GenerationActivity() {
402
402
  }
403
403
  />
404
404
  ) : (
405
- <section className="vgai-generation-grid" aria-label="Generated assets">
405
+ <section className="volter-generation-grid" aria-label="Generated assets">
406
406
  {jobs.map((job) => (
407
407
  <GenerationCard
408
408
  key={job.id}
@@ -7,66 +7,66 @@
7
7
  * query drops the card to a single readable column in a genuinely narrow dock.
8
8
  */
9
9
 
10
- .vgai-generation-gallery {
10
+ .volter-generation-gallery {
11
11
  display: flex;
12
12
  height: 100%;
13
13
  flex-direction: column;
14
- color: var(--vgai-content-primary);
14
+ color: var(--volter-content-primary);
15
15
  /* `size`, not `inline-size`: the cards answer to the drawer's HEIGHT as well
16
16
  * as its width — a short bottom drawer gets a shorter preview so the name,
17
17
  * cost and actions still land inside it. */
18
18
  container-type: size;
19
19
  }
20
- .vgai-generation-gallery .vgai-toolbar {
20
+ .volter-generation-gallery .volter-toolbar {
21
21
  flex: 0 0 auto;
22
22
  }
23
- .vgai-generation-gallery-bar {
24
- gap: var(--vgai-space-2);
23
+ .volter-generation-gallery-bar {
24
+ gap: var(--volter-space-2);
25
25
  }
26
- .vgai-generation-gallery-alert {
27
- margin: var(--vgai-space-3);
26
+ .volter-generation-gallery-alert {
27
+ margin: var(--volter-space-3);
28
28
  }
29
- .vgai-generation-gallery-empty {
29
+ .volter-generation-gallery-empty {
30
30
  margin: auto;
31
31
  max-width: 420px;
32
32
  text-align: center;
33
33
  }
34
34
 
35
- .vgai-generation-grid {
35
+ .volter-generation-grid {
36
36
  display: grid;
37
37
  min-height: 0;
38
38
  flex: 1;
39
39
  align-content: start;
40
- gap: var(--vgai-space-3);
41
- padding: var(--vgai-space-3);
40
+ gap: var(--volter-space-3);
41
+ padding: var(--volter-space-3);
42
42
  overflow-y: auto;
43
43
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
44
44
  grid-auto-rows: max-content;
45
45
  }
46
46
  @container (max-width: 380px) {
47
- .vgai-generation-grid {
47
+ .volter-generation-grid {
48
48
  grid-template-columns: 1fr;
49
49
  }
50
50
  }
51
- .vgai-generation-card {
51
+ .volter-generation-card {
52
52
  display: flex;
53
53
  flex-direction: column;
54
54
  overflow: hidden;
55
- border: var(--vgai-stroke-resting) solid var(--vgai-boundary-default);
56
- border-radius: var(--vgai-radius-md);
57
- background: var(--vgai-surface-panel);
55
+ border: var(--volter-stroke-resting) solid var(--volter-boundary-default);
56
+ border-radius: var(--volter-radius-md);
57
+ background: var(--volter-surface-panel);
58
58
  }
59
- .vgai-generation-card[data-state="failed"],
60
- .vgai-generation-card[data-state="save-failed"] {
61
- border-color: var(--vgai-danger-muted);
59
+ .volter-generation-card[data-state="failed"],
60
+ .volter-generation-card[data-state="save-failed"] {
61
+ border-color: var(--volter-danger-muted);
62
62
  }
63
- .vgai-generation-card[data-state="ready"] {
64
- border-color: var(--vgai-boundary-strong);
63
+ .volter-generation-card[data-state="ready"] {
64
+ border-color: var(--volter-boundary-strong);
65
65
  }
66
66
 
67
67
  /* The preview. One output fills the box; several share it as a tile grid, so a
68
68
  * multi-output job shows every file it produced without a second surface. */
69
- .vgai-generation-card-media {
69
+ .volter-generation-card-media {
70
70
  display: grid;
71
71
  /* `flex-shrink: 0` and the height cap are load-bearing TOGETHER: in the
72
72
  * ordinary ~260px bottom drawer the card was squeezed to a ~50px strip with
@@ -75,38 +75,38 @@
75
75
  flex-shrink: 0;
76
76
  height: 160px;
77
77
  max-height: 160px;
78
- gap: var(--vgai-stroke-active);
79
- background: var(--vgai-bg-inset);
78
+ gap: var(--volter-stroke-active);
79
+ background: var(--volter-bg-inset);
80
80
  grid-template-columns: 1fr;
81
81
  }
82
- .vgai-generation-card-media[data-outputs="2"],
83
- .vgai-generation-card-media[data-outputs="3"],
84
- .vgai-generation-card-media[data-outputs="4"] {
82
+ .volter-generation-card-media[data-outputs="2"],
83
+ .volter-generation-card-media[data-outputs="3"],
84
+ .volter-generation-card-media[data-outputs="4"] {
85
85
  grid-template-columns: 1fr 1fr;
86
86
  }
87
- .vgai-generation-output {
87
+ .volter-generation-output {
88
88
  display: flex;
89
89
  min-width: 0;
90
90
  min-height: 0;
91
91
  align-items: center;
92
92
  justify-content: center;
93
93
  overflow: hidden;
94
- padding: var(--vgai-space-1);
94
+ padding: var(--volter-space-1);
95
95
  }
96
96
  /* `contain`, never `cover`: cropping a generated frame hides exactly the part
97
97
  * a game developer is judging. */
98
- .vgai-generation-output-media {
98
+ .volter-generation-output-media {
99
99
  display: block;
100
100
  width: 100%;
101
101
  height: 100%;
102
102
  max-width: 100%;
103
103
  max-height: 100%;
104
- border-radius: var(--vgai-radius-sm);
104
+ border-radius: var(--volter-radius-sm);
105
105
  object-fit: contain;
106
106
  }
107
107
  /* The preview's own click target: a real Button stripped back to the image it
108
108
  * contains, so the gallery's most obvious gesture is still a focusable control. */
109
- .vgai-generation-output .vgai-generation-output-open.vgai-btn {
109
+ .volter-generation-output .volter-generation-output-open.volter-btn {
110
110
  display: flex;
111
111
  width: 100%;
112
112
  height: 100%;
@@ -119,113 +119,113 @@
119
119
  background: transparent;
120
120
  cursor: zoom-in;
121
121
  }
122
- video.vgai-generation-output-media {
122
+ video.volter-generation-output-media {
123
123
  width: 100%;
124
124
  }
125
- .vgai-generation-output-audio {
125
+ .volter-generation-output-audio {
126
126
  display: flex;
127
127
  width: 100%;
128
128
  height: 100%;
129
129
  flex-direction: column;
130
130
  align-items: center;
131
131
  justify-content: center;
132
- gap: var(--vgai-space-2);
133
- padding: var(--vgai-space-2);
132
+ gap: var(--volter-space-2);
133
+ padding: var(--volter-space-2);
134
134
  }
135
- .vgai-generation-output-audio audio {
135
+ .volter-generation-output-audio audio {
136
136
  width: 100%;
137
137
  }
138
- .vgai-generation-output-file {
138
+ .volter-generation-output-file {
139
139
  display: flex;
140
140
  flex-direction: column;
141
141
  align-items: center;
142
- gap: var(--vgai-space-2);
143
- padding: var(--vgai-space-3);
144
- color: var(--vgai-content-muted);
142
+ gap: var(--volter-space-2);
143
+ padding: var(--volter-space-3);
144
+ color: var(--volter-content-muted);
145
145
  text-align: center;
146
146
  overflow-wrap: anywhere;
147
147
  }
148
148
 
149
- .vgai-generation-state-media {
149
+ .volter-generation-state-media {
150
150
  display: flex;
151
151
  flex-direction: column;
152
152
  align-items: center;
153
153
  justify-content: center;
154
- gap: var(--vgai-space-2);
155
- padding: var(--vgai-space-3);
154
+ gap: var(--volter-space-2);
155
+ padding: var(--volter-space-3);
156
156
  text-align: center;
157
157
  }
158
- .vgai-generation-progress {
158
+ .volter-generation-progress {
159
159
  width: 70%;
160
160
  height: 4px;
161
- accent-color: var(--vgai-accent);
161
+ accent-color: var(--volter-accent);
162
162
  }
163
163
 
164
- .vgai-generation-card-body {
164
+ .volter-generation-card-body {
165
165
  display: flex;
166
166
  min-width: 0;
167
167
  flex-direction: column;
168
- gap: var(--vgai-space-1);
169
- padding: var(--vgai-space-3);
168
+ gap: var(--volter-space-1);
169
+ padding: var(--volter-space-3);
170
170
  }
171
- .vgai-generation-card-heading {
171
+ .volter-generation-card-heading {
172
172
  display: flex;
173
173
  min-width: 0;
174
174
  align-items: center;
175
- gap: var(--vgai-space-2);
175
+ gap: var(--volter-space-2);
176
176
  }
177
- .vgai-generation-card-heading > .vgai-text {
177
+ .volter-generation-card-heading > .volter-text {
178
178
  min-width: 0;
179
179
  flex: 1;
180
180
  }
181
- .vgai-generation-chip {
181
+ .volter-generation-chip {
182
182
  flex: 0 0 auto;
183
183
  }
184
- .vgai-generation-chip[data-state="ready"] {
185
- color: var(--vgai-success);
186
- border-color: var(--vgai-success-muted);
184
+ .volter-generation-chip[data-state="ready"] {
185
+ color: var(--volter-success);
186
+ border-color: var(--volter-success-muted);
187
187
  }
188
- .vgai-generation-chip[data-state="failed"],
189
- .vgai-generation-chip[data-state="save-failed"] {
190
- color: var(--vgai-danger);
191
- border-color: var(--vgai-danger-muted);
188
+ .volter-generation-chip[data-state="failed"],
189
+ .volter-generation-chip[data-state="save-failed"] {
190
+ color: var(--volter-danger);
191
+ border-color: var(--volter-danger-muted);
192
192
  }
193
- .vgai-generation-chip[data-state="queued"],
194
- .vgai-generation-chip[data-state="running"],
195
- .vgai-generation-chip[data-state="saving"],
196
- .vgai-generation-chip[data-state="new"] {
197
- color: var(--vgai-accent);
198
- border-color: var(--vgai-accent-muted);
193
+ .volter-generation-chip[data-state="queued"],
194
+ .volter-generation-chip[data-state="running"],
195
+ .volter-generation-chip[data-state="saving"],
196
+ .volter-generation-chip[data-state="new"] {
197
+ color: var(--volter-accent);
198
+ border-color: var(--volter-accent-muted);
199
199
  }
200
200
 
201
201
  /* The prompt is available, never dominant: two lines, full text on hover. */
202
- .vgai-generation-card-prompt {
202
+ .volter-generation-card-prompt {
203
203
  display: -webkit-box;
204
- margin: var(--vgai-space-1) 0 0;
204
+ margin: var(--volter-space-1) 0 0;
205
205
  overflow: hidden;
206
- color: var(--vgai-content-dim);
207
- font-size: var(--vgai-font-sm);
208
- line-height: var(--vgai-leading-normal);
206
+ color: var(--volter-content-dim);
207
+ font-size: var(--volter-font-sm);
208
+ line-height: var(--volter-leading-normal);
209
209
  -webkit-box-orient: vertical;
210
210
  -webkit-line-clamp: 2;
211
211
  line-clamp: 2;
212
212
  }
213
- .vgai-generation-card-alert {
214
- margin-top: var(--vgai-space-2);
215
- font-size: var(--vgai-font-sm);
213
+ .volter-generation-card-alert {
214
+ margin-top: var(--volter-space-2);
215
+ font-size: var(--volter-font-sm);
216
216
  }
217
- .vgai-generation-card-actions {
217
+ .volter-generation-card-actions {
218
218
  display: flex;
219
219
  flex-wrap: wrap;
220
- gap: var(--vgai-space-2);
221
- margin-top: var(--vgai-space-2);
220
+ gap: var(--volter-space-2);
221
+ margin-top: var(--volter-space-2);
222
222
  }
223
223
 
224
224
  @container (max-height: 300px) {
225
- .vgai-generation-card-media {
225
+ .volter-generation-card-media {
226
226
  height: 96px;
227
227
  }
228
- .vgai-generation-card-prompt {
228
+ .volter-generation-card-prompt {
229
229
  display: none;
230
230
  }
231
231
  }
@@ -49,7 +49,7 @@ function billingLabel(billing: GenerationBilling): string {
49
49
  if (billing.route === 'managed') {
50
50
  if (billing.settledCredits !== undefined) return `${billing.settledCredits} credits settled`;
51
51
  if (billing.estimatedCredits !== undefined) return `Up to ${billing.estimatedCredits} credits`;
52
- return 'VGAI subscription · estimate unavailable';
52
+ return 'VOLTER subscription · estimate unavailable';
53
53
  }
54
54
  if (billing.settledAmount !== undefined) return `$${billing.settledAmount.toFixed(3)} settled`;
55
55
  if (billing.estimatedAmount !== undefined) return `Up to $${billing.estimatedAmount.toFixed(3)}`;
@@ -109,11 +109,11 @@ export function GenerationCreateDocumentContent() {
109
109
  providers.set(provider, [...(providers.get(provider) ?? []), item]);
110
110
  }
111
111
  return (
112
- <div className="vgai-tool-page" data-testid="generation-create-catalog">
113
- <header className="vgai-tool-header">
114
- <div className="vgai-tool-eyebrow">Installed provider extensions</div>
115
- <h2 className="vgai-tool-title">Create an asset</h2>
116
- <p className="vgai-tool-description">
112
+ <div className="volter-tool-page" data-testid="generation-create-catalog">
113
+ <header className="volter-tool-header">
114
+ <div className="volter-tool-eyebrow">Installed provider extensions</div>
115
+ <h2 className="volter-tool-title">Create an asset</h2>
116
+ <p className="volter-tool-description">
117
117
  Choose a native provider operation. Mock, managed, and BYOK execution remain explicit in
118
118
  the operation you open. Current default: {account.preferredRoute}.
119
119
  </p>
@@ -126,13 +126,13 @@ export function GenerationCreateDocumentContent() {
126
126
  onChange={(event) => setQuery(event.target.value)}
127
127
  />
128
128
  {[...providers.entries()].map(([provider, contributions]) => (
129
- <section className="vgai-tool-card" key={provider}>
130
- <h3 className="vgai-tool-section-title">{provider}</h3>
131
- <div className="vgai-generation-create-grid">
129
+ <section className="volter-tool-card" key={provider}>
130
+ <h3 className="volter-tool-section-title">{provider}</h3>
131
+ <div className="volter-generation-create-grid">
132
132
  {contributions.map((contribution) => (
133
133
  <Button
134
134
  variant="ghost"
135
- className="vgai-generation-create-card"
135
+ className="volter-generation-create-card"
136
136
  key={contribution.id}
137
137
  onClick={() => openToolDocument(contribution.id)}
138
138
  >
@@ -144,7 +144,7 @@ export function GenerationCreateDocumentContent() {
144
144
  </section>
145
145
  ))}
146
146
  {tools.length === 0 && (
147
- <div className="vgai-generation-document-empty">
147
+ <div className="volter-generation-document-empty">
148
148
  No installed generation operation matches this search.
149
149
  </div>
150
150
  )}
@@ -173,7 +173,7 @@ function ProviderResult({
173
173
  );
174
174
  const contribution = getGenerationResultContribution(job.poll.tool, job, result);
175
175
  if (!contribution) {
176
- return <pre className="vgai-generation-native-result">{JSON.stringify(result, null, 2)}</pre>;
176
+ return <pre className="volter-generation-native-result">{JSON.stringify(result, null, 2)}</pre>;
177
177
  }
178
178
  const Component = contribution.Component;
179
179
  return (
@@ -228,7 +228,7 @@ export function GenerationDocumentContent({ documentId, active }: WorkspaceDocum
228
228
 
229
229
  if (!job) {
230
230
  return (
231
- <div className="vgai-generation-document-empty">
231
+ <div className="volter-generation-document-empty">
232
232
  This generation is no longer in project activity.
233
233
  </div>
234
234
  );
@@ -244,18 +244,18 @@ export function GenerationDocumentContent({ documentId, active }: WorkspaceDocum
244
244
  : null);
245
245
 
246
246
  return (
247
- <div className="vgai-generation-document" data-status={job.status}>
248
- <header className="vgai-generation-document-header">
247
+ <div className="volter-generation-document" data-status={job.status}>
248
+ <header className="volter-generation-document-header">
249
249
  <div>
250
- <div className="vgai-tool-eyebrow">
250
+ <div className="volter-tool-eyebrow">
251
251
  {job.provider} · {job.operation}
252
252
  </div>
253
- <h2 className="vgai-tool-title">{job.label}</h2>
254
- <div className="vgai-generation-job-meta">
253
+ <h2 className="volter-tool-title">{job.label}</h2>
254
+ <div className="volter-generation-job-meta">
255
255
  {GENERATION_STATE_LABEL[generationCardState(job)]} · {billingLabel(job.billing)}
256
256
  </div>
257
257
  </div>
258
- <div className="vgai-tool-actions">
258
+ <div className="volter-tool-actions">
259
259
  <Button
260
260
  size="compact"
261
261
  variant="ghost"
@@ -289,16 +289,16 @@ export function GenerationDocumentContent({ documentId, active }: WorkspaceDocum
289
289
  </div>
290
290
  </header>
291
291
 
292
- {job.message && <div className="vgai-tool-status">{job.message}</div>}
292
+ {job.message && <div className="volter-tool-status">{job.message}</div>}
293
293
  {alert && (
294
- <div className="vgai-tool-status" data-tone="error" role="alert">
294
+ <div className="volter-tool-status" data-tone="error" role="alert">
295
295
  {alert}
296
296
  </div>
297
297
  )}
298
298
 
299
- <section className="vgai-generation-result" aria-label="Generation result">
299
+ <section className="volter-generation-result" aria-label="Generation result">
300
300
  {result === undefined ? (
301
- <div className="vgai-generation-document-empty">
301
+ <div className="volter-generation-document-empty">
302
302
  {loading ? 'Loading provider result…' : 'No provider result is available yet.'}
303
303
  </div>
304
304
  ) : (
@@ -307,7 +307,7 @@ export function GenerationDocumentContent({ documentId, active }: WorkspaceDocum
307
307
  </section>
308
308
 
309
309
  {job.outputPaths && job.outputPaths.length > 0 && (
310
- <section className="vgai-generation-output-paths">
310
+ <section className="volter-generation-output-paths">
311
311
  <strong>Project assets</strong>
312
312
  {job.outputPaths.map((path) => (
313
313
  <code key={path}>{path}</code>
@@ -316,7 +316,7 @@ export function GenerationDocumentContent({ documentId, active }: WorkspaceDocum
316
316
  )}
317
317
 
318
318
  {generationRemovable(job) && (
319
- <div className="vgai-generation-document-footer">
319
+ <div className="volter-generation-document-footer">
320
320
  <Button
321
321
  size="compact"
322
322
  variant="ghost"
@@ -219,7 +219,7 @@ export function generationModelLabel(job: GenerationJob): string {
219
219
  }
220
220
 
221
221
  export function generationRouteLabel(job: GenerationJob): string {
222
- if (job.mode === 'managed') return 'VGAI subscription';
222
+ if (job.mode === 'managed') return 'VOLTER subscription';
223
223
  if (job.mode === 'direct') return 'Your provider key';
224
224
  return 'Mock';
225
225
  }