/* ============================================================
   Ferrari Metals — motion
   ============================================================ */

/* ============================================================
   1. The tuning surface — the only numbers in this file
   ============================================================ */
:root {
    --motion-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --motion-ease-soft: cubic-bezier(0.33, 1, 0.68, 1);
    --motion-ease-back: cubic-bezier(0.34, 1.34, 0.46, 1);

    --motion-hover: 0.22s;
    --motion-hover-slow: 0.5s;

    --motion-draw: 1.4s;
    --motion-enter: 0.62s;
    --motion-enter-step: 130ms;

    --motion-rise: 26px;
    --motion-scale-from: 0.94;
    --motion-dim: 0.15;

    --motion-pop-from: 0.9;

    --motion-nudge: 6px;
    --motion-zoom: 1.06;
    --motion-press: 0.98;

}

/* ============================================================
   2. Master switch
   ============================================================ */
:root[data-motion="off"] *,
:root[data-motion="off"] *::before,
:root[data-motion="off"] *::after {
    animation: none !important;
    transition: none !important;
}

/* ============================================================
   3. Hover — refinements of the vocabulary site.css already has
   ============================================================ */
.btn,
.site-nav__link,
.feature-card,
.gallery-card,
.gallery-jump a,
.spec-row__item,
.spec-row--numbered .spec-row__item::before,
.category-mosaic .category-card__label::after,
.category-card__img,
.project-card,
.service-card,
.site-footer a,
.contact-info__item a,
.finish-toggle {
    transition-timing-function: var(--motion-ease-out);
}

.category-card__img,
.gallery-card__media img,
.substrate-mosaic__item img,
.about-intro__frame img,
.photo-plate img,
.project-card__img {
    transition: transform var(--motion-hover-slow) var(--motion-ease-soft);
}
.category-card:hover .category-card__img,
.gallery-card__link:hover img,
.gallery-card__link:focus-visible img,
.substrate-mosaic__item:hover img,
.about-intro__frame:hover img,
.photo-plate:hover img,
.project-card:hover .project-card__img {
    transform: scale(var(--motion-zoom));
}

.field-steps li {
    transition: --step-size 2.2s ease,
                --srule-x var(--t-slow) var(--motion-ease-soft);
}
.field-steps li:hover { transition-duration: var(--t-fast), var(--t-slow); }

.project-card__cta span,
.link-external::after {
    display: inline-block;
    transition: transform var(--motion-hover) var(--motion-ease-out);
}
.project-card:hover .project-card__cta span,
.project-card__cta:hover span { transform: translateX(var(--motion-nudge)); }
.link-external:hover::after {
    transform: translate(var(--motion-nudge), calc(var(--motion-nudge) * -1));
}

.btn { transition: background var(--t-base) var(--motion-ease-out),
                   border-color var(--t-base) var(--motion-ease-out),
                   color var(--t-base) var(--motion-ease-out),
                   transform var(--motion-hover) var(--motion-ease-out); }
.btn:active { transform: scale(var(--motion-press)); }

/* ============================================================
   4. Reveals — the state machine
   ============================================================ */

:root[data-motion-ready] [data-motion-el="rise"],
:root[data-motion-ready] [data-motion-el="fade"],
:root[data-motion-ready] [data-motion-el="pop"] { opacity: var(--motion-dim); }
:root[data-motion-ready] [data-motion-el="rise"] {
    transform: translateY(calc(var(--card-offset, 0px) + var(--motion-rise)))
               scale(var(--motion-scale-from));
}
:root[data-motion-ready] [data-motion-el="pop"] {
    transform: translateY(var(--card-offset, 0px)) scale(var(--motion-pop-from));
}
:root[data-motion-ready] [data-motion-el="draw"]::before { clip-path: inset(0 100% 0 0); }
:root[data-motion-ready] [data-motion-el="inner"] > * {
    opacity: var(--motion-dim);
    transform: translateY(var(--motion-rise)) scale(var(--motion-scale-from));
}

/* The rule is uncovered, not scaled. A scaleX drags the element's own mask
   with it, and this rule's mask is what cuts the gaps the nodes sit in — at
   half progress the gaps land at half their x and the line runs across the
   icons instead of around them. A clip wipes without touching the mask. */
@keyframes fm-draw {
    from { clip-path: inset(0 100% 0 0); }
    to   { clip-path: inset(0 0 0 0); }
}

@keyframes fm-in {
    from {
        opacity: var(--motion-dim);
        transform: translateY(calc(var(--card-offset, 0px) + var(--motion-rise)))
                   scale(var(--motion-scale-from));
    }
    to {
        opacity: 1;
        transform: translateY(var(--card-offset, 0px)) scale(1);
    }
}
@keyframes fm-in-fade {
    from { opacity: var(--motion-dim); }
    to   { opacity: 1; }
}
@keyframes fm-pop {
    from {
        opacity: var(--motion-dim);
        transform: translateY(var(--card-offset, 0px)) scale(var(--motion-pop-from));
    }
    to {
        opacity: 1;
        transform: translateY(var(--card-offset, 0px)) scale(1);
    }
}

[data-motion-el="rise"][data-motion-in] { animation-name: fm-in; }
[data-motion-el="fade"][data-motion-in] { animation-name: fm-in-fade; }
[data-motion-el="pop"][data-motion-in]  { animation-name: fm-pop; }
[data-motion-el="inner"][data-motion-in] > * { animation-name: fm-in; }
[data-motion-el="rise"][data-motion-in],
[data-motion-el="fade"][data-motion-in],
[data-motion-el="pop"][data-motion-in],
[data-motion-el="inner"][data-motion-in] > * {
    animation-duration: var(--motion-enter);
    animation-timing-function: var(--motion-ease-out);
    animation-fill-mode: both;
    animation-delay: calc(var(--motion-index, 0) * var(--motion-enter-step));
}
[data-motion-el="inner"][data-motion-in] > * + * {
    animation-delay: calc(var(--motion-index, 0) * var(--motion-enter-step)
                          + var(--motion-enter-step) * 0.35);
}

[data-motion-el="pop"][data-motion-in] {
    animation-timing-function: var(--motion-ease-back);
    animation-duration: calc(var(--motion-enter) * 1.15);
}

[data-motion-el="draw"][data-motion-in]::before {
    animation: fm-draw var(--motion-draw) var(--motion-ease-soft) both;
}

/* ============================================================
   5. Reduced motion — the finished state, stated
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    [data-motion-el] {
        animation: none;
        opacity: 1;
        transform: translateY(var(--card-offset, 0px));
    }
    [data-motion-el="inner"] > * { animation: none; opacity: 1; transform: none; }
    [data-motion-el="draw"]::before { animation: none; clip-path: none; }
    .btn:active { transform: none; }
}
