/* ============================================================ NemakiWare — app shell, nav, lang toggle, hero switcher, footer ============================================================ */ const { useState, useEffect, useRef } = React; const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "brandAccent": "#076bb8", "headingFont": "Space Grotesk" }/*EDITMODE-END*/; const THEMES = { "#076bb8": { "--teal-700":"oklch(0.44 0.135 252)","--teal-600":"oklch(0.52 0.155 252)","--teal-500":"oklch(0.60 0.165 252)","--teal-400":"oklch(0.70 0.135 252)","--teal-200":"oklch(0.89 0.06 252)","--teal-100":"oklch(0.955 0.03 252)","--accent-bright":"oklch(0.72 0.15 254)" }, "#1c7d86": { "--teal-700":"oklch(0.45 0.075 205)","--teal-600":"oklch(0.55 0.085 200)","--teal-500":"oklch(0.64 0.095 195)","--teal-400":"oklch(0.74 0.085 192)","--teal-200":"oklch(0.90 0.045 195)","--teal-100":"oklch(0.95 0.025 195)","--accent-bright":"oklch(0.70 0.12 198)" }, "#2f6fd6": { "--teal-700":"oklch(0.46 0.115 250)","--teal-600":"oklch(0.54 0.13 250)","--teal-500":"oklch(0.62 0.14 250)","--teal-400":"oklch(0.72 0.12 250)","--teal-200":"oklch(0.90 0.05 250)","--teal-100":"oklch(0.955 0.028 250)","--accent-bright":"oklch(0.71 0.15 252)" }, "#6a59d8": { "--teal-700":"oklch(0.46 0.13 285)","--teal-600":"oklch(0.54 0.15 285)","--teal-500":"oklch(0.62 0.16 285)","--teal-400":"oklch(0.72 0.13 285)","--teal-200":"oklch(0.90 0.055 285)","--teal-100":"oklch(0.955 0.03 285)","--accent-bright":"oklch(0.72 0.16 288)" }, }; function applyTheme(hex) { const t = THEMES[hex] || THEMES["#076bb8"]; const root = document.documentElement; root.style.setProperty("--accent-strong", hex); Object.entries(t).forEach(([k, v]) => root.style.setProperty(k, v)); } /* ---- top navigation ------------------------------------------- */ function Nav({ t, lang, setLang, variant }) { const [scrolled, setScrolled] = useState(false); const [open, setOpen] = useState(false); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 24); onScroll(); window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); const logoDark = variant === "b" && !scrolled; const overDark = variant === "b" && !scrolled; const links = [ ["#features", t.nav.features], ["#security", t.nav.security], ["#mcp", t.nav.mcp], ["#lineage", t.nav.lineage], ["#architecture", t.nav.architecture], ]; return (
{t.nav.cta}
); } /* ---- hero variant switcher (design exploration control) ------- */ function HeroSwitcher({ variant, setVariant, lang }) { const labels = lang === "ja" ? { a: "エディトリアル", b: "没入型", c: "コンソール" } : { a: "Editorial", b: "Immersive", c: "Console" }; return (
{lang === "ja" ? "ヒーロー" : "Hero"} {["a", "b", "c"].map((v) => ( ))}
); } /* ---- footer --------------------------------------------------- */ function Footer({ t, lang, setLang }) { const f = t.footer; const cols = [ { h: f.product, links: f.links_product, hrefs: ["#features", "#architecture", "#mcp", "#security"] }, { h: f.community, links: f.links_community, hrefs: ["https://github.com/aegif/NemakiWare", "http://nemakiware.org/", "https://github.com/aegif/NemakiWare/tree/master/docs", "https://github.com/aegif/NemakiWare/releases"] }, { h: f.company, links: f.links_company, hrefs: ["http://aegif.jp/", "https://nemakiware.com/contact.php", "https://nemakiware.com/privacy.html"] }, ]; return ( ); } /* ---- root app ------------------------------------------------- */ function App() { const [tw, setTweak] = useTweaks(TWEAK_DEFAULTS); const [lang, setLangState] = useState(() => localStorage.getItem("nw_lang") || "en"); const [variant, setVariantState] = useState(() => localStorage.getItem("nw_hero") || "a"); const setLang = (l) => { setLangState(l); localStorage.setItem("nw_lang", l); }; const setVariant = (v) => { setVariantState(v); localStorage.setItem("nw_hero", v); }; useEffect(() => { applyTheme(tw.brandAccent); }, [tw.brandAccent]); useEffect(() => { document.documentElement.style.setProperty("--display", `"${tw.headingFont}", "Noto Sans JP", sans-serif`); }, [tw.headingFont]); useEffect(() => { document.documentElement.lang = lang; }, [lang]); const t = window.CONTENT[lang]; return (
); } const root = ReactDOM.createRoot(document.getElementById("root")); root.render();