Moustached commited on
Commit
0d3e698
·
verified ·
1 Parent(s): 5bb152c

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +750 -19
index.html CHANGED
@@ -1,19 +1,750 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </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>Z-Image Turbo | Transform Ideas into Visuals</title>
7
+
8
+ <!-- Google Fonts -->
9
+ <link rel="preconnect" href="https://fonts.googleapis.com">
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;700&family=Space+Grotesk:wght@300;500;700&display=swap" rel="stylesheet">
12
+
13
+ <!-- FontAwesome Icons -->
14
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
15
+
16
+ <style>
17
+ /*
18
+ * Z-Image Turbo - Modern CSS Styling
19
+ * Using CSS Variables for theming and Flexbox/Grid for layout
20
+ */
21
+ :root {
22
+ --bg-dark: #0b0c15;
23
+ --bg-panel: rgba(255, 255, 255, 0.03);
24
+ --bg-panel-hover: rgba(255, 255, 255, 0.07);
25
+ --primary: #6c5ce7;
26
+ --primary-glow: rgba(108, 92, 231, 0.5);
27
+ --accent: #00cec9;
28
+ --text-main: #ffffff;
29
+ --text-muted: #a0a0b0;
30
+ --border: rgba(255, 255, 255, 0.1);
31
+ --radius-lg: 24px;
32
+ --radius-md: 16px;
33
+ --radius-sm: 8px;
34
+ --font-main: 'Outfit', sans-serif;
35
+ --font-display: 'Space Grotesk', sans-serif;
36
+ }
37
+
38
+ * {
39
+ box-sizing: border-box;
40
+ margin: 0;
41
+ padding: 0;
42
+ outline: none;
43
+ }
44
+
45
+ body {
46
+ background-color: var(--bg-dark);
47
+ background-image:
48
+ radial-gradient(circle at 10% 20%, rgba(108, 92, 231, 0.15) 0%, transparent 40%),
49
+ radial-gradient(circle at 90% 80%, rgba(0, 206, 201, 0.15) 0%, transparent 40%);
50
+ color: var(--text-main);
51
+ font-family: var(--font-main);
52
+ min-height: 100vh;
53
+ display: flex;
54
+ flex-direction: column;
55
+ overflow-x: hidden;
56
+ }
57
+
58
+ /* --- Header --- */
59
+ header {
60
+ display: flex;
61
+ justify-content: space-between;
62
+ align-items: center;
63
+ padding: 20px 5%;
64
+ border-bottom: 1px solid var(--border);
65
+ backdrop-filter: blur(10px);
66
+ position: sticky;
67
+ top: 0;
68
+ z-index: 100;
69
+ background: rgba(11, 12, 21, 0.8);
70
+ }
71
+
72
+ .logo {
73
+ font-family: var(--font-display);
74
+ font-size: 1.5rem;
75
+ font-weight: 700;
76
+ display: flex;
77
+ align-items: center;
78
+ gap: 10px;
79
+ text-transform: uppercase;
80
+ letter-spacing: 1px;
81
+ background: linear-gradient(90deg, #fff, var(--accent));
82
+ -webkit-background-clip: text;
83
+ -webkit-text-fill-color: transparent;
84
+ }
85
+
86
+ .built-with {
87
+ color: var(--text-muted);
88
+ font-size: 0.85rem;
89
+ text-decoration: none;
90
+ display: flex;
91
+ align-items: center;
92
+ gap: 5px;
93
+ transition: color 0.3s;
94
+ }
95
+
96
+ .built-with:hover {
97
+ color: var(--accent);
98
+ }
99
+
100
+ /* --- Main Layout --- */
101
+ main {
102
+ flex: 1;
103
+ display: grid;
104
+ grid-template-columns: 1fr 1.5fr;
105
+ gap: 30px;
106
+ padding: 40px 5%;
107
+ max-width: 1600px;
108
+ width: 100%;
109
+ margin: 0 auto;
110
+ }
111
+
112
+ @media (max-width: 900px) {
113
+ main {
114
+ grid-template-columns: 1fr;
115
+ }
116
+ }
117
+
118
+ /* --- Control Panel (Left) --- */
119
+ .controls-panel {
120
+ display: flex;
121
+ flex-direction: column;
122
+ gap: 24px;
123
+ height: fit-content;
124
+ }
125
+
126
+ .input-group {
127
+ background: var(--bg-panel);
128
+ border: 1px solid var(--border);
129
+ border-radius: var(--radius-lg);
130
+ padding: 20px;
131
+ position: relative;
132
+ transition: all 0.3s ease;
133
+ }
134
+
135
+ .input-group:focus-within {
136
+ border-color: var(--primary);
137
+ box-shadow: 0 0 20px rgba(108, 92, 231, 0.2);
138
+ background: var(--bg-panel-hover);
139
+ }
140
+
141
+ label {
142
+ display: block;
143
+ font-size: 0.85rem;
144
+ color: var(--accent);
145
+ margin-bottom: 10px;
146
+ font-weight: 600;
147
+ text-transform: uppercase;
148
+ letter-spacing: 0.5px;
149
+ }
150
+
151
+ textarea {
152
+ width: 100%;
153
+ background: transparent;
154
+ border: none;
155
+ color: var(--text-main);
156
+ font-family: var(--font-main);
157
+ font-size: 1.1rem;
158
+ resize: none;
159
+ height: 120px;
160
+ line-height: 1.6;
161
+ }
162
+
163
+ textarea::placeholder {
164
+ color: rgba(255, 255, 255, 0.3);
165
+ }
166
+
167
+ /* Aspect Ratio Selector */
168
+ .aspect-ratio {
169
+ display: flex;
170
+ gap: 10px;
171
+ margin-top: 10px;
172
+ }
173
+
174
+ .ratio-btn {
175
+ background: rgba(255, 255, 255, 0.05);
176
+ border: 1px solid var(--border);
177
+ border-radius: var(--radius-sm);
178
+ padding: 8px 12px;
179
+ color: var(--text-muted);
180
+ cursor: pointer;
181
+ font-size: 0.8rem;
182
+ transition: all 0.2s;
183
+ display: flex;
184
+ align-items: center;
185
+ justify-content: center;
186
+ }
187
+
188
+ .ratio-btn:hover, .ratio-btn.active {
189
+ background: var(--primary);
190
+ color: white;
191
+ border-color: var(--primary);
192
+ }
193
+
194
+ /* Style Selector */
195
+ .style-grid {
196
+ display: grid;
197
+ grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
198
+ gap: 10px;
199
+ }
200
+
201
+ .style-chip {
202
+ background: rgba(255, 255, 255, 0.05);
203
+ border: 1px solid var(--border);
204
+ border-radius: var(--radius-sm);
205
+ padding: 10px;
206
+ text-align: center;
207
+ cursor: pointer;
208
+ transition: all 0.2s;
209
+ font-size: 0.8rem;
210
+ color: var(--text-muted);
211
+ }
212
+
213
+ .style-chip i {
214
+ display: block;
215
+ font-size: 1.2rem;
216
+ margin-bottom: 5px;
217
+ color: var(--text-main);
218
+ }
219
+
220
+ .style-chip:hover, .style-chip.active {
221
+ background: linear-gradient(135deg, rgba(108, 92, 231, 0.3), rgba(0, 206, 201, 0.2));
222
+ border-color: var(--accent);
223
+ color: white;
224
+ transform: translateY(-2px);
225
+ }
226
+
227
+ /* Generate Button */
228
+ .generate-btn {
229
+ background: linear-gradient(135deg, var(--primary), var(--accent));
230
+ color: white;
231
+ border: none;
232
+ padding: 18px;
233
+ border-radius: var(--radius-lg);
234
+ font-size: 1.1rem;
235
+ font-weight: 700;
236
+ cursor: pointer;
237
+ transition: all 0.3s ease;
238
+ display: flex;
239
+ justify-content: center;
240
+ align-items: center;
241
+ gap: 10px;
242
+ box-shadow: 0 10px 30px -10px var(--primary-glow);
243
+ position: relative;
244
+ overflow: hidden;
245
+ }
246
+
247
+ .generate-btn:hover {
248
+ transform: translateY(-2px);
249
+ box-shadow: 0 15px 40px -10px var(--primary-glow);
250
+ }
251
+
252
+ .generate-btn:active {
253
+ transform: translateY(1px);
254
+ }
255
+
256
+ .generate-btn:disabled {
257
+ opacity: 0.7;
258
+ cursor: not-allowed;
259
+ transform: none;
260
+ }
261
+
262
+ .btn-icon {
263
+ font-size: 1.2rem;
264
+ }
265
+
266
+ /* --- Preview Panel (Right) --- */
267
+ .preview-panel {
268
+ position: relative;
269
+ background: var(--bg-panel);
270
+ border: 1px solid var(--border);
271
+ border-radius: var(--radius-lg);
272
+ overflow: hidden;
273
+ min-height: 500px;
274
+ display: flex;
275
+ flex-direction: column;
276
+ align-items: center;
277
+ justify-content: center;
278
+ }
279
+
280
+ .image-container {
281
+ width: 100%;
282
+ height: 100%;
283
+ display: flex;
284
+ align-items: center;
285
+ justify-content: center;
286
+ position: relative;
287
+ }
288
+
289
+ .generated-image {
290
+ max-width: 100%;
291
+ max-height: 100%;
292
+ border-radius: var(--radius-md);
293
+ box-shadow: 0 20px 50px rgba(0,0,0,0.5);
294
+ display: none; /* Hidden by default */
295
+ animation: fadeIn 0.8s ease;
296
+ }
297
+
298
+ /* Loading State */
299
+ .loader-overlay {
300
+ position: absolute;
301
+ top: 0;
302
+ left: 0;
303
+ width: 100%;
304
+ height: 100%;
305
+ background: rgba(11, 12, 21, 0.9);
306
+ backdrop-filter: blur(5px);
307
+ display: flex;
308
+ flex-direction: column;
309
+ align-items: center;
310
+ justify-content: center;
311
+ z-index: 10;
312
+ opacity: 0;
313
+ pointer-events: none;
314
+ transition: opacity 0.3s;
315
+ }
316
+
317
+ .loader-overlay.active {
318
+ opacity: 1;
319
+ pointer-events: all;
320
+ }
321
+
322
+ .spinner {
323
+ width: 60px;
324
+ height: 60px;
325
+ border: 4px solid rgba(255, 255, 255, 0.1);
326
+ border-left-color: var(--accent);
327
+ border-radius: 50%;
328
+ animation: spin 1s linear infinite;
329
+ margin-bottom: 20px;
330
+ }
331
+
332
+ .loading-text {
333
+ font-family: var(--font-display);
334
+ font-size: 1.2rem;
335
+ letter-spacing: 2px;
336
+ color: var(--accent);
337
+ margin-bottom: 10px;
338
+ }
339
+
340
+ .progress-bar {
341
+ width: 200px;
342
+ height: 4px;
343
+ background: rgba(255, 255, 255, 0.1);
344
+ border-radius: 2px;
345
+ overflow: hidden;
346
+ }
347
+
348
+ .progress-fill {
349
+ height: 100%;
350
+ width: 0%;
351
+ background: linear-gradient(90deg, var(--primary), var(--accent));
352
+ transition: width 0.2s linear;
353
+ }
354
+
355
+ /* Empty State */
356
+ .empty-state {
357
+ text-align: center;
358
+ color: var(--text-muted);
359
+ }
360
+
361
+ .empty-state i {
362
+ font-size: 4rem;
363
+ margin-bottom: 20px;
364
+ opacity: 0.3;
365
+ }
366
+
367
+ .empty-state h3 {
368
+ font-size: 1.5rem;
369
+ margin-bottom: 10px;
370
+ color: var(--text-main);
371
+ }
372
+
373
+ /* --- Footer --- */
374
+ footer {
375
+ text-align: center;
376
+ padding: 30px;
377
+ color: var(--text-muted);
378
+ font-size: 0.9rem;
379
+ border-top: 1px solid var(--border);
380
+ margin-top: auto;
381
+ }
382
+
383
+ /* --- Toast Notification --- */
384
+ .toast {
385
+ position: fixed;
386
+ bottom: 30px;
387
+ left: 50%;
388
+ transform: translateX(-50%) translateY(100px);
389
+ background: #fff;
390
+ color: #000;
391
+ padding: 12px 24px;
392
+ border-radius: 50px;
393
+ font-weight: 600;
394
+ box-shadow: 0 10px 30px rgba(0,0,0,0.3);
395
+ opacity: 0;
396
+ transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
397
+ z-index: 1000;
398
+ display: flex;
399
+ align-items: center;
400
+ gap: 10px;
401
+ }
402
+
403
+ .toast.show {
404
+ transform: translateX(-50%) translateY(0);
405
+ opacity: 1;
406
+ }
407
+
408
+ /* --- Animations --- */
409
+ @keyframes spin {
410
+ to { transform: rotate(360deg); }
411
+ }
412
+
413
+ @keyframes fadeIn {
414
+ from { opacity: 0; transform: scale(0.98); }
415
+ to { opacity: 1; transform: scale(1); }
416
+ }
417
+
418
+ @keyframes pulse {
419
+ 0% { box-shadow: 0 0 0 0 rgba(108, 92, 231, 0.4); }
420
+ 70% { box-shadow: 0 0 0 10px rgba(108, 92, 231, 0); }
421
+ 100% { box-shadow: 0 0 0 0 rgba(108, 92, 231, 0); }
422
+ }
423
+
424
+ /* --- History Strip --- */
425
+ .history-strip {
426
+ margin-top: 20px;
427
+ display: flex;
428
+ gap: 15px;
429
+ overflow-x: auto;
430
+ padding-bottom: 10px;
431
+ scrollbar-width: thin;
432
+ scrollbar-color: var(--primary) transparent;
433
+ }
434
+
435
+ .history-item {
436
+ width: 80px;
437
+ height: 80px;
438
+ border-radius: var(--radius-md);
439
+ overflow: hidden;
440
+ border: 2px solid transparent;
441
+ cursor: pointer;
442
+ transition: all 0.2s;
443
+ flex-shrink: 0;
444
+ position: relative;
445
+ }
446
+
447
+ .history-item img {
448
+ width: 100%;
449
+ height: 100%;
450
+ object-fit: cover;
451
+ }
452
+
453
+ .history-item:hover, .history-item.active {
454
+ border-color: var(--accent);
455
+ transform: scale(1.05);
456
+ }
457
+
458
+ </style>
459
+ </head>
460
+ <body>
461
+
462
+ <!-- Header -->
463
+ <header>
464
+ <div class="logo">
465
+ <i class="fa-solid fa-bolt"></i> Z-Image Turbo
466
+ </div>
467
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="built-with">
468
+ Built with anycoder <i class="fa-solid fa-arrow-up-right-from-square"></i>
469
+ </a>
470
+ </header>
471
+
472
+ <!-- Main Content -->
473
+ <main>
474
+ <!-- Controls Section -->
475
+ <section class="controls-panel">
476
+
477
+ <div class="input-group">
478
+ <label for="prompt"><i class="fa-solid fa-wand-magic-sparkles"></i> Describe your vision</label>
479
+ <textarea id="prompt" placeholder="A futuristic city with neon lights, cyberpunk style, highly detailed..."></textarea>
480
+ </div>
481
+
482
+ <div class="input-group">
483
+ <label>Style</label>
484
+ <div class="style-grid">
485
+ <div class="style-chip active" data-style="realistic">
486
+ <i class="fa-solid fa-camera"></i> Real
487
+ </div>
488
+ <div class="style-chip" data-style="anime">
489
+ <i class="fa-solid fa-star"></i> Anime
490
+ </div>
491
+ <div class="style-chip" data-style="cyberpunk">
492
+ <i class="fa-solid fa-robot"></i> Cyber
493
+ </div>
494
+ <div class="style-chip" data-style="oil">
495
+ <i class="fa-solid fa-palette"></i> Oil
496
+ </div>
497
+ <div class="style-chip" data-style="3d">
498
+ <i class="fa-solid fa-cube"></i> 3D Render
499
+ </div>
500
+ <div class="style-chip" data-style="sketch">
501
+ <i class="fa-solid fa-pencil"></i> Sketch
502
+ </div>
503
+ </div>
504
+ </div>
505
+
506
+ <div class="input-group">
507
+ <label>Aspect Ratio</label>
508
+ <div class="aspect-ratio">
509
+ <div class="ratio-btn active" data-ratio="1:1">
510
+ <i class="fa-regular fa-square"></i> 1:1
511
+ </div>
512
+ <div class="ratio-btn" data-ratio="16:9">
513
+ <i class="fa-solid fa-video"></i> 16:9
514
+ </div>
515
+ <div class="ratio-btn" data-ratio="9:16">
516
+ <i class="fa-solid fa-mobile-screen"></i> 9:16
517
+ </div>
518
+ <div class="ratio-btn" data-ratio="4:3">
519
+ <i class="fa-solid fa-image"></i> 4:3
520
+ </div>
521
+ </div>
522
+ </div>
523
+
524
+ <button class="generate-btn" id="generateBtn">
525
+ <span class="btn-text">Generate Image</span>
526
+ <i class="fa-solid fa-arrow-right btn-icon"></i>
527
+ </button>
528
+
529
+ </section>
530
+
531
+ <!-- Preview Section -->
532
+ <section class="preview-panel" id="previewPanel">
533
+
534
+ <!-- Empty State -->
535
+ <div class="empty-state" id="emptyState">
536
+ <i class="fa-solid fa-image"></i>
537
+ <h3>Ready to create?</h3>
538
+ <p>Enter a prompt and let Z-Image Turbo work its magic.</p>
539
+ </div>
540
+
541
+ <!-- Loader -->
542
+ <div class="loader-overlay" id="loader">
543
+ <div class="spinner"></div>
544
+ <div class="loading-text" id="loadingText">Initializing...</div>
545
+ <div class="progress-bar">
546
+ <div class="progress-fill" id="progressFill"></div>
547
+ </div>
548
+ </div>
549
+
550
+ <!-- Result Image -->
551
+ <div class="image-container">
552
+ <img src="" alt="Generated AI Art" class="generated-image" id="resultImage">
553
+ </div>
554
+
555
+ <!-- History Strip -->
556
+ <div class="history-strip" id="historyStrip">
557
+ <!-- History items will be injected here -->
558
+ </div>
559
+
560
+ </section>
561
+ </main>
562
+
563
+ <!-- Footer -->
564
+ <footer>
565
+ <p>&copy; 2023 Z-Image Turbo. Powered by AI.</p>
566
+ </footer>
567
+
568
+ <!-- Toast Notification -->
569
+ <div class="toast" id="toast">
570
+ <i class="fa-solid fa-circle-info"></i>
571
+ <span id="toastMessage">Message here</span>
572
+ </div>
573
+
574
+ <!-- JavaScript Logic -->
575
+ <script>
576
+ document.addEventListener('DOMContentLoaded', () => {
577
+
578
+ // Elements
579
+ const promptInput = document.getElementById('prompt');
580
+ const generateBtn = document.getElementById('generateBtn');
581
+ const resultImage = document.getElementById('resultImage');
582
+ const emptyState = document.getElementById('emptyState');
583
+ const loader = document.getElementById('loader');
584
+ const progressFill = document.getElementById('progressFill');
585
+ const loadingText = document.getElementById('loadingText');
586
+ const toast = document.getElementById('toast');
587
+ const toastMessage = document.getElementById('toastMessage');
588
+ const styleChips = document.querySelectorAll('.style-chip');
589
+ const ratioBtns = document.querySelectorAll('.ratio-btn');
590
+ const historyStrip = document.getElementById('historyStrip');
591
+
592
+ // State
593
+ let currentStyle = 'realistic';
594
+ let currentRatio = '1:1';
595
+ const history = [];
596
+
597
+ // --- Event Listeners for UI Controls ---
598
+
599
+ // Style Selection
600
+ styleChips.forEach(chip => {
601
+ chip.addEventListener('click', () => {
602
+ styleChips.forEach(c => c.classList.remove('active'));
603
+ chip.classList.add('active');
604
+ currentStyle = chip.dataset.style;
605
+ });
606
+ });
607
+
608
+ // Ratio Selection
609
+ ratioBtns.forEach(btn => {
610
+ btn.addEventListener('click', () => {
611
+ ratioBtns.forEach(b => b.classList.remove('active'));
612
+ btn.classList.add('active');
613
+ currentRatio = btn.dataset.ratio;
614
+ });
615
+ });
616
+
617
+ // Generate Action
618
+ generateBtn.addEventListener('click', startGeneration);
619
+
620
+ // --- Core Functions ---
621
+
622
+ function startGeneration() {
623
+ const prompt = promptInput.value.trim();
624
+
625
+ // Validation
626
+ if (!prompt) {
627
+ showToast('Please enter a description first!', true);
628
+ promptInput.focus();
629
+ return;
630
+ }
631
+
632
+ // Lock UI
633
+ setLoading(true);
634
+
635
+ // Simulation Variables
636
+ let progress = 0;
637
+ const steps = [
638
+ "Analyzing prompt...",
639
+ "Connecting to neural network...",
640
+ "Diffusing pixels...",
641
+ "Refining details...",
642
+ "Finalizing output..."
643
+ ];
644
+ let stepIndex = 0;
645
+
646
+ // Simulate Progress Loop
647
+ const interval = setInterval(() => {
648
+ progress += Math.floor(Math.random() * 5) + 2; // Random increment
649
+
650
+ if (progress > 100) progress = 100;
651
+
652
+ progressFill.style.width = `${progress}%`;
653
+
654
+ // Update text based on progress thresholds
655
+ if (progress > 20 && stepIndex === 0) { loadingText.innerText = steps[1]; stepIndex++; }
656
+ if (progress > 50 && stepIndex === 1) { loadingText.innerText = steps[2]; stepIndex++; }
657
+ if (progress > 80 && stepIndex === 2) { loadingText.innerText = steps[3]; stepIndex++; }
658
+ if (progress > 95 && stepIndex === 3) { loadingText.innerText = steps[4]; stepIndex++; }
659
+
660
+ if (progress === 100) {
661
+ clearInterval(interval);
662
+ finishGeneration(prompt);
663
+ }
664
+ }, 100); // Speed of simulation
665
+ }
666
+
667
+ function finishGeneration(prompt) {
668
+ // Generate a consistent image based on prompt + style
669
+ // Using picsum.photos with a seed creates a deterministic "random" image
670
+ const seed = encodeURIComponent(prompt + currentStyle + Date.now());
671
+ let width = 1024;
672
+ let height = 1024;
673
+
674
+ // Adjust ratio for image dimensions
675
+ if (currentRatio === '16:9') { width = 1280; height = 720; }
676
+ if (currentRatio === '9:16') { width = 720; height = 1280; }
677
+ if (currentRatio === '4:3') { width = 1024; height = 768; }
678
+
679
+ // Construct URL (Unsplash Source API for variety, seeded)
680
+ // Note: In a real app, this would be your API endpoint.
681
+ const imageUrl = `https://picsum.photos/seed/${seed}/${width}/${height}.jpg`;
682
+
683
+ // Preload image to ensure smooth display
684
+ const tempImg = new Image();
685
+ tempImg.onload = () => {
686
+ resultImage.src = imageUrl;
687
+ emptyState.style.display = 'none';
688
+ resultImage.style.display = 'block';
689
+ setLoading(false);
690
+
691
+ // Add to history
692
+ addToHistory(imageUrl);
693
+ showToast('Image generated successfully!');
694
+ };
695
+ tempImg.src = imageUrl;
696
+ }
697
+
698
+ function setLoading(isLoading) {
699
+ if (isLoading) {
700
+ loader.classList.add('active');
701
+ generateBtn.disabled = true;
702
+ generateBtn.querySelector('.btn-text').innerText = 'Generating...';
703
+ resultImage.style.display = 'none';
704
+ historyStrip.innerHTML = ''; // Clear history while generating
705
+ } else {
706
+ loader.classList.remove('active');
707
+ generateBtn.disabled = false;
708
+ generateBtn.querySelector('.btn-text').innerText = 'Generate Image';
709
+ progressFill.style.width = '0%';
710
+ }
711
+ }
712
+
713
+ function addToHistory(url) {
714
+ const item = document.createElement('div');
715
+ item.className = 'history-item';
716
+ item.innerHTML = `<img src="${url}" alt="History">`;
717
+
718
+ item.addEventListener('click', () => {
719
+ // Remove active class from others
720
+ document.querySelectorAll('.history-item').forEach(i => i.classList.remove('active'));
721
+ item.classList.add('active');
722
+
723
+ // Show image in main view
724
+ emptyState.style.display = 'none';
725
+ resultImage.style.display = 'block';
726
+ resultImage.src = url;
727
+ });
728
+
729
+ history.prepend(item);
730
+
731
+ // Limit history to 5 items
732
+ if (history.length > 5) {
733
+ historyStrip.lastElementChild.remove();
734
+ }
735
+ }
736
+
737
+ function showToast(msg, isError = false) {
738
+ toastMessage.innerText = msg;
739
+ toast.style.background = isError ? '#ff4757' : '#fff';
740
+ toast.style.color = isError ? '#fff' : '#000';
741
+ toast.classList.add('show');
742
+
743
+ setTimeout(() => {
744
+ toast.classList.remove('show');
745
+ }, 3000);
746
+ }
747
+ });
748
+ </script>
749
+ </body>
750
+ </html>