// EVERSEAL — Auth VC Flow screens
// Requires icons.js (esIcon) + ios-frame.jsx (IOSDevice) + design system CSS

const AI = ({ n, s = 24, sw = 1.8, style }) => (
  <span style={{ display: 'inline-flex', ...style }}
        dangerouslySetInnerHTML={{ __html: esIcon(n, { size: s, sw }) }} />
);

// ── brand marks (full color, not currentColor) ──────────────
function BrandIcon({ kind }) {
  const marks = {
    // Apple logo — official silhouette, centered in 24 grid
    apple: (
      <svg viewBox="0 0 24 24" width="26" height="26" aria-hidden="true" style={{ display: 'block', marginTop: -1 }}>
        <path fill="#fff" d="M17.05 12.04c-.03-2.6 2.12-3.84 2.22-3.91-1.21-1.77-3.1-2.02-3.77-2.04-1.6-.16-3.13.94-3.95.94-.81 0-2.07-.92-3.4-.9-1.75.03-3.36 1.02-4.26 2.58-1.82 3.16-.46 7.83 1.3 10.4.86 1.25 1.89 2.66 3.24 2.61 1.3-.05 1.79-.84 3.36-.84 1.57 0 2.01.84 3.39.82 1.4-.03 2.29-1.28 3.15-2.54.99-1.45 1.4-2.86 1.42-2.93-.03-.02-2.72-1.05-2.75-4.16zM14.62 4.84c.72-.87 1.2-2.08 1.07-3.28-1.03.04-2.28.69-3.02 1.55-.66.77-1.24 2-1.08 3.18 1.15.09 2.32-.58 3.03-1.45z"/>
      </svg>
    ),
    // Google "G" — official 4-color mark, 48 grid
    google: (
      <svg viewBox="0 0 48 48" width="26" height="26" aria-hidden="true" style={{ display: 'block' }}>
        <path fill="#4285F4" d="M47.5 24.5c0-1.6-.14-3.2-.43-4.7H24v9h13.2c-.57 3-2.3 5.6-4.9 7.3v6h7.9c4.6-4.3 7.3-10.6 7.3-17.6z"/>
        <path fill="#34A853" d="M24 48c6.5 0 11.9-2.15 15.9-5.85l-7.9-6c-2.2 1.48-5 2.35-8 2.35-6.15 0-11.36-4.15-13.22-9.74H2.6v6.18C6.6 42.6 14.7 48 24 48z"/>
        <path fill="#FBBC05" d="M10.78 28.76c-.48-1.4-.74-2.9-.74-4.45s.27-3.05.74-4.45v-6.18H2.6A23.97 23.97 0 0 0 0 24.3c0 3.9.93 7.55 2.6 10.62l8.18-6.16z"/>
        <path fill="#EA4335" d="M24 9.55c3.47 0 6.6 1.2 9.05 3.54l6.78-6.78C35.9 2.43 30.5 0 24 0 14.7 0 6.6 5.4 2.6 13.68l8.18 6.18C12.64 13.7 17.85 9.55 24 9.55z"/>
      </svg>
    ),
    // Naver "N"
    naver: (
      <svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true" style={{ display: 'block' }}>
        <path fill="#fff" d="M15.13 12.62 8.78 3.5H3.5v17h5.37v-9.12l6.35 9.12h5.28v-17h-5.37z"/>
      </svg>
    ),
    // Kakao speech bubble
    kakao: (
      <svg viewBox="0 0 24 24" width="26" height="26" aria-hidden="true" style={{ display: 'block', marginTop: 1 }}>
        <path fill="#3C1E1E" d="M12 4C7.03 4 3 7.16 3 11.05c0 2.5 1.68 4.7 4.2 5.94-.18.65-.67 2.43-.77 2.81-.12.46.17.45.36.33.15-.1 2.36-1.6 3.32-2.27.6.09 1.22.13 1.69.13 4.97 0 9-3.16 9-7.05S16.97 4 12 4z"/>
      </svg>
    ),
  };
  const bg = { apple: '#000', google: '#fff', naver: '#03C75A', kakao: '#FEE500' };
  return (
    <button style={{
      width: 56, height: 56, borderRadius: '50%', flexShrink: 0,
      border: kind === 'google' ? '1px solid var(--es-separator)' : 'none',
      background: bg[kind], display: 'flex', alignItems: 'center', justifyContent: 'center',
      cursor: 'pointer', padding: 0, boxShadow: 'var(--es-shadow-1)',
    }}>{marks[kind]}</button>
  );
}

// shared bare nav (back button only)
function BareNav({ onBack, dark, right }) {
  return (
    <div style={{ paddingTop: 50, flexShrink: 0, display: 'flex', alignItems: 'center',
      justifyContent: 'space-between', padding: '50px 8px 0', position: 'relative', zIndex: 5 }}>
      <button className="es-navbar__btn" style={{ color: dark ? '#fff' : 'var(--es-ink)' }} onClick={onBack}>
        <AI n="chevron-left" s={26} />
      </button>
      <div style={{ display: 'flex', gap: 4 }}>{right}</div>
    </div>
  );
}

const Wordmark = ({ light, size = 'lg' }) => (
  <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
    <img src={light ? 'assets/everseal-mark-platinum.png' : 'assets/everseal-mark-green.png'}
      alt="" style={{ height: size === 'lg' ? 32 : 26, width: 'auto', display: 'block' }} />
    <span style={{ fontFamily: 'var(--es-serif)', fontSize: size === 'lg' ? 19 : 16, letterSpacing: '0.26em', textIndent: '0.26em',
      textTransform: 'uppercase', color: light ? '#fff' : 'var(--es-green)' }}>EVERSEAL</span>
  </div>
);

