// evaluation-nist-engine.jsx — Verigo Global: NIST CSF v2.0 readiness evaluation engine
// All six functions are assessed regardless of tier; tier shapes recommendations.
// Exposes window.EVAL_NIST
const { V: GV, MAXW: GMW, FONT: GFT } = window;

// Compute subcategory counts per function from NIST_FUNCS global (loaded first by data file)
const N_FN_COUNTS = {};
(function(){ NIST_FUNCS.forEach(f=>{ N_FN_COUNTS[f.fn]=f.cats.reduce((a,c)=>a+c.items.length,0); }); })();

/* ── QUESTION BANK — 6 functions × 3 questions, tagged with CSF subcategory IDs ── */
const NIST_Q = [
  { fn:'GV', name:'Govern', icon:'briefcase', docs:['Cybersecurity Policy','Organizational Risk Management Policy','Cybersecurity Roles & Responsibilities Policy'], q:[
    ['GV.OC-01','The organizational mission is understood and informs how cybersecurity risk is prioritized.'],
    ['GV.RM-02','Cybersecurity risk appetite and risk tolerance statements are established, communicated, and maintained.'],
    ['GV.SC-05','Requirements to address cybersecurity risks in supply chains are established and integrated into contracts.'],
  ]},
  { fn:'ID', name:'Identify', icon:'search', docs:['Asset Management Policy','Vulnerability Management Policy'], q:[
    ['ID.AM-01','Inventories of hardware and software managed by the organization are established and maintained.'],
    ['ID.RA-01','Vulnerabilities in assets are identified, validated, and recorded.'],
    ['ID.IM-01','Improvements are identified from security evaluations, tests, and exercises.'],
  ]},
  { fn:'PR', name:'Protect', icon:'shield', docs:['Identity & Access Management Policy','Data Security Policy','Platform & Infrastructure Security Policy','Security Awareness & Training Policy'], q:[
    ['PR.AA-01','Identities and credentials for authorized users, services, and hardware are managed.'],
    ['PR.DS-01','The confidentiality, integrity, and availability of data at rest are protected.'],
    ['PR.PS-01','Configuration management practices are established and applied across systems.'],
  ]},
  { fn:'DE', name:'Detect', icon:'activity', docs:['Continuous Monitoring Policy','Security Monitoring & Alerting Procedure'], q:[
    ['DE.CM-01','Networks and network services are monitored to find potentially adverse events.'],
    ['DE.AE-03','Information from multiple sources is correlated to understand the scope of adverse events.'],
    ['DE.AE-08','Incidents are declared when adverse events meet the defined incident criteria.'],
  ]},
  { fn:'RS', name:'Respond', icon:'zap', docs:['Incident Response Policy','Incident Response Procedure'], q:[
    ['RS.MA-01','The incident response plan is executed in coordination with relevant third parties.'],
    ['RS.AN-03','Analysis is performed to establish what occurred and the root cause of the incident.'],
    ['RS.MI-01','Incidents are contained to limit their impact on operations.'],
  ]},
  { fn:'RC', name:'Recover', icon:'refresh', docs:['Business Continuity & Recovery Policy','Business Continuity & Recovery Testing Procedure'], q:[
    ['RC.RP-01','The recovery portion of the incident response plan is executed once initiated.'],
    ['RC.RP-05','The integrity of restored assets is verified and normal operating status is confirmed.'],
    ['RC.CO-03','Recovery activities and progress are communicated to designated internal and external stakeholders.'],
  ]},
];

const NIST_TIER_LABELS = { tier1:'Tier 1 · Partial', tier2:'Tier 2 · Risk Informed', tier3:'Tier 3 · Repeatable', tier4:'Tier 4 · Adaptive' };

function nSectionsForTier(tier) {
  // All 6 functions are always assessed; tier shapes reco but not sections.
  const lv = (tier==='tier1'||tier==='tier2'||tier==='tier3'||tier==='tier4') ? tier : 'tier3';
  const grp = NIST_TIER_LABELS[lv];
  return NIST_Q.map(f=>({ fn:f.fn, theme:f.fn+' · '+f.name, group:grp, icon:f.icon, docs:f.docs, controls:N_FN_COUNTS[f.fn]||10, q:f.q }));
}

const NOPTIONS = [['Not started',0],['Partial',1],['Largely',2],['Fully',3]];
const NBANDS = [
  [0,'Initial',GV.orange,'Foundational cybersecurity practices are largely absent — start with Govern and Identify.'],
  [40,'Developing',GV.orange,'Some practices exist but the program is not consistently applied across the organization.'],
  [60,'Repeatable',GV.purple,'Formal, approved practices are in place — focus on closing the weaker functions.'],
  [80,'Adaptive',GV.purple,'Strong posture — refine evidence, expand monitoring, and optimize continuously.'],
];
const nBandFor = pct=>{ let b=NBANDS[0]; NBANDS.forEach(x=>{ if(pct>=x[0]) b=x; }); return b; };

function nCompute(answers, sections, tier) {
  const secs=sections||nSectionsForTier('tier3');
  const themes=secs.map((t,ti)=>{ const max=t.q.length*3; let sum=0; t.q.forEach((_,qi)=>{ sum+=(answers[ti+'-'+qi]||0); }); const pct=Math.round((sum/max)*100); return {fn:t.fn,theme:t.theme,group:t.group,icon:t.icon,docs:t.docs,controls:t.controls,pct,gaps:Math.round((1-pct/100)*t.controls)}; });
  const overall=themes.length?Math.round(themes.reduce((a,t)=>a+t.pct,0)/themes.length):0;
  const totalControls=secs.reduce((a,t)=>a+t.controls,0);
  const gaps=themes.reduce((a,t)=>a+t.gaps,0);
  return { themes, overall, gaps, totalControls, tier:(secs[0]&&secs[0].group)||NIST_TIER_LABELS.tier3, band:nBandFor(overall) };
}

/* ── SEGMENTED ────────────────────────────────────────────── */
const NSegmented = ({ value, onChange }) => (
  <div style={{display:'grid',gridTemplateColumns:'repeat(4,1fr)',gap:6}}>
    {NOPTIONS.map(([label,val])=>{ const on=value===val; return <button key={val} type="button" onClick={()=>onChange(val)} style={{fontFamily:GFT,fontSize:13,fontWeight:700,padding:'10px 6px',cursor:'pointer',textAlign:'center',background:on?GV.purple:'#fff',color:on?'#fff':GV.g600,border:`1.5px solid ${on?GV.purple:GV.g200}`,transition:'all 120ms'}}>{label}</button>; })}
  </div>
);

