AARIFSHABIR commited on
Commit
74815ad
·
verified ·
1 Parent(s): 98fa750

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +744 -586
index.html CHANGED
@@ -1,607 +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>Orbital UI Customizer</title>
7
-
8
- <!-- 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=Inter:wght@300;400;600;800&family=Space+Grotesk:wght@300;500;700&display=swap" rel="stylesheet">
12
-
13
- <!-- Icons -->
14
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
15
-
16
- <!-- Tailwind CSS -->
17
- <script src="https://cdn.tailwindcss.com"></script>
18
- <script>
19
- tailwind.config = {
20
- theme: {
21
- extend: {
22
- fontFamily: {
23
- sans: ['Inter', 'sans-serif'],
24
- display: ['Space Grotesk', 'sans-serif'],
25
- },
26
- colors: {
27
- brand: 'var(--brand-color)',
28
- surface: 'rgba(255, 255, 255, 0.05)',
29
- surfaceHover: 'rgba(255, 255, 255, 0.1)',
30
- }
31
- }
32
- }
33
- }
34
- </script>
35
-
36
- <style>
37
- /* CSS Variables for Dynamic Theming */
38
- :root {
39
- --brand-color: #6366f1;
40
- --bg-gradient-start: #0f172a;
41
- --bg-gradient-end: #1e293b;
42
- --glass-blur: 16px;
43
- --glass-opacity: 0.1;
44
- --border-radius: 1rem;
45
- --animation-speed: 20s;
46
- --glow-intensity: 0.5;
47
- }
48
-
49
- body {
50
- background: linear-gradient(135deg, var(--bg-gradient-start), var(--bg-gradient-end));
51
- color: white;
52
- overflow-x: hidden;
53
- transition: background 0.5s ease;
54
- }
55
-
56
- /* --- Custom Scrollbar --- */
57
- ::-webkit-scrollbar {
58
- width: 6px;
59
- }
60
- ::-webkit-scrollbar-track {
61
- background: rgba(0,0,0,0.2);
62
- }
63
- ::-webkit-scrollbar-thumb {
64
- background: var(--brand-color);
65
- border-radius: 10px;
66
- }
67
-
68
- /* --- 3D Orbital Scene --- */
69
- .scene-container {
70
- perspective: 1000px;
71
- width: 100%;
72
- height: 400px;
73
- display: flex;
74
- align-items: center;
75
- justify-content: center;
76
- position: relative;
77
- overflow: hidden;
78
- }
79
-
80
- .orbital-system {
81
- position: relative;
82
- width: 200px;
83
- height: 200px;
84
- transform-style: preserve-3d;
85
- animation: rotateSystem var(--animation-speed) linear infinite;
86
- }
87
-
88
- .planet {
89
- width: 100px;
90
- height: 100px;
91
- border-radius: 50%;
92
- background: radial-gradient(circle at 30% 30%, var(--brand-color), #000);
93
- box-shadow: 0 0 50px var(--brand-color);
94
- position: absolute;
95
- top: 50%;
96
- left: 50%;
97
- transform: translate(-50%, -50%);
98
- z-index: 10;
99
- transition: all 0.3s ease;
100
- }
101
-
102
- .orbit-ring {
103
- position: absolute;
104
- top: 50%;
105
- left: 50%;
106
- border: 2px solid rgba(255, 255, 255, 0.1);
107
- border-radius: 50%;
108
- transform: translate(-50%, -50%) rotateX(70deg);
109
- transform-style: preserve-3d;
110
- }
111
-
112
- .satellite {
113
- width: 20px;
114
- height: 20px;
115
- background: white;
116
- border-radius: 50%;
117
- position: absolute;
118
- top: -10px;
119
- left: 50%;
120
- transform: translateX(-50%) rotateX(-70deg);
121
- box-shadow: 0 0 15px white;
122
- }
123
-
124
- /* Dynamic Orbit Sizes */
125
- .ring-1 { width: 200px; height: 200px; animation: spin 10s linear infinite; }
126
- .ring-2 { width: 300px; height: 300px; animation: spin 15s linear infinite reverse; border-color: var(--brand-color); }
127
- .ring-3 { width: 400px; height: 400px; animation: spin 25s linear infinite; }
128
-
129
- @keyframes rotateSystem {
130
- 0% { transform: rotateY(0deg); }
131
- 100% { transform: rotateY(360deg); }
132
- }
133
-
134
- @keyframes spin {
135
- 0% { transform: translate(-50%, -50%) rotateX(70deg) rotateZ(0deg); }
136
- 100% { transform: translate(-50%, -50%) rotateX(70deg) rotateZ(360deg); }
137
- }
138
-
139
- /* --- Glassmorphism UI --- */
140
- .glass-panel {
141
- background: rgba(255, 255, 255, var(--glass-opacity));
142
- backdrop-filter: blur(var(--glass-blur));
143
- -webkit-backdrop-filter: blur(var(--glass-blur));
144
- border: 1px solid rgba(255, 255, 255, 0.1);
145
- border-radius: var(--border-radius);
146
- box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
147
- transition: all 0.3s ease;
148
- }
149
-
150
- .glass-input {
151
- background: rgba(0, 0, 0, 0.2);
152
- border: 1px solid rgba(255, 255, 255, 0.1);
153
- color: white;
154
- transition: all 0.2s;
155
- }
156
- .glass-input:focus {
157
- outline: none;
158
- border-color: var(--brand-color);
159
- box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);
160
- }
161
-
162
- /* --- Range Slider Styling --- */
163
- input[type=range] {
164
- -webkit-appearance: none;
165
- width: 100%;
166
- background: transparent;
167
- }
168
- input[type=range]::-webkit-slider-thumb {
169
- -webkit-appearance: none;
170
- height: 16px;
171
- width: 16px;
172
- border-radius: 50%;
173
- background: var(--brand-color);
174
- cursor: pointer;
175
- margin-top: -6px;
176
- box-shadow: 0 0 10px var(--brand-color);
177
- }
178
- input[type=range]::-webkit-slider-runnable-track {
179
- width: 100%;
180
- height: 4px;
181
- cursor: pointer;
182
- background: rgba(255,255,255,0.2);
183
- border-radius: 2px;
184
- }
185
-
186
- /* --- Color Swatches --- */
187
- .swatch {
188
- width: 32px;
189
- height: 32px;
190
- border-radius: 50%;
191
- cursor: pointer;
192
- border: 2px solid transparent;
193
- transition: transform 0.2s;
194
- }
195
- .swatch:hover { transform: scale(1.1); }
196
- .swatch.active { border-color: white; box-shadow: 0 0 10px currentColor; }
197
-
198
- /* --- Toast Notification --- */
199
- .toast {
200
- position: fixed;
201
- bottom: 20px;
202
- right: 20px;
203
- background: var(--brand-color);
204
- color: white;
205
- padding: 12px 24px;
206
- border-radius: 8px;
207
- box-shadow: 0 10px 30px rgba(0,0,0,0.5);
208
- transform: translateY(100px);
209
- opacity: 0;
210
- transition: all 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55);
211
- z-index: 1000;
212
- font-weight: 600;
213
- }
214
- .toast.show {
215
- transform: translateY(0);
216
- opacity: 1;
217
- }
218
-
219
- /* --- Grid Pattern Background --- */
220
- .bg-grid {
221
- position: fixed;
222
- top: 0; left: 0; width: 100%; height: 100%;
223
- background-image: linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
224
- linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
225
- background-size: 40px 40px;
226
- pointer-events: none;
227
- z-index: -1;
228
- }
229
- </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  </head>
231
  <body class="min-h-screen flex flex-col font-sans selection:bg-brand selection:text-white">
