/* static/css/effects.css */
/* O××OO× Module Effects System */

/* Effect Wrapper Base */
.effect-wrapper {
    position: relative;
}

/* ============================================
   GLOW EFFECT
   ============================================ */

.effect-glow {
    position: relative;
    transition: box-shadow 0.3s ease;
}

/* Intensity levels */
.effect-glow.intensity-1 { --glow-blur: 10px; --glow-spread: 20px; }
.effect-glow.intensity-2 { --glow-blur: 15px; --glow-spread: 30px; }
.effect-glow.intensity-3 { --glow-blur: 20px; --glow-spread: 40px; }
.effect-glow.intensity-4 { --glow-blur: 25px; --glow-spread: 50px; }
.effect-glow.intensity-5 { --glow-blur: 30px; --glow-spread: 60px; }
.effect-glow.intensity-6 { --glow-blur: 35px; --glow-spread: 70px; }
.effect-glow.intensity-7 { --glow-blur: 40px; --glow-spread: 80px; }
.effect-glow.intensity-8 { --glow-blur: 45px; --glow-spread: 90px; }
.effect-glow.intensity-9 { --glow-blur: 50px; --glow-spread: 100px; }
.effect-glow.intensity-10 { --glow-blur: 60px; --glow-spread: 120px; }

/* Direction variants */
.effect-glow.direction-all {
    box-shadow: 
        0 0 var(--glow-blur) calc(var(--glow-spread) * 0.5) var(--glow-color),
        0 0 calc(var(--glow-blur) * 2) var(--glow-spread) var(--glow-color);
}

.effect-glow.direction-top {
    box-shadow: 
        0 calc(var(--glow-spread) * -0.5) var(--glow-blur) calc(var(--glow-spread) * -0.3) var(--glow-color);
}

.effect-glow.direction-bottom {
    box-shadow: 
        0 calc(var(--glow-spread) * 0.5) var(--glow-blur) calc(var(--glow-spread) * -0.3) var(--glow-color);
}

.effect-glow.direction-left {
    box-shadow: 
        calc(var(--glow-spread) * -0.5) 0 var(--glow-blur) calc(var(--glow-spread) * -0.3) var(--glow-color);
}

.effect-glow.direction-right {
    box-shadow: 
        calc(var(--glow-spread) * 0.5) 0 var(--glow-blur) calc(var(--glow-spread) * -0.3) var(--glow-color);
}

/* Animation variants */
.effect-glow.animate-pulse {
    animation: glow-pulse 2s ease-in-out infinite;
}

.effect-glow.animate-pulse.speed-slow {
    animation-duration: 4s;
}

.effect-glow.animate-pulse.speed-fast {
    animation-duration: 1s;
}

.effect-glow.animate-breathe {
    animation: glow-breathe 3s ease-in-out infinite;
}

.effect-glow.animate-breathe.speed-slow {
    animation-duration: 6s;
}

.effect-glow.animate-breathe.speed-fast {
    animation-duration: 1.5s;
}

@keyframes glow-pulse {
    0%, 100% { 
        filter: brightness(1);
    }
    50% { 
        filter: brightness(1.3);
    }
}

@keyframes glow-breathe {
    0%, 100% { 
        opacity: 0.7;
    }
    50% { 
        opacity: 1;
    }
}

/* Hover enhancement */
.effect-glow:hover {
    filter: brightness(1.1);
}

/* ============================================
   SMOKE EFFECT
   ============================================ */

.effect-smoke {
    position: relative;
    overflow: visible;
}

/* Smoke layers - 2 pseudo-elements with randomized behavior */
.effect-smoke::before,
.effect-smoke::after {
    content: '';
    position: absolute;
    bottom: 0;
    width: 70%;
    height: 100%;
    background: radial-gradient(
        ellipse at 50% 100%,
        var(--smoke-color) 0%,
        transparent 60%
    );
    filter: blur(var(--smoke-blur));
    pointer-events: none;
    z-index: 1;
    opacity: var(--smoke-opacity);
}

.effect-smoke::before {
    left: 45%;
    transform: translateX(-50%);
    animation: smoke-rise-random-1 var(--smoke-speed) ease-out infinite;
}

.effect-smoke::after {
    left: 55%;
    width: 60%;
    height: 85%;
    transform: translateX(-50%);
    animation: smoke-rise-random-2 var(--smoke-speed) ease-out infinite;
    animation-delay: calc(var(--smoke-speed) * -0.35);
    filter: blur(calc(var(--smoke-blur) * 1.3));
}

/* Density levels - control blur and thickness */
.effect-smoke.density-1,
.effect-smoke.density-2,
.effect-smoke.density-3 { 
    --smoke-blur: 12px; 
}

.effect-smoke.density-4,
.effect-smoke.density-5,
.effect-smoke.density-6 { 
    --smoke-blur: 18px; 
}

.effect-smoke.density-7,
.effect-smoke.density-8,
.effect-smoke.density-9,
.effect-smoke.density-10 { 
    --smoke-blur: 24px; 
}

/* Speed variants */
.effect-smoke.speed-slow { --smoke-speed: 7s; }
.effect-smoke.speed-medium { --smoke-speed: 5s; }
.effect-smoke.speed-fast { --smoke-speed: 3s; }

/* Direction variants - override animations */
.effect-smoke.direction-straight::before {
    animation: smoke-rise-straight-1 var(--smoke-speed) ease-out infinite;
}

.effect-smoke.direction-straight::after {
    animation: smoke-rise-straight-2 var(--smoke-speed) ease-out infinite;
    animation-delay: calc(var(--smoke-speed) * -0.35);
}

.effect-smoke.direction-left::before {
    animation: smoke-rise-left-1 var(--smoke-speed) ease-out infinite;
}

.effect-smoke.direction-left::after {
    animation: smoke-rise-left-2 var(--smoke-speed) ease-out infinite;
    animation-delay: calc(var(--smoke-speed) * -0.35);
}

.effect-smoke.direction-right::before {
    animation: smoke-rise-right-1 var(--smoke-speed) ease-out infinite;
}

.effect-smoke.direction-right::after {
    animation: smoke-rise-right-2 var(--smoke-speed) ease-out infinite;
    animation-delay: calc(var(--smoke-speed) * -0.35);
}

