// Direction 1 — "Blueprint Grid"
// Faithful to the reference banners: dark base, radial perspective grid,
// chunky display sans + serif-italic accents, mascot as a placed character.
// Hero has the form anchored top-right on desktop, top-of-fold on mobile per
// brief. Section rhythm uses a left-rail spec-line motif (numbered, all-caps
// mono labels) so the whole page reads like a build doc.
//
// Constants & shared helpers come from brand.jsx (window.BRAND etc).

const CTA = 'Claim My Founding Spot';

// ── Supabase (LaunchPath · public.waitlist_signups) ───────────────────
// Publishable key is safe to ship to the client — RLS on the table
// limits permissions to insert-only for anon role.
const SUPABASE_URL = 'https://zpsavoyotyqlnepqkwkj.supabase.co';
const SUPABASE_ANON_KEY = 'sb_publishable_bdTbOYFMaQQprf7NEWg6IQ_r1voqIbB';

// ── Validation: email (WHATWG-spec via hidden input + Levenshtein TLD typo suggester) ──
// Cached input element used to delegate email syntax to the browser's
// native WHATWG implementation — same regex as `<input type="email">`,
// zero bytes shipped, cross-browser consistent.
let _emailValidatorInput = null;
function isValidEmailFormat(email) {
  if (typeof document === 'undefined') {
    // SSR fallback (we never SSR, but be safe): permissive regex
    return /^\S+@\S+\.\S+$/.test(email);
  }
  if (!_emailValidatorInput) {
    _emailValidatorInput = document.createElement('input');
    _emailValidatorInput.type = 'email';
  }
  _emailValidatorInput.value = email;
  return _emailValidatorInput.checkValidity();
}

function validateEmail(email) {
  const trimmed = (email || '').trim();
  if (!trimmed) return { ok: false, reason: 'Email is required' };
  if (trimmed.length > 254) return { ok: false, reason: 'That email looks too long' };
  if (!isValidEmailFormat(trimmed)) return { ok: false, reason: 'Enter a valid email address' };
  // WHATWG accepts single-label domains ("foo@bar") and 1-char TLDs ("foo@bar.c")
  // which are valid in some intranets but never in consumer signups. Require
  // a domain with a dot and a 2+ char final segment.
  const at = trimmed.lastIndexOf('@');
  const domain = trimmed.slice(at + 1);
  const lastDot = domain.lastIndexOf('.');
  if (lastDot < 1 || domain.length - lastDot < 3) {
    return { ok: false, reason: 'Enter a valid email address' };
  }
  return { ok: true };
}

// Catches "gmial.com", "yhaoo.com", "outloook.com", etc. on the providers
// our audience is actually likely to use.
const COMMON_EMAIL_DOMAINS = [
  // English-speaking
  'gmail.com', 'googlemail.com',
  'yahoo.com', 'yahoo.co.uk', 'yahoo.ca', 'yahoo.in', 'yahoo.com.au', 'ymail.com', 'rocketmail.com',
  'outlook.com', 'outlook.co.uk', 'outlook.com.au',
  'hotmail.com', 'hotmail.co.uk', 'hotmail.ca',
  'live.com', 'live.co.uk', 'msn.com',
  'icloud.com', 'me.com', 'mac.com',
  'aol.com', 'aol.co.uk',
  'proton.me', 'protonmail.com', 'pm.me',
  'fastmail.com', 'fastmail.fm',
  'zoho.com', 'zohomail.com',
  // UK ISPs
  'btinternet.com', 'sky.com', 'virginmedia.com', 'talktalk.net',
  // EU
  'gmx.com', 'gmx.de', 'gmx.net', 'web.de', 't-online.de',
  'outlook.fr', 'outlook.de', 'yahoo.fr', 'yahoo.de',
  'orange.fr', 'wanadoo.fr', 'free.fr', 'laposte.net', 'sfr.fr',
  // APAC + RU
  'yandex.com', 'yandex.ru', 'mail.ru',
  'qq.com', '163.com', '126.com', 'sina.com',
  'naver.com', 'daum.net',
  'rediffmail.com',
];

function levenshtein(a, b) {
  if (a === b) return 0;
  const m = a.length, n = b.length;
  if (!m) return n;
  if (!n) return m;
  let prev = new Array(n + 1);
  let curr = new Array(n + 1);
  for (let j = 0; j <= n; j++) prev[j] = j;
  for (let i = 1; i <= m; i++) {
    curr[0] = i;
    for (let j = 1; j <= n; j++) {
      const cost = a[i - 1] === b[j - 1] ? 0 : 1;
      curr[j] = Math.min(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + cost);
    }
    [prev, curr] = [curr, prev];
  }
  return prev[n];
}

function suggestEmailFix(email) {
  const trimmed = (email || '').trim().toLowerCase();
  const at = trimmed.lastIndexOf('@');
  if (at < 1 || at >= trimmed.length - 1) return null;
  const local = trimmed.slice(0, at);
  const domain = trimmed.slice(at + 1);
  if (!domain || COMMON_EMAIL_DOMAINS.includes(domain)) return null;
  // Allow up to 2 edits on short domains, 3 on longer ones
  let best = null;
  let bestDist = Math.min(3, Math.max(2, Math.floor(domain.length / 4)));
  for (const d of COMMON_EMAIL_DOMAINS) {
    if (Math.abs(d.length - domain.length) > 3) continue;
    const dist = levenshtein(domain, d);
    if (dist > 0 && dist <= bestDist) {
      bestDist = dist;
      best = d;
    }
  }
  return best ? `${local}@${best}` : null;
}

// ── Validation: phone (lazy-loaded libphonenumber-js) ──
// Loads ~22-28 kB gzipped from esm.sh, but only on first phone-field
// focus — so first paint is unaffected.
let _phoneLibPromise = null;
function loadPhoneLib() {
  if (typeof window === 'undefined') return Promise.resolve(null);
  if (!_phoneLibPromise) {
    _phoneLibPromise = import('https://esm.sh/libphonenumber-js@1.11.20/min')
      .catch(err => {
        console.warn('Failed to load libphonenumber-js:', err);
        _phoneLibPromise = null;
        return null;
      });
  }
  return _phoneLibPromise;
}

// Catches obvious junk regardless of whether libphonenumber loaded:
// - all-same-digit ("11111111111111", "0000000000")
// - pure sequential ascending or descending, treating 9→0 as +1 (so
//   "1234567890", "0123456789" and "9876543210" all match)
// libphonenumber accepts some of these as syntactically valid in
// permissive countries (e.g. "1111111111" parses as a Delhi landline),
// but a real signup never types these.
function looksLikeJunkPhone(numStr) {
  const digits = (numStr || '').replace(/\D/g, '');
  if (digits.length < 6) return true;
  if (/^(\d)\1+$/.test(digits)) return true;
  let asc = true, desc = true;
  for (let i = 1; i < digits.length; i++) {
    const d = (+digits[i] - +digits[i - 1] + 10) % 10;
    if (d !== 1) asc = false;
    if (d !== 9) desc = false;
  }
  return asc || desc;
}

async function validatePhoneAsync(num, iso) {
  const trimmed = (num || '').trim();
  if (!trimmed) return { ok: false, reason: 'Phone number is required' };
  const digits = (trimmed.match(/\d/g) || []).length;
  if (digits < 6) return { ok: false, reason: 'Enter a valid phone number' };
  // Pre-filter: junk patterns are rejected before we even look at the library.
  // Without this, a network/ad-blocker that prevents esm.sh from loading would
  // fall through to the digit-count fallback below and accept e.g. 14 ones.
  if (looksLikeJunkPhone(trimmed)) return { ok: false, reason: 'Enter a valid phone number' };

  const lib = await loadPhoneLib();
  if (!lib) {
    // Library failed to load. Conservative fallback: require 8+ digits.
    // Junk patterns already blocked above.
    return digits >= 8 ? { ok: true } : { ok: false, reason: 'Enter a valid phone number' };
  }
  try {
    const parser = lib.parsePhoneNumberFromString || (lib.default && lib.default.parsePhoneNumberFromString);
    if (!parser) return digits >= 8 ? { ok: true } : { ok: false, reason: 'Enter a valid phone number' };
    const parsed = parser(trimmed, iso || 'US');
    if (parsed && parsed.isValid()) return { ok: true };
    return { ok: false, reason: 'Enter a valid phone number for this country' };
  } catch (e) {
    return digits >= 8 ? { ok: true } : { ok: false, reason: 'Enter a valid phone number' };
  }
}

async function submitWaitlist(payload) {
  // Calls the public.submit_waitlist_signup SECURITY DEFINER RPC.
  // The function dedups on lower(trim(email)) — same email = same spot id,
  // just with the latest answers. Returns { id, status: 'new' | 'updated' }.
  const res = await fetch(`${SUPABASE_URL}/rest/v1/rpc/submit_waitlist_signup`, {
    method: 'POST',
    headers: {
      apikey: SUPABASE_ANON_KEY,
      Authorization: `Bearer ${SUPABASE_ANON_KEY}`,
      'Content-Type': 'application/json',
      Accept: 'application/json',
    },
    body: JSON.stringify({
      p_name: payload.name.trim(),
      p_email: payload.email.trim(),
      p_phone: payload.phone.trim(),
      p_bottleneck: payload.bottleneck,
      p_ai_level: payload.aiLevel,
      p_bottleneck_other: payload.bottleneck === 'Other' ? payload.bottleneckOther.trim() : null,
      p_ai_level_other: payload.aiLevel === 'Other' ? payload.aiLevelOther.trim() : null,
      p_honeypot: payload.honeypot || null,
    }),
  });
  if (!res.ok) {
    const body = await res.text().catch(() => '');
    throw new Error(`Waitlist submit failed (${res.status}): ${body}`);
  }
  return res.json().catch(() => null); // { id, status } | null
}

// ── Animation helpers ─────────────────────────────────────────────────
// useInView: fires once when the element enters the viewport.
// Uses a double-rAF after the observer fires so the initial opacity:0 paint
// is guaranteed to commit before the state flips — otherwise the CSS
// transition collapses on first paint (which is why first-load reveals
// often "skip" the animation).
function useInView({ threshold = 0.12, rootMargin = '0px 0px -8% 0px' } = {}) {
  const ref = React.useRef(null);
  const [inView, setInView] = React.useState(false);
  React.useEffect(() => {
    if (typeof IntersectionObserver === 'undefined') { setInView(true); return; }
    const el = ref.current;
    if (!el) return;
    let raf1, raf2;
    const obs = new IntersectionObserver(([entry]) => {
      if (!entry.isIntersecting) return;
      obs.disconnect();
      raf1 = requestAnimationFrame(() => {
        raf2 = requestAnimationFrame(() => setInView(true));
      });
    }, { threshold, rootMargin });
    obs.observe(el);
    return () => {
      obs.disconnect();
      if (raf1) cancelAnimationFrame(raf1);
      if (raf2) cancelAnimationFrame(raf2);
    };
  }, []);
  return [ref, inView];
}

// Reveal: scroll-triggered fade-up wrapper. delay in ms, distance in px.
function Reveal({ children, delay = 0, distance = 16, duration = 650, style, asGridItem }) {
  const [ref, inView] = useInView();
  return (
    <div ref={ref} style={{
      opacity: inView ? 1 : 0,
      transform: inView ? 'translateY(0)' : `translateY(${distance}px)`,
      transition: `opacity ${duration}ms cubic-bezier(.2,.7,.2,1) ${delay}ms, transform ${duration}ms cubic-bezier(.2,.7,.2,1) ${delay}ms`,
      willChange: 'opacity, transform',
      ...(asGridItem ? { height: '100%', display: 'flex', flexDirection: 'column' } : null),
      ...style,
    }}>
      {asGridItem
        ? React.Children.map(children, c => React.isValidElement(c)
            ? React.cloneElement(c, { style: { ...c.props.style, flex: 1 } })
            : c)
        : children}
    </div>
  );
}

// AnimatedNumber: counts 0 → value with ease-out, triggered when in view.
function AnimatedNumber({ value, duration = 1100, prefix = '', suffix = '' }) {
  const [ref, inView] = useInView({ threshold: 0.4 });
  const [n, setN] = React.useState(0);
  React.useEffect(() => {
    if (!inView) return;
    let raf;
    const t0 = performance.now();
    const tick = (now) => {
      const t = Math.min(1, (now - t0) / duration);
      const eased = 1 - Math.pow(1 - t, 3);
      setN(Math.round(value * eased));
      if (t < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [inView, value, duration]);
  return <span ref={ref}>{prefix}{n}{suffix}</span>;
}

// TerminalText: type-on-reveal text. Reveals chunkSize chars every speed ms once start=true.
function TerminalText({ text, start, speed = 14, chunkSize = 2 }) {
  const [idx, setIdx] = React.useState(0);
  React.useEffect(() => {
    if (!start) return;
    if (idx >= text.length) return;
    const t = setTimeout(() => setIdx(i => Math.min(i + chunkSize, text.length)), speed);
    return () => clearTimeout(t);
  }, [start, idx, text.length, speed, chunkSize]);
  return text.slice(0, idx);
}

const TERMINAL_TEXT_DESKTOP = `$ blueprint --join

Welcome to The AI Blueprint community.

  1. Content Engine        ▸ ready
  2. AI Ads Engine         ▸ ready
  3. Internal Dashboard    ▸ ready

> Claim your founding spot? `;

const TERMINAL_TEXT_MOBILE = `$ blueprint --join
Welcome to the community.
1. Content Engine ▸ ready
2. AI Ads Engine ▸ ready
3. Internal Dashboard ▸ ready`;

function TerminalPreviewDesktop() {
  const [ref, inView] = useInView({ threshold: 0.25 });
  const typed = TerminalText({ text: TERMINAL_TEXT_DESKTOP, start: inView, speed: 12, chunkSize: 2 });
  const done = typed.length >= TERMINAL_TEXT_DESKTOP.length;
  return (
    <div ref={ref} style={{
      background: BRAND.bgPanel, borderRadius: 12,
      border: `1px solid ${BRAND.ruleHi}`,
      padding: 24, position: 'relative',
      overflow: 'hidden',
      aspectRatio: '4 / 3',
    }}>
      <div style={{ display: 'flex', gap: 6, marginBottom: 16 }}>
        <span style={{ width: 10, height: 10, borderRadius: 5, background: '#FF5F57' }} />
        <span style={{ width: 10, height: 10, borderRadius: 5, background: '#FEBC2E' }} />
        <span style={{ width: 10, height: 10, borderRadius: 5, background: '#28C840' }} />
        <span style={{ marginLeft: 14, fontFamily: BRAND.mono, fontSize: 11, color: BRAND.inkDim }}>blueprint.sh — claude</span>
      </div>
      <pre style={{
        margin: 0, fontFamily: BRAND.mono, fontSize: 13, color: BRAND.ink, lineHeight: 1.6,
        whiteSpace: 'pre-wrap',
      }}>
        {typed}
        <span style={{
          background: BRAND.accent, color: '#1a0d07', padding: '0 6px',
          animation: done ? 'bp-blink 1s steps(2) infinite' : 'none',
          opacity: done ? 1 : 0.9,
        }}>_</span>
      </pre>
      <style>{`@keyframes bp-blink {50% {opacity: 0}}`}</style>
      <div style={{
        position: 'absolute', right: 18, bottom: 18,
        animation: 'bp-float 5s ease-in-out infinite',
      }}>
        <Mascot size={56} variant="lookLeft" />
      </div>
    </div>
  );
}

function TerminalPreviewMobile() {
  const [ref, inView] = useInView({ threshold: 0.3 });
  const typed = TerminalText({ text: TERMINAL_TEXT_MOBILE, start: inView, speed: 16, chunkSize: 2 });
  return (
    <div ref={ref} style={{
      marginTop: 28,
      background: BRAND.bgPanel, borderRadius: 10,
      border: `1px solid ${BRAND.ruleHi}`,
      padding: 14,
    }}>
      <div style={{ display: 'flex', gap: 5, marginBottom: 12, alignItems: 'center' }}>
        <span style={{ width: 8, height: 8, borderRadius: 4, background: '#FF5F57' }} />
        <span style={{ width: 8, height: 8, borderRadius: 4, background: '#FEBC2E' }} />
        <span style={{ width: 8, height: 8, borderRadius: 4, background: '#28C840' }} />
        <span style={{ marginLeft: 10, fontFamily: BRAND.mono, fontSize: 9, color: BRAND.inkFaint, letterSpacing: '0.04em' }}>
          blueprint.sh — claude
        </span>
      </div>
      <pre style={{
        margin: 0, fontFamily: BRAND.mono, fontSize: 11, color: BRAND.inkDim,
        whiteSpace: 'pre-wrap', minHeight: 96, lineHeight: 1.55,
      }}>
        {typed}
        <span style={{
          background: BRAND.accent, color: '#1a0d07', padding: '0 4px', marginLeft: 1,
          animation: 'bp-blink 1s steps(2) infinite',
        }}>_</span>
      </pre>
    </div>
  );
}

// Founder photo: real headshot cutout (transparent PNG) over a dark backdrop.
// Container aspect ratio matches the source images (612x854 → 0.717).
function FounderPhoto({ src, name, w, h }) {
  return (
    <div style={{
      width: w, height: h,
      flexShrink: 0,
      borderRadius: 6,
      background: 'linear-gradient(135deg, #2a2a2a, #1a1a1a)',
      border: `1px solid ${BRAND.ruleHi}`,
      position: 'relative',
      overflow: 'hidden',
    }}>
      {/* subtle diagonal stripe backdrop, same texture as the original placeholder */}
      <div style={{
        position: 'absolute', inset: 0,
        backgroundImage: 'repeating-linear-gradient(135deg, transparent 0 6px, rgba(255,255,255,0.04) 6px 7px)',
        pointerEvents: 'none',
      }} />
      <img
        src={src}
        alt={name}
        loading="lazy"
        style={{
          position: 'absolute', inset: 0,
          width: '100%', height: '100%',
          objectFit: 'cover',
          objectPosition: 'center top',
          display: 'block',
        }}
      />
    </div>
  );
}

function BPSpecLabel({ n, label, style }) {
  // left-rail spec-document label. n is the section index.
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 8,
      fontFamily: BRAND.mono, fontSize: 9, letterSpacing: '0.18em',
      color: BRAND.inkDim, textTransform: 'uppercase',
      ...style,
    }}>
      <span style={{ color: BRAND.accent }}>{String(n).padStart(2, '0')}</span>
      <span style={{ height: 1, width: 14, background: BRAND.ruleHi }} />
      <span>{label}</span>
    </div>
  );
}

function BPFormField({
  label, placeholder, type = 'text', value, onChange,
  error,            // string | null — current validation error (shown after touched)
  suggestion,       // string | null — "Did you mean ___?" fix (shown after touched, no error)
  onAcceptSuggestion, // () => void — called when user clicks the suggestion
  autoComplete,
  maxLength,
}) {
  const [touched, setTouched] = React.useState(false);
  const showError = touched && !!error;
  const showSuggestion = touched && !error && !!suggestion;
  return (
    <label style={{ display: 'block' }}>
      <div style={{
        fontFamily: BRAND.mono, fontSize: 10, letterSpacing: '0.2em',
        color: BRAND.inkDim, textTransform: 'uppercase', marginBottom: 6,
      }}>{label}</div>
      <input
        type={type} placeholder={placeholder} value={value} onChange={onChange}
        autoComplete={autoComplete}
        maxLength={maxLength}
        style={{
          width: '100%', boxSizing: 'border-box',
          padding: '14px 14px',
          background: '#0a0a0a',
          border: `1px solid ${showError ? BRAND.accent : BRAND.ruleHi}`,
          borderRadius: 6,
          color: BRAND.ink,
          fontFamily: BRAND.body, fontSize: 15,
          outline: 'none',
          transition: 'border-color .12s',
        }}
        onFocus={e => { e.target.style.borderColor = BRAND.accent; }}
        onBlur={e => {
          setTouched(true);
          e.target.style.borderColor = showError || !!error ? BRAND.accent : BRAND.ruleHi;
        }}
      />
      {showError && (
        <div style={{
          marginTop: 6, fontFamily: BRAND.body, fontSize: 12, color: BRAND.accent,
          lineHeight: 1.4,
        }}>{error}</div>
      )}
      {showSuggestion && (
        <div style={{
          marginTop: 6, fontFamily: BRAND.body, fontSize: 12, color: BRAND.inkDim,
          lineHeight: 1.4,
        }}>
          Did you mean{' '}
          <button
            type="button"
            onClick={onAcceptSuggestion}
            style={{
              background: 'transparent', border: 'none', padding: 0,
              color: BRAND.accent, fontFamily: BRAND.body, fontSize: 12,
              textDecoration: 'underline', cursor: 'pointer',
            }}
          >{suggestion}</button>
          ?
        </div>
      )}
    </label>
  );
}

function BPCTAButton({ children, full, onClick, style, disabled, type }) {
  const baseShadow = `0 0 0 1px ${BRAND.accentDim}, 0 18px 40px -16px ${BRAND.accentGlow}`;
  const hoverShadow = `0 0 0 1px ${BRAND.accentDim}, 0 22px 50px -14px ${BRAND.accentGlow}, 0 8px 24px -12px ${BRAND.accentGlow}`;
  return (
    <button type={type || 'submit'} onClick={onClick} disabled={disabled}
      onMouseEnter={e => {
        if (disabled) return;
        e.currentTarget.style.transform = 'translateY(-1px)';
        e.currentTarget.style.boxShadow = hoverShadow;
        const arrow = e.currentTarget.querySelector('[data-arrow]');
        if (arrow) arrow.style.transform = 'translateX(3px)';
      }}
      onMouseLeave={e => {
        e.currentTarget.style.transform = 'translateY(0)';
        e.currentTarget.style.boxShadow = baseShadow;
        const arrow = e.currentTarget.querySelector('[data-arrow]');
        if (arrow) arrow.style.transform = 'translateX(0)';
      }}
      style={{
        width: full ? '100%' : 'auto',
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 10,
        padding: '16px 22px',
        background: BRAND.accent,
        color: '#1a0d07',
        border: 'none',
        borderRadius: 6,
        fontFamily: BRAND.display, fontSize: 15, letterSpacing: '0.04em',
        textTransform: 'uppercase',
        cursor: disabled ? 'not-allowed' : 'pointer',
        opacity: disabled ? 0.45 : 1,
        boxShadow: baseShadow,
        transform: 'translateY(0)',
        transition: 'transform .2s cubic-bezier(.2,.7,.2,1), box-shadow .2s cubic-bezier(.2,.7,.2,1), opacity .12s',
        ...style,
      }}>
      <span>{children}</span>
      <span data-arrow style={{ fontFamily: BRAND.mono, fontSize: 13, transition: 'transform .2s cubic-bezier(.2,.7,.2,1)' }}>→</span>
    </button>
  );
}

// iso is the ISO 3166-1 alpha-2 country code, used by libphonenumber to pick
// the correct national format / validation rules when the user types digits
// without a leading "+".
const COUNTRIES = [
  { code: '+1',   iso: 'US', label: '+1 US/CA' },
  { code: '+44',  iso: 'GB', label: '+44 UK' },
  { code: '+61',  iso: 'AU', label: '+61 Australia' },
  { code: '+64',  iso: 'NZ', label: '+64 New Zealand' },
  { code: '+353', iso: 'IE', label: '+353 Ireland' },
  { code: '+33',  iso: 'FR', label: '+33 France' },
  { code: '+49',  iso: 'DE', label: '+49 Germany' },
  { code: '+34',  iso: 'ES', label: '+34 Spain' },
  { code: '+39',  iso: 'IT', label: '+39 Italy' },
  { code: '+31',  iso: 'NL', label: '+31 Netherlands' },
  { code: '+351', iso: 'PT', label: '+351 Portugal' },
  { code: '+41',  iso: 'CH', label: '+41 Switzerland' },
  { code: '+43',  iso: 'AT', label: '+43 Austria' },
  { code: '+32',  iso: 'BE', label: '+32 Belgium' },
  { code: '+46',  iso: 'SE', label: '+46 Sweden' },
  { code: '+47',  iso: 'NO', label: '+47 Norway' },
  { code: '+45',  iso: 'DK', label: '+45 Denmark' },
  { code: '+358', iso: 'FI', label: '+358 Finland' },
  { code: '+48',  iso: 'PL', label: '+48 Poland' },
  { code: '+91',  iso: 'IN', label: '+91 India' },
  { code: '+971', iso: 'AE', label: '+971 UAE' },
  { code: '+966', iso: 'SA', label: '+966 Saudi Arabia' },
  { code: '+972', iso: 'IL', label: '+972 Israel' },
  { code: '+27',  iso: 'ZA', label: '+27 South Africa' },
  { code: '+234', iso: 'NG', label: '+234 Nigeria' },
  { code: '+254', iso: 'KE', label: '+254 Kenya' },
  { code: '+65',  iso: 'SG', label: '+65 Singapore' },
  { code: '+852', iso: 'HK', label: '+852 Hong Kong' },
  { code: '+60',  iso: 'MY', label: '+60 Malaysia' },
  { code: '+62',  iso: 'ID', label: '+62 Indonesia' },
  { code: '+63',  iso: 'PH', label: '+63 Philippines' },
  { code: '+66',  iso: 'TH', label: '+66 Thailand' },
  { code: '+84',  iso: 'VN', label: '+84 Vietnam' },
  { code: '+81',  iso: 'JP', label: '+81 Japan' },
  { code: '+82',  iso: 'KR', label: '+82 South Korea' },
  { code: '+86',  iso: 'CN', label: '+86 China' },
  { code: '+886', iso: 'TW', label: '+886 Taiwan' },
  { code: '+52',  iso: 'MX', label: '+52 Mexico' },
  { code: '+55',  iso: 'BR', label: '+55 Brazil' },
  { code: '+54',  iso: 'AR', label: '+54 Argentina' },
  { code: '+56',  iso: 'CL', label: '+56 Chile' },
  { code: '+57',  iso: 'CO', label: '+57 Colombia' },
];

// Parse a "+CC USER_NUMBER" string back into {dial, iso, num} so the
// field can restore its state after a remount (e.g. viewport rotation
// triggering a Desktop ⇄ Mobile swap, or sessionStorage rehydration).
function parseInitialPhone(value) {
  if (typeof value !== 'string' || !value) return { dial: '+1', iso: 'US', num: '' };
  const sp = value.indexOf(' ');
  if (sp <= 0) return { dial: '+1', iso: 'US', num: value.trim() };
  const d = value.slice(0, sp).trim();
  const found = COUNTRIES.find(c => c.code === d);
  if (found) return { dial: found.code, iso: found.iso, num: value.slice(sp + 1).trim() };
  return { dial: '+1', iso: 'US', num: value.trim() };
}

function BPPhoneField({ label, initialValue, onChange, onValidChange }) {
  // useMemo with [] so the initial parse only runs once, even if the parent
  // re-renders with a different `initialValue`.
  const initial = React.useMemo(() => parseInitialPhone(initialValue), []);
  const [dial, setDial] = React.useState(initial.dial);
  const [iso, setIso] = React.useState(initial.iso);
  const [num, setNum] = React.useState(initial.num);
  const [focused, setFocused] = React.useState(false);
  const [open, setOpen] = React.useState(false);
  const [query, setQuery] = React.useState('');
  const [touched, setTouched] = React.useState(false);
  const [error, setError] = React.useState(null);
  const wrapRef = React.useRef(null);
  const searchRef = React.useRef(null);
  const libLoadedRef = React.useRef(false);
  const validateIdRef = React.useRef(0);

  React.useEffect(() => {
    if (!open) { setQuery(''); return; }
    const onDoc = e => { if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false); };
    const onKey = e => { if (e.key === 'Escape') setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    document.addEventListener('keydown', onKey);
    const t = setTimeout(() => searchRef.current && searchRef.current.focus(), 30);
    return () => {
      document.removeEventListener('mousedown', onDoc);
      document.removeEventListener('keydown', onKey);
      clearTimeout(t);
    };
  }, [open]);

  // Re-validate whenever the number or selected country changes.
  // Uses a stale-id guard so a fast typer doesn't flash old results when
  // the async libphonenumber load resolves out of order.
  React.useEffect(() => {
    const trimmed = num.trim();
    const myId = ++validateIdRef.current;
    if (!trimmed) {
      setError(null);
      onValidChange && onValidChange(false);
      return;
    }
    validatePhoneAsync(trimmed, iso).then(result => {
      if (myId !== validateIdRef.current) return;
      setError(result.ok ? null : result.reason);
      onValidChange && onValidChange(result.ok);
    });
  }, [num, iso, onValidChange]);

  const triggerLibLoad = () => {
    if (!libLoadedRef.current) {
      libLoadedRef.current = true;
      loadPhoneLib();
    }
  };

  const emit = (d, n) => onChange && onChange({ target: { value: n ? `${d} ${n}`.trim() : '' } });
  const placeholder = dial === '+1' ? '(555) 123-4567' : 'Phone number';
  const q = query.trim().toLowerCase();
  const filtered = q
    ? COUNTRIES.filter(c => c.label.toLowerCase().includes(q))
    : COUNTRIES;

  const showError = touched && !!error;
  const wrapperBorder = showError
    ? BRAND.accent
    : (focused || open) ? BRAND.accent : BRAND.ruleHi;

  return (
    <label style={{ display: 'block', position: 'relative' }} ref={wrapRef}>
      <div style={{
        fontFamily: BRAND.mono, fontSize: 10, letterSpacing: '0.2em',
        color: BRAND.inkDim, textTransform: 'uppercase', marginBottom: 6,
      }}>{label}</div>
      <div style={{
        display: 'flex', alignItems: 'stretch',
        background: '#0a0a0a',
        border: `1px solid ${wrapperBorder}`,
        borderRadius: 6, overflow: 'hidden',
        transition: 'border-color .12s',
      }}>
        <button
          type="button"
          onClick={() => { triggerLibLoad(); setOpen(o => !o); }}
          onFocus={() => { setFocused(true); triggerLibLoad(); }}
          onBlur={() => setFocused(false)}
          aria-haspopup="listbox"
          aria-expanded={open}
          aria-label="Select country code"
          style={{
            display: 'inline-flex', alignItems: 'center', gap: 8,
            background: 'transparent',
            color: BRAND.ink,
            fontFamily: BRAND.body, fontSize: 15,
            border: 'none',
            borderRight: `1px solid ${BRAND.ruleHi}`,
            padding: '14px 12px 14px 14px',
            outline: 'none',
            cursor: 'pointer',
            whiteSpace: 'nowrap',
          }}
        >
          <span>{dial}</span>
          <svg width="10" height="6" viewBox="0 0 10 6" aria-hidden="true" style={{
            transform: open ? 'rotate(180deg)' : 'none',
            transition: 'transform .15s',
            flexShrink: 0,
          }}>
            <path d="M1 1l4 4 4-4" stroke={BRAND.accent} strokeWidth="1.5" fill="none" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        </button>
        <input
          type="tel"
          inputMode="tel"
          autoComplete="tel-national"
          placeholder={placeholder}
          value={num}
          onChange={e => {
            const v = e.target.value;
            // Auto-sync the dial dropdown when the user pastes/types a "+CC" prefix.
            // Longest match first so "+1" doesn't claim "+44".
            if (v.startsWith('+')) {
              const sorted = [...COUNTRIES].sort((a, b) => b.code.length - a.code.length);
              for (const c of sorted) {
                if (v.startsWith(c.code) && (v.length === c.code.length || /[\s\d]/.test(v[c.code.length]))) {
                  const stripped = v.slice(c.code.length).trim();
                  setDial(c.code); setIso(c.iso); setNum(stripped); emit(c.code, stripped);
                  return;
                }
              }
            }
            setNum(v); emit(dial, v);
          }}
          onFocus={() => { setFocused(true); triggerLibLoad(); }}
          onBlur={() => { setFocused(false); setTouched(true); }}
          style={{
            flex: 1, minWidth: 0,
            background: 'transparent',
            color: BRAND.ink,
            fontFamily: BRAND.body, fontSize: 15,
            border: 'none',
            padding: '14px 14px',
            outline: 'none',
          }}
        />
      </div>
      {showError && (
        <div style={{
          marginTop: 6, fontFamily: BRAND.body, fontSize: 12, color: BRAND.accent,
          lineHeight: 1.4,
        }}>{error}</div>
      )}
      {open && (
        <div role="listbox" style={{
          position: 'absolute',
          top: 'calc(100% + 6px)', left: 0,
          width: '100%', minWidth: 260,
          background: BRAND.bgRaise,
          border: `1px solid ${BRAND.ruleHi}`,
          borderRadius: 8,
          boxShadow: `0 24px 48px -16px rgba(0,0,0,0.7), 0 0 0 1px ${BRAND.rule}`,
          zIndex: 60,
          overflow: 'hidden',
        }}>
          <div style={{
            padding: 8,
            borderBottom: `1px solid ${BRAND.rule}`,
            background: BRAND.bgPanel,
          }}>
            <input
              ref={searchRef}
              type="text"
              placeholder="Search country or code"
              value={query}
              onChange={e => setQuery(e.target.value)}
              style={{
                width: '100%', boxSizing: 'border-box',
                background: '#0a0a0a',
                color: BRAND.ink,
                fontFamily: BRAND.body, fontSize: 13,
                border: `1px solid ${BRAND.ruleHi}`,
                borderRadius: 4,
                padding: '8px 10px',
                outline: 'none',
              }}
              onFocus={e => e.target.style.borderColor = BRAND.accent}
              onBlur={e => e.target.style.borderColor = BRAND.ruleHi}
            />
          </div>
          <div style={{ maxHeight: 240, overflowY: 'auto' }}>
            {filtered.length === 0 ? (
              <div style={{
                padding: '14px 14px',
                fontFamily: BRAND.body, fontSize: 13, color: BRAND.inkFaint,
              }}>No matches</div>
            ) : filtered.map(c => {
              const isSelected = c.code === dial && c.iso === iso;
              return (
                <button
                  key={c.label}
                  type="button"
                  role="option"
                  aria-selected={isSelected}
                  onClick={() => {
                    setDial(c.code);
                    setIso(c.iso || 'US');
                    setOpen(false);
                    emit(c.code, num);
                  }}
                  onMouseEnter={e => { if (!isSelected) e.currentTarget.style.background = 'rgba(255,255,255,0.04)'; }}
                  onMouseLeave={e => { if (!isSelected) e.currentTarget.style.background = 'transparent'; }}
                  style={{
                    width: '100%',
                    display: 'flex', alignItems: 'center', gap: 12,
                    background: isSelected ? BRAND.accentSoft : 'transparent',
                    border: 'none',
                    color: isSelected ? BRAND.accent : BRAND.ink,
                    fontFamily: BRAND.body, fontSize: 14,
                    padding: '10px 14px',
                    textAlign: 'left',
                    cursor: 'pointer',
                  }}
                >
                  <span style={{
                    fontFamily: BRAND.mono, fontSize: 12,
                    color: isSelected ? BRAND.accent : BRAND.inkDim,
                    minWidth: 44,
                  }}>{c.code}</span>
                  <span style={{ flex: 1 }}>{c.label.replace(c.code, '').trim()}</span>
                  {isSelected && (
                    <svg width="12" height="12" viewBox="0 0 12 12" aria-hidden="true">
                      <path d="M2 6l3 3 5-6" stroke={BRAND.accent} strokeWidth="1.8" fill="none" strokeLinecap="round" strokeLinejoin="round" />
                    </svg>
                  )}
                </button>
              );
            })}
          </div>
        </div>
      )}
    </label>
  );
}

const BOTTLENECK_OPTIONS = [
  'Content creation',
  'Sales & follow-up',
  'Lead generation / ads',
  'Customer support',
  'Ops & admin',
  'Hiring / team management',
  'Other',
];

const AI_LEVEL_OPTIONS = [
  "Haven't really used them",
  'Use ChatGPT casually',
  'Built a few automations (Make / Zapier)',
  'Used Claude or Claude Code',
  'Already running AI systems in production',
  'Other',
];

function BPQuestion({ question, options, value, onSelect, otherValue, onOtherChange, compact }) {
  return (
    <div>
      <div style={{
        fontFamily: BRAND.body, fontSize: 14, color: BRAND.ink,
        marginBottom: 10, lineHeight: 1.35,
      }}>{question}</div>
      <div style={{
        display: 'grid',
        gap: 8,
        gridTemplateColumns: compact ? '1fr' : 'repeat(2, minmax(0, 1fr))',
      }}>
        {options.map(opt => {
          const selected = value === opt;
          return (
            <button
              key={opt}
              type="button"
              role="radio"
              aria-checked={selected}
              onClick={() => onSelect(opt)}
              style={{
                display: 'flex', alignItems: 'center', gap: 10,
                padding: '11px 12px',
                background: selected ? BRAND.accentSoft : '#0a0a0a',
                border: `1px solid ${selected ? BRAND.accent : BRAND.ruleHi}`,
                borderRadius: 6,
                cursor: 'pointer',
                color: selected ? BRAND.accent : BRAND.ink,
                fontFamily: BRAND.body, fontSize: 13,
                textAlign: 'left',
                transition: 'background .12s, border-color .12s, color .12s',
              }}
            >
              <span style={{
                width: 14, height: 14, borderRadius: 7,
                border: `1.5px solid ${selected ? BRAND.accent : BRAND.ruleHi}`,
                background: selected ? BRAND.accent : 'transparent',
                flexShrink: 0,
                boxShadow: selected ? `inset 0 0 0 3px ${BRAND.bgPanel}` : 'none',
                transition: 'all .12s',
              }} />
              <span>{opt}</span>
            </button>
          );
        })}
      </div>
      {value === 'Other' && (
        <input
          type="text"
          required
          placeholder="Tell us more"
          value={otherValue}
          onChange={e => onOtherChange(e.target.value)}
          style={{
            width: '100%', boxSizing: 'border-box',
            marginTop: 10,
            padding: '12px 12px',
            background: '#0a0a0a',
            color: BRAND.ink,
            fontFamily: BRAND.body, fontSize: 14,
            border: `1px solid ${BRAND.accent}`,
            borderRadius: 6,
            outline: 'none',
          }}
        />
      )}
    </div>
  );
}

// ConfirmationPanel — the post-submit panel, extracted from BPForm so the
// same UI can render inline (BPForm fallback) AND as a full-page experience
// via ConfirmationPage.
function ConfirmationPanel({ spotId, name, email, phone, returning, compact = false }) {
  const displayName = (name || '').trim().split(/\s+/)[0] || 'founder';
  const igLinks = [
    { handle: 'karam.mahaan', url: 'https://instagram.com/karam.mahaan' },
    { handle: 'varunmahaan_', url: 'https://instagram.com/varunmahaan_' },
  ];
  const receiptRows = [
    ['Your spot',       spotId || 'BPM-CLAIMED',     true],
    ['Locked for life', '$47/month',                 true],
    ['Regular price',   '$97/month',                 false],
    ['Email',           (email || '').trim(),        false],
    ['Phone',           (phone || '').trim(),        false],
  ];
  return (
    <div style={{
      padding: compact ? 22 : 32,
      background: BRAND.bgPanel,
      border: `1px solid ${BRAND.accent}`,
      borderRadius: 10,
      boxShadow: `0 30px 60px -30px rgba(0,0,0,0.7), 0 0 80px -30px ${BRAND.accentGlow}`,
      position: 'relative', zIndex: 5,
      animation: 'bp-form-mount .7s cubic-bezier(.2,.7,.2,1) backwards',
    }}>
      <div style={{
        display: 'inline-block',
        background: BRAND.accent, color: '#1a0d07',
        fontFamily: BRAND.display, fontSize: 10, letterSpacing: '0.14em',
        padding: '5px 9px',
        marginBottom: compact ? 16 : 20,
        animation: 'bp-field-in .5s cubic-bezier(.2,.7,.2,1) .1s backwards',
      }}>
        {returning ? 'ALREADY ON THE LIST · ANSWERS UPDATED' : 'WAITLIST MEMBER · FOUNDING SPOT CLAIMED'}
      </div>

      <div style={{
        fontFamily: BRAND.display,
        fontSize: compact ? 26 : 32, color: BRAND.ink, lineHeight: 1.05,
        marginBottom: 20,
        animation: 'bp-field-in .55s cubic-bezier(.2,.7,.2,1) .18s backwards',
      }}>
        {returning ? 'Welcome back,' : "You're in,"}{' '}
        <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400 }}>
          {displayName}.
        </span>
      </div>

      <div style={{
        background: '#0a0a0a',
        border: `1px solid ${BRAND.rule}`,
        borderRadius: 6,
        padding: compact ? '4px 14px' : '6px 18px',
        marginBottom: compact ? 18 : 22,
        animation: 'bp-field-in .55s cubic-bezier(.2,.7,.2,1) .26s backwards',
      }}>
        {receiptRows.map(([k, val, highlight], i, arr) => (
          <div key={k} style={{
            display: 'flex', justifyContent: 'space-between', alignItems: 'center',
            padding: '10px 0',
            borderBottom: i < arr.length - 1 ? `1px solid ${BRAND.rule}` : 'none',
            gap: 12,
          }}>
            <span style={{
              fontFamily: BRAND.mono, fontSize: 9,
              letterSpacing: '0.14em', textTransform: 'uppercase',
              color: BRAND.inkFaint,
              flexShrink: 0,
            }}>{k}</span>
            <span style={{
              fontFamily: BRAND.mono, fontSize: 12,
              color: highlight ? BRAND.accent : BRAND.ink,
              textAlign: 'right',
              wordBreak: 'break-all',
              maxWidth: '70%',
            }}>{val}</span>
          </div>
        ))}
      </div>

      <div style={{
        color: BRAND.inkDim, fontFamily: BRAND.body, fontSize: 14, lineHeight: 1.55,
        marginBottom: compact ? 22 : 26,
        animation: 'bp-field-in .55s cubic-bezier(.2,.7,.2,1) .34s backwards',
      }}>
        {returning
          ? <>Your spot stays the same. Your latest answers are saved — we'll text you when founding access opens.</>
          : <>We'll text you when founding access opens. First 50 to claim lock in <span style={{ color: BRAND.accent }}>$47/month</span> for life.</>
        }
      </div>

      <div style={{
        borderTop: `1px solid ${BRAND.ruleHi}`,
        paddingTop: compact ? 18 : 22,
        animation: 'bp-field-in .6s cubic-bezier(.2,.7,.2,1) .42s backwards',
      }}>
        <div style={{
          fontFamily: BRAND.mono, fontSize: 9, letterSpacing: '0.18em',
          color: BRAND.inkDim, textTransform: 'uppercase',
          marginBottom: 10,
        }}>
          While you wait
        </div>
        <div style={{
          fontFamily: BRAND.body, fontSize: 14, color: BRAND.ink, lineHeight: 1.55,
          marginBottom: 14,
        }}>
          Follow us on Instagram. We post the systems we build, the frameworks behind them, and behind-the-scenes from the community.
        </div>
        <div style={{
          display: 'grid',
          gridTemplateColumns: compact ? '1fr' : 'repeat(2, minmax(0, 1fr))',
          gap: 10,
        }}>
          {igLinks.map(({ handle, url }) => (
            <a
              key={handle}
              href={url}
              target="_blank"
              rel="noopener noreferrer"
              aria-label={`Follow @${handle} on Instagram`}
              onMouseEnter={e => {
                e.currentTarget.style.borderColor = BRAND.accent;
                e.currentTarget.style.transform = 'translateY(-1px)';
                e.currentTarget.style.background = BRAND.accentSoft;
              }}
              onMouseLeave={e => {
                e.currentTarget.style.borderColor = BRAND.ruleHi;
                e.currentTarget.style.transform = 'translateY(0)';
                e.currentTarget.style.background = '#0a0a0a';
              }}
              style={{
                display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                gap: 8,
                padding: '12px 14px',
                background: '#0a0a0a',
                border: `1px solid ${BRAND.ruleHi}`,
                borderRadius: 6,
                color: BRAND.ink,
                fontFamily: BRAND.body, fontSize: 14,
                textDecoration: 'none',
                transform: 'translateY(0)',
                transition: 'border-color .2s, transform .2s, background .2s',
                minWidth: 0,
              }}
            >
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 9, minWidth: 0 }}>
                <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke={BRAND.accent} strokeWidth="1.8" aria-hidden="true" style={{ flexShrink: 0 }}>
                  <rect x="3" y="3" width="18" height="18" rx="5" />
                  <circle cx="12" cy="12" r="4" />
                  <circle cx="17.5" cy="6.5" r="1" fill={BRAND.accent} stroke="none" />
                </svg>
                <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>@{handle}</span>
              </span>
              <span style={{ color: BRAND.accent, fontFamily: BRAND.mono, fontSize: 13, flexShrink: 0 }}>↗</span>
            </a>
          ))}
        </div>
      </div>
    </div>
  );
}

// sessionStorage key for in-progress form state — survives a remount within
// the same tab (e.g. viewport rotation swapping Desktop ⇄ Mobile components).
// Auto-cleared when the tab closes. Cleared on successful submit.
const BP_FORM_SS_KEY = 'bp_form_state';
function readFormStateFromSession() {
  try {
    const raw = sessionStorage.getItem(BP_FORM_SS_KEY);
    if (!raw) return null;
    const parsed = JSON.parse(raw);
    if (parsed && typeof parsed === 'object' && parsed.v && typeof parsed.step === 'number') {
      return parsed;
    }
  } catch (e) {}
  return null;
}

function BPForm({ compact }) {
  // Restore in-progress form state if the user got partway through and the
  // component remounted (rotation, resize across breakpoint, etc.)
  const ssInit = React.useMemo(() => readFormStateFromSession(), []);
  const [step, setStep] = React.useState(ssInit?.step || 1);
  const [direction, setDirection] = React.useState('forward'); // 'forward' | 'back'
  const [v, setV] = React.useState(() => ssInit?.v || {
    name: '', email: '', phone: '',
    bottleneck: '', bottleneckOther: '',
    aiLevel: '', aiLevelOther: '',
  });
  const [sent, setSent] = React.useState(false);
  const [submitting, setSubmitting] = React.useState(false);
  const [error, setError] = React.useState(null);
  const [spotId, setSpotId] = React.useState(null);
  const [returning, setReturning] = React.useState(false);
  const [phoneValid, setPhoneValid] = React.useState(false);
  const advanceTimerRef = React.useRef(null);
  const honeypotRef = React.useRef(null);
  const set = k => e => setV(s => ({ ...s, [k]: e.target.value }));
  const setVal = (k, val) => setV(s => ({ ...s, [k]: val }));

  React.useEffect(() => () => {
    if (advanceTimerRef.current) clearTimeout(advanceTimerRef.current);
  }, []);

  // Persist in-progress state on every change (cheap; sessionStorage is fast).
  React.useEffect(() => {
    if (sent) return; // don't persist once submitted
    try { sessionStorage.setItem(BP_FORM_SS_KEY, JSON.stringify({ step, v })); } catch (e) {}
  }, [step, v, sent]);

  // Clear persisted state once the signup succeeds.
  React.useEffect(() => {
    if (sent) {
      try { sessionStorage.removeItem(BP_FORM_SS_KEY); } catch (e) {}
    }
  }, [sent]);

  // Email validation: WHATWG syntax via cached <input type="email">.
  // Suggestion fires when format is valid but the domain looks like a typo
  // of a common provider (gmial.com → gmail.com, yhaoo.com → yahoo.com, …).
  const emailCheck = validateEmail(v.email);
  const emailValid = emailCheck.ok;
  const emailError = emailValid ? null : emailCheck.reason;
  const emailSuggestion = emailValid ? suggestEmailFix(v.email) : null;

  const otherOk = (sel, other) => sel !== 'Other' || other.trim().length > 0;
  const step1Valid = !!v.name.trim() && emailValid && phoneValid;
  const step2Valid = v.bottleneck && otherOk(v.bottleneck, v.bottleneckOther);
  const step3Valid = v.aiLevel && otherOk(v.aiLevel, v.aiLevelOther);

  const goBack = () => {
    if (step <= 1) return;
    if (advanceTimerRef.current) { clearTimeout(advanceTimerRef.current); advanceTimerRef.current = null; }
    setDirection('back');
    setStep(s => s - 1);
    setError(null);
  };

  // Step 2 (Q1) auto-advances to step 3 on a non-Other selection
  // after a short delay so the selected state visually registers first.
  const handleQ1Select = (val) => {
    setVal('bottleneck', val);
    if (advanceTimerRef.current) clearTimeout(advanceTimerRef.current);
    if (val !== 'Other') {
      advanceTimerRef.current = setTimeout(() => {
        setDirection('forward');
        setStep(3);
        advanceTimerRef.current = null;
      }, 250);
    }
  };

  const handleSubmit = async e => {
    e.preventDefault();
    if (step === 1) {
      if (!step1Valid) return;
      setDirection('forward');
      setStep(2);
      return;
    }
    if (step === 2) {
      if (!step2Valid) return;
      if (advanceTimerRef.current) { clearTimeout(advanceTimerRef.current); advanceTimerRef.current = null; }
      setDirection('forward');
      setStep(3);
      return;
    }
    // step === 3 → real backend submission
    if (!step3Valid || submitting) return;
    setSubmitting(true);
    setError(null);
    try {
      const honeypotValue = (honeypotRef.current && honeypotRef.current.value) || '';
      const result = await submitWaitlist({ ...v, honeypot: honeypotValue });
      const uuid = (result && typeof result === 'object' && typeof result.id === 'string') ? result.id : null;
      const hex = (uuid || '').replace(/[^a-f0-9]/gi, '').slice(0, 6).toUpperCase();
      const newSpotId = `BPM-${hex || 'CLAIMED'}`;
      const isReturning = !!(result && result.status === 'updated');
      setSpotId(newSpotId);
      setReturning(isReturning);
      // App listens for this and swaps to the full-page ConfirmationPage.
      try {
        window.dispatchEvent(new CustomEvent('bp:signup', {
          detail: {
            spotId: newSpotId,
            name: v.name.trim(),
            email: v.email.trim(),
            phone: v.phone.trim(),
            returning: isReturning,
          },
        }));
      } catch (_) { /* event dispatch best-effort */ }
      setSent(true);
    } catch (err) {
      console.error(err);
      setError("Something went wrong saving your spot. Check your details and try again.");
    } finally {
      setSubmitting(false);
    }
  };

  const stepAnim = direction === 'forward'
    ? 'bp-slide-in-right .42s cubic-bezier(.2,.7,.2,1) backwards'
    : 'bp-slide-in-left .42s cubic-bezier(.2,.7,.2,1) backwards';

  if (sent) {
    // Fallback only — App listens for the bp:signup event and swaps to
    // ConfirmationPage on the same render, so this rarely renders in practice.
    return <ConfirmationPanel
      spotId={spotId}
      name={v.name}
      email={v.email}
      phone={v.phone}
      returning={returning}
      compact={compact}
    />;
  }

  return (
    <form onSubmit={handleSubmit} style={{
      padding: compact ? 20 : 32,
      background: BRAND.bgPanel,
      border: `1px solid ${BRAND.ruleHi}`,
      borderRadius: 10,
      boxShadow: `0 30px 60px -30px rgba(0,0,0,0.7), 0 0 0 1px ${BRAND.rule}`,
      position: 'relative',
      zIndex: 5,
      animation: 'bp-form-mount .7s cubic-bezier(.2,.7,.2,1) backwards',
    }}>
      {/* corner ticks for a "blueprint" detail */}
      {[[8,8,'tl'],[8,8,'tr'],[8,8,'bl'],[8,8,'br']].map(([sz, , corner], i) => (
        <div key={i} style={{
          position: 'absolute',
          [corner[0] === 't' ? 'top' : 'bottom']: -1,
          [corner[1] === 'l' ? 'left' : 'right']: -1,
          width: sz, height: sz,
          borderTop: corner[0] === 't' ? `2px solid ${BRAND.accent}` : 'none',
          borderBottom: corner[0] === 'b' ? `2px solid ${BRAND.accent}` : 'none',
          borderLeft: corner[1] === 'l' ? `2px solid ${BRAND.accent}` : 'none',
          borderRight: corner[1] === 'r' ? `2px solid ${BRAND.accent}` : 'none',
          animation: `bp-corner-draw-${corner} .55s cubic-bezier(.2,.7,.2,1) ${0.35 + i * 0.05}s backwards`,
        }} />
      ))}
      {/* Honeypot — visually hidden, invisible to screen readers via aria-hidden,
          unreachable by keyboard via tabIndex=-1. A bot that auto-fills every
          input will fill this too; the RPC silently rejects when it's non-empty.
          Always rendered (outside step content) so the ref survives step changes. */}
      <div aria-hidden="true" style={{
        position: 'absolute', left: '-9999px', top: 'auto',
        width: 1, height: 1, overflow: 'hidden',
      }}>
        <label>
          Your website (leave blank)
          <input
            ref={honeypotRef}
            type="text"
            name="website"
            tabIndex={-1}
            autoComplete="off"
            defaultValue=""
          />
        </label>
      </div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: compact ? 14 : 18 }}>
        <Eyebrow>{step === 1 ? 'Founding waitlist · Skool community' : step === 2 ? 'Quick question' : 'Last step'}</Eyebrow>
        <span style={{ fontFamily: BRAND.mono, fontSize: 10, color: BRAND.inkFaint }}>step {step} / 3</span>
      </div>
      <div style={{
        fontFamily: BRAND.display, fontSize: compact ? 24 : 30, color: BRAND.ink, lineHeight: 1.1, marginBottom: compact ? 16 : 22,
      }}>
        {step === 1 ? (
          <>
            Join the waitlist.{' '}
            <span style={{ textDecoration: 'line-through', color: BRAND.inkFaint, fontSize: '0.7em', marginRight: 4 }}>$97</span>
            <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400 }}>$47/month</span>
            <span style={{ fontFamily: BRAND.body, fontSize: '0.55em', color: BRAND.inkDim, marginLeft: 6, textTransform: 'uppercase', letterSpacing: '0.1em' }}>locked for life</span>
          </>
        ) : step === 2 ? (
          <>About your <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400 }}>business.</span></>
        ) : (
          <>About your <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400 }}>AI experience.</span></>
        )}
      </div>

      <div key={step} style={{ animation: stepAnim }}>
        {step === 1 ? (
          <>
            <div style={{ display: 'grid', gap: compact ? 12 : 14 }}>
              {[
                <BPFormField key="n" label="Name"  placeholder="Your name" autoComplete="name" maxLength={80} value={v.name}  onChange={set('name')}  />,
                <BPFormField
                  key="e"
                  label="Email"
                  placeholder="you@email.com"
                  type="email"
                  autoComplete="email"
                  value={v.email}
                  onChange={set('email')}
                  error={emailError}
                  suggestion={emailSuggestion}
                  onAcceptSuggestion={() => emailSuggestion && setVal('email', emailSuggestion)}
                />,
                <BPPhoneField key="p" label="Phone" initialValue={v.phone} onChange={set('phone')} onValidChange={setPhoneValid} />,
              ].map((field, i) => (
                <div key={field.key} style={{
                  animation: `bp-field-in .45s cubic-bezier(.2,.7,.2,1) ${0.18 + i * 0.07}s backwards`,
                }}>{field}</div>
              ))}
            </div>
            <div style={{ animation: `bp-field-in .45s cubic-bezier(.2,.7,.2,1) ${0.18 + 3 * 0.07}s backwards` }}>
              <BPCTAButton full disabled={!step1Valid} style={{ marginTop: 18 }}>Continue</BPCTAButton>
            </div>
          </>
        ) : step === 2 ? (
          <>
            <div style={{ animation: 'bp-field-in .45s cubic-bezier(.2,.7,.2,1) .15s backwards' }}>
              <BPQuestion
                question="What's the biggest bottleneck in your business right now?"
                options={BOTTLENECK_OPTIONS}
                value={v.bottleneck}
                onSelect={handleQ1Select}
                otherValue={v.bottleneckOther}
                onOtherChange={val => setVal('bottleneckOther', val)}
                compact={compact}
              />
            </div>
            <div style={{ display: 'flex', gap: 10, marginTop: 18,
              animation: 'bp-field-in .45s cubic-bezier(.2,.7,.2,1) .3s backwards',
            }}>
              <button type="button" onClick={goBack} style={{
                padding: '14px 18px',
                background: 'transparent',
                color: BRAND.inkDim,
                border: `1px solid ${BRAND.ruleHi}`,
                borderRadius: 6,
                fontFamily: BRAND.mono, fontSize: 12, letterSpacing: '0.1em',
                textTransform: 'uppercase',
                cursor: 'pointer',
                transition: 'color .12s, border-color .12s',
              }}
                onMouseEnter={e => { e.currentTarget.style.color = BRAND.ink; e.currentTarget.style.borderColor = BRAND.accent; }}
                onMouseLeave={e => { e.currentTarget.style.color = BRAND.inkDim; e.currentTarget.style.borderColor = BRAND.ruleHi; }}
              >← Back</button>
              <BPCTAButton full disabled={!step2Valid}>Continue</BPCTAButton>
            </div>
          </>
        ) : (
          <>
            <div style={{ animation: 'bp-field-in .45s cubic-bezier(.2,.7,.2,1) .15s backwards' }}>
              <BPQuestion
                question="How comfortable are you with AI tools today?"
                options={AI_LEVEL_OPTIONS}
                value={v.aiLevel}
                onSelect={val => setVal('aiLevel', val)}
                otherValue={v.aiLevelOther}
                onOtherChange={val => setVal('aiLevelOther', val)}
                compact={compact}
              />
            </div>
            <div style={{ display: 'flex', gap: 10, marginTop: 18,
              animation: 'bp-field-in .45s cubic-bezier(.2,.7,.2,1) .3s backwards',
            }}>
              <button type="button" onClick={goBack} disabled={submitting} style={{
                padding: '14px 18px',
                background: 'transparent',
                color: BRAND.inkDim,
                border: `1px solid ${BRAND.ruleHi}`,
                borderRadius: 6,
                fontFamily: BRAND.mono, fontSize: 12, letterSpacing: '0.1em',
                textTransform: 'uppercase',
                cursor: submitting ? 'not-allowed' : 'pointer',
                opacity: submitting ? 0.5 : 1,
                transition: 'color .12s, border-color .12s, opacity .12s',
              }}
                onMouseEnter={e => { if (!submitting) { e.currentTarget.style.color = BRAND.ink; e.currentTarget.style.borderColor = BRAND.accent; } }}
                onMouseLeave={e => { e.currentTarget.style.color = BRAND.inkDim; e.currentTarget.style.borderColor = BRAND.ruleHi; }}
              >← Back</button>
              <BPCTAButton full disabled={!step3Valid || submitting}>
                {submitting ? 'Saving…' : CTA}
              </BPCTAButton>
            </div>
            {error && (
              <div style={{
                marginTop: 12, padding: '10px 12px',
                background: 'rgba(224,120,86,0.08)',
                border: `1px solid ${BRAND.accent}`,
                borderRadius: 6,
                fontFamily: BRAND.body, fontSize: 13, color: BRAND.accent,
              }}>{error}</div>
            )}
          </>
        )}
      </div>
      <div style={{
        marginTop: 12, fontFamily: BRAND.mono, fontSize: 10,
        color: BRAND.inkFaint, letterSpacing: '0.1em', textAlign: 'center',
      }}>
        {step === 1
          ? "Waitlist · we'll text you when founding access opens"
          : step === 2
          ? "Required · helps us tailor what we ship first"
          : "Last one · then you're on the list"}
      </div>
    </form>
  );
}

// ── 6-tile grid ────────────────────────────────────────────────────────
const TILES = [
  { k: 'guide',     title: 'Beginner Guide',    note: 'From zero to your first internal system.' },
  { k: 'templates', title: '10+ Templates',     note: 'Plug into your business, run same day.' },
  { k: 'skills',    title: 'Skills Library',    note: 'Library of 50+ skills across content, ads, agency, and productivity.' },
  { k: 'mcps',      title: 'MCPs & Tools',      note: 'Hook AI into the tools you already pay for.' },
  { k: 'master',    title: 'Master Claude Code',note: 'The engine behind every internal system you build.' },
  { k: 'experts',   title: 'Learn From Experts',note: 'Live builds with Varun & Karam, weekly.' },
];

function TileIcon({ k, size = 36, color = BRAND.accent }) {
  // simple pixel-style icons drawn with rects
  const c = color, b = '#1a1a1a';
  const common = {
    width: size, height: size, viewBox: '0 0 12 12',
    style: { imageRendering: 'pixelated', shapeRendering: 'crispEdges' },
  };
  switch (k) {
    case 'guide':
      return <svg {...common}>
        <rect x={1} y={2} width={10} height={8} fill={c} />
        <rect x={3} y={4} width={6} height={1} fill={b} />
        <rect x={3} y={6} width={6} height={1} fill={b} />
        <rect x={3} y={8} width={4} height={1} fill={b} />
      </svg>;
    case 'templates':
      return <svg {...common}>
        <rect x={1} y={1} width={6} height={4} fill={c} />
        <rect x={5} y={4} width={6} height={4} fill={c} />
        <rect x={2} y={7} width={6} height={4} fill={c} />
      </svg>;
    case 'skills':
      return <svg {...common}>
        <rect x={2} y={2} width={2} height={8} fill={c} />
        <rect x={5} y={2} width={2} height={8} fill={c} />
        <rect x={8} y={2} width={2} height={8} fill={c} />
        <rect x={2} y={5} width={8} height={2} fill={c} />
      </svg>;
    case 'mcps':
      return <svg {...common}>
        <rect x={1} y={5} width={2} height={2} fill={c} />
        <rect x={9} y={5} width={2} height={2} fill={c} />
        <rect x={5} y={1} width={2} height={2} fill={c} />
        <rect x={5} y={9} width={2} height={2} fill={c} />
        <rect x={5} y={5} width={2} height={2} fill={c} />
        <rect x={3} y={5} width={3} height={1} fill={c} />
        <rect x={6} y={6} width={3} height={1} fill={c} />
        <rect x={5} y={3} width={1} height={3} fill={c} />
        <rect x={6} y={6} width={1} height={3} fill={c} />
      </svg>;
    case 'master':
      return <svg {...common}>
        <rect x={4} y={1} width={1} height={2} fill={c} />
        <rect x={7} y={1} width={1} height={2} fill={c} />
        <rect x={3} y={3} width={6} height={1} fill={c} />
        <rect x={1} y={4} width={10} height={2} fill={c} />
        <rect x={2} y={6} width={8} height={5} fill={c} />
        <rect x={5} y={8} width={2} height={3} fill={b} />
      </svg>;
    case 'experts':
      return <svg {...common}>
        {/* crown */}
        <rect x={1} y={3} width={1} height={3} fill={c} />
        <rect x={5} y={3} width={1} height={3} fill={c} />
        <rect x={10} y={3} width={1} height={3} fill={c} />
        <rect x={3} y={2} width={1} height={1} fill={c} />
        <rect x={8} y={2} width={1} height={1} fill={c} />
        <rect x={1} y={6} width={10} height={3} fill={c} />
        <rect x={1} y={9} width={10} height={1} fill={c} />
      </svg>;
    default: return null;
  }
}

