Nuzwa commited on
Commit
4f3fd74
·
verified ·
1 Parent(s): e1add90

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +344 -503
index.html CHANGED
@@ -1,251 +1,104 @@
1
  <!DOCTYPE html>
2
- <html lang="ur">
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Veo3 JSON Prompt Generator Pro</title>
7
-
8
  <link rel="preconnect" href="https://fonts.googleapis.com">
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
- <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
11
  <style>
12
  :root {
13
  --primary-color-start: #4F46E5; /* Indigo */
14
  --primary-color-end: #8B5CF6; /* Violet */
15
- --background-color: #f4f4f9; /* Lighter, softer background */
16
  --container-bg: #ffffff;
17
  --text-color: #1f2937;
18
  --label-color: #374151;
19
- --border-color: #ddd6fe; /* Light violet for borders */
20
- --shadow-color: rgba(79, 70, 229, 0.1);
21
- --input-bg: #fafaff;
22
- --dark-bg: #0f172a;
23
- }
24
-
25
- /* --- General Setup --- */
26
- *, *::before, *::after {
27
- box-sizing: border-box;
28
  }
29
-
30
  body {
31
  font-family: 'Poppins', sans-serif;
32
  background-color: var(--background-color);
33
  color: var(--text-color);
34
  margin: 0;
35
- padding: 2rem 1rem;
36
  display: flex;
37
  justify-content: center;
38
  align-items: flex-start;
39
  min-height: 100vh;
40
  }
41
-
42
- /* --- Main Container --- */
43
  .container {
44
  width: 100%;
45
- max-width: 800px;
46
  background-color: var(--container-bg);
47
- padding: 2.5rem;
48
- border-radius: 20px;
49
- box-shadow: 0 12px 35px var(--shadow-color);
50
  border: 1px solid #e5e7eb;
51
  }
52
-
53
- /* --- Typography --- */
54
  h1 {
55
- font-size: 2.25rem;
56
- font-weight: 700;
57
- margin: 0 0 0.5rem 0;
58
- text-align: center;
59
  background: linear-gradient(90deg, var(--primary-color-start), var(--primary-color-end));
60
- -webkit-background-clip: text;
61
- -webkit-text-fill-color: transparent;
62
- line-height: 1.2;
63
- }
64
-
65
- .subtitle {
66
- text-align: center;
67
- font-size: 0.95rem;
68
- color: #6b7280;
69
- margin-bottom: 2rem;
70
- }
71
-
72
- label {
73
- font-weight: 600;
74
- display: block;
75
- margin-bottom: 0.6rem;
76
- color: var(--label-color);
77
- font-size: 0.9rem;
78
- }
79
-
80
- .note {
81
- font-size: 0.85rem;
82
- color: #6b7280;
83
- margin-top: 0.5rem;
84
  }
85
-
86
- /* --- Form Elements --- */
87
  select, textarea, input[type="text"] {
88
- width: 100%;
89
- padding: 0.8rem 1.1rem;
90
- border-radius: 10px;
91
- border: 1px solid var(--border-color);
92
- font-size: 1rem;
93
- font-family: 'Poppins', sans-serif;
94
- background-color: var(--input-bg);
95
- transition: all 0.2s ease-in-out;
96
- appearance: none; /* For custom select arrow */
97
- }
98
-
99
- select {
100
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
101
- background-position: right 0.7rem center;
102
- background-repeat: no-repeat;
103
- background-size: 1.5em 1.5em;
104
- padding-right: 2.5rem;
105
- }
106
-
107
- select:focus, textarea:focus, input[type="text"]:focus {
108
- outline: none;
109
- border-color: var(--primary-color-start);
110
- box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15);
111
- background-color: #fff;
112
- }
113
-
114
- /* --- Layout & Grouping --- */
115
- .form-section {
116
- margin-top: 1.5rem;
117
- }
118
-
119
- .row {
120
- display: grid;
121
- grid-template-columns: 1fr 1fr;
122
- gap: 1.5rem;
123
- margin-top: 1.5rem;
124
- }
125
-
126
- .row > div {
127
- width: 100%;
128
- }
129
-
130
- /* Special sections for better visual grouping */
131
- #lookPresetBlock, #voiceoverBlock {
132
- background-color: #f9f8ff;
133
- padding: 1rem 1.5rem;
134
- border-radius: 12px;
135
- margin-top: 1.5rem;
136
- border: 1px solid var(--border-color);
137
  }
138
- #lookPresetBlock > label, #voiceoverBlock > label {
139
- font-size: 1rem;
140
- color: var(--primary-color-start);
141
- }
142
-
143
- /* --- Buttons & Actions --- */
144
- .actions {
145
- display: grid;
146
- grid-template-columns: 1fr 1fr;
147
- gap: 1rem;
148
- margin-top: 2rem;
149
- }
150
-
151
  button {
152
- background-image: linear-gradient(95deg, var(--primary-color-start), var(--primary-color-end));
153
- color: #fff;
154
- border: none;
155
- padding: 0.9rem 1.2rem;
156
- font-size: 1.05rem;
157
- font-weight: 600;
158
- font-family: 'Poppins', sans-serif;
159
- border-radius: 10px;
160
- cursor: pointer;
161
- width: 100%;
162
- transition: transform 0.2s ease, box-shadow 0.2s ease, opacity 0.2s ease;
163
- box-shadow: 0 4px 15px rgba(79, 70, 229, 0.2);
164
- }
165
-
166
- button:hover {
167
- transform: translateY(-3px);
168
- box-shadow: 0 7px 20px rgba(79, 70, 229, 0.25);
169
- }
170
-
171
- button:active {
172
- transform: translateY(0);
173
- opacity: 0.9;
174
- }
175
-
176
- .secondary {
177
- background: #374151;
178
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
179
- }
180
- .secondary:hover {
181
- background: #1f2937;
182
- box-shadow: 0 7px 20px rgba(0, 0, 0, 0.2);
183
- }
184
-
185
- /* --- Output & Toast --- */
186
- pre {
187
- background: var(--dark-bg);
188
- color: #e5e7eb;
189
- padding: 1.25rem;
190
- white-space: pre-wrap;
191
- word-break: break-word;
192
- border-radius: 12px;
193
- margin-top: 2rem;
194
- font-family: 'SF Mono', 'Consolas', 'Menlo', monospace;
195
- font-size: 0.9rem;
196
- line-height: 1.7;
197
- border: 1px solid #374151;
198
- }
199
-
200
- .toast {
201
- position: fixed;
202
- right: 20px;
203
- bottom: 20px;
204
- background: linear-gradient(95deg, var(--primary-color-start), var(--primary-color-end));
205
- color: #fff;
206
- padding: 12px 18px;
207
- border-radius: 10px;
208
- opacity: 0;
209
- transform: translateY(15px);
210
- box-shadow: 0 8px 25px rgba(0, 0, 0, 0.2);
211
- transition: opacity .2s ease, transform .2s ease;
212
- font-size: 0.95rem;
213
- font-weight: 500;
214
- z-index: 1000;
215
- }
216
-
217
- .toast.show {
218
- opacity: 1;
219
- transform: translateY(0);
220
- }
221
-
222
- /* --- Responsive (Mobile-Friendly) Design --- */
223
- @media (max-width: 768px) {
224
- body { padding: 1rem 0.5rem; }
225
- .container { padding: 1.5rem; }
226
- h1 { font-size: 1.75rem; }
227
-
228
- .row, .actions {
229
- grid-template-columns: 1fr;
230
- gap: 1.25rem;
231
- }
232
- .form-section, .row, #lookPresetBlock, #voiceoverBlock {
233
- margin-top: 1.25rem;
234
- }
235
- }
236
  </style>
