// folio/Photo.jsx — image renderer with lazy-load + blur-up + tone placeholder. // When an entry has no `src`, renders a tone-tinted swatch composition so the // layout still reads as designed. const FOLIO_TONES = { bamboo: { bg: "linear-gradient(135deg,#e8c98a,#c9a35e 60%,#a07d40)", fg: "#3a2410" }, bark: { bg: "linear-gradient(135deg,#8a5a32,#5a3a1f 60%,#3a2410)", fg: "#f4ecde" }, cream: { bg: "linear-gradient(155deg,#f6efe1,#e3d4b6)", fg: "#3a2410" }, ink: { bg: "linear-gradient(155deg,#1c1410,#0a0805)", fg: "#f4ecde" }, burgundy:{ bg: "linear-gradient(155deg,#5a1a2a,#2a0010)", fg: "#f4ecde" }, }; function FolioSwatch({ img, big = false }) { const t = FOLIO_TONES[img.tone] || FOLIO_TONES.cream; return (
{/* Subtle grain texture */}
{/* Soft circular composition cue (suggests "subject lives roughly here") */}
{/* Corner labels */}
{img.no}
{img.title}
{img.cat}
); } function FolioPhoto({ img, big = false, eager = false }) { const [loaded, setLoaded] = React.useState(false); if (!img.src) return ; return ( <> {!loaded && } {img.title} setLoaded(true)} style={{ opacity: loaded ? 1 : 0, transition: "opacity 700ms ease", }} /> ); } Object.assign(window, { FolioPhoto, FolioSwatch });