// Mobile FIRST-RUN onboarding — 6 screens
// 1 Welcome → 2 Password → 3 Profile → 4 Loading → 5 Sync → 6 Success
//
// Visual language: Ajna dark + accent gradient + Geist/JetBrains Mono.
// Designed edge-to-edge (Android 15+); status bar is the host's, no app bar.
// Each screen is a self-contained component receiving { onNext, onBack, ctx, setCtx }.

const FR_STEPS = [
  { id: 'welcome',  label: 'Welcome' },
  { id: 'default',  label: 'Default' },
  { id: 'password', label: 'Password' },
  { id: 'profile',  label: 'Profile' },
  { id: 'loading',  label: 'Setup' },
  { id: 'sync',     label: 'Sync' },
  { id: 'success',  label: 'Done' },
];

// ── Ajna mark — gradient diamond glyph ─────────────────────────
function AjnaMark({ size = 56, glow = true }) {
  return (
    <svg width={size} height={size} viewBox="0 0 64 64" style={{ display: 'block', filter: glow ? 'drop-shadow(0 0 24px rgba(96,165,250,0.4))' : 'none' }}>
      <defs>
        <linearGradient id="ajnaMarkGrad" x1="0" y1="0" x2="1" y2="1">
          <stop offset="0%" stopColor={M_ACCENT}/>
          <stop offset="100%" stopColor={M_ACCENT_B}/>
        </linearGradient>
      </defs>
      <path d="M32 4 L60 32 L32 60 L4 32 Z" fill="url(#ajnaMarkGrad)" opacity="0.18"/>
      <path d="M32 12 L52 32 L32 52 L12 32 Z" fill="url(#ajnaMarkGrad)" opacity="0.45"/>
      <circle cx="32" cy="32" r="8" fill="url(#ajnaMarkGrad)"/>
    </svg>
  );
}

// ── Animated welcome illustration — peer-to-peer constellation ──
function FRWelcomeIllo() {
  const ORBITS = [
    { r: 58,  speed: 22, dir: 1,  border: 'rgba(96,165,250,0.10)',  peers: [
      { a:   0, c: M_ACCENT_B, size: 10 },
      { a: 165, c: M_ACCENT,   size: 8  },
    ]},
    { r: 96,  speed: 34, dir: -1, border: 'rgba(110,231,183,0.08)', peers: [
      { a:  40, c: '#A78BFA', size: 7  },
      { a: 200, c: '#FBBF24', size: 9  },
      { a: 310, c: M_ACCENT_B, size: 6 },
    ]},
  ];
  const SIZE = 240;
  return (
    <div style={{
      position: 'relative', width: SIZE, height: SIZE,
      display: 'grid', placeItems: 'center',
    }}>
      <style>{`
        @keyframes frwRot   { to { transform: rotate(360deg); } }
        @keyframes frwRotR  { to { transform: rotate(-360deg); } }
        @keyframes frwBob   { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
        @keyframes frwPulse { 0% { transform: scale(0.55); opacity: 0.55; } 100% { transform: scale(1.7); opacity: 0; } }
        @keyframes frwTwinkle { 0%,100% { opacity: 0.6; transform: scale(1); } 50% { opacity: 1; transform: scale(1.25); } }
        @keyframes frwBeam  { 0%   { stroke-dashoffset: 80; opacity: 0; }
                              30%  { opacity: 0.9; }
                              70%  { opacity: 0.9; }
                              100% { stroke-dashoffset: 0; opacity: 0; } }
      `}</style>

      {/* radial ambient glow */}
      <div style={{
        position: 'absolute', inset: 0, borderRadius: '50%',
        background: 'radial-gradient(closest-side, rgba(96,165,250,0.18), transparent 65%)',
        pointerEvents: 'none',
      }}/>

      {/* expanding ripples from center */}
      {[0, 1.4, 2.8].map((delay, i) => (
        <div key={i} style={{
          position: 'absolute', width: 80, height: 80, borderRadius: '50%',
          border: '1px solid ' + M_ACCENT_B,
          animation: `frwPulse 4.2s ease-out ${delay}s infinite`,
          pointerEvents: 'none',
        }}/>
      ))}

      {/* signal beams between center and an outer peer */}
      <svg width={SIZE} height={SIZE} style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
        <defs>
          <linearGradient id="frwBeamGrad" x1="0" y1="0" x2="1" y2="0">
            <stop offset="0%"  stopColor={M_ACCENT_B} stopOpacity="0"/>
            <stop offset="50%" stopColor={M_ACCENT_B} stopOpacity="0.8"/>
            <stop offset="100%" stopColor={M_ACCENT}  stopOpacity="0"/>
          </linearGradient>
        </defs>
        {[
          { x2: SIZE/2 + 96, y2: SIZE/2 - 30, delay: 0.4 },
          { x2: SIZE/2 - 80, y2: SIZE/2 + 60, delay: 1.6 },
          { x2: SIZE/2 + 50, y2: SIZE/2 + 90, delay: 2.8 },
        ].map((b, i) => (
          <line key={i}
            x1={SIZE/2} y1={SIZE/2} x2={b.x2} y2={b.y2}
            stroke="url(#frwBeamGrad)" strokeWidth="1.4"
            strokeDasharray="80" strokeLinecap="round"
            style={{ animation: `frwBeam 3.6s ease-in-out ${b.delay}s infinite` }}
          />
        ))}
      </svg>

      {/* orbit rings + peers */}
      {ORBITS.map((o, oi) => (
        <div key={oi} style={{
          position: 'absolute',
          width: o.r * 2, height: o.r * 2,
          borderRadius: '50%',
          border: '1px dashed ' + o.border,
          animation: `${o.dir > 0 ? 'frwRot' : 'frwRotR'} ${o.speed}s linear infinite`,
        }}>
          {o.peers.map((p, i) => (
            <div key={i} style={{
              position: 'absolute', left: '50%', top: '50%',
              width: 0, height: 0,
              transform: `rotate(${p.a}deg)`,
            }}>
              <div style={{
                position: 'absolute',
                left: o.r - p.size / 2,
                top: -p.size / 2,
                width: p.size, height: p.size, borderRadius: p.size,
                background: p.c,
                boxShadow: `0 0 14px ${p.c}, 0 0 4px ${p.c}`,
                animation: `frwTwinkle 2.4s ease-in-out ${i * 0.4}s infinite`,
              }}/>
            </div>
          ))}
        </div>
      ))}

      {/* center mark */}
      <div style={{ animation: 'frwBob 4.5s ease-in-out infinite', position: 'relative', zIndex: 2 }}>
        <AjnaMark size={84}/>
      </div>
    </div>
  );
}

