/* =========================================================
   SPECIAL FX — decorative, pure-CSS, class-only effects
   =========================================================

   HOW TO USE
   -----------------------------------------------------------
   Just add one class to any element:

       <div class="hero-banner snowfall">...</div>
       <div class="card fireworks">...</div>
       <div class="footer seawave">...</div>

   No extra markup, no JavaScript. Effects render on ::before /
   ::after layers, so your element's real content is untouched
   and still selectable/clickable.

   WHY THIS DOESN'T HURT UI/UX
   -----------------------------------------------------------
   - pointer-events: none on every effect layer — clicks, taps,
     text-selection and form inputs underneath keep working.
   - isolation: isolate — gives the element its own stacking
     context so the effect's z-index can never fight with the
     rest of the page's layering.
   - Low default opacity + `mix-blend-mode` where helpful, so
     text/content on top stays readable.
   - overflow: hidden on the effect host — the effect always
     stays clipped inside the element, never spills onto layout.
   - One `prefers-reduced-motion` block turns every animation
     off for people who've asked their OS for reduced motion.
   - Effects are GPU-friendly (transform/opacity/background-
     position only) — no layout thrashing, no jank.

   Combine with utility modifiers below (e.g. `snowfall--light`)
   to tune intensity for busy vs. quiet parts of a page.
   ========================================================= */


/* ---------------------------------------------------------
   Shared base for every fx host element
   --------------------------------------------------------- */

