// Layout.jsx — Header, Footer, QuoteBar, ContactModal function Header({ onContactClick }) { const { path, navigate } = useRouter(); const [scrolled, setScrolled] = React.useState(false); const [mobileOpen, setMobileOpen] = React.useState(false); React.useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 8); onScroll(); window.addEventListener('scroll', onScroll, { passive: true }); return () => window.removeEventListener('scroll', onScroll); }, []); React.useEffect(() => { setMobileOpen(false); }, [path]); const links = [ { to: '/', label: 'Home' }, { to: '/services', label: 'Services' }, { to: '/about', label: 'About' }, { to: '/blog', label: 'Blog' }, { to: '/contact', label: 'Contact' }, ]; const isActive = (to) => to === '/' ? path === '/' : path === to || path.startsWith(to + '/'); return (
CloudWise
{mobileOpen && (
{links.map(l => ( {l.label} ))}
)}
); } function Footer() { const cols = [ { title: 'Services', links: SERVICES.map(s => ({ label: s.title, to: '/services/' + s.slug })) }, { title: 'Company', links: [ { label: 'About us', to: '/about' }, { label: 'Blog', to: '/blog' }, { label: 'Contact', to: '/contact' }, ]}, ]; return ( ); } function QuoteBar({ onClick }) { const [show, setShow] = React.useState(false); React.useEffect(() => { const onScroll = () => setShow(window.scrollY > 400); onScroll(); window.addEventListener('scroll', onScroll, { passive: true }); return () => window.removeEventListener('scroll', onScroll); }, []); return ( ); } function ContactModal({ open, onClose }) { const [submitted, setSubmitted] = React.useState(false); const [submitting, setSubmitting] = React.useState(false); const [error, setError] = React.useState(null); React.useEffect(() => { if (!open) { setSubmitted(false); setError(null); } if (open) { const onKey = (e) => { if (e.key === 'Escape') onClose(); }; window.addEventListener('keydown', onKey); document.body.style.overflow = 'hidden'; return () => { window.removeEventListener('keydown', onKey); document.body.style.overflow = ''; }; } }, [open]); if (!open) return null; const handleSubmit = async (e) => { e.preventDefault(); setSubmitting(true); setError(null); try { await submitToFormspree(new FormData(e.target)); setSubmitted(true); } catch { setError('Something went wrong. Please try again or call us directly.'); } finally { setSubmitting(false); } }; return (
e.stopPropagation()} style={{ background: '#fff', borderRadius: 'var(--radius-2xl)', maxWidth: 520, width: '100%', padding: 36, boxShadow: 'var(--shadow-xl)', position: 'relative', maxHeight: '90vh', overflow: 'auto', }}> {submitted ? (

Thanks — we'll be in touch.

One of our team will reply within one business day. In the meantime, feel free to call us on +350 225 02143.

) : ( <>
Get a free quote

Tell us about your business.

No obligation — we'll review your needs and reply with a clear, costed proposal.