232
-
233
- <!-- Background Grid -->
234
- <div class="bg-grid"></div>
235
-
236
- <!-- Header -->
237
- <header class="w-full p-6 flex justify-between items-center z-50 relative">
238
- <div class="flex items-center gap-3">
239
- <div class="w-10 h-10 rounded-lg bg-gradient-to-br from-white/20 to-white/5 flex items-center justify-center border border-white/10 shadow-lg">
240
- <i class="fa-solid fa-layer-group text-brand text-xl"></i>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  </div>
242
- <div>
243
- <h1 class="font-display font-bold text-2xl tracking-tight">Orbital UI</h1>
244
- <p class="text-xs text-gray-400 font-medium tracking-wider uppercase">Customizer Engine v1.0</p>
245
  </div>
 
246
  </div>
247
- <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="text-xs text-gray-400 hover:text-white transition-colors flex items-center gap-2 group">
248
- <span>Built with anycoder</span>
249
- <i class="fa-solid fa-arrow-up-right-from-square group-hover:translate-x-1 group-hover:-translate-y-1 transition-transform"></i>
250
- </a>
251
- </header>
252
-
253
- <!-- Main Content -->
254
- <main class="flex-grow container mx-auto px-4 py-4 flex flex-col lg:flex-row gap-8 relative z-10">
255
-
256
- <!-- Left Column: Preview Area -->
257
- <div class="lg:w-1/2 flex flex-col gap-6">
258
-
259
- <!-- 3D Preview -->
260
- <div class="glass-panel p-1 flex-grow min-h-[400px] relative overflow-hidden group">
261
- <div class="absolute top-4 left-4 z-20">
262
- <span class="px-3 py-1 rounded-full bg-black/30 border border-white/10 text-xs font-mono text-gray-300 backdrop-blur-md">
263
- <i class="fa-solid fa-eye mr-2"></i>Live Preview
264
- </span>
265
- </div>
266
-
267
- <!-- The 3D Scene -->
268
- <div class="scene-container bg-gradient-to-b from-transparent to-black/20 rounded-xl" id="previewContainer">
269
- <div class="orbital-system">
270
- <div class="planet"></div>
271
- <div class="orbit-ring ring-1"><div class="satellite"></div></div>
272
- <div class="orbit-ring ring-2"><div class="satellite"></div></div>
273
- <div class="orbit-ring ring-3"><div class="satellite"></div></div>
274
- </div>
275
- </div>
276
-
277
- <!-- Reflection/Gloss effect -->
278
- <div class="absolute inset-0 bg-gradient-to-tr from-white/5 to-transparent pointer-events-none rounded-xl"></div>
279
  </div>
280
-
281
- <!-- Code Output Preview (Mini) -->
282
- <div class="glass-panel p-4">
283
- <div class="flex justify-between items-center mb-2">
284
- <h3 class="text-sm font-semibold text-gray-300"><i class="fa-solid fa-code mr-2"></i>Generated CSS</h3>
285
- <button onclick="copyCSS()" class="text-xs bg-white/10 hover:bg-white/20 px-2 py-1 rounded transition-colors">
286
- <i class="fa-regular fa-copy"></i> Copy
287
- </button>
288
- </div>
289
- <div class="bg-black/40 rounded-lg p-3 font-mono text-xs text-gray-400 overflow-x-auto border border-white/5">
290
- <code id="cssOutput">
291
- :root {<br>
292
- &nbsp;&nbsp;--brand-color: #6366f1;<br>
293
- &nbsp;&nbsp;--border-radius: 1rem;<br>
294
- }
295
- </code>
296
- </div>
297
  </div>
298
- </div>
299
-
300
- <!-- Right Column: Controls -->
301
- <div class="lg:w-1/2 flex flex-col gap-6">
302
-
303
- <!-- Controls Container -->
304
- <div class="glass-panel p-6 lg:p-8 h-full flex flex-col">
305
- <h2 class="font-display text-2xl font-bold mb-6 flex items-center gap-2">
306
- <i class="fa-solid fa-sliders text-brand"></i> Configuration
307
- </h2>
308
-
309
- <div class="space-y-8 overflow-y-auto pr-2 custom-scrollbar flex-grow">
310
-
311
- <!-- Section: Colors -->
312
- <div class="space-y-3">
313
- <label class="text-sm font-medium text-gray-300 uppercase tracking-wider">Brand Color</label>
314
- <div class="flex flex-wrap gap-3" id="colorPalette">
315
- <!-- Generated by JS -->
316
- </div>
317
- <div class="flex items-center gap-3 mt-2">
318
- <input type="color" id="customColorPicker" class="w-8 h-8 rounded cursor-pointer bg-transparent border-0 p-0" value="#6366f1">
319
- <span class="text-xs text-gray-400">Custom Hex</span>
320
- <input type="text" id="hexInput" class="glass-input px-2 py-1 rounded text-xs w-24 font-mono" value="#6366f1">
321
- </div>
322
- </div>
323
-
324
- <hr class="border-white/10">
325
-
326
- <!-- Section: Geometry -->
327
- <div class="space-y-6">
328
- <div class="space-y-2">
329
- <div class="flex justify-between">
330
- <label class="text-sm text-gray-300">Border Radius</label>
331
- <span id="radiusVal" class="text-xs font-mono text-brand">16px</span>
332
- </div>
333
- <input type="range" min="0" max="50" value="16" id="radiusRange">
334
- </div>
335
-
336
- <div class="space-y-2">
337
- <div class="flex justify-between">
338
- <label class="text-sm text-gray-300">Glass Blur</label>
339
- <span id="blurVal" class="text-xs font-mono text-brand">16px</span>
340
- </div>
341
- <input type="range" min="0" max="40" value="16" id="blurRange">
342
- </div>
343
-
344
- <div class="space-y-2">
345
- <div class="flex justify-between">
346
- <label class="text-sm text-gray-300">Glass Opacity</label>
347
- <span id="opacityVal" class="text-xs font-mono text-brand">10%</span>
348
- </div>
349
- <input type="range" min="0" max="50" value="10" id="opacityRange">
350
- </div>
351
- </div>
352
-
353
- <hr class="border-white/10">
354
-
355
- <!-- Section: Animation -->
356
- <div class="space-y-2">
357
- <div class="flex justify-between">
358
- <label class="text-sm text-gray-300">Orbit Speed</label>
359
- <span id="speedVal" class="text-xs font-mono text-brand">Normal</span>
360
- </div>
361
- <input type="range" min="1" max="50" value="20" id="speedRange">
362
- </div>
363
-
364
- <!-- Section: Background -->
365
- <div class="space-y-3">
366
- <label class="text-sm font-medium text-gray-300 uppercase tracking-wider">Background Mood</label>
367
- <div class="grid grid-cols-3 gap-2">
368
- <button class="bg-mood-btn p-2 rounded border border-white/10 hover:bg-white/5 text-xs transition-all active-mood" data-start="#0f172a" data-end="#1e293b">Midnight</button>
369
- <button class="bg-mood-btn p-2 rounded border border-white/10 hover:bg-white/5 text-xs transition-all" data-start="#2e1065" data-end="#4c1d95">Deep Purple</button>
370
- <button class="bg-mood-btn p-2 rounded border border-white/10 hover:bg-white/5 text-xs transition-all" data-start="#1e1b4b" data-end="#312e81">Indigo</button>
371
- <button class="bg-mood-btn p-2 rounded border border-white/10 hover:bg-white/5 text-xs transition-all" data-start="#111827" data-end="#374151">Obsidian</button>
372
- <button class="bg-mood-btn p-2 rounded border border-white/10 hover:bg-white/5 text-xs transition-all" data-start="#4c0519" data-end="#881337">Rose Noir</button>
373
- <button class="bg-mood-btn p-2 rounded border border-white/10 hover:bg-white/5 text-xs transition-all" data-start="#064e3b" data-end="#065f46">Emerald</button>
374
- </div>
375
- </div>
376
-
377
- </div>
378
-
379
- <!-- Action Buttons -->
380
- <div class="mt-8 pt-6 border-t border-white/10 flex gap-4">
381
- <button onclick="randomize()" class="flex-1 py-3 rounded-lg border border-white/20 hover:bg-white/5 transition-all font-medium text-sm flex items-center justify-center gap-2">
382
- <i class="fa-solid fa-shuffle"></i> Randomize
383
- </button>
384
- <button onclick="exportConfig()" class="flex-1 py-3 rounded-lg bg-brand hover:brightness-110 transition-all font-bold text-sm shadow-lg shadow-brand/25 flex items-center justify-center gap-2">
385
- <i class="fa-solid fa-download"></i> Export JSON
386
- </button>
387
- </div>
388
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
  </div>
