// 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 (
D&B Properties · Bayari HoldingRERA ORN 16576 · verifiedTemplate 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.
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) => (