/* Components for Allsopp & Allsopp — Darren Murphy microsite.
   All components attach to window for global scope sharing. */

const { useState, useEffect, useRef, useMemo, useCallback } = React;

// ============================================================
// SVG icons — minimal stroke set
// ============================================================
const Icon = {
  Menu: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M3 6h18M3 12h18M3 18h18"/></svg>,
  X: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M6 6l12 12M18 6L6 18"/></svg>,
  Arrow: (p) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M5 12h14M13 6l6 6-6 6"/></svg>,
  Phone: (p) => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M22 16.92v3a2 2 0 01-2.18 2A19.79 19.79 0 013.07 4.18 2 2 0 015.06 2h3a2 2 0 012 1.72c.13.96.37 1.9.7 2.8a2 2 0 01-.45 2.11L9.09 9.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45c.9.33 1.84.57 2.8.7A2 2 0 0122 16.92z"/></svg>,
  WA: (p) => <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" {...p}><path d="M12 2C6.48 2 2 6.48 2 12c0 1.85.5 3.58 1.37 5.07L2 22l5.06-1.33A9.93 9.93 0 0012 22c5.52 0 10-4.48 10-10S17.52 2 12 2zm5.34 14.34c-.23.64-1.34 1.22-1.84 1.27-.5.05-.97.21-3.27-.69-2.77-1.09-4.55-3.93-4.69-4.12-.14-.19-1.12-1.49-1.12-2.84 0-1.35.71-2.02.96-2.29.25-.27.55-.34.73-.34h.52c.17 0 .39-.06.61.46.23.55.78 1.91.85 2.05.07.14.12.3.02.48-.09.18-.14.3-.28.46-.14.16-.3.36-.43.48-.14.14-.29.29-.13.57.16.27.71 1.18 1.53 1.91 1.06.94 1.95 1.23 2.23 1.37.28.14.44.12.6-.07.16-.19.69-.8.87-1.07.18-.27.36-.23.61-.14.25.09 1.59.75 1.86.89.27.14.46.21.52.32.07.11.07.66-.16 1.3z"/></svg>,
  Calendar: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg>,
  Star: (p) => <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" {...p}><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>,
  Check: (p) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" {...p}><path d="M20 6L9 17l-5-5"/></svg>,
  Bed: (p) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M2 18v-7a3 3 0 013-3h14a3 3 0 013 3v7M2 15h20M6 11V7a1 1 0 011-1h3a1 1 0 011 1v4"/></svg>,
  Bath: (p) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M4 12V6a2 2 0 012-2h2a2 2 0 012 2M2 12h20v3a4 4 0 01-4 4H6a4 4 0 01-4-4v-3zM6 21l-1 2M18 21l1 2"/></svg>,
  Ruler: (p) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M3 17L17 3l4 4L7 21l-4-4zM7 13l2 2M11 9l2 2M15 5l2 2"/></svg>,
  MapPin: (p) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z"/><circle cx="12" cy="10" r="3"/></svg>,
  Award: (p) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><circle cx="12" cy="8" r="6"/><path d="M8.5 13.5L7 22l5-3 5 3-1.5-8.5"/></svg>,
};
window.Icon = Icon;

// ============================================================
// Ampersand mark (extracted from logo SVG)
// ============================================================
function Ampersand({ size = 32, color = "currentColor" }) {
  return (
    <svg width={size} height={size * 0.92} viewBox="0 0 30 28" fill={color} xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
      <path d="M22.95 22.4c.08-.1.17-.21.26-.33.76-.96 1.89-2.25 3.08-3.21.59-.48 1.19-.88 1.72-1.14.27-.13.51-.22.74-.28.22-.06.41-.08.58-.08h.12v-4.1h-.12c-.82 0-1.59.17-2.3.43-1.25.46-2.34 1.17-3.31 1.96-1.43 1.16-2.62 2.49-3.5 3.56l-12.32-13.93C7.74 4.13 6.17 2.17 6.23-.21 6.23-3.14 8.51-5.67 12.04-5.74h8.14v-3.81h-8.18c-5.42 0-10.05 3.81-10.05 9.15 0 3.27 1.08 5.05 2.53 7.02l.84 1.12-3.73 3.39c-4.76 4.28-5.54 11.11-.96 16.17 4.94 5.41 13.85 3.69 17.76.42l2.47-2.14 3.85 4.4h5.72L22.96 22.4zM14.69 24.42c-2.71 2.5-8.67 3.51-11.92-.18-3.01-3.33-2.29-7.78.54-10.4l3.55-3.21 10.18 11.65-2.35 2.14z" transform="translate(-2 5)"/>
    </svg>
  );
}
window.Ampersand = Ampersand;