/* ── QUIZ ────────────────────────────────────────────────── */
const EvalQuizNIST = ({ onComplete, onExit, tier, initialAnswers, initialStep, onProgress }) => {
  const sections = React.useMemo(()=>nSectionsForTier(tier),[tier]);
  const [step,setStep] = React.useState(()=>Math.min(Math.max(initialStep||0,0),sections.length-1));
  const [answers,setAnswers] = React.useState(()=>initialAnswers||{});
  const total=sections.length; const cur=sections[step];
  const report=(a,s)=>{ if(onProgress) onProgress(a,s); };
  const set=(qi,v)=>setAnswers(a=>{ const na={...a,[step+'-'+qi]:v}; report(na,step); return na; });
  const stepDone=cur.q.every((_,qi)=>answers[step+'-'+qi]!==undefined);
  const answeredCount=Object.keys(answers).length;
  const totalQ=sections.reduce((a,t)=>a+t.q.length,0);
  const progress=Math.round((answeredCount/totalQ)*100);
  const next=()=>{ if(step<total-1){const ns=step+1;setStep(ns);report(answers,ns);window.scrollTo({top:0});}else{onComplete(nCompute(answers,sections,tier));} };
  const back=()=>{ if(step>0){const ns=step-1;setStep(ns);report(answers,ns);window.scrollTo({top:0});}else{onExit();} };
  return (
    <window.Section bg={GV.g50} pad="48px 0 96px">
      <div style={{maxWidth:820,margin:'0 auto'}}>
        <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:12}}>
          <span style={{fontSize:12,fontWeight:700,letterSpacing:'0.08em',textTransform:'uppercase',color:GV.g400}}>Function {step+1} of {total}</span>
          <span style={{fontSize:12,fontWeight:700,color:GV.purple,fontFamily:"'JetBrains Mono',monospace"}}>{progress}% complete</span>
        </div>
        <div style={{height:6,background:GV.g200,marginBottom:28,overflow:'hidden'}}><div style={{width:progress+'%',height:'100%',background:GV.purple,transition:'width 200ms'}}></div></div>
        <div style={{background:'#fff',border:`1px solid ${GV.g200}`,padding:'32px 36px 36px'}}>
          <div style={{display:'flex',alignItems:'center',gap:12,marginBottom:8}}>
            <div style={{width:42,height:42,background:GV.purpleSubtle,color:GV.purple,display:'flex',alignItems:'center',justifyContent:'center'}}><window.Icon name={cur.icon} size={22} /></div>
            <div>
              <div style={{fontSize:11,fontWeight:700,letterSpacing:'0.08em',textTransform:'uppercase',color:GV.g400}}>{cur.group}</div>
              <h2 style={{fontSize:22,fontWeight:800,color:GV.black,margin:0,fontFamily:GFT,letterSpacing:'-0.02em'}}>{cur.theme}</h2>
            </div>
          </div>
          <p style={{fontSize:13.5,color:GV.g500,margin:'0 0 24px',lineHeight:1.55}}>For each statement, choose how completely it reflects your organization today. Each maps to a specific NIST CSF v2.0 subcategory.</p>
          <div style={{display:'flex',flexDirection:'column',gap:22}}>
            {cur.q.map(([id,text],qi)=>(
              <div key={qi} style={{borderTop:qi?`1px solid ${GV.g100}`:'none',paddingTop:qi?22:0}}>
                <div style={{display:'flex',gap:12,marginBottom:12}}>
                  <span style={{fontFamily:"'JetBrains Mono',monospace",fontSize:12,fontWeight:700,color:GV.orange,flexShrink:0,marginTop:2,minWidth:72}}>{id}</span>
                  <p style={{fontSize:15.5,fontWeight:600,color:GV.g800,margin:0,lineHeight:1.5}}>{text}</p>
                </div>
                <div style={{paddingLeft:84}}><NSegmented value={answers[step+'-'+qi]} onChange={v=>set(qi,v)} /></div>
              </div>
            ))}
          </div>
        </div>
        <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginTop:24}}>
          <window.Btn kind="ghost" onClick={back}>{step===0?'Exit':'Back'}</window.Btn>
          <window.Btn kind="primary" onClick={next} style={{opacity:stepDone?1:0.45,pointerEvents:stepDone?'auto':'none'}}>{step===total-1?'See my results':'Next function'} <window.Icon name="arrow" size={16} color="#fff" /></window.Btn>
        </div>
        {!stepDone&&<p style={{textAlign:'right',fontSize:12.5,color:GV.g400,marginTop:10}}>Answer all {cur.q.length} statements to continue.</p>}
        <div style={{display:'flex',alignItems:'center',gap:8,marginTop:14,fontSize:12.5,color:GV.g400}}><window.Icon name="refresh" size={14} color={GV.g400} /> Your progress is saved automatically — you can leave and resume later.</div>
      </div>
    </window.Section>
  );
};

