/* blocks_hero_graphic — scoped styles. Cycles through 3 product PNGs and
   highlights the matching badge in the underlying SVG with an animated
   stroke trace.

   Cycle = 2s per stage. PNGs cross-fade; badge opacity snaps; stroke
   traces over the full 2s. */

.hero-graphic {
    container-type: inline-size;
    --hg-cycle: 6s;
    /* Proportional overlap (cqw = % of .hero-graphic inline size). Both the
       PNG and the SVG scale with container width, so a fixed-px overlap
       drifts off at narrow widths. -18.42cqw matches the prior -140px @ 760w
       and keeps the badges underlapping the Pre-order pill at any size. */
    --hg-svg-overlap: -18.42cqw;
    width: 80%;
    max-width: 608px;
    margin-inline: auto;
}

.hero-graphic__scene {
    position: relative;
    width: 100%;
    /* Locked to the PNG aspect — the SVG is anchored relative to the
       PNG bottom via --hg-svg-overlap, so the scene itself doesn't need
       extra height. */
    aspect-ratio: 902 / 762;
}

/* === Static PNGs ===
   Stack three full-bleed images and toggle .is-active to cross-fade. */
.hero-graphic__static {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    /* Align all three statics to the bottom — the source PNGs differ by a
       few px in height, and aligning bottom keeps the Pre-order pill in
       a fixed spot across the cycle (no button jerk). */
    object-position: center bottom;
    opacity: 0;
    z-index: 2;
    pointer-events: none;
    user-select: none;
}
/* The active static runs a keyframe animation across the whole cycle:
   fade up at the start, hold in the middle, fade out at the end. This
   gives the "dim before swap, fade up after swap" effect — relying on
   plain transitions wasn't visible because both fades fired in lockstep
   and cancelled each other out. */
.hero-graphic__static.is-active {
    animation: hg-static-show var(--hg-cycle) ease-in-out both;
}
@keyframes hg-static-show {
    /* At 4s cycle: ~800ms fade in, hold ~2.4s, ~800ms fade out. Symmetric.
       The dim points pick up a soft blur too so swaps read as the image
       drifting in and out of focus. */
    0% {
        opacity: 0.3;
        filter: blur(5px);
    }
    5% {
        opacity: 1;
        filter: blur(0px);
    }
    /*50% {
        opacity: 1;
        filter: blur(0);
    }
    80% {
        opacity: 1;
        filter: blur(0);
    }*/
    95% {
        opacity: 1;
        filter: blur(0px);
    }
    100% {
        opacity: 0.3;
        filter: blur(5px);
    }
}

/* === Dashboard SVG ===
   Sits behind the PNG. Position so the badge row aligns with where the
   "Pre-order" pill ends in the PNG. Numbers come from the Figma layout
   (badges row at frame x≈199 / y≈543 inside the 902×760 frame; SVG badge
   row starts at x=50.5, y=65.6 in its own coords). */
.hero-graphic__svg {
    position: absolute;
    /* Anchor the SVG TOP to the bottom of the PNG, then slide it up by
       --hg-svg-overlap so the badges (~38% down the SVG) underlap the
       Pre-order pill instead of sitting in a gap below it. The SVG sits
       in the default stacking layer so the next section slides over it. */
    left: 16.46%;
    top: calc(100% + var(--hg-svg-overlap));
    width: 76.16%;
}
.hero-graphic__svg-el {
    display: block;
    width: 100%;
    height: auto;
    overflow: visible;
}

/* === Badge active state ===
   When the parent container is on stage N, that badge gets full opacity
   and its sibling stroke rect runs the trace animation. */
.hero-graphic .hg-badge {
    transition: opacity 250ms ease;
}
.hero-graphic[data-stage="1"] .hg-badge--later {
    opacity: 1;
}
.hero-graphic[data-stage="2"] .hg-badge--deposit {
    opacity: 1;
}
.hero-graphic[data-stage="3"] .hg-badge--upfront {
    opacity: 1;
}

/* === Feature list ===
   Sits BEHIND the static PNG (z-index 1, static is z-index 2) so the
   product imagery in the PNG occludes the list. The window clips the
   marquee, and the list inside slides up one row per --hg-feature-step,
   wrapping seamlessly thanks to the duplicated item set in the template.
   A linear-gradient mask gives the top row full opacity and fades rows
   below it down to invisible. */
