// app.jsx — Afridi & Angell elevation prototype // Main shell: nav, footer, home page, tweaks panel, and route dispatcher. // Page modules live in pages.jsx. const { useState, useEffect, useMemo, useRef, useCallback } = React; const { PRACTICES, SECTORS, PEOPLE, OFFICES, ARTICLES, QUOTES, AR } = window.AA_DATA; // ─────────────────────────── TWEAKS DEFAULTS ─────────────────────────── const AA_TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "accent": "#9C7A3C", "displaySerif": "Source Serif 4", "showRibbon": true, "heroVariant": "editorial" }/*EDITMODE-END*/; // ─────────────────────────── LOGO (redrawn SVG) ─────────────────────────── // Per brief §8: the source logo is a 298×98 raster JPEG. Rebuild as clean SVG. // Original-design wordmark: serif "Afridi & Angell" with hairline rule and // year mark below. No copying of any third-party UI; this is original mark-making. function Logo({ height = 30, dark = false }) { const inkColor = dark ? "#F6F4EF" : "#13233B"; const accentColor = "var(--accent)"; return ( {/* Monogram block */} A&A {/* Wordmark */} Afridi & Angell LEGAL CONSULTANTS · EST. 1975 ); } // ─────────────────────────── ROUTING ─────────────────────────── // Hash-based router so the prototype works file://. Sets a body data attribute // for screen-label context, too. function useRoute() { const [route, setRoute] = useState(() => parseHash(location.hash)); useEffect(() => { const h = () => setRoute(parseHash(location.hash)); window.addEventListener("hashchange", h); return () => window.removeEventListener("hashchange", h); }, []); useEffect(() => { document.body.setAttribute("data-screen-label", route.label || "00 Home"); window.scrollTo({ top: 0, behavior: "instant" }); }, [route]); return route; } function parseHash(h) { const path = (h || "#/").replace(/^#/, ""); const parts = path.split("/").filter(Boolean); if (parts.length === 0) return { name: "home", label: "01 Home" }; if (parts[0] === "expertise" && parts[1]) return { name: "practice", slug: parts[1], label: "04 Practice — " + parts[1] }; if (parts[0] === "expertise") return { name: "expertise", label: "03 Expertise" }; if (parts[0] === "people" && parts[1]) return { name: "lawyer", slug: parts[1], label: "06 Lawyer — " + parts[1] }; if (parts[0] === "people") return { name: "people", label: "05 People" }; if (parts[0] === "insights") return { name: "insights", label: "07 Insights" }; if (parts[0] === "offices" && parts[1]) return { name: "office", slug: parts[1], label: "09 Office — " + parts[1] }; if (parts[0] === "offices") return { name: "offices", label: "08 Offices" }; if (parts[0] === "about") return { name: "about", label: "10 About" }; if (parts[0] === "contact") return { name: "contact", label: "11 Contact" }; return { name: "home", label: "01 Home" }; } const go = (path) => { location.hash = "#/" + path.replace(/^\//, ""); }; // ─────────────────────────── NAV ─────────────────────────── function Nav({ route, lang, setLang, dir }) { const items = [ { key: "expertise", en: "Expertise", ar: AR.navExpertise }, { key: "people", en: "People", ar: AR.navPeople }, { key: "insights", en: "Insights", ar: AR.navInsights }, { key: "offices", en: "Offices", ar: AR.navOffices }, { key: "about", en: "About", ar: AR.navAbout } ]; return ( ); } // ─────────────────────────── FOOTER ─────────────────────────── function Footer({ lang }) { const ar = lang === "ar"; return ( ); } // ─────────────────────────── HOME ─────────────────────────── function HomePage({ lang, dir }) { const ar = lang === "ar"; return (
{/* HERO */}
{ar ? AR.est : "Established 1975"} Dubai · Abu Dhabi · Sharjah · DIFC · Toronto

{ar ? AR.heroH1 : <>Advising clients in the Middle East and beyond for 50 years.}

{ar ? AR.heroLede : "A full-service UAE law firm in its fifth decade — pragmatic local-law advice combined with international quality. Exclusive UAE member firm of Lex Mundi."}

go("/contact")}> {ar ? AR.ctaConsult : "Request a consultation"} {dir === "rtl" ? "←" : "→"} go("/expertise")}> {ar ? "تصفّح مجالات الممارسة" : "Explore our 27 practice areas"}
50·
{ar ? "خمسون عامًا من الممارسة" : "Years of practice in the UAE"}
4 offices
Dubai · Abu Dhabi · Sharjah · Toronto
100+ countries
Reach via Lex Mundi attributed
{/* TRUST STRIP — verifiable claims only, no star rating */}
Est. 1975 / Licensed in Dubai · Abu Dhabi · Sharjah · DIFC / Exclusive UAE member · Lex Mundi / Ranked by Chambers Global & The Legal 500 EMEA
{/* PRACTICE GRID */}
{ar ? "مجالات الممارسة" : "01 / Practice areas"}

