CJGibs commited on
Commit
703a33a
·
1 Parent(s): 98ad264

Build Aether Voice Studio Docker Space

Browse files
Files changed (47) hide show
  1. .dockerignore +11 -0
  2. .gitignore +25 -0
  3. AetherOps-HF-Hub-Build-Spec.md +401 -0
  4. Dockerfile +33 -0
  5. README.md +45 -6
  6. Recommended-YAML-Header-Starter.yaml +21 -0
  7. app/backend/main.py +146 -0
  8. app/data/architecture_layers.json +34 -0
  9. app/data/contracts/provider_config_shape.json +20 -0
  10. app/data/contracts/route_model_matrix_shape.json +14 -0
  11. app/data/contracts/seed_voice_library_shape.json +14 -0
  12. app/data/contracts/voice_registry_shape.json +19 -0
  13. app/data/demo_payloads.json +32 -0
  14. app/data/docs_nav.json +47 -0
  15. app/data/faq.json +26 -0
  16. app/data/features.json +58 -0
  17. app/data/route_model_matrix.json +67 -0
  18. app/data/site_manifest.json +116 -0
  19. app/data/voice_seed_library.json +50 -0
  20. app/data/workflow_examples.json +90 -0
  21. app/frontend/index.html +16 -0
  22. app/frontend/package-lock.json +1820 -0
  23. app/frontend/package.json +22 -0
  24. app/frontend/src/App.tsx +156 -0
  25. app/frontend/src/components/ArchitectureSection.tsx +27 -0
  26. app/frontend/src/components/ContractsSection.tsx +49 -0
  27. app/frontend/src/components/DocsPortal.tsx +18 -0
  28. app/frontend/src/components/FaqSection.tsx +18 -0
  29. app/frontend/src/components/FooterCta.tsx +24 -0
  30. app/frontend/src/components/Hero.tsx +50 -0
  31. app/frontend/src/components/OverviewGrid.tsx +31 -0
  32. app/frontend/src/components/RouteMatrix.tsx +70 -0
  33. app/frontend/src/components/Section.tsx +25 -0
  34. app/frontend/src/components/StudioSection.tsx +51 -0
  35. app/frontend/src/components/TopNav.tsx +46 -0
  36. app/frontend/src/components/WorkflowShowcase.tsx +105 -0
  37. app/frontend/src/content/api.ts +43 -0
  38. app/frontend/src/content/types.ts +140 -0
  39. app/frontend/src/main.tsx +11 -0
  40. app/frontend/src/theme/app.css +744 -0
  41. app/frontend/src/theme/tokens.css +61 -0
  42. app/frontend/tsconfig.app.json +26 -0
  43. app/frontend/tsconfig.json +8 -0
  44. app/frontend/vite.config.ts +13 -0
  45. app/public/architecture-flow.svg +32 -0
  46. app/public/studio-surface.svg +27 -0
  47. requirements.txt +2 -0