// ─────────────────────────────────────────────────────────
// 1) IntroViewController — single image-based intro
// ─────────────────────────────────────────────────────────
function SealMark({ size = 96 }) {
  // iconographic "봉인 & 인증" emblem — gold ring + NFC waves + shield seal
  return (
    <div style={{ position: 'relative', width: size, height: size }}>
      <span style={{ position: 'absolute', inset: 0, borderRadius: '50%',
        border: '1.5px solid rgba(184,153,122,0.35)' }} />
      <span style={{ position: 'absolute', inset: 8, borderRadius: '50%',
        border: '1px dashed rgba(184,153,122,0.5)' }} />
      <span style={{ position: 'absolute', inset: 16, borderRadius: '50%',
        background: 'radial-gradient(circle at 50% 35%, #2c4a3a, #142a20)',
        display: 'grid', placeItems: 'center',
        boxShadow: '0 0 32px rgba(184,153,122,0.25)' }}>
        <img src="assets/everseal-mark-platinum.png" alt="" style={{ width: size * 0.4, height: 'auto' }} />
      </span>
    </div>
  );
}

function IntroVC() {
  // original, copyright-free abstract artwork composed from gradients
  const blob = (style) => (
    <span style={{ position: 'absolute', borderRadius: '50%', filter: 'blur(14px)', ...style }} />
  );
  const steps = [['nfc', '태그'], ['seal', '등록'], ['shield-check', '인증']];
  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', color: '#fff', overflow: 'hidden',
      background: 'linear-gradient(180deg, #16281e 0%, #122017 100%)' }}>
      <span style={{ position: 'absolute', inset: 0, background:
        'radial-gradient(80% 55% at 22% 28%, rgba(184,153,122,0.28) 0%, rgba(184,153,122,0) 50%)',
        pointerEvents: 'none' }} />

      {/* wordmark — extra top breathing room */}
      <div style={{ paddingTop: 78, display: 'flex', justifyContent: 'center', flexShrink: 0, zIndex: 2 }}>
        <Wordmark light />
      </div>

      {/* framed original artwork */}
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center',
        justifyContent: 'center', gap: 26, padding: '28px 24px 0', zIndex: 2 }}>
        <div style={{ position: 'relative', width: 200, padding: 12, borderRadius: 7,
          background: 'linear-gradient(150deg,#3A332455,#142a20)', boxShadow: '0 30px 70px rgba(0,0,0,0.55)',
          border: '1px solid rgba(184,153,122,0.45)' }}>
          <div style={{ position: 'relative', width: '100%', height: 230, borderRadius: 3, overflow: 'hidden',
            background: 'linear-gradient(165deg,#16302F 0%,#0E1C1C 100%)' }}>
            <img src="assets/intro-poodle.jpg" alt="작품" style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
          </div>
          {/* authenticity emblem clipped to corner */}
          <div style={{ position: 'absolute', right: -16, bottom: -16 }}>
            <div style={{ width: 52, height: 52, borderRadius: '50%', background: '#122017',
              border: '1px solid rgba(184,153,122,0.6)', display: 'grid', placeItems: 'center',
              color: 'var(--es-gold)', boxShadow: '0 6px 18px rgba(0,0,0,0.5)' }}>
              <AI n="seal" s={26} sw={1.6} />
            </div>
          </div>
        </div>

        {/* 봉인 & 인증 process visualization */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
          {steps.map(([icon, label], i) => (
            <React.Fragment key={label}>
              <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6 }}>
                <span style={{ width: 40, height: 40, borderRadius: '50%',
                  background: 'rgba(184,153,122,0.14)', border: '1px solid rgba(184,153,122,0.4)',
                  display: 'grid', placeItems: 'center', color: 'var(--es-gold)' }}>
                  <AI n={icon} s={20} />
                </span>
                <span className="es-caption-2" style={{ color: 'rgba(255,255,255,0.7)', letterSpacing: '0.5px' }}>{label}</span>
              </div>
              {i < steps.length - 1 && (
                <span style={{ color: 'rgba(184,153,122,0.55)', marginBottom: 18 }}><AI n="chevron-right" s={16} /></span>
              )}
            </React.Fragment>
          ))}
        </div>
      </div>

      {/* bottom content */}
      <div style={{ flexShrink: 0, padding: '20px 24px 80px', display: 'flex', flexDirection: 'column', gap: 16, zIndex: 2 }}>
        <div>
          <div className="es-title-1" style={{ color: '#fff', lineHeight: 1.14, fontSize: 26 }}>
            정품을 인증하고<br/>가치를 거래하다
          </div>
          <p className="es-callout" style={{ color: 'rgba(255,255,255,0.6)', marginTop: 10, lineHeight: 1.5, fontSize: 16 }}>
            NFC로 쉽고 빠르게 정품을 등록하고, 전 세계 어디서나 안전하게 거래하세요.
          </p>
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          <button className="es-btn es-btn--primary es-btn--block">시작하기</button>
          <button className="es-btn es-btn--block" style={{ background: 'rgba(255,255,255,0.12)', color: '#fff' }}>
            <AI n="nfc" s={19} />로그인 없이 정품 확인
          </button>
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────
// 2) SignInViewController
// ─────────────────────────────────────────────────────────
function SignInVC() {
  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', color: 'var(--es-ink)', background: 'var(--es-bg)' }}>
      <div style={{ paddingTop: 50 }} />
      <div style={{ flex: 1, overflow: 'auto', padding: '24px 24px 28px' }}>
        <div style={{ marginBottom: 28 }}><Wordmark /></div>
        <div className="es-title-1">다시 오신 걸 환영합니다</div>

        <div style={{ display: 'flex', flexDirection: 'column', gap: 14, marginTop: 26 }}>
          <div className="es-field">
            <label className="es-label">이메일</label>
            <div className="es-input-group">
              <span className="es-input-icon"><AI n="person" s={20} /></span>
              <input className="es-input" placeholder="you@example.com" />
            </div>
          </div>
          <div className="es-field">
            <label className="es-label">비밀번호</label>
            <div className="es-input-group">
              <span className="es-input-icon"><AI n="lock" s={20} /></span>
              <input className="es-input" type="password" placeholder="••••••••" />
            </div>
          </div>
          <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
            <span className="es-subhead" style={{ color: 'var(--es-blue)', fontWeight: 600 }}>비밀번호 찾기</span>
          </div>
          <button className="es-btn es-btn--primary es-btn--block" style={{ marginTop: 2 }}>로그인</button>
        </div>

        {/* divider */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 12, margin: '24px 0' }}>
          <div style={{ flex: 1, height: '0.5px', background: 'var(--es-separator-strong)' }} />
          <span className="es-footnote es-ink-3">소셜 계정으로 로그인</span>
          <div style={{ flex: 1, height: '0.5px', background: 'var(--es-separator-strong)' }} />
        </div>
        <div style={{ display: 'flex', justifyContent: 'center', gap: 16 }}>
          <BrandIcon kind="apple" />
          <BrandIcon kind="google" />
          <BrandIcon kind="naver" />
          <BrandIcon kind="kakao" />
        </div>
      </div>

      {/* footer */}
      <div style={{ flexShrink: 0, padding: '14px 24px 34px', borderTop: '0.5px solid var(--es-separator)',
        display: 'flex', flexDirection: 'column', gap: 12, alignItems: 'center' }}>
        <div className="es-subhead es-ink-2">
          계정이 없으신가요? <span style={{ color: 'var(--es-blue)', fontWeight: 600 }}>회원가입</span>
        </div>
        <button className="es-btn es-btn--ghost" style={{ color: 'var(--es-gold)' }}>
          <AI n="nfc" s={19} />로그인 없이 정품 확인하기
        </button>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────
