Add animated gradient borders to realm cards and a live stats strip
Introduce animated gradient borders to IsometricRealmCard components by utilizing CSS variables and keyframe animations. Add a new "stats-strip" section to IsometricRealmSelector, displaying live project and realm statistics with responsive styling and a pulsing "Live Now" indicator. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 9203795e-937a-4306-b81d-b4d5c78c240e Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Event-Id: f769b2fa-c72d-498f-83ea-b1732d640dca Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7c94b7a0-29c7-4f2e-94ef-44b2153872b7/9203795e-937a-4306-b81d-b4d5c78c240e/QlSIsyp Replit-Helium-Checkpoint-Created: true
This commit is contained in:
parent
f6aed18d13
commit
0b978908a3
3 changed files with 150 additions and 10 deletions
8
.replit
8
.replit
|
|
@ -52,6 +52,10 @@ externalPort = 80
|
||||||
localPort = 8044
|
localPort = 8044
|
||||||
externalPort = 3003
|
externalPort = 3003
|
||||||
|
|
||||||
|
[[ports]]
|
||||||
|
localPort = 38223
|
||||||
|
externalPort = 3002
|
||||||
|
|
||||||
[[ports]]
|
[[ports]]
|
||||||
localPort = 38557
|
localPort = 38557
|
||||||
externalPort = 3000
|
externalPort = 3000
|
||||||
|
|
@ -60,10 +64,6 @@ externalPort = 3000
|
||||||
localPort = 40437
|
localPort = 40437
|
||||||
externalPort = 3001
|
externalPort = 3001
|
||||||
|
|
||||||
[[ports]]
|
|
||||||
localPort = 43575
|
|
||||||
externalPort = 3002
|
|
||||||
|
|
||||||
[deployment]
|
[deployment]
|
||||||
deploymentTarget = "autoscale"
|
deploymentTarget = "autoscale"
|
||||||
run = ["node", "dist/server/production.mjs"]
|
run = ["node", "dist/server/production.mjs"]
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,8 @@ export default function IsometricRealmCard({
|
||||||
boxShadow: isHovered
|
boxShadow: isHovered
|
||||||
? `0 25px 50px -12px ${realm.color}40, 0 0 0 1px ${realm.color}60, inset 0 1px 0 ${realm.color}20`
|
? `0 25px 50px -12px ${realm.color}40, 0 0 0 1px ${realm.color}60, inset 0 1px 0 ${realm.color}20`
|
||||||
: `0 10px 40px -15px ${realm.color}20`,
|
: `0 10px 40px -15px ${realm.color}20`,
|
||||||
}}
|
'--card-color': realm.color,
|
||||||
|
} as CSSProperties}
|
||||||
>
|
>
|
||||||
{/* Floating icon layer */}
|
{/* Floating icon layer */}
|
||||||
<div
|
<div
|
||||||
|
|
@ -218,15 +219,54 @@ export default function IsometricRealmCard({
|
||||||
border: 2px solid;
|
border: 2px solid;
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
145deg,
|
145deg,
|
||||||
rgba(15, 23, 42, 0.9) 0%,
|
hsl(var(--muted) / 0.9) 0%,
|
||||||
rgba(30, 41, 59, 0.7) 50%,
|
hsl(var(--card) / 0.7) 50%,
|
||||||
rgba(15, 23, 42, 0.9) 100%
|
hsl(var(--muted) / 0.9) 100%
|
||||||
);
|
);
|
||||||
backdrop-filter: blur(12px);
|
backdrop-filter: blur(12px);
|
||||||
transform-style: preserve-3d;
|
transform-style: preserve-3d;
|
||||||
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-surface::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: -2px;
|
||||||
|
border-radius: 22px;
|
||||||
|
padding: 2px;
|
||||||
|
background: linear-gradient(
|
||||||
|
var(--gradient-angle, 0deg),
|
||||||
|
transparent 0%,
|
||||||
|
var(--card-color) 25%,
|
||||||
|
transparent 50%,
|
||||||
|
var(--card-color) 75%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||||
|
mask-composite: exclude;
|
||||||
|
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||||
|
-webkit-mask-composite: xor;
|
||||||
|
opacity: 0;
|
||||||
|
animation: borderRotate 4s linear infinite;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.realm-card:hover .card-surface::before {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property --gradient-angle {
|
||||||
|
syntax: '<angle>';
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 0deg;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes borderRotate {
|
||||||
|
0% { --gradient-angle: 0deg; }
|
||||||
|
100% { --gradient-angle: 360deg; }
|
||||||
|
}
|
||||||
|
|
||||||
.card-icon-layer {
|
.card-icon-layer {
|
||||||
transform-style: preserve-3d;
|
transform-style: preserve-3d;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|
@ -257,7 +297,7 @@ export default function IsometricRealmCard({
|
||||||
|
|
||||||
.card-description {
|
.card-description {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #94a3b8;
|
color: hsl(var(--muted-foreground));
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,7 +314,7 @@ export default function IsometricRealmCard({
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #cbd5e1;
|
color: hsl(var(--foreground) / 0.8);
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,34 @@ export default function IsometricRealmSelector() {
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Live Stats Strip */}
|
||||||
|
<motion.div
|
||||||
|
className="stats-strip"
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.6, delay: 0.3 }}
|
||||||
|
>
|
||||||
|
<div className="stat-item">
|
||||||
|
<span className="stat-number">12,000+</span>
|
||||||
|
<span className="stat-label">Builders</span>
|
||||||
|
</div>
|
||||||
|
<div className="stat-divider" />
|
||||||
|
<div className="stat-item">
|
||||||
|
<span className="stat-number">500+</span>
|
||||||
|
<span className="stat-label">Projects</span>
|
||||||
|
</div>
|
||||||
|
<div className="stat-divider" />
|
||||||
|
<div className="stat-item">
|
||||||
|
<span className="stat-number">7</span>
|
||||||
|
<span className="stat-label">Realms</span>
|
||||||
|
</div>
|
||||||
|
<div className="stat-divider" />
|
||||||
|
<div className="stat-item">
|
||||||
|
<span className="stat-number pulse-dot">●</span>
|
||||||
|
<span className="stat-label">Live Now</span>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
<motion.div
|
<motion.div
|
||||||
className="hero-text"
|
className="hero-text"
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
|
@ -427,6 +455,60 @@ export default function IsometricRealmSelector() {
|
||||||
box-shadow: 0 0 20px hsl(var(--neon-blue) / 0.2);
|
box-shadow: 0 0 20px hsl(var(--neon-blue) / 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stats-strip {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 24px;
|
||||||
|
margin-bottom: 48px;
|
||||||
|
padding: 16px 32px;
|
||||||
|
background: hsl(var(--muted) / 0.4);
|
||||||
|
border: 1px solid hsl(var(--border) / 0.3);
|
||||||
|
border-radius: 12px;
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
max-width: 600px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-number {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: hsl(var(--foreground));
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: hsl(var(--muted-foreground));
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-divider {
|
||||||
|
width: 1px;
|
||||||
|
height: 32px;
|
||||||
|
background: hsl(var(--border) / 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pulse-dot {
|
||||||
|
color: hsl(120, 100%, 50%);
|
||||||
|
animation: pulse 2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%, 100% { opacity: 1; }
|
||||||
|
50% { opacity: 0.4; }
|
||||||
|
}
|
||||||
|
|
||||||
.hero-text {
|
.hero-text {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 40px;
|
margin-bottom: 40px;
|
||||||
|
|
@ -501,6 +583,24 @@ export default function IsometricRealmSelector() {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stats-strip {
|
||||||
|
gap: 16px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-number {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-divider {
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.hero-text {
|
.hero-text {
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue