// ─────────────────────────────────────────────────────────────────
// SIKKA ROYALE — Onboarding: splash, phone, OTP, name, pick, linking
// ─────────────────────────────────────────────────────────────────

const ROYAL_CATALOGUE = [
  // Popular — what most people in the GCC carry
  { id: 'adcb',         bank: 'adcb',    name: 'ADCB TouchPoints',         ar: 'بنك أبوظبي التجاري',     perk: 'Everyday · 4 TouchPoints / AED', last4: '6242', initials: 'AD',  popular: true },
  { id: 'fab',          bank: 'fab',     name: 'FAB Cashback',             ar: 'بنك الإمارات الأول',     perk: 'Cashback · 1% on all',           last4: '2891', initials: 'FAB', popular: true },
  { id: 'enbd-sky',     bank: 'enbd',    name: 'ENBD Skywards Infinite',   ar: 'بنك الإمارات دبي الوطني', perk: 'Travel · 2× miles',                              initials: 'EN',  popular: true },
  { id: 'mashreq',      bank: 'mashreq', name: 'Mashreq Smiles World',     ar: 'بنك المشرق',             perk: 'Dining · 5× Smiles',                              initials: 'MA',  popular: true },

  // ADCB
  { id: 'adcb-365',     bank: 'adcb',    name: 'ADCB 365 Cashback',        ar: 'بنك أبوظبي التجاري',     perk: 'Cashback · 1.5% everyday',                        initials: 'AD' },
  { id: 'adcb-lulu',    bank: 'adcb',    name: 'ADCB Lulu Platinum',       ar: 'بنك أبوظبي التجاري',     perk: 'Groceries · 5× points at Lulu',                   initials: 'AD' },
  { id: 'adcb-etihad',  bank: 'adcb',    name: 'ADCB Etihad Guest Above',  ar: 'بنك أبوظبي التجاري',     perk: 'Travel · 2.5× Etihad miles',                      initials: 'AD' },

  // FAB
  { id: 'fab-rewards',  bank: 'fab',     name: 'FAB Rewards Signature',    ar: 'بنك الإمارات الأول',     perk: 'Rewards · 3× on dining & travel',                 initials: 'FAB' },
  { id: 'fab-etihad',   bank: 'fab',     name: 'FAB Etihad Guest Elite',   ar: 'بنك الإمارات الأول',     perk: 'Travel · 2.25× Etihad miles',                     initials: 'FAB' },
  { id: 'fab-istarter', bank: 'fab',     name: 'FAB iStartHere',           ar: 'بنك الإمارات الأول',     perk: 'Starter · no annual fee',                         initials: 'FAB' },

  // ENBD
  { id: 'enbd-emaar',   bank: 'enbd',    name: 'ENBD U By Emaar',          ar: 'بنك الإمارات دبي الوطني', perk: 'Lifestyle · 10% U-points at Emaar',              initials: 'EN' },
  { id: 'enbd-dnata',   bank: 'enbd',    name: 'ENBD dnata World',         ar: 'بنك الإمارات دبي الوطني', perk: 'Travel · 5% off dnata bookings',                  initials: 'EN' },
  { id: 'enbd-go',      bank: 'enbd',    name: 'ENBD Go4it Platinum',      ar: 'بنك الإمارات دبي الوطني', perk: 'Lifestyle · BOGO dining',                         initials: 'EN' },

  // Others
  { id: 'wio',          bank: 'wio',     name: 'Wio One',                  ar: 'ويو',                    perk: 'Digital · 1% cashback',                            initials: 'WI' },
  { id: 'rak',          bank: 'rak',     name: 'RAK World Currency',       ar: 'بنك رأس الخيمة',         perk: 'Multi-currency · 0% FX',                           initials: 'RA' },
  { id: 'rak-titanium', bank: 'rak',     name: 'RAK Titanium',             ar: 'بنك رأس الخيمة',         perk: 'Cashback · 2% on supermarkets',                    initials: 'RA' },
  { id: 'adib',         bank: 'adib',    name: 'ADIB Cashback Visa',       ar: 'مصرف أبوظبي الإسلامي',   perk: 'Sharia · Groceries 3%',                            initials: 'AB' },
  { id: 'adib-etihad',  bank: 'adib',    name: 'ADIB Etihad Gold',         ar: 'مصرف أبوظبي الإسلامي',   perk: 'Travel · 1.5× Etihad miles',                       initials: 'AB' },
  { id: 'cbd',          bank: 'cbd',     name: 'CBD Visa Signature',       ar: 'بنك دبي التجاري',        perk: 'Travel · Lounge access',                           initials: 'CB' },
  { id: 'cbd-super',    bank: 'cbd',     name: 'CBD Super Saver',          ar: 'بنك دبي التجاري',        perk: 'Cashback · 10% on utilities',                      initials: 'CB' },
  { id: 'hsbc-prem',    bank: 'hsbc',    name: 'HSBC Premier World',       ar: 'بنك إتش إس بي سي',       perk: 'Travel · global lounges',                          initials: 'HS' },
  { id: 'sc-priority',  bank: 'sc',      name: 'SC Priority Visa Infinite', ar: 'ستاندرد تشارترد',       perk: 'Travel · 4 free lounges / mo',                     initials: 'SC' },
  { id: 'citi-prest',   bank: 'citi',    name: 'Citi Prestige',            ar: 'سيتي',                  perk: 'Premium · concierge + 4th-night-free',             initials: 'CI' },
];

