/* global React, window */
// Esimda shared components

const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ---------- i18n: detect language from URL path, expose t() globally ---------- */
window.LANG = (typeof location !== 'undefined' && location.pathname.startsWith('/ru')) ? 'ru' : 'en';
window.T = {
  en: {
    // Hero
    hero_h1_l1: 'Install once.',
    hero_h1_l2: 'Reuse on every trip.',
    hero_sub_a: '186 countries, plans from',
    hero_sub_b: '. Top up the same profile, add family members in one click.',
    hero_browse: 'Browse plans',
    hero_destinations: 'See destinations',
    we_accept: 'we accept',
    // Nav
    nav_rates: 'Rates', nav_how: 'How it works', nav_faq: 'FAQ',
    nav_credit_full: 'Get $5 credit', nav_credit_short: '$5 credit',
    lang_switch_label: 'RU', lang_switch_href: '/ru/',
    // Sections
    popular_eyebrow: 'popular destinations',
    popular_h: 'Where to next?',
    popular_search: 'Search 186 countries…',
    popular_search_regions: 'Search regions…',
    popular_search_cities: 'Search cities…',
    popular_search_global: 'Search global plans…',
    popular_no_match: 'No matches for',
    popular_show_all: 'Show all 186',
    popular_from: 'from',
    tab_countries: 'Countries', tab_regions: 'Regions', tab_global: 'Global', tab_cities: 'Cities',
    guarantees_eyebrow: 'what we promise',
    guarantees_h_a: 'New brand.', guarantees_h_b: 'Honest promises.',
    guarantees_lead: "We just launched, so we don't have years of reviews yet. What we have is a clear refund policy and an eSIM that either works on your phone or you pay nothing.",
    benefits_eyebrow: 'why simsimsim',
    benefits_h_a: 'Reliable eSIM', benefits_h_b: 'with', benefits_h_c: 'seamless coverage', benefits_h_dot: '.',
    whatis_eyebrow: 'what is an esim?',
    whatis_h_a: 'A SIM card, but ', whatis_h_b: 'built into your phone', whatis_h_dot: '.',
    whatis_lead_a: 'eSIM lets you activate mobile data directly from your phone’s settings — no physical card to swap, no SIM tray. With Simsimsim: pick a plan, install in 30 seconds, stay connected wherever.',
    whatis_li_1: 'Keeps your home number active — eSIM is a second profile',
    whatis_li_2: 'iPhone XS or later, Pixel 3 or later, Galaxy S20 or later, plus most modern unlocked Androids',
    whatis_li_3: 'Up to 8 different plans installed at once',
    whatis_learn: 'Learn more',
    hts_eyebrow: 'how to start',
    hts_h_a: 'From decision to data', hts_h_b: 'in', hts_h_c: 'under a minute', hts_h_dot: '.',
    carriers_eyebrow: '500+ partner networks · 186 countries',
    carriers_h: 'Auto-connect to the strongest local network — 5G or LTE, whatever your destination has.',
    payments_eyebrow: 'payment methods',
    payments_h: 'Pay your way.',
    payments_sub: 'Card, wallet or crypto — checkout in seconds.',
    faq_eyebrow: 'faq',
    faq_h: 'Frequently asked questions',
    // Hero phone-mockup chip
    just_launched: 'Just launched',
    welcome_credit: '$5 welcome credit',
    where_traveling_upper: 'WHERE ARE YOU TRAVELING?',
    where_traveling_hint: 'Japan, Spain, UAE, or any region…',
    // Footer
    footer_tagline: 'Travel data in 186 countries. Install once. Top up forever.',
    footer_col_product: 'Product', footer_col_company: 'Company',
    footer_col_support: 'Support', footer_col_legal: 'Legal',
    footer_link_rates: 'Rates', footer_link_countries: 'Countries',
    footer_link_how: 'How it works', footer_link_devices: 'Devices',
    footer_link_about: 'About', footer_link_press: 'Press',
    footer_link_careers: 'Careers', footer_link_blog: 'Blog',
    footer_link_help: 'Help center', footer_link_contact: 'Contact',
    footer_link_activation: 'Activation guide', footer_link_compat: 'Compatibility',
    footer_link_terms: 'Terms', footer_link_privacy: 'Privacy',
    footer_link_refund: 'Refund Policy', footer_link_imprint: 'Imprint',
    footer_copyright: '© 2026 Simsimsim B.V.',
  },
  ru: {
    // Hero
    hero_h1_l1: 'Установите один раз.',
    hero_h1_l2: 'Используйте в каждой поездке.',
    hero_sub_a: '186 стран, тарифы от',
    hero_sub_b: '. Пополняйте тот же профиль, добавляйте семью в один клик.',
    hero_browse: 'Тарифы',
    hero_destinations: 'Страны',
    we_accept: 'принимаем',
    // Nav
    nav_rates: 'Тарифы', nav_how: 'Как это работает', nav_faq: 'Вопросы',
    nav_credit_full: 'Бонус $5', nav_credit_short: '$5 бонус',
    lang_switch_label: 'EN', lang_switch_href: '/',
    // Sections
    popular_eyebrow: 'популярные направления',
    popular_h: 'Куда дальше?',
    popular_search: 'Поиск среди 186 стран…',
    popular_search_regions: 'Поиск регионов…',
    popular_search_cities: 'Поиск городов…',
    popular_search_global: 'Поиск глобальных тарифов…',
    popular_no_match: 'Ничего не найдено по запросу',
    popular_show_all: 'Все 186',
    popular_from: 'от',
    tab_countries: 'Страны', tab_regions: 'Регионы', tab_global: 'Глобал', tab_cities: 'Города',
    guarantees_eyebrow: 'что мы обещаем',
    guarantees_h_a: 'Новый бренд.', guarantees_h_b: 'Честные обещания.',
    guarantees_lead: 'Мы только запустились, поэтому у нас пока нет тысяч отзывов. Зато есть чёткая политика возврата и eSIM, который либо работает на вашем телефоне, либо вы ничего не платите.',
    benefits_eyebrow: 'почему simsimsim',
    benefits_h_a: 'Надёжный eSIM', benefits_h_b: 'с', benefits_h_c: 'покрытием без швов', benefits_h_dot: '.',
    whatis_eyebrow: 'что такое esim?',
    whatis_h_a: 'SIM-карта, но ', whatis_h_b: 'встроенная в телефон', whatis_h_dot: '.',
    whatis_lead_a: 'eSIM позволяет активировать мобильный интернет прямо из настроек телефона — никаких физических карт, никаких слотов. С Simsimsim: выберите тариф, установите за 30 секунд, оставайтесь онлайн везде.',
    whatis_li_1: 'Ваш основной номер остаётся активным — eSIM это второй профиль',
    whatis_li_2: 'iPhone XS или новее, Pixel 3 или новее, Galaxy S20 или новее, а также большинство современных Android',
    whatis_li_3: 'До 8 разных тарифов установлено одновременно',
    whatis_learn: 'Подробнее',
    hts_eyebrow: 'как начать',
    hts_h_a: 'От решения до интернета', hts_h_b: 'за', hts_h_c: 'меньше минуты', hts_h_dot: '.',
    carriers_eyebrow: '500+ партнёрских сетей · 186 стран',
    carriers_h: 'Автоматическое подключение к самой сильной местной сети — 5G или LTE, что есть в стране назначения.',
    payments_eyebrow: 'способы оплаты',
    payments_h: 'Платите как удобно.',
    payments_sub: 'Карта, кошелёк или крипта — оплата за секунды.',
    faq_eyebrow: 'вопросы',
    faq_h: 'Часто задаваемые вопросы',
    // Hero phone-mockup chip
    just_launched: 'Только запустились',
    welcome_credit: 'Бонус $5 на первый тариф',
    where_traveling_upper: 'КУДА ЕДЕТЕ?',
    where_traveling_hint: 'Япония, Испания, ОАЭ или регион…',
    // Footer
    footer_tagline: 'Мобильный интернет в 186 странах. Установите один раз. Пополняйте всегда.',
    footer_col_product: 'Продукт', footer_col_company: 'Компания',
    footer_col_support: 'Поддержка', footer_col_legal: 'Юридическое',
    footer_link_rates: 'Тарифы', footer_link_countries: 'Страны',
    footer_link_how: 'Как это работает', footer_link_devices: 'Устройства',
    footer_link_about: 'О нас', footer_link_press: 'Пресса',
    footer_link_careers: 'Вакансии', footer_link_blog: 'Блог',
    footer_link_help: 'База знаний', footer_link_contact: 'Контакт',
    footer_link_activation: 'Установка', footer_link_compat: 'Совместимость',
    footer_link_terms: 'Условия', footer_link_privacy: 'Конфиденциальность',
    footer_link_refund: 'Возврат', footer_link_imprint: 'Реквизиты',
    footer_copyright: '© 2026 Simsimsim B.V.',
  },
};
window.t = (key) => (window.T[window.LANG] || window.T.en)[key] || key;

