// ============================================================================
// Principia White Paper — Chart library (part 2: flow, economics, structure)
// ============================================================================

// ════════════════════════════════════════════════════════════════════════
// FIG — From 5 intermediaries to zero (settlement flow comparison)
// ════════════════════════════════════════════════════════════════════════
function IntermediaryFlow() {
  const [ref, seen] = useReveal();
  const today = ['Sender', 'Originating bank', 'Correspondent', 'Correspondent', 'Beneficiary bank', 'Recipient'];
  const ours = ['Sender', 'Digital Bank — direct settlement', 'Recipient'];

  const Node = ({ label, tone, i, n }) => (
    <div style={{
      flex: tone === 'hub' ? '1.4 1 min(180px, 35vw)' : '1 1 min(100px, 20vw)',
      minWidth: 'min(100px, 20vw)',
      padding: 'clamp(10px, 2vw, 14px) clamp(6px, 1.5vw, 10px)',
      borderRadius: 10,
      background: tone === 'hub' ? C_INK : tone === 'end' ? '#fff' : C_SURF2,
      color: tone === 'hub' ? '#fff' : C_INK,
      border: tone === 'hub' ? 'none' : `1px solid ${tone === 'end' ? C_RULE_STRONG : C_RULE}`,
      textAlign: 'center',
      fontFamily: FONT_SANS, fontSize: 12.5, fontWeight: 600, lineHeight: 1.25,
      opacity: seen ? 1 : 0, transform: seen ? 'translateY(0)' : 'translateY(8px)',
      transition: `opacity .5s ${EASE} ${i * 0.08}s, transform .5s ${EASE} ${i * 0.08}s`,
    }}>{label}</div>
  );
  const Arrow = ({ i, danger }) => (
    <div style={{
      flexShrink: 0, color: danger ? C_DANGER : C_SUCCESS, fontSize: 18, fontWeight: 700,
      opacity: seen ? 0.8 : 0, transition: `opacity .4s ${EASE} ${i * 0.08 + 0.1}s`,
    }}>→</div>
  );

  return (
    <div ref={ref} style={{ display: 'flex', flexDirection: 'column', gap: 26 }}>
      <div>
        <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 12, flexWrap: 'wrap', gap: 4 }}>
          <span style={{ fontFamily: FONT_MONO, fontSize: 10.5, letterSpacing: '0.16em', color: C_DANGER, textTransform: 'uppercase', fontWeight: 600 }}>Today · 5–7 parties</span>
          <span style={{ fontFamily: FONT_MONO, fontSize: 10.5, letterSpacing: '0.12em', color: C_MUTED, textTransform: 'uppercase' }}>$15–35 per hop · any bank can exit</span>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 7, flexWrap: 'wrap', rowGap: 10 }}>
          {today.map((t, i) => (
            <React.Fragment key={i}>
              <Node label={t} tone={i === 0 || i === today.length - 1 ? 'end' : 'mid'} i={i} />
              {i < today.length - 1 && <Arrow i={i} danger />}
            </React.Fragment>
          ))}
        </div>
      </div>

      <div style={{ height: 1, background: C_RULE }} />

      <div>
        <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 12, flexWrap: 'wrap', gap: 4 }}>
          <span style={{ fontFamily: FONT_MONO, fontSize: 10.5, letterSpacing: '0.16em', color: C_SUCCESS, textTransform: 'uppercase', fontWeight: 600 }}>Our model · 2 parties</span>
          <span style={{ fontFamily: FONT_MONO, fontSize: 10.5, letterSpacing: '0.12em', color: C_MUTED, textTransform: 'uppercase' }}>€0.002 per instant payment · cannot be de-risked</span>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
          {ours.map((t, i) => (
            <React.Fragment key={i}>
              <Node label={t} tone={i === 1 ? 'hub' : 'end'} i={i + today.length} />
              {i < ours.length - 1 && <Arrow i={i + today.length} />}
            </React.Fragment>
          ))}
        </div>
      </div>
    </div>
  );
}