// ─── Splash ───────────────────────────────────────────────────────
function Splash({ onStart, onSignIn, name = '', hasSaved = false }) {
  return (
    <div className="r-screen" style={{
      minHeight: '100dvh',
      background: `
        radial-gradient(ellipse 80% 60% at 50% 30%, rgba(74,155,122,0.14), transparent 65%),
        radial-gradient(ellipse 70% 45% at 50% 100%, rgba(74,155,122,0.10), transparent 65%),
        ${R.ink}
      `,
      color: R.pearl,
      display: 'flex', flexDirection: 'column',
      position: 'relative', overflow: 'hidden',
    }}>
      <MashrabiyaBG opacity={0.07} />

      {/* Establishment tag — anchored to the top safe area so the content
          below has room to breathe and the layout fills the viewport. */}
      <div style={{
        padding: '20px 22px 0', textAlign: 'center',
        position: 'relative', zIndex: 1,
      }}>
        <Eyebrow color={R.pearl4} size={9.5} ls={3.6} style={{
          animation: 'r-fade 800ms 80ms both',
        }}>
          ESTABLISHED · 2026
        </Eyebrow>
      </div>

      {/* center stack — logo + wordmark + tagline (fills remaining height) */}
      <div style={{
        flex: 1, display: 'flex', flexDirection: 'column',
        alignItems: 'center', justifyContent: 'center',
        padding: '12px 32px 0', position: 'relative', textAlign: 'center', zIndex: 1,
      }}>
        {/* Animated brand coin — orbiting particles, expanding rings, halo pulse */}
        <div style={{ position: 'relative', width: 220, height: 220,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          animation: 'r-rise 800ms 120ms cubic-bezier(.2,.7,.2,1) both' }}>
          {/* Soft glow halo (existing, slightly stronger) */}
          <div style={{
            position: 'absolute', inset: 0, borderRadius: '50%',
            background: 'radial-gradient(circle, rgba(74,155,122,0.42), transparent 65%)',
            filter: 'blur(22px)', animation: 'r-halo 4s ease-in-out infinite',
            pointerEvents: 'none',
          }} />

          {/* Expanding ripple rings — three staggered */}
          {[0, 1, 2].map(i => (
            <span key={`ripple-${i}`} style={{
              position: 'absolute', width: 140, height: 140, borderRadius: '50%',
              border: `1px solid ${R.gold}55`,
              animation: `r-splash-ripple 3.6s ${i * 1.2}s ease-out infinite`,
              pointerEvents: 'none',
            }} />
          ))}

          {/* Slow orbit ring — gradient stroked circle */}
          <svg width="200" height="200" viewBox="0 0 200 200" style={{
            position: 'absolute', inset: 10,
            animation: 'r-orbit-spin 22s linear infinite',
            pointerEvents: 'none',
          }}>
            <defs>
              <linearGradient id="orbitGrad" x1="0" y1="0" x2="1" y2="1">
                <stop offset="0%" stopColor={R.gold} stopOpacity="0" />
                <stop offset="40%" stopColor={R.gold} stopOpacity="0.6" />
                <stop offset="60%" stopColor={R.goldH} stopOpacity="0.9" />
                <stop offset="100%" stopColor={R.gold} stopOpacity="0" />
              </linearGradient>
            </defs>
            <circle cx="100" cy="100" r="92" fill="none"
              stroke="url(#orbitGrad)" strokeWidth="0.8"
              strokeDasharray="4 6" />
          </svg>

          {/* Counter-spinning inner ring */}
          <svg width="170" height="170" viewBox="0 0 170 170" style={{
            position: 'absolute',
            animation: 'r-orbit-spin-rev 32s linear infinite',
            pointerEvents: 'none',
          }}>
            <circle cx="85" cy="85" r="80" fill="none"
              stroke={R.gold} strokeOpacity="0.18" strokeWidth="0.5"
              strokeDasharray="1 8" />
          </svg>

          {/* Orbiting particles — small dots traveling around the coin */}
          {[0, 1, 2, 3].map(i => (
            <span key={`orbit-${i}`} style={{
              position: 'absolute', width: 200, height: 200,
              animation: `r-particle-orbit 9s ${i * -2.25}s linear infinite`,
              pointerEvents: 'none',
            }}>
              <span style={{
                position: 'absolute', left: '50%', top: 0,
                width: i === 0 ? 5 : 3, height: i === 0 ? 5 : 3,
                borderRadius: '50%',
                background: R.gold,
                boxShadow: `0 0 8px ${R.gold}, 0 0 14px ${R.gold}66`,
                transform: 'translateX(-50%)',
                opacity: 0.85,
              }} />
            </span>
          ))}

          {/* The coin itself — gentle breathing + slow rotation layered */}
          <div style={{
            position: 'relative',
            animation: 'r-coin-breath 3.4s ease-in-out infinite',
          }}>
            <div style={{
              animation: 'r-coin-spin 14s 0.8s cubic-bezier(.4,.0,.4,1) infinite',
            }}>
              <CoinMark size={132} />
            </div>
          </div>

          {/* Scoped keyframes for splash logo */}
          <style>{`
            @keyframes r-splash-ripple {
              0%   { transform: scale(0.6); opacity: 0; border-width: 1.5px }
              15%  { opacity: 0.9 }
              100% { transform: scale(1.55); opacity: 0; border-width: 0.4px }
            }
            @keyframes r-orbit-spin     { to { transform: rotate(360deg) } }
            @keyframes r-orbit-spin-rev { to { transform: rotate(-360deg) } }
            @keyframes r-particle-orbit { to { transform: rotate(360deg) } }
            @keyframes r-coin-breath {
              0%,100% { transform: scale(1) }
              50%     { transform: scale(1.035) }
            }
          `}</style>
        </div>

        {/* Wordmark — lowercase serif "sikka" matching brand */}
        <div style={{ marginTop: 32, animation: 'r-rise 800ms 240ms both' }}>
          <span style={{
            fontFamily: FR.serif, fontSize: 78, color: R.pearl,
            letterSpacing: -1.6, fontWeight: 500, lineHeight: 0.9,
          }}>sikka</span>
        </div>

        <div style={{ marginTop: 16, animation: 'r-fade 800ms 380ms both' }}>
          <span style={{
            fontFamily: FR.arab, fontSize: 30, color: R.pearl3,
            letterSpacing: 0.5, lineHeight: 1, fontWeight: 400, opacity: 0.7,
          }}>سِكَّة</span>
        </div>

        {/* Tagline */}
        <div style={{
          marginTop: 28, fontFamily: FR.serif, fontSize: 21,
          color: R.pearl2, fontStyle: 'italic', letterSpacing: -0.2,
          lineHeight: 1.35, animation: 'r-rise 800ms 460ms both',
          textWrap: 'pretty', maxWidth: 320,
        }}>
          One wallet. <span style={{ color: R.gold }}>Every reward.</span>
          <br />
          An advantage few will see.
        </div>
      </div>

      {/* Bottom CTAs — pinned to the very bottom */}
      <div style={{
        padding: '0 22px max(env(safe-area-inset-bottom), 22px)',
        position: 'relative', zIndex: 1,
        animation: 'r-rise 700ms 720ms cubic-bezier(.2,.7,.2,1) both',
      }}>
        {hasSaved && name && (
          <div style={{ textAlign: 'center', marginBottom: 14 }}>
            <button onClick={onSignIn} style={{
              background: 'none', border: 'none', cursor: 'pointer',
              fontFamily: FR.serif, fontSize: 14, color: R.pearl4, letterSpacing: 0,
              fontStyle: 'italic',
            }}>
              Welcome back, <span style={{ color: R.gold }}>{name}</span>{' '}
              <span style={{ color: R.gold }}>→</span>
            </button>
          </div>
        )}
        <GoldButton onClick={onStart}>{hasSaved ? 'Continue' : 'Begin'}</GoldButton>
      </div>
    </div>
  );
}