237
  </head>
238
  <body>
239
  <div class="container">
240
  <h1>🎬 Veo3 JSON Prompt Generator <span style="font-size: 1rem; font-weight: 400;">(Pro)</span></h1>
241
- <div class="subtitle">Single-file HTML • Inline JS • Copy-ready JSON for Hugging Face Spaces</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
 
 
243
  <div class="row">
244
  <div>
245
  <label for="domain">🎯 Select Domain</label>
246
  <select id="domain">
247
  <option value="education">Education</option>
248
- <option value="advertisement">Advertisement</option>
249
  <option value="product_demo">Product Demo</option>
250
  <option value="creator_pov">Creator POV</option>
251
  </select>
@@ -255,7 +108,7 @@
255
  <select id="characterType">
256
  <optgroup label="Characters">
257
  <option>Pakistani Male</option>
258
- <option>Pakistani Female</option>
259
  <option>Arab Male</option>
260
  <option>Arab Female</option>
261
  <option>South Asian Coach</option>
@@ -273,44 +126,13 @@
273
  </div>
274
  </div>
275
 
276
- <div id="lookPresetBlock">
277
- <label>
278
- <input type="checkbox" id="useLookPreset" checked style="margin-right: 8px; vertical-align: middle;">
279
- Enable Character Look Preset
280
- </label>
281
- <div id="lookPresetFields" class="row" style="margin-top:1rem;">
282
- <div>
283
- <label for="skinTone">🧑🏽‍ Skin Tone</label>
284
- <select id="skinTone">
285
- <option>light wheatish</option>
286
- <option>wheatish</option>
287
- <option>medium tan</option>
288
- <option>warm brown</option>
289
- <option>deep brown</option>
290
- </select>
291
- </div>
292
- <div id="headCoverWrap">
293
- <label for="headCover">🧕 Head Covering (if applicable)</label>
294
- <select id="headCover">
295
- <option value="auto">Auto</option>
296
- <option value="none">None</option>
297
- <option value="dupatta">Dupatta (draped)</option>
298
- <option value="hijab_wrap">Hijab (wrap)</option>
299
- <option value="shayla">Shayla</option>
300
- <option value="niqab">Niqab (eyes visible)</option>
301
- </select>
302
- </div>
303
- </div>
304
- <div class="note">These presets add culturally-accurate wardrobe, hair, makeup, and accessories.</div>
305
- </div>
306
-
307
- <div class="form-section">
308
  <label for="taskFocus">📆 Scene Title / Task Focus</label>
309
  <select id="taskFocus">
310
  <option>Lesson Planning</option>
311
  <option>Quiz Generator</option>
312
  <option>Feedback Automation</option>
313
- <option>Product Reveal</option>
314
  <option>How It Works</option>
315
  <option>From Chaos to Clarity</option>
316
  <option>Before vs. After</option>
@@ -322,7 +144,7 @@
322
  <option>Time-Saver Workflow</option>
323
  <option value="custom">🛠️ Custom</option>
324
  </select>
325
- <div id="customTaskWrapper" style="display:none; margin-top:0.75rem;">
326
  <input type="text" id="customTask" placeholder="Enter your custom task focus" />
327
  </div>
328
  </div>
@@ -331,7 +153,7 @@
331
  <div>
332
  <label for="variant">🎞️ Video Type / Variant</label>
333
  <select id="variant">
334
- <option value="cinematic">🎬 Cinematic</option>
335
  <option value="POV">📸 POV</option>
336
  <option value="meme">😂 Meme</option>
337
  <option value="teaser">🎯 Teaser</option>
@@ -355,6 +177,7 @@
355
  <option selected>9:16</option>
356
  <option>1:1</option>
357
  </select>
 
358
  </div>
359
  </div>
360
 
@@ -386,13 +209,43 @@
386
  </div>
387
  </div>
388
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
  <div class="row">
390
  <div>
391
  <label for="visualStyle">🎨 Visual Style</label>
392
  <select id="visualStyle">
393
  <option>Photorealistic</option>
394
  <option>Glossy Commercial</option>
395
- <option>Cinematic / Filmic Grain</option>
396
  <option>HDR High-Contrast</option>
397
  <option>Low-Key Noir</option>
398
  <option>High-Key Clean</option>
@@ -407,7 +260,7 @@
407
  <div>
408
  <label for="camera">🎥 Camera & Motion (optional)</label>
409
  <select id="camera">
410
- <option value="auto">🎯 Auto Based on Scene</option>
411
  <option value="dolly">Dolly</option>
412
  <option value="slider">Slider</option>
413
  <option value="handheld">Handheld (Micro Judder)</option>
@@ -425,7 +278,7 @@
425
  <div>
426
  <label for="background">🌆 Background Environment</label>
427
  <select id="background">
428
- <option value="auto">🎯 Auto Based on Task</option>
429
  <option value="studio">Studio Cyclorama</option>
430
  <option value="warehouse">Industrial Warehouse</option>
431
  <option value="garage">Neon Garage</option>
@@ -440,7 +293,7 @@
440
  <select id="lightingMood">
441
  <option>Golden Hour Beams</option>
442
  <option>Hard Rim / Silhouette</option>
443
- <option>Soft Wrap Key</option>
444
  <option>Top Light High-Contrast</option>
445
  <option>Backlight + Haze</option>
446
  <option>Neon Mix (Cyan / Magenta)</option>
@@ -462,14 +315,14 @@
462
  <option>Synthwave</option>
463
  <option>Techno</option>
464
  <option>Glitch-hop</option>
465
- <option>Cinematic Pulses</option>
466
  </select>
467
  </div>
468
  <div>
469
  <label for="sfx">🔊 Sound Effects (SFX)</label>
470
  <select id="sfx">
471
  <option>Braaam</option>
472
- <option>Whoosh / Riser</option>
473
  <option>Strap Snap</option>
474
  <option>Plastic Tear</option>
475
  <option>Metallic Clinks</option>
@@ -480,16 +333,16 @@
480
  </div>
481
  </div>
482
 
