/* ==========================================================================
   Festive theme layer  —  STRUCTURE ONLY
   --------------------------------------------------------------------------
   One stylesheet serves every festival. Nothing here is specific to a single
   occasion: the colours all come from custom properties that the active theme
   sets inline (see app/Views/common/festive/vars.php, fed from
   app/Config/Festivals.php). Adding a festival therefore means adding a config
   entry — this file does not change.

   Everything is scoped under body.dd-fest, plus body.dd-fest-<key> when a rule
   genuinely needs to differ per festival. Dropping the class reverts the whole
   site to the regular Demandeals look; no other stylesheet is touched.

   All motion uses transform/opacity only, so nothing here triggers layout.
   Every animation is switched off under prefers-reduced-motion at the bottom.
   ========================================================================== */

/* Fallbacks only. vars.php overrides all of these for the live theme; they
   exist so the layer still renders sanely if that partial is ever missed. */
body.dd-fest {
    --fest-a: #ff9933;
    --fest-a-deep: #e8791a;
    --fest-b: #138808;
    --fest-b-lite: #8ee07f;
    --fest-ink: #06038d;
    --fest-brand: #872b97;

    --fest-a-00: rgba(255, 153, 51, 0);
    --fest-a-12: rgba(255, 153, 51, .12);
    --fest-a-18: rgba(255, 153, 51, .18);
    --fest-a-22: rgba(255, 153, 51, .22);
    --fest-a-34: rgba(255, 153, 51, .34);
    --fest-a-38: rgba(255, 153, 51, .38);
    --fest-a-50: rgba(255, 153, 51, .5);

    --fest-b-00: rgba(19, 136, 8, 0);
    --fest-b-12: rgba(19, 136, 8, .12);
    --fest-b-18: rgba(19, 136, 8, .18);
    --fest-b-32: rgba(19, 136, 8, .32);
    --fest-b-42: rgba(19, 136, 8, .42);

    --fest-brand-10: rgba(135, 43, 151, .1);
    --fest-brand-12: rgba(135, 43, 151, .12);
    --fest-brand-14: rgba(135, 43, 151, .14);
    --fest-brand-55: rgba(135, 43, 151, .55);

    --fest-band: linear-gradient(90deg,
            var(--fest-a) 0%, var(--fest-a) 33.33%,
            #fdfdfd 33.33%, #fdfdfd 66.66%,
            var(--fest-b) 66.66%, var(--fest-b) 100%);

    --fest-band-soft: linear-gradient(90deg,
            var(--fest-a-18) 0%,
            rgba(255, 255, 255, 0) 50%,
            var(--fest-b-18) 100%);

    --fest-hero-bg:
        radial-gradient(115% 130% at 6% -10%, var(--fest-a-34) 0%, var(--fest-a-00) 52%),
        radial-gradient(110% 130% at 100% 110%, var(--fest-b-32) 0%, var(--fest-b-00) 55%),
        linear-gradient(135deg, #22103b 0%, #2c1550 42%, #171043 72%, #0d1435 100%);
}

.dd-fest-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ==========================================================================
   1. Page-level tricolour haze + tricolour hairline
   ========================================================================== */

/* Saffron settling from the top of the viewport, green rising from the bottom.
   This has to sit ABOVE the page rather than behind it: most sections here have
   their own white background, which would paint straight over a z-index:-1
   layer. So it is a fixed, click-through overlay parked below the navbar
   (z-index 5001) and the mobile bottom nav (4000) — site chrome stays clean
   while the content area picks up the atmosphere.

   Each plume is masked opaque at its own edge and transparent toward the
   middle, so the centre of the screen — where copy is actually read — is left
   essentially untouched. It grades the page; it does not fog it. */
.dd-fest-page-smoke {
    position: fixed;
    inset: 0;
    z-index: 3500;
    overflow: hidden;
    pointer-events: none;
}

/* The page sits on white, so multiply keeps the haze as a tinted wash rather
   than the milky lift screen would give. */
.dd-fest-page-smoke .dd-fest-smoke {
    position: absolute;
    left: -14%;
    width: 128%;
    height: 44vh;
    mix-blend-mode: multiply;
}

.dd-fest-page-smoke-top {
    top: -6vh;
    opacity: .17;
}

.dd-fest-page-smoke-btm {
    bottom: -6vh;
    opacity: .15;
}

/* Drift only where there is headroom for it: a permanently animating
   full-viewport blend is real GPU work, so phones and tablets get the same
   look held still — one composite instead of one per frame. */
@media (min-width: 992px) {
    .dd-fest-page-smoke-top {
        animation: dd-fest-smoke-drift-a 78s ease-in-out infinite;
    }

    .dd-fest-page-smoke-btm {
        animation: dd-fest-smoke-drift-b 94s ease-in-out infinite;
    }
}

@media (max-width: 767.98px) {

    /* shorter plumes, lighter tint — small screens have less neutral space */
    .dd-fest-page-smoke .dd-fest-smoke {
        height: 30vh;
    }

    .dd-fest-page-smoke-top {
        opacity: .13;
    }

    .dd-fest-page-smoke-btm {
        opacity: .11;
    }
}

.dd-fest-ribbon {
    position: relative;
    height: 5px;
    width: 100%;
    background: var(--fest-band);
    overflow: hidden;
    z-index: 1;
}

.dd-fest-ribbon-shine {
    position: absolute;
    inset: 0;
    background: linear-gradient(100deg,
            rgba(255, 255, 255, 0) 0%,
            rgba(255, 255, 255, .85) 50%,
            rgba(255, 255, 255, 0) 100%);
    transform: translate3d(-100%, 0, 0);
    animation: dd-fest-shine 5.5s ease-in-out infinite;
}

@keyframes dd-fest-shine {

    0%,
    55% {
        transform: translate3d(-100%, 0, 0);
    }

    100% {
        transform: translate3d(100%, 0, 0);
    }
}

/* ==========================================================================
   2. Ashoka Chakra
   ========================================================================== */

.dd-fest-chakra {
    width: 1em;
    height: 1em;
    color: var(--fest-ink);
    flex-shrink: 0;
    animation: dd-fest-spin 12s linear infinite;
}

@keyframes dd-fest-spin {
    to {
        transform: rotate(360deg);
    }
}

/* ==========================================================================
   3. Site-wide ticker strip
   ========================================================================== */

.dd-fest-strip {
    position: relative;
    display: flex;
    align-items: center;
    padding: 0 42px 0 0;
    background:
        var(--fest-band-soft),
        linear-gradient(180deg, #fffaf3 0%, #fffefc 100%);
    border-bottom: 1px solid var(--fest-brand-12);
    overflow: hidden;
}

.dd-fest-ticker {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    /* fade both edges so text never hard-clips */
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 44px, #000 calc(100% - 44px), transparent 100%);
    mask-image: linear-gradient(90deg, transparent 0, #000 44px, #000 calc(100% - 44px), transparent 100%);
}

.dd-fest-ticker-track {
    display: flex;
    width: max-content;
    animation: dd-fest-marquee 42s linear infinite;
}

.dd-fest-strip:hover .dd-fest-ticker-track {
    animation-play-state: paused;
}

@keyframes dd-fest-marquee {
    to {
        transform: translate3d(-50%, 0, 0);
    }
}

.dd-fest-ticker-run {
    display: flex;
    flex-shrink: 0;
}

.dd-fest-ticker-item {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 9px 26px;
    font-size: 13px;
    line-height: 1.4;
    font-weight: 600;
    color: #3d3346;
    white-space: nowrap;
}

.dd-fest-ticker-item strong {
    color: var(--fest-brand);
    font-weight: 800;
}

.dd-fest-ticker-item .dd-fest-chakra {
    font-size: 17px;
}

.dd-fest-strip-close {
    position: absolute;
    top: 50%;
    right: 10px;
    transform: translateY(-50%);
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, .9);
    /* #8b8194 was 3.71:1 against the near-white pill background. */
    color: #6b6478;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    z-index: 2;
}

.dd-fest-strip-close:hover {
    background: var(--fest-brand-10);
    color: var(--fest-brand);
}

@media (max-width: 575.98px) {
    .dd-fest-ticker-item {
        padding: 8px 18px;
        font-size: 12px;
    }
}

/* ==========================================================================
   4. Homepage campaign hero
   ========================================================================== */

.dd-fest-hero {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    margin: 20px 0 8px;
    padding: 40px 44px;
    border-radius: 26px;
    /* per-festival: glow tints + canvas, all set by vars.php */
    background: var(--fest-hero-bg);
    box-shadow: 0 22px 54px rgba(23, 10, 45, .3);
}

/* festival band across cap + base */
.dd-fest-hero::before,
.dd-fest-hero::after {
    content: "";
    position: absolute;
    left: 0;
    width: 100%;
    height: 5px;
    background: var(--fest-band);
    z-index: 4;
}

.dd-fest-hero::before {
    top: 0;
}

.dd-fest-hero::after {
    bottom: 0;
    opacity: .55;
}

/* ---------- decorative layer ---------- */

.dd-fest-hero-fx {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    overflow: hidden;
}

/* ---------- smoke plumes ---------- */

.dd-fest-smoke-layer {
    position: absolute;
    inset: 0;
    overflow: hidden;
    z-index: 1;
}

/* Oversized so the drift never exposes an edge. mix-blend-mode: screen makes
   the plumes read as light/haze against the dark hero rather than flat paint. */
.dd-fest-smoke {
    position: absolute;
    left: -18%;
    width: 136%;
    height: 78%;
    display: block;
    mix-blend-mode: screen;
    will-change: transform;
    pointer-events: none;
}

.dd-fest-smoke-top-a,
.dd-fest-smoke-top-b {
    top: -14%;
}

.dd-fest-smoke-btm-a,
.dd-fest-smoke-btm-b {
    bottom: -14%;
}

.dd-fest-smoke-top-a {
    opacity: .72;
    animation: dd-fest-smoke-drift-a 46s ease-in-out infinite;
}

.dd-fest-smoke-top-b {
    opacity: .5;
    animation: dd-fest-smoke-drift-b 63s ease-in-out infinite;
}

.dd-fest-smoke-btm-a {
    opacity: .68;
    animation: dd-fest-smoke-drift-b 52s ease-in-out infinite;
}

.dd-fest-smoke-btm-b {
    opacity: .46;
    animation: dd-fest-smoke-drift-a 71s ease-in-out infinite reverse;
}

/* Slow billow. Transform only — the noise filter is rasterised once. */
@keyframes dd-fest-smoke-drift-a {

    0%,
    100% {
        transform: translate3d(-3%, 0, 0) scale(1.04);
    }

    50% {
        transform: translate3d(4%, 5%, 0) scale(1.22);
    }
}

@keyframes dd-fest-smoke-drift-b {

    0%,
    100% {
        transform: translate3d(3%, 2%, 0) scale(1.16);
    }

    50% {
        transform: translate3d(-4%, -4%, 0) scale(1);
    }
}

.dd-fest-aurora {
    position: absolute;
    z-index: 0;
    border-radius: 50%;
    filter: blur(46px);
    opacity: .38;
    will-change: transform;
}

.dd-fest-aurora-1 {
    top: -90px;
    left: 8%;
    width: 300px;
    height: 300px;
    background: var(--fest-a-50);
    animation: dd-fest-drift-a 17s ease-in-out infinite;
}

.dd-fest-aurora-2 {
    bottom: -120px;
    left: 38%;
    width: 340px;
    height: 340px;
    background: var(--fest-b-42);
    animation: dd-fest-drift-b 21s ease-in-out infinite;
}

.dd-fest-aurora-3 {
    top: 10%;
    right: -70px;
    width: 260px;
    height: 260px;
    background: var(--fest-brand-55);
    animation: dd-fest-drift-a 19s ease-in-out infinite reverse;
}

@keyframes dd-fest-drift-a {

    0%,
    100% {
        transform: translate3d(0, 0, 0) scale(1);
    }

    50% {
        transform: translate3d(34px, 26px, 0) scale(1.14);
    }
}

@keyframes dd-fest-drift-b {

    0%,
    100% {
        transform: translate3d(0, 0, 0) scale(1.08);
    }

    50% {
        transform: translate3d(-40px, -22px, 0) scale(1);
    }
}

/* rotating chakra watermark */
.dd-fest-hero-chakra {
    position: absolute;
    right: 4%;
    top: 50%;
    width: 380px;
    height: 380px;
    margin-top: -190px;
    color: #fff;
    opacity: .07;
    animation: dd-fest-spin 110s linear infinite;
}

/* fireworks */
.dd-fest-firework {
    position: absolute;
    width: 0;
    height: 0;
}

/* Bright flash at the burst point — without it the rays look like they come
   from nowhere. */
.dd-fest-firework-core {
    position: absolute;
    left: -3px;
    top: -3px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 0 16px 5px var(--fw);
    opacity: 0;
    animation: dd-fest-flash 3.6s ease-out infinite;
    animation-delay: var(--fw-delay);
}

@keyframes dd-fest-flash {

    0%,
    100% {
        transform: scale(.2);
        opacity: 0;
    }

    3% {
        transform: scale(1.5);
        opacity: 1;
    }

    16% {
        transform: scale(.4);
        opacity: 0;
    }
}

/* Rays, not dots: each particle is stretched along its own direction and given
   its own reach (--r) and timing jitter (--pd) so the burst looks uneven. */
.dd-fest-firework i {
    position: absolute;
    left: 0;
    top: 0;
    width: 2px;
    height: 7px;
    margin: -3px 0 0 -1px;
    border-radius: 2px;
    background: linear-gradient(180deg, var(--fw) 0%, rgba(255, 255, 255, 0) 100%);
    box-shadow: 0 0 7px var(--fw);
    opacity: 0;
    transform: rotate(var(--a)) translateY(0) scaleY(.4);
    animation: dd-fest-burst 3.6s cubic-bezier(.15, .75, .25, 1) infinite;
    animation-delay: calc(var(--fw-delay) + var(--pd));
    will-change: transform, opacity;
}

@keyframes dd-fest-burst {
    0% {
        transform: rotate(var(--a)) translateY(0) scaleY(.4);
        opacity: 0;
    }

    5% {
        opacity: 1;
    }

    /* stretched mid-flight, like a trail */
    38% {
        transform: rotate(var(--a)) translateY(calc(var(--r) * -.72)) scaleY(2.1);
        opacity: 1;
    }

    68% {
        transform: rotate(var(--a)) translateY(calc(var(--r) * -1)) scaleY(1.1);
        opacity: .5;
    }

    80%,
    100% {
        transform: rotate(var(--a)) translateY(calc(var(--r) * -1.1)) scaleY(.5);
        opacity: 0;
    }
}

/* kites */
.dd-fest-kite {
    position: absolute;
    width: var(--k);
    transform-origin: 50% 0;
    animation: dd-fest-sway var(--k-dur) ease-in-out infinite;
    animation-delay: var(--k-delay);
    filter: drop-shadow(0 8px 14px rgba(0, 0, 0, .3));
    will-change: transform;
}

.dd-fest-kite svg {
    width: 100%;
    height: auto;
    display: block;
}

@keyframes dd-fest-sway {

    0%,
    100% {
        transform: translate3d(0, 0, 0) rotate(-9deg);
    }

    50% {
        transform: translate3d(16px, 14px, 0) rotate(9deg);
    }
}

/* drifting sparks */
.dd-fest-spark {
    position: absolute;
    bottom: -8px;
    width: 3px;
    height: 3px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .9);
    box-shadow: 0 0 7px rgba(255, 214, 165, .9);
    opacity: 0;
    animation: dd-fest-rise var(--s-dur) linear infinite;
    animation-delay: var(--s-delay);
    will-change: transform, opacity;
}

@keyframes dd-fest-rise {
    0% {
        transform: translate3d(0, 0, 0) scale(.6);
        opacity: 0;
    }

    12% {
        opacity: 1;
    }

    100% {
        transform: translate3d(18px, -320px, 0) scale(1);
        opacity: 0;
    }
}

/* ---------- content ---------- */

.dd-fest-hero-grid {
    position: relative;
    z-index: 3;
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, .85fr);
    align-items: center;
    gap: 30px;
}

