// Nav + Hero components function Nav({ t, lang, setLang }) { const [scrolled, setScrolled] = React.useState(false); const [menuOpen, setMenuOpen] = React.useState(false); React.useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 24); onScroll(); window.addEventListener('scroll', onScroll, { passive: true }); return () => window.removeEventListener('scroll', onScroll); }, []); // Lock body scroll when menu open React.useEffect(() => { document.body.style.overflow = menuOpen ? 'hidden' : ''; return () => { document.body.style.overflow = ''; }; }, [menuOpen]); const closeMenu = () => setMenuOpen(false); return (
sendar
); } // Hero backgrounds — abstract architectural gradients (no real photos) const HERO_BGS = [ { bg: `linear-gradient(180deg, #a8b5bd 0%, #5d6971 22%, #2b3138 55%, #0e1013 100%), radial-gradient(ellipse at 30% 90%, rgba(0,0,0,0.55) 0%, transparent 60%)`, accent: 'rgba(240,217,166,0.25)', }, { bg: `linear-gradient(200deg, #d6b985 0%, #7a6142 40%, #2c231a 80%, #0f0c08 100%)`, accent: 'rgba(255,210,150,0.35)', }, { bg: `linear-gradient(170deg, #2d3c45 0%, #1a2329 50%, #09110f 100%), radial-gradient(circle at 70% 20%, rgba(240,217,166,0.1) 0%, transparent 55%)`, accent: 'rgba(240,217,166,0.2)', }, ]; // Architectural skyline as stacked rectangles that rise on load. // Position / size set so they look like towers viewed from below. const SKYLINE = [ { x: 0, w: 180, h: 720, delay: 0.15, tilt: -0.4 }, { x: 180, w: 120, h: 820, delay: 0.05, tilt: -0.3 }, { x: 300, w: 90, h: 600, delay: 0.25, tilt: -0.25 }, { x: 960, w: 140, h: 680, delay: 0.10, tilt: 0.3 }, { x:1100, w: 170, h: 860, delay: 0.00, tilt: 0.5 }, { x:1270, w: 170, h: 740, delay: 0.20, tilt: 0.4 }, ]; function Hero({ t, cycle, sendStyle = 'broadcast' }) { const [idx, setIdx] = React.useState(0); const [mounted, setMounted] = React.useState(false); const bgRef = React.useRef(null); const contentRef = React.useRef(null); const skylineRef = React.useRef(null); React.useEffect(() => { const id = requestAnimationFrame(() => setMounted(true)); return () => cancelAnimationFrame(id); }, []); // Cycle backgrounds React.useEffect(() => { if (!cycle) return; const id = setInterval(() => setIdx((i) => (i + 1) % HERO_BGS.length), 7000); return () => clearInterval(id); }, [cycle]); // Parallax on scroll React.useEffect(() => { let ticking = false; const onScroll = () => { if (ticking) return; ticking = true; requestAnimationFrame(() => { const y = window.scrollY; if (bgRef.current) bgRef.current.style.transform = `translate3d(0, ${y * 0.35}px, 0) scale(1.05)`; if (skylineRef.current) skylineRef.current.style.transform = `translate3d(0, ${y * 0.55}px, 0)`; if (contentRef.current) { contentRef.current.style.transform = `translate3d(0, ${y * 0.18}px, 0)`; contentRef.current.style.opacity = String(Math.max(0, 1 - y / 600)); } ticking = false; }); }; onScroll(); window.addEventListener('scroll', onScroll, { passive: true }); return () => window.removeEventListener('scroll', onScroll); }, []); return (
{HERO_BGS.map((b, i) => (
))}
{/* Animated architectural skyline */}
{SKYLINE.map((s, i) => ( {/* Window grid overlay */} {/* Vertical accents — thin cream lines suggesting glazing */} {Array.from({ length: Math.floor(s.w / 22) }).map((_, j) => ( ))} {/* Top edge highlight */} ))}

{sendStyle === 'broadcast' && } {sendStyle === 'paperplane' && } {sendStyle === 'signal' && } {t('hero.title1')} {t('hero.title2')}

{t('hero.subtitle')}

{HERO_BGS.map((_, i) => (
{t('hero.scrollHint')}
); } Object.assign(window, { Nav, Hero, SendBroadcast, SendPaperplane, SendSignal }); // ———————————————————————————————————————————————————— // "Sending" reveal animations — one-shot: they play on mount // to reveal the word "sendar", then settle. NOT ambient background motion. function splitLetters(text) { return text.split('').map((ch, i) => ( {ch === ' ' ? '\u00A0' : ch} )); } function SendBroadcast({ text }) { // Each letter arrives like a received transmission: a ring ping expands // around the letter slot as the letter materializes. Left-to-right. return ( {splitLetters(text)} ); } function SendPaperplane({ text }) { // A paper plane flies in from the left trailing a dashed line; as it passes // each letter position, that letter drops into place from above. Plane exits right. return ( {splitLetters(text)} ); } function SendSignal({ text }) { // A radar sweep crosses the word left-to-right; letters reveal in its wake // like a signal sweeping across a screen. return ( {splitLetters(text)} ); }