// Shared UI helpers
const { useState, useEffect, useRef, useMemo } = React;
function Reveal({ children, delay = 0, as: Tag = "div", ...rest }) {
const ref = useRef(null);
const [visible, setVisible] = useState(false);
useEffect(() => {
const el = ref.current;if (!el) return;
const io = new IntersectionObserver((entries) => {
entries.forEach((e) => {if (e.isIntersecting) {setTimeout(() => setVisible(true), delay);io.unobserve(el);}});
}, { threshold: 0.12 });
io.observe(el);
return () => io.disconnect();
}, [delay]);
return {children};
}
function ThemeToggle() {
const [mode, setMode] = useState(() => {
try {return localStorage.getItem("stz_theme") || "system";}
catch {return "system";}
});
useEffect(() => {
const root = document.documentElement;
const apply = () => {
let effective = mode;
if (mode === "system") {
effective = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
}
if (effective === "dark") root.setAttribute("data-theme", "dark");else
root.removeAttribute("data-theme");
};
apply();
try {localStorage.setItem("stz_theme", mode);} catch {}
if (mode === "system") {
const mq = window.matchMedia("(prefers-color-scheme: dark)");
const handler = () => apply();
mq.addEventListener?.("change", handler);
return () => mq.removeEventListener?.("change", handler);
}
}, [mode]);
const opts = [
{ val: "light", label: "Light",
icon:
},
{ val: "system", label: "System",
icon:
},
{ val: "dark", label: "Dark",
icon:
}];
const cycle = () => {
const i = opts.findIndex((o) => o.val === mode);
setMode(opts[(i + 1) % opts.length].val);
};
const current = opts.find((o) => o.val === mode) || opts[1];
return (
<>
{opts.map((o) =>
)}
>);
}
function Nav({ current, onGo }) {
const [stuck, setStuck] = useState(false);
const [open, setOpen] = useState(false);
useEffect(() => {
const onScroll = () => setStuck(window.scrollY > 8);
window.addEventListener("scroll", onScroll, { passive: true });
return () => window.removeEventListener("scroll", onScroll);
}, []);
useEffect(() => {
document.body.style.overflow = open ? "hidden" : "";
return () => {document.body.style.overflow = "";};
}, [open]);
const links = [
["home", "Home"],
["about", "About"],
["work", "Work"],
["services", "Services"],
["insights", "Insights"],
["contact", "Contact"]];
const goAndClose = (id) => {onGo(id);setOpen(false);};
return (
<>
{/* Mobile drawer — sibling of nav so it escapes nav's backdrop-filter containing block */}
{if (e.target === e.currentTarget) setOpen(false);}}>
{links.map(([id, label], i) =>
)}
hello@stanzin.xyz
Bengaluru · IST
>);
}
function SectionHead({ num, title, lede, titleHtml }) {
return (
{num}
{titleHtml ?
:
{title}
}
{lede &&
{lede}
}
);
}
function Marquee({ items }) {
const doubled = [...items, ...items];
return (
{doubled.map((x, i) => {x})}
);
}
function Footer({ onGo }) {
return (
);
}
Object.assign(window, { Reveal, Nav, SectionHead, Marquee, Footer });