// wci26/app.jsx — root with tabbed nav (Globe | Leaderboard | Cards | Trophies)

const TABS = [
  { k: 'globe',   label: 'Globe',   icon: 'O' },
  { k: 'battle',  label: 'Battle',  icon: 'VS' },
  { k: 'rewards', label: 'Rewards', icon: '$' },
  { k: 'team',    label: 'Teams',   icon: '*' },
];

const CONTRACT_CONSTANTS = typeof WCI_CONTRACT_CONSTANTS !== 'undefined' ? WCI_CONTRACT_CONSTANTS : {
  buybackThresholdWETH: 0.1,
};
const WCI_TEAM_MONITOR_STORAGE_KEY = 'wci26-monitored-team-codes';
const WCI_WALLET_NICKNAME_STORAGE_KEY = 'wci26-wallet-nicknames';
const WCI_SUPPORTER_NICKNAME_MAX_LENGTH = 32;
const WCI26_HOME_URL = 'https://www.wci26.com/';
const WCI26_X_URL = 'https://x.com/WCI_26';
const WCI26_TELEGRAM_URL = 'https://t.me/WCI_26';
const WCI26_UNISWAP_BUY_URL = 'https://app.uniswap.org/#/swap?outputCurrency=0x80171b59e47EB9c385af40b09Cc345d79Ea40Ba8&use=V2';
const WCI_LIVE_FULL_REFRESH_MS = 30000;
const WCI_LIVE_EVENT_REFRESH_MS = 4000;

const WciXIcon = () => (
  <svg width="15" height="15" viewBox="0 0 24 24" aria-hidden="true">
    <path d="M4 4l12.9 16h3.1L7.1 4H4Zm15.2 0h-3.1L4.8 20h3.1L19.2 4Z" fill="currentColor" />
  </svg>
);

const WciTelegramIcon = () => (
  <svg width="17" height="17" viewBox="0 0 24 24" aria-hidden="true">
    <path d="M21 4.2 3.8 10.9c-1 .4-1 1.3-.2 1.6l4.4 1.4 1.7 5.2c.2.7.6.8 1.1.3l2.5-2.4 4.5 3.3c.8.4 1.3.2 1.5-.8L22 5.4c.2-.9-.3-1.5-1-1.2ZM9.3 13.4l8.7-5.5c.4-.2.7-.1.4.2l-7 6.3-.3 3.1-1.8-4.1Z" fill="currentColor" />
  </svg>
);

const fmtWeth = (value, digits = 3) => `${Number(value || 0).toFixed(digits)} WETH`;

const getWciMarketSnapshot = () => {
  if (typeof WCI_MARKET_DATA !== 'undefined' && WCI_MARKET_DATA.getSnapshot) return WCI_MARKET_DATA.getSnapshot();
  return typeof WCI_TOKEN !== 'undefined' ? WCI_TOKEN : {};
};

const formatWciUsd = (value) => (
  typeof wciFormatUsdPrice === 'function'
    ? wciFormatUsdPrice(value)
    : (Number(value) > 0 ? `$${Number(value).toFixed(4)}` : '--')
);

const formatWciChange = (value) => (
  typeof wciFormatPct === 'function'
    ? wciFormatPct(value)
    : `${Number(value || 0) >= 0 ? '+' : ''}${Number(value || 0).toFixed(1)}%`
);

const formatWciMarketCap = (market = {}) => {
  const value = Number(market.marketCapUsd || market.fdvUsd || market.marketCap || market.fdv || 0);
  return typeof wciFormatCompactUsd === 'function'
    ? wciFormatCompactUsd(value, '--')
    : (value > 0 ? `$${Math.round(value).toLocaleString('en-US')}` : '--');
};

const formatShortWallet = (address) => {
  const text = String(address || '');
  return text.length > 12 ? `${text.slice(0, 6)}...${text.slice(-4)}` : text;
};

const formatCountryChangeLabel = (country) => {
  const value = Number(country?.change24h || 0);
  return `${value >= 0 ? '+' : ''}${value.toFixed(1)}%`;
};

const formatCountryMarketCap = (country, fallback = '$--') => (
  typeof wciFormatCountryMarketCap === 'function'
    ? wciFormatCountryMarketCap(country, { fallback })
    : (typeof fmtMcap === 'function' ? fmtMcap(country?.mcap || 0) : fallback)
);

const formatCountryPrice = (country, fallback = '--') => (
  typeof wciFormatCountryPrice === 'function'
    ? wciFormatCountryPrice(country, { fallback })
    : (typeof fmtPrice === 'function' ? fmtPrice(country?.price || 0) : fallback)
);

const formatCountryVolume = (country, fallback = '$0') => (
  typeof wciFormatCountryVolume === 'function'
    ? wciFormatCountryVolume(country, { fallback })
    : (typeof fmtVol === 'function' ? fmtVol(country?.volume24h || 0) : fallback)
);

const formatAggregateMarketCap = (countries) => {
  if (typeof wciFormatAggregateCountryMarketCap === 'function') {
    return wciFormatAggregateCountryMarketCap(countries, { fallback: '$--' });
  }
  const totalUsd = typeof wciCountryMarketCapUsd === 'function'
    ? countries.reduce((sum, country) => sum + wciCountryMarketCapUsd(country), 0)
    : countries.reduce((sum, country) => sum + Number(country.mcap || 0), 0);
  return typeof wciFormatCompactUsd === 'function' ? wciFormatCompactUsd(totalUsd, '$--') : (typeof fmtMcap === 'function' ? fmtMcap(totalUsd) : '$--');
};

const getLiveActivitySummary = (countries = []) => {
  if (typeof WCI_LIVE_ADAPTER !== 'undefined' && WCI_LIVE_ADAPTER.getLiveActivitySummary) {
    return WCI_LIVE_ADAPTER.getLiveActivitySummary();
  }
  return {
    buysPerMinute: countries.reduce((sum, country) => sum + Number(country.buysPerMinute || country.buys1m || 0), 0),
    recentBuyCount: countries.reduce((sum, country) => sum + Number(country.recentBuyCount || 0), 0),
    recentBuyVolumeWETH: countries.reduce((sum, country) => sum + Number(country.recentBuyVolumeWETH || 0), 0),
  };
};

const formatAggregateVolume = (countries, totalVolume = 0) => (
  typeof wciFormatAggregateCountryVolume === 'function'
    ? wciFormatAggregateCountryVolume(countries, { fallback: '$0' })
    : (typeof fmtVol === 'function' ? fmtVol(totalVolume) : '$0')
);

const readMonitoredTeamCodes = () => {
  try {
    const stored = localStorage.getItem(WCI_TEAM_MONITOR_STORAGE_KEY);
    const parsed = stored ? JSON.parse(stored) : [];
    return Array.isArray(parsed) ? parsed.filter(Boolean) : [];
  } catch {
    return [];
  }
};

const cleanNicknameInput = (value) => (
  String(value || '').replace(/[\r\n\t]+/g, ' ').replace(/\s{2,}/g, ' ').slice(0, WCI_SUPPORTER_NICKNAME_MAX_LENGTH)
);

const sanitizeSupporterNickname = (value) => cleanNicknameInput(value).trim();

const walletNicknameKey = (address) => String(address || '').toLowerCase();

const readWalletNicknames = () => {
  try {
    const stored = localStorage.getItem(WCI_WALLET_NICKNAME_STORAGE_KEY);
    const parsed = stored ? JSON.parse(stored) : {};
    if (!parsed || Array.isArray(parsed) || typeof parsed !== 'object') return {};
    return Object.entries(parsed).reduce((acc, [address, nickname]) => {
      const key = walletNicknameKey(address);
      const clean = sanitizeSupporterNickname(nickname);
      if (key && clean) acc[key] = clean;
      return acc;
    }, {});
  } catch {
    return {};
  }
};

const getWalletNickname = (nicknames = {}, address) => (
  sanitizeSupporterNickname(nicknames[walletNicknameKey(address)] || '')
);

const TopBar = ({ tab, setTab, countries = [], totalVolume, wciMarket, walletAddress, walletNickname, onWalletOpen }) => {
  const market = wciMarket || getWciMarketSnapshot();
  const wciPriceLabel = formatWciUsd(market.priceUsd ?? market.price);
  const wciChange = Number(market.priceChange24h ?? market.change24h ?? 0);
  const wciChangeLabel = formatWciChange(wciChange);
  const wciMarketCapLabel = formatWciMarketCap(market);
  const walletLabel = walletAddress ? (sanitizeSupporterNickname(walletNickname) || formatShortWallet(walletAddress)) : 'CONNECT WALLET';

  return (
  <div className="topbar" style={{
    padding: '14px 20px',
    display: 'flex', alignItems: 'center', gap: 14,
    background: 'rgba(10,6,21,0.65)',
    borderBottom: '1px solid var(--hair)',
    backdropFilter: 'blur(20px)',
    height: 64, flexShrink: 0, position: 'relative', zIndex: 30,
  }}>
    {/* Logo + brand */}
    <div className="topbar-brand" style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
      <div style={{
        width: 40, height: 40, borderRadius: 10,
        background: 'linear-gradient(135deg, var(--gold), var(--fifa-orange))',
        display: 'grid', placeItems: 'center',
        boxShadow: '0 0 24px -4px var(--gold), inset 0 1px 0 rgba(255,255,255,0.4)',
      }}>
        <img src="assets/logo.png" width="32" height="32" alt="" />
      </div>
      <div>
        <div className="display" style={{ fontSize: 19, letterSpacing: '-0.01em', lineHeight: 1 }}>WCI26.com</div>
        <div className="label" style={{ fontSize: 9, color: 'var(--gold)' }}>CRYPTO WORLD CUP</div>
      </div>
    </div>

    {/* Tabs */}
    <div className="desktop-tabs" style={{
      display: 'flex', gap: 4,
      padding: 4, borderRadius: 12,
      background: 'rgba(255,255,255,0.04)',
      border: '1px solid var(--hair)',
      marginLeft: 12,
    }}>
      {TABS.map(t => (
        <button key={t.k} onClick={() => setTab(t.k)} style={{
          padding: '8px 12px', borderRadius: 8,
          background: tab === t.k ? 'linear-gradient(180deg, rgba(245,208,32,0.2), rgba(245,208,32,0.08))' : 'transparent',
          border: '1px solid ' + (tab === t.k ? 'rgba(245,208,32,0.3)' : 'transparent'),
          color: tab === t.k ? 'var(--gold)' : 'var(--t2)',
          fontSize: 12, fontWeight: 700, cursor: 'pointer',
          fontFamily: 'Bricolage Grotesque, sans-serif',
          letterSpacing: '0.04em', textTransform: 'uppercase',
          display: 'flex', alignItems: 'center', gap: 8,
          boxShadow: tab === t.k ? 'inset 0 1px 0 rgba(255,255,255,0.1), 0 0 20px -6px var(--gold)' : 'none',
          transition: 'all 200ms var(--ease)',
        }}>
          <span style={{ fontSize: 14 }}>{t.icon}</span>
          {t.label}
        </button>
      ))}
    </div>

    <div className="mobile-price-pill" style={{
      display: 'none',
      alignItems: 'center',
      gap: 7,
      marginLeft: 'auto',
      padding: '7px 9px',
      borderRadius: 10,
      background: 'rgba(245,208,32,0.08)',
      border: '1px solid rgba(245,208,32,0.28)',
      boxShadow: '0 10px 28px -18px var(--gold)',
    }}>
      <span className="label" style={{ fontSize: 8, color: 'var(--gold)' }}>$WCI26</span>
      <span className="mono" style={{ fontSize: 12, fontWeight: 800, color: '#fff' }}>{wciPriceLabel}</span>
      <span className="mono" style={{ fontSize: 10, fontWeight: 800, color: wciChange >= 0 ? 'var(--lime)' : 'var(--coral)' }}>
        {wciChangeLabel}
      </span>
    </div>

    <div style={{ flex: 1 }} />

    {/* Stats summary */}
    <div className="topbar-stats" style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 8,
        padding: '8px 10px', borderRadius: 10,
        background: 'linear-gradient(135deg, rgba(78,209,230,0.12), rgba(245,208,32,0.06))',
        border: '1px solid rgba(78,209,230,0.28)',
      }}>
        <span className="label" style={{ fontSize: 9, color: 'var(--fifa-cyan)' }}>WCI26 MCAP</span>
        <span className="mono" style={{ fontSize: 14, fontWeight: 800, color: '#fff' }}>{wciMarketCapLabel}</span>
      </div>
      <div style={{
        padding: '8px 10px', borderRadius: 10,
        background: 'rgba(245,208,32,0.08)',
        border: '1px solid rgba(245,208,32,0.3)',
        display: 'flex', alignItems: 'center', gap: 8,
      }}>
        <span className="label" style={{ fontSize: 9, color: 'var(--gold)' }}>$WCI26</span>
        <span className="mono" style={{ fontSize: 14, fontWeight: 700, color: '#fff' }}>{wciPriceLabel}</span>
        <span className="mono" style={{ fontSize: 11, fontWeight: 700, color: wciChange >= 0 ? 'var(--lime)' : 'var(--coral)' }}>
          {wciChangeLabel}
        </span>
      </div>
      <a
        href={WCI26_HOME_URL}
        target="_blank"
        rel="noopener noreferrer"
        className="wci26-home-link"
        style={{
          display: 'inline-flex',
          alignItems: 'center',
          justifyContent: 'center',
          minHeight: 38,
          padding: '0 14px',
          borderRadius: 12,
          color: 'var(--gold)',
          background: 'linear-gradient(180deg, rgba(245,208,32,0.12), rgba(245,208,32,0.045))',
          border: '1px solid rgba(245,208,32,0.32)',
          boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.08), 0 12px 24px -20px var(--gold)',
          fontFamily: 'Bricolage Grotesque, sans-serif',
          fontSize: 11,
          fontWeight: 900,
          letterSpacing: '0.04em',
          textTransform: 'uppercase',
          textDecoration: 'none',
          whiteSpace: 'nowrap',
        }}
      >
        GO TO WCI26.COM
      </a>
      <div className="topbar-social-links" aria-label="WCI26 social links">
        <a
          href={WCI26_X_URL}
          target="_blank"
          rel="noopener noreferrer"
          aria-label="WCI26 on X"
          title="WCI26 on X"
          className="topbar-social-link"
        >
          <WciXIcon />
        </a>
        <a
          href={WCI26_TELEGRAM_URL}
          target="_blank"
          rel="noopener noreferrer"
          aria-label="WCI26 Telegram"
          title="WCI26 Telegram"
          className="topbar-social-link"
        >
          <WciTelegramIcon />
        </a>
      </div>
      <button
        type="button"
        className="wallet-connect-button"
        onClick={onWalletOpen}
        style={{
          minHeight: 38,
          padding: '0 13px',
          borderRadius: 12,
          color: walletAddress ? 'var(--lime)' : 'var(--fifa-cyan)',
          background: walletAddress
            ? 'linear-gradient(180deg, rgba(159,214,52,0.14), rgba(159,214,52,0.045))'
            : 'linear-gradient(180deg, rgba(78,209,230,0.13), rgba(78,209,230,0.045))',
          border: '1px solid ' + (walletAddress ? 'rgba(159,214,52,0.34)' : 'rgba(78,209,230,0.32)'),
          boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.08), 0 12px 24px -20px var(--fifa-cyan)',
          cursor: 'pointer',
          fontFamily: 'Bricolage Grotesque, sans-serif',
          fontSize: 11,
          fontWeight: 900,
          letterSpacing: '0.04em',
          textTransform: 'uppercase',
          whiteSpace: 'nowrap',
          maxWidth: 150,
          overflow: 'hidden',
          textOverflow: 'ellipsis',
        }}
      >
        {walletLabel}
      </button>
      <a
        href={WCI26_UNISWAP_BUY_URL}
        target="_blank"
        rel="noopener noreferrer"
        className="btn-3d wci26-buy-link"
        style={{ padding: '11px 18px', fontSize: 12, textDecoration: 'none', whiteSpace: 'nowrap' }}
      >
        BUY $WCI26
      </a>
    </div>
  </div>
  );
};

const MobileGameNav = ({ tab, setTab }) => (
  <nav className="mobile-game-nav" aria-label="Game tabs">
    {TABS.map(t => (
      <button
        key={t.k}
        type="button"
        className={`mobile-game-nav-item ${tab === t.k ? 'is-active' : ''}`}
        onClick={() => setTab(t.k)}
      >
        <span className="mobile-game-nav-icon">{t.icon}</span>
        <span>{t.label}</span>
      </button>
    ))}
  </nav>
);

const useMobileViewport = () => {
  const getMatch = () => (
    typeof window !== 'undefined'
      && typeof window.matchMedia === 'function'
      && window.matchMedia('(max-width: 760px)').matches
  );
  const [isMobile, setIsMobile] = React.useState(getMatch);

  React.useEffect(() => {
    if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return undefined;
    const media = window.matchMedia('(max-width: 760px)');
    const onChange = () => setIsMobile(media.matches);
    onChange();
    if (typeof media.addEventListener === 'function') {
      media.addEventListener('change', onChange);
      return () => media.removeEventListener('change', onChange);
    }
    media.addListener(onChange);
    return () => media.removeListener(onChange);
  }, []);

  return isMobile;
};

// Top performer beam labels (renders rank tags over the globe in DOM, not WebGL)
const TopPerformerLabels = ({ countries, unfolded }) => {
  if (unfolded) return null;
  const top3 = countries.slice(0, 3);
  return (
    <div style={{
      position: 'absolute', top: 24, right: 24, zIndex: 4,
      width: 270, display: 'flex', flexDirection: 'column', gap: 8,
      padding: 12, borderRadius: 14,
      background: 'rgba(10,6,21,0.78)', backdropFilter: 'blur(12px)',
      border: '1px solid var(--hair-strong)',
      boxShadow: '0 16px 40px -10px rgba(0,0,0,0.7)',
    }}>
      <div className="label" style={{ color: 'var(--gold)', marginBottom: 2 }}>TOP PERFORMERS · 24H</div>
      {top3.map((c, i) => {
        const level = getCountryLevel(c);
        const milestone = getCountryMilestone(c);
        return (
          <div key={c.code} style={{
            padding: '8px 10px',
            background: i === 0 ? `linear-gradient(90deg, ${c.color}20, transparent)` : 'rgba(255,255,255,0.03)',
            border: '1px solid ' + (i === 0 ? c.color + '88' : 'var(--hair)'),
            borderRadius: 10,
            boxShadow: i === 0 ? `0 0 16px -8px ${c.color}` : 'none',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <span className="display" style={{
                fontSize: 14, width: 22, textAlign: 'center',
                color: i === 0 ? 'var(--gold)' : 'var(--fifa-yellow)',
              }}>#{i + 1}</span>
              <FlagRect code={c.code} w={20} h={14} />
              <span className="display" style={{ fontSize: 13, color: '#fff', flex: 1 }}>{c.code}</span>
              <span className="mono" style={{ fontSize: 10, color: c.change24h >= 0 ? 'var(--lime)' : 'var(--coral)', fontWeight: 700 }}>
                {formatCountryChangeLabel(c)}
              </span>
              <span className="mono" style={{ fontSize: 10, color: 'var(--t2)', fontWeight: 700, minWidth: 48, textAlign: 'right' }}>{formatCountryVolume(c)}</span>
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 7 }}>
              <span className="mono" style={{ fontSize: 9, color: c.color, fontWeight: 700 }}>LV {level.level}</span>
              <div style={{ flex: 1 }}><MiniProgressBar value={milestone.progress} color={c.color} /></div>
              <span className="mono" style={{ fontSize: 9, color: 'var(--t3)', fontWeight: 700 }}>{fmtVol(milestone.remaining)} left</span>
            </div>
          </div>
        );
      })}
    </div>
  );
};

// Mini WCI status overlay on globe view (bottom-right)
const GlobeStatusOverlay = ({ countries, buybackPool, globalBuybackPressure }) => {
  const activity = getLiveActivitySummary(countries);
  return (
    <div className="globe-status-overlay" style={{
      position: 'absolute', bottom: 84, left: 28, zIndex: 4,
      display: 'flex', gap: 8, alignItems: 'flex-end',
    }}>
      <StatChip
        label="RECENT BUYS"
        value={fmtNum(activity.recentBuyCount || 0)}
        sub="Indexed country buy events"
        color="var(--fifa-teal)"
      />
      <StatChip
        label="TOTAL MARKET CAP"
        value={formatAggregateMarketCap(countries)}
        sub={`${countries.length}/48 country tokens`}
        color="var(--lime)"
      />
      <StatChip label="LIVE COUNTRIES" value={`${countries.length} / 48`} color="var(--gold)" />
    </div>
  );
};
const StatChip = ({ label, value, sub, color }) => (
  <div className="globe-stat-chip" style={{
    padding: '10px 14px', borderRadius: 12,
    background: 'rgba(10,6,21,0.7)',
    backdropFilter: 'blur(12px)',
    border: '1px solid var(--hair)',
    minWidth: 140,
  }}>
    <div className="label" style={{ color, fontSize: 9 }}>{label}</div>
    <div className="mono" style={{ fontSize: 16, fontWeight: 700, color: '#fff', marginTop: 2 }}>{value}</div>
    {sub && <div className="mono" style={{ marginTop: 3, fontSize: 9, color: 'var(--t3)', fontWeight: 700 }}>{sub}</div>}
  </div>
);

const getWalletBuyRows = (address, countries = []) => {
  const normalized = String(address || '').toLowerCase();
  if (!normalized) return [];
  const events = typeof WCI_LIVE_ADAPTER !== 'undefined' && WCI_LIVE_ADAPTER.getRecentEvents
    ? WCI_LIVE_ADAPTER.getRecentEvents()
    : [];
  return (events || [])
    .filter((event) => {
      const candidates = [event.buyer, event.sender, event.from, event.txFrom, event.wallet, event.recipient]
        .filter(Boolean)
        .map((value) => String(value).toLowerCase());
      return event.isCountryBuy && candidates.includes(normalized);
    })
    .map((event) => {
      const country = countries.find((candidate) => candidate.code === (event.isoCode || event.code));
      const amountUsd = Number(event.amountUsd || event.usdAmount || event.valueUsd || 0)
        || (typeof wciWethToUsd === 'function' ? wciWethToUsd(event.wethAmount) : 0);
      const label = event.usdLabel
        || (typeof wciFormatCompactUsd === 'function'
          ? wciFormatCompactUsd(amountUsd, '$0')
          : `$${Math.round(amountUsd || 0).toLocaleString('en-US')}`);
      return {
        id: event.id || event.txHash || `${event.isoCode}-${event.blockNumber}`,
        country,
        code: event.isoCode || event.code || country?.code || '--',
        label,
        amountUsd,
        blockNumber: Number(event.blockNumber || 0),
        txHash: event.txHash,
      };
    })
    .slice(0, 6);
};

const formatSupporterUsd = (value) => (
  typeof wciFormatCompactUsd === 'function'
    ? wciFormatCompactUsd(value, '$0')
    : `$${Math.round(Number(value || 0)).toLocaleString('en-US')}`
);

const buildSupporterProfile = (address, countries = [], rows = []) => {
  const byCountry = new Map();
  rows.forEach((row) => {
    const key = row.code || '--';
    const existing = byCountry.get(key) || {
      code: key,
      country: row.country || countries.find((country) => country.code === key),
      count: 0,
      amountUsd: 0,
    };
    existing.count += 1;
    existing.amountUsd += Number(row.amountUsd || 0);
    byCountry.set(key, existing);
  });
  const countryEntries = [...byCountry.values()].sort((a, b) => (
    (b.amountUsd - a.amountUsd) || (b.count - a.count) || String(a.code).localeCompare(String(b.code))
  ));
  const totalBuys = rows.length;
  const countriesBacked = countryEntries.length;
  const totalSupportUsd = rows.reduce((sum, row) => sum + Number(row.amountUsd || 0), 0);
  const score = totalBuys * 100 + countriesBacked * 75 + Math.round(totalSupportUsd / 10);
  const tier = totalBuys >= 10 ? 'Legend supporter'
    : totalBuys >= 5 ? 'Captain supporter'
      : totalBuys >= 1 ? 'Active supporter'
        : 'Ready supporter';
  const badges = totalBuys ? ['First buy'] : ['Ready to back'];
  if (countriesBacked >= 2) badges.push('Multi-country');
  if (totalBuys >= 3) badges.push('Buy streak');
  if (totalSupportUsd >= 1000) badges.push('Four-figure push');
  const topEntry = countryEntries[0] || null;
  const nextMission = !totalBuys
    ? 'Back a country to unlock your first supporter badge.'
    : countriesBacked < 2
      ? 'Back one more country to unlock the multi-country badge.'
      : 'Push your top country higher on the live race board.';
  return {
    address,
    totalBuys,
    countriesBacked,
    totalSupportUsd,
    score,
    tier,
    badges,
    topEntry,
    nextMission,
  };
};

const WalletReadOnlyModal = ({ open, error, nicknameDraft = '', onNicknameChange, onClose, onConnect }) => {
  if (!open) return null;
  return (
    <div className="wallet-readonly-backdrop" role="presentation">
      <section className="wallet-readonly-modal" role="dialog" aria-modal="true" aria-label="Read-only wallet connection">
        <button type="button" className="wallet-modal-close" onClick={onClose}>Close</button>
        <div className="label">VIEW-ONLY WALLET</div>
        <h2>Read-only wallet view</h2>
        <p>Connect your public address to view indexed country buys. This dashboard cannot move tokens, approve spending, or start transactions from this step.</p>
        <div className="wallet-readonly-points">
          <span>Public address only</span>
          <span>No approvals</span>
          <span>No transactions</span>
        </div>
        <label className="wallet-nickname-field">
          <span>Supporter nickname</span>
          <input
            type="text"
            value={nicknameDraft}
            maxLength={WCI_SUPPORTER_NICKNAME_MAX_LENGTH}
            placeholder="Cup Commander"
            onChange={(event) => onNicknameChange?.(event.target.value)}
          />
        </label>
        {error && <div className="wallet-error">{error}</div>}
        <button type="button" className="wallet-connect-confirm" onClick={onConnect}>Connect read-only</button>
      </section>
    </div>
  );
};

const WalletViewPanel = ({ address, countries = [], rows, profile, nickname = '', onNicknameChange, onOpen, compact = false }) => {
  const [profileOpen, setProfileOpen] = React.useState(!compact);
  React.useEffect(() => {
    setProfileOpen(!compact);
  }, [address, compact]);
  if (!address) return null;
  const walletRows = Array.isArray(rows) ? rows : getWalletBuyRows(address, countries);
  const walletProfile = profile || buildSupporterProfile(address, countries, walletRows);
  const displayNickname = sanitizeSupporterNickname(nickname);
  const profileTitle = displayNickname || 'Supporter profile';
  return (
    <aside className={`wallet-view-panel ${compact ? 'is-team-compact' : ''}`} aria-label="Connected wallet buy view">
      <div className="wallet-view-head">
        <div>
          <div className="label">READ-ONLY WALLET</div>
          <strong className="wallet-view-name">{displayNickname || formatShortWallet(address)}</strong>
          {displayNickname && <span className="wallet-view-address mono">{formatShortWallet(address)}</span>}
        </div>
        <button type="button" onClick={onOpen}>Manage</button>
      </div>
      <section className={`supporter-profile-card ${profileOpen ? 'is-expanded' : 'is-collapsed'}`} aria-label="Supporter profile">
        <span className="supporter-profile-linkage" aria-hidden="true">
          <i />
          <i />
        </span>
        <div className="supporter-profile-head">
          <div>
            <div className="label">SUPPORTER PROFILE</div>
            <h3>{profileTitle}</h3>
          </div>
          <span className="supporter-tier">{walletProfile.tier}</span>
          <button
            type="button"
            className="supporter-profile-toggle"
            aria-label={profileOpen ? 'Collapse supporter profile' : 'Expand supporter profile'}
            aria-expanded={profileOpen ? 'true' : 'false'}
            onClick={() => setProfileOpen(open => !open)}
          >
            <span className="supporter-profile-affordance" aria-hidden="true">
              <i />
              <i />
            </span>
          </button>
        </div>
        <div className="supporter-profile-body" hidden={!profileOpen}>
          <label className="supporter-nickname-field">
            <span>Nickname</span>
            <input
              type="text"
              className="supporter-nickname-input"
              aria-label="Supporter nickname"
              value={displayNickname}
              maxLength={WCI_SUPPORTER_NICKNAME_MAX_LENGTH}
              placeholder="Name your supporter profile"
              onChange={(event) => onNicknameChange?.(event.target.value)}
            />
          </label>
          <div className="supporter-profile-metrics">
            <div>
              <span>Total support</span>
              <strong className="mono">{formatSupporterUsd(walletProfile.totalSupportUsd)}</strong>
            </div>
            <div>
              <span>Wallet buys</span>
              <strong className="mono">{walletProfile.totalBuys} buys</strong>
            </div>
            <div>
              <span>Countries backed</span>
              <strong className="mono">{walletProfile.countriesBacked} countries</strong>
            </div>
            <div>
              <span>Support score</span>
              <strong className="mono">{walletProfile.score}</strong>
            </div>
          </div>
          <div className="supporter-focus-row">
            <span>Top country</span>
            {walletProfile.topEntry ? (
              <strong>
                {walletProfile.topEntry.country && <FlagRect code={walletProfile.topEntry.country.code} w={22} h={15} />}
                {walletProfile.topEntry.country?.name || walletProfile.topEntry.code}
              </strong>
            ) : (
              <strong>None yet</strong>
            )}
          </div>
          <div className="supporter-badge-row">
            {walletProfile.badges.map((badge) => <span className="supporter-badge" key={badge}>{badge}</span>)}
          </div>
          <div className="supporter-next-mission">
            <span>Next mission</span>
            <strong>{walletProfile.nextMission}</strong>
          </div>
          {walletRows.length === 0 ? (
            <div className="wallet-empty">No indexed wallet buys yet.</div>
          ) : (
            <div className="wallet-buy-list">
              {walletRows.map((row) => (
                <div className="wallet-buy-row" key={row.id}>
                  {row.country && <FlagRect code={row.country.code} w={22} h={15} />}
                  <span className="mono">{row.code}</span>
                  <strong className="mono">{row.label}</strong>
                </div>
              ))}
            </div>
          )}
        </div>
      </section>
    </aside>
  );
};

// Hover hint
const HoverHint = ({ hoveredCountry, countries, unfolded }) => {
  if (!hoveredCountry) return null;
  const c = countries.find(x => x.code === hoveredCountry);
  if (!c) return null;
  const level = getCountryLevel(c);
  const milestone = getCountryMilestone(c);
  return (
    <div style={{
      position: 'absolute', bottom: 110, right: 28, zIndex: 5,
      padding: 14, minWidth: 250,
      background: 'rgba(10,6,21,0.92)', backdropFilter: 'blur(16px)',
      border: `1.5px solid ${c.color}`,
      borderRadius: 14,
      boxShadow: `0 16px 40px -10px rgba(0,0,0,0.8), 0 0 40px -8px ${c.color}`,
      pointerEvents: 'none',
      animation: 'toast-in 200ms var(--ease)',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8 }}>
        <FlagRect code={c.code} w={28} h={19} />
        <div>
          <div className="display" style={{ fontSize: 16, lineHeight: 1 }}>{c.name}</div>
          <div className="label" style={{ fontSize: 9, marginTop: 2 }}>RANK #{c.rank} · GROUP {c.group}</div>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
        <div>
          <div className="label" style={{ fontSize: 8 }}>PRICE</div>
          <div className="mono" style={{ fontSize: 12, fontWeight: 700 }}>{formatCountryPrice(c)}</div>
        </div>
        <div>
          <div className="label" style={{ fontSize: 8 }}>24h</div>
          <div className="mono" style={{ fontSize: 12, fontWeight: 700, color: c.change24h >= 0 ? 'var(--lime)' : 'var(--coral)' }}>
            {formatCountryChangeLabel(c)}
          </div>
        </div>
        <div>
          <div className="label" style={{ fontSize: 8 }}>24h VOL</div>
          <div className="mono" style={{ fontSize: 12, fontWeight: 700 }}>{formatCountryVolume(c)}</div>
        </div>
        <div>
          <div className="label" style={{ fontSize: 8 }}>HOLDERS</div>
          <div className="mono" style={{ fontSize: 12, fontWeight: 700 }}>{fmtNum(c.holders)}</div>
        </div>
      </div>
      <div style={{ marginTop: 10, paddingTop: 10, borderTop: '1px solid rgba(255,255,255,0.06)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12 }}>
          <span className="label" style={{ fontSize: 8 }}>{level.label}</span>
          <span className="mono" style={{ fontSize: 10, color: c.color, fontWeight: 700 }}>LV {level.level}</span>
        </div>
        <div style={{ marginTop: 6 }}>
          <MiniProgressBar value={milestone.progress} color={c.color} />
        </div>
        <div className="mono" style={{ marginTop: 5, fontSize: 9, color: 'var(--t3)' }}>
          {fmtVol(milestone.remaining)} to {fmtVol(milestone.next)}
        </div>
      </div>
      <div style={{ marginTop: 10, fontSize: 10, color: 'var(--t3)', textAlign: 'center' }}>
        Click to open buy panel
      </div>
    </div>
  );
};

// Globe view shell — hosts the WebGL globe + side rail + overlays
const CountryCommandPanel = ({ country, countries, unfolded, onBackCountry }) => {
  if (!country) return null;
  const level = getCountryLevel(country);
  const milestone = getCountryMilestone(country);
  const marketCapLabel = formatCountryMarketCap(country);
  const volumeLabel = formatCountryVolume(country);
  const nextPlay = country.rank === 1
    ? `Hold the market lead with steady volume and fresh buys.`
    : `Push live buys toward rank #${Math.max(1, country.rank - 1)}.`;

  return (
    <div className="country-command-panel" style={{
      position: 'absolute',
      right: 28,
      top: unfolded ? 286 : 354,
      zIndex: 5,
      width: 292,
      padding: 14,
      borderRadius: 16,
      background: 'linear-gradient(145deg, rgba(7,10,26,0.92), rgba(18,10,39,0.84) 52%, rgba(5,28,36,0.84))',
      border: `1px solid ${country.color}66`,
      boxShadow: `0 18px 44px -20px rgba(0,0,0,0.9), 0 0 34px -16px ${country.color}, inset 0 1px 0 rgba(255,255,255,0.08)`,
      backdropFilter: 'blur(18px)',
      pointerEvents: 'auto',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 10 }}>
        <div>
          <div className="label" style={{ color: 'var(--fifa-cyan)' }}>COUNTRY COMMAND</div>
          <div style={{ marginTop: 8, display: 'flex', alignItems: 'center', gap: 10 }}>
            <FlagRect code={country.code} w={32} h={22} />
            <div>
              <div className="display" style={{ fontSize: 22, color: '#fff', lineHeight: 1 }}>{country.name}</div>
              <div className="label" style={{ marginTop: 2, fontSize: 8 }}>GROUP {country.group} · RANK #{country.rank}</div>
            </div>
          </div>
        </div>
        <div className="mono" style={{
          padding: '5px 8px',
          borderRadius: 10,
          color: country.change24h >= 0 ? 'var(--lime)' : 'var(--coral)',
          background: country.change24h >= 0 ? 'rgba(159,214,52,0.10)' : 'rgba(232,57,44,0.12)',
          border: '1px solid ' + (country.change24h >= 0 ? 'rgba(159,214,52,0.34)' : 'rgba(232,57,44,0.34)'),
          fontSize: 11,
          fontWeight: 800,
        }}>{formatCountryChangeLabel(country)}</div>
      </div>

      <div style={{ marginTop: 13, display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 8 }}>
        {[
          ['PRICE', formatCountryPrice(country)],
          ['MARKET CAP', marketCapLabel],
          ['VOLUME', volumeLabel],
        ].map(([label, value]) => (
          <div key={label} style={{
            padding: '9px 8px',
            borderRadius: 11,
            background: 'rgba(255,255,255,0.045)',
            border: '1px solid rgba(255,255,255,0.07)',
          }}>
            <div className="label" style={{ fontSize: 8 }}>{label}</div>
            <div className="mono" style={{ marginTop: 4, fontSize: 11, color: '#fff', fontWeight: 800 }}>{value}</div>
          </div>
        ))}
      </div>

      <div style={{
        marginTop: 12,
        padding: 11,
        borderRadius: 12,
        background: 'linear-gradient(180deg, rgba(159,214,52,0.10), rgba(78,209,230,0.055))',
        border: '1px solid rgba(159,214,52,0.24)',
      }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, alignItems: 'baseline' }}>
          <div className="label" style={{ color: 'var(--lime)', fontSize: 8 }}>LIVE MARKET SNAPSHOT</div>
          <div className="mono" style={{ color: country.active !== false ? 'var(--lime)' : 'var(--t2)', fontSize: 9, fontWeight: 800 }}>
            {country.active === false ? 'INACTIVE' : 'ACTIVE'}
          </div>
        </div>
        <div style={{ marginTop: 7, display: 'flex', justifyContent: 'space-between', gap: 12 }}>
          <span className="mono" style={{ fontSize: 11, color: '#fff', fontWeight: 800 }}>MCap {marketCapLabel}</span>
          <span className="mono" style={{ fontSize: 11, color: 'var(--t3)', fontWeight: 800 }}>Vol {volumeLabel}</span>
        </div>
        <div style={{ marginTop: 8 }}><MiniProgressBar value={milestone.progress} color={country.color} /></div>
      </div>

      <div style={{
        marginTop: 12,
        padding: 11,
        borderRadius: 12,
        background: `linear-gradient(135deg, ${country.color}18, rgba(255,255,255,0.035))`,
        border: `1px solid ${country.color}44`,
      }}>
        <div className="label" style={{ color: country.color, fontSize: 8 }}>NEXT PLAY</div>
        <div style={{ marginTop: 5, fontSize: 12, lineHeight: 1.35, color: 'var(--t1)' }}>{nextPlay}</div>
      </div>

      <div style={{ marginTop: 12 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12 }}>
          <span className="label" style={{ fontSize: 8 }}>{level.label}</span>
          <span className="mono" style={{ fontSize: 10, color: country.color, fontWeight: 800 }}>LV {level.level}</span>
        </div>
        <div style={{ marginTop: 7 }}><MiniProgressBar value={milestone.progress} color={country.color} /></div>
      </div>

      <button onClick={() => onBackCountry(country)} style={{
        marginTop: 14,
        width: '100%',
        padding: '12px 14px',
        borderRadius: 13,
        border: '1px solid rgba(0,0,0,0.55)',
        background: `linear-gradient(180deg, ${country.color}, ${country.secondary})`,
        color: '#090615',
        cursor: 'pointer',
        fontFamily: 'Bricolage Grotesque, sans-serif',
        fontSize: 13,
        fontWeight: 900,
        letterSpacing: '0.04em',
        textTransform: 'uppercase',
        boxShadow: `inset 0 1px 0 rgba(255,255,255,0.45), 0 5px 0 rgba(0,0,0,0.42), 0 18px 30px -16px ${country.color}`,
      }}>
        Back this country
      </button>
    </div>
  );
};

const MiniProgressBar = ({ value, color = 'var(--gold)', height = 5 }) => (
  <div style={{
    height, borderRadius: height, background: 'rgba(255,255,255,0.07)',
    overflow: 'hidden', boxShadow: 'inset 0 1px 2px rgba(0,0,0,0.55)',
  }}>
    <div style={{
      width: `${Math.max(0, Math.min(100, value || 0))}%`, height: '100%',
      background: `linear-gradient(90deg, ${color}, rgba(255,255,255,0.75))`,
      boxShadow: `0 0 10px ${color}`,
      transition: 'width 500ms var(--ease)',
    }} />
  </div>
);

const MapModeSwitch = ({ mode, setMode, compact = false }) => (
  <div className="globe-mode-switch" style={{
    display: 'flex', gap: 4, padding: 4, borderRadius: 14,
    background: 'rgba(10,6,21,0.74)',
    border: '1px solid var(--hair-strong)',
    backdropFilter: 'blur(14px)',
    boxShadow: '0 14px 34px -16px rgba(0,0,0,0.8)',
    pointerEvents: 'auto',
  }}>
    {WCI_GAME_MODES.map((m) => (
      <button key={m.k} onClick={() => setMode(m.k)} style={{
        minWidth: compact ? 84 : 112,
        padding: compact ? '7px 9px' : '9px 12px',
        borderRadius: 10,
        background: mode === m.k ? 'linear-gradient(180deg, rgba(245,208,32,0.2), rgba(245,208,32,0.07))' : 'transparent',
        border: '1px solid ' + (mode === m.k ? 'rgba(245,208,32,0.45)' : 'transparent'),
        color: mode === m.k ? 'var(--gold)' : 'var(--t2)',
        cursor: 'pointer',
        textAlign: 'left',
        fontFamily: 'Bricolage Grotesque, sans-serif',
        transition: 'all 180ms var(--ease)',
      }}>
        <div style={{ fontSize: compact ? 10 : 11, fontWeight: 800, textTransform: 'uppercase', letterSpacing: '0.06em', whiteSpace: 'nowrap' }}>
          {m.label}
        </div>
        {!compact && <div style={{ marginTop: 1, fontSize: 9, color: mode === m.k ? 'rgba(245,208,32,0.72)' : 'var(--t4)', textTransform: 'uppercase', letterSpacing: '0.08em' }}>{m.sub}</div>}
      </button>
    ))}
  </div>
);

const FlatMapControl = ({ mode, setMode, focusCountries, selectedCountry, onSelectCountry }) => {
  const activeMode = WCI_GAME_MODES.find(m => m.k === mode) || WCI_GAME_MODES[0];
  return (
    <div className="flat-map-control" style={{
      position: 'absolute', top: 58, left: '50%', transform: 'translateX(-50%)', zIndex: 5,
      width: 560, maxWidth: 'calc(100% - 80px)',
      padding: 13, borderRadius: 16,
      background: 'linear-gradient(135deg, rgba(7,12,31,0.90), rgba(18,8,39,0.76) 52%, rgba(5,25,36,0.82))',
      border: '1px solid rgba(78,209,230,0.42)',
      boxShadow: '0 18px 44px -22px rgba(0,0,0,0.85), 0 0 34px -18px rgba(78,209,230,0.9), inset 0 1px 0 rgba(255,255,255,0.08)',
      backdropFilter: 'blur(16px)',
      display: 'grid', gridTemplateColumns: '1fr auto', gap: 12, alignItems: 'center',
    }}>
      <div style={{ minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 9, flexWrap: 'wrap' }}>
          <div className="label" style={{ color: 'var(--fifa-cyan)', textShadow: '0 0 14px rgba(78,209,230,0.7)' }}>
            TACTICAL MAP · {activeMode.label}
          </div>
          <div className="mono" style={{
            fontSize: 9, fontWeight: 800, letterSpacing: '0.08em',
            color: 'var(--gold)', textTransform: 'uppercase',
            padding: '3px 7px', borderRadius: 999,
            background: 'rgba(245,208,32,0.10)',
            border: '1px solid rgba(245,208,32,0.25)',
            boxShadow: '0 0 18px -8px var(--gold)',
          }}>LIVE ROUTES</div>
        </div>
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginTop: 7 }}>
          {focusCountries.slice(0, 6).map((c) => {
            const active = selectedCountry?.code === c.code;
            return (
            <button key={c.code} onClick={() => onSelectCountry(c)} style={{
              display: 'inline-flex', alignItems: 'center', gap: 5,
              padding: '4px 7px', borderRadius: 8,
              background: active
                ? `linear-gradient(135deg, ${c.color}44, rgba(255,255,255,0.08))`
                : `linear-gradient(135deg, ${c.color}28, rgba(255,255,255,0.035))`,
              border: `1px solid ${active ? c.color : c.color + '77'}`,
              boxShadow: active ? `0 0 22px -7px ${c.color}` : `0 0 16px -9px ${c.color}`,
              color: 'var(--t1)',
              cursor: 'pointer',
              fontFamily: 'inherit',
            }}>
              <FlagRect code={c.code} w={16} h={11} />
              <span className="mono" style={{ fontSize: 9, fontWeight: 700 }}>{c.code}</span>
            </button>
          );
          })}
        </div>
      </div>
      <MapModeSwitch mode={mode} setMode={setMode} compact />
    </div>
  );
};