// ─── Phone ────────────────────────────────────────────────────────
function PhoneStep({ onContinue, onBack, onSkip }) {
  const [num, setNum] = React.useState('501234567');
  const valid = num.length >= 7;
  return (
    <div className="r-screen" style={{
      minHeight: '100dvh', background: R.ink, color: R.pearl,
      display: 'flex', flexDirection: 'column', position: 'relative',
    }}>
      <MashrabiyaBG opacity={0.04} />
      <TopBar onBack={onBack}
        center={<StepCounter i={1} total={4} />}
        right={<button onClick={onSkip} style={{
          background: 'none', border: 'none', cursor: 'pointer',
          fontFamily: FR.serif, fontSize: 14, color: R.pearl3, fontStyle: 'italic',
        }}>Skip</button>} />

      <div style={{ padding: '22px 22px 0', animation: 'r-rise 600ms both', position: 'relative' }}>
        <Headline lead="Begin with your" tail="number" tailPunct="." size={44} />
        <Bilingual
          en="A six-digit code keeps the gates only yours."
          ar="رمز من ستة أرقام يحفظ الأبواب لك وحدك."
          size={15} style={{ marginTop: 16 }} />
      </div>

      <div style={{ padding: '32px 22px 0', animation: 'r-rise-soft 600ms 120ms both' }}>
        <Eyebrow style={{ marginBottom: 10 }}>MOBILE  ·  هاتف</Eyebrow>
        <div style={{ display: 'flex', gap: 10, position: 'relative' }}>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 8,
            padding: '0 14px', minWidth: 110, height: 60,
            background: R.ink2, border: `0.5px solid ${R.hair2}`, borderRadius: 14,
            fontFamily: FR.mono, fontSize: 15, color: R.pearl,
          }}>
            <span style={{ fontSize: 18 }}>🇦🇪</span>
            <span>+971</span>
          </div>
          <div style={{ flex: 1, position: 'relative' }}>
            <input
              type="tel"
              inputMode="numeric"
              value={num}
              onChange={(e) => setNum(e.target.value.replace(/\D/g, '').slice(0, 9))}
              placeholder="501234567"
              style={{
                width: '100%', height: 60, padding: '0 16px',
                background: R.ink2, border: `0.5px solid ${R.hair2}`, borderRadius: 14,
                fontFamily: FR.mono, fontSize: 17, color: R.pearl, letterSpacing: 1.4,
                outline: 'none',
              }}
            />
          </div>
        </div>
      </div>

      <div style={{ flex: 1, minHeight: 30 }} />

      {/* Bottom footer — CTA + trust marks */}
      <div style={{
        padding: '0 22px max(env(safe-area-inset-bottom), 24px)',
        display: 'flex', flexDirection: 'column', gap: 16,
      }}>
        <div style={{ animation: 'r-rise-soft 600ms 220ms both' }}>
          <GoldButton onClick={() => onContinue('+971 ' + num)} disabled={!valid}>
            Continue
          </GoldButton>
        </div>
        <div style={{ textAlign: 'center', animation: 'r-fade 800ms 500ms both' }}>
          <Eyebrow color={R.pearl4} size={9.5} ls={2.4}>
            ENCRYPTED · NEVER SOLD · ALWAYS YOURS
          </Eyebrow>
        </div>
      </div>
    </div>
  );
}

// ─── OTP ──────────────────────────────────────────────────────────
function OtpStep({ phone = '+971 50 123 4567', onVerify, onBack }) {
  const [code, setCode] = React.useState('');
  const [shake, setShake] = React.useState(false);
  const [countdown, setCountdown] = React.useState(0);
  const slots = 6;

  React.useEffect(() => {
    if (code.length === slots) {
      const t = setTimeout(() => onVerify(code), 350);
      return () => clearTimeout(t);
    }
  }, [code]);

  React.useEffect(() => {
    if (!countdown) return;
    const t = setTimeout(() => setCountdown(c => c - 1), 1000);
    return () => clearTimeout(t);
  }, [countdown]);

  return (
    <div className="r-screen" style={{
      minHeight: '100dvh', background: R.ink, color: R.pearl,
      display: 'flex', flexDirection: 'column', position: 'relative',
    }}>
      <MashrabiyaBG opacity={0.04} />
      <TopBar onBack={onBack} center={<StepCounter i={2} total={4} />} />

      <div style={{ padding: '22px 22px 0', animation: 'r-rise 600ms both' }}>
        <Headline lead="Enter the" tail="six" tailPunct="." size={44} />
        <Bilingual
          en={<>Sent to <span style={{ color: R.pearl, fontFamily: FR.mono, fontSize: 13 }}>{phone}</span></>}
          ar="أُرسِلَ إلى رقمك الكريم."
          size={15} style={{ marginTop: 16 }} />
      </div>

      <div style={{
        position: 'relative', padding: '36px 22px 0',
        animation: 'r-rise-soft 600ms 120ms both',
      }}>
        <div style={{
          display: 'grid', gridTemplateColumns: 'repeat(6, minmax(0, 1fr))', gap: 6,
          animation: shake ? 'r-shake 280ms' : 'none',
          maxWidth: '100%', boxSizing: 'border-box',
        }}>
          {Array.from({ length: slots }).map((_, i) => {
            const ch = code[i];
            const active = code.length === i;
            return (
              <div key={i} style={{
                position: 'relative',
                aspectRatio: '0.78', borderRadius: 12,
                background: ch ? R.ink3 : R.ink2,
                border: `0.5px solid ${active ? R.gold : ch ? R.hair3 : R.hair}`,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontFamily: FR.serif, fontSize: 30, color: R.pearl,
                fontWeight: 500,
                transition: 'all 200ms',
                boxShadow: active
                  ? `0 0 0 3px rgba(74,155,122,0.16), inset 0 0 0 0.5px ${R.gold}55`
                  : 'none',
              }}>
                {ch || (active ? <span style={{
                  width: 2, height: 28, background: R.gold,
                  animation: 'r-caret 1s steps(2, end) infinite',
                  boxShadow: `0 0 6px ${R.gold}`,
                }} /> : '')}
                {/* tiny corner pip when filled */}
                {ch && (
                  <span style={{
                    position: 'absolute', top: 4, right: 4, width: 3, height: 3,
                    borderRadius: '50%', background: R.gold, opacity: 0.7,
                  }} />
                )}
              </div>
            );
          })}
        </div>
        <HiddenNumInput value={code} onChange={setCode} max={slots} autoFocus />
      </div>

      <div style={{
        marginTop: 24, textAlign: 'center', fontFamily: FR.serif,
        fontSize: 14, color: R.pearl3, animation: 'r-fade 600ms 320ms both',
      }}>
        Didn't receive it?{' '}
        {countdown > 0
          ? <span style={{ color: R.pearl4 }}>Resend in {countdown}s</span>
          : <button onClick={() => { setCode(''); setCountdown(30); }} style={{
              background: 'none', border: 'none', cursor: 'pointer',
              color: R.gold, fontFamily: FR.serif, fontSize: 14, fontStyle: 'italic',
              textDecoration: 'underline', textUnderlineOffset: 4,
            }}>Resend</button>}
      </div>

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

      <div style={{
        padding: '0 22px max(env(safe-area-inset-bottom), 24px)',
        animation: 'r-rise-soft 600ms 400ms both',
      }}>
        <GoldButton onClick={() => {
          if (code.length === slots) onVerify(code);
          else { setShake(true); setTimeout(() => setShake(false), 300); }
        }} disabled={code.length < slots}>
          Verify
        </GoldButton>
      </div>
    </div>
  );
}

