// ─────────────────────────────────────────────────────────────────
// SIKKA ROYALE — Pay flow, Marketplace, Bills
// UX touches: hold-to-pay, gold-seal routing reveal, certificate receipt
// ─────────────────────────────────────────────────────────────────

const ROYAL_MERCHANTS = [
  { id: 'carrefour', name: 'Carrefour',  initial: 'C',  bg: '#1c4cc0', tx: '#fff' },
  { id: 'talabat',   name: 'Talabat',    initial: 'T',  bg: '#fa6541', tx: '#fff' },
  { id: 'emirates',  name: 'Emirates',   initial: 'EK', bg: '#a31a24', tx: '#fff' },
  { id: 'adnoc',     name: 'ADNOC',      initial: 'AD', bg: '#0c2d60', tx: '#fff' },
  { id: 'noon',      name: 'Noon',       initial: 'N',  bg: '#f5d020', tx: '#1c0c00' },
  { id: 'spinneys',  name: 'Spinneys',   initial: 'S',  bg: '#2db95e', tx: '#06170d' },
];

// ─── Pay · Merchant picker ─────────────────────────────────────────
function PayMerchantPicker({ onBack, onPick }) {
  return (
    <div className="r-screen" style={{
      minHeight: '100dvh', background: R.ink, color: R.pearl,
      paddingBottom: 96, position: 'relative',
    }}>
      <MashrabiyaBG opacity={0.04} />
      <TopBar onBack={onBack} center="PAY · ادفع" />

      <div style={{ padding: '20px 22px 0', animation: 'r-rise 600ms both' }}>
        <Headline lead="Which card" tail="wins" tailPunct=" this tap?" size={42} />
        <Bilingual
          en="Sikka chooses the best card the instant you tap."
          ar="يختار سِكَّة أفضل بطاقة في لحظة اللمس."
          size={15} style={{ marginTop: 14 }} />
      </div>

      {/* Pay at counter — hero CTA */}
      <div style={{ padding: '22px 22px 0', animation: 'r-rise-soft 600ms 120ms both' }}>
        <button onClick={() => onPick({ id: 'counter', name: 'Pay at counter' })} style={{
          position: 'relative', width: '100%', textAlign: 'left', cursor: 'pointer',
          padding: '18px',
          background: `
            radial-gradient(ellipse 80% 60% at 100% 100%, rgba(74,155,122,0.10), transparent 60%),
            ${R.velvet}`,
          border: `0.5px solid ${R.gold}66`, borderRadius: 18,
          color: R.pearl, overflow: 'hidden',
          display: 'flex', alignItems: 'center', gap: 14,
        }}>
          <FiligreeCorners inset={6} length={16} opacity={0.6} />
          <div style={{
            position: 'relative', overflow: 'hidden',
            width: 56, height: 56, borderRadius: 14,
            background: `linear-gradient(140deg, ${R.goldH} 0%, ${R.gold} 100%)`,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            boxShadow: `0 6px 18px ${R.gold}55, inset 0 1.5px 1.5px rgba(255,255,255,0.6)`, color: R.goldInk,
            fontFamily: FR.display, fontWeight: 700, fontSize: 22,
          }}>
            <CoinMark size={34} color={R.goldInk} accent={R.goldD} />
            {/* static gloss highlight */}
            <span style={{ position: 'absolute', inset: 0, pointerEvents: 'none', borderRadius: 14,
              background: 'linear-gradient(158deg, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0.12) 24%, transparent 46%)' }} />
            {/* animated sheen sweep */}
            <span style={{ position: 'absolute', top: 0, bottom: 0, left: '-40%', width: '38%',
              pointerEvents: 'none', transform: 'skewX(-18deg)',
              background: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.6), transparent)',
              animation: 'r-sheen 2.8s ease-in-out 1.2s infinite' }} />
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{
              display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap',
              fontFamily: FR.serif, fontSize: 22, color: R.pearl,
              letterSpacing: -0.3, fontWeight: 500, fontStyle: 'italic',
            }}>
              Pay at counter
            </div>
            <Eyebrow color={R.gold} style={{ marginTop: 4 }}>
              TAP-TO-PAY · QR · SIKKA ROUTES
            </Eyebrow>
          </div>
          <svg width="20" height="20" viewBox="0 0 20 20" fill="none" style={{ color: R.gold, flexShrink: 0 }}>
            <path d="M7 4L13 10L7 16" stroke="currentColor" strokeWidth="1.6"
              strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        </button>
      </div>

      {/* divider */}
      <div style={{ padding: '24px 22px 12px', animation: 'r-fade 600ms 200ms both' }}>
        <StarDivider />
        <Eyebrow color={R.pearl4} style={{ marginTop: 14, textAlign: 'center' }}>
          OR CHOOSE A HOUSE
        </Eyebrow>
      </div>

      <div style={{
        padding: '0 22px 22px',
        display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 10,
      }}>
        {ROYAL_MERCHANTS.map((m, i) => (
          <button key={m.id} onClick={() => onPick(m)} style={{
            padding: '14px 10px', background: R.ink2, cursor: 'pointer',
            border: `0.5px solid ${R.hair}`, borderRadius: 14,
            color: R.pearl, display: 'flex', flexDirection: 'column',
            alignItems: 'center', gap: 12, minHeight: 110,
            animation: `r-rise-soft 500ms ${260 + i*60}ms both`,
          }}>
            <BrandTile size={44} radius={10} domain={BRAND_DOMAIN[m.name]}
              initial={m.initial} bg={m.bg} tx={m.tx} />
            <div style={{
              fontFamily: FR.serif, fontSize: 15, color: R.pearl,
              letterSpacing: -0.2, fontWeight: 500,
            }}>{m.name}</div>
          </button>
        ))}
      </div>
    </div>
  );
}