.dd-fest-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 5px 14px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .1);
    border: 1px solid rgba(255, 255, 255, .26);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    color: #ffe4c4;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .8px;
    text-transform: uppercase;
}

.dd-fest-pill .dd-fest-chakra {
    font-size: 15px;
    color: #fff;
}

/* big "80" */
.dd-fest-bignum {
    display: flex;
    align-items: center;
    gap: 14px;
    margin: 14px 0 10px;
}

.dd-fest-bignum-value {
    font-family: "Montserrat", var(--font-heading, sans-serif);
    font-size: clamp(64px, 9vw, 108px);
    font-weight: 900;
    line-height: .86;
    letter-spacing: -3px;
    background: linear-gradient(150deg, #ffb45f 0%, #ffffff 48%, #6fd05e 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    filter: drop-shadow(0 6px 20px var(--fest-a-38));
}

.dd-fest-bignum-side {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding-top: 6px;
}

.dd-fest-bignum-side em {
    font-style: normal;
    font-size: 15px;
    font-weight: 800;
    color: var(--fest-a);
    text-transform: uppercase;
    letter-spacing: 1px;
}

.dd-fest-bignum-side b {
    font-family: "Montserrat", var(--font-heading, sans-serif);
    font-size: 17px;
    font-weight: 800;
    line-height: 1.15;
    color: #fff;
    text-transform: uppercase;
    letter-spacing: .5px;
}

.dd-fest-hero-title {
    margin: 0 0 10px;
    font-family: "Montserrat", var(--font-heading, sans-serif);
    font-size: clamp(1.4rem, 2.6vw, 2.15rem);
    font-weight: 800;
    line-height: 1.18;
    color: #fff;
}

.dd-fest-hero-title::after {
    content: none;
}

.dd-fest-tri {
    display: inline-block;
    background: linear-gradient(95deg, var(--fest-a) 0%, #ffffff 46%, var(--fest-b-lite) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.dd-fest-hero-copy-text {
    margin: 0 0 18px;
    max-width: 560px;
    color: rgba(255, 255, 255, .82);
    font-size: 14px;
    line-height: 1.8;
}

/* countdown */
.dd-fest-count {
    margin-bottom: 20px;
}

.dd-fest-count-label {
    display: block;
    margin-bottom: 8px;
    color: #ffdcb0;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 1.2px;
    text-transform: uppercase;
}

.dd-fest-count-tiles {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
}

.dd-fest-tile {
    min-width: 66px;
    padding: 10px 6px;
    border-radius: 14px;
    background: rgba(255, 255, 255, .09);
    border: 1px solid rgba(255, 255, 255, .2);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    text-align: center;
}

.dd-fest-tile b {
    display: block;
    font-family: "Montserrat", var(--font-heading, sans-serif);
    font-size: 26px;
    font-weight: 800;
    line-height: 1.1;
    color: #fff;
    font-variant-numeric: tabular-nums;
}

.dd-fest-tile small {
    display: block;
    margin-top: 2px;
    color: rgba(255, 255, 255, .7);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .7px;
    text-transform: uppercase;
}

/* CTAs */
.dd-fest-hero-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

.dd-fest-cta {
    position: relative;
    overflow: hidden;
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 13px 26px;
    border-radius: 999px;
    background: linear-gradient(135deg, var(--fest-a) 0%, #ff6a3d 52%, var(--fest-brand) 100%);
    color: #fff;
    font-size: 14px;
    font-weight: 800;
    text-decoration: none;
    white-space: nowrap;
    box-shadow: 0 12px 26px rgba(255, 106, 61, .34);
    transition: transform .25s ease, box-shadow .25s ease;
}

.dd-fest-cta::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(100deg,
            rgba(255, 255, 255, 0) 0%,
            rgba(255, 255, 255, .5) 50%,
            rgba(255, 255, 255, 0) 100%);
    transform: translate3d(-100%, 0, 0);
    animation: dd-fest-shine 4.5s ease-in-out infinite;
}

.dd-fest-cta:hover,
.dd-fest-cta:focus {
    color: #fff;
    transform: translateY(-2px);
    box-shadow: 0 16px 32px rgba(255, 106, 61, .44);
}

.dd-fest-cta-ghost {
    display: inline-flex;
    align-items: center;
    padding: 12px 22px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .08);
    border: 1px solid rgba(255, 255, 255, .3);
    color: #fff;
    font-size: 14px;
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
    transition: background .25s ease, border-color .25s ease;
}

.dd-fest-cta-ghost:hover,
.dd-fest-cta-ghost:focus {
    background: rgba(255, 255, 255, .18);
    border-color: rgba(255, 255, 255, .5);
    color: #fff;
}

/* ---------- waving flag ---------- */

.dd-fest-hero-art {
    position: relative;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* ---------- flag: free-flying rippling cloth ----------
   The cloth is a row of vertical strips. Each strip carries the full tricolour
   and shifts on Y with a phase offset, so the band boundaries and the silhouette
   form one travelling wave. Strips are solid rectangles, so edges stay crisp —
   this is what an SVG displacement map cannot do without tearing them. */

.dd-fest-flagstand {
    position: relative;
    width: 100%;
    max-width: 330px;
    animation: dd-fest-flag-bob 7s ease-in-out infinite;
}

.dd-fest-flag {
    position: relative;
    /* 3:2 is the official ratio of the Indian national flag */
    aspect-ratio: 3 / 2;
    filter: drop-shadow(0 14px 26px rgba(0, 0, 0, .34));
}

.dd-fest-cloth {
    position: absolute;
    inset: 0;
    display: flex;
}

.dd-fest-cloth-strip {
    position: relative;
    flex: 1 1 auto;
    /* slight overlap kills sub-pixel seams between strips */
    margin-right: -.5px;
    background: linear-gradient(180deg,
            #ff9933 0%, #ff9933 33.34%,
            #ffffff 33.34%, #ffffff 66.67%,
            #138808 66.67%, #138808 100%);
    transform: translate3d(0, calc(var(--amp) * -1), 0);
    animation: dd-fest-cloth-wave var(--flag-cycle) ease-in-out infinite;
    animation-delay: var(--phase);
    will-change: transform;
}

/* Fold shadow travelling with the same phase as the strip's motion — this is
   what makes it read as cloth rather than a sliding barcode. */
.dd-fest-cloth-strip::after {
    content: "";
    position: absolute;
    inset: 0;
    background: #120a24;
    opacity: 0;
    animation: dd-fest-cloth-fold var(--flag-cycle) ease-in-out infinite;
    animation-delay: var(--phase);
}

@keyframes dd-fest-cloth-wave {

    0%,
    100% {
        transform: translate3d(0, calc(var(--amp) * -1), 0);
    }

    50% {
        transform: translate3d(0, var(--amp), 0);
    }
}

@keyframes dd-fest-cloth-fold {

    0%,
    100% {
        opacity: .2;
    }

    50% {
        opacity: 0;
    }
}

.dd-fest-cloth-chakra {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 26%;
    aspect-ratio: 1;
    margin: -13% 0 0 -13%;
    animation: dd-fest-cloth-wave var(--flag-cycle) ease-in-out infinite;
    animation-delay: var(--phase);
}

.dd-fest-cloth-chakra svg {
    width: 100%;
    height: 100%;
    display: block;
}

@keyframes dd-fest-flag-bob {

    0%,
    100% {
        transform: translate3d(0, 0, 0) rotate(-.6deg);
    }

    50% {
        transform: translate3d(0, -7px, 0) rotate(.6deg);
    }
}

/* ---------- hero responsive ---------- */

@media (max-width: 991.98px) {
    .dd-fest-hero {
        padding: 32px 26px;
    }

    .dd-fest-hero-grid {
        grid-template-columns: minmax(0, 1fr);
        gap: 22px;
    }

    .dd-fest-hero-art {
        order: -1;
    }

    .dd-fest-flagstand {
        max-width: 230px;
    }

    .dd-fest-hero-chakra {
        width: 280px;
        height: 280px;
        margin-top: -140px;
        right: -60px;
    }
}

@media (max-width: 575.98px) {
    .dd-fest-hero {
        margin: 16px 0 6px;
        padding: 22px 16px;
        border-radius: 20px;
    }

    .dd-fest-hero-grid {
        gap: 14px;
    }

    .dd-fest-bignum {
        margin: 8px 0 6px;
        gap: 10px;
    }

    .dd-fest-bignum-value {
        font-size: 54px;
        letter-spacing: -2px;
    }

    .dd-fest-bignum-side b {
        font-size: 14px;
    }

    .dd-fest-bignum-side em {
        font-size: 13px;
    }

    .dd-fest-hero-title {
        font-size: 1.22rem;
        margin-bottom: 8px;
    }

    /* keep the blurb to three lines so the band never becomes a wall of text */
    .dd-fest-hero-copy-text {
        display: -webkit-box;
        -webkit-line-clamp: 3;
        -webkit-box-orient: vertical;
        overflow: hidden;
        margin-bottom: 14px;
        font-size: 12.5px;
        line-height: 1.7;
    }

    .dd-fest-count {
        margin-bottom: 14px;
    }

    .dd-fest-count-tiles {
        gap: 7px;
    }

    .dd-fest-tile {
        min-width: 0;
        flex: 1;
        padding: 7px 3px;
        border-radius: 11px;
    }

    .dd-fest-tile b {
        font-size: 19px;
    }

    .dd-fest-tile small {
        font-size: 9px;
    }

    .dd-fest-hero-actions {
        gap: 8px;
    }

    .dd-fest-cta {
        width: 100%;
        justify-content: center;
        padding: 11px 20px;
    }

    .dd-fest-cta-ghost {
        width: 100%;
        justify-content: center;
        padding: 9px 18px;
        font-size: 13px;
    }

    .dd-fest-flagstand {
        max-width: 148px;
    }

    /* keep the small screen calm */
    .dd-fest-kite-3 {
        display: none;
    }

    .dd-fest-hero-chakra {
        width: 220px;
        height: 220px;
        margin-top: -110px;
    }
}

/* ==========================================================================
   5. Site-wide accents
   ========================================================================== */

/* Section heading underline becomes the tricolour */
body.dd-fest h2.fw-bold::after {
    width: 92px;
    height: 4px;
    border-radius: 2px;
    background: var(--fest-band);
    background-color: transparent;
}

body.dd-fest .text-center h2.fw-bold::after {
    margin-left: auto;
    margin-right: auto;
}

/* Navbar gets a tricolour underline instead of the plain grey border */
body.dd-fest .navbar.osahan-header {
    position: relative;
    border-bottom-color: transparent !important;
}

body.dd-fest .navbar.osahan-header::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 2px;
    background: var(--fest-band);
    opacity: .8;
}

/* Deal panels: festive top edge + warmer glow */
body.dd-fest .main-banner-wrapper.theme {
    position: relative;
    border-color: var(--fest-a-34);
}

body.dd-fest .main-banner-wrapper.theme::after {
    background: radial-gradient(circle, var(--fest-a-34) 0%, var(--fest-a-00) 70%);
}

body.dd-fest .hover-lift:hover {
    box-shadow: 0 .75rem 1.5rem var(--fest-a-22);
}

/* ==========================================================================
   6. Footer
   ========================================================================== */

body.dd-fest .dd-footer {
    border-top: 0;
}

body.dd-fest .dd-footer::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 5px;
    background: var(--fest-band);
    z-index: 3;
}

.dd-fest-footer-note {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    margin-top: 12px;
    padding: 9px 18px;
    width: -moz-fit-content;
    width: fit-content;
    margin-inline: auto;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--fest-a-12) 0%, rgba(255, 255, 255, .6) 50%, var(--fest-b-12) 100%);
    border: 1px solid var(--fest-brand-14);
    color: #5f5567;
    font-size: 13px;
    font-weight: 600;
}