// ── Generic primary CTA ───────────────────────────────────────
function FRPrimary({ children, disabled, onClick, icon, style = {} }) {
  return (
    <button onClick={onClick} disabled={disabled} style={{
      width: '100%', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
      padding: '15px 18px', borderRadius: 14, border: 0,
      background: disabled
        ? M_SURFACE_2
        : 'linear-gradient(135deg, ' + M_ACCENT + ', ' + M_ACCENT_B + ')',
      color: disabled ? M_FG_DIM : '#0B0C0F',
      fontSize: 15, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.005em',
      cursor: disabled ? 'default' : 'pointer',
      boxShadow: disabled ? 'none' : '0 10px 30px -10px rgba(96,165,250,0.55), 0 1px 0 rgba(255,255,255,0.2) inset',
      transition: 'background 160ms, color 160ms, box-shadow 160ms',
      ...style,
    }}>{children}{icon}</button>
  );
}

function FRTextLink({ children, onClick, style = {} }) {
  return (
    <button onClick={onClick} style={{
      background: 'transparent', border: 0, color: M_FG_MUTED,
      fontSize: 13, fontFamily: 'inherit', cursor: 'pointer',
      padding: '10px 14px', textDecoration: 'underline', textUnderlineOffset: 4, textDecorationColor: M_BORDER,
      ...style,
    }}>{children}</button>
  );
}

// ── 1. WELCOME ────────────────────────────────────────────────
function FRWelcome({ onNext, onSkipToImport }) {
  return (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column', padding: '40px 28px 28px' }}>
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', textAlign: 'center', gap: 16 }}>
        <FRWelcomeIllo/>
        <div>
          <div style={{
            fontSize: 36, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif',
            letterSpacing: '-0.035em', lineHeight: 1.05, color: M_FG,
          }}>Welcome to <span style={{ background: 'linear-gradient(135deg, ' + M_ACCENT + ', ' + M_ACCENT_B + ')', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent' }}>Ajna</span></div>
          <div style={{ marginTop: 12, fontSize: 14.5, color: M_FG_MUTED, lineHeight: 1.5, maxWidth: 280, marginLeft: 'auto', marginRight: 'auto' }}>
            A browser that owns its identity. Yours. End-to-end, peer-to-peer.
          </div>
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10, alignItems: 'stretch', width: '100%', maxWidth: 320 }}>
          {[
            { ic: MIc.shield,    title: 'Self-sovereign identity', sub: 'Cryptographic keys live on your device' },
            { ic: MIc.bluetooth, title: 'Talk to anyone, anywhere',  sub: 'Internet, mesh, or Bluetooth — automatic' },
            { ic: MIc.bolt,      title: 'No accounts, no servers',  sub: 'You are the network' },
          ].map((b, i) => (
            <div key={i} style={{
              display: 'flex', alignItems: 'center', gap: 12, padding: '11px 14px',
              background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT, borderRadius: 14,
              textAlign: 'left',
            }}>
              <div style={{
                width: 32, height: 32, borderRadius: 10,
                background: 'linear-gradient(135deg, rgba(110,231,183,0.18), rgba(96,165,250,0.18))',
                color: M_ACCENT_B, display: 'grid', placeItems: 'center', flexShrink: 0,
              }}>{b.ic({ s: 16 })}</div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 13, fontWeight: 600, color: M_FG, letterSpacing: '-0.005em' }}>{b.title}</div>
                <div style={{ fontSize: 11.5, color: M_FG_MUTED, marginTop: 1, lineHeight: 1.35 }}>{b.sub}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        <FRPrimary onClick={onNext} icon={
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
        }>Get started</FRPrimary>
        <button onClick={onSkipToImport} style={{
          background: 'transparent', border: 0, color: M_FG_MUTED, padding: '12px',
          fontSize: 13, fontWeight: 500, fontFamily: 'inherit', cursor: 'pointer',
        }}>I already have an identity</button>
      </div>
    </div>
  );
}

// ── 2. PASSWORD ──────────────────────────────────────────────
function FRPassword({ onNext, onBack, ctx, setCtx, onUseExisting }) {
  const [pw, setPw] = React.useState(ctx.pw || '');
  const [pw2, setPw2] = React.useState(ctx.pw2 || '');
  const [showA, setShowA] = React.useState(false);
  const [showB, setShowB] = React.useState(false);

  const tooShort = pw.length > 0 && pw.length < 8;
  const mismatch = pw2.length > 0 && pw !== pw2;
  const valid = pw.length >= 8 && pw === pw2;

  // strength: chars + variety
  const score = React.useMemo(() => {
    let s = 0;
    if (pw.length >= 8) s++;
    if (pw.length >= 12) s++;
    if (/[A-Z]/.test(pw) && /[a-z]/.test(pw)) s++;
    if (/[0-9]/.test(pw)) s++;
    if (/[^A-Za-z0-9]/.test(pw)) s++;
    return Math.min(s, 4);
  }, [pw]);
  const strength = score <= 1 ? { label: 'Weak',   color: '#F87171', bars: 1 }
                 : score === 2 ? { label: 'Fair',   color: '#FBBF24', bars: 2 }
                 : score === 3 ? { label: 'Good',   color: '#22D27A', bars: 3 }
                 :               { label: 'Strong', color: M_ACCENT,  bars: 4 };

  const submit = () => {
    if (!valid) return;
    setCtx({ ...ctx, pw, pw2 });
    onNext();
  };

  return (
    <FRPage onBack={onBack}>
      <FRHeader title="Create a password" subtitle="We'll use this to protect your identity on this device."/>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14, marginTop: 24 }}>
        <FRPasswordField
          value={pw} onChange={setPw}
          placeholder="Password" show={showA} setShow={setShowA}
          error={tooShort ? 'At least 8 characters' : null}
        />
        {pw.length > 0 && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: -4, padding: '0 4px' }}>
            <div style={{ flex: 1, display: 'flex', gap: 4 }}>
              {[1,2,3,4].map(i => (
                <div key={i} style={{
                  flex: 1, height: 4, borderRadius: 2,
                  background: i <= strength.bars ? strength.color : 'var(--m-tint)',
                  transition: 'background 200ms',
                }}/>
              ))}
            </div>
            <span style={{ fontSize: 11.5, fontWeight: 600, color: strength.color, fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.02em', minWidth: 48, textAlign: 'right' }}>{strength.label}</span>
          </div>
        )}
        <FRPasswordField
          value={pw2} onChange={setPw2}
          placeholder="Confirm password" show={showB} setShow={setShowB}
          error={mismatch ? "Passwords don't match" : null}
          ok={valid}
        />
      </div>

      <div style={{
        marginTop: 18, padding: '11px 13px', borderRadius: 12,
        background: 'rgba(251,191,36,0.06)', border: '1px solid rgba(251,191,36,0.18)',
        display: 'flex', alignItems: 'flex-start', gap: 10,
      }}>
        <span style={{ color: '#FBBF24', flexShrink: 0, marginTop: 1 }}>{MIc.shield({ s: 14 })}</span>
        <div style={{ fontSize: 11.5, color: M_FG_MUTED, lineHeight: 1.45 }}>
          Try not to lose it — your password stays on this device. If you do, <span style={{ color: M_FG }}>social recovery</span> lets a few trusted contacts help you back in.
        </div>
      </div>

      <FRFooter>
        <FRPrimary disabled={!valid} onClick={submit}>Continue</FRPrimary>
        {onUseExisting && <button onClick={onUseExisting} style={{ background: 'transparent', border: 0, color: M_FG_MUTED, padding: '12px', fontSize: 13, fontWeight: 500, fontFamily: 'inherit', cursor: 'pointer', width: '100%' }}>Use an existing identity</button>}
      </FRFooter>
    </FRPage>
  );
}

