/* ui.jsx — shared helpers & primitives for RS Vial */ const { useState, useEffect, useRef, useCallback } = React; /* Reveal-on-scroll wrapper */ function Reveal({ children, as = "div", delay = 0, className = "", style = {}, ...rest }) { const ref = useRef(null); const [shown, setShown] = useState(false); useEffect(() => { const el = ref.current; if (!el) return; const io = new IntersectionObserver( (es) => es.forEach((e) => { if (e.isIntersecting) { setShown(true); io.disconnect(); } }), { threshold: 0.14, rootMargin: "0px 0px -8% 0px" } ); io.observe(el); return () => io.disconnect(); }, []); const Tag = as; return ( {children} ); } /* Small arrow glyph */ function Arrow({ size = 16 }) { return ( ); } /* Section header block (kicker + title) */ function SecHead({ num, kicker, title, intro, onDark = false, align = "left", max = 640 }) { return (
{num ? num + " · " : ""}{kicker}

{title}

{intro && (

{intro}

)}
); } /* Logo — real image, picks light/dark version by background */ function Logo({ name = "RS CONSTRUCTORA", onDark = false, size = 1 }) { return ( { e.preventDefault(); scrollToId("top"); }} aria-label={name} style={{ display: "inline-flex", alignItems: "center", lineHeight: 0 }}> {name} ); } Object.assign(window, { Reveal, Arrow, SecHead, Logo, scrollToId }); /* Safe smooth scroll to a section id (avoids scrollIntoView) */ function scrollToId(id) { const el = document.getElementById(id); if (!el) return; const top = el.getBoundingClientRect().top + window.scrollY - 64; window.scrollTo({ top, behavior: "smooth" }); }