// financial/src/estate.jsx — the Estate section.
//
// Two jobs, in the order that actually matters.
//
// STRATEGY comes first even though the tab reads "Will" first, because the
// finding that changes outcomes is not in the will at all: most of this
// balance sheet passes by beneficiary designation or by survivorship, and a
// will written without checking those forms quietly contradicts them. The
// transfer map computes that from accounts the app already holds.
//
// WILL captures what a drafting attorney asks for in the first meeting, so
// the meeting is spent drafting rather than on discovery.
//
// Everything here reports or captures. It does not advise, and it does not
// state a legal threshold — see lib/estatePlan for why the exemption is an
// input carrying the date it was confirmed rather than a constant.
//
// Slices run in their own Babel scope; src/shared.jsx runs first and
// publishes window.FinanceShared.

const { useState, useContext, useMemo } = React;
const { DataContext, useToast, fmtCur, USER_PROFILE, calcAge } = window.FinanceShared;

const AGE_OF_MAJORITY = 18;

// The questions that need a specialist. Kept as data so the briefing export
// and the on-screen list cannot drift apart, and phrased as questions on
// purpose: the US/UK rules changed recently and an answer written here would
// be relied on.
const CROSS_BORDER_QUESTIONS = [
  { group: 'Citizenship and the marital deduction', weight: 'critical', items: [
    'Are we both US citizens? If the surviving spouse is not, the unlimited marital deduction does not apply and transfers above the exemption are taxed at the first death unless a qualified domestic trust is used. Confirm before anything is drafted.',
    'Does dual citizenship change the analysis, and for which of us?',
  ]},
  { group: 'UK inheritance tax reach', weight: 'critical', items: [
    'On what basis would UK inheritance tax reach our worldwide estate, and does it apply to one of us or both? The UK moved from a domicile test to a residence-based test in 2025 — confirm the current rule and where we each fall under it.',
    'What is the current UK threshold, and how does it compare with the US exemption?',
    'How does the US/UK estate tax treaty allocate taxing rights and relieve double taxation?',
  ]},
  { group: 'If the children move to the UK', weight: 'critical', items: [
    'How should a US trust be structured so it can support UK-resident beneficiaries without punitive treatment on distributions?',
    'Should the trust be able to migrate its trustee or situs if the children actually relocate — build that in now, or accept it later?',
    'Who would the trustee be in that scenario, and what reporting falls on a UK-resident guardian?',
    'Should there be a parallel UK will covering UK-situs assets?',
  ]},
  { group: 'Inheriting from the UK', weight: 'normal', items: [
    'If we inherit UK assets, what is owed and by whom? UK inheritance tax is generally settled by the estate before distribution — what lands on us as US recipients?',
    'What reporting is triggered for a foreign bequest and foreign accounts, and what are the penalties for missing it?',
    'Do inherited UK assets get a US cost-basis step-up?',
  ]},
  { group: 'The UK pension specifically', weight: 'normal', items: [
    'Who inherits it, and does an expression-of-wish form override anything we write in a will?',
    'Is it inside or outside our taxable estate on each side?',
  ]},
  { group: 'US mechanics', weight: 'normal', items: [
    'Life insurance we own is included in our taxable estate. Is an irrevocable life insurance trust worth it at our numbers?',
    'If a trust is named as beneficiary of retirement accounts, how must it be drafted to avoid accelerating the payout, and how does the ten-year rule apply to minor children?',
    'Revocable living trust to avoid probate, or is Delaware probate light enough not to bother?',
    'Confirm Delaware has no state estate or inheritance tax, and what the current federal exemption is.',
  ]},
];

// Roles a plan needs filled. `why` is shown next to each because the reason a
// role exists is the thing people actually need in order to choose someone.
const ROLES = [
  { key: 'guardianPerson', label: 'Guardian of the person', why: 'Raises the children. With no will, a court chooses.' },
  { key: 'guardianEstate', label: 'Guardian of the estate', why: 'Manages their money. Need not be the same person.' },
  { key: 'executor', label: 'Executor', why: 'Administers the estate through probate.' },
  { key: 'trustee', label: 'Trustee', why: 'May serve for decades, and here may deal with beneficiaries abroad.' },
  { key: 'poaFinancial', label: 'Financial power of attorney', why: 'Acts if you are alive but unable to. A will never covers this.' },
  { key: 'poaHealthcare', label: 'Healthcare proxy', why: 'Decides medical care, and holds your directive.' },
];

const ANCILLARY = [
  { key: 'financialPoa', label: 'Durable financial power of attorney' },
  { key: 'healthcarePoa', label: 'Healthcare power of attorney / advance directive' },
  { key: 'hipaa', label: 'HIPAA authorisation' },
  { key: 'letterOfIntent', label: 'Letter of intent to the guardian' },
  { key: 'digitalAssets', label: 'Digital asset access and password custody' },
  { key: 'burial', label: 'Funeral and burial wishes' },
];

function Field({ label, hint, children }) {
  return (
    <div style={{marginBottom:10}}>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'baseline',marginBottom:3,gap:8}}>
        <span className="label" style={{marginBottom:0}}>{label}</span>
        {hint && <span style={{fontSize:10,color:'#64748b',textAlign:'right'}}>{hint}</span>}
      </div>
      {children}
    </div>
  );
}

