/* global React */
// =====================================================================
// Can Tho 2030 — v0.5 shared chrome + building blocks
// Loaded as a Babel script BEFORE each [page]-app.jsx. Everything is
// exported to window; page apps destructure from window at the top.
// =====================================================================
const { useState, useEffect } = React;

// -------------------- Bilingual chrome copy --------------------
const NAV = [
  { en: "Forum",              vi: "Diễn đàn",             href: "Home.html" },
  { en: "Challenges",         vi: "Thách thức",           href: "Challenges.html" },
  { en: "Pitch",              vi: "Đề xuất",              href: "Pitch a Solution.html" },
  { en: "Sponsor",            vi: "Tài trợ",              href: "Sponsor.html" },
  { en: "About",              vi: "Giới thiệu",           href: "About.html" },
  { en: "Contact",            vi: "Liên hệ",              href: "Contact.html" },
];

const CHROME = {
  en: {
    sponsorCta: "Sponsor or Host a Pilot",
    primaryCta: "Request Invitation",
    primaryCtaHref: "Home.html#request-invitation",
    convened: "Convened by TIC × CICT · within the Cần Thơ University ecosystem",
    langNote: null,
    footer: {
      anchorLine: "CICT — the College of Information and Communication Technology — is the institutional partner for Project Cần Thơ 2030 inside Cần Thơ University. TIC operates the programme. Cần Thơ University is the parent academic ecosystem. Government-facing engagement is coordinated through CICT where appropriate.",
      claimNote: "Partners are labelled honestly by engagement status. Any public use of CICT's name or logo will be reviewed by CICT before release.",
      cols: [
        { h: "Programme",   links: [["About","About.html"],["Forum","Home.html"],["For Faculty Leads","Challenges.html#faculty"],["For Community & Residents","Challenges.html#community"],["For Public-Sector Stakeholders","About.html#public-sector"]] },
        { h: "Get involved",links: [["Submit a challenge","Challenges.html"],["Pitch a solution","Pitch a Solution.html"],["Sponsor or Host a Pilot","Sponsor.html"],["Contact","Contact.html"]] },
        { h: "Contact",     links: (window.CT_OFFICES && window.CT_OFFICES.en.footerLinks) || [["hello@cantho2030.com","mailto:hello@cantho2030.com"],["Cần Thơ HQ · Cần Thơ University ecosystem","Contact.html"],["Melbourne — Australia-side coordination","Contact.html"],["Newsletter","Contact.html"]] },
      ],
      brandLine: "Operated by The Improbability Company (TIC) through Magrathea. CICT is the institutional partner inside Cần Thơ University.",
      legalNote: "Vietnam-registered operating entity — coming soon.",
      partnerStrip: {
        heading: "Partners & network",
        rows: [
          { label: "Institutional anchor & operator", items: [["CICT", "Institutional anchor"], ["The Improbability Company (TIC)", "Operator"]] },
          { label: "Education and talent network", items: [["Cần Thơ University"], ["Greenwich University"], ["Swinburne University"]] },
          { label: "Industry anchor partners", items: [["Kinatico"], ["VoltaRocks"]] },
        ],
      },
    },
  },
  vi: {
    sponsorCta: "Tài trợ hoặc Chủ trì Thí điểm",
    primaryCta: "Yêu cầu lời mời",
    primaryCtaHref: "Home.html#request-invitation",
    convened: "Tổ chức bởi TIC × CICT · trong hệ sinh thái Đại học Cần Thơ",
    langNote: "Bản tiếng Việt là bản nháp đang chờ rà soát của các đơn vị liên quan.",
    footer: {
      anchorLine: "CICT — Trường Công nghệ Thông tin và Truyền thông — là đối tác thể chế của Dự án Cần Thơ 2030 trong Đại học Cần Thơ. TIC vận hành chương trình. Đại học Cần Thơ là hệ sinh thái học thuật chủ quản. Việc tiếp xúc với phía chính quyền được điều phối qua CICT khi phù hợp.",
      claimNote: "Các đối tác được ghi nhận trung thực theo mức độ hợp tác. Mọi việc sử dụng công khai tên hoặc logo của CICT sẽ được CICT rà soát trước khi công bố.",
      cols: [
        { h: "Chương trình",  links: [["Giới thiệu","About.html"],["Diễn đàn","Home.html"],["Dành cho Giảng viên","Challenges.html#faculty"],["Dành cho Cộng đồng & Cư dân","Challenges.html#community"],["Dành cho Khối Công lập","About.html#public-sector"]] },
        { h: "Tham gia",      links: [["Đề xuất thách thức","Challenges.html"],["Đề xuất giải pháp","Pitch a Solution.html"],["Tài trợ hoặc Chủ trì Thí điểm","Sponsor.html"],["Liên hệ","Contact.html"]] },
        { h: "Liên hệ",       links: (window.CT_OFFICES && window.CT_OFFICES.vi.footerLinks) || [["hello@cantho2030.com","mailto:hello@cantho2030.com"],["Trụ sở Cần Thơ · hệ sinh thái Đại học Cần Thơ","Contact.html"],["Melbourne — điều phối phía Úc","Contact.html"],["Bản tin","Contact.html"]] },
      ],
      brandLine: "Vận hành bởi The Improbability Company (TIC) thông qua Magrathea. CICT là đối tác thể chế tại Đại học Cần Thơ.",
      legalNote: "Đơn vị vận hành đăng ký tại Việt Nam — sắp công bố.",
      partnerStrip: {
        heading: "Đối tác & mạng lưới",
        rows: [
          { label: "Đối tác thể chế nòng cốt & đơn vị vận hành", items: [["CICT", "Đối tác thể chế nòng cốt"], ["The Improbability Company (TIC)", "Đơn vị vận hành"]] },
          { label: "Mạng lưới giáo dục và nhân tài", items: [["Đại học Cần Thơ"], ["Đại học Greenwich"], ["Đại học Swinburne"]] },
          { label: "Đối tác ngành nòng cốt", items: [["Kinatico"], ["VoltaRocks"]] },
        ],
      },
    },
  },
};