390
- </main>
391
-
392
- <!-- Toast Element -->
393
- <div id="toast" class="toast">
394
- <i class="fa-solid fa-check-circle mr-2"></i> Configuration Copied!
 
 
 
 
 
 
 
 
 
395
  </div>
396
-
397
- <script>
398
- // --- State Management ---
399
- const state = {
400
- brandColor: '#6366f1',
401
- borderRadius: 16,
402
- glassBlur: 16,
403
- glassOpacity: 10,
404
- animationSpeed: 20,
405
- bgStart: '#0f172a',
406
- bgEnd: '#1e293b'
407
- };
408
-
409
- const presets = [
410
- '#ef4444', '#f97316', '#f59e0b', '#84cc16',
411
- '#10b981', '#06b6d4', '#3b82f6', '#6366f1',
412
- '#8b5cf6', '#d946ef', '#f43f5e', '#ffffff'
413
- ];
414
-
415
- // --- DOM Elements ---
416
- const root = document.documentElement;
417
- const colorContainer = document.getElementById('colorPalette');
418
- const customPicker = document.getElementById('customColorPicker');
419
- const hexInput = document.getElementById('hexInput');
420
-
421
- // --- Initialization ---
422
- function init() {
423
- renderColorPalette();
424
- setupEventListeners();
425
- updateUI();
426
- }
427
-
428
- // --- Render Functions ---
429
- function renderColorPalette() {
430
- colorContainer.innerHTML = '';
431
- presets.forEach(color => {
432
- const div = document.createElement('div');
433
- div.className = `swatch ${state.brandColor === color ? 'active' : ''}`;
434
- div.style.backgroundColor = color;
435
- div.style.color = color; // for shadow
436
- div.onclick = () => setColor(color);
437
- colorContainer.appendChild(div);
438
- });
439
- }
440
-
441
- // --- Logic Functions ---
442
- function setColor(color) {
443
- state.brandColor = color;
444
- root.style.setProperty('--brand-color', color);
445
-
446
- // Update UI inputs
447
- customPicker.value = color;
448
- hexInput.value = color;
449
-
450
- // Update active state in palette
451
- document.querySelectorAll('.swatch').forEach(el => {
452
- el.classList.toggle('active', el.style.backgroundColor === color || rgbToHex(el.style.backgroundColor) === color);
453
- });
454
-
455
- updateCSSOutput();
456
- }
457
-
458
- function setRadius(val) {
459
- state.borderRadius = val;
460
- root.style.setProperty('--border-radius', `${val}px`);
461
- document.getElementById('radiusVal').innerText = `${val}px`;
462
- updateCSSOutput();
463
- }
464
-
465
- function setBlur(val) {
466
- state.glassBlur = val;
467
- root.style.setProperty('--glass-blur', `${val}px`);
468
- document.getElementById('blurVal').innerText = `${val}px`;
469
- }
470
-
471
- function setOpacity(val) {
472
- state.glassOpacity = val;
473
- root.style.setProperty('--glass-opacity', val / 100);
474
- document.getElementById('opacityVal').innerText = `${val}%`;
475
- }
476
-
477
- function setSpeed(val) {
478
- // Invert logic: lower value = faster speed (lower duration)
479
- // Map 1-50 to 50s - 1s
480
- const duration = 51 - val;
481
- state.animationSpeed = duration;
482
- root.style.setProperty('--animation-speed', `${duration}s`);
483
-
484
- let label = "Normal";
485
- if(val > 40) label = "Warp Speed";
486
- else if(val > 25) label = "Fast";
487
- else if(val < 10) label = "Slow Motion";
488
-
489
- document.getElementById('speedVal').innerText = label;
490
- }
491
-
492
- function setBackground(start, end, btn) {
493
- state.bgStart = start;
494
- state.bgEnd = end;
495
- root.style.setProperty('--bg-gradient-start', start);
496
- root.style.setProperty('--bg-gradient-end', end);
497
-
498
- // Update active button state
499
- document.querySelectorAll('.bg-mood-btn').forEach(b => {
500
- b.classList.remove('bg-white/20', 'border-brand');
501
- b.classList.add('border-white/10');
502
- });
503
- btn.classList.remove('border-white/10');
504
- btn.classList.add('bg-white/20', 'border-brand');
505
- }
506
-
507
- // --- Event Listeners ---
508
- function setupEventListeners() {
509
- // Range Inputs
510
- document.getElementById('radiusRange').addEventListener('input', (e) => setRadius(e.target.value));
511
- document.getElementById('blurRange').addEventListener('input', (e) => setBlur(e.target.value));
512
- document.getElementById('opacityRange').addEventListener('input', (e) => setOpacity(e.target.value));
513
- document.getElementById('speedRange').addEventListener('input', (e) => setSpeed(e.target.value));
514
-
515
- // Color Inputs
516
- customPicker.addEventListener('input', (e) => setColor(e.target.value));
517
- hexInput.addEventListener('change', (e) => {
518
- let hex = e.target.value;
519
- if(!hex.startsWith('#')) hex = '#' + hex;
520
- if(/^#[0-9A-F]{6}$/i.test(hex)) setColor(hex);
521
- });
522
-
523
- // Background Buttons
524
- document.querySelectorAll('.bg-mood-btn').forEach(btn => {
525
- btn.addEventListener('click', () => {
526
- setBackground(btn.dataset.start, btn.dataset.end, btn);
527
- });
528
- });
529
- }
530
-
531
- // --- Utilities ---
532
- function updateCSSOutput() {
533
- const code = `:root {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
534
  --brand-color: ${state.brandColor};
535
  --border-radius: ${state.borderRadius}px;
536
  --glass-blur: ${state.glassBlur}px;
537
  --glass-opacity: ${state.glassOpacity / 100};
538
  --animation-speed: ${state.animationSpeed}s;
539
  }`;
540
- document.getElementById('cssOutput').innerHTML = code.replace(/\n/g, '<br>').replace(/ /g, '&nbsp;');
541
- }
542
-
543
- function updateUI() {
544
- // Trigger initial updates to sync UI with state
545
- setColor(state.brandColor);
546
- setRadius(state.borderRadius);
547
- setBlur(state.glassBlur);
548
- setOpacity(state.glassOpacity);
549
- setSpeed(20); // Default middle
550
- }
551
-
552
- function rgbToHex(rgb) {
553
- if(!rgb) return '';
554
- if(rgb.startsWith('#')) return rgb;
555
- // Basic rgb to hex conversion if needed for comparison
556
- // Not fully implemented as inputs are usually hex
557
- return rgb;
558
- }
559
-
560
- function showToast(msg) {
561
- const toast = document.getElementById('toast');
562
- toast.innerHTML = `<i class="fa-solid fa-check-circle mr-2"></i> ${msg}`;
563
- toast.classList.add('show');
564
- setTimeout(() => toast.classList.remove('show'), 3000);
565
- }
566
-
567
- function copyCSS() {
568
- const code = document.getElementById('cssOutput').innerText;
569
- navigator.clipboard.writeText(code).then(() => {
570
- showToast("CSS copied to clipboard!");
571
- });
572
- }
573
-
574
- function randomize() {
575
- const randomColor = presets[Math.floor(Math.random() * presets.length)];
576
- const randomRadius = Math.floor(Math.random() * 40);
577
- const randomSpeed = Math.floor(Math.random() * 50) + 1;
578
-
579
- setColor(randomColor);
580
-
581
- // Update inputs visually
582
- document.getElementById('radiusRange').value = randomRadius;
583
- setRadius(randomRadius);
584
-
585
- document.getElementById('speedRange').value = randomSpeed;
586
- setSpeed(randomSpeed);
587
-
588
- showToast("Randomized Style!");
589
- }
590
-
591
- function exportConfig() {
592
- const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(state, null, 2));
593
- const downloadAnchorNode = document.createElement('a');
594
- downloadAnchorNode.setAttribute("href", dataStr);
595
- downloadAnchorNode.setAttribute("download", "orbital-theme-config.json");
596
- document.body.appendChild(downloadAnchorNode);
597
- downloadAnchorNode.click();
598
- downloadAnchorNode.remove();
599
- showToast("Config Downloaded!");
600
- }
601
-
602
- // Run
603
- init();
604
-
605
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
606
  </body>