483
- <div id="voiceoverBlock">
484
- <label>
485
- <input type="checkbox" id="useVoiceover" checked style="margin-right: 8px; vertical-align: middle;">
486
- Enable Voiceover
487
  </label>
488
- <div id="voFields" class="row" style="margin-top:1rem;">
489
  <div>
490
  <label for="voLanguage">🎙 Language</label>
491
  <select id="voLanguage">
492
- <option value="ur-PK-roman">Urdu (Roman Urdu)</option>
493
  <option value="ur-PK">Urdu (Nastaliq)</option>
494
  <option value="en-US">English (US)</option>
495
  <option value="en-GB">English (UK)</option>
@@ -500,7 +353,7 @@
500
  <div>
501
  <label for="voGender">👤 Voice</label>
502
  <select id="voGender">
503
- <option value="female">Female</option>
504
  <option value="male">Male</option>
505
  <option value="youth">Youth</option>
506
  </select>
@@ -508,7 +361,7 @@
508
  <div>
509
  <label for="voTone">🎚 Tone</label>
510
  <select id="voTone">
511
- <option value="cinematic">Cinematic</option>
512
  <option value="friendly">Friendly</option>
513
  <option value="authoritative">Authoritative</option>
514
  <option value="educational">Educational</option>
@@ -525,10 +378,8 @@
525
  </select>
526
  </div>
527
  </div>
528
- <div class="form-section">
529
- <label for="voScript">📝 Voiceover Script (optional)</label>
530
- <textarea id="voScript" rows="3" placeholder="Write your VO script here... or leave empty to generate later"></textarea>
531
- </div>
532
  </div>
533
 
534
  <div class="row">
@@ -536,7 +387,7 @@
536
  <label for="colorPalette">🎨 Color Palette</label>
537
  <select id="colorPalette">
538
  <option>Graphite / Obsidian / Silver</option>
539
- <option>Amber / Gold / Copper</option>
540
  <option>Steel Blue / Cyan / Teal</option>
541
  <option>Neon Accents (Magenta / Cyan / Lime)</option>
542
  <option>Monochrome</option>
@@ -551,7 +402,7 @@
551
  <option>Sparks Hit Lens</option>
552
  <option>Seal Rip Recoil</option>
553
  <option>Lights Power-on Cascade</option>
554
- <option>Tarp Whip-Off</option>
555
  <option>Confetti Pop</option>
556
  <option>Macro Finger Press</option>
557
  <option>Countdown Flash</option>
@@ -564,9 +415,9 @@
564
  <div>
565
  <label for="finale">🎬 Finale / Closing Action</label>
566
  <select id="finale">
 
567
  <option>Butterfly Doors + 360 Orbit</option>
568
  <option>Taillight Bloom → Logo-out</option>
569
- <option>Hero Push-in → Blackout</option>
570
  <option>Freeze Frame + End Card</option>
571
  <option>Speed-Ramp Drive-by</option>
572
  <option>Reverse Reveal Cloth Fall</option>
@@ -578,10 +429,10 @@
578
  </div>
579
  </div>
580
 
581
- <div class="form-section">
582
  <label for="negativePrompt">🚫 Negative Prompt (Exclude Things)</label>
583
  <textarea id="negativePrompt" rows="3" placeholder="e.g., no logos, no text overlays, no watermark, no extra limbs"></textarea>
584
- <div class="note">Tip: Keep negatives short and specific for best results.</div>
585
  </div>
586
 
587
  <div class="actions">
@@ -595,275 +446,265 @@
595
  <div id="toast" class="toast" role="status" aria-live="polite">Copied!</div>
596
 
597
  <script>
598
- // --- helpers ---
599
  const $ = (id) => document.getElementById(id);
600
 
601
- // --- Character Look Presets (culturally-aware) ---
602
- const LOOK_PRESETS = {
603
- "Pakistani Female": {
604
- ethnicity: "Pakistani",
605
- age_range: "20s–30s",
606
- attire: "shalwar kameez with dupatta; modest, contemporary tailoring",
607
- fabrics: "lawn or cotton blend; subtle embroidery",
608
- accessories: "jhumka earrings; thin bangles",
609
- hair: "dark hair, braided or loose soft waves",
610
- makeup: "natural base, soft kohl eyeliner, nude/rose lipstick",
611
- head_cover_applicable: true
612
- },
613
- "Pakistani Male": {
614
- ethnicity: "Pakistani",
615
- age_range: "20s–30s",
616
- attire: "shalwar kameez (neutral) or kurta; optional waistcoat",
617
- grooming: "trimmed beard or clean‑shaven",
618
- accessories: "simple watch",
619
- head_cover_applicable: false
620
- },
621
- "Arab Female": {
622
- ethnicity: "Arab",
623
- age_range: "20s–30s",
624
- attire: "abaya with hijab (neutral/black) or modest dress",
625
- accessories: "minimal jewelry",
626
- makeup: "defined eyeliner, matte base",
627
- hair: "covered if hijab",
628
- head_cover_applicable: true
 
 
629
  },
630
- "Arab Male": {
631
- ethnicity: "Arab",
632
- age_range: "20s–30s",
633
- attire: "thobe/kandura (white) or smart casual",
634
- accessories: "optional ghutra + agal (Gulf)",
635
- grooming: "trimmed beard",
636
- head_cover_applicable: false
637
  },
638
- "South Asian Coach": {
639
- ethnicity: "South Asian",
640
- age_range: "30s–40s",
641
- attire: "smart casual blazer over shirt/kurta; lanyard/clipboard",
642
- head_cover_applicable: false
 
643
  },
644
- "Young Creator (Female)": {
645
- ethnicity: "South Asian",
646
- age_range: "18–25",
647
- attire: "streetwear/athleisure; denim jacket; sneakers",
648
- hair: "loose or ponytail; optional dyed streaks",
649
- accessories: "minimal rings/necklace",
650
- head_cover_applicable: false
651
  },
652
- "Young Creator (Male)": {
653
- ethnicity: "South Asian",
654
- age_range: "18–25",
655
- attire: "hoodie/overshirt; cap optional",
656
- hair: "short/messy",
657
- accessories: "watch/bracelet",
658
- head_cover_applicable: false
659
  }
660
  };
661
 
662
- const PRODUCT_LIST = ["Smartphone","Perfume","Luxury Car","Skincare Product"];
663
- const isProduct = (t) => PRODUCT_LIST.includes(t);
664
-
665
- const isFemaleChar = (t) => /Female/i.test(t);
 
 
666
 
667
- function resolveHeadCoverDefault(type){
668
- if(type === "Pakistani Female") return "dupatta (draped)";
669
- if(type === "Arab Female") return "hijab (wrap)";
670
- return undefined;
671
- }
672
 
