// Albanna Conwood — bilingual single-page (EN / AR)
// LangContext switches html dir+lang, persists choice, provides t() helper.

const { useEffect, useRef, useState, useContext, createContext } = React;
const ABC = window.AC_DATA;
const Ic = window.Icon;

// ---------- Language ----------
const LangContext = createContext({ lang: "en", setLang: () => {} });
const useLang = () => useContext(LangContext);
const t = (val, lang) => window.AC_T(val, lang);

const LangProvider = ({ children }) => {
  const [lang, setLangState] = useState(() => {
    try {
      const q = new URLSearchParams(window.location.search).get("lang");
      if (q === "en" || q === "ar") return q;
      const stored = localStorage.getItem("ac_lang");
      if (stored === "en" || stored === "ar") return stored;
      if (typeof navigator !== "undefined" && navigator.language && navigator.language.toLowerCase().startsWith("ar")) return "ar";
    } catch (e) {}
    return "en";
  });
  useEffect(() => {
    document.documentElement.lang = lang;
    document.documentElement.dir = lang === "ar" ? "rtl" : "ltr";
    document.documentElement.dataset.lang = lang;
    try { localStorage.setItem("ac_lang", lang); } catch (e) {}
  }, [lang]);
  const setLang = (l) => setLangState(l);
  return <LangContext.Provider value={{ lang, setLang }}>{children}</LangContext.Provider>;
};

// ---------- Reveal (singleton observer + variants + --d delay) ----------
const acRevealObserver = (() => {
  if (typeof IntersectionObserver === "undefined") return null;
  const map = new Map();
  const obs = new IntersectionObserver((entries) => {
    entries.forEach((e) => {
      if (e.isIntersecting) {
        const cb = map.get(e.target);
        if (cb) cb();
        obs.unobserve(e.target);
        map.delete(e.target);
      }
    });
  }, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" });
  return {
    observe(el, cb) { map.set(el, cb); obs.observe(el); },
    unobserve(el) { obs.unobserve(el); map.delete(el); },
  };
})();

const Reveal = ({ children, delay = 0, variant = "up", as: As = "div", className = "", style, ...rest }) => {
  const ref = useRef(null);
  const [shown, setShown] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (!acRevealObserver) { setShown(true); return; }
    acRevealObserver.observe(el, () => setShown(true));
    // Fail-open: if the observer misses an element already in view, reveal it
    // anyway — but leave below-the-fold content to the observer so the
    // scroll-reveal still plays as the user reaches it.
    const fallback = setTimeout(() => {
      const vh = window.innerHeight || document.documentElement.clientHeight;
      if (el.getBoundingClientRect().top < vh) setShown(true);
    }, 1200 + delay);
    return () => { acRevealObserver.unobserve(el); clearTimeout(fallback); };
  }, []);
  const mergedStyle = delay ? { ...(style || {}), "--d": `${delay}ms` } : style;
  return (
    <As ref={ref} style={mergedStyle} className={`reveal reveal--${variant} ${shown ? "in" : ""} ${className}`} {...rest}>
      {children}
    </As>
  );
};

// ---------- Scroll hooks ----------
const useScrolled = (threshold = 24) => {
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const cb = () => setScrolled(window.scrollY > threshold);
    window.addEventListener("scroll", cb, { passive: true });
    cb();
    return () => window.removeEventListener("scroll", cb);
  }, []);
  return scrolled;
};

const useScrollProgress = () => {
  const [p, setP] = useState(0);
  useEffect(() => {
    const cb = () => {
      const h = document.documentElement;
      const max = h.scrollHeight - h.clientHeight;
      setP(max > 0 ? Math.min(1, h.scrollTop / max) : 0);
    };
    window.addEventListener("scroll", cb, { passive: true }); cb();
    return () => window.removeEventListener("scroll", cb);
  }, []);
  return p;
};

// True while the viewport is still over the full-bleed hero.
const useOverHero = () => {
  const [over, setOver] = useState(true);
  useEffect(() => {
    let raf = 0;
    const compute = () => {
      raf = 0;
      const hero = document.getElementById("top");
      const h = hero ? hero.offsetHeight : window.innerHeight;
      setOver(window.scrollY < h - 90);
    };
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(compute); };
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll, { passive: true });
    compute();
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      if (raf) cancelAnimationFrame(raf);
    };
  }, []);
  return over;
};

const useScrollSpy = (ids) => {
  const [active, setActive] = useState("");
  useEffect(() => {
    const offset = 110;
    const cb = () => {
      const y = window.scrollY + offset;
      let cur = "";
      for (const id of ids) {
        const el = document.getElementById(id);
        if (el && el.offsetTop <= y) cur = id;
      }
      setActive(cur);
    };
    window.addEventListener("scroll", cb, { passive: true });
    cb();
    return () => window.removeEventListener("scroll", cb);
  }, []);
  return active;
};

// rAF-throttled, passive, reduced-motion aware parallax. Writes --py on the node.
const useParallax = (strength = 0.12) => {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const reduce = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduce) return;
    let raf = 0;
    const update = () => {
      raf = 0;
      const rect = el.getBoundingClientRect();
      const vh = window.innerHeight || 1;
      const center = rect.top + rect.height / 2;
      const prog = (center - vh / 2) / (vh / 2 + rect.height / 2);
      const y = -prog * strength * rect.height;
      el.style.setProperty("--py", y.toFixed(1) + "px");
    };
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(update); };
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll, { passive: true });
    update();
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      if (raf) cancelAnimationFrame(raf);
    };
  }, [strength]);
  return ref;
};

// Fires once when the element first enters the viewport.
const useInView = (threshold = 0.35) => {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (typeof IntersectionObserver === "undefined") { setInView(true); return; }
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) { setInView(true); io.disconnect(); }
      });
    }, { threshold });
    io.observe(el);
    // Fail-open: if the band is already in view but the observer misses it,
    // run the count-up anyway; below-the-fold stays for the observer.
    const fallback = setTimeout(() => {
      const vh = window.innerHeight || document.documentElement.clientHeight;
      if (el.getBoundingClientRect().top < vh) setInView(true);
    }, 1800);
    return () => { io.disconnect(); clearTimeout(fallback); };
  }, [threshold]);
  return [ref, inView];
};

// Count-up that holds at 0 until it is in view, then animates once.
const useCountUpInView = (target, duration, delay, inView) => {
  const [value, setValue] = useState(0);
  const done = useRef(false);
  useEffect(() => {
    if (!inView || done.current) return;
    done.current = true;
    let raf;
    const tid = setTimeout(() => {
      const t0 = performance.now();
      const tick = (now) => {
        const p = Math.min((now - t0) / duration, 1);
        const eased = 1 - Math.pow(1 - p, 3);
        setValue(Math.round(eased * target));
        if (p < 1) raf = requestAnimationFrame(tick);
      };
      raf = requestAnimationFrame(tick);
    }, delay);
    return () => { clearTimeout(tid); cancelAnimationFrame(raf); };
  }, [inView, target, duration, delay]);
  return value;
};

// ---------- Top bar ----------
const LangToggle = () => {
  const { lang, setLang } = useLang();
  return (
    <div className="lang-toggle" role="group" aria-label="Language">
      <button
        className={lang === "en" ? "active" : ""}
        onClick={() => setLang("en")}
        aria-pressed={lang === "en"}
        lang="en"
      >EN</button>
      <span className="lang-toggle__sep" aria-hidden="true">·</span>
      <button
        className={lang === "ar" ? "active" : ""}
        onClick={() => setLang("ar")}
        aria-pressed={lang === "ar"}
        lang="ar"
      >AR</button>
    </div>
  );
};

const ContactPill = () => {
  const { lang } = useLang();
  const isHome = typeof window !== "undefined"
    && !window.location.pathname.includes("client-guide")
    && !window.location.pathname.includes("the-practice")
    && !window.location.pathname.includes("survey");
  if (!isHome) return null;
  return (
    <a href="#contact" className="contact-pill">
      <span className="contact-pill__dot" aria-hidden="true" />
      <span className="contact-pill__txt">{t(ABC.UI.pill, lang)}</span>
      <span className="contact-pill__arrow" aria-hidden="true" />
    </a>
  );
};

const ProgressBar = () => {
  const p = useScrollProgress();
  return <div className="cg-progress" style={{ transform: `scaleX(${p})` }} aria-hidden="true" />;
};

const TopBar = () => {
  const { lang } = useLang();
  const scrolled = useScrolled();
  const over = useOverHero();
  const [menuOpen, setMenuOpen] = useState(false);
  const closeMenu = () => setMenuOpen(false);
  return (
    <header className={`topbar${scrolled ? " topbar--scrolled" : ""}${over ? " topbar--over" : ""}${menuOpen ? " topbar--menu" : ""}`}>
      <div className="topbar__inner">
        <a className="topbar__brand" href="/" aria-label="Albanna Conwood">
          <img className="brand-logo brand-logo--color" src={lang === "ar" ? "assets/logo-ar-color.png?v=23" : "assets/logo-en-color.png?v=23"} alt="Albanna Conwood Construction L.L.C — Since 1981" />
          <img className="brand-logo brand-logo--white" src={lang === "ar" ? "assets/logo-ar-white.png?v=23" : "assets/logo-en-white.png?v=23"} alt="" aria-hidden="true" />
          <img className="brand-logo brand-logo--mark" src="assets/logo-mark.png?v=23" alt="" aria-hidden="true" />
          <img className="brand-logo brand-logo--mark-white" src="assets/logo-mark-white.png?v=23" alt="" aria-hidden="true" />
        </a>
        <nav className={`topbar__nav${menuOpen ? " is-open" : ""}`} aria-label="Page navigation">
          <a href="/the-practice.html" onClick={closeMenu}>{lang === "ar" ? "منهجنا" : "The Practice"}</a>
          <a href="/client-guide.html" onClick={closeMenu}>{lang === "ar" ? "دليل المالك" : "Client Guide"}</a>
        </nav>
        <div className="topbar__actions">
          <LangToggle />
          <ContactPill />
          <button
            type="button"
            className="topbar__burger"
            aria-label={lang === "ar" ? "القائمة" : "Menu"}
            aria-expanded={menuOpen}
            onClick={() => setMenuOpen((o) => !o)}
          >
            <span /><span /><span />
          </button>
        </div>
      </div>
      <div className="topbar__scrim" aria-hidden="true" onClick={closeMenu} />
    </header>
  );
};

// ---------- Cycling word in hero headline ----------
const HeroCycle = () => {
  const words = ["once.", "well."];
  const [cur, setCur] = useState(0);
  const [prev, setPrev] = useState(null);
  useEffect(() => {
    let intervalId;
    const t = setTimeout(() => {
      intervalId = setInterval(() => {
        setCur(c => {
          setPrev(c);
          return (c + 1) % words.length;
        });
      }, 3000);
    }, 2200);
    return () => { clearTimeout(t); clearInterval(intervalId); };
  }, []);
  return (
    <span className="hero__cycle">
      {words.map((w, i) => (
        <span
          key={w}
          className={`hero__word it${i === cur ? " hero__word--active" : i === prev ? " hero__word--out" : ""}`}
        >{w}</span>
      ))}
    </span>
  );
};

// ---------- Hero (cinematic, full-bleed) ----------
const Hero = () => {
  const { lang } = useLang();
  const [heroIn, setHeroIn] = useState(false);
  const bgRef = useParallax(0.12);
  const heroRef = useRef(null);
  useEffect(() => {
    const id = requestAnimationFrame(() => setHeroIn(true));
    return () => cancelAnimationFrame(id);
  }, []);
  return (
    <section className="hero" id="top" ref={heroRef}>
      <div className="hero__bg" ref={bgRef}>
        <img className="hero__img" src="assets/photos/hero-dubai-bw.jpg" alt="" />
      </div>
      <div className="hero__scrim" aria-hidden="true" />

      <div className={`hero__content${heroIn ? " is-in" : ""}`}>
        <div className="hero__eyebrow" style={{ "--d": "120ms" }}>
          <Ic name="rosette" size={20} color="currentColor" />
          <span>{t(ABC.UI.eyebrow_maker, lang)}</span>
        </div>
        {lang === "ar" ? (
          <h1 className="hero__title hero__title--ar" lang="ar" dir="rtl">
            <span className="hero__line" style={{ "--d": "240ms" }}>
              <span className="hero__line-i">نبني <span className="it">للأجيال.</span></span>
            </span>
          </h1>
        ) : (
          <h1 className="hero__title">
            <span className="hero__line" style={{ "--d": "240ms" }}>
              <span className="hero__line-i">Built <HeroCycle /></span>
            </span>
          </h1>
        )}
      </div>

      <div className={`hero__foot${heroIn ? " is-in" : ""}`}>
        <a href="#services" className="hero__scroll" style={{ "--d": "820ms" }}>
          <span>{t(ABC.UI.hero_scroll, lang)}</span>
          <span className="hero__scroll-line" aria-hidden="true"><span /></span>
        </a>
      </div>
    </section>
  );
};

// ---------- Capability marquee ----------
const Marquee = () => {
  const { lang } = useLang();
  const items = ABC.MARQUEE || [];
  const row = [...items, ...items];
  return (
    <div className="marquee" aria-hidden="true">
      <div className="marquee__track">
        {row.map((m, i) => (
          <span className="marquee__item" key={i}>
            <span className="marquee__txt">{t(m, lang)}</span>
            <span className="marquee__dot" />
          </span>
        ))}
      </div>
    </div>
  );
};

// ---------- Stats band (dark, over interior) ----------
const BandStat = ({ s, delay, lang }) => {
  const [ref, inView] = useInView(0.4);
  const target = parseInt(s.num, 10);
  const value = useCountUpInView(target, 1500, delay, inView);
  const sufVal = s.suf && (typeof s.suf === "object" ? t(s.suf, lang) : s.suf);
  const isAr = lang === "ar";
  const isPct = sufVal === "%";
  // Bilingual suf objects contain Arabic text (e.g. "من كل 3") — needs its own class
  const isArText = isAr && typeof s.suf === "object";
  return (
    <div className="statsband__cell" ref={ref}>
      {/* dir="rtl" on the num span keeps Arabic suffix text flowing correctly
          (e.g. "1 من كل 3" → 1 anchors right, Arabic text extends left).
          For %, we prefix it in AR so it sits to the left of the digits. */}
      <span className="bandstat__num" dir={isAr ? "rtl" : undefined}>
        {isAr && isPct
          ? <><span className="plus plus--pct">%</span>{value}</>
          : <>{value}{sufVal && <span className={`plus${isPct ? " plus--pct" : isArText ? " plus--ar" : ""}`}>{sufVal}</span>}</>
        }
      </span>
      <span className="bandstat__lbl">{t(s.lbl, lang)}</span>
    </div>
  );
};

const StatsBand = () => {
  const { lang } = useLang();
  const bgRef = useParallax(0.1);
  return (
    <section className="statsband" id="stats">
      <div className="statsband__bg" ref={bgRef}>
        <video
          src="assets/video/dubai-timelapse.mp4?v=2"
          poster="assets/photos/hero-dubai-aerial.png"
          autoPlay
          loop
          muted
          playsInline
          aria-hidden="true"
        />
      </div>
      <div className="statsband__scrim" aria-hidden="true" />
      <div className="statsband__inner">
        <Reveal className="statsband__head">
          <span className="section-eyebrow section-eyebrow--light"><span className="rule" /><span>{t(ABC.UI.stats_eyebrow, lang)}</span></span>
          <p className="statsband__lede">{t(ABC.UI.stats_lede, lang)}</p>
        </Reveal>
        <div className="statsband__grid">
          {ABC.STATS.map((s, i) => (
            <BandStat key={i} s={s} delay={i * 90} lang={lang} />
          ))}
        </div>
      </div>
    </section>
  );
};

// ---------- Service Icons (Loro Piana–style line art) ----------
const ServiceIcon = ({ type }) => {
  const K = "#1a1918";
  const E = "#37857d";
  const lw = { fill: "none", stroke: K, strokeWidth: 0.65, strokeLinecap: "round", strokeLinejoin: "round" };
  const lt = { fill: "none", stroke: K, strokeWidth: 0.38, strokeLinecap: "round", strokeLinejoin: "round" };
  const le = { fill: "none", stroke: E, strokeWidth: 0.5,  strokeLinecap: "round", strokeLinejoin: "round" };
  const sv = { width: "100%", height: "100%", display: "block" };

  /* 01 — Luxury Villa */
  if (type === "villa") return (
    <svg viewBox="0 0 200 140" preserveAspectRatio="xMidYMid meet" style={sv}>
      <line x1="22" y1="118" x2="178" y2="118" {...lt} />
      <rect x="62" y="121" width="76" height="5" {...lt} />
      <line x1="68" y1="123.5" x2="132" y2="123.5" {...le} />
      <rect x="36" y="108" width="128" height="6" {...lw} />
      <rect x="52" y="62" width="96" height="46" {...lw} />
      <polyline points="32,62 100,22 168,62" {...lw} />
      <path d="M 72,62 Q 100,46 128,62" {...lt} strokeDasharray="1.8 2.2" />
      <line x1="32" y1="62" x2="168" y2="62" {...lt} />
      {[65, 80, 100, 120, 135].map(x => (
        <React.Fragment key={x}>
          <line x1={x} y1="62" x2={x} y2="108" {...lt} />
          <line x1={x-3} y1="63" x2={x+3} y2="63" {...lt} strokeWidth={0.3} />
          <line x1={x-3} y1="107" x2={x+3} y2="107" {...lt} strokeWidth={0.3} />
        </React.Fragment>
      ))}
      <path d="M 88,108 L 88,94 A 12,14,0,0,1,112,94 L 112,108" {...lw} />
      <rect x="55" y="72" width="16" height="13" {...lt} />
      <line x1="63" y1="72" x2="63" y2="85" {...lt} strokeWidth={0.28} />
      <rect x="129" y="72" width="16" height="13" {...lt} />
      <line x1="137" y1="72" x2="137" y2="85" {...lt} strokeWidth={0.28} />
    </svg>
  );

  /* 02 — Commercial Building */
  if (type === "building") return (
    <svg viewBox="0 0 200 140" preserveAspectRatio="xMidYMid meet" style={sv}>
      <line x1="18" y1="118" x2="182" y2="118" {...lt} />
      <rect x="36" y="12" width="128" height="106" {...lw} />
      <line x1="30" y1="12" x2="170" y2="12" {...lw} />
      <line x1="26" y1="8"  x2="174" y2="8"  {...lt} />
      <rect x="36" y="12" width="10" height="106" {...lt} strokeWidth={0.3} />
      <rect x="154" y="12" width="10" height="106" {...lt} strokeWidth={0.3} />
      {[36, 57, 78, 99].map(y => (
        <line key={y} x1="36" y1={y} x2="164" y2={y} {...lt} />
      ))}
      {[69, 100, 131].map(x => (
        <line key={x} x1={x} y1="12" x2={x} y2="118" {...lt} />
      ))}
      {[16, 40, 61, 82].map(y =>
        [44, 75, 106, 137].map(x => (
          <rect key={`${x}${y}`} x={x} y={y} width={14} height={14} {...lt} />
        ))
      )}
      <path d="M 82,118 L 82,106 Q 100,97 118,106 L 118,118" {...lw} />
      <line x1="36" y1="12" x2="164" y2="12" {...le} />
    </svg>
  );

  /* 03 — Warehouse */
  if (type === "warehouse") return (
    <svg viewBox="0 0 200 140" preserveAspectRatio="xMidYMid meet" style={sv}>
      <line x1="8" y1="114" x2="192" y2="114" {...lw} />
      <rect x="12" y="54" width="176" height="60" {...lw} />
      <polyline points="8,54 100,22 192,54" {...lw} />
      <line x1="12" y1="54" x2="188" y2="54" {...lt} />
      <line x1="100" y1="22" x2="100" y2="54" {...lt} strokeWidth={0.28} />
      {[36, 62, 138, 164].map((x,i) => (
        <line key={i} x1={x} y1={54} x2={100} y2={22} {...lt} strokeWidth={0.28} />
      ))}
      <rect x="20" y="70" width="66" height="44" {...lw} />
      <line x1="20" y1="86" x2="86" y2="86" {...lt} />
      <line x1="20" y1="100" x2="86" y2="100" {...lt} />
      <line x1="53" y1="70" x2="53" y2="114" {...lt} strokeWidth={0.28} />
      <rect x="114" y="70" width="66" height="44" {...lw} />
      <line x1="114" y1="86" x2="180" y2="86" {...lt} />
      <line x1="114" y1="100" x2="180" y2="100" {...lt} />
      <line x1="147" y1="70" x2="147" y2="114" {...lt} strokeWidth={0.28} />
      <line x1="86" y1="60" x2="114" y2="60" {...lt} strokeWidth={0.28} />
      <line x1="86" y1="68" x2="114" y2="68" {...lt} strokeWidth={0.28} />
      <rect x="86" y="28" width="28" height="12" fill={E} fillOpacity="0.15" stroke={E} strokeWidth="0.45" />
    </svg>
  );

  /* 04 — Specialized Works (marble slab with veining) */
  if (type === "craft") return (
    <svg viewBox="0 0 200 140" preserveAspectRatio="xMidYMid meet" style={sv}>
      <rect x="22" y="10" width="156" height="120" {...lw} />
      <rect x="28" y="16" width="144" height="108" {...lt} />
      <polygon points="22,10 66,10 22,54" fill={E} fillOpacity="0.1" stroke={E} strokeWidth="0.4" />
      <polygon points="178,130 134,130 178,86" fill={E} fillOpacity="0.08" stroke={E} strokeWidth="0.35" />
      <path d="M 22,46 C 75,42 115,88 178,80" stroke={E} strokeWidth="1.1" fill="none" strokeLinecap="round" />
      <path d="M 22,50 C 75,46 115,92 178,84" stroke={K} strokeWidth="0.32" fill="none" strokeLinecap="round" />
      <path d="M 22,88 C 60,84 138,110 178,104" stroke={E} strokeWidth="0.55" fill="none" strokeLinecap="round" />
      <path d="M 100,10 C 94,34 106,52 96,80" stroke={K} strokeWidth="0.3" fill="none" strokeLinecap="round" />
      <path d="M 96,52 C 110,58 120,56 136,62" stroke={K} strokeWidth="0.26" fill="none" strokeLinecap="round" />
    </svg>
  );

  return null;
};

// ---------- What We Do ----------
const SERVICE_ICON_TYPES = { "01": "villa", "02": "building", "03": "warehouse", "04": "craft" };

const WhatWeDo = () => {
  const { lang } = useLang();
  return (
    <section id="services" className="services-section">
      <div className="section-head">
        <Reveal className="section-eyebrow"><span className="rule" /><span>{t(ABC.UI.services_eyebrow, lang)}</span></Reveal>
        <Reveal as="h2" className="section-title" delay={80}>{t(ABC.UI.services_title_a, lang)}<span className="it">{t(ABC.UI.services_title_em, lang)}</span></Reveal>

      </div>
      <div className="discipline-grid">
        {ABC.SERVICES.map((s, i) => (
          <Reveal key={s.num} className="discipline" delay={i * 70}>
            <div className="discipline__media discipline__media--icon">
              <ServiceIcon type={SERVICE_ICON_TYPES[s.num]} />
            </div>
            <div className="discipline__top">
              <span className="discipline__num">{s.num}</span>
              <span className="discipline__tag">{t(s.tag, lang)}</span>
            </div>
            <div className="discipline__content">
              <h3 className="discipline__title">{t(s.title, lang)}</h3>
              <p className="discipline__body">{t(s.body, lang)}</p>
            </div>
          </Reveal>
        ))}
      </div>
    </section>
  );
};

// ---------- Selected Work (photography) ----------
const SelectedWork = () => {
  const { lang } = useLang();
  return (
    <section id="work" className="work-section">
      <div className="section-head">
        <Reveal className="section-eyebrow"><span className="rule" /><span>{t(ABC.UI.work_eyebrow, lang)}</span></Reveal>
        <Reveal as="h2" className="section-title" delay={80}>{t(ABC.UI.work_title_a, lang)}<span className="it">{t(ABC.UI.work_title_em, lang)}</span></Reveal>
        <Reveal as="p" className="section-sub work-note" delay={160}>{t(ABC.UI.work_note, lang)}</Reveal>
      </div>
      <div className="work-grid">
        {ABC.PROJECTS.map((p, i) => (
          <Reveal key={p.slug} as="article" className="pcard" variant="up" delay={(i % 3) * 80}>
            <div className="pcard__media"><img src={`${p.img}?v=63`} alt={t(p.location, lang)} loading="lazy" /></div>
            <div className="pcard__body">
              <span className={`pcard__status${p.inProgress ? " is-active" : ""}`}>{t(p.status, lang)}</span>
              <dl className="pcard__stats">
                {p.size && (
                  <div className="pcard__stat">
                    <dt>{t(ABC.UI.work_size, lang)}</dt>
                    <dd>{t(p.size, lang)}</dd>
                  </div>
                )}
                <div className="pcard__stat">
                  <dt>{t(ABC.UI.work_config, lang)}</dt>
                  <dd>{t(p.config, lang)}</dd>
                </div>
              </dl>
            </div>
          </Reveal>
        ))}
      </div>
    </section>
  );
};


// ---------- Inline quote highlighter ----------
const HlQuote = ({ text, hl }) => {
  if (!hl) return <>{text}</>;
  const i = text.indexOf(hl);
  if (i === -1) return <>{text}</>;
  return (
    <>
      {text.slice(0, i)}
      <mark className="confidence__hl">{text.slice(i, i + hl.length)}</mark>
      {text.slice(i + hl.length)}
    </>
  );
};

// ---------- Confidence (testimonial gallery — auto-advancing) ----------
const useReducedMotion = () => {
  const [reduce, setReduce] = useState(false);
  useEffect(() => {
    if (!window.matchMedia) return;
    const m = window.matchMedia("(prefers-reduced-motion: reduce)");
    const on = () => setReduce(!!m.matches);
    on();
    if (m.addEventListener) m.addEventListener("change", on);
    else if (m.addListener) m.addListener(on);
    return () => {
      if (m.removeEventListener) m.removeEventListener("change", on);
      else if (m.removeListener) m.removeListener(on);
    };
  }, []);
  return reduce;
};
const Chevron = () => (
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <path d="M15 5 L8 12 L15 19" />
  </svg>
);
const PauseIcon = () => (
  <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><rect x="6" y="5" width="4" height="14" rx="1" /><rect x="14" y="5" width="4" height="14" rx="1" /></svg>
);
const PlayIcon = () => (
  <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M7 5 L19 12 L7 19 Z" /></svg>
);

const Confidence = () => {
  const { lang } = useLang();
  const isAr = lang === "ar";
  const items = ABC.TESTIMONIALS;
  const n = items.length;
  const reduce = useReducedMotion();
  const [idx, setIdx] = useState(0);
  const [hover, setHover] = useState(false);
  const [kbFocus, setKbFocus] = useState(false);
  const [playing, setPlaying] = useState(true);
  const autoplay = !reduce;
  const stagePaused = hover || kbFocus;
  const running = autoplay && playing && !stagePaused;
  const touchX = useRef(null);
  const DURATION = 7000;

  const go = (i) => setIdx(((i % n) + n) % n);
  const prev = () => go(idx - 1);
  const next = () => go(idx + 1);

  useEffect(() => {
    if (!running || n < 2) return;
    const id = setTimeout(() => setIdx((i) => (i + 1) % n), DURATION);
    return () => clearTimeout(id);
  }, [idx, running, n]);

  const onTouchStart = (e) => { touchX.current = e.touches[0].clientX; };
  const onTouchEnd = (e) => {
    if (touchX.current == null) return;
    const dx = e.changedTouches[0].clientX - touchX.current;
    touchX.current = null;
    if (Math.abs(dx) > 44) (dx < 0 ? (isAr ? prev : next) : (isAr ? next : prev))();
  };

  return (
    <section className="confidence" id="confidence">
      <div className="confidence__inner">
        <Reveal className="section-eyebrow">
          <span className="rule" />
          <span>{t(ABC.UI.confidence_eyebrow, lang)}</span>
        </Reveal>

        <div
          className={`cf-stage${stagePaused ? " is-paused" : ""}`}
          onMouseEnter={() => setHover(true)}
          onMouseLeave={() => setHover(false)}
          onFocusCapture={(e) => { try { if (e.target.matches && e.target.matches(":focus-visible")) setKbFocus(true); } catch (_) {} }}
          onBlurCapture={() => setKbFocus(false)}
        >
          <span className="cf-glyph" aria-hidden="true">&ldquo;</span>

          <div className="cf-viewport" dir="ltr" onTouchStart={onTouchStart} onTouchEnd={onTouchEnd}>
            <div className="cf-track" style={{ transform: `translateX(${isAr ? idx * 100 : -idx * 100}%)` }}>
              {items.map((q, i) => (
                <figure className="cf-slide" key={i} aria-hidden={i !== idx}>
                  <blockquote className="cf-quote" dir="ltr" lang="en">
                    <HlQuote text={t(q.quote, "en")} hl={t(q.highlight, "en")} />
                  </blockquote>
                  <figcaption className="cf-attrib" dir={isAr ? "rtl" : "ltr"} lang={isAr ? "ar" : "en"}>
                    <span className="cf-attrib__text">
                      {(() => {
                        const full = t(q.attrib, lang);
                        const idx2 = full.indexOf(' · ');
                        if (idx2 === -1) return full;
                        return (<>
                          <span className="cf-attrib__name">{full.slice(0, idx2)}</span>
                          <span className="cf-attrib__sep" aria-hidden="true"> · </span>
                          <span className="cf-attrib__loc">{full.slice(idx2 + 3)}</span>
                        </>);
                      })()}
                    </span>
                  </figcaption>
                </figure>
              ))}
            </div>
          </div>

          <div className="cf-controls">
            <button className="cf-arrow" onClick={prev} aria-label={isAr ? "السابق" : "Previous"} type="button">
              <Chevron />
            </button>
            <div className="cf-dots">
              <span className="cf-count" aria-hidden="true">
                <b>{String(idx + 1).padStart(2, "0")}</b> / {String(n).padStart(2, "0")}
              </span>
              {items.map((_, i) => (
                <button
                  key={i}
                  className={`cf-dot${i === idx ? " is-active" : ""}`}
                  onClick={() => go(i)}
                  aria-label={`${isAr ? "شهادة" : "Testimonial"} ${i + 1}`}
                  aria-current={i === idx}
                  type="button"
                >
                  {i === idx && autoplay && playing && <span key={idx} className="cf-dot__fill" />}
                </button>
              ))}
              {autoplay && (
                <button
                  className="cf-play"
                  onClick={() => setPlaying((p) => !p)}
                  aria-label={playing ? (isAr ? "إيقاف العرض" : "Pause") : (isAr ? "تشغيل العرض" : "Play")}
                  aria-pressed={!playing}
                  type="button"
                >
                  {playing ? <PauseIcon /> : <PlayIcon />}
                </button>
              )}
            </div>
            <button className="cf-arrow" onClick={next} aria-label={isAr ? "التالي" : "Next"} type="button">
              <span style={{ transform: "scaleX(-1)", display: "inline-flex" }}><Chevron /></span>
            </button>
          </div>
        </div>
      </div>
    </section>
  );
};

// ---------- Practice ----------
const Practice = () => {
  const { lang } = useLang();
  const lede = t(ABC.UI.practice_lede, lang);
  return (
    <section className="practice" id="practice">
      <div className="practice__head">
        <Reveal className="section-eyebrow practice__eyebrow-span">
          <span className="rule" />
          <span>{t(ABC.UI.practice_eyebrow, lang)}</span>
        </Reveal>
        <Reveal as="p" className="about-opening" delay={100}>
          {lede.lead}<span className="em">{lede.em}</span>{lede.tail}
        </Reveal>
      </div>
      <div className="values-wrap">
        <div className="values">
          {ABC.VALUES.map((v, i) => (
            <Reveal key={v.title} className="value" delay={i * 80}>
              <span className="value__icon"><Ic name={v.icon} size={34} stroke={1} color="var(--emerald)" /></span>
              <h3 className="value__title">
                {lang === "ar"
                  ? <span className="value__ar" lang="ar" dir="rtl">{v.titleAr}</span>
                  : <span>{v.title}</span>}
              </h3>
              <p className="value__gloss">{t(v.gloss, lang)}</p>
              <p className="value__body">{t(v.body, lang)}</p>
            </Reveal>
          ))}
        </div>
      </div>
    </section>
  );
};

// ---------- Approach animated icons ----------
const ApproachIcon = ({ n }) => {
  const base = { viewBox:"0 0 48 48", fill:"none", stroke:"currentColor", strokeWidth:"1.6", strokeLinecap:"round", strokeLinejoin:"round", className:"aicon", "aria-hidden":"true" };
  if (n === 0) return (
    <svg {...base}>
      <circle cx="24" cy="24" r="9" />
      <circle cx="24" cy="24" r="2.8" fill="currentColor" stroke="none" />
      <circle cx="24" cy="24" r="18" strokeDasharray="6 3.5" className="aicon__spin" />
    </svg>
  );
  if (n === 1) return (
    <svg {...base}>
      <g className="aicon__travel">
        <line x1="9" y1="24" x2="33" y2="24" />
        <path d="M26 17 L37 24 L26 31" />
      </g>
    </svg>
  );
  if (n === 2) return (
    <svg {...base} strokeWidth="1.7">
      <line x1="8" y1="38" x2="40" y2="38" opacity="0.25" />
      <path d="M10 34 L18 22 L27 28 L36 14" className="aicon__draw" />
    </svg>
  );
  return (
    <svg {...base}>
      <circle cx="17.5" cy="24" r="10" className="aicon__pulse aicon__pulse--a" />
      <circle cx="30.5" cy="24" r="10" className="aicon__pulse aicon__pulse--b" />
    </svg>
  );
};

const emText = (text, phrase) => {
  if (!phrase || !text) return text;
  const i = text.indexOf(phrase);
  if (i < 0) return text;
  return (
    <React.Fragment>
      {text.slice(0, i)}
      <span className="approach-em">{phrase}</span>
      {text.slice(i + phrase.length)}
    </React.Fragment>
  );
};

// ---------- Approach (how we build) ----------
const Approach = () => {
  const { lang } = useLang();
  return (
    <section id="approach" className="approach-section">
      <div className="section-head">
        <Reveal className="section-eyebrow"><span className="rule" /><span>{t(ABC.UI.approach_eyebrow, lang)}</span></Reveal>
        <Reveal as="h2" className="section-title" delay={80}>{t(ABC.UI.approach_title_a, lang)}<span className="it">{t(ABC.UI.approach_title_em, lang)}</span></Reveal>
        <Reveal as="p" className="section-sub" delay={160}>{t(ABC.UI.approach_note, lang)}</Reveal>
      </div>
      <div className="approach-grid">
        {ABC.APPROACH.map((a, i) => (
          <Reveal key={a.num} className="approach-step" delay={i * 80}>
            <ApproachIcon n={i} />
            <span className="approach-step__num">{a.num}</span>
            <div className="approach-step__body">
              <h3 className="approach-step__title">{t(a.title, lang)}</h3>
              <p className="approach-step__text">{emText(t(a.body, lang), t(a.em, lang))}</p>
            </div>
          </Reveal>
        ))}
      </div>
    </section>
  );
};

// ---------- Map (own section, before contact) ----------
const MapSection = () => {
  const { lang } = useLang();
  return (
    <section className="mapsection" id="map">
      {/* The map must NOT sit inside a CSS-transformed ancestor — Leaflet's
          pixel math breaks under transforms (markers pile at the origin, tile
          seams appear). So the layout wrapper is a plain div and only the label
          gets a transform-free fade reveal. */}
      <div className="neighborhoods-map">
        <Reveal as="p" variant="fade" className="neighborhoods-map__label section-eyebrow">
          <span className="rule" aria-hidden="true"></span>
          {t(ABC.UI.map_label, lang)}
        </Reveal>
        <DubaiMap lang={lang} />
      </div>
    </section>
  );
};

// ---------- Office tower SVG (replaces binary-tower.png) ----------
const OfficeTower = () => (
  <svg viewBox="0 0 96 254" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
    <g stroke="currentColor" strokeWidth="0.9" strokeLinecap="round" strokeLinejoin="round">
      <line x1="2" y1="250" x2="94" y2="250"/>
      <path d="M10 250V224H86V250"/>
      <line x1="10" y1="234" x2="86" y2="234" opacity="0.5"/>
      <path d="M14,224 C10,178 9,130 11,82 C9,50 12,30 20,20 C22,17 24,16 26,16 C28,16 30,17 32,20 C40,30 43,50 41,82 C43,130 42,178 38,224 Z"/>
      <line x1="17" y1="192" x2="35" y2="192" opacity="0.38"/>
      <line x1="16" y1="155" x2="36" y2="155" opacity="0.38"/>
      <line x1="15" y1="118" x2="37" y2="118" opacity="0.38"/>
      <line x1="15" y1="80" x2="37" y2="80" opacity="0.38"/>
      <path d="M52,224 C48,175 47,122 49,72 C47,40 50,18 60,6 C62,3 64,2 66,2 C68,2 70,3 72,6 C82,18 85,40 83,72 C85,122 84,175 80,224 Z"/>
      <line x1="55" y1="192" x2="77" y2="192" opacity="0.38"/>
      <line x1="54" y1="155" x2="78" y2="155" opacity="0.38"/>
      <line x1="53" y1="118" x2="79" y2="118" opacity="0.38"/>
      <line x1="53" y1="80" x2="79" y2="80" opacity="0.38"/>
      <line x1="54" y1="44" x2="78" y2="44" opacity="0.38"/>
      <circle cx="26" cy="14" r="1.5" fill="currentColor" stroke="none"/>
      <circle cx="66" cy="2" r="1.5" fill="currentColor" stroke="none" opacity="0.6"/>
    </g>
  </svg>
);

// ---------- Contact ----------
const ContactSection = () => {
  const { lang } = useLang();
  const studio = t(ABC.UI.contact_studio, lang);
  return (
    <section className="contact" id="contact">
      <div className="contact__rosette" aria-hidden="true">
        <img src="assets/logo-mark-line.png" alt="" />
      </div>
      <Reveal className="contact__inner">
        <div className="contact__lede">
          <div className="contact__lede-head">
            <span className="section-eyebrow"><span className="rule" /><span>{t(ABC.UI.contact_eyebrow, lang)}</span></span>
            <h2 className="contact__title">{t(ABC.UI.contact_title_a, lang)}<span className="it">{t(ABC.UI.contact_title_em, lang)}</span></h2>
          </div>
          <div className="contact__place">
            <figure className="contact__photo" aria-hidden="true">
              <img src="assets/photos/binary-tower-transparent.png?v=92" alt="" />
            </figure>
            <div className="contact__place-text">
              <div className="contact__place-header">
                <span className="contact__place-icon" aria-hidden="true">
                  <Ic name="pin" size={26} stroke={1.2} color="var(--emerald)" />
                </span>
                <span className="contact__place-eyebrow">
                  {(studio.split("\n")[0] || "").split(" · ")[0]}
                </span>
              </div>
              <p className="contact__place-name">
                {(studio.split("\n")[0] || "").split(" · ").slice(1).join(" · ")}
              </p>
              <p className="contact__place-addr">
                {studio.split("\n")[1] || ""}
              </p>
              <p className="contact__near">{t(ABC.UI.office_near, lang)}</p>
              <a
                className="contact__directions"
                href="https://maps.app.goo.gl/xKoJJSVDX4uDg5yS6"
                target="_blank"
                rel="noopener noreferrer"
              >
                <Ic name="navigate" size={14} stroke={1.4} color="currentColor" />
                <span>{t(ABC.UI.contact_directions, lang)}</span>
              </a>
            </div>
          </div>
        </div>
        <div className="contact__cards">
          <a className="ccard ccard--primary" href="tel:+97145146919">
            <div className="ccard__icon">
              <Ic name="phone" size={24} stroke={1.2} color="currentColor" />
            </div>
            <div className="ccard__body">
              <span className="ccard__lbl">{t(ABC.UI.ccard_call_lbl, lang)}</span>
              <span className="ccard__val" dir="ltr">+971 4 514 6919</span>
              <span className="ccard__cta">{t(ABC.UI.ccard_call_cta, lang)}</span>
            </div>
            <div className="ccard__arrow">
              <Ic name="arrow" size={16} stroke={1.5} color="currentColor" />
            </div>
          </a>
          <a className="ccard" href="https://wa.me/97145146919" target="_blank" rel="noopener noreferrer">
            <div className="ccard__icon">
              <Ic name="whatsapp" size={24} stroke={1.1} color="var(--emerald)" />
            </div>
            <div className="ccard__body">
              <span className="ccard__lbl">{t(ABC.UI.ccard_wa_lbl, lang)}</span>
              <span className="ccard__val" dir="ltr">+971 4 514 6919</span>
            </div>
            <div className="ccard__arrow">
              <Ic name="arrow" size={16} stroke={1.5} color="currentColor" />
            </div>
          </a>
          <a className="ccard" href="mailto:info@albannaconwood.com">
            <div className="ccard__icon">
              <Ic name="mail" size={24} stroke={1.1} color="var(--emerald)" />
            </div>
            <div className="ccard__body">
              <span className="ccard__lbl">{t(ABC.UI.ccard_mail_lbl, lang)}</span>
              <span className="ccard__val" dir="ltr">info@albannaconwood.com</span>
            </div>
            <div className="ccard__arrow">
              <Ic name="arrow" size={16} stroke={1.5} color="currentColor" />
            </div>
          </a>
        </div>
      </Reveal>
    </section>
  );
};

