diff --git a/ado2-marketing-intelligence---lala-cabin/.gitignore b/ado2-marketing-intelligence---lala-cabin/.gitignore deleted file mode 100755 index a547bf3..0000000 --- a/ado2-marketing-intelligence---lala-cabin/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/ado2-marketing-intelligence---lala-cabin/App.tsx b/ado2-marketing-intelligence---lala-cabin/App.tsx deleted file mode 100755 index f7ca3fb..0000000 --- a/ado2-marketing-intelligence---lala-cabin/App.tsx +++ /dev/null @@ -1,233 +0,0 @@ -import React, { useMemo } from 'react'; -import { ArrowLeft, Sparkles, MapPin, Target, Zap, LayoutGrid, Users, Crown, TrendingUp } from 'lucide-react'; -import { LALA_CABIN_DATA } from './constants'; -import { GeometricChart } from './components/GeometricChart'; -import { KeywordBubble } from './components/KeywordBubble'; -import { BrandData, USP } from './types'; - -// Logic to calculate scores based on ICP (Ideal Customer Profile) signals -const calculateDynamicScores = (data: BrandData): USP[] => { - // 1. Extract Demand Signals from Targets (Needs + Triggers) - const marketSignals = data.targets.flatMap(t => [...t.needs, ...t.triggers]).map(s => s.replace(/\s+/g, '')); - - // High value keywords that represent the "Core Value" of this specific property type - const coreKeywords = ['프라이빗', '감성', '독채', '캐빈', '조명', '불멍', 'Private', 'Mood']; - - return data.usps.map(usp => { - let calculatedScore = 65; // Base score - const contentStr = (usp.label + usp.subLabel + usp.description).replace(/\s+/g, ''); - - // 2. Cross-reference USP with Market Signals - marketSignals.forEach(signal => { - if (contentStr.includes(signal)) calculatedScore += 4; - }); - - // 3. Boost based on Core Keywords (Weighted Importance) - coreKeywords.forEach(keyword => { - if (contentStr.includes(keyword)) calculatedScore += 6; - }); - - // 4. Special Boost based on specific Marketing Pillars (checking English SubLabels) - if (usp.subLabel === 'CONCEPT') calculatedScore += 10; - if (usp.subLabel === 'PRIVACY') calculatedScore += 8; - if (usp.subLabel === 'NIGHT MOOD') calculatedScore += 8; - if (usp.subLabel === 'PHOTO SPOT') calculatedScore += 5; - - return { - ...usp, - score: Math.min(Math.round(calculatedScore), 99) // Cap at 99 - }; - }); -}; - -export default function App() { - const rawData = LALA_CABIN_DATA; - - // Calculate scores on mount (or when data changes) - const scoredUSPs = useMemo(() => calculateDynamicScores(rawData), [rawData]); - - // Find the top selling point - const topUSP = useMemo(() => [...scoredUSPs].sort((a, b) => b.score - a.score)[0], [scoredUSPs]); - - return ( -
- {/* Top Navigation */} -
- -
- - {/* Main Header */} -
-
-
- -
-
-

브랜드 인텔리전스

-

- AI 데이터 분석을 통해 도출된 라라캐빈의 핵심 전략입니다. -

-
- - {/* Grid Container */} -
- - {/* LEFT COLUMN: Identity & Text Analysis */} -
- - {/* Main Identity Card */} -
-
-
- - 브랜드 정체성 - -
- -

{rawData.name}

-
- -
-

{rawData.address}

-

{rawData.subAddress}

-
-
- -
-
-

입지 특성 분석

-

{rawData.locationAnalysis}

-
-
-

컨셉 확장성

-

{rawData.conceptAnalysis}

-
-
-
- - {/* Positioning & Strategy Card */} -
-

- 시장 포지셔닝 -

- -
-
- 카테고리 정의 - {rawData.positioning.category} -
-
- 핵심 가치 (Core Value) - {rawData.positioning.coreValue} -
-
-
- - {/* Target Audience Card */} -
-

- 타겟 페르소나 -

-
- {rawData.targets.map((target, idx) => ( -
-
-
{target.segment}
-
{target.age}
-
-
-
- {target.needs.map((need, i) => ( - {need} - ))} -
-

- Trigger: {target.triggers.join(', ')} -

-
-
- ))} -
-
- -
- - {/* RIGHT COLUMN: Visuals & Keywords */} -
- - {/* Chart Card */} -
- -
-

주요 셀링 포인트 (USP)

-
- - AI Data Analysis -
-
- -
- -
- - {/* Core Competitiveness Highlight */} - {topUSP && ( -
-
- -
-
-
- Core Competitiveness -
-
-
-
{topUSP.label}
-
{topUSP.subLabel}
-
- {/* Score removed */} -
-
-
- )} - -
- {scoredUSPs.filter(u => u.label !== topUSP.label).slice(0, 4).map((usp, idx) => ( -
-
-
{usp.subLabel}
- {/* Score removed */} -
-
{usp.label}
-
{usp.description}
-
- ))} -
-
- - {/* Keywords Card */} -
-

추천 타겟 키워드

