// evaluation-cmmc-engine.jsx — Verigo Global: CMMC 2.0 readiness evaluation engine
// The CMMC Level chosen in scope decides which domains/questions are assessed.
// Exposes window.EVAL_CMMC
const { V: GV, MAXW: GMW, FONT: GFT } = window;

/* ── QUESTION BANK — per domain, with Level 1 and Level 2 question sets ─── */
// Each question is [practice id, statement] so every answer maps to a specific 800-171 practice.
const CQUESTIONS = [
  { code: 'AC', domain: 'Access Control', icon: 'lock', l1: 4, l2: 22,
    docs: ['Access Control Policy', 'Account Management Procedure'],
    qL1: [
      ['3.1.1', 'System access is limited to authorized users, processes, and devices.'],
      ['3.1.2', 'Access is limited to the transactions and functions users are permitted.'],
      ['3.1.22', 'Information posted on publicly accessible systems is controlled.'],
    ],
    qL2: [
      ['3.1.1', 'System access is limited to authorized users, processes, and devices.'],
      ['3.1.5', 'Least privilege and separation of duties are enforced for accounts.'],
      ['3.1.12', 'Remote access sessions are authorized, monitored, and encrypted.'],
    ] },
  { code: 'AT', domain: 'Awareness & Training', icon: 'users', l1: 0, l2: 3,
    docs: ['Awareness & Training Policy', 'Security Awareness & Training Procedure'],
    qL1: [],
    qL2: [
      ['3.2.1', 'Personnel receive security awareness training on risks and policies.'],
      ['3.2.2', 'Staff are trained for their assigned information-security duties.'],
      ['3.2.3', 'Insider-threat awareness is included in training.'],
    ] },
  { code: 'AU', domain: 'Audit & Accountability', icon: 'clipboard', l1: 0, l2: 9,
    docs: ['Audit & Accountability Policy', 'Audit Log Review Procedure'],
    qL1: [],
    qL2: [
      ['3.3.1', 'Audit logs are created and retained to support monitoring and investigation.'],
      ['3.3.2', 'Actions are traceable to individual users for accountability.'],
      ['3.3.5', 'Audit records are reviewed, analyzed, and correlated for issues.'],
    ] },
  { code: 'CM', domain: 'Configuration Management', icon: 'cpu', l1: 0, l2: 9,
    docs: ['Configuration Management Policy', 'Configuration Baseline & Change Procedure'],
    qL1: [],
    qL2: [
      ['3.4.1', 'Baseline configurations of systems are established and maintained.'],
      ['3.4.2', 'Security configuration settings are enforced on system components.'],
      ['3.4.3', 'Changes are tracked, reviewed, approved, and analyzed for impact.'],
    ] },
  { code: 'IA', domain: 'Identification & Authentication', icon: 'shield', l1: 2, l2: 11,
    docs: ['Identification & Authentication Policy', 'FIPS-Validated Cryptography Procedure'],
    qL1: [
      ['3.5.1', 'Users and devices are identified before access is granted.'],
      ['3.5.2', 'The identity of users and devices is authenticated.'],
    ],
    qL2: [
      ['3.5.1', 'Users, processes, and devices are uniquely identified.'],
      ['3.5.3', 'Multifactor authentication is used for network and privileged access.'],
      ['3.5.10', 'Passwords are cryptographically protected in storage and transit.'],
    ] },
  { code: 'IR', domain: 'Incident Response', icon: 'zap', l1: 0, l2: 3,
    docs: ['Incident Response Policy', 'Incident Response Procedure'],
    qL1: [],
    qL2: [
      ['3.6.1', 'An incident-handling capability covering prep, detection, and recovery exists.'],
      ['3.6.2', 'Incidents are tracked, documented, and reported to authorities.'],
      ['3.6.3', 'The incident response capability is tested.'],
    ] },
  { code: 'MA', domain: 'Maintenance', icon: 'refresh', l1: 0, l2: 6,
    docs: ['Maintenance Policy', 'Maintenance Logging Procedure'],
    qL1: [],
    qL2: [
      ['3.7.1', 'System maintenance is performed and controlled.'],
      ['3.7.4', 'Media used for maintenance is checked for malicious code.'],
      ['3.7.5', 'Nonlocal maintenance sessions require multifactor authentication.'],
    ] },
  { code: 'MP', domain: 'Media Protection', icon: 'file', l1: 1, l2: 9,
    docs: ['Media Protection Policy', 'Media Sanitization & Disposal Procedure'],
    qL1: [
      ['3.8.3', 'Media containing FCI is sanitized or destroyed before disposal or reuse.'],
      ['3.8.1', 'Media containing FCI is physically controlled and protected.'],
    ],
    qL2: [
      ['3.8.1', 'System media containing CUI is protected and access-controlled.'],
      ['3.8.3', 'Media is sanitized or destroyed before disposal or reuse.'],
      ['3.8.6', 'CUI on transported media is cryptographically protected.'],
    ] },
  { code: 'PS', domain: 'Personnel Security', icon: 'briefcase', l1: 0, l2: 2,
    docs: ['Personnel Security Policy', 'Access Provisioning & Deprovisioning Procedure'],
    qL1: [],
    qL2: [
      ['3.9.1', 'Individuals are screened before being granted access to CUI.'],
      ['3.9.2', 'CUI is protected during personnel actions such as termination and transfer.'],
    ] },
  { code: 'PE', domain: 'Physical Protection', icon: 'building', l1: 4, l2: 6,
    docs: ['Physical Protection Policy', 'Maintenance Logging Procedure'],
    qL1: [
      ['3.10.1', 'Physical access to systems and equipment is limited to authorized staff.'],
      ['3.10.3', 'Visitors are escorted and monitored.'],
      ['3.10.5', 'Physical access devices (keys, badges) are controlled and managed.'],
    ],
    qL2: [
      ['3.10.1', 'Physical access to systems and equipment is limited to authorized individuals.'],
      ['3.10.3', 'Visitors are escorted and their activity is monitored.'],
      ['3.10.4', 'Audit logs of physical access are maintained.'],
    ] },
  { code: 'RA', domain: 'Risk Assessment', icon: 'target', l1: 0, l2: 3,
    docs: ['Risk Assessment Policy', 'Vulnerability Scanning & Remediation Procedure'],
    qL1: [],
    qL2: [
      ['3.11.1', 'Risk to operations and CUI is assessed periodically.'],
      ['3.11.2', 'Systems are scanned for vulnerabilities on a defined cadence.'],
      ['3.11.3', 'Vulnerabilities are remediated in line with risk assessments.'],
    ] },
  { code: 'CA', domain: 'Security Assessment', icon: 'search', l1: 0, l2: 4,
    docs: ['Security Assessment Policy', 'System Security Plan (SSP) Procedure', 'POA&M Management Procedure'],
    qL1: [],
    qL2: [
      ['3.12.1', 'Security controls are assessed periodically for effectiveness.'],
      ['3.12.2', 'A Plan of Action & Milestones (POA&M) tracks remediation.'],
      ['3.12.4', 'A System Security Plan (SSP) is developed, maintained, and current.'],
    ] },
  { code: 'SC', domain: 'System & Communications Protection', icon: 'network', l1: 2, l2: 16,
    docs: ['System & Communications Protection Policy', 'FIPS-Validated Cryptography Procedure'],
    qL1: [
      ['3.13.1', 'Communications are monitored and controlled at external boundaries.'],
      ['3.13.5', 'Publicly accessible system components are separated on subnetworks.'],
    ],
    qL2: [
      ['3.13.1', 'Communications are monitored and controlled at system boundaries.'],
      ['3.13.8', 'Cryptographic mechanisms protect CUI in transit.'],
      ['3.13.11', 'FIPS-validated cryptography is employed to protect CUI.'],
    ] },
  { code: 'SI', domain: 'System & Information Integrity', icon: 'activity', l1: 4, l2: 7,
    docs: ['System & Information Integrity Policy', 'Vulnerability Scanning & Remediation Procedure'],
    qL1: [
      ['3.14.1', 'System flaws are identified and corrected in a timely manner.'],
      ['3.14.2', 'Protection from malicious code is provided.'],
      ['3.14.5', 'Periodic and real-time scans are performed.'],
    ],
    qL2: [
      ['3.14.1', 'System flaws are identified, reported, and corrected in a timely manner.'],
      ['3.14.2', 'Malicious-code protection is deployed at appropriate locations.'],
      ['3.14.5', 'Periodic and real-time scans of the system are performed.'],
    ] },
];