.dockerignore ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ node_modules
2
+ dist
3
+ build
4
+ app/frontend/node_modules
5
+ app/frontend/dist
6
+ .git
7
+ .gitignore
8
+ __pycache__
9
+ *.pyc
10
+ .DS_Store
11
+ *.log
.gitignore ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # OS / editor
2
+ .DS_Store
3
+ Thumbs.db
4
+ .idea/
5
+ .vscode/
6
+
7
+ # Python
8
+ __pycache__/
9
+ *.py[cod]
10
+ .pytest_cache/
11
+ .mypy_cache/
12
+ .ruff_cache/
13
+ .venv/
14
+ venv/
15
+
16
+ # Frontend / build artifacts
17
+ app/frontend/node_modules/
18
+ app/frontend/dist/
19
+ app/frontend/*.tsbuildinfo
20
+
21
+ # Logs
22
+ *.log
23
+ npm-debug.log*
24
+ yarn-debug.log*
25
+ yarn-error.log*
AetherOps-HF-Hub-Build-Spec.md ADDED
@@ -0,0 +1,401 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # AetherOps Hugging Face Docker Space — Build Spec
2
+
3
+ ## Objective
4
+
5
+ Build a polished Hugging Face Docker Space for the AetherOps organization that acts as:
6
+
7
+ 1. a public-facing product showcase
8
+ 2. a docs-style explainer for Aether Voice Studio
9
+ 3. a credibility layer for the Aether ecosystem
10
+ 4. a controlled demo surface for voice workflows
11
+ 5. a launchpad into AetherOps, Aether Voice Studio, and future public docs
12
+
13
+ This is not intended to replace production infrastructure.
14
+
15
+ ---
16
+
17
+ ## Product Positioning
18
+
19
+ The Space should feel like:
20
+ - a premium technical landing page
21
+ - a product docs entrypoint
22
+ - a live architecture showcase
23
+ - a curated interactive demo, not a toy
24
+
25
+ The tone should communicate:
26
+ - serious infrastructure
27
+ - creator utility
28
+ - enterprise utility
29
+ - model routing clarity
30
+ - composable voice tooling
31
+
32
+ ---
33
+
34
+ ## Platform Constraints
35
+
36
+ ### Docker Space requirements
37
+ The Space must be implemented as a Hugging Face Docker Space using:
38
+ - `sdk: docker` in README YAML
39
+ - a standard `Dockerfile`
40
+ - a single externally exposed app port via `app_port`
41
+
42
+ If multiple internal services are needed, they must be proxied behind the single external app port.
43
+
44
+ Do not use Docker Compose as the deployment contract for Hugging Face Space runtime.
45
+
46
+ ---
47
+
48
+ ## Primary Goal
49
+
50
+ Deliver a highly polished front-end app that explains and showcases:
51
+
52
+ - Aether Voice Studio
53
+ - Voice routes and model matrix
54
+ - ASR / TTS / Dialogue / Voice Design flows
55
+ - future Sound Design lane
56
+ - LLM routing
57
+ - internal architecture at a high level
58
+ - product screenshots / diagrams / cards
59
+ - selected live demo interactions if safe and lightweight
60
+
61
+ ---
62
+
63
+ ## Recommended Technical Stack
64
+
65
+ Preferred:
66
+ - Next.js or Vite + React frontend
67
+ - FastAPI backend for lightweight API/demo endpoints
68
+ - Nginx reverse proxy only if needed for clean single-port routing
69
+
70
+ Alternative:
71
+ - pure frontend app with static + client-side demo interactions if no backend is necessary
72
+
73
+ Do not build a heavyweight all-in-one inference stack inside the Space for v1.
74
+
75
+ ---
76
+
77
+ ## Information Architecture
78
+
79
+ ### Main sections
80
+ 1. Hero
81
+ 2. Product Overview
82
+ 3. Aether Voice Studio
83
+ 4. Route / Model Matrix
84
+ 5. Demo Workflows
85
+ 6. Creator Workflows
86
+ 7. Enterprise / VoiceOps Workflows
87
+ 8. Docs Entry
88
+ 9. Architecture
89
+ 10. FAQ
90
+ 11. CTA / Links
91
+
92
+ ---
93
+
94
+ ## Page Layout
95
+
96
+ ### 1. Hero
97
+ Content:
98
+ - product title
99
+ - short positioning statement
100
+ - 2-3 primary CTA buttons
101
+ - subtle animated visual or waveform motif
102
+ - one-line trust statement
103
+
104
+ Primary CTAs:
105
+ - View Voice Studio
106
+ - Explore Docs
107
+ - View Architecture
108
+
109
+ ### 2. Product Overview
110
+ Cards for:
111
+ - ASR Live
112
+ - ASR File
113
+ - TTS Live
114
+ - TTS File
115
+ - TTS Studio
116
+ - VoiceOps
117
+ - LLM Routing
118
+ - Sound Design (coming soon)
119
+
120
+ Each card should have:
121
+ - short explanation
122
+ - intended user
123
+ - route target summary
124
+ - status badge (live / in build / planned)
125
+
126
+ ### 3. Aether Voice Studio
127
+ Large section explaining:
128
+ - why TTS Live is separate from TTS Studio
129
+ - voice cloning
130
+ - voice design
131
+ - batch narration
132
+ - dialogue generation
133
+ - reusable voice assets
134
+
135
+ Use diagrams or cards.
136
+
137
+ ### 4. Route / Model Matrix
138
+ Present the canonical routing system:
139
+ - `moss_realtime`
140
+ - `moss_tts`
141
+ - `moss_ttsd`
142
+ - `moss_voice_generator`
143
+ - `moss_soundeffect`
144
+ - `chatterbox` fallback
145
+
146
+ Display:
147
+ - use case
148
+ - route
149
+ - output type
150
+ - UI surface
151
+
152
+ ### 5. Demo Workflows
153
+ Show example workflows:
154
+ - Live voice agent response
155
+ - Clone a reference voice
156
+ - Design a custom character voice
157
+ - Batch narration export
158
+ - Dialogue scene generation
159
+ - Future sound effects
160
+
161
+ If a backend demo is included, keep it small and stable.
162
+
163
+ ### 6. Creator Workflows
164
+ Emphasize:
165
+ - docuseries narration
166
+ - faceless YouTube content
167
+ - dialogue scenes
168
+ - voice design presets
169
+ - future ambience and transition sounds
170
+
171
+ ### 7. Enterprise / VoiceOps Workflows
172
+ Emphasize:
173
+ - telephony
174
+ - branded voice agents
175
+ - support routing
176
+ - dispatch and field service voices
177
+ - enterprise voice infrastructure
178
+
179
+ ### 8. Docs Entry
180
+ This should look like a docs portal.
181
+ Include:
182
+ - Overview
183
+ - Quick Start
184
+ - Architecture
185
+ - Voice Routes
186
+ - Voice Registry
187
+ - TTS Studio
188
+ - LLM Routing
189
+ - API Reference
190
+ - Troubleshooting
191
+
192
+ ### 9. Architecture
193
+ Show:
194
+ - Voice Studio frontend
195
+ - routing layer
196
+ - route targets
197
+ - provider-aware LLM config
198
+ - model registry / voice registry
199
+ - output artifacts
200
+
201
+ ### 10. FAQ
202
+ Keep concise.
203
+ Include:
204
+ - Why multiple MOSS routes?
205
+ - Why separate TTS Live from Studio?
206
+ - What is voice design?
207
+ - What is a voice registry?
208
+ - What is the role of Chatterbox?
209
+ - Is Sound Design included?
210
+
211
+ ### 11. CTA / Links
212
+ Buttons to:
213
+ - AetherOps
214
+ - docs
215
+ - future public API
216
+ - internal app screenshots
217
+ - contact / partner form later
218
+
219
+ ---
220
+
221
+ ## Navigation
222
+
223
+ Top nav:
224
+ - Overview
225
+ - Studio
226
+ - Routes
227
+ - Demos
228
+ - Docs
229
+ - Architecture
230
+ - FAQ
231
+
232
+ Optional secondary links:
233
+ - GitHub
234
+ - Hugging Face org
235
+ - API docs
236
+
237
+ ---
238
+
239
+ ## Visual Design Direction
240
+
241
+ Style goals:
242
+ - dark, premium, technical
243
+ - high-contrast but clean
244
+ - soft gradients
245
+ - waveform / voice / routing motifs
246
+ - “serious studio” look, not toy AI landing page
247
+
248
+ Use:
249
+ - large cards
250
+ - clean spacing
251
+ - strong section boundaries
252
+ - subtle motion
253
+ - architecture diagrams
254
+ - demo output panels
255
+
256
+ ---
257
+
258
+ ## Demo Scope for v1
259
+
260
+ Allowed:
261
+ - static screenshots
262
+ - route matrix interaction
263
+ - expandable workflow cards
264
+ - example voice design prompt gallery
265
+ - selected sample audio players if pre-generated
266
+ - lightweight metadata-driven demo UI
267
+
268
+ Avoid for v1:
269
+ - full realtime inference in the Space
270
+ - heavy model hosting
271
+ - anything that depends on long cold starts
272
+ - telephony integration
273
+ - complex secrets-dependent internal routing
274
+
275
+ ---
276
+
277
+ ## Suggested v1 Deliverables
278
+
279
+ ### Required
280
+ - Docker Space app builds and runs on single app port
281
+ - polished landing page
282
+ - route/model matrix section
283
+ - docs-style navigation section
284
+ - screenshots or diagrams from Aether Voice Studio
285
+ - creator and enterprise workflow sections
286
+ - FAQ section
287
+ - CTA/footer
288
+
289
+ ### Nice to have
290
+ - small demo API endpoint
291
+ - small JSON-driven voice preset gallery
292
+ - pre-generated audio preview cards
293
+ - architecture diagram tab
294
+
295
+ ---
296
+
297
+ ## Hugging Face Space Repo Files
298
+
299
+ Minimum structure:
300
+
301
+ - `README.md`
302
+ - `Dockerfile`
303
+ - `.dockerignore`
304
+ - `app/`
305
+ - `app/frontend/`
306
+ - `app/backend/`
307
+ - `app/public/`
308
+ - `app/data/`
309
+ - `app/data/voice_seed_library.json`
310
+ - `app/data/route_model_matrix.json`
311
+
312
+ If frontend-only:
313
+ - simplify accordingly
314
+
315
+ ---
316
+
317
+ ## README YAML
318
+
319
+ Use Hugging Face Space metadata in the README YAML block.
320
+
321
+ Recommended fields:
322
+ - title
323
+ - emoji
324
+ - colorFrom
325
+ - colorTo
326
+ - sdk: docker
327
+ - app_port
328
+ - short_description
329
+ - pinned
330
+ - header
331
+ - fullWidth
332
+ - suggested_hardware
333
+ - models
334
+ - tags
335
+
336
+ ---
337
+
338
+ ## Runtime / Secrets
339
+
340
+ The Space should be designed so it can run without production secrets for v1.
341
+
342
+ If environment variables are needed:
343
+ - use Hugging Face Space Settings variables/secrets
344
+ - keep secrets server-side only
345
+ - avoid any browser-visible secret flow
346
+
347
+ ---
348
+
349
+ ## Persistence
350
+
351
+ Do not assume persistent app state for v1.
352
+ Use:
353
+ - repo assets
354
+ - generated static content
355
+ - environment variables
356
+ - optional external APIs later
357
+
358
+ Do not design v1 around runtime disk persistence.
359
+
360
+ ---
361
+
362
+ ## Build / Runtime Requirements
363
+
364
+ - must run as a proper Docker Space app
365
+ - respect single public port model
366
+ - avoid permission issues by using UID 1000-compatible ownership in image build
367
+ - no GPU requirement for v1 Space
368
+
369
+ ---
370
+
371
+ ## Non-goals
372
+
373
+ - no full production inference cluster inside Hugging Face Space
374
+ - no Docker Compose-based deployment target
375
+ - no full telephony backend in Space
376
+ - no user secrets vault in v1
377
+ - no multi-tenant auth flows in v1
378
+
379
+ ---
380
+
381
+ ## Success Criteria
382
+
383
+ The finished Space should:
384
+ 1. look premium and intentional
385
+ 2. explain Aether Voice Studio clearly
386
+ 3. demonstrate model/route sophistication
387
+ 4. support partner/investor/customer credibility
388
+ 5. be easy to extend later into a richer public product surface
389
+
390
+ Add a small Data Contracts section with downloadable or viewable JSON snippets:
391
+
392
+ voice registry shape
393
+
394
+ route/model matrix
395
+
396
+ seed voice library
397
+
398
+ provider config shape
399
+
400
+ That quietly signals: “this thing is machine-readable and automation-native.”
401
+ That matters for your brand.
Dockerfile ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM node:20-alpine AS frontend-builder
2
+
3
+ WORKDIR /workspace
4
+ COPY app/frontend/package*.json ./app/frontend/
5
+ RUN cd app/frontend && npm ci
6
+ COPY app/frontend ./app/frontend
7
+ RUN cd app/frontend && npm run build
8
+
9
+ FROM python:3.11-slim AS runtime
10
+
11
+ ENV PYTHONDONTWRITEBYTECODE=1 \
12
+ PYTHONUNBUFFERED=1 \
13
+ PORT=7860 \
14
+ DEMO_MODE=true
15
+
16
+ WORKDIR /workspace
17
+
18
+ RUN adduser --disabled-password --gecos "" --uid 1000 appuser
19
+
20
+ COPY requirements.txt .
21
+ RUN pip install --no-cache-dir -r requirements.txt
22
+
23
+ COPY app/backend ./app/backend
24
+ COPY app/data ./app/data
25
+ COPY app/public ./app/public
26
+ COPY --from=frontend-builder /workspace/app/frontend/dist ./app/frontend/dist
27
+
28
+ RUN chown -R 1000:1000 /workspace
29
+
30
+ USER 1000
31
+ EXPOSE 7860
32
+
33
+ CMD ["sh", "-c", "uvicorn app.backend.main:app --host 0.0.0.0 --port ${PORT:-7860}"]
README.md CHANGED
@@ -1,10 +1,49 @@
1
  ---
2
- title: README
3
- emoji: 👀
4
- colorFrom: pink
5
- colorTo: green
6
  sdk: docker
7
- pinned: false
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  ---
9
 
10
- Edit this `README.md` markdown file to author your organization card.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Aether Voice Studio
3
+ emoji: 🎙️
4
+ colorFrom: blue
5
+ colorTo: cyan
6
  sdk: docker
7
+ app_port: 7860
8
+ short_description: Public AetherOps showcase for Aether Voice Studio, route intelligence, docs, and demo-ready voice workflows.
9
+ pinned: true
10
+ header: default
11
+ fullWidth: true
12
+ suggested_hardware: cpu-upgrade
13
+ tags:
14
+ - voice
15
+ - tts
16
+ - asr
17
+ - audio
18
+ - creator-tools
19
+ - enterprise-ai
20
+ - docker
21
  ---
22
 
23
+ # Aether Voice Studio
24
+
25
+ Frontend-first Hugging Face Docker Space for AetherOps. This v1 is a public showcase and docs-style entrypoint for Aether Voice Studio, route intelligence, creator workflows, and enterprise VoiceOps positioning.
26
+
27
+ ## Local run
28
+
29
+ ```bash
30
+ docker build -t aetherops-space .
31
+ docker run --rm -p 7860:7860 -e DEMO_MODE=true aetherops-space
32
+ ```
33
+
34
+ ## Runtime notes
35
+
36
+ - Single public port: `7860`
37
+ - No Docker Compose deployment contract
38
+ - CPU-safe by default
39
+ - Runs without private production secrets
40
+ - `DEMO_MODE=true` keeps the experience fully functional using local data and simulated demo responses
41
+
42
+ ## Key data files
43
+
44
+ - `app/data/features.json`
45
+ - `app/data/faq.json`
46
+ - `app/data/route_model_matrix.json`
47
+ - `app/data/docs_nav.json`
48
+ - `app/data/voice_seed_library.json`
49
+ - `app/data/contracts/*.json`
Recommended-YAML-Header-Starter.yaml ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Aether Voice Studio
3
+ emoji: 🎙️
4
+ colorFrom: indigo
5
+ colorTo: purple
6
+ sdk: docker
7
+ app_port: 7860
8
+ short_description: AI-native voice studio for realtime agents, narration, dialogue, voice design, and creator workflows.
9
+ pinned: true
10
+ header: default
11
+ fullWidth: true
12
+ suggested_hardware: cpu-upgrade
13
+ tags:
14
+ - voice
15
+ - tts
16
+ - asr
17
+ - audio
18
+ - creator-tools
19
+ - enterprise-ai
20
+ - docker
21
+ ---
app/backend/main.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+ from pathlib import Path
6
+
7
+ from fastapi import FastAPI, HTTPException
8
+ from fastapi.middleware.cors import CORSMiddleware
9
+ from fastapi.responses import FileResponse
10
+ from fastapi.staticfiles import StaticFiles
11
+ from pydantic import BaseModel
12
+
13
+
14
+ ROOT_DIR = Path(__file__).resolve().parents[2]
15
+ DATA_DIR = ROOT_DIR / "app" / "data"
16
+ PUBLIC_DIR = ROOT_DIR / "app" / "public"
17
+ DIST_DIR = ROOT_DIR / "app" / "frontend" / "dist"
18
+
19
+ ALLOWED_DATA_FILES = {
20
+ "features.json",
21
+ "faq.json",
22
+ "route_model_matrix.json",
23
+ "docs_nav.json",
24
+ "voice_seed_library.json",
25
+ "workflow_examples.json",
26
+ "architecture_layers.json",
27
+ "site_manifest.json",
28
+ }
29
+
30
+ CONTRACT_FILES = {
31
+ "voice_registry": "contracts/voice_registry_shape.json",
32
+ "route_model_matrix": "contracts/route_model_matrix_shape.json",
33
+ "seed_voice_library": "contracts/seed_voice_library_shape.json",
34
+ "provider_config": "contracts/provider_config_shape.json",
35
+ }
36
+
37
+
38
+ def load_json(relative_path: str) -> dict | list:
39
+ with (DATA_DIR / relative_path).open("r", encoding="utf-8") as handle:
40
+ return json.load(handle)
41
+
42
+
43
+ class DemoRequest(BaseModel):
44
+ workflow_id: str
45
+
46
+
47
+ app = FastAPI(title="Aether Voice Studio Space API", version="1.0.0")
48
+
49
+ app.add_middleware(
50
+ CORSMiddleware,
51
+ allow_origins=["*"],
52
+ allow_credentials=False,
53
+ allow_methods=["*"],
54
+ allow_headers=["*"],
55
+ )
56
+
57
+ if DIST_DIR.exists():
58
+ assets_dir = DIST_DIR / "assets"
59
+ if assets_dir.exists():
60
+ app.mount("/assets", StaticFiles(directory=assets_dir), name="assets")
61
+
62
+ if PUBLIC_DIR.exists():
63
+ app.mount("/public", StaticFiles(directory=PUBLIC_DIR), name="public")
64
+
65
+
66
+ @app.get("/api/health")
67
+ def health() -> dict:
68
+ return {"ok": True, "demo_mode": os.getenv("DEMO_MODE", "true").lower() == "true"}
69
+
70
+
71
+ @app.get("/api/config")
72
+ def config() -> dict:
73
+ return {
74
+ "demoMode": os.getenv("DEMO_MODE", "true").lower() == "true",
75
+ "spaceTitle": "Aether Voice Studio",
76
+ "singlePort": int(os.getenv("PORT", "7860")),
77
+ }
78
+
79
+
80
+ @app.get("/api/content")
81
+ def content() -> dict:
82
+ return {
83
+ "site": load_json("site_manifest.json"),
84
+ "features": load_json("features.json"),
85
+ "routes": load_json("route_model_matrix.json"),
86
+ "docsNav": load_json("docs_nav.json"),
87
+ "faq": load_json("faq.json"),
88
+ "seedLibrary": load_json("voice_seed_library.json"),
89
+ "workflows": load_json("workflow_examples.json"),
90
+ "architecture": load_json("architecture_layers.json"),
91
+ }
92
+
93
+
94
+ @app.get("/api/data/{filename}")
95
+ def data_file(filename: str) -> dict | list:
96
+ if filename not in ALLOWED_DATA_FILES:
97
+ raise HTTPException(status_code=404, detail="Unknown data file")
98
+ return load_json(filename)
99
+
100
+
101
+ @app.get("/api/contracts")
102
+ def contracts() -> dict:
103
+ return {
104
+ name: {
105
+ "endpoint": f"/api/contracts/{name}",
106
+ "download": f"/api/contracts/{name}?download=true",
107
+ }
108
+ for name in CONTRACT_FILES
109
+ }
110
+
111
+
112
+ @app.get("/api/contracts/{contract_name}")
113
+ def contract_file(contract_name: str, download: bool = False):
114
+ relative_path = CONTRACT_FILES.get(contract_name)
115
+ if not relative_path:
116
+ raise HTTPException(status_code=404, detail="Unknown contract")
117
+
118
+ file_path = DATA_DIR / relative_path
119
+ if download:
120
+ return FileResponse(file_path, media_type="application/json", filename=file_path.name)
121
+ return load_json(relative_path)
122
+
123
+
124
+ @app.post("/api/demo/simulate")
125
+ def simulate_demo(request: DemoRequest) -> dict:
126
+ payloads = load_json("demo_payloads.json")
127
+ workflow_id = request.workflow_id
128
+ selected = payloads.get(workflow_id)
129
+ if selected is None:
130
+ raise HTTPException(status_code=404, detail="Unknown workflow")
131
+ return {
132
+ "demoMode": os.getenv("DEMO_MODE", "true").lower() == "true",
133
+ "workflowId": workflow_id,
134
+ "result": selected,
135
+ }
136
+
137
+
138
+ @app.get("/{full_path:path}")
139
+ def spa_fallback(full_path: str):
140
+ requested = DIST_DIR / full_path
141
+ if full_path and requested.exists() and requested.is_file():
142
+ return FileResponse(requested)
143
+ index_file = DIST_DIR / "index.html"
144
+ if index_file.exists():
145
+ return FileResponse(index_file)
146
+ raise HTTPException(status_code=503, detail="Frontend build is unavailable")
app/data/architecture_layers.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "name": "Voice Studio frontend",
4
+ "items": [
5
+ "Docs-style product surface",
6
+ "Workflow cards and route matrix",
7
+ "Demo-safe UI interactions"
8
+ ]
9
+ },
10
+ {
11
+ "name": "Routing layer",
12
+ "items": [
13
+ "Canonical MOSS route selection",
14
+ "Fallback logic through Chatterbox",
15
+ "Provider-aware request shaping"
16
+ ]
17
+ },
18
+ {
19
+ "name": "Registries",
20
+ "items": [
21
+ "Voice registry metadata",
22
+ "Route/model matrix definitions",
23
+ "Provider config contract"
24
+ ]
25
+ },
26
+ {
27
+ "name": "Artifacts",
28
+ "items": [
29
+ "Audio previews",
30
+ "Dialogue packages",
31
+ "Voice assets and metadata"
32
+ ]
33
+ }
34
+ ]
app/data/contracts/provider_config_shape.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "contract": "provider_config",
3
+ "type": "object",
4
+ "shape": {
5
+ "provider": "string",
6
+ "modelFamily": "string",
7
+ "capabilities": [
8
+ "tts",
9
+ "asr",
10
+ "dialogue",
11
+ "voice_design"
12
+ ],
13
+ "routeBindings": [
14
+ "string"
15
+ ],
16
+ "fallbackProvider": "string|null",
17
+ "requiresSecret": "boolean",
18
+ "demoSafe": "boolean"
19
+ }
20
+ }
app/data/contracts/route_model_matrix_shape.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "contract": "route_model_matrix",
3
+ "type": "array",
4
+ "itemShape": {
5
+ "route": "string",
6
+ "useCase": "string",
7
+ "outputType": "string",
8
+ "uiSurface": "string",
9
+ "models": [
10
+ "string"
11
+ ],
12
+ "notes": "string"
13
+ }
14
+ }
app/data/contracts/seed_voice_library_shape.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "contract": "seed_voice_library",
3
+ "type": "array",
4
+ "itemShape": {
5
+ "id": "string",
6
+ "name": "string",
7
+ "persona": "string",
8
+ "bestFor": "string",
9
+ "route": "string",
10
+ "styleTags": [
11
+ "string"
12
+ ]
13
+ }
14
+ }
app/data/contracts/voice_registry_shape.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "contract": "voice_registry",
3
+ "type": "array",
4
+ "itemShape": {
5
+ "id": "string",
6
+ "name": "string",
7
+ "persona": "string",
8
+ "provider": "string",
9
+ "routeCompatibility": [
10
+ "moss_tts",
11
+ "moss_ttsd",
12
+ "moss_realtime"
13
+ ],
14
+ "styleTags": [
15
+ "string"
16
+ ],
17
+ "status": "active|planned|retired"
18
+ }
19
+ }
app/data/demo_payloads.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "live-agent-response": {
3
+ "headline": "Realtime response prepared",
4
+ "details": "Simulated low-latency reply with transcript events, route telemetry, and audio segment planning.",
5
+ "artifact": "stream_session_preview"
6
+ },
7
+ "clone-reference-voice": {
8
+ "headline": "Reference voice analyzed",
9
+ "details": "Demo clone package includes style tags, registry ID, and route compatibility fields.",
10
+ "artifact": "voice_asset_stub"
11
+ },
12
+ "design-custom-character": {
13
+ "headline": "Character voice scaffold generated",
14
+ "details": "Persona prompt converted into studio-ready voice seed metadata for later rendering.",
15
+ "artifact": "character_seed_profile"
16
+ },
17
+ "batch-narration-export": {
18
+ "headline": "Narration batch assembled",
19
+ "details": "Long-form script broken into export chunks with consistent preset selection and output packaging.",
20
+ "artifact": "narration_export_bundle"
21
+ },
22
+ "dialogue-scene-generation": {
23
+ "headline": "Dialogue scene structured",
24
+ "details": "Speaker assignments, route selection, and scene timeline prepared for render.",
25
+ "artifact": "dialogue_scene_package"
26
+ },
27
+ "future-sound-effects": {
28
+ "headline": "Sound design lane planned",
29
+ "details": "Current v1 exposes the future contract without attempting heavyweight generation inside the Space.",
30
+ "artifact": "planned_sound_design_contract"
31
+ }
32
+ }
app/data/docs_nav.json ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "title": "Overview",
4
+ "description": "Platform framing, workflow lanes, and product boundaries.",
5
+ "anchor": "#overview"
6
+ },
7
+ {
8
+ "title": "Quick Start",
9
+ "description": "How operators, creators, and partners should read the platform.",
10
+ "anchor": "#demos"
11
+ },
12
+ {
13
+ "title": "Architecture",
14
+ "description": "Frontend, routing layer, registries, and artifacts.",
15
+ "anchor": "#architecture"
16
+ },
17
+ {
18
+ "title": "Voice Routes",
19
+ "description": "Canonical route matrix and route responsibilities.",
20
+ "anchor": "#routes"
21
+ },
22
+ {
23
+ "title": "Voice Registry",
24
+ "description": "Machine-readable voice metadata and reuse semantics.",
25
+ "anchor": "#contracts"
26
+ },
27
+ {
28
+ "title": "TTS Studio",
29
+ "description": "Why studio workflows differ from instant TTS.",
30
+ "anchor": "#studio"
31
+ },
32
+ {
33
+ "title": "LLM Routing",
34
+ "description": "Provider-aware config layer around voice workflows.",
35
+ "anchor": "#architecture"
36
+ },
37
+ {
38
+ "title": "API Reference",
39
+ "description": "Current demo-safe endpoints and future public shape.",
40
+ "anchor": "#contracts"
41
+ },
42
+ {
43
+ "title": "Troubleshooting",
44
+ "description": "Space-safe operating assumptions and demo mode boundaries.",
45
+ "anchor": "#faq"
46
+ }
47
+ ]
app/data/faq.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "question": "Why multiple MOSS routes?",
4
+ "answer": "Each route maps to a distinct workflow class. That keeps latency, output structure, and UI assumptions explicit instead of burying everything behind a single generic voice endpoint."
5
+ },
6
+ {
7
+ "question": "Why separate TTS Live from Studio?",
8
+ "answer": "Immediate prompt iteration and long-form production behave differently. TTS Live optimizes for speed, while Studio supports cloning, dialogue composition, and export-oriented workflows."
9
+ },
10
+ {
11
+ "question": "What is voice design?",
12
+ "answer": "Voice design is the creation of reusable synthetic voice assets with controlled style, persona, and later operational metadata."
13
+ },
14
+ {
15
+ "question": "What is a voice registry?",
16
+ "answer": "A voice registry is a machine-readable inventory of available voice assets, their provenance, allowed routes, and usage semantics."
17
+ },
18
+ {
19
+ "question": "What is the role of Chatterbox?",
20
+ "answer": "Chatterbox is the fallback path. It provides compatibility and resilience when a primary route is unavailable or inappropriate for the requested workflow."
21
+ },
22
+ {
23
+ "question": "Is Sound Design included?",
24
+ "answer": "The lane is designed into the information architecture now, but it remains a planned surface in v1 rather than a fully interactive production subsystem."
25
+ }
26
+ ]
app/data/features.json ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "title": "ASR Live",
4
+ "summary": "Low-latency transcription surface for live operator and agent flows.",
5
+ "intendedUser": "Support teams and realtime voice systems",
6
+ "routeTargetSummary": "Ingress audio -> streaming ASR -> transcript events",
7
+ "status": "live"
8
+ },
9
+ {
10
+ "title": "ASR File",
11
+ "summary": "Upload-oriented transcription lane for longer recordings and batch review.",
12
+ "intendedUser": "Researchers, editors, QA teams",
13
+ "routeTargetSummary": "File ingest -> async ASR -> artifact output",
14
+ "status": "live"
15
+ },
16
+ {
17
+ "title": "TTS Live",
18
+ "summary": "Fast route-aware synthesis for immediate prompt iteration and quick previews.",
19
+ "intendedUser": "Creators and operator tooling",
20
+ "routeTargetSummary": "Prompt -> moss_tts -> preview artifact",
21
+ "status": "live"
22
+ },
23
+ {
24
+ "title": "TTS File",
25
+ "summary": "Export-oriented synthesis for narration runs and predictable file outputs.",
26
+ "intendedUser": "Production and batch pipelines",
27
+ "routeTargetSummary": "Script input -> moss_tts -> packaged audio files",
28
+ "status": "in build"
29
+ },
30
+ {
31
+ "title": "TTS Studio",
32
+ "summary": "Long-form workspace for cloning, voice design, dialogue scenes, and reusable assets.",
33
+ "intendedUser": "Voice directors and advanced creators",
34
+ "routeTargetSummary": "Studio workflow -> multiple routes -> saved assets",
35
+ "status": "live"
36
+ },
37
+ {
38
+ "title": "VoiceOps",
39
+ "summary": "Operational view into branded voice infrastructure and route governance.",
40
+ "intendedUser": "Enterprise voice teams",
41
+ "routeTargetSummary": "Registry + provider policy + route controls",
42
+ "status": "in build"
43
+ },
44
+ {
45
+ "title": "LLM Routing",
46
+ "summary": "Provider-aware language layer supporting prompt orchestration around voice tasks.",
47
+ "intendedUser": "Builders and automation teams",
48
+ "routeTargetSummary": "Prompt -> provider config -> structured task output",
49
+ "status": "live"
50
+ },
51
+ {
52
+ "title": "Sound Design",
53
+ "summary": "Future lane for ambience, transitions, effects, and scene support assets.",
54
+ "intendedUser": "Narrative and brand teams",
55
+ "routeTargetSummary": "Prompt -> moss_soundeffect -> scene assets",
56
+ "status": "planned"
57
+ }
58
+ ]
app/data/route_model_matrix.json ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "route": "moss_realtime",
4
+ "useCase": "Realtime conversational response loops",
5
+ "outputType": "Streaming audio + event payloads",
6
+ "uiSurface": "Live agent and telephony-ready surfaces",
7
+ "models": [
8
+ "Realtime speech stack",
9
+ "Streaming ASR",
10
+ "Dialogue controller"
11
+ ],
12
+ "notes": "Optimized for latency-sensitive interactions."
13
+ },
14
+ {
15
+ "route": "moss_tts",
16
+ "useCase": "General TTS preview and export",
17
+ "outputType": "Waveform audio artifact",
18
+ "uiSurface": "TTS Live and TTS File",
19
+ "models": [
20
+ "Narration TTS",
21
+ "Voice preset layer"
22
+ ],
23
+ "notes": "Primary route for standard synthesis requests."
24
+ },
25
+ {
26
+ "route": "moss_ttsd",
27
+ "useCase": "Dialogue generation and scene composition",
28
+ "outputType": "Multi-speaker audio package",
29
+ "uiSurface": "TTS Studio dialogue canvas",
30
+ "models": [
31
+ "Dialogue planner",
32
+ "Speaker assignment"
33
+ ],
34
+ "notes": "Built for structured dialogue scenes and character interplay."
35
+ },
36
+ {
37
+ "route": "moss_voice_generator",
38
+ "useCase": "Voice cloning and new voice design",
39
+ "outputType": "Voice asset + metadata",
40
+ "uiSurface": "Voice Studio asset builder",
41
+ "models": [
42
+ "Voice cloning",
43
+ "Voice design"
44
+ ],
45
+ "notes": "Produces reusable voices for later TTS and dialogue workflows."
46
+ },
47
+ {
48
+ "route": "moss_soundeffect",
49
+ "useCase": "Future ambience and effect generation",
50
+ "outputType": "Sound effect asset",
51
+ "uiSurface": "Planned sound design lane",
52
+ "models": [
53
+ "Effect generator"
54
+ ],
55
+ "notes": "Planned for future public workflows."
56
+ },
57
+ {
58
+ "route": "chatterbox",
59
+ "useCase": "Fallback or compatibility path",
60
+ "outputType": "Text or audio-ready response scaffolding",
61
+ "uiSurface": "Operational fallback surfaces",
62
+ "models": [
63
+ "Fallback assistant runtime"
64
+ ],
65
+ "notes": "Acts as a resilience layer when a primary route is not appropriate."
66
+ }
67
+ ]
app/data/site_manifest.json ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "hero": {
3
+ "eyebrow": "AetherOps public product surface",
4
+ "title": "Aether Voice Studio",
5
+ "statement": "AI-native voice infrastructure for realtime agents, studio-grade narration, dialogue systems, and reusable voice operations.",
6
+ "trustLine": "Frontend-first Docker Space v1 designed for credibility, clarity, and extension into future public workflows.",
7
+ "ctas": [
8
+ {
9
+ "label": "View Voice Studio",
10
+ "href": "#studio"
11
+ },
12
+ {
13
+ "label": "Explore Docs",
14
+ "href": "#docs"
15
+ },
16
+ {
17
+ "label": "View Architecture",
18
+ "href": "#architecture"
19
+ }
20
+ ],
21
+ "metrics": [
22
+ {
23
+ "label": "Canonical routes",
24
+ "value": "6"
25
+ },
26
+ {
27
+ "label": "Workflow lanes",
28
+ "value": "3"
29
+ },
30
+ {
31
+ "label": "Demo mode",
32
+ "value": "Public-safe"
33
+ }
34
+ ]
35
+ },
36
+ "navigation": [
37
+ {
38
+ "label": "Overview",
39
+ "href": "#overview"
40
+ },
41
+ {
42
+ "label": "Studio",
43
+ "href": "#studio"
44
+ },
45
+ {
46
+ "label": "Routes",
47
+ "href": "#routes"
48
+ },
49
+ {
50
+ "label": "Demos",
51
+ "href": "#demos"
52
+ },
53
+ {
54
+ "label": "Docs",
55
+ "href": "#docs"
56
+ },
57
+ {
58
+ "label": "Architecture",
59
+ "href": "#architecture"
60
+ },
61
+ {
62
+ "label": "FAQ",
63
+ "href": "#faq"
64
+ }
65
+ ],
66
+ "secondaryLinks": [
67
+ {
68
+ "label": "Hugging Face Org",
69
+ "href": "https://huggingface.co"
70
+ },
71
+ {
72
+ "label": "Public API Later",
73
+ "href": "#contracts"
74
+ },
75
+ {
76
+ "label": "JSON Contracts",
77
+ "href": "#contracts"
78
+ }
79
+ ],
80
+ "studioNarrative": {
81
+ "headline": "Voice Studio is built as an orchestration surface, not a single toy widget.",
82
+ "body": "TTS Live is optimized for immediate generation and iteration, while TTS Studio handles batch narration, dialogue assembly, cloning pipelines, and reusable voice assets. That split keeps realtime workflows sharp without collapsing long-form production into the same UI assumptions.",
83
+ "pillars": [
84
+ {
85
+ "title": "TTS Live",
86
+ "description": "Fast prompts, route-aware previews, and immediate iteration for operators or creators."
87
+ },
88
+ {
89
+ "title": "TTS Studio",
90
+ "description": "Batch narration, dialogue sequencing, voice design, and export-oriented production flows."
91
+ },
92
+ {
93
+ "title": "Reusable assets",
94
+ "description": "Voice presets, registry metadata, and future automation hooks that can travel across products."
95
+ }
96
+ ]
97
+ },
98
+ "cta": {
99
+ "title": "Ready for richer docs and future public interactions",
100
+ "body": "This v1 keeps the backend intentionally light while exposing the routing model, machine-readable contracts, and content architecture needed for later public demos.",
101
+ "buttons": [
102
+ {
103
+ "label": "AetherOps",
104
+ "href": "#top"
105
+ },
106
+ {
107
+ "label": "Docs entry",
108
+ "href": "#docs"
109
+ },
110
+ {
111
+ "label": "Architecture",
112
+ "href": "#architecture"
113
+ }
114
+ ]
115
+ }
116
+ }
app/data/voice_seed_library.json ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "id": "studio_narrator_01",
4
+ "name": "Atlas Narrator",
5
+ "persona": "Measured documentary narrator",
6
+ "bestFor": "Docuseries, explainers, course narration",
7
+ "route": "moss_tts",
8
+ "styleTags": [
9
+ "clear",
10
+ "grounded",
11
+ "premium"
12
+ ]
13
+ },
14
+ {
15
+ "id": "dialogue_character_07",
16
+ "name": "Mira Scene Lead",
17
+ "persona": "Expressive cinematic protagonist",
18
+ "bestFor": "Dialogue scenes and scripted character moments",
19
+ "route": "moss_ttsd",
20
+ "styleTags": [
21
+ "dramatic",
22
+ "warm",
23
+ "dynamic"
24
+ ]
25
+ },
26
+ {
27
+ "id": "ops_agent_03",
28
+ "name": "Vector Support",
29
+ "persona": "Branded enterprise support agent",
30
+ "bestFor": "VoiceOps, support flows, field dispatch messaging",
31
+ "route": "moss_realtime",
32
+ "styleTags": [
33
+ "confident",
34
+ "efficient",
35
+ "neutral"
36
+ ]
37
+ },
38
+ {
39
+ "id": "design_seed_11",
40
+ "name": "Solstice Prototype",
41
+ "persona": "Designed voice asset with stylized tone control",
42
+ "bestFor": "Voice design experiments and reusable presets",
43
+ "route": "moss_voice_generator",
44
+ "styleTags": [
45
+ "stylized",
46
+ "bright",
47
+ "brandable"
48
+ ]
49
+ }
50
+ ]
app/data/workflow_examples.json ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "demo": [
3
+ {
4
+ "id": "live-agent-response",
5
+ "title": "Live voice agent response",
6
+ "summary": "Demonstrates a low-latency route for conversational systems.",
7
+ "route": "moss_realtime",
8
+ "outcome": "Streaming response with transcript and audio event scaffolding."
9
+ },
10
+ {
11
+ "id": "clone-reference-voice",
12
+ "title": "Clone a reference voice",
13
+ "summary": "Takes a reference asset and turns it into a reusable library entry.",
14
+ "route": "moss_voice_generator",
15
+ "outcome": "Voice asset metadata with route-ready preset fields."
16
+ },
17
+ {
18
+ "id": "design-custom-character",
19
+ "title": "Design a custom character voice",
20
+ "summary": "Converts persona and tone prompts into a studio-ready seed.",
21
+ "route": "moss_voice_generator",
22
+ "outcome": "Designed voice asset prepared for dialogue workflows."
23
+ },
24
+ {
25
+ "id": "batch-narration-export",
26
+ "title": "Batch narration export",
27
+ "summary": "Shows how long-form scripts become consistent output packages.",
28
+ "route": "moss_tts",
29
+ "outcome": "Multiple narration files with preset continuity."
30
+ },
31
+ {
32
+ "id": "dialogue-scene-generation",
33
+ "title": "Dialogue scene generation",
34
+ "summary": "Assigns multiple voices and renders a structured scene package.",
35
+ "route": "moss_ttsd",
36
+ "outcome": "Scene timeline with speaker-aware voice assets."
37
+ },
38
+ {
39
+ "id": "future-sound-effects",
40
+ "title": "Future sound effects",
41
+ "summary": "Marks the planned lane for ambience and effects generation.",
42
+ "route": "moss_soundeffect",
43
+ "outcome": "Planned scene-support assets."
44
+ }
45
+ ],
46
+ "creator": [
47
+ {
48
+ "title": "Docuseries narration",
49
+ "summary": "Consistent long-form narration for educational or documentary content."
50
+ },
51
+ {
52
+ "title": "Faceless YouTube pipelines",
53
+ "summary": "Script to audio flows with reusable branded voices and batch export."
54
+ },
55
+ {
56
+ "title": "Dialogue scenes",
57
+ "summary": "Multi-speaker content generation with character-specific voices."
58
+ },
59
+ {
60
+ "title": "Voice design presets",
61
+ "summary": "Styleable voice seeds that can be reused across projects."
62
+ },
63
+ {
64
+ "title": "Future ambience and transitions",
65
+ "summary": "Planned support lane for narrative polish and scene texture."
66
+ }
67
+ ],
68
+ "enterprise": [
69
+ {
70
+ "title": "Telephony-ready architecture",
71
+ "summary": "Route-aware foundations for future voice agent and call flows."
72
+ },
73
+ {
74
+ "title": "Branded voice agents",
75
+ "summary": "Registry-backed voices with operational controls and policy hooks."
76
+ },
77
+ {
78
+ "title": "Support routing",
79
+ "summary": "Voice channels aligned to departments, use cases, and escalation lanes."
80
+ },
81
+ {
82
+ "title": "Dispatch and field service voices",
83
+ "summary": "Operational messaging for time-sensitive service scenarios."
84
+ },
85
+ {
86
+ "title": "Enterprise voice infrastructure",
87
+ "summary": "A layered model that separates UI, routing, registry, and providers."
88
+ }
89
+ ]
90
+ }
app/frontend/index.html ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Aether Voice Studio</title>
7
+ <meta
8
+ name="description"
9
+ content="AetherOps public Docker Space for Aether Voice Studio, route intelligence, docs, and demo-safe workflow exploration."
10
+ />
11
+ </head>
12
+ <body>
13
+ <div id="root"></div>
14
+ <script type="module" src="/src/main.tsx"></script>
15
+ </body>
16
+ </html>
app/frontend/package-lock.json ADDED
@@ -0,0 +1,1820 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "aetherops-space-frontend",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "aetherops-space-frontend",
9
+ "version": "1.0.0",
10
+ "dependencies": {
11
+ "react": "^19.1.0",
12
+ "react-dom": "^19.1.0"
13
+ },
14
+ "devDependencies": {
15
+ "@types/react": "^19.1.2",
16
+ "@types/react-dom": "^19.1.2",
17
+ "@vitejs/plugin-react": "^5.0.2",
18
+ "typescript": "^5.9.2",
19
+ "vite": "^7.1.3"
20
+ }
21
+ },
22
+ "node_modules/@babel/code-frame": {
23
+ "version": "7.29.0",
24
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
25
+ "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
26
+ "dev": true,
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "@babel/helper-validator-identifier": "^7.28.5",
30
+ "js-tokens": "^4.0.0",
31
+ "picocolors": "^1.1.1"
32
+ },
33
+ "engines": {
34
+ "node": ">=6.9.0"
35
+ }
36
+ },
37
+ "node_modules/@babel/compat-data": {
38
+ "version": "7.29.0",
39
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
40
+ "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
41
+ "dev": true,
42
+ "license": "MIT",
43
+ "engines": {
44
+ "node": ">=6.9.0"
45
+ }
46
+ },
47
+ "node_modules/@babel/core": {
48
+ "version": "7.29.0",
49
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
50
+ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
51
+ "dev": true,
52
+ "license": "MIT",
53
+ "dependencies": {
54
+ "@babel/code-frame": "^7.29.0",
55
+ "@babel/generator": "^7.29.0",
56
+ "@babel/helper-compilation-targets": "^7.28.6",
57
+ "@babel/helper-module-transforms": "^7.28.6",
58
+ "@babel/helpers": "^7.28.6",
59
+ "@babel/parser": "^7.29.0",
60
+ "@babel/template": "^7.28.6",
61
+ "@babel/traverse": "^7.29.0",
62
+ "@babel/types": "^7.29.0",
63
+ "@jridgewell/remapping": "^2.3.5",
64
+ "convert-source-map": "^2.0.0",
65
+ "debug": "^4.1.0",
66
+ "gensync": "^1.0.0-beta.2",
67
+ "json5": "^2.2.3",
68
+ "semver": "^6.3.1"
69
+ },
70
+ "engines": {
71
+ "node": ">=6.9.0"
72
+ },
73
+ "funding": {
74
+ "type": "opencollective",
75
+ "url": "https://opencollective.com/babel"
76
+ }
77
+ },
78
+ "node_modules/@babel/generator": {
79
+ "version": "7.29.1",
80
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
81
+ "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
82
+ "dev": true,
83
+ "license": "MIT",
84
+ "dependencies": {
85
+ "@babel/parser": "^7.29.0",
86
+ "@babel/types": "^7.29.0",
87
+ "@jridgewell/gen-mapping": "^0.3.12",
88
+ "@jridgewell/trace-mapping": "^0.3.28",
89
+ "jsesc": "^3.0.2"
90
+ },
91
+ "engines": {
92
+ "node": ">=6.9.0"
93
+ }
94
+ },
95
+ "node_modules/@babel/helper-compilation-targets": {
96
+ "version": "7.28.6",
97
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
98
+ "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
99
+ "dev": true,
100
+ "license": "MIT",
101
+ "dependencies": {
102
+ "@babel/compat-data": "^7.28.6",
103
+ "@babel/helper-validator-option": "^7.27.1",
104
+ "browserslist": "^4.24.0",
105
+ "lru-cache": "^5.1.1",
106
+ "semver": "^6.3.1"
107
+ },
108
+ "engines": {
109
+ "node": ">=6.9.0"
110
+ }
111
+ },
112
+ "node_modules/@babel/helper-globals": {
113
+ "version": "7.28.0",
114
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
115
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
116
+ "dev": true,
117
+ "license": "MIT",
118
+ "engines": {
119
+ "node": ">=6.9.0"
120
+ }
121
+ },
122
+ "node_modules/@babel/helper-module-imports": {
123
+ "version": "7.28.6",
124
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
125
+ "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
126
+ "dev": true,
127
+ "license": "MIT",
128
+ "dependencies": {
129
+ "@babel/traverse": "^7.28.6",
130
+ "@babel/types": "^7.28.6"
131
+ },
132
+ "engines": {
133
+ "node": ">=6.9.0"
134
+ }
135
+ },
136
+ "node_modules/@babel/helper-module-transforms": {
137
+ "version": "7.28.6",
138
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
139
+ "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
140
+ "dev": true,
141
+ "license": "MIT",
142
+ "dependencies": {
143
+ "@babel/helper-module-imports": "^7.28.6",
144
+ "@babel/helper-validator-identifier": "^7.28.5",
145
+ "@babel/traverse": "^7.28.6"
146
+ },
147
+ "engines": {
148
+ "node": ">=6.9.0"
149
+ },
150
+ "peerDependencies": {
151
+ "@babel/core": "^7.0.0"
152
+ }
153
+ },
154
+ "node_modules/@babel/helper-plugin-utils": {
155
+ "version": "7.28.6",
156
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
157
+ "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
158
+ "dev": true,
159
+ "license": "MIT",
160
+ "engines": {
161
+ "node": ">=6.9.0"
162
+ }
163
+ },
164
+ "node_modules/@babel/helper-string-parser": {
165
+ "version": "7.27.1",
166
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
167
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
168
+ "dev": true,
169
+ "license": "MIT",
170
+ "engines": {
171
+ "node": ">=6.9.0"
172
+ }
173
+ },
174
+ "node_modules/@babel/helper-validator-identifier": {
175
+ "version": "7.28.5",
176
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
177
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
178
+ "dev": true,
179
+ "license": "MIT",
180
+ "engines": {
181
+ "node": ">=6.9.0"
182
+ }
183
+ },
184
+ "node_modules/@babel/helper-validator-option": {
185
+ "version": "7.27.1",
186
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
187
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
188
+ "dev": true,
189
+ "license": "MIT",
190
+ "engines": {
191
+ "node": ">=6.9.0"
192
+ }
193
+ },
194
+ "node_modules/@babel/helpers": {
195
+ "version": "7.28.6",
196
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
197
+ "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
198
+ "dev": true,
199
+ "license": "MIT",
200
+ "dependencies": {
201
+ "@babel/template": "^7.28.6",
202
+ "@babel/types": "^7.28.6"
203
+ },
204
+ "engines": {
205
+ "node": ">=6.9.0"
206
+ }
207
+ },
208
+ "node_modules/@babel/parser": {
209
+ "version": "7.29.0",
210
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
211
+ "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==",
212
+ "dev": true,
213
+ "license": "MIT",
214
+ "dependencies": {
215
+ "@babel/types": "^7.29.0"
216
+ },
217
+ "bin": {
218
+ "parser": "bin/babel-parser.js"
219
+ },
220
+ "engines": {
221
+ "node": ">=6.0.0"
222
+ }
223
+ },
224
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
225
+ "version": "7.27.1",
226
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
227
+ "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
228
+ "dev": true,
229
+ "license": "MIT",
230
+ "dependencies": {
231
+ "@babel/helper-plugin-utils": "^7.27.1"
232
+ },
233
+ "engines": {
234
+ "node": ">=6.9.0"
235
+ },
236
+ "peerDependencies": {
237
+ "@babel/core": "^7.0.0-0"
238
+ }
239
+ },
240
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
241
+ "version": "7.27.1",
242
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
243
+ "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
244
+ "dev": true,
245
+ "license": "MIT",
246
+ "dependencies": {
247
+ "@babel/helper-plugin-utils": "^7.27.1"
248
+ },
249
+ "engines": {
250
+ "node": ">=6.9.0"
251
+ },
252
+ "peerDependencies": {
253
+ "@babel/core": "^7.0.0-0"
254
+ }
255
+ },
256
+ "node_modules/@babel/template": {
257
+ "version": "7.28.6",
258
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
259
+ "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
260
+ "dev": true,
261
+ "license": "MIT",
262
+ "dependencies": {
263
+ "@babel/code-frame": "^7.28.6",
264
+ "@babel/parser": "^7.28.6",
265
+ "@babel/types": "^7.28.6"
266
+ },
267
+ "engines": {
268
+ "node": ">=6.9.0"
269
+ }
270
+ },
271
+ "node_modules/@babel/traverse": {
272
+ "version": "7.29.0",
273
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
274
+ "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
275
+ "dev": true,
276
+ "license": "MIT",
277
+ "dependencies": {
278
+ "@babel/code-frame": "^7.29.0",
279
+ "@babel/generator": "^7.29.0",
280
+ "@babel/helper-globals": "^7.28.0",
281
+ "@babel/parser": "^7.29.0",
282
+ "@babel/template": "^7.28.6",
283
+ "@babel/types": "^7.29.0",
284
+ "debug": "^4.3.1"
285
+ },
286
+ "engines": {
287
+ "node": ">=6.9.0"
288
+ }
289
+ },
290
+ "node_modules/@babel/types": {
291
+ "version": "7.29.0",
292
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
293
+ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
294
+ "dev": true,
295
+ "license": "MIT",
296
+ "dependencies": {
297
+ "@babel/helper-string-parser": "^7.27.1",
298
+ "@babel/helper-validator-identifier": "^7.28.5"
299
+ },
300
+ "engines": {
301
+ "node": ">=6.9.0"
302
+ }
303
+ },
304
+ "node_modules/@esbuild/aix-ppc64": {
305
+ "version": "0.27.3",
306
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz",
307
+ "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==",
308
+ "cpu": [
309
+ "ppc64"
310
+ ],
311
+ "dev": true,
312
+ "license": "MIT",
313
+ "optional": true,
314
+ "os": [
315
+ "aix"
316
+ ],
317
+ "engines": {
318
+ "node": ">=18"
319
+ }
320
+ },
321
+ "node_modules/@esbuild/android-arm": {
322
+ "version": "0.27.3",
323
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz",
324
+ "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==",
325
+ "cpu": [
326
+ "arm"
327
+ ],
328
+ "dev": true,
329
+ "license": "MIT",
330
+ "optional": true,
331
+ "os": [
332
+ "android"
333
+ ],
334
+ "engines": {
335
+ "node": ">=18"
336
+ }
337
+ },
338
+ "node_modules/@esbuild/android-arm64": {
339
+ "version": "0.27.3",
340
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz",
341
+ "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==",
342
+ "cpu": [
343
+ "arm64"
344
+ ],
345
+ "dev": true,
346
+ "license": "MIT",
347
+ "optional": true,
348
+ "os": [
349
+ "android"
350
+ ],
351
+ "engines": {
352
+ "node": ">=18"
353
+ }
354
+ },
355
+ "node_modules/@esbuild/android-x64": {
356
+ "version": "0.27.3",
357
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz",
358
+ "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==",
359
+ "cpu": [
360
+ "x64"
361
+ ],
362
+ "dev": true,
363
+ "license": "MIT",
364
+ "optional": true,
365
+ "os": [
366
+ "android"
367
+ ],
368
+ "engines": {
369
+ "node": ">=18"
370
+ }
371
+ },
372
+ "node_modules/@esbuild/darwin-arm64": {
373
+ "version": "0.27.3",
374
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz",
375
+ "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==",
376
+ "cpu": [
377
+ "arm64"
378
+ ],
379
+ "dev": true,
380
+ "license": "MIT",
381
+ "optional": true,
382
+ "os": [
383
+ "darwin"
384
+ ],
385
+ "engines": {
386
+ "node": ">=18"
387
+ }
388
+ },
389
+ "node_modules/@esbuild/darwin-x64": {
390
+ "version": "0.27.3",
391
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz",
392
+ "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==",
393
+ "cpu": [
394
+ "x64"
395
+ ],
396
+ "dev": true,
397
+ "license": "MIT",
398
+ "optional": true,
399
+ "os": [
400
+ "darwin"
401
+ ],
402
+ "engines": {
403
+ "node": ">=18"
404
+ }
405
+ },
406
+ "node_modules/@esbuild/freebsd-arm64": {
407
+ "version": "0.27.3",
408
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz",
409
+ "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==",
410
+ "cpu": [
411
+ "arm64"
412
+ ],
413
+ "dev": true,
414
+ "license": "MIT",
415
+ "optional": true,
416
+ "os": [
417
+ "freebsd"
418
+ ],
419
+ "engines": {
420
+ "node": ">=18"
421
+ }
422
+ },
423
+ "node_modules/@esbuild/freebsd-x64": {
424
+ "version": "0.27.3",
425
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz",
426
+ "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==",
427
+ "cpu": [
428
+ "x64"
429
+ ],
430
+ "dev": true,
431
+ "license": "MIT",
432
+ "optional": true,
433
+ "os": [
434
+ "freebsd"
435
+ ],
436
+ "engines": {
437
+ "node": ">=18"
438
+ }
439
+ },
440
+ "node_modules/@esbuild/linux-arm": {
441
+ "version": "0.27.3",
442
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz",
443
+ "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==",
444
+ "cpu": [
445
+ "arm"
446
+ ],
447
+ "dev": true,
448
+ "license": "MIT",
449
+ "optional": true,
450
+ "os": [
451
+ "linux"
452
+ ],
453
+ "engines": {
454
+ "node": ">=18"
455
+ }
456
+ },
457
+ "node_modules/@esbuild/linux-arm64": {
458
+ "version": "0.27.3",
459
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz",
460
+ "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==",
461
+ "cpu": [
462
+ "arm64"
463
+ ],
464
+ "dev": true,
465
+ "license": "MIT",
466
+ "optional": true,
467
+ "os": [
468
+ "linux"
469
+ ],
470
+ "engines": {
471
+ "node": ">=18"
472
+ }
473
+ },
474
+ "node_modules/@esbuild/linux-ia32": {
475
+ "version": "0.27.3",
476
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz",
477
+ "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==",
478
+ "cpu": [
479
+ "ia32"
480
+ ],
481
+ "dev": true,
482
+ "license": "MIT",
483
+ "optional": true,
484
+ "os": [
485
+ "linux"
486
+ ],
487
+ "engines": {
488
+ "node": ">=18"
489
+ }
490
+ },
491
+ "node_modules/@esbuild/linux-loong64": {
492
+ "version": "0.27.3",
493
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz",
494
+ "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==",
495
+ "cpu": [
496
+ "loong64"
497
+ ],
498
+ "dev": true,
499
+ "license": "MIT",
500
+ "optional": true,
501
+ "os": [
502
+ "linux"
503
+ ],
504
+ "engines": {
505
+ "node": ">=18"
506
+ }
507
+ },
508
+ "node_modules/@esbuild/linux-mips64el": {
509
+ "version": "0.27.3",
510
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz",
511
+ "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==",
512
+ "cpu": [
513
+ "mips64el"
514
+ ],
515
+ "dev": true,
516
+ "license": "MIT",
517
+ "optional": true,
518
+ "os": [
519
+ "linux"
520
+ ],
521
+ "engines": {
522
+ "node": ">=18"
523
+ }
524
+ },
525
+ "node_modules/@esbuild/linux-ppc64": {
526
+ "version": "0.27.3",
527
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz",
528
+ "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==",
529
+ "cpu": [
530
+ "ppc64"
531
+ ],
532
+ "dev": true,
533
+ "license": "MIT",
534
+ "optional": true,
535
+ "os": [
536
+ "linux"
537
+ ],
538
+ "engines": {
539
+ "node": ">=18"
540
+ }
541
+ },
542
+ "node_modules/@esbuild/linux-riscv64": {
543
+ "version": "0.27.3",
544
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz",
545
+ "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==",
546
+ "cpu": [
547
+ "riscv64"
548
+ ],
549
+ "dev": true,
550
+ "license": "MIT",
551
+ "optional": true,
552
+ "os": [
553
+ "linux"
554
+ ],
555
+ "engines": {
556
+ "node": ">=18"
557
+ }
558
+ },
559
+ "node_modules/@esbuild/linux-s390x": {
560
+ "version": "0.27.3",
561
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz",
562
+ "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==",
563
+ "cpu": [
564
+ "s390x"
565
+ ],
566
+ "dev": true,
567
+ "license": "MIT",
568
+ "optional": true,
569
+ "os": [
570
+ "linux"
571
+ ],
572
+ "engines": {
573
+ "node": ">=18"
574
+ }
575
+ },
576
+ "node_modules/@esbuild/linux-x64": {
577
+ "version": "0.27.3",
578
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz",
579
+ "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==",
580
+ "cpu": [
581
+ "x64"
582
+ ],
583
+ "dev": true,
584
+ "license": "MIT",
585
+ "optional": true,
586
+ "os": [
587
+ "linux"
588
+ ],
589
+ "engines": {
590
+ "node": ">=18"
591
+ }
592
+ },
593
+ "node_modules/@esbuild/netbsd-arm64": {
594
+ "version": "0.27.3",
595
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz",
596
+ "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==",
597
+ "cpu": [
598
+ "arm64"
599
+ ],
600
+ "dev": true,
601
+ "license": "MIT",
602
+ "optional": true,
603
+ "os": [
604
+ "netbsd"
605
+ ],
606
+ "engines": {
607
+ "node": ">=18"
608
+ }
609
+ },
610
+ "node_modules/@esbuild/netbsd-x64": {
611
+ "version": "0.27.3",
612
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz",
613
+ "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==",
614
+ "cpu": [
615
+ "x64"
616
+ ],
617
+ "dev": true,
618
+ "license": "MIT",
619
+ "optional": true,
620
+ "os": [
621
+ "netbsd"
622
+ ],
623
+ "engines": {
624
+ "node": ">=18"
625
+ }
626
+ },
627
+ "node_modules/@esbuild/openbsd-arm64": {
628
+ "version": "0.27.3",
629
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz",
630
+ "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==",
631
+ "cpu": [
632
+ "arm64"
633
+ ],
634
+ "dev": true,
635
+ "license": "MIT",
636
+ "optional": true,
637
+ "os": [
638
+ "openbsd"
639
+ ],
640
+ "engines": {
641
+ "node": ">=18"
642
+ }
643
+ },
644
+ "node_modules/@esbuild/openbsd-x64": {
645
+ "version": "0.27.3",
646
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz",
647
+ "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==",
648
+ "cpu": [
649
+ "x64"
650
+ ],
651
+ "dev": true,
652
+ "license": "MIT",
653
+ "optional": true,
654
+ "os": [
655
+ "openbsd"
656
+ ],
657
+ "engines": {
658
+ "node": ">=18"
659
+ }
660
+ },
661
+ "node_modules/@esbuild/openharmony-arm64": {
662
+ "version": "0.27.3",
663
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz",
664
+ "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==",
665
+ "cpu": [
666
+ "arm64"
667
+ ],
668
+ "dev": true,
669
+ "license": "MIT",
670
+ "optional": true,
671
+ "os": [
672
+ "openharmony"
673
+ ],
674
+ "engines": {
675
+ "node": ">=18"
676
+ }
677
+ },
678
+ "node_modules/@esbuild/sunos-x64": {
679
+ "version": "0.27.3",
680
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz",
681
+ "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==",
682
+ "cpu": [
683
+ "x64"
684
+ ],
685
+ "dev": true,
686
+ "license": "MIT",
687
+ "optional": true,
688
+ "os": [
689
+ "sunos"
690
+ ],
691
+ "engines": {
692
+ "node": ">=18"
693
+ }
694
+ },
695
+ "node_modules/@esbuild/win32-arm64": {
696
+ "version": "0.27.3",
697
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz",
698
+ "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==",
699
+ "cpu": [
700
+ "arm64"
701
+ ],
702
+ "dev": true,
703
+ "license": "MIT",
704
+ "optional": true,
705
+ "os": [
706
+ "win32"
707
+ ],
708
+ "engines": {
709
+ "node": ">=18"
710
+ }
711
+ },
712
+ "node_modules/@esbuild/win32-ia32": {
713
+ "version": "0.27.3",
714
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz",
715
+ "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==",
716
+ "cpu": [
717
+ "ia32"
718
+ ],
719
+ "dev": true,
720
+ "license": "MIT",
721
+ "optional": true,
722
+ "os": [
723
+ "win32"
724
+ ],
725
+ "engines": {
726
+ "node": ">=18"
727
+ }
728
+ },
729
+ "node_modules/@esbuild/win32-x64": {
730
+ "version": "0.27.3",
731
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz",
732
+ "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==",
733
+ "cpu": [
734
+ "x64"
735
+ ],
736
+ "dev": true,
737
+ "license": "MIT",
738
+ "optional": true,
739
+ "os": [
740
+ "win32"
741
+ ],
742
+ "engines": {
743
+ "node": ">=18"
744
+ }
745
+ },
746
+ "node_modules/@jridgewell/gen-mapping": {
747
+ "version": "0.3.13",
748
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
749
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
750
+ "dev": true,
751
+ "license": "MIT",
752
+ "dependencies": {
753
+ "@jridgewell/sourcemap-codec": "^1.5.0",
754
+ "@jridgewell/trace-mapping": "^0.3.24"
755
+ }
756
+ },
757
+ "node_modules/@jridgewell/remapping": {
758
+ "version": "2.3.5",
759
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
760
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
761
+ "dev": true,
762
+ "license": "MIT",
763
+ "dependencies": {
764
+ "@jridgewell/gen-mapping": "^0.3.5",
765
+ "@jridgewell/trace-mapping": "^0.3.24"
766
+ }
767
+ },
768
+ "node_modules/@jridgewell/resolve-uri": {
769
+ "version": "3.1.2",
770
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
771
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
772
+ "dev": true,
773
+ "license": "MIT",
774
+ "engines": {
775
+ "node": ">=6.0.0"
776
+ }
777
+ },
778
+ "node_modules/@jridgewell/sourcemap-codec": {
779
+ "version": "1.5.5",
780
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
781
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
782
+ "dev": true,
783
+ "license": "MIT"
784
+ },
785
+ "node_modules/@jridgewell/trace-mapping": {
786
+ "version": "0.3.31",
787
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
788
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
789
+ "dev": true,
790
+ "license": "MIT",
791
+ "dependencies": {
792
+ "@jridgewell/resolve-uri": "^3.1.0",
793
+ "@jridgewell/sourcemap-codec": "^1.4.14"
794
+ }
795
+ },
796
+ "node_modules/@rolldown/pluginutils": {
797
+ "version": "1.0.0-rc.3",
798
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz",
799
+ "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==",
800
+ "dev": true,
801
+ "license": "MIT"
802
+ },
803
+ "node_modules/@rollup/rollup-android-arm-eabi": {
804
+ "version": "4.59.0",
805
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
806
+ "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
807
+ "cpu": [
808
+ "arm"
809
+ ],
810
+ "dev": true,
811
+ "license": "MIT",
812
+ "optional": true,
813
+ "os": [
814
+ "android"
815
+ ]
816
+ },
817
+ "node_modules/@rollup/rollup-android-arm64": {
818
+ "version": "4.59.0",
819
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
820
+ "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
821
+ "cpu": [
822
+ "arm64"
823
+ ],
824
+ "dev": true,
825
+ "license": "MIT",
826
+ "optional": true,
827
+ "os": [
828
+ "android"
829
+ ]
830
+ },
831
+ "node_modules/@rollup/rollup-darwin-arm64": {
832
+ "version": "4.59.0",
833
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
834
+ "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
835
+ "cpu": [
836
+ "arm64"
837
+ ],
838
+ "dev": true,
839
+ "license": "MIT",
840
+ "optional": true,
841
+ "os": [
842
+ "darwin"
843
+ ]
844
+ },
845
+ "node_modules/@rollup/rollup-darwin-x64": {
846
+ "version": "4.59.0",
847
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
848
+ "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
849
+ "cpu": [
850
+ "x64"
851
+ ],
852
+ "dev": true,
853
+ "license": "MIT",
854
+ "optional": true,
855
+ "os": [
856
+ "darwin"
857
+ ]
858
+ },
859
+ "node_modules/@rollup/rollup-freebsd-arm64": {
860
+ "version": "4.59.0",
861
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
862
+ "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
863
+ "cpu": [
864
+ "arm64"
865
+ ],
866
+ "dev": true,
867
+ "license": "MIT",
868
+ "optional": true,
869
+ "os": [
870
+ "freebsd"
871
+ ]
872
+ },
873
+ "node_modules/@rollup/rollup-freebsd-x64": {
874
+ "version": "4.59.0",
875
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
876
+ "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
877
+ "cpu": [
878
+ "x64"
879
+ ],
880
+ "dev": true,
881
+ "license": "MIT",
882
+ "optional": true,
883
+ "os": [
884
+ "freebsd"
885
+ ]
886
+ },
887
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
888
+ "version": "4.59.0",
889
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
890
+ "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
891
+ "cpu": [
892
+ "arm"
893
+ ],
894
+ "dev": true,
895
+ "license": "MIT",
896
+ "optional": true,
897
+ "os": [
898
+ "linux"
899
+ ]
900
+ },
901
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
902
+ "version": "4.59.0",
903
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
904
+ "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
905
+ "cpu": [
906
+ "arm"
907
+ ],
908
+ "dev": true,
909
+ "license": "MIT",
910
+ "optional": true,
911
+ "os": [
912
+ "linux"
913
+ ]
914
+ },
915
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
916
+ "version": "4.59.0",
917
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
918
+ "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
919
+ "cpu": [
920
+ "arm64"
921
+ ],
922
+ "dev": true,
923
+ "license": "MIT",
924
+ "optional": true,
925
+ "os": [
926
+ "linux"
927
+ ]
928
+ },
929
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
930
+ "version": "4.59.0",
931
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
932
+ "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
933
+ "cpu": [
934
+ "arm64"
935
+ ],
936
+ "dev": true,
937
+ "license": "MIT",
938
+ "optional": true,
939
+ "os": [
940
+ "linux"
941
+ ]
942
+ },
943
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
944
+ "version": "4.59.0",
945
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
946
+ "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
947
+ "cpu": [
948
+ "loong64"
949
+ ],
950
+ "dev": true,
951
+ "license": "MIT",
952
+ "optional": true,
953
+ "os": [
954
+ "linux"
955
+ ]
956
+ },
957
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
958
+ "version": "4.59.0",
959
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
960
+ "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
961
+ "cpu": [
962
+ "loong64"
963
+ ],
964
+ "dev": true,
965
+ "license": "MIT",
966
+ "optional": true,
967
+ "os": [
968
+ "linux"
969
+ ]
970
+ },
971
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
972
+ "version": "4.59.0",
973
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
974
+ "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
975
+ "cpu": [
976
+ "ppc64"
977
+ ],
978
+ "dev": true,
979
+ "license": "MIT",
980
+ "optional": true,
981
+ "os": [
982
+ "linux"
983
+ ]
984
+ },
985
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
986
+ "version": "4.59.0",
987
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
988
+ "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
989
+ "cpu": [
990
+ "ppc64"
991
+ ],
992
+ "dev": true,
993
+ "license": "MIT",
994
+ "optional": true,
995
+ "os": [
996
+ "linux"
997
+ ]
998
+ },
999
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
1000
+ "version": "4.59.0",
1001
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
1002
+ "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
1003
+ "cpu": [
1004
+ "riscv64"
1005
+ ],
1006
+ "dev": true,
1007
+ "license": "MIT",
1008
+ "optional": true,
1009
+ "os": [
1010
+ "linux"
1011
+ ]
1012
+ },
1013
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
1014
+ "version": "4.59.0",
1015
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
1016
+ "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
1017
+ "cpu": [
1018
+ "riscv64"
1019
+ ],
1020
+ "dev": true,
1021
+ "license": "MIT",
1022
+ "optional": true,
1023
+ "os": [
1024
+ "linux"
1025
+ ]
1026
+ },
1027
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
1028
+ "version": "4.59.0",
1029
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
1030
+ "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
1031
+ "cpu": [
1032
+ "s390x"
1033
+ ],
1034
+ "dev": true,
1035
+ "license": "MIT",
1036
+ "optional": true,
1037
+ "os": [
1038
+ "linux"
1039
+ ]
1040
+ },
1041
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
1042
+ "version": "4.59.0",
1043
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
1044
+ "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
1045
+ "cpu": [
1046
+ "x64"
1047
+ ],
1048
+ "dev": true,
1049
+ "license": "MIT",
1050
+ "optional": true,
1051
+ "os": [
1052
+ "linux"
1053
+ ]
1054
+ },
1055
+ "node_modules/@rollup/rollup-linux-x64-musl": {
1056
+ "version": "4.59.0",
1057
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
1058
+ "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
1059
+ "cpu": [
1060
+ "x64"
1061
+ ],
1062
+ "dev": true,
1063
+ "license": "MIT",
1064
+ "optional": true,
1065
+ "os": [
1066
+ "linux"
1067
+ ]
1068
+ },
1069
+ "node_modules/@rollup/rollup-openbsd-x64": {
1070
+ "version": "4.59.0",
1071
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
1072
+ "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
1073
+ "cpu": [
1074
+ "x64"
1075
+ ],
1076
+ "dev": true,
1077
+ "license": "MIT",
1078
+ "optional": true,
1079
+ "os": [
1080
+ "openbsd"
1081
+ ]
1082
+ },
1083
+ "node_modules/@rollup/rollup-openharmony-arm64": {
1084
+ "version": "4.59.0",
1085
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
1086
+ "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
1087
+ "cpu": [
1088
+ "arm64"
1089
+ ],
1090
+ "dev": true,
1091
+ "license": "MIT",
1092
+ "optional": true,
1093
+ "os": [
1094
+ "openharmony"
1095
+ ]
1096
+ },
1097
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
1098
+ "version": "4.59.0",
1099
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
1100
+ "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
1101
+ "cpu": [
1102
+ "arm64"
1103
+ ],
1104
+ "dev": true,
1105
+ "license": "MIT",
1106
+ "optional": true,
1107
+ "os": [
1108
+ "win32"
1109
+ ]
1110
+ },
1111
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
1112
+ "version": "4.59.0",
1113
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
1114
+ "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
1115
+ "cpu": [
1116
+ "ia32"
1117
+ ],
1118
+ "dev": true,
1119
+ "license": "MIT",
1120
+ "optional": true,
1121
+ "os": [
1122
+ "win32"
1123
+ ]
1124
+ },
1125
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
1126
+ "version": "4.59.0",
1127
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
1128
+ "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
1129
+ "cpu": [
1130
+ "x64"
1131
+ ],
1132
+ "dev": true,
1133
+ "license": "MIT",
1134
+ "optional": true,
1135
+ "os": [
1136
+ "win32"
1137
+ ]
1138
+ },
1139
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
1140
+ "version": "4.59.0",
1141
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
1142
+ "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
1143
+ "cpu": [
1144
+ "x64"
1145
+ ],
1146
+ "dev": true,
1147
+ "license": "MIT",
1148
+ "optional": true,
1149
+ "os": [
1150
+ "win32"
1151
+ ]
1152
+ },
1153
+ "node_modules/@types/babel__core": {
1154
+ "version": "7.20.5",
1155
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
1156
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
1157
+ "dev": true,
1158
+ "license": "MIT",
1159
+ "dependencies": {
1160
+ "@babel/parser": "^7.20.7",
1161
+ "@babel/types": "^7.20.7",
1162
+ "@types/babel__generator": "*",
1163
+ "@types/babel__template": "*",
1164
+ "@types/babel__traverse": "*"
1165
+ }
1166
+ },
1167
+ "node_modules/@types/babel__generator": {
1168
+ "version": "7.27.0",
1169
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
1170
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
1171
+ "dev": true,
1172
+ "license": "MIT",
1173
+ "dependencies": {
1174
+ "@babel/types": "^7.0.0"
1175
+ }
1176
+ },
1177
+ "node_modules/@types/babel__template": {
1178
+ "version": "7.4.4",
1179
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
1180
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
1181
+ "dev": true,
1182
+ "license": "MIT",
1183
+ "dependencies": {
1184
+ "@babel/parser": "^7.1.0",
1185
+ "@babel/types": "^7.0.0"
1186
+ }
1187
+ },
1188
+ "node_modules/@types/babel__traverse": {
1189
+ "version": "7.28.0",
1190
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
1191
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
1192
+ "dev": true,
1193
+ "license": "MIT",
1194
+ "dependencies": {
1195
+ "@babel/types": "^7.28.2"
1196
+ }
1197
+ },
1198
+ "node_modules/@types/estree": {
1199
+ "version": "1.0.8",
1200
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
1201
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
1202
+ "dev": true,
1203
+ "license": "MIT"
1204
+ },
1205
+ "node_modules/@types/react": {
1206
+ "version": "19.2.14",
1207
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
1208
+ "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
1209
+ "dev": true,
1210
+ "license": "MIT",
1211
+ "dependencies": {
1212
+ "csstype": "^3.2.2"
1213
+ }
1214
+ },
1215
+ "node_modules/@types/react-dom": {
1216
+ "version": "19.2.3",
1217
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
1218
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
1219
+ "dev": true,
1220
+ "license": "MIT",
1221
+ "peerDependencies": {
1222
+ "@types/react": "^19.2.0"
1223
+ }
1224
+ },
1225
+ "node_modules/@vitejs/plugin-react": {
1226
+ "version": "5.1.4",
1227
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz",
1228
+ "integrity": "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==",
1229
+ "dev": true,
1230
+ "license": "MIT",
1231
+ "dependencies": {
1232
+ "@babel/core": "^7.29.0",
1233
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
1234
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
1235
+ "@rolldown/pluginutils": "1.0.0-rc.3",
1236
+ "@types/babel__core": "^7.20.5",
1237
+ "react-refresh": "^0.18.0"
1238
+ },
1239
+ "engines": {
1240
+ "node": "^20.19.0 || >=22.12.0"
1241
+ },
1242
+ "peerDependencies": {
1243
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
1244
+ }
1245
+ },
1246
+ "node_modules/baseline-browser-mapping": {
1247
+ "version": "2.10.0",
1248
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz",
1249
+ "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==",
1250
+ "dev": true,
1251
+ "license": "Apache-2.0",
1252
+ "bin": {
1253
+ "baseline-browser-mapping": "dist/cli.cjs"
1254
+ },
1255
+ "engines": {
1256
+ "node": ">=6.0.0"
1257
+ }
1258
+ },
1259
+ "node_modules/browserslist": {
1260
+ "version": "4.28.1",
1261
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
1262
+ "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
1263
+ "dev": true,
1264
+ "funding": [
1265
+ {
1266
+ "type": "opencollective",
1267
+ "url": "https://opencollective.com/browserslist"
1268
+ },
1269
+ {
1270
+ "type": "tidelift",
1271
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
1272
+ },
1273
+ {
1274
+ "type": "github",
1275
+ "url": "https://github.com/sponsors/ai"
1276
+ }
1277
+ ],
1278
+ "license": "MIT",
1279
+ "dependencies": {
1280
+ "baseline-browser-mapping": "^2.9.0",
1281
+ "caniuse-lite": "^1.0.30001759",
1282
+ "electron-to-chromium": "^1.5.263",
1283
+ "node-releases": "^2.0.27",
1284
+ "update-browserslist-db": "^1.2.0"
1285
+ },
1286
+ "bin": {
1287
+ "browserslist": "cli.js"
1288
+ },
1289
+ "engines": {
1290
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
1291
+ }
1292
+ },
1293
+ "node_modules/caniuse-lite": {
1294
+ "version": "1.0.30001777",
1295
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001777.tgz",
1296
+ "integrity": "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==",
1297
+ "dev": true,
1298
+ "funding": [
1299
+ {
1300
+ "type": "opencollective",
1301
+ "url": "https://opencollective.com/browserslist"
1302
+ },
1303
+ {
1304
+ "type": "tidelift",
1305
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
1306
+ },
1307
+ {
1308
+ "type": "github",
1309
+ "url": "https://github.com/sponsors/ai"
1310
+ }
1311
+ ],
1312
+ "license": "CC-BY-4.0"
1313
+ },
1314
+ "node_modules/convert-source-map": {
1315
+ "version": "2.0.0",
1316
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
1317
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
1318
+ "dev": true,
1319
+ "license": "MIT"
1320
+ },
1321
+ "node_modules/csstype": {
1322
+ "version": "3.2.3",
1323
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
1324
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
1325
+ "dev": true,
1326
+ "license": "MIT"
1327
+ },
1328
+ "node_modules/debug": {
1329
+ "version": "4.4.3",
1330
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
1331
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
1332
+ "dev": true,
1333
+ "license": "MIT",
1334
+ "dependencies": {
1335
+ "ms": "^2.1.3"
1336
+ },
1337
+ "engines": {
1338
+ "node": ">=6.0"
1339
+ },
1340
+ "peerDependenciesMeta": {
1341
+ "supports-color": {
1342
+ "optional": true
1343
+ }
1344
+ }
1345
+ },
1346
+ "node_modules/electron-to-chromium": {
1347
+ "version": "1.5.307",
1348
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz",
1349
+ "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==",
1350
+ "dev": true,
1351
+ "license": "ISC"
1352
+ },
1353
+ "node_modules/esbuild": {
1354
+ "version": "0.27.3",
1355
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz",
1356
+ "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==",
1357
+ "dev": true,
1358
+ "hasInstallScript": true,
1359
+ "license": "MIT",
1360
+ "bin": {
1361
+ "esbuild": "bin/esbuild"
1362
+ },
1363
+ "engines": {
1364
+ "node": ">=18"
1365
+ },
1366
+ "optionalDependencies": {
1367
+ "@esbuild/aix-ppc64": "0.27.3",
1368
+ "@esbuild/android-arm": "0.27.3",
1369
+ "@esbuild/android-arm64": "0.27.3",
1370
+ "@esbuild/android-x64": "0.27.3",
1371
+ "@esbuild/darwin-arm64": "0.27.3",
1372
+ "@esbuild/darwin-x64": "0.27.3",
1373
+ "@esbuild/freebsd-arm64": "0.27.3",
1374
+ "@esbuild/freebsd-x64": "0.27.3",
1375
+ "@esbuild/linux-arm": "0.27.3",
1376
+ "@esbuild/linux-arm64": "0.27.3",
1377
+ "@esbuild/linux-ia32": "0.27.3",
1378
+ "@esbuild/linux-loong64": "0.27.3",
1379
+ "@esbuild/linux-mips64el": "0.27.3",
1380
+ "@esbuild/linux-ppc64": "0.27.3",
1381
+ "@esbuild/linux-riscv64": "0.27.3",
1382
+ "@esbuild/linux-s390x": "0.27.3",
1383
+ "@esbuild/linux-x64": "0.27.3",
1384
+ "@esbuild/netbsd-arm64": "0.27.3",
1385
+ "@esbuild/netbsd-x64": "0.27.3",
1386
+ "@esbuild/openbsd-arm64": "0.27.3",
1387
+ "@esbuild/openbsd-x64": "0.27.3",
1388
+ "@esbuild/openharmony-arm64": "0.27.3",
1389
+ "@esbuild/sunos-x64": "0.27.3",
1390
+ "@esbuild/win32-arm64": "0.27.3",
1391
+ "@esbuild/win32-ia32": "0.27.3",
1392
+ "@esbuild/win32-x64": "0.27.3"
1393
+ }
1394
+ },
1395
+ "node_modules/escalade": {
1396
+ "version": "3.2.0",
1397
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
1398
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
1399
+ "dev": true,
1400
+ "license": "MIT",
1401
+ "engines": {
1402
+ "node": ">=6"
1403
+ }
1404
+ },
1405
+ "node_modules/fdir": {
1406
+ "version": "6.5.0",
1407
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
1408
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
1409
+ "dev": true,
1410
+ "license": "MIT",
1411
+ "engines": {
1412
+ "node": ">=12.0.0"
1413
+ },
1414
+ "peerDependencies": {
1415
+ "picomatch": "^3 || ^4"
1416
+ },
1417
+ "peerDependenciesMeta": {
1418
+ "picomatch": {
1419
+ "optional": true
1420
+ }
1421
+ }
1422
+ },
1423
+ "node_modules/fsevents": {
1424
+ "version": "2.3.3",
1425
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
1426
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
1427
+ "dev": true,
1428
+ "hasInstallScript": true,
1429
+ "license": "MIT",
1430
+ "optional": true,
1431
+ "os": [
1432
+ "darwin"
1433
+ ],
1434
+ "engines": {
1435
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1436
+ }
1437
+ },
1438
+ "node_modules/gensync": {
1439
+ "version": "1.0.0-beta.2",
1440
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
1441
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
1442
+ "dev": true,
1443
+ "license": "MIT",
1444
+ "engines": {
1445
+ "node": ">=6.9.0"
1446
+ }
1447
+ },
1448
+ "node_modules/js-tokens": {
1449
+ "version": "4.0.0",
1450
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
1451
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
1452
+ "dev": true,
1453
+ "license": "MIT"
1454
+ },
1455
+ "node_modules/jsesc": {
1456
+ "version": "3.1.0",
1457
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
1458
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
1459
+ "dev": true,
1460
+ "license": "MIT",
1461
+ "bin": {
1462
+ "jsesc": "bin/jsesc"
1463
+ },
1464
+ "engines": {
1465
+ "node": ">=6"
1466
+ }
1467
+ },
1468
+ "node_modules/json5": {
1469
+ "version": "2.2.3",
1470
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
1471
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
1472
+ "dev": true,
1473
+ "license": "MIT",
1474
+ "bin": {
1475
+ "json5": "lib/cli.js"
1476
+ },
1477
+ "engines": {
1478
+ "node": ">=6"
1479
+ }
1480
+ },
1481
+ "node_modules/lru-cache": {
1482
+ "version": "5.1.1",
1483
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
1484
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
1485
+ "dev": true,
1486
+ "license": "ISC",
1487
+ "dependencies": {
1488
+ "yallist": "^3.0.2"
1489
+ }
1490
+ },
1491
+ "node_modules/ms": {
1492
+ "version": "2.1.3",
1493
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1494
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
1495
+ "dev": true,
1496
+ "license": "MIT"
1497
+ },
1498
+ "node_modules/nanoid": {
1499
+ "version": "3.3.11",
1500
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
1501
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
1502
+ "dev": true,
1503
+ "funding": [
1504
+ {
1505
+ "type": "github",
1506
+ "url": "https://github.com/sponsors/ai"
1507
+ }
1508
+ ],
1509
+ "license": "MIT",
1510
+ "bin": {
1511
+ "nanoid": "bin/nanoid.cjs"
1512
+ },
1513
+ "engines": {
1514
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
1515
+ }
1516
+ },
1517
+ "node_modules/node-releases": {
1518
+ "version": "2.0.36",
1519
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz",
1520
+ "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==",
1521
+ "dev": true,
1522
+ "license": "MIT"
1523
+ },
1524
+ "node_modules/picocolors": {
1525
+ "version": "1.1.1",
1526
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
1527
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
1528
+ "dev": true,
1529
+ "license": "ISC"
1530
+ },
1531
+ "node_modules/picomatch": {
1532
+ "version": "4.0.3",
1533
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
1534
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
1535
+ "dev": true,
1536
+ "license": "MIT",
1537
+ "engines": {
1538
+ "node": ">=12"
1539
+ },
1540
+ "funding": {
1541
+ "url": "https://github.com/sponsors/jonschlinkert"
1542
+ }
1543
+ },
1544
+ "node_modules/postcss": {
1545
+ "version": "8.5.8",
1546
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
1547
+ "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
1548
+ "dev": true,
1549
+ "funding": [
1550
+ {
1551
+ "type": "opencollective",
1552
+ "url": "https://opencollective.com/postcss/"
1553
+ },
1554
+ {
1555
+ "type": "tidelift",
1556
+ "url": "https://tidelift.com/funding/github/npm/postcss"
1557
+ },
1558
+ {
1559
+ "type": "github",
1560
+ "url": "https://github.com/sponsors/ai"
1561
+ }
1562
+ ],
1563
+ "license": "MIT",
1564
+ "dependencies": {
1565
+ "nanoid": "^3.3.11",
1566
+ "picocolors": "^1.1.1",
1567
+ "source-map-js": "^1.2.1"
1568
+ },
1569
+ "engines": {
1570
+ "node": "^10 || ^12 || >=14"
1571
+ }
1572
+ },
1573
+ "node_modules/react": {
1574
+ "version": "19.2.4",
1575
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
1576
+ "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
1577
+ "license": "MIT",
1578
+ "engines": {
1579
+ "node": ">=0.10.0"
1580
+ }
1581
+ },
1582
+ "node_modules/react-dom": {
1583
+ "version": "19.2.4",
1584
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
1585
+ "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
1586
+ "license": "MIT",
1587
+ "dependencies": {
1588
+ "scheduler": "^0.27.0"
1589
+ },
1590
+ "peerDependencies": {
1591
+ "react": "^19.2.4"
1592
+ }
1593
+ },
1594
+ "node_modules/react-refresh": {
1595
+ "version": "0.18.0",
1596
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz",
1597
+ "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==",
1598
+ "dev": true,
1599
+ "license": "MIT",
1600
+ "engines": {
1601
+ "node": ">=0.10.0"
1602
+ }
1603
+ },
1604
+ "node_modules/rollup": {
1605
+ "version": "4.59.0",
1606
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
1607
+ "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
1608
+ "dev": true,
1609
+ "license": "MIT",
1610
+ "dependencies": {
1611
+ "@types/estree": "1.0.8"
1612
+ },
1613
+ "bin": {
1614
+ "rollup": "dist/bin/rollup"
1615
+ },
1616
+ "engines": {
1617
+ "node": ">=18.0.0",
1618
+ "npm": ">=8.0.0"
1619
+ },
1620
+ "optionalDependencies": {
1621
+ "@rollup/rollup-android-arm-eabi": "4.59.0",
1622
+ "@rollup/rollup-android-arm64": "4.59.0",
1623
+ "@rollup/rollup-darwin-arm64": "4.59.0",
1624
+ "@rollup/rollup-darwin-x64": "4.59.0",
1625
+ "@rollup/rollup-freebsd-arm64": "4.59.0",
1626
+ "@rollup/rollup-freebsd-x64": "4.59.0",
1627
+ "@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
1628
+ "@rollup/rollup-linux-arm-musleabihf": "4.59.0",
1629
+ "@rollup/rollup-linux-arm64-gnu": "4.59.0",
1630
+ "@rollup/rollup-linux-arm64-musl": "4.59.0",
1631
+ "@rollup/rollup-linux-loong64-gnu": "4.59.0",
1632
+ "@rollup/rollup-linux-loong64-musl": "4.59.0",
1633
+ "@rollup/rollup-linux-ppc64-gnu": "4.59.0",
1634
+ "@rollup/rollup-linux-ppc64-musl": "4.59.0",
1635
+ "@rollup/rollup-linux-riscv64-gnu": "4.59.0",
1636
+ "@rollup/rollup-linux-riscv64-musl": "4.59.0",
1637
+ "@rollup/rollup-linux-s390x-gnu": "4.59.0",
1638
+ "@rollup/rollup-linux-x64-gnu": "4.59.0",
1639
+ "@rollup/rollup-linux-x64-musl": "4.59.0",
1640
+ "@rollup/rollup-openbsd-x64": "4.59.0",
1641
+ "@rollup/rollup-openharmony-arm64": "4.59.0",
1642
+ "@rollup/rollup-win32-arm64-msvc": "4.59.0",
1643
+ "@rollup/rollup-win32-ia32-msvc": "4.59.0",
1644
+ "@rollup/rollup-win32-x64-gnu": "4.59.0",
1645
+ "@rollup/rollup-win32-x64-msvc": "4.59.0",
1646
+ "fsevents": "~2.3.2"
1647
+ }
1648
+ },
1649
+ "node_modules/scheduler": {
1650
+ "version": "0.27.0",
1651
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
1652
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
1653
+ "license": "MIT"
1654
+ },
1655
+ "node_modules/semver": {
1656
+ "version": "6.3.1",
1657
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
1658
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
1659
+ "dev": true,
1660
+ "license": "ISC",
1661
+ "bin": {
1662
+ "semver": "bin/semver.js"
1663
+ }
1664
+ },
1665
+ "node_modules/source-map-js": {
1666
+ "version": "1.2.1",
1667
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
1668
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
1669
+ "dev": true,
1670
+ "license": "BSD-3-Clause",
1671
+ "engines": {
1672
+ "node": ">=0.10.0"
1673
+ }
1674
+ },
1675
+ "node_modules/tinyglobby": {
1676
+ "version": "0.2.15",
1677
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
1678
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
1679
+ "dev": true,
1680
+ "license": "MIT",
1681
+ "dependencies": {
1682
+ "fdir": "^6.5.0",
1683
+ "picomatch": "^4.0.3"
1684
+ },
1685
+ "engines": {
1686
+ "node": ">=12.0.0"
1687
+ },
1688
+ "funding": {
1689
+ "url": "https://github.com/sponsors/SuperchupuDev"
1690
+ }
1691
+ },
1692
+ "node_modules/typescript": {
1693
+ "version": "5.9.3",
1694
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
1695
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
1696
+ "dev": true,
1697
+ "license": "Apache-2.0",
1698
+ "bin": {
1699
+ "tsc": "bin/tsc",
1700
+ "tsserver": "bin/tsserver"
1701
+ },
1702
+ "engines": {
1703
+ "node": ">=14.17"
1704
+ }
1705
+ },
1706
+ "node_modules/update-browserslist-db": {
1707
+ "version": "1.2.3",
1708
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
1709
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
1710
+ "dev": true,
1711
+ "funding": [
1712
+ {
1713
+ "type": "opencollective",
1714
+ "url": "https://opencollective.com/browserslist"
1715
+ },
1716
+ {
1717
+ "type": "tidelift",
1718
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
1719
+ },
1720
+ {
1721
+ "type": "github",
1722
+ "url": "https://github.com/sponsors/ai"
1723
+ }
1724
+ ],
1725
+ "license": "MIT",
1726
+ "dependencies": {
1727
+ "escalade": "^3.2.0",
1728
+ "picocolors": "^1.1.1"
1729
+ },
1730
+ "bin": {
1731
+ "update-browserslist-db": "cli.js"
1732
+ },
1733
+ "peerDependencies": {
1734
+ "browserslist": ">= 4.21.0"
1735
+ }
1736
+ },
1737
+ "node_modules/vite": {
1738
+ "version": "7.3.1",
1739
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
1740
+ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
1741
+ "dev": true,
1742
+ "license": "MIT",
1743
+ "dependencies": {
1744
+ "esbuild": "^0.27.0",
1745
+ "fdir": "^6.5.0",
1746
+ "picomatch": "^4.0.3",
1747
+ "postcss": "^8.5.6",
1748
+ "rollup": "^4.43.0",
1749
+ "tinyglobby": "^0.2.15"
1750
+ },
1751
+ "bin": {
1752
+ "vite": "bin/vite.js"
1753
+ },
1754
+ "engines": {
1755
+ "node": "^20.19.0 || >=22.12.0"
1756
+ },
1757
+ "funding": {
1758
+ "url": "https://github.com/vitejs/vite?sponsor=1"
1759
+ },
1760
+ "optionalDependencies": {
1761
+ "fsevents": "~2.3.3"
1762
+ },
1763
+ "peerDependencies": {
1764
+ "@types/node": "^20.19.0 || >=22.12.0",
1765
+ "jiti": ">=1.21.0",
1766
+ "less": "^4.0.0",
1767
+ "lightningcss": "^1.21.0",
1768
+ "sass": "^1.70.0",
1769
+ "sass-embedded": "^1.70.0",
1770
+ "stylus": ">=0.54.8",
1771
+ "sugarss": "^5.0.0",
1772
+ "terser": "^5.16.0",
1773
+ "tsx": "^4.8.1",
1774
+ "yaml": "^2.4.2"
1775
+ },
1776
+ "peerDependenciesMeta": {
1777
+ "@types/node": {
1778
+ "optional": true
1779
+ },
1780
+ "jiti": {
1781
+ "optional": true
1782
+ },
1783
+ "less": {
1784
+ "optional": true
1785
+ },
1786
+ "lightningcss": {
1787
+ "optional": true
1788
+ },
1789
+ "sass": {
1790
+ "optional": true
1791
+ },
1792
+ "sass-embedded": {
1793
+ "optional": true
1794
+ },
1795
+ "stylus": {
1796
+ "optional": true
1797
+ },
1798
+ "sugarss": {
1799
+ "optional": true
1800
+ },
1801
+ "terser": {
1802
+ "optional": true
1803
+ },
1804
+ "tsx": {
1805
+ "optional": true
1806
+ },
1807
+ "yaml": {
1808
+ "optional": true
1809
+ }
1810
+ }
1811
+ },
1812
+ "node_modules/yallist": {
1813
+ "version": "3.1.1",
1814
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
1815
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
1816
+ "dev": true,
1817
+ "license": "ISC"
1818
+ }
1819
+ }
1820
+ }
app/frontend/package.json ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "aetherops-space-frontend",
3
+ "private": true,
4
+ "version": "1.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc -b && vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "react": "^19.1.0",
13
+ "react-dom": "^19.1.0"
14
+ },
15
+ "devDependencies": {
16
+ "@types/react": "^19.1.2",
17
+ "@types/react-dom": "^19.1.2",
18
+ "@vitejs/plugin-react": "^5.0.2",
19
+ "typescript": "^5.9.2",
20
+ "vite": "^7.1.3"
21
+ }
22
+ }
app/frontend/src/App.tsx ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useEffect, useState } from "react";
2
+ import { ArchitectureSection } from "./components/ArchitectureSection";
3
+ import { ContractsSection } from "./components/ContractsSection";
4
+ import { DocsPortal } from "./components/DocsPortal";
5
+ import { FaqSection } from "./components/FaqSection";
6
+ import { FooterCta } from "./components/FooterCta";
7
+ import { Hero } from "./components/Hero";
8
+ import { OverviewGrid } from "./components/OverviewGrid";
9
+ import { RouteMatrix } from "./components/RouteMatrix";
10
+ import { Section } from "./components/Section";
11
+ import { StudioSection } from "./components/StudioSection";
12
+ import { TopNav } from "./components/TopNav";
13
+ import { WorkflowShowcase } from "./components/WorkflowShowcase";
14
+ import { getConfig, getContent, getContracts } from "./content/api";
15
+ import type { AppConfig, ContentResponse, ContractMap } from "./content/types";
16
+
17
+ function App() {
18
+ const [content, setContent] = useState<ContentResponse | null>(null);
19
+ const [config, setConfig] = useState<AppConfig | null>(null);
20
+ const [contracts, setContracts] = useState<ContractMap | null>(null);
21
+ const [error, setError] = useState<string | null>(null);
22
+
23
+ useEffect(() => {
24
+ async function bootstrap() {
25
+ try {
26
+ const [nextConfig, nextContent, nextContracts] = await Promise.all([
27
+ getConfig(),
28
+ getContent(),
29
+ getContracts(),
30
+ ]);
31
+ setConfig(nextConfig);
32
+ setContent(nextContent);
33
+ setContracts(nextContracts);
34
+ } catch (caughtError) {
35
+ setError(caughtError instanceof Error ? caughtError.message : "Failed to load app");
36
+ }
37
+ }
38
+
39
+ void bootstrap();
40
+ }, []);
41
+
42
+ if (error) {
43
+ return (
44
+ <main className="app-shell centered">
45
+ <div className="shell-block error-card">
46
+ <h1>Unable to load Aether Voice Studio</h1>
47
+ <p>{error}</p>
48
+ </div>
49
+ </main>
50
+ );
51
+ }
52
+
53
+ if (!content || !config || !contracts) {
54
+ return (
55
+ <main className="app-shell centered">
56
+ <div className="shell-block loading-card">
57
+ <h1>Loading Aether Voice Studio</h1>
58
+ <p>Preparing the docs surface, route matrix, and demo contracts.</p>
59
+ </div>
60
+ </main>
61
+ );
62
+ }
63
+
64
+ return (
65
+ <main className="app-shell">
66
+ <TopNav
67
+ links={content.site.navigation}
68
+ secondaryLinks={content.site.secondaryLinks}
69
+ demoMode={config.demoMode}
70
+ />
71
+ <Hero hero={content.site.hero} demoMode={config.demoMode} />
72
+
73
+ <Section
74
+ id="overview"
75
+ kicker="Product overview"
76
+ title="Aether Voice Studio spans live, studio, registry, and route-aware product lanes."
77
+ description="This v1 positions the platform as a premium product surface and technical entrypoint rather than a production inference cluster."
78
+ >
79
+ <OverviewGrid features={content.features} />
80
+ </Section>
81
+
82
+ <Section
83
+ id="studio"
84
+ kicker="Aether Voice Studio"
85
+ title="Separate immediate TTS from long-form voice production."
86
+ description="The platform keeps fast preview workflows distinct from studio-grade cloning, design, and dialogue assembly."
87
+ >
88
+ <StudioSection narrative={content.site.studioNarrative} seedLibrary={content.seedLibrary} />
89
+ </Section>
90
+
91
+ <Section
92
+ id="routes"
93
+ kicker="Route / Model Matrix"
94
+ title="Canonical route intelligence is visible, not hidden."
95
+ description="Each route is tied to a workflow class, output contract, and UI surface so the system reads as infrastructure rather than generic AI glue."
96
+ >
97
+ <RouteMatrix routes={content.routes} />
98
+ </Section>
99
+
100
+ <Section
101
+ id="demos"
102
+ kicker="Demo workflows"
103
+ title="Public-safe demos still signal real operational structure."
104
+ description="The workflow panel is lightweight by design and remains useful with local content only."
105
+ aside={<span className="route-pill">Port {config.singlePort}</span>}
106
+ >
107
+ <WorkflowShowcase
108
+ demoWorkflows={content.workflows.demo}
109
+ creatorWorkflows={content.workflows.creator}
110
+ enterpriseWorkflows={content.workflows.enterprise}
111
+ demoMode={config.demoMode}
112
+ />
113
+ </Section>
114
+
115
+ <Section
116
+ id="docs"
117
+ kicker="Docs entry"
118
+ title="The Space doubles as a docs-style portal."
119
+ description="Overview, architecture, routing, registry, and troubleshooting entry points are organized as a clean documentation surface."
120
+ >
121
+ <DocsPortal entries={content.docsNav} />
122
+ </Section>
123
+
124
+ <Section
125
+ id="architecture"
126
+ kicker="Architecture"
127
+ title="Frontend, routing, registries, and artifacts are deliberately separated."
128
+ description="That separation makes the Space credible today and extendable into richer docs or interactive flows later."
129
+ >
130
+ <ArchitectureSection layers={content.architecture} />
131
+ </Section>
132
+
133
+ <Section
134
+ id="contracts"
135
+ kicker="Data Contracts"
136
+ title="Machine-readable shapes are public by design."
137
+ description="The registry, route matrix, seed library, and provider config are exposed as JSON contracts to signal automation-native architecture."
138
+ >
139
+ <ContractsSection contracts={contracts} />
140
+ </Section>
141
+
142
+ <Section
143
+ id="faq"
144
+ kicker="FAQ"
145
+ title="Concise answers for route strategy, studio boundaries, and platform vocabulary."
146
+ description="The v1 Space emphasizes clarity over gimmicks."
147
+ >
148
+ <FaqSection faq={content.faq} />
149
+ </Section>
150
+
151
+ <FooterCta cta={content.site.cta} />
152
+ </main>
153
+ );
154
+ }
155
+
156
+ export default App;
app/frontend/src/components/ArchitectureSection.tsx ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { ArchitectureLayer } from "../content/types";
2
+
3
+ interface ArchitectureSectionProps {
4
+ layers: ArchitectureLayer[];
5
+ }
6
+
7
+ export function ArchitectureSection({ layers }: ArchitectureSectionProps) {
8
+ return (
9
+ <div className="architecture-layout">
10
+ <div className="image-card">
11
+ <img src="/public/architecture-flow.svg" alt="Aether Voice Studio architecture diagram" />
12
+ </div>
13
+ <div className="architecture-grid">
14
+ {layers.map((layer) => (
15
+ <article key={layer.name} className="arch-card">
16
+ <h3>{layer.name}</h3>
17
+ <ul>
18
+ {layer.items.map((item) => (
19
+ <li key={item}>{item}</li>
20
+ ))}
21
+ </ul>
22
+ </article>
23
+ ))}
24
+ </div>
25
+ </div>
26
+ );
27
+ }
app/frontend/src/components/ContractsSection.tsx ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useState } from "react";
2
+ import type { ContractMap } from "../content/types";
3
+
4
+ interface ContractsSectionProps {
5
+ contracts: ContractMap;
6
+ }
7
+
8
+ const contractLabels: Array<{ key: keyof ContractMap; label: string; endpoint: string }> = [
9
+ { key: "voice_registry", label: "Voice registry", endpoint: "/api/contracts/voice_registry?download=true" },
10
+ {
11
+ key: "route_model_matrix",
12
+ label: "Route/model matrix",
13
+ endpoint: "/api/contracts/route_model_matrix?download=true",
14
+ },
15
+ {
16
+ key: "seed_voice_library",
17
+ label: "Seed voice library",
18
+ endpoint: "/api/contracts/seed_voice_library?download=true",
19
+ },
20
+ { key: "provider_config", label: "Provider config", endpoint: "/api/contracts/provider_config?download=true" },
21
+ ];
22
+
23
+ export function ContractsSection({ contracts }: ContractsSectionProps) {
24
+ const [activeKey, setActiveKey] = useState<keyof ContractMap>("voice_registry");
25
+
26
+ return (
27
+ <div className="contracts-layout">
28
+ <div className="contract-tabs" role="tablist" aria-label="Data contracts">
29
+ {contractLabels.map((item) => (
30
+ <button
31
+ key={item.key}
32
+ type="button"
33
+ className={item.key === activeKey ? "contract-tab active" : "contract-tab"}
34
+ onClick={() => setActiveKey(item.key)}
35
+ >
36
+ {item.label}
37
+ </button>
38
+ ))}
39
+ </div>
40
+ <div className="contract-viewer">
41
+ <div className="contract-meta">
42
+ <strong>{contractLabels.find((item) => item.key === activeKey)?.label}</strong>
43
+ <a href={contractLabels.find((item) => item.key === activeKey)?.endpoint}>Download JSON</a>
44
+ </div>
45
+ <pre>{JSON.stringify(contracts[activeKey], null, 2)}</pre>
46
+ </div>
47
+ </div>
48
+ );
49
+ }
app/frontend/src/components/DocsPortal.tsx ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { DocsEntry } from "../content/types";
2
+
3
+ interface DocsPortalProps {
4
+ entries: DocsEntry[];
5
+ }
6
+
7
+ export function DocsPortal({ entries }: DocsPortalProps) {
8
+ return (
9
+ <div className="docs-portal">
10
+ {entries.map((entry) => (
11
+ <a key={entry.title} className="doc-card" href={entry.anchor}>
12
+ <h3>{entry.title}</h3>
13
+ <p>{entry.description}</p>
14
+ </a>
15
+ ))}
16
+ </div>
17
+ );
18
+ }
app/frontend/src/components/FaqSection.tsx ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { FaqEntry } from "../content/types";
2
+
3
+ interface FaqSectionProps {
4
+ faq: FaqEntry[];
5
+ }
6
+
7
+ export function FaqSection({ faq }: FaqSectionProps) {
8
+ return (
9
+ <div className="faq-list">
10
+ {faq.map((item) => (
11
+ <details key={item.question} className="faq-item">
12
+ <summary>{item.question}</summary>
13
+ <p>{item.answer}</p>
14
+ </details>
15
+ ))}
16
+ </div>
17
+ );
18
+ }
app/frontend/src/components/FooterCta.tsx ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { CtaContent } from "../content/types";
2
+
3
+ interface FooterCtaProps {
4
+ cta: CtaContent;
5
+ }
6
+
7
+ export function FooterCta({ cta }: FooterCtaProps) {
8
+ return (
9
+ <section className="footer-cta shell-block">
10
+ <div>
11
+ <p className="section-kicker">Launchpad</p>
12
+ <h2>{cta.title}</h2>
13
+ <p>{cta.body}</p>
14
+ </div>
15
+ <div className="cta-actions">
16
+ {cta.buttons.map((button, index) => (
17
+ <a key={button.label} className={index === 0 ? "button primary" : "button ghost"} href={button.href}>
18
+ {button.label}
19
+ </a>
20
+ ))}
21
+ </div>
22
+ </section>
23
+ );
24
+ }
app/frontend/src/components/Hero.tsx ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { HeroContent } from "../content/types";
2
+
3
+ interface HeroProps {
4
+ hero: HeroContent;
5
+ demoMode: boolean;
6
+ }
7
+
8
+ export function Hero({ hero, demoMode }: HeroProps) {
9
+ return (
10
+ <section className="hero shell-block">
11
+ <div className="hero-copy">
12
+ <p className="section-kicker">{hero.eyebrow}</p>
13
+ <h1>{hero.title}</h1>
14
+ <p className="hero-statement">{hero.statement}</p>
15
+ <p className="hero-trust">{hero.trustLine}</p>
16
+ <div className="hero-actions">
17
+ {hero.ctas.map((cta, index) => (
18
+ <a
19
+ key={cta.label}
20
+ className={index === 0 ? "button primary" : "button ghost"}
21
+ href={cta.href}
22
+ >
23
+ {cta.label}
24
+ </a>
25
+ ))}
26
+ </div>
27
+ <div className="hero-metrics">
28
+ {hero.metrics.map((metric) => (
29
+ <div key={metric.label} className="metric-card">
30
+ <strong>{metric.value}</strong>
31
+ <span>{metric.label}</span>
32
+ </div>
33
+ ))}
34
+ </div>
35
+ </div>
36
+ <div className="hero-visual">
37
+ <div className="signal-panel">
38
+ <div className="signal-grid" />
39
+ <div className="signal-wave signal-wave-a" />
40
+ <div className="signal-wave signal-wave-b" />
41
+ <div className="signal-wave signal-wave-c" />
42
+ <div className="signal-status">
43
+ <span>routing clarity</span>
44
+ <span>{demoMode ? "public-safe demo surface" : "live-ready surface"}</span>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ </section>
49
+ );
50
+ }
app/frontend/src/components/OverviewGrid.tsx ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { FeatureCard } from "../content/types";
2
+
3
+ interface OverviewGridProps {
4
+ features: FeatureCard[];
5
+ }
6
+
7
+ export function OverviewGrid({ features }: OverviewGridProps) {
8
+ return (
9
+ <div className="card-grid">
10
+ {features.map((feature) => (
11
+ <article key={feature.title} className="feature-card">
12
+ <div className="feature-head">
13
+ <h3>{feature.title}</h3>
14
+ <span className={`status-badge ${feature.status.replace(" ", "-")}`}>{feature.status}</span>
15
+ </div>
16
+ <p>{feature.summary}</p>
17
+ <dl>
18
+ <div>
19
+ <dt>Intended user</dt>
20
+ <dd>{feature.intendedUser}</dd>
21
+ </div>
22
+ <div>
23
+ <dt>Route target</dt>
24
+ <dd>{feature.routeTargetSummary}</dd>
25
+ </div>
26
+ </dl>
27
+ </article>
28
+ ))}
29
+ </div>
30
+ );
31
+ }
app/frontend/src/components/RouteMatrix.tsx ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useState } from "react";
2
+ import type { RouteMatrixEntry } from "../content/types";
3
+
4
+ interface RouteMatrixProps {
5
+ routes: RouteMatrixEntry[];
6
+ }
7
+
8
+ export function RouteMatrix({ routes }: RouteMatrixProps) {
9
+ const [activeRoute, setActiveRoute] = useState(routes[0]?.route ?? "");
10
+ const selected = routes.find((route) => route.route === activeRoute) ?? routes[0];
11
+
12
+ return (
13
+ <div className="matrix-layout">
14
+ <div className="matrix-list" role="tablist" aria-label="Route matrix">
15
+ {routes.map((route) => (
16
+ <button
17
+ key={route.route}
18
+ type="button"
19
+ className={route.route === selected.route ? "route-card active" : "route-card"}
20
+ onClick={() => setActiveRoute(route.route)}
21
+ >
22
+ <strong>{route.route}</strong>
23
+ <span>{route.useCase}</span>
24
+ </button>
25
+ ))}
26
+ </div>
27
+ <div className="matrix-detail">
28
+ <div className="detail-head">
29
+ <h3>{selected.route}</h3>
30
+ <span className="route-pill">{selected.outputType}</span>
31
+ </div>
32
+ <p>{selected.notes}</p>
33
+ <dl className="detail-grid">
34
+ <div>
35
+ <dt>Use case</dt>
36
+ <dd>{selected.useCase}</dd>
37
+ </div>
38
+ <div>
39
+ <dt>UI surface</dt>
40
+ <dd>{selected.uiSurface}</dd>
41
+ </div>
42
+ <div>
43
+ <dt>Models</dt>
44
+ <dd>{selected.models.join(", ")}</dd>
45
+ </div>
46
+ </dl>
47
+ <table className="matrix-table">
48
+ <thead>
49
+ <tr>
50
+ <th>Route</th>
51
+ <th>Use case</th>
52
+ <th>Output</th>
53
+ <th>UI surface</th>
54
+ </tr>
55
+ </thead>
56
+ <tbody>
57
+ {routes.map((route) => (
58
+ <tr key={route.route}>
59
+ <td>{route.route}</td>
60
+ <td>{route.useCase}</td>
61
+ <td>{route.outputType}</td>
62
+ <td>{route.uiSurface}</td>
63
+ </tr>
64
+ ))}
65
+ </tbody>
66
+ </table>
67
+ </div>
68
+ </div>
69
+ );
70
+ }
app/frontend/src/components/Section.tsx ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { PropsWithChildren, ReactNode } from "react";
2
+
3
+ interface SectionProps extends PropsWithChildren {
4
+ id: string;
5
+ kicker: string;
6
+ title: string;
7
+ description: string;
8
+ aside?: ReactNode;
9
+ }
10
+
11
+ export function Section({ id, kicker, title, description, aside, children }: SectionProps) {
12
+ return (
13
+ <section id={id} className="section shell-block">
14
+ <div className="section-header">
15
+ <div>
16
+ <p className="section-kicker">{kicker}</p>
17
+ <h2>{title}</h2>
18
+ <p className="section-description">{description}</p>
19
+ </div>
20
+ {aside ? <div className="section-aside">{aside}</div> : null}
21
+ </div>
22
+ {children}
23
+ </section>
24
+ );
25
+ }
app/frontend/src/components/StudioSection.tsx ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { SeedVoice, StudioNarrative } from "../content/types";
2
+
3
+ interface StudioSectionProps {
4
+ narrative: StudioNarrative;
5
+ seedLibrary: SeedVoice[];
6
+ }
7
+
8
+ export function StudioSection({ narrative, seedLibrary }: StudioSectionProps) {
9
+ return (
10
+ <div className="studio-layout">
11
+ <div className="studio-story">
12
+ <h3>{narrative.headline}</h3>
13
+ <p>{narrative.body}</p>
14
+ <div className="pillar-grid">
15
+ {narrative.pillars.map((pillar) => (
16
+ <article key={pillar.title} className="pillar-card">
17
+ <h4>{pillar.title}</h4>
18
+ <p>{pillar.description}</p>
19
+ </article>
20
+ ))}
21
+ </div>
22
+ </div>
23
+ <div className="studio-assets">
24
+ <div className="image-card">
25
+ <img src="/public/studio-surface.svg" alt="Aether Voice Studio workflow illustration" />
26
+ </div>
27
+ <div className="seed-list">
28
+ <div className="seed-list-head">
29
+ <h4>Seed voice library</h4>
30
+ <span>{seedLibrary.length} curated entries</span>
31
+ </div>
32
+ {seedLibrary.map((voice) => (
33
+ <article key={voice.id} className="seed-card">
34
+ <div>
35
+ <h5>{voice.name}</h5>
36
+ <p>{voice.persona}</p>
37
+ </div>
38
+ <span className="route-pill">{voice.route}</span>
39
+ <p className="seed-purpose">{voice.bestFor}</p>
40
+ <div className="tag-row">
41
+ {voice.styleTags.map((tag) => (
42
+ <span key={tag}>{tag}</span>
43
+ ))}
44
+ </div>
45
+ </article>
46
+ ))}
47
+ </div>
48
+ </div>
49
+ </div>
50
+ );
51
+ }
app/frontend/src/components/TopNav.tsx ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { NavLink } from "../content/types";
2
+
3
+ interface TopNavProps {
4
+ links: NavLink[];
5
+ secondaryLinks: NavLink[];
6
+ demoMode: boolean;
7
+ }
8
+
9
+ export function TopNav({ links, secondaryLinks, demoMode }: TopNavProps) {
10
+ return (
11
+ <header className="topnav shell-block" id="top">
12
+ <div className="brand-block">
13
+ <div className="brand-mark" aria-hidden="true">
14
+ <span />
15
+ <span />
16
+ </div>
17
+ <div>
18
+ <p className="brand-name">AetherOps</p>
19
+ <p className="brand-subtitle">Aether Voice Studio</p>
20
+ </div>
21
+ </div>
22
+ <nav className="primary-nav" aria-label="Primary">
23
+ {links.map((link) => (
24
+ <a key={link.label} href={link.href}>
25
+ {link.label}
26
+ </a>
27
+ ))}
28
+ </nav>
29
+ <div className="nav-meta">
30
+ <span className={`mode-chip ${demoMode ? "demo" : "live"}`}>
31
+ {demoMode ? "DEMO_MODE" : "LIVE_MODE"}
32
+ </span>
33
+ {secondaryLinks.map((link) => (
34
+ <a
35
+ key={link.label}
36
+ href={link.href}
37
+ target={link.href.startsWith("http") ? "_blank" : undefined}
38
+ rel={link.href.startsWith("http") ? "noreferrer" : undefined}
39
+ >
40
+ {link.label}
41
+ </a>
42
+ ))}
43
+ </div>
44
+ </header>
45
+ );
46
+ }
app/frontend/src/components/WorkflowShowcase.tsx ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useState } from "react";
2
+ import { runDemo } from "../content/api";
3
+ import type { DemoResult, SimpleWorkflowCard, WorkflowCard } from "../content/types";
4
+
5
+ interface WorkflowShowcaseProps {
6
+ demoWorkflows: WorkflowCard[];
7
+ creatorWorkflows: SimpleWorkflowCard[];
8
+ enterpriseWorkflows: SimpleWorkflowCard[];
9
+ demoMode: boolean;
10
+ }
11
+
12
+ export function WorkflowShowcase({
13
+ demoWorkflows,
14
+ creatorWorkflows,
15
+ enterpriseWorkflows,
16
+ demoMode,
17
+ }: WorkflowShowcaseProps) {
18
+ const [selectedId, setSelectedId] = useState<string>(demoWorkflows[0]?.id ?? "");
19
+ const [result, setResult] = useState<DemoResult["result"] | null>(null);
20
+ const [loading, setLoading] = useState(false);
21
+
22
+ async function handleRun(workflowId: string) {
23
+ setSelectedId(workflowId);
24
+ setLoading(true);
25
+ try {
26
+ const response = await runDemo(workflowId);
27
+ setResult(response.result);
28
+ } finally {
29
+ setLoading(false);
30
+ }
31
+ }
32
+
33
+ return (
34
+ <div className="workflow-stack">
35
+ <div className="demo-workbench">
36
+ <div className="workbench-copy">
37
+ <h3>Controlled demo workflows</h3>
38
+ <p>
39
+ {demoMode
40
+ ? "Demo responses are simulated from local metadata so the Space remains polished without private infrastructure."
41
+ : "Responses can be switched to live behavior later without changing the surface model."}
42
+ </p>
43
+ </div>
44
+ <div className="workflow-grid">
45
+ {demoWorkflows.map((workflow) => (
46
+ <article key={workflow.id} className="workflow-card">
47
+ <div className="workflow-head">
48
+ <h4>{workflow.title}</h4>
49
+ <span className="route-pill">{workflow.route}</span>
50
+ </div>
51
+ <p>{workflow.summary}</p>
52
+ <p className="workflow-outcome">{workflow.outcome}</p>
53
+ <button
54
+ type="button"
55
+ className="button ghost"
56
+ onClick={() => handleRun(workflow.id)}
57
+ disabled={loading && selectedId === workflow.id}
58
+ >
59
+ {loading && selectedId === workflow.id ? "Running..." : "Preview demo"}
60
+ </button>
61
+ </article>
62
+ ))}
63
+ </div>
64
+ <div className="demo-console">
65
+ <div className="console-head">
66
+ <h4>Demo console</h4>
67
+ <span>{selectedId || "select a workflow"}</span>
68
+ </div>
69
+ {result ? (
70
+ <div className="console-body">
71
+ <strong>{result.headline}</strong>
72
+ <p>{result.details}</p>
73
+ <code>{result.artifact}</code>
74
+ </div>
75
+ ) : (
76
+ <div className="console-body muted">
77
+ <p>Select a workflow to view the simulated output contract.</p>
78
+ </div>
79
+ )}
80
+ </div>
81
+ </div>
82
+
83
+ <div className="lane-grid">
84
+ <div className="lane-card">
85
+ <h3>Creator workflows</h3>
86
+ {creatorWorkflows.map((workflow) => (
87
+ <article key={workflow.title}>
88
+ <h4>{workflow.title}</h4>
89
+ <p>{workflow.summary}</p>
90
+ </article>
91
+ ))}
92
+ </div>
93
+ <div className="lane-card">
94
+ <h3>Enterprise / VoiceOps workflows</h3>
95
+ {enterpriseWorkflows.map((workflow) => (
96
+ <article key={workflow.title}>
97
+ <h4>{workflow.title}</h4>
98
+ <p>{workflow.summary}</p>
99
+ </article>
100
+ ))}
101
+ </div>
102
+ </div>
103
+ </div>
104
+ );
105
+ }
app/frontend/src/content/api.ts ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { AppConfig, ContentResponse, ContractMap, DemoResult } from "./types";
2
+
3
+ async function fetchJson<T>(path: string, init?: RequestInit): Promise<T> {
4
+ const response = await fetch(path, init);
5
+ if (!response.ok) {
6
+ throw new Error(`Request failed for ${path}`);
7
+ }
8
+ return (await response.json()) as T;
9
+ }
10
+
11
+ export async function getConfig(): Promise<AppConfig> {
12
+ return fetchJson<AppConfig>("/api/config");
13
+ }
14
+
15
+ export async function getContent(): Promise<ContentResponse> {
16
+ return fetchJson<ContentResponse>("/api/content");
17
+ }
18
+
19
+ export async function getContracts(): Promise<ContractMap> {
20
+ const [voiceRegistry, routeMatrix, seedLibrary, providerConfig] = await Promise.all([
21
+ fetchJson<unknown>("/api/contracts/voice_registry"),
22
+ fetchJson<unknown>("/api/contracts/route_model_matrix"),
23
+ fetchJson<unknown>("/api/contracts/seed_voice_library"),
24
+ fetchJson<unknown>("/api/contracts/provider_config"),
25
+ ]);
26
+
27
+ return {
28
+ voice_registry: voiceRegistry,
29
+ route_model_matrix: routeMatrix,
30
+ seed_voice_library: seedLibrary,
31
+ provider_config: providerConfig,
32
+ };
33
+ }
34
+
35
+ export async function runDemo(workflowId: string): Promise<DemoResult> {
36
+ return fetchJson<DemoResult>("/api/demo/simulate", {
37
+ method: "POST",
38
+ headers: {
39
+ "Content-Type": "application/json",
40
+ },
41
+ body: JSON.stringify({ workflow_id: workflowId }),
42
+ });
43
+ }
app/frontend/src/content/types.ts ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export type Status = "live" | "in build" | "planned";
2
+
3
+ export interface NavLink {
4
+ label: string;
5
+ href: string;
6
+ }
7
+
8
+ export interface HeroMetric {
9
+ label: string;
10
+ value: string;
11
+ }
12
+
13
+ export interface HeroContent {
14
+ eyebrow: string;
15
+ title: string;
16
+ statement: string;
17
+ trustLine: string;
18
+ ctas: NavLink[];
19
+ metrics: HeroMetric[];
20
+ }
21
+
22
+ export interface StudioPillar {
23
+ title: string;
24
+ description: string;
25
+ }
26
+
27
+ export interface StudioNarrative {
28
+ headline: string;
29
+ body: string;
30
+ pillars: StudioPillar[];
31
+ }
32
+
33
+ export interface CtaContent {
34
+ title: string;
35
+ body: string;
36
+ buttons: NavLink[];
37
+ }
38
+
39
+ export interface SiteManifest {
40
+ hero: HeroContent;
41
+ navigation: NavLink[];
42
+ secondaryLinks: NavLink[];
43
+ studioNarrative: StudioNarrative;
44
+ cta: CtaContent;
45
+ }
46
+
47
+ export interface FeatureCard {
48
+ title: string;
49
+ summary: string;
50
+ intendedUser: string;
51
+ routeTargetSummary: string;
52
+ status: Status;
53
+ }
54
+
55
+ export interface RouteMatrixEntry {
56
+ route: string;
57
+ useCase: string;
58
+ outputType: string;
59
+ uiSurface: string;
60
+ models: string[];
61
+ notes: string;
62
+ }
63
+
64
+ export interface DocsEntry {
65
+ title: string;
66
+ description: string;
67
+ anchor: string;
68
+ }
69
+
70
+ export interface FaqEntry {
71
+ question: string;
72
+ answer: string;
73
+ }
74
+
75
+ export interface SeedVoice {
76
+ id: string;
77
+ name: string;
78
+ persona: string;
79
+ bestFor: string;
80
+ route: string;
81
+ styleTags: string[];
82
+ }
83
+
84
+ export interface WorkflowCard {
85
+ id: string;
86
+ title: string;
87
+ summary: string;
88
+ route: string;
89
+ outcome: string;
90
+ }
91
+
92
+ export interface SimpleWorkflowCard {
93
+ title: string;
94
+ summary: string;
95
+ }
96
+
97
+ export interface WorkflowGroups {
98
+ demo: WorkflowCard[];
99
+ creator: SimpleWorkflowCard[];
100
+ enterprise: SimpleWorkflowCard[];
101
+ }
102
+
103
+ export interface ArchitectureLayer {
104
+ name: string;
105
+ items: string[];
106
+ }
107
+
108
+ export interface ContentResponse {
109
+ site: SiteManifest;
110
+ features: FeatureCard[];
111
+ routes: RouteMatrixEntry[];
112
+ docsNav: DocsEntry[];
113
+ faq: FaqEntry[];
114
+ seedLibrary: SeedVoice[];
115
+ workflows: WorkflowGroups;
116
+ architecture: ArchitectureLayer[];
117
+ }
118
+
119
+ export interface AppConfig {
120
+ demoMode: boolean;
121
+ spaceTitle: string;
122
+ singlePort: number;
123
+ }
124
+
125
+ export interface ContractMap {
126
+ voice_registry: unknown;
127
+ route_model_matrix: unknown;
128
+ seed_voice_library: unknown;
129
+ provider_config: unknown;
130
+ }
131
+
132
+ export interface DemoResult {
133
+ demoMode: boolean;
134
+ workflowId: string;
135
+ result: {
136
+ headline: string;
137
+ details: string;
138
+ artifact: string;
139
+ };
140
+ }
app/frontend/src/main.tsx ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import App from "./App";
4
+ import "./theme/tokens.css";
5
+ import "./theme/app.css";
6
+
7
+ ReactDOM.createRoot(document.getElementById("root")!).render(
8
+ <React.StrictMode>
9
+ <App />
10
+ </React.StrictMode>,
11
+ );
app/frontend/src/theme/app.css ADDED
@@ -0,0 +1,744 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .app-shell {
2
+ width: var(--shell);
3
+ margin: 0 auto;
4
+ padding: 24px 0 48px;
5
+ }
6
+
7
+ .centered {
8
+ min-height: 100vh;
9
+ display: grid;
10
+ place-items: center;
11
+ }
12
+
13
+ .shell-block {
14
+ margin-bottom: 20px;
15
+ border: 1px solid var(--line);
16
+ background: linear-gradient(180deg, rgba(10, 24, 42, 0.92), rgba(8, 16, 30, 0.9));
17
+ backdrop-filter: blur(18px);
18
+ border-radius: var(--radius-xl);
19
+ box-shadow: var(--shadow);
20
+ }
21
+
22
+ .topnav,
23
+ .section,
24
+ .footer-cta,
25
+ .hero {
26
+ padding: 22px;
27
+ }
28
+
29
+ .topnav {
30
+ display: grid;
31
+ grid-template-columns: auto 1fr auto;
32
+ gap: 18px;
33
+ align-items: center;
34
+ position: sticky;
35
+ top: 14px;
36
+ z-index: 10;
37
+ }
38
+
39
+ .brand-block {
40
+ display: flex;
41
+ align-items: center;
42
+ gap: 14px;
43
+ }
44
+
45
+ .brand-mark {
46
+ width: 44px;
47
+ height: 44px;
48
+ border-radius: 14px;
49
+ display: grid;
50
+ place-items: center;
51
+ background: linear-gradient(135deg, rgba(92, 210, 255, 0.22), rgba(132, 255, 225, 0.1));
52
+ border: 1px solid var(--line-strong);
53
+ position: relative;
54
+ overflow: hidden;
55
+ }
56
+
57
+ .brand-mark span {
58
+ position: absolute;
59
+ width: 24px;
60
+ height: 2px;
61
+ background: linear-gradient(90deg, transparent, var(--accent), transparent);
62
+ }
63
+
64
+ .brand-mark span:first-child {
65
+ transform: rotate(25deg);
66
+ }
67
+
68
+ .brand-mark span:last-child {
69
+ transform: rotate(-25deg);
70
+ }
71
+
72
+ .brand-name,
73
+ .brand-subtitle,
74
+ .section-kicker,
75
+ .section-description,
76
+ .hero-trust,
77
+ .metric-card span,
78
+ .feature-card dt,
79
+ .workflow-outcome,
80
+ .seed-purpose,
81
+ .nav-meta a,
82
+ .route-card span,
83
+ .lane-card p,
84
+ .doc-card p,
85
+ .faq-item p,
86
+ .contract-meta a {
87
+ color: var(--muted);
88
+ }
89
+
90
+ .brand-name,
91
+ .brand-subtitle {
92
+ margin: 0;
93
+ }
94
+
95
+ .brand-name {
96
+ font-size: 0.78rem;
97
+ text-transform: uppercase;
98
+ letter-spacing: 0.14em;
99
+ }
100
+
101
+ .brand-subtitle {
102
+ font-size: 0.98rem;
103
+ }
104
+
105
+ .primary-nav,
106
+ .nav-meta {
107
+ display: flex;
108
+ flex-wrap: wrap;
109
+ align-items: center;
110
+ gap: 14px;
111
+ }
112
+
113
+ .primary-nav {
114
+ justify-content: center;
115
+ }
116
+
117
+ .primary-nav a,
118
+ .nav-meta a,
119
+ .doc-card,
120
+ .faq-item summary {
121
+ transition: color 160ms ease, border-color 160ms ease, background 160ms ease, transform 160ms ease;
122
+ }
123
+
124
+ .primary-nav a:hover,
125
+ .nav-meta a:hover,
126
+ .doc-card:hover,
127
+ .faq-item summary:hover {
128
+ color: var(--text);
129
+ }
130
+
131
+ .mode-chip,
132
+ .route-pill,
133
+ .status-badge {
134
+ display: inline-flex;
135
+ align-items: center;
136
+ justify-content: center;
137
+ min-height: 28px;
138
+ padding: 0 12px;
139
+ border-radius: 999px;
140
+ border: 1px solid var(--line-strong);
141
+ background: var(--accent-soft);
142
+ font-size: 0.78rem;
143
+ }
144
+
145
+ .mode-chip.demo,
146
+ .status-badge.live {
147
+ color: var(--good);
148
+ }
149
+
150
+ .mode-chip.live,
151
+ .status-badge.in-build {
152
+ color: var(--warn);
153
+ }
154
+
155
+ .status-badge.planned {
156
+ color: var(--planned);
157
+ }
158
+
159
+ .hero {
160
+ display: grid;
161
+ grid-template-columns: 1.2fr 0.8fr;
162
+ gap: 24px;
163
+ overflow: hidden;
164
+ }
165
+
166
+ .hero-copy h1,
167
+ .section h2,
168
+ .footer-cta h2,
169
+ .workbench-copy h3,
170
+ .detail-head h3,
171
+ .studio-story h3,
172
+ .lane-card h3,
173
+ .contract-meta strong,
174
+ .arch-card h3,
175
+ .doc-card h3,
176
+ .image-card img,
177
+ .seed-list-head h4 {
178
+ font-family: var(--title-font);
179
+ }
180
+
181
+ .hero-copy h1 {
182
+ margin: 10px 0 14px;
183
+ font-size: clamp(2.9rem, 6vw, 5.6rem);
184
+ line-height: 0.94;
185
+ max-width: 9ch;
186
+ }
187
+
188
+ .hero-statement {
189
+ font-size: 1.08rem;
190
+ line-height: 1.7;
191
+ max-width: 60ch;
192
+ }
193
+
194
+ .hero-trust {
195
+ margin-top: 18px;
196
+ max-width: 62ch;
197
+ }
198
+
199
+ .button {
200
+ display: inline-flex;
201
+ align-items: center;
202
+ justify-content: center;
203
+ min-height: 48px;
204
+ padding: 0 18px;
205
+ border-radius: 999px;
206
+ border: 1px solid var(--line-strong);
207
+ cursor: pointer;
208
+ }
209
+
210
+ .button.primary {
211
+ background: linear-gradient(135deg, #5cd2ff, #84ffe1);
212
+ color: #041018;
213
+ font-weight: 600;
214
+ border-color: transparent;
215
+ }
216
+
217
+ .button.ghost {
218
+ background: rgba(255, 255, 255, 0.02);
219
+ color: var(--text);
220
+ }
221
+
222
+ .hero-actions,
223
+ .cta-actions {
224
+ display: flex;
225
+ flex-wrap: wrap;
226
+ gap: 12px;
227
+ margin-top: 22px;
228
+ }
229
+
230
+ .hero-metrics {
231
+ display: grid;
232
+ grid-template-columns: repeat(3, minmax(0, 1fr));
233
+ gap: 12px;
234
+ margin-top: 26px;
235
+ }
236
+
237
+ .metric-card,
238
+ .feature-card,
239
+ .pillar-card,
240
+ .seed-card,
241
+ .route-card,
242
+ .workflow-card,
243
+ .demo-console,
244
+ .lane-card,
245
+ .doc-card,
246
+ .arch-card,
247
+ .faq-item,
248
+ .contract-viewer,
249
+ .error-card,
250
+ .loading-card {
251
+ border: 1px solid var(--line);
252
+ background: linear-gradient(180deg, rgba(14, 30, 48, 0.82), rgba(8, 18, 32, 0.88));
253
+ border-radius: var(--radius-lg);
254
+ }
255
+
256
+ .metric-card {
257
+ padding: 16px;
258
+ }
259
+
260
+ .metric-card strong {
261
+ display: block;
262
+ font-size: 1.4rem;
263
+ margin-bottom: 6px;
264
+ }
265
+
266
+ .hero-visual {
267
+ display: flex;
268
+ align-items: stretch;
269
+ }
270
+
271
+ .signal-panel {
272
+ position: relative;
273
+ flex: 1;
274
+ min-height: 420px;
275
+ border-radius: calc(var(--radius-xl) - 4px);
276
+ overflow: hidden;
277
+ border: 1px solid var(--line);
278
+ background:
279
+ radial-gradient(circle at center, rgba(92, 210, 255, 0.14), transparent 34%),
280
+ linear-gradient(180deg, rgba(14, 30, 52, 0.95), rgba(8, 16, 28, 0.95));
281
+ }
282
+
283
+ .signal-grid {
284
+ position: absolute;
285
+ inset: 0;
286
+ background-image:
287
+ linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
288
+ linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
289
+ background-size: 32px 32px;
290
+ mask-image: linear-gradient(180deg, rgba(0, 0, 0, 1), transparent);
291
+ }
292
+
293
+ .signal-wave {
294
+ position: absolute;
295
+ left: 8%;
296
+ right: 8%;
297
+ height: 2px;
298
+ border-radius: 999px;
299
+ background: linear-gradient(90deg, transparent, var(--accent), transparent);
300
+ box-shadow: 0 0 28px rgba(92, 210, 255, 0.42);
301
+ animation: drift 8s ease-in-out infinite;
302
+ }
303
+
304
+ .signal-wave-a {
305
+ top: 28%;
306
+ }
307
+
308
+ .signal-wave-b {
309
+ top: 50%;
310
+ animation-delay: -2s;
311
+ }
312
+
313
+ .signal-wave-c {
314
+ top: 72%;
315
+ animation-delay: -4s;
316
+ }
317
+
318
+ .signal-status {
319
+ position: absolute;
320
+ left: 24px;
321
+ right: 24px;
322
+ bottom: 24px;
323
+ display: flex;
324
+ justify-content: space-between;
325
+ gap: 16px;
326
+ padding-top: 16px;
327
+ border-top: 1px solid var(--line);
328
+ text-transform: uppercase;
329
+ letter-spacing: 0.08em;
330
+ font-size: 0.78rem;
331
+ }
332
+
333
+ .section-header {
334
+ display: grid;
335
+ grid-template-columns: 1fr auto;
336
+ gap: 18px;
337
+ margin-bottom: 24px;
338
+ align-items: end;
339
+ }
340
+
341
+ .section-kicker {
342
+ margin: 0 0 8px;
343
+ text-transform: uppercase;
344
+ letter-spacing: 0.16em;
345
+ font-size: 0.78rem;
346
+ }
347
+
348
+ .section h2,
349
+ .footer-cta h2 {
350
+ margin: 0 0 10px;
351
+ font-size: clamp(1.9rem, 4vw, 3.2rem);
352
+ line-height: 1;
353
+ max-width: 15ch;
354
+ }
355
+
356
+ .section-description,
357
+ .footer-cta p {
358
+ max-width: 70ch;
359
+ line-height: 1.7;
360
+ }
361
+
362
+ .card-grid,
363
+ .pillar-grid,
364
+ .workflow-grid,
365
+ .docs-portal,
366
+ .architecture-grid {
367
+ display: grid;
368
+ gap: 16px;
369
+ }
370
+
371
+ .card-grid {
372
+ grid-template-columns: repeat(4, minmax(0, 1fr));
373
+ }
374
+
375
+ .feature-card,
376
+ .doc-card,
377
+ .arch-card,
378
+ .workflow-card,
379
+ .lane-card {
380
+ padding: 18px;
381
+ }
382
+
383
+ .feature-head,
384
+ .workflow-head,
385
+ .detail-head,
386
+ .console-head,
387
+ .seed-list-head,
388
+ .contract-meta {
389
+ display: flex;
390
+ align-items: center;
391
+ justify-content: space-between;
392
+ gap: 12px;
393
+ }
394
+
395
+ .feature-card h3,
396
+ .workflow-card h4,
397
+ .lane-card h4,
398
+ .doc-card h3,
399
+ .arch-card h3,
400
+ .faq-item summary,
401
+ .seed-card h5,
402
+ .studio-story h3 {
403
+ margin: 0;
404
+ }
405
+
406
+ .feature-card p,
407
+ .workflow-card p,
408
+ .lane-card p,
409
+ .doc-card p,
410
+ .arch-card li,
411
+ .faq-item p,
412
+ .seed-card p,
413
+ .studio-story p,
414
+ .pillar-card p {
415
+ line-height: 1.65;
416
+ }
417
+
418
+ .feature-card dl,
419
+ .detail-grid {
420
+ display: grid;
421
+ gap: 14px;
422
+ margin: 18px 0 0;
423
+ }
424
+
425
+ .feature-card dd,
426
+ .feature-card dt,
427
+ .detail-grid dt,
428
+ .detail-grid dd {
429
+ margin: 0;
430
+ }
431
+
432
+ .feature-card dt,
433
+ .detail-grid dt {
434
+ margin-bottom: 4px;
435
+ font-size: 0.8rem;
436
+ text-transform: uppercase;
437
+ letter-spacing: 0.08em;
438
+ }
439
+
440
+ .studio-layout,
441
+ .matrix-layout,
442
+ .architecture-layout,
443
+ .contracts-layout,
444
+ .footer-cta {
445
+ display: grid;
446
+ gap: 18px;
447
+ }
448
+
449
+ .studio-layout,
450
+ .matrix-layout,
451
+ .architecture-layout {
452
+ grid-template-columns: 1.05fr 0.95fr;
453
+ }
454
+
455
+ .studio-story,
456
+ .seed-list,
457
+ .matrix-detail,
458
+ .lane-card {
459
+ display: grid;
460
+ gap: 16px;
461
+ }
462
+
463
+ .studio-assets {
464
+ display: grid;
465
+ gap: 16px;
466
+ }
467
+
468
+ .image-card {
469
+ overflow: hidden;
470
+ border-radius: var(--radius-lg);
471
+ border: 1px solid var(--line);
472
+ background: linear-gradient(180deg, rgba(10, 20, 34, 0.88), rgba(9, 16, 26, 0.96));
473
+ }
474
+
475
+ .seed-list {
476
+ padding: 18px;
477
+ border: 1px solid var(--line);
478
+ border-radius: var(--radius-lg);
479
+ background: rgba(7, 17, 31, 0.72);
480
+ }
481
+
482
+ .seed-card {
483
+ padding: 16px;
484
+ }
485
+
486
+ .tag-row {
487
+ display: flex;
488
+ flex-wrap: wrap;
489
+ gap: 8px;
490
+ }
491
+
492
+ .tag-row span {
493
+ padding: 6px 10px;
494
+ border-radius: 999px;
495
+ border: 1px solid var(--line);
496
+ color: var(--muted);
497
+ font-size: 0.8rem;
498
+ }
499
+
500
+ .matrix-list {
501
+ display: grid;
502
+ gap: 12px;
503
+ }
504
+
505
+ .route-card {
506
+ padding: 18px;
507
+ text-align: left;
508
+ cursor: pointer;
509
+ }
510
+
511
+ .route-card.active {
512
+ border-color: var(--line-strong);
513
+ background: linear-gradient(180deg, rgba(21, 43, 66, 0.92), rgba(10, 20, 34, 0.92));
514
+ }
515
+
516
+ .matrix-detail {
517
+ padding: 20px;
518
+ border: 1px solid var(--line);
519
+ border-radius: var(--radius-lg);
520
+ background: rgba(8, 18, 32, 0.72);
521
+ }
522
+
523
+ .matrix-table {
524
+ width: 100%;
525
+ border-collapse: collapse;
526
+ font-size: 0.94rem;
527
+ }
528
+
529
+ .matrix-table th,
530
+ .matrix-table td {
531
+ padding: 12px 10px;
532
+ text-align: left;
533
+ border-top: 1px solid var(--line);
534
+ vertical-align: top;
535
+ }
536
+
537
+ .workflow-stack {
538
+ display: grid;
539
+ gap: 20px;
540
+ }
541
+
542
+ .demo-workbench {
543
+ display: grid;
544
+ gap: 16px;
545
+ }
546
+
547
+ .demo-console {
548
+ padding: 18px;
549
+ }
550
+
551
+ .console-body code {
552
+ display: inline-flex;
553
+ margin-top: 10px;
554
+ padding: 8px 12px;
555
+ border-radius: 999px;
556
+ background: rgba(92, 210, 255, 0.1);
557
+ color: var(--accent-strong);
558
+ }
559
+
560
+ .console-body.muted {
561
+ color: var(--muted);
562
+ }
563
+
564
+ .lane-grid {
565
+ display: grid;
566
+ grid-template-columns: repeat(2, minmax(0, 1fr));
567
+ gap: 16px;
568
+ }
569
+
570
+ .lane-card {
571
+ align-content: start;
572
+ }
573
+
574
+ .lane-card article {
575
+ padding-top: 12px;
576
+ border-top: 1px solid var(--line);
577
+ }
578
+
579
+ .docs-portal {
580
+ grid-template-columns: repeat(3, minmax(0, 1fr));
581
+ }
582
+
583
+ .doc-card:hover {
584
+ transform: translateY(-2px);
585
+ border-color: var(--line-strong);
586
+ }
587
+
588
+ .architecture-grid {
589
+ grid-template-columns: repeat(2, minmax(0, 1fr));
590
+ }
591
+
592
+ .arch-card ul {
593
+ margin: 0;
594
+ padding-left: 18px;
595
+ color: var(--muted);
596
+ }
597
+
598
+ .contracts-layout {
599
+ grid-template-columns: 280px 1fr;
600
+ }
601
+
602
+ .contract-tabs {
603
+ display: grid;
604
+ gap: 10px;
605
+ }
606
+
607
+ .contract-tab {
608
+ min-height: 56px;
609
+ padding: 0 16px;
610
+ text-align: left;
611
+ color: var(--text);
612
+ border-radius: 16px;
613
+ border: 1px solid var(--line);
614
+ background: rgba(9, 20, 34, 0.7);
615
+ cursor: pointer;
616
+ }
617
+
618
+ .contract-tab.active {
619
+ border-color: var(--line-strong);
620
+ background: rgba(18, 37, 58, 0.92);
621
+ }
622
+
623
+ .contract-viewer {
624
+ padding: 18px;
625
+ }
626
+
627
+ .contract-viewer pre {
628
+ margin: 14px 0 0;
629
+ padding: 18px;
630
+ overflow: auto;
631
+ border-radius: 18px;
632
+ background: rgba(4, 10, 18, 0.86);
633
+ border: 1px solid rgba(132, 255, 225, 0.1);
634
+ color: #d5f2ff;
635
+ font-size: 0.9rem;
636
+ line-height: 1.55;
637
+ }
638
+
639
+ .faq-list {
640
+ display: grid;
641
+ gap: 14px;
642
+ }
643
+
644
+ .faq-item {
645
+ padding: 18px;
646
+ }
647
+
648
+ .faq-item summary {
649
+ cursor: pointer;
650
+ list-style: none;
651
+ font-weight: 600;
652
+ }
653
+
654
+ .faq-item summary::-webkit-details-marker {
655
+ display: none;
656
+ }
657
+
658
+ .faq-item p {
659
+ margin: 14px 0 0;
660
+ }
661
+
662
+ .footer-cta {
663
+ grid-template-columns: 1fr auto;
664
+ align-items: center;
665
+ }
666
+
667
+ .error-card,
668
+ .loading-card {
669
+ padding: 28px;
670
+ max-width: 680px;
671
+ }
672
+
673
+ @keyframes drift {
674
+ 0%,
675
+ 100% {
676
+ transform: translateY(0) scaleX(0.92);
677
+ opacity: 0.35;
678
+ }
679
+ 50% {
680
+ transform: translateY(-14px) scaleX(1);
681
+ opacity: 1;
682
+ }
683
+ }
684
+
685
+ @media (max-width: 1100px) {
686
+ .topnav,
687
+ .hero,
688
+ .studio-layout,
689
+ .matrix-layout,
690
+ .architecture-layout,
691
+ .contracts-layout,
692
+ .footer-cta {
693
+ grid-template-columns: 1fr;
694
+ }
695
+
696
+ .topnav {
697
+ position: static;
698
+ }
699
+
700
+ .card-grid,
701
+ .docs-portal,
702
+ .architecture-grid,
703
+ .lane-grid {
704
+ grid-template-columns: repeat(2, minmax(0, 1fr));
705
+ }
706
+ }
707
+
708
+ @media (max-width: 720px) {
709
+ .app-shell {
710
+ width: min(100vw - 20px, var(--shell));
711
+ padding-top: 10px;
712
+ }
713
+
714
+ .topnav,
715
+ .section,
716
+ .footer-cta,
717
+ .hero {
718
+ padding: 18px;
719
+ }
720
+
721
+ .hero-metrics,
722
+ .card-grid,
723
+ .docs-portal,
724
+ .architecture-grid,
725
+ .lane-grid {
726
+ grid-template-columns: 1fr;
727
+ }
728
+
729
+ .section-header {
730
+ grid-template-columns: 1fr;
731
+ }
732
+
733
+ .signal-panel {
734
+ min-height: 280px;
735
+ }
736
+
737
+ .primary-nav {
738
+ justify-content: flex-start;
739
+ }
740
+
741
+ .nav-meta {
742
+ justify-content: flex-start;
743
+ }
744
+ }
app/frontend/src/theme/tokens.css ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=IBM+Plex+Sans:wght@400;500;600&display=swap");
2
+
3
+ :root {
4
+ color-scheme: dark;
5
+ --bg: #07111f;
6
+ --bg-elevated: rgba(10, 24, 42, 0.82);
7
+ --bg-strong: #0d1d32;
8
+ --panel: rgba(12, 29, 48, 0.9);
9
+ --line: rgba(137, 191, 255, 0.16);
10
+ --line-strong: rgba(137, 191, 255, 0.32);
11
+ --text: #f4f8ff;
12
+ --muted: #97aac7;
13
+ --accent: #5cd2ff;
14
+ --accent-soft: rgba(92, 210, 255, 0.14);
15
+ --accent-strong: #84ffe1;
16
+ --good: #7ff3c7;
17
+ --warn: #f9d46b;
18
+ --planned: #8ca6cc;
19
+ --shadow: 0 24px 80px rgba(2, 8, 20, 0.42);
20
+ --radius-xl: 28px;
21
+ --radius-lg: 22px;
22
+ --radius-md: 16px;
23
+ --shell: min(1220px, calc(100vw - 32px));
24
+ --title-font: "Space Grotesk", "Avenir Next", "Segoe UI", sans-serif;
25
+ --body-font: "IBM Plex Sans", "Helvetica Neue", sans-serif;
26
+ }
27
+
28
+ * {
29
+ box-sizing: border-box;
30
+ }
31
+
32
+ html {
33
+ scroll-behavior: smooth;
34
+ }
35
+
36
+ body {
37
+ margin: 0;
38
+ font-family: var(--body-font);
39
+ background:
40
+ radial-gradient(circle at top left, rgba(92, 210, 255, 0.16), transparent 30%),
41
+ radial-gradient(circle at top right, rgba(132, 255, 225, 0.12), transparent 24%),
42
+ linear-gradient(180deg, #091424 0%, #07111f 52%, #060d17 100%);
43
+ color: var(--text);
44
+ }
45
+
46
+ a {
47
+ color: inherit;
48
+ text-decoration: none;
49
+ }
50
+
51
+ button,
52
+ input,
53
+ textarea,
54
+ select {
55
+ font: inherit;
56
+ }
57
+
58
+ img {
59
+ display: block;
60
+ max-width: 100%;
61
+ }
app/frontend/tsconfig.app.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "useDefineForClassFields": true,
5
+ "lib": [
6
+ "DOM",
7
+ "DOM.Iterable",
8
+ "ES2022"
9
+ ],
10
+ "allowJs": false,
11
+ "skipLibCheck": true,
12
+ "esModuleInterop": true,
13
+ "allowSyntheticDefaultImports": true,
14
+ "strict": true,
15
+ "forceConsistentCasingInFileNames": true,
16
+ "module": "ESNext",
17
+ "moduleResolution": "Node",
18
+ "resolveJsonModule": true,
19
+ "isolatedModules": true,
20
+ "noEmit": true,
21
+ "jsx": "react-jsx"
22
+ },
23
+ "include": [
24
+ "src"
25
+ ]
26
+ }
app/frontend/tsconfig.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ {
5
+ "path": "./tsconfig.app.json"
6
+ }
7
+ ]
8
+ }
app/frontend/vite.config.ts ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { defineConfig } from "vite";
2
+ import react from "@vitejs/plugin-react";
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ server: {
7
+ port: 5173,
8
+ proxy: {
9
+ "/api": "http://localhost:7860",
10
+ "/public": "http://localhost:7860",
11
+ },
12
+ },
13
+ });
app/public/architecture-flow.svg ADDED
app/public/studio-surface.svg ADDED
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastapi==0.116.1
2
+ uvicorn[standard]==0.35.0