function FRPasswordField({ value, onChange, placeholder, show, setShow, error, ok }) {
  const borderColor = error ? 'rgba(248,113,113,0.45)' : ok ? 'rgba(110,231,183,0.4)' : value ? 'rgba(96,165,250,0.4)' : M_BORDER_SOFT;
  return (
    <div>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 10,
        padding: '13px 14px', background: M_SURFACE,
        border: '1px solid ' + borderColor, borderRadius: 14,
        boxShadow: error ? '0 0 0 4px rgba(248,113,113,0.06)' : 'none',
        transition: 'border 160ms, box-shadow 160ms',
      }}>
        <span style={{ color: M_FG_DIM, flexShrink: 0 }}>
          <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="4" y="11" width="16" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/></svg>
        </span>
        <input
          type={show ? 'text' : 'password'}
          value={value} onChange={e => onChange(e.target.value)}
          placeholder={placeholder}
          style={{
            flex: 1, background: 'transparent', border: 0, outline: 0,
            color: M_FG, fontSize: 14.5, fontFamily: show ? 'JetBrains Mono, monospace' : 'inherit',
            letterSpacing: show ? '0.02em' : '0.18em',
            minWidth: 0,
          }}
        />
        <button onClick={() => setShow(!show)} style={{
          background: 'transparent', border: 0, color: M_FG_DIM, cursor: 'pointer',
          padding: 4, display: 'grid', placeItems: 'center', flexShrink: 0,
        }}>
          {show ? (
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="m3 3 18 18"/><path d="M10.5 10.7a2 2 0 0 0 2.8 2.8"/><path d="M9.9 5.1A10 10 0 0 1 22 12c-.7 1.6-1.7 3-3 4.1M6.6 6.6A10 10 0 0 0 2 12c1.4 3.5 5.1 7 10 7 1.5 0 3-.4 4.4-1.1"/></svg>
          ) : (
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/></svg>
          )}
        </button>
      </div>
      {error && (
        <div style={{ fontSize: 11.5, color: '#F87171', marginTop: 6, paddingLeft: 4, display: 'flex', alignItems: 'center', gap: 5 }}>
          <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><circle cx="12" cy="12" r="9"/><path d="M12 8v5M12 16h0"/></svg>
          {error}
        </div>
      )}
    </div>
  );
}

// ── 3. PROFILE ───────────────────────────────────────────────
function FRProfile({ onNext, onBack, ctx, setCtx }) {
  const [name, setName] = React.useState(ctx.name || '');
  const [handle, setHandle] = React.useState(ctx.handle || '');
  const valid = name.trim().length >= 1;

  const initial = (name.trim()[0] || '?').toUpperCase();
  const submit = () => { if (!valid) return; setCtx({ ...ctx, name, handle }); onNext(); };

  return (
    <FRPage onBack={onBack}>
      <FRHeader title="How should you appear to others?" subtitle="You can change this anytime in Settings."/>

      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginTop: 28, marginBottom: 24 }}>
        <div style={{ position: 'relative' }}>
          <div style={{
            width: 96, height: 96, borderRadius: 48,
            background: 'linear-gradient(135deg, ' + M_ACCENT + ', ' + M_ACCENT_B + ')',
            display: 'grid', placeItems: 'center',
            color: '#0B0C0F', fontSize: 42, fontWeight: 600,
            fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.02em',
            boxShadow: '0 18px 50px -16px rgba(96,165,250,0.5), inset 0 1px 0 rgba(255,255,255,0.25)',
          }}>{initial}</div>
          <button style={{
            position: 'absolute', bottom: -2, right: -2,
            width: 32, height: 32, borderRadius: 16,
            background: M_FG, color: '#0B0C0F',
            border: '3px solid ' + M_BG,
            display: 'grid', placeItems: 'center', cursor: 'pointer',
            boxShadow: '0 4px 12px rgba(0,0,0,0.4)',
          }}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M14 2 22 10M3 21l5-1L20 8l-4-4L4 16l-1 5z"/></svg>
          </button>
        </div>
        <div style={{ fontSize: 11, color: M_FG_DIM, marginTop: 12, fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.08em', textTransform: 'uppercase' }}>Tap to change photo</div>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <FRTextField
          label="Name"
          value={name} onChange={setName}
          placeholder="Your name" autoFocus maxLength={40}
        />
        <FRTextField
          label="Handle"
          optional
          value={handle} onChange={(v) => setHandle(v.replace(/^@/, '').replace(/[^a-z0-9-]/gi, '').toLowerCase())}
          placeholder="yourname"
          prefix="@"
          maxLength={80}
          mono
          hint="Others can find you with @your-handle"
        />
      </div>

      <FRFooter>
        <FRPrimary disabled={!valid} onClick={submit}>Continue</FRPrimary>
      </FRFooter>
    </FRPage>
  );
}