607
  </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>Orbital UI Customizer</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=Inter:wght@300;400;600;800&family=Space+Grotesk:wght@300;500;700&display=swap" rel="stylesheet">
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
+ <script src="https://cdn.tailwindcss.com"></script>
12
+ <script>
13
+ tailwind.config = {
14
+ theme: {
15
+ extend: {
16
+ fontFamily: {
17
+ sans: ['Inter', 'sans-serif'],
18
+ display: ['Space Grotesk', 'sans-serif'],
19
+ },
20
+ colors: {
21
+ brand: 'var(--brand-color)',
22
+ surface: 'rgba(255, 255, 255, 0.05)',
23
+ surfaceHover: 'rgba(255, 255, 255, 0.1)',
24
+ }
25
+ }
26
+ }
27
+ }
28
+ </script>
29
+ <style>
30
+ :root {
31
+ --brand-color: #6366f1;
32
+ --bg-gradient-start: #0f172a;
33
+ --bg-gradient-end: #1e293b;
34
+ --glass-blur: 16px;
35
+ --glass-opacity: 0.1;
36
+ --border-radius: 1rem;
37
+ --animation-speed: 20s;
38
+ --glow-intensity: 0.5;
39
+ }
40
+ body {
41
+ background: linear-gradient(135deg, var(--bg-gradient-start), var(--bg-gradient-end));
42
+ color: white;
43
+ overflow-x: hidden;
44
+ transition: background 0.5s ease;
45
+ }
46
+ ::-webkit-scrollbar {
47
+ width: 6px;
48
+ }
49
+ ::-webkit-scrollbar-track {
50
+ background: rgba(0, 0, 0, 0.2);
51
+ }
52
+ ::-webkit-scrollbar-thumb {
53
+ background: var(--brand-color);
54
+ border-radius: 10px;
55
+ }
56
+ .scene-container {
57
+ perspective: 1000px;
58
+ width: 100%;
59
+ height: 400px;
60
+ display: flex;
61
+ align-items: center;
62
+ justify-content: center;
63
+ position: relative;
64
+ overflow: hidden;
65
+ }
66
+ .orbital-system {
67
+ position: relative;
68
+ width: 200px;
69
+ height: 200px;
70
+ transform-style: preserve-3d;
71
+ animation: rotateSystem var(--animation-speed) linear infinite;
72
+ }
73
+ .planet {
74
+ width: 100px;
75
+ height: 100px;
76
+ border-radius: 50%;
77
+ background: radial-gradient(circle at 30% 30%, var(--brand-color), #000);
78
+ box-shadow: 0 0 50px var(--brand-color);
79
+ position: absolute;
80
+ top: 50%;
81
+ left: 50%;
82
+ transform: translate(-50%, -50%);
83
+ z-index: 10;
84
+ transition: all 0.3s ease;
85
+ }
86
+ .orbit-ring {
87
+ position: absolute;
88
+ top: 50%;
89
+ left: 50%;
90
+ border: 2px solid rgba(255, 255, 255, 0.1);
91
+ border-radius: 50%;
92
+ transform: translate(-50%, -50%) rotateX(70deg);
93
+ transform-style: preserve-3d;
94
+ }
95
+ .satellite {
96
+ width: 20px;
97
+ height: 20px;
98
+ background: white;
99
+ border-radius: 50%;
100
+ position: absolute;
101
+ top: -10px;
102
+ left: 50%;
103
+ transform: translateX(-50%) rotateX(-70deg);
104
+ box-shadow: 0 0 15px white;
105
+ }
106
+ .ring-1 {
107
+ width: 200px;
108
+ height: 200px;
109
+ animation: spin 10s linear infinite;
110
+ }
111
+ .ring-2 {
112
+ width: 300px;
113
+ height: 300px;
114
+ animation: spin 15s linear infinite reverse;
115
+ border-color: var(--brand-color);
116
+ }
117
+ .ring-3 {
118
+ width: 400px;
119
+ height: 400px;
120
+ animation: spin 25s linear infinite;
121
+ }
122
+ @keyframes rotateSystem {
123
+ 0% { transform: rotateY(0deg); }
124
+ 100% { transform: rotateY(360deg); }
125
+ }
126
+ @keyframes spin {
127
+ 0% { transform: translate(-50%, -50%) rotateX(70deg) rotateZ(0deg); }
128
+ 100% { transform: translate(-50%, -50%) rotateX(70deg) rotateZ(360deg); }
129
+ }
130
+ .glass-panel {
131
+ background: rgba(255, 255, 255, var(--glass-opacity));
132
+ backdrop-filter: blur(var(--glass-blur));
133
+ -webkit-backdrop-filter: blur(var(--glass-blur));
134
+ border: 1px solid rgba(255, 255, 255, 0.1);
135
+ border-radius: var(--border-radius);
136
+ box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
137
+ transition: all 0.3s ease;
138
+ }
139
+ .glass-input {
140
+ background: rgba(0, 0, 0, 0.2);
141
+ border: 1px solid rgba(255, 255, 255, 0.1);
142
+ color: white;
143
+ transition: all 0.2s;
144
+ }
145
+ .glass-input:focus {
146
+ outline: none;
147
+ border-color: var(--brand-color);
148
+ box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);
149
+ }
150
+ input[type=range] {
151
+ -webkit-appearance: none;
152
+ width: 100%;
153
+ background: transparent;
154
+ }
155
+ input[type=range]::-webkit-slider-thumb {
156
+ -webkit-appearance: none;
157
+ height: 16px;
158
+ width: 16px;
159
+ border-radius: 50%;
160
+ background: var(--brand-color);
161
+ cursor: pointer;
162
+ margin-top: -6px;
163
+ box-shadow: 0 0 10px var(--brand-color);
164
+ }
165
+ input[type=range]::-webkit-slider-runnable-track {
166
+ width: 100%;
167
+ height: 4px;
168
+ cursor: pointer;
169
+ background: rgba(255, 255, 255, 0.2);
170
+ border-radius: 2px;
171
+ }
172
+ .swatch {
173
+ width: 32px;
174
+ height: 32px;
175
+ border-radius: 50%;
176
+ cursor: pointer;
177
+ border: 2px solid transparent;
178
+ transition: transform 0.2s;
179
+ }
180
+ .swatch:hover {
181
+ transform: scale(1.1);
182
+ }
183
+ .swatch.active {
184
+ border-color: white;
185
+ box-shadow: 0 0 10px currentColor;
186
+ }
187
+ .toast {
188
+ position: fixed;
189
+ bottom: 20px;
190
+ right: 20px;
191
+ background: var(--brand-color);
192
+ color: white;
193
+ padding: 12px 24px;
194
+ border-radius: 8px;
195
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
196
+ transform: translateY(100px);
197
+ opacity: 0;
198
+ transition: all 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55);
199
+ z-index: 1000;
200
+ font-weight: 600;
201
+ }
202
+ .toast.show {
203
+ transform: translateY(0);
204
+ opacity: 1;
205
+ }
206
+ .bg-grid {
207
+ position: fixed;
208
+ top: 0;
209
+ left: 0;
210
+ width: 100%;
211
+ height: 100%;
212
+ background-image: linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
213
+ linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
214
+ background-size: 40px 40px;
215
+ pointer-events: none;
216
+ z-index: -1;
217
+ }
218
+ /* Modal Styles */
219
+ .modal-overlay {
220
+ position: fixed;
221
+ inset: 0;
222
+ background: rgba(0, 0, 0, 0.8);
223
+ backdrop-filter: blur(8px);
224
+ display: flex;
225
+ align-items: center;
226
+ justify-content: center;
227
+ z-index: 2000;
228
+ opacity: 0;
229
+ visibility: hidden;
230
+ transition: all 0.3s ease;
231
+ }
232
+ .modal-overlay.active {
233
+ opacity: 1;
234
+ visibility: visible;
235
+ }
236
+ .modal-content {
237
+ background: linear-gradient(135deg, var(--bg-gradient-start), var(--bg-gradient-end));
238
+ border: 1px solid rgba(255, 255, 255, 0.1);
239
+ border-radius: var(--border-radius);
240
+ padding: 2rem;
241
+ max-width: 500px;
242
+ width: 90%;
243
+ transform: scale(0.9) translateY(20px);
244
+ transition: all 0.3s ease;
245
+ }
246
+ .modal-overlay.active .modal-content {
247
+ transform: scale(1) translateY(0);
248
+ }
249
+ .share-preview {
250
+ aspect-ratio: 1200/630;
251
+ background: linear-gradient(135deg, var(--bg-gradient-start), var(--bg-gradient-end));
252
+ border-radius: 12px;
253
+ position: relative;
254
+ overflow: hidden;
255
+ display: flex;
256
+ align-items: center;
257
+ justify-content: center;
258
+ }
259
+ .share-preview .orbital-system {
260
+ transform: scale(0.6);
261
+ animation: rotateSystem var(--animation-speed) linear infinite;
262
+ }
263
+ .social-btn {
264
+ transition: all 0.2s ease;
265
+ }
266
+ .social-btn:hover {
267
+ transform: translateY(-2px);
268
+ }
269
+ </style>
270
  </head>