// ════════════════════════════════════════════════════════════════════════
// FIG — Partner economics: net margin per $200 transfer (+105%)
// ════════════════════════════════════════════════════════════════════════
function MarginCompare() {
  const [ref, seen] = useReveal();
  const mobile = useIsMobile(640);
  const H = mobile ? 200 : 300, MAX = 16;
  const cols = [
    {
      title: 'Today', tone: C_DANGER,
      segs: [
        { label: 'Net margin', value: 4.0, color: C_INK, net: true, display: '$4.00' },
        { label: 'Compliance + ops', value: 4.0, color: 'rgba(91,107,133,0.45)', display: '–$4.00' },
        { label: 'Intermediary fees', value: 8.0, color: C_DANGER2, display: '–$8.00' },
      ],
    },
    {
      title: 'On our rails', tone: C_SUCCESS,
      segs: [
        { label: 'Net margin', value: 8.2, color: C_SUCCESS, net: true, display: '$8.20' },
        { label: 'Payout (mobile money)', value: 4.0, color: 'rgba(91,107,133,0.45)', display: '–$4.00' },
        { label: 'Our fee (1.90%)', value: 3.8, color: C_ACCENT, display: '–$3.80' },
      ],
    },
  ];
  const netToday = useCountUp(4, seen, { decimals: 2 });
  const netOurs = useCountUp(8.2, seen, { decimals: 2 });
  return (
    <div ref={ref} style={{ display: 'flex', flexDirection: mobile ? 'column' : 'row', gap: mobile ? 24 : 'clamp(20px, 4vw, 44px)', alignItems: mobile ? 'stretch' : 'stretch' }}>
      <div style={{ display: 'flex', gap: 'clamp(16px, 3vw, 30px)', flex: mobile ? 'none' : '1 1 min(400px, 100%)' }}>
        {cols.map((col, ci) => (
          <div key={col.title} style={{ flex: 1, display: 'flex', flexDirection: 'column' }}>
            <div style={{ display: 'flex', alignItems: 'flex-end', gap: 18, height: H }}>
              <div style={{ width: 64, height: H, display: 'flex', flexDirection: 'column-reverse', borderRadius: '0 0 6px 6px', overflow: 'hidden', flexShrink: 0 }}>
                {col.segs.map((s, si) => (
                  <div key={si} title={s.label} style={{
                    height: seen ? (s.value / MAX) * H : 0,
                    background: s.color,
                    transition: `height .9s ${EASE} ${ci * 0.15 + si * 0.1}s`,
                    borderTop: s.net ? 'none' : `1px solid rgba(255,255,255,0.55)`,
                  }} />
                ))}
              </div>
              <div style={{ flex: 1, display: 'flex', flexDirection: 'column', height: H, justifyContent: 'center', gap: 16 }}>
                {col.segs.slice().reverse().map((s, si) => (
                  <div key={si} style={{
                    display: 'flex', alignItems: 'flex-start', gap: 9,
                    opacity: seen ? 1 : 0, transform: seen ? 'translateX(0)' : 'translateX(-6px)',
                    transition: `all .5s ${EASE} ${ci * 0.15 + si * 0.1 + 0.4}s`,
                  }}>
                    <span style={{ width: 11, height: 11, borderRadius: 3, background: s.color, flexShrink: 0, marginTop: 3 }} />
                    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', flex: 1, gap: 8, borderBottom: s.net ? `1px solid ${C_RULE}` : 'none', paddingBottom: s.net ? 6 : 0 }}>
                      <span style={{ fontFamily: FONT_SANS, fontSize: 12.5, fontWeight: s.net ? 700 : 500, color: s.net ? C_INK : C_MUTED, lineHeight: 1.25 }}>{s.label}</span>
                      <span style={{ fontFamily: FONT_MONO, fontSize: 12.5, color: s.net ? s.color : C_MUTED, fontWeight: 600, whiteSpace: 'nowrap' }}>{s.display}</span>
                    </div>
                  </div>
                ))}
              </div>
            </div>
            <div style={{ marginTop: 14, paddingTop: 12, borderTop: `2px solid ${col.tone}`, textAlign: 'left' }}>
              <div style={{ fontFamily: FONT_MONO, fontSize: 10, letterSpacing: '0.16em', textTransform: 'uppercase', color: C_MUTED }}>{col.title}</div>
              <div style={{ fontFamily: FONT_DISP, fontSize: 38, color: col.tone, letterSpacing: '-0.02em', lineHeight: 1.1 }}>
                ${ci === 0 ? netToday : netOurs}
              </div>
              <div style={{ fontFamily: FONT_SANS, fontSize: 12.5, color: C_MUTED }}>net margin · per $200 transfer</div>
            </div>
          </div>
        ))}
      </div>
      <div style={{
        flex: mobile ? 'none' : '0 0 auto',
        minWidth: mobile ? undefined : 168,
        display: 'flex', flexDirection: mobile ? 'row' : 'column',
        alignItems: mobile ? 'center' : 'stretch',
        justifyContent: mobile ? 'flex-start' : 'center',
        gap: mobile ? 16 : 0,
        borderLeft: mobile ? 'none' : `1px solid ${C_RULE}`,
        borderTop: mobile ? `1px solid ${C_RULE}` : 'none',
        paddingLeft: mobile ? 0 : 'clamp(16px, 3vw, 30px)',
        paddingTop: mobile ? 20 : 0,
      }}>
        <div style={{ fontFamily: FONT_DISP, fontSize: mobile ? 42 : 58, color: C_SUCCESS, lineHeight: 0.95, letterSpacing: '-0.03em', flexShrink: 0 }}>+105%</div>
        <div style={{ fontFamily: FONT_SANS, fontSize: mobile ? 13 : 14, color: C_MUTED, marginTop: mobile ? 0 : 10, lineHeight: 1.5 }}>
          net margin improvement. Same price to the customer. Same volume — four layers of intermediaries removed.
        </div>
      </div>
    </div>
  );
}

// ════════════════════════════════════════════════════════════════════════
// FIG — Competitive matrix (capabilities × providers)
// ════════════════════════════════════════════════════════════════════════
function CompetitiveMatrix() {
  const [ref, seen] = useReveal(0.12);
  const mobile = useIsMobile(640);
  const caps = [
    'Direct ECB (TARGET2 / TIPS)',
    'Direct BoE (FPS / CHAPS)',
    'Nordic direct (SEK / DKK / NOK)',
    'MC / Visa principal membership',
    'Own POS acquiring stack',
    'Sub-Saharan Africa corridor',
    'Zero intermediary dependency',
  ];
  // 2 = full, 1 = partial, 0 = none
  const providers = [
    { name: 'Banking Circle', vals: [2, 0, 1, 0, 0, 0, 0], score: '2 / 7' },
    { name: 'ClearBank', vals: [0, 2, 0, 0, 0, 0, 0], score: '1 / 7' },
    { name: 'Modulr', vals: [0, 0, 0, 2, 0, 0, 0], score: '1 / 7' },
    { name: 'Digital Bank', vals: [2, 2, 2, 2, 2, 2, 2], score: '7 / 7', us: true },
  ];
  const Dot = ({ v, us, delay }) => {
    const color = v === 2 ? (us ? '#fff' : C_INK) : v === 1 ? C_ACCENT : 'transparent';
    return (
      <span style={{ display: 'inline-flex', width: 22, height: 22, alignItems: 'center', justifyContent: 'center',
        opacity: seen ? 1 : 0, transform: seen ? 'scale(1)' : 'scale(0.5)', transition: `all .4s ${EASE} ${delay}s` }}>
        {v === 1 ? (
          <span style={{ width: 16, height: 16, borderRadius: '50%', background: `linear-gradient(90deg, ${color} 50%, ${us ? 'rgba(255,255,255,0.2)' : 'rgba(10,31,61,0.12)'} 50%)`, border: `1.5px solid ${color}` }} />
        ) : v === 2 ? (
          <span style={{ width: 16, height: 16, borderRadius: '50%', background: color }} />
        ) : (
          <span style={{ width: 14, height: 14, borderRadius: '50%', border: `1.5px solid ${us ? 'rgba(255,255,255,0.3)' : 'rgba(10,31,61,0.15)'}` }} />
        )}
      </span>
    );
  };
  if (mobile) {
    const StatusIcon = ({ v }) => v === 2 ? <span style={{ color: C_SUCCESS, fontWeight: 700 }}>✓</span> : v === 1 ? <span style={{ color: C_ACCENT, fontWeight: 700 }}>½</span> : <span style={{ color: C_MUTED }}>—</span>;
    return (
      <div ref={ref} style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        {providers.map((p) => (
          <div key={p.name} style={{
            background: p.us ? C_INK : '#fff', color: p.us ? '#fff' : C_INK,
            border: p.us ? 'none' : `1px solid ${C_RULE}`, borderRadius: 14,
            padding: '20px 22px', boxShadow: p.us ? '0 8px 28px rgba(10,31,61,0.12)' : '0 1px 2px rgba(10,31,61,0.04)',
          }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 14 }}>
              <div style={{ fontFamily: FONT_SANS, fontSize: 17, fontWeight: 700 }}>{p.name}</div>
              <div style={{ fontFamily: FONT_DISP, fontSize: 26, letterSpacing: '-0.02em' }}>{p.score}</div>
            </div>
            {caps.map((cap, ri) => (
              <div key={ri} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '8px 0', borderTop: `1px solid ${p.us ? 'rgba(255,255,255,0.12)' : C_RULE}` }}>
                <span style={{ fontFamily: FONT_SANS, fontSize: 13.5, color: p.us ? 'rgba(255,255,255,0.8)' : C_INK }}>{cap}</span>
                <StatusIcon v={p.vals[ri]} />
              </div>
            ))}
          </div>
        ))}
        <div style={{ display: 'flex', gap: 22, fontFamily: FONT_MONO, fontSize: 9.5, letterSpacing: '0.1em', textTransform: 'uppercase', color: C_MUTED, flexWrap: 'wrap' }}>
          <span style={{ display: 'flex', alignItems: 'center', gap: 7 }}><span style={{ color: C_SUCCESS, fontWeight: 700 }}>✓</span> Full</span>
          <span style={{ display: 'flex', alignItems: 'center', gap: 7 }}><span style={{ color: C_ACCENT, fontWeight: 700 }}>½</span> Partial</span>
          <span style={{ display: 'flex', alignItems: 'center', gap: 7 }}><span style={{ color: C_MUTED }}>—</span> None</span>
        </div>
      </div>
    );
  }

  return (
    <div ref={ref} style={{ overflowX: 'auto' }}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr repeat(4, 116px)', minWidth: 640 }}>
        {/* header */}
        <div />
        {providers.map((p) => (
          <div key={p.name} style={{
            textAlign: 'center', padding: '14px 8px 16px', borderRadius: '12px 12px 0 0',
            background: p.us ? C_INK : 'transparent',
            color: p.us ? '#fff' : C_INK,
          }}>
            <div style={{ fontFamily: FONT_SANS, fontSize: 13.5, fontWeight: 700, lineHeight: 1.2 }}>{p.name}</div>
          </div>
        ))}
        {/* rows */}
        {caps.map((cap, ri) => (
          <React.Fragment key={cap}>
            <div style={{ display: 'flex', alignItems: 'center', padding: '11px 16px 11px 0', borderTop: `1px solid ${C_RULE}`, fontFamily: FONT_SANS, fontSize: 13.5, color: C_INK }}>{cap}</div>
            {providers.map((p) => (
              <div key={p.name + ri} style={{
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                borderTop: `1px solid ${p.us ? 'rgba(255,255,255,0.12)' : C_RULE}`,
                background: p.us ? C_INK : 'transparent',
              }}>
                <Dot v={p.vals[ri]} us={p.us} delay={0.1 + ri * 0.05 + (p.us ? 0.2 : 0)} />
              </div>
            ))}
          </React.Fragment>
        ))}
        {/* score */}
        <div style={{ display: 'flex', alignItems: 'center', padding: '16px 16px 16px 0', borderTop: `2px solid ${C_INK}`, fontFamily: FONT_MONO, fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: C_INK, fontWeight: 600 }}>Score</div>
        {providers.map((p) => (
          <div key={p.name + 'sc'} style={{
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            padding: '12px 0 18px',
            borderTop: `2px solid ${p.us ? '#fff' : C_INK}`,
            background: p.us ? C_INK : 'transparent',
            borderRadius: p.us ? '0 0 12px 12px' : 0,
          }}>
            <span style={{ fontFamily: FONT_DISP, fontSize: 30, color: p.us ? '#fff' : C_INK, letterSpacing: '-0.02em' }}>{p.score}</span>
          </div>
        ))}
      </div>
      <div style={{ display: 'flex', gap: 22, marginTop: 18, fontFamily: FONT_MONO, fontSize: 9.5, letterSpacing: '0.1em', textTransform: 'uppercase', color: C_MUTED, flexWrap: 'wrap' }}>
        <span style={{ display: 'flex', alignItems: 'center', gap: 7 }}><span style={{ width: 12, height: 12, borderRadius: '50%', background: C_INK }} /> Full</span>
        <span style={{ display: 'flex', alignItems: 'center', gap: 7 }}><span style={{ width: 12, height: 12, borderRadius: '50%', background: `linear-gradient(90deg, ${C_ACCENT} 50%, rgba(10,31,61,0.12) 50%)`, border: `1.5px solid ${C_ACCENT}` }} /> Partial</span>
        <span style={{ display: 'flex', alignItems: 'center', gap: 7 }}><span style={{ width: 11, height: 11, borderRadius: '50%', border: `1.5px solid rgba(10,31,61,0.2)` }} /> None</span>
      </div>
    </div>
  );
}

// ════════════════════════════════════════════════════════════════════════
// FIG — Five currencies, five central banks, direct (hub diagram)
// ════════════════════════════════════════════════════════════════════════
function CentralBanksDiagram() {
  const [ref, seen] = useReveal();
  const banks = [
    { cur: 'EUR', bank: 'ECB', rail: 'TARGET2 / TIPS' },
    { cur: 'GBP', bank: 'Bank of England', rail: 'FPS / CHAPS' },
    { cur: 'SEK', bank: 'Riksbanken', rail: 'RIX' },
    { cur: 'DKK', bank: 'Nationalbanken', rail: 'TARGET DKK' },
    { cur: 'NOK', bank: 'Norges Bank', rail: 'NBO' },
  ];
  return (
    <div ref={ref}>
      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 0 }}>
        <div style={{
          padding: '16px 28px', background: C_INK, color: '#fff', borderRadius: 12, textAlign: 'center',
          opacity: seen ? 1 : 0, transform: seen ? 'translateY(0)' : 'translateY(-8px)', transition: `all .5s ${EASE}`,
        }}>
          <div style={{ fontFamily: FONT_MONO, fontSize: 9.5, letterSpacing: '0.16em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.6)' }}>One licence</div>
          <div style={{ fontFamily: FONT_SANS, fontSize: 16, fontWeight: 700, marginTop: 3 }}>Lithuanian specialised bank</div>
        </div>
        <svg viewBox="0 0 500 44" style={{ width: '100%', maxWidth: 620, height: 44, marginTop: -1 }} preserveAspectRatio="none">
          {[50, 150, 250, 350, 450].map((x, i) => (
            <path key={i} d={`M250,2 C250,24 ${x},18 ${x},42`} fill="none" stroke={C_ACCENT}
              strokeWidth="1.5" strokeDasharray="200" strokeDashoffset={seen ? 0 : 200}
              style={{ transition: `stroke-dashoffset .8s ${EASE} ${0.2 + i * 0.08}s` }} />
          ))}
        </svg>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(120px, 100%), 1fr))', gap: 'clamp(8px, 1.5vw, 14px)', width: '100%', marginTop: -2 }}>
          {banks.map((b, i) => (
            <div key={b.cur} style={{
              background: '#fff', border: `1px solid ${C_RULE}`, borderTop: `3px solid ${C_ACCENT}`,
              borderRadius: 10, padding: '14px 10px', textAlign: 'center',
              opacity: seen ? 1 : 0, transform: seen ? 'translateY(0)' : 'translateY(10px)',
              transition: `all .5s ${EASE} ${0.5 + i * 0.08}s`,
            }}>
              <div style={{ fontFamily: FONT_DISP, fontSize: 26, color: C_INK, letterSpacing: '-0.02em' }}>{b.cur}</div>
              <div style={{ fontFamily: FONT_SANS, fontSize: 12.5, fontWeight: 600, color: C_INK, marginTop: 4, lineHeight: 1.2 }}>{b.bank}</div>
              <div style={{ fontFamily: FONT_MONO, fontSize: 8.5, letterSpacing: '0.08em', color: C_MUTED, marginTop: 6, textTransform: 'uppercase' }}>{b.rail}</div>
            </div>
          ))}
        </div>
      </div>
      <div style={{ textAlign: 'center', fontFamily: FONT_MONO, fontSize: 9.5, letterSpacing: '0.14em', color: C_MUTED, textTransform: 'uppercase', marginTop: 20 }}>
        No correspondent bank required for any major European currency
      </div>
    </div>
  );
}

