// app.jsx — main Paisa eKYC prototype shell

const { useState: useS, useEffect: useE } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "tier": 1,
  "returningUser": false,
  "biometricFail": false,
  "otpFail": false,
  "accent": "saffron"
}/*EDITMODE-END*/;

const ACCENT_PRESETS = {
  saffron: { '--accent': 'oklch(0.66 0.15 45)', '--accent-ink': 'oklch(0.32 0.09 45)', '--accent-soft': 'oklch(0.93 0.04 60)' },
  rhodo:   { '--accent': 'oklch(0.62 0.18 0)',  '--accent-ink': 'oklch(0.30 0.10 0)',  '--accent-soft': 'oklch(0.94 0.04 0)' },
  himal:   { '--accent': 'oklch(0.62 0.13 220)','--accent-ink': 'oklch(0.30 0.09 220)','--accent-soft': 'oklch(0.94 0.03 220)' },
  forest:  { '--accent': 'oklch(0.55 0.13 155)','--accent-ink': 'oklch(0.28 0.08 155)','--accent-soft': 'oklch(0.94 0.04 155)' },
};

// Apply accent at runtime
function applyAccent(name) {
  const root = document.documentElement;
  const preset = ACCENT_PRESETS[name] || ACCENT_PRESETS.saffron;
  Object.entries(preset).forEach(([k, v]) => root.style.setProperty(k, v));
  // also mirror onto the C constant so JS-driven inline colors update on re-render
  C.accent = preset['--accent'];
  C.accentInk = preset['--accent-ink'];
  C.accentSoft = preset['--accent-soft'];
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // Wallet & gov flow state
  // Possible screens:
  //   welcome → returning? → ckycr-fast | nid → otp → consent → biometric → bundle → success → home
  const [screen, setScreen] = useS('welcome');
  const [govOverlay, setGovOverlay] = useS(null); // 'audit' | null

  // Re-apply accent whenever it changes
  useE(() => { applyAccent(t.accent); }, [t.accent]);

  const reset = () => setScreen('welcome');

  // Decide which onboarding step to start with
  const startSignup = () => {
    if (t.returningUser) setScreen('returning');
    else setScreen('nid');
  };
  const useExistingCKYC = () => setScreen('ckyc-fast');
  const startFresh = () => setScreen('nid');

  // Tier 0 skips biometric+consent, just nid → otp → bundle
  // Tier 1 full: nid → otp → consent → biometric → bundle
  // Tier 2 same as Tier 1 + extra step (we'll just label it as such)
  const afterOTP = () => {
    if (t.tier === 0) setScreen('bundle');
    else setScreen('consent');
  };
  const afterConsent = () => setScreen('biometric');
  const afterBiometric = () => setScreen('bundle');
  const afterBundle = () => setScreen('success');
  const afterSuccess = () => setScreen('home');

  // Render the active screen for the phone
  const renderScreen = () => {
    switch (screen) {
      case 'welcome':
        return <WelcomeScreen onStart={startSignup} tier={t.tier} returningUser={t.returningUser}/>;
      case 'returning':
        return <ReturningScreen onUseExisting={useExistingCKYC} onStartFresh={startFresh}/>;
      case 'nid':
        return <NIDEntryScreen onNext={() => setScreen('otp')} onBack={reset}/>;
      case 'otp':
        return <OTPScreen onNext={afterOTP} onBack={() => setScreen('nid')} otpFail={t.otpFail}/>;
      case 'consent':
        return <ConsentScreen onNext={afterConsent} onBack={() => setScreen('otp')} tier={t.tier}/>;
      case 'biometric':
        return <BiometricScreen onNext={afterBiometric} onBack={() => setScreen('consent')}
                                fail={t.biometricFail} tier={t.tier}/>;
      case 'bundle':
        return <BundleScreen onNext={afterBundle} onBack={reset} tier={t.tier}/>;
      case 'ckyc-fast':
        // Skip everything; jump to success after a short reveal
        return <CKYCFastSuccess onDone={() => setScreen('home')} tier={t.tier}/>;
      case 'success':
        return <SuccessScreen onDone={afterSuccess} tier={t.tier} returningUser={t.returningUser}/>;
      case 'home':
        return <WalletHome tier={t.tier}
                            onOpenAudit={() => setGovOverlay('audit')}
                            onUpgrade={() => setTweak('tier', Math.min(2, t.tier + 1))}/>;
      default:
        return null;
    }
  };

  // Step labels for the timeline (the right-side column)
  const flowSteps = [
    { key: 'welcome',   label: 'Welcome' },
    { key: 'nid',       label: 'NID + DOB' },
    { key: 'otp',       label: 'OTP challenge' },
    ...(t.tier > 0 ? [
      { key: 'consent',   label: 'Gov consent' },
      { key: 'biometric', label: 'Biometric · liveness' },
    ] : []),
    { key: 'bundle',    label: 'Signed eKYC bundle' },
    { key: 'success',   label: 'CKYCR registration' },
    { key: 'home',      label: 'Wallet active' },
  ];
  const currentStepIdx = Math.max(0, flowSteps.findIndex(s => s.key === screen));

  return (
    <div data-screen-label="01 Canvas"
         className="canvas-bg"
         style={{ minHeight: '100vh', padding: '40px 32px 80px' }}>
      <Header onReset={reset} screen={screen}/>

      <div style={{
        marginTop: 28, display: 'grid',
        gridTemplateColumns: '1fr 460px 1fr',
        gap: 32, alignItems: 'start',
      }}>
        {/* LEFT: Flow timeline + tier explainer */}
        <FlowTimeline steps={flowSteps} currentIdx={currentStepIdx}
                      currentScreen={screen}
                      tier={t.tier} setTier={(v) => { setTweak('tier', v); reset(); }}
                      returningUser={t.returningUser}
                      setReturningUser={(v) => { setTweak('returningUser', v); reset(); }}/>

        {/* CENTER: Phone */}
        <div data-screen-label="02 Wallet (phone)"
             style={{ display: 'flex', justifyContent: 'center', position: 'sticky', top: 24 }}>
          <IOSDevice width={402} height={874}
                     dark={['consent', 'biometric'].includes(screen)}>
            <div style={{ position: 'relative', height: '100%' }} key={screen + t.tier}>
              {/* render-only key forces fade-up on screen change */}
              <div style={{ height: '100%', animation: 'fade-up .35s ease' }}>
                {renderScreen()}
              </div>
              {govOverlay === 'audit' && (
                <div style={{
                  position: 'absolute', inset: 0, zIndex: 30,
                  animation: 'fade-up .25s ease',
                }}>
                  <AuditLogApp onClose={() => setGovOverlay(null)}/>
                </div>
              )}
            </div>
          </IOSDevice>
        </div>

        {/* RIGHT: Behind-the-scenes payload + reset shortcuts */}
        <BehindTheScenes screen={screen} tier={t.tier} returningUser={t.returningUser}/>
      </div>

      {/* Architecture below — full width */}
      <div data-screen-label="03 Architecture"
           style={{ marginTop: 56, display: 'flex', justifyContent: 'center' }}>
        <ArchitectureView/>
      </div>

      {/* Tweaks panel */}
      <TweaksPanel title="Tweaks">
        <TweakSection label="Scenario"/>
        <TweakRadio label="KYC Tier" value={t.tier}
                    options={[
                      { value: 0, label: 'Tier 0' },
                      { value: 1, label: 'Tier 1' },
                      { value: 2, label: 'Tier 2' },
                    ]}
                    onChange={(v) => { setTweak('tier', v); reset(); }}/>
        <TweakToggle label="Returning (CKYCR hit)"
                     value={t.returningUser}
                     onChange={(v) => { setTweak('returningUser', v); reset(); }}/>
        <TweakSection label="Failure paths"/>
        <TweakToggle label="Biometric fails"
                     value={t.biometricFail}
                     onChange={(v) => setTweak('biometricFail', v)}/>
        <TweakToggle label="OTP not received"
                     value={t.otpFail}
                     onChange={(v) => setTweak('otpFail', v)}/>
        <TweakSection label="Brand"/>
        <TweakRadio label="Accent" value={t.accent}
                    options={[
                      { value: 'saffron', label: 'Saffron' },
                      { value: 'himal',   label: 'Himal' },
                    ]}
                    onChange={(v) => setTweak('accent', v)}/>
        <TweakRadio label="More" value={t.accent}
                    options={[
                      { value: 'rhodo',  label: 'Rhodo' },
                      { value: 'forest', label: 'Forest' },
                    ]}
                    onChange={(v) => setTweak('accent', v)}/>
      </TweaksPanel>
    </div>
  );
}

// ─── CKYCR fast path (returning user) ──────────────────────
function CKYCFastSuccess({ onDone, tier }) {
  const [phase, setPhase] = useS(0);
  useE(() => {
    const t1 = setTimeout(() => setPhase(1), 1200);
    const t2 = setTimeout(() => setPhase(2), 2200);
    return () => { clearTimeout(t1); clearTimeout(t2); };
  }, []);

  const lines = [
    'GET ckycr.gov.np/v1/lookup',
    '→ matched · pulling bundle…',
    '✓ activated · 6s total',
  ];

  return (
    <div style={{
      padding: '90px 28px 32px', height: '100%', background: C.bg,
      display: 'flex', flexDirection: 'column',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
        <PaisaMark size={28} />
        <span style={{ fontSize: 18, fontWeight: 700 }}>paisa</span>
      </div>

      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
        {phase < 2 ? (
          <div>
            <Spinner size={28}/>
            <h2 style={{ fontSize: 28, fontWeight: 700, letterSpacing: -0.8,
                         margin: '20px 0 8px', lineHeight: 1.1 }}>
              Pulling your CKYCR<br/>record…
            </h2>
            <p style={{ fontSize: 14, color: C.ink2, lineHeight: 1.5, margin: 0 }}>
              No biometric. No OTP. Just consent.
            </p>
            <div style={{ marginTop: 24, display: 'flex', flexDirection: 'column', gap: 6 }}>
              {lines.slice(0, phase + 1).map((l, i) => (
                <div key={i} className="mono" style={{
                  fontSize: 12, color: i === phase ? C.ink : C.ink3,
                  letterSpacing: 0.4, animation: 'fade-up .3s ease',
                }}>{l}</div>
              ))}
            </div>
          </div>
        ) : (
          <div style={{ animation: 'fade-up .4s ease' }}>
            <AnimatedCheck size={64}/>
            <h1 style={{ fontSize: 36, fontWeight: 700, letterSpacing: -1,
                         margin: '20px 0 6px', lineHeight: 1.05 }}>
              Welcome back,<br/>Aanya.
            </h1>
            <p style={{ fontSize: 15, color: C.ink2, lineHeight: 1.5, margin: 0 }}>
              Wallet active in 6 seconds — that's the whole point of a central registry.
            </p>
            <div style={{ marginTop: 22 }}>
              <TierBadge tier={tier} size="lg"/>
            </div>
          </div>
        )}
      </div>

      {phase >= 2 && <PrimaryBtn onClick={onDone}>Open my wallet</PrimaryBtn>}
    </div>
  );
}

// ─── Header ────────────────────────────────────────────────
function Header({ onReset, screen }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 16,
                  maxWidth: 1400, margin: '0 auto' }}>
      <PaisaMark size={26} />
      <div>
        <div style={{ fontSize: 14, fontWeight: 700, letterSpacing: -0.2 }}>
          Paisa Wallet × NID Authority
        </div>
        <div style={{ fontSize: 11, color: C.ink3, fontFamily: 'JetBrains Mono, monospace',
                      letterSpacing: 0.4 }}>
          eKYC onboarding prototype · Nepal
        </div>
      </div>
      <div style={{ flex: 1 }}/>
      <button onClick={onReset} style={{
        padding: '8px 14px', borderRadius: 999,
        border: `1px solid ${C.line}`, background: C.surface,
        fontSize: 12, fontWeight: 500, color: C.ink2,
        display: 'flex', alignItems: 'center', gap: 6,
      }}>
        <span style={{ fontSize: 14 }}>↺</span> Reset flow
      </button>
    </div>
  );
}