{ar ? "خبرة قانونية متكاملة في الإمارات." : "Twenty-seven practice areas, two flagship strengths."}

{ar ? "نقدّم خدمات قانونية شاملة عبر الإمارات الثلاث الكبرى ومركز دبي المالي العالمي." : "Full-service across the three largest Emirates and the DIFC. Ranked in dispute resolution and banking & finance by Chambers Global and The Legal 500 EMEA."}

{PRACTICES.map((p, i) => ( go("/expertise/" + p.slug)}>
{String(i + 1).padStart(2, "0")}
{p.name}
))}

 Ranked by Chambers Global & The Legal 500 EMEA. Tier & edition to confirm before publication.

go("/expertise")}>{ar ? "كل المجالات والقطاعات" : "All practice areas & industry sectors"}

{/* PULLQUOTE — attributed editorial, never a numeric score */}
02 / Independent recognition
"The firm is unique in that it can provide international quality services and advice on local law issues." — The Legal 500 EMEA edition to confirm

Quotes are independent editorial assessments from legal directories — they are not client testimonials, and the firm does not publish any aggregate star rating.

Lex Mundi

Exclusive UAE member firm — access to 21,000+ lawyers in 100+ countries.

Figures attributed to Lex Mundi · Badge rights to confirm

World Services Group

Member of the global multidisciplinary network.

{/* PEOPLE TEASER */}
03 / Partners & senior lawyers

{ar ? "نخبة من الشركاء والمستشارين." : "The people behind every matter."}

go("/people")}>View all {PEOPLE.length}
{PEOPLE.filter(p => p.rank <= 8).slice(0, 8).map(p => ( ))}

{/* INBRIEF TEASER */}
04 / inBrief

{ar ? "أحدث النشرات القانونية." : "Recent legal updates."}

The firm's branded publications series.

go("/insights")}>All publications
{ARTICLES.map(a => ( go("/insights")}>
{a.date}
{a.title}
{a.areaLabel}
))}
{/* OFFICES STRIP */}
05 / Offices

{ar ? "أربعة مكاتب، ثلاث إمارات، وعاصمة كندية." : "Four offices, three Emirates, one Canadian city."}

{OFFICES.map(o => ( go("/offices/" + o.slug)} style={{ cursor: "pointer", background: "var(--paper)", border: "1px solid var(--line)", padding: 0, transition: "all .18s ease" }}>
{o.country}

{o.city}

{o.address[0]}
{o.address[1]}

{o.phone}

))}

Office hours and map coordinates are not currently published — to be confirmed by the firm before launch.

{/* SUBSCRIBE */}
Subscribe

{ar ? "اشترك في نشرة inBrief." : "Receive inBrief in your inbox."}

{ar ? "تحليلات قانونية موجزة حول التطورات في الإمارات والمنطقة." : "Concise legal updates on UAE and regional developments — by practice area."}

{ e.preventDefault(); alert("Demo — wire to Formspree / Netlify Forms + CRM webhook."); }}>
); } // ─────────────────────────── REUSED ───────────────────────────── function LawyerCard({ p }) { return ( go("/people/" + p.id)}>
{p.name}
{p.name}
{p.role}
); } // ─────────────────────────── APP ROOT ─────────────────────────── function App() { const [t, setTweak] = useTweaks(AA_TWEAK_DEFAULTS); const [lang, setLang] = useState(() => localStorage.getItem("aa-lang") || "en"); const route = useRoute(); const dir = lang === "ar" ? "rtl" : "ltr"; useEffect(() => { document.documentElement.lang = lang; document.documentElement.dir = dir; localStorage.setItem("aa-lang", lang); }, [lang, dir]); // Tweak: live accent color useEffect(() => { document.documentElement.style.setProperty("--accent", t.accent); }, [t.accent]); useEffect(() => { document.documentElement.style.setProperty("--serif", `"${t.displaySerif}", Georgia, serif`); }, [t.displaySerif]); let page; if (route.name === "home") page = ; else if (route.name === "expertise") page = ; else if (route.name === "practice") page = ; else if (route.name === "people") page = ; else if (route.name === "lawyer") page = ; else if (route.name === "insights") page = ; else if (route.name === "offices") page = ; else if (route.name === "office") page = ; else if (route.name === "about") page = ; else if (route.name === "contact") page = ; return (