/* Randomized smoke rise animations - Layer 1 */
@keyframes smoke-rise-random-1 {
    0% {
        transform: translateX(-50%) translateY(0%) scale(0.9) rotate(0deg);
        opacity: var(--smoke-opacity);
    }
    20% {
        transform: translateX(-48%) translateY(-25%) scale(1) rotate(3deg);
        opacity: calc(var(--smoke-opacity) * 0.9);
    }
    45% {
        transform: translateX(-52%) translateY(-55%) scale(1.2) rotate(-2deg);
        opacity: calc(var(--smoke-opacity) * 0.7);
    }
    70% {
        transform: translateX(-49%) translateY(-85%) scale(1.4) rotate(1deg);
        opacity: calc(var(--smoke-opacity) * 0.4);
    }
    100% {
        transform: translateX(-50%) translateY(-120%) scale(1.6) rotate(0deg);
        opacity: 0;
    }
}

/* Randomized smoke rise animations - Layer 2 */
@keyframes smoke-rise-random-2 {
    0% {
        transform: translateX(-50%) translateY(0%) scale(0.85) rotate(0deg);
        opacity: var(--smoke-opacity);
    }
    25% {
        transform: translateX(-53%) translateY(-30%) scale(1.05) rotate(-4deg);
        opacity: calc(var(--smoke-opacity) * 0.85);
    }
    50% {
        transform: translateX(-47%) translateY(-62%) scale(1.25) rotate(3deg);
        opacity: calc(var(--smoke-opacity) * 0.65);
    }
    75% {
        transform: translateX(-51%) translateY(-90%) scale(1.45) rotate(-1deg);
        opacity: calc(var(--smoke-opacity) * 0.35);
    }
    100% {
        transform: translateX(-50%) translateY(-125%) scale(1.65) rotate(0deg);
        opacity: 0;
    }
}

/* Straight up variants */
@keyframes smoke-rise-straight-1 {
    0% {
        transform: translateX(-50%) translateY(0%) scale(0.9);
        opacity: var(--smoke-opacity);
    }
    100% {
        transform: translateX(-50%) translateY(-120%) scale(1.6);
        opacity: 0;
    }
}

@keyframes smoke-rise-straight-2 {
    0% {
        transform: translateX(-50%) translateY(0%) scale(0.85);
        opacity: var(--smoke-opacity);
    }
    100% {
        transform: translateX(-50%) translateY(-125%) scale(1.65);
        opacity: 0;
    }
}

/* Drift left variants */
@keyframes smoke-rise-left-1 {
    0% {
        transform: translateX(-50%) translateY(0%) scale(0.9) rotate(0deg);
        opacity: var(--smoke-opacity);
    }
    50% {
        transform: translateX(-65%) translateY(-60%) scale(1.2) rotate(-5deg);
        opacity: calc(var(--smoke-opacity) * 0.7);
    }
    100% {
        transform: translateX(-75%) translateY(-120%) scale(1.6) rotate(-8deg);
        opacity: 0;
    }
}

@keyframes smoke-rise-left-2 {
    0% {
        transform: translateX(-50%) translateY(0%) scale(0.85) rotate(0deg);
        opacity: var(--smoke-opacity);
    }
    50% {
        transform: translateX(-62%) translateY(-62%) scale(1.25) rotate(-3deg);
        opacity: calc(var(--smoke-opacity) * 0.65);
    }
    100% {
        transform: translateX(-72%) translateY(-125%) scale(1.65) rotate(-6deg);
        opacity: 0;
    }
}

/* Drift right variants */
@keyframes smoke-rise-right-1 {
    0% {
        transform: translateX(-50%) translateY(0%) scale(0.9) rotate(0deg);
        opacity: var(--smoke-opacity);
    }
    50% {
        transform: translateX(-35%) translateY(-60%) scale(1.2) rotate(5deg);
        opacity: calc(var(--smoke-opacity) * 0.7);
    }
    100% {
        transform: translateX(-25%) translateY(-120%) scale(1.6) rotate(8deg);
        opacity: 0;
    }
}

@keyframes smoke-rise-right-2 {
    0% {
        transform: translateX(-50%) translateY(0%) scale(0.85) rotate(0deg);
        opacity: var(--smoke-opacity);
    }
    50% {
        transform: translateX(-38%) translateY(-62%) scale(1.25) rotate(3deg);
        opacity: calc(var(--smoke-opacity) * 0.65);
    }
    100% {
        transform: translateX(-28%) translateY(-125%) scale(1.65) rotate(6deg);
        opacity: 0;
    }
}

/* Mobile optimizations */
@media (max-width: 768px) {
    .effect-smoke::before,
    .effect-smoke::after {
        height: 80%;
        bottom: 0;
    }
}

/* ============================================
   FIRE EFFECT
   ============================================ */

.effect-fire {
    position: relative;
}

.effect-fire::before,
.effect-fire::after {
    content: '';
    position: absolute;
    inset: -2px;
    background: linear-gradient(45deg, 
        transparent 30%, 
        #ff6b35 50%, 
        #ffd700 60%, 
        transparent 70%);
    background-size: 200% 200%;
    animation: fire-flow 3s linear infinite;
    border-radius: inherit;
    z-index: -1;
    filter: blur(8px);
    opacity: 0.8;
    pointer-events: none;
}

.effect-fire::after {
    animation-delay: -1.5s;
    filter: blur(4px);
}

@keyframes fire-flow {
    0% { background-position: 0% 50%; }
    50% { background-position: 100% 50%; }
    100% { background-position: 0% 50%; }
}

/* Fire Intensity */
.effect-fire.intensity-low::before,
.effect-fire.intensity-low::after {
    opacity: 0.4;
}

.effect-fire.intensity-high::before,
.effect-fire.intensity-high::after {
    opacity: 1;
    filter: blur(12px);
}

/* ============================================
   HOLOGRAM EFFECT
   ============================================ */

.effect-hologram {
    box-shadow: 
        0 0 20px rgba(0, 255, 204, 0.5),
        inset 0 0 20px rgba(0, 255, 204, 0.1);
    filter: brightness(1.1);
    position: relative;
}

.effect-hologram::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
        180deg,
        transparent 0%,
        rgba(0, 255, 204, 0.05) 50%,
        transparent 100%
    );
    animation: hologram-scan 2s linear infinite;
    pointer-events: none;
}