/* ── RESULTS ─────────────────────────────────────────────── */
const NDonut = ({ pct }) => (
  <div style={{width:168,height:168,borderRadius:'50%',background:`conic-gradient(#fff 0% ${pct}%, rgba(255,255,255,0.2) ${pct}% 100%)`,display:'flex',alignItems:'center',justifyContent:'center',flexShrink:0}}>
    <div style={{width:128,height:128,borderRadius:'50%',background:'#fff',display:'flex',flexDirection:'column',alignItems:'center',justifyContent:'center'}}>
      <span style={{fontSize:48,fontWeight:800,color:GV.black,fontFamily:GFT,letterSpacing:'-0.03em',lineHeight:1}}>{pct}</span>
      <span style={{fontSize:11,fontWeight:700,letterSpacing:'0.08em',textTransform:'uppercase',color:GV.g400,marginTop:4}}>/ 100</span>
    </div>
  </div>
);

const EvalResultsNIST = ({ results, user, onNav, onRetake }) => {
  const { themes, overall, gaps, band, totalControls, tier } = results;
  const [,label,,bandDesc] = band;
  const isHighTier = /Tier 3|Tier 4/.test(tier||'');
  const sorted = [...themes].sort((a,b)=>a.pct-b.pct);
  const focus = sorted.filter(t=>t.pct<80);
  const MODULES = window.TK_NIST.QUOTE_MODULES;
  const reco = new Set(['tailor']);
  if (overall<80) reco.add('guidance');
  if (overall<60) { reco.add('impl'); reco.add('profile'); reco.add('gap'); }
  if (isHighTier) reco.add('mapping');
  themes.forEach(t=>{ if(t.pct<60&&t.fn==='DE') reco.add('monitor'); });
  const recoModules = MODULES.filter(m=>reco.has(m.id));
  const goBuild = ()=>{ try{localStorage.setItem('verigo_reco_nist',JSON.stringify([...reco]));}catch(e){} onNav('checkout'); };
  return (
    <div>
      <section style={{background:GV.purpleDark,position:'relative',overflow:'hidden'}}>
        <window.GeoWatermark color={GV.orange} style={{top:-40,right:40,width:360,height:340,opacity:0.16}} />
        <div style={{position:'relative',zIndex:1,maxWidth:GMW,margin:'0 auto',padding:'56px 32px 60px'}}>
          <div style={{display:'inline-flex',alignItems:'center',gap:8,background:'rgba(255,255,255,0.12)',color:'#fff',fontSize:11,fontWeight:700,letterSpacing:'0.1em',textTransform:'uppercase',padding:'6px 13px',marginBottom:24}}><window.Icon name="gauge" size={14} color="#fff" /> Your readiness report · {tier}</div>
          <div style={{display:'grid',gridTemplateColumns:'168px 1fr',gap:40,alignItems:'center'}}>
            <NDonut pct={overall} />
            <div>
              <div style={{fontSize:13,fontWeight:700,letterSpacing:'0.08em',textTransform:'uppercase',color:'rgba(255,255,255,0.6)',marginBottom:8}}>Overall maturity · {label}</div>
              <h1 className="vg-hero-title" style={{fontSize:38,fontWeight:800,color:'#fff',letterSpacing:'-0.03em',lineHeight:1.1,margin:'0 0 14px',fontFamily:GFT}}>{overall>=80?"You're approaching your target tier.":overall>=60?"A solid base, with clear gaps to close.":"There's real groundwork to do first."}</h1>
              <p style={{fontSize:16,color:'rgba(255,255,255,0.7)',lineHeight:1.6,margin:0,maxWidth:600}}>{bandDesc} We estimate <strong style={{color:'#fff'}}>~{gaps} of {totalControls} subcategories</strong> need attention across your profile.{user&&user.company?' Prepared for '+user.company:''}</p>
            </div>
          </div>
        </div>
      </section>
      <window.Section bg="#fff" pad="72px 0 64px">
        <window.SectionHeader overline="By CSF function" align="left" title="Where you stand across the six functions" sub="Your maturity in each NIST CSF v2.0 function, scored from your answers." maxSub={620} />
        <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:'28px 56px'}}>
          {themes.map((t,i)=>{ const c=t.pct<60?GV.orange:GV.purple; return(
            <div key={i}>
              <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:8}}>
                <span style={{display:'flex',alignItems:'center',gap:10,fontSize:14.5,fontWeight:700,color:GV.g800,fontFamily:GFT}}><window.Icon name={t.icon} size={18} color={GV.purple} />{t.theme}</span>
                <span style={{fontSize:15,fontWeight:800,color:c,fontFamily:"'JetBrains Mono',monospace"}}>{t.pct}%</span>
              </div>
              <div style={{height:9,background:GV.g100,overflow:'hidden'}}><div style={{width:t.pct+'%',height:'100%',background:c,transition:'width 400ms'}}></div></div>
              <div style={{fontSize:12.5,color:GV.g500,marginTop:7}}>~{t.gaps} of {t.controls} subcategories need attention</div>
            </div>
          ); })}
        </div>
      </window.Section>
      <window.Section bg={GV.g50} pad="64px 0 72px">
        <window.SectionHeader overline="Your next steps" align="left" title="A plan mapped straight to the toolkit" sub="Start with your weakest functions. Each links to the toolkit documents that close the gap fastest." maxSub={640} />
        <div style={{display:'flex',flexDirection:'column',gap:14}}>
          {focus.length===0&&(<div style={{background:'#fff',border:`1px solid ${GV.g200}`,padding:'24px 28px',display:'flex',alignItems:'center',gap:14}}><window.Icon name="check" size={24} color={GV.purple} /><div style={{fontSize:15.5,fontWeight:600,color:GV.g800}}>Every function scored 80%+ — you're in strong shape. A practitioner can validate evidence and optimize your target profile.</div></div>)}
          {focus.map((t,i)=>(
            <div key={i} style={{background:'#fff',border:`1px solid ${GV.g200}`,padding:'24px 28px',display:'grid',gridTemplateColumns:'44px 1fr auto',gap:20,alignItems:'center'}}>
              <div style={{width:44,height:44,background:GV.purpleSubtle,color:GV.purple,display:'flex',alignItems:'center',justifyContent:'center',fontFamily:"'JetBrains Mono',monospace",fontSize:16,fontWeight:800}}>{i+1}</div>
              <div>
                <div style={{display:'flex',alignItems:'center',gap:10,marginBottom:6}}>
                  <h3 style={{fontSize:16.5,fontWeight:700,color:GV.black,margin:0,fontFamily:GFT}}>{t.theme}</h3>
                  <span style={{fontSize:11,fontWeight:700,padding:'3px 9px',background:t.pct<60?GV.orangeSubtle:GV.purpleSubtle,color:t.pct<60?GV.orange:GV.purple,fontFamily:"'JetBrains Mono',monospace"}}>{t.pct}%</span>
                </div>
                <div style={{display:'flex',flexWrap:'wrap',gap:8}}>{t.docs.map((d,di)=>(<span key={di} style={{display:'inline-flex',alignItems:'center',gap:7,fontSize:13,fontWeight:600,color:GV.g700,background:GV.g50,border:`1px solid ${GV.g200}`,padding:'6px 11px'}}><window.Icon name="doc" size={14} color={GV.purple} />{d}</span>))}</div>
              </div>
              <window.Btn kind="ghostBrand" onClick={()=>onNav('toolkit:nist')} style={{whiteSpace:'nowrap'}}>Open toolkit <window.Icon name="arrow" size={15} color={GV.purple} /></window.Btn>
            </div>
          ))}
        </div>
        <div style={{display:'flex',gap:12,flexWrap:'wrap',marginTop:32}}>
          <window.Btn kind="primary" onClick={()=>window.EVAL_NIST.generateEvalPDF(results,user)}><window.Icon name="doc" size={16} color="#fff" /> Download my results (PDF)</window.Btn>
          <window.Btn kind="ghost" onClick={onRetake}>Retake the evaluation</window.Btn>
        </div>
      </window.Section>
      <window.Section bg="#fff" pad="72px 0 64px">
        <window.SectionHeader overline="Recommended next step" align="left" title="Build a package that closes your gaps" sub="Based on your results we've pre-selected the options most likely to close your gaps fastest." maxSub={680} />
        <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:14,marginBottom:28}}>
          {recoModules.map((m,i)=>(<div key={i} style={{display:'flex',gap:14,alignItems:'flex-start',border:`1px solid ${GV.g200}`,padding:'18px 20px'}}><div style={{width:38,height:38,background:GV.purpleSubtle,color:GV.purple,display:'flex',alignItems:'center',justifyContent:'center',flexShrink:0}}><window.Icon name="check" size={20} color={GV.purple} /></div><div><div style={{fontSize:15,fontWeight:700,color:GV.black,fontFamily:GFT}}>{m.name}</div><div style={{fontSize:13,color:GV.g500,lineHeight:1.5,marginTop:3}}>{m.desc}</div></div></div>))}
        </div>
        <div style={{display:'flex',alignItems:'center',gap:16,flexWrap:'wrap'}}>
          <window.Btn kind="primary" onClick={goBuild}>Build my custom package <window.Icon name="arrow" size={16} color="#fff" /></window.Btn>
          <span style={{fontSize:13,color:GV.g500}}>Pick your options, see the price, then download a custom quote.</span>
        </div>
      </window.Section>
      <window.Section bg={GV.g50} pad="64px 0 0">
        <window.CTABand overline="Turn the score into a target profile" title="Have a practitioner walk you through your results" body="Your readiness report is a starting point. Our team can validate every gap, define your target profile, and build the implementation roadmap." primary="Talk to a practitioner" onNav={onNav} dest="contact" />
      </window.Section>
    </div>
  );
};