/* ---------- icons (inline lucide-style) ---------- */
const Icon = ({ d, w = 18, stroke = 1.7, ...rest }) => (
  <svg viewBox="0 0 24 24" width={w} height={w} fill="none" stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" {...rest}>{d}</svg>
);
const I = {
  arrow: <Icon d={<><path d="M5 12h14"/><path d="m13 6 6 6-6 6"/></>} />,
  arrowSm: <Icon w={14} d={<><path d="M5 12h14"/><path d="m13 6 6 6-6 6"/></>} />,
  globe: <Icon d={<><circle cx="12" cy="12" r="9"/><path d="M3 12h18"/><path d="M12 3a14 14 0 0 1 0 18"/><path d="M12 3a14 14 0 0 0 0 18"/></>} />,
  zap: <Icon d={<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/>} />,
  shield: <Icon d={<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>} />,
  check: <Icon d={<path d="M4 12.5 9 17.5 20 6.5"/>} />,
  x: <Icon d={<><path d="m6 6 12 12"/><path d="m6 18L18 6"/></>} />,
  gift: <Icon d={<><rect x="3" y="8" width="18" height="4" rx="1"/><path d="M12 8v13"/><path d="M19 12v9H5v-9"/><path d="M7.5 8a2.5 2.5 0 1 1 0-5C11 3 12 8 12 8s1-5 4.5-5a2.5 2.5 0 1 1 0 5"/></>} />,
  menu: <Icon d={<><path d="M4 6h16"/><path d="M4 12h16"/><path d="M4 18h16"/></>} />,
  search: <Icon d={<><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></>} />,
  qr: <Icon d={<><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><path d="M14 14h3v3"/><path d="M14 20h3"/><path d="M20 14v7"/></>} />,
  signal: <Icon d={<><path d="M2 20v-2"/><path d="M6 20v-6"/><path d="M10 20v-10"/><path d="M14 20v-14"/><path d="M18 20v-18"/></>} />,
  phone: <Icon d={<rect x="6" y="2" width="12" height="20" rx="3"/>} />,
  chevD: <Icon w={16} d={<path d="m6 9 6 6 6-6"/>} />,
  chevR: <Icon w={16} d={<path d="m9 6 6 6-6 6"/>} />,
  plus: <Icon d={<><path d="M5 12h14"/><path d="M12 5v14"/></>} />,
  star: <Icon d={<polygon points="12 2 15 9 22 10 17 15 18 22 12 18 6 22 7 15 2 10 9 9"/>} />,
  copy: <Icon w={14} d={<><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></>} />,
  refresh: <Icon d={<><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/><path d="M3 21v-5h5"/></>} />,
  euro: <Icon d={<><path d="M19 5a8 8 0 1 0 0 14"/><path d="M3 10h12"/><path d="M3 14h12"/></>} />,
  lightning: <Icon d={<polygon points="13 2 4 14 11 14 11 22 20 10 13 10 13 2"/>} />,
};
window.I = I;