// ============================================================
// Brand logo (inline allsopp wordmark)
// ============================================================
function BrandMark({ color = "var(--navy)" }) {
  return (
    <img src="media/allsopp-logo.svg" alt="Allsopp & Allsopp" style={{ height: 22, width: "auto", display: "block", filter: color === "#fff" ? "brightness(0) invert(1)" : "none" }} />
  );
}
window.BrandMark = BrandMark;

// ============================================================
// Top navigation
// ============================================================
function TopNav({ t, lang, onLangToggle, onBook, dark = false }) {
  const [open, setOpen] = useState(false);
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 12);
    window.addEventListener('scroll', onScroll);
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return (
    <header className={`top-nav ${scrolled ? 'top-nav-scrolled' : ''}`}>
      <div className="nav-inner">
        <a href="#top" className="nav-logo" aria-label="Allsopp & Allsopp home">
          <BrandMark/>
        </a>
        <nav className="nav-links" aria-label="Primary">
          <a href="#about">{t.nav.agents}</a>
          <a href="#communities">{t.nav.areas}</a>
          <a href="#listings">{t.nav.offplan}</a>
          <a href="#press">{t.nav.about}</a>
        </nav>
        <div className="nav-actions">
          <button className="nav-lang" onClick={onLangToggle} aria-label="Toggle language">
            <span className="dot"/>{t.nav.lang}
          </button>
          <a href={`tel:${AGENT.phone}`} className="nav-icon-btn" aria-label="Call">
            <Icon.Phone/>
          </a>
          <button className="nav-cta" onClick={onBook}>
            <Icon.Calendar/><span>{t.nav.book}</span>
          </button>
          <button className="nav-burger" onClick={() => setOpen(true)} aria-label="Open menu"><Icon.Menu/></button>
        </div>
      </div>
      {open && (
        <div className="mobile-drawer" role="dialog">
          <div className="drawer-head">
            <BrandMark/>
            <button onClick={() => setOpen(false)} aria-label="Close menu"><Icon.X/></button>
          </div>
          <nav className="drawer-links">
            <a onClick={() => setOpen(false)} href="#about">{t.nav.agents}</a>
            <a onClick={() => setOpen(false)} href="#communities">{t.nav.areas}</a>
            <a onClick={() => setOpen(false)} href="#listings">{t.nav.offplan}</a>
            <a onClick={() => setOpen(false)} href="#press">{t.nav.about}</a>
          </nav>
          <div className="drawer-foot">
            <button className="nav-cta wide" onClick={() => { setOpen(false); onBook(); }}>
              <Icon.Calendar/><span>{t.nav.book}</span>
            </button>
            <button className="nav-lang wide" onClick={onLangToggle}>
              <span className="dot"/>{t.nav.lang}
            </button>
          </div>
        </div>
      )}
    </header>
  );
}
window.TopNav = TopNav;