// 2b) SignInViewController (이메일 전용, 소셜 로그인 제외)
// ─────────────────────────────────────────────────────────
function SignInEmailOnlyVC() {
  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', color: 'var(--es-ink)', background: 'var(--es-bg)' }}>
      <div style={{ paddingTop: 50 }} />
      <div style={{ flex: 1, overflow: 'auto', padding: '24px 24px 28px' }}>
        <div style={{ marginBottom: 28 }}><Wordmark /></div>
        <div className="es-title-1">다시 오신 걸 환영합니다</div>

        <div style={{ display: 'flex', flexDirection: 'column', gap: 14, marginTop: 26 }}>
          <div className="es-field">
            <label className="es-label">이메일</label>
            <div className="es-input-group">
              <span className="es-input-icon"><AI n="person" s={20} /></span>
              <input className="es-input" placeholder="you@example.com" />
            </div>
          </div>
          <div className="es-field">
            <label className="es-label">비밀번호</label>
            <div className="es-input-group">
              <span className="es-input-icon"><AI n="lock" s={20} /></span>
              <input className="es-input" type="password" placeholder="••••••••" />
            </div>
          </div>
          <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
            <span className="es-subhead" style={{ color: 'var(--es-blue)', fontWeight: 600 }}>비밀번호 찾기</span>
          </div>
          <button className="es-btn es-btn--primary es-btn--block" style={{ marginTop: 2 }}>로그인</button>
        </div>
      </div>

      {/* footer */}
      <div style={{ flexShrink: 0, padding: '14px 24px 34px', borderTop: '0.5px solid var(--es-separator)',
        display: 'flex', flexDirection: 'column', gap: 12, alignItems: 'center' }}>
        <div className="es-subhead es-ink-2">
          계정이 없으신가요? <span style={{ color: 'var(--es-blue)', fontWeight: 600 }}>회원가입</span>
        </div>
        <button className="es-btn es-btn--ghost" style={{ color: 'var(--es-gold)' }}>
          <AI n="nfc" s={19} />로그인 없이 정품 확인하기
        </button>
      </div>
    </div>
  );
}

