/* =========================================================
   Reward Bar — Unlock Tiles  (Pro feature, visual only)
   ========================================================= */

.os-reward-bar-wrap {
    box-sizing: border-box;
    margin-top: 24px;
    margin-bottom: 16px;

    /* Theme-neutral design tokens. Override any of these on the wrap
       (or on a parent like the .single-product container) to re-skin
       the Reward Bar to match a brand without forking the CSS:

       .my-theme .os-reward-bar-wrap {
           --os-rb-accent: #db2777;
           --os-rb-tile-radius: 6px;
       }
    */
    --os-rb-tile-bg:        #ffffff;
    --os-rb-tile-border:    #e2e8f0;
    --os-rb-tile-radius:    8px;
    --os-rb-tile-shadow:    0 1px 2px rgba(15, 23, 42, 0.04);
    --os-rb-tile-shadow-h:  0 8px 22px rgba(15, 23, 42, 0.10);
    --os-rb-accent:         #16a34a;
    --os-rb-accent-soft:    rgba(22, 163, 74, 0.18);
    --os-rb-accent-ring:    rgba(22, 163, 74, 0.30);
    --os-rb-text:           #0f172a;
    --os-rb-text-muted:     #64748b;
    /* Per-type accents — used for the top accent bar and the icon halo.
       Defaults are intentionally muted so the design feels modern and
       brand-neutral; themes can override per-type. */
    --os-rb-fs-accent:      #0ea5e9;
    --os-rb-fg-accent:      #f97316;
    --os-rb-gc-accent:      #a855f7;
    --os-rb-custom-accent:  #6366f1;
}

/* ── Progress track ──────────────────────────────────────── */
/* Conversion-focused redesign: a deeper, pill-shaped track reads as a
   "fuel gauge being filled up" rather than a loading indicator. The
   inset shadow gives it physical weight to anchor the reward tiles
   visually. Height bumped from 4px → 10px to comfortably host the
   rocket riding the leading edge of the fill.

   `overflow: visible` is required so the rocket pseudo-element can
   sit slightly above the track. The fill itself still has its own
   `border-radius: 999px`, so the pill shape is preserved at every
   width — there is no visual regression vs. the previous clip-based
   approach. */
.os-reward-progress {
    position: relative;
    height: 10px;
    background: linear-gradient(180deg, #f1f5f9 0%, #e2e8f0 100%);
    border-radius: 999px;
    overflow: visible;
    margin: 6px 0 22px;
    box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.08);
}

/* The fill uses a multi-stop warm→green gradient that subtly shifts
   its position on a 6s loop, creating a sense that *something is
   being earned in real time*. The `background-size: 200%` plus the
   `os-reward-gradient-shift` animation give the static green a
   living, energetic feel without any JS animation loop. */
.os-reward-progress-fill {
    position: relative;
    height: 100%;
    width: 0%;
    background: linear-gradient(
        90deg,
        #f59e0b 0%,
        #fbbf24 18%,
        #84cc16 42%,
        #22c55e 68%,
        #16a34a 100%
    );
    background-size: 200% 100%;
    border-radius: 999px;
    box-shadow:
        0 0 0 1px rgba(34, 197, 94, 0.12),
        0 2px 8px rgba(34, 197, 94, 0.28),
        inset 0 1px 0 rgba(255, 255, 255, 0.4);
    /* Springy "thrust" transition: when JS bumps the width on tier
       unlock, the fill rockets forward with a satisfying ease-out
       quint curve, then settles. Pairs with the rocket bob for a
       launch-and-cruise feel. */
    transition: width 0.85s cubic-bezier(0.22, 1, 0.36, 1);
    animation: os-reward-gradient-shift 6s ease-in-out infinite;
    overflow: visible;
    will-change: width;
}

/* 🚀 Rocket — rides the leading edge of the fill. Because it is a
   pseudo-element of the fill, it inherits the fill's width-driven
   position automatically, and the spring transition makes it
   "thrust" smoothly when a tier unlocks. The subtle bob keeps the
   rocket alive during idle moments without being distracting. */
.os-reward-progress-fill::before {
    content: "🚀";
    position: absolute;
    top: 50%;
    right: -10px;
    transform: translateY(-50%) rotate(-12deg);
    font-size: 18px;
    line-height: 1;
    filter: drop-shadow(0 2px 3px rgba(15, 23, 42, 0.25));
    animation: os-reward-rocket-bob 1.4s ease-in-out infinite;
    pointer-events: none;
    z-index: 2;
    /* Hide the rocket while the fill has zero width so it doesn't
       awkwardly hover at the very start of the track before the
       customer has selected a tier. The fill width is set via inline
       style, so we use container queries via :where() unsupported —
       fall back to opacity transition tied to width keyframes. */
    opacity: 1;
}

