/* ================================================================
   contact.jsx — Contact Us page.
   Structure (top→bottom): hero · trial deflection band · routing
   grid ("What do you need?") · enquiry form · offices · response
   strip. Header/footer/eyebrow come from shared.jsx via window.

   A floating harness (bottom of screen) lets the CE team compare the
   two required alternatives without leaving the page:
     • Routing grid  — cards  vs  dense list
     • Offices       — per-office contacts  vs  single global support
     • Form state    — empty · validation error · success
     • View          — desktop  vs  mobile (renders the live page in a
                       390px device frame so real media queries fire)
   In ?embed=1 mode the harness is hidden (used inside the device frame).
================================================================ */
const { Icon, MAX, NS, SERIF, Eyebrow, SectionHead, SiteHeader, SiteFooter } = window;
const { Button, Input, Select, Checkbox } = window.CapitalEconomicsDesignSystem_f2a5b2;

/* ---- extra line icons (Lucide, 24×24 / 2px) not in shared set ---- */
const CI = {
  mail: <><rect width="20" height="16" x="2" y="4" rx="2" /><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" /></>,
  phone: <path d="M13.83 19a15.05 15.05 0 0 1-6.59-6.59l1.87-1.87a1 1 0 0 0 .25-1L8.09 5.4A1 1 0 0 0 7.1 4.64H4.06a1 1 0 0 0-1 1.11A17 17 0 0 0 18.25 20.94a1 1 0 0 0 1.11-1V16.9a1 1 0 0 0-.76-.99l-4.14-1.27a1 1 0 0 0-1 .25Z" />,
  "map-pin": <><path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" /><circle cx="12" cy="10" r="3" /></>,
  shield: <path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1Z" />,
  headset: <><path d="M3 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H4a1 1 0 0 1-1-1v-6a9 9 0 0 1 18 0v6a1 1 0 0 1-1 1h-2a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3" /></>,
  newspaper: <><path d="M15 18h-5" /><path d="M18 14h-8" /><path d="M4 22h16a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v16a2 2 0 0 1-2 2Zm0 0a2 2 0 0 1-2-2v-9c0-1.1.9-2 2-2h2" /><path d="M10 6h8v4h-8V6Z" /></>,
  "share-2": <><circle cx="18" cy="5" r="3" /><circle cx="6" cy="12" r="3" /><circle cx="18" cy="19" r="3" /><path d="m8.6 13.5 6.8 4M15.4 6.5l-6.8 4" /></>,
  "credit-card": <><rect width="20" height="14" x="2" y="5" rx="2" /><path d="M2 10h20" /></>,
  "alert-circle": <><circle cx="12" cy="12" r="10" /><path d="M12 8v4M12 16h.01" /></>,
  "check-circle": <><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" /><path d="m9 11 3 3L22 4" /></>,
  "arrow-right": <><path d="M5 12h14" /><path d="m12 5 7 7-7 7" /></>,
  "chevron-right": <path d="m9 18 6-6-6-6" />,
  clock: <><circle cx="12" cy="12" r="10" /><path d="M12 6v6l4 2" /></>,
  send: <><path d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z" /><path d="m21.854 2.147-10.94 10.939" /></>,
  users: <><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" /><circle cx="9" cy="7" r="4" /><path d="M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75" /></>,
};
function CIcon({ name, size = 20, stroke = 2, style }) {
  return (
    <svg style={style} width={size} height={size} viewBox="0 0 24 24" fill="none"
      stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      {CI[name]}
    </svg>
  );
}

/* ---- reason values (must match the tile → form preselect) ---- */
const R = {
  subs: "Subscriptions and pricing",
  consult: "Consultancy and bespoke research",
  dist: "Distribution and channel partners",
  media: "Media and press",
  support: "Client support",
  other: "Something else",
};
const REASONS = [R.subs, R.consult, R.dist, R.media, R.support, R.other];
const TEAM = {
  [R.subs]: "subscriptions team",
  [R.consult]: "consultancy team",
  [R.dist]: "partnerships team",
  [R.media]: "press office",
  [R.support]: "client support team",
  [R.other]: "team",
};
const emailHref = (a) => "mailto:" + a;
const telHref = (s) => "tel:" + s.replace(/[^\d+]/g, "");
const mapHref = (q) => "https://www.google.com/maps/search/?api=1&query=" + encodeURIComponent(q);

/* ================================================================
   Page-scoped CSS. Mobile rules are authored once with a "@@" token
   and emitted twice: inside a real media query (true responsive) and
   under .ce-view-mobile (so the harness device frame is faithful too).
================================================================ */
let cssInjected = false;
function injectCSS() {
  if (cssInjected || typeof document === "undefined") return;
  cssInjected = true;
  const base = `
  .ce-plain-mail { font-family: var(--font-ui); font-weight: 700; color: var(--brand); text-decoration: none; font-variant-numeric: tabular-nums; word-break: break-word; }
  .ce-plain-mail:hover { text-decoration: underline; color: var(--brand-hover); }
  .ce-tel { font-family: var(--font-ui); color: var(--text-primary); text-decoration: none; font-variant-numeric: tabular-nums; }
  .ce-tel:hover { text-decoration: underline; }

  /* ---- Trial deflection band ---- */
  .ce-trialband-inner { display: flex; align-items: center; gap: 20px 26px; flex-wrap: wrap; }
  .ce-trialband-copy { flex: 1 1 420px; }

  /* ---- Routing grid: CARDS ---- */
  .ce-tiles-a { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; grid-auto-rows: 1fr; }
  .ce-tiles-a .ce-tile--hero { grid-column: 1 / -1; }
  .ce-tiles-b { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; margin-top: 18px; }
  .ce-tile { position: relative; display: flex; flex-direction: column; text-align: left; width: 100%; background: var(--surface-card); border: 1px solid var(--border-default); border-radius: var(--radius-lg); padding: 26px 28px; cursor: pointer; transition: border-color 150ms cubic-bezier(0.2,0,0,1), box-shadow 150ms cubic-bezier(0.2,0,0,1), transform 150ms cubic-bezier(0.2,0,0,1); appearance: none; font: inherit; color: inherit; }
  .ce-tile:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
  .ce-tile:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }
  .ce-tile--hero { background: linear-gradient(180deg, #F4F6FC 0%, #E8EEFA 100%); border-color: #cdd8f0; padding: 32px 34px; }
  .ce-tile--b { background: var(--surface-sunken); padding: 22px 24px; }
  .ce-tile-ico { width: 40px; height: 40px; border-radius: 9px; background: var(--brand-subtle); color: var(--brand); display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; }
  .ce-tile--hero .ce-tile-ico { width: 46px; height: 46px; }
  .ce-tile h3 { font-family: var(--font-ui); font-weight: 700; color: var(--text-primary); margin: 0; }
  .ce-tile-support { font-family: var(--font-ui); font-size: 15px; line-height: 1.5; color: var(--text-secondary); margin: 0; }
  .ce-tile-cta { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-ui); font-weight: 700; color: var(--brand); }
  .ce-tile:hover .ce-tile-cta .ce-cta-arrow { transform: translateX(3px); }
  .ce-cta-arrow { transition: transform 150ms cubic-bezier(0.2,0,0,1); }

  /* ---- Routing grid: LIST ---- */
  .ce-list { border: 1px solid var(--border-default); border-radius: var(--radius-lg); overflow: hidden; background: var(--surface-card); }
  .ce-list-row { display: grid; grid-template-columns: 44px minmax(230px, 1.1fr) 1.4fr auto; align-items: center; gap: 22px; width: 100%; text-align: left; background: transparent; border: 0; border-top: 1px solid var(--border-subtle); padding: 20px 26px; cursor: pointer; appearance: none; font: inherit; color: inherit; transition: background 140ms cubic-bezier(0.2,0,0,1); }
  .ce-list-row:first-child { border-top: 0; }
  .ce-list-row:hover { background: var(--surface-sunken); }
  .ce-list-row:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: -3px; }
  .ce-list-row--hero { background: var(--brand-subtle); }
  .ce-list-row--hero:hover { background: #dbe4f6; }
  .ce-list-ico { width: 40px; height: 40px; border-radius: 9px; background: var(--brand-subtle); color: var(--brand); display: inline-flex; align-items: center; justify-content: center; }
  .ce-list-row--hero .ce-list-ico { background: #fff; }
  .ce-list-title { font-family: var(--font-ui); font-weight: 700; color: var(--text-primary); margin: 0; }
  .ce-list-support { font-family: var(--font-ui); font-size: 14.5px; line-height: 1.45; color: var(--text-secondary); margin: 0; }
  .ce-list-action { justify-self: end; text-align: right; }
  .ce-list-group + .ce-list-group { margin-top: 40px; }

  /* ---- Enquiry form ---- */
  .ce-form-grid { display: grid; grid-template-columns: 1.55fr 0.95fr; gap: 40px; align-items: start; }
  .ce-form-card { background: var(--surface-card); border: 1px solid var(--border-default); border-radius: var(--radius-lg); padding: 34px 36px; box-shadow: var(--shadow-sm); }
  .ce-field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
  .ce-form-side > * + * { margin-top: 18px; }
  .ce-side-card { background: var(--surface-sunken); border: 1px solid var(--border-subtle); border-radius: var(--radius-lg); padding: 22px 24px; }
  .ce-errsum { display: flex; gap: 12px; background: var(--negative-100); border: 1px solid #f0c3c3; border-radius: var(--radius-md); padding: 16px 18px; margin-bottom: 24px; }
  .ce-errsum a { color: var(--negative); font-weight: 700; }

  /* ---- Offices ---- */
  .ce-office-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px; }
  .ce-office { display: flex; flex-direction: column; }
  .ce-office-contact { border-top: 1px solid var(--border-subtle); margin-top: 20px; padding-top: 18px; }

  /* ---- Response strip ---- */
  .ce-resp-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px; }

  @keyframes ceFade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
  .ce-fade { animation: ceFade 220ms cubic-bezier(0.2,0,0,1) both; }
  @media (prefers-reduced-motion: reduce) { .ce-fade { animation: none; } }
  `;
  const mobile = `
  @@.ce-tiles-a { grid-template-columns: 1fr; }
  @@.ce-tiles-a .ce-tile--hero { grid-column: auto; }
  @@.ce-tiles-b { grid-template-columns: 1fr; }
  @@.ce-tile, @@.ce-tile--hero { padding: 22px 22px; }
  @@.ce-list-row { grid-template-columns: 40px 1fr; grid-template-areas: "ico title" "sup sup" "act act"; gap: 8px 16px; padding: 18px 18px; }
  @@.ce-list-ico { grid-area: ico; }
  @@.ce-list-main { grid-area: title; }
  @@.ce-list-sup { grid-area: sup; }
  @@.ce-list-action { grid-area: act; justify-self: start; text-align: left; margin-top: 4px; }
  @@.ce-form-grid { grid-template-columns: 1fr; gap: 24px; }
  @@.ce-form-card { padding: 24px 20px; }
  @@.ce-field-row { grid-template-columns: 1fr; gap: 0; }
  @@.ce-office-grid { grid-template-columns: 1fr; gap: 30px; }
  @@.ce-resp-grid { grid-template-columns: 1fr; gap: 22px; }
  @@.ce-trialband-inner { align-items: flex-start; }
  @@.ce-hero-h1 { font-size: 34px !important; }
  `;
  const media = mobile.replace(/@@/g, "");
  const classed = mobile.replace(/@@/g, ".ce-view-mobile ");
  const el = document.createElement("style");
  el.setAttribute("data-ce", "contact-page");
  el.textContent = base + "\n@media (max-width: 820px){" + media + "}\n" + classed;
  document.head.appendChild(el);
}
injectCSS();

/* ================================================================
   Hero — shared shallow navy marketing hero. No image, no CTA.
================================================================ */
function ContactHero() {
  return (
    <section style={{ background: "#1d233f", position: "relative", overflow: "hidden" }}>
      <div style={{ maxWidth: MAX, margin: "0 auto", padding: "78px 32px 66px", position: "relative", zIndex: 2 }}>
        <Eyebrow style={{ marginBottom: 16, color: "var(--ce-blue-light)" }}>Contact us</Eyebrow>
        <h1 className="ce-hero-h1" style={{ fontFamily: SERIF, fontWeight: 600, fontSize: 52, lineHeight: 1.06, letterSpacing: "-0.02em", color: "#fff", margin: 0 }}>
          Get in touch
        </h1>
        <p style={{ fontFamily: NS, fontSize: 19, lineHeight: 1.5, color: "var(--text-on-navy)", margin: "20px 0 0", maxWidth: 560 }}>
          Every enquiry goes straight to the team that handles it.
        </p>
      </div>
    </section>
  );
}

/* ================================================================
   Trial deflection band — slim, one line, one button. A shortcut,
   not an obstacle.
================================================================ */
function TrialBand() {
  return (
    <section style={{ background: "var(--brand-subtle)", borderBottom: "1px solid var(--border-subtle)" }}>
      <div style={{ maxWidth: MAX, margin: "0 auto", padding: "18px 32px" }}>
        <div className="ce-trialband-inner">
          <div style={{ width: 34, height: 34, borderRadius: 8, background: "#fff", border: "1px solid #cdd8f0", color: "var(--brand)", display: "inline-flex", alignItems: "center", justifyContent: "center", flex: "0 0 auto" }}>
            <CIcon name="arrow-right" size={18} />
          </div>
          <p className="ce-trialband-copy" style={{ fontFamily: NS, fontSize: 16, lineHeight: 1.45, color: "var(--text-primary)", margin: 0 }}>
            <strong style={{ fontWeight: 700 }}>Want to see the platform first?</strong>{" "}
            <span style={{ color: "var(--text-secondary)" }}>Start a free trial and get instant access to the research. No sales call needed.</span>
          </p>
          <Button variant="primary" size="md" iconEnd={<CIcon name="arrow-right" size={17} />}>Start free trial</Button>
        </div>
      </div>
    </section>
  );
}

/* ================================================================
   Routing grid data.
================================================================ */
const GROUP_A = [
  { key: "subs", icon: "credit-card", hero: true, title: "Subscriptions and pricing",
    support: "Coverage options, team access, add-ons and renewals.",
    action: { type: "form", reason: R.subs, label: "Talk to our team" },
    email: "sales@capitaleconomics.com" },
  { key: "consult", icon: "users", title: "Consultancy and bespoke research",
    support: "Commissioned projects, custom modelling and expert advisory.",
    action: { type: "email", email: "consultancy@capitaleconomics.com" },
    formLink: { reason: R.consult, label: "Send us a brief" } },
  { key: "dist", icon: "share-2", title: "Distribution and channel partners",
    support: "Bloomberg, FactSet, API and third-party distribution.",
    action: { type: "form", reason: R.dist, label: "Talk to our team" } },
  { key: "media", icon: "newspaper", title: "Media and press",
    support: "Interview requests, comment and citing our data.",
    action: { type: "form", reason: R.media, label: "Contact the press office" } },
];
const GROUP_B = [
  { key: "support", icon: "headset", title: "Client support",
    support: "Account access, technical issues and billing.",
    action: { type: "email", email: "support@capitaleconomics.com" },
    formLink: { reason: R.support, label: "Contact support" } },
  { key: "dp", icon: "shield", title: "Data protection",
    support: "Subject access requests and right to be forgotten.",
    action: { type: "email", email: "data.protection@capitaleconomics.com" } },
];

function stop(e) { e.stopPropagation(); }

/* ---- CARD treatment ---- */
function TileCard({ t, group, onPick }) {
  const hero = t.hero;
  const primaryForm = t.action.type === "form";
  const activate = () => {
    if (primaryForm) onPick(t.action.reason);
    else window.location.href = emailHref(t.action.email);
  };
  const onKey = (e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); activate(); } };
  return (
    <div className={"ce-tile" + (hero ? " ce-tile--hero" : "") + (group === "b" ? " ce-tile--b" : "")}
      role="button" tabIndex={0} onClick={activate} onKeyDown={onKey}>
      <div style={{ display: "flex", alignItems: "center", gap: 14, marginBottom: 14 }}>
        <span className="ce-tile-ico"><CIcon name={t.icon} size={hero ? 24 : 20} /></span>
        <h3 style={{ fontSize: hero ? 22 : 18 }}>{t.title}</h3>
      </div>
      <p className="ce-tile-support" style={{ marginBottom: 18, maxWidth: hero ? 520 : 340 }}>{t.support}</p>
      <div style={{ marginTop: "auto", display: "flex", flexWrap: "wrap", alignItems: "center", gap: "10px 22px" }}>
        {primaryForm ? (
          <span className="ce-tile-cta" style={{ fontSize: hero ? 16 : 15 }}>
            {t.action.label}<CIcon name="arrow-right" size={16} className="ce-cta-arrow" />
          </span>
        ) : (
          <a href={emailHref(t.action.email)} className="ce-plain-mail" onClick={stop} style={{ fontSize: hero ? 17 : 16 }}>
            {t.action.email}
          </a>
        )}
        {/* secondary route */}
        {t.action.type === "form" && t.email && (
          <a href={emailHref(t.email)} className="ce-plain-mail" onClick={stop} style={{ fontWeight: 600, fontSize: 14.5, color: "var(--text-secondary)" }}>{t.email}</a>
        )}
        {t.formLink && (
          <button className="ce-textlink" onClick={(e) => { stop(e); onPick(t.formLink.reason); }} style={{ background: "none", border: 0, cursor: "pointer", padding: 0, fontSize: 14.5 }}>
            {t.formLink.label}<CIcon name="chevron-right" size={15} />
          </button>
        )}
      </div>
    </div>
  );
}

/* ---- LIST treatment ---- */
function ListRow({ t, hero, onPick }) {
  const primaryForm = t.action.type === "form";
  const activate = () => {
    if (primaryForm) onPick(t.action.reason);
    else window.location.href = emailHref(t.action.email);
  };
  const onKey = (e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); activate(); } };
  return (
    <div className={"ce-list-row" + (hero ? " ce-list-row--hero" : "")} role="button" tabIndex={0} onClick={activate} onKeyDown={onKey}>
      <span className="ce-list-ico"><CIcon name={t.icon} size={20} /></span>
      <div className="ce-list-main"><h3 className="ce-list-title" style={{ fontSize: hero ? 18 : 16.5 }}>{t.title}</h3></div>
      <p className="ce-list-support ce-list-sup">{t.support}</p>
      <div className="ce-list-action">
        {primaryForm ? (
          <span className="ce-tile-cta" style={{ fontSize: 15 }}>{t.action.label}<CIcon name="arrow-right" size={16} className="ce-cta-arrow" /></span>
        ) : (
          <a href={emailHref(t.action.email)} className="ce-plain-mail" onClick={stop} style={{ fontSize: 15.5 }}>{t.action.email}</a>
        )}
        {t.action.type === "form" && t.email && (
          <div><a href={emailHref(t.email)} className="ce-plain-mail" onClick={stop} style={{ fontWeight: 600, fontSize: 13.5, color: "var(--text-secondary)" }}>{t.email}</a></div>
        )}
        {t.formLink && (
          <div><button className="ce-textlink" onClick={(e) => { stop(e); onPick(t.formLink.reason); }} style={{ background: "none", border: 0, cursor: "pointer", padding: 0, fontSize: 13.5, marginTop: 4 }}>{t.formLink.label}<CIcon name="chevron-right" size={14} /></button></div>
        )}
      </div>
    </div>
  );
}

function GroupLabel({ children, sub }) {
  return (
    <div style={{ marginBottom: 18 }}>
      <div style={{ fontFamily: NS, fontWeight: 700, fontSize: 13, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--brand)" }}>{children}</div>
      {sub && <div style={{ fontFamily: NS, fontSize: 14.5, color: "var(--text-muted)", marginTop: 5 }}>{sub}</div>}
    </div>
  );
}

function RoutingGrid({ variant, onPick }) {
  return (
    <section style={{ background: "var(--surface-card)", borderBottom: "1px solid var(--border-subtle)" }}>
      <div style={{ maxWidth: MAX, margin: "0 auto", padding: "60px 32px" }}>
        <SectionHead eyebrow="Choose a route" title="What do you need?"
          intro="Pick the closest match. We'll take you to the right team, with the reason for contact already set." />

        {variant === "cards" ? (
          <>
            <div style={{ marginBottom: 30 }}>
              <GroupLabel sub="Subscriptions, consultancy, distribution and press.">New to Capital Economics</GroupLabel>
              <div className="ce-tiles-a">
                {GROUP_A.map((t) => <TileCard key={t.key} t={t} group="a" onPick={onPick} />)}
              </div>
            </div>
            <div>
              <GroupLabel sub="Support and data protection for existing clients.">Already a client</GroupLabel>
              <div className="ce-tiles-b">
                {GROUP_B.map((t) => <TileCard key={t.key} t={t} group="b" onPick={onPick} />)}
              </div>
            </div>
          </>
        ) : (
          <>
            <div className="ce-list-group">
              <GroupLabel sub="Subscriptions, consultancy, distribution and press.">New to Capital Economics</GroupLabel>
              <div className="ce-list">
                {GROUP_A.map((t) => <ListRow key={t.key} t={t} hero={t.hero} onPick={onPick} />)}
              </div>
            </div>
            <div className="ce-list-group">
              <GroupLabel sub="Support and data protection for existing clients.">Already a client</GroupLabel>
              <div className="ce-list">
                {GROUP_B.map((t) => <ListRow key={t.key} t={t} onPick={onPick} />)}
              </div>
            </div>
          </>
        )}
      </div>
    </section>
  );
}

/* ================================================================
   Enquiry form — one form, reason-driven. States: empty · error ·
   success. `seedReason` preselects on arrival from a tile;
   `demoState` lets the harness force a state for review.
================================================================ */
const EMPTY = { reason: "", name: "", email: "", company: "", jobtitle: "", region: "", message: "", consent: false };
const ERROR_SEED = { reason: "", name: "Alex Morgan", email: "alex.morgan@fund", company: "", jobtitle: "Portfolio Manager", region: "", message: "", consent: false };
const REGIONS = ["UK and Europe", "Americas", "Asia Pacific"];

function validate(v) {
  const e = {};
  if (!v.reason) e.reason = "Choose a reason for contact.";
  if (!v.name.trim()) e.name = "Enter your full name.";
  if (!v.email.trim()) e.email = "Enter your work email.";
  else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v.email.trim())) e.email = "Enter a valid work email address.";
  if (!v.company.trim()) e.company = "Enter your company.";
  if (!v.region) e.region = "Select a region.";
  if (!v.message.trim()) e.message = "Add a short message.";
  return e;
}