.dd-fest-footer-note .dd-fest-chakra {
    font-size: 17px;
}

.dd-fest-footer-note strong {
    color: var(--fest-brand);
    font-weight: 800;
}

/* ==========================================================================
   7. Mobile bottom nav
   ========================================================================== */

@media (max-width: 991.98px) {
    body.dd-fest .dd-bottom-nav {
        border-top: 0;
    }

    body.dd-fest .dd-bottom-nav::before {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 3px;
        border-radius: 25px 25px 0 0;
        background: var(--fest-band);
    }
}

/* ==========================================================================
   7b. Motifs shared by the non-tricolour festivals
   ========================================================================== */

/* ---------- campaign badge (themes with no anniversary number) ---------- */

.dd-fest-badge {
    display: inline-block;
    margin: 14px 0 12px;
    padding: 8px 20px;
    border-radius: 999px;
    background: linear-gradient(135deg, var(--fest-a) 0%, var(--fest-a-deep) 100%);
    color: #fff;
    font-family: "Montserrat", var(--font-heading, sans-serif);
    font-size: clamp(1.1rem, 2.2vw, 1.6rem);
    font-weight: 900;
    letter-spacing: .4px;
    text-transform: uppercase;
    box-shadow: 0 10px 24px rgba(0, 0, 0, .28);
}

