// Aggregate Findings page — all the deep-dive data from the new PDF

function SectionHead({ eyebrow, title, lede, n, base, action }) {
  return (
    <div style={{ paddingBottom: 32, marginBottom: 32, borderBottom: '1px solid var(--rule)' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 16 }}>
        <div className="eyebrow sans">{eyebrow}</div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
          {(base || n) &&
            <div className="eyebrow sans" style={{ textAlign: 'right' }}>
              {base}{base && n ? ' · ' : ''}{n ? 'n = ' + fmtNum(n) : ''}
            </div>}
          {action}
        </div>
      </div>
      <h2 style={{ marginTop: 8, maxWidth: '24ch' }}>{title}</h2>
      {lede && <p style={{ maxWidth: '58ch', color: 'var(--ink-2)', fontSize: 17, marginTop: 14, marginBottom: 0 }}>{lede}</p>}
    </div>);

}

function MiniBars({ items, highlight, valueKey = 'v', labelKey = 'label', max = null, color = 'var(--accent-data)' }) {
  const m = max || Math.max(...items.map((x) => x[valueKey] || 0));
  return (
    <div data-keep-cols className="uchart-rows" style={{ display: 'grid', gridTemplateColumns: 'minmax(140px, 32%) 1fr 56px', gap: 10, alignItems: 'center' }}>
      {items.map((it, i) =>
      <React.Fragment key={i}>
          <div style={{ fontFamily: 'Inter Tight, sans-serif', fontSize: 13, color: 'var(--fg)', lineHeight: 1.25 }}>
            {it[labelKey]}
          </div>
          <div style={{ position: 'relative', height: 18, background: 'var(--surface-2)' }}>
            <div style={{ position: 'absolute', inset: 0, width: it[valueKey] / m * 100 + '%',
            background: highlight && highlight(it, i) ? 'var(--brand)' : color }} />
          </div>
          <div className="mono" style={{ textAlign: 'right',
          fontFamily: 'JetBrains Mono, monospace', fontSize: 12, fontVariantNumeric: 'tabular-nums' }}>
            {fmtPct(it[valueKey], 0)}
          </div>
        </React.Fragment>
      )}
    </div>);

}

function AwarenessOwnershipBlock({ aggregate }) {
  const exRef = useRef(null);
  const awareness = [
  { label: 'Bitcoin', v: aggregate.awareness.bitcoin, hl: true },
  { label: 'Ethereum (ETH)', v: aggregate.awareness.ethereum },
  { label: 'Binance Coin (BNB)', v: aggregate.awareness.binance },
  { label: 'Dogecoin', v: aggregate.awareness.dogecoin },
  { label: 'Stablecoins', v: aggregate.awareness.stablecoins }];

  const ownership = [
  { label: 'Bitcoin — currently own', v: aggregate.ownership.bitcoinCurrent, hl: true },
  { label: 'Bitcoin — previously, no longer', v: aggregate.ownership.bitcoinPrevious },
  { label: 'Bitcoin — ever owned (current + past)', v: aggregate.ownership.bitcoinEver },
  { label: 'Stablecoins — ever owned', v: aggregate.ownership.stablecoinsEver }];

  return (
    <section className="section" style={{ paddingBottom: 48 }} ref={exRef}>
      <SectionHead eyebrow="01 · Awareness & ownership"
      action={<ExportButton targetRef={exRef} filename="cbai-awareness-ownership.png"/>}
      title="Awareness is highest for Bitcoin — by far."
      lede="Bitcoin awareness means simply having heard of it — not understanding how it works. On that measure it is nearly universal, and ahead of every other cryptocurrency. Ownership, shown as a share of all survey respondents, tells a very different story."
      n={25880} base="All survey respondents" />
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 48 }}>
        <div>
          <div className="eyebrow sans" style={{ marginBottom: 10 }}>Awareness — heard of</div>
          <MiniBars items={awareness} highlight={(it) => it.hl} />
        </div>
        <div>
          <div className="eyebrow sans" style={{ marginBottom: 10 }}>Ownership</div>
          <MiniBars items={ownership} highlight={(it) => it.hl} />
        </div>
      </div>
    </section>);

}

function HoldingBlock({ aggregate }) {
  const exRef = useRef(null);
  return (
    <section className="section" style={{ padding: '48px 0' }} ref={exRef}>
      <SectionHead eyebrow="02 · Where owners keep their bitcoin"
      action={<ExportButton targetRef={exRef} filename="cbai-how-owners-hold.png"/>}
      title="Most keep bitcoin in a digital wallet."
      lede='45% name a digital wallet as their primary method of holding, more than exchanges (28%) and ETFs (9%) combined. A physical hardware wallet is the primary method for just 4.6%.'
      n={3589} base="Current Bitcoin owners" />
      <div style={{ display: 'grid', gridTemplateColumns: '1.2fr .8fr', gap: 48 }}>
        <div>
          <MiniBars items={aggregate.holdMethod} color="var(--accent-data)" />
          <p style={{ fontFamily: 'Inter Tight, sans-serif', fontSize: 12, color: 'var(--muted)', marginTop: 14, fontStyle: 'italic', lineHeight: 1.5 }}>
            Respondents were not asked who controls the private keys, and no custodial-wallet option was offered.
            The wallet categories therefore report a method of holding rather than verified self-custody.
          </p>
        </div>
        <div>
          <div className="eyebrow sans" style={{ marginBottom: 10 }}>% of savings/investments in Bitcoin (current owners)</div>
          <MiniBars items={aggregate.pctSavings} />
          <p style={{ fontFamily: 'Inter Tight, sans-serif', fontSize: 12.5, color: 'var(--muted)', marginTop: 14 }}>
            Most owners hold a small share. 20% hold less than 1%; just over 60% hold less than 15%.
            But 8% hold more than half of their assets in Bitcoin.
          </p>
        </div>
      </div>
    </section>);

}

function KnowledgeTile({ label, value, unit, footnote }) {
  return (
    <div style={{ background: 'var(--surface)', padding: '18px 18px' }}>
      <div className="eyebrow sans" style={{ marginBottom: 8 }}>{label}</div>
      <div style={{ fontFamily: 'Source Serif 4, serif', fontSize: 36, letterSpacing: '-0.02em', lineHeight: 1, display: 'flex', alignItems: 'baseline', gap: 6, marginBottom: 8 }}>
        <span>{value}</span>
        <span style={{ fontSize: '.42em', color: 'var(--muted)', fontFamily: 'Inter Tight, sans-serif', fontWeight: 500 }}>{unit}</span>
      </div>
      {footnote && <div style={{ fontFamily: 'Inter Tight, sans-serif', fontSize: 11.5, color: 'var(--muted)', lineHeight: 1.4 }}>{footnote}</div>}
    </div>
  );
}

function KnowledgeBlock({ aggregate }) {
  const exRef = useRef(null);
  const items = aggregate.supplyCap;
  return (
    <section className="section" style={{ padding: '48px 0' }} ref={exRef}>
      <SectionHead eyebrow="03 · Knowledge"
      action={<ExportButton targetRef={exRef} filename="cbai-knowledge.png"/>}
      title="On every measure, knowledge is shallow — even among owners."
      lede="Only 13% of those aware of Bitcoin know its supply is capped at 21 million. 58% said 'don't know.'"
      n={23393} base="Aware of Bitcoin" />
      <div style={{ display: 'grid', gridTemplateColumns: '1.4fr .6fr', gap: 48 }}>
        <div>
          <div className="eyebrow sans" style={{ marginBottom: 10 }}>How many Bitcoin can ever exist?</div>
          <MiniBars items={items}
          highlight={(it) => it.correct}
          color="var(--accent-neutral)" />
        </div>
        <div style={{ display: 'grid', gap: 1, background: 'var(--rule)', border: '1px solid var(--rule)', alignSelf: 'start' }}>
          {/* Self-reported knowledge — Bitcoin */}
          <KnowledgeTile
            label="Self-reported knowledge: Bitcoin"
            value={aggregate.knowledge.bitcoin.mean.toFixed(1)}
            unit="/ 10"
            footnote={`Mean self-rating ("How much do you know about bitcoin?", 1–10 scale). Among bitcoin-aware respondents, n=${fmtNum(aggregate.knowledge.bitcoin.n)}.`} />
          {/* Self-reported knowledge — Stablecoins */}
          <KnowledgeTile
            label="Self-reported knowledge: Stablecoins"
            value={aggregate.knowledge.stablecoins.mean.toFixed(1)}
            unit="/ 10"
            footnote={`Same scale, asked of the smaller pool who'd heard of stablecoins (n=${fmtNum(aggregate.knowledge.stablecoins.n)}). They rate themselves higher than bitcoin-aware respondents do on bitcoin.`} />
        </div>
      </div>
    </section>);

}

