// Al Bustan Palace case study + lightbox const { useState: useStateC, useEffect: useEffectC, useCallback: useCallbackC } = React; function CaseStudy({ onRoute, onEnquire, t }) { const [lightbox, setLightbox] = useStateC(null); return (
{lightbox !== null && setLightbox(null)} onSet={setLightbox} />}
); } function CaseHero({ onRoute }) { return (
I · Wedding · Destination

Marble &
Magnolia.

); } function Meta({ label, value, dark }) { return (
{label}
{value}
); } function CaseMeta() { const r = useReveal(); return (

"A three-day destination wedding that doesn't feel like a destination wedding — that feels like a family home, just larger, just more candlelit, just outside Muscat."

— The couple, in their first meeting
); } function CaseNarrative({ chapter, num, title, body, images, reverse, onLightbox }) { const r = useReveal(); return (
{num} · Phase {chapter}

{title}

{body.map((p, i) => (

{p}

))}
{images.map((img, i) => ( ))}
); } function CaseFullBleed({ src, credit, caption }) { return (
{caption}
© {credit}
{caption}
); } function CaseStats() { const r = useReveal(); const stats = [ ["420", "guests"], ["3", "days"], ["1,400", "candles"], ["9", "countries"], ["42", "tables"], ["97", "run-of-show cues"], ]; return (
{stats.map(([n, l]) => (
{n}
{l}
))}
); } function CaseGalleryGrid({ onLightbox }) { const r = useReveal(); return (

Eight frames.

Click any image to enlarge
{CASE_GALLERY.map((g, i) => { const spans = [ { col: "span 7", row: "span 2", ratio: "4/3" }, { col: "span 5", row: "span 1", ratio: "1/1" }, { col: "span 5", row: "span 1", ratio: "5/4" }, { col: "span 4", row: "span 1", ratio: "3/4" }, { col: "span 4", row: "span 1", ratio: "3/4" }, { col: "span 4", row: "span 1", ratio: "3/4" }, { col: "span 6", row: "span 1", ratio: "4/3" }, { col: "span 6", row: "span 1", ratio: "4/3" }, ]; const s = spans[i] || spans[0]; return ( ); })}
); } function CaseCredits() { return (
{[ ["Design & planning", "Carousel Events"], ["Creative direction", "Zainab Alsalih"], ["Floral", "Carousel Floral (in-house)"], ["Photography", "Varna Studios"], ["Stationery", "Atelier P."], ["Catering", "Al Bustan Palace"], ["Music", "Live ensemble · Vienna"], ["Couple consent", "Cleared · names withheld"], ].map(([k, v]) => (
{k}
{v}
))}
); } function CaseCTA({ onEnquire, onRoute, t }) { return (

Yours will be its own.

Tell us about your wedding and a designer will be in touch personally. Three rounds of design conversations, no obligation.

); } const GALLERY_LOOKUP = Object.fromEntries(CASE_GALLERY.map((g, i) => [g.src, i])); function Lightbox({ index, onClose, onSet }) { const total = CASE_GALLERY.length; const item = CASE_GALLERY[index]; const prev = () => onSet((index - 1 + total) % total); const next = () => onSet((index + 1) % total); useEffectC(() => { document.body.style.overflow = "hidden"; const onKey = (e) => { if (e.key === "Escape") onClose(); else if (e.key === "ArrowLeft") prev(); else if (e.key === "ArrowRight") next(); }; window.addEventListener("keydown", onKey); return () => { window.removeEventListener("keydown", onKey); document.body.style.overflow = ""; }; }, [index]); return (
{String(index + 1).padStart(2, "0")} / {String(total).padStart(2, "0")} · {item.chapter}
e.stopPropagation()} style={{ flex: 1, display: "flex", alignItems: "center", justifyContent: "center", position: "relative" }}> {item.caption}
e.stopPropagation()} style={{ paddingTop: 20, color: "rgba(255,255,255,0.7)", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
{item.caption}
Use ← → to navigate
); } Object.assign(window, { CaseStudy });