function BPTile({ k, title, note }) {
  return (
    <div
      onMouseEnter={e => {
        e.currentTarget.style.transform = 'translateY(-3px)';
        e.currentTarget.style.borderColor = BRAND.accent;
        e.currentTarget.style.boxShadow = `0 16px 36px -20px ${BRAND.accentGlow}`;
      }}
      onMouseLeave={e => {
        e.currentTarget.style.transform = 'translateY(0)';
        e.currentTarget.style.borderColor = BRAND.ruleHi;
        e.currentTarget.style.boxShadow = 'none';
      }}
      style={{
        background: BRAND.bgPanel,
        border: `1px solid ${BRAND.ruleHi}`,
        borderRadius: 10,
        padding: '24px 22px',
        position: 'relative',
        overflow: 'hidden',
        height: '100%',
        transform: 'translateY(0)',
        transition: 'transform .25s cubic-bezier(.2,.7,.2,1), border-color .25s, box-shadow .25s',
        cursor: 'default',
      }}>
      <div style={{
        position: 'absolute', top: 0, right: 0,
        fontFamily: BRAND.mono, fontSize: 10, color: BRAND.inkFaint,
        padding: '8px 10px',
      }}>0{TILES.findIndex(t => t.k === k) + 1}</div>
      <TileIcon k={k} size={36} />
      <div style={{
        fontFamily: BRAND.display, fontSize: 20, color: BRAND.ink, marginTop: 16, lineHeight: 1.1,
      }}>{title}</div>
      <div style={{
        fontFamily: BRAND.body, fontSize: 13, color: BRAND.inkDim, marginTop: 6,
      }}>{note}</div>
    </div>
  );
}

// ── FAQ ─────────────────────────────────────────────────────────────────
const FAQS = [
  {
    q: 'What is The AI Blueprint?',
    a: "A Skool community for business owners who want to install AI systems into their business — sales follow-ups, content, ads, ops, and support. Built on Claude, Claude Code, and the wider AI stack. Live builds every week with Varun and Karam, plus a growing library of templates, skills, and MCPs. The point: you scale your business without scaling your hours.",
  },
  {
    q: 'What will I actually walk out with?',
    a: "At least one internal AI system running in your business inside your first day — depending on your bottleneck, that's a content engine, an ads engine, a sales follow-up bot, or your internal dashboard. After that, a new template, skill, or MCP every week to plug into what you've already built.",
  },
  {
    q: 'How fast will I install my first system?',
    a: "Installing a pre-built system from the library takes about 5 minutes. Building your own from scratch takes a week or more — depends on the system's complexity and your skill level. We walk you through both inside the community.",
  },
  {
    q: 'Do I need to know how to code?',
    a: "No. Claude Code does the building — you direct it like an operator. We start at zero and walk you up to real systems running in your business: sales follow-ups, content engines, ads, ops, and support.",
  },
  {
    q: 'What happens after I join the waitlist?',
    a: "We open the doors in June 2026. You'll get a text when founding spots open — click through, claim your seat at $47/month, and you're locked in for life. The first 50 to sign up get founding pricing.",
  },
  {
    q: 'Is the price really locked forever?',
    a: "Yes. The first 50 founding members keep $47/month for as long as the Skool community runs. Everyone else pays $97/month at launch — and after.",
  },
];

function BPFAQ({ wide }) {
  const [open, setOpen] = React.useState(0);
  return (
    <div style={{ display: 'grid', gap: 0 }}>
      {FAQS.map((f, i) => {
        const isOpen = open === i;
        return (
          <div key={i} style={{
            borderTop: i === 0 ? `1px solid ${BRAND.ruleHi}` : 'none',
            borderBottom: `1px solid ${BRAND.ruleHi}`,
          }}>
            <button
              onClick={() => setOpen(isOpen ? -1 : i)}
              onMouseEnter={e => e.currentTarget.style.paddingLeft = wide ? '8px' : '6px'}
              onMouseLeave={e => e.currentTarget.style.paddingLeft = '0px'}
              style={{
                width: '100%', textAlign: 'left',
                background: 'transparent', border: 'none', cursor: 'pointer',
                padding: wide ? '22px 0' : '18px 0',
                paddingLeft: 0,
                display: 'flex', alignItems: 'center', gap: 16,
                color: BRAND.ink,
                transition: 'padding-left .2s cubic-bezier(.2,.7,.2,1)',
              }}>
              <span style={{
                fontFamily: BRAND.mono, fontSize: 11, color: BRAND.accent,
                width: 24,
              }}>0{i + 1}</span>
              <span style={{
                flex: 1,
                fontFamily: BRAND.display, fontSize: wide ? 20 : 16,
                lineHeight: 1.2,
              }}>{f.q}</span>
              <span style={{
                fontFamily: BRAND.mono, fontSize: 18, color: BRAND.accent,
                transform: isOpen ? 'rotate(45deg)' : 'rotate(0)',
                transition: 'transform .2s',
              }}>+</span>
            </button>
            {isOpen && (
              <div style={{
                paddingLeft: 40, paddingBottom: 20, paddingRight: 30,
                fontFamily: BRAND.body, fontSize: wide ? 16 : 14,
                color: BRAND.inkDim, lineHeight: 1.55,
                maxWidth: 720,
              }}>{f.a}</div>
            )}
          </div>
        );
      })}
    </div>
  );
}

