Reaperxxxx commited on
Commit
5e4cb31
·
verified ·
1 Parent(s): ee6a831

Update docs.html

Browse files
Files changed (1) hide show
  1. docs.html +1649 -887
docs.html CHANGED
@@ -12,179 +12,175 @@
12
  box-sizing: border-box;
13
  }
14
 
15
- /* Enhanced theme system with comprehensive CSS variables */
 
 
 
 
 
 
 
 
 
 
 
 
16
  :root {
17
  --theme-primary: #00bcd4;
18
  --theme-secondary: #87ceeb;
19
- --theme-accent: #4caf50;
20
  --theme-bg-primary: #0a0a0a;
21
  --theme-bg-secondary: #1a1a2e;
22
  --theme-bg-tertiary: #16213e;
23
  --theme-text-primary: #e0e6ed;
24
  --theme-text-secondary: #87ceeb;
25
- --theme-border: #00bcd4;
26
- --theme-shadow: rgba(0, 188, 212, 0.3);
27
- --theme-glow: rgba(0, 188, 212, 0.8);
28
  }
29
 
30
  /* Red Theme */
31
  .theme-red {
32
  --theme-primary: #ff4444;
33
  --theme-secondary: #ff6b6b;
34
- --theme-accent: #ff8a80;
35
  --theme-bg-primary: #1a0a0a;
36
  --theme-bg-secondary: #2e1a1a;
37
  --theme-bg-tertiary: #3e1616;
38
- --theme-text-primary: #ffe0e0;
39
- --theme-text-secondary: #ff6b6b;
40
- --theme-border: #ff4444;
41
- --theme-shadow: rgba(255, 68, 68, 0.3);
42
- --theme-glow: rgba(255, 68, 68, 0.8);
43
  }
44
 
45
  /* Black Theme */
46
  .theme-black {
47
  --theme-primary: #ffffff;
48
  --theme-secondary: #cccccc;
49
- --theme-accent: #888888;
50
  --theme-bg-primary: #000000;
51
  --theme-bg-secondary: #1a1a1a;
52
  --theme-bg-tertiary: #2a2a2a;
53
  --theme-text-primary: #ffffff;
54
- --theme-text-secondary: #cccccc;
55
- --theme-border: #ffffff;
56
- --theme-shadow: rgba(255, 255, 255, 0.3);
57
- --theme-glow: rgba(255, 255, 255, 0.8);
58
  }
59
 
60
  /* Yellow Theme */
61
  .theme-yellow {
62
  --theme-primary: #ffd700;
63
  --theme-secondary: #ffeb3b;
64
- --theme-accent: #fff176;
65
  --theme-bg-primary: #1a1a0a;
66
  --theme-bg-secondary: #2e2e1a;
67
  --theme-bg-tertiary: #3e3e16;
68
- --theme-text-primary: #fffde7;
69
- --theme-text-secondary: #ffeb3b;
70
- --theme-border: #ffd700;
71
- --theme-shadow: rgba(255, 215, 0, 0.3);
72
- --theme-glow: rgba(255, 215, 0, 0.8);
73
  }
74
 
75
  /* Green Theme */
76
  .theme-green {
77
  --theme-primary: #4caf50;
78
- --theme-secondary: #66bb6a;
79
- --theme-accent: #81c784;
80
  --theme-bg-primary: #0a1a0a;
81
  --theme-bg-secondary: #1a2e1a;
82
  --theme-bg-tertiary: #163e16;
83
- --theme-text-primary: #e8f5e8;
84
- --theme-text-secondary: #66bb6a;
85
- --theme-border: #4caf50;
86
- --theme-shadow: rgba(76, 175, 80, 0.3);
87
- --theme-glow: rgba(76, 175, 80, 0.8);
88
  }
89
 
90
- html, body {
91
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
92
- background: linear-gradient(135deg, var(--theme-bg-primary) 0%, var(--theme-bg-secondary) 50%, var(--theme-bg-tertiary) 100%);
93
- color: var(--theme-text-primary);
94
- padding: 0;
95
- margin: 0;
96
- min-height: 100vh;
97
- position: relative;
98
- overflow-x: hidden;
99
- max-width: 100vw;
100
- transition: all 0.3s ease;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  }
102
 
103
- /* Completely restructured header with better layout */
104
  .header {
105
  background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
106
- border-bottom: 2px solid var(--theme-border);
107
- padding: 15px 20px;
108
- box-shadow: 0 4px 20px var(--theme-shadow);
 
109
  position: relative;
110
  z-index: 100;
111
- display: flex;
112
- justify-content: space-between;
113
- align-items: center;
114
  }
115
 
116
- .header-left {
117
- display: flex;
118
- flex-direction: column;
119
- align-items: flex-start;
 
 
 
 
 
 
 
 
 
 
120
  }
121
 
122
- .header-right {
123
  display: flex;
 
124
  align-items: center;
125
- gap: 15px;
 
 
126
  }
127
 
128
  .page-title {
129
- font-size: 1.8rem;
130
  font-weight: 900;
131
- background: linear-gradient(45deg, var(--theme-primary), var(--theme-secondary), var(--theme-text-primary), var(--theme-primary));
132
  background-size: 300% 300%;
133
  -webkit-background-clip: text;
134
  -webkit-text-fill-color: transparent;
135
  background-clip: text;
136
- margin-bottom: 2px;
137
- text-shadow: 0 0 30px var(--theme-glow);
138
  animation: gradientShift 4s ease-in-out infinite;
139
- letter-spacing: 1px;
140
- position: relative;
141
- }
142
-
143
- .page-title::after {
144
- content: '🔍';
145
- position: absolute;
146
- right: -25px;
147
- top: -3px;
148
- font-size: 1rem;
149
- animation: spark 2s infinite;
150
  }
151
 
152
  .creator {
153
- font-size: 0.75rem;
154
  background: linear-gradient(45deg, var(--theme-secondary), var(--theme-primary));
155
  -webkit-background-clip: text;
156
  -webkit-text-fill-color: transparent;
157
  background-clip: text;
158
  font-weight: 600;
159
- letter-spacing: 0.5px;
160
  }
161
 
162
- .header-stats {
163
- display: flex;
164
- flex-direction: column;
165
- align-items: flex-end;
166
- font-size: 0.8rem;
167
  color: var(--theme-text-secondary);
168
- }
169
-
170
- .online-indicator {
171
- display: flex;
172
- align-items: center;
173
- gap: 5px;
174
- margin-bottom: 3px;
175
- }
176
-
177
- .status-dot {
178
- width: 8px;
179
- height: 8px;
180
- border-radius: 50%;
181
- background: var(--theme-accent);
182
- animation: pulse 2s infinite;
183
- }
184
-
185
- @keyframes pulse {
186
- 0%, 100% { opacity: 1; }
187
- 50% { opacity: 0.5; }
188
  }
189
 
190
  @keyframes gradientShift {
@@ -192,470 +188,704 @@
192
  50% { background-position: 100% 50%; }
193
  }
194
 
