// become-instructor-v2.jsx — Wyzant-style 6-step instructor signup wizard.
//
// Mounted at ?page=become-instructor (the legacy single-form lives at
// ?page=become-instructor-legacy). All editable copy/quiz/agreement comes
// from the signup_config / signup_quiz_questions / signup_agreements tables
// — admin edits via admin-signup-config.jsx. Step gates and quiz validation
// run server-side via SECURITY DEFINER RPCs.
//
// State machine (post-account-creation):
//   step 1: subjects        -> signup_save_subjects
//   step 2: how-it-works    -> signup_complete_how_it_works (quiz)
//   step 3: basic info      -> signup_save_basic_info
//   step 4: profile         -> signup_save_profile (photo upload to storage)
//   step 5: agreement       -> signup_sign_agreement
//   step 6: confirmation    -> signup_submit_for_review

const BecomeInstructorV2 = ({ setPage }) => {
  // Dispatcher-only — NO hooks past this point, so the conditional
  // return doesn't violate the Rules of Hooks. The wizard's
  // useState / useEffect calls live inside BIV2Wizard, which only
  // mounts once auth.user is truthy. Without this split, when
  // auth.user transitioned null → set mid-render the hook count
  // changed and React silently bailed — symptom was a permanent
  // "Loading…" on coachingforall.co/?page=become-instructor.
  const auth = window.useAuth();
  if (!auth.user) return <window.BIV2AccountCreate setPage={setPage} />;
  return <BIV2Wizard setPage={setPage} authUser={auth.user} />;
};