// ──────────────────────────────────────────────────────────────────────
// DESKTOP
// ──────────────────────────────────────────────────────────────────────
function BlueprintDesktop() {
  return (
    <div style={{
      width: '100%', minHeight: '100%',
      background: BRAND.bg, color: BRAND.ink,
      fontFamily: BRAND.body,
      position: 'relative', overflow: 'hidden',
    }}>
      <DotGrid size={28} color="rgba(255,255,255,0.04)" />

      {/* NAV */}
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: '24px 56px', position: 'relative', zIndex: 2,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <Mascot size={28} variant="default" />
          <div style={{ fontFamily: BRAND.display, fontSize: 14, letterSpacing: '0.06em' }}>THE AI BLUEPRINT</div>
        </div>
        <nav style={{ display: 'flex', gap: 22, fontFamily: BRAND.mono, fontSize: 12, color: BRAND.inkDim, letterSpacing: '0.14em', textTransform: 'uppercase' }}>
          {[
            ["What's Inside", '#inside'],
            ['Founders',      '#founders'],
            ['Pricing',       '#pricing'],
            ['FAQs',          '#faq'],
          ].map(([text, href]) => (
            <a key={href} href={href} style={{
              color: 'inherit', textDecoration: 'none', cursor: 'pointer',
              transition: 'color .15s',
            }}
              onMouseEnter={e => e.currentTarget.style.color = BRAND.accent}
              onMouseLeave={e => e.currentTarget.style.color = BRAND.inkDim}
            >{text}</a>
          ))}
        </nav>
        <div style={{
          fontFamily: BRAND.mono, fontSize: 11, color: BRAND.accent,
          border: `1px solid ${BRAND.accent}`, borderRadius: 4, padding: '6px 10px',
          letterSpacing: '0.14em',
        }}>FOUNDING · 50 SPOTS</div>
      </div>

      {/* HERO */}
      <section style={{ position: 'relative', padding: '40px 56px 80px' }}>
        <div style={{ position: 'absolute', inset: 0, opacity: 0.5, pointerEvents: 'none' }}>
          <PerspectiveGrid opacity={0.16} />
        </div>
        <div style={{
          display: 'grid', gridTemplateColumns: '1fr 560px', gap: 60,
          position: 'relative', zIndex: 20, alignItems: 'start',
        }}>
          <div>
            <Reveal duration={550} distance={6}>
              <BPSpecLabel n={1} label="Founding member waitlist · Skool community" />
            </Reveal>
            <Reveal delay={80} duration={750} distance={14}>
              <h1 style={{
                fontFamily: BRAND.display, fontSize: 80, lineHeight: 0.95,
                margin: '24px 0 0', letterSpacing: '-0.02em',
              }}>
                SCALE YOUR<br />
                BUSINESS<br />
                <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400, display: 'inline-block', animation: 'bp-fade-in .8s cubic-bezier(.2,.7,.2,1) .35s backwards' }}>
                  without scaling
                </span><br />
                <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400, display: 'inline-block', animation: 'bp-fade-in .8s cubic-bezier(.2,.7,.2,1) .48s backwards' }}>
                  your hours.
                </span>
              </h1>
            </Reveal>
            <Reveal delay={220} duration={650}>
              <p style={{
                maxWidth: 540, marginTop: 28, fontSize: 17, lineHeight: 1.55, color: BRAND.inkDim,
              }}>
                AI systems that run sales, content, ops, support, and ads — for founders who'd rather build and deploy full-stack systems than learn to code, hire a dev team, or keep being the bottleneck.
              </p>
            </Reveal>
            <Reveal delay={320} duration={650}>
            <div style={{ display: 'flex', gap: 36, marginTop: 36, alignItems: 'center' }}>
              <div>
                <div style={{ fontFamily: BRAND.display, fontSize: 36, color: BRAND.accent }}>
                  <AnimatedNumber value={50} duration={1100} />
                </div>
                <div style={{ fontFamily: BRAND.mono, fontSize: 11, color: BRAND.inkDim, letterSpacing: '0.16em' }}>FOUNDING<br/>SPOTS</div>
              </div>
              <div style={{ width: 1, height: 50, background: BRAND.ruleHi }} />
              <div>
                <div style={{ fontFamily: BRAND.display, fontSize: 36 }}>
                  <span style={{ textDecoration: 'line-through', color: BRAND.inkFaint, fontSize: 24, marginRight: 8 }}>$97</span>
                  $47
                </div>
                <div style={{ fontFamily: BRAND.mono, fontSize: 11, color: BRAND.inkDim, letterSpacing: '0.16em' }}>FOUNDING MEMBER<br/>LOCKED FOR LIFE</div>
              </div>
              <div style={{ width: 1, height: 50, background: BRAND.ruleHi }} />
              <div style={{ position: 'relative', animation: 'bp-float 4.5s ease-in-out infinite' }}>
                <Mascot size={64} variant="lookRight" glow pointing />
              </div>
            </div>
            </Reveal>
          </div>

          <div id="waitlist-form" style={{ position: 'sticky', top: 24, marginTop: 38, scrollMarginTop: 24 }}>
            <Reveal delay={140} duration={700}>
              <BPForm />
            </Reveal>
          </div>
        </div>
      </section>

      {/* SCARCITY BAR */}
      <section style={{
        background: BRAND.accent, color: '#1a0d07',
        padding: '20px 56px',
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 24,
        position: 'relative', zIndex: 2,
        borderTop: '1px solid #b85d3f', borderBottom: '1px solid #b85d3f',
      }}>
        <Reveal duration={500} distance={6}>
          <div style={{ fontFamily: BRAND.display, fontSize: 18, letterSpacing: '0.03em', textAlign: 'center' }}>
            50 FOUNDING MEMBERSHIPS · $47/MO LOCKED FOR LIFE
          </div>
        </Reveal>
      </section>

      {/* WHAT'S INSIDE */}
      <section id="inside" style={{ padding: '120px 56px', position: 'relative', zIndex: 2, scrollMarginTop: 24 }}>
        <Reveal>
          <BPSpecLabel n={2} label="What's inside the community" />
          <h2 style={{
            fontFamily: BRAND.display, fontSize: 72, margin: '16px 0 0', lineHeight: 0.95, letterSpacing: '-0.02em',
          }}>
            SIX THINGS<br />
            <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400 }}>inside the community.</span>
          </h2>
        </Reveal>
        <div style={{
          marginTop: 56,
          display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 20,
        }}>
          {TILES.map((t, i) => (
            <Reveal key={t.k} delay={120 + i * 70} asGridItem>
              <BPTile {...t} />
            </Reveal>
          ))}
        </div>
      </section>

      {/* LEAD MAGNET PAYOFF */}
      <section style={{
        padding: '100px 56px', position: 'relative', zIndex: 2,
        borderTop: `1px solid ${BRAND.rule}`,
      }}>
        <div style={{ display: 'grid', gridTemplateColumns: '1.1fr 1fr', gap: 80, alignItems: 'center' }}>
          <Reveal>
            <BPSpecLabel n={3} label="What you install" />
            <h2 style={{
              fontFamily: BRAND.display, fontSize: 60, margin: '20px 0 0', lineHeight: 1, letterSpacing: '-0.02em',
            }}>
              INSTALL AI SYSTEMS<br/>
              <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400 }}>tailored to your niche and vertical.</span>
            </h2>
            <p style={{ marginTop: 24, fontSize: 17, color: BRAND.inkDim, lineHeight: 1.55, maxWidth: 520 }}>
              Content engine, ads engine, and your internal dashboard — built inside The AI Blueprint Skool community at launch. Founding members get them first.
            </p>
            <ul style={{
              listStyle: 'none', padding: 0, margin: '32px 0 0',
              display: 'grid', gap: 14,
            }}>
              {[
                'Content engine — tailored to your niche',
                'AI ads engine',
                'Internal dashboard — command centre for your business',
              ].map((t, i) => (
                <li key={i} style={{ display: 'flex', gap: 14, alignItems: 'baseline' }}>
                  <span style={{ fontFamily: BRAND.mono, color: BRAND.accent, fontSize: 12 }}>▸</span>
                  <span style={{ fontSize: 15 }}>{t}</span>
                </li>
              ))}
              <li style={{ display: 'flex', gap: 14, alignItems: 'baseline', marginTop: 4 }}>
                <span style={{ fontFamily: BRAND.mono, color: BRAND.accent, fontSize: 12 }}>+</span>
                <span style={{ fontSize: 15, fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.inkDim }}>
                  more shipped inside the community every week.
                </span>
              </li>
            </ul>
          </Reveal>
          <Reveal delay={150}>
            <TerminalPreviewDesktop />
          </Reveal>
        </div>
      </section>

      {/* FOUNDERS */}
      <section id="founders" style={{ padding: '100px 56px', position: 'relative', zIndex: 2, borderTop: `1px solid ${BRAND.rule}`, scrollMarginTop: 24 }}>
        <Reveal>
          <BPSpecLabel n={4} label="Who's building this" />
          <h2 style={{
            fontFamily: BRAND.display, fontSize: 60, margin: '20px 0 56px', letterSpacing: '-0.02em',
          }}>
            Built by <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400 }}>two operators</span><br/>
            not gurus.
          </h2>
        </Reveal>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 32 }}>
          {[
            { name: 'Varun', img: 'varun.png', tagline: 'AI builder · Skool operator',  bio: 'Studying AI at university and shipping production systems for business. Runs a Skool community where owners install AI into their workflow.' },
            { name: 'Karam', img: 'karam.png', tagline: 'AI builder · Skool operator',  bio: 'Studying AI at university and shipping production systems for business. Runs the community day-to-day — unblocking owners as they ship their first installs.' },
          ].map((f, i) => (
            <Reveal key={i} delay={120 + i * 100} asGridItem>
              <div
                onMouseEnter={e => {
                  e.currentTarget.style.transform = 'translateY(-3px)';
                  e.currentTarget.style.borderColor = BRAND.accent;
                  e.currentTarget.style.boxShadow = `0 16px 36px -20px ${BRAND.accentGlow}`;
                }}
                onMouseLeave={e => {
                  e.currentTarget.style.transform = 'translateY(0)';
                  e.currentTarget.style.borderColor = BRAND.ruleHi;
                  e.currentTarget.style.boxShadow = 'none';
                }}
                style={{
                  display: 'flex', gap: 24,
                  padding: 24,
                  background: BRAND.bgPanel,
                  border: `1px solid ${BRAND.ruleHi}`,
                  borderRadius: 10,
                  transform: 'translateY(0)',
                  transition: 'transform .25s cubic-bezier(.2,.7,.2,1), border-color .25s, box-shadow .25s',
                  cursor: 'default',
                }}>
                <FounderPhoto src={f.img} name={f.name} w={132} h={184} />
                <div>
                  <div style={{ fontFamily: BRAND.display, fontSize: 32, lineHeight: 1 }}>{f.name}</div>
                  <div style={{ fontFamily: BRAND.mono, fontSize: 11, color: BRAND.accent, letterSpacing: '0.16em', textTransform: 'uppercase', marginTop: 6 }}>{f.tagline}</div>
                  <div style={{ marginTop: 14, fontSize: 14, color: BRAND.inkDim, lineHeight: 1.55 }}>{f.bio}</div>
                </div>
              </div>
            </Reveal>
          ))}
        </div>
      </section>

      {/* PRICING ANCHOR */}
      <section id="pricing" style={{
        padding: '100px 56px', position: 'relative', zIndex: 2,
        borderTop: `1px solid ${BRAND.rule}`,
        scrollMarginTop: 24,
      }}>
       <Reveal>
        <div style={{
          display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 60, alignItems: 'center',
          background: BRAND.bgPanel,
          border: `1px solid ${BRAND.accent}`,
          borderRadius: 12,
          padding: '56px 60px',
          position: 'relative',
          boxShadow: `0 0 80px -20px ${BRAND.accentGlow}`,
        }}>
          <div style={{
            position: 'absolute', top: -14, left: 40,
            background: BRAND.accent, color: '#1a0d07',
            padding: '6px 12px', fontFamily: BRAND.display, fontSize: 12, letterSpacing: '0.12em',
          }}>FOUNDING MEMBER PRICE</div>
          <div>
            <Eyebrow>Pricing</Eyebrow>
            <div style={{
              fontFamily: BRAND.display, fontSize: 96, lineHeight: 0.9, marginTop: 14,
            }}>
              <span style={{
                fontSize: 40, color: BRAND.inkFaint, textDecoration: 'line-through',
                display: 'inline-block', marginRight: 16, verticalAlign: 'top',
              }}>$97</span>
              $47<span style={{ fontSize: 28, color: BRAND.inkDim }}>/mo</span>
            </div>
            <div style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontSize: 28, marginTop: 14 }}>
              locked for life.
            </div>
            <div style={{ marginTop: 22, color: BRAND.inkDim, fontSize: 15, lineHeight: 1.55, maxWidth: 460 }}>
              First 50 founding members lock in $47/month forever, for as long as the Skool community runs. After that the door reopens at $97 — and stays there.
            </div>
          </div>
          <div>
            <BPForm compact />
          </div>
        </div>
       </Reveal>
      </section>

      {/* FAQ */}
      <section id="faq" style={{ padding: '100px 56px', position: 'relative', zIndex: 2, borderTop: `1px solid ${BRAND.rule}`, scrollMarginTop: 24 }}>
        <div style={{ display: 'grid', gridTemplateColumns: '320px 1fr', gap: 60 }}>
          <Reveal>
            <BPSpecLabel n={5} label="Frequently asked" />
            <h2 style={{
              fontFamily: BRAND.display, fontSize: 48, margin: '20px 0 0', lineHeight: 1, letterSpacing: '-0.02em',
            }}>
              The <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400 }}>six things</span> you'll wonder.
            </h2>
            <div style={{ marginTop: 32, animation: 'bp-float 5s ease-in-out infinite' }}>
              <Mascot size={80} variant="lookRight" />
            </div>
          </Reveal>
          <Reveal delay={150}>
            <BPFAQ wide />
          </Reveal>
        </div>
      </section>

      {/* FINAL CTA */}
      <section style={{
        padding: '120px 56px', position: 'relative', zIndex: 2,
        borderTop: `1px solid ${BRAND.rule}`,
        textAlign: 'center',
        overflow: 'hidden',
      }}>
        <div style={{ position: 'absolute', inset: 0, opacity: 0.6 }}><PerspectiveGrid opacity={0.2} /></div>
        <Reveal style={{ position: 'relative' }}>
          <div style={{ display: 'inline-block', animation: 'bp-float 4.5s ease-in-out infinite' }}>
            <Mascot size={120} variant="default" glow />
          </div>
          <h2 style={{
            fontFamily: BRAND.display, fontSize: 96, margin: '36px 0 0', lineHeight: 0.92, letterSpacing: '-0.03em',
          }}>
            BUILD ONCE.<br/>
            <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400 }}>
              scale forever.
            </span>
          </h2>
          <p style={{ maxWidth: 560, margin: '24px auto 0', color: BRAND.inkDim, fontSize: 17, lineHeight: 1.55 }}>
            50 founding spots in The AI Blueprint Skool community. $47/month, locked for life. Once they're gone, the door opens at $97 — and stays there.
          </p>
          <div style={{ marginTop: 40, display: 'inline-block' }}>
            <BPCTAButton type="button" onClick={() => document.getElementById('waitlist-form')?.scrollIntoView({ behavior: 'smooth', block: 'start' })}>{CTA}</BPCTAButton>
          </div>
        </Reveal>
      </section>

      <footer style={{
        padding: '36px 56px', borderTop: `1px solid ${BRAND.rule}`,
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        fontFamily: BRAND.mono, fontSize: 11, color: BRAND.inkFaint, letterSpacing: '0.14em',
        textTransform: 'uppercase',
      }}>
        <span>The AI Blueprint © 2026</span>
        <span>varun & karam · london</span>
      </footer>
    </div>
  );
}

