// Generic grid + lightbox behavior shared across photoflow apps. // Apps spread this into their own Alpine component: { ...photoGrid(), ...appLogic } function photoGrid() { return { focused: null, lightboxOpen: false, cards() { return [...document.querySelectorAll('.photo-card')] .filter(c => c.style.display !== 'none'); }, select(el) { if (this.focused) this.focused.classList.remove('ring-4', 'ring-white', 'z-10'); this.focused = el; if (el) { el.classList.add('ring-4', 'ring-white', 'z-10'); el.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); if (this.lightboxOpen) this.updateLightbox(); } }, selectFirst() { const cards = this.cards(); if (cards.length) this.select(cards[0]); }, navigate(dir) { const cards = this.cards(); if (!cards.length) return; const idx = this.focused ? cards.indexOf(this.focused) : -1; const next = cards[Math.max(0, Math.min(cards.length - 1, idx + dir))]; if (next) this.select(next); }, openLightbox(el) { this.select(el); this.lightboxOpen = true; document.getElementById('lb').style.display = ''; this.updateLightbox(); }, closeLightbox() { this.lightboxOpen = false; const lb = document.getElementById('lb'); if (lb) lb.style.display = 'none'; }, updateLightbox() { const el = this.focused; if (!el) return; const img = el.querySelector('img'); const lbImg = document.getElementById('lb-img'); if (img && lbImg) lbImg.src = img.src; }, }; }