/* ---------- Logo ---------- */
function Logo({ size = 22, dark = false }) {
  return (
    <span style={{ display: 'inline-flex', alignItems: 'baseline', gap: 0, color: dark ? '#fff' : 'var(--fg)', fontWeight: 600, fontSize: size, letterSpacing: '-0.04em' }}>
      <span>sim</span>
      <span style={{ color: 'var(--accent)', fontStyle: 'italic', fontWeight: 500 }}>sim</span>
      <span>sim</span>
      <span aria-hidden style={{ marginLeft: 1, width: 5, height: 5, background: 'var(--accent)', borderRadius: 2, display: 'inline-block', alignSelf: 'flex-end', marginBottom: size * 0.18 }} />
    </span>
  );
}
window.Logo = Logo;

/* ---------- Top Nav ---------- */
function TopNav({ creditAmount = 5, authed = false, current = 'home', onNav, onOpenSearch }) {
  const [open, setOpen] = useState(false);
  const go = (href) => (e) => {
    if (onNav) { e.preventDefault(); onNav(href); }
  };
  return (
    <header style={{ position: 'sticky', top: 0, zIndex: 50 }} className="nav-blur">
      <div className="container-wide" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', height: 64, gap: 16 }}>
        <a href="home.html" onClick={go('home')} style={{ display: 'flex', alignItems: 'center' }} aria-label="Simsimsim home">
          <Logo size={22} />
        </a>
        <nav className="only-desktop" style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
          <a href="#countries" onClick={go('rates')} className="nav-link">{window.t('nav_rates')}</a>
          <a href="#how" className="nav-link">{window.t('nav_how')}</a>
          <a href="#faq" className="nav-link">{window.t('nav_faq')}</a>
          <a href={window.t('lang_switch_href')} className="nav-link" hreflang={window.t('lang_switch_label').toLowerCase()} aria-label="Switch language">{window.t('lang_switch_label')}</a>
          <a href="#countries" onClick={go('rates')} className="btn btn-sm btn-accent" style={{ marginLeft: 6 }} aria-label={window.t('nav_credit_full')}>
            <span style={{ fontSize: 13 }}>🎁</span>
            {window.t('nav_credit_full')}
          </a>
        </nav>
        <div className="only-mobile" style={{ alignItems: 'center', gap: 4 }}>
          <a href={window.t('lang_switch_href')} className="nav-link" hreflang={window.t('lang_switch_label').toLowerCase()} aria-label="Switch language" style={{ padding: '8px 10px' }}>{window.t('lang_switch_label')}</a>
          <button onClick={() => setOpen(true)} aria-label="Open menu" style={{ background: 'transparent', border: 0, padding: 6 }}>
            {I.menu}
          </button>
        </div>
      </div>
      {open && (
        <div className="only-mobile" style={{ position: 'fixed', inset: 0, background: 'rgba(10,10,10,0.5)', zIndex: 100, backdropFilter: 'blur(2px)' }} onClick={() => setOpen(false)}>
          <div style={{ position: 'fixed', top: 0, right: 0, width: 280, maxWidth: '85vw', height: '100vh', backgroundColor: '#ffffff', backgroundImage: 'none', padding: 20, display: 'flex', flexDirection: 'column', gap: 4, boxShadow: '-4px 0 20px rgba(0,0,0,0.15)', zIndex: 110, overflowY: 'auto', boxSizing: 'border-box' }} onClick={(e) => e.stopPropagation()}>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
              <Logo size={20} />
              <button onClick={() => setOpen(false)} aria-label="Close menu" style={{ background: 'transparent', border: 0, padding: 6 }}>{I.x}</button>
            </div>
            {[
              [window.t('nav_rates'),         '#countries'],
              [window.t('nav_how'),           '#how'],
              [window.t('nav_faq'),           '#faq'],
              [window.t('footer_link_refund'),'/refund'],
            ].map(([l, href]) => (
              <a key={l} href={href} onClick={() => setOpen(false)} className="nav-link" style={{ padding: '14px 12px', fontSize: 16 }}>{l}</a>
            ))}
            <a href="#countries" onClick={() => setOpen(false)} className="btn btn-accent" style={{ marginTop: 12, justifyContent: 'center' }}>🎁 {window.t('nav_credit_full')}</a>
          </div>
        </div>
      )}
    </header>
  );
}
window.TopNav = TopNav;