/* Without the flag there is no art column. Give the copy the width but stop
   short of the right edge, so the corner artwork (moon, sun, crescent, Santa)
   is not sitting directly behind the headline. */
.dd-fest-hero-grid-wide {
    grid-template-columns: minmax(0, 1fr);
}

.dd-fest-hero-grid-wide .dd-fest-hero-copy {
    max-width: 74%;
}

.dd-fest-hero-grid-wide .dd-fest-hero-copy-text {
    max-width: 660px;
}

@media (max-width: 991.98px) {
    .dd-fest-hero-grid-wide .dd-fest-hero-copy {
        max-width: 100%;
    }
}

/**
 * Scrim behind the copy.
 *
 * The motif layer is deliberately busy, and on the wide themes it runs under
 * the text — a lit pumpkin or a glowing diya directly behind the CTA would eat
 * its contrast. This lays a soft wash of the hero's own canvas colour between
 * the artwork and the words. It sits at z-index -1 inside .dd-fest-hero-grid,
 * which is a stacking context, so it stays above the motif layer and below the
 * copy rather than escaping to the back of the hero.
 */
.dd-fest-hero-copy {
    position: relative;
}

.dd-fest-hero-copy::before {
    content: "";
    position: absolute;
    /* bleed past the text so the falloff is never visible as an edge */
    inset: -28px -60px -28px -34px;
    z-index: -1;
    border-radius: 40px;
    background:
        radial-gradient(75% 90% at 26% 50%, rgba(6, 4, 20, .58) 0%, rgba(6, 4, 20, .3) 52%, rgba(6, 4, 20, 0) 82%);
    pointer-events: none;
}

@media (max-width: 575.98px) {
    .dd-fest-hero-copy::before {
        inset: -18px -20px -18px -20px;
        background:
            radial-gradient(90% 92% at 50% 50%, rgba(6, 4, 20, .62) 0%, rgba(6, 4, 20, .36) 58%, rgba(6, 4, 20, 0) 88%);
    }
}

/* ---------- hanging lanterns / diyas (Diwali, Eid) ---------- */

.dd-fest-lantern {
    position: absolute;
    top: 0;
    width: var(--l);
    /* swings from where the cord meets the top of the hero, not from the body */
    transform-origin: 50% 0;
    animation: dd-fest-lantern-sway var(--l-dur) ease-in-out infinite;
    animation-delay: var(--l-delay);
    will-change: transform;
}

.dd-fest-lantern svg {
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 6px 14px rgba(0, 0, 0, .34));
}

/* the cord it hangs from */
.dd-fest-lantern-cord {
    display: block;
    width: 1px;
    height: 34px;
    margin: 0 auto;
    background: linear-gradient(180deg, rgba(255, 255, 255, .05) 0%, rgba(255, 255, 255, .35) 100%);
}

/* warm pool of light, pulsing like a flame */
.dd-fest-lantern-glow {
    position: absolute;
    left: 50%;
    top: 52%;
    width: 220%;
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: radial-gradient(circle, var(--fest-a-38) 0%, var(--fest-a-00) 68%);
    pointer-events: none;
    animation: dd-fest-flicker 3.4s ease-in-out infinite;
    animation-delay: var(--l-delay);
}

@keyframes dd-fest-lantern-sway {

    0%,
    100% {
        transform: rotate(-5deg);
    }

    50% {
        transform: rotate(5deg);
    }
}

@keyframes dd-fest-flicker {

    0%,
    100% {
        opacity: .55;
        transform: translate(-50%, -50%) scale(1);
    }

    45% {
        opacity: .9;
        transform: translate(-50%, -50%) scale(1.1);
    }
}

/* ---------- drifting petals / colour (Holi, Navratri, gifting) ---------- */

.dd-fest-petal {
    position: absolute;
    top: -6%;
    width: var(--p);
    height: var(--p);
    /* asymmetric radius reads as a petal rather than a dot */
    border-radius: 60% 40% 55% 45%;
    background: var(--p-tint);
    opacity: 0;
    animation: dd-fest-fall var(--p-dur) linear infinite;
    animation-delay: var(--p-delay);
    will-change: transform, opacity;
}

/* ---------- snow (Christmas) ---------- */

.dd-fest-flake {
    position: absolute;
    top: -4%;
    width: var(--f);
    height: var(--f);
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 0 6px rgba(255, 255, 255, .8);
    opacity: 0;
    animation: dd-fest-fall var(--f-dur) linear infinite;
    animation-delay: var(--f-delay);
    will-change: transform, opacity;
}

/* Shared fall: drop past the bottom of the hero while swaying sideways and
   tumbling. --p-sway / --f-sway give each one its own drift width.

   The distance MUST be an absolute length, not a percentage: a percentage in
   translate resolves against the moving element's own box, and these are 6-14px
   specks — 55% of that is half a pixel of travel. --fest-fall is set to clear
   the hero's height, and .dd-fest-hero-fx clips whatever overshoots. */
.dd-fest-hero-fx {
    --fest-fall: 620px;
}

@keyframes dd-fest-fall {
    0% {
        transform: translate3d(0, 0, 0) rotate(0deg);
        opacity: 0;
    }

    8% {
        opacity: .9;
    }

    50% {
        transform: translate3d(var(--p-sway, var(--f-sway, 18px)), calc(var(--fest-fall) * .5), 0) rotate(180deg);
    }

    88% {
        opacity: .55;
    }

    100% {
        transform: translate3d(0, var(--fest-fall), 0) rotate(360deg);
        opacity: 0;
    }
}

/* ==========================================================================
   7c. Festival-specific artwork
   --------------------------------------------------------------------------
   Placement and motion only — the SVGs carry their own colour, taken from the
   palette in the motif partials.
   ========================================================================== */

/* ---------- Halloween: moon, cobweb, spider ---------- */

.dd-fest-moon {
    position: absolute;
    top: 6%;
    right: 6%;
    width: 128px;
    filter: drop-shadow(0 0 34px rgba(255, 249, 219, .5));
    opacity: .9;
}

.dd-fest-moon svg,
.dd-fest-sun svg,
.dd-fest-crescent svg,
.dd-fest-charkhi svg,
.dd-fest-rangoli svg,
.dd-fest-bow svg,
.dd-fest-santa svg,
.dd-fest-pichkari svg {
    width: 100%;
    height: auto;
    display: block;
}

.dd-fest-cobweb {
    position: absolute;
    top: 0;
    width: 150px;
    opacity: .5;
}

.dd-fest-cobweb svg {
    width: 100%;
    height: auto;
    display: block;
}

.dd-fest-cobweb-tl {
    left: 0;
}

.dd-fest-cobweb-tr {
    right: 0;
}