673
- function buildSubjectLook(type, skinTone, headCover){
674
- const base = LOOK_PRESETS[type];
675
- if(!base) return null;
676
- const out = { ...base, skin_tone: skinTone };
677
- if(base.head_cover_applicable){
678
- if(headCover && headCover !== "auto"){
679
- out.head_cover = headCover === "none" ? "none" : headCover.replace('_',' ');
680
- } else {
681
- const def = resolveHeadCoverDefault(type);
682
- if(def) out.head_cover = def;
683
- }
 
 
 
 
 
 
 
 
 
 
684
  }
685
- return out;
686
  }
687
 
688
- function buildProCamera(aspect, camera){
689
- return {
690
- profile: "P.R.O C.A.M.E.R.A",
691
- P: "Photoreal lighting, accurate materials, cinematic exposure",
692
- R: "Render at 4K master",
693
- O: "Optics: 35mm & 85mm primes; shallow depth; creamy bokeh",
694
- C: "Camera: full‑frame color science; natural skin tones",
695
- A: `Angles: ${camera} + macro inserts for details`,
696
- M: "Motion: subtle handheld micro‑jitter at 30fps (if applicable)",
697
- E: "Environment motivated by background; practicals for depth",
698
- R2: "Rendering: light filmic grain; no oversharpening"
699
- };
700
- }
701
-
702
- function updateLookUiVisibility() {
703
- const type = $("characterType")?.value;
704
- const usePreset = $("useLookPreset")?.checked;
705
- const showBlock = usePreset && !isProduct(type);
706
- const showHeadCover = showBlock && isFemaleChar(type);
707
-
708
- if ($("lookPresetFields")) $("lookPresetFields").style.display = showBlock ? "grid" : "none";
709
- if ($("headCoverWrap")) $("headCoverWrap").style.display = showHeadCover ? "block" : "none";
710
  }
711
 
