// financial/src/strategy.jsx — the Financial Strategy section.
//
// Household overview, MFJ bracket ladder (year-keyed numbers from
// lib/taxConstants), contribution waterfall, milestone phases, and the two
// AI calls (generateStrategyInsights / generateTaxOptimization) rendered
// through the shared MarkdownView.
//
// Slices run in their own Babel scope; src/shared.jsx runs first and
// publishes window.FinanceShared.

const { useState, useEffect, useContext, useMemo, useRef, useCallback } = React;
const { DataContext, useToast, callFn, fmtCur, MarkdownView } = window.FinanceShared;

// ── Strategy ──────────────────────────────────────────────────────────────────
function Strategy() {
  const { compensation, retirementConfig, uid } = useContext(DataContext);
  const { show, Toast } = useToast();
  const currentYear = new Date().getFullYear();
  // Skip _projected synthetic rows so Strategy inputs reflect real comp, not
  // the 10yr-forward ladder-interpolated projection.
  const latestComp = (() => {
    const cur = compensation[currentYear];
    if (cur && !cur._projected) return cur;
    const prev = compensation[currentYear-1];
    if (prev && !prev._projected) return prev;
    return cur || prev || {};
  })();

  const [cfg, setCfg] = useState({
    yourSalary:150000, wifeSalary:80000, yourIC:0, yourRSU:0, yourAge:45, wifeAge:44,
    your401kContrib:23500, employerMatchPct:3, employerCorePct:5,
    employerCoreSalaryCap:100000, wife403bContrib:20500,
    wife403bEmployerContrib:0, expectedRetirementRate:22,
    dependentCareFsa:0, healthcareFsa:0,
  });
  // Strategies the household already has in place — passed to the AI so
  // suggestions build on (not repeat) what's already happening.
  const CURRENTLY_USING_OPTIONS = [
    {k:'depCareFsa', label:'Dependent Care FSA (spouse)'},
    {k:'healthFsa', label:'Healthcare FSA'},
    {k:'hsa', label:'HSA'},
    {k:'backdoorRoth', label:'Backdoor Roth IRA'},
    {k:'megaBackdoorRoth', label:'Mega Backdoor Roth'},
    {k:'traditional401k', label:'Traditional 401(k) (not Roth)'},
    {k:'espp', label:'ESPP'},
    {k:'dsp529', label:'529 for kids'},
    {k:'daf', label:'Donor-Advised Fund'},
    {k:'tlh', label:'Tax-loss harvesting'},
    {k:'itemize', label:'Itemizing deductions'},
  ];
  const [currentlyUsing, setCurrentlyUsing] = useState({});
  // Hydrate once when real data first arrives. Without the ref guard this
  // effect loops: latestComp is a fresh object every render (the IIFE returns
  // a new {} when no comp rows exist), so the deps always "change" and the
  // unconditional setCfg schedules another render. Same fix as Retirement.
  const hydratedRef = useRef(false);
  useEffect(()=>{
    if(hydratedRef.current) return;
    const hasComp = latestComp.baseSalary!=null || latestComp.bonus!=null || latestComp.rsu!=null;
    if(!hasComp && !retirementConfig) return; // nothing loaded yet — keep waiting
    hydratedRef.current = true;
    const n={...cfg};
    if(latestComp.baseSalary) n.yourSalary=latestComp.baseSalary;
    if(latestComp.bonus!=null) n.yourIC=latestComp.bonus;
    if(latestComp.rsu!=null) n.yourRSU=latestComp.rsu;
    if(retirementConfig){
      // NOTE: retirementConfig.salary is Total Comp (base+bonus+RSU) for the
      // Retirement tab. The Strategy tab computes grossIncome by summing
      // base + bonus + RSU + wifeSalary separately, so we must NOT copy TC
      // into yourSalary here — it would double-count bonus and RSU.
      if(retirementConfig.wifeSalary) n.wifeSalary=retirementConfig.wifeSalary;
      if(retirementConfig.currentAge) n.yourAge=retirementConfig.currentAge;
      if(retirementConfig.wifeAge) n.wifeAge=retirementConfig.wifeAge;
      if(retirementConfig.annualContribution) n.your401kContrib=retirementConfig.annualContribution;
      if(retirementConfig.employerMatchPct!==undefined) n.employerMatchPct=retirementConfig.employerMatchPct;
      if(retirementConfig.employerCorePct!==undefined) n.employerCorePct=retirementConfig.employerCorePct;
      if(retirementConfig.employerCoreSalaryCap) n.employerCoreSalaryCap=retirementConfig.employerCoreSalaryCap;
      if(retirementConfig.wife403bContrib) n.wife403bContrib=retirementConfig.wife403bContrib;
      if(retirementConfig.wife403bEmployerContrib!==undefined) n.wife403bEmployerContrib=retirementConfig.wife403bEmployerContrib;
    }
    setCfg(n);
  },[retirementConfig, latestComp]);
  const upd=k=>e=>setCfg(c=>({...c,[k]:Number(e.target.value)||0}));

  // All year-keyed IRS numbers come from lib/taxConstants. `tax.stale` means
  // the table has no entry for the current year yet — rendered as a chip on
  // the bracket card rather than silently computing with old numbers.
  const tax = window.TaxConstants.forYear(currentYear);
  const TAX_YEAR = tax.year;
  const BRACKET_COLORS = ['#10b981','#3b82f6','#8b5cf6','#f59e0b','#f97316','#ef4444','#dc2626'];
  const MFJ = tax.mfj.brackets.map((b,i)=>({...b, color: BRACKET_COLORS[i]||'#dc2626'}));
  const STD_DED = tax.mfj.stdDeduction;
  const grossIncome=(cfg.yourSalary||0)+(cfg.yourIC||0)+(cfg.yourRSU||0)+(cfg.wifeSalary||0);

  // Annualize YTD pre-tax payslip deductions (health + other) so taxable income
  // reflects actual payroll-level exclusions, not just 401(k) + standard ded.
  const ytd = compensation[currentYear]?.ytd;
  const payslipCount = compensation[currentYear]?.payslipCount || 0;
  const annualizePayslip = v => payslipCount > 0 ? Math.round((v||0) / payslipCount * 26) : 0;
  const healthPreTaxAnnual = annualizePayslip(ytd?.healthInsurance);
  const otherPreTaxAnnual = annualizePayslip(ytd?.otherDeductions); // FSA/HSA/commuter, etc.
  const preTaxDeductions = (cfg.your401kContrib||0) + healthPreTaxAnnual + otherPreTaxAnnual
    + (cfg.dependentCareFsa||0) + (cfg.healthcareFsa||0);

  const taxableIncome=Math.max(0, grossIncome - STD_DED - preTaxDeductions);
  const curBracket=MFJ.find(b=>taxableIncome>b.min&&(b.max===null||taxableIncome<=b.max))||MFJ[6];
  const marginalRate=curBracket.rate;
  const roomInBracket=curBracket.max?curBracket.max-taxableIncome:null;
  // Headroom to the 32% bracket — goal is to stay in the 24% bracket. Derived
  // from the table so it can't drift from the brackets again.
  const TWENTY_FOUR_CAP = MFJ.find(b=>b.rate===24).max;
  const roomToBracketJump = Math.max(0, TWENTY_FOUR_CAP - taxableIncome);
  const calcTax=inc=>{let t=0;for(const b of MFJ){if(inc<=b.min)break;t+=(Math.min(inc,b.max||inc)-b.min)*b.rate/100;}return t;};
  const estTax=calcTax(taxableIncome);
  const effectiveRate=taxableIncome>0?estTax/taxableIncome*100:0;

  const catchUpFor=age=>age>=60&&age<=63?(tax.k401.superCatchUp60to63||tax.k401.catchUp50):age>=50?tax.k401.catchUp50:0;
  const empLimit=tax.k401.employee+catchUpFor(cfg.yourAge);
  const totalLimit=tax.k401.total415c+(cfg.yourAge>=50?tax.k401.catchUp50:0);
  const wife403bLimit=tax.k401.employee+catchUpFor(cfg.wifeAge); // 403(b) shares the 402(g) limit
  const iraLimit=tax.ira.limit+(cfg.yourAge>=50?tax.ira.catchUp50:0);
  const wifeIraLimit=tax.ira.limit+(cfg.wifeAge>=50?tax.ira.catchUp50:0);
  const matchAmt=Math.min(cfg.your401kContrib||0,(cfg.yourSalary||0)*(cfg.employerMatchPct||0)/100);
  const coreAmt=Math.min(cfg.yourSalary||0,cfg.employerCoreSalaryCap||0)*(cfg.employerCorePct||0)/100;
  const totalEmp=matchAmt+coreAmt;
  const megaRoom=Math.max(0,totalLimit-(cfg.your401kContrib||0)-totalEmp);
  const ROTH_START=tax.mfj.rothPhaseOut.start,ROTH_END=tax.mfj.rothPhaseOut.end;
  const needsBackdoor=grossIncome>ROTH_START;
  const canDirectRoth=grossIncome<ROTH_START;
  const expRetRate=cfg.expectedRetirementRate||22;
  const rothAdv=expRetRate-marginalRate;
  const rothRec=rothAdv>0;
  const totalTaxAdv=empLimit+(iraLimit+wifeIraLimit)+wife403bLimit+megaRoom;
  const waterfall=[
    {p:1,name:'401(k) to employer match',amt:Math.round((cfg.yourSalary||0)*(cfg.employerMatchPct||0)/100),done:(cfg.your401kContrib||0)>0,note:cfg.employerMatchPct+'% match = free '+fmtCur(matchAmt)},
    {p:2,name:'HSA (if eligible)',amt:tax.hsa.family,done:false,note:'Triple tax advantage — '+fmtCur(tax.hsa.family)+' family '+TAX_YEAR},
    {p:3,name:'Max 401(k) — $'+empLimit.toLocaleString(),amt:empLimit,done:(cfg.your401kContrib||0)>=empLimit,note:'Contributing '+fmtCur(cfg.your401kContrib)},
    {p:4,name:"Wife's 403(b) match",amt:cfg.wife403bEmployerContrib||0,done:(cfg.wife403bContrib||0)>0,note:'Maximize employer match first'},
    {p:5,name:needsBackdoor?'Backdoor Roth IRA (both)':'Roth IRA (both)',amt:iraLimit+wifeIraLimit,done:false,note:needsBackdoor?'Non-deductible trad → convert':'Direct contribution'},
    {p:6,name:"Wife's 403(b) to max",amt:wife403bLimit,done:(cfg.wife403bContrib||0)>=wife403bLimit,note:'Additional tax-deferred growth'},
    {p:7,name:'Mega Backdoor Roth',amt:megaRoom,done:false,note:megaRoom>0?fmtCur(megaRoom)+' after-tax room':'No room left',off:megaRoom<=0},
    {p:8,name:'Taxable brokerage',amt:null,done:false,note:'Low-cost index funds, tax-loss harvesting'},
  ];
  const milestones=[
    {label:'Phase 1 — Building the Base',range:'Under $200k',active:grossIncome<200000,color:'#10b981',
     items:['Target Roth 401(k) — lower brackets now','Roth IRA direct contributions ($7.5k each)','Max employer match first','Build 3-6 month emergency fund']},
    {label:'Phase 2 — Accelerating',range:'$200k–$300k',active:grossIncome>=200000&&grossIncome<300000,color:'#3b82f6',
     items:['Switch to Traditional 401(k) — 24% bracket','Backdoor Roth IRA for both ($14k/yr)','Max wife\'s 403(b)','Explore mega backdoor Roth']},
    {label:'Phase 3 — Optimizing',range:'$300k–$400k',active:grossIncome>=300000&&grossIncome<400000,color:'#f59e0b',
     items:['Traditional 401(k) + backdoor Roth combo','Mega backdoor Roth for after-tax room','Tax-loss harvesting in taxable','Asset location across tax buckets']},
    {label:'Phase 4 — Wealth Compounding',range:'$400k+',active:grossIncome>=400000,color:'#8b5cf6',
     items:['Max all tax-advantaged accounts','Mega backdoor Roth to cap','DAF for charitable giving','Estate planning: wills, trusts, 529s']},
  ];
  const [insights,setInsights]=useState('');
  const [loadingInsights,setLoadingInsights]=useState(false);
  const handleGenerate=async()=>{
    setLoadingInsights(true);setInsights('');
    try{
      const r=await callFn('generateStrategyInsights',{
        yourSalary:cfg.yourSalary,yourIC:cfg.yourIC,yourRSU:cfg.yourRSU,wifeSalary:cfg.wifeSalary,yourAge:cfg.yourAge,wifeAge:cfg.wifeAge,
        grossIncome,marginalRatePct:marginalRate,taxableIncome,effectiveRatePct:Math.round(effectiveRate*10)/10,
        your401kContrib:cfg.your401kContrib,employerMatchPct:cfg.employerMatchPct,employerCorePct:cfg.employerCorePct,
        totalEmployerContrib:Math.round(totalEmp),megaBackdoorRoom:megaRoom,canDirectRoth,needsBackdoor,
        rothRecommended:rothRec,currentMarginalRatePct:marginalRate,expectedRetirementRatePct:expRetRate,
        wife403bContrib:cfg.wife403bContrib,iraLimit,wifeIraLimit,employeeLimit:empLimit,totalTaxAdvantaged:totalTaxAdv,
      });
      setInsights(r.insights);
    }catch(e){show(e.message,'error');}
    setLoadingInsights(false);
  };

  // ── Tax Optimization ──────────────────────────────────────────────────────
  // Build a 5-year forward income projection from compensation data so Claude
  // can ground year-by-year recommendations. Uses projected compensation if
  // present (compensation[y] for future years), otherwise escalates today's
  // base by salaryGrowthPct.
  const incomeProjection = useMemo(()=>{
    const growth = 0.05; // conservative fallback if compensation lacks projection
    const out = [];
    for (let i = 0; i <= 5; i++) {
      const y = currentYear + i;
      const c = compensation[y];
      const base = c?.baseSalary ?? Math.round((cfg.yourSalary||0) * Math.pow(1+growth, i));
      const bonus = c?.bonus ?? cfg.yourIC ?? 0;
      const rsu = c?.rsu ?? cfg.yourRSU ?? 0;
      const wife = c?.wifeSalary ?? Math.round((cfg.wifeSalary||0) * Math.pow(1+(retirementConfig?.wifeSalaryGrowth||2.5)/100, i));
      out.push({ year: y, base, bonus, rsu, wifeSalary: wife, gross: base + bonus + rsu + wife });
    }
    return out;
  },[compensation, currentYear, cfg.yourSalary, cfg.yourIC, cfg.yourRSU, cfg.wifeSalary, retirementConfig]);

  const [taxOpt, setTaxOpt] = useState('');
  const [loadingTaxOpt, setLoadingTaxOpt] = useState(false);
  const handleGenerateTaxOpt = async () => {
    setLoadingTaxOpt(true); setTaxOpt('');
    try {
      const activeStrategies = Object.entries(currentlyUsing).filter(([,v])=>v).map(([k])=>k);
      const r = await callFn('generateTaxOptimization', {
        filingStatus: 'MFJ',
        state: 'Delaware',
        ages: { you: cfg.yourAge, spouse: cfg.wifeAge },
        gross: { yourBase: cfg.yourSalary, yourBonus: cfg.yourIC, yourRSU: cfg.yourRSU, wifeSalary: cfg.wifeSalary, total: grossIncome },
        payrollPreTax: {
          yourElective401k: cfg.your401kContrib,
          wife403b: cfg.wife403bContrib,
          healthInsurancePayslipAnnualized: healthPreTaxAnnual,
          otherPayslipPreTaxAnnualized: otherPreTaxAnnual,
          dependentCareFsa: cfg.dependentCareFsa,
          healthcareFsaOrHsa: cfg.healthcareFsa,
        },
        employerContributions: { matchPct: cfg.employerMatchPct, corePct: cfg.employerCorePct, coreSalaryCap: cfg.employerCoreSalaryCap, totalEmployerDollars: Math.round(totalEmp) },
        currentTaxPicture: { standardDeductionMFJ: STD_DED, taxableIncome, marginalRatePct: marginalRate, effectiveRatePct: Math.round(effectiveRate*10)/10, roomBeforeCurrentBracketTops: roomInBracket, roomBefore32Bracket: roomToBracketJump },
        rothContext: { canDirectRoth, needsBackdoor, mergaBackdoorRoomAfterTax: megaRoom, expectedRetirementMarginalPct: expRetRate, rothFavoredByAnalysis: rothRec },
        irsLimits: { employee402g: empLimit, iraYour: iraLimit, iraWife: wifeIraLimit, totalTaxAdvantaged: totalTaxAdv },
        spouseContext: {
          delawareStateEmployee: true,
          seocPensionAccruing: true,
          eligibleForDSHBP: true,
          wife403bEmployerContrib: cfg.wife403bEmployerContrib,
        },
        currentlyUsing: activeStrategies,
        forwardIncomeProjection: incomeProjection,
      });
      setTaxOpt(r.insights);
    } catch (e) { show(e.message, 'error'); }
    setLoadingTaxOpt(false);
  };
  return (
    <div className="page">
      {Toast}
      <div className="page-title">Financial Strategy</div>

      <div className="card" style={{marginBottom:16}}>
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:14}}>
          <div style={{fontWeight:600,fontSize:14}}>Household Overview</div>
          <div style={{fontSize:11,color:'#64748b'}}>Auto-populated from Retirement tab</div>
        </div>
        {(() => {
          const renderField = ({k,label,prefix,suffix}) => (
            <div key={k}>
              <div className="label" style={{marginBottom:3,fontSize:11}}>{label}</div>
              <div style={{display:'flex',alignItems:'center',gap:4}}>
                {prefix&&<span style={{fontSize:11,color:'#64748b'}}>{prefix}</span>}
                <input type="number" value={cfg[k]??0} onChange={upd(k)} style={{flex:1}}/>
                {suffix&&<span style={{fontSize:11,color:'#64748b'}}>{suffix}</span>}
              </div>
            </div>
          );
          const sectionHeader = (label) => (
            <div style={{fontSize:11,fontWeight:600,color:'#94a3b8',textTransform:'uppercase',letterSpacing:0.5,marginBottom:10}}>{label}</div>
          );
          const gridStyle = {display:'grid',gridTemplateColumns:'repeat(auto-fill,minmax(180px,1fr))',gap:12};
          return (
            <div style={{display:'flex',flexDirection:'column',gap:16}}>
              <div>
                {sectionHeader('You')}
                <div style={gridStyle}>
                  {[
                    {k:'yourSalary',label:'Base Salary',prefix:'$'},
                    {k:'yourIC',label:'IC / Bonus',prefix:'$'},
                    {k:'yourRSU',label:'RSU',prefix:'$'},
                    {k:'yourAge',label:'Age'},
                    {k:'your401kContrib',label:'401(k) Contrib',prefix:'$'},
                    {k:'employerMatchPct',label:'Employer Match',suffix:'%'},
                    {k:'employerCorePct',label:'Employer Core',suffix:'%'},
                  ].map(renderField)}
                </div>
              </div>
              <div>
                {sectionHeader('Wife')}
                <div style={gridStyle}>
                  {[
                    {k:'wifeSalary',label:'Salary',prefix:'$'},
                    {k:'wifeAge',label:'Age'},
                    {k:'wife403bContrib',label:'403(b) Contrib',prefix:'$'},
                    {k:'dependentCareFsa',label:'Dependent Care FSA',prefix:'$'},
                  ].map(renderField)}
                </div>
              </div>
              <div>
                {sectionHeader('Household')}
                <div style={gridStyle}>
                  {[
                    {k:'healthcareFsa',label:'Healthcare FSA / HSA',prefix:'$'},
                    {k:'expectedRetirementRate',label:'Expected Retire Rate',suffix:'%'},
                  ].map(renderField)}
                </div>
              </div>
            </div>
          );
        })()}
      </div>

      <div className="grid-2" style={{marginBottom:16}}>
        <div className="card">
          <div style={{fontWeight:600,marginBottom:14}}>Tax Bracket Analysis — MFJ {TAX_YEAR}
            {tax.stale && <span style={{fontSize:10,color:'#f59e0b',marginLeft:8,padding:'2px 6px',background:'rgba(245,158,11,0.1)',border:'1px solid rgba(245,158,11,0.3)',borderRadius:4}}>no {tax.requestedYear} constants yet — showing {tax.year}</span>}
          </div>
          {MFJ.map((b,i)=>{
            const isA=b===curBracket;
            const fill=b.min>taxableIncome?0:Math.min(1,(Math.min(taxableIncome,b.max||taxableIncome)-b.min)/((b.max||taxableIncome+100000)-b.min));
            return(<div key={i} style={{marginBottom:6}}>
              <div style={{display:'flex',justifyContent:'space-between',fontSize:10,color:isA?b.color:'#64748b',marginBottom:2}}>
                <span style={{fontWeight:isA?700:400}}>{b.rate}%{isA?' ← you':''}</span>
                <span>{fmtCur(b.min)} – {b.max?fmtCur(b.max):'∞'}</span>
              </div>
              <div style={{height:6,background:'#1e2a3a',borderRadius:3,overflow:'hidden'}}>
                <div style={{width:(fill*100)+'%',height:'100%',background:b.color,opacity:isA?1:0.4,borderRadius:3}}/>
              </div>
            </div>);
          })}
          <div style={{paddingTop:8,borderTop:'1px solid #1e2a3a',fontSize:12,display:'flex',flexDirection:'column',gap:6}}>
            <div style={{display:'flex',justifyContent:'space-between'}}><span className="muted">Gross Income</span><strong>{fmtCur(grossIncome)}</strong></div>
            <div style={{display:'flex',justifyContent:'space-between',paddingLeft:12,fontSize:11,color:'#94a3b8'}}><span>– Standard Deduction (MFJ)</span><span>{fmtCur(STD_DED)}</span></div>
            <div style={{display:'flex',justifyContent:'space-between',paddingLeft:12,fontSize:11,color:'#94a3b8'}}><span>– 401(k) / 403(b)</span><span>{fmtCur(cfg.your401kContrib||0)}</span></div>
            {healthPreTaxAnnual>0 && <div style={{display:'flex',justifyContent:'space-between',paddingLeft:12,fontSize:11,color:'#94a3b8'}}><span>– Health insurance (payslip)</span><span>{fmtCur(healthPreTaxAnnual)}</span></div>}
            {otherPreTaxAnnual>0 && <div style={{display:'flex',justifyContent:'space-between',paddingLeft:12,fontSize:11,color:'#94a3b8'}}><span>– Other pre-tax (payslip)</span><span>{fmtCur(otherPreTaxAnnual)}</span></div>}
            {(cfg.dependentCareFsa||0)>0 && <div style={{display:'flex',justifyContent:'space-between',paddingLeft:12,fontSize:11,color:'#94a3b8'}}><span>– Dependent Care FSA</span><span>{fmtCur(cfg.dependentCareFsa)}</span></div>}
            {(cfg.healthcareFsa||0)>0 && <div style={{display:'flex',justifyContent:'space-between',paddingLeft:12,fontSize:11,color:'#94a3b8'}}><span>– Healthcare FSA / HSA</span><span>{fmtCur(cfg.healthcareFsa)}</span></div>}
            <div style={{display:'flex',justifyContent:'space-between'}}><span className="muted">Taxable Income</span><strong>{fmtCur(taxableIncome)}</strong></div>
            <div style={{display:'flex',justifyContent:'space-between'}}><span className="muted">Marginal Rate</span><strong style={{color:curBracket.color}}>{marginalRate}%</strong></div>
            <div style={{display:'flex',justifyContent:'space-between'}}><span className="muted">Effective Rate</span><strong>{effectiveRate.toFixed(1)}%</strong></div>
            {roomInBracket!=null&&<div style={{display:'flex',justifyContent:'space-between'}}><span className="muted">Room in bracket</span><strong style={{color:'#10b981'}}>{fmtCur(roomInBracket)}</strong></div>}
            {marginalRate < 32 && taxableIncome > 0 && (
              <div style={{marginTop:4,padding:'8px 10px',background:roomToBracketJump>20000?'rgba(16,185,129,0.08)':'rgba(245,158,11,0.12)',border:`1px solid ${roomToBracketJump>20000?'rgba(16,185,129,0.25)':'rgba(245,158,11,0.35)'}`,borderRadius:6,fontSize:11}}>
                <span style={{color:'#94a3b8'}}>Headroom before 32% bracket: </span>
                <strong style={{color:roomToBracketJump>20000?'#10b981':'#f59e0b'}}>{fmtCur(roomToBracketJump)}</strong>
              </div>
            )}
            {marginalRate >= 32 && (
              <div style={{marginTop:4,padding:'8px 10px',background:'rgba(239,68,68,0.12)',border:'1px solid rgba(239,68,68,0.35)',borderRadius:6,fontSize:11,color:'#fca5a5'}}>
                Over the 24%/32% bracket line by <strong>{fmtCur(taxableIncome - TWENTY_FOUR_CAP)}</strong>. Max pre-tax contributions (Trad 401(k), HSA, Dep Care FSA) to pull back under <strong>{fmtCur(TWENTY_FOUR_CAP)}</strong>.
              </div>
            )}
          </div>
        </div>

        <div className="card">
          <div style={{fontWeight:600,marginBottom:14}}>Traditional vs Roth 401(k)</div>
          <div style={{display:'flex',gap:8,marginBottom:16}}>
            <div style={{flex:1,background:rothRec?'#0d1117':'rgba(16,185,129,0.1)',border:rothRec?'1px solid #1e2a3a':'1px solid #10b981',borderRadius:8,padding:12,textAlign:'center'}}>
              <div style={{fontSize:11,color:'#64748b',marginBottom:4}}>TRADITIONAL</div>
              <div style={{fontSize:20,fontWeight:700,color:rothRec?'#64748b':'#10b981'}}>{marginalRate}%</div>
              <div style={{fontSize:10,color:'#64748b'}}>current marginal</div>
              {!rothRec&&<div style={{fontSize:10,color:'#10b981',marginTop:4,fontWeight:600}}>RECOMMENDED</div>}
            </div>
            <div style={{flex:1,background:rothRec?'rgba(59,130,246,0.1)':'#0d1117',border:rothRec?'1px solid #3b82f6':'1px solid #1e2a3a',borderRadius:8,padding:12,textAlign:'center'}}>
              <div style={{fontSize:11,color:'#64748b',marginBottom:4}}>ROTH</div>
              <div style={{fontSize:20,fontWeight:700,color:rothRec?'#3b82f6':'#64748b'}}>{expRetRate}%</div>
              <div style={{fontSize:10,color:'#64748b'}}>expected retire rate</div>
              {rothRec&&<div style={{fontSize:10,color:'#3b82f6',marginTop:4,fontWeight:600}}>RECOMMENDED</div>}
            </div>
          </div>
          <div style={{background:'#161b22',borderRadius:8,padding:12,fontSize:12,lineHeight:1.7}}>
            {rothRec
              ?<span>Retirement rate (<strong style={{color:'#3b82f6'}}>{expRetRate}%</strong>) exceeds marginal (<strong>{marginalRate}%</strong>). Pay taxes now — Roth advantage: <strong style={{color:'#10b981'}}>+{rothAdv}%</strong>.</span>
              :<span>Marginal rate (<strong style={{color:'#10b981'}}>{marginalRate}%</strong>) exceeds retirement (<strong>{expRetRate}%</strong>). Take deduction now — Traditional advantage: <strong style={{color:'#10b981'}}>+{Math.abs(rothAdv)}%</strong>.</span>
            }
          </div>
          <div style={{marginTop:12,padding:10,background:'rgba(59,130,246,0.08)',borderRadius:6,fontSize:11,color:'#94a3b8'}}>
            <strong style={{color:'#3b82f6'}}>Tax savings:</strong> Maxing Traditional saves <strong style={{color:'#e2e8f0'}}>{fmtCur((cfg.your401kContrib||0)*marginalRate/100)}</strong> in federal taxes this year.
          </div>
        </div>
      </div>
      <div className="grid-2" style={{marginBottom:16}}>
        <div className="card">
          <div style={{fontWeight:600,marginBottom:12}}>Backdoor Roth IRA</div>
          <div style={{display:'flex',alignItems:'center',gap:8,padding:'8px 12px',borderRadius:8,marginBottom:10,background:canDirectRoth?'rgba(16,185,129,0.1)':'rgba(245,158,11,0.1)',border:'1px solid '+(canDirectRoth?'#10b981':'#f59e0b')}}>
            <span style={{fontSize:16}}>{canDirectRoth?'✓':'⚡'}</span>
            <div>
              <div style={{fontSize:12,fontWeight:600,color:canDirectRoth?'#10b981':'#f59e0b'}}>{canDirectRoth?'Direct Roth eligible':'Use backdoor method'}</div>
              <div style={{fontSize:10,color:'#64748b'}}>MAGI {fmtCur(grossIncome)} vs limit {fmtCur(ROTH_START)}</div>
            </div>
          </div>
          {needsBackdoor?(
            <div style={{fontSize:12,lineHeight:1.8}}>
              <div style={{fontWeight:600,marginBottom:6,color:'#e2e8f0'}}>Backdoor Steps:</div>
              {['Contribute $'+iraLimit.toLocaleString()+' to your Traditional IRA (non-deductible)',
                'Contribute $'+wifeIraLimit.toLocaleString()+' to wife\'s Traditional IRA',
                'Wait 1-2 days, then convert both to Roth IRA',
                'File Form 8606 — tracks basis',
                'Beware pro-rata rule if you have pre-tax IRA money',
              ].map((s,i)=>(
                <div key={i} style={{display:'flex',gap:8,padding:'4px 0',borderBottom:'1px solid #1e2a3a'}}>
                  <span style={{color:'#10b981',fontWeight:700,minWidth:16}}>{i+1}.</span>
                  <span style={{color:'#94a3b8'}}>{s}</span>
                </div>
              ))}
              <div style={{marginTop:10,padding:'8px 10px',background:'rgba(16,185,129,0.08)',borderRadius:6,fontSize:11}}>
                Combined: <strong style={{color:'#10b981'}}>{fmtCur(iraLimit+wifeIraLimit)}/yr</strong> into Roth via backdoor
              </div>
            </div>
          ):(
            <div style={{fontSize:12,lineHeight:1.8,color:'#94a3b8'}}>
              <div>Direct Roth IRA contributions:</div>
              <div style={{marginTop:6}}>Your Roth IRA: up to <strong style={{color:'#e2e8f0'}}>{fmtCur(iraLimit)}/yr</strong></div>
              <div>Wife's Roth IRA: up to <strong style={{color:'#e2e8f0'}}>{fmtCur(wifeIraLimit)}/yr</strong></div>
              <div style={{marginTop:6,fontSize:11,color:'#64748b'}}>Switch to backdoor when income nears {fmtCur(ROTH_START)}</div>
            </div>
          )}
        </div>

        <div className="card">
          <div style={{fontWeight:600,marginBottom:12}}>Mega Backdoor Roth</div>
          <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:8,marginBottom:12}}>
            <div style={{background:'#161b22',borderRadius:6,padding:'8px 12px'}}>
              <div style={{fontSize:10,color:'#64748b',marginBottom:2}}>Total 401(k) limit</div>
              <div style={{fontWeight:700,color:'#e2e8f0'}}>{fmtCur(totalLimit)}</div>
            </div>
            <div style={{background:'#161b22',borderRadius:6,padding:'8px 12px'}}>
              <div style={{fontSize:10,color:'#64748b',marginBottom:2}}>Your employee contrib</div>
              <div style={{fontWeight:700,color:'#3b82f6'}}>{fmtCur(cfg.your401kContrib)}</div>
            </div>
            <div style={{background:'#161b22',borderRadius:6,padding:'8px 12px'}}>
              <div style={{fontSize:10,color:'#64748b',marginBottom:2}}>Employer contributions</div>
              <div style={{fontWeight:700,color:'#f59e0b'}}>{fmtCur(totalEmp)}</div>
            </div>
            <div style={{background:megaRoom>0?'rgba(16,185,129,0.1)':'rgba(100,116,139,0.1)',border:'1px solid '+(megaRoom>0?'#10b981':'#475569'),borderRadius:6,padding:'8px 12px'}}>
              <div style={{fontSize:10,color:'#64748b',marginBottom:2}}>After-tax room</div>
              <div style={{fontWeight:700,color:megaRoom>0?'#10b981':'#64748b'}}>{fmtCur(megaRoom)}</div>
            </div>
          </div>
          {megaRoom>0?(
            <div style={{fontSize:12,lineHeight:1.8,color:'#94a3b8'}}>
              <div style={{marginBottom:6}}>You have <strong style={{color:'#10b981'}}>{fmtCur(megaRoom)}</strong> in after-tax 401(k) capacity:</div>
              {['Contribute as after-tax (non-Roth) to 401(k)','Immediately convert to Roth in-plan','Check with HR that plan supports after-tax + in-plan conversions'].map((s,i)=>(
                <div key={i} style={{display:'flex',gap:8,padding:'3px 0'}}><span style={{color:'#10b981'}}>→</span><span>{s}</span></div>
              ))}
            </div>
          ):(
            <div style={{fontSize:12,color:'#64748b',padding:'8px 12px',background:'#161b22',borderRadius:6}}>
              Employer contributions fill remaining 401(k) space. No after-tax room this year.
            </div>
          )}
        </div>
      </div>
      <div className="card" style={{marginBottom:16}}>
        <div style={{fontWeight:600,marginBottom:14}}>Contribution Priority Waterfall</div>
        <div style={{display:'flex',flexDirection:'column',gap:2}}>
          {waterfall.map((w,i)=>(
            <div key={i} style={{display:'flex',alignItems:'center',gap:12,padding:'10px 12px',borderRadius:8,background:w.off?'transparent':w.done?'rgba(16,185,129,0.06)':'rgba(255,255,255,0.02)',border:'1px solid',borderColor:w.off?'#0d1117':w.done?'rgba(16,185,129,0.2)':'#1e2a3a',opacity:w.off?0.4:1}}>
              <div style={{width:22,height:22,borderRadius:'50%',background:w.off?'#1e2a3a':w.done?'#10b981':'#1e2a3a',display:'flex',alignItems:'center',justifyContent:'center',fontSize:10,fontWeight:700,color:w.done?'#fff':'#64748b',flexShrink:0}}>{w.done?'✓':w.p}</div>
              <div style={{flex:1,minWidth:0}}>
                <div style={{fontSize:12,fontWeight:600,color:w.off?'#475569':'#e2e8f0'}}>{w.name}</div>
                <div style={{fontSize:11,color:'#64748b'}}>{w.note}</div>
              </div>
              <div style={{textAlign:'right',flexShrink:0}}>
                {w.amt!=null?<div style={{fontSize:13,fontWeight:700,color:w.done?'#10b981':w.off?'#475569':'#e2e8f0'}}>{fmtCur(w.amt)}/yr</div>:<div style={{fontSize:11,color:'#64748b'}}>uncapped</div>}
              </div>
            </div>
          ))}
        </div>
        <div style={{marginTop:10,paddingTop:10,borderTop:'1px solid #1e2a3a',display:'flex',justifyContent:'space-between',fontSize:12}}>
          <span className="muted">Total tax-advantaged capacity</span>
          <strong style={{color:'#10b981'}}>{fmtCur(totalTaxAdv)}/yr</strong>
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div style={{fontWeight:600,marginBottom:14}}>Income Milestone Strategy Roadmap</div>
        <div style={{display:'flex',flexDirection:'column',gap:10}}>
          {milestones.map((m,i)=>(
            <div key={i} style={{borderRadius:8,border:'1px solid '+(m.active?m.color:'#1e2a3a'),background:m.active?m.color+'12':'transparent',padding:'12px 14px'}}>
              <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:m.active?10:6}}>
                {m.active&&<span style={{background:m.color,color:'#000',fontSize:9,fontWeight:800,padding:'2px 6px',borderRadius:3}}>CURRENT</span>}
                <span style={{fontWeight:600,color:m.active?m.color:'#64748b',fontSize:13}}>{m.label}</span>
                <span style={{fontSize:11,color:'#475569',marginLeft:'auto'}}>{m.range}</span>
              </div>
              {m.active?(
                <div style={{display:'flex',flexDirection:'column',gap:4}}>
                  {m.items.map((item,j)=>(<div key={j} style={{display:'flex',gap:8,fontSize:12,color:'#94a3b8'}}><span style={{color:m.color}}>→</span><span>{item}</span></div>))}
                </div>
              ):(
                <div style={{fontSize:11,color:'#475569'}}>{m.items[0]}{m.items.length>1?' + '+(m.items.length-1)+' more':''}</div>
              )}
            </div>
          ))}
        </div>
      </div>

      {/* ── Tax Optimization ─────────────────────────────────────────────── */}
      <div className="card" style={{marginBottom:16}}>
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',flexWrap:'wrap',gap:10,marginBottom:14}}>
          <div>
            <div style={{fontWeight:600,fontSize:14}}>Tax Optimization</div>
            <div style={{fontSize:11,color:'#64748b',marginTop:2}}>Full-picture analysis with 5-year forward projection — skips anything you're already doing</div>
          </div>
          <button className="btn-primary" onClick={handleGenerateTaxOpt} disabled={loadingTaxOpt} style={{padding:'8px 16px'}}>
            {loadingTaxOpt?<span className="spinner"/>:'Generate Suggestions'}
          </button>
        </div>

        <div style={{marginBottom:14}}>
          <div className="label" style={{fontSize:11,marginBottom:8}}>What we already use (tick all that apply — the AI will build on these, not repeat them)</div>
          <div style={{display:'flex',flexWrap:'wrap',gap:8}}>
            {CURRENTLY_USING_OPTIONS.map(({k,label})=>(
              <label key={k} style={{display:'flex',alignItems:'center',gap:6,fontSize:11,padding:'5px 10px',background:currentlyUsing[k]?'rgba(59,130,246,0.15)':'#161b22',border:`1px solid ${currentlyUsing[k]?'rgba(59,130,246,0.4)':'#1e2a3a'}`,borderRadius:6,cursor:'pointer',color:currentlyUsing[k]?'#3b82f6':'#94a3b8'}}>
                <input type="checkbox" checked={!!currentlyUsing[k]} onChange={e=>setCurrentlyUsing(s=>({...s,[k]:e.target.checked}))} style={{margin:0}}/>
                {label}
              </label>
            ))}
          </div>
        </div>

        {incomeProjection.length>0 && (
          <div style={{marginBottom:14,padding:10,background:'#0f1520',border:'1px solid #1e2a3a',borderRadius:6,fontSize:11}}>
            <div style={{color:'#64748b',marginBottom:6,fontWeight:600}}>Forward income projection (household gross, for AI context)</div>
            <div style={{display:'flex',gap:14,flexWrap:'wrap'}}>
              {incomeProjection.map(p=>(
                <div key={p.year}><span style={{color:'#64748b'}}>{p.year}:</span> <strong style={{color:'#e2e8f0'}}>{fmtCur(p.gross)}</strong></div>
              ))}
            </div>
          </div>
        )}

        {taxOpt?(
          <MarkdownView text={taxOpt} />
        ):(
          <div style={{padding:'24px 20px',textAlign:'center',color:'#475569',fontSize:12}}>
            Click "Generate Suggestions" for dollar-quantified tax moves tailored to your exact pre-tax deductions, bracket position, and projected income.
          </div>
        )}
      </div>

      <div className="card">
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:12}}>
          <div>
            <div style={{fontWeight:600,fontSize:14}}>AI Strategy Analysis</div>
            <div style={{fontSize:11,color:'#64748b',marginTop:2}}>Powered by Claude — personalized to your household</div>
          </div>
          <button className="btn-primary" onClick={handleGenerate} disabled={loadingInsights} style={{padding:'8px 16px'}}>
            {loadingInsights?<span className="spinner"/>:'Generate Analysis'}
          </button>
        </div>
        {insights?(
          <MarkdownView text={insights} />
        ):(
          <div style={{padding:'32px 20px',textAlign:'center',color:'#475569',fontSize:12}}>
            Click "Generate Analysis" for a personalized strategy based on your tax situation, accounts, and retirement goals.
          </div>
        )}
      </div>
    </div>
  );
}

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