/* ===================================================================
 * WelcomesU — scroll & entrance animations
 *
 * Driven by js/animations.js, which adds .is-in when an element scrolls
 * into view. Everything degrades to "visible, no motion" if JS never
 * runs (see .no-anim below) or the visitor asks for reduced motion.
 * =================================================================== */


/* -------------------------------------------------------------------
 * ## scroll progress bar
 * ------------------------------------------------------------------- */
.scroll-progress {
    position: fixed;
    top: 0;
    left: 0;
    height: 3px;
    width: 100%;
    z-index: 700;
    transform: scaleX(0);
    transform-origin: 0 50%;
    background: #39b54a;
    pointer-events: none;
    will-change: transform;
}


/* -------------------------------------------------------------------
 * ## masked word reveal
 *
 * js wraps each word as .aw > .aw__i. The outer span clips, the inner
 * one slides up into it. Padding/margin pair keeps descenders (g, y, p)
 * from being sheared off by the overflow.
 * ------------------------------------------------------------------- */
.aw {
    display: inline-block;
    overflow: hidden;
    vertical-align: top;
    padding-bottom: 0.12em;
    margin-bottom: -0.12em;
}

.aw__i {
    display: inline-block;
    transform: translate3d(0, 110%, 0);
    transition: transform 1s cubic-bezier(0.16, 1, 0.3, 1);
    transition-delay: calc(var(--aw-i, 0) * 45ms);
    will-change: transform;
}

.is-in .aw__i,
.aw.is-in .aw__i {
    transform: translate3d(0, 0, 0);
}


/* -------------------------------------------------------------------
 * ## generic reveal
 * ------------------------------------------------------------------- */
[data-reveal] {
    opacity: 0;
    transform: translate3d(0, 34px, 0);
    transition: opacity 0.9s cubic-bezier(0.16, 1, 0.3, 1),
                transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
    transition-delay: calc(var(--d, 0) * 1ms);
}

[data-reveal].is-in {
    opacity: 1;
    transform: translate3d(0, 0, 0);
}

/* direction variants */
[data-reveal="left"]  { transform: translate3d(-38px, 0, 0); }
[data-reveal="right"] { transform: translate3d(38px, 0, 0); }
[data-reveal="fade"]  { transform: none; }

[data-reveal="left"].is-in,
[data-reveal="right"].is-in {
    transform: translate3d(0, 0, 0);
}


/* -------------------------------------------------------------------
 * ## hero choreography
 * ------------------------------------------------------------------- */
.home-content__desc,
.home-content__buttons .btn {
    opacity: 0;
    transform: translate3d(0, 26px, 0);
    transition: opacity 0.9s cubic-bezier(0.16, 1, 0.3, 1),
                transform 0.9s cubic-bezier(0.16, 1, 0.3, 1),
                background-color 0.3s ease-in-out,
                border-color 0.3s ease-in-out,
                color 0.3s ease-in-out;
}

.hero-ready .home-content__desc {
    opacity: 1;
    transform: translate3d(0, 0, 0);
    transition-delay: 0.55s;
}

.hero-ready .home-content__buttons .btn {
    opacity: 1;
    transform: translate3d(0, 0, 0);
}

.hero-ready .home-content__buttons .btn:nth-child(1) { transition-delay: 0.72s; }
.hero-ready .home-content__buttons .btn:nth-child(2) { transition-delay: 0.82s; }

/* The template fades this whole block in over 2s once the preloader
 * clears. We choreograph its children individually instead, so hand the
 * container straight over at full opacity. It stays hidden during
 * preload via html.cl-preload, which is left untouched. */
html.cl-loaded .home-content__main {
    -webkit-animation: none;
    animation: none;
    opacity: 1;
}

/* the hero block drifts up and dissolves as you scroll past it */
.home-content__main {
    will-change: transform, opacity;
}


/* -------------------------------------------------------------------
 * ## section header separator draws itself in
 * ------------------------------------------------------------------- */
.has-bottom-sep::after,
.section-header.has-bottom-sep::after {
    transform: scaleX(0);
    transform-origin: 50% 50%;
    transition: transform 1.2s cubic-bezier(0.16, 1, 0.3, 1) 0.25s;
}

.has-bottom-sep.is-in::after {
    transform: scaleX(1);
}


/* -------------------------------------------------------------------
 * ## service cards
 * ------------------------------------------------------------------- */
.service-item .service-icon i {
    display: inline-block;
    transform: scale(0.4) rotate(-18deg);
    opacity: 0;
    transition: transform 0.8s cubic-bezier(0.34, 1.56, 0.64, 1),
                opacity 0.5s ease-out;
    transition-delay: calc(var(--d, 0) * 1ms + 120ms);
}

.service-item.is-in .service-icon i {
    transform: scale(1) rotate(0deg);
    opacity: 1;
}


/* -------------------------------------------------------------------
 * ## stat counters
 * ------------------------------------------------------------------- */
.stats__col {
    opacity: 0;
    transform: translate3d(0, 30px, 0);
    transition: opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1),
                transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);
    transition-delay: calc(var(--d, 0) * 1ms);
}

.stats.is-in .stats__col {
    opacity: 1;
    transform: translate3d(0, 0, 0);
}


/* -------------------------------------------------------------------
 * ## buttons — sheen on hover
 * ------------------------------------------------------------------- */
.btn--stroke {
    position: relative;
    overflow: hidden;
}

.btn--stroke::after {
    content: "";
    position: absolute;
    top: 0;
    left: -120%;
    width: 60%;
    height: 100%;
    background: linear-gradient(100deg,
                rgba(255, 255, 255, 0) 0%,
                rgba(255, 255, 255, 0.18) 50%,
                rgba(255, 255, 255, 0) 100%);
    transform: skewX(-20deg);
    pointer-events: none;
}

.btn--stroke:hover::after {
    animation: cl-sheen 0.9s ease-out;
}

@keyframes cl-sheen {
    to { left: 140%; }
}


/* -------------------------------------------------------------------
 * ## escape hatches
 *
 * .no-anim is set by the script when it cannot run its own effects, so
 * nothing is ever left stranded at opacity 0.
 * ------------------------------------------------------------------- */
.no-anim [data-reveal],
.no-anim .home-content__desc,
.no-anim .home-content__buttons .btn,
.no-anim .stats__col,
.no-anim .service-item .service-icon i {
    opacity: 1 !important;
    transform: none !important;
}

.no-anim .aw__i {
    transform: none !important;
}

.no-anim .has-bottom-sep::after {
    transform: scaleX(1) !important;
}

@media (prefers-reduced-motion: reduce) {
    .scroll-progress {
        display: none;
    }

    [data-reveal],
    .home-content__desc,
    .home-content__buttons .btn,
    .stats__col,
    .service-item .service-icon i,
    .aw__i,
    .has-bottom-sep::after {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }

    .btn--stroke:hover::after {
        animation: none;
    }
}
