XXXMARK commited on
Commit
918bcc1
·
verified ·
1 Parent(s): a0314d6

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +741 -618
index.html CHANGED
@@ -1,642 +1,765 @@
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>FLUX KLEIN | Next-Gen Generative Interface</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Inter:wght@300;400;500;600&display=swap" rel="stylesheet">
9
- <style>
10
- :root {
11
- --neon-cyan: #00f3ff;
12
- --neon-pink: #ff00aa;
13
- --neon-purple: #bc13fe;
14
- --glass-bg: rgba(10, 10, 15, 0.7);
15
- --glass-border: rgba(255, 255, 255, 0.1);
16
- }
17
-
18
- body {
19
- font-family: 'Inter', sans-serif;
20
- background-color: #050505;
21
- color: #e0e0e0;
22
- overflow: hidden;
23
- }
24
-
25
- h1, h2, h3, .brand-font {
26
- font-family: 'Space Grotesk', sans-serif;
27
- }
28
-
29
- /* Custom Scrollbar */
30
- ::-webkit-scrollbar {
31
- width: 6px;
32
- }
33
- ::-webkit-scrollbar-track {
34
- background: #0a0a0a;
35
- }
36
- ::-webkit-scrollbar-thumb {
37
- background: #333;
38
- border-radius: 3px;
39
- }
40
- ::-webkit-scrollbar-thumb:hover {
41
- background: var(--neon-cyan);
42
- }
43
-
44
- /* Glassmorphism Utilities */
45
- .glass-panel {
46
- background: var(--glass-bg);
47
- backdrop-filter: blur(12px);
48
- -webkit-backdrop-filter: blur(12px);
49
- border: 1px solid var(--glass-border);
50
- box-shadow: 0 4px 30px rgba(0, 0, 0, 0.5);
51
- }
52
-
53
- .glass-input {
54
- background: rgba(0, 0, 0, 0.4);
55
- border: 1px solid rgba(255, 255, 255, 0.1);
56
- transition: all 0.3s ease;
57
- }
58
- .glass-input:focus {
59
- border-color: var(--neon-cyan);
60
- box-shadow: 0 0 15px rgba(0, 243, 255, 0.2);
61
- outline: none;
62
- }
63
-
64
- /* Animations */
65
- @keyframes pulse-glow {
66
- 0%, 100% { box-shadow: 0 0 10px rgba(0, 243, 255, 0.2); }
67
- 50% { box-shadow: 0 0 25px rgba(0, 243, 255, 0.6); }
68
- }
69
-
70
- @keyframes scanline {
71
- 0% { transform: translateY(-100%); }
72
- 100% { transform: translateY(100%); }
73
- }
74
-
75
- .scanline-overlay {
76
- position: absolute;
77
- top: 0;
78
- left: 0;
79
- width: 100%;
80
- height: 100%;
81
- background: linear-gradient(to bottom, transparent 50%, rgba(0, 0, 0, 0.3) 51%);
82
- background-size: 100% 4px;
83
- pointer-events: none;
84
- z-index: 10;
85
- }
86
 
