motionrender 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/cli.js +2634 -528
  2. package/dist/index.js +46 -1
  3. package/dist/player.js +13 -13
  4. package/dist/react.js +704 -9
  5. package/dist/types/packages/ai/src/agent.d.ts +57 -0
  6. package/dist/types/packages/ai/src/brand-scraper.d.ts +35 -0
  7. package/dist/types/packages/ai/src/captions.d.ts +11 -0
  8. package/dist/types/packages/ai/src/compose.d.ts +2 -0
  9. package/dist/types/packages/ai/src/edit.d.ts +69 -0
  10. package/dist/types/packages/ai/src/index.d.ts +8 -1
  11. package/dist/types/packages/ai/src/plan.d.ts +42 -0
  12. package/dist/types/packages/ai/src/prompt.d.ts +18 -0
  13. package/dist/types/packages/ai/src/providers.d.ts +35 -2
  14. package/dist/types/packages/ai/src/registry.d.ts +81 -0
  15. package/dist/types/packages/ai/src/retime.d.ts +7 -0
  16. package/dist/types/packages/ai/src/shorts.d.ts +75 -0
  17. package/dist/types/packages/cli/src/agent-cli.d.ts +15 -0
  18. package/dist/types/packages/cli/src/ai-studio-page.d.ts +1 -1
  19. package/dist/types/packages/cli/src/ai.d.ts +1 -1
  20. package/dist/types/packages/cli/src/build.d.ts +2 -0
  21. package/dist/types/packages/cli/src/templates.d.ts +13 -4
  22. package/dist/types/packages/contracts/src/index.d.ts +12 -12
  23. package/dist/types/packages/core/src/review.d.ts +24 -0
  24. package/dist/types/packages/ffmpeg/src/index.d.ts +1 -0
  25. package/dist/types/packages/jobs/src/queue.d.ts +2 -2
  26. package/dist/types/packages/jobs/src/redis.d.ts +2 -2
  27. package/dist/types/packages/react/src/components.d.ts +166 -0
  28. package/dist/types/packages/react/src/index.d.ts +54 -2
  29. package/dist/types/packages/react/src/springs.d.ts +25 -0
  30. package/dist/types/packages/schema/src/captions.d.ts +2 -0
  31. package/dist/types/packages/schema/src/index.d.ts +66 -66
  32. package/dist/types/scripts/eval-briefs.d.ts +67 -0
  33. package/package.json +1 -1
  34. package/skills/ove/SKILL.md +40 -2
  35. package/skills/ove-agent/SKILL.md +144 -0
  36. package/skills/ove-code-video/SKILL.md +17 -9
  37. package/skills/ove-motion-graphics/SKILL.md +113 -0
  38. package/skills/ove-react-video/SKILL.md +212 -0
  39. package/skills/ove-remotion/SKILL.md +122 -0
  40. package/studio/assets/index-DmZj9wTZ.css +1 -0
  41. package/studio/assets/index-n3DJI_GV.js +10 -0
  42. package/studio/index.html +2 -2
  43. package/templates/case-study/composition.json +25 -10
  44. package/templates/event-invite/composition.json +12 -2
  45. package/templates/explainer-square/composition.json +1 -1
  46. package/templates/keynote-wide/composition.json +2 -2
  47. package/templates/kinetic-reel/composition.json +73 -0
  48. package/templates/kinetic-reel/composition.schema.json +9295 -0
  49. package/templates/kinetic-reel/template.json +17 -0
  50. package/templates/kinetic-reel/video.bundle.js +72 -0
  51. package/templates/kinetic-reel/video.tsx +283 -0
  52. package/templates/product-card/composition.json +7 -2
  53. package/templates/product-wide/composition.json +1 -1
  54. package/templates/quote-card/composition.json +6 -1
  55. package/templates/saas-launch/composition.json +70 -0
  56. package/templates/saas-launch/composition.schema.json +9295 -0
  57. package/templates/saas-launch/template.json +16 -0
  58. package/templates/saas-launch/video.bundle.js +72 -0
  59. package/templates/saas-launch/video.tsx +217 -0
  60. package/templates/sale-promo/composition.json +16 -1
  61. package/templates/showcase-tall/composition.json +4 -4
  62. package/templates/slideshow/composition.json +1 -1
  63. package/templates/social-reel/composition.json +19 -4
  64. package/templates/story-tall/composition.json +1 -1
  65. package/studio/assets/index-CzOvWv9w.css +0 -1
  66. package/studio/assets/index-J_fvKgng.js +0 -11
