/**
 * IPC loaders
 *
 * A family of loading animations that restyle the existing loaders in place: .globalLoader inside .loading (the status
 * pop-up, list searches, the users finder) and the v2 pages' #loadingContainer spinner. CSS only, in IPC orange.
 * Layer: Interface
 * Chosen site-wide by $ipcLoaderStyle in brandings/2/head.php, which sets data-ipc-loader on <html> ('classic' sets
 * nothing, so the original ring in theme-ipc.css shows). A wrapper with class ipc-loader-preview shows any of them by
 * name: <div class="loading" data-loader="wave"><div class="globalLoader"></div></div>.
 * Styles: classic, arc, material, dots, wave, bar, breathe, bars, ring, material-mono, line, ellipsis
 * Last updated: 2026-10-30 by jack
 */

/* --- RESET: every style starts from a blank, so none leaks into another ---- */

html[data-ipc-loader] .loading .globalLoader,
html[data-ipc-loader] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader] .globalLoader {
    position: relative;
    box-sizing: border-box;
    width: 34px;
    height: 34px;
    padding: 0 !important;
    border: 0;
    border-radius: 0;
    color: var(--theme-color-1, #da773e);
    --ipc-loader-yellow: #ecb630;
    /* Pace for every loader but classic: 1 is as designed, lower is quicker */
    --ipc-loader-pace: 0.7;
    background: none;
    -webkit-mask: none;
    mask: none;
    animation: none;
}

html[data-ipc-loader] .loading .globalLoader::before,
html[data-ipc-loader] .loading .globalLoader::after,
html[data-ipc-loader] #loadingContainer .spinner-border::before,
html[data-ipc-loader] #loadingContainer .spinner-border::after,
.ipc-loader-preview .loading[data-loader] .globalLoader::before,
.ipc-loader-preview .loading[data-loader] .globalLoader::after {
    content: none;
    position: absolute;
    inset: auto;
    width: auto;
    height: auto;
    margin: 0;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    opacity: 1;
    transform: none;
    animation: none;
}

/* --- CLASSIC: the original ring (for the preview; site-wide it comes from theme-ipc.css) ---- */

html[data-ipc-loader="classic"] .loading .globalLoader,
html[data-ipc-loader="classic"] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader="classic"] .globalLoader {
    width: 35px;
    height: 35px;
    border: 6px solid var(--theme-color-8, #f7f7f7);
    border-top-color: currentColor;
    border-radius: 50%;
    animation: ipc-loader-turn 0.4s linear infinite;
}

/* --- ARC: a thin arc fading from logo yellow into a rounded orange head, on a faint track ---- */

html[data-ipc-loader="arc"] .loading .globalLoader,
html[data-ipc-loader="arc"] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader="arc"] .globalLoader {
    border-radius: 50%;
    background:
        conic-gradient(from 0deg, transparent 0%, var(--ipc-loader-yellow) 45%, currentColor 100%),
        linear-gradient(rgba(236, 182, 48, 0.18), rgba(236, 182, 48, 0.18));
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3.5px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3.5px));
    animation: ipc-loader-turn calc(0.75s * var(--ipc-loader-pace)) linear infinite;
}

html[data-ipc-loader="arc"] .loading .globalLoader::after,
html[data-ipc-loader="arc"] #loadingContainer .spinner-border::after,
.ipc-loader-preview .loading[data-loader="arc"] .globalLoader::after {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    width: 4px;
    height: 4px;
    margin-left: -2px;
    border-radius: 50%;
    background: currentColor;
}

/* --- MATERIAL: an arc that grows and shrinks while it turns, shifting between orange and logo yellow ---- */

@property --ipc-loader-arc {
    syntax: "<angle>";
    inherits: false;
    initial-value: 40deg;
}

html[data-ipc-loader="material"] .loading .globalLoader,
html[data-ipc-loader="material"] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader="material"] .globalLoader {
    border-radius: 50%;
    background: conic-gradient(currentColor var(--ipc-loader-arc), transparent 0);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3.5px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3.5px));
    animation:
        ipc-loader-turn calc(1.2s * var(--ipc-loader-pace)) linear infinite,
        ipc-loader-grow calc(1.2s * var(--ipc-loader-pace)) ease-in-out infinite,
        ipc-loader-tone calc(2.4s * var(--ipc-loader-pace)) ease-in-out infinite;
}

/* --- DOTS: three dots fading in turn, orange / logo yellow / orange ---- */

html[data-ipc-loader="dots"] .loading .globalLoader,
html[data-ipc-loader="dots"] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader="dots"] .globalLoader,
html[data-ipc-loader="dots"] .loading .globalLoader::before,
html[data-ipc-loader="dots"] .loading .globalLoader::after,
html[data-ipc-loader="dots"] #loadingContainer .spinner-border::before,
html[data-ipc-loader="dots"] #loadingContainer .spinner-border::after,
.ipc-loader-preview .loading[data-loader="dots"] .globalLoader::before,
.ipc-loader-preview .loading[data-loader="dots"] .globalLoader::after {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background-color: rgba(218, 119, 62, 0.25);
    animation: ipc-loader-fade calc(1s * var(--ipc-loader-pace)) ease-in-out infinite;
}

html[data-ipc-loader="dots"] .loading .globalLoader,
html[data-ipc-loader="dots"] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader="dots"] .globalLoader {
    background-color: rgba(236, 182, 48, 0.25);
    animation-name: ipc-loader-fade-yellow;
    animation-delay: calc(0.15s * var(--ipc-loader-pace));
}

html[data-ipc-loader="dots"] .loading .globalLoader::before,
html[data-ipc-loader="dots"] .loading .globalLoader::after,
html[data-ipc-loader="dots"] #loadingContainer .spinner-border::before,
html[data-ipc-loader="dots"] #loadingContainer .spinner-border::after,
.ipc-loader-preview .loading[data-loader="dots"] .globalLoader::before,
.ipc-loader-preview .loading[data-loader="dots"] .globalLoader::after {
    content: "";
    position: absolute;
    top: 0;
    left: -15px;
}

html[data-ipc-loader="dots"] .loading .globalLoader::after,
html[data-ipc-loader="dots"] #loadingContainer .spinner-border::after,
.ipc-loader-preview .loading[data-loader="dots"] .globalLoader::after {
    left: 15px;
    animation-delay: calc(0.3s * var(--ipc-loader-pace));
}

/* --- WAVE: three dots bouncing in a wave, orange / logo yellow / orange ---- */

html[data-ipc-loader="wave"] .loading .globalLoader,
html[data-ipc-loader="wave"] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader="wave"] .globalLoader {
    width: 9px;
    height: 9px;
    margin-top: 8px;
}

html[data-ipc-loader="wave"] .loading .globalLoader::before,
html[data-ipc-loader="wave"] #loadingContainer .spinner-border::before,
.ipc-loader-preview .loading[data-loader="wave"] .globalLoader::before {
    content: "";
    position: absolute;
    top: 0;
    left: -30px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    animation: ipc-loader-wave calc(1s * var(--ipc-loader-pace)) ease-in-out infinite;
}

/* --- BAR: a short bar, logo yellow into orange, sliding back and forth on a track ---- */

html[data-ipc-loader="bar"] .loading .globalLoader,
html[data-ipc-loader="bar"] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader="bar"] .globalLoader {
    width: 96px;
    height: 4px;
    overflow: hidden;
    border-radius: 2px;
    background: rgba(236, 182, 48, 0.2);
}

html[data-ipc-loader="bar"] .loading .globalLoader::after,
html[data-ipc-loader="bar"] #loadingContainer .spinner-border::after,
.ipc-loader-preview .loading[data-loader="bar"] .globalLoader::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 40%;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--ipc-loader-yellow), currentColor);
    animation: ipc-loader-slide calc(0.8s * var(--ipc-loader-pace)) ease-in-out infinite alternate;
}

/* --- BREATHE: a ring gently growing and shrinking, shifting between orange and logo yellow ---- */

html[data-ipc-loader="breathe"] .loading .globalLoader,
html[data-ipc-loader="breathe"] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader="breathe"] .globalLoader {
    border: 4px solid currentColor;
    border-radius: 50%;
    animation:
        ipc-loader-breathe calc(0.9s * var(--ipc-loader-pace)) ease-in-out infinite alternate,
        ipc-loader-tone calc(1.8s * var(--ipc-loader-pace)) ease-in-out infinite;
}

/* --- BARS: three bars rising and falling like a level meter, orange / logo yellow / orange ---- */

html[data-ipc-loader="bars"] .loading .globalLoader,
html[data-ipc-loader="bars"] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader="bars"] .globalLoader {
    width: 26px;
    height: 26px;
    background:
        linear-gradient(currentColor 0 0) 0 50% / 6px 40% no-repeat,
        linear-gradient(var(--ipc-loader-yellow) 0 0) 50% 50% / 6px 40% no-repeat,
        linear-gradient(currentColor 0 0) 100% 50% / 6px 40% no-repeat;
    animation: ipc-loader-bars calc(0.9s * var(--ipc-loader-pace)) ease-in-out infinite;
}

/* --- RING: a thin grey ring with one orange quarter, turning smoothly (the calm, business-software spinner) ---- */

html[data-ipc-loader="ring"] .loading .globalLoader,
html[data-ipc-loader="ring"] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader="ring"] .globalLoader {
    border: 3px solid #e5e7eb;
    border-top-color: currentColor;
    border-radius: 50%;
    animation: ipc-loader-turn calc(0.8s * var(--ipc-loader-pace)) cubic-bezier(0.5, 0.15, 0.5, 0.85) infinite;
}

/* --- MATERIAL-MONO: material's growing and shrinking arc, orange only, thinner and slower ---- */

html[data-ipc-loader="material-mono"] .loading .globalLoader,
html[data-ipc-loader="material-mono"] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader="material-mono"] .globalLoader {
    border-radius: 50%;
    background: conic-gradient(currentColor var(--ipc-loader-arc), transparent 0);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2.5px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2.5px));
    animation:
        ipc-loader-turn calc(1.6s * var(--ipc-loader-pace)) linear infinite,
        ipc-loader-grow calc(1.6s * var(--ipc-loader-pace)) ease-in-out infinite;
}

/* --- LINE: a thin orange segment sweeping one way across a grey line ---- */

html[data-ipc-loader="line"] .loading .globalLoader,
html[data-ipc-loader="line"] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader="line"] .globalLoader {
    width: 96px;
    height: 3px;
    overflow: hidden;
    border-radius: 2px;
    background: #e5e7eb;
}

html[data-ipc-loader="line"] .loading .globalLoader::after,
html[data-ipc-loader="line"] #loadingContainer .spinner-border::after,
.ipc-loader-preview .loading[data-loader="line"] .globalLoader::after {
    content: "";
    top: 0;
    bottom: 0;
    width: 35%;
    border-radius: 2px;
    background: currentColor;
    animation: ipc-loader-sweep calc(0.75s * var(--ipc-loader-pace)) cubic-bezier(0.65, 0, 0.35, 1) infinite;
}

/* --- ELLIPSIS: three small orange dots fading in turn, slowly ---- */

html[data-ipc-loader="ellipsis"] .loading .globalLoader,
html[data-ipc-loader="ellipsis"] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader="ellipsis"] .globalLoader,
html[data-ipc-loader="ellipsis"] .loading .globalLoader::before,
html[data-ipc-loader="ellipsis"] .loading .globalLoader::after,
html[data-ipc-loader="ellipsis"] #loadingContainer .spinner-border::before,
html[data-ipc-loader="ellipsis"] #loadingContainer .spinner-border::after,
.ipc-loader-preview .loading[data-loader="ellipsis"] .globalLoader::before,
.ipc-loader-preview .loading[data-loader="ellipsis"] .globalLoader::after {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background-color: rgba(218, 119, 62, 0.25);
    animation: ipc-loader-fade calc(1.4s * var(--ipc-loader-pace)) ease-in-out infinite;
}

html[data-ipc-loader="ellipsis"] .loading .globalLoader,
html[data-ipc-loader="ellipsis"] #loadingContainer .spinner-border,
.ipc-loader-preview .loading[data-loader="ellipsis"] .globalLoader {
    animation-delay: calc(0.2s * var(--ipc-loader-pace));
}

html[data-ipc-loader="ellipsis"] .loading .globalLoader::before,
html[data-ipc-loader="ellipsis"] .loading .globalLoader::after,
html[data-ipc-loader="ellipsis"] #loadingContainer .spinner-border::before,
html[data-ipc-loader="ellipsis"] #loadingContainer .spinner-border::after,
.ipc-loader-preview .loading[data-loader="ellipsis"] .globalLoader::before,
.ipc-loader-preview .loading[data-loader="ellipsis"] .globalLoader::after {
    content: "";
    top: 0;
    left: -12px;
}