271
  <body class="min-h-screen flex flex-col font-sans selection:bg-brand selection:text-white">
272
+ <div class="bg-grid"></div>
273
+ <header class="w-full p-6 flex justify-between items-center z-50 relative">
274
+ <div class="flex items-center gap-3">
275
+ <div class="w-10 h-10 rounded-lg bg-gradient-to-br from-white/20 to-white/5 flex items-center justify-center border border-white/10 shadow-lg">
276
+ <i class="fa-solid fa-layer-group text-brand text-xl"></i>
277
+ </div>
278
+ <div>
279
+ <h1 class="font-display font-bold text-2xl tracking-tight">Orbital UI</h1>
280
+ <p class="text-xs text-gray-400 font-medium tracking-wider uppercase">Customizer Engine v1.0</p>
281
+ </div>
282
+ </div>
283
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="text-xs text-gray-400 hover:text-white transition-colors flex items-center gap-2 group">
284
+ <span>Built with anycoder</span>
285
+ <i class="fa-solid fa-arrow-up-right-from-square group-hover:translate-x-1 group-hover:-translate-y-1 transition-transform"></i>
286
+ </a>
287
+ </header>
288
+ <main class="flex-grow container mx-auto px-4 py-4 flex flex-col lg:flex-row gap-8 relative z-10">
289
+ <div class="lg:w-1/2 flex flex-col gap-6">
290
+ <div class="glass-panel p-1 flex-grow min-h-[400px] relative overflow-hidden group">
291
+ <div class="absolute top-4 left-4 z-20">
292
+ <span class="px-3 py-1 rounded-full bg-black/30 border border-white/10 text-xs font-mono text-gray-300 backdrop-blur-md">
293
+ <i class="fa-solid fa-eye mr-2"></i>Live Preview
294
+ </span>
295
+ </div>
296
+ <div class="scene-container bg-gradient-to-b from-transparent to-black/20 rounded-xl" id="previewContainer">
297
+ <div class="orbital-system">
298
+ <div class="planet"></div>
299
+ <div class="orbit-ring ring-1">
300
+ <div class="satellite"></div>
301
+ </div>
302
+ <div class="orbit-ring ring-2">
303
+ <div class="satellite"></div>
304
  </div>
305
+ <div class="orbit-ring ring-3">
306
+ <div class="satellite"></div>
 
307
  </div>
308
+ </div>
309
  </div>
310
+ <div class="absolute inset-0 bg-gradient-to-tr from-white/5 to-transparent pointer-events-none rounded-xl"></div>
311
+ </div>
312
+ <div class="glass-panel p-4">
313
+ <div class="flex justify-between items-center mb-2">
314
+ <h3 class="text-sm font-semibold text-gray-300"><i class="fa-solid fa-code mr-2"></i>Generated CSS</h3>
315
+ <button onclick="copyCSS()" class="text-xs bg-white/10 hover:bg-white/20 px-2 py-1 rounded transition-colors">
316
+ <i class="fa-regular fa-copy"></i> Copy
317
+ </button>
318
+ </div>
319
+ <div class="bg-black/40 rounded-lg p-3 font-mono text-xs text-gray-400 overflow-x-auto border border-white/5">
320
+ <code id="cssOutput">
321
+ :root {<br>
322
+ &nbsp;&nbsp;--brand-color: #6366f1;<br>
323
+ &nbsp;&nbsp;--border-radius: 1rem;<br>
324
+ }
325
+ </code>
326
+ </div>
327
+ </div>
328
+ </div>
329
+ <div class="lg:w-1/2 flex flex-col gap-6">
330
+ <div class="glass-panel p-6 lg:p-8 h-full flex flex-col">
331
+ <h2 class="font-display text-2xl font-bold mb-6 flex items-center gap-2">
332
+ <i class="fa-solid fa-sliders text-brand"></i> Configuration
333
+ </h2>
334
+ <div class="space-y-8 overflow-y-auto pr-2 custom-scrollbar flex-grow">
335
+ <div class="space-y-3">
336
+ <label class="text-sm font-medium text-gray-300 uppercase tracking-wider">Brand Color</label>
337
+ <div class="flex flex-wrap gap-3" id="colorPalette"></div>
338
+ <div class="flex items-center gap-3 mt-2">
339
+ <input type="color" id="customColorPicker" class="w-8 h-8 rounded cursor-pointer bg-transparent border-0 p-0" value="#6366f1">
340
+ <span class="text-xs text-gray-400">Custom Hex</span>
341
+ <input type="text" id="hexInput" class="glass-input px-2 py-1 rounded text-xs w-24 font-mono" value="#6366f1">
342
  </div>