// ════════════════════════════════════════════════════════════════════════
// FIG — Settlement rails table (currency lanes)
// ════════════════════════════════════════════════════════════════════════
function CurrencyRails() {
  const [ref, seen] = useReveal(0.15);
  const mobile = useIsMobile(640);
  const rows = [
    { cur: 'EUR', rail: 'TARGET2 / TIPS', cost: '€0.002', speed: '<10 sec', entity: 'Lithuanian specialised bank — direct ECB' },
    { cur: 'GBP', rail: 'FPS / CHAPS', cost: '£0.487', speed: '<2 sec', entity: 'PRA branch — Year 2 (CHAPS direct)' },
    { cur: 'SEK', rail: 'RIX-INST', cost: '~SEK 0.02', speed: '<10 sec', entity: 'Direct — Riksbanken (Apr 2025, TIPS-based)' },
    { cur: 'DKK', rail: 'TARGET DKK', cost: '~DKK 0.015', speed: '<10 sec', entity: 'Direct — ECB TIPS infrastructure' },
    { cur: 'NOK', rail: 'NBO', cost: 'Fixed fee', speed: 'Same-day', entity: 'Direct — Norges Bank (NBO INST H1 2028)' },
  ];

  if (mobile) {
    return (
      <div ref={ref} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        {rows.map((r, i) => (
          <div key={r.cur} style={{
            background: '#fff', border: `1px solid ${C_RULE}`, borderTop: `3px solid ${C_ACCENT}`,
            borderRadius: 12, padding: '18px 20px',
            opacity: seen ? 1 : 0, transform: seen ? 'translateY(0)' : 'translateY(10px)',
            transition: `all .5s ${EASE} ${i * 0.08}s`,
          }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
              <div style={{ fontFamily: FONT_DISP, fontSize: 28, color: C_INK, letterSpacing: '-0.02em' }}>{r.cur}</div>
              <span style={{ fontFamily: FONT_MONO, fontSize: 11, color: C_INK, background: C_SURF2, border: `1px solid ${C_RULE}`, padding: '3px 9px', borderRadius: 5, letterSpacing: '0.04em' }}>{r.speed}</span>
            </div>
            <div style={{ fontFamily: FONT_SANS, fontSize: 15, color: C_INK, fontWeight: 600, marginTop: 8 }}>{r.rail}</div>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginTop: 10 }}>
              <div style={{ fontFamily: FONT_MONO, fontSize: 9, letterSpacing: '0.12em', textTransform: 'uppercase', color: C_MUTED }}>Cost / txn</div>
              <div style={{ fontFamily: FONT_MONO, fontSize: 15, color: C_SUCCESS, fontWeight: 600 }}>{r.cost}</div>
            </div>
            <div style={{ fontFamily: FONT_SANS, fontSize: 13, color: C_MUTED, marginTop: 8, lineHeight: 1.4 }}>{r.entity}</div>
          </div>
        ))}
      </div>
    );
  }

  return (
    <div ref={ref} style={{ display: 'flex', flexDirection: 'column', gap: 0 }}>
      <div style={{ display: 'grid', gridTemplateColumns: '64px 1.1fr 0.9fr 0.9fr 1.8fr', gap: 16, padding: '0 18px 12px', fontFamily: FONT_MONO, fontSize: 9.5, letterSpacing: '0.14em', textTransform: 'uppercase', color: C_MUTED, borderBottom: `1px solid ${C_RULE}` }}>
        <div>Cur.</div><div>Rail</div><div>Cost / txn</div><div>Speed</div><div>Settlement entity</div>
      </div>
      {rows.map((r, i) => (
        <div key={r.cur} style={{
          display: 'grid', gridTemplateColumns: '64px 1.1fr 0.9fr 0.9fr 1.8fr', gap: 16, padding: '15px 18px',
          alignItems: 'center', borderBottom: `1px solid ${C_RULE}`,
          opacity: seen ? 1 : 0, transform: seen ? 'translateX(0)' : 'translateX(-10px)',
          transition: `all .5s ${EASE} ${i * 0.08}s`,
        }}>
          <div style={{ fontFamily: FONT_DISP, fontSize: 22, color: C_INK, letterSpacing: '-0.02em' }}>{r.cur}</div>
          <div style={{ fontFamily: FONT_SANS, fontSize: 14, color: C_INK, fontWeight: 600 }}>{r.rail}</div>
          <div style={{ fontFamily: FONT_MONO, fontSize: 13, color: C_SUCCESS, fontWeight: 600 }}>{r.cost}</div>
          <div><span style={{ fontFamily: FONT_MONO, fontSize: 11, color: C_INK, background: C_SURF2, border: `1px solid ${C_RULE}`, padding: '3px 9px', borderRadius: 5, letterSpacing: '0.04em' }}>{r.speed}</span></div>
          <div style={{ fontFamily: FONT_SANS, fontSize: 13.5, color: C_MUTED }}>{r.entity}</div>
        </div>
      ))}
    </div>
  );
}