// Level 3 adds a subset of enhanced NIST SP 800-172 requirements.
const C_ENHANCED = { code: 'EN', domain: 'Enhanced Protection (NIST SP 800-172)', icon: 'shield', controls: 24,
  docs: ['Risk Assessment Policy', 'System & Communications Protection Policy'],
  q: [
    ['3.x', 'Advanced threat-hunting and detection operate continuously across the environment.'],
    ['3.x', 'Dual authorization and enhanced access controls protect high-value CUI.'],
    ['3.x', 'Supply-chain risk and component authenticity controls are applied to critical assets.'],
  ] };

const CLEVEL_LABEL = { 1: 'Level 1 · Foundational', 2: 'Level 2 · Advanced', 3: 'Level 3 · Expert' };

// Build the in-scope sections for the chosen level.
function cSectionsForLevel(level) {
  const lv = Number(level) || 2;
  const grp = CLEVEL_LABEL[lv] || CLEVEL_LABEL[2];
  if (lv === 1) {
    return CQUESTIONS.filter((d) => d.qL1 && d.qL1.length).map((d) => ({ code: d.code, theme: d.code + ' · ' + d.domain, group: grp, icon: d.icon, docs: d.docs, controls: d.l1, q: d.qL1 }));
  }
  const base = CQUESTIONS.map((d) => ({ code: d.code, theme: d.code + ' · ' + d.domain, group: grp, icon: d.icon, docs: d.docs, controls: d.l2, q: d.qL2 }));
  if (lv === 3) base.push({ code: C_ENHANCED.code, theme: C_ENHANCED.code + ' · ' + C_ENHANCED.domain, group: grp, icon: C_ENHANCED.icon, docs: C_ENHANCED.docs, controls: C_ENHANCED.controls, q: C_ENHANCED.q });
  return base;
}

