// Shared primitives: Nav, Footer, MonoLabel, Arrow, Lightbox, etc.
const { useState, useEffect, useRef, useCallback, useMemo } = React;
// --------- Arrow svg
function Arrow({ size = 18 }) {
return (
);
}
function Eyebrow({ children, accent = true }) {
return (
{accent && }
{children}
);
}
// --------- Logo (inline SVG version of the brand mark, simplified to "DI" wordmark style)
function Logo({ inverted = false, size = 28 }) {
const c = inverted ? "#FFFFFF" : "#15161A";
// Recolor the mark — accent on the infinity dot ('i').
return (
{ e.preventDefault(); window.DI_NAV?.go("home"); }} aria-label="Design Infinity — Home" style={{ display: "inline-flex", alignItems: "center", gap: "0.75rem" }}>
);
}
// --------- Nav
function Nav({ current, onNav }) {
const [scrolled, setScrolled] = useState(false);
const [menuOpen, setMenuOpen] = useState(false);
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 8);
window.addEventListener("scroll", onScroll);
return () => window.removeEventListener("scroll", onScroll);
}, []);
const navItems = [
{ key: "projects", label: "Projects" },
{ key: "in-house", label: "In-house" },
{ key: "contact", label: "Contact" },
];
return (
{menuOpen && (
)}
);
}
// --------- Footer
function Footer({ onNav }) {
return (
);
}
// --------- Lightbox
function Lightbox({ images, index, onClose, onIndex }) {
useEffect(() => {
const onKey = (e) => {
if (e.key === "Escape") onClose();
if (e.key === "ArrowLeft") onIndex((index - 1 + images.length) % images.length);
if (e.key === "ArrowRight") onIndex((index + 1) % images.length);
};
document.addEventListener("keydown", onKey);
document.body.style.overflow = "hidden";
return () => {
document.removeEventListener("keydown", onKey);
document.body.style.overflow = "";
};
}, [index, images.length, onClose, onIndex]);
return (

e.stopPropagation()} />
{String(index + 1).padStart(2, "0")} / {String(images.length).padStart(2, "0")}
);
}
Object.assign(window, { Arrow, Eyebrow, Logo, Nav, Footer, Lightbox });