// ════════════════════════════════════════════════════════════════════════
// FIG — Partner onboarding timeline (Day 1 → 7)
// ════════════════════════════════════════════════════════════════════════
function OnboardingTimeline() {
  const [ref, seen] = useReveal();
  const steps = [
    { day: '1–3', t: 'Onboarding & due diligence', d: 'EDD, AML/CTF policy & procedures, external audit document. KYC/KYB. Sanctions screening. Risk assessment.' },
    { day: '3–4', t: 'Account setup', d: 'Segregated safeguarding account. API credentials. Sandbox access.' },
    { day: '4–5', t: 'Integration', d: 'Iframe drop-in or API integration. Test transactions in sandbox.' },
    { day: '5–7', t: 'Go-live', d: 'Production switch. First live transaction. Settlement cycle begins.' },
  ];
  return (
    <div ref={ref}>
      <div style={{ position: 'relative', display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(180px, 100%), 1fr))', gap: 'clamp(16px, 3vw, 16px)' }}>
        {steps.map((s, i) => (
          <div key={i} style={{ position: 'relative', textAlign: 'center' }}>
            <div style={{
              width: 28, height: 28, borderRadius: '50%', background: i === steps.length - 1 ? C_SUCCESS : C_INK, color: '#fff',
              display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto',
              fontFamily: FONT_MONO, fontSize: 10, fontWeight: 600,
              opacity: seen ? 1 : 0, transform: seen ? 'scale(1)' : 'scale(0.4)', transition: `all .45s ${EASE} ${0.2 + i * 0.18}s`,
              boxShadow: '0 0 0 4px #fff',
            }}>{i + 1}</div>
            <div style={{ fontFamily: FONT_MONO, fontSize: 9.5, letterSpacing: '0.12em', color: C_ACCENT, textTransform: 'uppercase', marginTop: 12, fontWeight: 600 }}>Day {s.day}</div>
            <div style={{ fontFamily: FONT_SANS, fontSize: 14.5, fontWeight: 600, color: C_INK, marginTop: 4 }}>{s.t}</div>
            <div style={{ fontFamily: FONT_SANS, fontSize: 12.5, color: C_MUTED, marginTop: 6, lineHeight: 1.45 }}>{s.d}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ════════════════════════════════════════════════════════════════════════
// FIG — Platform architecture (layered stack)
// ════════════════════════════════════════════════════════════════════════
function ArchitectureStack() {
  const [ref, seen] = useReveal(0.12);
  const layers = [
    { name: 'Regulatory', items: [
      ['EU', 'Lithuanian specialised bank', 'EEA passporting · SEPA direct · MC/Visa principal'],
      ['UK', 'PRA branch', 'BoE settlement · FPS/CHAPS · Year 2'],
      ['Nordics', 'Direct clearing', 'Riksbanken · Nationalbanken · Norges Bank'],
    ] },
    { name: 'Infrastructure', items: [
      ['Core banking', 'Mambu', 'Cloud SaaS · ledger · FX engine'],
      ['Payments', 'SWIFT + TIPS', 'Own BIC · HSM + PKI · direct participant'],
      ['Cards', 'MC/Visa principal', 'Own BIN · issuing + acquiring'],
      ['Risk', 'Onfido / Sumsub', 'KYC/AML · Chainalysis · Dow Jones screening'],
    ] },
    { name: 'Partner', items: [
      ['API', 'REST / GraphQL', 'OpenAPI 3.0 · OAuth 2.0 · webhooks'],
      ['Gateway', 'Hosted iframe + SDK', 'PCI-compliant · 48-hour go-live'],
      ['Portal', 'Dashboard', 'Transactions · settlements · reconciliation'],
    ] },
  ];
  return (
    <div ref={ref} style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      {layers.map((layer, li) => (
        <div key={layer.name} style={{
          display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(140px, 100%), 1fr))', gap: 'clamp(12px, 2vw, 20px)', alignItems: 'stretch',
          opacity: seen ? 1 : 0, transform: seen ? 'translateY(0)' : 'translateY(12px)', transition: `all .55s ${EASE} ${li * 0.12}s`,
        }}>
          <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', padding: '16px 18px', background: C_INK, borderRadius: 10, color: '#fff' }}>
            <div style={{ fontFamily: FONT_MONO, fontSize: 9, letterSpacing: '0.18em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.55)' }}>Layer {li + 1}</div>
            <div style={{ fontFamily: FONT_DISP, fontSize: 22, marginTop: 4, letterSpacing: '-0.01em' }}>{layer.name}</div>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(160px, 100%), 1fr))', gap: 10 }}>
            {layer.items.map((it, ii) => (
              <div key={ii} style={{ background: C_SURF2, border: `1px solid ${C_RULE}`, borderRadius: 9, padding: '12px 13px' }}>
                <div style={{ fontFamily: FONT_MONO, fontSize: 9, letterSpacing: '0.12em', textTransform: 'uppercase', color: C_ACCENT, fontWeight: 600 }}>{it[0]}</div>
                <div style={{ fontFamily: FONT_SANS, fontSize: 14, fontWeight: 700, color: C_INK, marginTop: 4 }}>{it[1]}</div>
                <div style={{ fontFamily: FONT_SANS, fontSize: 11.5, color: C_MUTED, marginTop: 5, lineHeight: 1.4 }}>{it[2]}</div>
              </div>
            ))}
          </div>
        </div>
      ))}
    </div>
  );
}

Object.assign(window, {
  IntermediaryFlow, MarginCompare, CompetitiveMatrix, CentralBanksDiagram,
  CurrencyRails, OnboardingTimeline, ArchitectureStack,
});