// ── iOS-style bottom sheet: "지갑이 없으신가요?" → 대신 생성 ──
function WalletCreateSheet({ state, addr, onCreate, onClose, onUse }) {
  const open = state !== 'closed';
  const busy = state === 'creating';
  const features = [
    ['plus', '담당자가 발급', '가입 후 EverSeal이 대신 만들어요'],
    ['shield-check', '안전한 보관', '키는 기기에 암호화 저장'],
    ['wallet', '바로 사용', '발급 완료 후 주소 자동 입력'],
  ];
  return (
    <React.Fragment>
      <style>{'@keyframes esSheetSpin{to{transform:rotate(360deg)}}'}</style>
      {/* scrim */}
      <div onClick={() => !busy && onClose()} style={{
        position: 'absolute', inset: 0, zIndex: 60, background: 'rgba(18,32,23,0.42)',
        opacity: open ? 1 : 0, pointerEvents: open ? 'auto' : 'none', transition: 'opacity .28s ease',
      }} />
      {/* sheet */}
      <div style={{
        position: 'absolute', left: 0, right: 0, bottom: 0, zIndex: 61,
        background: 'var(--es-bg)', borderTopLeftRadius: 22, borderTopRightRadius: 22,
        boxShadow: '0 -12px 44px rgba(0,0,0,0.20)', padding: '10px 30px 36px',
        transform: open ? 'translateY(0)' : 'translateY(102%)',
        transition: 'transform .38s cubic-bezier(.32,.72,0,1)',
      }}>
        <div style={{ width: 38, height: 5, borderRadius: 3, background: 'var(--es-fill-press)', margin: '0 auto 20px' }} />

        {state === 'done' ? (
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center' }}>
            <div style={{ width: 60, height: 60, borderRadius: '50%', background: 'var(--es-success-soft, #E4F0E8)',
              color: 'var(--es-success)', display: 'grid', placeItems: 'center', marginBottom: 16 }}>
              <AI n="check" s={30} />
            </div>
            <div className="es-title-2">지갑이 생성되었어요</div>
            <p className="es-subhead es-ink-2" style={{ marginTop: 8, lineHeight: 1.5 }}>
              EverSeal가 새 XRPL 지갑을 만들었어요.<br />키는 기기에 안전하게 보관됩니다.
            </p>
            <div style={{ width: '100%', background: 'var(--es-surface-2)', border: '0.5px solid var(--es-separator)',
              borderRadius: 'var(--es-r-md)', padding: '12px 14px', marginTop: 18, display: 'flex', alignItems: 'center', gap: 10 }}>
              <AI n="wallet" s={18} style={{ color: 'var(--es-bronze)', flexShrink: 0 }} />
              <span className="es-mono es-footnote" style={{ wordBreak: 'break-all', textAlign: 'left', lineHeight: 1.45 }}>{addr}</span>
            </div>
            <button className="es-btn es-btn--primary es-btn--block" style={{ marginTop: 20 }} onClick={onUse}>이 지갑 사용하기</button>
          </div>
        ) : busy ? (
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', padding: '14px 0 8px' }}>
            <div style={{ width: 44, height: 44, borderRadius: '50%', border: '3px solid var(--es-fill)',
              borderTopColor: 'var(--es-gold)', animation: 'esSheetSpin .8s linear infinite', marginBottom: 18 }} />
            <div className="es-headline">지갑을 만들고 있어요</div>
            <p className="es-subhead es-ink-3" style={{ marginTop: 6 }}>XRPL 원장에 안전하게 생성 중…</p>
          </div>
        ) : (
          <React.Fragment>
            <div style={{ width: 56, height: 56, borderRadius: 16, background: 'var(--es-green-soft, #E3ECE5)',
              color: 'var(--es-green-deep, #16281e)', display: 'grid', placeItems: 'center', marginTop: 32, marginBottom: 16 }}>
              <AI n="wallet" s={28} />
            </div>
            <div className="es-title-2">지갑 주소를 모르시나요?</div>
            <p className="es-subhead es-ink-2" style={{ marginTop: 8, lineHeight: 1.55 }}>
              지금 없어도 괜찮아요. <b style={{ color: 'var(--es-ink)' }}>가입 후 담당자가 지갑 발급을 도와드려요.</b>
            </p>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 4, marginTop: 18 }}>
              {features.map(([ic, t, d], i) => (
                <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 13, padding: '9px 0',
                  borderTop: i ? '0.5px solid var(--es-separator)' : 'none' }}>
                  <div style={{ width: 34, height: 34, borderRadius: 9, background: 'var(--es-surface-2)',
                    color: 'var(--es-bronze)', display: 'grid', placeItems: 'center', flexShrink: 0 }}>
                    <AI n={ic} s={17} />
                  </div>
                  <div style={{ textAlign: 'left' }}>
                    <div className="es-subhead" style={{ fontWeight: 600 }}>{t}</div>
                    <div className="es-caption es-ink-3" style={{ marginTop: 1 }}>{d}</div>
                  </div>
                </div>
              ))}
            </div>
            <button className="es-btn es-btn--primary es-btn--block" style={{ marginTop: 24 }} onClick={onClose}>회원가입 계속하기</button>
          </React.Fragment>
        )}
      </div>
    </React.Fragment>
  );
}