function PerceptionsBlock({ aggregate }) {
  // aware vs owners side by side
  const fields = [
  ['Bitcoin increases financial freedom', 'financialFreedom'],
  ['Bitcoin is easy to use', 'easyToUse'],
  ['Bitcoin protects my privacy', 'protectsPrivacy'],
  ['Bitcoin reduces transaction fees', 'reducesFees'],
  ['Bitcoin is volatile', 'volatile'],
  ['Bitcoin is confusing', 'confusing'],
  ['Bitcoin is prone to fraud', 'proneToFraud']];

  const tip = useTooltip();
  const exRef = useRef(null);
  return (
    <section className="section" style={{ padding: '48px 0' }} ref={exRef}>
      <SectionHead eyebrow="04 · Perceptions of Bitcoin"
      action={<ExportButton targetRef={exRef} filename="cbai-perceptions.png"/>}
      title="Owners and non-owners see very different Bitcoins."
      lede='Among those aware, only 47% agree Bitcoin increases financial freedom. Among current owners that share rises to 79%. The same pattern repeats across "easy to use," "protects privacy," and "reduces fees."'
      n={23393} base="Aware of Bitcoin" />

      <div style={{ background: 'var(--surface-2)', border: '1px solid var(--rule)', borderLeft: '3px solid var(--accent-data)', padding: '12px 16px', marginBottom: 22, maxWidth: '72ch', fontFamily: 'Inter Tight, sans-serif', fontSize: 13, color: 'var(--ink-2)', lineHeight: 1.55 }}>
        <strong style={{ color: 'var(--fg)' }}>“Financial freedom”</strong> here means agreeing (a 5–7 rating on a 1–7 scale) that bitcoin gives a person more control over their own money — the ability to save, send, and hold value without needing permission from a bank or government.
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr', gap: 14 }}>
        <div data-keep-cols className="sans uperc-row" style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr 42px 1fr 42px 70px', gap: 12, fontFamily: 'Inter Tight, sans-serif', fontSize: 12, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '.08em', paddingBottom: 8, borderBottom: '1px solid var(--rule)' }}>
          <div>Statement (% rated above neutral, 5–7 of 1–7)</div>
          <div style={{ gridColumn: 'span 2' }}>All aware (n=23,393)</div>
          <div style={{ gridColumn: 'span 2' }}>Current owners (n=3,589)</div>
          <div style={{ textAlign: 'right' }}>Δ</div>
        </div>
        {fields.map(([label, key]) => {
          const aware = aggregate.perceptions.aware[key];
          const owners = aggregate.perceptions.owners[key];
          const delta = owners - aware;
          return (
            <div key={key} data-keep-cols className="uperc-row" style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr 42px 1fr 42px 70px', gap: 12, alignItems: 'center', padding: '4px 0' }}>
              <div style={{ fontFamily: 'Source Serif 4, serif', fontSize: 16 }}>{label}</div>
              <div style={{ position: 'relative', height: 14, background: 'var(--surface-2)' }}>
                <div style={{ position: 'absolute', inset: 0, width: aware * 100 + '%', background: 'var(--accent-neutral)' }} />
              </div>
              <div className="mono" style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 12, fontVariantNumeric: 'tabular-nums', color: 'var(--fg)' }}>{fmtPct(aware, 0)}</div>
              <div style={{ position: 'relative', height: 14, background: 'var(--surface-2)' }}>
                <div style={{ position: 'absolute', inset: 0, width: owners * 100 + '%', background: 'var(--accent-data)' }} />
              </div>
              <div className="mono" style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 12, fontVariantNumeric: 'tabular-nums', color: 'var(--fg)' }}>{fmtPct(owners, 0)}</div>
              <div className="mono" style={{ textAlign: 'right', fontFamily: 'JetBrains Mono, monospace', fontSize: 12, color: delta > 0 ? 'var(--accent-data)' : 'var(--ink-2)', fontWeight: 600 }}>
                {delta > 0 ? '+' : ''}{(delta * 100).toFixed(0)}pp
              </div>
            </div>);

        })}
      </div>
    </section>);

}

function ReasonsBlock({ aggregate }) {
  const exRef = useRef(null);
  return (
    <section className="section" style={{ padding: '48px 0' }} ref={exRef}>
      <SectionHead eyebrow="05 · Why people use — or don't"
      action={<ExportButton targetRef={exRef} filename="cbai-reasons.png"/>}
      title="Investment leads. Inaccessibility lags."
      lede="Among owners, investment opportunity (79%) and personal freedom (73%) are the most cited reasons. Among non-owners, the top reason is simply lack of interest (37%); the second is not being able to afford it." base="Current owners & non-owners (aware, never owned)" />
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 48 }}>
        <div>
          <div className="eyebrow sans" style={{ marginBottom: 10 }}>Why current owners use bitcoin · n = 3,589</div>
          <MiniBars items={aggregate.whyUse}
          highlight={(it, i) => i < 3}
          color="var(--accent-data)" />
          <p style={{ fontFamily: 'Inter Tight, sans-serif', fontSize: 12.5, color: 'var(--muted)', marginTop: 12 }}>
            % saying each reason is "important" or "very important" (top 2 of 1–5 scale).
          </p>
        </div>
        <div>
          <div className="eyebrow sans" style={{ marginBottom: 10 }}>Why non-owners have never owned · n = 15,116</div>
          <MiniBars items={aggregate.whyNever}
          highlight={(it, i) => i < 3}
          color="var(--accent-neutral)" />
          <p style={{ fontFamily: 'Inter Tight, sans-serif', fontSize: 12.5, color: 'var(--muted)', marginTop: 12 }}>
            Multi-select — % of non-owners selecting each reason.
          </p>
        </div>
      </div>
    </section>);

}

function RiskBlock({ aggregate }) {
  const entries = Object.entries(aggregate.risk).sort((a, b) => b[1].higher - a[1].higher);
  const exRef = useRef(null);
  return (
    <section className="section" style={{ padding: '48px 0' }} ref={exRef}>
      <SectionHead eyebrow="06 · Relative risk"
      action={<ExportButton targetRef={exRef} filename="cbai-risk.png"/>}
      title="Bitcoin vs. other assets."
      lede="The gap is narrower than expected. 49% see bitcoin as riskier than gold (the highest comparison). Only 34% see it as riskier than stocks (the lowest). For every asset class, about 1 in 5 respondents actually see bitcoin as the safer option."
      n={23393} base="Aware of Bitcoin" />
      <div style={{ display: 'grid', gap: 1, background: 'var(--rule)', border: '1px solid var(--rule)' }}>
        <div data-keep-cols className="sans urisk-row" style={{ display: 'grid', gridTemplateColumns: '1fr 1.5fr 80px 80px 80px', gap: 12, background: 'var(--surface)', padding: '12px 16px', fontFamily: 'Inter Tight, sans-serif', fontSize: 11, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '.08em' }}>
          <div>Vs. asset</div>
          <div>Distribution</div>
          <div style={{ textAlign: 'right' }}>Higher</div>
          <div style={{ textAlign: 'right' }}>Equal</div>
          <div style={{ textAlign: 'right' }}>Lower</div>
        </div>
        {entries.map(([asset, row]) =>
        <div key={asset} data-keep-cols className="urisk-row" style={{ display: 'grid', gridTemplateColumns: '1fr 1.5fr 80px 80px 80px', gap: 12, background: 'var(--surface)', padding: '10px 16px', alignItems: 'center' }}>
            <div style={{ fontFamily: 'Source Serif 4, serif', fontSize: 15 }}>{asset}</div>
            <div className="stack" style={{ height: 18 }}>
              <span style={{ width: row.higher * 100 + '%', background: 'var(--brand)' }} />
              <span style={{ width: row.equal * 100 + '%', background: 'var(--accent-neutral)' }} />
              <span style={{ width: row.lower * 100 + '%', background: 'var(--accent-data)' }} />
            </div>
            <div className="mono" style={{ textAlign: 'right', fontSize: 12 }}>{fmtPct(row.higher, 0)}</div>
            <div className="mono" style={{ textAlign: 'right', fontSize: 12, color: 'var(--muted)' }}>{fmtPct(row.equal, 0)}</div>
            <div className="mono" style={{ textAlign: 'right', fontSize: 12 }}>{fmtPct(row.lower, 0)}</div>
          </div>
        )}
      </div>
      <div style={{ fontFamily: 'Inter Tight, sans-serif', fontSize: 11, color: 'var(--muted)', marginTop: 12, display: 'flex', gap: 18 }}>
        <span><span style={{ display: 'inline-block', width: 10, height: 10, background: 'var(--brand)', marginRight: 5, verticalAlign: 'middle' }} /> Bitcoin is higher risk</span>
        <span><span style={{ display: 'inline-block', width: 10, height: 10, background: 'var(--accent-neutral)', marginRight: 5, verticalAlign: 'middle' }} /> Equal risk</span>
        <span><span style={{ display: 'inline-block', width: 10, height: 10, background: 'var(--accent-data)', marginRight: 5, verticalAlign: 'middle' }} /> Lower risk</span>
      </div>
    </section>);

}

function DemographicBlock({ aggregate }) {
  // Render ownByDemo as a comparison
  const groups = [
  { l: 'Gender', items: [['Men', aggregate.ownByDemo.men], ['Women', aggregate.ownByDemo.women]] },
  { l: 'Age', items: [['18–29', aggregate.ownByDemo.age_18_29], ['30–44', aggregate.ownByDemo.age_30_44], ['45–64', aggregate.ownByDemo.age_45_64], ['65+', aggregate.ownByDemo.age_65plus]] },
  { l: 'Income', items: [['High', aggregate.ownByDemo.high_income], ['Middle', aggregate.ownByDemo.mid_income], ['Low', aggregate.ownByDemo.low_income]] },
  { l: 'Education', items: [['College+', aggregate.ownByDemo.college], ['No college', aggregate.ownByDemo.no_college]] },
  { l: 'Trust in government', items: [['Trust', aggregate.ownByDemo.trust_govt], ['Distrust', aggregate.ownByDemo.no_trust_govt]] },
  { l: 'Confidence in financial institutions', items: [['High', aggregate.ownByDemo.trust_finance], ['Low', aggregate.ownByDemo.no_trust_finance]] }];

  const maxv = 0.22;
  const exRef = useRef(null);
  return (
    <section className="section" style={{ padding: '48px 0' }} ref={exRef}>
      <SectionHead eyebrow="09 · Demographics"
      action={<ExportButton targetRef={exRef} filename="cbai-demographics.png"/>}
      title="Who owns bitcoin?"
      lede="Bitcoin ownership skews male, college-educated, and high-income. Trust in government is a positive predictor — perhaps surprisingly. The effect of confidence in financial institutions is small and statistically insignificant." base="Among those aware of Bitcoin" />
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 1, background: 'var(--rule)', border: '1px solid var(--rule)' }}>
        {groups.map((g) =>
        <div key={g.l} style={{ background: 'var(--surface)', padding: '22px 24px' }}>
            <div className="eyebrow sans" style={{ marginBottom: 14 }}>{g.l}</div>
            {g.items.map(([n, v]) =>
          <div key={n} data-keep-cols className="uchart-rows" style={{ display: 'grid', gridTemplateColumns: '80px 1fr 48px', gap: 8, alignItems: 'center', marginBottom: 6 }}>
                <div style={{ fontFamily: 'Inter Tight, sans-serif', fontSize: 13 }}>{n}</div>
                <div style={{ height: 14, background: 'var(--surface-2)' }}>
                  <div style={{ height: '100%', width: v / maxv * 100 + '%', background: 'var(--accent-data)' }} />
                </div>
                <div className="mono" style={{ textAlign: 'right', fontSize: 12 }}>{fmtPct(v, 0)}</div>
              </div>
          )}
          </div>
        )}
      </div>
    </section>);

}

function TopCountriesBlock({ summary }) {
  const exRef = useRef(null);
  const top = [...summary.perCountry]
    .filter(r => r.ownEver != null)
    .sort((a, b) => (b.ownEver || 0) - (a.ownEver || 0))
    .slice(0, 3);
  return (
    <section className="section" style={{ padding: '8px 0 48px' }}>
      <div ref={exRef} style={{ position: 'relative', background: 'var(--surface)', border: '1px solid var(--rule)', borderTop: '3px solid var(--brand)', padding: '28px 30px' }}>
        <div data-noexport="1" style={{ position: 'absolute', top: 16, right: 18 }}><ExportButton targetRef={exRef} filename="cbai-top-countries.png"/></div>
        <div className="eyebrow sans" style={{ marginBottom: 8 }}>Where bitcoin use is highest</div>
        <h2 style={{ marginTop: 0, marginBottom: 10, maxWidth: '22ch' }}>The top three countries have one thing in common.</h2>
        <p style={{ maxWidth: '68ch', color: 'var(--ink-2)', fontSize: 16, marginTop: 0, marginBottom: 24 }}>
          Ranked by the share of all respondents who have <strong>ever owned bitcoin</strong>, the
          leaders are not wealthy financial centers — they are economies where the national
          currency has been unstable and everyday access to dollars or reliable banking is hard.
          In each, bitcoin functions less as a speculative bet and more as a practical workaround.
        </p>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 1, background: 'var(--rule)', border: '1px solid var(--rule)' }}>
          {top.map((r, i) => (
            <div key={r.name} style={{ background: 'var(--surface)', padding: '22px 22px' }}>
              <div className="eyebrow sans" style={{ marginBottom: 10, color: 'var(--brand)' }}>#{i + 1}</div>
              <div style={{ fontFamily: 'Source Serif 4, serif', fontSize: 24, marginBottom: 4 }}>
                <span style={{ marginRight: 8 }}>{flagEmoji(COUNTRY_META[r.name]?.iso || '')}</span>{titleCase(r.name)}
              </div>
              <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 12, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '.1em', marginBottom: 12 }}>{fmtPct(r.ownEver, 0)} ever owned</div>
            </div>
          ))}
        </div>
        <p style={{ fontFamily: 'Inter Tight, sans-serif', fontStyle: 'italic', fontSize: 12.5, color: 'var(--muted)', marginTop: 16, marginBottom: 0 }}>
          Shared traits: high or volatile inflation, currency or capital controls, and large
          numbers of people underserved by traditional banks.
        </p>
      </div>
    </section>);
}

function FindingsPage({ data }) {
  const { aggregate } = data;
  return (
    <div className="container" style={{ paddingTop: 56 }}>
      <div className="eyebrow sans">Key findings</div>
      <h1 style={{ maxWidth: '22ch', margin: '12px 0 16px' }}>What 25,880 people told us about bitcoin.</h1>
      <p style={{ maxWidth: '62ch', color: 'var(--ink-2)', fontSize: 18 }}>
        Headline numbers from all 25,880 respondents across 25 countries, pooled and weighted.
        For country-by-country detail, use the Country Explorer; for raw question banner data,
        use the Question Explorer.
      </p>
      <AwarenessOwnershipBlock aggregate={aggregate} />
      <TopCountriesBlock summary={data.summary} />
      <HoldingBlock aggregate={aggregate} />
      <KnowledgeBlock aggregate={aggregate} />
      <PerceptionsBlock aggregate={aggregate} />
      <ReasonsBlock aggregate={aggregate} />
      <RiskBlock aggregate={aggregate} />
      <HeatmapBlock summary={data.summary} />
      <GroupedOwnershipBlock summary={data.summary} />
      <DemographicBlock aggregate={aggregate} />
    </div>);

}

const REGIME_GROUPS = [
{ label: 'Democracies', members: ['BRAZIL', 'SWITZERLAND', 'INDIA', 'INDONESIA', 'ARGENTINA', 'SOUTH KOREA', 'US', 'PHILIPPINES', 'SOUTH AFRICA', 'POLAND', 'JAPAN', 'ITALY'] },
{ label: 'Hybrid regimes', members: ['EL SALVADOR', 'TURKEY', 'UKRAINE', 'NIGERIA', 'KENYA', 'MEXICO'] },
{ label: 'Authoritarian regimes', members: ['UAE', 'VENEZUELA', 'RUSSIA', 'LEBANON', 'SAUDI ARABIA'] }];

const INCOME_GROUPS = [
{ label: 'Lower income tier', members: ['EL SALVADOR', 'VENEZUELA', 'UKRAINE', 'INDIA', 'INDONESIA', 'NIGERIA', 'KENYA', 'PHILIPPINES'] },
{ label: 'Middle income tier', members: ['TURKEY', 'BRAZIL', 'RUSSIA', 'ARGENTINA', 'SOUTH AFRICA', 'LEBANON', 'MEXICO'] },
{ label: 'Upper income tier', members: ['UAE', 'SWITZERLAND', 'SOUTH KOREA', 'US', 'SAUDI ARABIA', 'POLAND', 'JAPAN', 'ITALY'] }];

function GroupedOwnershipBlock({ summary }) {
  const [mode, setMode] = useState('regime');
  const exRef = useRef(null);
  const byName = {};
  summary.perCountry.forEach((c) => byName[c.name] = c);
  const groups = mode === 'regime' ? REGIME_GROUPS : INCOME_GROUPS;
  const SCALE = 0.30;

  return (
    <section className="section" style={{ padding: '48px 0' }} ref={exRef}>
      <SectionHead eyebrow="08 · Cross-national comparisons"
      action={<ExportButton targetRef={exRef} filename={`cbai-ownership-by-${mode}.png`}/>}
      title={mode === 'regime' ? 'Regime type does not sort adoption.' : 'Adoption is highest in the lower income tier.'}
      lede={mode === 'regime' ?
      'Grouping countries by regime classification produces more variation within each group than between them. Democracies run from 19.6% (Brazil) to 6.3% (Italy); authoritarian countries from 20.9% (UAE) to 9.8% (Saudi Arabia).' :
      'In six of the eight lower-income-tier countries, more than 15% of respondents own bitcoin — true of fewer than half the countries in the middle and upper tiers. Within tiers the spread stays wide: 19.6% in Brazil against 6.9% in Mexico.'}
      n={23807} base="Aware of Bitcoin, excl. China & Hong Kong" />

      <div className="sans" style={{ display: 'flex', gap: 8, marginBottom: 26, flexWrap: 'wrap' }}>
        {[['regime', 'By political regime'], ['income', 'By income tier']].map(([k, l]) =>
        <button key={k} onClick={() => setMode(k)} className="sans"
        style={{ padding: '9px 15px', fontSize: 12, cursor: 'pointer', whiteSpace: 'nowrap', border: '1px solid ' + (mode === k ? 'var(--ink)' : 'var(--rule)'),
          background: mode === k ? 'var(--ink)' : 'transparent', color: mode === k ? 'var(--paper)' : 'var(--fg)' }}>
          {l}
        </button>
        )}
      </div>

      <div style={{ display: 'grid', gap: 30 }}>
        {groups.map((g) => {
          const rows = g.members.
          map((m) => ({ name: m, v: byName[m] ? byName[m].ownCurrent : null })).
          filter((r) => r.v != null).
          sort((a, b) => b.v - a.v);
          return (
            <div key={g.label}>
              <div className="eyebrow sans" style={{ color: 'var(--brand)', marginBottom: 12 }}>{g.label}</div>
              <div data-keep-cols className="uchart-rows" style={{ display: 'grid', gridTemplateColumns: 'minmax(120px, 22%) 1fr 56px', gap: '7px 10px', alignItems: 'center' }}>
                {rows.map((r) =>
                <React.Fragment key={r.name}>
                    <div style={{ fontFamily: 'Inter Tight, sans-serif', fontSize: 13 }}>{titleCase(r.name)}</div>
                    <div style={{ position: 'relative', height: 16, background: 'var(--surface-2)' }}>
                      <div style={{ position: 'absolute', inset: 0, width: Math.min(100, r.v / SCALE * 100) + '%', background: 'var(--accent-data)' }} />
                    </div>
                    <div className="mono" style={{ textAlign: 'right', fontFamily: 'JetBrains Mono, monospace', fontSize: 12, fontVariantNumeric: 'tabular-nums' }}>
                      {(r.v * 100).toFixed(1)}%
                    </div>
                  </React.Fragment>
                )}
              </div>
            </div>);

        })}
      </div>

      <p style={{ fontFamily: 'Inter Tight, sans-serif', fontSize: 12.5, color: 'var(--muted)', marginTop: 20, maxWidth: '76ch', lineHeight: 1.55 }}>
        Common scale, 0–30%. China and Hong Kong are excluded: Bitcoin-ownership questions were not fielded there.
        Income tiers follow World Bank GNI per capita. Comparisons across tiers should be read with care — how closely an
        online sample tracks the general adult population varies by country.
      </p>
    </section>);

}

function HeatmapBlock({ summary }) {
  const { countries, perCountry } = summary;
  const tip = useTooltip();
  const exRef = useRef(null);

  // Rows: each demographic group
  const rows = [
  { label: 'Adults', accessor: (r) => r.ownCurrentAware },
  { label: 'Gender: Male', accessor: (r) => r.byDemo?.men },
  { label: 'Gender: Female', accessor: (r) => r.byDemo?.women },
  { label: 'Age: 18–29', accessor: (r) => r.byDemo?.age_18_29 },
  { label: 'Age: 30–44', accessor: (r) => r.byDemo?.age_30_44 },
  { label: 'Age: 45–64', accessor: (r) => r.byDemo?.age_45_64 },
  { label: 'Age: 65+', accessor: (r) => r.byDemo?.age_65plus },
  { label: 'Higher income', accessor: (r) => r.byDemo?.high_income },
  { label: 'Medium income', accessor: (r) => r.byDemo?.mid_income },
  { label: 'Lower income', accessor: (r) => r.byDemo?.low_income },
  { label: "Bachelor's degree or higher", accessor: (r) => r.byDemo?.college },
  { label: "Less than bachelor's degree", accessor: (r) => r.byDemo?.no_college },
  { label: 'Trust government', accessor: (r) => r.byDemo?.trust_govt },
  { label: 'Do not trust government', accessor: (r) => r.byDemo?.no_trust_govt },
  { label: 'Trust financial institutions', accessor: (r) => r.byDemo?.trust_finance },
  { label: 'Do not trust financial institutions', accessor: (r) => r.byDemo?.no_trust_finance }];


  // Cornell-aligned sequential ramp, 6 buckets
  const BUCKETS = [
  { max: 0.05, color: '#B31B1B', label: '0–5%' }, // Cornell carnelian
  { max: 0.10, color: '#E89999', label: '5–10%' }, // Light carnelian
  { max: 0.15, color: '#D47500', label: '10–15%' }, // Cornell orange
  { max: 0.20, color: '#E5C547', label: '15–20%' }, // Yellow
  { max: 0.25, color: '#9FAD9F', label: '20–25%' }, // Cornell sage green
  { max: 1.00, color: '#4B7B2B', label: '25%+' } // Cornell green
  ];

  function bucketColor(v) {
    if (v == null) return null;
    for (const b of BUCKETS) if (v <= b.max) return b.color;
    return BUCKETS[BUCKETS.length - 1].color;
  }
  function bucketTextColor(v) {
    if (v == null) return 'var(--muted)';
    // Yellow / sage / pink → dark text; red / orange / dark green → white
    if (v > 0.15 && v <= 0.25) return '#222';
    if (v > 0.05 && v <= 0.10) return '#222';
    return '#fff';
  }

  return (
    <section className="section" style={{ padding: '48px 0' }} ref={exRef}>
      <SectionHead eyebrow="07 · How the world holds wealth"
      title="Respondents who own bitcoin (%)"
      base="Among those aware of Bitcoin"
      action={<ExportButton targetRef={exRef} filename="cbai-ownership-heatmap.png"/>}
      lede="Each cell is the share of that demographic group, in that country, who currently own bitcoin — among those aware of Bitcoin. Color encodes the bucket. China and Hong Kong show 0 owners — data was not collected for current ownership in those countries due to regulatory constraints." />

      <div style={{ overflowX: 'auto' }}>
        <table style={{ borderCollapse: 'separate', borderSpacing: 0, width: '100%', minWidth: 1100, tableLayout: 'fixed' }}>
          <thead>
            <tr>
              <th style={{ position: 'sticky', left: 0, background: 'var(--surface)', zIndex: 1, padding: '8px 12px 8px 0', textAlign: 'left', width: 230, fontFamily: 'Inter Tight, sans-serif', fontSize: 11, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '.08em', fontWeight: 500 }}>Category</th>
              {countries.map((c) =>
              <th key={c} style={{ padding: '8px 2px', textAlign: 'center', verticalAlign: 'bottom', fontFamily: 'Inter Tight, sans-serif', fontSize: 10.5, color: 'var(--muted)', fontWeight: 500, height: 120 }}>
                  <div style={{ transform: 'rotate(-65deg)', transformOrigin: 'left bottom', whiteSpace: 'nowrap', position: 'relative', left: '50%' }}>
                    {titleCase(c)}
                  </div>
                </th>
              )}
            </tr>
          </thead>
          <tbody>
            {rows.map((row, ri) =>
            <tr key={row.label}>
                <th style={{ position: 'sticky', left: 0, background: 'var(--surface)', zIndex: 1, padding: '4px 12px 4px 0', textAlign: 'left', fontFamily: 'Inter Tight, sans-serif', fontSize: 12, color: 'var(--fg)', fontWeight: 500, borderTop: '1px solid var(--rule)' }}>
                  {row.label}
                </th>
                {countries.map((c, ci) => {
                const v = row.accessor(perCountry[ci]);
                const bg = bucketColor(v);
                const fg = bucketTextColor(v);
                return (
                  <td key={c}
                  style={{ padding: 0, height: 30, textAlign: 'center', verticalAlign: 'middle',
                    background: bg || 'repeating-linear-gradient(45deg, var(--surface-2), var(--surface-2) 4px, var(--surface) 4px, var(--surface) 7px)',
                    color: fg,
                    border: '1px solid var(--surface)',
                    fontFamily: 'JetBrains Mono, monospace', fontSize: 10.5, fontVariantNumeric: 'tabular-nums', cursor: v != null ? 'default' : 'help' }}
                  onMouseEnter={(e) => tip.show(e, v == null ?
                  `<strong>${titleCase(c)}</strong><div class="tv">${row.label} — ${c === 'CHINA' || c === 'HONG KONG' ? 'not collected' : 'suppressed (fewer than 50 respondents)'}</div>` :
                  `<strong>${titleCase(c)}</strong><div class="tv">${row.label} — ${Math.round(v * 100)}%</div>`)}
                  onMouseMove={tip.move}
                  onMouseLeave={tip.hide}>
                      {v == null ? '' : Math.round(v * 100)}
                    </td>);

              })}
              </tr>
            )}
          </tbody>
        </table>
      </div>

      {/* Legend */}
      <div style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'center', alignItems: 'center', gap: 18, marginTop: 22, fontFamily: 'Inter Tight, sans-serif', fontSize: 12, color: 'var(--ink-2)' }}>
        <span style={{ fontFamily: 'Inter Tight, sans-serif', fontSize: 11, textTransform: 'uppercase', letterSpacing: '.08em', color: 'var(--muted)', fontWeight: 600 }}>Key:</span>
        {BUCKETS.map((b) =>
        <span key={b.label} style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
            <span style={{ display: 'inline-block', width: 18, height: 18, background: b.color, border: '1px solid rgba(0,0,0,.08)' }} />
            {b.label}
          </span>
        )}
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
          <span style={{ display: 'inline-block', width: 18, height: 18, background: 'repeating-linear-gradient(45deg, var(--surface-2), var(--surface-2) 4px, var(--surface) 4px, var(--surface) 7px)', border: '1px solid rgba(0,0,0,.08)' }} />
          No data
        </span>
      </div>

      <p style={{ fontFamily: 'Inter Tight, sans-serif', fontStyle: 'italic', fontSize: 12.5, color: 'var(--muted)', marginTop: 18, textAlign: 'center', maxWidth: '70ch', marginLeft: 'auto', marginRight: 'auto' }}>
        Cells based on fewer than 50 respondents are suppressed rather than shown — including Lebanon's trust-in-government and confidence-in-financial-institutions groups, its higher-income group, and the 65+ group in several countries. Data on current bitcoin ownership in China and Hong Kong was not collected due to regulatory constraints.
      </p>
    </section>);

}

window.HeatmapBlock = HeatmapBlock;