// ─── Name ─────────────────────────────────────────────────────────
function NameStep({ onContinue, onBack, initial = 'Praneet Sinha' }) {
  const [name, setName] = React.useState(initial);
  return (
    <div className="r-screen" style={{
      minHeight: '100dvh', background: R.ink, color: R.pearl,
      display: 'flex', flexDirection: 'column', position: 'relative',
    }}>
      <MashrabiyaBG opacity={0.04} />
      <TopBar onBack={onBack} center={<StepCounter i={3} total={4} />} />

      <div style={{ padding: '22px 22px 0', animation: 'r-rise 600ms both' }}>
        <Headline lead="And shall we call you" tail="…" size={42} />
        <Bilingual
          en="Engraved on your coin and every receipt."
          ar="يُنقَش على عُملتك وعلى كل إيصال."
          size={15} style={{ marginTop: 16 }} />
      </div>

      <div style={{ padding: '34px 22px 0', animation: 'r-rise-soft 600ms 120ms both' }}>
        <Eyebrow style={{ marginBottom: 10 }}>FULL NAME · الاسم الكامل</Eyebrow>
        <input
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="Your name"
          autoFocus
          style={{
            width: '100%', height: 64, padding: '0 16px',
            background: R.ink2, border: `0.5px solid ${R.hair2}`,
            borderRadius: 14, fontFamily: FR.serif, fontSize: 22,
            color: R.pearl, outline: 'none', letterSpacing: -0.3,
            fontStyle: 'italic',
          }}
        />
      </div>

      <div style={{ flex: 1, minHeight: 30 }} />

      <div style={{
        padding: '0 22px max(env(safe-area-inset-bottom), 24px)',
        animation: 'r-rise-soft 600ms 220ms both',
      }}>
        <GoldButton onClick={() => onContinue(name)} disabled={!name.trim()}>
          Continue
        </GoldButton>
      </div>
    </div>
  );
}

// ─── Section header — roman numeral + title + sublabel ───────────
function SectionHeader({ index, title, sub, delay = 0 }) {
  return (
    <div style={{
      padding: '24px 22px 10px',
      display: 'flex', alignItems: 'baseline', gap: 12,
      animation: `r-rise-soft 600ms ${delay}ms both`,
    }}>
      <span style={{
        fontFamily: FR.mono, fontSize: 10, color: R.gold,
        letterSpacing: 2.6, fontWeight: 600, minWidth: 22,
      }}>{index}</span>
      <div style={{
        flex: 1, height: 0,
        borderTop: `0.5px solid ${R.hair3}`,
        opacity: 0.7, transform: 'translateY(-6px)',
      }} />
      <div style={{ textAlign: 'right' }}>
        <div style={{
          fontFamily: FR.serif, fontSize: 17, color: R.pearl,
          letterSpacing: -0.2, fontWeight: 500, fontStyle: 'italic',
          lineHeight: 1,
        }}>{title}</div>
        {sub && (
          <Eyebrow color={R.pearl4} size={9} ls={1.8}
            style={{ marginTop: 4 }}>{sub}</Eyebrow>
        )}
      </div>
    </div>
  );
}

// ─── Pick cards ───────────────────────────────────────────────────
// Vertical list with miniature card-face previews, animated check
// stamps, and a sticky footer showing a fanned stack of the picks.
function PickCards({ name = 'Praneet', linked = ['adcb', 'fab'], onLink, onDone, onBack }) {
  const [picked, setPicked] = React.useState(new Set(linked));
  const [query, setQuery] = React.useState('');
  const toggle = (id) => {
    setPicked(prev => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });
  };

  const popularCards = ROYAL_CATALOGUE.filter(c => c.popular);
  const bankCards = ROYAL_CATALOGUE.filter(c => !c.popular);
  const q = query.trim().toLowerCase();
  const filteredBank = q
    ? bankCards.filter(c =>
        c.name.toLowerCase().includes(q) ||
        c.bank.toLowerCase().includes(q) ||
        (c.perk || '').toLowerCase().includes(q))
    : bankCards;

  return (
    <div className="r-screen" style={{
      minHeight: '100dvh', background: R.ink, color: R.pearl,
      paddingBottom: 140, position: 'relative',
    }}>
      <MashrabiyaBG opacity={0.03} />
      <TopBar onBack={onBack} center={<StepCounter i={4} total={4} />} />

      <div style={{ padding: '14px 22px 0', animation: 'r-rise 600ms both' }}>
        <Eyebrow color={R.gold} size={10} ls={3.2}>WELCOME, {name.toUpperCase()}</Eyebrow>
        <Headline lead="Pick the cards you" tail="carry" tailPunct="." size={34}
          style={{ marginTop: 8 }} />
        <Sub style={{ marginTop: 12, fontSize: 14.5 }}>
          Sikka reads every reward catalogue in the GCC. The more cards you bring,
          the better routes we find.
        </Sub>
      </div>

      {/* ─── Section I — Scan a card ─────────────────────────── */}
      <SectionHeader index="I" title="Scan a card" sub="Tap-to-pay or camera read"
        delay={120} />
      <div style={{ padding: '0 22px', animation: 'r-rise-soft 600ms 140ms both' }}>
        <button onClick={onLink} style={{
          position: 'relative', width: '100%', textAlign: 'left',
          padding: '14px 18px', background: R.velvet,
          border: `0.5px solid ${R.hair3}`, borderRadius: 16, cursor: 'pointer',
          color: R.pearl, display: 'flex', alignItems: 'center', gap: 14, overflow: 'hidden',
        }}>
          <FiligreeCorners inset={6} length={14} opacity={0.55} />
          <div style={{
            position: 'relative', width: 48, height: 48, flexShrink: 0,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>
            {[0, 1].map(i => (
              <span key={i} style={{
                position: 'absolute', inset: 0, borderRadius: '50%',
                border: `1px solid ${R.gold}77`,
                animation: `r-ring 2.4s ${i * 0.8}s ease-out infinite`,
              }} />
            ))}
            <div style={{
              width: 42, height: 42, borderRadius: 12,
              background: R.goldDim, border: `0.5px solid ${R.gold}66`,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              color: R.gold,
            }}>
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none">
                <path d="M4 8V6a2 2 0 012-2h2M16 4h2a2 2 0 012 2v2M20 16v2a2 2 0 01-2 2h-2M8 20H6a2 2 0 01-2-2v-2"
                  stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
                <path d="M8 12h8" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" />
              </svg>
            </div>
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{
              fontFamily: FR.serif, fontSize: 18, color: R.pearl,
              letterSpacing: -0.3, fontWeight: 500, fontStyle: 'italic',
            }}>Hold a card to the back</div>
            <Eyebrow color={R.gold} size={9.5} ls={1.8} style={{ marginTop: 4 }}>
              READS ISSUER · LAST-4 · TOKEN
            </Eyebrow>
          </div>
          <span style={{ color: R.gold, fontSize: 18 }}>›</span>
        </button>
      </div>

      {/* ─── Section II — Popular cards ──────────────────────── */}
      <SectionHeader index="II" title="Popular cards"
        sub={`Currently listed · ${popularCards.length}`} delay={220} />
      <div style={{
        padding: '0 22px',
        display: 'flex', flexDirection: 'column', gap: 10,
      }}>
        {popularCards.map((c, i) => (
          <CardRow key={c.id} card={c} on={picked.has(c.id)} index={i}
            onToggle={() => toggle(c.id)} />
        ))}
      </div>

      {/* ─── Section III — Choose from your bank ────────────── */}
      <SectionHeader index="III" title="Choose from your bank"
        sub={`All issuers · ${bankCards.length} cards`} delay={320} />

      {/* Search bar */}
      <div style={{ padding: '0 22px 12px',
        animation: 'r-rise-soft 600ms 340ms both' }}>
        <div style={{
          position: 'relative',
          display: 'flex', alignItems: 'center', gap: 10,
          height: 46, padding: '0 14px',
          background: R.ink2, border: `0.5px solid ${R.hair2}`, borderRadius: 12,
        }}>
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" style={{ flexShrink: 0, color: R.pearl4 }}>
            <circle cx="11" cy="11" r="7" stroke="currentColor" strokeWidth="1.6" />
            <path d="M20 20l-3.5-3.5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" />
          </svg>
          <input
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder="Search ADCB, Etihad, cashback…"
            style={{
              flex: 1, height: '100%', background: 'transparent', border: 'none',
              outline: 'none', color: R.pearl, fontFamily: FR.serif,
              fontSize: 15, letterSpacing: -0.1, fontStyle: query ? 'normal' : 'italic',
            }}
          />
          {query && (
            <button onClick={() => setQuery('')} style={{
              background: 'none', border: 'none', cursor: 'pointer',
              color: R.pearl4, fontSize: 18, padding: 0, lineHeight: 1,
              fontFamily: FR.serif,
            }}>×</button>
          )}
          <span style={{
            fontFamily: FR.mono, fontSize: 9.5, color: R.pearl4,
            letterSpacing: 1.6, borderLeft: `0.5px solid ${R.hair2}`,
            paddingLeft: 10, flexShrink: 0,
          }}>{filteredBank.length}</span>
        </div>
      </div>

      {/* Filtered list */}
      <div style={{
        padding: '0 22px',
        display: 'flex', flexDirection: 'column', gap: 10,
      }}>
        {filteredBank.length > 0 ? filteredBank.map((c, i) => (
          <CardRow key={c.id} card={c} on={picked.has(c.id)} index={i}
            onToggle={() => toggle(c.id)} />
        )) : (
          <div style={{
            padding: '28px 18px', textAlign: 'center',
            border: `0.5px dashed ${R.hair2}`, borderRadius: 14,
            background: R.ink2,
          }}>
            <div style={{
              fontFamily: FR.serif, fontSize: 16, color: R.pearl2,
              fontStyle: 'italic',
            }}>No matches for "{query}"</div>
            <Eyebrow color={R.pearl4} size={9} ls={1.8} style={{ marginTop: 6 }}>
              REQUEST · TYPE A BANK NAME
            </Eyebrow>
          </div>
        )}
      </div>

      {/* Sticky footer — stack preview + CTA */}
      <div style={{
        position: 'sticky', bottom: 0, marginTop: 22,
        padding: '14px 22px max(env(safe-area-inset-bottom), 22px)',
        background: `linear-gradient(180deg, ${R.ink}00 0%, ${R.ink}e6 28%, ${R.ink} 60%)`,
        backdropFilter: 'blur(12px)',
        animation: 'r-rise-soft 600ms 320ms both',
      }}>
        {picked.size > 0 && (
          <div style={{
            display: 'flex', alignItems: 'center', gap: 14, marginBottom: 12,
            animation: 'r-rise-soft 320ms both',
          }}>
            <div style={{ position: 'relative', width: 78, height: 36, flexShrink: 0 }}>
              {[...picked].slice(0, 5).map((id, j) => {
                const b = R.bank[id] || { bg: R.ink3 };
                return (
                  <div key={id} style={{
                    position: 'absolute', left: j * 12, top: j * 1.5,
                    width: 38, height: 26, borderRadius: 5,
                    background: `linear-gradient(135deg, ${b.bg}, ${shade(b.bg, -18)})`,
                    border: `0.5px solid ${R.hair3}`,
                    boxShadow: `0 ${4 + j*2}px ${8 + j*2}px rgba(0,0,0,0.45)`,
                    zIndex: 5 - j,
                    animation: `r-rise-soft 320ms ${j * 60}ms both`,
                  }} />
                );
              })}
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <Eyebrow color={R.pearl4} size={9} ls={1.8}>YOUR SIKKA</Eyebrow>
              <div style={{
                fontFamily: FR.serif, fontSize: 15.5, color: R.pearl,
                fontStyle: 'italic', fontWeight: 500, marginTop: 2,
              }}>
                {picked.size} {picked.size === 1 ? 'card linked' : 'cards linked'}
              </div>
            </div>
          </div>
        )}

        <GoldButton onClick={() => onDone(Array.from(picked))} disabled={picked.size === 0}>
          {picked.size === 0
            ? 'Pick at least one'
            : `Mint my Sikka · ${picked.size}`}
        </GoldButton>
      </div>
    </div>
  );
}

