/* CP Pricing Table — sticky footer promo banner. Defensively scoped under .cppt. */

.cppt .cppt-banner {
    /* Token defaults — overridden by inline style from the Settings → Banner colours tab */
    --cppt-banner-bg: var(--cppt-text-dark, #131413);
    --cppt-banner-bg-active: #0f3d2c;
    --cppt-banner-bg-hurry: #3d0f12;
    --cppt-banner-text: #ffffff;
    --cppt-banner-badge-offer-bg: var(--cppt-focus, #27c2f3);
    --cppt-banner-badge-active-bg: #16a34a;
    --cppt-banner-badge-hurry-bg: #dc2626;
    --cppt-banner-button-bg: var(--cppt-focus, #27c2f3);
    --cppt-banner-button-text: #ffffff;
    --cppt-banner-current-bg: var(--cppt-banner-bg);

    position: fixed;
    left: 16px;
    right: 16px;
    bottom: 16px;
    z-index: 99999;
    background: linear-gradient(135deg,
        color-mix(in srgb, var(--cppt-banner-current-bg) 100%, transparent),
        color-mix(in srgb, var(--cppt-banner-current-bg) 70%, #000000));
    color: var(--cppt-banner-text);
    border-radius: var(--cppt-radius);
    border: 2px solid #ffffff35;
    box-shadow: 0 18px 48px rgba(15, 23, 42, 0.35);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    line-height: 1.4;
    max-width: 1200px;
    margin: 0 auto;
    animation: cppt-banner-enter 0.5s cubic-bezier(.16,1.36,.34,1) both;
    transition: background 0.4s ease;
}

/* Stage swaps which colour the gradient derives from */
.cppt .cppt-banner[data-cppt-banner-stage="offer"]  { --cppt-banner-current-bg: var(--cppt-banner-bg); }
.cppt .cppt-banner[data-cppt-banner-stage="active"] { --cppt-banner-current-bg: var(--cppt-banner-bg-active); }
.cppt .cppt-banner[data-cppt-banner-stage="hurry"]  { --cppt-banner-current-bg: var(--cppt-banner-bg-hurry); }

@keyframes cppt-banner-enter {
    0% { transform: translateY(120%); opacity: 0; }
    100% { transform: translateY(0); opacity: 1; }
}

/* ---------- Position variants ---------- */

.cppt .cppt-banner--bottom {
    /* Defaults already match: left: 16, right: 16, bottom: 16. Nothing to do. */
}

/* Edge-connected variants: flush to the viewport edges, square corners, and a
   single border on the side that faces the page content. The base rule's 2px
   border is deliberately reset to 0 first — on a strip that bleeds off three
   screen edges, three of its four sides are invisible anyway and the fourth is
   the only one doing any work. */
.cppt .cppt-banner--top,
.cppt .cppt-banner--bottom-full {
    left: 0;
    right: 0;
    width: 100%;
    max-width: none;
    margin: 0;
    border: 0;
    border-radius: 0;
}

.cppt .cppt-banner--top {
    top: 0;
    bottom: auto;
    border-bottom: 2px solid var(--cppt-banner-edge-border, #ffffff35);
    animation-name: cppt-banner-enter-top;
}

/* WP admin bar. #wpadminbar is position:fixed at top:0, and so is this strip —
   so for a logged-in user the two overlap. Offset by the height WP itself
   publishes on <html> (--wp-admin--admin-bar--height: 32px, 46px at <=782px)
   rather than hardcoding, so it tracks core. The variable only exists when
   admin-bar.css is loaded, and body.admin-bar only exists when the bar renders,
   so logged-out visitors are untouched either way. */
body.admin-bar .cppt .cppt-banner--top {
    top: var(--wp-admin--admin-bar--height, 32px);
}

.cppt .cppt-banner--bottom-full {
    top: auto;
    bottom: 0;
    border-top: 2px solid var(--cppt-banner-edge-border, #ffffff35);
    animation-name: cppt-banner-enter;
}
.cppt .cppt-banner--bottom-full.is-leaving {
    animation: cppt-banner-leave-bottom 0.35s cubic-bezier(.16,1.36,.34,1) both;
}
@keyframes cppt-banner-enter-top {
    0%   { transform: translateY(-100%); opacity: 0; }
    100% { transform: translateY(0);     opacity: 1; }
}

/* Side floating cards: anchored low (toward the footer) so they don’t
   eclipse hero / nav content. Pure horizontal slide-in/out — no vertical
   centring transform — keeps the enter / leave keyframes simple. */
.cppt .cppt-banner--left,
.cppt .cppt-banner--right {
    top: auto;
    bottom: 40px;
    width: 340px;
    max-width: calc(100vw - 40px);
    margin: 0;
}
.cppt .cppt-banner--left {
    left: 20px;
    right: auto;
    animation-name: cppt-banner-enter-left;
}
.cppt .cppt-banner--right {
    right: 20px;
    left: auto;
    animation-name: cppt-banner-enter-right;
}
@keyframes cppt-banner-enter-left {
    0%   { transform: translateX(-130%); opacity: 0; }
    100% { transform: translateX(0);     opacity: 1; }
}
@keyframes cppt-banner-enter-right {
    0%   { transform: translateX(130%); opacity: 0; }
    100% { transform: translateX(0);    opacity: 1; }
}

/* Side-card layout — vertical instead of horizontal strip */
.cppt .cppt-banner--left .cppt-banner__inner,
.cppt .cppt-banner--right .cppt-banner__inner {
    flex-direction: column;
    align-items: stretch;
    padding: 26px 22px 22px;
    gap: 16px;
    flex-wrap: nowrap;
}
.cppt .cppt-banner--left .cppt-banner__state,
.cppt .cppt-banner--right .cppt-banner__state {
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 14px;
    min-width: 0;
}
.cppt .cppt-banner--left .cppt-banner__badge,
.cppt .cppt-banner--right .cppt-banner__badge {
    align-self: center;
}
.cppt .cppt-banner--left .cppt-banner__message,
.cppt .cppt-banner--right .cppt-banner__message {
    min-width: 0;
    text-align: center;
    flex: 0 0 auto;
}
.cppt .cppt-banner--left .cppt-banner__cta,
.cppt .cppt-banner--right .cppt-banner__cta {
    width: 100%;
    justify-content: center;
}
.cppt .cppt-banner--left .cppt-banner__timer,
.cppt .cppt-banner--right .cppt-banner__timer {
    align-self: center;
}

/* ---------- Exit animations (top / left / right only) ----------
   Bottom uses the simple [hidden] attribute since there’s no in-flow
   neighbour to coordinate with. The other positions slide back to their
   home edge while body padding (top) drains in parallel — a single,
   coordinated motion. */
.cppt .cppt-banner--top.is-leaving {
    animation: cppt-banner-leave-top 0.35s cubic-bezier(.16,1.36,.34,1) both;
}
.cppt .cppt-banner--left.is-leaving {
    animation: cppt-banner-leave-left 0.35s cubic-bezier(.16,1.36,.34,1) both;
}
.cppt .cppt-banner--right.is-leaving {
    animation: cppt-banner-leave-right 0.35s cubic-bezier(.16,1.36,.34,1) both;
}
@keyframes cppt-banner-leave-top {
    0%   { transform: translateY(0);    opacity: 1; }
    100% { transform: translateY(-100%); opacity: 0; }
}
@keyframes cppt-banner-leave-left {
    0%   { transform: translateX(0);    opacity: 1; }
    100% { transform: translateX(-130%); opacity: 0; }
}
@keyframes cppt-banner-leave-right {
    0%   { transform: translateX(0);   opacity: 1; }
    100% { transform: translateX(130%); opacity: 0; }
}

/* ---------- Mobile: every non-bottom position falls back to the bottom strip ---------- */
@media (max-width: 600px) {
    .cppt .cppt-banner--top,
    .cppt .cppt-banner--left,
    .cppt .cppt-banner--right {
        top: auto;
        left: 8px;
        right: 8px;
        bottom: 8px;
        width: auto;
        max-width: none;
        transform: none;
        border-radius: var(--cppt-radius);
        animation-name: cppt-banner-enter;
    }
    /* Explicit reset, not redundant: the admin-bar offset above is (0,3,1) and
       media queries add no specificity, so without this the strip would stay
       pinned at top:32px instead of collapsing to the bottom. WP also switches
       #wpadminbar to position:absolute at this width, so it scrolls away and
       there is nothing left to clear. */
    body.admin-bar .cppt .cppt-banner--top {
        top: auto;
    }
    .cppt .cppt-banner--top.is-leaving,
    .cppt .cppt-banner--left.is-leaving,
    .cppt .cppt-banner--right.is-leaving {
        animation-name: cppt-banner-leave-bottom;
    }
    .cppt .cppt-banner--left .cppt-banner__inner,
    .cppt .cppt-banner--right .cppt-banner__inner {
        flex-direction: row;
        align-items: center;
        gap: 16px;
        padding: 12px 56px 12px 18px;
    }
    .cppt .cppt-banner--left .cppt-banner__state,
    .cppt .cppt-banner--right .cppt-banner__state {
        flex-direction: row;
        text-align: left;
    }
    .cppt .cppt-banner--left .cppt-banner__cta,
    .cppt .cppt-banner--right .cppt-banner__cta {
        width: auto;
    }
}
@keyframes cppt-banner-leave-bottom {
    0%   { transform: translateY(0);    opacity: 1; }
    100% { transform: translateY(120%); opacity: 0; }
}

.cppt .cppt-banner[hidden] { display: none; }

.cppt .cppt-banner__inner {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 8px 20px;
    position: relative;
    flex-wrap: wrap;
}

.cppt .cppt-banner__state {
    display: flex;
    align-items: center;
    gap: 14px;
    flex: 1;
    min-width: 0;
    flex-wrap: wrap;
    justify-content: center;
}
.cppt .cppt-banner__state[hidden] { display: none; }

.cppt .cppt-banner__badge {
    background: var(--cppt-banner-badge-offer-bg);
    color: var(--cppt-banner-button-text);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    padding: 6px 10px;
    border-radius: var(--cppt-radius-pill);
    white-space: nowrap;
    line-height: 1;
    flex-shrink: 0;
    transition: background 0.3s ease;
}
.cppt .cppt-banner__badge--active {
    background: var(--cppt-banner-badge-active-bg);
}
.cppt .cppt-banner.is-hurry .cppt-banner__badge--active {
    background: var(--cppt-banner-badge-hurry-bg);
    animation: cppt-banner-hurry-pulse 1.2s ease-in-out infinite;
}
@keyframes cppt-banner-hurry-pulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.06); }
}

.cppt .cppt-banner__message {
    margin: 0;
    font-size: 14px;
    color: var(--cppt-banner-text);
    min-width: 220px;
}

/* ---------- Apply button (eye-catching) ----------
   !important on padding / background / border-radius / box-shadow / text-*
   because Elementor and most themes globally style `button { ... }` with
   high-specificity hover/focus rules that otherwise leak through. */
.cppt .cppt-banner__cta {
    appearance: none;
    -webkit-appearance: none;
    background: var(--cppt-banner-button-bg) !important;
    background-image: none !important;
    color: var(--cppt-banner-button-text) !important;
    border: 0 !important;
    padding: 11px 18px !important;
    margin: 0 !important;
    border-radius: var(--cppt-control-radius, var(--cppt-radius-pill)) !important;
    font-family: inherit !important;
    font-size: 13px !important;
    font-weight: 700 !important;
    /* letter-spacing locally overrides the global reset's "normal" — kept for
       the slight tracking the button design wants. */
    letter-spacing: 0.02em !important;
    text-decoration: none !important;
    text-transform: none !important;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: filter 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
    line-height: 1 !important;
    position: relative;
    isolation: isolate;
    animation: cppt-cta-breathe 2.4s ease-in-out infinite;
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--cppt-banner-button-bg) 60%, transparent),
                0 4px 14px rgba(0, 0, 0, 0.18) !important;
}
.cppt .cppt-banner__cta::before {
    content: "";
    position: absolute;
    inset: -2px;
    border-radius: inherit;
    border: 2px solid var(--cppt-banner-button-bg);
    opacity: 0;
    z-index: -1;
    animation: cppt-cta-ring 2.4s ease-out infinite;
}
.cppt .cppt-banner__cta::after {
    content: "";
    position: absolute;
    top: 0; left: 0;
    width: 40%; height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
    transform: skewX(-20deg);
    border-radius: inherit;
    z-index: -1;
    animation: cppt-cta-sheen 3.6s ease-in-out infinite;
}
.cppt .cppt-banner__cta:hover,
.cppt .cppt-banner__cta:focus {
    background: var(--cppt-banner-button-bg) !important;
    background-image: none !important;
    color: var(--cppt-banner-button-text) !important;
    text-decoration: none !important;
    filter: brightness(1.08);
    transform: translateY(-1px);
}
.cppt .cppt-banner__cta:active {
    background: var(--cppt-banner-button-bg) !important;
    transform: translateY(0) scale(0.97);
}
.cppt .cppt-banner__cta:focus-visible {
    outline: 2px solid var(--cppt-banner-text);
    outline-offset: 2px;
}

@keyframes cppt-cta-breathe {
    0%, 100% { transform: scale(1);    box-shadow: 0 0 0 0 color-mix(in srgb, var(--cppt-banner-button-bg) 60%, transparent), 0 4px 14px rgba(0, 0, 0, 0.18); }
    50%      { transform: scale(1.04); box-shadow: 0 0 0 6px color-mix(in srgb, var(--cppt-banner-button-bg) 25%, transparent), 0 6px 20px rgba(0, 0, 0, 0.28); }
}
@keyframes cppt-cta-ring {
    0%   { transform: scale(1);    opacity: 0.65; }
    80%  { transform: scale(1.45); opacity: 0; }
    100% { transform: scale(1.45); opacity: 0; }
}
@keyframes cppt-cta-sheen {
    0%, 60% { left: 0%; }
    100%    { left: 80px; }
}

@media (prefers-reduced-motion: reduce) {
    .cppt .cppt-banner { animation: none; }
    .cppt .cppt-banner__cta { animation: none; }
    .cppt .cppt-banner__cta::before,
    .cppt .cppt-banner__cta::after { animation: none; }
}

/* ---------- Countdown ---------- */
.cppt .cppt-banner__timer {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: rgba(255, 255, 255, 0.08);
    padding: 4px 8px;
    border-radius: 10px;
    flex-shrink: 0;
}
.cppt .cppt-banner__timer-ico {
    width: 16px;
    height: 16px;
    color: var(--cppt-banner-badge-active-bg);
    flex-shrink: 0;
    display: block;
    transition: color 0.3s ease;
}
.cppt .cppt-banner.is-hurry .cppt-banner__timer-ico {
    color: var(--cppt-banner-badge-hurry-bg);
}
.cppt .cppt-banner__timer-unit {
    display: inline-flex;
    flex-direction: row;
    align-items: baseline;
    gap: 1px;
}
.cppt .cppt-banner__timer-num {
    font-size: 17px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}
.cppt .cppt-banner__timer-label {
    font-size: 11px;
    color: color-mix(in srgb, var(--cppt-banner-text) 65%, transparent);
    letter-spacing: 0.04em;
    font-weight: 600;
}
.cppt .cppt-banner__timer-sep {
    font-size: 16px;
    font-weight: 700;
    color: color-mix(in srgb, var(--cppt-banner-text) 40%, transparent);
}

/* ---------- "View Pricing" inline link (shown in active + hurry stages) ----------
   The global .cppt button reset locks text-decoration: none !important to
   defeat theme `button { text-decoration: underline }` rules. This rule
   re-asserts the underline (with same priority, higher specificity), so the
   intended underline still shows. */
/* Bordered outline button, sitting after the countdown. Deliberately NOT a
   filled button: the filled treatment belongs to "Apply", and two solid buttons
   in one strip would compete. The !important run mirrors the Apply button's —
   host themes and page builders style bare <button> aggressively. */
.cppt .cppt-banner__view-pricing {
    appearance: none;
    background: transparent !important;
    background-image: none !important;
    border: 1px dashed currentColor !important;
    padding: 8px 16px !important;
    margin: 0 !important;
    color: var(--cppt-banner-text) !important;
    font: inherit;
    font-size: 13px !important;
    font-weight: 700 !important;
    text-decoration: none !important;
    text-transform: none !important;
    letter-spacing: 0.01em;
    border-radius: var(--cppt-control-radius, 999px) !important;
    cursor: pointer;
    opacity: 0.9;
    transition: opacity 0.15s ease, background-color 0.15s ease, color 0.15s ease;
    flex-shrink: 0;
    white-space: nowrap;
    line-height: 1.2 !important;
    box-shadow: none !important;
}
/* Fills on hover — the border colour becomes the fill and the label flips to
   the banner background, so it reads as "activating" without a new token. */
.cppt .cppt-banner__view-pricing:hover,
.cppt .cppt-banner__view-pricing:focus {
    background: var(--cppt-banner-text) !important;
    background-image: none !important;
    color: var(--cppt-banner-current-bg) !important;
    text-decoration: none !important;
    box-shadow: none !important;
    opacity: 1;
}
.cppt .cppt-banner__view-pricing:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 3px;
    border-radius: 2px;
}
/* Stretch full-width inside the side floating cards (vertical layout) */
.cppt .cppt-banner--left .cppt-banner__view-pricing,
.cppt .cppt-banner--right .cppt-banner__view-pricing {
    align-self: center;
}

/* "ENDS IN" lead-in before the digits. Uppercase + tracked so it reads as a
   label rather than part of the countdown, and hidden on the narrow side-card
   layouts where horizontal room is scarce. */
.cppt .cppt-banner__timer-lead {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0.75;
    white-space: nowrap;
}
.cppt .cppt-banner--left .cppt-banner__timer-lead,
.cppt .cppt-banner--right .cppt-banner__timer-lead {
    display: none;
}

/* ---------- Dismiss ---------- */
.cppt .cppt-banner__close {
    position: absolute;
    top: 8px;
    right: 8px;
    appearance: none;
    background: transparent !important;
    background-image: none !important;
    border: 0 !important;
    color: rgba(255, 255, 255, 0.65) !important;
    padding: 6px !important;
    margin: 0 !important;
    border-radius: 6px !important;
    cursor: pointer;
    line-height: 0 !important;
    box-shadow: none !important;
    text-decoration: none !important;
}
.cppt .cppt-banner__close:hover,
.cppt .cppt-banner__close:focus {
    color: #fff !important;
    background: rgba(255, 255, 255, 0.08) !important;
    background-image: none !important;
    box-shadow: none !important;
    text-decoration: none !important;
}
.cppt .cppt-banner__close:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 1px;
}

