🔥 Add Fire Glow Login Background
✨ Beautiful Animated Fire Glow: - Slow-moving fire gradient background with light/dark modes - Floating ember particles with realistic animation - 12-second background animation cycle with subtle color shifts - Theme-aware gradient colors (warm daylight vs cozy evening) 🎨 Enhanced Login Experience: - Updated branding to Deck Hearth with fire emoji - Backdrop blur effects on form elements - Semi-transparent containers for depth - Orange focus states to match fire theme - Enhanced shadows and glow effects 🌙 Theme Support: - Light mode: Warm daylight fire with golden embers - Dark mode: Cozy evening fire with bright orange flames - RGB color variables for backdrop-blur compatibility - Gradient-bg-ember class for consistent fire theming The login page now perfectly captures the warm, inviting Deck Hearth atmosphere
This commit is contained in:
parent
308d2de365
commit
2163b9ea0e
3 changed files with 164 additions and 23 deletions
|
|
@ -4,8 +4,59 @@ export default function AuthLayout({ children }) {
|
||||||
const { theme } = useTheme();
|
const { theme } = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen" style={{ backgroundColor: 'var(--bg-primary)' }}>
|
<div className="min-h-screen relative overflow-hidden">
|
||||||
{children}
|
{/* Animated Fire Glow Background */}
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 fire-glow-bg"
|
||||||
|
style={{
|
||||||
|
background: theme === 'dark'
|
||||||
|
? `
|
||||||
|
radial-gradient(circle at 20% 80%, rgba(255, 107, 0, 0.15) 0%, transparent 50%),
|
||||||
|
radial-gradient(circle at 80% 20%, rgba(255, 69, 0, 0.12) 0%, transparent 50%),
|
||||||
|
radial-gradient(circle at 40% 40%, rgba(220, 38, 127, 0.08) 0%, transparent 50%),
|
||||||
|
linear-gradient(135deg, rgba(31, 41, 55, 0.95) 0%, rgba(17, 24, 39, 0.98) 100%)
|
||||||
|
`
|
||||||
|
: `
|
||||||
|
radial-gradient(circle at 20% 80%, rgba(255, 171, 64, 0.08) 0%, transparent 50%),
|
||||||
|
radial-gradient(circle at 80% 20%, rgba(251, 146, 60, 0.06) 0%, transparent 50%),
|
||||||
|
radial-gradient(circle at 40% 40%, rgba(249, 115, 22, 0.04) 0%, transparent 50%),
|
||||||
|
linear-gradient(135deg, rgba(255, 251, 235, 0.9) 0%, rgba(254, 243, 199, 0.95) 100%)
|
||||||
|
`
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Floating Embers */}
|
||||||
|
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||||
|
{Array.from({ length: 12 }).map((_, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="absolute animate-ember-float opacity-30"
|
||||||
|
style={{
|
||||||
|
left: `${Math.random() * 100}%`,
|
||||||
|
top: `${Math.random() * 100}%`,
|
||||||
|
animationDelay: `${Math.random() * 8}s`,
|
||||||
|
animationDuration: `${8 + Math.random() * 4}s`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="w-1 h-1 rounded-full"
|
||||||
|
style={{
|
||||||
|
backgroundColor: theme === 'dark'
|
||||||
|
? `rgba(255, ${100 + Math.random() * 100}, 0, 0.6)`
|
||||||
|
: `rgba(251, ${100 + Math.random() * 46}, 60, 0.4)`,
|
||||||
|
boxShadow: theme === 'dark'
|
||||||
|
? `0 0 8px rgba(255, ${100 + Math.random() * 100}, 0, 0.4)`
|
||||||
|
: `0 0 6px rgba(251, ${100 + Math.random() * 46}, 60, 0.3)`
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="relative z-10">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -67,21 +67,27 @@ export default function Login() {
|
||||||
<div className="max-w-md w-full space-y-8">
|
<div className="max-w-md w-full space-y-8">
|
||||||
<div>
|
<div>
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<div className="text-6xl mb-4">🃏</div>
|
<div className="text-6xl mb-4">🔥</div>
|
||||||
<h2 className="text-3xl font-bold" style={{ color: 'var(--text-primary)' }}>
|
<h2 className="text-3xl font-bold gradient-text-flame mb-2">
|
||||||
Sign in to TCG Vault
|
Welcome to Deck Hearth
|
||||||
</h2>
|
</h2>
|
||||||
<p className="mt-2 text-sm" style={{ color: 'var(--text-secondary)' }}>
|
<p className="mt-2 text-sm" style={{ color: 'var(--text-secondary)' }}>
|
||||||
Access your trading card collection
|
Sign in to access your trading card collection
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-8 rounded-2xl shadow-lg" style={{ backgroundColor: 'var(--bg-secondary)' }}>
|
<div
|
||||||
|
className="p-8 rounded-2xl shadow-2xl backdrop-blur-sm border border-opacity-20"
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'rgba(var(--bg-secondary-rgb), 0.85)',
|
||||||
|
borderColor: 'var(--border)'
|
||||||
|
}}
|
||||||
|
>
|
||||||
<form onSubmit={handleSubmit} className="space-y-6">
|
<form onSubmit={handleSubmit} className="space-y-6">
|
||||||
{error && (
|
{error && (
|
||||||
<div className="p-4 rounded-lg bg-red-100 border border-red-200">
|
<div className="p-4 rounded-lg bg-red-500 bg-opacity-10 border border-red-500 border-opacity-20 backdrop-blur-sm">
|
||||||
<p className="text-red-700 text-sm">{error}</p>
|
<p className="text-red-400 text-sm">{error}</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
@ -97,9 +103,9 @@ export default function Login() {
|
||||||
required
|
required
|
||||||
value={formData.email}
|
value={formData.email}
|
||||||
onChange={(e) => handleInputChange('email', e.target.value)}
|
onChange={(e) => handleInputChange('email', e.target.value)}
|
||||||
className="w-full px-4 py-3 rounded-lg border transition-all duration-200 focus:ring-2 focus:ring-purple-500 focus:border-transparent"
|
className="w-full px-4 py-3 rounded-lg border transition-all duration-200 focus:ring-2 focus:ring-orange-500 focus:border-transparent backdrop-blur-sm"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: 'var(--bg-primary)',
|
backgroundColor: 'rgba(var(--bg-primary-rgb), 0.7)',
|
||||||
borderColor: 'var(--border)',
|
borderColor: 'var(--border)',
|
||||||
color: 'var(--text-primary)'
|
color: 'var(--text-primary)'
|
||||||
}}
|
}}
|
||||||
|
|
@ -119,9 +125,9 @@ export default function Login() {
|
||||||
required
|
required
|
||||||
value={formData.password}
|
value={formData.password}
|
||||||
onChange={(e) => handleInputChange('password', e.target.value)}
|
onChange={(e) => handleInputChange('password', e.target.value)}
|
||||||
className="w-full px-4 py-3 rounded-lg border transition-all duration-200 focus:ring-2 focus:ring-purple-500 focus:border-transparent"
|
className="w-full px-4 py-3 rounded-lg border transition-all duration-200 focus:ring-2 focus:ring-orange-500 focus:border-transparent backdrop-blur-sm"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: 'var(--bg-primary)',
|
backgroundColor: 'rgba(var(--bg-primary-rgb), 0.7)',
|
||||||
borderColor: 'var(--border)',
|
borderColor: 'var(--border)',
|
||||||
color: 'var(--text-primary)'
|
color: 'var(--text-primary)'
|
||||||
}}
|
}}
|
||||||
|
|
@ -136,7 +142,7 @@ export default function Login() {
|
||||||
className={`w-full px-4 py-3 rounded-lg font-medium transition-all duration-200 ${
|
className={`w-full px-4 py-3 rounded-lg font-medium transition-all duration-200 ${
|
||||||
loading
|
loading
|
||||||
? 'opacity-50 cursor-not-allowed'
|
? 'opacity-50 cursor-not-allowed'
|
||||||
: 'gradient-bg-purple text-white hover:shadow-lg transform hover:scale-105'
|
: 'gradient-bg-ember text-white hover:shadow-xl transform hover:scale-105 hover:shadow-orange-500/20'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
|
|
@ -145,13 +151,13 @@ export default function Login() {
|
||||||
Signing in...
|
Signing in...
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
'Sign in'
|
'Sign in to Deck Hearth'
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Quick Login for Testing */}
|
{/* Quick Login for Testing */}
|
||||||
<div className="mt-6 pt-6 border-t" style={{ borderColor: 'var(--border)' }}>
|
<div className="mt-6 pt-6 border-t border-opacity-20" style={{ borderColor: 'var(--border)' }}>
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<p className="text-sm mb-3" style={{ color: 'var(--text-secondary)' }}>
|
<p className="text-sm mb-3" style={{ color: 'var(--text-secondary)' }}>
|
||||||
Quick Login for Testing:
|
Quick Login for Testing:
|
||||||
|
|
@ -160,9 +166,9 @@ export default function Login() {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => handleQuickLogin('admin@tcgvault.com', 'admin123')}
|
onClick={() => handleQuickLogin('admin@tcgvault.com', 'admin123')}
|
||||||
className="px-3 py-2 rounded-lg text-xs font-medium border transition-all duration-200 hover:shadow-md"
|
className="px-3 py-2 rounded-lg text-xs font-medium border border-opacity-20 transition-all duration-200 hover:shadow-md backdrop-blur-sm hover:bg-opacity-80"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: 'var(--bg-primary)',
|
backgroundColor: 'rgba(var(--bg-primary-rgb), 0.6)',
|
||||||
borderColor: 'var(--border)',
|
borderColor: 'var(--border)',
|
||||||
color: 'var(--text-primary)'
|
color: 'var(--text-primary)'
|
||||||
}}
|
}}
|
||||||
|
|
@ -172,9 +178,9 @@ export default function Login() {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => handleQuickLogin('alice@tcgvault.com', 'alice123')}
|
onClick={() => handleQuickLogin('alice@tcgvault.com', 'alice123')}
|
||||||
className="px-3 py-2 rounded-lg text-xs font-medium border transition-all duration-200 hover:shadow-md"
|
className="px-3 py-2 rounded-lg text-xs font-medium border border-opacity-20 transition-all duration-200 hover:shadow-md backdrop-blur-sm hover:bg-opacity-80"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: 'var(--bg-primary)',
|
backgroundColor: 'rgba(var(--bg-primary-rgb), 0.6)',
|
||||||
borderColor: 'var(--border)',
|
borderColor: 'var(--border)',
|
||||||
color: 'var(--text-primary)'
|
color: 'var(--text-primary)'
|
||||||
}}
|
}}
|
||||||
|
|
@ -184,9 +190,9 @@ export default function Login() {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => handleQuickLogin('bob@tcgvault.com', 'bob123')}
|
onClick={() => handleQuickLogin('bob@tcgvault.com', 'bob123')}
|
||||||
className="px-3 py-2 rounded-lg text-xs font-medium border transition-all duration-200 hover:shadow-md"
|
className="px-3 py-2 rounded-lg text-xs font-medium border border-opacity-20 transition-all duration-200 hover:shadow-md backdrop-blur-sm hover:bg-opacity-80"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: 'var(--bg-primary)',
|
backgroundColor: 'rgba(var(--bg-primary-rgb), 0.6)',
|
||||||
borderColor: 'var(--border)',
|
borderColor: 'var(--border)',
|
||||||
color: 'var(--text-primary)'
|
color: 'var(--text-primary)'
|
||||||
}}
|
}}
|
||||||
|
|
@ -206,7 +212,13 @@ export default function Login() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Testing Guide */}
|
{/* Testing Guide */}
|
||||||
<div className="p-4 rounded-xl border" style={{ backgroundColor: 'var(--bg-secondary)', borderColor: 'var(--border)' }}>
|
<div
|
||||||
|
className="p-4 rounded-xl border border-opacity-20 backdrop-blur-sm"
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'rgba(var(--bg-secondary-rgb), 0.6)',
|
||||||
|
borderColor: 'var(--border)'
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<h3 className="text-sm font-semibold mb-2" style={{ color: 'var(--text-primary)' }}>
|
<h3 className="text-sm font-semibold mb-2" style={{ color: 'var(--text-primary)' }}>
|
||||||
🧪 Testing Accounts
|
🧪 Testing Accounts
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,11 @@ body {
|
||||||
--input-border-light: #e8dcc6;
|
--input-border-light: #e8dcc6;
|
||||||
--input-text-light: #2d1810;
|
--input-text-light: #2d1810;
|
||||||
--input-placeholder-light: #5d4037;
|
--input-placeholder-light: #5d4037;
|
||||||
|
|
||||||
|
/* RGB color variables for backdrop-blur effects */
|
||||||
|
--bg-primary-rgb: 254, 252, 248;
|
||||||
|
--bg-secondary-rgb: 247, 243, 237;
|
||||||
|
--bg-tertiary-rgb: 240, 230, 214;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] {
|
[data-theme="dark"] {
|
||||||
|
|
@ -59,6 +64,11 @@ body {
|
||||||
--search-border-dark: #4a2f1f;
|
--search-border-dark: #4a2f1f;
|
||||||
--search-text-dark: #fff8f0;
|
--search-text-dark: #fff8f0;
|
||||||
--search-placeholder-dark: #d7c4b0;
|
--search-placeholder-dark: #d7c4b0;
|
||||||
|
|
||||||
|
/* RGB color variables for backdrop-blur effects */
|
||||||
|
--bg-primary-rgb: 26, 15, 10;
|
||||||
|
--bg-secondary-rgb: 45, 27, 18;
|
||||||
|
--bg-tertiary-rgb: 61, 35, 23;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply theme colors */
|
/* Apply theme colors */
|
||||||
|
|
@ -96,6 +106,11 @@ body {
|
||||||
--input-border: var(--input-border-light);
|
--input-border: var(--input-border-light);
|
||||||
--input-text: var(--input-text-light);
|
--input-text: var(--input-text-light);
|
||||||
--input-placeholder: var(--input-placeholder-light);
|
--input-placeholder: var(--input-placeholder-light);
|
||||||
|
|
||||||
|
/* RGB color variables for backdrop-blur effects */
|
||||||
|
--bg-primary-rgb: 254, 252, 248;
|
||||||
|
--bg-secondary-rgb: 247, 243, 237;
|
||||||
|
--bg-tertiary-rgb: 240, 230, 214;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dark theme variables */
|
/* Dark theme variables */
|
||||||
|
|
@ -172,6 +187,10 @@ body {
|
||||||
background: var(--gradient-secondary);
|
background: var(--gradient-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gradient-bg-ember {
|
||||||
|
background: linear-gradient(135deg, #d84315 0%, #bf360c 100%);
|
||||||
|
}
|
||||||
|
|
||||||
/* Fire glow effects */
|
/* Fire glow effects */
|
||||||
.fire-glow {
|
.fire-glow {
|
||||||
box-shadow: 0 0 20px rgba(255, 111, 0, 0.3);
|
box-shadow: 0 0 20px rgba(255, 111, 0, 0.3);
|
||||||
|
|
@ -698,3 +717,62 @@ body {
|
||||||
.animate-float {
|
.animate-float {
|
||||||
animation: float 4s ease-in-out infinite;
|
animation: float 4s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fire Glow Background Animation */
|
||||||
|
@keyframes fire-glow {
|
||||||
|
0%, 100% {
|
||||||
|
filter: hue-rotate(0deg) brightness(1) saturate(1);
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
filter: hue-rotate(5deg) brightness(1.05) saturate(1.1);
|
||||||
|
transform: scale(1.02);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
filter: hue-rotate(-3deg) brightness(0.98) saturate(1.05);
|
||||||
|
transform: scale(0.99);
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
filter: hue-rotate(8deg) brightness(1.03) saturate(1.08);
|
||||||
|
transform: scale(1.01);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fire-glow-bg {
|
||||||
|
animation: fire-glow 12s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ember Floating Animation */
|
||||||
|
@keyframes ember-float {
|
||||||
|
0% {
|
||||||
|
transform: translateY(0px) translateX(0px) scale(0.8);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
10% {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
20% {
|
||||||
|
transform: translateY(-30px) translateX(15px) scale(1);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
40% {
|
||||||
|
transform: translateY(-60px) translateX(-10px) scale(0.9);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
60% {
|
||||||
|
transform: translateY(-90px) translateX(20px) scale(1.1);
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
80% {
|
||||||
|
transform: translateY(-120px) translateX(-5px) scale(0.8);
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateY(-150px) translateX(10px) scale(0.6);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-ember-float {
|
||||||
|
animation: ember-float 10s linear infinite;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue