/* ============================================================ Agency BRN — Shared Language Provider + Auto-detect Toast Used by homepage and all service pages. ============================================================ */ const LANG_STORAGE_KEY = "agencybrn_lang"; const LEGACY_STORAGE_KEY = "brn-lang"; function detectBrowserLanguage() { const browser = (navigator.language || "en").toLowerCase(); if (browser.startsWith("pt")) return "pt"; if (browser.startsWith("es")) return "es"; return "en"; } function getInitialLanguage() { const saved = localStorage.getItem(LANG_STORAGE_KEY) || localStorage.getItem(LEGACY_STORAGE_KEY); if (saved && ["en", "pt", "es"].includes(saved)) { return { lang: saved, autoDetected: false }; } return { lang: detectBrowserLanguage(), autoDetected: true }; } /* Direct-DOM toast — avoids React double-mount/effect timing pitfalls */ function showAutoDetectToast(lang) { if (window.__brnToastShown) return; window.__brnToastShown = true; const copy = { pt: { msg: "Detectamos seu navegador em português.", link: "Trocar idioma" }, es: { msg: "Detectamos tu navegador en español.", link: "Cambiar idioma" }, }; const c = copy[lang]; if (!c) return; const root = document.createElement("div"); root.className = "lang-toast"; root.setAttribute("role", "status"); root.setAttribute("aria-live", "polite"); const msg = document.createElement("span"); msg.className = "lang-toast__msg"; msg.textContent = c.msg; const link = document.createElement("a"); link.href = "#"; link.className = "lang-toast__link"; link.textContent = c.link + " →"; link.addEventListener("click", (e) => { e.preventDefault(); root.remove(); const sw = document.querySelector(".lang-switch"); if (sw) { sw.scrollIntoView({ behavior: "smooth", block: "center" }); sw.classList.add("lang-switch--pulse"); setTimeout(() => sw.classList.remove("lang-switch--pulse"), 2000); } }); const close = document.createElement("button"); close.type = "button"; close.className = "lang-toast__close"; close.setAttribute("aria-label", "Dismiss"); close.textContent = "×"; close.addEventListener("click", () => root.remove()); root.appendChild(msg); root.appendChild(link); root.appendChild(close); document.body.appendChild(root); window.__brnToastEl = root; console.log("[Toast] appended to body, children:", document.body.children.length); setTimeout(() => { if (root.parentNode) root.remove(); }, 60000); } function LanguageProvider({ children, basePath = "" }) { const initialRef = React.useRef(null); if (initialRef.current === null) { initialRef.current = getInitialLanguage(); } const initial = initialRef.current; const [lang, setLangState] = React.useState(initial.lang); // On mount: sync html lang + show auto-detect toast (idempotent via window flag) React.useEffect(() => { document.documentElement.lang = initial.lang; if (initial.autoDetected && initial.lang !== "en") { showAutoDetectToast(initial.lang); } }, []); const setLang = React.useCallback( (code) => { if (code === lang) return; // Dismiss any visible auto-detect toast when user picks manually document.querySelectorAll(".lang-toast").forEach((el) => el.remove()); document.body.classList.add("lang-fading"); setTimeout(() => { setLangState(code); localStorage.setItem(LANG_STORAGE_KEY, code); try { localStorage.removeItem(LEGACY_STORAGE_KEY); } catch (e) {} document.documentElement.lang = code; setTimeout(() => document.body.classList.remove("lang-fading"), 60); }, 180); }, [lang] ); const t = window.TRANSLATIONS[lang]; // Reveal-on-scroll observer (re-bind on lang change so newly mounted nodes are observed) React.useEffect(() => { const els = document.querySelectorAll(".reveal"); if (!("IntersectionObserver" in window)) { els.forEach((el) => el.classList.add("is-visible")); return; } const io = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add("is-visible"); io.unobserve(entry.target); } }); }, { threshold: 0.12, rootMargin: "0px 0px -40px 0px" } ); els.forEach((el) => io.observe(el)); return () => io.disconnect(); }, [lang]); const ctx = React.useMemo( () => ({ lang, setLang, t, basePath }), [lang, setLang, t, basePath] ); return ( {children} ); } window.LanguageProvider = LanguageProvider; window.showAutoDetectToast = showAutoDetectToast;