// ─── Pay · Amount keypad ───────────────────────────────────────────
function PayAmountKeypad({ merchant, onBack, onPay }) {
  const [amt, setAmt] = React.useState('50');
  const press = (k) => {
    setAmt(prev => {
      if (k === '⌫') return prev.length <= 1 ? '0' : prev.slice(0, -1);
      if (k === '.') return prev.includes('.') ? prev : prev + '.';
      if (prev === '0') return k;
      if (prev.length >= 9) return prev;
      return prev + k;
    });
  };
  const keys = ['1','2','3','4','5','6','7','8','9','.','0','⌫'];
  const [whole, frac] = amt.includes('.') ? amt.split('.') : [amt, '00'];
  const fracDisplay = (frac + '00').slice(0, 2);
  const valid = amt !== '0' && amt !== '';

  return (
    <div className="r-screen" style={{
      minHeight: '100dvh', background: R.ink, color: R.pearl,
      display: 'flex', flexDirection: 'column', position: 'relative',
    }}>
      <MashrabiyaBG opacity={0.03} />
      <TopBar onBack={onBack}
        center={merchant.name.toUpperCase()} />

      {/* Amount */}
      <div style={{
        flex: 1, padding: '32px 22px 0', textAlign: 'center',
        animation: 'r-fade 500ms both',
      }}>
        <Eyebrow color={R.gold} ls={2.8} size={10}>
          PAYING {'· ' + merchant.name.toUpperCase() + ' ·'}
        </Eyebrow>
        <div style={{
          marginTop: 14, display: 'flex', alignItems: 'baseline',
          justifyContent: 'center', gap: 6,
        }}>
          <span style={{
            fontFamily: FR.display, fontSize: 14, color: R.gold,
            letterSpacing: 3, fontWeight: 600,
          }}>AED</span>
          <span style={{
            fontFamily: FR.serif, fontSize: 88, color: R.pearl,
            letterSpacing: 88 * -0.014, lineHeight: 1, fontWeight: 500,
            fontVariantNumeric: 'tabular-nums',
          }}>{whole}</span>
          <span style={{
            fontFamily: FR.serif, fontSize: 88, color: R.pearl4,
            letterSpacing: 88 * -0.014, lineHeight: 1, fontWeight: 500,
            fontVariantNumeric: 'tabular-nums',
          }}>.{fracDisplay}</span>
        </div>
        <div style={{
          marginTop: 14, fontFamily: FR.arab, fontSize: 14, color: R.pearl4,
          direction: 'rtl',
        }}>درهم إماراتي</div>
      </div>

      {/* Hold-to-pay button */}
      <div style={{ padding: '6px 22px 12px' }}>
        <HoldToPay disabled={!valid} onConfirm={() => onPay(amt)} />
      </div>

      {/* Keypad */}
      <div style={{
        padding: '0 16px max(env(safe-area-inset-bottom), 14px)',
        display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8,
      }}>
        {keys.map((k) => {
          if (k === '⌫') {
            return (
              <button key={k} onClick={() => press(k)} aria-label="Delete" style={keyStyle()}>
                <svg width="20" height="20" viewBox="0 0 24 24" fill="none">
                  <path d="M9 5h10a2 2 0 012 2v10a2 2 0 01-2 2H9l-7-7 7-7z M14 9l-5 5M9 9l5 5"
                    stroke={R.pearl} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
              </button>
            );
          }
          return (
            <button key={k} onClick={() => press(k)} style={keyStyle()}>{k}</button>
          );
        })}
      </div>
    </div>
  );
}

function keyStyle() {
  return {
    padding: '16px 0', minHeight: 44, border: `0.5px solid ${R.hair}`,
    background: R.ink2, color: R.pearl,
    borderRadius: 14, fontFamily: FR.serif, fontSize: 26,
    cursor: 'pointer', fontVariantNumeric: 'tabular-nums', fontWeight: 500,
  };
}

// ─── Hold-to-pay control — long-press fills a gold ring ────────────
function HoldToPay({ onConfirm, disabled }) {
  const [pressing, setPressing] = React.useState(false);
  const [done, setDone] = React.useState(false);
  const timerRef = React.useRef(null);
  const HOLD_MS = 900;

  const start = (e) => {
    if (disabled || done) return;
    e.preventDefault();
    setPressing(true);
    timerRef.current = setTimeout(() => {
      setDone(true);
      setTimeout(onConfirm, 200);
    }, HOLD_MS);
  };
  const cancel = () => {
    setPressing(false);
    if (timerRef.current) {
      clearTimeout(timerRef.current);
      timerRef.current = null;
    }
  };

  return (
    <button
      onMouseDown={start} onMouseUp={cancel} onMouseLeave={cancel}
      onTouchStart={start} onTouchEnd={cancel} onTouchCancel={cancel}
      disabled={disabled}
      style={{
        position: 'relative', width: '100%', padding: '17px 22px',
        border: 'none', cursor: disabled ? 'not-allowed' : 'pointer',
        color: R.goldInk, overflow: 'hidden',
        background: disabled
          ? 'linear-gradient(180deg, rgba(74,155,122,0.4), rgba(47,110,84,0.5))'
          : `linear-gradient(180deg, ${R.goldH} 0%, ${R.gold} 50%, ${R.goldD} 100%)`,
        boxShadow: disabled ? 'none' :
          '0 14px 32px rgba(74,155,122,0.25), inset 0 0 0 0.5px rgba(220,255,235,0.6), inset 0 -2px 0 rgba(8,28,18,0.35)',
        borderRadius: 14,
        fontFamily: FR.display, fontSize: 14, letterSpacing: 3.6,
        textTransform: 'uppercase', fontWeight: 600,
        transform: pressing ? 'scale(0.985)' : 'scale(1)',
        transition: 'transform 200ms',
      }}>
      <span style={{ position: 'relative', zIndex: 2, display: 'inline-flex', alignItems: 'center', gap: 7 }}>
        {done && (
          <svg width="13" height="13" viewBox="0 0 12 12" fill="none">
            <path d="M2 6l3 3 5-6" stroke="currentColor" strokeWidth="1.8"
              strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        )}
        {done ? 'Confirmed' : pressing ? 'Hold to pay…' : 'Hold to pay'}
      </span>
      {/* Fill bar */}
      <span style={{
        position: 'absolute', left: 0, top: 0, bottom: 0,
        width: pressing ? '100%' : '0%',
        background: 'linear-gradient(90deg, rgba(225,255,240,0.55), rgba(225,255,240,0.25))',
        transition: pressing
          ? `width ${HOLD_MS}ms linear`
          : 'width 200ms cubic-bezier(.2,.7,.2,1)',
        pointerEvents: 'none', zIndex: 1,
      }} />
    </button>
  );
}

// ─── Pay · Routing live ───────────────────────────────────────────
// Cinematic engine animation in 4 phases:
//   0 read   — amount lands, scan-line sweeps the panel
//   1 score  — three cards race their score bars + earn tickers
//   2 settle — runners-up dim and recede; winner elevates with gold halo
//   3 stamp  — engraved seal stamps the winner; laser line links amount→card
// Fallback used only if the engine call fails or there's no linked data.
const FALLBACK_ROUTING_CARDS = [
  { id: 'adcb', label: 'ADCB TouchPoints', last4: '6242', rule: '1.00% Everyday', finalScore: 94, earnRate: 0.0100 },
  { id: 'fab',  label: 'FAB Cashback',     last4: '2891', rule: '0.50% Standard', finalScore: 58, earnRate: 0.0050 },
  { id: 'enbd', label: 'ENBD Skywards',    last4: '4108', rule: '0.25 mi / AED',  finalScore: 42, earnRate: 0.0025 },
];

// ROYAL_CATALOGUE card id → bank chip id used by R.bank lookups
const ROUTING_BANK_BY_ID = {
  'adcb': 'adcb', 'adcb-365': 'adcb', 'adcb-lulu': 'adcb', 'adcb-etihad': 'adcb',
  'fab': 'fab', 'fab-rewards': 'fab', 'fab-etihad': 'fab', 'fab-istarter': 'fab',
  'enbd-sky': 'enbd', 'enbd-emaar': 'enbd', 'enbd-dnata': 'enbd', 'enbd-go': 'enbd',
  'mashreq': 'mashreq', 'wio': 'wio',
  'rak': 'rak', 'rak-titanium': 'rak',
  'adib': 'adib', 'adib-etihad': 'adib',
  'cbd': 'cbd', 'cbd-super': 'cbd',
  'hsbc-prem': 'adcb', 'sc-priority': 'fab', 'citi-prest': 'cbd',
};

// ROYAL_CATALOGUE bank → engine issuer string used by src/catalog.ts
const ROUTING_ISSUER_BY_BANK = {
  adcb: 'ADCB', fab: 'FAB', enbd: 'Emirates NBD', mashreq: 'Mashreq',
  wio: 'Wio', rak: 'RAKBANK', adib: 'ADIB', cbd: 'CBD',
  hsbc: 'HSBC', sc: 'SCB', citi: 'Citi',
};

function PayRoutingLive({ merchant, amount, linked, onComplete, onBack }) {
  const [phase, setPhase] = React.useState(0); // 0 read | 1 score | 2 settle | 3 stamp
  const [routingCards, setRoutingCards] = React.useState(FALLBACK_ROUTING_CARDS);
  const amtNum = parseFloat(amount) || 0;

  // Live engine call — POST /recommendations/card-routing with the user's
  // actually-linked cards, mapped to the catalog shape the engine expects.
  React.useEffect(() => {
    const ids = (linked && linked.length > 0) ? linked : ['adcb', 'fab', 'enbd-sky'];
    const catalogue = (typeof window !== 'undefined' && window.ROYAL_CATALOGUE) || [];
    const linkedFull = ids.map(id => catalogue.find(c => c.id === id)).filter(Boolean);
    const inlineCards = linkedFull.map((c, i) => ({
      id: 'card_' + i, userId: 'demo',
      cardName: c.name,
      issuer: ROUTING_ISSUER_BY_BANK[c.bank] || c.bank,
      last4: c.last4 || String(1000 + (i * 1111) % 9000),
      confidence: 'medium', source: 'manual',
    }));

    let cancelled = false;
    let timers = [];
    (async () => {
      let rec = null;
      try {
        const r = await fetch('/recommendations/card-routing', {
          method: 'POST', headers: { 'content-type': 'application/json' },
          body: JSON.stringify({
            userId: 'demo',
            merchantName: merchant && merchant.id === 'counter' ? 'At counter' : (merchant?.name || 'Carrefour'),
            amountAed: amtNum,
            cards: inlineCards,
            rewardPreference: 'cashback',
          }),
        });
        rec = await r.json();
      } catch (e) { rec = null; }
      if (cancelled) return;

      // Map engine response → ROUTING_CARDS shape. Sort by valueAed desc.
      // Show ALL linked cards (not just top 3) so the user sees the full
      // evaluation set — proves Sikka actually scored every card.
      if (rec && Array.isArray(rec.evaluatedCards) && rec.evaluatedCards.length > 0) {
        const sorted = rec.evaluatedCards.slice().sort((a, b) => Number(b.valueAed || 0) - Number(a.valueAed || 0));
        const maxValue = Number(sorted[0]?.valueAed) || 1;
        const real = sorted.map((ec) => {
          const ix = linkedFull.findIndex(lc => lc.name === ec.cardName);
          const lc = ix >= 0 ? linkedFull[ix] : null;
          const cat = ec.category || rec.category || 'spend';
          const pct = Number(ec.rewardRate || 0) * 100;
          const rateText = pct >= 1 ? pct.toFixed(1).replace(/\.0$/, '') + '%' : pct.toFixed(2) + '%';
          const ratio = maxValue > 0 ? Math.min(1, Number(ec.valueAed || 0) / maxValue) : 0;
          return {
            id: lc ? (ROUTING_BANK_BY_ID[lc.id] || lc.bank) : 'adcb',
            label: ec.cardName || (lc && lc.name) || 'Card',
            last4: (lc && lc.last4) || (inlineCards[ix] && inlineCards[ix].last4) || '••••',
            rule: rateText + ' on ' + cat,
            finalScore: Math.round(20 + ratio * 78),
            earnRate: Number(ec.rewardRate || 0),
          };
        });
        if (real.length > 0) setRoutingCards(real);
      }

      // Slower phase timing — engine should read as deliberate, not flippant.
      // Adds ~1.5s to the score phase so the user sees the bars actually race.
      timers.push(setTimeout(() => !cancelled && setPhase(1), 900));
      timers.push(setTimeout(() => !cancelled && setPhase(2), 3700));
      timers.push(setTimeout(() => !cancelled && setPhase(3), 4500));
      timers.push(setTimeout(() => {
        if (cancelled) return;
        const winnerLabel = (rec && rec.bestCardName) ? rec.bestCardName : 'ADCB TouchPoints';
        const earned = (rec && Number(rec.estimatedBestValueAed)) || 0;
        const saved  = (rec && Number(rec.extraValueAed)) || 0;
        onComplete && onComplete({ winner: winnerLabel, earn: earned, saved });
      }, 6200));
    })();
    return () => {
      cancelled = true;
      timers.forEach(clearTimeout);
    };
  }, [merchant && merchant.id, amount]);

  const winner = routingCards[0] || FALLBACK_ROUTING_CARDS[0];

  const statusLabel = phase === 0 ? 'READING TRANSACTION'
    : phase === 1 ? 'EVALUATING CARDS'
    : phase === 2 ? 'SELECTING BEST ROUTE'
    : 'ROUTED · ' + winner.label.toUpperCase();

  return (
    <div className="r-screen" style={{
      minHeight: '100dvh', background: R.ink, color: R.pearl,
      paddingBottom: 24, position: 'relative',
    }}>
      <MashrabiyaBG opacity={0.04} />
      <TopBar onBack={onBack}
        center={<Eyebrow color={R.gold} ls={3} style={{ display: 'inline-flex', alignItems: 'center', gap: 7, animation: 'r-blink 1.4s infinite' }}>
          <span style={{
            width: 6, height: 6, borderRadius: '50%',
            background: R.gold, boxShadow: `0 0 8px ${R.gold}`, flexShrink: 0,
          }} />
          ROUTING LIVE
        </Eyebrow>} />

      {/* Compact merchant + amount header */}
      <div style={{ padding: '8px 22px 0', animation: 'r-rise 500ms both' }}>
        <div style={{
          position: 'relative', borderRadius: 16, padding: '14px 16px',
          background: R.velvet, border: `0.5px solid ${R.hair3}`, overflow: 'hidden',
          display: 'flex', alignItems: 'center', gap: 12,
        }}>
          <FiligreeCorners inset={6} length={14} opacity={0.5} />
          <div style={{
            position: 'relative', overflow: 'hidden',
            width: 44, height: 44, borderRadius: 12,
            background: `linear-gradient(140deg, ${R.goldH} 0%, ${R.gold} 100%)`,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            boxShadow: `0 6px 18px ${R.gold}55, inset 0 1.5px 1.5px rgba(255,255,255,0.6)`,
            color: R.goldInk, flexShrink: 0,
          }}>
            <CoinMark size={28} color={R.goldInk} accent={R.goldD} />
            {/* static gloss highlight */}
            <span style={{ position: 'absolute', inset: 0, pointerEvents: 'none', borderRadius: 12,
              background: 'linear-gradient(158deg, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0.12) 24%, transparent 46%)' }} />
            {/* animated sheen sweep */}
            <span style={{ position: 'absolute', top: 0, bottom: 0, left: '-40%', width: '38%',
              pointerEvents: 'none', transform: 'skewX(-18deg)',
              background: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.6), transparent)',
              animation: 'r-sheen 2.8s ease-in-out 1.2s infinite' }} />
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <Eyebrow color={R.pearl4} size={9} ls={2}>PAYING</Eyebrow>
            <div style={{
              fontFamily: FR.serif, fontSize: 19, color: R.pearl,
              letterSpacing: -0.3, fontWeight: 500, fontStyle: 'italic',
              marginTop: 2,
            }}>{merchant.name}</div>
          </div>
          <div style={{ textAlign: 'right' }}>
            <Eyebrow color={R.pearl4} size={9} ls={2}>AMOUNT</Eyebrow>
            <div style={{
              fontFamily: FR.serif, fontSize: 22, color: R.gold,
              letterSpacing: -0.5, fontWeight: 500, marginTop: 2,
              fontVariantNumeric: 'tabular-nums',
            }}>{amtNum.toFixed(2)}</div>
          </div>
        </div>
      </div>

      {/* Engine */}
      <div style={{ padding: '14px 22px 0', animation: 'r-rise-soft 500ms 80ms both' }}>
        <div style={{
          position: 'relative', padding: '18px',
          background: R.ink2, border: `0.5px solid ${R.hair2}`, borderRadius: 18,
          overflow: 'hidden',
        }}>
          {/* Sweeping highlight beam during score phase */}
          {phase >= 1 && phase < 3 && (
            <div style={{
              position: 'absolute', top: 0, bottom: 0, width: '38%', left: 0,
              background: `linear-gradient(90deg, transparent, ${R.gold}22, transparent)`,
              animation: 'r-beam 1.6s ease-in-out infinite',
              pointerEvents: 'none', zIndex: 0,
            }} />
          )}

          {/* Top: engine label */}
          <div style={{
            display: 'flex', justifyContent: 'space-between', alignItems: 'center',
            position: 'relative', zIndex: 1,
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <span style={{
                width: 6, height: 6, borderRadius: '50%',
                background: phase >= 3 ? R.emerald : R.gold,
                boxShadow: `0 0 8px ${phase >= 3 ? R.emerald : R.gold}`,
                animation: phase < 3 ? 'r-blink 1s infinite' : 'none',
              }} />
              <Eyebrow color={R.gold} ls={2.6} size={10}>SIKKA ENGINE</Eyebrow>
            </div>
            <Eyebrow color={R.pearl4} size={9} ls={1.8}
              style={{ fontVariantNumeric: 'tabular-nums' }}>
              {phase < 3 ? 'SCANNING' : 'STAMPED'}
            </Eyebrow>
          </div>

          {/* Headline — changes per phase */}
          <div style={{ marginTop: 10, position: 'relative', zIndex: 1 }}>
            <div key={phase < 3 ? 'pre' : 'post'} style={{
              fontFamily: FR.serif, fontSize: 22, color: R.pearl,
              letterSpacing: -0.4, fontWeight: 500, lineHeight: 1.2, fontStyle: 'italic',
              animation: 'r-fade 400ms both',
            }}>
              {phase < 3
                ? <>Best card for <span style={{ color: R.gold }}>AED {amtNum.toFixed(2)}</span>?</>
                : <>Routed to <span style={{ color: R.gold }}>{winner.label}</span>.</>}
            </div>
          </div>

          {/* Cards stack */}
          <div style={{
            marginTop: 16, display: 'flex', flexDirection: 'column', gap: 9,
            position: 'relative', zIndex: 1,
          }}>
            {routingCards.map((c, i) => (
              <RoutingCardRow key={c.id + '_' + i}
                card={c} amount={amtNum}
                phase={phase}
                isWinner={i === 0}
                delay={i * 110}
              />
            ))}
          </div>

          {/* Status footer */}
          <div style={{
            marginTop: 14, display: 'flex', alignItems: 'center', justifyContent: 'center',
            gap: 8, position: 'relative', zIndex: 1, minHeight: 18,
          }}>
            {phase < 3 ? (
              <>
                <Eyebrow color={R.gold} ls={2.4} size={10}
                  style={{ animation: 'r-fade 300ms both' }}>{statusLabel}</Eyebrow>
                <Dots />
              </>
            ) : (
              <Eyebrow color={R.emerald} ls={2.4} size={10}
                style={{ display: 'inline-flex', alignItems: 'center', gap: 6, animation: 'r-pop 360ms both' }}>
                <svg width="12" height="12" viewBox="0 0 12 12" fill="none" style={{ flexShrink: 0 }}>
                  <path d="M2 6l3 3 5-6" stroke="currentColor" strokeWidth="1.8"
                    strokeLinecap="round" strokeLinejoin="round" />
                </svg>
                {statusLabel}
              </Eyebrow>
            )}
          </div>
        </div>
      </div>

      <div style={{ flex: 1, minHeight: 24 }} />
    </div>
  );
}

// Single routing card row — bank chip, name, score bar that races,
// animated earn ticker, and post-decision elevation/dimming.
function RoutingCardRow({ card, amount, phase, isWinner, delay }) {
  // Score animates only after phase 1 begins
  const scoring = phase >= 1;
  const settled = phase >= 2;
  const stamped = phase >= 3;

  // Earn ticker — animates from 0 to final value during score phase
  const finalEarn = amount * card.earnRate;
  const [earn, setEarn] = React.useState(0);
  React.useEffect(() => {
    if (!scoring) return;
    const start = performance.now() + delay;
    const dur = 1200;
    let raf;
    const tick = (now) => {
      const p = Math.max(0, Math.min(1, (now - start) / dur));
      const e = 1 - Math.pow(1 - p, 3);
      setEarn(finalEarn * e);
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [scoring, finalEarn, delay]);

  const dim = settled && !isWinner;
  const elev = stamped && isWinner;

  return (
    <div style={{
      position: 'relative', display: 'flex', alignItems: 'center', gap: 12,
      padding: '12px 14px',
      background: R.ink3, borderRadius: 12,
      borderLeft: `3px solid ${(R.bank[card.id] || {}).bg || R.gold}`,
      opacity: dim ? 0.34 : 1,
      transform: dim ? 'scale(0.97)' : elev ? 'scale(1.025)' : 'scale(1)',
      boxShadow: elev
        ? `0 0 0 1.5px ${R.gold}, 0 14px 32px rgba(74,155,122,0.28)`
        : 'none',
      transition: 'opacity 500ms cubic-bezier(.2,.7,.2,1), transform 500ms cubic-bezier(.2,.7,.2,1), box-shadow 400ms',
      overflow: 'hidden',
      animation: `r-card-in 480ms ${delay}ms both`,
    }}>
      <BankAvatar id={card.id} size={32}
        text={card.id.toUpperCase().slice(0, 2)} />

      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
          gap: 8,
        }}>
          <div style={{
            fontFamily: FR.serif, fontSize: 15.5, color: R.pearl,
            letterSpacing: -0.2, fontWeight: 500,
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          }}>{card.label}</div>
          <div style={{
            fontFamily: FR.mono, fontSize: 12.5,
            color: isWinner && stamped ? R.gold : R.pearl2,
            letterSpacing: 0.4, flexShrink: 0,
            fontVariantNumeric: 'tabular-nums',
            transition: 'color 300ms',
          }}>+AED {earn.toFixed(2)}</div>
        </div>
        <Eyebrow size={8.5} ls={1.4} color={R.pearl4} style={{ marginTop: 3 }}>
          ····{card.last4} · {card.rule}
        </Eyebrow>

        {/* Score bar — races to its final value over 1.4s */}
        <div style={{
          marginTop: 8, height: 3, background: R.hair, borderRadius: 99,
          overflow: 'hidden', position: 'relative',
        }}>
          <div style={{
            position: 'absolute', inset: 0,
            width: scoring ? card.finalScore + '%' : '0%',
            background: isWinner
              ? `linear-gradient(90deg, ${R.goldD}, ${R.gold} 60%, ${R.goldH})`
              : `linear-gradient(90deg, ${R.pearl5}, ${R.pearl3})`,
            boxShadow: isWinner && scoring
              ? `0 0 8px ${R.gold}88`
              : 'none',
            transition: `width ${1200 + delay}ms cubic-bezier(.2,.7,.2,1), background 300ms`,
            borderRadius: 99,
          }} />
        </div>
      </div>

      {/* Winner seal — animates in at stamp phase */}
      {elev && (
        <div style={{
          position: 'absolute', right: -6, top: '50%',
          transform: 'translate(0, -50%)',
          animation: 'r-stamp 700ms cubic-bezier(.2,.7,.2,1) both',
          pointerEvents: 'none',
        }}>
          <RoyalSeal size={52} />
        </div>
      )}
      {/* Spark burst under winner seal */}
      {elev && (
        <div style={{
          position: 'absolute', right: 14, top: '50%',
          width: 60, height: 60, transform: 'translate(0, -50%)',
          borderRadius: '50%',
          background: `radial-gradient(circle, ${R.gold}55 0%, transparent 70%)`,
          animation: 'r-spark 900ms ease-out both',
          pointerEvents: 'none',
        }} />
      )}
    </div>
  );
}

