Luigi commited on
Commit
bf4a5d3
·
verified ·
1 Parent(s): 4f87493

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +296 -181
index.html CHANGED
@@ -2,71 +2,159 @@
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>Autotutorial.ai Desktop - Video Tutorial Generator</title>
 
 
 
7
  <!-- Radix UI Styles -->
8
  <link rel="stylesheet" href="https://unpkg.com/@radix-ui/[email protected]/dist/index.css">
9
  <!-- Tailwind CSS CDN -->
10
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
11
  <!-- Font Awesome CDN -->
12
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" integrity="sha512-9usAa10IRO0HhonpyAIVpjrylPvoDwiPUiKdWk5t3PyolY1cOd4DSE0Ga+ri4AuTroPR5aQvXU9xC6qOPnzFeg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
13
- <!-- Inter & Poppins Fonts -->
14
  <link rel="preconnect" href="https://fonts.googleapis.com">
15
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
16
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@500;600;700&display=swap" rel="stylesheet">
 
17
  <style>
18
- body { font-family: 'Inter', sans-serif; background-color: var(--gray-50); color: var(--gray-900); }
19
- .app-container { max-width: 1200px; margin: 2rem auto; background-color: var(--white); border-radius: 0.75rem; overflow: hidden; box-shadow: 0 8px 16px rgba(0,0,0,0.12); /* More window-like shadow */ }
20
- header { background-image: linear-gradient(to right, var(--indigo-700), var(--indigo-800)); padding: 2.5rem 3rem; color: var(--white); position: relative; /* For title bar effect */ }
21
- header::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 8px; background-color: rgba(0,0,0,0.1); border-top-left-radius: 0.75rem; border-top-right-radius: 0.75rem; } /* Subtle title bar effect */
22
- header h1 { font-family: 'Poppins', sans-serif; font-size: 2.75rem; font-weight: 700; margin-bottom: 0.75rem; letter-spacing: -0.025em; }
23
- header p { font-size: 1.25rem; color: var(--indigo-200); font-weight: 500; }
24
- nav { background-color: var(--gray-100); border-bottom: 1px solid var(--gray-200); }
25
- nav ul { display: flex; padding-left: 3rem; }
26
- nav li { margin-right: 2.5rem; }
27
- nav a { display: block; padding: 1.25rem 0; color: var(--gray-700); font-weight: 500; transition: color 0.2s, border-bottom-color 0.2s; border-bottom: 2px solid transparent; }
28
- nav a:hover, nav a.active { color: var(--gray-900); border-bottom-color: var(--indigo-500); }
29
- nav a.active { color: var(--indigo-600); }
30
- main { padding: 3rem; }
31
- section { margin-bottom: 3rem; }
32
- section h2 { font-family: 'Poppins', sans-serif; font-size: 2rem; font-weight: 600; color: var(--gray-800); margin-bottom: 1.75rem; letter-spacing: -0.02em; }
33
- section h3 { font-family: 'Poppins', sans-serif; font-size: 1.5rem; font-weight: 500; color: var(--gray-700); margin-bottom: 1rem; letter-spacing: -0.015em; }
34
- .input-label { @apply block text-gray-700 text-sm font-semibold mb-2; }
35
- .status-box { @apply border rounded-md p-5 mb-5 bg-gray-50 border-gray-200 relative overflow-hidden; } /* Status box relative for progress bar */
36
- .error-text { @apply text-red-500 mt-2 text-sm; }
37
- .video-player-container { @apply rounded-md overflow-hidden shadow-xl relative; } /* Relative for video overlay */
38
- .video-overlay-title { position: absolute; bottom: 20px; left: 20px; color: white; font-size: 1.75rem; font-weight: 600; text-shadow: 2px 2px 4px rgba(0,0,0,0.6); } /* Video title overlay */
39
- footer { background-color: var(--gray-100); border-top: 1px solid var(--gray-200); padding: 2rem 3rem; text-center text-gray-500 text-sm; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  footer a { color: var(--gray-600); text-decoration: none; }
41
  footer a:hover { text-decoration: underline; }
42
- .tutorial-item { @apply bg-white p-5 rounded-md shadow-sm border border-gray-100 hover:shadow-md transition-shadow duration-200 cursor-pointer; }
43
- .tutorial-item h3 { @apply font-semibold text-gray-800 mb-2; }
 
44
  .tutorial-item p { @apply text-gray-600 text-sm; }
45
- .tutorial-list-section { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 2rem; }
46
- .settings-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2.5rem; }
47
- .help-section p { line-height: 1.7; margin-bottom: 1.25rem; }
 
 
 
48
 
49
- /* Radix UI Button Styling */
50
  .radix-button {
51
- @apply inline-flex items-center justify-center rounded-md px-5 py-2.5 font-semibold text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-colors duration-200;
 
52
  }
53
- .radix-button-primary { @apply radix-button bg-indigo-600 hover:bg-indigo-700 active:bg-indigo-800 text-white shadow-sm hover:shadow-md; } /* More distinct hover/active */
54
  .radix-button-primary:disabled { @apply bg-indigo-300 cursor-not-allowed hover:bg-indigo-300 focus:ring-0 shadow-none; }
55
- .radix-button-secondary { @apply radix-button bg-gray-200 hover:bg-gray-300 active:bg-gray-400 text-gray-700 shadow-sm hover:shadow-md; } /* More distinct hover/active */
56
- .radix-button-apply { @apply radix-button bg-green-500 hover:bg-green-600 active:bg-green-700 text-white shadow-sm hover:shadow-md; } /* Apply button style */
57
 
58
- /* Radix UI Input Styling */
59
  .radix-input {
60
- @apply shadow-sm appearance-none border rounded-md w-full py-2.5 px-3.5 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-shadow duration-200;
61
  border-color: var(--gray-300);
62
- background-color: var(--white);
63
  color: var(--gray-900);
 
64
  }
65
- .radix-input:focus { @apply shadow-md border-indigo-500; } /* Clearer focus effect */
66
 
67
- /* Radix UI Select Styling (Trigger only - see JS for full select in React) */
68
  .radix-select-trigger {
69
  @apply radix-button radix-button-secondary w-full justify-between;
 
 
70
  }
71
  .radix-select-content {
72
  @apply rounded-md shadow-md bg-white border border-gray-200 overflow-hidden;
@@ -76,54 +164,74 @@
76
  }
77
  .radix-select-item[data-highlighted] { @apply bg-indigo-50 text-indigo-900; }
78
 
79
- /* Progress Bar */
80
- .status-progress-bar { position: absolute; bottom: 0; left: 0; right: 0; height: 6px; background-color: var(--indigo-500); border-bottom-left-radius: 0.75rem; border-bottom-right-radius: 0.75rem; transform-origin: 0% 0%; transform: scaleX(0); transition: transform 0.4s ease-out; }
81
  .status-progress-bar.active { transform: scaleX(1); }
82
 
83
  /* Transitions */
84
  .transition-opacity { transition-property: opacity; transition-timing-function: ease-out; transition-duration: 200ms; }
85
 