const FIELD_ORDER = ["reason", "name", "email", "company", "region", "message"];
const FIELD_LABEL = { reason: "Reason for contact", name: "Full name", email: "Work email", company: "Company", region: "Region", message: "Message" };

function EnquiryForm({ seedReason, demoState, formRef }) {
  const [v, setV] = React.useState(EMPTY);
  const [errors, setErrors] = React.useState({});
  const [state, setState] = React.useState("empty"); // empty | success
  const sumRef = React.useRef();
  const focusField = (k) => { const el = typeof document !== "undefined" && document.getElementById("f-" + k); if (el) el.focus(); };

  const set = (k) => (e) => setV((s) => ({ ...s, [k]: e.target.type === "checkbox" ? e.target.checked : e.target.value }));

  // Tile preselect
  React.useEffect(() => {
    if (seedReason) { setV((s) => ({ ...s, reason: seedReason })); setState("empty"); setErrors({}); }
  }, [seedReason]);

  // Harness-driven demo states
  React.useEffect(() => {
    if (demoState === "error") { setV(ERROR_SEED); setErrors(validate(ERROR_SEED)); setState("empty"); setTimeout(() => sumRef.current && sumRef.current.focus(), 30); }
    else if (demoState === "success") { setV((s) => ({ ...s, reason: s.reason || R.subs, name: "Alex Morgan", email: "alex.morgan@brightwater.com", company: "Brightwater Capital", region: "UK and Europe", message: "We're reviewing macro research providers for our multi-asset desk." })); setState("success"); }
    else if (demoState === "empty") { setV(EMPTY); setErrors({}); setState("empty"); }
  }, [demoState]);

  const submit = (e) => {
    e.preventDefault();
    setState("success");
    if (formRef && formRef.current) { const r = formRef.current.getBoundingClientRect(); window.scrollTo({ top: window.scrollY + r.top - 90, behavior: "smooth" }); }
  };

  const team = TEAM[v.reason] || "team";

  return (
    <section ref={formRef} style={{ background: "var(--surface-page)", borderBottom: "1px solid var(--border-subtle)" }}>
      <div style={{ maxWidth: MAX, margin: "0 auto", padding: "64px 32px" }}>
        <SectionHead eyebrow="Send an enquiry" title="Tell us what you need."
          intro="One form, routed by your reason for contact. Fields marked with * are required." />

        <div className="ce-form-grid">
          {/* ---- main column ---- */}
          <div className="ce-form-card">
            {state === "success" ? (
              <div className="ce-fade" role="status" aria-live="polite" style={{ padding: "8px 4px" }}>
                <div style={{ width: 52, height: 52, borderRadius: "50%", background: "var(--positive-100)", color: "var(--positive)", display: "inline-flex", alignItems: "center", justifyContent: "center", marginBottom: 20 }}>
                  <CIcon name="check-circle" size={28} />
                </div>
                <h3 style={{ fontFamily: SERIF, fontWeight: 600, fontSize: 26, letterSpacing: "-0.015em", color: "var(--text-primary)", margin: "0 0 12px" }}>Thanks. Your enquiry is on its way.</h3>
                <p style={{ fontFamily: NS, fontSize: 16.5, lineHeight: 1.6, color: "var(--text-secondary)", margin: "0 0 8px", maxWidth: 520 }}>
                  This has gone to our {team}. We'll reply within <strong style={{ color: "var(--text-primary)" }}>[response window to be confirmed]</strong>.
                </p>
                <p style={{ fontFamily: NS, fontSize: 16.5, lineHeight: 1.6, color: "var(--text-secondary)", margin: "0 0 26px", maxWidth: 520 }}>
                  In the meantime, you can start a free trial and look around the platform.
                </p>
                <div style={{ display: "flex", flexWrap: "wrap", gap: 12 }}>
                  <Button variant="primary" size="lg" iconEnd={<CIcon name="arrow-right" size={18} />}>Start free trial</Button>
                  <Button variant="secondary" size="lg" onClick={() => { setV(EMPTY); setErrors({}); setState("empty"); }}>Send another enquiry</Button>
                </div>
              </div>
            ) : (
              <form onSubmit={submit} noValidate>
                {Object.keys(errors).length > 0 && (
                  <div className="ce-errsum" ref={sumRef} tabIndex={-1} role="alert">
                    <span style={{ color: "var(--negative)", flex: "0 0 auto", marginTop: 1 }}><CIcon name="alert-circle" size={20} /></span>
                    <div>
                      <div style={{ fontFamily: NS, fontWeight: 700, fontSize: 15, color: "var(--text-primary)", marginBottom: 6 }}>Please fix {Object.keys(errors).length} {Object.keys(errors).length === 1 ? "field" : "fields"} before sending.</div>
                      <ul style={{ margin: 0, paddingLeft: 18, fontFamily: NS, fontSize: 14, lineHeight: 1.7, color: "var(--text-secondary)" }}>
                        {FIELD_ORDER.filter((k) => errors[k]).map((k) => (
                          <li key={k}><a href={"#f-" + k} onClick={(e) => { e.preventDefault(); focusField(k); }}>{FIELD_LABEL[k]}</a>: {errors[k]}</li>
                        ))}
                      </ul>
                    </div>
                  </div>
                )}

                <div style={{ display: "flex", flexDirection: "column", gap: 18 }}>
                  <div>
                    <Select id="f-reason" label="Reason for contact *" required value={v.reason} onChange={set("reason")} error={errors.reason}
                      options={[{ value: "", label: "Select a reason…" }, ...REASONS.map((r) => ({ value: r, label: r }))]} />
                    {v.reason === R.consult && (
                      <p className="ce-fade" style={{ fontFamily: NS, fontSize: 14, lineHeight: 1.5, color: "var(--text-secondary)", margin: "10px 2px 0" }}>
                        Prefer to email directly? Send your brief to <a href={emailHref("consultancy@capitaleconomics.com")} className="ce-plain-mail" style={{ fontSize: 14 }}>consultancy@capitaleconomics.com</a>
                      </p>
                    )}
                  </div>

                  <div className="ce-field-row">
                    <Input id="f-name" label="Full name" required value={v.name} onChange={set("name")} error={errors.name} autoComplete="name" />
                    <Input id="f-email" label="Work email" required type="email" value={v.email} onChange={set("email")} error={errors.email} autoComplete="email" />
                  </div>

                  <div className="ce-field-row">
                    <Input id="f-company" label="Company" required value={v.company} onChange={set("company")} error={errors.company} autoComplete="organization" />
                    <Input id="f-jobtitle" label="Job title" value={v.jobtitle} onChange={set("jobtitle")} hint="Optional" autoComplete="organization-title" />
                  </div>

                  <Select id="f-region" label="Region *" required value={v.region} onChange={set("region")} error={errors.region}
                    options={[{ value: "", label: "Select a region…" }, ...REGIONS.map((r) => ({ value: r, label: r }))]} />

                  <div>
                    <label htmlFor="f-message" style={{ display: "block", fontFamily: NS, fontWeight: 600, fontSize: 14, color: "var(--text-primary)", marginBottom: 7 }}>Message *</label>
                    <textarea id="f-message" value={v.message} onChange={set("message")} rows={4}
                      style={{ width: "100%", boxSizing: "border-box", fontFamily: NS, fontSize: 15.5, lineHeight: 1.5, color: "var(--text-primary)", padding: "11px 13px", borderRadius: "var(--radius-md, 5px)", border: "1px solid " + (errors.message ? "var(--negative)" : "var(--border-default)"), outline: "none", resize: "vertical", background: "var(--surface-card)" }} />
                    {errors.message && <div style={{ fontFamily: NS, fontSize: 13, color: "var(--negative)", marginTop: 6 }}>{errors.message}</div>}
                  </div>

                  <Checkbox checked={v.consent} onChange={set("consent")}
                    label={<span style={{ fontSize: 14.5 }}>Send me occasional research highlights and product updates. You can unsubscribe at any time. See our <a href="#privacy">privacy policy</a>.</span>} />

                  <div style={{ marginTop: 4 }}>
                    <Button type="submit" variant="primary" size="lg" iconEnd={<CIcon name="send" size={17} />}>Send enquiry</Button>
                  </div>
                </div>
              </form>
            )}

            {/* Persistent data-protection line — deliberately outside the dropdown */}
            <div style={{ display: "flex", gap: 11, marginTop: 22, paddingTop: 20, borderTop: "1px solid var(--border-subtle)" }}>
              <span style={{ color: "var(--text-muted)", flex: "0 0 auto", marginTop: 1 }}><CIcon name="shield" size={18} /></span>
              <p style={{ fontFamily: NS, fontSize: 13.5, lineHeight: 1.55, color: "var(--text-secondary)", margin: 0 }}>
                Data protection requests, including subject access and right to be forgotten, must be sent to <a href={emailHref("data.protection@capitaleconomics.com")} className="ce-plain-mail" style={{ fontSize: 13.5 }}>data.protection@capitaleconomics.com</a>.
              </p>
            </div>
          </div>

          {/* ---- supporting side panel ---- */}
          <aside className="ce-form-side">
            <div className="ce-side-card">
              <div className="ce-eyebrow" style={{ marginBottom: 14 }}>Prefer email?</div>
              <SideRow icon="credit-card" label="Subscriptions" mail="sales@capitaleconomics.com" />
              <SideRow icon="users" label="Consultancy" mail="consultancy@capitaleconomics.com" />
              <SideRow icon="headset" label="Client support" mail="support@capitaleconomics.com" last />
            </div>
            <div className="ce-side-card" style={{ background: "var(--brand-subtle)", border: "1px solid #cdd8f0" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 10 }}>
                <span style={{ color: "var(--brand)" }}><CIcon name="clock" size={18} /></span>
                <div style={{ fontFamily: NS, fontWeight: 700, fontSize: 15, color: "var(--text-primary)" }}>What to expect</div>
              </div>
              <p style={{ fontFamily: NS, fontSize: 14, lineHeight: 1.55, color: "var(--text-secondary)", margin: 0 }}>
                Your enquiry is routed straight to the named team. A specialist replies within <strong style={{ color: "var(--text-primary)" }}>[response window to be confirmed]</strong> — no call centre in between.
              </p>
            </div>
          </aside>
        </div>
      </div>
    </section>
  );
}

