Gaurav vashistha commited on
Commit
4b47c3d
·
1 Parent(s): e99491d

Fix UI layout: Header, Drawer, and Floating Controls

Browse files
Files changed (1) hide show
  1. stitch_continuity_dashboard/code.html +227 -166
stitch_continuity_dashboard/code.html CHANGED
@@ -46,7 +46,20 @@
46
  overflow: hidden;
47
  }
48
 
49
- /* Sliders */
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  input[type=range] {
51
  -webkit-appearance: none;
52
  background: transparent;
@@ -75,178 +88,219 @@
75
 
76
  <body
77
  class="bg-background-dark font-body text-white h-screen w-screen overflow-hidden flex flex-col selection:bg-primary selection:text-white relative">
78
- <div class="flex items-center gap-3">
79
- <div
80
- class="size-8 flex items-center justify-center bg-primary/20 rounded-lg border border-primary/30 text-primary">
81
- <span class="material-symbols-outlined">movie_filter</span>
 
 
 
 
 
 
 
 
 
 
82
  </div>
83
- <h1 class="text-xl font-display font-bold tracking-tight">Continuity</h1>
84
- </div>
85
- <div class="flex items-center gap-3">
86
- <button onclick="toggleDrawer(true)"
87
- class="flex items-center gap-2 px-4 py-2 bg-primary hover:bg-[#6b0bc9] text-white rounded-lg transition-colors text-xs font-bold uppercase tracking-wider shadow-neon">
88
- <span class="material-symbols-outlined text-lg">history</span> Gallery
89
- </button>
90
- </div>
91
- <div class="w-full max-w-6xl mx-auto flex items-center justify-center gap-4 md:gap-8 lg:gap-12 mt-12">
92
-
93
- <div class="flex flex-col gap-3 flex-1 max-w-[320px] group">
94
- <div class="flex justify-between px-1"><span
95
- class="text-[10px] font-bold tracking-widest text-gray-500 uppercase">Scene A (Start)</span></div>
96
- <div class="relative aspect-[9/16] md:aspect-[3/4] bg-surface-dark border-2 border-dashed border-border-dark rounded-2xl flex flex-col items-center justify-center gap-4 hover:border-primary/50 hover:bg-surface-dark/80 transition-all cursor-pointer shadow-lg overflow-hidden"
97
- onclick="document.getElementById('video-upload-a').click()">
98
- <div
99
- class="size-12 rounded-full bg-white/5 flex items-center justify-center group-hover:scale-110 transition-transform relative z-10">
100
- <span class="material-symbols-outlined text-2xl text-gray-400 group-hover:text-white">upload</span>
 
 
 
 
 
 
 
 
 
 
 
101
  </div>
102
- <p id="label-a" class="text-xs font-medium text-gray-400 text-center px-4 relative z-10">Upload Start
103
- Clip</p>
104
- <input type="file" id="video-upload-a" accept="video/*" class="hidden"
105
- onchange="handleFileSelect(this, 'label-a')">
106
  </div>
107
- </div>
108
- <div class="flex flex-col gap-3 flex-[1.5] max-w-[500px] relative z-20">
109
- <div class="flex justify-center px-1"><span
110
- class="text-[10px] font-bold tracking-[0.2em] text-primary uppercase animate-pulse">Generated
111
- Bridge</span></div>
112
- <div id="bridge-card-outer"
113
- class="relative aspect-video rounded-2xl shadow-neon transition-all duration-500 border border-primary/20">
114
- <div id="bridge-card-inner" class="force-clip w-full h-full bg-black relative">
115
- <div id="bridge-content" class="w-full h-full">
116
- <div
117
- class="absolute inset-0 bg-[url('https://images.unsplash.com/photo-1614850523060-8da1d56ae167?q=80&w=1000&auto=format&fit=crop')] bg-cover bg-center opacity-20 mix-blend-overlay">
118
- </div>
119
- <div class="absolute inset-0 flex flex-col items-center justify-center text-center p-6">
120
  <div
121
- class="size-16 rounded-full bg-primary/10 border border-primary/20 flex items-center justify-center mb-3">
122
- <span class="material-symbols-outlined text-3xl text-primary">auto_awesome</span></div>
123
- <p class="text-sm text-gray-300">Ready to bridge the gap</p>
 
 
 
 
 
 
 
 
 
124
  </div>
125
  </div>
126
- <div id="bridge-border"
127
- class="absolute inset-0 rounded-2xl border-2 border-transparent pointer-events-none z-30"></div>
 
 
 
 
 
 
128
  </div>
129
  </div>
130
- <div id="merged-download-container"
131
- class="hidden flex justify-center mt-4 animate-in fade-in slide-in-from-top-2">
132
- <a id="merged-download-btn" href="#" download
133
- class="flex items-center gap-2 px-6 py-3 bg-surface-dark hover:bg-white/5 border border-primary/30 hover:border-primary text-primary hover:text-white rounded-xl font-bold text-xs uppercase tracking-widest transition-all shadow-lg group">
134
- <span class="material-symbols-outlined group-hover:animate-bounce">movie</span> Download Merged
135
- (A+B+C)
136
- </a>
137
- </div>
138
- </div>
139
- <div class="flex flex-col gap-3 flex-1 max-w-[320px] group">
140
- <div class="flex justify-end px-1"><span
141
- class="text-[10px] font-bold tracking-widest text-gray-500 uppercase">Scene C (End)</span></div>
142
- <div class="relative aspect-[9/16] md:aspect-[3/4] bg-surface-dark border-2 border-dashed border-border-dark rounded-2xl flex flex-col items-center justify-center gap-4 hover:border-primary/50 hover:bg-surface-dark/80 transition-all cursor-pointer shadow-lg overflow-hidden"
143
- onclick="document.getElementById('video-upload-c').click()">
144
- <div
145
- class="size-12 rounded-full bg-white/5 flex items-center justify-center group-hover:scale-110 transition-transform relative z-10">
146
- <span class="material-symbols-outlined text-2xl text-gray-400 group-hover:text-white">upload</span>
147
  </div>
148
- <p id="label-c" class="text-xs font-medium text-gray-400 text-center px-4 relative z-10">Upload End Clip
149
- </p>
150
- <input type="file" id="video-upload-c" accept="video/*" class="hidden"
151
- onchange="handleFileSelect(this, 'label-c')">
152
  </div>
 
153
  </div>
154
- </div>
155
- <div id="analysis-panel"
156
- class="glass-panel p-2 rounded-full shadow-neon flex items-center justify-between pl-6 pr-2">
157
- <div class="flex flex-col"><span class="text-sm font-bold text-white">Continuity Engine</span><span
158
- class="text-[10px] text-gray-400 uppercase tracking-wide">Ready for analysis</span></div>
159
- <div class="flex gap-2">
160
- <button onclick="toggleDrawer(true)"
161
- class="bg-surface-dark hover:bg-white/10 text-white p-3 rounded-full transition-all flex items-center justify-center border border-white/10"><span
162
- class="material-symbols-outlined text-lg">history</span></button>
163
- <button id="analyze-btn"
164
- class="bg-primary hover:bg-[#6b0bc9] text-white px-6 py-3 rounded-full font-bold text-sm transition-all flex items-center gap-2 shadow-lg"><span
165
- class="material-symbols-outlined text-lg">analytics</span> Analyze Scenes</button>
166
- </div>
167
- </div>
168
- <div id="review-panel"
169
- class="hidden glass-panel rounded-2xl p-5 shadow-2xl flex flex-col gap-4 animate-in slide-in-from-bottom-4 duration-300 max-h-[80vh] overflow-y-auto custom-scrollbar">
170
- <div class="flex items-center justify-between border-b border-white/10 pb-3">
171
- <h3 class="text-sm font-bold text-white flex items-center gap-2"><span
172
- class="material-symbols-outlined text-primary">movie_edit</span> Director's Configuration</h3>
173
  <div class="flex gap-2">
174
  <button onclick="toggleDrawer(true)"
175
- class="text-xs text-gray-400 hover:text-white uppercase tracking-wider flex items-center gap-1"><span
176
- class="material-symbols-outlined text-sm">history</span> History</button>
177
- <span class="text-white/10">|</span>
178
- <button onclick="resetUI()"
179
- class="text-xs text-gray-500 hover:text-white uppercase tracking-wider">Reset</button>
180
  </div>
181
  </div>
182
- <div><label class="text-[10px] font-bold text-gray-500 uppercase tracking-widest mb-1 block">Visual
183
- Direction</label><textarea id="prompt-box" rows="2"
184
- class="w-full bg-black/20 border border-white/10 rounded-lg p-3 text-sm text-white focus:border-primary focus:ring-1 focus:ring-primary outline-none resize-none"></textarea>
185
- </div>
186
- <div class="grid grid-cols-2 gap-4">
187
- <div><label class="text-[10px] font-bold text-gray-500 uppercase tracking-widest mb-1 block">Visual
188
- Style</label><select id="style-select" onchange="savePreference('style', this.value)"
189
- class="w-full bg-black/20 border border-white/10 rounded-lg p-2.5 text-sm text-white focus:border-primary outline-none cursor-pointer">
190
- <option value="Cinematic">Cinematic</option>
191
- <option value="Anime">Anime</option>
192
- <option value="Cyberpunk">Cyberpunk</option>
193
- <option value="VHS">VHS Glitch</option>
194
- <option value="Noir">Noir</option>
195
- </select></div>
196
- <div><label class="text-[10px] font-bold text-gray-500 uppercase tracking-widest mb-1 block">Audio
197
- Mood</label><select id="audio-input" onchange="savePreference('audio', this.value)"
198
- class="w-full bg-black/20 border border-white/10 rounded-lg p-2.5 text-sm text-white focus:border-primary outline-none cursor-pointer">
199
- <option value="Cinematic orchestral score">Cinematic</option>
200
- <option value="Industrial synthwave">Cyberpunk</option>
201
- <option value="Nature sounds">Nature</option>
202
- <option value="Tense atmosphere">Horror</option>
203
- <option value="High energy rock">Action</option>
204
- </select></div>
205
- </div>
206
- <div class="border-t border-white/10 pt-3">
207
- <button onclick="document.getElementById('advanced-settings').classList.toggle('hidden')"
208
- class="flex items-center gap-2 text-xs font-bold text-gray-400 uppercase tracking-widest hover:text-white transition-colors w-full"><span
209
- class="material-symbols-outlined text-sm">tune</span> Advanced Physics & Controls <span
210
- class="material-symbols-outlined text-sm ml-auto">expand_more</span></button>
211
- <div id="advanced-settings"
212
- class="hidden pt-3 grid grid-cols-1 md:grid-cols-2 gap-4 animate-in fade-in slide-in-from-top-2">
213
- <div class="col-span-1 md:col-span-2"><label
214
- class="text-[10px] text-gray-500 uppercase font-bold">Negative Prompt</label><input
215
- id="negative-prompt" type="text" placeholder="text, blurry, watermark"
216
- class="w-full bg-black/20 border border-white/10 rounded-lg p-2 text-xs text-white focus:border-red-500/50 outline-none mt-1">
217
- </div>
218
- <div>
219
- <div class="flex justify-between"><label
220
- class="text-[10px] text-gray-500 uppercase font-bold">Guidance Scale</label><span
221
- id="guidance-val" class="text-[10px] text-primary">5.0</span></div><input
222
- id="guidance-scale" type="range" min="1" max="20" value="5" step="0.5" class="w-full mt-2"
223
- oninput="document.getElementById('guidance-val').innerText = this.value">
224
  </div>
225
- <div>
226
- <div class="flex justify-between"><label
227
- class="text-[10px] text-gray-500 uppercase font-bold">Motion Strength</label><span
228
- id="motion-val" class="text-[10px] text-primary">5</span></div><input id="motion-strength"
229
- type="range" min="1" max="10" value="5" class="w-full mt-2"
230
- oninput="document.getElementById('motion-val').innerText = this.value">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  </div>
232
  </div>
 
 
 
233
  </div>
234
- <button id="generate-btn"
235
- class="w-full bg-gradient-to-r from-primary to-[#9d4edd] hover:brightness-110 text-white py-3.5 rounded-xl font-bold text-sm tracking-wide shadow-lg flex items-center justify-center gap-2 mt-1"><span
236
- class="material-symbols-outlined">auto_fix_high</span> Generate Video</button>
237
- </div>
238
- <div class="p-6 border-b border-white/5 flex items-center justify-between bg-surface-dark">
239
- <h2 class="text-lg font-bold text-white flex items-center gap-2"><span
240
- class="material-symbols-outlined text-primary">history</span> History</h2>
241
- <button onclick="toggleDrawer(false)"
242
- class="text-gray-400 hover:text-white transition-colors cursor-pointer"><span
243
- class="material-symbols-outlined">close</span></button>
244
- </div>
245
- <div id="gallery-content" class="flex-1 overflow-y-auto p-4 space-y-4">
246
- <div class="text-center text-gray-500 mt-10">Loading history...</div>
247
- </div>
248
  </div>
249
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  <script>
251
  function toggleDrawer(show) {
252
  const drawer = document.getElementById('gallery-drawer');
@@ -256,21 +310,23 @@
256
  console.error("Drawer elements not found! Check HTML structure.");
257
  return;
258
  }
 
259
  if (show) {
260
- // Use Tailwind classes to animate
261
- drawer.classList.remove('translate-x-full');
262
- drawer.classList.add('translate-x-0');
263
  overlay.classList.remove('hidden');
264
  fetchHistory();
265
  } else {
266
- drawer.classList.remove('translate-x-0');
267
- drawer.classList.add('translate-x-full');
268
  overlay.classList.add('hidden');
269
  }
270
  }