/* ---------- Footer ---------- */
function Footer() {
  return (
    <footer style={{ borderTop: '1px solid var(--border)', background: 'var(--bg-muted)', marginTop: 'auto' }}>
      <div className="container" style={{ paddingTop: 64, paddingBottom: 40 }}>
        <style>{`
          @media (max-width: 760px) {
            .footer-grid { grid-template-columns: repeat(2, 1fr) !important; gap: 32px 24px !important; }
            .footer-brand { grid-column: 1 / -1; }
          }
        `}</style>
        <div className="footer-grid" style={{ display: 'grid', gridTemplateColumns: '2fr 1fr 1fr 1fr 1fr', gap: 32, alignItems: 'start' }}>
          <div className="footer-brand">
            <Logo size={22} />
            <p style={{ marginTop: 14, color: 'var(--fg-muted)', fontSize: 14, maxWidth: 280 }}>
              {window.t('footer_tagline')}
            </p>
          </div>
          {[
            { h: window.t('footer_col_product'), l: [[window.t('footer_link_rates'), '#countries'], [window.t('footer_link_countries'), '#countries'], [window.t('footer_link_how'), '#how'], [window.t('footer_link_devices'), '#faq']] },
            { h: window.t('footer_col_company'), l: [[window.t('footer_link_about'), '#'], [window.t('footer_link_press'), '#'], [window.t('footer_link_careers'), '#'], [window.t('footer_link_blog'), '#']] },
            { h: window.t('footer_col_support'), l: [[window.t('footer_link_help'), '#faq'], [window.t('footer_link_contact'), 'mailto:support@simsimsim.app'], [window.t('footer_link_activation'), '#how'], [window.t('footer_link_compat'), '#faq']] },
            { h: window.t('footer_col_legal'),   l: [[window.t('footer_link_terms'), '#'], [window.t('footer_link_privacy'), '#'], [window.t('footer_link_refund'), '/refund'], [window.t('footer_link_imprint'), '#']] },
          ].map((col) => (
            <div key={col.h}>
              <div className="eyebrow" style={{ marginBottom: 14 }}>{col.h}</div>
              <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 10 }}>
                {col.l.map(([label, href]) => <li key={label}><a href={href} style={{ fontSize: 14, color: 'var(--fg-muted)' }} className="nav-link">{label}</a></li>)}
              </ul>
            </div>
          ))}
        </div>
        <div style={{ marginTop: 56, paddingTop: 24, borderTop: '1px solid var(--border)', fontSize: 13, color: 'var(--fg-muted)' }}>
          {window.t('footer_copyright')}
        </div>
      </div>
    </footer>
  );
}
window.Footer = Footer;

