// ViSdkSheet — the entire Vi-powered SDK surface lives in this single bottom sheet.
// Internal step machine: verifying → consent → (dpdp) → done.
// The partner app stays mounted as the base layer; the sheet morphs in place.

// ─────────────────────────────────────────────────────────────
// Data model: purposes → attributes
// ─────────────────────────────────────────────────────────────
const CONSENT_MODEL = [
  {
    id: 'identity',
    title: 'Account identity',
    purpose: 'Create and secure your account.',
    retention: 'While account is active',
    required: true,
    attrs: [
      { id: 'phone', label: 'Mobile number', sub: 'Network-verified', required: true, defaultOn: true },
    ],
  },
  {
    id: 'personalize',
    title: 'Personalisation',
    purpose: 'Tailor your feed and recommendations.',
    retention: '24 months',
    attrs: [
      { id: 'name',   label: 'Full name',     defaultOn: false },
      { id: 'gender', label: 'Gender',        defaultOn: false },
      { id: 'dob',    label: 'Date of birth', defaultOn: false },
    ],
  },
  {
    id: 'delivery',
    title: 'Faster checkout',
    purpose: 'Pre-fill delivery & billing at checkout.',
    retention: '24 months',
    attrs: [
      { id: 'email',   label: 'Email address',    defaultOn: false },
      { id: 'address', label: 'Billing address',  defaultOn: false },
    ],
  },
  {
    id: 'security',
    title: 'Fraud & security',
    purpose: 'Detect fraud and protect your account.',
    retention: '12 months',
    attrs: [
      { id: 'device',   label: 'Device info',     sub: 'Model, OS, IMEI hash', defaultOn: false },
      { id: 'location', label: 'Coarse location', sub: 'Cell-tower level',     defaultOn: false },
    ],
  },
];

const ATTR_LIST = CONSENT_MODEL.flatMap((p) => p.attrs.map((a) => ({ ...a, purposeId: p.id })));

// ─────────────────────────────────────────────────────────────
// Toggle (with locked-on state for required attributes)
// ─────────────────────────────────────────────────────────────
const Toggle = ({ on, onChange, disabled }) => (
  <button
    onClick={() => !disabled && onChange(!on)}
    disabled={disabled}
    style={{
      width: 38, height: 22, borderRadius: 100,
      background: disabled ? (on ? VI.ink : VI.lineStrong) : (on ? VI.ink : '#d4cebc'),
      border: 'none', padding: 0, cursor: disabled ? 'not-allowed' : 'pointer',
      position: 'relative', flexShrink: 0,
      transition: 'background .18s ease',
      opacity: disabled ? 0.85 : 1,
    }}
    aria-label={on ? 'On' : 'Off'}
  >
    <div style={{
      position: 'absolute', top: 2, left: on ? 18 : 2,
      width: 18, height: 18, borderRadius: '50%',
      background: '#fff',
      transition: 'left .18s cubic-bezier(.2,.7,.2,1)',
      boxShadow: '0 1px 3px rgba(0,0,0,0.2)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
    }}>
      {disabled && on && (
        <svg width="9" height="9" viewBox="0 0 9 9" fill="none">
          <rect x="2" y="4" width="5" height="4" rx="0.7" stroke={VI.ink} strokeWidth="1" fill="none"/>
          <path d="M3 4 V3 a1.5 1.5 0 0 1 3 0 V4" stroke={VI.ink} strokeWidth="1" fill="none" strokeLinecap="round"/>
        </svg>
      )}
    </div>
  </button>
);

// ─────────────────────────────────────────────────────────────
// Step 1 — Verifying (network handshake, fetches MSISDN)
// ─────────────────────────────────────────────────────────────
const VerifyingPanel = ({ onVerified, lang }) => {
  const [phase, setPhase] = React.useState(0);
  React.useEffect(() => {
    const t1 = setTimeout(() => setPhase(1), 1600);
    const t2 = setTimeout(() => { if (onVerified) onVerified(); }, 2400);
    return () => { clearTimeout(t1); clearTimeout(t2); };
  }, []);

  const phases = lang === 'hi'
    ? [`${VI.name} से जुड़ रहे हैं`, 'नंबर सत्यापित']
    : [`Connecting with ${VI.name}`, 'Number verified'];

  const progressPct = phase === 0 ? 55 : 100;

  return (
    <div style={{
      padding: '8px 24px 28px', display: 'flex', flexDirection: 'column',
      alignItems: 'center', textAlign: 'center', gap: 22,
    }}>
      {/* Hero: rotating gradient ring around Vi mark, with SIM glyph */}
      <div style={{ position: 'relative', width: 132, height: 132 }}>
        {/* Background ring */}
        <svg width="132" height="132" viewBox="0 0 132 132" style={{ position: 'absolute', inset: 0 }}>
          <circle cx="66" cy="66" r="58" fill="none"
            stroke={VI.line} strokeWidth="3" />
        </svg>
        {/* Animated arc */}
        <svg width="132" height="132" viewBox="0 0 132 132"
          style={{
            position: 'absolute', inset: 0,
            animation: phase < 1 ? 'rotate 1.5s linear infinite' : 'none',
            transformOrigin: '66px 66px',
          }}>
          <defs>
            <linearGradient id="vi-arc" x1="0" y1="0" x2="1" y2="1">
              <stop offset="0" stopColor={VI.red} />
              <stop offset="1" stopColor={VI.yellow} />
            </linearGradient>
          </defs>
          <circle cx="66" cy="66" r="58" fill="none"
            stroke={phase < 1 ? 'url(#vi-arc)' : VI.green}
            strokeWidth={phase < 1 ? 3.5 : 5}
            strokeDasharray={phase < 1 ? '120 250' : '364 0'}
            strokeLinecap="round" />
        </svg>
        {/* Center: SIM card / check */}
        <div style={{
          position: 'absolute', inset: 22, borderRadius: '50%',
          background: '#fff',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          boxShadow: phase < 1
            ? 'inset 0 0 0 1px ' + VI.line
            : 'inset 0 0 0 1px rgba(15,138,95,0.25)',
        }}>
          {phase < 1 ? (
            // SIM card glyph
            <svg width="42" height="48" viewBox="0 0 42 48" fill="none">
              <path d="M5 4 H29 L37 12 V44 a2 2 0 0 1 -2 2 H7 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 Z"
                stroke={VI.ink} strokeWidth="1.6" fill="none" strokeLinejoin="round" />
              {/* gold chip */}
              <rect x="11" y="18" width="20" height="16" rx="2.5" fill={VI.gold} />
              <line x1="17" y1="18" x2="17" y2="34" stroke="#a87f00" strokeWidth="0.9" />
              <line x1="25" y1="18" x2="25" y2="34" stroke="#a87f00" strokeWidth="0.9" />
              <line x1="11" y1="26" x2="31" y2="26" stroke="#a87f00" strokeWidth="0.9" />
            </svg>
          ) : (
            <svg width="46" height="46" viewBox="0 0 46 46" fill="none">
              <circle cx="23" cy="23" r="21" fill={VI.green} />
              <path d="M14 23 L20 29 L32 17" stroke="#fff" strokeWidth="3.2"
                strokeLinecap="round" strokeLinejoin="round" fill="none" />
            </svg>
          )}
        </div>
      </div>

      {/* Status text */}
      <div>
        <div style={{
          fontSize: 18, fontWeight: 600, letterSpacing: -0.3, color: VI.ink,
          minHeight: 24,
        }}>{phases[phase]}</div>
        <div style={{
          marginTop: 6, fontSize: 12, color: VI.soft, lineHeight: 1.5,
        }}>
          {lang === 'hi' ? 'सुरक्षित सेल्युलर चैनल पर' : 'Over a secure cellular channel'}
        </div>
      </div>

      {/* Progress bar */}
      <div style={{
        width: '100%', height: 4, background: VI.line, borderRadius: 4, overflow: 'hidden',
      }}>
        <div style={{
          height: '100%', width: `${progressPct}%`,
          background: phase < 1
            ? `linear-gradient(90deg, ${VI.red}, ${VI.yellow})`
            : VI.green,
          borderRadius: 4,
          transition: 'width .5s ease, background .3s ease',
        }} />
      </div>
    </div>
  );
};

// ─────────────────────────────────────────────────────────────
// Step 2 — Consent (verified phone + per-attribute toggles, all in one)
// ─────────────────────────────────────────────────────────────
// little uppercase tag pill (Required / Optional)
const ConsentTag = ({ text, tone }) => (
  <span style={{
    fontFamily: "'JetBrains Mono', monospace", fontSize: 9,
    letterSpacing: 0.5, textTransform: 'uppercase', fontWeight: 600,
    padding: '2px 7px', borderRadius: 100, whiteSpace: 'nowrap',
    background: tone === 'req' ? VI.ink : '#fff',
    color: tone === 'req' ? '#fff' : VI.soft,
    border: tone === 'req' ? 'none' : `1px solid ${VI.lineStrong}`,
  }}>{text}</span>
);

const ConsentPanel = ({ phone, partnerName, selections, onToggle, onContinue, onShareOnlyRequired, onSeeDpdp, lang }) => {
  const t = lang === 'hi' ? {
    title: 'डेटा साझा करने की सहमति',
    sourceCap: 'स्रोत', viaCap: 'एग्रीगेटर', toCap: 'प्राप्तकर्ता',
    role: 'डेटा फ़िड्यूशियरी',
    sub: `${VI.name} नीचे आपकी अनुमति वाली सत्यापित जानकारी, OTPless के ज़रिए, ${partnerName} को भेजेगा।`,
    via: `${VI.name} द्वारा सत्यापित`,
    required: 'आवश्यक', optional: 'वैकल्पिक', keep: 'संग्रह',
    declare: `नीचे टैप करके आप ${VI.name} को निर्देश देते हैं कि चुनी गई जानकारी OTPless के माध्यम से ${partnerName} को साझा करे, और ${partnerName} को सिर्फ़ दिखाए गए उद्देश्यों के लिए उसे संसाधित करने की सहमति देते हैं। यह सहमति स्वतंत्र, विशिष्ट और कभी भी वापस लेने योग्य है।`,
    cta: 'सहमत हूँ, साझा करें', onlyReq: 'सिर्फ़ आवश्यक साझा करें',
    withdraw: `${VI.name} ऐप → जुड़े ऐप्स में कभी भी वापस लें। कुछ सुविधाएँ बंद हो सकती हैं।`,
    dpdp: 'पूर्ण सूचना और आपके अधिकार',
  } : {
    title: 'Data sharing consent',
    sourceCap: 'Source', viaCap: 'Aggregator', toCap: 'Recipient',
    role: 'Data Fiduciary',
    sub: `${VI.name} will share the verified details you allow below with ${partnerName}, routed securely through OTPless.`,
    via: `Verified by ${VI.name}`,
    required: 'Required', optional: 'Optional', keep: 'Kept',
    declare: `By tapping below you direct ${VI.name} to share the data you’ve enabled with ${partnerName} through OTPless, and consent to ${partnerName} processing it only for the purposes shown. This consent is free, specific and withdrawable anytime.`,
    cta: 'Agree & share', onlyReq: 'Share only what’s required',
    withdraw: `Withdraw anytime in the ${VI.name} app → Connected apps. Some features may stop working.`,
    dpdp: 'Full notice & your rights',
  };
  return (
    <div style={{ display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0 }}>
      <div style={{ padding: '0 22px 10px', flexShrink: 0 }}>
        {/* Title */}
        <h2 style={{
          margin: 0, fontSize: 19, fontWeight: 600, letterSpacing: -0.4, lineHeight: 1.2,
        }}>{t.title}</h2>
        <p style={{ margin: '7px 0 10px', fontSize: 12.5, color: VI.body, lineHeight: 1.5 }}>{t.sub}</p>

        {/* Data-flow strip: telco (source) → OTPless (aggregator) → partner (Data Fiduciary) */}
        <div style={{ display: 'flex', alignItems: 'center', marginBottom: 12 }}>
          {[
            { name: VI.name, cap: t.sourceCap },
            { name: 'OTPless', cap: t.viaCap },
            { name: partnerName, cap: t.role },
          ].map((n, i, arr) => (
            <React.Fragment key={i}>
              <div style={{
                flex: 1, minWidth: 0, padding: '8px 4px', borderRadius: 10,
                background: VI.paper2, border: `1px solid ${VI.line}`, textAlign: 'center',
              }}>
                <div style={{
                  fontSize: 12.5, fontWeight: 700, color: VI.ink,
                  whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                }}>{n.name}</div>
                <div style={{
                  fontFamily: "'JetBrains Mono', monospace", fontSize: 8,
                  letterSpacing: 0.3, textTransform: 'uppercase', color: VI.soft, marginTop: 2,
                }}>{n.cap}</div>
              </div>
              {i < arr.length - 1 && (
                <div style={{ flexShrink: 0, padding: '0 4px', color: VI.soft, display: 'flex' }}>
                  <svg width="13" height="13" viewBox="0 0 12 12">
                    <path d="M2 6 H9 M6.5 3 L9.5 6 L6.5 9" stroke="currentColor" strokeWidth="1.4"
                      fill="none" strokeLinecap="round" strokeLinejoin="round" />
                  </svg>
                </div>
              )}
            </React.Fragment>
          ))}
        </div>

        {/* Verified phone card — REQUIRED identity (the anchor the telco verifies & shares) */}
        <div style={{
          padding: '12px 14px', borderRadius: 12,
          background: VI.paper2, border: `1px solid ${VI.line}`,
          display: 'flex', alignItems: 'center', gap: 12,
        }}>
          <div style={{
            width: 24, height: 24, borderRadius: '50%',
            background: VI.green, color: '#fff', flexShrink: 0,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>
            <svg width="12" height="12" viewBox="0 0 12 12"><path d="M2 6 L5 9 L10 4"
              stroke="#fff" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{
              fontFamily: "'JetBrains Mono', monospace", fontSize: 14,
              fontWeight: 600, color: VI.ink, letterSpacing: 0.2,
            }}>{phone}</div>
            <div style={{
              fontSize: 10, color: VI.soft, marginTop: 1,
              fontFamily: "'JetBrains Mono', monospace", letterSpacing: 0.4, textTransform: 'uppercase',
            }}>{t.via}</div>
          </div>
          <ConsentTag text={t.required} tone="req" />
        </div>
      </div>

      <div style={{ flex: 1, overflow: 'auto', padding: '10px 22px 14px' }}>
        {CONSENT_MODEL.filter((p) => p.id !== 'identity').map((p) => (
          <div key={p.id} style={{
            marginBottom: 10, padding: '12px 14px',
            background: '#fff', borderRadius: 12,
            border: `1px solid ${VI.line}`,
          }}>
            {/* Purpose header: name + why + retention/optional meta */}
            <div style={{ paddingBottom: 9, borderBottom: `1px solid ${VI.line}` }}>
              <div style={{ fontSize: 14, fontWeight: 600, color: VI.ink, letterSpacing: -0.2 }}>
                {p.title}
              </div>
              <div style={{ fontSize: 11.5, color: VI.soft, marginTop: 2, lineHeight: 1.4 }}>
                {p.purpose}
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 7, marginTop: 8 }}>
                <ConsentTag text={t.optional} />
                <span style={{
                  fontFamily: "'JetBrains Mono', monospace", fontSize: 10,
                  letterSpacing: 0.3, textTransform: 'uppercase', color: VI.soft,
                }}>{t.keep} · {p.retention}</span>
              </div>
            </div>

            {p.attrs.map((a, i) => (
              <div key={a.id} style={{
                display: 'flex', alignItems: 'center', gap: 12,
                padding: '9px 0 7px',
                borderTop: i === 0 ? 'none' : `1px solid ${VI.line}`,
              }}>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 13.5, fontWeight: 500, color: VI.ink }}>{a.label}</div>
                  {a.sub && <div style={{ fontSize: 11, color: VI.soft, marginTop: 2 }}>{a.sub}</div>}
                </div>
                <Toggle on={!!selections[a.id]} onChange={(v) => onToggle(a.id, v)} disabled={a.required} />
              </div>
            ))}
          </div>
        ))}

        <button onClick={onSeeDpdp} style={{
          width: '100%', textAlign: 'left', cursor: 'pointer',
          background: VI.paper2, border: `1px solid ${VI.line}`, borderRadius: 10,
          padding: '11px 12px', display: 'flex', alignItems: 'center', gap: 10,
          fontFamily: 'inherit', color: VI.ink,
        }}>
          <DPDPShield size={15} color={VI.green} />
          <span style={{ fontSize: 12.5, fontWeight: 600, flex: 1 }}>{t.dpdp}</span>
          <svg width="12" height="12" viewBox="0 0 14 14" fill="none">
            <path d="M5 3 L9 7 L5 11" stroke={VI.soft} strokeWidth="1.6"
              strokeLinecap="round" strokeLinejoin="round" fill="none" />
          </svg>
        </button>
      </div>

      <div style={{
        padding: '11px 22px 8px', background: '#fff',
        borderTop: `1px solid ${VI.line}`, flexShrink: 0,
      }}>
        {/* Affirmative consent declaration */}
        <p style={{
          margin: '0 0 9px', fontSize: 10.5, color: VI.soft, lineHeight: 1.45,
        }}>{t.declare}</p>
        <button onClick={onContinue} style={{
          width: '100%', padding: '13px 18px', borderRadius: 12,
          background: VI.red, color: '#fff', border: 'none',
          fontFamily: "'DM Sans', system-ui", fontSize: 14.5, fontWeight: 600,
          cursor: 'pointer',
        }}>{t.cta}</button>
      </div>
    </div>
  );
};