function Dots() {
  return (
    <span style={{ display: 'inline-flex', gap: 4 }}>
      {[0,1,2].map(i => (
        <span key={i} style={{
          width: 4, height: 4, borderRadius: '50%', background: R.gold,
          display: 'inline-block',
          animation: `r-dot-bounce 1.2s ${i * 0.15}s ease-in-out infinite`,
        }} />
      ))}
    </span>
  );
}

function RoutingRow_DEPRECATED() { return null; }

// ─── Pay · Receipt (Certificate) ──────────────────────────────────
function PayReceipt({ merchant, amount, winner = 'ADCB TouchPoints', earn = '0.50', saved = '0.50',
  onBack, onHome }) {
  const time = new Date().toLocaleTimeString('en-GB', { hour: 'numeric', minute: '2-digit', hour12: true });
  const dateStr = new Date().toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' });

  return (
    <div className="r-screen" style={{
      minHeight: '100dvh', background: R.ink, color: R.pearl,
      paddingBottom: 96, position: 'relative',
    }}>
      <MashrabiyaBG opacity={0.04} />
      <TopBar onBack={onBack} center="RECEIPT" />

      {/* Certificate panel */}
      <div style={{
        padding: '18px 22px 0',
        animation: 'r-pop 600ms cubic-bezier(.2,.7,.2,1) both',
      }}>
        <div style={{
          position: 'relative', borderRadius: 20,
          background: R.velvet,
          border: `0.5px solid ${R.gold}66`,
          padding: '26px 22px 22px',
          overflow: 'hidden',
        }}>
          <FiligreeCorners inset={8} length={20} opacity={0.6} />

          {/* Approved word */}
          <Eyebrow color={R.gold} ls={3.4} style={{ textAlign: 'center' }}>
            CERTIFICATE OF SETTLEMENT
          </Eyebrow>
          <div style={{
            fontFamily: FR.serif, fontSize: 54, color: R.gold,
            letterSpacing: 54 * -0.014, fontWeight: 500, lineHeight: 1, textAlign: 'center',
            fontStyle: 'italic', marginTop: 8,
          }}>Approved</div>
          <div style={{
            fontFamily: FR.mono, fontSize: 10, color: R.goldH,
            textAlign: 'center', marginTop: 10, letterSpacing: 3.4,
            textTransform: 'uppercase', opacity: 0.85,
          }}>NO · {Math.floor(Math.random() * 90000 + 10000)} · 2026</div>

          <div style={{ marginTop: 18 }}>
            <StarDivider />
          </div>

          {/* Body grid */}
          <div style={{
            marginTop: 22, display: 'grid', gap: 14,
          }}>
            <ReceiptLine label="To" value={merchant.name} />
            <ReceiptLine label="Amount" value={<span style={{
              fontFamily: FR.serif, fontSize: 22, color: R.pearl, fontWeight: 500,
              letterSpacing: -0.4,
            }}>AED {amount}</span>} />
            <ReceiptLine label="Stamped to" value={<span style={{
              fontFamily: FR.serif, fontSize: 17, color: R.gold, fontWeight: 500, fontStyle: 'italic',
            }}>{winner}</span>} />
            <ReceiptLine label="Earned" value={<span style={{
              fontFamily: FR.mono, fontSize: 15, color: R.gold,
            }}>+ AED {earn}</span>} />
            <ReceiptLine label="Saved vs next best" value={<span style={{
              fontFamily: FR.mono, fontSize: 15, color: R.gold,
            }}>AED {saved}</span>} />
          </div>

          <div style={{ marginTop: 22 }}>
            <StarDivider dim={0.4} />
          </div>

          {/* Seal */}
          <div style={{ marginTop: 18, display: 'flex', justifyContent: 'center' }}>
            <div style={{ animation: 'r-stamp 800ms 200ms both' }}>
              <RoyalSeal size={86} motion={true} />
            </div>
          </div>

          <Eyebrow color={R.pearl4} ls={2.4} style={{ textAlign: 'center', marginTop: 14 }}>
            {dateStr.toUpperCase()} · {time.toUpperCase()}
          </Eyebrow>
        </div>
      </div>

      {/* Technical block — honest: the routing decision is real, the
          settlement is simulated (no live authorization in this demo). */}
      <div style={{ padding: '22px 22px 0' }}>
        <Eyebrow color={R.pearl4}>SIMULATED SETTLEMENT · NOT A REAL AUTHORIZATION</Eyebrow>
        <div style={{
          marginTop: 12, background: R.ink2, border: `0.5px solid ${R.hair}`,
          borderRadius: 14, overflow: 'hidden',
        }}>
          <TechRow label="Routing decision" value={<span style={{ color: R.gold }}>Real · live catalog engine</span>} />
          <TechRow label="Settlement" value="Simulated · demo only" />
          <TechRow label="Reference" value="sim_noir_demo" />
          <TechRow label="Processed" value={`${dateStr} at ${time}`} last />
        </div>
      </div>

      <div style={{ padding: '24px 22px 0', animation: 'r-rise-soft 600ms 600ms both' }}>
        <GoldButton onClick={onHome}>Done</GoldButton>
      </div>
    </div>
  );
}

function ReceiptLine({ label, value }) {
  return (
    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 12 }}>
      <Eyebrow size={9.5} ls={2.2} color={R.pearl3}>{label.toUpperCase()}</Eyebrow>
      <div style={{ textAlign: 'right' }}>
        {typeof value === 'string' ? <span style={{
          fontFamily: FR.serif, fontSize: 17, color: R.pearl, fontWeight: 500, fontStyle: 'italic',
        }}>{value}</span> : value}
      </div>
    </div>
  );
}

function TechRow({ label, value, last = false }) {
  return (
    <div style={{
      display: 'flex', justifyContent: 'space-between', alignItems: 'center',
      padding: '12px 16px',
      borderBottom: last ? 'none' : `0.5px solid ${R.hair}`,
    }}>
      <Eyebrow size={9.5} ls={2} color={R.pearl3}>{label}</Eyebrow>
      <span style={{
        fontFamily: FR.mono, fontSize: 12, color: R.pearl, letterSpacing: 0.4,
      }}>{value}</span>
    </div>
  );
}