.dd-fest-spider {
    position: absolute;
    top: 0;
    left: 22%;
    width: 34px;
    animation: dd-fest-spider-drop 9s ease-in-out infinite;
    transform-origin: 50% 0;
}

.dd-fest-spider svg {
    width: 100%;
    height: auto;
    display: block;
}

/* the silk it hangs from, drawn upward out of the hero */
.dd-fest-spider-thread {
    position: absolute;
    left: 50%;
    bottom: 100%;
    width: 1px;
    height: 300px;
    background: rgba(255, 255, 255, .35);
}

@keyframes dd-fest-spider-drop {

    0%,
    100% {
        transform: translate3d(0, 30px, 0);
    }

    50% {
        transform: translate3d(0, 150px, 0);
    }
}

/* ---------- Halloween: jack-o'-lantern ---------- */

.dd-fest-pumpkin {
    position: absolute;
    width: var(--pk);
    transform: scaleX(var(--pk-flip, 1));
    animation: dd-fest-pumpkin-bob 6s ease-in-out infinite;
    animation-delay: var(--pk-delay);
}

.dd-fest-pumpkin svg {
    position: relative;
    z-index: 2;
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 10px 20px rgba(0, 0, 0, .4));
}

/* candle light spilling out of the carving */
.dd-fest-pumpkin-glow {
    position: absolute;
    left: 50%;
    top: 58%;
    width: 190%;
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255, 190, 60, .5) 0%, rgba(255, 190, 60, 0) 66%);
    animation: dd-fest-flicker 2.6s ease-in-out infinite;
    animation-delay: var(--pk-delay);
    pointer-events: none;
}

@keyframes dd-fest-pumpkin-bob {

    0%,
    100% {
        transform: scaleX(var(--pk-flip, 1)) translate3d(0, 0, 0);
    }

    50% {
        transform: scaleX(var(--pk-flip, 1)) translate3d(0, -7px, 0);
    }
}

/* ---------- Halloween: bats ---------- */

.dd-fest-bat {
    position: absolute;
    width: var(--bat);
    animation: dd-fest-bat-fly var(--bat-dur) ease-in-out infinite;
    animation-delay: var(--bat-delay);
    will-change: transform;
}

.dd-fest-bat svg {
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 6px 10px rgba(0, 0, 0, .45));
}

/* wings flap independently of the flight path */
.dd-fest-bat-wing {
    animation: dd-fest-bat-flap .42s ease-in-out infinite;
    transform-box: fill-box;
}

.dd-fest-bat-wing-l {
    transform-origin: 100% 50%;
}

.dd-fest-bat-wing-r {
    transform-origin: 0 50%;
}

@keyframes dd-fest-bat-flap {

    0%,
    100% {
        transform: scaleY(1) scaleX(1);
    }

    50% {
        transform: scaleY(.42) scaleX(.9);
    }
}

@keyframes dd-fest-bat-fly {

    0%,
    100% {
        transform: translate3d(0, 0, 0) rotate(-4deg);
    }

    25% {
        transform: translate3d(calc(var(--bat-drift) * .4), -22px, 0) rotate(5deg);
    }

    50% {
        transform: translate3d(var(--bat-drift), 12px, 0) rotate(-3deg);
    }

    75% {
        transform: translate3d(calc(var(--bat-drift) * .5), 30px, 0) rotate(4deg);
    }
}

/* ---------- Halloween: ghost ---------- */

.dd-fest-ghost {
    position: absolute;
    width: var(--gh);
    opacity: .82;
    animation: dd-fest-ghost-float var(--gh-dur) ease-in-out infinite;
    animation-delay: var(--gh-delay);
    will-change: transform, opacity;
}

.dd-fest-ghost svg {
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 0 18px rgba(210, 225, 255, .45));
}

@keyframes dd-fest-ghost-float {

    0%,
    100% {
        transform: translate3d(0, 0, 0) scale(1);
        opacity: .3;
    }

    50% {
        transform: translate3d(26px, -26px, 0) scale(1.06);
        opacity: .85;
    }
}

/* ---------- Christmas: tree ---------- */

.dd-fest-tree {
    position: absolute;
    width: var(--tr);
    animation: dd-fest-sway-soft 8s ease-in-out infinite;
    animation-delay: var(--tr-delay);
    transform-origin: 50% 100%;
}

.dd-fest-tree svg {
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 10px 22px rgba(0, 0, 0, .38));
}

.dd-fest-bauble {
    animation: dd-fest-twinkle 2.4s ease-in-out infinite;
    animation-delay: var(--tw-delay);
    transform-box: fill-box;
    transform-origin: center;
}

.dd-fest-tree-star {
    animation: dd-fest-star-pulse 3s ease-in-out infinite;
    transform-box: fill-box;
    transform-origin: center;
    filter: drop-shadow(0 0 8px rgba(255, 220, 120, .9));
}

@keyframes dd-fest-twinkle {

    0%,
    100% {
        opacity: .55;
        transform: scale(.85);
    }

    50% {
        opacity: 1;
        transform: scale(1.15);
    }
}

@keyframes dd-fest-star-pulse {

    0%,
    100% {
        transform: scale(1) rotate(0deg);
    }

    50% {
        transform: scale(1.14) rotate(8deg);
    }
}

@keyframes dd-fest-sway-soft {

    0%,
    100% {
        transform: rotate(-1.4deg);
    }

    50% {
        transform: rotate(1.4deg);
    }
}

/* ---------- Christmas: Santa, gifts, candy canes ---------- */

.dd-fest-santa {
    position: absolute;
    right: 7%;
    bottom: -2%;
    width: 120px;
    animation: dd-fest-santa-peek 7s ease-in-out infinite;
    filter: drop-shadow(0 10px 20px rgba(0, 0, 0, .38));
}

@keyframes dd-fest-santa-peek {

    0%,
    100% {
        transform: translate3d(0, 8px, 0) rotate(-2deg);
    }

    50% {
        transform: translate3d(0, -6px, 0) rotate(2deg);
    }
}

.dd-fest-gift {
    position: absolute;
    width: var(--g);
    transform: rotate(var(--g-tilt));
    animation: dd-fest-gift-hop 5.5s ease-in-out infinite;
    animation-delay: var(--g-delay);
}

.dd-fest-gift svg {
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 8px 16px rgba(0, 0, 0, .34));
}

@keyframes dd-fest-gift-hop {

    0%,
    100% {
        transform: rotate(var(--g-tilt)) translate3d(0, 0, 0);
    }

    50% {
        transform: rotate(var(--g-tilt)) translate3d(0, -6px, 0);
    }
}

.dd-fest-cane {
    position: absolute;
    width: var(--c);
    transform: rotate(var(--c-tilt));
    animation: dd-fest-cane-swing 6.5s ease-in-out infinite;
    animation-delay: var(--c-delay);
    transform-origin: 50% 0;
}

.dd-fest-cane svg {
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 6px 12px rgba(0, 0, 0, .3));
}

@keyframes dd-fest-cane-swing {

    0%,
    100% {
        transform: rotate(calc(var(--c-tilt) - 5deg));
    }

    50% {
        transform: rotate(calc(var(--c-tilt) + 5deg));
    }
}

/* ---------- New Year: balloons ---------- */

.dd-fest-balloon {
    position: absolute;
    bottom: -22%;
    width: var(--bl);
    opacity: 0;
    animation: dd-fest-balloon-rise var(--bl-dur) linear infinite;
    animation-delay: var(--bl-delay);
    will-change: transform, opacity;
}

.dd-fest-balloon svg {
    width: 100%;
    height: auto;
    display: block;
}

@keyframes dd-fest-balloon-rise {
    0% {
        transform: translate3d(0, 0, 0) rotate(-4deg);
        opacity: 0;
    }

    12% {
        opacity: .9;
    }

    50% {
        transform: translate3d(20px, -320px, 0) rotate(4deg);
    }

    85% {
        opacity: .5;
    }

    100% {
        transform: translate3d(0, -640px, 0) rotate(-4deg);
        opacity: 0;
    }
}

/* ---------- Holi: pichkari + spray ---------- */

/**
 * Pichkari sits in the hero's right-hand space. The artwork is drawn with its
 * nozzle at the LEFT of the viewBox and the grip/pump at the right, so with no
 * mirroring at all and the box anchored via `right`, the nozzle already lands
 * on the inward (hero-centre) side and the grip near the hero's edge — as if
 * held by someone standing just off-canvas. (An earlier pass added scaleX(-1)
 * here on the assumption that would aim it inward; it did the opposite —
 * flipping the nozzle out to the edge, firing off the corner. Removed.)
 *
 * Rotation is positive (clockwise in screen space) rather than negative, which
 * tilts the nozzle end — and with it the whole spray fan, since the droplets
 * inherit this same rotation — slightly UP rather than down toward the floor.
 */
.dd-fest-pichkari {
    position: absolute;
    right: 1%;
    bottom: 26%;
    width: 232px;
    transform: rotate(14deg);
    animation: dd-fest-pichkari-kick 2.6s ease-in-out infinite;
    filter: drop-shadow(0 10px 18px rgba(0, 0, 0, .34));
}