@@ -0,0 +1,217 @@
1
+ import {
2
+ AbsoluteFill,
3
+ AmbientGlow,
4
+ Audio,
5
+ Badge,
6
+ DeviceFrame,
7
+ GlassCard,
8
+ KineticText,
9
+ NumberTicker,
10
+ ProgressBar,
11
+ Sequence,
12
+ useCurrentFrame,
13
+ useVideoConfig,
14
+ springValue,
15
+ } from '@ove/react';
16
+
17
+ export const config = {
18
+ id: 'saas-launch',
19
+ name: 'Modern SaaS Launch (React)',
20
+ width: 1920,
21
+ height: 1080,
22
+ fps: 30,
23
+ durationInFrames: 180,
24
+ background: '#080c14',
25
+ props: {
26
+ badge: 'AI ENGINE 2.0',
27
+ title: 'Design Videos in React',
28
+ subtitle: 'Frame-accurate motion graphics, spring physics, and headless render speed.',
29
+ metric: 10,
30
+ metricLabel: 'Faster Video Rendering',
31
+ url: 'openvideo.dev/engine',
32
+ },
33
+ };
34
+
35
+ export default function SaasLaunchVideo({
36
+ badge,
37
+ title,
38
+ subtitle,
39
+ metric,
40
+ metricLabel,
41
+ url,
42
+ }: typeof config.props) {
43
+ const frame = useCurrentFrame();
44
+ const { fps } = useVideoConfig();
45
+
46
+ return (
47
+ <AbsoluteFill
48
+ style={{
49
+ color: '#f8fafc',
50
+ fontFamily: 'Inter, system-ui, -apple-system, sans-serif',
51
+ overflow: 'hidden',
52
+ }}
53
+ >
54
+ {/* Dynamic ambient gradient lighting */}
55
+ <AmbientGlow
56
+ orbs={[
57
+ { x: '20%', y: '18%', size: 700, color: '#6366f1', opacity: 0.28, speed: 0.02 },
58
+ { x: '80%', y: '82%', size: 850, color: '#06b6d4', opacity: 0.22, speed: 0.025 },
59
+ { x: '50%', y: '50%', size: 600, color: '#8b5cf6', opacity: 0.18, speed: 0.015 },
60
+ ]}
61
+ />
62
+
63
+ {/* Subtle background tech grid */}
64
+ <div
65
+ style={{
66
+ position: 'absolute',
67
+ inset: 0,
68
+ backgroundImage:
69
+ 'radial-gradient(rgba(255, 255, 255, 0.07) 1px, transparent 1px)',
70
+ backgroundSize: '40px 40px',
71
+ opacity: 0.5,
72
+ pointerEvents: 'none',
73
+ }}
74
+ />
75
+
76
+ {/* SCENE 1: Kinetic Opening (Frames 0 to 75) */}
77
+ <Sequence from={0} durationInFrames={75}>
78
+ <Audio src="sfx:whoosh" volume={0.6} />
79
+ <AbsoluteFill
80
+ style={{
81
+ alignItems: 'center',
82
+ justifyContent: 'center',
83
+ flexDirection: 'column',
84
+ gap: 28,
85
+ padding: 80,
86
+ }}
87
+ >
88
+ <Badge dotColor="#38bdf8" delay={4}>
89
+ {badge}
90
+ </Badge>
91
+
92
+ <h1
93
+ style={{
94
+ fontSize: 88,
95
+ fontWeight: 800,
96
+ letterSpacing: '-0.04em',
97
+ margin: 0,
98
+ textAlign: 'center',
99
+ maxWidth: 1200,
100
+ lineHeight: 1.1,
101
+ }}
102
+ >
103
+ <KineticText text={title} delay={8} preset="bouncy" />
104
+ </h1>
105
+
106
+ <p
107
+ style={{
108
+ fontSize: 26,
109
+ color: '#94a3b8',
110
+ maxWidth: 800,
111
+ textAlign: 'center',
112
+ margin: 0,
113
+ lineHeight: 1.5,
114
+ opacity: springValue({ frame, fps, delay: 24, from: 0, to: 1, preset: 'smooth' }),
115
+ transform: `translateY(${(1 - springValue({ frame, fps, delay: 24, from: 0, to: 1, preset: 'smooth' })) * 20}px)`,
116
+ }}
117
+ >
118
+ {subtitle}
119
+ </p>
120
+ </AbsoluteFill>
121
+ </Sequence>
122
+
123
+ {/* SCENE 2: Glassmorphic Bento & Metric (Frames 75 to 135) */}
124
+ <Sequence from={75} durationInFrames={60}>
125
+ <Audio src="sfx:pop" volume={0.5} />
126
+ <AbsoluteFill
127
+ style={{
128
+ alignItems: 'center',
129
+ justifyContent: 'center',
130
+ flexDirection: 'row',
131
+ gap: 40,
132
+ padding: '0 120px',
133
+ }}
134
+ >
135
+ {/* Metric Card */}
136
+ <GlassCard delay={4} style={{ width: 440, padding: 40, display: 'flex', flexDirection: 'column', gap: 16 }}>
137
+ <span style={{ fontSize: 16, color: '#94a3b8', fontWeight: 600, letterSpacing: '0.04em' }}>
138
+ PERFORMANCE
139
+ </span>
140
+ <div style={{ fontSize: 96, fontWeight: 900, color: '#38bdf8', letterSpacing: '-0.03em' }}>
141
+ <NumberTicker value={metric} decimals={0} suffix="x" delay={8} preset="bouncy" />
142
+ </div>
143
+ <span style={{ fontSize: 20, color: '#e2e8f0', fontWeight: 600 }}>
144
+ {metricLabel}
145
+ </span>
146
+ <ProgressBar value={0.88} color="#38bdf8" delay={12} />
147
+ </GlassCard>
148
+
149
+ {/* Feature Showcase Card */}
150
+ <GlassCard delay={10} style={{ width: 560, padding: 40, display: 'flex', flexDirection: 'column', gap: 20 }}>
151
+ <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
152
+ <div
153
+ style={{
154
+ width: 44,
155
+ height: 44,
156
+ borderRadius: 12,
157
+ background: 'linear-gradient(135deg, #6366f1, #06b6d4)',
158
+ display: 'flex',
159
+ alignItems: 'center',
160
+ justifyContent: 'center',
161
+ fontWeight: 800,
162
+ fontSize: 20,
163
+ }}
164
+ >
165
+ ⚛
166
+ </div>
167
+ <div>
168
+ <div style={{ fontSize: 20, fontWeight: 700 }}>Pure React Components</div>
169
+ <div style={{ fontSize: 14, color: '#94a3b8' }}>Flexbox, Springs & CSS Grid</div>
170
+ </div>
171
+ </div>
172
+ <p style={{ margin: 0, color: '#cbd5e1', fontSize: 18, lineHeight: 1.6 }}>
173
+ Build production videos with the tools you already know: React hooks, inline styles, CSS animations, and instant headless rendering.
174
+ </p>
175
+ </GlassCard>
176
+ </AbsoluteFill>
177
+ </Sequence>
178
+
179
+ {/* SCENE 3: Product Frame & Final Call To Action (Frames 135 to 180) */}
180
+ <Sequence from={135} durationInFrames={45}>
181
+ <Audio src="sfx:ding" volume={0.5} />
182
+ <AbsoluteFill
183
+ style={{
184
+ alignItems: 'center',
185
+ justifyContent: 'center',
186
+ flexDirection: 'column',
187
+ gap: 32,
188
+ }}
189
+ >
190
+ <DeviceFrame url={url} delay={4} style={{ width: 720, height: 380 }}>
191
+ <div
192
+ style={{
193
+ width: '100%',
194
+ height: '100%',
195
+ display: 'flex',
196
+ flexDirection: 'column',
197
+ alignItems: 'center',
198
+ justifyContent: 'center',
199
+ gap: 16,
200
+ background: 'linear-gradient(180deg, #0f172a 0%, #020617 100%)',
201
+ }}
202
+ >
203
+ <Badge dotColor="#10b981">LIVE NOW</Badge>
204
+ <div style={{ fontSize: 36, fontWeight: 800, letterSpacing: '-0.02em' }}>
205
+ Open Video Engine
206
+ </div>
207
+ <div style={{ fontSize: 16, color: '#64748b' }}>
208
+ Build, preview, and render in milliseconds
209
+ </div>
210
+ </div>
211
+ </DeviceFrame>
212
+ </AbsoluteFill>
213
+ </Sequence>
214
+ </AbsoluteFill>
215
+ );
216
+ }
217
+
@@ -32,6 +32,11 @@
32
32
  "name": "The offer",