function FRTextField({ label, value, onChange, placeholder, autoFocus, maxLength, prefix, optional, mono, hint }) {
  const focused = !!value;
  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 6, marginBottom: 6, paddingLeft: 4 }}>
        <span style={{ fontSize: 10.5, fontWeight: 600, color: M_FG_DIM, letterSpacing: '0.12em', textTransform: 'uppercase' }}>{label}</span>
        {optional && <span style={{ fontSize: 10, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>· optional</span>}
      </div>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 6,
        padding: '13px 14px', background: M_SURFACE,
        border: '1px solid ' + (focused ? 'rgba(96,165,250,0.4)' : M_BORDER_SOFT),
        borderRadius: 14, transition: 'border 160ms',
      }}>
        {prefix && <span style={{ color: M_ACCENT_B, fontWeight: 600, fontSize: 15, fontFamily: 'JetBrains Mono, monospace' }}>{prefix}</span>}
        <input
          autoFocus={autoFocus}
          maxLength={maxLength}
          value={value} onChange={e => onChange(e.target.value)}
          placeholder={placeholder}
          style={{
            flex: 1, background: 'transparent', border: 0, outline: 0,
            color: M_FG, fontSize: 15,
            fontFamily: mono ? 'JetBrains Mono, monospace' : 'inherit',
            minWidth: 0,
          }}
        />
      </div>
      {hint && <div style={{ fontSize: 11, color: M_FG_DIM, marginTop: 6, paddingLeft: 4 }}>{hint}</div>}
    </div>
  );
}

