Portfolio

Proyectos que
hablan por sí solos.

Webs, apps y campañas que han generado resultados reales para negocios de toda España.

¿El siguiente?

Tu proyecto puede ser
el próximo.

Primera consulta gratuita y sin compromiso.

📞 Llamar 💬 WhatsApp
/* ── LIGHTBOX ─────────────────────────────── */ let lbImages = [], lbCurrent = 0, lbTitle = ''; function openGallery(proyIdx) { const p = currentList()[proyIdx] || PROYECTOS.find((pr,i) => pr.type === 'gallery'); if (!p || !p.images) return; // Filter out empty URLs lbImages = p.images.filter(Boolean); if (!lbImages.length) { alert('Aún no hay imágenes en esta galería. Añade las URLs en el array images[] del proyecto.'); return; } lbTitle = p.title; lbCurrent = 0; document.getElementById('lb-title').textContent = lbTitle; buildThumbs(); showLbImg(0); const ov = document.getElementById('lightbox-overlay'); ov.style.display = 'flex'; requestAnimationFrame(() => ov.classList.add('open')); document.body.style.overflow = 'hidden'; } function closeLightbox() { const ov = document.getElementById('lightbox-overlay'); ov.classList.remove('open'); ov.style.display = 'none'; document.body.style.overflow = ''; } function buildThumbs() { const container = document.getElementById('lb-thumbs'); container.innerHTML = lbImages.map((src, i) => `Pieza ${i+1}` ).join(''); } function showLbImg(idx) { lbCurrent = ((idx % lbImages.length) + lbImages.length) % lbImages.length; const imgEl = document.getElementById('lb-img'); imgEl.classList.add('fade'); setTimeout(() => { imgEl.src = lbImages[lbCurrent]; imgEl.alt = `${lbTitle} — pieza ${lbCurrent + 1}`; imgEl.onload = () => imgEl.classList.remove('fade'); imgEl.onerror = () => imgEl.classList.remove('fade'); }, 200); document.getElementById('lb-count').textContent = `${lbCurrent + 1} / ${lbImages.length}`; document.querySelectorAll('.lb-thumb').forEach((t, i) => t.classList.toggle('active', i === lbCurrent)); // Scroll active thumb into view const activeThumb = document.querySelectorAll('.lb-thumb')[lbCurrent]; if (activeThumb) activeThumb.scrollIntoView({behavior:'smooth', block:'nearest', inline:'center'}); } function lbNav(dir) { showLbImg(lbCurrent + dir); } // Keyboard navigation document.addEventListener('keydown', e => { if (!document.getElementById('lightbox-overlay').classList.contains('open')) return; if (e.key === 'Escape') closeLightbox(); if (e.key === 'ArrowRight') lbNav(1); if (e.key === 'ArrowLeft') lbNav(-1); }); // Close on overlay click (not on image) document.getElementById('lightbox-overlay').addEventListener('click', function(e) { if (e.target === this) closeLightbox(); }); // Helper: get current filtered list index mapping function currentList() { const activeBtn = document.querySelector('.port-filter.active'); const filter = activeBtn ? activeBtn.textContent.trim() : 'all'; return filter === 'all' ? PROYECTOS : PROYECTOS.filter(p => p.sector === filter); } // Touch swipe support for lightbox let lbTouchX = null; document.getElementById('lightbox-overlay').addEventListener('touchstart', e => { lbTouchX = e.touches[0].clientX; }, {passive:true}); document.getElementById('lightbox-overlay').addEventListener('touchend', e => { if (lbTouchX === null) return; const dx = e.changedTouches[0].clientX - lbTouchX; if (Math.abs(dx) > 50) lbNav(dx < 0 ? 1 : -1); lbTouchX = null; }, {passive:true});