271
- // --- REST OF APP LOGIC ---
 
272
  let currentVideoAPath = "";
273
  let currentVideoCPath = "";
 
274
  function savePreference(key, value) { localStorage.setItem('continuity_' + key, value); }
275
  function loadPreferences() {
276
  const s = localStorage.getItem('continuity_style');
@@ -279,6 +335,7 @@
279
  if (a) document.getElementById('audio-input').value = a;
280
  }
281
  loadPreferences();
 
282
  async function fetchHistory() {
283
  const c = document.getElementById('gallery-content');
284
  c.innerHTML = '<div class="text-center mt-10"><span class="material-symbols-outlined animate-spin">progress_activity</span></div>';
@@ -290,23 +347,25 @@
290
  return;
291
  }
292
  c.innerHTML = data.map(i => `
293
- <div class="bg-black/40 rounded-lg overflow-hidden border border-white/5 mb-4">
294
- <video src="${i.url}" class="w-full aspect-video object-cover" controls></video>
295
- <div class="p-2 flex justify-between items-center">
296
- <span class="text-[10px] text-gray-400 truncate w-32">${i.name}</span>
297
- <a href="${i.url}" download class="text-gray-400 hover:text-white"><span class="material-symbols-outlined text-sm">download</span></a>
298
- </div>
299
- </div>`).join('');
300
  } catch (e) {
301
  c.innerHTML = '<div class="text-center text-red-400 mt-10">Error loading history.</div>';
302
  }