// ── 4. LOADING ───────────────────────────────────────────────
function FRLoading({ onNext }) {
  const stepDefs = [
    'Encrypting with your password',
    'Generating identity keys',
    'Registering with the network',
    'Connecting mediator',
  ];
  const [stepIdx, setStepIdx] = React.useState(0);
  const [reassureIdx, setReassureIdx] = React.useState(0);
  const reassures = [
    'This usually takes a few seconds…',
    'Strong cryptography, every time.',
    'Almost there — securing your keys.',
  ];

  React.useEffect(() => {
    const t1 = setInterval(() => setReassureIdx(i => (i + 1) % reassures.length), 2400);
    const advance = (i) => {
      if (i >= stepDefs.length) { setTimeout(onNext, 600); return; }
      setStepIdx(i);
      setTimeout(() => advance(i + 1), 1300);
    };
    advance(1);
    return () => clearInterval(t1);
  }, []);

  return (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column', padding: '60px 28px 40px', alignItems: 'stretch' }}>
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
        {/* spinner orbit */}
        <div style={{ display: 'flex', justifyContent: 'center', marginBottom: 32 }}>
          <div style={{ position: 'relative', width: 96, height: 96 }}>
            <div style={{
              position: 'absolute', inset: 0, borderRadius: '50%',
              border: '2px solid rgba(96,165,250,0.10)',
            }}/>
            <div style={{
              position: 'absolute', inset: 0, borderRadius: '50%',
              border: '2px solid transparent',
              borderTopColor: M_ACCENT, borderRightColor: M_ACCENT_B,
              animation: 'frSpin 1.4s linear infinite',
            }}/>
            <div style={{
              position: 'absolute', inset: 18, borderRadius: '50%',
              background: 'radial-gradient(closest-side, rgba(96,165,250,0.25), transparent 70%)',
              display: 'grid', placeItems: 'center',
            }}>
              <AjnaMark size={40} glow={false}/>
            </div>
            <style>{`@keyframes frSpin { to { transform: rotate(360deg); } }`}</style>
          </div>
        </div>

        <div style={{ textAlign: 'center', marginBottom: 28 }}>
          <div style={{ fontSize: 22, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.02em' }}>Setting up your identity</div>
          <div style={{ fontSize: 13, color: M_FG_MUTED, marginTop: 8, minHeight: 18, transition: 'opacity 200ms' }} key={reassureIdx}>{reassures[reassureIdx]}</div>
        </div>

        <div style={{ background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT, borderRadius: 14, padding: '6px 4px' }}>
          {stepDefs.map((label, i) => {
            const state = i < stepIdx ? 'done' : i === stepIdx ? 'active' : 'idle';
            return (
              <div key={i} style={{
                display: 'flex', alignItems: 'center', gap: 12,
                padding: '11px 12px', borderBottom: i < stepDefs.length - 1 ? '1px solid ' + M_BORDER_SOFT : 'none',
                opacity: state === 'idle' ? 0.45 : 1, transition: 'opacity 200ms',
              }}>
                <div style={{
                  width: 22, height: 22, borderRadius: 11,
                  background: state === 'done' ? 'linear-gradient(135deg, ' + M_ACCENT + ', ' + M_ACCENT_B + ')'
                            : state === 'active' ? 'rgba(96,165,250,0.14)'
                            : 'transparent',
                  border: state === 'idle' ? '1.5px dashed ' + M_BORDER : '0',
                  display: 'grid', placeItems: 'center', flexShrink: 0,
                }}>
                  {state === 'done' && (
                    <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="#0B0C0F" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12.5 10 17 19 7"/></svg>
                  )}
                  {state === 'active' && (
                    <svg width="14" height="14" viewBox="0 0 24 24" style={{ animation: 'frSpin 0.9s linear infinite' }}>
                      <circle cx="12" cy="12" r="9" fill="none" stroke="rgba(96,165,250,0.18)" strokeWidth="2.5"/>
                      <path d="M21 12a9 9 0 0 0-9-9" fill="none" stroke={M_ACCENT_B} strokeWidth="2.5" strokeLinecap="round"/>
                    </svg>
                  )}
                </div>
                <div style={{
                  fontSize: 13.5, fontWeight: state === 'active' ? 600 : 500,
                  color: state === 'done' ? M_FG : state === 'active' ? M_FG : M_FG_MUTED,
                }}>{label}</div>
                {state === 'active' && (
                  <span style={{
                    marginLeft: 'auto', fontSize: 10, color: M_ACCENT_B,
                    fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.08em',
                  }}>RUNNING</span>
                )}
              </div>
            );
          })}
        </div>
      </div>

      <div style={{ textAlign: 'center', fontSize: 10.5, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.08em', textTransform: 'uppercase' }}>
        Ed25519 · X25519 · DID:KEY
      </div>
    </div>
  );
}

// ── 5. SYNC ──────────────────────────────────────────────────
function FRSync({ onNext, onBack }) {
  return (
    <FRPage onBack={onBack}>
      <FRHeader title="Sync with another device?" subtitle="Share bookmarks, history, and tabs. End-to-end encrypted."/>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 12, marginTop: 28 }}>
        <button style={{
          display: 'flex', alignItems: 'center', gap: 14,
          padding: '16px 18px', borderRadius: 16,
          background: 'linear-gradient(135deg, rgba(110,231,183,0.10), rgba(96,165,250,0.10)), ' + M_SURFACE,
          border: '1px solid rgba(96,165,250,0.25)',
          color: M_FG, cursor: 'pointer', textAlign: 'left',
        }}>
          <div style={{
            width: 48, height: 48, borderRadius: 14,
            background: 'rgba(96,165,250,0.14)', color: M_ACCENT_B,
            display: 'grid', placeItems: 'center', flexShrink: 0,
          }}>{MIc.scan({ s: 22 })}</div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 15, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.005em' }}>Scan a QR code</div>
            <div style={{ fontSize: 12, color: M_FG_MUTED, marginTop: 2 }}>Use the camera on this device</div>
          </div>
          <span style={{ color: M_FG_DIM }}><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M9 6l6 6-6 6"/></svg></span>
        </button>

        <button style={{
          display: 'flex', alignItems: 'center', gap: 14,
          padding: '16px 18px', borderRadius: 16,
          background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT,
          color: M_FG, cursor: 'pointer', textAlign: 'left',
        }}>
          <div style={{
            width: 48, height: 48, borderRadius: 14,
            background: 'rgba(110,231,183,0.14)', color: M_ACCENT,
            display: 'grid', placeItems: 'center', flexShrink: 0,
          }}>
            <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><path d="M14 14h3M14 19h3M19 14v3M19 17v4"/></svg>
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 15, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.005em' }}>Show my QR code</div>
            <div style={{ fontSize: 12, color: M_FG_MUTED, marginTop: 2 }}>Pair from another device</div>
          </div>
          <span style={{ color: M_FG_DIM }}><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M9 6l6 6-6 6"/></svg></span>
        </button>
      </div>

      <FRFooter>
        <button onClick={onNext} style={{
          width: '100%', padding: '14px 18px', borderRadius: 14,
          background: 'transparent', border: '1px solid ' + M_BORDER,
          color: M_FG, fontSize: 14.5, fontWeight: 600, fontFamily: 'inherit', cursor: 'pointer',
        }}>Skip for now</button>
        <div style={{ textAlign: 'center', fontSize: 11.5, color: M_FG_DIM, marginTop: 10 }}>
          You can pair anytime in <span style={{ color: M_FG_MUTED }}>Settings &rsaquo; Sync</span>
        </div>
      </FRFooter>
    </FRPage>
  );
}

// ── 6. SUCCESS ───────────────────────────────────────────────
function FRSuccess({ onNext, ctx }) {
  const [copied, setCopied] = React.useState(false);
  const did = 'did:ajna:k1z' + (ctx.handle ? ctx.handle.slice(0, 3) + 'P9' : 'qX7P9') + '7yA';
  const initial = (ctx.name?.trim()?.[0] || 'A').toUpperCase();

  const copy = () => { setCopied(true); setTimeout(() => setCopied(false), 1600); };

  return (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column', padding: '40px 28px 28px', position: 'relative', overflow: 'hidden' }}>
      {/* confetti dots */}
      <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
        {[
          { l: '15%', t: '12%', c: M_ACCENT,   d: 0    },
          { l: '85%', t: '8%',  c: M_ACCENT_B, d: 0.2  },
          { l: '20%', t: '38%', c: '#F472B6',  d: 0.4  },
          { l: '78%', t: '42%', c: '#FBBF24',  d: 0.1  },
          { l: '8%',  t: '58%', c: M_ACCENT_B, d: 0.5  },
          { l: '90%', t: '62%', c: M_ACCENT,   d: 0.3  },
        ].map((p, i) => (
          <div key={i} style={{
            position: 'absolute', left: p.l, top: p.t,
            width: 6, height: 6, borderRadius: 3, background: p.c, opacity: 0.6,
            animation: `frFloat 3s ease-in-out ${p.d}s infinite`,
          }}/>
        ))}
        <style>{`@keyframes frFloat { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }`}</style>
      </div>

      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', textAlign: 'center', gap: 24, position: 'relative', zIndex: 1 }}>
        {/* check ring */}
        <div style={{
          width: 96, height: 96, borderRadius: 48,
          background: 'linear-gradient(135deg, ' + M_ACCENT + ', ' + M_ACCENT_B + ')',
          display: 'grid', placeItems: 'center',
          boxShadow: '0 20px 60px -12px rgba(96,165,250,0.55), inset 0 2px 0 rgba(255,255,255,0.3)',
          animation: 'frPop 600ms cubic-bezier(0.2,1.5,0.3,1) both',
        }}>
          <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#0B0C0F" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12.5 10 17 19 7"/></svg>
          <style>{`@keyframes frPop { from { transform: scale(0.4); opacity: 0; } to { transform: scale(1); opacity: 1; } }`}</style>
        </div>

        <div>
          <div style={{ fontSize: 32, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.03em' }}>You're all set</div>
          <div style={{ fontSize: 13.5, color: M_FG_MUTED, marginTop: 8, maxWidth: 280 }}>
            Share your address to receive messages from anyone on Ajna.
          </div>
        </div>

        {/* name pill */}
        <div style={{
          display: 'inline-flex', alignItems: 'center', gap: 10,
          padding: '8px 16px 8px 8px', borderRadius: 999,
          background: M_SURFACE, border: '1px solid ' + M_BORDER,
        }}>
          <div style={{
            width: 28, height: 28, borderRadius: 14,
            background: 'linear-gradient(135deg, ' + M_ACCENT + ', ' + M_ACCENT_B + ')',
            display: 'grid', placeItems: 'center',
            color: '#0B0C0F', fontSize: 12, fontWeight: 700, fontFamily: 'Geist, Inter, sans-serif',
          }}>{initial}</div>
          <div style={{ fontSize: 14, fontWeight: 600, color: M_FG }}>{ctx.name || 'Your name'}</div>
          {ctx.handle && <span style={{ fontSize: 11.5, color: M_ACCENT_B, fontFamily: 'JetBrains Mono, monospace' }}>@{ctx.handle}</span>}
        </div>

        {/* DID */}
        <div onClick={copy} style={{
          display: 'flex', alignItems: 'center', gap: 10,
          padding: '12px 14px', borderRadius: 12, cursor: 'pointer',
          background: M_SURFACE, border: '1px solid ' + M_BORDER_SOFT,
          maxWidth: 320, width: '100%',
        }}>
          <span style={{ color: M_FG_DIM, flexShrink: 0 }}>{MIc.shield({ s: 14 })}</span>
          <span style={{ flex: 1, fontSize: 12.5, color: M_FG, fontFamily: 'JetBrains Mono, monospace', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', textAlign: 'left' }}>{did}</span>
          <span style={{
            display: 'inline-flex', alignItems: 'center', gap: 4,
            fontSize: 11, fontFamily: 'JetBrains Mono, monospace', fontWeight: 600,
            color: copied ? M_ACCENT : M_FG_MUTED, flexShrink: 0,
          }}>
            {copied ? (
              <>
                <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12.5 10 17 19 7"/></svg>
                COPIED
              </>
            ) : (
              <>
                <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg>
                COPY
              </>
            )}
          </span>
        </div>
      </div>

      <FRPrimary onClick={onNext} icon={
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
      }>Start browsing</FRPrimary>
    </div>
  );
}

// ── Page chrome — back button + scroll body ──────────────────
function FRPage({ children, onBack }) {
  return (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
      <div style={{ padding: '8px 12px', display: 'flex', alignItems: 'center', flexShrink: 0 }}>
        <button onClick={onBack} aria-label="Back" style={{
          width: 40, height: 40, borderRadius: 20,
          background: 'transparent', border: 0, color: M_FG,
          display: 'grid', placeItems: 'center', cursor: 'pointer',
        }}>{MIc.back({ s: 22 })}</button>
      </div>
      <div style={{ flex: 1, overflowY: 'auto', padding: '0 28px 24px', display: 'flex', flexDirection: 'column' }}>
        {children}
      </div>
    </div>
  );
}

function FRHeader({ title, subtitle }) {
  return (
    <div style={{ marginTop: 4 }}>
      <div style={{ fontSize: 28, fontWeight: 600, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.025em', lineHeight: 1.1, color: M_FG }}>{title}</div>
      <div style={{ marginTop: 8, fontSize: 14, color: M_FG_MUTED, lineHeight: 1.45 }}>{subtitle}</div>
    </div>
  );
}

function FRFooter({ children }) {
  return (
    <div style={{ marginTop: 'auto', paddingTop: 24 }}>
      {children}
    </div>
  );
}

// ── Progress bar ─────────────────────────────────────────────
function FRProgress({ idx, total }) {
  const pct = ((idx + 1) / total) * 100;
  return (
    <div style={{ position: 'absolute', top: 50, left: 0, right: 0, height: 2, background: 'var(--m-tint)', zIndex: 9 }}>
      <div style={{
        height: '100%', width: pct + '%',
        background: 'linear-gradient(90deg, ' + M_ACCENT + ', ' + M_ACCENT_B + ')',
        transition: 'width 360ms cubic-bezier(0.2,0.8,0.2,1)',
      }}/>
    </div>
  );
}

// ── Flow shell ───────────────────────────────────────────────
function MFirstRunFlow({ onComplete }) {
  const [idx, setIdx] = React.useState(0);
  const [ctx, setCtx] = React.useState({});
  const next = () => setIdx(i => Math.min(i + 1, FR_STEPS.length - 1));
  const back = () => setIdx(i => Math.max(i - 1, 0));
  const finish = () => onComplete && onComplete();
  // Skip identity setup entirely — chat / sync / mesh stay locked until the
  // user completes setup from the Messages gate (MIdentityGate).
  const skipIdentity = () => { try { localStorage.setItem('ajna-identity-ready', '0'); } catch {} finish(); };
  const completeAll = () => { try { localStorage.setItem('ajna-identity-ready', '1'); } catch {} finish(); };

  // for loading screen, advance is automatic
  const screen = FR_STEPS[idx].id;

  return (
    <MobileScreen>
      <MStatusBar/>
      {screen !== 'welcome' && screen !== 'default' && screen !== 'loading' && screen !== 'success' && <FRProgress idx={idx} total={FR_STEPS.length}/>}
      <div style={{ flex: 1, position: 'relative', display: 'flex', flexDirection: 'column' }}>
        {screen === 'welcome'  && <FRWelcome  onNext={next} onSkipToImport={next}/>}
        {screen === 'default'  && <FRDefaultBrowser onNext={next} onSkip={next}/>}
        {screen === 'password' && <FRPassword onNext={next} onBack={back} ctx={ctx} setCtx={setCtx} onUseExisting={next}/>}
        {screen === 'profile'  && <FRProfile  onNext={next} onBack={back} ctx={ctx} setCtx={setCtx}/>}
        {screen === 'loading'  && <FRLoading  onNext={next}/>}
        {screen === 'sync'     && <FRSync     onNext={next} onBack={back}/>}
        {screen === 'success'  && <FRSuccess  onNext={completeAll} ctx={ctx}/>}

        {/* Skip identity — available on the password + profile steps */}
        {(screen === 'password' || screen === 'profile') && (
          <button onClick={skipIdentity} style={{
            position: 'absolute', top: 2, right: 18, zIndex: 5,
            background: 'transparent', border: 0, color: M_ACCENT_B,
            fontSize: 13.5, fontWeight: 500, fontFamily: 'inherit', cursor: 'pointer', padding: '6px 2px',
          }}>Skip</button>
        )}
      </div>
      <MHomeIndicator/>
    </MobileScreen>
  );
}

// ── Default-browser step — Opera-style promo card with Skip ─────
function FRDefaultBrowser({ onNext, onSkip }) {
  const rows = [{ mock: true }, { ajna: true }, { mock: true }, { mock: true }];
  const tile = (d) => (
    <div style={{ width: 44, height: 44, borderRadius: 13, background: 'rgba(167,139,250,0.16)', border: '1px solid rgba(167,139,250,0.3)', color: '#C4B5FD', display: 'grid', placeItems: 'center' }}>{d}</div>
  );
  return (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column', padding: '0 24px 26px', overflowY: 'auto' }}>
      <div style={{ display: 'flex', justifyContent: 'flex-end', padding: '8px 0 2px' }}>
        <button onClick={onSkip} style={{ background: 'transparent', border: 0, color: M_ACCENT_B, fontSize: 14, fontWeight: 500, fontFamily: 'inherit', cursor: 'pointer', padding: '6px 2px' }}>Skip</button>
      </div>

      {/* Illustration — tilted accent card + default-picker sheet */}
      <div style={{ position: 'relative', height: 290, margin: '6px 0 22px', flexShrink: 0 }}>
        <div style={{ position: 'absolute', left: 34, right: 8, top: 12, bottom: 12, borderRadius: 22, background: 'linear-gradient(135deg, color-mix(in oklch, ' + M_ACCENT + ' 30%, transparent), color-mix(in oklch, ' + M_ACCENT_B + ' 34%, transparent))', opacity: 0.55 }}/>
        <div style={{ position: 'absolute', left: 6, top: 30, display: 'flex', flexDirection: 'column', gap: 14 }}>
          {tile(<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M10 13a5 5 0 0 0 7.5.5l3-3a5 5 0 0 0-7-7l-1.7 1.7"/><path d="M14 11a5 5 0 0 0-7.5-.5l-3 3a5 5 0 0 0 7 7l1.7-1.7"/></svg>)}
          {tile(<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M12 2 4 5v7c0 5 3.5 8.5 8 10 4.5-1.5 8-5 8-10V5z"/></svg>)}
          {tile(<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>)}
        </div>
        <div className="glass" style={{ position: 'absolute', left: 64, right: 0, top: 24, bottom: 24, borderRadius: 18, padding: '16px 18px 12px', display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
          <AjnaMark size={28} glow={false}/>
          <div style={{ fontSize: 13, fontWeight: 600, color: M_FG, textAlign: 'center', margin: '8px 0 13px', fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.01em', lineHeight: 1.35 }}>Set Ajna as your default browser?</div>
          <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 9 }}>
            {rows.map((r, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 9 }}>
                {r.ajna
                  ? <><AjnaMark size={18} glow={false}/><span style={{ fontSize: 12, fontWeight: 600, color: M_FG, fontFamily: 'Geist, Inter, sans-serif' }}>Ajna</span></>
                  : <><span style={{ width: 16, height: 16, borderRadius: 8, background: 'rgba(255,255,255,0.10)', flexShrink: 0 }}/><span style={{ width: 74, height: 8, borderRadius: 4, background: 'rgba(255,255,255,0.10)' }}/></>}
                <span style={{ flex: 1 }}/>
                <span style={{ width: 15, height: 15, borderRadius: 8, flexShrink: 0, border: r.ajna ? 0 : '1.5px solid rgba(255,255,255,0.18)', background: r.ajna ? 'linear-gradient(135deg, ' + M_ACCENT + ', ' + M_ACCENT_B + ')' : 'transparent', display: 'grid', placeItems: 'center' }}>
                  {r.ajna && <span style={{ width: 5, height: 5, borderRadius: 3, background: '#0B0C0F' }}/>}
                </span>
              </div>
            ))}
          </div>
        </div>
      </div>

      <div style={{ fontSize: 28, fontWeight: 700, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.03em', lineHeight: 1.12, color: M_FG }}>Browse on your terms</div>
      <div style={{ fontSize: 14, color: M_FG_MUTED, lineHeight: 1.55, marginTop: 10 }}>Set Ajna as your default browser so every link opens private, encrypted, and mesh-ready.</div>

      {/* Why Ajna — feature rows with Ajna ✓ vs Chrome — */}
      <div style={{ marginTop: 18, border: '1px solid ' + M_BORDER_SOFT, borderRadius: 16, overflow: 'hidden', flexShrink: 0, opacity: 1 }}>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 46px 56px', alignItems: 'center', padding: '9px 14px', background: '#FFFFFF00', borderBottom: '1px solid ' + M_BORDER_SOFT }}>
          <span/>
          <span style={{ display: 'grid', placeItems: 'center' }}><AjnaMark size={15} glow={false}/></span>
          <span style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 5 }}><img src="src/assets/chrome-logo.svg" alt="Chrome" style={{ width: 15, height: 15 }}/></span>
        </div>
        {[
          { l: 'Ad blocker', ic: <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M12 2 4 5v7c0 5 3.5 8.5 8 10 4.5-1.5 8-5 8-10V5z"/><path d="m9 12 2 2 4-4"/></svg>, color: M_ACCENT },
          { l: 'Mesh messaging', ic: MIc.mesh({ s: 15 }), color: '#A78BFA' },
          { l: 'Your DID identity', ic: <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="8" r="4"/><path d="M5 21c0-4 3-6 7-6s7 2 7 6"/></svg>, color: M_ACCENT_B },
          { l: 'Interactive UI', ic: <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M5.6 18.4l2.1-2.1M16.3 7.7l2.1-2.1"/><circle cx="12" cy="12" r="3"/></svg>, color: '#FBBF24' },
        ].map((f, i, arr) => (
          <div key={f.l} style={{ display: 'grid', gridTemplateColumns: '1fr 46px 56px', alignItems: 'center', padding: '10px 14px', borderBottom: i === arr.length - 1 ? 'none' : '1px solid ' + M_BORDER_SOFT }}>
            <span style={{ display: 'flex', alignItems: 'center', gap: 9 }}>
              <span style={{ color: f.color, display: 'grid', placeItems: 'center', flexShrink: 0 }}>{f.ic}</span>
              <span style={{ fontSize: 12.5, fontWeight: 600, color: M_FG, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.01em' }}>{f.l}</span>
            </span>
            <span style={{ display: 'grid', placeItems: 'center' }}>
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke={M_ACCENT} strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="m4 12.5 5 5L20 6.5"/></svg>
            </span>
            <span style={{ display: 'grid', placeItems: 'center' }}>
              <span style={{ width: 10, height: 2, borderRadius: 1, background: 'rgba(255,255,255,0.16)' }}/>
            </span>
          </div>
        ))}
      </div>

      <div style={{ flex: 1 }}/>
      <button onClick={onNext} style={{
        width: '100%', padding: '15px 0', borderRadius: 999, border: 0,
        background: 'linear-gradient(135deg, ' + M_ACCENT + ', ' + M_ACCENT_B + ')',
        color: '#0B0C0F', fontSize: 15, fontWeight: 700, fontFamily: 'Geist, Inter, sans-serif',
        letterSpacing: '-0.01em', cursor: 'pointer', marginTop: 20, flexShrink: 0,
      }}>Set Ajna as default</button>
    </div>
  );
}

// ── Identity gate — shown on Messages/Chat when setup was skipped ──
function MIdentityGate({ onSetup }) {
  const locked = [
    { l: 'Chat & messaging', s: 'End-to-end encrypted DMs', ic: MIc.chat },
    { l: 'Mesh & sync',      s: 'Peers, devices, shared groups', ic: MIc.mesh },
    { l: 'Calls',            s: 'DIDComm voice & video', ic: MIc.calls },
  ];
  return (
    <div style={{ height: '100%', overflowY: 'auto', padding: '32px 24px 110px', boxSizing: 'border-box', display: 'flex', flexDirection: 'column' }}>
      <div style={{ textAlign: 'center', margin: '26px 0 24px' }}>
        <div style={{ position: 'relative', width: 96, height: 96, margin: '0 auto 20px', display: 'grid', placeItems: 'center' }}>
          {[0, 1].map(i => <div key={i} style={{ position: 'absolute', inset: i * 14, borderRadius: '50%', border: '1px solid rgba(96,165,250,' + (0.26 - i * 0.1) + ')' }}/>)}
          <div style={{ width: 56, height: 56, borderRadius: 18, background: 'rgba(96,165,250,0.14)', border: '1px solid rgba(96,165,250,0.3)', color: M_ACCENT_B, display: 'grid', placeItems: 'center' }}>
            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
          </div>
        </div>
        <div style={{ fontSize: 22, fontWeight: 700, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.025em', color: M_FG }}>Set up your identity</div>
        <div style={{ fontSize: 13, color: M_FG_MUTED, lineHeight: 1.55, maxWidth: 280, margin: '10px auto 0' }}>
          You skipped setup. Messaging needs your keys — a password, a name, and a handle. Takes about a minute.
        </div>
      </div>

      <div className="glass" style={{ borderRadius: 14, overflow: 'hidden', marginBottom: 22 }}>
        {locked.map((f, i) => (
          <div key={f.l} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '13px 14px', borderTop: i === 0 ? 0 : '1px solid var(--glass-border)' }}>
            <span style={{ width: 32, height: 32, borderRadius: 9, background: 'rgba(255,255,255,0.05)', color: M_FG_DIM, display: 'grid', placeItems: 'center', flexShrink: 0 }}>{f.ic({ s: 15 })}</span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 13, fontWeight: 500, color: M_FG, fontFamily: 'Geist, Inter, sans-serif', letterSpacing: '-0.01em' }}>{f.l}</div>
              <div style={{ fontSize: 10.5, color: M_FG_DIM, marginTop: 1 }}>{f.s}</div>
            </div>
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="var(--m-fg-dim)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
          </div>
        ))}
      </div>

      <button onClick={onSetup} style={{
        width: '100%', padding: '14px 0', borderRadius: 999, border: 0,
        background: 'linear-gradient(135deg, ' + M_ACCENT + ', ' + M_ACCENT_B + ')',
        color: '#0B0C0F', fontSize: 14.5, fontWeight: 700, fontFamily: 'Geist, Inter, sans-serif',
        letterSpacing: '-0.01em', cursor: 'pointer',
      }}>Set up now</button>
      <div style={{ textAlign: 'center', fontSize: 10.5, color: M_FG_DIM, marginTop: 12, fontFamily: 'JetBrains Mono, monospace' }}>Keys never leave this device</div>
    </div>
  );
}

// ── In-app identity setup — password → profile → keygen → done ───
function MIdentitySetupFlow({ onComplete, onCancel }) {
  const steps = ['password', 'profile', 'loading', 'success'];
  const [idx, setIdx] = React.useState(0);
  const [ctx, setCtx] = React.useState({});
  const screen = steps[idx];
  const next = () => {
    if (idx === steps.length - 1) { try { localStorage.setItem('ajna-identity-ready', '1'); } catch {} onComplete && onComplete(); }
    else setIdx(i => i + 1);
  };
  const back = () => idx === 0 ? (onCancel && onCancel()) : setIdx(i => i - 1);
  return (
    <div style={{ position: 'absolute', inset: 0, zIndex: 70, background: M_BG, display: 'flex', flexDirection: 'column' }}>
      {(screen === 'password' || screen === 'profile') && (
        <div style={{ display: 'flex', alignItems: 'center', padding: '12px 18px 0' }}>
          <button onClick={onCancel} aria-label="Cancel" style={{ background: 'transparent', border: 0, color: M_FG_MUTED, fontSize: 13, fontFamily: 'inherit', cursor: 'pointer', padding: '4px 0' }}>Cancel</button>
          <div style={{ flex: 1 }}/>
          <div style={{ fontSize: 10.5, color: M_FG_DIM, fontFamily: 'JetBrains Mono, monospace' }}>Step {idx + 1} of 2</div>
        </div>
      )}
      <div style={{ flex: 1, position: 'relative', display: 'flex', flexDirection: 'column' }}>
        {screen === 'password' && <FRPassword onNext={next} onBack={back} ctx={ctx} setCtx={setCtx}/>}
        {screen === 'profile'  && <FRProfile  onNext={next} onBack={back} ctx={ctx} setCtx={setCtx}/>}
        {screen === 'loading'  && <FRLoading  onNext={next}/>}
        {screen === 'success'  && <FRSuccess  onNext={next} ctx={ctx}/>}
      </div>
    </div>
  );
}

Object.assign(window, { MFirstRunFlow, FR_STEPS, FRDefaultBrowser, MIdentityGate, MIdentitySetupFlow });