195
- @keyframes spark {
196
- 0%, 100% { transform: rotate(0deg) scale(1); opacity: 0.7; }
197
- 50% { transform: rotate(15deg) scale(1.2); opacity: 1; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  }
199
 
200
- /* Enhanced loading animations */
201
- .loading-overlay {
202
  position: fixed;
203
  top: 0;
204
- left: 0;
205
- width: 100%;
206
- height: 100%;
207
- background: linear-gradient(135deg, var(--theme-bg-primary) 0%, var(--theme-bg-secondary) 100%);
208
- display: flex;
209
- flex-direction: column;
210
- justify-content: center;
211
- align-items: center;
212
- z-index: 9999;
213
- transition: opacity 0.5s ease;
214
- }
215
-
216
- .loading-overlay.hidden {
217
- opacity: 0;
218
- pointer-events: none;
219
  }
220
 
221
- .main-loading {
222
- display: flex;
223
- flex-direction: column;
224
- align-items: center;
225
- gap: 20px;
226
  }
227
 
228
- .loading-spinner-large {
229
- width: 60px;
230
- height: 60px;
231
- border: 4px solid rgba(255, 255, 255, 0.1);
232
- border-left: 4px solid var(--theme-primary);
233
- border-radius: 50%;
234
- animation: spin 1s linear infinite;
235
  }
236
 
237
- .loading-text-large {
238
- font-size: 1.2rem;
239
  color: var(--theme-primary);
240
- font-weight: bold;
241
- text-align: center;
242
  }
243
 
244
- .loading-subtext-large {
245
- font-size: 0.9rem;
246
- color: var(--theme-text-secondary);
247
- text-align: center;
248
- margin-top: 5px;
249
  }
250
 
251
- @keyframes spin {
252
- 0% { transform: rotate(0deg); }
253
- 100% { transform: rotate(360deg); }
 
 
 
 
 
 
254
  }
255
 
256
- .loading-enhanced {
257
- display: flex;
258
- flex-direction: column;
259
- align-items: center;
260
- padding: 40px 20px;
261
- gap: 15px;
262
  }
263
 
264
- .loading-pulse {
265
- width: 40px;
266
- height: 40px;
267
- border-radius: 50%;
268
  background: var(--theme-primary);
269
- animation: loadingPulse 1.5s ease-in-out infinite;
270
  }
271
 
272
- .loading-text {
273
- font-size: 1rem;
274
- color: var(--theme-primary);
275
- font-weight: bold;
276
- }
277
 
278
- .loading-subtext {
279
- font-size: 0.8rem;
280
- color: var(--theme-text-secondary);
281
- text-align: center;
 
282
  }
283
 
284
- @keyframes loadingPulse {
285
- 0%, 100% { transform: scale(1); opacity: 1; }
286
- 50% { transform: scale(1.2); opacity: 0.7; }
 
287
  }
288
 
289
- .main-layout {
290
- display: flex;
291
- min-height: calc(100vh - 90px);
 
 
 
 
 
 
292
  }
293
 
294
- .sidebar {
295
- width: 280px;
296
- background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
297
- border-right: 2px solid var(--theme-border);
298
- padding: 15px;
299
- position: fixed;
300
- left: 0;
301
- top: 90px;
302
- height: calc(100vh - 90px);
303
- overflow-y: auto;
304
- z-index: 50;
305
- box-shadow: 4px 0 20px var(--theme-shadow);
306
- transition: all 0.3s ease;
307
  }
308
 
309
- .sidebar-toggle {
310
- display: none;
311
- position: fixed;
312
- top: 100px;
313
- left: 10px;
314
- z-index: 60;
315
- background: linear-gradient(45deg, var(--theme-primary), var(--theme-secondary));
316
- border: none;
317
- border-radius: 50%;
318
- width: 40px;
319
- height: 40px;
320
  color: var(--theme-bg-primary);
321
- font-size: 1.2rem;
 
 
 
322
  cursor: pointer;
323
- box-shadow: 0 4px 15px var(--theme-shadow);
324
  transition: all 0.3s ease;
325
- }
326
-
327
- .search-section {
328
- background: linear-gradient(135deg, var(--theme-bg-tertiary) 0%, var(--theme-bg-secondary) 100%);
329
- border: 1px solid var(--theme-border);
330
- border-radius: 10px;
331
- padding: 15px;
332
- margin-bottom: 15px;
333
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
334
  position: relative;
335
  overflow: hidden;
336
  }
337
 
338
- .search-section::before {
339
- content: '';
340
- position: absolute;
341
- top: 0;
342
- left: 0;
343
- right: 0;
344
- height: 2px;
345
- background: linear-gradient(90deg, transparent, var(--theme-border), transparent);
346
  }
347
 
348
- .search-section h3 {
349
- font-size: 1rem;
350
- color: var(--theme-primary);
351
- margin-bottom: 12px;
352
- display: flex;
353
- align-items: center;
354
- gap: 6px;
355
  }
356
 
357
- .search-section h3::before {
358
- content: '';
359
- width: 3px;
360
- height: 15px;
361
- background: linear-gradient(45deg, var(--theme-primary), var(--theme-secondary));
362
- border-radius: 2px;
363
  }
364
 
365
- .search-input {
366
- padding: 10px 12px;
367
- font-size: 0.9rem;
368
- width: 100%;
369
- border: 2px solid var(--theme-border);
370
- border-radius: 6px;
371
- margin-bottom: 10px;
372
- background: rgba(26, 26, 46, 0.8);
373
- color: var(--theme-text-primary);
374
- transition: all 0.3s ease;
375
  }
376
 
377
- .search-input:focus {
378
- outline: none;
379
- border-color: var(--theme-secondary);
380
- box-shadow: 0 0 10px var(--theme-shadow);
 
 
381
  }
382
 
383
- .search-input::placeholder {
384
- color: var(--theme-text-secondary);
 
 
 
 
385
  }
386
 
387
- .search-btn {
388
- padding: 10px 16px;
389
- font-size: 0.9rem;
390
- background: linear-gradient(45deg, var(--theme-primary), var(--theme-secondary));
391
  color: var(--theme-bg-primary);
392
  border: none;
393
  border-radius: 6px;
394
  cursor: pointer;
395
- font-weight: bold;
396
- transition: all 0.3s ease;
397
- width: 100%;
398
  }
399
 
400
- .search-btn:hover {
401
- transform: translateY(-1px);
402
- box-shadow: 0 4px 15px var(--theme-shadow);
403
  }
404
 
405
- .search-btn:disabled {
406
- background: #555;
407
- cursor: not-allowed;
408
- transform: none;
409
- box-shadow: none;
410
  }
411
 
412
- .search-result {
413
- margin-top: 10px;
414
- padding: 12px;
415
- background: rgba(0, 188, 212, 0.1);
416
- border: 1px solid var(--theme-border);
417
- border-radius: 6px;
418
- font-size: 0.85rem;
419
  }
420
 
421
- .view-profile-btn {
422
- padding: 6px 12px;
423
- background: linear-gradient(45deg, var(--theme-accent), var(--theme-secondary));
424
- color: var(--theme-text-primary);
425
- border: none;
426
- border-radius: 4px;
427
- cursor: pointer;
428
- margin-top: 8px;
429
- font-weight: bold;
430
- font-size: 0.8rem;
431
- transition: all 0.3s ease;
432
  width: 100%;
 
 
 
 
 
433
  }
434
 
435
- .view-profile-btn:hover {
436
- transform: translateY(-1px);
437
- box-shadow: 0 3px 10px var(--theme-shadow);
 
438
  }
439
 
440
- /* Enhanced theme selector with green theme */
441
- .theme-selector {
442
- background: linear-gradient(135deg, var(--theme-bg-tertiary) 0%, var(--theme-bg-secondary) 100%);
443
- border: 1px solid var(--theme-border);
444
- border-radius: 10px;
445
- padding: 15px;
446
- margin-bottom: 15px;
447
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
448
  }
449
 
450
- .theme-selector h3 {
451
- font-size: 1rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
452
  color: var(--theme-primary);
453
- margin-bottom: 12px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
454
  display: flex;
455
  align-items: center;
456
- gap: 6px;
 
457
  }
458
 
459
- .theme-buttons {
 
 
 
 
 
 
 
 
 
 
460
  display: grid;
461
- grid-template-columns: 1fr 1fr;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  gap: 8px;
463
  }
464
 
465
- .theme-btn {
466
- padding: 8px 12px;
467
- border: 2px solid transparent;
468
- border-radius: 6px;
469
- cursor: pointer;
470
- font-weight: bold;
471
- font-size: 0.8rem;
472
- transition: all 0.3s ease;
473
- text-align: center;
474
- position: relative;
475
- overflow: hidden;
476
  }
477
 
478
- .theme-btn.current {
479
- border-color: var(--theme-primary);
480
- box-shadow: 0 0 10px var(--theme-shadow);
 
 
 
481
  }
482
 
483
- .theme-btn:hover {
484
- transform: translateY(-1px);
 
 
 
485
  }
486
 
487
- .theme-btn.default {
488
- background: linear-gradient(45deg, #00bcd4, #87ceeb);
489
- color: #0a0a0a;
 
490
  }
491
 
492
- .theme-btn.red {
493
- background: linear-gradient(45deg, #ff4444, #ff6b6b);
494
- color: #ffe0e0;
 
 
 
 
 
 
495
  }
496
 
497
- .theme-btn.black {
498
- background: linear-gradient(45deg, #ffffff, #cccccc);
499
- color: #000000;
 
 
 
 
500
  }
501
 
502
- .theme-btn.yellow {
503
- background: linear-gradient(45deg, #ffd700, #ffeb3b);
504
- color: #1a1a0a;
 
 
 
 
505
  }
506
 
507
- .theme-btn.green {
508
- background: linear-gradient(45deg, #4caf50, #66bb6a);
509
- color: #e8f5e8;
 
 
 
 
510
  }
511
 
512
- .content {
513
- flex: 1;
514
- margin-left: 280px;
515
- padding: 15px;
516
- overflow-x: auto;
517
  }
518
 
519
- .top-section {
520
  display: grid;
521
- grid-template-columns: 1fr 300px;
522
- gap: 15px;
523
  margin-bottom: 15px;
524
- min-height: 200px;
525
  }
526
 
527
- .banner-profile-container {
528
- position: relative;
529
- background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
530
- border: 1px solid var(--theme-border);
531
  border-radius: 10px;
 
 
 
532
  overflow: hidden;
533
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
 
534
  }
535
 
536
- .banner-profile-container::before {
537
- content: '';
538
- position: absolute;
539
- top: 0;
540
- left: 0;
541
- right: 0;
542
- height: 2px;
543
- background: linear-gradient(90deg, transparent, var(--theme-border), transparent);
544
- z-index: 2;
545
  }
546
 
547
- #banner {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
548
  width: 100%;
549
- height: 140px;
550
  object-fit: cover;
551
- border-radius: 0;
 
552
  }
553
 
554
- .banner-overlay {
555
- position: absolute;
556
- top: 2px;
557
- left: 0;
558
- right: 0;
559
- height: 138px;
560
- background: linear-gradient(
561
- to bottom,
562
- rgba(0, 0, 0, 0.1) 0%,
563
- rgba(0, 0, 0, 0.3) 50%,
564
- var(--theme-bg-secondary) 100%
565
- );
566
- z-index: 2;
567
  }
568
 
569
- #pfp {
570
- position: absolute;
571
- bottom: 10px;
572
- left: 50%;
573
- transform: translateX(-50%);
574
- width: 105px;
575
- height: 105px;
576
- object-fit: cover;
577
- border-radius: 5%;
578
- border: 3px solid var(--theme-border);
579
- box-shadow:
580
- 0 0 20px var(--theme-glow),
581
- 0 0 40px var(--theme-shadow);
582
- background: var(--theme-bg-secondary);
583
- z-index: 4;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
584
  }
585
 
586
- .profile-glow {
587
- position: absolute;
588
- bottom: -30px;
589
- left: 50%;
590
- transform: translateX(-50%);
591
- width: 100px;
592
- height: 100px;
593
- border-radius: 50%;
594
- background: radial-gradient(circle, var(--theme-shadow) 0%, var(--theme-shadow) 50%, transparent 70%);
595
- z-index: 3;
596
- animation: profileGlow 3s ease-in-out infinite alternate;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
597
  }
598
 
599
- @keyframes profileGlow {
600
- 0% { transform: translateX(-50%) scale(1); opacity: 0.6; }
601
- 100% { transform: translateX(-50%) scale(1.1); opacity: 0.9; }
 
 
 
 
 
 
602
  }
603
 
604
- .user-info-card {
605
- background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
606
- border: 1px solid var(--theme-border);
607
- border-radius: 10px;
608
- padding: 15px;
609
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
610
- position: relative;
611
- overflow: hidden;
612
- display: flex;
613
- flex-direction: column;
614
- justify-content: center;
615
  }
616
 
617
- .user-info-card::before {
618
- content: '';
619
- position: absolute;
620
- top: 0;
621
- left: 0;
622
- right: 0;
623
- height: 2px;
624
- background: linear-gradient(90deg, transparent, var(--theme-border), transparent);
625
  }
626
 
627
- .welcome-title {
628
- font-size: 1.2rem;
629
- font-weight: bold;
 
 
 
 
 
 
 
 
 
 
630
  color: var(--theme-text-primary);
631
- margin-bottom: 8px;
632
- background: linear-gradient(45deg, var(--theme-text-primary), var(--theme-secondary));
633
- -webkit-background-clip: text;
634
- -webkit-text-fill-color: transparent;
635
- background-clip: text;
636
- text-align: center;
637
  }
638
 
639
- .chat-id {
640
- font-size: 1rem;
641
- font-weight: bold;
642
- color: var(--theme-primary);
643
- background: rgba(0, 188, 212, 0.1);
644
- border: 1px solid var(--theme-border);
645
- border-radius: 6px;
646
- padding: 8px;
647
- text-align: center;
648
- margin-bottom: 10px;
649
  }
650
 
651
- /* Enhanced floating widget with smaller collapsed state */
652
  .floating-user-widget {
653
  position: fixed;
654
  bottom: 20px;
655
  right: 20px;
656
- width: 280px;
657
  background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
658
- border: 2px solid var(--theme-border);
659
  border-radius: 12px;
660
  padding: 15px;
661
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4);
@@ -665,9 +895,7 @@
665
  }
666
 
667
  .floating-user-widget.collapsed {
668
- height: 50px;
669
- width: 200px;
670
- padding: 10px 15px;
671
  overflow: hidden;
672
  }
673
 
@@ -679,10 +907,6 @@
679
  cursor: pointer;
680
  }
681
 
682
- .floating-user-widget.collapsed .widget-header {
683
- margin-bottom: 0;
684
- }
685
-
686
  .widget-title {
687
  font-weight: bold;
688
  color: var(--theme-primary);
@@ -708,8 +932,6 @@
708
 
709
  .floating-user-widget.collapsed .widget-content {
710
  opacity: 0;
711
- height: 0;
712
- overflow: hidden;
713
  }
714
 
715
  .widget-user-info {
@@ -723,7 +945,7 @@
723
  width: 40px;
724
  height: 40px;
725
  border-radius: 50%;
726
- border: 2px solid var(--theme-border);
727
  }
728
 
729
  .widget-user-details h4 {
@@ -740,7 +962,7 @@
740
 
741
  .widget-rank {
742
  background: rgba(0, 188, 212, 0.1);
743
- border: 1px solid var(--theme-border);
744
  border-radius: 6px;
745
  padding: 8px;
746
  text-align: center;
@@ -759,316 +981,181 @@
759
  color: var(--theme-primary);
760
  }
761
 
762
- /* Restructured and enhanced NFT section */
763
- .nfts-section {
764
- background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
765
- border: 1px solid var(--theme-border);
766
- border-radius: 15px;
767
- padding: 20px;
768
- margin-bottom: 20px;
769
- box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
770
- position: relative;
771
- overflow: hidden;
772
- }
773
-
774
- .nfts-section::before {
775
- content: '';
776
- position: absolute;
777
- top: 0;
778
- left: 0;
779
- right: 0;
780
- height: 3px;
781
- background: linear-gradient(90deg, transparent, var(--theme-primary), var(--theme-secondary), var(--theme-primary), transparent);
782
  }
783
 
784
- .nfts-section h3 {
785
- font-size: 1.3rem;
786
  color: var(--theme-primary);
787
- margin-bottom: 15px;
788
  display: flex;
789
  align-items: center;
790
- gap: 8px;
791
- font-weight: bold;
792
  }
793
 
794
- .nft-stats {
795
  display: grid;
796
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
797
- gap: 15px;
798
- margin-bottom: 20px;
799
- padding: 15px;
800
- background: rgba(0, 0, 0, 0.2);
801
- border-radius: 10px;
802
- border: 1px solid var(--theme-border);
803
- }
804
-
805
- .nft-stat {
806
- text-align: center;
807
- padding: 10px;
808
- background: linear-gradient(135deg, var(--theme-bg-tertiary), var(--theme-bg-secondary));
809
- border-radius: 8px;
810
- border: 1px solid var(--theme-border);
811
  }
812
 
813
- .nft-stat-value {
814
- display: block;
815
- font-size: 1.5rem;
 
 
816
  font-weight: bold;
817
- color: var(--theme-primary);
818
- margin-bottom: 5px;
819
- }
820
-
821
- .nft-stat-label {
822
  font-size: 0.8rem;
823
- color: var(--theme-text-secondary);
824
- text-transform: uppercase;
825
- letter-spacing: 0.5px;
826
- }
827
-
828
- #nftsContainer {
829
- display: grid;
830
- grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
831
- gap: 20px;
832
- margin-bottom: 20px;
833
- }
834
-
835
- .nft-card {
836
- background: linear-gradient(135deg, var(--theme-bg-tertiary) 0%, var(--theme-bg-secondary) 100%);
837
- border: 2px solid var(--theme-border);
838
- border-radius: 12px;
839
- padding: 15px;
840
  transition: all 0.3s ease;
841
- position: relative;
842
- overflow: hidden;
843
- animation: nftFadeIn 0.6s ease-out;
844
- }
845
-
846
- .nft-card:hover {
847
- transform: translateY(-5px) scale(1.02);
848
- box-shadow: 0 10px 30px var(--theme-shadow);
849
- border-color: var(--theme-secondary);
850
- }
851
-
852
- .nft-card::before {
853
- content: '';
854
- position: absolute;
855
- top: 0;
856
- left: 0;
857
- right: 0;
858
- height: 2px;
859
- background: linear-gradient(90deg, var(--theme-primary), var(--theme-secondary), var(--theme-primary));
860
  }
861
 
862
- @keyframes nftFadeIn {
863
- 0% { opacity: 0; transform: translateY(20px); }
864
- 100% { opacity: 1; transform: translateY(0); }
865
  }
866
 
867
- .show-all-btn {
868
- width: 100%;
869
- padding: 12px 20px;
870
- background: linear-gradient(45deg, var(--theme-primary), var(--theme-secondary));
871
- color: var(--theme-bg-primary);
872
- border: none;
873
- border-radius: 8px;
874
- font-size: 1rem;
875
- font-weight: bold;
876
- cursor: pointer;
877
- transition: all 0.3s ease;
878
  }
879
 
880
- .show-all-btn:hover {
881
- transform: translateY(-2px);
882
- box-shadow: 0 6px 20px var(--theme-shadow);
883
  }
884
 
885
- /* Enhanced stats sections with theme colors */
886
- .stats-grid {
887
- display: grid;
888
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
889
- gap: 20px;
890
- margin-bottom: 20px;
891
  }
892
 
893
- .stats-section {
894
- background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
895
- border: 1px solid var(--theme-border);
896
- border-radius: 12px;
897
- padding: 20px;
898
- box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
899
- position: relative;
900
- overflow: hidden;
901
  }
902
 
903
- .stats-section::before {
904
- content: '';
905
- position: absolute;
906
- top: 0;
907
- left: 0;
908
- right: 0;
909
- height: 2px;
910
- background: linear-gradient(90deg, transparent, var(--theme-border), transparent);
911
  }
912
 
913
- .stats-section h3 {
914
- font-size: 1.1rem;
915
- color: var(--theme-primary);
916
- margin-bottom: 15px;
917
  display: flex;
 
918
  align-items: center;
919
- gap: 8px;
920
- font-weight: bold;
 
 
921
  }
922
 
923
- .basic-stats-grid {
924
- display: grid;
925
- grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
926
- gap: 12px;
 
 
 
927
  }
928
 
929
- .stat-item {
930
- background: rgba(0, 0, 0, 0.2);
931
- border: 1px solid var(--theme-border);
932
- border-radius: 8px;
933
- padding: 12px;
934
- text-align: center;
935
- transition: all 0.3s ease;
 
 
 
 
936
  }
937
 
938
- .stat-item:hover {
939
- transform: translateY(-2px);
940
- box-shadow: 0 4px 15px var(--theme-shadow);
941
  }
942
 
943
- .stat-item strong {
944
- display: block;
945
- font-size: 0.8rem;
946
- color: var(--theme-text-secondary);
947
- margin-bottom: 5px;
948
- text-transform: uppercase;
949
- letter-spacing: 0.5px;
950
  }
951
-
952
- .stat-value {
953
- font-size: 1.2rem;
954
  font-weight: bold;
955
- color: var(--theme-primary);
956
  }
957
 
958
- /* Enhanced groups section */
959
- .groups-container {
960
- display: grid;
961
- grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
962
- gap: 15px;
963
  }
964
 
965
- .group-card {
966
- background: linear-gradient(135deg, var(--theme-bg-tertiary) 0%, var(--theme-bg-secondary) 100%);
967
- border: 1px solid var(--theme-border);
968
- border-radius: 10px;
969
- padding: 15px;
970
- transition: all 0.3s ease;
971
  position: relative;
972
  overflow: hidden;
973
  }
974
 
975
- .group-card:hover {
976
- transform: translateY(-3px);
977
- box-shadow: 0 6px 20px var(--theme-shadow);
978
- border-color: var(--theme-secondary);
979
- }
980
-
981
- .group-card::before {
982
  content: '';
983
  position: absolute;
984
- top: 0;
985
- left: 0;
986
- right: 0;
987
- height: 2px;
988
- background: linear-gradient(90deg, var(--theme-primary), var(--theme-secondary));
 
 
 
 
989
  }
990
 
991
- /* Mobile responsive */
992
- @media (max-width: 768px) {
993
- .header {
994
- flex-direction: column;
995
- align-items: center;
996
- text-align: center;
997
- padding: 10px;
998
- }
999
-
1000
- .header-right {
1001
- margin-top: 10px;
1002
- }
1003
-
1004
- .sidebar {
1005
- transform: translateX(-100%);
1006
- transition: transform 0.3s ease;
1007
- }
1008
-
1009
- .sidebar.open {
1010
- transform: translateX(0);
1011
- }
1012
-
1013
- .sidebar-toggle {
1014
- display: block;
1015
- }
1016
-
1017
- .content {
1018
- margin-left: 0;
1019
- padding: 10px;
1020
- }
1021
 
1022
- .top-section {
1023
- grid-template-columns: 1fr;
1024
- gap: 10px;
1025
- }
 
 
1026
 
 
 
1027
  .floating-user-widget {
1028
  width: calc(100vw - 40px);
1029
  right: 20px;
1030
  left: 20px;
1031
  bottom: 10px;
1032
  }
1033
-
1034
- .floating-user-widget.collapsed {
1035
- width: calc(100vw - 40px);
1036
- }
1037
-
1038
- .stats-grid {
1039
- grid-template-columns: 1fr;
1040
- }
1041
-
1042
- #nftsContainer {
1043
- grid-template-columns: 1fr;
1044
- }
1045
  }
1046
  </style>
1047
  </head>
1048
  <body>
1049
- <!-- Added main loading overlay -->
1050
- <div class="loading-overlay" id="mainLoadingOverlay">
1051
- <div class="main-loading">
1052
- <div class="loading-spinner-large"></div>
1053
- <div class="loading-text-large">Loading Finral Search</div>
1054
- <div class="loading-subtext-large">Initializing user interface...</div>
1055
- </div>
1056
  </div>
1057
 
1058
- <!-- Restructured header with better layout -->
1059
  <div class="header">
1060
- <div class="header-left">
1061
  <div class="page-title">Finral Search</div>
1062
  <div class="creator">✨ Crafted with Excellence by Saul ✨</div>
1063
- </div>
1064
- <div class="header-right">
1065
- <div class="header-stats">
1066
- <div class="online-indicator">
1067
- <div class="status-dot"></div>
1068
- <span>System Online</span>
1069
- </div>
1070
- <div>Advanced Search Engine</div>
1071
- </div>
1072
  </div>
1073
  </div>
1074
 
@@ -1076,7 +1163,7 @@
1076
 
1077
  <div class="main-layout">
1078
  <div class="sidebar" id="sidebar">
1079
- <!-- Enhanced theme selector with green theme -->
1080
  <div class="theme-selector">
1081
  <h3>🎨 Theme</h3>
1082
  <div class="theme-buttons">
@@ -1114,17 +1201,16 @@
1114
 
1115
  <div class="user-info-card">
1116
  <div class="welcome-title" id="welcomeTitle">Welcome to Finral</div>
1117
- <div id="userName" class="chat-id" style="display:none; margin-bottom: 8px; background: rgba(135, 206, 235, 0.1); border-color: rgba(135, 206, 235, 0.3);"></div>
1118
  <div id="chatId" class="chat-id">
1119
  <div class="loading">
1120
  <div class="loading-spinner"></div>
1121
  Loading...
1122
  </div>
1123
  </div>
1124
- <!-- Added rank display in user info section -->
1125
- <div id="userRank" class="chat-id" style="display:none; background: rgba(76, 175, 80, 0.1); border-color: rgba(76, 175, 80, 0.3); font-size: 0.9rem;">
1126
- <div class="rank-title">Global Rank</div>
1127
- <div class="rank-value">🥉 Bronze</div>
1128
  </div>
1129
  </div>
1130
  </div>
@@ -1175,54 +1261,54 @@
1175
  </div>
1176
  </div>
1177
 
1178
- <!-- Enhanced NFT section with better structure -->
 
 
 
 
 
 
 
 
 
 
1179
  <div class="nfts-section" id="nftsSection" style="display:none;">
1180
  <h3>🎨 NFT Collection</h3>
1181
- <div class="nft-stats" id="nftStats" style="display:none;">
1182
- <div class="nft-stat">
1183
- <span class="nft-stat-value" id="totalNfts">0</span>
1184
- <span class="nft-stat-label">Total NFTs</span>
1185
- </div>
1186
- <div class="nft-stat">
1187
- <span class="nft-stat-value" id="avgQuality">0</span>
1188
- <span class="nft-stat-label">Avg Quality</span>
1189
- </div>
1190
- <div class="nft-stat">
1191
- <span class="nft-stat-value" id="rarestHolders">0</span>
1192
- <span class="nft-stat-label">Rarest (Holders)</span>
1193
- </div>
1194
- <div class="nft-stat">
1195
- <span class="nft-stat-value" id="highestQuality">0</span>
1196
- <span class="nft-stat-label">Highest Quality</span>
1197
- </div>
1198
  </div>
1199
- <div id="nftsContainer">
1200
- <div class="loading-enhanced">
1201
- <div class="loading-pulse"></div>
1202
- <div class="loading-text">Loading NFT Collection</div>
1203
- <div class="loading-subtext">Fetching your digital treasures...</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1204
  </div>
1205
  </div>
 
1206
  <button id="showAllNftsBtn" class="show-all-btn" style="display:none;">
1207
  Show All NFTs (<span id="remainingCount">0</span> more)
1208
  </button>
1209
  </div>
1210
-
1211
- <!-- Enhanced groups section -->
1212
- <div class="stats-section" id="groupsSection" style="display:none;">
1213
- <h3>👥 Group Memberships</h3>
1214
- <div class="groups-container" id="groupsContainer">
1215
- <div class="loading-enhanced">
1216
- <div class="loading-pulse"></div>
1217
- <div class="loading-text">Loading Group Data</div>
1218
- <div class="loading-subtext">Gathering your community connections...</div>
1219
- </div>
1220
- </div>
1221
- </div>
1222
  </div>
1223
  </div>
1224
 
1225
- <!-- Enhanced floating user widget with smaller collapsed state -->
1226
  <div class="floating-user-widget" id="floatingWidget" style="display:none;">
1227
  <div class="widget-header" onclick="toggleWidget()">
1228
  <div class="widget-title">User Info</div>
@@ -1245,140 +1331,378 @@
1245
 
1246
  <script src="utils/xp-calculations.js"></script>
1247
  <script>
1248
- let currentTheme = 'default';
1249
- let currentUserId = null;
1250
-
1251
- // Initialize app
1252
- document.addEventListener('DOMContentLoaded', function() {
1253
- initializeApp();
1254
- });
1255
-
1256
- async function initializeApp() {
1257
- // Show main loading
1258
- const loadingOverlay = document.getElementById('mainLoadingOverlay');
1259
-
1260
- // Get user ID from Telegram WebApp
1261
- if (window.Telegram && window.Telegram.WebApp) {
1262
- const user = window.Telegram.WebApp.initDataUnsafe?.user;
1263
- if (user) {
1264
- currentUserId = user.id.toString();
1265
- await fetchUserTheme(currentUserId);
1266
- updateUserInfo(user);
1267
- }
1268
- }
1269
-
1270
- // Hide loading after 2 seconds
1271
- setTimeout(() => {
1272
- loadingOverlay.classList.add('hidden');
1273
- }, 2000);
1274
- }
1275
-
1276
- async function fetchUserTheme(userId) {
1277
  try {
1278
- const response = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/theme`);
1279
  const data = await response.json();
1280
 
1281
  if (data.status && data.theme) {
1282
- changeTheme(data.theme);
 
 
1283
  }
1284
  } catch (error) {
1285
- console.log('Failed to fetch user theme, using default');
 
1286
  }
1287
  }
1288
 
1289
  function changeTheme(theme) {
1290
- // Remove all theme classes
1291
- document.body.classList.remove('theme-default', 'theme-red', 'theme-black', 'theme-yellow', 'theme-green');
1292
 
1293
- // Add new theme class
1294
  if (theme !== 'default') {
1295
- document.body.classList.add(`theme-${theme}`);
1296
  }
1297
 
1298
- currentTheme = theme;
1299
-
1300
- // Update theme buttons
1301
  document.querySelectorAll('.theme-btn').forEach(btn => {
1302
  btn.classList.remove('current');
1303
  });
1304
- document.querySelector(`.theme-btn.${theme}`).classList.add('current');
 
 
 
1305
 
1306
  // Save theme preference
1307
- localStorage.setItem('finral-theme', theme);
1308
-
1309
- // Update theme on server if user is logged in
1310
- if (currentUserId) {
1311
- updateUserTheme(currentUserId, theme);
1312
- }
1313
  }
1314
 
1315
- async function updateUserTheme(userId, theme) {
1316
- try {
1317
- await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/theme`, {
1318
- method: 'POST',
1319
- headers: {
1320
- 'Content-Type': 'application/json',
1321
- },
1322
- body: JSON.stringify({ theme: theme })
1323
- });
1324
- } catch (error) {
1325
- console.log('Failed to update user theme on server');
 
 
 
 
1326
  }
1327
- }
1328
 
1329
- function updateUserInfo(user) {
1330
- const chatIdElement = document.getElementById('chatId');
1331
- const userNameElement = document.getElementById('userName');
1332
- const welcomeTitle = document.getElementById('welcomeTitle');
1333
- const userRankElement = document.getElementById('userRank');
1334
 
1335
- // Update chat ID
1336
- chatIdElement.innerHTML = `Chat ID: ${user.id}`;
 
 
1337
 
1338
- // Update user name
1339
- const fullName = `${user.first_name || ''} ${user.last_name || ''}`.trim();
1340
- if (fullName) {
1341
- userNameElement.innerHTML = `👤 ${fullName}`;
1342
- userNameElement.style.display = 'block';
1343
- welcomeTitle.innerHTML = `Welcome, ${user.first_name || 'User'}!`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1344
  }
1345
 
1346
- // Calculate and display rank
1347
- const rank = calculateGlobalRank(user.id);
1348
- userRankElement.innerHTML = `
1349
- <div class="rank-title">Global Rank</div>
1350
- <div class="rank-value">${rank}</div>
1351
- `;
1352
- userRankElement.style.display = 'block';
 
1353
 
1354
- // Update floating widget
1355
- updateFloatingWidget(user, rank);
1356
- document.getElementById('floatingWidget').style.display = 'block';
1357
  }
1358
 
1359
- function updateFloatingWidget(user, rank) {
1360
- const widgetName = document.getElementById('widgetName');
1361
- const widgetId = document.getElementById('widgetId');
1362
  const widgetRank = document.getElementById('widgetRank');
1363
- const widgetAvatar = document.getElementById('widgetAvatar');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1364
 
1365
- const fullName = `${user.first_name || ''} ${user.last_name || ''}`.trim();
1366
- widgetName.textContent = fullName || 'User';
1367
- widgetId.textContent = `ID: ${user.id}`;
1368
- widgetRank.textContent = rank;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1369
 
1370
- // Set avatar if available
1371
- if (user.photo_url) {
1372
- widgetAvatar.src = user.photo_url;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1373
  }
1374
  }
1375
 
1376
- function toggleWidget() {
1377
- const widget = document.getElementById('floatingWidget');
1378
- const collapseBtn = document.getElementById('collapseBtn');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1379
 
1380
- widget.classList.toggle('collapsed');
1381
- collapseBtn.classList.toggle('collapsed');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1382
  }
1383
 
1384
  // Sidebar toggle functionality
@@ -1387,93 +1711,531 @@
1387
 
1388
  sidebarToggle.addEventListener('click', () => {
1389
  sidebar.classList.toggle('open');
 
1390
  });
1391
 
1392
- // Search functionality with enhanced loading
1393
- const searchBtn = document.getElementById('searchBtn');
1394
- const searchInput = document.getElementById('searchInput');
1395
- const searchResult = document.getElementById('searchResult');
1396
-
1397
- searchBtn.addEventListener('click', async () => {
1398
- const userId = searchInput.value.trim();
1399
- if (!userId) return;
 
 
1400
 
1401
- // Show loading state
 
 
 
 
 
 
1402
  searchBtn.disabled = true;
1403
- searchBtn.innerHTML = `
1404
- <div class="loading-enhanced" style="padding: 0; gap: 10px;">
1405
- <div class="loading-pulse" style="width: 20px; height: 20px;"></div>
1406
- <span>Searching...</span>
1407
- </div>
1408
- `;
1409
-
1410
  try {
1411
- // Simulate API call
1412
- await new Promise(resolve => setTimeout(resolve, 2000));
1413
 
1414
- // Show result
1415
- searchResult.innerHTML = `
1416
- <div>User found: ${userId}</div>
1417
- <button class="view-profile-btn" onclick="viewProfile('${userId}')">View Profile</button>
1418
- `;
1419
- searchResult.style.display = 'block';
 
 
 
 
 
 
 
 
 
 
1420
  } catch (error) {
1421
- searchResult.innerHTML = `<div style="color: var(--theme-primary);">Error searching for user</div>`;
1422
  searchResult.style.display = 'block';
1423
- } finally {
1424
- searchBtn.disabled = false;
1425
- searchBtn.innerHTML = 'Search User';
1426
  }
1427
- });
1428
-
1429
- function viewProfile(userId) {
1430
- // Enhanced profile viewing with loading states
1431
- showProfileLoadingStates();
1432
 
1433
- // Simulate loading profile data
1434
- setTimeout(() => {
1435
- loadProfileData(userId);
1436
- }, 1500);
1437
  }
1438
 
1439
- function showProfileLoadingStates() {
1440
- // Show sections with loading states
1441
- document.getElementById('bannerContainer').style.display = 'block';
1442
- document.getElementById('statsGrid').style.display = 'block';
1443
- document.getElementById('nftsSection').style.display = 'block';
1444
- document.getElementById('groupsSection').style.display = 'block';
 
 
 
 
 
 
 
 
 
 
1445
  }
1446
 
1447
- function loadProfileData(userId) {
1448
- // Simulate loading complete - replace loading states with actual data
1449
- // This would be replaced with actual API calls
1450
 
1451
- // Remove loading states and show content
1452
- setTimeout(() => {
1453
- const nftsContainer = document.getElementById('nftsContainer');
1454
- nftsContainer.innerHTML = `
1455
- <div class="nft-card">
1456
- <h4 style="color: var(--theme-primary); margin-bottom: 10px;">Sample NFT #1</h4>
1457
- <p style="color: var(--theme-text-secondary);">Quality: Legendary</p>
1458
- <p style="color: var(--theme-text-secondary);">Holders: 5</p>
1459
- </div>
1460
- `;
1461
-
1462
- const groupsContainer = document.getElementById('groupsContainer');
1463
- groupsContainer.innerHTML = `
1464
- <div class="group-card">
1465
- <h4 style="color: var(--theme-primary); margin-bottom: 8px;">Sample Group</h4>
1466
- <p style="color: var(--theme-text-secondary); font-size: 0.8rem;">Member since: 2024</p>
1467
- </div>
1468
- `;
1469
- }, 1000);
1470
  }
1471
 
1472
- // Load saved theme on page load
1473
- const savedTheme = localStorage.getItem('finral-theme');
1474
- if (savedTheme) {
1475
  changeTheme(savedTheme);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1476
  }
1477
  </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1478
  </body>
1479
  </html>
 
12
  box-sizing: border-box;
13
  }
