pearsonkyle commited on
Commit
a40c981
·
verified ·
1 Parent(s): 1731f51

Optimize this website and make sure it works for mobile and desktop - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +389 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Mtg Card Explorer
3
- emoji: 📊
4
- colorFrom: purple
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: mtg-card-explorer
3
+ emoji: 🐳
4
+ colorFrom: yellow
5
+ colorTo: gray
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,389 @@
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>MTG Card Explorer</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .mana-symbol {
11
+ display: inline-block;
12
+ width: 1.2em;
13
+ height: 1.2em;
14
+ background-size: contain;
15
+ background-repeat: no-repeat;
16
+ vertical-align: middle;
17
+ }
18
+
19
+ .card-container {
20
+ perspective: 1000px;
21
+ }
22
+
23
+ .card-inner {
24
+ transition: transform 0.6s;
25
+ transform-style: preserve-3d;
26
+ }
27
+
28
+ .card-container:hover .card-inner,
29
+ .card-container.flipped .card-inner {
30
+ transform: rotateY(180deg);
31
+ }
32
+
33
+ .card-front, .card-back {
34
+ backface-visibility: hidden;
35
+ }
36
+
37
+ .card-back {
38
+ transform: rotateY(180deg);
39
+ }
40
+
41
+ @keyframes pulse {
42
+ 0% { transform: scale(1); }
43
+ 50% { transform: scale(1.05); }
44
+ 100% { transform: scale(1); }
45
+ }
46
+
47
+ .pulse {
48
+ animation: pulse 2s infinite;
49
+ }
50
+
51
+ .card-shadow {
52
+ box-shadow: 0 10px 30px -5px rgba(0, 0, 0, 0.3);
53
+ }
54
+
55
+ .card-border {
56
+ border-radius: 3.5% / 4.7%;
57
+ }
58
+
59
+ .type-line {
60
+ border-bottom: 2px solid #d9c8a9;
61
+ }
62
+
63
+ .legal-badge {
64
+ transition: all 0.2s ease;
65
+ }
66
+
67
+ .legal-badge:hover {
68
+ transform: translateY(-2px);
69
+ }
70
+ </style>
71
+ </head>
72
+ <body class="bg-gray-900 text-gray-100 min-h-screen">
73
+ <div class="container mx-auto px-4 py-8">
74
+ <header class="text-center mb-12">
75
+ <h1 class="text-4xl md:text-5xl font-bold bg-gradient-to-r from-purple-600 via-blue-500 to-green-400 bg-clip-text text-transparent mb-2">
76
+ MTG Card Explorer
77
+ </h1>
78
+ <p class="text-lg text-gray-300 max-w-2xl mx-auto">
79
+ Discover random Magic: The Gathering cards with detailed information. Click below to get started!
80
+ </p>
81
+ </header>
82
+
83
+ <div class="flex flex-col lg:flex-row gap-4 lg:gap-8 items-center lg:items-start justify-center">
84
+ <!-- Card Display Section -->
85
+ <div class="w-full lg:w-1/2 xl:w-2/5 flex flex-col items-center">
86
+ <div class="card-container w-full max-w-md mb-6">
87
+ <div class="card-inner relative">
88
+ <!-- Front of Card -->
89
+ <div class="card-front">
90
+ <div id="card-image" class="card-border overflow-hidden bg-gray-800 relative">
91
+ <div class="aspect-[0.72] w-full flex items-center justify-center bg-gray-700">
92
+ <div class="text-center p-4">
93
+ <i class="fas fa-cards text-6xl text-gray-600 mb-4"></i>
94
+ <p class="text-gray-400">Click "Random Card" to load a Magic card</p>
95
+ </div>
96
+ </div>
97
+ </div>
98
+ </div>
99
+
100
+ <!-- Back of Card (Details) -->
101
+ <div class="card-back absolute top-0 left-0 w-full h-full bg-gray-800 p-6 rounded-lg card-shadow card-border">
102
+ <div id="card-details" class="h-full overflow-y-auto">
103
+ <p class="text-gray-400">Card details will appear here</p>
104
+ </div>
105
+ </div>
106
+ </div>
107
+ </div>
108
+
109
+ <div class="flex gap-4 mt-4">
110
+ <button id="random-btn" class="bg-gradient-to-r from-blue-600 to-blue-800 hover:from-blue-700 hover:to-blue-900 text-white font-bold py-3 px-6 rounded-full shadow-lg transition-all duration-300 transform hover:scale-105 active:scale-95 flex items-center gap-2">
111
+ <i class="fas fa-random"></i>
112
+ <span>Random Card</span>
113
+ </button>
114
+
115
+ <button id="flip-btn" class="bg-gray-700 hover:bg-gray-600 text-white font-bold py-3 px-6 rounded-full shadow-lg transition-all duration-300 transform hover:scale-105 active:scale-95 flex items-center gap-2">
116
+ <i class="fas fa-exchange-alt"></i>
117
+ <span>Flip Card</span>
118
+ </button>
119
+ </div>
120
+ </div>
121
+
122
+ <!-- Card Info Section -->
123
+ <div id="card-info" class="w-full lg:w-1/2 xl:w-3/5 bg-gray-800 rounded-lg p-4 lg:p-6 shadow-xl">
124
+ <div class="flex flex-col h-full">
125
+ <h2 id="card-name" class="text-2xl font-bold mb-2 text-center lg:text-left">No Card Loaded</h2>
126
+ <div id="card-type" class="text-lg text-gray-300 mb-4 text-center lg:text-left"></div>
127
+
128
+ <div class="flex flex-wrap gap-2 justify-center lg:justify-start mb-6" id="mana-cost"></div>
129
+
130
+ <div class="bg-gray-700 rounded-lg p-4 mb-6">
131
+ <div id="card-text" class="text-gray-100 whitespace-pre-line"></div>
132
+ </div>
133
+
134
+ <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
135
+ <div class="bg-gray-700 rounded-lg p-4">
136
+ <h3 class="font-semibold text-gray-300 mb-2">Legalities</h3>
137
+ <div id="card-legalities" class="flex flex-wrap gap-2"></div>
138
+ </div>
139
+ <div class="bg-gray-700 rounded-lg p-4">
140
+ <h3 class="font-semibold text-gray-300 mb-2">Details</h3>
141
+ <div id="card-stats" class="text-gray-100"></div>
142
+ </div>
143
+
144
+ <div class="bg-gray-700 rounded-lg p-4">
145
+ <h3 class="font-semibold text-gray-300 mb-2">Prices</h3>
146
+ <div id="card-prices" class="text-gray-100"></div>
147
+ </div>
148
+
149
+ <div class="bg-gray-700 rounded-lg p-4">
150
+ <h3 class="font-semibold text-gray-300 mb-2">Links</h3>
151
+ <div id="card-links" class="flex flex-wrap gap-2"></div>
152
+ </div>
153
+ </div>
154
+ </div>
155
+ </div>
156
+ </div>
157
+
158
+ <!-- Loading Indicator -->
159
+ <div id="loading" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50">
160
+ <div class="bg-gray-800 p-8 rounded-lg shadow-2xl text-center max-w-md">
161
+ <div class="animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-blue-500 mx-auto mb-4"></div>
162
+ <h3 class="text-xl font-bold mb-2">Fetching Card</h3>
163
+ <p class="text-gray-300">Contacting the Multiverse...</p>
164
+ </div>
165
+ </div>
166
+ </div>
167
+
168
+ <script>
169
+ document.addEventListener('DOMContentLoaded', function() {
170
+ const randomBtn = document.getElementById('random-btn');
171
+ const flipBtn = document.getElementById('flip-btn');
172
+ const loading = document.getElementById('loading');
173
+ const cardImage = document.getElementById('card-image');
174
+ const cardDetails = document.getElementById('card-details');
175
+ const cardName = document.getElementById('card-name');
176
+ const cardType = document.getElementById('card-type');
177
+ const manaCost = document.getElementById('mana-cost');
178
+ const cardText = document.getElementById('card-text');
179
+ const cardStats = document.getElementById('card-stats');
180
+ const cardLegalities = document.getElementById('card-legalities');
181
+ const cardInfo = document.getElementById('card-info');
182
+
183
+ // Flip card functionality
184
+ flipBtn.addEventListener('click', function() {
185
+ document.querySelector('.card-container').classList.toggle('flipped');
186
+ });
187
+
188
+ // Fetch random card
189
+ randomBtn.addEventListener('click', fetchRandomCard);
190
+
191
+ // Initial fetch
192
+ // fetchRandomCard();
193
+
194
+ function fetchRandomCard() {
195
+ loading.classList.remove('hidden');
196
+ document.body.style.overflow = 'hidden';
197
+ cardInfo.classList.add('opacity-50');
198
+ randomBtn.disabled = true;
199
+ flipBtn.disabled = true;
200
+
201
+ fetch('https://api.scryfall.com/cards/random')
202
+ .then(response => {
203
+ if (!response.ok) {
204
+ throw new Error('Network response was not ok');
205
+ }
206
+ return response.json();
207
+ })
208
+ .then(data => {
209
+ displayCard(data);
210
+ loading.classList.add('hidden');
211
+ document.body.style.overflow = '';
212
+ cardInfo.classList.remove('opacity-50');
213
+ randomBtn.disabled = false;
214
+ flipBtn.disabled = false;
215
+ })
216
+ .catch(error => {
217
+ console.error('Error fetching card:', error);
218
+ loading.classList.add('hidden');
219
+ document.body.style.overflow = '';
220
+ cardInfo.classList.remove('opacity-50');
221
+ randomBtn.disabled = false;
222
+ flipBtn.disabled = false;
223
+ alert('Error fetching card. Please try again.');
224
+ });
225
+ }
226
+
227
+ function displayCard(card) {
228
+ // Display card image
229
+ if (card.image_uris) {
230
+ cardImage.innerHTML = `
231
+ <img src="${card.image_uris.large}"
232
+ alt="${card.name}"
233
+ class="w-full h-full object-cover card-border"
234
+ onerror="this.onerror=null;this.src='${card.image_uris.normal}';">
235
+ `;
236
+ } else if (card.card_faces) {
237
+ // Handle double-faced cards
238
+ cardImage.innerHTML = `
239
+ <img src="${card.card_faces[0].image_uris.large}"
240
+ alt="${card.name}"
241
+ class="w-full h-full object-cover card-border"
242
+ onerror="this.onerror=null;this.src='${card.card_faces[0].image_uris.normal}';">
243
+ `;
244
+ }
245
+
246
+ // Display card details on back
247
+ let detailsHtml = `
248
+ <h3 class="text-xl font-bold mb-4">${card.name}</h3>
249
+ <div class="mb-4">
250
+ <p class="text-gray-300"><span class="font-semibold">Set:</span> ${card.set_name} (${card.set.toUpperCase()})</p>
251
+ <p class="text-gray-300"><span class="font-semibold">Artist:</span> ${card.artist}</p>
252
+ </div>
253
+ `;
254
+
255
+ if (card.flavor_text) {
256
+ detailsHtml += `
257
+ <div class="bg-gray-700 rounded-lg p-4 mb-4 italic text-gray-300">
258
+ ${card.flavor_text}
259
+ </div>
260
+ `;
261
+ }
262
+
263
+ cardDetails.innerHTML = detailsHtml;
264
+
265
+ // Display card info
266
+ cardName.textContent = card.name;
267
+
268
+ // Display type line
269
+ cardType.textContent = card.type_line;
270
+
271
+ // Display mana cost
272
+ manaCost.innerHTML = '';
273
+ if (card.mana_cost) {
274
+ const cost = card.mana_cost;
275
+ const symbols = cost.match(/\{[^{}]+\}/g) || [];
276
+
277
+ symbols.forEach(symbol => {
278
+ const symbolName = symbol.replace(/[{}]/g, '').toLowerCase();
279
+ const symbolElement = document.createElement('div');
280
+ symbolElement.className = 'mana-symbol';
281
+ symbolElement.style.backgroundImage = `url(https://c2.scryfall.com/file/scryfall-symbols/card-symbols/${symbolName}.svg)`;
282
+ symbolElement.title = symbolName.toUpperCase();
283
+ manaCost.appendChild(symbolElement);
284
+ });
285
+ }
286
+
287
+ // Display card text
288
+ cardText.textContent = card.oracle_text || '';
289
+
290
+ // Display stats (power/toughness or loyalty)
291
+ let statsHtml = '';
292
+ if (card.power && card.toughness) {
293
+ statsHtml += `<p><span class="font-semibold">P/T:</span> ${card.power}/${card.toughness}</p>`;
294
+ }
295
+ if (card.loyalty) {
296
+ statsHtml += `<p><span class="font-semibold">Loyalty:</span> ${card.loyalty}</p>`;
297
+ }
298
+ statsHtml += `<p><span class="font-semibold">CMC:</span> ${card.cmc}</p>`;
299
+
300
+ if (card.colors) {
301
+ const colorMap = {
302
+ 'W': 'White',
303
+ 'U': 'Blue',
304
+ 'B': 'Black',
305
+ 'R': 'Red',
306
+ 'G': 'Green'
307
+ };
308
+ const colorNames = card.colors.map(c => colorMap[c]).join(', ');
309
+ statsHtml += `<p><span class="font-semibold">Colors:</span> ${colorNames}</p>`;
310
+ }
311
+
312
+ if (card.keywords && card.keywords.length > 0) {
313
+ statsHtml += `<p><span class="font-semibold">Keywords:</span> ${card.keywords.join(', ')}</p>`;
314
+ }
315
+
316
+ cardStats.innerHTML = statsHtml;
317
+
318
+ // Display prices and purchase links
319
+ let pricesHtml = '';
320
+ if (card.prices) {
321
+ pricesHtml += `
322
+ ${card.prices.usd ? `<p><span class="font-semibold">USD:</span> ${card.prices.usd}</p>` : ''}
323
+ ${card.prices.usd_foil ? `<p><span class="font-semibold">Foil:</span> ${card.prices.usd_foil}</p>` : ''}
324
+ ${card.prices.eur ? `<p><span class="font-semibold">EUR:</span> €${card.prices.eur}</p>` : ''}
325
+ ${card.prices.tix ? `<p><span class="font-semibold">MTGO:</span> ${card.prices.tix} tix</p>` : ''}
326
+ `;
327
+
328
+ // Add purchase links if they exist
329
+ if (card.purchase_uris) {
330
+ pricesHtml += `<div class="mt-4"><h4 class="font-semibold mb-2">Buy From:</h4>`;
331
+ if (card.purchase_uris.tcgplayer) {
332
+ pricesHtml += `<a href="${card.purchase_uris.tcgplayer}" target="_blank" class="bg-orange-600 hover:bg-orange-700 text-white px-3 py-1 rounded text-sm mr-2 mb-2 inline-block">TCGplayer</a>`;
333
+ }
334
+ if (card.purchase_uris.cardmarket) {
335
+ pricesHtml += `<a href="${card.purchase_uris.cardmarket}" target="_blank" class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded text-sm mr-2 mb-2 inline-block">Cardmarket</a>`;
336
+ }
337
+ if (card.purchase_uris.cardhoarder) {
338
+ pricesHtml += `<a href="${card.purchase_uris.cardhoarder}" target="_blank" class="bg-green-600 hover:bg-green-700 text-white px-3 py-1 rounded text-sm mr-2 mb-2 inline-block">Cardhoarder</a>`;
339
+ }
340
+ pricesHtml += `</div>`;
341
+ }
342
+ }
343
+ document.getElementById('card-prices').innerHTML = pricesHtml;
344
+
345
+ // Display links
346
+ let linksHtml = '';
347
+ if (card.related_uris) {
348
+ linksHtml += `
349
+ ${card.related_uris.gatherer ? `<a href="${card.related_uris.gatherer}" target="_blank" class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded text-sm">Gatherer</a>` : ''}
350
+ ${card.related_uris.edhrec ? `<a href="${card.related_uris.edhrec}" target="_blank" class="bg-purple-600 hover:bg-purple-700 text-white px-3 py-1 rounded text-sm">EDHREC</a>` : ''}
351
+ ${card.scryfall_uri ? `<a href="${card.scryfall_uri}" target="_blank" class="bg-green-600 hover:bg-green-700 text-white px-3 py-1 rounded text-sm">Scryfall</a>` : ''}
352
+ `;
353
+ }
354
+ document.getElementById('card-links').innerHTML = linksHtml;
355
+
356
+ // Display legalities
357
+ cardLegalities.innerHTML = '';
358
+ if (card.legalities) {
359
+ const formatMap = {
360
+ 'standard': 'Standard',
361
+ 'modern': 'Modern',
362
+ 'legacy': 'Legacy',
363
+ 'vintage': 'Vintage',
364
+ 'commander': 'Commander',
365
+ 'pioneer': 'Pioneer',
366
+ 'historic': 'Historic',
367
+ 'pauper': 'Pauper',
368
+ 'brawl': 'Brawl'
369
+ };
370
+
371
+ for (const [format, status] of Object.entries(card.legalities)) {
372
+ if (formatMap[format]) {
373
+ const badge = document.createElement('div');
374
+ badge.className = `legal-badge px-3 py-1 rounded-full text-xs font-semibold ${
375
+ status === 'legal' ? 'bg-green-600 text-white' :
376
+ status === 'not_legal' ? 'bg-red-600 text-white' :
377
+ 'bg-yellow-600 text-black'
378
+ }`;
379
+ badge.textContent = `${formatMap[format]}: ${status.replace('_', ' ')}`;
380
+ badge.title = `${formatMap[format]} is ${status.replace('_', ' ')}`;
381
+ cardLegalities.appendChild(badge);
382
+ }
383
+ }
384
+ }
385
+ }
386
+ });
387
+ </script>
388
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=pearsonkyle/mtg-card-explorer" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
389
+ </html>