/* public/assets/css/skeleton.css
   ────────────────────────────────────────────────────────────────────
   Site-wide loading skeleton ("swip gris"). The preloader tries to load
   every image first; anything still loading once it lifts shows this
   animated grey sweep until it is displayed — like the profile feed.

   Driven by skeleton.js:
     - img.ffsk-img            → grey rounded box + sweep, covered once the
                                 image paints (→ .ffsk-done).
     - .ffsk-block             → sweep overlay (::after) for a <video> or a
                                 CSS background element (slider, hero…).
     - .ffsk-text              → grey rectangle the width of the text, for
                                 text grouped with a still-loading image.
     - .ffsk-reveal            → fade-in once loaded.

   !important is used on the image background so per-page rules (e.g.
   `img { background:#000 }`) can't hide the sweep. Degrades gracefully:
   with no JS nothing is touched. */

@keyframes ffsk-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}
/* Reveal as a focus-in (blur → sharp), NOT an opacity fade. A fade from
   transparent would briefly show whatever sits behind the media — black on
   the dark slider / featured band. Blur keeps the pixels fully opaque. */
@keyframes ffsk-reveal-in {
    from { filter: blur(10px); }
    to   { filter: blur(0); }
}

/* ── Images still loading ── */
img.ffsk-img {
    border-radius: 8px !important;
    background-color: var(--ff-gray-2) !important;
    background-image: linear-gradient(100deg,
        transparent 30%,
        var(--ff-white-a60) 50%,
        transparent 70%) !important;
    background-size: 200% 100% !important;
    background-repeat: no-repeat !important;
    background-position: 0 0 !important;
    animation: ffsk-shimmer 1.3s linear infinite !important;
}
img.ffsk-img.ffsk-done {
    animation: none !important;
    background-image: none !important;
    background-color: transparent !important;
}

/* ── Block media (video / CSS background element) ──
   The element keeps loading underneath; a sweep overlay sits on top.
   (Positioning is handled in JS only when the element is `static`, so we
   never break already-positioned elements like absolute slider slides.) */
.ffsk-block::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    border-radius: inherit;
    background-color: var(--ff-gray-2);
    background-image: linear-gradient(100deg,
        transparent 30%,
        var(--ff-white-a60) 50%,
        transparent 70%);
    background-size: 200% 100%;
    background-repeat: no-repeat;
    animation: ffsk-shimmer 1.3s linear infinite;
    opacity: 1;
    transition: opacity 0.4s ease;
}
/* Reveal: the loaded media is already painted underneath, so we fade the
   grey overlay OUT (never the element from transparent → no dark flash). */
.ffsk-block.ffsk-block-out::after {
    opacity: 0;
    animation: none;
}

/* ── Text grouped with a loading image ──
   A rectangle the width/height of the text: the real text stays in place
   (keeps the box size) but is made transparent and overlaid with sweep. */
.ffsk-text {
    color: transparent !important;
    border-radius: 6px;
    width: -moz-fit-content;
    width: fit-content;
    max-width: 100%;
    background-color: var(--ff-gray-2);
    background-image: linear-gradient(100deg,
        transparent 30%,
        var(--ff-white-a60) 50%,
        transparent 70%);
    background-size: 200% 100%;
    background-repeat: no-repeat;
    animation: ffsk-shimmer 1.3s linear infinite;
}
.ffsk-text * { color: transparent !important; }

/* ── Reveal ── (images + grouped text: focus-in, no opacity fade) */
.ffsk-reveal { animation: ffsk-reveal-in 0.4s ease; }