const GlobeView = ({
  countries, buybackPool, globalBuybackPressure, onPickCountry, onSelectCountry,
  selectedCountry, globeSize, rotationSpeed, ticker,
}) => {
  const [unfolded, setUnfolded] = React.useState(false);
  const [hoveredCountry, setHoveredCountry] = React.useState(null);
  const [mapMode, setMapMode] = React.useState('live');
  const containerRef = React.useRef(null);

  const targetUnfold = unfolded;
  const focusCodes = React.useMemo(
    () => getGlobeFocusCodes(mapMode, countries),
    [mapMode, countries]
  );
  const focusCountries = React.useMemo(
    () => focusCodes.map(code => countries.find(c => c.code === code)).filter(Boolean),
    [focusCodes, countries]
  );

  React.useEffect(() => {
    document.body.classList.toggle('globe-unfolded', targetUnfold);
    return () => document.body.classList.remove('globe-unfolded');
  }, [targetUnfold]);

  // Top ranked = top 3 (get beams + scale)
  const topRanked = countries.slice(0, 3);

  return (
    <div ref={containerRef} style={{
      position: 'relative', flex: 1, minHeight: 0,
      display: 'flex', overflow: 'hidden',
    }} data-screen-label="01 Globe">
      {/* Left rail */}
      <LeaderboardRail
        countries={countries}
        onPick={onSelectCountry}
        selectedCountry={selectedCountry}
        ticker={ticker}
        buybackPool={buybackPool}
      />

      {/* Globe canvas area */}
      <div className="globe-stage" style={{ flex: 1, position: 'relative', overflow: 'hidden' }}>
        <Globe
          countries={countries}
          topRanked={topRanked}
          unfolded={targetUnfold}
          setUnfolded={setUnfolded}
          onCountryHover={setHoveredCountry}
          onCountryClick={(code) => {
            const c = countries.find(x => x.code === code);
            if (c) onSelectCountry(c);
          }}
          rotationSpeed={rotationSpeed}
          scale={globeSize}
          focusCodes={focusCodes}
          selectedCountryCode={selectedCountry?.code}
        />

        {/* HUD corner brackets — only when unfolded */}
        {targetUnfold && (
          <>
            <div className="hud-bracket tl" />
            <div className="hud-bracket tr" />
            <div className="hud-bracket bl" />
            <div className="hud-bracket br" />
            {/* HUD coordinate readouts */}
            <div style={{
              position: 'absolute', top: 24, left: 60, zIndex: 4,
              fontFamily: 'JetBrains Mono', fontSize: 9, color: 'rgba(78,209,230,0.7)',
              letterSpacing: '0.1em', pointerEvents: 'none',
            }}>
              <div>LAT 00°00′ N · LNG 00°00′ E</div>
              <div style={{ marginTop: 2 }}>WCI26 · ALL 48 NATIONS · GRID 1:48</div>
            </div>
            <div style={{
              position: 'absolute', top: 24, right: 60, zIndex: 4,
              fontFamily: 'JetBrains Mono', fontSize: 9, color: 'rgba(78,209,230,0.7)',
              letterSpacing: '0.1em', pointerEvents: 'none', textAlign: 'right',
            }}>
              <div>SYS LIVE · {new Date().toISOString().slice(11, 19)}</div>
              <div style={{ marginTop: 2 }}>FLAT PROJECTION · EQUIRECTANGULAR</div>
            </div>
          </>
        )}

        {targetUnfold && (
          <FlatMapControl
            mode={mapMode}
            setMode={setMapMode}
            focusCountries={focusCountries}
            selectedCountry={selectedCountry}
            onSelectCountry={onSelectCountry}
          />
        )}

        {/* Headline overlay (top-left) — compact card */}
        <FederationLoopPanel
          countries={countries}
          globalBuybackPressure={globalBuybackPressure}
          selectedCountry={selectedCountry}
          hidden={targetUnfold}
        />

        <div style={{
          position: 'absolute', top: 24, left: 24, zIndex: 4,
          display: 'none', maxWidth: 340, pointerEvents: 'none',
          opacity: targetUnfold ? 0 : 1,
          transform: targetUnfold ? 'translateY(-10px)' : 'translateY(0)',
          transition: 'opacity 400ms var(--ease), transform 500ms var(--ease)',
        }}>
          <Chip kind="gold" style={{ background: 'rgba(245,208,32,0.15)' }}>48 NATIONS · 48 TOKENS</Chip>
          <div className="display" style={{
            fontSize: 44, lineHeight: 0.95, marginTop: 12, letterSpacing: '-0.03em',
            textShadow: '0 4px 24px rgba(0,0,0,0.9)',
          }}>
            <span style={{ background: 'linear-gradient(180deg, #fff, var(--gold))', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent' }}>
              Which country
            </span><br />
            <span style={{ color: 'var(--gold)' }}>are you?</span>
          </div>
          <div style={{ marginTop: 10, color: 'var(--t2)', fontSize: 12, lineHeight: 1.5 }}>
            Back your nation, lift the live board, and move the market with every country buy.
          </div>
        </div>

        {/* Toggle button — fold/unfold lock — bottom center */}
        <button className="globe-unfold-button" onClick={() => setUnfolded(u => !u)} style={{
          position: 'absolute', bottom: 28, left: '50%', transform: 'translateX(-50%)', zIndex: 6,
          padding: '12px 22px', borderRadius: 14,
          background: unfolded ? 'rgba(245,208,32,0.18)' : 'rgba(10,6,21,0.78)',
          backdropFilter: 'blur(12px)',
          border: '1px solid ' + (unfolded ? 'var(--gold)' : 'var(--hair-strong)'),
          color: unfolded ? 'var(--gold)' : 'var(--t1)',
          cursor: 'pointer', fontSize: 12, fontWeight: 700,
          fontFamily: 'Bricolage Grotesque, sans-serif',
          letterSpacing: '0.08em', textTransform: 'uppercase',
          display: 'flex', alignItems: 'center', gap: 10,
          boxShadow: unfolded ? '0 0 32px -8px var(--gold)' : '0 8px 24px -6px rgba(0,0,0,0.6)',
        }}>
          <span>{unfolded ? '↺ Fold to globe' : '⊕ Unfold to flat map'}</span>
        </button>

        {/* Top performers labels — only on sphere */}
        <TopPerformerLabels countries={countries} unfolded={targetUnfold} />

        {/* Hover hint */}
        <HoverHint hoveredCountry={hoveredCountry} countries={countries} unfolded={targetUnfold} />

        {/* Status chips */}
        <GlobeStatusOverlay countries={countries} buybackPool={buybackPool} globalBuybackPressure={globalBuybackPressure} />

        <CountryCommandPanel
          country={selectedCountry}
          countries={countries}
          unfolded={targetUnfold}
          onBackCountry={onPickCountry}
        />

        {/* Floating Golden Boot mini */}
        <div className="globe-trophy-dock" style={{
          position: 'absolute', bottom: 28, right: 28, zIndex: 4,
          display: 'flex', gap: 14, alignItems: 'flex-end',
          opacity: targetUnfold ? 0 : 1, transition: 'opacity 400ms var(--ease)',
          pointerEvents: targetUnfold ? 'none' : 'auto',
        }}>
          <MiniBoot countries={countries} />
        </div>
      </div>
    </div>
  );
};

// Mini trophies on globe view
const MiniBoot = ({ countries }) => {
  const champ = countries[0];
  const fill = Math.min(100, (champ.volume24h / 2_500_000) * 100);
  return (
    <div style={{
      width: 200, padding: 14, borderRadius: 14,
      background: 'rgba(10,6,21,0.85)', backdropFilter: 'blur(16px)',
      border: '1px solid rgba(245,208,32,0.3)',
      boxShadow: '0 16px 40px -10px rgba(0,0,0,0.8), 0 0 32px -10px var(--gold)',
    }}>
      <div className="label" style={{ color: 'var(--gold)', fontSize: 9 }}>GOLDEN BOOT · TODAY</div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 8 }}>
        <FlagRect code={champ.code} w={28} h={19} />
        <div>
          <div className="display" style={{ fontSize: 14, color: '#fff' }}>{champ.name}</div>
          <div className="mono" style={{ fontSize: 11, color: 'var(--gold)', fontWeight: 700 }}>{formatCountryVolume(champ)}</div>
        </div>
      </div>
      <div style={{
        marginTop: 10, height: 5, borderRadius: 3, background: 'rgba(255,255,255,0.06)',
        overflow: 'hidden',
      }}>
        <div style={{
          height: '100%', width: fill + '%',
          background: 'linear-gradient(90deg, #FFF1A0, #F5D020, #A88900)',
          boxShadow: '0 0 8px var(--gold)',
          transition: 'width 1s var(--ease)',
        }} />
      </div>
    </div>
  );
};
const MiniBall = ({ buybackPool }) => (
  <div style={{
    width: 200, padding: 14, borderRadius: 14,
    background: 'rgba(10,6,21,0.85)', backdropFilter: 'blur(16px)',
    border: '1px solid rgba(159,214,52,0.3)',
    boxShadow: '0 16px 40px -10px rgba(0,0,0,0.8), 0 0 32px -10px var(--lime)',
    position: 'relative', overflow: 'hidden',
  }}>
    <div className="label" style={{ color: 'var(--lime)', fontSize: 9 }}>$WCI26 OPS</div>
    <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 8 }}>
      <svg width="38" height="38" viewBox="-20 -20 40 40">
        <circle cx="0" cy="0" r="17" fill="none" stroke="rgba(159,214,52,0.6)" strokeWidth="1.5" />
        <circle cx="0" cy="0" r="17" fill="rgba(159,214,52,0.1)" />
        <polygon points="0,-9 8,-3 6,7 -6,7 -8,-3" fill="none" stroke="rgba(255,255,255,0.4)" strokeWidth="0.8" />
      </svg>
      <div>
        <div className="display" style={{ fontSize: 16, color: '#fff', lineHeight: 1 }}>Manual</div>
        <div className="mono" style={{ fontSize: 10, color: 'var(--t3)' }}>ops controlled</div>
      </div>
    </div>
  </div>
);

// ───────────────── Main App ───────────────────────────────
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "globeSize": 1.0,
  "rotationSpeed": 0.04,
  "marketState": "live"
}/*EDITMODE-END*/;

const PAUL_LINES = [
  "Sepolia live data synced.",
  "Waiting for on-chain fee events.",
  "Country pools are wired.",
];

const App = () => {
  const isMobileViewport = useMobileViewport();
  const [tweaks, setTweaks] = React.useState(() => {
    try {
      const s = localStorage.getItem('wci26-tweaks');
      return s ? { ...TWEAK_DEFAULTS, ...JSON.parse(s) } : TWEAK_DEFAULTS;
    } catch { return TWEAK_DEFAULTS; }
  });
  const [editMode, setEditMode] = React.useState(false);
  const [tab, setTab] = React.useState('globe');
  const [drawerOpen, setDrawerOpen] = React.useState(false);
  const [drawerCountry, setDrawerCountry] = React.useState(null);
  const [shareModal, setShareModal] = React.useState(null);
  const [paulMsg, setPaulMsg] = React.useState(null);
  const [ballBurst, setBallBurst] = React.useState(0);
  const [selectedCountryCode, setSelectedCountryCode] = React.useState('BRA');
  const [liveVersion, setLiveVersion] = React.useState(0);
  const [monitoredTeamCodes, setMonitoredTeamCodes] = React.useState(readMonitoredTeamCodes);
  const [walletModalOpen, setWalletModalOpen] = React.useState(false);
  const [walletAddress, setWalletAddress] = React.useState('');
  const [walletError, setWalletError] = React.useState('');
  const [walletNicknames, setWalletNicknames] = React.useState(readWalletNicknames);
  const [walletNicknameDraft, setWalletNicknameDraft] = React.useState('');
  const [walletTeamNotice, setWalletTeamNotice] = React.useState('');
  const liveAutoRefresh = React.useMemo(() => {
    const params = new URLSearchParams(window.location.search);
    return !['manual', 'off'].includes(String(params.get('live') || '').toLowerCase());
  }, []);
  const [wciMarketVersion, setWciMarketVersion] = React.useState(0);
  const wciMarket = React.useMemo(() => getWciMarketSnapshot(), [wciMarketVersion]);

  // Build country roster + recompute on state change
  const countries = React.useMemo(() => {
    if (typeof WCI_LIVE_ADAPTER !== 'undefined' && WCI_LIVE_ADAPTER.getCountries) {
      return WCI_LIVE_ADAPTER.getCountries(tweaks.marketState);
    }
    const builder = typeof buildContractCountries === 'function' ? buildContractCountries : buildCountryTokens;
    return builder(tweaks.marketState);
  }, [tweaks.marketState, liveVersion]);
  const globalBuybackPressure = React.useMemo(() => {
    if (typeof WCI_LIVE_ADAPTER !== 'undefined' && WCI_LIVE_ADAPTER.getGlobalBuybackPressure) {
      return WCI_LIVE_ADAPTER.getGlobalBuybackPressure();
    }
    if (typeof WCI_CONTRACT_ADAPTER !== 'undefined' && WCI_CONTRACT_ADAPTER.getGlobalBuybackPressure) {
      return WCI_CONTRACT_ADAPTER.getGlobalBuybackPressure(tweaks.marketState);
    }
    return {
      pendingWETH: countries.reduce((s, c) => s + (c.pendingWETH || 0), 0),
      thresholdWETH: CONTRACT_CONSTANTS.buybackThresholdWETH,
      buybackReadyCount: countries.filter(c => c.buybackReady).length,
    };
  }, [countries, tweaks.marketState, liveVersion]);
  const buybackPool = React.useMemo(() => {
    if (typeof WCI_LIVE_ADAPTER !== 'undefined' && WCI_LIVE_ADAPTER.getBuybackPoolValue) {
      return WCI_LIVE_ADAPTER.getBuybackPoolValue();
    }
    return calcBuybackPool(countries);
  }, [countries, liveVersion]);
  const totalVolume = React.useMemo(() => countries.reduce((s, c) => s + c.volume24h, 0), [countries]);
  const selectedCountry = React.useMemo(
    () => countries.find(c => c.code === selectedCountryCode) || countries[0],
    [countries, selectedCountryCode]
  );
  const walletRows = React.useMemo(
    () => (walletAddress ? getWalletBuyRows(walletAddress, countries) : []),
    [walletAddress, countries, liveVersion]
  );
  const walletProfile = React.useMemo(
    () => (walletAddress ? buildSupporterProfile(walletAddress, countries, walletRows) : null),
    [walletAddress, countries, walletRows]
  );
  const walletNickname = React.useMemo(
    () => getWalletNickname(walletNicknames, walletAddress),
    [walletNicknames, walletAddress]
  );

  React.useEffect(() => {
    if (countries.length && !countries.some(c => c.code === selectedCountryCode)) {
      setSelectedCountryCode(countries[0].code);
    }
  }, [countries, selectedCountryCode]);

  React.useEffect(() => {
    setMonitoredTeamCodes((codes) => codes.filter((code) => countries.some((country) => country.code === code)));
  }, [countries]);

  React.useEffect(() => {
    try {
      localStorage.setItem(WCI_TEAM_MONITOR_STORAGE_KEY, JSON.stringify(monitoredTeamCodes));
    } catch {}
  }, [monitoredTeamCodes]);

  React.useEffect(() => {
    try {
      localStorage.setItem(WCI_WALLET_NICKNAME_STORAGE_KEY, JSON.stringify(walletNicknames));
    } catch {}
  }, [walletNicknames]);

  React.useEffect(() => {
    if (!walletAddress) return;
    setWalletNicknameDraft(getWalletNickname(walletNicknames, walletAddress));
  }, [walletAddress]);

  React.useEffect(() => {
    if (typeof WCI_LIVE_ADAPTER === 'undefined' || !WCI_LIVE_ADAPTER.refresh) return undefined;
    let cancelled = false;
    const bump = () => {
      if (!cancelled) setLiveVersion((version) => version + 1);
    };
    const unsubscribe = WCI_LIVE_ADAPTER.subscribe ? WCI_LIVE_ADAPTER.subscribe(bump) : null;
    if (!liveAutoRefresh) {
      return () => {
        cancelled = true;
        if (typeof unsubscribe === 'function') unsubscribe();
      };
    }
    const refreshFull = () => WCI_LIVE_ADAPTER.refresh().catch(() => bump());
    const refreshEvents = () => (
      WCI_LIVE_ADAPTER.refreshEvents
        ? WCI_LIVE_ADAPTER.refreshEvents().catch(() => bump())
        : refreshFull()
    );
    const refreshWhenVisible = () => {
      if (document.visibilityState !== 'hidden') refreshEvents();
    };
    refreshFull();
    const eventId = setInterval(refreshEvents, WCI_LIVE_EVENT_REFRESH_MS);
    const fullId = setInterval(refreshFull, WCI_LIVE_FULL_REFRESH_MS);
    window.addEventListener('focus', refreshEvents);
    document.addEventListener('visibilitychange', refreshWhenVisible);
    return () => {
      cancelled = true;
      clearInterval(eventId);
      clearInterval(fullId);
      window.removeEventListener('focus', refreshEvents);
      document.removeEventListener('visibilitychange', refreshWhenVisible);
      if (typeof unsubscribe === 'function') unsubscribe();
    };
  }, [liveAutoRefresh]);

  React.useEffect(() => {
    if (typeof WCI_MARKET_DATA === 'undefined' || !WCI_MARKET_DATA.refresh) return undefined;
    let cancelled = false;
    const bump = () => {
      if (!cancelled) setWciMarketVersion((version) => version + 1);
    };
    const unsubscribe = WCI_MARKET_DATA.subscribe ? WCI_MARKET_DATA.subscribe(bump) : null;
    WCI_MARKET_DATA.refresh().catch(() => bump());
    const id = setInterval(() => {
      WCI_MARKET_DATA.refresh().catch(() => bump());
    }, 30000);
    return () => {
      cancelled = true;
      clearInterval(id);
      if (typeof unsubscribe === 'function') unsubscribe();
    };
  }, []);

  // Live ticker
  const [ticker, setTicker] = React.useState(() => (
    typeof WCI_LIVE_ADAPTER !== 'undefined' && WCI_LIVE_ADAPTER.getTickerEvents
      ? WCI_LIVE_ADAPTER.getTickerEvents()
      : []
  ));
  React.useEffect(() => {
    if (typeof WCI_LIVE_ADAPTER !== 'undefined' && WCI_LIVE_ADAPTER.getTickerEvents) {
      setTicker(WCI_LIVE_ADAPTER.getTickerEvents());
    }
  }, [countries, liveVersion]);

  // Paul only speaks from explicit local actions; live sync status belongs in the ticker.

  // Apply tweaks to localStorage
  React.useEffect(() => {
    localStorage.setItem('wci26-tweaks', JSON.stringify(tweaks));
  }, [tweaks]);

  // Edit mode protocol
  React.useEffect(() => {
    const h = (e) => {
      if (e.data?.type === '__activate_edit_mode') setEditMode(true);
      if (e.data?.type === '__deactivate_edit_mode') setEditMode(false);
    };
    window.addEventListener('message', h);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', h);
  }, []);

  const updateTweak = (k, v) => {
    setTweaks(t => {
      const next = { ...t, [k]: v };
      window.parent.postMessage({ type: '__edit_mode_set_keys', edits: { [k]: v } }, '*');
      return next;
    });
  };

  // Buy flow
  const selectCountry = (country) => {
    if (country?.code) setSelectedCountryCode(country.code);
  };
  const openBuyDrawer = (country) => {
    selectCountry(country);
    setDrawerCountry(country);
    setDrawerOpen(true);
  };
  const toggleTeamMonitor = (country) => {
    if (!country?.code) return;
    selectCountry(country);
    setMonitoredTeamCodes((codes) => (
      codes.includes(country.code)
        ? codes.filter((code) => code !== country.code)
        : [...codes, country.code]
    ));
  };
  const updateNicknameForAddress = React.useCallback((address, nickname) => {
    const key = walletNicknameKey(address);
    if (!key) return;
    const clean = sanitizeSupporterNickname(nickname);
    setWalletNicknames((current) => {
      const next = { ...current };
      if (clean) {
        next[key] = clean;
      } else {
        delete next[key];
      }
      return next;
    });
  }, []);
  const handleWalletNicknameChange = React.useCallback((value) => {
    const draft = cleanNicknameInput(value);
    setWalletNicknameDraft(draft);
    if (walletAddress) updateNicknameForAddress(walletAddress, draft);
  }, [walletAddress, updateNicknameForAddress]);
  const connectWalletReadOnly = async () => {
    setWalletError('');
    const provider = window.ethereum;
    if (!provider?.request) {
      setWalletError('No browser wallet was found. Open this page in a wallet-enabled browser to use the read-only view.');
      return;
    }
    try {
      const accounts = await provider.request({ method: 'eth_requestAccounts' });
      const address = accounts?.[0];
      if (!address) {
        setWalletError('No wallet address was returned.');
        return;
      }
      const storedNickname = getWalletNickname(walletNicknames, address);
      const nickname = sanitizeSupporterNickname(walletNicknameDraft) || storedNickname;
      if (nickname) {
        updateNicknameForAddress(address, nickname);
        setWalletNicknameDraft(nickname);
      }
      setWalletAddress(address);
      setWalletModalOpen(false);
      setTab('team');
      setWalletTeamNotice('Supporter profile is now in Teams.');
    } catch (error) {
      setWalletError(error?.message || 'Wallet connection was cancelled.');
    }
  };
  const handleBuyConfirm = (country) => {
    setDrawerOpen(false);
    if (typeof WCI_TRADE_LINKS !== 'undefined') {
      WCI_TRADE_LINKS.openUniswapSwap(country);
    }
  };

  if (isMobileViewport && typeof MobileApp === 'function') {
    return (
      <div className="wci-mobile-runtime">
        <MobileApp
          countries={countries}
          buybackPool={buybackPool}
          ticker={ticker}
          wciMarket={wciMarket}
          monitoredTeamCodes={monitoredTeamCodes}
          onToggleTeamMonitor={toggleTeamMonitor}
          walletAddress={walletAddress}
          walletNickname={walletNickname}
          walletNicknameDraft={walletNicknameDraft}
          walletError={walletError}
          walletProfile={walletProfile}
          walletRows={walletRows}
          onWalletConnect={connectWalletReadOnly}
          onWalletNicknameChange={handleWalletNicknameChange}
          defaultTab="globe"
          onSelectCountry={selectCountry}
        />
      </div>
    );
  }

  return (
    <div style={{ height: '100vh', display: 'flex', flexDirection: 'column', position: 'relative', overflow: 'hidden' }}>
      {/* Background */}
      <div className="bg-fifa" />
      <div className="bg-arcs" />
      <div className="bg-overlay" />
      <div className="bg-grain" />

      <div style={{ position: 'relative', zIndex: 1, display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0 }}>
        {/* Live ticker tape */}
        <TickerTape ticker={ticker.slice(0, 24)} countries={countries} />

        {/* Top bar w/ tabs */}
        <TopBar
          tab={tab}
          setTab={setTab}
          countries={countries}
          totalVolume={totalVolume}
          wciMarket={wciMarket}
          walletAddress={walletAddress}
          walletNickname={walletNickname}
          onWalletOpen={() => {
            if (walletAddress) {
              setTab('team');
              setWalletTeamNotice('Supporter profile is now in Teams.');
              return;
            }
            setWalletModalOpen(true);
          }}
        />
        <MobileGameNav tab={tab} setTab={setTab} />

        {/* Tab content */}
        {tab === 'globe' && (
          <GlobeView countries={countries}
                     buybackPool={buybackPool}
                     globalBuybackPressure={globalBuybackPressure}
                     onPickCountry={openBuyDrawer}
                     onSelectCountry={selectCountry}
                     selectedCountry={selectedCountry}
                     globeSize={tweaks.globeSize}
                     rotationSpeed={tweaks.rotationSpeed}
                     ticker={ticker} />
        )}
        {tab === 'battle' && (
          <BattleSeasonView
            countries={countries}
            selectedCountry={selectedCountry}
            onSelectCountry={selectCountry}
          />
        )}
        {tab === 'rewards' && (
          <RewardsCenterView
            countries={countries}
            selectedCountry={selectedCountry}
            onSelectCountry={selectCountry}
          />
        )}
        {tab === 'team' && (
          <CountryDetailView
            countries={countries}
            country={selectedCountry}
            monitoredTeamCodes={monitoredTeamCodes}
            onSelectCountry={selectCountry}
            onToggleTeamMonitor={toggleTeamMonitor}
            onBackCountry={openBuyDrawer}
            supporterNotice={walletTeamNotice}
            onDismissSupporterNotice={() => setWalletTeamNotice('')}
            supporterPanel={walletAddress ? (
              <WalletViewPanel
                address={walletAddress}
                countries={countries}
                rows={walletRows}
                profile={walletProfile}
                nickname={walletNickname}
                onNicknameChange={handleWalletNicknameChange}
                onOpen={() => setWalletModalOpen(true)}
                compact
              />
            ) : null}
          />
        )}
      </div>

      {/* Buy drawer */}
      <BuyDrawer open={drawerOpen} country={drawerCountry}
                 countries={countries}
                 buybackPool={buybackPool}
                 onClose={() => setDrawerOpen(false)}
                 onConfirm={handleBuyConfirm} />

      {/* Share modal */}
      <ShareModal open={!!shareModal} country={shareModal?.country} amount={shareModal?.amount}
                  onClose={() => setShareModal(null)} />

      <WalletReadOnlyModal
        open={walletModalOpen}
        error={walletError}
        nicknameDraft={walletNicknameDraft}
        onNicknameChange={handleWalletNicknameChange}
        onClose={() => setWalletModalOpen(false)}
        onConnect={connectWalletReadOnly}
      />

      {/* Ball burst when buys happen */}
      <BallBurst trigger={ballBurst} color={drawerCountry?.color} />

      {/* Paul peek */}
      <PaulPeek msg={paulMsg} color="var(--fifa-purple)" />

      {/* Tweaks panel */}
      {editMode && <TweaksPanel tweaks={tweaks} updateTweak={updateTweak} />}
    </div>
  );
};