// ─── Flow timeline (left column) ───────────────────────────
function FlowTimeline({ steps, currentIdx, currentScreen, tier, setTier, returningUser, setReturningUser }) {
  const tierLimits = {
    0: { bal: 'NPR 10K', mo: 'NPR 25K / mo', use: 'First-time, rural, students' },
    1: { bal: 'NPR 1L',  mo: 'NPR 5L / mo',  use: 'Salary, P2P, merchants' },
    2: { bal: 'NPR 5L+', mo: 'No cap',       use: 'Bank-grade, business' },
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 18, position: 'sticky', top: 24 }}>
      <div style={{
        padding: 20, borderRadius: 16, background: C.surface,
        border: `1px solid ${C.line}`,
      }}>
        <div style={{ fontSize: 11, color: C.ink3, fontWeight: 700,
                      textTransform: 'uppercase', letterSpacing: 0.8 }}>
          Try a tier
        </div>
        <div style={{ marginTop: 10, display: 'flex', gap: 6 }}>
          {[0, 1, 2].map(n => (
            <button key={n} onClick={() => setTier(n)} style={{
              flex: 1, padding: '8px 0', borderRadius: 10,
              background: tier === n ? C.ink : 'transparent',
              color: tier === n ? '#fffdf8' : C.ink,
              border: `1px solid ${tier === n ? C.ink : C.line}`,
              fontSize: 12, fontWeight: 600, letterSpacing: 0.2,
            }}>Tier {n}</button>
          ))}
        </div>
        <div style={{ marginTop: 14, padding: 12, borderRadius: 10,
                      background: C.bg, border: `1px solid ${C.line2}` }}>
          <div style={{ fontSize: 13, fontWeight: 600 }}>
            {tier === 0 ? 'Inclusion · NID + OTP' :
             tier === 1 ? 'Full · NID + biometric' :
             'Bank-grade · NID + biometric + video'}
          </div>
          <div style={{ marginTop: 8, display: 'flex', flexDirection: 'column', gap: 6,
                        fontSize: 12 }}>
            <Row k="Balance cap" v={tierLimits[tier].bal}/>
            <Row k="Monthly cap" v={tierLimits[tier].mo}/>
            <Row k="Use case" v={tierLimits[tier].use}/>
          </div>
        </div>

        <label style={{
          marginTop: 14, display: 'flex', alignItems: 'center', gap: 10,
          padding: '10px 12px', borderRadius: 10,
          background: returningUser ? C.goodSoft : C.bg,
          border: `1px solid ${returningUser ? C.good + '40' : C.line2}`,
          cursor: 'pointer',
        }}>
          <input type="checkbox" checked={returningUser}
                 onChange={(e) => setReturningUser(e.target.checked)}
                 style={{ accentColor: C.good }}/>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 12, fontWeight: 600, color: returningUser ? C.good : C.ink }}>
              CKYCR hit (returning user)
            </div>
            <div style={{ fontSize: 11, color: C.ink3, marginTop: 2 }}>
              Skip to a 6-second flow
            </div>
          </div>
        </label>
      </div>

      <div style={{
        padding: 20, borderRadius: 16, background: C.surface,
        border: `1px solid ${C.line}`,
      }}>
        <div style={{ fontSize: 11, color: C.ink3, fontWeight: 700,
                      textTransform: 'uppercase', letterSpacing: 0.8, marginBottom: 14 }}>
          User journey
        </div>
        {steps.map((s, i) => {
          const isCurrent = currentScreen === s.key;
          const done = i < currentIdx;
          return (
            <div key={s.key} style={{ display: 'flex', gap: 12, alignItems: 'flex-start',
                                      paddingBottom: 14, position: 'relative' }}>
              {i < steps.length - 1 && (
                <div style={{
                  position: 'absolute', left: 9, top: 22, bottom: 0,
                  width: 1, background: done ? C.ink : C.line,
                }}/>
              )}
              <div style={{
                width: 18, height: 18, borderRadius: 999, marginTop: 2,
                background: done ? C.ink : isCurrent ? C.surface : 'transparent',
                border: `2px solid ${done ? C.ink : isCurrent ? C.accent : C.line}`,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                flexShrink: 0,
              }}>
                {done && <svg width="10" height="10" viewBox="0 0 10 10">
                  <path d="M2 5l2 2 4-4" fill="none" stroke="#fffdf8" strokeWidth="1.6"
                        strokeLinecap="round" strokeLinejoin="round"/>
                </svg>}
                {isCurrent && <div style={{ width: 6, height: 6, borderRadius: 999, background: C.accent }}/>}
              </div>
              <div style={{ flex: 1, paddingTop: 2 }}>
                <div style={{ fontSize: 13, fontWeight: isCurrent ? 700 : 500,
                              color: done ? C.ink3 : C.ink,
                              textDecoration: done ? 'line-through' : 'none',
                              textDecorationColor: C.ink3 }}>
                  {s.label}
                </div>
                {isCurrent && <StepHint step={s.key}/>}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function StepHint({ step }) {
  const hints = {
    welcome: 'User opens the app for the first time.',
    nid: 'Wallet collects only the public NID number + DOB.',
    otp: 'Wallet asks NID Authority to challenge the citizen.',
    consent: 'Hand-off to a government-controlled screen.',
    biometric: 'Liveness check, then 1:N match against NID DB.',
    bundle: 'Wallet receives a signed payload — never the raw record.',
    success: 'Wallet pushes onboarding to the central registry.',
    home: 'Wallet active. Audit log lives in mNID.',
    returning: 'CKYCR already has the user — fast path available.',
    'ckyc-fast': 'Pulling existing record with consent only.',
  };
  return (
    <div style={{ marginTop: 4, fontSize: 11.5, color: C.ink2, lineHeight: 1.5 }}>
      {hints[step] || ''}
    </div>
  );
}

function Row({ k, v }) {
  return (
    <div style={{ display: 'flex', justifyContent: 'space-between', gap: 8 }}>
      <span style={{ color: C.ink3 }}>{k}</span>
      <span style={{ fontWeight: 500, textAlign: 'right' }}>{v}</span>
    </div>
  );
}

// ─── Behind-the-scenes panel (right column) ────────────────
function BehindTheScenes({ screen, tier, returningUser }) {
  const payloads = {
    welcome: {
      title: 'No payload yet',
      kind: 'idle',
      lines: ['# Wallet hasn\'t made a request', '# Waiting for user input'],
    },
    nid: {
      title: 'Pre-flight',
      kind: 'wallet',
      lines: [
        '# Wallet validates locally:',
        'nid: "98•••••••42"',
        'dob: "1996-04-12"',
        '# Will be tokenized client-side',
      ],
    },
    otp: {
      title: 'Auth request',
      kind: 'wallet',
      lines: [
        'POST /v2/authenticate',
        '{',
        '  vid: "9842•••••3076",',
        '  challenge: "otp",',
        `  tier: ${tier},`,
        '  purpose: "ACCT_OPEN",',
        '  client: "paisa-wallet"',
        '}',
      ],
    },
    consent: {
      title: 'Consent prompt',
      kind: 'gov',
      lines: [
        '# Government screen — not Paisa\'s UI',
        '# User explicitly approves each field',
        'fields_requested: [name, photo,',
        '                   dob, address, gender]',
        'token_ttl: 86400  // 24h, then re-consent',
      ],
    },
    biometric: {
      title: 'Liveness + 1:N match',
      kind: 'gov',
      lines: [
        '# Biometric template never leaves device',
        'capture: face_template_v3',
        'liveness: passed',
        'match_score: 0.996',
        '# NID compares hash, not raw',
      ],
    },
    bundle: {
      title: 'Signed eKYC bundle',
      kind: 'good',
      lines: [
        '{',
        '  vid:    "9842•••••3076",',
        '  name:   "Aanya Sharma",',
        '  photo:  "<base64 32×32>",',
        '  dob:    "1996-04-12",',
        '  addr:   "Lalitpur, Bagmati",',
        '  tier:   ' + tier + ',',
        '  iss:    "nid.gov.np",',
        '  iat:    1746537143,',
        '  sig:    "ed25519:7f3a…b29e"',
        '}',
      ],
    },
    success: {
      title: 'CKYCR push',
      kind: 'good',
      lines: [
        'POST ckycr.gov.np/v1/onboard',
        '{',
        '  ckyc_id:     "CKYC-NP-7HQ4J2-K88B",',
        '  bundle_hash: "sha256:a14b…c2",',
        '  onboarded_by:"paisa-wallet",',
        `  tier:        ${tier}`,
        '}',
        '→ 201 created · reusable',
      ],
    },
    home: {
      title: 'Steady state',
      kind: 'idle',
      lines: [
        '# Wallet stores:',
        '#  - VID token',
        '#  - Signed bundle',
        '#  - Bundle public key fingerprint',
        '# That\'s it.',
      ],
    },
    returning: {
      title: 'CKYCR lookup',
      kind: 'good',
      lines: [
        'GET ckycr.gov.np/v1/lookup',
        '?vid=9842•••••3076',
        '→ found · CKYC-NP-7HQ4J2-K88B',
        '   onboarded_by: esewa',
        '   age: 78 days · valid',
      ],
    },
    'ckyc-fast': {
      title: 'CKYCR pull (with consent)',
      kind: 'good',
      lines: [
        'POST ckycr.gov.np/v1/pull',
        '{',
        '  ckyc_id: "CKYC-NP-7HQ4J2-K88B",',
        '  consent: "user-approved",',
        '  requestor: "paisa-wallet"',
        '}',
        '→ bundle returned in 1.4s',
      ],
    },
  };

  const facts = {
    welcome: { ttl: '~30s for Tier 0', cost: 'NPR 5–15 / KYC', vs: 'vs. NPR 150–300 today' },
    nid: { ttl: '0s – local validation', cost: 'no API call yet', vs: '' },
    otp: { ttl: '~10s SMS delivery', cost: 'NPR 0.30 / SMS', vs: '' },
    consent: { ttl: 'user-controlled', cost: '—', vs: 'Government-owned screen' },
    biometric: { ttl: '~8s capture + match', cost: 'NPR 2 / call', vs: '' },
    bundle: { ttl: '<1s response', cost: '—', vs: 'No manual review' },
    success: { ttl: '~3s registry write', cost: 'NPR 1', vs: 'Onboarding cost: ~NPR 12 total' },
    home: { ttl: '—', cost: '—', vs: '' },
    returning: { ttl: '<2s lookup', cost: 'NPR 1', vs: '' },
    'ckyc-fast': { ttl: '~6s end-to-end', cost: 'NPR 2', vs: '50s saved per onboarding' },
  };

  const p = payloads[screen] || payloads.welcome;
  const f = facts[screen] || facts.welcome;

  const kindColor = {
    wallet: { tag: 'WALLET → NID', col: C.accent },
    gov:    { tag: 'GOV NID',      col: C.gov },
    good:   { tag: 'OK',           col: C.good },
    idle:   { tag: 'IDLE',         col: C.ink3 },
  }[p.kind];

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 18, position: 'sticky', top: 24 }}>
      <div style={{
        padding: 20, borderRadius: 16, background: C.ink, color: '#fffdf8',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{
            padding: '3px 8px', borderRadius: 6,
            fontSize: 9.5, fontWeight: 700, letterSpacing: 0.6,
            background: kindColor.col, color: C.ink,
          }}>{kindColor.tag}</span>
          <span style={{ fontSize: 12, fontWeight: 600, opacity: 0.8 }}>{p.title}</span>
        </div>
        <pre className="mono" style={{
          margin: '14px 0 0', fontSize: 11.5, lineHeight: 1.6,
          color: '#f5f1ea', whiteSpace: 'pre-wrap', wordBreak: 'break-word',
        }}>
          {p.lines.join('\n')}
        </pre>
      </div>

      <div style={{
        padding: 18, borderRadius: 16, background: C.surface,
        border: `1px solid ${C.line}`,
      }}>
        <div style={{ fontSize: 11, color: C.ink3, fontWeight: 700,
                      textTransform: 'uppercase', letterSpacing: 0.8 }}>
          What's happening
        </div>
        <div style={{ marginTop: 10, display: 'flex', flexDirection: 'column', gap: 8 }}>
          <Row k="Latency" v={f.ttl}/>
          <Row k="Cost" v={f.cost}/>
          {f.vs && <div style={{ fontSize: 11, color: C.accentInk,
                                 fontWeight: 600, marginTop: 4 }}>{f.vs}</div>}
        </div>
      </div>

      <div style={{
        padding: 18, borderRadius: 16,
        background: C.accentSoft, border: `1px solid ${C.accent}40`,
      }}>
        <div style={{ fontSize: 11, color: C.accentInk, fontWeight: 700,
                      textTransform: 'uppercase', letterSpacing: 0.8 }}>
          Design principle
        </div>
        <div style={{ fontSize: 13, color: C.ink, marginTop: 8, lineHeight: 1.5 }}>
          {principle(screen)}
        </div>
      </div>
    </div>
  );
}

function principle(screen) {
  const map = {
    welcome: 'Tiered onboarding: never force the highest standard on everyone — that kills inclusion. Allow the lowest, and you invite fraud.',
    nid: 'The wallet stores a Virtual ID, not the raw NID. If breached, attackers get tokens useless elsewhere.',
    otp: 'The user receives the challenge from the NID Authority — not from the wallet. Phishable wallet flows are out.',
    consent: 'Consent must be explicit, granular, and revocable. The screen lives on the government side, not the wallet\'s.',
    biometric: 'Liveness prevents deepfakes. Templates stay on-device; only encrypted matches travel.',
    bundle: 'The wallet receives a signed payload, not access to the database. Verification is mathematical, not procedural.',
    success: 'Reuse is the whole point of the registry. Next wallet pulls this in seconds.',
    home: 'Trust comes from the audit log: users see every authentication, by whom, for what purpose.',
    returning: 'India\'s cost dropped from ₹1,500 to ₹15 post-Aadhaar. Reusable KYC is a 100× savings.',
    'ckyc-fast': 'Reusable across wallets — the central registry\'s purpose. User stays in control via consent.',
  };
  return map[screen] || '';
}

// Mount
ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