712
- function updateVoUiVisibility(){
713
- const enabled = $("useVoiceover")?.checked;
714
- if($("voFields")) $("voFields").style.display = enabled ? "grid" : "none";
715
- const voScriptParent = $("voScript")?.parentElement;
716
- if(voScriptParent) voScriptParent.style.display = enabled ? "block" : "none";
717
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
718
 
719
- function handleTaskFocusChange() {
720
- const selected = $("taskFocus").value;
721
- $("customTaskWrapper").style.display = selected === "custom" ? "block" : "none";
722
- }
 
 
 
 
 
 
723
 
724
- function resolveAutoCamera(variant) {
725
- const map = {
726
- "product-hero": "dolly",
727
- "cinematic": "slider",
728
- "POV": "handheld",
729
- "drone-flythrough": "fpv",
730
- "montage": "whip-pan",
731
- "teaser": "rack-focus",
732
- "tutorial": "slider",
733
- };
734
- return map[variant] || "dolly";
735
- }
736
 
737
- function resolveAutoBackground(task) {
738
- const t = (task || "").toLowerCase();
739
- if (t.includes("reveal") || t.includes("product")) return "showroom";
740
- if (t.includes("lesson") || t.includes("quiz") || t.includes("feedback")) return "studio";
741
- if (t.includes("behind")) return "warehouse";
742
- if (t.includes("pov")) return "night_city";
743
- return "studio";
744
- }
745
 
746
- function generatePrompt() {
747
- // base values
748
- const domain = $("domain").value;
749
- const characterOrProduct = $("characterType").value;
750
- const taskFocusSel = $("taskFocus").value;
751
- const customTask = ($("customTask")?.value || "").trim();
752
- const taskFocus = taskFocusSel === "custom" ? (customTask || "Custom Task") : taskFocusSel;
753
-
754
- const variant = $("variant").value;
755
- const aspectRatio = $("aspectRatio").value;
756
- const platform = $("platform").value;
757
- const description = $("description").value;
758
- const visualStyle = $("visualStyle").value;
759
- const cameraSel = $("camera").value;
760
- const backgroundSel = $("background").value;
761
- const lightingMood = $("lightingMood").value;
762
- const audioTrack = $("audioTrack").value;
763
- const sfx = $("sfx").value;
764
- const colorPalette = $("colorPalette").value;
765
- const hook = $("hook").value;
766
- const finale = $("finale").value;
767
- const keywordsRaw = $("keywords").value;
768
- const negativePrompt = $("negativePrompt").value;
769
-
770
- // autos
771
- const camera = cameraSel === "auto" ? resolveAutoCamera(variant) : cameraSel;
772
- const background = backgroundSel === "auto" ? resolveAutoBackground(taskFocus) : backgroundSel;
773
-
774
- // subject look (optional)
775
- const useLook = $("useLookPreset")?.checked;
776
- const subjectLook = (useLook && !isProduct(characterOrProduct))
777
- ? buildSubjectLook(characterOrProduct, $("skinTone")?.value, $("headCover")?.value)
778
- : null;
779
-
780
- // P.R.O C.A.M.E.R.A auto-add for realistic/professional intents
781
- const styleStr = (visualStyle || "").toLowerCase();
782
- const kwStr = (keywordsRaw || "").toLowerCase();
783
- const shouldPro = /photo|realistic|professional/.test(styleStr) || kwStr.includes("realistic") || kwStr.includes("dslr") || kwStr.includes("pro camera");
784
- const proCamera = shouldPro ? buildProCamera(aspectRatio, camera) : null;
785
-
786
- // Voiceover (optional)
787
- const useVo = $("useVoiceover")?.checked;
788
- const vo = {
789
- enabled: !!useVo,
790
- language: $("voLanguage")?.value,
791
- voice: $("voGender")?.value,
792
- tone: $("voTone")?.value,
793
- pace: $("voPace")?.value,
794
- script: ($("voScript")?.value || "").trim()
795
  };
796
 
797
- const prompt = {
798
- domain,
799
- main_subject: characterOrProduct,
800
- task_focus: taskFocus,
801
  variant,
802
- meta: {
803
- aspect_ratio: aspectRatio,
804
- platform: platform,
805
- fps: 30
806
- },
807
- description,
808
- visual_style: visualStyle,
809
  camera,
810
- background,
811
- lighting_mood: lightingMood,
812
- audio: {
813
- music: audioTrack,
814
- sfx: sfx
815
- },
816
- color_palette: colorPalette,
817
- hook,
818
- finale,
819
- keywords: (keywordsRaw||'').split(',').map(s => s.trim()).filter(Boolean),
820
- negative_prompt: negativePrompt
821
- };
822
-
823
- if(subjectLook) prompt.subject_look = subjectLook;
824
- if(proCamera) prompt.pro_camera = proCamera;
825
- if(useVo) prompt.audio.voiceover = vo;
826
-
827
- $("output").textContent = JSON.stringify(prompt, null, 2);
828
- }
829
 
830
- async function copyToClipboard() {
831
- const text = $("output").textContent || "";
832
- if (!text.trim() || text.trim() === "{}") { showToast("Nothing to copy yet"); return; }
833
- try {
834
- await navigator.clipboard.writeText(text);
835
- showToast("✅ Prompt copied to clipboard!");
836
- } catch (err) {
837
- // fallback
838
- const ta = document.createElement('textarea');
839
- ta.value = text; document.body.appendChild(ta); ta.select();
840
- try { document.execCommand('copy'); showToast("✅ Prompt copied (fallback)!"); }
841
- catch (e) { showToast("❌ Copy failed. Select text manually."); }
842
- finally { document.body.removeChild(ta); }
843
- }
844
- }
845
 
846
- function showToast(msg) {
847
- const t = $("toast");
848
- t.textContent = msg; t.classList.add('show');
849
- setTimeout(() => t.classList.remove('show'), 2000);
850
- }
851
 
852
- // --- Initialize & Attach Listeners ---
853
- document.addEventListener('DOMContentLoaded', () => {
854
- $("taskFocus").addEventListener('change', handleTaskFocusChange);
855
- $("characterType").addEventListener('change', updateLookUiVisibility);
856
- $("useLookPreset").addEventListener('change', updateLookUiVisibility);
857
- $("useVoiceover").addEventListener('change', updateVoUiVisibility);
858
-
859
- // Initial UI setup
860
- handleTaskFocusChange();
861
- updateLookUiVisibility();
862
- updateVoUiVisibility();
863
-
864
- // Generate a starter prompt on page load
865
- generatePrompt();
866
  });
867
  </script>
868
  </body>
869
- </html>
 
1
  <!DOCTYPE html>
2
+ <html lang="en">
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Veo3 JSON Prompt Generator Pro — Smart Mode</title>
 
7
  <link rel="preconnect" href="https://fonts.googleapis.com">
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
10
  <style>
11
  :root {
12
  --primary-color-start: #4F46E5; /* Indigo */
13
  --primary-color-end: #8B5CF6; /* Violet */
14
+ --background-color: #f8f9fc;
15
  --container-bg: #ffffff;
16
  --text-color: #1f2937;
17
  --label-color: #374151;
18
+ --border-color: #d1d5db;
19
+ --shadow-color: rgba(0, 0, 0, 0.08);
 
 
 
 
 
 
 
20
  }
21
+ * { box-sizing: border-box; }
22
  body {
23
  font-family: 'Poppins', sans-serif;
24
  background-color: var(--background-color);
25
  color: var(--text-color);
26
  margin: 0;
27
+ padding: 1rem;
28
  display: flex;
29
  justify-content: center;
30
  align-items: flex-start;
31
  min-height: 100vh;
32
  }
 
 
33
  .container {
34
  width: 100%;
35
+ max-width: 820px;
36
  background-color: var(--container-bg);
37
+ padding: 2rem;
38
+ border-radius: 16px;
39
+ box-shadow: 0 10px 30px var(--shadow-color);
40
  border: 1px solid #e5e7eb;
41
  }
42
+ @media (max-width: 600px) { .container { padding: 1.25rem; } }
 
43
  h1 {
44
+ font-size: 2rem; font-weight: 700; margin: 0 0 .75rem 0; text-align: center;
 
 
 
45
  background: linear-gradient(90deg, var(--primary-color-start), var(--primary-color-end));
46
+ -webkit-background-clip: text; -webkit-text-fill-color: transparent;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  }
48
+ .subtitle { text-align:center; font-size:.9rem; color:#6b7280; margin-bottom: .75rem; }
49
+ label { font-weight: 600; display:block; margin-top: 1rem; margin-bottom: .4rem; color: var(--label-color); font-size:.95rem; }
50
  select, textarea, input[type="text"] {
51
+ width: 100%; padding: .8rem 1rem; border-radius: 10px; border: 1px solid var(--border-color);
52
+ font-size: 1rem; font-family: 'Poppins', sans-serif; background: #f9fafb; transition: all .2s ease-in-out;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  }
54
+ select:focus, textarea:focus, input[type="text"]:focus { outline:none; border-color: var(--primary-color-start); box-shadow: 0 0 0 3px rgba(79,70,229,.15); background:#fff; }
55
+ .row { display:grid; grid-template-columns: 1fr 1fr; gap: .75rem 1rem; }
56
+ .row > div { width:100%; }
57
+ .actions { display:grid; grid-template-columns: 1fr 1fr; gap:.75rem; margin-top:1.25rem; }
 
 
 
 
 
 
 
 
 
58
  button {
59
+ background-image: linear-gradient(90deg, var(--primary-color-start), var(--primary-color-end)); color:#fff; border:none; padding:.9rem 1.2rem; font-size:1.05rem; font-weight:700; border-radius:10px; cursor:pointer; width:100%;
60
+ transition: transform .18s ease, box-shadow .18s ease; box-shadow: 0 4px 15px rgba(0,0,0,.10);
61
+ }
62
+ button:hover { transform: translateY(-2px); box-shadow: 0 7px 20px rgba(0,0,0,.15); }
63
+ button.secondary { background:#111827; }
64
+ pre { background:#0f172a; color:#e5e7eb; padding:1rem 1.25rem; white-space:pre-wrap; word-break:break-word; border-radius:12px; margin-top:1rem; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size:.92rem; line-height:1.6; border:1px solid #1f2937; }
65
+ .note { font-size:.8rem; color:#6b7280; margin-top:.25rem; }
66
+ .toolbar { display:flex; gap:1rem; align-items:center; justify-content:center; flex-wrap: wrap; margin:.35rem 0 1rem; }
67
+ .toolbar .group { display:flex; gap:.5rem; align-items:center; }
68
+ .dimmed { opacity:.55; }
69
+ .toast { position: fixed; right: 16px; bottom: 16px; background: #111827; color: #fff; padding: 10px 12px; border-radius: 10px; opacity: 0; transform: translateY(10px); box-shadow: 0 8px 20px rgba(0,0,0,0.2); transition: opacity .2s ease, transform .2s ease; font-size: .9rem; z-index:1000; }
70
+ .toast.show { opacity:1; transform: translateY(0); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  </style>
72
  </head>
73
  <body>
74
  <div class="container">
75
  <h1>🎬 Veo3 JSON Prompt Generator <span style="font-size: 1rem; font-weight: 400;">(Pro)</span></h1>
76
+ <div class="subtitle">Singlefile HTML • Smart Mode • Copyready JSON</div>
77
+
78
+ <!-- Smart / Pro toolbar -->
79
+ <div class="toolbar">
80
+ <div class="group">
81
+ <label style="display:flex;gap:.5rem;align-items:center;margin:0">
82
+ <input type="checkbox" id="proModeToggle"> Advanced / Pro
83
+ </label>
84
+ </div>
85
+ <div class="group">
86
+ <label for="qualityPreset" style="margin:0">🎚 Quality:</label>
87
+ <select id="qualityPreset">
88
+ <option value="pro" selected>Pro (default)</option>
89
+ <option value="draft">Draft / Fast</option>
90
+ <option value="cinematic">Cinematic</option>
91
+ </select>
92
+ </div>
93
+ </div>
94
 
95
+ <!-- Core choices: minimal inputs -->
96
  <div class="row">
97
  <div>
98
  <label for="domain">🎯 Select Domain</label>
99
  <select id="domain">
100
  <option value="education">Education</option>
101
+ <option value="advertisement" selected>Advertisement</option>
102
  <option value="product_demo">Product Demo</option>
103
  <option value="creator_pov">Creator POV</option>
104
  </select>
 
108
  <select id="characterType">
109
  <optgroup label="Characters">
110
  <option>Pakistani Male</option>
111
+ <option selected>Pakistani Female</option>
112
  <option>Arab Male</option>
113
  <option>Arab Female</option>
114
  <option>South Asian Coach</option>
 
126
  </div>
127
  </div>
128
 
129
+ <div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  <label for="taskFocus">📆 Scene Title / Task Focus</label>
131
  <select id="taskFocus">
132
  <option>Lesson Planning</option>
133
  <option>Quiz Generator</option>
134
  <option>Feedback Automation</option>
135
+ <option selected>Product Reveal</option>
136
  <option>How It Works</option>
137
  <option>From Chaos to Clarity</option>
138
  <option>Before vs. After</option>
 
144
  <option>Time-Saver Workflow</option>
145
  <option value="custom">🛠️ Custom</option>
146
  </select>
147
+ <div id="customTaskWrapper" style="display:none; margin-top:.5rem;">
148
  <input type="text" id="customTask" placeholder="Enter your custom task focus" />
149
  </div>
150
  </div>
 
153
  <div>
154
  <label for="variant">🎞️ Video Type / Variant</label>
155
  <select id="variant">
156
+ <option value="cinematic" selected>🎬 Cinematic</option>
157
  <option value="POV">📸 POV</option>
158
  <option value="meme">😂 Meme</option>
159
  <option value="teaser">🎯 Teaser</option>
 
177
  <option selected>9:16</option>
178
  <option>1:1</option>
179
  </select>
180
+ <div class="note">Smart Mode: platforms auto‑map from aspect ratio</div>
181
  </div>
182
  </div>
183
 
 
209
  </div>
210
  </div>
211
 
212
+ <div id="lookPresetBlock" style="margin-top:.5rem;">
213
+ <label style="display:flex; align-items:center; gap:8px; font-weight:600;">
214
+ <input type="checkbox" id="useLookPreset" checked /> Enable Character Look Preset
215
+ </label>
216
+ <div id="lookPresetFields" class="row" style="margin-top:0.5rem;">
217
+ <div>
218
+ <label for="skinTone">🧑🏽‍ Skin Tone</label>
219
+ <select id="skinTone">
220
+ <option>light wheatish</option>
221
+ <option selected>wheatish</option>
222
+ <option>medium tan</option>
223
+ <option>warm brown</option>
224
+ <option>deep brown</option>
225
+ </select>
226
+ </div>
227
+ <div id="headCoverWrap">
228
+ <label for="headCover">🧕 Head Covering (if applicable)</label>
229
+ <select id="headCover">
230
+ <option value="auto" selected>Auto</option>
231
+ <option value="none">None</option>
232
+ <option value="dupatta">Dupatta (draped)</option>
233
+ <option value="hijab_wrap">Hijab (wrap)</option>
234
+ <option value="shayla">Shayla</option>
235
+ <option value="niqab">Niqab (eyes visible)</option>
236
+ </select>
237
+ </div>
238
+ </div>
239
+ <div class="note">Presets add culturally accurate wardrobe & grooming to JSON.</div>
240
+ </div>
241
+
242
  <div class="row">
243
  <div>
244
  <label for="visualStyle">🎨 Visual Style</label>
245
  <select id="visualStyle">
246
  <option>Photorealistic</option>
247
  <option>Glossy Commercial</option>
248
+ <option selected>Cinematic / Filmic Grain</option>
249
  <option>HDR High-Contrast</option>
250
  <option>Low-Key Noir</option>
251
  <option>High-Key Clean</option>
 
260
  <div>
261
  <label for="camera">🎥 Camera & Motion (optional)</label>
262
  <select id="camera">
263
+ <option value="auto" selected>🎯 Auto Based on Scene</option>
264
  <option value="dolly">Dolly</option>
265
  <option value="slider">Slider</option>
266
  <option value="handheld">Handheld (Micro Judder)</option>
 
278
  <div>
279
  <label for="background">🌆 Background Environment</label>
280
  <select id="background">
281
+ <option value="auto" selected>🎯 Auto Based on Task</option>
282
  <option value="studio">Studio Cyclorama</option>
283
  <option value="warehouse">Industrial Warehouse</option>
284
  <option value="garage">Neon Garage</option>
 
293
  <select id="lightingMood">
294
  <option>Golden Hour Beams</option>
295
  <option>Hard Rim / Silhouette</option>
296
+ <option selected>Soft Wrap Key</option>
297
  <option>Top Light High-Contrast</option>
298
  <option>Backlight + Haze</option>
299
  <option>Neon Mix (Cyan / Magenta)</option>
 
315
  <option>Synthwave</option>
316
  <option>Techno</option>
317
  <option>Glitch-hop</option>
318
+ <option selected>Cinematic Pulses</option>
319
  </select>
320
  </div>
321
  <div>
322
  <label for="sfx">🔊 Sound Effects (SFX)</label>
323
  <select id="sfx">
324
  <option>Braaam</option>
325
+ <option selected>Whoosh / Riser</option>
326
  <option>Strap Snap</option>
327
  <option>Plastic Tear</option>
328
  <option>Metallic Clinks</option>
 
333
  </div>
334
  </div>
335
 
336
+ <!-- Voiceover Block -->
337
+ <div id="voiceoverBlock" style="margin-top:.5rem;">
338
+ <label style="display:flex; align-items:center; gap:8px; font-weight:600;">
339
+ <input type="checkbox" id="useVoiceover" checked /> Enable Voiceover
340
  </label>
341
+ <div id="voFields" class="row" style="margin-top:0.5rem;">
342
  <div>
343
  <label for="voLanguage">🎙 Language</label>
344
  <select id="voLanguage">
345
+ <option value="ur-PK-roman" selected>Urdu (Roman Urdu)</option>
346
  <option value="ur-PK">Urdu (Nastaliq)</option>
347
  <option value="en-US">English (US)</option>
348
  <option value="en-GB">English (UK)</option>
 
353
  <div>
354
  <label for="voGender">👤 Voice</label>
355
  <select id="voGender">
356
+ <option value="female" selected>Female</option>
357
  <option value="male">Male</option>
358
  <option value="youth">Youth</option>
359
  </select>
 
361
  <div>
362
  <label for="voTone">🎚 Tone</label>
363
  <select id="voTone">
364
+ <option value="cinematic" selected>Cinematic</option>
365
  <option value="friendly">Friendly</option>
366
  <option value="authoritative">Authoritative</option>
367
  <option value="educational">Educational</option>
 
378
  </select>
379
  </div>
380
  </div>
381
+ <label for="voScript" style="margin-top:.5rem;">📝 Voiceover Script (optional)</label>
382
+ <textarea id="voScript" rows="3" placeholder="Write your VO script here... or leave empty to generate later"></textarea>
 
 
383
  </div>
384
 
385
  <div class="row">
 
387
  <label for="colorPalette">🎨 Color Palette</label>
388
  <select id="colorPalette">
389
  <option>Graphite / Obsidian / Silver</option>
390
+ <option selected>Amber / Gold / Copper</option>
391
  <option>Steel Blue / Cyan / Teal</option>
392
  <option>Neon Accents (Magenta / Cyan / Lime)</option>
393
  <option>Monochrome</option>
 
402
  <option>Sparks Hit Lens</option>
403
  <option>Seal Rip Recoil</option>
404
  <option>Lights Power-on Cascade</option>
405
+ <option selected>Tarp Whip-Off</option>
406
  <option>Confetti Pop</option>
407
  <option>Macro Finger Press</option>
408
  <option>Countdown Flash</option>
 
415
  <div>
416
  <label for="finale">🎬 Finale / Closing Action</label>
417
  <select id="finale">
418
+ <option selected>Hero Push-in → Blackout</option>
419
  <option>Butterfly Doors + 360 Orbit</option>
420
  <option>Taillight Bloom → Logo-out</option>
 
421
  <option>Freeze Frame + End Card</option>
422
  <option>Speed-Ramp Drive-by</option>
423
  <option>Reverse Reveal Cloth Fall</option>
 
429
  </div>
430
  </div>
431
 
432
+ <div>
433
  <label for="negativePrompt">🚫 Negative Prompt (Exclude Things)</label>
434
  <textarea id="negativePrompt" rows="3" placeholder="e.g., no logos, no text overlays, no watermark, no extra limbs"></textarea>
435
+ <div class="note">Smart Mode auto-adds clean negatives if left empty.</div>
436
  </div>
437
 
438
  <div class="actions">
 
446
  <div id="toast" class="toast" role="status" aria-live="polite">Copied!</div>
447
 
448
  <script>
449
+ // ===== Helpers & Baseline =====
450
  const $ = (id) => document.getElementById(id);
451
 
452
+ function showToast(msg="Copied!"){
453
+ const t = $("toast"); if(!t) return; t.textContent = msg; t.classList.add("show"); setTimeout(()=>t.classList.remove("show"), 1200);
454
+ }
455
+
456
+ function copyToClipboard(){
457
+ const text = $("output").textContent || "";
458
+ navigator.clipboard.writeText(text).then(()=>showToast("Copied!"));
459
+ }
460
+
461
+ // Fallback generatePrompt so our override can call it safely
462
+ if (typeof window.generatePrompt !== 'function') {
463
+ window.generatePrompt = function(){ /* no-op baseline */ };
464
+ }
465
+ </script>
466
+
467
+ <script>
468
+ // ====== SMART MAPPINGS ======
469
+ const AR_TO_PLATFORMS = {
470
+ "9:16": ["tiktok","instagram_reels","facebook_reels","shorts","snap","stories"],
471
+ "16:9": ["youtube","facebook","x","linkedin"],
472
+ "1:1": ["instagram_feed","facebook"]
473
+ };
474
+
475
+ const AUTO_PRESETS = {
476
+ cinematic: {
477
+ camera: ["dolly","rack-focus","360 orbit"],
478
+ lighting: "Backlight + Haze",
479
+ bg: "showroom",
480
+ music: "Cinematic Pulses",
481
+ sfx: "Whoosh / Riser"
482
  },
483
+ "product-hero": {
484
+ camera: ["slider","macro"],
485
+ lighting: "Top Light High-Contrast",
486
+ bg: "studio",
487
+ music: "Hybrid Orchestral",
488
+ sfx: "Metallic Clinks"
 
489
  },
490
+ tutorial: {
491
+ camera: ["handheld","rack-focus"],
492
+ lighting: "Soft Wrap Key",
493
+ bg: "lab",
494
+ music: "Educational",
495
+ sfx: "Click / Tap"
496
  },
497
+ "BTS/documentary": {
498
+ camera: ["handheld"],
499
+ lighting: "Neutral Daylight",
500
+ bg: "warehouse",
501
+ music: "Natural Documentary",
502
+ sfx: "Ambient Room"
 
503
  },
504
+ meme: {
505
+ camera: ["smash-zoom","whip-pan"],
506
+ lighting: "High-Key Clean",
507
+ bg: "auto",
508
+ music: "Trap",
509
+ sfx: "Smash-Zoom Gag"
 
510
  }
511
  };
512
 
513
+ const DOMAIN_HINTS = {
514
+ education: { lighting: "Neutral Daylight", bg: "lab" },
515
+ advertisement:{ lighting: "Top Light High-Contrast", bg: "showroom" },
516
+ product_demo:{ lighting: "High-Key Clean", bg: "studio" },
517
+ creator_pov: { lighting: "Soft Wrap Key", bg: "night_city" }
518
+ };
519
 
520
+ const QUALITY_PRESET = {
521
+ draft: { fps: 24, grain: "off", denoise: "on", duration: "8–10s" },
522
+ pro: { fps: 30, grain: "light",denoise: "auto",duration: "10–12s" },
523
+ cinematic: { fps: 30, grain: "gentle filmic", denoise: "auto", duration: "12–14s" }
524
+ };
525
 
526
+ const el = (id)=>document.getElementById(id);
527
+
528
+ const aspectEl = el("aspectRatio");
529
+ const platEl = el("platform");
530
+ const varEl = el("variant");
531
+ const domEl = el("domain");
532
+ const proToggle = el("proModeToggle");
533
+ const qualEl = el("qualityPreset") || { value:"pro" };
534
+
535
+ function syncPlatformsFromAspect() {
536
+ if (!aspectEl || !platEl) return;
537
+ const ar = aspectEl.value;
538
+ const rec = AR_TO_PLATFORMS[ar] || [];
539
+ platEl.dataset.recommended = JSON.stringify(rec);
540
+ const pro = proToggle?.checked;
541
+ if (!pro) {
542
+ platEl.value = rec[0] || "tiktok";
543
+ platEl.disabled = true;
544
+ platEl.title = `Auto: ${rec.join(", ")}`;
545
+ } else {
546
+ platEl.disabled = false; platEl.title = "";
547
  }
 
548
  }
549
 
550
+ function setIfAuto(selectEl, val){
551
+ if (!selectEl) return;
552
+ const cur = (selectEl.value||"").toLowerCase();
553
+ if (cur === "auto" || cur === "🎯 auto based on scene".toLowerCase() || cur === "🛠️ auto select".toLowerCase() || cur === "") {
554
+ selectEl.value = val;
555
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
556
  }
557
 
558
+ function autoFromVariantAndDomain() {
559
+ const v = (varEl?.value || "cinematic").toLowerCase();
560
+ const d = (domEl?.value || "advertisement").toLowerCase();
561
+ const vAuto = AUTO_PRESETS[v] || {};
562
+ const dAuto = DOMAIN_HINTS[d] || {};
563
+
564
+ const cameraEl = el("camera");
565
+ const lightingEl = el("lightingMood");
566
+ const bgEl = el("background");
567
+ const musicEl = el("audioTrack");
568
+ const sfxEl = el("sfx");
569
+
570
+ const cameraVal = Array.isArray(vAuto.camera) ? vAuto.camera[0] : vAuto.camera;
571
+ setIfAuto(cameraEl, cameraVal || "auto");
572
+ setIfAuto(lightingEl, vAuto.lighting || dAuto.lighting || "🛠️ Auto Select");
573
+ setIfAuto(bgEl, vAuto.bg || dAuto.bg || "auto");
574
+ setIfAuto(musicEl, vAuto.music || "Cinematic Pulses");
575
+ setIfAuto(sfxEl, vAuto.sfx || "Whoosh / Riser");
576
+ }
577
+
578
+ function syncProLocking(){
579
+ const pro = proToggle?.checked;
580
+ const advancedIds = [
581
+ "platform","camera","background","lightingMood","audioTrack","sfx",
582
+ "colorPalette","hook","finale","keywords","negativePrompt",
583
+ "skinTone","headCover","voLanguage","voGender","voTone","voPace"
584
+ ];
585
+ advancedIds.forEach(id=>{
586
+ const node = el(id);
587
+ if (!node) return;
588
+ node.disabled = !pro;
589
+ node.closest("div")?.classList?.toggle("dimmed", !pro);
590
+ });
591
+ syncPlatformsFromAspect();
592
+ }
593
+
594
+ function cleanObj(obj){
595
+ const isArr = Array.isArray(obj);
596
+ const acc = isArr ? [] : {};
597
+ Object.entries(obj).forEach(([k,v])=>{
598
+ if (v === undefined || v === null) return;
599
+ if (typeof v === 'string' && v.trim() === '') return;
600
+ if (typeof v === 'string' && /^(auto|🛠️ Auto Select|🎯 Auto Based on Scene)$/i.test(v.trim())) return;
601
+ if (Array.isArray(v) && v.length===0) return;
602
+ acc[k] = (v && typeof v === 'object' && !Array.isArray(v)) ? cleanObj(v) : v;
603
+ });
604
+ return acc;
605
+ }
606
+
607
+ const _oldGenerate = window.generatePrompt;
608
+ window.generatePrompt = function(){
609
+ autoFromVariantAndDomain();
610
+ syncPlatformsFromAspect();
611
+
612
+ const qp = QUALITY_PRESET[qualEl.value] || QUALITY_PRESET.pro;
613
+
614
+ const variant = el("variant")?.value || "cinematic";
615
+ const ar = el("aspectRatio")?.value || "16:9";
616
+ const domain = el("domain")?.value || "advertisement";
617
+ const scene = (el("taskFocus")?.value === "custom" ? el("customTask")?.value : el("taskFocus")?.value) || "Product Reveal";
618
+
619
+ const lookOn = el("useLookPreset")?.checked;
620
+ const voOn = el("useVoiceover")?.checked;
621
+
622
+ let subjectLook = null;
623
+ if (lookOn) {
624
+ const type = el("characterType")?.value;
625
+ const tone = el("skinTone")?.value;
626
+ const hc = el("headCover")?.value;
627
+ subjectLook = { type, skin_tone: tone, head_cover: hc };
628
+ }
629
 
630
+ let voiceover = null;
631
+ if (voOn) {
632
+ voiceover = {
633
+ language: el("voLanguage")?.value,
634
+ voice: el("voGender")?.value,
635
+ tone: el("voTone")?.value,
636
+ pace: el("voPace")?.value,
637
+ script: (el("voScript")?.value || "").trim()
638
+ };
639
+ }
640
 
641
+ const camera = el("camera")?.value;
642
+ const lighting = el("lightingMood")?.value;
643
+ const bg = el("background")?.value;
644
+ const music = el("audioTrack")?.value;
645
+ const sfx = el("sfx")?.value;
646
+
647
+ let platforms = [];
648
+ if (platEl?.dataset?.recommended && !platEl.disabled){
649
+ platforms = [platEl.value];
650
+ } else if (platEl?.dataset?.recommended){
651
+ platforms = JSON.parse(platEl.dataset.recommended);
652
+ }
653
 
654
+ const negatives = (el("negativePrompt")?.value || "no logos, no text overlays, no watermark").trim();
 
 
 
 
 
 
 
655
 
656
+ const meta = {
657
+ aspect_ratio: ar,
658
+ duration: qp.duration,
659
+ fps: qp.fps,
660
+ grain: qp.grain,
661
+ denoise: qp.denoise,
662
+ platforms
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
663
  };
664
 
665
+ const out = cleanObj({
 
 
 
666
  variant,
667
+ domain,
668
+ scene_title: scene,
669
+ meta,
670
+ subject_look: subjectLook,
671
+ visual_style: el("visualStyle")?.value || "Cinematic / Filmic Grain",
 
 
672
  camera,
673
+ background: bg,
674
+ lighting,
675
+ music,
676
+ sfx,
677
+ color_palette: el("colorPalette")?.value,
678
+ hook: el("hook")?.value,
679
+ finale: el("finale")?.value,
680
+ voiceover,
681
+ keywords: (el("keywords")?.value||"").trim(),
682
+ negative_prompt: negatives
683
+ });
684
+
685
+ const pretty = JSON.stringify(out, null, 2);
686
+ document.getElementById("output").textContent = pretty;
687
+
688
+ if (typeof _oldGenerate === "function") { try { _oldGenerate(); } catch(e){} }
689
+ };
 
 
690
 
691
+ // Events
692
+ aspectEl?.addEventListener("change", syncPlatformsFromAspect);
693
+ varEl?.addEventListener("change", ()=>{ autoFromVariantAndDomain(); });
694
+ domEl?.addEventListener("change", ()=>{ autoFromVariantAndDomain(); });
 
 
 
 
 
 
 
 
 
 
 
695
 
696
+ const taskFocus = el('taskFocus');
697
+ const customTaskWrap = el('customTaskWrapper');
698
+ taskFocus?.addEventListener('change', ()=>{
699
+ customTaskWrap.style.display = taskFocus.value === 'custom' ? 'block' : 'none';
700
+ });
701
 
702
+ proToggle?.addEventListener("change", ()=>{ syncProLocking(); });
703
+ document.addEventListener("DOMContentLoaded", ()=>{
704
+ syncProLocking();
705
+ autoFromVariantAndDomain();
706
+ syncPlatformsFromAspect();
 
 
 
 
 
 
 
 
 
707
  });
708
  </script>
709
  </body>
710
+ </html>