/* ============================================================ NemakiWare — shared UI: logo, icons, reveal, primitives Exposes components on window. ============================================================ */ const { useState, useEffect, useRef } = React; /* ---- scroll reveal (scroll + fallback; IO-free for reliability) */ function Reveal({ children, as = "div", delay = 0, className = "", ...rest }) { const ref = useRef(null); const El = as; useEffect(() => { const el = ref.current; if (!el) return; let done = false; const reveal = () => { if (!done) { done = true; el.classList.add("in"); cleanup(); } }; const check = () => { const r = el.getBoundingClientRect(); if (r.top < (window.innerHeight || 800) * 0.92 && r.bottom > 0) reveal(); }; const onScroll = () => check(); function cleanup() { window.removeEventListener("scroll", onScroll); window.removeEventListener("resize", onScroll); clearTimeout(t); } check(); window.addEventListener("scroll", onScroll, { passive: true }); window.addEventListener("resize", onScroll, { passive: true }); const t = setTimeout(reveal, 1600); // hard fallback so content never stays hidden return cleanup; }, []); return ( {children} ); } /* ---- logo (real brand asset) ---------------------------------- */ function Logo({ onDark = false, size = 40 }) { return ( NemakiWare ); } /* ---- icon set (simple line icons) ----------------------------- */ const ICONS = { shield: "M12 3l7 3v5c0 4.5-3 7.6-7 9-4-1.4-7-4.5-7-9V6l7-3z", search: ["M11 4a7 7 0 1 0 0 14 7 7 0 0 0 0-14z", "M16.5 16.5L21 21"], layers: ["M12 3l9 5-9 5-9-5 9-5z", "M3 13l9 5 9-5"], plug: ["M8 3v5", "M16 3v5", "M6 8h12v2a6 6 0 0 1-12 0V8z", "M12 16v5"], cube: ["M12 3l8 4.5v9L12 21l-8-4.5v-9L12 3z", "M12 3v18", "M4 7.5l8 4.5 8-4.5"], cycle: ["M4 12a8 8 0 0 1 13.5-5.8L20 8", "M20 4v4h-4", "M20 12a8 8 0 0 1-13.5 5.8L4 16", "M4 20v-4h4"], monitor: ["M3 4h18v12H3z", "M8 20h8", "M12 16v4"], lock: ["M6 10V8a6 6 0 0 1 12 0v2", "M5 10h14v10H5z"], tree: ["M12 4v5", "M6 20v-4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v4", "M12 9v5", "M10 2h4v4h-4z", "M4 18h4v4H4z", "M16 18h4v4h-4z"], users: ["M9 11a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z", "M2.5 20a6.5 6.5 0 0 1 13 0", "M16 4.5a3.5 3.5 0 0 1 0 7", "M17 14.2A6.5 6.5 0 0 1 21.5 20"], eye: ["M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7z", "M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"], check: ["M4 12.5l5 5 11-11"], arrow: ["M5 12h14", "M13 6l6 6-6 6"], arrowDown: ["M12 5v14", "M6 13l6 6 6-6"], github: "M12 2a10 10 0 0 0-3.16 19.49c.5.09.68-.22.68-.48l-.01-1.7c-2.78.6-3.37-1.34-3.37-1.34-.45-1.16-1.11-1.47-1.11-1.47-.91-.62.07-.61.07-.61 1 .07 1.53 1.03 1.53 1.03.9 1.53 2.36 1.09 2.94.83.09-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.94 0-1.09.39-1.98 1.03-2.68-.1-.25-.45-1.27.1-2.65 0 0 .84-.27 2.75 1.02a9.56 9.56 0 0 1 5 0c1.91-1.29 2.75-1.02 2.75-1.02.55 1.38.2 2.4.1 2.65.64.7 1.03 1.59 1.03 2.68 0 3.84-2.34 4.69-4.57 4.94.36.31.68.92.68 1.85l-.01 2.74c0 .27.18.58.69.48A10 10 0 0 0 12 2z", globe: ["M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18z", "M3 12h18", "M12 3c2.5 2.4 3.8 5.6 3.8 9s-1.3 6.6-3.8 9c-2.5-2.4-3.8-5.6-3.8-9S9.5 5.4 12 3z"], spark: ["M12 3l1.8 5.2L19 10l-5.2 1.8L12 17l-1.8-5.2L5 10l5.2-1.8L12 3z"], doc: ["M7 3h7l4 4v14H7z", "M14 3v4h4"], bolt: ["M13 3L5 13h6l-1 8 8-10h-6l1-8z"], key: ["M14 7a4 4 0 1 1-5.7 3.6L3 16v3h3l1-1h2v-2h2l1.3-1.3A4 4 0 0 1 14 7z"], link: ["M9 15l6-6", "M11 6l1-1a4 4 0 0 1 6 6l-1 1", "M13 18l-1 1a4 4 0 0 1-6-6l1-1"], import: ["M12 3v12", "M7 10l5 5 5-5", "M4 20h16"], database: ["M12 3c4.4 0 8 1.3 8 3s-3.6 3-8 3-8-1.3-8-3 3.6-3 8-3z", "M4 6v6c0 1.7 3.6 3 8 3s8-1.3 8-3V6", "M4 12v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6"], }; function Icon({ name, size = 22, stroke = 1.9, fill = false, style }) { const d = ICONS[name]; const paths = Array.isArray(d) ? d : [d]; const isFill = fill || name === "github"; return ( {paths.map((p, i) => )} ); } /* ---- placeholder visual (subtle striped) ---------------------- */ function Placeholder({ label, h = 200, dark = false }) { const stroke = dark ? "rgba(255,255,255,0.10)" : "oklch(0.55 0.06 220 / 0.14)"; return (
{label}
); } Object.assign(window, { Reveal, Logo, Icon, Placeholder });