33
33
  "startFrame": 0,
34
34
  "durationFrames": 210,
35
+ "camera": {
36
+ "animations": [
37
+ { "property": "zoom", "keyframes": [{ "frame": 0, "value": 1 }, { "frame": 210, "value": 1.08, "easing": "drift" }] }
38
+ ]
39
+ },
35
40
  "transitionIn": { "type": "fade", "durationFrames": 10 },
36
41
  "transitionOut": { "type": "fade", "durationFrames": 10 },
37
42
  "layers": [
@@ -141,6 +146,11 @@
141
146
  "name": "The code",
142
147
  "startFrame": 210,
143
148
  "durationFrames": 150,
149
+ "camera": {
150
+ "animations": [
151
+ { "property": "zoom", "keyframes": [{ "frame": 0, "value": 1 }, { "frame": 150, "value": 1.08, "easing": "drift" }] }
152
+ ]
153
+ },
144
154
  "transitionIn": { "type": "slide", "direction": "bottom", "durationFrames": 16 },
145
155
  "transitionOut": { "type": "fade", "durationFrames": 10 },
146
156
  "layers": [
@@ -206,7 +216,7 @@
206
216
  "content": "{{detail}}",
207
217
  "x": 540,
208
218
  "y": 810,
209
- "fontSize": 34,
219
+ "fontSize": 30,
210
220
  "lineHeight": 1.5,
211
221
  "textAlign": "center",
212
222
  "maxWidth": 760,
@@ -220,6 +230,11 @@
220
230
  "name": "Call to action",
221
231
  "startFrame": 360,
222
232
  "durationFrames": 90,
233
+ "camera": {
234
+ "animations": [
235
+ { "property": "zoom", "keyframes": [{ "frame": 0, "value": 1 }, { "frame": 90, "value": 1.08, "easing": "drift" }] }
236
+ ]
237
+ },
223
238
  "transitionIn": { "type": "fade", "durationFrames": 12 },
224
239
  "transitionOut": { "type": "fade", "durationFrames": 10 },
225
240
  "layers": [
@@ -448,7 +448,7 @@
448
448
  "x": "{{round(canvas.width * 0.08)}}",
449
449
  "y": "{{round(canvas.height * 0.35)}}",
450
450
  "width": "{{round(canvas.width * 0.84)}}",
451
- "height": "{{round(canvas.height * 0.57)}}",
451
+ "height": "{{round(canvas.height * 0.45)}}",
452
452
  "layout": {
453
453
  "direction": "column",
454
454
  "gap": "{{round(min(canvas.width, canvas.height) * 0.025)}}",
@@ -1285,7 +1285,7 @@
1285
1285
  "id": "label-{{index}}",
1286
1286
  "type": "text",
1287
1287
  "content": "{{it.label}}",
1288
- "fontSize": "{{round(min(canvas.width, canvas.height) * 0.046)}}",
1288
+ "fontSize": "{{round(min(canvas.width, canvas.height) * 0.05)}}",
1289
1289
  "color": "{{text}}",
1290
1290
  "fontWeight": 700,
1291
1291
  "maxWidth": "{{canvas.width > canvas.height ? round(canvas.width * 0.24) : round(canvas.width * 0.6)}}",
@@ -1296,7 +1296,7 @@
1296
1296
  "id": "detail-{{index}}",
1297
1297
  "type": "text",
1298
1298
  "content": "{{it.detail}}",
1299
- "fontSize": "{{round(min(canvas.width, canvas.height) * 0.034)}}",
1299
+ "fontSize": "{{round(min(canvas.width, canvas.height) * 0.032)}}",
1300
1300
  "color": "{{muted}}",
1301
1301
  "maxWidth": "{{canvas.width > canvas.height ? round(canvas.width * 0.24) : round(canvas.width * 0.6)}}",
1302
1302
  "maxLines": 3,
@@ -1600,7 +1600,7 @@
1600
1600
  }
1601
1601
  ],
1602
1602
  "x": "{{round(canvas.width * 0.06)}}",
1603
- "y": "{{round(canvas.height * 0.05)}}",
1603
+ "y": "{{round(canvas.height * 0.09)}}",
1604
1604
  "fontSize": "{{round(min(canvas.width, canvas.height) * 0.032)}}",
1605
1605
  "letterSpacing": "{{round(min(canvas.width, canvas.height) * 0.003)}}",
1606
1606
  "animations": [
@@ -139,7 +139,7 @@
139
139
  "content": "{{footer}}",
140
140
  "x": 160,
141
141
  "y": 970,
142
- "fontSize": 24,
142
+ "fontSize": 22,
143
143
  "letterSpacing": 3,
144
144
  "color": "#64748b"
145
145
  },
@@ -33,6 +33,11 @@
33
33
  "name": "Hook",
34
34
  "startFrame": 0,
35
35
  "durationFrames": 180,
36
+ "camera": {
37
+ "animations": [
38
+ { "property": "zoom", "keyframes": [{ "frame": 0, "value": 1 }, { "frame": 180, "value": 1.08, "easing": "drift" }] }
39
+ ]
40
+ },
36
41
  "transitionIn": { "type": "fade", "durationFrames": 12 },
37
42
  "transitionOut": { "type": "fade", "durationFrames": 12 },
38
43
  "layers": [
@@ -54,8 +59,8 @@
54
59
  "type": "text",
55
60
  "content": "{{kicker}}",
56
61
  "x": 90,
57
- "y": 150,
58
- "fontSize": 30,
62
+ "y": 230,
63
+ "fontSize": 28,
59
64
  "fontWeight": 700,
60
65
  "letterSpacing": 8,
61
66
  "color": "{{accent}}",
@@ -127,6 +132,11 @@
127
132
  "name": "Three steps",
128
133
  "startFrame": 180,
129
134
  "durationFrames": 240,
135
+ "camera": {
136
+ "animations": [
137
+ { "property": "zoom", "keyframes": [{ "frame": 0, "value": 1 }, { "frame": 240, "value": 1.08, "easing": "drift" }] }
138
+ ]
139
+ },
130
140
  "transitionIn": { "type": "slide", "direction": "left", "durationFrames": 18 },
131
141
  "transitionOut": { "type": "fade", "durationFrames": 12 },
132
142
  "layers": [
@@ -145,7 +155,7 @@
145
155
  "type": "text",
146
156
  "content": "{{stepsTitle}}",
147
157
  "x": 90,
148
- "y": 190,
158
+ "y": 250,
149
159
  "fontSize": 28,
150
160
  "fontWeight": 700,
151
161
  "letterSpacing": 7,
@@ -171,7 +181,7 @@
171
181
  "content": "{{detail}}",
172
182
  "x": 90,
173
183
  "y": 1080,
174
- "fontSize": 36,
184
+ "fontSize": 32,
175
185
  "lineHeight": 1.5,
176
186
  "maxWidth": 820,
177
187
  "maxLines": 6,
@@ -194,6 +204,11 @@
194
204
  "name": "Call to action",
195
205
  "startFrame": 420,
196
206
  "durationFrames": 180,
207
+ "camera": {
208
+ "animations": [
209
+ { "property": "zoom", "keyframes": [{ "frame": 0, "value": 1 }, { "frame": 180, "value": 1.08, "easing": "drift" }] }
210
+ ]
211
+ },
197
212
  "transitionIn": { "type": "fade", "durationFrames": 14 },
198
213
  "transitionOut": { "type": "fade", "durationFrames": 12 },
199
214
  "layers": [
@@ -1333,7 +1333,7 @@
1333
1333
  }
1334
1334
  ],
1335
1335
  "x": "{{round(canvas.width * 0.06)}}",
1336
- "y": "{{round(canvas.height * 0.05)}}",
1336
+ "y": "{{round(canvas.height * 0.09)}}",
1337
1337
  "fontSize": "{{round(min(canvas.width, canvas.height) * 0.032)}}",
1338
1338
  "letterSpacing": "{{round(min(canvas.width, canvas.height) * 0.003)}}",
1339
1339
  "animations": [
@@ -1 +0,0 @@
1
- :root{--bg: #000;--surface: #0a0a0a;--surface-2: #111;--hover: #1a1a1a;--border: #2e2e2e;--border-strong: #454545;--text: #ededed;--muted: #a1a1a1;--faint: #6b6b6b;--inverse: #000;--blue: #3291ff;--green: #50e3c2;--red: #ff6166;--amber: #f5a623;--radius: 8px;--font: "Geist", "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;--mono: "Geist Mono", ui-monospace, "SF Mono", Consolas, monospace;color-scheme:dark}:root[data-theme=light]{--bg: #fff;--surface: #fafafa;--surface-2: #f2f2f2;--hover: #ededed;--border: #eaeaea;--border-strong: #c9c9c9;--text: #171717;--muted: #666;--faint: #8f8f8f;--inverse: #fff;--blue: #0070f3;--green: #0a8f6c;--red: #e5484d;--amber: #b86e00;color-scheme:light}*{box-sizing:border-box}html,body,#root{height:100%}body{margin:0;background:var(--bg);color:var(--text);font:14px/1.5 var(--font);-webkit-font-smoothing:antialiased}a{color:var(--text);text-decoration:none}h1,h2,h3{margin:0;letter-spacing:-.02em;font-weight:600}h1{font-size:28px;line-height:1.2}h2{font-size:18px}h3{font-size:15px}::selection{background:color-mix(in srgb,var(--blue) 35%,transparent)}.shell{height:100%;display:flex;flex-direction:column}.topbar{flex:none;display:flex;align-items:center;gap:8px;height:56px;padding:0 24px;border-bottom:1px solid var(--border);background:var(--bg)}.brand,.navtabs a,.topbar .btn{white-space:nowrap}.brand{display:flex;align-items:center;gap:10px;font-weight:600;letter-spacing:-.02em;margin-right:12px}.brand svg{width:18px;height:18px;fill:var(--text)}.brand .slash{color:var(--border-strong);font-weight:300}.navtabs{display:flex;gap:2px;height:100%}.navtabs a{display:flex;align-items:center;padding:0 12px;color:var(--muted);border-bottom:2px solid transparent;margin-bottom:-1px;font-size:14px}.navtabs a:hover{color:var(--text)}.navtabs a.on{color:var(--text);border-bottom-color:var(--text)}.grow{flex:1}.busy{display:flex;align-items:center;gap:8px;color:var(--muted);font-size:13px;max-width:320px;margin-right:8px}.busy span:last-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.main{flex:1;min-height:0;overflow:auto}.main.fixed{overflow:hidden}.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;font:inherit;font-weight:500;cursor:pointer;border-radius:6px;border:1px solid transparent;white-space:nowrap;transition:background .12s,border-color .12s,color .12s}.btn.md{height:36px;padding:0 14px}.btn.sm{height:30px;padding:0 10px;font-size:13px}.btn.lg{height:42px;padding:0 18px;font-size:15px}.btn.primary{background:var(--text);color:var(--inverse)}.btn.primary:hover{background:color-mix(in srgb,var(--text) 85%,var(--bg))}.btn.secondary{background:var(--bg);color:var(--text);border-color:var(--border)}.btn.secondary:hover{background:var(--hover);border-color:var(--border-strong)}.btn.ghost{background:transparent;color:var(--muted)}.btn.ghost:hover{background:var(--hover);color:var(--text)}.btn.danger{background:var(--bg);color:var(--red);border-color:var(--border)}.btn.danger:hover{background:color-mix(in srgb,var(--red) 12%,var(--bg));border-color:var(--red)}.btn:disabled{opacity:.5;cursor:not-allowed}.btn:focus-visible,.input:focus-visible,.tile:focus-visible{outline:2px solid var(--blue);outline-offset:1px}.input,textarea.input,select.input{width:100%;background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:6px;padding:8px 12px;font:inherit;transition:border-color .12s}.input:hover{border-color:var(--border-strong)}.input:focus{border-color:var(--text);outline:none}textarea.input{resize:vertical;min-height:84px;line-height:1.5}input[type=color].input{padding:2px;height:36px;width:64px;cursor:pointer}input[type=range]{accent-color:var(--text)}.field{display:block;margin-bottom:18px}.field .label{display:block;font-size:13px;font-weight:500;margin-bottom:6px}.field .hint{display:block;color:var(--muted);font-size:12.5px;margin-top:6px}.check{display:flex;align-items:center;gap:10px;margin-bottom:14px;cursor:pointer}.check input{width:16px;height:16px;accent-color:var(--text)}.spinner{width:14px;height:14px;border:2px solid var(--border-strong);border-top-color:var(--text);border-radius:50%;animation:spin .7s linear infinite;flex:none;display:inline-block}@keyframes spin{to{transform:rotate(360deg)}}.badge{display:inline-flex;align-items:center;height:20px;padding:0 8px;border-radius:999px;font-size:12px;font-weight:500;border:1px solid var(--border);color:var(--muted)}.badge.blue{color:var(--blue);border-color:color-mix(in srgb,var(--blue) 40%,transparent)}.badge.green{color:var(--green);border-color:color-mix(in srgb,var(--green) 40%,transparent)}.badge.amber{color:var(--amber);border-color:color-mix(in srgb,var(--amber) 40%,transparent)}.badge.red{color:var(--red);border-color:color-mix(in srgb,var(--red) 40%,transparent)}.notice{border:1px solid var(--border);border-radius:var(--radius);padding:12px 14px;margin:14px 0;font-size:13.5px;color:var(--muted);background:var(--surface);white-space:pre-wrap}.notice.error{color:var(--red);border-color:color-mix(in srgb,var(--red) 45%,transparent);background:color-mix(in srgb,var(--red) 8%,var(--bg))}.notice.warn{color:var(--amber);border-color:color-mix(in srgb,var(--amber) 45%,transparent);background:color-mix(in srgb,var(--amber) 8%,var(--bg))}.empty{text-align:center;border:1px dashed var(--border-strong);border-radius:12px;padding:72px 24px;color:var(--muted)}.empty h3{color:var(--text);font-size:18px;margin-bottom:8px}.empty .btn{margin-top:16px}.page{max-width:1200px;margin:0 auto;padding:40px 24px 80px}.page.narrow{max-width:720px}.page-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin-bottom:28px}.sub{color:var(--muted);margin:6px 0 0}.toolbar{display:flex;gap:10px;margin-bottom:20px}.toolbar .input{max-width:320px}.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:16px}.card{border:1px solid var(--border);border-radius:12px;background:var(--bg);overflow:hidden;display:flex;flex-direction:column;transition:border-color .15s}.card:hover{border-color:var(--border-strong)}.thumb{aspect-ratio:16 / 10;background:var(--surface);display:flex;align-items:center;justify-content:center;cursor:pointer;border-bottom:1px solid var(--border);overflow:hidden}.thumb img{width:100%;height:100%;object-fit:contain;display:block}.thumb .ph{color:var(--faint);font-size:13px}.card-body{padding:14px 16px 6px}.card-body b{display:block;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:-.01em}.meta{color:var(--muted);font-size:13px;margin-top:2px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}.card-foot{display:flex;gap:6px;padding:10px 12px 12px}.section-title{margin:36px 0 14px;font-size:13px;font-weight:500;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}.tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin-bottom:22px}.tile{text-align:left;border:1px solid var(--border);border-radius:var(--radius);background:var(--bg);color:var(--text);padding:14px;cursor:pointer;font:inherit;transition:border-color .12s}.tile:hover{border-color:var(--border-strong)}.tile b{display:block;font-weight:600}.tile span{color:var(--muted);font-size:13px}.tile.on{border-color:var(--text);box-shadow:0 0 0 1px var(--text)}.chips{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0 22px}.chip{border:1px solid var(--border);background:var(--bg);color:var(--muted);border-radius:999px;padding:4px 12px;font:inherit;font-size:13px;cursor:pointer}.chip:hover{color:var(--text);border-color:var(--border-strong)}.drop{border:1px dashed var(--border-strong);border-radius:var(--radius);padding:22px;text-align:center;color:var(--muted);background:var(--surface)}.drop.over{border-color:var(--text);color:var(--text)}.drop a{color:var(--blue);cursor:pointer}.files{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}.files span{border:1px solid var(--border);border-radius:6px;padding:2px 8px;font-size:13px;cursor:pointer}.files span:hover{border-color:var(--red)}.two{display:grid;grid-template-columns:1fr 1fr;gap:14px}details{margin:4px 0 20px}summary{cursor:pointer;color:var(--muted);padding:4px 0}details[open] summary{margin-bottom:14px}.center{max-width:560px;margin:100px auto;text-align:center;padding:0 24px}.center .spinner{width:28px;height:28px;border-width:3px;margin-bottom:22px}.log{text-align:left;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:12px 14px;font:12.5px/1.6 var(--mono);color:var(--muted);max-height:220px;overflow:auto;white-space:pre-wrap;margin-top:18px}.swatches{display:flex;height:28px;border-radius:6px;overflow:hidden;margin-bottom:8px;border:1px solid var(--border)}.swatches i{flex:1}.kv{display:grid;grid-template-columns:180px 1fr;gap:6px 16px;padding:12px 0;border-bottom:1px solid var(--border)}.kv code{font:13px var(--mono);color:var(--muted);word-break:break-all}.editor{height:100%;display:grid;grid-template-columns:minmax(0,1fr) 400px}.stage{min-width:0;min-height:0;overflow:auto;padding:20px 24px;display:flex;flex-direction:column;gap:14px;background:var(--surface)}.etop{display:flex;align-items:center;gap:10px}.etop .input.title{border-color:transparent;background:transparent;font-weight:600;font-size:16px;width:auto;min-width:240px;padding:4px 8px}.etop .input.title:hover{border-color:var(--border)}.etop .input.title:focus{border-color:var(--text);background:var(--bg)}.saved{color:var(--muted);font-size:13px}.screen{background:#000;border:1px solid var(--border);border-radius:10px;overflow:hidden;display:flex;justify-content:center;align-items:center;min-height:200px}.screen .ove-player{margin:0 auto}.screen canvas{max-height:56vh;width:auto!important;max-width:100%;margin:0 auto}.xport{display:flex;align-items:center;gap:12px}.xport input[type=range]{flex:1}.xport .time{color:var(--muted);font:12.5px var(--mono);min-width:92px;text-align:right}.scenes{display:flex;gap:8px;overflow:auto;padding-bottom:2px}.scenes button{flex:none;display:flex;flex-direction:column;align-items:flex-start;gap:0;border:1px solid var(--border);background:var(--bg);color:var(--text);padding:6px 12px;border-radius:6px;font:inherit;font-size:13px;cursor:pointer}.scenes button:hover{border-color:var(--border-strong)}.scenes small{color:var(--muted)}.side{border-left:1px solid var(--border);background:var(--bg);display:flex;flex-direction:column;min-height:0}.tabs{display:flex;padding:0 12px;border-bottom:1px solid var(--border);flex:none}.tabs button{background:none;border:0;border-bottom:2px solid transparent;margin-bottom:-1px;color:var(--muted);padding:14px 10px;font:inherit;font-size:13.5px;cursor:pointer}.tabs button:hover{color:var(--text)}.tabs button.on{color:var(--text);border-bottom-color:var(--text)}.pane{padding:20px;overflow:auto;flex:1;min-height:0}.pane h2{font-size:15px;margin-bottom:4px}.pane .sub{margin:0 0 18px;font-size:13px}.row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 0;border-top:1px solid var(--border)}.row small{display:block;color:var(--muted)}.row b{font-weight:500}.themes{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-bottom:8px}.theme{text-align:left;border:1px solid var(--border);border-radius:var(--radius);background:var(--bg);color:var(--text);padding:8px;font:inherit;cursor:pointer}.theme:hover:not(:disabled){border-color:var(--border-strong)}.theme:disabled{opacity:.45;cursor:not-allowed}.theme b{font-weight:500;font-size:13px}.result{margin-top:18px}.result video,.result img{width:100%;border:1px solid var(--border);border-radius:var(--radius);background:#000;margin-top:10px}.toasts{position:fixed;bottom:24px;left:50%;transform:translate(-50%);display:flex;flex-direction:column;gap:8px;z-index:50;align-items:center}.toast{background:var(--text);color:var(--inverse);padding:10px 16px;border-radius:8px;font-size:14px;box-shadow:0 8px 30px #00000059;max-width:80vw}.toast.error{background:var(--red);color:#fff}.overlay{position:fixed;inset:0;background:#0009;display:flex;align-items:center;justify-content:center;z-index:40}.dialog{width:min(420px,92vw);background:var(--bg);border:1px solid var(--border);border-radius:12px;padding:22px;box-shadow:0 20px 60px #00000080}.dialog h3{margin-bottom:14px;font-size:16px;line-height:1.4}.dialog-actions{display:flex;gap:8px;justify-content:flex-end;margin-top:20px}@media(max-width:640px){.brand .slash,.brand span:last-child,.theme .lbl{display:none}.navtabs a{padding:0 8px}.topbar{gap:4px;padding:0 10px}.page-head{flex-direction:column;align-items:flex-start}}@media(max-width:900px){.editor{grid-template-columns:1fr;height:auto}.side{border-left:0;border-top:1px solid var(--border)}.main.fixed{overflow:auto}.topbar{padding:0 14px}.busy{display:none}.two{grid-template-columns:1fr}.page{padding-top:24px}}