.effects-layer{position:absolute;inset:0;pointer-events:none;z-index:50;overflow:hidden;border-radius:inherit}
.balloon{position:absolute;width:40px;height:50px;opacity:0.9;will-change:transform;animation:riseUp var(--duration,15s) linear forwards}
.balloon-body{width:100%;height:100%;border-radius:50% 50% 50% 50%/40% 40% 60% 60%;background:var(--balloon-color);position:relative}
.balloon-shine{position:absolute;width:35%;height:30%;background:rgba(255,255,255,0.55);border-radius:50%;top:14%;left:18%;filter:blur(2px)}
.balloon-knot{position:absolute;top:100%;left:50%;transform:translateX(-50%);width:0;height:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:5px solid var(--balloon-color)}
.balloon-string{position:absolute;top:calc(100% + 5px);left:50%;width:1px;height:38px;background:rgba(0,0,0,0.25);transform:translateX(-50%)}
@keyframes riseUp{0%{transform:translateY(0) translateX(0) rotate(-2deg);opacity:0}10%{opacity:0.9}33%{transform:translateY(-40vh) translateX(calc(var(--drift)*0.4)) rotate(2deg)}66%{transform:translateY(-80vh) translateX(calc(var(--drift)*0.7)) rotate(-2deg)}100%{transform:translateY(-120vh) translateX(var(--drift)) rotate(1deg);opacity:0}}
.confetti{position:absolute;width:8px;height:8px;background:var(--col);will-change:transform;animation:tumble var(--duration,4s) linear forwards}
.confetti-circle{border-radius:50%}
.confetti-ribbon{width:4px;height:14px}
@keyframes tumble{0%{top:-10px;transform:translateX(0) rotate(0deg)}20%{transform:translateX(var(--side-drift)) rotate(72deg)}40%{transform:translateX(0) rotate(144deg)}60%{transform:translateX(calc(var(--side-drift)*-0.8)) rotate(216deg)}80%{transform:translateX(calc(var(--side-drift)*0.4)) rotate(288deg)}100%{top:110%;transform:translateX(0) rotate(360deg)}}
.snowflake{position:absolute;color:#e9f6ff;will-change:transform;animation:fall var(--duration,12s) linear forwards;text-shadow:0 0 4px rgba(200,230,255,0.9),0 0 10px rgba(100,180,255,0.4),0 0 1px rgba(0,0,0,0.35)}
@keyframes fall{0%{transform:translateY(0) translateX(0);opacity:0}8%{opacity:var(--opacity,0.9)}25%{transform:translateY(25vh) translateX(calc(var(--wind-drift)*0.5))}50%{transform:translateY(50vh) translateX(var(--wind-drift))}75%{transform:translateY(75vh) translateX(calc(var(--wind-drift)*0.3))}92%{opacity:var(--opacity,0.9)}100%{transform:translateY(110vh) translateX(0);opacity:0}}
.heart-container{position:absolute;will-change:transform;animation:floatHeart var(--duration,10s) ease-in forwards}
.heart-shape{width:var(--heart-size,18px);height:var(--heart-size,18px);background:var(--heart-color,#e74c3c);position:relative;transform:rotate(-45deg);filter:drop-shadow(0 0 3px var(--heart-color))}
.heart-shape::before,.heart-shape::after{content:'';position:absolute;width:100%;height:100%;border-radius:50%;background:inherit}
.heart-shape::before{top:-50%;left:0}
.heart-shape::after{left:50%;top:0}
@keyframes floatHeart{0%{bottom:-30px;transform:translateX(0) rotate(-8deg);opacity:0}10%{opacity:1}25%{transform:translateX(calc(var(--drift)*0.25)) rotate(8deg)}50%{transform:translateX(calc(var(--drift)*0.55)) rotate(-5deg)}75%{transform:translateX(calc(var(--drift)*0.8)) rotate(5deg)}90%{opacity:1}100%{bottom:110%;transform:translateX(var(--drift)) rotate(-2deg);opacity:0}}
.firework-trail{position:absolute;width:3px;height:35px;background:linear-gradient(to top,transparent,var(--col));animation:launch 0.7s ease-out forwards;opacity:0;transform-origin:bottom center}
.firework-flash{position:absolute;width:10px;height:10px;border-radius:50%;background:white;box-shadow:0 0 8px 4px var(--col);transform:translate(-50%,-50%);animation:burst-flash 0.35s ease-out forwards;pointer-events:none}
.firework-particle{position:absolute;width:4px;height:4px;border-radius:50%;background:var(--col);box-shadow:0 0 5px var(--col);will-change:transform,opacity;animation:explode var(--dur,1.5s) ease-out forwards}
@keyframes launch{0%{bottom:0;opacity:1}80%{opacity:0.8}100%{bottom:60%;opacity:0}}
@keyframes burst-flash{0%{transform:translate(-50%,-50%) scale(1);opacity:1}100%{transform:translate(-50%,-50%) scale(4);opacity:0}}
@keyframes explode{0%{transform:translate(0,0);opacity:1}60%{opacity:0.9}100%{transform:translate(var(--tx),var(--ty));opacity:0}}
.bubble{position:absolute;border-radius:50%;background:radial-gradient(circle at 30% 28%,rgba(255,255,255,0.94),rgba(176,212,255,0.58) 42%,rgba(118,178,250,0.30));border:1.5px solid rgba(122,178,242,0.88);box-shadow:inset 0 0 7px rgba(255,255,255,0.48),0 0 0 1px rgba(0,0,0,0.14),0 1px 5px rgba(0,0,0,0.14);will-change:transform;animation:riseBubble var(--duration,12s) linear forwards,bubblePulse var(--shimmer-dur,4s) ease-in-out infinite}
@keyframes riseBubble{0%{bottom:-50px;transform:translateX(0) scale(0.8);opacity:0}8%{opacity:0.88;transform:translateX(0) scale(1)}50%{transform:translateX(calc(var(--drift)*0.6))}100%{bottom:120%;transform:translateX(var(--drift)) scale(0.9);opacity:0}}
@keyframes bubblePulse{0%,100%{opacity:0.88}50%{opacity:0.72}}
.star-container{position:absolute;will-change:transform;animation:twinkle var(--twinkle-dur,2.5s) ease-in-out var(--cycles,3);animation-delay:var(--delay,0s);animation-fill-mode:forwards}
.star-shape{width:var(--star-size,18px);height:var(--star-size,18px);background:var(--star-color,#FFD700);clip-path:polygon(50% 0%,61% 35%,98% 35%,68% 57%,79% 91%,50% 70%,21% 91%,32% 57%,2% 35%,39% 35%);filter:drop-shadow(0 0 4px var(--star-color))}
@keyframes twinkle{0%,100%{opacity:0.15;transform:scale(0.5) rotate(0deg)}50%{opacity:1;transform:scale(1.3) rotate(20deg)}}
.leaf{position:absolute;will-change:transform;animation:leafFall var(--duration,10s) ease-in forwards}
.leaf-shape{width:var(--leaf-w,12px);height:var(--leaf-h,20px);background:var(--leaf-color,#c0702b);border-radius:2px 50% 2px 50%;position:relative;filter:drop-shadow(0 1px 2px rgba(0,0,0,0.15))}
.leaf-shape::after{content:'';position:absolute;top:45%;left:15%;width:70%;height:1px;background:rgba(255,255,255,0.25);transform:rotate(-20deg)}
@keyframes leafFall{0%{top:-20px;transform:translateX(0) rotate(0deg)}15%{transform:translateX(var(--sway)) rotate(45deg)}30%{transform:translateX(0) rotate(90deg)}45%{transform:translateX(calc(var(--sway)*-0.8)) rotate(135deg)}60%{transform:translateX(var(--sway)) rotate(200deg)}75%{transform:translateX(0) rotate(260deg)}90%{transform:translateX(calc(var(--sway)*-0.5)) rotate(320deg)}100%{top:110%;transform:translateX(0) rotate(360deg)}}