const COPTIONS = [
  ['Not started', 0],
  ['Partial', 1],
  ['Largely', 2],
  ['Fully', 3],
];

const CBANDS = [
  [0, 'Initial', GV.orange, 'Foundations are largely missing — start with the core policy and SSP set.'],
  [40, 'Developing', GV.orange, 'Key practices exist, but real gaps remain before an assessment is viable.'],
  [60, 'Established', GV.purple, 'A working control environment is in place — focus on closing the weaker domains.'],
  [80, 'Optimized', GV.purple, 'Strong posture — finalize evidence and the SSP, and keep it continuous.'],
];
const cBandFor = (pct) => { let b = CBANDS[0]; CBANDS.forEach((x) => { if (pct >= x[0]) b = x; }); return b; };

function cCompute(answers, sections) {
  const secs = sections || cSectionsForLevel(2);
  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 { theme: t.theme, code: t.code, group: t.group, icon: t.icon, docs: t.docs, controls: t.controls, pct, gaps: Math.round((1 - pct / 100) * t.controls) };
  });
  const totSum = themes.reduce((a, t) => a + (t.pct), 0);
  const overall = themes.length ? Math.round(totSum / themes.length) : 0;
  const gaps = themes.reduce((a, t) => a + t.gaps, 0);
  const totalControls = secs.reduce((a, t) => a + t.controls, 0);
  return { themes, overall, gaps, totalControls, level: (secs[0] && secs[0].group) || CLEVEL_LABEL[2], band: cBandFor(overall) };
}

/* ── SEGMENTED MATURITY CONTROL ──────────────────────────── */
const CSegmented = ({ value, onChange }) => (
  <div className="vg-grid-4" style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 6 }}>
    {COPTIONS.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 EvalQuizCMMC = ({ onComplete, onExit, level, initialAnswers, initialStep, onProgress }) => {
  const sections = React.useMemo(() => cSectionsForLevel(level), [level]);
  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(cCompute(answers, sections)); } };
  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 }}>Domain {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 SP 800-171 practice.</p>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 22 }}>
            {cur.q.map(([code, 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: 42 }}>{code}</span>
                  <p style={{ fontSize: 15.5, fontWeight: 600, color: GV.g800, margin: 0, lineHeight: 1.5 }}>{text}</p>
                </div>
                <div style={{ paddingLeft: 54 }}>
                  <CSegmented 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 domain'} <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 this evaluation later.
        </div>
      </div>
    </window.Section>
  );
};