const BIV2Wizard = ({ setPage, authUser }) => {
  const isMobile = window.useIsMobile();
  // initialLoading: true only on the first mount, so the full-screen
  // "Loading…" spinner shows only once. Step transitions silently refresh
  // progress + instructorRow without unmounting the frame — that "blank flash
  // between every Next click" was the wizard's "not smooth" symptom.
  const [initialLoading, setInitialLoading] = React.useState(true);
  const [progress, setProgress] = React.useState(null);
  const [config, setConfig]     = React.useState({});
  const [categories, setCategories] = React.useState([]);
  const [quiz, setQuiz]         = React.useState([]);
  const [agreement, setAgreement] = React.useState(null);
  const [instructorRow, setInstructorRow] = React.useState(null);
  const [step, setStep]         = React.useState(1);
  const [error, setError]       = React.useState(null);
  // Initial-mount-only landing-step logic gate. After the first load picks
  // a step (e.g. user resumes mid-wizard or comes back from rejection),
  // subsequent refreshes must NOT clobber the step the user is on — the
  // step component's own setStep(N) after a save is the source of truth.
  const initialLandingDoneRef = React.useRef(false);

  // -------------------------------------------------------------------
  // Loaders.
  //
  // Split into "load everything" (initial mount) and "refresh dynamic"
  // (just progress + instructorRow, after a step save). Static lookups
  // — config, categories, subjects, quiz, agreement — never change while
  // the user is filling out the wizard, so re-fetching them between
  // every step was pure waste. Pulling them out of the per-step path
  // removed 5 parallel queries per Next click and got rid of the
  // full-screen "Loading…" flash that made the wizard feel choppy.
  // -------------------------------------------------------------------
  const loadDynamic = React.useCallback(async () => {
    const { data: instr, error: ie } = await window.supa
      .from('instructors').select('*').eq('user_id', authUser.id).maybeSingle();
    if (ie) throw ie;
    if (!instr) return { instr: null, prog: null };
    // Already-approved teachers (admin-created, or legacy pre-wizard rows)
    // who click "For Instructors" in the navbar shouldn't be funneled through
    // the wizard. Skip signup_ensure_progress so we don't leave an empty
    // progress row dangling on their record — the render branch below
    // intercepts and points them back to their dashboard.
    if (instr.profile_status === 'approved') return { instr, prog: null };
    const { data: prog, error: pe } = await window.supa.rpc('signup_ensure_progress');
    if (pe) throw pe;
    return { instr, prog };
  }, [authUser?.id]);

  const initialLoad = React.useCallback(async () => {
    setInitialLoading(true); setError(null);
    try {
      const { instr, prog } = await loadDynamic();
      if (!instr) {
        // Logged-in user with no instructor row — almost always a student
        // account that landed here. Show a friendly "sign out to apply"
        // screen instead of a bare error.
        setInstructorRow(null);
        return;
      }
      setInstructorRow(instr);
      // Already-approved teachers: render branch shows the redirect screen
      // and skips the wizard entirely. Don't run the step-derivation block
      // (prog is null for them) or load the static signup config / quiz /
      // agreement — none of it is needed.
      if (instr.profile_status === 'approved') return;
      setProgress(prog);

      // Pick which step to land on. Default: first incomplete step. But
      // rejected tutors come back to edit, so drop them at the Review
      // step (6) — they can navigate back via the progress bar to edit
      // any field and then resubmit. Without this, the dashboard's "Edit
      // and resubmit" button dumped them straight onto confirmation and
      // gave them no way forward. Only runs on initial mount — subsequent
      // refreshes leave step alone (the step component owns it).
      if (!initialLandingDoneRef.current) {
        let s = 1;
        if (prog.subjects_completed_at)     s = 2;
        if (prog.how_it_works_completed_at) s = 3;
        if (prog.basic_info_completed_at)   s = 4;
        if (prog.profile_completed_at)      s = 5;
        if (prog.agreement_completed_at)    s = 6;
        if (prog.submitted_at)              s = 7;  // confirmation
        if (prog.review_status === 'rejected') s = 6;
        setStep(s);
        initialLandingDoneRef.current = true;
      }

      // Static lookups (config / subjects / quiz / agreement). Fetched
      // once per mount — they never change mid-wizard.
      const [cfg, cats, subs, qz, agr] = await Promise.all([
        window.supa.from('signup_config').select('key,payload'),
        window.supa.from('signup_categories').select('*').order('position'),
        window.supa.from('signup_subjects').select('*').order('position'),
        window.supa.from('signup_quiz_questions').select('id,step_key,question,options,position').order('position'),
        window.supa.from('signup_agreements').select('*').eq('is_current', true).maybeSingle(),
      ]);
      if (cfg.error) throw cfg.error;
      const cfgMap = {};
      (cfg.data || []).forEach(r => { cfgMap[r.key] = r.payload; });
      setConfig(cfgMap);

      const catTree = (cats.data || []).map(c => ({
        ...c,
        subjects: (subs.data || []).filter(s => s.category_id === c.id),
      }));
      setCategories(catTree);
      setQuiz(qz.data || []);
      setAgreement(agr.data || null);
    } catch (e) {
      setError(window.friendlyError ? window.friendlyError(e, 'Could not load') : (e.message || String(e)));
    } finally {
      setInitialLoading(false);
    }
  }, [loadDynamic]);

  // After a step save, refresh just progress + the instructor row so the
  // next step has up-to-date data. No setLoading flip — the current step's
  // own busy state already shows "Saving…" on its Next button, and we
  // don't want the whole frame to remount.
  const refreshAfterSave = React.useCallback(async () => {
    try {
      const { instr, prog } = await loadDynamic();
      if (instr) setInstructorRow(instr);
      if (prog)  setProgress(prog);
    } catch (e) {
      // Non-fatal: the save itself succeeded; we just couldn't pull the
      // fresh row. The next step will mostly use the locally-set values
      // it already has, and a later step's open will retry. Surface to
      // the console for diagnosis but don't blow up the wizard.
      console.warn('[wizard] refresh after save failed', e);
    }
  }, [loadDynamic]);

  React.useEffect(() => { initialLoad(); }, [initialLoad]);

  if (initialLoading) return <BIV2Loading />;
  if (error)   return <BIV2ErrorScreen message={error} onRetry={initialLoad} />;
  if (!instructorRow) return <BIV2NotAnInstructor setPage={setPage} authUser={authUser} />;
  // Already approved AND no in-flight progress — admin created them, or
  // they're a legacy pre-wizard row. The "For Instructors" navbar link
  // points here unconditionally, so without this guard an approved teacher
  // who clicks it lands on step 1 of a wizard that has nothing to ask them.
  // The `!progress` half avoids yanking the screen out from under a
  // mid-wizard teacher if admin approves them between two step saves —
  // they finish their current step naturally and pick up the new state
  // on their next page visit.
  if (instructorRow.profile_status === 'approved' && !progress) {
    return <BIV2AlreadyApproved setPage={setPage} fullName={instructorRow.full_name} />;
  }

  // X closes the wizard. Send them to instructor-portal (not home) so they
  // land on the new pending-application placeholder if their profile isn't
  // approved yet. Without this they'd just hit the marketplace homepage
  // and could navigate back to a dashboard they haven't earned access to.
  //
  // ALSO update the URL — without this, the URL stays at
  // ?page=become-instructor so a browser refresh after exit just bounces
  // the user back into the wizard. Joe specifically called this out:
  // exiting should "redirect them to their dashboard so that it prompts
  // them again to reapply". Now refresh from the pending screen stays put.
  const goHome = () => {
    try {
      history.replaceState({}, '', location.pathname + '?page=instructor-portal' + location.hash);
    } catch (_) {}
    setPage('instructor-portal');
  };
  // `advance` is what the step components call after a successful save.
  // Used to do a full reload + full-screen Loading flash; now silently
  // refreshes the dynamic bits in the background.
  const advance = async () => { await refreshAfterSave(); };

  // -------------------------------------------------------------------
  // Step renderer.
  // -------------------------------------------------------------------
  const stepProps = { progress, config, instructorRow, advance, setStep, isMobile };
  return (
    <BIV2Frame
      step={step} setStep={setStep} progress={progress} onClose={goHome} isMobile={isMobile}
      brandName={(config.global && config.global.brand_name) || 'Coaching'}
    >
      {step === 1 && <window.BIV2Subjects {...stepProps} categories={categories} />}
      {step === 2 && <window.BIV2HowItWorks {...stepProps} quiz={quiz} />}
      {step === 3 && <window.BIV2BasicInfo  {...stepProps} />}
      {step === 4 && <window.BIV2Profile    {...stepProps} />}
      {step === 5 && <window.BIV2Agreement  {...stepProps} agreement={agreement} />}
      {step === 6 && <window.BIV2Review     {...stepProps} categories={categories} agreement={agreement} />}
      {step === 7 && <window.BIV2Confirmation {...stepProps} setPage={setPage} categories={categories} />}
    </BIV2Frame>
  );
};

