Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | |
| <title>Finral - User Profile Search</title> | |
| <script src="https://telegram.org/js/telegram-web-app.js"></script> | |
| <style> | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| html, body { | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| background: linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 50%, #16213e 100%); | |
| color: #e0e6ed; | |
| padding: 0; | |
| margin: 0; | |
| min-height: 100vh; | |
| position: relative; | |
| overflow-x: hidden; | |
| max-width: 100vw; | |
| } | |
| .header { | |
| background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); | |
| border-bottom: 2px solid #00bcd4; | |
| padding: 10px; | |
| text-align: center; | |
| box-shadow: 0 4px 20px rgba(0, 188, 212, 0.3); | |
| position: relative; | |
| z-index: 100; | |
| } | |
| .header::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: linear-gradient(45deg, transparent 30%, rgba(0, 188, 212, 0.1) 50%, transparent 70%); | |
| animation: shimmer 3s infinite; | |
| } | |
| @keyframes shimmer { | |
| 0% { transform: translateX(-100%); } | |
| 100% { transform: translateX(100%); } | |
| } | |
| .page-title { | |
| font-size: 1.6rem; | |
| font-weight: 900; | |
| background: linear-gradient(45deg, var(--theme-primary), var(--theme-secondary), #ffffff, var(--theme-primary)); | |
| background-size: 300% 300%; | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| margin-bottom: 3px; | |
| text-shadow: 0 0 30px rgba(0, 188, 212, 0.8); | |
| animation: gradientShift 4s ease-in-out infinite; | |
| letter-spacing: 1px; | |
| position: relative; | |
| z-index: 3; | |
| } | |
| .page-title::after { | |
| content: '🔍'; | |
| position: absolute; | |
| right: -25px; | |
| top: -3px; | |
| font-size: 1rem; | |
| animation: spark 2s infinite; | |
| } | |
| @keyframes gradientShift { | |
| 0%, 100% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| } | |
| @keyframes spark { | |
| 0%, 100% { transform: rotate(0deg) scale(1); opacity: 0.7; } | |
| 50% { transform: rotate(15deg) scale(1.2); opacity: 1; } | |
| } | |
| .creator { | |
| font-size: 0.7rem; | |
| background: linear-gradient(45deg, var(--theme-secondary), var(--theme-primary)); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| margin-bottom: 3px; | |
| font-weight: 600; | |
| letter-spacing: 0.5px; | |
| position: relative; | |
| z-index: 3; | |
| } | |
| .page-subtitle { | |
| font-size: 0.65rem; | |
| color: rgba(135, 206, 235, 0.8); | |
| margin-bottom: 0; | |
| font-style: italic; | |
| font-weight: 300; | |
| position: relative; | |
| z-index: 3; | |
| } | |
| .main-layout { | |
| display: flex; | |
| min-height: calc(100vh - 80px); | |
| } | |
| .sidebar { | |
| width: 280px; | |
| background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-primary) 100%); | |
| border-right: 2px solid var(--theme-primary); | |
| padding: 15px; | |
| position: fixed; | |
| left: 0; | |
| top: 80px; | |
| height: calc(100vh - 80px); | |
| overflow-y: auto; | |
| z-index: 50; | |
| box-shadow: 4px 0 20px rgba(var(--theme-primary-rgb), 0.3); | |
| } | |
| .sidebar-toggle { | |
| display: none; | |
| position: fixed; | |
| top: 90px; | |
| left: 10px; | |
| z-index: 60; | |
| background: linear-gradient(45deg, var(--theme-primary), var(--theme-secondary)); | |
| border: none; | |
| border-radius: 50%; | |
| width: 40px; | |
| height: 40px; | |
| color: #0a0a0a; | |
| font-size: 1.2rem; | |
| cursor: pointer; | |
| box-shadow: 0 4px 15px rgba(0, 188, 212, 0.5); | |
| } | |
| .search-section { | |
| background: linear-gradient(135deg, var(--theme-bg-primary) 0%, var(--theme-bg-secondary) 100%); | |
| border: 1px solid var(--theme-primary); | |
| border-radius: 10px; | |
| padding: 15px; | |
| margin-bottom: 15px; | |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .search-section::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, var(--theme-primary), transparent); | |
| } | |
| .search-section h3 { | |
| font-size: 1rem; | |
| color: var(--theme-primary); | |
| margin-bottom: 12px; | |
| display: flex; | |
| align-items: center; | |
| gap: 6px; | |
| } | |
| .search-section h3::before { | |
| content: ''; | |
| width: 3px; | |
| height: 15px; | |
| background: linear-gradient(45deg, #00bcd4, #87ceeb); | |
| border-radius: 2px; | |
| } | |
| .search-input { | |
| padding: 10px 12px; | |
| font-size: 0.9rem; | |
| width: 100%; | |
| border: 2px solid #00bcd4; | |
| border-radius: 6px; | |
| margin-bottom: 10px; | |
| background: rgba(26, 26, 46, 0.8); | |
| color: #e0e6ed; | |
| transition: all 0.3s ease; | |
| } | |
| .search-input:focus { | |
| outline: none; | |
| border-color: var(--theme-secondary); | |
| box-shadow: 0 0 10px rgba(0, 188, 212, 0.4); | |
| } | |
| .search-input::placeholder { | |
| color: var(--theme-secondary); | |
| } | |
| .search-btn { | |
| padding: 10px 16px; | |
| font-size: 0.9rem; | |
| background: linear-gradient(45deg, var(--theme-primary), var(--theme-secondary)); | |
| color: #0a0a0a; | |
| border: none; | |
| border-radius: 6px; | |
| cursor: pointer; | |
| font-weight: bold; | |
| transition: all 0.3s ease; | |
| width: 100%; | |
| } | |
| .search-btn:hover { | |
| transform: translateY(-1px); | |
| box-shadow: 0 4px 15px rgba(0, 188, 212, 0.4); | |
| } | |
| .search-btn:disabled { | |
| background: #555; | |
| cursor: not-allowed; | |
| transform: none; | |
| box-shadow: none; | |
| } | |
| .search-result { | |
| margin-top: 10px; | |
| padding: 12px; | |
| background: rgba(0, 188, 212, 0.1); | |
| border: 1px solid rgba(0, 188, 212, 0.3); | |
| border-radius: 6px; | |
| font-size: 0.85rem; | |
| } | |
| .view-profile-btn { | |
| padding: 6px 12px; | |
| background: linear-gradient(45deg, #4caf50, #66bb6a); | |
| color: white; | |
| border: none; | |
| border-radius: 4px; | |
| cursor: pointer; | |
| margin-top: 8px; | |
| font-weight: bold; | |
| font-size: 0.8rem; | |
| transition: all 0.3s ease; | |
| width: 100%; | |
| } | |
| .view-profile-btn:hover { | |
| transform: translateY(-1px); | |
| box-shadow: 0 3px 10px rgba(76, 175, 80, 0.4); | |
| } | |
| .content { | |
| flex: 1; | |
| margin-left: 280px; | |
| padding: 15px; | |
| overflow-x: auto; | |
| } | |
| .top-section { | |
| display: grid; | |
| grid-template-columns: 1fr 300px; | |
| gap: 15px; | |
| margin-bottom: 15px; | |
| min-height: 200px; | |
| } | |
| .banner-profile-container { | |
| position: relative; | |
| background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-primary) 100%); | |
| border: 1px solid var(--theme-primary); | |
| border-radius: 10px; | |
| overflow: hidden; | |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); | |
| } | |
| .banner-profile-container::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, var(--theme-primary), transparent); | |
| z-index: 2; | |
| } | |
| #banner { | |
| width: 100%; | |
| height: 140px; | |
| object-fit: cover; | |
| border-radius: 0; | |
| } | |
| .banner-overlay { | |
| position: absolute; | |
| top: 2px; | |
| left: 0; | |
| right: 0; | |
| height: 138px; | |
| background: linear-gradient( | |
| to bottom, | |
| rgba(0, 0, 0, 0.1) 0%, | |
| rgba(0, 0, 0, 0.3) 50%, | |
| rgba(26, 26, 46, 0.8) 100% | |
| ); | |
| z-index: 2; | |
| } | |
| #pfp { | |
| position: absolute; | |
| bottom: 10px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: 105px; | |
| height: 105px; | |
| object-fit: cover; | |
| border-radius: 5%; | |
| border: 3px solid var(--theme-primary); /* use theme color */ | |
| box-shadow: | |
| 0 0 20px rgba(var(--theme-primary-rgb), 0.8), /* use theme RGB for shadow */ | |
| 0 0 40px rgba(var(--theme-primary-rgb), 0.4); | |
| background: var(--theme-bg-secondary); | |
| z-index: 4; | |
| } | |
| .profile-glow { | |
| position: absolute; | |
| bottom: -30px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: 100px; | |
| height: 100px; | |
| border-radius: 50%; | |
| background: radial-gradient( | |
| circle, | |
| rgba(var(--theme-primary-rgb), 0.4) 0%, | |
| rgba(var(--theme-primary-rgb), 0.2) 50%, | |
| transparent 70% | |
| ); | |
| z-index: 3; | |
| animation: profileGlow 3s ease-in-out infinite alternate; | |
| } | |
| @keyframes profileGlow { | |
| 0% { transform: translateX(-50%) scale(1); opacity: 0.6; } | |
| 100% { transform: translateX(-50%) scale(1.1); opacity: 0.9; } | |
| } | |
| .user-info-card { | |
| background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-primary) 100%); | |
| border: 1px solid var(--theme-primary); | |
| border-radius: 10px; | |
| padding: 15px; | |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); | |
| position: relative; | |
| overflow: hidden; | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| } | |
| .user-info-card::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, var(--theme-primary), transparent); | |
| } | |
| .welcome-title { | |
| font-size: 1.2rem; | |
| font-weight: bold; | |
| color: #e0e6ed; | |
| margin-bottom: 8px; | |
| background: linear-gradient(45deg, #e0e6ed, #87ceeb); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| text-align: center; | |
| } | |
| .chat-id { | |
| font-size: 1rem; | |
| font-weight: bold; | |
| color: #00bcd4; | |
| background: rgba(0, 188, 212, 0.1); | |
| border: 1px solid rgba(0, 188, 212, 0.3); | |
| border-radius: 6px; | |
| padding: 8px; | |
| text-align: center; | |
| margin-bottom: 10px; | |
| } | |
| .stats-grid { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 12px; | |
| margin-bottom: 15px; | |
| } | |
| .stats-section { | |
| background: | |
| var(--theme-stats-bg-image, none), /* optional image */ | |
| linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); | |
| background-size: contain; /* or cover, depending on whether you want full image or cropped */ | |
| background-position: center; | |
| background-repeat: no-repeat; | |
| border: 1px solid #00bcd4; | |
| border-radius: 10px; | |
| padding: 15px; | |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .stats-section::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, #00bcd4, transparent); | |
| } | |
| .stats-section h3 { | |
| font-size: 1.1rem; | |
| color: #00bcd4; | |
| margin-bottom: 12px; | |
| display: flex; | |
| align-items: center; | |
| gap: 6px; | |
| } | |
| .stats-section h3::before { | |
| content: ''; | |
| width: 3px; | |
| height: 15px; | |
| background: linear-gradient(45deg, #00bcd4, #87ceeb); | |
| border-radius: 2px; | |
| } | |
| .basic-stats-grid { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 8px; | |
| } | |
| .stat-item { | |
| background: rgba(0, 188, 212, 0.1); | |
| border: 1px solid rgba(0, 188, 212, 0.3); | |
| border-radius: 6px; | |
| padding: 8px 6px; | |
| text-align: center; | |
| transition: all 0.3s ease; | |
| } | |
| .stat-item:hover { | |
| border-color: #00bcd4; | |
| box-shadow: 0 2px 8px rgba(0, 188, 212, 0.3); | |
| transform: translateY(-1px); | |
| } | |
| .stat-item strong { | |
| color: #87ceeb; | |
| font-size: 0.75rem; | |
| display: block; | |
| margin-bottom: 2px; | |
| } | |
| .stat-value { | |
| color: #00bcd4; | |
| font-weight: bold; | |
| font-size: 0.9rem; | |
| } | |
| .groups-container { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | |
| gap: 12px; | |
| } | |
| .group-box { | |
| background: linear-gradient(135deg, var(--theme-bg-tertiary) 0%, var(--theme-bg-secondary) 100%); | |
| border: 1px solid var(--theme-primary); | |
| border-radius: 8px; | |
| padding: 12px; | |
| transition: all 0.3s ease; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .group-box::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 1px; | |
| background: linear-gradient(90deg, transparent, var(--theme-primary), transparent); | |
| } | |
| .group-box:hover { | |
| border-color: var(--theme-primary); | |
| box-shadow: 0 4px 15px rgba(0, 188, 212, 0.3); | |
| transform: translateY(-2px); | |
| } | |
| .group-header { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| margin-bottom: 10px; | |
| } | |
| .group-pic { | |
| width: 50px; | |
| height: 50px; | |
| object-fit: cover; | |
| border-radius: 8px; | |
| border: 2px solid var(--theme-primary); | |
| flex-shrink: 0; | |
| } | |
| .group-info { | |
| flex: 1; | |
| min-width: 0; | |
| } | |
| .group-name { | |
| font-weight: bold; | |
| color: var(--theme-primary); | |
| font-size: 0.9rem; | |
| margin-bottom: 2px; | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| .group-id { | |
| font-size: 0.75rem; | |
| color: var(--theme-secondary); | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| .group-stats { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 6px; | |
| margin-bottom: 8px; | |
| } | |
| .group-stat-item { | |
| background: rgba(0, 188, 212, 0.05); | |
| border: 1px solid var(--theme-primary); | |
| border-radius: 4px; | |
| padding: 4px 6px; | |
| text-align: center; | |
| } | |
| .group-stat-value { | |
| font-weight: bold; | |
| color: var(--theme-primary); | |
| font-size: 0.8rem; | |
| display: block; | |
| } | |
| .group-stat-label { | |
| font-size: 0.65rem; | |
| color: var(--theme-secondary); | |
| } | |
| .group-admins { | |
| margin-top: 8px; | |
| font-size: 0.8rem; | |
| } | |
| .group-admins summary { | |
| color: var(--theme-secondary); | |
| cursor: pointer; | |
| font-weight: bold; | |
| margin-bottom: 4px; | |
| } | |
| .admin-list { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 4px; | |
| margin-top: 4px; | |
| } | |
| .admin-tag { | |
| background: rgba(0, 188, 212, 0.2); | |
| border: 1px solid var(--theme-primary); | |
| border-radius: 12px; | |
| padding: 2px 6px; | |
| font-size: 0.7rem; | |
| color: var(--theme-secondary); | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| } | |
| .admin-tag:hover { | |
| background: rgba(0, 188, 212, 0.3); | |
| color: #00bcd4; | |
| } | |
| .error { | |
| color: #ff6b6b; | |
| font-style: italic; | |
| background: rgba(255, 107, 107, 0.1); | |
| border: 1px solid rgba(255, 107, 107, 0.3); | |
| border-radius: 4px; | |
| padding: 6px; | |
| margin: 6px 0; | |
| font-size: 0.8rem; | |
| } | |
| .loading { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 10px; | |
| color: #87ceeb; | |
| font-size: 1rem; | |
| padding: 40px 20px; | |
| } | |
| .loading-spinner { | |
| width: 20px; | |
| height: 20px; | |
| border: 2px solid #87ceeb; | |
| border-top: 2px solid #00bcd4; | |
| border-radius: 50%; | |
| animation: spin 1s linear infinite; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| .loading-dots { | |
| display: inline-flex; | |
| gap: 4px; | |
| } | |
| .loading-dot { | |
| width: 6px; | |
| height: 6px; | |
| background: #00bcd4; | |
| border-radius: 50%; | |
| animation: loadingDots 1.4s infinite ease-in-out; | |
| } | |
| @keyframes loadingDots { | |
| 0%, 80%, 100% { transform: scale(0); opacity: 0.5; } | |
| 40% { transform: scale(1); opacity: 1; } | |
| } | |
| /* NFT Styles */ | |
| .nfts-section { | |
| background: var(--theme-nft-bg-image, none), /* optional image */ | |
| linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%); | |
| background-size: cover; | |
| background-position: center; | |
| background-repeat: no-repeat; | |
| border: 1px solid var(--theme-primary); | |
| border-radius: 10px; | |
| padding: 15px; | |
| margin-bottom: 15px; | |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .nfts-section::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, var(--theme-primary), transparent); | |
| } | |
| .nfts-section h3 { | |
| font-size: 1.1rem; | |
| color: var(--theme-primary); | |
| margin-bottom: 15px; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .nfts-section h3::before { | |
| content: ''; | |
| width: 3px; | |
| height: 15px; | |
| background: linear-gradient(45deg, var(--theme-primary), var(--theme-secondary)); | |
| border-radius: 2px; | |
| } | |
| .nfts-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); | |
| gap: 15px; | |
| margin-bottom: 15px; | |
| } | |
| .nft-card { | |
| border-radius: 12px; | |
| padding: 12px; | |
| transition: all 0.3s ease; | |
| position: relative; | |
| overflow: hidden; | |
| cursor: pointer; | |
| } | |
| /* Basic Quality (0-20) */ | |
| .nft-card.basic { | |
| background: linear-gradient(135deg, #2a2a3e 0%, #1e1e32 100%); | |
| border: 1px solid #555; | |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); | |
| } | |
| .nft-card.basic:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 4px 12px rgba(85, 85, 85, 0.4); | |
| } | |
| /* Better Quality (21-40) */ | |
| .nft-card.better { | |
| background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%); | |
| border: 1px solid #4caf50; | |
| box-shadow: 0 3px 10px rgba(76, 175, 80, 0.3); | |
| } | |
| .nft-card.better::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, #4caf50, transparent); | |
| } | |
| .nft-card.better:hover { | |
| transform: translateY(-3px); | |
| box-shadow: 0 6px 15px rgba(76, 175, 80, 0.5); | |
| } | |
| /* Even Better Quality (41-60) */ | |
| .nft-card.even-better { | |
| background: linear-gradient(135deg, #1a1e3e 0%, #2e1a3e 100%); | |
| border: 1px solid #9c27b0; | |
| box-shadow: 0 4px 12px rgba(156, 39, 176, 0.4); | |
| position: relative; | |
| } | |
| .nft-card.even-better::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, #9c27b0, #e91e63, transparent); | |
| } | |
| .nft-card.even-better::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: linear-gradient(45deg, transparent 30%, rgba(156, 39, 176, 0.1) 50%, transparent 70%); | |
| animation: shimmer 3s infinite; | |
| pointer-events: none; | |
| } | |
| .nft-card.even-better:hover { | |
| transform: translateY(-4px); | |
| box-shadow: 0 8px 20px rgba(156, 39, 176, 0.6); | |
| } | |
| /* Way Better Quality (61-80) */ | |
| .nft-card.way-better { | |
| background: linear-gradient(135deg, #3e1a1a 0%, #3e2a1a 100%); | |
| border: 2px solid #ff9800; | |
| box-shadow: 0 5px 15px rgba(255, 152, 0, 0.5); | |
| position: relative; | |
| } | |
| .nft-card.way-better::before { | |
| content: ''; | |
| position: absolute; | |
| top: -2px; | |
| left: -2px; | |
| right: -2px; | |
| bottom: -2px; | |
| background: linear-gradient(45deg, #ff9800, #ffc107, #ff5722, #ff9800); | |
| background-size: 300% 300%; | |
| border-radius: 12px; | |
| z-index: -1; | |
| animation: gradientShift 2s ease-in-out infinite; | |
| } | |
| .nft-card.way-better::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: linear-gradient(45deg, transparent 30%, rgba(255, 152, 0, 0.2) 50%, transparent 70%); | |
| animation: shimmer 2s infinite; | |
| pointer-events: none; | |
| } | |
| .nft-card.way-better:hover { | |
| transform: translateY(-5px) scale(1.02); | |
| box-shadow: 0 10px 25px rgba(255, 152, 0, 0.7); | |
| } | |
| /* Legendary Quality (81-100) */ | |
| .nft-card.legendary { | |
| background: linear-gradient(135deg, #3e1a3e 0%, #1a3e3e 100%); | |
| border: 3px solid #ffd700; | |
| box-shadow: | |
| 0 0 20px rgba(255, 215, 0, 0.6), | |
| 0 0 40px rgba(255, 215, 0, 0.4), | |
| 0 0 60px rgba(255, 215, 0, 0.2); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .nft-card.legendary::before { | |
| content: ''; | |
| position: absolute; | |
| top: -3px; | |
| left: -3px; | |
| right: -3px; | |
| bottom: -3px; | |
| background: linear-gradient(45deg, #ffd700, #ffeb3b, #ff6f00, #ffd700); | |
| background-size: 400% 400%; | |
| border-radius: 12px; | |
| z-index: -1; | |
| animation: legendaryGlow 1.5s ease-in-out infinite; | |
| } | |
| .nft-card.legendary::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: | |
| radial-gradient(circle at 20% 20%, rgba(255, 215, 0, 0.3) 0%, transparent 50%), | |
| radial-gradient(circle at 80% 80%, rgba(255, 235, 59, 0.3) 0%, transparent 50%), | |
| linear-gradient(45deg, transparent 30%, rgba(255, 215, 0, 0.1) 50%, transparent 70%); | |
| animation: legendaryShimmer 3s infinite; | |
| pointer-events: none; | |
| } | |
| .nft-card.legendary:hover { | |
| transform: translateY(-6px) scale(1.05); | |
| box-shadow: | |
| 0 0 30px rgba(255, 215, 0, 0.8), | |
| 0 0 60px rgba(255, 215, 0, 0.6), | |
| 0 0 90px rgba(255, 215, 0, 0.4); | |
| } | |
| @keyframes legendaryGlow { | |
| 0%, 100% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| } | |
| @keyframes legendaryShimmer { | |
| 0% { transform: translateX(-100%) rotate(45deg); } | |
| 100% { transform: translateX(100%) rotate(45deg); } | |
| } | |
| .nft-image { | |
| width: 100%; | |
| aspect-ratio: 1; | |
| object-fit: cover; | |
| border-radius: 8px; | |
| margin-bottom: 12px; | |
| transition: all 0.3s ease; | |
| } | |
| .nft-card:hover .nft-image { | |
| transform: scale(1.05); | |
| } | |
| .nft-info { | |
| position: relative; | |
| z-index: 2; | |
| } | |
| .nft-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: flex-start; | |
| margin-bottom: 8px; | |
| } | |
| .nft-name { | |
| font-weight: bold; | |
| font-size: 1rem; | |
| color: #e0e6ed; | |
| flex: 1; | |
| margin-right: 8px; | |
| line-height: 1.2; | |
| } | |
| .nft-id { | |
| font-size: 0.7rem; | |
| color: #87ceeb; | |
| background: rgba(0, 188, 212, 0.1); | |
| border: 1px solid rgba(0, 188, 212, 0.3); | |
| border-radius: 4px; | |
| padding: 2px 6px; | |
| white-space: nowrap; | |
| } | |
| .nft-rarity { | |
| font-size: 0.8rem; | |
| padding: 3px 8px; | |
| border-radius: 12px; | |
| display: inline-block; | |
| margin-bottom: 8px; | |
| font-weight: bold; | |
| text-transform: uppercase; | |
| letter-spacing: 0.5px; | |
| } | |
| /* Keep rarity colors as they represent game mechanics, but make rare use theme color */ | |
| .rarity-common { background: #666; color: #fff; } | |
| .rarity-uncommon { background: #4caf50; color: #fff; } | |
| .rarity-rare { background: var(--theme-primary); color: #fff; } | |
| .rarity-epic { background: #9c27b0; color: #fff; } | |
| .rarity-legendary { background: #ff9800; color: #fff; } | |
| .rarity-mythic { background: #f44336; color: #fff; } | |
| .nft-details { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 6px; | |
| margin-bottom: 10px; | |
| } | |
| .nft-detail { | |
| background: rgba(0, 188, 212, 0.1); | |
| border: 1px solid rgba(0, 188, 212, 0.2); | |
| border-radius: 6px; | |
| padding: 6px 8px; | |
| text-align: center; | |
| transition: all 0.3s ease; | |
| } | |
| .nft-detail:hover { | |
| background: rgba(0, 188, 212, 0.15); | |
| border-color: rgba(0, 188, 212, 0.4); | |
| } | |
| .nft-detail-label { | |
| color: #87ceeb; | |
| display: block; | |
| font-size: 0.7rem; | |
| margin-bottom: 2px; | |
| font-weight: 500; | |
| } | |
| .nft-detail-value { | |
| color: #00bcd4; | |
| font-weight: bold; | |
| font-size: 0.85rem; | |
| display: block; | |
| } | |
| .nft-obtained { | |
| background: rgba(135, 206, 235, 0.1); | |
| border: 1px solid rgba(135, 206, 235, 0.3); | |
| border-radius: 6px; | |
| padding: 6px 8px; | |
| text-align: center; | |
| grid-column: 1 / -1; | |
| } | |
| .nft-obtained-label { | |
| color: #87ceeb; | |
| font-size: 0.7rem; | |
| margin-bottom: 2px; | |
| display: block; | |
| } | |
| .nft-obtained-value { | |
| color: #87ceeb; | |
| font-weight: bold; | |
| font-size: 0.8rem; | |
| } | |
| .quality-badge { | |
| position: absolute; | |
| top: 8px; | |
| right: 8px; | |
| padding: 4px 8px; | |
| border-radius: 12px; | |
| font-size: 0.75rem; | |
| font-weight: bold; | |
| z-index: 3; | |
| display: flex; | |
| align-items: center; | |
| gap: 4px; | |
| } | |
| .quality-basic { | |
| background: linear-gradient(45deg, #666, #888); | |
| color: #fff; | |
| } | |
| .quality-better { | |
| background: linear-gradient(45deg, #4caf50, #66bb6a); | |
| color: #fff; | |
| } | |
| .quality-even-better { | |
| background: linear-gradient(45deg, #9c27b0, #ba68c8); | |
| color: #fff; | |
| } | |
| .quality-way-better { | |
| background: linear-gradient(45deg, #ff9800, #ffb74d); | |
| color: #fff; | |
| } | |
| .quality-legendary { | |
| background: linear-gradient(45deg, #ffd700, #ffeb3b); | |
| color: #000; | |
| box-shadow: 0 0 10px rgba(255, 215, 0, 0.5); | |
| } | |
| .quality-badge::before { | |
| content: '💠'; | |
| font-size: 0.8rem; | |
| } | |
| .no-nfts { | |
| text-align: center; | |
| padding: 60px 20px; | |
| color: #87ceeb; | |
| font-style: italic; | |
| } | |
| .no-nfts-icon { | |
| font-size: 4rem; | |
| margin-bottom: 15px; | |
| opacity: 0.5; | |
| } | |
| .no-nfts h4 { | |
| font-size: 1.2rem; | |
| margin-bottom: 8px; | |
| color: #e0e6ed; | |
| } | |
| .no-nfts p { | |
| font-size: 0.9rem; | |
| margin-bottom: 5px; | |
| } | |
| .show-all-btn { | |
| background: linear-gradient(45deg, #00bcd4, #87ceeb); | |
| color: #0a0a0a; | |
| border: none; | |
| border-radius: 8px; | |
| padding: 12px 24px; | |
| font-weight: bold; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| display: block; | |
| margin: 0 auto; | |
| font-size: 0.9rem; | |
| } | |
| .show-all-btn:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 20px rgba(0, 188, 212, 0.4); | |
| } | |
| .nft-loading { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 10px; | |
| padding: 60px; | |
| color: #87ceeb; | |
| } | |
| .nft-stats { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 15px; | |
| padding: 10px 15px; | |
| background: rgba(0, 188, 212, 0.1); | |
| border: 1px solid rgba(0, 188, 212, 0.3); | |
| border-radius: 8px; | |
| } | |
| .nft-stat { | |
| text-align: center; | |
| } | |
| .nft-stat-value { | |
| font-size: 1.2rem; | |
| font-weight: bold; | |
| color: #00bcd4; | |
| display: block; | |
| } | |
| .nft-stat-label { | |
| font-size: 0.7rem; | |
| color: #87ceeb; | |
| margin-top: 2px; | |
| } | |
| /* Mobile Responsive */ | |
| @media (max-width: 768px) { | |
| .sidebar { | |
| transform: translateX(-100%); | |
| transition: transform 0.3s ease; | |
| } | |
| .sidebar.open { | |
| transform: translateX(0); | |
| } | |
| .sidebar-toggle { | |
| display: block; | |
| } | |
| .content { | |
| margin-left: 0; | |
| padding: 10px; | |
| } | |
| .top-section { | |
| grid-template-columns: 1fr; | |
| gap: 10px; | |
| } | |
| .stats-grid { | |
| grid-template-columns: 1fr; | |
| gap: 10px; | |
| } | |
| .basic-stats-grid { | |
| grid-template-columns: repeat(3, 1fr); | |
| gap: 6px; | |
| } | |
| .groups-container { | |
| grid-template-columns: 1fr; | |
| gap: 10px; | |
| } | |
| .group-stats { | |
| grid-template-columns: repeat(4, 1fr); | |
| gap: 4px; | |
| } | |
| .group-stat-item { | |
| padding: 3px 4px; | |
| } | |
| .group-stat-value { | |
| font-size: 0.75rem; | |
| } | |
| .toggle-details { | |
| background: none; | |
| border: none; | |
| color: var(--theme-primary); | |
| cursor: pointer; | |
| font-weight: bold; | |
| margin-top: 5px; | |
| padding: 0; | |
| } | |
| .toggle-details:hover { | |
| text-decoration: underline; | |
| } | |
| .group-stat-label { | |
| font-size: 0.6rem; | |
| } | |
| .nfts-grid { | |
| grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); | |
| gap: 10px; | |
| } | |
| .nft-card { | |
| padding: 10px; | |
| } | |
| .nft-name { | |
| font-size: 0.9rem; | |
| } | |
| .nft-details { | |
| gap: 4px; | |
| } | |
| .nft-detail { | |
| padding: 4px 6px; | |
| } | |
| .nft-stats { | |
| flex-direction: column; | |
| gap: 8px; | |
| } | |
| .nft-stats > div { | |
| display: flex; | |
| justify-content: space-around; | |
| width: 100%; | |
| } | |
| } | |
| @media (max-width: 480px) { | |
| .page-title { | |
| font-size: 1.4rem; | |
| } | |
| .page-title::after { | |
| right: -20px; | |
| font-size: 0.9rem; | |
| } | |
| .header { | |
| padding: 8px; | |
| } | |
| .content { | |
| padding: 8px; | |
| } | |
| .basic-stats-grid { | |
| grid-template-columns: 1fr 1fr; | |
| gap: 4px; | |
| } | |
| .stat-item { | |
| padding: 6px 4px; | |
| } | |
| .stat-item strong { | |
| font-size: 0.7rem; | |
| } | |
| .stat-value { | |
| font-size: 0.8rem; | |
| } | |
| .nfts-grid { | |
| grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); | |
| gap: 8px; | |
| } | |
| .nft-card { | |
| padding: 8px; | |
| } | |
| .nft-name { | |
| font-size: 0.8rem; | |
| } | |
| .nft-rarity { | |
| font-size: 0.7rem; | |
| padding: 2px 6px; | |
| } | |
| .nft-details { | |
| grid-template-columns: 1fr; | |
| gap: 3px; | |
| } | |
| .nft-detail { | |
| padding: 4px 6px; | |
| } | |
| .quality-badge { | |
| padding: 2px 6px; | |
| font-size: 0.7rem; | |
| } | |
| } | |
| /* Added theme variables and floating widget styles */ | |
| :root { | |
| --theme-primary: #00bcd4; | |
| --theme-secondary: #87ceeb; | |
| --theme-bg-primary: #0a0a0a; | |
| --theme-bg-secondary: #1a1a2e; | |
| --theme-bg-tertiary: #16213e; | |
| --theme-text-primary: #e0e6ed; | |
| --theme-text-secondary: #87ceeb; | |
| } | |
| /* Red Theme */ | |
| .theme-red { | |
| --theme-primary: #ff4444; | |
| --theme-secondary: #ff6b6b; | |
| --theme-bg-primary: #1a0a0a; | |
| --theme-bg-secondary: #2e1a1a; | |
| --theme-bg-tertiary: #3e1616; | |
| --theme-stats-bg-image: url('https://files.catbox.moe/0im7km.jpeg'); | |
| } | |
| /* Black Theme */ | |
| .theme-black { | |
| --theme-primary: #ffffff; | |
| --theme-secondary: #cccccc; | |
| --theme-bg-primary: #000000; | |
| --theme-bg-secondary: #1a1a1a; | |
| --theme-bg-tertiary: #2a2a2a; | |
| } | |
| .username-wrapper { | |
| display: inline-flex; /* keeps username and icon in one row */ | |
| align-items: center; /* vertical alignment */ | |
| gap: 6px; /* spacing between username and icon */ | |
| margin-bottom: 8px; | |
| } | |
| .username-icon { | |
| width: 20px; | |
| height: 20px; | |
| object-fit: contain; /* keeps icon proportion */ | |
| } | |
| /* Yellow Theme */ | |
| .theme-yellow { | |
| --theme-primary: #ffd700; | |
| --theme-secondary: #ffeb3b; | |
| --theme-bg-primary: #1a1a0a; | |
| --theme-bg-secondary: #2e2e1a; | |
| --theme-bg-tertiary: #3e3e16; | |
| --theme-text-primary: #f0f0f0; | |
| } | |
| /* Added green theme */ | |
| .theme-green { | |
| --theme-primary: #4caf50; | |
| --theme-secondary: #81c784; | |
| --theme-bg-primary: #0a1a0a; | |
| --theme-bg-secondary: #1a2e1a; | |
| --theme-bg-tertiary: #163e16; | |
| --theme-text-primary: #e8f5e8; | |
| } | |
| .theme-pink { | |
| --theme-primary: #ff66b2; | |
| --theme-secondary: #ff99cc; | |
| --theme-bg-primary: #1a0a12; | |
| --theme-bg-secondary: #2e1a24; | |
| --theme-bg-tertiary: #3e1630; | |
| --theme-text-primary: #ffe6f0; | |
| } | |
| /* Purple Theme */ | |
| .theme-purple { | |
| --theme-primary: #9b59b6; | |
| --theme-secondary: #b57edc; | |
| --theme-bg-primary: #140a1a; | |
| --theme-bg-secondary: #23142e; | |
| --theme-bg-tertiary: #31163e; | |
| --theme-text-primary: #e6d9f0; | |
| --theme-nft-bg-image: url(''); | |
| } | |
| /* Brown Theme */ | |
| .theme-brown { | |
| --theme-primary: #a0522d; /* sienna */ | |
| --theme-secondary: #cd853f; /* peru */ | |
| --theme-bg-primary: #1a120a; | |
| --theme-bg-secondary: #2e1f14; | |
| --theme-bg-tertiary: #3e2a1a; | |
| --theme-text-primary: #f5e6d3; /* light beige */ | |
| } | |
| /* White Theme */ | |
| .theme-white { | |
| --theme-primary: #cccccc; | |
| --theme-secondary: #e0e0e0; | |
| --theme-bg-primary: #1f1f1f; | |
| --theme-bg-secondary: #2a2a2a; | |
| --theme-bg-tertiary: #333333; | |
| --theme-text-primary: #f0f0f0; | |
| --theme-text-secondary: #b0b0b0; | |
| --theme-bg-image: url(''); | |
| } | |
| /* Cyan Theme */ | |
| .theme-cyan { | |
| --theme-primary: #00bcd4; /* bright cyan */ | |
| --theme-secondary: #33e0f0; /* lighter cyan */ | |
| --theme-bg-primary: #0a1a1f; /* dark cyanish background */ | |
| --theme-bg-secondary: #0f2a33; | |
| --theme-bg-tertiary: #162a3e; | |
| --theme-text-primary: #e0f7fa; /* light cyan text */ | |
| --theme-text-secondary: #a0e0e5; | |
| --theme-bg-image: url(''); /* optional background image */ | |
| } | |
| /* Teal Theme */ | |
| .theme-teal { | |
| --theme-primary: #008080; /* teal */ | |
| --theme-secondary: #20b2aa; /* lightseagreen */ | |
| --theme-bg-primary: #0a1a1a; | |
| --theme-bg-secondary: #1a2e2e; | |
| --theme-bg-tertiary: #163e3e; | |
| --theme-text-primary: #e0f7f7; | |
| } | |
| /* Orange Theme */ | |
| .theme-orange { | |
| --theme-primary: #ff7f50; /* coral */ | |
| --theme-secondary: #ffa07a; /* lightsalmon */ | |
| --theme-bg-primary: #1a0f0a; | |
| --theme-bg-secondary: #2e1a14; | |
| --theme-bg-tertiary: #3e2616; | |
| --theme-text-primary: #fff2e6; | |
| } | |
| /* Splash Theme */ | |
| .theme-splash { | |
| --theme-primary: #0d47a1; /* dark navy blue */ | |
| --theme-secondary: #1a237e; /* deeper blue */ | |
| --theme-bg-primary: #0d47a1; /* main dark blue background */ | |
| --theme-bg-secondary: #000000; /* subtle black touch */ | |
| --theme-bg-tertiary: #1b5e20; /* hint of dark green */ | |
| --theme-text-primary: #ffffff; /* white text */ | |
| --theme-text-secondary: #a5d6a7; /* light green accent */ | |
| --theme-bg-image: url(''); /* optional image */ | |
| } | |
| .theme-coral { | |
| --theme-primary: #ff7f50; | |
| --theme-secondary: #ff9f7f; | |
| --theme-bg-primary: #1a0a0a; | |
| --theme-bg-secondary: #2e1a1a; | |
| --theme-bg-tertiary: #3e1616; | |
| --theme-text-primary: #fff0e6; | |
| } | |
| .theme-magenta { | |
| --theme-primary: #ff00ff; | |
| --theme-secondary: #ff66ff; | |
| --theme-bg-primary: #1a001a; | |
| --theme-bg-secondary: #2e002e; | |
| --theme-bg-tertiary: #3e003e; | |
| --theme-text-primary: #ffe6ff; | |
| } | |
| .theme-gold { | |
| --theme-primary: #ffd700; | |
| --theme-secondary: #ffdf40; | |
| --theme-bg-primary: #1a1500; | |
| --theme-bg-secondary: #2e2700; | |
| --theme-bg-tertiary: #3e3600; | |
| --theme-text-primary: #fff9e6; | |
| } | |
| /* Violet Theme */ | |
| .theme-violet { | |
| --theme-primary: #8a2be2; /* blue violet */ | |
| --theme-secondary: #b266ff; /* lighter violet */ | |
| --theme-bg-primary: #1a0a1f; | |
| --theme-bg-secondary: #2e1a3e; | |
| --theme-bg-tertiary: #3e163e; | |
| --theme-text-primary: #e6d9f0; /* light violet text */ | |
| } | |
| /* Olive Theme */ | |
| .theme-olive { | |
| --theme-primary: #808000; /* classic olive */ | |
| --theme-secondary: #a0a050; /* lighter olive */ | |
| --theme-bg-primary: #1a1a0a; /* dark oliveish background */ | |
| --theme-bg-secondary: #2e2e1a; | |
| --theme-bg-tertiary: #3e3e16; | |
| --theme-text-primary: #f5f5e0; /* off-white text */ | |
| --theme-text-secondary: #d0d0b0; | |
| --theme-bg-image: url(''); /* optional background image */ | |
| } | |
| /* Enhanced theme coverage - applying theme colors to all elements */ | |
| html, body { | |
| background: | |
| var(--theme-bg-image, none), | |
| linear-gradient( | |
| 135deg, | |
| var(--theme-bg-primary) 0%, | |
| var(--theme-bg-secondary) 50%, | |
| var(--theme-bg-tertiary) 100% | |
| ); | |
| background-size: cover; | |
| background-position: center; | |
| background-attachment: fixed; /* keeps image in place */ | |
| color: var(--theme-text-primary); | |
| } | |
| .header { | |
| background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%); | |
| border-bottom: 2px solid var(--theme-primary); | |
| box-shadow: 0 4px 20px rgba(0, 188, 212, 0.3); | |
| } | |
| /* Apply theme colors to all buttons, inputs, and interactive elements */ | |
| .search-btn, .theme-btn, .view-profile-btn, .show-all-btn { | |
| background: linear-gradient(135deg, var(--theme-primary) 0%, var(--theme-secondary) 100%); | |
| border: 1px solid var(--theme-primary); | |
| color: var(--theme-bg-primary); | |
| } | |
| .search-btn:hover, .theme-btn:hover, .view-profile-btn:hover, .show-all-btn:hover { | |
| background: var(--theme-secondary); | |
| box-shadow: 0 4px 15px rgba(var(--theme-primary), 0.4); | |
| } | |
| .search-input { | |
| background: var(--theme-bg-secondary); | |
| border: 2px solid var(--theme-primary); | |
| color: var(--theme-text-primary); | |
| } | |
| .search-input:focus { | |
| border-color: var(--theme-secondary); | |
| box-shadow: 0 0 10px rgba(var(--theme-primary), 0.3); | |
| } | |
| /* Apply theme to all cards and containers */ | |
| .user-card, .nft-card, .group-card, .stats-section { | |
| background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%); | |
| border: 1px solid var(--theme-primary); | |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); | |
| } | |
| .stats-item { | |
| background: var(--theme-bg-tertiary); | |
| border: 1px solid var(--theme-primary); | |
| } | |
| .stats-item .label { | |
| color: var(--theme-secondary); | |
| } | |
| .stats-item .value { | |
| color: var(--theme-primary); | |
| } | |
| /* Enhanced floating widget with smaller collapsed state */ | |
| .floating-user-widget { | |
| position: fixed; | |
| bottom: 15px; | |
| right: 15px; | |
| width: 200px; | |
| background: rgba(255, 255, 255, 0.06); /* even more transparent */ | |
| border: 1px solid rgba(255, 255, 255, 0.15); | |
| border-radius: 8px; | |
| padding: 2px 6px; /* minimal padding */ | |
| font-size: 11px; /* smaller text */ | |
| line-height: 1; /* very tight line spacing */ | |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); | |
| z-index: 1000; | |
| transition: all 0.3s ease; | |
| backdrop-filter: blur(4px); | |
| } | |
| .floating-user-widget.collapsed { | |
| height: 20px; /* smaller */ | |
| width: 70px; /* smaller */ | |
| padding: 2px 4px; | |
| font-size: 10px; /* tiny text */ | |
| overflow: hidden; | |
| opacity: 0.8; /* slightly see-through when collapsed */ | |
| } | |
| .widget-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 10px; | |
| cursor: pointer; | |
| } | |
| .widget-title { | |
| font-weight: bold; | |
| color: var(--theme-primary); | |
| font-size: 0.9rem; | |
| } | |
| .collapse-btn { | |
| background: none; | |
| border: none; | |
| color: var(--theme-primary); | |
| font-size: 1.2rem; | |
| cursor: pointer; | |
| transition: transform 0.3s ease; | |
| } | |
| .collapse-btn.collapsed { | |
| transform: rotate(180deg); | |
| } | |
| .widget-content { | |
| transition: opacity 0.3s ease; | |
| } | |
| .floating-user-widget.collapsed .widget-content { | |
| opacity: 0; | |
| height: 0; | |
| overflow: hidden; | |
| } | |
| /* Enhanced widget styling with theme colors */ | |
| .widget-user-info { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| margin-bottom: 10px; | |
| } | |
| .widget-avatar { | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 50%; | |
| border: 2px solid var(--theme-primary); | |
| } | |
| .widget-user-details h4 { | |
| color: var(--theme-text-primary); | |
| margin: 0; | |
| font-size: 0.9rem; | |
| } | |
| .widget-user-details p { | |
| color: var(--theme-secondary); | |
| margin: 0; | |
| font-size: 0.8rem; | |
| } | |
| .widget-rank { | |
| background: rgba(var(--theme-primary-rgb), 0.1); | |
| border: 1px solid var(--theme-primary); | |
| text-align: center; | |
| padding: 8px; | |
| border-radius: 6px; | |
| border: 1px solid var(--theme-primary); | |
| } | |
| .rank-title { | |
| font-size: 0.7rem; | |
| color: var(--theme-secondary); | |
| margin-bottom: 4px; | |
| } | |
| .rank-value { | |
| font-weight: bold; | |
| color: var(--theme-primary); | |
| font-size: 0.9rem; | |
| } | |
| /* Enhanced loading animations with theme colors */ | |
| .loading-enhanced { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 15px; | |
| padding: 40px 20px; | |
| color: var(--theme-text-secondary); | |
| } | |
| .loading-pulse { | |
| width: 60px; | |
| height: 60px; | |
| border: 3px solid var(--theme-primary); | |
| border-radius: 50%; | |
| position: relative; | |
| animation: pulse 2s infinite; | |
| } | |
| .loading-pulse::before { | |
| content: ''; | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| width: 30px; | |
| height: 30px; | |
| background: var(--theme-primary); | |
| border-radius: 50%; | |
| animation: innerPulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0%, 100% { transform: scale(1); opacity: 1; } | |
| 50% { transform: scale(1.1); opacity: 0.7; } | |
| } | |
| @keyframes innerPulse { | |
| 0%, 100% { transform: translate(-50%, -50%) scale(1); } | |
| 50% { transform: translate(-50%, -50%) scale(0.8); } | |
| } | |
| .loading-text { | |
| font-size: 1.1rem; | |
| font-weight: bold; | |
| text-align: center; | |
| color: var(--theme-primary); | |
| } | |
| .loading-subtext { | |
| font-size: 0.9rem; | |
| opacity: 0.8; | |
| text-align: center; | |
| color: var(--theme-secondary); | |
| } | |
| /* Enhanced NFT and group card styles with theme colors */ | |
| .nft-card, .group-card { | |
| position: relative; | |
| overflow: hidden; | |
| transition: all 0.3s ease; | |
| } | |
| .nft-card:hover, .group-card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 8px 25px rgba(var(--theme-primary), 0.3); | |
| } | |
| .nft-card::before, .group-card::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 3px; | |
| background: linear-gradient(90deg, var(--theme-primary), var(--theme-secondary)); | |
| } | |
| /* Apply theme to all text elements */ | |
| h1, h2, h3, h4, h5, h6 { | |
| color: var(--theme-primary); | |
| } | |
| p, span, div { | |
| color: var(--theme-text-primary); | |
| } | |
| .error { | |
| color: #ff6b6b; | |
| background: rgba(255, 107, 107, 0.1); | |
| border: 1px solid #ff6b6b; | |
| padding: 10px; | |
| border-radius: 6px; | |
| } | |
| /* Theme loading indicator */ | |
| .theme-loading { | |
| position: fixed; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| background: var(--theme-bg-secondary); | |
| border: 2px solid var(--theme-primary); | |
| border-radius: 12px; | |
| padding: 20px; | |
| z-index: 9999; | |
| display: none; | |
| } | |
| /* Added floating user widget styles */ | |
| .floating-user-widget { | |
| position: fixed; | |
| bottom: 20px; | |
| right: 20px; | |
| width: 300px; | |
| background: linear-gradient(135deg, var(--theme-bg-secondary) 0%, var(--theme-bg-tertiary) 100%); | |
| border: 2px solid var(--theme-primary); | |
| border-radius: 12px; | |
| padding: 15px; | |
| box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4); | |
| z-index: 1000; | |
| transition: all 0.3s ease; | |
| backdrop-filter: blur(10px); | |
| } | |
| .floating-user-widget.collapsed { | |
| height: 60px; | |
| overflow: hidden; | |
| } | |
| .widget-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 10px; | |
| cursor: pointer; | |
| } | |
| .widget-title { | |
| font-weight: bold; | |
| color: var(--theme-primary); | |
| font-size: 0.9rem; | |
| } | |
| .collapse-btn { | |
| background: none; | |
| border: none; | |
| color: var(--theme-primary); | |
| font-size: 1.2rem; | |
| cursor: pointer; | |
| transition: transform 0.3s ease; | |
| } | |
| .collapse-btn.collapsed { | |
| transform: rotate(180deg); | |
| } | |
| .widget-content { | |
| transition: opacity 0.3s ease; | |
| } | |
| .floating-user-widget.collapsed .widget-content { | |
| opacity: 0; | |
| } | |
| .widget-user-info { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| margin-bottom: 10px; | |
| } | |
| .widget-avatar { | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 50%; | |
| border: 2px solid var(--theme-primary); | |
| } | |
| .widget-user-details h4 { | |
| margin: 0; | |
| color: var(--theme-text-primary); | |
| font-size: 0.9rem; | |
| } | |
| .widget-user-details p { | |
| margin: 2px 0; | |
| color: var(--theme-text-secondary); | |
| font-size: 0.8rem; | |
| } | |
| .widget-rank { | |
| background: rgba(0, 188, 212, 0.1); | |
| border: 1px solid var(--theme-primary); | |
| border-radius: 6px; | |
| padding: 8px; | |
| text-align: center; | |
| margin-bottom: 10px; | |
| } | |
| .rank-title { | |
| font-size: 0.8rem; | |
| color: var(--theme-text-secondary); | |
| margin-bottom: 4px; | |
| } | |
| .rank-value { | |
| font-size: 1rem; | |
| font-weight: bold; | |
| color: var(--theme-primary); | |
| } | |
| /* Added theme selector styles to sidebar */ | |
| .theme-selector { | |
| background: linear-gradient(135deg, var(--theme-bg-tertiary) 0%, var(--theme-bg-secondary) 100%); | |
| border: 1px solid var(--theme-primary); | |
| border-radius: 10px; | |
| padding: 15px; | |
| margin-bottom: 15px; | |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); | |
| } | |
| .theme-selector h3 { | |
| font-size: 1rem; | |
| color: var(--theme-primary); | |
| margin-bottom: 12px; | |
| display: flex; | |
| align-items: center; | |
| gap: 6px; | |
| } | |
| .theme-buttons { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 8px; | |
| } | |
| .theme-btn { | |
| padding: 8px 12px; | |
| border: 2px solid transparent; | |
| border-radius: 6px; | |
| cursor: pointer; | |
| font-weight: bold; | |
| font-size: 0.8rem; | |
| transition: all 0.3s ease; | |
| text-align: center; | |
| } | |
| .theme-btn.current { | |
| border-color: var(--theme-primary); | |
| box-shadow: 0 0 10px rgba(0, 188, 212, 0.4); | |
| } | |
| .theme-btn:hover { | |
| transform: translateY(-1px); | |
| } | |
| .theme-btn.default { | |
| background: linear-gradient(45deg, #00bcd4, #87ceeb); | |
| color: #0a0a0a; | |
| } | |
| .theme-btn.red { | |
| background: linear-gradient(45deg, #ff4444, #ff6b6b); | |
| color: white; | |
| } | |
| .theme-btn.black { | |
| background: linear-gradient(45deg, #333, #666); | |
| color: white; | |
| } | |
| .theme-btn.yellow { | |
| background: linear-gradient(45deg, #ffd700, #ffeb3b); | |
| color: #000; | |
| } | |
| /* Enhanced loading animations */ | |
| .loading-enhanced { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 15px; | |
| padding: 40px 20px; | |
| color: var(--theme-text-secondary); | |
| } | |
| /* Spinner Loader */ | |
| .loading-spinner { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| padding: 40px 0; | |
| } | |
| .spinner { | |
| width: 50px; | |
| height: 50px; | |
| border: 6px solid rgba(255, 255, 255, 0.2); | |
| border-top-color: var(--theme-primary, #00bcd4); | |
| border-radius: 50%; | |
| animation: spin 1s linear infinite; | |
| margin-bottom: 15px; | |
| } | |
| .loading-text { | |
| font-size: 1rem; | |
| color: var(--theme-text-primary, #ffffff); | |
| text-align: center; | |
| font-weight: 600; | |
| } | |
| @keyframes spin { | |
| to { transform: rotate(360deg); } | |
| } | |
| .loading-pulse { | |
| width: 60px; | |
| height: 60px; | |
| border: 3px solid var(--theme-primary); | |
| border-radius: 50%; | |
| position: relative; | |
| animation: pulse 2s infinite; | |
| } | |
| .loading-pulse::before { | |
| content: ''; | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| width: 30px; | |
| height: 30px; | |
| background: var(--theme-primary); | |
| border-radius: 50%; | |
| animation: innerPulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0%, 100% { transform: scale(1); opacity: 1; } | |
| 50% { transform: scale(1.1); opacity: 0.7; } | |
| } | |
| @keyframes innerPulse { | |
| 0%, 100% { transform: translate(-50%, -50%) scale(1); } | |
| 50% { transform: translate(-50%, -50%) scale(0.8); } | |
| } | |
| .loading-text { | |
| font-size: 1.1rem; | |
| font-weight: bold; | |
| text-align: center; | |
| } | |
| .loading-subtext { | |
| font-size: 0.9rem; | |
| opacity: 0.8; | |
| text-align: center; | |
| } | |
| /* Enhanced NFT card styles */ | |
| .nft-card { | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .nft-card::before { | |
| content: ''; | |
| position: absolute; | |
| top: -2px; | |
| left: -2px; | |
| right: -2px; | |
| bottom: -2px; | |
| background: linear-gradient(45deg, transparent, var(--theme-primary), transparent); | |
| border-radius: 12px; | |
| z-index: -1; | |
| opacity: 0; | |
| transition: opacity 0.3s ease; | |
| } | |
| .nft-card:hover::before { | |
| opacity: 0.3; | |
| } | |
| .nft-card.legendary::before { | |
| background: linear-gradient(45deg, #ffd700, #ffeb3b, #ff6f00, #ffd700); | |
| background-size: 400% 400%; | |
| animation: legendaryGlow 2s ease-in-out infinite; | |
| opacity: 0.6; | |
| } | |
| /* Mobile responsive updates for floating widget */ | |
| @media (max-width: 768px) { | |
| .floating-user-widget { | |
| width: calc(100vw - 40px); | |
| right: 20px; | |
| left: 20px; | |
| bottom: 10px; | |
| } | |
| } | |
| </style> | |
| <div class="theme-loading" id="theme-loading"> | |
| <div class="loading-enhanced"> | |
| <div class="loading-pulse"></div> | |
| <div class="loading-text">Loading Theme</div> | |
| <div class="loading-subtext">Fetching your preferred style...</div> | |
| </div> | |
| </div> | |
| </head> | |
| <body> | |
| <div class="header"> | |
| <div class="page-title">FINRAL - PROFILE</div> | |
| <div class="creator">Owner : Saul | Reiker</div> | |
| <div class="page-subtitle">"t.me/finralxbot"</div> | |
| </div> | |
| <button class="sidebar-toggle" id="sidebarToggle">🔍</button> | |
| <div class="main-layout"> | |
| <div class="sidebar" id="sidebar"> | |
| <!-- Search section first --> | |
| <div class="search-section"> | |
| <h3>🔍 Search User</h3> | |
| <input type="text" id="searchInput" class="search-input" placeholder="Enter Chat/User ID"> | |
| <button id="searchBtn" class="search-btn"> | |
| <span class="btn-text">Search User</span> | |
| <div class="loading-dots" style="display: none;"> | |
| <div class="loading-dot"></div> | |
| <div class="loading-dot"></div> | |
| <div class="loading-dot"></div> | |
| </div> | |
| </button> | |
| <div id="searchResult" class="search-result" style="display:none;"></div> | |
| </div> | |
| <!-- Theme selector below search --> | |
| <div class="theme-selector"> | |
| <h3>🎨 Theme</h3> | |
| <div class="theme-buttons"> | |
| <button class="theme-btn default current" onclick="changeTheme('default')">Default</button> | |
| <button class="theme-btn red" onclick="changeTheme('red')">Red</button> | |
| <button class="theme-btn black" onclick="changeTheme('black')">Black</button> | |
| <button class="theme-btn yellow" onclick="changeTheme('yellow')">Yellow</button> | |
| <button class="theme-btn green" onclick="changeTheme('green')">Green</button> | |
| <button class="theme-btn pink" onclick="changeTheme('pink')">Pink</button> | |
| <button class="theme-btn purple" onclick="changeTheme('purple')">Purple</button> | |
| <button class="theme-btn brown" onclick="changeTheme('brown')">Brown</button> | |
| <button class="theme-btn cyan" onclick="changeTheme('cyan')">Cyan</button> | |
| <button class="theme-btn coral" onclick="changeTheme('coral')">Coral</button> | |
| <button class="theme-btn magenta" onclick="changeTheme('magenta')">Magenta</button> | |
| <button class="theme-btn violet" onclick="changeTheme('violet')">Violet</button> | |
| <button class="theme-btn teal" onclick="changeTheme('teal')">Teal</button> | |
| <button class="theme-btn orange" onclick="changeTheme('orange')">Orange</button> | |
| <button class="theme-btn olive" onclick="changeTheme('olive')">Olive</button> | |
| <button class="theme-btn white" onclick="changeTheme('white')">White</button> | |
| <button class="theme-btn splash" onclick="changeTheme('splash')">Splash</button> | |
| <button class="theme-btn gold" onclick="changeTheme('gold')">Gold</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="content"> | |
| <div class="top-section"> | |
| <div class="banner-profile-container" id="bannerContainer" style="display:none;"> | |
| <img id="banner" src="/placeholder.svg" alt="User Banner"> | |
| <div class="banner-overlay"></div> | |
| <div class="profile-glow"></div> | |
| <img id="pfp" src="/placeholder.svg" alt="Profile Picture"> | |
| </div> | |
| <div class="user-info-card"> | |
| <div class="welcome-title" id="welcomeTitle">Welcome to Finral</div> | |
| <!-- Added user name display --> | |
| <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> | |
| <div id="chatId" class="chat-id"> | |
| <div class="loading"> | |
| <div class="loading-spinner"></div> | |
| Loading... | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="stats-grid" id="statsGrid" style="display:none;"> | |
| <div class="stats-section"> | |
| <h3>🎀 Basic Stats</h3> | |
| <div class="basic-stats-grid"> | |
| <div class="stat-item"> | |
| <strong>Level</strong> | |
| <div class="stat-value" id="totalLevel">-</div> | |
| </div> | |
| <div class="stat-item"> | |
| <strong>Total XP</strong> | |
| <div class="stat-value" id="totalXP">-</div> | |
| </div> | |
| <div class="stat-item"> | |
| <strong>Royalties</strong> | |
| <div class="stat-value" id="totalRoyalties">-</div> | |
| </div> | |
| <div class="stat-item"> | |
| <strong>Daily Msgs</strong> | |
| <div class="stat-value" id="totalDailyMessages">-</div> | |
| </div> | |
| <div class="stat-item"> | |
| <strong>Full Name</strong> | |
| <div class="stat-value" id="fullName">-</div> | |
| </div> | |
| <div class="stat-item"> | |
| <strong>Username</strong> | |
| <div class="stat-value" id="username">-</div> | |
| </div> | |
| <div class="stat-item"> | |
| <strong>Groups</strong> | |
| <div class="stat-value" id="groupCount">-</div> | |
| </div> | |
| <div class="stat-item"> | |
| <strong>Status</strong> | |
| <div class="stat-value">Active</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Enhanced loading for NFT section --> | |
| <div class="nfts-section" id="nftsSection" style="display:none;"> | |
| <h3>🎨 NFT Collection</h3> | |
| <div class="nft-stats" id="nftStats" style="display:none;"> | |
| <div> | |
| <div class="nft-stat"> | |
| <span class="nft-stat-value" id="totalNfts">0</span> | |
| <span class="nft-stat-label">Total NFTs</span> | |
| </div> | |
| <div class="nft-stat"> | |
| <span class="nft-stat-value" id="avgQuality">0</span> | |
| <span class="nft-stat-label">Avg Quality</span> | |
| </div> | |
| </div> | |
| <div> | |
| <div class="nft-stat"> | |
| <span class="nft-stat-value" id="rarestHolders">0</span> | |
| <span class="nft-stat-label">Rarest (Holders)</span> | |
| </div> | |
| <div class="nft-stat"> | |
| <span class="nft-stat-value" id="highestQuality">0</span> | |
| <span class="nft-stat-label">Highest Quality</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Spinner Loader --> | |
| <div id="nftsContainer"> | |
| <div class="loading-spinner"> | |
| <div class="spinner"></div> | |
| <div class="loading-text">Loading NFT Collection</div> | |
| </div> | |
| </div> | |
| <button id="showAllNftsBtn" class="show-all-btn" style="display:none;"> | |
| Show All NFTs (<span id="remainingCount">0</span> more) | |
| </button> | |
| </div> | |
| <!-- Enhanced loading for groups section --> | |
| <div class="stats-section" id="groupsSection" style="display:none;"> | |
| <h3>👥 Group Memberships</h3> | |
| <div class="groups-container" id="groupsContainer"> | |
| <div class="loading-enhanced"> | |
| <div class="loading-pulse"></div> | |
| <div class="loading-text">Loading Group Data</div> | |
| <div class="loading-subtext">Gathering your community connections...</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Added floating user widget --> | |
| <div class="floating-user-widget" id="floatingWidget" style="display:none;"> | |
| <div class="widget-header" onclick="toggleWidget()"> | |
| <div class="widget-title">User Info</div> | |
| <button class="collapse-btn" id="collapseBtn">▼</button> | |
| </div> | |
| <div class="widget-content"> | |
| <div class="widget-user-info"> | |
| <img id="widgetAvatar" class="widget-avatar" src="/placeholder.svg" alt="Avatar"> | |
| <div class="widget-user-details"> | |
| <h4 id="widgetName">Loading...</h4> | |
| <p id="widgetId">ID: Loading...</p> | |
| </div> | |
| </div> | |
| <div class="widget-rank"> | |
| <div class="rank-title">Global Rank</div> | |
| <div class="rank-value" id="widgetRank">🥉 Bronze</div> | |
| </div> | |
| </div> | |
| </div> | |
| <script src="utils/xp-calculations.js"></script> | |
| <script> | |
| async function loadUserTheme() { | |
| const themeLoadingIndicator = document.getElementById('theme-loading'); | |
| if (themeLoadingIndicator) { | |
| themeLoadingIndicator.style.display = 'block'; | |
| } | |
| try { | |
| // ✅ Figure out userId dynamically | |
| let userId; | |
| const initData = Telegram.WebApp.initDataUnsafe; | |
| const startParam = initData.start_param; | |
| if (startParam) { | |
| userId = startParam; // viewing someone else | |
| } else if (initData.user && initData.user.id) { | |
| userId = initData.user.id; // current user | |
| } else { | |
| console.error("❌ Unable to fetch userId"); | |
| return; | |
| } | |
| // ✅ Use the dynamic userId in API call | |
| const response = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/theme`); | |
| const data = await response.json(); | |
| if (data.status && data.theme) { | |
| console.log('[v0] Theme loaded from API:', data.theme); | |
| changeTheme(data.theme); | |
| return; | |
| } | |
| } catch (error) { | |
| console.log('[v0] API theme fetch failed, using default:', error); | |
| changeTheme('default'); | |
| } finally { | |
| if (themeLoadingIndicator) { | |
| themeLoadingIndicator.remove(); | |
| } | |
| } | |
| } | |
| // ✅ Run after DOM is ready | |
| window.addEventListener('DOMContentLoaded', loadUserTheme); | |
| </script> | |
| <script> | |
| // Sidebar toggle functionality | |
| const sidebarToggle = document.getElementById('sidebarToggle'); | |
| const sidebar = document.getElementById('sidebar'); | |
| sidebarToggle.addEventListener('click', () => { | |
| sidebar.classList.toggle('open'); | |
| sidebarToggle.textContent = sidebar.classList.contains('open') ? '✕' : '🔍'; | |
| }); | |
| // Close sidebar when clicking outside on mobile | |
| document.addEventListener('click', (e) => { | |
| if (window.innerWidth <= 768 && | |
| !sidebar.contains(e.target) && | |
| !sidebarToggle.contains(e.target) && | |
| sidebar.classList.contains('open')) { | |
| sidebar.classList.remove('open'); | |
| sidebarToggle.textContent = '🔍'; | |
| } | |
| }); | |
| // Function to search user by chat ID | |
| async function searchUser(chatId) { | |
| const searchBtn = document.getElementById('searchBtn'); | |
| const searchResult = document.getElementById('searchResult'); | |
| const btnText = searchBtn.querySelector('.btn-text'); | |
| const loadingDots = searchBtn.querySelector('.loading-dots'); | |
| searchBtn.disabled = true; | |
| btnText.style.display = 'none'; | |
| loadingDots.style.display = 'flex'; | |
| searchResult.style.display = 'none'; | |
| try { | |
| const response = await fetch(`https://reaperxxxx-testldb.hf.space/user/${chatId}/info`); | |
| const data = await response.json(); | |
| if (data.status && data.groups && data.groups.length > 0) { | |
| const userInfo = data.groups[0]; | |
| searchResult.innerHTML = ` | |
| <p><strong>✅ Found User:</strong></p> | |
| <p><strong>Name:</strong> ${userInfo.fullName || 'N/A'}</p> | |
| <p><strong>Username:</strong> ${userInfo.username || 'N/A'}</p> | |
| <p><strong>ID:</strong> ${chatId}</p> | |
| <button class="view-profile-btn" onclick="window.open('https://t.me/finralxbot/info?startapp=${chatId}', '_blank')"> | |
| View Full Profile | |
| </button> | |
| `; | |
| searchResult.style.display = 'block'; | |
| } else { | |
| searchResult.innerHTML = '<p class="error">❌ User not found or no data available.</p>'; | |
| searchResult.style.display = 'block'; | |
| } | |
| } catch (error) { | |
| searchResult.innerHTML = '<p class="error">⚠️ Error searching for user. Please try again.</p>'; | |
| searchResult.style.display = 'block'; | |
| } | |
| searchBtn.disabled = false; | |
| btnText.style.display = 'block'; | |
| loadingDots.style.display = 'none'; | |
| } | |
| function changeTheme(theme) { | |
| const body = document.body; | |
| body.className = body.className.replace(/theme-\w+/g, ''); | |
| if (theme !== 'default') { | |
| body.classList.add(`theme-${theme}`); | |
| } | |
| // Update active theme button | |
| document.querySelectorAll('.theme-btn').forEach(btn => { | |
| btn.classList.remove('current'); | |
| }); | |
| document.querySelector(`.theme-btn.${theme}`).classList.add('current'); | |
| // Save theme preference | |
| localStorage.setItem('selectedTheme', theme); | |
| } | |
| function toggleWidget() { | |
| const widget = document.getElementById('floatingWidget'); | |
| const btn = document.getElementById('collapseBtn'); | |
| widget.classList.toggle('collapsed'); | |
| btn.classList.toggle('collapsed'); | |
| btn.textContent = widget.classList.contains('collapsed') ? '▲' : '▼'; | |
| } | |
| function updateGlobalRank(totalLevel) { | |
| const rank = getGlobalRank(totalLevel); | |
| const widgetRank = document.getElementById('widgetRank'); | |
| if (widgetRank) { | |
| widgetRank.textContent = `${rank.emoji} ${rank.rank}`; | |
| } | |
| } | |
| window.addEventListener('DOMContentLoaded', async () => { | |
| const savedTheme = localStorage.getItem('xselectedTheme') || 'default'; | |
| changeTheme(savedTheme); | |
| // Set up search functionality | |
| const searchBtn = document.getElementById('searchBtn'); | |
| const searchInput = document.getElementById('searchInput'); | |
| searchBtn.addEventListener('click', () => { | |
| const chatId = searchInput.value.trim(); | |
| if (chatId) { | |
| searchUser(chatId); | |
| } | |
| }); | |
| searchInput.addEventListener('keypress', (e) => { | |
| if (e.key === 'Enter') { | |
| const chatId = searchInput.value.trim(); | |
| if (chatId) { | |
| searchUser(chatId); | |
| } | |
| } | |
| }); | |
| // Get userId from Telegram WebApp start parameter or current user | |
| let userId; | |
| let isViewingOther = false; | |
| const initData = Telegram.WebApp.initDataUnsafe; | |
| const startParam = initData.start_param; | |
| if (startParam) { | |
| userId = startParam; | |
| isViewingOther = true; | |
| document.getElementById('welcomeTitle').textContent = `Viewing Profile`; | |
| } else { | |
| const user = initData.user; | |
| if (user && user.id) { | |
| userId = user.id; | |
| document.getElementById('welcomeTitle').textContent = `Welcome to Finral`; | |
| } else { | |
| document.getElementById('chatId').innerHTML = '<div class="error">❌ Unable to fetch chat ID</div>'; | |
| return; | |
| } | |
| } | |
| document.getElementById('chatId').textContent = userId; | |
| try { | |
| // Fetch user banner with fallback | |
| try { | |
| const bannerRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/banner`); | |
| const bannerData = await bannerRes.json(); | |
| const bannerEl = document.getElementById('banner'); | |
| if (bannerData.status && bannerData.catboxUrl) { | |
| bannerEl.src = bannerData.catboxUrl; | |
| } else { | |
| bannerEl.src = 'https://files.catbox.moe/pdt55w.jpg'; | |
| } | |
| document.getElementById('bannerContainer').style.display = 'block'; | |
| } catch (err) { | |
| const bannerEl = document.getElementById('banner'); | |
| bannerEl.src = 'https://files.catbox.moe/pdt55w.jpg'; | |
| document.getElementById('bannerContainer').style.display = 'block'; | |
| } | |
| // Fetch user PFP | |
| const pfpRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/pfp`); | |
| const pfpData = await pfpRes.json(); | |
| const imgEl = document.getElementById('pfp'); | |
| if (pfpData.status && pfpData.catboxUrl) { | |
| imgEl.src = pfpData.catboxUrl; | |
| } else { | |
| imgEl.src = 'https://uploadnx.zone.id/w63l4b.jpeg'; | |
| } | |
| // Fetch user info | |
| const infoRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/info`); | |
| const infoData = await infoRes.json(); | |
| if (infoData.status) { | |
| const userInfo = infoData.groups[0] || {}; | |
| const fullName = userInfo.fullName || 'N/A'; | |
| const username = userInfo.username || 'N/A'; | |
| const iconURL = (await (async () => { try { const res = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/mark`); const data = await res.json(); return data.status && data.url ? data.url : 'https://files.catbox.moe/t8x1r8.png'; } catch { return 'https://files.catbox.moe/t8x1r8.png'; } })()); | |
| // iconURL is already set above | |
| if (fullName !== 'N/A') { | |
| const userNameEl = document.getElementById('userName'); | |
| userNameEl.innerHTML = ''; // clear previous content | |
| // Create username text first | |
| const nameText = document.createElement('span'); | |
| nameText.textContent = fullName; | |
| // Create image element | |
| const img = document.createElement('img'); | |
| img.src = iconURL; | |
| img.alt = 'icon'; | |
| img.className = 'username-icon'; | |
| img.style.width = '20px'; | |
| img.style.height = '20px'; | |
| img.style.objectFit = 'contain'; | |
| // Append username first, then image (so image is on the right) | |
| userNameEl.appendChild(nameText); | |
| userNameEl.appendChild(img); | |
| // Flex container to center content | |
| userNameEl.style.display = 'inline-flex'; | |
| userNameEl.style.alignItems = 'center'; | |
| userNameEl.style.justifyContent = 'center'; // center horizontally | |
| userNameEl.style.gap = '6px'; | |
| } | |
| // Update floating widget | |
| document.getElementById('widgetName').textContent = fullName; | |
| document.getElementById('widgetId').textContent = `ID: ${userId}`; | |
| document.getElementById('widgetAvatar').src = document.getElementById('pfp').src; | |
| updateGlobalRank(infoData.totalLevel); | |
| document.getElementById('floatingWidget').style.display = 'block'; | |
| // Display basic stats | |
| document.getElementById('fullName').textContent = fullName; | |
| document.getElementById('username').textContent = username; | |
| document.getElementById('totalXP').textContent = infoData.totalXP.toLocaleString(); | |
| document.getElementById('totalLevel').textContent = infoData.totalLevel; | |
| document.getElementById('totalRoyalties').textContent = infoData.totalRoyalties.toLocaleString(); | |
| document.getElementById('totalDailyMessages').textContent = infoData.totalDailyMessages; | |
| document.getElementById('groupCount').textContent = infoData.groups.length; | |
| // Show stats grid | |
| document.getElementById('statsGrid').style.display = 'grid'; | |
| // Group unique groups by groupId | |
| const uniqueGroups = {}; | |
| for (const group of infoData.groups) { | |
| const groupId = group.groupId || group.id; | |
| if (!uniqueGroups[groupId]) { | |
| uniqueGroups[groupId] = { | |
| groupId: groupId, | |
| fullName: group.fullName, | |
| username: group.username, | |
| totalLevel: 0, | |
| totalXP: 0, | |
| totalRoyalties: 0, | |
| totalDailyMessages: 0, | |
| entries: [] | |
| }; | |
| } | |
| uniqueGroups[groupId].totalLevel += group.level || 0; | |
| uniqueGroups[groupId].totalXP += group.xp || 0; | |
| uniqueGroups[groupId].totalRoyalties += group.royalties || 0; | |
| uniqueGroups[groupId].totalDailyMessages += group.dailyMessages || 0; | |
| uniqueGroups[groupId].entries.push({ | |
| level: group.level, | |
| xp: group.xp, | |
| royalties: group.royalties, | |
| dailyMessages: group.dailyMessages | |
| }); | |
| } | |
| document.getElementById('groupsContainer').innerHTML = ''; | |
| // Display group stats | |
| const groupsContainer = document.getElementById('groupsContainer'); | |
| for (const groupId in uniqueGroups) { | |
| const group = uniqueGroups[groupId]; | |
| let groupMeta = null; | |
| let metaError = null; | |
| try { | |
| const groupMetaRes = await fetch(`https://reaperxxxx-testldb.hf.space/group/${groupId}/meta`); | |
| if (groupMetaRes.ok) { | |
| groupMeta = await groupMetaRes.json(); | |
| } else { | |
| const errorText = await groupMetaRes.text(); | |
| metaError = `API Error: ${groupMetaRes.status}`; | |
| } | |
| } catch (err) { | |
| metaError = `Fetch Error: ${err.message}`; | |
| } | |
| const div = document.createElement('div'); | |
| div.className = 'group-box'; | |
| const displayName = (groupMeta && groupMeta.status && groupMeta.groupName) | |
| ? groupMeta.groupName | |
| : group.fullName || 'Unknown Group'; | |
| const groupPic = (groupMeta && groupMeta.status && groupMeta.groupPic) | |
| ? groupMeta.groupPic | |
| : null; | |
| const admins = (groupMeta && groupMeta.status && groupMeta.admins) | |
| ? groupMeta.admins | |
| : null; | |
| div.innerHTML = ` | |
| <div class="group-header"> | |
| ${groupPic ? `<img class="group-pic" src="${groupPic}" alt="Group Picture">` : `<div class="group-pic" style="background: linear-gradient(45deg, var(--theme-primary), var(--theme-secondary)); display: flex; align-items: center; justify-content: center; color: #0a0a0a; font-weight: bold;">👥</div>`} | |
| <div class="group-info"> | |
| <div class="group-name">${displayName}</div> | |
| <div class="group-id">ID: ${groupId}</div> | |
| </div> | |
| </div> | |
| <div class="group-stats"> | |
| <div class="group-stat-item"> | |
| <span class="group-stat-value">${group.totalLevel}</span> | |
| <span class="group-stat-label">Level</span> | |
| </div> | |
| <div class="group-stat-item"> | |
| <span class="group-stat-value">${group.totalXP.toLocaleString()}</span> | |
| <span class="group-stat-label">XP</span> | |
| </div> | |
| <div class="group-stat-item"> | |
| <span class="group-stat-value">${group.totalRoyalties.toLocaleString()}</span> | |
| <span class="group-stat-label">Royalties</span> | |
| </div> | |
| <div class="group-stat-item"> | |
| <span class="group-stat-value">${group.totalDailyMessages}</span> | |
| <span class="group-stat-label">Daily</span> | |
| </div> | |
| </div> | |
| ${metaError ? `<div class="error">⚠️ ${metaError}</div>` : ''} | |
| ${admins && admins.length > 0 ? ` | |
| <div class="group-admins"> | |
| <details> | |
| <summary>👑 Admins (${admins.length})</summary> | |
| <div class="admin-list"> | |
| ${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('')} | |
| ${admins.length > 5 ? `<span class="admin-tag">+${admins.length - 5} more</span>` : ''} | |
| </div> | |
| </details> | |
| </div>` : ''} | |
| `; | |
| groupsContainer.appendChild(div); | |
| } | |
| document.getElementById('groupsSection').style.display = 'block'; | |
| } | |
| const nftsContainer = document.getElementById('nftsContainer'); | |
| const showAllBtn = document.getElementById('showAllNftsBtn'); | |
| const remainingCount = document.getElementById('remainingCount'); | |
| const nftStats = document.getElementById('nftStats'); | |
| // Show loading spinner while fetching | |
| nftsContainer.innerHTML = ` | |
| <div class="nft-loader" id="nftLoading"> | |
| <div class="spinner"></div> | |
| </div> | |
| `; | |
| try { | |
| const nftsRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/nfts`); | |
| const nftsData = await nftsRes.json(); | |
| // Hide loading spinner | |
| const nftLoading = document.getElementById('nftLoading'); | |
| if (nftLoading) nftLoading.style.display = 'none'; | |
| if (nftsData.status && nftsData.nfts && nftsData.nfts.length > 0) { | |
| // Sort NFTs by holders (ascending) | |
| const sortedNfts = nftsData.nfts.sort((a, b) => a.holders - b.holders); | |
| // NFT stats | |
| const totalNfts = sortedNfts.length; | |
| const avgQuality = Math.round(sortedNfts.reduce((sum, nft) => sum + nft.nftquality, 0) / totalNfts); | |
| const rarestHolders = Math.min(...sortedNfts.map(nft => nft.holders)); | |
| const highestQuality = Math.max(...sortedNfts.map(nft => nft.nftquality)); | |
| document.getElementById('totalNfts').textContent = totalNfts; | |
| document.getElementById('avgQuality').textContent = avgQuality; | |
| document.getElementById('rarestHolders').textContent = rarestHolders; | |
| document.getElementById('highestQuality').textContent = highestQuality; | |
| nftStats.style.display = 'block'; | |
| function getQualityClass(quality) { | |
| if (quality >= 81) return 'legendary'; | |
| if (quality >= 61) return 'way-better'; | |
| if (quality >= 41) return 'even-better'; | |
| if (quality >= 21) return 'better'; | |
| return 'basic'; | |
| } | |
| function getQualityBadgeClass(quality) { | |
| if (quality >= 81) return 'quality-legendary'; | |
| if (quality >= 61) return 'quality-way-better'; | |
| if (quality >= 41) return 'quality-even-better'; | |
| if (quality >= 21) return 'quality-better'; | |
| return 'quality-basic'; | |
| } | |
| function getRarityClass(rarity) { | |
| const rarityLower = rarity.toLowerCase(); | |
| if (rarityLower.includes('mythic')) return 'rarity-mythic'; | |
| if (rarityLower.includes('legendary')) return 'rarity-legendary'; | |
| if (rarityLower.includes('epic')) return 'rarity-epic'; | |
| if (rarityLower.includes('rare')) return 'rarity-rare'; | |
| if (rarityLower.includes('uncommon')) return 'rarity-uncommon'; | |
| return 'rarity-common'; | |
| } | |
| function formatDateTime(dateString) { | |
| const date = new Date(dateString); | |
| return date.toLocaleString('en-US', { | |
| month: 'short', | |
| day: 'numeric', | |
| year: 'numeric', | |
| hour: '2-digit', | |
| minute: '2-digit' | |
| }); | |
| } | |
| function createNftCard(nft) { | |
| const qualityClass = getQualityClass(nft.nftquality); | |
| const qualityBadgeClass = getQualityBadgeClass(nft.nftquality); | |
| const rarityClass = getRarityClass(nft.rarity); | |
| const uniqueId = `details-${nft.nftid}`; | |
| return ` | |
| <div class="nft-card ${qualityClass}" style="animation: fadeInUp 0.6s ease forwards; opacity: 0;"> | |
| <div class="quality-badge ${qualityBadgeClass}">${nft.nftquality}</div> | |
| <img src="${nft.nftimage}" alt="${nft.name}" class="nft-image" loading="lazy"> | |
| <div class="nft-info"> | |
| <div class="nft-header"> | |
| <div class="nft-name" title="${nft.name}">${nft.name}</div> | |
| <div class="nft-id">#${nft.nftid}</div> | |
| </div> | |
| <div class="nft-rarity ${rarityClass}">${nft.rarity}</div> | |
| <button class="toggle-details" onclick="toggleDetails('${uniqueId}', this)">▼ Show Details</button> | |
| <div class="nft-details-wrapper" id="${uniqueId}" style="display: none;"> | |
| <div class="nft-details"> | |
| <div class="nft-detail"> | |
| <span class="nft-detail-label">Quality</span> | |
| <span class="nft-detail-value">${nft.nftquality}/100</span> | |
| </div> | |
| <div class="nft-detail"> | |
| <span class="nft-detail-label">Holders</span> | |
| <span class="nft-detail-value">${nft.holders}</span> | |
| </div> | |
| </div> | |
| <div class="nft-obtained"> | |
| <span class="nft-obtained-label">Obtained On</span> | |
| <span class="nft-obtained-value">${formatDateTime(nft.gotten_on)}</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| } | |
| // Show first 5 NFTs initially | |
| const initialNfts = sortedNfts.slice(0, 5); | |
| const remainingNfts = sortedNfts.slice(5); | |
| nftsContainer.innerHTML = ` | |
| <div class="nfts-grid"> | |
| ${initialNfts.map(nft => createNftCard(nft)).join('')} | |
| </div> | |
| `; | |
| if (remainingNfts.length > 0) { | |
| remainingCount.textContent = remainingNfts.length; | |
| showAllBtn.style.display = 'block'; | |
| let allShown = false; | |
| showAllBtn.addEventListener('click', () => { | |
| const nftsGrid = nftsContainer.querySelector('.nfts-grid'); | |
| if (!allShown) { | |
| nftsGrid.innerHTML += remainingNfts.map(nft => createNftCard(nft)).join(''); | |
| showAllBtn.textContent = 'Show Less'; | |
| allShown = true; | |
| } else { | |
| nftsGrid.innerHTML = initialNfts.map(nft => createNftCard(nft)).join(''); | |
| showAllBtn.innerHTML = `Show All NFTs (<span id="remainingCount">${remainingNfts.length}</span> more)`; | |
| allShown = false; | |
| } | |
| }); | |
| } | |
| setTimeout(() => { | |
| const nftCards = document.querySelectorAll('.nft-card'); | |
| nftCards.forEach((card, index) => { | |
| setTimeout(() => { card.style.opacity = '1'; }, index * 100); | |
| }); | |
| }, 100); | |
| document.getElementById('nftsSection').style.display = 'block'; | |
| } else { | |
| // No NFTs found | |
| nftsContainer.innerHTML = ` | |
| <div class="no-nfts"> | |
| <div class="no-nfts-icon">🎨</div> | |
| <h4>No NFTs Found</h4> | |
| <p>This user hasn't collected any NFTs yet.</p> | |
| <p>Start your digital art journey today!</p> | |
| </div> | |
| `; | |
| document.getElementById('nftsSection').style.display = 'block'; | |
| } | |
| } catch (err) { | |
| console.error('Error fetching NFTs:', err); | |
| nftsContainer.innerHTML = ` | |
| <div class="no-nfts"> | |
| <div class="no-nfts-icon">⚠️</div> | |
| <h4>Failed to Load NFTs</h4> | |
| <p>Unable to fetch NFT collection data.</p> | |
| <p>Please try again later.</p> | |
| </div> | |
| `; | |
| document.getElementById('nftsSection').style.display = 'block'; | |
| } | |
| } catch (err) { | |
| console.error('Error fetching user data:', err); | |
| document.getElementById('chatId').innerHTML = '<div class="error">❌ Failed to load user info</div>'; | |
| } | |
| }); | |
| function toggleDetails(id, button) { | |
| const details = document.getElementById(id); | |
| const isVisible = details.style.display === 'block'; | |
| details.style.display = isVisible ? 'none' : 'block'; | |
| button.textContent = isVisible ? '▼ Show Details' : '▲ Hide Details'; | |
| } | |
| </script> | |
| <!-- Added fadeInUp animation --> | |
| <style> | |
| @keyframes fadeInUp { | |
| from { | |
| opacity: 0; | |
| transform: translateY(30px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| </style> | |
| </body> | |
| </html> | |