// ─── Marketplace ───────────────────────────────────────────────────
const PARTNER_OFFERS = [
  { id: 'EK', brand: 'Emirates',    cat: 'FLIGHTS',  title: 'Book and save 5%',
    sub: '+ double Skywards miles',  pct: '5%',  color: '#a31a24' },
  { id: 'MB', brand: 'Marriott',    cat: 'HOTELS',   title: '10% off your next stay',
    sub: 'UAE-wide · Bonvoy linked',  pct: '10%', color: '#722030' },
  { id: 'VX', brand: 'VOX Cinemas', cat: 'CINEMA',   title: '25% off weekend tickets',
    sub: 'Friday + Saturday',         pct: '25%', color: '#c01818' },
  { id: 'T',  brand: 'Talabat',     cat: 'DINING',   title: 'AED 30 off next 3 orders',
    sub: 'No minimum spend',          pct: '15%', color: '#fa6541' },
  { id: 'AT', brand: 'Atlantis',    cat: 'STAYCATIONS', title: '20% off + 2 aquarium passes',
    sub: 'Sun–Wed, 2 nights min',     pct: '20%', color: '#1e6cb8' },
  { id: 'N',  brand: 'Noon',        cat: 'COMMERCE', title: '30 days free Express delivery',
    sub: 'Same-day on millions',      pct: 'FREE', pctSub: '30D', color: '#f5d020', textOnLight: true },
];

const CONVERT_DEALS = [
  { src: 'ENBD SKYWARDS',    dest: 'Emirates miles',  points: 8420,  rate: '1,000 pts ≈ 1,200 miles' },
  { src: 'ADCB TOUCHPOINTS', dest: 'AED cashback',    points: 12800, rate: '1,000 pts ≈ AED 25' },
  { src: 'MARRIOTT BONVOY',  dest: 'Marriott Bonvoy', points: 6450,  rate: '1,000 pts ≈ 800 Bonvoy' },
];

