mAI-models commited on
Commit
d32ff5a
·
verified ·
1 Parent(s): d666e19

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +792 -19
index.html CHANGED
@@ -1,19 +1,792 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Hero Roster Manager</title>
7
+ <!-- Google Fonts -->
8
+ <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;800&display=swap" rel="stylesheet">
9
+ <!-- Font Awesome for Icons -->
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
+
12
+ <style>
13
+ :root {
14
+ --primary: #6366f1;
15
+ --primary-dark: #4f46e5;
16
+ --secondary: #ec4899;
17
+ --bg-dark: #0f172a;
18
+ --card-bg: #1e293b;
19
+ --text-light: #f8fafc;
20
+ --text-gray: #94a3b8;
21
+ --success: #22c55e;
22
+ --danger: #ef4444;
23
+ --glass: rgba(30, 41, 59, 0.7);
24
+ --border: rgba(255, 255, 255, 0.1);
25
+ }
26
+
27
+ * {
28
+ box-sizing: border-box;
29
+ margin: 0;
30
+ padding: 0;
31
+ font-family: 'Outfit', sans-serif;
32
+ }
33
+
34
+ body {
35
+ background-color: var(--bg-dark);
36
+ color: var(--text-light);
37
+ min-height: 100vh;
38
+ background-image:
39
+ radial-gradient(at 0% 0%, rgba(99, 102, 241, 0.15) 0px, transparent 50%),
40
+ radial-gradient(at 100% 0%, rgba(236, 72, 153, 0.15) 0px, transparent 50%);
41
+ padding-bottom: 4rem;
42
+ }
43
+
44
+ /* Header */
45
+ header {
46
+ display: flex;
47
+ justify-content: space-between;
48
+ align-items: center;
49
+ padding: 1.5rem 2rem;
50
+ background: var(--glass);
51
+ backdrop-filter: blur(12px);
52
+ border-bottom: 1px solid var(--border);
53
+ position: sticky;
54
+ top: 0;
55
+ z-index: 100;
56
+ }
57
+
58
+ .brand {
59
+ font-weight: 800;
60
+ font-size: 1.5rem;
61
+ background: linear-gradient(to right, var(--primary), var(--secondary));
62
+ -webkit-background-clip: text;
63
+ background-clip: text;
64
+ color: transparent;
65
+ display: flex;
66
+ align-items: center;
67
+ gap: 0.5rem;
68
+ }
69
+
70
+ .anycoder-link {
71
+ font-size: 0.85rem;
72
+ color: var(--text-gray);
73
+ text-decoration: none;
74
+ transition: color 0.3s ease;
75
+ font-weight: 600;
76
+ }
77
+
78
+ .anycoder-link:hover {
79
+ color: var(--primary);
80
+ }
81
+
82
+ /* Main Container */
83
+ .container {
84
+ max-width: 1200px;
85
+ margin: 2rem auto;
86
+ padding: 0 1.5rem;
87
+ }
88
+
89
+ .controls {
90
+ display: flex;
91
+ justify-content: space-between;
92
+ align-items: center;
93
+ margin-bottom: 2rem;
94
+ flex-wrap: wrap;
95
+ gap: 1rem;
96
+ }
97
+
98
+ .stats {
99
+ color: var(--text-gray);
100
+ font-size: 0.9rem;
101
+ }
102
+
103
+ .btn {
104
+ padding: 0.75rem 1.5rem;
105
+ border-radius: 0.75rem;
106
+ border: none;
107
+ cursor: pointer;
108
+ font-weight: 600;
109
+ transition: all 0.3s ease;
110
+ display: inline-flex;
111
+ align-items: center;
112
+ gap: 0.5rem;
113
+ font-size: 0.95rem;
114
+ }
115
+
116
+ .btn-primary {
117
+ background: linear-gradient(135deg, var(--primary), var(--primary-dark));
118
+ color: white;
119
+ box-shadow: 0 4px 15px rgba(99, 102, 241, 0.3);
120
+ }
121
+
122
+ .btn-primary:hover {
123
+ transform: translateY(-2px);
124
+ box-shadow: 0 8px 25px rgba(99, 102, 241, 0.4);
125
+ }
126
+
127
+ .btn-icon {
128
+ padding: 0.5rem;
129
+ border-radius: 50%;
130
+ width: 36px;
131
+ height: 36px;
132
+ display: flex;
133
+ justify-content: center;
134
+ align-items: center;
135
+ }
136
+
137
+ /* Grid Layout */
138
+ .hero-grid {
139
+ display: grid;
140
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
141
+ gap: 2rem;
142
+ }
143
+
144
+ /* Hero Card */
145
+ .hero-card {
146
+ background: var(--card-bg);
147
+ border-radius: 1.5rem;
148
+ overflow: hidden;
149
+ border: 1px solid var(--border);
150
+ transition: all 0.3s ease;
151
+ position: relative;
152
+ display: flex;
153
+ flex-direction: column;
154
+ }
155
+
156
+ .hero-card:hover {
157
+ transform: translateY(-5px);
158
+ border-color: var(--primary);
159
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
160
+ }
161
+
162
+ .card-header {
163
+ height: 120px;
164
+ background-size: cover;
165
+ background-position: center;
166
+ position: relative;
167
+ }
168
+
169
+ .card-header::after {
170
+ content: '';
171
+ position: absolute;
172
+ bottom: 0;
173
+ left: 0;
174
+ width: 100%;
175
+ height: 60%;
176
+ background: linear-gradient(to top, var(--card-bg), transparent);
177
+ }
178
+
179
+ .hero-avatar {
180
+ width: 80px;
181
+ height: 80px;
182
+ border-radius: 50%;
183
+ border: 4px solid var(--card-bg);
184
+ position: absolute;
185
+ bottom: -40px;
186
+ left: 20px;
187
+ background-color: #334155;
188
+ object-fit: cover;
189
+ z-index: 2;
190
+ }
191
+
192
+ .card-body {
193
+ padding: 3rem 1.5rem 1.5rem;
194
+ flex-grow: 1;
195
+ }
196
+
197
+ .hero-name {
198
+ font-size: 1.5rem;
199
+ font-weight: 700;
200
+ margin-bottom: 0.25rem;
201
+ }
202
+
203
+ .hero-alias {
204
+ color: var(--secondary);
205
+ font-size: 0.9rem;
206
+ font-weight: 600;
207
+ text-transform: uppercase;
208
+ letter-spacing: 1px;
209
+ margin-bottom: 1rem;
210
+ display: block;
211
+ }
212
+
213
+ .hero-desc {
214
+ color: var(--text-gray);
215
+ font-size: 0.95rem;
216
+ line-height: 1.6;
217
+ margin-bottom: 1.5rem;
218
+ display: -webkit-box;
219
+ -webkit-line-clamp: 3;
220
+ -webkit-box-orient: vertical;
221
+ overflow: hidden;
222
+ }
223
+
224
+ /* Stats Bars */
225
+ .stat-row {
226
+ display: flex;
227
+ align-items: center;
228
+ margin-bottom: 0.5rem;
229
+ font-size: 0.85rem;
230
+ }
231
+
232
+ .stat-label {
233
+ width: 80px;
234
+ color: var(--text-gray);
235
+ }
236
+
237
+ .stat-bar-bg {
238
+ flex-grow: 1;
239
+ height: 6px;
240
+ background: rgba(255, 255, 255, 0.1);
241
+ border-radius: 3px;
242
+ overflow: hidden;
243
+ }
244
+
245
+ .stat-bar-fill {
246
+ height: 100%;
247
+ border-radius: 3px;
248
+ background: var(--primary);
249
+ }
250
+
251
+ .card-actions {
252
+ padding: 1rem 1.5rem;
253
+ border-top: 1px solid var(--border);
254
+ display: flex;
255
+ justify-content: flex-end;
256
+ gap: 0.5rem;
257
+ background: rgba(0, 0, 0, 0.1);
258
+ }
259
+
260
+ .action-btn {
261
+ background: transparent;
262
+ color: var(--text-gray);
263
+ border: 1px solid var(--border);
264
+ padding: 0.5rem 1rem;
265
+ border-radius: 0.5rem;
266
+ cursor: pointer;
267
+ transition: all 0.2s;
268
+ font-size: 0.85rem;
269
+ }
270
+
271
+ .action-btn:hover {
272
+ background: rgba(255, 255, 255, 0.05);
273
+ color: white;
274
+ }
275
+
276
+ .action-btn.delete:hover {
277
+ background: rgba(239, 68, 68, 0.1);
278
+ color: var(--danger);
279
+ border-color: var(--danger);
280
+ }
281
+
282
+ /* Modal */
283
+ .modal-overlay {
284
+ position: fixed;
285
+ top: 0;
286
+ left: 0;
287
+ width: 100%;
288
+ height: 100%;
289
+ background: rgba(0, 0, 0, 0.7);
290
+ backdrop-filter: blur(5px);
291
+ z-index: 1000;
292
+ display: flex;
293
+ justify-content: center;
294
+ align-items: center;
295
+ opacity: 0;
296
+ pointer-events: none;
297
+ transition: opacity 0.3s ease;
298
+ }
299
+
300
+ .modal-overlay.active {
301
+ opacity: 1;
302
+ pointer-events: all;
303
+ }
304
+
305
+ .modal {
306
+ background: var(--card-bg);
307
+ width: 90%;
308
+ max-width: 500px;
309
+ border-radius: 1.5rem;
310
+ padding: 2rem;
311
+ border: 1px solid var(--border);
312
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
313
+ transform: translateY(20px);
314
+ transition: transform 0.3s ease;
315
+ }
316
+
317
+ .modal-overlay.active .modal {
318
+ transform: translateY(0);
319
+ }
320
+
321
+ .modal-header {
322
+ display: flex;
323
+ justify-content: space-between;
324
+ align-items: center;
325
+ margin-bottom: 1.5rem;
326
+ }
327
+
328
+ .modal-title {
329
+ font-size: 1.5rem;
330
+ font-weight: 700;
331
+ }
332
+
333
+ .close-modal {
334
+ background: none;
335
+ border: none;
336
+ color: var(--text-gray);
337
+ font-size: 1.5rem;
338
+ cursor: pointer;
339
+ }
340
+
341
+ .form-group {
342
+ margin-bottom: 1.25rem;
343
+ }
344
+
345
+ .form-label {
346
+ display: block;
347
+ margin-bottom: 0.5rem;
348
+ color: var(--text-gray);
349
+ font-size: 0.9rem;
350
+ }
351
+
352
+ .form-input, .form-textarea {
353
+ width: 100%;
354
+ background: rgba(0, 0, 0, 0.2);
355
+ border: 1px solid var(--border);
356
+ padding: 0.75rem;
357
+ border-radius: 0.75rem;
358
+ color: white;
359
+ font-size: 1rem;
360
+ transition: border-color 0.3s;
361
+ }
362
+
363
+ .form-input:focus, .form-textarea:focus {
364
+ outline: none;
365
+ border-color: var(--primary);
366
+ }
367
+
368
+ .range-container {
369
+ display: flex;
370
+ align-items: center;
371
+ gap: 1rem;
372
+ }
373
+
374
+ input[type=range] {
375
+ flex-grow: 1;
376
+ accent-color: var(--primary);
377
+ }
378
+
379
+ .range-value {
380
+ width: 30px;
381
+ text-align: right;
382
+ font-weight: 600;
383
+ color: var(--primary);
384
+ }
385
+
386
+ /* Empty State */
387
+ .empty-state {
388
+ grid-column: 1 / -1;
389
+ text-align: center;
390
+ padding: 4rem 2rem;
391
+ background: rgba(255, 255, 255, 0.02);
392
+ border-radius: 1.5rem;
393
+ border: 2px dashed var(--border);
394
+ }
395
+
396
+ .empty-icon {
397
+ font-size: 3rem;
398
+ color: var(--text-gray);
399
+ margin-bottom: 1rem;
400
+ opacity: 0.5;
401
+ }
402
+
403
+ /* Notification */
404
+ .notification {
405
+ position: fixed;
406
+ bottom: 2rem;
407
+ right: 2rem;
408
+ background: var(--card-bg);
409
+ padding: 1rem 1.5rem;
410
+ border-radius: 0.75rem;
411
+ border-left: 4px solid var(--success);
412
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3);
413
+ transform: translateY(100px);
414
+ transition: transform 0.3s ease;
415
+ z-index: 2000;
416
+ display: flex;
417
+ align-items: center;
418
+ gap: 0.75rem;
419
+ }
420
+
421
+ .notification.show {
422
+ transform: translateY(0);
423
+ }
424
+
425
+ @media (max-width: 600px) {
426
+ .hero-grid {
427
+ grid-template-columns: 1fr;
428
+ }
429
+
430
+ .controls {
431
+ flex-direction: column;
432
+ align-items: stretch;
433
+ }
434
+
435
+ .btn {
436
+ justify-content: center;
437
+ }
438
+ }
439
+ </style>
440
+ </head>
441
+ <body>
442
+
443
+ <header>
444
+ <div class="brand">
445
+ <i class="fa-solid fa-bolt"></i> HeroForce
446
+ </div>
447
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">Built with anycoder</a>
448
+ </header>
449
+
450
+ <div class="container">
451
+ <div class="controls">
452
+ <div>
453
+ <h1 style="margin-bottom: 0.5rem;">Hero Roster</h1>
454
+ <span class="stats" id="heroCount">0 Heroes Active</span>
455
+ </div>
456
+ <button class="btn btn-primary" onclick="openModal()">
457
+ <i class="fa-solid fa-plus"></i> Add New Hero
458
+ </button>
459
+ </div>
460
+
461
+ <div class="hero-grid" id="heroGrid">
462
+ <!-- Heroes will be injected here -->
463
+ </div>
464
+ </div>
465
+
466
+ <!-- Create/Edit Modal -->
467
+ <div class="modal-overlay" id="heroModal">
468
+ <div class="modal">
469
+ <div class="modal-header">
470
+ <h2 class="modal-title" id="modalTitle">New Hero</h2>
471
+ <button class="close-modal" onclick="closeModal()">&times;</button>
472
+ </div>
473
+ <form id="heroForm">
474
+ <input type="hidden" id="heroId">
475
+
476
+ <div class="form-group">
477
+ <label class="form-label">Hero Name</label>
478
+ <input type="text" class="form-input" id="heroName" required placeholder="e.g. Captain Velocity">
479
+ </div>
480
+
481
+ <div class="form-group">
482
+ <label class="form-label">Alias / Secret Identity</label>
483
+ <input type="text" class="form-input" id="heroAlias" required placeholder="e.g. John Doe">
484
+ </div>
485
+
486
+ <div class="form-group">
487
+ <label class="form-label">Power Description</label>
488
+ <textarea class="form-textarea" id="heroDesc" rows="3" placeholder="Describe their abilities..."></textarea>
489
+ </div>
490
+
491
+ <div class="form-group">
492
+ <label class="form-label">Strength Level</label>
493
+ <div class="range-container">
494
+ <input type="range" id="heroStrength" min="1" max="100" value="50" oninput="updateRangeValue(this)">
495
+ <span class="range-value">50</span>
496
+ </div>
497
+ </div>
498
+
499
+ <div class="form-group">
500
+ <label class="form-label">Speed Level</label>
501
+ <div class="range-container">
502
+ <input type="range" id="heroSpeed" min="1" max="100" value="50" oninput="updateRangeValue(this)">
503
+ <span class="range-value">50</span>
504
+ </div>
505
+ </div>
506
+
507
+ <div class="form-group">
508
+ <label class="form-label">Intelligence Level</label>
509
+ <div class="range-container">
510
+ <input type="range" id="heroIntel" min="1" max="100" value="50" oninput="updateRangeValue(this)">
511
+ <span class="range-value">50</span>
512
+ </div>
513
+ </div>
514
+
515
+ <button type="submit" class="btn btn-primary" style="width: 100%">Save Hero</button>
516
+ </form>
517
+ </div>
518
+ </div>
519
+
520
+ <!-- Notification Toast -->
521
+ <div class="notification" id="notification">
522
+ <i class="fa-solid fa-check-circle" style="color: var(--success)"></i>
523
+ <span id="notificationMsg">Action successful</span>
524
+ </div>
525
+
526
+ <script>
527
+ // Initial Data (The 5 Heroes requested)
528
+ const defaultHeroes = [
529
+ {
530
+ id: '1',
531
+ name: 'Iron Guardian',
532
+ alias: 'Tony Stark-ish',
533
+ desc: 'A genius billionaire who built a high-tech suit of armor to protect the world from cosmic threats.',
534
+ strength: 85,
535
+ speed: 70,
536
+ intel: 95,
537
+ avatarColor: '#ef4444',
538
+ headerColor: '#991b1b'
539
+ },
540
+ {
541
+ id: '2',
542
+ name: 'Solar Flare',
543
+ alias: 'Elena Rodriguez',
544
+ desc: 'Capable of manipulating solar energy to fly and project intense beams of heat.',
545
+ strength: 75,
546
+ speed: 90,
547
+ intel: 60,
548
+ avatarColor: '#f59e0b',
549
+ headerColor: '#b45309'
550
+ },
551
+ {
552
+ id: '3',
553
+ name: 'Shadow Weaver',
554
+ alias: 'Damian Black',
555
+ desc: 'Can merge with shadows and teleport instantly between dark places. Master of stealth.',
556
+ strength: 50,
557
+ speed: 88,
558
+ intel: 80,
559
+ avatarColor: '#8b5cf6',
560
+ headerColor: '#5b21b6'
561
+ },
562
+ {
563
+ id: '4',
564
+ name: 'Titanus',
565
+ alias: 'Marcus Steel',
566
+ desc: 'Possesses immense physical strength and invulnerability. The tank of the team.',
567
+ strength: 98,
568
+ speed: 40,
569
+ intel: 55,
570
+ avatarColor: '#10b981',
571
+ headerColor: '#065f46'
572
+ },
573
+ {
574
+ id: '5',
575
+ name: 'Mind Reader',
576
+ alias: 'Sarah Jean',
577
+ desc: 'A powerful telepath who can read thoughts and influence the actions of others.',
578
+ strength: 30,
579
+ speed: 45,
580
+ intel: 100,
581
+ avatarColor: '#ec4899',
582
+ headerColor: '#9d174d'
583
+ }
584
+ ];
585
+
586
+ // State Management
587
+ let heroes = JSON.parse(localStorage.getItem('heroes')) || defaultHeroes;
588
+
589
+ // DOM Elements
590
+ const grid = document.getElementById('heroGrid');
591
+ const modalOverlay = document.getElementById('heroModal');
592
+ const heroForm = document.getElementById('heroForm');
593
+ const heroCountLabel = document.getElementById('heroCount');
594
+
595
+ // Render Function
596
+ function renderHeroes() {
597
+ grid.innerHTML = '';
598
+
599
+ if (heroes.length === 0) {
600
+ grid.innerHTML = `
601
+ <div class="empty-state">
602
+ <div class="empty-icon"><i class="fa-solid fa-mask"></i></div>
603
+ <h3>No Heroes Found</h3>
604
+ <p style="color: var(--text-gray); margin-top: 0.5rem;">The world needs saving! Add a hero to start.</p>
605
+ </div>
606
+ `;
607
+ heroCountLabel.textContent = `0 Heroes Active`;
608
+ return;
609
+ }
610
+
611
+ heroCountLabel.textContent = `${heroes.length} Heroes Active`;
612
+
613
+ heroes.forEach(hero => {
614
+ const card = document.createElement('div');
615
+ card.className = 'hero-card';
616
+
617
+ // Generate random-ish gradients based on name if no color set (for new adds)
618
+ const headerBg = hero.headerColor || `hsl(${Math.random() * 360}, 60%, 30%)`;
619
+ const avatarBg = hero.avatarColor || `hsl(${Math.random() * 360}, 70%, 50%)`;
620
+
621
+ card.innerHTML = `
622
+ <div class="card-header" style="background-color: ${headerBg};">
623
+ <div class="hero-avatar" style="background-color: ${avatarBg}; display: flex; justify-content: center; align-items: center; font-size: 2rem;">
624
+ ${hero.name.charAt(0)}
625
+ </div>
626
+ </div>
627
+ <div class="card-body">
628
+ <h3 class="hero-name">${hero.name}</h3>
629
+ <span class="hero-alias">${hero.alias}</span>
630
+ <p class="hero-desc">${hero.desc}</p>
631
+
632
+ <div class="stat-row">
633
+ <span class="stat-label">STR</span>
634
+ <div class="stat-bar-bg">
635
+ <div class="stat-bar-fill" style="width: ${hero.strength}%"></div>
636
+ </div>
637
+ </div>
638
+ <div class="stat-row">
639
+ <span class="stat-label">SPD</span>
640
+ <div class="stat-bar-bg">
641
+ <div class="stat-bar-fill" style="width: ${hero.speed}%; background-color: var(--secondary)"></div>
642
+ </div>
643
+ </div>
644
+ <div class="stat-row">
645
+ <span class="stat-label">INT</span>
646
+ <div class="stat-bar-bg">
647
+ <div class="stat-bar-fill" style="width: ${hero.intel}%; background-color: var(--success)"></div>
648
+ </div>
649
+ </div>
650
+ </div>
651
+ <div class="card-actions">
652
+ <button class="action-btn" onclick="editHero('${hero.id}')">
653
+ <i class="fa-solid fa-pen"></i> Edit
654
+ </button>
655
+ <button class="action-btn delete" onclick="deleteHero('${hero.id}')">
656
+ <i class="fa-solid fa-trash"></i>
657
+ </button>
658
+ </div>
659
+ `;
660
+ grid.appendChild(card);
661
+ });
662
+ }
663
+
664
+ // Form Handling
665
+ function openModal(isEdit = false) {
666
+ document.getElementById('modalTitle').textContent = isEdit ? 'Edit Hero' : 'New Hero';
667
+ modalOverlay.classList.add('active');
668
+ if(!isEdit) {
669
+ heroForm.reset();
670
+ document.getElementById('heroId').value = '';
671
+ // Reset ranges visuals
672
+ document.querySelectorAll('input[type=range]').forEach(input => {
673
+ input.nextElementSibling.textContent = input.value;
674
+ });
675
+ }
676
+ }
677
+
678
+ function closeModal() {
679
+ modalOverlay.classList.remove('active');
680
+ }
681
+
682
+ // Update range number display
683
+ function updateRangeValue(input) {
684
+ input.nextElementSibling.textContent = input.value;
685
+ }
686
+
687
+ // CRUD Operations
688
+ function saveHero(e) {
689
+ e.preventDefault();
690
+
691
+ const id = document.getElementById('heroId').value;
692
+ const name = document.getElementById('heroName').value;
693
+ const alias = document.getElementById('heroAlias').value;
694
+ const desc = document.getElementById('heroDesc').value;
695
+ const strength = document.getElementById('heroStrength').value;
696
+ const speed = document.getElementById('heroSpeed').value;
697
+ const intel = document.getElementById('heroIntel').value;
698
+
699
+ if (id) {
700
+ // Update
701
+ const index = heroes.findIndex(h => h.id === id);
702
+ if (index !== -1) {
703
+ heroes[index] = {
704
+ ...heroes[index],
705
+ name, alias, desc, strength, speed, intel
706
+ };
707
+ showNotification('Hero updated successfully!');
708
+ }
709
+ } else {
710
+ // Create
711
+ const newHero = {
712
+ id: Date.now().toString(),
713
+ name,
714
+ alias,
715
+ desc,
716
+ strength,
717
+ speed,
718
+ intel,
719
+ headerColor: `hsl(${Math.random() * 360}, 60%, 30%)`,
720
+ avatarColor: `hsl(${Math.random() * 360}, 70%, 50%)`
721
+ };
722
+ heroes.push(newHero);
723
+ showNotification('New hero recruited!');
724
+ }
725
+
726
+ saveToStorage();
727
+ renderHeroes();
728
+ closeModal();
729
+ }
730
+
731
+ function editHero(id) {
732
+ const hero = heroes.find(h => h.id === id);
733
+ if (!hero) return;
734
+
735
+ document.getElementById('heroId').value = hero.id;
736
+ document.getElementById('heroName').value = hero.name;
737
+ document.getElementById('heroAlias').value = hero.alias;
738
+ document.getElementById('heroDesc').value = hero.desc;
739
+
740
+ const sInput = document.getElementById('heroStrength');
741
+ sInput.value = hero.strength;
742
+ updateRangeValue(sInput);
743
+
744
+ const spInput = document.getElementById('heroSpeed');
745
+ spInput.value = hero.speed;
746
+ updateRangeValue(spInput);
747
+
748
+ const iInput = document.getElementById('heroIntel');
749
+ iInput.value = hero.intel;
750
+ updateRangeValue(iInput);
751
+
752
+ openModal(true);
753
+ }
754
+
755
+ function deleteHero(id) {
756
+ if(confirm('Are you sure you want to remove this hero from the roster?')) {
757
+ heroes = heroes.filter(h => h.id !== id);
758
+ saveToStorage();
759
+ renderHeroes();
760
+ showNotification('Hero removed from roster.');
761
+ }
762
+ }
763
+
764
+ // Storage
765
+ function saveToStorage() {
766
+ localStorage.setItem('heroes', JSON.stringify(heroes));
767
+ }
768
+
769
+ // Notification System
770
+ function showNotification(msg) {
771
+ const notif = document.getElementById('notification');
772
+ document.getElementById('notificationMsg').textContent = msg;
773
+ notif.classList.add('show');
774
+ setTimeout(() => {
775
+ notif.classList.remove('show');
776
+ }, 3000);
777
+ }
778
+
779
+ // Event Listeners
780
+ heroForm.addEventListener('submit', saveHero);
781
+
782
+ // Close modal when clicking outside
783
+ modalOverlay.addEventListener('click', (e) => {
784
+ if (e.target === modalOverlay) closeModal();
785
+ });
786
+
787
+ // Initial Load
788
+ renderHeroes();
789
+
790
+ </script>
791
+ </body>
792
+ </html>