-
- {rawData.keywords.map((keyword, idx) => ( - - ))} -
-
- -
-
- - {/* Floating Action Button (Sticky Bottom) */} -
- -
-
- ); -} \ No newline at end of file diff --git a/ado2-marketing-intelligence---lala-cabin/README.md b/ado2-marketing-intelligence---lala-cabin/README.md deleted file mode 100755 index d767aa2..0000000 --- a/ado2-marketing-intelligence---lala-cabin/README.md +++ /dev/null @@ -1,20 +0,0 @@ -
-GHBanner -
- -# Run and deploy your AI Studio app - -This contains everything you need to run your app locally. - -View your app in AI Studio: https://ai.studio/apps/drive/198bB4uG9EOOi0btQWINncwYJz7xEjWS3 - -## Run Locally - -**Prerequisites:** Node.js - - -1. Install dependencies: - `npm install` -2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key -3. Run the app: - `npm run dev` diff --git a/ado2-marketing-intelligence---lala-cabin/components/GeometricChart.tsx b/ado2-marketing-intelligence---lala-cabin/components/GeometricChart.tsx deleted file mode 100755 index 4c66635..0000000 --- a/ado2-marketing-intelligence---lala-cabin/components/GeometricChart.tsx +++ /dev/null @@ -1,159 +0,0 @@ -import React from 'react'; -import { USP } from '../types'; - -interface GeometricChartProps { - data: USP[]; -} - -export const GeometricChart: React.FC = ({ data }) => { - // Increased canvas size to prevent labels (especially on the right side like 'Privacy') from being cut off - const size = 500; - const center = size / 2; - const radius = 110; // Slightly increased radius for better visibility - const sides = data.length; - - // Mint Color #94FBE0 - const accentColor = "#94FBE0"; - - // Calculate polygon points - const getPoints = (r: number) => { - return data.map((_, i) => { - const angle = (Math.PI * 2 * i) / sides - Math.PI / 2; - const x = center + r * Math.cos(angle); - const y = center + r * Math.sin(angle); - return `${x},${y}`; - }).join(' '); - }; - - // Calculate data points based on score - const getDataPoints = () => { - return data.map((item, i) => { - const normalizedScore = item.score / 100; - const r = radius * normalizedScore; - const angle = (Math.PI * 2 * i) / sides - Math.PI / 2; - const x = center + r * Math.cos(angle); - const y = center + r * Math.sin(angle); - return `${x},${y}`; - }).join(' '); - }; - - // Calculate label positions (pushed out slightly further) - const labelRadius = radius + 55; // Increased padding for labels - const labels = data.map((item, i) => { - const angle = (Math.PI * 2 * i) / sides - Math.PI / 2; - const x = center + labelRadius * Math.cos(angle); - const y = center + labelRadius * Math.sin(angle); - - // Adjust text anchor based on position - let anchor: 'start' | 'middle' | 'end' = 'middle'; - if (x < center - 20) anchor = 'end'; - if (x > center + 20) anchor = 'start'; - - return { x, y, text: item.label, sub: item.subLabel, anchor, score: item.score }; - }); - - return ( -
- - - - - - - - - {/* Background Grids (Concentric) - Increased Opacity for Visibility */} - {[1, 0.75, 0.5, 0.25].map((scale, i) => ( - - ))} - - {/* Axes Lines - Increased Opacity */} - {data.map((_, i) => { - const angle = (Math.PI * 2 * i) / sides - Math.PI / 2; - const x = center + radius * Math.cos(angle); - const y = center + radius * Math.sin(angle); - return ( - - ); - })} - - {/* Data Shape */} - - - {/* Data Points (Dots) - Increased base size and highlight size */} - {data.map((item, i) => { - const normalizedScore = item.score / 100; - const r = radius * normalizedScore; - const angle = (Math.PI * 2 * i) / sides - Math.PI / 2; - const x = center + r * Math.cos(angle); - const y = center + r * Math.sin(angle); - const isHigh = item.score >= 90; - return ( - - {isHigh && ( - - )} - {/* Base dot is brighter (white) for all, slightly smaller for non-high */} - - - ) - })} - - {/* Labels */} - {labels.map((l, i) => { - const isHigh = l.score >= 90; - return ( - - - {l.text} - - - {l.sub} - - - ); - })} - -
- ); -}; \ No newline at end of file diff --git a/ado2-marketing-intelligence---lala-cabin/components/KeywordBubble.tsx b/ado2-marketing-intelligence---lala-cabin/components/KeywordBubble.tsx deleted file mode 100755 index 3ac29fc..0000000 --- a/ado2-marketing-intelligence---lala-cabin/components/KeywordBubble.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react'; - -interface KeywordBubbleProps { - text: string; -} - -export const KeywordBubble: React.FC = ({ text }) => { - return ( -
- # {text} -
- ); -}; \ No newline at end of file diff --git a/ado2-marketing-intelligence---lala-cabin/constants.ts b/ado2-marketing-intelligence---lala-cabin/constants.ts deleted file mode 100755 index 6cacae7..0000000 --- a/ado2-marketing-intelligence---lala-cabin/constants.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { BrandData } from './types'; - -export const LALA_CABIN_DATA: BrandData = { - name: "라라캐빈 펜션", - address: "경기 가평군 조종면 와곡길 176", - subAddress: "[별관] 경기 가평군 조종면 운악리 175-6", - summary: "서울·경기 북부 근교 1~2시간대 숏브레이크 권역에 위치한 캐빈 감성 스테이. 조종면의 한적함과 프라이빗한 독채 구조를 강점으로 내세우며, '숲속 캐빈 무드'와 '야간 조명 감성'이 핵심입니다.", - locationAnalysis: "조종면은 청평/가평읍 대비 '한적함·프라이빗' 이미지가 강해 커플 및 소규모 힐링 고객에게 유리하며, 운악산 권역의 자연형 스테이 포지셔닝에 적합합니다.", - conceptAnalysis: "'라라캐빈'은 오두막(Cabin) 연상을 강하게 주며, 감성 목조/숲속/프라이빗 스테이로 스토리텔링 확장성이 큽니다. 별관의 동 분리 구조는 '세컨드 하우스' 느낌을 강화합니다.", - usps: [ - { label: "입지 환경", subLabel: "LOCATION", score: 85, description: "서울근교 한적한 조종면 자연권 숲속 드라이브" }, - { label: "브랜드 컨셉", subLabel: "CONCEPT", score: 95, description: "숙소 자체가 여행 목적이 되는 캐빈 감성" }, - { label: "프라이버시", subLabel: "PRIVACY", score: 90, description: "우리만 쓰는 느낌의 별관 분리동 독립 동선" }, - { label: "야간 무드", subLabel: "NIGHT MOOD", score: 92, description: "어두울수록 예쁜 스테이 장면과 불멍" }, - { label: "힐링 요소", subLabel: "HEALING", score: 88, description: "창밖 자연로딩, 숲뷰 산책 리셋" }, - { label: "포토 스팟", subLabel: "PHOTO SPOT", score: 94, description: "찍는 곳마다 커버샷 무드, 인스타 각" }, - { label: "숏브레이크", subLabel: "SHORT GETAWAY", score: 80, description: "1박2일 가볍게 떠나는 주말 리셋 여행" } - ], - keywords: [ - "가평 독채 펜션", "숲속 오두막", "감성 숙소", "불멍 스테이", - "서울근교 드라이브", "프라이빗 힐링", "커플 여행", "운악산 펜션", - "반려견 동반", "비오는날 감성" - ], - targets: [ - { - segment: "서울·경기 커플", - age: "25~39세", - needs: ["사진", "분위기", "프라이빗"], - triggers: ["숲속 캐빈 무드", "비 오는 날 감성", "밤 조명"] - }, - { - segment: "소규모 우정여행", - age: "20~34세", - needs: ["예쁜 공간", "수다", "바베큐"], - triggers: ["인스타 각", "감성 포토존", "테이블 셋업"] - }, - { - segment: "힐링 부부", - age: "30~50세", - needs: ["조용한 휴식", "숙면", "따뜻함"], - triggers: ["조용한 숲뷰", "따뜻한 캐빈", "기념일"] - } - ], - positioning: { - category: "서울근교 숲속 캐빈 감성 스테이", - coreValue: "프라이빗한 휴식 + 사진이 되는 공간 + 밤 무드", - strategy: "시설 나열보다 '장면(Scenes)' 중심의 마케팅 전개" - } -}; \ No newline at end of file diff --git a/ado2-marketing-intelligence---lala-cabin/index.html b/ado2-marketing-intelligence---lala-cabin/index.html deleted file mode 100755 index f7651b2..0000000 --- a/ado2-marketing-intelligence---lala-cabin/index.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - ADO2 Brand Analysis - - - - - - - - -
- - - \ No newline at end of file diff --git a/ado2-marketing-intelligence---lala-cabin/index.tsx b/ado2-marketing-intelligence---lala-cabin/index.tsx deleted file mode 100755 index 6ca5361..0000000 --- a/ado2-marketing-intelligence---lala-cabin/index.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import App from './App'; - -const rootElement = document.getElementById('root'); -if (!rootElement) { - throw new Error("Could not find root element to mount to"); -} - -const root = ReactDOM.createRoot(rootElement); -root.render( - - - -); \ No newline at end of file diff --git a/ado2-marketing-intelligence---lala-cabin/metadata.json b/ado2-marketing-intelligence---lala-cabin/metadata.json deleted file mode 100755 index 1bfb315..0000000 --- a/ado2-marketing-intelligence---lala-cabin/metadata.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "ADO2 Marketing Intelligence - Lala Cabin", - "description": "AI-powered marketing analysis dashboard for Lala Cabin Pension visualizing brand identity, target demographics, and key selling points.", - "requestFramePermissions": [] -} \ No newline at end of file diff --git a/ado2-marketing-intelligence---lala-cabin/package.json b/ado2-marketing-intelligence---lala-cabin/package.json deleted file mode 100755 index 1803756..0000000 --- a/ado2-marketing-intelligence---lala-cabin/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "ado2-marketing-intelligence---lala-cabin", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview" - }, - "dependencies": { - "react-dom": "^19.2.3", - "react": "^19.2.3", - "lucide-react": "^0.563.0" - }, - "devDependencies": { - "@types/node": "^22.14.0", - "@vitejs/plugin-react": "^5.0.0", - "typescript": "~5.8.2", - "vite": "^6.2.0" - } -} diff --git a/ado2-marketing-intelligence---lala-cabin/tsconfig.json b/ado2-marketing-intelligence---lala-cabin/tsconfig.json deleted file mode 100755 index 2c6eed5..0000000 --- a/ado2-marketing-intelligence---lala-cabin/tsconfig.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "experimentalDecorators": true, - "useDefineForClassFields": false, - "module": "ESNext", - "lib": [ - "ES2022", - "DOM", - "DOM.Iterable" - ], - "skipLibCheck": true, - "types": [ - "node" - ], - "moduleResolution": "bundler", - "isolatedModules": true, - "moduleDetection": "force", - "allowJs": true, - "jsx": "react-jsx", - "paths": { - "@/*": [ - "./*" - ] - }, - "allowImportingTsExtensions": true, - "noEmit": true - } -} \ No newline at end of file diff --git a/ado2-marketing-intelligence---lala-cabin/types.ts b/ado2-marketing-intelligence---lala-cabin/types.ts deleted file mode 100755 index 9ea0640..0000000 --- a/ado2-marketing-intelligence---lala-cabin/types.ts +++ /dev/null @@ -1,30 +0,0 @@ -export interface USP { - label: string; - subLabel: string; - score: number; // 0-100 - description: string; -} - -export interface TargetPersona { - segment: string; - age: string; - needs: string[]; - triggers: string[]; -} - -export interface BrandData { - name: string; - address: string; - subAddress: string; - summary: string; - locationAnalysis: string; - conceptAnalysis: string; - usps: USP[]; - keywords: string[]; - targets: TargetPersona[]; - positioning: { - category: string; - coreValue: string; - strategy: string; - }; -} \ No newline at end of file diff --git a/ado2-marketing-intelligence---lala-cabin/vite.config.ts b/ado2-marketing-intelligence---lala-cabin/vite.config.ts deleted file mode 100755 index ee5fb8d..0000000 --- a/ado2-marketing-intelligence---lala-cabin/vite.config.ts +++ /dev/null @@ -1,23 +0,0 @@ -import path from 'path'; -import { defineConfig, loadEnv } from 'vite'; -import react from '@vitejs/plugin-react'; - -export default defineConfig(({ mode }) => { - const env = loadEnv(mode, '.', ''); - return { - server: { - port: 3000, - host: '0.0.0.0', - }, - plugins: [react()], - define: { - 'process.env.API_KEY': JSON.stringify(env.GEMINI_API_KEY), - 'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY) - }, - resolve: { - alias: { - '@': path.resolve(__dirname, '.'), - } - } - }; -}); diff --git a/index.css b/index.css index c28b10d..3f51efb 100644 --- a/index.css +++ b/index.css @@ -7914,7 +7914,7 @@ } .genre-btn-placeholder { - /* Empty space for grid alignment */ + visibility: hidden; } /* Language Selector */ @@ -11905,6 +11905,27 @@ text-align: center; } +/* Schedule conflict notice */ +.upload-progress-schedule-notice { + display: flex; + align-items: flex-start; + gap: 0.5rem; + width: 100%; + background: rgba(251, 191, 36, 0.1); + border: 1px solid rgba(251, 191, 36, 0.35); + border-radius: 8px; + padding: 0.75rem 1rem; + color: #92400e; + font-size: 0.8125rem; + line-height: 1.5; +} + +.upload-progress-schedule-notice svg { + flex-shrink: 0; + margin-top: 1px; + stroke: #d97706; +} + /* YouTube Link */ .upload-progress-youtube-link { display: inline-flex; @@ -11978,37 +11999,6 @@ text-align: center; } -/* ===================================================== - Test Data Button (for development/testing) - ===================================================== */ -.test-data-button { - position: fixed; - bottom: 24px; - right: 24px; - padding: 12px 20px; - background-color: rgba(174, 114, 249, 0.9); - color: #FFFFFF; - border: 1px solid rgba(174, 114, 249, 0.5); - border-radius: 8px; - font-size: 14px; - font-weight: 600; - cursor: pointer; - z-index: 9999; - transition: all 0.2s ease; - box-shadow: 0 4px 12px rgba(174, 114, 249, 0.3); -} - -.test-data-button:hover { - background-color: rgba(174, 114, 249, 1); - transform: translateY(-2px); - box-shadow: 0 6px 16px rgba(174, 114, 249, 0.4); -} - -.test-data-button:disabled { - opacity: 0.6; - cursor: not-allowed; - transform: none; -} /* Calendar panel scrollbar */ .calendar-panel-scroll::-webkit-scrollbar { @@ -12583,3 +12573,1150 @@ opacity: 0.35; cursor: not-allowed; } + +/* ============================================ + Hero 로그인 버튼 (랜딩 전용) + ============================================ */ +.hero-login-btn { + display: flex; + height: 52px; + padding: 0 2.5rem; + justify-content: center; + align-items: center; + gap: 10px; + min-width: 200px; + border-radius: 999px; + background-color: #AE72F9; + color: #ffffff; + font-weight: 600; + font-size: 16px; + letter-spacing: -0.006em; + box-shadow: 0px 4px 24px 0px rgba(174, 114, 249, 0.4); + transition: all var(--transition-normal); + border: none; + cursor: pointer; + margin-top: 2rem; + animation: button-glow 1.5s ease-in-out infinite; +} + +.hero-login-btn:hover { + background-color: #9a5ef0; + animation: none; + box-shadow: 0px 4px 32px 0px rgba(174, 114, 249, 0.6); +} + +.hero-login-btn:active { + transform: scale(0.98); +} + +/* ============================================ + UrlInputContent 숏폼 버튼 + ============================================ */ +.url-input-shortform-btn { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + width: 100%; + height: 48px; + padding: 0 1.5rem; + margin-top: 12px; + border-radius: 999px; + border: 1px solid rgba(94, 235, 195, 0.4); + background: rgba(94, 235, 195, 0.06); + color: #5EEBC3; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all var(--transition-normal); + letter-spacing: -0.006em; +} + +.url-input-shortform-btn:hover { + border-color: rgba(94, 235, 195, 0.7); + background: rgba(94, 235, 195, 0.12); + color: #7ff0d0; +} + +.url-input-shortform-btn:active { + transform: scale(0.98); +} + +/* ============================================ + ShortformContent — 멀티스텝 위자드 + ============================================ */ + +/* 뒤로가기 버튼 (GenerationFlow 공통) */ +.shortform-back-btn { + display: flex; + align-items: center; + gap: 4px; + background-color: #462E64; + color: #CFABFB; + font-size: 0.875rem; + font-weight: 600; + padding: 0 1.25rem 0 0.5rem; + height: 36px; + border: 1px solid #694596; + border-radius: 999px; + cursor: pointer; + white-space: nowrap; + transition: background-color 0.2s; + line-height: 1.19; + letter-spacing: -0.006em; +} + +.shortform-back-btn:hover { + background-color: #5a3a80; +} + +/* 페이지 래퍼 */ +.sf-page { + display: flex; + flex-direction: column; + height: 100%; + background-color: #0c1a1b; + overflow: hidden; + position: relative; +} + +.sf-page-center { + align-items: center; + justify-content: center; +} + +/* 스티키 헤더 */ +.sf-sticky-header { + flex-shrink: 0; + display: flex; + align-items: center; + gap: 1rem; + padding: 12px 1.25rem; + border-bottom: 1px solid rgba(255,255,255,0.06); + background: #0c1a1b; + z-index: 10; +} + +/* 스크롤 영역 */ +.sf-scroll-area { + flex: 1; + overflow-y: auto; + overflow-x: hidden; + padding: 5rem 1.25rem 6rem; +} + +.sf-scroll-area::-webkit-scrollbar { width: 4px; } +.sf-scroll-area::-webkit-scrollbar-track { background: transparent; } +.sf-scroll-area::-webkit-scrollbar-thumb { background: #2a4a4d; border-radius: 2px; } + +/* ---- 히어로 영역 (Step 1만) ---- */ +.sf-hero { + max-width: 560px; + margin: 0 auto 2rem; + padding-top: 0; +} + +.sf-hero-title { + font-size: clamp(1.25rem, 4vw, 1.75rem); + font-weight: 800; + color: #E5F1F2; + line-height: 1.3; + margin: 0 0 0.75rem; + letter-spacing: -0.02em; +} + +.sf-hero-accent { + color: #AE72F9; +} + +.sf-hero-desc { + font-size: 0.9rem; + color: rgba(229, 241, 242, 0.55); + line-height: 1.6; + margin: 0; +} + +/* ---- 스텝 인디케이터 바 ---- */ +.sf-step-bar { + max-width: 560px; + margin: 0 auto 2rem; + display: flex; + align-items: flex-start; + gap: 0; + position: relative; +} + +.sf-step-bar::before { + content: ''; + position: absolute; + top: 14px; + left: 14px; + right: 14px; + height: 1px; + background: rgba(255,255,255,0.1); +} + +.sf-step-item { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + gap: 6px; + position: relative; + z-index: 1; +} + +.sf-step-circle { + width: 28px; + height: 28px; + border-radius: 50%; + border: 1.5px solid rgba(255,255,255,0.15); + background: #0c1a1b; + color: rgba(229,241,242,0.3); + font-size: 0.8rem; + font-weight: 700; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.25s; +} + +.sf-step-item.active .sf-step-circle { + border-color: #AE72F9; + background: rgba(174,114,249,0.15); + color: #CFABFB; +} + +.sf-step-item.done .sf-step-circle { + border-color: #5EEBC3; + background: rgba(94,235,195,0.15); + color: #5EEBC3; +} + +.sf-step-label { + display: flex; + flex-direction: column; + align-items: center; + gap: 1px; +} + +.sf-step-name { + font-size: 0.7rem; + font-weight: 600; + color: rgba(229,241,242,0.35); + letter-spacing: -0.01em; + white-space: nowrap; +} + +.sf-step-item.active .sf-step-name { color: #CFABFB; } +.sf-step-item.done .sf-step-name { color: #5EEBC3; } + +.sf-step-sub { + font-size: 0.625rem; + color: rgba(229,241,242,0.2); + white-space: nowrap; +} + +.sf-step-item.active .sf-step-sub { color: rgba(207,171,251,0.6); } +.sf-step-item.done .sf-step-sub { color: rgba(94,235,195,0.5); } + +/* ---- 카드 컨테이너 ---- */ +.sf-card { + max-width: 560px; + margin: 0 auto; + background: rgba(255,255,255,0.03); + border: 1px solid rgba(255,255,255,0.07); + border-radius: 16px; + padding: 1.5rem; + display: flex; + flex-direction: column; + gap: 1.25rem; +} + +.sf-card-title { + font-size: 1.125rem; + font-weight: 700; + color: #E5F1F2; + margin: 0; + letter-spacing: -0.02em; +} + +.sf-card-desc { + font-size: 0.8375rem; + color: rgba(229,241,242,0.5); + margin: -0.5rem 0 0; + line-height: 1.55; +} + +/* ---- 드래그앤드롭 업로드 영역 ---- */ +.sf-drop-zone { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 8px; + min-height: 130px; + border: 1.5px dashed rgba(94,235,195,0.3); + border-radius: 14px; + background: rgba(94,235,195,0.03); + cursor: pointer; + transition: all 0.2s; + padding: 1.5rem; +} + +.sf-drop-zone:hover { + border-color: rgba(94,235,195,0.6); + background: rgba(94,235,195,0.07); +} + +.sf-drop-icon { color: rgba(94,235,195,0.5); } +.sf-drop-zone:hover .sf-drop-icon { color: #5EEBC3; } + +.sf-drop-text { + font-size: 0.9rem; + font-weight: 600; + color: rgba(229,241,242,0.65); + margin: 0; +} + +.sf-drop-hint { + font-size: 0.775rem; + color: rgba(229,241,242,0.3); + margin: 0; +} + +/* ---- 사진 그리드 ---- */ +.sf-photo-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(90px, 1fr)); + gap: 8px; +} + +.sf-photo-item { + position: relative; + border-radius: 10px; + overflow: hidden; + aspect-ratio: 1; + background: rgba(0,0,0,0.3); +} + +.sf-photo-item img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + +.sf-photo-num { + position: absolute; + top: 5px; + left: 6px; + font-size: 0.7rem; + font-weight: 700; + color: #fff; + background: rgba(0,0,0,0.55); + border-radius: 4px; + padding: 1px 5px; + line-height: 1.4; +} + +.sf-photo-remove { + position: absolute; + top: 4px; + right: 4px; + width: 22px; + height: 22px; + border-radius: 50%; + background: rgba(0,0,0,0.6); + color: #fff; + border: none; + font-size: 15px; + line-height: 1; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; +} + +.sf-photo-remove:hover { background: rgba(220,50,50,0.85); } + +/* ---- 하단 푸터 ---- */ +.sf-footer { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + padding: 14px 1.25rem; + border-top: 1px solid rgba(255,255,255,0.07); + background: #0c1a1b; +} + +.sf-footer-two { + justify-content: flex-end; +} + +.sf-footer-info { + display: flex; + align-items: center; + gap: 8px; +} + +.sf-footer-count { + font-size: 0.9375rem; + font-weight: 700; + color: #E5F1F2; +} + +.sf-footer-status { + font-size: 0.8125rem; + color: rgba(229,241,242,0.4); +} + +.sf-footer-status.ok { + color: #5EEBC3; +} + +/* ---- 버튼 ---- */ +.sf-btn-next { + height: 44px; + padding: 0 1.5rem; + border-radius: 999px; + border: none; + background: #AE72F9; + color: #fff; + font-size: 0.9375rem; + font-weight: 700; + cursor: pointer; + letter-spacing: -0.01em; + transition: background 0.2s, opacity 0.2s; + font-family: inherit; + white-space: nowrap; +} + +.sf-btn-next:hover:not(:disabled) { background: #9a5ef0; } +.sf-btn-next:disabled { opacity: 0.3; cursor: not-allowed; } + +.sf-btn-prev { + height: 44px; + padding: 0 1.25rem; + border-radius: 999px; + border: 1px solid rgba(255,255,255,0.18); + background: transparent; + color: rgba(229,241,242,0.7); + font-size: 0.875rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s; + font-family: inherit; + white-space: nowrap; +} + +.sf-btn-prev:hover { + border-color: rgba(255,255,255,0.35); + color: #E5F1F2; +} + +.sf-btn-generate { + height: 44px; + padding: 0 1.75rem; + border-radius: 999px; + border: none; + background: linear-gradient(135deg, #AE72F9 0%, #5EEBC3 100%); + color: #fff; + font-size: 0.9375rem; + font-weight: 700; + cursor: pointer; + letter-spacing: -0.01em; + transition: opacity 0.2s; + font-family: inherit; + white-space: nowrap; +} + +.sf-btn-generate:hover:not(:disabled) { opacity: 0.88; } +.sf-btn-generate:disabled { opacity: 0.3; cursor: not-allowed; } + +/* ---- 폼 필드 ---- */ +.sf-field { + display: flex; + flex-direction: column; + gap: 6px; +} + +.sf-label { + font-size: 0.8375rem; + font-weight: 600; + color: rgba(229,241,242,0.75); + letter-spacing: -0.006em; +} + +.sf-required { color: #AE72F9; margin-left: 2px; } +.sf-optional { color: rgba(229,241,242,0.35); font-weight: 400; font-size: 0.8rem; margin-left: 4px; } + +.sf-input { + width: 100%; + height: 46px; + padding: 0 14px; + border-radius: 10px; + border: 1px solid rgba(255,255,255,0.1); + background: rgba(255,255,255,0.05); + color: #E5F1F2; + font-size: 0.9375rem; + transition: border-color 0.2s, background 0.2s; + box-sizing: border-box; + outline: none; + font-family: inherit; +} + +.sf-input:focus { + border-color: rgba(174,114,249,0.55); + background: rgba(255,255,255,0.07); +} + +.sf-input::placeholder { color: rgba(229,241,242,0.25); } + +.sf-textarea { + width: 100%; + padding: 12px 14px; + border-radius: 10px; + border: 1px solid rgba(255,255,255,0.1); + background: rgba(255,255,255,0.05); + color: #E5F1F2; + font-size: 0.9375rem; + line-height: 1.5; + transition: border-color 0.2s, background 0.2s; + box-sizing: border-box; + outline: none; + font-family: inherit; + resize: vertical; + min-height: 80px; +} + +.sf-textarea:focus { + border-color: rgba(174,114,249,0.55); + background: rgba(255,255,255,0.07); +} + +.sf-textarea::placeholder { color: rgba(229,241,242,0.25); } + +.sf-field-hint { + font-size: 0.775rem; + color: rgba(229,241,242,0.35); + line-height: 1.5; + margin: 0; +} + +/* ---- Kind 카드 선택 ---- */ +.sf-kind-grid { + display: flex; + flex-direction: column; + gap: 8px; +} + +.sf-kind-card { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 3px; + padding: 12px 14px; + border-radius: 12px; + border: 1.5px solid rgba(255,255,255,0.1); + background: rgba(255,255,255,0.03); + cursor: pointer; + transition: all 0.2s; + text-align: left; + font-family: inherit; +} + +.sf-kind-card:hover:not(.active) { + border-color: rgba(255,255,255,0.22); + background: rgba(255,255,255,0.06); +} + +.sf-kind-card.active { + border-color: #AE72F9; + background: rgba(174,114,249,0.12); +} + +.sf-kind-label { + font-size: 0.9rem; + font-weight: 700; + color: rgba(229,241,242,0.6); +} + +.sf-kind-card.active .sf-kind-label { color: #CFABFB; } + +.sf-kind-desc { + font-size: 0.775rem; + color: rgba(229,241,242,0.35); + line-height: 1.4; +} + +.sf-kind-card.active .sf-kind-desc { color: rgba(207,171,251,0.6); } + +/* ---- 자막 생성 헤더 행 ---- */ +.sf-subtitle-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; +} + +.sf-subtitle-btn { + height: 32px; + padding: 0 1rem; + border-radius: 999px; + border: 1px solid rgba(94,235,195,0.35); + background: rgba(94,235,195,0.07); + color: rgba(94,235,195,0.7); + font-size: 0.8125rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s; + font-family: inherit; + white-space: nowrap; +} + +.sf-subtitle-btn:hover:not(:disabled) { + border-color: rgba(94,235,195,0.65); + color: #5EEBC3; +} + +.sf-subtitle-btn:disabled { + opacity: 0.35; + cursor: not-allowed; +} + +/* ---- 자막 미리보기 결과 ---- */ +.sf-field-error { + font-size: 0.8rem; + color: #ff7070; + margin: 2px 0 0; +} + +.sf-preview-spec { + display: flex; + flex-direction: column; + gap: 2px; + margin-top: 10px; + border: 1px solid transparent; + border-radius: 12px; + overflow: hidden; +} + +.sf-preview-block { + padding: 12px 14px; + border-bottom: 1px solid rgba(255,255,255,0.05); + display: flex; + flex-direction: column; + gap: 6px; +} + +.sf-preview-block:last-child { + border-bottom: none; +} + +.sf-preview-tag { + font-size: 0.7rem; + font-weight: 700; + letter-spacing: 0.04em; + text-transform: uppercase; + color: rgba(94,235,195,0.7); + background: rgba(94,235,195,0.08); + border-radius: 4px; + padding: 2px 7px; + align-self: flex-start; +} + +.sf-preview-main { + font-size: 1rem; + font-weight: 700; + color: #E5F1F2; + margin: 0; + line-height: 1.4; +} + +.sf-preview-sub { + font-size: 0.875rem; + color: rgba(229,241,242,0.65); + margin: 0; + line-height: 1.5; +} + +.sf-preview-badges { + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.sf-preview-badge { + font-size: 0.8rem; + font-weight: 600; + color: #CFABFB; + background: rgba(174,114,249,0.12); + border: 1px solid rgba(174,114,249,0.3); + border-radius: 999px; + padding: 3px 10px; +} + +.sf-preview-caption { + background: rgba(255,255,255,0.02); +} + +.sf-preview-input { + width: 100%; + background: rgba(255,255,255,0.04); + border: 1px solid rgba(255,255,255,0.08); + border-radius: 6px; + color: rgba(229,241,242,0.75); + font-size: 0.875rem; + font-family: inherit; + padding: 6px 10px; + box-sizing: border-box; + outline: none; + transition: border-color 0.15s, background 0.15s; +} + +.sf-preview-input:focus { + border-color: rgba(94,235,195,0.4); + background: rgba(255,255,255,0.07); + color: #E5F1F2; +} + +.sf-preview-input-bold { + font-size: 1rem; + font-weight: 700; + color: #E5F1F2; +} + +.sf-preview-badge-inputs { + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.sf-preview-badge-input { + background: rgba(174,114,249,0.1); + border: 1px solid rgba(174,114,249,0.25); + border-radius: 999px; + color: #CFABFB; + font-size: 0.8rem; + font-weight: 600; + font-family: inherit; + padding: 4px 12px; + outline: none; + min-width: 60px; + width: auto; + max-width: 100%; + transition: border-color 0.15s; +} + +.sf-preview-badge-input:focus { + border-color: rgba(174,114,249,0.6); + background: rgba(174,114,249,0.18); +} + +.sf-preview-textarea { + width: 100%; + background: rgba(255,255,255,0.04); + border: 1px solid rgba(255,255,255,0.08); + border-radius: 6px; + color: rgba(229,241,242,0.7); + font-size: 0.8375rem; + font-family: inherit; + padding: 8px 10px; + box-sizing: border-box; + outline: none; + resize: vertical; + line-height: 1.5; + transition: border-color 0.15s, background 0.15s; +} + +.sf-preview-textarea:focus { + border-color: rgba(94,235,195,0.4); + background: rgba(255,255,255,0.07); + color: #E5F1F2; +} + +/* ---- 생성 중 화면 ---- */ +.sf-generating { + display: flex; + flex-direction: column; + align-items: center; + gap: 1.75rem; + padding: 3rem 2rem 4rem; + width: 100%; + max-width: 560px; + margin: 0 auto; +} + +/* 스피너 + 아이콘 오버레이 */ +.sf-gen-orb-ring { + position: relative; + width: 120px; + height: 120px; + display: flex; + align-items: center; + justify-content: center; +} + +.sf-gen-spinner-lg { + position: absolute; + inset: 0; + border-radius: 50%; + border: 3px solid rgba(174,114,249,0.15); + border-top-color: #AE72F9; + border-right-color: rgba(94,235,195,0.5); + animation: sf-spin 1.1s linear infinite; +} + +@keyframes sf-spin { + to { transform: rotate(360deg); } +} + +.sf-gen-icon { + color: rgba(207,171,251,0.7); +} + +.sf-gen-title { + font-size: 1.5rem; + font-weight: 800; + color: #E5F1F2; + margin: 0; + letter-spacing: -0.02em; + text-align: center; +} + +.sf-gen-msg { + font-size: 0.9375rem; + font-weight: 500; + color: rgba(229,241,242,0.6); + margin: -0.75rem 0 0; + letter-spacing: -0.01em; + text-align: center; + min-height: 1.4em; +} + +.sf-gen-sub { + font-size: 0.8125rem; + color: rgba(229,241,242,0.35); + margin: -0.75rem 0 0; + text-align: center; +} + +/* 진행 단계 표시 */ +.sf-gen-steps { + display: flex; + flex-direction: column; + gap: 12px; + width: 100%; + max-width: 280px; + padding: 1.25rem 1.5rem; + border: 1px solid rgba(255,255,255,0.07); + border-radius: 14px; + background: rgba(255,255,255,0.03); +} + +.sf-gen-step { + display: flex; + align-items: center; + gap: 10px; + font-size: 0.875rem; + color: rgba(229,241,242,0.3); + transition: color 0.3s; +} + +.sf-gen-step.done { + color: rgba(94,235,195,0.7); +} + +.sf-gen-step.active { + color: #E5F1F2; + font-weight: 600; +} + +.sf-gen-step-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: currentColor; + flex-shrink: 0; + transition: background 0.3s; +} + +.sf-gen-step.active .sf-gen-step-dot { + background: #AE72F9; + box-shadow: 0 0 6px rgba(174,114,249,0.6); + animation: sf-dot-pulse 1s ease-in-out infinite; +} + +.sf-gen-step.done .sf-gen-step-dot { + background: #5EEBC3; +} + +@keyframes sf-dot-pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.4; } +} + +/* ---- 완성 화면 ---- */ +.sf-result { + max-width: 400px; + margin: 0 auto; + display: flex; + flex-direction: column; + align-items: center; + gap: 1.25rem; + padding: 1rem 0 2rem; +} + +.sf-result-label { + font-size: 1.125rem; + font-weight: 700; + color: #5EEBC3; + margin: 0; +} + +.sf-result-video-wrap { + width: 100%; + max-width: 320px; + aspect-ratio: 9 / 16; + border-radius: 16px; + overflow: hidden; + background: #000; + position: relative; +} + +.sf-result-video { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + border-radius: 16px; +} + +.sf-result-actions { + display: flex; + flex-wrap: wrap; + gap: 10px; + width: 100%; + justify-content: center; +} + +.sf-download-btn { + height: 48px; + padding: 0 2rem; + border-radius: 999px; + border: none; + background: #AE72F9; + color: #fff; + font-size: 0.9375rem; + font-weight: 600; + font-family: inherit; + cursor: pointer; + transition: background 0.2s, opacity 0.2s; + display: inline-flex; + align-items: center; + justify-content: center; +} + +.sf-download-btn:hover:not(:disabled) { background: #9a5ef0; } +.sf-download-btn:disabled { opacity: 0.5; cursor: not-allowed; } + +/* ---- 에러 토스트 ---- */ +.sf-error-toast { + position: fixed; + bottom: 80px; + left: 50%; + transform: translateX(-50%); + background: rgba(200,50,50,0.9); + color: #fff; + font-size: 0.875rem; + font-weight: 500; + padding: 10px 20px; + border-radius: 999px; + z-index: 100; + white-space: nowrap; + max-width: 90vw; + text-align: center; +} + +/* ---- 데스크톱: sf-* 요소 확대 ---- */ +@media (min-width: 768px) { + .sf-scroll-area { + padding: 5rem 2.5rem 6rem; + } + + .sf-hero, + .sf-step-bar, + .sf-card { + max-width: 760px; + } + + .sf-hero-title { + font-size: 2.25rem; + margin-bottom: 1rem; + } + + .sf-hero-desc { + font-size: 1rem; + } + + .sf-card { + padding: 2rem 2.5rem; + gap: 1.5rem; + border-radius: 20px; + } + + .sf-card-title { + font-size: 1.375rem; + } + + .sf-card-desc { + font-size: 0.9rem; + margin-top: -0.75rem; + } + + .sf-drop-zone { + min-height: 180px; + padding: 2.5rem; + } + + .sf-drop-text { + font-size: 1rem; + } + + .sf-drop-hint { + font-size: 0.875rem; + } + + .sf-photo-grid { + grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); + gap: 12px; + } + + .sf-step-circle { + width: 34px; + height: 34px; + font-size: 0.875rem; + } + + .sf-step-bar::before { + top: 17px; + } + + .sf-step-name { + font-size: 0.8rem; + } + + .sf-step-sub { + font-size: 0.7rem; + } + + .sf-kind-grid { + flex-direction: row; + gap: 10px; + } + + .sf-kind-card { + flex: 1; + padding: 16px 18px; + } + + .sf-kind-label { + font-size: 1rem; + } + + .sf-kind-desc { + font-size: 0.825rem; + } + + .sf-input { + height: 52px; + font-size: 1rem; + padding: 0 16px; + } + + .sf-textarea { + padding: 14px 16px; + font-size: 1rem; + min-height: 96px; + } + + .sf-label { + font-size: 0.9rem; + } + + .sf-field-hint { + font-size: 0.825rem; + } + + .sf-btn-next, + .sf-btn-generate { + height: 50px; + padding: 0 2rem; + font-size: 1rem; + } + + .sf-btn-prev { + height: 50px; + padding: 0 1.5rem; + font-size: 0.9375rem; + } + + .sf-footer { + padding: 16px 2.5rem; + } + + .sf-footer-count { + font-size: 1.0625rem; + } + + .sf-footer-status { + font-size: 0.875rem; + } + + .sf-gen-title { + font-size: 1.875rem; + } + + .sf-gen-msg { + font-size: 1rem; + } + + .sf-gen-sub { + font-size: 0.875rem; + } + + .sf-gen-orb-ring { + width: 160px; + height: 160px; + } + + .sf-gen-icon svg { + width: 48px; + height: 48px; + } + + .sf-gen-steps { + max-width: 320px; + font-size: 0.9375rem; + } + + .sf-result { + max-width: 500px; + } + + .sf-result-label { + font-size: 1.375rem; + } + + .sf-download-btn { + height: 52px; + line-height: 52px; + font-size: 1rem; + padding: 0 2.5rem; + } +} diff --git a/package-lock.json b/package-lock.json index b35197e..ed853d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,8 @@ }, "devDependencies": { "@types/node": "^22.14.0", + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^5.0.0", "typescript": "~5.8.2", "vite": "^6.2.0" @@ -52,6 +54,7 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -1288,10 +1291,32 @@ "integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~6.21.0" } }, + "node_modules/@types/react": { + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, "node_modules/@types/use-sync-external-store": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", @@ -1349,6 +1374,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -1400,6 +1426,13 @@ "dev": true, "license": "MIT" }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/d3-array": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", @@ -1691,6 +1724,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.4" }, @@ -1811,6 +1845,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -1852,6 +1887,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -1861,6 +1897,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -1907,6 +1944,7 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", "license": "MIT", + "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -1969,7 +2007,8 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -2083,6 +2122,7 @@ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2166,6 +2206,7 @@ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", diff --git a/package.json b/package.json index bdf154e..b049997 100755 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ }, "devDependencies": { "@types/node": "^22.14.0", + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^5.0.0", "typescript": "~5.8.2", "vite": "^6.2.0" diff --git a/remotion/package-lock.json b/remotion/package-lock.json new file mode 100644 index 0000000..aaa7a82 --- /dev/null +++ b/remotion/package-lock.json @@ -0,0 +1,2907 @@ +{ + "name": "@ado2/higgsfield-remotion", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@ado2/higgsfield-remotion", + "version": "0.1.0", + "dependencies": { + "@remotion/cli": "4.0.468", + "@remotion/google-fonts": "4.0.468", + "react": "19.2.0", + "react-dom": "19.2.0", + "remotion": "4.0.468" + }, + "devDependencies": { + "@types/react": "19.2.0", + "typescript": "5.7.3" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", + "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", + "license": "MIT", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", + "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz", + "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", + "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz", + "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", + "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", + "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", + "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", + "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", + "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", + "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", + "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", + "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", + "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", + "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", + "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", + "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", + "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", + "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", + "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", + "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", + "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", + "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", + "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", + "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", + "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", + "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mediabunny/aac-encoder": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/@mediabunny/aac-encoder/-/aac-encoder-1.45.0.tgz", + "integrity": "sha512-vLQw8cY7Me6pvTTMkMhOiH9UCuINzfTOETCeDxbGNeNfDqc/7QlxloUH1Ylp/Zz2ek0O8kc6YdygV2vWAPakrA==", + "license": "MPL-2.0", + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/Vanilagy" + }, + "peerDependencies": { + "mediabunny": "^1.0.0" + } + }, + "node_modules/@mediabunny/flac-encoder": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/@mediabunny/flac-encoder/-/flac-encoder-1.45.0.tgz", + "integrity": "sha512-LfKbAMZVkxRS7PpEIVnWOY/l0KcHv+rjO7pYY3O0TPCZvbHWfrnQjn8JPacPIfuq6Yv7r4f8lhcl7yHSynoRkQ==", + "license": "MPL-2.0", + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/Vanilagy" + }, + "peerDependencies": { + "mediabunny": "^1.0.0" + } + }, + "node_modules/@mediabunny/mp3-encoder": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/@mediabunny/mp3-encoder/-/mp3-encoder-1.45.0.tgz", + "integrity": "sha512-Bobi6AaQYEc7TWmPJ8Q0/hcUtBN7pLUC2qjoC7oZR4FcGqGztby6k7A1SWlmswoMOEIhYsOrgDaemrSDAC0QVQ==", + "license": "MPL-2.0", + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/Vanilagy" + }, + "peerDependencies": { + "mediabunny": "^1.0.0" + } + }, + "node_modules/@module-federation/error-codes": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.22.0.tgz", + "integrity": "sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==", + "license": "MIT" + }, + "node_modules/@module-federation/runtime": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.22.0.tgz", + "integrity": "sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==", + "license": "MIT", + "dependencies": { + "@module-federation/error-codes": "0.22.0", + "@module-federation/runtime-core": "0.22.0", + "@module-federation/sdk": "0.22.0" + } + }, + "node_modules/@module-federation/runtime-core": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-core/-/runtime-core-0.22.0.tgz", + "integrity": "sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==", + "license": "MIT", + "dependencies": { + "@module-federation/error-codes": "0.22.0", + "@module-federation/sdk": "0.22.0" + } + }, + "node_modules/@module-federation/runtime-tools": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.22.0.tgz", + "integrity": "sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==", + "license": "MIT", + "dependencies": { + "@module-federation/runtime": "0.22.0", + "@module-federation/webpack-bundler-runtime": "0.22.0" + } + }, + "node_modules/@module-federation/sdk": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.22.0.tgz", + "integrity": "sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==", + "license": "MIT" + }, + "node_modules/@module-federation/webpack-bundler-runtime": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.22.0.tgz", + "integrity": "sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==", + "license": "MIT", + "dependencies": { + "@module-federation/runtime": "0.22.0", + "@module-federation/sdk": "0.22.0" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz", + "integrity": "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.5.0", + "@emnapi/runtime": "^1.5.0", + "@tybys/wasm-util": "^0.10.1" + } + }, + "node_modules/@remotion/bundler": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/bundler/-/bundler-4.0.468.tgz", + "integrity": "sha512-jsCzE4KmDLnV+hz4UOWjOJnhzH90LNrnqIrSpwg+Wu5fZip9tPA414qZNKuF+M3Z4riBC4UOJVt5/BQ41Uk0wg==", + "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "@remotion/media-parser": "4.0.468", + "@remotion/studio": "4.0.468", + "@remotion/studio-shared": "4.0.468", + "@remotion/timeline-utils": "4.0.468", + "@rspack/core": "1.7.6", + "@rspack/plugin-react-refresh": "1.6.1", + "css-loader": "7.1.4", + "esbuild": "0.28.0", + "react-refresh": "0.18.0", + "remotion": "4.0.468", + "style-loader": "4.0.0", + "webpack": "5.105.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@remotion/cli": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/cli/-/cli-4.0.468.tgz", + "integrity": "sha512-wHc9cjDYJDiP5hfFHal1xuDnkb5Wku6162tCQ9V5bNf5BKC1zEN6DA+S5sN/yWMhYgUxyaO12nLmz9h50PrkDA==", + "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "@remotion/bundler": "4.0.468", + "@remotion/media-utils": "4.0.468", + "@remotion/player": "4.0.468", + "@remotion/renderer": "4.0.468", + "@remotion/studio": "4.0.468", + "@remotion/studio-server": "4.0.468", + "@remotion/studio-shared": "4.0.468", + "dotenv": "17.3.1", + "minimist": "1.2.6", + "prompts": "2.4.2", + "remotion": "4.0.468" + }, + "bin": { + "remotion": "remotion-cli.js", + "remotionb": "remotionb-cli.js", + "remotiond": "remotiond-cli.js" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@remotion/compositor-darwin-arm64": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/compositor-darwin-arm64/-/compositor-darwin-arm64-4.0.468.tgz", + "integrity": "sha512-wB1m1bSvqU+CGg4qxZt8XGZf+4eDFot58IMy6Z7b2+qHpvE/qdtm2CENvlSuDu/zVO6b10wWbaWGKz0jf2YM0Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@remotion/compositor-darwin-x64": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/compositor-darwin-x64/-/compositor-darwin-x64-4.0.468.tgz", + "integrity": "sha512-WdJS1T7zbxHRraK9F6SIpWbfU3UprSeLnmoHtkMhW35o0zfaq3scfprmm1eTHSynlttz2nRwEvNPrNvhbJrBtg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@remotion/compositor-linux-arm64-gnu": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/compositor-linux-arm64-gnu/-/compositor-linux-arm64-gnu-4.0.468.tgz", + "integrity": "sha512-HEXjGlcL1b/7EfZkJOSs+XQt5mJ88f6SJB/uIHzde3hpYwZvqmtls9zC8wzM6VncIYNQOu8gDxfbVzAZ+Hfv3Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@remotion/compositor-linux-arm64-musl": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/compositor-linux-arm64-musl/-/compositor-linux-arm64-musl-4.0.468.tgz", + "integrity": "sha512-8Qf14zSsvbAKfWdcrdxhPP4pm0A6qsc72vzWjDIH1XmYAKHg49eOHolQTr6bzNyekMLgJ3eKC66W4UFYny0gfg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@remotion/compositor-linux-x64-gnu": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/compositor-linux-x64-gnu/-/compositor-linux-x64-gnu-4.0.468.tgz", + "integrity": "sha512-PqbgcutSTR3Od3WTkOlMBIgW4sFeylnWYK8Pdcfs81TePD2xFDXEKY45HBYpi58EzSt6zp2qdQAW8b3NrIhEiw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@remotion/compositor-linux-x64-musl": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/compositor-linux-x64-musl/-/compositor-linux-x64-musl-4.0.468.tgz", + "integrity": "sha512-EtMjnQvaYOvNDGvYqEQdcfznN0sKCf7fT9lA1admcTYJ7h/jxFydj8aTTpvgmA3VG4TN1IL70RSLVu3Esx1Ylg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@remotion/compositor-win32-x64-msvc": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/compositor-win32-x64-msvc/-/compositor-win32-x64-msvc-4.0.468.tgz", + "integrity": "sha512-h6fpDu9e1Wfpg5jpYABYwbh1y3uqhkOS3FYfnUCvKNBp+ZpNkla8TfsQsQVoMECtxxOwLHLYesY5BzvUtOZ/5Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@remotion/google-fonts": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/google-fonts/-/google-fonts-4.0.468.tgz", + "integrity": "sha512-Dl59gKL+GiVaozSfNt+b4b6iYyR5T1GtlMOF5Yxn/JLyRSw1hUYFreon+m0qZ8n5mZ+iipqlKeNjfYKGWtbtww==", + "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "remotion": "4.0.468" + } + }, + "node_modules/@remotion/licensing": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/licensing/-/licensing-4.0.468.tgz", + "integrity": "sha512-l0iIn8YVdKiOBYDN1bnbtguMReq/Q7QozxtHr+mKIHr66zeCjhpwFvHklmN/LXMFGWh2OxfNJ6fgXKWS1Iuy3A==", + "license": "MIT" + }, + "node_modules/@remotion/media-parser": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/media-parser/-/media-parser-4.0.468.tgz", + "integrity": "sha512-lh6IGOmVnCsV6oytuGbgr9PB/AkWnWRwBr8tsq7gpjBqhR3oLe3fFd+p7jJreMrF+l4y55bcrf52qT3yxBD9fw==", + "license": "Remotion License https://remotion.dev/license" + }, + "node_modules/@remotion/media-utils": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/media-utils/-/media-utils-4.0.468.tgz", + "integrity": "sha512-at4/faHpezfYuv3WikG1ePQY3pBnjWTgFv2++IRJ4z5+ZneoSM1mtFS9lIJO9maCPRLxJRqHWOI0+rnNrNHADA==", + "license": "MIT", + "dependencies": { + "mediabunny": "1.45.0", + "remotion": "4.0.468" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@remotion/player": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/player/-/player-4.0.468.tgz", + "integrity": "sha512-M0kdFnAZvstMctK2ypoTkFOahI61kUE9HnQAh5/9dPb+FlOwCDLRDnM2LBkltZsJxgqgH1nDe1iNPsry0QCjmw==", + "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "remotion": "4.0.468" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@remotion/renderer": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/renderer/-/renderer-4.0.468.tgz", + "integrity": "sha512-n8fLD9o5W0N4FEz9V7OBmHjiG/Qo36cwH/MaUsEdATCfKIUGlMjrBvyFuKGobl5GHdt3xCyzYQoar3vFiwll8Q==", + "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "@remotion/licensing": "4.0.468", + "@remotion/streaming": "4.0.468", + "execa": "5.1.1", + "remotion": "4.0.468", + "source-map": "0.8.0-beta.0", + "ws": "8.20.1" + }, + "optionalDependencies": { + "@remotion/compositor-darwin-arm64": "4.0.468", + "@remotion/compositor-darwin-x64": "4.0.468", + "@remotion/compositor-linux-arm64-gnu": "4.0.468", + "@remotion/compositor-linux-arm64-musl": "4.0.468", + "@remotion/compositor-linux-x64-gnu": "4.0.468", + "@remotion/compositor-linux-x64-musl": "4.0.468", + "@remotion/compositor-win32-x64-msvc": "4.0.468" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@remotion/streaming": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/streaming/-/streaming-4.0.468.tgz", + "integrity": "sha512-Ts0pq7Lh+ztSvJp5oOTHOc2oKuQ3LtXGfWhQKiJXm81Xz5Qjz3KbPhQ/Z94/GzbZDRrs+zdzwRyqS6pTFnoLdg==", + "license": "MIT" + }, + "node_modules/@remotion/studio": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/studio/-/studio-4.0.468.tgz", + "integrity": "sha512-Wzy/EtI4GLbkExet253KTrwOunJb3ciGFf+/bd0FBOt3plmaPxuJe4iJ4IvMwwA0/xR1U9HkgXg/gPZxzVHsSQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.31", + "@remotion/media-utils": "4.0.468", + "@remotion/player": "4.0.468", + "@remotion/renderer": "4.0.468", + "@remotion/studio-shared": "4.0.468", + "@remotion/timeline-utils": "4.0.468", + "@remotion/web-renderer": "4.0.468", + "@remotion/zod-types": "4.0.468", + "mediabunny": "1.45.0", + "memfs": "3.4.3", + "open": "8.4.2", + "remotion": "4.0.468", + "semver": "7.5.3", + "zod": "4.3.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@remotion/studio-server": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/studio-server/-/studio-server-4.0.468.tgz", + "integrity": "sha512-xg5BlBUSnb/t1wa84fPwfgOe5WkS25fr6JVEUt9SBRZW3bbtcrGgCfykSFvIqx/nlG6S9Rw9XZuQnO6GOKR2oQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "7.24.1", + "@babel/types": "7.24.0", + "@remotion/bundler": "4.0.468", + "@remotion/renderer": "4.0.468", + "@remotion/studio-shared": "4.0.468", + "memfs": "3.4.3", + "open": "8.4.2", + "prettier": "3.8.1", + "recast": "0.23.11", + "remotion": "4.0.468", + "semver": "7.5.3" + } + }, + "node_modules/@remotion/studio-shared": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/studio-shared/-/studio-shared-4.0.468.tgz", + "integrity": "sha512-PNfOIpQ+tSzOuEbedU+SueyvSXemp2i5IesHwlJgN+70jcbOCt29d5/1MDlJbgcydBe9fMnsrYrosP3ln5kAxA==", + "license": "MIT", + "dependencies": { + "remotion": "4.0.468" + } + }, + "node_modules/@remotion/timeline-utils": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/timeline-utils/-/timeline-utils-4.0.468.tgz", + "integrity": "sha512-B99PXVVDILfUurh8QesJAfwZOy56H2oHs6dxf8HUnUN8xMSNKJx62C0zELiYb56KBTT1ryTGxWY64lTaUIuEcw==", + "license": "MIT", + "dependencies": { + "mediabunny": "1.45.0" + } + }, + "node_modules/@remotion/web-renderer": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/web-renderer/-/web-renderer-4.0.468.tgz", + "integrity": "sha512-Ucxw9F7IkqHQdol9qu6UqpQKr29JjeyLrTDPSzDp0ec55MCO7oDvlktYkdc8IGmMQfh0FD8b603phUSXax4XnQ==", + "license": "UNLICENSED", + "dependencies": { + "@mediabunny/aac-encoder": "1.45.0", + "@mediabunny/flac-encoder": "1.45.0", + "@mediabunny/mp3-encoder": "1.45.0", + "@remotion/licensing": "4.0.468", + "mediabunny": "1.45.0", + "remotion": "4.0.468" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@remotion/zod-types": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/@remotion/zod-types/-/zod-types-4.0.468.tgz", + "integrity": "sha512-W6KejABTdCFZW0P0uVO7Ol7QMD8n/ewaKhyo5AzKx+0CfIelgQREWDXINBzJxZM5XnJXdn9Q0ffDWsBCnQFAaw==", + "license": "MIT", + "dependencies": { + "remotion": "4.0.468" + }, + "peerDependencies": { + "zod": "4.3.6" + } + }, + "node_modules/@rspack/binding": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.7.6.tgz", + "integrity": "sha512-/NrEcfo8Gx22hLGysanrV6gHMuqZSxToSci/3M4kzEQtF5cPjfOv5pqeLK/+B6cr56ul/OmE96cCdWcXeVnFjQ==", + "license": "MIT", + "optionalDependencies": { + "@rspack/binding-darwin-arm64": "1.7.6", + "@rspack/binding-darwin-x64": "1.7.6", + "@rspack/binding-linux-arm64-gnu": "1.7.6", + "@rspack/binding-linux-arm64-musl": "1.7.6", + "@rspack/binding-linux-x64-gnu": "1.7.6", + "@rspack/binding-linux-x64-musl": "1.7.6", + "@rspack/binding-wasm32-wasi": "1.7.6", + "@rspack/binding-win32-arm64-msvc": "1.7.6", + "@rspack/binding-win32-ia32-msvc": "1.7.6", + "@rspack/binding-win32-x64-msvc": "1.7.6" + } + }, + "node_modules/@rspack/binding-darwin-arm64": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.7.6.tgz", + "integrity": "sha512-NZ9AWtB1COLUX1tA9HQQvWpTy07NSFfKBU8A6ylWd5KH8AePZztpNgLLAVPTuNO4CZXYpwcoclf8jG/luJcQdQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rspack/binding-darwin-x64": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.7.6.tgz", + "integrity": "sha512-J2g6xk8ZS7uc024dNTGTHxoFzFovAZIRixUG7PiciLKTMP78svbSSWrmW6N8oAsAkzYfJWwQpVgWfFNRHvYxSw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rspack/binding-linux-arm64-gnu": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.7.6.tgz", + "integrity": "sha512-eQfcsaxhFrv5FmtaA7+O1F9/2yFDNIoPZzV/ZvqvFz5bBXVc4FAm/1fVpBg8Po/kX1h0chBc7Xkpry3cabFW8w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-arm64-musl": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.7.6.tgz", + "integrity": "sha512-DfQXKiyPIl7i1yECHy4eAkSmlUzzsSAbOjgMuKn7pudsWf483jg0UUYutNgXSlBjc/QSUp7906Cg8oty9OfwPA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-x64-gnu": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.7.6.tgz", + "integrity": "sha512-NdA+2X3lk2GGrMMnTGyYTzM3pn+zNjaqXqlgKmFBXvjfZqzSsKq3pdD1KHZCd5QHN+Fwvoszj0JFsquEVhE1og==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-x64-musl": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.7.6.tgz", + "integrity": "sha512-rEy6MHKob02t/77YNgr6dREyJ0e0tv1X6Xsg8Z5E7rPXead06zefUbfazj4RELYySWnM38ovZyJAkPx/gOn3VA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-wasm32-wasi": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-1.7.6.tgz", + "integrity": "sha512-YupOrz0daSG+YBbCIgpDgzfMM38YpChv+afZpaxx5Ml7xPeAZIIdgWmLHnQ2rts73N2M1NspAiBwV00Xx0N4Vg==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "1.0.7" + } + }, + "node_modules/@rspack/binding-win32-arm64-msvc": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.7.6.tgz", + "integrity": "sha512-INj7aVXjBvlZ84kEhSK4kJ484ub0i+BzgnjDWOWM1K+eFYDZjLdAsQSS3fGGXwVc3qKbPIssFfnftATDMTEJHQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/binding-win32-ia32-msvc": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.7.6.tgz", + "integrity": "sha512-lXGvC+z67UMcw58In12h8zCa9IyYRmuptUBMItQJzu+M278aMuD1nETyGLL7e4+OZ2lvrnnBIcjXN1hfw2yRzw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/binding-win32-x64-msvc": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.7.6.tgz", + "integrity": "sha512-zeUxEc0ZaPpmaYlCeWcjSJUPuRRySiSHN23oJ2Xyw0jsQ01Qm4OScPdr0RhEOFuK/UE+ANyRtDo4zJsY52Hadw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/core": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.7.6.tgz", + "integrity": "sha512-Iax6UhrfZqJajA778c1d5DBFbSIqPOSrI34kpNIiNpWd8Jq7mFIa+Z60SQb5ZQDZuUxcCZikjz5BxinFjTkg7Q==", + "license": "MIT", + "dependencies": { + "@module-federation/runtime-tools": "0.22.0", + "@rspack/binding": "1.7.6", + "@rspack/lite-tapable": "1.1.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "@swc/helpers": ">=0.5.1" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@rspack/lite-tapable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rspack/lite-tapable/-/lite-tapable-1.1.0.tgz", + "integrity": "sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==", + "license": "MIT" + }, + "node_modules/@rspack/plugin-react-refresh": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@rspack/plugin-react-refresh/-/plugin-react-refresh-1.6.1.tgz", + "integrity": "sha512-eqqW5645VG3CzGzFgNg5HqNdHVXY+567PGjtDhhrM8t67caxmsSzRmT5qfoEIfBcGgFkH9vEg7kzXwmCYQdQDw==", + "license": "MIT", + "dependencies": { + "error-stack-parser": "^2.1.4", + "html-entities": "^2.6.0" + }, + "peerDependencies": { + "react-refresh": ">=0.10.0 <1.0.0", + "webpack-hot-middleware": "2.x" + }, + "peerDependenciesMeta": { + "webpack-hot-middleware": { + "optional": true + } + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/dom-mediacapture-transform": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@types/dom-mediacapture-transform/-/dom-mediacapture-transform-0.1.11.tgz", + "integrity": "sha512-Y2p+nGf1bF2XMttBnsVPHUWzRRZzqUoJAKmiP10b5umnO6DDrWI0BrGDJy1pOHoOULVmGSfFNkQrAlC5dcj6nQ==", + "license": "MIT", + "dependencies": { + "@types/dom-webcodecs": "*" + } + }, + "node_modules/@types/dom-webcodecs": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/@types/dom-webcodecs/-/dom-webcodecs-0.1.13.tgz", + "integrity": "sha512-O5hkiFIcjjszPIYyUSyvScyvrBoV3NOEEZx/pMlsu44TKzWNkLVBBxnxJz42in5n3QIolYOcBYFCPZZ0h8SkwQ==", + "license": "MIT" + }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", + "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", + "license": "MIT", + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, + "node_modules/@types/react": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.0.tgz", + "integrity": "sha512-1LOH8xovvsKsCBq1wnT4ntDUdCJKmnEakhsuoUSy6ExlHCkGP2hqnatagYTgFk6oeL0VU31u7SNjunPN+GchtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "license": "Apache-2.0" + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.32", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.32.tgz", + "integrity": "sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001793", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", + "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-loader": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.4.tgz", + "integrity": "sha512-vv3J9tlOl04WjiMvHQI/9tmIrCxVrj6PFbHemBB1iihpeRbi/I4h033eoFIhwxBBqLhI0KYFS7yvynBFhIZfTw==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.40", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.6.3" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", + "webpack": "^5.27.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-loader/node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "17.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz", + "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.363", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.363.tgz", + "integrity": "sha512-VjUKPyWzGnT1fujlkEGC/BvN70Hh70KXtAqcmniXviYlJC/ivcT+BWGPyxWVbJZLfvtKR6dqg1L7T7pgAMBtWA==", + "license": "ISC" + }, + "node_modules/enhanced-resolve": { + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.0.tgz", + "integrity": "sha512-xYcDWrpELkFzz9SpZ3PlI6Eu6eD93Yf0WLDRxikGhWJ3MAir2SNZTIVCVZqZ/NUyx8AdMc2gT9C0gPiw18kG+A==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/es-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", + "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.0", + "@esbuild/android-arm": "0.28.0", + "@esbuild/android-arm64": "0.28.0", + "@esbuild/android-x64": "0.28.0", + "@esbuild/darwin-arm64": "0.28.0", + "@esbuild/darwin-x64": "0.28.0", + "@esbuild/freebsd-arm64": "0.28.0", + "@esbuild/freebsd-x64": "0.28.0", + "@esbuild/linux-arm": "0.28.0", + "@esbuild/linux-arm64": "0.28.0", + "@esbuild/linux-ia32": "0.28.0", + "@esbuild/linux-loong64": "0.28.0", + "@esbuild/linux-mips64el": "0.28.0", + "@esbuild/linux-ppc64": "0.28.0", + "@esbuild/linux-riscv64": "0.28.0", + "@esbuild/linux-s390x": "0.28.0", + "@esbuild/linux-x64": "0.28.0", + "@esbuild/netbsd-arm64": "0.28.0", + "@esbuild/netbsd-x64": "0.28.0", + "@esbuild/openbsd-arm64": "0.28.0", + "@esbuild/openbsd-x64": "0.28.0", + "@esbuild/openharmony-arm64": "0.28.0", + "@esbuild/sunos-x64": "0.28.0", + "@esbuild/win32-arm64": "0.28.0", + "@esbuild/win32-ia32": "0.28.0", + "@esbuild/win32-x64": "0.28.0" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fs-monkey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", + "license": "Unlicense" + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause" + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/loader-runner": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", + "license": "MIT", + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mediabunny": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.45.0.tgz", + "integrity": "sha512-oK3sMMYbucoF6LUX62L/2M9d+p9ve6KDQgL87kNfhsB0/XmTe9iRLUcgQgg9Gpgvi8Sb96zYfOUL6i17y0bdNg==", + "license": "MPL-2.0", + "workspaces": [ + ".", + "packages/*" + ], + "dependencies": { + "@types/dom-mediacapture-transform": "^0.1.11", + "@types/dom-webcodecs": "0.1.13" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/Vanilagy" + } + }, + "node_modules/memfs": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.3.tgz", + "integrity": "sha512-eivjfi7Ahr6eQTn44nvTnR60e4a1Fs1Via2kCR5lHo/kyNoiMWaXCNJ/GpSd0ilXas2JSOl9B5FTIhflXu0hlg==", + "license": "Unlicense", + "dependencies": { + "fs-monkey": "1.0.3" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.46", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.46.tgz", + "integrity": "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "license": "ISC", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "node_modules/prettier": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", + "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", + "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.0" + } + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/recast": { + "version": "0.23.11", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", + "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", + "license": "MIT", + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/recast/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/remotion": { + "version": "4.0.468", + "resolved": "https://registry.npmjs.org/remotion/-/remotion-4.0.468.tgz", + "integrity": "sha512-TPfoy8XZgKDgZDRseAiLpWfLUdix3+d6pL7eh9myPBW2ajdb6tAPzTd9BBKMp/9j+Ajpc5DZVqKuGQPHmBkGQA==", + "license": "SEE LICENSE IN LICENSE.md", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "deprecated": "The work that was done in this beta branch won't be included in future versions", + "license": "BSD-3-Clause", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "license": "MIT" + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/style-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", + "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", + "license": "MIT", + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.27.0" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser": { + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz", + "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==", + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "license": "MIT", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/watchpack": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "license": "BSD-2-Clause" + }, + "node_modules/webpack": { + "version": "5.105.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", + "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.19.0", + "es-module-lexer": "^2.0.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.3.1", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.16", + "watchpack": "^2.5.1", + "webpack-sources": "^3.3.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-sources": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "license": "MIT", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/ws": { + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/remotion/package.json b/remotion/package.json new file mode 100644 index 0000000..ecacb19 --- /dev/null +++ b/remotion/package.json @@ -0,0 +1,22 @@ +{ + "name": "@ado2/higgsfield-remotion", + "version": "0.1.0", + "private": true, + "description": "ADO2 Higgsfield Shorts — Remotion 자막·타이틀 오버레이 합성", + "scripts": { + "studio": "remotion studio", + "render": "remotion render MumumShort out/mumum-poc2-final.mp4", + "upgrade": "remotion upgrade" + }, + "dependencies": { + "@remotion/cli": "4.0.468", + "@remotion/google-fonts": "4.0.468", + "remotion": "4.0.468", + "react": "19.2.0", + "react-dom": "19.2.0" + }, + "devDependencies": { + "@types/react": "19.2.0", + "typescript": "5.7.3" + } +} diff --git a/remotion/public/mumum_marketing_v1.mp4 b/remotion/public/mumum_marketing_v1.mp4 new file mode 100644 index 0000000..04c27f7 Binary files /dev/null and b/remotion/public/mumum_marketing_v1.mp4 differ diff --git a/remotion/remotion.config.ts b/remotion/remotion.config.ts new file mode 100644 index 0000000..a0087e8 --- /dev/null +++ b/remotion/remotion.config.ts @@ -0,0 +1,6 @@ +import { Config } from "@remotion/cli/config"; + +Config.setVideoImageFormat("jpeg"); +Config.setOverwriteOutput(true); +// H.264 + AAC, 모바일 9:16 Shorts/Reels 호환 +Config.setCodec("h264"); diff --git a/remotion/src/MumumShort.tsx b/remotion/src/MumumShort.tsx new file mode 100644 index 0000000..c9484bc --- /dev/null +++ b/remotion/src/MumumShort.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import { AbsoluteFill, OffthreadVideo, Sequence, staticFile } from "remotion"; +import { ShortProps } from "./data/types"; +import { HookTitle } from "./components/HookTitle"; +import { BrandLines } from "./components/BrandLines"; +import { SellingBadge } from "./components/SellingBadge"; +import { EndCard } from "./components/EndCard"; + +// Higgsfield 완성본을 배경으로 깔고(오디오 포함), 자막/타이틀만 오버레이. +// 모든 콘텐츠는 props로 주입 (펜션/제품마다 교체). +export const MumumShort: React.FC = ({ + videoSrc, + hook, + sellingPoint, + brandLines, + endCard, +}) => { + return ( + + + + {/* 상단 후킹 타이틀 */} + + + + + {/* 셀링포인트: 3개 독립 박스 */} + + + {/* 브랜드 감성 2줄 (상단 중앙) */} + + + {/* 엔드카드 + AI 디스클로저 */} + + + ); +}; diff --git a/remotion/src/Root.tsx b/remotion/src/Root.tsx new file mode 100644 index 0000000..85499b5 --- /dev/null +++ b/remotion/src/Root.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import { Composition } from "remotion"; +import { MumumShort } from "./MumumShort"; +import { defaultProps } from "./data/mumum"; + +export const RemotionRoot: React.FC = () => { + return ( + ({ + durationInFrames: props.durationInFrames, + fps: props.fps, + width: props.width, + height: props.height, + })} + /> + ); +}; diff --git a/remotion/src/components/BrandLines.tsx b/remotion/src/components/BrandLines.tsx new file mode 100644 index 0000000..9712e17 --- /dev/null +++ b/remotion/src/components/BrandLines.tsx @@ -0,0 +1,63 @@ +import React from "react"; +import { useCurrentFrame, interpolate, AbsoluteFill } from "remotion"; +import { serifFont } from "../fonts"; + +// 브랜드 감성 2줄: 우상단 통일 위치에 한 덩어리로 쌓아 노출. +// 첫 줄 먼저, 둘째 줄 살짝 뒤따라 등장 → 같은 자리에서 읽힘. +export const BrandLines: React.FC<{ + lines: string[]; + fromFrame: number; + toFrame: number; +}> = ({ lines, fromFrame, toFrame }) => { + const frame = useCurrentFrame(); + const LINE_STAGGER = 18; // 줄 간 등장 간격(frame) + + return ( + + {lines.map((line, i) => { + const start = fromFrame + i * LINE_STAGGER; + // interpolate는 배열이 단조증가해야 한다. + // 영상이 짧아 toFrame 이 start+24 이하로 내려오면 범위가 뒤집혀 크래시 발생. + const fadeIn = start + 12; + const fadeOut = Math.max(fadeIn + 1, toFrame - 12); + const end = Math.max(fadeOut + 1, toFrame); + const opacity = interpolate( + frame, + [start, fadeIn, fadeOut, end], + [0, 1, 1, 0], + { extrapolateLeft: "clamp", extrapolateRight: "clamp" }, + ); + const rise = interpolate(frame, [start, start + 16], [16, 0], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + }); + return ( +
+ {line} +
+ ); + })} +
+ ); +}; diff --git a/remotion/src/components/EndCard.tsx b/remotion/src/components/EndCard.tsx new file mode 100644 index 0000000..f61cd92 --- /dev/null +++ b/remotion/src/components/EndCard.tsx @@ -0,0 +1,91 @@ +import React from "react"; +import { + useCurrentFrame, + useVideoConfig, + interpolate, + spring, + AbsoluteFill, +} from "remotion"; +import { serifFont } from "../fonts"; + +// 엔드카드: 브랜드 + 위치 + AI 디스클로저 (가드레일 필수) +export const EndCard: React.FC<{ + brand: string; + location: string; + disclosure: string; + fromFrame: number; +}> = ({ brand, location, disclosure, fromFrame }) => { + const frame = useCurrentFrame(); + const { fps } = useVideoConfig(); + + const appear = interpolate(frame, [fromFrame, fromFrame + 12], [0, 1], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + }); + const brandSpring = spring({ + frame: frame - fromFrame, + fps, + config: { damping: 200, mass: 0.5 }, + }); + const brandScale = interpolate(brandSpring, [0, 1], [0.92, 1]); + + return ( + +
+
+ {brand} +
+
+ {location} +
+
+
+ {disclosure} +
+
+ ); +}; diff --git a/remotion/src/components/HookTitle.tsx b/remotion/src/components/HookTitle.tsx new file mode 100644 index 0000000..8eba087 --- /dev/null +++ b/remotion/src/components/HookTitle.tsx @@ -0,0 +1,93 @@ +import React from "react"; +import { + useCurrentFrame, + useVideoConfig, + interpolate, + spring, + AbsoluteFill, +} from "remotion"; +import { hookFont } from "../fonts"; + +export const HookTitle: React.FC<{ + eyebrow: string; + title: string; + fromFrame: number; + toFrame: number; +}> = ({ eyebrow, title, fromFrame, toFrame }) => { + const frame = useCurrentFrame(); + const { fps } = useVideoConfig(); + + // 스프링 슬라이드-다운 등장 + const enter = spring({ + frame: frame - fromFrame, + fps, + config: { damping: 200, mass: 0.6 }, + }); + const translateY = interpolate(enter, [0, 1], [-60, 0]); + // 퇴장 페이드 + const fadeIn = fromFrame + 8; + const fadeOut = Math.max(fadeIn + 1, toFrame - 12); + const end = Math.max(fadeOut + 1, toFrame); + const opacity = interpolate( + frame, + [fromFrame, fadeIn, fadeOut, end], + [0, 1, 1, 0], + { extrapolateLeft: "clamp", extrapolateRight: "clamp" }, + ); + + return ( + + {/* 상단 가독성 그라데이션 */} +
+
+
+ {eyebrow} +
+
+ {title} +
+
+ + ); +}; diff --git a/remotion/src/components/SellingBadge.tsx b/remotion/src/components/SellingBadge.tsx new file mode 100644 index 0000000..9b99046 --- /dev/null +++ b/remotion/src/components/SellingBadge.tsx @@ -0,0 +1,72 @@ +import React from "react"; +import { + useCurrentFrame, + useVideoConfig, + interpolate, + spring, + AbsoluteFill, +} from "remotion"; +import { serifFont } from "../fonts"; + +// 셀링포인트: 3개 독립 pill 박스를 세로로 쌓고 순차 등장. +// 컬러 지양 → 반투명 다크 pill + 흰색 텍스트. 앞 구간 단독 노출(시선 집중). +export const SellingBadge: React.FC<{ + items: string[]; + fromFrame: number; + toFrame: number; +}> = ({ items, fromFrame, toFrame }) => { + const frame = useCurrentFrame(); + const { fps } = useVideoConfig(); + const STAGGER = 9; // 박스 간 등장 간격(frame) + + return ( + + {items.map((item, i) => { + const start = fromFrame + i * STAGGER; + const enter = spring({ + frame: frame - start, + fps, + config: { damping: 200, mass: 0.5 }, + }); + const rise = interpolate(enter, [0, 1], [22, 0]); + const fadeIn = start + 8; + const fadeOut = Math.max(fadeIn + 1, toFrame - 10); + const end = Math.max(fadeOut + 1, toFrame); + const appear = interpolate( + frame, + [start, fadeIn, fadeOut, end], + [0, 1, 1, 0], + { extrapolateLeft: "clamp", extrapolateRight: "clamp" }, + ); + return ( +
+ {item} +
+ ); + })} +
+ ); +}; diff --git a/remotion/src/components/Subtitle.tsx b/remotion/src/components/Subtitle.tsx new file mode 100644 index 0000000..aa09d86 --- /dev/null +++ b/remotion/src/components/Subtitle.tsx @@ -0,0 +1,53 @@ +import React from "react"; +import { + useCurrentFrame, + interpolate, + AbsoluteFill, +} from "remotion"; +import { serifFont } from "../fonts"; + +// 브랜드 자막: 페이드 + 미세 상승 (Profile A 모션 프리셋) +export const Subtitle: React.FC<{ + text: string; + fromFrame: number; + toFrame: number; +}> = ({ text, fromFrame, toFrame }) => { + const frame = useCurrentFrame(); + + const opacity = interpolate( + frame, + [fromFrame, fromFrame + 10, toFrame - 10, toFrame], + [0, 1, 1, 0], + { extrapolateLeft: "clamp", extrapolateRight: "clamp" }, + ); + const rise = interpolate(frame, [fromFrame, fromFrame + 18], [18, 0], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + }); + + return ( + +
+ {text} +
+
+ ); +}; diff --git a/remotion/src/data/mumum.ts b/remotion/src/data/mumum.ts new file mode 100644 index 0000000..ad44444 --- /dev/null +++ b/remotion/src/data/mumum.ts @@ -0,0 +1,35 @@ +// Default props = the verified 머뭄 PoC #2 layout. +// The Python render bridge overrides these per-job via --props. +import { ShortProps } from "./types"; + +export const defaultProps: ShortProps = { + videoSrc: "mumum_marketing_v1.mp4", + fps: 30, + width: 720, + height: 1280, + durationInFrames: 241, // ≈ 8.04s + + hook: { + eyebrow: "아무도 모르는 군산", + title: "골목 안, 단 한 채의 독채 스테이 머뭄", + fromFrame: 0, + toFrame: 78, + }, + sellingPoint: { + items: ["프라이빗 독채펜션", "넓은 정원", "핵심 관광지 가까이"], + fromFrame: 80, + toFrame: 138, + }, + brandLines: { + lines: ["머무는 시간이", "다르게 흐르는 곳"], + fromFrame: 138, + toFrame: 196, + }, + endCard: { + brand: "Stay, 머뭄", + location: "전북 군산시 절골길 18", + disclosure: "실제 사진 기반, AI 카메라 효과를 적용한 영상입니다.", + fromFrame: 192, + toFrame: 241, + }, +}; diff --git a/remotion/src/data/types.ts b/remotion/src/data/types.ts new file mode 100644 index 0000000..bcc7c26 --- /dev/null +++ b/remotion/src/data/types.ts @@ -0,0 +1,19 @@ +// Props contract — shared by Remotion composition and the Python render bridge. +// Mirrors server/app/schemas.py VideoSpec (+ video config + timings). +export type ShortProps = { + videoSrc: string; // file in public/ (staticFile name) + fps: number; + width: number; + height: number; + durationInFrames: number; + hook: { eyebrow: string; title: string; fromFrame: number; toFrame: number }; + sellingPoint: { items: string[]; fromFrame: number; toFrame: number }; + brandLines: { lines: string[]; fromFrame: number; toFrame: number }; + endCard: { + brand: string; + location: string; + disclosure: string; + fromFrame: number; + toFrame: number; + }; +}; diff --git a/remotion/src/fonts.ts b/remotion/src/fonts.ts new file mode 100644 index 0000000..383b303 --- /dev/null +++ b/remotion/src/fonts.ts @@ -0,0 +1,21 @@ +// 한글 폰트 로딩 (@remotion/google-fonts, korean subset) +// Hook = Black Han Sans (굵고 강렬한 바이럴 헤드라인) +// Body/Brand = Nanum Myeongjo (우아한 명조 — 머뭄의 정적 브랜드 톤) +// +// 주의: korean subset 자체가 unicode-range 파일이 많아 요청 수가 많다. +// weights 를 최소화(NanumMyeongjo는 400/700만 실제 존재)해 요청 수를 줄임. +// latin 서브셋 제거 — 콘텐츠가 한국어 전용이므로 불필요. +import { loadFont as loadHook } from "@remotion/google-fonts/BlackHanSans"; +import { loadFont as loadSerif } from "@remotion/google-fonts/NanumMyeongjo"; + +export const hookFont = loadHook("normal", { + weights: ["400"], + subsets: ["korean"], + ignoreTooManyRequestsWarning: true, +}).fontFamily; + +export const serifFont = loadSerif("normal", { + weights: ["400", "700"], // 800은 NanumMyeongjo에 없음 → 제거 + subsets: ["korean"], + ignoreTooManyRequestsWarning: true, +}).fontFamily; diff --git a/remotion/src/index.ts b/remotion/src/index.ts new file mode 100644 index 0000000..f31c790 --- /dev/null +++ b/remotion/src/index.ts @@ -0,0 +1,4 @@ +import { registerRoot } from "remotion"; +import { RemotionRoot } from "./Root"; + +registerRoot(RemotionRoot); diff --git a/remotion/tsconfig.json b/remotion/tsconfig.json new file mode 100644 index 0000000..fea0181 --- /dev/null +++ b/remotion/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "Bundler", + "jsx": "react-jsx", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true + }, + "include": ["src"] +} diff --git a/src/App.tsx b/src/App.tsx index 2a5ad82..6b8d7f5 100755 --- a/src/App.tsx +++ b/src/App.tsx @@ -358,32 +358,6 @@ const App: React.FC = () => { } }; - // 테스트 데이터로 브랜드 분석 페이지 이동 - const handleTestData = (data: CrawlingResponse) => { - const tagged = { ...data, _isTestData: true }; - setAnalysisData(tagged); - localStorage.setItem(ANALYSIS_DATA_KEY, JSON.stringify(tagged)); - setViewMode('analysis'); - }; - - // 언어 변경 시 테스트 데이터 다시 로드 - useEffect(() => { - const saved = localStorage.getItem(ANALYSIS_DATA_KEY); - if (!saved) return; - try { - const parsed = JSON.parse(saved); - if (!parsed._isTestData) return; - const jsonFile = i18n.language === 'en' ? '/example_analysis_en.json' : '/example_analysis.json'; - fetch(jsonFile) - .then(res => res.json()) - .then((data: CrawlingResponse) => { - const tagged = { ...data, _isTestData: true }; - setAnalysisData(tagged); - localStorage.setItem(ANALYSIS_DATA_KEY, JSON.stringify(tagged)); - }) - .catch(err => console.error('Failed to reload test data:', err)); - } catch { /* ignore */ } - }, [i18n.language]); const handleToLogin = async () => { // 이미 로그인된 상태면 바로 generation_flow로 이동 @@ -504,12 +478,8 @@ const App: React.FC = () => {
scrollToSection(1)} - error={error} scrollProgress={scrollProgress} />
diff --git a/src/components/SearchInputForm.tsx b/src/components/SearchInputForm.tsx index e616416..f488572 100644 --- a/src/components/SearchInputForm.tsx +++ b/src/components/SearchInputForm.tsx @@ -24,6 +24,7 @@ interface SearchInputFormProps { onManualInput?: (businessName: string, address: string) => void; /** 직접입력 버튼 클릭 시 기본 동작(모달 열기)을 대체합니다. 제공 시 모달을 직접 관리해야 합니다. */ onManualButtonClick?: () => void; + onShortform?: () => void; error?: string | null; } @@ -32,6 +33,7 @@ const SearchInputForm: React.FC = ({ onAutocomplete, onManualInput, onManualButtonClick, + onShortform, error: externalError, }) => { const { t } = useTranslation(); @@ -68,6 +70,7 @@ const SearchInputForm: React.FC = ({ const searchTypeOptions = [ { value: 'url' as SearchType, label: 'URL' }, { value: 'name' as SearchType, label: t('landing.hero.searchTypeBusinessName') }, + { value: 'manual' as SearchType, label: t('landing.hero.searchTypeManual') }, ]; const getPlaceholder = () => @@ -196,8 +199,12 @@ const SearchInputForm: React.FC = ({ type="button" className={`hero-dropdown-item ${searchType === option.value ? 'active' : ''}`} onClick={() => { - setSearchType(option.value); setIsDropdownOpen(false); + if (option.value === 'manual') { + handleManualButtonClick(); + } else { + setSearchType(option.value); + } }} > {option.label} @@ -321,9 +328,19 @@ const SearchInputForm: React.FC = ({ {t('landing.hero.analyzeButton')} - + {onShortform && ( + + )} {/* onManualButtonClick 미제공 시 모달을 내부에서 관리 */} {!onManualButtonClick && isManualModalOpen && ( diff --git a/src/components/SocialPostingModal.tsx b/src/components/SocialPostingModal.tsx index 486f377..5321306 100644 --- a/src/components/SocialPostingModal.tsx +++ b/src/components/SocialPostingModal.tsx @@ -157,6 +157,7 @@ const SocialPostingModal: React.FC = ({ const [uploadVideoTitle, setUploadVideoTitle] = useState(''); const [uploadChannelName, setUploadChannelName] = useState(''); const [uploadIsScheduled, setUploadIsScheduled] = useState(false); + const [uploadScheduledAt, setUploadScheduledAt] = useState(null); // 드롭다운 외부 클릭 시 닫기 useEffect(() => { @@ -373,6 +374,7 @@ const SocialPostingModal: React.FC = ({ // 예약 업로드: 폴링 없이 바로 완료 처리 setUploadStatus('completed'); setUploadProgress(100); + setUploadScheduledAt(uploadResponse.scheduled_at ?? null); onClose(); resetForm(); } else { @@ -432,6 +434,7 @@ const SocialPostingModal: React.FC = ({ setUploadVideoTitle(''); setUploadChannelName(''); setUploadIsScheduled(false); + setUploadScheduledAt(null); }; const handleClose = () => { @@ -461,6 +464,7 @@ const SocialPostingModal: React.FC = ({ youtubeUrl={uploadYoutubeUrl} errorMessage={uploadErrorMessage} isScheduled={uploadIsScheduled} + scheduledAt={uploadScheduledAt} onGoToCalendar={onGoToCalendar} /> ); diff --git a/src/components/Tutorial/tutorialSteps.ts b/src/components/Tutorial/tutorialSteps.ts index 0633fd7..40299b3 100644 --- a/src/components/Tutorial/tutorialSteps.ts +++ b/src/components/Tutorial/tutorialSteps.ts @@ -45,44 +45,7 @@ export const TUTORIAL_PAGE_GROUPS: string[][] = [ export const tutorialSteps: TutorialStepDef[] = [ { key: TUTORIAL_KEYS.LANDING, - hints: [ - { - targetSelector: '.hero-dropdown-trigger', - titleKey: 'tutorial.landing.dropdown.title', - descriptionKey: 'tutorial.landing.dropdown.desc', - position: 'top', - clickToAdvance: false, - noSpotlight: true, - variant: 'bubble', - }, - { - targetSelector: '.hero-input-wrapper', - titleKey: 'tutorial.landing.field.title', - descriptionKey: 'tutorial.landing.field.desc', - position: 'top', - clickToAdvance: false, - noSpotlight: true, - variant: 'bubble', - }, - { - targetSelector: '.hero-manual-button', - titleKey: 'tutorial.landing.manual.title', - descriptionKey: 'tutorial.landing.manual.desc', - position: 'bottom', - clickToAdvance: false, - noSpotlight: true, - variant: 'bubble', - }, - { - targetSelector: '.hero-button', - titleKey: 'tutorial.landing.button.title', - descriptionKey: 'tutorial.landing.button.desc', - position: 'bottom', - clickToAdvance: true, - noSpotlight: true, - variant: 'bubble', - }, - ], + hints: [], }, { key: TUTORIAL_KEYS.ASSET, diff --git a/src/components/UploadProgressModal.tsx b/src/components/UploadProgressModal.tsx index 8572619..8aec55a 100644 --- a/src/components/UploadProgressModal.tsx +++ b/src/components/UploadProgressModal.tsx @@ -14,6 +14,7 @@ interface UploadProgressModalProps { youtubeUrl?: string; errorMessage?: string; isScheduled?: boolean; + scheduledAt?: string | null; onGoToCalendar?: () => void; } @@ -27,6 +28,7 @@ const UploadProgressModal: React.FC = ({ youtubeUrl, errorMessage, isScheduled = false, + scheduledAt, onGoToCalendar, }) => { const { t } = useTranslation(); @@ -148,6 +150,28 @@ const UploadProgressModal: React.FC = ({ {t('upload.viewOnYoutube')} )} + + {/* Scheduled conflict notice */} + {status === 'completed' && isScheduled && scheduledAt && ( +
+ + + + + + + {t('upload.scheduleConflict', { + time: new Date(scheduledAt).toLocaleString('ko-KR', { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: '2-digit', + minute: '2-digit', + }), + })} + +
+ )}
{/* Footer */} diff --git a/src/locales/en.json b/src/locales/en.json index a6393c5..35f4434 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -154,7 +154,8 @@ "confirm": "OK", "close": "Close", "doNotClose": "Upload is in progress. Do not close this window.", - "goToCalendar": "View in Calendar" + "goToCalendar": "View in Calendar", + "scheduleConflict": "Schedule adjusted to {{time}} due to a conflict." }, "landing": { "hero": { diff --git a/src/locales/ko.json b/src/locales/ko.json index 26a79ed..9ce0d77 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -154,7 +154,8 @@ "confirm": "확인", "close": "닫기", "doNotClose": "업로드가 진행 중입니다. 창을 닫지 마세요.", - "goToCalendar": "캘린더에서 확인" + "goToCalendar": "캘린더에서 확인", + "scheduleConflict": "예약 시간이 충돌하여 {{time}}으로 조정되었습니다." }, "landing": { "hero": { diff --git a/src/pages/Dashboard/GenerationFlow.tsx b/src/pages/Dashboard/GenerationFlow.tsx index 2c5dc23..b38f447 100755 --- a/src/pages/Dashboard/GenerationFlow.tsx +++ b/src/pages/Dashboard/GenerationFlow.tsx @@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import Sidebar from '../../components/Sidebar'; +import ShortformContent from './ShortformContent'; import AssetManagementContent from './AssetManagementContent'; import SoundStudioContent from './SoundStudioContent'; import CompletionContent from './CompletionContent'; @@ -54,6 +55,7 @@ interface GenerationFlowProps { initialImageList?: string[]; businessInfo?: BusinessInfo; initialAnalysisData?: CrawlingResponse | null; + initialShortform?: boolean; } // 위저드 단계: @@ -69,7 +71,8 @@ const GenerationFlow: React.FC = ({ initialActiveItem = '대시보드', initialImageList = [], businessInfo, - initialAnalysisData + initialAnalysisData, + initialShortform = false, }) => { const { t, i18n } = useTranslation(); // localStorage에서 저장된 상태 복원 @@ -94,6 +97,9 @@ const GenerationFlow: React.FC = ({ // 초기 위저드 단계 결정 const getInitialWizardStep = (): number => { + // 숏폼 진입 플래그가 있으면 숏폼 화면(-3)으로 바로 + if (initialShortform) return -3; + if (savedWizardStep !== null) { const step = parseInt(savedWizardStep, 10); // 분석 데이터가 있는데 URL 입력(-2) 또는 로딩(-1) 단계로 저장된 경우: @@ -289,37 +295,6 @@ const GenerationFlow: React.FC = ({ }; // 테스트용 랜덤 m_id 생성 (99 ~ 300) - const generateRandomMId = (): number => { - return Math.floor(Math.random() * (300 - 99 + 1)) + 99; - }; - - // 테스트 데이터로 브랜드 분석 페이지 이동 - const handleTestData = (data: CrawlingResponse) => { - const tagged = { ...data, m_id: generateRandomMId(), _isTestData: true }; - setAnalysisData(tagged); - localStorage.setItem(ANALYSIS_DATA_KEY, JSON.stringify(tagged)); - goToWizardStep(0); // 브랜드 분석 결과로 - }; - - // 언어 변경 시 테스트 데이터 다시 로드 - useEffect(() => { - const saved = localStorage.getItem(ANALYSIS_DATA_KEY); - if (!saved) return; - try { - const parsed = JSON.parse(saved); - if (!parsed._isTestData) return; - const jsonFile = i18n.language === 'en' ? '/example_analysis_en.json' : '/example_analysis.json'; - fetch(jsonFile) - .then(res => res.json()) - .then((data: CrawlingResponse) => { - // 언어 변경 시에는 기존 m_id 유지 - const tagged = { ...data, m_id: parsed.m_id || generateRandomMId(), _isTestData: true }; - setAnalysisData(tagged); - localStorage.setItem(ANALYSIS_DATA_KEY, JSON.stringify(tagged)); - }) - .catch(err => console.error('Failed to reload test data:', err)); - } catch { /* ignore */ } - }, [i18n.language]); // URL 분석 시작 const handleStartAnalysis = async (url: string) => { @@ -432,6 +407,13 @@ const GenerationFlow: React.FC = ({ // 새 프로젝트 만들기 - 단계별 컨텐츠 렌더링 const renderWizardContent = () => { switch (wizardStep) { + case -3: + // 숏폼 생성 단계 + return ( + + ); case -2: // URL 입력 단계 return ( @@ -439,7 +421,7 @@ const GenerationFlow: React.FC = ({ onAnalyze={handleStartAnalysis} onAutocomplete={handleAutocomplete} onManualInput={handleManualInput} - onTestData={handleTestData} +onShortform={() => goToWizardStep(-3)} error={analysisError} /> ); @@ -551,8 +533,8 @@ const GenerationFlow: React.FC = ({ case '내 정보': return ; case '새 프로젝트 만들기': - // 브랜드 분석(0)과 로딩(-1)은 전체 화면으로 표시 - if (wizardStep === 0 || wizardStep === -1) { + // 브랜드 분석(0), 로딩(-1), 숏폼(-3)은 전체 화면으로 표시 + if (wizardStep === 0 || wizardStep === -1 || wizardStep === -3) { return renderWizardContent(); } return ( diff --git a/src/pages/Dashboard/ShortformContent.tsx b/src/pages/Dashboard/ShortformContent.tsx new file mode 100644 index 0000000..6d1a39f --- /dev/null +++ b/src/pages/Dashboard/ShortformContent.tsx @@ -0,0 +1,478 @@ +import React, { useRef, useState } from 'react'; +import { uploadImages, generateShortform, waitForShortformComplete, previewShortform } from '../../utils/api'; +import { ShortformStatusResponse, VideoSpec } from '../../types/api'; + +type Kind = 'place' | 'product' | 'message'; +type Step = 1 | 2 | 3 | 4; + +interface ShortformContentProps { + onComplete?: () => void; +} + +const KIND_OPTIONS: { value: Kind; label: string; desc: string }[] = [ + { value: 'place', label: '장소', desc: '펜션·카페·식당·매장 등 공간' }, + { value: 'product', label: '물건', desc: '제품, 음식 등 시각적인 아이템' }, + { value: 'message', label: '메시지', desc: '축하·안부·홍보 등' }, +]; + +const STEP_META = [ + { label: '사진 업로드', sub: '4~5장' }, + { label: '정보 입력', sub: '몇 가지만 답하기' }, + { label: '영상 생성', sub: 'AI 카메라 + 자막' }, + { label: '완성', sub: '다운로드' }, +]; + +const MIN_PHOTOS = 4; +const MIN_PHOTOS_LABEL = `${MIN_PHOTOS}장`; + +const ShortformContent: React.FC = ({ onComplete }) => { + const fileInputRef = useRef(null); + const dropRef = useRef(null); + + // 단계 + const [step, setStep] = useState(1); + + // Step 1 — 사진 + const [files, setFiles] = useState([]); + const [previews, setPreviews] = useState([]); + + // Step 2 — 폼 + const [kind, setKind] = useState('place'); + const [bizName, setBizName] = useState(''); + const [selling, setSelling] = useState(''); + const [addr, setAddr] = useState(''); + const [price, setPrice] = useState(''); + + // Step 3/4 — 생성 상태 + const [statusMsg, setStatusMsg] = useState(''); + const [result, setResult] = useState(null); + const [errorMsg, setErrorMsg] = useState(''); + + // 자막 미리보기 + const [preview, setPreview] = useState(null); + const [previewLoading, setPreviewLoading] = useState(false); + const [previewError, setPreviewError] = useState(''); + + // --- 사진 관리 --- + const addFiles = (newFiles: File[]) => { + const images = newFiles.filter(f => f.type.startsWith('image/')); + if (!images.length) return; + const newUrls = images.map(f => URL.createObjectURL(f)); + setFiles(prev => [...prev, ...images]); + setPreviews(prev => [...prev, ...newUrls]); + }; + + const removeFile = (index: number) => { + URL.revokeObjectURL(previews[index]); + setFiles(prev => prev.filter((_, i) => i !== index)); + setPreviews(prev => prev.filter((_, i) => i !== index)); + }; + + const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); }; + const handleDrop = (e: React.DragEvent) => { + e.preventDefault(); + addFiles(Array.from(e.dataTransfer.files)); + }; + + // --- 미리보기 필드 수정 --- + const patchPreview = (updater: (prev: NonNullable) => NonNullable) => { + setPreview(prev => prev ? updater(prev) : prev); + }; + + // --- 자막 미리보기 --- + const handlePreview = async () => { + if (!selling.trim()) return; + setPreviewLoading(true); + setPreviewError(''); + try { + const spec = await previewShortform({ + kind, + biz_name: bizName.trim(), + selling: selling.trim(), + addr: addr.trim() || undefined, + price: price.trim() || undefined, + }); + setPreview(spec); + } catch (err) { + setPreviewError(err instanceof Error ? err.message : '미리보기 생성에 실패했습니다.'); + } finally { + setPreviewLoading(false); + } + }; + + // --- 다운로드 --- + const [isDownloading, setIsDownloading] = useState(false); + const handleDownload = async (url: string) => { + if (isDownloading) return; + setIsDownloading(true); + try { + const resp = await fetch(url); + const blob = await resp.blob(); + const blobUrl = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = blobUrl; + link.download = `${bizName || 'shortform'}.mp4`; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + URL.revokeObjectURL(blobUrl); + } catch { + const link = document.createElement('a'); + link.href = url; + link.download = `${bizName || 'shortform'}.mp4`; + link.target = '_blank'; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } finally { + setIsDownloading(false); + } + }; + + // --- 생성 실행 --- + const handleGenerate = async () => { + setStep(3); + setErrorMsg(''); + setResult(null); + try { + setStatusMsg('사진 업로드 중...'); + const uploadResp = await uploadImages([], files); + + setStatusMsg('영상 생성 요청 중...'); + await generateShortform({ + task_id: uploadResp.task_id, + kind, + biz_name: bizName.trim(), + addr: addr.trim() || undefined, + price: price.trim() || undefined, + selling: selling.trim(), + spec: preview ?? undefined, + dry_run: true, + }); + + setStatusMsg('AI 카메라 무브·자막 렌더링 중...'); + const statusResp = await waitForShortformComplete(uploadResp.task_id, s => { + setStatusMsg(s === 'processing' ? 'AI 카메라 무브·자막 렌더링 중...' : s); + }); + + setResult(statusResp); + setStep(4); + onComplete?.(); + } catch (err) { + setErrorMsg(err instanceof Error ? err.message : '생성 중 오류가 발생했습니다.'); + setStep(2); + } + }; + + const step1Valid = files.length >= MIN_PHOTOS; + const step2Valid = bizName.trim() && selling.trim(); + + // ===================== 렌더 ===================== + + // 스텝 인디케이터 + const StepBar = () => ( +
+ {STEP_META.map((s, i) => { + const n = (i + 1) as Step; + const done = step > n; + const active = step === n; + return ( +
+
+ {done + ? + : n} +
+
+ {s.label} + {s.sub} +
+
+ ); + })} +
+ ); + + // ---- Step 1: 사진 업로드 ---- + if (step === 1) return ( +
+
+
+

사진 몇 장과 한마디면, 8초 홍보 영상이 됩니다

+

복잡한 분석 없이 — 사진을 올리고 몇 가지만 답하면, AI 카메라 무브와 자막을 입힌 세로형 숏폼이 완성됩니다.

+
+ + + +
+

사진 업로드

+

홍보할 장소나 물건 사진 4~5장. 전경 1장·디테일 2~3장을 섞으면 영상의 서사가 살아납니다.

+ +
fileInputRef.current?.click()} + onDragOver={handleDragOver} + onDrop={handleDrop} + > +
+ +
+

여기로 사진을 끌어다 놓거나 클릭

+

JPG·PNG·{MIN_PHOTOS_LABEL} 이상

+
+ { addFiles(Array.from(e.target.files || [])); e.target.value = ''; }} /> + + {previews.length > 0 && ( +
+ {previews.map((url, i) => ( +
+ {i + 1} + {`사진 + +
+ ))} +
+ )} +
+
+ +
+
+ {files.length}장 + {step1Valid + ? 업로드됨·준비 완료 + : {MIN_PHOTOS - files.length}장 더 추가해주세요} +
+ +
+
+ ); + + // ---- Step 2: 정보 입력 ---- + if (step === 2) return ( +
+
+ + +
+

몇 가지만 알려주세요

+

사장님·마케터가 가장 잘 아는 정보로 카피를 만듭니다.

+ + {/* Kind */} +
+ +
+ {KIND_OPTIONS.map(opt => ( + + ))} +
+
+ + {/* 업체명 */} +
+ + setBizName(e.target.value)} + maxLength={50} + /> +
+ + {/* 셀링포인트 */} +
+ +