function SideRow({ icon, label, mail, last }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 12, padding: "11px 0", borderBottom: last ? "none" : "1px solid var(--border-subtle)" }}>
      <span style={{ width: 30, height: 30, borderRadius: 7, background: "#fff", border: "1px solid var(--border-subtle)", color: "var(--brand)", display: "inline-flex", alignItems: "center", justifyContent: "center", flex: "0 0 auto" }}><CIcon name={icon} size={16} /></span>
      <div style={{ minWidth: 0 }}>
        <div style={{ fontFamily: NS, fontSize: 12, fontWeight: 700, letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--text-muted)" }}>{label}</div>
        <a href={emailHref(mail)} className="ce-plain-mail" style={{ fontSize: 14 }}>{mail}</a>
      </div>
    </div>
  );
}

/* ================================================================
   Offices — static three-column block. Two versions:
     • perOffice — each office lists its own contact emails
     • global    — phone is the only per-office detail; support@ once
================================================================ */
const OFFICES = [
  { key: "london", city: "London", phone: "+44 (0)20 7823 5000",
    entity: "Capital Economics Ltd", lines: ["5th Floor, 100 Victoria Street", "Cardinal Place, London", "SW1E 5JL, United Kingdom"],
    emails: ["sales@capitaleconomics.com", "business@capitaleconomics.com", "support@capitaleconomics.com"],
    map: "Capital Economics, 100 Victoria Street, Cardinal Place, London SW1E 5JL" },
  { key: "toronto", city: "Toronto", phone: "+1 416 413 0428",
    entity: "Capital Economics (N.A.) Ltd", lines: ["Suite 600, 77 Bloor Street West", "Toronto, ON", "M5S 1M2, Canada"],
    emails: ["support@capitaleconomics.com"],
    map: "Capital Economics, 77 Bloor Street West, Toronto ON M5S 1M2" },
  { key: "singapore", city: "Singapore", phone: "+65 6595 5190",
    entity: "Capital Economics (Asia) Pte. Ltd", lines: ["05-01/02, CapitaGreen", "138 Market Street", "Singapore 048946"],
    emails: ["support@capitaleconomics.com"],
    map: "Capital Economics, CapitaGreen, 138 Market Street, Singapore 048946" },
];

