/* <x-image> (Image.php): hidden until loaded, then faded in; data-loaded is set by its
   onload/onerror. It shows its blurred preview (--placeholder) in the meantime, as the
   img's own background; once loaded the photo takes its place blurred about as much, and
   comes into focus (a crossfade would need a wrapper, which would break the classes passed
   to the img). Only with scripting, so without JS nothing stays hidden. wire.js keeps
   data-loaded across a morph, so the focus doesn't run again.
   The focus blurs through #x-image-focus (Image::focusFilter(), printed by the Layout), which
   keeps the edges opaque; clip-path: border-box then cuts what the blur spills outside, along
   the border-radius. A page without that filter gets no focus: a plain blur fringes white. */

/* animated instead of filter itself: a filter list with a url() in it doesn't interpolate */
@property --x-image-blur {
    syntax: '<length>';
    inherits: false;
    initial-value: 0px;
}
@media (scripting: enabled) {

    img[data-fade]:not([data-loaded]) {
        opacity: 0;
    }

    /* the photo itself moved out of its box (and clipped) until loaded: left in place, the
       browser would draw it over the preview strip by strip as the bytes arrive */
    img[data-placeholder]:not([data-loaded]) {
        opacity: 1;
        background: var(--placeholder) center / cover no-repeat;
        object-position: -99999px -99999px;
    }

    /* object-contain (data-fit, Image::attrs()): where the photo will be, not cropped to the box */
    img[data-placeholder][data-fit="contain"]:not([data-loaded]) {
        background-size: contain;
    }

    @media (prefers-reduced-motion: no-preference) {
        /* not one from the cache (data-loaded="cached", Image::fadeScript()): it just shows */
        img[data-fade]:not([data-loaded="cached"]) {
            transition: opacity .3s ease;
        }

        :root:has(#x-image-focus) img[data-placeholder=""][data-loaded]:not([data-fit]):not([data-loaded="cached"]) {
            animation: x-image-focus .6s ease-out;
        }

        /* transparent (data-placeholder="transparent"), or not filling its box (data-fit):
           #x-image-focus would fill the see-through parts black, a plain blur softens the
           edges as the preview's did */
        img[data-placeholder="transparent"][data-loaded]:not([data-loaded="cached"]),
        img[data-placeholder][data-fit][data-loaded]:not([data-loaded="cached"]) {
            animation: x-image-focus-soft .6s ease-out;
        }
    }
}

/* filter and clip-path only while it runs: kept on, they would cost every photo a layer of its own */
@keyframes x-image-focus {
    from {
        --x-image-blur: 10px;
        filter: blur(var(--x-image-blur)) url(#x-image-focus);
        clip-path: border-box;
    }

    to {
        --x-image-blur: 0px;
        filter: blur(var(--x-image-blur)) url(#x-image-focus);
        clip-path: border-box;
    }
}

@keyframes x-image-focus-soft {
    from {
        --x-image-blur: 10px;
        filter: blur(var(--x-image-blur));
    }

    to {
        --x-image-blur: 0px;
        filter: blur(var(--x-image-blur));
    }
}
