/* global React, BrainMark, I, Progress, StepHead, Field, Select, CheckRow, NavFooter, Helper, HelpLink, Opt, ZipField */
const { useState: useBI, useEffect: useBIE } = React;

const US_STATES = ['AL','AK','AZ','AR','CA','CO','CT','DE','FL','GA','HI','ID','IL','IN','IA','KS','KY','LA','ME','MD','MA','MI','MN','MS','MO','MT','NE','NV','NH','NJ','NM','NY','NC','ND','OH','OK','OR','PA','RI','SC','SD','TN','TX','UT','VT','VA','WA','WV','WI','WY','DC'];
const COUNTRIES = ['Canada','Mexico','United Kingdom','Australia','Germany','France','India','China','Japan','Other'];
const SUFFIXES = ['Jr.','Sr.','II','III','IV','V','Other'];
const MONTHS = ['0','1','2','3','4','5','6','7','8','9','10','11'];
const MIL_BRANCH = ['Army','Navy','Air Force','Marine Corps','Coast Guard','Space Force','National Guard','Reserves','Other'];

const HOUSING = [
  { value: 'Own', sub: 'I own my current home.', icon: () => I.home(22) },
  { value: 'Rent', sub: 'I rent my current home.', icon: () => I.condo(20) },
  { value: 'Living Rent Free', sub: "I'm living rent free.", icon: () => I.seedling(20) },
];
const CITIZENSHIP = [
  { value: 'U.S. Citizen', sub: 'I am a citizen of the United States.' },
  { value: 'Permanent Resident Alien', sub: 'I hold a green card / permanent residency.' },
  { value: 'Non-Permanent Resident Alien', sub: 'I live in the U.S. on a visa or other status.' },
];
const MARITAL = [
  { value: 'Married', sub: 'I am legally married.' },
  { value: 'Unmarried', sub: 'Single, divorced, or widowed.' },
  { value: 'Separated', sub: 'Legally separated from my spouse.' },
];
const MIL_STATUS = [
  { value: 'Active Duty', sub: 'Currently serving on active duty.' },
  { value: 'Retired, Discharged, or Departed from Service', sub: 'No longer serving.' },
  { value: 'Reserve / National Guard', sub: 'Serving in the Reserve or National Guard.' },
  { value: 'Surviving Spouse', sub: 'Surviving spouse of a service member.' },
];
const CREDIT = [
  { value: '760+', title: 'Excellent', sub: '760 and above' },
  { value: '720-759', title: 'Very Good', sub: '720 – 759' },
  { value: '680-719', title: 'Good', sub: '680 – 719' },
  { value: '640-679', title: 'Fair', sub: '640 – 679' },
  { value: '580-639', title: 'Needs Work', sub: '580 – 639' },
  { value: 'not-sure', title: 'Not Sure', sub: "I don't know my score? That's okay." },
];
const CREDIT_LABEL = { '760+': 'Excellent · 760+', '720-759': 'Very Good · 720–759', '680-719': 'Good · 680–719', '640-679': 'Fair · 640–679', '580-639': 'Needs Work · 580–639', 'not-sure': 'Not Sure' };

const BI_LS = 'bevri_borrower_v1';
const biDigits = s => (s || '').replace(/[^\d]/g, '');
const biMoney = s => { const d = biDigits(s); return d ? Number(d).toLocaleString('en-US') : ''; };
const biEmailOk = e => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e || '');
const biPhoneOk = p => biDigits(p).length === 10;
const biFmtPhone = s => {
  const d = biDigits(s).slice(0, 10);
  if (d.length > 6) return `(${d.slice(0,3)}) ${d.slice(3,6)}-${d.slice(6)}`;
  if (d.length > 3) return `(${d.slice(0,3)}) ${d.slice(3)}`;
  return d ? `(${d}` : '';
};
const biFmtDobInput = s => {
  const d = biDigits(s).slice(0, 8);
  if (d.length > 4) return `${d.slice(0,2)}/${d.slice(2,4)}/${d.slice(4)}`;
  if (d.length > 2) return `${d.slice(0,2)}/${d.slice(2)}`;
  return d;
};
const biDobIso = s => {
  if (/^\d{4}-\d{2}-\d{2}$/.test(s || '')) return s;
  const d = biDigits(s);
  if (d.length !== 8) return '';
  const mm = d.slice(0,2), dd = d.slice(2,4), yyyy = d.slice(4);
  const date = new Date(`${yyyy}-${mm}-${dd}T00:00:00Z`);
  if (date.getUTCFullYear() !== Number(yyyy) || date.getUTCMonth() + 1 !== Number(mm) || date.getUTCDate() !== Number(dd)) return '';
  return `${yyyy}-${mm}-${dd}`;
};

