// cultural-market.jsx — Cultural & Market Considerations
// ─────────────────────────────────────────────────────────────────
// Beyond translation: per-territory rights conventions, royalty
// norms, naming conventions, cultural sensitivities, religious
// observances affecting release timing, sub-publishing customs,
// and tax/regulatory facts that affect catalog operations.
//
// Tabs:
//   01 ATLAS        — world map / heatmap of advisories per market
//   02 NORMS        — per-territory rights & royalty conventions
//   03 CALENDAR     — release-timing calendar (holidays, fasting,
//                     festivals, ad-blackout windows)
//   04 SENSITIVITY  — content advisories per market (lyric, artwork,
//                     sample policy, gov't censorship)
//   05 CUSTOMS      — sub-publishing customs (commission rates,
//                     advance norms, audit conventions)
//
// Exports: window.ScreenCulturalMarket, window.CULTURAL_MARKETS
// ─────────────────────────────────────────────────────────────────
(function () {
  if (typeof window === 'undefined' || !window.React) return;
  const _S = React.useState, _M = React.useMemo;

  // ─── Per-market cultural/market profile ────────────────────────
  // Real-world data: society conventions, cultural observances,
  // royalty norms, content sensitivities. Sourced from CISAC,
  // BIEM, IFPI 2024 reports.
  const CULTURAL_MARKETS = [
    {
      iso: 'US', flag: '🇺🇸', name: 'United States', region: 'NA',
      earningsRank: 1, marketShare: 35.4,
      pro: 'ASCAP / BMI / SESAC / GMR (writers may pick)',
      mro: 'HFA / MLC (statutory mech)',
      mechanicalRate: '$0.124 per phys. unit (12.4¢ statutory) · DSP rate via CRB Phonorecords IV',
      perfRoyaltyConvention: 'Performance: 50/50 writer/publisher. No general performance right for sound recordings on terrestrial radio.',
      culturalCalendar: [
        { date: 'JAN 1',          label: 'New Year — release cycle restart' },
        { date: 'NOV (4th Thu)',  label: 'Thanksgiving · Black Fri promo blackout for editorial' },
        { date: 'DEC 25',         label: 'Christmas — holiday playlist priority' },
      ],
      contentNotes: ['FCC enforcement on terrestrial broadcast (Carlin 7-words still live).', 'No formal lyric review; platforms self-moderate.'],
      subPubNorms: '15–25% commission · advance 50–80% of NPS · bi-annual statements',
      audit: 'GAAP · 3-year audit window typical · no statutory cap',
      hot: ['MMA / DLC compliance — match required to claim mech', 'CRB rate increases scheduled annually'],
      tone: 'standard',
    },
    {
      iso: 'GB', flag: '🇬🇧', name: 'United Kingdom', region: 'EU',
      earningsRank: 4, marketShare: 7.1,
      pro: 'PRS for Music',
      mro: 'MCPS (administered by PRS)',
      mechanicalRate: 'JOL: 8.5% of net DSP revenue · phys: 6.5% of PPD',
      perfRoyaltyConvention: 'Performance: 50/50 writer/publisher. PPL administers neighbouring rights for performers + labels (separate from PRS).',
      culturalCalendar: [
        { date: 'BANK HOLIDAYS', label: 'May Day, Spring, Summer — broadcast slow days' },
        { date: 'DEC 26',        label: 'Boxing Day — chart counted weekly' },
      ],
      contentNotes: ['Ofcom regulates broadcast content (watershed 9pm).', 'BBFC rates music videos for retail.'],
      subPubNorms: '10–20% commission · advances common · quarterly statements',
      audit: 'IFRS · 3-year audit window · MCPS audit rights statutory',
      hot: ['Post-Brexit: separate UK CRM authorisation (no longer EU-passported).'],
      tone: 'standard',
    },
    {
      iso: 'DE', flag: '🇩🇪', name: 'Germany', region: 'EU',
      earningsRank: 3, marketShare: 8.0,
      pro: 'GEMA',
      mro: 'GEMA (combined)',
      mechanicalRate: '9.009% of PPD (BIEM/IFPI standard)',
      perfRoyaltyConvention: 'GEMAvermutung — historical presumption of GEMA representation; abolished 2016 but admin culture lingers. Strict point-system payout.',
      culturalCalendar: [
        { date: 'MAY 1',        label: 'Tag der Arbeit — broadcasting limited' },
        { date: 'OCT 3',        label: 'Tag der Deutschen Einheit' },
        { date: 'DEC 24–26',    label: 'Weihnachten · physical-heavy market' },
      ],
      contentNotes: ['BPjM youth-protection: indexed releases excluded from public sale & ads.', 'Anti-Nazi clause (StGB §86a): swastikas, slogans = automatic block.', 'Strong moral-rights culture (Urheberpersönlichkeitsrecht): credits cannot be waived.'],
      subPubNorms: '15–25% commission · sub-pub typically excludes synch (separate deal)',
      audit: 'HGB · 5-year audit window · GEMA audit rights extensive',
      hot: ['Schiedsstelle (DPMA arbitration) before court for tariff disputes.', 'DSP rates set by Gesamtvertrag — collective negotiation.'],
      tone: 'standard',
    },
    {
      iso: 'FR', flag: '🇫🇷', name: 'France', region: 'EU',
      earningsRank: 5, marketShare: 5.5,
      pro: 'SACEM',
      mro: 'SDRM (administered by SACEM)',
      mechanicalRate: '11% of PPD (BIEM)',
      perfRoyaltyConvention: 'Performance: 33⅓ author / 33⅓ composer / 33⅓ publisher (3-way split when both author & composer present). Droit moral perpetual & inalienable.',
      culturalCalendar: [
        { date: 'JUL 14',     label: 'Bastille Day — high broadcast' },
        { date: 'AUG',        label: 'Vacances — entire month ad-light' },
        { date: 'JUN 21',     label: 'Fête de la Musique — free-music day' },
      ],
      contentNotes: ['Loi Toubon: 40% francophone quota on music radio (Loi du 1 fév 1994).', 'CSA / Arcom enforcement.', 'Droit moral cannot be assigned — credit and integrity rights stay with author forever.'],
      subPubNorms: '15–20% commission · French-territory deals frequently bundle author & publisher shares',
      audit: 'PCG · 5-year audit window · SDRM audit rights formal',
      hot: ['Quota enforcement = real rotation pressure; localization pays.', 'CMO arbitration via Médiateur de la Musique.'],
      tone: 'standard',
    },
    {
      iso: 'JP', flag: '🇯🇵', name: 'Japan', region: 'APAC',
      earningsRank: 2, marketShare: 11.4,
      pro: 'JASRAC (also NexTone)',
      mro: 'JASRAC',
      mechanicalRate: '6% of retail · CD market still ~50% of recorded',
      perfRoyaltyConvention: 'Performance: 50/50 writer/publisher (no separate composer/author). JASRAC blanket licensing dominant; NexTone competing since 2014.',
      culturalCalendar: [
        { date: 'JAN 1–3',    label: 'Shōgatsu — most operations closed' },
        { date: 'GOLDEN WEEK', label: 'Late Apr–early May · 4 holidays clustered' },
        { date: 'AUG 13–16',  label: 'Obon — release blackout common' },
        { date: 'DEC 31',     label: 'Kōhaku Uta Gassen broadcast — career-defining' },
      ],
      contentNotes: ['Strong physical (CD/vinyl) market — handakuten, choon-pu, kanji on packaging is mandatory.', 'Tatoo / yakuza imagery → broadcast risk on terrestrial.', 'Romaji + kanji + furigana titles all needed for full coverage.'],
      subPubNorms: '20–30% commission · 12-month advance + 3-year roll-over · annual statements',
      audit: 'J-GAAP · 3-year audit window',
      hot: ['NexTone alternative gaining DSP share (~12% by 2024).', 'Karaoke royalties significant (JOYSOUND/DAM blanket).'],
      tone: 'high',
    },
    {
      iso: 'KR', flag: '🇰🇷', name: 'South Korea', region: 'APAC',
      earningsRank: 7, marketShare: 2.4,
      pro: 'KOMCA (also FNCMS)',
      mro: 'KOMCA',
      mechanicalRate: '10.5% of net price · DSP rate negotiated with KCCA',
      perfRoyaltyConvention: 'Performance: 50/50. 2018 reform allowed competing CMOs; KOMCA still dominant.',
      culturalCalendar: [
        { date: 'JAN/FEB',    label: 'Seollal (lunar new year) — 3-day holiday' },
        { date: 'AUG 15',     label: 'Gwangbokjeol' },
        { date: 'CHUSEOK',    label: 'Mid-autumn 3-day · operations pause' },
      ],
      contentNotes: ['Hangul title required for KOMCA registration.', 'KMRB rates content for broadcast (G/12/15/19+).', 'Strict enforcement on smoking/alcohol imagery in MV broadcast.'],
      subPubNorms: '20–25% commission · advances common; K-pop ecosystem highly vertically integrated',
      audit: 'K-IFRS · 3-year window · KOMCA distribution detailed',
      hot: ['K-pop rights split: composers, lyricists, arrangers, top-liners often all separately credited.', 'MMS + Apple/Spotify share growing vs domestic Melon.'],
      tone: 'high',
    },
    {
      iso: 'CN', flag: '🇨🇳', name: 'China (Mainland)', region: 'APAC',
      earningsRank: 8, marketShare: 2.1,
      pro: 'MCSC (Music Copyright Society of China)',
      mro: 'MCSC',
      mechanicalRate: 'Effective ~3% of DSP revenue (negotiated, opaque)',
      perfRoyaltyConvention: 'Performance: 50/50 by convention; in practice CMRA + MCSC operate parallel systems. CMRA disputes MCSC monopoly.',
      culturalCalendar: [
        { date: 'JAN/FEB',    label: 'Spring Festival — 7-day national holiday, all-stop' },
        { date: 'OCT 1–7',    label: 'National Day Golden Week' },
        { date: 'JUN 4',      label: 'Sensitive date — DSP recommendation engines deboost political content' },
      ],
      contentNotes: ['NRTA pre-approval needed for foreign artist tour/MV.', 'NPNA blocks: any reference to Tibet/TW independence, Tiananmen, Falun Gong, prominent dissidents.', 'Lyric translation + simplified Chinese title required for all CMOs.', 'Romanization: pinyin standard, NOT Wade-Giles.'],
      subPubNorms: '25–35% commission · sub-pub MUST be onshore entity for collection · annual or longer audit cycle',
      audit: 'CAS · 3-year window but CMO data quality variable',
      hot: ['Tencent/NetEase exclusivity ban (2021) reshaped DSP economics.', 'Significant under-reporting risk; on-the-ground audit recommended.'],
      tone: 'critical',
    },
    {
      iso: 'BR', flag: '🇧🇷', name: 'Brazil', region: 'LATAM',
      earningsRank: 9, marketShare: 1.8,
      pro: 'ECAD (umbrella) — UBC, ABRAMUS, SOCINPRO, AMAR, SBACEM, ASSIM',
      mro: 'ECAD (mech via individual associations)',
      mechanicalRate: '7.5% of net retail · DSP per CISAC norms',
      perfRoyaltyConvention: 'Performance: 50/50 default. ECAD distributes; member assocs handle author registration. Notoriously slow.',
      culturalCalendar: [
        { date: 'CARNAVAL (FEB/MAR)', label: 'Carnival week — release peak window' },
        { date: 'JUN',                label: 'Festas Juninas — sertanejo seasonal peak' },
        { date: 'DEC 25 / 31',        label: 'Festas — pagode/samba peak' },
      ],
      contentNotes: ['Portuguese title strongly preferred; English-only releases lose airplay.', 'Classind ratings (LIVRE → 18) apply to MV content.'],
      subPubNorms: '15–25% commission · ECAD distribution lag 6–9 months · audit access via assoc',
      audit: 'BR-GAAP · 5-year window · ECAD distribution opaque historically',
      hot: ['ECAD distribution speed improving but still 9–12 months trail.', 'Funk/sertanejo radio plays hard to track via traditional CMOs.'],
      tone: 'standard',
    },
    {
      iso: 'MX', flag: '🇲🇽', name: 'Mexico', region: 'LATAM',
      earningsRank: 14, marketShare: 1.0,
      pro: 'SACM (writers) · EMMAC (publishers)',
      mro: 'SACM',
      mechanicalRate: '~10% of PPD',
      perfRoyaltyConvention: 'Performance: 60/40 writer/publisher (writer-favored, unusual).',
      culturalCalendar: [
        { date: 'NOV 1–2',    label: 'Día de Muertos — strong cultural moment' },
        { date: 'DEC 12',     label: 'Día de la Virgen de Guadalupe' },
        { date: 'SEP 16',     label: 'Independencia' },
      ],
      contentNotes: ['Spanish title preferred for radio rotation.', 'RTC ratings (AA, A, B, B-15, C, D) apply to MV broadcast.', 'Narcocorrido restrictions in some states (Sinaloa, Chihuahua).'],
      subPubNorms: '15–25% commission · semi-annual statements · SACM data improving',
      audit: 'NIF · 5-year window',
      hot: ['Regional Mexican (música mexicana) global growth — sub-pub rates competitive.'],
      tone: 'standard',
    },
    {
      iso: 'IN', flag: '🇮🇳', name: 'India', region: 'APAC',
      earningsRank: 14, marketShare: 1.1,
      pro: 'IPRS · also Novex (re-registered 2017)',
      mro: 'PPL India (recordings) · IPRS (works)',
      mechanicalRate: 'Statutory rate revisions ongoing · 2021 amendments boosted authors',
      perfRoyaltyConvention: 'Performance: 2012 Copyright Amendment guarantees authors equal share with assignees; 50/50 minimum to authors statutory.',
      culturalCalendar: [
        { date: 'DIWALI (OCT/NOV)', label: 'Festival of lights — Bollywood release peak' },
        { date: 'EID',              label: 'Two Eids — release timing factors' },
        { date: 'NAVRATRI',         label: 'Garba/dandiya 9-night period' },
      ],
      contentNotes: ['CBFC censors film music videos.', '22 official languages; Hindi + regional (Tamil, Telugu, Bengali, Marathi, Gujarati, Punjabi…) titles all relevant.', 'Devnagari + regional scripts on metadata.'],
      subPubNorms: '20–30% commission · advance norms changing · sub-pub onshore entity preferred',
      audit: 'Ind-AS · 3-year window',
      hot: ['Tamil + Telugu (Tollywood) revenue often exceeds Hindi for non-Bollywood catalogs.', 'IPRS distribution improving since 2017 reorg.'],
      tone: 'high',
    },
    {
      iso: 'SA', flag: '🇸🇦', name: 'Saudi Arabia', region: 'MENA',
      earningsRank: 25, marketShare: 0.4,
      pro: 'SAIP (just stood up; pre-CISAC affiliation)',
      mro: 'SAIP',
      mechanicalRate: 'Pre-tariff; DSP-by-DSP negotiation',
      perfRoyaltyConvention: 'New regime — copyright modernization 2020+. Pre-2020 CMO infrastructure essentially absent.',
      culturalCalendar: [
        { date: 'RAMADAN',    label: 'Month-long fasting · ad markets shift evening; entertainment cadence changes' },
        { date: 'EID AL-FITR', label: '3-day · post-Ramadan release peak' },
        { date: 'EID AL-ADHA', label: '4-day · Hajj period' },
        { date: 'SEP 23',     label: 'National Day' },
      ],
      contentNotes: ['Strict content review — alcohol, sexual content, LGBTQ+ themes blocked.', 'Arabic title strongly preferred.', 'Prayer times affect broadcast scheduling (5x/day).', 'Apple Music & Anghami dominant; YouTube blocked content varies.'],
      subPubNorms: 'Sub-pub onshore preferred · 25–35% commission given complexity · audit access limited',
      audit: 'IFRS · early-stage market data',
      hot: ['Vision 2030 entertainment liberalization growing market fast.', 'MDLBeast / Soundstorm festival now major cultural event.', 'Anghami IPO 2022 increased local DSP transparency.'],
      tone: 'critical',
    },
    {
      iso: 'NG', flag: '🇳🇬', name: 'Nigeria', region: 'AFRICA',
      earningsRank: 35, marketShare: 0.2,
      pro: 'COSON (suspended 2018) / MCSN (active)',
      mro: 'MCSN',
      mechanicalRate: 'CMO infrastructure recovering · variable enforcement',
      perfRoyaltyConvention: 'Disputed dual-CMO landscape; 2017 NCC suspended COSON. MCSN now operative but coverage gaps significant.',
      culturalCalendar: [
        { date: 'OCT 1',     label: 'Independence Day' },
        { date: 'EID + EASTER + CHRISTMAS', label: 'Multi-faith calendar; "Detty December" peak release window' },
      ],
      contentNotes: ['English dominant for international; Yoruba/Igbo/Hausa for regional reach.', 'NBC (broadcast regulator) restricts some content.', 'Nollywood sync market significant.'],
      subPubNorms: '20–30% commission · onshore entity advised · cash-collection complex',
      audit: 'IFRS · weak distribution data historically',
      hot: ['Afrobeats global breakout = sub-pub rates increasingly competitive.', 'Detty December (Dec 15–Jan 5) is THE release window for diaspora.', 'Boomplay + Audiomack are #1 DSPs (not Spotify).'],
      tone: 'high',
    },
    {
      iso: 'TR', flag: '🇹🇷', name: 'Turkey', region: 'MENA',
      earningsRank: 24, marketShare: 0.4,
      pro: 'MESAM, MSG (writers/composers)',
      mro: 'MESAM',
      mechanicalRate: 'BIEM-style ~9%',
      perfRoyaltyConvention: 'Two competing PROs (MESAM, MSG); writers must pick one. RATEM administers some perf rights.',
      culturalCalendar: [
        { date: 'RAMAZAN',    label: '30-day fasting · radio/event programming shifts' },
        { date: 'OCT 29',     label: 'Cumhuriyet Bayramı' },
      ],
      contentNotes: ['RTÜK regulates broadcast content; Kurdish-language quotas relaxed since 2009 but still sensitive.', 'Turkish title preferred.'],
      subPubNorms: '20–30% commission · TRY currency volatility complicates fixed advances',
      audit: 'TFRS (IFRS-aligned) · 3-year window',
      hot: ['Currency hedging often required in sub-pub contracts.', 'Strong domestic streaming via Fizy.'],
      tone: 'standard',
    },
    {
      iso: 'AU', flag: '🇦🇺', name: 'Australia', region: 'OCEANIA',
      earningsRank: 6, marketShare: 1.9,
      pro: 'APRA AMCOS',
      mro: 'AMCOS',
      mechanicalRate: 'BIEM-style 8.5–9%',
      perfRoyaltyConvention: '50/50 standard. APRA + AMCOS combined administration; one of the cleanest CMO setups globally.',
      culturalCalendar: [
        { date: 'JAN 26',     label: 'Australia Day (debate over date)' },
        { date: 'APR 25',     label: 'ANZAC Day — solemn programming' },
        { date: 'AFL/NRL',    label: 'Grand finals = broadcast peaks' },
      ],
      contentNotes: ['ACMA classification for broadcast.', 'Indigenous cultural protocols (ICIP) increasingly recognized for sample/use of First Nations material.'],
      subPubNorms: '15–20% commission · APRA AMCOS data quality high',
      audit: 'AAS · 3-year window',
      hot: ['ICIP guidelines from AIATSIS — sample clearance now multi-stakeholder for First Nations material.'],
      tone: 'standard',
    },
    {
      iso: 'SE', flag: '🇸🇪', name: 'Sweden', region: 'EU',
      earningsRank: 12, marketShare: 1.1,
      pro: 'STIM',
      mro: 'NCB (Nordic-wide)',
      mechanicalRate: 'BIEM 9.009% via NCB',
      perfRoyaltyConvention: 'NCB administers DK/FI/IS/NO/SE mechanicals jointly. STIM perf 50/50.',
      culturalCalendar: [
        { date: 'JUN 21–24',  label: 'Midsommar — most country offline' },
        { date: 'JUL',        label: 'Industry-wide vacation month' },
      ],
      contentNotes: ['Swedish title preferred for SVT broadcast.', 'High Spotify HQ origin = hyper-data-rich market.'],
      subPubNorms: '12–20% commission · NCB combined statements simplify Nordic admin',
      audit: 'IFRS · 5-year window · STIM data top-tier',
      hot: ['Nordic NCB administration = treat DK/FI/IS/NO/SE as one operationally.'],
      tone: 'standard',
    },
    {
      iso: 'CA', flag: '🇨🇦', name: 'Canada', region: 'NA',
      earningsRank: 11, marketShare: 1.4,
      pro: 'SOCAN',
      mro: 'CMRRA / SODRAC',
      mechanicalRate: 'CRB Phonorecords IV ~9.1¢ phys · DSP via tariff',
      perfRoyaltyConvention: '50/50. SOCAN dominant for perf; SOCAN + Re:Sound for neighbouring rights.',
      culturalCalendar: [
        { date: 'JUL 1',      label: 'Canada Day' },
        { date: 'JUN 24',     label: 'Saint-Jean (Quebec) — francophone broadcast peak' },
      ],
      contentNotes: ['CRTC Cancon: 35% Canadian content quota for English commercial radio, 65% French-language for francophone stations (Loi sur la radiodiffusion).', 'Quebec is effectively a francophone market — separate strategy.'],
      subPubNorms: '15–20% commission · Quebec sub-pub often separate',
      audit: 'IFRS · 5-year window',
      hot: ['Cancon quota = real airplay advantage for Canadian-registered works (MAPL system).'],
      tone: 'standard',
    },
  ];

  window.CULTURAL_MARKETS = CULTURAL_MARKETS;

  // ─── Helpers ──────────────────────────────────────────────────
  function Mono({ children, upper, size, color, style, ...rest }) {
    return <span className={'ff-mono' + (upper?' upper':'')} style={{ fontSize: size||11, color: color||'var(--ink)', letterSpacing: upper?'.08em':0, ...style }} {...rest}>{children}</span>;
  }
  const TONE = {
    standard: { c: '#0a8754', l: 'STANDARD', desc: 'Mature CMO, clear conventions, low operational risk' },
    high:     { c: '#d4881f', l: 'HIGH ATTN', desc: 'Cultural specifics affect rotation, registration, or release timing' },
    critical: { c: '#a32a18', l: 'CRITICAL',  desc: 'Censorship, on-shore entity, or emerging regulatory regime' },
  };
  const REGIONS = ['NA','EU','APAC','LATAM','MENA','AFRICA','OCEANIA'];

  // ─── 01 ATLAS ────────────────────────────────────────────────
  function AtlasTab({ onSelect }) {
    const total = CULTURAL_MARKETS.reduce((s, m) => s + m.marketShare, 0);
    const counts = { standard: 0, high: 0, critical: 0 };
    CULTURAL_MARKETS.forEach(m => counts[m.tone]++);

    return (
      <div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', borderTop: '1px solid var(--rule)', borderBottom: '1px solid var(--rule)', marginBottom: 24 }}>
          <Cell label="MARKETS PROFILED" value={CULTURAL_MARKETS.length} sub="major + emerging"/>
          <Cell label="STANDARD" value={counts.standard} sub="mature CMO, clear conventions" tone="#0a8754"/>
          <Cell label="HIGH ATTN" value={counts.high} sub="cultural specifics matter" tone="#d4881f"/>
          <Cell label="CRITICAL" value={counts.critical} sub="censorship / regime risk" tone="#a32a18"/>
        </div>

        {REGIONS.map(region => {
          const inRegion = CULTURAL_MARKETS.filter(m => m.region === region);
          if (inRegion.length === 0) return null;
          return (
            <div key={region} style={{ marginBottom: 28 }}>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginBottom: 10, padding: '0 0 8px', borderBottom: '1px solid var(--rule)' }}>
                <Mono upper size={10} color="var(--ink-3)">{region}</Mono>
                <span style={{ fontSize: 11, color: 'var(--ink-2)' }}>{inRegion.length} markets · {inRegion.reduce((s, m) => s + m.marketShare, 0).toFixed(1)}% of global</span>
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: 10 }}>
                {inRegion.map(m => {
                  const tm = TONE[m.tone];
                  return (
                    <button key={m.iso} onClick={() => onSelect(m.iso)} style={{
                      textAlign: 'left', padding: '14px 16px', border: '1px solid var(--rule)',
                      background: 'var(--paper)', cursor: 'pointer', position: 'relative',
                      borderLeft: '3px solid ' + tm.c,
                    }}>
                      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 6 }}>
                        <div>
                          <div style={{ fontSize: 14, fontWeight: 600 }}>{m.flag} {m.name}</div>
                          <Mono size={10} color="var(--ink-3)" style={{ marginTop: 2 }}>{m.iso} · #{m.earningsRank} · {m.marketShare}% global</Mono>
                        </div>
                        <Mono size={9} style={{ background: tm.c, color: '#fff', padding: '2px 5px', letterSpacing: '0.06em' }}>{tm.l}</Mono>
                      </div>
                      <div style={{ fontSize: 11, color: 'var(--ink-2)', marginTop: 8 }}>
                        {m.pro.split('/')[0].split('·')[0].trim()}
                      </div>
                    </button>
                  );
                })}
              </div>
            </div>
          );
        })}
      </div>
    );
  }

  // ─── DETAIL PANEL ────────────────────────────────────────────
  function MarketDetail({ market, onClose }) {
    if (!market) return null;
    const tm = TONE[market.tone];
    return (
      <div style={{ position: 'fixed', inset: 0, background: 'rgba(10,10,10,0.42)', zIndex: 1000, display: 'flex', justifyContent: 'flex-end' }} onClick={onClose}>
        <div onClick={(e) => e.stopPropagation()} style={{
          width: 'min(720px, 92vw)', height: '100vh', background: 'var(--bg)', overflow: 'auto',
          borderLeft: '1px solid var(--rule)',
        }}>
          {/* Header */}
          <div style={{ padding: '24px 32px', borderBottom: '1px solid var(--rule)', background: 'var(--bg-2)' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
              <div>
                <Mono upper size={9} color="var(--ink-3)" style={{ marginBottom: 8, display: 'block' }}>
                  {market.region} · {market.iso} · GLOBAL #{market.earningsRank} · {market.marketShare}% SHARE
                </Mono>
                <div className="ff-display" style={{ fontSize: 32, fontWeight: 600, letterSpacing: '-0.02em' }}>
                  {market.flag} {market.name}
                </div>
                <Mono size={10} style={{ background: tm.c, color: '#fff', padding: '3px 7px', letterSpacing: '0.08em', display: 'inline-block', marginTop: 10 }}>
                  {tm.l} · {tm.desc}
                </Mono>
              </div>
              <button onClick={onClose} style={{ background: 'transparent', border: 0, fontSize: 24, cursor: 'pointer', color: 'var(--ink-3)' }}>×</button>
            </div>
          </div>

          {/* Body sections */}
          <div style={{ padding: '24px 32px', display: 'flex', flexDirection: 'column', gap: 28 }}>
            <Section label="RIGHTS INFRASTRUCTURE">
              <KV k="Performing Rights">{market.pro}</KV>
              <KV k="Mechanical Rights">{market.mro}</KV>
              <KV k="Mechanical Rate">{market.mechanicalRate}</KV>
              <KV k="Royalty Convention">{market.perfRoyaltyConvention}</KV>
            </Section>

            <Section label="CULTURAL CALENDAR · RELEASE TIMING">
              <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                {market.culturalCalendar.map((c, i) => (
                  <div key={i} style={{ display: 'grid', gridTemplateColumns: '160px 1fr', gap: 14, alignItems: 'baseline', padding: '8px 0', borderBottom: i < market.culturalCalendar.length - 1 ? '1px solid var(--rule-soft)' : 0 }}>
                    <Mono size={11} color="var(--ink-2)">{c.date}</Mono>
                    <div style={{ fontSize: 13 }}>{c.label}</div>
                  </div>
                ))}
              </div>
            </Section>

            <Section label="CONTENT & CULTURAL ADVISORIES">
              <ul style={{ paddingLeft: 16, margin: 0, fontSize: 13, lineHeight: 1.6, color: 'var(--ink-2)' }}>
                {market.contentNotes.map((note, i) => <li key={i} style={{ marginBottom: 6 }}>{note}</li>)}
              </ul>
            </Section>

            <Section label="SUB-PUBLISHING CUSTOMS">
              <KV k="Commission norms">{market.subPubNorms}</KV>
              <KV k="Audit framework">{market.audit}</KV>
            </Section>

            <Section label="HOT NOTES · RECENT DEVELOPMENTS">
              <ul style={{ paddingLeft: 16, margin: 0, fontSize: 13, lineHeight: 1.6 }}>
                {market.hot.map((h, i) => <li key={i} style={{ marginBottom: 6, color: 'var(--ink)' }}>{h}</li>)}
              </ul>
            </Section>
          </div>
        </div>
      </div>
    );
  }

  function Section({ label, children }) {
    return (
      <div>
        <Mono upper size={9} color="var(--ink-3)" style={{ marginBottom: 12, display: 'block', paddingBottom: 6, borderBottom: '1px solid var(--rule)' }}>{label}</Mono>
        <div>{children}</div>
      </div>
    );
  }
  function KV({ k, children }) {
    return (
      <div style={{ display: 'grid', gridTemplateColumns: '170px 1fr', gap: 14, padding: '7px 0', borderBottom: '1px solid var(--rule-soft)' }}>
        <Mono upper size={9} color="var(--ink-3)">{k}</Mono>
        <div style={{ fontSize: 12.5, lineHeight: 1.55 }}>{children}</div>
      </div>
    );
  }

  // ─── 02 NORMS TAB ─────────────────────────────────────────────
  function NormsTab({ onSelect }) {
    return (
      <div style={{ border: '1px solid var(--rule)' }}>
        <div style={{ display: 'grid', gridTemplateColumns: '32px 60px 180px 1fr 1fr 90px', gap: 10, padding: '10px 14px', background: 'var(--bg-2)', borderBottom: '1px solid var(--rule)' }}>
          <Mono upper size={9} color="var(--ink-3)">#</Mono>
          <Mono upper size={9} color="var(--ink-3)">ISO</Mono>
          <Mono upper size={9} color="var(--ink-3)">MARKET</Mono>
          <Mono upper size={9} color="var(--ink-3)">PRO / MRO</Mono>
          <Mono upper size={9} color="var(--ink-3)">RATE / CONVENTION</Mono>
          <Mono upper size={9} color="var(--ink-3)" style={{ textAlign: 'right' }}>STATUS</Mono>
        </div>
        {CULTURAL_MARKETS.sort((a, b) => a.earningsRank - b.earningsRank).map(m => {
          const tm = TONE[m.tone];
          return (
            <div key={m.iso} onClick={() => onSelect(m.iso)} style={{
              display: 'grid', gridTemplateColumns: '32px 60px 180px 1fr 1fr 90px', gap: 10,
              padding: '10px 14px', borderBottom: '1px solid var(--rule-soft)', cursor: 'pointer',
            }}
            onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-2)'}
            onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
              <Mono size={11} color="var(--ink-3)">{m.earningsRank}</Mono>
              <Mono size={11}>{m.iso}</Mono>
              <div>
                <div style={{ fontSize: 12.5, fontWeight: 500 }}>{m.flag} {m.name}</div>
                <Mono size={10} color="var(--ink-3)" style={{ marginTop: 1 }}>{m.region} · {m.marketShare}% global</Mono>
              </div>
              <div style={{ fontSize: 11, lineHeight: 1.5, color: 'var(--ink-2)' }}>{m.pro}</div>
              <div style={{ fontSize: 11, lineHeight: 1.5, color: 'var(--ink-2)' }}>{m.mechanicalRate}</div>
              <Mono size={9} style={{ background: tm.c, color: '#fff', padding: '2px 5px', letterSpacing: '0.06em', textAlign: 'center', alignSelf: 'center', justifySelf: 'end' }}>{tm.l}</Mono>
            </div>
          );
        })}
      </div>
    );
  }

  // ─── 03 CALENDAR TAB ──────────────────────────────────────────
  function CalendarTab({ onSelect }) {
    const allEntries = [];
    CULTURAL_MARKETS.forEach(m => {
      m.culturalCalendar.forEach(c => allEntries.push({ ...c, market: m }));
    });
    return (
      <div>
        <div style={{ padding: '14px 18px', background: 'var(--bg-2)', border: '1px solid var(--rule)', marginBottom: 22 }}>
          <Mono upper size={9} color="var(--ink-3)" style={{ marginBottom: 4, display: 'block' }}>RELEASE-TIMING ADVISORY</Mono>
          <div style={{ fontSize: 12, color: 'var(--ink-2)', lineHeight: 1.5 }}>
            Major cultural moments and observances by market. Use to align release windows, avoid blackout periods, and capture seasonal listening peaks.
          </div>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(360px, 1fr))', gap: 14 }}>
          {CULTURAL_MARKETS.map(m => (
            <div key={m.iso} style={{ border: '1px solid var(--rule)', overflow: 'hidden' }}>
              <button onClick={() => onSelect(m.iso)} style={{
                display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%',
                padding: '10px 14px', background: 'var(--bg-2)', border: 0, borderBottom: '1px solid var(--rule)',
                cursor: 'pointer', textAlign: 'left',
              }}>
                <div style={{ fontSize: 13, fontWeight: 600 }}>{m.flag} {m.name}</div>
                <Mono size={10} color="var(--ink-3)">{m.region}</Mono>
              </button>
              <div style={{ padding: '10px 14px' }}>
                {m.culturalCalendar.map((c, i) => (
                  <div key={i} style={{ display: 'grid', gridTemplateColumns: '120px 1fr', gap: 10, padding: '6px 0', borderBottom: i < m.culturalCalendar.length - 1 ? '1px solid var(--rule-soft)' : 0 }}>
                    <Mono size={10} color="var(--ink-2)">{c.date}</Mono>
                    <div style={{ fontSize: 11.5, color: 'var(--ink)' }}>{c.label}</div>
                  </div>
                ))}
              </div>
            </div>
          ))}
        </div>
      </div>
    );
  }

  // ─── 04 SENSITIVITY TAB ───────────────────────────────────────
  function SensitivityTab({ onSelect }) {
    const sorted = [...CULTURAL_MARKETS].sort((a, b) => {
      const order = { critical: 0, high: 1, standard: 2 };
      return order[a.tone] - order[b.tone];
    });
    return (
      <div>
        <div style={{ padding: '14px 18px', background: '#a32a1808', borderLeft: '3px solid #a32a18', marginBottom: 22 }}>
          <Mono upper size={10} color="#a32a18">CONTENT REVIEW BEFORE RELEASE</Mono>
          <div style={{ fontSize: 12, marginTop: 4, color: 'var(--ink-2)', lineHeight: 1.5 }}>
            Per-market content sensitivities affecting lyric, artwork, MV, sample policy, and broadcast clearance. Run this checklist before territory-specific release.
          </div>
        </div>
        {sorted.map(m => {
          const tm = TONE[m.tone];
          return (
            <div key={m.iso} style={{ border: '1px solid var(--rule)', marginBottom: 12, borderLeft: '3px solid ' + tm.c }}>
              <button onClick={() => onSelect(m.iso)} style={{
                display: 'grid', gridTemplateColumns: '1fr 90px', gap: 10, width: '100%',
                padding: '12px 18px', background: 'var(--bg-2)', border: 0, borderBottom: '1px solid var(--rule-soft)',
                cursor: 'pointer', textAlign: 'left', alignItems: 'center',
              }}>
                <div>
                  <div style={{ fontSize: 14, fontWeight: 600 }}>{m.flag} {m.name}</div>
                  <Mono size={10} color="var(--ink-3)" style={{ marginTop: 2 }}>{m.contentNotes.length} advisor{m.contentNotes.length === 1 ? 'y' : 'ies'}</Mono>
                </div>
                <Mono size={9} style={{ background: tm.c, color: '#fff', padding: '3px 6px', letterSpacing: '0.08em', textAlign: 'center', justifySelf: 'end' }}>{tm.l}</Mono>
              </button>
              <ul style={{ paddingLeft: 38, margin: 0, padding: '12px 18px 14px 38px', fontSize: 12.5, lineHeight: 1.6, color: 'var(--ink-2)' }}>
                {m.contentNotes.map((note, i) => <li key={i} style={{ marginBottom: 4 }}>{note}</li>)}
              </ul>
            </div>
          );
        })}
      </div>
    );
  }

  // ─── 05 CUSTOMS TAB ───────────────────────────────────────────
  function CustomsTab({ onSelect }) {
    return (
      <div style={{ border: '1px solid var(--rule)' }}>
        <div style={{ display: 'grid', gridTemplateColumns: '60px 200px 1fr 1fr', gap: 10, padding: '10px 14px', background: 'var(--bg-2)', borderBottom: '1px solid var(--rule)' }}>
          <Mono upper size={9} color="var(--ink-3)">ISO</Mono>
          <Mono upper size={9} color="var(--ink-3)">MARKET</Mono>
          <Mono upper size={9} color="var(--ink-3)">SUB-PUB CUSTOMS</Mono>
          <Mono upper size={9} color="var(--ink-3)">AUDIT FRAMEWORK</Mono>
        </div>
        {CULTURAL_MARKETS.map(m => (
          <div key={m.iso} onClick={() => onSelect(m.iso)} style={{
            display: 'grid', gridTemplateColumns: '60px 200px 1fr 1fr', gap: 10,
            padding: '11px 14px', borderBottom: '1px solid var(--rule-soft)', cursor: 'pointer',
          }}
          onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-2)'}
          onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
            <Mono size={11}>{m.iso}</Mono>
            <div>
              <div style={{ fontSize: 12.5, fontWeight: 500 }}>{m.flag} {m.name}</div>
              <Mono size={10} color="var(--ink-3)" style={{ marginTop: 1 }}>{m.region}</Mono>
            </div>
            <div style={{ fontSize: 11.5, lineHeight: 1.55, color: 'var(--ink-2)' }}>{m.subPubNorms}</div>
            <div style={{ fontSize: 11.5, lineHeight: 1.55, color: 'var(--ink-2)' }}>{m.audit}</div>
          </div>
        ))}
      </div>
    );
  }

  // ─── Cell ────────────────────────────────────────────────────
  function Cell({ label, value, sub, tone }) {
    return (
      <div style={{ padding: '18px 22px', borderRight: '1px solid var(--rule)' }}>
        <Mono upper size={9} color="var(--ink-3)">{label}</Mono>
        <div className="ff-display" style={{ fontSize: 26, fontWeight: 600, letterSpacing: '-0.02em', marginTop: 4, color: tone || 'var(--ink)' }}>{value}</div>
        <div style={{ fontSize: 11, color: 'var(--ink-2)', marginTop: 3 }}>{sub}</div>
      </div>
    );
  }

  // ─── MAIN SCREEN ─────────────────────────────────────────────
  function ScreenCulturalMarket({ go, payload }) {
    const PageHeader = window.PageHeader;
    const [tab, setTab] = _S(payload?.tab || 'atlas');
    const [selectedIso, setSelectedIso] = _S(null);

    const TABS = [
      { k: 'atlas',       l: 'Atlas' },
      { k: 'norms',       l: 'Rights & Norms' },
      { k: 'calendar',    l: 'Cultural Calendar' },
      { k: 'sensitivity', l: 'Content Sensitivity' },
      { k: 'customs',     l: 'Sub-Pub Customs' },
    ];

    const selectedMarket = _M(() => CULTURAL_MARKETS.find(m => m.iso === selectedIso), [selectedIso]);

    return (
      <div>
        {PageHeader && (
          <PageHeader
            eyebrow={['LOCALIZATION', 'TERRITORY OPERATIONS', `${CULTURAL_MARKETS.length} MARKETS`]}
            title="cultural & market."
            highlight="cultural & market."
            sub="Per-territory rights conventions, royalty norms, cultural calendars, content sensitivities, and sub-publishing customs across major and emerging markets."
          />
        )}

        <div style={{ borderBottom: '1px solid var(--rule)', display: 'flex', gap: 0, marginBottom: 24 }}>
          {TABS.map(t => (
            <button key={t.k} onClick={() => setTab(t.k)} style={{
              padding: '14px 22px', background: 'transparent', border: 0,
              borderBottom: '2px solid ' + (tab === t.k ? 'var(--ink)' : 'transparent'),
              cursor: 'pointer', color: tab === t.k ? 'var(--ink)' : 'var(--ink-3)',
              fontSize: 13, fontWeight: tab === t.k ? 600 : 400,
            }}>{t.l}</button>
          ))}
        </div>

        {tab === 'atlas'       && <AtlasTab       onSelect={setSelectedIso}/>}
        {tab === 'norms'       && <NormsTab       onSelect={setSelectedIso}/>}
        {tab === 'calendar'    && <CalendarTab    onSelect={setSelectedIso}/>}
        {tab === 'sensitivity' && <SensitivityTab onSelect={setSelectedIso}/>}
        {tab === 'customs'     && <CustomsTab     onSelect={setSelectedIso}/>}

        {selectedMarket && <MarketDetail market={selectedMarket} onClose={() => setSelectedIso(null)}/>}
      </div>
    );
  }

  window.ScreenCulturalMarket = ScreenCulturalMarket;

  console.log('[CulturalMarket] loaded · ' + CULTURAL_MARKETS.length + ' markets · ' + REGIONS.length + ' regions');
})();
