// Eu Faço Parte — Sections part 1: Nav, Hero, Mission band, "O que fazemos" intro
const HeartIcon = ({ size = 14 }) => (
);
const Logo = ({ src = "assets/logo.png" }) =>
;
const PROJETOS_NAV = [
{ name: 'Surf Sagi', href: 'projeto-surf-sagi.html' },
{ name: 'Artesanato & Brinquedos', href: 'projeto-artesanato.html' },
{ name: 'Sagi Vidas', href: 'projeto-sagi-vidas.html' },
{ name: 'Sonhos em Campo', href: 'projeto-sonhos-campo.html' },
{ name: 'Juntos nós Cuidamos', href: 'projeto-juntos.html' },
{ name: 'Abrigo ANCA & Educação Profissional', href: 'projeto-anca.html' },
{ name: 'Roupas & Memórias', href: 'projeto-roupas.html' },
{ name: 'Dia das Crianças para 300 jovens', href: 'projeto-dia-criancas.html' },
{ name: 'O direito de celebrar', href: 'projeto-celebrar.html' },
{ name: 'Memórias Afetivas e Saudáveis na Cozinha', href: 'projeto-cozinha.html' },
];
const ProjectsModal = ({ onClose }) => (
e.stopPropagation()} style={{ maxWidth: '640px' }}>
×
01.1 · Nossas iniciativas
Selecione o projeto
);
const Nav = () => {
const [projectsOpen, setProjectsOpen] = React.useState(false);
React.useEffect(() => { window.openProjectsModal = () => setProjectsOpen(true); }, []);
const GT_LANGS = [
{ code: 'pt', country: 'br', label: 'Português (BR)' },
{ code: 'pt', country: 'pt', label: 'Português (PT)' },
{ code: 'en', country: 'gb', label: 'English' },
{ code: 'de', country: 'ch', label: 'Deutsch' },
{ code: 'fr', country: 'fr', label: 'Français' },
{ code: 'it', country: 'it', label: 'Italiano' },
{ code: 'es', country: 'es', label: 'Español' },
{ code: 'ja', country: 'jp', label: '日本語' },
{ code: 'zh-CN', country: 'cn', label: '中文' },
];
const GoogleTranslate = () => {
const [open, setOpen] = React.useState(false);
const wrapRef = React.useRef(null);
React.useEffect(() => {
const close = (e) => { if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false); };
document.addEventListener('mousedown', close);
return () => document.removeEventListener('mousedown', close);
}, []);
const openTranslation = (lang) => {
setOpen(false);
const url = `https://translate.google.com/translate?sl=pt&tl=${encodeURIComponent(lang.code)}&u=${encodeURIComponent(window.location.href)}`;
window.open(url, '_blank', 'noopener');
};
const Flag = ({ country, w }) => (
{ e.currentTarget.style.display = 'none'; }} />
);
const GlobeIcon = () => (
);
const langs = GT_LANGS.filter(l => l.code !== 'pt');
return (
{open && (
{langs.map(lang => (
openTranslation(lang)} title={lang.label}
style={{
background: 'none', border: 'none', cursor: 'pointer',
padding: '5px', borderRadius: '7px',
display: 'flex', alignItems: 'center', justifyContent: 'center',
transition: 'background 0.15s',
}}
onMouseEnter={(e) => e.currentTarget.style.background = 'var(--paper-2)'}
onMouseLeave={(e) => e.currentTarget.style.background = 'none'}
>
))}
)}
setOpen(o => !o)} title="Selecionar idioma"
style={{
width: '52px', height: '52px', borderRadius: '50%',
background: 'var(--paper)', border: '1px solid var(--rule)',
cursor: 'pointer', padding: 0,
display: 'flex', alignItems: 'center', justifyContent: 'center',
boxShadow: '0 4px 18px rgba(0,0,0,0.13)',
transition: 'box-shadow 0.2s, border-color 0.2s',
}}
onMouseEnter={(e) => { e.currentTarget.style.boxShadow = '0 6px 24px rgba(0,0,0,0.20)'; e.currentTarget.style.borderColor = 'var(--accent)'; }}
onMouseLeave={(e) => { e.currentTarget.style.boxShadow = '0 4px 18px rgba(0,0,0,0.13)'; e.currentTarget.style.borderColor = 'var(--rule)'; }}
>
);
};
const scrollTo = (id) => (e) => {
const el = document.getElementById(id);
if (el) { e.preventDefault(); el.scrollIntoView({ behavior: 'smooth' }); }
};
return (
<>
window.openDonationModal?.()}>
Faça uma doação
{projectsOpen && setProjectsOpen(false)} />}
>
);
};
// ---- Translation banner ----
const BANNER_LANGS = {
en: { msg: "We noticed your browser is set to English. Would you like to see this page translated?", btn: "Yes, translate", code: 'en' },
de: { msg: "Wir haben bemerkt, dass Ihr Browser auf Deutsch eingestellt ist. Möchten Sie die Seite übersetzt sehen?", btn: "Ja, übersetzen", code: 'de' },
fr: { msg: "Votre navigateur est en français. Souhaitez-vous voir cette page traduite ?", btn: "Oui, traduire", code: 'fr' },
it: { msg: "Il tuo browser è impostato in italiano. Vuoi vedere questa pagina tradotta?", btn: "Sì, traduci", code: 'it' },
es: { msg: "Tu navegador está en español. ¿Deseas ver esta página traducida?", btn: "Sí, traducir", code: 'es' },
ja: { msg: "ブラウザが日本語に設定されています。このページを翻訳して表示しますか?", btn: "翻訳する", code: 'ja' },
zh: { msg: "您的浏览器设置为中文。您是否希望查看此页面的翻译版本?", btn: "翻译页面", code: 'zh-CN' },
ar: { msg: "لاحظنا أن متصفحك مضبوط على اللغة العربية. هل تريد رؤية هذه الصفحة مترجمة؟", btn: "نعم، ترجم", code: 'ar' },
};
const TranslationBanner = () => {
const [show, setShow] = React.useState(false);
const [lang, setLang] = React.useState(null);
React.useEffect(() => {
if (sessionStorage.getItem('transl-banner-dismissed')) return;
const base = (navigator.language || '').toLowerCase().split('-')[0];
if (base === 'pt' || !BANNER_LANGS[base]) return;
setLang(BANNER_LANGS[base]);
setShow(true);
}, []);
if (!show || !lang) return null;
const dismiss = () => {
setShow(false);
sessionStorage.setItem('transl-banner-dismissed', '1');
};
const translate = () => {
const url = `https://translate.google.com/translate?sl=pt&tl=${encodeURIComponent(lang.code)}&u=${encodeURIComponent(window.location.href)}`;
window.open(url, '_blank', 'noopener');
dismiss();
};
return (
{lang.msg} 🤍
e.currentTarget.style.background = 'rgba(255,255,255,0.25)'}
onMouseLeave={e => e.currentTarget.style.background = 'rgba(255,255,255,0.15)'}
>{lang.btn}
×
);
};
// ---- Donation social proof toast ----
const TOAST_NAMES = [
'Maria S.','João P.','Ana C.','Carlos M.','Fernanda L.',
'Rafael T.','Beatriz O.','Lucas N.','Camila R.','Pedro A.',
'Juliana F.','Marcos V.','Larissa B.','Thiago D.','Isabela G.',
'Bruno K.','Vanessa H.','Diego E.','Natália W.','Felipe C.',
'Letícia M.','Rodrigo A.','Priscila S.','Eduardo B.','Aline F.',
];
const DonationToast = () => {
const [visible, setVisible] = React.useState(false);
const [info, setInfo] = React.useState({ name: '', value: '' });
React.useEffect(() => {
let hideTimer, nextTimer;
const trigger = () => {
const name = TOAST_NAMES[Math.floor(Math.random() * TOAST_NAMES.length)];
const val = Math.floor(Math.random() * 171) + 30;
setInfo({ name, value: `R$${val},00` });
setVisible(true);
hideTimer = setTimeout(() => setVisible(false), 5000);
nextTimer = setTimeout(trigger, 25000 + Math.random() * 50000);
};
nextTimer = setTimeout(trigger, 4000);
return () => { clearTimeout(hideTimer); clearTimeout(nextTimer); };
}, []);
return (
{info.name} doou {info.value}
);
};
// ---- HERO ----
const Hero = () =>
Associação sem fins lucrativos · 🇧🇷 / 🇨🇭
Juntos nós cuidamos, sonhamos e realizamos.
Nossa missão é oferecer abrigo, educação e profissionalização para jovens e crianças em situações de vulnerabilidade social, possibilitando que desenvolvam seus caminhos, ampliem seus olhares sobre o mundo e conquistem a sua independência.
✻ {' '}
O potencial para um futuro brilhante existe em todos, mas a vulnerabilidade social nega a muitos a chance de sonhar. A nossa união é a força que pode derrubar essas barreiras e criar novas oportunidades.
;
// ---- Partners band ----
const Partners = () =>
✻ Nossos parceiros
Google for Nonprofits
NordVPN
Allegra Private Tours
;
// ---- Loja — catálogo completo (loja.eufacoparte.org/shop) ----
// Preços convertidos de BRL → CHF (taxa: 1 CHF ≈ 6,0 BRL — conversão manual mai/2026)
const LOJA_ALL = [
// Decoração natalina
{ name: '3 Bolas natalinas douradas', art: 'as', price: 'CHF 107', oldPrice: null, cat: 'Decoração', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-125-35-min-433x516.jpg' },
{ name: 'Anjinho decorativo natalino', art: 'o', price: 'CHF 54', oldPrice: null, cat: 'Decoração', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-153-Edit-43-min-433x516.jpg' },
{ name: 'Bolas decorativas de natal – Luxo', art: 'as', price: 'CHF 129', oldPrice: null, cat: 'Decoração', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/produto_natal_01_bolas-433x516.png' },
{ name: 'Bolas natalinas exclusivas', art: 'as', price: 'CHF 214', oldPrice: null, cat: 'Decoração', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-146-Edit-41-min-433x516.jpg' },
{ name: 'Botas decorativas natal azul', art: 'as', price: 'CHF 54', oldPrice: null, cat: 'Decoração', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-139-39-min-433x516.jpg' },
{ name: 'Conjunto 3 bolas natalinas', art: 'o', price: 'CHF 107', oldPrice: null, cat: 'Decoração', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-131-38-min-433x516.jpg' },
{ name: 'Conjunto 6 bolas natalinas história', art: 'o', price: 'CHF 161', oldPrice: 'CHF 214', cat: 'Decoração', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-128-37-min-433x516.jpg' },
{ name: 'Conjunto dourado natalino exclusivo', art: 'o', price: 'CHF 214', oldPrice: null, cat: 'Decoração', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-123-Edit-34-min-433x516.jpg' },
{ name: 'Conjunto exclusivo natal dourado', art: 'o', price: 'CHF 75', oldPrice: 'CHF 107', cat: 'Decoração', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-125-35-min-433x516.jpg' },
{ name: 'Conjunto natalino premium', art: 'o', price: 'CHF 321', oldPrice: null, cat: 'Decoração', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-144-40-min-433x516.jpg' },
{ name: 'Conjunto premium natal histórias', art: 'o', price: 'CHF 321', oldPrice: null, cat: 'Decoração', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-118-Edit-33-min-433x516.jpg' },
{ name: 'Decoração premium rainha', art: 'a', price: 'CHF 171', oldPrice: 'CHF 214', cat: 'Decoração', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-127-36-min-433x516.jpg' },
{ name: 'Enfeite natalino anjinho', art: 'o', price: null, oldPrice: null, cat: 'Decoração', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-159-Edit-45-min-433x516.jpg' },
// Moda Circular
{ name: 'Blazer couro legítimo', art: 'o', price: 'CHF 482', oldPrice: 'CHF 535', cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-221-Edit-64-433x516.jpg' },
{ name: 'Blazer elegante Modeco', art: 'o', price: 'CHF 535', oldPrice: null, cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-254-Edit-73-433x516.jpg' },
{ name: 'Blazer marrom xadrez interno', art: 'o', price: 'CHF 535', oldPrice: null, cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-247-Edit-70-433x516.jpg' },
{ name: 'Blazer preto', art: 'o', price: 'CHF 535', oldPrice: null, cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-261-Edit-75-433x516.jpg' },
{ name: 'Blazer único de marca elegante', art: 'o', price: 'CHF 1.605',oldPrice: null, cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-231-Edit-66-433x516.jpg' },
{ name: 'Calça preta elegante MODECO', art: 'a', price: 'CHF 535', oldPrice: null, cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-253-Edit-72-433x516.jpg' },
{ name: 'Casaco de Marca M', art: 'o', price: 'CHF 129', oldPrice: null, cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/produto_casaco_01-433x516.png' },
{ name: 'Casaco de Marca M Textura', art: 'o', price: 'CHF 96', oldPrice: null, cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/produto_casaco_02-433x516.png' },
{ name: 'Casaco marrom elegante', art: 'o', price: 'CHF 535', oldPrice: null, cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-250-Edit-71-433x516.jpg' },
{ name: 'Saia conjunto', art: 'a', price: 'CHF 166', oldPrice: 'CHF 209', cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/produto_saia_02-433x516.png' },
{ name: 'Saia preta elegante', art: 'a', price: 'CHF 535', oldPrice: null, cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-256-Edit-74-433x516.jpg' },
{ name: 'Sobretudo elegante', art: 'o', price: 'CHF 482', oldPrice: 'CHF 535', cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-244-Edit-69-433x516.jpg' },
{ name: 'Sobretudo marrom', art: 'o', price: 'CHF 482', oldPrice: 'CHF 535', cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-242-Edit-68-433x516.jpg' },
{ name: 'Sobretudo marrom c/ manga bordada', art: 'o', price: 'CHF 482', oldPrice: 'CHF 535', cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-239-Edit-67-433x516.jpg' },
{ name: 'Sobretudo modelo chinês', art: 'o', price: 'CHF 1.605',oldPrice: null, cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-228-Edit-65-433x516.jpg' },
{ name: 'Stripe Sweater', art: 'o', price: 'CHF 214', oldPrice: null, cat: 'Moda Circular', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/1-33-433x516.jpg' },
// Acessórios
{ name: 'Bolsa em couro legítimo', art: 'a', price: 'CHF 642', oldPrice: null, cat: 'Acessório', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-064-Edit-18-min-433x516.jpg' },
{ name: 'Chapéu beje LOEVENICH', art: 'o', price: 'CHF 321', oldPrice: null, cat: 'Acessório', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-071-Edit-20-min-433x516.jpg' },
{ name: 'Chapéu de cor natural', art: 'o', price: 'CHF 54', oldPrice: 'CHF 75', cat: 'Acessório', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/produto_chapeu_01-433x516.png' },
{ name: 'Chapéu de Marca', art: 'o', price: 'CHF 155', oldPrice: null, cat: 'Acessório', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/produto_chapeu_02-433x516.png' },
{ name: 'Chapéu Golfino', art: 'o', price: 'CHF 321', oldPrice: null, cat: 'Acessório', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-033-Edit-8-min-433x516.jpg' },
{ name: 'Chapéu lembert com laço', art: 'o', price: 'CHF 321', oldPrice: null, cat: 'Acessório', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-100-Edit-28-min-433x516.jpg' },
{ name: 'Chapeu Luielle', art: 'o', price: 'CHF 428', oldPrice: null, cat: 'Acessório', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-039-Edit-10-min-433x516.jpg' },
{ name: 'Chapeu Montegallo', art: 'o', price: 'CHF 428', oldPrice: null, cat: 'Acessório', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-044-Edit-2-12-min-433x516.jpg' },
{ name: 'Chapeu Montegallo premium', art: 'o', price: null, oldPrice: null, cat: 'Acessório', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-031-Edit-6-min-433x516.jpg' },
{ name: 'Chapéu natural premium', art: 'o', price: 'CHF 257', oldPrice: null, cat: 'Acessório', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-021-Edit-3-min-433x516.jpg' },
{ name: 'Chapéu preto LOEVENICH', art: 'o', price: 'CHF 268', oldPrice: null, cat: 'Acessório', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-086-Edit-23-min-433x516.jpg' },
{ name: 'Chapéu preto Seeberger', art: 'o', price: 'CHF 428', oldPrice: null, cat: 'Acessório', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-023-Edit-4-min-433x516.jpg' },
{ name: 'Chapéu tradicional de marca', art: 'o', price: 'CHF 535', oldPrice: null, cat: 'Acessório', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-054-Edit-16-min-433x516.jpg' },
{ name: 'Chapéu verde LOEVENICH', art: 'o', price: 'CHF 321', oldPrice: null, cat: 'Acessório', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-094-Edit-26-min-433x516.jpg' },
// Calçados
{ name: 'Sandália Gucci', art: 'a', price: 'CHF 1.605',oldPrice: null, cat: 'Calçado', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-218-Edit-58-433x516.jpg' },
{ name: 'Sapato branco em couro', art: 'o', price: null, oldPrice: null, cat: 'Calçado', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-193-Edit-53-433x516.jpg' },
{ name: 'Sapato branco c/ detalhes', art: 'o', price: 'CHF 696', oldPrice: 'CHF 1.070',cat: 'Calçado', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-189-Edit-52-433x516.jpg' },
{ name: 'Sapato casual de marca preto', art: 'o', price: 'CHF 535', oldPrice: 'CHF 696', cat: 'Calçado', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-177-Edit-49-433x516.jpg' },
{ name: 'Sapato casual de marca branco', art: 'o', price: null, oldPrice: null, cat: 'Calçado', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-167-Edit-47-433x516.jpg' },
{ name: 'Sapato com detalhes xadrez', art: 'o', price: null, oldPrice: null, cat: 'Calçado', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-213-Edit-57-433x516.jpg' },
{ name: 'Sapato elegante c/ detalhes em couro', art: 'o', price: 'CHF 482', oldPrice: 'CHF 535', cat: 'Calçado', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-205-Edit-56-433x516.jpg' },
{ name: 'Sapato elegante único feito a mão', art: 'o', price: 'CHF 963', oldPrice: 'CHF 1.070',cat: 'Calçado', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-201-Edit-55-433x516.jpg' },
{ name: 'Sapato Gucci', art: 'o', price: 'CHF 450', oldPrice: null, cat: 'Calçado', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/produto_sapato_03-433x516.png' },
{ name: 'Sapato para golf elegante', art: 'o', price: 'CHF 749', oldPrice: 'CHF 1.070',cat: 'Calçado', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-185-Edit-51-433x516.jpg' },
{ name: 'Sapato preto e marrom legítimo', art: 'o', price: 'CHF 535', oldPrice: null, cat: 'Calçado', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-197-Edit-54-433x516.jpg' },
{ name: 'Sapato em couro', art: 'o', price: 'CHF 535', oldPrice: null, cat: 'Calçado', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-201-Edit-55-433x516.jpg' },
{ name: 'Sapato preto em couro', art: 'o', price: 'CHF 589', oldPrice: 'CHF 642', cat: 'Calçado', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/FacoParte-184-Edit-50-433x516.jpg' },
{ name: 'Tênis Rosa', art: 'o', price: 'CHF 236', oldPrice: 'CHF 289', cat: 'Calçado', img: 'https://loja.eufacoparte.org/wp-content/uploads/2016/07/produto_tennis_01-433x516.png' },
];
// Fisher-Yates shuffle
function lojaShuffled(arr) {
const a = [...arr];
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
const t = a[i]; a[i] = a[j]; a[j] = t;
}
return a;
}
const LOJA_COUNT = 10; // itens por sessão
const LOJA_VISIBLE = 5; // cards visíveis ao mesmo tempo
const LOJA_DUR = 380; // ms da transição
// ---- Loja item modal ----
const LojaModal = ({ produto, onClose, onEncomenda }) => {
React.useEffect(() => {
const esc = e => { if (e.key === 'Escape') onClose(); };
document.addEventListener('keydown', esc);
document.body.style.overflow = 'hidden';
return () => {
document.removeEventListener('keydown', esc);
document.body.style.overflow = '';
};
}, [onClose]);
return (
e.stopPropagation()}>
×
{/* Esquerda: foto */}
{ e.currentTarget.style.display = 'none'; }} />
{/* Direita: detalhes */}
);
};
const Announce = () => {
// 10 itens aleatórios, estáveis durante a sessão
const produtos = React.useMemo(() => lojaShuffled(LOJA_ALL).slice(0, LOJA_COUNT), []);
const total = produtos.length;
// Track: 10 reais + 5 clones no final para loop infinito
const track = React.useMemo(() => [...produtos, ...produtos.slice(0, LOJA_VISIBLE)], [produtos]);
const [idx, setIdx] = React.useState(0);
const [anim, setAnim] = React.useState(true);
const [cardW, setCardW] = React.useState(0);
const [modalItem, setModalItem] = React.useState(null);
const [paused, setPaused] = React.useState(false);
const wrapRef = React.useRef(null);
// Mede a largura de cada card
React.useLayoutEffect(() => {
const update = () => {
if (wrapRef.current) setCardW(wrapRef.current.offsetWidth / LOJA_VISIBLE);
};
update();
const ro = new ResizeObserver(update);
if (wrapRef.current) ro.observe(wrapRef.current);
return () => ro.disconnect();
}, []);
const goto = React.useCallback((i, withAnim) => {
setAnim(withAnim);
setIdx(i);
}, []);
// Auto-avança a cada 4 segundos (pausa quando o modal está aberto ou hover)
React.useEffect(() => {
if (paused) return;
const iv = setInterval(() => {
setAnim(true);
setIdx(prev => {
const next = prev + 1;
if (next >= total) setTimeout(() => goto(0, false), LOJA_DUR + 16);
return next;
});
}, 4000);
return () => clearInterval(iv);
}, [total, goto, paused]);
return (
<>
✻ · Loja solidária
Consumo consciente e solidário.
Cada peça é um ato de solidariedade, 100% do valor vai diretamente para nossos projetos sociais.
Itens selecionados e enviados direto da nossa sede na Suíça 🇨🇭.
{/* Carousel */}
setPaused(true)}
onMouseLeave={() => setPaused(false)}
>
{track.map((p, i) => (
{ setModalItem(p); setPaused(true); }}
>
{ e.currentTarget.style.display = 'none'; }} />
{p.oldPrice &&
Promoção }
{p.cat}
{p.name}
{p.price || 'Consulte'}
{p.oldPrice && <> {p.oldPrice} >}
{p.price && Francos suíços }
))}
{modalItem && (
{ setModalItem(null); setPaused(false); }}
onEncomenda={(name) => { window.setLojaEncomenda?.(name); }}
/>
)}
>
);
};
// ---- Hero Slider ----
const HeroSlider = () => {
const slides = [
{ src: "images/iniciativa-surf-sagi.jpg", caption: "Surf Sagi · esporte transforma" },
{ src: "images/iniciativa-artesanato.jpg", caption: "Artesanato & Brinquedos · geração de renda" },
{ src: "images/iniciativa-sagi-vidas.jpg", caption: "Sagi Vidas · resgate animal" },
{ src: "images/iniciativa-sonhos-campo.png", caption: "Sonhos em Campo · esporte e inclusão" },
{ src: "images/iniciativa-juntos.png", caption: "Juntos nós Cuidamos · cuidado e comunidade" },
{ src: "images/iniciativa-anca.jpg", caption: "Abrigo ANCA & Educação Profissional" },
{ src: "images/iniciativa-roupas.jpg", caption: "Roupas & Memórias · moda circular" },
];
const [idx, setIdx] = React.useState(0);
React.useEffect(() => {
const id = setInterval(() => setIdx((i) => (i + 1) % slides.length), 5000);
return () => clearInterval(id);
}, []);
return (
{slides.map((s, i) =>
{e.currentTarget.style.display = 'none';}} />
)}
{slides[idx].caption}
setIdx((i) => (i - 1 + slides.length) % slides.length)}>
←
{slides.map((_, i) =>
setIdx(i)} />
)}
setIdx((i) => (i + 1) % slides.length)}>
→
);
};
window.Nav = Nav;
window.TranslationBanner = TranslationBanner;
window.Hero = Hero;
window.HeroSlider = HeroSlider;
window.Partners = Partners;
window.Announce = Announce;
window.HeartIcon = HeartIcon;