// -------------------- Language sync across pages --------------------
const LANG_KEY = "ct2030-lang";
function useSharedLang(tweaks, setTweak) {
  // On mount, adopt the language stored from a previous page (if any).
  useEffect(() => {
    try {
      const stored = localStorage.getItem(LANG_KEY);
      if (stored && stored !== tweaks.lang) setTweak("lang", stored);
    } catch (e) {}
  }, []); // eslint-disable-line
  const setLang = (l) => {
    try { localStorage.setItem(LANG_KEY, l); } catch (e) {}
    setTweak("lang", l);
  };
  return setLang;
}

// -------------------- Icon set (lucide-style inline) --------------------
const Icon = ({ name, className = "size-4" }) => {
  const p = { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true };
  switch (name) {
    case "arrow-right":   return (<svg {...p}><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>);
    case "arrow-left":    return (<svg {...p}><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg>);
    case "arrow-up-right":return (<svg {...p}><line x1="7" y1="17" x2="17" y2="7"/><polyline points="7 7 17 7 17 17"/></svg>);
    case "external":      return (<svg {...p}><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>);
    case "chevron-right": return (<svg {...p}><polyline points="9 18 15 12 9 6"/></svg>);
    case "chevron-down":  return (<svg {...p}><polyline points="6 9 12 15 18 9"/></svg>);
    case "plus":          return (<svg {...p}><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>);
    case "minus":         return (<svg {...p}><line x1="5" y1="12" x2="19" y2="12"/></svg>);
    case "menu":          return (<svg {...p}><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>);
    case "close":         return (<svg {...p}><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>);
    case "check":         return (<svg {...p}><polyline points="20 6 9 17 4 12"/></svg>);
    case "doc":           return (<svg {...p}><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>);
    case "mail":          return (<svg {...p}><rect x="2" y="4" width="20" height="16" rx="2"/><polyline points="22,6 12,13 2,6"/></svg>);
    case "lock":          return (<svg {...p}><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>);
    case "phone":         return (<svg {...p}><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92z"/></svg>);
    case "pin":           return (<svg {...p}><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>);
    case "users":         return (<svg {...p}><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>);
    case "linkedin":      return (<svg {...p}><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-4 0v7h-4v-7a6 6 0 0 1 6-6z"/><rect x="2" y="9" width="4" height="12"/><circle cx="4" cy="4" r="2"/></svg>);
    case "twitter":       return (<svg {...p}><path d="M4 4l11.5 11.5M20 20L8.5 8.5M20 4L4 20"/></svg>);
    default:              return null;
  }
};

// -------------------- Claim-status badge --------------------
// Four institutional states, muted (not loud).
const CLAIM = {
  confirmed:  { en: "Confirmed",     vi: "Đã xác nhận",   cls: "border-ct-green-300 bg-ct-green-50 text-ct-green-700",  dot: "bg-ct-green-600" },
  discussion: { en: "In discussion", vi: "Đang trao đổi",  cls: "border-ct-gold-300 bg-ct-gold-50 text-ct-gold-800",     dot: "bg-ct-gold-500" },
  proposed:   { en: "Proposed",      vi: "Đề xuất",        cls: "border-ct-indigo-200 bg-ct-indigo-50 text-ct-indigo-800",dot: "bg-ct-indigo-400" },
  future:     { en: "Future pathway",vi: "Hướng tương lai",cls: "border-gray-300 bg-gray-100 text-gray-600",            dot: "bg-gray-400" },
};
const ClaimBadge = ({ status, lang = "en" }) => {
  const c = CLAIM[status] || CLAIM.future;
  return (
    <span className={`inline-flex items-center gap-1.5 rounded-sm border px-2 py-0.5 text-[11px] font-mono tracking-wide ${c.cls}`}>
      <span className={`size-1.5 rounded-full ${c.dot}`}/> {c[lang] || c.en}
    </span>
  );
};

// -------------------- Eyebrow tag --------------------
const Eyebrow = ({ n, children, className = "" }) => (
  <p className={`text-[11px] font-mono tracking-[0.2em] uppercase text-ct-indigo-500 ${className}`}>
    {n && <span className="text-gray-400">§{n} · </span>}{children}
  </p>
);

// -------------------- Decision / call-out box --------------------
const Callout = ({ title, children, className = "" }) => (
  <div className={`rounded-r-md border-l-2 border-ct-gold-500 bg-ct-gold-50/70 px-5 py-4 ${className}`}>
    {title && <p className="text-[11px] font-mono tracking-[0.16em] uppercase text-ct-gold-800 mb-1.5">{title}</p>}
    <div className="text-sm leading-relaxed text-gray-700">{children}</div>
  </div>
);

// -------------------- Stat box --------------------
const StatBox = ({ value, label, source }) => (
  <div className="rounded-lg border border-gray-200 bg-white p-6">
    <p className="text-3xl sm:text-4xl font-semibold tracking-tight text-ct-indigo-900 tabular-nums">{value}</p>
    <p className="mt-2 text-sm leading-snug text-gray-700">{label}</p>
    {source && <p className="mt-3 text-[11px] font-mono tracking-wide text-gray-400">{source}</p>}
  </div>
);

// -------------------- Section heading --------------------
const SectionHeading = ({ children, className = "" }) => (
  <h2 className={`text-3xl font-semibold tracking-tight text-ct-indigo-900 sm:text-4xl text-balance ${className}`}>{children}</h2>
);

// -------------------- Header --------------------
const Header = ({ lang, setLang, current }) => {
  const [scrolled, setScrolled] = useState(false);
  const [open, setOpen] = useState(false);
  const c = CHROME[lang] || CHROME.en;
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 8);
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  return (
    <header data-screen-label="00 Header" className={`sticky top-0 z-50 border-b bg-white/95 backdrop-blur-md transition-shadow ${scrolled ? "border-gray-200 shadow-sm" : "border-gray-100"}`}>
      <div className="mx-auto flex h-16 items-center justify-between gap-4 max-w-7xl px-4 sm:px-6 lg:px-8">
        <a href="Home.html" className="flex items-center gap-2 shrink-0">
          <img src="images/ct2030-logo.svg" alt="Project Cần Thơ 2030" className="h-9 w-auto"/>
        </a>
        <nav className="hidden xl:flex items-center gap-0.5">
          {NAV.map((item) => {
            const active = item.href === current;
            return (
              <a key={item.href} href={item.href}
                 className={`inline-flex items-center min-h-[44px] px-3 text-sm whitespace-nowrap transition-colors ${active ? "text-ct-indigo-900 font-medium" : "text-gray-600 hover:text-ct-indigo-900"}`}>
                {item[lang] || item.en}
              </a>
            );
          })}
        </nav>
        <div className="flex items-center gap-2 sm:gap-3 shrink-0">
          <a href={c.primaryCtaHref || "Home.html#request-invitation"}
             className="hidden sm:inline-flex h-11 items-center gap-2 rounded-md bg-ct-indigo-900 px-4 text-sm font-medium text-white hover:bg-ct-indigo-800 transition-colors">
            {c.primaryCta}<Icon name="arrow-right" className="size-3.5"/>
          </a>
          <div className="flex items-center gap-0.5 text-xs font-mono">
            {[["en","EN"],["vi","VI"]].map(([k,label]) => (
              <button key={k} onClick={() => setLang(k)}
                      className={`inline-flex items-center justify-center min-h-[44px] min-w-[40px] px-2.5 rounded transition-colors ${lang===k ? "bg-ct-indigo-900 text-white" : "text-gray-500 hover:text-ct-indigo-900"}`}>
                {label}
              </button>
            ))}
          </div>
          <button className="xl:hidden p-1.5 text-gray-700" aria-label="Menu" onClick={() => setOpen(o => !o)}>
            <Icon name={open ? "close" : "menu"} className="size-5"/>
          </button>
        </div>
      </div>
      {/* Mobile menu */}
      {open && (
        <div className="xl:hidden border-t border-gray-200 bg-white">
          <nav className="mx-auto max-w-7xl px-4 sm:px-6 py-3 flex flex-col">
            <div className="flex items-center justify-between py-2.5 border-b border-gray-100">
              <span className="text-[11px] font-mono tracking-[0.16em] uppercase text-gray-400">{lang==="vi" ? "Ngôn ngữ" : "Language"}</span>
              <div className="flex items-center gap-0.5 text-xs font-mono">
                {[["en","EN"],["vi","VI"]].map(([k,labelTxt]) => (
                  <button key={k} onClick={() => setLang(k)}
                          className={`inline-flex items-center justify-center min-h-[44px] min-w-[44px] px-2.5 rounded transition-colors ${lang===k ? "bg-ct-indigo-900 text-white" : "text-gray-500 hover:text-ct-indigo-900"}`}>
                    {labelTxt}
                  </button>
                ))}
              </div>
            </div>
            {NAV.map((item) => {
              const active = item.href === current;
              return (
                <a key={item.href} href={item.href}
                   className={`py-2.5 text-base border-b border-gray-100 last:border-0 ${active ? "text-ct-indigo-900 font-medium" : "text-gray-600"}`}>
                  {item[lang] || item.en}
                </a>
              );
            })}
            <a href={c.primaryCtaHref || "Home.html#request-invitation"} className="mt-4 inline-flex h-12 w-full items-center justify-center gap-2 rounded-md bg-ct-indigo-900 text-sm font-medium text-white">
              {c.primaryCta}<Icon name="arrow-right" className="size-4"/>
            </a>
          </nav>
        </div>
      )}
    </header>
  );
};

// -------------------- Framing strip (used on Home) --------------------
const FramingStrip = ({ lang }) => {
  const c = CHROME[lang] || CHROME.en;
  return (
    <section data-screen-label="Framing strip" className="border-b border-gray-200 bg-white py-6">
      <div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 flex flex-col items-center gap-5">
        <div className="flex flex-wrap items-center justify-center gap-x-10 gap-y-3">
          {[
            { mark: "CICT", role: lang==="vi" ? "Đối tác thể chế" : "Institutional partner" },
            { mark: "TIC",  subtext: "The Improbability Company", role: lang==="vi" ? "Đơn vị vận hành" : "Operator" },
            { mark: "Cần Thơ University", role: lang==="vi" ? "Hệ sinh thái chủ quản" : "Parent ecosystem" },
          ].map((logo, i, arr) => (
            <React.Fragment key={logo.mark}>
              <div className="flex items-baseline gap-2 text-ct-indigo-900 whitespace-nowrap">
                <span className="text-base font-semibold tracking-tight">{logo.mark}</span>
                {logo.subtext && <span className="text-[10px] font-mono uppercase tracking-[0.14em] text-gray-400">{logo.subtext}</span>}
                <span className="text-xs font-mono text-gray-500">· {logo.role}</span>
              </div>
              {i < arr.length - 1 && <span className="hidden md:inline-block h-4 w-px bg-gray-300"/>}
            </React.Fragment>
          ))}
        </div>
        <p className="text-[11px] font-mono tracking-[0.18em] text-gray-500 uppercase text-center">{c.convened}</p>
      </div>
    </section>
  );
};

// -------------------- Footer --------------------
const Footer = ({ lang }) => {
  const c = CHROME[lang] || CHROME.en;
  const f = c.footer;
  return (
    <footer data-screen-label="Footer" className="bg-ct-indigo-900 text-white py-12 lg:py-16">
      <div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
        <p className="max-w-3xl text-sm leading-relaxed text-white/85">{f.anchorLine}</p>
        <p className="mt-4 max-w-3xl text-xs leading-relaxed text-white/70 font-mono">{f.claimNote}</p>

        {f.partnerStrip && (
          <div className="mt-10 border-t border-white/12 pt-8">
            <p className="text-[11px] font-mono tracking-[0.18em] uppercase text-ct-gold-300">{f.partnerStrip.heading}</p>
            <div className="mt-5 space-y-4">
              {f.partnerStrip.rows.map((row, i) => (
                <div key={i} className="flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-5">
                  <span className="shrink-0 sm:w-64 text-[10px] font-mono tracking-[0.16em] uppercase text-white/45">{row.label}</span>
                  <div className="flex flex-wrap items-center gap-2">
                    {row.items.map((it, j) => (
                      <span key={j} className="inline-flex items-baseline gap-1.5 rounded-md border border-white/15 bg-white/[0.04] px-3 py-1.5">
                        <span className="text-sm font-semibold tracking-tight text-white whitespace-nowrap">{it[0]}</span>
                        {it[1] && <span className="text-[10px] font-mono uppercase tracking-wide text-ct-gold-300/80 whitespace-nowrap">{it[1]}</span>}
                      </span>
                    ))}
                  </div>
                </div>
              ))}
            </div>
          </div>
        )}

        <div className="mt-12 grid grid-cols-2 gap-8 md:grid-cols-3">
          {f.cols.map((col, i) => (
            <div key={i}>
              <p className="text-[11px] font-mono tracking-[0.18em] uppercase text-ct-gold-300">{col.h}</p>
              <ul className="mt-4 space-y-2.5">
                {col.links.map((link, j) => (
                  <li key={j}><a href={link[1]} className="inline-flex items-center min-h-[40px] py-1 text-sm text-white/75 hover:text-white transition-colors">{link[0]}</a></li>
                ))}
              </ul>
            </div>
          ))}
        </div>

        {c.langNote && <p className="mt-10 text-xs italic text-ct-gold-200/80">{c.langNote}</p>}

        <div className="mt-10 pt-6 border-t border-white/15 flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
          <div>
            <p className="text-xs text-white/55">© {new Date().getFullYear()} Project Cần Thơ 2030 — Dự án Cần Thơ 2030</p>
            <p className="text-xs leading-relaxed text-white/75 mt-1 max-w-2xl">{f.brandLine}</p>
            <p className="text-[11px] italic text-white/55 mt-1">{f.legalNote}</p>
          </div>
          <div className="flex items-center gap-2">
            {[{icon:"linkedin",label:"LinkedIn"},{icon:"twitter",label:"X / Twitter"},{icon:"mail",label:"Newsletter"}].map(s => (
              <a key={s.icon} href="#" aria-label={`${s.label} — coming soon`} title={`${s.label} — coming soon`}
                 className="size-9 rounded-md border border-white/15 bg-white/[0.03] flex items-center justify-center text-white/60 hover:text-white hover:bg-white/10 transition-colors">
                <Icon name={s.icon} className="size-4"/>
              </a>
            ))}
            <span className="ml-1 text-[10px] font-mono tracking-wider text-white/55 uppercase">{lang==="vi" ? "sắp ra mắt" : "coming soon"}</span>
          </div>
        </div>
      </div>
    </footer>
  );
};

// -------------------- Page hero (breadcrumb + title + lede) --------------------
const PageHero = ({ lang, breadcrumb, eyebrow, title, lede, archLine, tone = "light" }) => {
  const dark = tone === "dark";
  return (
    <section data-screen-label="Page hero" className={dark ? "bg-ct-indigo-900 text-white" : "bg-gray-50 border-b border-gray-200"}>
      <div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-16 lg:py-20">
        {breadcrumb && (
          <nav aria-label="Breadcrumb" className={`flex items-center gap-2 text-xs font-mono tracking-wide uppercase mb-6 ${dark ? "text-white/55" : "text-gray-500"}`}>
            {breadcrumb.map((b, i) => (
              <React.Fragment key={i}>
                {i > 0 && <Icon name="chevron-right" className="size-3.5 opacity-50"/>}
                {b[1] ? <a href={b[1]} className="hover:text-ct-gold-400">{b[0]}</a> : <span className={dark ? "text-ct-gold-300" : "text-ct-indigo-900"}>{b[0]}</span>}
              </React.Fragment>
            ))}
          </nav>
        )}
        {eyebrow && <Eyebrow className={dark ? "text-ct-gold-300 mb-4" : "mb-4"}>{eyebrow}</Eyebrow>}
        <h1 className={`text-3xl font-semibold tracking-tight sm:text-4xl lg:text-5xl text-balance leading-[1.12] ${dark ? "text-white" : "text-ct-indigo-900"}`}>{title}</h1>
        {archLine && <p className={`mt-6 max-w-3xl text-base font-medium leading-relaxed text-balance ${dark ? "text-ct-gold-200" : "text-ct-indigo-800"}`}>{archLine}</p>}
        {lede && <p className={`mt-4 max-w-3xl text-lg leading-relaxed ${dark ? "text-white/85" : "text-gray-700"}`}>{lede}</p>}
      </div>
    </section>
  );
};

// -------------------- CTA strip (sponsor + prospectus) --------------------
const CtaStrip = ({ lang }) => {
  const t = lang === "vi"
    ? { h: "Mở cả hai phía của vòng lặp", sub: "Đề xuất một thách thức, đề xuất một giải pháp, hoặc hậu thuẫn một Sprint với vai trò nhà tài trợ.", a: "Tài trợ hoặc Chủ trì Thí điểm", b: "Đề xuất một thách thức", c: "Đề xuất một giải pháp" }
    : { h: "Open both sides of the loop", sub: "Submit a challenge, pitch a solution, or back a 90-day Sprint as a sponsor.", a: "Sponsor or Host a Pilot", b: "Submit a challenge", c: "Pitch a solution" };
  return (
    <section data-screen-label="CTA strip" className="bg-ct-indigo-900 text-white py-16 lg:py-20">
      <div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 flex flex-col lg:flex-row lg:items-center lg:justify-between gap-8">
        <div className="max-w-2xl">
          <h2 className="text-2xl sm:text-3xl font-semibold tracking-tight text-balance">{t.h}</h2>
          <p className="mt-3 text-white/80 leading-relaxed">{t.sub}</p>
        </div>
        <div className="flex flex-col sm:flex-row gap-3 shrink-0">
          <a href="Sponsor.html" className="inline-flex h-11 items-center justify-center gap-2 rounded-md bg-ct-gold-400 px-5 text-sm font-medium text-ct-indigo-900 hover:bg-ct-gold-300 transition-colors">
            {t.a}<Icon name="arrow-right" className="size-4"/>
          </a>
          <a href="Challenges.html" className="inline-flex h-11 items-center justify-center gap-2 rounded-md border border-white/30 px-5 text-sm font-medium text-white hover:bg-white/10 transition-colors">
            {t.b}<Icon name="arrow-right" className="size-4"/>
          </a>
          <a href="Pitch a Solution.html" className="inline-flex h-11 items-center justify-center gap-2 rounded-md border border-white/30 px-5 text-sm font-medium text-white hover:bg-white/10 transition-colors">
            {t.c}<Icon name="arrow-right" className="size-4"/>
          </a>
        </div>
      </div>
    </section>
  );
};

// -------------------- Generic Tweaks mount (lang only; pages can extend) --------------------
const LangTweak = ({ lang, setLang }) => {
  if (!window.TweaksPanel) return null;
  const { TweakSection, TweakRadio } = window;
  return (
    <TweakSection label="Language">
      <TweakRadio label="Display" value={lang}
                  options={[{value:"en",label:"EN"},{value:"vi",label:"VI"}]}
                  onChange={setLang}/>
    </TweakSection>
  );
};

// -------------------- Sprint progress tracker (Define · Staff · Build · Show · Pilot or progress) --------------------
const SPRINT_STEPS = {
  en: ["Define", "Staff", "Build", "Show", "Pilot or progress"],
  vi: ["Xác định", "Bố trí", "Xây dựng", "Trình diễn", "Thí điểm hoặc tiến tới"],
};
const SprintProgress = ({ lang = "en", active = 0, caption }) => {
  const steps = SPRINT_STEPS[lang] || SPRINT_STEPS.en;
  return (
    <div className="mb-6">
      <div className="flex items-center gap-1.5 sm:gap-2 flex-wrap">
        {steps.map((s, i) => (
          <React.Fragment key={i}>
            <span className={`inline-flex items-center gap-1.5 text-[11px] font-mono tracking-wide uppercase ${i === active ? "text-ct-gold-800 font-medium" : "text-gray-400"}`}>
              <span className={`size-2 rounded-full ${i === active ? "bg-ct-gold-500 ring-2 ring-ct-gold-200" : "bg-gray-300"}`}/>{s}
            </span>
            {i < steps.length - 1 && <span className="h-px w-3 sm:w-4 bg-gray-200"/>}
          </React.Fragment>
        ))}
      </div>
      {caption && <p className="mt-2.5 text-sm text-gray-600">{caption}</p>}
    </div>
  );
};

// -------------------- Standardised "what happens after you submit" block --------------------
const AFTER = {
  en: { h: "What happens after you submit", steps: ["Anh Phan (Project Lead) reviews every submission personally — within 2 weeks.", "If relevant, we contact you to shape the brief, pitch, or partnership.", "CICT + TIC decide whether it enters review, sprint, forum, or archive.", "Submission does not guarantee selection."] },
  vi: { h: "Sau khi bạn gửi", steps: ["Anh Phan (Trưởng dự án) đích thân rà soát mọi đề xuất — trong vòng 2 tuần.", "Nếu phù hợp, chúng tôi liên hệ để cùng định hình đề bài, đề xuất hoặc hợp tác.", "CICT + TIC quyết định đưa vào rà soát, sprint, diễn đàn, hay lưu trữ.", "Việc gửi không đảm bảo được chọn."] },
};
const AfterSubmit = ({ lang = "en" }) => {
  const a = AFTER[lang] || AFTER.en;
  return (
    <div className="mt-7 rounded-md border border-ct-indigo-200 bg-ct-indigo-50/50 p-5">
      <p className="text-[11px] font-mono tracking-[0.16em] uppercase text-ct-indigo-800 mb-3">{a.h}</p>
      <ol className="space-y-2">
        {a.steps.map((s, i) => (
          <li key={i} className="flex gap-2.5 text-sm leading-6 text-gray-700">
            <span className="shrink-0 font-mono text-xs text-ct-indigo-700 mt-0.5">{i + 1}</span>{s}
          </li>
        ))}
      </ol>
    </div>
  );
};

// -------------------- Universal form microcopy (5–7 min · non-confidential · 2-week review · no fee) --------------------
const FORM_INTRO = {
  en: "Takes 5–7 minutes. Submit a non-confidential summary only. We review within 2 weeks. No fee.",
  vi: "Mất 5–7 phút. Chỉ gửi bản tóm tắt không bảo mật. Chúng tôi rà soát trong vòng 2 tuần. Miễn phí.",
};
const FormIntro = ({ lang = "en", className = "" }) => (
  <p className={`flex items-start gap-2.5 rounded-md border border-ct-green-200 bg-ct-green-50/60 px-4 py-3 text-sm leading-6 text-ct-green-900 ${className}`}>
    <span className="mt-1.5 size-1.5 shrink-0 rounded-full bg-ct-green-600"/>
    <span>{FORM_INTRO[lang] || FORM_INTRO.en}</span>
  </p>
);

// -------------------- Request the Sponsor Prospectus (lang-aware structured mailto) --------------------
const PROSPECTUS_EMAIL = "hello@cantho2030.com";
const RequestProspectus = ({ lang = "en", tier, variant = "link", className = "" }) => {
  const label = lang === "vi" ? "Yêu cầu Hồ sơ Tài trợ" : "Request the Sponsor Prospectus";
  const subject = "[CT2030 Sponsor] Prospectus request";
  const bodyLine = tier
    ? (lang === "vi" ? `Quan tâm: ${tier}` : `Interested in: ${tier}`)
    : "";
  const href = `mailto:${PROSPECTUS_EMAIL}?subject=${encodeURIComponent(subject)}${bodyLine ? "&body=" + encodeURIComponent(bodyLine) : ""}`;
  if (variant === "button") {
    return (
      <a href={href} className={`inline-flex h-9 items-center justify-center gap-1.5 rounded-md px-3 text-sm font-medium transition-colors ${className}`}>
        {label}<Icon name="arrow-right" className="size-3.5"/>
      </a>
    );
  }
  return (
    <a href={href} className={`inline-flex items-center gap-1.5 text-sm font-medium hover:gap-2.5 transition-all ${className}`}>
      {label}<Icon name="arrow-right" className="size-3.5"/>
    </a>
  );
};

// -------------------- Talk-first secondary CTA (lang-aware, side-routed) --------------------
// Persistent "prefer to talk first" anchor that lives directly above every form.
// sideHint: "vn" → Anh Phan · "au" → Oz Omegna · "both" → both named options.
const TALK_EMAIL = "hello@cantho2030.com";
const TALK_COPY = {
  en: {
    lead: "Prefer to talk first?",
    sub: "Many partners start with a short call instead of the form — no commitment.",
    book: "Book a 20-min call",
    withName: (n) => `Book a 20-min call with ${n}`,
    anh: { name: "Anh Phan", role: "Cần Thơ / CICT liaison" },
    oz:  { name: "Oz Omegna", role: "Australia lead" },
  },
  vi: {
    lead: "Muốn trao đổi trước?",
    sub: "Nhiều đối tác bắt đầu bằng một cuộc gọi ngắn thay vì biểu mẫu — không ràng buộc.",
    book: "Đặt lịch gọi 20 phút",
    withName: (n) => `Đặt lịch gọi 20 phút với ${n}`,
    anh: { name: "Anh Phan", role: "Đầu mối Cần Thơ / CICT" },
    oz:  { name: "Oz Omegna", role: "Phụ trách Úc" },
  },
};
const talkHref = (page, who) => {
  const subj = `[CT2030 Discovery Call] — ${page}`;
  const body = who ? (who === "vi-anh" ? "" : "") : "";
  return `mailto:${TALK_EMAIL}?subject=${encodeURIComponent(subj)}${who ? "&body=" + encodeURIComponent(who) : ""}`;
};
const TalkFirstCTA = ({ lang = "en", sideHint = "both", page = "Website", className = "" }) => {
  const c = TALK_COPY[lang] || TALK_COPY.en;
  const subj = encodeURIComponent(`[CT2030 Discovery Call] — ${page}`);
  const mk = (person) => `mailto:${TALK_EMAIL}?subject=${subj}&body=${encodeURIComponent((lang === "vi" ? "Liên hệ ưu tiên: " : "Preferred contact: ") + person.name)}`;
  const btn = "inline-flex h-10 items-center justify-center gap-1.5 rounded-md px-4 text-sm font-medium transition-colors";
  return (
    <div className={`rounded-md border border-ct-indigo-200 bg-ct-indigo-50/60 px-4 py-3.5 sm:px-5 sm:py-4 ${className}`}>
      <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
        <div className="flex items-start gap-2.5">
          <Icon name="phone" className="size-4 shrink-0 text-ct-indigo-700 mt-0.5"/>
          <p className="text-sm leading-6 text-ct-indigo-900">
            <span className="font-semibold italic">{c.lead}</span>{" "}
            <span className="text-ct-indigo-800/80">{c.sub}</span>
          </p>
        </div>
        <div className="flex flex-wrap gap-2 shrink-0 sm:justify-end">
          {sideHint === "both" ? (
            <>
              <a href={mk(c.anh)} className={`${btn} bg-ct-indigo-900 text-white hover:bg-ct-indigo-800`}>{c.anh.name}<Icon name="arrow-right" className="size-3.5"/></a>
              <a href={mk(c.oz)} className={`${btn} border border-ct-indigo-900/25 text-ct-indigo-900 hover:bg-ct-indigo-900 hover:text-white`}>{c.oz.name}<Icon name="arrow-right" className="size-3.5"/></a>
            </>
          ) : (
            <a href={mk(sideHint === "au" ? c.oz : c.anh)} className={`${btn} bg-ct-indigo-900 text-white hover:bg-ct-indigo-800`}>
              {c.withName(sideHint === "au" ? c.oz.name : c.anh.name)}<Icon name="arrow-right" className="size-3.5"/>
            </a>
          )}
        </div>
      </div>
    </div>
  );
};

// -------------------- IP / confidentiality safety badge (lang-aware, per form type) --------------------
const IP_COPY = {
  en: {
    challenge: { label: "Confidentiality", body: "Submit a non-confidential summary only. CICT + TIC operate under standard NDA terms with selected partners. Public listing requires your written consent." },
    pitch:     { label: "IP protection", body: "Do not submit confidential technical details, code, or proprietary methods through this form. Selected solutions enter a standard NDA framework before any Sprint work begins." },
    host:      { label: "Confidentiality", body: "Share only non-sensitive details here. Pilot scope, data access, and any disclosure are co-designed under NDA before any commitment." },
    sponsor:   { label: "Confidentiality", body: "Share only non-confidential information here. Sponsor terms and any attribution are confirmed in writing before release." },
  },
  vi: {
    challenge: { label: "Bảo mật", body: "Chỉ gửi bản tóm tắt không bảo mật. CICT + TIC làm việc theo điều khoản NDA tiêu chuẩn với các đối tác được chọn. Việc công bố cần sự đồng ý bằng văn bản của bạn." },
    pitch:     { label: "Bảo vệ sở hữu trí tuệ", body: "Đừng gửi chi tiết kỹ thuật bảo mật, mã nguồn hay phương pháp độc quyền qua biểu mẫu này. Các giải pháp được chọn sẽ vào khung NDA tiêu chuẩn trước khi bắt đầu Sprint." },
    host:      { label: "Bảo mật", body: "Chỉ chia sẻ thông tin không nhạy cảm tại đây. Phạm vi thí điểm, quyền truy cập dữ liệu và mọi tiết lộ được cùng thiết kế theo NDA trước khi cam kết." },
    sponsor:   { label: "Bảo mật", body: "Chỉ chia sẻ thông tin không bảo mật tại đây. Điều khoản tài trợ và mọi ghi nhận được xác nhận bằng văn bản trước khi công bố." },
  },
};
const IPSafetyBadge = ({ lang = "en", formType = "challenge", className = "" }) => {
  const set = IP_COPY[lang] || IP_COPY.en;
  const c = set[formType] || set.challenge;
  return (
    <div className={`flex items-start gap-3 rounded-md border border-ct-gold-300 bg-ct-gold-50/70 px-4 py-3 ${className}`}>
      <span className="mt-0.5 inline-flex size-6 shrink-0 items-center justify-center rounded-md bg-ct-gold-100 text-ct-gold-800">
        <Icon name="lock" className="size-3.5"/>
      </span>
      <p className="text-sm leading-6 text-ct-gold-900">
        <span className="font-semibold">{c.label}:</span> {c.body}
      </p>
    </div>
  );
};

// -------------------- "Why bother" lede block (Challenges / Pitch / Sponsor) --------------------
const WhyBother = ({ eyebrow, children, tone = "light" }) => (
  <section data-screen-label="Why bother" className={`border-b py-14 lg:py-16 ${tone === "gray" ? "bg-gray-50 border-gray-200" : "bg-white border-gray-200"}`}>
    <div className="mx-auto max-w-3xl px-4 sm:px-6 lg:px-8">
      <Eyebrow>{eyebrow}</Eyebrow>
      <p className="mt-4 text-lg leading-relaxed text-gray-700 text-pretty">{children}</p>
    </div>
  </section>
);

Object.assign(window, {
  NAV, CHROME, useSharedLang, Icon, CLAIM, ClaimBadge, Eyebrow, Callout,
  StatBox, SectionHeading, Header, Footer, FramingStrip, PageHero, CtaStrip, LangTweak,
  SprintProgress, AfterSubmit, FormIntro, RequestProspectus, TalkFirstCTA, IPSafetyBadge, WhyBother,
});
