// Onboarding (3 screens) + Phone/OTP/Profile auth

// Splash — brief logo animation before onboarding
function GLSplash({ onDone }) {
  React.useEffect(() => {
    const t = setTimeout(onDone, 1800);
    return () => clearTimeout(t);
  }, []);
  return (
    <div style={{
      width: '100%', height: '100%', background: GL.ink,
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
      position: 'relative', overflow: 'hidden',
    }}>
      {/* rotating conic accent */}
      <div style={{
        position: 'absolute', width: 600, height: 600, borderRadius: '50%',
        background: `conic-gradient(from 0deg, transparent, ${GL.teal}33, transparent, ${GL.teal}1a, transparent)`,
        animation: 'gl-spin 4s linear infinite', filter: 'blur(30px)',
      }}/>
      <div className="gl-slide-up" style={{ position: 'relative', zIndex: 2, textAlign: 'center' }}>
        <div style={{ width: 56, height: 56, borderRadius: 16, background: GL.teal, margin: '0 auto 24px', display: 'grid', placeItems: 'center' }}>
          <div className="gl-display" style={{ fontSize: 28, color: GL.ink }}>G</div>
        </div>
        <div className="gl-display" style={{ fontSize: 42, color: '#fff', lineHeight: 0.9 }}>Gustai</div>
        <div className="gl-display" style={{ fontSize: 42, color: GL.teal, lineHeight: 0.9, fontStyle: 'italic' }}>Lab</div>
        <div style={{
          width: 40, height: 2, background: GL.teal, margin: '18px auto',
        }}/>
        <div className="gl-mono" style={{ fontSize: 10, color: 'rgba(255,255,255,0.5)', letterSpacing: '0.3em' }}>EST. 2024 · PHUKET</div>
      </div>
    </div>
  );
}

function GLOnboarding({ onDone }) {
  const [i, setI] = React.useState(0);
  const slides = [
    {
      dark: true,
      bg: 'https://images.unsplash.com/photo-1551183053-bf91a1d81141?w=1200&q=80',
      kicker: null,
      title: <>Gustai<br/><span style={{ color: GL.teal, fontStyle: 'italic' }}>Lab</span></>,
      body: "Phuket's high-contrast pasta experience. Freshly extruded daily in Rawai.",
      cta: 'Next',
    },
    {
      dark: false,
      bg: 'https://images.unsplash.com/photo-1587740908075-9e245311e158?w=1200&q=80',
      kicker: null,
      title: <>Complete<br/>Dish Sets.</>,
      body: <>Pasta <span style={{color: GL.teal}}>●</span> Signature Sauce <span style={{color: GL.teal}}>●</span> Toppings.<br/>We prep. You boil.<br/><b>5 minutes to perfection.</b></>,
      cta: 'Next',
    },
    {
      dark: true,
      bg: 'https://images.unsplash.com/photo-1566577739112-5180d4bf9390?w=1200&q=80',
      kicker: null,
      title: 'The Drop',
      body: <>A la carte or weekly drops.<br/><span style={{color: GL.teal, fontWeight: 700}}>Join the club for 15% off every box.</span><br/>Pause anytime.</>,
      cta: 'Explore the Menu',
    },
  ];
  const s = slides[i];
  const last = i === slides.length - 1;
  const next = () => last ? onDone() : setI(i + 1);

  return (
    <div style={{ width: '100%', height: '100%', position: 'relative', background: s.dark ? GL.darkBg : GL.offwhite, overflow: 'hidden' }}>
      {/* top skip */}
      {!last && (
        <button onClick={onDone} style={{
          position: 'absolute', top: 18, right: 20, zIndex: 10,
          color: s.dark ? '#fff' : GL.ink, fontSize: 12, fontWeight: 700, letterSpacing: '0.18em', textTransform: 'uppercase',
        }}>Skip</button>
      )}

      {/* Image area */}
      {i === 0 && (
        <div style={{ position: 'absolute', inset: 0 }}>
          <div style={{ position: 'absolute', inset: 0, background: `url(${s.bg}) center/cover`, filter: 'grayscale(100%) contrast(1.15) brightness(0.7)' }}/>
          <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(180deg, transparent 0%, rgba(14,27,29,0.4) 60%, rgba(14,27,29,0.98) 100%)' }}/>
        </div>
      )}
      {i === 1 && (
        <div style={{ position: 'absolute', top: 80, left: 20, right: 20, height: 380, borderRadius: 4, overflow: 'hidden' }}>
          <div style={{ width: '100%', height: '100%', background: `url(${s.bg}) center/cover`, filter: 'grayscale(100%) contrast(1.1)' }}/>
        </div>
      )}
      {i === 2 && (
        <div style={{ position: 'absolute', top: 90, left: 24, right: 24, height: 260, borderRadius: 4, overflow: 'hidden' }}>
          <div style={{ width: '100%', height: '100%', background: `url(${s.bg}) center/cover`, filter: 'grayscale(100%) contrast(1.2)' }}/>
        </div>
      )}

      {/* Content */}
      <div style={{
        position: 'absolute', bottom: 0, left: 0, right: 0, padding: '0 24px 48px',
        display: 'flex', flexDirection: 'column',
      }}>
        <div className="gl-slide-up" key={i} style={{ textAlign: i === 0 ? 'left' : 'center', marginBottom: 28 }}>
          <h1 className="gl-display" style={{
            fontSize: i === 0 ? 68 : 44, lineHeight: 0.88, margin: 0,
            color: s.dark ? '#fff' : GL.ink,
            fontStyle: i === 0 ? 'italic' : 'normal',
            textShadow: i === 0 ? '0 2px 20px rgba(0,0,0,0.5)' : 'none',
          }}>{s.title}</h1>
          {i === 0 && <div style={{ width: 64, height: 4, background: GL.teal, margin: '18px 0', borderRadius: 2 }}/>}
          <p style={{
            fontSize: i === 0 ? 12 : 14, fontWeight: 700, letterSpacing: '0.12em', textTransform: 'uppercase',
            color: s.dark ? 'rgba(255,255,255,0.9)' : GL.ink,
            maxWidth: i === 0 ? '85%' : '100%', margin: i === 0 ? '0' : '14px auto 0',
            lineHeight: 1.6,
            borderLeft: i === 0 ? `2px solid ${GL.teal}` : 'none',
            paddingLeft: i === 0 ? 14 : 0,
          }}>{s.body}</p>
        </div>

        {/* dots */}
        <div style={{ display: 'flex', gap: 8, justifyContent: i === 0 ? 'flex-start' : 'center', marginBottom: 24 }}>
          {slides.map((_, idx) => (
            <div key={idx} style={{
              height: 6, width: idx === i ? 28 : 6, borderRadius: 4,
              background: idx === i ? GL.teal : (s.dark ? 'rgba(255,255,255,0.2)' : 'rgba(10,10,10,0.2)'),
              transition: 'width .3s',
            }}/>
          ))}
        </div>

        <GLButton onClick={next}
          variant={i === 0 ? 'teal' : i === 1 ? 'primary' : 'darkPrimary'}
          icon={
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M5 12h14M12 5l7 7-7 7"/>
            </svg>
          }
        >{s.cta}</GLButton>
      </div>
    </div>
  );
}

// ─── Social Login ─────────────────────────────────────────────────────────────
// Google · Facebook OAuth + Email OTP (6-digit code, stays in PWA)
function GLSocialLogin({ app, onBack }) {
  const [agreed,  setAgreed]  = React.useState(false);
  const [step,    setStep]    = React.useState('social'); // 'social' | 'otp'
  const [email,   setEmail]   = React.useState('');
  const [code,    setCode]    = React.useState('');
  const [loading, setLoading] = React.useState(null); // 'google'|'facebook'|'email'|'verify'|null
  const [err,     setErr]     = React.useState('');

  // Save postAuth to localStorage before any OAuth redirect — survives page reload
  const savePostAuth = () => {
    const dest = (app && app.postAuth) || '';
    if (dest) localStorage.setItem('gl.postAuth', dest);
    else       localStorage.removeItem('gl.postAuth');
  };

  const signInGoogle = async () => {
    if (!agreed) return;
    setLoading('google'); setErr('');
    try {
      savePostAuth();
      const { data, error } = await window.db.auth.signInWithOAuth({
        provider: 'google',
        options:  { redirectTo: window.location.origin + '/' },
      });
      if (error) throw error;
      if (data?.url) window.location.href = data.url;
      else throw new Error('Google sign-in is not configured in Supabase.');
    } catch (e) { setErr(e.message || String(e)); setLoading(null); }
  };

  const signInFacebook = async () => {
    if (!agreed) return;
    setLoading('facebook'); setErr('');
    try {
      savePostAuth();
      const { data, error } = await window.db.auth.signInWithOAuth({
        provider: 'facebook',
        options:  { redirectTo: window.location.origin + '/' },
      });
      if (error) throw error;
      if (data?.url) window.location.href = data.url;
      else throw new Error('Facebook sign-in is not configured in Supabase.');
    } catch (e) { setErr(e.message || String(e)); setLoading(null); }
  };

  const sendEmailCode = async () => {
    if (!agreed || !email.trim()) return;
    setLoading('email'); setErr('');
    try {
      const { error } = await window.db.auth.signInWithOtp({
        email: email.trim().toLowerCase(),
        options: { shouldCreateUser: true },
      });
      if (error) throw error;
      setStep('otp');
    } catch (e) { setErr(e.message || String(e)); }
    finally { setLoading(null); }
  };

  const verifyCode = async () => {
    if (code.length !== 6) return;
    setLoading('verify'); setErr('');
    try {
      const { error } = await window.db.auth.verifyOtp({
        email: email.trim().toLowerCase(),
        token: code,
        type:  'email',
      });
      if (error) throw error;
      // Navigate directly — onAuthStateChange has stale postAuth closure
      const dest = localStorage.getItem('gl.postAuth') || (app && app.postAuth) || 'home';
      localStorage.removeItem('gl.postAuth');
      app.setIsRegistered(true);
      app.go(dest);
    } catch (e) { setErr(e.message || String(e)); setLoading(null); }
  };

  const Spinner = ({ color }) => (
    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={color || '#888'} strokeWidth="2" strokeLinecap="round">
      <path d="M21 12a9 9 0 1 1-6.219-8.56"/>
    </svg>
  );

  // ── OTP code entry step ───────────────────────────────────────────────────
  if (step === 'otp') {
    return (
      <div style={{ width: '100%', height: '100%', background: GL.paper, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
        <div style={{ padding: '62px 24px 0' }}>
          <button onClick={() => { setStep('social'); setCode(''); setErr(''); }} style={{ marginBottom: 40 }}>
            <div style={{ width: 40, height: 40, borderRadius: 10, background: GL.ink, display: 'grid', placeItems: 'center' }}>
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.4" strokeLinecap="round"><path d="M19 12H5M12 19l-7-7 7-7"/></svg>
            </div>
          </button>
          <h1 className="gl-display" style={{ fontSize: 48, lineHeight: 0.9, margin: 0, color: GL.ink }}>
            Check<br/><span style={{ color: '#B4C1C2' }}>your email</span>
          </h1>
          <p style={{ marginTop: 16, fontSize: 13, color: GL.muted, lineHeight: 1.6 }}>
            6-digit code sent to<br/>
            <strong style={{ color: GL.ink }}>{email}</strong>
          </p>
        </div>
        <div style={{ padding: '40px 24px 0', flex: 1 }}>
          <input
            type="text" inputMode="numeric" maxLength={6} value={code} autoFocus
            onChange={e => setCode(e.target.value.replace(/\D/g, '').slice(0, 6))}
            onKeyDown={e => e.key === 'Enter' && verifyCode()}
            placeholder="000000"
            style={{
              width: '100%', height: 72, border: `2px solid ${GL.ink}`, background: '#fff',
              textAlign: 'center', fontSize: 36, fontFamily: 'monospace', fontWeight: 700,
              letterSpacing: '0.35em', color: GL.ink, outline: 'none',
              boxSizing: 'border-box', boxShadow: `4px 4px 0 ${GL.ink}`,
            }}
          />
          {err && <div style={{ marginTop: 12, padding: '10px 12px', border: '1px solid #c0392b', background: '#fdecea', color: '#922b21', fontSize: 12, fontWeight: 600 }}>{err}</div>}
          <button
            onClick={verifyCode} disabled={code.length !== 6 || !!loading}
            style={{
              width: '100%', height: 56, marginTop: 20, background: GL.ink, color: '#fff',
              fontSize: 14, fontWeight: 800, letterSpacing: '0.1em',
              opacity: (code.length === 6 && !loading) ? 1 : 0.4,
              cursor: (code.length === 6 && !loading) ? 'pointer' : 'not-allowed',
              display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
            }}
          >
            {loading === 'verify' && <Spinner color="#fff"/>}
            {loading === 'verify' ? 'Verifying…' : 'Sign In'}
          </button>
          <button onClick={() => { setCode(''); setErr(''); sendEmailCode(); }}
            style={{ width: '100%', marginTop: 16, padding: '10px 0', fontSize: 12, fontWeight: 700, letterSpacing: '0.08em', color: GL.muted, textAlign: 'center' }}>
            Resend code
          </button>
        </div>
      </div>
    );
  }

  // ── Social + email entry ──────────────────────────────────────────────────
  return (
    <div style={{ width: '100%', height: '100%', background: GL.paper, display: 'flex', flexDirection: 'column', position: 'relative', overflow: 'hidden' }}>
      <div style={{ position: 'absolute', top: -60, right: -60, width: 240, height: 240, borderRadius: '50%', border: `1.5px solid ${GL.line}`, pointerEvents: 'none' }}/>

      <div style={{ padding: '62px 24px 0' }}>
        {onBack && (
          <button onClick={onBack} style={{ marginBottom: 40 }}>
            <div style={{ width: 40, height: 40, borderRadius: 10, background: GL.ink, display: 'grid', placeItems: 'center' }}>
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.4" strokeLinecap="round"><path d="M19 12H5M12 19l-7-7 7-7"/></svg>
            </div>
          </button>
        )}
        <h1 className="gl-display" style={{ fontSize: 52, lineHeight: 0.9, margin: 0, color: GL.ink }}>
          Join<br/>The Lab
        </h1>
        <p style={{ marginTop: 16, fontSize: 13, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: GL.muted, lineHeight: 1.6, maxWidth: 260 }}>
          Sign in to order &amp; track your pasta
        </p>
      </div>

      <div style={{ padding: '32px 24px 0', flex: 1, overflowY: 'auto' }} className="gl-noscroll">
        {/* PDPA consent */}
        <div style={{ marginBottom: 24 }}>
          <ConsentBox checked={agreed} onChange={setAgreed} required badge="Required"
            label={<>I agree to the{' '}
              <a href="#" onClick={e => { e.preventDefault(); app.go('terms'); }} style={{ color: GL.ink, fontWeight: 700, textDecoration: 'underline' }}>Terms of Service</a>
              {' '}and{' '}
              <a href="#" onClick={e => { e.preventDefault(); app.go('privacy'); }} style={{ color: GL.ink, fontWeight: 700, textDecoration: 'underline' }}>Privacy Policy</a>.
            </>}
          />
        </div>

        {/* Google */}
        <button onClick={signInGoogle} disabled={!!loading} style={{
          width: '100%', height: 58, display: 'flex', alignItems: 'center',
          border: `2px solid ${GL.ink}`, background: '#fff', marginBottom: 12,
          opacity: loading ? 0.6 : (!agreed ? 0.35 : 1),
          cursor: (!agreed || loading) ? 'not-allowed' : 'pointer',
          boxShadow: (agreed && !loading) ? `4px 4px 0 ${GL.ink}` : 'none',
          transition: 'box-shadow .15s, opacity .15s',
        }}>
          <div style={{ width: 56, height: '100%', display: 'grid', placeItems: 'center', borderRight: `1px solid ${GL.line}`, flexShrink: 0 }}>
            {loading === 'google' ? <Spinner/> : <svg width="20" height="20" viewBox="0 0 24 24">
              <path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" fill="#4285F4"/>
              <path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/>
              <path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/>
              <path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/>
            </svg>}
          </div>
          <span style={{ flex: 1, textAlign: 'center', fontSize: 14, fontWeight: 800, letterSpacing: '0.1em', color: GL.ink, paddingRight: 56 }}>
            {loading === 'google' ? 'Redirecting…' : 'Continue with Google'}
          </span>
        </button>

        {/* Facebook */}
        <button onClick={signInFacebook} disabled={!!loading} style={{
          width: '100%', height: 58, display: 'flex', alignItems: 'center',
          border: `2px solid ${GL.ink}`, background: '#1877F2', marginBottom: 20,
          opacity: loading ? 0.6 : (!agreed ? 0.35 : 1),
          cursor: (!agreed || loading) ? 'not-allowed' : 'pointer',
          boxShadow: (agreed && !loading) ? `4px 4px 0 ${GL.ink}` : 'none',
          transition: 'box-shadow .15s, opacity .15s',
        }}>
          <div style={{ width: 56, height: '100%', display: 'grid', placeItems: 'center', borderRight: '1px solid rgba(255,255,255,0.2)', flexShrink: 0 }}>
            {loading === 'facebook' ? <Spinner color="rgba(255,255,255,0.8)"/> : <svg width="22" height="22" viewBox="0 0 24 24" fill="#fff">
              <path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
            </svg>}
          </div>
          <span style={{ flex: 1, textAlign: 'center', fontSize: 14, fontWeight: 800, letterSpacing: '0.1em', color: '#fff', paddingRight: 56 }}>
            {loading === 'facebook' ? 'Redirecting…' : 'Continue with Facebook'}
          </span>
        </button>

        {/* Divider */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 16 }}>
          <div style={{ flex: 1, height: 1, background: GL.line }}/>
          <span style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.12em', color: GL.muted, textTransform: 'uppercase' }}>or email</span>
          <div style={{ flex: 1, height: 1, background: GL.line }}/>
        </div>

        {/* Email + Send Code */}
        <div style={{ display: 'flex', gap: 8, marginBottom: 16 }}>
          <input type="email" value={email} placeholder="your@email.com"
            onChange={e => setEmail(e.target.value)}
            onKeyDown={e => e.key === 'Enter' && sendEmailCode()}
            style={{
              flex: 1, height: 56, padding: '0 16px',
              border: `2px solid ${GL.ink}`, background: '#fff',
              fontSize: 14, color: GL.ink, outline: 'none', boxSizing: 'border-box',
            }}
          />
          <button onClick={sendEmailCode} disabled={!agreed || !email.trim() || !!loading}
            style={{
              height: 56, padding: '0 18px', background: GL.ink, color: '#fff', flexShrink: 0,
              fontSize: 13, fontWeight: 800, letterSpacing: '0.08em',
              opacity: (agreed && email.trim() && !loading) ? 1 : 0.35,
              cursor: (agreed && email.trim() && !loading) ? 'pointer' : 'not-allowed',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}
          >
            {loading === 'email' ? <Spinner color="#fff"/> : 'Send Code'}
          </button>
        </div>

        {!agreed && <p style={{ textAlign: 'center', fontSize: 11, fontWeight: 600, color: GL.muted }}>Please accept the Terms to continue.</p>}
        {err && <div style={{ marginTop: 8, padding: '10px 12px', border: '1px solid #c0392b', background: '#fdecea', color: '#922b21', fontSize: 12, fontWeight: 600 }}>{err}</div>}
      </div>
    </div>
  );
}

// ── Legacy stubs — kept so existing references don't crash, redirect to social login ──
const GL_COUNTRY_CODES = [
  { c: 'TH', dial: '+66',  name: 'Thailand' },
  { c: 'US', dial: '+1',   name: 'United States' },
  { c: 'GB', dial: '+44',  name: 'United Kingdom' },
  { c: 'AU', dial: '+61',  name: 'Australia' },
  { c: 'DE', dial: '+49',  name: 'Germany' },
  { c: 'FR', dial: '+33',  name: 'France' },
  { c: 'IT', dial: '+39',  name: 'Italy' },
  { c: 'ES', dial: '+34',  name: 'Spain' },
  { c: 'NL', dial: '+31',  name: 'Netherlands' },
  { c: 'SE', dial: '+46',  name: 'Sweden' },
  { c: 'NO', dial: '+47',  name: 'Norway' },
  { c: 'DK', dial: '+45',  name: 'Denmark' },
  { c: 'CH', dial: '+41',  name: 'Switzerland' },
  { c: 'RU', dial: '+7',   name: 'Russia' },
  { c: 'IL', dial: '+972', name: 'Israel' },
  { c: 'IN', dial: '+91',  name: 'India' },
  { c: 'CN', dial: '+86',  name: 'China' },
  { c: 'JP', dial: '+81',  name: 'Japan' },
  { c: 'KR', dial: '+82',  name: 'South Korea' },
  { c: 'SG', dial: '+65',  name: 'Singapore' },
  { c: 'HK', dial: '+852', name: 'Hong Kong' },
  { c: 'MY', dial: '+60',  name: 'Malaysia' },
  { c: 'ID', dial: '+62',  name: 'Indonesia' },
  { c: 'PH', dial: '+63',  name: 'Philippines' },
];

function glNormalizeE164(dial, local) {
  const digits = (local || '').replace(/\D/g, '').replace(/^0+/, '');
  return digits ? `${dial}${digits}` : '';
}

// Reusable consent checkbox — PDPA-compliant explicit tick
function ConsentBox({ checked, onChange, label, badge, required }) {
  return (
    <div style={{ display: 'flex', alignItems: 'flex-start', gap: 12 }}>
      <button
        type="button"
        onClick={() => onChange(!checked)}
        aria-checked={checked}
        role="checkbox"
        style={{
          flex: '0 0 22px', width: 22, height: 22, marginTop: 2,
          border: `2px solid ${checked ? GL.ink : GL.line}`,
          background: checked ? GL.ink : '#fff',
          display: 'grid', placeItems: 'center',
          transition: 'background .15s, border .15s',
        }}>
        {checked && (
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round">
            <path d="M20 6L9 17l-5-5"/>
          </svg>
        )}
      </button>
      <div style={{ flex: 1 }}>
        {badge && (
          <span style={{
            display: 'inline-block', marginBottom: 4,
            fontSize: 9, fontWeight: 800, letterSpacing: '0.18em', textTransform: 'uppercase',
            color: required ? '#fff' : GL.muted,
            background: required ? GL.ink : GL.line,
            padding: '2px 7px',
          }}>{badge}</span>
        )}
        <div style={{ fontSize: 12, color: GL.ink, lineHeight: 1.55, fontWeight: 500 }}>{label}</div>
      </div>
    </div>
  );
}

// Phone number sign up — country picker + channel choice (SMS / WhatsApp)
function GLPhoneSignup({ onSubmit, onBack }) {
  const [dial, setDial]         = React.useState('+66');
  const [local, setLocal]       = React.useState('');
  const [channel, setChannel]   = React.useState('sms');
  const [agreedTerms, setAgreedTerms]     = React.useState(false);
  const [agreedMarketing, setAgreedMarketing] = React.useState(false);
  const [busy, setBusy]         = React.useState(false);
  const [err, setErr]           = React.useState('');
  const e164 = glNormalizeE164(dial, local);
  const canSend = !!e164 && agreedTerms && !busy;

  async function handleSend() {
    if (!canSend) return;
    setErr('');
    setBusy(true);
    try {
      await window.GLAuth.sendOTP({ phone: e164, channel, purpose: 'signup' });
      onSubmit({ phone: e164, channel, marketingConsent: agreedMarketing });
    } catch (e) {
      let msg = e?.message || String(e);
      if (e?.try_other_channel) msg += ` — try ${e.try_other_channel}.`;
      setErr(msg);
      setBusy(false);
    }
  }

  const CHANNELS = [
    {
      id: 'sms',
      label: 'Text message',
      icon: (
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
        </svg>
      ),
    },
    {
      id: 'whatsapp',
      label: 'WhatsApp',
      icon: (
        <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
          <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 0 1-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 0 1-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 0 1 2.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0 0 12.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 0 0 5.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 0 0-3.48-8.413z"/>
        </svg>
      ),
    },
    {
      id: 'line',
      label: 'LINE',
      icon: (
        <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
          <path d="M19.365 9.863c.349 0 .63.285.63.631 0 .345-.281.63-.63.63H17.61v1.125h1.755c.349 0 .63.283.63.63 0 .344-.281.629-.63.629h-2.386c-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.627-.63h2.386c.349 0 .63.285.63.63 0 .349-.281.63-.63.63H17.61v1.125h1.755zm-3.855 3.016c0 .27-.174.51-.432.596-.064.021-.133.031-.199.031-.211 0-.391-.09-.51-.25l-2.443-3.317v2.94c0 .344-.279.629-.631.629-.346 0-.626-.285-.626-.629V8.108c0-.27.173-.51.43-.595.06-.023.136-.033.194-.033.195 0 .375.104.495.254l2.462 3.33V8.108c0-.345.282-.63.63-.63.345 0 .63.285.63.63v4.771zm-5.741 0c0 .344-.282.629-.631.629-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.627-.63.349 0 .631.285.631.63v4.771zm-2.466.629H4.917c-.345 0-.63-.285-.63-.629V8.108c0-.345.285-.63.63-.63.348 0 .63.285.63.63v4.141h1.756c.348 0 .629.283.629.63 0 .344-.281.629-.629.629M24 10.314C24 4.943 18.615.572 12 .572S0 4.943 0 10.314c0 4.811 4.27 8.842 10.035 9.608.391.082.923.258 1.058.59.12.301.079.766.038 1.08l-.164 1.02c-.045.301-.24 1.186 1.049.645 1.291-.539 6.916-4.078 9.436-6.975C23.176 14.393 24 12.458 24 10.314"/>
        </svg>
      ),
    },
  ];

  return (
    <div style={{ width: '100%', height: '100%', background: GL.paper, display: 'flex', flexDirection: 'column', position: 'relative' }}>
      {/* decorative corner */}
      <div style={{
        position: 'absolute', top: -60, right: -60, width: 240, height: 240, borderRadius: '50%',
        border: `1.5px solid ${GL.line}`, pointerEvents: 'none',
      }}/>
      <div style={{ padding: '62px 24px 0' }}>
        <button onClick={onBack} style={{ marginBottom: 40 }} aria-label="Back">
          <div style={{ width: 40, height: 40, borderRadius: 10, background: GL.ink, display: 'grid', placeItems: 'center' }}>
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
              <path d="M19 12H5M12 19l-7-7 7-7"/>
            </svg>
          </div>
        </button>
        <h1 className="gl-display" style={{ fontSize: 52, lineHeight: 0.9, margin: 0, color: GL.ink }}>
          Join<br/>The Lab
        </h1>
        <p style={{ marginTop: 22, fontSize: 13, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: GL.ink, lineHeight: 1.6, maxWidth: 280 }}>
          Enter your number — we'll send a 6-digit code.
        </p>
      </div>

      <div style={{ padding: '32px 24px 0' }}>
        {/* Phone row: country dial + local digits */}
        <div style={{ display: 'flex', border: `2px solid ${GL.ink}`, height: 64 }}>
          <select
            value={dial}
            onChange={e => setDial(e.target.value)}
            style={{
              width: 96, border: 'none', outline: 'none',
              borderRight: `2px solid ${GL.ink}`,
              padding: '0 8px 0 12px', fontWeight: 800, fontSize: 14,
              background: '#fff', color: GL.ink, cursor: 'pointer',
              appearance: 'none', WebkitAppearance: 'none',
            }}
          >
            {GL_COUNTRY_CODES.map(c => (
              <option key={c.c} value={c.dial}>{c.dial}&nbsp;{c.c}</option>
            ))}
          </select>
          <input
            value={local}
            onChange={e => setLocal(e.target.value.replace(/[^\d\s]/g, ''))}
            placeholder="81 234 5678"
            inputMode="tel"
            style={{ flex: 1, border: 'none', outline: 'none', padding: '0 18px', fontSize: 16, fontWeight: 600, letterSpacing: '0.05em' }}
          />
        </div>
        {e164 && (
          <div style={{ marginTop: 8, fontSize: 11, fontWeight: 700, letterSpacing: '0.14em', color: GL.muted, textTransform: 'uppercase' }}>
            We'll send to: <span style={{ color: GL.ink }}>{e164}</span>
          </div>
        )}

        {/* Channel picker — SMS / WhatsApp */}
        <div style={{ marginTop: 20 }}>
          <div className="gl-display" style={{ fontSize: 11, color: GL.muted, letterSpacing: '0.18em', textTransform: 'uppercase', marginBottom: 10 }}>
            Send code via
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 0, border: `2px solid ${GL.ink}` }}>
            {CHANNELS.map((opt, idx) => {
              const active = channel === opt.id;
              return (
                <button key={opt.id} onClick={() => setChannel(opt.id)}
                  style={{
                    border: 'none',
                    borderLeft: idx > 0 ? `2px solid ${GL.ink}` : 'none',
                    background: active ? GL.ink : '#fff',
                    color: active ? '#fff' : GL.ink,
                    padding: '14px 10px',
                    display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6,
                    transition: 'background .15s, color .15s',
                    cursor: 'pointer',
                  }}>
                  <div style={{ opacity: active ? 1 : 0.5 }}>{opt.icon}</div>
                  <span style={{ fontWeight: 800, fontSize: 13, letterSpacing: '0.04em' }}>{opt.label}</span>
                </button>
              );
            })}
          </div>
        </div>

        {err && (
          <div style={{ marginTop: 14, padding: '10px 12px', border: `1px solid #c0392b`, background: '#fdecea', color: '#922b21', fontSize: 12, fontWeight: 600 }}>
            {err}
          </div>
        )}

        {/* ── Consent checkboxes ─────────────────────────────────────────── */}
        <div style={{ marginTop: 20, display: 'flex', flexDirection: 'column', gap: 14 }}>

          {/* REQUIRED — Terms + Privacy */}
          <ConsentBox
            checked={agreedTerms}
            onChange={setAgreedTerms}
            required
            label={<>
              I have read and agree to the{' '}
              <a href="#" onClick={e => { e.preventDefault(); onLegal && onLegal('terms'); }} style={{ color: GL.ink, fontWeight: 700, textDecoration: 'underline' }}>Terms of Service</a>
              {' '}and{' '}
              <a href="#" onClick={e => { e.preventDefault(); onLegal && onLegal('privacy'); }} style={{ color: GL.ink, fontWeight: 700, textDecoration: 'underline' }}>Privacy Policy</a>.
            </>}
            badge="Required"
          />

          {/* OPTIONAL — Marketing */}
          <ConsentBox
            checked={agreedMarketing}
            onChange={setAgreedMarketing}
            label={<>
              I'd like to receive "The Drop" alerts and promotions via {channel === 'whatsapp' ? 'WhatsApp' : 'SMS'}.
            </>}
            badge="Optional"
          />

        </div>

        <div style={{ height: 18 }}/>
        <GLButton onClick={handleSend} variant="primary" disabled={!canSend}
          icon={
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M5 12h14M12 5l7 7-7 7"/>
            </svg>
          }>{busy ? 'Sending…' : 'Send Verification Code'}</GLButton>
        {!agreedTerms && e164 && !busy && (
          <p style={{ marginTop: 10, textAlign: 'center', fontSize: 11, fontWeight: 600, color: GL.muted }}>
            Please agree to the Terms &amp; Privacy Policy to continue.
          </p>
        )}
      </div>

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

// OTP verification — real 6-digit entry against phone-otp-verify Edge Function
function GLOTP({ phone, channel, onVerify, onBack }) {
  const [code, setCode]       = React.useState(['','','','','','']);
  const [busy, setBusy]       = React.useState(false);
  const [err, setErr]         = React.useState('');
  const [info, setInfo]       = React.useState('');
  const [resendIn, setResendIn] = React.useState(30);
  const refs = React.useRef([]);

  React.useEffect(() => {
    if (resendIn <= 0) return;
    const t = setTimeout(() => setResendIn(s => s - 1), 1000);
    return () => clearTimeout(t);
  }, [resendIn]);

  // Auto-submit when all 6 digits filled
  React.useEffect(() => {
    if (code.every(d => /\d/.test(d)) && !busy) handleVerify();
    // eslint-disable-next-line
  }, [code]);

  function handleChange(i, v) {
    const d = (v || '').replace(/\D/g, '').slice(0, 1);
    setErr('');
    setCode(prev => {
      const n = [...prev]; n[i] = d; return n;
    });
    if (d && i < 5 && refs.current[i + 1]) refs.current[i + 1].focus();
  }

  function handleKeyDown(i, e) {
    if (e.key === 'Backspace' && !code[i] && i > 0) {
      refs.current[i - 1]?.focus();
    } else if (e.key === 'ArrowLeft' && i > 0) {
      refs.current[i - 1]?.focus();
    } else if (e.key === 'ArrowRight' && i < 5) {
      refs.current[i + 1]?.focus();
    }
  }

  function handlePaste(e) {
    const txt = (e.clipboardData?.getData('text') || '').replace(/\D/g, '').slice(0, 6);
    if (!txt) return;
    e.preventDefault();
    const arr = ['','','','','',''];
    for (let i = 0; i < txt.length; i++) arr[i] = txt[i];
    setCode(arr);
    refs.current[Math.min(txt.length, 5)]?.focus();
  }

  async function handleVerify() {
    const c = code.join('');
    if (c.length !== 6) return;
    setBusy(true);
    setErr('');
    try {
      const r = await window.GLAuth.verifyOTP({ phone, code: c, channel });
      onVerify({ user_id: r.user_id, is_new: r.is_new });
    } catch (e) {
      if (typeof e?.attempts_left === 'number') {
        setErr(`Wrong code — ${e.attempts_left} attempt${e.attempts_left === 1 ? '' : 's'} left.`);
      } else {
        setErr(e?.message || String(e));
      }
      setBusy(false);
      setCode(['','','','','','']);
      refs.current[0]?.focus();
    }
  }

  async function handleResend() {
    if (resendIn > 0) return;
    setErr(''); setInfo('');
    try {
      await window.GLAuth.sendOTP({ phone, channel });
      setInfo('New code sent.');
      setResendIn(30);
    } catch (e) {
      let msg = e?.message || String(e);
      if (e?.try_other_channel) msg += ` — try ${e.try_other_channel}.`;
      setErr(msg);
    }
  }

  // Mask phone for display: keep last 4 digits visible
  const maskedPhone = phone && phone.length > 4
    ? `${phone.slice(0, phone.length - 4).replace(/\d/g, '•')}${phone.slice(-4)}`
    : phone;
  const channelLabel = channel === 'whatsapp' ? 'WhatsApp' : channel === 'line' ? 'LINE' : 'SMS';

  return (
    <div style={{ width: '100%', height: '100%', background: GL.paper, display: 'flex', flexDirection: 'column', position: 'relative' }}>
      {/* teal top accent */}
      <div style={{ height: 3, background: GL.teal }}/>
      <GLTopBar onBack={onBack} center={
        <div style={{ textAlign: 'center' }}>
          <div className="gl-mono" style={{ fontSize: 9, letterSpacing: '0.2em', color: GL.muted }}>EST. 2024</div>
          <div className="gl-display" style={{ fontSize: 13, color: GL.ink }}>GUSTAI LAB</div>
        </div>
      }/>
      <div style={{ padding: '40px 24px 0', textAlign: 'center' }}>
        <h1 className="gl-display" style={{ fontSize: 38, lineHeight: 0.95, margin: 0, color: GL.ink }}>
          Verify Your<br/>Lab Access
        </h1>

        {channel === 'line' ? (
          /* LINE instructions — user must message the OA first */
          <div style={{ marginTop: 24, textAlign: 'left' }}>
            <div style={{ background: GL.offwhite, border: `2px solid ${GL.ink}`, padding: '18px 20px', marginBottom: 20 }}>
              <div className="gl-display" style={{ fontSize: 11, letterSpacing: '0.18em', color: GL.muted, marginBottom: 12 }}>HOW TO GET YOUR CODE</div>
              {[
                { n: '1', t: 'Open LINE and add us as a friend' },
                { n: '2', t: `Send your phone number: ${phone.replace('+66', '0')}` },
                { n: '3', t: 'We\'ll reply with your 6-digit code' },
              ].map(s => (
                <div key={s.n} style={{ display: 'flex', gap: 12, alignItems: 'flex-start', marginBottom: 10 }}>
                  <div style={{ width: 24, height: 24, background: GL.ink, color: GL.teal, display: 'grid', placeItems: 'center', flexShrink: 0, fontSize: 11, fontWeight: 800 }}>{s.n}</div>
                  <div style={{ fontSize: 13, fontWeight: 600, color: GL.ink, lineHeight: 1.5, paddingTop: 3 }}>{s.t}</div>
                </div>
              ))}
            </div>
            <a href="line://ti/p/@330ybexe"
              style={{ display: 'block', width: '100%', background: '#06C755', border: `2px solid ${GL.ink}`, padding: '16px', textAlign: 'center', color: '#fff', fontWeight: 800, fontSize: 14, letterSpacing: '0.08em', textDecoration: 'none', boxSizing: 'border-box' }}>
              Open LINE → @GustaiLab
            </a>
          </div>
        ) : (
          <p style={{ marginTop: 28, fontSize: 11, fontWeight: 700, letterSpacing: '0.16em', textTransform: 'uppercase', color: GL.muted }}>
            Enter the 6-digit code sent via {channelLabel} to<br/>
            <span style={{ color: GL.ink, fontSize: 14, letterSpacing: '0.1em' }}>{maskedPhone}</span>
          </p>
        )}

        <div style={{ display: 'flex', gap: 8, justifyContent: 'center', marginTop: 28 }} onPaste={handlePaste}>
          {code.map((d, i) => (
            <input
              key={i}
              ref={el => refs.current[i] = el}
              value={d}
              onChange={e => handleChange(i, e.target.value)}
              onKeyDown={e => handleKeyDown(i, e)}
              inputMode="numeric"
              maxLength={1}
              autoFocus={i === 0}
              disabled={busy}
              style={{
                width: 46, height: 56, border: `1.5px solid ${d ? GL.ink : GL.line}`,
                textAlign: 'center', outline: 'none',
                fontFamily: GL.display, fontSize: 24, color: GL.ink,
                transition: 'border .2s',
                background: d ? '#fff' : GL.offwhite,
              }}/>
          ))}
        </div>

        {err && (
          <div style={{ marginTop: 16, fontSize: 12, color: '#922b21', fontWeight: 700 }}>{err}</div>
        )}
        {info && !err && (
          <div style={{ marginTop: 16, fontSize: 12, color: GL.teal, fontWeight: 700 }}>{info}</div>
        )}

        <button onClick={handleResend} disabled={resendIn > 0} style={{
          marginTop: 24, fontSize: 11, fontWeight: 700, letterSpacing: '0.18em',
          color: resendIn > 0 ? GL.muted : GL.ink, textTransform: 'uppercase',
          display: 'flex', gap: 8, margin: '24px auto 0', alignItems: 'center',
          opacity: resendIn > 0 ? 0.5 : 1, cursor: resendIn > 0 ? 'default' : 'pointer',
        }}>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M1 4v6h6M23 20v-6h-6M20.5 9A9 9 0 0 0 5.3 5.3L1 10M23 14l-4.3 4.7A9 9 0 0 1 3.5 15"/></svg>
          {resendIn > 0 ? `Resend in ${resendIn}s` : 'Resend Code'}
        </button>
      </div>

      <div style={{ flex: 1 }}/>

      <div style={{ padding: '0 24px 20px', borderTop: `1px solid ${GL.line}`, paddingTop: 16, display: 'flex', justifyContent: 'space-between', fontSize: 10, fontWeight: 700, letterSpacing: '0.18em', color: GL.muted, textTransform: 'uppercase' }}>
        <span>Secure Session</span>
        <span><span style={{ display: 'inline-block', width: 6, height: 6, borderRadius: '50%', background: GL.teal, marginRight: 6, animation: 'gl-pulse 1.5s infinite' }}/>{channelLabel}</span>
      </div>
      <div style={{ padding: '0 24px 32px' }}>
        <GLButton onClick={handleVerify} variant="primary" disabled={busy || code.join('').length !== 6}
          icon={<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>}>
          {busy ? 'Verifying…' : 'Verify & Continue'}
        </GLButton>
        <p style={{ textAlign: 'center', marginTop: 12, fontSize: 9, fontWeight: 700, letterSpacing: '0.18em', color: GL.muted, textTransform: 'uppercase' }}>By verifying, you agree to our Lab Terms</p>
      </div>
    </div>
  );
}

// Account / Profile setup — works for both social auth and legacy phone auth
function GLProfileSetup({ phone, channel, marketingConsent, initialName, onDone, onBack, onLegal }) {
  const [name, setName]     = React.useState(initialName || '');
  const [area, setArea]     = React.useState('');
  const [busy, setBusy]     = React.useState(false);
  const [err, setErr]       = React.useState('');

  async function handleSave() {
    setErr('');
    setBusy(true);
    try {
      // Persist profile fields if a Supabase session is active
      const db = window.db;
      const session = db?.auth ? (await db.auth.getSession()).data?.session : null;
      if (session?.user?.id) {
        const updates = {
          display_name:       name || null,
          delivery_area:      area || null,
          notify_drops:       !!marketingConsent,   // from explicit signup consent
          marketing_consent:  !!marketingConsent,   // timestamped record
          preferred_channel:  channel || 'whatsapp',
        };
        const { error } = await db
          .from('profiles')
          .update(updates)
          .eq('id', session.user.id);
        if (error) {
          // Surface the error but don't block — user can still continue
          console.warn('profile update failed:', error);
        }
      }
      onDone({ name, area, marketingConsent });
    } catch (e) {
      setErr(String(e?.message || e));
    } finally {
      setBusy(false);
    }
  }

  return (
    <div style={{ width: '100%', height: '100%', background: GL.offwhite, display: 'flex', flexDirection: 'column' }}>
      <GLTopBar onBack={onBack}/>
      <div style={{ padding: '16px 24px 0', flex: 1, overflowY: 'auto' }} className="gl-noscroll">
        <h1 className="gl-display" style={{ fontSize: 48, lineHeight: 0.9, margin: '8px 0 16px', color: GL.ink }}>
          Lab Profile<br/>Setup
        </h1>
        {phone && (
          <div style={{ marginBottom: 28, padding: '10px 12px', background: '#fff', border: `1px solid ${GL.line}` }}>
            <div className="gl-mono" style={{ fontSize: 9, letterSpacing: '0.2em', color: GL.muted, textTransform: 'uppercase' }}>Verified via</div>
            <div style={{ fontSize: 14, fontWeight: 700, color: GL.ink, marginTop: 4 }}>{phone}</div>
          </div>
        )}
        {[
          { label: 'Full Name', v: name, s: setName, ph: 'Enter your full name' },
          { label: 'Preferred Delivery Area', v: area, s: setArea, ph: 'e.g., Rawai, Chalong' },
        ].map((f, i) => (
          <div key={i} style={{ marginBottom: 26 }}>
            <label className="gl-display" style={{ fontSize: 13, color: GL.ink, letterSpacing: '0.1em' }}>{f.label}</label>
            <input value={f.v} onChange={e => f.s(e.target.value)} placeholder={f.ph}
              style={{ width: '100%', border: 'none', borderBottom: `1px solid ${GL.ink}`, background: 'transparent', padding: '14px 0', fontSize: 16, outline: 'none', marginTop: 6 }}/>
          </div>
        ))}
        {/* Show the marketing preference they already chose at sign-up — read only */}
        <div style={{ marginTop: 8, padding: '16px 0', borderTop: `1px solid ${GL.line}`, borderBottom: `1px solid ${GL.line}`, display: 'flex', alignItems: 'center', gap: 12 }}>
          <div style={{
            width: 22, height: 22, flex: '0 0 22px',
            border: `2px solid ${marketingConsent ? GL.ink : GL.line}`,
            background: marketingConsent ? GL.ink : '#fff',
            display: 'grid', placeItems: 'center',
          }}>
            {marketingConsent && (
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round">
                <path d="M20 6L9 17l-5-5"/>
              </svg>
            )}
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 12, fontWeight: 700, color: GL.ink }}>
              {marketingConsent ? 'Opted in to Drop alerts' : 'Not subscribed to Drop alerts'}
            </div>
            <div style={{ fontSize: 11, color: GL.muted, marginTop: 3, lineHeight: 1.4 }}>
              You can change this anytime in your profile settings.
            </div>
          </div>
        </div>
        {err && (
          <div style={{ marginTop: 14, padding: '10px 12px', border: `1px solid #c0392b`, background: '#fdecea', color: '#922b21', fontSize: 12, fontWeight: 600 }}>
            {err}
          </div>
        )}
      </div>
      <div style={{ padding: '20px 24px 32px' }}>
        <GLButton onClick={handleSave} disabled={busy}>{busy ? 'Saving…' : 'Create Account'}</GLButton>
        <p style={{ textAlign: 'center', marginTop: 10, fontSize: 11, fontWeight: 500, color: GL.muted }}>By continuing, you agree to our <u>Terms of Service</u>.</p>
      </div>
    </div>
  );
}

Object.assign(window, {
  GLSplash, GLOnboarding, GLSocialLogin, GLProfileSetup,
  // Legacy exports kept so old references don't crash
  GLPhoneSignup: GLSocialLogin, GLOTP: GLSocialLogin,
  GL_COUNTRY_CODES, glNormalizeE164,
});
