/* global React */ const { useState, useEffect, useRef } = React; function Themes({ onBack, onOpenPhoto }) { const themes = window.THEMES || []; const photos = window.DARSHAN || []; const photoById = Object.fromEntries(photos.map(p => [p.id, p])); const [active, setActive] = useState(null); const scrollRef = useRef(null); useEffect(() => { const onKey = (e) => { if (e.key === "Escape") { active ? setActive(null) : onBack(); } }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [active, onBack]); if (active) { const t = themes.find(x => x.key === active); return setActive(null)} onOpenPhoto={onOpenPhoto} />; } return (

five lenses, one looking.

the archive is not a category. it is a slow river that has chosen to enter five separate rooms.

{themes.map((t, i) => { const cover = photoById[t.photoIds[0]]; return ( ); })}

five chambers · one breath · twenty photographs

); } function ThemeChapter({ theme, photoById, onBack, onOpenPhoto }) { return (
— {theme.num} —

{theme.dev} {theme.en}

{theme.enSub}

"{theme.epigraph}"
{theme.body.map((p, i) =>

{p}

)}
{theme.photoIds.map((id, i) => { const p = photoById[id]; if (!p) return null; return (
onOpenPhoto && onOpenPhoto(id)} data-cursor>
{p.title}
{p.dev}
{p.title}
{p.line}
{p.place} · {p.year}
); })}
); } function ChamberChrome({ onBack, num, dev, en, hint = "back to the threshold" }) { return (
{num} {dev} {en}
); } window.Themes = Themes; window.ChamberChrome = ChamberChrome;