@media (max-width: 700px) {
    /* Edge-connected variants must stay flush. Without the :not() guards this
       rule inset --top by 8px between 601px and 700px (the 600px block below
       only re-collapses it under 600px), leaving a floating strip with square
       corners. --bottom-full is a full-width bottom strip at every width, so it
       is excluded at all breakpoints. */
    .cppt .cppt-banner:not(.cppt-banner--top):not(.cppt-banner--bottom-full) {
        left: 8px;
        right: 8px;
        bottom: 8px;
    }
    .cppt .cppt-banner__inner {
        padding: 10px 15px;
    }
    .cppt .cppt-banner__message {
        font-size: 13px;
        min-width: 100%;
    }
    .cppt .cppt-banner__timer {
        padding: 6px 10px;
    }
    .cppt .cppt-banner__timer-num {
        font-size: 14px;
    }
}

/* Bottom strip pushes content up; top strip pushes content down.
   The transition lives on `body` unconditionally (scoped to pages that load
   our CSS) so it animates symmetrically: padding ramps up when the banner
   slides in and ramps back to 0 when the banner slides out — single
   coordinated motion paired with the cppt-banner-leave-* keyframes.
   Left / right floats overlay the page and don’t touch body padding. */
body {
    transition: padding-top 0.35s cubic-bezier(.16,1.36,.34,1),
                padding-bottom 0.35s cubic-bezier(.16,1.36,.34,1);
}
body.cppt-has-banner-bottom {
    padding-bottom: 100px;
}
body.cppt-has-banner-top {
    padding-top: var(--cppt-banner-top-height, 64px);
}
/* Measured by banner.js, same as the top strip — the hardcoded 100px used by
   the floating bottom card is wrong for an edge-connected strip whose height
   varies with the message length. */