.snowfall,
.fireworks,
.seawave,
.leaffall,
.thunderstorm,
.bubbles,
.sparkle,
.confetti {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

.snowfall::before,
.snowfall::after,
.fireworks::before,
.fireworks::after,
.seawave::before,
.seawave::after,
.leaffall::before,
.leaffall::after,
.thunderstorm::before,
.thunderstorm::after,
.bubbles::before,
.bubbles::after,
.sparkle::before,
.sparkle::after,
.confetti::before,
.confetti::after {
    content: "";
    position: absolute;
    pointer-events: none;
    z-index: 5;
}


/* =========================================================
   1. SNOWFALL — gentle falling snow inside the element
   ========================================================= */

.snowfall::before,
.snowfall::after {
    inset: 0;
    background-repeat: repeat;
    animation: fx-snow-fall linear infinite;
    will-change: background-position;
}

.snowfall::before {
    background-image:
            radial-gradient(2px 2px at 20px 30px, #fff, transparent 65%),
            radial-gradient(1.5px 1.5px at 80px 90px, #fff, transparent 65%),
            radial-gradient(2.5px 2.5px at 140px 50px, #fff, transparent 65%),
            radial-gradient(1.5px 1.5px at 200px 120px, #fff, transparent 65%);
    background-size: 220px 220px;
    opacity: .85;
    animation-duration: 9s;
}

.snowfall::after {
    background-image:
            radial-gradient(1px 1px at 40px 60px, #fff, transparent 65%),
            radial-gradient(2px 2px at 120px 20px, #fff, transparent 65%),
            radial-gradient(1px 1px at 170px 150px, #fff, transparent 65%);
    background-size: 190px 190px;
    opacity: .55;
    animation-duration: 14s;
    animation-delay: -4s; /* stagger so both layers don't sync */
}

@keyframes fx-snow-fall {
    from { background-position: 0 0; }
    to   { background-position: 0 220px; } /* one full tile = seamless loop */
}

/* Intensity modifiers */
.snowfall--light::before  { opacity: .45; }
.snowfall--light::after   { opacity: .3; }
.snowfall--heavy::before  { opacity: 1; animation-duration: 6s; }
.snowfall--heavy::after   { opacity: .75; animation-duration: 9s; }


/* =========================================================
   2. FIREWORKS — soft recurring bursts inside the element
   ========================================================= */

.fireworks::before,
.fireworks::after {
    width: 90px;
    height: 90px;
    margin: -45px;
    border-radius: 50%;
    opacity: 0;
    animation: fx-firework-burst 2.6s cubic-bezier(.2, .7, .3, 1) infinite;
}

/* 8-point spark pattern inside a 90x90 box, two color themes */
.fireworks::before {
    top: 30%;
    left: 28%;
    background-image:
            radial-gradient(circle 3px at 84px 45px, #ffd76a, transparent 70%),
            radial-gradient(circle 3px at 73px 73px, #ffd76a, transparent 70%),
            radial-gradient(circle 3px at 45px 84px, #ffd76a, transparent 70%),
            radial-gradient(circle 3px at 17px 73px, #ffd76a, transparent 70%),
            radial-gradient(circle 3px at 6px 45px, #ffd76a, transparent 70%),
            radial-gradient(circle 3px at 17px 17px, #ffd76a, transparent 70%),
            radial-gradient(circle 3px at 45px 6px, #ffd76a, transparent 70%),
            radial-gradient(circle 3px at 73px 17px, #ffd76a, transparent 70%),
            radial-gradient(circle 6px at 45px 45px, #fff6d9, transparent 60%);
    animation-delay: 0s;
}

.fireworks::after {
    top: 55%;
    left: 62%;
    background-image:
            radial-gradient(circle 3px at 84px 45px, #7fe7ff, transparent 70%),
            radial-gradient(circle 3px at 73px 73px, #7fe7ff, transparent 70%),
            radial-gradient(circle 3px at 45px 84px, #7fe7ff, transparent 70%),
            radial-gradient(circle 3px at 17px 73px, #7fe7ff, transparent 70%),
            radial-gradient(circle 3px at 6px 45px, #7fe7ff, transparent 70%),
            radial-gradient(circle 3px at 17px 17px, #7fe7ff, transparent 70%),
            radial-gradient(circle 3px at 45px 6px, #7fe7ff, transparent 70%),
            radial-gradient(circle 3px at 73px 17px, #7fe7ff, transparent 70%),
            radial-gradient(circle 6px at 45px 45px, #e3faff, transparent 60%);
    animation-delay: 1.3s; /* offset so the two bursts alternate */
}

@keyframes fx-firework-burst {
    0%   { transform: scale(.15); opacity: 0; }
    12%  { opacity: 1; }
    45%  { opacity: .8; }
    100% { transform: scale(1.35); opacity: 0; }
}


/* =========================================================
   3. SEAWAVE — a rolling wave along the bottom of the element
   ========================================================= */

.seawave::before,
.seawave::after {
    left: 0;
    right: 0;
    bottom: 0;
    height: 45%;
    background-repeat: repeat-x;
    background-size: 400px 100%;
    background-position: 0 bottom;
    will-change: background-position;
}

.seawave::before {
    opacity: .55;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='60' viewBox='0 0 400 60'%3E%3Cpath d='M0 30 Q 50 5 100 30 T 200 30 T 300 30 T 400 30 V60 H0 Z' fill='%2338bdf8'/%3E%3C/svg%3E");
    animation: fx-wave-scroll 7s linear infinite;
}

.seawave::after {
    opacity: .35;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='60' viewBox='0 0 400 60'%3E%3Cpath d='M0 34 Q 50 12 100 34 T 200 34 T 300 34 T 400 34 V60 H0 Z' fill='%230ea5e9'/%3E%3C/svg%3E");
    animation: fx-wave-scroll 11s linear infinite reverse;
}

@keyframes fx-wave-scroll {
    from { background-position-x: 0; }
    to   { background-position-x: -400px; } /* one tile width = seamless loop */
}


/* =========================================================
   4. LEAFFALL — autumn leaves drifting down and sideways
   ========================================================= */

.leaffall::before,
.leaffall::after {
    inset: 0;
    background-repeat: repeat;
    animation: fx-leaf-fall linear infinite;
    will-change: background-position;
}

.leaffall::before {
    background-image:
            radial-gradient(5px 3px at 30px 40px, #d97706, transparent 70%),
            radial-gradient(4px 3px at 110px 90px, #b45309, transparent 70%),
            radial-gradient(5px 3px at 170px 30px, #ca8a04, transparent 70%),
            radial-gradient(4px 3px at 220px 130px, #a16207, transparent 70%);
    background-size: 240px 240px;
    opacity: .8;
    animation-duration: 10s;
}

.leaffall::after {
    background-image:
            radial-gradient(4px 3px at 60px 70px, #dc2626, transparent 70%),
            radial-gradient(5px 3px at 150px 20px, #ea580c, transparent 70%),
            radial-gradient(4px 3px at 200px 100px, #b91c1c, transparent 70%);
    background-size: 210px 210px;
    opacity: .55;
    animation-duration: 15s;
    animation-delay: -5s;
}

/* Drifts diagonally (down + sideways) to read as wind-blown, not just falling */
@keyframes fx-leaf-fall {
    from { background-position: 0 0; }
    to   { background-position: -60px 240px; }
}

.leaffall--light::before { opacity: .4; }
.leaffall--light::after  { opacity: .25; }


/* =========================================================
   5. THUNDERSTORM — falling rain with occasional lightning
   ========================================================= */

.thunderstorm::before {
    inset: 0;
    background-image: repeating-linear-gradient(
            100deg,
            rgba(210, 230, 255, .55) 0px,
            rgba(210, 230, 255, .55) 1px,
            transparent 1px,
            transparent 16px
    );
    background-size: 220px 220px;
    animation: fx-rain-fall .85s linear infinite;
    will-change: background-position;
}

.thunderstorm::after {
    inset: 0;
    background: radial-gradient(ellipse at 50% 0%, #fff, rgba(255, 255, 255, 0) 70%);
    opacity: 0;
    mix-blend-mode: screen; /* brightens instead of flattening content underneath */
    animation: fx-lightning-flash 6.5s ease-in-out infinite;
}

@keyframes fx-rain-fall {
    from { background-position: 0 -20px; }
    to   { background-position: -40px 220px; }
}

/* Two quick flickers, then a longer dark pause — reads as real lightning */
@keyframes fx-lightning-flash {
    0%, 89%, 100% { opacity: 0; }
    90%           { opacity: .85; }
    91%           { opacity: .1; }
    92%           { opacity: .65; }
    93%           { opacity: 0; }
}

.thunderstorm--calm::before { opacity: .5; animation-duration: 1.4s; }
.thunderstorm--calm::after  { animation-duration: 10s; }


/* =========================================================
   6. BUBBLES — rising bubbles (aquarium / soda style)
   ========================================================= */

.bubbles::before,
.bubbles::after {
    inset: 0;
    background-repeat: repeat;
    animation: fx-bubbles-rise linear infinite;
    will-change: background-position;
}

.bubbles::before {
    background-image:
            radial-gradient(circle 5px at 30px 200px, transparent 55%, rgba(255,255,255,.75) 56% 62%, transparent 64%),
            radial-gradient(circle 3px at 100px 140px, transparent 55%, rgba(255,255,255,.75) 56% 62%, transparent 64%),
            radial-gradient(circle 6px at 170px 210px, transparent 55%, rgba(255,255,255,.7) 56% 62%, transparent 64%);
    background-size: 220px 220px;
    opacity: .8;
    animation-duration: 8s;
}

.bubbles::after {
    background-image:
            radial-gradient(circle 4px at 60px 180px, transparent 55%, rgba(255,255,255,.65) 56% 62%, transparent 64%),
            radial-gradient(circle 3px at 150px 120px, transparent 55%, rgba(255,255,255,.65) 56% 62%, transparent 64%);
    background-size: 190px 190px;
    opacity: .55;
    animation-duration: 12s;
    animation-delay: -3s;
}

/* Moves upward (negative Y) — the opposite direction of snow/leaves */
@keyframes fx-bubbles-rise {
    from { background-position: 0 0; }
    to   { background-position: 0 -220px; }
}


/* =========================================================
   7. SPARKLE — twinkling stardust, no motion, just shimmer
   ========================================================= */

.sparkle::before,
.sparkle::after {
    inset: 0;
    background-repeat: repeat;
    animation: fx-twinkle ease-in-out infinite;
}

.sparkle::before {
    background-image:
            radial-gradient(1.5px 1.5px at 25px 35px, #fff, transparent 70%),
            radial-gradient(2px 2px at 90px 80px, #ffe9a8, transparent 70%),
            radial-gradient(1.5px 1.5px at 150px 40px, #fff, transparent 70%),
            radial-gradient(2px 2px at 190px 120px, #ffe9a8, transparent 70%);
    background-size: 210px 210px;
    animation-duration: 2.4s;
}

.sparkle::after {
    background-image:
            radial-gradient(1.5px 1.5px at 55px 100px, #fff, transparent 70%),
            radial-gradient(2px 2px at 130px 30px, #ffe9a8, transparent 70%),
            radial-gradient(1.5px 1.5px at 175px 150px, #fff, transparent 70%);
    background-size: 230px 230px;
    animation-duration: 3.1s;
    animation-delay: -1.2s; /* out of phase so not every dot twinkles in unison */
}

@keyframes fx-twinkle {
    0%, 100% { opacity: .25; }
    50%      { opacity: 1; }
}


/* =========================================================
   8. CONFETTI — festive falling multi-color pieces
   ========================================================= */

.confetti::before,
.confetti::after {
    inset: 0;
    background-repeat: repeat;
    animation: fx-confetti-fall linear infinite;
    will-change: background-position;
}

.confetti::before {
    background-image:
            radial-gradient(3px 3px at 25px 30px, #ef4444, transparent 70%),
            radial-gradient(3px 3px at 80px 90px, #3b82f6, transparent 70%),
            radial-gradient(3px 3px at 140px 50px, #22c55e, transparent 70%),
            radial-gradient(3px 3px at 190px 130px, #eab308, transparent 70%),
            radial-gradient(3px 3px at 60px 160px, #ec4899, transparent 70%);
    background-size: 220px 220px;
    opacity: .9;
    animation-duration: 5.5s;
}

.confetti::after {
    background-image:
            radial-gradient(3px 3px at 45px 70px, #06b6d4, transparent 70%),
            radial-gradient(3px 3px at 120px 20px, #f97316, transparent 70%),
            radial-gradient(3px 3px at 170px 150px, #a855f7, transparent 70%);
    background-size: 190px 190px;
    opacity: .65;
    animation-duration: 8s;
    animation-delay: -2.5s;
}

@keyframes fx-confetti-fall {
    from { background-position: 0 0; }
    to   { background-position: 40px 220px; }
}


/* =========================================================
   ACCESSIBILITY — respect reduced-motion preference
   ========================================================= */

@media (prefers-reduced-motion: reduce) {
    .snowfall::before,
    .snowfall::after,
    .fireworks::before,
    .fireworks::after,
    .seawave::before,
    .seawave::after,
    .leaffall::before,
    .leaffall::after,
    .thunderstorm::before,
    .thunderstorm::after,
    .bubbles::before,
    .bubbles::after,
    .sparkle::before,
    .sparkle::after,
    .confetti::before,
    .confetti::after {
        animation: none !important;
    }

    /* Keep a faint static hint of the effect instead of nothing */
    .snowfall::before     { opacity: .3; }
    .snowfall::after      { opacity: .15; }
    .fireworks::before,
    .fireworks::after     { opacity: .25; transform: scale(1); }
    .seawave::before      { opacity: .3; }
    .seawave::after       { opacity: .18; }
    .leaffall::before     { opacity: .3; }
    .leaffall::after      { opacity: .15; }
    .thunderstorm::before { opacity: .2; }
    .thunderstorm::after  { opacity: 0; }
    .bubbles::before      { opacity: .3; }
    .bubbles::after       { opacity: .15; }
    .sparkle::before,
    .sparkle::after       { opacity: .35; }
    .confetti::before     { opacity: .3; }
    .confetti::after      { opacity: .15; }
}