// ============================================================
// Hero — 3 layout variants
// ============================================================
function Hero({ t, heroLayout, onBook }) {
  const eyebrow = (
    <div className="hero-eyebrow">
      <span className="eyebrow-line"/>
      <span>{t.heroEyebrow}</span>
    </div>
  );

  const stats = (
    <div className="hero-stats">
      <div><div className="stat-num">10<span>+</span></div><div className="stat-label">{t.statsLabel.years}</div></div>
      <div><div className="stat-num">6</div><div className="stat-label">{t.statsLabel.communities}</div></div>
      <div><div className="stat-num">2</div><div className="stat-label">{t.statsLabel.languages}</div></div>
      <div><div className="stat-num">&lt;1h</div><div className="stat-label">{t.statsLabel.response}</div></div>
    </div>
  );

  const ctas = (
    <div className="hero-ctas">
      <button className="btn btn-primary" onClick={onBook}><Icon.Calendar/><span>{t.cta1}</span></button>
      <a className="btn btn-ghost" href="#valuation"><span>{t.cta2}</span><Icon.Arrow/></a>
      <a className="btn btn-wa" href={`https://wa.me/${AGENT.whatsapp}?text=${encodeURIComponent("Hi Darren, I'd like to...")}`} target="_blank" rel="noreferrer"><Icon.WA/><span>{t.cta3}</span></a>
    </div>
  );

  if (heroLayout === "cinematic") {
    return (
      <section className="hero hero-cinematic" id="top">
        <div className="hero-cine-bg">
          <img src="media/agent-darren-murphy.webp" alt="Darren Murphy"/>
          <div className="hero-cine-grad"/>
        </div>
        <div className="hero-cine-content">
          {eyebrow}
          <h1 className="hero-headline">
            <span className="headline-soft">{t.heroPre}</span>
            <span className="headline-name">Darren Murphy.</span>
          </h1>
          <p className="hero-sub">{t.heroSub}</p>
          {ctas}
          <div className="hero-honour">
            <Icon.Award/>
            <div><strong>{AGENT.honour}</strong> · {AGENT.honourIssuer} 2025 <span className="muted">— {AGENT.honourNote.toLowerCase()}</span></div>
          </div>
        </div>
        <div className="hero-cine-stats">{stats}</div>
      </section>
    );
  }

  if (heroLayout === "magazine") {
    return (
      <section className="hero hero-magazine" id="top">
        <div className="mag-grid">
          <div className="mag-meta">
            {eyebrow}
            <div className="mag-runner">VOL. XVII · 2026 · DUBAI · ISSUE №1815</div>
          </div>
          <div className="mag-title">
            <div className="mag-pre">{t.heroPre}</div>
            <h1 className="mag-name">Darren<br/>Murphy</h1>
            <div className="mag-tagline">{AGENT.role}</div>
          </div>
          <div className="mag-portrait">
            <img src="media/agent-darren-murphy.webp" alt="Darren Murphy"/>
            <div className="mag-caption">— Portrait, Motor City Head Office, Dubai</div>
          </div>
          <div className="mag-side">
            <p className="hero-sub">{t.heroSub}</p>
            {ctas}
            <div className="hero-honour boxed">
              <Icon.Award/>
              <div><strong>{AGENT.honour}</strong><div className="muted">{AGENT.honourIssuer} 2025 · {AGENT.honourNote}</div></div>
            </div>
          </div>
        </div>
        <div className="mag-stats">{stats}</div>
      </section>
    );
  }

  // default: editorial split
  return (
    <section className="hero hero-editorial" id="top">
      <div className="hero-grid">
        <div className="hero-text">
          {eyebrow}
          <h1 className="hero-headline">
            <span className="headline-soft">{t.heroPre}</span>{" "}
            <span className="headline-name">Darren Murphy.</span>
          </h1>
          <p className="hero-sub">{t.heroSub}</p>
          {ctas}
          <div className="hero-honour">
            <Icon.Award/>
            <div><strong>{AGENT.honour}</strong> · {AGENT.honourIssuer} 2025 <span className="muted">— {AGENT.honourNote.toLowerCase()}</span></div>
          </div>
        </div>
        <div className="hero-portrait">
          <div className="portrait-wrap">
            <img src="media/agent-darren-murphy.webp" alt="Darren Murphy"/>
            <div className="portrait-badge">
              <Ampersand size={20} color="#fff"/>
              <div>
                <div className="pb-name">Darren Murphy</div>
                <div className="pb-role">{AGENT.role}</div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div className="hero-stats-wrap">{stats}</div>
    </section>
  );
}
window.Hero = Hero;