function Estate() {
  const { accounts, kidsPlan, estatePlan, estateDesignations, saveEstatePlan, saveEstateDesignation } = useContext(DataContext);
  const { show, Toast } = useToast();
  const [view, setView] = useState('strategy'); // 'strategy' | 'will' | 'briefing'
  const [saving, setSaving] = useState(false);
  const [editing, setEditing] = useState(null); // account id whose designation is open

  // The stored plan is the source of truth until the moment you edit, and only
  // then does a local draft take over. Copying the stored doc into state with
  // an effect instead has two faults: the first render shows an empty form
  // while the data is already in hand, and a later reload of the doc — a save
  // from another tab, a provider refresh — silently overwrites edits in
  // progress. A null draft means "nothing typed yet", which is a different
  // state from "typed and identical".
  const [draft, setDraft] = useState(null);
  const cfg = draft || estatePlan || {};
  const dirty = draft !== null;

  const set = (patch) => setDraft(d => ({...(d || estatePlan || {}), ...patch}));
  const setPerson = (role, slot, value) => {
    const people = {...(cfg.people||{})};
    people[role] = {...(people[role]||{}), [slot]: value};
    set({people});
  };
  const save = async () => {
    setSaving(true);
    try { await saveEstatePlan(cfg); setDraft(null); show('Estate plan saved'); }
    catch(e){ show(e.message,'error'); }
    finally { setSaving(false); }
  };

  // Only children who are actually minors matter here — the flag exists
  // because a minor cannot receive property, and an adult child can.
  const minors = useMemo(()=>{
    return ((kidsPlan && kidsPlan.kids) || [])
      .filter(k => k && k.name && k.dob)
      .map(k => ({ name: k.name, age: calcAge(k.dob) }))
      .filter(k => k.age < AGE_OF_MAJORITY);
  },[kidsPlan]);

  const map = useMemo(
    ()=>EstatePlan.buildTransferMap(accounts, estateDesignations, { minors }),
    [accounts, estateDesignations, minors]
  );
  const exposure = useMemo(()=>EstatePlan.probateExposure(map),[map]);
  const gross = useMemo(()=>EstatePlan.grossEstate(map, cfg.policies||[]),[map, cfg.policies]);

  // The date the youngest child stops depending on the cover. Term insurance
  // that lapses before it is cover that isn't there when it is needed, and
  // that date is derivable rather than something to ask for.
  const dependentUntil = useMemo(()=>{
    const kids = ((kidsPlan && kidsPlan.kids)||[]).filter(k=>k && k.dob);
    if(!kids.length) return null;
    const latest = kids.map(k=>{
      const d = new Date(k.dob); d.setFullYear(d.getFullYear() + AGE_OF_MAJORITY); return d;
    }).sort((a,b)=>b-a)[0];
    return latest ? latest.toISOString().slice(0,10) : null;
  },[kidsPlan]);

  const policies = cfg.policies || [];

  // Everyone a policy can be written on, from the real kid records rather
  // than free text — a policy has to name a person the rest of the app knows,
  // or the beneficiary and minor checks have nothing to match against.
  const insurable = useMemo(()=>{
    const kids = ((kidsPlan && kidsPlan.kids)||[])
      .filter(k=>k && k.name)
      .map(k=>({ value:`kid:${k.id||k.name}`, label:k.name, kind:'dependent' }));
    return [
      { value:'you', label:'You', kind:'principal' },
      { value:'spouse', label:'Your wife', kind:'principal' },
      ...kids,
    ];
  },[kidsPlan]);

  // Cover in force counts the EARNERS only — see estatePlan.coverInForce.
  const cover = useMemo(()=>EstatePlan.coverInForce(policies),[policies]);
  const coverage = useMemo(()=>EstatePlan.lifeCoverageNeed({
    ...(cfg.coverageInputs||{}), coverInForce: cover.total,
  }),[cfg.coverageInputs, cover.total]);

  const policyAudit = useMemo(
    ()=>policies.map(p=>({ policy:p, flags: EstatePlan.policyFlags(p, {
      minors, dependentUntil, principalShortfall: Math.max(0, coverage.gap),
    }) })),
    [policies, minors, dependentUntil, coverage.gap]
  );

  const setPolicy = (i, patch) => {
    const next = policies.map((p,j)=>j===i?{...p,...patch}:p);
    set({policies:next});
  };
  const headroom = useMemo(
    ()=>EstatePlan.exemptionHeadroom(gross.total, cfg.exemption, { today: new Date().toISOString().slice(0,10) }),
    [gross, cfg.exemption]
  );
  const ready = useMemo(()=>EstatePlan.readiness(cfg, map),[cfg, map]);

  const errorRows = map.filter(r => r.flags.some(f => f.severity === 'error'));

  return (
    <div className="page">
      {Toast}
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:16,flexWrap:'wrap',gap:8}}>
        <div className="page-title" style={{marginBottom:0}}>Estate</div>
        <div style={{display:'flex',gap:8,alignItems:'center'}}>
          {dirty && <button className="btn-primary" onClick={save} disabled={saving} style={{padding:'5px 14px',fontSize:12,borderRadius:6,cursor:'pointer'}}>{saving?'Saving…':'Save'}</button>}
          <div style={{display:'flex',gap:4}}>
            {[['strategy','Strategy'],['will','Will'],['briefing','Briefing']].map(([k,lbl])=>(
              <button key={k} onClick={()=>setView(k)}
                style={{padding:'5px 14px',fontSize:12,borderRadius:6,cursor:'pointer',
                  background:view===k?'#10b981':'transparent',
                  color:view===k?'#fff':'#64748b',
                  border:`1px solid ${view===k?'#10b981':'#334155'}`}}>{lbl}</button>
            ))}
          </div>
        </div>
      </div>

      {/* Readiness — the same weighted items the briefing exports. */}
      <div className="card" style={{marginBottom:16}}>
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',flexWrap:'wrap',gap:10}}>
          <div>
            <div className="label" style={{marginBottom:2}}>Preparation</div>
            <div style={{fontSize:11,color:'#64748b'}}>{ready.done} of {ready.total} settled · weighted by consequence, not effort</div>
          </div>
          <div style={{fontSize:26,fontWeight:700,color:ready.pct>=80?'#10b981':ready.pct>=40?'#f59e0b':'#ef4444'}}>{ready.pct}%</div>
        </div>
        <div style={{height:6,background:'#1e2a3a',borderRadius:3,overflow:'hidden',margin:'10px 0 12px'}}>
          <div style={{width:`${ready.pct}%`,height:'100%',background:ready.pct>=80?'#10b981':ready.pct>=40?'#f59e0b':'#ef4444'}}/>
        </div>
        <div style={{display:'grid',gap:6}}>
          {ready.items.filter(i=>!i.done).map(i=>(
            <div key={i.id} style={{fontSize:11,color:'#94a3b8',lineHeight:1.55,display:'flex',gap:8}}>
              <span style={{color:'#ef4444',flexShrink:0}}>○</span>
              <span><strong style={{color:'#e2e8f0'}}>{i.label}.</strong> {i.why}</span>
            </div>
          ))}
          {ready.items.every(i=>i.done) && <div style={{fontSize:11,color:'#10b981'}}>Everything this app can check is answered. The remaining work is the lawyer's.</div>}
        </div>
      </div>

      {/* ── Strategy ─────────────────────────────────────────────────────── */}
      {view==='strategy' && (<>
        {errorRows.length > 0 && (
          <div className="card" style={{marginBottom:16,borderColor:'rgba(239,68,68,0.4)',background:'rgba(239,68,68,0.05)'}}>
            <div style={{color:'#fca5a5',fontWeight:600,marginBottom:8,fontSize:13}}>
              {errorRows.length} account{errorRows.length!==1?'s':''} need attention before any document is drafted
            </div>
            <div style={{display:'grid',gap:8}}>
              {errorRows.map(r=>(
                <div key={r.id} style={{fontSize:11,color:'#94a3b8',lineHeight:1.6}}>
                  <strong style={{color:'#e2e8f0'}}>{r.name}</strong> · {fmtCur(r.balance)}
                  {r.flags.filter(f=>f.severity==='error').map((f,i)=>(
                    <div key={i} style={{color:'#fca5a5',marginTop:2}}>{f.message}</div>
                  ))}
                </div>
              ))}
            </div>
          </div>
        )}

        <div className="grid-4" style={{marginBottom:16}}>
          <div className="card-sm">
            <div className="label">Passes under the will</div>
            <div className="val-md">{fmtCur(exposure.underWill)}</div>
            <div style={{fontSize:10,color:'#64748b',marginTop:3}}>{exposure.pctUnderWill.toFixed(0)}% of assets</div>
          </div>
          <div className="card-sm">
            <div className="label">Passes outside it</div>
            <div className="val-md" style={{color:'#3b82f6'}}>{fmtCur(exposure.outsideWill)}</div>
            <div style={{fontSize:10,color:'#64748b',marginTop:3}}>by designation or title</div>
          </div>
          <div className="card-sm">
            <div className="label">At risk</div>
            <div className="val-md" style={{color:exposure.atRisk>0?'#ef4444':'#10b981'}}>{fmtCur(exposure.atRisk)}</div>
            <div style={{fontSize:10,color:'#64748b',marginTop:3}}>no beneficiary recorded</div>
          </div>
          <div className="card-sm">
            <div className="label">Gross estate</div>
            <div className="val-md">{fmtCur(gross.total)}</div>
            <div style={{fontSize:10,color:'#64748b',marginTop:3}}>
              {gross.ownedDeathBenefit>0 ? `incl. ${fmtCur(gross.ownedDeathBenefit)} life cover` : 'no policies captured'}
            </div>
          </div>
        </div>

        <div className="card" style={{marginBottom:16}}>
          <div className="label" style={{marginBottom:6}}>Transfer map</div>
          <div style={{fontSize:11,color:'#64748b',marginBottom:12,lineHeight:1.6,maxWidth:'62ch'}}>
            How each account actually moves. A will only reaches the rows marked <strong style={{color:'#e2e8f0'}}>Probate</strong> —
            everything else is decided by a form held by the custodian or by how the title is worded, and never reads the will.
            An account with no beneficiary recorded falls into probate by default, which is why it counts as at risk rather than outside it.
          </div>
          <div style={{overflowX:'auto'}}>
            <table>
              <thead><tr>
                <th>Account</th><th style={{textAlign:'right'}}>Balance</th><th>Transfers by</th>
                <th>Will?</th><th>Beneficiaries</th><th></th>
              </tr></thead>
              <tbody>
                {map.map(r=>{
                  const errs = r.flags.filter(f=>f.severity==='error');
                  return (
                    <tr key={r.id} style={errs.length?{background:'rgba(239,68,68,0.06)'}:undefined}>
                      <td>
                        <span style={{color:'#e2e8f0'}}>{r.name}</span>
                        {r.flags.map((f,i)=>(
                          <div key={i} style={{fontSize:9,marginTop:2,lineHeight:1.4,color:f.severity==='error'?'#fca5a5':'#fbbf24'}}>{f.message}</div>
                        ))}
                      </td>
                      <td style={{textAlign:'right',fontVariantNumeric:'tabular-nums'}}>{fmtCur(r.balance)}</td>
                      <td>
                        <span style={{color:'#94a3b8'}}>{r.mode.label}</span>
                        {!r.certain && <div style={{fontSize:9,color:'#64748b',marginTop:2}}>assumed — {r.modeSource}</div>}
                      </td>
                      <td style={{color:r.mode.willControls?'#10b981':'#64748b'}}>{r.mode.willControls?'Yes':'No'}</td>
                      <td style={{fontSize:11,color:'#94a3b8'}}>
                        {r.recorded
                          ? <>
                              {r.primary.length>0 && <div>1st: {r.primary.map(p=>p.name).join(', ')}</div>}
                              {r.contingent.length>0 && <div style={{color:'#64748b'}}>2nd: {r.contingent.map(p=>p.name).join(', ')}</div>}
                              {r.lastConfirmed && <div style={{fontSize:9,color:'#475569',marginTop:2}}>confirmed {r.lastConfirmed}</div>}
                            </>
                          : <span style={{color:'#64748b'}}>nothing recorded</span>}
                      </td>
                      <td style={{textAlign:'right'}}>
                        <button onClick={()=>setEditing(editing===r.id?null:r.id)}
                          style={{padding:'2px 8px',fontSize:10,borderRadius:5,cursor:'pointer',background:'transparent',color:'#64748b',border:'1px solid #334155'}}>
                          {editing===r.id?'Close':'Record'}
                        </button>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
          {editing && (()=>{
            const row = map.find(r=>r.id===editing);
            if(!row) return null;
            return <DesignationEditor row={row} onSave={async (rec)=>{
              try { await saveEstateDesignation(row.id, rec); show(`Recorded for ${row.name}`); setEditing(null); }
              catch(e){ show(e.message,'error'); }
            }}/>;
          })()}
        </div>

        <div className="card" style={{marginBottom:16}}>
          <div className="label" style={{marginBottom:6}}>Estate tax headroom</div>
          {headroom.unknown
            ? <div style={{fontSize:11,color:'#f59e0b',lineHeight:1.6,maxWidth:'62ch'}}>{headroom.message}</div>
            : <div style={{fontSize:12,color:'#94a3b8',lineHeight:1.7}}>
                Gross estate <strong style={{color:'#e2e8f0'}}>{fmtCur(gross.total)}</strong> against{' '}
                <strong style={{color:'#e2e8f0'}}>{fmtCur(headroom.available)}</strong> of exemption
                ({headroom.people} × {fmtCur(headroom.perPerson)}) →{' '}
                <strong style={{color:headroom.over?'#ef4444':'#10b981'}}>
                  {headroom.over ? `${fmtCur(-headroom.headroom)} over` : `${fmtCur(headroom.headroom)} of headroom`}
                </strong>
                {headroom.stale && <div style={{color:'#f59e0b',fontSize:11,marginTop:4}}>
                  Confirmed {headroom.confirmedOn} — over a year ago. This figure is indexed and has been changed by statute; re-confirm it.
                </div>}
              </div>}
          <div className="grid-2" style={{gap:10,marginTop:12}}>
            <Field label="Exemption per person" hint="from your lawyer — never assumed here">
              <input type="number" step={100000} value={(cfg.exemption&&cfg.exemption.perPerson)||''}
                onChange={e=>set({exemption:{...(cfg.exemption||{}),perPerson:Number(e.target.value)||0}})}/>
            </Field>
            <Field label="Date confirmed">
              <input type="date" value={(cfg.exemption&&cfg.exemption.confirmedOn)||''}
                onChange={e=>set({exemption:{...(cfg.exemption||{}),confirmedOn:e.target.value,people:(cfg.exemption&&cfg.exemption.people)||2}})}/>
            </Field>
          </div>
        </div>

        <div className="card" style={{marginBottom:16}}>
          <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:6,flexWrap:'wrap',gap:8}}>
            <div className="label" style={{marginBottom:0}}>Life insurance</div>
            <button onClick={()=>set({policies:[...policies,{insurer:'',kind:'term',insured:'you',owner:'insured',deathBenefit:0,beneficiaries:[],expires:''}]})}
              style={{padding:'4px 12px',fontSize:11,borderRadius:6,cursor:'pointer',background:'transparent',color:'#10b981',border:'1px solid #10b981'}}>Add a policy</button>
          </div>
          <div style={{fontSize:11,color:'#64748b',marginBottom:12,lineHeight:1.6,maxWidth:'62ch'}}>
            Usually the largest single sum a family ever receives, and the one asset bought once and never
            looked at again. Who <strong style={{color:'#e2e8f0'}}>owns</strong> a policy decides whether its
            death benefit sits inside the taxable estate — which is a different question from who receives it.
          </div>

          {policies.length === 0 && (
            <div style={{fontSize:11,color:'#f59e0b'}}>
              No policies recorded, so the gross estate above excludes life cover entirely and the coverage
              check below has nothing to measure.
            </div>
          )}

          <div style={{display:'grid',gap:12}}>
            {policyAudit.map(({policy:p, flags}, i)=>{
              const errs = flags.filter(f=>f.severity==='error');
              return (
                <div key={i} style={{border:`1px solid ${errs.length?'rgba(239,68,68,0.35)':'#1e2a3a'}`,
                  background:errs.length?'rgba(239,68,68,0.05)':'rgba(255,255,255,0.02)',borderRadius:8,padding:12}}>
                  <div className="grid-2" style={{gap:10}}>
                    <Field label="Insurer"><input value={p.insurer||''} onChange={e=>setPolicy(i,{insurer:e.target.value})}/></Field>
                    <Field label="Death benefit">
                      <input type="number" step={50000} value={p.deathBenefit||0} onChange={e=>setPolicy(i,{deathBenefit:Number(e.target.value)||0})}/>
                    </Field>
                    <Field label="Type" hint="group cover ends with the job">
                      <select value={p.kind||'term'} onChange={e=>setPolicy(i,{kind:e.target.value})}>
                        <option value="term">Term</option>
                        <option value="whole">Whole / permanent</option>
                        <option value="group">Employer group</option>
                        <option value="rider">Child rider on a parent's policy</option>
                      </select>
                    </Field>
                    <Field label="Who is insured" hint={insurable.length<3?'add the children on the Kids tab to insure them here':undefined}>
                      <select value={p.insured||'you'} onChange={e=>setPolicy(i,{insured:e.target.value})}>
                        {insurable.map(o=>(<option key={o.value} value={o.value}>{o.label}</option>))}
                      </select>
                    </Field>
                    <Field label="Who owns the policy" hint="decides the tax treatment">
                      <select value={p.owner||'insured'} onChange={e=>setPolicy(i,{owner:e.target.value})}>
                        <option value="insured">The person insured</option>
                        <option value="other">Someone else</option>
                        <option value="trust">A trust</option>
                      </select>
                    </Field>
                    <Field label={p.kind==='term'?'Term ends':p.kind==='rider'?'Rider ends':'Expiry (if any)'}>
                      <input type="date" value={p.expires||''} onChange={e=>setPolicy(i,{expires:e.target.value})}/>
                    </Field>
                    {(p.kind==='whole'||p.kind==='rider') && (
                      <Field label="Cash value" hint="an asset you own today, unlike the death benefit">
                        <input type="number" step={1000} value={p.cashValue||0}
                          onChange={e=>setPolicy(i,{cashValue:Number(e.target.value)||0})}/>
                      </Field>
                    )}
                  </div>
                  <Field label="Beneficiaries" hint="comma separated, exactly as the form reads">
                    <input value={(p.beneficiaries||[]).map(b=>b.name).join(', ')}
                      onChange={e=>setPolicy(i,{beneficiaries:e.target.value.split(',').map(x=>x.trim()).filter(Boolean).map(name=>({name}))})}/>
                  </Field>
                  {flags.map((f,fi)=>(
                    <div key={fi} style={{fontSize:10,lineHeight:1.6,marginTop:4,
                      color:f.severity==='error'?'#fca5a5':f.severity==='warn'?'#fbbf24':'#64748b'}}>{f.message}</div>
                  ))}
                  <button onClick={()=>set({policies:policies.filter((_,j)=>j!==i)})}
                    style={{marginTop:8,padding:'2px 10px',fontSize:10,borderRadius:5,cursor:'pointer',background:'transparent',color:'#64748b',border:'1px solid #334155'}}>Remove</button>
                </div>
              );
            })}
          </div>
        </div>

        <div className="card" style={{marginBottom:16}}>
          <div className="label" style={{marginBottom:6}}>Is there enough cover?</div>
          <div style={{fontSize:11,color:'#64748b',marginBottom:12,lineHeight:1.6,maxWidth:'62ch'}}>
            Built from obligations rather than a multiple of salary, because the multiple hides which
            obligation is driving it — and the obligations are the part that changes as a mortgage
            amortises and children age out.
          </div>
          <div className="grid-2" style={{gap:10}}>
            {[['debts','Debts to clear','$'],['annualIncome','Annual income to replace','$'],
              ['incomeReplacementYears','Years of income',''],['childYearsRemaining','Total child-years to independence',''],
              ['costPerChildYear','Cost per child-year','$'],['education','Education','$'],
              ['finalExpenses','Final expenses','$'],['liquidAssets','Liquid assets already available','$']].map(([k,lbl,pre])=>(
              <Field key={k} label={lbl}>
                <input type="number" value={(cfg.coverageInputs&&cfg.coverageInputs[k])||0}
                  onChange={e=>set({coverageInputs:{...(cfg.coverageInputs||{}),[k]:Number(e.target.value)||0}})}/>
              </Field>
            ))}
          </div>
          {coverage.unknown
            ? <div style={{fontSize:11,color:'#64748b',marginTop:6}}>Fill in what applies and the shortfall appears here with its arithmetic.</div>
            : <div style={{marginTop:10,paddingTop:10,borderTop:'1px solid #1e2a3a'}}>
                {coverage.components.map((c,i)=>(
                  <div key={i} style={{display:'flex',justifyContent:'space-between',fontSize:11,color:'#94a3b8',padding:'2px 0'}}>
                    <span>{c.label}</span><span style={{fontVariantNumeric:'tabular-nums'}}>{fmtCur(c.amount)}</span>
                  </div>
                ))}
                <div style={{display:'flex',justifyContent:'space-between',fontSize:12,color:'#e2e8f0',fontWeight:600,padding:'6px 0 2px',borderTop:'1px solid #1e2a3a',marginTop:4}}>
                  <span>Cover needed</span><span style={{fontVariantNumeric:'tabular-nums'}}>{fmtCur(coverage.need)}</span>
                </div>
                <div style={{display:'flex',justifyContent:'space-between',fontSize:12,color:'#94a3b8',padding:'2px 0'}}>
                  <span>In force on you and your wife</span>
                  <span style={{fontVariantNumeric:'tabular-nums'}}>{fmtCur(cover.principal)}</span>
                </div>
                {cover.dependent > 0 && (
                  <div style={{display:'flex',justifyContent:'space-between',fontSize:11,color:'#64748b',padding:'2px 0'}}>
                    <span>On the children — not counted, it replaces no income</span>
                    <span style={{fontVariantNumeric:'tabular-nums'}}>{fmtCur(cover.dependent)}</span>
                  </div>
                )}
                <div style={{display:'flex',justifyContent:'space-between',fontSize:13,fontWeight:700,padding:'6px 0 0',
                  color:coverage.covered?'#10b981':'#ef4444'}}>
                  <span>{coverage.covered?'Surplus':'Shortfall'}</span>
                  <span style={{fontVariantNumeric:'tabular-nums'}}>{fmtCur(Math.abs(coverage.gap))}</span>
                </div>
              </div>}
        </div>

        <div className="card">
          <div className="label" style={{marginBottom:6}}>Questions for a US/UK specialist</div>
          <div style={{fontSize:11,color:'#64748b',marginBottom:12,lineHeight:1.6,maxWidth:'62ch'}}>
            Ask directly whether the firm has handled US/UK estates. These are questions rather than answers
            because the rules changed recently — the UK moved to a residence-based test in 2025 — and a
            summary held in an app is exactly the thing that goes stale and gets believed.
          </div>
          {CROSS_BORDER_QUESTIONS.map(g=>(
            <div key={g.group} style={{marginBottom:14}}>
              <div style={{fontSize:10,letterSpacing:'0.08em',textTransform:'uppercase',color:g.weight==='critical'?'#f59e0b':'#64748b',marginBottom:6}}>
                {g.group}{g.weight==='critical' && ' · critical'}
              </div>
              <ol style={{margin:0,paddingLeft:18,display:'grid',gap:5}}>
                {g.items.map((q,i)=><li key={i} style={{fontSize:11,color:'#94a3b8',lineHeight:1.6,maxWidth:'68ch'}}>{q}</li>)}
              </ol>
            </div>
          ))}
        </div>
      </>)}

      {/* ── Will ─────────────────────────────────────────────────────────── */}
      {view==='will' && (<>
        <div className="card" style={{marginBottom:16}}>
          <div className="label" style={{marginBottom:6}}>Who does what</div>
          <div style={{fontSize:11,color:'#64748b',marginBottom:12,lineHeight:1.6,maxWidth:'62ch'}}>
            Name a backup for every role. A nomination with no alternate fails the moment the first choice
            cannot serve, and that is when it matters.
          </div>
          <div className="grid-2" style={{gap:'0 20px'}}>
            {ROLES.map(role=>(
              <div key={role.key} style={{marginBottom:14}}>
                <div style={{fontSize:12,color:'#e2e8f0',fontWeight:600}}>{role.label}</div>
                <div style={{fontSize:10,color:'#64748b',margin:'2px 0 6px',lineHeight:1.5}}>{role.why}</div>
                <div className="grid-2" style={{gap:8}}>
                  <input placeholder="Primary" value={(cfg.people&&cfg.people[role.key]&&cfg.people[role.key].primary)||''}
                    onChange={e=>setPerson(role.key,'primary',e.target.value)}/>
                  <input placeholder="Backup" value={(cfg.people&&cfg.people[role.key]&&cfg.people[role.key].backup)||''}
                    onChange={e=>setPerson(role.key,'backup',e.target.value)}/>
                </div>
              </div>
            ))}
          </div>
        </div>

        <div className="card" style={{marginBottom:16}}>
          <div className="label" style={{marginBottom:6}}>When the children receive money</div>
          <div style={{fontSize:11,color:'#64748b',marginBottom:12,lineHeight:1.6,maxWidth:'62ch'}}>
            With no trust the default is the entire share outright at {AGE_OF_MAJORITY}. Staging it is a
            decision you make, not one the lawyer makes for you. A trustee can still pay for education,
            health and housing before these ages.
          </div>
          <div style={{display:'grid',gap:8,maxWidth:520}}>
            {(cfg.distributionAges||[]).map((d,i)=>(
              <div key={i} style={{display:'flex',gap:8,alignItems:'center'}}>
                <input type="number" value={d.age} min={18} max={65} style={{width:90}}
                  onChange={e=>{ const a=[...cfg.distributionAges]; a[i]={...a[i],age:Number(e.target.value)}; set({distributionAges:a}); }}/>
                <span style={{fontSize:11,color:'#64748b'}}>years old →</span>
                <input type="number" value={d.pct} min={0} max={100} style={{width:90}}
                  onChange={e=>{ const a=[...cfg.distributionAges]; a[i]={...a[i],pct:Number(e.target.value)}; set({distributionAges:a}); }}/>
                <span style={{fontSize:11,color:'#64748b'}}>% of their share</span>
                <button onClick={()=>set({distributionAges:cfg.distributionAges.filter((_,j)=>j!==i)})}
                  style={{marginLeft:'auto',padding:'2px 8px',fontSize:10,borderRadius:5,cursor:'pointer',background:'transparent',color:'#64748b',border:'1px solid #334155'}}>✕</button>
              </div>
            ))}
            <div style={{display:'flex',gap:8,alignItems:'center'}}>
              <button onClick={()=>set({distributionAges:[...(cfg.distributionAges||[]),{age:25,pct:33}]})}
                style={{padding:'4px 12px',fontSize:11,borderRadius:6,cursor:'pointer',background:'transparent',color:'#10b981',border:'1px solid #10b981'}}>Add a stage</button>
              {(cfg.distributionAges||[]).length>0 && (()=>{
                const tot=(cfg.distributionAges||[]).reduce((s,d)=>s+(Number(d.pct)||0),0);
                return <span style={{fontSize:11,color:tot===100?'#10b981':'#f59e0b'}}>{tot}% allocated{tot!==100?' — should total 100':''}</span>;
              })()}
            </div>
          </div>
        </div>

        <div className="card" style={{marginBottom:16}}>
          <div className="label" style={{marginBottom:6}}>Disposition</div>
          <div className="grid-2" style={{gap:10}}>
            <Field label="Residuary estate" hint="who takes what's left">
              <select value={cfg.residuary||'spouse-then-children'} onChange={e=>set({residuary:e.target.value})}>
                <option value="spouse-then-children">All to spouse; if neither survives, to the children</option>
                <option value="split">Split between spouse and a trust for the children</option>
                <option value="custom">Something else — describe below</option>
              </select>
            </Field>
            <Field label="Survivorship period" hint="days a beneficiary must outlive you">
              <input type="number" value={cfg.survivorshipDays!=null?cfg.survivorshipDays:30} min={0} max={180}
                onChange={e=>set({survivorshipDays:Number(e.target.value)})}/>
            </Field>
          </div>
          <Field label="Specific bequests, charities, or anything unusual">
            <textarea rows={3} value={cfg.bequests||''} onChange={e=>set({bequests:e.target.value})} style={{fontSize:12}}/>
          </Field>
          <Field label="If none of us survives" hint="the ultimate contingent beneficiary — otherwise intestacy decides">
            <input value={cfg.ultimateBeneficiary||''} onChange={e=>set({ultimateBeneficiary:e.target.value})}/>
          </Field>
        </div>

        <div className="card" style={{marginBottom:16}}>
          <div className="label" style={{marginBottom:6}}>Cross-border facts to confirm</div>
          <div className="grid-2" style={{gap:10}}>
            <Field label="Are both spouses US citizens?" hint="drives the marital deduction">
              <select value={(cfg.crossBorder&&cfg.crossBorder.bothUsCitizens)||'unknown'}
                onChange={e=>set({crossBorder:{...(cfg.crossBorder||{}),bothUsCitizens:e.target.value}})}>
                <option value="unknown">Not confirmed</option>
                <option value="yes">Yes, both</option>
                <option value="no">No — one or both are not</option>
              </select>
            </Field>
            <Field label="Would the children live in the UK if neither of us survives?">
              <select value={(cfg.crossBorder&&cfg.crossBorder.ukChildren)||'unknown'}
                onChange={e=>set({crossBorder:{...(cfg.crossBorder||{}),ukChildren:e.target.value}})}>
                <option value="unknown">Not decided</option>
                <option value="likely">Likely</option>
                <option value="no">No</option>
              </select>
            </Field>
          </div>
          {(cfg.crossBorder&&cfg.crossBorder.bothUsCitizens)==='no' && (
            <div style={{fontSize:11,color:'#fca5a5',background:'rgba(239,68,68,0.07)',border:'1px solid rgba(239,68,68,0.3)',borderRadius:8,padding:'8px 12px',marginTop:4,lineHeight:1.6}}>
              Raise this first. The unlimited marital deduction requires the surviving spouse to be a US citizen —
              without it, transfers above the exemption are taxed at the first death unless a qualified domestic
              trust is used. It changes the structure of everything else.
            </div>
          )}
          {(cfg.crossBorder&&cfg.crossBorder.ukChildren)==='likely' && (
            <div style={{fontSize:11,color:'#fbbf24',background:'rgba(245,158,11,0.07)',border:'1px solid rgba(245,158,11,0.3)',borderRadius:8,padding:'8px 12px',marginTop:8,lineHeight:1.6}}>
              Then the trust has to be drafted for UK-resident beneficiaries from the start, and a US will
              nominates a guardian without binding a UK court. Both belong in the first conversation, not a later one.
            </div>
          )}
        </div>

        <div className="card">
          <div className="label" style={{marginBottom:6}}>Documents beyond the will</div>
          <div style={{fontSize:11,color:'#64748b',marginBottom:12,lineHeight:1.6,maxWidth:'62ch'}}>
            A will only operates after death. Incapacity is more likely at your ages and is covered by none of it.
          </div>
          <div style={{display:'grid',gap:7}}>
            {ANCILLARY.map(d=>(
              <label key={d.key} style={{display:'flex',gap:9,alignItems:'center',fontSize:12,color:'#94a3b8',cursor:'pointer'}}>
                <input type="checkbox" checked={!!(cfg.ancillary&&cfg.ancillary[d.key])}
                  onChange={e=>set({ancillary:{...(cfg.ancillary||{}),[d.key]:e.target.checked}})}/>
                {d.label}
              </label>
            ))}
          </div>
        </div>
      </>)}

      {/* ── Briefing ─────────────────────────────────────────────────────── */}
      {view==='briefing' && (
        <div className="card">
          <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:10,flexWrap:'wrap',gap:8}}>
            <div>
              <div className="label" style={{marginBottom:2}}>Briefing for the lawyer</div>
              <div style={{fontSize:11,color:'#64748b'}}>Everything below is assembled from what the app already holds. Print it or copy it.</div>
            </div>
            <button onClick={()=>window.print()} style={{padding:'5px 14px',fontSize:12,borderRadius:6,cursor:'pointer',background:'transparent',color:'#10b981',border:'1px solid #10b981'}}>Print</button>
          </div>
          <pre style={{whiteSpace:'pre-wrap',fontSize:11,lineHeight:1.7,color:'#94a3b8',fontFamily:'inherit',margin:0}}>
{buildBriefing({cfg, map, exposure, gross, headroom, minors, ready})}
          </pre>
        </div>
      )}
    </div>
  );
}