/* Flame / exhaust trail behind the rocket — rendered inside the fill
   so it is naturally clipped to the fill's pill shape and never
   bleeds onto the unfilled portion of the track. The trail is a
   horizontal alpha gradient that pulses slightly to imply thrust. */
.os-reward-progress-fill::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    width: 60px;
    max-width: 100%;
    height: 100%;
    background: linear-gradient(
        90deg,
        rgba(255, 255, 255, 0)    0%,
        rgba(255, 237, 213, 0.35) 55%,
        rgba(255, 255, 255, 0.7)  100%
    );
    border-top-right-radius: 999px;
    border-bottom-right-radius: 999px;
    animation: os-reward-exhaust 1.4s ease-in-out infinite;
    pointer-events: none;
    z-index: 1;
}

/* Celebratory state — triggered purely in CSS via :has() when every
   tile is unlocked (customer reached the top tier). Track gains a
   green halo that breathes, and the rocket rotates upright as if
   "landed at the goal". Degrades gracefully on engines without
   `:has()` — they simply skip the celebration, no broken UI. */
.os-reward-bar-wrap:has(.os-reward-tile.unlocked:last-child) .os-reward-progress {
    box-shadow:
        inset 0 1px 2px rgba(15, 23, 42, 0.08),
        0 0 0 2px rgba(34, 197, 94, 0.20);
    animation: os-reward-track-pulse 1.6s ease-in-out infinite;
}

.os-reward-bar-wrap:has(.os-reward-tile.unlocked:last-child) .os-reward-progress-fill::before {
    transform: translateY(-50%) rotate(0deg);
    animation: os-reward-rocket-celebrate 1.6s ease-in-out infinite;
}

/* ── Progress animations ─────────────────────────────────── */
@keyframes os-reward-gradient-shift {
    0%   { background-position: 0% 50%; }
    50%  { background-position: 100% 50%; }
    100% { background-position: 0% 50%; }
}

/* Rocket idle bob — gentle vertical sway with a tiny rotational
   wobble to look like it's hovering / thrusting in place. */
@keyframes os-reward-rocket-bob {
    0%, 100% { transform: translateY(-50%) rotate(-12deg); }
    50%      { transform: translateY(-65%) rotate(-8deg);  }
}

/* Exhaust pulse — varies the trail's opacity & length to imply
   continuous thrust output. */
@keyframes os-reward-exhaust {
    0%, 100% { opacity: 0.85; width: 55px; }
    50%      { opacity: 1;    width: 70px; }
}

@keyframes os-reward-track-pulse {
    0%, 100% { box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.08), 0 0 0 2px rgba(34, 197, 94, 0.20); }
    50%      { box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.08), 0 0 0 5px rgba(34, 197, 94, 0.10); }
}

/* Final-tier "rocket landed" celebration — small victory hop. */
@keyframes os-reward-rocket-celebrate {
    0%, 100% { transform: translateY(-50%) rotate(0deg)   scale(1);    }
    40%      { transform: translateY(-95%) rotate(-6deg)  scale(1.18); }
    70%      { transform: translateY(-35%) rotate(4deg)   scale(1.05); }
}

/* Accessibility — respect users who opted into reduced motion. The
   progress bar still works (width transition shortened, no shimmer,
   no bob, no celebration animation). The rocket remains visible and
   still anchors the leading edge — just stationary. */
@media (prefers-reduced-motion: reduce) {
    .os-reward-progress-fill {
        animation: none;
        transition: width 0.2s linear;
    }
    .os-reward-progress-fill::before {
        animation: none;
    }
    .os-reward-progress-fill::after {
        animation: none;
        opacity: 0.7;
    }
    .os-reward-bar-wrap:has(.os-reward-tile.unlocked:last-child) .os-reward-progress {
        animation: none;
    }
    .os-reward-bar-wrap:has(.os-reward-tile.unlocked:last-child) .os-reward-progress-fill::before {
        animation: none;
    }
    /* Tile-state animations: state classes still flip (so .unlocked is
       still visually distinguishable via colour + scale + ring), but
       the looping pulse, the unlock pop, the burst, and hover lift
       are all suppressed for users who opted into reduced motion. */
    .os-reward-tile,
    .os-reward-tile.unlocked,
    .os-reward-tile.next-target {
        transition: none;
        animation: none;
    }
    .os-reward-tile:hover {
        transform: none;
    }
    .os-reward-tile.unlocked .os-reward-icon::after {
        animation: none;
        display: none;
    }
    .os-reward-lock {
        transition: none;
    }
}

