/* ═══════════════════════════════════════════════════════════════
   Progressive Image Loading
   ───────────────────────────────────────────────────────────────
   The HTML (text, prices, names) paints immediately; each photo
   fades in on its own as it arrives, over a shimmering skeleton.

   Usage — the WRAPPER gets .lazy-frame, the IMG gets .lazy-img:

     <div class="rp-card-image lazy-frame">
       <img class="lazy-img" loading="lazy" decoding="async"
            onload="this.classList.add('is-loaded')"
            onerror="this.classList.add('is-failed')" src="..." />
     </div>

   The wrapper MUST have a fixed height (or aspect-ratio) so the
   skeleton reserves the space and nothing shifts when the photo
   lands. .rp-card-image (260px) and .cp-gallery-item (220px)
   already do.
   ═══════════════════════════════════════════════════════════════ */

/* ---------- The skeleton: a sweeping shimmer behind the image ---------- */
.lazy-frame {
    position: relative;
    overflow: hidden;
    background-color: rgba(0, 0, 0, 0.06);
}

.lazy-frame::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(100deg,
            rgba(255, 255, 255, 0) 20%,
            rgba(255, 255, 255, 0.45) 50%,
            rgba(255, 255, 255, 0) 80%);
    background-size: 220% 100%;
    animation: lazy-shimmer 1.4s ease-in-out infinite;
    z-index: 0;
}

/* Once the photo has arrived (or failed), stop animating — an
   endlessly spinning skeleton under a loaded image wastes CPU
   and, on failure, lies to the user about work still happening. */
.lazy-frame.is-settled::before {
    display: none;
    animation: none;
}

@keyframes lazy-shimmer {
    from { background-position: 130% 0; }
    to   { background-position: -30% 0; }
}

/* ---------- The image: invisible until decoded, then fades in ----------
   Both selectors are listed so the descendant form (0,2,0) outranks
   page-level rules like `.cp-gallery-item img` (0,1,1) in catering.css,
   which loads AFTER this file and would otherwise drop the opacity
   transition. `transform` stays in the transition list so the existing
   hover zoom on gallery tiles still animates. */
.lazy-img,
.lazy-frame .lazy-img {
    position: relative;
    z-index: 1;
    opacity: 0;
    transition: opacity 0.45s ease, transform 0.4s ease;
}

.lazy-img.is-loaded,
.lazy-frame .lazy-img.is-loaded {
    opacity: 1;
}

/* A broken/missing upload must not leave a permanent shimmer.
   Show a neutral tile instead of an invisible gap. */
.lazy-img.is-failed {
    opacity: 1;
    visibility: hidden;
}

/* ---------- Accessibility ---------- */
@media (prefers-reduced-motion: reduce) {
    .lazy-frame::before {
        animation: none;
        background: none;
    }

    .lazy-img {
        transition: none;
    }
}
