Add Rarity-Based Gradients & Animated Particles

🎨 Rarity-Based Visual System:
- Replaced TCG-based gradients with subtle rarity-based backgrounds
- Common: Subtle gray gradient (no particles)
- Uncommon: Subtle green gradient (15 particles)
- Rare: Subtle gold gradient (25 particles)
- Mythic: Rich gold gradient (40 particles)
- Holographic: Subtle pink gradient (50 particles)
- Enchanted: Subtle purple gradient (60 particles)
- Super Rare: Subtle blue gradient (45 particles)
- Legendary: Vibrant gold gradient (80 particles)

 Animated Particle Effects:
- Floating particle animation with random positioning
- Particles match rarity colors with glowing effects
- Random animation delays and durations for natural movement
- More rare cards = more magical particle effects
- Particles are pointer-events-none (do not interfere with UI)

🎯 Smart Text Contrast:
- Light rarities (common/uncommon/rare) use dark text
- Dark rarities (mythic+) use white text for readability
- Automatic contrast adaptation based on background

🌟 Enhanced Atmosphere:
- Subtle background patterns (reduced opacity)
- Rarity-appropriate visual hierarchy
- Immersive, magical feel for rare cards

The hero section now creates a truly magical experience
This commit is contained in:
Randall Stillwell 2025-07-27 21:46:48 -05:00
parent 36fe4a6f0f
commit 2867a8ff23
2 changed files with 99 additions and 9 deletions

View file

@ -132,13 +132,49 @@ export default function CardDetail() {
} }
}, [card, id]); }, [card, id]);
const getTCGGradient = (game) => { const getRarityGradient = (rarity) => {
const rarityKey = rarity?.toLowerCase();
const gradients = { const gradients = {
'MTG': '#9333ea, #8b5cf6, #4f46e5', 'common': '#f3f4f6, #e5e7eb, #d1d5db', // Subtle gray
'Pokemon': '#2563eb, #3b82f6, #0891b2', 'uncommon': '#ecfdf5, #d1fae5, #a7f3d0', // Subtle green
'Lorcana': '#db2777, #ec4899, #a855f7' 'rare': '#fef3c7, #fde68a, #fcd34d', // Subtle gold
'mythic': '#fef9c3, #fef08a, #facc15', // Rich gold
'holographic': '#fce7f3, #fbcfe8, #f9a8d4', // Subtle pink
'enchanted': '#f3e8ff, #e9d5ff, #c4b5fd', // Subtle purple
'super rare': '#dbeafe, #bfdbfe, #93c5fd', // Subtle blue
'legendary': '#fef3c7, #fde68a, #f59e0b' // Vibrant gold
}; };
return gradients[game] || '#4b5563, #374151'; return gradients[rarityKey] || '#f9fafb, #f3f4f6, #e5e7eb';
};
const getParticleCount = (rarity) => {
const rarityKey = rarity?.toLowerCase();
const particleCounts = {
'common': 0,
'uncommon': 15,
'rare': 25,
'mythic': 40,
'holographic': 50,
'enchanted': 60,
'super rare': 45,
'legendary': 80
};
return particleCounts[rarityKey] || 0;
};
const getParticleColor = (rarity) => {
const rarityKey = rarity?.toLowerCase();
const colors = {
'common': '#ffffff',
'uncommon': '#10b981',
'rare': '#f59e0b',
'mythic': '#ffd700',
'holographic': '#ff6b6b',
'enchanted': '#a855f7',
'super rare': '#3b82f6',
'legendary': '#ffd700'
};
return colors[rarityKey] || '#ffffff';
}; };
const getTCGIcon = (game) => { const getTCGIcon = (game) => {
@ -338,13 +374,39 @@ export default function CardDetail() {
<div <div
className="relative min-h-96 flex items-center justify-center overflow-hidden" className="relative min-h-96 flex items-center justify-center overflow-hidden"
style={{ style={{
background: `linear-gradient(135deg, ${getTCGGradient(card.game)})` background: `linear-gradient(135deg, ${getRarityGradient(card.rarity)})`
}} }}
> >
{/* Animated Particles Background */}
{getParticleCount(card.rarity) > 0 && (
<div className="absolute inset-0 overflow-hidden pointer-events-none">
{Array.from({ length: getParticleCount(card.rarity) }).map((_, i) => (
<div
key={i}
className="absolute animate-float"
style={{
left: `${Math.random() * 100}%`,
top: `${Math.random() * 100}%`,
animationDelay: `${Math.random() * 3}s`,
animationDuration: `${3 + Math.random() * 2}s`
}}
>
<div
className="w-1 h-1 rounded-full opacity-60"
style={{
backgroundColor: getParticleColor(card.rarity),
boxShadow: `0 0 6px ${getParticleColor(card.rarity)}`
}}
/>
</div>
))}
</div>
)}
{/* Background Pattern */} {/* Background Pattern */}
<div className="absolute inset-0 opacity-10"> <div className="absolute inset-0 opacity-5">
<div className="absolute inset-0" style={{ <div className="absolute inset-0" style={{
backgroundImage: `url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.1'%3E%3Ccircle cx='30' cy='30' r='2'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")` backgroundImage: `url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23000000' fill-opacity='0.1'%3E%3Ccircle cx='30' cy='30' r='2'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")`
}}></div> }}></div>
</div> </div>
@ -385,7 +447,11 @@ export default function CardDetail() {
</div> </div>
{/* Card Info */} {/* Card Info */}
<div style={{ color: 'white' }}> <div style={{
color: ['common', 'uncommon', 'rare'].includes(card.rarity?.toLowerCase())
? 'var(--text-primary)'
: 'white'
}}>
<div className="mb-6"> <div className="mb-6">
<h1 className="text-4xl font-bold mb-2">{card.name}</h1> <h1 className="text-4xl font-bold mb-2">{card.name}</h1>
<p className="text-xl opacity-90 mb-4">{card.oracle_text || card.card_type}</p> <p className="text-xl opacity-90 mb-4">{card.oracle_text || card.card_type}</p>

View file

@ -674,3 +674,27 @@ body {
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
overflow: hidden; overflow: hidden;
} }
/* Floating particle animation */
@keyframes float {
0%, 100% {
transform: translateY(0px) translateX(0px) scale(1);
opacity: 0.6;
}
25% {
transform: translateY(-20px) translateX(10px) scale(1.1);
opacity: 0.8;
}
50% {
transform: translateY(-10px) translateX(-15px) scale(0.9);
opacity: 1;
}
75% {
transform: translateY(-25px) translateX(5px) scale(1.05);
opacity: 0.7;
}
}
.animate-float {
animation: float 4s ease-in-out infinite;
}