/*
 * The site's loader (includes/loader.blade.php), in place of rolling_spinner.gif
 * (Javier, 2026-10-23). Every animation here moves only `transform` and
 * `opacity`: a phone keeps those running while the page's thread is busy
 * (learning the picture), where a GIF stops. Keep it that way:
 * tests/create/loader.cjs fails on any other animated property.
 * Which look shows is .file-loading's data-mode: none, "upload" or "photo".
 */
.file-loading .ml-stage { position: relative; width: 150px; height: 150px; margin: 0 auto; }
.file-loading .ml-mark { position: absolute; inset: 0; display: none; }
.file-loading:not([data-mode]) .ml-default,
.file-loading[data-mode="upload"] .ml-upload,
.file-loading[data-mode="photo"] .ml-photo { display: block; }
.file-loading .ml-stage svg { display: block; }
.file-loading p#status2 { margin-top: 18px; }

/* Default: the round logo, the viewer's red brackets closing on it (#web-boot). */
.ml-default .ml-logo { position: absolute; left: 41px; top: 41px; width: 68px; height: 68px; }
.ml-corner { position: absolute; width: 24px; height: 24px; border: 0 solid #CC0000; animation: ml-close 1.4s ease-in-out infinite; will-change: transform; }
.ml-corner.tl { top: 19px; left: 19px; border-width: 3px 0 0 3px; border-radius: 7px 0 0 0; --x: 8px; --y: 8px; }
.ml-corner.tr { top: 19px; right: 19px; border-width: 3px 3px 0 0; border-radius: 0 7px 0 0; --x: -8px; --y: 8px; }
.ml-corner.bl { bottom: 19px; left: 19px; border-width: 0 0 3px 3px; border-radius: 0 0 0 7px; --x: 8px; --y: -8px; }
.ml-corner.br { bottom: 19px; right: 19px; border-width: 0 3px 3px 0; border-radius: 0 0 7px 0; --x: -8px; --y: -8px; }
@keyframes ml-close { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(var(--x), var(--y)); } }

/* Upload: the video icon, red chevrons rising out of it. */
.ml-upload .ml-video-svg { position: absolute; left: 15px; top: 15px; width: 120px; height: 120px; animation: ml-bob 1.6s ease-in-out infinite; will-change: transform; }
.ml-chev { position: absolute; left: 64px; top: 2px; width: 22px; height: 14px; opacity: 0; animation: ml-rise 1.6s ease-out infinite; will-change: transform, opacity; }
.ml-chev svg { width: 100%; height: 100%; }
.ml-chev path { fill: none; stroke: #CC0000; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
/* Negative delays: every chevron starts at once, a third of a cycle apart.
   A positive delay waits for the page's thread on iPhone (WebKit), so a busy
   page showed one chevron (2026-10-23). */
.ml-chev.c2 { animation-delay: -0.53s; }
.ml-chev.c3 { animation-delay: -1.06s; }
@keyframes ml-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
@keyframes ml-rise { 0% { transform: translateY(26px); opacity: 0; } 25% { opacity: 1; } 100% { transform: translateY(-14px); opacity: 0; } }

/* Photo: Magoo's photo icon posing in perspective, thin red sparkles on it. */
.ml-photo { perspective: 420px; }
.ml-disc { position: absolute; inset: 15px; border-radius: 50%; background: #F5F5F5; }
.ml-shadow { position: absolute; left: 44px; right: 44px; bottom: 30px; height: 10px; border-radius: 50%; background: rgba(15, 19, 58, 0.18); filter: blur(3px); animation: ml-shadow 6s ease-in-out infinite; will-change: transform, opacity; }
.ml-model { position: absolute; left: 39px; top: 37px; width: 72px; height: 72px; transform-style: preserve-3d; animation: ml-pose 6s ease-in-out infinite; will-change: transform; }
.ml-photo-svg { width: 100%; height: 100%; }
.ml-photo-svg path { fill: #0F133A; }
@keyframes ml-pose {
    0%, 100% { transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg) translateX(0); }
    20% { transform: rotateY(-22deg) rotateX(8deg) rotateZ(-5deg) translateX(-5px); }
    42% { transform: rotateY(-8deg) rotateX(-6deg) rotateZ(2deg) translateX(-1px); }
    64% { transform: rotateY(22deg) rotateX(6deg) rotateZ(5deg) translateX(5px); }
    84% { transform: rotateY(6deg) rotateX(-8deg) rotateZ(-2deg) translateX(1px); }
}
@keyframes ml-shadow {
    0%, 100% { transform: translateX(0) scaleX(1); opacity: 1; }
    20% { transform: translateX(-6px) scaleX(0.85); opacity: 0.75; }
    64% { transform: translateX(6px) scaleX(0.85); opacity: 0.75; }
}
.ml-spark { position: absolute; width: 20px; height: 20px; margin: -10px 0 0 -10px; opacity: 0; transform: scale(0); animation: ml-spark var(--d, 1.7s) ease-in-out infinite; animation-delay: calc(var(--w, 0s) * -1); will-change: transform, opacity; }
/* Started part way through their cycles (negative delay), not after a wait:
   on iPhone a sparkle waiting for its delay did not appear while the page was
   busy learning the picture; only the one without a delay did (Javier,
   2026-10-23: "una chispa en una esquina"). */
.ml-spark.s { width: 13px; height: 13px; margin: -6.5px 0 0 -6.5px; }
.ml-spark svg { width: 100%; height: 100%; }
.ml-spark path { fill: #CC0000; }
@keyframes ml-spark {
    0%, 100% { opacity: 0; transform: scale(0) rotate(0deg); }
    22% { opacity: 0.95; transform: scale(1) rotate(20deg); }
    42% { opacity: 0.8; transform: scale(0.75) rotate(40deg); }
    60% { opacity: 0; transform: scale(0) rotate(70deg); }
}

/* The upload's share: a red bar, scaled (never resized) by the page. */
.file-loading .ml-track { width: 70%; max-width: 240px; height: 6px; margin: 16px auto 0; border-radius: 3px; background: #F1F1F1; overflow: hidden; }
.file-loading .ml-track[hidden] { display: none; }
.file-loading .ml-fill { width: 100%; height: 100%; border-radius: 3px; background: #CC0000; transform-origin: left center; transform: scaleX(0); }

@media (prefers-reduced-motion: reduce) {
    .ml-corner, .ml-upload .ml-video-svg, .ml-chev, .ml-shadow, .ml-model, .ml-spark { animation: none; }
    .ml-chev.c2 { opacity: 1; transform: none; }
    .ml-spark.keep { opacity: 0.95; transform: scale(1); }
}
