/* Shared UI components for Sham-e-Mehfil */
const { useState, useEffect, useRef } = React;
/* ---- Inline icons (thin, editorial) ---- */
const Icon = {
arrow: (p) => ,
arrowUp: (p) => ,
quote: (p) => ,
feather: (p) => ,
check: (p) => ,
pin: (p) => ,
clock: (p) => ,
seat: (p) => ,
ig: (p) => ,
};
/* ---- Editorial image (real photo) or placeholder ---- */
function Ph({ label, pic, src, alt, dark, style, className = "", ratio, w = 1100, overlay }) {
const s = { ...(ratio ? { aspectRatio: ratio } : {}), ...style };
const imgSrc = src ? src : (pic ? (pic.indexOf("/") >= 0 ? pic : IMG(pic, w)) : null);
if (imgSrc) {
return (

{overlay &&
}
);
}
return (
);
}
/* ---- Classical Indian ornamental divider (lotus + line) ---- */
function Ornament({ color = "var(--gold)", width = 240, style }) {
return (
);
}
/* ---- Mughal cusped arch outline (decorative frame top) ---- */
function ArchTop({ color = "var(--gold)", style, w = 320 }) {
return (
);
}
/* ---- Scroll reveal hook ---- */
function useReveal() {
useEffect(() => {
const els = document.querySelectorAll(".reveal:not(.in)");
const io = new IntersectionObserver((entries) => {
entries.forEach((e) => { if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); } });
}, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" });
els.forEach((el) => io.observe(el));
return () => io.disconnect();
});
}
/* ---- Eyebrow label ---- */
function Eyebrow({ children, ink, style }) {
return {children}
;
}
/* ---- Section heading block ---- */
function SectionHead({ eyebrow, title, lede, align = "left", max }) {
return (
{eyebrow &&
{eyebrow}}
{title}
{lede &&
{lede}
}
);
}
/* ---- Status pill for events ---- */
function SeatPill({ status, seats }) {
if (status === "wait") return Waitlist;
if (status === "few") return {seats} seats left;
return {seats} seats;
}
/* ---- Event card ---- */
function EventCard({ ev, onRegister, d }) {
return (
{ev.theme}
{ev.title}
{ev.blurb}
{ev.date} · {ev.time}
{ev.venue}
{ev.price}
);
}
/* ---- Navigation ---- */
const NAV_ITEMS = [
{ to: "events", label: "Events" }, { to: "poets", label: "Poets" },
{ to: "journal", label: "Journal" }, { to: "library", label: "Library" },
{ to: "membership", label: "Membership" }, { to: "about", label: "About" },
];
const DRAWER_ITEMS = [...NAV_ITEMS, { to: "community", label: "Community" }, { to: "perform", label: "Perform" }, { to: "partners", label: "Partners" }, { to: "contact", label: "Contact" }];
function Nav({ route, go }) {
const [solid, setSolid] = useState(false);
const [open, setOpen] = useState(false);
const overHero = route === "home" && !solid && !open;
useEffect(() => {
const onScroll = () => setSolid(window.scrollY > 24);
onScroll(); window.addEventListener("scroll", onScroll);
return () => window.removeEventListener("scroll", onScroll);
}, []);
useEffect(() => { document.body.style.overflow = open ? "hidden" : ""; }, [open]);
const nav = (to) => { go(to); setOpen(false); };
return (
);
}
/* ---- Footer ---- */
function Footer({ go }) {
const cols = [
{ h: "Attend", links: [["events", "Upcoming events"], ["membership", "Membership"], ["community", "Community"]] },
{ h: "Read", links: [["journal", "Stories & Journal"], ["library", "Shayari library"], ["poets", "Featured poets"]] },
{ h: "Take part", links: [["perform", "Perform at SEM"], ["partners", "Partnerships"], ["contact", "Contact"]] },
];
return (
);
}
Object.assign(window, { Icon, Ph, Ornament, ArchTop, useReveal, Eyebrow, SectionHead, SeatPill, EventCard, Nav, Footer });