// The briefing is generated from the same objects the screen renders, so it
// cannot drift from what was reviewed.
function buildBriefing({cfg, map, exposure, gross, headroom, minors, ready}) {
  const L = [];
  const money = n => fmtCur(n);
  L.push('ESTATE PLANNING BRIEFING');
  L.push(`Prepared ${new Date().toLocaleDateString('en-US',{month:'long',day:'numeric',year:'numeric'})}`);
  L.push('');
  L.push('HOUSEHOLD');
  L.push(`  Adults aged ${calcAge(USER_PROFILE.birthday)} and ${calcAge(USER_PROFILE.spouseBirthday)}`);
  if (minors.length) L.push(`  Minor children: ${minors.map(m=>`${m.name} (${m.age})`).join(', ')}`);
  L.push('  Domicile: Delaware. Cross-border exposure: United States / United Kingdom.');
  L.push('');
  L.push('HOW ASSETS TRANSFER');
  L.push(`  Under the will:      ${money(exposure.underWill)}  (${exposure.pctUnderWill.toFixed(0)}%)`);
  L.push(`  Outside the will:    ${money(exposure.outsideWill)}`);
  L.push(`  No designation:      ${money(exposure.atRisk)}  <- defaults into probate`);
  L.push(`  Gross estate:        ${money(gross.total)}${gross.ownedDeathBenefit?`  (incl. ${money(gross.ownedDeathBenefit)} owned life cover)`:''}`);
  if (!headroom.unknown) L.push(`  Exemption available: ${money(headroom.available)} -> ${headroom.over?`${money(-headroom.headroom)} OVER`:`${money(headroom.headroom)} headroom`}`);
  else L.push('  Exemption:           not on file — please supply the current figure');
  L.push('');
  const problems = map.filter(r=>r.flags.some(f=>f.severity==='error'));
  if (problems.length) {
    L.push('ACCOUNTS NEEDING ATTENTION');
    problems.forEach(r=>{
      L.push(`  ${r.name} — ${money(r.balance)} — ${r.mode.label}`);
      r.flags.filter(f=>f.severity==='error').forEach(f=>L.push(`      ${f.message}`));
    });
    L.push('');
  }
  L.push('APPOINTMENTS');
  ROLES.forEach(role=>{
    const p = (cfg.people&&cfg.people[role.key])||{};
    L.push(`  ${role.label}: ${p.primary||'NOT NAMED'}${p.backup?` (backup ${p.backup})`:''}`);
  });
  L.push('');
  if ((cfg.distributionAges||[]).length) {
    L.push('DISTRIBUTION TO CHILDREN');
    cfg.distributionAges.forEach(d=>L.push(`  ${d.pct}% at age ${d.age}`));
    L.push('');
  }
  L.push('OPEN QUESTIONS');
  ready.items.filter(i=>!i.done).forEach(i=>L.push(`  - ${i.label}: ${i.why}`));
  L.push('');
  L.push('QUESTIONS FOR A US/UK SPECIALIST');
  CROSS_BORDER_QUESTIONS.forEach(g=>{
    L.push(`  ${g.group.toUpperCase()}${g.weight==='critical'?' (critical)':''}`);
    g.items.forEach(q=>L.push(`    - ${q}`));
  });
  return L.join('\n');
}