// ---------- Footer ----------
const Footer = () => {
  const { lang } = useLang();
  return (
    <footer className="footer">
      <div className="footer__bar">
        <div className="footer__brand">
          <img className="brand-logo brand-logo--color" src={lang === "ar" ? "assets/logo-ar-color.png?v=23" : "assets/logo-en-color.png?v=23"} alt="Albanna Conwood Construction L.L.C" />
          <img className="brand-logo brand-logo--white" src={lang === "ar" ? "assets/logo-ar-white.png?v=23" : "assets/logo-en-white.png?v=23"} alt="Albanna Conwood Construction L.L.C" />
        </div>
        <span className="footer__copy">{t(ABC.UI.footer_copyright, lang)}</span>
      </div>
    </footer>
  );
};

// ---------- App ----------
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "direction": "editorial"
}/*EDITMODE-END*/;

function App() {
  const [direction, setDirection] = useState(TWEAK_DEFAULTS.direction);
  const [tweaksOn, setTweaksOn] = useState(false);

  useEffect(() => { document.documentElement.dataset.dir = direction; }, [direction]);

  // Deep links: the page renders client-side, so the browser's native hash jump
  // fires before the sections exist. Re-run it once the app has mounted.
  useEffect(() => {
    const hash = window.location.hash;
    if (!hash) return;
    const tid = setTimeout(() => {
      try {
        const el = document.querySelector(hash);
        if (el) el.scrollIntoView({ behavior: "instant" });
      } catch (e) {}
    }, 250);
    return () => clearTimeout(tid);
  }, []);

  useEffect(() => {
    const handler = (e) => {
      const d = e.data || {};
      if (d.type === "__activate_edit_mode") setTweaksOn(true);
      if (d.type === "__deactivate_edit_mode") setTweaksOn(false);
    };
    window.addEventListener("message", handler);
    window.parent.postMessage({ type: "__edit_mode_available" }, "*");
    return () => window.removeEventListener("message", handler);
  }, []);

  const setDir = (d) => {
    setDirection(d);
    window.parent.postMessage({ type: "__edit_mode_set_keys", edits: { direction: d } }, "*");
  };

  return (
    <LangProvider>
      <ProgressBar />
      <TopBar />
      <main>
        <Hero />
        <Marquee />
        <WhatWeDo />
        <StatsBand />
        <MapSection />
        {/* HIDDEN — awaiting client consents; restore by uncommenting <SelectedWork /> */}

        <Confidence />
        <ContactSection />
      </main>
      <Footer />
      {tweaksOn && (
        <div className="tweaks-mini" role="dialog" aria-label="Tweaks">
          <span className="lbl">Direction</span>
          <button className={direction === "editorial" ? "active" : ""} onClick={() => setDir("editorial")}>Editorial</button>
        </div>
      )}
    </LangProvider>
  );
}

window.AppComponents = { TopBar, Footer, LangProvider, useLang };

class ErrorBoundary extends React.Component {
  constructor(props) { super(props); this.state = { error: null }; }
  static getDerivedStateFromError(err) { return { error: err }; }
  componentDidCatch(err, info) { console.error("[ABC] React error:", err, info); }
  render() {
    if (this.state.error) {
      return (
        <div style={{ minHeight: "100vh", display: "flex", alignItems: "center", justifyContent: "center", background: "#f6f4ef", flexDirection: "column", gap: 16, padding: 32, textAlign: "center", fontFamily: "sans-serif" }}>
          <img src="assets/logo-mark-circle-emerald.png" alt="" width="64" height="64" />
          <p style={{ color: "#1a1918", fontSize: 16, maxWidth: 400, margin: 0 }}>Something went wrong loading the page. Please refresh to try again.</p>
          <button onClick={() => window.location.reload()} style={{ background: "#37857d", color: "#fff", border: "none", borderRadius: 3, padding: "10px 24px", cursor: "pointer", fontSize: 14 }}>Refresh</button>
        </div>
      );
    }
    return this.props.children;
  }
}

if (document.getElementById("root") && !document.querySelector('[data-page="tips"]')) {
  ReactDOM.createRoot(document.getElementById("root")).render(
    <ErrorBoundary><App /></ErrorBoundary>
  );
}
