// components.jsx — chrome (nav, hero, footer, fab, modal) + register-interest form. // Loaded BEFORE sections.jsx so window globals share a render order. const { useState, useEffect, useRef, useMemo } = React; // ─── Logo SVG (inline so we can recolor via currentColor / fill-override) ── window.LogoSVG = function LogoSVG() { // Inline logo from media/logo-dandb-main.svg. Fills are overridden via CSS by parent class. return ( ); }; // Simple inline SVG copy of logo to allow CSS fill override on path[fill] window.LogoInline = function LogoInline() { // CSS-masked monochrome lockup so it inherits currentColor cleanly on dark + light surfaces. return ( ); }; // ─── Nav ──────────────────────────────────────────────────────────── window.Nav = function Nav({ locale, setLocale, dark, onOpenRegister, onOpenLocale, localeOpen }) { const L = window.LOCALES[locale]; return (
{window.PROJECT.codename} · {window.PROJECT.name}
); }; // ─── Locale menu ─────────────────────────────────────────────────── window.LocaleMenu = function LocaleMenu({ open, locale, setLocale, onClose }) { if (!open) return null; const codes = ["en", "ar", "de", "ru", "zh"]; return (
e.stopPropagation()} style={{ background: "var(--paper)", border: "1px solid var(--line)", padding: 24, width: 280, borderRadius: 2, }} >
Language
{codes.map((c) => ( ))}

Matches the corporate site's five-language set (EN / AR / RU / ZH / DE). AR mirrors via dir="rtl".

); }; // ─── Hero ────────────────────────────────────────────────────────── window.Hero = function Hero({ L, variant, onOpenRegister, accent }) { return (
D&B Properties · Bayari Holding RERA ORN 16576 · verified Template demo · no live prices
{window.PROJECT.codename} · {L.hero.eyebrow}
{variant === "split" ? (

{window.renderTokens(L.hero.title)}

{L.hero.sub}

) : (

{window.renderTokens(L.hero.title)}

{L.hero.sub}

)}
Location
Palm Jebel Ali
Completion
Q4 2027
Payment
60 / 40
Residences
1 – 4 BR + PH
); }; // ─── Register Interest form (in-page CTA section + modal) ───────── window.RegisterForm = function RegisterForm({ L, compact }) { const [step, setStep] = useState(1); const [submitted, setSubmitted] = useState(false); const [form, setForm] = useState({ name: "", phone: "", email: "", unit: ["2-bedroom"], budget: "", notes: "", consent: false, }); const [errors, setErrors] = useState({}); function toggleUnit(u) { const has = form.unit.includes(u); setForm({ ...form, unit: has ? form.unit.filter((x) => x !== u) : [...form.unit, u] }); } function validateStep1() { const e = {}; if (!form.name.trim()) e.name = "Required"; if (!form.phone.trim()) e.phone = "Required"; else if (!/^[\d\s+()-]{7,}$/.test(form.phone)) e.phone = "Looks short — include country code"; if (!form.email.trim()) e.email = "Required"; else if (!/^[^@]+@[^@]+\.[^@]+$/.test(form.email)) e.email = "Invalid email"; setErrors(e); return Object.keys(e).length === 0; } function submit() { if (!form.consent) { setErrors({ ...errors, consent: "Please confirm" }); return; } // honeypot 'website' field would be checked here in prod setSubmitted(true); // demo: log goal console.info("[goal] lead_register", { ...form, source: "marsa-cove", locale: window.__LOCALE }); } if (submitted) { return (
Lead received · queued to off-plan team

Thanks, {form.name.split(" ")[0] || "we'll be in touch"}.

A senior off-plan consultant will be in touch within one working day with the developer's full deck, the 60/40 payment plan, current availability and any remaining inventory tiers. Direct from the source — no bots, no invented prices.

Continue on WhatsApp
); } return (
Step {step} of 2 · {step === 1 ? "About you" : "Your interest"} = 1 ? "is-active" : ""} ${step > 1 ? "is-done" : ""}`}> = 2 ? "is-active" : ""}`}>

{step === 1 ? Start your enquiry : What are you looking for?}

{/* honeypot */} {step === 1 && (
Name *
setForm({ ...form, name: e.target.value })} placeholder="Your full name" /> {errors.name &&
{errors.name}
}
Phone *
setForm({ ...form, phone: e.target.value })} placeholder="+971 …" /> {errors.phone &&
{errors.phone}
}
Email *
setForm({ ...form, email: e.target.value })} placeholder="you@…" /> {errors.email &&
{errors.email}
}
We never call without permission. RERA registered — ORN 16576.
)} {step === 2 && (
Unit type interest *
{["1-bedroom", "2-bedroom", "3-bedroom", "Townhouse", "Duplex", "Penthouse"].map((u) => ( ))}
Budget band (optional — for us to filter)
Anything else?
{errors.consent &&
{errors.consent}
}
Goal: {L.cta.goal} · Lead routed to off-plan CRM queue.
)}
); }; // ─── CTA section (full-bleed Register Interest) ─────────────────── window.CTASection = function CTASection({ L }) { return (
{L.cta.eyebrow}

{window.renderTokens(L.cta.title)}

{L.cta.body}

    {[ ["Developer-direct payment plan", "No middleman, no marked-up tiers."], ["RERA-registered consultant", "ORN 16576 · verified on PropertyFinder broker profile."], ["End-to-end multilingual support", "EN · AR · DE · RU · ZH from enquiry through handover."], ["Re-sale exit thinking, day one", "Modelled against community absorption and listing data."], ].map(([t, s], i) => (
  • {t}
    {s}
  • ))}
); }; // ─── Modal (mini register form) ─────────────────────────────────── window.RegisterModal = function RegisterModal({ open, onClose, L }) { useEffect(() => { function onKey(e) { if (e.key === "Escape") onClose(); } window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [onClose]); return (
e.stopPropagation()} style={{ position: "relative" }}>
{window.PROJECT.codename} · Register Interest
); }; // ─── WhatsApp FAB ────────────────────────────────────────────────── window.WhatsAppFAB = function WhatsAppFAB({ L, show }) { if (!show) return null; return ( console.info("[goal] whatsapp_click")} > W {L.waFab.sub} {L.waFab.main} ); }; // ─── Footer ──────────────────────────────────────────────────────── window.Footer = function Footer({ L }) { return ( ); };