const BI_STEPS = ['name', 'contact', 'address', 'time', 'housing', 'mailing', 'citizenship', 'dob', 'marital', 'military', 'credit', 'review'];

const BI_DEFAULT = {
  name: { first: '', middle: '', last: '', suffix: '', suffixOther: '' },
  email: '',
  phone: '',
  curAddr: { intl: false, street: '', unit: '', city: '', state: '', zip: '', province: '', postal: '', country: '' },
  // Zero years and zero months is a valid answer (just moved in), so the
  // fields start at 0 and never demand interaction.
  timeAt: { years: '0', months: '0' },
  housing: '',
  // Renter follow-up (URLA parity: monthly rent is required when renting).
  rent: '',
  mailingSame: false,
  mailAddr: { intl: false, street: '', unit: '', city: '', state: '', zip: '', province: '', postal: '', country: '' },
  citizenship: '',
  dob: '',
  marital: '',
  military: null,
  milStatus: '', milBranch: '', milBranchOther: '',
  vaDisability: null,
  credit: '',
  coBorrowers: [],
  touched: false,
};

/* ---- reusable address block (US or international) ---- */
function AddressBlock({ a, setA, t }) {
  // ZIP-first autofill: entering a ZIP fills city/state (editable; never
  // overwrites typed values, a re-fill only replaces our own previous fill).
  // Hook lives above the intl early-return so the hook order never changes.
  const zipFillRef = React.useRef({ city: '', state: '' });
  const applyZipFill = hit => {
    const patch = {};
    if (!String(a.city || '').trim() || a.city === zipFillRef.current.city) { patch.city = hit.city; zipFillRef.current.city = hit.city; }
    if (!a.state || a.state === zipFillRef.current.state) { patch.state = hit.state; zipFillRef.current.state = hit.state; }
    if (Object.keys(patch).length) setA(patch);
  };
  if (a.intl) {
    const e = f => t && !String(a[f] || '').trim();
    return <>
      <Field label="Street address" value={a.street} onChange={v => setA({ street: v })} placeholder="221B Baker Street" error={e('street') ? 'Required' : ''} />
      <Field label="Apartment / unit number" optional value={a.unit} onChange={v => setA({ unit: v })} placeholder="Flat 2" />
      <div className="field-row">
        <Field label="City / locality" value={a.city} onChange={v => setA({ city: v })} placeholder="London" error={e('city') ? 'Required' : ''} />
        <Field label="State / province / region" value={a.province} onChange={v => setA({ province: v })} placeholder="Greater London" error={e('province') ? 'Required' : ''} />
      </div>
      <div className="field-row">
        <Field label="Postal code" value={a.postal} onChange={v => setA({ postal: v })} placeholder="NW1 6XE" error={e('postal') ? 'Required' : ''} />
        <Select label="Country" value={a.country} onChange={v => setA({ country: v })} options={COUNTRIES} placeholder="Select country" error={e('country') ? 'Required' : ''} />
      </div>
    </>;
  }
  const errStreet = t && !a.street.trim() ? 'Required' : '';
  const errCity = t && !a.city.trim() ? 'Required' : '';
  const errState = t && !a.state ? 'Required' : '';
  const errZip = t && !/^\d{5}$/.test(biDigits(a.zip)) ? 'Enter a 5-digit ZIP' : '';
  return <>
    <Field label="Street address" value={a.street} onChange={v => setA({ street: v })} placeholder="123 Main Street" error={errStreet} />
    <Field label="Apartment / unit number" optional value={a.unit} onChange={v => setA({ unit: v })} placeholder="Unit 4B" />
    <ZipField value={a.zip} onChange={v => setA({ zip: biDigits(v).slice(0, 5) })} onFill={applyZipFill} error={errZip} />
    <div className="field-row">
      <Field label="City" value={a.city} onChange={v => setA({ city: v })} placeholder="San Mateo" error={errCity} />
      <Select label="State" value={a.state} onChange={v => setA({ state: v })} options={US_STATES} placeholder="State" error={errState} />
    </div>
  </>;
}