343
+ </div>
344
+ <hr class="border-white/10">
345
+ <div class="space-y-6">
346
+ <div class="space-y-2">
347
+ <div class="flex justify-between">
348
+ <label class="text-sm text-gray-300">Border Radius</label>
349
+ <span id="radiusVal" class="text-xs font-mono text-brand">16px</span>
350
+ </div>
351
+ <input type="range" min="0" max="50" value="16" id="radiusRange">
 
 
 
 
 
 
 
 
352
  </div>
353
+ <div class="space-y-2">
354
+ <div class="flex justify-between">
355
+ <label class="text-sm text-gray-300">Glass Blur</label>
356
+ <span id="blurVal" class="text-xs font-mono text-brand">16px</span>
357
+ </div>
358
+ <input type="range" min="0" max="40" value="16" id="blurRange">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
359
  </div>
360
+ <div class="space-y-2">
361
+ <div class="flex justify-between">
362
+ <label class="text-sm text-gray-300">Glass Opacity</label>
363
+ <span id="opacityVal" class="text-xs font-mono text-brand">10%</span>
364
+ </div>
365
+ <input type="range" min="0" max="50" value="10" id="opacityRange">
366
+ </div>
367
+ </div>
368
+ <hr class="border-white/10">
369
+ <div class="space-y-2">
370
+ <div class="flex justify-between">
371
+ <label class="text-sm text-gray-300">Orbit Speed</label>
372
+ <span id="speedVal" class="text-xs font-mono text-brand">Normal</span>
373
+ </div>
374
+ <input type="range" min="1" max="50" value="20" id="speedRange">
375
+ </div>
376
+ <div class="space-y-3">
377
+ <label class="text-sm font-medium text-gray-300 uppercase tracking-wider">Background Mood</label>
378
+ <div class="grid grid-cols-3 gap-2">
379
+ <button class="bg-mood-btn p-2 rounded border border-white/10 hover:bg-white/5 text-xs transition-all active-mood" data-start="#0f172a" data-end="#1e293b">Midnight</button>
380
+ <button class="bg-mood-btn p-2 rounded border border-white/10 hover:bg-white/5 text-xs transition-all" data-start="#2e1065" data-end="#4c1d95">Deep Purple</button>
381
+ <button class="bg-mood-btn p-2 rounded border border-white/10 hover:bg-white/5 text-xs transition-all" data-start="#1e1b4b" data-end="#312e81">Indigo</button>
382
+ <button class="bg-mood-btn p-2 rounded border border-white/10 hover:bg-white/5 text-xs transition-all" data-start="#111827" data-end="#374151">Obsidian</button>
383
+ <button class="bg-mood-btn p-2 rounded border border-white/10 hover:bg-white/5 text-xs transition-all" data-start="#4c0519" data-end="#881337">Rose Noir</button>
384
+ <button class="bg-mood-btn p-2 rounded border border-white/10 hover:bg-white/5 text-xs transition-all" data-start="#064e3b" data-end="#065f46">Emerald</button>
385
+ </div>
386
+ </div>
387
  </div>
388
+ <div class="mt-8 pt-6 border-t border-white/10 flex gap-4">
389
+ <button onclick="randomize()" class="flex-1 py-3 rounded-lg border border-white/20 hover:bg-white/5 transition-all font-medium text-sm flex items-center justify-center gap-2">
390
+ <i class="fa-solid fa-shuffle"></i> Randomize
391
+ </button>
392
+ <button onclick="exportConfig()" class="flex-1 py-3 rounded-lg bg-brand hover:brightness-110 transition-all font-bold text-sm shadow-lg shadow-brand/25 flex items-center justify-center gap-2">
393
+ <i class="fa-solid fa-download"></i> Export JSON
394
+ </button>
395
+ </div>
396
+ <div class="mt-4 flex gap-4">
397
+ <button onclick="openShareModal()" class="flex-1 py-3 rounded-lg bg-gradient-to-r from-pink-500 via-purple-500 to-indigo-500 hover:brightness-110 transition-all font-bold text-sm shadow-lg flex items-center justify-center gap-2">
398
+ <i class="fa-solid fa-share-nodes"></i> Share to Social
399
+ </button>
400
+ </div>
401
+ </div>
402
  </div>