function Marketplace({ onBack, onOpenOffer, onConvert }) {
  return (
    <div className="r-screen" style={{
      minHeight: '100dvh', background: R.ink, color: R.pearl,
      paddingBottom: 120, position: 'relative',
    }}>
      <MashrabiyaBG opacity={0.04} />
      <TopBar onBack={onBack} center="SOUQ · السوق" />

      <div style={{ padding: '14px 22px 0', animation: 'r-rise 600ms both' }}>
        <Headline lead="Spend your" tail="points" tailPunct="." size={40} />
        <Headline lead="Skip" tail="retail." size={40} style={{ marginTop: -4 }} />
        <Bilingual
          en="Trade your loyalty points across programmes — or claim a partner offer."
          ar="بدّل نقاط ولائك بين البرامج، أو احصل على عرض شريك."
          size={14.5} style={{ marginTop: 14 }} />
      </div>

      {/* Partner offers */}
      <div style={{ padding: '22px 22px 0' }}>
        <Eyebrow color={R.pearl4}>PARTNER OFFERS · هذا الشهر</Eyebrow>
        <div style={{ marginTop: 12, display: 'flex', flexDirection: 'column', gap: 10 }}>
          {PARTNER_OFFERS.map((o, i) => (
            <button key={o.id} onClick={() => onOpenOffer(o)} style={{
              all: 'unset', cursor: 'pointer', display: 'flex', alignItems: 'center',
              gap: 12, padding: 12,
              background: R.ink2, border: `0.5px solid ${R.hair}`,
              borderRadius: 14, width: '100%',
              animation: `r-rise-soft 500ms ${100 + i*60}ms both`,
            }}>
              <BrandTile size={52} radius={12} domain={BRAND_DOMAIN[o.brand]}
                initial={o.id} bg={o.color} tx={o.textOnLight ? '#1c0c00' : '#fff'} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <Eyebrow size={9} ls={1.6} color={R.pearl3}>{o.brand.toUpperCase()} · {o.cat}</Eyebrow>
                <div style={{
                  fontFamily: FR.serif, fontSize: 16, color: R.pearl,
                  marginTop: 4, letterSpacing: -0.2, fontWeight: 500, fontStyle: 'italic',
                  lineHeight: 1.2,
                }}>{o.title}</div>
                <Eyebrow size={9} ls={1.4} color={R.gold} style={{ marginTop: 4, textTransform: 'none' }}>
                  {o.sub}
                </Eyebrow>
              </div>
              <div style={{
                padding: '8px 12px', borderRadius: 10,
                background: R.goldDim, color: R.gold,
                border: `0.5px solid ${R.gold}55`,
                fontFamily: FR.mono, fontSize: 18, fontWeight: 600, lineHeight: 1.1,
                textAlign: 'center',
              }}>
                <div>{o.pct}</div>
                <Eyebrow size={8} ls={1.2} color={R.gold} style={{ marginTop: 2 }}>
                  {o.pctSub || 'OFF'}
                </Eyebrow>
              </div>
            </button>
          ))}
        </div>
      </div>

      {/* Convert points */}
      <div style={{ padding: '32px 22px 0' }}>
        <Eyebrow color={R.pearl4}>CONVERT POINTS → VALUE · حوّل نقاطك</Eyebrow>
        <div style={{ marginTop: 12, display: 'flex', flexDirection: 'column', gap: 10 }}>
          {CONVERT_DEALS.map((d, i) => (
            <div key={i} style={{
              position: 'relative', padding: '16px',
              background: R.ink2, border: `0.5px solid ${R.hair}`, borderRadius: 14,
              animation: `r-rise-soft 500ms ${500 + i*80}ms both`,
            }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                <Eyebrow color={R.pearl4} ls={1.8} size={9}>{d.src}</Eyebrow>
                <div style={{ textAlign: 'right' }}>
                  <span style={{
                    fontFamily: FR.serif, fontSize: 24, color: R.pearl, fontWeight: 500,
                    letterSpacing: -0.4,
                  }}>{d.points.toLocaleString()}</span>
                  <Eyebrow size={9} ls={1.2} color={R.pearl3} style={{ marginTop: 0 }}>points</Eyebrow>
                </div>
              </div>
              <div style={{
                marginTop: 6, fontFamily: FR.serif, fontSize: 22, color: R.pearl,
                letterSpacing: -0.4, fontWeight: 500, fontStyle: 'italic',
              }}>
                → <span style={{ color: R.gold }}>{d.dest}</span>
              </div>
              <Eyebrow color={R.gold} size={9.5} ls={1.6} style={{ marginTop: 6, textTransform: 'none' }}>
                {d.rate}
              </Eyebrow>
              <div style={{ marginTop: 14 }}>
                <GoldButton onClick={() => onConvert(d)}
                  style={{ padding: '13px 18px', fontSize: 12, letterSpacing: 3 }}>
                  Convert
                </GoldButton>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// ─── Voucher modal ────────────────────────────────────────────────
function VoucherModal({ offer, onClose }) {
  const [copied, setCopied] = React.useState(false);
  const code = `SIKKA-${offer.id}${offer.pct.replace(/[^0-9A-Z]/g, '')}`;
  const copy = () => {
    try { navigator.clipboard?.writeText(code); } catch (_) {}
    setCopied(true);
    setTimeout(() => setCopied(false), 1600);
  };
  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 100,
      background: 'rgba(5,8,10,0.85)', backdropFilter: 'blur(12px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 24, animation: 'r-scrim-in 200ms both',
    }} onClick={onClose}>
      <div onClick={(e) => e.stopPropagation()} style={{
        position: 'relative', maxWidth: 320, width: '100%',
        background: R.pearl, color: R.goldInk, borderRadius: 20,
        padding: '24px 22px', animation: 'r-modal-in 380ms cubic-bezier(.2,.7,.2,1) both',
        boxShadow: '0 30px 60px rgba(0,0,0,0.6), 0 0 0 1px rgba(74,155,122,0.4)',
      }}>
        <FiligreeCorners color={R.goldD} inset={6} length={16} opacity={0.55} />
        {/* perforation notches */}
        <span style={{
          position: 'absolute', left: -8, top: '50%', width: 16, height: 16,
          background: R.ink, borderRadius: '50%', transform: 'translateY(-50%)',
        }} />
        <span style={{
          position: 'absolute', right: -8, top: '50%', width: 16, height: 16,
          background: R.ink, borderRadius: '50%', transform: 'translateY(-50%)',
        }} />

        <Eyebrow color={R.goldDk} ls={2.4} size={9.5}>{offer.brand.toUpperCase()}</Eyebrow>
        <div style={{
          fontFamily: FR.serif, fontSize: 22, color: R.goldInk, marginTop: 6,
          letterSpacing: -0.3, lineHeight: 1.15, fontWeight: 500, fontStyle: 'italic',
        }}>{offer.title}</div>
        <div style={{
          marginTop: 12, fontFamily: FR.serif, fontSize: 64, color: R.goldInk,
          letterSpacing: 64 * -0.014, fontWeight: 500, lineHeight: 1,
          display: 'flex', alignItems: 'baseline', gap: 6,
        }}>
          {offer.pct} <Eyebrow color={R.goldDk} size={11} ls={2.5}>OFF</Eyebrow>
        </div>

        <div style={{ margin: '20px -22px', borderTop: `1.5px dashed ${R.goldDk}66` }} />

        <Eyebrow color={R.goldDk} ls={2.4} size={9.5} style={{ textAlign: 'center' }}>
          SHOW AT CHECKOUT
        </Eyebrow>
        <div style={{
          margin: '10px 0 0', padding: '14px 14px',
          background: R.goldDim, borderRadius: 12,
          fontFamily: FR.mono, fontSize: 19, letterSpacing: 3, color: R.goldInk,
          textAlign: 'center', fontWeight: 500,
        }}>{code}</div>

        <Sub style={{
          marginTop: 14, fontSize: 12, color: 'rgba(6,18,14,0.55)',
          fontFamily: FR.mono, lineHeight: 1.5, textAlign: 'center', letterSpacing: 0.2,
        }}>
          Valid for bookings made through {offer.brand.toLowerCase()}.com before 30 Jun. One-time use per account.
        </Sub>

        <button onClick={copy} style={{
          width: '100%', marginTop: 14, padding: '13px 16px',
          background: R.goldInk, color: R.gold, border: 'none', borderRadius: 14,
          fontFamily: FR.display, fontSize: 12, letterSpacing: 3.4, fontWeight: 600,
          cursor: 'pointer', textTransform: 'uppercase',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 7,
        }}>
          {copied && (
            <svg width="12" height="12" viewBox="0 0 12 12" fill="none" style={{ flexShrink: 0 }}>
              <path d="M2 6l3 3 5-6" stroke="currentColor" strokeWidth="1.8"
                strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          )}
          {copied ? 'Copied' : 'Copy code'}
        </button>

        <button onClick={onClose} style={{
          width: '100%', marginTop: 6, padding: '10px 16px',
          background: 'transparent', color: R.goldDk, border: 'none',
          fontFamily: FR.mono, fontSize: 10, letterSpacing: 2, cursor: 'pointer',
          textTransform: 'uppercase',
        }}>Close</button>
      </div>
    </div>
  );
}

// ─── Convert overlay ──────────────────────────────────────────────
function ConvertingOverlay({ deal, onDone }) {
  const [stage, setStage] = React.useState('loading');
  React.useEffect(() => {
    const t = setTimeout(() => setStage('done'), 2200);
    return () => clearTimeout(t);
  }, []);
  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 100,
      background: 'rgba(5,8,10,0.94)', backdropFilter: 'blur(14px)',
      display: 'flex', flexDirection: 'column',
      alignItems: 'center', justifyContent: 'center', padding: 24,
      animation: 'r-scrim-in 250ms both', color: R.pearl,
    }}>
      <MashrabiyaBG opacity={0.06} />
      <div style={{ textAlign: 'center', animation: 'r-rise 500ms both', position: 'relative' }}>
        <Eyebrow color={R.pearl4} ls={3}>{deal.src}</Eyebrow>
        <div style={{
          fontFamily: FR.serif, fontSize: 28, letterSpacing: -0.6,
          color: R.pearl, fontWeight: 500, marginTop: 8, fontStyle: 'italic',
        }}>1,000 points</div>
        <div style={{
          margin: '20px 0', display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <div style={{
            animation: stage === 'done' ? 'r-pop 500ms both' : 'r-blink 1s ease-in-out infinite',
          }}>
            <CoinMark size={64} />
          </div>
        </div>
        <div style={{
          fontFamily: FR.serif, fontSize: 28, letterSpacing: -0.6,
          color: R.gold, fontWeight: 500, fontStyle: 'italic',
        }}>{deal.dest}</div>

        <div style={{ marginTop: 30, width: 240, marginInline: 'auto' }}>
          <ProgressBar pct={stage === 'done' ? 100 : 60} height={3} />
        </div>

        <Eyebrow color={R.gold} style={{ marginTop: 16 }}>
          {stage === 'done' ? 'COMPLETE · تم' : 'CONVERTING…'}
        </Eyebrow>

        {stage === 'done' && (
          <div style={{ marginTop: 26, animation: 'r-pop 400ms both' }}>
            <GoldButton onClick={onDone} full={false}
              style={{ padding: '12px 30px', fontSize: 12 }}>Done</GoldButton>
          </div>
        )}
      </div>
    </div>
  );
}

// ─── Pay bills ────────────────────────────────────────────────────
function PayBillsScreen({ onBack, onPaySomething }) {
  return (
    <div className="r-screen" style={{
      minHeight: '100dvh', background: R.ink, color: R.pearl,
      paddingBottom: 120, position: 'relative',
    }}>
      <MashrabiyaBG opacity={0.04} />
      <TopBar onBack={onBack} center="BILLS · فواتير" />

      <div style={{ padding: '14px 22px 0', animation: 'r-rise 600ms both' }}>
        <Headline lead="Settle your" tail="dues" tailPunct=" with grace." size={36} />
        <Bilingual
          en="Sikka routes utilities through your best card, and tells you which balance to clear first."
          ar="سِكَّة يوجّه الفواتير عبر أفضل بطاقاتك، ويرشدك إلى الرصيد الذي يستحق التسديد أولاً."
          size={14.5} style={{ marginTop: 14 }} />
      </div>

      {/* Strategic banner */}
      <div style={{ padding: '20px 22px 0', animation: 'r-rise-soft 600ms 100ms both' }}>
        <div style={{
          position: 'relative', padding: '16px 18px',
          background: R.velvet, border: `0.5px solid ${R.gold}66`, borderRadius: 16,
          display: 'flex', gap: 12, alignItems: 'flex-start', overflow: 'hidden',
        }}>
          <FiligreeCorners inset={6} length={14} opacity={0.5} />
          <CoinMark size={22} bare color={R.gold} style={{ flexShrink: 0 }} />
          <div style={{ flex: 1 }}>
            <div style={{
              fontFamily: FR.serif, fontSize: 18, color: R.pearl,
              letterSpacing: -0.3, fontWeight: 500, fontStyle: 'italic',
            }}>Pay ADCB first this cycle</div>
            <Sub style={{ marginTop: 6, fontSize: 13.5 }}>
              Saves <span style={{ color: R.gold, fontFamily: FR.mono, fontSize: 12.5 }}>AED 47</span> in
              {' '}next-cycle interest vs paying FAB first.
            </Sub>
            <Eyebrow size={9} ls={1.4} color={R.pearl4} style={{ marginTop: 8, textTransform: 'none' }}>
              Avalanche method · assumes 2.95% / month APR on rolled balance
            </Eyebrow>
          </div>
        </div>
      </div>

      {/* CC bills */}
      <div style={{ padding: '14px 22px 0', display: 'flex', flexDirection: 'column', gap: 12 }}>
        <CreditCardBill bank="adcb" label="ADCB TouchPoints" last4="6242" due="in 3 days"
          statement="2,480.00" min="125.00" urgent
          onPayFull={() => onPaySomething('adcb-full')}
          onPayMin={() => onPaySomething('adcb-min')} />
        <CreditCardBill bank="fab" label="FAB Cashback" last4="2891" due="in 12 days"
          statement="892.50" min="50.00"
          onPayFull={() => onPaySomething('fab-full')}
          onPayMin={() => onPaySomething('fab-min')} />
      </div>

      {/* Utilities */}
      <div style={{ padding: '28px 22px 0' }}>
        <Eyebrow color={R.pearl4}>UTILITIES · مرافق</Eyebrow>
        <div style={{
          marginTop: 12, background: R.ink2,
          border: `0.5px solid ${R.hair}`, borderRadius: 14,
          overflow: 'hidden',
        }}>
          <BillRow id="dewa" label="DEWA" sub="DUBAI ELECTRICITY & WATER" bg="#1a5a8a" tx="#fff"
            onClick={() => onPaySomething('dewa')} />
          <BillRow id="addc" label="ADDC" sub="ABU DHABI DISTRIBUTION" bg="#a82a2a" tx="#fff"
            onClick={() => onPaySomething('addc')} />
          <BillRow id="etisalat" label="Etisalat" sub="MOBILE + HOME INTERNET" bg="#0a6c4e" tx="#fff"
            onClick={() => onPaySomething('etisalat')} last />
        </div>
      </div>
    </div>
  );
}

function CreditCardBill({ bank, label, last4, due, statement, min, urgent, onPayFull, onPayMin }) {
  return (
    <div style={{
      position: 'relative', padding: '16px',
      background: R.ink2, border: `0.5px solid ${urgent ? R.gold + '66' : R.hair}`,
      borderRadius: 16, overflow: 'hidden',
    }}>
      {urgent && <FiligreeCorners inset={4} length={12} opacity={0.5} />}
      <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        <BankAvatar id={bank} size={44} text={bank.toUpperCase().slice(0, 2)} />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{
            fontFamily: FR.serif, fontSize: 18, color: R.pearl,
            letterSpacing: -0.3, fontWeight: 500, fontStyle: 'italic',
          }}>{label}</div>
          <Eyebrow size={9} ls={1.6} color={R.pearl3} style={{ marginTop: 3 }}>
            ····{last4} · DUE {due.toUpperCase()}
          </Eyebrow>
        </div>
        {urgent ? (
          <div style={{
            width: 26, height: 26, borderRadius: '50%',
            background: R.goldDim, color: R.gold,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontFamily: FR.serif, fontWeight: 700, fontSize: 15,
            border: `0.5px solid ${R.gold}55`,
          }}>!</div>
        ) : (
          <div style={{
            width: 26, height: 26, borderRadius: '50%',
            background: R.emeraldD, color: R.emerald,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>
            <svg width="12" height="12" viewBox="0 0 12 12" fill="none">
              <path d="M2 6l3 3 5-6" stroke="currentColor" strokeWidth="1.8"
                strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          </div>
        )}
      </div>

      <div style={{ marginTop: 14, display: 'flex', gap: 24 }}>
        <div>
          <Eyebrow size={9} ls={1.6} color={R.pearl4}>STATEMENT</Eyebrow>
          <div style={{
            fontFamily: FR.mono, fontSize: 19, color: R.pearl,
            marginTop: 4, letterSpacing: 0.5,
          }}>AED {statement}</div>
        </div>
        <div>
          <Eyebrow size={9} ls={1.6} color={R.pearl4}>MINIMUM</Eyebrow>
          <div style={{
            fontFamily: FR.mono, fontSize: 19, color: R.gold,
            marginTop: 4, letterSpacing: 0.5,
          }}>AED {min}</div>
        </div>
      </div>

      <div style={{ marginTop: 14, display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 8 }}>
        <GoldButton onClick={onPayFull}
          style={{ padding: '13px 14px', fontSize: 11, letterSpacing: 2.6 }}>
          Pay AED {statement} in full
        </GoldButton>
        <GhostButton onClick={onPayMin}
          style={{ padding: '13px 14px', fontSize: 11, letterSpacing: 2.6 }}>Pay min</GhostButton>
      </div>
    </div>
  );
}

function BillRow({ id, label, sub, bg, tx, onClick, last = false }) {
  return (
    <button onClick={onClick} style={{
      all: 'unset', cursor: 'pointer', display: 'flex', alignItems: 'center',
      width: '100%', gap: 14, padding: '14px 16px',
      borderBottom: last ? 'none' : `0.5px solid ${R.hair}`,
    }}>
      <div style={{
        width: 38, height: 38, borderRadius: 10,
        background: bg, color: tx,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontFamily: FR.mono, fontSize: 12, fontWeight: 700, letterSpacing: 0.5,
        boxShadow: 'inset 0 0 0 0.5px rgba(74,155,122,0.20)',
      }}>{id.toUpperCase().slice(0, 2)}</div>
      <div style={{ flex: 1 }}>
        <div style={{
          fontFamily: FR.serif, fontSize: 17, color: R.pearl,
          letterSpacing: -0.2, fontWeight: 500, fontStyle: 'italic',
        }}>{label}</div>
        <Eyebrow size={9} ls={1.6} color={R.pearl3} style={{ marginTop: 3 }}>{sub}</Eyebrow>
      </div>
      <svg width="16" height="16" viewBox="0 0 20 20" fill="none" style={{ color: R.gold, flexShrink: 0 }}>
        <path d="M7 4L13 10L7 16" stroke="currentColor" strokeWidth="1.6"
          strokeLinecap="round" strokeLinejoin="round" />
      </svg>
    </button>
  );
}

Object.assign(window, {
  PayMerchantPicker, PayAmountKeypad, HoldToPay, PayRoutingLive, PayReceipt,
  Marketplace, VoucherModal, ConvertingOverlay, PayBillsScreen,
});