/* ── Tile row — always 3 columns via grid ────────────────── */
.os-reward-bar {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 10px;
    width: 100%;
    box-sizing: border-box;
}

/* ── Individual tile ─────────────────────────────────────────────────
   Unified shell for every tile. Type identity (Free Shipping, Free Gift,
   Gift Card, Custom) is communicated by:
     1. a thin top accent bar (`::before`) coloured via --os-rb-*-accent
     2. a soft icon halo behind the icon glyph
   Borders, radii, paddings, and shadows are now identical across types,
   fixing the previous Free-Shipping dashed-border inconsistency.
   ────────────────────────────────────────────────────────────────── */
.os-reward-tile {
    --os-rb-this-accent: var(--os-rb-custom-accent);

    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 4px;
    padding: 9px 10px 9px;
    border-radius: var(--os-rb-tile-radius);
    border: 1px solid var(--os-rb-tile-border);
    background: var(--os-rb-tile-bg);
    box-shadow: var(--os-rb-tile-shadow);
    min-width: 0;
    text-align: center;
    cursor: default;
    box-sizing: border-box;
    overflow: hidden;
    transition:
        opacity 0.3s ease,
        transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1),
        filter 0.3s ease,
        box-shadow 0.3s ease,
        border-color 0.3s ease;
}

/* Top accent bar — type identity without breaking layout. */
.os-reward-tile::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: var(--os-rb-this-accent);
    opacity: 0.85;
    transition: opacity 0.3s ease, height 0.3s ease;
    pointer-events: none;
}

/* Type accents — only set --os-rb-this-accent on the type variants;
   border / shape stays uniform. */
.os-reward-tile.os-reward-free-shipping { --os-rb-this-accent: var(--os-rb-fs-accent); }
.os-reward-tile.os-reward-free-gift     { --os-rb-this-accent: var(--os-rb-fg-accent); }
.os-reward-tile.os-reward-gift-card     { --os-rb-this-accent: var(--os-rb-gc-accent); }

/* Hover — purely cosmetic feedback (tiles are info-display, not
   interactive). Lifts the tile, deepens the shadow, brightens the
   accent. Not applied while reduced-motion is on (handled below). */
.os-reward-tile:hover {
    transform: translateY(-2px);
    box-shadow: var(--os-rb-tile-shadow-h);
}
.os-reward-tile:hover::before {
    opacity: 1;
    height: 3px;
}

/* Focus-visible — graceful no-op today (the renderer emits a div),
   but ready if a theme ever wraps tiles in <a> / <button>. */
.os-reward-tile:focus-visible {
    outline: 2px solid var(--os-rb-this-accent);
    outline-offset: 2px;
}

/* ── Inner elements ──────────────────────────────────────── */
.os-reward-tile .os-reward-icon {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    margin: 0;
    border-radius: 50%;
    background: color-mix(in srgb, var(--os-rb-this-accent) 14%, transparent);
    font-size: 17px;
    line-height: 1;
    transition: background 0.3s ease, transform 0.3s ease, filter 0.3s ease;
}

.os-reward-tile .os-reward-icon img {
    width: 22px !important;
    height: 22px !important;
}

.os-reward-title {
    font-size: 12px;
    font-weight: 600;
    color: var(--os-rb-text);
    line-height: 1.3;
    letter-spacing: 0.01em;
}