/* ---------- World Map ---------- */
function WorldMap({ countries, onPick, dense = false }) {
  const [hover, setHover] = useState(null);
  const world = window.ESIMDA_WORLD;
  const rows = world.length;
  const cols = world[0].length;
  // Build land dots
  const dots = useMemo(() => {
    const out = [];
    for (let y = 0; y < rows; y++) {
      for (let x = 0; x < cols; x++) {
        if (world[y][x] === '#') out.push([x, y]);
      }
    }
    return out;
  }, [world, rows, cols]);
  // Pins (countries with x,y in 0-100 percent of cols/rows space)
  const pins = countries;

  return (
    <div
      style={{ position: 'relative', width: '100%', aspectRatio: '80 / 32', borderRadius: 'var(--r-lg)', background: 'var(--bg-muted)', border: '1px solid var(--border)', overflow: 'hidden' }}
      aria-label="World map of supported countries"
      role="img"
    >
      <svg viewBox={`0 0 ${cols} ${rows}`} style={{ width: '100%', height: '100%', display: 'block' }} preserveAspectRatio="xMidYMid meet">
        {/* base subtle grid */}
        {!dense && [...Array(rows / 2 | 0)].map((_, j) =>
          [...Array(cols / 2 | 0)].map((_, i) =>
            <circle key={`g-${i}-${j}`} cx={i * 2 + 1} cy={j * 2 + 1} r={0.12} fill="#0A0A0A" opacity={0.05} />
          )
        )}
        {/* land dots */}
        {dots.map(([x, y]) => (
          <circle key={`${x}-${y}`} cx={x + 0.5} cy={y + 0.5} r={0.32} fill="#0A0A0A" opacity={0.42} />
        ))}
        {/* country pins */}
        {pins.map((c) => {
          const px = (c.x / 100) * cols;
          const py = (c.y / 100) * rows;
          const isHover = hover === c.iso;
          return (
            <g key={c.iso} style={{ cursor: 'pointer' }}
              onMouseEnter={() => setHover(c.iso)}
              onMouseLeave={() => setHover((h) => h === c.iso ? null : h)}
              onClick={() => onPick && onPick(c)}
              tabIndex={0}
              role="button"
              aria-label={`${c.name} from $${c.from.toFixed(2)}`}
              onKeyDown={(e) => { if (e.key === 'Enter') onPick && onPick(c); }}
            >
              <circle cx={px} cy={py} r={isHover ? 1.6 : 0.9} fill={isHover ? '#D97706' : '#F59E0B'} />
              {isHover && <circle cx={px} cy={py} r={2.8} fill="#F59E0B" opacity={0.25} />}
            </g>
          );
        })}
      </svg>
      {/* Tooltip layer (HTML positioned over SVG) */}
      {hover && (() => {
        const c = pins.find((p) => p.iso === hover);
        if (!c) return null;
        return (
          <div
            style={{
              position: 'absolute',
              left: `${c.x}%`,
              top: `${c.y}%`,
              transform: 'translate(-50%, calc(-100% - 14px))',
              pointerEvents: 'none',
            }}
          >
            <div style={{ background: 'var(--fg)', color: '#fff', padding: '8px 12px', borderRadius: 8, fontSize: 12.5, display: 'flex', alignItems: 'center', gap: 8, whiteSpace: 'nowrap', boxShadow: 'var(--shadow-lg)' }}>
              <span style={{ fontSize: 14 }}>{c.flag}</span>
              <span style={{ fontWeight: 500 }}>{c.name}</span>
              <span style={{ color: '#A3A3A3' }}>·</span>
              <span className="mono tnum" style={{ color: 'var(--accent)' }}>from ${c.from.toFixed(2)}</span>
            </div>
            <div style={{ position: 'absolute', left: '50%', top: '100%', transform: 'translateX(-50%)', width: 0, height: 0, borderLeft: '5px solid transparent', borderRight: '5px solid transparent', borderTop: '5px solid var(--fg)' }} />
          </div>
        );
      })()}
    </div>
  );
}
window.WorldMap = WorldMap;

/* ---------- FAQ ---------- */
function FAQ({ items }) {
  const [open, setOpen] = useState(0);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 0, borderTop: '1px solid var(--border)' }}>
      {items.map((it, i) => {
        const isOpen = open === i;
        return (
          <div key={i} style={{ borderBottom: '1px solid var(--border)' }}>
            <button
              onClick={() => setOpen(isOpen ? -1 : i)}
              aria-expanded={isOpen}
              style={{
                display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                width: '100%', padding: '20px 4px', background: 'transparent', border: 0, textAlign: 'left',
                fontSize: 17, fontWeight: 500, letterSpacing: '-0.01em', color: 'var(--fg)',
              }}
            >
              <span>{it.q}</span>
              <span style={{ transition: 'transform 0.2s', transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)', color: 'var(--fg-muted)' }}>{I.chevD}</span>
            </button>
            <div style={{
              maxHeight: isOpen ? 240 : 0,
              opacity: isOpen ? 1 : 0,
              overflow: 'hidden',
              transition: 'max-height 0.3s ease, opacity 0.2s ease',
            }}>
              <div style={{ padding: '0 4px 24px', color: 'var(--fg-muted)', fontSize: 15.5, maxWidth: 720, lineHeight: 1.65 }}>{it.a}</div>
            </div>
          </div>
        );
      })}
    </div>
  );
}
window.FAQ = FAQ;