// ──────────────────────────────────────────────────────────────────────
// MOBILE
// ──────────────────────────────────────────────────────────────────────
function BlueprintMobile() {
  return (
    <div style={{
      width: '100%', minHeight: '100%',
      background: BRAND.bg, color: BRAND.ink,
      fontFamily: BRAND.body,
      position: 'relative', overflow: 'hidden',
    }}>
      <DotGrid size={20} color="rgba(255,255,255,0.05)" />

      {/* NAV */}
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: '20px 20px', position: 'relative', zIndex: 2,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <Mascot size={24} variant="default" />
          <div style={{ fontFamily: BRAND.display, fontSize: 12, letterSpacing: '0.05em' }}>AI BLUEPRINT</div>
        </div>
        <div style={{
          fontFamily: BRAND.mono, fontSize: 9, color: BRAND.accent,
          border: `1px solid ${BRAND.accent}`, borderRadius: 4, padding: '4px 8px',
          letterSpacing: '0.12em',
        }}>FOUNDING · 50</div>
      </div>

      {/* HERO */}
      <section style={{ position: 'relative', padding: '24px 20px 56px' }}>
        <div style={{ position: 'absolute', inset: 0, opacity: 0.4 }}>
          <PerspectiveGrid opacity={0.2} />
        </div>
        <div style={{ position: 'relative', zIndex: 20 }}>
          <Reveal duration={500} distance={6}>
            <BPSpecLabel n={1} label="Founding waitlist · Skool community" />
          </Reveal>
          <Reveal delay={70} duration={700} distance={12}>
            <h1 style={{
              fontFamily: BRAND.display, fontSize: 48, lineHeight: 1,
              margin: '32px 0 0', letterSpacing: '-0.02em',
            }}>
              SCALE YOUR<br/>
              BUSINESS<br/>
              <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400, display: 'inline-block', animation: 'bp-fade-in .75s cubic-bezier(.2,.7,.2,1) .3s backwards' }}>
                without scaling<br/>your hours.
              </span>
            </h1>
          </Reveal>
          <Reveal delay={190} duration={650}>
            <p style={{
              marginTop: 32, fontSize: 15, lineHeight: 1.6, color: BRAND.inkDim,
            }}>
              AI systems that run sales, content, ops, support, and ads — for founders who'd rather build and deploy full-stack systems than learn to code or hire a dev team.
            </p>
          </Reveal>
          <Reveal delay={260} duration={700}>
            <div id="waitlist-form" style={{ marginTop: 44, scrollMarginTop: 16 }}>
              <BPForm compact />
            </div>
          </Reveal>
        </div>
      </section>

      {/* SCARCITY BAR */}
      <section style={{
        background: BRAND.accent, color: '#1a0d07',
        padding: '16px 20px',
        position: 'relative', zIndex: 2,
      }}>
        <div style={{ fontFamily: BRAND.display, fontSize: 14, letterSpacing: '0.02em' }}>
          50 FOUNDING MEMBERSHIPS
        </div>
        <div style={{ fontFamily: BRAND.mono, fontSize: 11, marginTop: 4 }}>
          $47/month locked for life
        </div>
      </section>

      {/* WHAT'S INSIDE */}
      <section style={{ padding: '60px 20px', position: 'relative', zIndex: 2 }}>
        <Reveal>
          <BPSpecLabel n={2} label="What's inside the community" />
          <h2 style={{
            fontFamily: BRAND.display, fontSize: 48, margin: '16px 0 0', lineHeight: 0.95, letterSpacing: '-0.02em',
          }}>
            SIX THINGS<br/>
            <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400 }}>inside the community.</span>
          </h2>
        </Reveal>
        <div style={{
          marginTop: 28,
          display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 12,
        }}>
          {TILES.map((t, i) => (
            <Reveal key={t.k} delay={80 + i * 60} asGridItem>
              <BPTile {...t} />
            </Reveal>
          ))}
        </div>
      </section>

      {/* LEAD MAGNET */}
      <section style={{ padding: '40px 20px 60px', position: 'relative', zIndex: 2, borderTop: `1px solid ${BRAND.rule}` }}>
        <Reveal>
          <BPSpecLabel n={3} label="What you install" />
          <h2 style={{
            fontFamily: BRAND.display, fontSize: 36, margin: '16px 0 0', lineHeight: 1, letterSpacing: '-0.02em',
          }}>
            INSTALL AI SYSTEMS<br/>
            <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400 }}>tailored to your niche.</span>
          </h2>
          <p style={{ marginTop: 16, fontSize: 14, color: BRAND.inkDim, lineHeight: 1.55 }}>
            Content engine, ads engine, and your internal dashboard — built inside The AI Blueprint Skool community at launch. Founding members get them first.
          </p>
          <ul style={{ listStyle: 'none', padding: 0, marginTop: 20, display: 'grid', gap: 10 }}>
            {[
              'Content engine — tailored to your niche',
              'AI ads engine',
              'Internal dashboard — command centre for your business',
            ].map((t, i) => (
              <li key={i} style={{ display: 'flex', gap: 10 }}>
                <span style={{ fontFamily: BRAND.mono, color: BRAND.accent, fontSize: 12 }}>▸</span>
                <span style={{ fontSize: 14 }}>{t}</span>
              </li>
            ))}
            <li style={{ display: 'flex', gap: 10, marginTop: 2 }}>
              <span style={{ fontFamily: BRAND.mono, color: BRAND.accent, fontSize: 12 }}>+</span>
              <span style={{ fontSize: 14, fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.inkDim }}>
                more added every week.
              </span>
            </li>
          </ul>
        </Reveal>
        <Reveal delay={120}>
          <TerminalPreviewMobile />
        </Reveal>
      </section>

      {/* FOUNDERS */}
      <section style={{ padding: '60px 20px', position: 'relative', zIndex: 2, borderTop: `1px solid ${BRAND.rule}` }}>
        <Reveal>
          <BPSpecLabel n={4} label="Who's building this" />
          <h2 style={{
            fontFamily: BRAND.display, fontSize: 40, margin: '16px 0 28px', lineHeight: 1, letterSpacing: '-0.02em',
          }}>
            Built by <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400 }}>two operators.</span>
          </h2>
        </Reveal>
        <div style={{ display: 'grid', gap: 16 }}>
          {[
            { name: 'Varun', img: 'varun.png', tagline: 'AI builder · Skool operator', bio: 'Studies AI at university. Ships AI systems in production and runs a Skool community for owners installing AI.' },
            { name: 'Karam', img: 'karam.png', tagline: 'AI builder · Skool operator', bio: 'Studies AI at university. Ships AI systems in production and runs the community — answers, unblocks, ships with members.' },
          ].map((f, i) => (
            <Reveal key={i} delay={80 + i * 100}>
              <div style={{
                display: 'flex', gap: 16, padding: 16,
                background: BRAND.bgPanel,
                border: `1px solid ${BRAND.ruleHi}`,
                borderRadius: 10,
              }}>
                <FounderPhoto src={f.img} name={f.name} w={92} h={128} />
                <div>
                  <div style={{ fontFamily: BRAND.display, fontSize: 22, lineHeight: 1 }}>{f.name}</div>
                  <div style={{ fontFamily: BRAND.mono, fontSize: 9, color: BRAND.accent, letterSpacing: '0.16em', textTransform: 'uppercase', marginTop: 4 }}>{f.tagline}</div>
                  <div style={{ marginTop: 10, fontSize: 13, color: BRAND.inkDim, lineHeight: 1.5 }}>{f.bio}</div>
                </div>
              </div>
            </Reveal>
          ))}
        </div>
      </section>

      {/* PRICING ANCHOR */}
      <section style={{ padding: '60px 20px', position: 'relative', zIndex: 2, borderTop: `1px solid ${BRAND.rule}` }}>
       <Reveal>
        <div style={{
          background: BRAND.bgPanel,
          border: `1px solid ${BRAND.accent}`,
          borderRadius: 12,
          padding: 24, position: 'relative',
          boxShadow: `0 0 60px -20px ${BRAND.accentGlow}`,
        }}>
          <div style={{
            position: 'absolute', top: -10, left: 20,
            background: BRAND.accent, color: '#1a0d07',
            padding: '4px 10px', fontFamily: BRAND.display, fontSize: 10, letterSpacing: '0.12em',
          }}>FOUNDING PRICE</div>
          <Eyebrow style={{ marginTop: 8 }}>Pricing</Eyebrow>
          <div style={{
            fontFamily: BRAND.display, fontSize: 64, lineHeight: 0.9, marginTop: 10,
          }}>
            <span style={{
              fontSize: 24, color: BRAND.inkFaint, textDecoration: 'line-through',
              display: 'inline-block', marginRight: 10, verticalAlign: 'top',
            }}>$97</span>
            $47<span style={{ fontSize: 20, color: BRAND.inkDim }}>/mo</span>
          </div>
          <div style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontSize: 22, marginTop: 6 }}>
            locked for life.
          </div>
          <div style={{ marginTop: 16, color: BRAND.inkDim, fontSize: 14, lineHeight: 1.5 }}>
            First 50 founding members lock in $47/month for as long as the Skool community runs. After that, $97 — for everyone.
          </div>
          <div style={{ marginTop: 20 }}>
            <BPCTAButton full type="button" onClick={() => document.getElementById('waitlist-form')?.scrollIntoView({ behavior: 'smooth', block: 'start' })}>{CTA}</BPCTAButton>
          </div>
        </div>
       </Reveal>
      </section>

      {/* FAQ */}
      <section style={{ padding: '60px 20px', position: 'relative', zIndex: 2, borderTop: `1px solid ${BRAND.rule}` }}>
        <Reveal>
          <BPSpecLabel n={5} label="FAQ" />
          <h2 style={{
            fontFamily: BRAND.display, fontSize: 36, margin: '16px 0 24px', lineHeight: 1, letterSpacing: '-0.02em',
          }}>
            Six <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400 }}>questions.</span>
          </h2>
        </Reveal>
        <Reveal delay={100}>
          <BPFAQ />
        </Reveal>
      </section>

      {/* FINAL CTA */}
      <section style={{
        padding: '60px 20px 80px', position: 'relative', zIndex: 2,
        borderTop: `1px solid ${BRAND.rule}`,
        textAlign: 'center', overflow: 'hidden',
      }}>
        <div style={{ position: 'absolute', inset: 0, opacity: 0.5 }}><PerspectiveGrid opacity={0.22} /></div>
        <Reveal style={{ position: 'relative' }}>
          <div style={{ display: 'inline-block', animation: 'bp-float 4.5s ease-in-out infinite' }}>
            <Mascot size={80} variant="default" glow />
          </div>
          <h2 style={{
            fontFamily: BRAND.display, fontSize: 52, margin: '20px 0 0', lineHeight: 0.92, letterSpacing: '-0.03em',
          }}>
            BUILD ONCE.<br/>
            <span style={{ fontFamily: BRAND.serif, fontStyle: 'italic', color: BRAND.accent, fontWeight: 400 }}>
              scale forever.
            </span>
          </h2>
          <p style={{ margin: '16px 0 0', color: BRAND.inkDim, fontSize: 14, lineHeight: 1.5 }}>
            50 founding spots in the Skool community. $47/month locked for life. Then $97 — and stays there.
          </p>
          <div style={{ marginTop: 24 }}>
            <BPCTAButton full type="button" onClick={() => document.getElementById('waitlist-form')?.scrollIntoView({ behavior: 'smooth', block: 'start' })}>{CTA}</BPCTAButton>
          </div>
        </Reveal>
      </section>

      <footer style={{
        padding: '24px 20px', borderTop: `1px solid ${BRAND.rule}`,
        textAlign: 'center',
        fontFamily: BRAND.mono, fontSize: 9, color: BRAND.inkFaint, letterSpacing: '0.14em',
        textTransform: 'uppercase',
      }}>
        The AI Blueprint © 2026 · Varun & Karam
      </footer>
    </div>
  );
}

// ConfirmationPage — full-page takeover after a successful signup.
// App reads localStorage / listens for the bp:signup event and renders this
// instead of the marketing page.
function ConfirmationPage({ signup, onReset, isMobile }) {
  return (
    <div style={{
      width: '100%', minHeight: '100vh',
      background: BRAND.bg, color: BRAND.ink,
      fontFamily: BRAND.body,
      position: 'relative', overflow: 'hidden',
      display: 'flex', flexDirection: 'column',
    }}>
      <DotGrid size={isMobile ? 20 : 28} color="rgba(255,255,255,0.04)" />

      {/* Minimal nav */}
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: isMobile ? '20px 20px' : '24px 56px',
        position: 'relative', zIndex: 2,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: isMobile ? 10 : 12 }}>
          <Mascot size={isMobile ? 24 : 28} variant="default" />
          <div style={{ fontFamily: BRAND.display, fontSize: isMobile ? 12 : 14, letterSpacing: '0.06em' }}>
            {isMobile ? 'AI BLUEPRINT' : 'THE AI BLUEPRINT'}
          </div>
        </div>
        <div style={{
          fontFamily: BRAND.mono, fontSize: isMobile ? 9 : 11, color: BRAND.accent,
          border: `1px solid ${BRAND.accent}`, borderRadius: 4,
          padding: isMobile ? '4px 8px' : '6px 10px',
          letterSpacing: '0.14em',
        }}>
          {isMobile ? 'CLAIMED' : 'FOUNDING SPOT · CLAIMED'}
        </div>
      </div>

      {/* Centered confirmation panel */}
      <div style={{
        flex: 1,
        display: 'flex', alignItems: 'flex-start', justifyContent: 'center',
        padding: isMobile ? '24px 20px 40px' : '40px 56px 60px',
        position: 'relative', zIndex: 2,
      }}>
        <div style={{ width: '100%', maxWidth: isMobile ? 480 : 580 }}>
          <ConfirmationPanel
            spotId={signup.spotId}
            name={signup.name}
            email={signup.email}
            phone={signup.phone}
            returning={signup.returning}
            compact={isMobile}
          />
        </div>
      </div>

      {/* Footer with back link */}
      <div style={{
        padding: isMobile ? '20px 20px 28px' : '24px 56px 32px',
        borderTop: `1px solid ${BRAND.rule}`,
        display: 'flex',
        flexDirection: isMobile ? 'column' : 'row',
        alignItems: isMobile ? 'flex-start' : 'center',
        justifyContent: 'space-between',
        gap: isMobile ? 14 : 16,
        position: 'relative', zIndex: 2,
        fontFamily: BRAND.mono, fontSize: isMobile ? 9 : 11,
        color: BRAND.inkFaint, letterSpacing: '0.14em',
        textTransform: 'uppercase',
      }}>
        <span>The AI Blueprint © 2026</span>
        <div style={{
          display: 'flex',
          flexDirection: isMobile ? 'column' : 'row',
          alignItems: isMobile ? 'flex-start' : 'center',
          gap: isMobile ? 8 : 16,
        }}>
          <span style={{ textTransform: 'none', letterSpacing: 0, fontFamily: BRAND.body, fontSize: isMobile ? 11 : 12, color: BRAND.inkFaint }}>
            Your receipt auto-clears from this browser in 24h.
          </span>
          <button
            onClick={onReset}
            onMouseEnter={e => { e.currentTarget.style.color = BRAND.accent; e.currentTarget.style.borderColor = BRAND.accent; }}
            onMouseLeave={e => { e.currentTarget.style.color = BRAND.inkFaint; e.currentTarget.style.borderColor = BRAND.ruleHi; }}
            style={{
              background: 'transparent',
              border: `1px solid ${BRAND.ruleHi}`,
              borderRadius: 4,
              cursor: 'pointer',
              fontFamily: BRAND.mono, fontSize: isMobile ? 9 : 10,
              color: BRAND.inkFaint, letterSpacing: '0.14em',
              textTransform: 'uppercase',
              transition: 'color .15s, border-color .15s',
              padding: '6px 10px',
            }}
          >
            ← clear my receipt now
          </button>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { BlueprintDesktop, BlueprintMobile, ConfirmationPage });
