/* ========================================================================== SOLUCIONIKA — main.js Comportamiento compartido: nav al hacer scroll, revelado de secciones, contadores animados. Se incluye una sola vez desde footerTest.php ========================================================================== */ document.addEventListener('DOMContentLoaded', function () { /* Sidenav Materialize */ var sidenavElems = document.querySelectorAll('.sidenav'); if (window.M) { M.Sidenav.init(sidenavElems); } /* Header: estado "scrolled" */ var headerBar = document.querySelector('.nk-header-bar'); function onScrollHeader() { if (!headerBar) return; if (window.scrollY > 24) headerBar.classList.add('is-scrolled'); else headerBar.classList.remove('is-scrolled'); } onScrollHeader(); window.addEventListener('scroll', onScrollHeader, { passive: true }); /* Marcar link activo según la página actual */ var here = window.location.pathname.split('/').pop() || 'index.html'; document.querySelectorAll('.nk-links a, .nk-sidenav a').forEach(function (a) { var href = a.getAttribute('href'); if (href && href === here) a.classList.add('active'); }); /* Revelado al hacer scroll (IntersectionObserver) */ var revealEls = document.querySelectorAll('.reveal'); if ('IntersectionObserver' in window && revealEls.length) { var io = new IntersectionObserver(function (entries) { entries.forEach(function (entry) { if (entry.isIntersecting) { entry.target.classList.add('is-visible'); io.unobserve(entry.target); } }); }, { threshold: 0.15, rootMargin: '0px 0px -40px 0px' }); revealEls.forEach(function (el, i) { el.style.setProperty('--i', i % 6); io.observe(el); }); } else { revealEls.forEach(function (el) { el.classList.add('is-visible'); }); } /* Contadores animados de la sección de estadísticas */ var counters = document.querySelectorAll('[data-count]'); if (counters.length) { var counted = new WeakSet(); var countObserver = new IntersectionObserver(function (entries) { entries.forEach(function (entry) { if (entry.isIntersecting && !counted.has(entry.target)) { counted.add(entry.target); animateCount(entry.target); } }); }, { threshold: 0.6 }); counters.forEach(function (el) { countObserver.observe(el); }); } function animateCount(el) { var target = parseFloat(el.getAttribute('data-count')); var duration = 1400; var start = null; function step(ts) { if (!start) start = ts; var progress = Math.min((ts - start) / duration, 1); var eased = 1 - Math.pow(1 - progress, 3); var value = target * eased; el.textContent = (target % 1 === 0) ? Math.floor(value) : value.toFixed(1); if (progress < 1) requestAnimationFrame(step); else el.textContent = target % 1 === 0 ? target : target.toFixed(1); } requestAnimationFrame(step); } });