87
- .crt-flicker {
88
- animation: flicker 0.15s infinite;
89
- }
90
-
91
- @keyframes flicker {
92
- 0% { opacity: 0.97; }
93
- 50% { opacity: 1; }
94
- 100% { opacity: 0.98; }
95
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
- /* Loader */
98
- .loader-ring {
99
- display: inline-block;
100
- position: relative;
101
- width: 24px;
102
- height: 24px;
103
- }
104
- .loader-ring div {
105
- box-sizing: border-box;
106
- display: block;
107
- position: absolute;
108
- width: 20px;
109
- height: 20px;
110
- margin: 2px;
111
- border: 2px solid var(--neon-cyan);
112
- border-radius: 50%;
113
- animation: loader-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
114
- border-color: var(--neon-cyan) transparent transparent transparent;
115
- }
116
- .loader-ring div:nth-child(1) { animation-delay: -0.45s; }
117
- .loader-ring div:nth-child(2) { animation-delay: -0.3s; }
118
- .loader-ring div:nth-child(3) { animation-delay: -0.15s; }
119
- @keyframes loader-ring {
120
- 0% { transform: rotate(0deg); }
121
- 100% { transform: rotate(360deg); }
122
- }
123
 
124
- /* Range Slider Styling */
125
- input[type=range] {
126
- -webkit-appearance: none;
127
- width: 100%;
128
- background: transparent;
129
- }
130
- input[type=range]::-webkit-slider-thumb {
131
- -webkit-appearance: none;
132
- height: 16px;
133
- width: 16px;
134
- border-radius: 50%;
135
- background: var(--neon-cyan);
136
- cursor: pointer;
137
- margin-top: -6px;
138
- box-shadow: 0 0 10px var(--neon-cyan);
139
- }
140
- input[type=range]::-webkit-slider-runnable-track {
141
- width: 100%;
142
- height: 4px;
143
- cursor: pointer;
144
- background: #333;
145
- border-radius: 2px;
146
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
- /* Grid Background */
149
- .bg-grid {
150
- background-size: 40px 40px;
151
- background-image: linear-gradient(to right, rgba(255, 255, 255, 0.03) 1px, transparent 1px),
152
- linear-gradient(to bottom, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
153
- mask-image: radial-gradient(circle at center, black 40%, transparent 100%);
154
- }
 
 
 
 
 
 
 
 
 
155
 
156
- .layer-active {
157
- border-color: var(--neon-cyan);
158
- background: rgba(0, 243, 255, 0.1);
159
- }
160
- </style>
161
- </head>
162
- <body class="h-screen w-screen flex flex-col text-sm selection:bg-cyan-500 selection:text-black">
 
 
 
 
163
 
164
- <!-- Background Canvas for Particles -->
165
- <canvas id="bgCanvas" class="fixed top-0 left-0 w-full h-full -z-10"></canvas>
166
- <div class="fixed top-0 left-0 w-full h-full bg-grid -z-10 pointer-events-none"></div>
 
 
 
 
 
 
 
 
 
 
167
 
168
- <!-- Header -->
169
- <header class="h-16 glass-panel border-b border-white/10 flex items-center justify-between px-6 z-20 shrink-0">
170
- <div class="flex items-center gap-3">
171
- <div class="w-8 h-8 rounded bg-gradient-to-br from-cyan-500 to-blue-600 flex items-center justify-center shadow-[0_0_15px_rgba(0,243,255,0.5)]">
172
- <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
173
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.384-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
174
- </svg>
175
  </div>
176
  <div>
177
- <h1 class="text-xl font-bold tracking-wider text-white">FLUX <span class="text-cyan-400">KLEIN</span></h1>
178
- <p class="text-[10px] text-gray-400 uppercase tracking-[0.2em]">Generative Synthesis Core v4.2</p>
 
 
 
 
179
  </div>
180
- </div>
181
-
182
- <div class="hidden md:flex items-center gap-6">
183
- <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="text-xs text-gray-400 hover:text-cyan-400 transition-colors border border-gray-700 px-3 py-1 rounded-full hover:border-cyan-400">
184
- Built with anycoder
185
- </a>
186
- <div class="flex items-center gap-2 text-xs text-gray-400">
187
- <span class="w-2 h-2 rounded-full bg-green-500 animate-pulse"></span>
188
- SYSTEM ONLINE
 
 
 
189
  </div>
 
190
  </div>
191
- </header>
192
-
193
- <!-- Main Workspace -->
194
- <main class="flex-1 flex overflow-hidden relative z-10">
195
-
196
- <!-- Left Control Panel -->
197
- <aside class="w-80 glass-panel border-r border-white/10 flex flex-col overflow-y-auto shrink-0 transition-all duration-300" id="sidebar">
198
-
199
- <!-- Prompt Section -->
200
- <div class="p-5 border-b border-white/5">
201
- <label class="flex justify-between text-xs font-semibold text-cyan-400 mb-2 uppercase tracking-wider">
202
- <span>Input Prompt</span>
203
- <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
204
- </label>
205
- <textarea id="promptInput" class="w-full h-24 glass-input rounded p-3 text-gray-200 placeholder-gray-600 resize-none focus:ring-1 focus:ring-cyan-500" placeholder="Describe your vision here... (e.g., Cyberpunk city in neon rain)"></textarea>
206
-
207
- <div class="mt-3 flex gap-2">
208
- <button onclick="randomizePrompt()" class="flex-1 py-1.5 text-xs border border-white/10 rounded hover:bg-white/5 text-gray-400 transition-colors">Randomize</button>
209
- <button onclick="clearPrompt()" class="flex-1 py-1.5 text-xs border border-white/10 rounded hover:bg-white/5 text-gray-400 transition-colors">Clear</button>
210
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
  </div>
212
-
213
- <!-- Reference Layers -->
214
- <div class="p-5 border-b border-white/5">
215
- <label class="text-xs font-semibold text-purple-400 mb-3 uppercase tracking-wider block">Reference Layers</label>
216
-
217
- <div class="space-y-3">
218
- <!-- Layer Main -->
219
- <div class="group relative">
220
- <div class="flex items-center justify-between mb-1">
221
- <span class="text-xs text-gray-300">Main Structure</span>
222
- <span class="text-[10px] text-gray-500" id="main-val">80%</span>
223
- </div>
224
- <input type="range" min="0" max="100" value="80" class="w-full" oninput="updateLayer('main', this.value)">
225
- <div class="h-1 w-full bg-gray-800 rounded mt-1 overflow-hidden">
226
- <div id="bar-main" class="h-full bg-purple-500 transition-all duration-100" style="width: 80%"></div>
227
- </div>
228
- </div>
229
-
230
- <!-- Layer Aux A -->
231
- <div class="group relative">
232
- <div class="flex items-center justify-between mb-1">
233
- <span class="text-xs text-gray-300">Auxiliary A (Texture)</span>
234
- <span class="text-[10px] text-gray-500" id="auxa-val">45%</span>
235
- </div>
236
- <input type="range" min="0" max="100" value="45" class="w-full" oninput="updateLayer('auxa', this.value)">
237
- <div class="h-1 w-full bg-gray-800 rounded mt-1 overflow-hidden">
238
- <div id="bar-auxa" class="h-full bg-pink-500 transition-all duration-100" style="width: 45%"></div>
239
- </div>
240
- </div>
241
-
242
- <!-- Layer Aux B -->
243
- <div class="group relative">
244
- <div class="flex items-center justify-between mb-1">
245
- <span class="text-xs text-gray-300">Auxiliary B (Lighting)</span>
246
- <span class="text-[10px] text-gray-500" id="auxb-val">60%</span>
247
- </div>
248
- <input type="range" min="0" max="100" value="60" class="w-full" oninput="updateLayer('auxb', this.value)">
249
- <div class="h-1 w-full bg-gray-800 rounded mt-1 overflow-hidden">
250
- <div id="bar-auxb" class="h-full bg-cyan-500 transition-all duration-100" style="width: 60%"></div>
251
- </div>
252
- </div>
253
- </div>
254
  </div>
255
-
256
- <!-- Advanced Params -->
257
- <div class="p-5">
258
- <label class="text-xs font-semibold text-gray-400 mb-3 uppercase tracking-wider block">Synthesis Parameters</label>
259
- <div class="grid grid-cols-2 gap-3">
260
- <div>
261
- <label class="text-[10px] text-gray-500 block mb-1">Seed</label>
262
- <input type="number" id="seedInput" class="w-full glass-input rounded px-2 py-1 text-xs text-gray-300" value="10294">
263
- </div>
264
- <div>
265
- <label class="text-[10px] text-gray-500 block mb-1">Guidance</label>
266
- <select class="w-full glass-input rounded px-2 py-1 text-xs text-gray-300 bg-black">
267
- <option>Standard</option>
268
- <option>High Fidelity</option>
269
- <option>Abstract</option>
270
- </select>
271
- </div>
272
- </div>
273
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
 
275
- <div class="mt-auto p-5">
276
- <button id="generateBtn" onclick="startGeneration()" class="w-full group relative overflow-hidden rounded bg-gradient-to-r from-cyan-600 to-blue-600 p-3 text-white font-bold tracking-widest uppercase transition-all hover:shadow-[0_0_20px_rgba(0,243,255,0.4)] active:scale-95">
277
- <span class="relative z-10 flex items-center justify-center gap-2">
278
- Execute Synthesis
279
- <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 group-hover:translate-x-1 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" /></svg>
280
- </span>
281
- <div class="absolute inset-0 bg-white/20 translate-y-full group-hover:translate-y-0 transition-transform duration-300"></div>
282
- </button>
283
- </div>
284
- </aside>
285
-
286
- <!-- Center Canvas Area -->
287
- <section class="flex-1 relative bg-black/40 flex flex-col">
288
- <!-- Toolbar -->
289
- <div class="h-10 border-b border-white/5 flex items-center justify-between px-4 bg-black/20">
290
- <div class="flex items-center gap-4">
291
- <span class="text-xs text-gray-500">CANVAS: <span class="text-gray-300">1024x1024</span></span>
292
- <span class="text-xs text-gray-500">MODE: <span class="text-cyan-400">REALTIME</span></span>
293
- </div>
294
- <div class="flex items-center gap-2">
295
- <button onclick="downloadImage()" class="p-1.5 rounded hover:bg-white/10 text-gray-400 hover:text-white transition-colors" title="Download">
296
- <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /></svg>
297
- </button>
298
- <button onclick="resetCanvas()" class="p-1.5 rounded hover:bg-white/10 text-gray-400 hover:text-white transition-colors" title="Reset">
299
- <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" /></svg>
300
- </button>
301
- </div>
302
- </div>
303
 
304
- <!-- The Canvas -->
305
- <div class="flex-1 relative flex items-center justify-center p-8 overflow-hidden" id="canvasContainer">
306
- <div class="relative w-full max-w-3xl aspect-square shadow-2xl border border-white/10 bg-black group">
307
- <!-- Scanlines -->
308
- <div class="scanline-overlay opacity-20"></div>
309
-
310
- <!-- Actual Drawing Canvas -->
311
- <canvas id="artCanvas" width="1024" height="1024" class="w-full h-full object-contain crt-flicker"></canvas>
312
-
313
- <!-- Overlay UI -->
314
- <div id="canvasOverlay" class="absolute inset-0 flex flex-col items-center justify-center bg-black/80 backdrop-blur-sm transition-opacity duration-500 z-20">
315
- <div class="text-cyan-400 font-mono text-xs mb-2 tracking-widest">READY TO INITIALIZE</div>
316
- <div class="text-gray-500 text-xs">Awaiting Input Stream...</div>
317
- </div>
318
-
319
- <!-- Loading State -->
320
- <div id="loadingState" class="absolute inset-0 flex flex-col items-center justify-center bg-black/90 z-30 hidden">
321
- <div class="loader-ring mb-4"><div></div><div></div><div></div><div></div></div>
322
- <div class="text-cyan-400 font-mono text-xs tracking-widest animate-pulse">SYNTHESIZING NEURAL PATHWAYS...</div>
323
- <div class="w-64 h-1 bg-gray-800 mt-4 rounded overflow-hidden">
324
- <div id="progressBar" class="h-full bg-cyan-500 w-0 transition-all duration-100"></div>
325
- </div>
326
- <div id="statusText" class="text-[10px] text-gray-500 mt-2 font-mono">Initializing tensors...</div>
327
- </div>
328
- </div>
329
- </div>
330
- </section>
 
 
 
 
 
 
 
 
 
 
 
 
331
 
332
- <!-- Right Archives Panel -->
333
- <aside class="w-64 glass-panel border-l border-white/10 flex flex-col shrink-0 hidden lg:flex">
334
- <div class="p-4 border-b border-white/10 flex justify-between items-center">
335
- <h3 class="text-xs font-bold text-gray-300 uppercase tracking-wider">Archives</h3>
336
- <span class="text-[10px] bg-white/10 px-2 py-0.5 rounded text-gray-400">12 Items</span>
 
 
 
 
 
 
 
 
 
 
337
  </div>
338
-
339
- <div class="flex-1 overflow-y-auto p-3 space-y-3" id="archiveList">
340
- <!-- Archive Item Template -->
341
- <div class="group relative aspect-square rounded border border-white/5 bg-black/40 overflow-hidden cursor-pointer hover:border-cyan-500/50 transition-all">
342
- <img src="https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?q=80&w=400&auto=format&fit=crop" class="w-full h-full object-cover opacity-60 group-hover:opacity-100 transition-opacity grayscale group-hover:grayscale-0">
343
- <div class="absolute bottom-0 left-0 w-full bg-gradient-to-t from-black to-transparent p-2">
344
- <div class="text-[10px] text-white truncate">Neon Genesis</div>
345
- <div class="text-[9px] text-gray-500">02:14 PM</div>
346
- </div>
347
- </div>
348
- <div class="group relative aspect-square rounded border border-white/5 bg-black/40 overflow-hidden cursor-pointer hover:border-cyan-500/50 transition-all">
349
- <img src="https://images.unsplash.com/photo-1633167606207-d840b5070fc2?q=80&w=400&auto=format&fit=crop" class="w-full h-full object-cover opacity-60 group-hover:opacity-100 transition-opacity grayscale group-hover:grayscale-0">
350
- <div class="absolute bottom-0 left-0 w-full bg-gradient-to-t from-black to-transparent p-2">
351
- <div class="text-[10px] text-white truncate">Quantum Flux</div>
352
- <div class="text-[9px] text-gray-500">Yesterday</div>
353
- </div>
354
- </div>
355
  </div>
356
- </aside>
357
-
358
- </main>
359
-
360
- <script>
361
- // --- Configuration & State ---
362
- const canvas = document.getElementById('artCanvas');
363
- const ctx = canvas.getContext('2d');
364
- const bgCanvas = document.getElementById('bgCanvas');
365
- const bgCtx = bgCanvas.getContext('2d');
366
-
367
- let state = {
368
- prompt: '',
369
- layers: {
370
- main: 80,
371
- auxa: 45,
372
- auxb: 60
373
- },
374
- seed: 10294,
375
- isGenerating: false
376
- };
377
-
378
- const prompts = [
379
- "Cybernetic organism in a rain-soaked metropolis",
380
- "Abstract geometric landscape floating in void",
381
- "Bioluminescent forest at midnight",
382
- "Retro-futuristic car speeding through neon tunnel",
383
- "Crystalline structure reflecting aurora borealis"
384
- ];
385
-
386
- // --- Initialization ---
387
- function resizeCanvases() {
388
- bgCanvas.width = window.innerWidth;
389
- bgCanvas.height = window.innerHeight;
390
- // Art canvas stays fixed logical size but scales via CSS
391
- }
392
- window.addEventListener('resize', resizeCanvases);
393
- resizeCanvases();
394
-
395
- // --- Particle System for Background ---
396
- const particles = [];
397
- class Particle {
398
- constructor() {
399
- this.x = Math.random() * bgCanvas.width;
400
- this.y = Math.random() * bgCanvas.height;
401
- this.vx = (Math.random() - 0.5) * 0.5;
402
- this.vy = (Math.random() - 0.5) * 0.5;
403
- this.size = Math.random() * 2;
404
- this.color = Math.random() > 0.5 ? 'rgba(0, 243, 255, ' : 'rgba(188, 19, 254, ';
405
- }
406
- update() {
407
- this.x += this.vx;
408
- this.y += this.vy;
409
- if (this.x < 0 || this.x > bgCanvas.width) this.vx *= -1;
410
- if (this.y < 0 || this.y > bgCanvas.height) this.vy *= -1;
411
- }
412
- draw() {
413
- bgCtx.beginPath();
414
- bgCtx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
415
- bgCtx.fillStyle = this.color + (Math.random() * 0.5 + 0.1) + ')';
416
- bgCtx.fill();
417
- }
418
- }
419
-
420
- for (let i = 0; i < 50; i++) particles.push(new Particle());
421
-
422
- function animateBg() {
423
- bgCtx.clearRect(0, 0, bgCanvas.width, bgCanvas.height);
424
- particles.forEach(p => {
425
- p.update();
426
- p.draw();
427
- });
428
-
429
- // Draw connecting lines
430
- bgCtx.strokeStyle = 'rgba(255,255,255,0.03)';
431
- bgCtx.lineWidth = 1;
432
- for(let i=0; i<particles.length; i++) {
433
- for(let j=i; j<particles.length; j++) {
434
- const dx = particles[i].x - particles[j].x;
435
- const dy = particles[i].y - particles[j].y;
436
- const dist = Math.sqrt(dx*dx + dy*dy);
437
- if(dist < 150) {
438
- bgCtx.beginPath();
439
- bgCtx.moveTo(particles[i].x, particles[i].y);
440
- bgCtx.lineTo(particles[j].x, particles[j].y);
441
- bgCtx.stroke();
442
- }
443
- }
444
- }
445
- requestAnimationFrame(animateBg);
446
- }
447
- animateBg();
448
-
449
- // --- UI Logic ---
450
- function randomizePrompt() {
451
- const r = Math.floor(Math.random() * prompts.length);
452
- document.getElementById('promptInput').value = prompts[r];
453
- }
454
-
455
- function clearPrompt() {
456
- document.getElementById('promptInput').value = '';
457
- }
458
-
459
- function updateLayer(id, val) {
460
- state.layers[id] = parseInt(val);
461
- document.getElementById(`${id}-val`).innerText = val + '%';
462
- document.getElementById(`bar-${id}`).style.width = val + '%';
463
- }
464
-
465
- // --- Generative Art Engine (The Core) ---
466
-
467
- // Seeded Random Number Generator
468
- function seededRandom(seed) {
469
- var x = Math.sin(seed++) * 10000;
470
- return x - Math.floor(x);
471
- }
472
-
473
- function generateArt() {
474
- const width = canvas.width;
475
- const height = canvas.height;
476
- const seed = parseInt(document.getElementById('seedInput').value) || 1234;
477
-
478
- // Clear
479
- ctx.fillStyle = '#000000';
480
- ctx.fillRect(0, 0, width, height);
481
-
482
- // 1. Base Noise / Gradient (Main Layer)
483
- if (state.layers.main > 0) {
484
- const opacity = state.layers.main / 100;
485
- for (let i = 0; i < 400; i++) {
486
- const x = seededRandom(seed + i) * width;
487
- const y = seededRandom(seed + i + 1000) * height;
488
- const r = seededRandom(seed + i + 2000) * (state.layers.main * 3);
489
-
490
- const hue = seededRandom(seed + i + 3000) * 360;
491
- ctx.beginPath();
492
- ctx.arc(x, y, r, 0, Math.PI * 2);
493
- ctx.fillStyle = `hsla(${hue}, 70%, 50%, ${opacity * 0.05})`;
494
- ctx.fill();
495
- }
496
- }
497
-
498
- // 2. Geometric Structures (Aux A - Texture)
499
- if (state.layers.auxa > 0) {
500
- const count = state.layers.auxa * 2;
501
- ctx.lineWidth = 2;
502
- for (let i = 0; i < count; i++) {
503
- const x = seededRandom(seed + i + 4000) * width;
504
- const y = seededRandom(seed + i + 5000) * height;
505
- const s = seededRandom(seed + i + 6000) * 200;
506
-
507
- ctx.strokeStyle = `rgba(255, 0, 170, ${state.layers.auxa/200})`;
508
- ctx.beginPath();
509
- if (seededRandom(seed + i + 7000) > 0.5) {
510
- ctx.rect(x, y, s, s);
511
- } else {
512
- ctx.moveTo(x, y);
513
- ctx.lineTo(x + s, y + s);
514
- ctx.lineTo(x - s, y + s);
515
- ctx.closePath();
516
- }
517
- ctx.stroke();
518
- }
519
- }
520
-
521
- // 3. Light Beams / Flow Fields (Aux B - Lighting)
522
- if (state.layers.auxb > 0) {
523
- ctx.globalCompositeOperation = 'screen';
524
- const beams = state.layers.auxb / 2;
525
- for (let i = 0; i < beams; i++) {
526
- const x = seededRandom(seed + i + 8000) * width;
527
- const y = seededRandom(seed + i + 9000) * height;
528
- const angle = seededRandom(seed + i + 10000) * Math.PI * 2;
529
- const len = seededRandom(seed + i + 11000) * 500 + 200;
530
-
531
- const grad = ctx.createLinearGradient(x, y, x + Math.cos(angle)*len, y + Math.sin(angle)*len);
532
- grad.addColorStop(0, `rgba(0, 243, 255, 0)`);
533
- grad.addColorStop(0.5, `rgba(0, 243, 255, ${state.layers.auxb/150})`);
534
- grad.addColorStop(1, `rgba(0, 243, 255, 0)`);
535
-
536
- ctx.strokeStyle = grad;
537
- ctx.lineWidth = seededRandom(seed + i + 12000) * 20 + 5;
538
- ctx.beginPath();
539
- ctx.moveTo(x, y);
540
- ctx.lineTo(x + Math.cos(angle)*len, y + Math.sin(angle)*len);
541
- ctx.stroke();
542
- }
543
- ctx.globalCompositeOperation = 'source-over';
544
- }
545
-
546
- // 4. Glitch / Digital Artifact Overlay
547
- if (Math.random() > 0.7) {
548
- for(let i=0; i<10; i++) {
549
- const y = Math.random() * height;
550
- const h = Math.random() * 20 + 2;
551
- ctx.fillStyle = `rgba(255, 255, 255, ${Math.random() * 0.1})`;
552
- ctx.fillRect(0, y, width, h);
553
- }
554
- }
555
- }
556
-
557
- // --- Execution Logic ---
558
- async function startGeneration() {
559
- if (state.isGenerating) return;
560
-
561
- const btn = document.getElementById('generateBtn');
562
- const overlay = document.getElementById('canvasOverlay');
563
- const loader = document.getElementById('loadingState');
564
- const progressBar = document.getElementById('progressBar');
565
- const statusText = document.getElementById('statusText');
566
-
567
- // UI Updates
568
- state.isGenerating = true;
569
- btn.disabled = true;
570
- btn.classList.add('opacity-50', 'cursor-not-allowed');
571
- overlay.style.opacity = '0';
572
- setTimeout(() => overlay.style.display = 'none', 500);
573
-
574
- loader.classList.remove('hidden');
575
-
576
- // Simulation Steps
577
- const steps = [
578
- { pct: '10%', msg: 'Parsing semantic tokens...' },
579
- { pct: '35%', msg: 'Allocating GPU tensors...' },
580
- { pct: '60%', msg: 'Diffusing latent space...' },
581
- { pct: '85%', msg: 'Refining edges...' },
582
- { pct: '100%', msg: 'Finalizing render...' }
583
- ];
584
-
585
- for (let step of steps) {
586
- await new Promise(r => setTimeout(r, 600 + Math.random() * 800));
587
- progressBar.style.width = step.pct;
588
- statusText.innerText = step.msg;
589
- }
590
-
591
- // Render Actual Image
592
- generateArt();
593
- addToArchive();
594
-
595
- // Cleanup
596
- await new Promise(r => setTimeout(r, 500));
597
- loader.classList.add('hidden');
598
- progressBar.style.width = '0';
599
-
600
- btn.disabled = false;
601
- btn.classList.remove('opacity-50', 'cursor-not-allowed');
602
- state.isGenerating = false;
603
- }
604
-
605
- function resetCanvas() {
606
- ctx.fillStyle = '#000000';
607
- ctx.fillRect(0, 0, canvas.width, canvas.height);
608
- document.getElementById('canvasOverlay').style.display = 'flex';
609
- document.getElementById('canvasOverlay').style.opacity = '1';
610
- }
611
-
612
- function downloadImage() {
613
- const link = document.createElement('a');
614
- link.download = `flux-klein-gen-${Date.now()}.png`;
615
- link.href = canvas.toDataURL();
616
- link.click();
617
- }
618
-
619
- function addToArchive() {
620
- const list = document.getElementById('archiveList');
621
- const dataUrl = canvas.toDataURL();
622
- const promptText = document.getElementById('promptInput').value || "Untitled Generation";
623
-
624
- const div = document.createElement('div');
625
- div.className = "group relative aspect-square rounded border border-white/5 bg-black/40 overflow-hidden cursor-pointer hover:border-cyan-500/50 transition-all animate-[pulse-glow_0.5s_ease-out]";
626
- div.innerHTML = `
627
- <img src="${dataUrl}" class="w-full h-full object-cover opacity-60 group-hover:opacity-100 transition-opacity grayscale group-hover:grayscale-0">
628
- <div class="absolute bottom-0 left-0 w-full bg-gradient-to-t from-black to-transparent p-2">
629
- <div class="text-[10px] text-white truncate">${promptText.substring(0, 15)}...</div>
630
- <div class="text-[9px] text-gray-500">Just now</div>
631
- </div>
632
- `;
633
-
634
- list.insertBefore(div, list.firstChild);
635
- }
636
 
637
- // Initial random prompt
638
- randomizePrompt();
 
 
 
 
 
 
 
 
 
 
 
639
 
640
- </script>
641
- </body>
642
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <!DOCTYPE html>
2
  <html lang="en">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>FLUX KLEIN | Next-Gen Generative Interface</title>
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Inter:wght@300;400;500;600&display=swap" rel="stylesheet">
10
+ <style>
11
+ :root {
12
+ --neon-cyan: #00f3ff;
13
+ --neon-pink: #ff00aa;
14
+ --neon-purple: #bc13fe;
15
+ --glass-bg: rgba(10, 10, 15, 0.7);
16
+ --glass-border: rgba(255, 255, 255, 0.1);
17
+ }
18
+
19
+ body {
20
+ font-family: 'Inter', sans-serif;
21
+ background-color: #050505;
22
+ color: #e0e0e0;
23
+ overflow: hidden;
24
+ }
25
+
26
+ h1,
27
+ h2,
28
+ h3,
29
+ .brand-font {
30
+ font-family: 'Space Grotesk', sans-serif;
31
+ }
32
+
33
+ /* Custom Scrollbar */
34
+ ::-webkit-scrollbar {
35
+ width: 6px;
36
+ }
37
+
38
+ ::-webkit-scrollbar-track {
39
+ background: #0a0a0a;
40
+ }
41
+
42
+ ::-webkit-scrollbar-thumb {
43
+ background: #333;
44
+ border-radius: 3px;
45
+ }
46
+
47
+ ::-webkit-scrollbar-thumb:hover {
48
+ background: var(--neon-cyan);
49
+ }
50
+
51
+ /* Glassmorphism Utilities */
52
+ .glass-panel {
53
+ background: var(--glass-bg);
54
+ backdrop-filter: blur(12px);
55
+ -webkit-backdrop-filter: blur(12px);
56
+ border: 1px solid var(--glass-border);
57
+ box-shadow: 0 4px 30px rgba(0, 0, 0, 0.5);
58
+ }
59
+
60
+ .glass-input {
61
+ background: rgba(0, 0, 0, 0.4);
62
+ border: 1px solid rgba(255, 255, 255, 0.1);
63
+ transition: all 0.3s ease;
64
+ }
65
+
66
+ .glass-input:focus {
67
+ border-color: var(--neon-cyan);
68
+ box-shadow: 0 0 15px rgba(0, 243, 255, 0.2);
69
+ outline: none;
70
+ }
71
+
72
+ /* Animations */
73
+ @keyframes pulse-glow {
74
+
75
+ 0%,
76
+ 100% {
77
+ box-shadow: 0 0 10px rgba(0, 243, 255, 0.2);
78
+ }
79
+
80
+ 50% {
81
+ box-shadow: 0 0 25px rgba(0, 243, 255, 0.6);
82
+ }
83
+ }
84
+
85
+ @keyframes scanline {
86
+ 0% {
87
+ transform: translateY(-100%);
88
+ }
89
+
90
+ 100% {
91
+ transform: translateY(100%);
92
+ }
93
+ }
94
+
95
+ .scanline-overlay {
96
+ position: absolute;
97
+ top: 0;
98
+ left: 0;
99
+ width: 100%;
100
+ height: 100%;
101
+ background: linear-gradient(to bottom, transparent 50%, rgba(0, 0, 0, 0.3) 51%);
102
+ background-size: 100% 4px;
103
+ pointer-events: none;
104
+ z-index: 10;
105
+ }
106
+
107
+ .crt-flicker {
108
+ animation: flicker 0.15s infinite;
109
+ }
110
+
111
+ @keyframes flicker {
112
+ 0% {
113
+ opacity: 0.97;
114
+ }
115
+
116
+ 50% {
117
+ opacity: 1;
118
+ }
119
+
120
+ 100% {
121
+ opacity: 0.98;
122
+ }
123
+ }
124
+
125
+ /* Loader */
126
+ .loader-ring {
127
+ display: inline-block;
128
+ position: relative;
129
+ width: 24px;
130
+ height: 24px;
131
+ }
132
+
133
+ .loader-ring div {
134
+ box-sizing: border-box;
135
+ display: block;
136
+ position: absolute;
137
+ width: 20px;
138
+ height: 20px;
139
+ margin: 2px;
140
+ border: 2px solid var(--neon-cyan);
141
+ border-radius: 50%;
142
+ animation: loader-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
143
+ border-color: var(--neon-cyan) transparent transparent transparent;
144
+ }
145
+
146
+ .loader-ring div:nth-child(1) {
147
+ animation-delay: -0.45s;
148
+ }
149
+
150
+ .loader-ring div:nth-child(2) {
151
+ animation-delay: -0.3s;
152
+ }
153
+
154
+ .loader-ring div:nth-child(3) {
155
+ animation-delay: -0.15s;
156
+ }
157
+
158
+ @keyframes loader-ring {
159
+ 0% {
160
+ transform: rotate(0deg);
161
+ }
162
+
163
+ 100% {
164
+ transform: rotate(360deg);
165
+ }
166
+ }
167
+
168
+ /* Range Slider Styling */
169
+ input[type=range] {
170
+ -webkit-appearance: none;
171
+ width: 100%;
172
+ background: transparent;
173
+ }
174
+
175
+ input[type=range]::-webkit-slider-thumb {
176
+ -webkit-appearance: none;
177
+ height: 16px;
178
+ width: 16px;
179
+ border-radius: 50%;
180
+ background: var(--neon-cyan);
181
+ cursor: pointer;
182
+ margin-top: -6px;
183
+ box-shadow: 0 0 10px var(--neon-cyan);
184
+ }
185
+
186
+ input[type=range]::-webkit-slider-runnable-track {
187
+ width: 100%;
188
+ height: 4px;
189
+ cursor: pointer;
190
+ background: #333;
191
+ border-radius: 2px;
192
+ }
193
+
194
+ /* Grid Background */
195
+ .bg-grid {
196
+ background-size: 40px 40px;
197
+ background-image: linear-gradient(to right, rgba(255, 255, 255, 0.03) 1px, transparent 1px),
198
+ linear-gradient(to bottom, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
199
+ mask-image: radial-gradient(circle at center, black 40%, transparent 100%);
200
+ }
201
+
202
+ .layer-active {
203
+ border-color: var(--neon-cyan);
204
+ background: rgba(0, 243, 255, 0.1);
205
+ }
206
+
207
+ /* Guide Modal Styles */
208
+ .guide-modal {
209
+ position: fixed;
210
+ inset: 0;
211
+ background: rgba(0, 0, 0, 0.85);
212
+ backdrop-filter: blur(8px);
213
+ z-index: 100;
214
+ display: flex;
215
+ align-items: center;
216
+ justify-content: center;
217
+ opacity: 0;
218
+ pointer-events: none;
219
+ transition: opacity 0.3s ease;
220
+ }
221
+
222
+ .guide-modal.active {
223
+ opacity: 1;
224
+ pointer-events: auto;
225
+ }
226
+
227
+ .guide-content {
228
+ max-height: 80vh;
229
+ overflow-y: auto;
230
+ }
231
+
232
+ /* Scroll indicator */
233
+ .scroll-indicator {
234
+ position: absolute;
235
+ bottom: 80px;
236
+ left: 50%;
237
+ transform: translateX(-50%);
238
+ width: 40px;
239
+ height: 40px;
240
+ border-radius: 50%;
241
+ background: linear-gradient(180deg, transparent 0%, rgba(0, 243, 255, 0.1) 100%);
242
+ display: flex;
243
+ align-items: center;
244
+ justify-content: center;
245
+ animation: bounce 2s infinite;
246
+ pointer-events: none;
247
+ opacity: 0;
248
+ transition: opacity 0.3s ease;
249
+ }
250
+
251
+ .scroll-indicator.visible {
252
+ opacity: 1;
253
+ }
254
+
255
+ @keyframes bounce {
256
+
257
+ 0%,
258
+ 100% {
259
+ transform: translateX(-50%) translateY(0);
260
+ }
261
+
262
+ 50% {
263
+ transform: translateX(-50%) translateY(-8px);
264
+ }
265
+ }
266
+
267
+ /* Custom scrollbar for sidebar */
268
+ .sidebar-scroll::-webkit-scrollbar {
269
+ width: 4px;
270
+ }
271
+
272
+ .sidebar-scroll::-webkit-scrollbar-track {
273
+ background: transparent;
274
+ }
275
+
276
+ .sidebar-scroll::-webkit-scrollbar-thumb {
277
+ background: rgba(0, 243, 255, 0.3);
278
+ border-radius: 2px;
279
+ }
280
+
281
+ .sidebar-scroll::-webkit-scrollbar-thumb:hover {
282
+ background: rgba(0, 243, 255, 0.6);
283
+ }
284
+ </style>
285
+ </head>
286
 
287
+ <body class="h-screen w-screen flex flex-col text-sm selection:bg-cyan-500 selection:text-black">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
 
289
+ <!-- Background Canvas for Particles -->
290
+ <canvas id="bgCanvas" class="fixed top-0 left-0 w-full h-full -z-10"></canvas>
291
+ <div class="fixed top-0 left-0 w-full h-full bg-grid -z-10 pointer-events-none"></div>
292
+
293
+ <!-- Header -->
294
+ <header class="h-16 glass-panel border-b border-white/10 flex items-center justify-between px-6 z-20 shrink-0">
295
+ <div class="flex items-center gap-3">
296
+ <div class="w-8 h-8 rounded bg-gradient-to-br from-cyan-500 to-blue-600 flex items-center justify-center shadow-[0_0_15px_rgba(0,243,255,0.5)]">
297
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
298
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.384-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
299
+ </svg>
300
+ </div>
301
+ <div>
302
+ <h1 class="text-xl font-bold tracking-wider text-white">FLUX <span class="text-cyan-400">KLEIN</span></h1>
303
+ <p class="text-[10px] text-gray-400 uppercase tracking-[0.2em]">Generative Synthesis Core v4.2</p>
304
+ </div>
305
+ </div>
306
+
307
+ <div class="hidden md:flex items-center gap-6">
308
+ <button onclick="toggleGuide()" class="flex items-center gap-2 text-xs text-cyan-400 hover:text-cyan-300 transition-colors border border-cyan-500/30 px-3 py-1.5 rounded-full hover:border-cyan-400 hover:bg-cyan-500/10">
309
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
310
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
311
+ </svg>
312
+ How to Use
313
+ </button>
314
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="text-xs text-gray-400 hover:text-cyan-400 transition-colors border border-gray-700 px-3 py-1 rounded-full hover:border-cyan-400">
315
+ Built with anycoder
316
+ </a>
317
+ <div class="flex items-center gap-2 text-xs text-gray-400">
318
+ <span class="w-2 h-2 rounded-full bg-green-500 animate-pulse"></span>
319
+ SYSTEM ONLINE
320
+ </div>
321
+ </div>
322
+ </header>
323
+
324
+ <!-- Main Workspace -->
325
+ <main class="flex-1 flex overflow-hidden relative z-10">
326
+
327
+ <!-- Left Control Panel -->
328
+ <aside class="w-80 glass-panel border-r border-white/10 flex flex-col shrink-0 transition-all duration-300 relative" id="sidebar">
329
+ <!-- Scrollable Content Area -->
330
+ <div class="flex-1 overflow-y-auto sidebar-scroll relative" id="sidebarContent">
331
+ <!-- Prompt Section -->
332
+ <div class="p-5 border-b border-white/5">
333
+ <label class="flex justify-between text-xs font-semibold text-cyan-400 mb-2 uppercase tracking-wider">
334
+ <span>Input Prompt</span>
335
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
336
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
337
+ </svg>
338
+ </label>
339
+ <textarea id="promptInput" class="w-full h-24 glass-input rounded p-3 text-gray-200 placeholder-gray-600 resize-none focus:ring-1 focus:ring-cyan-500" placeholder="Describe your vision here... (e.g., Cyberpunk city in neon rain)"></textarea>
340
+
341
+ <div class="mt-3 flex gap-2">
342
+ <button onclick="randomizePrompt()" class="flex-1 py-1.5 text-xs border border-white/10 rounded hover:bg-white/5 text-gray-400 transition-colors">Randomize</button>
343
+ <button onclick="clearPrompt()" class="flex-1 py-1.5 text-xs border border-white/10 rounded hover:bg-white/5 text-gray-400 transition-colors">Clear</button>
344
+ </div>
345
+ </div>
346
 
347
+ <!-- Reference Layers -->
348
+ <div class="p-5 border-b border-white/5">
349
+ <label class="text-xs font-semibold text-purple-400 mb-3 uppercase tracking-wider block">Reference Layers</label>
350
+
351
+ <div class="space-y-4">
352
+ <!-- Layer Main -->
353
+ <div class="group relative">
354
+ <div class="flex items-center justify-between mb-1">
355
+ <span class="text-xs text-gray-300">Main Structure</span>
356
+ <span class="text-[10px] text-gray-500" id="main-val">80%</span>
357
+ </div>
358
+ <input type="range" min="0" max="100" value="80" class="w-full" oninput="updateLayer('main', this.value)">
359
+ <div class="h-1 w-full bg-gray-800 rounded mt-1 overflow-hidden">
360
+ <div id="bar-main" class="h-full bg-purple-500 transition-all duration-100" style="width: 80%"></div>
361
+ </div>
362
+ </div>
363
 
364
+ <!-- Layer Aux A -->
365
+ <div class="group relative">
366
+ <div class="flex items-center justify-between mb-1">
367
+ <span class="text-xs text-gray-300">Auxiliary A (Texture)</span>
368
+ <span class="text-[10px] text-gray-500" id="auxa-val">45%</span>
369
+ </div>
370
+ <input type="range" min="0" max="100" value="45" class="w-full" oninput="updateLayer('auxa', this.value)">
371
+ <div class="h-1 w-full bg-gray-800 rounded mt-1 overflow-hidden">
372
+ <div id="bar-auxa" class="h-full bg-pink-500 transition-all duration-100" style="width: 45%"></div>
373
+ </div>
374
+ </div>
375
 
376
+ <!-- Layer Aux B -->
377
+ <div class="group relative">
378
+ <div class="flex items-center justify-between mb-1">
379
+ <span class="text-xs text-gray-300">Auxiliary B (Lighting)</span>
380
+ <span class="text-[10px] text-gray-500" id="auxb-val">60%</span>
381
+ </div>
382
+ <input type="range" min="0" max="100" value="60" class="w-full" oninput="updateLayer('auxb', this.value)">
383
+ <div class="h-1 w-full bg-gray-800 rounded mt-1 overflow-hidden">
384
+ <div id="bar-auxb" class="h-full bg-cyan-500 transition-all duration-100" style="width: 60%"></div>
385
+ </div>
386
+ </div>
387
+ </div>
388
+ </div>
389
 
390
+ <!-- Advanced Params -->
391
+ <div class="p-5 pb-24">
392
+ <label class="text-xs font-semibold text-gray-400 mb-3 uppercase tracking-wider block">Synthesis Parameters</label>
393
+ <div class="grid grid-cols-2 gap-3">
394
+ <div>
395
+ <label class="text-[10px] text-gray-500 block mb-1">Seed</label>
396
+ <input type="number" id="seedInput" class="w-full glass-input rounded px-2 py-1 text-xs text-gray-300" value="10294">
397
  </div>
398
  <div>
399
+ <label class="text-[10px] text-gray-500 block mb-1">Guidance</label>
400
+ <select class="w-full glass-input rounded px-2 py-1 text-xs text-gray-300 bg-black">
401
+ <option>Standard</option>
402
+ <option>High Fidelity</option>
403
+ <option>Abstract</option>
404
+ </select>
405
  </div>
406
+ </div>
407
+
408
+ <!-- Quick Tips -->
409
+ <div class="mt-5 p-3 rounded bg-cyan-500/5 border border-cyan-500/20">
410
+ <div class="flex items-start gap-2">
411
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-cyan-400 mt-0.5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
412
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
413
+ </svg>
414
+ <div>
415
+ <p class="text-[10px] text-cyan-300 font-medium mb-1">Pro Tip</p>
416
+ <p class="text-[10px] text-gray-400 leading-relaxed">Higher Main Structure values create denser base patterns. Combine with Auxiliary layers for complex results.</p>
417
+ </div>
418
  </div>
419
+ </div>
420
  </div>
421
+ </div>
422
+
423
+ <!-- Scroll Indicator -->
424
+ <div class="scroll-indicator visible" id="scrollIndicator">
425
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-cyan-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
426
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3" />
427
+ </svg>
428
+ </div>
429
+
430
+ <!-- Fixed Generate Button Area -->
431
+ <div class="absolute bottom-0 left-0 right-0 p-5 bg-gradient-to-t from-[#0a0a0f] via-[#0a0a0f] to-transparent pt-8">
432
+ <button id="generateBtn" onclick="startGeneration()" class="w-full group relative overflow-hidden rounded bg-gradient-to-r from-cyan-600 to-blue-600 p-3 text-white font-bold tracking-widest uppercase transition-all hover:shadow-[0_0_20px_rgba(0,243,255,0.4)] active:scale-95">
433
+ <span class="relative z-10 flex items-center justify-center gap-2">
434
+ Execute Synthesis
435
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 group-hover:translate-x-1 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor">
436
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
437
+ </svg>
438
+ </span>
439
+ <div class="absolute inset-0 bg-white/20 translate-y-full group-hover:translate-y-0 transition-transform duration-300"></div>
440
+ </button>
441
+ </div>
442
+ </aside>
443
+
444
+ <!-- Center Canvas Area -->
445
+ <section class="flex-1 relative bg-black/40 flex flex-col">
446
+ <!-- Toolbar -->
447
+ <div class="h-10 border-b border-white/5 flex items-center justify-between px-4 bg-black/20">
448
+ <div class="flex items-center gap-4">
449
+ <span class="text-xs text-gray-500">CANVAS: <span class="text-gray-300">1024x1024</span></span>
450
+ <span class="text-xs text-gray-500">MODE: <span class="text-cyan-400">REALTIME</span></span>
451
+ </div>
452
+ <div class="flex items-center gap-2">
453
+ <button onclick="downloadImage()" class="p-1.5 rounded hover:bg-white/10 text-gray-400 hover:text-white transition-colors" title="Download">
454
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
455
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
456
+ </svg>
457
+ </button>
458
+ <button onclick="resetCanvas()" class="p-1.5 rounded hover:bg-white/10 text-gray-400 hover:text-white transition-colors" title="Reset">
459
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
460
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
461
+ </svg>
462
+ </button>
463
+ </div>
464
+ </div>
465
+
466
+ <!-- The Canvas -->
467
+ <div class="flex-1 relative flex items-center justify-center p-8 overflow-hidden" id="canvasContainer">
468
+ <div class="relative w-full max-w-3xl aspect-square shadow-2xl border border-white/10 bg-black group">
469
+ <!-- Scanlines -->
470
+ <div class="scanline-overlay opacity-20"></div>
471
+
472
+ <!-- Actual Drawing Canvas -->
473
+ <canvas id="artCanvas" width="1024" height="1024" class="w-full h-full object-contain crt-flicker"></canvas>
474
+
475
+ <!-- Overlay UI -->
476
+ <div id="canvasOverlay" class="absolute inset-0 flex flex-col items-center justify-center bg-black/80 backdrop-blur-sm transition-opacity duration-500 z-20">
477
+ <div class="text-cyan-400 font-mono text-xs mb-2 tracking-widest">READY TO INITIALIZE</div>
478
+ <div class="text-gray-500 text-xs">Awaiting Input Stream...</div>
479
+ </div>
480
+
481
+ <!-- Loading State -->
482
+ <div id="loadingState" class="absolute inset-0 flex flex-col items-center justify-center bg-black/90 z-30 hidden">
483
+ <div class="loader-ring mb-4">
484
+ <div></div>
485
+ <div></div>
486
+ <div></div>
487
+ <div></div>
488
  </div>
489
+ <div class="text-cyan-400 font-mono text-xs tracking-widest animate-pulse">SYNTHESIZING NEURAL PATHWAYS...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
490
  </div>
491
+ <div class="w-64 h-1 bg-gray-800 mt-4 rounded overflow-hidden">
492
+ <div id="progressBar" class="h-full bg-cyan-500 w-0 transition-all duration-100"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
493
  </div>
494
+ <div id="statusText" class="text-[10px] text-gray-500 mt-2 font-mono">Initializing tensors...</div>
495
+ </div>
496
+ </div>
497
+ </div>
498
+ </section>
499
+
500
+ <!-- Right Archives Panel -->
501
+ <aside class="w-64 glass-panel border-l border-white/10 flex flex-col shrink-0 hidden lg:flex">
502
+ <div class="p-4 border-b border-white/10 flex justify-between items-center">
503
+ <h3 class="text-xs font-bold text-gray-300 uppercase tracking-wider">Archives</h3>
504
+ <span class="text-[10px] bg-white/10 px-2 py-0.5 rounded text-gray-400">12 Items</span>
505
+ </div>
506
+
507
+ <div class="flex-1 overflow-y-auto p-3 space-y-3" id="archiveList">
508
+ <!-- Archive Item Template -->
509
+ <div class="group relative aspect-square rounded border border-white/5 bg-black/40 overflow-hidden cursor-pointer hover:border-cyan-500/50 transition-all">
510
+ <img src="https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?q=80&w=400&auto=format&fit=crop" class="w-full h-full object-cover opacity-60 group-hover:opacity-100 transition-opacity grayscale group-hover:grayscale-0">
511
+ <div class="absolute bottom-0 left-0 w-full bg-gradient-to-t from-black to-transparent p-2">
512
+ <div class="text-[10px] text-white truncate">Neon Genesis</div>
513
+ <div class="text-[9px] text-gray-500">02:14 PM</div>
514
+ </div>
515
+ </div>
516
+ <div class="group relative aspect-square rounded border border-white/5 bg-black/40 overflow-hidden cursor-pointer hover:border-cyan-500/50 transition-all">
517
+ <img src="https://images.unsplash.com/photo-1633167606207-d840b5070fc2?q=80&w=400&auto=format&fit=crop" class="w-full h-full object-cover opacity-60 group-hover:opacity-100 transition-opacity grayscale group-hover:grayscale-0">
518
+ <div class="absolute bottom-0 left-0 w-full bg-gradient-to-t from-black to-transparent p-2">
519
+ <div class="text-[10px] text-white truncate">Quantum Flux</div>
520
+ <div class="text-[9px] text-gray-500">Yesterday</div>
521
+ </div>
522
+ </div>
523
+ </div>
524
+ </aside>
525
 
526
+ </main>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
527
 
528
+ <!-- How to Use Guide Modal -->
529
+ <div class="guide-modal" id="guideModal">
530
+ <div class="glass-panel rounded-lg w-full max-w-2xl mx-4 guide-content">
531
+ <div class="p-6 border-b border-white/10 flex items-center justify-between sticky top-0 bg-[#0a0a0f]/95 backdrop-blur-sm z-10">
532
+ <div class="flex items-center gap-3">
533
+ <div class="w-10 h-10 rounded-lg bg-gradient-to-br from-cyan-500 to-blue-600 flex items-center justify-center">
534
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
535
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
536
+ </svg>
537
+ </div>
538
+ <div>
539
+ <h2 class="text-lg font-bold text-white brand-font">How to Use FLUX KLEIN</h2>
540
+ <p class="text-xs text-gray-400">Complete guide to generative synthesis</p>
541
+ </div>
542
+ </div>
543
+ <button onclick="toggleGuide()" class="p-2 rounded-lg hover:bg-white/10 text-gray-400 hover:text-white transition-colors">
544
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
545
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
546
+ </svg>
547
+ </button>
548
+ </div>
549
+
550
+ <div class="p-6 space-y-6">
551
+ <!-- Quick Start -->
552
+ <div class="p-4 rounded-lg bg-cyan-500/5 border border-cyan-500/20">
553
+ <h3 class="text-sm font-semibold text-cyan-400 mb-2 flex items-center gap-2">
554
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
555
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
556
+ </svg>
557
+ Quick Start
558
+ </h3>
559
+ <ol class="text-xs text-gray-300 space-y-2 list-decimal list-inside leading-relaxed">
560
+ <li>Enter a descriptive prompt in the <strong>Input Prompt</strong> field (or click Randomize for inspiration)</li>
561
+ <li>Adjust the <strong>Reference Layers</strong> sliders to control visual complexity</li>
562
+ <li>Set your preferred <strong>Seed</strong> for reproducible results, or use random</li>
563
+ <li>Click <strong>Execute Synthesis</strong> to generate your artwork</li>
564
+ <li>Download or save to Archives when satisfied</li>
565
+ </ol>
566
+ </div>
567
 
568
+ <!-- Layer Controls -->
569
+ <div>
570
+ <h3 class="text-sm font-semibold text-purple-400 mb-3 flex items-center gap-2">
571
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
572
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
573
+ </svg>
574
+ Understanding Reference Layers
575
+ </h3>
576
+ <div class="grid gap-3">
577
+ <div class="p-3 rounded bg-white/5 border border-white/10">
578
+ <div class="flex items-center gap-2 mb-1">
579
+ <div class="w-3 h-3 rounded-full bg-purple-500"></div>
580
+ <span class="text-xs font-medium text-white">Main Structure</span>
581
+ </div>
582
+ <p class="text-[11px] text-gray-400">Controls the density and size of base noise patterns. Higher values create more complex, dense foundational imagery with larger organic shapes.</p>
583
  </div>
584
+ <div class="p-3 rounded bg-white/5 border border-white/10">
585
+ <div class="flex items-center gap-2 mb-1">
586
+ <div class="w-3 h-3 rounded-full bg-pink-500"></div>
587
+ <span class="text-xs font-medium text-white">Auxiliary A (Texture)</span>
588
+ </div>
589
+ <p class="text-[11px] text-gray-400">Adds geometric elements—squares, triangles, and lines. Perfect for creating structured, architectural, or crystalline effects.</p>
 
 
 
 
 
 
 
 
 
 
 
590
  </div>
591
+ <div class="p-3 rounded bg-white/5 border border-white/10">
592
+ <div class="flex items-center gap-2 mb-1">
593
+ <div class="w-3 h-3 rounded-full bg-cyan-500"></div>
594
+ <span class="text-xs font-medium text-white">Auxiliary B (Lighting)</span>
595
+ </div>
596
+ <p class="text-[11px] text-gray-400">Injects light beams and flow-field effects using screen blending. Creates ethereal glows, aurora-like streaks, and atmospheric depth.</p>
597
+ </div>
598
+ </div>
599
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
600
 
601
+ <!-- Parameters -->
602
+ <div>
603
+ <h3 class="text-sm font-semibold text-gray-300 mb-3 flex items-center gap-2">
604
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
605
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" />
606
+ </svg>
607
+ Synthesis Parameters
608
+ </h3>
609
+ <div class="space-y-2 text-xs text-gray-400">
610
+ <p><strong class="text-gray-300">Seed:</strong> A numerical starting point for the random generator. Same seed + same settings = identical output. Use this to refine or reproduce results.</p>
611
+ <p><strong class="text-gray-300">Guidance:</strong> Affects how strictly the algorithm follows internal rules. Standard is balanced; High Fidelity creates cleaner edges; Abstract embraces chaos.</p>
612
+ </div>
613
+ </div>
614
 
615
+ <!-- Tips -->
616
+ <div class="p-4 rounded-lg bg-gradient-to-r from-purple-500/10 to-pink-500/10 border border-purple-500/20">
617
+ <h3 class="text-sm font-semibold text-purple-300 mb-2 flex items-center gap-2">
618
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
619
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
620
+ </svg>
621
+ Pro Tips
622
+ </h3>
623
+ <ul class="text-xs text-gray-300 space-y-1.5 list-disc list-inside">
624
+ <li>Combine low Main Structure (20-30%) with high Auxiliary B for minimalist light paintings</li>
625
+ <li>Use similar seed values (e.g., 1000, 1001, 1002) to explore variations of a theme</li>
626
+ <li>All three layers at maximum create intense, maximalist compositions—great for album art</li>
627
+ <li>The Archives panel saves your last 20 generations automatically</li>
628
+ </ul>
629
+ </div>
630
+ </div>
631
+
632
+ <div class="p-6 border-t border-white/10 flex justify-end gap-3 sticky bottom-0 bg-[#0a0a0f]/95 backdrop-blur-sm">
633
+ <button onclick="toggleGuide()" class="px-4 py-2 text-xs text-gray-400 hover:text-white transition-colors">Close</button>
634
+ <button onclick="startTour(); toggleGuide();" class="px-4 py-2 text-xs bg-cyan-600 hover:bg-cyan-500 text-white rounded transition-colors flex items-center gap-2">
635
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
636
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
637
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
638
+ </svg>
639
+ Start Interactive Tour
640
+ </button>
641
+ </div>
642
+ </div>
643
+ </div>
644
+
645
+ <!-- Tour Overlay -->
646
+ <div class="fixed inset-0 z-50 pointer-events-none hidden" id="tourOverlay">
647
+ <div class="absolute inset-0 bg-black/50"></div>
648
+ <div class="absolute bg-cyan-500/20 border-2 border-cyan-400 rounded-lg transition-all duration-500" id="tourHighlight"></div>
649
+ <div class="absolute p-4 glass-panel rounded-lg max-w-xs transition-all duration-500" id="tourTooltip">
650
+ <p class="text-xs text-white mb-2" id="tourText"></p>
651
+ <button onclick="nextTourStep()" class="text-xs bg-cyan-600 hover:bg-cyan-500 text-white px-3 py-1 rounded transition-colors">Next</button>
652
+ </div>
653
+ </div>
654
+
655
+ <script>
656
+ // --- Configuration & State ---
657
+ const canvas = document.getElementById('artCanvas');
658
+ const ctx = canvas.getContext('2d');
659
+ const bgCanvas = document.getElementById('bgCanvas');
660
+ const bgCtx = bgCanvas.getContext('2d');
661
+ let state = {
662
+ prompt: '',
663
+ layers: {
664
+ main: 80,
665
+ auxa: 45,
666
+ auxb: 60
667
+ },
668
+ seed: 10294,
669
+ isGenerating: false
670
+ };
671
+ const prompts = [
672
+ "Cybernetic organism in a rain-soaked metropolis",
673
+ "Abstract geometric landscape floating in void",
674
+ "Bioluminescent forest at midnight",
675
+ "Retro-futuristic car speeding through neon tunnel",
676
+ "Crystalline structure reflecting aurora borealis"
677
+ ];
678
+ // --- Initialization ---
679
+ function resizeCanvases() {
680
+ bgCanvas.width = window.innerWidth;
681
+ bgCanvas.height = window.innerHeight;
682
+ // Art canvas stays fixed logical size but scales via CSS
683
+ }
684
+ window.addEventListener('resize', resizeCanvases);
685
+ resizeCanvases();
686
+ // --- Sidebar Scroll Detection ---
687
+ const sidebarContent = document.getElementById('sidebarContent');
688
+ const scrollIndicator = document.getElementById('scrollIndicator');
689
+
690
+ function updateScrollIndicator() {
691
+ const scrollTop = sidebarContent.scrollTop;
692
+ const scrollHeight = sidebarContent.scrollHeight - sidebarContent.clientHeight;
693
+ if (scrollTop >= scrollHeight - 10) {
694
+ scrollIndicator.classList.remove('visible');
695
+ } else {
696
+ scrollIndicator.classList.add('visible');
697
+ }
698
+ }
699
+ sidebarContent.addEventListener('scroll', updateScrollIndicator);
700
+ updateScrollIndicator();
701
+ // --- Particle System for Background ---
702
+ const particles = [];
703
+ class Particle {
704
+ constructor() {
705
+ this.x = Math.random() * bgCanvas.width;
706
+ this.y = Math.random() * bgCanvas.height;
707
+ this.vx = (Math.random() - 0.5) * 0.5;
708
+ this.vy = (Math.random() - 0.5) * 0.5;
709
+ this.size = Math.random() * 2;
710
+ this.color = Math.random() > 0.5 ? 'rgba(0, 243, 255, ' : 'rgba(188, 19, 254, ';
711
+ }
712
+ update() {
713
+ this.x += this.vx;
714
+ this.y += this.vy;
715
+ if (this.x < 0 || this.x > bgCanvas.width) this.vx *= -1;
716
+ if (this.y < 0 || this.y > bgCanvas.height) this.vy *= -1;
717
+ }
718
+ draw() {
719
+ bgCtx.beginPath();
720
+ bgCtx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
721
+ bgCtx.fillStyle = this.color + (Math.random() * 0.5 + 0.1) + ')';
722
+ bgCtx.fill();
723
+ }
724
+ }
725
+ for (let i = 0; i < 50; i++) particles.push(new Particle());
726
+
727
+ function animateBg() {
728
+ bgCtx.clearRect(0, 0, bgCanvas.width, bgCanvas.height);
729
+ particles.forEach(p => {
730
+ p.update();
731
+ p.draw();
732
+ });
733
+ // Draw connecting lines
734
+ bgCtx.strokeStyle = 'rgba(255,255,255,0.03)';
735
+ bgCtx.lineWidth = 1;
736
+ for (let i = 0; i < particles.length; i++) {
737
+ for (let j = i; j < particles.length; j++) {
738
+ const dx = particles[i].x - particles[j].x;
739
+ const dy = particles[i].y - particles[j].y;
740
+ const dist = Math.sqrt(dx * dx + dy * dy);
741
+ if (dist < 150) {
742
+ bgCtx.beginPath();
743
+ bgCtx.moveTo(particles[i].x, particles[i].y);
744
+ bgCtx.lineTo(particles[j].x, particles[j].y);
745
+ bgCtx.stroke();
746
+ }
747
+ }
748
+ }
749
+ requestAnimationFrame(animateBg);
750
+ }
751
+ animateBg();
752
+ // --- UI Logic ---
753
+ function randomizePrompt() {
754
+ const r = Math.floor(Math.random() * prompts.length);
755
+ document.getElementById('promptInput').value = prompts[r];
756
+ }
757
+
758
+ function clearPrompt() {
759
+ document.getElementById('promptInput').value = '';
760
+ }
761
+
762
+ function updateLayer(id, val) {
763
+ state.layers[id] = parseInt(val);
764
+ document.getElementById(`${id}-val`).innerText = val + '%';
765
+ document.getElementById(`bar-${id}`).style.width