/* recoil, timed with the spray bursts: the muzzle kicks further up on the shot */
@keyframes dd-fest-pichkari-kick {

    0%,
    100% {
        transform: rotate(14deg) translate3d(0, 0, 0);
    }

    12% {
        transform: rotate(16deg) translate3d(-6px, -2px, 0);
    }

    40% {
        transform: rotate(14deg) translate3d(0, 0, 0);
    }
}

/* droplets leave the muzzle, at the nozzle end of the barrel */
.dd-fest-spray {
    position: absolute;
    left: 6%;
    top: 52%;
    width: 0;
    height: 0;
}

/* Elongated along the direction of travel, not round: a fan of circles reads
   as scattered dots, whereas a streak reads as liquid leaving a nozzle. */
.dd-fest-spray i {
    position: absolute;
    left: 0;
    top: 0;
    width: calc(var(--sp-size) * 2.6);
    height: var(--sp-size);
    margin: calc(var(--sp-size) / -2) 0 0 calc(var(--sp-size) * -1.3);
    border-radius: 999px;
    background: linear-gradient(90deg, var(--sp-tint) 0%, var(--sp-tint) 55%, rgba(255, 255, 255, 0) 100%);
    box-shadow: 0 0 10px var(--sp-tint);
    opacity: 0;
    transform: rotate(var(--sp-a)) translateX(0);
    animation: dd-fest-spray-shot 2.6s cubic-bezier(.2, .7, .35, 1) infinite;
    animation-delay: var(--sp-delay);
    will-change: transform, opacity;
}

/**
 * Droplets travel toward -X (screen-left): the nozzle now points inward from
 * the hero's right edge toward its centre, so "outward from the nozzle" is
 * leftward, not rightward. The elongated streak's gradient (solid at its own
 * local 0%, fading toward 100%) already leads with the solid end in that
 * direction, so only the sign of the travel distance needed to flip.
 */
@keyframes dd-fest-spray-shot {
    0% {
        transform: rotate(var(--sp-a)) translateX(0) scale(.5);
        opacity: 0;
    }

    8% {
        opacity: 1;
    }

    /* gravity: the arc sags as the droplet loses speed */
    60% {
        transform: rotate(var(--sp-a)) translateX(calc(var(--sp-r) * -.75)) translateY(14px) scale(1.05);
        opacity: .95;
    }

    100% {
        transform: rotate(var(--sp-a)) translateX(calc(var(--sp-r) * -1)) translateY(52px) scale(.4);
        opacity: 0;
    }
}

/* ---------- Holi: gulal clouds + splats ---------- */

.dd-fest-gulal {
    position: absolute;
    width: var(--gu);
    aspect-ratio: 1;
    margin: calc(var(--gu) / -2) 0 0 calc(var(--gu) / -2);
    border-radius: 50%;
    background: radial-gradient(circle, var(--gu-tint) 0%, transparent 62%);
    filter: blur(18px);
    opacity: 0;
    animation: dd-fest-gulal-puff var(--gu-dur) ease-out infinite;
    animation-delay: var(--gu-delay);
    will-change: transform, opacity;
}

@keyframes dd-fest-gulal-puff {
    0% {
        transform: scale(.25) translate3d(0, 20px, 0);
        opacity: 0;
    }

    18% {
        opacity: .75;
    }

    100% {
        transform: scale(1.5) translate3d(0, -60px, 0);
        opacity: 0;
    }
}

.dd-fest-splat {
    position: absolute;
    width: var(--sl);
    transform: rotate(var(--sl-rot)) scale(0);
    opacity: 0;
    animation: dd-fest-splat-hit 9s ease-out infinite;
    animation-delay: var(--sl-delay);
}

.dd-fest-splat svg {
    width: 100%;
    height: auto;
    display: block;
}

/* lands with a quick overshoot, sits wet, then fades */
@keyframes dd-fest-splat-hit {
    0% {
        transform: rotate(var(--sl-rot)) scale(0);
        opacity: 0;
    }

    6% {
        transform: rotate(var(--sl-rot)) scale(1.18);
        opacity: .85;
    }

    12% {
        transform: rotate(var(--sl-rot)) scale(1);
        opacity: .7;
    }

    72% {
        transform: rotate(var(--sl-rot)) scale(1);
        opacity: .7;
    }

    100% {
        transform: rotate(var(--sl-rot)) scale(1.05);
        opacity: 0;
    }
}

/* ---------- Valentine's / Raksha Bandhan ---------- */

.dd-fest-heart {
    position: absolute;
    top: -6%;
    width: var(--h);
    opacity: 0;
    animation: dd-fest-fall var(--h-dur) linear infinite;
    animation-delay: var(--h-delay);
    --p-sway: var(--h-sway);
    will-change: transform, opacity;
}

.dd-fest-heart svg {
    width: 100%;
    height: auto;
    display: block;
}

.dd-fest-rakhi {
    position: absolute;
    width: var(--rk);
    animation: dd-fest-rakhi-turn var(--rk-dur) ease-in-out infinite;
    animation-delay: var(--rk-delay);
}

.dd-fest-rakhi svg {
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 6px 14px rgba(0, 0, 0, .3));
}

@keyframes dd-fest-rakhi-turn {

    0%,
    100% {
        transform: translate3d(0, 0, 0) rotate(-6deg);
    }

    50% {
        transform: translate3d(10px, -12px, 0) rotate(6deg);
    }
}

/* ---------- Makar Sankranti: sun + charkhi ---------- */

.dd-fest-sun {
    position: absolute;
    top: 4%;
    right: 5%;
    width: 150px;
    filter: drop-shadow(0 0 40px var(--fest-a-50));
}

.dd-fest-sun-rays {
    animation: dd-fest-spin 40s linear infinite;
    transform-origin: center;
}

.dd-fest-charkhi {
    position: absolute;
    left: 3%;
    bottom: 4%;
    width: 104px;
    animation: dd-fest-spin 14s linear infinite;
    filter: drop-shadow(0 8px 18px rgba(0, 0, 0, .34));
}

/* ---------- Diwali / Navratri / Ganesh: diya, rangoli, toran ---------- */

.dd-fest-diya {
    position: absolute;
    width: var(--d);
}

.dd-fest-diya svg {
    position: relative;
    z-index: 2;
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 6px 12px rgba(0, 0, 0, .34));
}

/* the flame leans and stretches; the bowl stays put */
.dd-fest-diya-flame {
    animation: dd-fest-flame-dance 1.7s ease-in-out infinite;
    animation-delay: var(--d-delay);
    transform-box: fill-box;
    transform-origin: 50% 100%;
}

@keyframes dd-fest-flame-dance {

    0%,
    100% {
        transform: scale(1, 1) rotate(-3deg);
    }

    30% {
        transform: scale(.92, 1.12) rotate(4deg);
    }

    65% {
        transform: scale(1.06, .94) rotate(-2deg);
    }
}

.dd-fest-diya-glow {
    position: absolute;
    left: 50%;
    top: 34%;
    width: 240%;
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: radial-gradient(circle, var(--fest-a-38) 0%, var(--fest-a-00) 66%);
    animation: dd-fest-flicker 2.2s ease-in-out infinite;
    animation-delay: var(--d-delay);
    pointer-events: none;
}

.dd-fest-rangoli {
    position: absolute;
    left: 50%;
    bottom: -34%;
    width: 300px;
    margin-left: -150px;
    opacity: .16;
    animation: dd-fest-spin 120s linear infinite;
}

.dd-fest-toran {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 90px;
}

.dd-fest-toran svg {
    width: 100%;
    height: 90px;
    display: block;
    opacity: .8;
}

/* marigold buds hanging off the string */
.dd-fest-toran-bud {
    position: absolute;
    top: var(--tb-drop);
    width: var(--tb);
    aspect-ratio: 1;
    border-radius: 50%;
    background:
        radial-gradient(circle at 33% 28%, rgba(255, 255, 255, .5) 0%, rgba(255, 255, 255, 0) 38%),
        radial-gradient(circle at 50% 50%, var(--tb-tint) 40%, rgba(0, 0, 0, .28) 100%);
    box-shadow: 0 2px 6px rgba(0, 0, 0, .3);
    animation: dd-fest-sway-soft 4.5s ease-in-out infinite;
    animation-delay: var(--tb-delay);
    transform-origin: 50% -10px;
}

/* ---------- Eid: crescent ---------- */

.dd-fest-crescent {
    position: absolute;
    top: 6%;
    right: 6%;
    width: 124px;
    filter: drop-shadow(0 0 26px var(--fest-a-50));
    animation: dd-fest-sway-soft 9s ease-in-out infinite;
}

/* ---------- Navratri: dandiya ---------- */

.dd-fest-dandiya {
    position: absolute;
    width: var(--dn);
    filter: drop-shadow(0 8px 16px rgba(0, 0, 0, .32));
}

