amro-alasri commited on
Commit
2a0bf7e
·
verified ·
1 Parent(s): b7c9fcf

عن طريق ال react.js اريد بناء لعبة عن طريق ال blockchain

Browse files
Files changed (9) hide show
  1. README.md +8 -5
  2. components/client-logos.js +67 -0
  3. components/footer.js +175 -0
  4. components/navbar.js +161 -0
  5. game.html +29 -0
  6. game.js +161 -0
  7. index.html +263 -19
  8. script.js +154 -0
  9. style.css +132 -19
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Crypto Snap Quest
3
- emoji: 🏃
4
- colorFrom: indigo
5
- colorTo: pink
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: Crypto Snap Quest 🕹️
3
+ colorFrom: red
4
+ colorTo: red
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://huggingface.co/deepsite).
components/client-logos.js ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomClientLogos extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ :host {
7
+ display: block;
8
+ }
9
+
10
+ .logos-container {
11
+ display: flex;
12
+ justify-content: center;
13
+ align-items: center;
14
+ flex-wrap: wrap;
15
+ gap: 3rem;
16
+ }
17
+
18
+ .logo-item {
19
+ opacity: 0.6;
20
+ transition: opacity 0.3s ease;
21
+ filter: grayscale(100%);
22
+ }
23
+
24
+ .logo-item:hover {
25
+ opacity: 1;
26
+ filter: grayscale(0%);
27
+ }
28
+
29
+ .logo-item img {
30
+ height: 40px;
31
+ width: auto;
32
+ max-width: 150px;
33
+ object-fit: contain;
34
+ }
35
+
36
+ @media (max-width: 768px) {
37
+ .logos-container {
38
+ gap: 2rem;
39
+ }
40
+
41
+ .logo-item img {
42
+ height: 30px;
43
+ }
44
+ }
45
+ </style>
46
+ <div class="logos-container">
47
+ <div class="logo-item">
48
+ <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Wipro_Primary_Logo_Color_RGB.svg/1200px-Wipro_Primary_Logo_Color_RGB.svg.png" alt="Wipro">
49
+ </div>
50
+ <div class="logo-item">
51
+ <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/1200px-Google_%22G%22_Logo.svg.png" alt="Google">
52
+ </div>
53
+ <div class="logo-item">
54
+ <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Apple_logo_black.svg/1667px-Apple_logo_black.svg.png" alt="Apple">
55
+ </div>
56
+ <div class="logo-item">
57
+ <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/Amazon_logo.svg/2560px-Amazon_logo.svg.png" alt="Amazon">
58
+ </div>
59
+ <div class="logo-item">
60
+ <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/96/Microsoft_logo_%282012%29.svg/2560px-Microsoft_logo_%282012%29.svg.png" alt="Microsoft">
61
+ </div>
62
+ </div>
63
+ `;
64
+ }
65
+ }
66
+
67
+ customElements.define('custom-client-logos', CustomClientLogos);
components/footer.js ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomFooter extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ :host {
7
+ display: block;
8
+ background-color: #111827;
9
+ color: #d1d5db;
10
+ }
11
+
12
+ .footer-container {
13
+ max-width: 1440px;
14
+ margin: 0 auto;
15
+ padding: 4rem 2rem;
16
+ display: grid;
17
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
18
+ gap: 3rem;
19
+ }
20
+
21
+ .footer-logo {
22
+ font-size: 1.5rem;
23
+ font-weight: 700;
24
+ color: white;
25
+ margin-bottom: 1.5rem;
26
+ display: inline-block;
27
+ }
28
+
29
+ .footer-logo span {
30
+ color: #f59e0b;
31
+ }
32
+
33
+ .footer-about p {
34
+ margin-bottom: 1.5rem;
35
+ line-height: 1.6;
36
+ }
37
+
38
+ .social-links {
39
+ display: flex;
40
+ gap: 1rem;
41
+ }
42
+
43
+ .social-links a {
44
+ color: #d1d5db;
45
+ transition: color 0.3s ease;
46
+ }
47
+
48
+ .social-links a:hover {
49
+ color: #f59e0b;
50
+ }
51
+
52
+ .footer-links h3, .footer-contact h3 {
53
+ color: white;
54
+ font-size: 1.25rem;
55
+ margin-bottom: 1.5rem;
56
+ position: relative;
57
+ padding-bottom: 0.5rem;
58
+ }
59
+
60
+ .footer-links h3::after, .footer-contact h3::after {
61
+ content: '';
62
+ position: absolute;
63
+ bottom: 0;
64
+ left: 0;
65
+ width: 50px;
66
+ height: 2px;
67
+ background-color: #f59e0b;
68
+ }
69
+
70
+ .footer-links ul {
71
+ list-style: none;
72
+ }
73
+
74
+ .footer-links li {
75
+ margin-bottom: 0.75rem;
76
+ }
77
+
78
+ .footer-links a {
79
+ color: #d1d5db;
80
+ text-decoration: none;
81
+ transition: color 0.3s ease;
82
+ }
83
+
84
+ .footer-links a:hover {
85
+ color: #f59e0b;
86
+ }
87
+
88
+ .contact-info {
89
+ display: flex;
90
+ flex-direction: column;
91
+ gap: 1rem;
92
+ }
93
+
94
+ .contact-item {
95
+ display: flex;
96
+ align-items: flex-start;
97
+ gap: 0.75rem;
98
+ }
99
+
100
+ .contact-item i {
101
+ color: #f59e0b;
102
+ margin-top: 0.25rem;
103
+ }
104
+
105
+ .copyright {
106
+ text-align: center;
107
+ padding: 1.5rem;
108
+ border-top: 1px solid #374151;
109
+ font-size: 0.875rem;
110
+ }
111
+
112
+ @media (max-width: 768px) {
113
+ .footer-container {
114
+ grid-template-columns: 1fr;
115
+ }
116
+ }
117
+ </style>
118
+ <div class="footer-container">
119
+ <div class="footer-about">
120
+ <a href="/" class="footer-logo">Lens<span>Crafted</span></a>
121
+ <p>Professional photography services to capture your most precious moments with creativity and passion.</p>
122
+ <div class="social-links">
123
+ <a href="#"><i data-feather="instagram"></i></a>
124
+ <a href="#"><i data-feather="facebook"></i></a>
125
+ <a href="#"><i data-feather="twitter"></i></a>
126
+ <a href="#"><i data-feather="youtube"></i></a>
127
+ </div>
128
+ </div>
129
+ <div class="footer-links">
130
+ <h3>Quick Links</h3>
131
+ <ul>
132
+ <li><a href="#portfolio">Portfolio</a></li>
133
+ <li><a href="#about">About Me</a></li>
134
+ <li><a href="#services">Services</a></li>
135
+ <li><a href="#contact">Contact</a></li>
136
+ <li><a href="#">Blog</a></li>
137
+ </ul>
138
+ </div>
139
+ <div class="footer-contact">
140
+ <h3>Contact Info</h3>
141
+ <div class="contact-info">
142
+ <div class="contact-item">
143
+ <i data-feather="map-pin"></i>
144
+ <span>123 Photography Lane, Creative City, CC 90210</span>
145
+ </div>
146
+ <div class="contact-item">
147
+ <i data-feather="mail"></i>
148
+ <span>hello@lenscrafted.com</span>
149
+ </div>
150
+ <div class="contact-item">
151
+ <i data-feather="phone"></i>
152
+ <span>(555) 123-4567</span>
153
+ </div>
154
+ </div>
155
+ </div>
156
+ </div>
157
+ <div class="copyright">
158
+ &copy; ${new Date().getFullYear()} LensCrafted. All rights reserved.
159
+ </div>
160
+ `;
161
+
162
+ // Initialize Feather Icons within the shadow DOM
163
+ const featherScript = document.createElement('script');
164
+ featherScript.src = 'https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js';
165
+ this.shadowRoot.appendChild(featherScript);
166
+
167
+ featherScript.onload = () => {
168
+ const featherReplaceScript = document.createElement('script');
169
+ featherReplaceScript.textContent = 'feather.replace();';
170
+ this.shadowRoot.appendChild(featherReplaceScript);
171
+ };
172
+ }
173
+ }
174
+
175
+ customElements.define('custom-footer', CustomFooter);
components/navbar.js ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomNavbar extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ :host {
7
+ display: block;
8
+ position: fixed;
9
+ width: 100%;
10
+ top: 0;
11
+ left: 0;
12
+ z-index: 1000;
13
+ transition: all 0.3s ease;
14
+ }
15
+
16
+ .scrolled {
17
+ background-color: rgba(17, 24, 39, 0.95);
18
+ backdrop-filter: blur(10px);
19
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
20
+ }
21
+
22
+ nav {
23
+ max-width: 1440px;
24
+ margin: 0 auto;
25
+ padding: 1.5rem 2rem;
26
+ display: flex;
27
+ justify-content: space-between;
28
+ align-items: center;
29
+ }
30
+
31
+ .logo {
32
+ font-size: 1.5rem;
33
+ font-weight: 700;
34
+ color: white;
35
+ text-decoration: none;
36
+ display: flex;
37
+ align-items: center;
38
+ }
39
+
40
+ .logo span {
41
+ color: #f59e0b;
42
+ }
43
+
44
+ .nav-links {
45
+ display: flex;
46
+ gap: 2rem;
47
+ }
48
+
49
+ .nav-links a {
50
+ color: white;
51
+ text-decoration: none;
52
+ font-weight: 500;
53
+ transition: color 0.3s ease;
54
+ position: relative;
55
+ }
56
+
57
+ .nav-links a:hover {
58
+ color: #f59e0b;
59
+ }
60
+
61
+ .nav-links a::after {
62
+ content: '';
63
+ position: absolute;
64
+ bottom: -5px;
65
+ left: 0;
66
+ width: 0;
67
+ height: 2px;
68
+ background-color: #f59e0b;
69
+ transition: width 0.3s ease;
70
+ }
71
+
72
+ .nav-links a:hover::after {
73
+ width: 100%;
74
+ }
75
+
76
+ .mobile-menu-btn {
77
+ display: none;
78
+ background: none;
79
+ border: none;
80
+ color: white;
81
+ cursor: pointer;
82
+ }
83
+
84
+ @media (max-width: 768px) {
85
+ .nav-links {
86
+ position: fixed;
87
+ top: 80px;
88
+ left: 0;
89
+ width: 100%;
90
+ background-color: rgba(17, 24, 39, 0.98);
91
+ flex-direction: column;
92
+ align-items: center;
93
+ padding: 2rem 0;
94
+ gap: 1.5rem;
95
+ transform: translateY(-150%);
96
+ transition: transform 0.4s ease;
97
+ z-index: 999;
98
+ }
99
+
100
+ .nav-links.open {
101
+ transform: translateY(0);
102
+ }
103
+
104
+ .mobile-menu-btn {
105
+ display: block;
106
+ }
107
+ }
108
+ </style>
109
+ <nav>
110
+ <a href="/" class="logo">Lens<span>Crafted</span></a>
111
+ <div class="nav-links">
112
+ <a href="#portfolio">Portfolio</a>
113
+ <a href="#about">About</a>
114
+ <a href="#services">Services</a>
115
+ <a href="#contact">Contact</a>
116
+ <a href="game.html">Game</a>
117
+ </div>
118
+ <button class="mobile-menu-btn">
119
+ <i data-feather="menu"></i>
120
+ </button>
121
+ </nav>
122
+ `;
123
+
124
+ // Add scroll event listener for navbar effect
125
+ window.addEventListener('scroll', this.handleScroll.bind(this));
126
+
127
+ // Mobile menu toggle
128
+ const mobileMenuBtn = this.shadowRoot.querySelector('.mobile-menu-btn');
129
+ const navLinks = this.shadowRoot.querySelector('.nav-links');
130
+
131
+ mobileMenuBtn.addEventListener('click', () => {
132
+ navLinks.classList.toggle('open');
133
+ mobileMenuBtn.innerHTML = navLinks.classList.contains('open')
134
+ ? '<i data-feather="x"></i>'
135
+ : '<i data-feather="menu"></i>';
136
+ feather.replace();
137
+ });
138
+
139
+ // Close mobile menu when clicking a link
140
+ this.shadowRoot.querySelectorAll('.nav-links a').forEach(link => {
141
+ link.addEventListener('click', () => {
142
+ if (navLinks.classList.contains('open')) {
143
+ navLinks.classList.remove('open');
144
+ mobileMenuBtn.innerHTML = '<i data-feather="menu"></i>';
145
+ feather.replace();
146
+ }
147
+ });
148
+ });
149
+ }
150
+
151
+ handleScroll() {
152
+ const nav = this.shadowRoot.querySelector('nav');
153
+ if (window.scrollY > 50) {
154
+ nav.parentElement.classList.add('scrolled');
155
+ } else {
156
+ nav.parentElement.classList.remove('scrolled');
157
+ }
158
+ }
159
+ }
160
+
161
+ customElements.define('custom-navbar', CustomNavbar);
game.html ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Crypto Snap Quest - Blockchain Game</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
10
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
11
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
12
+ <script src="https://cdn.ethers.io/lib/ethers-5.2.umd.min.js"></script>
13
+ <script src="components/navbar.js"></script>
14
+ <script src="components/footer.js"></script>
15
+ </head>
16
+ <body class="bg-gray-900 text-white">
17
+ <custom-navbar></custom-navbar>
18
+
19
+ <main>
20
+ <div id="game-root" class="min-h-screen py-16 px-4 sm:px-6 lg:px-8"></div>
21
+ </main>
22
+
23
+ <custom-footer></custom-footer>
24
+
25
+ <!-- Game React Component -->
26
+ <script type="text/babel" src="game.js"></script>
27
+ <script src="script.js"></script>
28
+ </body>
29
+ </html>
game.js ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { useState, useEffect } = React;
2
+
3
+ function CryptoSnapGame() {
4
+ const [score, setScore] = useState(0);
5
+ const [isConnected, setIsConnected] = useState(false);
6
+ const [walletAddress, setWalletAddress] = useState('');
7
+ const [nfts, setNfts] = useState([]);
8
+ const [gameStarted, setGameStarted] = useState(false);
9
+ const [timeLeft, setTimeLeft] = useState(60);
10
+ const [targetNFT, setTargetNFT] = useState(null);
11
+ const [gameMessage, setGameMessage] = useState('');
12
+
13
+ // Connect to MetaMask
14
+ const connectWallet = async () => {
15
+ if (window.ethereum) {
16
+ try {
17
+ const provider = new ethers.providers.Web3Provider(window.ethereum);
18
+ const accounts = await provider.send("eth_requestAccounts", []);
19
+ setWalletAddress(accounts[0]);
20
+ setIsConnected(true);
21
+ fetchNFTs(accounts[0]);
22
+ } catch (error) {
23
+ console.error("Error connecting:", error);
24
+ setGameMessage("Failed to connect wallet");
25
+ }
26
+ } else {
27
+ setGameMessage("Please install MetaMask to play");
28
+ }
29
+ };
30
+
31
+ // Fetch user's NFTs (mock function)
32
+ const fetchNFTs = async (address) => {
33
+ // In a real app, you would query a blockchain API here
34
+ const mockNFTs = [
35
+ { id: 1, name: "Crypto Punk #1234", image: "http://static.photos/nft/200x200/1" },
36
+ { id: 2, name: "Bored Ape #5678", image: "http://static.photos/nft/200x200/2" },
37
+ { id: 3, name: "Art Blocks #9012", image: "http://static.photos/nft/200x200/3" }
38
+ ];
39
+ setNfts(mockNFTs);
40
+ };
41
+
42
+ // Start the game
43
+ const startGame = () => {
44
+ if (nfts.length === 0) {
45
+ setGameMessage("You need at least 1 NFT to play");
46
+ return;
47
+ }
48
+ setGameStarted(true);
49
+ setScore(0);
50
+ setTimeLeft(60);
51
+ setTargetNFT(nfts[Math.floor(Math.random() * nfts.length)]);
52
+ setGameMessage(`Find: ${targetNFT?.name}`);
53
+ };
54
+
55
+ // Handle NFT selection
56
+ const selectNFT = (nft) => {
57
+ if (!gameStarted) return;
58
+
59
+ if (nft.id === targetNFT.id) {
60
+ setScore(score + 10);
61
+ setGameMessage("Correct! +10 points");
62
+ setTargetNFT(nfts[Math.floor(Math.random() * nfts.length)]);
63
+ setTimeout(() => setGameMessage(`Find: ${targetNFT?.name}`), 1000);
64
+ } else {
65
+ setGameMessage("Wrong NFT! Try again");
66
+ }
67
+ };
68
+
69
+ // Game timer
70
+ useEffect(() => {
71
+ if (!gameStarted) return;
72
+
73
+ const timer = setInterval(() => {
74
+ setTimeLeft(prev => {
75
+ if (prev <= 1) {
76
+ clearInterval(timer);
77
+ setGameStarted(false);
78
+ setGameMessage(`Game Over! Final Score: ${score}`);
79
+ return 0;
80
+ }
81
+ return prev - 1;
82
+ });
83
+ }, 1000);
84
+
85
+ return () => clearInterval(timer);
86
+ }, [gameStarted, score]);
87
+
88
+ return (
89
+ <div className="max-w-4xl mx-auto text-center">
90
+ <h1 className="text-4xl md:text-5xl font-bold mb-8">Crypto Snap Quest</h1>
91
+
92
+ {!isConnected ? (
93
+ <div className="bg-gray-800 p-8 rounded-xl shadow-lg max-w-md mx-auto">
94
+ <h2 className="text-2xl font-bold mb-4">Connect Your Wallet</h2>
95
+ <p className="mb-6">Connect your MetaMask wallet to play and earn crypto rewards!</p>
96
+ <button
97
+ onClick={connectWallet}
98
+ className="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-6 rounded-lg transition"
99
+ >
100
+ Connect Wallet
101
+ </button>
102
+ </div>
103
+ ) : (
104
+ <div className="space-y-8">
105
+ <div className="bg-gray-800 p-6 rounded-xl shadow-lg">
106
+ <div className="flex justify-between items-center mb-4">
107
+ <div className="text-xl font-bold">Score: {score}</div>
108
+ <div className="text-xl font-bold">Time: {timeLeft}s</div>
109
+ </div>
110
+
111
+ <div className="bg-gray-700 p-4 rounded-lg mb-4 min-h-16 flex items-center justify-center">
112
+ {gameMessage || (gameStarted ? `Find: ${targetNFT?.name}` : "Ready to play?")}
113
+ </div>
114
+
115
+ {!gameStarted ? (
116
+ <button
117
+ onClick={startGame}
118
+ className="bg-green-600 hover:bg-green-700 text-white font-bold py-3 px-6 rounded-lg transition"
119
+ >
120
+ Start Game
121
+ </button>
122
+ ) : (
123
+ <p className="text-sm text-gray-400">Click on the matching NFT below</p>
124
+ )}
125
+ </div>
126
+
127
+ <div className="grid grid-cols-2 sm:grid-cols-3 gap-4">
128
+ {nfts.map(nft => (
129
+ <div
130
+ key={nft.id}
131
+ onClick={() => selectNFT(nft)}
132
+ className={`bg-gray-800 p-4 rounded-lg cursor-pointer transition ${gameStarted ? 'hover:bg-gray-700' : ''}`}
133
+ >
134
+ <img
135
+ src={nft.image}
136
+ alt={nft.name}
137
+ className="w-full h-32 object-cover rounded mb-2"
138
+ />
139
+ <p className="text-sm font-medium truncate">{nft.name}</p>
140
+ </div>
141
+ ))}
142
+ </div>
143
+ </div>
144
+ )}
145
+
146
+ <div className="mt-12 bg-gray-800 p-6 rounded-xl shadow-lg">
147
+ <h2 className="text-2xl font-bold mb-4">How to Play</h2>
148
+ <ul className="text-left max-w-md mx-auto space-y-2">
149
+ <li>1. Connect your crypto wallet</li>
150
+ <li>2. Start the game and find the matching NFT</li>
151
+ <li>3. Click the correct NFT to earn points</li>
152
+ <li>4. Score as much as you can in 60 seconds!</li>
153
+ </ul>
154
+ <p className="mt-4 text-blue-400">Coming Soon: Real crypto rewards for top scores!</p>
155
+ </div>
156
+ </div>
157
+ );
158
+ }
159
+
160
+ const root = ReactDOM.createRoot(document.getElementById('game-root'));
161
+ root.render(<CryptoSnapGame />);
index.html CHANGED
@@ -1,19 +1,263 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>LensCrafted | Professional Photography Portfolio</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <script src="components/navbar.js"></script>
12
+ <script src="components/footer.js"></script>
13
+ <script src="components/client-logos.js"></script>
14
+ </head>
15
+ <body class="bg-gray-50 text-gray-800 font-sans">
16
+ <custom-navbar></custom-navbar>
17
+
18
+ <main>
19
+ <!-- Hero Section -->
20
+ <section class="relative h-screen flex items-center justify-center bg-black overflow-hidden">
21
+ <div class="absolute inset-0 bg-black opacity-50"></div>
22
+ <video autoplay muted loop class="absolute min-w-full min-h-full object-cover">
23
+ <source src="https://static.videezy.com/system/resources/previews/000/050/246/original/4K_018.mp4" type="video/mp4">
24
+ </video>
25
+ <div class="relative z-10 text-center px-4">
26
+ <h1 class="text-4xl md:text-6xl lg:text-7xl font-bold text-white mb-6">Capture Moments <span class="text-yellow-400">Forever</span></h1>
27
+ <p class="text-xl md:text-2xl text-gray-200 mb-8 max-w-2xl mx-auto">Professional photography services to immortalize your most precious memories</p>
28
+ <a href="#contact" class="bg-yellow-400 hover:bg-yellow-500 text-gray-900 font-bold py-3 px-8 rounded-full transition duration-300 inline-flex items-center">
29
+ Book a Session
30
+ <i data-feather="arrow-right" class="ml-2 w-5 h-5"></i>
31
+ </a>
32
+ </div>
33
+ </section>
34
+
35
+ <!-- Gallery Section -->
36
+ <section id="portfolio" class="py-20 px-4 sm:px-6 lg:px-8">
37
+ <div class="max-w-7xl mx-auto">
38
+ <div class="text-center mb-16">
39
+ <h2 class="text-3xl md:text-4xl font-bold mb-4">My Portfolio</h2>
40
+ <p class="text-lg text-gray-600 max-w-2xl mx-auto">Explore my diverse photography projects across different categories</p>
41
+ </div>
42
+
43
+ <!-- Filter Buttons -->
44
+ <div class="flex flex-wrap justify-center gap-4 mb-12">
45
+ <button class="filter-btn active px-6 py-2 rounded-full font-medium bg-yellow-400 text-gray-900" data-filter="all">All</button>
46
+ <button class="filter-btn px-6 py-2 rounded-full font-medium bg-gray-200 hover:bg-gray-300 transition" data-filter="wedding">Wedding</button>
47
+ <button class="filter-btn px-6 py-2 rounded-full font-medium bg-gray-200 hover:bg-gray-300 transition" data-filter="portrait">Portrait</button>
48
+ <button class="filter-btn px-6 py-2 rounded-full font-medium bg-gray-200 hover:bg-gray-300 transition" data-filter="landscape">Landscape</button>
49
+ <button class="filter-btn px-6 py-2 rounded-full font-medium bg-gray-200 hover:bg-gray-300 transition" data-filter="product">Product</button>
50
+ </div>
51
+
52
+ <!-- Masonry Gallery -->
53
+ <div class="masonry-grid gap-6">
54
+ <!-- Images will be loaded via JavaScript -->
55
+ </div>
56
+ </div>
57
+ </section>
58
+
59
+ <!-- About Section -->
60
+ <section id="about" class="py-20 bg-gray-100">
61
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
62
+ <div class="flex flex-col lg:flex-row items-center gap-12">
63
+ <div class="lg:w-1/2">
64
+ <img src="http://static.photos/people/640x360/10" alt="Photographer" class="rounded-lg shadow-xl w-full h-auto">
65
+ </div>
66
+ <div class="lg:w-1/2">
67
+ <h2 class="text-3xl md:text-4xl font-bold mb-6">About Me</h2>
68
+ <p class="text-gray-600 mb-4">Hi, I'm Sarah Johnson, a professional photographer with over 10 years of experience capturing life's beautiful moments.</p>
69
+ <p class="text-gray-600 mb-4">My journey began when I received my first camera as a birthday gift, and since then, I've never looked back. Photography isn't just my profession—it's my passion and way of life.</p>
70
+ <p class="text-gray-600 mb-6">I specialize in wedding, portrait, and commercial photography, but I'm always excited to take on new challenges and creative projects.</p>
71
+ <div class="flex flex-wrap gap-4 mb-6">
72
+ <span class="bg-gray-200 px-4 py-2 rounded-full text-sm font-medium">Canon EOS R5</span>
73
+ <span class="bg-gray-200 px-4 py-2 rounded-full text-sm font-medium">Sony A7IV</span>
74
+ <span class="bg-gray-200 px-4 py-2 rounded-full text-sm font-medium">Nikon Z7 II</span>
75
+ </div>
76
+ <a href="#contact" class="inline-flex items-center text-yellow-600 font-medium hover:text-yellow-700 transition">
77
+ Let's Work Together
78
+ <i data-feather="arrow-right" class="ml-2 w-5 h-5"></i>
79
+ </a>
80
+ </div>
81
+ </div>
82
+ </div>
83
+ </section>
84
+
85
+ <!-- Services Section -->
86
+ <section id="services" class="py-20">
87
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
88
+ <div class="text-center mb-16">
89
+ <h2 class="text-3xl md:text-4xl font-bold mb-4">My Services</h2>
90
+ <p class="text-lg text-gray-600 max-w-2xl mx-auto">Comprehensive photography services tailored to your needs</p>
91
+ </div>
92
+
93
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
94
+ <!-- Service 1 -->
95
+ <div class="bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition duration-300">
96
+ <img src="http://static.photos/wedding/640x360/1" alt="Wedding Photography" class="w-full h-48 object-cover">
97
+ <div class="p-6">
98
+ <h3 class="text-xl font-bold mb-2">Wedding Photography</h3>
99
+ <p class="text-gray-600 mb-4">Capture your special day with timeless, romantic imagery that tells your unique love story.</p>
100
+ <div class="flex justify-between items-center">
101
+ <span class="font-bold text-gray-900">$1,200+</span>
102
+ <a href="#contact" class="text-yellow-600 hover:text-yellow-700 font-medium">Book Now</a>
103
+ </div>
104
+ </div>
105
+ </div>
106
+
107
+ <!-- Service 2 -->
108
+ <div class="bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition duration-300">
109
+ <img src="http://static.photos/portrait/640x360/2" alt="Portrait Photography" class="w-full h-48 object-cover">
110
+ <div class="p-6">
111
+ <h3 class="text-xl font-bold mb-2">Portrait Photography</h3>
112
+ <p class="text-gray-600 mb-4">Professional portraits for individuals, families, or business needs that showcase personality and professionalism.</p>
113
+ <div class="flex justify-between items-center">
114
+ <span class="font-bold text-gray-900">$350+</span>
115
+ <a href="#contact" class="text-yellow-600 hover:text-yellow-700 font-medium">Book Now</a>
116
+ </div>
117
+ </div>
118
+ </div>
119
+
120
+ <!-- Service 3 -->
121
+ <div class="bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition duration-300">
122
+ <img src="http://static.photos/product/640x360/3" alt="Product Photography" class="w-full h-48 object-cover">
123
+ <div class="p-6">
124
+ <h3 class="text-xl font-bold mb-2">Product Photography</h3>
125
+ <p class="text-gray-600 mb-4">High-quality images of your products that boost sales and enhance your brand's visual appeal.</p>
126
+ <div class="flex justify-between items-center">
127
+ <span class="font-bold text-gray-900">$75/hr</span>
128
+ <a href="#contact" class="text-yellow-600 hover:text-yellow-700 font-medium">Book Now</a>
129
+ </div>
130
+ </div>
131
+ </div>
132
+ </div>
133
+ </div>
134
+ </section>
135
+
136
+ <!-- Clients Section -->
137
+ <section class="py-16 bg-gray-100">
138
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
139
+ <div class="text-center mb-12">
140
+ <h2 class="text-2xl md:text-3xl font-bold mb-4">Trusted By</h2>
141
+ <p class="text-gray-600">Brands and clients I've had the pleasure to work with</p>
142
+ </div>
143
+ <custom-client-logos></custom-client-logos>
144
+ </div>
145
+ </section>
146
+
147
+ <!-- Contact Section -->
148
+ <section id="contact" class="py-20 bg-gray-900 text-white">
149
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
150
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-12">
151
+ <div>
152
+ <h2 class="text-3xl md:text-4xl font-bold mb-6">Get In Touch</h2>
153
+ <p class="text-gray-300 mb-8">Ready to book a session or have questions about my services? Fill out the form or reach out directly.</p>
154
+ <div class="space-y-6">
155
+ <div class="flex items-start">
156
+ <div class="flex-shrink-0 mt-1">
157
+ <i data-feather="mail" class="w-5 h-5 text-yellow-400"></i>
158
+ </div>
159
+ <div class="ml-4">
160
+ <h3 class="font-bold">Email</h3>
161
+ <p class="text-gray-300">hello@lenscrafted.com</p>
162
+ </div>
163
+ </div>
164
+ <div class="flex items-start">
165
+ <div class="flex-shrink-0 mt-1">
166
+ <i data-feather="phone" class="w-5 h-5 text-yellow-400"></i>
167
+ </div>
168
+ <div class="ml-4">
169
+ <h3 class="font-bold">Phone</h3>
170
+ <p class="text-gray-300">(555) 123-4567</p>
171
+ </div>
172
+ </div>
173
+ <div class="flex items-start">
174
+ <div class="flex-shrink-0 mt-1">
175
+ <i data-feather="map-pin" class="w-5 h-5 text-yellow-400"></i>
176
+ </div>
177
+ <div class="ml-4">
178
+ <h3 class="font-bold">Studio</h3>
179
+ <p class="text-gray-300">123 Photography Lane, Creative City, CC 90210</p>
180
+ </div>
181
+ </div>
182
+ </div>
183
+ <div class="mt-8">
184
+ <h3 class="font-bold mb-4">Follow Me</h3>
185
+ <div class="flex space-x-4">
186
+ <a href="#" class="text-gray-300 hover:text-yellow-400 transition">
187
+ <i data-feather="instagram" class="w-6 h-6"></i>
188
+ </a>
189
+ <a href="#" class="text-gray-300 hover:text-yellow-400 transition">
190
+ <i data-feather="facebook" class="w-6 h-6"></i>
191
+ </a>
192
+ <a href="#" class="text-gray-300 hover:text-yellow-400 transition">
193
+ <i data-feather="twitter" class="w-6 h-6"></i>
194
+ </a>
195
+ <a href="#" class="text-gray-300 hover:text-yellow-400 transition">
196
+ <i data-feather="youtube" class="w-6 h-6"></i>
197
+ </a>
198
+ </div>
199
+ </div>
200
+ </div>
201
+ <div>
202
+ <form class="bg-gray-800 p-8 rounded-lg shadow-lg">
203
+ <div class="mb-6">
204
+ <label for="name" class="block text-gray-300 mb-2">Your Name</label>
205
+ <input type="text" id="name" class="w-full px-4 py-3 bg-gray-700 border border-gray-600 rounded focus:outline-none focus:ring-2 focus:ring-yellow-400 text-white">
206
+ </div>
207
+ <div class="mb-6">
208
+ <label for="email" class="block text-gray-300 mb-2">Email Address</label>
209
+ <input type="email" id="email" class="w-full px-4 py-3 bg-gray-700 border border-gray-600 rounded focus:outline-none focus:ring-2 focus:ring-yellow-400 text-white">
210
+ </div>
211
+ <div class="mb-6">
212
+ <label for="service" class="block text-gray-300 mb-2">Service Interested In</label>
213
+ <select id="service" class="w-full px-4 py-3 bg-gray-700 border border-gray-600 rounded focus:outline-none focus:ring-2 focus:ring-yellow-400 text-white">
214
+ <option value="">Select a service</option>
215
+ <option value="wedding">Wedding Photography</option>
216
+ <option value="portrait">Portrait Photography</option>
217
+ <option value="product">Product Photography</option>
218
+ <option value="other">Other</option>
219
+ </select>
220
+ </div>
221
+ <div class="mb-6">
222
+ <label for="message" class="block text-gray-300 mb-2">Your Message</label>
223
+ <textarea id="message" rows="4" class="w-full px-4 py-3 bg-gray-700 border border-gray-600 rounded focus:outline-none focus:ring-2 focus:ring-yellow-400 text-white"></textarea>
224
+ </div>
225
+ <button type="submit" class="w-full bg-yellow-400 hover:bg-yellow-500 text-gray-900 font-bold py-3 px-4 rounded transition duration-300">
226
+ Send Message
227
+ </button>
228
+ </form>
229
+ </div>
230
+ </div>
231
+ </div>
232
+ </section>
233
+ </main>
234
+
235
+ <!-- Lightbox Modal -->
236
+ <div id="lightbox" class="fixed inset-0 bg-black bg-opacity-90 z-50 flex items-center justify-center hidden">
237
+ <div class="relative max-w-6xl w-full">
238
+ <button id="close-lightbox" class="absolute -top-12 right-0 text-white hover:text-yellow-400 transition">
239
+ <i data-feather="x" class="w-8 h-8"></i>
240
+ </button>
241
+ <div class="flex items-center justify-center">
242
+ <button id="prev-btn" class="absolute left-0 ml-4 text-white hover:text-yellow-400 transition">
243
+ <i data-feather="chevron-left" class="w-12 h-12"></i>
244
+ </button>
245
+ <img id="lightbox-img" src="" alt="" class="max-h-screen max-w-full">
246
+ <button id="next-btn" class="absolute right-0 mr-4 text-white hover:text-yellow-400 transition">
247
+ <i data-feather="chevron-right" class="w-12 h-12"></i>
248
+ </button>
249
+ </div>
250
+ <div id="lightbox-caption" class="text-center text-white mt-4"></div>
251
+ </div>
252
+ </div>
253
+
254
+ <custom-footer></custom-footer>
255
+
256
+ <script src="script.js"></script>
257
+ <script>
258
+ feather.replace();
259
+ </script>
260
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
261
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
262
+ </body>
263
+ </html>
script.js ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ document.addEventListener('DOMContentLoaded', function() {
2
+ // Initialize Feather Icons
3
+ feather.replace();
4
+
5
+ // Gallery data
6
+ const galleryData = [
7
+ { id: 1, category: 'wedding', src: 'http://static.photos/wedding/640x360/1', caption: 'Romantic wedding moment' },
8
+ { id: 2, category: 'portrait', src: 'http://static.photos/portrait/640x360/2', caption: 'Professional headshot' },
9
+ { id: 3, category: 'landscape', src: 'http://static.photos/landscape/640x360/3', caption: 'Mountain sunset' },
10
+ { id: 4, category: 'product', src: 'http://static.photos/product/640x360/4', caption: 'Luxury watch' },
11
+ { id: 5, category: 'wedding', src: 'http://static.photos/wedding/640x360/5', caption: 'First dance' },
12
+ { id: 6, category: 'portrait', src: 'http://static.photos/portrait/640x360/6', caption: 'Family portrait' },
13
+ { id: 7, category: 'landscape', src: 'http://static.photos/landscape/640x360/7', caption: 'Ocean view' },
14
+ { id: 8, category: 'product', src: 'http://static.photos/product/640x360/8', caption: 'Cosmetics line' },
15
+ { id: 9, category: 'wedding', src: 'http://static.photos/wedding/640x360/9', caption: 'Bride preparation' },
16
+ { id: 10, category: 'portrait', src: 'http://static.photos/portrait/640x360/10', caption: 'Corporate portrait' },
17
+ { id: 11, category: 'landscape', src: 'http://static.photos/landscape/640x360/11', caption: 'Forest path' },
18
+ { id: 12, category: 'product', src: 'http://static.photos/product/640x360/12', caption: 'Fashion accessories' }
19
+ ];
20
+
21
+ // Lightbox elements
22
+ const lightbox = document.getElementById('lightbox');
23
+ const lightboxImg = document.getElementById('lightbox-img');
24
+ const lightboxCaption = document.getElementById('lightbox-caption');
25
+ const closeLightbox = document.getElementById('close-lightbox');
26
+ const prevBtn = document.getElementById('prev-btn');
27
+ const nextBtn = document.getElementById('next-btn');
28
+
29
+ // Current image index for lightbox navigation
30
+ let currentImageIndex = 0;
31
+ let filteredImages = [];
32
+
33
+ // Initialize gallery
34
+ function initGallery() {
35
+ const galleryContainer = document.querySelector('.masonry-grid');
36
+ galleryContainer.innerHTML = '';
37
+
38
+ // Create gallery items
39
+ filteredImages.forEach((item, index) => {
40
+ const galleryItem = document.createElement('div');
41
+ galleryItem.className = 'gallery-item cursor-pointer';
42
+ galleryItem.dataset.category = item.category;
43
+ galleryItem.dataset.index = index;
44
+
45
+ galleryItem.innerHTML = `
46
+ <div class="category-label">${item.category}</div>
47
+ <img src="${item.src}" alt="${item.caption}" loading="lazy">
48
+ `;
49
+
50
+ galleryItem.addEventListener('click', () => openLightbox(index));
51
+ galleryContainer.appendChild(galleryItem);
52
+ });
53
+ }
54
+
55
+ // Filter gallery by category
56
+ function filterGallery(category) {
57
+ if (category === 'all') {
58
+ filteredImages = [...galleryData];
59
+ } else {
60
+ filteredImages = galleryData.filter(item => item.category === category);
61
+ }
62
+ initGallery();
63
+ }
64
+
65
+ // Open lightbox
66
+ function openLightbox(index) {
67
+ currentImageIndex = index;
68
+ lightboxImg.src = filteredImages[index].src;
69
+ lightboxCaption.textContent = filteredImages[index].caption;
70
+ lightbox.classList.add('show');
71
+ lightbox.classList.remove('hidden');
72
+ document.body.style.overflow = 'hidden';
73
+ }
74
+
75
+ // Close lightbox
76
+ function closeLightboxHandler() {
77
+ lightbox.classList.remove('show');
78
+ lightbox.classList.add('hidden');
79
+ document.body.style.overflow = '';
80
+ }
81
+
82
+ // Navigate to previous image
83
+ function prevImage() {
84
+ currentImageIndex = (currentImageIndex - 1 + filteredImages.length) % filteredImages.length;
85
+ lightboxImg.src = filteredImages[currentImageIndex].src;
86
+ lightboxCaption.textContent = filteredImages[currentImageIndex].caption;
87
+ }
88
+
89
+ // Navigate to next image
90
+ function nextImage() {
91
+ currentImageIndex = (currentImageIndex + 1) % filteredImages.length;
92
+ lightboxImg.src = filteredImages[currentImageIndex].src;
93
+ lightboxCaption.textContent = filteredImages[currentImageIndex].caption;
94
+ }
95
+
96
+ // Initialize filter buttons
97
+ function initFilterButtons() {
98
+ const filterButtons = document.querySelectorAll('.filter-btn');
99
+ filterButtons.forEach(button => {
100
+ button.addEventListener('click', function() {
101
+ // Remove active class from all buttons
102
+ filterButtons.forEach(btn => btn.classList.remove('active'));
103
+ // Add active class to clicked button
104
+ this.classList.add('active');
105
+ // Filter gallery
106
+ filterGallery(this.dataset.filter);
107
+ });
108
+ });
109
+ }
110
+
111
+ // Smooth scrolling for anchor links
112
+ document.querySelectorAll('a[href^="#"]').forEach(anchor => {
113
+ anchor.addEventListener('click', function(e) {
114
+ e.preventDefault();
115
+ const targetId = this.getAttribute('href');
116
+ if (targetId === '#') return;
117
+
118
+ const targetElement = document.querySelector(targetId);
119
+ if (targetElement) {
120
+ targetElement.scrollIntoView({
121
+ behavior: 'smooth'
122
+ });
123
+ }
124
+ });
125
+ });
126
+
127
+ // Initialize everything
128
+ filteredImages = [...galleryData];
129
+ initGallery();
130
+ initFilterButtons();
131
+
132
+ // Lightbox event listeners
133
+ closeLightbox.addEventListener('click', closeLightboxHandler);
134
+ prevBtn.addEventListener('click', prevImage);
135
+ nextBtn.addEventListener('click', nextImage);
136
+ lightbox.addEventListener('click', function(e) {
137
+ if (e.target === lightbox) {
138
+ closeLightboxHandler();
139
+ }
140
+ });
141
+
142
+ // Keyboard navigation for lightbox
143
+ document.addEventListener('keydown', function(e) {
144
+ if (!lightbox.classList.contains('hidden')) {
145
+ if (e.key === 'Escape') {
146
+ closeLightboxHandler();
147
+ } else if (e.key === 'ArrowLeft') {
148
+ prevImage();
149
+ } else if (e.key === 'ArrowRight') {
150
+ nextImage();
151
+ }
152
+ }
153
+ });
154
+ });
style.css CHANGED
@@ -1,28 +1,141 @@
1
- body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
 
 
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
 
 
 
 
 
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
28
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Masonry Grid */
2
+ .masonry-grid {
3
+ display: grid;
4
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
5
+ grid-auto-rows: 10px;
6
  }
7
 
8
+ .masonry-grid .gallery-item {
9
+ margin-bottom: 20px;
10
+ break-inside: avoid;
11
+ position: relative;
12
+ overflow: hidden;
13
+ border-radius: 8px;
14
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
15
+ transition: transform 0.3s ease;
16
  }
17
 
18
+ .masonry-grid .gallery-item:hover {
19
+ transform: scale(1.02);
 
 
 
20
  }
21
 
22
+ .masonry-grid .gallery-item img {
23
+ width: 100%;
24
+ height: auto;
25
+ display: block;
26
+ transition: transform 0.5s ease;
 
27
  }
28
 
29
+ .masonry-grid .gallery-item:hover img {
30
+ transform: scale(1.05);
31
  }
32
+
33
+ .masonry-grid .gallery-item .category-label {
34
+ position: absolute;
35
+ top: 15px;
36
+ left: 15px;
37
+ background-color: rgba(234, 179, 8, 0.9);
38
+ color: white;
39
+ padding: 4px 12px;
40
+ border-radius: 20px;
41
+ font-size: 12px;
42
+ font-weight: 600;
43
+ text-transform: capitalize;
44
+ }
45
+
46
+ /* Lightbox transitions */
47
+ #lightbox {
48
+ opacity: 0;
49
+ transition: opacity 0.3s ease;
50
+ }
51
+
52
+ #lightbox.show {
53
+ opacity: 1;
54
+ }
55
+
56
+ /* Custom scrollbar */
57
+ ::-webkit-scrollbar {
58
+ width: 10px;
59
+ }
60
+
61
+ ::-webkit-scrollbar-track {
62
+ background: #f1f1f1;
63
+ }
64
+
65
+ ::-webkit-scrollbar-thumb {
66
+ background: #d1d5db;
67
+ border-radius: 5px;
68
+ }
69
+
70
+ ::-webkit-scrollbar-thumb:hover {
71
+ background: #9ca3af;
72
+ }
73
+
74
+ /* Smooth scrolling */
75
+ html {
76
+ scroll-behavior: smooth;
77
+ }
78
+
79
+ /* Custom animation for hero section */
80
+ @keyframes fadeInUp {
81
+ from {
82
+ opacity: 0;
83
+ transform: translateY(20px);
84
+ }
85
+ to {
86
+ opacity: 1;
87
+ transform: translateY(0);
88
+ }
89
+ }
90
+
91
+ .hero-content {
92
+ animation: fadeInUp 1s ease forwards;
93
+ }
94
+
95
+ /* Responsive video background */
96
+ video {
97
+ position: absolute;
98
+ top: 50%;
99
+ left: 50%;
100
+ transform: translate(-50%, -50%);
101
+ min-width: 100%;
102
+ min-height: 100%;
103
+ width: auto;
104
+ height: auto;
105
+ z-index: -1;
106
+ }
107
+
108
+ /* Filter button active state */
109
+ .filter-btn.active {
110
+ background-color: #f59e0b !important;
111
+ color: #1f2937 !important;
112
+ }
113
+ /* Game NFT card effects */
114
+ .nft-card {
115
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
116
+ }
117
+
118
+ .nft-card:hover {
119
+ transform: translateY(-5px);
120
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
121
+ }
122
+
123
+ /* Game UI styles */
124
+ .game-message {
125
+ min-height: 4rem;
126
+ display: flex;
127
+ align-items: center;
128
+ justify-content: center;
129
+ background-color: #1f2937;
130
+ border-radius: 0.5rem;
131
+ }
132
+
133
+ /* Service card hover effect */
134
+ .service-card:hover img {
135
+ transform: scale(1.1);
136
+ transition: transform 0.5s ease;
137
+ }
138
+
139
+ .service-card img {
140
+ transition: transform 0.5s ease;
141
+ }