// =====================================================================
// Account creation screen (Wyzant "Apply now" pattern).
// =====================================================================
const BIV2Frame = ({ step, setStep, progress, children, onClose, isMobile, brandName }) => {
  const STEPS = [
    { n:1, label:'Select Subjects' },
    { n:2, label:'How Coaching Works' },
    { n:3, label:'Basic Information' },
    { n:4, label:'Personalize Profile' },
    { n:5, label:'Terms for Tutoring' },
    { n:6, label:'Review & Submit' },
  ];
  const completed = (n) => {
    if (!progress) return false;
    if (n === 1) return !!progress.subjects_completed_at;
    if (n === 2) return !!progress.how_it_works_completed_at;
    if (n === 3) return !!progress.basic_info_completed_at;
    if (n === 4) return !!progress.profile_completed_at;
    if (n === 5) return !!progress.agreement_completed_at;
    return false;
  };

  const currentLabel = (STEPS.find(s => s.n === step) || {}).label || 'Submitted';
  const pct = step === 7 ? 100 : Math.round((step / 6) * 100);

  return (
    <div style={{ background:'oklch(98% 0.008 60)', minHeight:'100vh', position:'relative' }}>
      <header style={{ background:'#fff', borderBottom:'1px solid oklch(94% 0.01 265)', padding: isMobile ? '10px 12px 10px' : '20px 80px', position:'sticky', top:0, zIndex:80 }}>
        <div style={{ maxWidth:1100, margin:'0 auto', display:'flex', justifyContent:'space-between', alignItems:'center', gap: isMobile ? 8 : 14 }}>
          <div style={{ display:'flex', alignItems:'center', gap:8, minWidth:0, flexShrink:1 }}>
            <div style={{ width: isMobile ? 26 : 30, height: isMobile ? 26 : 30, borderRadius:7, background:'oklch(22% 0.06 265)', color:'oklch(72% 0.17 80)', display:'flex', alignItems:'center', justifyContent:'center', fontFamily:"'Cormorant Garamond', serif", fontWeight:700, fontSize: isMobile ? 15 : 18, flexShrink:0 }}>C</div>
            <div style={{ minWidth:0 }}>
              <div style={{ fontSize: isMobile ? 12 : 13, fontWeight:700, color:'oklch(22% 0.06 265)', whiteSpace:'nowrap' }}>Tutor Sign Up</div>
              <div style={{ fontSize: isMobile ? 10 : 11, color:'oklch(50% 0.03 265)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{isMobile ? `Step ${step <= 6 ? step : 7} of 6` : `${currentLabel} · ${step <= 6 ? `${step} of 6 steps` : 'Submitted for review'}`}</div>
            </div>
          </div>
          <div style={{ flex:1, minWidth: isMobile ? 60 : 200, maxWidth:520, marginLeft: isMobile ? 6 : 32 }}>
            <div style={{ height: isMobile ? 4 : 6, background:'oklch(94% 0.01 265)', borderRadius:3, overflow:'hidden' }}>
              <div style={{ width:`${pct}%`, height:'100%', background:'oklch(72% 0.17 80)', transition:'width 200ms' }} />
            </div>
          </div>
          <button onClick={onClose} aria-label="Save & exit" title="Save & exit"
            style={{ flexShrink:0, width: isMobile ? 32 : 36, height: isMobile ? 32 : 36, borderRadius:'50%', background:'#fff', border:'1px solid oklch(88% 0.02 265)', cursor:'pointer', fontSize: isMobile ? 18 : 20, color:'oklch(28% 0.05 265)', display:'flex', alignItems:'center', justifyContent:'center', padding:0, lineHeight:1 }}>×</button>
        </div>
        {!isMobile && step <= 6 && (
          <div style={{ maxWidth:1100, margin:'14px auto 0', display:'grid', gridTemplateColumns:'repeat(6, 1fr)', gap:10 }}>
            {STEPS.map(s => {
              const isCur  = s.n === step;
              const isDone = completed(s.n);
              return (
                <button key={s.n} type="button"
                  onClick={() => { if (isDone || isCur) setStep(s.n); }}
                  disabled={!isDone && !isCur}
                  style={{
                    background: isCur ? 'oklch(45% 0.13 265)' : (isDone ? '#fff' : 'oklch(96% 0.008 265)'),
                    color: isCur ? '#fff' : 'oklch(40% 0.04 265)',
                    border:'1px solid oklch(88% 0.02 265)', borderRadius:6,
                    padding:'10px 12px', fontSize:12, fontWeight:600,
                    cursor: (isDone || isCur) ? 'pointer' : 'default',
                    textAlign:'left', fontFamily:"'Plus Jakarta Sans', sans-serif",
                    display:'flex', alignItems:'center', gap:8,
                  }}>
                  <span style={{ display:'inline-flex', alignItems:'center', justifyContent:'center', width:22, height:22, borderRadius:'50%',
                    background: isCur ? 'rgba(255,255,255,0.2)' : (isDone ? 'oklch(72% 0.16 155)' : 'transparent'),
                    color: isDone && !isCur ? '#fff' : 'inherit',
                    fontSize:12, fontWeight:700, border: isCur ? 'none' : (isDone ? 'none' : '1px solid oklch(80% 0.02 265)') }}>
                    {isDone ? '✓' : s.n}
                  </span>
                  <span>{s.label}</span>
                </button>
              );
            })}
          </div>
        )}
      </header>

      <main style={{ maxWidth: 920, margin: '0 auto', padding: isMobile ? '20px 16px calc(180px + env(safe-area-inset-bottom))' : '40px 32px 140px' }}>
        {children}
      </main>
    </div>
  );
};

// =====================================================================
// STEP 1 — Subjects (2-level tree, pick 1-5).
// =====================================================================
// onNext is the primary action (centered, brand-coloured). onBack is a
// secondary outline button placed to its left within the centered group.
// `hideNext` (used by the quiz when the answer is wrong) suppresses Next
// so the user can't skip forward — they get only a "Try again" inside the
// card body.
const BIV2NavBar = ({ onBack, onNext, nextLabel, busy, hideNext }) => {
  const isMobile = window.useIsMobile();
  return (
    <div style={{
      position:'fixed', bottom:0, left:0, right:0,
      background:'#fff', borderTop:'1px solid oklch(94% 0.01 265)',
      padding: isMobile
        ? '12px 14px calc(12px + env(safe-area-inset-bottom))'
        : '18px 32px',
      display:'flex',
      justifyContent:'center', alignItems:'center', gap:12,
      zIndex:100, boxShadow:'0 -2px 12px rgba(0,0,0,0.04)',
    }}>
      {!isMobile && (
        <div style={{ position:'absolute', left:32, top:'50%', transform:'translateY(-50%)', fontSize:12, color:'oklch(50% 0.03 265)' }}>
          🔒 AES-256 · Need help? hello@coachingforall.co
        </div>
      )}
      {onBack && (
        <button type="button" onClick={onBack} disabled={busy} style={{
          background:'#fff', color:'oklch(28% 0.05 265)', border:'1.5px solid oklch(80% 0.02 265)',
          borderRadius:999, padding: isMobile ? '12px 18px' : '12px 22px',
          fontWeight:600, fontSize:14, cursor: busy ? 'wait' : 'pointer',
          fontFamily:"'Plus Jakarta Sans', sans-serif",
          minWidth: isMobile ? 96 : 'unset',
        }}>← Back</button>
      )}
      {!hideNext && (
        <button type="button" onClick={onNext} disabled={busy} style={{
          background:'oklch(22% 0.06 265)', color:'#fff', border:'none', borderRadius:999,
          padding: isMobile ? '14px 32px' : '14px 40px',
          fontWeight:700, fontSize:15, cursor: busy ? 'wait' : 'pointer',
          fontFamily:"'Plus Jakarta Sans', sans-serif", opacity: busy ? 0.7 : 1,
          minWidth: isMobile ? 180 : 220,
          boxShadow:'0 4px 14px rgba(0,0,0,0.08)',
        }}>{busy ? 'Saving…' : nextLabel}</button>
      )}
    </div>
  );
};

// `required` renders a red asterisk after the label so the user can see
// up-front which fields are mandatory — solves the "I had to scroll to
// the bottom to find which one was missing" complaint.
// `fieldId` lets the wizard scrollIntoView/focus the first invalid field on
// validation failure.
const BIV2Field = ({ label, hint, children, required, fieldId }) => {
  const isMobile = window.useIsMobile ? window.useIsMobile() : false;
  return (
    <div data-field-id={fieldId} style={{ marginBottom: isMobile ? 12 : 16, scrollMarginTop: 90 }}>
      <label style={{ display:'block', fontSize:13, fontWeight:600, color:'oklch(35% 0.04 265)', marginBottom: isMobile ? 4 : 6 }}>
        {label}
        {required && <span style={{ color:'oklch(55% 0.20 25)', marginLeft:4 }}>*</span>}
      </label>
      {children}
      {hint && <div style={{ fontSize:12, color:'oklch(55% 0.03 265)', marginTop:4, lineHeight:1.5 }}>{hint}</div>}
    </div>
  );
};

const BIV2Loading = () => (
  <div style={{ minHeight:'70vh', display:'flex', alignItems:'center', justifyContent:'center', color:'oklch(50% 0.03 265)' }}>
    Loading…
  </div>
);
const BIV2ErrorScreen = ({ message, onRetry }) => (
  <div style={{ minHeight:'70vh', display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap:14, padding:20 }}>
    <div style={biv2ErrorBox}>{message}</div>
    <button onClick={onRetry} style={{ background:'oklch(22% 0.06 265)', color:'#fff', border:'none', borderRadius:8, padding:'10px 22px', cursor:'pointer', fontWeight:600 }}>Retry</button>
  </div>
);

// Rendered when the visitor is logged in but doesn't have an instructor
// row — most commonly a student account that landed on /?page=become-instructor.
// We can't drop them into the wizard (no row to attach progress to) and
// we can't show the Apply Now form (their account already exists). Best
// move: explain + sign-out button so they can apply fresh.
const BIV2NotAnInstructor = ({ setPage, authUser }) => {
  const [busy, setBusy] = React.useState(false);
  const signOut = async () => {
    setBusy(true);
    try {
      await window.AUTH.signOut();
      // Reload so the wizard re-mounts in the logged-out state and shows
      // the Apply Now form.
      location.assign(location.pathname + '?page=become-instructor');
    } catch (e) {
      setBusy(false);
    }
  };
  return (
    <div style={{ minHeight:'70vh', display:'flex', alignItems:'center', justifyContent:'center', padding:'40px 24px' }}>
      <div style={{ maxWidth:520, background:'#fff', border:'1px solid oklch(92% 0.01 265)', borderRadius:14, padding:'36px 32px', boxShadow:'0 4px 24px rgba(0,0,0,0.06)', textAlign:'center' }}>
        <div style={{ fontSize:44, marginBottom:14 }}>👋</div>
        <h2 style={{ fontFamily:"'Cormorant Garamond', serif", fontSize:28, fontWeight:700, color:'oklch(22% 0.06 265)', marginBottom:10 }}>You're already signed in.</h2>
        <p style={{ fontSize:14.5, color:'oklch(40% 0.04 265)', lineHeight:1.6, marginBottom:24 }}>
          You're logged in as <strong>{authUser?.email}</strong>, which isn't an instructor account. To apply as an instructor, please sign out first and complete the application form fresh.
        </p>
        <div style={{ display:'flex', gap:10, justifyContent:'center', flexWrap:'wrap' }}>
          <button onClick={() => setPage('home')} style={{ background:'#fff', color:'oklch(28% 0.05 265)', border:'1.5px solid oklch(85% 0.02 265)', borderRadius:8, padding:'11px 22px', fontWeight:600, fontSize:14, cursor:'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif" }}>Back to home</button>
          <button onClick={signOut} disabled={busy} style={{ background:'oklch(22% 0.06 265)', color:'#fff', border:'none', borderRadius:8, padding:'11px 22px', fontWeight:700, fontSize:14, cursor: busy ? 'wait' : 'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif", opacity: busy ? 0.7 : 1 }}>
            {busy ? 'Signing out…' : 'Sign out and apply →'}
          </button>
        </div>
      </div>
    </div>
  );
};

// Rendered when an already-approved teacher (admin-created, or a legacy
// pre-wizard row) clicks the navbar "For Instructors" link. The wizard
// has nothing to ask them, so we point them straight back at their
// dashboard. Auto-redirects after 2.5s in case the teacher just clicked
// through reflexively.
const BIV2AlreadyApproved = ({ setPage, fullName }) => {
  const goDashboard = React.useCallback(() => {
    try {
      history.replaceState({}, '', location.pathname + '?page=instructor-portal' + location.hash);
    } catch (_) {}
    setPage('instructor-portal');
  }, [setPage]);
  React.useEffect(() => {
    const t = setTimeout(goDashboard, 2500);
    return () => clearTimeout(t);
  }, [goDashboard]);
  const first = (fullName || '').trim().split(/\s+/)[0] || 'there';
  return (
    <div style={{ minHeight:'70vh', display:'flex', alignItems:'center', justifyContent:'center', padding:'40px 24px' }}>
      <div style={{ maxWidth:520, background:'#fff', border:'1px solid oklch(92% 0.01 265)', borderRadius:14, padding:'36px 32px', boxShadow:'0 4px 24px rgba(0,0,0,0.06)', textAlign:'center' }}>
        <div style={{ fontSize:44, marginBottom:14 }}>✅</div>
        <h2 style={{ fontFamily:"'Cormorant Garamond', serif", fontSize:28, fontWeight:700, color:'oklch(22% 0.06 265)', marginBottom:10 }}>You're already set up, {first}.</h2>
        <p style={{ fontSize:14.5, color:'oklch(40% 0.04 265)', lineHeight:1.6, marginBottom:24 }}>
          Your teaching profile is approved — no application to fill out. Taking you to your dashboard…
        </p>
        <button onClick={goDashboard} style={{ background:'oklch(22% 0.06 265)', color:'#fff', border:'none', borderRadius:8, padding:'11px 22px', fontWeight:700, fontSize:14, cursor:'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif" }}>
          Go to my dashboard →
        </button>
      </div>
    </div>
  );
};

const biv2H1 = { fontFamily:"'Cormorant Garamond', serif", fontSize:'clamp(22px, 6.5vw, 30px)', fontWeight:600, color:'oklch(22% 0.06 265)', lineHeight:1.15, marginBottom:6 };
const biv2H3 = { fontFamily:"'Plus Jakarta Sans', sans-serif", fontSize:15, fontWeight:700, color:'oklch(22% 0.06 265)', marginBottom:14 };
const biv2Sub = { fontSize:14.5, color:'oklch(45% 0.04 265)', lineHeight:1.55 };
const biv2Input = {
  width:'100%', padding:'12px 14px', border:'1.5px solid oklch(88% 0.01 265)',
  borderRadius:8, fontSize:15, fontFamily:"'Plus Jakarta Sans', sans-serif",
  outline:'none', background:'#fff', minHeight:44,
};
const biv2ErrorBox = {
  background:'oklch(96% 0.03 25)', color:'oklch(40% 0.15 25)',
  padding:'10px 14px', borderRadius:8, fontSize:13, marginTop:14,
  border:'1px solid oklch(88% 0.06 25)',
};
const biv2CheckLabel = {
  display:'flex', alignItems:'flex-start', fontSize:13.5, lineHeight:1.5, color:'oklch(28% 0.04 265)', cursor:'pointer',
};

Object.assign(window, {
  // Public entry component, mounted by app.jsx
  BecomeInstructorV2,
  // Shared by the step components in become-instructor-v2-steps.jsx —
  // they read these off window at load time.
  BIV2Field, BIV2NavBar,
  biv2H1, biv2H3, biv2Sub, biv2Input, biv2ErrorBox, biv2CheckLabel,
});