function addrValid(a) {
  if (a.intl) return a.street.trim() && a.city.trim() && a.province.trim() && a.postal.trim() && a.country;
  return a.street.trim() && a.city.trim() && a.state && /^\d{5}$/.test(biDigits(a.zip));
}
function addrSummary(a) {
  if (a.intl) return `${a.street}${a.unit ? ', ' + a.unit : ''}\n${[a.city, a.province].filter(Boolean).join(', ')} ${a.postal}\n${a.country}`;
  return `${a.street}${a.unit ? ', ' + a.unit : ''}\n${[a.city, a.state].filter(Boolean).join(', ')} ${a.zip}`;
}
function fmtDob(s) {
  if (!s) return '—';
  const [y, m, d] = s.split('-');
  return `${m}/${d}/${y}`;
}

/* ---- per-step validity ---- */
function stepValid(step, d) {
  switch (step) {
    case 'name': return d.name.first.trim() && d.name.last.trim() && (d.name.suffix !== 'Other' || d.name.suffixOther.trim());
    case 'contact': return biEmailOk(d.email) && biPhoneOk(d.phone);
    case 'address': return addrValid(d.curAddr);
    // Empty means 0 (older drafts started blank); 0 yr 0 mo is always valid.
    case 'time': return true;
    // Renters must provide monthly rent (URLA requires it); Own and Living
    // Rent Free have no follow-ups by design.
    case 'housing': return !!d.housing && (d.housing !== 'Rent' || d.rent !== '');
    case 'mailing': return d.mailingSame || addrValid(d.mailAddr);
    case 'citizenship': return !!d.citizenship;
    case 'dob': return !!biDobIso(d.dob);
    case 'marital': return !!d.marital;
    case 'military':
      if (!d.military) return false;
      if (d.military === 'no') return true;
      return d.milStatus && d.milBranch && (d.milBranch !== 'Other' || d.milBranchOther.trim()) && d.vaDisability;
    case 'credit': return !!d.credit;
    default: return true;
  }
}