303
  }
 
304
  function handleFileSelect(input, labelId) {
305
  if (input.files[0]) {
306
  document.getElementById(labelId).innerText = input.files[0].name;
307
  document.getElementById(labelId).classList.add("text-primary", "font-bold");
308
  }
309
  }
 
310
  function resetUI() {
311
  document.getElementById("analysis-panel").classList.remove("hidden");
312
  document.getElementById("review-panel").classList.add("hidden");
@@ -319,6 +378,7 @@
319
  document.getElementById("bridge-border").classList.replace("border-primary/50", "border-transparent");
320
  document.getElementById("merged-download-container").classList.add("hidden");
321
  }
 
322
  document.getElementById("analyze-btn").addEventListener("click", async () => {
323
  const fA = document.getElementById("video-upload-a").files[0];
324
  const fC = document.getElementById("video-upload-c").files[0];
@@ -344,6 +404,7 @@
344
  btn.innerHTML = `<span class="material-symbols-outlined text-lg">analytics</span> Analyze Scenes`;
345
  }
346
  });
 
347
  document.getElementById("generate-btn").addEventListener("click", async () => {
348
  const btn = document.getElementById("generate-btn");
349
  btn.disabled = true;
@@ -372,7 +433,7 @@
372
  clearInterval(poll);
373
  document.getElementById("bridge-content").innerHTML = `<video controls autoplay loop class="w-full h-full object-contain bg-black"><source src="${s.video_url}" type="video/mp4"></video>`;
374
  document.getElementById("bridge-card-outer").classList.replace("border-primary/20", "border-primary");
375
- document.getElementById("bridge-border").classList.replace("border-transparent", "border-primary/50");
376
  if (s.merged_video_url) {
377
  const dlBtn = document.getElementById("merged-download-btn");
378
  dlBtn.href = s.merged_video_url;
 
46
  overflow: hidden;
47
  }
48
 
49
+ /* Drawer Transitions */
50
+ #gallery-drawer {
51
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
52
+ }
53
+
54
+ .drawer-open {
55
+ transform: translateX(0%);
56
+ }
57
+
58
+ .drawer-closed {
59
+ transform: translateX(100%);
60
+ }
61
+
62
+ /* Range Sliders */
63
  input[type=range] {
64
  -webkit-appearance: none;
65
  background: transparent;
 
88
 
89
  <body
90
  class="bg-background-dark font-body text-white h-screen w-screen overflow-hidden flex flex-col selection:bg-primary selection:text-white relative">
91
+
92
+ <!-- Header: Logo & Top Controls -->
93
+ <header
94
+ class="flex items-center justify-between px-6 py-4 z-40 relative w-full border-b border-white/5 bg-background-dark/50 backdrop-blur-sm">
95
+ <div class="flex items-center gap-3">
96
+ <div
97
+ class="size-8 flex items-center justify-center bg-primary/20 rounded-lg border border-primary/30 text-primary">
98
+ <span class="material-symbols-outlined">movie_filter</span>
99
+ </div>
100
+ <h1 class="text-xl font-display font-bold tracking-tight">Continuity</h1>
101
+ <div class="flex items-center gap-2 px-2 py-1 bg-green-500/10 border border-green-500/20 rounded-full ml-2">
102
+ <div class="size-1.5 rounded-full bg-green-500 animate-pulse"></div>
103
+ <span class="text-[10px] font-bold text-green-500 uppercase tracking-wider">Online</span>
104
+ </div>
105
  </div>
106
+
107
+ <div class="flex items-center gap-3">
108
+ <button onclick="toggleDrawer(true)"
109
+ class="flex items-center gap-2 px-4 py-2 bg-primary hover:bg-[#6b0bc9] text-white rounded-lg transition-colors text-xs font-bold uppercase tracking-wider shadow-neon">
110
+ <span class="material-symbols-outlined text-lg">history</span> Gallery
111
+ </button>
112
+ </div>
113
+ </header>
114
+
115
+ <!-- Main Stage: Scrollable Content -->
116
+ <main class="flex-1 w-full overflow-y-auto relative flex flex-col items-center pt-8 pb-32">
117
+ <div class="w-full max-w-6xl mx-auto flex items-center justify-center gap-4 md:gap-8 lg:gap-12 px-4">
118
+
119
+ <!-- SCENE A -->
120
+ <div class="flex flex-col gap-3 flex-1 max-w-[320px] group">
121
+ <div class="flex justify-between px-1"><span
122
+ class="text-[10px] font-bold tracking-widest text-gray-500 uppercase">Scene A (Start)</span>
123
+ </div>
124
+ <div class="relative aspect-[9/16] md:aspect-[3/4] bg-surface-dark border-2 border-dashed border-border-dark rounded-2xl flex flex-col items-center justify-center gap-4 hover:border-primary/50 hover:bg-surface-dark/80 transition-all cursor-pointer shadow-lg overflow-hidden"
125
+ onclick="document.getElementById('video-upload-a').click()">
126
+ <div
127
+ class="size-12 rounded-full bg-white/5 flex items-center justify-center group-hover:scale-110 transition-transform relative z-10">
128
+ <span
129
+ class="material-symbols-outlined text-2xl text-gray-400 group-hover:text-white">upload</span>
130
+ </div>
131
+ <p id="label-a" class="text-xs font-medium text-gray-400 text-center px-4 relative z-10">Upload
132
+ Start Clip</p>
133
+ <input type="file" id="video-upload-a" accept="video/*" class="hidden"
134
+ onchange="handleFileSelect(this, 'label-a')">
135
  </div>
 
 
 
 
136
  </div>
137
+
138
+ <!-- GENERATED BRIDGE -->
139
+ <div class="flex flex-col gap-3 flex-[1.5] max-w-[500px] relative z-20">
140
+ <div class="flex justify-center px-1"><span
141
+ class="text-[10px] font-bold tracking-[0.2em] text-primary uppercase animate-pulse">Generated
142
+ Bridge</span></div>
143
+ <div id="bridge-card-outer"
144
+ class="relative aspect-video rounded-2xl shadow-neon transition-all duration-500 border border-primary/20">
145
+ <div id="bridge-card-inner" class="force-clip w-full h-full bg-black relative">
146
+ <div id="bridge-content" class="w-full h-full">
 
 
 
147
  <div
148
+ class="absolute inset-0 bg-[url('https://images.unsplash.com/photo-1614850523060-8da1d56ae167?q=80&w=1000&auto=format&fit=crop')] bg-cover bg-center opacity-20 mix-blend-overlay">
149
+ </div>
150
+ <div class="absolute inset-0 flex flex-col items-center justify-center text-center p-6">
151
+ <div
152
+ class="size-16 rounded-full bg-primary/10 border border-primary/20 flex items-center justify-center mb-3">
153
+ <span class="material-symbols-outlined text-3xl text-primary">auto_awesome</span>
154
+ </div>
155
+ <p class="text-sm text-gray-300">Ready to bridge the gap</p>
156
+ </div>
157
+ </div>
158
+ <div id="bridge-border"
159
+ class="absolute inset-0 rounded-2xl border-2 border-transparent pointer-events-none z-30">
160
  </div>
161
  </div>
162
+ </div>
163
+ <div id="merged-download-container"
164
+ class="hidden flex justify-center mt-4 animate-in fade-in slide-in-from-top-2">
165
+ <a id="merged-download-btn" href="#" download
166
+ class="flex items-center gap-2 px-6 py-3 bg-surface-dark hover:bg-white/5 border border-primary/30 hover:border-primary text-primary hover:text-white rounded-xl font-bold text-xs uppercase tracking-widest transition-all shadow-lg group">
167
+ <span class="material-symbols-outlined group-hover:animate-bounce">movie</span> Download Merged
168
+ (A+B+C)
169
+ </a>
170
  </div>
171
  </div>
172
+
173
+ <!-- SCENE C -->
174
+ <div class="flex flex-col gap-3 flex-1 max-w-[320px] group">
175
+ <div class="flex justify-end px-1"><span
176
+ class="text-[10px] font-bold tracking-widest text-gray-500 uppercase">Scene C (End)</span></div>
177
+ <div class="relative aspect-[9/16] md:aspect-[3/4] bg-surface-dark border-2 border-dashed border-border-dark rounded-2xl flex flex-col items-center justify-center gap-4 hover:border-primary/50 hover:bg-surface-dark/80 transition-all cursor-pointer shadow-lg overflow-hidden"
178
+ onclick="document.getElementById('video-upload-c').click()">
179
+ <div
180
+ class="size-12 rounded-full bg-white/5 flex items-center justify-center group-hover:scale-110 transition-transform relative z-10">
181
+ <span
182
+ class="material-symbols-outlined text-2xl text-gray-400 group-hover:text-white">upload</span>
183
+ </div>
184
+ <p id="label-c" class="text-xs font-medium text-gray-400 text-center px-4 relative z-10">Upload End
185
+ Clip</p>
186
+ <input type="file" id="video-upload-c" accept="video/*" class="hidden"
187
+ onchange="handleFileSelect(this, 'label-c')">
 
188
  </div>
 
 
 
 
189
  </div>
190
+
191
  </div>
192
+ </main>
193
+
194
+ <!-- Floating Controls (Absolute/Fixed over content) -->
195
+ <div class="fixed bottom-8 left-1/2 -translate-x-1/2 z-50 w-full max-w-2xl px-4 pointer-events-none">
196
+
197
+ <!-- Analysis Panel -->
198
+ <div id="analysis-panel"
199
+ class="glass-panel p-2 rounded-full shadow-neon flex items-center justify-between pl-6 pr-2 pointer-events-auto">
200
+ <div class="flex flex-col"><span class="text-sm font-bold text-white">Continuity Engine</span><span
201
+ class="text-[10px] text-gray-400 uppercase tracking-wide">Ready for analysis</span></div>
 
 
 
 
 
 
 
 
 
202
  <div class="flex gap-2">
203
  <button onclick="toggleDrawer(true)"
204
+ class="bg-surface-dark hover:bg-white/10 text-white p-3 rounded-full transition-all flex items-center justify-center border border-white/10"><span
205
+ class="material-symbols-outlined text-lg">history</span></button>
206
+ <button id="analyze-btn"
207
+ class="bg-primary hover:bg-[#6b0bc9] text-white px-6 py-3 rounded-full font-bold text-sm transition-all flex items-center gap-2 shadow-lg"><span
208
+ class="material-symbols-outlined text-lg">analytics</span> Analyze Scenes</button>
209
  </div>
210
  </div>
211
+
212
+ <!-- Review Panel -->
213
+ <div id="review-panel"
214
+ class="hidden glass-panel rounded-2xl p-5 shadow-2xl flex flex-col gap-4 animate-in slide-in-from-bottom-4 duration-300 max-h-[80vh] overflow-y-auto custom-scrollbar pointer-events-auto">
215
+ <div class="flex items-center justify-between border-b border-white/10 pb-3">
216
+ <h3 class="text-sm font-bold text-white flex items-center gap-2"><span
217
+ class="material-symbols-outlined text-primary">movie_edit</span> Director's Configuration</h3>
218
+ <div class="flex gap-2">
219
+ <button onclick="toggleDrawer(true)"
220
+ class="text-xs text-gray-400 hover:text-white uppercase tracking-wider flex items-center gap-1"><span
221
+ class="material-symbols-outlined text-sm">history</span> History</button>
222
+ <span class="text-white/10">|</span>
223
+ <button onclick="resetUI()"
224
+ class="text-xs text-gray-500 hover:text-white uppercase tracking-wider">Reset</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  </div>
226
+ </div>
227
+ <div><label class="text-[10px] font-bold text-gray-500 uppercase tracking-widest mb-1 block">Visual
228
+ Direction</label><textarea id="prompt-box" rows="2"
229
+ class="w-full bg-black/20 border border-white/10 rounded-lg p-3 text-sm text-white focus:border-primary focus:ring-1 focus:ring-primary outline-none resize-none"></textarea>
230
+ </div>
231
+ <div class="grid grid-cols-2 gap-4">
232
+ <div><label class="text-[10px] font-bold text-gray-500 uppercase tracking-widest mb-1 block">Visual
233
+ Style</label><select id="style-select" onchange="savePreference('style', this.value)"
234
+ class="w-full bg-black/20 border border-white/10 rounded-lg p-2.5 text-sm text-white focus:border-primary outline-none cursor-pointer">
235
+ <option value="Cinematic">Cinematic</option>
236
+ <option value="Anime">Anime</option>
237
+ <option value="Cyberpunk">Cyberpunk</option>
238
+ <option value="VHS">VHS Glitch</option>
239
+ <option value="Noir">Noir</option>
240
+ </select></div>
241
+ <div><label class="text-[10px] font-bold text-gray-500 uppercase tracking-widest mb-1 block">Audio
242
+ Mood</label><select id="audio-input" onchange="savePreference('audio', this.value)"
243
+ class="w-full bg-black/20 border border-white/10 rounded-lg p-2.5 text-sm text-white focus:border-primary outline-none cursor-pointer">
244
+ <option value="Cinematic orchestral score">Cinematic</option>
245
+ <option value="Industrial synthwave">Cyberpunk</option>
246
+ <option value="Nature sounds">Nature</option>
247
+ <option value="Tense atmosphere">Horror</option>
248
+ <option value="High energy rock">Action</option>
249
+ </select></div>
250
+ </div>
251
+ <div class="border-t border-white/10 pt-3">
252
+ <button onclick="document.getElementById('advanced-settings').classList.toggle('hidden')"
253
+ class="flex items-center gap-2 text-xs font-bold text-gray-400 uppercase tracking-widest hover:text-white transition-colors w-full"><span
254
+ class="material-symbols-outlined text-sm">tune</span> Advanced Physics & Controls <span
255
+ class="material-symbols-outlined text-sm ml-auto">expand_more</span></button>
256
+ <div id="advanced-settings"
257
+ class="hidden pt-3 grid grid-cols-1 md:grid-cols-2 gap-4 animate-in fade-in slide-in-from-top-2">
258
+ <div class="col-span-1 md:col-span-2"><label
259
+ class="text-[10px] text-gray-500 uppercase font-bold">Negative Prompt</label><input
260
+ id="negative-prompt" type="text" placeholder="text, blurry, watermark"
261
+ class="w-full bg-black/20 border border-white/10 rounded-lg p-2 text-xs text-white focus:border-red-500/50 outline-none mt-1">
262
+ </div>
263
+ <div>
264
+ <div class="flex justify-between"><label
265
+ class="text-[10px] text-gray-500 uppercase font-bold">Guidance Scale</label><span
266
+ id="guidance-val" class="text-[10px] text-primary">5.0</span></div><input
267
+ id="guidance-scale" type="range" min="1" max="20" value="5" step="0.5" class="w-full mt-2"
268
+ oninput="document.getElementById('guidance-val').innerText = this.value">
269
+ </div>
270
+ <div>
271
+ <div class="flex justify-between"><label
272
+ class="text-[10px] text-gray-500 uppercase font-bold">Motion Strength</label><span
273
+ id="motion-val" class="text-[10px] text-primary">5</span></div><input
274
+ id="motion-strength" type="range" min="1" max="10" value="5" class="w-full mt-2"
275
+ oninput="document.getElementById('motion-val').innerText = this.value">
276
+ </div>
277
  </div>
278
  </div>
279
+ <button id="generate-btn"
280
+ class="w-full bg-gradient-to-r from-primary to-[#9d4edd] hover:brightness-110 text-white py-3.5 rounded-xl font-bold text-sm tracking-wide shadow-lg flex items-center justify-center gap-2 mt-1"><span
281
+ class="material-symbols-outlined">auto_fix_high</span> Generate Video</button>
282
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
283
  </div>
284
 
285
+ <!-- History Drawer Overlay -->
286
+ <div id="drawer-overlay" onclick="toggleDrawer(false)"
287
+ class="fixed inset-0 bg-black/80 backdrop-blur-sm z-[90] hidden transition-opacity"></div>
288
+
289
+ <!-- History Drawer -->
290
+ <aside id="gallery-drawer"
291
+ class="fixed top-0 right-0 h-full w-[400px] bg-background-dark border-l border-white/10 z-[100] drawer-closed flex flex-col shadow-2xl">
292
+ <div class="p-6 border-b border-white/5 flex items-center justify-between bg-surface-dark">
293
+ <h2 class="text-lg font-bold text-white flex items-center gap-2"><span
294
+ class="material-symbols-outlined text-primary">history</span> History</h2>
295
+ <button onclick="toggleDrawer(false)"
296
+ class="text-gray-400 hover:text-white transition-colors cursor-pointer"><span
297
+ class="material-symbols-outlined">close</span></button>
298
+ </div>
299
+ <div id="gallery-content" class="flex-1 overflow-y-auto p-4 space-y-4 custom-scrollbar">
300
+ <div class="text-center text-gray-500 mt-10">Loading history...</div>
301
+ </div>
302
+ </aside>
303
+
304
  <script>
305
  function toggleDrawer(show) {
306
  const drawer = document.getElementById('gallery-drawer');
 
310
  console.error("Drawer elements not found! Check HTML structure.");
311
  return;
312
  }
313
+
314
  if (show) {
315
+ drawer.classList.remove('drawer-closed');
316
+ drawer.classList.add('drawer-open');
 
317
  overlay.classList.remove('hidden');
318
  fetchHistory();
319
  } else {
320
+ drawer.classList.remove('drawer-open');
321
+ drawer.classList.add('drawer-closed');
322
  overlay.classList.add('hidden');
323
  }
324
  }
325
+
326
+ // --- APP LOGIC ---
327
  let currentVideoAPath = "";
328
  let currentVideoCPath = "";
329
+
330
  function savePreference(key, value) { localStorage.setItem('continuity_' + key, value); }
331
  function loadPreferences() {
332
  const s = localStorage.getItem('continuity_style');
 
335
  if (a) document.getElementById('audio-input').value = a;
336
  }
337
  loadPreferences();
338
+
339
  async function fetchHistory() {
340
  const c = document.getElementById('gallery-content');
341
  c.innerHTML = '<div class="text-center mt-10"><span class="material-symbols-outlined animate-spin">progress_activity</span></div>';
 
347
  return;
348
  }
349
  c.innerHTML = data.map(i => `
350
+ <div class="bg-black/40 rounded-lg overflow-hidden border border-white/5 mb-4 group">
351
+ <video src="${i.url}" class="w-full aspect-video object-cover" controls></video>
352
+ <div class="p-2 flex justify-between items-center bg-white/5">
353
+ <span class="text-[10px] text-gray-400 truncate w-32">${i.name}</span>
354
+ <a href="${i.url}" download class="text-gray-400 hover:text-white transition-colors"><span class="material-symbols-outlined text-sm">download</span></a>
355
+ </div>
356
+ </div>`).join('');
357
  } catch (e) {
358
  c.innerHTML = '<div class="text-center text-red-400 mt-10">Error loading history.</div>';
359
  }