// ─────────────────────────────────────────────────────────
// 3) SignUpViewController — 2 steps
// ─────────────────────────────────────────────────────────
function SignUpVC() {
  const [step, setStep] = React.useState(1);
  const [role, setRole] = React.useState('화가');
  const [sig, setSig] = React.useState('idle'); // idle | nonce | done
  const [terms, setTerms] = React.useState({ all: false, t1: false, t2: false });
  const [sheet, setSheet] = React.useState('closed'); // closed | intro | creating | done
  const [addr, setAddr] = React.useState('');
  const GEN_ADDR = 'rPv8s2KqWmEx7Yd4LhTnZc9bF6jRnUa3E';
  const generated = addr === GEN_ADDR;
  const createWallet = () => {
    setSheet('creating');
    setTimeout(() => { setAddr(GEN_ADDR); setSheet('done'); }, 1300);
  };
  const roles = ['화가', '경매사', '투자자'];

  const TOTAL = 4;
  const STEP_TITLES = ['계정 정보', '프로필', '지갑 연결', '약관 동의'];
  const Progress = () => (
    <div style={{ display: 'flex', gap: 5, marginBottom: 18 }}>
      {Array.from({ length: TOTAL }).map((_, i) => (
        <div key={i} style={{ flex: 1, height: 4, borderRadius: 2, background: i < step ? 'var(--es-blue)' : 'var(--es-fill)' }} />
      ))}
    </div>
  );

  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', color: 'var(--es-ink)', background: 'var(--es-bg)', position: 'relative', overflow: 'hidden' }}>
      <BareNav onBack={() => step > 1 ? setStep(step - 1) : null} />
      <div style={{ flex: 1, overflow: 'auto', padding: '8px 24px 24px' }}>
        <Progress />
        <div className="es-caption" style={{ color: 'var(--es-blue)', fontWeight: 600, letterSpacing: 0.3 }}>회원가입 · {step}/{TOTAL}</div>
        <div className="es-title-1" style={{ marginTop: 4, marginBottom: 20 }}>{STEP_TITLES[step - 1]}</div>

        {step === 1 ? (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            <div className="es-field">
              <label className="es-label">이름</label>
              <input className="es-input" placeholder="홍길동" />
            </div>
            <div className="es-field">
              <label className="es-label">이메일 주소</label>
              <input className="es-input" placeholder="you@example.com" />
            </div>
            <div className="es-field">
              <label className="es-label">비밀번호</label>
              <input className="es-input" type="password" placeholder="8자 이상, 영문·숫자 포함" />
            </div>
            <button className="es-btn es-btn--primary es-btn--block" style={{ marginTop: 8 }} onClick={() => setStep(2)}>다음</button>
          </div>
        ) : step === 2 ? (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            <div className="es-field">
              <label className="es-label">구분</label>
              <div className="es-segment">
                {roles.map(r => (
                  <button key={r} className="es-segment__item" aria-selected={r === role} onClick={() => setRole(r)}>{r}</button>
                ))}
              </div>
            </div>
            <div className="es-field">
              <label className="es-label">전화번호</label>
              <input className="es-input" placeholder="010-0000-0000" inputMode="tel" />
            </div>
            <button className="es-btn es-btn--primary es-btn--block" style={{ marginTop: 8 }} onClick={() => setStep(3)}>다음</button>
          </div>
        ) : step === 3 ? (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
            <div style={{ background: 'var(--es-surface-2)', border: '0.5px solid var(--es-separator)', borderRadius: 'var(--es-r-lg)', padding: '12px 14px', display: 'flex', gap: 10, alignItems: 'flex-start' }}>
              <AI n="wallet" s={18} style={{ color: 'var(--es-bronze)', flexShrink: 0, marginTop: 1 }} />
              <p className="es-footnote es-ink-2" style={{ margin: 0, lineHeight: 1.5 }}>
                EverSeal은 <b style={{ color: 'var(--es-ink)' }}>내부 지갑만</b> 지원해요. 이미 발급받은 EverSeal 지갑 주소가 있다면 입력해 주세요.
              </p>
            </div>
            <div className="es-field">
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginBottom: 6 }}>
                <label className="es-label" style={{ margin: 0 }}>EverSeal 지갑 주소 (선택)</label>
                <button onClick={() => setSheet('intro')} style={{ marginLeft: 'auto', background: 'none', border: 'none',
                  padding: '2px 0', color: 'var(--es-blue)', fontWeight: 600, fontSize: 14, cursor: 'pointer', fontFamily: 'inherit' }}>
                  주소를 모르시나요?
                </button>
              </div>
              <div className="es-input-group">
                <span className="es-input-icon"><AI n="wallet" s={20} /></span>
                <input className="es-input" placeholder="r... (알고 계신 경우에만 입력)" value={addr} onChange={e => setAddr(e.target.value)} style={{ fontSize: 15 }} />
              </div>
              {generated && (
                <span className="es-badge es-badge--success" style={{ display: 'inline-flex', alignItems: 'center', gap: 4, marginTop: 8 }}>
                  <AI n="check" s={12} />EverSeal 생성
                </span>
              )}
            </div>
            <button className="es-btn es-btn--primary es-btn--block" onClick={() => setStep(4)}>다음</button>
            <button className="es-btn es-btn--ghost" style={{ height: 46, color: 'var(--es-ink-3)' }} onClick={() => setStep(4)}>주소가 없거나 모르면, 나중에 확인 또는 생성이 가능하니 다음으로 넘어가셔도 돼요</button>
          </div>
        ) : (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
              {[['all', '약관 전체 동의', true], ['t1', '서비스 이용약관 (필수)', false], ['t2', '개인정보 처리방침 (필수)', false]].map(([k, label, bold]) => {
                const on = k === 'all' ? terms.all : terms[k];
                const toggle = () => {
                  if (k === 'all') { const v = !terms.all; setTerms({ all: v, t1: v, t2: v }); }
                  else { const nt = { ...terms, [k]: !terms[k] }; nt.all = nt.t1 && nt.t2; setTerms(nt); }
                };
                return (
                  <div key={k} onClick={toggle} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '11px 0', cursor: 'pointer',
                    borderTop: k === 't1' ? '0.5px solid var(--es-separator)' : 'none' }}>
                    <span className={'es-check' + (on ? ' es-check--on' : '')} style={{ width: 24, height: 24 }}>
                      {on && <AI n="check" s={15} />}
                    </span>
                    <span className="es-subhead" style={{ fontWeight: bold ? 600 : 400 }}>{label}</span>
                    {!bold && <span className="es-row__chev" style={{ marginLeft: 'auto' }}><AI n="chevron-right" s={16} /></span>}
                  </div>
                );
              })}
            </div>
            <button className="es-btn es-btn--primary es-btn--block" disabled={!terms.all}>가입 완료</button>
          </div>
        )}
      </div>
      <WalletCreateSheet
        state={sheet}
        addr={addr}
        onCreate={createWallet}
        onClose={() => setSheet('closed')}
        onUse={() => setSheet('closed')}
      />
    </div>
  );
}