// ============================================================
// About / approach
// ============================================================
function About({ t }) {
  return (
    <section className="section about-section" id="about" data-screen-label="About Darren">
      <div className="container">
        <div className="about-grid">
          <div className="about-left">
            <div className="section-eyebrow"><span className="eyebrow-line"/>{t.aboutTitle}</div>
            <h2 className="section-h">A consultant, not a closer-of-deals.</h2>
            <p className="about-bio">{AGENT.bio}</p>
            <div className="about-meta">
              <div><div className="meta-k">RERA</div><div className="meta-v">{AGENT.brnNote}</div></div>
              <div><div className="meta-k">Languages</div><div className="meta-v">{AGENT.speaks.join(", ")}</div></div>
              <div><div className="meta-k">Office</div><div className="meta-v">Motor City HQ · JGE</div></div>
            </div>
          </div>
          <div className="about-right">
            {AGENT.approach.map((a, i) => (
              <div className="approach-card" key={i}>
                <div className="approach-num">0{i + 1}</div>
                <h3>{a.h}</h3>
                <p>{a.b}</p>
              </div>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}
window.About = About;

// ============================================================
// Listing card + grid (filterable)
// ============================================================
function ListingCard({ l, t }) {
  const statusLabel = l.status === "sale" ? t.forSale : l.status === "rent" ? t.toRent : t.offPlan;
  return (
    <article className="listing-card">
      <div className="card-media">
        <img src={l.image} alt={l.community} loading="lazy"/>
        <div className="card-sample">{t.sampleWatermark}</div>
        <div className="card-status">{statusLabel}</div>
      </div>
      <div className="card-body">
        <div className="card-loc"><Icon.MapPin/><span>{l.community}</span></div>
        <h3 className="card-title">{l.title}</h3>
        <div className="card-price">
          <span className="price-amt">{l.price}</span>
          {l.priceQualifier && l.priceQualifier !== "Asking" && <span className="price-q">· {l.priceQualifier}</span>}
        </div>
        <div className="card-specs">
          <span><Icon.Bed/>{l.beds} {t.bedsLabel}</span>
          <span><Icon.Bath/>{l.baths} {t.bathsLabel}</span>
          <span><Icon.Ruler/>{l.sizeSqft.toLocaleString()} {t.sqftLabel}</span>
        </div>
        <div className="card-tags">
          {l.tags.map((x, i) => <span className="card-tag" key={i}>{x}</span>)}
        </div>
        <div className="card-foot">
          <span className="card-ref">Ref. {l.ref}</span>
          <button className="card-cta">{t.nav.book}<Icon.Arrow/></button>
        </div>
      </div>
    </article>
  );
}

function ListingsGrid({ t }) {
  const [filter, setFilter] = useState("all");
  const filters = [
    { k: "all", l: t.filterAll },
    { k: "sale", l: t.filterSale },
    { k: "rent", l: t.filterRent },
    { k: "offplan", l: t.filterOffplan }
  ];
  const filtered = filter === "all" ? LISTINGS : LISTINGS.filter(l => l.status === filter);
  return (
    <section className="section listings-section" id="listings" data-screen-label="Listings">
      <div className="container">
        <div className="section-head">
          <div>
            <div className="section-eyebrow"><span className="eyebrow-line"/>{t.listingsTitle}</div>
            <h2 className="section-h">{filtered.length} {filtered.length === 1 ? 'property' : 'properties'} currently with Darren.</h2>
            <p className="section-sub">{t.listingsSub}</p>
          </div>
          <div className="filter-chips" role="tablist">
            {filters.map(f => (
              <button key={f.k} role="tab" aria-selected={filter === f.k} className={filter === f.k ? 'chip chip-active' : 'chip'} onClick={() => setFilter(f.k)}>{f.l}</button>
            ))}
          </div>
        </div>
        <div className="listings-grid">
          {filtered.map(l => <ListingCard key={l.ref} l={l} t={t}/>)}
        </div>
        <div className="feed-note">
          <span className="feed-dot"/>
          Production listings sync live from Strapi CMS → Property Finder, Bayut and dubizzle feeds. Demo cards above are non-published sample data.
        </div>
      </div>
    </section>
  );
}
window.ListingsGrid = ListingsGrid;

// ============================================================
// Communities
// ============================================================
function Communities({ t }) {
  const items = [
    { name: "Palm Jumeirah", img: "media/community-palm-jumeirah.webp", tag: "Waterfront luxury" },
    { name: "Downtown Dubai", img: "media/community-downtown.webp", tag: "Burj Khalifa district" },
    { name: "Dubai Hills Estate", img: "media/community-dubai-hills.webp", tag: "Family villas" },
    { name: "Business Bay", img: "media/community-business-bay.webp", tag: "Canal-side towers" },
    { name: "Arabian Ranches", img: "media/community-arabian-ranches.webp", tag: "Established community" },
    { name: "City Walk", img: "media/community-city-walk.webp", tag: "Urban resort" },
  ];
  return (
    <section className="section communities-section" id="communities" data-screen-label="Communities">
      <div className="container">
        <div className="section-eyebrow"><span className="eyebrow-line"/>{t.communitiesTitle}</div>
        <h2 className="section-h">{t.communitiesTitle}.</h2>
        <p className="section-sub">{t.communitiesSub}</p>
        <div className="communities-grid">
          {items.map((c, i) => (
            <a className="community-card" key={i} href="#listings">
              <div className="community-img"><img src={c.img} alt={c.name} loading="lazy"/></div>
              <div className="community-body">
                <div className="community-tag">{c.tag}</div>
                <div className="community-name">{c.name}</div>
                <div className="community-cta">View listings <Icon.Arrow/></div>
              </div>
            </a>
          ))}
        </div>
      </div>
    </section>
  );
}
window.Communities = Communities;

// ============================================================
// Awards strip
// ============================================================
function Press({ t }) {
  return (
    <section className="section press-section" id="press" data-screen-label="Awards">
      <div className="container">
        <div className="section-eyebrow"><span className="eyebrow-line"/>{t.pressTitle}</div>
        <h2 className="section-h">{t.pressTitle}.</h2>
        <p className="section-sub">{t.pressSub}</p>
        <div className="press-list">
          {PRESS.map((p, i) => (
            <div className="press-row" key={i}>
              <div className="press-year">{p.year}</div>
              <div className="press-title">{p.title}</div>
              <div className="press-issuer">{p.issuer}</div>
              <div className="press-note">{p.note}</div>
              <div className="press-verified"><Icon.Check/>Verified</div>
            </div>
          ))}
        </div>
        <div className="press-foot">
          Source attributions per <code>research/reviews-ratings.md</code>. Logo rights to be cleared with each issuer before public display.
        </div>
      </div>
    </section>
  );
}
window.Press = Press;

// ============================================================
// Testimonials
// ============================================================
function Testimonials({ t }) {
  return (
    <section className="section testimonials-section" data-screen-label="Testimonials">
      <div className="container">
        <div className="section-eyebrow"><span className="eyebrow-line"/>{t.testimonialsTitle}</div>
        <h2 className="section-h">{t.testimonialsTitle}.</h2>
        <p className="section-sub">{t.testimonialsSub}</p>
        <div className="testimonials-grid">
          {TESTIMONIALS.map((tm, i) => (
            <figure className="testimonial" key={i}>
              <div className="quote-mark">&ldquo;</div>
              <blockquote>{tm.q}</blockquote>
              <figcaption>
                <strong>{tm.name}</strong>
                <span className="muted">— {tm.detail}</span>
              </figcaption>
            </figure>
          ))}
        </div>
      </div>
    </section>
  );
}
window.Testimonials = Testimonials;

// ============================================================
// Book viewing modal (multi-step)
// ============================================================
function BookViewingModal({ open, onClose, t }) {
  const [step, setStep] = useState(1);
  const [form, setForm] = useState({ name: "", phone: "", email: "", property: "", date: "", time: "10:00", notes: "" });
  const [errors, setErrors] = useState({});
  const upd = (k, v) => setForm(f => ({ ...f, [k]: v }));

  useEffect(() => {
    if (!open) {
      setTimeout(() => { setStep(1); setForm({ name: "", phone: "", email: "", property: "", date: "", time: "10:00", notes: "" }); setErrors({}); }, 300);
    }
  }, [open]);

  useEffect(() => {
    document.body.style.overflow = open ? 'hidden' : '';
    return () => { document.body.style.overflow = ''; };
  }, [open]);

  const validate1 = () => {
    const e = {};
    if (!form.name.trim()) e.name = "Required";
    if (!form.phone.trim()) e.phone = "Required";
    if (!form.email.trim() || !form.email.includes('@')) e.email = "Valid email required";
    setErrors(e);
    return Object.keys(e).length === 0;
  };
  const validate2 = () => {
    const e = {};
    if (!form.property) e.property = "Pick a property";
    if (!form.date) e.date = "Pick a date";
    setErrors(e);
    return Object.keys(e).length === 0;
  };

  if (!open) return null;
  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()} role="dialog" aria-modal="true">
        <button className="modal-close" onClick={onClose} aria-label="Close"><Icon.X/></button>
        <div className="modal-left">
          <img src="media/agent-darren-murphy.webp" alt="Darren Murphy"/>
          <div className="modal-left-card">
            <Ampersand size={22} color="#fff"/>
            <div className="ml-name">Darren Murphy</div>
            <div className="ml-role">{AGENT.role}</div>
            <div className="ml-honour"><Icon.Award/>{AGENT.honour} · {AGENT.honourIssuer} 2025</div>
            <div className="ml-divider"/>
            <div className="ml-row"><Icon.Phone/><span>+971 4 429 4444</span></div>
            <div className="ml-row"><Icon.WA/><span>wa.me/97144294444</span></div>
            <div className="ml-row"><Icon.MapPin/><span>Motor City, Dubai</span></div>
          </div>
        </div>
        <div className="modal-right">
          {step <= 2 && (
            <div className="modal-step-indicator">
              <span className={step >= 1 ? 'on' : ''}>01 <em>Your details</em></span>
              <span className={step >= 2 ? 'on' : ''}>02 <em>Property & time</em></span>
              <span>03 <em>Confirm</em></span>
            </div>
          )}
          {step === 1 && (
            <>
              <h3 className="modal-h">{t.bookTitle}</h3>
              <p className="modal-sub">{t.bookSub}</p>
              <div className="form-grid">
                <label className="field">
                  <span>Full name</span>
                  <input type="text" value={form.name} onChange={e => upd('name', e.target.value)} aria-invalid={!!errors.name}/>
                  {errors.name && <em className="err">{errors.name}</em>}
                </label>
                <label className="field">
                  <span>Phone (intl. format)</span>
                  <input type="tel" placeholder="+971 5… or +44 7…" value={form.phone} onChange={e => upd('phone', e.target.value)} aria-invalid={!!errors.phone}/>
                  {errors.phone && <em className="err">{errors.phone}</em>}
                </label>
                <label className="field field-full">
                  <span>Email</span>
                  <input type="email" value={form.email} onChange={e => upd('email', e.target.value)} aria-invalid={!!errors.email}/>
                  {errors.email && <em className="err">{errors.email}</em>}
                </label>
              </div>
              <input type="text" name="_gotcha" style={{display:'none'}}/>
              <div className="modal-actions">
                <a className="btn btn-wa" href={`https://wa.me/${AGENT.whatsapp}`} target="_blank" rel="noreferrer"><Icon.WA/>WhatsApp instead</a>
                <button className="btn btn-primary" onClick={() => validate1() && setStep(2)}>Continue<Icon.Arrow/></button>
              </div>
            </>
          )}
          {step === 2 && (
            <>
              <h3 className="modal-h">Pick a property and a time.</h3>
              <p className="modal-sub">Darren confirms every appointment by phone — you'll never get a silent calendar invite.</p>
              <div className="form-grid">
                <label className="field field-full">
                  <span>Property</span>
                  <select value={form.property} onChange={e => upd('property', e.target.value)} aria-invalid={!!errors.property}>
                    <option value="">— select one —</option>
                    {LISTINGS.map(l => <option key={l.ref} value={l.ref}>{l.title} · {l.community} ({l.ref})</option>)}
                    <option value="other">Something else — I'll explain</option>
                  </select>
                  {errors.property && <em className="err">{errors.property}</em>}
                </label>
                <label className="field">
                  <span>Preferred date</span>
                  <input type="date" value={form.date} onChange={e => upd('date', e.target.value)} aria-invalid={!!errors.date}/>
                  {errors.date && <em className="err">{errors.date}</em>}
                </label>
                <label className="field">
                  <span>Time</span>
                  <select value={form.time} onChange={e => upd('time', e.target.value)}>
                    {["09:00","10:00","11:00","12:00","14:00","15:00","16:00","17:00","18:00"].map(x => <option key={x}>{x}</option>)}
                  </select>
                </label>
                <label className="field field-full">
                  <span>Notes (optional)</span>
                  <textarea rows="3" value={form.notes} onChange={e => upd('notes', e.target.value)} placeholder="Cash buyer, 60-day completion, etc."></textarea>
                </label>
              </div>
              <div className="modal-actions">
                <button className="btn btn-ghost" onClick={() => setStep(1)}>Back</button>
                <button className="btn btn-primary" onClick={() => validate2() && setStep(3)}>Request viewing<Icon.Arrow/></button>
              </div>
            </>
          )}
          {step === 3 && (
            <div className="modal-success">
              <div className="success-tick"><Icon.Check/></div>
              <h3 className="modal-h">Request received.</h3>
              <p className="modal-sub">Darren will call <strong>{form.phone || "your number"}</strong> within the hour during working hours. You'll also get a confirmation at <strong>{form.email}</strong>.</p>
              <div className="success-card">
                <div className="sc-row"><span>Property</span><strong>{LISTINGS.find(l => l.ref === form.property)?.title || form.property || "—"}</strong></div>
                <div className="sc-row"><span>When</span><strong>{form.date || "—"} · {form.time}</strong></div>
                <div className="sc-row"><span>Agent</span><strong>Darren Murphy</strong></div>
                <div className="sc-row"><span>Reference</span><strong>VW-{Math.random().toString(36).slice(2,8).toUpperCase()}</strong></div>
              </div>
              <p className="muted small">Demo flow — production submits to Formspree/Netlify + mirrors to the CRM webhook so the lead lands in Darren's pipeline.</p>
              <div className="modal-actions">
                <button className="btn btn-ghost" onClick={onClose}>Close</button>
                <a className="btn btn-wa" href={`https://wa.me/${AGENT.whatsapp}`} target="_blank" rel="noreferrer"><Icon.WA/>Message Darren now</a>
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
window.BookViewingModal = BookViewingModal;

// ============================================================
// Valuation block (inline strip)
// ============================================================
function ValuationStrip({ t, onBook }) {
  const [v, setV] = useState({ type: "Apartment", area: "", beds: "2" });
  const [sent, setSent] = useState(false);
  return (
    <section className="section val-section" id="valuation">
      <div className="container">
        <div className="val-card">
          <div className="val-left">
            <div className="section-eyebrow light"><span className="eyebrow-line"/>Free valuation</div>
            <h2 className="val-h">Thinking of selling or letting?</h2>
            <p className="val-sub">A RERA-registered consultant who actually knows your community will come back with a realistic range — no bots, no guesswork, no instant-quote nonsense.</p>
            <ul className="val-list">
              <li><Icon.Check/>Comparable evidence from the last 90 days</li>
              <li><Icon.Check/>Marketing plan + photography spec</li>
              <li><Icon.Check/>Honest "list or wait" recommendation</li>
            </ul>
          </div>
          <div className="val-right">
            {!sent ? (
              <>
                <div className="val-form">
                  <label className="field"><span>Property type</span>
                    <select value={v.type} onChange={e => setV({...v, type: e.target.value})}>
                      <option>Apartment</option><option>Villa</option><option>Townhouse</option><option>Commercial</option>
                    </select>
                  </label>
                  <label className="field"><span>Community / tower</span>
                    <input type="text" placeholder="e.g. Burj Vista" value={v.area} onChange={e => setV({...v, area: e.target.value})}/>
                  </label>
                  <label className="field"><span>Bedrooms</span>
                    <select value={v.beds} onChange={e => setV({...v, beds: e.target.value})}>
                      <option>Studio</option><option>1</option><option>2</option><option>3</option><option>4</option><option>5+</option>
                    </select>
                  </label>
                </div>
                <button className="btn btn-primary wide" onClick={() => setSent(true)}>
                  Request my valuation<Icon.Arrow/>
                </button>
                <p className="muted small">We'll come back with a realistic range — never a machine-generated figure.</p>
              </>
            ) : (
              <div className="val-success">
                <div className="success-tick"><Icon.Check/></div>
                <h3>Thanks — Darren has it.</h3>
                <p>Expect a call within the hour. In the meantime, <a href={`https://wa.me/${AGENT.whatsapp}`} target="_blank" rel="noreferrer">WhatsApp him directly</a> if it's urgent.</p>
                <button className="btn btn-ghost" onClick={() => setSent(false)}>Submit another</button>
              </div>
            )}
          </div>
        </div>
      </div>
    </section>
  );
}
window.ValuationStrip = ValuationStrip;

// ============================================================
// WhatsApp FAB
// ============================================================
function WhatsAppFab() {
  const [hint, setHint] = useState(false);
  useEffect(() => {
    const t = setTimeout(() => setHint(true), 3500);
    const t2 = setTimeout(() => setHint(false), 9000);
    return () => { clearTimeout(t); clearTimeout(t2); };
  }, []);
  return (
    <a className="wa-fab" href={`https://wa.me/${AGENT.whatsapp}?text=${encodeURIComponent("Hi Darren, I'd like to...")}`} target="_blank" rel="noreferrer" aria-label="WhatsApp Darren">
      <Icon.WA/>
      {hint && <span className="wa-hint">Message Darren on WhatsApp</span>}
    </a>
  );
}
window.WhatsAppFab = WhatsAppFab;

// ============================================================
// Sticky mobile bottom bar
// ============================================================
function StickyBar({ t, onBook }) {
  return (
    <div className="sticky-bar">
      <a className="sb-btn" href={`tel:${AGENT.phone}`}><Icon.Phone/><span>{t.nav.call}</span></a>
      <a className="sb-btn sb-wa" href={`https://wa.me/${AGENT.whatsapp}`} target="_blank" rel="noreferrer"><Icon.WA/><span>{t.nav.whatsapp}</span></a>
      <button className="sb-btn sb-book" onClick={onBook}><Icon.Calendar/><span>{t.nav.book}</span></button>
    </div>
  );
}
window.StickyBar = StickyBar;

// ============================================================
// Footer
// ============================================================
function Footer({ t }) {
  return (
    <footer className="footer">
      <div className="container">
        <div className="footer-grid">
          <div className="footer-brand">
            <BrandMark color="#fff"/>
            <p className="footer-tag">A traditional UK estate-agency model, built for Dubai. In Dubai since 2008.</p>
            <div className="footer-social">
              <a href="#" aria-label="Instagram">IG</a>
              <a href="#" aria-label="Facebook">FB</a>
              <a href="#" aria-label="LinkedIn">LI</a>
              <a href="#" aria-label="YouTube">YT</a>
              <a href="#" aria-label="X">X</a>
            </div>
          </div>
          <div className="footer-col">
            <h4>Services</h4>
            <a>Residential sales</a><a>Lettings</a><a>Commercial</a><a>Off-plan</a><a>Property management</a><a>Mortgages</a><a>Private Office</a>
          </div>
          <div className="footer-col">
            <h4>Offices</h4>
            <div className="office">
              <strong>Head Office — Motor City</strong>
              <span>Control Tower, 30th Floor, Motor City, Dubai</span>
              <span>PO Box 55720</span>
            </div>
            <div className="office">
              <strong>Branch — Jumeirah Golf Estates</strong>
              <span>Unit 8, The Fairway Mall</span>
            </div>
            <div className="office muted-block">
              <strong>Business Bay / Vision Tower (26th)</strong>
              <span className="muted">Verified on portals — confirming before public publish.</span>
            </div>
          </div>
          <div className="footer-col">
            <h4>Talk to us</h4>
            <a href={`tel:${AGENT.phone}`}>+971 4 429 4444</a>
            <a href={`https://wa.me/${AGENT.whatsapp}`} target="_blank" rel="noreferrer">WhatsApp · wa.me/97144294444</a>
            <span className="muted small">Mon–Fri 9am–5pm (confirm)</span>
            <span className="muted small">Public email — confirm before publish</span>
          </div>
        </div>
        <div className="footer-legal">
          <span>{t.footerLegal}</span>
          <span className="muted">© 2026 Allsopp & Allsopp Real Estate Broker · Microsite demo for agent Darren Murphy</span>
        </div>
      </div>
    </footer>
  );
}
window.Footer = Footer;
