);
}
// ========== SECTION 04 — FULLSCREEN IMAGE SLIDER ==========
// To add more images: just append { src: 'assets/yourfile.jpg', caption: '...' }
// Works with ANY number of slides.
// NO static fallback — banners are 100% admin-driven via /super-admin/banners.
// If the API returns nothing, the carousel section just doesn't render at all.
const IMAGE_SLIDES_FALLBACK = [];
function ImageCarousel() {
const [i, setI] = useStateC(0);
const [IMAGE_SLIDES, setSlides] = useStateC(IMAGE_SLIDES_FALLBACK);
const [loaded, setLoaded] = useStateC(false);
// Auto-discover whatever's in /public/assets/banners/. No renaming needed —
// any .webp/.jpg/.png/.avif files in the folder show up here.
useEffectC(() => {
fetch('/api/home-banners')
.then(r => r.ok ? r.json() : null)
.then(d => { if (Array.isArray(d) && d.length) setSlides(d); setLoaded(true); })
.catch(() => { setLoaded(true); });
}, []);
const n = IMAGE_SLIDES.length;
// ALL hooks must run on every render (React Rules of Hooks). The actual
// "should we render" decision happens AFTER all useEffect calls below.
useEffectC(() => {
if (n <= 1) return;
const t = setInterval(() => setI(x => (x + 1) % n), 7000);
return () => clearInterval(t);
}, [n]);
// Now safe to early-return: hooks have all been called.
if (!loaded) return null;
if (!n) return null;
const pad = (x) => String(x).padStart(2, '0');
return (