// ─────────────────────────────────────────────────────────
// 4) FindPasswordViewController
// ─────────────────────────────────────────────────────────
function FindPasswordVC() {
  const [sent, setSent] = React.useState(false);
  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', color: 'var(--es-ink)', background: 'var(--es-bg)' }}>
      <BareNav onBack={() => setSent(false)} />
      <div style={{ flex: 1, overflow: 'auto', padding: '8px 24px 24px' }}>
        <div style={{ width: 56, height: 56, borderRadius: 'var(--es-r-lg)', background: 'var(--es-blue-soft)',
          color: 'var(--es-blue)', display: 'grid', placeItems: 'center', marginBottom: 20 }}>
          <AI n={sent ? 'check' : 'lock'} s={28} />
        </div>
        <div className="es-title-1">{sent ? '메일을 확인하세요' : '비밀번호 찾기'}</div>
        <p className="es-body es-ink-2" style={{ marginTop: 8, lineHeight: 1.55 }}>
          {sent
            ? '입력하신 주소로 재설정 링크를 보냈습니다. 메일의 안내에 따라 비밀번호를 다시 설정해 주세요.'
            : '가입하신 이메일 주소를 입력하시면 비밀번호 재설정 링크를 보내드립니다.'}
        </p>

        {!sent && (
          <div className="es-field" style={{ marginTop: 26 }}>
            <label className="es-label">이메일 주소</label>
            <div className="es-input-group">
              <span className="es-input-icon"><AI n="person" s={20} /></span>
              <input className="es-input" placeholder="you@example.com" />
            </div>
          </div>
        )}

        {sent && (
          <div style={{ background: 'var(--es-surface-2)', border: '0.5px solid var(--es-separator)',
            borderRadius: 'var(--es-r-md)', padding: '14px 16px', marginTop: 24, display: 'flex', alignItems: 'center', gap: 10 }}>
            <AI n="person" s={18} style={{ color: 'var(--es-ink-3)' }} />
            <span className="es-subhead" style={{ fontWeight: 600 }}>you@example.com</span>
          </div>
        )}
      </div>
      <div style={{ flexShrink: 0, padding: '12px 24px 34px', borderTop: '0.5px solid var(--es-separator)' }}>
        {!sent
          ? <button className="es-btn es-btn--primary es-btn--block" onClick={() => setSent(true)}>재설정 링크 보내기</button>
          : <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
              <button className="es-btn es-btn--secondary es-btn--block" onClick={() => setSent(true)}>메일 다시 보내기</button>
              <button className="es-btn es-btn--ghost" style={{ height: 44 }}>로그인으로 돌아가기</button>
            </div>}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────
// 5) AuthenticityVerificationViewController — GUEST
// ─────────────────────────────────────────────────────────
function GuestVerifyVC() {
  const [state, setState] = React.useState('idle'); // idle | scanning | done
  React.useEffect(() => {
    if (state === 'scanning') { const t = setTimeout(() => setState('done'), 2200); return () => clearTimeout(t); }
  }, [state]);

  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', color: '#fff',
      background: 'linear-gradient(180deg,#142a20,#122017)' }}>
      <BareNav dark onBack={() => setState('idle')}
        right={<span className="es-badge" style={{ background: 'rgba(255,255,255,0.1)', color: 'rgba(255,255,255,0.7)', marginTop: 4 }}>게스트</span>} />

      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center',
        justifyContent: 'center', padding: '0 28px', textAlign: 'center' }}>
        {state !== 'done' ? (
          <>
            <div style={{ position: 'relative', width: 200, height: 200, display: 'grid', placeItems: 'center', marginBottom: 36 }}>
              {state === 'scanning' && [0, 1, 2].map(i => (
                <span key={i} style={{ position: 'absolute', inset: 0, borderRadius: '50%',
                  border: '2px solid rgba(184,153,122,0.5)', animation: `esPulse 2s ${i * 0.6}s ease-out infinite` }} />
              ))}
              <div style={{ width: 116, height: 116, borderRadius: '50%',
                background: 'radial-gradient(circle at 50% 35%, #2c4a3a, #142a20)',
                border: '1px solid rgba(184,153,122,0.35)', display: 'grid', placeItems: 'center',
                color: 'var(--es-gold)', boxShadow: '0 0 60px rgba(184,153,122,0.18)' }}>
                <AI n="nfc" s={52} sw={1.6} />
              </div>
            </div>
            <div className="es-title-2" style={{ color: '#fff' }}>
              {state === 'idle' ? '작품에 휴대폰을 가까이 대세요' : '정품 여부를 확인하는 중…'}
            </div>
            <p className="es-callout" style={{ color: 'rgba(255,255,255,0.6)', marginTop: 10, maxWidth: '30ch', lineHeight: 1.5 }}>
              {state === 'idle'
                ? '로그인 없이도 작품의 NFC 태그로 정품 여부를 바로 확인할 수 있어요.'
                : 'NFC 태그와 서버 원장을 대조하고 있습니다.'}
            </p>
          </>
        ) : (
          <div style={{ width: '100%' }}>
            <div style={{ width: 88, height: 88, borderRadius: '50%', margin: '0 auto 22px',
              background: 'var(--es-success)', display: 'grid', placeItems: 'center', color: '#fff',
              boxShadow: '0 0 50px rgba(31,164,99,0.35)' }}>
              <AI n="check" s={46} sw={2.4} />
            </div>
            <div className="es-title-2" style={{ color: '#fff' }}>정품으로 확인되었습니다</div>
            <p className="es-footnote" style={{ color: 'rgba(255,255,255,0.5)', marginTop: 8 }}>NFC 태그 · 서버 원장 검증 완료</p>

            <div style={{ background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(255,255,255,0.12)',
              borderRadius: 'var(--es-r-lg)', padding: 16, marginTop: 24, textAlign: 'left' }}>
              <div style={{ display: 'flex', gap: 12, alignItems: 'center' }}>
                <div style={{ width: 56, height: 56, borderRadius: 10, background: 'linear-gradient(135deg,#C9BBA0,#6E5C3C)', flexShrink: 0 }} />
                <div style={{ flex: 1 }}>
                  <div className="es-headline" style={{ color: '#fff' }}>새벽의 정물 No.3</div>
                  <div className="es-footnote" style={{ color: 'rgba(255,255,255,0.55)' }}>박서린 · 2025 · 에디션 12/50</div>
                </div>
              </div>
            </div>
            <p className="es-footnote" style={{ color: 'rgba(255,255,255,0.45)', marginTop: 14, lineHeight: 1.5 }}>
              자세한 거래·소유 이력은 로그인 후 확인할 수 있습니다.
            </p>
          </div>
        )}
      </div>

      <div style={{ flexShrink: 0, padding: '0 24px 40px', display: 'flex', flexDirection: 'column', gap: 10 }}>
        {state === 'idle' && <button className="es-btn es-btn--gold es-btn--block" onClick={() => setState('scanning')}><AI n="wave" s={19} />스캔 시작</button>}
        {state === 'scanning' && <button className="es-btn es-btn--block" style={{ background: 'rgba(255,255,255,0.1)', color: '#fff' }} onClick={() => setState('idle')}>취소</button>}
        {state === 'done' && <>
          <button className="es-btn es-btn--block" style={{ background: 'rgba(255,255,255,0.14)', color: '#fff' }}>작품 상세 보기</button>
          <button className="es-btn es-btn--ghost" style={{ color: 'rgba(255,255,255,0.6)' }} onClick={() => setState('idle')}>다른 작품 확인</button>
        </>}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────