body.cppt-has-banner-bottom-full {
    padding-bottom: var(--cppt-banner-bottom-height, 64px);
}
@media (max-width: 600px) {
    /* Mobile: top falls back to bottom strip — swap the padding too. */
    body.cppt-has-banner-top {
        padding-top: 0;
        padding-bottom: 100px;
    }
}

/* ---------- Elementor sticky-header compatibility ----------
 *
 * The body padding above makes room for the banner in normal flow, but an
 * Elementor element that becomes sticky is switched to `position: fixed` with
 * `top: 0` as an INLINE style. Fixed elements are positioned against the
 * viewport, so they ignore that padding entirely and land underneath our strip.
 *
 * !important is unavoidable here: the competing declaration is inline, and
 * inline beats any external selector regardless of specificity.
 *
 * TWO subtleties in the selector, both learned the hard way:
 *
 * 1. It matches "; top: " (or "top: " at the very start) rather than "top: 0".
 *    Elementor always writes `margin-top: 0px` alongside, and "margin-top: 0px"
 *    CONTAINS the substring "top: 0" — so the naive match also fired on elements
 *    Elementor had deliberately offset (e.g. top: 105px), overwriting their
 *    offset. Requiring the preceding "; " excludes margin-top, and the ^= arm
 *    covers the case where `top` happens to be serialised first.
 *
 * 2. It sets margin-top, not top. margin-top ADDS to whatever offset Elementor
 *    already applied, so a header at top: 105px ends up at 105px + banner height
 *    instead of being yanked back to the banner height. Setting `top` would
 *    discard their offset.
 *
 * Elementor sticks to the BOTTOM by setting `bottom` and leaving `top` auto, so
 * those elements have no "; top: " and are never touched by the first rule.
 *
 * Both rules self-disable: the body class is removed when the banner is
 * dismissed or expires, and the sticky element returns to the viewport edge.
 */