86
- /* Scrollbar Styles */
87
- ::-webkit-scrollbar { width: 8px; height: 8px; }
88
- ::-webkit-scrollbar-track { background: #f1f1f1; }
89
- ::-webkit-scrollbar-thumb { background: #a8a8a8; border-radius: 4px; }
90
- ::-webkit-scrollbar-thumb:hover { background: #888; }
91
- * { scrollbar-width: thin; scrollbar-color: #a8a8a8 #f1f1f1; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
  </style>
94
  </head>
95
- <body class="bg-gray-50">
96
  <div class="app-container">
97
- <!-- Header Section -->
98
  <header>
99
- <h1 class="text-3xl">Autotutorial.ai Desktop</h1>
100
- <p class="text-lg">Video Tutorial Generator</p>
101
  </header>
102
 
103
- <!-- Navigation Bar -->
104
- <nav>
105
- <ul>
106
- <li><a href="#generate" class="nav-link active" data-section="generate">Generate Tutorial</a></li>
107
- <li><a href="#history" class="nav-link" data-section="history">Tutorial History</a></li>
108
- <li><a href="#settings" class="nav-link" data-section="settings">Settings</a></li>
109
- <li><a href="#help" class="nav-link" data-section="help">Help</a></li>
110
- </ul>
111
- </nav>
112
-
113
  <!-- Main Content Area -->
114
  <main>
115
  <!-- Generate Tutorial Section -->
116
  <section id="generate-section">
117
- <h2 class="text-2xl">Generate New Tutorial</h2>
118
- <p class="text-gray-700 mb-7">Topic and duration for your next tutorial video.</p>
119
 
120
- <div class="grid grid-cols-1 md:grid-cols-2 gap-7 mb-7">
121
  <div>
122
- <label for="tutorialTopic" class="input-label">Tutorial Topic <span class="text-gray-500">(e.g., "Vue.js Composition API")</span></label>
123
- <input type="text" id="tutorialTopic" class="radix-input" placeholder="Enter tutorial topic" value="Advanced React Context API Patterns" required>
124
  </div>
125
  <div>
126
- <label for="desiredDuration" class="input-label">Desired Duration (Minutes)</label>
127
  <select id="desiredDuration" class="radix-select-trigger">
128
  <option value="5" class="radix-select-item">5 Minutes</option>
129
  <option value="10" selected class="radix-select-item">10 Minutes</option>
@@ -133,51 +241,50 @@
133
  </div>
134
  </div>
135
 
136
- <section class="mb-7">
137
- <h3 class="text-xl font-semibold mb-4 text-gray-800">API Keys <span class="text-gray-500">(Optional, Enhanced Features)</span></h3>
138
  <div class="settings-grid">
139
  <div>
140
- <label for="openaiApiKey" class="input-label">OpenAI API Key <span class="text-gray-500">(AI Script Generation)</span></label>
141
- <input type="text" id="openaiApiKey" class="radix-input" placeholder="Enter OpenAI API Key (Optional)" value="sk-DEMO_OPENAI_KEY">
142
  </div>
143
  <div>
144
- <label for="videoGenApiKey" class="input-label">Video Generation API Key <span class="text-gray-500">(AI Video Synthesis)</span></label>
145
- <input type="text" id="videoGenApiKey" class="radix-input" placeholder="Enter Video API Key (Optional)" value="vg-DEMO_VIDEO_GEN_KEY">
146
  </div>
147
  </div>
148
- <p class="text-sm text-gray-500 mt-2">Optional API keys for advanced AI features. Basic tutorials work without them.</p>
149
  </section>
150
 
151
- <section class="mb-7 flex justify-start gap-4">
152
- <button id="generateButton" class="radix-button-primary"><i class="fas fa-magic mr-2"></i> Generate Tutorial</button>
153
  <button id="resetButton" class="radix-button-secondary hidden"><i class="fas fa-redo mr-2"></i> Reset</button>
154
  </section>
155
 
156
  <section id="statusSection" class="status-box">
157
- <h3 class="font-semibold text-gray-700 mb-3"><i class="fas fa-info-circle mr-2"></i> Status Updates</h3>
158
  <div id="statusMessages">
159
- <p class="text-gray-600"><i class="fas fa-check-circle text-green-500 mr-1"></i> Ready to generate. Click "Generate Tutorial".</p>
160
  </div>
161
  <p id="errorMessage" class="error-text hidden"></p>
162
- <div id="progressBar" class="status-progress-bar"></div> <!-- Progress Bar -->
163
  </section>
164
 
165
  <section id="videoOutputSection" class="hidden transition-opacity opacity-0 duration-200">
166
- <h2 class="text-xl font-semibold mb-4 text-gray-800"><i class="fas fa-film mr-2"></i> Tutorial Preview</h2>
167
  <div class="video-player-container">
168
  <video id="tutorialVideo" controls width="100%">
169
- <source src="https://joy.videvo.net/videvo_files/video/free/2016-06/small_watermarked/Drone_Flying_Above_City_Skyline_preview.mp4" type="video/mp4"> <!-- Tutorial-style stock video -->
170
  Your browser does not support the video tag.
171
  </video>
172
- <div id="videoTitleOverlay" class="video-overlay-title"></div> <!-- Video Title Overlay -->
173
  </div>
174
- <div class="mt-5 flex justify-between items-center">
175
  <div>
176
- <p class="text-gray-700"><strong>Tutorial Title:</strong> <span id="videoTitle"></span></p>
177
- <p class="text-gray-500 text-sm">Generated tutorial preview.</p>
178
  </div>
179
  <div>
180
- <a href="#" id="downloadButton" class="radix-button-primary" download="tutorial.mp4"><i class="fas fa-download mr-2"></i> Download Video</a>
181
  </div>
182
  </div>
183
  </section>
@@ -185,37 +292,34 @@
185
 
186
  <!-- Tutorial History Section -->
187
  <section id="history-section" class="hidden">
188
- <h2 class="text-2xl">Tutorial History</h2>
189
- <p class="text-gray-700 mb-7">Access and manage past tutorial videos.</p>
190
 
191
  <div class="tutorial-list-section">
192
  <div class="tutorial-item history-item" data-video-title="Mastering JavaScript Promises">
193
- <h3>Mastering JavaScript Promises</h3>
194
- <p>Generated: October 26, 2023</p>
195
- <p class="text-indigo-600 font-semibold">View Tutorial</p>
196
  </div>
197
  <div class="tutorial-item history-item" data-video-title="Introduction to Python for Data Science">
198
- <h3>Introduction to Python for Data Science</h3>
199
- <p>Generated: October 25, 2023</p>
200
- <p class="text-indigo-600 font-semibold">View Tutorial</p>
201
  </div>
202
  <div class="tutorial-item history-item" data-video-title="Building a REST API with Express.js">
203
- <h3>Building a REST API with Express.js</h3>
204
- <p>Generated: October 20, 2023</p>
205
- <p class="text-indigo-600 font-semibold">View Tutorial</p>
206
  </div>
207
  </div>
208
- <p class="mt-4 text-sm text-gray-500">Tutorial history is simulated for demonstration.</p>
209
  </section>
210
 
211
  <!-- Settings Section -->
212
  <section id="settings-section" class="hidden">
213
- <h2 class="text-2xl">Settings</h2>
214
- <p class="text-gray-700 mb-7">Customize your Autotutorial.ai Desktop preferences.</p>
215
 
216
  <div class="settings-grid">
217
  <div>
218
- <label for="defaultDurationSetting" class="input-label">Default Tutorial Duration</label>
219
  <select id="defaultDurationSetting" class="radix-select-trigger">
220
  <option value="5" class="radix-select-item">5 Minutes</option>
221
  <option value="10" selected class="radix-select-item">10 Minutes</option>
@@ -223,11 +327,11 @@
223
  </select>
224
  </div>
225
  <div>
226
- <label for="videoQualitySetting" class="input-label">Default Video Quality</label>
227
  <select id="videoQualitySetting" class="radix-select-trigger">
228
- <option value="720p" selected class="radix-select-item">720p (HD)</option>
229
- <option value="1080p" class="radix-select-item">1080p (Full HD)</option>
230
- <option value="4k" class="radix-select-item">4K (Ultra HD) - Premium</option>
231
  </select>
232
  </div>
233
  <div>
@@ -235,12 +339,12 @@
235
  <select id="voiceoverLanguage" class="radix-select-trigger">
236
  <option value="en-US" selected class="radix-select-item">English (US)</option>
237
  <option value="en-GB" class="radix-select-item">English (UK)</option>
238
- <option value="es-ES" class="radix-select-item">Spanish (ES)</option>
239
- <option value="fr-FR" class="radix-select-item">French (FR)</option>
240
  </select>
241
  </div>
242
  <div>
243
- <label for="outputFormat" class="input-label">Default Output Format</label>
244
  <select id="outputFormat" class="radix-select-trigger">
245
  <option value="mp4" selected class="radix-select-item">MP4 (Recommended)</option>
246
  <option value="mov" class="radix-select-item">MOV</option>
@@ -248,71 +352,87 @@
248
  </select>
249
  </div>
250
  </div>
251
- <div class="mt-5 flex justify-start">
252
- <button id="applySettingsButton" class="radix-button-apply"><i class="fas fa-check mr-2"></i> Apply Settings</button> <!-- Apply Settings Button -->
253
  </div>
254
- <p class="mt-4 text-sm text-gray-500">Basic settings for demonstration purposes only.</p>
255
  </section>
256
 
257
  <!-- Help Section -->
258
  <section id="help-section" class="hidden">
259
- <h2 class="text-2xl">Help & Support</h2>
260
- <p class="text-gray-700 mb-7">Guidance and support for Autotutorial.ai Desktop users.</p>
261
 
262
  <div class="help-section">
263
- <p>Welcome to Autotutorial.ai Desktop! Generate tutorials with ease.</p>
264
  <p><strong>Getting Started:</strong></p>
265
- <ol class="list-decimal pl-6 mb-5">
266
- <li>Go to "Generate Tutorial" via the top navigation.</li>
267
- <li>Enter your tutorial topic in the "Tutorial Topic" field.</li>
268
- <li>Select the desired tutorial duration from "Desired Duration".</li>
269
- <li>(Optional) Add API keys for enhanced AI tutorial generation.</li>
270
- <li>Click "Generate Tutorial" to begin the process.</li>
271
- <li>Monitor the "Status Updates" section for generation progress.</li>
272
- <li>Preview and download your tutorial in the "Tutorial Preview".</li>
273
  </ol>
274
- <p><strong>Tutorial History:</strong></p>
275
- <p>Access and manage your previously generated tutorials in "Tutorial History" (demo feature).</p>
276
  <p><strong>Settings:</strong></p>
277
- <p>Customize default preferences like duration, video quality, and output format in the "Settings" section (basic demo settings).</p>
278
- <p>For further assistance, contact support at <a href="mailto:[email protected]">[email protected]</a>.</p>
279
  </div>
280
  </section>
281
 
282
  </main>
283
 
284
- <!-- Footer Section -->
285
- <footer>
286
- © 2023 Autotutorial.ai Desktop. All rights reserved. | <a href="#">Terms of Service</a> | <a href="#">Privacy Policy</a> | <a href="#">Contact Us</a>
287
- </footer>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  </div>
289
 
290
  <script>
291
  document.addEventListener('DOMContentLoaded', () => {
292
- // Navigation functionality (same as before)
293
- const navLinks = document.querySelectorAll('nav a.nav-link');
294
  const sections = document.querySelectorAll('main > section');
295
 
296
- navLinks.forEach(link => {
297
- link.addEventListener('click', function(event) {
298
  event.preventDefault();
299
  const sectionId = this.getAttribute('data-section');
300
 
301
- navLinks.forEach(nl => nl.classList.remove('active'));
302
  sections.forEach(sec => sec.classList.add('hidden'));
303
 
304
  this.classList.add('active');
305
  document.getElementById(`${sectionId}-section`).classList.remove('hidden');
306
  if (sectionId === 'generate') {
307
- document.getElementById('videoOutputSection').classList.add('hidden'); // Hide video output when going back to generate
308
- document.getElementById('videoOutputSection').classList.remove('opacity-0'); // Reset opacity for next generation
309
  }
310
  });
311
  });
312
- document.querySelector('nav a.nav-link[data-section="generate"]').classList.add('active');
313
  document.getElementById('generate-section').classList.remove('hidden');
314
 
315
- // Tutorial History Item Click Simulation
316
  const historyItems = document.querySelectorAll('.history-item');
317
  const videoTitleSpan = document.getElementById('videoTitle');
318
  const videoTitleOverlay = document.getElementById('videoTitleOverlay');
@@ -323,19 +443,14 @@
323
  videoTitleSpan.textContent = title + " (Preview)";
324
  videoTitleOverlay.textContent = title;
325
  videoOutputSection.classList.remove('hidden');
326
- videoOutputSection.classList.remove('opacity-0'); // Fade in video output if hidden
327
- // Optionally, you could change the video source here if you had different demo videos
328
- // document.getElementById('tutorialVideo').src = 'url_to_different_video.mp4';
329
- // document.getElementById('tutorialVideo source').src = 'url_to_different_video.mp4';
330
- // document.getElementById('tutorialVideo').load(); // Important to reload video source
331
- // Show status message
332
  const statusMessagesDiv = document.getElementById('statusMessages');
333
- statusMessagesDiv.innerHTML = `<p class="text-gray-600"><i class="fas fa-video text-indigo-500 mr-1"></i> Loading tutorial from history: ${title}</p>`;
334
  statusMessagesDiv.scrollTop = statusMessagesDiv.scrollHeight;
335
  });
336
  });
337
 
338
- // Apply Settings Button Simulation
339
  document.getElementById('applySettingsButton').addEventListener('click', function() {
340
  const statusMessagesDiv = document.getElementById('statusMessages');
341
  statusMessagesDiv.innerHTML = `<p class="text-green-600"><i class="fas fa-check-circle text-green-500 mr-1"></i> Settings Applied.</p>`;
@@ -345,6 +460,7 @@
345
 
346
 
347
  document.getElementById('generateButton').addEventListener('click', function() {
 
348
  const topic = document.getElementById('tutorialTopic').value;
349
  const duration = document.getElementById('desiredDuration').value;
350
  const openaiKey = document.getElementById('openaiApiKey').value;
@@ -363,60 +479,59 @@
363
  statusMessagesDiv.innerHTML = '';
364
  errorMessageDiv.classList.add('hidden');
365
  videoOutputSection.classList.add('hidden');
366
- videoOutputSection.classList.remove('opacity-0'); // Reset opacity for next generation
367
  resetButton.classList.add('hidden');
368
  generateButton.disabled = true;
369
  statusSection.querySelector('h3 i').classList.remove('fa-check-circle', 'text-green-500', 'fa-times-circle', 'text-red-500');
370
  statusSection.querySelector('h3 i').classList.add('fa-spinner', 'fa-spin', 'mr-2');
371
- statusSection.querySelector('h3').innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Status Updates';
372
- progressBar.style.transform = 'scaleX(0)'; // Reset progress bar
373
- progressBar.classList.add('active'); // Start progress bar animation
374
 
375
 
376
  const steps = [
377
- { message: "Analyzing Tutorial Topic...", delay: 800 },
378
- { message: "Generating Script Outline (AI)...", delay: 1500 },
379
- { message: "Writing Script Content (AI)...", delay: 2200 },
380
- { message: "Synthesizing Voiceover (AI)...", delay: 2000 },
381
- { message: "Selecting Relevant Visuals...", delay: 1800 },
382
- { message: "Assembling Video Scenes...", delay: 2500 },
383
- { message: "Adding Transitions and Music...", delay: 1500 },
384
- { message: "Rendering Final Video...", delay: 3000 }
385
  ];
386
 
387
  let currentStepIndex = 0;
388
  function processStep() {
389
  if (currentStepIndex < steps.length) {
390
  simulateStep(statusMessagesDiv, steps[currentStepIndex].message, steps[currentStepIndex].delay, () => {
391
- progressBar.style.transform = `scaleX(${((currentStepIndex + 1) / steps.length)})`; // Update progress bar
392
  currentStepIndex++;
393
  processStep();
394
  }, true);
395
  } else {
396
- // Simulate success - after all steps
397
- progressBar.classList.remove('active'); // Stop progress bar animation
398
- statusMessagesDiv.innerHTML = '<p class="text-green-600"><i class="fas fa-check-circle text-green-500 mr-1"></i> Tutorial generation complete!</p>';
399
  statusSection.querySelector('h3 i').classList.remove('fa-spinner', 'fa-spin', 'mr-2');
400
  statusSection.querySelector('h3 i').classList.add('fa-check-circle', 'text-green-500', 'mr-2');
401
- statusSection.querySelector('h3').innerHTML = '<i class="fas fa-check-circle text-green-500 mr-2"></i> Status Updates';
402
 
403
- videoTitleSpan.textContent = topic + " in " + duration + " Minutes (Preview)";
404
- videoTitleOverlay.textContent = topic + " - " + duration + " Minute Tutorial"; // Set video overlay title
405
  videoOutputSection.classList.remove('hidden');
406
- setTimeout(() => videoOutputSection.classList.remove('opacity-0'), 50); // Fade in video output
407
  generateButton.disabled = false;
408
  generateButton.classList.add('hidden');
409
  resetButton.classList.remove('hidden');
410
  }
411
  }
412
- processStep(); // Start the step processing
413
 
414
 
415
  });
416
 
417
  document.getElementById('resetButton').addEventListener('click', function() {
418
  // ... (same resetButton event listener logic as before) ...
419
- const statusMessagesDiv = document.getElementById('statusMessages');
420
  const errorMessageDiv = document.getElementById('errorMessage');
421
  const generateButton = document.getElementById('generateButton');
422
  const resetButton = document.getElementById('resetButton');
@@ -424,18 +539,18 @@
424
  const videoOutputSection = document.getElementById('videoOutputSection');
425
  const progressBar = document.getElementById('progressBar');
426
 
427
- statusMessagesDiv.innerHTML = '<p class="text-gray-600"><i class="fas fa-check-circle text-green-500 mr-1"></i> Ready to generate tutorial. Please click "Generate Tutorial".</p>';
428
  errorMessageDiv.classList.add('hidden');
429
  videoOutputSection.classList.add('hidden');
430
- videoOutputSection.classList.remove('opacity-0'); // Reset opacity for next generation
431
  generateButton.disabled = false;
432
  generateButton.classList.remove('hidden');
433
  resetButton.classList.add('hidden');
434
  statusSection.querySelector('h3 i').classList.remove('fa-times-circle', 'text-red-500', 'fa-spinner', 'fa-spin', 'mr-2');
435
  statusSection.querySelector('h3 i').classList.add('fa-check-circle', 'text-green-500', 'mr-2');
436
- statusSection.querySelector('h3').innerHTML = '<i class="fas fa-check-circle text-green-500 mr-2"></i> Status Updates';
437
- progressBar.classList.remove('active'); // Stop progress bar animation if running
438
- progressBar.style.transform = 'scaleX(0)'; // Reset progress bar
439
 
440
  });
441
 
@@ -445,24 +560,24 @@
445
  const messageElement = document.createElement('p');
446
  if (isSuccess) {
447
  messageElement.classList.add('text-gray-600');
448
- messageElement.innerHTML = `<i class="fas fa-spinner fa-pulse text-indigo-500 mr-1"></i> ${message}`; // Use spinner for ongoing steps
449
  } else {
450
  messageElement.classList.add('text-red-500');
451
  messageElement.innerHTML = `<i class="fas fa-times-circle text-red-500 mr-1"></i> ${message}`;
452
- document.getElementById('errorMessage').textContent = "Error during tutorial generation. Please check API keys and try again.";
453
  document.getElementById('errorMessage').classList.remove('hidden');
454
  document.getElementById('statusSection').querySelector('h3 i').classList.remove('fa-spinner', 'fa-spin', 'mr-2');
455
  document.getElementById('statusSection').querySelector('h3 i').classList.add('fa-times-circle', 'text-red-500', 'mr-2');
456
- document.getElementById('statusSection').querySelector('h3').innerHTML = '<i class="fas fa-times-circle text-red-500 mr-2"></i> Status Updates';
457
  document.getElementById('generateButton').disabled = false;
458
  document.getElementById('generateButton').classList.add('hidden');
459
  document.getElementById('resetButton').classList.remove('hidden');
460
- document.getElementById('progressBar').classList.remove('active'); // Stop progress bar on error
461
  }
462
  statusDiv.appendChild(messageElement);
463
  statusDiv.scrollTop = statusDiv.scrollHeight;
464
  if (callback) callback();
465
- }, delay + Math.random() * 500); // Add slight random delay variation
466
  }
467
  </script>
468
 
 
2
  <html lang="en">
3
  <head>
4
  <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"> <!-- iOS viewport settings -->
6
+ <title>Autotutorial.ai - iOS Demo</title> <!-- iOS Style Title -->
7
+ <link rel="manifest" href="manifest.json"> <!-- PWA manifest (placeholder - create manifest.json for full PWA) -->
8
+ <meta name="apple-mobile-web-app-capable" content="yes"> <!-- iOS PWA meta -->
9
+ <meta name="apple-mobile-web-app-status-bar-style" content="default"> <!-- iOS status bar style -->
10
  <!-- Radix UI Styles -->
11
  <link rel="stylesheet" href="https://unpkg.com/@radix-ui/[email protected]/dist/index.css">
12
  <!-- Tailwind CSS CDN -->
13
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
14
  <!-- Font Awesome CDN -->
15
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" integrity="sha512-9usAa10IRO0HhonpyAIVpjrylPvoDwiPUiKdWk5t3PyolY1cOd4DSE0Ga+ri4AuTroPR5aQvXU9xC6qOPnzFeg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
16
+ <!-- Inter & SF Pro Display Fonts (SF Pro Display approximation) -->
17
  <link rel="preconnect" href="https://fonts.googleapis.com">
18
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
19
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=SF+Pro+Display:wght@400;500;600;700&display=swap" rel="stylesheet"> <!-- SF Pro Display approximation -->
20
+
21
  <style>
22
+ /* iOS App Reset and Base Styles */
23
+ body {
24
+ font-family: 'Inter', sans-serif; /* Default to Inter, fallback if SF Pro Display doesn't load perfectly */
25
+ -webkit-font-smoothing: antialiased;
26
+ -moz-osx-font-smoothing: grayscale;
27
+ background-color: var(--gray-100); /* Lighter iOS-like background */
28
+ color: var(--gray-900);
29
+ margin: 0; /* Reset margins */
30
+ padding-bottom: 50px; /* Padding for bottom tab bar */
31
+ }
32
+
33
+ /* Use SF Pro Display if available, for headings and key UI text - approximation */
34
+ @font-face {
35
+ font-family: 'SF Pro Display'; /* Name to use in CSS */
36
+ src: url('https://cdn.jsdelivr.net/gh/fontsource/fontsource-sf-pro-display@latest/files/sf-pro-display-latin-400-normal.woff2') format('woff2'), /* Example CDN - consider hosting or local */
37
+ url('https://cdn.jsdelivr.net/gh/fontsource/fontsource-sf-pro-display@latest/files/sf-pro-display-latin-400-normal.woff') format('woff');
38
+ /* Add other weights as needed */
39
+ font-weight: 400;
40
+ font-style: normal;
41
+ font-display: swap; /* or optional */
42
+ }
43
+
44
+ h1, h2, h3, h4, h5, h6, .ios-title-font { font-family: 'SF Pro Display', sans-serif; } /* Apply to titles and key text */
45
+
46
+
47
+ .app-container {
48
+ max-width: 768px; /* Mobile-first max width */
49
+ margin: 0 auto; /* Center on larger screens */
50
+ background-color: var(--gray-50); /* Even lighter background, closer to iOS */
51
+ border-radius: 0px; /* No border radius for full-screen app feel */
52
+ overflow: hidden;
53
+ box-shadow: none; /* Remove shadow for flatter iOS style */
54
+ min-height: 100vh; /* Full viewport height */
55
+ display: flex;
56
+ flex-direction: column; /* Vertical flex layout */
57
+ }
58
+
59
+ header {
60
+ background-color: var(--gray-50); /* White header background */
61
+ padding: 2rem 1.5rem 1rem 1.5rem; /* Adjusted header padding - less top, more bottom */
62
+ color: var(--gray-900);
63
+ border-bottom: 1px solid var(--gray-200); /* iOS-style separator */
64
+ }
65
+
66
+ header h1 {
67
+ font-size: 2.25rem; /* Large iOS title size */
68
+ font-weight: 700;
69
+ letter-spacing: -0.02em;
70
+ margin-bottom: 0.25rem; /* Reduced bottom margin */
71
+ text-align: left; /* Left-align iOS style */
72
+ }
73
+
74
+ header p {
75
+ font-size: 1.1rem; /* Slightly smaller subtitle */
76
+ color: var(--gray-600); /* Muted subtitle color */
77
+ font-weight: 400;
78
+ }
79
+
80
+ main {
81
+ padding: 1.5rem; /* Reduced main padding for mobile */
82
+ flex-grow: 1; /* Main content takes up remaining space */
83
+ }
84
+
85
+ section {
86
+ margin-bottom: 2rem; /* Reduced section margin */
87
+ }
88
+
89
+ section h2 {
90
+ font-size: 1.7rem; /* Section title size */
91
+ font-weight: 600;
92
+ color: var(--gray-800);
93
+ margin-bottom: 1.25rem; /* Reduced section title margin */
94
+ letter-spacing: -0.015em;
95
+ text-align: left; /* Left-align section titles */
96
+ }
97
+
98
+ section h3 {
99
+ font-size: 1.3rem; /* Subtitle size */
100
+ font-weight: 500;
101
+ color: var(--gray-700);
102
+ margin-bottom: 0.8rem; /* Reduced subtitle margin */
103
+ letter-spacing: -0.01em;
104
+ text-align: left; /* Left-align subtitles */
105
+ }
106
+
107
+ .input-label { @apply block text-gray-700 text-sm font-semibold mb-1; } /* Smaller label margin */
108
+ .status-box { @apply border rounded-md p-4 mb-3 bg-gray-50 border-gray-200 relative overflow-hidden; } /* Reduced status box margin */
109
+ .error-text { @apply text-red-500 mt-1 text-sm; } /* Smaller error text margin */
110
+ .video-player-container { @apply rounded-md overflow-hidden shadow-md; } /* Keep shadow for video player */
111
+ .video-overlay-title { position: absolute; bottom: 15px; left: 15px; color: white; font-size: 1.5rem; font-weight: 600; text-shadow: 1px 1px 2px rgba(0,0,0,0.6); } /* Smaller video overlay title */
112
+
113
+ footer {
114
+ background-color: var(--gray-50); /* White footer */
115
+ border-top: 1px solid var(--gray-200); /* iOS footer separator */
116
+ padding: 1.25rem 1.5rem; /* Reduced footer padding */
117
+ text-center text-gray-500 text-sm;
118
+ }
119
+
120
  footer a { color: var(--gray-600); text-decoration: none; }
121
  footer a:hover { text-decoration: underline; }
122
+
123
+ .tutorial-item { @apply bg-white p-3.5 rounded-md shadow-sm border border-gray-100 hover:shadow-md transition-shadow duration-200 cursor-pointer mb-2; } /* Reduced tutorial item padding and margin */
124
+ .tutorial-item h3 { @apply font-semibold text-gray-800 mb-1; font-size: 1.1rem; } /* Smaller tutorial item title */
125
  .tutorial-item p { @apply text-gray-600 text-sm; }
126
+ .tutorial-list-section { display: flex; flex-direction: column; gap: 0.75rem; } /* Vertical tutorial list */
127
+ .settings-grid { display: grid; grid-template-columns: 1fr; gap: 1.75rem; } /* Single column settings on mobile */
128
+ @media (min-width: 768px) { /* Medium screens and up */
129
+ .settings-grid { grid-template-columns: 1fr 1fr; } /* Two-column settings on larger screens */
130
+ }
131
+ .help-section p { line-height: 1.6; margin-bottom: 1rem; }
132
 
133
+ /* Radix UI Button Styling - iOS Style Refinements */
134
  .radix-button {
135
+ @apply inline-flex items-center justify-center rounded-md px-4 py-2 font-semibold text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-colors duration-200; /* Reduced button padding */
136
+ -webkit-tap-highlight-color: transparent; /* Remove tap highlight on iOS */
137
  }
138
+ .radix-button-primary { @apply radix-button bg-indigo-600 hover:bg-indigo-700 active:bg-indigo-800 text-white shadow-sm hover:shadow-md; }
139
  .radix-button-primary:disabled { @apply bg-indigo-300 cursor-not-allowed hover:bg-indigo-300 focus:ring-0 shadow-none; }
140
+ .radix-button-secondary { @apply radix-button bg-gray-200 hover:bg-gray-300 active:bg-gray-400 text-gray-700 shadow-sm hover:shadow-md; }
141
+ .radix-button-apply { @apply radix-button bg-green-500 hover:bg-green-600 active:bg-green-700 text-white shadow-sm hover:shadow-md; }
142
 
143
+ /* Radix UI Input Styling - iOS Style Refinements */
144
  .radix-input {
145
+ @apply appearance-none border rounded-md w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-shadow duration-200; /* Reduced input padding */
146
  border-color: var(--gray-300);
147
+ background-color: var(--gray-50); /* Light gray input background */
148
  color: var(--gray-900);
149
+ box-shadow: inset 0 0 0 1px var(--gray-300); /* iOS-like border shadow */
150
  }
151
+ .radix-input:focus { @apply shadow-none border-indigo-500; box-shadow: inset 0 0 0 2px var(--indigo-500); } /* iOS-like focus */
152
 
153
+ /* Radix UI Select Styling - iOS Style - Needs more JS for true iOS Picker */
154
  .radix-select-trigger {
155
  @apply radix-button radix-button-secondary w-full justify-between;
156
+ border-radius: 8px; /* More rounded select */
157
+ padding-left: 1rem; padding-right: 1rem; /* Adjust select padding */
158
  }
159
  .radix-select-content {
160
  @apply rounded-md shadow-md bg-white border border-gray-200 overflow-hidden;
 
164
  }
165
  .radix-select-item[data-highlighted] { @apply bg-indigo-50 text-indigo-900; }
166
 
167
+ /* Progress Bar - iOS Style - Thinner */
168
+ .status-progress-bar { position: absolute; bottom: 0; left: 0; right: 0; height: 3px; background-color: var(--indigo-500); transform-origin: 0% 0%; transform: scaleX(0); transition: transform 0.4s ease-out; }
169
  .status-progress-bar.active { transform: scaleX(1); }
170
 
171
  /* Transitions */
172
  .transition-opacity { transition-property: opacity; transition-timing-function: ease-out; transition-duration: 200ms; }
173
 
174
+ /* Bottom Tab Bar Navigation - iOS Style */
175
+ .bottom-tab-bar {
176
+ position: fixed; bottom: 0; left: 0; right: 0;
177
+ background-color: var(--gray-50); /* White tab bar background */
178
+ border-top: 1px solid var(--gray-200); /* iOS tab bar border */
179
+ padding-top: 0.5rem; padding-bottom: calc(env(safe-area-inset-bottom) + 0.5rem); /* Safe area padding for iOS */
180
+ display: flex; justify-content: space-around;
181
+ z-index: 100; /* Ensure it's on top */
182
+ }
183
+
184
+ .bottom-tab-button {
185
+ display: flex; flex-direction: column; align-items: center;
186
+ color: var(--gray-500); /* Inactive tab color */
187
+ text-decoration: none;
188
+ font-size: 0.85rem; /* Smaller tab label */
189
+ padding: 0.5rem 1rem; border-radius: 8px; /* Tab button padding and rounded corners */
190
+ -webkit-tap-highlight-color: transparent; /* Remove tap highlight on iOS */
191
+ }
192
+
193
+ .bottom-tab-button.active, .bottom-tab-button:active, .bottom-tab-button:hover {
194
+ color: var(--indigo-600); /* Active/tapped tab color */
195
+ background-color: var(--gray-100); /* Slightly highlight active tab */
196
+ }
197
+
198
+ .bottom-tab-icon {
199
+ font-size: 1.3rem; /* Tab icon size */
200
+ margin-bottom: 0.25rem;
201
+ }
202
+
203
+ /* Scrollbar - minimal for mobile */
204
+ ::-webkit-scrollbar { width: 4px; height: 4px; }
205
+ ::-webkit-scrollbar-track { background: transparent; } /* Transparent track */
206
+ ::-webkit-scrollbar-thumb { background: var(--gray-400); border-radius: 2px; } /* Thinner, lighter thumb */
207
+ ::-webkit-scrollbar-thumb:hover { background: var(--gray-500); }
208
+ * { scrollbar-width: thin; scrollbar-color: var(--gray-400) transparent; } /* Firefox scrollbar */
209
+
210
 
211
  </style>
212
  </head>
213
+ <body class="bg-gray-100"> <!-- Body background for overscroll effect -->
214
  <div class="app-container">
215
+ <!-- Header Section (iOS Style - Large Title) -->
216
  <header>
217
+ <h1 class="ios-title-font">Autotutorial.ai</h1>
218
+ <p>Generate Video Tutorials</p>
219
  </header>
220
 
 
 
 
 
 
 
 
 
 
 
221
  <!-- Main Content Area -->
222
  <main>
223
  <!-- Generate Tutorial Section -->
224
  <section id="generate-section">
225
+ <h2 class="text-xl">New Tutorial</h2>
226
+ <p class="text-gray-700 mb-6">Set topic and duration to begin.</p>
227
 
228
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-5 mb-5">
229
  <div>
230
+ <label for="tutorialTopic" class="input-label">Topic <span class="text-gray-500">(e.g., "React Forms")</span></label>
231
+ <input type="text" id="tutorialTopic" class="radix-input" placeholder="Enter topic" value="Vue.js Teleport Feature" required>
232
  </div>
233
  <div>
234
+ <label for="desiredDuration" class="input-label">Duration (Minutes)</label>
235
  <select id="desiredDuration" class="radix-select-trigger">
236
  <option value="5" class="radix-select-item">5 Minutes</option>
237
  <option value="10" selected class="radix-select-item">10 Minutes</option>
 
241
  </div>
242
  </div>
243
 
244
+ <section class="mb-5">
245
+ <h3 class="text-lg font-semibold mb-3 text-gray-800">API Keys <span class="text-gray-500">(Optional)</span></h3>
246
  <div class="settings-grid">
247
  <div>
248
+ <label for="openaiApiKey" class="input-label">OpenAI Key <span class="text-gray-500">(Script AI)</span></label>
249
+ <input type="text" id="openaiApiKey" class="radix-input" placeholder="OpenAI API Key (Optional)" value="sk-DEMO_OPENAI_KEY">
250
  </div>
251
  <div>
252
+ <label for="videoGenApiKey" class="input-label">Video Key <span class="text-gray-500">(Video AI)</span></label>
253
+ <input type="text" id="videoGenApiKey" class="radix-input" placeholder="Video API Key (Optional)" value="vg-DEMO_VIDEO_GEN_KEY">
254
  </div>
255
  </div>
256
+ <p class="text-sm text-gray-500 mt-2">For enhanced AI features.</p>
257
  </section>
258
 
259
+ <section class="mb-5 flex justify-start gap-3">
260
+ <button id="generateButton" class="radix-button-primary"><i class="fas fa-magic mr-2"></i> Generate</button>
261
  <button id="resetButton" class="radix-button-secondary hidden"><i class="fas fa-redo mr-2"></i> Reset</button>
262
  </section>
263
 
264
  <section id="statusSection" class="status-box">
265
+ <h3 class="font-semibold text-gray-700 mb-2"><i class="fas fa-info-circle mr-2"></i> Status</h3>
266
  <div id="statusMessages">
267
+ <p class="text-gray-600"><i class="fas fa-check-circle text-green-500 mr-1"></i> Ready. Tap "Generate".</p>
268
  </div>
269
  <p id="errorMessage" class="error-text hidden"></p>
270
+ <div id="progressBar" class="status-progress-bar"></div>
271
  </section>
272
 
273
  <section id="videoOutputSection" class="hidden transition-opacity opacity-0 duration-200">
274
+ <h2 class="text-lg font-semibold mb-3 text-gray-800"><i class="fas fa-film mr-2"></i> Preview</h2>
275
  <div class="video-player-container">
276
  <video id="tutorialVideo" controls width="100%">
277
+ <source src="https://joy.videvo.net/videvo_files/video/free/2016-06/small_watermarked/Drone_Flying_Above_City_Skyline_preview.mp4" type="video/mp4">
278
  Your browser does not support the video tag.
279
  </video>
280
+ <div id="videoTitleOverlay" class="video-overlay-title"></div>
281
  </div>
282
+ <div class="mt-3 flex justify-between items-center">
283
  <div>
284
+ <p class="text-gray-700 text-sm"><strong>Title:</strong> <span id="videoTitle"></span></p>
 
285
  </div>
286
  <div>
287
+ <a href="#" id="downloadButton" class="radix-button-primary" download="tutorial.mp4"><i class="fas fa-download mr-2"></i> Download</a>
288
  </div>
289
  </div>
290
  </section>
 
292
 
293
  <!-- Tutorial History Section -->
294
  <section id="history-section" class="hidden">
295
+ <h2 class="text-xl">History</h2>
296
+ <p class="text-gray-700 mb-6">Past tutorials.</p>
297
 
298
  <div class="tutorial-list-section">
299
  <div class="tutorial-item history-item" data-video-title="Mastering JavaScript Promises">
300
+ <h3>JavaScript Promises</h3>
301
+ <p>Oct 26, 2023</p>
 
302
  </div>
303
  <div class="tutorial-item history-item" data-video-title="Introduction to Python for Data Science">
304
+ <h3>Python for Data Science</h3>
305
+ <p>Oct 25, 2023</p>
 
306
  </div>
307
  <div class="tutorial-item history-item" data-video-title="Building a REST API with Express.js">
308
+ <h3>REST API with Express.js</h3>
309
+ <p>Oct 20, 2023</p>
 
310
  </div>
311
  </div>
312
+ <p class="mt-3 text-sm text-gray-500">Demo history.</p>
313
  </section>
314
 
315
  <!-- Settings Section -->
316
  <section id="settings-section" class="hidden">
317
+ <h2 class="text-xl">Settings</h2>
318
+ <p class="text-gray-700 mb-6">App preferences.</p>
319
 
320
  <div class="settings-grid">
321
  <div>
322
+ <label for="defaultDurationSetting" class="input-label">Default Duration</label>
323
  <select id="defaultDurationSetting" class="radix-select-trigger">
324
  <option value="5" class="radix-select-item">5 Minutes</option>
325
  <option value="10" selected class="radix-select-item">10 Minutes</option>
 
327
  </select>
328
  </div>
329
  <div>
330
+ <label for="videoQualitySetting" class="input-label">Video Quality</label>
331
  <select id="videoQualitySetting" class="radix-select-trigger">
332
+ <option value="720p" selected class="radix-select-item">720p HD</option>
333
+ <option value="1080p" class="radix-select-item">1080p Full HD</option>
334
+ <option value="4k" class="radix-select-item">4K Ultra HD (Premium)</option>
335
  </select>
336
  </div>
337
  <div>
 
339
  <select id="voiceoverLanguage" class="radix-select-trigger">
340
  <option value="en-US" selected class="radix-select-item">English (US)</option>
341
  <option value="en-GB" class="radix-select-item">English (UK)</option>
342
+ <option value="es-ES" class="radix-select-item">Spanish</option>
343
+ <option value="fr-FR" class="radix-select-item">French</option>
344
  </select>
345
  </div>
346
  <div>
347
+ <label for="outputFormat" class="input-label">Output Format</label>
348
  <select id="outputFormat" class="radix-select-trigger">
349
  <option value="mp4" selected class="radix-select-item">MP4 (Recommended)</option>
350
  <option value="mov" class="radix-select-item">MOV</option>
 
352
  </select>
353
  </div>
354
  </div>
355
+ <div class="mt-4 flex justify-start">
356
+ <button id="applySettingsButton" class="radix-button-apply"><i class="fas fa-check mr-2"></i> Apply</button>
357
  </div>
358
+ <p class="mt-3 text-sm text-gray-500">Demo settings.</p>
359
  </section>
360
 
361
  <!-- Help Section -->
362
  <section id="help-section" class="hidden">
363
+ <h2 class="text-xl">Help</h2>
364
+ <p class="text-gray-700 mb-6">App guidance.</p>
365
 
366
  <div class="help-section">
367
+ <p>Welcome to Autotutorial.ai! Generate videos easily.</p>
368
  <p><strong>Getting Started:</strong></p>
369
+ <ol class="list-decimal pl-5 mb-4">
370
+ <li>Go to "Generate" tab.</li>
371
+ <li>Enter tutorial topic.</li>
372
+ <li>Select duration.</li>
373
+ <li>(Optional) Add API keys.</li>
374
+ <li>Tap "Generate".</li>
375
+ <li>See "Status" for progress.</li>
376
+ <li>Preview in "Preview" section.</li>
377
  </ol>
378
+ <p><strong>History:</strong></p>
379
+ <p>Access past tutorials in "History" (demo).</p>
380
  <p><strong>Settings:</strong></p>
381
+ <p>Customize preferences in "Settings" (demo).</p>
382
+ <p>For support, contact <a href="mailto:[email protected]">[email protected]</a>.</p>
383
  </div>
384
  </section>
385
 
386
  </main>
387
 
388
+ <!-- Bottom Tab Bar Navigation -->
389
+ <nav class="bottom-tab-bar">
390
+ <a href="#generate" class="bottom-tab-button active" data-section="generate">
391
+ <i class="fas fa-magic bottom-tab-icon"></i>
392
+ Generate
393
+ </a>
394
+ <a href="#history" class="bottom-tab-button" data-section="history">
395
+ <i class="fas fa-history bottom-tab-icon"></i>
396
+ History
397
+ </a>
398
+ <a href="#settings" class="bottom-tab-button" data-section="settings">
399
+ <i class="fas fa-cog bottom-tab-icon"></i>
400
+ Settings
401
+ </a>
402
+ <a href="#help" class="bottom-tab-button" data-section="help">
403
+ <i class="fas fa-question-circle bottom-tab-icon"></i>
404
+ Help
405
+ </a>
406
+ </nav>
407
+
408
  </div>
409
 
410
  <script>
411
  document.addEventListener('DOMContentLoaded', () => {
412
+ // Bottom Tab Navigation functionality
413
+ const tabButtons = document.querySelectorAll('.bottom-tab-button');
414
  const sections = document.querySelectorAll('main > section');
415
 
416
+ tabButtons.forEach(button => {
417
+ button.addEventListener('click', function(event) {
418
  event.preventDefault();
419
  const sectionId = this.getAttribute('data-section');
420
 
421
+ tabButtons.forEach(btn => btn.classList.remove('active'));
422
  sections.forEach(sec => sec.classList.add('hidden'));
423
 
424
  this.classList.add('active');
425
  document.getElementById(`${sectionId}-section`).classList.remove('hidden');
426
  if (sectionId === 'generate') {
427
+ document.getElementById('videoOutputSection').classList.add('hidden');
428
+ document.getElementById('videoOutputSection').classList.remove('opacity-0');
429
  }
430
  });
431
  });
432
+ document.querySelector('.bottom-tab-button[data-section="generate"]').classList.add('active');
433
  document.getElementById('generate-section').classList.remove('hidden');
434
 
435
+ // Tutorial History Item Click Simulation (same as before)
436
  const historyItems = document.querySelectorAll('.history-item');
437
  const videoTitleSpan = document.getElementById('videoTitle');
438
  const videoTitleOverlay = document.getElementById('videoTitleOverlay');
 
443
  videoTitleSpan.textContent = title + " (Preview)";
444
  videoTitleOverlay.textContent = title;
445
  videoOutputSection.classList.remove('hidden');
446
+ videoOutputSection.classList.remove('opacity-0');
 
 
 
 
 
447
  const statusMessagesDiv = document.getElementById('statusMessages');
448
+ statusMessagesDiv.innerHTML = `<p class="text-gray-600"><i class="fas fa-video text-indigo-500 mr-1"></i> Loading: ${title}</p>`;
449
  statusMessagesDiv.scrollTop = statusMessagesDiv.scrollHeight;
450
  });
451
  });
