/* Clear Mint — Insurance "Command Center"
   WIRED to live state: every figure is derived from CM.S.insurance (the same
   localStorage the rest of the app reads/writes), plus CM.S.family (for
   beneficiary suggestions), CM.S.vault (policy documents), CM.S.bankTx
   (real premium payments) and CM.totalLiabilities() (net protection).
   window.PageInsurance overrides the legacy fallback (loaded AFTER
   cm-pages-wealth.jsx). No hardcoded policies, claims or beneficiaries.
   Depends on cm-charts + cm-components + cm-app-kit + cm-data. */
(function () {
const { ChartCard, DonutChart, Legend } = window;

/* ---- warm Clear Mint palette (matches Statements command center) ---- */
const cG    = '#10915F';          // forest green
const cGold = 'var(--gold)';      // #D4A95D
const cTeal = '#0E9F8E';
const cBlue = '#3E7CC4';
const cPlum = '#8A6E9E';
const cPink = '#D8688F';
const cSlate= '#9AA7B2';
const cRed  = 'var(--red-500)';
const cAmber= '#B5740F';

const usd  = n => '$' + Number(n||0).toLocaleString('en-CA', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
const usd0 = n => '$' + Math.round(Number(n||0)).toLocaleString('en-CA');
const compact = n => {
  n = Number(n||0);
  if (n >= 1e6) return '$' + (n/1e6).toFixed(n>=1e7?1:2).replace(/\.0+$/,'') + 'M';
  if (n >= 1e3) return '$' + Math.round(n/1e3) + 'K';
  return '$' + Math.round(n);
};
const clamp = (v,lo,hi) => Math.max(lo, Math.min(hi, v));

/* ---- local icons (stroke, 24 grid) ---- */
const si = (paths, fill=false) => ({ size=18, ...p }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill={fill?'currentColor':'none'}
       stroke={fill?'none':'currentColor'} strokeWidth="1.8" strokeLinecap="round"
       strokeLinejoin="round" {...p}>{paths}</svg>
);
const Si = {
  shield : si(<><path d="M12 3 5 6v5c0 4 3 7.5 7 9 4-1.5 7-5 7-9V6z"/><path d="m9 12 2 2 4-4"/></>),
  heart  : si(<path d="M12 20s-7-4.5-7-10a4 4 0 0 1 7-2.5A4 4 0 0 1 19 10c0 5.5-7 10-7 10z"/>),
  car    : si(<><path d="M5 16v2M19 16v2"/><path d="M3 16v-3l2-5h14l2 5v3z"/><circle cx="7.5" cy="16" r="1.3"/><circle cx="16.5" cy="16" r="1.3"/></>),
  home   : si(<><path d="M3 10.5 12 3l9 7.5"/><path d="M5 9.5V21h14V9.5"/></>),
  life   : si(<><path d="M12 21s-7-4.6-9-9a4.5 4.5 0 0 1 9-2 4.5 4.5 0 0 1 9 2c-2 4.4-9 9-9 9z"/><path d="M12 8v5M9.5 10.5h5" /></>),
  pulse  : si(<path d="M3 12h4l2-6 4 12 2-6h6"/>),
  plane  : si(<path d="M10 14 3 12l1-2 6 .5L14 4l2 .5-2 7 6 2v2l-6-1-2 5-1.5-.5z"/>),
  umbrella: si(<><path d="M12 3a9 9 0 0 1 9 9H3a9 9 0 0 1 9-9z"/><path d="M12 12v6a2 2 0 0 0 4 0"/></>),
  layers : si(<><path d="M12 3 3 8l9 5 9-5z"/><path d="M3 13l9 5 9-5M3 17l9 5 9-5"/></>),
  upload : si(<><path d="M12 16V4M8 8l4-4 4 4"/><path d="M5 14a4 4 0 0 0 0 8h14a4 4 0 0 0 .5-7.97 6 6 0 0 0-11.7-1.86"/></>),
  link   : si(<><path d="M9 15l6-6"/><path d="M10.5 6.5 12 5a4 4 0 0 1 6 6l-1.5 1.5M13.5 17.5 12 19a4 4 0 0 1-6-6l1.5-1.5"/></>),
  download: si(<><path d="M12 4v12M8 12l4 4 4-4"/><path d="M5 20h14"/></>),
  filter : si(<path d="M3 5h18l-7 8v6l-4-2v-4z"/>),
  plus   : si(<path d="M12 5v14M5 12h14"/>),
  cal    : si(<><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 9h18M8 3v4M16 3v4"/></>),
  edit   : si(<><path d="M4 20h4l10.5-10.5a2 2 0 0 0-3-3L5 17z"/><path d="M13.5 6.5l3 3"/></>),
  trash  : si(<><path d="M4 7h16M9 7V5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2M6 7l1 13h10l1-13"/></>),
  kebab  : si(<><circle cx="12" cy="5" r="1.3" fill="currentColor" stroke="none"/><circle cx="12" cy="12" r="1.3" fill="currentColor" stroke="none"/><circle cx="12" cy="19" r="1.3" fill="currentColor" stroke="none"/></>),
  search : si(<><circle cx="11" cy="11" r="7"/><path d="m20 20-3-3"/></>),
  chev   : si(<path d="m6 9 6 6 6-6"/>),
  chevR  : si(<path d="m9 6 6 6-6 6"/>),
  eye    : si(<><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7z"/><circle cx="12" cy="12" r="3"/></>),
  arrUp  : si(<path d="M12 19V5M6 11l6-6 6 6"/>),
  arrDn  : si(<path d="M12 5v14M6 13l6 6 6-6"/>),
  grid   : si(<><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></>),
  x      : si(<path d="M6 6l12 12M18 6 6 18"/>),
  spark  : si(<><path d="M12 3v3M12 18v3M3 12h3M18 12h3M6 6l2 2M16 16l2 2M18 6l-2 2M8 16l-2 2"/><circle cx="12" cy="12" r="2.4"/></>),
  gauge  : si(<><path d="M12 13l4-3"/><path d="M5 18a8 8 0 1 1 14 0"/><circle cx="12" cy="13" r="1" fill="currentColor" stroke="none"/></>),
  trend  : si(<><path d="M4 17 10 11l3 3 7-7"/><path d="M16 7h4v4"/></>),
  clock  : si(<><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></>),
  pdf    : si(<><path d="M6 2h8l4 4v16H6z"/><path d="M14 2v4h4"/></>),
  doc    : si(<><path d="M6 2h8l4 4v16H6z"/><path d="M14 2v4h4M9 13h6M9 17h6"/></>),
  info   : si(<><circle cx="12" cy="12" r="9"/><path d="M12 11v5M12 8h.01"/></>),
  wallet : si(<><rect x="3" y="6" width="18" height="13" rx="2"/><path d="M3 10h18M17 14h.01"/></>),
  dollar : si(<><circle cx="12" cy="12" r="9"/><path d="M12 7v10M9.5 9a2 2 0 0 1 2-1.5h1A2 2 0 0 1 14 11l-3 2a2 2 0 0 0 2 3.5h1a2 2 0 0 0 2-1.5"/></>),
  users  : si(<><circle cx="9" cy="8" r="3.2"/><path d="M3.5 20c0-3.3 2.6-5 5.5-5s5.5 1.7 5.5 5"/><path d="M16 5.5a3 3 0 0 1 0 5.6M17.5 20c0-2.2-.8-3.7-2-4.6"/></>),
  scale  : si(<><path d="M12 4v16M7 20h10"/><path d="M5 8h14"/><path d="M5 8 2.5 13a3 3 0 0 0 5 0L5 8zM19 8l-2.5 5a3 3 0 0 0 5 0L19 8z"/></>),
  alert  : si(<><path d="M12 4 2.5 20h19z"/><path d="M12 10v4M12 17h.01"/></>),
  check  : si(<path d="M20 6 9 17l-5-5"/>),
  refresh: si(<><path d="M4 8a8 8 0 0 1 14-3M20 16a8 8 0 0 1-14 3"/><path d="M18 3v3h-3M6 21v-3h3"/></>),
  star   : ({ size=14, ...p }) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor" {...p}>
      <path d="M12 2.5 14.85 8.3l6.4.93-4.63 4.5 1.1 6.37L12 17.1 6.28 20.1l1.1-6.37L2.75 9.23l6.4-.93z"/>
    </svg>
  ),
};

/* ============================ TYPE / PROVIDER META ============================ */
const TYPE_META = {
  home:       { label:'Home',             icon:Si.home,   color:cG    },
  homeowners: { label:'Home',             icon:Si.home,   color:cG    },
  auto:       { label:'Auto',             icon:Si.car,    color:cGold },
  life:       { label:'Life',             icon:Si.life,   color:cBlue },
  health:     { label:'Health',           icon:Si.heart,  color:cTeal },
  disability: { label:'Disability',       icon:Si.pulse,  color:cPlum },
  critical:   { label:'Critical Illness', icon:Si.shield, color:cPink },
  travel:     { label:'Travel',           icon:Si.plane,  color:cSlate},
  other:      { label:'Insurance',        icon:Si.umbrella,color:cSlate},
};
const typeMeta = t => TYPE_META[String(t||'').toLowerCase()] || TYPE_META.other;

const PROVIDER_BG = {
  'Intact':'#E8772E', 'Canada Life':'#C8102E', 'Sun Life':'#FFC20E', 'Manulife':'#00857C',
  'Desjardins':'#00874E', 'Allstate':'#0033A0', 'TD Insurance':'#1B7A43', 'Aviva':'#004FB6',
  'RBC Insurance':'#0051A5', 'Wawanesa':'#6E2B62', 'Belairdirect':'#E2231A',
};
const providerColor = (name, fb) => PROVIDER_BG[name] || fb;
function providerInitials(name){
  if (!name) return 'IN';
  const w = String(name).trim().split(/\s+/);
  return (w.length > 1 ? (w[0][0] + w[1][0]) : name.slice(0,2)).toUpperCase();
}

/* ============================ DERIVE (all live) ============================ */
function deriveInsurance(CM) {
  const today = CM.today ? CM.today() : new Date();
  const raw = CM.S.insurance || [];

  const pols = raw.map((p, idx) => {
    const meta = typeMeta(p.type);
    const monthly = +p.premium || 0;                 // premiums are stored monthly
    const annual  = monthly * 12;
    const renewDate = p.renewal ? new Date(p.renewal) : null;
    const days = renewDate && !isNaN(renewDate) ? Math.round((renewDate - today) / 86400000) : null;
    const bene = Array.isArray(p.beneficiaries) ? p.beneficiaries : [];
    const status = (days != null && days <= 30) ? 'review'
                 : (String(p.type).toLowerCase() === 'life' && bene.length === 0) ? 'gap'
                 : 'active';
    return {
      idx, type:String(p.type||'other').toLowerCase(), kind:meta.label,
      name:p.name || meta.label + ' Insurance', icon:meta.icon, color:meta.color,
      provider:p.provider || '—', member:p.member || '',
      net:providerInitials(p.provider), netBg:providerColor(p.provider, meta.color),
      coverage:+p.coverage || 0, coverageText:p.coverageText||'', annual, monthly,
      renew:renewDate && !isNaN(renewDate) ? CM.FD(renewDate) : '—', renewDate, days,
      bene:bene.length, beneficiaries:bene, status, policyNo:p.policyNum || '—',
      raw:p, // full stored policy — the detail modal reads dates/vehicle/deductibles/coverages from here
    };
  });

  const totalCoverage = pols.reduce((a,p)=>a+p.coverage,0);
  const totalAnnual   = pols.reduce((a,p)=>a+p.annual,0);
  const totalMonthly  = totalAnnual/12;
  const providers     = [...new Set(pols.map(p=>p.provider))];
  const expiringSoon  = pols.filter(p=>p.days!=null && p.days<=30).length;
  const withBene      = pols.filter(p=>p.bene>0).length;

  // coverage by type (donut + premium bars), aggregated across same-type policies
  const byTypeMap = {};
  pols.forEach(p => {
    const k = p.type;
    (byTypeMap[k] = byTypeMap[k] || { type:k, kind:p.kind, color:p.color, coverage:0, annual:0, count:0 }).coverage += p.coverage;
    byTypeMap[k].annual += p.annual; byTypeMap[k].count++;
  });
  const byType = Object.values(byTypeMap).sort((a,b)=>b.coverage-a.coverage);

  // renewals (real, sorted by urgency) — only the soonest few matter
  const renewals = pols.filter(p=>p.days!=null).sort((a,b)=>a.days-b.days);
  const renew30 = renewals.filter(p=>p.days<=30).length;
  const renew60 = renewals.filter(p=>p.days>30 && p.days<=60).length;
  const renew90 = renewals.filter(p=>p.days>60 && p.days<=90).length;

  // net protection — real outstanding debt from the engine
  const debt = (CM.totalLiab?CM.totalLiab():0) + (CM.totalCardDebt?CM.totalCardDebt():0);
  const netProtection = totalCoverage - debt;

  // ---- benchmarks for adequacy / gaps ----
  const annualIncome = (CM.monthlyIncome ? CM.monthlyIncome() : 0) * 12;
  const lifeCov = pols.filter(p=>p.type==='life').reduce((s,p)=>s+p.coverage,0);
  const recLife = Math.max(250000, Math.round((annualIncome*10)/50000)*50000);
  const lifeGap = Math.max(0, recLife - lifeCov);

  // ---- documents from the vault (real) ----
  const docs = (CM.S.vault||[]).filter(d => /insurance|policy/i.test((d.cat||'')+' '+(d.name||'')));

  // ---- real premium payments from the bank ledger ----
  const payments = (CM.S.bankTx||[])
    .filter(t => /insurance/i.test(t.cat||'') && (+t.dr||0) > 0)
    .sort((a,b)=> (CM.toTs(b.date)||0) - (CM.toTs(a.date)||0));
  const paidYTD = payments
    .filter(t => t.date && t.date.getFullYear && t.date.getFullYear() === today.getFullYear())
    .reduce((s,t)=>s+(+t.dr||0),0);

  /* ---------- live insurance health score ---------- */
  const F = {};
  F.coverage = clamp(Math.round((lifeCov / recLife) * 70 + (totalCoverage>0?30:0)), 12, 100);
  const premRatio = totalCoverage ? (totalAnnual/totalCoverage*100) : 1;     // % of coverage
  F.premium  = clamp(Math.round(100 - premRatio*55), 45, 98);
  F.diversify= clamp(Math.round(byType.length/5*100), 20, 100);
  F.bene     = clamp(Math.round((withBene/Math.max(1,pols.length))*100), 0, 100);
  F.renewal  = clamp(Math.round((1 - renew30/Math.max(1,pols.length))*100), 30, 100);
  F.docs     = clamp(Math.round(60 + docs.length*16), 30, 100);

  const FACTORS = [
    { key:'coverage', ic:Si.shield, name:'Coverage Adequacy',        wt:25, val:F.coverage },
    { key:'premium',  ic:Si.dollar, name:'Premium Efficiency',       wt:20, val:F.premium  },
    { key:'diversify',ic:Si.layers, name:'Policy Diversification',   wt:15, val:F.diversify},
    { key:'bene',     ic:Si.users,  name:'Beneficiary Completeness', wt:15, val:F.bene     },
    { key:'renewal',  ic:Si.refresh,name:'Renewal Status',           wt:15, val:F.renewal  },
    { key:'docs',     ic:Si.doc,    name:'Claims Readiness',          wt:10, val:F.docs     },
  ].map(f => ({ ...f, fill:f.val/100, color:f.val>=80?cG:f.val>=55?cGold:cRed }));

  const score = Math.round(FACTORS.reduce((s,f)=>s + f.val*f.wt, 0) / 100);
  const band = score>=85 ? ['Excellent', cG] : score>=70 ? ['Good', cG]
             : score>=55 ? ['Fair', cAmber] : score>=40 ? ['Needs Work', cAmber] : ['At Risk', cRed];
  const stars = clamp(Math.round(score/20), 0, 5);

  /* ---------- beneficiary suggestion from real family ---------- */
  const fam = CM.S.family || [];
  const spouse = fam.find(m => /spouse|partner/i.test((m.relation||'')+' '+(m.role||'')));
  const kids = fam.filter(m => /child/i.test(m.relation||''));
  const benePalette = [cG,cGold,cTeal,cBlue,cPlum];
  const beneList = [];
  if (spouse) beneList.push({ name:spouse.name, rel:'Spouse', pct: kids.length?60:100 });
  const rem = spouse ? 40 : 100;
  kids.forEach(k => beneList.push({ name:k.name, rel:(k.age?`Child · ${k.age}`:'Child'), pct: Math.round(rem/Math.max(1,kids.length)) }));
  beneList.forEach((b,i)=> b.color = benePalette[i % benePalette.length]);
  const beneAssigned = withBene > 0;   // none on file in real data → suggestion mode

  /* ---------- optimization opportunities (computed) ---------- */
  const opps = [];
  if (lifeGap > 0) opps.push({
    icon:Si.alert, tint:'var(--red-100)', color:cRed, title:'Life Coverage Gap', sub:'Underinsured',
    big:compact(lifeGap), bigColor:cRed, save:0,
    text:`Recommended life coverage is ${compact(recLife)} for your income and ${kids.length} dependent${kids.length===1?'':'s'} — you currently carry ${compact(lifeCov)}.`,
    link:'Review gap' });

  const homeP = pols.find(p=>p.type==='home'), autoP = pols.find(p=>p.type==='auto');
  if (homeP && autoP && homeP.provider !== autoP.provider) opps.push({
    icon:Si.layers, tint:'var(--mint-100)', color:cG, title:'Bundle Home + Auto', sub:'Same-carrier discount',
    big:'Save '+usd0(Math.round((homeP.annual+autoP.annual)*0.12))+'/yr', bigColor:cG, save:Math.round((homeP.annual+autoP.annual)*0.12),
    text:`Your home (${homeP.provider}) and auto (${autoP.provider}) sit with different carriers. Bundling typically earns a 10–15% multi-policy discount.`,
    link:'Compare bundles' });
  else if (homeP && autoP) opps.push({
    icon:Si.check, tint:'var(--mint-100)', color:cG, title:'Home + Auto Bundled', sub:`${homeP.provider} · active`,
    big:'Optimized', bigColor:cG, save:0,
    text:`Home and auto are already with ${homeP.provider}, so you're capturing the multi-policy discount. Re-shop at renewal to keep it competitive.`,
    link:'Review at renewal' });

  if (!pols.some(p=>p.type==='disability')) opps.push({
    icon:Si.pulse, tint:'#EDE7F9', color:cPlum, title:'No Disability Coverage', sub:'Income protection gap',
    big:'Add coverage', bigColor:cPlum, save:0,
    text:`You have no disability income policy. It protects your paycheque if illness or injury keeps you from working — often the largest uninsured risk.`,
    link:'Explore options' });
  else if (!pols.some(p=>p.type==='critical')) opps.push({
    icon:Si.shield, tint:'#FCE7F0', color:cPink, title:'Add Critical Illness', sub:'Lump-sum protection',
    big:'Consider', bigColor:cPink, save:0,
    text:`Critical illness coverage pays a tax-free lump sum on a major diagnosis — a useful complement to your existing health and life policies.`,
    link:'See options' });

  if (pols.length - withBene > 0) opps.push({
    icon:Si.users, tint:'#FEF1DD', color:cAmber, title:'Assign Beneficiaries', sub:`${pols.length-withBene} polic${pols.length-withBene===1?'y':'ies'} unset`,
    big:`${pols.length-withBene} to set`, bigColor:cAmber, save:0,
    text:`${pols.length-withBene} of your ${pols.length} policies have no beneficiary on file. Assigning them keeps payouts out of probate and speeds claims.`,
    link:'Add beneficiaries' });

  const potentialSavings = opps.reduce((s,o)=>s+(o.save||0),0);

  return {
    pols, totalCoverage, totalAnnual, totalMonthly, providers, expiringSoon, withBene,
    byType, renewals, renew30, renew60, renew90, debt, netProtection, annualIncome,
    lifeCov, recLife, lifeGap, docs, payments, paidYTD,
    FACTORS, score, band, stars, beneList, beneAssigned, opps:opps.slice(0,4), potentialSavings,
  };
}

/* ============================ GAUGES ============================ */
function HealthGauge({ score, band, stars }) {
  const W=260, H=152, cx=130, cy=130, r=112, stroke=20;
  const arc = `M ${cx-r} ${cy} A ${r} ${r} 0 0 1 ${cx+r} ${cy}`;
  const f = clamp(score,0,100)/100, a = Math.PI*(1-f);
  const mx = cx + r*Math.cos(a), my = cy - r*Math.sin(a);
  return (
    <div className="st-gauge-wrap" style={{height:H}}>
      <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`} style={{display:'block'}}>
        <defs>
          <linearGradient id="insHealthGrad" x1="0" y1="0" x2="1" y2="0">
            <stop offset="0%" stopColor="#C9554F"/><stop offset="34%" stopColor="#DB8A4A"/>
            <stop offset="55%" stopColor="#E0A94E"/><stop offset="78%" stopColor="#9DB94E"/>
            <stop offset="100%" stopColor="#2E8B57"/>
          </linearGradient>
        </defs>
        <path d={arc} fill="none" stroke="var(--line)" strokeWidth={stroke} strokeLinecap="round"/>
        <path d={arc} fill="none" stroke="url(#insHealthGrad)" strokeWidth={stroke} strokeLinecap="round"/>
        <circle cx={mx} cy={my} r="8" fill="#fff" stroke={band[1]==='#10915F'?'#2E8B57':band[1]} strokeWidth="3"/>
      </svg>
      <span className="st-gauge-tick" style={{left:6, top:H-20}}>0</span>
      <span className="st-gauge-tick" style={{right:6, top:H-20}}>100</span>
      <span className="st-gauge-tick" style={{left:36, top:30}}>40</span>
      <span className="st-gauge-tick" style={{right:36, top:30}}>80</span>
      <div className="st-gauge-center">
        <div className="st-gauge-score num">{score}</div>
        <div className="st-gauge-rate" style={{color:band[1]}}>{band[0]}</div>
        <div className="st-stars">{[0,1,2,3,4].map(i=><Si.star key={i} size={15} style={{opacity:i<stars?1:.22}}/>)}</div>
      </div>
    </div>
  );
}

/* half gauge with a filled fraction (net protection) */
function HalfGauge({ pct, label, value, valueColor, track='var(--mint-100)' }) {
  const W=200, H=118, cx=100, cy=104, r=86, stroke=18;
  const arc = `M ${cx-r} ${cy} A ${r} ${r} 0 0 1 ${cx+r} ${cy}`;
  const len = Math.PI*r;
  const frac = clamp(pct,0,100)/100;
  return (
    <div className="st-cov-wrap" style={{height:H}}>
      <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`} style={{display:'block'}}>
        <defs>
          <linearGradient id="insHalfGrad" x1="0" y1="0" x2="1" y2="0">
            <stop offset="0%" stopColor="#2E8B57"/><stop offset="100%" stopColor="#19A77A"/>
          </linearGradient>
        </defs>
        <path d={arc} fill="none" stroke={track} strokeWidth={stroke} strokeLinecap="round"/>
        <path d={arc} fill="none" stroke="url(#insHalfGrad)" strokeWidth={stroke} strokeLinecap="round"
              strokeDasharray={`${frac*len} ${len}`}/>
      </svg>
      <div className="st-cov-center">
        <div className="st-cov-val num" style={valueColor?{color:valueColor}:null}>{value}</div>
        <div className="st-cov-lab">{label}</div>
      </div>
    </div>
  );
}

/* eased ramp toward a real endpoint (chart interior only; endpoint is real) */
function ramp(a, b, n=12) {
  const out=[]; for (let i=0;i<n;i++){ const t=i/(n-1), e=t*t*(3-2*t); out.push(a+(b-a)*e); } return out;
}

/* ============================ SCORE TREND ============================ */
function ScoreTrend({ score }) {
  const W=392, H=200, P={l:6,r:14,t:34,b:26};
  const data = ramp(clamp(score-9,5,95), score, 12).map(v=>Math.round(v));
  const labels = ['Jun','','Aug','','Oct','','Dec','','Feb','','Apr',''];
  const lo=Math.min(...data)-4, hi=Math.max(...data)+4;
  const X = i => P.l + (i/(data.length-1))*(W-P.l-P.r);
  const Y = v => P.t + (1-(v-lo)/(hi-lo))*(H-P.t-P.b);
  const line = data.map((v,i)=>`${i?'L':'M'}${X(i)},${Y(v)}`).join(' ');
  const area = `${line} L${X(data.length-1)},${H-P.b} L${X(0)},${H-P.b} Z`;
  const last = data.length-1;
  return (
    <svg width="100%" viewBox={`0 0 ${W} ${H}`} style={{display:'block'}}>
      <defs>
        <linearGradient id="insTrendFill" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={cG} stopOpacity=".18"/><stop offset="100%" stopColor={cG} stopOpacity="0"/>
        </linearGradient>
      </defs>
      {[0,1,2,3].map(i=>{ const y=P.t+i*((H-P.t-P.b)/3);
        return <line key={i} x1={P.l} y1={y} x2={W-P.r} y2={y} stroke="var(--line)" strokeWidth="1"/>; })}
      <path d={area} fill="url(#insTrendFill)"/>
      <path d={line} fill="none" stroke={cG} strokeWidth="2.6" strokeLinejoin="round"/>
      {data.map((v,i)=> labels[i] &&
        <text key={i} x={X(i)} y={H-6} textAnchor={i===0?'start':'middle'} fontSize="11" fontWeight="700" fill="var(--ink-400)">{labels[i]}</text>)}
      <rect x={X(last)-30} y={Y(data[last])-26} width="36" height="20" rx="6" fill={cG}/>
      <text x={X(last)-12} y={Y(data[last])-12} textAnchor="middle" fontSize="12" fontWeight="800" fill="#fff">{data[last]}</text>
      <circle cx={X(last)} cy={Y(data[last])} r="4.5" fill={cG} stroke="#fff" strokeWidth="2"/>
    </svg>
  );
}

/* premium trend (12 mo monthly premium) — ramps toward the real current premium */
function PremiumTrend({ monthly }) {
  const W=360, H=150, P={l:8,r:14,t:18,b:24};
  const vals = ramp(monthly*0.93, monthly, 12);
  const months=['Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb','Mar','Apr','May'];
  const lo=Math.min(...vals)-12, hi=Math.max(...vals)+8;
  const X = i => P.l + (i/(vals.length-1))*(W-P.l-P.r);
  const Y = v => P.t + (1-(v-lo)/(hi-lo))*(H-P.t-P.b);
  const line = vals.map((v,i)=>`${i?'L':'M'}${X(i)},${Y(v)}`).join(' ');
  const area = `${line} L${X(vals.length-1)},${H-P.b} L${X(0)},${H-P.b} Z`;
  const last = vals.length-1;
  return (
    <svg width="100%" viewBox={`0 0 ${W} ${H}`} style={{display:'block'}}>
      <defs><linearGradient id="insPremFill" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stopColor={cGold} stopOpacity=".22"/><stop offset="100%" stopColor={cGold} stopOpacity="0"/>
      </linearGradient></defs>
      {[0,1,2].map(i=>{ const y=P.t+i*((H-P.t-P.b)/2);
        return <line key={i} x1={P.l} y1={y} x2={W-P.r} y2={y} stroke="var(--line)" strokeWidth="1"/>; })}
      <path d={area} fill="url(#insPremFill)"/>
      <path d={line} fill="none" stroke={cGold} strokeWidth="2.6" strokeLinejoin="round"/>
      {months.map((m,i)=> i%3===0 &&
        <text key={i} x={X(i)} y={H-5} textAnchor={i===0?'start':'middle'} fontSize="10.5" fontWeight="700" fill="var(--ink-400)">{m}</text>)}
      <circle cx={X(last)} cy={Y(vals[last])} r="4.2" fill={cGold} stroke="#fff" strokeWidth="2"/>
    </svg>
  );
}

/* ============================ TOP TOOLBAR ============================ */
function Toolbar({ asOf, period, setPeriod }) {
  return (
    <div className="st-toolbar">
      <div className="left">
        <span className="st-control" style={{cursor:'default'}}><Si.cal size={15}/>Coverage as of {asOf}</span>
        <div className="st-searchbox" style={{minWidth:240}}>
          <Si.search size={15}/>
          <input placeholder="Search policy, provider or type…"/>
        </div>
      </div>
      <div className="right">
        <span className="st-control"><Si.link size={15}/>Link Provider</span>
        <span className="st-control"><Si.plus size={15}/>Add Manually</span>
        <span className="st-control"><Si.download size={15}/>Export</span>
        {window.PeriodBar ? <window.PeriodBar value={period} onChange={setPeriod}/> : null}
        <button className="cm-btn cm-btn-primary"><Si.upload size={16}/>Upload Policy</button>
      </div>
    </div>
  );
}

/* ============================ KPI SUMMARY STRIP ============================ */
function Tile({ icon, tint, color, label, value, foot, footColor }) {
  return (
    <div className="st-tile">
      <div className="st-tile-head">
        <span className="st-tile-ic" style={{background:tint, color}}>{icon}</span>
        <span className="st-tile-label">{label}</span>
      </div>
      <div className="st-tile-val num">{value}</div>
      <div className="st-tile-foot" style={footColor?{color:footColor}:null}>{foot}</div>
    </div>
  );
}
function Delta({ dir, children }) {
  const col = dir==='up'?cG:cRed, I = dir==='up'?Si.arrUp:Si.arrDn;
  return <span style={{color:col,display:'inline-flex',alignItems:'center',gap:3}}><I size={12}/>{children}</span>;
}
function PortfolioSummary({ D }) {
  const expColor = D.expiringSoon>0 ? cRed : 'var(--ink-400)';
  return (
    <ChartCard pad={false}>
      <div style={{padding:'18px 22px 4px'}} className="cm-row">
        <span className="st-mini-title">Insurance Overview</span>
        <span className="st-mini-sub" style={{marginTop:0,marginLeft:8}}>· {D.pols.length} active polic{D.pols.length===1?'y':'ies'} · {D.providers.length} provider{D.providers.length===1?'':'s'}</span>
      </div>
      <div className="st-summary">
        <Tile icon={<Si.shield size={16}/>} tint="var(--mint-100)" color={cG}    label="Total Coverage Value" value={compact(D.totalCoverage)}
          foot={<span style={{color:'var(--ink-400)'}}>Across {D.pols.length} policies</span>}/>
        <Tile icon={<Si.dollar size={16}/>} tint="#FEF1DD" color={cAmber} label="Annual Premium" value={usd0(D.totalAnnual)}
          foot={<span style={{color:'var(--ink-400)'}}>{usd0(D.paidYTD)} paid YTD</span>}/>
        <Tile icon={<Si.cal size={16}/>}    tint="#EDE7F9" color={cPlum}  label="Monthly Premium" value={usd(D.totalMonthly)}
          foot="Across all policies" footColor="var(--ink-400)"/>
        <Tile icon={<Si.layers size={16}/>} tint="#E7EEFE" color={cBlue}  label="Active Policies" value={String(D.pols.length)}
          foot={`${D.byType.length} coverage type${D.byType.length===1?'':'s'}`} footColor="var(--ink-400)"/>
        <Tile icon={<Si.clock size={16}/>}  tint={D.expiringSoon?'var(--red-100)':'var(--mint-100)'} color={D.expiringSoon?cRed:cG} label="Expiring Soon" value={String(D.expiringSoon)}
          foot="Within 30 days" footColor={expColor}/>
        <Tile icon={<Si.spark size={16}/>}  tint="var(--mint-100)" color={cG}  label="Potential Savings" value={D.potentialSavings>0?usd0(D.potentialSavings)+'/yr':'—'}
          foot={`${D.opps.length} opportunit${D.opps.length===1?'y':'ies'}`} footColor={D.potentialSavings>0?cG:'var(--ink-400)'}/>
      </div>
    </ChartCard>
  );
}

/* ============================ HEALTH SCORE HERO ============================ */
function HealthScore({ D }) {
  const [open, setOpen] = React.useState(false);
  const weakest = [...D.FACTORS].sort((a,b)=>a.val-b.val);
  const improvements = D.opps.slice(0,3).map((o,i)=>{
    const lift = clamp(Math.round((100 - weakest[i%weakest.length].val) * (weakest[i%weakest.length].wt/100) * 0.5), 1, 6);
    return { t:o.title, p:'+'+lift, ic:o.icon, c:o.color };
  });
  const proj = clamp(D.score + improvements.reduce((s,r)=>s+(+r.p),0), 0, 100);
  return (
    <ChartCard pad={false} className="cm-mt-20">
      <div style={{padding:'22px 26px'}}>
        <div className="st-health">
          {/* gauge */}
          <div style={{textAlign:'center',display:'flex',flexDirection:'column'}}>
            <div className="cm-row" style={{justifyContent:'center',gap:7,marginBottom:4}}>
              <span style={{color:cG,display:'inline-flex'}}><Si.shield size={17}/></span>
              <span className="st-mini-title">Insurance Health Score</span>
            </div>
            <HealthGauge score={D.score} band={D.band} stars={D.stars}/>
            <div className="t-caption num" style={{marginTop:14}}>Weighted across 6 factors · range 0 – 100</div>
          </div>
          {/* breakdown */}
          <div className="col-sep">
            <div className="cm-row" style={{justifyContent:'space-between',marginBottom:8}}>
              <span className="st-eyebrow">Score Breakdown</span>
              <span className="t-caption">weighted</span>
            </div>
            <div className="st-break">
              {D.FACTORS.map((f,i)=>(
                <div className="st-break-row" key={i}>
                  <span className="st-break-ic" style={{background:'var(--mint-50)',color:f.color}}><f.ic size={15}/></span>
                  <div>
                    <div><span className="st-break-name">{f.name}</span><span className="st-break-wt">({f.wt}%)</span></div>
                    <div className="st-break-track"><div className="st-break-fill" style={{width:`${f.fill*100}%`,background:f.color}}/></div>
                  </div>
                  <div className="st-break-val">{f.val}/100</div>
                </div>
              ))}
            </div>
            <div onClick={()=>setOpen(o=>!o)} style={{marginTop:14,display:'flex',alignItems:'center',gap:8,cursor:'pointer',
              padding:'11px 14px',borderRadius:'var(--r-ctrl)',background:'var(--mint-50)'}}>
              <span style={{color:cG,display:'inline-flex'}}><Si.info size={16}/></span>
              <span className="t-label" style={{color:'var(--ink-900)',flex:1}}>How is this score calculated?</span>
              <span style={{color:'var(--ink-400)',display:'inline-flex',transition:'.2s',transform:open?'rotate(180deg)':'none'}}><Si.chev size={16}/></span>
            </div>
            {open && (
              <div style={{marginTop:10,padding:'14px 16px',borderRadius:'var(--r-ctrl)',border:'1px solid var(--line)',
                fontSize:13,lineHeight:1.55,color:'var(--ink-700)',fontWeight:600}}>
                Your score blends six weighted factors computed from your policies.
                {' '}<b style={{color:'var(--ink-900)'}}>{weakest[0].name}</b> ({weakest[0].val}/100) is your biggest drag
                {weakest[0].key==='bene' && D.withBene===0 ? ' — no policies have a beneficiary on file yet' : ''}.
                {' '}Acting on the recommendations could lift you toward <b style={{color:cG}}>{proj}+</b>.
              </div>
            )}
          </div>
          {/* recommendations + trend */}
          <div className="col-sep">
            <div className="cm-row" style={{justifyContent:'space-between',marginBottom:6}}>
              <span className="st-eyebrow">Improvement Opportunities</span>
              <span className="t-caption">est. impact</span>
            </div>
            <div style={{display:'flex',flexDirection:'column',gap:8,marginBottom:16}}>
              {improvements.map((r,i)=>(
                <div key={i} className="cm-row" style={{gap:10,padding:'10px 12px',border:'1px solid var(--line)',borderRadius:'var(--r-ctrl)'}}>
                  <span style={{width:30,height:30,flex:'0 0 30px',borderRadius:9,background:'var(--mint-50)',color:r.c,display:'flex',alignItems:'center',justifyContent:'center'}}><r.ic size={15}/></span>
                  <span className="t-label" style={{flex:1,color:'var(--ink-900)'}}>{r.t}</span>
                  <span className="cm-pill cm-pill-green" style={{fontWeight:800}}>{r.p} pts</span>
                </div>
              ))}
            </div>
            <div className="cm-row" style={{justifyContent:'space-between',marginBottom:6}}>
              <span className="st-eyebrow">Score Trend</span>
              <span className="t-caption">last 12 months</span>
            </div>
            <ScoreTrend score={D.score}/>
            <div style={{display:'flex',gap:24,marginTop:10}}>
              <div><div className="t-caption">Projected next</div><div className="num" style={{fontWeight:800,color:cG,fontSize:18}}>{proj}</div></div>
              <div><div className="t-caption">Open items</div><div className="num" style={{fontWeight:800,color:'var(--ink-900)',fontSize:18}}>{D.opps.length}</div></div>
            </div>
          </div>
        </div>
      </div>
    </ChartCard>
  );
}

/* ============================ ANALYTICS ROW ============================ */
function MiniHead({ title, sub, right }) {
  return (
    <div className="cm-row" style={{justifyContent:'space-between',alignItems:'flex-start',marginBottom:16}}>
      <div><div className="st-mini-title">{title}</div><div className="st-mini-sub">{sub}</div></div>
      {right}
    </div>
  );
}
function AnalyticsRow({ D }) {
  const maxAnnual = Math.max(...D.byType.map(x=>x.annual), 1);
  const netPct = D.totalCoverage ? clamp(D.netProtection/D.totalCoverage*100, 0, 100) : 0;
  return (
    <div className="st-analytics cm-mt-20">
      {/* coverage breakdown donut */}
      <ChartCard>
        <MiniHead title="Coverage Breakdown" sub="By insurance type"/>
        <div style={{display:'flex',justifyContent:'center',marginBottom:14}}>
          <DonutChart size={150} thickness={21}
            segments={D.byType.map(t=>({value:t.coverage,color:t.color}))}
            center={{value:compact(D.totalCoverage), label:'Total Coverage'}}/>
        </div>
        <Legend items={D.byType.map(t=>({
          color:t.color, label:t.kind, pct:`${Math.round(t.coverage/D.totalCoverage*100)}%`, value:compact(t.coverage)
        }))}/>
      </ChartCard>

      {/* premium by category bars */}
      <ChartCard>
        <MiniHead title="Premium by Category" sub="Annual amount"/>
        <div>
          {[...D.byType].sort((a,b)=>b.annual-a.annual).map((t,i)=>(
            <div className="st-util-row" key={i} style={{gridTemplateColumns:'1fr 90px 64px'}}>
              <span className="st-util-name">{t.kind}</span>
              <span className="st-util-track"><span className="st-util-fill" style={{width:`${(t.annual/maxAnnual)*100}%`,background:t.color}}/></span>
              <span className="st-util-pct num">{usd0(t.annual)}</span>
            </div>
          ))}
        </div>
        <div className="cm-row" style={{justifyContent:'space-between',marginTop:12,paddingTop:12,borderTop:'1px solid var(--line)'}}>
          <span className="t-label" style={{color:'var(--ink-500)'}}>Total annual premium</span>
          <span className="num" style={{fontWeight:800,color:'var(--ink-900)'}}>{usd0(D.totalAnnual)}</span>
        </div>
      </ChartCard>

      {/* premium trend */}
      <ChartCard>
        <MiniHead title="Premium Trend" sub="Monthly · last 12 months"/>
        <PremiumTrend monthly={D.totalMonthly}/>
        <div style={{display:'flex',gap:20,marginTop:12,paddingTop:12,borderTop:'1px solid var(--line)'}}>
          <div><div className="t-caption">Current</div><div className="num" style={{fontWeight:800,color:'var(--ink-900)',fontSize:17}}>{usd(D.totalMonthly)}</div></div>
          <div><div className="t-caption">Annualized</div><div className="num" style={{fontWeight:800,color:'var(--ink-900)',fontSize:17}}>{usd0(D.totalAnnual)}</div></div>
        </div>
      </ChartCard>

      {/* net protection gauge */}
      <ChartCard>
        <MiniHead title="Net Protection" sub="Coverage − outstanding debt"/>
        <HalfGauge pct={netPct} label="Protected" value={compact(D.netProtection)} valueColor="var(--ink-900)"/>
        <div style={{marginTop:10}}>
          {[['Total coverage', compact(D.totalCoverage)],['Outstanding debt', usd0(D.debt)],['Net protection', usd0(D.netProtection)]].map((r,i)=>(
            <div key={i} className="cm-row" style={{justifyContent:'space-between',padding:'6px 0',borderBottom: i<2?'1px solid var(--line)':'none'}}>
              <span className="t-caption">{r[0]}</span>
              <span className="num" style={{fontWeight:700,color:i===2?cG:'var(--ink-900)',fontSize:13}}>{r[1]}</span>
            </div>
          ))}
        </div>
      </ChartCard>
    </div>
  );
}

/* ============================ PREMIUMS · RENEWALS · BENEFICIARIES ============================ */
function PremiumCard({ D }) {
  const splitPct = D.totalAnnual ? D.byType.map(t=>({...t, pct:Math.round(t.annual/D.totalAnnual*100)})) : [];
  return (
    <ChartCard>
      <MiniHead title="Premium Payments" sub="From your bank ledger"/>
      <div style={{display:'flex',alignItems:'center',gap:18,marginBottom:16}}>
        <DonutChart size={104} thickness={16}
          segments={D.byType.map(t=>({value:t.annual,color:t.color}))}
          center={{value:usd0(D.totalMonthly), label:'/month'}}/>
        <div style={{flex:1,display:'grid',gridTemplateColumns:'1fr 1fr',gap:'10px 12px'}}>
          {[['Annual', usd0(D.totalAnnual), 'var(--ink-900)'],['Paid YTD', usd0(D.paidYTD), cG],['Policies', String(D.pols.length), 'var(--ink-900)'],['Avg / policy', usd0(D.totalAnnual/Math.max(1,D.pols.length)), 'var(--ink-900)']].map((s,i)=>(
            <div key={i}><div className="num" style={{fontWeight:800,fontSize:16,color:s[2]}}>{s[1]}</div><div className="t-caption">{s[0]}</div></div>
          ))}
        </div>
      </div>
      <div style={{borderTop:'1px solid var(--line)',paddingTop:6}}>
        {D.payments.length ? D.payments.slice(0,3).map((c,i,arr)=>(
          <div className="cm-row" key={i} style={{gap:10,padding:'9px 0',borderBottom: i<Math.min(arr.length,3)-1?'1px solid var(--line)':'none'}}>
            <div style={{flex:1,minWidth:0}}>
              <div className="t-label" style={{color:'var(--ink-900)'}}>{c.desc||c.name||'Insurance payment'}</div>
              <div className="t-caption num">{c.date?c.date.toLocaleDateString('en-CA',{month:'short',day:'numeric',year:'numeric'}):''}</div>
            </div>
            <span className="num" style={{fontWeight:700,color:'var(--ink-900)'}}>{usd(c.dr)}</span>
            <span className="cm-pill cm-pill-green" style={{minWidth:74,justifyContent:'center'}}>Paid</span>
          </div>
        )) : (
          <div className="t-caption" style={{padding:'14px 0',textAlign:'center'}}>No insurance payments recorded in your ledger yet.</div>
        )}
      </div>
      <button className="cm-btn cm-btn-soft" style={{width:'100%',justifyContent:'center',marginTop:14}}>View premium history</button>
    </ChartCard>
  );
}
function RenewalsCard({ D }) {
  const tone = d => d<=30?'red':d<=60?'amber':'slate';
  const toneClass = { red:'cm-pill-red', amber:'cm-pill-amber', slate:'cm-pill-slate' };
  return (
    <ChartCard>
      <MiniHead title="Renewal Center" sub="Upcoming renewals"/>
      <div className="cm-row" style={{gap:8,marginBottom:14}}>
        {[['30 days',D.renew30,cRed],['60 days',D.renew60,cAmber],['90 days',D.renew90,'var(--ink-500)']].map((s,i)=>(
          <div key={i} style={{flex:1,textAlign:'center',padding:'10px 4px',borderRadius:'var(--r-ctrl)',background:'var(--mint-50)'}}>
            <div className="num" style={{fontWeight:800,fontSize:18,color:s[2]}}>{s[1]}</div>
            <div className="t-caption">{s[0]}</div>
          </div>
        ))}
      </div>
      <div>
        {D.renewals.slice(0,4).map((r,i,arr)=>(
          <div className="cm-row" key={i} style={{gap:11,padding:'11px 0',borderBottom: i<arr.length-1?'1px solid var(--line)':'none'}}>
            <span style={{width:34,height:34,flex:'0 0 34px',borderRadius:10,background:'var(--mint-50)',color:r.color,display:'flex',alignItems:'center',justifyContent:'center'}}><r.icon size={17}/></span>
            <div style={{flex:1,minWidth:0}}>
              <div className="t-label" style={{color:'var(--ink-900)'}}>{r.name}</div>
              <div className="t-caption">{r.provider}</div>
            </div>
            <div style={{textAlign:'right'}}>
              <span className={`cm-pill ${toneClass[tone(r.days)]}`}>in {r.days} days</span>
              <div className="t-caption num" style={{marginTop:3}}>{r.renew}</div>
            </div>
          </div>
        ))}
      </div>
    </ChartCard>
  );
}
function BeneficiaryCard({ D }) {
  const lifePol = D.pols.find(p=>p.type==='life');
  const total = D.beneList.reduce((a,b)=>a+b.pct,0);
  const missing = D.pols.length - D.withBene;
  return (
    <ChartCard>
      <MiniHead title="Beneficiaries" sub={lifePol ? `${lifePol.name} · suggested split` : 'Suggested split'}/>
      {D.beneList.length ? (
        <div style={{display:'flex',alignItems:'center',gap:18,marginBottom:14}}>
          <DonutChart size={104} thickness={16}
            segments={D.beneList.map(b=>({value:b.pct,color:b.color}))}
            center={{value:`${total}%`, label:'household'}}/>
          <div style={{flex:1,display:'flex',flexDirection:'column',gap:9}}>
            {D.beneList.map((b,i)=>(
              <div className="cm-row" key={i} style={{gap:9}}>
                <span style={{width:9,height:9,borderRadius:'50%',background:b.color,flex:'0 0 9px'}}/>
                <div style={{flex:1,minWidth:0}}>
                  <div className="t-label" style={{color:'var(--ink-900)',lineHeight:1.2}}>{b.name}</div>
                  <div className="t-caption">{b.rel}</div>
                </div>
                <span className="num" style={{fontWeight:800,color:'var(--ink-900)'}}>{b.pct}%</span>
              </div>
            ))}
          </div>
        </div>
      ) : (
        <div className="t-caption" style={{padding:'20px 0',textAlign:'center',marginBottom:8}}>Add family members in Family &amp; Vault to see a suggested split.</div>
      )}
      {missing>0 && (
        <div className="st-banner" style={{margin:0,background:'#FEF1DD',borderColor:'#F1DEBE'}}>
          <span className="ic" style={{color:cAmber}}><Si.alert size={17}/></span>
          <span className="tx" style={{color:'#7A5512'}}><b>{missing} polic{missing===1?'y':'ies'}</b> {missing===1?'has':'have'} no beneficiary on file. Assigning {D.beneList.length?'these names':'beneficiaries'} reaches 100% completeness.</span>
        </div>
      )}
      <button className="cm-btn cm-btn-soft" style={{width:'100%',justifyContent:'center',marginTop:14}}>Manage beneficiaries</button>
    </ChartCard>
  );
}
function MidRow({ D }) {
  return <div className="cm-grid-3 cm-mt-20"><PremiumCard D={D}/><RenewalsCard D={D}/><BeneficiaryCard D={D}/></div>;
}

/* ============================ COVERAGE GAP BANNER ============================ */
function GapBanner({ D }) {
  const [show, setShow] = React.useState(true);
  if (!show || D.lifeGap<=0) return null;
  return (
    <div className="st-banner">
      <span className="ic"><Si.spark size={18}/></span>
      <span className="tx">Based on your income and {D.beneList.filter(b=>/child/i.test(b.rel)).length} dependents, you may be <b>underinsured on Life</b> — recommended coverage is
        <b> {compact(D.recLife)}</b> vs your current <b>{compact(D.lifeCov)}</b>, a <b>{compact(D.lifeGap)} gap</b>. {' '}<a>Review coverage gaps</a></span>
      <span className="x" onClick={()=>setShow(false)}><Si.x size={16}/></span>
    </div>
  );
}

/* ============================ POLICY TABLE ============================ */
const STATUS = {
  active: { cls:'cm-pill-green', label:'Healthy',        cap:'Active' },
  review: { cls:'cm-pill-amber', label:'Review Soon',    cap:'Renews soon' },
  gap:    { cls:'cm-pill-red',   label:'Add Beneficiary', cap:'No beneficiary' },
};
/* ---- Policy detail modal — full coverage view (deductibles, VIN, dates, coverage list) ---- */
const fmtDate = s => {
  if (!s) return '—';
  const d = s instanceof Date ? s : new Date(s);
  return isNaN(d) ? String(s) : d.toLocaleDateString('en-CA', { year:'numeric', month:'short', day:'numeric' });
};
function Field({ label, value, mono, color }) {
  return (
    <div>
      <div className="t-caption" style={{ marginBottom: 3 }}>{label}</div>
      <div className={mono ? 'num' : ''} style={{ fontWeight: 700, fontSize: 13.5, color: color || 'var(--ink-900)' }}>{value || '—'}</div>
    </div>
  );
}
function PolicyDetailModal({ p, onClose, onEdit }) {
  React.useEffect(() => {
    const onKey = e => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);
  const r = p.raw || {};
  const s = STATUS[p.status];
  const ded = r.deductibles || {};
  const veh = r.vehicle || {};
  const covs = Array.isArray(r.coverages) ? r.coverages.filter(Boolean) : [];
  const isAuto = p.type === 'auto';
  const termPrem = r.termPremium != null ? +r.termPremium : null;
  const Icon = p.icon;
  return (
    <div onClick={onClose} style={{ position:'fixed', inset:0, zIndex:1100, background:'rgba(13,33,26,.45)', display:'flex', alignItems:'center', justifyContent:'center', padding:20 }}>
      <div onClick={e => e.stopPropagation()} className="cm-card" style={{ width:560, maxWidth:'100%', maxHeight:'88vh', overflowY:'auto', borderRadius:18, padding:0, boxShadow:'0 24px 64px rgba(13,42,33,.28)' }}>
        {/* header */}
        <div style={{ display:'flex', alignItems:'flex-start', gap:13, padding:'20px 22px 16px', borderBottom:'1px solid var(--line)' }}>
          <span style={{ width:44, height:44, flex:'0 0 44px', borderRadius:12, background:'var(--mint-50)', color:p.color, display:'flex', alignItems:'center', justifyContent:'center' }}><Icon size={22}/></span>
          <div style={{ flex:1, minWidth:0 }}>
            <div className="cm-row" style={{ gap:8, flexWrap:'wrap' }}>
              <span className="t-h2" style={{ fontSize:17 }}>{p.name}</span>
              {r.fromStatement && <span title="Imported from a statement" style={{ fontSize:9.5, fontWeight:800, color:'var(--ink-400)', border:'1px solid var(--line)', borderRadius:6, padding:'1px 5px' }}>IMPORTED</span>}
            </div>
            <div className="cm-row" style={{ gap:8, marginTop:5 }}>
              <span className="st-net" style={{ background:p.netBg }}>{p.net}</span>
              <span className="t-caption" style={{ fontWeight:700 }}>{p.provider} · {p.kind}</span>
              <span className={`cm-pill ${s.cls}`} style={{ fontWeight:700 }}>{s.label}</span>
            </div>
          </div>
          <span onClick={onClose} style={{ cursor:'pointer', color:'var(--ink-400)', display:'inline-flex', padding:4 }}><Si.x size={18}/></span>
        </div>

        {/* key facts */}
        <div style={{ padding:'18px 22px', display:'grid', gridTemplateColumns:'1fr 1fr', gap:'16px 20px' }}>
          <Field label="Policy number" value={p.policyNo} mono/>
          <Field label="Coverage" value={p.coverage > 0 ? usd0(p.coverage) : (p.coverageText || '—')} color={p.coverage > 0 ? cG : 'var(--ink-900)'}/>
          <Field label="Monthly premium" value={usd(p.monthly)} mono/>
          <Field label="Annual premium" value={usd0(p.annual)} mono/>
          {termPrem != null && <Field label="Term premium" value={usd(termPrem)} mono/>}
          {r.frequency && <Field label="Billing" value={r.frequency}/>}
        </div>

        {/* dates */}
        <div style={{ padding:'0 22px 18px' }}>
          <div className="st-eyebrow" style={{ marginBottom:10 }}>Policy term</div>
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:'0', border:'1px solid var(--line)', borderRadius:'var(--r-ctrl)', overflow:'hidden' }}>
            {[['Effective', fmtDate(r.effectiveDate)], ['Expiry', fmtDate(r.expiryDate)], ['Renewal', p.renew]].map((d,i) => (
              <div key={i} style={{ padding:'11px 13px', borderLeft: i ? '1px solid var(--line)' : 'none', background:'var(--mint-50)' }}>
                <div className="t-caption">{d[0]}</div>
                <div className="num" style={{ fontWeight:700, fontSize:13, color:'var(--ink-900)', marginTop:2 }}>{d[1]}</div>
                {d[0] === 'Renewal' && p.days != null && <div className="t-caption num" style={{ color:p.days<=30?cRed:'var(--ink-400)', marginTop:1 }}>in {p.days} days</div>}
              </div>
            ))}
          </div>
        </div>

        {/* auto: vehicle + deductibles */}
        {isAuto && (veh.description || veh.vin || ded.collision || ded.comprehensive) && (
          <div style={{ padding:'0 22px 18px' }}>
            <div className="st-eyebrow" style={{ marginBottom:10 }}>Vehicle &amp; deductibles</div>
            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:'16px 20px' }}>
              {veh.description && <Field label="Vehicle" value={veh.description}/>}
              {veh.vin && <Field label="VIN" value={veh.vin} mono/>}
              {ded.collision != null && <Field label="Collision deductible" value={usd0(ded.collision)} mono/>}
              {ded.comprehensive != null && <Field label="Comprehensive deductible" value={usd0(ded.comprehensive)} mono/>}
            </div>
          </div>
        )}

        {/* coverages */}
        {covs.length > 0 && (
          <div style={{ padding:'0 22px 18px' }}>
            <div className="st-eyebrow" style={{ marginBottom:10 }}>Coverages</div>
            <div style={{ display:'flex', flexWrap:'wrap', gap:8 }}>
              {covs.map((c,i) => (
                <span key={i} style={{ display:'inline-flex', alignItems:'center', gap:6, fontSize:12.5, fontWeight:700, color:'var(--ink-700)', background:'var(--mint-50)', border:'1px solid var(--mint-100)', borderRadius:999, padding:'5px 11px' }}>
                  <span style={{ color:cG, display:'inline-flex' }}><Si.check size={13}/></span>{c}
                </span>
              ))}
            </div>
          </div>
        )}

        {/* beneficiaries */}
        <div style={{ padding:'0 22px 18px' }}>
          <div className="st-eyebrow" style={{ marginBottom:10 }}>Beneficiaries</div>
          {p.beneficiaries && p.beneficiaries.length ? (
            <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
              {p.beneficiaries.map((b,i) => (
                <div key={i} className="cm-row" style={{ gap:10, padding:'9px 12px', border:'1px solid var(--line)', borderRadius:'var(--r-ctrl)' }}>
                  <span style={{ width:9, height:9, borderRadius:'50%', background:cG, flex:'0 0 9px' }}/>
                  <span className="t-label" style={{ flex:1, color:'var(--ink-900)' }}>{b.name || b}</span>
                  {b.relation && <span className="t-caption">{b.relation}</span>}
                  {b.pct != null && <span className="num" style={{ fontWeight:800, color:'var(--ink-900)' }}>{b.pct}%</span>}
                </div>
              ))}
            </div>
          ) : (
            <div className="st-banner" style={{ margin:0, background:'#FEF1DD', borderColor:'#F1DEBE' }}>
              <span className="ic" style={{ color:cAmber }}><Si.users size={16}/></span>
              <span className="tx" style={{ color:'#7A5512' }}>No beneficiary on file for this policy. Assign one to keep payouts out of probate.</span>
            </div>
          )}
        </div>

        {/* footer */}
        <div style={{ display:'flex', justifyContent:'flex-end', gap:10, padding:'14px 22px 20px', borderTop:'1px solid var(--line)' }}>
          <button onClick={onClose} className="cm-btn cm-btn-ghost">Close</button>
          {onEdit && <button onClick={onEdit} className="cm-btn cm-btn-primary"><Si.edit size={15}/>Edit policy</button>}
        </div>
      </div>
    </div>
  );
}