body.cppt-has-banner-top .elementor-sticky--active[style*="; top: "],
body.cppt-has-banner-top .elementor-sticky--active[style^="top: "] {
    margin-top: var(--cppt-banner-top-height, 64px) !important;
    transition: margin-top 0.25s ease;
}
body.cppt-has-banner-bottom-full .elementor-sticky--active[style*="; bottom: "],
body.cppt-has-banner-bottom-full .elementor-sticky--active[style^="bottom: "] {
    margin-bottom: var(--cppt-banner-bottom-height, 64px) !important;
    transition: margin-bottom 0.25s ease;
}

/* Below 600px the top banner collapses to a bottom strip (see the media query
   above), so a top-stuck header must go back to the viewport edge or it would
   sit with an unexplained gap above it. */
@media (max-width: 600px) {
    body.cppt-has-banner-top .elementor-sticky--active[style*="; top: "],
    body.cppt-has-banner-top .elementor-sticky--active[style^="top: "] {
        margin-top: 0 !important;
    }
}

/* ---------- Confetti celebration (mounted inside the pricing wrapper) ---------- */
.cppt-confetti {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 30;
    overflow: visible;
}
.cppt-confetti__piece {
    position: absolute;
    top: -18px;
    width: 8px;
    height: 14px;
    border-radius: 2px;
    opacity: 0;
    animation-name: cppt-confetti-fall;
    animation-timing-function: cubic-bezier(.18, .6, .42, 1);
    animation-fill-mode: forwards;
    transform-origin: center;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
}
.cppt-confetti__piece--ribbon {
    border-radius: 1px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
@keyframes cppt-confetti-fall {
    0%   { transform: translate3d(0, 0, 0) rotate(0deg); opacity: 1; }
    100% { transform: translate3d(var(--cppt-confetti-x, 0px), 540px, 0) rotate(var(--cppt-confetti-r, 720deg)); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .cppt-confetti { display: none; }
}
