PageSourceSearch

https://www.bbanana.ai/assets/ShortsAgentView-38EcyaYy.js

js bbanana.ai collected 2026-10-05 11:53:09 UTC 279,496 bytes, 124 lines download raw bytes

1import{o as dn}from"./rolldown-runtime-ChpBd9eV.js";import{a as ro,o as ao}from"./framer-D6rFZViT.js";import{Cr as un,Er as so,Ji as ve,Ki as no,Kn as mn,S as As,Wn as pn,Yi as pe,Yt as oo,b as io,ea as lo,k as co,mr as st,pr as ds,qr as xe,v as uo,vi as mo,w as Rs,x as Er,y as fr,zn as po}from"./landing-bottom-BIxvSgA_.js";import{t as $s}from"./arrow-right-CPaKH5-d.js";import{t as da}from"./MediaSourcePicker-BMNzdwRi.js";import{t as ho}from"./minimize-2-DkdGXfqP.js";import{t as us}from"./package-B6rnr8j3.js";import{t as fo}from"./pencil-yoyrsiY0.js";import{t as go}from"./refresh-cw-Q4wKUrok.js";import{t as yo}from"./user-round-DfLn3uHn.js";import{I as bo,Jn as hn,Jr as Wr,Kr as Jr,Pi as xo,Qn as je,Qr as Ms,Ri as Gr,Ti as Zr,Vi as vo,Xn as ja,_n as ko,bn as wo,gn as _o,gr as Ve,hr as Io,qn as fn,qr as Fa,si as So,ui as jo,vn as No,xn as Co,yn as Po}from"./index-Cj5sqahA.js";import{n as To}from"./useVideoPlayBudget-CmTUTdkg.js";import{a as Eo,n as Tr}from"./invokeProviderRouter-EMfp98Qx.js";import{t as Ao}from"./creditRounding-B6m0fPdg.js";import{F as Ro}from"./modelPromptLimitStore-B9Wn0w86.js";import{L as $o,N as Mo,P as Ga,S as Uo,b as os,f as Do,i as Va,m as Xr,r as na,v as Oo,x as Lo,y as gn,z as Fo}from"./Seedance2Module-BMRq3jXv.js";import{r as yn}from"./creditCost-DvoVJGm-.js";import{r as Ha,t as za}from"./useProviderPolling-O16yAYEi.js";import{_ as Go,g as Us,i as Vo,m as Ho,o as sr,p as Ds,r as zo,s as qo,t as bn,u as Bo,x as Ko,y as Wo}from"./marketing-studio-DSrGrSys.js";import{a as Jo,i as Yo,n as Xo,r as Qo}from"./seedance2ModelSelect-BLbJ4NN-.js";/* empty css              */import{o as Zo,r as ei}from"./sanitizeErrorMessage-B8sLtBHk.js";import{n as xn}from"./BbananaCreditContext-DVHuDxCt.js";import{t as ti}from"./CreditInsufficientModal-BRlgi437.js";import{o as ri}from"./fashionFilmTutorialFixture-CQMvMl-d.js";import{t as ai}from"./pollingConfig-B6Jhza1P.js";import{t as si}from"./useBbananaTaskPolling-Drr3H_mU.js";import{n as ni,r as oi,t as Fr}from"./absoluteAssetUrl-DOTg39dG.js";import{r as Os}from"./ensureRealPhotoAssets-pbYFLeLN.js";import{t as Ls}from"./dist-D3WKI0zm.js";import{a as Fs,c as ii,o as Gs,s as qa}from"./settings-DfRBgoyn.js";import{t as li}from"./DirectorOrb-BpOAbBik.js";import{i as ci,n as Vs,r as di,t as Hs}from"./AgentChat-46xPZkKx.js";import{a as ui,i as mi,n as Ba,o as pi,r as zs}from"./shortsHeroCleanFrame-B8T4XF95.js";import{t as ms}from"./MentionInput-D2DoYwJb.js";import{i as hi,n as fi,o as gi,s as yi,t as bi}from"./select-BKfCmozG.js";import{n as qs,r as xi}from"./studioFreeGrant-DpDesLc9.js";import{t as vi}from"./seedance2Credit-TsDH99Ls.js";import{n as ki,t as va}from"./templateOmniMedia-B6ZQQs-Q.js";import{a as oa,i as Ka,n as wi,r as Bs,t as Yr}from"./shortsAgentTutorialFixture-DBt9ENLB.js";var _i=ds("CupSoda",[["path",{d:"m6 8 1.75 12.28a2 2 0 0 0 2 1.72h4.54a2 2 0 0 0 2-1.72L18 8",key:"8166m8"}],["path",{d:"M5 8h14",key:"pcz4l3"}],["path",{d:"M7 15a6.47 6.47 0 0 1 5 0 6.47 6.47 0 0 0 5 0",key:"yjz344"}],["path",{d:"m12 8 1-6h2",key:"3ybfa4"}]]),vn=ds("Mountain",[["path",{d:"m8 3 4 8 5-5 5 15H2L8 3z",key:"otkl63"}]]),Ii=ds("PawPrint",[["circle",{cx:"11",cy:"4",r:"2",key:"vol9p0"}],["circle",{cx:"18",cy:"8",r:"2",key:"17gozi"}],["circle",{cx:"20",cy:"16",r:"2",key:"1v9bxh"}],["path",{d:"M9 10a5 5 0 0 1 5 5v3.5a3.5 3.5 0 0 1-6.84 1.045Q6.52 17.48 4.46 16.84A3.5 3.5 0 0 1 5.5 10Z",key:"1ydw1z"}]]),s=dn(ao(),1);var kn=t=>!0,Si=(t,r)=>kn(r)?"2.5":"2.0",ji=(t,r)=>t==="2.5"?Xo:Jo(r),wn=(t,r)=>t==="2.5"?["480p","720p","1080p"]:r>15?["720p"]:["720p","1080p"],Ks=(t,r,n)=>t==="2.5"?n==="4k"?"720p":n:r>15&&n!=="480p"?"720p":n,Ws=(t,r,n)=>t==="2.5"||r>15?n.seedance25:n.seedance2,Lr=t=>t==="2.5"?{seedanceEngine:"2.5"}:{},Ni=(t,r,n)=>t!==null?t!==r:r!=="2.5"?!1:!/\b\d+-\d+ seconds:/.test(n||""),Ci=["Seedance 2.5","Seedance 2.0","Seedance 2"],Ia=dn(lo(),1),e=ro(),Wa=`${no}/functions/v1`,Js=3,ia=1,ot="shorts",ka="Preserve authentic product packaging text and label typography. Do not add unrelated overlay captions, subtitles, or watermarks.",Pi=`TEXT RENDERING POLICY — mandatory (ABSOLUTE NO ON-SCREEN TEXT rule).
2
3PRESERVE (render accurately, DO NOT blur, DO NOT erase, DO NOT replace with placeholder shapes): authentic product packaging text, brand marks, label typography, printed logos, ingredient lists, barcodes, serial numbers, regulatory marks, and any typography that is physically printed, embossed, etched, screen-printed, or stickered on the actual product body as visible in the hero reference image. These ARE part of the product identity and MUST be rendered faithfully.
4
5FORBIDDEN (never render, under no circumstances): burned-in subtitles, lower-third captions, closed captions, karaoke lyrics, bottom-aligned text, title cards, chapter titles, credits, date/time stamps, watermarks, UI overlays, caption bars, floating words, typed-out narration, speech-bubbles, or any typography added by the video model that is NOT physically present on the product in the reference image.
6
7AUDIO-ONLY: all narration, dialogue, and VO are spoken on the audio track — never transcribed or rendered as on-screen text.
8
9DECISION RULE for the model: "Is this text visible on the physical product in the reference image?" — if YES, preserve it faithfully. If NO (it would have to be invented, transcribed from speech, or added as a caption/overlay), do not render it.
10
11This policy is non-negotiable.`,_n=t=>t?t.replace(/\bno\s*text\s*,?\s*no\s*watermarks?\b/gi,ka).replace(/\bno\s*text\b/gi,"Preserve authentic product packaging text and label typography").replace(/\bnever\s+include(?:\s+any)?\s+text(?:\/typography)?[^.]*\./gi,`${ka}.`).replace(/\bdo\s+not\s+include(?:\s+any)?\s+text(?:\/typography)?[^.]*\./gi,`${ka}.`).replace(/\bdo\s+not\s+render(?:\s+any)?\s+text[^.]*\./gi,`${ka}.`).replace(/\s{2,}/g," ").replace(/\s+([,.;:!?])/g,"$1").trim():"",In=t=>t?t.includes("ABSOLUTE NO ON-SCREEN TEXT")||t.includes("화면 텍스트 정책")||t.includes("SEEDANCE 2.5 TEXT RENDERING POLICY")?t:`${t.trimEnd()}
12
13${Pi}`.trim():"",Ys=t=>({...t,finalPrompt:t.finalPrompt?In(_n(t.finalPrompt)):""}),jt=t=>{if(!t)return null;if(typeof t=="string"){const r=t.trim();if(r.startsWith("http"))return r;if(r.startsWith("[")&&r.endsWith("]")||r.startsWith("{")&&r.endsWith("}"))try{return jt(JSON.parse(r))}catch{return r}return r}if(Array.isArray(t)){for(const r of t){if(typeof r=="string"&&r.startsWith("http"))return r;const n=jt(r);if(n)return n}return null}if(typeof t=="object"){const r=t;return jt(r.url)||jt(r.resultUrl)||jt(r.result_url)||jt(r.videoUrl)||jt(r.video_url)||jt(r.imageUrl)||jt(r.image_url)||jt(r.editedImageUrl)||jt(r.output)||jt(r.images)||jt(r.allResultUrls)||jt(r.resultUrls)||jt(r.data)||null}return null},ar=t=>typeof t=="string"&&t.startsWith("http")?t.trim():Array.isArray(t)&&t.length>0&&typeof t[0]=="string"&&t[0].startsWith("http")?t[0].trim():jt(t),J=(t,r,n)=>({id:`${t}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,role:t,content:r,suggestions:n?.suggestions?.filter(Boolean),moodPresets:n?.moodPresets,imageUrl:n?.imageUrl,videoUrl:n?.videoUrl,sourceTaskId:n?.sourceTaskId,showStoryboard:n?.showStoryboard,...n?.storyboardFollowUp?{storyboardFollowUp:!0}:{},timestamp:Date.now()}),Xs=t=>t==="ko"?`특정 부분만 콕 집어 ê³ ì¹  수도 있고, 완전히 다른 컨셉을 주시면 거기에 맞ê²
13Œ 스토리보드를 새로 짜 드려요 ✍️
14마음에 드시면 아래에서 바로 영상을 만들면 돼요.
15혹시 바꾸고 싶은 부분이 있을까요?`:t==="ja"?`一部だけピンポイントで直すことも、まったく別のコンセプトに合わせて書き直すこともできますよ ✍️
16気に入ったら下からすぐ動画を作れます。
17変えたいところはありますか?`:`I can tweak just one part, or rewrite the whole storyboard for a completely different concept ✍️
18If you like it, you can make the video right below.
19Anything you want to change?`,pr=[{id:"hold_explain",label:"들고 설명",emoji:"🤳",description:'예쁜 모델이 제품을 들고 카메라에 직접 설명 — 첫 마디가 "대박!" 같은 후킹 한마디로 시작하는 클래식 쇼츠'},{id:"pov_review",label:"POV 리뷰",emoji:"🎥",description:"진짜 인플루언서 쇼츠 문법 — 앞 2초 얼굴+제품 후킹 → 가운데는 통째로 1인칭 POV 사용 장면에 더빙만 → 마지막 2초 같은 자리에서 얼굴로 마무리 (30초 권장, 15초부터)"},{id:"ugc",label:"UGC 극한",emoji:"🪂",description:"스카이다이빙·수중·우주·화재 같은 극한 환경에서 화자가 침착하게 제품 설명 — 환경의 위험 vs 차분함의 갭이 후크"},{id:"drama",label:"K-드라마 PPL",emoji:"💌",description:'막장/로맨스 드라마처럼 진행되다가 뜬금없이 배우들이 멈추고 카메라 보며 제품 들이밀고 추천하는 "갑자기 광고" 트로프'},{id:"fooh",label:"FOOH (도심 합성)",emoji:"🏙️",description:"거대 제품이 도시와 상호작용하는 특이하고 감각적인 가짜 OOH 스펙터클 — 녹아내리고 개화하고 수면 위를 떠다니는 합성 룩"},{id:"cgi",label:"CGI 3D 제품",emoji:"🎬",description:"풀 3D 렌더 — 액체 스플래시·분해·원료 휘감기·360 회전 등 sim FX가 제품 주변에서 터지는 프리미엄 히어로샷"},{id:"vfx",label:"VFX 후킹",emoji:"✨",description:'만화경·글리치·입자·차원문 등 추상 비주얼 트릭 — 시청자가 "어떻게 찍은거지?" 싶은 효과 중심'}],hr=[{id:"hold_explain",label:"Hold & Explain",emoji:"🤳",description:"A beautiful model holds the product up and explains it to camera — opening with a Korean hook one-liner, the classic shorts format"},{id:"pov_review",label:"POV Review",emoji:"🎥",description:"How real influencer shorts are cut — 2s of face + product hook, then the whole middle in first-person POV with voice-over only, back to the same frame for a 2s sign-off (best at 30s, 15s floor)"},{id:"ugc",label:"UGC Extreme",emoji:"🪂",description:"A presenter calmly explains the product in an extreme setting — skydiving, underwater, space, fire — the danger-vs-calm gap is the hook"},{id:"drama",label:"K-Drama PPL",emoji:"💌",description:'Plays like a makjang/romance K-drama then suddenly the actors freeze, turn to camera and pitch the product — the "sudden ad" trope'},{id:"fooh",label:"FOOH (Fake OOH)",emoji:"🏙️",description:"A giant product interacts with a real city in a unique, sensory spectacle — melting, blooming, floating on water — faked out-of-home composite look"},{id:"cgi",label:"CGI 3D Product",emoji:"🎬",description:"Full 3D render — liquid splash, exploded view, ingredient swirl, 360 rotate sim-FX erupting around the product, premium hero shot"},{id:"vfx",label:"VFX Hook",emoji:"✨",description:'Kaleidoscope, glitch, particles, portals — abstract visual tricks that make viewers go "how did they shoot that?"'}],Ti={hold_explain:{emoji:"🤳",labelKo:"들고 설명",labelEn:"Hold & Explain"},pov_review:{emoji:"🎥",labelKo:"POV 리뷰",labelEn:"POV Review"},ugc:{emoji:"🪂",labelKo:"UGC 극한",labelEn:"UGC Extreme"},fooh:{emoji:"🏙️",labelKo:"FOOH 도심 합성",labelEn:"FOOH City"},cgi:{emoji:"🎬",labelKo:"CGI 3D 제품",labelEn:"CGI 3D Product"},vfx:{emoji:"✨",labelKo:"VFX 후킹",labelEn:"VFX Hook"},drama:{emoji:"💌",labelKo:"K-드라마 PPL",labelEn:"K-Drama PPL"},motion_graphic:{emoji:"🎨",labelKo:"모션그래픽",labelEn:"Motion Graphics"},free_concept:{emoji:"✨",labelKo:"AI 자동 컨셉",labelEn:"AI Auto Concept"}},is="bbanana-shorts-agent-session",Ei="bbanana-shorts-agent-session-input",Na="shorts-agent-session:",ps="mcp_",hs=t=>t.startsWith(ps),ea=t=>`bbanana-shorts-agent-session:${t}`,fs=t=>`bbanana-shorts-agent-session-input:${t}`,Ca=t=>`${Na}${t}`,Sn=(t,r)=>({...r,sessionPresetId:t.sessionId,savedAt:Date.now()}),jn=(t,r)=>
19({sessionInput:t,state:r}),Nn=t=>{switch(t){case"hero":return 15;case"mood_select":return 35;case"drafting":return 50;case"discussion":return 70;case"generating":return 90;case"result":return 100;case"error":return 60;default:return 0}},Ai=(t,r)=>{if(!r)return null;const n=r.clientTaskId,l=r.apiTaskId;return t.find(p=>{const h=p.generationOptions||{},o=h.client_task_id||h.clientTaskId,S=h.api_task_id||h.apiTaskId;return p.id===n||p.id===l||p.apiTaskId===n||p.apiTaskId===l||o===n||o===l||S===l||S===n})||null};async function Cn(t){if(t.state.phase==="result"&&t.state.finalVideoUrl){const r=t.state.finalVideoUrl;if(!(r.includes("supabase.co/storage/")||r.includes("supabase.in/storage/"))&&t.state.activeGeneration?.apiTaskId)try{const n=t.state.activeGeneration.apiTaskId,{data:l}=await ve.from("user_tasks").select("result_url").eq("task_id",n).maybeSingle(),p=ar(l?.result_url);if(p&&p!==r)return{...t,state:{...t.state,finalVideoUrl:p,savedAt:Date.now()}}}catch{}return t}if(t.state.phase!=="generating"||!t.state.activeGeneration?.apiTaskId)return t;try{const{data:r,error:n}=await ve.from("user_tasks").select("status, result_url").eq("task_id",t.state.activeGeneration.apiTaskId).maybeSingle();if(n||!r)return t;const l=ar(r.result_url)||t.state.finalVideoUrl;return l?{...t,state:{...t.state,phase:"result",finalVideoUrl:l,activeGeneration:null,savedAt:Date.now()}}:t}catch{return t}}async function gs(t,r,n){if(ja()||hs(r))return;const l=Ca(r),p=new Date().toISOString(),h=n.state.draft?.title||n.sessionInput.highlights?.trim()||n.sessionInput.preset.name,o=n.state.phase==="result"||!!n.state.finalVideoUrl,S={task_id:l,user_id:t,status:n.state.phase==="error"?"failed":o?"completed":"processing",progress:o?100:Nn(n.state.phase),prompt:h,model:"AD Video Agent",service_name:"ad",preset_name:n.sessionInput.preset.name,error_message:n.state.phase==="error"?"AD video agent session paused with an error.":null,terminal_reason:n.state.phase==="error"?"agent_session_error":null,terminated_at:n.state.phase==="error"?p:null,result_url:n.state.finalVideoUrl||null,generation_options:{provider:"internal",mode:"video",task_type:"ad",preset_name:n.sessionInput.preset.name,client_task_id:l,ad_workflow:"video_agent_session",shorts_agent_session:n},updated_at:p,created_at:p};await Eo();let{error:v}=await ve.from("user_tasks").upsert(S,{onConflict:"task_id"});v&&(await ve.auth.refreshSession()).data.session?.access_token&&({error:v}=await ve.from("user_tasks").upsert(S,{onConflict:"task_id"})),v&&pe.error("[useShortsVideoAgent] Failed to sync session task after retry:",v)}async function Ri(t,r,n){if(ja())return;const l=n||Ca(r);l.startsWith(`${Na}${ps}`)||await ve.from("user_tasks").delete().eq("user_id",t).eq("task_id",l)}async function $i(t,r){if(hs(r))return null;const n=Ca(r),{data:l,error:p}=await ve.from("user_tasks").select("generation_options").eq("user_id",t).eq("task_id",n).maybeSingle();if(p||!l)return null;const h=l?.generation_options?.shorts_agent_session;return!h?.state||!h?.sessionInput?null:h}var Pn=t=>Sn(t,{phase:"hero",messages:[],draft:null,heroImageUrl:t.presetHeroImageUrl||null,sourceProductImageUrls:(t.productImages||[]).filter(r=>typeof r=="string"&&!!r),sourceFaceImageUrl:t.faceImage||void 0,selectedMood:null,dynamicMoods:null,finalVideoUrl:null,activeGeneration:null,brandPronunciation:null,brandPronunciationSkipped:!1,productFingerprint:null,interactionCount:0});function Ja(t){const r=Pn(t);return{sessionId:t.sessionId,taskId:Ca(t.sessionId),sessionInput:t,phase:r.phase,heroImageUrl:r.heroImageUrl,finalVideoUrl:r.finalVideoUrl,draftTitle:null,presetName:t.preset?.name||"",error:null,savedAt:r.savedAt,progress:Nn(r.phase)}}async function Ya(t,r){if(!t)return;const n=Pn(r);await gs(t,r.sessionId,jn(r,n))}async function Qs(t){if(!t)return[];try{const{data:r,error:n}=await ve.from("user_tasks").select("task_id, generation_options, error_message, progress").eq("user_id",t).like("task_id",`${Na}%`).not("task_id","like",`${Na}${ps}%`).in("status",["processing","failed"]).order("created_at",{ascending:!1}).limit(50);if(n||!r)return[];const l=[];for(const p of r){const h=p?.generation_options?.shorts_agent_session;!h?.state||!h?.sessionInput||hs(h.sessionInput.sessionId)||h?.orchestrator?.mcp_managed||l.push({sessionId:h.sessionInput.sessionId,taskId:p.task_id,sessionInput
19:h.sessionInput,phase:h.state.phase,heroImageUrl:h.state.heroImageUrl,finalVideoUrl:h.state.finalVideoUrl,draftTitle:h.state.draft?.title||null,presetName:h.sessionInput.preset?.name||"",error:p.error_message||null,savedAt:h.state.savedAt||0,progress:p.progress||0})}return l}catch{return[]}}function Mi(t,r,n){if(!t)return;const l=Sn(t,r);try{localStorage.setItem(ea(t.sessionId),JSON.stringify(l))}catch{}if(n){const p=jn(t,l);gs(n,t.sessionId,p)}}function Ui(t){try{const r=t?ea(t):is,n=localStorage.getItem(r);if(!n){if(t){const l=localStorage.getItem(is);if(l){const p=JSON.parse(l);if(p.sessionPresetId===t)return p}}return null}return JSON.parse(n)}catch{return null}}function Zs(t,r,n){if(r){try{localStorage.removeItem(ea(r))}catch{}try{localStorage.removeItem(fs(r))}catch{}try{localStorage.removeItem(`shorts-agent-input:${r}`)}catch{}}try{localStorage.removeItem(is)}catch{}try{localStorage.removeItem(Ei)}catch{}t&&r&&Ri(t,r,n)}async function Di(t,r){if(!t||!r)return null;try{const n=await $i(t,r);if(!n?.state||!n?.sessionInput)return null;const l=await Cn(n);let p=l;try{const h=localStorage.getItem(ea(r));if(h){const o=JSON.parse(h);(o?.savedAt||0)>(l.state.savedAt||0)&&o.sessionPresetId===r&&o.phase!=="idle"&&l.state.phase!=="result"&&(p={sessionInput:l.sessionInput,state:o})}}catch{}return localStorage.setItem(fs(r),JSON.stringify(p.sessionInput)),localStorage.setItem(ea(r),JSON.stringify(p.state)),p}catch{return null}}async function Oi(t){if(!t)return!1;try{const{data:r}=await ve.from("user_preferences").select("ad_video_agent_state").eq("user_id",t).maybeSingle(),n=r?.ad_video_agent_state;if(n?.state&&n?.sessionInput){const l=await Cn(n),p=l.sessionInput.sessionId;return localStorage.setItem(fs(p),JSON.stringify(l.sessionInput)),localStorage.setItem(ea(p),JSON.stringify(l.state)),await ve.from("user_preferences").update({ad_video_agent_state:null}).eq("user_id",t),gs(t,p,l),!0}}catch{}return!1}function Li({open:t,session:r,language:n,pollingHistory:l,generationTasks:p,createRepresentativeImage:h,uploadImages:o,startSeedanceGeneration:S,onTaskComplete:v,onSessionCompleted:U,demoFixture:D,userId:I}){const f=(i,m,g)=>n==="ko"?i:n==="ja"?m:g,H=()=>f(`영상이 완성됐어요 🎉
20아래에서 확인해 보세요.`,`動画ができました 🎉
21下でチェックしてみてください。`,`Your video is ready 🎉
22Check it out below.`),ee=()=>f(`분위기를 골라 주시면 바로 스토리보드를 짜 볼게요 ✍️
23어떤 분위기로 만들어 볼까요?`,`雰囲気を選んでもらえたら、すぐストーリーボードを作りますね ✍️
24どんな雰囲気で作りましょうか?`,`Pick a mood and I'll write the storyboard right away ✍️
25Which mood shall we go with?`),Ee=()=>f(`이미지에 어울리는 분위기를 찾고 있어요 👀
26잠깐만 기다려 주세요!`,`画像に合う雰囲気を探しています 👀
27少し待っててくださいね!`,`Looking for moods that fit the image 👀
28Just a moment!`),[N,F]=(0,s.useState)("idle"),[se,_]=(0,s.useState)([]),[B,ie]=(0,s.useState)(null),[K,x]=(0,s.useState)(null),[te,ue]=(0,s.useState)([]),[R,$]=(0,s.useState)(void 0),[O,G]=(0,s.useState)(null),[Oe,fe]=(0,s.useState)(null),[_e,Ne]=(0,s.useState)(!1),[P,Ce]=(0,s.useState)(!1),[Re,We]=(0,s.useState)(null),[Ie,q]=(0,s.useState)(!1),[V,X]=(0,s.useState)(!1),ge=(0,s.useRef)(null),[Qe,ht]=(0,s.useState)(""),[$t,ft]=(0,s.useState)(0),[W,Le]=(0,s.useState)(null),[kt,De]=(0,s.useState)(null),[yt,rt]=(0,s.useState)(null),[A,ye]=(0,s.useState)(null),[Ze,Lt]=(0,s.useState)(null),[ut,at]=(0,s.useState)(null),[qt,re]=(0,s.useState)(!1),[Me,ce]=(0,s.useState)(null),[gt,Ae]=(0,s.useState)(0),[bt,Ue]=(0,s.useState)(null),Nt=(0,s.useRef)(null),{checkCredit:Mt,deductCredit:wt,showCreditRequiredModal:nr}=xn(),Bt=(0,s.useRef)(!1),Je=(0,s.useRef)(!1),me=(0,s.useRef)(0),Fe=(0,s.useRef)(N);Fe.current=N;const Qt=(0,s.useRef)(_e);Qt.current=_e;const vr=(0,s.useRef)(r);vr.current=r;const et=(0,s.useCallback)(async i=>{const m=D?.respond(i);return m?(await new Promise(g=>{setTimeout(g,m.delayMs)}),m.data):null},[D]),xt=(0,s.useCallback)(async i=>{const m=await et(i.body?.action);return m?{data:m,error:null}:ve.functions.invoke("shorts-video-agent",i)},[et]),kr=(0,s.useMemo)(()=>A||(n==="en"?hr:pr),[A,n]),mt=(0,s.useMemo)(()=>{const i=Ai(p,W);return i?{progress:Math.min(Math.round(i.progress),100),status:i.status,error:i.error||i.errorMessage,message:i.message,resultUrl:ar(i.resultUrl||i.imageUrl)}:null},[W,p]),gr=(0,s.useMemo)(()=>n==="en"?["Make the overall tone more emotional","Make the product stand out more","Make the first 3 seconds more impactful","Give the ending more resonance"]:["전체적으로 더 감성적인 톤으로 바꿔줘","제품이 더 부각되게 수정해줘","첫 3초를 더 임팩트 있게 바꿔줘","엔딩을 더 여운이 남게 바꿔줘"],[n]),Ye=(0,s.useCallback)((i,m)=>{if(!i||Je.current)return;if(Fe.current!=="generating"){pe.log("[shorts-agent] Stale completion ignored — phase is",Fe.current);return}Je.current=!0;const g=W?.clientTaskId;g&&v&&v(g,i),G(i),De(null),Le(null),fe(null),F("result"),_(b=>[...b,J("agent",m,{videoUrl:i,sourceTaskId:g||void 0})]),r?.sessionId&&U&&U(r.sessionId,i)},[W?.clientTaskId,v,U,r?.sessionId]),_t=(0,s.useCallback)(i=>{fe(i),De(null),Le(null),F("discussion");const m=ei(i),g=!m&&/InputImageSensitiveContentDetected|PolicyViolation|sensitive.?content|content.?policy|copyright.?restrictions|안전\s*정책|콘텐츠\s*정책|콘텐츠\s*검열|검열|(?:차단|거부)되었습니다|유해\s*콘텐츠|부적절/i.test(i),b=Zo(i,n)||f("영상 생성에 실패했습니다.","動画生成に失敗しました。","Video generation failed."),C=m?b:g?f(["🚫 콘텐츠 검열로 생성이 차단되었습니다.","","업스트림 AI 모델의 안전 정책상 아래 중 하나가 감지되면 자동으로 거부됩니다:","• 👶 미성년자·아기","• 🌟 유명인·초상권 대상 인물","• 🏷️ 브랜드 로고·캐릭터·저작물","• ⚠️ 성적/폭력적·민감 이미지","","💡 해결 방법","• 제품 이미지에서 위 요소가 보이면 다른 각도·컷으로 교체","• 얼굴 참조 이미지를 제거하거나 성인 일반인 사진으로 교체","• 배경에 인물/로고가 보이면 크롭해서 다시 업로드","","수정 후 다시 시도해 주세요. 생성 실패분은 크레딧이 자동 환불됩니다."].join(`
29`),["🚫 コンテンツポリシーにより生成がブロックされました。","","上流AIモデルの安全ポリシーにより、以下のいずれかが検出されると自動拒否されます:","• 👶 未成年者・赤ちゃん","• 🌟 有名人・肖像権対象者","• 🏷️ ブランドロゴ・キャラクター・著作物","• ⚠️ 性的・暴力的・センシティブな画像","","💡 解決方法","• 製品画像に上記要素が含まれていれば別のアングル・カットに変更","• 顔参照画像を削除するか一般成人の写真に交換","• 背景に人物・ロゴが見える場合はクロップして再アップロード","","修正後に再試行してください。生成失敗分はクレジットが自動返金されます。"].join(`
30`),["🚫 Generation blocked by content policy.","","The upstream AI model auto-rejects requests when it detects any of:","• 👶 Minors / infants","• 🌟 Celebrities / identifiable public figures","• 🏷️ Brand logos, characters, or copyrighted material","• ⚠️ Sexual / violent / sensitive imagery","","💡 How to fix","• Replace the product image if it contains any of the above","• Remove or swap the face-reference image for a generic adult","• Crop out background peo
30ple/logos and re-upload","","Please revise and retry. Credits for failed generations are auto-refunded."].join(`
31`)):f(`${b}
32스토리보드를 수정하거나 다시 시도해 주세요.`,`${b}
33ストーリーボードを修正するか再試行してください。`,`${b}
34Please revise the storyboard or try again.`);_(T=>[...T,J("system",C)])},[n]),wr=(0,s.useCallback)(async()=>{const i=W?.apiTaskId,m=W?.clientTaskId,g=!!(i||m);if(me.current+=1,Ne(!1),Le(null),De(null),F("discussion"),fe(null),_(b=>[...b,J("system",g?f("🛑 영상 생성을 취소했습니다. 환불은 진행되지 않습니다. 스토리보드를 수정하거나 다시 생성해 주세요.","🛑 動画生成をキャンセルしました。返金は行われません。ストーリーボードを修正するか再生成してください。","🛑 Video generation cancelled. Credits are not refunded. Edit the storyboard or generate again."):f("🛑 영상 생성을 취소했습니다. 진행 중이던 작업이 없어 차감된 크레딧도 없습니다. 스토리보드를 수정하거나 다시 생성해 주세요.","🛑 動画生成をキャンセルしました。進行中の作業がなかったため、差し引かれたクレジットもありません。ストーリーボードを修正するか再生成してください。","🛑 Video generation cancelled. No job was actually running, so no credits were charged. Edit the storyboard or generate again."))]),!g)return{ok:!0};try{const{data:{session:b}}=await ve.auth.getSession(),C=b?.access_token;if(!C)return{ok:!1,error:"not_authenticated"};const T=[i,m].filter(y=>typeof y=="string"&&y.length>0),E=await fetch(`${Wa}/cancel-task`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${C}`},body:JSON.stringify({task_ids:T})}),z=await E.json().catch(()=>({}));return!E.ok||!z?.success?{ok:!1,error:z?.error||`http_${E.status}`}:{ok:!0}}catch(b){return{ok:!1,error:b?.message??"unknown"}}},[W?.apiTaskId,W?.clientTaskId,n]),Vr=(0,s.useCallback)(()=>{me.current+=1,F("idle"),_([]),ie(null),Zt.current=null,x(null),ue([]),$(void 0),G(null),fe(null),Ne(!1),ht(""),ft(0),Le(null),De(null),rt(null),ye(null),at(null),re(!1),ce(null),Ae(0),X(!1),We(null),Ce(!1),Ue(null),Nt.current=null,Bt.current=!1,Je.current=!1,pt.current=!1},[]);(0,s.useEffect)(()=>{if(!t||!r)return;const i=r.sessionId;if(Nt.current===i)return;me.current+=1,Bt.current=!1,Je.current=!1,pt.current=!1,X(!1);const m=Ui(i);if(!m||m.sessionPresetId!==i){F("idle"),_([]),ie(null),Zt.current=null,x(null),ue([]),$(void 0),G(null),fe(null),Ne(!1),ht(""),ft(0),Le(null),De(null),rt(null),ye(null),at(null),re(!1),ce(null),Ae(0),Ue(i),Nt.current=i;return}pe.log("[shorts-video-agent] Restoring session from localStorage, phase:",m.phase);let g=m.phase,b=null,C=!1;if(g==="drafting"?(g="mood_select",m.selectedMood=null,b=f("스토리보드 생성이 중단되었습니다. 분위기를 다시 선택해 주세요.","ストーリーボード生成が中断されました。雰囲気を再度選択してください。","Storyboard generation was interrupted. Please pick a mood again."),pe.log('[shorts-video-agent] Rolled back "drafting" → "mood_select" (API call cannot resume, selectedMood cleared)')):g==="hero"&&(m.heroImageUrl?(g="mood_select",m.dynamicMoods&&m.dynamicMoods.length?(b=f("분위기 분석이 중단되었습니다. 분위기 중 하나를 선택하거나 이미지를 재생성해 주세요.","雰囲気分析が中断されました。雰囲気を選択するか画像を再生成してください。","Mood analysis was interrupted. Please select a mood or regenerate the image."),pe.log('[shorts-video-agent] Rolled back "hero" → "mood_select" (hero image exists)')):(C=!0,pe.log('[shorts-video-agent] Rolled back "hero" → "mood_select" (hero exists, re-running mood analysis)'))):(g="idle",m.messages=[],m.heroImageUrl=null,m.dynamicMoods=null,m.selectedMood=null,pe.log('[shorts-video-agent] Rolled back "hero" → "idle" (will auto-restart)'))),b&&(m.messages=[...m.messages||[],J("system",b)]),Bt.current=g!=="idle",F(g),_(m.messages||[]),ie(m.draft),x(m.heroImageUrl),ue(m.sourceProductImageUrls||[]),$(m.sourceFaceImageUrl),rt(m.selectedMood),ye(m.dynamicMoods),G(m.finalVideoUrl),Le(m.activeGeneration),fe(null),Ne(!1),ht(""),ft(0),m.brandPronunciation!==void 0?at(m.brandPronunciation):at(null),m.brandPronunciationSkipped!==void 0?re(m.brandPronunciationSkipped):re(!1),m.productFingerprint!==void 0?ce(m.productFingerprint):ce(null),typeof m.interactionCount=="number"?Ae(m.interactionCount):Ae(0),De(null),Ue(i),Nt.current=i,C&&m.heroImageUrl&&r){const T=m.heroImageUrl;Ir(T,r).catch(E=>{})}if(g==="generating"&&m.activeGeneration?.apiTaskId){const T=m.activeGeneration.apiTaskId,E=m.activeGeneration.clientTaskId,z=i;(async()=>{try{const{data:y}=await ve.from("user_tasks").select("status, result_url").eq("task_id",T).eq("user_id",I).maybeSingle();if(r?.sessionId!==z){pe.log("[shorts-video-agent] Session changed during restore, aborting");return}const j=ar(y?.result_url);if(j){pe.log("[shorts-video-agent] Restored generating → result (from user_tasks):",j.substring(0,80)),G(j),Le(null),De(null),F("result"),_(Pe=>[...Pe,J("agent",H(),{videoUrl:j,sourceTaskId:T})]);return}const M=[T,E].filter(Pe=>typeof Pe=="string"&&Pe.length>0);let Q=null;if(M.length>0){const{data:Pe}=await ve.from("user_image_library").select("image_url, task_id").eq("user_id",I).eq("task_type","shorts").in("task_id",M).is("deleted_at",null).order("created_at",{ascending:!1}).limit(1);Q=Pe}const ke=Q?.[0],ae=ar(ke?.image_url);if(ae){pe.log("[shorts-video-agent] Restored generating → result (from user_image_library):",ae.substring(0,80)),G(ae),Le(null),De(null),F("result"),_(Pe=>
34[...Pe,J("agent",H(),{videoUrl:ae,sourceTaskId:ke?.task_id||T})]);return}if(I){const{data:Pe}=await ve.from("user_image_library").select("image_url, task_id, created_at").eq("user_id",I).eq("task_type","shorts").eq("media_type","video").is("deleted_at",null).order("created_at",{ascending:!1}).limit(1),Te=Pe?.[0],St=ar(Te?.image_url);if(St){const Tt=Te?.created_at?new Date(Te.created_at).getTime():0;if(Date.now()-Tt<3600*1e3){pe.log("[shorts-video-agent] Restored generating → result (from agent lib fallback):",St.substring(0,80)),G(St),Le(null),De(null),F("result"),_(Ht=>[...Ht,J("agent",H(),{videoUrl:St})]);return}}}if(y?.status==="failed"){pe.log("[shorts-video-agent] Restored generating → discussion (task failed)"),Le(null),De(null),F("discussion");return}pe.log("[shorts-video-agent] Restored generating — waiting for polling/realtime to complete"),De({progress:10,status:"generating",message:f("영상 생성 중...","動画生成中...","Generating video..."),resultUrl:null})}catch{}})()}},[t,r,I]),(0,s.useEffect)(()=>{N==="idle"||!r||bt===r.sessionId&&Mi(r,{phase:N,messages:se,draft:B,heroImageUrl:K,sourceProductImageUrls:te,sourceFaceImageUrl:R,selectedMood:yt,dynamicMoods:A,finalVideoUrl:O,activeGeneration:W,brandPronunciation:ut,productFingerprint:Me,brandPronunciationSkipped:qt,interactionCount:gt},I)},[N,se,B,K,te,R,yt,A,O,W,ut,Me,qt,gt,r,I,bt]);const _r=(0,s.useCallback)(async i=>{const m=await et(i.action);if(m)return m;const g=me.current,b=i.session.sessionId,C=()=>{if(me.current!==g)throw new Error("INVOKE_AGENT_CANCELLED_BY_RESET");if(vr.current?.sessionId!==b)throw new Error("INVOKE_AGENT_CANCELLED_BY_SESSION_CHANGE")},T=(i.messages||[]).filter(Te=>Te.role==="agent"||Te.role==="user").slice(-12).map(({role:Te,content:St})=>({role:Te,content:St.substring(0,800)})),{data:{session:E}}=await ve.auth.getSession();let z=E?.access_token;if(!z){const{data:Te}=await ve.auth.refreshSession();z=Te.session?.access_token}if(!z)throw new Error("Not authenticated");const y={action:i.action,stream:!0,language:n,...Lr(i.session.seedanceEngine??"2.0"),targetDuration:i.session.videoDuration||15,heroImageUrl:i.heroImageUrl,productImageUrls:i.productImageUrls,faceImageUrl:i.faceImageUrl,template:{id:i.session.preset.id,name:i.session.preset.name,description:i.session.preset.description,category:i.session.preset.category,promptTemplate:i.session.preset.promptTemplate},highlights:i.session.highlights,currentDraft:i.draft,messages:T,userMessage:i.userMessage,mood:i.mood?{id:i.mood.id,label:i.mood.label,description:i.mood.description,...i.mood.recipe?{recipe:i.mood.recipe}:{}}:void 0,autoConcept:i.session.autoConcept?{hook:i.session.autoConcept.hook,cta:i.session.autoConcept.cta,sellingPoints:i.session.autoConcept.sellingPoints,casting:i.session.autoConcept.casting,location:i.session.autoConcept.location,visualStyle:i.session.autoConcept.visualStyle,hookAction:i.session.autoConcept.hookAction,productPitch:i.session.autoConcept.productPitch,benefit:i.session.autoConcept.benefit,speechStyle:i.session.autoConcept.speechStyle,narrationStyle:i.session.autoConcept.narrationStyle,cgModuleLabel:i.session.autoConcept.cgModuleLabel,cgIntensity:i.session.autoConcept.cgIntensity,cgDirection:i.session.autoConcept.cgDirection}:void 0,revisionMode:i.revisionMode,brandPronunciation:i.brandPronunciation&&i.brandPronunciation.koreanReading?.trim()?{displayName:i.brandPronunciation.displayName||"",koreanReading:i.brandPronunciation.koreanReading.trim(),confidence:i.brandPronunciation.confidence||"medium",alternatives:i.brandPronunciation.alternatives||[]}:void 0,productFingerprint:i.productFingerprint&&i.productFingerprint.categoryLabel?.trim()?{categoryLabel:i.productFingerprint.categoryLabel.trim(),shape:i.productFingerprint.shape||"",material:i.productFingerprint.material||"",distinctive:i.productFingerprint.distinctive||"",motionHint:i.productFingerprint.motionHint||"",highlightsSummary:i.productFingerprint.highlightsSummary||""}:void 0},j=new AbortController,M=setTimeout(()=>j.abort(),155e3);let Q;try{Q=await fetch(`${Wa}/shorts-video-agent`,{method:"POST",headers:{Authorization:`Bearer ${z}`,"Content-Type":"application/json"},body:JSON.stringify(y),signal:j.signal})}
34catch(Te){throw clearTimeout(M),Te.name==="AbortError"?new Error(f("AI 응답 대기 시간이 초과되었습니다. 다시 시도해 주세요.","AI応答待ち時間が超過しました。再試行してください。","AI response timed out. Please try again.")):Te}if(clearTimeout(M),!Q.ok){const Te=await Q.text().catch(()=>"Unknown error"),St=Q.status===401||Q.status===403?f("인증이 만료되었습니다. 다시 로그인해 주세요.","認証の有効期限が切れました。再度ログインしてください。","Authentication expired. Please log in again."):Q.status===429?f("요청이 너무 많아요. 잠시 후 다시 시도해 주세요.","リクエストが多すぎます。しばらく後に再試行してください。","Too many requests. Please try again in a moment."):Q.status>=500?f("서버 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.","サーバーエラーが発生しました。しばらく後に再試行してください。","Server error. Please try again shortly."):f(`요청이 실패했습니다 (${Q.status}).`,`リクエストが失敗しました (${Q.status}).`,`Request failed (${Q.status}).`);throw new Error(St)}if(C(),!(Q.headers.get("content-type")||"").includes("text/event-stream")){const Te=await Q.json();if(C(),Te.error)throw new Error(Te.error);if(!Te.success||!Te.draft||!Te.assistantMessage)throw new Error(Te.error||"Agent response was incomplete.");return Te}const ke=Q.body.getReader(),ae=new TextDecoder;let Pe="";for(ht("start"),ft(0);;){const{done:Te,value:St}=await ke.read();if(Te)break;Pe+=ae.decode(St,{stream:!0});const Tt=Pe.split(`
35`);Pe=Tt.pop()??"";for(const Ht of Tt){if(!Ht.startsWith("data: "))continue;const er=Ht.slice(6).trim();if(er)try{const Et=JSON.parse(er);if(Et.phase&&(ht(Et.phase),Et.phase==="cut"&&Et.cutNumber&&ft(Et.cutNumber)),Et.error)throw new Error(Et.error);if(Et.done&&Et.result){ht(""),ft(0);const $r=Et.result;if(!$r.success||!$r.draft||!$r.assistantMessage)throw new Error($r.error||"Agent response was incomplete.");return $r}}catch(Et){if(Et.message!=="Unexpected token")throw Et}}}if(Pe.trim()){const Te=Pe.trim();if(Te.startsWith("data: ")){const St=Te.slice(6).trim();if(St)try{const Tt=JSON.parse(St);if(Tt.done&&Tt.result){ht(""),ft(0);const Ht=Tt.result;if(!Ht.success||!Ht.draft||!Ht.assistantMessage)throw new Error(Ht.error||"Agent response was incomplete.");return C(),Ht}if(Tt.error)throw new Error(Tt.error)}catch(Tt){if(Tt.message!=="Unexpected token")throw Tt}}}throw new Error("Stream ended without a result.")},[n,et]),Ct=(0,s.useCallback)(i=>{const m=i?.brandPronunciation;m&&typeof m=="object"&&typeof m.koreanReading=="string"&&m.koreanReading.trim()?(at({displayName:typeof m.displayName=="string"?m.displayName:"",koreanReading:m.koreanReading.trim(),confidence:["high","medium","low"].includes(m.confidence)?m.confidence:"medium",alternatives:Array.isArray(m.alternatives)?m.alternatives.filter(C=>typeof C=="string"&&C.trim()).slice(0,3):[]}),re(!1)):at(null);const g=i?.productFingerprint,b=C=>typeof C=="string"?C.trim():"";g&&typeof g=="object"&&b(g.categoryLabel)?ce({categoryLabel:b(g.categoryLabel),shape:b(g.shape),material:b(g.material),distinctive:b(g.distinctive),motionHint:b(g.motionHint),highlightsSummary:b(g.highlightsSummary)}):ce(null)},[]),Ir=(0,s.useCallback)(async(i,m)=>{_(g=>[...g,J("agent",Ee(),{imageUrl:i})]),q(!0);try{const{data:g}=await xt({body:{action:"analyze",language:n,...Lr(m.seedanceEngine??"2.0"),heroImageUrl:i,template:{name:m.preset.name,description:m.preset.description,category:m.preset.category,previewImage:Fr(m.preset.previewImage)},highlights:m.highlights}});Ct(g);const b=m.preset.tone,C=b?Ti[b]:void 0;if(C){const T={id:b,label:n==="en"?C.labelEn:C.labelKo,emoji:C.emoji,description:m.preset.description||"",...m.autoConcept?.recipe?{recipe:m.autoConcept.recipe}:{}},E=b==="free_concept";_(z=>[...z,J("agent",E?f(`고르신 컨셉 그대로 스토리보드를 짜 볼게요 ✍️
36후킹 → 제품 설명 → 장점 → 마무리 순서로 갈게요.`,`選んだコンセプトのままストーリーボードを作りますね ✍️
37フック → 製品説明 → メリット → 締めの順で進めます。`,`I'll write the storyboard straight from your concept ✍️
38Hook, product, benefit, then the close.`):f(`${C.labelKo} 템플릿 톤으로 바로 스토리보드를 짜 볼게요 ${C.emoji}`,`${C.labelKo} テンプレートのトーンで、すぐストーリーボードを作りますね ${C.emoji}`,`I'll write the storyboard right away in the ${C.labelEn} template tone ${C.emoji}`))]),Lt(T);return}if(g?.success&&g.moods?.length){const T=g.moods.map(E=>({id:E.id||`mood_${Date.now()}`,label:E.label,emoji:E.emoji||"🎬",description:E.description}));ye(T),_(E=>[...E,J("agent",g.assistantMessage||ee(),{moodPresets:T})])}else{const T=n==="en"?hr:pr;_(E=>[...E,J("agent",ee(),{moodPresets:T})])}}catch{const g=n==="en"?hr:pr;_(b=>[...b,J("agent",ee(),{moodPresets:g})])}finally{q(!1)}},[n,xt]),Ft=(0,s.useCallback)(async i=>{const m=me.current;if(fe(null),G(null),ie(null),Zt.current=null,x(null),ue([]),$(void 0),Le(null),rt(null),i.presetHeroImageUrl){const g=i.presetHeroImageUrl;x(g),ue(i.productImages||[]),_([J("agent",f(`안녕하세요, 빠냥이예요 🐱
39고르신 이미지를 보고 어울리는 분위기를 추천해 드릴게요!`,`こんにちは、パニャンです 🐱
40選んだ画像に合う雰囲気をおすすめしますね!`,`Hi, I'm Bbanyang 🐱
41I'll suggest moods that fit the image you picked!`))]),F("mood_select");try{await Ir(g,i)}catch(b){if(m!==me.current)return;fe(b?.message||"Analysis failed"),F("error")}return}_([J("agent",i.productImages?.length>0?f(`안녕하세요, 빠냥이예요 🐱
42올려 주신 제품으로 대표 이미지를 먼저 한 장 그려 볼게요 🎨`,`こんにちは、パニャンです 🐱
43アップロードした商品で、まず代表画像を1枚描きますね 🎨`,`Hi, I'm Bbanyang 🐱
44First I'll draw one hero image with your product 🎨`):f(`안녕하세요, 빠냥이예요 🐱
45"${i.highlights||i.preset.name}" 내용으로 광고 컨셉 이미지를 먼저 그려 볼게요 🎨`,`こんにちは、パニャンです 🐱
46「${i.highlights||i.preset.name}」の内容で、まず広告コンセプト画像を描きますね 🎨`,`Hi, I'm Bbanyang 🐱
47First I'll draw a concept image for your ad based on "${i.highlights||i.preset.name}" 🎨`))]),F("hero");try{const g=await h(i);if(m!==me.current||(x(g.heroImageUrl),ue(g.productImageUrls),$(g.faceImageUrl),await Ir(g.heroImageUrl,i),m!==me.current))return;F("mood_select")}catch(g){if(m!==me.current)return;const b=g?.message||"Failed to initialize the video agent.";fe(b),F("error"),_(C=>[...C,J("system",f(`에이전트를 준비하지 못했습니다. ${b}`,`エージェントを準備できませんでした。${b}`,`I couldn't prepare the agent. ${b}`))])}},[Ir,h,o,n]),ua=(0,s.useCallback)(async()=>{if(!r||N!=="mood_select")return;const i=me.current;F("hero"),x(null),ye(null),_(m=>[...m,J("user",f("이미지 재생성 요청","画像再生成リクエスト","Regenerate image")),J("agent",f(`네, 대표 이미지를 새로 그려 볼게요 🎨
48다 되면 바로 보여 드릴게요!`,`はい、代表画像を描き直しますね 🎨
49できたらすぐお見せします!`,`Sure, I'll redraw the hero image 🎨
50I'll show you as soon as it's done!`))]);try{const m=K||r.presetHeroImageUrl,g=await h(r.productImages.length>0?r:{...r,productImages:m?[m]:[],presetHeroImageUrl:void 0});if(i!==me.current)return;x(g.heroImageUrl),ue(g.productImageUrls),$(g.faceImageUrl),_(b=>[...b,J("agent",f(`짜잔, 새 대표 이미지가 나왔어요 🎨
51어울리는 분위기를 골라 보고 있어요 👀`,`ジャーン、新しい代表画像ができました 🎨
52合う雰囲気を選んでいます 👀`,`Ta-da, here's the new hero image 🎨
53Picking moods that fit it 👀`),{imageUrl:g.heroImageUrl})]),q(!0);try{const{data:b}=await xt({body:{action:"analyze",language:n,...Lr(r.seedanceEngine??"2.0"),heroImageUrl:g.heroImageUrl,template:{name:r.preset.name,description:r.preset.description,category:r.preset.category,previewImage:Fr(r.preset.previewImage)},highlights:r.highlights}});if(i!==me.current)return;if(Ct(b),b?.success&&b.moods?.length){const C=b.moods.map(T=>({id:T.id||`mood_${Date.now()}`,label:T.label,emoji:T.emoji||"🎬",description:T.description}));ye(C),_(T=>[...T,J("agent",b.assistantMessage||ee(),{moodPresets:C})])}else{const C=n==="en"?hr:pr;_(T=>[...T,J("agent",ee(),{moodPresets:C})])}}catch{if(i!==me.current)return;const b=n==="en"?hr:pr;_(C=>[...C,J("agent",ee(),{moodPresets:b})])}finally{q(!1)}F("mood_select")}catch(m){if(i!==me.current)return;fe(m?.message||"Regeneration failed"),F("mood_select"),_(g=>[...g,J("system",f(`재생성에 실패했습니다: ${m?.message}`,`再生成に失敗しました: ${m?.message}`,`Regeneration failed: ${m?.message}`))])}},[r,N,h,n,xt]),Gt=(0,s.useCallback)(async(i,m={})=>
53{if(!r||N!=="mood_select"||_e)return;const g=me.current;F("hero"),Ne(!0),x(null),ye(null),_(E=>[...E,...m.userBubbleShown?[]:[J("user",i)],J("agent",f(`네, 말씀하신 대로 이미지를 다시 그려 볼게요 🎨
54다 되면 바로 보여 드릴게요!`,`はい、ご要望どおり画像を描き直しますね 🎨
55できたらすぐお見せします!`,`Sure, I'll redraw the image the way you asked 🎨
56I'll show you as soon as it's done!`))]);const b=K||r.presetHeroImageUrl,C=r.productImages.length>0?r.productImages:b?[b]:[],T={...r,productImages:C,presetHeroImageUrl:void 0,highlights:r.highlights?`${r.highlights}
57
58User feedback for image regeneration: ${i}`:`User feedback for image regeneration: ${i}`};try{const E=await h(T);if(g!==me.current)return;x(E.heroImageUrl),ue(E.productImageUrls),$(E.faceImageUrl),_(z=>[...z,J("agent",f(`짜잔, 새 이미지가 나왔어요 🎨
59어울리는 분위기를 골라 보고 있어요 👀`,`ジャーン、新しい画像ができました 🎨
60合う雰囲気を選んでいます 👀`,`Ta-da, here's the new image 🎨
61Picking moods that fit it 👀`),{imageUrl:E.heroImageUrl})]),q(!0);try{const{data:z}=await xt({body:{action:"analyze",language:n,...Lr(r.seedanceEngine??"2.0"),heroImageUrl:E.heroImageUrl,template:{name:r.preset.name,description:r.preset.description,category:r.preset.category,previewImage:Fr(r.preset.previewImage)},highlights:r.highlights}});if(g!==me.current)return;if(Ct(z),z?.success&&z.moods?.length){const y=z.moods.map(j=>({id:j.id||`mood_${Date.now()}`,label:j.label,emoji:j.emoji||"🎬",description:j.description}));ye(y),_(j=>[...j,J("agent",z.assistantMessage||ee(),{moodPresets:y})])}else{const y=n==="en"?hr:pr;_(j=>[...j,J("agent",ee(),{moodPresets:y})])}}catch{if(g!==me.current)return;const z=n==="en"?hr:pr;_(y=>[...y,J("agent",ee(),{moodPresets:z})])}finally{q(!1)}F("mood_select")}catch(E){if(g!==me.current)return;fe(E?.message||"Regeneration failed"),F("mood_select"),_(z=>[...z,J("system",f(`재생성에 실패했습니다: ${E?.message}`,`再生成に失敗しました: ${E?.message}`,`Regeneration failed: ${E?.message}`))])}finally{g===me.current&&Ne(!1)}},[r,N,_e,h,n,xt]),ma=(0,s.useCallback)(async()=>{if(!r||!K||_e)return;const i=me.current;ie(null),Zt.current=null,rt(null),ye(null),Ne(!0),q(!0),F("mood_select"),_(m=>[...m,J("user",f("다른 컨셉 시도","他のコンセプトを試す","Try a different concept")),J("agent",f(`좋아요, 다른 컨셉을 찾아볼게요 🔍
62잠깐만 기다려 주세요!`,`いいですね、別のコンセプトを探しますね 🔍
63少し待っててください!`,`Sure, let me find a different concept 🔍
64Just a moment!`))]);try{const{data:m}=await xt({body:{action:"analyze",language:n,...Lr(r.seedanceEngine??"2.0"),heroImageUrl:K,template:{name:r.preset.name,description:r.preset.description,category:r.preset.category,previewImage:Fr(r.preset.previewImage)},highlights:r.highlights}});if(i!==me.current)return;if(m?.success&&m.moods?.length){const g=m.moods.map(b=>({id:`mood_${Date.now()}_${Math.random().toString(36).slice(2)}`,label:b.label,emoji:b.emoji||"🎬",description:b.description}));ye(g),_(b=>[...b,J("agent",m.assistantMessage||ee(),{moodPresets:g})])}else{const g=n==="en"?hr:pr;_(b=>[...b,J("agent",ee(),{moodPresets:g})])}}catch{if(i!==me.current)return;const m=n==="en"?hr:pr;_(g=>[...g,J("agent",ee(),{moodPresets:m})])}finally{Ne(!1),q(!1)}},[r,K,_e,n,xt]),or=(0,s.useCallback)(async(i,m)=>{if(!(!r||!K||_e)){rt(i),m?.auto||_(g=>[...g,J("user",i.label),J("agent",f(`좋아요, "${i.label}" 분위기로 가 볼게요 👍
65${r.videoDuration||15}초 쇼츠 스토리보드를 바로 짜 볼게요 ✍️`,`いいですね、「${i.label}」の雰囲気でいきましょう 👍
66${r.videoDuration||15}秒ショートのストーリーボードをすぐ作りますね ✍️`,`Great, let's go with the "${i.label}" vibe 👍
67I'll write the ${r.videoDuration||15}-second shorts storyboard right away ✍️`))]),F("drafting"),Ne(!0);try{const g=await _r({action:"draft",session:r,heroImageUrl:K,productImageUrls:te,faceImageUrl:R,mood:i,brandPronunciation:ut,productFingerprint:Me});if(!g.draft?.title&&!g.draft?.cuts?.length)throw new Error(f("AI가 스토리보드를 생성하지 못했습니다. 다시 시도해 주세요.","AIがストーリーボードを生成できませんでした。再試行してください。","AI failed to generate storyboard. Please try again."));
67ie(Ys(g.draft)),_(b=>[...b,J("agent",g.assistantMessage||f("스토리보드를 다 썼어요 📝","ストーリーボードができました 📝","Your storyboard is ready 📝"),{suggestions:g.suggestions?.length?g.suggestions:gr,showStoryboard:!0}),J("agent",Xs(n),{storyboardFollowUp:!0})]),F("discussion")}catch(g){const b=g?.message||"Failed to create storyboard draft.";if(b.startsWith("INVOKE_AGENT_CANCELLED")){pe.log("[shorts-video-agent] selectMood cancelled (session/reset):",b);return}fe(b),F("mood_select"),_(C=>[...C,J("system",`⚠️ ${b}`),J("agent",f(`앗, 이번엔 스토리보드를 못 썼어요 😿
68다른 분위기를 고르거나 한 번 더 시도해 볼까요?`,`あっ、今回はストーリーボードを作れませんでした 😿
69別の雰囲気を選ぶか、もう一度試してみましょうか?`,`Oops, I couldn't write the storyboard this time 😿
70Want to pick another mood or try again?`),{moodPresets:n==="en"?hr:pr})])}finally{Ne(!1)}}},[ut,gr,K,_r,_e,n,Me,r,R,te]);(0,s.useEffect)(()=>{if(!Ze||!r||!K||_e||N!=="mood_select"&&N!=="hero")return;const i=Ze;Lt(null),or(i,{auto:!0})},[Ze,r,K,_e,N,or]);const Ar=(0,s.useCallback)(async(i,m,g)=>{try{const{data:b,error:C}=await xt({body:{action:"chat",language:n,phase:N,revisionAvailable:m,userMessage:i,targetDuration:r?.videoDuration||15,currentDraft:B,messages:g.slice(-10).map(T=>({role:T.role,content:String(T.content||"")}))}});if(C||!b?.success)throw new Error(C?.message||b?.error||"chat failed");return{received:!0,intent:b.intent,reply:typeof b.reply=="string"?b.reply.trim():"",quality:typeof b.quality=="string"?b.quality:null,suggestions:Array.isArray(b.suggestions)?b.suggestions.filter(T=>typeof T=="string"):[]}}catch(b){return pe.warn("[shorts-agent] chat judge failed",b?.message),{received:!1,intent:void 0,reply:"",quality:null,suggestions:[]}}},[xt,n,N,r?.videoDuration,B]),it=(0,s.useCallback)(async(i,m)=>{if(!r||_e)return;const g=me.current;Ne(!0),_(T=>[...T,J("agent",m)]);const b=K||r.presetHeroImageUrl,C={...r,productImages:r.productImages.length>0?r.productImages:b?[b]:[],presetHeroImageUrl:void 0,highlights:r.highlights?`${r.highlights}
71
72User feedback for image regeneration: ${i}`:`User feedback for image regeneration: ${i}`};try{const T=await h(C);if(g!==me.current)return;x(T.heroImageUrl),ue(T.productImageUrls),$(T.faceImageUrl),ie(E=>E&&{...E,finalPrompt:""}),_(E=>[...E,J("agent",f(`짜잔, 새 대표 이미지가 나왔어요 🎨
73스토리보드는 그대로 두고, 영상은 이 이미지로 만들게요.`,`ジャーン、新しい代表画像ができました 🎨
74ストーリーボードはそのままで、動画はこの画像で作りますね。`,`Here is the new representative image 🎨
75The storyboard stays as it is — the video will use this image.`),{imageUrl:T.heroImageUrl})])}catch(T){if(g!==me.current)return;_(E=>[...E,J("system",f(`대표 이미지를 다시 그리지 못했어요: ${T?.message||""}`.trim(),`代表画像を描き直せませんでした: ${T?.message||""}`.trim(),`Could not redraw the representative image: ${T?.message||""}`.trim()))])}finally{g===me.current&&Ne(!1)}},[r,_e,K,h,n]),ir=(0,s.useCallback)(async i=>{const m=i.trim();if(!m||!r||P)return;const g=V&&N==="result"&&!!B&&!_e,b=[...se,J("user",m)];_(M=>[...M,J("user",m)]);const C=async(M,Q)=>{if(!(!K||!B)){if(!D&&gt>=Js){if(!await Mt(ia)){nr(ia),_(ke=>[...ke,J("system",f("4회째 수정부터는 1크레딧이 필요합니다. 크레딧이 부족해 요청을 처리할 수 없어요.","4回目以降の修正は1クレジット必要です。クレジットが不足しているためリクエストを処理できません。","Revisions beyond the free count require 1 credit. Insufficient credits to process this request."))]);return}if(!await wt(ia,"쇼츠 에이전트 스토리보드 수정")){nr(ia),_(ke=>[...ke,J("system",f("크레딧 차감에 실패했습니다. 잠시 후 다시 시도해 주세요.","クレジット控除に失敗しました。しばらく後に再試行してください。","Credit deduction failed. Please try again in a moment."))]);return}}Ae(ke=>ke+1),Ne(!0),Q&&_(ke=>[...ke,J("agent",Q)]);try{const ke=await _r({action:"revise",session:r,heroImageUrl:K,productImageUrls:te,faceImageUrl:R,draft:M==="reconstruct"?null:B,messages:b,userMessage:m,mood:M==="reconstruct"?null:yt,revisionMode:M,brandPronunciation:ut,productFingerprint:Me});ke.draft&&ie(Ys(ke.draft)),_(ae=>[...ae,J("agent",ke.assistantMessage||f("말씀하신 대로 고쳤어요 ✨","ご要望どおり直しました ✨","Done — updated as you asked ✨"),{suggestions:ke.suggestions?.length?ke.suggestions:gr,showStoryboard:!!ke.draft}),...ke.draft?[J("agent",Xs(n),{storyboardFollowUp:!0})]:[]]),fe(null),F("discussion")}catch(ke){const ae=ke?.message||"Failed to update the storyboard.";if(ae.startsWith("INVOKE_AGENT_CANCELLED")){pe.log("[shorts-video-agent] sendMessage cancelled (session/reset):",ae);return}fe(ae),_(Pe=>[...Pe,J("system",f(`수정 반영 중 문제가 생겼습니다. ${ae}`,`修正反映中に問題が発生しました。${ae}`,`There was a problem applying the revision. ${ae}`))])}finally{Ne(!1)}}};if(g){X(!1),ge.current?.({silent:!0}),await C("revise",f(`알겠어요!
76기존 스토리보드에서 말씀하신 부분을 고쳐 다시 써 볼게요 ✍️`,`わかりました!
77今のストーリーボードで、言われたところを直して書き直しますね ✍️`,`Got it!
78I'll rewrite the current storyboard with your changes ✍️`));return}const T=pi({phase:N,hasDraft:!!B&&!!K,isBusy:_e||Ie});Ce(!0);let E;try{E=await Ar(m,T!=="answer_only",b)}finally{Ce(!1)}const z=mi({intent:E.intent,received:E.received,route:T}),y=E.reply,j=(M,Q,ke)=>{_(ae=>[...ae,y?J("agent",y,E.suggestions.length?{suggestions:E.suggestions}:void 0):J("system",f(M,Q,ke))])};
78if(z==="answer"||T==="answer_only"){j("답을 가져오지 못했어요. 잠시 후 다시 말씀해 주세요.","回答を取得できませんでした。少し後にもう一度お話しください。","I could not get an answer. Please try again in a moment.");return}if(T==="mood_select"){if(z==="redraw_hero"&&K){await Gt(m,{userBubbleShown:!0});return}await or({id:`custom_${Date.now()}`,label:m.length>20?m.substring(0,20)+"...":m,description:m,emoji:"✏️"});return}if(T==="gate_then_act"&&ge.current?.({silent:!0}),z==="redraw_hero"){await it(m,y||f(`네, 대표 이미지를 다시 그려 볼게요 🎨
79스토리보드는 그대로 둘게요.`,`はい、代表画像を描き直しますね 🎨
80ストーリーボードはそのままにします。`,`Sure, I'll redraw the representative image 🎨
81The storyboard stays as it is.`));return}if(z==="generate_video"){const M=wn(r.seedanceEngine??"2.0",r.videoDuration??15),Q=ui(E.quality,M);We({quality:Q,nonce:Date.now()}),_(ke=>[...ke,J("agent",f(`좋아요, 지금 스토리보드로 ${Q} 영상을 만들게요 🎬
82확인창에서 시작을 눌러 주세요!`,`いいですね、今のストーリーボードで${Q}の動画を作りますね 🎬
83確認画面で開始を押してください!`,`Great — I'll make the ${Q} video from this storyboard 🎬
84Press start in the confirmation.`))]);return}await C(z==="reconstruct"?"reconstruct":"revise",y||(z==="reconstruct"?f("좋아요, 말씀하신 방향으로 스토리보드를 처음부터 새로 짜 볼게요 ✍️","いいですね、言われた方向でストーリーボードを最初から作り直しますね ✍️","Sure, I'll rebuild the storyboard from scratch in your new direction ✍️"):f("말씀하신 부분을 고쳐서 다시 정리할게요 ✍️","言われたところを直して整え直しますね ✍️","I'll rework that part and tidy up the storyboard ✍️")))},[Ar,ut,gr,B,K,_r,Ie,P,_e,n,se,N,Me,it,yt,or,r,R,te,Gt,gt,Mt,wt,nr,V,D]),Vt=(0,s.useCallback)(async i=>{if(!r||!K)return i.finalPrompt;const m=await et("rebuild-prompt");if(m)return m.finalPrompt||i.finalPrompt;const g=new AbortController,b=setTimeout(()=>g.abort(),155e3);try{const C=(await ve.auth.getSession()).data.session?.access_token,T=await fetch(`${Wa}/shorts-video-agent`,{method:"POST",headers:{"Content-Type":"application/json",...C?{Authorization:`Bearer ${C}`}:{}},body:JSON.stringify({action:"rebuild-prompt",targetDuration:r.videoDuration||15,heroImageUrl:K,currentDraft:i,language:n,highlights:r.highlights,template:{name:r.preset.name,description:r.preset.description},mood:yt,autoConcept:r.autoConcept?{hook:r.autoConcept.hook,cta:r.autoConcept.cta,sellingPoints:r.autoConcept.sellingPoints,casting:r.autoConcept.casting,location:r.autoConcept.location,hookAction:r.autoConcept.hookAction,benefit:r.autoConcept.benefit,speechStyle:r.autoConcept.speechStyle,narrationStyle:r.autoConcept.narrationStyle,cgModuleLabel:r.autoConcept.cgModuleLabel,cgIntensity:r.autoConcept.cgIntensity,cgDirection:r.autoConcept.cgDirection}:void 0,brandPronunciation:ut,productFingerprint:Me,...Lr(r.seedanceEngine??"2.0"),...r.seedanceEngine==="2.5"?{productImageUrls:te,faceImageUrl:R??null}:{}}),signal:g.signal});if((T.headers.get("content-type")||"").includes("text/event-stream")){const E=(await T.text()).split(`
85`).filter(z=>z.startsWith("data: "));for(let z=E.length-1;z>=0;z--)try{const y=JSON.parse(E[z].slice(6));if(y.finalPrompt)return y.finalPrompt;if(y.draft?.finalPrompt)return y.draft.finalPrompt}catch{}}else{const E=await T.json(),z=E.finalPrompt||E.draft?.finalPrompt;if(z&&z.trim())return z}}catch{}finally{clearTimeout(b)}throw new Error(f("프롬프트 생성에 실패했습니다. 잠시 후 다시 시도해 주세요.","プロンプト生成に失敗しました。しばらく後に再試行してください。","Prompt generation failed. Please try again in a moment."))},[ut,K,n,Me,yt,r,te,R]),Kt=(0,s.useCallback)((i,m)=>{ie(g=>!g||!g.cuts?g:{...g,cuts:g.cuts.map(b=>b.cutNumber===i?m:b)})},[]),pt=(0,s.useRef)(!1),Pt=(0,s.useRef)([]),Zt=(0,s.useRef)(null),Sr=(0,s.useRef)(0),lr=(0,s.useCallback)(async(i="720p")=>{if(!(!r||!K||!B||_e||pt.current)){pt.current=!0,W&&(pe.log("[shorts-video-agent] Clearing previous activeGeneration before new generation"),Le(null),De(null)),Ne(!0),F("generating"),Sr.current=Date.now(),Je.current=!1,De({progress:5,status:"generating",message:f("편집된 컷 기반으로 최종 프롬프트 생성 중...","編集されたカットをもとに最終プロンプトを生成中...","Rebuilding final prompt from edited cuts...")}),_(m=>
85[...m,J("agent",f(`스토리보드대로 영상 만들기 시작할게요 🎬
86보통 1~2분이면 완성돼요.`,`ストーリーボードどおりに動画を作り始めますね 🎬
87だいたい1〜2分でできあがります。`,`Starting the video from your storyboard 🎬
88It usually takes 1–2 minutes.`))]);try{const m=In(_n(await Vt(B))),g={...B,finalPrompt:m};ie(g),Zt.current=r.seedanceEngine??"2.0",De({progress:10,status:"generating",message:f("영상 프롬프트 전송 중...","動画プロンプト送信中...","Sending the video prompt...")});const b=await S({session:r,heroImageUrl:K,productImageUrls:te,faceImageUrl:R,finalPrompt:m,storyboardDraft:g,quality:i,excludeProviders:Pt.current});b.resultUrl?Ye(b.resultUrl,H()):Le(b)}catch(m){if(Os(m)){De(null),F("discussion");return}const g=m?.message||"Failed to start video generation.";De(null),fe(g),F("discussion"),_(b=>[...b,J("system",f(`영상 생성 요청에 실패했습니다: ${g}
89스토리보드를 수정하거나 다시 시도해 주세요.`,`動画生成リクエストに失敗しました: ${g}
90ストーリーボードを修正するか再試行してください。`,`Video generation request failed: ${g}
91Please revise the storyboard or try again.`))])}finally{Ne(!1),pt.current=!1}}},[B,K,_e,n,Ye,Vt,r,S]),It=(0,s.useCallback)(()=>{const i=D?.finalVideoUrl;if(!i||Fe.current==="result")return;const m=H();if(Fe.current==="generating"){Ye(i,m);return}const g=D?.respond("draft")?.data?.draft??null;ie(b=>b??g),Ne(!1),fe(null),Le(null),De(null),pt.current=!1,G(i),F("result"),_(b=>b.some(C=>C.videoUrl===i)?b:[...b,J("agent",m,{videoUrl:i})])},[D,n,Ye]),pa=(0,s.useCallback)(()=>{!D||Fe.current!=="result"||(me.current+=1,Je.current=!1,pt.current=!1,Le(null),De(null),G(null),Ne(!1),fe(null),F("generating"))},[D]),Ut=(0,s.useCallback)(()=>{if(!D||Fe.current!=="generating"&&Fe.current!=="result")return;me.current+=1,Je.current=!1,pt.current=!1,Le(null),De(null),G(null),Ne(!1),fe(null);const i=D.respond("draft")?.data?.draft??null;ie(m=>m??i),F("discussion")},[D]);(0,s.useEffect)(()=>{if(!t){Fe.current!=="generating"&&Fe.current!=="result"&&Vr();return}if(t&&r&&N==="idle"){if(Bt.current){Bt.current=!1;return}if(bt!==r.sessionId)return;Ft(r)}},[Ft,t,N,Vr,r,bt]),(0,s.useEffect)(()=>{if(!W||N!=="generating")return;const i=l.find(m=>{const g=m.generationOptions||{},b=g.client_task_id||g.clientTaskId,C=g.ad_workflow==="video_agent";return m.taskId===W.apiTaskId||b===W.clientTaskId?m.mediaType==="video"||C||/\.(mp4|webm|mov)/i.test(m.editedImageUrl||""):!1});i?.editedImageUrl&&Ye(i.editedImageUrl,H())},[W,n,Ye,N,l]),(0,s.useEffect)(()=>{if(!(!mt||N!=="generating")){if(mt.status==="completed"&&mt.resultUrl){Ye(mt.resultUrl,H());return}De(i=>({progress:Math.max(i?.progress??0,mt.progress??0),status:mt.status,error:mt.error,message:mt.message,resultUrl:mt.resultUrl??i?.resultUrl??null}))}},[mt,n,Ye,N]);const{markObserved:cr}=ni({active:N==="generating",suspended:()=>Qt.current,label:"shorts-video-agent",onZombie:()=>{Je.current||(Le(null),De(null),F("discussion"),Ne(!1),pt.current=!1,_(i=>[...i,J("system",f("진행 중이던 영상 작업을 찾지 못해 생성을 중단했습니다. 차감된 크레딧은 없습니다. 스토리보드를 확인하고 다시 생성해 주세요.","進行中の動画作業が見つからなかったため生成を中断しました。差し引かれたクレジットはありません。ストーリーボードを確認して再生成してください。","We could not find the video job in progress, so generation was stopped. No credits were charged. Please review the storyboard and generate again."))]))}});(0,s.useEffect)(()=>{if(N!=="generating")return;const i=W?.apiTaskId;let m=!1;const g=async()=>{if(m||Je.current)return;let j=null,M=null;if(i){let ae=ve.from("user_tasks").select("status, progress, result_url, error_message").eq("task_id",i);I&&(ae=ae.eq("user_id",I));const Pe=await ae.maybeSingle();j=Pe.data,M=Pe.error}else if(I){const ae=new Date(Date.now()-3e5).toISOString(),Pe=await ve.from("user_tasks").select("status, progress, result_url, error_message").eq("user_id",I).in("model",Ci).filter("generation_options->>ad_workflow","eq","video_agent").filter("generation_options->>task_type","eq",ot).gt("created_at",ae).order("created_at",{ascending:!1}).limit(1).maybeSingle();j=Pe.data,M=Pe.error}if(m||M||!j)return;cr();const Q=ar(j.result_url);if(Q){Pt.current=[],Ye(Q,H());return}if(j.status==="failed"){const ae=j.error_message||f("영상 생성에 실패했습니다.","動画生成に失敗しました。","Video generation failed."),Pe=j?.generation_options?.provider;
91typeof Pe=="string"&&Pe.trim()&&!Pt.current.includes(Pe)&&(Pt.current=[...Pt.current,Pe],pe.warn("[shorts-video-agent] provider failed → 다음 재시도에서 제외:",Pe,Pt.current)),_t(ae);return}const ke=typeof j.progress=="number"?Math.max(10,Math.min(Math.round(j.progress),99)):10;De(ae=>({progress:Math.max(ae?.progress??0,ke),status:"generating",error:void 0,message:ae?.message||f("영상 생성 중","動画生成中","Generating video"),resultUrl:ae?.resultUrl??null}))};g();const b=window.setInterval(()=>{g()},3e3),C=97,T=8,E=4.5,z=Date.now(),y=window.setInterval(()=>{if(m||Je.current)return;const j=(Date.now()-z)/6e4,M=Math.floor(C-(C-T)*Math.exp(-j/E));De(Q=>{if(!Q||Q.status!=="generating")return Q;const ke=Math.max(Q.progress??0,M);return ke===(Q.progress??0)?Q:{...Q,progress:ke}})},3e3);return()=>{m=!0,window.clearInterval(b),window.clearInterval(y)}},[W,n,Ye,_t,N,I]),(0,s.useEffect)(()=>{if(!W?.apiTaskId||N!=="generating")return;const i=W.apiTaskId,m=async()=>{try{const{data:E}=await ve.from("user_tasks").select("generation_options").eq("task_id",i).single(),z=E?.generation_options?.provider;return z&&{segmind:"segmind-task-status",evolink:"evolink-task-status",kie:"kie-task-status"}[z]||null}catch{return null}};let g=null;const b=async()=>{if(g)try{const{data:E}=await ve.functions.invoke(g,{body:{taskId:i}});E?.status==="completed"&&E?.result_url?Ye(E.result_url,H()):E?.status==="failed"&&_t(E.error||f("영상 생성에 실패했습니다.","動画生成に失敗しました。","Video generation failed."))}catch{}};m().then(E=>{g=E});const C=setTimeout(b,1e4),T=setInterval(b,15e3);return()=>{clearTimeout(C),clearInterval(T)}},[W?.apiTaskId,n,Ye,_t,N]),(0,s.useEffect)(()=>{if(!W?.apiTaskId||N!=="generating")return;const i=ve.channel(`shorts-agent-task-watch-${W.apiTaskId}`).on("postgres_changes",{event:"UPDATE",schema:"public",table:"user_tasks",filter:`task_id=eq.${W.apiTaskId}`},m=>{const g=m.new;if(I&&g?.user_id&&g.user_id!==I){pe.log("[shorts-agent] Ignoring realtime update from another user:",g.user_id);return}const b=ar(g?.result_url);b?Ye(b,H()):g?.status==="failed"&&_t(g.error_message||f("영상 생성에 실패했습니다.","動画生成に失敗しました。","Video generation failed."))}).subscribe();return()=>{ve.removeChannel(i)}},[W?.apiTaskId,n,Ye,_t,N]),(0,s.useEffect)(()=>{const i=mt||kt;if(!(!i||N!=="generating")){if(i.resultUrl){Ye(i.resultUrl,H());return}if(i.status==="failed"){_t(i.error||f("영상 생성에 실패했습니다.","動画生成に失敗しました。","Video generation failed."));return}}},[mt,kt,n,Ye,_t,N]),(0,s.useEffect)(()=>{if(N!=="generating"||!W?.apiTaskId||!I)return;const i=W.apiTaskId,m=W.clientTaskId,g=async()=>{try{const{data:T}=await ve.from("user_tasks").select("status, result_url").eq("task_id",i).eq("user_id",I).maybeSingle(),E=ar(T?.result_url);if(E){Ye(E,H());return}const z=[i,m].filter(M=>typeof M=="string"&&M.length>0);let y=null;if(z.length>0){const{data:M}=await ve.from("user_image_library").select("image_url").eq("user_id",I).in("task_id",z).is("deleted_at",null).order("created_at",{ascending:!1}).limit(1);y=M}const j=ar(y?.[0]?.image_url);if(j){Ye(j,H());return}if(I){const{data:M}=await ve.from("user_image_library").select("image_url, created_at").eq("user_id",I).eq("task_type","shorts").eq("media_type","video").is("deleted_at",null).order("created_at",{ascending:!1}).limit(1),Q=M?.[0],ke=ar(Q?.image_url);if(ke){const ae=Q?.created_at?new Date(Q.created_at).getTime():0,Pe=Sr.current;Pe>0&&ae>=Pe-60*1e3&&Ye(ke,H())}}}catch{}},b=window.setTimeout(()=>{g()},3e3),C=window.setInterval(()=>{g()},2e4);return()=>{window.clearTimeout(b),window.clearInterval(C)}},[N,W?.apiTaskId,W?.clientTaskId,I,n,Ye]);const vt=(0,s.useCallback)((i={})=>{N!=="result"||!B||(G(null),F("discussion"),Le(null),De(null),Je.current=!1,pt.current=!1,ie(m=>m&&{...m,finalPrompt:""}),i.silent||_(m=>
91[...m,J("agent",f(`스토리보드를 다시 고칠 수 있어요 ✏️
92다 고치면 아래에서 영상 만들기를 눌러 주세요!`,`ストーリーボードをもう一度直せますよ ✏️
93直し終わったら下で動画を作るボタンを押してくださいね!`,`You can edit the storyboard again ✏️
94When you are done, press Generate below!`))]))},[N,B,n]);ge.current=vt;const Rr=(0,s.useCallback)(()=>{N!=="result"||!B||V||(X(!0),_(i=>[...i,J("agent",f(`좋아요, 같이 고쳐 봐요 ✏️
95영상을 어떻게 수정할까요?`,`いいですね、一緒に直しましょう ✏️
96動画をどう修正しましょうか?`,`Sure, let's fix it together ✏️
97How would you like to change the video?`))]))},[N,B,V,n]);(0,s.useEffect)(()=>{N!=="result"&&X(!1)},[N]);const dr=(0,s.useCallback)(async(i="720p")=>{if(!r||!K||!B||_e||pt.current)return;pt.current=!0;const m=B.finalPrompt,g=r.seedanceEngine??"2.0",b=Ni(Zt.current,g,m);if(!m||b){pt.current=!1,await lr(i);return}Ne(!0),F("generating"),Sr.current=Date.now(),Je.current=!1,G(null),Le(null),De({progress:10,status:"generating",message:f("동일한 프롬프트로 영상 재생성 중...","同じプロンプトで動画を再生成中...","Regenerating video with same prompt...")}),_(C=>[...C,J("agent",f("같은 스토리보드로 영상을 한 번 더 만들어 볼게요 🎬","同じストーリーボードで動画をもう一度作りますね 🎬","I'll make one more video from the same storyboard 🎬"))]);try{const C=await S({session:r,heroImageUrl:K,productImageUrls:te,faceImageUrl:R,finalPrompt:m,storyboardDraft:B,quality:i,excludeProviders:Pt.current});Le({clientTaskId:C.clientTaskId,apiTaskId:C.apiTaskId||null}),C.resultUrl&&Ye(C.resultUrl,H())}catch(C){if(Os(C)){F("discussion");return}_t(C?.message||"Regeneration failed")}finally{Ne(!1),pt.current=!1}},[r,K,B,_e,n,S,te,R,Ye,_t,lr]),ur=(0,s.useCallback)(i=>{const m=i.trim();m&&(at(g=>({displayName:g?.displayName||"",koreanReading:m,confidence:"high",alternatives:g?.alternatives||[]})),re(!1))},[]),Hr=(0,s.useCallback)((i,m)=>{const g=m.trim();g&&(at({displayName:i.trim(),koreanReading:g,confidence:"high",alternatives:[]}),re(!1))},[]),Wt=(0,s.useCallback)(i=>{re(i),i&&at(null)},[]);return{phase:N,messages:se,draft:B,heroImageUrl:K,finalVideoUrl:O,error:Oe,isThinking:_e,isAnalyzing:Ie,streamingPhase:Qe,streamingCutNumber:$t,selectedMood:yt,moodPresets:kr,brandPronunciation:ut,productFingerprint:Me,activeTaskProgress:Math.max(mt?.progress??0,kt?.progress??0)||(N==="generating"?10:null),activeTaskStatus:mt?.status??kt?.status??null,activeTaskMessage:mt?.message??kt?.message??null,canSendMessage:!!r&&N!=="idle"&&!P,isAnswering:P,generateRequest:Re,clearGenerateRequest:()=>We(null),canGenerateVideo:N==="discussion"&&!_e&&!!B&&!!K,brandPronunciationSkipped:qt,nextMessageCost:(N==="discussion"||N==="result")&&gt>=Js?ia:0,canSelectMood:N==="mood_select"&&!_e,canRegenerateHero:N==="mood_select"&&!_e&&!!K,sendMessage:ir,selectMood:or,updateBrandPronunciation:ur,confirmBrandPronunciation:Hr,markBrandPronunciationSkipped:Wt,generateVideo:lr,regenerateVideo:dr,editStoryboard:vt,askVideoRevision:Rr,videoRevisionAsked:V,updateCut:Kt,regenerateHero:ua,restartConcept:ma,cancelGeneration:wr,jumpToResultForTutorial:It,showProgressForTutorial:pa,rewindToDiscussionForTutorial:Ut,reset:Vr}}var Fi={analyzing:"searching",start:"searching",concept:"solving",cuts_start:"composing",cut:"shaping",narration:"composing",final:"working"},Gi=yn({quality:"medium",resolution:"1K"}),ta=t=>(r,n,l)=>t==="ko"?r:t==="ja"?n:l,Vi=({cut:t,language:r,index:n,editable:l=!1,onSave:p,onEditingChange:h})=>{const o=ta(r),[S,v]=(0,s.useState)(!1),[U,D]=(0,s.useState)(t),I=(0,s.useRef)(!1),f=te=>{I.current!==te&&(I.current=te,h?.(te?1:-1))};(0,s.useEffect)(()=>()=>{I.current&&h?.(-1)},[]);const H=t.narration&&t.narration!=="없음"&&t.narration!=="None",ee=t.dialogue&&t.dialogue!=="없음"&&t.dialogue!=="None",Ee="bg-white/[0.03]",N="border-border",F="text-brand-ink",se="border-border",_="shrink-0 w-[46px] md:w-[52px] pt-px text-[10px] md:text-[10.5px] font-bold text-muted-foreground",B=()=>{D({...t}),v(!0),f(!0)},ie=()=>{p?.(U),v(!1),f(!1)},K=()=>{D({...t}),v(!1),f(!1)},x=(te,ue)=>{D(R=>({...R,[te]:ue}))};if(S){const te="mb-1 block text-[10.5px] font-bold text-muted-foreground",ue="w-full rounded-xl border border-white/[0.14] bg-white/[0.02] px-3 py-1.5 text-[12.5px] text-foreground placeholder:text-muted-foreground
97/70 outline-none transition-colors focus:border-brand/55 dark:bg-black/25";return(0,e.jsxs)("div",{className:st("overflow-hidden rounded-2xl border border-brand/50",Ee),children:[(0,e.jsxs)("div",{className:st("flex items-center justify-between border-b px-4 py-2",se),children:[(0,e.jsxs)("span",{className:st("font-geo text-[10.5px] font-bold uppercase tracking-[0.16em]",F),children:["Cut ",t.cutNumber]}),(0,e.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,e.jsx)("button",{type:"button",onClick:K,className:"rn-btn rn-btn-g is-xs",children:o("취소","キャンセル","Cancel")}),(0,e.jsx)("button",{type:"button",onClick:ie,className:"rn-btn rn-btn-y is-xs",children:o("저장","保存","Save")})]})]}),(0,e.jsxs)("div",{className:"space-y-2.5 px-4 py-3",children:[(0,e.jsxs)("div",{children:[(0,e.jsx)("label",{className:te,children:o("장면 설명","シーン説明","Scene Description")}),(0,e.jsx)("textarea",{value:U.description,onChange:R=>x("description",R.target.value),rows:3,className:st(ue,"py-2 leading-5 resize-none")})]}),(0,e.jsxs)("div",{children:[(0,e.jsx)("label",{className:te,children:o("카메라워크","カメラワーク","Camera Work")}),(0,e.jsx)("input",{value:U.cameraWork,onChange:R=>x("cameraWork",R.target.value),className:ue})]}),(0,e.jsxs)("div",{children:[(0,e.jsx)("label",{className:te,children:o("내레이션","ナレーション","Narration")}),(0,e.jsx)("input",{value:U.narration,onChange:R=>x("narration",R.target.value),className:ue})]}),(0,e.jsxs)("div",{children:[(0,e.jsx)("label",{className:te,children:o("대사","セリフ","Dialogue")}),(0,e.jsx)("input",{value:U.dialogue,onChange:R=>x("dialogue",R.target.value),placeholder:o("없음","なし","None"),className:ue})]}),(0,e.jsxs)("div",{children:[(0,e.jsx)("label",{className:te,children:"BGM / SFX"}),(0,e.jsx)("input",{value:U.bgm,onChange:R=>x("bgm",R.target.value),className:ue})]})]})]})}return(0,e.jsxs)("div",{...n===0?Ve(je.shortsAgentStoryboardCut):{},className:st("group overflow-hidden rounded-xl md:rounded-2xl border transition-colors",Ee,N,l&&"cursor-pointer hover:border-brand/55"),onClick:l?B:void 0,children:[(0,e.jsxs)("div",{className:st("flex items-center justify-between border-b px-3 md:px-4 py-2 md:py-2.5",se),children:[(0,e.jsxs)("span",{className:st("font-geo text-[10px] md:text-[10.5px] font-bold uppercase tracking-[0.16em]",F),children:["Cut ",t.cutNumber]}),(0,e.jsxs)("div",{className:"flex items-center gap-1.5 md:gap-2",children:[l&&(0,e.jsx)(fo,{className:"h-3 w-3 text-muted-foreground md:opacity-0 md:transition-opacity md:group-hover:opacity-100","aria-hidden":!0}),(0,e.jsx)("span",{className:"rounded-full bg-white/[0.08] px-2 md:px-2.5 py-0.5 font-geo text-[10px] md:text-[11px] font-semibold text-foreground/80",children:t.timeRange})]})]}),(0,e.jsxs)("div",{className:"space-y-2 md:space-y-2.5 px-3 md:px-4 py-2.5 md:py-3",children:[t.description&&(0,e.jsx)("p",{className:"text-[12px] md:text-[13px] leading-5 text-foreground",children:t.description}),(0,e.jsxs)("div",{className:"space-y-1 md:space-y-1.5 pt-0.5",children:[t.cameraWork&&(0,e.jsxs)("div",{className:"flex items-start gap-2",children:[(0,e.jsx)("small",{className:_,children:o("카메라","カメラ","Camera")}),(0,e.jsx)("span",{className:"text-[11px] md:text-[12px] leading-5 text-muted-foreground",children:t.cameraWork})]}),H&&(0,e.jsxs)("div",{className:"flex items-start gap-2",children:[(0,e.jsx)("small",{className:_,children:o("내레이션","ナレ","VO")}),(0,e.jsxs)("span",{className:"text-[11px] md:text-[12px] leading-5 text-foreground/85 italic",children:['"',t.narration,'"']})]}),ee&&(0,e.jsxs)("div",{className:"flex items-start gap-2",children:[(0,e.jsx)("small",{className:_,children:o("대사","セリフ","Line")}),(0,e.jsxs)("span",{className:"text-[11px] md:text-[12px] leading-5 text-foreground/85 italic",children:['"',t.dialogue,'"']})]}),t.bgm&&(0,e.jsxs)("div",{className:"flex items-start gap-2",children:[(0,e.jsx)("small",{className:_,children:o("소리","サウンド","Sound")}),(0,e.jsx)("span",{className:"text-[11px] md:text-[12px] leading-5 text-muted-foreground",children:t.bgm})]})]})]})]})},Hi=({draft:t,language:r,videoDuration:n=15,editable:l=!1,onCutSave:p,onCutEditingChange:h})=>{const o=ta(r);return(0,e.jsxs)("div",{...Ve(je.shortsAgentStoryboard),className:"mka-card mt-4 md:mt-5 mb-2 !rounded-2xl md:!rounded-[22px]",children:[(0,e.jsxs)("div",{className:"border-b border-border px-3 md:px-5 py-3 md:py-4",children:[(0,e.jsx)("p",{className:"rn-eyebrow is-y !text-[10px] md:!text-[10.5px]",children:o("스토리보드","ストーリーボード","Storyboard")}),(0,e.jsx)("h4",{className:"mt-1.5 truncate font-title text-[16px] md:text-[19px] font-black leading-tight text-foreground",children:t.title})]}),(0,e.jsxs)("div",{className:"space-y-3 md:space-y-4 p-3 md:p-5",children:[t.conceptSummary?.trim()&&(0,e.jsxs)("div",{className:"mka-box px-3 md:px-4 py-2.5 md:py-3",children:[(0,e.jsx)("p",{className:"mka-lab mb-1 md:mb-1.5",children:o("컨셉","コンセプト","Concept")}),(0,e.jsx)("p",{className:"text-[12px] md:text-[13px] leading-5 text-foreground
97/85",children:t.conceptSummary})]}),t.cuts&&t.cuts.length>0&&(0,e.jsxs)("div",{className:"space-y-2",children:[(0,e.jsx)("p",{className:"mka-lab",children:o(`${n}초 스토리보드`,`${n}秒ストーリーボード`,`${n}s Storyboard`)}),(0,e.jsx)("div",{className:"space-y-2",children:t.cuts.map((S,v)=>(0,e.jsx)(Vi,{cut:S,language:r,index:v,editable:l,onSave:U=>p?.(S.cutNumber,U),onEditingChange:h},S.cutNumber))})]}),!t.cuts?.length&&t.storyboard?.trim()&&(0,e.jsxs)("div",{className:"mka-box px-4 py-3",children:[(0,e.jsx)("p",{className:"mka-lab mb-1.5",children:o(`${n}초 스토리보드`,`${n}秒ストーリーボード`,`${n}s Storyboard`)}),(0,e.jsx)("p",{className:"whitespace-pre-wrap text-[13px] leading-5 text-foreground/85",children:t.storyboard})]}),(t.narration?.trim()||t.dialogue?.trim()||t.directorNote?.trim())&&(0,e.jsxs)("div",{className:"grid gap-2 sm:grid-cols-2",children:[t.narration?.trim()&&(0,e.jsxs)("div",{className:"mka-box px-3 md:px-4 py-2.5 md:py-3",children:[(0,e.jsx)("p",{className:"mka-lab mb-1 md:mb-1.5",children:o("내레이션","ナレーション","Narration")}),(0,e.jsxs)("p",{className:"text-[11px] md:text-[12px] leading-5 text-foreground/85 italic",children:['"',t.narration,'"']})]}),t.dialogue?.trim()&&(0,e.jsxs)("div",{className:"mka-box px-3 md:px-4 py-2.5 md:py-3",children:[(0,e.jsx)("p",{className:"mka-lab mb-1 md:mb-1.5",children:o("배우 대사","俳優セリフ","Actor Dialogue")}),(0,e.jsxs)("p",{className:"text-[11px] md:text-[12px] leading-5 text-foreground/85 italic",children:['"',t.dialogue,'"']})]})]})]})]})},zi=(t,r)=>t==="hero"?r==="ko"?{title:"대표 이미지 생성 중",description:"템플릿 이미지와 제품 이미지를 묶어 대표 컷을 만들고 있습니다."}:r==="ja"?{title:"ヒーロー画像を生成中",description:"テンプレートと製品画像を組み合わせてヒーローフレームを作成しています。"}:{title:"Creating Hero Image",description:"Combining the template and product images into a representative hero frame."}:t==="mood_select"?r==="ko"?{title:"분위기/컨셉 선택",description:"대표 이미지가 완성되었습니다. 어떤 분위기의 쇼츠를 만들지 선택해 주세요."}:r==="ja"?{title:"ムード/コンセプト選択",description:"ヒーロー画像が完成しました。どんな雰囲気のショートを作るか選んでください。"}:{title:"Select Mood & Concept",description:"The hero image is ready. Choose what mood and concept for the 쇼츠."}:t==="drafting"?r==="ko"?{title:"스토리보드 구상 중",description:"선택한 분위기를 바탕으로 쇼츠 ì´
97ˆì•ˆì„ 잡고 있습니다."}:r==="ja"?{title:"ストーリーボード構想中",description:"選択したムードをもとにショートの草案を作成しています。"}:{title:"Drafting Storyboard",description:"Building a 15-second 쇼츠 concept based on the selected mood."}:t==="generating"?r==="ko"?{title:"영상 생성 중",description:"확정된 스토리보드를 기반으로 영상을 생성하고 있습니다."}:r==="ja"?{title:"動画を生成中",description:"確定したストーリーボードをもとに動画を生成しています。"}:{title:"Generating Video",description:"The approved storyboard is being used to generate your video."}:t==="result"?r==="ko"?{title:"최종 영상 완료",description:"완성된 영상을 바로 확인할 수 있습니다."}:r==="ja"?{title:"最終動画完了",description:"完成した動画をすぐ確認できます。"}:{title:"Video Ready",description:"Your final video is ready to preview."}:t==="error"?r==="ko"?{title:"준비 중 문제가 생겼습니다",description:"아래 메시지를 확인한 뒤 다시 시도해 주세요."}:r==="ja"?{title:"準備中に問題が発生しました",description:"下のメッセージを確認してからもう一度お試しください。"}:{title:"Something Went Wrong",description:"Check the message below and try again."}:r==="ko"?{title:"스토리보드 협의 중",description:"에이전트와 대화하면서 쇼츠 스토리보드를 다듬고 있습니다."}:r==="ja"?{title:"ストーリーボード協議中",description:"エージェントと会話しながらショートストーリーボードを練っています。"}:{title:"Refining Storyboard",description:"Refining the 쇼츠 storyboard with the agent through chat."},qi=({language:t,aspectRatio:r="9:16"})=>{const n=ta(t),[l,p]=(0,s.useState)(0);(0,s.useEffect)(()=>{const D=Date.now(),I=setInterval(()=>p(Math.floor((Date.now()-D)/1e3)),500);return()=>clearInterval(I)},[]);const h=l<25?Math.min(75,Math.round(l/25*75)):Math.min(99,75+Math.round((l-25)/60*24)),o=l>60,S=l>90,v=125.66,U=v*(1-h/100);return(0,e.jsxs)("div",{className:"mka-card w-full md:max-w-[240px]",children:[(0,e.jsxs)("div",{className:"relative w-full overflow-hidden bg-zinc-900 md:aspect-[var(--hero-ar)]",style:{"--hero-ar":String(r).replace(":"," / ")},children:[(0,e.jsx)("div",{className:"absolute inset-0 -translate-x-full animate-[shimmer_1.6s_infinite] bg-gradient-to-r from-transparent via-white/[0.06] to-transparent"}),(0,e.jsxs)("div",{className:"flex items-center gap-3 px-4 py-4 md:absolute md:inset-0 md:flex-col md:justify-center md:p-0",children:[(0,e.jsxs)("div",{className:"relative flex h-12 w-12 md:h-16 md:w-16 shrink-0 items-center justify-center",children:[(0,e.jsxs)("svg",{className:"absolute inset-0 -rotate-90",viewBox:"0 0 48 48",children:[(0,e.jsx)("circle",{cx:"24",cy:"24",r:"20",fill:"none",style:{stroke:"rgb(var(--c-white) / 0.1)"},strokeWidth:"3"}),(0,e.jsx)("circle",{cx:"24",cy:"24",r:"20",fill:"none",stroke:"#FFE600",strokeWidth:"3",strokeLinecap:"round",strokeDasharray:v,strokeDashoffset:U,style:{transition:"stroke-dashoffset 0.5s ease-out"}})]}),(0,e.jsxs)("span",{className:"font-geo text-[12px] md:text-[13px] font-bold tabular-nums text-foreground",children:[h,"%"]})]}),(0,e.jsxs)("div",{className:"min-w-0 flex-1 space-y-1 text-left md:flex-none md:space-y-3 md:text-center",children:[(0,e.jsx)("p",{className:"text-[13px] font-semibold text-foreground",children:n("대표 이미지 생성 중...","ヒーロー画像を生成中...","Generating hero image...")}),(0,e.jsx)("p",{className:"text-[11px] text-muted-foreground",children:S?n(`${l}초 경과 — 평소보다 많이 걸리고 있어요. 조금만 더 기다려 주세요.`,`${l}秒経過 — 通常より時間がかかっています。もう少しお待ちください。`,`${l}s elapsed — taking longer than usual. Hang in there.`):o?n(`${l}초 경과 — 조금 더 걸리는 중...`,`${l}秒経過 — もう少しかかっています...`,`${l}s elapsed — taking a bit longer...`):n("템플릿 + 제품 이미지를 합성하고 있습니다","テンプレートと製品画像を合成しています","Compositing template and product images")})]})]})]}),(0,e.jsxs)("div",{className:"space-y-2 px-4 py-3",children:[(0,e.jsx)("div",{className:"mka-track h-1.5 w-full",children:(0,e.jsx)("div",{className:"mka-fill",style:{width:`${h}%`}})}),(0,e.jsxs)("div",{className:"flex items-center justify-between text-[10.5px] text-muted-foreground",children:[(0,e.jsx)("span",{children:h<100?n("진행 중","進行中","In progress"):n("완료","完了","Done")}),(0,e.jsxs)("span",{className:"font-geo tabular-nums",children:[l,"s"]}
97)]})]})]})},en=t=>t&&t.replace(/\s*\(?\d{1,3}\s*%\)?\s*$/,"").trim()||null,Bi=({progress:t,message:r,language:n,onCancel:l})=>{const p=ta(n),h=Math.min(Math.max(t,0),99),o=2*Math.PI*20,S=o-h/100*o;return(0,e.jsxs)("div",{className:"mka-card w-full !rounded-xl md:!rounded-2xl",children:[(0,e.jsxs)("div",{className:"flex items-center gap-3 md:gap-4 px-3 md:px-5 py-3 md:py-4",children:[(0,e.jsxs)("div",{className:"relative flex h-12 w-12 md:h-14 md:w-14 shrink-0 items-center justify-center",children:[(0,e.jsxs)("svg",{className:"absolute inset-0 -rotate-90",viewBox:"0 0 48 48",children:[(0,e.jsx)("circle",{cx:"24",cy:"24",r:"20",fill:"none",style:{stroke:"rgb(var(--c-white) / 0.1)"},strokeWidth:"3"}),(0,e.jsx)("circle",{cx:"24",cy:"24",r:"20",fill:"none",stroke:"#FFE600",strokeWidth:"3",strokeLinecap:"round",strokeDasharray:o,strokeDashoffset:S,className:"transition-all duration-700"})]}),(0,e.jsxs)("span",{className:"font-geo text-xs font-bold text-foreground",children:[h,"%"]})]}),(0,e.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,e.jsx)("p",{className:"mb-1 text-[10.5px] font-bold uppercase tracking-[0.16em] text-brand-ink",children:p("영상 생성 중","動画を生成中","Generating Video")}),(0,e.jsx)("p",{className:"truncate text-sm text-foreground/85",children:r}),(0,e.jsx)("p",{className:"mt-0.5 text-[11px] text-muted-foreground",children:p("보통 1~2분이면 완성됩니다","通常1〜2分で完成します","Usually done in 1-2 minutes")})]}),l&&(0,e.jsx)("button",{type:"button",onClick:l,className:"rn-btn rn-btn-g is-sm shrink-0",children:p("취소","キャンセル","Cancel")})]}),(0,e.jsx)("div",{className:"h-1 w-full bg-white/[0.06]",children:(0,e.jsx)("div",{className:"h-full bg-brand transition-all duration-700",style:{width:`${h}%`}})})]})},Ki=async(t,r)=>{try{const n=await(await fetch(t)).blob(),l=URL.createObjectURL(n),p=document.createElement("a");p.href=l,p.download=r,document.body.appendChild(p),p.click(),document.body.removeChild(p),URL.revokeObjectURL(l)}catch{window.open(t,"_blank","noopener,noreferrer")}},Wi=({videoUrl:t,language:r,userId:n,sourceTaskId:l,onReviseVideo:p,onGenerateOnceMore:h,onSetShowcaseShare:o,onDone:S})=>{const v=ta(r),U=()=>Ki(t,`ad-video-${Date.now()}.mp4`),[D,I]=s.useState(!1),[f,H]=s.useState(!1);s.useEffect(()=>{H(!1)},[t]);const ee=s.useCallback(async()=>{if(!t||D)return;const Ee=!f;I(!0),H(Ee);try{await o?.(t,Ee)}catch{H(!Ee)}finally{I(!1)}},[t,f,D,o]);return(0,e.jsxs)("div",{...Ve(je.shortsAgentResult),className:"mka-card w-full",children:[(0,e.jsx)("div",{className:"relative aspect-video w-full overflow-hidden bg-black",children:(0,e.jsx)("video",{src:t,controls:!0,autoPlay:!0,loop:!0,muted:!0,playsInline:!0,className:"h-full w-full object-contain"})}),(0,e.jsxs)("div",{className:"px-4 py-3 space-y-3",children:[(0,e.jsx)("p",{className:"text-xs font-bold text-brand-ink",children:v("영상이 완성되었습니다","動画が完成しました","Video is ready")}),(0,e.jsxs)("div",{className:"flex flex-wrap gap-2",children:[p&&(0,e.jsx)("button",{type:"button",...Ve(je.shortsAgentEditStoryboard),onClick:p,className:"rn-btn rn-btn-g is-sm",children:v("영상 수정","動画を修正","Revise video")}),h&&(0,e.jsx)("button",{type:"button",onClick:h,title:v("같은 이미지·같은 프롬프트로 영상만 한 번 더 생성합니다. 이전 결과는 위에 그대로 남아요.","同じ画像・同じプロンプトで動画だけもう一度生成します。以前の結果は上にそのまま残ります。","Generate one more video from the same image and prompt. Previous results stay above."),className:"rn-btn rn-btn-g is-sm",children:v("한 번 더 생성","もう一度生成","Generate one more")}),o&&(0,e.jsx)("button",{type:"button",onClick:ee,disabled:D,title:v("인플루언서 갤러리에 공유하면 5크레딧을 드려요. 공유한 영상은 템플릿 카드에서 재생됩니다.","インフルエンサーギャラリーに共有すると5クレジット付与。共有した動画はテンプレートカードで再生されます。","Share to the influencer gallery and get 5 credits. Shared videos play on the template card."),className:st("rn-btn is-sm",f?"rn-btn-o":"rn-btn-y"),children:D?v("처리 중...","処理中...","Working..."):f?v("공유됨 · 공유 취소","共有済み · 取り消し","Shared · Undo"):v("공유하고 5크레딧 받기","共有して5クレジット","Share & get 5 credits")}),(0,e.jsx)("button",{type:"button",onClick:U,className:"rn-btn rn-btn-g is-sm",children:v("다운로드","ダウンロード","Download")}),S&&(0,e.jsx)("button",{type:"button",onClick:S,className:"rn-btn rn-btn-g is-sm",children:v("완료","完了","Done")})]})]})]})},Ji=({onSetShowcaseShare:t,open:r,visible:n,onClose:l,onEndSession:p,onStateChange:h,onGenerateStart:o,session:S,language:v,pollingHistory:U,generationTasks:D,createRepresentativeImage:I,uploadImages:f,startSeedanceGeneration:H,userId:ee,onTaskComplete:Ee,onSessionCompleted:N,videoCreditCost480p:F,videoCreditCost720p:se=75.6,videoCreditCost1080p:_=187.2,videoCreditCost4k:B=388.8,onCheckCredit:ie,demoFixture:K})=>{const x=ta(v),te=S?.sessionId?`shorts-agent-input:${S.sessionId}
97`:null,[ue,R]=(0,s.useState)(()=>{if(!te)return"";try{return localStorage.getItem(te)||""}catch{return""}}),[$,O]=(0,s.useState)(!1),[G,Oe]=(0,s.useState)(""),[fe,_e]=(0,s.useState)(""),[Ne,P]=(0,s.useState)(""),[Ce,Re]=(0,s.useState)(!1),[We,Ie]=(0,s.useState)(!1),[q,V]=(0,s.useState)(!1),[X,ge]=(0,s.useState)(!1),[Qe,ht]=(0,s.useState)(null),[$t,ft]=(0,s.useState)(null),[W,Le]=(0,s.useState)(null),[kt,De]=(0,s.useState)(!1),yt=(0,s.useRef)("720p"),[rt,A]=(0,s.useState)(!1),[ye,Ze]=(0,s.useState)(!1);(0,s.useEffect)(()=>{if(te)try{ue?localStorage.setItem(te,ue):localStorage.removeItem(te)}catch{}},[ue,te]);const Lt=(0,s.useRef)(null),ut=(0,s.useRef)(null),at=(0,s.useCallback)(()=>{const y=ut.current;return y&&y.scrollHeight>y.clientHeight+1?y:qt.current??y},[]),qt=(0,s.useRef)(null),{phase:re,messages:Me,draft:ce,heroImageUrl:gt,finalVideoUrl:Ae,error:bt,isThinking:Ue,isAnalyzing:Nt,streamingPhase:Mt,streamingCutNumber:wt,selectedMood:nr,canSendMessage:Bt,canGenerateVideo:Je,canSelectMood:me,canRegenerateHero:Fe,nextMessageCost:Qt,moodPresets:vr,brandPronunciation:et,brandPronunciationSkipped:xt,activeTaskProgress:kr,activeTaskStatus:mt,activeTaskMessage:gr,sendMessage:Ye,selectMood:_t,updateBrandPronunciation:wr,confirmBrandPronunciation:Vr,markBrandPronunciationSkipped:_r,generateVideo:Ct,regenerateVideo:Ir,editStoryboard:Ft,askVideoRevision:ua,videoRevisionAsked:Gt,isAnswering:ma,generateRequest:or,clearGenerateRequest:Ar,updateCut:it,regenerateHero:ir,restartConcept:Vt,cancelGeneration:Kt,jumpToResultForTutorial:pt,showProgressForTutorial:Pt,rewindToDiscussionForTutorial:Zt}=Li({open:r,session:S,language:v,pollingHistory:U,generationTasks:D,createRepresentativeImage:I,uploadImages:f,startSeedanceGeneration:H,onTaskComplete:Ee,onSessionCompleted:N,demoFixture:K,userId:ee}),Sr=(0,s.useMemo)(()=>Me.reduce((y,j,M)=>j.role==="agent"?M:y,-1),[Me]),lr=(0,s.useMemo)(()=>Me.reduce((y,j,M)=>j.videoUrl?M:y,-1),[Me]),It=(0,s.useMemo)(()=>{const y=Me[Me.length-1];return y?.role==="agent"&&y.storyboardFollowUp?y:null},[Me]),[pa,Ut]=(0,s.useState)(0),cr=(0,s.useCallback)(y=>{Ut(j=>Math.max(0,j+y))},[]),vt=pa>0,Rr=(0,s.useRef)(Me.length),dr=(0,s.useCallback)(y=>{const j=at();j&&(typeof j.scrollTo=="function"?j.scrollTo({top:j.scrollHeight,behavior:y?"smooth":"auto"}):j.scrollTop=j.scrollHeight)},[at]);(0,s.useEffect)(()=>{const y=Me.length>Rr.current;if(Rr.current=Me.length,vt)return;if(y){dr(!Mt);return}const j=at();j&&j.scrollHeight-j.scrollTop-j.clientHeight<200&&dr(!1)},[Me,ce,Ae,Ue,Nt,Mt,wt,bt,vt,dr]),(0,s.useEffect)(()=>{const y=ut.current?.firstElementChild;if(!y||typeof ResizeObserver>"u")return;const j=new ResizeObserver(()=>{if(vt)return;const M=at();M&&M.scrollHeight-M.scrollTop-M.clientHeight<200&&dr(!1)});return j.observe(y),()=>j.disconnect()},[vt,r,re,dr,at]);const ur=(0,s.useMemo)(()=>zi(re,v),[v,re]);(0,s.useEffect)(()=>{!r||!S||!h||h({phase:re,title:ur.title,description:ur.description,draftTitle:ce?.title,heroImageUrl:gt,finalVideoUrl:Ae,error:bt,isThinking:Ue,canGenerateVideo:Je})},[Je,ce?.title,bt,Ae,gt,Ue,h,r,re,ur.description,ur.title,S]),(0,s.useEffect)(()=>{const y=qt.current;if(!y)return;const j=Array.from(y.querySelectorAll("video, audio"));n?j.forEach(M=>{if(M.loop)try{M.muted=!0,M.play().catch(()=>{})}catch{}}):j.forEach(M=>{try{M.pause()}catch{}})},[n,Ae,Me.length]);const Hr=(0,s.useCallback)(y=>{Ue||!me||ht(y)},[me,Ue]),Wt=(0,s.useCallback)(()=>{const y=Qe;!y||Ue||!me||(ht(null),_t(y))},[me,Ue,Qe,_t]);if(fn((0,s.useCallback)(()=>{r&&l()},[r,l])),hn((0,s.useCallback)(y=>{if(ja()){if(y.includes(je.shortsAgentMoodConfirm)||ht(null),y.includes(je.shortsAgentGenerateConfirm)||(ft(null),Le(null),A(!1),Ze(!1)),[je.shortsAgentStoryboard,je.shortsAgentStoryboardCut,je.shortsAgentChat,je.shortsAgentNewConcept,je.shortsAgentGenerate,je.shortsAgentGenerateConfirm].some(j=>y.includes(j))){Zt();return}if(y.includes(je.shortsAgentProgress)&&re==="result"){Pt();return}y.includes(je.shortsAgentResult)&&pt()}},[re,Zt,pt,Pt])),(0,s.useEffect)(()=>{!or||re!=="discussion"||!Je||(Le(or.quality),Ar())},[or,re,Je,Ar]),!r||!S)return null;const i=async y=>{const j=(y??ue).trim();if(j){if(!y&&re==="mood_select"&&gt){ft(j);return}R(""),await Ye(j)}},m=y=>y==="4k"?B:y==="1080p"?_:y==="480p"?F??se:se,g=async(y="720p")=>{Je&&(ie&&!await ie(m(y))||(yt.current=y,o?.(),await Ct(y)))},b=async y=>{ie&&!await ie(m(y))||(yt.current=y,o?.(),await Ir(y))},C=W==="4k"?B:W==="1080p"?_:W==="480p"?F:se,T=$t||W||rt||ye,E=()=>{ft(null),Le(null),De(!1),A(!1),Ze(!1)},z=()=>{if($t){const y=$t;E(),R(""),Ye(y);return}if(W){const y=W,j=kt;E(),j?b(y):g(y);return}if(rt){E(),ir();return}ye&&(E(),Vt())};return(0,e.jsxs)("div",{ref:qt,"aria-hidden":!n,className:st("mka-scrim fixed inset-0 z-[70] flex items-start md:items-center justify-center md:p-6 transition-opacity duration-200 max-md:overflow-y-auto",n?"opacity-100":"pointer-events-none opacity-0"),children:[(0,e.jsxs)("div",{className:"mka-shell relative flex flex-col md:flex-row max-md:h-auto max-md:min-h-full md:h-[88vh] w-full max-w-[1440px] md:overflow-hidden md:rounded-[28px]",children:[(0,e.jsx)("div",{className:"max-md:sticky max-md:top-0 max-md:h-0 max-md:overflow-visible max-md:z-20 md:absolute md:right-4 md:top-4 md:z-10",children:(0,e.jsxs)("div",{className:"absolute right-3 top-3 md:static flex items-center gap-1.5",children:[(0,e.jsx)("button",{type:"button",onClick:l,title:x("최소화","最小化","Minim
97ize"),"aria-label":x("에이전트 최소화","エージェントを最小化","Minimize agent"),className:"mka-x",children:(0,e.jsx)(ho,{"aria-hidden":!0})}),p&&(0,e.jsx)("button",{type:"button",onClick:()=>V(!0),title:x("세션 종료","セッション終了","End Session"),"aria-label":x("세션 종료","セッション終了","End session"),className:"mka-x",children:(0,e.jsx)(Zr,{"aria-hidden":!0})})]})}),(0,e.jsxs)("div",{className:"mka-side flex w-full md:w-[34%] md:min-w-[320px] shrink-0 md:shrink flex-col max-md:overflow-visible md:overflow-y-auto border-b md:border-b-0 md:border-r",children:[(0,e.jsxs)("div",{className:"px-4 md:px-6 pt-3 md:pt-6 pb-3 md:pb-5 pr-24 md:pr-6",children:[(0,e.jsx)("p",{className:"rn-eyebrow is-y max-md:!text-[10px] max-md:!tracking-[0.16em]",children:(0,e.jsx)("span",{className:"truncate",children:x("쇼츠 에이전트","ショートエージェント","Shorts Agent")})}),(0,e.jsx)("h2",{className:"mka-title",children:ur.title}),(0,e.jsx)("p",{className:"mka-desc line-clamp-2 md:line-clamp-none",children:ur.description})]}),(0,e.jsx)("div",{className:"px-4 md:px-6",children:(0,e.jsxs)("div",{className:"mka-card !rounded-2xl",children:[(0,e.jsx)("div",{className:"flex justify-center p-2.5 md:p-3",children:(0,e.jsxs)("div",{...Ve(je.shortsAgentHero),className:"relative aspect-[9/16] w-full max-w-[180px] md:max-w-[240px] overflow-hidden rounded-xl bg-zinc-900",children:[Ae?(0,e.jsx)("video",{src:Ae,controls:!0,autoPlay:!0,loop:!0,muted:!0,playsInline:!0,className:"h-full w-full object-cover"}):gt?(0,e.jsx)("img",{src:gt,alt:S.preset.name,className:"h-full w-full object-cover"}):S.preset.previewImage?(0,e.jsx)("img",{src:S.preset.previewImage,alt:S.preset.name,className:"h-full w-full object-cover opacity-80"}):(0,e.jsx)("div",{className:"h-full w-full",style:{background:S.preset.previewGradient}}),!Ae&&re==="hero"&&!gt&&(0,e.jsxs)("div",{className:"absolute inset-0 flex flex-col items-center justify-center bg-black/50 backdrop-blur-sm",children:[(0,e.jsx)("span",{className:"mka-spin",style:{"--sz":"28px"}}),(0,e.jsx)("p",{className:"mt-4 text-sm font-semibold text-[#fff]",children:x("대표 이미지 준비 중","ヒーロー画像を準備中","Preparing hero image")})]}),!Ae&&Nt&&!!gt&&(0,e.jsxs)("div",{className:"absolute bottom-3 left-3 flex items-center gap-1.5 rounded-full bg-black/60 px-3 py-1.5 text-xs font-semibold text-[#fff] backdrop-blur-sm",children:[(0,e.jsx)("span",{className:"mka-spin",style:{"--sz":"12px"}}),x("이미지 분석 중","画像を分析中","Analyzing image")]}),Fe&&!Ae&&re==="mood_select"&&(0,e.jsx)("button",{type:"button",onClick:()=>A(!0),className:"rn-glass absolute bottom-3 right-3 inline-flex h-8 items-center rounded-full px-3.5 text-xs font-bold transition-colors hover:bg-black/75",children:x("이미지 재생성","再生成","Regenerate")}),re==="generating"&&(0,e.jsxs)("div",{className:"absolute inset-0 flex flex-col items-center justify-center bg-black/65 backdrop-blur-sm",children:[(0,e.jsxs)("div",{className:"relative flex h-24 w-24 items-center justify-center",children:[(0,e.jsxs)("svg",{className:"-rotate-90",width:"96",height:"96",viewBox:"0 0 96 96",children:[(0,e.jsx)("circle",{cx:"48",cy:"48",r:"42",fill:"none",stroke:"rgba(255,255,255,0.14)",strokeWidth:"5"}),(0,e.jsx)("circle",{cx:"48",cy:"48",r:"42",fill:"none",stroke:"#FFE600",strokeWidth:"5",strokeLinecap:"round",strokeDasharray:2*Math.PI*42,strokeDashoffset:2*Math.PI*42-(kr??0)/100*2*Math.PI*42,className:"transition-all duration-500"})]}),(0,e.jsxs)("span",{className:"absolute font-geo text-2xl font-bold text-[#fff]",children:[kr!=null?Math.min(kr,99):0,(0,e.jsx)("span",{className:"text-sm text-[#fff]/70",children:"%"})]})]}),(0,e.jsx)("p",{className:"mt-4 text-sm font-semibold text-[#fff]",children:en(gr)||x("영상 생성 중","動画を生成中","Generating video")}),(0,e.jsx)("p",{className:"mt-1 text-xs text-[#fff]/70",children:x("보통 1~2분이면 완성됩니다","通常1〜2分で完成します","Usually done in 1-2 minutes")})]})]})}),(0,e.jsxs)("div",{className:"hidden md:block space-y-3.5 p-4",children:[(0,e.jsxs)("div",{children:[(0,e.jsx)("p",{className:"mka-lab",children:x("템플릿","テンプレート","Template")}),(0,e.jsx)("div",{className:"mt-1 text-sm font-bold text-foreground",children:S.preset.name}),S.preset.description&&(0,e.jsx)("p",{className:"mt-0.5 text-xs leading-5 text-muted-foreground",children:S.preset.description})]}),(0,e.jsxs)("div",{children:[(0,e.jsx)("p",{className:"mka-lab",children:x("제품 특장점","製品の特長","Product Highlights")}),(0,e.jsx)("p",{className:"mt-1 whitespace-pre-wrap text-sm leading-6 text-foreground
97/85",children:S.highlights.trim()||x("추가 입력 없음","追加入力なし","No extra highlights provided")})]})]})]})}),(0,e.jsx)("div",{className:"mt-2 md:mt-5 px-4 md:px-6 pb-3 md:pb-6",children:(0,e.jsxs)("div",{...Ve(je.shortsAgentPhasePanel),className:"mka-box !rounded-xl md:!rounded-2xl p-2.5 md:p-4",children:[(0,e.jsx)("p",{className:"mka-lab",children:x("현재 진행","現在の進捗","Current Progress")}),(0,e.jsx)("div",{className:"mka-track mt-2 md:mt-3 h-1.5",children:(0,e.jsx)("div",{className:st("mka-fill",re==="hero"&&"w-[18%]",re==="mood_select"&&"w-[33%]",re==="drafting"&&"w-[50%]",re==="discussion"&&"w-[72%]",re==="generating"&&"w-[88%]",re==="result"&&"w-full",re==="error"&&"w-[58%]",re==="idle"&&"w-0")})})]})})]}),(0,e.jsxs)("div",{className:"mka-main flex min-h-0 max-md:shrink-0 min-w-0 flex-1 flex-col",children:[(0,e.jsxs)("div",{...Ve(je.shortsAgentPanelHeader),className:"border-b border-border px-4 md:px-6 py-2.5 md:py-5 md:pr-28",children:[(0,e.jsx)("p",{className:"rn-eyebrow max-md:!text-[10px] max-md:!tracking-[0.16em]",children:x("스토리보드 협의","ストーリーボード協議","Storyboard Discussion")}),(0,e.jsx)("p",{className:"hidden md:block mt-2 text-[13.5px] leading-6 text-muted-foreground",children:re==="mood_select"?x("아래 분위기/컨셉 중 하나를 선택하면, 에이전트가 해당 분위기로 쇼츠 스토리보드를 구성합니다.","以下のムード/コンセプトから一つ選ぶと、エージェントがそのムードでショートストーリーボードを構成します。","Select a mood/concept below, and the agent will craft a 쇼츠 storyboard in that style."):x("대사, 내레이션, 전개, 엔딩 CTA까지 자연스럽게 수정 요청하면 에이전트가 쇼츠 초안을 바로 반영합니다.","セリフ、ナレーション、展開、エンディングCTAまで自然に修正依頼するとエージェントがショート草案にすぐ反映します。","Ask for changes to the dialogue, narration, pacing, or CTA, and the agent will update the 쇼츠 draft.")})]}),(0,e.jsx)("div",{ref:ut,className:"min-h-0 max-md:shrink-0 flex-1 max-md:overflow-visible md:overflow-y-auto px-4 md:px-6 py-3 md:py-5",children:(0,e.jsxs)("div",{className:"space-y-3",children:[Me.map((y,j)=>y.storyboardFollowUp?null:(0,e.jsxs)(s.Fragment,{children:[y.content?.trim()&&y.role==="agent"&&(0,e.jsx)(Hs,{text:y.content,language:v,typewriter:j===Sr}),y.content?.trim()&&y.role==="user"&&(0,e.jsx)(ci,{children:y.content}),y.content?.trim()&&y.role==="system"&&(0,e.jsx)("div",{className:"mka-msg is-sys w-fit max-w-[90%]",children:(0,e.jsx)("p",{className:"whitespace-pre-wrap",children:y.content})}),y.imageUrl&&(0,e.jsx)("div",{className:"mka-card w-fit max-w-full",children:(0,e.jsx)("img",{src:y.imageUrl,alt:x("대표 이미지","ヒーロー画像","Hero image"),className:"block max-h-[clamp(280px,48vh,460px)] w-auto max-w-full object-contain"})}),y.videoUrl&&(0,e.jsx)(Wi,{videoUrl:y.videoUrl,language:v,userId:ee,sourceTaskId:y.sourceTaskId,onReviseVideo:re==="result"&&j===lr?()=>ja()?Ft():ua():void 0,onDone:re==="result"?()=>p?V(!0):l():void 0,onSetShowcaseShare:re==="result"?t:void 0,onGenerateOnceMore:re==="result"&&j===lr&&ce?.finalPrompt?()=>{De(!0),Le(yt.current)}:void 0}),y.role==="agent"&&y.moodPresets&&y.moodPresets.length>0&&me&&et&&et.koreanReading&&(0,e.jsx)("div",{className:"mka-box px-3 py-2.5",children:$?(0,e.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,e.jsx)("span",{className:"mka-lab",children:x("내레이션 발음","ナレーション発音","Narration reading")}),et.displayName&&(0,e.jsxs)("span",{className:"text-xs text-muted-foreground",children:[(0,e.jsx)("span",{className:"font-geo",children:et.displayName}),(0,e.jsx)("span",{className:"mx-1.5",children:"→"})]}),(0,e.jsx)("input",{type:"text",value:G,onChange:M=>Oe(M.target.value),onKeyDown:M=>{if(M.key==="Enter")M.preventDefault(),G.trim()&&(wr(G),O(!1));else if(M.key==="Escape"){if(G.trim()&&G.trim()!==et?.koreanReading?.trim()&&!window.confirm(x("변경 사항을 저장하지 않고 닫을까요?","変更内容を保存せずに閉じますか?","Discard unsaved changes?")))return;O(!1)}},placeholder:x("예: 써마지 에프엘엑스","例: サーマジFLX","e.g. Thermage FLX"),autoFocus:!0,className:"mka-ta !py-1.5 !text-sm w-full sm:flex-1 sm:min-w-[160px] sm:w-auto"}),(0,e.jsx)("button",{type:"button",onClick:()=>{G.trim()&&(wr(G),O(!1))},disabled:!G.trim(),className:"rn-btn rn-btn-y is-xs",children:x("확정","確定","Save")}),(0,e.jsx)("button",{type:"button",onClick:()=>O(!1),className:"rn-btn rn-btn-g is-xs",children:x("취소","キャンセル","Cancel")})]}):(0,e.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,e.jsx)("span",{className:"mka-lab",children:x("내레이션 발음","ナレーション発音","Narration reading")}),et.displayName&&(0,e.jsxs)("span",{className:"text-xs text-muted-foreground",children:[(0,e.jsx)("span",{className:"font-geo",children:et.displayName}),(0,e.jsx)("span",{className:"mx-1.5",children:"→"})]}),(0,e.jsx)("span",{className:"rounded-lg bg-brand/[0.14] px-2.5 py-0.5 text-sm font-bold text-brand-ink",children:et.koreanReading}),(0,e.jsx)("button",{type:"button",onClick:()=>{Oe(et.koreanReading),O(!0)},className:"rn-btn rn-btn-g is-xs ml-auto",children:x("수정","修正","Edit")}),et.alternatives&&et.alternatives.length>0&&(0,e.jsxs)("div",{className:"mt-1.5 flex w-full flex-wrap items-center gap-1.5",children:[(0,e.jsx)("span",{className:"text-[10.5px] text-muted-foreground",children:x("다른 발음:","他の発音:","Alternatives:")}),et.alternatives.map(M=>(0,e.jsx)("button",{type:"button",onClick:()=>wr(M),className:"rn-btn rn-btn-g is-xs",children:M},M))]}),et.confidence==="low"&&(0,e.jsx)("p",{className:"mka-warn mt-1 w-full px-2.5 py-1.5 text-[11px] font-semibold",children:x("발음이 불확실해요. 확인해 주세요.","発音が不確かです。確認してください。","Pronunciation uncertain — please confirm.")})]})}),y.role==="agent"&&y.moodPresets&&y.moodPresets.length>0&&me&&(0,e.jsxs)("div",{...Ve(je.shortsAgentMoodGrid),className:"ac-chips",children:[(0,e.jsx)("small",{children:x("분위기 고르기","雰囲気を選ぶ","Pick a mood")}),y.moodPresets.map(M=>(0,e.jsx)("button",{type:"button",onClick:()=>
97Hr(M),disabled:Ue,title:M.description,className:st(Ue&&"cursor-not-allowed opacity-50"),children:M.label},M.id))]})]},y.id)),ce&&(0,e.jsx)(Hi,{draft:ce,language:v,videoDuration:S.videoDuration||15,editable:re==="discussion",onCutSave:it,onCutEditingChange:cr}),ce&&It&&(0,e.jsx)(Hs,{text:It.content,language:v,typewriter:Me.length-1===Sr}),re==="hero"&&!gt&&(0,e.jsx)(qi,{language:v,aspectRatio:S?.aspectRatio}),re==="generating"&&(0,e.jsx)("div",{...Ve(je.shortsAgentProgress),children:(0,e.jsx)(Bi,{progress:kr??5,message:en(gr)||x("영상을 제작하고 있습니다...","動画を制作しています...","Generating your video..."),language:v,onCancel:()=>Ie(!0)})}),Nt&&re!=="generating"&&(0,e.jsxs)("div",{className:"grid w-full gap-1.5",children:[(0,e.jsx)(Vs,{language:v}),(0,e.jsxs)("div",{className:"mka-box w-full px-4 py-3",children:[(0,e.jsxs)("div",{className:"mb-2.5 flex items-center gap-2 text-[10.5px] font-bold uppercase tracking-[0.16em] text-brand-ink",children:[(0,e.jsx)("span",{className:"inline-block h-1.5 w-1.5 animate-pulse rounded-full bg-brand"}),x("AI 이미지 분석 중","AIが画像を分析中","AI Analyzing Image")]}),(0,e.jsxs)("div",{className:"flex items-center gap-2.5",children:[(0,e.jsx)("span",{className:"mka-spin",style:{"--sz":"14px"}}),(0,e.jsx)("span",{className:"text-sm text-foreground/85",children:x("어울리는 분위기와 브랜드 발음을 추출하고 있습니다...","合う雰囲気とブランドの読み方を抽出しています...","Extracting fitting moods & brand pronunciation...")})]})]})]}),Ue&&!Nt&&re!=="hero"&&re!=="generating"&&(()=>{const y={start:{label:"스토리보드 분석 중...",labelJa:"ストーリーボードを分析中...",labelEn:"Analyzing storyboard..."},concept:{label:"쇼츠 컨셉 구성 중...",labelJa:"ショートコンセプトを構成中...",labelEn:"Building shorts concept..."},cuts_start:{label:"컷 스토리보드 작성 시작...",labelJa:"カットストーリーボードの作成開始...",labelEn:"Starting cut storyboard..."},cut:{label:`Cut ${wt} 작성 중...`,labelJa:`カット ${wt} を作成中...`,labelEn:`Writing Cut ${wt}...`},narration:{label:"내레이션 & 디렉터 노트 작성 중...",labelJa:"ナレーション&ディレクターノートを作成中...",labelEn:"Writing narration & director note..."},final:{label:"최종 영상 프롬프트 완성 중...",labelJa:"最終動画プロンプトを仕上げ中...",labelEn:"Finalizing video prompt..."}},j=y[Mt]??y.start,M=v==="ko"?j.label:v==="ja"?j.labelJa:j.labelEn,Q=Mt==="cut"||Mt==="cuts_start";return(0,e.jsxs)("div",{className:"grid w-full gap-1.5",children:[(0,e.jsx)(Vs,{language:v}),(0,e.jsxs)("div",{className:"mka-box w-full px-4 py-3",children:[(0,e.jsxs)("div",{className:"mb-2.5 flex items-center gap-2 text-[10.5px] font-bold uppercase tracking-[0.16em] text-brand-ink",children:[(0,e.jsx)("span",{className:"inline-block h-1.5 w-1.5 animate-pulse rounded-full bg-brand"}),x("AI 스토리보드 작성 중","AIがストーリーボードを作成中","AI Writing Storyboard")]}),(0,e.jsxs)("div",{className:"flex items-center gap-2.5",children:[(0,e.jsx)(li,{state:Fi[Mt]??"composing",size:20,className:"flex h-5 w-5 shrink-0 items-center justify-center"}),(0,e.jsx)("span",{className:"text-sm text-foreground/85",children:M})]}),Q&&wt>0&&(0,e.jsxs)("div",{className:"mt-2.5 flex items-center gap-1.5",children:[Array.from({length:Math.max(wt,6)}).map((ke,ae)=>(0,e.jsx)("div",{className:st("h-1 flex-1 rounded-full transition-all duration-300",ae<wt?"bg-brand":"bg-white/10")},ae)),(0,e.jsx)("span",{className:"ml-1 font-geo text-[10.5px] font-bold text-brand-ink",children:wt})]})]})]})})(),ce&&!Ue&&re!=="generating"&&re!=="result"&&(0,e.jsx)(e.Fragment,{children:(Je||!Ue&&ce)&&(0,e.jsx)("div",{className:"flex flex-col gap-3",children:(0,e.jsxs)("div",{className:"flex flex-col gap-2 lg:flex-row lg:flex-nowrap lg:items-center lg:justify-end",children:[(0,e.jsx)("button",{type:"button",onClick:()=>Ze(!0),disabled:Ue,...Ve(je.shortsAgentNewConcept),className:"rn-btn rn-btn-g w-full lg:w-auto 
97shrink-0",children:x("다른 컨셉 제안","別のコンセプト提案","New Concept")}),re==="discussion"&&(()=>{const y=Je?"":v==="ko"?et?.koreanReading?.trim()||xt?"잠시 후 다시 시도해 주세요":'브랜드 발음을 입력하거나 "건너뛰기"를 선택하면 활성화됩니다':v==="ja"?et?.koreanReading?.trim()||xt?"しばらくしてからもう一度お試しください":"ブランド発音を入力するか「スキップ」を選択すると有効化されます":et?.koreanReading?.trim()||xt?"Please wait a moment":"Enter brand pronunciation or skip to enable";return(0,e.jsx)("div",{className:"flex flex-col gap-2",children:(0,e.jsx)("div",{className:"flex flex-col gap-2 sm:flex-row sm:flex-wrap lg:flex-nowrap",children:(()=>{const j=wn(S?.seedanceEngine??"2.0",S?.videoDuration??15),M=!j.includes("1080p"),Q={"480p":F,"720p":se,"1080p":_},ke=j.map(ae=>({res:ae,onClick:()=>Le(ae),cost:Q[ae],primary:ae==="720p"}));return(0,e.jsxs)(e.Fragment,{children:[M&&(0,e.jsx)("span",{className:"self-center whitespace-nowrap text-[11px] text-muted-foreground",children:x("30초 영상은 720p로 제공됩니다","30秒動画は720pのみ対応です","30-second videos are available in 720p")}),ke.map(ae=>(0,e.jsxs)("button",{type:"button",onClick:ae.onClick,disabled:!Je,title:y,...ae.res==="720p"?Ve(je.shortsAgentGenerate):ae.res==="1080p"?Ve(je.shortsAgentGenerateAlt):{},className:st("rn-btn",ae.primary?"rn-btn-y":"rn-btn-o"),children:[x(`${ae.res} 생성`,`${ae.res} 生成`,`Generate ${ae.res}`),(0,e.jsx)(fr,{value:ae.cost??"—",variant:ae.primary?"ink":"soft"})]},ae.res))]})})()})})})()]})})}),ma&&(0,e.jsx)(di,{language:v,label:x("답변을 쓰는 중...","回答を作成中...","Writing a reply...")}),(0,e.jsx)("div",{ref:Lt})]})}),(0,e.jsx)("div",{className:"mka-in px-3 md:px-6 py-3 md:py-4",children:(0,e.jsxs)("div",{...Ve(je.shortsAgentChat),children:[(0,e.jsx)("textarea",{value:ue,onChange:y=>R(y.target.value),onKeyDown:y=>{y.key==="Enter"&&!y.shiftKey&&(y.preventDefault(),i())},placeholder:Bt?re==="generating"||re==="hero"||re==="drafting"||Ue?x("만드는 중에도 궁금한 건 편하게 물어보세요 🙂","作成中でも気になることは気軽に聞いてくださいね 🙂","Ask me anything while I work 🙂"):Gt?x("예: 마지막 컷을 제품 클로즈업으로 바꿔줘 / 대사를 더 짧게 해줘","例: 最後のカットを商品のクローズアップに / セリフをもっと短く","Example: End on a product close-up / Shorten the dialogue"):re==="mood_select"?x("예: 따뜻한 봄 느낌으로 해줘 / 이미지를 더 밝게 해줘","例: 暖かい春の雰囲気で / 画像をもっと明るくして","Example: Make it feel like warm spring / Make the image brighter"):x("예: 대사를 더 짧게 해줘 / 아예 새 컨셉으로 다시 짜줘","例: セリフをもっと短くして / 完全に新しいコンセプトで作り直して","Example: Shorten the dialogue / Rebuild with a completely new concept"):x("에이전트가 답하는 중이에요. 잠시만 기다려 주세요…","エージェントが回答中です。少々お待ちください…","The agent is answering. One moment…"),className:"mka-ta h-16 md:h-24",disabled:!Bt}),(0,e.jsxs)("div",{className:"mt-2.5 md:mt-3 flex items-center justify-between gap-2 md:gap-3",children:[(0,e.jsx)("div",{className:"hidden md:block text-xs text-muted-foreground",children:re==="mood_select"?x("분위기를 선택하거나, 원하는 분위기를 직접 입력할 수 있습니다.","ムードプリセットを選ぶか、希望のムードを直接入力できます。","Select a mood preset, or describe your own mood."):x("부분 수정도, 완전히 새로운 컨셉으로 다시 짜달라는 요청도 자유롭게 보낼 수 있습니다.","部分修正も、完全に新しいコンセプトで作り直す依頼も自由に送ることができます。","Request partial tweaks, or ask to rebuild the whole concept from scratch.")}),(0,e.jsxs)("button",{type:"button",onClick:()=>{i()},disabled:!Bt||!ue.trim(),className:"rn-btn rn-btn-y ml-auto shrink-0",children:[x("보내기","送る","Send"),Qt>0&&(0,e.jsx)(fr,{value:Qt,variant:"ink"})]})]})]})})]})]}),T&&(0,Ia.createPortal)((0,e.jsx)("div",{className:"mka-scrim fixed inset-0 z-[80] flex items-center justify-center px-4",onClick:()=>{Ue||E()},children:(0,e.jsxs)("div",{className:"mka-dlg max-w-[560px]",onClick:y=>y.stopPropagation(),children:[(0,e.jsx)("p",{className:"rn-eyebrow is-y",children:x("시작 전 확인","開始前の確認","Confirm start")}),(0,e.jsx)("h3",{children:W?kt?x("같은 설정으로 한 번 더 만들까요?","同じ設定でもう一度作りますか?","Generate one more with the same settings?"):x("영상 생성을 시작할까요?","動画生成を開始しますか?","Start video generation?"):rt?x("이미지를 재생성할까요?","画像を再生成しますか?","Regenerate the image?"):ye?x("새 컨셉 생성을 시작할까요?","新しいコンセプト生成を開始しますか?","Start a new concept?"):x("입력한 내용으로 진행할까요?","入力内容で進行しますか?","Continue with this input?")}),(0,e.jsx)("p",{children:W?kt?x("같은 대표 이미지와 같은 프롬프트로 영상만 다시 만듭니다. 스토리보드는 그대로이고, 이전 결과도 위에 그대로 남아요. 크레딧은 새로 차감됩니다.","同じメインビジュアルと同じプロンプトで動画だけ作り直します。ストーリーボードはそのままで、以前の結果も上に残ります。クレジットは新たに消費されます。","Generates another video from the same hero image and prompt. The storyboard stays as-is and previous results remain above. Credits are charged again."):x("확정된 스토리보드로 쇼츠 영상 생성을 시작하면 AI 작업이 바로 진행됩니다. 시작 후에는 중간 중지나 비용 취소가 어려울 수 있어요.","確定したストーリーボードでショート動画生成を開始すると、AI処理がすぐに進行します。開始後は途中停止や費用の取り消しが難しい場合があります。","Once Shorts video generation starts from the approved storyboard, the AI job begins right away. After it starts, stopping midway or cancelling the cost may not be possible."):rt?x("현재 대표 이미지를 새로 만들며 AI 작업이 바로 진행됩니다. 시작 후에는 중간 중지나 비용 취소가 어려울 수 있어요.","現在のメインビジュアルを作り直し、AI処理がすぐに進行します。開始後は途中停止や費用の取り消しが難しい場合があります。","This will recreate the current hero image and start the AI job right away. After it starts, stopping midway or cancelling the cost may not be possible."):ye?x("새 쇼츠 컨셉 초안을 다시 만들며 AI 작업이 바로 진행됩니다. 시작 후에는 중간 중지나 비용 취소가 어려울 수 있어요.","新しいショート動画コンセプト案を作り直し、AI処理がすぐに進行します。開始後は途中停止や費用の取り消しが難しい場合があります。","This will create a new Shorts concept draft and start the AI job right away. After it starts, stopping midway or cancelling the cost may not be possible."):x("이 내용을 보내면 대표 이미지 수정 또는 쇼츠 스토리보드 생성이 바로 진행될 수 있습니다. 시작 후에는 중간 중지나 비용 취소가 어려울 수 있어요.","この内容を送信すると、メインビジュアルの修正またはショート動画のストーリーボード生成がすぐに進行する場合があります。開始後は途中停止や費用の取り消しが難しい場合があります。","Sending this may immediately start hero image revision or Shorts storyboard generation. After it starts, stopping midway or cancelling the cost may not be possible.")}),(0,e.jsxs)("div",{className:"mka-box mt-5 p-4",children:[(0,e.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-x-3 gap-y-1",children:[(0,e.jsx)("span",{className:"text-[15px] font-bold text-foreground",children:W?x(`${W.toUpperCase()}
97 영상 생성`,`${W.toUpperCase()} 動画生成`,`${W.toUpperCase()} video generation`):rt?x("대표 이미지 재생성","メインビジュアル再生成","Hero image regeneration"):ye?x("다른 컨셉 제안","別コンセプト提案","New concept"):x("직접 입력한 요청","直接入力したリクエスト","Custom request")}),W&&(0,e.jsx)("span",{className:"text-[12.5px] font-medium text-muted-foreground",children:x("보통 1~2분이면 완성됩니다","通常1〜2分で完成します","Usually done in 1-2 minutes")})]}),W&&(0,e.jsx)("p",{className:"mka-warn mt-3 whitespace-pre-line p-3 text-[12.5px] font-semibold leading-5",children:x(`AI 음성은 영문·숫자·고유명사를 어색하게 발음할 수 있습니다. 해외 모델의 한계라 환불 사유가 아닙니다.
98이 경우 완성 화면의 “한 번 더 생성”으로 다시 만드시거나, 음성만 따로 받아 해당 부분을 교체해 사용하시면 됩니다.`,`AI音声は英数字・固有名詞を不自然に発音することがあります。海外モデルの限界のため返金対象外です。
99その場合は完成画面の「もう一度生成」で作り直すか、音声のみ取得して該当部分を差し替えてご利用ください。`,'AI voice may mispronounce English words, numbers or proper nouns. This is a limitation of the overseas model and is not grounds for a refund — use "Generate one more" on the result screen, or download the voice track and swap that part.')}),!W&&(0,e.jsx)("p",{className:"mt-2 text-sm leading-6 text-foreground/85",children:$t||x("생성 작업이 시작됩니다.","生成処理が開始されます。","The generation job will start.")})]}),(0,e.jsxs)("div",{className:"mka-dlg-f",children:[(0,e.jsx)("button",{type:"button",disabled:Ue,onClick:E,className:"rn-btn rn-btn-g",children:x("아니오","いいえ","No")}),(0,e.jsxs)("button",{type:"button",disabled:Ue,onClick:z,...Ve(je.shortsAgentGenerateConfirm),className:"rn-btn rn-btn-y",children:[x("동의하고 시작","同意して開始","Agree and start"),(W||rt)&&(0,e.jsx)(fr,{value:W?C:Gi,variant:"ink"})]})]})]})}),document.body),Qe&&(0,Ia.createPortal)((0,e.jsx)("div",{className:"mka-scrim fixed inset-0 z-[80] flex items-center justify-center px-4",onClick:()=>{Ue||ht(null)},children:(0,e.jsxs)("div",{className:"mka-dlg max-w-md",onClick:y=>y.stopPropagation(),children:[(0,e.jsx)("p",{className:"rn-eyebrow is-y",children:x("시작 전 확인","開始前の確認","Confirm start")}),(0,e.jsx)("h3",{children:x("쇼츠 스토리보드 생성을 시작할까요?","ショート動画のストーリーボード生成を開始しますか?","Start Shorts storyboard generation?")}),(0,e.jsx)("p",{children:x("이 분위기로 쇼츠 스토리보드 작성을 시작하면 AI 작업이 바로 진행됩니다. 시작 후에는 중간 중지나 비용 취소가 어려울 수 있어요.","この雰囲気でショート動画のストーリーボード作成を開始すると、AI処理がすぐに進行します。開始後は途中停止や費用の取り消しが難しい場合があります。","Once Shorts storyboard drafting starts with this mood, the AI job begins right away. After it starts, stopping midway or cancelling the cost may not be possible.")}),(0,e.jsxs)("div",{className:"mka-box mt-4 p-3",children:[(0,e.jsx)("p",{className:"text-sm font-bold text-foreground",children:Qe.label}),(0,e.jsx)("p",{className:"mt-1 text-xs leading-5 text-muted-foreground",children:Qe.description})]}),(0,e.jsxs)("div",{className:"mka-dlg-f",children:[(0,e.jsx)("button",{type:"button",disabled:Ue,onClick:()=>ht(null),className:"rn-btn rn-btn-g",children:x("아니오","いいえ","No")}),(0,e.jsx)("button",{type:"button",disabled:Ue||!me,onClick:Wt,...Ve(je.shortsAgentMoodConfirm),className:"rn-btn rn-btn-y",children:x("네, 시작","はい、開始","Yes, start")})]})]})}),document.body),q&&(0,Ia.createPortal)((0,e.jsx)("div",{className:"mka-scrim fixed inset-0 z-[85] flex items-center justify-center px-4",onClick:()=>V(!1),children:(0,e.jsxs)("div",{className:"mka-dlg max-w-[520px]",onClick:y=>y.stopPropagation(),children:[(0,e.jsx)("p",{className:"rn-eyebrow is-y",children:x("닫기 전 확인","閉じる前の確認","Confirm close")}),(0,e.jsx)("h3",{children:x("세션을 종료할까요?","セッションを終了しますか?","End the session?")}),(0,e.jsx)("p",{children:re==="generating"?x(`영상 생성이 진행 중입니다. 종료하면 이 창에서는 더 이상 진행을 추적할 수 없고, 스토리보드와 대화 기록이 삭제됩니다.
100이미 시작된 영상은 서버에서 계속 만들어져 완성되면 보관함에 저장됩니다.`,`動画生成が進行中です。終了するとこのウィンドウでは進行を追跡できなくなり、ストーリーボードと会話å
100±¥æ­´ãŒå‰Šé™¤ã•れます。
101すでに始まった動画はサーバーで生成が続き、完成するとライブラリに保存されます。`,`A video is being generated. Ending stops this window from tracking it, and deletes the storyboard and chat history.
102The video already started keeps rendering on the server and lands in your library when done.`):re==="hero"||re==="drafting"||Ue?x(`진행 중인 작업이 있습니다. 종료하면 그 결과를 받을 수 없고, 스토리보드와 대화 기록이 삭제됩니다.
103되돌릴 수 없으니 잠시 접어두려면 최소화를 눌러 주세요.`,`進行中の作業があります。終了するとその結果を受け取れず、ストーリーボードと会話履歴が削除されます。
104元に戻せないため、一時的に隠すだけなら最小化を押してください。`,`A task is still running. Ending discards its result and deletes the storyboard and chat history.
105This cannot be undone — use Minimize if you just want it out of the way.`):re==="result"?x(`완성된 영상은 보관함에 저장되어 있어 언제든 다시 볼 수 있습니다.
106종료하면 이 세션의 스토리보드와 대화 기록만 삭제됩니다.`,`完成した動画はライブラリに保存されており、いつでも見られます。
107終了するとこのセッションのストーリーボードと会話履歴のみ削除されます。`,`Your finished video is saved in the library and stays available.
108Ending only deletes this session's storyboard and chat history.`):x(`종료하면 이 세션의 스토리보드와 대화 기록이 삭제되고 다시 열 수 없습니다.
109잠시 접어두려면 최소화를 눌러 주세요.`,`終了するとこのセッションのストーリーボードと会話履歴が削除され、再度開けません。
110一時的に隠すだけなら最小化を押してください。`,`Ending deletes this session's storyboard and chat history for good.
111Use Minimize if you just want it out of the way.`)}),(0,e.jsxs)("div",{className:"mka-dlg-f",children:[(0,e.jsx)("button",{type:"button",onClick:()=>V(!1),className:"rn-btn rn-btn-g",children:x("아니오","いいえ","No")}),(0,e.jsx)("button",{type:"button",onClick:()=>{V(!1),p?.()},className:"rn-btn rn-btn-danger",children:x("세션 종료","セッション終了","End session")})]})]})}),document.body),We&&(0,e.jsx)("div",{className:"mka-scrim fixed inset-0 z-[80] flex items-center justify-center px-4",onClick:()=>{X||Ie(!1)},children:(0,e.jsxs)("div",{className:"mka-dlg max-w-[440px]",onClick:y=>y.stopPropagation(),children:[(0,e.jsx)("h3",{className:"!mt-0",children:x("정말 취소하시겠습니까?","本当にキャンセルしますか?","Cancel generation?")}),(0,e.jsx)("p",{children:x("영상 생성을 중단합니다. 환불은 진행되지 않으며, 늦게 도착한 결과물도 저장되지 않습니다.","動画生成を中断します。返金は行われず、遅れて届いた結果物も保存されません。","Stop video generation now. No refund will be issued, and any late-arriving result will be discarded.")}),(0,e.jsxs)("div",{className:"mka-dlg-f",children:[(0,e.jsx)("button",{type:"button",disabled:X,onClick:()=>Ie(!1),className:"rn-btn rn-btn-g",children:x("아니오","いいえ","No")}),(0,e.jsx)("button",{type:"button",disabled:X,onClick:async()=>{ge(!0),await Kt(),ge(!1),Ie(!1)},className:"rn-btn rn-btn-danger",children:X?x("취소 중...","キャンセル中...","Cancelling..."):x("예, 취소","はい、キャンセル","Yes, cancel")})]})]})})]})},Xa=({children:t})=>(0,e.jsxs)("div",{className:"flex items-start gap-2.5",children:[(0,e.jsx)("span",{className:"mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-rose-500 to-violet-500",children:(0,e.jsx)(pn,{size:14,className:"text-white"})}),(0,e.jsx)("div",{className:"max-w-[46rem] rounded-2xl rounded-tl-sm border border-white/10 bg-white/[0.05] px-4 py-2.5 text-[13px] leading-relaxed text-zinc-200",children:t})]}),ca=4,ys="shorts_auto_concept_progress_v1",Tn=t=>typeof t=="string"&&/^https?:\/\//i.test(t),Yi=()=>{try{const t=localStorage.getItem(ys);if(!t)return null;const r=JSON.parse(t);return!r?.savedAt||Date.now()-r.savedAt>1440*60*1e3?null:(r.phase==="loading"&&(r.phase="input"),!r.images?.length&&r.uploadedUrls?.length&&(r.images=r.uploadedUrls.filter(Tn).slice(0,ca)),r)}catch{return null}},Xi=t=>{try{localStorage.setItem(ys,JSON.stringify({...t,images:t.images.filter(Tn),savedAt:Date.now()}))}catch{}},Qi=({open:t,onClose:r,uploadImages:n,onStart:l,initialImages:p,initialHighlights:h,inline:o=!1,lockedCasting:S,lockedLocation:v,lockedPresetName:U,seedanceEngine:D="2.0"})=>{const{language:I}=un(),f=(0,s.useCallback)((P,Ce,Re)=>I==="ko"?P:I==="ja"?Ce:Re,[I]),H=(0,s.useRef)(Yi()),[ee,Ee]=(0,s.use
111State)(H.current?.phase||"input"),[N,F]=(0,s.useState)(H.current?.images||[]),[se,_]=(0,s.useState)(H.current?.productName||""),[B,ie]=(0,s.useState)(H.current?.highlights||""),[K,x]=(0,s.useState)(H.current?.concepts||[]),[te,ue]=(0,s.useState)(H.current?.sellingPoints||[]),[R,$]=(0,s.useState)(H.current?.uploadedUrls||[]),O=(0,s.useRef)(null);(0,s.useEffect)(()=>{ee!=="loading"&&Xi({phase:ee,productName:se,images:N,highlights:B,concepts:K,sellingPoints:te,uploadedUrls:R})},[ee,se,N,B,K,te,R]),(0,s.useEffect)(()=>{t&&(p?.length&&F(P=>P.length===0?p.slice(0,ca):P),h?.trim()&&ie(P=>P.trim()?P:h.trim()))},[t,p,h]);const G=(0,s.useCallback)(P=>P.vibe||(I==="ja"?P.labelJa:I==="en"?P.labelEn:P.labelKo),[I]),Oe=(0,s.useCallback)(P=>{if(!P?.length)return;const Ce=ca-N.length;Array.from(P).slice(0,Ce).forEach(Re=>{if(!Re.type.startsWith("image/"))return;const We=new FileReader;We.onload=()=>{typeof We.result=="string"&&F(Ie=>Ie.length<ca?[...Ie,We.result]:Ie)},We.readAsDataURL(Re)})},[N.length]),fe=(0,s.useCallback)(async()=>{if(N.length===0&&!B.trim()&&!se.trim()){xe.error(f("입력 필요","入力が必要","Input Required"),{description:f("제품 사진을 올리거나 제품 설명을 입력해 주세요.","製品写真をアップロードするか、製品説明を入力してください。","Upload a product photo or enter a product description.")});return}Ee("loading");try{const P=N.length>0?await n(N,null):[];$(P);const{data:Ce,error:Re}=await ve.functions.invoke("shorts-auto-concept",{body:{productImageUrls:P,productName:se.trim(),highlights:B.trim(),language:I,conceptCount:4,lockedCasting:S||void 0,lockedLocation:v||void 0,...Lr(D)}});if(Re)throw new Error(Re.message||"shorts-auto-concept failed");if(!Ce?.success||!Array.isArray(Ce.concepts)||Ce.concepts.length===0)throw new Error(Ce?.error||"No concepts generated");x(Ce.concepts),ue(Array.isArray(Ce.sellingPoints)?Ce.sellingPoints:[]),Ee("concepts")}catch(P){pe.warn("[ShortsAutoConceptModal] concept generation failed:",P),xe.error(f("컨셉 생성 실패","コンセプト生成失敗","Concept Generation Failed"),{description:f("잠시 후 다시 시도해 주세요.","しばらくしてから再試行してください。","Please try again in a moment.")}),Ee("input")}},[N,se,B,I,f,n,S,v,D]),_e=(0,s.useCallback)(()=>{r()},[r]);if(!t)return null;const Ne=(0,e.jsxs)("div",{className:st(o?"w-full rounded-2xl border border-white/10 bg-white/[0.02]":"relative w-full max-w-5xl max-h-[90vh] overflow-y-auto rounded-2xl border border-white/10 bg-zinc-950 shadow-2xl"),children:[(0,e.jsxs)("div",{className:st("flex items-center justify-between px-5 sm:px-7 py-4 border-b border-white/10",!o&&"sticky top-0 z-10 bg-zinc-950/95 backdrop-blur"),children:[(0,e.jsxs)("div",{className:"flex items-center gap-2.5",children:[(0,e.jsx)("span",{className:"flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-rose-500 to-violet-500",children:(0,e.jsx)(pn,{size:16,className:"text-white"})}),(0,e.jsxs)("div",{children:[(0,e.jsx)("h2",{className:"text-base sm:text-lg font-black text-white leading-tight",children:f("AI 자동 쇼츠","AI自動ショート","AI Auto Shorts")}),(0,e.jsx)("p",{className:"text-[11px] text-zinc-500",children:f("제품만 주면 컨셉·후킹·CTA까지 알아서","製品を渡すだけでコンセプト・フック・CTAまで自動","Product in — concept, hook & CTA out")})]})]}),!o&&ee!=="loading"&&(0,e.jsx)("button",{onClick:_e,className:"p-2 rounded-lg text-zinc-500 hover:text-white hover:bg-white/10 transition-colors",children:(0,e.jsx)(Zr,{size:18})})]}),ee==="input"&&(0,e.jsxs)("div",{className:"p-5 sm:p-7 space-y-5",children:[o&&(0,e.jsx)(Xa,{children:f("안녕하세요. 제품 사진만 올려주시면 제가 컨셉·후킹·모델·장소까지 짜서 10초 쇼츠로 만들어 드릴게요.","こんにちは。商品写真をアップしていただければ、コンセプト・フック・モデル・ロケまで組み立てて10秒ショートにします。","Hi — just drop a product photo and I'll work out the concept, hook, cast and location, then build a 10-second short.")}),(0,e.jsxs)("div",{children:[(0,e.jsxs)("p",{className:"text-sm font-bold text-white mb-2",children:[f("제품 이름","製品名","Product Name"),(0,e.jsx)("span",{className:"ml-1.5 text-[11px] font-normal text-zinc-500",children:f("대사에 이 이름 그대로 들어갑니다","セリフにこの名前がそのまま入ります","used verbatim in the spoken lines")})]}),(0,e.jsx)("input",{value:se,onChange:P=>_(P.target.value),maxLength:80,placeholder:f("예) 빠나나 에이아이","例)ppabanana AI","e.g. BBANANA AI"),className:"w-full rounded-xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-white placeholder:text-zinc-600 focus:outline-none focus:border-rose-400/50"})]}),(0,e.jsxs)("div",{children:[(0,e.jsxs)("p",{className:"text-sm font-bold text-white mb-2",children:[f("제품 사진","製品写真","Product Photos"),(0,e.jsx)("span",{className:"ml-1.5 text-[11px] font-normal text-zinc-500",children:f("최대 4장","最大4枚","up to 4")})]}),(0,e.jsxs)("div",{className:"grid grid-cols-4 gap-2",children:[N.map((P,Ce)=>(0,e.jsxs)("div",{className:"relative aspect-square rounded-xl overflow-hidden border border-white/10 bg-white/5 group",children:[(0,e.jsx)("img",{src:P,alt:"",className:"w-full h-full object-cover"}),(0,e.jsx)("button",{onClick:()=>F(Re=>Re.filter((We,Ie)=>Ie!==Ce)),className:"absolute top-1 right-1 p-1 rounded-md bg-black/70 text-white opacity-0 group-hover:opacity-100 transition-opacity",children:(0,e.jsx)(Zr,{size:12})})]},Ce)),N.length<ca&&(0,e.jsxs)("button",{onClick:()=>O.current?.click(),className:"aspect-square rounded-xl border border-white/15 bg-white/5 hover:bg-white/10 hover:border-white/25 transition-colors flex flex-col items-center justify-center gap-1.5 text-zinc-500 hover:text-zinc-300",children:[(0,e.jsx)(vo,{size:20}),(0,e.jsx)("span",{className:"text-[10px] font-medium",children:f("추가","追加","Add")})]})]}),(0,e.jsx)("input",{ref:O,type:"file",accept:"image/*",multiple:!0,className:"hidden",onChange:P=>{Oe(P.target.files),P.target.value=""}})]}),(0,e.jsxs)("div",{children:[(0,e.jsxs)("p",{className:"text-sm font-bold text-white mb-2",children:[f("제품 설명","製品説明","Product Notes"),(0,e.jsx)("span",{className:"ml-1.5 text-[11px] font-normal text-zinc-500",children:f("선택 — 브랜드명·특장점·타깃","任意 — ブランド名・特徴・ターゲット","optional — brand, features, target")})]}),(0,e.jsx)("textarea",{value:B,onChange:P=>ie(P.target.value),rows:3,maxLength:1e3,placeholder:f("예) 비건 저자극 수분 세럼, 20-30대 민감성 피부 타깃","例)ヴィーガン低刺激セラム、20-30代敏感肌向け","e.g. vegan hydrating serum for sensitive skin, 20-30s"),className:"w-full rounded-xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-white placeholder:text-zinc-600 focus:outline-none focus:border-rose-400/50 resize-none"})]}),(0,e.jsxs)("button",{onClick:fe,className:"w-full flex items-center justify-center gap-2 rounded-xl bg-gradient-to-r from-rose-500 to-violet-500 hover:from-rose-400 hover:to-violet-400 px-5 py-3.5 text-sm font-black text-white transition-all shadow-lg shadow-rose-500/20",children:[f("컨셉 4개 뽑기","コンセプトを4つ生成","Generate 4 Concepts"),(0,e.jsx)($s,{size:16})]}),(0,e.jsx)("p",{className:"text-center text-[11px] text-zinc-600",children:f("AI가 제품을 ë³´ê³  컨셉·모델·장소를 직접 정하고, 후킹 액션은 모듈 라이브러리에서 골라옵니다 · 컨셉 생성은 무료","AIが製品を見てコンセプト・モデル・ロケを決め、フックはモジュールライブラリから選びます · コンセプト生成は無料","The AI reads your product and decides the concept, cast and location — hook actions come from the module library · free")})]}),ee==="loading"&&o&&(0,e.jsx)("div",{className:"p-5 sm:p-7 pb-0",children:(0,e.jsx)(Xa,{children:f("제품 ë³´ê³  어울리는 컨셉을 짜고 있어요. 30초쯤 걸려요.","商品を見て合うコンセプトを考えています。30秒ほどかかります。","Reading your product and working out concepts — about 30 seconds.")})}),ee==="loading"&&(0,e.jsxs)("div",{className:"p-16 flex flex-col items-center justify-center gap-4",children:[(0,e.jsx)(Gr,{size:32,className:"text-rose-400 animate-spin"}),(0,e.jsxs)("div",{className:"text-center",children:[(0,e.jsx)("p",{className:"text-sm font-bold text-white",children:f("제품을 분석하고 컨셉을 조합하고 있습니다...","製品を分析してコンセプトを組み合わせています...","Analyzing your product and mixing concepts...")}),(0,e.jsx)("p",{className:"text-[11px] text-zinc-500 mt-1.5",children:f("셀링포인트 추출 → 컨셉 발상 → 캐스팅·장소·후킹 액션 확정 (약 40초)","セールスポイント抽出 → コンセプト発想 → キャスト・ロケ・フック確定(約40秒)","Extracting selling points → inventing concepts â
111†’ locking cast, location & hook action (~40s)")})]})]}),ee==="concepts"&&(0,e.jsxs)("div",{className:"p-5 sm:p-7 space-y-4",children:[o&&(0,e.jsx)(Xa,{children:f("이 제품엔 이런 컨셉들이 어울려요. 마음에 드는 걸 고르시면 바로 스토리보드를 짜기 시작할게요.","この商品にはこんなコンセプトが合いそうです。気に入ったものを選んでいただければ、すぐストーリーボードを作り始めます。","These concepts fit your product. Pick one and I'll start building the storyboard.")}),te.length>0&&(0,e.jsxs)("div",{className:"rounded-xl border border-white/10 bg-white/[0.03] px-4 py-3",children:[(0,e.jsx)("p",{className:"text-[11px] font-bold text-zinc-400 mb-1.5",children:f("AI가 찝은 셀링포인트","AIが掴んだセールスポイント","Selling points AI picked")}),(0,e.jsx)("div",{className:"flex flex-wrap gap-1.5",children:te.map((P,Ce)=>(0,e.jsx)("span",{className:"rounded-full bg-rose-500/10 border border-rose-400/20 px-2.5 py-1 text-[11px] text-rose-200",children:P},Ce))})]}),(0,e.jsx)("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:K.map((P,Ce)=>(0,e.jsxs)("button",{onClick:()=>{try{localStorage.removeItem(ys)}catch{}l({concept:P,productImageUrls:R,productName:se.trim(),highlights:B.trim(),sellingPoints:te})},className:"group text-left rounded-2xl border border-white/10 bg-white/[0.03] hover:bg-white/[0.07] hover:border-rose-400/40 transition-all p-4 flex flex-col gap-2.5",children:[(0,e.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,e.jsxs)("span",{className:"inline-flex items-center gap-1.5 rounded-full bg-white/5 border border-white/10 px-2.5 py-1 text-[11px] font-bold text-zinc-300",children:[(0,e.jsx)("span",{children:P.emoji}),(0,e.jsx)("span",{children:G(P)})]}),(0,e.jsx)($s,{size:14,className:"shrink-0 text-zinc-600 group-hover:text-rose-300 transition-colors"})]}),(0,e.jsx)("p",{className:"text-sm font-black text-white leading-snug",children:P.title}),(0,e.jsxs)("p",{className:"text-[13px] text-rose-200/90 leading-snug",children:["“",P.hook,"”"]}),P.hookModuleLabel&&(0,e.jsxs)("span",{className:"w-max rounded-md bg-violet-500/10 border border-violet-400/25 px-2 py-0.5 text-[10px] font-bold text-violet-200",children:[f("후킹","フック","Hook")," · ",P.hookModuleLabel]}),P.hookAction&&(0,e.jsx)("p",{className:"text-[11px] text-zinc-400 leading-relaxed line-clamp-2",children:P.hookAction}),(P.casting||P.location)&&(0,e.jsxs)("div",{className:"space-y-1 rounded-lg bg-black/30 px-2.5 py-2",children:[P.casting&&(0,e.jsxs)("p",{className:"text-[10.5px] text-zinc-400 leading-relaxed line-clamp-2",children:[(0,e.jsx)("span",{className:"font-bold text-zinc-500",children:f("캐스팅","キャスト","Cast")})," ",P.casting]}),P.location&&(0,e.jsxs)("p",{className:"text-[10.5px] text-zinc-400 leading-relaxed line-clamp-2",children:[(0,e.jsx)("span",{className:"font-bold text-zinc-500",children:f("장소","ロケ","Location")})," ",P.location]})]}),P.microStoryboard&&(0,e.jsx)("p",{className:"text-[11px] text-zinc-500 leading-relaxed whitespace-pre-line line-clamp-4",children:P.microStoryboard}),P.fitReason&&(0,e.jsx)("p",{className:"text-[11px] text-zinc-400 leading-snug mt-auto pt-1 border-t border-white/5",children:P.fitReason})]},Ce))}),(0,e.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,e.jsx)("button",{onClick:()=>Ee("input"),className:"text-[12px] text-zinc-500 hover:text-zinc-300 transition-colors",children:f("입력 수정하기","入力を修正","Edit inputs")}),(0,e.jsxs)("button",{onClick:fe,className:"inline-flex items-center gap-1.5 rounded-lg border border-white/10 bg-white/5 hover:bg-white/10 px-3.5 py-2 text-[12px] font-bold text-zinc-300 hover:text-white transition-colors",children:[f("다른 컨셉 4개 다시 뽑기","別のコンセプトを再生成","Reroll 4 new concepts"),(0,e.jsx)(go,{size:13})]})]})]})]});return o?Ne:(0,Ia.createPortal)((0,e.jsxs)("div",{className:"fixed inset-0 z-[80] flex items-center justify-center p-3 sm:p-6",children:[(0,e.jsx)("div",{className:"absolute inset-0 bg-black/80 backdrop-blur-sm",onClick:ee==="loading"?void 0:_e}),Ne]}),document.body)},bs="!min-h-[120px] !rounded-[14px] !border-white/[0.14] !bg-zinc-950/[0.35] focus-within:!ring-0 focus-within:!border-[rgba(255,230,0,0.55)]",tn=(t,r,n,l)=>t==="ko"?r:t==="ja"?n:l,Zi="mk-modal is-narrow-pv bg-card text-foreground 2xl:!w-[min(92vw,1760px)] 2xl:!h-[min(88vh,1100px)] 2xl:!grid-cols-[minmax(0,1fr)_440px] data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",Pa=({language:t,onClose:r,title:n,description:l,adminBadge:p,videoUrl:h,posterUrl:o,overlayUrl:S,onCloseAutoFocus:v,onInteractOutside:U,children:D,footer:I,extra:f})=>(0,e.jsx)(wo,{modal:!0,open:!0,onOpenChange:H=>{H||r()},children:(0,e.jsx)(Po,{children:(0,e.jsx)(No,{className:"mk-scrim data-[state=open]:animate-in data-[state=open]:fade-in-0",children:(0,e.jsxs)(_o,{onCloseAutoFocus:v,onInteractOutside:U,...l?{}:{"aria-describedby":void 0},className:Zi,children:[(0,e.jsx)(bn,{onClick:r,label:tn(t,"닫기","閉じる","Close")}),(0,e.jsx)("div",{className:"mk-pv",children:(0,e.jsx)("div",{className:"mk-pv-media",children:(0,e.jsxs)("div",{className:"absolute inset-0 bg-[#000] flex items-center justify-center overflow-hidden",children:[o&&(0,e.jsx)("img",{src:o,alt:"","aria-hidden":"true",className:"absolute inset-0 w-full h-full object-cover scale-110 blur-2xl opacity-40 pointer-events-none select-none"}),h?(0,e.jsx)("video",{src:h,poster:o||void 0,controls:!0,autoPlay:!0,loop:!0,muted:!0,playsInl
111ine:!0,className:"relative w-full h-full object-contain"},h):o?(0,e.jsx)("img",{src:o,alt:n,className:"relative w-full h-full object-contain"}):null,S&&(h||o)&&(0,e.jsx)("img",{src:S,alt:"","aria-hidden":"true","data-testid":"shift-preview-overlay",className:"absolute inset-0 w-full h-full object-contain pointer-events-none select-none"})]})})}),(0,e.jsxs)("div",{className:"mk-mform",children:[(0,e.jsxs)("header",{className:"mk-mhead",children:[(0,e.jsx)("p",{className:"rn-eyebrow is-y",children:tn(t,"릴스","リール","Reels")}),(0,e.jsxs)("div",{className:"flex items-center gap-2 min-w-0 mt-1.5",children:[(0,e.jsx)(Co,{asChild:!0,children:(0,e.jsx)("h3",{className:"!m-0 min-w-0 truncate",children:n})}),p&&(0,e.jsx)("span",{className:"shrink-0 px-1 py-px text-[9px] font-bold leading-none bg-brand/15 text-brand rounded ring-1 ring-brand/30",children:"관"})]}),l&&(0,e.jsx)(ko,{className:"line-clamp-2",children:l})]}),(0,e.jsx)("div",{className:"mk-mbody",children:D}),(0,e.jsx)("div",{className:"mk-mfoot",children:I})]}),f]})})})}),xs=({label:t,Icon:r,src:n,ariaLabel:l,need:p,onPick:h,onRemove:o,removeLabel:S,corner:v,language:U,muted:D})=>(0,e.jsxs)("div",{className:"mk-slot shrink-0",children:[(0,e.jsxs)("button",{type:"button",onClick:I=>{I.currentTarget.blur(),h()},"aria-label":l,className:st("mk-slot-box",n&&"is-filled"),children:[n?(0,e.jsx)("img",{src:n,alt:"",draggable:!1}):(0,e.jsx)(r,{"aria-hidden":"true",strokeWidth:1.6}),p&&!n&&(0,e.jsx)("em",{className:"mk-slot-need","aria-hidden":"true",children:p})]}),n&&o&&(0,e.jsx)("button",{type:"button",className:"mk-slot-x",onClick:o,"aria-label":S,title:S,children:(0,e.jsx)(Zr,{size:11,strokeWidth:2.6,"aria-hidden":"true"})}),!n&&v,(0,e.jsx)("small",{className:st("max-w-[4.5rem] text-center !whitespace-normal leading-tight",U==="ja"?"break-words":"break-keep",D&&"opacity-80"),children:t})]}),En=()=>(0,e.jsx)("span",{className:"mk-sep","aria-hidden":"true"});function vs({value:t,options:r,onChange:n,ariaLabel:l}){return(0,e.jsxs)(bi,{value:t,onValueChange:p=>n(p),children:[(0,e.jsx)(gi,{"aria-label":l,className:"w-full h-12 rounded-[14px] border border-border bg-white/[0.03] px-4 text-[14.5px] font-bold text-foreground shadow-none transition-colors hover:border-[rgba(255,230,0,0.35)] focus:ring-0 focus:ring-offset-0 focus:border-[rgba(255,230,0,0.55)] data-[state=open]:border-[rgba(255,230,0,0.55)]",children:(0,e.jsx)(yi,{})}),(0,e.jsx)(fi,{className:"z-[60]",children:r.map(p=>(0,e.jsx)(hi,{value:p,className:"text-sm font-semibold cursor-pointer focus:bg-[rgba(255,230,0,0.13)] focus:text-[rgb(var(--c-brand-ink))]",children:p},p))})]})}var Qr=[{key:"lead",label:{ko:"주연 교체",ja:"主役を差し替え",en:"Swap lead"},Icon:yo},{key:"support",label:{ko:"조연 교체",ja:"脇役を差し替え",en:"Swap supporting"},Icon:po},{key:"background",label:{ko:"ë°°ê²½ 교체",ja:"背景を差し替え",en:"Swap background"},Icon:vn}],el=[1,2,3,4].map(t=>({key:`product${t}`,label:{ko:`제품 ${t}`,ja:`商品 ${t}`,en:`Product ${t}`},Icon:mn})),tl={key:"finished",label:{ko:"나오는 제품",ja:"出てくる商品",en:"Product that comes out"},Icon:us},rl=[Qr[0],Qr[1],tl,Qr[2],...el];function An(t){const r=t.shiftSlots;if(!r||r.length===0)return Qr;const n=[];for(const l of rl){const p=r.find(v=>v.role===l.key);if(!p)continue;const h=l.key==="lead"&&p.subject==="pet",o=l.key.startsWith("product")&&p.anchor==="product",S=l.key==="support"&&p.anchor==="product"||o?us:h?Ii:l.Icon;n.push({...l,Icon:S,...p.label?{label:p.label}:{},...p.required?{required:!0}:{},...p.atLeastOne?{atLeastOne:!0}:{},...l.key==="support"&&p.anchor==="product"?{productAnchor:!0}:{},...h?{pet:!0}:{},...o?{productObject:!0}:{}})}return n.length>0?n:Qr}function al(t){return t.some(r=>r.key==="lead"&&r.pet)?{hint:{ko:"반려동물 사진 한 장이면 됩니다. 사진 속 털·무늬·옷 그대로 거대해져 나오고, 거리·타워·헬기는 원본 그대로 둡니다.",ja:"ペットの写真1枚で大丈夫でã
111™ã€‚写真の毛並み・模様・服のまま巨大になり、街・タワー・ヘリは元のままです。",en:"One pet photo is all it takes. Your pet appears giant with the same fur, markings and outfit; the street, tower and helicopters stay as in the original."},placeholder:{ko:"예) 반려동물 사진만 넣고 프롬프트는 비워 두어도 됩니다.",ja:"例) ペットの写真だけ入れて、プロンプトは空のままでも大丈夫です。",en:"e.g. Just add a pet photo — you can leave the prompt empty."}}:t.some(r=>r.key==="finished")?{hint:{ko:"던지는 제품과 나오는 제품 사진은 ê·¸ 모습 그대로 나옵니다. 한쪽만 넣으면 나머지는 프롬프트로 정하세요.",ja:"投げ入れる商品と出てくる商品の写真は、その見た目どおりに出ます。片方だけなら、もう片方はプロンプトで指定してください。",en:"Photos of what is thrown in and what comes out appear exactly as shown. With only one, describe the other in the prompt."},placeholder:{ko:"예) @던지는제품 원두를 던지면 @나오는제품 캔커피가 쏟아지고, 마지막에 @인물이 캔커피를 마시게.",ja:"例) 投げ入れたコーヒー豆から缶コーヒーが噴き出し、最後に人物が缶コーヒーを飲む。",en:"e.g. Throw in coffee beans and canned coffee erupts out; at the end the person drinks one."}}:t.some(r=>r.key==="support"&&r.productAnchor)&&t.some(r=>r.atLeastOne)?{hint:{ko:'인물·제품 사진 중 한 장 이상 넣어 주세요. 넣은 사진은 ê·¸ 모습 그대로 바뀌고, 넣지 않은 쪽은 원본 그대로 둡니다. 원본 옷을 유지하려면 프롬프트에 "얼굴만"이라고 적어 주세요.',ja:"人物・製品の写真を1枚以上入れてください。入れた写真はその見た目どおりに差し替わり、入れなかった方は元のままです。元の服のままにするにはプロンプトに「顔だけ」と書いてください。",en:'Add at least one photo, a person or a product. Photos are swapped in exactly as shown, and anything you leave out stays as in the original. To keep the original outfit, write "face only" in the prompt.'},placeholder:{ko:"예) 제품 사진만 넣고 프롬프트는 비워 두어도 됩니다.",ja:"例) 製品写真だけ入れて、プロンプトは空のままでも大丈夫でã
111™ã€‚",en:"e.g. Just add a product photo — you can leave the prompt empty."}}:t.length===1&&t[0].key==="support"&&t[0].productAnchor&&t[0].required?{hint:{ko:"사진 한 장은 필수입니다. 넣은 사진 모습 그대로 영상 속 대상이 바뀌고, 나머지 장면은 원본 그대로입니다.",ja:"写真1枚は必須です。入れた写真の見た目どおりに動画の対象が差し替わり、ほかの場面は元のままです。",en:"One photo is required. It replaces the subject in the video exactly as shown; the rest of the scene stays as in the original."},placeholder:{ko:"예) 사진만 넣고 프롬프트는 비워 두어도 됩니다.",ja:"例) 写真だけ入れて、プロンプトは空のままでも大丈夫です。",en:"e.g. Just add the photo — you can leave the prompt empty."}}:t.some(r=>r.key==="support"&&r.productAnchor)?{hint:{ko:"인물·제품 사진은 ê·¸ 모습 그대로 바뀌고, 넣지 않은 쪽은 원본 그대로 둡니다. 제품을 바꾸려면 제품 사진을 넣어 주세요.",ja:"人物・製品の写真はその見た目どおりに差し替わり、入れなかった方は元のままです。製品を替えるときは製品写真を入れてください。",en:"Person and product photos are swapped in exactly as shown, and anything you leave out stays as in the original. To change the product, add a product photo."},placeholder:{ko:"예) 제품 사진만 넣고 프롬프트는 비워 두어도 됩니다.",ja:"例) 製品写真だけ入れて、プロンプトは空のままでも大丈夫でã
111™ã€‚",en:"e.g. Just add a product photo — you can leave the prompt empty."}}:t.some(r=>r.productObject)?{hint:{ko:"제품 사진 3장은 필수입니다. 제품 1·2·3이 공중에 뜬 물건을 순서대로 바꾸고, 사진 모습 그대로 나옵니다. 인물 사진은 선택입니다.",ja:"商品写真3枚は必須です。商品1・2・3が空中に浮かぶ物を順に差し替え、写真の見た目どおりに出ます。人物写真は任意です。",en:"Three product photos are required. Products 1, 2 and 3 replace the flying items in order, exactly as shown. The person photo is optional."},placeholder:{ko:"예) 제품 사진만 넣고 프롬프트는 비워 두어도 됩니다.",ja:"例) 商品写真だけ入れて、プロンプトは空のままでも大丈夫です。",en:"e.g. Just add product photos — you can leave the prompt empty."}}:t.some(r=>r.key.startsWith("product"))?{hint:{ko:"제품 사진은 필수입니다. 제품 1~4는 영상에서 옷이 바뀌는 순서대로 입혀집니다. 인물 사진은 선택입니다.",ja:"商品写真は必須です。商品1〜4は動画で服が替わる順に着せ替えます。人物写真は任意です。",en:"Product photos are required. Products 1–4 are worn in the order the outfits change in the video. The person photo is optional."},placeholder:{ko:"예) 제품 2 원피스는 무릎 위 길이로. 마지막에 카메라를 ë³´ë©° 웃는 표정은 그대로.",ja:"例) 商品2のワンピースは膝上丈に。最後のカメラ目線の笑顔はそのまま。",en:"e.g. Make the product 2 dress above the knee. Keep the final smile to the camera."}}:null}var sl=new Set(["image/jpeg","image/jpg","image/pjpeg","image/png","image/webp","image/gif","image/bmp","image/x-ms-bmp","image/avif","image/svg+xml"]),nl=/\.(jpe?g|png|webp|gif|bmp|avif|svg)$/i;function Ta(t){const r=String(t?.type||"").trim().toLowerCase();return r?sl.has(r):nl.test(String(t?.name||""))}var ks="480p",rn=["480p","720p","1080p"];function ol(t,r,n=Qr){const l=n.map(p=>p.key).filter(p=>!!t[p]);return{prompt:_s(r,n).trim(),mode:t.lead?"recast":"restyle",imageOrder:l}}var il=/^[a-zA-Z0-9_\-가-힣]+$/;function ls(t,r){const n=String(t.label?.[r]||"").trim();return(r==="ko"?n.replace(/\s*교체$/,""):n.replace(/^swap\s+/i,"").toLowerCase()).trim()}function ws(t,r){const n=r==="ko"?["ko","en"]:["en"];for(const l of n){const p=ls(t,l).replace(/\s+/g,"");if(p&&il.test(p))return p}return t.key}function _s(t,r){if(!t||!t.includes("@"))return t;const n=new Map;for(const p of r){for(const h of["ko","en"]){const o=ls(p,h);o&&n.set(o.replace(/\s+/g,"").toLowerCase(),o)}n.set(p.key.toLowerCase(),ls(p,"en")||p.key)}const l=[...n.keys()].sort((p,h)=>h.length-p.length);return t.replace(/@([a-zA-Z0-9_\-가-힣]+)/g,(p,h)=>{const o=h.toLowerCase(),S=n.get(o);if(S!==void 0)return S;const v=l.find(U=>o.startsWith(U)&&/^[가-힣]+$/.test(o.slice(U.length)));return v?`${n.get(v)}${h.slice(v.length)}`:p})}var ll=({preset:t,sourceVideoUrl:r,variant:n=null,onVariantChange:l,language:p,sourceSeconds:h,estimateCredit:o,freeGrant:S=null,isSubmitting:v,onClose:U,onSubmit:D})=>{const I=(A,ye,Ze)=>p==="ko"?A:p==="ja"?ye:Ze,f=p!=="ko"&&t.i18n?.name?.[p]||t.name,H=p!=="ko"&&t.i18n?.description?.[p]||t.description,[ee,Ee]=(0,s.useState)({}
111),[N,F]=(0,s.useState)(null),se=(0,s.useMemo)(()=>An(t),[t]),[_,B]=(0,s.useState)(""),ie=S?.maxDurationSec!=null,K=rn.find(A=>A===S?.maxQuality)??null,[x,te]=(0,s.useState)(ks),[ue,R]=(0,s.useState)(null),$=(0,s.useRef)(typeof document<"u"&&document.activeElement instanceof HTMLElement&&document.activeElement!==document.body?document.activeElement:null),O=A=>{const ye=$.current;!ye||!ye.isConnected||(A.preventDefault(),ye.focus({preventScroll:!0}))},G=r,Oe=n?.poster||t.previewImage||"",fe=(t.shiftVariants||[]).map(A=>A.key),_e=!!l&&fe.includes("day")&&fe.includes("night"),Ne=(n?.key??t.shiftVariants?.[0]?.key)==="night",P=(0,s.useMemo)(()=>ol(ee,_,se),[ee,_,se]),Ce=Object.prototype.hasOwnProperty.call(os,t.id)&&!gn.includes(t.id),Re=se.filter(A=>!!ee[A.key]||A.required).map(A=>A.key),We=Ce&&Oo[t.id]?.promptOnly===!0&&Re.length===0&&!P.prompt.trim(),Ie=Ce?We?se.filter(A=>A.key!=="lead").slice(0,1).map(A=>A.key):Re:P.imageOrder,q=o(Ce?Ie.includes("lead")?"recast":"restyle":P.mode,x,Ie,P.prompt),V=!!S&&q===0,X=P.imageOrder.length>0||_.trim().length>0,ge=se.filter(A=>A.required&&!ee[A.key]),Qe=se.filter(A=>A.atLeastOne),ht=Qe.length>0&&!Qe.some(A=>ee[A.key]),$t=!v&&h>0&&X&&ge.length===0&&!ht&&q!==null,ft=al(se),W=se.length>4,Le=(A,ye)=>{if(!ye)return;if(!Ta(ye)){F(I("이 형식은 사용할 수 없습니다. JPG·PNG·WebP 로 저장해 올려 주세요. (아이폰 사진은 HEIC 형식일 수 있습니다)","この形式は使用できません。JPG・PNG・WebP で保存してアップロードしてください。(iPhone の写真は HEIC 形式の場合があります)","This file type can’t be used. Please upload a JPG, PNG or WebP. (iPhone photos may be in HEIC format.)"));return}const Ze=new FileReader;Ze.onerror=()=>F(I("사진을 읽지 못했습니다. 다시 선택해 주세요.","写真を読み込めませんでした。もう一度選んでください。","Could not read the photo. Please pick it again.")),Ze.onload=()=>{typeof Ze.result=="string"&&(F(null),Ee(Lt=>({...Lt,[A]:Ze.result})))},Ze.readAsDataURL(ye)},kt=(A,ye)=>{ye&&(F(null),Ee(Ze=>({...Ze,[A]:ye})))},De=(0,s.useMemo)(()=>se.map(A=>({tag:`@${ws(A,p)}`,type:"image",previewUrl:ee[A.key]||void 0})),[se,p,ee]),yt=A=>Ee(ye=>{const Ze={...ye};return delete Ze[A],Ze}),rt=r?h>0?I(`원본 ${Math.round(h)}초 · 같은 길이·비율`,`元動画 ${Math.round(h)}秒・同じ長さ・比率`,`${Math.round(h)}s · same length and ratio`):I("영상 정보를 읽는 중…","動画情報を読み込み中…","Reading video details…"):I("이 템플릿은 원본 영상을 준비 중입니다.","このテンプレートは元動画を準備中です。","This template’s source video is not ready yet.");return(0,e.jsxs)(Pa,{language:p,onClose:U,title:f,description:H,adminBadge:!!t.adminOnly,videoUrl:G,posterUrl:Oe,overlayUrl:Uo[t.id]||null,onCloseAutoFocus:O,onInteractOutside:A=>{A.target?.closest?.("[data-mention-dropdown]")&&A.preventDefault()},footer:(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("span",{className:"mk-foot-note",children:rt}),(0,e.jsxs)(Er,{variant:"y",disabled:!$t,onClick:()=>D({mode:P.mode,userPrompt:P.prompt,referenceImages:P.imageOrder.map(A=>ee[A]),referenceRoles:P.imageOrder,quality:x}),children:[v&&(0,e.jsx)(Gr,{className:"w-4 h-4 animate-spin","aria-hidden":"true"}),I("바꾸기 시작","変換を開始","Start"),q!==null&&(0,e.jsxs)(e.Fragment,{children:[" ",(0,e.jsx)(fr,{value:V?I("무료 1회","無料1回","Free run"):q,variant:"ink"})]})]})]}),extra:(0,e.jsx)(da,{open:ue!==null,accept:"image",onOpenChange:A=>{A||R(null)},onSelectFile:A=>{ue&&Le(ue,A)},onSelectLibrary:A=>{ue&&kt(ue,A)}}),children:[(0,e.jsx)("section",{className:"mk-slots","aria-label":I("교체 사진","差し替え写真","Replacement photos"),children:se.map(({key:A,label:ye,Icon:Ze,required:Lt},ut)=>{const at=ee[A];return(0,e.jsxs)(s.Fragment,{children:[ut>0&&!W&&(se.length<=3||ut===1&&se[0].key==="lead")&&(0,e.jsx)(En,{}),W&&ut===1&&(0,e.jsx)("div",{className:"basis-full h-0","aria-hidden":"true"}),(0,e.jsx)(xs,{language:p,label:ye[p],Icon:Ze,src:at,ariaLabel:Lt?`${ye[p]} (${I("필수","必須","Required")})`:ye[p],need:Lt?I("필수","必須","Required"):void 0,onPick:()=>R(A),onRemove:()=>yt(A),removeLabel:`${I("제거","削除","Remove")}: ${ye[p]}`})]},A)})}),N&&(0,e.jsx)("p",{role:"alert",className:"mk-hint !text-destructive",children:N}),(0,e.jsx)(sr,{title:I("프롬프트","プロンプト","Prompt")}),(0,e.jsx)(ms,{ariaLabel:I("프롬프트","プロンプト","Prompt"),value:_,onCh
111ange:B,omniSlots:De,disableCharacterMentions:!0,disableLibraryMentions:!0,constrainHeight:!0,placeholder:ft?ft.placeholder[p]:I("예) 주연 손의 바나나를 아이스 아메리카노로. 조연은 흰 셔츠에 청바지, 배경은 도쿄 야경으로.","例) 主役の手のバナナをアイスコーヒーに。脇役は白シャツにジーンズ、背景は東京の夜景に。","e.g. Banana in the lead’s hand → iced coffee. Supporting cast in white shirts and jeans, background a Tokyo night skyline."),className:bs}),(0,e.jsx)("p",{className:"mk-hint",children:ft?ft.hint[p]:I("주연·조연·배경이라는 말만으로 충분합니다. 언급하지 않은 요소는 원본 그대로 둡니다.","「主役・脇役・背景」と書くだけで通じます。触れなかった要素は元のままです。","Just say “lead”, “supporting” or “background”. Anything unmentioned stays as in the original.")}),_e&&(0,e.jsxs)("div",{className:"mk-toggle",children:[(0,e.jsxs)("b",{children:[I("낮 · 밤","昼 · 夜","Day · Night"),(0,e.jsx)("span",{className:"ml-2 text-xs font-medium text-muted-foreground","data-testid":"shift-daynight-state",children:Ne?I("밤","夜","Night"):I("낮","昼","Day")})]}),(0,e.jsx)(bo,{dark:Ne,onToggle:()=>{v||l?.(Ne?"day":"night")},ariaLabel:I("밤으로 보기","夜で表示","Night version"),className:v?"opacity-50 cursor-not-allowed":""})]}),(0,e.jsx)(sr,{title:I("해상도","解像度","Resolution")}),(0,e.jsx)(vs,{value:x,onChange:te,ariaLabel:I("해상도","解像度","Resolution"),options:rn}),S&&(0,e.jsx)("p",{className:"mk-hint","data-testid":"shift-free-note",children:V?I(`${ie?"가입 기념":"오픈 기념"} 무료 1회가 적용됩니다${K?` (${K} 한정)`:""}.`,`${ie?"新規登録記念":"オープン記念"}の無料1回が適用されます${K?`(${K}限定)`:""}。`,`Your ${ie?"sign-up":"launch"}-gift free run applies${K?` (${K} only)`:""}.`):I(`무료 1회는 ${K??"480p"} 에서만 적용됩니다. 이 해상도는 정가로 차감됩니다.`,`無料1回は${K??"480p"}のみ対象です。この解像度は通常料金です。`,`The free run applies only at ${K??"480p"}. This resolution is charged at the normal rate.`)})]})};function cl(t){return[...t].sort((r,n)=>(n.popularityCount??0)-(r.popularityCount??0))}var dl=["shift_menu_lights","shift_drink_player","shift_crayon_hanger"];function ul(t){return typeof t=="string"&&dl.includes(t.trim())}var an={ko:16,en:32};function Qa(t){const r=.335+(Math.min(6,Math.max(2,Math.floor(t)))-1)*2.14+.875;return Math.round((r+1.345+2.1)*1e3)/1e3}var Za=()=>({image:null,ko:"",en:""});function ml(t){const r=[];for(const n of t){const l=n.ko.trim(),p=n.en.trim();if(!n.image){if(l||p)return{items:[],problem:"photo"};continue}if(!l)return{items:[],problem:"name"};r.push({image:n.image,ko:l,en:p})}return r.length<2||r.length>6?{items:r,problem:"count"}:{items:r,problem:null}}var pl=({preset:t,sourceVideoUrl:r,language:n,credit:l,isFree:p,isSubmitting:h,onClose:o,onSubmit:S})=>{const v=($,O,G)=>n==="ko"?$:n==="ja"?O:G,U=n!=="ko"&&t.i18n?.name?.[n]||t.name,D=n!=="ko"&&t.i18n?.description?.[n]||t.description,[I,f]=(0,s.useState)(()=>Array.from({length:2},Za)),[H,ee]=(0,s.useState)(null),[Ee,N]=(0,s.useState)(null),F=(0,s.useRef)(typeof document<"u"&&document.activeElement instanceof HTMLElement&&document.activeElement!==document.body?document.activeElement:null),se=$=>{const O=F.current;!O||!O.isConnected||($.preventDefault(),O.focus({preventScroll:!0}))},_=ml(I),B=I.filter($=>$.image).length,ie=!h&&_.problem===null&&l!==null,K=t.previewImage||"",x=($,O)=>f(G=>G.map((Oe,fe)=>fe===$?{...Oe,...O}:Oe)),te=$=>f(O=>{const G=O.filter((Oe,fe)=>fe!==$);for(;G.length<2;)G.push(Za());return G}),ue=($,O)=>{if(!O)return;if(!Ta(O)){N(v("이 형식은 사용할 수 없습니다. JPG·PNG·WebP 로 저장해 올려 주세요. (아이폰 사진은 HEIC 형식일 수 있습니다)","この形式は使用できません。JPG・PNG・WebP で保存してアップロードしてください。(iPhone の写真は HEIC 形式の場合があります)","This file type can’t be used. Please upload a JPG, PNG or WebP. (iPhone photos may be in HEIC format.)"));return}const G=new FileReader;G.onerror=()=>N(v("사진을 읽지 못했습니다. 다시 선택해 주세요.","写真を読み込めませんでした。もう一度選んでください。","Could not read the photo. Please pick it again.")),G.onload=()=>{typeof G.result=="string"&&(N(null),x($,{image:G.result}))}
111,G.readAsDataURL(O)},R=_.problem==="name"?v("사진을 넣은 제품마다 이름을 적어 주세요.","写真を入れた商品ごとに名前を入力してください。","Add a name for every product with a photo."):_.problem==="photo"?v("이름을 적은 칸에 제품 사진을 넣어 주세요.","名前を入力した欄に商品写真を入れてください。","Add a product photo to every row with a name."):_.problem==="count"?v("제품을 2~6개 넣어 주세요.","商品を2〜6個入れてください。","Add 2–6 products."):null;return(0,e.jsxs)(Pa,{language:n,onClose:o,title:U,description:D,adminBadge:!!t.adminOnly,videoUrl:r,posterUrl:K,onCloseAutoFocus:se,footer:(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("span",{className:"mk-foot-note",children:v(`${Math.round(Qa(Math.max(B,2)))}초 · 1080×1920`,`${Math.round(Qa(Math.max(B,2)))}秒・1080×1920`,`${Math.round(Qa(Math.max(B,2)))}s · 1080×1920`)}),(0,e.jsxs)(Er,{variant:"y",disabled:!ie,onClick:()=>S({items:_.items}),children:[h&&(0,e.jsx)(Gr,{className:"w-4 h-4 animate-spin","aria-hidden":"true"}),v("만들기 시작","作成を開始","Start"),l!==null&&(0,e.jsxs)(e.Fragment,{children:[" ",(0,e.jsx)(fr,{value:p?v("무료 1회","無料1回","Free run"):l,variant:"ink"})]})]})]}),extra:(0,e.jsx)(da,{open:H!==null,accept:"image",onOpenChange:$=>{$||ee(null)},onSelectFile:$=>{H!==null&&ue(H,$)},onSelectLibrary:$=>{H!==null&&$&&(N(null),x(H,{image:$}))}}),children:[(0,e.jsxs)("section",{className:"rounded-[14px] bg-muted/40 ring-1 ring-border px-3.5 py-3",children:[(0,e.jsx)("p",{className:"text-[11px] font-bold tracking-[0.15em] text-muted-foreground uppercase",children:v("켜지는 순서","点灯の順番","Lighting order")}),(0,e.jsxs)("div",{className:"mt-2 flex flex-wrap items-center gap-1.5","aria-hidden":"true",children:[I.map(($,O)=>(0,e.jsxs)(s.Fragment,{children:[(0,e.jsx)("span",{className:st("inline-flex items-center justify-center w-6 h-6 rounded-full text-[11px] font-bold",$.image?"bg-[#D0B692] text-[#1d140f]":"bg-muted text-muted-foreground ring-1 ring-border"),children:O+1}),(0,e.jsx)("span",{className:"text-muted-foreground text-[11px]",children:"→"})]},O)),(0,e.jsx)("span",{className:"inline-flex items-center h-6 rounded-full px-2.5 text-[11px] font-bold bg-[#D0B692] text-[#1d140f]",children:v("전체","全体","All")})]}),(0,e.jsx)("p",{className:"mt-2 text-[11px] leading-4 text-muted-foreground",children:v("제품이 하나씩 켜지며 이름이 뜨고, 마지막에 전부 켜집니다.","商品が1つずつ点灯して名前が出て、最後に全部点灯します。","Each product lights up with its name, then everything lights up.")})]}),(0,e.jsx)("ol",{className:"flex flex-col gap-2.5 mt-2","aria-label":v("제품 목록","商品リスト","Products"),children:I.map(($,O)=>(0,e.jsxs)("li",{className:"relative flex items-stretch gap-3 rounded-2xl bg-muted/30 ring-1 ring-border p-2.5",children:[(0,e.jsx)("span",{className:"absolute -top-2 -left-2 w-5 h-5 rounded-full bg-[#D0B692] text-[#1d140f] text-[10px] font-bold flex items-center justify-center ring-2 ring-card","aria-hidden":"true",children:O+1}),(0,e.jsxs)("div",{className:"relative shrink-0",children:[(0,e.jsx)("button",{type:"button",onClick:G=>{G.currentTarget.blur(),ee(O)},"aria-label":v(`제품 ${O+1} 사진`,`商品 ${O+1} の写真`,`Product ${O+1} photo`),className:st("w-[76px] h-[76px] rounded-[14px] border overflow-hidden flex flex-col items-center justify-center gap-1 transition-colors","outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[rgba(255,230,0,0.7)]",$.image?"border-border":"border-border bg-muted/40 text-muted-foreground hover:border-[rgba(255,230,0,0.5)] hover:text-[rgb(var(--c-brand-ink))]"),children:$.image?(0,e.jsx)("img",{src:$.image,alt:"",className:"w-full h-full object-cover"}):(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)(us,{className:"w-5 h-5",strokeWidth:1.6}),(0,e.jsx)("span",{className:"text-[10px] font-semibold",children:v("사진","写真","Photo")})]})}),$.image&&(0,e.jsx)("button",{type:"button",onClick:()=>x(O,{image:null}),"aria-label":`${v("사진 빼기","写真を外す","Remove photo")}: ${v(`제품 ${O+1}`,`商品 ${O+1}`,`Product ${O+1}`)}`,className:"absolute -top-1.5 -right-1.5 w-4 h-4 rounded-full bg-[rgba(10,10,11,0.82)
111] ring-1 ring-[rgba(255,255,255,0.25)] text-[#fff] flex items-center justify-center hover:bg-[#ef4444]",children:(0,e.jsx)(Zr,{className:"w-2.5 h-2.5"})})]}),(0,e.jsxs)("div",{className:"flex-1 min-w-0 rounded-xl bg-[#1d140f] ring-1 ring-[#3a2a1f] px-3 py-2.5 flex flex-col items-center justify-center gap-1 focus-within:ring-[#D0B692]/60",children:[(0,e.jsx)("input",{value:$.ko,maxLength:an.ko,onChange:G=>x(O,{ko:G.target.value}),"aria-label":v(`제품 ${O+1} 이름(첫 줄)`,`商品 ${O+1} の名前(1行目)`,`Product ${O+1} name (first line)`),placeholder:v("제품 이름","商品名","Product name"),className:"w-full bg-transparent border-0 outline-none text-center text-[15px] font-bold text-[#D0B692] placeholder:text-[#D0B692]/35"}),(0,e.jsx)("input",{value:$.en,maxLength:an.en,onChange:G=>x(O,{en:G.target.value}),"aria-label":v(`제품 ${O+1} 둘째 줄(선택)`,`商品 ${O+1} の2行目(任意)`,`Product ${O+1} second line (optional)`),placeholder:v("둘째 줄 (선택)","2行目(任意)","Second line (optional)"),className:"w-full bg-transparent border-0 outline-none text-center text-[11px] font-serif text-[#D0B692]/90 placeholder:text-[#D0B692]/30"})]}),I.length>2&&(0,e.jsx)("button",{type:"button",onClick:()=>te(O),"aria-label":`${v("제품 삭제","商品を削除","Delete product")}: ${v(`제품 ${O+1}`,`商品 ${O+1}`,`Product ${O+1}`)}`,className:"shrink-0 self-start p-1 rounded-md text-muted-foreground hover:text-foreground hover:bg-muted",children:(0,e.jsx)(Zr,{className:"w-3.5 h-3.5"})})]},O))}),I.length<6&&(0,e.jsx)("button",{type:"button",onClick:()=>f($=>[...$,Za()]),className:"mk-chipb",children:v(`제품 추가 (${I.length}/6)`,`商品を追加(${I.length}/6)`,`Add product (${I.length}/6)`)}),(0,e.jsx)("p",{className:"mk-hint",children:v("라벨은 적은 그대로 들어갑니다. 한 줄만 쓰면 한 줄 라벨, 영어만 원하시면 첫 줄에 영어를 쓰세요.","ラベルは入力どおりに入ります。1行だけなら1行のラベル、英語だけなら1行目に英語を入力してください。","Labels appear exactly as typed. Fill only the first line for a one-line label.")}),Ee&&(0,e.jsx)("p",{role:"alert",className:"mk-hint !text-destructive",children:Ee}),!Ee&&B>0&&R&&(0,e.jsx)("p",{className:"mk-hint !text-destructive",children:R})]})};function hl(t){return typeof t=="string"&&t.trim()==="shift_drink_player"}var fl={10:20},sn=["480p","720p","1080p"],gl={"480p":0,"720p":18,"1080p":63};function yl(t){const r=fl[10];return t.background?r+gl[t.resolution]:r}var bl=({preset:t,sourceVideoUrl:r,language:n,ready:l,freeGrant:p,isQualityFree:h,estimateCredit:o,isSubmitting:S,onClose:v,onSubmit:U})=>{const D=(q,V,X)=>n==="ko"?q:n==="ja"?V:X,I=n!=="ko"&&t.i18n?.name?.[n]||t.name,f=n!=="ko"&&t.i18n?.description?.[n]||t.description,[H,ee]=(0,s.useState)({}
111),Ee=H.product??null,[N,F]=(0,s.useState)(null),[se,_]=(0,s.useState)(null),[B,ie]=(0,s.useState)(""),K=(0,s.useRef)(typeof document<"u"&&document.activeElement instanceof HTMLElement&&document.activeElement!==document.body?document.activeElement:null),x=q=>{const V=K.current;!V||!V.isConnected||(q.preventDefault(),V.focus({preventScroll:!0}))},te=10,ue=p?.maxDurationSec!=null,R=sn.includes(String(p?.maxQuality))?p.maxQuality:null,[$,O]=(0,s.useState)(ks),G=!!H.background,Oe=!!p&&h($),fe=Oe?0:o($,G),_e=!S&&l&&!!Ee&&(Oe||fe!==null),Ne=t.previewImage||"",P=(0,s.useMemo)(()=>{const q=(V,X)=>t.shiftSlots?.find(ge=>ge.role===V)?.label??X;return[{key:"product",label:q("support",{ko:"제품 교체",ja:"製品を差し替え",en:"Swap product"}),Icon:_i,required:!0},{key:"background",label:q("background",{ko:"배경 교체",ja:"背景を差し替え",en:"Swap background"}),Icon:vn}]},[t.shiftSlots]),Ce=(0,s.useMemo)(()=>P.map(q=>({tag:`@${ws(q,n)}`,type:"image",previewUrl:H[q.key]||void 0})),[P,n,H]),Re=_s(B,P).trim(),We=(q,V)=>ee(X=>{const ge={...X};return V?ge[q]=V:delete ge[q],ge}),Ie=(q,V)=>{if(!V)return;if(!Ta(V)){_(D("이 형식은 사용할 수 없습니다. JPG·PNG·WebP 로 저장해 올려 주세요. (아이폰 사진은 HEIC 형식일 수 있습니다)","この形式は使用できません。JPG・PNG・WebP で保存してアップロードしてください。(iPhone の写真は HEIC 形式の場合があります)","This file type can’t be used. Please upload a JPG, PNG or WebP. (iPhone photos may be in HEIC format.)"));return}const X=new FileReader;X.onerror=()=>_(D("사진을 읽지 못했습니다. 다시 선택해 주세요.","写真を読み込めませんでした。もう一度選んでください。","Could not read the photo. Please pick it again.")),X.onload=()=>{typeof X.result=="string"&&(_(null),We(q,X.result))},X.readAsDataURL(V)};return(0,e.jsxs)(Pa,{language:n,onClose:v,title:I,description:f,adminBadge:!!t.adminOnly,videoUrl:r,posterUrl:Ne,onCloseAutoFocus:x,onInteractOutside:q=>{q.target?.closest?.("[data-mention-dropdown]")&&q.preventDefault()},footer:(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("span",{className:"mk-foot-note",children:D(`${te}초 · ${$}`,`${te}秒・${$}`,`${te}s · ${$}`)}),(0,e.jsxs)(Er,{variant:"y",disabled:!_e,onClick:()=>{Ee&&U({image:Ee,resolution:$,...H.background?{background:H.background}:{},...Re?{prompt:Re}:{}})},children:[S&&(0,e.jsx)(Gr,{className:"w-4 h-4 animate-spin","aria-hidden":"true"}),D("바꾸기 시작","変換を開始","Start"),l&&(Oe||fe!==null)&&(0,e.jsxs)(e.Fragment,{children:[" ",(0,e.jsx)(fr,{value:Oe?D("무료 1회","無料1回","Free run"):fe,variant:"ink"})]})]})]}),extra:(0,e.jsx)(da,{open:N!==null,accept:"image",onOpenChange:q=>{q||F(null)},onSelectFile:q=>{N&&Ie(N,q)},onSelectLibrary:q=>{N&&q&&(_(null),We(N,q))}}),children:[(0,e.jsx)("section",{className:"mk-slots","aria-label":D("교체 사진","差し替え写真","Replacement photos"),children:P.map(({key:q,label:V,Icon:X,required:ge},Qe)=>(0,e.jsxs)(s.Fragment,{children:[Qe>0&&(0,e.jsx)(En,{}),(0,e.jsx)(xs,{language:n,label:V[n],Icon:X,src:H[q],ariaLabel:ge?`${V[n]} (${D("필수","必須","Required")})`:V[n],need:ge?D("필수","必須","Required"):void 0,onPick:()=>F(q),onRemove:()=>We(q,null),removeLabel:`${D("제거","削除","Remove")}: ${V[n]}`})]},q))}),se&&(0,e.jsx)("p",{role:"alert",className:"mk-hint !text-destructive",children:se}),(0,e.jsx)(sr,{title:D("프롬프트","プロンプト","Prompt")}),(0,e.jsx)(ms,{ariaLabel:D("프롬프트","プロンプト","Prompt"),value:B,onChange:ie,omniSlots:Ce,disableCharacterMentions:!0,disableLibraryMentions:!0,constrainHeight:!0,placeholder:D("예) 곡 제목은 '우베 라떼', 가수는 '카페 빠나나'로.","例) 曲名は「ウベラテ」、アーティストは「カフェ ババナナ」に。","e.g. Song title 'Ube Latte', artist 'Cafe Bbanana'."),className:bs}),(0,e.jsx)("p",{className:"mk-hint",children:D("음료 사진은 유리잔에 담긴, 층이 있는 음료가 잘 어울립니다. 프롬프트로 플레이어의 곡 제목·가수 이름과 음료 모습을 바꿀 수 있습니다. 배경 사진을 넣으면 그 바닥 위에서 손 장면을 다시 찍고, 바닥이 밝으면 플레이어 글씨는 검은색이 됩니다. 음료가 아닌 사진은 만들 수 없고 크레딧은 환불됩니다.","グラスに入った層のあるドリンクが映えます。プロンプトでプレーヤーの曲名・アーティスト名とドリンクの見た目を変えられます。背景写真を入れるとその床の上で手のシーンを撮り直し、明るい床ではプレーヤーの文字が黒になります。ドリンク以外の写真は作成できず、クレジットは返金されます。","Layered drinks in a clear glass work best. Use the prompt to change the player’s song title and artist or how the drink looks. Add a background photo to reshoot the hand scene on that surface; on light surfaces the player text turns black. Photos without a drink can’t be made and are refunded.")}),(0,e.jsx)(sr,{title:D("해상도","解像度","Resolution")}),(0,e.jsx)(vs,{value:$,onChange:O,ariaLabel:D("해상도","解像度","Resolution"),options:sn}),p&&(0,e.jsx)("p",{className:"mk-hint","data-testid":"shift-free-note",children:Oe?D(`${ue?"가입 기념":"오픈 기념"} 무료 1회가 적용됩니다${R?` (${R} 한정)`:""}.`,`${ue?"新規登録記念":"オープン記念"}の無料1回が適用されます${R?`(${R}限定)`:""}
111。`,`Your ${ue?"sign-up":"launch"}-gift free run applies${R?` (${R} only)`:""}.`):D(`무료 1회는 ${R??"480p"} 에서만 적용됩니다. 이 해상도는 정가로 차감됩니다.`,`無料1回は${R??"480p"}のみ対象です。この解像度は通常料金です。`,`The free run applies only at ${R??"480p"}. This resolution is charged at the normal rate.`)})]})};function xl(t){return typeof t=="string"&&t.trim()==="shift_crayon_hanger"}var nn=["480p","720p","1080p"],vl=2.5;var kl=2.6,wl={"480p":{perOutfit:28,base:12},"720p":{perOutfit:57,base:27},"1080p":{perOutfit:133,base:65}};function Sa(t){return t*kl+(t-1)*2+vl}function _l(t,r){const n=Math.min(5,Math.max(2,Math.floor(t))),l=wl[r];return n*l.perOutfit+l.base}function Il(t){return _l(t.outfits,t.resolution)}function Sl(t){const r=t.filter(n=>typeof n=="string"&&n.length>0);return r.length<2||r.length>5?{outfits:r,problem:"count"}:{outfits:r,problem:null}}function jl(t){const r=t.filter(Boolean).length;let n=-1;return t.forEach((l,p)=>{l&&(n=p)}),Math.min(5,Math.max(2,r+1,n+1))}function Nl(t){return{key:`outfit${t+1}`,label:{ko:`의상 ${t+1}`,ja:`衣装 ${t+1}`,en:`Outfit ${t+1}`}}}var Cl=({preset:t,sourceVideoUrl:r,language:n,estimateCredit:l,freeGrant:p=null,isQualityFree:h,isSubmitting:o,onClose:S,onSubmit:v})=>{const U=(V,X,ge)=>n==="ko"?V:n==="ja"?X:ge,D=n!=="ko"&&t.i18n?.name?.[n]||t.name,I=n!=="ko"&&t.i18n?.description?.[n]||t.description,[f,H]=(0,s.useState)(()=>Array.from({length:5},()=>
111null)),[ee,Ee]=(0,s.useState)(ks),[N,F]=(0,s.useState)(""),[se,_]=(0,s.useState)(null),[B,ie]=(0,s.useState)(null),K=(0,s.useRef)(typeof document<"u"&&document.activeElement instanceof HTMLElement&&document.activeElement!==document.body?document.activeElement:null),x=V=>{const X=K.current;!X||!X.isConnected||(V.preventDefault(),X.focus({preventScroll:!0}))},te=Sl(f),ue=te.outfits.length,R=jl(f),$=Math.max(ue,2),O=p?.maxDurationSec!=null,G=nn.includes(String(p?.maxQuality))?p.maxQuality:null,Oe=h(ee),fe=Oe?0:l($,ee),_e=!o&&te.problem===null&&fe!==null,Ne=t.previewImage||"",P=f.slice(0,R),Ce=(0,s.useMemo)(()=>Array.from({length:R},(V,X)=>Nl(X)),[R]),Re=(0,s.useMemo)(()=>Ce.map((V,X)=>({tag:`@${ws(V,n)}`,type:"image",previewUrl:P[X]||void 0})),[Ce,P,n]),We=_s(N,Ce).trim(),Ie=(V,X)=>H(ge=>ge.map((Qe,ht)=>ht===V?X:Qe)),q=(V,X)=>{if(!X)return;if(!Ta(X)){ie(U("이 형식은 사용할 수 없습니다. JPG·PNG·WebP 로 저장해 올려 주세요. (아이폰 사진은 HEIC 형식일 수 있습니다)","この形式は使用できません。JPG・PNG・WebP で保存してアップロードしてください。(iPhone の写真は HEIC 形式の場合があります)","This file type can’t be used. Please upload a JPG, PNG or WebP. (iPhone photos may be in HEIC format.)"));return}const ge=new FileReader;ge.onerror=()=>ie(U("사진을 읽지 못했습니다. 다시 선택해 주세요.","写真を読み込めませんでした。もう一度選んでください。","Could not read the photo. Please pick it again.")),ge.onload=()=>{typeof ge.result=="string"&&(ie(null),Ie(V,ge.result))},ge.readAsDataURL(X)};return(0,e.jsxs)(Pa,{language:n,onClose:S,title:D,description:I,adminBadge:!!t.adminOnly,videoUrl:r,posterUrl:Ne,onCloseAutoFocus:x,onInteractOutside:V=>{V.target?.closest?.("[data-mention-dropdown]")&&V.preventDefault()},footer:(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("span",{className:"mk-foot-note",children:U(`${$}벌 · 약 ${Math.round(Sa($))}초 · ${ee}`,`${$}着・約${Math.round(Sa($))}秒・${ee}`,`${$} outfits · ~${Math.round(Sa($))}s · ${ee}`)}),(0,e.jsxs)(Er,{variant:"y",disabled:!_e,onClick:()=>v({outfits:te.outfits,resolution:ee,...We?{prompt:We}:{}}),children:[o&&(0,e.jsx)(Gr,{className:"w-4 h-4 animate-spin","aria-hidden":"true"}),U("바꾸기 시작","変換を開始","Start"),fe!==null&&(0,e.jsxs)(e.Fragment,{children:[" ",(0,e.jsx)(fr,{value:Oe?U("무료 1회","無料1回","Free run"):fe,variant:"ink"})]})]})]}),extra:(0,e.jsx)(da,{open:se!==null,accept:"image",onOpenChange:V=>{V||_(null)},onSelectFile:V=>{se!==null&&q(se,V)},onSelectLibrary:V=>{se!==null&&V&&(ie(null),Ie(se,V))}}),children:[(0,e.jsx)("section",{className:"mk-slots","aria-label":U("의상 사진","衣装の写真","Outfit photos"),children:P.map((V,X)=>{const ge=Ce[X].label[n],Qe=X<2;return(0,e.jsx)(xs,{language:n,label:ge,Icon:mn,src:V,ariaLabel:Qe?`${ge} (${U("필수","必須","Required")})`:ge,need:Qe?U("필수","必須","Required"):void 0,onPick:()=>_(X),onRemove:()=>Ie(X,null),removeLabel:`${U("제거","削除","Remove")}: ${ge}`},X)})}),B&&(0,e.jsx)("p",{role:"alert",className:"mk-hint !text-destructive",children:B}),(0,e.jsx)(sr,{title:U("프롬프트","プロンプト","Prompt")}),(0,e.jsx)(ms,{ariaLabel:U("프롬프트","プロンプト","Prompt"),value:N,onChange:F,omniSlots:Re,disableCharacterMentions:!0,disableLibraryMentions:!0,constrainHeight:!0,placeholder:U("예) @의상2 는 상의만 걸어 주세요. 비워 두어도 됩니다.","例) 衣装2はトップスだけ掛けてください。空欄でも大丈夫でã
111™ã€‚","e.g. Hang only the top for @outfit2. You can leave this empty."),className:bs}),(0,e.jsx)("p",{className:"mk-hint",children:U("의상 사진은 2장 이상 필요하고, 칸 순서대로 크레파스로 그려진 뒤 실물로 바뀝니다. 상의·하의가 한 사진에 있으면 한 옷걸이에 같이 걸립니다. 프롬프트로는 걸리는 옷의 모양(상의만 걸기, 소매 걷기 등)을 정할 수 있습니다.","衣装写真は2枚以上必要で、枠の順にクレヨンで描かれてから実物に変わります。上下が1枚の写真にあれば同じハンガーに掛かります。プロンプトでは掛ける服の見た目(トップスだけ、袖をまくる など)を指定できます。","At least two outfit photos are needed; they are drawn in crayon in slot order and then turn real. A top and bottom in one photo hang together. Use the prompt to shape how the clothes hang (top only, sleeves rolled up, etc.).")}),(0,e.jsx)(sr,{title:U("해상도","解像度","Resolution")}),(0,e.jsx)(vs,{value:ee,onChange:Ee,ariaLabel:U("해상도","解像度","Resolution"),options:nn}),p&&(0,e.jsx)("p",{className:"mk-hint","data-testid":"shift-free-note",children:Oe?U(`${O?"가입 기념":"오픈 기념"} 무료 1회가 적용됩니다${G?` (${G} 한정)`:""}.`,`${O?"新規登録記念":"オープン記念"}の無料1回が適用されます${G?`(${G}限定)`:""}。`,`Your ${O?"sign-up":"launch"}-gift free run applies${G?` (${G} only)`:""}.`):U(`무료 1회는 ${G??"480p"} 에서만 적용됩니다. 이 해상도는 정가로 차감됩니다.`,`無料1回は${G??"480p"}のみ対象です。この解像度は通常料金です。`,`The free run applies only at ${G??"480p"}. This resolution is charged at the normal rate.`)})]})};function Pl(t){if(!(t.sourceSeconds>0))return null;const r=Fo({templateKey:t.templateKey,mode:t.mode,roles:t.roles,sourceSeconds:t.sourceSeconds,isAdmin:t.isAdmin,hasPrompt:t.hasPrompt}),n=(t.templateKey||"").trim(),l=Math.min(30,Math.max(4,Math.round(t.sourceSeconds)));if((r.total>0||gn.includes(n))&&Object.prototype.hasOwnProperty.call(os,n)&&l<=Lo[n]+1)return os[n][t.quality];const p=vi({serviceName:Xr,variants:t.variants||[],tier:"pro",quality:t.quality,duration:t.sourceSeconds,inputVideoDuration:t.sourceSeconds,useOmni:!1});if(p===null)return null;const{total:h}=r,o=$o(t.templateKey,t.sourceSeconds);return Ao(p+(h>0?Mo(h):0)+o)}var wa="Preserve authentic product packaging text and label typography. Do not add unrelated overlay captions, subtitles, or watermarks.",Tl="no subtitles, no captions, no on-screen text, no burned-in text, no Hangul text overlay. audio only.",Ke="shorts",El=9,Al={10:{"720p":50.4,"1080p":124.8,"4k":259.2},15:{"720p":75.6,"1080p":187.2,"4k":388.8}},Rl={"480p":3,"720p":6.4,"1080p":19.3};function $l(t){if(!t)return"";const r=[[/\b(gym\s+)?locker[\s-]?room\b/gi,"gym lounge area"],[/\b(shower|changing)[\s-]?room\b/gi,"lounge area"],[/\b탈의실\b/g,"헬스장 라운지"],[/\b락커\s*룸\b/g,"헬스장 라운지"],[/\b샤워실\b/g,"헬스장 라운지"],[/\b(a\s+)?(white\s+)?towel\s+(draped|wrapped)[^.,]*/gi,"a sports jacket over the shoulders"],[/\btowel\s+over\s+(her|his|their)\s+shoulder/gi,"a sports jacket over the shoulders"],[/\bbare\s+(skin|thigh|thighs|underarm|underarms|armpit|armpits)\b/gi,"the clothed area"],[/맨살/g,"피부"],[/\b(inner\s+)?(thigh|thighs|underarm|underarms|armpit|armpits)\b/gi,"the application area"],[/겨드랑이\s*안쪽/g,"사용 부위"],[/허벅지\s*안쪽/g,"사용 부위"],[/\b(sports\s+bra|underwear|lingerie|swimsuit|bikini)\b/gi,"athletic top"],[/\bsweaty\b/gi,"freshly active"]];let n=t;for(const[l,p]of r)n=n.replace(l,p);return n}function es(t){const r=String(t||"").toLowerCase();return r?/inappropriate content|suggestive or explicit|content[_\s-]?policy|safety system|moderation|flagged|nsfw|선정|유해|정책 위반/.test(r):!1}function Ml(t){if(!t)return"";const r=[[/\b(a|the)\s+(strikingly\s+)?(pretty|beautiful|gorgeous|attractive|sexy)\s+/gi,"a "],[/\bin (her|his|their) (early|mid|late)[\s-]?(twenties|thirties|forties|fifties|\d{2}s)\b/gi,""],[/\b(dewy|damp|glowing|flushed)\s+(skin|hair)\b/gi,"natural $2"],[/\bpost[\s-]?workout\b/gi,"after a light activity"],[/\b(skin texture|pores|collarbone|shoulder line|waist|hips|legs|thigh[s]?|underarm[s]?|armpit[s]?|chest|cleavage)\b/gi,"the scene"],[/\b(bare|exposed)\s+\w+/gi,"covered"],[/\b(selfie|front[\s-]?camera)\b/gi,"handheld camera"],[/\bface (and|,) upper chest fill the frame\b/gi,"the product fills the frame"],[/\bnext to (her|his|their) face\b/gi,"in front of the camera"]];let n=t;for(const[l,p]of r)n=n.replace(l,p);return`${n} Framing note: keep the composition centered on the product in its setting, fully clothed people only, modest everyday wardrobe, no close-up of skin. Safe-for-all-ages commercial photography.`}function Xt(t){if(!t)return"";const r=[[/\bno\s*text\s*,?\s*no\s*watermarks?\b/gi,wa],[/\bno\s*text\b/gi,"Preserve authentic product packaging text and label typography"],[/\bnever\s+include(?:\s+any)?\s+text(?:\/typography)?[^.]*\./gi,`${wa}.`],[/\bdo\s+not\s+include(?:\s+any)?\s+text(?:\/typography)?[^.]*\./gi,`${wa}.`],[/\bdo\s+not\s+render(?:\s+any)?\s+text[^.]*\./gi,`${wa}.`],[/\bno\s+typography\b/gi,"preserve authentic product packaging text and label typography"]];let n=t;for(const[l,p]of r)n=n.replace(l,p);return n.replace(/\s{2,}/g," ").replace(/\s+([,.;:!?])/g,"$1").trim()}function Ul(t){const r=Xt(t||"");if(!r)return"";const n=r.replace(/(".*?[\uac00-\ud7a3].*?")\s*\([A-Za-z][^)]*\)/g,"$1").replace(/\s*FULL NARRATION SCRIPT:[\s\S]*?(?=(?:ACTOR DIALOGUE:|STYLE:|$))/i,`
112`).replace(/\n{3,}/g,`
113
114`).trim();return n.includes("ABSOLUTE NO ON-SCREEN TEXT")||n.includes("화면 텍스트 정책")||n.includes("SEEDANCE 2.5 TEXT RENDERING POLICY")?n:`${Tl}
115
116${n}`.trim()}function on(t,r){if(!t)return t;try{const n=new URL(t,typeof window<"u"?window.location.origin:"http://localhost");return n.searchParams.set("_thumb_retry",r),n.toString()}catch{return`${t}${t.includes("?")?"&":"?"}_thumb_retry=${encodeURIComponent(r)}`}}function cs(t,r){if(!t)return"";const{width:n=420,height:l,quality:p=55}=r||{};try{const h=new URL(t,typeof window<"u"?window.location.origin:"http://localhost"),o="/storage/v1/object/public/";if(!h.pathname.includes(o))return t;if(h.pathname.includes("/storage/v1/render/image/"))return h.searchParams.has("width")||h.searchParams.set("width",String(n)),l&&!h.searchParams.has("height")&&h.searchParams.set("height",String(l)),h.searchParams.has("quality")||h.searchParams.set("qual
116ity",String(p)),h.searchParams.has("resize")||h.searchParams.set("resize","cover"),h.toString();const[S,...v]=h.pathname.split(o)[1].split("/");return!S||v.length===0?t:(h.pathname=`/storage/v1/render/image/public/${S}/${v.join("/")}`,h.searchParams.set("width",String(n)),l&&h.searchParams.set("height",String(l)),h.searchParams.set("quality",String(p)),h.searchParams.set("resize","cover"),h.toString())}catch{return t}}var Dl=t=>{if(!Array.isArray(t))return;const r=t.map(n=>{if(typeof n=="string")return n.trim()?{url:n.trim()}:null;const l=typeof n?.url=="string"?n.url.trim():"";return l?{url:l,poster:typeof n?.poster=="string"&&n.poster.trim()?n.poster.trim():void 0}:null}).filter(Boolean);return r.length>0?r:void 0},Ol=t=>{if(!Array.isArray(t))return;const r=["lead","support","finished","background","product1","product2","product3","product4"],n=[];for(const l of r){const p=t.find(f=>f&&typeof f=="object"&&f.role===l);if(!p)continue;const h=p.label,o=h&&typeof h.ko=="string"&&typeof h.ja=="string"&&typeof h.en=="string"?{ko:h.ko,ja:h.ja,en:h.en}:void 0,S=l==="lead"&&p.wardrobe==="replace"?"replace":void 0,v=(l==="support"||l.startsWith("product"))&&p.anchor==="product"?"product":void 0,U=p.required===!0,D=l==="lead"&&p.subject==="pet"?"pet":void 0,I=p.atLeastOne===!0;n.push({role:l,...o?{label:o}:{},...S?{wardrobe:S}:{},...v?{anchor:v}:{},...U?{required:U}:{},...D?{subject:D}:{},...I?{atLeastOne:I}:{}})}return n.length>0?n:void 0},Ll=t=>{if(!Array.isArray(t))return;const r=[];for(const n of t){if(!n||typeof n!="object")continue;const l=n,p=l.key==="day"||l.key==="night"?l.key:null,h=typeof l.templateKey=="string"?l.templateKey.trim():"",o=typeof l.sourceUrl=="string"?l.sourceUrl.trim():"";if(!p||!/^shift_[a-z0-9_]+$/.test(h)||!/^https:\/\//.test(o)||r.some(v=>v.key===p))continue;const S=typeof l.poster=="string"&&/^https:\/\//.test(l.poster.trim())?l.poster.trim():void 0;r.push({key:p,templateKey:h,sourceUrl:o,...S?{poster:S}:{}})}return r.length>=2?r:void 0},Fl=t=>{if(!t||typeof t!="object")return;const r=p=>{if(!p||typeof p!="object")return;const h={};for(const o of["ja","en"]){const S=p[o];typeof S=="string"&&S.trim()&&(h[o]=S.trim())}return Object.keys(h).length>0?h:void 0},n=r(t.name),l=r(t.description);return n||l?{name:n,description:l}:void 0},Gl=t=>({id:t.preset_key,name:t.name,description:t.description||"",category:t.category,industry:t.industry||null,colorSwatch:t.color_swatch||"#FFFFFF",previewGradient:t.preview_gradient||"linear-gradient(135deg,#333,#555)",previewImage:t.preview_image_url||void 0,promptTemplate:Xt(t.prompt_template||""),createdAt:t.created_at,displayOrder:t.display_order,popularityCount:typeof t.popularity_count=="number"?t.popularity_count:void 0,tone:t.tone||void 0,casting:t.casting||void 0,ethnicity:t.ethnicity||void 0,theme:t.theme==="shift"?"shift":"influencer",location:t.location||void 0,showcaseVideos:Dl(t.showcase_videos),shiftSourceVideoUrl:typeof t.shift_source_video_url=="string"&&t.shift_source_video_url.trim()?t.shift_source_video_url.trim():void 0,i18n:Fl(t.i18n),adminOnly:t.admin_only===!0,shiftSlots:Ol(t.shift_slots),shiftVariants:Ll(t.shift_variants)}),Vl=["hold_explain"],ts=yn({quality:"medium",resolution:"1K"}),ln=[{key:"hold_explain",emoji:"🤳",labelKo:"들고 설명",labelJa:"持って説明",labelEn:"Hold & Explain"},{key:"fooh",emoji:"🏙️",labelKo:"FOOH 도시",labelJa:"FOOH シティ",labelEn:"FOOH City"},{key:"ugc",emoji:"🪂",labelKo:"UGC 극한",labelJa:"UGC エクストリーム",labelEn:"UGC Extreme"},{key:"cgi",emoji:"🎬",labelKo:"CGI 3D",labelJa:"CGI 3D",labelEn:"CGI 3D"},{key:"vfx",emoji:"✨",labelKo:"VFX 효과",labelJa:"VFX エフェクト",labelEn:"VFX Effects"},{key:"drama",emoji:"💌",labelKo:"K-드라마",labelJa:"K-ドラマ",labelEn:"K-Drama"},{key:"legacy",emoji:"🎞️",labelKo:"클래식",labelJa:"クラシック",labelEn:"Classic"}],Hl=[{key:"influencer",labelKo:"인플루언서",labelJa:"インフルエンサー",labelEn:"Influencer"},{key:"shift",labelKo:"뜨는릴스",labelJa:"急上昇リール",labelEn:"Trending Reels",comingSoon:!0}],rs=48,as=2e3,zl=["image/jpeg","image/png","image/webp","image/gif"],_a=10*1024*1024,ss=()=>ai("image"),ns=t=>new Promise(r=>{window.setTimeout(r,t)}),$e=t=>{if(!t)return null;if(typeof t=="string"){const r=t.trim();return r||null}if(Array.isArray(t)){for(const r of t){const n=$e(r);if(n)return n}return null}if(typeof t=="object"){const r=t;return $e(r.url)||$e(r.resultUrl)||$e(r.result_url)||$e(r.imageUrl)||$e(r.image_url)||$e(r.videoUrl)||$e(r.video_url)||$e(r.output)||$e(r.images)||$e(r.data)}return null},cn=t=>$e(t?.taskId??t?.task_id??t?.data?.taskId??t?.data?.task_id??t?.data?.data?.taskId??t?.data?.data?.task_id),la=t=>typeof t=="string"&&t.startsWith("http")?t:Array.isArray(t)&&t.length>0&&typeof t[0]=="string"&&t[0].startsWith("http")?t[0]:$e(t?.imageUrl)||$e(t?.image_url)||$e(t?.resultUrl)||$e(t?.result_url)||$e(t?.videoUrl)||$e(t?.video_url)||$e(t?.images)||$e(t?.allResultUrls)||$e(t?.resultUrls)||$e(t?.output)||$e(t?.data?.imageUrl)||$e(t?.data?.image_url)||$e(t?.data?.resultUrl)||$e(t?.data?.result_url)||$e(t?.data?.videoUrl)||$e(t?.data?.video_url)||$e(t?.data?.images)||$e(t?.data?.allResultUrls)||$e(t?.data?.resultUrls)||$e(t?.data?.response?.resultUrls)||$e(t?.data?.resultInfoJson?.resultUrls)||$e(t?.data?.resultJson)||null,ql=(t,r)=>{const n=(l,p,h)=>r==="ko"?l:r==="ja"?p:h;return t==="hero"?{label:n("대표 이미지","ヒーロー画像","Hero Image"),description:n("대표 이미지를 만들고 있습니다.","ヒーロー画像を作成しています。","Creating the representative image.")}:t==="drafting"?{label:n("초안 작성","ドラフト作成","Drafting"),description:n("쇼츠 ì´
116ˆì•ˆì„ 구성하고 있습니다.","ショート動画の草案を構成しています。","Building the shorts draft.")}:t==="discussion"?{label:n("협의 중","協議中","Discussing"),description:n("사용자 수정 요청을 기다리거나 반영할 수 있습니다.","ユーザーの修正リクエストを待つか反映できます。","Ready for user edits and approval.")}:t==="generating"?{label:n("영상 생성 중","動画を生成中","Generating"),description:n("Seedance 2.0 결과를 기다리고 있습니다.","Seedance 2.0の結果を待っています。","Waiting for the Seedance 2.0 result.")}:t==="result"?{label:n("ê²°ê³¼ 도착","結果到着","Ready"),description:n("완성된 결과를 다시 열어 확인할 수 있습니다.","完成した結果を再度開いて確認できます。","The finished result is ready to reopen.")}:t==="error"?{label:n("확인 필요","確認が必要","Needs Attention"),description:n("오류 내용을 확인하고 이어서 진행할 수 있습니다.","エラー内容を確認して続けて進められます。","Review the error and continue from the agent.")}:{label:n("준비 중","準備中","Preparing"),description:n("에이전트 세션을 준비하고 있습니다.","エージェントセッションを準備しています。","Preparing the agent session.")}},Rn=s.memo(({preset:t,onClick:r,priority:n=!1,tutorialAnchor:l,badge:p=null})=>{const h=t.category==="fashion_film",[o,S]=s.useState(!1),[v,U]=s.useState(!1),[D,I]=s.useState(!1),f=t.previewImage||"",H=s.useMemo(()=>cs(f,{width:360,height:640,quality:55}),[f]),[ee,Ee]=s.useState(H||f),N=s.useRef(0),{ref:F,inView:se}=Ls({triggerOnce:!0,rootMargin:"320px 0px",initialInView:n}),_=s.useMemo(()=>(t.showcaseVideos||[]).filter(ge=>ge&&typeof ge.url=="string"&&ge.url),[t.showcaseVideos]),[B,ie]=s.useState(0),[K,x]=s.useState(!1),[te,ue]=s.useState(!1),[R,$]=s.useState(!1),[O,G]=s.useState(!1);s.useEffect(()=>{ie(0),x(!1),ue(!1),$(!1)},[_.length]);const Oe=_.length>0?_[B%_.length]:null;s.useEffect(()=>{ue(!1),$(!1)},[Oe?.url]);const{ref:fe,inView:_e,entry:Ne}=Ls({rootMargin:"120px 0px",threshold:[0,.25,.5,.75,1],initialInView:n}),P=Ne?.intersectionRatio??0,Ce=P>0?P:n?.001:0,Re=To(`shorts-preset-${t.id}`,!!Oe&&!K&&(!R||O),Ce,O),We=!!Oe&&!K,Ie=We&&(n||_e)&&Re,q=Oe?.poster||H||f||void 0;s.useEffect(()=>{N.current=0,S(!1),U(!1),I(!1),Ee(H||f)},[H,f]);const V=s.useCallback(()=>{if(f&&!D&&H&&H!==f){U(!1),I(!0),Ee(on(f,"full"));return}N.current<1&&f?(N.current+=1,U(!1),I(!0),Ee(on(f,String(N.current)))):S(!0)},[f,H,D]),X=!!f&&(n||se);return(0,e.jsxs)("button",{ref:F,type:"button",onClick:r,...l?Ve(l):{},"aria-label":t.name,className:"mk-tcard",style:{aspectRatio:h?"3 / 4":"9 / 16"},children:[(0,e.jsxs)("div",{ref:fe,onMouseEnter:()=>G(!0),onMouseLeave:()=>G(!1),className:"mk-media overflow-hidden",children:[(0,e.jsx)("div",{className:"absolute inset-0 w-full h-full",style:{background:t.previewGradient}}),We?(0,e.jsxs)(e.Fragment,{children:[Ie?(0,e.jsx)("video",{src:Oe.url,poster:q,muted:!0,autoPlay:!0,playsInline:!0,preload:"metadata",loop:_.length<=1,onEnded:()=>{_.length>1&&ie(ge=>(ge+1)%_.length)},onLoadedData:()=>ue(!0),onLoadedMetadata:ge=>{const Qe=ge.currentTarget;(Qe.videoWidth>1920||Qe.videoHeight>1920)&&$(!0)},onError:()=>x(!0),className:st("absolute inset-0 w-full h-full object-cover transition-opacity duration-300",te?"opacity-100":"opacity-0")},Oe.url):null,(!Ie||!te)&&q&&(0,e.jsx)("img",{src:q,alt:t.name,className:"absolute inset-0 w-full h-full object-cover",loading:n?"eager":"lazy",decoding:"async",draggable:!1})]}):X&&!o?(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("img",{src:ee,alt:t.name,className:st("absolute inset-0 w-full h-full object-cover transition-opacity duration-300",v?"opacity-100":"opacity-0"),loading:n?"eager":"lazy",decoding:"async",sizes:h?"(max-width: 1024px) 50vw, 20vw":"(max-width: 1024px) 50vw, 25vw",draggable:!1,onLoad:()=>U(!0),onError:V,fetchpriority:n?"high":"low"}),!v&&(0,e.jsx)("div",{className:"absolute inset-0 animate-pulse bg-white/[0.05]"})]}):null]}),t.adminOnly&&(0,e.jsx)("span",{className:"mk-vb",style:{color:"#ffe600"},children:"관"}),p&&(0,e.jsx)("span",{className:"mk-vb is-round",style:{left:"auto",right:10},children:p})]})});Rn.displayName="AdTemplateCard";var Bl=({summary:t,language:r,onOpen:n,onDismiss:l})=>{const p=(I,f,H)=>r==="ko"?I:r==="ja"?f:H,h=ql(t.phase||"idle",r),o=t.heroImageUrl||t.sessionInput?.preset?.previewImage||null,S=t.draftTitle||t.presetName,v=t.error||h.description,U=t.phase==="error"||!!t.error,D=!U&&(t.phase==="result"||!!t.finalVideoUrl);return(0,e.jsx)(Ho,{video:t.finalVideoUrl,image:o,background:t.sessionInput?.preset?.previewGradient,title:S,sub:v,status:U?"error":D?"done":"active",statusLabel:h.label,progress:t.progress?`${t.progress}%`:void 0,onClick:n,onDelete:l,deleteLabel:p("종료","セッション終了","End"),deleteIcon:"close"})},$c=({user:t,onClose:r,onOpenStorage:n,sandbox:l=!1})=>{const{t:p,language:h}=un(),o=(0,s.useCallback)((a,c,d)=>
116h==="ko"?a:h==="ja"?c:d,[h]),{signInWithGoogle:S}=so(),{isAdmin:v,canUseAdminFeatures:U}=uo(),{currentModel:D}=Ro(),{checkCredit:I,showCreditRequiredModal:f,showCreditModal:H,setShowCreditModal:ee,requiredCredit:Ee}=xn(),{settings:N}=ii(),F=(0,s.useMemo)(()=>qa(N.type_specific_settings),[N.type_specific_settings]),se=oo(),[_,B]=(0,s.useState)(()=>{if(l)return"templates";try{const a=localStorage.getItem("ad-active-tab");if(a==="templates"||a==="history")return a}catch{}return"templates"});(0,s.useEffect)(()=>{if(!l)try{localStorage.setItem("ad-active-tab",_)}catch{}},[_,l]);const ie=Ko("mk-lib-shorts"),[K,x]=(0,s.useState)("all"),[te,ue]=(0,s.useState)(0),[R,$]=(0,s.useState)([]),[O,G]=(0,s.useState)(!0);(0,s.useEffect)(()=>{(async()=>{G(!0);try{const{data:a,error:c}=await ve.from("shorts_preset_templates").select("*").eq("is_active",!0).or(`tone.in.(${Vl.join(",")}),theme.eq.shift`).not("preview_image_url","is",null).order("display_order",{ascending:!0});if(c)throw c;$((a||[]).map(Gl))}catch{$([])}finally{G(!1)}})()},[]);const[Oe,fe]=(0,s.useState)(void 0);(0,s.useEffect)(()=>{(async()=>{try{const{data:a,error:c}=await ve.from("bbanana_models").select("model_variants").eq("id","a8785abe-d139-479a-9202-d69119078e4b").single();!c&&a?.model_variants&&(fe(a.model_variants),pe.log("[ShortsAgentView] NB2 variants loaded from DB, credit_map:",a.model_variants?.[0]?.params?.find(d=>d.key==="resolution")?.credit_map))}catch{}})()},[]);const[_e,Ne]=(0,s.useState)(null),[P,Ce]=(0,s.useState)(null);(0,s.useEffect)(()=>{(async()=>{try{const{data:a,error:c}=await ve.from("bbanana_models").select("id, service_name, model_variants, credit_cost").in("id",[Yo,Qo]);!c&&Array.isArray(a)&&(Ne(a.find(d=>d.id==="2fd1c0c1-2e5c-435d-bf31-ee4b00830f49")??null),Ce(a.find(d=>d.id==="6db87733-d7dd-410c-b9e8-6650d0f5fbea")??null))}catch{}})()},[]);const[Re,We]=(0,s.useState)(15),Ie=!l&&kn(U)?"2.5":"2.0",q=(0,s.useCallback)((a,c,d)=>{const u=d??Ie,k=Ws(u,a,{seedance2:_e,seedance25:P}),w=Ks(u,a,c);if(u==="2.5"||a>15){if(k)return Va(a,w,!0,k,"pro");const ne=Rl[w==="4k"?"720p":w];return Math.ceil(ne*a*10)/10}const L=w==="480p"?"720p":w;return k?Va(a,L,!0,k,"pro"):Al[a][L]},[_e,P,Ie]),V=(0,s.useMemo)(()=>["service","product"],[]),[X,ge]=(0,s.useState)("all"),[Qe,ht]=(0,s.useState)("all"),[$t,ft]=(0,s.useState)("all"),[W,Le]=(0,s.useState)("all"),kt=(0,s.useMemo)(()=>{const a={};for(const c of R){if((c.theme||"influencer")==="shift")continue;const d=c.tone||"legacy";a[d]=(a[d]||0)+1}return a},[R]),De=(0,s.useMemo)(()=>ln.filter(a=>(kt[a.key]||0)>0).length>1,[kt]),yt=(0,s.useMemo)(()=>{const a={};for(const c of R){if(c.adminOnly&&!v)continue;const d=c.theme||"influencer";a[d]=(a[d]||0)+1}return a},[R,v]),rt=!1;(0,s.useMemo)(()=>{const a={},c=X==="all"?R.filter(d=>V.includes(d.category)):R.filter(d=>d.category===X);for(const d of c)d.industry&&(a[d.industry]=(a[d.industry]||0)+1);return a},[X,R,V]);const A=(0,s.useMemo)(()=>{let a=R;return X==="all"?a=[...R].sort((c,d)=>{const u=c.displayOrder??0,k=d.displayOrder??0;if(u!==k)return u-k;const w=c.createdAt?new Date(c.createdAt).getTime():0;return(d.createdAt?new Date(d.createdAt).getTime():0)-w}).filter(c=>V.includes(c.category)):a=R.filter(c=>c.category===X),Qe!=="all"&&(a=a.filter(c=>c.industry===Qe)),$t!=="all"&&(a=a.filter(c=>(c.tone||"legacy")===$t)),W!=="all"?a=a.filter(c=>(c.theme||"influencer")===W):rt&&(a=a.filter(c=>(c.theme||"influencer")!=="shift")),W==="shift"&&rt&&(a=[]),W==="shift"&&(a=cl(a)),v||(a=a.filter(c=>!c.adminOnly)),l&&(a=a.filter(c=>(c.theme||"influencer")!=="shift")),a},[X,Qe,$t,W,rt,v,l,R,V]),[ye,Ze]=(0,s.useState)(rs),Lt=(0,s.useRef)(null),ut=(0,s.useMemo)(()=>{const a=A.slice(0,ye);if(!l)return a;const c=A.find(d=>d.id===Bs);return c?[c,...a.filter(d=>d.id!==c.id)]:a},[A,ye,l]),at=ye<A.length,qt=(0,s.useCallback)(()=>{Ze(a=>a>=A.length?a:Math.min(a+rs,A.length))},[A.length]),re=(0,s.useCallback)(a=>{if(!at)return;const{scrollTop:c,scrollHeight:d,clientHeight:u}=a.currentTarget;d-c-u<=420&&qt()},[at,qt]);(0,s.useEffect)(()=>{Ze(rs)},[X,Qe,$t,W]),(0,s.useEffect)(()=>{if(_!=="templates"||!at)return;const a=Lt.current;a&&a.scrollHeight<=a.clientHeight+320&&qt()},[_,at,qt,ye]);
116const Me=6,[ce,gt]=(0,s.useState)(null);(0,s.useEffect)(()=>{if(!ce)return;const a=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.body.style.overflow=a}},[ce]);const[Ae,bt]=(0,s.useState)([]),[Ue,Nt]=(0,s.useState)(null),[Mt,wt]=(0,s.useState)(null),[nr,Bt]=(0,s.useState)(null),[Je,me]=(0,s.useState)(null),[Fe,Qt]=(0,s.useState)(""),[vr,et]=(0,s.useState)(""),[xt,kr]=(0,s.useState)(!1),[mt,gr]=(0,s.useState)([]),[Ye,_t]=(0,s.useState)(!1),wr=(0,s.useRef)(null),{unregisterPortraitAsset:Vr}=So(),_r=(0,s.useRef)(new Set);(0,s.useEffect)(()=>{if(!ce)return;if(l){const c=Yr.productImages.map(oa).filter(d=>!!d);bt(d=>d.length===0?c:d),et(d=>d||Ka.productName),We(Ka.videoDuration);return}const a=qa(N.type_specific_settings);Ae.length===0&&a.productImages.length>0&&bt(a.productImages.slice(0,Me)),!Fe.trim()&&a.highlights.trim()&&Qt(a.highlights.trim())},[ce,N.type_specific_settings,l]),(0,s.useCallback)(async()=>{if(!(mt.length>0)){_t(!0);try{const{data:a,error:c}=await ve.from("model_presets").select("id, name, preview_image, category").eq("is_active",!0).order("sort_order");!c&&a&&gr(a)}catch{}finally{_t(!1)}}},[mt.length]),(0,s.useEffect)(()=>{if(!xt)return;const a=c=>{wr.current&&!wr.current.contains(c.target)&&kr(!1)};return document.addEventListener("mousedown",a),()=>document.removeEventListener("mousedown",a)},[xt]);const[Ct,Ir]=(0,s.useState)("9:16"),[Ft,ua]=(0,s.useState)("1K"),[Gt,ma]=(0,s.useState)("jpg"),[or,Ar]=(0,s.useState)(!1),[it,ir]=(0,s.useState)(null),Vt=it?.seedanceEngine??Ie,Kt=it?.videoDuration??Re,pt=(0,s.useMemo)(()=>q(Kt,"480p",Vt),[q,Kt,Vt]),Pt=(0,s.useMemo)(()=>q(Kt,"720p",Vt),[q,Kt,Vt]),Zt=(0,s.useMemo)(()=>q(Kt,"1080p",Vt),[q,Kt,Vt]),Sr=(0,s.useMemo)(()=>q(Kt,"4k",Vt),[q,Kt,Vt]),[lr,It]=(0,s.useState)(!1),[pa,Ut]=(0,s.useState)(null),[cr,vt]=(0,s.useState)([]);(0,s.useRef)(null),(0,s.useEffect)(()=>{if(!t?.id)return;let a=!1;return(async()=>{if(await Oi(t.id),a)return;const d=await Qs(t.id);a||vt(d)})(),()=>{a=!0}},[t?.id]);const Rr=(0,s.useRef)(null);(0,s.useEffect)(()=>{Rr.current=it?.sessionId??null},[it?.sessionId]);const dr=(0,s.useRef)(!1);(0,s.useEffect)(()=>{dr.current=lr},[lr]);const ur=(0,s.useCallback)((a,c)=>{vt(d=>d.filter(u=>u.sessionId!==a)),dr.current||xe.success(o("영상 완성","動画完成","Video Ready"),{description:o("에이전트 영상이 완성되었습니다. 내 영상 탭에서 확인하세요.","エージェント動画が完成しました。マイ動画タブで確認してください。","Your agent video is ready. Check the history tab.")})},[o]);(0,s.useEffect)(()=>{if(!t?.id)return;const a=setInterval(async()=>{const c=await Qs(t.id);vt(d=>{const u=Rr.current;if(!u)return c;const k=d.find(w=>w.sessionId===u);return k?c.map(w=>w.sessionId===u?k:w):c})},1e4);return()=>clearInterval(a)},[t?.id]);const Hr=(0,s.useRef)(null),Wt=(0,s.useRef)(new Set),i=(0,s.useCallback)(async a=>{if(!t?.id||Wt.current.has(a))return;Hr.current=a;const c=await Di(t.id,a);if(Hr.current===a&&!Wt.current.has(a))if(c?.sessionInput){const d={...c.sessionInput};c.state?.heroImageUrl&&!d.presetHeroImageUrl&&(d.presetHeroImageUrl=c.state.heroImageUrl),d.seedanceEngine=Si(d.seedanceEngine,U),ir(d),Ut(null),It(!0)}else vt(d=>d.filter(u=>u.sessionId!==a)),Wt.current.add(a),setTimeout(()=>Wt.current.delete(a),3e4),xe.error(o("세션을 불러올 수 없어요","セッションを読み込めません","Session unavailable"),{description:o("이 에이전트 세션은 복원에 필요한 데이터가 누락되었거나 만료됐어요. 새 세션으로 다시 시작해 주세요.","このエージェントセッションは復元に必要なデータが欠損しているか期限切れです。新しいセッションで再開してください。","This agent session cannot be restored (missing or expired data). Please start a new session.")})},[t?.id,o,U]),m=(0,s.useCallback)(async a=>{if(!t?.id)return;const c=a?.image_url;if(c)try{const{data:d,error:u}=await ve.from("user_tasks").select("task_id").eq("user_id",t.id).eq("result_url",c).like("task_id","shorts-agent-session:%").order("created_at",{ascending:!1}).limit(1).maybeSingle();if(u)throw u;
116const k=d?.task_id,w=k?.startsWith("shorts-agent-session:")?k.slice(21):null;if(!w){xe.error(o("수정을 시작할 수 없어요","編集を開始できません","Can't start editing"),{description:o("이 영상의 원본 에이전트 세션을 찾지 못했어요. 보관 기간이 지났거나 다른 경로로 만든 영상일 수 있어요.","この動画の元のエージェントセッションが見つかりませんでした。保存期間が過ぎたか、別の経路で作成された可能性があります。","We couldn't find the original agent session for this video. It may have expired or been created through a different flow.")});return}B("templates"),await i(w)}catch(d){pe.error("[shorts] remake lookup failed",d),xe.error(o("수정을 시작할 수 없어요","編集を開始できません","Can't start editing"),{description:o("잠시 후 다시 시도해 주세요.","しばらくしてから再試行してください。","Please try again in a moment.")})}},[t?.id,o,i]),[g,b]=(0,s.useState)([]),{addTask:C,updateTaskProgress:T,updateTaskStatus:E,updateTaskApiId:z,completeTask:y,failTask:j,tasks:M}=jo(),{startPolling:Q}=si(ot,()=>Ke,()=>Ke,b,()=>{pe.log("🎨 [ShortsAgentView] Task completed via shared hook")}),ke=(0,s.useMemo)(()=>M.filter(a=>(a.status==="generating"||a.status==="waiting")&&a.generationOptions?.task_type==="shorts"&&a.generationOptions?.ad_workflow!=="video_agent_session"),[M]),ae=(0,s.useCallback)(a=>{},[]),Pe=(0,s.useCallback)(a=>{const c=new Image;c.onload=()=>me({width:c.naturalWidth,height:c.naturalHeight}),c.src=a},[]),Te=(0,s.useCallback)(a=>{if(!a)return"1:1";const c=a.width/a.height,d=[["1:1",1],["16:9",16/9],["9:16",9/16],["4:3",4/3],["3:4",3/4],["3:2",3/2],["2:3",2/3],["21:9",21/9]];let u="1:1",k=1/0;for(const[w,L]of d){const ne=Math.abs(c-L);ne<k&&(k=ne,u=w)}return u},[]),St=(0,s.useCallback)(a=>a&&["16:9","9:16","1:1","4:3","3:4","21:9","adaptive"].includes(a)?a:a==="3:2"?"16:9":a==="2:3"?"9:16":"16:9",[]),Tt=(0,s.useCallback)(a=>new Promise(c=>{try{const d=new Image;d.crossOrigin="anonymous",d.onload=()=>{if(!d.naturalWidth||!d.naturalHeight)return c(null);c(Te({width:d.naturalWidth,height:d.naturalHeight}))},d.onerror=()=>c(null),d.src=a}catch{c(null)}}),[Te]),Ht=(0,s.useCallback)(async a=>{const u=URL.createObjectURL(a);let k;try{k=await new Promise((le,he)=>{const Be=new Image;Be.onload=()=>le(Be),Be.onerror=()=>he(new Error("image load failed")),Be.src=u})}catch{return URL.revokeObjectURL(u),a}const w=k.naturalWidth,L=k.naturalHeight;if(!(w>2048||L>2048||a.size>4194304))return URL.revokeObjectURL(u),a;const ne=Math.min(2048/w,2048/L,1),Z=Math.round(w*ne),we=Math.round(L*ne),de=document.createElement("canvas");de.width=Z,de.height=we;const be=de.getContext("2d");if(!be)return URL.revokeObjectURL(u),a;be.drawImage(k,0,0,Z,we),URL.revokeObjectURL(u);const oe=a.type==="image/png";let Y=await new Promise(le=>de.toBlob(le,oe?"image/png":"image/jpeg",oe?void 0:.85));if(!Y||Y.size>4194304){const le=await new Promise(he=>de.toBlob(he,"image/jpeg",.85));le&&(!Y||le.size<Y.size)&&(Y=le)}if(Y&&Y.size>4194304&&Y.type==="image/jpeg"){const le=await new Promise(he=>de.toBlob(he,"image/jpeg",.7));le&&le.size<Y.size&&(Y=le)}if(!Y)return a;const He=Y.type==="image/png"?".png":".jpg",ze=a.name.replace(/\.[^.]+$/,"")+He;return pe.log("🗜️ [AD-UPLOAD] 자동 리사이즈:",{원본:`${w}x${L}, ${(a.size/1024/1024).toFixed(2)}MB, ${a.type}`,ê²°ê³¼:`${Z}x${we}, ${(Y.size/1024/1024).toFixed(2)}MB, ${Y.type}`}),new File([Y],ze,{type:Y.type})},[]),er=(0,s.useCallback)(async(a,c)=>{if(!t){xe.warning(o("로그인 필요","ログイン必要","Login Required"),{description:o("이미지를 업로드하려면 로그인이 필요합니다.","画像をアップロードするにはログインが必要です。","Please log in to upload images.")}),S();return}if(!zl.includes(a.type)){xe.error(o("지원하지 않는 파일 형식","サポートされていないファイル形式","Unsupported file type"),{description:o("JPEG, PNG, WebP, GIF 이미지만 업로드할 수 있어요. (SVG는 보안상 제외)","JPEG、PNG、WebP、GIF画像ã
116®ã¿ã‚¢ãƒƒãƒ—ロードできます。(SVGはセキュリティ上除外)","Only JPEG, PNG, WebP, and GIF images are supported. (SVG is blocked for security.)")});return}if(a.size>_a){xe.error(o("파일이 너무 커요","ファイルが大きすぎます","File too large"),{description:o(`최대 ${_a/1024/1024}MB까지 업로드 가능해요. 현재 파일: ${(a.size/1024/1024).toFixed(1)}MB`,`最大${_a/1024/1024}MBまでアップロード可能です。現在のファイル: ${(a.size/1024/1024).toFixed(1)}MB`,`Maximum size is ${_a/1024/1024}MB. Your file: ${(a.size/1024/1024).toFixed(1)}MB`)});return}if(a.size<1024){xe.error(o("파일이 너무 작아요","ファイルが小さすぎます","File too small"),{description:o("1KB 이상의 이미지를 올려주세요.","1KB以上の画像をアップロードしてください。","Please upload an image larger than 1KB.")});return}try{const u=await Ms(a);if(!u.valid){let k,w;const L=u.ratio.toFixed(2);u.reason==="too_small"?(k=o("이미지 해상도가 너무 작습니다","画像解像度が小さすぎます","Image resolution too small"),w=o(`${u.width}×${u.height}px — 가로·세로 모두 300px 이상이어야 합니다.`,`${u.width}×${u.height}px — 縦横ともに300px以上必要です。`,`${u.width}×${u.height}px — both width and height must be at least 300px.`)):u.reason==="too_large"?(k=o("이미지 해상도가 너무 큽니다","画像解像度が大きすぎます","Image resolution too large"),w=o(`${u.width}×${u.height}px — 가로·세로 모두 ${Fa}px 이하여야 합니다.`,`${u.width}×${u.height}px — 縦横ともに${Fa}px以下必要です。`,`${u.width}×${u.height}px — both width and height must be at most ${Fa}px.`)):(k=o("이미지 비율이 허용 범위를 벗어났습니다","画像比率が許容範囲外です","Image aspect ratio out of range"),w=o(`${u.width}×${u.height}, 비율 ${L} — 허용 비율 ${Wr} ~ ${Jr}.`,`${u.width}×${u.height}、比率${L} — 許容比率${Wr}~${Jr}.`,`${u.width}×${u.height}, ratio ${L} — allowed ${Wr} ~ ${Jr}.`)),xe.error(k,{description:w});return}}catch{}try{a=await Ht(a)}catch{}const d=new FileReader;d.onload=u=>{const k=u.target?.result;c==="product"?(bt(w=>w.length<Me?[...w,k]:w),Pe(k)):c==="face"?Nt(k):wt(k)},d.readAsDataURL(a)},[S,t,Pe,Ht,o]),Et=(0,s.useCallback)(a=>{a.preventDefault(),Array.from(a.dataTransfer.files).slice(0,Me).forEach(c=>er(c,"product"))},[er]);(0,s.useCallback)(a=>{a.preventDefault();const c=a.dataTransfer.files[0];c&&er(c,"face")},[er]),(0,s.useCallback)(a=>{a.preventDefault();const c=a.dataTransfer.files[0];c&&er(c,"logo")},[er]);const $r=(0,s.useCallback)(async(a,c)=>{try{const d=await Ms(a);if(d.reason==="too_small"||d.reason==="too_wide"||d.reason==="too_tall"){const u=d.ratio.toFixed(2);d.reason==="too_small"?xe.error(o("이미지 해상도가 너무 작습니다","画像解像度が小さすぎます","Image resolution too small"),{description:o(`${d.width}×${d.height}px — 가로·세로 모두 300px 이상이어야 합니다.`,`${d.width}×${d.height}px — 縦横ともに300px以上必要です。`,`${d.width}×${d.height}px — both width and height must be at least 300px.`)}):xe.error(o("이미지 비율이 허용 범위를 벗어났습니다","画像比率が許容範囲外です","Image aspect ratio out of range"),{description:o(`${d.width}×${d.height}, 비율 ${u} — 허용 비율 ${Wr} ~ ${Jr}.`,`${d.width}×${d.height}、比率${u} — 許容比率${Wr}~${Jr}.`,`${d.width}×${d.height}, ratio ${u} — allowed ${Wr} ~ ${Jr}.`)});return}}catch{}c==="product"?(bt(d=>d.length<Me?[...d,a]:d),Pe(a)):c==="face"?Nt(a):wt(a)},[o,Pe]),ra=(0,s.useCallback)((a,c)=>{if(!a)return"";let d=Xt(a.promptTemplate);return a.category==="fashion_film"&&(d+=" The model must be Korean, with hair, makeup, and overall styling that naturally match the mood and atmosphere of the scene. Shot on a mirrorless camera with a prime lens ??shallow depth of field, professional bokeh, sharp micro-textures on fabric and skin. Professional color depth and dynamic range. Do NOT look like a phone camera photo."),a.tone==="hold_explain"&&(d+=" CAPTURE STYLE (mandatory): authentic iPhone handheld look — KEEP the framing shown in the reference image (a selfie close-up, a full-body standing shot, or the product placed in the scene — do not force it into an arm-extended selfie), available ambient light only, realistic smartphone HDR, natural visible skin texture, deep phone-camera depth of field with the background in focus. NOT studio lighting, NOT a professional photoshoot, NOT DSLR bokeh, NOT retouched commercial polish."),c.trim()?Xt(`${d} Additionally: ${c.trim()}`):d},[]),Dt=(0,s.useCallback)(async(a,c)=>{if(a.length===0)throw new Error("No product image");if(!t?.id)throw new Error("User not authenticated");const d=576,u=1408,k=async(L,ne,Z)=>
116{if(L.startsWith("http")&&!L.startsWith("data:"))return L;const we=await new Promise((He,ze)=>{const le=new Image;le.crossOrigin="anonymous",le.onload=()=>{let he=le.width,Be=le.height;if(he>u||Be>u){const qe=Math.min(u/he,u/Be);he=Math.round(he*qe),Be=Math.round(Be*qe)}if(he<d||Be<d){const qe=Math.max(d/he,d/Be);he=Math.round(he*qe),Be=Math.round(Be*qe),he>u&&(he=u),Be>u&&(Be=u)}const tt=document.createElement("canvas");tt.width=he,tt.height=Be,tt.getContext("2d").drawImage(le,0,0,he,Be),tt.toBlob(qe=>qe?He(qe):ze(new Error("Canvas toBlob failed")),"image/png")},le.onerror=()=>ze(new Error("Image load failed")),le.src=L}),de=new File([we],`ad-${Z}-${Date.now()}-${ne}.png`,{type:"image/png"}),be=`user-${t.id}/bbanana/${de.name}`,{error:oe}=await ve.storage.from("public-assets").upload(be,de,{upsert:!0});if(oe)throw new Error(`Upload failed: ${oe.message}`);const{data:Y}=ve.storage.from("public-assets").getPublicUrl(be);return Z==="face"&&_r.current.add(Y.publicUrl),Y.publicUrl},w=[];for(let L=0;L<a.length;L++)w.push(await k(a[L],L,"product"));return c&&w.push(await k(c,a.length,"face")),w},[t]);(0,s.useCallback)(()=>{if(!ce)return"";let a=Xt(ce.promptTemplate);return ce.category==="fashion_film"&&(a+=" The model must be Korean, with hair, makeup, and overall styling that naturally match the mood and atmosphere of the scene. Shot on a mirrorless camera with a prime lens — shallow depth of field, professional bokeh, sharp micro-textures on fabric and skin. Professional color depth and dynamic range. Do NOT look like a phone camera photo."),Fe.trim()?Xt(`${a} Additionally: ${Fe.trim()}`):a},[ce,Fe]);const Is=(0,s.useCallback)(()=>Dt(Ae,Ue),[Dt,Ae,Ue]),Ss=(0,s.useCallback)(()=>ra(ce,Fe),[ra,ce,Fe]),[js,$n]=(0,s.useState)(!1),Mn=(0,s.useCallback)(async()=>{if(l){Mr(null),xe.info(o("연습용 화면입니다","練習用の画面です","This is a practice screen"),{description:o("이 편에서는 실행 버튼으로 쇼츠 만드는 과정만 따라가 봅니다.","ここでは実行ボタンでショート制作の流れだけを体験します。","Here you only walk through making shorts with the run button.")});return}if(Ae.length===0&&!Fe.trim()||!ce){xe.error(o("입력 오류","入力エラー","Input Error"),{description:o("제품 이미지 또는 서비스 설명을 입력해 주세요.","製品画像またはサービス説明を入力してください。","Please upload a product image or enter a service description.")});return}if(!t?.id){xe.warning(o("로그인 필요","ログイン必要","Login Required"),{description:o("생성하려면 로그인이 필요합니다.","生成するにはログインが必要です。","Please log in to generate.")}),S();return}const a=ce,c=[...Ae],d=Ue,u=Fe.trim(),k=Ct,w=Ft,L=Gt,ne=Je;gt(null),B("history"),$n(!1),bt([]),Nt(null),wt(null),me(null),Qt("");const Z=`local_${Date.now()}`,we="evolink";C(Z,Z,"GPT Image 2","GPT Image 2",Xt(a.promptTemplate),"image",void 0,k==="auto"?Te(ne):k,"waiting",5,{provider:we,task_type:ot,preset_name:a.name,client_task_id:Z}),(async()=>{try{T(Z,5,o("이미지 업로드 중...","画像をアップロード中...","Uploading images..."));const de=await Is(),be=de[0],oe=d&&de.length>c.length?de[de.length-1]:void 0,Y=Fr(a.previewImage),He=[];Y&&(He.push(Y),pe.log("📸 [ShortsAgentView] Template reference image:",Y)),He.push(...de),T(Z,15,o("AI 프롬프트 최적화 중...","AIプロンプトを最適化中...","Optimizing prompt..."));let ze=Ss();try{pe.log("🧠 [ShortsAgentView] Adapting prompt via Claude...");const{data:qe,error:Ot}=await ve.functions.invoke("adapt-ad-prompt",{body:{productImageUrl:be,presetPromptTemplate:a.promptTemplate,presetName:a.name,category:a.category,faceImageUrl:oe,customPrompt:u||void 0,templateReferenceImageUrl:Y}});!Ot&&qe?.success&&qe?.adaptedPrompt&&(ze=Xt(qe.adaptedPrompt),pe.log("✅ [ShortsAgentView] Adapted prompt:",ze.substring(0,120)+"..."))}catch{}E(Z,"generating"),T(Z,25,o("이미지 생성 요청 중...","画像生成をリクエスト中...","Requesting generation..."));const le={model_id:"8fb8755a-f16a-4240-ad9c-0699be359700",model_key:"gpt-image-2",provider_name:we,service_name:"GPT Image 2",mode:"editing",prompt:ze,image_urls:He,has_image:!0,size:k==="auto"?Te(ne):k,resolution:w,quality:"medium",excludeProviders:["atlas"],output_format:L,preset_name:a.name,task_type:ot,generationOptions:{provider:we,task_type:ot,preset_name:a.name,client_task_id:Z}};pe.log("🎨 [ShortsAgentView] Payload:",JSON.stringify(le));const{data:he,error:Be}=await Tr(le);if(Be||!he?.success)throw new Error(he?.error||Be?.message||"Generation failed");const tt=he?.imageUrl||(Array.isArray(he?.images)&&he.images.length>0?he.images[0]:null)||he?.data?.imageUrl;if(tt&&typeof tt=="string"&&tt.startsWith("http"))y(Z,tt),xe.success("✨ "+o("AD 생성 완료!","AD生成完了!","AD Generation Complete!"),{description:a.name}),t?.id&&ve.from("user_image_library").update({task_type:ot,preset_name:a.name,service_name:Ke}).eq("user_id",t.id).eq("image_url",tt).is("deleted_at",null).then(()=>{});else{const qe=he?.taskId||he?.data?.data?.taskId,Ot=he?.provider||we;if(qe){z(Z,qe);const Xe={provider:Ot,task_type:ot,preset_name:a.name,client_task_id:Z};Q(Z,qe,ze,5,Ke,Ke,void 0,a.name,Xe)}}}catch(de){j(Z,de.message),xe.error(o("생성 실패","生成失敗","Generation Failed"),{description:de.message})}})()},[l,Ae,Ue,ce,t,Is,Ss,Je,Te,Ct,Ft,Gt,C,T,E,z,y,j,Q,S,Fe,o]),tr=(0,s.useCallback)(async(a,c)=>{try{const d=a?.context;if(d&&typeof d.clone=="function"&&typeof d.json=="function"){const u=await d.clone().json();if(u?.insufficientCredits){const k=typeof u.available=="number"?u.available:0,w=typeof u.required=="number"?u.required:0;return f(w),o(`크레딧이 부족합니다. (보유 ${k} / 필요 ${w})`,`クレジットが不足しています。(保有${k} / 必要${w})`,`Insufficient credits. (available ${k} / required ${w})`)}if(typeof u?.error=="string"&&u.error.trim())return u.error}}catch{}return a?.message||c},[h,f]),Ea=(0,s.useRef)(new Map),Un=(0,s.useCallback)(async a=>{if(l){const u=oa(Yr.heroImage),k=Yr.productImages.map(oa).filter(w=>!!w);if(u)return await new Promise(w=>{setTimeout(w,2400)}),{heroImageUrl:u,productImageUrls:k}}if(!t?.id)throw new Error(o("로그인이 필요합니다.","ログインが必要です。","Login is required."));const c=Ea.current.get(a.sessionId);if(c)return pe.log("🔒 [createRepImage] In-flight hero gen detected for session",a.sessionId,"— reusing existing promise"),c;const d=(async()=>{const u=`ad-hero-lock-${a.sessionId}`,k=(()=>{try{return JSON.parse(localStorage.getItem(u)||"null")}catch{return null}})();if(k?.taskId){pe.log("🔄 [createRepImage] 기존 hero task 복구 시도:",k.taskId);try{const{data:Xe}=await ve.from("user_tasks").select("status, result_url").eq("task_id",k.taskId).maybeSingle();if(Xe?.status==="completed"&&Xe?.result_url)return pe.log("✅ [createRepImage] 기존 hero task 완료 — 복구:",Xe.result_url),localStorage.removeItem(u),{heroImageUrl:Xe.result_url,productImageUrls:k.productImageUrls||[],faceImageUrl:k.faceImageUrl};
116if(Xe?.status==="processing"){pe.log("⏳ [createRepImage] 기존 hero task 진행 중 — 폴링 재개:",k.taskId);const At=k.provider||await Ha(k.taskId),zt=Date.now();let Ge=null;for(;!Ge&&Date.now()-zt<ss();){const Yt=await za(k.taskId,At,"GPT Image 2","GPT Image 2");if(Yt.status==="completed"){Ge=la(Yt.result);break}if(Yt.status==="failed")throw localStorage.removeItem(u),new Error(Yt.error||"Hero image generation failed.");await ns(as)}if(Ge)return localStorage.removeItem(u),{heroImageUrl:Ge,productImageUrls:k.productImageUrls||[],faceImageUrl:k.faceImageUrl}}localStorage.removeItem(u)}catch{localStorage.removeItem(u)}}if(pe.log("🖼️ [createRepImage] agentSession images:",{productImages:a.productImages,productImagesCount:a.productImages?.length??0,faceImage:a.faceImage}),!((a.productImages?.length??0)>0)){pe.log("🖼️ [createRepImage] No product images — text-only service mode");const Xe=ra(a.preset,""),At=a.preset.category||"service",zt=Fr(a.preset.previewImage),Ge=a.highlights?`This is a service advertisement (no physical product). The service/brand being advertised: ${a.highlights}. If the template reference image shows a model holding or displaying a physical product, REMOVE the product entirely and instead have the model pose or gesture in a way that naturally represents this service concept (e.g. using a phone, pointing at something, confident lifestyle pose). Create a hero image that visually represents this service concept.`:"This is a service advertisement (no physical product). If the template reference image shows a model holding or displaying a physical product, REMOVE the product entirely and instead have the model in a natural, service-appropriate pose or lifestyle gesture. Create an evocative conceptual hero image based purely on the template's visual direction.",Yt=zt?[zt]:[];let Pr=Xt(`Professional 쇼츠 ${At} advertisement photograph. Use this registered template prompt as the primary creative direction: ${Xe}. Keep the template's camera composition, framing, lens feel, focal length, background, set dressing, props, mise-en-scene, lighting, texture, grain, color grading, and overall atmosphere. `+(zt?"The reference image is the template scene guide — use it only for atmosphere and composition, do NOT keep any product or person from it. ":"")+`Do NOT integrate any product object into the scene. ${Ge} Cinematic 8K quality, premium commercial photography. ${Ba} No watermarks, no product packaging.`);try{const{data:rr,error:Kr}=await ve.functions.invoke("adapt-ad-prompt",{body:{presetPromptTemplate:Xe,presetName:a.preset.name,category:a.preset.category,customPrompt:a.highlights||void 0,templateReferenceImageUrl:zt,serviceOnlyMode:!0}});!Kr&&rr?.success&&rr?.adaptedPrompt&&(Pr=Xt(`${rr.adaptedPrompt} ${Ge} Do NOT include any physical product object.`.trim()))}catch{}const Br=a.aspectRatio==="auto"?Te(a.imageDimensions):a.aspectRatio,{data:Rt,error:Dr}=await Tr({model_id:"8fb8755a-f16a-4240-ad9c-0699be359700",model_key:"gpt-image-2",provider_name:"evolink",service_name:"GPT Image 2",mode:Yt.length>0?"editing":"generation",prompt:Pr,image_urls:Yt,has_image:Yt.length>0,size:Br,resolution:a.resolution,quality:"medium",excludeProviders:["atlas"],output_format:a.outputFormat,preset_name:a.preset.name,task_type:ot,generationOptions:{provider:"evolink",task_type:ot,preset_name:a.preset.name,ad_workflow:"video_agent_hero"}});if(Dr||!Rt?.success){const rr="Hero image generation failed (text-only mode)",Kr=Dr?await tr(Dr,rr):Rt?.error||rr;throw new Error(Kr)}let Or=la(Rt);if(!Or){const rr=cn(Rt);if(!rr)throw new Error(o("대표 이미지 task ID를 받지 못했습니다.","ヒーロー画像のタスクIDが返されませんでした。","Hero image task ID was not returned."));const Kr=typeof Rt?.provider=="string"&&Rt.provider.trim()?Rt.provider:await Ha(rr);localStorage.setItem(u,JSON.stringify({taskId:rr,provider:Kr,productImageUrls:[],faceImageUrl:void 0}));const to=Date.now();for(;!Or&&Date.now()-to<ss();){const xa=await za(rr,Kr,"GPT Image 2","GPT Image 2");if(xa.status==="completed"){Or=la(xa.result);break}if(xa.status==="failed")throw localStorage.removeItem(u),new Error(xa.error||"Hero image generation failed.");await ns(as)}}if(!Or)throw new Error(o("대표 이미지 생성이 지연되고 있습니다.","ヒーロー画像の生成が遅れています。","Hero image generation timed out."));return localStorage.removeItem(u),{heroImageUrl:Or,productImageUrls:[],faceImageUrl:void 0}}const w=await Dt(a.productImages,a.faceImage);pe.log("🖼️ [createRepImage] uploadedUrls:",w),w[0];const L=w.slice(0,a.productImages.length),ne=a.faceImage&&w.length>a.productImages.length?w[w.length-1]:void 0,Z=Fr(a.preset.previewImage),we=[...L,...ne?[ne]:[],...Z?[Z]:[]];pe.log("🖼️ [createRepImage] final referenceImages:",we);const de=ra(a.preset,"");a.preset.category;const be=L.length>1?`The first ${L.length}
116 reference images are user-provided product photos from multiple angles. Use them as the actual product source and preserve the exact packaging, labels, logo, colors, and structure.`:"The first reference image is the user-provided product photo. Use it as the actual hero product and preserve the exact packaging, labels, logo, colors, and structure.",oe=ne?L.length>1?"The next reference image is the user-provided model face. Use this exact person if a human appears, matching facial features, skin tone, and likeness closely.":"The second reference image is the user-provided model face. Use this exact person if a human appears, matching facial features, skin tone, and likeness closely.":"",Y=Z?"The last reference image is THE INFLUENCER. Keep ONLY that person — the same face, hair character, age feel and overall look, so viewers recognise the same creator. Everything else MUST change to suit this product: choose a different location, different wardrobe, different props and time of day. Do NOT reuse that image's setting or outfit, and do not keep its original product.":"",He=a.highlights?`Additional user guidance to weave in naturally: ${a.highlights}.`:"",ze="The product must appear exactly as photographed in its reference: same closure and cap state, nothing attached or inserted that the photo does not show — no straw, spoon, ribbon, sticker or accessory added to it.",le="If the product reference reveals a clear brand or accent color, echo that point color naturally through selected props, wardrobe accents, background accents, styling details, or lighting cues so the hero image feels tonally aligned to the product. Keep it tasteful and template-appropriate rather than flooding the whole frame with that color.";let he="";he=Xt(`Vertical 9:16 product advertising photograph for a short-form video. ${be} ${zs} ${oe} ${Y} Build a scene that genuinely suits THIS product — pick the location, wardrobe and props a real person would naturally have around them when using it. Only the influencer's face and identity carry over from the reference; the place and the outfit are chosen fresh for this product. The person is Korean, fully clothed in ordinary everyday wear appropriate to that setting, holding or using the product naturally. ${le} ${He} Clean modern commercial quality. ${Ba} ${ze}`),a.preset.id?.startsWith("auto_")&&(he=Xt(`${de} ${be} ${zs} ${oe} ${le} ${He} ${ze} ${Ba}`.trim()),pe.log("🎛️ [createRepImage] Auto-concept preset — using recipe-driven hero scene prompt as-is")),he=$l(he);const Be=a.aspectRatio==="auto"?Te(a.imageDimensions):a.aspectRatio,tt={model_id:"8fb8755a-f16a-4240-ad9c-0699be359700",model_key:"gpt-image-2",provider_name:"evolink",service_name:"GPT Image 2",mode:"editing",prompt:he,image_urls:we,has_image:!0,size:Be,resolution:a.resolution,quality:"medium",excludeProviders:["atlas"],output_format:a.outputFormat,preset_name:a.preset.name,task_type:ot,generationOptions:{provider:"evolink",task_type:ot,preset_name:a.preset.name,ad_workflow:"video_agent_hero"}};let qe=null;for(let Xe=0;Xe<2;Xe++){const At=await Tr(tt);if(!At.error&&At.data?.success){qe=At.data;break}const zt="Representative image generation failed",Ge=At.error?await tr(At.error,zt):At.data?.error||zt;if(Xe===0&&es(Ge)){pe.warn("🛡️ [createRepImage] 모더레이션 거부 → 프롬프트 강화 후 재시도"),tt.prompt=Ml(tt.prompt);continue}throw new Error(es(Ge)?o("이미지가 안전 정책에 걸려 생성되지 않았습니다. 프롬프트를 자동으로 순화해 한 번 더 시도했지만 통과하지 못했어요. 다른 인플루언서를 골라 다시 시도해 주세요.","画像が安全ポリシーに抵触して生成できませんでした。プロンプトを自動で調整して再試行しましたが通りませんでした。別のインフルエンサーを選んでお試しください。","The image was blocked by the safety policy. We softened the prompt and retried once, but it still did not pass. Please pick a different influencer and try again."):Ge)}let Ot=la(qe);if(!Ot){const Xe=cn(qe);if(!Xe)throw new Error(o("대표 이미지 task ID를 받지 못했습니다.","ヒーロー画像のタスクIDが返されませんでした。","Representative image task ID w
116as not returned."));const At=typeof qe?.provider=="string"&&qe.provider.trim()?qe.provider:await Ha(Xe);localStorage.setItem(u,JSON.stringify({taskId:Xe,provider:At,productImageUrls:L,faceImageUrl:ne}));const zt=Date.now();for(;!Ot&&Date.now()-zt<ss();){const Ge=await za(Xe,At,"GPT Image 2","GPT Image 2");if(Ge.status==="completed"){if(Ot=la(Ge.result),!Ot)throw new Error(o("대표 이미지 생성은 완료됐지만 결과 URL을 찾지 못했습니다.","代表画像の生成は完了しましたが、結果URLが見つかりませんでした。","Representative image generation completed, but no result URL was found."));break}if(Ge.status==="failed")throw localStorage.removeItem(u),new Error(es(Ge.error)?o("이미지가 안전 정책에 걸려 생성되지 않았습니다. 다른 인플루언서를 골라 다시 시도해 주세요.","画像が安全ポリシーに抵触して生成できませんでした。別のインフルエンサーを選んでお試しください。","The image was blocked by the safety policy. Please pick a different influencer and try again."):Ge.error||o("대표 이미지 생성에 실패했습니다.","代表画像の生成に失敗しました。","Representative image generation failed."));await ns(as)}}if(!Ot||typeof Ot!="string")throw new Error(o("대표 이미지 생성이 지연되고 있습니다. 잠시 후 다시 시도해 주세요.","代表画像の生成が遅れています。しばらくしてから再試行してください。","Representative image generation is taking longer than expected. Please try again shortly."));return localStorage.removeItem(u),{heroImageUrl:Ot,productImageUrls:L,faceImageUrl:ne}})();Ea.current.set(a.sessionId,d);try{return await d}finally{Ea.current.delete(a.sessionId)}},[ra,Te,h,tr,Dt,t?.id]),aa=(0,s.useRef)(null),Dn=(0,s.useCallback)(async({session:a,heroImageUrl:c,productImageUrls:d,faceImageUrl:u,finalPrompt:k,storyboardDraft:w,quality:L="720p"})=>{if(l){const oe=oa(Yr.finalVideo);if(oe)return await new Promise(Y=>{setTimeout(Y,3400)}),{clientTaskId:`tutorial-shorts-${a.sessionId}`,resultUrl:oe}}const ne=a.videoDuration||Re,Z=a.seedanceEngine??"2.0",we=q(ne,L,Z),de=a.sessionId;if(aa.current===de)throw new Error("Video generation already in progress for this session");aa.current=de;let be;try{const oe=Ul(k),Y=`local_${Date.now()}`,He=Z==="2.5"?St(a.aspectRatio):a.aspectRatio==="16:9"?"16:9":"9:16";pe.log("🎬 [startShortsVideoGeneration] aspect_ratio =",He);const ze=[c,...d,...u?[u]:[]].filter((Rt,Dr,Or)=>!!Rt&&Or.indexOf(Rt)===Dr),le=El,he=ze.slice(0,le),Be=ze.length-he.length;Be>0&&xe.warning(o(`참조 이미지는 최대 ${le}장까지만 사용됩니다`,`参照画像は最大${le}枚まで使用されます`,`Only up to ${le} reference images are used`),{description:o(`제품 사진 ${Be}장을 제외하고 생성합니다. 중요한 사진을 앞쪽에 두려면 제품 사진 수를 줄여 주세요.`,`商品写真${Be}枚を除いて生成します。重要な写真を優先するには商品写真の枚数を減らしてください。`,`Generating without ${Be} product photo(s). Reduce the number of product photos to prioritize the ones you need.`)});const tt={provider:"segmind",task_type:ot,preset_name:a.preset.name,client_task_id:Y,ad_workflow:"video_agent",image_urls:he,_sourceImageUrl:c,_sourceProductImageUrls:d};tt.video_engine="seedance-2",tt.duration=ne,tt.quality=L,tt.tier="pro",w&&(tt.ad_title=w.title||"",tt.ad_storyboard={title:w.title,conceptSummary:w.conceptSummary,cuts:w.cuts,narration:w.narration,dialogue:w.dialogue,directorNote:w.directorNote}),C(Y,Y,Ke,Ke,oe,"video",void 0,He,"waiting",we,tt),T(Y,10,o("영상 생성 시작 중...","動画生成を開始中...","Starting video generation..."));const qe=ji(Z,ne),Ot={model_id:qe.model_id,model_key:qe.model_key,provider_name:"byteplus",force_provider:"byteplus",ad_channel:!0,service_name:qe.service_name,mode:"video",prompt:oe,has_image:!0},Xe=na(Ot,{aspect_ratio:He,duration:ne,quality:Ks(Z,ne,L),tier:"pro",generate_audio:!0,web_search:!1,use_omni:!0,seedance2_mode:"omni"},he);Xe.generationOptions=tt,Xe.task_type=ot,Xe.preset_name=a.preset.name,w?.title&&(Xe.display_name=w.title);const At=Tr(Xe),zt=new Promise((Rt,Dr)=>{be=setTimeout(()=>
116Dr(new Error(o("영상 주문 시간이 초과되었습니다. 다시 시도해 주세요.","動画リクエストがタイムアウトしました。もう一度お試しください。","Video request timed out. Please try again."))),12e4)}),{data:Ge,error:Yt}=await Promise.race([At,zt]);if(Yt||!Ge?.success){(Ge??Yt?.context?.data??null)?.insufficientCredits===!0&&f(we);const Rt=Ge?.error||Yt?.message||"Video generation failed";throw j(Y,Rt),new Error(Rt)}const Pr=Ge?.resultUrl||Ge?.videoUrl||Ge?.imageUrl||Ge?.data?.result_url||Ge?.data?.video_url;if(Pr&&typeof Pr=="string")return t?.id&&(async()=>{try{await ve.functions.invoke("download-bbanana-image",{body:{imageUrl:Pr,userId:t.id,mediaType:"video",modelName:Ot.service_name,mode:"video",taskId:Y,prompt:oe,presetName:a.preset.name,task_type:ot,generationOptions:tt}})}catch{}})(),y(Y,Pr),{clientTaskId:Y,resultUrl:Pr};const Br=Ge?.taskId||Ge?.data?.task_id||Ge?.data?.data?.taskId;if(!Br)throw j(Y,o("영상 task ID를 수신하지 못했습니다.","動画タスクIDを受信できませんでした。","Video task ID was not returned.")),new Error(o("영상 task ID를 수신하지 못했습니다.","動画タスクIDを受信できませんでした。","Video task ID was not returned."));return z(Y,Br),Q(Y,Br,oe,we,Ke,Ke,10,a.preset.name,tt),{clientTaskId:Y,apiTaskId:Br}}finally{clearTimeout(be),aa.current=null}},[C,y,j,Te,q,h,Tt,St,f,Q,z,T,Re,t?.id]),[Se,yr]=(0,s.useState)(null),[sa,Aa]=(0,s.useState)(null),[jr,Nr]=(0,s.useState)(!1),{row:lt}=xi(v),[On,Ns]=(0,s.useState)(null);(0,s.useEffect)(()=>{Ns(null)},[Se?.id]);const ha=Se?.shiftVariants?Se.shiftVariants.find(a=>a.key===On)??Se.shiftVariants[0]:null,ct=ha?.sourceUrl||Se?.shiftSourceVideoUrl||"";(0,s.useEffect)(()=>{if(!ct){Aa(null);return}let a=!0;return Aa(null),ki(ct).then(c=>{a&&Aa({url:ct,...c})}),()=>{a=!1}},[ct]);const nt=sa?.url===ct&&sa?.durationSec||0,br=Do(l?null:Xr),fa=mo(),mr=(0,s.useMemo)(()=>!br.hasGrant||br.dailyLimit!=null&&br.remainingToday<=0||Array.isArray(br.allowedSources)&&br.allowedSources.length>0?null:{maxQuality:br.maxQuality,eventName:br.eventName,maxDurationSec:br.maxDurationSec},[br]),Ra=ha?.templateKey||Se?.id,xr=(0,s.useCallback)(a=>!!mr&&(!mr.maxQuality||qs(a)<=qs(mr.maxQuality))&&Ga(mr.maxDurationSec,Ra,nt||null),[mr,Ra,nt]),ga=mr&&Ga(mr.maxDurationSec,Ra,nt||null)?mr:null,dt=ha?.templateKey||Se?.id,$a=(0,s.useCallback)((a,c,d,u)=>!lt||!(nt>0)?null:xr(c)?0:Pl({variants:lt.model_variants||[],quality:c,sourceSeconds:nt,templateKey:dt,mode:a,roles:d,isAdmin:v,hasPrompt:!!String(u??"").trim()}),[lt,nt,v,xr,dt]),Jt=(0,s.useRef)(!1),Ln=(0,s.useCallback)(async a=>{if(!Se||!lt||!t?.id)return;if(l){xe.info(o("연습 화면에서는 실제 영상 편집을 시작하지 않습니다.","練習画面では実際の動画編集は開始しません。","Video edits are not started on the practice screen."));return}if(Jt.current)return;if(!(nt>0)){xe.error(o("영상 정보를 읽지 못했습니다. 잠시 후 다시 시도해 주세요.","動画情報を読み取れませんでした。しばらくしてからもう一度お試しください。","Could not read the video details. Please try again shortly."));return}const c=$a(a.mode,a.quality,a.referenceRoles,a.userPrompt);if(c===null)return;Jt.current=!0,Nr(!0);const d=`local_${Date.now()}`;try{if(!await I(c)){f(c);return}const u=a.referenceImages.length>0?await Dt(a.referenceImages,null):[],k=Se.shiftSlots?.find(le=>le.role==="lead")?.wardrobe!=="replace",w=Object.fromEntries(An(Se).map(le=>[le.key,o(le.label.ko,le.label.ja,le.label.en)])),L=a.userPrompt||a.referenceRoles.map(le=>w[le]).join(" · "),ne=sa?.width||0,Z=sa?.height||0,we=ne>0&&Z>0?ne>Z?"16:9":ne<Z?"9:16":"1:1":"16:9",de=Math.min(30,Math.max(4,Math.round(nt))),be={provider:"byteplus",task_type:ot,preset_name:Se.name,client_task_id:d,ad_workflow:"shift_template",shift_template_key:dt,shift_template_roles:a.referenceRoles,shift_template_user_prompt:a.userPrompt,shift_mode:a.mode,shift_preserve_wardrobe:k,seedance25_mode:"edit",quality:a.quality,duration:de,input_video_duration:nt,aspect_ratio:we,generate_audio:!1,image_urls:u,_sourceVideoUrl:ct};C(d,d,Ke,Ke,L,"video",void 0,we,"waiting",c,be),T(d,10,o("영상 편집 시작 중...","動画編集を開始中...","Starting video edit..."));const oe=na({model_id:lt.id,provider_name:"byteplus",service_name:Xr,mode:"video",prompt:a.userPrompt,has_image:u.length>0,shift_template_key:dt,client_task_id:d},{aspect_ratio:we,duration:de,quality:a.quality,tier:"pro",generate_audio:!1,web_search:!1,use_omni:!1,seedance2_mode:"edit",shift_mode:a.mode,shift_preserve_wardrobe:k,input_video_duration:nt},u);va(oe,ct,null,nt),oe.generationOptions=be,oe.task_type=ot,oe.preset_name=Se.name,oe.shift_template_key=dt,oe.shift_template_roles=a.referenceRoles;const{data:Y,error:He}=await Tr(oe);if(He||!Y?.success){Y?.insufficientCredits===!0&&f(c);const le=o("영상 편집을 시작하지 못했습니다.","動画編集を開始できませんでした。","Could not start the video edit."),he=Y?.error||(He?await tr(He,le):le);throw j(d,he),new Error(he)}const ze=Y?.taskId||Y?.data?.task_id||Y?.data?.data?.taskId;if(!ze){const le=o("영상 task ID를 수신하지 못했습니다.","動画タスクIDを受信できませんでした。","Video task ID w
116as not returned.");throw j(d,le),new Error(le)}z(d,ze),Q(d,ze,L,c,Ke,Ke,10,Se.name,be),xe.success(o("영상 편집을 시작했습니다. 완료되면 내 작업에 나타납니다.","動画編集を開始しました。完了すると「マイ作品」に表示されます。","Video edit started. It will appear in My Works when done.")),c===0&&fa.invalidateQueries({queryKey:["unlimited-grant-status"]}),yr(null),B("history")}catch(u){const k=String(u?.message||""),w=/image load failed/i.test(k)?o("사진을 열지 못했습니다. JPG·PNG·WebP 로 저장해 다시 올려 주세요. (아이폰 사진은 HEIC 형식일 수 있습니다)","写真を開けませんでした。JPG・PNG・WebP で保存して再度アップロードしてください。(iPhone の写真は HEIC 形式の場合があります)","Could not open the photo. Please save it as JPG, PNG or WebP and upload again. (iPhone photos may be in HEIC format.)"):k||o("영상 편집 주문에 실패했습니다.","動画編集の依頼に失敗しました。","Could not start the video edit.");xe.error(w)}finally{Jt.current=!1,Nr(!1)}},[Se,lt,t?.id,l,nt,sa,ct,dt,$a,I,f,tr,Dt,C,T,z,j,Q]),Cs=ul(dt),ya=lt?xr("480p")?0:10:null,Fn=(0,s.useCallback)(async a=>{if(!Se||!lt||!t?.id)return;if(l){xe.info(o("연습 화면에서는 실제 영상 편집을 시작하지 않습니다.","練習画面では実際の動画編集は開始しません。","Video edits are not started on the practice screen."));return}if(Jt.current)return;const c=ya;if(c===null)return;Jt.current=!0,Nr(!0);const d=`local_${Date.now()}`;try{if(!await I(c)){f(c);return}const u=await Dt(a.items.map(oe=>oe.image),null),k=a.items.map(oe=>({ko:oe.ko,en:oe.en})),w=k.map(oe=>oe.ko).join(" · "),L=nt>0?nt:10,ne={provider:"byteplus",task_type:ot,preset_name:Se.name,client_task_id:d,ad_workflow:"shift_template",shift_template_key:dt,shift_template_user_prompt:w,shift_composite_labels:k,quality:"480p",aspect_ratio:"9:16",generate_audio:!1,image_urls:u,_sourceVideoUrl:ct};C(d,d,Ke,Ke,w,"video",void 0,"9:16","waiting",c,ne),T(d,10,o("영상 만드는 중...","動画を作成中...","Creating video..."));const Z=na({model_id:lt.id,provider_name:"byteplus",service_name:Xr,mode:"video",prompt:w,has_image:!0,shift_template_key:dt,client_task_id:d},{aspect_ratio:"9:16",duration:Math.min(30,Math.max(4,Math.round(L))),quality:"480p",tier:"pro",generate_audio:!1,web_search:!1,use_omni:!1,seedance2_mode:"edit",shift_mode:"restyle",input_video_duration:L},u);va(Z,ct,null,L),Z.generationOptions=ne,Z.task_type=ot,Z.preset_name=Se.name,Z.shift_template_key=dt,Z.shift_composite_labels=k;const{data:we,error:de}=await Tr(Z);if(de||!we?.success){we?.insufficientCredits===!0&&f(c);const oe=o("영상 만들기를 시작하지 못했습니다.","動画作成を開始できませんでした。","Could not start the video."),Y=we?.error||(de?await tr(de,oe):oe);throw j(d,Y),new Error(Y)}const be=we?.taskId||we?.data?.task_id||we?.data?.data?.taskId;if(!be){const oe=o("영상 task ID를 수신하지 못했습니다.","動画タスクIDを受信できませんでした。","Video task ID was not returned.");throw j(d,oe),new Error(oe)}z(d,be),Q(d,be,w,c,Ke,Ke,10,Se.name,ne),xe.success(o("영상 만들기를 시작했습니다. 완료되면 내 작업에 나타납니다.","動画作成を開始しました。完了すると「マイ作品」に表示されます。","Video started. It will appear in My Works when done.")),c===0&&fa.invalidateQueries({queryKey:["unlimited-grant-status"]}),yr(null),B("history")}catch(u){const k=String(u?.message||""),w=/image load failed/i.test(k)?o("사진을 열지 못했습니다. JPG·PNG·WebP 로 저장해 다시 올려 주세요. (아이폰 사진은 HEIC 형식일 수 있습니다)","写真を開けませんでした。JPG・PNG・WebP で保存して再度アップロードしてください。(iPhone の写真は HEIC 形式の場合があります)","Could not open the photo. Please save it as JPG, PNG or WebP and upload again. (iPhone photos may be in HEIC format.)"):k||o("영상 만들기 주문에 실패했습니다.","動画作成の依頼に失敗しました。","Could not start the video.");xe.error(w)}finally{Jt.current=!1,Nr(!1)}},[Se,lt,t?.id,l,nt,ct,dt,ya,I,f,tr,Dt,C,T,z,j,Q]),Ps=xl(dt),Ma=(0,s.useCallback)((a,c)=>lt?Il({outfits:a,resolution:c}):null,[lt]),Gn=(0,s.useCallback)(async a=>{if(!Se||!lt||!t?.id)return;if(l){xe.info(o("연습 화면에서는 실제 영상 편집을 시작하지 않습니다.","練習画面では実際の動画編集は開始しません。","Video edits are not started on the practice screen."));return}if(Jt.current)return;const c=a.resolution,d=Ma(a.outfits.length,c);if(d===null)return;const u=xr(c)?0:d;Jt.current=!0,Nr(!0);const k=`local_${Date.now()}`;try{if(!await I(u)){f(u);return}const w=await Dt(a.outfits,null),L=Math.round(Sa(w.length)),ne=`${Se.name} · ${o(`${w.length}벌`,`${w.length}着`,`${w.length} outfits`)}`,Z=nt>0?nt:10,we={provider:"byteplus",task_type:ot,preset_name:Se.name,client_task_id:k,ad_workflow:"shift_template",shift_template_key:dt,shift_template_user_prompt:ne,shift_crayon_resolution:c,...a.prompt?{shift_crayon_prompt:a.prompt}:{}
116,quality:c,aspect_ratio:"9:16",generate_audio:!1,image_urls:w,_sourceVideoUrl:ct};C(k,k,Ke,Ke,ne,"video",void 0,"9:16","waiting",u,we),T(k,10,o("영상 만드는 중...","動画を作成中...","Creating video..."));const de=na({model_id:lt.id,provider_name:"byteplus",service_name:Xr,mode:"video",prompt:ne,has_image:!0,shift_template_key:dt,client_task_id:k},{aspect_ratio:"9:16",duration:Math.min(30,Math.max(4,Math.round(Z))),quality:c,tier:"pro",generate_audio:!1,web_search:!1,use_omni:!1,seedance2_mode:"edit",shift_mode:"restyle",input_video_duration:Z},w);va(de,ct,null,Z),de.generationOptions=we,de.task_type=ot,de.preset_name=Se.name,de.shift_template_key=dt,de.shift_crayon_resolution=c,a.prompt&&(de.shift_crayon_prompt=a.prompt);const{data:be,error:oe}=await Tr(de);if(oe||!be?.success){be?.insufficientCredits===!0&&f(u);const He=o("영상 만들기를 시작하지 못했습니다.","動画作成を開始できませんでした。","Could not start the video."),ze=be?.error||(oe?await tr(oe,He):He);throw j(k,ze),new Error(ze)}const Y=be?.taskId||be?.data?.task_id||be?.data?.data?.taskId;if(!Y){const He=o("영상 task ID를 수신하지 못했습니다.","動画タスクIDを受信できませんでした。","Video task ID was not returned.");throw j(k,He),new Error(He)}z(k,Y),Q(k,Y,ne,u,Ke,Ke,L,Se.name,we),xe.success(o("영상 만들기를 시작했습니다. 완료되면 내 작업에 나타납니다.","動画作成を開始しました。完了すると「マイ作品」に表示されます。","Video started. It will appear in My Works when done.")),u===0&&fa.invalidateQueries({queryKey:["unlimited-grant-status"]}),yr(null),B("history")}catch(w){const L=String(w?.message||""),ne=/image load failed/i.test(L)?o("사진을 열지 못했습니다. JPG·PNG·WebP 로 저장해 다시 올려 주세요. (아이폰 사진은 HEIC 형식일 수 있습니다)","写真を開けませんでした。JPG・PNG・WebP で保存して再度アップロードしてください。(iPhone の写真は HEIC 形式の場合があります)","Could not open the photo. Please save it as JPG, PNG or WebP and upload again. (iPhone photos may be in HEIC format.)"):L||o("영상 만들기 주문에 실패했습니다.","動画作成の依頼に失敗しました。","Could not start the video.");xe.error(ne)}finally{Jt.current=!1,Nr(!1)}},[Se,lt,t?.id,l,nt,ct,dt,Ma,xr,I,f,tr,Dt,C,T,z,j,Q]),Ts=hl(dt),Ua=(0,s.useCallback)((a,c)=>lt?yl({resolution:a,background:c}):null,[lt]),Vn=(0,s.useCallback)(async a=>{if(!Se||!lt||!t?.id)return;if(l){xe.info(o("연습 화면에서는 실제 영상 편집을 시작하지 않습니다.","練習画面では実際の動画編集は開始しません。","Video edits are not started on the practice screen."));return}if(Jt.current)return;const c=10,d=a.resolution,u=!!a.background,k=Ua(d,u);if(k===null)return;const w=xr(d)?0:k;Jt.current=!0,Nr(!0);const L=`local_${Date.now()}`;try{if(!await I(w)){f(w);return}const ne=await Dt(u?[a.image,a.background]:[a.image],null),Z=`${Se.name} · ${o(`${c}초`,`${c}秒`,`${c}s`)}`,we=nt>0?nt:10,de={provider:"byteplus",task_type:ot,preset_name:Se.name,client_task_id:L,ad_workflow:"shift_template",shift_template_key:dt,shift_template_user_prompt:Z,shift_drink_duration:c,shift_drink_background:u,shift_drink_resolution:d,...a.prompt?{shift_drink_prompt:a.prompt}:{},quality:d,aspect_ratio:"16:9",generate_audio:!1,image_urls:ne,_sourceVideoUrl:ct};C(L,L,Ke,Ke,Z,"video",void 0,"16:9","waiting",w,de),T(L,10,o("영상 만드는 중...","動画を作成中...","Creating video..."));const be=na({model_id:lt.id,provider_name:"byteplus",service_name:Xr,mode:"video",prompt:Z,has_image:!0,shift_template_key:dt,client_task_id:L},{aspect_ratio:"16:9",duration:Math.min(30,Math.max(4,Math.round(we))),quality:d,tier:"pro",generate_audio:!1,web_search:!1,use_omni:!1,seedance2_mode:"edit",shift_mode:"restyle",input_video_duration:we},ne);va(be,ct,null,we),be.generationOptions=de,be.task_type=ot,be.preset_name=Se.name,be.shift_template_key=dt,be.shift_drink_duration=c,be.shift_drink_background=u,be.shift_drink_resolution=d,a.prompt&&(be.shift_drink_prompt=a.prompt);const{data:oe,error:Y}=await Tr(be);if(Y||!oe?.success){oe?.insufficientCredits===!0&&f(w);const ze=o("영상 만들기를 시작하지 못했습니다.","動画作成を開始できませんでした。","Could not start the video."),le=oe?.error||(Y?await tr(Y,ze):ze);throw j(L,le),new Error(le)}const He=oe?.taskId||oe?.data?.task_id||oe?.data?.data?.taskId;if(!He){const ze=o("영상 task ID를 수신하지 못했습니다.","動画タスクIDを受信できませんでした。","Video task ID w
116as not returned.");throw j(L,ze),new Error(ze)}z(L,He),Q(L,He,Z,w,Ke,Ke,10,Se.name,de),xe.success(o("영상 만들기를 시작했습니다. 완료되면 내 작업에 나타납니다.","動画作成を開始しました。完了すると「マイ作品」に表示されます。","Video started. It will appear in My Works when done.")),w===0&&fa.invalidateQueries({queryKey:["unlimited-grant-status"]}),yr(null),B("history")}catch(ne){const Z=String(ne?.message||""),we=/image load failed/i.test(Z)?o("사진을 열지 못했습니다. JPG·PNG·WebP 로 저장해 다시 올려 주세요. (아이폰 사진은 HEIC 형식일 수 있습니다)","写真を開けませんでした。JPG・PNG・WebP で保存して再度アップロードしてください。(iPhone の写真は HEIC 形式の場合があります)","Could not open the photo. Please save it as JPG, PNG or WebP and upload again. (iPhone photos may be in HEIC format.)"):Z||o("영상 만들기 주문에 실패했습니다.","動画作成の依頼に失敗しました。","Could not start the video.");xe.error(we)}finally{Jt.current=!1,Nr(!1)}},[Se,lt,t?.id,l,nt,ct,dt,Ua,xr,I,f,tr,Dt,C,T,z,j,Q]),Cr=(0,s.useCallback)(()=>{gt(null),ba(null),bt([]),Nt(null),wt(null),me(null),Qt(""),Ar(!1)},[]);(0,s.useEffect)(()=>{const a=()=>Cr();return window.addEventListener(Fs,a),window.addEventListener(Gs,a),()=>{window.removeEventListener(Fs,a),window.removeEventListener(Gs,a)}},[Cr]);const Hn=(0,s.useCallback)(()=>{It(!1),l||B("history")},[l]),zn=(0,s.useCallback)(()=>{const a=it?.sessionId;if(It(!1),ir(null),Ut(null),a){Wt.current.add(a),setTimeout(()=>Wt.current.delete(a),3e4);const c=cr.find(d=>d.sessionId===a);Zs(t?.id,a,c?.taskId),vt(d=>d.filter(u=>u.sessionId!==a))}},[t?.id,it,cr]),qn=(0,s.useCallback)(a=>{Wt.current.add(a),setTimeout(()=>Wt.current.delete(a),3e4);const c=cr.find(d=>d.sessionId===a);Zs(t?.id,a,c?.taskId),vt(d=>d.filter(u=>u.sessionId!==a)),it?.sessionId===a&&(ir(null),Ut(null),It(!1))},[t?.id,it?.sessionId,cr]);(0,s.useCallback)(()=>{xe.info(o("준비 중","準備中","Coming Soon"),{description:o("Seedance 2.0 동영상 생성 기능이 곧 추가됩니다.","Seedance 2.0動画生成機能がまもなく追加されます。","Seedance 2.0 video generation is coming soon.")})},[o]);const Bn=(0,s.useCallback)(()=>{const a=Ae.length>0,c=Fe.trim().length>0;if(!a&&!c){xe.error(o("입력 오류","入力エラー","Input Error"),{description:o("제품 이미지 또는 서비스 설명을 입력해 주세요.","製品画像またはサービス説明を入力してください。","Please upload a product image or enter a service description.")});return}if(!ce){xe.error(o("입력 오류","入力エラー","Input Error"),{description:o("템플릿을 선택해 주세요.","テンプレートを選択してください。","Please select a template.")});return}if(!l&&!t?.id){xe.warning(o("로그인 필요","ログイン必要","Login Required"),{description:o("동영상 생성 전에 로그인해 주세요.","動画生成前にログインしてください。","Please log in before creating a video.")}),S();return}it&&(Ut(null),It(!1)),aa.current=null;const d=Mt?[...Ae,Mt]:[...Ae];pe.log("🎬 [handleMakeVideo] Creating agent session with:",{productImages:Ae,productImagesCount:Ae.length,faceImage:Ue,logoImage:!!Mt,totalReferenceImages:d.length});const u=ce.tone==="hold_explain"?{...ce,tone:"pov_review"}:ce,k={sessionId:`agent_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,preset:u,productImages:d,faceImage:Ue,highlights:[vr.trim()&&`제품명: ${vr.trim()}`,Fe.trim()].filter(Boolean).join(`
117`),aspectRatio:Ct,resolution:Ft,outputFormat:Gt,imageDimensions:Je,videoDuration:Re,seedanceEngine:Ie},w=Ja(k);vt(L=>[w,...L.filter(ne=>ne.sessionId!==k.sessionId)]),Ya(t.id,k).catch(L=>{pe.warn("[ShortsAgentView] Failed to persist initial agent session:",L)}),ir(k),It(!0),Ut(null),Cr()},[Cr,Fe,Ue,Mt,Je,ce,Ae,Ct,Re,Gt,Ft,Ie,S,t?.id,it,o]),[zr,Mr]=(0,s.useState)(null);fn((0,s.useCallback)(()=>{l&&Cr()},[l,Cr])),hn((0,s.useCallback)(a=>{l&&(a.includes(je.shortsStartConfirm)||Mr(null),It(a.includes("shorts-agent-")))},[l]));
117const[Ur,ba]=(0,s.useState)(null),[Kn,Es]=(0,s.useState)(!1),[Da,Kl]=(0,s.useState)(null),Wn=(0,s.useCallback)(a=>{if(!t?.id){xe.warning(o("로그인 필요","ログイン必要","Login Required"),{description:o("동영상 생성 전에 로그인해 주세요.","動画生成前にログインしてください。","Please log in before creating a video.")}),S();return}const{concept:c,productImageUrls:d,productName:u,highlights:k,sellingPoints:w}=a,L=u?[`제품명: ${u}`,k].filter(Boolean).join(`
118`):k;it&&(Ut(null),It(!1)),aa.current=null;const ne={id:`auto_${Date.now()}`,name:c.title||c.vibe||(h==="ja"?c.labelJa:h==="en"?c.labelEn:c.labelKo),description:c.logline||c.microStoryboard||c.hook,category:"product",colorSwatch:"#F43F5E",previewGradient:"linear-gradient(135deg, #F43F5E, #8B5CF6)",previewImage:"",promptTemplate:c.heroScenePrompt,tone:c.tone},Z={sessionId:`agent_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,preset:ne,productImages:d,faceImage:null,highlights:L,aspectRatio:Ct,resolution:Ft,outputFormat:Gt,imageDimensions:null,videoDuration:Re,seedanceEngine:Ie,autoConcept:{hook:c.hook,cta:c.cta,sellingPoints:w,recipe:c.recipe,casting:c.casting,location:c.location,visualStyle:c.visualStyle,hookAction:c.hookAction,productPitch:c.productPitch,benefit:c.benefit,speechStyle:c.speechStyle,narrationStyle:c.narrationStyle,cgModuleLabel:c.cgModuleLabel,cgIntensity:c.cgIntensity,cgDirection:c.cgDirection}},we=Ja(Z);vt(de=>[we,...de.filter(be=>be.sessionId!==Z.sessionId)]),Ya(t.id,Z).catch(de=>{pe.warn("[ShortsAgentView] Failed to persist initial auto-concept agent session:",de)}),ir(Z),It(!0),Ut(null),Es(!1)},[t?.id,it,h,Ct,Re,Gt,Ft,Ie,S,o]),Jn=(0,s.useCallback)(a=>{if(!t?.id){xe.warning(o("로그인 필요","ログイン必要","Login Required"),{description:o("동영상 생성 전에 로그인해 주세요.","動画生成前にログインしてください。","Please log in before creating a video.")}),S();return}it&&(Ut(null),It(!1));const c={id:`library_${Date.now()}`,name:o("내 이미지","マイ画像","My Image"),description:o("라이브러리 이미지로 영상 생성","ライブラリ画像から動画を生成","Create video from library image"),category:"service",colorSwatch:"#4F46E5",previewGradient:"linear-gradient(135deg, #4F46E5, #7C3AED)",previewImage:a,promptTemplate:""},d={sessionId:`agent_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,preset:c,productImages:[],faceImage:null,highlights:"",aspectRatio:Ct,resolution:Ft,outputFormat:Gt,imageDimensions:null,videoDuration:Re,seedanceEngine:Ie,presetHeroImageUrl:a},u=Ja(d);vt(k=>[u,...k.filter(w=>w.sessionId!==d.sessionId)]),Ya(t.id,d).catch(k=>{pe.warn("[ShortsAgentView] Failed to persist initial library agent session:",k)}),ir(d),It(!0),Ut(null)},[t?.id,it,Ct,Re,Ft,Gt,Ie,S,o]),Yn=ke.length+cr.length,Xn=(0,s.useMemo)(()=>A.slice(0,3).map(a=>cs(a.previewImage||"",{width:360,height:640,quality:55})||a.previewImage||null),[A]),Qn=(0,s.useMemo)(()=>{const a=R.find(c=>c.id===Bs);return a?.previewImage?cs(a.previewImage,{width:360,height:640,quality:55})||a.previewImage:null},[R]);if((0,s.useEffect)(()=>{const a=Lt.current;a&&(a.scrollTop=0)},[_]),O)return(0,e.jsx)(ri,{preset:"shorts"});const Zn=h==="ko"?"ko":h==="ja"?"ja":"en",qr=yt.influencer||0,Oa=yt.shift||0,eo=W==="shift"&&rt?o("새로운 뜨는릴스 테마를 준비하고 있어요. 지금은 인플루언서 테마에서 골라 주세요.","新しい急上昇リールテーマを準備中です。今はインフルエンサーテーマからお選びください。","The Trending Reels theme is coming soon — pick from the Influencer theme for now."):rt?o(`${qr}명 중 마음에 드는 사람을 고르세요. 장소와 상황은 올리신 제품에 맞춰 AI가 다시 정합니다.`,`${qr}人から好きな人を選んでください。ロケや状況はアップした商品に合わせてAIが決め直します。`,`Pick someone from ${qr} — the location and situation are re-chosen to fit the product you upload.`):o(`인플루언서 ${qr}명 · 뜨는릴스 ${Oa}개 중 마음에 드는 걸 고르세요. 장소와 상황은 올리신 제품에 맞춰 AI가 다시 정합니다.`,`インフルエンサー${qr}人・急上昇リール${Oa}本からお好みを選んでください。ロケや状況はアップした商品に合わせてAIが決め直します。`,`Pick from ${qr} influencers and ${Oa} trending reels. The location and situation are re-chosen by AI to fit the product you upload.`),La=cr.map(a=>(0,e.jsx)(Bl,{summary:a,language:Zn,onOpen:()=>i(a.sessionId),onDismiss:()=>qn(a.sessionId)},a.sessionId));return(0,e.jsxs)("div",{className:"flex flex-col h-full min-h-0 overflow-hidden",children:[(0,e.jsx)("div",{ref:Lt,className:"flex-1 min-h-0 overflow-y-auto custom-scrollbar",onScroll:_==="templates"?re:void 0,children:(0,e.jsxs)(co,{children:[(0,e.jsx)(Wo,{value:_,onCh
118ange:B,ariaLabel:o("릴스 보기","リールの表示","Reels view"),options:[{value:"templates",label:o("템플릿","テンプレート","Templates"),attrs:Ve(je.shortsInfluencerTab)},{value:"history",label:o("내 작업","マイプロジェクト","My Projects"),count:Yn||void 0,attrs:Ve(je.shortsHistoryTab)}]}),_==="templates"&&(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)(Rs,{eyebrow:"AI MARKETING · REELS",line1:o("요즘 유행하는 릴스를","流行りのリールを","Make the reels everyone's watching"),line2:o("순식간에 만들어보세요","一瞬で作ってみましょう","in no time"),sub:eo,aside:(0,e.jsx)(Vo,{ratio:"9 / 16",images:Xn,pick:Qn,product:"/marketing-howto/reels-product.jpg",done:"/marketing-howto/reels-result.jpg",doneVideo:Yr.finalVideo,video:!0,loc3:o}),asideClassName:"mk-aside is-howto"}),(0,e.jsx)("div",{className:"mk-chiprow",children:(0,e.jsx)(As,{value:W,onChange:a=>Le(a),ariaLabel:o("분류","分類","Category"),options:[{value:"all",label:o("전체","すべて","All")},...Hl.map(a=>{const c=!!a.comingSoon&&rt,d=h==="ja"?a.labelJa:h==="en"?a.labelEn:a.labelKo;return{value:a.key,label:c?`${d} ${o("준비중","準備中","Soon")}`:d,count:c?void 0:yt[a.key]||0}})]})}),De&&(0,e.jsx)("div",{...Ve(je.shortsToneFilter),className:"mk-chiprow",children:(0,e.jsx)(As,{value:$t,onChange:a=>ft(a),ariaLabel:o("톤","トーン","Tone"),options:[{value:"all",label:o("모든 톤","全トーン","All Tones")},...ln.filter(a=>(kt[a.key]||0)>0).map(a=>({value:a.key,label:h==="ja"?a.labelJa:h==="en"?a.labelEn:a.labelKo,count:kt[a.key]||0}))]})}),W==="shift"&&rt&&(0,e.jsxs)("div",{className:"mk-empty",children:[(0,e.jsx)("b",{children:o("뜨는릴스 테마를 준비하고 있어요","急上昇リールテーマを準備中です","The Trending Reels theme is on its way")}),(0,e.jsx)("span",{children:o("곧 새로운 인플루언서 스타일로 찾아뵙겠습니다.","まもなく新しいスタイルでお届けします。","New influencer styles are coming soon.")})]}),!(W==="shift"&&rt)&&(0,e.jsxs)(e.Fragment,{children:[(0,e.jsxs)("div",{...Ve(je.shortsTemplateGrid),className:"mk-grid mk-g-shorts",children:[ut.map((a,c)=>(0,e.jsx)(Rn,{preset:a,priority:c<6,tutorialAnchor:Io(a.id),badge:a.theme==="shift"&&mr&&Ga(mr.maxDurationSec,a.id)?o("무료 1회","無料1回","Free run"):null,onClick:()=>{if(a.theme==="shift"){yr(a);return}const d=qa(N.type_specific_settings);gt(a),ba(null),l||(bt(d.productImages.slice(0,Me)),Qt(d.highlights.trim())),Nt(null),me(null)}},a.id)),A.length===0&&(0,e.jsx)("p",{className:"mk-lempty",children:o("템플릿이 없습니다","テンプレートがありません","No templates")})]}),at&&(0,e.jsx)("div",{className:"flex items-center justify-center py-8",children:(0,e.jsx)(Gr,{size:16,className:"text-muted-foreground animate-spin"})})]})]}),_==="history"&&(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)(Rs,{eyebrow:"MY WORKS",line1:o("내가 만든","作った","Your"),line2:o("릴스 영상","リール動画","reels"),sub:te>0?o(`지금까지 만든 ${te}개의 릴스. 클릭하면 크게 보고 바로 다운로드할 수 있어요.`,`これまでに作成した${te}本のリール。クリックで拡大表示・ダウンロードできます。`,`${te} reels you've made so far. Click any to view large and download.`):o("템플릿으로 릴스를 만들면 여기에 모입니다.","テンプレートからリールを作るとここに集まります。","Reels you generate from templates will land here.")}),(0,e.jsx)(qo,{media:K,onMedia:x,view:ie.view,onView:ie.setView,zoom:ie.zoom,onZoom:ie.setZoom,cols:ie.cols,onCols:ie.setCols,loc3:o}),l?(0,e.jsxs)("div",{...Ve(je.shortsHistoryGrid),className:"mk-grid mk-g-shorts",children:[La.map(a=>(0,e.jsx)("div",{className:"relative overflow-hidden rounded-[14px]",style:{aspectRatio:"9 / 16"},children:a},a.key)),(0,e.jsx)("div",{className:"relative overflow-hidden rounded-[14px]",style:{aspectRatio:"9 / 16"},children:(0,e.jsxs)("div",{className:"mk-rc",style:{cursor:"default"},children:[(0,e.jsx)("video",{src:oa(Yr.finalVideo)||void 0,muted:!0,loop:!0,autoPlay:!0,playsInl
118ine:!0}),(0,e.jsxs)(io,{className:"mk-rc-cap",children:[(0,e.jsx)("b",{children:Ka.productName}),(0,e.jsx)("span",{children:o("방금 만든 쇼츠","今作ったショート","Just created")})]})]})})]}):(0,e.jsx)("div",{...Ve(je.shortsHistoryGrid),children:(0,e.jsx)(oi,{serviceName:Ke,serviceNames:[Ke],taskType:"shorts",pollingTasks:ke,onRemoveTask:ae,emptyTitle:o("아직 생성을 하지 않으셨네요","まだ生成していません","No creations yet"),emptySubtitle:o("템플릿으로 가서 원하시는 쇼츠 템플릿을 골라서 쇼츠 제작을 시작해 보세요!","テンプレートに行き、お好みのショートテンプレートを選んでショート制作を始めましょう!","Go to Templates and pick a template to start creating your shorts!"),onEmptyAction:()=>B("templates"),emptyActionLabel:o("템플릿 둘러보기","テンプレートを見る","Browse Templates"),cardAspect:"auto",extraGridCards:La.length>0?La:void 0,viewType:ie.view,rowZoom:ie.zoom,gridColumns:ie.cols,placeholderAspect:9/16,mediaTypeFilter:K,onMakeVideo:Jn,onCountChange:ue,showNarrationReplace:!1,showDirectorNote:!1,onRemakeAdVideo:m})})]})]})}),ce&&(()=>{const a=ce.showcaseVideos||[],c=[10,15,20,30],d=["9:16","16:9","1:1","4:3","3:4","21:9"];return(0,e.jsx)("div",{className:"mk-scrim",onMouseDown:u=>{u.target===u.currentTarget&&(u.currentTarget.dataset.bd="true")},onClick:u=>{u.target===u.currentTarget&&u.currentTarget.dataset.bd==="true"&&Cr(),delete u.currentTarget.dataset.bd},children:(0,e.jsxs)("div",{className:"mk-modal is-narrow-pv",role:"dialog","aria-modal":"true","aria-label":ce.name,onMouseDown:u=>u.stopPropagation(),children:[(0,e.jsx)(bn,{onClick:Cr,label:o("닫기","閉じる","Close")}),(0,e.jsxs)("div",{...Ve(je.shortsDetailPreview),className:"mk-pv",children:[(0,e.jsx)("div",{className:"mk-pv-media",children:Ur?(0,e.jsx)("video",{src:Ur.url,poster:Ur.poster,controls:!0,autoPlay:!0,playsInline:!0},Ur.url):ce.previewImage?(0,e.jsx)("img",{src:ce.previewImage,alt:ce.name}):(0,e.jsx)("div",{className:"mk-fill",style:{background:ce.previewGradient}})}),a.length>0&&(0,e.jsxs)("div",{className:"mk-pv-strip",children:[(0,e.jsx)("p",{children:o("이 템플릿으로 만든 영상","このテンプレートで作った動画","Videos made with this template")}),(0,e.jsxs)("div",{className:"mk-strip",children:[(0,e.jsx)("button",{type:"button",onClick:()=>ba(null),className:st("mk-strip-i",!Ur&&"is-on"),title:o("템플릿 이미지","テンプレート画像","Template image"),"aria-label":o("템플릿 이미지","テンプレート画像","Template image"),"aria-pressed":!Ur,children:ce.previewImage?(0,e.jsx)("img",{src:ce.previewImage,alt:""}):(0,e.jsx)("div",{className:"w-full h-full",style:{background:ce.previewGradient}})}),a.map((u,k)=>{const w=Ur?.url===u.url;return(0,e.jsxs)("button",{type:"button",onClick:()=>ba(u),className:st("mk-strip-i",w&&"is-on"),title:o("영상 재생","動画を再生","Play video"),"aria-label":`${o("영상 재생","動画を再生","Play video")} ${k+1}`,"aria-pressed":w,children:[u.poster?(0,e.jsx)("img",{src:u.poster,alt:""}):(0,e.jsx)("video",{src:u.url,muted:!0,playsInline:!0,preload:"metadata"}),(0,e.jsx)("span",{className:"mk-strip-play",children:(0,e.jsx)(xo,{size:14,fill:"currentColor","aria-hidden":!0})})]},`${u.url}-${k}`)})]})]})]}),(0,e.jsxs)("div",{className:"mk-mform",children:[(0,e.jsx)(Bo,{eyebrow:o("릴스","リール","Reels"),title:ce.name,desc:ce.description||void 0}),(0,e.jsxs)("div",{className:"mk-mbody",children:[(0,e.jsxs)("div",{...Ve(je.shortsDetailName),className:"grid gap-2",children:[(0,e.jsx)(sr,{title:o("제품 이름","製品名","Product Name"),extra:o("대사에 이 이름 그대로 들어갑니다","セリフにこの名前がそのまま入ります","used verbatim in the spoken lines"),count:`${vr.length}/80`}),(0,e.jsx)("input",{value:vr,onChange:u=>et(u.target.value),maxLength:80,placeholder:o("예) 빠나나 에이아이","例)ppabanana AI","e.g. BBANANA AI"),"aria-label":o("제품 이름","製品名","Product Name"),className:"mk-field"})]}),(0,e.jsxs)("div",{...Ve(je.shortsDetailProducts),className:"grid gap-2",children:[(0,e.jsx)(sr,{title:o("제품 이미지","製品画像","Product Image"),count:`${Ae.length}/${Me}`}),(0,e.jsx)("input",{id:"product-upload",type:"file",accept:"image/*",multiple:!0,className:"hidden",onChange:u=>{const k=u.target.files;
118k&&Array.from(k).slice(0,Me-Ae.length).forEach(w=>er(w,"product")),u.target.value=""}}),(0,e.jsxs)(Go,{children:[Ae.map((u,k)=>(0,e.jsx)(Us,{src:u,label:`Image ${k+1}`,removeLabel:o("이미지 삭제","画像を削除","Remove image"),onRemove:()=>{u&&_r.current.has(u)&&Vr(u),bt(w=>w.filter((L,ne)=>ne!==k)),k===0&&me(null)}},k)),Ae.length<Me&&(0,e.jsx)(Us,{label:`Image ${Ae.length+1}`,ariaLabel:o("제품 이미지 추가","製品画像を追加","Add product image"),onClick:()=>Bt("product"),onDrop:Et,onDragOver:u=>u.preventDefault()})]}),(0,e.jsx)("p",{className:"mk-tip",children:o("한글이 있는 제품의 경우 가급적 큰 사이즈의 이미지를 업로드하시면 한글이 덜 깨집니다.","韓国語テキストのある製品の場合、できるだけ大きなサイズの画像をアップロードすると韓国語が崩れにくくなります。","For products with Korean text, uploading a larger image helps preserve the Korean characters more accurately.")})]}),(0,e.jsxs)("div",{...Ve(je.shortsDetailHighlights),className:"grid gap-2",children:[(0,e.jsx)(sr,{title:o("제품 특장점","製品の特長","Product Highlights"),count:Fe.length>1800?`${Fe.length}/2000`:void 0}),(0,e.jsx)("textarea",{value:Fe,onChange:u=>Qt(u.target.value.slice(0,2e3)),maxLength:2e3,rows:3,"aria-label":o("제품 특장점","製品の特長","Product Highlights"),placeholder:Ae.length===0?o('이미지 없이 서비스 쇼츠를 만들 수 있습니다. 예: "여행 예약 앱, 간편하고 빠른 예약", "프리미엄 헬스케어 구독 서비스"','画像なしでサービスショートを作れます。例: "旅行予約アプリ、簡単で素早い予約"、"プレミアムヘルスケア定期購読サービス"','No image? Describe your service here. e.g. "Travel booking app, fast & easy reservations" or "Premium skincare subscription"'):o("추가 지시사항을 입력하세요...","追加の指示を入力してください...","Add extra instructions..."),className:"mk-field"})]}),(0,e.jsxs)(zo,{title:o("출력 옵션","出力オプション","Output Options"),attrs:Ve(je.shortsDetailOptions),children:[(0,e.jsx)(sr,{title:o("비율","比率","Aspect Ratio")}),(0,e.jsx)(Ds,{value:Ct,onChange:u=>Ir(u),ariaLabel:o("비율","比率","Aspect Ratio"),options:d.map(u=>({value:u,label:u}))}),(0,e.jsx)(sr,{title:o("영상 길이","動画の長さ","Video Length")}),(0,e.jsx)(Ds,{value:String(Re),onChange:u=>We(Number(u)),ariaLabel:o("영상 길이","動画の長さ","Video Length"),options:c.map(u=>{const k=Ws(Ie,u,{seedance2:_e,seedance25:P}),w=k?Va(u,"720p",!0,k,"pro"):0;return{value:String(u),label:`${u}${o("초","秒","s")}`,sub:w>0?`${w}${o("크레딧~","クレジット~"," credits~")}`:void 0}})}),(0,e.jsx)("p",{className:"mk-foot-note",children:Ie==="2.5"?o("* 모든 길이가 Seedance 2.5 로 생성됩니다 — 720p/1080p 모두 선택할 수 있고, 해상도에 따라 크레딧이 변동됩니다.","* すべての長さがSeedance 2.5で生成されます — 720p/1080pを選択でき、解像度によりクレジットが変動します。","* Every length is generated 
118with Seedance 2.5 — both 720p and 1080p are available; credits scale with resolution."):Re>15?o("* 30초 영상은 Seedance 2.5로 생성되며 720p로 제공됩니다.","* 30秒動画はSeedance 2.5で生成され、720pのみ対応です。","* 30-second videos are generated with Seedance 2.5 and available in 720p."):o("* 해상도(720p/1080p)에 따라 크레딧이 추가로 변동됩니다.","* 解像度 (720p/1080p) によりクレジットが追加変動します。","* Credits scale with resolution (720p/1080p).")})]})]}),(0,e.jsxs)("div",{className:"mk-mfoot is-two",children:[(0,e.jsx)(Er,{variant:"o",onClick:()=>Mr("image"),disabled:Ae.length===0&&!Fe.trim()||js,children:js?(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)(Gr,{size:16,className:"animate-spin shrink-0","aria-hidden":!0}),o("생성 중...","生成中...","Generating...")]}):(0,e.jsxs)(e.Fragment,{children:[o("이미지만 생성","画像のみ生成","Generate Image Only")," ",(0,e.jsx)(fr,{value:ts})]})}),(0,e.jsxs)(Er,{variant:"y",onClick:()=>Mr("agent"),...Ve(je.shortsRunAgent),title:o("쇼츠 비디오 에이전트 시작","ショートビデオエージェント開始","Start shorts video agent"),children:[o("에이전트 실행","エージェント実行","Run Agent")," ",!l&&(0,e.jsx)(fr,{value:ts,variant:"ink"})]})]})]})]})})})(),Se&&Ts&&(0,e.jsx)(bl,{preset:Se,sourceVideoUrl:ct,language:h==="ko"?"ko":h==="ja"?"ja":"en",ready:!!lt,freeGrant:ga,isQualityFree:xr,estimateCredit:Ua,isSubmitting:jr,onClose:()=>{jr||yr(null)},onSubmit:Vn}),Se&&Ps&&(0,e.jsx)(Cl,{preset:Se,sourceVideoUrl:ct,language:h==="ko"?"ko":h==="ja"?"ja":"en",estimateCredit:Ma,freeGrant:ga,isQualityFree:xr,isSubmitting:jr,onClose:()=>{jr||yr(null)},onSubmit:Gn}),Se&&Cs&&!Ts&&!Ps&&(0,e.jsx)(pl,{preset:Se,sourceVideoUrl:ct,language:h==="ko"?"ko":h==="ja"?"ja":"en",credit:ya,isFree:!!ga&&ya===0,isSubmitting:jr,onClose:()=>{jr||yr(null)},onSubmit:Fn}),Se&&!Cs&&(0,e.jsx)(ll,{preset:Se,sourceVideoUrl:ct,variant:ha,onVariantChange:Ns,language:h==="ko"?"ko":h==="ja"?"ja":"en",sourceSeconds:nt,estimateCredit:$a,freeGrant:ga,isSubmitting:jr,onClose:()=>{jr||yr(null)},onSubmit:Ln}),(0,e.jsx)(Ji,{open:!!it,visible:lr,onClose:Hn,onEndSession:zn,onStateChange:Ut,onGenerateStart:void 0,session:it,language:h==="ko"?"ko":h==="ja"?"ja":"en",pollingHistory:g,generationTasks:M,createRepresentativeImage:Un,uploadImages:Dt,startSeedanceGeneration:Dn,userId:t?.id,onTaskComplete:y,onSessionCompleted:ur,videoCreditCost480p:pt,videoCreditCost720p:Pt,videoCreditCost1080p:Zt,videoCreditCost4k:Sr,demoFixture:l?wi:void 0,onCheckCredit:async a=>{if(l||!t?.id)return!0;const c=await I(a);return c||f(a),c},onSetShowcaseShare:async(a,c)=>{try{const{data:d,error:u}=await ve.rpc("set_my_shorts_video_public",{p_url:a,p_public:c});if(u)throw u;if(!d?.ok)throw new Error(d?.reason||"share_failed");c?xe.success(d.rewarded?o("공유 완료 · 5크레딧 적립!","共有完了 · 5クレジット付与!","Shared · +5 credits!"):o("갤러리에 공유했어요","ギャラリーに共有しました","Shared to the gallery"),{description:d.rewarded?o("인플루언서 템플릿 카드에서 이 영상이 재생됩니다.","インフルエンサーテンプレートカードでこの動画が再生されます。","Your video now plays on the influencer template card."):d.reward_reason==="already_rewarded"?o("이미 보상을 받은 영상이라 크레딧은 추가로 적립되지 않아요.","すでに報酬を受け取った動画のため、追加のクレジットはありません。","This video was already rewarded, so no additional credits were granted."):o("이 영상은 크레딧 적립 대상이 아니에요.","この動画はクレジット付与の対象外です。","This video is not eligible for a credit reward.")}):xe.success(o("공유를 취소했어요","共有を取り消しました","Sharing turned off"),d.reclaimed?{description:o("적립됐던 5크레딧이 회수되었습니다.","付与された5クレジットが回収されました。","The 5 credits granted earlier were reclaimed.")}:void 0)}catch(d){throw xe.error(o("공유에 실패했어요","共有に失敗しました","Sharing failed"),{description:o("잠시 후 다시 시도해 주세요.","しばらくしてから再試行してください。","Please try again in a moment.")}),d}}}),(0,e.jsx)(ti,{open:H,onOpenChange:ee,requiredCredit:Ee,onPurchase:()=>{ee(!1),se("/credit-purchase")}}),zr&&(0,e.jsx)("div",{className:"mka-scrim fixed inset-0 z-[85] flex items-center justify-center px-4",onClick:()=>Mr(null),children:(0,e.jsxs)("div",{className:"mka-dlg max-w-[560px]",onClick:a=>a.stopPropagation(),children:[(0,e.jsx)("p",{className:"rn-eyebrow is-y",children:o("시작 전 확인","開始前の確認","Confirm start")}),(0,e.jsx)("h3",{children:zr==="image"?o("이미지 생성을 시작할까요?","画像生成を開始しますか?","Start image generation?"):o("쇼츠영ìƒ
118 에이전트를 시작할까요?","ショート動画エージェントを開始しますか?","Start the shorts video agent?")}),(0,e.jsx)("p",{children:zr==="image"?o(`업로드한 제품으로 합성 이미지를 만듭니다.
119시작 후에는 중간 중지나 비용 취소가 어려울 수 있어요.`,`アップロードした商品で合成画像を作成します。
120開始後は途中停止や費用の取り消しが難しい場合があります。`,`Creates a composite image from your product.
121After it starts, stopping midway or cancelling the cost may not be possible.`):o(`먼저 합성 이미지를 만든 뒤 컨셉·스토리보드로 이어집니다.
122영상 생성 비용은 그 다음 단계에서 따로 확인합니다.`,`まず合成画像を作成し、コンセプト・ストーリーボードへ進みます。
123動画生成の費用は次の段階で別途確認します。`,`It first creates the composite image, then moves on to concept and storyboard.
124The video generation cost is confirmed separately at that step.`)}),(0,e.jsxs)("div",{className:"mka-box mt-5 p-4",children:[(0,e.jsx)("span",{className:"text-[15px] font-bold text-foreground",children:zr==="image"?o("합성 이미지 생성","合成画像の生成","Composite image generation"):o("쇼츠영상 에이전트 실행","ショート動画エージェント実行","Run shorts video agent")}),zr==="agent"&&(0,e.jsx)("p",{className:"mt-3 border-t border-border pt-3 text-[12px] leading-5 text-muted-foreground",children:o(`영상까지 만들면 720p 기준 ${Pt} 크레딧이 추가로 차감됩니다(1080p 는 더 듭니다). 스토리보드를 확인한 뒤 결정하시면 됩니다.`,`動画まで作成すると720p基準で ${Pt} クレジットが追加で消費されます(1080pはさらに必要です)。ストーリーボードを確認してから決められます。`,`Generating the video costs another ${Pt} credits at 720p (1080p costs more). You can decide after reviewing the storyboard.`)})]}),(0,e.jsxs)("div",{className:"mka-dlg-f",children:[(0,e.jsx)(Er,{variant:"g",onClick:()=>Mr(null),children:o("아니오","いいえ","No")}),(0,e.jsxs)(Er,{variant:"y",onClick:()=>{const a=zr;Mr(null),a==="image"?Mn():Bn()},...Ve(je.shortsStartConfirm),children:[o("동의하고 시작","同意して開始","Agree and start"),(0,e.jsx)(fr,{value:ts,variant:"ink"})]})]})]})}),(0,e.jsx)(Qi,{open:Kn,onClose:()=>Es(!1),uploadImages:Dt,onStart:Wn,initialImages:F.productImages,initialHighlights:F.highlights,lockedCasting:Da?.casting,lockedLocation:Da?.location,lockedPresetName:Da?.presetName,seedanceEngine:Ie}),(0,e.jsx)(da,{open:nr!==null,accept:"image",onOpenChange:a=>{a||Bt(null)},onSelectFile:a=>{nr&&er(a,nr)},onSelectLibrary:a=>{nr&&$r(a,nr)}})]})};export{$c as ShortsAgentView};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.