/* ── RESULTS PDF ──────────────────────────────────────────── */
function genEvalPDFNIST(results, user) {
  const lib=window.jspdf; if(!lib||!lib.jsPDF){alert('PDF engine is still loading.');return;}
  const {themes,overall,gaps,band,totalControls,tier}=results;
  const doc=new lib.jsPDF({unit:'pt',format:'a4'}); const W=doc.internal.pageSize.getWidth(); const H=doc.internal.pageSize.getHeight(); const M=50;
  const PURPLE=[91,46,145],ORANGE=[232,98,42],INK=[30,30,46],GREY=[120,120,134]; let y=100;
  doc.setFillColor(...PURPLE);doc.rect(0,0,W,70,'F');doc.setFillColor(...ORANGE);doc.rect(W-M-11,28,11,11,'F');doc.setTextColor(255,255,255);doc.setFont('helvetica','bold');doc.setFontSize(15);doc.text('VERIGO GLOBAL',M,33);doc.setFont('helvetica','normal');doc.setFontSize(8.5);doc.setTextColor(214,204,232);doc.text('Compliance by Design',M,49);doc.setTextColor(255,255,255);doc.setFontSize(8.5);doc.text('NIST CSF v2.0',W-M-20,35,{align:'right'});
  doc.setTextColor(...INK);doc.setFont('helvetica','bold');doc.setFontSize(21);doc.text('NIST CSF v2.0 Readiness Report',M,y);y+=12;doc.setDrawColor(...ORANGE);doc.setLineWidth(2.5);doc.line(M,y,M+54,y);y+=16;doc.setFont('helvetica','normal');doc.setFontSize(10);doc.setTextColor(...GREY);doc.text(String(tier||''),M,y);y+=18;
  doc.setFont('helvetica','bold');doc.setFontSize(40);doc.setTextColor(...PURPLE);doc.text(String(overall),M,y+14);doc.setFontSize(11);doc.setTextColor(...GREY);doc.setFont('helvetica','normal');doc.text('/ 100',M+58,y+14);doc.setFont('helvetica','bold');doc.setFontSize(13);doc.setTextColor(...INK);doc.text('Overall maturity: '+band[1],M+130,y-2);doc.setFont('helvetica','normal');doc.setFontSize(10);doc.setTextColor(...GREY);doc.splitTextToSize('~'+gaps+' of '+(totalControls||90)+' subcategories need attention. '+band[3],W-M-(M+130)).forEach((ln,i)=>doc.text(ln,M+130,y+14+i*13));y+=56;
  if(user&&(user.company||user.name)){doc.setDrawColor(224,224,232);doc.setLineWidth(0.5);doc.line(M,y,W-M,y);y+=16;doc.setFontSize(9);doc.setTextColor(...PURPLE);doc.setFont('helvetica','bold');doc.text('Prepared for '+(user.company||user.name),M,y);doc.setFont('helvetica','normal');doc.setTextColor(...GREY);doc.text(new Date().toLocaleDateString('en-US',{year:'numeric',month:'long',day:'numeric'}),W-M,y,{align:'right'});y+=22;}
  doc.setFont('helvetica','bold');doc.setFontSize(12.5);doc.setTextColor(...PURPLE);doc.text('Maturity by CSF function',M,y);y+=6;doc.setDrawColor(...PURPLE);doc.setLineWidth(0.8);doc.line(M,y,W-M,y);y+=20;
  const barX=M+200,barW=W-M-barX;
  themes.forEach(t=>{if(y>H-70){doc.addPage();y=60;}doc.setFont('helvetica','bold');doc.setFontSize(10);doc.setTextColor(...INK);doc.text(t.theme,M,y+3);doc.setFillColor(237,237,245);doc.rect(barX,y-7,barW,10,'F');const col=t.pct<60?ORANGE:PURPLE;doc.setFillColor(...col);doc.rect(barX,y-7,barW*(t.pct/100),10,'F');doc.setFont('helvetica','bold');doc.setFontSize(10);doc.setTextColor(...col);doc.text(t.pct+'%',W-M,y+3,{align:'right'});y+=26;});
  const focus=[...themes].sort((a,b)=>a.pct-b.pct).filter(t=>t.pct<80);
  if(focus.length){if(y>H-90){doc.addPage();y=60;}doc.setFont('helvetica','bold');doc.setFontSize(12.5);doc.setTextColor(...PURPLE);doc.text('Recommended next steps',M,y);y+=6;doc.setDrawColor(...PURPLE);doc.setLineWidth(0.8);doc.line(M,y,W-M,y);y+=18;focus.forEach((t,i)=>{if(y>H-90){doc.addPage();y=60;}doc.setFont('helvetica','bold');doc.setFontSize(10.5);doc.setTextColor(...INK);doc.text((i+1)+'. '+t.theme+' ('+t.pct+'%)',M,y);y+=14;doc.setFont('helvetica','normal');doc.setFontSize(9.5);doc.setTextColor(...GREY);doc.splitTextToSize('Toolkit documents: '+t.docs.join(', '),W-2*M-14).forEach(ln=>{doc.text(ln,M+14,y);y+=12;});y+=8;});}
  const total=doc.internal.getNumberOfPages();for(let i=1;i<=total;i++){doc.setPage(i);doc.setDrawColor(224,224,232);doc.setLineWidth(0.5);doc.line(M,H-38,W-M,H-38);doc.setFont('helvetica','normal');doc.setFontSize(8);doc.setTextColor(150,150,160);doc.text('© 2026 Verigo Global · Readiness self-assessment — indicative, not a formal assessment',M,H-24);doc.text(i+' / '+total,W-M,H-24,{align:'right'});}
  doc.save('Verigo-NIST-Readiness-Report.pdf');
}

window.EVAL_NIST = { QUESTIONS:NIST_Q, sectionsForTier:nSectionsForTier, computeResults:nCompute, EvalQuiz:EvalQuizNIST, EvalResults:EvalResultsNIST, generateEvalPDF:genEvalPDFNIST };
Object.assign(window, { EvalQuizNIST, EvalResultsNIST });