function OfficesBlock({ variant }) {
  const global = variant === "global";
  return (
    <section style={{ background: "var(--surface-card)", borderBottom: "1px solid var(--border-subtle)" }}>
      <div style={{ maxWidth: MAX, margin: "0 auto", padding: "64px 32px" }}>
        <SectionHead eyebrow="Our offices" title="Three offices, one team."
          intro="Call the office closest to you. Postal addresses are for correspondence — enquiries are fastest through the routes above." />

        <div className="ce-office-grid">
          {OFFICES.map((o) => (
            <div key={o.key} className="ce-office">
              <h3 style={{ fontFamily: SERIF, fontWeight: 600, fontSize: 24, letterSpacing: "-0.01em", color: "var(--text-primary)", margin: "0 0 14px" }}>{o.city}</h3>

              {/* Phone — most useful item, given the most weight */}
              <a href={telHref(o.phone)} className="ce-tel" style={{ display: "inline-flex", alignItems: "center", gap: 9, fontWeight: 700, fontSize: 20, letterSpacing: "-0.01em" }}>
                <span style={{ color: "var(--brand)" }}><CIcon name="phone" size={18} /></span>{o.phone}
              </a>

              {/* Address */}
              <address style={{ fontStyle: "normal", fontFamily: NS, fontSize: 14.5, lineHeight: 1.6, color: "var(--text-secondary)", margin: "16px 0 0" }}>
                <div style={{ fontWeight: 600, color: "var(--text-primary)" }}>{o.entity}</div>
                {o.lines.map((l) => <div key={l}>{l}</div>)}
              </address>
              <a href={mapHref(o.map)} target="_blank" rel="noopener" className="ce-textlink" style={{ marginTop: 12, fontSize: 14 }}>
                <CIcon name="map-pin" size={15} />View on map
              </a>

              {/* Per-office contacts (perOffice version only) */}
              {!global && (
                <div className="ce-office-contact">
                  <div style={{ fontFamily: NS, fontSize: 12, fontWeight: 700, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--text-muted)", marginBottom: 9 }}>Contact</div>
                  <div style={{ display: "flex", flexDirection: "column", gap: 5 }}>
                    {o.emails.map((m) => <a key={m} href={emailHref(m)} className="ce-plain-mail" style={{ fontSize: 14.5, fontWeight: 600 }}>{m}</a>)}
                  </div>
                </div>
              )}
            </div>
          ))}
        </div>

        {/* Global support line (global version only) */}
        {global && (
          <div style={{ display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap", marginTop: 32, paddingTop: 26, borderTop: "1px solid var(--border-subtle)" }}>
            <span style={{ color: "var(--brand)" }}><CIcon name="headset" size={18} /></span>
            <span style={{ fontFamily: NS, fontSize: 15, color: "var(--text-secondary)" }}>Client support is a single global inbox:</span>
            <a href={emailHref("support@capitaleconomics.com")} className="ce-plain-mail" style={{ fontSize: 15.5 }}>support@capitaleconomics.com</a>
          </div>
        )}
      </div>
    </section>
  );
}

/* ================================================================
   Response expectation strip — closing, above the footer.
================================================================ */
function ResponseStrip() {
  const items = [
    { icon: "send", h: "After you send", b: "Your enquiry is routed automatically to the team named on the form. Nothing sits in a shared inbox." },
    { icon: "clock", h: "Typical response", b: "A specialist replies within [response window to be confirmed], during office hours across our three regions." },
    { icon: "users", h: "Who replies", b: "The relevant team — subscriptions, consultancy, partnerships, press or client support — not a general agent." },
  ];
  return (
    <section style={{ background: "var(--surface-sunken)", borderBottom: "1px solid var(--border-subtle)" }}>
      <div style={{ maxWidth: MAX, margin: "0 auto", padding: "48px 32px" }}>
        <div className="ce-resp-grid">
          {items.map((it) => (
            <div key={it.h} style={{ display: "flex", gap: 14 }}>
              <span style={{ width: 40, height: 40, borderRadius: 9, background: "var(--surface-card)", border: "1px solid var(--border-subtle)", color: "var(--brand)", display: "inline-flex", alignItems: "center", justifyContent: "center", flex: "0 0 auto" }}><CIcon name={it.icon} size={19} /></span>
              <div>
                <div style={{ fontFamily: NS, fontWeight: 700, fontSize: 15.5, color: "var(--text-primary)", marginBottom: 5 }}>{it.h}</div>
                <p style={{ fontFamily: NS, fontSize: 14.5, lineHeight: 1.55, color: "var(--text-secondary)", margin: 0 }}>{it.b}</p>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ================================================================
   The page.
================================================================ */
function PageContent({ grid, offices, demoForm, onPick, seedReason, formRef }) {
  return (
    <div>
      <SiteHeader />
      <ContactHero />
      <EnquiryForm seedReason={seedReason} demoState={demoForm} formRef={formRef} />
      <TrialBand />
      <RoutingGrid variant={grid} onPick={onPick} />
      <OfficesBlock variant={offices} />
      <ResponseStrip />
      <SiteFooter />
    </div>
  );
}

/* ---- floating harness ---- */
function Seg({ active, onClick, children }) {
  return (
    <button onClick={onClick} style={{ border: 0, cursor: "pointer", fontFamily: NS, fontSize: 12.5, fontWeight: 700, padding: "6px 11px", borderRadius: 7, background: active ? "var(--brand)" : "transparent", color: active ? "#fff" : "var(--text-secondary)", whiteSpace: "nowrap" }}>{children}</button>
  );
}
function SegGroup({ label, children }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
      <span style={{ fontFamily: NS, fontSize: 10.5, fontWeight: 700, letterSpacing: "0.09em", textTransform: "uppercase", color: "var(--text-muted)" }}>{label}</span>
      <div style={{ display: "flex", gap: 2, background: "var(--surface-sunken)", borderRadius: 9, padding: 3 }}>{children}</div>
    </div>
  );
}
function Harness({ grid, setGrid, offices, setOffices, form, setForm, view, setView }) {
  return (
    <div style={{ position: "fixed", bottom: 16, left: "50%", transform: "translateX(-50%)", zIndex: 100, display: "flex", alignItems: "center", gap: 16, background: "var(--surface-card)", border: "1px solid var(--border-default)", borderRadius: 12, boxShadow: "0 10px 34px rgba(36,33,58,0.2)", padding: "9px 14px", maxWidth: "calc(100vw - 24px)", flexWrap: "wrap", justifyContent: "center" }}>
      <SegGroup label="Grid"><Seg active={grid === "cards"} onClick={() => setGrid("cards")}>Cards</Seg><Seg active={grid === "list"} onClick={() => setGrid("list")}>List</Seg></SegGroup>
      <div style={{ width: 1, height: 22, background: "var(--border-default)" }} />
      <SegGroup label="Offices"><Seg active={offices === "perOffice"} onClick={() => setOffices("perOffice")}>Per office</Seg><Seg active={offices === "global"} onClick={() => setOffices("global")}>Global</Seg></SegGroup>
      <div style={{ width: 1, height: 22, background: "var(--border-default)" }} />
      <SegGroup label="Form"><Seg active={form === "empty"} onClick={() => setForm("empty")}>Empty</Seg><Seg active={form === "error"} onClick={() => setForm("error")}>Error</Seg><Seg active={form === "success"} onClick={() => setForm("success")}>Success</Seg></SegGroup>
      <div style={{ width: 1, height: 22, background: "var(--border-default)" }} />
      <SegGroup label="View"><Seg active={view === "desktop"} onClick={() => setView("desktop")}>Desktop</Seg><Seg active={view === "mobile"} onClick={() => setView("mobile")}>Mobile</Seg></SegGroup>
    </div>
  );
}

function App() {
  const [seedReason, setSeedReason] = React.useState("");
  const formRef = React.useRef();

  const onPick = (reason) => {
    setSeedReason(reason + "|" + Date.now()); // force effect even if same reason picked twice
    if (formRef.current) { const r = formRef.current.getBoundingClientRect(); window.scrollTo({ top: window.scrollY + r.top - 80, behavior: "smooth" }); }
  };
  const cleanReason = seedReason ? seedReason.split("|")[0] : "";

  return (
    <div style={{ minHeight: "100vh", background: "var(--surface-page)" }}>
      <PageContent grid="list" offices="global" demoForm="empty" onPick={onPick} seedReason={cleanReason} formRef={formRef} />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
