/* =========================================================================
   App — Zhijie Tan personal site (Dark / Light, bilingual)
   ========================================================================= */

const { useState, useEffect, useCallback } = React;

/* ---------- Icons --------------------------------------------------------- */

const Icon = {
  Globe: () => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <circle cx="12" cy="12" r="10"/>
      <path d="M2 12h20"/>
      <path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/>
    </svg>
  ),
  MapPin: () => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <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"/>
    </svg>
  ),
  Phone: () => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <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>
  ),
  Mail: () => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <rect x="2.5" y="4.5" width="19" height="15" rx="2"/>
      <path d="M3 6l9 7 9-7"/>
    </svg>
  ),
  Languages: () => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <path d="M5 8l6 6"/><path d="M4 14l6-6 2-3"/><path d="M2 5h12"/><path d="M7 2h1"/>
      <path d="M22 22l-5-10-5 10"/><path d="M14 18h6"/>
    </svg>
  ),
  Share: () => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/>
      <line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/>
    </svg>
  ),
  Copy: () => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <rect x="9" y="9" width="13" height="13" rx="2"/>
      <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
    </svg>
  ),
  Check: () => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <polyline points="20 6 9 17 4 12"/>
    </svg>
  ),
  Close: () => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
    </svg>
  ),
  Menu: () => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <line x1="4" y1="7" x2="20" y2="7"/>
      <line x1="4" y1="12" x2="20" y2="12"/>
      <line x1="4" y1="17" x2="20" y2="17"/>
    </svg>
  ),
  Sun: () => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <circle cx="12" cy="12" r="4"/>
      <path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/>
    </svg>
  ),
  Moon: () => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
    </svg>
  ),
  LinkedIn: () => (
    <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
      <path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z"/>
    </svg>
  ),
  Instagram: () => (
    <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
      <path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/>
    </svg>
  ),
  Facebook: () => (
    <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
      <path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.469h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.469h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
    </svg>
  ),
  WeChat: () => (
    <svg viewBox="0 0 1024 1024" fill="currentColor" aria-hidden="true">
      <path d="M685.2 399.7c-17.6 0-34.5 1.6-50.6 4.7C596.5 284 466.8 192 313.3 192 140.3 192 0 308.2 0 451.7c0 80.6 44.5 152.6 114.6 201l-29.6 89.2 103.5-52.7c39.6 11.2 81 17.2 124.8 17.2 10.6 0 20.9-0.4 31.4-1-6.1-20.2-9.5-41.5-9.5-63.7 0-133 125.7-240.8 280.9-240.8-21.7-0.7-10.9-1.4 69.1 0z m-464.7-44.5c-23 0-41.6-18.6-41.6-41.6s18.6-41.6 41.6-41.6 41.6 18.6 41.6 41.6-18.7 41.6-41.6 41.6z m232.7 0c-23 0-41.6-18.6-41.6-41.6s18.6-41.6 41.6-41.6 41.6 18.6 41.6 41.6-18.6 41.6-41.6 41.6z"/>
      <path d="M1024 642.3c0-111-105-201-234.4-201s-234.4 90-234.4 201 105 201 234.4 201c31.1 0 60.8-6.1 88-16.8l77.4 41.6-20.4-69.2c56.4-38.3 93.8-95 93.8-156.6z m-322.9-28c-17.2 0-31.2-14-31.2-31.2s14-31.2 31.2-31.2 31.2 14 31.2 31.2-14 31.2-31.2 31.2z m177 0c-17.2 0-31.2-14-31.2-31.2s14-31.2 31.2-31.2 31.2 14 31.2 31.2-14 31.2-31.2 31.2z"/>
    </svg>
  ),
};

/* ---------- Content ------------------------------------------------------- */

const CONTENT = {
  en: {
    eyebrow: "Financial Professional",
    name: "Zhijie Tan",
    nameZh: "",
    titlePart1: "FINRA Registered Representative",
    titlePart2: "Transamerica Financial Advisors, Inc.",
    licenses: [
      "NY Insurance License #1588714",
      "CT Insurance License #19418685",
      "TX Insurance License #3455701",
    ],
    contact: {
      website: "Website",
      office: "Office",
      mobile: "Mobile",
      email: "Email",
      languages: "Languages",
      languagesValue: "English · Mandarin · Cantonese",
    },
    socialLabel: "Follow me on social media",
    menuItems: [
      { label: "COMPANY",          href: "https://financialprofessional.tfaconnects.com/zhijie-tan" },
      { label: "PRODUCT CARRIERS", href: "https://www.tfaconnect.com/learn" },
      { label: "MY BROKERAGE",     href: "https://www.tfaconnect.com/about" },
    ],
    disclaimer: "Securities offered through Transamerica Financial Advisors, Inc. (TFA) — Member FINRA, MSRB, and SIPC.",
    copied: "Copied to clipboard",
    wechatTitle: "WeChat",
    wechatHint: "Scan to add me on WeChat",
    langButton: "中文",
    menuTitle: "Menu",
  },
  zh: {
    eyebrow: "财务专业人士",
    name: "Zhijie Tan",
    nameZh: "谭智杰",
    titlePart1: "FINRA 证券注册代表",
    titlePart2: "Transamerica Financial Advisors, Inc.",
    licenses: [
      "纽约州保险执照 #1588714",
      "康州保险执照 #19418685",
      "德州保险执照 #3455701",
    ],
    contact: {
      website: "官方网站",
      office: "办公室",
      mobile: "手机",
      email: "电子邮件",
      languages: "语言",
      languagesValue: "普通话 · 广东话 · 英文",
    },
    socialLabel: "欢迎在社交媒体关注我喔！",
    menuItems: [
      { label: "公司",       href: "https://financialprofessional.tfaconnects.com/zhijie-tan" },
      { label: "产品合作方", href: "https://www.tfaconnect.com/learn" },
      { label: "我的所属券商", href: "https://www.tfaconnect.com/about" },
    ],
    disclaimer: "证券服务由 Transamerica Financial Advisors, Inc. (TFA) 提供 — Member FINRA, MSRB, and SIPC.",
    copied: "已复制到剪贴板",
    wechatTitle: "微信",
    wechatHint: "扫一扫加我微信",
    langButton: "English",
    menuTitle: "菜单",
  },
};

const FIXED = {
  website:     "financialprofessional.tfaconnects.com/zhijie-tan",
  websiteHref: "https://financialprofessional.tfaconnects.com/zhijie-tan",
  office:      "37-20 Prince St. Suite 2A, Flushing, NY 11354",
  officeMapHref: "https://maps.google.com/?q=37-20+Prince+St+Suite+2A+Flushing+NY+11354",
  mobile:      "(646) 288-7870",
  mobileHref:  "tel:+16462887870",
  email:       "Zhijie.Tan@TFAconnect.com",
  emailHref:   "mailto:Zhijie.Tan@TFAconnect.com",
  socials: {
    linkedin:  "https://www.linkedin.com/in/zhijietan/",
    instagram: "https://www.instagram.com/zhijie.us/",
    facebook:  "https://www.facebook.com/Zhijietan2019",
    wechat:    "#",
  },
};

/* ---------- Subcomponents ------------------------------------------------- */

function CopyButton({ text, onCopied, ariaLabel }) {
  const [copied, setCopied] = useState(false);
  const onClick = async (e) => {
    e.preventDefault();
    e.stopPropagation();
    try { await navigator.clipboard.writeText(text); }
    catch (_) {
      const ta = document.createElement("textarea");
      ta.value = text;
      document.body.appendChild(ta);
      ta.select();
      try { document.execCommand("copy"); } catch (_) {}
      ta.remove();
    }
    setCopied(true);
    onCopied?.();
    setTimeout(() => setCopied(false), 1800);
  };
  return (
    <button className="copy-btn" onClick={onClick} aria-label={ariaLabel} title={ariaLabel}>
      {copied ? <Icon.Check /> : <Icon.Copy />}
    </button>
  );
}

function ContactRow({ icon, label, children }) {
  return (
    <li className="contact-row">
      <span className="contact-icon">{icon}</span>
      <span className="contact-label">{label}</span>
      <span className="contact-value">{children}</span>
    </li>
  );
}

function SocialLink({ network, href, label, onClick }) {
  const iconMap = {
    linkedin:  <Icon.LinkedIn />,
    instagram: <Icon.Instagram />,
    facebook:  <Icon.Facebook />,
    wechat:    <Icon.WeChat />,
  };
  const isWechat = network === "wechat";
  return (
    <a
      className="social-link"
      data-network={network}
      href={isWechat ? "#wechat" : href}
      target={isWechat ? "_self" : "_blank"}
      rel="noopener noreferrer"
      title={label}
      aria-label={label}
      onClick={(e) => { if (isWechat) { e.preventDefault(); onClick?.(); } }}
    >
      {iconMap[network]}
    </a>
  );
}

function WeChatModal({ open, onClose, t }) {
  useEffect(() => {
    if (!open) return;
    const onKey = (e) => e.key === "Escape" && onClose();
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal-card" onClick={(e) => e.stopPropagation()}>
        <h3>{t.wechatTitle}</h3>
        <p>{t.wechatHint}</p>
        <div className="qr-box"><img src="./images/wechat-qr.png" alt="WeChat QR Code" width="180" height="180" style={{objectFit:"contain"}} /></div>
        <button className="modal-close" onClick={onClose}>
          <Icon.Close /> Close
        </button>
      </div>
    </div>
  );
}

function PlaceholderQR() {
  const cells = [];
  for (let r = 0; r < 21; r++) {
    for (let c = 0; c < 21; c++) {
      const inFinder = ((r < 7 && c < 7) || (r < 7 && c > 13) || (r > 13 && c < 7));
      let fill;
      if (inFinder) {
        const inOuter = (r === 0 || r === 6 || c === 0 || c === 6) ||
                        (r > 13 ? (r === 14 || r === 20 || c === 0 || c === 6) : false) ||
                        (c > 13 ? (c === 14 || c === 20 || r === 0 || r === 6) : false);
        const inInner = (r >= 2 && r <= 4 && c >= 2 && c <= 4) ||
                        (r >= 2 && r <= 4 && c >= 16 && c <= 18) ||
                        (r >= 16 && r <= 18 && c >= 2 && c <= 4);
        fill = inInner || inOuter;
      } else {
        fill = ((r * 7 + c * 13 + r * c) % 5) < 2;
      }
      if (fill) cells.push(<rect key={`${r}-${c}`} x={c} y={r} width="1" height="1" fill="#0F2A1A"/>);
    }
  }
  return (
    <svg viewBox="0 0 21 21" width="180" height="180" style={{ shapeRendering: "crispEdges" }}>
      <rect width="21" height="21" fill="#fff" />
      {cells}
      <circle cx="10.5" cy="10.5" r="2.6" fill="#fff" />
      <circle cx="10.5" cy="10.5" r="2.1" fill="#07C160" />
    </svg>
  );
}

function Toast({ message }) {
  if (!message) return null;
  return (
    <div className="toast" key={message.id}>
      <span className="toast-dot" />
      {message.text}
    </div>
  );
}

/* ---------- Background ornament ------------------------------------------ */

function BgOrnament() {
  // Removed per request — user wants a single uniform background.
  return null;
}

/* ---------- Header chrome ------------------------------------------------- */

function HeaderActions({ lang, mode, onToggleLang, onToggleMode, t }) {
  return (
    <div className="header-actions">
      <button
        className="header-btn icon-only"
        onClick={onToggleMode}
        aria-label={mode === "dark" ? "Switch to light mode" : "Switch to dark mode"}
        title={mode === "dark" ? "Switch to light mode" : "Switch to dark mode"}
      >
        {mode === "dark" ? <Icon.Sun /> : <Icon.Moon />}
      </button>
      <button
        className="header-btn"
        onClick={onToggleLang}
        aria-label="Toggle language"
      >
        <Icon.Globe />
        <span>{t.langButton}</span>
      </button>
    </div>
  );
}

/* ---------- Mobile menu drawer ------------------------------------------- */

function MobileMenu({ open, onClose, t, lang, mode, onToggleLang, onToggleMode }) {
  useEffect(() => {
    if (!open) return;
    document.body.style.overflow = "hidden";
    const onKey = (e) => e.key === "Escape" && onClose();
    window.addEventListener("keydown", onKey);
    return () => {
      document.body.style.overflow = "";
      window.removeEventListener("keydown", onKey);
    };
  }, [open, onClose]);

  return (
    <nav className={"mobile-menu " + (open ? "is-open" : "")} aria-hidden={!open}>
      <div className="mobile-menu-top">
        <span style={{ fontFamily: "var(--font-display)", color: "var(--accent)", letterSpacing: "0.16em", fontSize: 14, textTransform: "uppercase" }}>
          {t.menuTitle}
        </span>
        <button className="header-btn icon-only" onClick={onClose} aria-label="Close menu">
          <Icon.Close />
        </button>
      </div>
      <ul className="mobile-menu-items">
        {t.menuItems.map((item, i) => (
          <li key={i}>
            <a href={item.href} target="_blank" rel="noopener noreferrer" onClick={onClose}>
              {item.label}
            </a>
          </li>
        ))}
      </ul>
      <div className="mobile-menu-foot">
        <button className="header-btn" onClick={onToggleMode}>
          {mode === "dark" ? <Icon.Sun /> : <Icon.Moon />}
          <span>{mode === "dark" ? "Light" : "Dark"}</span>
        </button>
        <button className="header-btn" onClick={onToggleLang}>
          <Icon.Globe />
          <span>{t.langButton}</span>
        </button>
      </div>
    </nav>
  );
}

/* ---------- App ----------------------------------------------------------- */

function App() {
  const initialTweaks = window.__TWEAKS_DEFAULTS || { mode: "dark", fontScale: 1 };
  // Migrate any legacy "direction" key from earlier builds.
  if (initialTweaks.direction && !initialTweaks.mode) {
    initialTweaks.mode = initialTweaks.direction === "light" ? "light" : "dark";
  }
  // Force mode into one of the two valid values
  if (initialTweaks.mode !== "light") initialTweaks.mode = "dark";

  const [tweaks, setTweak] = useTweaks(initialTweaks);

  const [lang, setLang] = useState("zh");
  const [langFading, setLangFading] = useState(false);
  const [wechatOpen, setWechatOpen] = useState(false);
  const [menuOpen, setMenuOpen] = useState(false);
  const [toast, setToast] = useState(null);

  const t = CONTENT[lang];
  const mode = tweaks.mode === "light" ? "light" : "dark";

  useEffect(() => {
    document.documentElement.dataset.theme = mode;
    document.documentElement.style.setProperty("--font-scale", tweaks.fontScale || 1);
    document.documentElement.lang = lang === "zh" ? "zh-Hans" : "en";
  }, [mode, tweaks.fontScale, lang]);

  const toggleLang = useCallback(() => {
    setLangFading(true);
    setTimeout(() => {
      setLang((prev) => (prev === "zh" ? "en" : "zh"));
      setTimeout(() => setLangFading(false), 30);
    }, 240);
  }, []);

  const toggleMode = useCallback(() => {
    setTweak("mode", mode === "dark" ? "light" : "dark");
  }, [mode, setTweak]);

  const showToast = useCallback((text) => {
    setToast({ text, id: Date.now() });
    setTimeout(() => setToast(null), 2200);
  }, []);

  const onCopied = () => showToast(CONTENT[lang].copied);

  // Social order — WeChat first when Chinese
  const socialOrder = lang === "zh"
    ? ["wechat", "linkedin", "instagram", "facebook"]
    : ["linkedin", "instagram", "facebook", "wechat"];

  const socialLabels = {
    linkedin:  "LinkedIn",
    instagram: "Instagram",
    facebook:  "Facebook",
    wechat:    lang === "zh" ? "微信" : "WeChat",
  };

  return (
    <div className="app-shell">
      <BgOrnament />

      <header className="site-header">
        {/* Phone: hamburger menu trigger. No mark on desktop — keeps layout clean. */}
        <button className="brand-mark hamburger" type="button" aria-label="Open menu" onClick={() => setMenuOpen(true)}>
          <Icon.Menu />
        </button>

        <HeaderActions
          lang={lang}
          mode={mode}
          onToggleLang={toggleLang}
          onToggleMode={toggleMode}
          t={t}
        />
      </header>

      <main className="hero">
        <section className="hero-info">
          <div className={"lang-fade " + (langFading ? "is-out" : "")}>
            <div className="eyebrow reveal">{t.eyebrow}</div>
            <div className="name-block reveal" style={{ "--reveal-delay": "80ms" }}>
              <h1 className="name-en">
                <span>{t.name}</span>
                {t.nameZh && <span className="name-zh">{t.nameZh}</span>}
              </h1>
            </div>
            <p className="title-line reveal" style={{ "--reveal-delay": "160ms", marginTop: 18 }}>
              <span className="title-part1">{t.titlePart1}</span>
              <span className="title-sep"> · </span>
              <span className="title-part2">{t.titlePart2}</span>
            </p>
            <ul className="licenses reveal" style={{ "--reveal-delay": "220ms" }}>
              {t.licenses.map((l, i) => <li key={i}>{l}</li>)}
            </ul>

            <ul className="contact-list reveal" style={{ "--reveal-delay": "280ms" }}>
              <ContactRow icon={<Icon.Globe />} label={t.contact.website}>
                <a href={FIXED.websiteHref} target="_blank" rel="noopener noreferrer">{FIXED.website}</a>
              </ContactRow>
              <ContactRow icon={<Icon.MapPin />} label={t.contact.office}>
                <a href={FIXED.officeMapHref} target="_blank" rel="noopener noreferrer">{FIXED.office}</a>
                <CopyButton text={FIXED.office} onCopied={onCopied} ariaLabel="Copy address" />
              </ContactRow>
              <ContactRow icon={<Icon.Phone />} label={t.contact.mobile}>
                <a href={FIXED.mobileHref}>{FIXED.mobile}</a>
                <CopyButton text={FIXED.mobile} onCopied={onCopied} ariaLabel="Copy phone" />
              </ContactRow>
              <ContactRow icon={<Icon.Mail />} label={t.contact.email}>
                <a href={FIXED.emailHref}>{FIXED.email}</a>
                <CopyButton text={FIXED.email} onCopied={onCopied} ariaLabel="Copy email" />
              </ContactRow>
              <ContactRow icon={<Icon.Languages />} label={t.contact.languages}>
                <span>{t.contact.languagesValue}</span>
              </ContactRow>
            </ul>

            <div className="social reveal" style={{ "--reveal-delay": "360ms" }}>
              <div className="social-label">
                <span className="contact-icon"><Icon.Share /></span>
                <span>{t.socialLabel}</span>
              </div>
              <div className="social-row">
                {socialOrder.map((net) => (
                  <SocialLink
                    key={net}
                    network={net}
                    href={FIXED.socials[net]}
                    label={socialLabels[net]}
                    onClick={() => setWechatOpen(true)}
                  />
                ))}
              </div>
            </div>
          </div>
        </section>

        <aside className="hero-photo reveal" style={{ "--reveal-delay": "120ms" }}>
          <div className="photo-glow" aria-hidden="true"></div>
          <img className="photo-img" src="./images/zhijie-transparent.png" alt={t.name} />
          <img className="photo-img-mobile" src="./images/zhijie-circle.png" alt={t.name} />
        </aside>
      </main>

      <footer className="site-footer">
        <div className="footer-inner">
          <div className="footer-links">
            <div className="footer-link-row">
              {t.menuItems.map((link, i) => (
                <React.Fragment key={i}>
                  <a className="footer-link" href={link.href} target="_blank" rel="noopener noreferrer">{link.label}</a>
                  {i < t.menuItems.length - 1 && <span className="footer-divider" aria-hidden="true"></span>}
                </React.Fragment>
              ))}
            </div>
            <p className="footer-disclaimer">{t.disclaimer}</p>
          </div>
          <div className="footer-badges">
            <div className="footer-badge-wrap">
              <a className="footer-badge" href="https://brokercheck.finra.org/" target="_blank" rel="noopener noreferrer" title="BrokerCheck by FINRA">
                <img src="./images/brokercheck.png" alt="BrokerCheck by FINRA" />
              </a>
              <span className="footer-badge-label">Broker Check</span>
            </div>
            <div className="footer-badge-wrap">
              <a className="footer-badge" href="https://myportal.dfs.ny.gov/nylinxext/elsearch.alis" target="_blank" rel="noopener noreferrer" title="New York State Insurance Producer Search">
                <img src="./images/ny-state.png" alt="New York State" />
              </a>
              <span className="footer-badge-label">Producer Search</span>
            </div>
          </div>
        </div>
      </footer>

      <MobileMenu
        open={menuOpen}
        onClose={() => setMenuOpen(false)}
        t={t}
        lang={lang}
        mode={mode}
        onToggleLang={() => { toggleLang(); }}
        onToggleMode={toggleMode}
      />

      <WeChatModal open={wechatOpen} onClose={() => setWechatOpen(false)} t={t} />
      <Toast message={toast} />

      <TweaksUI tweaks={tweaks} setTweak={setTweak} mode={mode} />
    </div>
  );
}

/* ---------- Tweaks UI ----------------------------------------------------- */

function TweaksUI({ tweaks, setTweak, mode }) {
  return (
    <TweaksPanel title="Tweaks">
      <TweakSection label="Appearance">
        <TweakRadio
          label="Mode"
          options={[
            { label: "Dark",  value: "dark"  },
            { label: "Light", value: "light" },
          ]}
          value={mode}
          onChange={(v) => setTweak("mode", v)}
        />
        <TweakSlider
          label="Text size"
          min={0.9} max={1.15} step={0.01}
          unit="x"
          value={tweaks.fontScale || 1}
          onChange={(v) => setTweak("fontScale", v)}
        />
      </TweakSection>
    </TweaksPanel>
  );
}

/* ---------- Mount --------------------------------------------------------- */

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