@keyframes hologram-scan {
    0% { transform: translateY(-100%); }
    100% { transform: translateY(100%); }
}

/* ============================================
   GLITCH EFFECT
   ============================================ */

.effect-glitch {
    position: relative;
}

.effect-glitch:hover {
    animation: glitch 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) both infinite;
}

@keyframes glitch {
    0% { transform: translate(0); }
    20% { transform: translate(-2px, 2px); }
    40% { transform: translate(-2px, -2px); }
    60% { transform: translate(2px, 2px); }
    80% { transform: translate(2px, -2px); }
    100% { transform: translate(0); }
}

/* ============================================
   NEON EFFECT
   ============================================ */

.effect-neon {
    box-shadow: 
        0 0 5px var(--glow-color, #00FFCC),
        0 0 10px var(--glow-color, #00FFCC),
        0 0 20px var(--glow-color, #00FFCC),
        inset 0 0 10px var(--glow-color, #00FFCC);
    text-shadow: 0 0 5px var(--glow-color, #00FFCC);
    animation: neon-flicker 1.5s infinite alternate;
}

@keyframes neon-flicker {
    0%, 19%, 21%, 23%, 25%, 54%, 56%, 100% { opacity: 1; }
    20%, 24%, 55% { opacity: 0.85; }
}

/* ============================================
   PROFILE PICTURE EFFECTS
   ============================================ */

.effect-glow .profile-picture {
    box-shadow: 0 0 30px var(--effect-color, var(--toxic));
}

.effect-fire .profile-picture {
    box-shadow: 0 0 40px #ff6b35, 0 0 60px #ffd700;
    animation: fire-pulse 2s infinite;
}

.effect-hologram .profile-picture {
    box-shadow: 0 0 20px rgba(0, 255, 204, 0.5);
    filter: brightness(1.1);
}

.effect-smoke .profile-picture {
    /* Smoke effect on profile pictures - more subtle */
    position: relative;
}

@keyframes fire-pulse {
    0%, 100% { filter: brightness(1); }
    50% { filter: brightness(1.2); }
}

/* ============================================
   HEARTS EFFECT
   ============================================ */

.effect-hearts {
    position: relative;
    overflow: visible;
}

/* Heart shapes using pseudo-elements */
.effect-hearts::before,
.effect-hearts::after {
    content: '';
    position: absolute;
    bottom: -10px;
    width: var(--heart-size, 20px);
    height: var(--heart-size, 20px);
    background: var(--heart-color);
    transform: rotate(-45deg);
    opacity: 0;
    pointer-events: none;
    z-index: 1;
}

/* Create heart shape with rounded top */
.effect-hearts::before {
    left: 30%;
    border-radius: 50% 50% 0 0;
    animation: heart-float-1 var(--heart-speed, 4s) ease-in infinite;
}

.effect-hearts::after {
    left: 60%;
    border-radius: 50% 50% 0 0;
    animation: heart-float-2 var(--heart-speed, 4s) ease-in infinite;
    animation-delay: 2s;
}

/* Add the top curves of the heart */
.effect-hearts::before {
    box-shadow: 
        calc(var(--heart-size, 20px) * 0.5) 0 0 var(--heart-color),
        0 calc(var(--heart-size, 20px) * -0.5) 0 var(--heart-color);
}

.effect-hearts::after {
    box-shadow: 
        calc(var(--heart-size, 20px) * 0.5) 0 0 var(--heart-color),
        0 calc(var(--heart-size, 20px) * -0.5) 0 var(--heart-color);
}

/* Size variants */
.effect-hearts.size-small { --heart-size: 12px; }
.effect-hearts.size-medium { --heart-size: 20px; }
.effect-hearts.size-large { --heart-size: 28px; }

/* Speed variants */
.effect-hearts.speed-slow { --heart-speed: 6s; }
.effect-hearts.speed-medium { --heart-speed: 4s; }
.effect-hearts.speed-fast { --heart-speed: 2s; }

/* Drift variants - no horizontal movement */
@keyframes heart-float-1 {
    0% {
        transform: translateY(0) translateX(0) rotate(-45deg) scale(0.8);
        opacity: 0;
    }
    10% {
        opacity: var(--heart-opacity, 0.7);
    }
    90% {
        opacity: var(--heart-opacity, 0.7);
    }
    100% {
        transform: translateY(-150%) translateX(0) rotate(-45deg) scale(1.2);
        opacity: 0;
    }
}

@keyframes heart-float-2 {
    0% {
        transform: translateY(0) translateX(0) rotate(-45deg) scale(0.8);
        opacity: 0;
    }
    10% {
        opacity: var(--heart-opacity, 0.7);
    }
    90% {
        opacity: var(--heart-opacity, 0.7);
    }
    100% {
        transform: translateY(-150%) translateX(0) rotate(-45deg) scale(1.2);
        opacity: 0;
    }
}

/* Drift subtle - slight left-right movement */
.effect-hearts.drift-subtle::before {
    animation: heart-float-drift-subtle-1 var(--heart-speed, 4s) ease-in-out infinite;
}

.effect-hearts.drift-subtle::after {
    animation: heart-float-drift-subtle-2 var(--heart-speed, 4s) ease-in-out infinite;
    animation-delay: 2s;
}

@keyframes heart-float-drift-subtle-1 {
    0% {
        transform: translateY(0) translateX(0) rotate(-45deg) scale(0.8);
        opacity: 0;
    }
    10% {
        opacity: var(--heart-opacity, 0.7);
    }
    25% {
        transform: translateY(-37.5%) translateX(10px) rotate(-45deg) scale(0.95);
    }
    50% {
        transform: translateY(-75%) translateX(-10px) rotate(-45deg) scale(1.05);
    }
    75% {
        transform: translateY(-112.5%) translateX(10px) rotate(-45deg) scale(1.15);
    }
    90% {
        opacity: var(--heart-opacity, 0.7);
    }
    100% {
        transform: translateY(-150%) translateX(0) rotate(-45deg) scale(1.2);
        opacity: 0;
    }
}

@keyframes heart-float-drift-subtle-2 {
    0% {
        transform: translateY(0) translateX(0) rotate(-45deg) scale(0.8);
        opacity: 0;
    }
    10% {
        opacity: var(--heart-opacity, 0.7);
    }
    25% {
        transform: translateY(-37.5%) translateX(-10px) rotate(-45deg) scale(0.95);
    }
    50% {
        transform: translateY(-75%) translateX(10px) rotate(-45deg) scale(1.05);
    }
    75% {
        transform: translateY(-112.5%) translateX(-10px) rotate(-45deg) scale(1.15);
    }
    90% {
        opacity: var(--heart-opacity, 0.7);
    }
    100% {
        transform: translateY(-150%) translateX(0) rotate(-45deg) scale(1.2);
        opacity: 0;
    }
}

/* Drift wide - larger left-right movement */
.effect-hearts.drift-wide::before {
    animation: heart-float-drift-wide-1 var(--heart-speed, 4s) ease-in-out infinite;
}

.effect-hearts.drift-wide::after {
    animation: heart-float-drift-wide-2 var(--heart-speed, 4s) ease-in-out infinite;
    animation-delay: 2s;
}

@keyframes heart-float-drift-wide-1 {
    0% {
        transform: translateY(0) translateX(0) rotate(-45deg) scale(0.8);
        opacity: 0;
    }
    10% {
        opacity: var(--heart-opacity, 0.7);
    }
    25% {
        transform: translateY(-37.5%) translateX(30px) rotate(-45deg) scale(0.95);
    }
    50% {
        transform: translateY(-75%) translateX(-30px) rotate(-45deg) scale(1.05);
    }
    75% {
        transform: translateY(-112.5%) translateX(30px) rotate(-45deg) scale(1.15);
    }
    90% {
        opacity: var(--heart-opacity, 0.7);
    }
    100% {
        transform: translateY(-150%) translateX(0) rotate(-45deg) scale(1.2);
        opacity: 0;
    }
}

@keyframes heart-float-drift-wide-2 {
    0% {
        transform: translateY(0) translateX(0) rotate(-45deg) scale(0.8);
        opacity: 0;
    }
    10% {
        opacity: var(--heart-opacity, 0.7);
    }
    25% {
        transform: translateY(-37.5%) translateX(-30px) rotate(-45deg) scale(0.95);
    }
    50% {
        transform: translateY(-75%) translateX(30px) rotate(-45deg) scale(1.05);
    }
    75% {
        transform: translateY(-112.5%) translateX(-30px) rotate(-45deg) scale(1.15);
    }
    90% {
        opacity: var(--heart-opacity, 0.7);
    }
    100% {
        transform: translateY(-150%) translateX(0) rotate(-45deg) scale(1.2);
        opacity: 0;
    }
}

/* Mobile optimizations */
@media (max-width: 768px) {
    .effect-hearts::before,
    .effect-hearts::after {
        --heart-size: 16px;
    }
}

/* ============================================
   PONG EFFECT
   ============================================ */

.effect-pong {
    position: relative;
    overflow: hidden;
}

/* Left paddle */
.effect-pong::before {
    content: '';
    position: absolute;
    left: 5%;
    top: 50%;
    width: 4px;
    height: var(--paddle-height, 40px);
    background: var(--pong-color);
    transform: translateY(-50%);
    animation: paddle-left var(--pong-speed, 3s) ease-in-out infinite;
    pointer-events: none;
    z-index: 1;
}

/* Right paddle */
.effect-pong::after {
    content: '';
    position: absolute;
    right: 5%;
    top: 50%;
    width: 4px;
    height: var(--paddle-height, 40px);
    background: var(--pong-color);
    transform: translateY(-50%);
    animation: paddle-right var(--pong-speed, 3s) ease-in-out infinite;
    animation-delay: calc(var(--pong-speed, 3s) * 0.5);
    pointer-events: none;
    z-index: 1;
}

/* Ball - using box-shadow hack to create third pseudo-element effect */
.effect-pong {
    box-shadow: inset 0 0 0 var(--ball-size, 8px) transparent;
}

.effect-pong::before {
    box-shadow: 
        calc(50% - 2px) calc(50% - var(--paddle-height, 40px) / 2) 0 var(--ball-size, 8px) var(--pong-color);
    animation: 
        paddle-left var(--pong-speed, 3s) ease-in-out infinite,
        ball-bounce var(--pong-speed, 3s) linear infinite;
}

/* Paddle size variants */
.effect-pong.paddle-short { --paddle-height: 30px; }
.effect-pong.paddle-medium { --paddle-height: 40px; }
.effect-pong.paddle-long { --paddle-height: 60px; }

/* Speed variants */
.effect-pong.speed-slow { --pong-speed: 5s; }
.effect-pong.speed-medium { --pong-speed: 3s; }
.effect-pong.speed-fast { --pong-speed: 2s; }

/* Ball trail effect */
.effect-pong.with-trail::before {
    filter: blur(2px);
}

/* Paddle animations */
@keyframes paddle-left {
    0%, 100% {
        transform: translateY(-50%) translateY(-30px);
    }
    50% {
        transform: translateY(-50%) translateY(30px);
    }
}

@keyframes paddle-right {
    0%, 100% {
        transform: translateY(-50%) translateY(30px);
    }
    50% {
        transform: translateY(-50%) translateY(-30px);
    }
}

/* Ball bounce animation */
@keyframes ball-bounce {
    0% {
        box-shadow: 
            15% 20% 0 var(--ball-size, 8px) var(--pong-color);
    }
    25% {
        box-shadow: 
            50% 50% 0 var(--ball-size, 8px) var(--pong-color);
    }
    50% {
        box-shadow: 
            85% 80% 0 var(--ball-size, 8px) var(--pong-color);
    }
    75% {
        box-shadow: 
            50% 50% 0 var(--ball-size, 8px) var(--pong-color);
    }
    100% {
        box-shadow: 
            15% 20% 0 var(--ball-size, 8px) var(--pong-color);
    }
}

/* Mobile optimizations */
@media (max-width: 768px) {
    .effect-pong::before,
    .effect-pong::after {
        width: 3px;
    }
    .effect-pong { --ball-size: 6px; }
}

/* ============================================
   GLITCH EFFECT
   ============================================ */

.effect-glitch {
    position: relative;
}

/* Intensity levels affect displacement */
.effect-glitch.intensity-1 { --glitch-amount: 2px; }
.effect-glitch.intensity-2 { --glitch-amount: 3px; }
.effect-glitch.intensity-3 { --glitch-amount: 4px; }
.effect-glitch.intensity-4 { --glitch-amount: 5px; }
.effect-glitch.intensity-5 { --glitch-amount: 6px; }
.effect-glitch.intensity-6 { --glitch-amount: 7px; }
.effect-glitch.intensity-7 { --glitch-amount: 8px; }
.effect-glitch.intensity-8 { --glitch-amount: 10px; }
.effect-glitch.intensity-9 { --glitch-amount: 12px; }
.effect-glitch.intensity-10 { --glitch-amount: 15px; }

/* RGB split effect using box-shadow */
.effect-glitch.with-color-shift {
    position: relative;
}

.effect-glitch.with-color-shift::before,
.effect-glitch.with-color-shift::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    mix-blend-mode: screen;
    opacity: 0;
}

.effect-glitch.with-color-shift::before {
    background: rgba(255, 0, 0, 0.7);
}

.effect-glitch.with-color-shift::after {
    background: rgba(0, 255, 255, 0.7);
}

/* Trigger: Always */
.effect-glitch.trigger-always {
    animation: glitch-shift var(--glitch-duration, 0.3s) infinite;
}

.effect-glitch.trigger-always.with-color-shift::before {
    animation: glitch-channel-red var(--glitch-duration, 0.3s) infinite;
}

.effect-glitch.trigger-always.with-color-shift::after {
    animation: glitch-channel-cyan var(--glitch-duration, 0.3s) infinite;
}

/* Trigger: Hover */
.effect-glitch.trigger-hover:hover {
    animation: glitch-shift var(--glitch-duration, 0.3s) infinite;
}

.effect-glitch.trigger-hover:hover.with-color-shift::before {
    animation: glitch-channel-red var(--glitch-duration, 0.3s) infinite;
}

.effect-glitch.trigger-hover:hover.with-color-shift::after {
    animation: glitch-channel-cyan var(--glitch-duration, 0.3s) infinite;
}

/* Trigger: Random */
.effect-glitch.trigger-random {
    animation: glitch-shift-random 8s infinite;
}

.effect-glitch.trigger-random.with-color-shift::before {
    animation: glitch-channel-red-random 8s infinite;
}

.effect-glitch.trigger-random.with-color-shift::after {
    animation: glitch-channel-cyan-random 8s infinite;
}

/* Speed/Frequency variants */
.effect-glitch.speed-slow { --glitch-duration: 0.5s; }
.effect-glitch.speed-medium { --glitch-duration: 0.3s; }
.effect-glitch.speed-fast { --glitch-duration: 0.15s; }

/* Style: Position Shift */
@keyframes glitch-shift {
    0%, 100% { 
        transform: translate(0, 0); 
    }
    20% { 
        transform: translate(calc(var(--glitch-amount) * -1), var(--glitch-amount)); 
    }
    40% { 
        transform: translate(var(--glitch-amount), calc(var(--glitch-amount) * -1)); 
    }
    60% { 
        transform: translate(calc(var(--glitch-amount) * -1), calc(var(--glitch-amount) * -1)); 
    }
    80% { 
        transform: translate(var(--glitch-amount), var(--glitch-amount)); 
    }
}

/* RGB channel animations */
@keyframes glitch-channel-red {
    0%, 100% { 
        opacity: 0;
        transform: translate(0, 0); 
    }
    20%, 80% { 
        opacity: 0.7;
        transform: translate(calc(var(--glitch-amount) * -1), 0); 
    }
}

@keyframes glitch-channel-cyan {
    0%, 100% { 
        opacity: 0;
        transform: translate(0, 0); 
    }
    20%, 80% { 
        opacity: 0.7;
        transform: translate(var(--glitch-amount), 0); 
    }
}

/* Random trigger animations - glitch happens at specific intervals */
@keyframes glitch-shift-random {
    0%, 15%, 85%, 100% { 
        transform: translate(0, 0); 
    }
    16% { 
        transform: translate(calc(var(--glitch-amount) * -1), var(--glitch-amount)); 
    }
    17% { 
        transform: translate(var(--glitch-amount), calc(var(--glitch-amount) * -1)); 
    }
    18% { 
        transform: translate(0, 0); 
    }
}

@keyframes glitch-channel-red-random {
    0%, 15%, 19%, 85%, 100% { 
        opacity: 0; 
    }
    16%, 18% { 
        opacity: 0.7;
        transform: translate(calc(var(--glitch-amount) * -1), 0); 
    }
}

@keyframes glitch-channel-cyan-random {
    0%, 15%, 19%, 85%, 100% { 
        opacity: 0; 
    }
    16%, 18% { 
        opacity: 0.7;
        transform: translate(var(--glitch-amount), 0); 
    }
}

/* Style: Data Corruption (uses clip-path) */
.effect-glitch.style-corruption {
    animation: glitch-corruption var(--glitch-duration, 0.3s) infinite;
}

@keyframes glitch-corruption {
    0%, 100% { 
        clip-path: inset(0 0 0 0); 
    }
    10% { 
        clip-path: inset(20% 0 0 0); 
    }
    20% { 
        clip-path: inset(0 0 80% 0); 
    }
    30% { 
        clip-path: inset(40% 0 0 0); 
    }
    40% { 
        clip-path: inset(0 0 60% 0); 
    }
    50% { 
        clip-path: inset(0 0 0 0); 
    }
}

/* Mobile optimizations */
@media (max-width: 768px) {
    .effect-glitch {
        --glitch-amount: calc(var(--glitch-amount) * 0.7);
    }
}

/* ============================================
   RIPPLE EFFECT
   ============================================ */

.effect-ripple {
    position: relative;
    overflow: hidden;
}

/* Three ripple layers with staggered delays */
.effect-ripple::before,
.effect-ripple::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 0;
    height: 0;
    border-radius: 50%;
    border: 2px solid var(--ripple-base);
    opacity: 0;
    transform: translate(-50%, -50%);
    pointer-events: none;
}

.effect-ripple::before {
    animation: ripple-expand var(--ripple-duration, 3s) ease-out infinite;
}

.effect-ripple::after {
    animation: ripple-expand var(--ripple-duration, 3s) ease-out infinite;
    animation-delay: 1s;
}

/* Third ripple using background gradient
.effect-ripple {
    background-image: 
        radial-gradient(circle, var(--ripple-color) 0%, transparent 70%);
    background-size: 0% 0%;
    background-position: center;
    background-repeat: no-repeat;
    animation: ripple-bg var(--ripple-duration, 3s) ease-out infinite;
    animation-delay: 2s;
} */

/* Ripple expansion animation */
@keyframes ripple-expand {
    0% {
        width: 0;
        height: 0;
        opacity: 1;
    }
    50% {
        opacity: var(--fade-midpoint, 0.6);
    }
    100% {
        width: 200%;
        height: 200%;
        opacity: 0;
    }
}

@keyframes ripple-bg {
    0% {
        background-size: 0% 0%;
        opacity: 1;
    }
    50% {
        opacity: var(--fade-midpoint-bg, 0.3);
    }
    100% {
        background-size: 200% 200%;
        opacity: 0;
    }
}

/* Fade amount variants - controls how quickly ripples fade */
.effect-ripple.fade-1 { --fade-midpoint: 0.2; --fade-midpoint-bg: 0.1; }
.effect-ripple.fade-2 { --fade-midpoint: 0.3; --fade-midpoint-bg: 0.15; }
.effect-ripple.fade-3 { --fade-midpoint: 0.4; --fade-midpoint-bg: 0.2; }
.effect-ripple.fade-4 { --fade-midpoint: 0.5; --fade-midpoint-bg: 0.25; }
.effect-ripple.fade-5 { --fade-midpoint: 0.6; --fade-midpoint-bg: 0.3; }
.effect-ripple.fade-6 { --fade-midpoint: 0.7; --fade-midpoint-bg: 0.35; }
.effect-ripple.fade-7 { --fade-midpoint: 0.8; --fade-midpoint-bg: 0.4; }
.effect-ripple.fade-8 { --fade-midpoint: 0.85; --fade-midpoint-bg: 0.45; }
.effect-ripple.fade-9 { --fade-midpoint: 0.9; --fade-midpoint-bg: 0.5; }
.effect-ripple.fade-10 { --fade-midpoint: 0.95; --fade-midpoint-bg: 0.55; }

/* Intensity variants */
.effect-ripple.intensity-1 { --ripple-opacity: 0.15; }
.effect-ripple.intensity-2 { --ripple-opacity: 0.2; }
.effect-ripple.intensity-3 { --ripple-opacity: 0.25; }
.effect-ripple.intensity-4 { --ripple-opacity: 0.3; }
.effect-ripple.intensity-5 { --ripple-opacity: 0.35; }
.effect-ripple.intensity-6 { --ripple-opacity: 0.4; }
.effect-ripple.intensity-7 { --ripple-opacity: 0.45; }
.effect-ripple.intensity-8 { --ripple-opacity: 0.5; }
.effect-ripple.intensity-9 { --ripple-opacity: 0.55; }
.effect-ripple.intensity-10 { --ripple-opacity: 0.6; }

/* Speed variants */
.effect-ripple.speed-slow {
    --ripple-duration: 4s;
}

.effect-ripple.speed-medium {
    --ripple-duration: 3s;
}

.effect-ripple.speed-fast {
    --ripple-duration: 2s;
}

/* Higher intensity = thicker borders */
.effect-ripple.intensity-7::before,
.effect-ripple.intensity-7::after {
    border-width: 3px;
}

.effect-ripple.intensity-9::before,
.effect-ripple.intensity-9::after {
    border-width: 4px;
}

.effect-ripple.intensity-10::before,
.effect-ripple.intensity-10::after {
    border-width: 5px;
}

/* Mobile optimizations - reduce complexity */
@media (max-width: 768px) {
    .effect-ripple {
        background-image: none; /* Remove third ripple on mobile */
    }
    
    .effect-ripple::before,
    .effect-ripple::after {
        border-width: 2px !important; /* Consistent border */
    }
    
    /* Faster animation on mobile for performance */
    .effect-ripple.speed-slow {
        --ripple-duration: 3s;
    }
    
    .effect-ripple.speed-medium {
        --ripple-duration: 2.5s;
    }
}

/* Hover state - pause animation */
.effect-ripple:hover::before,
.effect-ripple:hover::after {
    animation-play-state: paused;
}

/* ============================================
   SNOW EFFECT (JavaScript-based)
   ============================================ */

.effect-snow {
    position: relative;
    overflow: hidden;
}

@keyframes snowfall {
    0% {
        top: -10%;
        transform: translateX(0) rotate(0deg);
        opacity: 0;
    }
    10% {
        opacity: 1;
    }
    25% {
        transform: translateX(10px) rotate(90deg);
    }
    50% {
        transform: translateX(-5px) rotate(180deg);
    }
    75% {
        transform: translateX(8px) rotate(270deg);
    }
    90% {
        opacity: 1;
    }
    100% {
        top: 110%;
        transform: translateX(0) rotate(360deg);
        opacity: 0;
    }
}

// static/js/starry-sky.js
// Random twinkling stars effect

(function() {
    function initStarrySky() {
        const containers = document.querySelectorAll('.effect-starry-sky');
        
        containers.forEach(container => {
            // Skip if already initialized
            if (container.querySelector('.star')) return;
            
            // Get config from data attributes or CSS variables
            const density = parseInt(container.classList.toString().match(/density-(\d+)/)?.[1] || '5');
            const starColor = getComputedStyle(container).getPropertyValue('--star-color').trim() || '#ffffff';
            const twinkleSpeed = container.classList.toString().match(/twinkle-(slow|medium|fast)/)?.[1] || 'medium';
            const rotateSpeed = container.classList.toString().match(/rotate-(none|slow|medium|fast)/)?.[1] || 'medium';
            
            // Calculate number of stars based on density (5-50 stars)
            const starCount = Math.floor(density * 5);
            
            // Twinkle duration ranges
            const twinkleDurations = {
                slow: [3, 5],
                medium: [1.5, 3],
                fast: [0.8, 1.5]
            };
            
            // Rotation duration
            const rotateDurations = {
                none: 0,
                slow: 120,
                medium: 60,
                fast: 30
            };
            
            const [minTwinkle, maxTwinkle] = twinkleDurations[twinkleSpeed];
            const rotateDuration = rotateDurations[rotateSpeed];
            
            // Create star container
            const starContainer = document.createElement('div');
            starContainer.className = 'stars-container';
            starContainer.style.cssText = `
                position: absolute;
                inset: 0;
                pointer-events: none;
                z-index: 1;
                ${rotateDuration ? `animation: starry-sky-rotate ${rotateDuration}s linear infinite;` : ''}
            `;
            
            // Generate stars
            for (let i = 0; i < starCount; i++) {
                const star = document.createElement('span');
                star.className = 'star';
                
                // Random position
                const x = Math.random() * 100;
                const y = Math.random() * 100;
                
                // Random size (1-3px)
                const size = Math.floor(Math.random() * 3) + 1;
                
                // Random twinkle duration
                const duration = minTwinkle + Math.random() * (maxTwinkle - minTwinkle);
                
                // Random delay
                const delay = Math.random() * duration;
                
                // Random opacity range
                const minOpacity = 0.2 + Math.random() * 0.2;
                const maxOpacity = 0.7 + Math.random() * 0.3;
                
                star.style.cssText = `
                    position: absolute;
                    left: ${x}%;
                    top: ${y}%;
                    width: ${size}px;
                    height: ${size}px;
                    background: ${starColor};
                    border-radius: 50%;
                    box-shadow: 0 0 ${size * 2}px ${starColor};
                    animation: star-twinkle-${i} ${duration}s ease-in-out infinite;
                    animation-delay: ${delay}s;
                    --min-opacity: ${minOpacity};
                    --max-opacity: ${maxOpacity};
                `;
                
                // Create unique keyframe animation for this star
                const keyframeName = `star-twinkle-${i}`;
                if (!document.getElementById(`starry-keyframes-${i}`)) {
                    const style = document.createElement('style');
                    style.id = `starry-keyframes-${i}`;
                    style.textContent = `
                        @keyframes ${keyframeName} {
                            0%, 100% { opacity: var(--min-opacity, 0.3); }
                            50% { opacity: var(--max-opacity, 1); }
                        }
                    `;
                    document.head.appendChild(style);
                }
                
                starContainer.appendChild(star);
            }
            
            container.appendChild(starContainer);
        });
    }
    
    // Initialize on page load
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initStarrySky);
    } else {
        initStarrySky();
    }
    
    // Re-initialize on HTMX content swap (for module editing)
    document.addEventListener('htmx:afterSwap', initStarrySky);
})();/* ============================================
   STARRY SKY EFFECT
   Replace existing starry sky section in: static/css/effects.css
   ============================================ */

.effect-starry-sky {
    position: relative;
    overflow: hidden;
}

/* Star field layer - rotates */
.effect-starry-sky::before {
    content: '';
    position: absolute;
    inset: 0;
    background-image: 
        radial-gradient(2px 2px at 20% 30%, var(--star-color), transparent),
        radial-gradient(2px 2px at 60% 70%, var(--star-color), transparent),
        radial-gradient(1px 1px at 50% 50%, var(--star-color), transparent),
        radial-gradient(1px 1px at 80% 10%, var(--star-color), transparent),
        radial-gradient(2px 2px at 90% 60%, var(--star-color), transparent),
        radial-gradient(1px 1px at 33% 80%, var(--star-color), transparent),
        radial-gradient(2px 2px at 70% 40%, var(--star-color), transparent),
        radial-gradient(1px 1px at 15% 55%, var(--star-color), transparent),
        radial-gradient(2px 2px at 45% 15%, var(--star-color), transparent),
        radial-gradient(1px 1px at 85% 85%, var(--star-color), transparent);
    background-size: 100% 100%;
    background-repeat: no-repeat;
    animation-name: starry-sky-rotate, starry-sky-twinkle;
    animation-duration: var(--rotate-speed), var(--twinkle-speed);
    animation-timing-function: linear, ease-in-out;
    animation-iteration-count: infinite, infinite;
    z-index: 1;
    pointer-events: none;
}

/* Additional star layer for more density */
.effect-starry-sky::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image: 
        radial-gradient(1px 1px at 25% 40%, var(--star-color), transparent),
        radial-gradient(2px 2px at 55% 65%, var(--star-color), transparent),
        radial-gradient(1px 1px at 75% 25%, var(--star-color), transparent),
        radial-gradient(2px 2px at 40% 85%, var(--star-color), transparent),
        radial-gradient(1px 1px at 10% 10%, var(--star-color), transparent),
        radial-gradient(2px 2px at 95% 45%, var(--star-color), transparent),
        radial-gradient(1px 1px at 65% 90%, var(--star-color), transparent),
        radial-gradient(1px 1px at 30% 20%, var(--star-color), transparent);
    background-size: 100% 100%;
    background-repeat: no-repeat;
    animation-name: starry-sky-rotate, starry-sky-twinkle;
    animation-duration: var(--rotate-speed), var(--twinkle-speed);
    animation-timing-function: linear, ease-in-out;
    animation-iteration-count: infinite, infinite;
    animation-delay: 0s, 1s;
    animation-direction: reverse, normal;
    z-index: 1;
    pointer-events: none;
}

