linoyts HF Staff commited on
Commit
ba60d42
·
verified ·
1 Parent(s): aa49bd5

Claude on the frontenddd

Browse files
Files changed (1) hide show
  1. index.html +671 -19
index.html CHANGED
@@ -1,19 +1,671 @@
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>Open Image Generation Progress</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Syne:wght@400;500;600;700;800&display=swap" rel="stylesheet">
10
+ <style>
11
+ :root {
12
+ --bg-primary: #0a0a0b;
13
+ --bg-secondary: #131316;
14
+ --bg-card: #1a1a1f;
15
+ --text-primary: #f5f5f7;
16
+ --text-secondary: #8e8e93;
17
+ --text-muted: #636366;
18
+ --accent: #6366f1;
19
+ --accent-glow: rgba(99, 102, 241, 0.3);
20
+ --border: #2c2c2e;
21
+ --year-2022: #f472b6;
22
+ --year-2023: #fb923c;
23
+ --year-2024: #4ade80;
24
+ --year-2025: #60a5fa;
25
+ }
26
+
27
+ * {
28
+ margin: 0;
29
+ padding: 0;
30
+ box-sizing: border-box;
31
+ }
32
+
33
+ body {
34
+ font-family: 'Syne', sans-serif;
35
+ background: var(--bg-primary);
36
+ color: var(--text-primary);
37
+ min-height: 100vh;
38
+ overflow-x: hidden;
39
+ }
40
+
41
+ /* Grain overlay */
42
+ body::before {
43
+ content: '';
44
+ position: fixed;
45
+ top: 0;
46
+ left: 0;
47
+ width: 100%;
48
+ height: 100%;
49
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
50
+ opacity: 0.03;
51
+ pointer-events: none;
52
+ z-index: 1000;
53
+ }
54
+
55
+ /* Header */
56
+ header {
57
+ padding: 2rem 3rem;
58
+ border-bottom: 1px solid var(--border);
59
+ display: flex;
60
+ justify-content: space-between;
61
+ align-items: center;
62
+ position: sticky;
63
+ top: 0;
64
+ background: rgba(10, 10, 11, 0.85);
65
+ backdrop-filter: blur(20px);
66
+ z-index: 100;
67
+ }
68
+
69
+ .logo {
70
+ font-size: 1.1rem;
71
+ font-weight: 700;
72
+ letter-spacing: -0.02em;
73
+ display: flex;
74
+ align-items: center;
75
+ gap: 0.5rem;
76
+ }
77
+
78
+ .logo-icon {
79
+ width: 32px;
80
+ height: 32px;
81
+ }
82
+
83
+ .nav-links {
84
+ display: flex;
85
+ gap: 2rem;
86
+ font-size: 0.875rem;
87
+ color: var(--text-secondary);
88
+ }
89
+
90
+ .nav-links a {
91
+ color: inherit;
92
+ text-decoration: none;
93
+ transition: color 0.2s;
94
+ }
95
+
96
+ .nav-links a:hover {
97
+ color: var(--text-primary);
98
+ }
99
+
100
+ /* Hero */
101
+ .hero {
102
+ padding: 6rem 3rem 4rem;
103
+ text-align: center;
104
+ max-width: 900px;
105
+ margin: 0 auto;
106
+ }
107
+
108
+ .hero h1 {
109
+ font-size: clamp(2.5rem, 6vw, 4rem);
110
+ font-weight: 800;
111
+ letter-spacing: -0.03em;
112
+ line-height: 1.1;
113
+ margin-bottom: 1.5rem;
114
+ background: linear-gradient(135deg, var(--text-primary) 0%, var(--text-secondary) 100%);
115
+ -webkit-background-clip: text;
116
+ -webkit-text-fill-color: transparent;
117
+ background-clip: text;
118
+ }
119
+
120
+ .hero p {
121
+ font-size: 1.125rem;
122
+ color: var(--text-secondary);
123
+ max-width: 600px;
124
+ margin: 0 auto 2rem;
125
+ line-height: 1.6;
126
+ }
127
+
128
+ /* Prompt Navigation */
129
+ .prompt-nav {
130
+ display: flex;
131
+ justify-content: center;
132
+ align-items: center;
133
+ gap: 1rem;
134
+ padding: 1.5rem 3rem;
135
+ border-bottom: 1px solid var(--border);
136
+ position: sticky;
137
+ top: 73px;
138
+ background: rgba(10, 10, 11, 0.9);
139
+ backdrop-filter: blur(20px);
140
+ z-index: 99;
141
+ }
142
+
143
+ .nav-btn {
144
+ width: 48px;
145
+ height: 48px;
146
+ border-radius: 50%;
147
+ border: 1px solid var(--border);
148
+ background: var(--bg-secondary);
149
+ color: var(--text-primary);
150
+ cursor: pointer;
151
+ display: flex;
152
+ align-items: center;
153
+ justify-content: center;
154
+ transition: all 0.2s;
155
+ font-size: 1.25rem;
156
+ }
157
+
158
+ .nav-btn:hover {
159
+ background: var(--bg-card);
160
+ border-color: var(--text-muted);
161
+ }
162
+
163
+ .prompt-indicator {
164
+ font-family: 'Space Mono', monospace;
165
+ font-size: 0.875rem;
166
+ color: var(--text-muted);
167
+ min-width: 80px;
168
+ text-align: center;
169
+ }
170
+
171
+ /* Prompt Display */
172
+ .prompt-section {
173
+ padding: 3rem;
174
+ max-width: 1400px;
175
+ margin: 0 auto;
176
+ }
177
+
178
+ .prompt-label {
179
+ font-family: 'Space Mono', monospace;
180
+ font-size: 0.75rem;
181
+ color: var(--text-muted);
182
+ text-transform: uppercase;
183
+ letter-spacing: 0.1em;
184
+ margin-bottom: 0.75rem;
185
+ }
186
+
187
+ .prompt-text {
188
+ font-size: clamp(1.25rem, 3vw, 1.75rem);
189
+ font-weight: 600;
190
+ line-height: 1.4;
191
+ max-width: 900px;
192
+ margin-bottom: 3rem;
193
+ color: var(--text-primary);
194
+ }
195
+
196
+ /* Timeline */
197
+ .timeline {
198
+ display: flex;
199
+ justify-content: center;
200
+ gap: 0.5rem;
201
+ margin-bottom: 3rem;
202
+ flex-wrap: wrap;
203
+ }
204
+
205
+ .timeline-btn {
206
+ padding: 0.75rem 1.5rem;
207
+ border-radius: 100px;
208
+ border: 1px solid var(--border);
209
+ background: transparent;
210
+ color: var(--text-secondary);
211
+ cursor: pointer;
212
+ font-family: 'Space Mono', monospace;
213
+ font-size: 0.8rem;
214
+ transition: all 0.3s;
215
+ display: flex;
216
+ flex-direction: column;
217
+ align-items: center;
218
+ gap: 0.25rem;
219
+ }
220
+
221
+ .timeline-btn .year {
222
+ font-weight: 700;
223
+ font-size: 0.9rem;
224
+ }
225
+
226
+ .timeline-btn .model {
227
+ font-size: 0.7rem;
228
+ opacity: 0.7;
229
+ }
230
+
231
+ .timeline-btn:hover {
232
+ border-color: var(--text-muted);
233
+ color: var(--text-primary);
234
+ }
235
+
236
+ .timeline-btn.active {
237
+ background: var(--text-primary);
238
+ color: var(--bg-primary);
239
+ border-color: var(--text-primary);
240
+ }
241
+
242
+ .timeline-btn[data-year="2022"] { --btn-accent: var(--year-2022); }
243
+ .timeline-btn[data-year="2023"] { --btn-accent: var(--year-2023); }
244
+ .timeline-btn[data-year="2024"] { --btn-accent: var(--year-2024); }
245
+ .timeline-btn[data-year="2025"] { --btn-accent: var(--year-2025); }
246
+
247
+ .timeline-btn.active {
248
+ background: var(--btn-accent);
249
+ border-color: var(--btn-accent);
250
+ color: var(--bg-primary);
251
+ }
252
+
253
+ /* Image Display */
254
+ .image-container {
255
+ display: flex;
256
+ justify-content: center;
257
+ gap: 1.5rem;
258
+ flex-wrap: wrap;
259
+ }
260
+
261
+ .image-card {
262
+ background: var(--bg-card);
263
+ border-radius: 16px;
264
+ overflow: hidden;
265
+ border: 1px solid var(--border);
266
+ transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
267
+ max-width: 350px;
268
+ opacity: 0;
269
+ transform: translateY(20px);
270
+ animation: fadeInUp 0.5s ease forwards;
271
+ }
272
+
273
+ .image-card:nth-child(1) { animation-delay: 0s; }
274
+ .image-card:nth-child(2) { animation-delay: 0.1s; }
275
+ .image-card:nth-child(3) { animation-delay: 0.2s; }
276
+
277
+ @keyframes fadeInUp {
278
+ to {
279
+ opacity: 1;
280
+ transform: translateY(0);
281
+ }
282
+ }
283
+
284
+ .image-card:hover {
285
+ transform: translateY(-4px);
286
+ border-color: var(--text-muted);
287
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
288
+ }
289
+
290
+ .image-card img {
291
+ width: 100%;
292
+ aspect-ratio: 1;
293
+ object-fit: cover;
294
+ display: block;
295
+ }
296
+
297
+ .image-meta {
298
+ padding: 1rem 1.25rem;
299
+ display: flex;
300
+ justify-content: space-between;
301
+ align-items: center;
302
+ }
303
+
304
+ .model-name {
305
+ font-weight: 600;
306
+ font-size: 0.9rem;
307
+ }
308
+
309
+ .model-year {
310
+ font-family: 'Space Mono', monospace;
311
+ font-size: 0.75rem;
312
+ padding: 0.25rem 0.75rem;
313
+ border-radius: 100px;
314
+ background: var(--bg-secondary);
315
+ }
316
+
317
+ /* Compare Mode */
318
+ .view-toggle {
319
+ display: flex;
320
+ justify-content: center;
321
+ gap: 0.5rem;
322
+ margin-bottom: 2rem;
323
+ }
324
+
325
+ .view-btn {
326
+ padding: 0.5rem 1rem;
327
+ border-radius: 8px;
328
+ border: 1px solid var(--border);
329
+ background: transparent;
330
+ color: var(--text-secondary);
331
+ cursor: pointer;
332
+ font-size: 0.8rem;
333
+ transition: all 0.2s;
334
+ }
335
+
336
+ .view-btn.active {
337
+ background: var(--bg-card);
338
+ color: var(--text-primary);
339
+ border-color: var(--text-muted);
340
+ }
341
+
342
+ /* Compare Grid */
343
+ .compare-grid {
344
+ display: grid;
345
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
346
+ gap: 1rem;
347
+ max-width: 1200px;
348
+ margin: 0 auto;
349
+ }
350
+
351
+ .compare-grid .image-card {
352
+ max-width: none;
353
+ }
354
+
355
+ .compare-grid .image-card img {
356
+ aspect-ratio: 1;
357
+ }
358
+
359
+ /* Footer */
360
+ footer {
361
+ padding: 4rem 3rem;
362
+ border-top: 1px solid var(--border);
363
+ text-align: center;
364
+ margin-top: 6rem;
365
+ }
366
+
367
+ footer p {
368
+ color: var(--text-muted);
369
+ font-size: 0.875rem;
370
+ }
371
+
372
+ footer a {
373
+ color: var(--text-secondary);
374
+ }
375
+
376
+ /* Responsive */
377
+ @media (max-width: 768px) {
378
+ header {
379
+ padding: 1rem 1.5rem;
380
+ }
381
+
382
+ .hero {
383
+ padding: 4rem 1.5rem 2rem;
384
+ }
385
+
386
+ .prompt-section {
387
+ padding: 2rem 1.5rem;
388
+ }
389
+
390
+ .prompt-nav {
391
+ padding: 1rem 1.5rem;
392
+ }
393
+
394
+ .timeline {
395
+ gap: 0.25rem;
396
+ }
397
+
398
+ .timeline-btn {
399
+ padding: 0.5rem 1rem;
400
+ }
401
+
402
+ .nav-links {
403
+ display: none;
404
+ }
405
+ }
406
+ </style>
407
+ </head>
408
+ <body>
409
+ <header>
410
+ <div class="logo">
411
+ <svg class="logo-icon" viewBox="0 0 95 88" fill="none" xmlns="http://www.w3.org/2000/svg">
412
+ <path d="M47.2119 76.5C54.4037 76.5 60.2119 70.6918 60.2119 63.5C60.2119 56.3082 54.4037 50.5 47.2119 50.5C40.0201 50.5 34.2119 56.3082 34.2119 63.5C34.2119 70.6918 40.0201 76.5 47.2119 76.5Z" fill="#FFD21E"/>
413
+ <path d="M81.3494 24.5C81.3494 34.165 73.5765 42 63.9119 42C54.2473 42 46.4744 34.165 46.4744 24.5C46.4744 14.835 54.2473 7 63.9119 7C73.5765 7 81.3494 14.835 81.3494 24.5Z" fill="#FF9D00"/>
414
+ <path d="M47.9494 24.5C47.9494 34.165 40.1765 42 30.5119 42C20.8473 42 13.0744 34.165 13.0744 24.5C13.0744 14.835 20.8473 7 30.5119 7C40.1765 7 47.9494 14.835 47.9494 24.5Z" fill="#FF9D00"/>
415
+ <path d="M86.7115 46.0001C86.7115 44.0001 85.8304 42.1466 84.2977 40.8775C82.765 39.6083 80.7302 38.9524 78.6511 39.0626C76.572 39.1727 74.6277 40.0391 73.2592 41.4677C71.8908 42.8963 71.2119 44.7636 71.2119 46.7636V52.2365C71.2119 53.0843 71.5469 53.8974 72.1439 54.4975C72.7409 55.0976 73.5508 55.4365 74.3956 55.4365H74.5282C75.373 55.4365 76.1829 55.0976 76.7799 54.4975C77.3769 53.8974 77.7119 53.0843 77.7119 52.2365V46.7636C77.7119 46.2636 77.9119 45.7636 78.2619 45.4136C78.6119 45.0636 79.1119 44.8636 79.6119 44.8636C80.1119 44.8636 80.6119 45.0636 80.9619 45.4136C81.3119 45.7636 81.5119 46.2636 81.5119 46.7636V63.5001C81.5119 65.0913 82.1428 66.6175 83.2681 67.7427C84.3933 68.868 85.9194 69.5001 87.5107 69.5001C87.9028 69.5001 88.2119 69.191 88.2119 68.7989V46.0001H86.7115Z" fill="#FF9D00"/>
416
+ <path d="M7.71191 46.0001C7.71191 44.0001 8.59307 42.1466 10.1258 40.8775C11.6585 39.6083 13.6932 38.9524 15.7723 39.0626C17.8515 39.1727 19.7957 40.0391 21.1642 41.4677C22.5327 42.8963 23.2119 44.7636 23.2119 46.7636V52.2365C23.2119 53.0843 22.8769 53.8974 22.2799 54.4975C21.6829 55.0976 20.873 55.4365 20.0282 55.4365H19.8956C19.0508 55.4365 18.2409 55.0976 17.6439 54.4975C17.0469 53.8974 16.7119 53.0843 16.7119 52.2365V46.7636C16.7119 46.2636 16.5119 45.7636 16.1619 45.4136C15.8119 45.0636 15.3119 44.8636 14.8119 44.8636C14.3119 44.8636 13.8119 45.0636 13.4619 45.4136C13.1119 45.7636 12.9119 46.2636 12.9119 46.7636V63.5001C12.9119 65.0913 12.281 66.6175 11.1558 67.7427C10.0305 68.868 8.50439 69.5001 6.91309 69.5001C6.52098 69.5001 6.21191 69.191 6.21191 68.7989V46.0001H7.71191Z" fill="#FF9D00"/>
417
+ <path d="M31.2119 28C32.8688 28 34.2119 26.6569 34.2119 25C34.2119 23.3431 32.8688 22 31.2119 22C29.555 22 28.2119 23.3431 28.2119 25C28.2119 26.6569 29.555 28 31.2119 28Z" fill="#3A3B45"/>
418
+ <path d="M63.2119 28C64.8688 28 66.2119 26.6569 66.2119 25C66.2119 23.3431 64.8688 22 63.2119 22C61.555 22 60.2119 23.3431 60.2119 25C60.2119 26.6569 61.555 28 63.2119 28Z" fill="#3A3B45"/>
419
+ <path d="M39.2119 56C39.2119 56 42.2119 62 47.2119 62C52.2119 62 55.2119 56 55.2119 56" stroke="#3A3B45" stroke-width="3" stroke-linecap="round"/>
420
+ </svg>
421
+ Open Image Progress
422
+ </div>
423
+ <nav class="nav-links">
424
+ <a href="https://huggingface.co" target="_blank">Hugging Face</a>
425
+ <a href="https://github.com" target="_blank">GitHub</a>
426
+ </nav>
427
+ </header>
428
+
429
+ <section class="hero">
430
+ <h1>Open-Source Image Generation Has Evolved</h1>
431
+ <p>Witness the remarkable progress of open image models from 2022 to 2025. Same prompts, different eras.</p>
432
+ </section>
433
+
434
+ <nav class="prompt-nav">
435
+ <button class="nav-btn" id="prevPrompt">←</button>
436
+ <span class="prompt-indicator"><span id="promptNum">1</span> / <span id="totalPrompts">10</span></span>
437
+ <button class="nav-btn" id="nextPrompt">→</button>
438
+ </nav>
439
+
440
+ <main class="prompt-section">
441
+ <div class="prompt-label">Prompt</div>
442
+ <p class="prompt-text" id="promptText"></p>
443
+
444
+ <div class="view-toggle">
445
+ <button class="view-btn active" data-view="single">Single Model</button>
446
+ <button class="view-btn" data-view="compare">Compare All</button>
447
+ </div>
448
+
449
+ <div class="timeline" id="timeline"></div>
450
+
451
+ <div class="image-container" id="imageContainer"></div>
452
+ </main>
453
+
454
+ <footer>
455
+ <p>Built to showcase the progress of open-source image generation models.</p>
456
+ <p style="margin-top: 0.5rem;">
457
+ <a href="https://huggingface.co/spaces" target="_blank">Hosted on Hugging Face Spaces</a>
458
+ </p>
459
+ </footer>
460
+
461
+ <script>
462
+ // Data
463
+ const models = [
464
+ { id: 'dalle_mini', name: 'DALL-E Mini', year: '2022', folder: 'dalle_mini' },
465
+ { id: 'sd15', name: 'SD 1.5', year: '2022', folder: 'sd1.5' },
466
+ { id: 'sdxl', name: 'SDXL', year: '2023', folder: 'sdxl' },
467
+ { id: 'flux1', name: 'FLUX.1 Dev', year: '2024', folder: 'flux1_dev' },
468
+ { id: 'qwen', name: 'Qwen-Image', year: '2025', folder: 'qwen_image' },
469
+ ];
470
+
471
+ const prompts = [
472
+ {
473
+ id: 'avocado',
474
+ text: 'An armchair in the shape of an avocado',
475
+ file: 'avocado'
476
+ },
477
+ {
478
+ id: 'astronaut',
479
+ text: 'A photograph of an astronaut riding a horse',
480
+ file: 'astronaut_rides_horse'
481
+ },
482
+ {
483
+ id: 'coffee',
484
+ text: 'A coffee shop chalkboard sign that reads "Today\'s Special: Vanilla Latte $4.50"',
485
+ file: 'coffee_shop'
486
+ },
487
+ {
488
+ id: 'hands',
489
+ text: 'A close-up photograph of a person\'s hands playing a chord on an acoustic guitar',
490
+ file: 'hands'
491
+ },
492
+ {
493
+ id: 'fisherman',
494
+ text: 'Portrait photograph of an elderly fisherman with weathered skin, wearing a wool sweater, soft window light',
495
+ file: 'fisherman'
496
+ },
497
+ {
498
+ id: 'golden',
499
+ text: 'A golden retriever wearing red sunglasses sits in a turquoise kayak on a calm lake at sunset. Next to it, an orange tabby cat wearing a small purple top hat looks unimpressed. Mountains reflected in the water, golden hour lighting.',
500
+ file: 'golden'
501
+ },
502
+ {
503
+ id: 'fox',
504
+ text: 'A Japanese woodblock print of a fox in a bamboo forest, in the style of Hiroshige',
505
+ file: 'fox'
506
+ },
507
+ {
508
+ id: 'gameshow',
509
+ text: 'A man in a business suit standing in front of a large screen, shot from behind-the-scenes perspective of a game show set. The suit is split vertically down the middle: left half bright green, right half bright orange. The screen behind him is also split vertically: left half pink, right half blue. Realistic photography style, professional lighting, behind-the-scenes candid shot, game show studio environment, detailed fabric textures on the suit, crisp color separation',
510
+ file: 'game_show'
511
+ },
512
+ {
513
+ id: 'whale',
514
+ text: 'A massive blue whale swimming gracefully through the clouds above a small Italian village, casting a shadow over terracotta rooftops and narrow cobblestone streets. Elderly villagers look up in wonder from a piazza with a fountain. Late afternoon Mediterranean light, photorealistic, cinematic composition, sense of magical realism and scale',
515
+ file: 'whale'
516
+ },
517
+ {
518
+ id: 'robot',
519
+ text: 'A hyper-detailed oil painting in the style of the Dutch Golden Age masters, depicting a robot made of polished brass and copper sitting at a wooden table, peeling an orange. Dramatic chiaroscuro lighting from a single window, rich dark background, meticulous attention to metallic reflections and citrus texture, visible brushstrokes, museum quality, Vermeer meets steampunk',
520
+ file: 'robot'
521
+ }
522
+ ];
523
+
524
+ // State
525
+ let currentPromptIndex = 0;
526
+ let currentModelIndex = models.length - 1; // Start with latest
527
+ let viewMode = 'single'; // 'single' or 'compare'
528
+
529
+ // DOM Elements
530
+ const promptText = document.getElementById('promptText');
531
+ const promptNum = document.getElementById('promptNum');
532
+ const totalPrompts = document.getElementById('totalPrompts');
533
+ const timeline = document.getElementById('timeline');
534
+ const imageContainer = document.getElementById('imageContainer');
535
+ const prevBtn = document.getElementById('prevPrompt');
536
+ const nextBtn = document.getElementById('nextPrompt');
537
+ const viewBtns = document.querySelectorAll('.view-btn');
538
+
539
+ // Initialize
540
+ function init() {
541
+ totalPrompts.textContent = prompts.length;
542
+ renderTimeline();
543
+ renderPrompt();
544
+ setupEventListeners();
545
+ }
546
+
547
+ function renderTimeline() {
548
+ timeline.innerHTML = models.map((model, index) => `
549
+ <button class="timeline-btn ${index === currentModelIndex ? 'active' : ''}"
550
+ data-index="${index}"
551
+ data-year="${model.year}">
552
+ <span class="year">${model.year}</span>
553
+ <span class="model">${model.name}</span>
554
+ </button>
555
+ `).join('');
556
+
557
+ // Add click handlers
558
+ document.querySelectorAll('.timeline-btn').forEach(btn => {
559
+ btn.addEventListener('click', () => {
560
+ currentModelIndex = parseInt(btn.dataset.index);
561
+ updateTimeline();
562
+ renderImages();
563
+ });
564
+ });
565
+ }
566
+
567
+ function updateTimeline() {
568
+ document.querySelectorAll('.timeline-btn').forEach((btn, index) => {
569
+ btn.classList.toggle('active', index === currentModelIndex);
570
+ });
571
+ }
572
+
573
+ function renderPrompt() {
574
+ const prompt = prompts[currentPromptIndex];
575
+ promptText.textContent = prompt.text;
576
+ promptNum.textContent = currentPromptIndex + 1;
577
+ renderImages();
578
+ }
579
+
580
+ function renderImages() {
581
+ const prompt = prompts[currentPromptIndex];
582
+
583
+ if (viewMode === 'compare') {
584
+ renderCompareView(prompt);
585
+ } else {
586
+ renderSingleView(prompt);
587
+ }
588
+ }
589
+
590
+ function renderSingleView(prompt) {
591
+ const model = models[currentModelIndex];
592
+ const images = [
593
+ `${model.folder}/${prompt.file}.png`,
594
+ `${model.folder}/${prompt.file}_2.png`,
595
+ `${model.folder}/${prompt.file}_3.png`
596
+ ];
597
+
598
+ imageContainer.className = 'image-container';
599
+ imageContainer.innerHTML = images.map((src, i) => `
600
+ <div class="image-card" style="animation-delay: ${i * 0.1}s">
601
+ <img src="${src}" alt="${prompt.text}" loading="lazy" onerror="this.src='data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><rect fill=%22%231a1a1f%22 width=%22100%22 height=%22100%22/><text x=%2250%22 y=%2250%22 text-anchor=%22middle%22 fill=%22%23636366%22 font-size=%228%22>Not found</text></svg>'">
602
+ <div class="image-meta">
603
+ <span class="model-name">${model.name}</span>
604
+ <span class="model-year">${model.year}</span>
605
+ </div>
606
+ </div>
607
+ `).join('');
608
+ }
609
+
610
+ function renderCompareView(prompt) {
611
+ imageContainer.className = 'image-container compare-grid';
612
+ imageContainer.innerHTML = models.map((model, i) => `
613
+ <div class="image-card" style="animation-delay: ${i * 0.1}s">
614
+ <img src="${model.folder}/${prompt.file}.png" alt="${prompt.text}" loading="lazy" onerror="this.src='data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><rect fill=%22%231a1a1f%22 width=%22100%22 height=%22100%22/><text x=%2250%22 y=%2250%22 text-anchor=%22middle%22 fill=%22%23636366%22 font-size=%228%22>Not found</text></svg>'">
615
+ <div class="image-meta">
616
+ <span class="model-name">${model.name}</span>
617
+ <span class="model-year">${model.year}</span>
618
+ </div>
619
+ </div>
620
+ `).join('');
621
+ }
622
+
623
+ function setupEventListeners() {
624
+ prevBtn.addEventListener('click', () => {
625
+ currentPromptIndex = (currentPromptIndex - 1 + prompts.length) % prompts.length;
626
+ renderPrompt();
627
+ });
628
+
629
+ nextBtn.addEventListener('click', () => {
630
+ currentPromptIndex = (currentPromptIndex + 1) % prompts.length;
631
+ renderPrompt();
632
+ });
633
+
634
+ viewBtns.forEach(btn => {
635
+ btn.addEventListener('click', () => {
636
+ viewMode = btn.dataset.view;
637
+ viewBtns.forEach(b => b.classList.remove('active'));
638
+ btn.classList.add('active');
639
+
640
+ // Show/hide timeline in compare mode
641
+ timeline.style.display = viewMode === 'compare' ? 'none' : 'flex';
642
+
643
+ renderImages();
644
+ });
645
+ });
646
+
647
+ // Keyboard navigation
648
+ document.addEventListener('keydown', (e) => {
649
+ if (e.key === 'ArrowLeft') {
650
+ currentPromptIndex = (currentPromptIndex - 1 + prompts.length) % prompts.length;
651
+ renderPrompt();
652
+ } else if (e.key === 'ArrowRight') {
653
+ currentPromptIndex = (currentPromptIndex + 1) % prompts.length;
654
+ renderPrompt();
655
+ } else if (e.key === 'ArrowUp' && viewMode === 'single') {
656
+ currentModelIndex = Math.min(currentModelIndex + 1, models.length - 1);
657
+ updateTimeline();
658
+ renderImages();
659
+ } else if (e.key === 'ArrowDown' && viewMode === 'single') {
660
+ currentModelIndex = Math.max(currentModelIndex - 1, 0);
661
+ updateTimeline();
662
+ renderImages();
663
+ }
664
+ });
665
+ }
666
+
667
+ // Start
668
+ init();
669
+ </script>
670
+ </body>
671
+ </html>