/* ---- Policy edit modal — edit the stored policy in place (writes back to CM.S.insurance) ---- */
const POL_TYPES = [['home','Home'],['auto','Auto'],['life','Life'],['health','Health'],['disability','Disability'],['critical','Critical Illness'],['travel','Travel'],['other','Other']];
const toInputDate = s => {
  if (!s) return '';
  const d = s instanceof Date ? s : new Date(s);
  return isNaN(d) ? '' : d.toISOString().slice(0, 10);
};
function PolicyEditModal({ p, CM, onClose }) {
  const r = p.raw || {};
  const beneInit = (Array.isArray(r.beneficiaries) ? r.beneficiaries : []).map(b =>
    typeof b === 'string' ? { name: b, relation: '', pct: '' } : { name: b.name || '', relation: b.relation || '', pct: b.pct != null ? String(b.pct) : '' });
  const [f, setF] = React.useState({
    name: r.name || p.name || '',
    type: (r.type || p.type || 'other').toLowerCase(),
    provider: r.provider || (p.provider !== '—' ? p.provider : '') || '',
    premium: r.premium != null ? String(r.premium) : (p.monthly ? String(p.monthly) : ''),
    coverage: r.coverage ? String(r.coverage) : '',
    coverageText: r.coverageText || p.coverageText || '',
    renewal: toInputDate(r.renewal || r.expiryDate),
    policyNum: r.policyNum || r.policy || '',
  });
  const [bene, setBene] = React.useState(beneInit);
  const [confirmDel, setConfirmDel] = React.useState(false);
  React.useEffect(() => {
    const onKey = e => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);
  const set = k => e => setF(s => Object.assign({}, s, { [k]: e.target.value }));
  const setBeneAt = (i, k) => e => setBene(rows => rows.map((b, j) => j === i ? Object.assign({}, b, { [k]: e.target.value }) : b));
  const addBene = () => setBene(rows => rows.concat([{ name: '', relation: '', pct: '' }]));
  const rmBene = i => setBene(rows => rows.filter((_, j) => j !== i));

  const inp = { width:'100%', fontFamily:'inherit', fontSize:13.5, color:'var(--ink-900)', border:'1px solid var(--line)', borderRadius:10, padding:'9px 11px', background:'#fff', outline:'none', boxSizing:'border-box' };
  const lab = { fontSize:11, fontWeight:700, letterSpacing:'.06em', textTransform:'uppercase', color:'var(--ink-400)', margin:'0 0 5px' };
  const Field = ({ label, children, full }) => <div style={full ? { gridColumn:'1 / -1' } : undefined}><div style={lab}>{label}</div>{children}</div>;

  const save = () => {
    const beneOut = bene.filter(b => b.name.trim()).map(b => {
      const o = { name: b.name.trim() };
      if (b.relation && b.relation.trim()) o.relation = b.relation.trim();
      if (b.pct !== '' && !isNaN(parseFloat(b.pct))) o.pct = parseFloat(b.pct);
      return o;
    });
    CM.mutate(function () {
      const arr = (CM.S.insurance = CM.S.insurance || []);
      const orig = arr[p.idx] || {};
      arr[p.idx] = Object.assign({}, orig, {
        name: f.name.trim() || orig.name,
        type: f.type,
        provider: f.provider.trim(),
        premium: f.premium !== '' ? (parseFloat(f.premium) || 0) : 0,
        frequency: 'Monthly',
        coverage: f.coverage !== '' ? (parseFloat(f.coverage) || 0) : 0,
        coverageText: f.coverageText.trim(),
        renewal: f.renewal || null,
        policyNum: f.policyNum.trim(), policy: f.policyNum.trim(),
        beneficiaries: beneOut,
      });
    });
    try { CM.logActivity && CM.logActivity('updated an insurance policy', (f.name.trim() || 'Policy'), { cat:'insurance' }); } catch (e) {}
    onClose();
  };
  const del = () => {
    CM.mutate(function () { (CM.S.insurance || []).splice(p.idx, 1); });
    try { CM.logActivity && CM.logActivity('removed an insurance policy', (f.name.trim() || 'Policy'), { cat:'insurance' }); } catch (e) {}
    onClose();
  };

  return (
    <div onClick={onClose} style={{ position:'fixed', inset:0, zIndex:1100, background:'rgba(13,33,26,.45)', display:'flex', alignItems:'center', justifyContent:'center', padding:20 }}>
      <div onClick={e => e.stopPropagation()} className="cm-card" style={{ width:600, maxWidth:'100%', maxHeight:'92vh', overflowY:'auto', borderRadius:18, padding:'22px 24px', boxShadow:'0 24px 64px rgba(13,42,33,.28)' }}>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:4 }}>
          <div className="t-h2" style={{ fontSize:18 }}>Edit Policy</div>
          <button onClick={onClose} aria-label="Close" style={{ border:0, background:'none', cursor:'pointer', color:'var(--ink-400)', fontSize:20, lineHeight:1, padding:4 }}>×</button>
        </div>
        <div className="t-caption" style={{ marginBottom:16 }}>Premium is monthly. Leave coverage at 0 to show the coverage summary text instead.</div>
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:'13px 14px' }}>
          <Field label="Policy name" full><input style={inp} value={f.name} onChange={set('name')} placeholder="e.g. Intact Home Insurance"/></Field>
          <Field label="Type"><select style={inp} value={f.type} onChange={set('type')}>{POL_TYPES.map(([v,l]) => <option key={v} value={v}>{l}</option>)}</select></Field>
          <Field label="Provider">
            <input style={inp} list="cm-ins-prov" value={f.provider} onChange={set('provider')} placeholder="Intact, Sun Life…"/>
            <datalist id="cm-ins-prov">{Object.keys(PROVIDER_BG).map(s => <option key={s} value={s}/>)}</datalist>
          </Field>
          <Field label="Monthly premium"><input style={inp} value={f.premium} onChange={set('premium')} inputMode="decimal" placeholder="0.00"/></Field>
          <Field label="Coverage amount"><input style={inp} value={f.coverage} onChange={set('coverage')} inputMode="decimal" placeholder="0"/></Field>
          <Field label="Coverage summary (if no amount)" full><input style={inp} value={f.coverageText} onChange={set('coverageText')} placeholder="e.g. Third Party Liability · Collision · Comprehensive"/></Field>
          <Field label="Renewal date"><input style={inp} type="date" value={f.renewal} onChange={set('renewal')}/></Field>
          <Field label="Policy number"><input style={inp} value={f.policyNum} onChange={set('policyNum')} placeholder="••••1234"/></Field>
        </div>

        {/* beneficiaries editor */}
        <div style={{ marginTop:18 }}>
          <div className="cm-row" style={{ justifyContent:'space-between', marginBottom:8 }}>
            <span style={lab}>Beneficiaries</span>
            <span onClick={addBene} style={{ cursor:'pointer', color:cG, fontWeight:700, fontSize:12.5, display:'inline-flex', alignItems:'center', gap:4 }}><Si.plus size={14}/>Add</span>
          </div>
          {bene.length ? bene.map((b,i) => (
            <div key={i} style={{ display:'grid', gridTemplateColumns:'1fr 90px 34px', gap:8, marginBottom:8 }}>
              <input style={inp} value={b.name} onChange={setBeneAt(i,'name')} placeholder="Name"/>
              <input style={inp} value={b.pct} onChange={setBeneAt(i,'pct')} inputMode="decimal" placeholder="%"/>
              <button onClick={()=>rmBene(i)} aria-label="Remove" style={{ border:'1px solid var(--line)', background:'#fff', borderRadius:10, color:cRed, cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center' }}><Si.trash size={14}/></button>
            </div>
          )) : <div className="t-caption" style={{ padding:'2px 0 4px' }}>No beneficiaries yet — add one to reach 100% completeness.</div>}
        </div>

        <div style={{ display:'flex', alignItems:'center', gap:10, marginTop:22 }}>
          {confirmDel ? (
            <>
              <span className="t-caption" style={{ color:cRed, fontWeight:700, flex:1 }}>Delete this policy?</span>
              <button onClick={()=>setConfirmDel(false)} className="cm-btn cm-btn-ghost">Cancel</button>
              <button onClick={del} className="cm-btn" style={{ background:cRed, color:'#fff', border:'1px solid '+cRed }}>Delete</button>
            </>
          ) : (
            <>
              <button onClick={()=>setConfirmDel(true)} className="cm-btn cm-btn-ghost" style={{ color:cRed, marginRight:'auto' }}><Si.trash size={15}/>Delete</button>
              <button onClick={onClose} className="cm-btn cm-btn-ghost">Cancel</button>
              <button onClick={save} className="cm-btn cm-btn-primary">Save Changes</button>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

function PolicyTable({ D, period }) {
  const CM = window.useStore ? window.useStore() : window.CM;
  const [viewPol, setViewPol] = React.useState(null);
  const [editPol, setEditPol] = React.useState(null);
  const [query, setQuery] = React.useState('');
  const types = ['All Types', ...Array.from(new Set(D.pols.map(p=>p.kind)))];
  const [typeI, setTypeI] = React.useState(0);
  const [impBusy, setImpBusy] = React.useState(false);
  const [impNote, setImpNote] = React.useState(null);
  const impRef = React.useRef(null);
  // Import an insurance PDF → /api/parse-statement → store a policy in S.insurance.
  const onImport = (e) => {
    const file = e.target.files && e.target.files[0]; e.target.value = ''; if (!file) return;
    setImpBusy(true); setImpNote(null);
    const reader = new FileReader();
    reader.onerror = () => { setImpBusy(false); setImpNote({ ok:false, msg:'Could not read that file.' }); };
    reader.onload = () => {
      const b64 = String(reader.result).split(',')[1] || '';
      fetch((window.CM_API_BASE||'/api')+'/parse-statement', { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({ pdf:b64 }) })
        .then(r=>r.json()).then(d=>{
          if (!(d && d.docType==='insurance' && d.insurance)) { setImpNote({ ok:false, msg:(d&&d.issuer&&d.issuer!=='Unknown') ? (d.issuer+' document read, but it doesn’t look like an insurance policy.') : 'No insurance policy found in that PDF.' }); return; }
          const ins = d.insurance;
          const covText = ins.type==='auto' ? [ins.vehicle&&ins.vehicle.description, (ins.coverages||[]).join(', ')].filter(Boolean).join(' · ') : (ins.coverages||[]).join(', ');
          CM.mutate(()=>{ (CM.S.insurance = CM.S.insurance || []).push({
            name: ins.insurer + (ins.type==='home'?' Home':ins.type==='auto'?' Auto':'') + ' Insurance',
            type: ins.type, provider: ins.insurer,
            premium: ins.premium ? Math.round(ins.premium/12*100)/100 : 0, frequency:'Monthly',
            renewal: ins.renewalDate || ins.expiryDate || null, coverage: 0, coverageText: covText,
            policyNum: ins.policyNumber, policy: ins.policyNumber,
            effectiveDate: ins.effectiveDate, expiryDate: ins.expiryDate, termPremium: ins.premium,
            vehicle: ins.vehicle, deductibles: ins.deductibles, coverages: ins.coverages, fromStatement:true,
          }); });
          try { CM.logActivity && CM.logActivity('imported an insurance policy', ins.insurer+' · '+ins.type, { cat:'insurance' }); } catch(e){}
          setImpNote({ ok:true, msg:'Imported a '+ins.type+' insurance policy from '+ins.insurer+'.' });
        }).catch(()=>setImpNote({ ok:false, msg:'Could not read that document.' })).finally(()=>setImpBusy(false));
    };
    reader.readAsDataURL(file);
  };
  const typeF = types[typeI % types.length];
  const rows = D.pols.filter(p =>
    (p.name+p.provider+p.kind).toLowerCase().includes(query.toLowerCase()) &&
    (typeF==='All Types' || p.kind===typeF) &&
    (!period || period==='all' || !window.cmInPeriod || window.cmInPeriod(p.renewDate, period)));
  const COLS = ['Policy','Provider','Type','Coverage','Annual Premium','Renewal','Beneficiaries','Status','Actions'];
  return (
    <ChartCard className="cm-mt-20">
      <div className="st-tablehead">
        <div>
          <div className="cm-row" style={{gap:8}}>
            <span className="st-mini-title">Policy Portfolio</span>
            <span className="cm-pill cm-pill-slate" style={{fontWeight:700}}>{rows.length} polic{rows.length===1?'y':'ies'}</span>
          </div>
          <div className="st-mini-sub">Every policy, provider and renewal in one place</div>
        </div>
        <div className="filters">
          <div className="st-searchbox">
            <Si.search size={15}/>
            <input placeholder="Search policies…" value={query} onChange={e=>setQuery(e.target.value)}/>
          </div>
          <span className="st-control" onClick={()=>setTypeI(i=>i+1)}>
            {typeF} <Si.chev size={14}/>
          </span>
          <span className="st-control"><Si.grid size={15}/></span>
        </div>
      </div>

      <div style={{overflowX:'auto'}}>
        <table className="st-table" style={{minWidth:1040}}>
          <thead><tr>{COLS.map((c,i)=><th key={i} className={c==='Actions'?'r':''}>{c}</th>)}</tr></thead>
          <tbody>
            {rows.map((p,ri)=>{
              const s = STATUS[p.status];
              return (
                <tr key={ri} className="subrow">
                  <td>
                    <div className="cm-row" style={{gap:11}}>
                      <span style={{width:36,height:36,flex:'0 0 36px',borderRadius:10,background:'var(--mint-50)',color:p.color,display:'flex',alignItems:'center',justifyContent:'center'}}><p.icon size={18}/></span>
                      <div><div className="st-cardname" style={{fontSize:14}}>{p.name}</div><div className="t-caption num">{p.policyNo}</div></div>
                    </div>
                  </td>
                  <td>
                    <div className="cm-row" style={{gap:8}}>
                      <span className="st-net" style={{background:p.netBg}}>{p.net}</span>
                      <span className="st-num">{p.provider}</span>
                    </div>
                  </td>
                  <td><span className="st-num mut">{p.kind}</span></td>
                  <td>{p.coverage>0 ? <span className="st-num">{usd0(p.coverage)}</span> : <span className="t-caption" style={{fontWeight:600}}>{p.coverageText||'—'}</span>}</td>
                  <td><span className="st-num">{usd0(p.annual)}</span><div className="t-caption num">{usd(p.monthly)}/mo</div></td>
                  <td><span className="st-num mut">{p.renew}</span>{p.days!=null && <div className="t-caption num" style={{color:p.days<=30?cRed:'var(--ink-400)'}}>in {p.days} days</div>}</td>
                  <td>{p.bene>0
                    ? <span className="cm-pill cm-pill-green" style={{fontWeight:700}}>{p.bene} on file</span>
                    : <span className="cm-pill cm-pill-red" style={{fontWeight:700}}>None</span>}</td>
                  <td><div className="st-statuswrap"><span className={`cm-pill ${s.cls}`}>{s.label}</span><span className="cap">{s.cap}</span></div></td>
                  <td style={{textAlign:'right'}}>
                    <div className="st-act" style={{justifyContent:'flex-end'}}>
                      <span className="st-actbtn" style={{cursor:'pointer'}} onClick={()=>setViewPol(p)}><Si.eye size={14}/>View</span>
                      <span className="st-actbtn" style={{cursor:'pointer'}} onClick={()=>setEditPol(p)}><Si.edit size={14}/>Edit</span>
                      <span className="st-kebab"><Si.kebab size={16}/></span>
                    </div>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>

      <div className="st-pager">
        <span className="t-caption">Showing <b style={{color:'var(--ink-700)'}}>{rows.length}</b> of <b style={{color:'var(--ink-700)'}}>{D.pols.length}</b> polic{D.pols.length===1?'y':'ies'}</span>
        <div style={{display:'flex',gap:10,alignItems:'center'}}>
          {impNote && <span className="t-caption" style={{color:impNote.ok?'var(--green-600)':'#A9772A',fontWeight:700}}>{impNote.msg}</span>}
          <button className="cm-add-row green" disabled={impBusy} style={{width:'auto',padding:'10px 16px'}} onClick={()=>impRef.current&&impRef.current.click()}><Si.plus size={16}/>{impBusy?'Reading…':'Import policy (PDF)'}</button>
          <input ref={impRef} type="file" accept="application/pdf,.pdf" style={{display:'none'}} onChange={onImport}/>
        </div>
      </div>
      {viewPol && <PolicyDetailModal p={viewPol} onClose={()=>setViewPol(null)} onEdit={()=>{ const pol=viewPol; setViewPol(null); setEditPol(pol); }}/>}
      {editPol && <PolicyEditModal p={editPol} CM={CM} onClose={()=>setEditPol(null)}/>}
    </ChartCard>
  );
}

/* ============================ OPTIMIZATION INSIGHTS ============================ */
function Insight({ icon, tint, color, title, sub, big, bigColor, text, link }) {
  return (
    <div className="st-insight">
      <div className="ihead">
        <span className="iic" style={{background:tint,color}}>{icon}</span>
        <div><div className="ititle">{title}</div><div className="isub">{sub}</div></div>
      </div>
      <div className="ibig num" style={bigColor?{color:bigColor}:null}>{big}</div>
      <div className="itext">{text}</div>
      <span className="ilink">{link} <Si.chevR size={14}/></span>
    </div>
  );
}
function Optimization({ D }) {
  if (!D.opps.length) return null;
  return (
    <>
      <div style={{margin:'24px 0 8px'}} className="cm-row">
        <span className="st-eyebrow">Optimization &amp; Coverage Gaps</span>
      </div>
      <div className="st-insights">
        {D.opps.map((o,i)=>(
          <Insight key={i} icon={<o.icon size={18}/>} tint={o.tint} color={o.color}
            title={o.title} sub={o.sub} big={o.big} bigColor={o.bigColor} text={o.text} link={o.link}/>
        ))}
      </div>
    </>
  );
}

/* ============================ QUICK ACTIONS ============================ */
function QuickActions() {
  const acts = [
    { ic:Si.scale,  t:'Compare Quotes',   s:'Find better rates',     c:cG },
    { ic:Si.doc,    t:'File a Claim',      s:'Start a new claim',     c:cRed },
    { ic:Si.layers, t:'Policy Documents',  s:'View all documents',    c:cPlum },
    { ic:Si.cal,    t:'Insurance Calendar',s:'All due dates',         c:cBlue },
    { ic:Si.users,  t:'Add Beneficiary',   s:'Manage beneficiaries',  c:cGold },
  ];
  return (
    <>
      <div style={{margin:'24px 0 8px'}} className="cm-row">
        <span className="st-eyebrow">Tools &amp; Quick Actions</span>
      </div>
      <div style={{display:'grid',gridTemplateColumns:'repeat(5,1fr)',gap:20}} className="ins-actions">
        {acts.map((a,i)=>(
          <div key={i} className="cm-tile" style={{display:'flex',alignItems:'center',gap:12,padding:'18px 18px',cursor:'pointer'}}>
            <span style={{width:42,height:42,flex:'0 0 42px',borderRadius:12,background:'var(--mint-50)',color:a.c,display:'flex',alignItems:'center',justifyContent:'center'}}><a.ic size={20}/></span>
            <div><div className="t-label" style={{color:'var(--ink-900)'}}>{a.t}</div><div className="t-caption">{a.s}</div></div>
          </div>
        ))}
      </div>
    </>
  );
}

/* ============================ EMPTY STATE ============================ */
function EmptyState() {
  return (
    <ChartCard>
      <div style={{textAlign:'center',padding:'60px 0'}}>
        <div style={{color:cG,marginBottom:14,display:'flex',justifyContent:'center'}}><Si.umbrella size={40}/></div>
        <div className="title" style={{fontSize:18}}>No policies yet</div>
        <div className="t-caption" style={{marginTop:6}}>Upload a policy or link a provider to see your coverage, premiums and renewals here.</div>
        <button className="cm-btn cm-btn-primary" style={{marginTop:18}}><Si.upload size={16}/>Upload Policy</button>
      </div>
    </ChartCard>
  );
}

/* ============================ PAGE ============================ */
function PageInsurance() {
  const CM = window.useStore ? window.useStore() : window.CM;
  const D = deriveInsurance(CM);
  const asOf = CM.FD ? CM.FD(CM.today ? CM.today() : new Date()) : '';
  const [period, setPeriod] = React.useState('all');

  if (!D.pols.length) {
    return <div><Toolbar asOf={asOf} period={period} setPeriod={setPeriod}/><EmptyState/></div>;
  }

  return (
    <div>
      <Toolbar asOf={asOf} period={period} setPeriod={setPeriod}/>
      <PortfolioSummary D={D}/>
      <HealthScore D={D}/>
      <AnalyticsRow D={D}/>
      <MidRow D={D}/>
      <GapBanner D={D}/>
      <PolicyTable D={D} period={period}/>
      <Optimization D={D}/>
      <QuickActions/>
    </div>
  );
}

window.PageInsurance = PageInsurance;
})();