.os-reward-value {
    font-size: 11px;
    font-weight: 700;
    color: var(--os-rb-this-accent);
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

.os-reward-lock {
    position: absolute;
    top: 4px;
    right: 4px;
    font-size: 10px;
    line-height: 1;
    opacity: 1;
    transform: scale(1);
    transition: opacity 0.25s ease, transform 0.25s ease;
    pointer-events: none;
}

/* ── State: locked ───────────────────────────────────────── */
.os-reward-tile.locked {
    opacity: 0.55;
}
.os-reward-tile.locked .os-reward-icon {
    filter: grayscale(70%);
}
.os-reward-tile.locked .os-reward-value {
    color: var(--os-rb-text-muted);
}

/* ── State: next-target — the lowest-threshold tile still locked.
   Driven by JS in offerstack-reward-bar.js. Mutually exclusive with
   .unlocked. Falls back to identical-to-locked styling on engines
   that don't load this CSS. ───────────────────────────────────────── */
.os-reward-tile.next-target {
    opacity: 1;
    border-color: color-mix(in srgb, var(--os-rb-this-accent) 55%, var(--os-rb-tile-border));
    box-shadow:
        0 0 0 3px color-mix(in srgb, var(--os-rb-this-accent) 22%, transparent),
        var(--os-rb-tile-shadow-h);
    animation: os-reward-next-pulse 1.8s ease-in-out infinite;
}
.os-reward-tile.next-target .os-reward-icon {
    filter: none;
    background: color-mix(in srgb, var(--os-rb-this-accent) 22%, transparent);
    transform: scale(1.03);
}
.os-reward-tile.next-target .os-reward-value {
    color: var(--os-rb-this-accent);
}
.os-reward-tile.next-target::after {
    content: "NEXT";
    position: absolute;
    top: 4px;
    left: 4px;
    font-size: 7px;
    font-weight: 700;
    letter-spacing: 0.08em;
    padding: 1px 4px;
    border-radius: 999px;
    color: #fff;
    background: var(--os-rb-this-accent);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.18);
}

/* ── State: unlocked ─────────────────────────────────────── */
.os-reward-tile.unlocked {
    opacity: 1;
    transform: scale(1.025);
    border-color: color-mix(in srgb, var(--os-rb-accent) 45%, var(--os-rb-tile-border));
    box-shadow:
        0 0 0 2px var(--os-rb-accent-ring),
        0 5px 14px rgba(22, 163, 74, 0.16);
    animation: os-reward-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.os-reward-tile.unlocked::before {
    background: var(--os-rb-accent);
    opacity: 1;
    height: 3px;
}
.os-reward-tile.unlocked .os-reward-icon {
    filter: none;
    background: var(--os-rb-accent-soft);
}
.os-reward-tile.unlocked .os-reward-icon::after {
    content: "";
    position: absolute;
    inset: -8px;
    border-radius: 50%;
    background: radial-gradient(
        circle,
        var(--os-rb-accent-soft) 0%,
        transparent 70%
    );
    animation: os-reward-burst 0.65s ease-out 1 forwards;
    pointer-events: none;
}
.os-reward-tile.unlocked .os-reward-value {
    color: var(--os-rb-accent);
}
.os-reward-tile.unlocked .os-reward-lock {
    opacity: 0;
    transform: scale(0);
}

/* ── Animations ──────────────────────────────────────────── */
@keyframes os-reward-pop {
    0%   { transform: scale(1);    }
    60%  { transform: scale(1.06); }
    100% { transform: scale(1.025); }
}

/* One-shot radial burst behind the icon when a tile transitions to
   `.unlocked`. Plays once via animation-fill-mode: forwards so the
   burst settles invisible. */
@keyframes os-reward-burst {
    0%   { opacity: 0;   transform: scale(0.6); }
    35%  { opacity: 0.75; transform: scale(1.05); }
    100% { opacity: 0;   transform: scale(1.5); }
}

/* Soft, brand-neutral pulse for the next-target tile — concentric
   ring breathes 1× per 1.8s on top of the static box-shadow. */
@keyframes os-reward-next-pulse {
    0%, 100% {
        box-shadow:
            0 0 0 3px color-mix(in srgb, var(--os-rb-this-accent) 20%, transparent),
            var(--os-rb-tile-shadow-h);
    }
    50% {
        box-shadow:
            0 0 0 5px color-mix(in srgb, var(--os-rb-this-accent) 8%, transparent),
            var(--os-rb-tile-shadow-h);
    }
}

/* ── Mobile: keep 3 columns, shrink content ─────────────── */
@media (max-width: 768px) {
    .os-reward-bar-wrap {
        width: 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
    }
    .os-reward-bar {
        gap: 6px;
    }
}

@media (max-width: 480px) {
    .os-reward-tile {
        padding: 7px 7px 7px;
        gap: 3px;
    }
    .os-reward-tile .os-reward-icon {
        width: 28px;
        height: 28px;
        font-size: 14px;
    }
    .os-reward-tile .os-reward-icon img {
        width: 18px !important;
        height: 18px !important;
    }
    .os-reward-title {
        font-size: 11px;
    }
    .os-reward-value {
        font-size: 10px;
    }
    .os-reward-lock {
        font-size: 8px;
        top: 2px;
        right: 2px;
    }
    .os-reward-tile.next-target::after {
        font-size: 6px;
        padding: 0 4px;
    }
    .os-reward-progress {
        margin-bottom: 10px;
    }
}