/* ── RESULTS ─────────────────────────────────────────────── */
const CDonut = ({ pct, color }) => (
  <div style={{ width: 168, height: 168, borderRadius: '50%', background: `conic-gradient(${color} 0% ${pct}%, ${GV.g100} ${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 EvalResultsCMMC = ({ results, user, onNav, onRetake }) => {
  const { themes, overall, gaps, band, totalControls, level } = results;
  const [, label, bandColor, bandDesc] = band;
  const sorted = [...themes].sort((a, b) => a.pct - b.pct);
  const focus = sorted.filter((t) => t.pct < 80);
  const MODULES = window.TK_CMMC.QUOTE_MODULES;
  const isL2plus = /Level 2|Level 3/.test(level || '');
  const reco = new Set(['tailor', 'ssp']);
  if (isL2plus) reco.add('c3pao');
  if (overall < 80) reco.add('guidance');
  if (overall < 60) reco.add('impl');
  themes.forEach((t) => {
    if (t.pct < 60) {
      if (t.code === 'SC' || t.code === 'AC' || t.code === 'IA') reco.add('impl');
      if (t.code === 'CA') reco.add('scoping');
    }
  });
  const recoIds = [...reco];
  const recoModules = MODULES.filter((m) => reco.has(m.id));
  const goBuild = () => { try { localStorage.setItem('verigo_reco_cmmc', JSON.stringify(recoIds)); } catch (e) {} onNav('checkout'); };

  return (
    <div>
      {/* SCORE HEADER */}
      <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 · {level}
          </div>
          <div className="vg-detail-grid" style={{ display: 'grid', gridTemplateColumns: '168px 1fr', gap: 40, alignItems: 'center' }}>
            <CDonut pct={overall} color="#fff" />
            <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, maxWidth: 640 }}>
                {overall >= 80 ? 'You\u2019re close to assessment-ready.' : overall >= 60 ? 'A solid base, with clear gaps to close.' : 'There\u2019s 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} practices</strong> need attention before your assessment.
                {user && user.company ? ` Prepared for ${user.company}.` : ''}
              </p>
            </div>
          </div>
        </div>
      </section>

      {/* DOMAIN BREAKDOWN */}
      <window.Section bg="#fff" pad="72px 0 64px">
        <window.SectionHeader overline="By domain" align="left"
          title="Where you stand across the practices"
          sub="Your maturity in each in-scope NIST SP 800-171 domain for your chosen CMMC level, scored from your answers." maxSub={640} />
        <div className="vg-grid-2" 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} practices need attention</div>
              </div>
            );
          })}
        </div>
      </window.Section>

      {/* ACTION PLAN */}
      <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 domains. 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 domain scored 80%+ — you\u2019re in strong shape. A practitioner can help validate evidence, finalize the SSP, and prepare for assessment.</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, letterSpacing: '-0.01em' }}>{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:cmmc')} 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_CMMC.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>

      {/* CUSTOM PACKAGE CTA */}
      <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="There are no fixed bundles. Based on your results we’ve pre-selected the options most likely to close your gaps fastest — add or remove anything, see your price update live, and download a custom quote." maxSub={720} />
        <div className="vg-grid-2" 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', background: '#fff' }}>
              <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 certification"
          title="Have a practitioner walk you through your results"
          body="Your readiness report is a starting point. Our team can validate every gap, build your SSP and POA&M, and prepare you for a C3PAO assessment."
          primary="Talk to a practitioner" onNav={onNav} dest="contact" />
      </window.Section>
    </div>
  );
};

/* ── RESULTS PDF ─────────────────────────────────────────── */
function genEvalPDFCMMC(results, user) {
  const lib = window.jspdf;
  if (!lib || !lib.jsPDF) { alert('PDF engine is still loading — please try again in a moment.'); return; }
  const { themes, overall, gaps, band, totalControls, level } = 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('CMMC 2.0 · NIST SP 800-171', W - M - 20, 35, { align: 'right' });

  doc.setTextColor(...INK); doc.setFont('helvetica', 'bold'); doc.setFontSize(21);
  doc.text('CMMC 2.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(level || ''), 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 || 110) + ' practices need attention before your assessment. ' + 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 domain', M, y); y += 6;
  doc.setDrawColor(...PURPLE); doc.setLineWidth(0.8); doc.line(M, y, W - M, y); y += 20;
  const barX = M + 230, barW = W - M - barX;
  themes.forEach((t) => {
    if (y > H - 70) { doc.addPage(); y = 60; }
    doc.setFont('helvetica', 'bold'); doc.setFontSize(9.5); doc.setTextColor(...INK);
    doc.splitTextToSize(t.theme, 210).forEach((ln, i) => doc.text(ln, M, y + 3 + i * 11));
    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;
  });
  y += 6;

  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 C3PAO assessment', M, H - 24);
    doc.text(i + ' / ' + total, W - M, H - 24, { align: 'right' });
  }
  doc.save('Verigo-CMMC-Readiness-Report.pdf');
}

window.EVAL_CMMC = { QUESTIONS: CQUESTIONS, OPTIONS: COPTIONS, BANDS: CBANDS, sectionsForLevel: cSectionsForLevel, computeResults: cCompute, EvalQuiz: EvalQuizCMMC, EvalResults: EvalResultsCMMC, generateEvalPDF: genEvalPDFCMMC };
Object.assign(window, { EvalQuizCMMC, EvalResultsCMMC });