html[data-ipc-loader="ellipsis"] .loading .globalLoader::after,
html[data-ipc-loader="ellipsis"] #loadingContainer .spinner-border::after,
.ipc-loader-preview .loading[data-loader="ellipsis"] .globalLoader::after {
    left: 12px;
    animation-delay: calc(0.4s * var(--ipc-loader-pace));
}

/* --- NO TEXT: every loader but classic stands on its own; "Please wait" is kept for screen readers only ---- */

html[data-ipc-loader]:not([data-ipc-loader="classic"]) .loading h4 {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: 0 !important;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

/* With no text under it, the loader needs no gap below either */
html[data-ipc-loader]:not([data-ipc-loader="classic"]) .statusMessage .loading .globalLoader {
    margin-bottom: 0;
}

/* --- MOTION ---- */

@keyframes ipc-loader-turn {
    to {
        transform: rotate(360deg);
    }
}

@keyframes ipc-loader-grow {
    0%, 100% {
        --ipc-loader-arc: 30deg;
    }
    50% {
        --ipc-loader-arc: 270deg;
    }
}

@keyframes ipc-loader-fade {
    0%, 80%, 100% {
        background-color: rgba(218, 119, 62, 0.25);
    }
    40% {
        background-color: rgba(218, 119, 62, 1);
    }
}

@keyframes ipc-loader-fade-yellow {
    0%, 80%, 100% {
        background-color: rgba(236, 182, 48, 0.25);
    }
    40% {
        background-color: rgba(236, 182, 48, 1);
    }
}

/* Orange to logo yellow and back */
@keyframes ipc-loader-tone {
    0%, 100% {
        color: var(--theme-color-1, #da773e);
    }
    50% {
        color: var(--ipc-loader-yellow);
    }
}

/* The dots are shadows of a hidden anchor 30px to the left: a shadow under its own box wouldn't show */
@keyframes ipc-loader-wave {
    0%, 70%, 100% {
        box-shadow: 15px 0 currentColor, 30px 0 var(--ipc-loader-yellow), 45px 0 currentColor;
    }
    15% {
        box-shadow: 15px -8px currentColor, 30px 0 var(--ipc-loader-yellow), 45px 0 currentColor;
    }
    30% {
        box-shadow: 15px 0 currentColor, 30px -8px var(--ipc-loader-yellow), 45px 0 currentColor;
    }
    45% {
        box-shadow: 15px 0 currentColor, 30px 0 var(--ipc-loader-yellow), 45px -8px currentColor;
    }
}

@keyframes ipc-loader-slide {
    to {
        transform: translateX(150%);
    }
}

/* In from the left, out to the right, then again */
@keyframes ipc-loader-sweep {
    from {
        left: -35%;
    }
    to {
        left: 100%;
    }
}

@keyframes ipc-loader-breathe {
    from {
        transform: scale(0.72);
        opacity: 0.45;
    }
    to {
        transform: scale(1);
        opacity: 1;
    }
}

@keyframes ipc-loader-bars {
    0%, 100% {
        background-size: 6px 40%, 6px 40%, 6px 40%;
    }
    20% {
        background-size: 6px 100%, 6px 40%, 6px 40%;
    }
    40% {
        background-size: 6px 40%, 6px 100%, 6px 40%;
    }
    60% {
        background-size: 6px 40%, 6px 40%, 6px 100%;
    }
}

/* Slower for people who have asked for less motion; still moving, so loading stays visible */
@media (prefers-reduced-motion: reduce) {
    html[data-ipc-loader] .loading .globalLoader,
    html[data-ipc-loader] .loading .globalLoader::before,
    html[data-ipc-loader] .loading .globalLoader::after,
    html[data-ipc-loader] #loadingContainer .spinner-border,
    html[data-ipc-loader] #loadingContainer .spinner-border::before,
    html[data-ipc-loader] #loadingContainer .spinner-border::after,
    .ipc-loader-preview .loading[data-loader] .globalLoader,
    .ipc-loader-preview .loading[data-loader] .globalLoader::before,
    .ipc-loader-preview .loading[data-loader] .globalLoader::after {
        animation-duration: 2s;
    }
}
