/*
 * Общая система движения витрины. Подключается всеми темами.
 *
 * Правила:
 *  - Длительности и кривые — только через переменные ниже, чтобы тема могла
 *    их переопределить, а ревью видел один источник истины.
 *  - Любая анимация появления работает от класса, который ставит JS
 *    (`.mo-reveal` -> `.mo-in`), поэтому контент виден и без скриптов.
 *  - `prefers-reduced-motion` полностью выключает перемещения: остаётся
 *    мгновенная смена состояния, но не мигание.
 */

:root {
    --mo-fast: 140ms;
    --mo-base: 240ms;
    --mo-slow: 420ms;
    /* Стандартный выход: быстро стартует, мягко тормозит. */
    --mo-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
    /* Для входа элемента снизу — чуть более пружинисто, без перелёта. */
    --mo-ease-out: cubic-bezier(0.16, 0.84, 0.44, 1);
    --mo-stagger: 45ms;
}

/* === Появление ======================================================== */

.mo-reveal {
    opacity: 0;
    transform: translate3d(0, 10px, 0);
    transition:
        opacity var(--mo-base) var(--mo-ease),
        transform var(--mo-base) var(--mo-ease-out);
    will-change: opacity, transform;
}

.mo-reveal.mo-in {
    opacity: 1;
    transform: none;
}

/* Каскад: задержку ставит JS через --mo-i, чтобы не плодить классы. */
.mo-reveal[style*="--mo-i"] {
    transition-delay: calc(var(--mo-i) * var(--mo-stagger));
}

/* Появление после завершения — снимаем will-change, иначе слой висит в памяти. */
.mo-reveal.mo-done {
    will-change: auto;
}

/* === Отклик на нажатие ================================================ */

/*
 * Тач-устройства не имеют hover, поэтому обратная связь строится на :active.
 * Сжатие маленькое: на карточке товара 0.97 уже читается как отклик.
 */
.mo-press {
    transition: transform var(--mo-fast) var(--mo-ease);
}

.mo-press:active {
    transform: scale(0.97);
}

.mo-press-soft:active {
    transform: scale(0.985);
}

/* === Скелетон ========================================================= */

.mo-skeleton {
    position: relative;
    overflow: hidden;
    background: color-mix(in srgb, var(--text-secondary, #8e8e93) 14%, transparent);
    border-radius: 8px;
}

.mo-skeleton::after {
    content: '';
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(
        90deg,
        transparent,
        color-mix(in srgb, var(--card-bg, #ffffff) 55%, transparent),
        transparent
    );
    animation: mo-shimmer 1.4s ease-in-out infinite;
}

@keyframes mo-shimmer {
    to { transform: translateX(100%); }
}

/* === Точечные утилиты ================================================= */

.mo-fade {
    animation: mo-fade-in var(--mo-base) var(--mo-ease) both;
}

@keyframes mo-fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

.mo-rise {
    animation: mo-rise-in var(--mo-slow) var(--mo-ease-out) both;
}

@keyframes mo-rise-in {
    from { opacity: 0; transform: translate3d(0, 16px, 0); }
    to { opacity: 1; transform: none; }
}

/* Пульс для «код действует» и прочих таймеров. */
.mo-pulse {
    animation: mo-pulse 2s var(--mo-ease) infinite;
}

@keyframes mo-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.55; }
}

/* === Уважение к системной настройке =================================== */

@media (prefers-reduced-motion: reduce) {
    .mo-reveal {
        opacity: 1;
        transform: none;
        transition: none;
        transition-delay: 0ms !important;
    }
    .mo-press:active,
    .mo-press-soft:active {
        transform: none;
    }
    .mo-skeleton::after,
    .mo-pulse {
        animation: none;
    }
    .mo-fade,
    .mo-rise {
        animation: none;
    }
}