// Row component — animated row with miniature card face on the left
function CardRow({ card, on, index, onToggle }) {
  const b = R.bank[card.bank] || { bg: R.ink3, tx: R.pearl };
  return (
    <button onClick={onToggle} style={{
      position: 'relative', width: '100%', textAlign: 'left',
      padding: '12px 14px',
      background: on ? R.velvet : R.ink2,
      border: `0.5px solid ${on ? R.gold + 'cc' : R.hair}`,
      borderRadius: 14, cursor: 'pointer', color: R.pearl,
      display: 'flex', alignItems: 'center', gap: 14,
      transition: 'all 240ms cubic-bezier(.2,.7,.2,1)',
      animation: `r-rise-soft 500ms ${260 + index * 50}ms both`,
      boxShadow: on
        ? `0 10px 24px rgba(74,155,122,0.20), inset 0 0 0 0.5px ${R.gold}66`
        : 'none',
      transform: on ? 'translateY(-1px)' : 'translateY(0)',
      overflow: 'hidden',
    }}>
      {/* Mini bank card face */}
      <div style={{
        width: 58, height: 38, borderRadius: 6, flexShrink: 0,
        background: `linear-gradient(135deg, ${b.bg} 0%, ${shade(b.bg, -18)} 100%)`,
        color: b.tx, position: 'relative',
        boxShadow: '0 4px 10px rgba(0,0,0,0.4), inset 0 0 0 0.5px rgba(255,255,255,0.1)',
        overflow: 'hidden',
      }}>
        <div style={{
          position: 'absolute', left: 5, top: 6, width: 10, height: 7, borderRadius: 1.5,
          background: 'linear-gradient(135deg, #fff5c0 0%, #f0d27a 25%, #c89a3a 55%, #8a5d1a 90%)',
          boxShadow: 'inset 0 0 0 0.3px rgba(60,35,5,0.5), 0 0.5px 1px rgba(0,0,0,0.3)',
        }} />
        <div style={{
          position: 'absolute', right: 5, bottom: 4,
          fontFamily: FR.mono, fontSize: 8, letterSpacing: 0.4,
          color: b.tx, fontWeight: 700,
        }}>{card.initials}</div>
      </div>

      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          fontFamily: FR.serif, fontSize: 15.5, color: R.pearl,
          letterSpacing: -0.2, fontWeight: 500, lineHeight: 1.2,
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
        }}>{card.name}</div>
        <Eyebrow size={9} ls={1.6} color={on ? R.gold : R.pearl3}
          style={{ marginTop: 3 }}>
          {on
            ? <>···· {card.last4 || '••••'} · LINKED</>
            : card.perk}
        </Eyebrow>
      </div>

      {/* Check stamp — animates in when selected */}
      <div style={{
        position: 'relative', width: 26, height: 26, flexShrink: 0,
        borderRadius: '50%',
        background: on ? R.gold : 'transparent',
        border: `1.5px solid ${on ? R.gold : R.hair3}`,
        transition: 'all 240ms',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        {on && (
          <svg width="14" height="14" viewBox="0 0 14 14" fill="none"
            style={{ animation: 'r-pop 320ms both' }}>
            <path d="M3 7l3 3 5-6" stroke={R.goldInk} strokeWidth="2"
              strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        )}
      </div>
    </button>
  );
}

// ─── Minting / Linking screen ─────────────────────────────────────
// Cinematic per-card mint. For each card:
//   - Card flies in
//   - A mint scan line sweeps top→bottom across it
//   - Extracted data (BIN, last-4, issuer, status) appears below
//   - A trace path animates from the card down to a small Sikka coin
//   - Card gets a check stamp, then slides off into a growing fanned stack
function LinkingScreen({ name = 'Praneet', cards = ['adcb', 'fab'], onDone }) {
  const SCAN_MS = 1900;
  const COOL_MS = 520;
  const [i, setI] = React.useState(0);
  const [phase, setPhase] = React.useState('scan'); // scan | done | finished
  const [completed, setCompleted] = React.useState([]);

  React.useEffect(() => {
    if (i >= cards.length) {
      setPhase('finished');
      const t = setTimeout(onDone, 1400);
      return () => clearTimeout(t);
    }
    setPhase('scan');
    const t1 = setTimeout(() => setPhase('done'), SCAN_MS);
    const t2 = setTimeout(() => {
      setCompleted(c => [...c, cards[i]]);
      setI(j => j + 1);
    }, SCAN_MS + COOL_MS);
    return () => { clearTimeout(t1); clearTimeout(t2); };
  }, [i]);

  const finished = phase === 'finished';
  const currentId = finished ? cards[cards.length - 1] : cards[Math.min(i, cards.length - 1)];
  const card = ROYAL_CATALOGUE.find(c => c.id === currentId) || ROYAL_CATALOGUE[0];

  return (
    <div className="r-screen" style={{
      minHeight: '100dvh', background: R.ink, color: R.pearl,
      display: 'flex', flexDirection: 'column',
      padding: '0 22px', position: 'relative', overflow: 'hidden',
    }}>
      <MashrabiyaBG opacity={0.04} />

      {/* Soft mint halo */}
      <div style={{
        position: 'absolute', width: '110%', height: 380, left: '-5%', top: '10%',
        background: 'radial-gradient(ellipse, rgba(74,155,122,0.22), transparent 60%)',
        filter: 'blur(28px)', animation: 'r-halo 4s ease-in-out infinite',
        pointerEvents: 'none',
      }} />

      {/* Top: progress counter */}
      <div style={{
        position: 'relative', textAlign: 'center', paddingTop: 24,
        animation: 'r-fade 400ms both',
      }}>
        <Eyebrow color={R.gold} ls={3} size={10.5}
          style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
          <span style={{
            width: 6, height: 6, borderRadius: '50%', background: R.gold,
            boxShadow: `0 0 8px ${R.gold}`, animation: 'r-blink 1.2s infinite',
          }} />
          MINTING {Math.min(i + (finished ? 0 : 1), cards.length)} / {cards.length}
        </Eyebrow>
        <ProgressBar pct={((completed.length + (phase === 'done' ? 1 : 0)) / cards.length) * 100}
          height={2} style={{ marginTop: 14, maxWidth: 240, marginInline: 'auto' }} />
      </div>

      {/* Completed stack rail — small fanned thumbnails */}
      <div style={{
        position: 'relative', height: 30, marginTop: 18,
        display: 'flex', justifyContent: 'center',
      }}>
        {completed.map((id, idx) => {
          const c = ROYAL_CATALOGUE.find(x => x.id === id);
          const b = R.bank[(c || {}).bank] || { bg: R.ink3 };
          return (
            <div key={id} style={{
              position: 'relative', marginLeft: idx === 0 ? 0 : -16,
              width: 36, height: 24, borderRadius: 4,
              background: `linear-gradient(135deg, ${b.bg}, ${shade(b.bg, -18)})`,
              border: `0.5px solid ${R.gold}66`,
              boxShadow: `0 4px 12px rgba(0,0,0,0.45), 0 0 0 1px ${R.gold}33`,
              animation: 'r-rise-soft 380ms both',
              transform: `rotate(${(idx - completed.length / 2) * 4}deg)`,
            }} />
          );
        })}
      </div>

      {/* Center: card being scanned */}
      <div style={{
        position: 'relative', flex: 1,
        display: 'flex', flexDirection: 'column', alignItems: 'center',
        justifyContent: 'center', minHeight: 0,
      }}>
        {finished ? (
          <FinishedSeal name={name} />
        ) : (
          <div key={card.id + '-' + i} style={{
            position: 'relative',
            animation: phase === 'done'
              ? 'r-card-out 600ms 300ms cubic-bezier(.2,.7,.2,1) both'
              : 'r-card-in-mint 600ms cubic-bezier(.2,.7,.2,1) both',
          }}>
            <ScanningCard card={card} name={name} phase={phase} variant={i % 5} />
          </div>
        )}

      </div>

      {/* Bottom status */}
      <div style={{
        position: 'relative', textAlign: 'center',
        paddingBottom: 'max(env(safe-area-inset-bottom), 30px)',
      }}>
        {finished ? (
          <div style={{ animation: 'r-rise-soft 500ms both' }}>
            <div style={{
              fontFamily: FR.serif, fontSize: 22, color: R.pearl,
              fontStyle: 'italic', fontWeight: 500, letterSpacing: -0.3,
            }}>
              Your Sikka is <span style={{ color: R.gold }}>minted</span>.
            </div>
            <Eyebrow color={R.pearl4} ls={2.4} style={{ marginTop: 8 }}>
              {cards.length} {cards.length === 1 ? 'CARD LINKED' : 'CARDS LINKED'} · READY
            </Eyebrow>
          </div>
        ) : (
          <React.Fragment>
            <Sub style={{ color: R.pearl, fontSize: 17 }}>
              {phase === 'done' ? (
                <><span style={{ color: R.gold, fontStyle: 'italic' }}>{card.name}</span> linked</>
              ) : (
                <>Reading <span style={{ color: R.gold, fontStyle: 'italic' }}>{card.name}</span>…</>
              )}
            </Sub>
            <Eyebrow color={R.pearl4} style={{ marginTop: 8 }} ls={2.4}>
              SECURE TOKENISATION · OAUTH HANDSHAKE
            </Eyebrow>
          </React.Fragment>
        )}
      </div>

      {/* Scoped keyframes */}
      <style>{`
        @keyframes r-card-in-mint { 0% { transform: translateY(22px) scale(0.94); opacity: 0 }
                                    100% { transform: translateY(0) scale(1); opacity: 1 } }
        @keyframes r-card-out { 0% { transform: translateX(0) scale(1); opacity: 1 }
                                100% { transform: translateX(-180px) scale(0.55) rotate(-8deg); opacity: 0 } }
        @keyframes r-stamp-in { 0% { transform: scale(2.4) rotate(-22deg); opacity: 0 }
                                60% { transform: scale(0.94) rotate(4deg); opacity: 1 }
                                100% { transform: scale(1) rotate(0deg); opacity: 1 } }
        @keyframes r-scan-sweep { 0% { transform: translateY(-50%); opacity: 0 }
                                  15% { opacity: 1 }
                                  85% { opacity: 1 }
                                  100% { transform: translateY(150%); opacity: 0 } }
        @keyframes r-data-in { 0% { opacity: 0; transform: translateX(-8px) }
                              100% { opacity: 1; transform: translateX(0) } }
        @keyframes r-sheen-sweep { 0% { transform: translateX(-120%); opacity: 0 }
                                   12% { opacity: 1 }
                                   88% { opacity: 1 }
                                   100% { transform: translateX(120%); opacity: 0 } }
        @keyframes r-ring-out { 0% { transform: translate(-50%, 50%) scale(0.4); opacity: 0.95 }
                                100% { transform: translate(-50%, 50%) scale(18); opacity: 0 } }
        @keyframes r-pulse-glow { 0%,100% { opacity: 0.2 }
                                  50% { opacity: 0.9 } }
        @keyframes r-holo-sweep { 0% { transform: translateX(-30%); opacity: 0 }
                                  15% { opacity: 1 }
                                  85% { opacity: 1 }
                                  100% { transform: translateX(450%); opacity: 0 } }
        @keyframes r-bracket-in { 0% { transform: rotate(var(--rot, 0deg)) scale(2.4); opacity: 0 }
                                  100% { transform: rotate(var(--rot, 0deg)) scale(1); opacity: 1 } }
      `}</style>
    </div>
  );
}

// Card being scanned — face + variant-specific animation + extracted data + check stamp on done
// variant: 0=vertical scan · 1=diagonal sheen · 2=radial pulse · 3=horizontal holo shimmer · 4=decode reveal
function ScanningCard({ card, name, phase, variant = 0 }) {
  const b = R.bank[card.bank] || { bg: R.ink3, tx: R.pearl };
  const last4 = card.last4 || '0000';
  return (
    <div style={{ position: 'relative' }}>
      {/* Card face */}
      <div style={{
        position: 'relative', width: 270, aspectRatio: '1.586', borderRadius: 16,
        background: `linear-gradient(135deg, ${b.bg} 0%, ${shade(b.bg, -22)} 100%)`,
        color: b.tx, padding: '16px 18px',
        boxShadow: '0 22px 48px rgba(0,0,0,0.65), inset 0 0 0 0.5px rgba(255,255,255,0.1)',
        overflow: 'hidden',
        display: 'flex', flexDirection: 'column', justifyContent: 'space-between',
      }}>
        <div style={{ position: 'relative', zIndex: 2 }}>
          <div style={{
            fontFamily: FR.display, fontSize: 14, fontWeight: 600,
            letterSpacing: 2.6, textTransform: 'uppercase',
          }}>{card.name.split(' ')[0]}</div>
          <div style={{
            fontFamily: FR.mono, fontSize: 9.5, letterSpacing: 1.6,
            opacity: 0.7, marginTop: 3, textTransform: 'uppercase',
          }}>{(card.name.split(' ').slice(1).join(' ') || '')}</div>
        </div>

        <div style={{ display: 'flex', alignItems: 'center', gap: 10,
          position: 'relative', zIndex: 2 }}>
          <GoldChip width={36} height={26} radius={4}
            style={{ position: 'relative', zIndex: 2 }} />
          <span style={{ opacity: 0.85, fontSize: 14, fontFamily: FR.mono }}>))</span>
        </div>

        <div style={{ position: 'relative', zIndex: 2 }}>
          <div style={{
            fontFamily: FR.mono, fontSize: 16, letterSpacing: 1.6,
            marginBottom: 8, color: b.tx, opacity: 0.95,
          }}>
            {phase === 'scan' && variant === 4
              ? <DecodeText final={`···· ···· ····  ${last4}`} duration={1700} />
              : <>···· ···· ····  {last4}</>}
          </div>
          <div style={{
            display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end',
            fontFamily: FR.mono, fontSize: 10.5, letterSpacing: 1.2,
          }}>
            <div style={{ opacity: 0.75 }}>{name.toUpperCase()}</div>
            <div style={{ textAlign: 'right' }}>
              <div style={{ opacity: 0.55, fontSize: 8.5 }}>VALID THRU</div>
              <div>12/30</div>
            </div>
            <div style={{
              fontFamily: FR.serif, fontSize: 18, fontStyle: 'italic',
              fontWeight: 700, color: '#dff0e3', opacity: 0.95,
            }}>VISA</div>
          </div>
        </div>

        {/* ── Variant overlays during scan phase ── */}
        {phase === 'scan' && (
          <ScanOverlay variant={variant} />
        )}

        {/* Check stamp when linked */}
        {phase === 'done' && (
          <div style={{
            position: 'absolute', inset: 0,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            background: 'rgba(0,0,0,0.30)',
            backdropFilter: 'blur(1px)',
            animation: 'r-fade 240ms both',
            zIndex: 5,
          }}>
            <div style={{
              width: 70, height: 70, borderRadius: '50%',
              background: R.gold, color: R.goldInk,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              boxShadow: `0 0 0 6px rgba(74,155,122,0.18), 0 0 30px ${R.gold}88`,
              animation: 'r-stamp-in 600ms cubic-bezier(.2,.7,.2,1) both',
            }}>
              <svg width="32" height="32" viewBox="0 0 24 24" fill="none">
                <path d="M5 12l5 5L20 7" stroke="currentColor"
                  strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </div>
          </div>
        )}
      </div>

      {/* Data points emerging during scan — rule of 3: BIN · LAST 4 · MODE */}
      {phase === 'scan' && (
        <div style={{
          marginTop: 18, padding: '10px 14px',
          background: R.ink2, border: `0.5px solid ${R.hair}`, borderRadius: 10,
          display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 10,
          fontFamily: FR.mono, fontSize: 10, letterSpacing: 1.4,
          animation: 'r-rise-soft 400ms 200ms both',
        }}>
          <DataTile label="BIN" value={'4' + (411111 + card.bank.length * 37).toString().slice(0, 5)} delay={400} />
          <DataTile label="LAST 4" value={last4} delay={700} accent />
          <DataTile label="MODE"
            value={['MAGSTRIPE', 'SHEEN', 'NFC PULSE', 'HOLO READ', 'DECRYPT'][variant]}
            delay={1000} />
        </div>
      )}
    </div>
  );
}