// ─────────────────────────────────────────────────────────────
// Step 3 — DPDP notice (push view inside sheet)
// ─────────────────────────────────────────────────────────────
const DpdpPanel = ({ partnerName, onBack, lang }) => {
  const t = lang === 'hi' ? { back: 'वापस', title: 'सूचना और अधिकार', close: 'समझ गया' }
                          : { back: 'Back', title: 'Notice & your rights', close: 'Got it' };
  const sections = lang === 'hi' ? [
    { label: 'आपका डेटा कौन संभालता है', body: `${VI.name} (स्रोत) इसे साझा करता है · OTPless (एग्रीगेटर/प्रोसेसर) इसे भेजता है · ${partnerName} (डेटा फ़िड्यूशियरी) उद्देश्य तय कर इसे संसाधित करता है।` },
    { label: 'उद्देश्य-सीमित', body: 'हर श्रेणी सिर्फ़ अपने बताए उद्देश्य के लिए। किसी और काम के लिए नई सहमति चाहिए।' },
    { label: 'अनुमति वापस लें', body: `${VI.name} ऐप → जुड़े ऐप्स → ${partnerName}. ${partnerName} व OTPless उचित समय में प्रोसेसिंग रोक देंगे; कुछ सुविधाएँ बंद हो सकती हैं।` },
    { label: 'आपके अधिकार', body: 'देखें, ठीक करें, पूरा करें, मिटाएँ, या nomination करें।' },
    { label: 'डेटा मिटाना', body: 'उद्देश्य पूरा होने या सहमति वापस लेने पर डेटा मिटा दिया जाता है, जब तक कानून रखना ज़रूरी न करे।' },
    { label: 'सहमति रसीद', body: `हस्ताक्षरित रिकॉर्ड ${VI.name} खाते में सेव — जुड़े ऐप्स में देखें या वापस लें।` },
    { label: 'भारत में प्रोसेस', body: 'आपका डेटा भारत में ही संसाधित होता है।' },
    { label: 'सवाल? डेटा संरक्षण अधिकारी', body: `${partnerName} DPO · dpo@bazaar.in` },
    { label: 'शिकायत अधिकारी', body: `${VI.grievance} · 7 दिन में जवाब।` },
    { label: 'डेटा संरक्षण बोर्ड', body: 'हल न हो तो भारत के डेटा संरक्षण बोर्ड में शिकायत करें।' },
  ] : [
    { label: 'Who handles your data', body: `${VI.name} (source) shares it · OTPless (aggregator / processor) transmits it · ${partnerName} (Data Fiduciary) sets the purposes and processes it.` },
    { label: 'Purpose-bound', body: 'Each category is used only for its stated purpose. Anything else needs fresh consent.' },
    { label: 'Withdraw any time', body: `${VI.name} app → Connected apps → ${partnerName}. ${partnerName} and OTPless stop processing within a reasonable time; some features may stop.` },
    { label: 'Your rights', body: 'Access, correct, complete, erase or nominate someone for your data.' },
    { label: 'Erasure', body: 'Data is erased once its purpose is met or you withdraw consent, unless a law requires it to be kept.' },
    { label: 'Consent receipt', body: `A signed record is kept in your ${VI.name} account — review or revoke under Connected apps.` },
    { label: 'Processed in India', body: 'Your data is processed within India.' },
    { label: 'Questions? Data Protection Officer', body: `${partnerName} DPO · dpo@bazaar.in` },
    { label: 'Grievance Officer', body: `${VI.grievance} · response in 7 days.` },
    { label: 'Data Protection Board', body: 'Unresolved? Escalate to the Data Protection Board of India.' },
  ];
  return (
    <div style={{ display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0 }}>
      <div style={{
        padding: '0 22px 8px', display: 'flex', alignItems: 'center', gap: 10, flexShrink: 0,
      }}>
        <button onClick={onBack} style={{
          background: 'transparent', border: 'none', cursor: 'pointer', padding: 4, marginLeft: -4,
        }} aria-label={t.back}>
          <svg width="20" height="20" viewBox="0 0 20 20" fill="none">
            <path d="M12 4 L6 10 L12 16" stroke={VI.ink} strokeWidth="1.8" fill="none"
              strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        </button>
        <DPDPShield size={16} />
        <div style={{ fontSize: 16, fontWeight: 600, color: VI.ink, letterSpacing: -0.3 }}>{t.title}</div>
      </div>

      <div style={{ flex: 1, overflow: 'auto', padding: '0 22px 12px' }}>
        {sections.map((s, i) => (
          <div key={i} style={{ padding: '12px 0', borderTop: `1px solid ${VI.line}` }}>
            <div style={{
              fontFamily: "'JetBrains Mono', monospace", fontSize: 10,
              letterSpacing: 0.7, textTransform: 'uppercase', color: VI.soft, marginBottom: 4,
            }}>{s.label}</div>
            <div style={{ fontSize: 12.5, color: VI.ink, lineHeight: 1.55 }}>{s.body}</div>
          </div>
        ))}
      </div>

      <div style={{
        padding: '12px 22px 8px', borderTop: `1px solid ${VI.line}`,
        background: '#fff', flexShrink: 0,
      }}>
        <button onClick={onBack} style={{
          width: '100%', padding: '13px 18px', borderRadius: 12,
          background: VI.ink, color: '#fff', border: 'none',
          fontFamily: 'inherit', fontSize: 14, fontWeight: 600, cursor: 'pointer',
        }}>{t.close}</button>
      </div>
    </div>
  );
};

