// Cozmo Yachts — main App const { useState: useStateA, useEffect: useEffectA, useMemo: useMemoA } = React; const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "palette": "marine-amber", "heroHeadline": "Your private yacht on the Dubai coastline.", "displayFont": "Cormorant Garamond", "showPromos": true }/*EDITMODE-END*/; const PALETTES = { "marine-amber": { label: "Marine + Amber", "--noir": "#0A1622", "--ink": "#16212B", "--paper": "#F7FAFB", "--sand": "#EFE9DC", "--marine": "#11507A", "--sun": "#E8A317", "--muted": "#5B6B78", "--line": "#DCE3E8", }, "midnight": { label: "Deep midnight", "--noir": "#050D17", "--ink": "#0A1A29", "--paper": "#F4F6F9", "--sand": "#E6E9EE", "--marine": "#0E3E64", "--sun": "#D89B1E", "--muted": "#5A6878", "--line": "#D8DCE2", }, "warm-sand": { label: "Warm sand", "--noir": "#1A1812", "--ink": "#2A2419", "--paper": "#FAF6EE", "--sand": "#EFE4CC", "--marine": "#7C5D2B", "--sun": "#D88B14", "--muted": "#6B6151", "--line": "#E0D6BD", }, }; const FONTS = ["Cormorant Garamond", "EB Garamond", "Playfair Display"]; function buildWAMessage({ yacht, date, time, guests, duration, topic }) { const lines = ["Hi Cozmo Yachts,"]; if (topic) { lines.push("", `I'd like to enquire about: ${topic}.`); } else if (yacht) { lines.push("", `I'd like to enquire about chartering the ${yacht.name}${yacht.sub ? ` (${yacht.sub})` : ""}.`); } else { lines.push("", "I'd like to enquire about a charter."); } if (date) lines.push("", `Date: ${new Date(date).toLocaleDateString('en-GB', { weekday: 'short', day: 'numeric', month: 'short', year: 'numeric' })}`); if (time) lines.push(`Departure: ${time}`); if (guests) lines.push(`Guests: ${guests}`); if (duration) lines.push(`Duration: ${duration}`); lines.push("", "Could you confirm availability and share an indicative quote? Thanks."); return lines.join("\n"); } function App() { const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); // Apply palette CSS vars useEffectA(() => { const p = PALETTES[t.palette] || PALETTES["marine-amber"]; Object.entries(p).forEach(([k, v]) => { if (k.startsWith("--")) document.documentElement.style.setProperty(k, v); }); }, [t.palette]); useEffectA(() => { document.documentElement.style.setProperty("--serif", `"${t.displayFont}", "Cormorant Garamond", Georgia, serif`); // ensure font is loaded if (!document.getElementById(`gf-${t.displayFont}`)) { const link = document.createElement("link"); link.id = `gf-${t.displayFont}`; link.rel = "stylesheet"; const fam = t.displayFont.replace(/ /g, "+"); link.href = `https://fonts.googleapis.com/css2?family=${fam}:ital,wght@0,300;0,400;0,500;1,400&display=swap`; document.head.appendChild(link); } }, [t.displayFont]); const [scrolled, setScrolled] = useStateA(false); const [lang, setLang] = useStateA("EN"); const [heroIdx, setHeroIdx] = useStateA(0); const [shortlist, setShortlist] = useStateA([]); const [toast, setToast] = useStateA(null); const [modal, setModal] = useStateA(null); useEffectA(() => { const onScroll = () => setScrolled(window.scrollY > 80); window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); useEffectA(() => { if (!toast) return; const id = setTimeout(() => setToast(null), 2400); return () => clearTimeout(id); }, [toast]); function handleFavorite(yacht) { setShortlist(prev => { if (prev.includes(yacht.slug)) { setToast(`Removed ${yacht.name} from shortlist`); return prev.filter(s => s !== yacht.slug); } else { setToast(`${yacht.name} added to shortlist`); return [...prev, yacht.slug]; } }); } function handleEnquire(yachtOrTopic) { setModal({ kind: "enquiry", yacht: yachtOrTopic }); } function handleAvailabilitySubmit(payload) { setModal({ kind: "availability", payload }); } function handleCallWhatsApp({ topic }) { setModal({ kind: "enquiry", topic }); } function handleShortlistClick() { const yachts = FLEET.filter(y => shortlist.includes(y.slug)); setModal({ kind: "shortlist", yachts }); } return (
We'll pre-fill the details below. Edit anything before you send.
> ); body = ( <>Confirm your enquiry and we'll match you to vessels available for these dates.
> ); body = ( <>{yachts.length} vessel{yachts.length === 1 ? "" : "s"} ready to compare.
> ); body = ( <>