/* ---------- ComparisonTable ---------- */
function ComparisonTable() {
  const rows = [
    { label: '5 GB · 30 days in Japan', us: '$9.90', a: '$19.50', b: '$25.99' },
    { label: 'Same eSIM, every trip',   us: 'yes',   a: 'no',     b: 'no' },
    { label: 'Browser activation (no app)', us: 'yes', a: 'no',   b: 'no' },
    { label: 'Top-up an existing eSIM',  us: 'yes',  a: 'limited', b: 'no' },
    { label: 'Welcome credit',           us: '$5',   a: '—',       b: '—' },
    { label: 'Local 5G networks',        us: 'yes',  a: 'yes',     b: 'yes' },
    { label: 'Support response time',    us: '< 10 min', a: '~2 h', b: '~24 h' },
  ];
  const cell = (v) => {
    if (v === 'yes') return <span style={{ color: 'var(--success)', display: 'inline-flex', alignItems: 'center', gap: 4 }}>{I.check} Yes</span>;
    if (v === 'no')  return <span style={{ color: 'var(--fg-faint)', display: 'inline-flex', alignItems: 'center', gap: 4 }}>{I.x} No</span>;
    if (v === '—')   return <span style={{ color: 'var(--fg-faint)' }}>—</span>;
    if (v === 'limited') return <span style={{ color: 'var(--fg-muted)' }}>Limited</span>;
    return <span className="mono tnum">{v}</span>;
  };
  return (
    <div className="card" style={{ overflow: 'hidden' }}>
      <table className="compare">
        <thead>
          <tr>
            <th style={{ width: '40%' }}></th>
            <th className="us">Simsimsim</th>
            <th>Other A</th>
            <th>Other B</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((r) => (
            <tr key={r.label}>
              <td style={{ color: 'var(--fg-muted)' }}>{r.label}</td>
              <td className="us" style={{ fontWeight: 500 }}>{cell(r.us)}</td>
              <td>{cell(r.a)}</td>
              <td>{cell(r.b)}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}
window.ComparisonTable = ComparisonTable;

/* ---------- Phone frame ---------- */
function PhoneFrame({ children, label }) {
  return (
    <div style={{ width: 248, height: 510, borderRadius: 36, background: '#0A0A0A', padding: 8, boxShadow: 'var(--shadow-lg)', position: 'relative' }}>
      <div style={{ position: 'absolute', top: 18, left: '50%', transform: 'translateX(-50%)', width: 90, height: 22, background: '#0A0A0A', borderRadius: 14, zIndex: 2 }} />
      <div style={{ width: '100%', height: '100%', borderRadius: 28, background: '#FAF9F6', overflow: 'hidden', position: 'relative' }}>
        {children}
      </div>
      {label && <div style={{ position: 'absolute', bottom: -28, left: 0, right: 0, textAlign: 'center', fontFamily: 'var(--mono)', fontSize: 11.5, color: 'var(--fg-muted)' }}>{label}</div>}
    </div>
  );
}
window.PhoneFrame = PhoneFrame;

/* ---------- QR code (simple deterministic visual) ---------- */
function QRCode({ size = 140, seed = 'esimda' }) {
  const N = 21;
  const cells = useMemo(() => {
    // pseudo-random pattern from seed
    let s = 0;
    for (let i = 0; i < seed.length; i++) s = (s * 31 + seed.charCodeAt(i)) | 0;
    const rng = () => {
      s = (s * 1664525 + 1013904223) | 0;
      return ((s >>> 0) % 1000) / 1000;
    };
    const grid = Array.from({ length: N }, () => Array(N).fill(false));
    for (let y = 0; y < N; y++) for (let x = 0; x < N; x++) grid[y][x] = rng() > 0.52;
    // finder squares
    const setFinder = (ox, oy) => {
      for (let y = 0; y < 7; y++) for (let x = 0; x < 7; x++) {
        grid[oy + y][ox + x] = (x === 0 || x === 6 || y === 0 || y === 6) || (x >= 2 && x <= 4 && y >= 2 && y <= 4);
      }
      // clear ring
      for (let i = -1; i <= 7; i++) {
        if (ox + i >= 0 && ox + i < N && oy - 1 >= 0) grid[oy - 1][ox + i] = false;
        if (ox + i >= 0 && ox + i < N && oy + 7 < N) grid[oy + 7][ox + i] = false;
        if (oy + i >= 0 && oy + i < N && ox - 1 >= 0) grid[oy + i][ox - 1] = false;
        if (oy + i >= 0 && oy + i < N && ox + 7 < N) grid[oy + i][ox + 7] = false;
      }
    };
    setFinder(0, 0);
    setFinder(N - 7, 0);
    setFinder(0, N - 7);
    return grid;
  }, [seed]);
  const cell = size / N;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${N} ${N}`} style={{ display: 'block', background: '#fff' }} aria-label="QR code">
      {cells.map((row, y) => row.map((on, x) => on ? <rect key={`${x}-${y}`} x={x} y={y} width={1.05} height={1.05} fill="#0A0A0A" /> : null))}
    </svg>
  );
}
window.QRCode = QRCode;

/* ---------- Skeleton ---------- */
function Skel({ w = '100%', h = 14, r = 6, style }) {
  return <div className="skel" style={{ width: w, height: h, borderRadius: r, ...style }} />;
}
window.Skel = Skel;

/* ---------- Country Search (⌘K command palette) ---------- */
function CountrySearch({ open, onClose, onPick }) {
  const [q, setQ] = useState('');
  const [active, setActive] = useState(0);
  const inputRef = useRef(null);
  const listRef = useRef(null);

  const all = window.ESIMDA_COUNTRIES;
  const RECENTS = ['jp', 'es', 'ae', 'tr'];
  const POPULAR = ['jp', 'us', 'th', 'es', 'ae', 'tr', 'de', 'gb'];

  // Filter
  const results = useMemo(() => {
    if (!q.trim()) return null;
    const needle = q.trim().toLowerCase();
    const score = (c) => {
      const name = c.name.toLowerCase();
      if (name === needle) return 100;
      if (name.startsWith(needle)) return 50;
      if (name.includes(needle)) return 20;
      if (c.iso.toLowerCase().startsWith(needle)) return 30;
      if (c.region.toLowerCase().includes(needle)) return 5;
      return 0;
    };
    return all
      .map((c) => ({ ...c, _s: score(c) }))
      .filter((c) => c._s > 0)
      .sort((a, b) => b._s - a._s)
      .slice(0, 8);
  }, [q, all]);

  // Sections when no query
  const sections = useMemo(() => {
    if (results) return [{ title: 'Results', items: results }];
    const recents = RECENTS.map((iso) => all.find((c) => c.iso === iso)).filter(Boolean);
    const popular = POPULAR.map((iso) => all.find((c) => c.iso === iso)).filter(Boolean);
    return [
      { title: 'Recent', items: recents },
      { title: 'Popular this week', items: popular },
    ];
  }, [results, all]);

  // Flatten for keyboard nav
  const flat = useMemo(() => sections.flatMap((s) => s.items), [sections]);

  useEffect(() => { if (open) { setQ(''); setActive(0); setTimeout(() => inputRef.current?.focus(), 50); } }, [open]);
  useEffect(() => { setActive(0); }, [q]);

  // Global ⌘K
  useEffect(() => {
    const onKey = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
        e.preventDefault();
        window.dispatchEvent(new CustomEvent('esimda:opensearch'));
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);

  // Local key nav while open
  useEffect(() => {
    if (!open) return undefined;
    const onKey = (e) => {
      if (e.key === 'Escape') { e.preventDefault(); onClose(); }
      else if (e.key === 'ArrowDown') { e.preventDefault(); setActive((i) => Math.min(flat.length - 1, i + 1)); }
      else if (e.key === 'ArrowUp')   { e.preventDefault(); setActive((i) => Math.max(0, i - 1)); }
      else if (e.key === 'Enter')     { e.preventDefault(); const c = flat[active]; if (c) onPick(c); }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, flat, active, onPick, onClose]);

  // Scroll active into view
  useEffect(() => {
    if (!open || !listRef.current) return;
    const el = listRef.current.querySelector(`[data-idx="${active}"]`);
    if (el) el.scrollIntoView({ block: 'nearest' });
  }, [active, open]);

  if (!open) return null;

  let cursor = 0;
  return (
    <div
      style={{
        position: 'fixed', inset: 0, zIndex: 200,
        background: 'rgba(20, 16, 43, 0.55)',
        backdropFilter: 'blur(6px)',
        display: 'flex', justifyContent: 'center', alignItems: 'flex-start',
        paddingTop: 'min(10vh, 100px)',
        animation: 'fadeIn 0.15s ease',
      }}
      onClick={onClose}
    >
      <div
        onClick={(e) => e.stopPropagation()}
        style={{
          width: 'min(640px, calc(100% - 32px))',
          background: '#fff',
          borderRadius: 18,
          boxShadow: '0 30px 80px rgba(20, 16, 43, 0.5)',
          overflow: 'hidden',
          display: 'flex', flexDirection: 'column',
          maxHeight: '70vh',
        }}
        role="dialog"
        aria-label="Search countries"
      >
        {/* Search input */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '16px 18px', borderBottom: '1px solid var(--border)' }}>
          <span style={{ color: 'var(--fg-muted)' }}>{I.search}</span>
          <input
            ref={inputRef}
            value={q}
            onChange={(e) => setQ(e.target.value)}
            placeholder="Where are you traveling? Japan, Spain, UAE…"
            aria-label="Country search"
            style={{
              flex: 1, border: 0, outline: 0, background: 'transparent',
              fontSize: 17, fontFamily: 'inherit', color: 'var(--fg)',
              padding: '8px 0',
            }}
          />
          {q && (
            <button
              onClick={() => { setQ(''); inputRef.current?.focus(); }}
              aria-label="Clear search"
              style={{ background: 'transparent', border: 0, color: 'var(--fg-faint)', padding: 4 }}
            >{I.x}</button>
          )}
          <kbd style={{
            fontFamily: 'var(--mono)', fontSize: 11, padding: '3px 7px',
            background: 'var(--bg-muted)', border: '1px solid var(--border)', borderRadius: 5,
            color: 'var(--fg-muted)',
          }}>esc</kbd>
        </div>

        {/* Results */}
        <div ref={listRef} style={{ overflowY: 'auto', flex: 1, padding: '6px 6px 8px' }}>
          {flat.length === 0 && (
            <div style={{ padding: '40px 16px', textAlign: 'center', color: 'var(--fg-muted)' }}>
              <div style={{ fontSize: 38, marginBottom: 8 }}>🔍</div>
              <div style={{ fontWeight: 500, color: 'var(--fg)', fontSize: 15 }}>No matches for “{q}”</div>
              <div style={{ marginTop: 4, fontSize: 13 }}>Try a different country, region, or ISO code.</div>
            </div>
          )}

          {sections.map((sec) => (
            sec.items.length > 0 && (
              <div key={sec.title}>
                <div className="eyebrow" style={{ padding: '12px 14px 6px', fontSize: 10.5 }}>
                  {sec.title}
                  {sec.title === 'Results' && <span style={{ marginLeft: 8, color: 'var(--fg-faint)' }}>· {sec.items.length}</span>}
                </div>
                {sec.items.map((c) => {
                  const idx = cursor++;
                  const isActive = idx === active;
                  return (
                    <button
                      key={c.iso}
                      data-idx={idx}
                      onMouseEnter={() => setActive(idx)}
                      onClick={() => onPick(c)}
                      style={{
                        display: 'flex', alignItems: 'center', gap: 12,
                        width: '100%', padding: '10px 14px',
                        background: isActive ? 'var(--brand-soft)' : 'transparent',
                        border: 0, borderRadius: 10,
                        textAlign: 'left', cursor: 'pointer',
                        transition: 'background 0.1s',
                      }}
                    >
                      <span style={{ fontSize: 24, lineHeight: 1, width: 28, textAlign: 'center' }}>{c.flag}</span>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ fontSize: 14.5, fontWeight: 500, color: 'var(--fg)' }}>{c.name}</div>
                        <div style={{ fontSize: 12, color: 'var(--fg-muted)' }}>
                          <span className="mono tnum" style={{ color: isActive ? 'var(--brand-deep)' : 'var(--fg-muted)' }}>from ${c.from.toFixed(2)}</span>
                          <span> · {c.plans} plans · {c.region}</span>
                          {c.fiveG && <span style={{ marginLeft: 8, fontFamily: 'var(--mono)', fontSize: 10, padding: '1px 5px', borderRadius: 3, background: 'var(--brand-soft)', color: 'var(--brand-deep)' }}>5G</span>}
                        </div>
                      </div>
                      {isActive && <span style={{ color: 'var(--brand)' }}>{I.arrowSm}</span>}
                    </button>
                  );
                })}
              </div>
            )
          ))}
        </div>

        {/* Footer hints */}
        <div style={{
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          padding: '10px 16px', borderTop: '1px solid var(--border)',
          background: 'var(--bg-muted)',
          fontSize: 11.5, color: 'var(--fg-muted)',
        }}>
          <div style={{ display: 'flex', gap: 14 }}>
            <span><Kbd>↑</Kbd><Kbd>↓</Kbd> navigate</span>
            <span><Kbd>↵</Kbd> select</span>
            <span><Kbd>esc</Kbd> close</span>
          </div>
          <div>186 countries indexed</div>
        </div>
      </div>
      <style>{`@keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } }`}</style>
    </div>
  );
}

function Kbd({ children }) {
  return (
    <kbd style={{
      display: 'inline-block', minWidth: 16, textAlign: 'center',
      fontFamily: 'var(--mono)', fontSize: 10.5, padding: '1px 5px',
      background: '#fff', border: '1px solid var(--border)', borderRadius: 4,
      marginRight: 4, color: 'var(--fg-muted)',
    }}>{children}</kbd>
  );
}
window.CountrySearch = CountrySearch;

/* ---------- Hero search input (the big white card that opens the modal) ---------- */
function HeroSearch({ onOpen }) {
  return (
    <button
      onClick={onOpen}
      style={{
        display: 'flex', alignItems: 'center', gap: 14,
        width: '100%', maxWidth: 520,
        padding: '14px 18px 14px 20px',
        background: '#fff',
        border: '1px solid rgba(255,255,255,0.85)',
        borderRadius: 16,
        boxShadow: '0 12px 36px rgba(20, 16, 43, 0.12), 0 0 0 1px rgba(255,255,255,0.6) inset',
        cursor: 'pointer',
        textAlign: 'left',
        transition: 'transform 0.15s, box-shadow 0.15s',
      }}
      onMouseEnter={(e) => { e.currentTarget.style.transform = 'translateY(-1px)'; e.currentTarget.style.boxShadow = '0 18px 44px rgba(20, 16, 43, 0.16)'; }}
      onMouseLeave={(e) => { e.currentTarget.style.transform = ''; e.currentTarget.style.boxShadow = '0 12px 36px rgba(20, 16, 43, 0.12), 0 0 0 1px rgba(255,255,255,0.6) inset'; }}
      aria-label="Search countries"
    >
      <span style={{ color: 'var(--brand)' }}>{I.search}</span>
      <span style={{ flex: 1 }}>
        <span style={{ display: 'block', fontSize: 11, color: 'var(--fg-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', fontWeight: 500 }}>{window.t('where_traveling_upper')}</span>
        <span style={{ display: 'block', fontSize: 15.5, color: 'var(--fg-faint)', marginTop: 2 }}>
          {window.t('where_traveling_hint')}
        </span>
      </span>
    </button>
  );
}
window.HeroSearch = HeroSearch;

/* ---------- Nav search trigger (used inside TopNav) ---------- */
function NavSearchTrigger({ onOpen }) {
  return (
    <button
      onClick={onOpen}
      aria-label="Search countries"
      style={{
        display: 'inline-flex', alignItems: 'center', gap: 8,
        padding: '6px 10px 6px 12px',
        background: 'rgba(255,255,255,0.6)',
        border: '1px solid var(--border)',
        borderRadius: 9,
        color: 'var(--fg-muted)',
        fontSize: 13,
        cursor: 'pointer',
        transition: 'background 0.15s, border-color 0.15s, color 0.15s',
      }}
      onMouseEnter={(e) => { e.currentTarget.style.background = '#fff'; e.currentTarget.style.borderColor = 'var(--border-strong)'; e.currentTarget.style.color = 'var(--fg)'; }}
      onMouseLeave={(e) => { e.currentTarget.style.background = 'rgba(255,255,255,0.6)'; e.currentTarget.style.borderColor = 'var(--border)'; e.currentTarget.style.color = 'var(--fg-muted)'; }}
    >
      <span style={{ color: 'var(--fg-faint)' }}>{I.search}</span>
      <span>Find country…</span>
    </button>
  );
}
window.NavSearchTrigger = NavSearchTrigger;