.dd-fest-dandiya svg {
    width: 100%;
    height: auto;
    display: block;
}

/* the pair taps together on the beat */
.dd-fest-dandiya-stick {
    transform-box: view-box;
    animation: dd-fest-dandiya-tap 1.3s ease-in-out infinite;
    animation-delay: var(--dn-delay);
}

.dd-fest-dandiya-stick-r {
    animation-name: dd-fest-dandiya-tap-r;
}

@keyframes dd-fest-dandiya-tap {

    0%,
    100% {
        transform: rotate(-22deg);
    }

    50% {
        transform: rotate(-6deg);
    }
}

@keyframes dd-fest-dandiya-tap-r {

    0%,
    100% {
        transform: rotate(22deg);
    }

    50% {
        transform: rotate(6deg);
    }
}

/* ---------- Dussehra: bow + Ravana effigy ----------
   Staged as one scene in the hero's right-hand space: bow on the left of the
   pair, effigy on the right, arrow flying between them. */

.dd-fest-bow {
    position: absolute;
    right: 18%;
    bottom: 14%;
    width: 104px;
    filter: drop-shadow(0 8px 18px rgba(0, 0, 0, .34));
}

.dd-fest-ravana {
    position: absolute;
    right: 3%;
    bottom: 2%;
    width: 150px;
}

.dd-fest-ravana svg {
    position: relative;
    z-index: 2;
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 10px 22px rgba(0, 0, 0, .42));
}

/* the effigy alight — flares on the arrow's 4.5s beat, so the shot lands */
.dd-fest-ravana-fire {
    animation: dd-fest-ravana-burn 4.5s ease-in-out infinite;
    transform-box: fill-box;
    transform-origin: 50% 100%;
}

.dd-fest-ravana-glow {
    position: absolute;
    left: 50%;
    bottom: -10%;
    width: 180%;
    aspect-ratio: 1;
    transform: translateX(-50%);
    border-radius: 50%;
    background: radial-gradient(circle, var(--fest-a-38) 0%, var(--fest-a-00) 64%);
    animation: dd-fest-ravana-burn 4.5s ease-in-out infinite;
    pointer-events: none;
}

@keyframes dd-fest-ravana-burn {

    0%,
    60% {
        transform: scaleY(.72) scaleX(.92);
        opacity: .55;
    }

    /* the arrow arrives around 72% of its flight */
    78% {
        transform: scaleY(1.35) scaleX(1.08);
        opacity: 1;
    }

    100% {
        transform: scaleY(.9) scaleX(1);
        opacity: .75;
    }
}

/* ---------- Ganesh Chaturthi: Ganesha ---------- */

.dd-fest-ganesha {
    position: absolute;
    right: 3%;
    bottom: 0;
    width: 188px;
}

.dd-fest-ganesha svg {
    position: relative;
    z-index: 2;
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 12px 26px rgba(0, 0, 0, .4));
}

.dd-fest-ganesha-halo {
    position: absolute;
    left: 50%;
    top: 34%;
    width: 150%;
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: radial-gradient(circle, var(--fest-a-38) 0%, var(--fest-a-00) 62%);
    animation: dd-fest-flicker 5s ease-in-out infinite;
    pointer-events: none;
}

/* ---------- Eid: mosque ---------- */

.dd-fest-mosque {
    position: absolute;
    right: 1%;
    bottom: 0;
    width: 268px;
    opacity: .95;
}

.dd-fest-mosque svg {
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 0 24px var(--fest-a-22));
}

/* ---------- Valentine's: teddy + chocolates ---------- */

.dd-fest-teddy {
    position: absolute;
    right: 5%;
    bottom: 0;
    width: 132px;
    animation: dd-fest-teddy-tilt 6.5s ease-in-out infinite;
    transform-origin: 50% 100%;
}

.dd-fest-teddy svg {
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 10px 20px rgba(0, 0, 0, .38));
}

@keyframes dd-fest-teddy-tilt {

    0%,
    100% {
        transform: rotate(-2.5deg);
    }

    50% {
        transform: rotate(2.5deg);
    }
}

.dd-fest-chocolates {
    position: absolute;
    right: 22%;
    bottom: 4%;
    width: 122px;
    animation: dd-fest-gift-hop 5.8s ease-in-out infinite;
    --g-tilt: -6deg;
}

.dd-fest-chocolates svg {
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 8px 18px rgba(0, 0, 0, .36));
}

/* The arrow is loosed toward Ravana, then reappears nocked. The shaft is
   drawn pointing right (arrowhead tip at the bow's local x=100, fletching at
   the string end near x=6) since Ravana sits to the right of the bow — so the
   loose has to travel in +X. It previously moved -150px, firing the arrow
   backward through the bow instead of at the target. */
.dd-fest-bow-arrow {
    animation: dd-fest-loose 4.5s ease-in infinite;
}

@keyframes dd-fest-loose {

    0%,
    55% {
        transform: translateX(0);
        opacity: 1;
    }

    72% {
        transform: translateX(150px);
        opacity: 0;
    }

    73%,
    100% {
        transform: translateX(0);
        opacity: 1;
    }
}

/* ---------- Ganesh Chaturthi: modak ---------- */

.dd-fest-modak {
    position: absolute;
    width: var(--m);
    animation: dd-fest-gift-hop 5.5s ease-in-out infinite;
    animation-delay: var(--m-delay);
    --g-tilt: 0deg;
}

.dd-fest-modak svg {
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 6px 14px rgba(0, 0, 0, .3));
}

/* ---------- Raksha Bandhan: puja thali ---------- */

.dd-fest-thali {
    position: absolute;
    width: var(--th);
    animation: dd-fest-gift-hop 6s ease-in-out infinite;
    animation-delay: var(--th-delay);
    --g-tilt: 0deg;
}

.dd-fest-thali svg {
    position: relative;
    z-index: 2;
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 8px 16px rgba(0, 0, 0, .34));
}

.dd-fest-thali-flame {
    animation: dd-fest-flame-dance 1.7s ease-in-out infinite;
    animation-delay: var(--th-delay);
    transform-box: fill-box;
    transform-origin: 50% 100%;
}

.dd-fest-thali-glow {
    position: absolute;
    left: 26%;
    top: 34%;
    width: 130%;
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: radial-gradient(circle, var(--fest-a-38) 0%, var(--fest-a-00) 66%);
    animation: dd-fest-flicker 2.4s ease-in-out infinite;
    animation-delay: var(--th-delay);
    pointer-events: none;
}

/* ---------- Valentine's: long-stem rose ---------- */

/* Roses flank the right-hand grouping rather than sitting under the CTAs. */
.dd-fest-rose {
    position: absolute;
    width: var(--ro);
    transform: rotate(var(--ro-tilt));
    animation: dd-fest-rose-sway 7.5s ease-in-out infinite;
    animation-delay: var(--ro-delay);
    transform-origin: 50% 100%;
}

.dd-fest-rose svg {
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 10px 20px rgba(0, 0, 0, .34));
}

@keyframes dd-fest-rose-sway {

    0%,
    100% {
        transform: rotate(calc(var(--ro-tilt) - 3deg));
    }

    50% {
        transform: rotate(calc(var(--ro-tilt) + 3deg));
    }
}

/* ---------- New Year: champagne + confetti ---------- */

.dd-fest-champagne {
    position: absolute;
    right: 5%;
    bottom: 0;
    width: 176px;
    animation: dd-fest-santa-peek 7.5s ease-in-out infinite;
    filter: drop-shadow(0 10px 20px rgba(0, 0, 0, .36));
}

.dd-fest-champagne svg {
    width: 100%;
    height: auto;
    display: block;
}

/* the cork keeps launching */
.dd-fest-cork {
    animation: dd-fest-cork-pop 5s cubic-bezier(.2, .7, .4, 1) infinite;
    transform-box: view-box;
}

@keyframes dd-fest-cork-pop {

    0%,
    8% {
        transform: translate3d(0, 34px, 0) rotate(0deg);
        opacity: 0;
    }

    14% {
        opacity: 1;
    }

    58% {
        transform: translate3d(46px, -50px, 0) rotate(300deg);
        opacity: 1;
    }

    76%,
    100% {
        transform: translate3d(92px, 20px, 0) rotate(620deg);
        opacity: 0;
    }
}

.dd-fest-bubble {
    animation: dd-fest-bubble-rise 2.6s ease-in infinite;
    animation-delay: var(--bu-delay);
    transform-box: fill-box;
}

@keyframes dd-fest-bubble-rise {
    0% {
        transform: translateY(6px);
        opacity: 0;
    }

    20% {
        opacity: .9;
    }

    100% {
        transform: translateY(-16px);
        opacity: 0;
    }
}

.dd-fest-confetti {
    position: absolute;
    top: -6%;
    width: var(--cf-w);
    height: var(--cf-h);
    border-radius: 1px;
    background: var(--cf-tint);
    opacity: 0;
    animation: dd-fest-confetti-fall var(--cf-dur) linear infinite;
    animation-delay: var(--cf-delay);
    will-change: transform, opacity;
}