// Recording a beneficiary is data entry, so it stays deliberately plain: names
// and a confirmation date. The date matters as much as the names — a
// designation nobody has checked since before a marriage or a birth is the
// usual way an ex-spouse inherits a retirement account.
function DesignationEditor({ row, onSave }) {
  const [primary, setPrimary] = useState((row.primary||[]).map(p=>p.name).join(', '));
  const [contingent, setContingent] = useState((row.contingent||[]).map(p=>p.name).join(', '));
  const [lastConfirmed, setLastConfirmed] = useState(row.lastConfirmed||'');
  const [mode, setMode] = useState(row.designation&&row.designation.transferMode||'');
  const parse = s => String(s||'').split(',').map(x=>x.trim()).filter(Boolean).map(name=>({name}));
  return (
    <div style={{marginTop:12,padding:12,background:'rgba(59,130,246,0.06)',border:'1px solid rgba(59,130,246,0.25)',borderRadius:8}}>
      <div style={{fontSize:12,color:'#e2e8f0',fontWeight:600,marginBottom:8}}>{row.name}</div>
      <div className="grid-2" style={{gap:10}}>
        <Field label="Primary beneficiaries" hint="comma separated, as written on the form">
          <input value={primary} onChange={e=>setPrimary(e.target.value)}/>
        </Field>
        <Field label="Contingent beneficiaries">
          <input value={contingent} onChange={e=>setContingent(e.target.value)}/>
        </Field>
        <Field label="Last confirmed with the custodian">
          <input type="date" value={lastConfirmed} onChange={e=>setLastConfirmed(e.target.value)}/>
        </Field>
        <Field label="Transfer route" hint="override if the guess is wrong">
          <select value={mode} onChange={e=>setMode(e.target.value)}>
            <option value="">Use the app's classification</option>
            {Object.values(EstatePlan.TRANSFER_MODES).map(m=>(
              <option key={m.key} value={m.key}>{m.label}</option>
            ))}
          </select>
        </Field>
      </div>
      <button className="btn-primary" style={{padding:'5px 14px',fontSize:12,borderRadius:6,cursor:'pointer'}}
        onClick={()=>onSave({ primary:parse(primary), contingent:parse(contingent), lastConfirmed:lastConfirmed||null, transferMode:mode||null })}>
        Save this account
      </button>
    </div>
  );
}

window.FinanceViews = Object.assign(window.FinanceViews || {}, { Estate });