/* ===================================================================== */
function BorrowerInfo({ loanType = 'purchase', onBack, onContinue, onProgress }) {
  const saved = (() => { try { return JSON.parse(localStorage.getItem(BI_LS)); } catch { return null; } })();
  const [data, setData] = useBI(saved?.data ? { ...BI_DEFAULT, ...saved.data, touched: false } : (saved && !saved.data ? { ...BI_DEFAULT, ...saved, touched: false } : BI_DEFAULT));
  // Identity-first gate already captured name + contact on screen one;
  // fresh entries skip straight to the address step (a saved mid-flow
  // position always wins, and the data stays editable from the review list).
  const biIdentityDone = d => Boolean(d?.name?.first?.trim() && d?.name?.last?.trim() && biEmailOk(d?.email) && biPhoneOk(d?.phone));
  const [step, setStep] = useBI(saved?.step || (biIdentityDone(saved?.data) ? 'address' : 'name'));
  const [editReturn, setEditReturn] = useBI(false);
  const [cbEditing, setCbEditing] = useBI(null);   // { index: number|null, data } when adding/editing a co-borrower
  const [confirmRemove, setConfirmRemove] = useBI(null); // index pending removal
  const [primaryOpen, setPrimaryOpen] = useBI(false); // expand primary borrower cards when co-borrowers exist
  const [touchedFields, setTouchedFields] = useBI(new Set());
  const tb = field => () => setTouchedFields(prev => new Set([...prev, field]));
  const tf = field => t || touchedFields.has(field);

  const coBorrowers = data.coBorrowers || [];
  const primaryName = `${data.name.first} ${data.name.last}`.trim() || 'the borrower';

  function openAddCo() { if (coBorrowers.length >= 3) return; setCbEditing({ index: null, data: null }); }
  function openEditCo(i) { setCbEditing({ index: i, data: coBorrowers[i] }); }
  function saveCo(cb) {
    setData(d => {
      const list = [...(d.coBorrowers || [])];
      if (cbEditing.index == null) list.push(cb); else list[cbEditing.index] = cb;
      return { ...d, coBorrowers: list };
    });
    setCbEditing(null);
    const el = document.querySelector('.flow'); if (el) el.scrollTop = 0;
  }
  function removeCo(i) {
    setData(d => ({ ...d, coBorrowers: (d.coBorrowers || []).filter((_, idx) => idx !== i) }));
    setConfirmRemove(null);
  }

  useBIE(() => { try { localStorage.setItem(BI_LS, JSON.stringify({ step, data: { ...data, touched: false } })); } catch {} }, [step, data]);
  useBIE(() => {
    function onAutoFill(e) {
      if (!(e.detail?.posKeys || []).includes(BI_LS)) return;
      const updated = (() => { try { return JSON.parse(localStorage.getItem(BI_LS)); } catch { return null; } })();
      if (updated?.data) setData(d => ({ ...d, ...updated.data, name: { ...d.name, ...updated.data.name }, curAddr: { ...d.curAddr, ...updated.data.curAddr } }));
    }
    window.addEventListener('bevri:fields-autofilled', onAutoFill);
    return () => window.removeEventListener('bevri:fields-autofilled', onAutoFill);
  }, []);

  const set = patch => setData(d => ({ ...d, ...patch }));
  const setName = patch => set({ name: { ...data.name, ...patch } });
  const setCur = patch => set({ curAddr: { ...data.curAddr, ...patch } });
  const setMail = patch => set({ mailAddr: { ...data.mailAddr, ...patch } });
  const setTime = patch => set({ timeAt: { ...data.timeAt, ...patch } });
  const t = data.touched;

  const flowTop = () => { const el = document.querySelector('.flow'); if (el) el.scrollTop = 0; };
  function goTo(key) { setData(d => ({ ...d, touched: false })); setTouchedFields(new Set()); setStep(key); flowTop(); }

  function next() {
    if (!stepValid(step, data)) { set({ touched: true }); return; }
    if (editReturn) { setEditReturn(false); return goTo('review'); }
    const i = BI_STEPS.indexOf(step);
    goTo(BI_STEPS[i + 1]);
  }
  function back() {
    if (editReturn) { setEditReturn(false); return goTo('review'); }
    if (step === 'name') return onBack();
    const i = BI_STEPS.indexOf(step);
    goTo(BI_STEPS[i - 1]);
  }
  function edit(key) { setEditReturn(true); goTo(key); }

  // progress
  const sections = loanType === 'refinance'
    ? ['Refinance Details', 'Property Information', 'Borrower Information', 'Employment & Income', 'Assets', 'Credit / Declarations', 'Review & Submit']
    : ['Purchase Details', 'Borrower Information', 'Employment & Income', 'Assets', 'Credit / Declarations', 'Review & Submit'];
  const secIdx = loanType === 'refinance' ? 2 : 1;
  const di = BI_STEPS.indexOf(step);
  const fill = Math.round((di / (BI_STEPS.length - 1)) * 100);
  useBIE(() => { onProgress && onProgress({ fill, stepTitle: step }); }, [step, fill]);
  const nextLabel = editReturn ? 'Save changes' : 'Next';
  const ynErr = v => t && !v ? 'Please select an option' : '';

  let body = null;

  if (step === 'name') {
    body = <>
      <StepHead title="What's your name?" sub="Enter your legal name as it appears on your government ID." />
      <div className="field-row">
        <Field label="First name" value={data.name.first} onChange={v => setName({ first: v })} placeholder="Jane" error={t && !data.name.first.trim() ? 'Required' : ''} />
        <Field label="Middle name" optional value={data.name.middle} onChange={v => setName({ middle: v })} placeholder="A." />
      </div>
      <div className="field-row">
        <Field label="Last name" value={data.name.last} onChange={v => setName({ last: v })} placeholder="Doe" error={t && !data.name.last.trim() ? 'Required' : ''} />
        <Select label="Suffix" optional value={data.name.suffix} onChange={v => setName({ suffix: v })} options={SUFFIXES} placeholder="None" />
      </div>
      {data.name.suffix === 'Other' &&
        <Field label="Enter suffix" value={data.name.suffixOther} onChange={v => setName({ suffixOther: v })} placeholder="Your suffix" error={t && !data.name.suffixOther.trim() ? 'Required' : ''} />}
      <NavFooter onBack={back} onNext={next} nextLabel={nextLabel} />
    </>;
  }

  else if (step === 'contact') {
    const errEmail = tf('email') && !biEmailOk(data.email) ? 'Enter a valid email' : '';
    const errPhone = tf('phone') && !biPhoneOk(data.phone) ? 'Enter a valid 10-digit phone' : '';
    body = <>
      <StepHead title="What's your contact information?" sub="We'll use this for resume links, document requests, and loan team follow-up." />
      <div className="secure-note">
        {I.lock(13)}
        Your contact information is encrypted and stored securely.
      </div>
      <Field label="Email address" type="email" inputMode="email" value={data.email} onChange={v => set({ email: v })} onBlur={tb('email')} placeholder="jane@example.com" error={errEmail} />
      <Field label="Phone number" inputMode="tel" value={data.phone} onChange={v => set({ phone: biFmtPhone(v) })} onBlur={tb('phone')} placeholder="(555) 555-0123" error={errPhone} />
      <NavFooter onBack={back} onNext={next} nextLabel={nextLabel} />
    </>;
  }

  else if (step === 'address') {
    body = <>
      <StepHead title="What's your current address?" sub="Where do you currently live?" />
      <div className="bi-inline-check">
        <CheckRow checked={data.curAddr.intl} onToggle={() => setCur({ intl: !data.curAddr.intl })}>
          This address is outside of the U.S.
        </CheckRow>
      </div>
      <AddressBlock a={data.curAddr} setA={setCur} t={t} />
      <NavFooter onBack={back} onNext={next} nextLabel={nextLabel} />
    </>;
  }

  else if (step === 'time') {
    body = <>
      <StepHead title="How long have you lived at this address?" />
      <div className="field-row">
        <Field label="Years" inputMode="numeric" value={data.timeAt.years}
          onChange={v => setTime({ years: biDigits(v).slice(0, 2) })} placeholder="0" />
        <Select label="Months" value={data.timeAt.months} onChange={v => setTime({ months: v })} options={MONTHS} placeholder="0" />
      </div>
      <NavFooter onBack={back} onNext={next} nextLabel={nextLabel} />
    </>;
  }

  else if (step === 'housing') {
    body = <>
      <StepHead title="Do you own or rent your current home?" />
      <div className="opt-list">
        {HOUSING.map(h => (
          <Opt key={h.value} icon={h.icon()} title={h.value} sub={h.sub}
            selected={data.housing === h.value} onClick={() => set({ housing: h.value })} />
        ))}
      </div>
      {/* Renter-specific follow-up: only rent needs a dollar amount. */}
      {data.housing === 'Rent' && (
        <div className="step-anim" style={{ marginTop: 14 }}>
          <Field label="Monthly rent" prefix="$" inputMode="numeric" value={data.rent}
            onChange={v => set({ rent: biMoney(v) })} placeholder="1,800" />
        </div>
      )}
      <NavFooter onBack={back} onNext={next} nextLabel={nextLabel} nextDisabled={!stepValid('housing', data)} />
    </>;
  }

  else if (step === 'mailing') {
    body = <>
      <StepHead title="Where should we send your mail?"
        sub="We'll use this address for any physical documents related to your loan." />
      <div className="bi-inline-check">
        <CheckRow checked={data.mailingSame} onToggle={() => set({ mailingSame: !data.mailingSame })}>
          My mailing address is the same as my current address.
        </CheckRow>
      </div>
      {!data.mailingSame && <div className="step">
        <div className="bi-inline-check">
          <CheckRow checked={data.mailAddr.intl} onToggle={() => setMail({ intl: !data.mailAddr.intl })}>
            This mailing address is outside of the U.S.
          </CheckRow>
        </div>
        <AddressBlock a={data.mailAddr} setA={setMail} t={t} />
      </div>}
      <NavFooter onBack={back} onNext={next} nextLabel={nextLabel} />
    </>;
  }

  else if (step === 'citizenship') {
    body = <>
      <StepHead title="What's your citizenship status?"
        sub="Required for federal loan reporting and eligibility." />
      <div className="opt-list">
        {CITIZENSHIP.map(c => (
          <Opt key={c.value} title={c.value} sub={c.sub}
            selected={data.citizenship === c.value} onClick={() => set({ citizenship: c.value })} />
        ))}
      </div>
      <Helper label="Why do we ask this?" items={[
        { t: 'Loan program eligibility', d: 'Your citizenship status affects which loan programs you qualify for. For example, some programs require U.S. citizenship or permanent residency.' },
        { t: 'Federal reporting', d: 'Lenders are required by federal law to collect this information for compliance and fair lending oversight.' },
      ]} />
      <NavFooter onBack={back} onNext={next} nextLabel={nextLabel} nextDisabled={!data.citizenship} />
    </>;
  }

  else if (step === 'dob') {
    body = <>
      <StepHead title="What's your date of birth?" sub="Enter MM/DD/YYYY. Used to verify your identity and pull your credit report." />
      <div className="secure-note">
        {I.lock(13)}
        Date of birth is encrypted and only used to verify your identity.
      </div>
      <Field label="Date of birth" type="text" inputMode="numeric" value={/^\d{4}-/.test(data.dob || '') ? fmtDob(data.dob) : data.dob} onChange={v => set({ dob: biFmtDobInput(v) })} placeholder="MM/DD/YYYY" error={t && !biDobIso(data.dob) ? 'Enter a valid date' : ''} />
      <NavFooter onBack={back} onNext={next} nextLabel={nextLabel} />
    </>;
  }

  else if (step === 'marital') {
    body = <>
      <StepHead title="What's your marital status?" />
      <div className="opt-list">
        {MARITAL.map(m => (
          <Opt key={m.value} title={m.value} sub={m.sub}
            selected={data.marital === m.value} onClick={() => set({ marital: m.value })} />
        ))}
      </div>
      <NavFooter onBack={back} onNext={next} nextLabel={nextLabel} nextDisabled={!data.marital} />
    </>;
  }

  else if (step === 'military') {
    const isMil = data.military === 'yes';
    body = <>
      <StepHead title="Have you served in the U.S. military?"
        sub="Veterans and active service members may qualify for VA loan benefits including no down payment requirements and reduced fees." />
      <div className="opt-list two-up">
        <Opt icon={I.yes(22)} title="Yes" twoUp selected={data.military === 'yes'} onClick={() => set({ military: 'yes' })} />
        <Opt icon={I.no(20)} title="No" twoUp selected={data.military === 'no'} onClick={() => set({ military: 'no' })} />
      </div>
      {ynErr(data.military) && <div className="field-err" style={{ marginTop: 10 }}>{ynErr(data.military)}</div>}

      {isMil && <div className="step" style={{ marginTop: 24 }}>
        <Select label="What is your military service status?" value={data.milStatus} onChange={v => set({ milStatus: v })}
          options={MIL_STATUS.map(s => s.value)} placeholder="Select service status" error={t && !data.milStatus ? 'Required' : ''} />
        <Select label="Military branch" value={data.milBranch} onChange={v => set({ milBranch: v })} options={MIL_BRANCH} placeholder="Select branch"
          error={t && !data.milBranch ? 'Required' : ''} />
        {data.milBranch === 'Other' &&
          <Field label="Enter branch or service type" value={data.milBranchOther} onChange={v => set({ milBranchOther: v })} placeholder="Your branch" error={t && !data.milBranchOther.trim() ? 'Required' : ''} />}
        <p className="bi-q">Do you receive VA disability benefits?</p>
        <div className="bi-yesno">
          <Opt icon={I.yes(20)} title="Yes" twoUp selected={data.vaDisability === 'yes'} onClick={() => set({ vaDisability: 'yes' })} />
          <Opt icon={I.no(18)} title="No" twoUp selected={data.vaDisability === 'no'} onClick={() => set({ vaDisability: 'no' })} />
        </div>
        {ynErr(data.vaDisability) && <div className="field-err" style={{ marginTop: -8, marginBottom: 10 }}>{ynErr(data.vaDisability)}</div>}
        <p className="bi-helper-text">This information may help determine whether certain VA loan fees or benefits apply.</p>
      </div>}
      <NavFooter onBack={back} onNext={next} nextLabel={nextLabel} />
    </>;
  }

  else if (step === 'credit') {
    body = <>
      <StepHead title="What's your estimated credit score range?"
        sub="Your credit score helps us understand which loan options may be available. Don't worry if it's not perfect. This is only one part of the process." />
      <div className="opt-list">
        {CREDIT.map(c => (
          <Opt key={c.value} title={c.title} sub={c.sub}
            selected={data.credit === c.value} onClick={() => set({ credit: c.value })} />
        ))}
      </div>
      <Helper label="Why is your credit important?" items={[
        { t: 'Credit is one part of the picture', d: 'Your credit helps lenders understand your borrowing history and may impact your loan options, interest rate, and required down payment.' },
        { t: "It's not the only thing that matters", d: 'Income, assets, property type, loan program, and your overall financial profile are also reviewed. If your score needs work, we can help review your options.' },
      ]} />
      <NavFooter onBack={back} onNext={next} nextLabel={nextLabel} nextDisabled={!data.credit} />
    </>;
  }

  else if (step === 'review') {
    const normalizedDob = biDobIso(data.dob);
    if (normalizedDob && normalizedDob !== data.dob) setTimeout(() => set({ dob: normalizedDob }), 0);
    const nm = `${data.name.first}${data.name.middle ? ' ' + data.name.middle : ''} ${data.name.last}${data.name.suffix ? ' ' + (data.name.suffix === 'Other' ? data.name.suffixOther : data.name.suffix) : ''}`;
    const milVal = data.military === 'yes'
      ? `Yes\n${data.milStatus}\n${data.milBranch === 'Other' ? data.milBranchOther : data.milBranch}\nVA disability: ${data.vaDisability === 'yes' ? 'Yes' : 'No'}`
      : 'No';
    const sections2 = [
      { key: 'name', label: 'Name', value: nm },
      { key: 'contact', label: 'Contact', value: `${data.email || '—'}\n${data.phone || '—'}` },
      { key: 'address', label: 'Current Address', value: addrSummary(data.curAddr) },
      { key: 'time', label: 'Time at Address', value: `${data.timeAt.years || '0'} yr ${data.timeAt.months || '0'} mo` },
      { key: 'housing', label: 'Housing Type', value: data.housing === 'Rent' && data.rent ? `Rent · $${data.rent}/mo` : (data.housing || '—') },
      { key: 'mailing', label: 'Mailing Address', value: data.mailingSame ? 'Same as current address' : addrSummary(data.mailAddr) },
      { key: 'citizenship', label: 'Citizenship', value: data.citizenship || '—' },
      { key: 'dob', label: 'Date of Birth', value: fmtDob(biDobIso(data.dob) || data.dob), mono: true },
      { key: 'marital', label: 'Marital Status', value: data.marital || '—' },
      { key: 'military', label: 'Military Service', value: milVal },
      { key: 'credit', label: 'Credit Score Range', value: CREDIT_LABEL[data.credit] || '—' },
    ];
    const hasCo = coBorrowers.length > 0;
    const showPrimaryCards = !hasCo || primaryOpen;
    const primaryCards = (
      <div className="summary">
        {sections2.map(s => (
          <div className="sum-card" key={s.key}>
            <div className="sum-head">
              <div style={{ flex: 1 }}>
                <div className="sum-label">{s.label}</div>
                <div className={'sum-value' + (s.mono ? ' mono' : '')} style={{ whiteSpace: 'pre-line' }}>{s.value}</div>
              </div>
              <button className="sum-edit" onClick={() => edit(s.key)}>{I.pencil(13)}Edit</button>
            </div>
          </div>
        ))}
      </div>
    );
    body = <>
      <StepHead title="Review your borrower information"
        sub="Make sure everything looks right. You can edit any answer before we continue." />

      {hasCo ? (
        <div className="person-block">
          <button className="person-bar" onClick={() => setPrimaryOpen(o => !o)} aria-expanded={primaryOpen}>
            <span className="co-card-ava">{(data.name.first[0] || '') + (data.name.last[0] || '')}</span>
            <span className="person-bar-body">
              <span className="co-card-name">{nm}</span>
              <span className="person-bar-tag">Primary borrower</span>
            </span>
            <span className={'person-chev' + (primaryOpen ? ' open' : '')}>{I.chev(18)}</span>
          </button>
          {showPrimaryCards && <div className="person-cards">{primaryCards}</div>}
        </div>
      ) : primaryCards}

      {/* ---- co-borrowers ---- */}
      <div className="co-section">
        <div className="co-head">
          <div>
            <div className="co-title">Co-Borrowers</div>
            <div className="co-desc">Add anyone else who will be included on this loan application.</div>
          </div>
          <span className="co-count mono">{coBorrowers.length} / 3</span>
        </div>

        {coBorrowers.length === 0
          ? <div className="co-empty">No co-borrowers added yet.</div>
          : <div className="co-list">
              {coBorrowers.map((cb, i) => (
                <div className="co-card" key={i}>
                  <div className="co-card-ava">{(cb.name.first[0] || '') + (cb.name.last[0] || '')}</div>
                  <div className="co-card-body">
                    <div className="co-card-name">{cb.name.first} {cb.name.last}</div>
                    <div className="co-card-meta">{cb.email}</div>
                    <div className="co-card-meta">{cb.phone}</div>
                    {cb.marital && <div className="co-card-tag">{cb.marital === 'Married' && cb.marriedToBorrower === 'yes' ? `Married to ${primaryName}` : cb.marital}</div>}
                  </div>
                  <div className="co-card-actions">
                    <button className="co-act" onClick={() => openEditCo(i)}>{I.pencil(13)}Edit</button>
                    <button className="co-act danger" onClick={() => setConfirmRemove(i)}>{I.trash ? I.trash(13) : null}Remove</button>
                  </div>
                </div>
              ))}
            </div>}

        {coBorrowers.length < 3
          ? <button className="co-add" onClick={openAddCo}>
              <span className="co-add-icon">{I.plus ? I.plus(18) : '+'}</span>
              Add Co-Borrower
            </button>
          : <div className="co-limit">Maximum co-borrowers added. You can have up to 4 total borrowers on a loan application.</div>}
      </div>

      <NavFooter onBack={back} onNext={() => onContinue && onContinue()} nextLabel="Confirm and Continue" />
    </>;
  }

  if (cbEditing) {
    return (
      <CoBorrowerFlow
        initial={cbEditing.data}
        primaryName={primaryName}
        primaryAddr={data.curAddr}
        onCancel={() => { setCbEditing(null); const el = document.querySelector('.flow'); if (el) el.scrollTop = 0; }}
        onSave={saveCo}
        onProgress={onProgress} />
    );
  }

  const biStepNum = BI_STEPS.indexOf(step);
  const biTotalSteps = BI_STEPS.length - 1; // exclude 'review'

  return (
    <main className="flow">
      <div className="flow-col">
        <div className="step" key={step}>
          {step !== 'review' && (
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
              <div style={{ flex: 1, height: 3, borderRadius: 2, background: 'var(--line)' }}>
                <div style={{ height: '100%', borderRadius: 2, background: 'var(--sage)', width: `${((biStepNum) / biTotalSteps) * 100}%`, transition: 'width .35s' }} />
              </div>
              <span style={{ fontSize: 11, fontWeight: 600, letterSpacing: '.06em', color: 'var(--muted)', whiteSpace: 'nowrap', fontFamily: 'monospace' }}>
                {biStepNum + 1} / {biTotalSteps}
              </span>
            </div>
          )}
          <div className="step-anim" key={step}>{body}</div>
        </div>
      </div>
      {confirmRemove != null && (
        <div className="modal-scrim" onClick={() => setConfirmRemove(null)}>
          <div className="modal" onClick={e => e.stopPropagation()}>
            <div className="modal-title">Remove this co-borrower?</div>
            <div className="modal-body">
              This will remove {coBorrowers[confirmRemove] ? `${coBorrowers[confirmRemove].name.first} ${coBorrowers[confirmRemove].name.last}'s` : 'their'} information from the application.
            </div>
            <div className="modal-actions">
              <button className="btn btn-secondary" onClick={() => setConfirmRemove(null)}>Cancel</button>
              <button className="btn btn-danger" onClick={() => removeCo(confirmRemove)}>Remove Co-Borrower</button>
            </div>
          </div>
        </div>
      )}
    </main>
  );
}

window.BorrowerInfo = BorrowerInfo;