403
+ </main>
404
+ <div id="toast" class="toast">
405
+ <i class="fa-solid fa-check-circle mr-2"></i> Configuration Copied!
406
+ </div>
407
+ <div id="shareModal" class="modal-overlay">
408
+ <div class="modal-content glass-panel">
409
+ <div class="flex justify-between items-center mb-4">
410
+ <h3 class="font-display text-xl font-bold flex items-center gap-2">
411
+ <i class="fa-solid fa-share-nodes text-brand"></i> Share Your Creation
412
+ </h3>
413
+ <button onclick="closeShareModal()" class="text-gray-400 hover:text-white transition-colors">
414
+ <i class="fa-solid fa-xmark text-xl"></i>
415
+ </button>
416
+ </div>
417
+ <div class="share-preview mb-4" id="sharePreview">
418
+ <div class="orbital-system" style="transform: scale(0.5);">
419
+ <div class="planet"></div>
420
+ <div class="orbit-ring ring-1">
421
+ <div class="satellite"></div>
422
+ </div>
423
+ <div class="orbit-ring ring-2">
424
+ <div class="satellite"></div>
425
+ </div>
426
+ <div class="orbit-ring ring-3">
427
+ <div class="satellite"></div>
428
+ </div>
429
+ </div>
430
+ <div class="absolute bottom-4 left-4 right-4 flex justify-between items-end">
431
+ <div>
432
+ <h4 class="font-display font-bold text-lg">Orbital UI Theme</h4>
433
+ <p class="text-xs text-gray-400">Created with Orbital Customizer</p>
434
+ </div>
435
+ <div class="text-right">
436
+ <p class="text-xs font-mono text-brand" id="shareColorCode">#6366f1</p>
437
+ </div>
438
+ </div>
439
+ </div>
440
+ <div class="space-y-4">
441
+ <div class="flex gap-2">
442
+ <input type="text" id="shareUrl" readonly class="flex-1 glass-input px-3 py-2 rounded text-xs font-mono" value="">
443
+ <button onclick="copyShareUrl()" class="bg-brand hover:brightness-110 px-4 py-2 rounded text-sm font-medium transition-all">
444
+ <i class="fa-regular fa-copy"></i>
445
+ </button>
446
+ </div>
447
+ <div class="grid grid-cols-4 gap-2">
448
+ <button onclick="shareToTwitter()" class="social-btn bg-[#1DA1F2] hover:bg-[#1a8cd8] py-3 rounded-lg flex items-center justify-center gap-2 text-sm font-medium">
449
+ <i class="fa-brands fa-twitter"></i> Tweet
450
+ </button>
451
+ <button onclick="shareToFacebook()" class="social-btn bg-[#4267B2] hover:bg-[#365899] py-3 rounded-lg flex items-center justify-center gap-2 text-sm font-medium">
452
+ <i class="fa-brands fa-facebook-f"></i> Share
453
+ </button>
454
+ <button onclick="shareToLinkedIn()" class="social-btn bg-[#0077b5] hover:bg-[#006396] py-3 rounded-lg flex items-center justify-center gap-2 text-sm font-medium">
455
+ <i class="fa-brands fa-linkedin-in"></i> Post
456
+ </button>
457
+ <button onclick="shareNative()" class="social-btn bg-gradient-to-r from-green-500 to-emerald-600 hover:brightness-110 py-3 rounded-lg flex items-center justify-center gap-2 text-sm font-medium">
458
+ <i class="fa-solid fa-arrow-up-from-bracket"></i> More
459
+ </button>
460
+ </div>
461
+ <button onclick="downloadImage()" class="w-full py-3 rounded-lg border border-white/20 hover:bg-white/5 transition-all font-medium text-sm flex items-center justify-center gap-2">
462
+ <i class="fa-solid fa-image"></i> Download as Image (PNG)
463
+ </button>
464
+ </div>
465
+ </div>
466
+ </div>
467
+ <canvas id="exportCanvas" style="display: none;"></canvas>
468
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
469
+ <script>
470
+ const state = {
471
+ brandColor: '#6366f1',
472
+ borderRadius: 16,
473
+ glassBlur: 16,
474
+ glassOpacity: 10,
475
+ animationSpeed: 20,
476
+ bgStart: '#0f172a',
477
+ bgEnd: '#1e293b'
478
+ };
479
+ const presets = [
480
+ '#ef4444', '#f97316', '#f59e0b', '#84cc16',
481
+ '#10b981', '#06b6d4', '#3b82f6', '#6366f1',
482
+ '#8b5cf6', '#d946ef', '#f43f5e', '#ffffff'
483
+ ];
484
+ const root = document.documentElement;
485
+ const colorContainer = document.getElementById('colorPalette');
486
+ const customPicker = document.getElementById('customColorPicker');
487
+ const hexInput = document.getElementById('hexInput');
488
+
489
+ function init() {
490
+ loadFromUrl();
491
+ renderColorPalette();
492
+ setupEventListeners();
493
+ updateUI();
494
+ updateSharePreview();
495
+ }
496
+
497
+ function renderColorPalette() {
498
+ colorContainer.innerHTML = '';
499
+ presets.forEach(color => {
500
+ const div = document.createElement('div');
501
+ div.className = `swatch ${state.brandColor === color ? 'active' : ''}`;
502
+ div.style.backgroundColor = color;
503
+ div.style.color = color;
504
+ div.onclick = () => setColor(color);
505
+ colorContainer.appendChild(div);
506
+ });
507
+ }
508
+
509
+ function setColor(color) {
510
+ state.brandColor = color;
511
+ root.style.setProperty('--brand-color', color);
512
+ customPicker.value = color;
513
+ hexInput.value = color;
514
+ document.querySelectorAll('.swatch').forEach(el => {
515
+ el.classList.toggle('active', el.style.backgroundColor === color || rgbToHex(el.style.backgroundColor) === color);
516
+ });
517
+ updateCSSOutput();
518
+ updateSharePreview();
519
+ updateUrl();
520
+ }
521
+
522
+ function setRadius(val) {
523
+ state.borderRadius = val;
524
+ root.style.setProperty('--border-radius', `${val}px`);
525
+ document.getElementById('radiusVal').innerText = `${val}px`;
526
+ updateCSSOutput();
527
+ updateUrl();
528
+ }
529
+
530
+ function setBlur(val) {
531
+ state.glassBlur = val;
532
+ root.style.setProperty('--glass-blur', `${val}px`);
533
+ document.getElementById('blurVal').innerText = `${val}px`;
534
+ updateUrl();
535
+ }
536
+
537
+ function setOpacity(val) {
538
+ state.glassOpacity = val;
539
+ root.style.setProperty('--glass-opacity', val / 100);
540
+ document.getElementById('opacityVal').innerText = `${val}%`;
541
+ updateUrl();
542
+ }
543
+
544
+ function setSpeed(val) {
545
+ const duration = 51 - val;
546
+ state.animationSpeed = duration;
547
+ root.style.setProperty('--animation-speed', `${duration}s`);
548
+ let label = "Normal";
549
+ if(val > 40) label = "Warp Speed";
550
+ else if(val > 25) label = "Fast";
551
+ else if(val < 10) label = "Slow Motion";
552
+ document.getElementById('speedVal').innerText = label;
553
+ updateUrl();
554
+ }
555
+
556
+ function setBackground(start, end, btn) {
557
+ state.bgStart = start;
558
+ state.bgEnd = end;
559
+ root.style.setProperty('--bg-gradient-start', start);
560
+ root.style.setProperty('--bg-gradient-end', end);
561
+ document.querySelectorAll('.bg-mood-btn').forEach(b => {
562
+ b.classList.remove('bg-white/20', 'border-brand');
563
+ b.classList.add('border-white/10');
564
+ });
565
+ btn.classList.remove('border-white/10');
566
+ btn.classList.add('bg-white/20', 'border-brand');
567
+ updateSharePreview();
568
+ updateUrl();
569
+ }
570
+
571
+ function setupEventListeners() {
572
+ document.getElementById('radiusRange').addEventListener('input', (e) => setRadius(e.target.value));
573
+ document.getElementById('blurRange').addEventListener('input', (e) => setBlur(e.target.value));
574
+ document.getElementById('opacityRange').addEventListener('input', (e) => setOpacity(e.target.value));
575
+ document.getElementById('speedRange').addEventListener('input', (e) => setSpeed(e.target.value));
576
+ customPicker.addEventListener('input', (e) => setColor(e.target.value));
577
+ hexInput.addEventListener('change', (e) => {
578
+ let hex = e.target.value;
579
+ if(!hex.startsWith('#')) hex = '#' + hex;
580
+ if(/^#[0-9A-F]{6}$/i.test(hex)) setColor(hex);
581
+ });
582
+ document.querySelectorAll('.bg-mood-btn').forEach(btn => {
583
+ btn.addEventListener('click', () => {
584
+ setBackground(btn.dataset.start, btn.dataset.end, btn);
585
+ });
586
+ });
587
+ }
588
+
589
+ function updateCSSOutput() {
590
+ const code = `:root {
591
  --brand-color: ${state.brandColor};
592
  --border-radius: ${state.borderRadius}px;
593
  --glass-blur: ${state.glassBlur}px;
594
  --glass-opacity: ${state.glassOpacity / 100};
595
  --animation-speed: ${state.animationSpeed}s;
596
  }`;
597
+ document.getElementById('cssOutput').innerHTML = code.replace(/\n/g, '<br>').replace(/ /g, '&nbsp;');
598
+ }
599
+
600
+ function updateUI() {
601
+ setColor(state.brandColor);
602
+ setRadius(state.borderRadius);
603
+ setBlur(state.glassBlur);
604
+ setOpacity(state.glassOpacity);
605
+ setSpeed(51 - state.animationSpeed);
606
+ const moodBtn = document.querySelector(`[data-start="${state.bgStart}"]`);
607
+ if(moodBtn) setBackground(state.bgStart, state.bgEnd, moodBtn);
608
+ }
609
+
610
+ function rgbToHex(rgb) {
611
+ if(!rgb) return '';
612
+ if(rgb.startsWith('#')) return rgb;
613
+ return rgb;
614
+ }
615
+
616
+ function showToast(msg) {
617
+ const toast = document.getElementById('toast');
618
+ toast.innerHTML = `<i class="fa-solid fa-check-circle mr-2"></i> ${msg}`;
619
+ toast.classList.add('show');
620
+ setTimeout(() => toast.classList.remove('show'), 3000);
621
+ }
622
+
623
+ function copyCSS() {
624
+ const code = document.getElementById('cssOutput').innerText;
625
+ navigator.clipboard.writeText(code).then(() => {
626
+ showToast("CSS copied to clipboard!");
627
+ });
628
+ }
629
+
630
+ function randomize() {
631
+ const randomColor = presets[Math.floor(Math.random() * presets.length)];
632
+ const randomRadius = Math.floor(Math.random() * 40);
633
+ const randomSpeed = Math.floor(Math.random() * 50) + 1;
634
+ setColor(randomColor);
635
+ document.getElementById('radiusRange').value = randomRadius;
636
+ setRadius(randomRadius);
637
+ document.getElementById('speedRange').value = randomSpeed;
638
+ setSpeed(randomSpeed);
639
+ showToast("Randomized Style!");
640
+ }
641
+
642
+ function exportConfig() {
643
+ const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(state, null, 2));
644
+ const downloadAnchorNode = document.createElement('a');
645
+ downloadAnchorNode.setAttribute("href", dataStr);
646
+ downloadAnchorNode.setAttribute("download", "orbital-theme-config.json");
647
+ document.body.appendChild(downloadAnchorNode);
648
+ downloadAnchorNode.click();
649
+ downloadAnchorNode.remove();
650
+ showToast("Config Downloaded!");
651
+ }
652
+
653
+ function updateUrl() {
654
+ const params = new URLSearchParams();
655
+ params.set('c', state.brandColor.replace('#', ''));
656
+ params.set('r', state.borderRadius);
657
+ params.set('b', state.glassBlur);
658
+ params.set('o', state.glassOpacity);
659
+ params.set('s', state.animationSpeed);
660
+ params.set('bs', state.bgStart.replace('#', ''));
661
+ params.set('be', state.bgEnd.replace('#', ''));
662
+ const newUrl = `${window.location.pathname}?${params.toString()}`;
663
+ window.history.replaceState({}, '', newUrl);
664
+ }
665
+
666
+ function loadFromUrl() {
667
+ const params = new URLSearchParams(window.location.search);
668
+ if(params.has('c')) state.brandColor = '#' + params.get('c');
669
+ if(params.has('r')) state.borderRadius = parseInt(params.get('r'));
670
+ if(params.has('b')) state.glassBlur = parseInt(params.get('b'));
671
+ if(params.has('o')) state.glassOpacity = parseInt(params.get('o'));
672
+ if(params.has('s')) state.animationSpeed = parseInt(params.get('s'));
673
+ if(params.has('bs')) state.bgStart = '#' + params.get('bs');
674
+ if(params.has('be')) state.bgEnd = '#' + params.get('be');
675
+ document.getElementById('radiusRange').value = state.borderRadius;
676
+ document.getElementById('blurRange').value = state.glassBlur;
677
+ document.getElementById('opacityRange').value = state.glassOpacity;
678
+ document.getElementById('speedRange').value = 51 - state.animationSpeed;
679
+ }
680
+
681
+ function openShareModal() {
682
+ updateSharePreview();
683
+ const shareUrl = window.location.href;
684
+ document.getElementById('shareUrl').value = shareUrl;
685
+ document.getElementById('shareModal').classList.add('active');
686
+ }
687
+
688
+ function closeShareModal() {
689
+ document.getElementById('shareModal').classList.remove('active');
690
+ }
691
+
692
+ function updateSharePreview() {
693
+ const preview = document.getElementById('sharePreview');
694
+ preview.style.background = `linear-gradient(135deg, ${state.bgStart}, ${state.bgEnd})`;
695
+ const previewSystem = preview.querySelector('.orbital-system');
696
+ const previewPlanet = preview.querySelector('.planet');
697
+ previewPlanet.style.background = `radial-gradient(circle at 30% 30%, ${state.brandColor}, #000)`;
698
+ previewPlanet.style.boxShadow = `0 0 50px ${state.brandColor}`;
699
+ const previewRing2 = preview.querySelector('.ring-2');
700
+ previewRing2.style.borderColor = state.brandColor;
701
+ document.getElementById('shareColorCode').textContent = state.brandColor;
702
+ }
703
+
704
+ function copyShareUrl() {
705
+ const url = document.getElementById('shareUrl').value;
706
+ navigator.clipboard.writeText(url).then(() => {
707
+ showToast("Share link copied!");
708
+ });
709
+ }
710
+
711
+ function shareToTwitter() {
712
+ const text = `Check out my custom Orbital UI theme! 🎨 ${state.brandColor} gradient with ${state.animationSpeed}s animation speed.`;
713
+ const url = encodeURIComponent(window.location.href);
714
+ window.open(`https://twitter.com/intent/tweet?text=${encodeURIComponent(text)}&url=${url}`, '_blank');
715
+ }
716
+
717
+ function shareToFacebook() {
718
+ const url = encodeURIComponent(window.location.href);
719
+ window.open(`https://www.facebook.com/sharer/sharer.php?u=${url}`, '_blank');
720
+ }
721
+
722
+ function shareToLinkedIn() {
723
+ const url = encodeURIComponent(window.location.href);
724
+ const title = encodeURIComponent('Orbital UI Custom Theme');
725
+ const summary = encodeURIComponent(`A stunning ${state.brandColor} themed UI configuration created with Orbital Customizer.`);
726
+ window.open(`https://www.linkedin.com/sharing/share-offsite/?url=${url}`, '_blank');
727
+ }
728
+
729
+ function shareNative() {
730
+ if(navigator.share) {
731
+ navigator.share({
732
+ title: 'My Orbital UI Theme',
733
+ text: `Check out this ${state.brandColor} themed UI configuration!`,
734
+ url: window.location.href
735
+ }).catch(() => {
736
+ showToast('Share cancelled');
737
+ });
738
+ } else {
739
+ copyShareUrl();
740
+ }
741
+ }
742
+
743
+ async function downloadImage() {
744
+ const preview = document.getElementById('sharePreview');
745
+ const canvas = await html2canvas(preview, {
746
+ backgroundColor: null,
747
+ scale: 2
748
+ });
749
+ const link = document.createElement('a');
750
+ link.download = `orbital-theme-${state.brandColor.replace('#', '')}.png`;
751
+ link.href = canvas.toDataURL();
752
+ link.click();
753
+ showToast("Image downloaded!");
754
+ }
755
+
756
+ document.getElementById('shareModal').addEventListener('click', (e) => {
757
+ if(e.target === document.getElementById('shareModal')) {
758
+ closeShareModal();
759
+ }
760
+ });
761
+
762
+ init();
763
+ </script>
764
  </body>
765
  </html>