/* tumbles on two axes, so a ribbon flashes edge-on as it turns */
@keyframes dd-fest-confetti-fall {
    0% {
        transform: translate3d(0, 0, 0) rotateZ(0deg) rotateY(0deg);
        opacity: 0;
    }

    8% {
        opacity: 1;
    }

    50% {
        transform: translate3d(var(--cf-sway), calc(var(--fest-fall) * .5), 0)
            rotateZ(calc(var(--cf-spin) * .5)) rotateY(540deg);
    }

    88% {
        opacity: .6;
    }

    100% {
        transform: translate3d(0, var(--fest-fall), 0)
            rotateZ(var(--cf-spin)) rotateY(1080deg);
        opacity: 0;
    }
}

/* ---------- New Year: the year, set large ---------- */

.dd-fest-yearnum {
    position: absolute;
    right: 4%;
    top: 16%;
    width: 274px;
}

.dd-fest-yearnum svg {
    width: 100%;
    height: auto;
    display: block;
    filter: drop-shadow(0 8px 24px rgba(0, 0, 0, .45));
}

/* the highlight band sweeping across the numerals */
.dd-fest-yearnum-shine {
    animation: dd-fest-yearnum-sweep 4.5s ease-in-out infinite;
}

@keyframes dd-fest-yearnum-sweep {

    0%,
    45% {
        transform: translateX(0);
    }

    100% {
        transform: translateX(600px);
    }
}

/* four-point glints popping around the numerals */
.dd-fest-glint {
    position: absolute;
    width: 16px;
    height: 16px;
    margin: -8px 0 0 -8px;
    opacity: 0;
    background:
        linear-gradient(to right, transparent 46%, #fff 46%, #fff 54%, transparent 54%),
        linear-gradient(to bottom, transparent 46%, #fff 46%, #fff 54%, transparent 54%);
    animation: dd-fest-glint-pop 2.8s ease-in-out infinite;
    animation-delay: var(--gl-delay);
    filter: drop-shadow(0 0 5px var(--fest-a));
}

@keyframes dd-fest-glint-pop {

    0%,
    70%,
    100% {
        transform: scale(0) rotate(0deg);
        opacity: 0;
    }

    82% {
        transform: scale(1) rotate(45deg);
        opacity: 1;
    }
}

/* ---------- snowflake glyphs ---------- */

.dd-fest-flake-star {
    background: none;
    box-shadow: none;
    border-radius: 0;
}

.dd-fest-flake-star svg {
    width: 100%;
    height: auto;
    display: block;
    opacity: .85;
}

/* ---------- keep small screens uncluttered ---------- */

@media (max-width: 767.98px) {

    .dd-fest-santa,
    .dd-fest-cane-2,
    .dd-fest-gift-3,
    .dd-fest-tree-2,
    .dd-fest-pumpkin-2,
    .dd-fest-ghost-2,
    .dd-fest-bat-3,
    .dd-fest-bat-4,
    .dd-fest-cobweb-tr,
    .dd-fest-spider,
    .dd-fest-kite-4,
    .dd-fest-diya-4,
    .dd-fest-diya-5,
    .dd-fest-diya-6,
    .dd-fest-dandiya-3,
    .dd-fest-rakhi-3,
    .dd-fest-modak-3,
    .dd-fest-charkhi {
        display: none;
    }

    .dd-fest-moon,
    .dd-fest-sun,
    .dd-fest-crescent {
        width: 88px;
    }

    /* The per-element size lives in an inline custom property, which an
       inline style always wins — so scale down by setting `width` here rather
       than trying to redefine --pk / --tr / --d from a media query. */
    .dd-fest-pumpkin-1 {
        width: 88px;
    }

    .dd-fest-tree-1 {
        width: 100px;
    }

    .dd-fest-gift-1,
    .dd-fest-gift-2 {
        width: 40px;
    }

    .dd-fest-cane-1 {
        width: 38px;
    }

    .dd-fest-diya {
        width: 44px;
    }

    .dd-fest-dandiya {
        width: 72px;
    }

    .dd-fest-rakhi {
        width: 52px;
    }

    .dd-fest-modak {
        width: 44px;
    }

    .dd-fest-bow {
        width: 72px;
    }

    .dd-fest-ghost-1 {
        width: 48px;
    }

    /* Feature figures: keep them, scaled down — they are the point of the
       theme. The repeated ground rows thin out instead. */
    .dd-fest-ravana {
        width: 86px;
    }

    .dd-fest-ganesha {
        width: 108px;
    }

    .dd-fest-mosque {
        width: 168px;
    }

    .dd-fest-teddy {
        width: 78px;
    }

    .dd-fest-chocolates {
        width: 68px;
    }

    .dd-fest-pichkari {
        width: 132px;
    }

    .dd-fest-yearnum {
        width: 150px;
        top: 8%;
    }

    .dd-fest-champagne {
        width: 104px;
    }

    .dd-fest-thali {
        width: 68px;
    }

    .dd-fest-rose-1 {
        width: 66px;
    }

    .dd-fest-diya-1,
    .dd-fest-diya-3,
    .dd-fest-modak-2,
    .dd-fest-thali-1,
    .dd-fest-rose-2,
    .dd-fest-chocolates {
        display: none;
    }

    .dd-fest-pichkari {
        width: 138px;
    }

    .dd-fest-rangoli {
        width: 210px;
        margin-left: -105px;
    }

    .dd-fest-cobweb {
        width: 96px;
    }
}

/* ---------- ticker bullet for themes without the Chakra ---------- */

.dd-fest-ticker-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--fest-a) 0%, var(--fest-b) 100%);
    flex-shrink: 0;
}

/* ==========================================================================
   8. Accessibility / print
   ========================================================================== */

/* Scoped to this theme's own elements only — the site's other animations
   (slick carousel, dropdowns) are left alone. */
@media (prefers-reduced-motion: reduce) {

    .dd-fest-ribbon-shine,
    .dd-fest-chakra,
    .dd-fest-hero-chakra,
    .dd-fest-aurora,
    .dd-fest-smoke,
    .dd-fest-kite,
    .dd-fest-flagstand,
    .dd-fest-cloth-strip,
    .dd-fest-cloth-strip::after,
    .dd-fest-cloth-chakra,
    .dd-fest-ticker-track,
    .dd-fest-cta,
    .dd-fest-cta::after {
        animation: none !important;
        transition: none !important;
    }

    /* Hold the cloth flat rather than frozen mid-ripple, and drop the fold
       shadows that only make sense while it is moving. */
    .dd-fest-cloth-strip,
    .dd-fest-cloth-chakra {
        transform: none !important;
    }

    .dd-fest-cloth-strip::after {
        opacity: 0 !important;
    }

    /* the ticker still needs to be readable when it cannot scroll */
    .dd-fest-ticker-track {
        transform: none;
    }

    .dd-fest-ticker-run:nth-child(2) {
        display: none;
    }

    /* artwork stays, motion stops */
    .dd-fest-lantern,
    .dd-fest-lantern-glow,
    .dd-fest-pumpkin,
    .dd-fest-pumpkin-glow,
    .dd-fest-bat,
    .dd-fest-bat-wing,
    .dd-fest-ghost,
    .dd-fest-spider,
    .dd-fest-tree,
    .dd-fest-bauble,
    .dd-fest-tree-star,
    .dd-fest-santa,
    .dd-fest-gift,
    .dd-fest-cane,
    .dd-fest-pichkari,
    .dd-fest-splat,
    .dd-fest-rakhi,
    .dd-fest-sun-rays,
    .dd-fest-charkhi,
    .dd-fest-diya-flame,
    .dd-fest-diya-glow,
    .dd-fest-rangoli,
    .dd-fest-toran-bud,
    .dd-fest-crescent,
    .dd-fest-dandiya-stick,
    .dd-fest-bow-arrow,
    .dd-fest-modak,
    .dd-fest-yearnum-shine,
    .dd-fest-ravana-fire,
    .dd-fest-ravana-glow,
    .dd-fest-ganesha-halo,
    .dd-fest-teddy,
    .dd-fest-chocolates,
    .dd-fest-thali-flame,
    .dd-fest-thali-glow,
    .dd-fest-rose,
    .dd-fest-cork,
    .dd-fest-bubble {
        animation: none !important;
    }

    .dd-fest-glint {
        display: none;
    }

    /* a splat mid-fade would be invisible without its animation */
    .dd-fest-splat {
        opacity: .7;
        transform: rotate(var(--sl-rot)) scale(1);
    }

    /* purely kinetic effects have nothing to show when held still */
    .dd-fest-firework,
    .dd-fest-spark,
    .dd-fest-petal,
    .dd-fest-flake,
    .dd-fest-heart,
    .dd-fest-balloon,
    .dd-fest-gulal,
    .dd-fest-spray {
        display: none;
    }
}

@media print {

    .dd-fest-strip,
    .dd-fest-ribbon,
    .dd-fest-hero-fx {
        display: none;
    }

    .dd-fest-hero {
        background: #fff;
        box-shadow: none;
    }
}
