@effectnode/media 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backend/movie-backend/generation-queue.js +99 -43
- package/frontend/index.html +8 -1
- package/frontend/public/lambobo.png +0 -0
- package/frontend/src/movie-app/MediaStudio.tsx +6 -2
- package/frontend/src/movie-app/SetupPage.tsx +98 -63
- package/frontend/src/movie-app/components/Aurora.tsx +13 -0
- package/frontend/src/movie-app/components/EditorTabs/GenerateVideoTab.tsx +5 -8
- package/frontend/src/movie-app/components/EditorTabs/MovieStudioTab.tsx +297 -189
- package/frontend/src/movie-app/components/EditorTabs/SetupAiModelTab.tsx +345 -0
- package/frontend/src/movie-app/components/ProjectEditorPage.tsx +40 -34
- package/frontend/src/movie-app/components/ProjectManager.tsx +80 -52
- package/frontend/src/movie-app/index.css +260 -19
- package/frontend/src/movie-app/stores/aiModelStore.ts +163 -0
- package/frontend/src/movie-app/stores/generationStore.ts +2 -2
- package/frontend/src/movie-app/stores/movieStudioStore.ts +45 -0
- package/package.json +1 -1
- package/frontend/src/movie-app/components/EditorTabs/ReferencesToVideoTab.tsx +0 -881
|
@@ -163,15 +163,20 @@ export default function ProjectManager() {
|
|
|
163
163
|
// ========== Render ==========
|
|
164
164
|
|
|
165
165
|
return (
|
|
166
|
-
<div className="flex flex-col
|
|
167
|
-
{/*
|
|
168
|
-
<
|
|
169
|
-
<div>
|
|
170
|
-
<
|
|
171
|
-
|
|
172
|
-
</
|
|
173
|
-
<
|
|
174
|
-
|
|
166
|
+
<div className="flex flex-col">
|
|
167
|
+
{/* Hero */}
|
|
168
|
+
<header className="flex flex-col gap-7 md:flex-row md:items-end md:justify-between">
|
|
169
|
+
<div className="max-w-xl">
|
|
170
|
+
<p className="text-[11px] font-semibold uppercase tracking-[0.24em] text-tiffany-600">
|
|
171
|
+
Lambobo Studio
|
|
172
|
+
</p>
|
|
173
|
+
<h1 className="mt-3 font-display text-4xl font-light leading-[1.06] text-ink-900 md:text-5xl">
|
|
174
|
+
Make the movies{" "}
|
|
175
|
+
<span className="wordmark font-medium italic">you dream of</span>
|
|
176
|
+
</h1>
|
|
177
|
+
<p className="mt-4 text-sm leading-relaxed text-ink-600/80">
|
|
178
|
+
A local AI studio for writing stories, casting characters, and
|
|
179
|
+
turning scenes into motion.
|
|
175
180
|
</p>
|
|
176
181
|
</div>
|
|
177
182
|
<button
|
|
@@ -179,24 +184,24 @@ export default function ProjectManager() {
|
|
|
179
184
|
resetForm();
|
|
180
185
|
setShowCreate(true);
|
|
181
186
|
}}
|
|
182
|
-
className="flex items-center gap-1.5 px-
|
|
187
|
+
className="btn-primary flex w-fit items-center gap-1.5 rounded-2xl px-5 py-2.5 text-sm font-medium"
|
|
183
188
|
>
|
|
184
189
|
{PlusIcon}
|
|
185
190
|
New Project
|
|
186
191
|
</button>
|
|
187
|
-
</
|
|
192
|
+
</header>
|
|
188
193
|
|
|
189
194
|
{/* Error */}
|
|
190
195
|
{error && (
|
|
191
|
-
<div className="
|
|
196
|
+
<div className="mt-8 rounded-2xl border border-rose-200 bg-rose-50/70 px-4 py-3 text-sm text-rose-600 backdrop-blur-sm">
|
|
192
197
|
{error}
|
|
193
198
|
</div>
|
|
194
199
|
)}
|
|
195
200
|
|
|
196
201
|
{/* Create / Edit Form */}
|
|
197
202
|
{showCreate && (
|
|
198
|
-
<div className="
|
|
199
|
-
<h3 className="text-
|
|
203
|
+
<div className="glass mt-8 rounded-3xl p-6 shadow-card">
|
|
204
|
+
<h3 className="font-display text-lg font-medium text-ink-900">
|
|
200
205
|
{editingId ? "Edit Project" : "New Project"}
|
|
201
206
|
</h3>
|
|
202
207
|
<input
|
|
@@ -210,7 +215,7 @@ export default function ProjectManager() {
|
|
|
210
215
|
editingId ? handleUpdate() : handleCreate();
|
|
211
216
|
if (e.key === "Escape") resetForm();
|
|
212
217
|
}}
|
|
213
|
-
className="w-full
|
|
218
|
+
className="mt-4 w-full rounded-2xl border border-white/70 bg-white/70 px-4 py-2.5 text-sm text-ink-900 placeholder-ink-500/40 transition-all focus:border-tiffany-500 focus:outline-none focus:ring-2 focus:ring-tiffany-500/30"
|
|
214
219
|
/>
|
|
215
220
|
<input
|
|
216
221
|
type="text"
|
|
@@ -222,18 +227,18 @@ export default function ProjectManager() {
|
|
|
222
227
|
editingId ? handleUpdate() : handleCreate();
|
|
223
228
|
if (e.key === "Escape") resetForm();
|
|
224
229
|
}}
|
|
225
|
-
className="w-full
|
|
230
|
+
className="mt-3 w-full rounded-2xl border border-white/70 bg-white/70 px-4 py-2.5 text-sm text-ink-900 placeholder-ink-500/40 transition-all focus:border-tiffany-500 focus:outline-none focus:ring-2 focus:ring-tiffany-500/30"
|
|
226
231
|
/>
|
|
227
|
-
<div className="flex gap-2">
|
|
232
|
+
<div className="mt-4 flex gap-2">
|
|
228
233
|
<button
|
|
229
234
|
onClick={editingId ? handleUpdate : handleCreate}
|
|
230
|
-
className="px-5 py-2
|
|
235
|
+
className="btn-primary rounded-2xl px-5 py-2 text-sm font-medium"
|
|
231
236
|
>
|
|
232
237
|
{editingId ? "Update" : "Create"}
|
|
233
238
|
</button>
|
|
234
239
|
<button
|
|
235
240
|
onClick={resetForm}
|
|
236
|
-
className="
|
|
241
|
+
className="rounded-2xl border border-ink-200 bg-white/60 px-5 py-2 text-sm font-medium text-ink-700 transition-colors hover:bg-ink-100"
|
|
237
242
|
>
|
|
238
243
|
Cancel
|
|
239
244
|
</button>
|
|
@@ -241,64 +246,87 @@ export default function ProjectManager() {
|
|
|
241
246
|
</div>
|
|
242
247
|
)}
|
|
243
248
|
|
|
249
|
+
{/* Section label */}
|
|
250
|
+
<div className="mt-12 mb-4 flex items-center gap-3">
|
|
251
|
+
<h2 className="font-display text-xl font-medium text-ink-900">
|
|
252
|
+
Projects
|
|
253
|
+
</h2>
|
|
254
|
+
<span className="text-xs text-ink-500">
|
|
255
|
+
{loading ? "…" : `${projects.length} in the studio`}
|
|
256
|
+
</span>
|
|
257
|
+
<div className="hairline flex-1" />
|
|
258
|
+
</div>
|
|
259
|
+
|
|
244
260
|
{/* Project List */}
|
|
245
261
|
{loading ? (
|
|
246
|
-
<div className="flex items-center justify-center py-16 text-ink-600/50
|
|
247
|
-
Loading
|
|
262
|
+
<div className="flex items-center justify-center py-16 text-sm text-ink-600/50">
|
|
263
|
+
Loading…
|
|
248
264
|
</div>
|
|
249
265
|
) : projects.length === 0 ? (
|
|
250
|
-
<div className="flex flex-col items-center justify-center py-
|
|
251
|
-
<div className="
|
|
266
|
+
<div className="glass flex flex-col items-center justify-center rounded-3xl px-6 py-20 text-center shadow-card">
|
|
267
|
+
<div className="thumb flex h-20 w-20 items-center justify-center rounded-3xl text-ink-900/70 shadow-glow-sm">
|
|
252
268
|
<svg
|
|
253
|
-
width="
|
|
254
|
-
height="
|
|
269
|
+
width="32"
|
|
270
|
+
height="32"
|
|
255
271
|
viewBox="0 0 24 24"
|
|
256
272
|
fill="none"
|
|
257
|
-
stroke="
|
|
273
|
+
stroke="currentColor"
|
|
258
274
|
strokeWidth="1.5"
|
|
259
275
|
>
|
|
260
276
|
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" />
|
|
261
277
|
</svg>
|
|
262
278
|
</div>
|
|
263
|
-
<p className="text-
|
|
264
|
-
|
|
265
|
-
|
|
279
|
+
<p className="mt-5 font-display text-2xl font-light text-ink-900">
|
|
280
|
+
Your studio is empty
|
|
281
|
+
</p>
|
|
282
|
+
<p className="mt-1.5 max-w-xs text-sm leading-relaxed text-ink-600/70">
|
|
283
|
+
Create your first project and start turning an idea into motion.
|
|
266
284
|
</p>
|
|
285
|
+
<button
|
|
286
|
+
onClick={() => {
|
|
287
|
+
resetForm();
|
|
288
|
+
setShowCreate(true);
|
|
289
|
+
}}
|
|
290
|
+
className="btn-primary mt-6 flex items-center gap-1.5 rounded-2xl px-5 py-2.5 text-sm font-medium"
|
|
291
|
+
>
|
|
292
|
+
{PlusIcon}
|
|
293
|
+
New Project
|
|
294
|
+
</button>
|
|
267
295
|
</div>
|
|
268
296
|
) : (
|
|
269
|
-
<div className="
|
|
297
|
+
<div className="space-y-2.5">
|
|
270
298
|
{projects.map((p) => (
|
|
271
299
|
<div
|
|
272
300
|
key={p.id}
|
|
273
|
-
className="flex items-center gap-3 px-4 py-3.5
|
|
301
|
+
className="group flex items-center gap-3 rounded-2xl px-4 py-3.5 shadow-card transition-all duration-200 hover:-translate-y-0.5 hover:shadow-card-hover glass"
|
|
274
302
|
>
|
|
275
303
|
{/* Project info */}
|
|
276
304
|
<button
|
|
277
305
|
onClick={() => openProject(p.id)}
|
|
278
|
-
className="flex-
|
|
306
|
+
className="flex min-w-0 flex-1 items-center gap-3 text-left"
|
|
279
307
|
>
|
|
280
|
-
<div className="
|
|
308
|
+
<div className="thumb flex h-11 w-11 shrink-0 items-center justify-center rounded-2xl text-ink-900/70">
|
|
281
309
|
<svg
|
|
282
|
-
width="
|
|
283
|
-
height="
|
|
310
|
+
width="16"
|
|
311
|
+
height="16"
|
|
284
312
|
viewBox="0 0 24 24"
|
|
285
313
|
fill="none"
|
|
286
|
-
stroke="
|
|
314
|
+
stroke="currentColor"
|
|
287
315
|
strokeWidth="2"
|
|
288
316
|
>
|
|
289
317
|
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" />
|
|
290
318
|
</svg>
|
|
291
319
|
</div>
|
|
292
320
|
<div className="min-w-0">
|
|
293
|
-
<p className="text-
|
|
321
|
+
<p className="truncate font-display text-[15px] font-medium leading-tight text-ink-900">
|
|
294
322
|
{p.name}
|
|
295
323
|
</p>
|
|
296
324
|
{p.description ? (
|
|
297
|
-
<p className="text-xs text-ink-600/
|
|
325
|
+
<p className="mt-0.5 truncate text-xs text-ink-600/70">
|
|
298
326
|
{p.description}
|
|
299
327
|
</p>
|
|
300
328
|
) : (
|
|
301
|
-
<p className="text-xs text-ink-500/60
|
|
329
|
+
<p className="mt-0.5 text-xs italic text-ink-500/60">
|
|
302
330
|
No description
|
|
303
331
|
</p>
|
|
304
332
|
)}
|
|
@@ -306,38 +334,38 @@ export default function ProjectManager() {
|
|
|
306
334
|
</button>
|
|
307
335
|
|
|
308
336
|
{/* Actions */}
|
|
309
|
-
<div className="flex items-center gap-0.5 opacity-0 group-hover:opacity-100
|
|
337
|
+
<div className="flex items-center gap-0.5 opacity-0 transition-opacity duration-150 group-hover:opacity-100">
|
|
310
338
|
<button
|
|
311
339
|
onClick={() => startEdit(p)}
|
|
312
|
-
className="p-2 text-ink-600/40
|
|
340
|
+
className="rounded-xl p-2 text-ink-600/40 transition-colors hover:bg-ink-100 hover:text-tiffany-700"
|
|
313
341
|
title="Edit"
|
|
314
342
|
>
|
|
315
343
|
{EditIcon}
|
|
316
344
|
</button>
|
|
317
345
|
<button
|
|
318
346
|
onClick={() => openFolder(p.id, "upload")}
|
|
319
|
-
className="p-2 text-ink-600/40
|
|
347
|
+
className="rounded-xl p-2 text-ink-600/40 transition-colors hover:bg-ink-100 hover:text-tiffany-700"
|
|
320
348
|
title="Open Uploads Folder"
|
|
321
349
|
>
|
|
322
350
|
{UploadFolderIcon}
|
|
323
351
|
</button>
|
|
324
352
|
<button
|
|
325
353
|
onClick={() => openFolder(p.id, "output")}
|
|
326
|
-
className="p-2 text-ink-600/40
|
|
354
|
+
className="rounded-xl p-2 text-ink-600/40 transition-colors hover:bg-ink-100 hover:text-tiffany-700"
|
|
327
355
|
title="Open Outputs Folder"
|
|
328
356
|
>
|
|
329
357
|
{OutputFolderIcon}
|
|
330
358
|
</button>
|
|
331
359
|
<button
|
|
332
360
|
onClick={() => setDeleteConfirm(p.id)}
|
|
333
|
-
className="p-2 text-ink-600/40
|
|
361
|
+
className="rounded-xl p-2 text-ink-600/40 transition-colors hover:bg-rose-50 hover:text-rose-600"
|
|
334
362
|
title="Delete"
|
|
335
363
|
>
|
|
336
364
|
{DeleteIcon}
|
|
337
365
|
</button>
|
|
338
366
|
<button
|
|
339
367
|
onClick={() => openProject(p.id)}
|
|
340
|
-
className="p-2 text-ink-600/40
|
|
368
|
+
className="rounded-xl p-2 text-ink-600/40 transition-colors hover:bg-ink-100 hover:text-tiffany-700"
|
|
341
369
|
title="Open"
|
|
342
370
|
>
|
|
343
371
|
{OpenIcon}
|
|
@@ -350,25 +378,25 @@ export default function ProjectManager() {
|
|
|
350
378
|
|
|
351
379
|
{/* Delete Confirmation Modal */}
|
|
352
380
|
{deleteConfirm && (
|
|
353
|
-
<div className="fixed inset-0 z-50 flex items-center justify-center bg-
|
|
354
|
-
<div className="
|
|
355
|
-
<h3 className="text-
|
|
381
|
+
<div className="fixed inset-0 z-50 flex items-center justify-center bg-ink-950/40 backdrop-blur-sm">
|
|
382
|
+
<div className="w-80 rounded-3xl border border-white/70 bg-white/90 p-8 shadow-modal backdrop-blur-xl">
|
|
383
|
+
<h3 className="font-display text-lg font-medium text-ink-900">
|
|
356
384
|
Delete Project
|
|
357
385
|
</h3>
|
|
358
|
-
<p className="text-sm text-ink-600/80
|
|
386
|
+
<p className="mt-2 text-sm leading-relaxed text-ink-600/80">
|
|
359
387
|
Are you sure you want to delete this project? This action cannot
|
|
360
388
|
be undone.
|
|
361
389
|
</p>
|
|
362
|
-
<div className="flex gap-2
|
|
390
|
+
<div className="mt-5 flex justify-end gap-2">
|
|
363
391
|
<button
|
|
364
392
|
onClick={() => setDeleteConfirm(null)}
|
|
365
|
-
className="
|
|
393
|
+
className="rounded-2xl bg-ink-100 px-4 py-2 text-sm font-medium text-ink-700 transition-colors hover:bg-ink-300"
|
|
366
394
|
>
|
|
367
395
|
Cancel
|
|
368
396
|
</button>
|
|
369
397
|
<button
|
|
370
398
|
onClick={() => handleDelete(deleteConfirm)}
|
|
371
|
-
className="
|
|
399
|
+
className="rounded-2xl bg-rose-500 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-rose-600"
|
|
372
400
|
>
|
|
373
401
|
Delete
|
|
374
402
|
</button>
|
|
@@ -1,22 +1,80 @@
|
|
|
1
1
|
@import "tailwindcss";
|
|
2
2
|
|
|
3
|
+
/* ==========================================================================
|
|
4
|
+
Lambobo Studio — design tokens
|
|
5
|
+
A dreamy, tiffany-blue film studio. Gradients read like light through
|
|
6
|
+
shallow water: tiffany teal → aqua → periwinkle → blush.
|
|
7
|
+
========================================================================== */
|
|
8
|
+
|
|
9
|
+
@theme {
|
|
10
|
+
/* ---- Type ---- */
|
|
11
|
+
--font-sans: "Avenir Next", Avenir, "Helvetica Neue", -apple-system,
|
|
12
|
+
BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
13
|
+
--font-display: "Cormorant", "Iowan Old Style", "Baskerville", "Georgia",
|
|
14
|
+
serif;
|
|
15
|
+
--font-mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas,
|
|
16
|
+
"Liberation Mono", monospace;
|
|
17
|
+
|
|
18
|
+
/* ---- Tiffany (the brand) ---- */
|
|
19
|
+
--color-tiffany-50: #effbf9;
|
|
20
|
+
--color-tiffany-100: #d7f4f1;
|
|
21
|
+
--color-tiffany-200: #b0e8e3;
|
|
22
|
+
--color-tiffany-300: #81d8d0;
|
|
23
|
+
--color-tiffany-400: #4fc3bc;
|
|
24
|
+
--color-tiffany-500: #0abab5;
|
|
25
|
+
--color-tiffany-600: #089a96;
|
|
26
|
+
--color-tiffany-700: #077a77;
|
|
27
|
+
--color-tiffany-800: #06605e;
|
|
28
|
+
--color-tiffany-900: #04403f;
|
|
29
|
+
--color-tiffany-950: #022726;
|
|
30
|
+
|
|
31
|
+
/* ---- Ink (cool, teal-tinted neutrals) ---- */
|
|
32
|
+
--color-ink-50: #f3f7f7;
|
|
33
|
+
--color-ink-100: #e6edee;
|
|
34
|
+
--color-ink-200: #d2dee1;
|
|
35
|
+
--color-ink-300: #b0c3c8;
|
|
36
|
+
--color-ink-400: #83a0a7;
|
|
37
|
+
--color-ink-500: #5e7c83;
|
|
38
|
+
--color-ink-600: #47636b;
|
|
39
|
+
--color-ink-700: #395057;
|
|
40
|
+
--color-ink-800: #283a40;
|
|
41
|
+
--color-ink-900: #18272c;
|
|
42
|
+
--color-ink-950: #0d191c;
|
|
43
|
+
|
|
44
|
+
/* ---- Dream accents (the aurora) ---- */
|
|
45
|
+
--color-dream-periwinkle: #c3b4f4;
|
|
46
|
+
--color-dream-blush: #ffd6ea;
|
|
47
|
+
--color-dream-sky: #b7e1fb;
|
|
48
|
+
--color-dream-mint: #c8f1e6;
|
|
49
|
+
|
|
50
|
+
/* ---- Shadows ---- */
|
|
51
|
+
--shadow-glow: 0 8px 30px -6px rgba(10, 186, 181, 0.55),
|
|
52
|
+
0 2px 10px -2px rgba(10, 186, 181, 0.4);
|
|
53
|
+
--shadow-glow-sm: 0 0 14px -2px rgba(10, 186, 181, 0.45);
|
|
54
|
+
--shadow-card: 0 1px 2px rgba(13, 25, 28, 0.04),
|
|
55
|
+
0 10px 30px -12px rgba(13, 25, 28, 0.16);
|
|
56
|
+
--shadow-card-hover: 0 2px 4px rgba(13, 25, 28, 0.05),
|
|
57
|
+
0 18px 44px -14px rgba(10, 186, 181, 0.35);
|
|
58
|
+
--shadow-modal: 0 24px 80px -16px rgba(13, 25, 28, 0.35);
|
|
59
|
+
}
|
|
60
|
+
|
|
3
61
|
:root {
|
|
4
62
|
color-scheme: light;
|
|
5
63
|
}
|
|
6
64
|
|
|
7
65
|
body {
|
|
8
66
|
margin: 0;
|
|
9
|
-
background: #
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
sans-serif;
|
|
67
|
+
background-color: #f3f7f7;
|
|
68
|
+
background-image: radial-gradient(
|
|
69
|
+
120% 90% at 85% -10%,
|
|
70
|
+
rgba(183, 225, 251, 0.5),
|
|
71
|
+
transparent 60%
|
|
72
|
+
),
|
|
73
|
+
radial-gradient(100% 80% at 0% 0%, rgba(255, 214, 234, 0.4), transparent 55%);
|
|
74
|
+
background-attachment: fixed;
|
|
75
|
+
color: #283a40;
|
|
76
|
+
font-family: "Avenir Next", Avenir, "Helvetica Neue", -apple-system,
|
|
77
|
+
BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
20
78
|
-webkit-font-smoothing: antialiased;
|
|
21
79
|
-moz-osx-font-smoothing: grayscale;
|
|
22
80
|
}
|
|
@@ -24,23 +82,206 @@ body {
|
|
|
24
82
|
code,
|
|
25
83
|
pre,
|
|
26
84
|
.font-mono {
|
|
27
|
-
font-family:
|
|
28
|
-
ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas,
|
|
85
|
+
font-family: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas,
|
|
29
86
|
"Liberation Mono", monospace;
|
|
30
87
|
}
|
|
31
88
|
|
|
32
|
-
|
|
89
|
+
::selection {
|
|
90
|
+
background: rgba(10, 186, 181, 0.24);
|
|
91
|
+
color: #0d191c;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
:focus-visible {
|
|
95
|
+
outline: 2px solid rgba(10, 186, 181, 0.6);
|
|
96
|
+
outline-offset: 2px;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Subtle tiffany scrollbar */
|
|
33
100
|
::-webkit-scrollbar {
|
|
34
|
-
width:
|
|
35
|
-
height:
|
|
101
|
+
width: 10px;
|
|
102
|
+
height: 10px;
|
|
36
103
|
}
|
|
37
104
|
::-webkit-scrollbar-track {
|
|
38
105
|
background: transparent;
|
|
39
106
|
}
|
|
40
107
|
::-webkit-scrollbar-thumb {
|
|
41
|
-
background:
|
|
42
|
-
border-radius:
|
|
108
|
+
background: rgba(10, 186, 181, 0.28);
|
|
109
|
+
border-radius: 9999px;
|
|
110
|
+
border: 2px solid transparent;
|
|
111
|
+
background-clip: padding-box;
|
|
43
112
|
}
|
|
44
113
|
::-webkit-scrollbar-thumb:hover {
|
|
45
|
-
background:
|
|
114
|
+
background: rgba(10, 186, 181, 0.5);
|
|
115
|
+
background-clip: padding-box;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* ==========================================================================
|
|
119
|
+
Atmosphere — the signature. Slow-drifting aurora of tiffany, periwinkle,
|
|
120
|
+
blush and sky, breathing behind a frosted-glass interface.
|
|
121
|
+
========================================================================== */
|
|
122
|
+
|
|
123
|
+
.aurora {
|
|
124
|
+
position: fixed;
|
|
125
|
+
inset: 0;
|
|
126
|
+
z-index: 0;
|
|
127
|
+
overflow: hidden;
|
|
128
|
+
pointer-events: none;
|
|
129
|
+
background: radial-gradient(
|
|
130
|
+
120% 90% at 85% -10%,
|
|
131
|
+
rgba(183, 225, 251, 0.55),
|
|
132
|
+
transparent 60%
|
|
133
|
+
),
|
|
134
|
+
radial-gradient(
|
|
135
|
+
100% 80% at 8% 0%,
|
|
136
|
+
rgba(255, 214, 234, 0.5),
|
|
137
|
+
transparent 55%
|
|
138
|
+
),
|
|
139
|
+
linear-gradient(165deg, #eaf8f6 0%, #f3f7f7 48%, #eceff9 100%);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.aurora-blob {
|
|
143
|
+
position: absolute;
|
|
144
|
+
border-radius: 50%;
|
|
145
|
+
filter: blur(70px);
|
|
146
|
+
opacity: 0.55;
|
|
147
|
+
will-change: transform;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.aurora-blob--tiffany {
|
|
151
|
+
width: 44rem;
|
|
152
|
+
height: 44rem;
|
|
153
|
+
left: -12rem;
|
|
154
|
+
top: -14rem;
|
|
155
|
+
background: radial-gradient(circle at 35% 35%, #81d8d0, transparent 68%);
|
|
156
|
+
animation: drift-a 36s ease-in-out infinite;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.aurora-blob--periwinkle {
|
|
160
|
+
width: 40rem;
|
|
161
|
+
height: 40rem;
|
|
162
|
+
right: -10rem;
|
|
163
|
+
top: -8rem;
|
|
164
|
+
background: radial-gradient(circle at 60% 40%, #c3b4f4, transparent 70%);
|
|
165
|
+
animation: drift-b 44s ease-in-out infinite;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.aurora-blob--blush {
|
|
169
|
+
width: 36rem;
|
|
170
|
+
height: 36rem;
|
|
171
|
+
left: 18%;
|
|
172
|
+
bottom: -16rem;
|
|
173
|
+
background: radial-gradient(circle at 50% 50%, #ffd6ea, transparent 70%);
|
|
174
|
+
animation: drift-c 40s ease-in-out infinite;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.aurora-blob--sky {
|
|
178
|
+
width: 46rem;
|
|
179
|
+
height: 46rem;
|
|
180
|
+
right: 8%;
|
|
181
|
+
bottom: -12rem;
|
|
182
|
+
background: radial-gradient(circle at 50% 50%, #b7e1fb, transparent 70%);
|
|
183
|
+
animation: drift-a 50s ease-in-out infinite;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
@keyframes drift-a {
|
|
187
|
+
0%,
|
|
188
|
+
100% {
|
|
189
|
+
transform: translate3d(0, 0, 0) scale(1);
|
|
190
|
+
}
|
|
191
|
+
50% {
|
|
192
|
+
transform: translate3d(4rem, 3rem, 0) scale(1.08);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
@keyframes drift-b {
|
|
197
|
+
0%,
|
|
198
|
+
100% {
|
|
199
|
+
transform: translate3d(0, 0, 0) scale(1);
|
|
200
|
+
}
|
|
201
|
+
50% {
|
|
202
|
+
transform: translate3d(-3rem, 4rem, 0) scale(0.94);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
@keyframes drift-c {
|
|
207
|
+
0%,
|
|
208
|
+
100% {
|
|
209
|
+
transform: translate3d(0, 0, 0) scale(1);
|
|
210
|
+
}
|
|
211
|
+
50% {
|
|
212
|
+
transform: translate3d(2rem, -4rem, 0) scale(1.12);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
@media (prefers-reduced-motion: reduce) {
|
|
217
|
+
.aurora-blob {
|
|
218
|
+
animation: none;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/* ==========================================================================
|
|
223
|
+
Surfaces & primitives
|
|
224
|
+
========================================================================== */
|
|
225
|
+
|
|
226
|
+
.glass {
|
|
227
|
+
background: rgba(255, 255, 255, 0.55);
|
|
228
|
+
border: 1px solid rgba(255, 255, 255, 0.65);
|
|
229
|
+
backdrop-filter: blur(20px) saturate(150%);
|
|
230
|
+
-webkit-backdrop-filter: blur(20px) saturate(150%);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.glass-dark {
|
|
234
|
+
background: rgba(13, 25, 28, 0.82);
|
|
235
|
+
border: 1px solid rgba(129, 216, 208, 0.16);
|
|
236
|
+
backdrop-filter: blur(20px) saturate(140%);
|
|
237
|
+
-webkit-backdrop-filter: blur(20px) saturate(140%);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.wordmark {
|
|
241
|
+
background: linear-gradient(
|
|
242
|
+
115deg,
|
|
243
|
+
#0abab5 0%,
|
|
244
|
+
#4fc3bc 34%,
|
|
245
|
+
#c3b4f4 72%,
|
|
246
|
+
#ffd6ea 100%
|
|
247
|
+
);
|
|
248
|
+
-webkit-background-clip: text;
|
|
249
|
+
background-clip: text;
|
|
250
|
+
color: transparent;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.thumb {
|
|
254
|
+
background-image: linear-gradient(135deg, #b0e8e3 0%, #81d8d0 50%, #c3b4f4 100%);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.btn-primary {
|
|
258
|
+
background-image: linear-gradient(
|
|
259
|
+
120deg,
|
|
260
|
+
#089a96 0%,
|
|
261
|
+
#0abab5 55%,
|
|
262
|
+
#4fc3bc 100%
|
|
263
|
+
);
|
|
264
|
+
color: #ffffff;
|
|
265
|
+
box-shadow: var(--shadow-glow);
|
|
266
|
+
transition: filter 150ms ease, box-shadow 150ms ease, transform 150ms ease;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.btn-primary:hover {
|
|
270
|
+
filter: brightness(1.05);
|
|
271
|
+
box-shadow: 0 10px 34px -6px rgba(10, 186, 181, 0.6),
|
|
272
|
+
0 4px 12px -4px rgba(10, 186, 181, 0.45);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.btn-primary:active {
|
|
276
|
+
transform: translateY(1px);
|
|
277
|
+
filter: brightness(0.97);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.hairline {
|
|
281
|
+
height: 1px;
|
|
282
|
+
background: linear-gradient(
|
|
283
|
+
to right,
|
|
284
|
+
rgba(176, 195, 200, 0.7),
|
|
285
|
+
rgba(176, 195, 200, 0)
|
|
286
|
+
);
|
|
46
287
|
}
|