452
 
453
+ // Apply Settings Button Simulation (same as before)
454
  document.getElementById('applySettingsButton').addEventListener('click', function() {
455
  const statusMessagesDiv = document.getElementById('statusMessages');
456
  statusMessagesDiv.innerHTML = `<p class="text-green-600"><i class="fas fa-check-circle text-green-500 mr-1"></i> Settings Applied.</p>`;
 
460
 
461
 
462
  document.getElementById('generateButton').addEventListener('click', function() {
463
+ // ... (same generateButton event listener logic as before) ...
464
  const topic = document.getElementById('tutorialTopic').value;
465
  const duration = document.getElementById('desiredDuration').value;
466
  const openaiKey = document.getElementById('openaiApiKey').value;
 
479
  statusMessagesDiv.innerHTML = '';
480
  errorMessageDiv.classList.add('hidden');
481
  videoOutputSection.classList.add('hidden');
482
+ videoOutputSection.classList.remove('opacity-0');
483
  resetButton.classList.add('hidden');
484
  generateButton.disabled = true;
485
  statusSection.querySelector('h3 i').classList.remove('fa-check-circle', 'text-green-500', 'fa-times-circle', 'text-red-500');
486
  statusSection.querySelector('h3 i').classList.add('fa-spinner', 'fa-spin', 'mr-2');
487
+ statusSection.querySelector('h3').innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Status';
488
+ progressBar.style.transform = 'scaleX(0)';
489
+ progressBar.classList.add('active');
490
 
491
 
492
  const steps = [
493
+ { message: "Analyzing Topic...", delay: 800 },
494
+ { message: "Generating Script...", delay: 1500 },
495
+ { message: "Creating Voiceover...", delay: 2200 },
496
+ { message: "Synthesizing Scenes...", delay: 2000 },
497
+ { message: "Selecting Visuals...", delay: 1800 },
498
+ { message: "Assembling Video...", delay: 2500 },
499
+ { message: "Adding Effects...", delay: 1500 },
500
+ { message: "Rendering Video...", delay: 3000 }
501
  ];
502
 
503
  let currentStepIndex = 0;
504
  function processStep() {
505
  if (currentStepIndex < steps.length) {
506
  simulateStep(statusMessagesDiv, steps[currentStepIndex].message, steps[currentStepIndex].delay, () => {
507
+ progressBar.style.transform = `scaleX(${((currentStepIndex + 1) / steps.length)})`;
508
  currentStepIndex++;
509
  processStep();
510
  }, true);
511
  } else {
512
+ progressBar.classList.remove('active');
513
+ statusMessagesDiv.innerHTML = '<p class="text-green-600"><i class="fas fa-check-circle text-green-500 mr-1"></i> Generation Complete!</p>';
 
514
  statusSection.querySelector('h3 i').classList.remove('fa-spinner', 'fa-spin', 'mr-2');
515
  statusSection.querySelector('h3 i').classList.add('fa-check-circle', 'text-green-500', 'mr-2');
516
+ statusSection.querySelector('h3').innerHTML = '<i class="fas fa-check-circle text-green-500 mr-2"></i> Status';
517
 
518
+ videoTitleSpan.textContent = topic + " (" + duration + "min Preview)";
519
+ videoTitleOverlay.textContent = topic;
520
  videoOutputSection.classList.remove('hidden');
521
+ setTimeout(() => videoOutputSection.classList.remove('opacity-0'), 50);
522
  generateButton.disabled = false;
523
  generateButton.classList.add('hidden');
524
  resetButton.classList.remove('hidden');
525
  }
526
  }
527
+ processStep();
528
 
529
 
530
  });
531
 
532
  document.getElementById('resetButton').addEventListener('click', function() {
533
  // ... (same resetButton event listener logic as before) ...
534
+ const statusMessagesDiv = document.getElementById('statusMessages');
535
  const errorMessageDiv = document.getElementById('errorMessage');
536
  const generateButton = document.getElementById('generateButton');
537
  const resetButton = document.getElementById('resetButton');
 
539
  const videoOutputSection = document.getElementById('videoOutputSection');
540
  const progressBar = document.getElementById('progressBar');
541
 
542
+ statusMessagesDiv.innerHTML = '<p class="text-gray-600"><i class="fas fa-check-circle text-green-500 mr-1"></i> Ready. Tap "Generate".</p>';
543
  errorMessageDiv.classList.add('hidden');
544
  videoOutputSection.classList.add('hidden');
545
+ videoOutputSection.classList.remove('opacity-0');
546
  generateButton.disabled = false;
547
  generateButton.classList.remove('hidden');
548
  resetButton.classList.add('hidden');
549
  statusSection.querySelector('h3 i').classList.remove('fa-times-circle', 'text-red-500', 'fa-spinner', 'fa-spin', 'mr-2');
550
  statusSection.querySelector('h3 i').classList.add('fa-check-circle', 'text-green-500', 'mr-2');
551
+ statusSection.querySelector('h3').innerHTML = '<i class="fas fa-check-circle text-green-500 mr-2"></i> Status';
552
+ progressBar.classList.remove('active');
553
+ progressBar.style.transform = 'scaleX(0)';
554
 
555
  });
556
 
 
560
  const messageElement = document.createElement('p');
561
  if (isSuccess) {
562
  messageElement.classList.add('text-gray-600');
563
+ messageElement.innerHTML = `<i class="fas fa-spinner fa-pulse text-indigo-500 mr-1"></i> ${message}`;
564
  } else {
565
  messageElement.classList.add('text-red-500');
566
  messageElement.innerHTML = `<i class="fas fa-times-circle text-red-500 mr-1"></i> ${message}`;
567
+ document.getElementById('errorMessage').textContent = "Error generating tutorial. Check API keys.";
568
  document.getElementById('errorMessage').classList.remove('hidden');
569
  document.getElementById('statusSection').querySelector('h3 i').classList.remove('fa-spinner', 'fa-spin', 'mr-2');
570
  document.getElementById('statusSection').querySelector('h3 i').classList.add('fa-times-circle', 'text-red-500', 'mr-2');
571
+ document.getElementById('statusSection').querySelector('h3').innerHTML = '<i class="fas fa-times-circle text-red-500 mr-2"></i> Status';
572
  document.getElementById('generateButton').disabled = false;
573
  document.getElementById('generateButton').classList.add('hidden');
574
  document.getElementById('resetButton').classList.remove('hidden');
575
+ document.getElementById('progressBar').classList.remove('active');
576
  }
577
  statusDiv.appendChild(messageElement);
578
  statusDiv.scrollTop = statusDiv.scrollHeight;
579
  if (callback) callback();
580
+ }, delay + Math.random() * 500);
581
  }
582
  </script>
583