323 lines
7.6 KiB
SCSS
323 lines
7.6 KiB
SCSS
// ============================================
|
|
// STANDALONE ARCADE JOYSTICK ELEMENT
|
|
// Decorative joystick with neon arcade aesthetics
|
|
// ============================================
|
|
|
|
.joystick-element {
|
|
width: 100%;
|
|
aspect-ratio: 1 / 1;
|
|
container-type: inherit;
|
|
position: relative;
|
|
display: flex;
|
|
align-items: flex-end;
|
|
justify-content: center;
|
|
//padding: 10% 20%;
|
|
//margin: 2rem auto;
|
|
perspective: 800px;
|
|
max-width: 250px;
|
|
margin: auto;
|
|
|
|
// Ground shadow for depth
|
|
&::before {
|
|
content: "";
|
|
position: absolute;
|
|
bottom: 15%;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 80%;
|
|
height: 20%;
|
|
background: radial-gradient(
|
|
ellipse at center,
|
|
rgba(0, 0, 0, 0.6) 0%,
|
|
rgba(0, 0, 0, 0.4) 40%,
|
|
transparent 70%
|
|
);
|
|
border-radius: 50%;
|
|
filter: blur(0.5cqw);
|
|
z-index: -1;
|
|
}
|
|
|
|
.joystick-housing {
|
|
position: absolute;
|
|
bottom: 25%;
|
|
left: 50%;
|
|
transform: translateX(-50%) rotateX(25deg);
|
|
transform-style: preserve-3d;
|
|
width: 50%;
|
|
height: 20%;
|
|
background: linear-gradient(
|
|
180deg,
|
|
#0a0a0a 0%,
|
|
#1a1a1a 10%,
|
|
#2a2a2a 50%,
|
|
#3a3a3a 70%,
|
|
#4a4a4a 90%
|
|
);
|
|
border-radius: 1.5cqw 1.5cqw 0.5cqw 0.5cqw;
|
|
box-shadow:
|
|
inset 0 0.8cqw 1.5cqw rgba(255, 255, 255, 0.08),
|
|
inset 0 -0.8cqw 1.5cqw rgba(0, 0, 0, 0.4);
|
|
z-index: 1;
|
|
|
|
&::before {
|
|
content: "";
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 35%;
|
|
transform: rotateX(-55deg);
|
|
background: linear-gradient(
|
|
180deg,
|
|
rgba(255, 255, 255, 0.1) 0%,
|
|
rgba(255, 255, 255, 0.03) 20%,
|
|
transparent 50%,
|
|
rgba(0, 0, 0, 0.2) 100%
|
|
);
|
|
border-radius: 1cqw;
|
|
pointer-events: none;
|
|
}
|
|
}
|
|
|
|
.joystick-base {
|
|
position: absolute;
|
|
bottom: 30%;
|
|
left: 50%;
|
|
transform: translateX(-50%) translateY(-50%);
|
|
width: 20%;
|
|
height: 8%;
|
|
background: radial-gradient(
|
|
ellipse at center,
|
|
#3a3a3a 0%,
|
|
#2a2a2a 40%,
|
|
#1a1a1a 70%,
|
|
#0a0a0a 100%
|
|
);
|
|
border-radius: 50%;
|
|
box-shadow:
|
|
0 0 2cqw rgba(0, 255, 255, 0.2),
|
|
0 0.8cqw 2cqw rgba(0, 0, 0, 0.8),
|
|
inset 0 0.5cqw 1.5cqw rgba(0, 0, 0, 0.9),
|
|
inset 0 -0.3cqw 0.8cqw rgba(255, 255, 255, 0.08);
|
|
z-index: 2;
|
|
|
|
&::before {
|
|
content: none;
|
|
}
|
|
|
|
// Mounting screws
|
|
&::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 15%;
|
|
transform: translateY(-50%);
|
|
width: 8%;
|
|
aspect-ratio: 1 / 1;
|
|
background: radial-gradient(
|
|
circle at 30% 30%,
|
|
#4a4a4a 0%,
|
|
#2a2a2a 50%,
|
|
#1a1a1a 100%
|
|
);
|
|
border-radius: 50%;
|
|
box-shadow:
|
|
inset 0 0.15cqw 0.3cqw rgba(0, 0, 0, 0.9),
|
|
inset 0 -0.08cqw 0.15cqw rgba(255, 255, 255, 0.15);
|
|
}
|
|
}
|
|
|
|
.joystick-stick {
|
|
position: absolute;
|
|
bottom: 37%;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 5%;
|
|
height: 20%;
|
|
background: linear-gradient(
|
|
90deg,
|
|
#5a5a5a 0%,
|
|
#4a4a4a 30%,
|
|
#3a3a3a 50%,
|
|
#2a2a2a 70%,
|
|
#1a1a1a 100%
|
|
);
|
|
border-radius: 50% / 8%;
|
|
box-shadow:
|
|
-0.4cqw 0 1cqw rgba(0, 0, 0, 0.7),
|
|
0.4cqw 0 0.8cqw rgba(255, 255, 255, 0.1),
|
|
inset 0.2cqw 0 0.5cqw rgba(255, 255, 255, 0.08),
|
|
inset -0.2cqw 0 0.5cqw rgba(0, 0, 0, 0.6);
|
|
transform-origin: bottom center;
|
|
animation: joystick-idle-sway 4s ease-in-out infinite;
|
|
z-index: 3;
|
|
}
|
|
|
|
.joystick-ball {
|
|
position: absolute;
|
|
top: -30%;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
aspect-ratio: 1 / 1;
|
|
width: 300%;
|
|
height: auto;
|
|
background: radial-gradient(
|
|
circle at 35% 35%,
|
|
#7dffff 0%,
|
|
#00ffff 40%,
|
|
#00cccc 70%,
|
|
#00aaaa 100%
|
|
);
|
|
border-radius: 50%;
|
|
box-shadow:
|
|
0 0 2cqw rgba(0, 255, 255, 0.9),
|
|
0 0 4cqw rgba(0, 255, 255, 0.7),
|
|
0 0 6cqw rgba(0, 255, 255, 0.4),
|
|
0 1cqw 2cqw rgba(0, 0, 0, 0.8),
|
|
inset -0.5cqw -0.5cqw 1cqw rgba(0, 0, 0, 0.6),
|
|
inset 0.5cqw 0.5cqw 1cqw rgba(125, 255, 255, 0.7);
|
|
animation: joystick-neon-pulse 3s ease-in-out infinite;
|
|
z-index: 4;
|
|
}
|
|
|
|
// ============================================
|
|
// ANIMATIONS
|
|
// ============================================
|
|
|
|
// Gentle swaying motion
|
|
@keyframes joystick-idle-sway {
|
|
0%,
|
|
100% {
|
|
transform: translateX(-50%) rotate(0deg);
|
|
}
|
|
25% {
|
|
transform: translateX(-50%) rotate(-3deg);
|
|
}
|
|
50% {
|
|
transform: translateX(-50%) rotate(0deg);
|
|
}
|
|
75% {
|
|
transform: translateX(-50%) rotate(3deg);
|
|
}
|
|
}
|
|
|
|
// Pulsing neon glow
|
|
@keyframes joystick-neon-pulse {
|
|
0%,
|
|
100% {
|
|
filter: brightness(1);
|
|
}
|
|
50% {
|
|
filter: brightness(1.2);
|
|
}
|
|
}
|
|
|
|
// Optional: Color cycling animation
|
|
@keyframes joystick-color-cycle {
|
|
0%,
|
|
100% {
|
|
background: radial-gradient(
|
|
circle at 35% 35%,
|
|
#7dffff 0%,
|
|
#00ffff 40%,
|
|
#00cccc 70%,
|
|
#00aaaa 100%
|
|
);
|
|
box-shadow:
|
|
0 0 1.5cqw rgba(0, 255, 255, 0.8),
|
|
0 0 3cqw rgba(0, 255, 255, 0.6),
|
|
0 0 5cqw rgba(0, 255, 255, 0.4),
|
|
0 0.8cqw 1.5cqw rgba(0, 0, 0, 0.7),
|
|
inset -0.3cqw -0.3cqw 0.8cqw rgba(0, 0, 0, 0.5),
|
|
inset 0.3cqw 0.3cqw 0.8cqw rgba(125, 255, 255, 0.6);
|
|
}
|
|
33% {
|
|
background: radial-gradient(
|
|
circle at 35% 35%,
|
|
#ff7dff 0%,
|
|
#ff00ff 40%,
|
|
#cc00cc 70%,
|
|
#aa00aa 100%
|
|
);
|
|
box-shadow:
|
|
0 0 1.5cqw rgba(255, 0, 255, 0.8),
|
|
0 0 3cqw rgba(255, 0, 255, 0.6),
|
|
0 0 5cqw rgba(255, 0, 255, 0.4),
|
|
0 0.8cqw 1.5cqw rgba(0, 0, 0, 0.7),
|
|
inset -0.3cqw -0.3cqw 0.8cqw rgba(0, 0, 0, 0.5),
|
|
inset 0.3cqw 0.3cqw 0.8cqw rgba(255, 125, 255, 0.6);
|
|
}
|
|
66% {
|
|
background: radial-gradient(
|
|
circle at 35% 35%,
|
|
#ffff7d 0%,
|
|
#ffff00 40%,
|
|
#cccc00 70%,
|
|
#aaaa00 100%
|
|
);
|
|
box-shadow:
|
|
0 0 1.5cqw rgba(255, 255, 0, 0.8),
|
|
0 0 3cqw rgba(255, 255, 0, 0.6),
|
|
0 0 5cqw rgba(255, 255, 0, 0.4),
|
|
0 0.8cqw 1.5cqw rgba(0, 0, 0, 0.7),
|
|
inset -0.3cqw -0.3cqw 0.8cqw rgba(0, 0, 0, 0.5),
|
|
inset 0.3cqw 0.3cqw 0.8cqw rgba(255, 255, 125, 0.6);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================
|
|
// COLOR VARIANTS
|
|
// ============================================
|
|
|
|
.joystick-element.magenta .joystick-ball {
|
|
background: radial-gradient(
|
|
circle at 35% 35%,
|
|
#ff7dff 0%,
|
|
#ff00ff 40%,
|
|
#cc00cc 70%,
|
|
#aa00aa 100%
|
|
);
|
|
box-shadow:
|
|
0 0 1.5cqw rgba(255, 0, 255, 0.8),
|
|
0 0 3cqw rgba(255, 0, 255, 0.6),
|
|
0 0 5cqw rgba(255, 0, 255, 0.4),
|
|
0 0.8cqw 1.5cqw rgba(0, 0, 0, 0.7),
|
|
inset -0.3cqw -0.3cqw 0.8cqw rgba(0, 0, 0, 0.5),
|
|
inset 0.3cqw 0.3cqw 0.8cqw rgba(255, 125, 255, 0.6);
|
|
}
|
|
|
|
.joystick-element.yellow .joystick-ball {
|
|
background: radial-gradient(
|
|
circle at 35% 35%,
|
|
#ffff7d 0%,
|
|
#ffff00 40%,
|
|
#cccc00 70%,
|
|
#aaaa00 100%
|
|
);
|
|
box-shadow:
|
|
0 0 1.5cqw rgba(255, 255, 0, 0.8),
|
|
0 0 3cqw rgba(255, 255, 0, 0.6),
|
|
0 0 5cqw rgba(255, 255, 0, 0.4),
|
|
0 0.8cqw 1.5cqw rgba(0, 0, 0, 0.7),
|
|
inset -0.3cqw -0.3cqw 0.8cqw rgba(0, 0, 0, 0.5),
|
|
inset 0.3cqw 0.3cqw 0.8cqw rgba(255, 255, 125, 0.6);
|
|
}
|
|
|
|
// Apply color cycle animation to modifier class
|
|
.joystick-element.color-cycle .joystick-ball {
|
|
animation:
|
|
joystick-color-cycle 6s ease-in-out infinite,
|
|
joystick-neon-pulse 3s ease-in-out infinite;
|
|
}
|
|
|
|
// ============================================
|
|
// ACCESSIBILITY
|
|
// ============================================
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.joystick-stick,
|
|
.joystick-ball {
|
|
animation: none;
|
|
}
|
|
}
|