14
 
15
+ html, body {
16
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
17
+ background: linear-gradient(135deg, var(--theme-bg-primary) 0%, var(--theme-bg-secondary) 50%, var(--theme-bg-tertiary) 100%);
18
+ color: var(--theme-text-primary);
19
+ padding: 0;
20
+ margin: 0;
21
+ min-height: 100vh;
22
+ position: relative;
23
+ overflow-x: hidden;
24
+ max-width: 100vw;
25
+ }
26
+
27
+ /* Added comprehensive theme system with green theme */
28
  :root {
29
  --theme-primary: #00bcd4;
30
  --theme-secondary: #87ceeb;
 
31
  --theme-bg-primary: #0a0a0a;
32
  --theme-bg-secondary: #1a1a2e;
33
  --theme-bg-tertiary: #16213e;
34
  --theme-text-primary: #e0e6ed;
35
  --theme-text-secondary: #87ceeb;
36
+ --theme-accent: #00bcd4;
 
 
37
  }
38
 
39
  /* Red Theme */
40
  .theme-red {
41
  --theme-primary: #ff4444;
42
  --theme-secondary: #ff6b6b;
 
43
  --theme-bg-primary: #1a0a0a;
44
  --theme-bg-secondary: #2e1a1a;
45
  --theme-bg-tertiary: #3e1616;
46
+ --theme-text-primary: #f0f0f0;
47
+ --theme-accent: #ff4444;
 
 
 
48
  }
49
 
50
  /* Black Theme */
51
  .theme-black {
52
  --theme-primary: #ffffff;
53
  --theme-secondary: #cccccc;
 
54
  --theme-bg-primary: #000000;
55
  --theme-bg-secondary: #1a1a1a;
56
  --theme-bg-tertiary: #2a2a2a;
57
  --theme-text-primary: #ffffff;
58
+ --theme-accent: #ffffff;
 
 
 
59
  }
60
 
61
  /* Yellow Theme */
62
  .theme-yellow {
63
  --theme-primary: #ffd700;
64
  --theme-secondary: #ffeb3b;
 
65
  --theme-bg-primary: #1a1a0a;
66
  --theme-bg-secondary: #2e2e1a;
67
  --theme-bg-tertiary: #3e3e16;
68
+ --theme-text-primary: #f0f0f0;
69
+ --theme-accent: #ffd700;
 
 
 
70
  }
71
 
72
  /* Green Theme */
73
  .theme-green {
74
  --theme-primary: #4caf50;
75
+ --theme-secondary: #81c784;
 
76
  --theme-bg-primary: #0a1a0a;
77
  --theme-bg-secondary: #1a2e1a;
78
  --theme-bg-tertiary: #163e16;
79
+ --theme-text-primary: #f0f0f0;
80
+ --theme-accent: #4caf50;
 
 
 
81
  }
82
 
83
+ /* Loading animations */
84
+ .site-loading {
85
+ position: fixed;
86
+ top: 0;
87
+ left: 0;
88
+ width: 100%;
89
+ height: 100%;
90
+ background: var(--theme-bg-primary);
91
+ display: flex;
92
+ justify-content: center;
93
+ align-items: center;
94
+ z-index: 9999;
95
+ flex-direction: column;
96
+ }
97
+
98
+ .site-loading-spinner {
99
+ width: 60px;
100
+ height: 60px;
101
+ border: 4px solid rgba(255, 255, 255, 0.1);
102
+ border-left: 4px solid var(--theme-primary);
103
+ border-radius: 50%;
104
+ animation: spin 1s linear infinite;
105
+ margin-bottom: 20px;
106
+ }
107
+
108
+ .site-loading-text {
109
+ color: var(--theme-primary);
110
+ font-size: 1.2rem;
111
+ font-weight: 600;
112
+ }
113
+
114
+ @keyframes spin {
115
+ 0% { transform: rotate(0deg); }
116
+ 100% { transform: rotate(360deg); }
117
  }
118
 
119
+ /* Restructured header with better design */
120
  .header {
121
  background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
122
+ border-bottom: 2px solid var(--theme-primary);
123
+ padding: 20px 15px;
124
+ text-align: center;
125
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
126
  position: relative;
127
  z-index: 100;
128
+ backdrop-filter: blur(10px);
 
 
129
  }
130
 
131
+ .header::before {
132
+ content: '';
133
+ position: absolute;
134
+ top: 0;
135
+ left: 0;
136
+ right: 0;
137
+ bottom: 0;
138
+ background: linear-gradient(45deg, transparent 30%, rgba(255, 255, 255, 0.05) 50%, transparent 70%);
139
+ animation: shimmer 3s infinite;
140
+ }
141
+
142
+ @keyframes shimmer {
143
+ 0% { transform: translateX(-100%); }
144
+ 100% { transform: translateX(100%); }
145
  }
146
 
147
+ .header-content {
148
  display: flex;
149
+ flex-direction: column;
150
  align-items: center;
151
+ gap: 8px;
152
+ position: relative;
153
+ z-index: 2;
154
  }
155
 
156
  .page-title {
157
+ font-size: 2rem;
158
  font-weight: 900;
159
+ background: linear-gradient(45deg, var(--theme-primary), var(--theme-secondary), #ffffff, var(--theme-primary));
160
  background-size: 300% 300%;
161
  -webkit-background-clip: text;
162
  -webkit-text-fill-color: transparent;
163
  background-clip: text;
164
+ text-shadow: 0 0 30px var(--theme-primary);
 
165
  animation: gradientShift 4s ease-in-out infinite;
166
+ letter-spacing: 2px;
 
 
 
 
 
 
 
 
 
 
167
  }
168
 
169
  .creator {
170
+ font-size: 0.8rem;
171
  background: linear-gradient(45deg, var(--theme-secondary), var(--theme-primary));
172
  -webkit-background-clip: text;
173
  -webkit-text-fill-color: transparent;
174
  background-clip: text;
175
  font-weight: 600;
176
+ letter-spacing: 1px;
177
  }
178
 
179
+ .page-subtitle {
180
+ font-size: 0.9rem;
 
 
 
181
  color: var(--theme-text-secondary);
182
+ font-style: italic;
183
+ opacity: 0.8;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  }
185
 
186
  @keyframes gradientShift {
 
188
  50% { background-position: 100% 50%; }
189
  }
190
 
191
+ /* Improved sidebar with theme selector */
192
+ .sidebar-toggle {
193
+ position: fixed;
194
+ top: 20px;
195
+ left: 20px;
196
+ background: var(--theme-primary);
197
+ color: var(--theme-bg-primary);
198
+ border: none;
199
+ border-radius: 50%;
200
+ width: 50px;
201
+ height: 50px;
202
+ font-size: 1.2rem;
203
+ cursor: pointer;
204
+ z-index: 1001;
205
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
206
+ transition: all 0.3s ease;
207
+ }
208
+
209
+ .sidebar-toggle:hover {
210
+ transform: scale(1.1);
211
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
212
  }
213
 
214
+ .sidebar {
 
215
  position: fixed;
216
  top: 0;
217
+ left: -350px;
218
+ width: 350px;
219
+ height: 100vh;
220
+ background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
221
+ border-right: 2px solid var(--theme-primary);
222
+ padding: 80px 20px 20px;
223
+ transition: left 0.3s ease;
224
+ z-index: 1000;
225
+ overflow-y: auto;
226
+ backdrop-filter: blur(10px);
 
 
 
 
 
227
  }
228
 
229
+ .sidebar.open {
230
+ left: 0;
 
 
 
231
  }
232
 
233
+ .theme-selector {
234
+ margin-bottom: 30px;
235
+ padding: 20px;
236
+ background: rgba(255, 255, 255, 0.05);
237
+ border-radius: 12px;
238
+ border: 1px solid var(--theme-primary);
 
239
  }
240
 
241
+ .theme-selector h3 {
 
242
  color: var(--theme-primary);
243
+ margin-bottom: 15px;
244
+ font-size: 1.1rem;
245
  }
246
 
247
+ .theme-buttons {
248
+ display: grid;
249
+ grid-template-columns: 1fr 1fr;
250
+ gap: 10px;
 
251
  }
252
 
253
+ .theme-btn {
254
+ padding: 10px 15px;
255
+ border: 2px solid transparent;
256
+ border-radius: 8px;
257
+ background: var(--theme-bg-tertiary);
258
+ color: var(--theme-text-primary);
259
+ cursor: pointer;
260
+ transition: all 0.3s ease;
261
+ font-weight: 600;
262
  }
263
 
264
+ .theme-btn:hover {
265
+ border-color: var(--theme-primary);
266
+ transform: translateY(-2px);
 
 
 
267
  }
268
 
269
+ .theme-btn.current {
270
+ border-color: var(--theme-primary);
 
 
271
  background: var(--theme-primary);
272
+ color: var(--theme-bg-primary);
273
  }
274
 
275
+ .theme-btn.red { background: linear-gradient(45deg, #ff4444, #ff6b6b); }
276
+ .theme-btn.black { background: linear-gradient(45deg, #000000, #333333); }
277
+ .theme-btn.yellow { background: linear-gradient(45deg, #ffd700, #ffeb3b); }
278
+ .theme-btn.green { background: linear-gradient(45deg, #4caf50, #81c784); }
 
279
 
280
+ .search-section {
281
+ padding: 20px;
282
+ background: rgba(255, 255, 255, 0.05);
283
+ border-radius: 12px;
284
+ border: 1px solid var(--theme-primary);
285
  }
286
 
287
+ .search-section h3 {
288
+ color: var(--theme-primary);
289
+ margin-bottom: 15px;
290
+ font-size: 1.1rem;
291
  }
292
 
293
+ .search-input {
294
+ width: 100%;
295
+ padding: 12px;
296
+ border: 2px solid var(--theme-primary);
297
+ border-radius: 8px;
298
+ background: var(--theme-bg-tertiary);
299
+ color: var(--theme-text-primary);
300
+ font-size: 1rem;
301
+ margin-bottom: 15px;
302
  }
303
 
304
+ .search-input:focus {
305
+ outline: none;
306
+ box-shadow: 0 0 10px var(--theme-primary);
 
 
 
 
 
 
 
 
 
 
307
  }
308
 
309
+ .search-btn {
310
+ width: 100%;
311
+ padding: 12px;
312
+ background: var(--theme-primary);
 
 
 
 
 
 
 
313
  color: var(--theme-bg-primary);
314
+ border: none;
315
+ border-radius: 8px;
316
+ font-size: 1rem;
317
+ font-weight: 600;
318
  cursor: pointer;
 
319
  transition: all 0.3s ease;
 
 
 
 
 
 
 
 
 
320
  position: relative;
321
  overflow: hidden;
322
  }
323
 
324
+ .search-btn:hover {
325
+ transform: translateY(-2px);
326
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
 
 
 
 
 
327
  }
328
 
329
+ .search-btn:disabled {
330
+ opacity: 0.7;
331
+ cursor: not-allowed;
 
 
 
 
332
  }
333
 
334
+ .loading-dots {
335
+ display: flex;
336
+ justify-content: center;
337
+ gap: 4px;
 
 
338
  }
339
 
340
+ .loading-dot {
341
+ width: 8px;
342
+ height: 8px;
343
+ background: currentColor;
344
+ border-radius: 50%;
345
+ animation: loadingDot 1.4s infinite ease-in-out both;
 
 
 
 
346
  }
347
 
348
+ .loading-dot:nth-child(1) { animation-delay: -0.32s; }
349
+ .loading-dot:nth-child(2) { animation-delay: -0.16s; }
350
+
351
+ @keyframes loadingDot {
352
+ 0%, 80%, 100% { transform: scale(0); }
353
+ 40% { transform: scale(1); }
354
  }
355
 
356
+ .search-result {
357
+ margin-top: 15px;
358
+ padding: 15px;
359
+ background: var(--theme-bg-tertiary);
360
+ border-radius: 8px;
361
+ border: 1px solid var(--theme-primary);
362
  }
363
 
364
+ .view-profile-btn {
365
+ margin-top: 10px;
366
+ padding: 8px 16px;
367
+ background: var(--theme-primary);
368
  color: var(--theme-bg-primary);
369
  border: none;
370
  border-radius: 6px;
371
  cursor: pointer;
372
+ font-weight: 600;
 
 
373
  }
374
 
375
+ .main-layout {
376
+ display: flex;
377
+ min-height: calc(100vh - 120px);
378
  }
379
 
380
+ .content {
381
+ flex: 1;
382
+ padding: 20px;
383
+ max-width: 100%;
 
384
  }
385
 
386
+ /* Improved user info section with rank display */
387
+ .top-section {
388
+ margin-bottom: 30px;
 
 
 
 
389
  }
390
 
391
+ .banner-profile-container {
392
+ position: relative;
 
 
 
 
 
 
 
 
 
393
  width: 100%;
394
+ height: 200px;
395
+ border-radius: 15px;
396
+ overflow: hidden;
397
+ margin-bottom: 20px;
398
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
399
  }
400
 
401
+ .banner-profile-container img#banner {
402
+ width: 100%;
403
+ height: 100%;
404
+ object-fit: cover;
405
  }
406
 
407
+ .banner-overlay {
408
+ position: absolute;
409
+ bottom: 0;
410
+ left: 0;
411
+ right: 0;
412
+ height: 50%;
413
+ background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
 
414
  }
415
 
416
+ .profile-glow {
417
+ position: absolute;
418
+ bottom: -40px;
419
+ left: 20px;
420
+ width: 80px;
421
+ height: 80px;
422
+ border-radius: 50%;
423
+ background: radial-gradient(circle, var(--theme-primary), transparent);
424
+ filter: blur(20px);
425
+ }
426
+
427
+ .banner-profile-container img#pfp {
428
+ position: absolute;
429
+ bottom: -40px;
430
+ left: 20px;
431
+ width: 80px;
432
+ height: 80px;
433
+ border-radius: 50%;
434
+ border: 4px solid var(--theme-primary);
435
+ object-fit: cover;
436
+ background: var(--theme-bg-secondary);
437
+ }
438
+
439
+ .user-info-card {
440
+ background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
441
+ border: 2px solid var(--theme-primary);
442
+ border-radius: 15px;
443
+ padding: 25px;
444
+ margin-top: 50px;
445
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
446
+ position: relative;
447
+ }
448
+
449
+ .welcome-title {
450
+ font-size: 1.8rem;
451
+ font-weight: 700;
452
  color: var(--theme-primary);
453
+ margin-bottom: 15px;
454
+ text-align: center;
455
+ }
456
+
457
+ .chat-id {
458
+ background: rgba(255, 255, 255, 0.1);
459
+ border: 1px solid var(--theme-primary);
460
+ border-radius: 8px;
461
+ padding: 12px;
462
+ text-align: center;
463
+ font-weight: 600;
464
+ color: var(--theme-text-primary);
465
+ margin-bottom: 10px;
466
+ }
467
+
468
+ .user-rank {
469
+ background: linear-gradient(45deg, var(--theme-primary), var(--theme-secondary));
470
+ color: var(--theme-bg-primary);
471
+ padding: 8px 16px;
472
+ border-radius: 20px;
473
+ font-weight: 600;
474
+ text-align: center;
475
+ margin-top: 10px;
476
+ font-size: 0.9rem;
477
+ }
478
+
479
+ .loading {
480
  display: flex;
481
  align-items: center;
482
+ justify-content: center;
483
+ gap: 10px;
484
  }
485
 
486
+ .loading-spinner {
487
+ width: 20px;
488
+ height: 20px;
489
+ border: 2px solid rgba(255, 255, 255, 0.3);
490
+ border-left: 2px solid var(--theme-primary);
491
+ border-radius: 50%;
492
+ animation: spin 1s linear infinite;
493
+ }
494
+
495
+ /* Improved stats grid with better theming */
496
+ .stats-grid {
497
  display: grid;
498
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
499
+ gap: 20px;
500
+ margin-bottom: 30px;
501
+ }
502
+
503
+ .stats-section {
504
+ background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
505
+ border: 2px solid var(--theme-primary);
506
+ border-radius: 12px;
507
+ padding: 20px;
508
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
509
+ }
510
+
511
+ .stats-section h3 {
512
+ font-size: 1.2rem;
513
+ color: var(--theme-primary);
514
+ margin-bottom: 15px;
515
+ display: flex;
516
+ align-items: center;
517
  gap: 8px;
518
  }
519
 
520
+ .basic-stats-grid {
521
+ display: grid;
522
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
523
+ gap: 15px;
 
 
 
 
 
 
 
524
  }
525
 
526
+ .stat-item {
527
+ text-align: center;
528
+ padding: 15px;
529
+ background: rgba(255, 255, 255, 0.05);
530
+ border-radius: 8px;
531
+ border: 1px solid var(--theme-primary);
532
  }
533
 
534
+ .stat-item strong {
535
+ display: block;
536
+ color: var(--theme-secondary);
537
+ font-size: 0.9rem;
538
+ margin-bottom: 5px;
539
  }
540
 
541
+ .stat-value {
542
+ font-size: 1.1rem;
543
+ font-weight: 700;
544
+ color: var(--theme-primary);
545
  }
546
 
547
+ /* Restructured and smaller NFT cards with loading animations */
548
+ .nfts-section {
549
+ background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
550
+ border: 2px solid var(--theme-primary);
551
+ border-radius: 12px;
552
+ padding: 20px;
553
+ margin-bottom: 20px;
554
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
555
+ position: relative;
556
  }
557
 
558
+ .nfts-section h3 {
559
+ font-size: 1.2rem;
560
+ color: var(--theme-primary);
561
+ margin-bottom: 20px;
562
+ display: flex;
563
+ align-items: center;
564
+ gap: 10px;
565
  }
566
 
567
+ .nft-loading {
568
+ display: flex;
569
+ justify-content: center;
570
+ align-items: center;
571
+ padding: 40px;
572
+ flex-direction: column;
573
+ gap: 15px;
574
  }
575
 
576
+ .nft-loading-spinner {
577
+ width: 40px;
578
+ height: 40px;
579
+ border: 3px solid rgba(255, 255, 255, 0.1);
580
+ border-left: 3px solid var(--theme-primary);
581
+ border-radius: 50%;
582
+ animation: spin 1s linear infinite;
583
  }
584
 
585
+ .nft-loading-text {
586
+ color: var(--theme-primary);
587
+ font-weight: 600;
 
 
588
  }
589
 
590
+ .nfts-grid {
591
  display: grid;
592
+ grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
593
+ gap: 12px;
594
  margin-bottom: 15px;
 
595
  }
596
 
597
+ .nft-card {
 
 
 
598
  border-radius: 10px;
599
+ padding: 10px;
600
+ transition: all 0.3s ease;
601
+ position: relative;
602
  overflow: hidden;
603
+ cursor: pointer;
604
+ min-height: 200px;
605
  }
606
 
607
+ .nft-card:hover {
608
+ transform: translateY(-3px);
609
+ }
610
+
611
+ /* NFT Quality Classes with theme colors */
612
+ .nft-card.basic {
613
+ background: linear-gradient(135deg, var(--theme-bg-tertiary) 0%, var(--theme-bg-secondary) 100%);
614
+ border: 1px solid #666;
615
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
616
  }
617
 
618
+ .nft-card.better {
619
+ background: linear-gradient(135deg, var(--theme-bg-tertiary) 0%, var(--theme-bg-secondary) 100%);
620
+ border: 1px solid #4caf50;
621
+ box-shadow: 0 3px 10px rgba(76, 175, 80, 0.3);
622
+ }
623
+
624
+ .nft-card.even-better {
625
+ background: linear-gradient(135deg, var(--theme-bg-tertiary) 0%, var(--theme-bg-secondary) 100%);
626
+ border: 1px solid #2196f3;
627
+ box-shadow: 0 4px 12px rgba(33, 150, 243, 0.4);
628
+ }
629
+
630
+ .nft-card.way-better {
631
+ background: linear-gradient(135deg, var(--theme-bg-tertiary) 0%, var(--theme-bg-secondary) 100%);
632
+ border: 1px solid #9c27b0;
633
+ box-shadow: 0 5px 15px rgba(156, 39, 176, 0.4);
634
+ }
635
+
636
+ .nft-card.legendary {
637
+ background: linear-gradient(135deg, #ffd700 0%, #ffb300 100%);
638
+ border: 2px solid #ffd700;
639
+ box-shadow: 0 6px 20px rgba(255, 215, 0, 0.5);
640
+ color: #000;
641
+ }
642
+
643
+ .nft-image {
644
  width: 100%;
645
+ height: 100px;
646
  object-fit: cover;
647
+ border-radius: 6px;
648
+ margin-bottom: 8px;
649
  }
650
 
651
+ .nft-info {
652
+ font-size: 0.8rem;
 
 
 
 
 
 
 
 
 
 
 
653
  }
654
 
655
+ .nft-name {
656
+ font-weight: 600;
657
+ margin-bottom: 4px;
658
+ font-size: 0.9rem;
659
+ }
660
+
661
+ .nft-details {
662
+ display: flex;
663
+ justify-content: space-between;
664
+ margin-bottom: 4px;
665
+ font-size: 0.75rem;
666
+ }
667
+
668
+ .quality-badge {
669
+ padding: 2px 6px;
670
+ border-radius: 4px;
671
+ font-size: 0.7rem;
672
+ font-weight: 600;
673
+ }
674
+
675
+ .quality-basic { background: #666; color: white; }
676
+ .quality-better { background: #4caf50; color: white; }
677
+ .quality-even-better { background: #2196f3; color: white; }
678
+ .quality-way-better { background: #9c27b0; color: white; }
679
+ .quality-legendary { background: #ffd700; color: black; }
680
+
681
+ /* Smaller collapsed floating widget */
682
+ .floating-user-widget {
683
+ position: fixed;
684
+ bottom: 20px;
685
+ right: 20px;
686
+ width: 280px;
687
+ background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
688
+ border: 2px solid var(--theme-primary);
689
+ border-radius: 12px;
690
+ padding: 15px;
691
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4);
692
+ z-index: 1000;
693
+ transition: all 0.3s ease;
694
+ backdrop-filter: blur(10px);
695
+ }
696
+
697
+ .floating-user-widget.collapsed {
698
+ height: 50px;
699
+ overflow: hidden;
700
+ padding: 10px 15px;
701
+ }
702
+
703
+ .widget-header {
704
+ display: flex;
705
+ justify-content: space-between;
706
+ align-items: center;
707
+ margin-bottom: 10px;
708
+ cursor: pointer;
709
+ }
710
+
711
+ .widget-title {
712
+ font-weight: bold;
713
+ color: var(--theme-primary);
714
+ font-size: 0.9rem;
715
+ }
716
+
717
+ .collapse-btn {
718
+ background: none;
719
+ border: none;
720
+ color: var(--theme-primary);
721
+ font-size: 1rem;
722
+ cursor: pointer;
723
+ transition: transform 0.3s ease;
724
+ }
725
+
726
+ .collapse-btn.collapsed {
727
+ transform: rotate(180deg);
728
+ }
729
+
730
+ .widget-content {
731
+ transition: opacity 0.3s ease;
732
+ }
733
+
734
+ .widget-user-info {
735
+ display: flex;
736
+ align-items: center;
737
+ gap: 10px;
738
+ margin-bottom: 10px;
739
+ }
740
+
741
+ .widget-avatar {
742
+ width: 40px;
743
+ height: 40px;
744
+ border-radius: 50%;
745
+ border: 2px solid var(--theme-primary);
746
+ }
747
+
748
+ .widget-user-details h4 {
749
+ color: var(--theme-text-primary);
750
+ font-size: 0.9rem;
751
+ margin-bottom: 2px;
752
+ }
753
+
754
+ .widget-user-details p {
755
+ color: var(--theme-text-secondary);
756
+ font-size: 0.8rem;
757
+ }
758
+
759
+ .widget-rank {
760
+ text-align: center;
761
+ padding: 8px;
762
+ background: rgba(255, 255, 255, 0.1);
763
+ border-radius: 6px;
764
+ border: 1px solid var(--theme-primary);
765
+ }
766
+
767
+ .rank-title {
768
+ font-size: 0.8rem;
769
+ color: var(--theme-text-secondary);
770
+ margin-bottom: 4px;
771
+ }
772
+
773
+ .rank-value {
774
+ font-weight: 600;
775
+ color: var(--theme-primary);
776
+ font-size: 0.9rem;
777
+ }
778
+
779
+ /* Groups loading animation */
780
+ .groups-loading {
781
+ display: flex;
782
+ justify-content: center;
783
+ align-items: center;
784
+ padding: 30px;
785
+ flex-direction: column;
786
+ gap: 15px;
787
+ }
788
+
789
+ .groups-loading-spinner {
790
+ width: 35px;
791
+ height: 35px;
792
+ border: 3px solid rgba(255, 255, 255, 0.1);
793
+ border-left: 3px solid var(--theme-primary);
794
+ border-radius: 50%;
795
+ animation: spin 1s linear infinite;
796
+ }
797
+
798
+ .groups-loading-text {
799
+ color: var(--theme-primary);
800
+ font-weight: 600;
801
  }
802
 
803
+ /* Responsive Design */
804
+ @media (max-width: 768px) {
805
+ .sidebar {
806
+ width: 100%;
807
+ left: -100%;
808
+ }
809
+
810
+ .floating-user-widget {
811
+ width: calc(100% - 40px);
812
+ right: 20px;
813
+ left: 20px;
814
+ }
815
+
816
+ .nfts-grid {
817
+ grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
818
+ gap: 10px;
819
+ }
820
+
821
+ .stats-grid {
822
+ grid-template-columns: 1fr;
823
+ }
824
+
825
+ .page-title {
826
+ font-size: 1.5rem;
827
+ }
828
  }
829
 
830
+ /* Added theme variables and floating widget styles */
831
+ :root {
832
+ --theme-primary: #00bcd4;
833
+ --theme-secondary: #87ceeb;
834
+ --theme-bg-primary: #0a0a0a;
835
+ --theme-bg-secondary: #1a1a2e;
836
+ --theme-bg-tertiary: #16213e;
837
+ --theme-text-primary: #e0e6ed;
838
+ --theme-text-secondary: #87ceeb;
839
  }
840
 
841
+ /* Red Theme */
842
+ .theme-red {
843
+ --theme-primary: #ff4444;
844
+ --theme-secondary: #ff6b6b;
845
+ --theme-bg-primary: #1a0a0a;
846
+ --theme-bg-secondary: #2e1a1a;
847
+ --theme-bg-tertiary: #3e1616;
 
 
 
 
848
  }
849
 
850
+ /* Black Theme */
851
+ .theme-black {
852
+ --theme-primary: #ffffff;
853
+ --theme-secondary: #cccccc;
854
+ --theme-bg-primary: #000000;
855
+ --theme-bg-secondary: #1a1a1a;
856
+ --theme-bg-tertiary: #2a2a2a;
 
857
  }
858
 
859
+ /* Yellow Theme */
860
+ .theme-yellow {
861
+ --theme-primary: #ffd700;
862
+ --theme-secondary: #ffeb3b;
863
+ --theme-bg-primary: #1a1a0a;
864
+ --theme-bg-secondary: #2e2e1a;
865
+ --theme-bg-tertiary: #3e3e16;
866
+ --theme-text-primary: #f0f0f0;
867
+ }
868
+
869
+ /* Update existing styles to use CSS variables */
870
+ html, body {
871
+ background: linear-gradient(135deg, var(--theme-bg-primary) 0%, var(--theme-bg-secondary) 50%, var(--theme-bg-tertiary) 100%);
872
  color: var(--theme-text-primary);
 
 
 
 
 
 
873
  }
874
 
875
+ .header {
876
+ background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
877
+ border-bottom: 2px solid var(--theme-primary);
878
+ box-shadow: 0 4px 20px rgba(0, 188, 212, 0.3);
 
 
 
 
 
 
879
  }
880
 
881
+ /* Added floating user widget styles */
882
  .floating-user-widget {
883
  position: fixed;
884
  bottom: 20px;
885
  right: 20px;
886
+ width: 300px;
887
  background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%);
888
+ border: 2px solid var(--theme-primary);
889
  border-radius: 12px;
890
  padding: 15px;
891
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4);
 
895
  }
896
 
897
  .floating-user-widget.collapsed {
898
+ height: 60px;
 
 
899
  overflow: hidden;
900
  }
901
 
 
907
  cursor: pointer;
908
  }
909
 
 
 
 
 
910
  .widget-title {
911
  font-weight: bold;
912
  color: var(--theme-primary);
 
932
 
933
  .floating-user-widget.collapsed .widget-content {
934
  opacity: 0;
 
 
935
  }
936
 
937
  .widget-user-info {
 
945
  width: 40px;
946
  height: 40px;
947
  border-radius: 50%;
948
+ border: 2px solid var(--theme-primary);
949
  }
950
 
951
  .widget-user-details h4 {
 
962
 
963
  .widget-rank {
964
  background: rgba(0, 188, 212, 0.1);
965
+ border: 1px solid var(--theme-primary);
966
  border-radius: 6px;
967
  padding: 8px;
968
  text-align: center;
 
981
  color: var(--theme-primary);
982
  }
983
 
984
+ /* Added theme selector styles to sidebar */
985
+ .theme-selector {
986
+ background: linear-gradient(135deg, var(--theme-bg-tertiary) 0%, var(--theme-bg-secondary) 100%);
987
+ border: 1px solid var(--theme-primary);
988
+ border-radius: 10px;
989
+ padding: 15px;
990
+ margin-bottom: 15px;
991
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
 
 
 
 
 
 
 
 
 
 
 
 
992
  }
993
 
994
+ .theme-selector h3 {
995
+ font-size: 1rem;
996
  color: var(--theme-primary);
997
+ margin-bottom: 12px;
998
  display: flex;
999
  align-items: center;
1000
+ gap: 6px;
 
1001
  }
1002
 
1003
+ .theme-buttons {
1004
  display: grid;
1005
+ grid-template-columns: 1fr 1fr;
1006
+ gap: 8px;
 
 
 
 
 
 
 
 
 
 
 
 
 
1007
  }
1008
 
1009
+ .theme-btn {
1010
+ padding: 8px 12px;
1011
+ border: 2px solid transparent;
1012
+ border-radius: 6px;
1013
+ cursor: pointer;
1014
  font-weight: bold;
 
 
 
 
 
1015
  font-size: 0.8rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1016
  transition: all 0.3s ease;
1017
+ text-align: center;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1018
  }
1019
 
1020
+ .theme-btn.current {
1021
+ border-color: var(--theme-primary);
1022
+ box-shadow: 0 0 10px rgba(0, 188, 212, 0.4);
1023
  }
1024
 
1025
+ .theme-btn:hover {
1026
+ transform: translateY(-1px);
 
 
 
 
 
 
 
 
 
1027
  }
1028
 
1029
+ .theme-btn.default {
1030
+ background: linear-gradient(45deg, #00bcd4, #87ceeb);
1031
+ color: #0a0a0a;
1032
  }
1033
 
1034
+ .theme-btn.red {
1035
+ background: linear-gradient(45deg, #ff4444, #ff6b6b);
1036
+ color: white;
 
 
 
1037
  }
1038
 
1039
+ .theme-btn.black {
1040
+ background: linear-gradient(45deg, #333, #666);
1041
+ color: white;
 
 
 
 
 
1042
  }
1043
 
1044
+ .theme-btn.yellow {
1045
+ background: linear-gradient(45deg, #ffd700, #ffeb3b);
1046
+ color: #000;
 
 
 
 
 
1047
  }
1048
 
1049
+ /* Enhanced loading animations */
1050
+ .loading-enhanced {
 
 
1051
  display: flex;
1052
+ flex-direction: column;
1053
  align-items: center;
1054
+ justify-content: center;
1055
+ gap: 15px;
1056
+ padding: 40px 20px;
1057
+ color: var(--theme-text-secondary);
1058
  }
1059
 
1060
+ .loading-pulse {
1061
+ width: 60px;
1062
+ height: 60px;
1063
+ border: 3px solid var(--theme-primary);
1064
+ border-radius: 50%;
1065
+ position: relative;
1066
+ animation: pulse 2s infinite;
1067
  }
1068
 
1069
+ .loading-pulse::before {
1070
+ content: '';
1071
+ position: absolute;
1072
+ top: 50%;
1073
+ left: 50%;
1074
+ transform: translate(-50%, -50%);
1075
+ width: 30px;
1076
+ height: 30px;
1077
+ background: var(--theme-primary);
1078
+ border-radius: 50%;
1079
+ animation: innerPulse 2s infinite;
1080
  }
1081
 
1082
+ @keyframes pulse {
1083
+ 0%, 100% { transform: scale(1); opacity: 1; }
1084
+ 50% { transform: scale(1.1); opacity: 0.7; }
1085
  }
1086
 
1087
+ @keyframes innerPulse {
1088
+ 0%, 100% { transform: translate(-50%, -50%) scale(1); }
1089
+ 50% { transform: translate(-50%, -50%) scale(0.8); }
 
 
 
 
1090
  }
1091
+
1092
+ .loading-text {
1093
+ font-size: 1.1rem;
1094
  font-weight: bold;
1095
+ text-align: center;
1096
  }
1097
 
1098
+ .loading-subtext {
1099
+ font-size: 0.9rem;
1100
+ opacity: 0.8;
1101
+ text-align: center;
 
1102
  }
1103
 
1104
+ /* Enhanced NFT card styles */
1105
+ .nft-card {
 
 
 
 
1106
  position: relative;
1107
  overflow: hidden;
1108
  }
1109
 
1110
+ .nft-card::before {
 
 
 
 
 
 
1111
  content: '';
1112
  position: absolute;
1113
+ top: -2px;
1114
+ left: -2px;
1115
+ right: -2px;
1116
+ bottom: -2px;
1117
+ background: linear-gradient(45deg, transparent, var(--theme-primary), transparent);
1118
+ border-radius: 12px;
1119
+ z-index: -1;
1120
+ opacity: 0;
1121
+ transition: opacity 0.3s ease;
1122
  }
1123
 
1124
+ .nft-card:hover::before {
1125
+ opacity: 0.3;
1126
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1127
 
1128
+ .nft-card.legendary::before {
1129
+ background: linear-gradient(45deg, #ffd700, #ffeb3b, #ff6f00, #ffd700);
1130
+ background-size: 400% 400%;
1131
+ animation: legendaryGlow 2s ease-in-out infinite;
1132
+ opacity: 0.6;
1133
+ }
1134
 
1135
+ /* Mobile responsive updates for floating widget */
1136
+ @media (max-width: 768px) {
1137
  .floating-user-widget {
1138
  width: calc(100vw - 40px);
1139
  right: 20px;
1140
  left: 20px;
1141
  bottom: 10px;
1142
  }
 
 
 
 
 
 
 
 
 
 
 
 
1143
  }
1144
  </style>
1145
  </head>
1146
  <body>
1147
+ <!-- Added site loading animation -->
1148
+ <div class="site-loading" id="siteLoading">
1149
+ <div class="site-loading-spinner"></div>
1150
+ <div class="site-loading-text">Loading Finral...</div>
 
 
 
1151
  </div>
1152
 
1153
+ <!-- Restructured header -->
1154
  <div class="header">
1155
+ <div class="header-content">
1156
  <div class="page-title">Finral Search</div>
1157
  <div class="creator">✨ Crafted with Excellence by Saul ✨</div>
1158
+ <div class="page-subtitle">"Find Any Telegram User"</div>
 
 
 
 
 
 
 
 
1159
  </div>
1160
  </div>
1161
 
 
1163
 
1164
  <div class="main-layout">
1165
  <div class="sidebar" id="sidebar">
1166
+ <!-- Added green theme to selector -->
1167
  <div class="theme-selector">
1168
  <h3>🎨 Theme</h3>
1169
  <div class="theme-buttons">
 
1201
 
1202
  <div class="user-info-card">
1203
  <div class="welcome-title" id="welcomeTitle">Welcome to Finral</div>
1204
+ <div id="userName" class="chat-id" style="display:none; margin-bottom: 8px;"></div>
1205
  <div id="chatId" class="chat-id">
1206
  <div class="loading">
1207
  <div class="loading-spinner"></div>
1208
  Loading...
1209
  </div>
1210
  </div>
1211
+ <!-- Added rank display in user info -->
1212
+ <div id="userRank" class="user-rank" style="display:none;">
1213
+ 🥉 Loading Rank...
 
1214
  </div>
1215
  </div>
1216
  </div>
 
1261
  </div>
1262
  </div>
1263
 
1264
+ <!-- Added loading animations for groups -->
1265
+ <div class="stats-section" id="groupsSection" style="display:none;">
1266
+ <h3>👥 Groups</h3>
1267
+ <div class="groups-loading" id="groupsLoading">
1268
+ <div class="groups-loading-spinner"></div>
1269
+ <div class="groups-loading-text">Loading groups...</div>
1270
+ </div>
1271
+ <div id="groupsContainer"></div>
1272
+ </div>
1273
+
1274
+ <!-- Improved NFT section with loading -->
1275
  <div class="nfts-section" id="nftsSection" style="display:none;">
1276
  <h3>🎨 NFT Collection</h3>
1277
+ <div class="nft-loading" id="nftLoading">
1278
+ <div class="nft-loading-spinner"></div>
1279
+ <div class="nft-loading-text">Loading NFTs...</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1280
  </div>
1281
+ <div id="nftStats" class="stats-section" style="display:none;">
1282
+ <div>
1283
+ <div class="nft-stat">
1284
+ <span class="nft-stat-value" id="totalNfts">0</span>
1285
+ <span class="nft-stat-label">Total NFTs</span>
1286
+ </div>
1287
+ <div class="nft-stat">
1288
+ <span class="nft-stat-value" id="avgQuality">0</span>
1289
+ <span class="nft-stat-label">Avg Quality</span>
1290
+ </div>
1291
+ </div>
1292
+ <div>
1293
+ <div class="nft-stat">
1294
+ <span class="nft-stat-value" id="rarestHolders">0</span>
1295
+ <span class="nft-stat-label">Rarest (Holders)</span>
1296
+ </div>
1297
+ <div class="nft-stat">
1298
+ <span class="nft-stat-value" id="highestQuality">0</span>
1299
+ <span class="nft-stat-label">Highest Quality</span>
1300
+ </div>
1301
  </div>
1302
  </div>
1303
+ <div id="nftsContainer" class="nfts-grid"></div>
1304
  <button id="showAllNftsBtn" class="show-all-btn" style="display:none;">
1305
  Show All NFTs (<span id="remainingCount">0</span> more)
1306
  </button>
1307
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
1308
  </div>
1309
  </div>
1310
 
1311
+ <!-- Smaller collapsed floating widget -->
1312
  <div class="floating-user-widget" id="floatingWidget" style="display:none;">
1313
  <div class="widget-header" onclick="toggleWidget()">
1314
  <div class="widget-title">User Info</div>
 
1331
 
1332
  <script src="utils/xp-calculations.js"></script>
1333
  <script>
1334
+ async function fetchUserTheme(chatId) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1335
  try {
1336
+ const response = await fetch(`https://reaperxxxx-testldb.hf.space/user/${chatId}/theme`);
1337
  const data = await response.json();
1338
 
1339
  if (data.status && data.theme) {
1340
+ return data.theme;
1341
+ } else {
1342
+ return 'default';
1343
  }
1344
  } catch (error) {
1345
+ console.log('Theme fetch error, using default:', error);
1346
+ return 'default';
1347
  }
1348
  }
1349
 
1350
  function changeTheme(theme) {
1351
+ const body = document.body;
1352
+ body.className = body.className.replace(/theme-\w+/g, '');
1353
 
 
1354
  if (theme !== 'default') {
1355
+ body.classList.add(`theme-${theme}`);
1356
  }
1357
 
1358
+ // Update active theme button
 
 
1359
  document.querySelectorAll('.theme-btn').forEach(btn => {
1360
  btn.classList.remove('current');
1361
  });
1362
+ const themeBtn = document.querySelector(`.theme-btn.${theme}`);
1363
+ if (themeBtn) {
1364
+ themeBtn.classList.add('current');
1365
+ }
1366
 
1367
  // Save theme preference
1368
+ localStorage.setItem('selectedTheme', theme);
 
 
 
 
 
1369
  }
1370
 
1371
+ const sidebarToggle = document.getElementById('sidebarToggle');
1372
+ const sidebar = document.getElementById('sidebar');
1373
+
1374
+ sidebarToggle.addEventListener('click', () => {
1375
+ sidebar.classList.toggle('open');
1376
+ sidebarToggle.textContent = sidebar.classList.contains('open') ? '✕' : '🔍';
1377
+ });
1378
+
1379
+ document.addEventListener('click', (e) => {
1380
+ if (window.innerWidth <= 768 &&
1381
+ !sidebar.contains(e.target) &&
1382
+ !sidebarToggle.contains(e.target) &&
1383
+ sidebar.classList.contains('open')) {
1384
+ sidebar.classList.remove('open');
1385
+ sidebarToggle.textContent = '🔍';
1386
  }
1387
+ });
1388
 
1389
+ async function searchUser(chatId) {
1390
+ const searchBtn = document.getElementById('searchBtn');
1391
+ const searchResult = document.getElementById('searchResult');
1392
+ const btnText = searchBtn.querySelector('.btn-text');
1393
+ const loadingDots = searchBtn.querySelector('.loading-dots');
1394
 
1395
+ searchBtn.disabled = true;
1396
+ btnText.style.display = 'none';
1397
+ loadingDots.style.display = 'flex';
1398
+ searchResult.style.display = 'none';
1399
 
1400
+ try {
1401
+ const response = await fetch(`https://reaperxxxx-testldb.hf.space/user/${chatId}/info`);
1402
+ const data = await response.json();
1403
+
1404
+ if (data.status && data.groups && data.groups.length > 0) {
1405
+ const userInfo = data.groups[0];
1406
+ searchResult.innerHTML = `
1407
+ <p><strong>✅ Found User:</strong></p>
1408
+ <p><strong>Name:</strong> ${userInfo.fullName || 'N/A'}</p>
1409
+ <p><strong>Username:</strong> ${userInfo.username || 'N/A'}</p>
1410
+ <p><strong>ID:</strong> ${chatId}</p>
1411
+ <button class="view-profile-btn" onclick="window.open('https://t.me/finralxbot/info?startapp=${chatId}', '_blank')">
1412
+ View Full Profile
1413
+ </button>
1414
+ `;
1415
+ searchResult.style.display = 'block';
1416
+ } else {
1417
+ searchResult.innerHTML = '<p class="error">❌ User not found or no data available.</p>';
1418
+ searchResult.style.display = 'block';
1419
+ }
1420
+ } catch (error) {
1421
+ searchResult.innerHTML = '<p class="error">⚠️ Error searching for user. Please try again.</p>';
1422
+ searchResult.style.display = 'block';
1423
  }
1424
 
1425
+ searchBtn.disabled = false;
1426
+ btnText.style.display = 'block';
1427
+ loadingDots.style.display = 'none';
1428
+ }
1429
+
1430
+ function toggleWidget() {
1431
+ const widget = document.getElementById('floatingWidget');
1432
+ const btn = document.getElementById('collapseBtn');
1433
 
1434
+ widget.classList.toggle('collapsed');
1435
+ btn.classList.toggle('collapsed');
1436
+ btn.textContent = widget.classList.contains('collapsed') ? '' : '▼';
1437
  }
1438
 
1439
+ function updateGlobalRank(totalLevel) {
1440
+ const rank = getGlobalRank(totalLevel);
 
1441
  const widgetRank = document.getElementById('widgetRank');
1442
+ const userRank = document.getElementById('userRank');
1443
+
1444
+ if (widgetRank) {
1445
+ widgetRank.textContent = `${rank.emoji} ${rank.rank}`;
1446
+ }
1447
+ if (userRank) {
1448
+ userRank.textContent = `${rank.emoji} ${rank.rank}`;
1449
+ userRank.style.display = 'block';
1450
+ }
1451
+ }
1452
+
1453
+ window.addEventListener('DOMContentLoaded', async () => {
1454
+ // Show site loading
1455
+ const siteLoading = document.getElementById('siteLoading');
1456
+
1457
+ // Get user ID from Telegram WebApp
1458
+ const userId = window.Telegram?.WebApp?.initDataUnsafe?.user?.id || '7365381557';
1459
 
1460
+ try {
1461
+ // Fetch and apply user theme
1462
+ const userTheme = await fetchUserTheme(userId);
1463
+ changeTheme(userTheme);
1464
+
1465
+ // Hide site loading after theme is applied
1466
+ setTimeout(() => {
1467
+ siteLoading.style.display = 'none';
1468
+ }, 1000);
1469
+
1470
+ } catch (error) {
1471
+ // Fallback to saved theme or default
1472
+ const savedTheme = localStorage.getItem('selectedTheme') || 'default';
1473
+ changeTheme(savedTheme);
1474
+ siteLoading.style.display = 'none';
1475
+ }
1476
+
1477
+ // Set up search functionality
1478
+ const searchBtn = document.getElementById('searchBtn');
1479
+ const searchInput = document.getElementById('searchInput');
1480
 
1481
+ searchBtn.addEventListener('click', () => {
1482
+ const chatId = searchInput.value.trim();
1483
+ if (chatId) {
1484
+ searchUser(chatId);
1485
+ }
1486
+ });
1487
+
1488
+ searchInput.addEventListener('keypress', (e) => {
1489
+ if (e.key === 'Enter') {
1490
+ const chatId = searchInput.value.trim();
1491
+ if (chatId) {
1492
+ searchUser(chatId);
1493
+ }
1494
+ }
1495
+ });
1496
+
1497
+ // Load user data with enhanced loading states
1498
+ await loadUserData(userId);
1499
+ });
1500
+
1501
+ async function loadUserData(userId) {
1502
+ document.getElementById('chatId').innerHTML = `
1503
+ <div class="loading">
1504
+ <div class="loading-spinner"></div>
1505
+ Loading user data...
1506
+ </div>
1507
+ `;
1508
+
1509
+ try {
1510
+ // Fetch user banner with fallback
1511
+ try {
1512
+ const bannerRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/banner`);
1513
+ const bannerData = await bannerRes.json();
1514
+
1515
+ const bannerEl = document.getElementById('banner');
1516
+ if (bannerData.status && bannerData.catboxUrl) {
1517
+ bannerEl.src = bannerData.catboxUrl;
1518
+ } else {
1519
+ bannerEl.src = 'https://files.catbox.moe/pdt55w.jpg';
1520
+ }
1521
+ document.getElementById('bannerContainer').style.display = 'block';
1522
+ } catch (err) {
1523
+ const bannerEl = document.getElementById('banner');
1524
+ bannerEl.src = 'https://files.catbox.moe/pdt55w.jpg';
1525
+ document.getElementById('bannerContainer').style.display = 'block';
1526
+ }
1527
+
1528
+ // Fetch user PFP
1529
+ const pfpRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/pfp`);
1530
+ const pfpData = await pfpRes.json();
1531
+ const imgEl = document.getElementById('pfp');
1532
+
1533
+ if (pfpData.status && pfpData.catboxUrl) {
1534
+ imgEl.src = pfpData.catboxUrl;
1535
+ } else {
1536
+ imgEl.src = 'https://files.catbox.moe/hmicys.jpeg';
1537
+ }
1538
+
1539
+ document.getElementById('groupsSection').style.display = 'block';
1540
+ document.getElementById('groupsLoading').style.display = 'flex';
1541
+
1542
+ document.getElementById('nftsSection').style.display = 'block';
1543
+ document.getElementById('nftLoading').style.display = 'flex';
1544
+
1545
+ // Fetch user info
1546
+ const infoRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/info`);
1547
+ const infoData = await infoRes.json();
1548
+
1549
+ if (infoData.status) {
1550
+ const userInfo = infoData.groups[0] || {};
1551
+
1552
+ const fullName = userInfo.fullName || 'N/A';
1553
+ const username = userInfo.username || 'N/A';
1554
+
1555
+ // Update UI elements
1556
+ document.getElementById('chatId').textContent = `Chat ID: ${userId}`;
1557
+
1558
+ if (fullName !== 'N/A') {
1559
+ document.getElementById('userName').textContent = fullName;
1560
+ document.getElementById('userName').style.display = 'block';
1561
+ }
1562
+
1563
+ // Update floating widget
1564
+ document.getElementById('widgetName').textContent = fullName;
1565
+ document.getElementById('widgetId').textContent = `ID: ${userId}`;
1566
+ document.getElementById('widgetAvatar').src = document.getElementById('pfp').src;
1567
+ updateGlobalRank(infoData.totalLevel);
1568
+ document.getElementById('floatingWidget').style.display = 'block';
1569
+
1570
+ // Display stats
1571
+ document.getElementById('fullName').textContent = fullName;
1572
+ document.getElementById('username').textContent = username;
1573
+ document.getElementById('totalXP').textContent = infoData.totalXP.toLocaleString();
1574
+ document.getElementById('totalLevel').textContent = infoData.totalLevel;
1575
+ document.getElementById('totalRoyalties').textContent = infoData.totalRoyalties.toLocaleString();
1576
+ document.getElementById('totalDailyMessages').textContent = infoData.totalDailyMessages;
1577
+ document.getElementById('groupCount').textContent = infoData.groups.length;
1578
+
1579
+ document.getElementById('statsGrid').style.display = 'grid';
1580
+
1581
+ setTimeout(() => {
1582
+ document.getElementById('groupsLoading').style.display = 'none';
1583
+ loadGroups(infoData.groups);
1584
+ }, 800);
1585
+
1586
+ setTimeout(async () => {
1587
+ await loadNFTs(userId);
1588
+ document.getElementById('nftLoading').style.display = 'none';
1589
+ }, 1200);
1590
+ }
1591
+ } catch (error) {
1592
+ console.error('Error loading user data:', error);
1593
+ document.getElementById('chatId').textContent = 'Error loading user data';
1594
+ document.getElementById('groupsLoading').style.display = 'none';
1595
+ document.getElementById('nftLoading').style.display = 'none';
1596
  }
1597
  }
1598
 
1599
+ async function loadGroups(groups) {
1600
+ // Process and display groups (existing logic)
1601
+ const groupsContainer = document.getElementById('groupsContainer');
1602
+ groupsContainer.innerHTML = '';
1603
+
1604
+ for (const group of groups) {
1605
+ const div = document.createElement('div');
1606
+ div.className = 'group-box';
1607
+ div.innerHTML = `
1608
+ <div class="group-header">
1609
+ <img class="group-pic" src="${group.groupPic || '/placeholder.svg'}" alt="Group Picture">
1610
+ <div class="group-info">
1611
+ <div class="group-name">${group.fullName || 'Unknown Group'}</div>
1612
+ <div class="group-id">ID: ${group.groupId || group.id}</div>
1613
+ </div>
1614
+ </div>
1615
+ <div class="group-stats">
1616
+ <div class="group-stat-item">
1617
+ <span class="group-stat-value">${group.level}</span>
1618
+ <span class="group-stat-label">Level</span>
1619
+ </div>
1620
+ <div class="group-stat-item">
1621
+ <span class="group-stat-value">${group.xp}</span>
1622
+ <span class="group-stat-label">XP</span>
1623
+ </div>
1624
+ <div class="group-stat-item">
1625
+ <span class="group-stat-value">${group.royalties}</span>
1626
+ <span class="group-stat-label">Royalties</span>
1627
+ </div>
1628
+ <div class="group-stat-item">
1629
+ <span class="group-stat-value">${group.dailyMessages}</span>
1630
+ <span class="group-stat-label">Daily</span>
1631
+ </div>
1632
+ </div>
1633
+ `;
1634
+ groupsContainer.appendChild(div);
1635
+ }
1636
+ }
1637
+
1638
+ async function loadNFTs(userId) {
1639
+ try {
1640
+ const nftsRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/nfts`);
1641
+ const nftsData = await nftsRes.json();
1642
+
1643
+ const nftsContainer = document.getElementById('nftsContainer');
1644
+
1645
+ if (nftsData.status && nftsData.nfts && nftsData.nfts.length > 0) {
1646
+ const sortedNfts = nftsData.nfts.sort((a, b) => a.holders - b.holders);
1647
+
1648
+ // Display NFTs with smaller cards
1649
+ nftsContainer.innerHTML = '';
1650
+ sortedNfts.slice(0, 12).forEach(nft => {
1651
+ const nftCard = createNftCard(nft);
1652
+ nftsContainer.appendChild(nftCard);
1653
+ });
1654
+
1655
+ // Show remaining count if more than 12
1656
+ if (sortedNfts.length > 12) {
1657
+ document.getElementById('remainingCount').textContent = sortedNfts.length - 12;
1658
+ document.getElementById('showAllNftsBtn').style.display = 'block';
1659
+ }
1660
+ } else {
1661
+ nftsContainer.innerHTML = '<p>No NFTs found</p>';
1662
+ }
1663
+ } catch (error) {
1664
+ console.error('Error loading NFTs:', error);
1665
+ document.getElementById('nftsContainer').innerHTML = '<p>Error loading NFTs</p>';
1666
+ }
1667
+ }
1668
+
1669
+ function createNftCard(nft) {
1670
+ const qualityClass = getQualityClass(nft.nftquality);
1671
+ const qualityBadgeClass = getQualityBadgeClass(nft.nftquality);
1672
 
1673
+ const card = document.createElement('div');
1674
+ card.className = `nft-card ${qualityClass}`;
1675
+
1676
+ card.innerHTML = `
1677
+ <img src="${nft.imageUrl || '/placeholder.svg?height=100&width=180'}"
1678
+ alt="${nft.name}" class="nft-image" loading="lazy">
1679
+ <div class="nft-info">
1680
+ <div class="nft-name">${nft.name}</div>
1681
+ <div class="nft-details">
1682
+ <span class="quality-badge ${qualityBadgeClass}">${nft.nftquality}%</span>
1683
+ <span>${nft.holders} holders</span>
1684
+ </div>
1685
+ </div>
1686
+ `;
1687
+
1688
+ return card;
1689
+ }
1690
+
1691
+ // Helper functions
1692
+ function getQualityClass(quality) {
1693
+ if (quality >= 81) return 'legendary';
1694
+ if (quality >= 61) return 'way-better';
1695
+ if (quality >= 41) return 'even-better';
1696
+ if (quality >= 21) return 'better';
1697
+ return 'basic';
1698
+ }
1699
+
1700
+ function getQualityBadgeClass(quality) {
1701
+ if (quality >= 81) return 'quality-legendary';
1702
+ if (quality >= 61) return 'quality-way-better';
1703
+ if (quality >= 41) return 'quality-even-better';
1704
+ if (quality >= 21) return 'quality-better';
1705
+ return 'quality-basic';
1706
  }
1707
 
1708
  // Sidebar toggle functionality
 
1711
 
1712
  sidebarToggle.addEventListener('click', () => {
1713
  sidebar.classList.toggle('open');
1714
+ sidebarToggle.textContent = sidebar.classList.contains('open') ? '✕' : '🔍';
1715
  });
1716
 
1717
+ // Close sidebar when clicking outside on mobile
1718
+ document.addEventListener('click', (e) => {
1719
+ if (window.innerWidth <= 768 &&
1720
+ !sidebar.contains(e.target) &&
1721
+ !sidebarToggle.contains(e.target) &&
1722
+ sidebar.classList.contains('open')) {
1723
+ sidebar.classList.remove('open');
1724
+ sidebarToggle.textContent = '🔍';
1725
+ }
1726
+ });
1727
 
1728
+ // Function to search user by chat ID
1729
+ async function searchUser(chatId) {
1730
+ const searchBtn = document.getElementById('searchBtn');
1731
+ const searchResult = document.getElementById('searchResult');
1732
+ const btnText = searchBtn.querySelector('.btn-text');
1733
+ const loadingDots = searchBtn.querySelector('.loading-dots');
1734
+
1735
  searchBtn.disabled = true;
1736
+ btnText.style.display = 'none';
1737
+ loadingDots.style.display = 'flex';
1738
+ searchResult.style.display = 'none';
1739
+
 
 
 
1740
  try {
1741
+ const response = await fetch(`https://reaperxxxx-testldb.hf.space/user/${chatId}/info`);
1742
+ const data = await response.json();
1743
 
1744
+ if (data.status && data.groups && data.groups.length > 0) {
1745
+ const userInfo = data.groups[0];
1746
+ searchResult.innerHTML = `
1747
+ <p><strong>✅ Found User:</strong></p>
1748
+ <p><strong>Name:</strong> ${userInfo.fullName || 'N/A'}</p>
1749
+ <p><strong>Username:</strong> ${userInfo.username || 'N/A'}</p>
1750
+ <p><strong>ID:</strong> ${chatId}</p>
1751
+ <button class="view-profile-btn" onclick="window.open('https://t.me/finralxbot/info?startapp=${chatId}', '_blank')">
1752
+ View Full Profile
1753
+ </button>
1754
+ `;
1755
+ searchResult.style.display = 'block';
1756
+ } else {
1757
+ searchResult.innerHTML = '<p class="error">❌ User not found or no data available.</p>';
1758
+ searchResult.style.display = 'block';
1759
+ }
1760
  } catch (error) {
1761
+ searchResult.innerHTML = '<p class="error">⚠️ Error searching for user. Please try again.</p>';
1762
  searchResult.style.display = 'block';
 
 
 
1763
  }
 
 
 
 
 
1764
 
1765
+ searchBtn.disabled = false;
1766
+ btnText.style.display = 'block';
1767
+ loadingDots.style.display = 'none';
 
1768
  }
1769
 
1770
+ function changeTheme(theme) {
1771
+ const body = document.body;
1772
+ body.className = body.className.replace(/theme-\w+/g, '');
1773
+
1774
+ if (theme !== 'default') {
1775
+ body.classList.add(`theme-${theme}`);
1776
+ }
1777
+
1778
+ // Update active theme button
1779
+ document.querySelectorAll('.theme-btn').forEach(btn => {
1780
+ btn.classList.remove('current');
1781
+ });
1782
+ document.querySelector(`.theme-btn.${theme}`).classList.add('current');
1783
+
1784
+ // Save theme preference
1785
+ localStorage.setItem('selectedTheme', theme);
1786
  }
1787
 
1788
+ function toggleWidget() {
1789
+ const widget = document.getElementById('floatingWidget');
1790
+ const btn = document.getElementById('collapseBtn');
1791
 
1792
+ widget.classList.toggle('collapsed');
1793
+ btn.classList.toggle('collapsed');
1794
+ btn.textContent = widget.classList.contains('collapsed') ? '▲' : '▼';
1795
+ }
1796
+
1797
+ function updateGlobalRank(totalLevel) {
1798
+ const rank = getGlobalRank(totalLevel);
1799
+ const widgetRank = document.getElementById('widgetRank');
1800
+ if (widgetRank) {
1801
+ widgetRank.textContent = `${rank.emoji} ${rank.rank}`;
1802
+ }
 
 
 
 
 
 
 
 
1803
  }
1804
 
1805
+ window.addEventListener('DOMContentLoaded', async () => {
1806
+ const savedTheme = localStorage.getItem('selectedTheme') || 'default';
 
1807
  changeTheme(savedTheme);
1808
+
1809
+ // Set up search functionality
1810
+ const searchBtn = document.getElementById('searchBtn');
1811
+ const searchInput = document.getElementById('searchInput');
1812
+
1813
+ searchBtn.addEventListener('click', () => {
1814
+ const chatId = searchInput.value.trim();
1815
+ if (chatId) {
1816
+ searchUser(chatId);
1817
+ }
1818
+ });
1819
+
1820
+ searchInput.addEventListener('keypress', (e) => {
1821
+ if (e.key === 'Enter') {
1822
+ const chatId = searchInput.value.trim();
1823
+ if (chatId) {
1824
+ searchUser(chatId);
1825
+ }
1826
+ }
1827
+ });
1828
+
1829
+ // Get userId from Telegram WebApp start parameter or current user
1830
+ let userId;
1831
+ let isViewingOther = false;
1832
+
1833
+ const initData = Telegram.WebApp.initDataUnsafe;
1834
+ const startParam = initData.start_param;
1835
+
1836
+ if (startParam) {
1837
+ userId = startParam;
1838
+ isViewingOther = true;
1839
+ document.getElementById('welcomeTitle').textContent = `Viewing Profile`;
1840
+ } else {
1841
+ const user = initData.user;
1842
+ if (user && user.id) {
1843
+ userId = user.id;
1844
+ document.getElementById('welcomeTitle').textContent = `Welcome to Finral`;
1845
+ } else {
1846
+ document.getElementById('chatId').innerHTML = '<div class="error">❌ Unable to fetch chat ID</div>';
1847
+ return;
1848
+ }
1849
+ }
1850
+
1851
+ document.getElementById('chatId').textContent = userId;
1852
+
1853
+ try {
1854
+ // Fetch user banner with fallback
1855
+ try {
1856
+ const bannerRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/banner`);
1857
+ const bannerData = await bannerRes.json();
1858
+
1859
+ const bannerEl = document.getElementById('banner');
1860
+ if (bannerData.status && bannerData.catboxUrl) {
1861
+ bannerEl.src = bannerData.catboxUrl;
1862
+ } else {
1863
+ bannerEl.src = 'https://files.catbox.moe/pdt55w.jpg';
1864
+ }
1865
+ document.getElementById('bannerContainer').style.display = 'block';
1866
+ } catch (err) {
1867
+ const bannerEl = document.getElementById('banner');
1868
+ bannerEl.src = 'https://files.catbox.moe/pdt55w.jpg';
1869
+ document.getElementById('bannerContainer').style.display = 'block';
1870
+ }
1871
+
1872
+ // Fetch user PFP
1873
+ const pfpRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/pfp`);
1874
+ const pfpData = await pfpRes.json();
1875
+ const imgEl = document.getElementById('pfp');
1876
+
1877
+ if (pfpData.status && pfpData.catboxUrl) {
1878
+ imgEl.src = pfpData.catboxUrl;
1879
+ } else {
1880
+ imgEl.src = 'https://files.catbox.moe/hmicys.jpeg';
1881
+ }
1882
+
1883
+ // Fetch user info
1884
+ const infoRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/info`);
1885
+ const infoData = await infoRes.json();
1886
+
1887
+ if (infoData.status) {
1888
+ const userInfo = infoData.groups[0] || {};
1889
+
1890
+ const fullName = userInfo.fullName || 'N/A';
1891
+ const username = userInfo.username || 'N/A';
1892
+
1893
+ if (fullName !== 'N/A') {
1894
+ document.getElementById('userName').textContent = fullName;
1895
+ document.getElementById('userName').style.display = 'block';
1896
+ }
1897
+
1898
+ // Update floating widget
1899
+ document.getElementById('widgetName').textContent = fullName;
1900
+ document.getElementById('widgetId').textContent = `ID: ${userId}`;
1901
+ document.getElementById('widgetAvatar').src = document.getElementById('pfp').src;
1902
+ updateGlobalRank(infoData.totalLevel);
1903
+ document.getElementById('floatingWidget').style.display = 'block';
1904
+
1905
+ // Display basic stats
1906
+ document.getElementById('fullName').textContent = fullName;
1907
+ document.getElementById('username').textContent = username;
1908
+ document.getElementById('totalXP').textContent = infoData.totalXP.toLocaleString();
1909
+ document.getElementById('totalLevel').textContent = infoData.totalLevel;
1910
+ document.getElementById('totalRoyalties').textContent = infoData.totalRoyalties.toLocaleString();
1911
+ document.getElementById('totalDailyMessages').textContent = infoData.totalDailyMessages;
1912
+ document.getElementById('groupCount').textContent = infoData.groups.length;
1913
+
1914
+ // Show stats grid
1915
+ document.getElementById('statsGrid').style.display = 'grid';
1916
+
1917
+ // Group unique groups by groupId
1918
+ const uniqueGroups = {};
1919
+
1920
+ for (const group of infoData.groups) {
1921
+ const groupId = group.groupId || group.id;
1922
+
1923
+ if (!uniqueGroups[groupId]) {
1924
+ uniqueGroups[groupId] = {
1925
+ groupId: groupId,
1926
+ fullName: group.fullName,
1927
+ username: group.username,
1928
+ totalLevel: 0,
1929
+ totalXP: 0,
1930
+ totalRoyalties: 0,
1931
+ totalDailyMessages: 0,
1932
+ entries: []
1933
+ };
1934
+ }
1935
+
1936
+ uniqueGroups[groupId].totalLevel += group.level || 0;
1937
+ uniqueGroups[groupId].totalXP += group.xp || 0;
1938
+ uniqueGroups[groupId].totalRoyalties += group.royalties || 0;
1939
+ uniqueGroups[groupId].totalDailyMessages += group.dailyMessages || 0;
1940
+ uniqueGroups[groupId].entries.push({
1941
+ level: group.level,
1942
+ xp: group.xp,
1943
+ royalties: group.royalties,
1944
+ dailyMessages: group.dailyMessages
1945
+ });
1946
+ }
1947
+
1948
+
1949
+ document.getElementById('groupsContainer').innerHTML = '';
1950
+
1951
+ // Display group stats
1952
+ const groupsContainer = document.getElementById('groupsContainer');
1953
+
1954
+ for (const groupId in uniqueGroups) {
1955
+ const group = uniqueGroups[groupId];
1956
+
1957
+ let groupMeta = null;
1958
+ let metaError = null;
1959
+
1960
+ try {
1961
+ const groupMetaRes = await fetch(`https://reaperxxxx-testldb.hf.space/group/${groupId}/meta`);
1962
+
1963
+ if (groupMetaRes.ok) {
1964
+ groupMeta = await groupMetaRes.json();
1965
+ } else {
1966
+ const errorText = await groupMetaRes.text();
1967
+ metaError = `API Error: ${groupMetaRes.status}`;
1968
+ }
1969
+ } catch (err) {
1970
+ metaError = `Fetch Error: ${err.message}`;
1971
+ }
1972
+
1973
+ const div = document.createElement('div');
1974
+ div.className = 'group-box';
1975
+
1976
+ const displayName = (groupMeta && groupMeta.status && groupMeta.groupName)
1977
+ ? groupMeta.groupName
1978
+ : group.fullName || 'Unknown Group';
1979
+
1980
+ const groupPic = (groupMeta && groupMeta.status && groupMeta.groupPic)
1981
+ ? groupMeta.groupPic
1982
+ : null;
1983
+
1984
+ const admins = (groupMeta && groupMeta.status && groupMeta.admins)
1985
+ ? groupMeta.admins
1986
+ : null;
1987
+
1988
+ div.innerHTML = `
1989
+ <div class="group-header">
1990
+ ${groupPic ? `<img class="group-pic" src="${groupPic}" alt="Group Picture">` : '<div class="group-pic" style="background: linear-gradient(45deg, #00bcd4, #87ceeb); display: flex; align-items: center; justify-content: center; color: #0a0a0a; font-weight: bold;">👥</div>'}
1991
+ <div class="group-info">
1992
+ <div class="group-name">${displayName}</div>
1993
+ <div class="group-id">ID: ${groupId}</div>
1994
+ </div>
1995
+ </div>
1996
+
1997
+ <div class="group-stats">
1998
+ <div class="group-stat-item">
1999
+ <span class="group-stat-value">${group.totalLevel}</span>
2000
+ <span class="group-stat-label">Level</span>
2001
+ </div>
2002
+ <div class="group-stat-item">
2003
+ <span class="group-stat-value">${group.totalXP.toLocaleString()}</span>
2004
+ <span class="group-stat-label">XP</span>
2005
+ </div>
2006
+ <div class="group-stat-item">
2007
+ <span class="group-stat-value">${group.totalRoyalties.toLocaleString()}</span>
2008
+ <span class="group-stat-label">Royalties</span>
2009
+ </div>
2010
+ <div class="group-stat-item">
2011
+ <span class="group-stat-value">${group.totalDailyMessages}</span>
2012
+ <span class="group-stat-label">Daily</span>
2013
+ </div>
2014
+ </div>
2015
+
2016
+ ${metaError ? `<div class="error">⚠️ ${metaError}</div>` : ''}
2017
+
2018
+ ${admins && admins.length > 0 ? `
2019
+ <div class="group-admins">
2020
+ <details>
2021
+ <summary>👑 Admins (${admins.length})</summary>
2022
+ <div class="admin-list">
2023
+ ${admins.slice(0, 5).map(a => `<span class="admin-tag" onclick="window.open('https://t.me/finralxbot/info?startapp=${a.id}', '_blank')">${a.name || 'Unknown'}</span>`).join('')}
2024
+ ${admins.length > 5 ? `<span class="admin-tag">+${admins.length - 5} more</span>` : ''}
2025
+ </div>
2026
+ </details>
2027
+ </div>` : ''}
2028
+ `;
2029
+
2030
+ groupsContainer.appendChild(div);
2031
+ }
2032
+
2033
+ document.getElementById('groupsSection').style.display = 'block';
2034
+ }
2035
+
2036
+ try {
2037
+ const nftsRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/nfts`);
2038
+ const nftsData = await nftsRes.json();
2039
+
2040
+ const nftsContainer = document.getElementById('nftsContainer');
2041
+ const showAllBtn = document.getElementById('showAllNftsBtn');
2042
+ const remainingCount = document.getElementById('remainingCount');
2043
+ const nftStats = document.getElementById('nftStats');
2044
+
2045
+ if (nftsData.status && nftsData.nfts && nftsData.nfts.length > 0) {
2046
+ // Sort NFTs by holders (ascending) to show rarest first
2047
+ const sortedNfts = nftsData.nfts.sort((a, b) => a.holders - b.holders);
2048
+
2049
+ // Calculate NFT statistics
2050
+ const totalNfts = sortedNfts.length;
2051
+ const avgQuality = Math.round(sortedNfts.reduce((sum, nft) => sum + nft.nftquality, 0) / totalNfts);
2052
+ const rarestHolders = Math.min(...sortedNfts.map(nft => nft.holders));
2053
+ const highestQuality = Math.max(...sortedNfts.map(nft => nft.nftquality));
2054
+
2055
+ // Update NFT stats
2056
+ document.getElementById('totalNfts').textContent = totalNfts;
2057
+ document.getElementById('avgQuality').textContent = avgQuality;
2058
+ document.getElementById('rarestHolders').textContent = rarestHolders;
2059
+ document.getElementById('highestQuality').textContent = highestQuality;
2060
+ nftStats.style.display = 'block';
2061
+
2062
+ function getQualityClass(quality) {
2063
+ if (quality >= 81) return 'legendary';
2064
+ if (quality >= 61) return 'way-better';
2065
+ if (quality >= 41) return 'even-better';
2066
+ if (quality >= 21) return 'better';
2067
+ return 'basic';
2068
+ }
2069
+
2070
+ function getQualityBadgeClass(quality) {
2071
+ if (quality >= 81) return 'quality-legendary';
2072
+ if (quality >= 61) return 'quality-way-better';
2073
+ if (quality >= 41) return 'quality-even-better';
2074
+ if (quality >= 21) return 'quality-better';
2075
+ return 'quality-basic';
2076
+ }
2077
+
2078
+ function getRarityClass(rarity) {
2079
+ const rarityLower = rarity.toLowerCase();
2080
+ if (rarityLower.includes('mythic')) return 'rarity-mythic';
2081
+ if (rarityLower.includes('legendary')) return 'rarity-legendary';
2082
+ if (rarityLower.includes('epic')) return 'rarity-epic';
2083
+ if (rarityLower.includes('rare')) return 'rarity-rare';
2084
+ if (rarityLower.includes('uncommon')) return 'rarity-uncommon';
2085
+ return 'rarity-common';
2086
+ }
2087
+
2088
+ function formatDate(dateString) {
2089
+ const date = new Date(dateString);
2090
+ return date.toLocaleDateString('en-US', {
2091
+ month: 'short',
2092
+ day: 'numeric',
2093
+ year: 'numeric'
2094
+ });
2095
+ }
2096
+
2097
+ function formatDateTime(dateString) {
2098
+ const date = new Date(dateString);
2099
+ return date.toLocaleString('en-US', {
2100
+ month: 'short',
2101
+ day: 'numeric',
2102
+ year: 'numeric',
2103
+ hour: '2-digit',
2104
+ minute: '2-digit'
2105
+ });
2106
+ }
2107
+
2108
+ function createNftCard(nft) {
2109
+ const qualityClass = getQualityClass(nft.nftquality);
2110
+ const qualityBadgeClass = getQualityBadgeClass(nft.nftquality);
2111
+ const rarityClass = getRarityClass(nft.rarity);
2112
+ const uniqueId = `details-${nft.nftid}`;
2113
+
2114
+ return `
2115
+ <div class="nft-card ${qualityClass}" style="animation: fadeInUp 0.6s ease forwards; opacity: 0;">
2116
+ <div class="quality-badge ${qualityBadgeClass}">${nft.nftquality}</div>
2117
+ <img src="${nft.nftimage}" alt="${nft.name}" class="nft-image" loading="lazy">
2118
+ <div class="nft-info">
2119
+ <div class="nft-header">
2120
+ <div class="nft-name" title="${nft.name}">${nft.name}</div>
2121
+ <div class="nft-id">#${nft.nftid}</div>
2122
+ </div>
2123
+ <div class="nft-rarity ${rarityClass}">${nft.rarity}</div>
2124
+ <button class="toggle-details" onclick="toggleDetails('${uniqueId}', this)">▼ Show Details</button>
2125
+ <div class="nft-details-wrapper" id="${uniqueId}" style="display: none;">
2126
+ <div class="nft-details">
2127
+ <div class="nft-detail">
2128
+ <span class="nft-detail-label">Quality</span>
2129
+ <span class="nft-detail-value">${nft.nftquality}/100</span>
2130
+ </div>
2131
+ <div class="nft-detail">
2132
+ <span class="nft-detail-label">Holders</span>
2133
+ <span class="nft-detail-value">${nft.holders}</span>
2134
+ </div>
2135
+ </div>
2136
+ <div class="nft-obtained">
2137
+ <span class="nft-obtained-label">Obtained On</span>
2138
+ <span class="nft-obtained-value">${formatDateTime(nft.gotten_on)}</span>
2139
+ </div>
2140
+ </div>
2141
+ </div>
2142
+ </div>
2143
+ `;
2144
+ }
2145
+
2146
+ // Show first 5 NFTs initially
2147
+ const initialNfts = sortedNfts.slice(0, 5);
2148
+ const remainingNfts = sortedNfts.slice(5);
2149
+
2150
+ nftsContainer.innerHTML = `
2151
+ <div class="nfts-grid">
2152
+ ${initialNfts.map(nft => createNftCard(nft)).join('')}
2153
+ </div>
2154
+ `;
2155
+
2156
+ // Show "Show All" button if there are more NFTs
2157
+ if (remainingNfts.length > 0) {
2158
+ remainingCount.textContent = remainingNfts.length;
2159
+ showAllBtn.style.display = 'block';
2160
+
2161
+ let allShown = false;
2162
+ showAllBtn.addEventListener('click', () => {
2163
+ if (!allShown) {
2164
+ const nftsGrid = nftsContainer.querySelector('.nfts-grid');
2165
+ nftsGrid.innerHTML += remainingNfts.map(nft => createNftCard(nft)).join('');
2166
+ showAllBtn.textContent = 'Show Less';
2167
+ allShown = true;
2168
+ } else {
2169
+ const nftsGrid = nftsContainer.querySelector('.nfts-grid');
2170
+ nftsGrid.innerHTML = initialNfts.map(nft => createNftCard(nft)).join('');
2171
+ showAllBtn.innerHTML = `Show All NFTs (<span id="remainingCount">${remainingNfts.length}</span> more)`;
2172
+ allShown = false;
2173
+ }
2174
+ });
2175
+ }
2176
+
2177
+ setTimeout(() => {
2178
+ const nftCards = document.querySelectorAll('.nft-card');
2179
+ nftCards.forEach((card, index) => {
2180
+ setTimeout(() => {
2181
+ card.style.opacity = '1';
2182
+ }, index * 100);
2183
+ });
2184
+ }, 100);
2185
+
2186
+ document.getElementById('nftsSection').style.display = 'block';
2187
+ } else {
2188
+ // No NFTs found
2189
+ nftsContainer.innerHTML = `
2190
+ <div class="no-nfts">
2191
+ <div class="no-nfts-icon">🎨</div>
2192
+ <h4>No NFTs Found</h4>
2193
+ <p>This user hasn't collected any NFTs yet.</p>
2194
+ <p>Start your digital art journey today!</p>
2195
+ </div>
2196
+ `;
2197
+ document.getElementById('nftsSection').style.display = 'block';
2198
+ }
2199
+ } catch (err) {
2200
+ console.error('Error fetching NFTs:', err);
2201
+ const nftsContainer = document.getElementById('nftsContainer');
2202
+ nftsContainer.innerHTML = `
2203
+ <div class="no-nfts">
2204
+ <div class="no-nfts-icon">⚠️</div>
2205
+ <h4>Failed to Load NFTs</h4>
2206
+ <p>Unable to fetch NFT collection data.</p>
2207
+ <p>Please try again later.</p>
2208
+ </div>
2209
+ `;
2210
+ document.getElementById('nftsSection').style.display = 'block';
2211
+ }
2212
+ } catch (err) {
2213
+ console.error('Error fetching user data:', err);
2214
+ document.getElementById('chatId').innerHTML = '<div class="error">❌ Failed to load user info</div>';
2215
+ }
2216
+ });
2217
+
2218
+ function toggleDetails(id, button) {
2219
+ const details = document.getElementById(id);
2220
+ const isVisible = details.style.display === 'block';
2221
+
2222
+ details.style.display = isVisible ? 'none' : 'block';
2223
+ button.textContent = isVisible ? '▼ Show Details' : '▲ Hide Details';
2224
  }
2225
  </script>
2226
+
2227
+ <!-- Added fadeInUp animation -->
2228
+ <style>
2229
+ @keyframes fadeInUp {
2230
+ from {
2231
+ opacity: 0;
2232
+ transform: translateY(30px);
2233
+ }
2234
+ to {
2235
+ opacity: 1;
2236
+ transform: translateY(0);
2237
+ }
2238
+ }
2239
+ </style>
2240
  </body>
2241
  </html>