// ─── Per-variant scan overlay ────────────────────────────────────
function ScanOverlay({ variant }) {
  // 0 — Vertical mint scan line + horizontal grid
  if (variant === 0) {
    return (
      <React.Fragment>
        <div style={{
          position: 'absolute', left: 0, right: 0, top: 0, height: 6, zIndex: 3,
          background: `linear-gradient(180deg, ${R.gold}00, ${R.gold}cc, ${R.gold}00)`,
          boxShadow: `0 0 18px ${R.gold}, 0 0 36px ${R.gold}88`,
          animation: 'r-scan-sweep 1700ms ease-in-out',
        }} />
        <div style={{
          position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 1,
          background: 'repeating-linear-gradient(0deg, transparent 0, transparent 7px, rgba(74,155,122,0.06) 7px, rgba(74,155,122,0.06) 8px)',
          mixBlendMode: 'screen',
        }} />
      </React.Fragment>
    );
  }

  // 1 — Diagonal gold sheen sweep
  if (variant === 1) {
    return (
      <React.Fragment>
        <div style={{
          position: 'absolute', inset: -40, pointerEvents: 'none', zIndex: 3,
          background: `linear-gradient(115deg, transparent 35%, ${R.gold}55 47%, ${R.gold}aa 50%, ${R.gold}55 53%, transparent 65%)`,
          mixBlendMode: 'screen',
          animation: 'r-sheen-sweep 1700ms cubic-bezier(.6,.2,.4,.9)',
        }} />
        <div style={{
          position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 1,
          background: 'repeating-linear-gradient(115deg, transparent 0, transparent 4px, rgba(74,155,122,0.05) 4px, rgba(74,155,122,0.05) 5px)',
          mixBlendMode: 'screen',
        }} />
      </React.Fragment>
    );
  }

  // 2 — Radial pulse from chip (centre-left)
  if (variant === 2) {
    return (
      <React.Fragment>
        {[0, 1, 2].map(i => (
          <span key={i} style={{
            position: 'absolute', left: 36, bottom: 56,
            width: 12, height: 12, borderRadius: '50%',
            border: `1.2px solid ${R.gold}`,
            transform: 'translate(-50%, 50%)', zIndex: 3, pointerEvents: 'none',
            animation: `r-ring-out 1700ms ${i * 280}ms ease-out`,
          }} />
        ))}
        <div style={{
          position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 1,
          background: `radial-gradient(circle at 22% 70%, ${R.gold}30 0%, transparent 50%)`,
          mixBlendMode: 'screen',
          animation: 'r-pulse-glow 1700ms ease-out',
        }} />
      </React.Fragment>
    );
  }

  // 3 — Holographic horizontal shimmer
  if (variant === 3) {
    return (
      <React.Fragment>
        <div style={{
          position: 'absolute', top: 0, bottom: 0, left: 0, width: 60, zIndex: 3,
          background: `linear-gradient(90deg,
            transparent 0%,
            rgba(255,215,150,0.18) 25%,
            rgba(74,200,155,0.55) 45%,
            rgba(180,120,210,0.45) 65%,
            rgba(255,215,150,0.18) 80%,
            transparent 100%)`,
          mixBlendMode: 'screen',
          filter: 'blur(0.5px)',
          animation: 'r-holo-sweep 1700ms cubic-bezier(.6,.2,.4,.9)',
        }} />
        <div style={{
          position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 1,
          background: 'repeating-linear-gradient(90deg, transparent 0, transparent 2px, rgba(255,255,255,0.05) 2px, rgba(255,255,255,0.05) 3px)',
          mixBlendMode: 'overlay',
        }} />
      </React.Fragment>
    );
  }

  // 4 — Decode reveal (corner brackets close in)
  return (
    <React.Fragment>
      {[
        { top: 8, left: 8, rot: 0 },
        { top: 8, right: 8, rot: 90 },
        { bottom: 8, right: 8, rot: 180 },
        { bottom: 8, left: 8, rot: 270 },
      ].map((p, idx) => (
        <span key={idx} style={{
          position: 'absolute', ...p, width: 18, height: 18, zIndex: 3,
          borderTop: `1.5px solid ${R.gold}`,
          borderLeft: `1.5px solid ${R.gold}`,
          transform: `rotate(${p.rot}deg)`,
          opacity: 0,
          animation: `r-bracket-in 1400ms ${idx * 120}ms ease-out forwards`,
          filter: `drop-shadow(0 0 4px ${R.gold}88)`,
        }} />
      ))}
      <div style={{
        position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 1,
        background: `radial-gradient(ellipse at 50% 50%, ${R.gold}25 0%, transparent 55%)`,
        mixBlendMode: 'screen',
        opacity: 0,
        animation: 'r-fade 600ms 200ms forwards',
      }} />
    </React.Fragment>
  );
}

// Scrambling decode reveal — locks in characters left-to-right
function DecodeText({ final, duration = 1700 }) {
  const [text, setText] = React.useState(final.replace(/[0-9]/g, '0'));
  React.useEffect(() => {
    const start = performance.now();
    const indices = [];
    for (let i = 0; i < final.length; i++) if (/[0-9]/.test(final[i])) indices.push(i);
    let raf;
    const tick = (t) => {
      const p = Math.min(1, (t - start) / duration);
      const locked = Math.floor(p * indices.length);
      const arr = final.split('');
      for (let j = locked; j < indices.length; j++) {
        arr[indices[j]] = String(Math.floor(Math.random() * 10));
      }
      setText(arr.join(''));
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [final, duration]);
  return <span>{text}</span>;
}

function DataPoint({ label, value, delay }) {
  return (
    <div style={{
      display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
      gap: 8, opacity: 0,
      animation: `r-data-in 280ms ${delay}ms cubic-bezier(.2,.7,.2,1) both`,
      borderBottom: `0.5px dashed ${R.hair2}`, paddingBottom: 3,
    }}>
      <span style={{ color: R.pearl4 }}>{label}</span>
      <span style={{ color: R.gold }}>{value}</span>
    </div>
  );
}

// Stacked tile variant — label on top, value below. Used in 3-col grids
// where horizontal label/value layout would crowd long values.
function DataTile({ label, value, delay = 0, accent = false }) {
  return (
    <div style={{
      opacity: 0,
      animation: `r-data-in 320ms ${delay}ms cubic-bezier(.2,.7,.2,1) both`,
      borderRight: `0.5px dashed ${R.hair2}`, paddingRight: 8,
      minWidth: 0, overflow: 'hidden',
    }}>
      <div style={{ color: R.pearl4, fontSize: 8.5, letterSpacing: 1.6,
        textTransform: 'uppercase' }}>{label}</div>
      <div style={{
        color: accent ? R.goldH : R.gold, marginTop: 4,
        fontSize: 11, letterSpacing: 1.2, fontWeight: 500,
        whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
      }}>{value}</div>
    </div>
  );
}

// Finished state — animated coin + all-linked seal
function FinishedSeal({ name }) {
  return (
    <div style={{ position: 'relative', textAlign: 'center' }}>
      <div style={{
        position: 'relative',
        animation: 'r-pop 600ms cubic-bezier(.2,.7,.2,1) both',
      }}>
        <div style={{
          position: 'absolute', inset: -50, borderRadius: '50%',
          background: 'radial-gradient(circle, rgba(74,155,122,0.45), transparent 65%)',
          filter: 'blur(20px)', animation: 'r-halo 2s ease-in-out infinite',
        }} />
        <div style={{
          position: 'relative',
          animation: 'r-coin-spin 5s ease-in-out infinite',
        }}>
          <CoinMark size={130} />
        </div>
      </div>
    </div>
  );
}

// Legacy alias kept for compatibility — used by other prototypes/screens
function BankCardFace({ card, name = 'Praneet Sinha' }) {
  return <ScanningCard card={card} name={name} phase="idle" />;
}

Object.assign(window, {
  ROYAL_CATALOGUE,
  Splash, PhoneStep, OtpStep, NameStep, PickCards, LinkingScreen, BankCardFace,
});
