/* ==========================================================
   FamAPI — animations.js (vanilla, no dependencies)
   Scroll reveals + count-up counters + 3D tilt cards.
   ========================================================== */
(function () {
    'use strict';

    /* ---------- Scroll reveal ---------- */
    var revealEls = document.querySelectorAll('.reveal');
    if ('IntersectionObserver' in window) {
        var revealIO = new IntersectionObserver(function (entries) {
            entries.forEach(function (entry) {
                if (entry.isIntersecting) {
                    entry.target.classList.add('visible');
                    revealIO.unobserve(entry.target);
                }
            });
        }, { threshold: 0.12, rootMargin: '0px 0px -40px 0px' });
        revealEls.forEach(function (el) { revealIO.observe(el); });
    } else {
        revealEls.forEach(function (el) { el.classList.add('visible'); });
    }

    /* ---------- Count-up counters ---------- */
    function animateCount(el) {
        var target = parseFloat(el.getAttribute('data-count') || '0');
        var decimals = parseInt(el.getAttribute('data-decimals') || '0', 10);
        var prefix = el.getAttribute('data-prefix') || '';
        var suffix = el.getAttribute('data-suffix') || '';
        var duration = 1700;
        var start = null;
        var opts = { minimumFractionDigits: decimals, maximumFractionDigits: decimals };
        function step(ts) {
            if (start === null) start = ts;
            var p = Math.min((ts - start) / duration, 1);
            var eased = 1 - Math.pow(1 - p, 3);
            var val = target * eased;
            el.textContent = prefix + val.toLocaleString('en-US', opts) + suffix;
            if (p < 1) requestAnimationFrame(step);
        }
        requestAnimationFrame(step);
    }
    var counters = document.querySelectorAll('[data-count]');
    if ('IntersectionObserver' in window) {
        var countIO = new IntersectionObserver(function (entries) {
            entries.forEach(function (entry) {
                if (entry.isIntersecting) {
                    animateCount(entry.target);
                    countIO.unobserve(entry.target);
                }
            });
        }, { threshold: 0.4 });
        counters.forEach(function (el) { countIO.observe(el); });
    } else {
        counters.forEach(function (el) { animateCount(el); });
    }

    /* ---------- 3D tilt (hover-capable pointers only) ---------- */
    var tiltCards = document.querySelectorAll('.tilt');
    if (window.matchMedia && window.matchMedia('(hover: hover) and (pointer: fine)').matches) {
        tiltCards.forEach(function (card) {
            var rx = 0, ry = 0, raf = null;
            function apply() {
                card.style.transform =
                    'perspective(900px) rotateX(' + rx.toFixed(2) + 'deg) rotateY(' + ry.toFixed(2) + 'deg) translate3d(0,-6px,0)';
            }
            card.addEventListener('mousemove', function (ev) {
                var r = card.getBoundingClientRect();
                var px = (ev.clientX - r.left) / r.width - 0.5;
                var py = (ev.clientY - r.top) / r.height - 0.5;
                ry = px * 9;
                rx = -py * 9;
                if (!raf) {
                    raf = requestAnimationFrame(function () { apply(); raf = null; });
                }
            });
            card.addEventListener('mouseleave', function () {
                rx = 0; ry = 0;
                if (!raf) {
                    raf = requestAnimationFrame(function () { card.style.transform = ''; raf = null; });
                }
            });
        });
    }
})();