// 6) WalletAuthViewController — standalone XRPL signature auth
// ─────────────────────────────────────────────────────────
function WalletAuthVC({ initial = 'address', onSkip }) {
  const demoAddr = 'rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH';
  const [state, setState] = React.useState(initial); // address | done
  const [addr, setAddr] = React.useState(initial === 'address' ? '' : demoAddr);
  const [err, setErr] = React.useState('');

  const connect = () => {
    if (addr.trim().length < 20 || !addr.trim().startsWith('r')) { setErr('올바른 XRPL 지갑 주소를 입력해 주세요.'); return; }
    setErr(''); setState('done');
  };

  const subtitle = {
    address: 'EverSeal은 내부 지갑만 지원해요. 이미 발급받은 주소가 있다면 입력해 주세요.',
    done: '지갑이 연결되어 서비스를 이용할 수 있어요.',
  }[state];

  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', color: 'var(--es-ink)', background: 'var(--es-bg)' }}>
      <BareNav onBack={() => setState('address')} />
      <div style={{ flex: 1, overflow: 'auto', padding: '8px 24px 24px' }}>
        <div style={{ display: 'flex', justifyContent: 'center', margin: '6px 0 20px' }}>
          <SealMarkLight done={state === 'done'} />
        </div>
        <div className="es-title-1" style={{ textAlign: 'center' }}>
          {state === 'done' ? '지갑 연결 완료' : '지갑 연결'}
        </div>
        <p className="es-subhead es-ink-2" style={{ textAlign: 'center', marginTop: 8, lineHeight: 1.5, padding: '0 4px' }}>
          {subtitle}
        </p>

        {state === 'address' && (
          <div className="es-field" style={{ marginTop: 24 }}>
            <label className="es-label">EverSeal 지갑 주소</label>
            <div className="es-input-group">
              <span className="es-input-icon"><AI n="wallet" s={20} /></span>
              <input className={'es-input' + (err ? ' es-input--invalid' : '')} placeholder="r..." value={addr}
                onChange={(e) => { setAddr(e.target.value); if (err) setErr(''); }} style={{ fontSize: 15 }} />
            </div>
            {err
              ? <span className="es-help es-help--error">{err}</span>
              : <span className="es-help">주소가 없거나 모르면, 나중에 확인 또는 생성이 가능하니 다음으로 넘어가셔도 돼요.</span>}
          </div>
        )}

        {state === 'done' && (
          <div style={{ marginTop: 24, background: 'var(--es-gold-soft)', border: '1px solid var(--es-gold-border)',
            borderRadius: 'var(--es-r-lg)', padding: 16 }}>
            {[['지갑', 'EverSeal 내부 지갑'], ['주소', addr.slice(0, 8) + '…' + addr.slice(-4)], ['상태', '연결 완료']].map(([k, v], i) => (
              <div key={k} style={{ display: 'flex', justifyContent: 'space-between', gap: 12, padding: '8px 0',
                borderTop: i ? '0.5px solid var(--es-gold-border)' : 'none' }}>
                <span className="es-subhead es-ink-2" style={{ flexShrink: 0 }}>{k}</span>
                <span className="es-subhead es-mono" style={{ fontWeight: 600, flex: 1, textAlign: 'right', minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{v}</span>
              </div>
            ))}
          </div>
        )}
      </div>

      <div style={{ flexShrink: 0, padding: '12px 24px 34px', borderTop: '0.5px solid var(--es-separator)',
        display: 'flex', flexDirection: 'column', gap: 6 }}>
        {state === 'address' && <>
          <button className="es-btn es-btn--primary es-btn--block" onClick={connect}><AI n="wallet" s={19} />연결하기</button>
          <button className="es-btn es-btn--ghost" style={{ height: 46, color: 'var(--es-ink-3)' }} onClick={onSkip}>다음에 하기</button>
        </>}
        {state === 'done' && <button className="es-btn es-btn--primary es-btn--block" onClick={onSkip}>완료</button>}
      </div>
    </div>
  );
}

function Spinner() {
  return (
    <div style={{ position: 'relative', width: 88, height: 88, display: 'grid', placeItems: 'center' }}>
      <span style={{ position: 'absolute', inset: 0, borderRadius: '50%',
        border: '3px solid var(--es-gold-soft)', borderTopColor: 'var(--es-gold)',
        animation: 'esSpin 0.9s linear infinite' }} />
      <span style={{ color: 'var(--es-gold)' }}><AI n="shield-check" s={30} /></span>
    </div>
  );
}

function SealMarkLight({ done }) {
  return (
    <div style={{ position: 'relative', width: 88, height: 88 }}>
      <span style={{ position: 'absolute', inset: 0, borderRadius: '50%', border: '1.5px solid var(--es-gold-border)' }} />
      <span style={{ position: 'absolute', inset: 8, borderRadius: '50%', border: '1px dashed var(--es-gold-border)' }} />
      <span style={{ position: 'absolute', inset: 16, borderRadius: '50%',
        background: done ? 'var(--es-success)' : 'var(--es-gold-soft)',
        display: 'grid', placeItems: 'center', color: done ? '#fff' : 'var(--es-gold)' }}>
        <AI n={done ? 'check' : 'shield-check'} s={done ? 32 : 28} sw={done ? 2.4 : 1.8} />
      </span>
    </div>
  );
}

// ─────────────────────────────────────────────────────────
// 7) SignUpCompleteViewController — 가입 완료 · 이메일 인증 안내
// ─────────────────────────────────────────────────────────
function EnvelopeMark({ s = 22 }) {
  return (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor"
      strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <rect x="3" y="5" width="18" height="14" rx="2.5" />
      <path d="M3.6 7.4 11 12.1a2 2 0 0 0 2 0l7.4-4.7" />
    </svg>
  );
}

function SignUpCompleteVC({ email = 'you@example.com' }) {
  return (
    <div style={{ position: 'relative', height: '100%', display: 'flex', flexDirection: 'column', color: '#fff', overflow: 'hidden',
      background: 'linear-gradient(180deg,#1a3327 0%,#0f1b14 100%)' }}>
      <span style={{ position: 'absolute', inset: 0, pointerEvents: 'none', background:
        'radial-gradient(90% 46% at 50% 6%, rgba(184,153,122,0.20) 0%, rgba(184,153,122,0) 58%)' }} />
      <div style={{ paddingTop: 50, flexShrink: 0 }} />

      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center',
        justifyContent: 'center', padding: '0 28px', textAlign: 'center', zIndex: 2 }}>
        {/* gold seal ring with success check */}
        <div style={{ position: 'relative', width: 104, height: 104, marginBottom: 26 }}>
          <span style={{ position: 'absolute', inset: 0, borderRadius: '50%', border: '1.5px solid rgba(184,153,122,0.42)' }} />
          <span style={{ position: 'absolute', inset: 9, borderRadius: '50%', border: '1px dashed rgba(184,153,122,0.5)' }} />
          <span style={{ position: 'absolute', inset: 19, borderRadius: '50%',
            background: 'var(--es-success)', display: 'grid', placeItems: 'center', color: '#fff',
            boxShadow: '0 0 52px rgba(42,140,90,0.45)' }}>
            <AI n="check" s={40} sw={2.4} />
          </span>
        </div>

        <div className="es-title-1" style={{ color: '#fff' }}>가입이 완료되었습니다</div>
        <p className="es-callout" style={{ color: 'rgba(255,255,255,0.62)', marginTop: 10, maxWidth: '28ch', lineHeight: 1.55 }}>
          인증 메일을 보냈어요.<br/>메일함을 확인해 주세요.
        </p>

        {/* email chip */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 22,
          background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(184,153,122,0.32)',
          borderRadius: 999, padding: '10px 16px' }}>
          <span style={{ color: 'var(--es-gold)', display: 'grid', placeItems: 'center' }}>
            <EnvelopeMark s={19} />
          </span>
          <span className="es-subhead es-mono" style={{ color: '#fff', fontWeight: 600 }}>{email}</span>
        </div>
      </div>

      <div style={{ flexShrink: 0, padding: '0 24px 40px', display: 'flex', flexDirection: 'column', gap: 10, zIndex: 2 }}>
        <button className="es-btn es-btn--gold es-btn--block">로그인하기</button>
        <button className="es-btn es-btn--block" style={{ background: 'rgba(255,255,255,0.12)', color: '#fff' }}>
          인증 메일 다시 보내기
        </button>
      </div>
    </div>
  );
}

Object.assign(window, { IntroVC, SignInVC, SignInEmailOnlyVC, SignUpVC, FindPasswordVC, GuestVerifyVC, WalletAuthVC, SignUpCompleteVC });