// ─────────────────────────────────────────────────────────────
// Step 4 — Done (brief success state before sheet dismisses)
// ─────────────────────────────────────────────────────────────
const DonePanel = ({ partnerName, lang }) => {
  const t = lang === 'hi'
    ? { title: 'साइन इन हो गए', sub: `${partnerName} में ले जा रहे हैं…` }
    : { title: 'Signed in', sub: `Returning to ${partnerName}…` };
  return (
    <div style={{
      padding: '8px 22px 28px', display: 'flex', flexDirection: 'column',
      alignItems: 'center', textAlign: 'center', gap: 18,
    }}>
      <div style={{
        width: 76, height: 76, borderRadius: '50%',
        background: VI.green,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        <svg width="34" height="34" viewBox="0 0 44 44" fill="none">
          <path d="M14 22 L20 28 L31 16" stroke="#fff" strokeWidth="3.2"
            strokeLinecap="round" strokeLinejoin="round" fill="none" />
        </svg>
      </div>
      <div>
        <div style={{ fontSize: 18, fontWeight: 600, color: VI.ink, letterSpacing: -0.3 }}>{t.title}</div>
        <div style={{ fontSize: 12.5, color: VI.body, marginTop: 4 }}>{t.sub}</div>
      </div>
    </div>
  );
};

// ─────────────────────────────────────────────────────────────
// ViSdkSheet — the modal that hosts the flow
// ─────────────────────────────────────────────────────────────
const SHEET_HEIGHTS = {
  verifying: 420,
  consent:   672,
  dpdp:      600,
  done:      300,
};

const ViSdkSheet = ({
  phone, partnerName = 'Bazaar',
  sheetStep,                  // 'verifying' | 'consent' | 'dpdp' | 'done'
  selections, onToggle,
  onVerified,
  onContinueFromConsent,
  onShareOnlyRequired,
  onSeeDpdp, onBackFromDpdp,
  onCancel,
  lang,
}) => {
  const [mounted, setMounted] = React.useState(false);
  React.useEffect(() => {
    const id = setTimeout(() => setMounted(true), 20);
    return () => clearTimeout(id);
  }, []);

  const height = SHEET_HEIGHTS[sheetStep] || 420;
  const showCloseX = sheetStep === 'consent';

  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 10,
      background: mounted ? 'rgba(0,0,0,0.45)' : 'rgba(0,0,0,0)',
      transition: 'background .25s ease',
      display: 'flex', alignItems: 'flex-end', justifyContent: 'stretch',
    }} onClick={(sheetStep === 'verifying' || sheetStep === 'done') ? undefined : onCancel}>
      <div onClick={(e) => e.stopPropagation()} style={{
        width: '100%', height,
        background: '#fff', color: VI.ink,
        borderTopLeftRadius: 22, borderTopRightRadius: 22,
        transform: mounted ? 'translateY(0)' : 'translateY(100%)',
        transition: 'transform .32s cubic-bezier(.2,.7,.2,1), height .3s cubic-bezier(.2,.7,.2,1)',
        display: 'flex', flexDirection: 'column',
        boxSizing: 'border-box',
        overflow: 'hidden',
        boxShadow: '0 -10px 40px -10px rgba(0,0,0,0.18)',
      }}>
        {/* Drag handle */}
        <div style={{ display: 'flex', justifyContent: 'center', flexShrink: 0, paddingTop: 8, paddingBottom: 4 }}>
          <div style={{ width: 36, height: 4, borderRadius: 2, background: VI.line }} />
        </div>

        {/* Sheet header */}
        <div style={{
          padding: '8px 22px 14px', display: 'flex', alignItems: 'center', flexShrink: 0,
        }}>
          <ViLogo height={24} />
          {showCloseX && (
            <button onClick={onCancel} style={{
              marginLeft: 'auto', background: 'transparent', border: 'none', cursor: 'pointer',
              padding: 4, color: VI.soft,
            }} aria-label="Close">
              <svg width="18" height="18" viewBox="0 0 18 18" fill="none">
                <path d="M4 4 L14 14 M14 4 L4 14" stroke={VI.soft} strokeWidth="1.6" strokeLinecap="round"/>
              </svg>
            </button>
          )}
        </div>

        {/* Step content */}
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
          {sheetStep === 'verifying' && (
            <VerifyingPanel onVerified={onVerified} lang={lang} />
          )}
          {sheetStep === 'consent' && (
            <ConsentPanel phone={phone} partnerName={partnerName}
              selections={selections} onToggle={onToggle}
              onContinue={onContinueFromConsent}
              onShareOnlyRequired={onShareOnlyRequired}
              onSeeDpdp={onSeeDpdp} lang={lang} />
          )}
          {sheetStep === 'dpdp' && (
            <DpdpPanel partnerName={partnerName} onBack={onBackFromDpdp} lang={lang} />
          )}
          {sheetStep === 'done' && (
            <DonePanel partnerName={partnerName} lang={lang} />
          )}
        </div>

        {/* Persistent footer: powered by OTPless */}
        <div style={{
          flexShrink: 0,
          padding: '10px 22px 14px',
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
          background: '#fff',
        }}>
          <span style={{
            fontFamily: "'JetBrains Mono', monospace", fontSize: 9.5,
            letterSpacing: 0.8, textTransform: 'uppercase', color: VI.soft,
          }}>Powered by</span>
          <img src="assets/otpless-logo-full-240.png" alt="OTPless"
            style={{ height: 13, width: 'auto', opacity: 0.7, display: 'block' }} />
        </div>
      </div>
    </div>
  );
};

Object.assign(window, { ViSdkSheet, CONSENT_MODEL, ATTR_LIST, SHEET_HEIGHTS });