/* Rotation animation */
@keyframes starry-sky-rotate {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

/* Twinkle animation */
@keyframes starry-sky-twinkle {
    0%, 100% { opacity: 0.3; }
    50% { opacity: 1; }
}

/* Rotation speed variants */
.effect-starry-sky.rotate-none {
    --rotate-speed: 0s;
}

.effect-starry-sky.rotate-none::before,
.effect-starry-sky.rotate-none::after {
    animation-name: starry-sky-twinkle;
    animation-duration: var(--twinkle-speed);
}

.effect-starry-sky.rotate-slow {
    --rotate-speed: 120s;
}

.effect-starry-sky.rotate-medium {
    --rotate-speed: 60s;
}

.effect-starry-sky.rotate-fast {
    --rotate-speed: 30s;
}

/* Twinkle speed variants */
.effect-starry-sky.twinkle-slow {
    --twinkle-speed: 4s;
}

.effect-starry-sky.twinkle-medium {
    --twinkle-speed: 2s;
}

.effect-starry-sky.twinkle-fast {
    --twinkle-speed: 1s;
}

/* Density variants - uses twinkle animation opacity range */
.effect-starry-sky.density-1 {
    --density-min: 0.03;
    --density-max: 0.1;
}

.effect-starry-sky.density-2 {
    --density-min: 0.06;
    --density-max: 0.2;
}

.effect-starry-sky.density-3 {
    --density-min: 0.09;
    --density-max: 0.3;
}

.effect-starry-sky.density-4 {
    --density-min: 0.12;
    --density-max: 0.4;
}

.effect-starry-sky.density-5 {
    --density-min: 0.15;
    --density-max: 0.5;
}

.effect-starry-sky.density-6 {
    --density-min: 0.18;
    --density-max: 0.6;
}

.effect-starry-sky.density-7 {
    --density-min: 0.21;
    --density-max: 0.7;
}

.effect-starry-sky.density-8 {
    --density-min: 0.24;
    --density-max: 0.8;
}

.effect-starry-sky.density-9 {
    --density-min: 0.27;
    --density-max: 0.9;
}

.effect-starry-sky.density-10 {
    --density-min: 0.3;
    --density-max: 1;
}

/* Apply density to twinkle animation */
@keyframes starry-sky-twinkle {
    0%, 100% { opacity: var(--density-min, 0.3); }
    50% { opacity: var(--density-max, 1); }
}

/* Mobile optimizations - reduce complexity */
@media (max-width: 768px) {
    .effect-starry-sky::after {
        display: none;
    }
    
    .effect-starry-sky::before {
        animation-duration: calc(var(--rotate-speed) * 1.5), var(--twinkle-speed);
    }
}

/* ============================================
   STARRY SKY EFFECT
   Replace existing starry sky section in: static/css/effects.css
   ============================================ */

.effect-starry-sky {
    position: relative;
    overflow: hidden;
}

/* Stars are generated by JavaScript - see static/js/starry-sky.js */

/* Rotation animation for star container */
@keyframes starry-sky-rotate {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

/* Rotation speed variants */
.effect-starry-sky.rotate-none {
    --rotate-speed: 0s;
}

.effect-starry-sky.rotate-none::before,
.effect-starry-sky.rotate-none::after {
    animation-name: starry-sky-twinkle;
    animation-duration: var(--twinkle-speed);
}

.effect-starry-sky.rotate-slow {
    --rotate-speed: 120s;
}

.effect-starry-sky.rotate-medium {
    --rotate-speed: 60s;
}

.effect-starry-sky.rotate-fast {
    --rotate-speed: 30s;
}

/* Twinkle speed variants */
.effect-starry-sky.twinkle-slow {
    --twinkle-speed: 4s;
}

.effect-starry-sky.twinkle-medium {
    --twinkle-speed: 2s;
}

.effect-starry-sky.twinkle-fast {
    --twinkle-speed: 1s;
}

/* Density variants - uses twinkle animation opacity range */
.effect-starry-sky.density-1 {
    --density-min: 0.03;
    --density-max: 0.1;
}

.effect-starry-sky.density-2 {
    --density-min: 0.06;
    --density-max: 0.2;
}

.effect-starry-sky.density-3 {
    --density-min: 0.09;
    --density-max: 0.3;
}

.effect-starry-sky.density-4 {
    --density-min: 0.12;
    --density-max: 0.4;
}

.effect-starry-sky.density-5 {
    --density-min: 0.15;
    --density-max: 0.5;
}

.effect-starry-sky.density-6 {
    --density-min: 0.18;
    --density-max: 0.6;
}

.effect-starry-sky.density-7 {
    --density-min: 0.21;
    --density-max: 0.7;
}

.effect-starry-sky.density-8 {
    --density-min: 0.24;
    --density-max: 0.8;
}

.effect-starry-sky.density-9 {
    --density-min: 0.27;
    --density-max: 0.9;
}

.effect-starry-sky.density-10 {
    --density-min: 0.3;
    --density-max: 1;
}

/* Apply density to twinkle animation */
@keyframes starry-sky-twinkle {
    0%, 100% { opacity: var(--density-min, 0.3); }
    50% { opacity: var(--density-max, 1); }
}

/* Mobile optimizations - reduce complexity */
@media (max-width: 768px) {
    .effect-starry-sky::after {
        display: none;
    }
    
    .effect-starry-sky::before {
        animation-duration: calc(var(--rotate-speed) * 1.5), var(--twinkle-speed);
    }
}

/* ============================================
   FIREWORKS EFFECT
   Add to: static/css/effects.css
   ============================================ */

.effect-fireworks {
    position: relative;
    overflow: visible;
}

/* Cursor styling based on trigger */
.effect-fireworks.trigger-hover {
    cursor: pointer;
}

.effect-fireworks.trigger-click {
    cursor: crosshair;
}

/* Particle base styling (applied via JavaScript) */
.firework-particle {
    will-change: transform, opacity;
}

/* Sparkle animation for particles */
@keyframes sparkle-twinkle {
    0%, 100% { 
        opacity: 1;
        filter: brightness(1);
    }
    50% { 
        opacity: 0.3;
        filter: brightness(1.5);
    }
}

/* Hover state indicator for hover trigger */
.effect-fireworks.trigger-hover::before {
    content: '';
    position: absolute;
    inset: 0;
    border: 2px solid transparent;
    border-radius: inherit;
    transition: border-color 0.3s ease;
    pointer-events: none;
}

.effect-fireworks.trigger-hover:hover::before {
    border-color: rgba(255, 215, 0, 0.3);
}

/* Click feedback for click trigger */
.effect-fireworks.trigger-click:active {
    transform: scale(0.98);
    transition: transform 0.1s ease;
}

/* Mobile optimizations */
@media (max-width: 768px) {
    .effect-fireworks {
        overflow: hidden; /* Prevent particles from extending beyond viewport */
    }
    
    /* Reduce particle trails on mobile for performance */
    .firework-particle {
        box-shadow: none !important;
    }
}

/* Accessibility - reduce motion */
@media (prefers-reduced-motion: reduce) {
    .effect-fireworks.trigger-always {
        /* Disable continuous animation if user prefers reduced motion */
        pointer-events: auto;
    }
    
    .firework-particle {
        animation: none !important;
        transition: opacity 0.3s ease !important;
    }
}
