const { useState, useEffect, useRef } = React; /* ------------ Icons (minimal, line) ------------ */ const IconPhone = () => ( ); const IconMail = () => ( ); const IconPin = () => ( ); const IconClock = () => ( ); const IconArrow = () => ( ); const IconInstagram = () => ( ); /* ------------ Tweak defaults ------------ */ const TWEAK_DEFAULS = /*EDITMODE-BEGIN*/{ "accent": "red" }/*EDITMODE-END*/; const ACCENTS = { red: { hex: "#C8102E", soft: "#8A1523", label: "Red" }, muted: { hex: "#8F2A2A", soft: "#5E1A1A", label: "Muted" }, orange: { hex: "#E25822", soft: "#9A3A12", label: "Orange" } }; /* ------------ Reveal on scroll ------------ */ function useReveal() { useEffect(() => { const els = document.querySelectorAll(".reveal"); const io = new IntersectionObserver((entries) => { entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); } }); }, { threshold: 0.12 }); els.forEach(el => io.observe(el)); return () => io.disconnect(); }); } /* ------------ Nav ------------ */ function Nav({ data }) { return ( ); } /* ------------ Hero ------------ */ function Hero({ data }) { return (

Onde a tua Moto ganha alma.

{data.hero.subtitle}

{data.hero.ctaPrimary.label} {data.hero.ctaSecondary.label}
Dom Serafim Custom House
); } /* ------------ About ------------ */ function About({ data }) { return (
{data.about.kicker}

Uma oficina, um ofício.

{data.about.body.map((p, i) =>

{p}

)}
{data.about.stats.map((s, i) => (
{s.value}
{s.label}
))}
); } /* ------------ Services ------------ */ function Services({ data }) { return (
{data.services.kicker}

O que fazemos dentro do armazém.

{data.services.items.map((s, i) => (
[ {s.code} ]

{s.title}

{s.body}

))}
); } /* ------------ Contact ------------ */ function Contact({ data }) { const todayIdx = (new Date().getDay() + 6) % 7; // 0 = Segunda return (
{data.contact.kicker}

Passa pelo armazém.

{data.contact.subtitle}

Telefone {data.contact.phone} i Chamada para rede móvel nacional
Morada
{data.contact.address.line1}
{data.contact.address.line2}
{(data.socials || []).filter(s => s.name === "Instagram").map((s, i) => (
Instagram {s.handle}
))}
Horário
{data.hours.map((h, i) => (
{h.day}{i === todayIdx ? " · Hoje" : ""} {h.time}
))}
Sintra · PT
Abrir no Maps
); } /* ------------ Footer ------------ */ function Footer({ data }) { const ig = (data.socials || []).find(s => s.name === "Instagram"); return ( ); } /* ------------ App ------------ */ function App() { const [data, setData] = useState(null); const [tw, setTw] = (window.useTweaks ? window.useTweaks(TWEAK_DEFAULS) : useState(TWEAK_DEFAULS)); // load JSON (try fetch; if sandbox blocks it, fall back to embedded data) useEffect(() => { fetch("content.json") .then(r => r.json()) .then(setData) .catch(() => { if (window.__FALLBACK_DATA__) setData(window.__FALLBACK_DATA__); }); }, []); // apply accent CSS var useEffect(() => { const a = ACCENTS[tw.accent] || ACCENTS.red; document.documentElement.style.setProperty("--accent", a.hex); document.documentElement.style.setProperty("--accent-soft", a.soft); }, [tw.accent]); useReveal(); if (!data) { return (
Loading · Dom Serafim
); } const Tweaks = window.TweaksPanel; const TweakSection = window.TweakSection; const TweakRadio = window.TweakRadio; return (