360
  }
361
+
362
  function handleFileSelect(input, labelId) {
363
  if (input.files[0]) {
364
  document.getElementById(labelId).innerText = input.files[0].name;
365
  document.getElementById(labelId).classList.add("text-primary", "font-bold");
366
  }
367
  }
368
+
369
  function resetUI() {
370
  document.getElementById("analysis-panel").classList.remove("hidden");
371
  document.getElementById("review-panel").classList.add("hidden");
 
378
  document.getElementById("bridge-border").classList.replace("border-primary/50", "border-transparent");
379
  document.getElementById("merged-download-container").classList.add("hidden");
380
  }
381
+
382
  document.getElementById("analyze-btn").addEventListener("click", async () => {
383
  const fA = document.getElementById("video-upload-a").files[0];
384
  const fC = document.getElementById("video-upload-c").files[0];
 
404
  btn.innerHTML = `<span class="material-symbols-outlined text-lg">analytics</span> Analyze Scenes`;
405
  }
406
  });
407
+
408
  document.getElementById("generate-btn").addEventListener("click", async () => {
409
  const btn = document.getElementById("generate-btn");
410
  btn.disabled = true;
 
433
  clearInterval(poll);
434
  document.getElementById("bridge-content").innerHTML = `<video controls autoplay loop class="w-full h-full object-contain bg-black"><source src="${s.video_url}" type="video/mp4"></video>`;
435
  document.getElementById("bridge-card-outer").classList.replace("border-primary/20", "border-primary");
436
+ document.getElementById("bridge-border").classList.replace("border-primary/50", "border-transparent");
437
  if (s.merged_video_url) {
438
  const dlBtn = document.getElementById("merged-download-btn");
439
  dlBtn.href = s.merged_video_url;