.hero-graphic__features-window {
    --hg-feature-row: 32px; /* 29px row + 3px gap (smaller than before) */
    --hg-feature-rows: 4; /* number of unique items */
    --hg-feature-cycle: 32s; /* full loop duration */
    --hg-feature-step: calc(var(--hg-feature-cycle) / var(--hg-feature-rows));

    position: absolute;
    left: 70.6%;
    top: 58.16%;
    /* Show 4 rows; the duplicates below scroll up into view. */
    height: calc(var(--hg-feature-row) * var(--hg-feature-rows));
    overflow: hidden;
    z-index: 1;
    pointer-events: none;
    /* Both ends are feathered now — items fade IN as they enter from
       the bottom and fade OUT as they exit at the top, instead of being
       cut off by a hard line. */
    -webkit-mask-image: linear-gradient(
        to bottom,
        transparent 0%,
        rgba(0, 0, 0, 0.6) 12%,
        #000 28%,
        rgba(0, 0, 0, 0.7) 50%,
        rgba(0, 0, 0, 0.4) 75%,
        transparent 100%
    );
    mask-image: linear-gradient(
        to bottom,
        transparent 0%,
        rgba(0, 0, 0, 0.6) 12%,
        #000 28%,
        rgba(0, 0, 0, 0.7) 50%,
        rgba(0, 0, 0, 0.4) 75%,
        transparent 100%
    );
}
.hero-graphic__features {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
    width: max-content;
    animation: hg-features-scroll var(--hg-feature-cycle) linear infinite;
}
.hero-graphic__feature {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 29px;
}

.hero-graphic__feature-icon {
    flex: 0 0 auto;
    width: 29px;
    height: 29px;
    border-radius: 9999px;
    background: #e7e3ff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.hero-graphic__feature-icon svg {
    width: 17px;
    height: 17px;
    display: block;
}

.hero-graphic__feature-text {
    color: #29165e;
    font-family:
        "Inter",
        system-ui,
        -apple-system,
        sans-serif;
    font-weight: 700;
    font-size: 10px;
    line-height: 1.2;
    white-space: nowrap;
}

/* Translate up by the height of the unique-item set; the second copy in
   the DOM keeps the visible set populated until the snap back to 0. */
@keyframes hg-features-scroll {
    from {
        transform: translateY(0);
    }
    to {
        transform: translateY(
            calc(-1 * var(--hg-feature-row) * var(--hg-feature-rows))
        );
    }
}

/* Hide on mobile — the list is decoration over the static, and there's no
   room for it on narrow viewports. */
@media (max-width: 767px) {
    .hero-graphic__features-window {
        display: none;
    }
}

/* === Per-stage price summary ===
   All three summary groups occupy the same spot in the SVG; only the one
   matching the active stage is visible. Soft cross-fade matches the
   static-image transition. */
.hero-graphic .hg-summary {
    opacity: 0;
    transition: opacity 250ms ease-in-out;
}
.hero-graphic[data-stage="1"] .hg-summary--later {
    opacity: 1;
}
.hero-graphic[data-stage="2"] .hg-summary--deposit {
    opacity: 1;
}
.hero-graphic[data-stage="3"] .hg-summary--upfront {
    opacity: 1;
}

/* === SVG perimeter progress trace ===
   A loading-bar style stroke that wraps around the outer card every cycle.
   Path is authored to start at the left-middle and go clockwise (up the
   left edge, across the top, down the right, across the bottom, back). */
.hero-graphic .hg-svg-trace {
    /* Progress-bar mode: dasharray=1 means the whole perimeter is one
       continuous dash. Animating dashoffset from 1 → 0 grows the visible
       stroke from the path's start point all the way around the card,
       so left stays drawn while top/right/bottom catch up. Stroke colour
       follows the active badge below. */
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    pointer-events: none;
    /* Ease-in-out so the progress bar nudges off the start point softly
       and decelerates as it reaches the end, rather than a hard linear
       slide. */
    animation: hg-stroke-trace var(--hg-cycle) ease-in-out infinite;
}
.hero-graphic[data-stage="1"] .hg-svg-trace {
    stroke: #ffe36f;
}
.hero-graphic[data-stage="2"] .hg-svg-trace {
    stroke: #dcbbf5;
}
.hero-graphic[data-stage="3"] .hg-svg-trace {
    stroke: #afebff;
}

@keyframes hg-stroke-trace {
    from {
        stroke-dashoffset: 1;
    }
    to {
        stroke-dashoffset: 0;
    }
}

/* === Offscreen pause ===
   When the section scrolls out of view the JS interval stops cycling
   stages, but CSS animations keep ticking on their own. Without this,
   the active-static animation reaches its 100% keyframe (opacity 0.3,
   blur 5px) and freezes there — so on scroll-back-in the user sees the
   dim end-state instead of the live image until the next JS tick fires.
   Pausing the animations alongside the interval keeps both halves in
   lockstep. */
.hero-graphic[data-hg-paused="1"] .hero-graphic__static.is-active,
.hero-graphic[data-hg-paused="1"] .hero-graphic__features,
.hero-graphic[data-hg-paused="1"] .hg-svg-trace {
    animation-play-state: paused;
}

@media (prefers-reduced-motion: reduce) {
    .hero-graphic__static.is-active {
        animation: none;
        opacity: 1;
    }
    .hero-graphic .hg-svg-trace {
        animation: none !important;
    }
}