// Full leaderboard view (when tab = leaderboard) — bigger version of the rail
const FullLeaderboard = ({ countries, onPick }) => {
  const maxVol = Math.max(1, ...countries.map(c => c.volume24h || 0));
  return (
    <div style={{ padding: '32px 40px 80px', maxWidth: 1300, margin: '0 auto' }}>
      <div style={{ marginBottom: 24 }}>
        <div className="label" style={{ color: 'var(--gold)' }}>LIVE BUY PRESSURE BATTLE</div>
        <div className="display" style={{ fontSize: 44, letterSpacing: '-0.03em', lineHeight: 1 }}>The board.</div>
        <div style={{ color: 'var(--t2)', marginTop: 6 }}>
          All 48 country tokens ranked by 24h buy volume. Click any row to open the buy panel.
        </div>
      </div>

      <div style={{
        borderRadius: 18,
        background: 'linear-gradient(180deg, rgba(41,31,82,0.4), rgba(20,16,40,0.9))',
        border: '1px solid var(--hair)',
        overflow: 'hidden',
      }}>
        {/* Header */}
        <div style={{
          display: 'grid',
          gridTemplateColumns: '60px 60px 200px 1fr 140px 110px 110px 110px',
          gap: 12, padding: '12px 18px',
          background: 'rgba(0,0,0,0.4)',
          borderBottom: '1px solid var(--hair)',
        }}>
          {['RANK', 'FLAG', 'COUNTRY', '24H VOLUME', 'PRICE', '24h %', 'HOLDERS', 'MCAP'].map(h => (
            <div key={h} className="label" style={{ fontSize: 9 }}>{h}</div>
          ))}
        </div>
        {countries.map((c, i) => {
          const pct = ((c.volume24h || 0) / maxVol) * 100;
          return (
            <button key={c.code} onClick={() => onPick(c)} style={{
              display: 'grid',
              gridTemplateColumns: '60px 60px 200px 1fr 140px 110px 110px 110px',
              gap: 12, padding: '12px 18px',
              background: 'transparent', border: 0,
              borderBottom: '1px solid rgba(255,255,255,0.03)',
              width: '100%', textAlign: 'left', cursor: 'pointer',
              alignItems: 'center', color: 'inherit',
              transition: 'background 160ms',
            }}
            onMouseEnter={e => e.currentTarget.style.background = `rgba(${parseInt(c.color.slice(1,3),16)}, ${parseInt(c.color.slice(3,5),16)}, ${parseInt(c.color.slice(5,7),16)}, 0.06)`}
            onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
              <span className="display" style={{
                fontSize: 18,
                color: c.rank === 1 ? 'var(--gold)' : c.rank <= 3 ? 'var(--fifa-yellow)' : 'var(--t2)',
              }}>#{c.rank}</span>
              <FlagRect code={c.code} w={28} h={19} />
              <div>
                <div className="display" style={{ fontSize: 14, color: '#fff' }}>{c.code}</div>
                <div style={{ fontSize: 11, color: 'var(--t3)' }}>{c.name}</div>
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                <div style={{
                  flex: 1, height: 8, borderRadius: 4,
                  background: 'rgba(255,255,255,0.05)',
                  overflow: 'hidden', position: 'relative',
                  boxShadow: 'inset 0 1px 2px rgba(0,0,0,0.5)',
                }}>
                  <div style={{
                    position: 'absolute', inset: 0, width: pct + '%',
                    background: `linear-gradient(90deg, ${c.color}, ${c.secondary})`,
                    boxShadow: `0 0 12px ${c.color}, inset 0 1px 0 rgba(255,255,255,0.4)`,
                  }} />
                </div>
                <span className="mono" style={{ fontSize: 11, color: 'var(--t2)', fontWeight: 700, minWidth: 70 }}>{formatCountryVolume(c)}</span>
              </div>
              <span className="mono" style={{ fontSize: 13, fontWeight: 700 }}>{formatCountryPrice(c)}</span>
              <span className="mono" style={{ fontSize: 13, fontWeight: 700, color: c.change24h >= 0 ? 'var(--lime)' : 'var(--coral)' }}>
                {c.change24h >= 0 ? '+' : ''}{c.change24h.toFixed(1)}%
              </span>
              <span className="mono" style={{ fontSize: 13 }}>{fmtNum(c.holders)}</span>
              <span className="mono" style={{ fontSize: 13 }}>{formatCountryMarketCap(c)}</span>
            </button>
          );
        })}
      </div>
    </div>
  );
};

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