/* global React */ const { useState: useS_sh, useEffect: useE_sh } = React; /* ────────────────────────────────────────────── Page identifiers — used for active nav state ────────────────────────────────────────────── */ const NAV_ITEMS = [ { id: "home", href: "index.html", label: "Início" }, { id: "sobre", href: "sobre.html", label: "Sobre" }, { id: "plataforma", href: "plataforma.html", label: "Plataforma" }, { id: "servicos", href: "servicos.html", label: "Serviços" }, { id: "contato", href: "contato.html", label: "Contato" }, ]; /* ────────────────────────────────────────────── Logo (respeita logo original; fallback elegante) ────────────────────────────────────────────── */ function Logo() { const [failed, setFailed] = useS_sh(false); return ( {!failed && ( Crime Solution setFailed(true)} /> )} {failed && ( CRIME SOLUTION )} ); } /* ────────────────────────────────────────────── Nav with active page state ────────────────────────────────────────────── */ function Nav({ active }) { const [open, setOpen] = useS_sh(false); const [scrolled, setScrolled] = useS_sh(false); useE_sh(() => { const on = () => setScrolled(window.scrollY > 24); on(); window.addEventListener("scroll", on, { passive: true }); return () => window.removeEventListener("scroll", on); }, []); return (
Área restrita Falar agora
{open && (
{NAV_ITEMS.map((it) => ( {it.label} ))} Área restrita Falar agora
)}
); } /* ────────────────────────────────────────────── Footer ────────────────────────────────────────────── */ function Footer() { return ( ); } /* ────────────────────────────────────────────── Tweaks orchestration — shared across pages via localStorage ────────────────────────────────────────────── */ const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "theme": "dark", "accent": "#5eead4", "density": "comfortable", "scanlines": true }/*EDITMODE-END*/; const ACCENTS = ["#5eead4", "#7dd3fc", "#a3e635", "#f0abfc"]; function applyTheme(t) { document.documentElement.setAttribute("data-theme", t.theme || "dark"); document.documentElement.style.setProperty("--accent", t.accent || "#5eead4"); document.documentElement.style.setProperty( "--accent-fg", t.theme === "light" ? "#0a0f1c" : "#06121b" ); document.documentElement.dataset.density = t.density || "comfortable"; document.documentElement.dataset.scanlines = t.scanlines ? "on" : "off"; } function CrimeTweaks({ extra }) { // useTweaks comes from tweaks-panel.jsx and writes to the host through the // edit-mode protocol; we ALSO mirror to localStorage so tweaks survive page nav. const stored = (() => { try { return JSON.parse(localStorage.getItem("cs.tweaks") || "null"); } catch { return null; } })(); const initial = { ...TWEAK_DEFAULTS, ...(stored || {}) }; const [t, setTweak] = useTweaks(initial); useE_sh(() => { applyTheme(t); localStorage.setItem("cs.tweaks", JSON.stringify(t)); }, [t]); return ( setTweak("theme", v)} /> setTweak("accent", v)} /> {extra && extra(t, setTweak)} setTweak("density", v)} /> setTweak("scanlines", v === "on")} /> ); } /* ────────────────────────────────────────────── Page shell — wraps Nav + main + Footer + Tweaks + Security ────────────────────────────────────────────── */ function PageShell({ active, tweaksExtra, children }) { // Active runtime hardening on every page usePageHardening(); // Reveal-on-scroll for .reveal elements useE_sh(() => { const io = new IntersectionObserver( (entries) => entries.forEach((e) => { if (e.isIntersecting) e.target.classList.add("in"); }), { threshold: 0.12 } ); document.querySelectorAll(".reveal").forEach((el) => io.observe(el)); return () => io.disconnect(); }, []); // Apply persisted theme even before tweaks panel mounts useE_sh(() => { try { const stored = JSON.parse(localStorage.getItem("cs.tweaks") || "null"); if (stored) applyTheme(stored); } catch {} }, []); return ( <>