// Phishing Simulations — 10 scenarios across healthcare-relevant threat themes.
// UX: campaign picker grid first, then a live inbox view per selected scenario.
// Each scenario is pure data — body text is a renderer function that accepts
// the global `flag()` helper so we can embed tooltipped red-flag spans inline.
function PhishingPage({ onNavigate, toast }) {
  const [activeId, setActiveId] = useState(null);       // which scenario is running
  const [outcome, setOutcome] = useState(null);          // 'report' | 'click' | 'ignore' | null
  const [reportTime, setReportTime] = useState(null);
  const [results, setResults] = useState({});            // scenario.id → 'passed' | 'clicked' | 'ignored'
  const startRef = useRef(Date.now());

  const flag = (text, tooltip) => <span className="flag" data-flag={tooltip}>{text}</span>;

  // -- Scenario catalog -----------------------------------------------------
  const scenarios = [
    {
      id: 'login-alert',
      title: 'Unusual login alert',
      theme: 'Credential phishing',
      audience: 'All clinical',
      difficulty: 'easy',
      summary: 'Classic credential-harvest lure that impersonates the hospital security team.',
      sender: 'St. Luke Security',
      senderEmail: 'security@st-lukes-alert.com',
      senderTooltip: "Real St. Luke's security emails come from @stlukes.org. This has extra dashes.",
      replyTo: 'noreply-security@gmail.com',
      replyTooltip: "Reply-to mismatch — a huge red flag. Legitimate orgs don't route security to Gmail.",
      subject: 'URGENT: Unusual login on your St. Luke account — verify now',
      time: '08:29',
      body: (f) => (<>
        <p style={{margin: '0 0 12px'}}>Elena,</p>
        <p style={{margin: '0 0 12px'}}>
          We detected an {f('unusual login', "Vague 'unusual location' is a scripted lever. Real alerts include specific geolocation + device.")} from <b>Tbilisi, GE</b> on your St. Luke account at 03:12 local time.
        </p>
        <p style={{margin: '0 0 12px'}}>
          If this wasn't you, verify your identity in the next {f('30 minutes', 'Tight deadlines bypass rational thought. Legit processes give you days, not minutes.')} to prevent account suspension. Otherwise, all shift access will be revoked:
        </p>
        <p style={{margin: '0 0 12px'}}>
          {f('➡ Verify account now', 'Hover: https://st-lukes-alert.com/verify?u=epapadaki — mismatched domain. The real portal is sso.stlukes.org.')}
        </p>
        <p style={{margin: '0 0 12px', color: 'var(--ink-3)', fontSize: 12.5}}>
          — St. Luke's Security Operations · Do not reply to this automated message.
        </p>
      </>),
      clickConsequence: { headline: 'Credentials could have been harvested.', body: 'In reality, this would give an attacker access to roughly 2,340 patient records in Cardiology-3B.' },
      ignoreMessage: 'Your silence means a colleague might still fall for it. Always report — the SOC uses every report to build blocklists.',
    },

    {
      id: 'mailbox-quota',
      title: 'Mailbox quota exceeded',
      theme: 'Credential phishing',
      audience: 'All staff',
      difficulty: 'easy',
      summary: "Fake IT warning claiming your mailbox is full and will stop receiving lab results.",
      sender: 'IT Support',
      senderEmail: 'IT-Support@st-|ukes.org',
      senderTooltip: "The pipe character '|' replaces a lowercase 'l'. The real domain is st-lukes.org.",
      subject: 'URGENT: Mailbox quota exceeded — action required in 2 hours',
      time: '06:42',
      body: (f) => (<>
        <p style={{margin: '0 0 12px'}}>Dear Elena,</p>
        <p style={{margin: '0 0 12px'}}>
          Our system has detected your mailbox is {f('99.8% full and will stop receiving patient lab results within the next 2 hours', 'Fake urgency is the #1 phishing lever — real IT gives 24–72h windows, not 2 hours.')}. To prevent interruption in care, please verify your credentials immediately.
        </p>
        <p style={{margin: '0 0 12px'}}>
          {f('👉 Verify mailbox quota here', "Hover reveals 'hxxps://stlukes-verify.cloud-mx[.]com' — not a St. Luke's domain.")}
        </p>
        <p style={{margin: '0 0 12px'}}>
          {f('Failure to verify within 2 hours will result in loss of access and may delay patient care.', 'Pressure + consequences = classic phishing playbook. Real IT communicates through the ticketing portal, not threats.')}
        </p>
        <p style={{margin: 0}}>— IT Support, St. Luke's</p>
      </>),
      clickConsequence: { headline: 'Your password would be captured.', body: 'Attackers chain this to mailbox-access attacks — reading your email, impersonating you, and pivoting to ePHI.' },
      ignoreMessage: "Ignoring buys the attacker time — they'll try the same lure on the next shift.",
    },

    {
      id: 'mri-chief',
      title: "Chief requesting urgent MRI export",
      theme: 'Clinical social engineering',
      audience: 'Radiology · Physicians',
      difficulty: 'medium',
      summary: "Look-alike domain impersonates the Chief of Radiology asking for a patient scan right now.",
      sender: 'Dr. Vakhtang Beridze (Chief Radiology)',
      senderEmail: 'chief.radiology@hosp1tal.com',
      senderTooltip: "The domain swaps an 'i' for a '1' — a typosquat. The real address is @stlukes.org.",
      subject: 'Re: Need Patient 448293 MRI export — do it now',
      time: '07:58',
      body: (f) => (<>
        <p style={{margin: '0 0 12px'}}>Elena,</p>
        <p style={{margin: '0 0 12px'}}>
          Patient {f('448293', "Real requests reference patient identifiers via the clinical portal — never via email in plain text.")} — I'm in surgery in 20 minutes and the consult just called.
        </p>
        <p style={{margin: '0 0 12px'}}>
          Can you {f('export the full DICOM set and email it to my mobile', 'Attachments of PHI to external/mobile addresses are a policy breach regardless of the sender.')} in the next 10 minutes? I know it skips the protocol, but this is time-critical.
        </p>
        <p style={{margin: '0 0 12px'}}>
          Use {f('this drop link if the attachment is too large', "Drop links outside the hospital EHR are a known phish mechanic — they often lead to credential screens.")}.
        </p>
        <p style={{margin: 0}}>— V.B.</p>
      </>),
      clickConsequence: { headline: '2,340 patient records could have been exfiltrated.', body: 'Exporting PHI to an external drop site is a reportable HIPAA breach, regardless of who "asked" for it.' },
      ignoreMessage: "Don't just ignore — attackers pivot to the next radiologist. Report so the SOC can quarantine the campaign.",
    },

    {
      id: 'hr-w2',
      title: 'HR — tax form update for payroll',
      theme: 'HR / payroll phishing',
      audience: 'Admin · HR · All staff',
      difficulty: 'medium',
      summary: 'Fake HR email asking you to re-confirm your tax form details before the next payroll run.',
      sender: 'St. Luke Human Resources',
      senderEmail: 'payroll@stlukes-hr.com',
      senderTooltip: 'The real HR domain is @stlukes.org — this one prepends "hr-" and uses .com.',
      subject: 'Action required: re-confirm your tax form before April payroll',
      time: '09:04',
      body: (f) => (<>
        <p style={{margin: '0 0 12px'}}>Hello Elena,</p>
        <p style={{margin: '0 0 12px'}}>
          As part of our {f('annual payroll reconciliation', 'Real HR gives weeks of notice with calendar reminders — not next-day surprises.')}, we need you to re-confirm your tax form before April 21 to avoid delayed payment.
        </p>
        <p style={{margin: '0 0 12px'}}>
          {f('Verify details in the HR portal', 'The link is stlukes-hr-login[.]com — not the real self-service portal at hr.stlukes.org.')}.
        </p>
        <p style={{margin: '0 0 12px'}}>
          You'll need your SSN and direct-deposit bank details to complete the form.
        </p>
        <p style={{margin: 0}}>— Payroll Operations</p>
      </>),
      clickConsequence: { headline: 'SSN and bank details would be harvested.', body: 'HR phishing is a top source of payroll fraud — attackers redirect salaries or commit identity theft.' },
      ignoreMessage: "If you saw it, others did too. Report so HR can blast a correction notice to the whole staff.",
    },

    {
      id: 'ehr-session',
      title: 'Epic EHR — session expired',
      theme: 'EHR impersonation',
      audience: 'Physicians · Nurses',
      difficulty: 'medium',
      summary: 'Imitation Epic login page reached via an email link — asks you to "re-authenticate".',
      sender: 'Epic Systems (auto)',
      senderEmail: 'notifications@epic-systems-login.com',
      senderTooltip: "Epic never sends login emails from external domains. Real in-product notifications are @epic.com.",
      subject: 'Your clinical session has expired — sign in to continue',
      time: '14:22',
      body: (f) => (<>
        <p style={{margin: '0 0 12px'}}>Elena,</p>
        <p style={{margin: '0 0 12px'}}>
          Your Epic clinical session at {f('St. Luke General (prod-east-3)', 'Real Epic instance names are internal identifiers — never mentioned in user-facing email.')} has expired after 30 minutes of inactivity.
        </p>
        <p style={{margin: '0 0 12px'}}>
          To protect patient data, please {f('sign in again here', 'The link goes to epic-systems-login.com — a fake single-sign-on page. The real SSO is sso.stlukes.org.')} to resume your chart review.
        </p>
        <p style={{margin: '0 0 12px'}}>
          If you do not re-authenticate within 15 minutes, any unsaved notes may be lost.
        </p>
        <p style={{margin: 0, color: 'var(--ink-3)', fontSize: 12.5}}>
          — Epic Systems Automated Notice · Do not reply.
        </p>
      </>),
      clickConsequence: { headline: 'Clinical credentials would be captured.', body: 'With Epic credentials an attacker can read every chart you can — often thousands of patient records.' },
      ignoreMessage: "Report — this is how adversary groups map out clinical staff schedules by who clicks and when.",
    },

    {
      id: 'vendor-invoice',
      title: 'Vendor invoice — updated payment details',
      theme: 'Business email compromise',
      audience: 'Admin · Billing',
      difficulty: 'hard',
      summary: 'A long-time supplier "changed their bank account" and wants the next wire redirected.',
      sender: 'Dr. Mikheil Beridze',
      senderEmail: 'm.beridze@stlukes-finance.com',
      senderTooltip: "The real internal finance domain is @stlukes.org. Notice the extra '-finance' and .com.",
      subject: 'Re: Paravaxis Medical Q2 invoice — updated bank info',
      time: '11:17',
      body: (f) => (<>
        <p style={{margin: '0 0 12px'}}>Hi Elena,</p>
        <p style={{margin: '0 0 12px'}}>
          Finance is cleaning up {f("the Paravaxis Q2 wire — their controller sent updated routing details this morning", "Classic vendor-switch pretext. BEC attackers monitor invoices for months before striking.")}. Please use the new IBAN attached and process as usual.
        </p>
        <p style={{margin: '0 0 12px'}}>
          {f('New IBAN: GE74 CBAS 1234 5678 9010 (Bank of Cyprus, Nicosia branch)', "Route change to a foreign bank in a jurisdiction Paravaxis has never used before. Verify by phone with Paravaxis's known AP contact.")}
        </p>
        <p style={{margin: '0 0 12px'}}>
          {f('Can you push this through today? They are threatening to pause shipments.', "Urgency + vendor-pressure tactic. Real vendors accept a 48h hold for verification.")}
        </p>
        <p style={{margin: 0}}>Thanks — MB</p>
      </>),
      clickConsequence: { headline: 'The hospital could wire €840,000 to an attacker.', body: 'BEC is the #1 cybercrime by dollar value according to the FBI IC3 report. Always verify bank-change requests out-of-band.' },
      ignoreMessage: "Do not ignore — report immediately so Finance can verify with the real Paravaxis AP contact by phone.",
    },

    {
      id: 'conference-abstract',
      title: 'Conference abstract review',
      theme: 'Spearphishing · research',
      audience: 'Research staff',
      difficulty: 'medium',
      summary: 'Ostensibly from a cardiology conference, asking you to review an "abstract" attachment.',
      sender: 'European Cardiology Congress 2026',
      senderEmail: 'abstracts@ecc-2026.review',
      senderTooltip: "Conferences use .org / .eu / country domains — never .review. This TLD is a known phishing marker.",
      subject: 'Action needed: peer-review your assigned abstract (deadline Friday)',
      time: '10:38',
      body: (f) => (<>
        <p style={{margin: '0 0 12px'}}>Dear Dr. Papadaki,</p>
        <p style={{margin: '0 0 12px'}}>
          Thank you for accepting to peer-review for ECC 2026. Your assigned abstract is {f('attached (Abstract_448.docx)', "Unexpected Office documents from external senders are a major malware vector — even if they open normally, they can run macros.")}.
        </p>
        <p style={{margin: '0 0 12px'}}>
          Please submit your score and written feedback by {f('Friday, April 24, 23:59 CET', "Pressure timeline designed to stop you from checking whether you actually agreed to review anything.")} to keep the conference schedule on track.
        </p>
        <p style={{margin: '0 0 12px'}}>
          {f('Scoring portal link (requires your institutional login)', "Portal link hxxps://ecc-2026.review/submit?t= is a credential harvest page styled to look like a conference workflow.")}
        </p>
        <p style={{margin: 0}}>— ECC 2026 Scientific Committee</p>
      </>),
      clickConsequence: { headline: 'Macro-embedded document or fake SSO.', body: 'Spearphishing targets researchers specifically — your institutional login grants access to grants, datasets, and the EHR.' },
      ignoreMessage: "Report — the same lure usually targets several researchers in one department.",
    },

    {
      id: 'device-firmware',
      title: 'Infusion pump firmware update',
      theme: 'Supply chain · medical device',
      audience: 'Biomed · IT / Security',
      difficulty: 'hard',
      summary: '"Urgent" firmware patch for the ward\'s infusion pumps — with a USB driver attached.',
      sender: 'MedTech Biomedical Updates',
      senderEmail: 'updates@medtech-biomedical-patches.net',
      senderTooltip: "MedTech notifications normally come from the vendor portal, not an email with an executable attached.",
      subject: 'CRITICAL: firmware 4.2.1 patch for Alaris-8100 pumps — apply today',
      time: '15:49',
      body: (f) => (<>
        <p style={{margin: '0 0 12px'}}>Biomed team,</p>
        <p style={{margin: '0 0 12px'}}>
          A {f('critical vulnerability', "Real device advisories link to ICS-CERT / MITRE CVE entries — never to a raw attachment.")} was disclosed this morning affecting Alaris 8100-series infusion pumps in your inventory.
        </p>
        <p style={{margin: '0 0 12px'}}>
          Please apply firmware {f('4.2.1 (attached: alaris-update-421.exe)', "A .exe attachment is never the correct path for medical-device firmware. Real updates are signed .bin files loaded via the vendor portal.")} to all pumps on the cardiology and ICU wards by end of shift.
        </p>
        <p style={{margin: '0 0 12px'}}>
          {f('Plug the attached USB installer directly into each pump.', "USB-to-medical-device is a textbook supply-chain attack path (BadUSB, Rubber Ducky).")}
        </p>
        <p style={{margin: 0}}>— MedTech Global Patch Ops</p>
      </>),
      clickConsequence: { headline: 'Malware on clinical workstations and medical devices.', body: 'Compromised infusion pumps can drift dosing, freeze during delivery, or become network pivots — this is a patient-safety event.' },
      ignoreMessage: 'Report immediately. Biomed needs to coordinate with the real vendor before anyone acts on the email.',
    },

    {
      id: 'covid-roster',
      title: 'Occupational Health — booster roster',
      theme: 'Topical lure',
      audience: 'All clinical',
      difficulty: 'easy',
      summary: 'Asks you to confirm your vaccination booster slot by "logging into the portal".',
      sender: 'Occupational Health',
      senderEmail: 'occhealth@stlukes-bookings.co',
      senderTooltip: "Occ Health sits on the St. Luke intranet, never on an external .co domain.",
      subject: 'Your flu + COVID booster slot is on the roster — confirm by Thursday',
      time: '13:11',
      body: (f) => (<>
        <p style={{margin: '0 0 12px'}}>Elena,</p>
        <p style={{margin: '0 0 12px'}}>
          You've been {f('added to Thursday\'s 10:40 slot', 'Topical lures rely on things you\'re expecting anyway — flu/COVID boosters, training updates, payroll cycles.')} for the annual booster clinic.
        </p>
        <p style={{margin: '0 0 12px'}}>
          Please {f('confirm or reschedule via the Occ Health portal', 'Portal link is stlukes-bookings[.]co — an external host, not the internal intranet where Occ Health actually lives.')} before end-of-day Thursday.
        </p>
        <p style={{margin: '0 0 12px'}}>
          {f('If you do not confirm, your slot will be reassigned to a waitlist colleague.', "FOMO pressure plus social proof — attacker-crafted, not real policy.")}
        </p>
        <p style={{margin: 0}}>— Occupational Health</p>
      </>),
      clickConsequence: { headline: 'Intranet password would leak.', body: 'Attackers harvest a generic intranet password and then try it against email, Epic, and the VPN.' },
      ignoreMessage: "Don't ignore — the moment one colleague confirms, attackers pivot. Report so IT can block the bookings domain.",
    },

    {
      id: 'gift-card-ceo',
      title: 'Gift card request from "Chief of Staff"',
      theme: 'CEO fraud',
      audience: 'Admin · Assistants',
      difficulty: 'easy',
      summary: "A 'senior' exec asks you to quietly buy store gift cards for an off-site.",
      sender: "Dr. N. Kakabadze (via mobile)",
      senderEmail: "n.kakabadze.office@gmail.com",
      senderTooltip: "A real hospital exec never emails staff from a personal Gmail — especially on a money matter.",
      subject: 'Quick favor — need this done before the 4pm meeting',
      time: '15:02',
      body: (f) => (<>
        <p style={{margin: '0 0 12px'}}>Elena,</p>
        <p style={{margin: '0 0 12px'}}>
          Are you at your desk? I'm {f("in back-to-back meetings and can't take calls", "Classic pretext — attacker preempts the obvious verification step (calling the sender) by claiming unavailability.")}.
        </p>
        <p style={{margin: '0 0 12px'}}>
          I need a small favor — can you {f('pick up 6 Apple gift cards at $200 each', "Gift-card asks are the signature of a CEO-fraud scam. The organization never legitimately works this way.")} from the pharmacy across the street for the 4pm team retro? I'll expense it back tomorrow.
        </p>
        <p style={{margin: '0 0 12px'}}>
          {f('Scratch off the codes and reply with photos when you have them.', "Photos of codes = the attacker drains the cards in minutes. No legitimate exec would ever ask this.")}
        </p>
        <p style={{margin: 0}}>— N.K.</p>
      </>),
      clickConsequence: { headline: '$1,200 cash-equivalent lost.', body: "Gift-card fraud nets attackers real money fast — they burn the codes in minutes and the hospital rarely recovers." },
      ignoreMessage: "Report — the SOC pins down which exec is being impersonated and sends a staff-wide alert before others fall for it.",
    },
  ];

  const active = scenarios.find(s => s.id === activeId);

  const difficultyColor = (d) => d === 'easy' ? 'var(--green)' : d === 'medium' ? 'var(--amber)' : 'var(--coral)';
  const difficultyLabel = (d) => d === 'easy' ? 'Easy' : d === 'medium' ? 'Medium' : 'Hard';

  const resultChip = (r) => {
    if (r === 'passed')  return <span className="chip chip-green"><I.CheckCircle size={10}/> Reported</span>;
    if (r === 'clicked') return <span className="chip chip-coral"><I.AlertTriangle size={10}/> Clicked</span>;
    if (r === 'ignored') return <span className="chip chip-amber"><I.Clock size={10}/> Ignored</span>;
    return <span className="chip chip-outline">Not tested</span>;
  };

  const startScenario = (id) => {
    setActiveId(id);
    setOutcome(null);
    setReportTime(null);
    startRef.current = Date.now();
    window.scrollTo({ top: 0, behavior: 'smooth' });
  };

  const report = () => {
    const t = Math.max(8, Math.min(60, Math.round((Date.now() - startRef.current) / 1000)));
    setReportTime(t);
    setOutcome('report');
    setResults(r => ({ ...r, [activeId]: 'passed' }));
    toast('Reported to SOC · +20 points', 'success');
  };
  const click = () => {
    setOutcome('click');
    setResults(r => ({ ...r, [activeId]: 'clicked' }));
  };
  const ignore = () => {
    setOutcome('ignore');
    setResults(r => ({ ...r, [activeId]: 'ignored' }));
  };
  const backToPicker = () => {
    setActiveId(null);
    setOutcome(null);
    setReportTime(null);
  };

  // -- Campaign picker view -------------------------------------------------
  if (!active) {
    const passed = Object.values(results).filter(r => r === 'passed').length;
    return (
      <div className="page-enter">
        <div className="row-between" style={{marginBottom: 16, alignItems: 'flex-start', flexWrap: 'wrap', gap: 12}}>
          <div>
            <h1>Phishing Simulations</h1>
            <p className="muted" style={{fontSize: 12.5}}>Ten scenarios across the threats actually seen in healthcare — pick one to run.</p>
          </div>
          <div style={{display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap'}}>
            <span className="chip chip-outline"><I.Clock size={12}/> Campaign Q2 · Wave 3</span>
            <span className="chip chip-green"><I.Activity size={12}/> Live</span>
            <button
              className="btn btn-sm btn-outline phase2-disabled"
              onClick={() => toast('Role-specific scenarios will be generated and queued for approval in Phase 2', 'success')}
              title="Role-specific scenarios will be generated and queued for approval in Phase 2."
              style={{gap: 6}}
            >
              <I.Compass size={12}/> Generate scenario <Phase2Badge/>
            </button>
          </div>
        </div>

        <div className="sim-banner" style={{marginBottom: 20}}>
          <I.AlertTriangle size={18}/>
          <span><b>Simulation — not real threats.</b> This is a safe training environment. Your actions are tracked for learning only.</span>
        </div>

        <div className="kpi-grid" style={{marginBottom: 20}}>
          <div className="kpi">
            <div className="kpi-label">Campaigns available</div>
            <div className="kpi-value">{scenarios.length}</div>
            <div className="kpi-sub">across 8 threat themes</div>
          </div>
          <div className="kpi">
            <div className="kpi-label">Reported correctly</div>
            <div className="kpi-value">{passed}</div>
            <div className="kpi-sub">of {scenarios.length} attempted this session</div>
          </div>
          <div className="kpi">
            <div className="kpi-label">Difficulty spread</div>
            <div className="kpi-value">{scenarios.filter(s => s.difficulty === 'easy').length}·{scenarios.filter(s => s.difficulty === 'medium').length}·{scenarios.filter(s => s.difficulty === 'hard').length}</div>
            <div className="kpi-sub">easy · medium · hard</div>
          </div>
          <div className="kpi">
            <div className="kpi-label">Synthetic data</div>
            <div className="kpi-value" style={{fontSize: 18}}>100%</div>
            <div className="kpi-sub">no real patient or vendor info</div>
          </div>
        </div>

        <div className="campaign-grid">
          {scenarios.map(s => {
            const res = results[s.id];
            return (
              <button
                key={s.id}
                className="card hover campaign-card"
                onClick={() => startScenario(s.id)}
                style={{padding: 18, textAlign: 'left', cursor: 'pointer', border: '1px solid var(--border)', display: 'flex', flexDirection: 'column', gap: 12}}
              >
                <div style={{display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 10}}>
                  <div style={{flex: 1, minWidth: 0}}>
                    <div style={{fontFamily: 'JetBrains Mono, monospace', fontSize: 10, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 600, marginBottom: 6}}>
                      {s.theme}
                    </div>
                    <div style={{fontFamily: 'var(--serif)', fontSize: 16, fontWeight: 600, color: 'var(--navy)', lineHeight: 1.3, letterSpacing: '-0.005em'}}>
                      {s.title}
                    </div>
                  </div>
                  <span style={{display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 10.5, fontWeight: 600, color: difficultyColor(s.difficulty), textTransform: 'uppercase', letterSpacing: '0.06em', flexShrink: 0}}>
                    <span style={{width: 8, height: 8, borderRadius: '50%', background: difficultyColor(s.difficulty)}}/>
                    {difficultyLabel(s.difficulty)}
                  </span>
                </div>
                <p style={{fontSize: 12.5, color: 'var(--ink-2)', lineHeight: 1.55, margin: 0}}>{s.summary}</p>
                <div style={{display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, marginTop: 'auto', flexWrap: 'wrap'}}>
                  <span style={{fontSize: 11, color: 'var(--ink-3)'}}>{s.audience}</span>
                  {resultChip(res)}
                </div>
                <div style={{display: 'flex', alignItems: 'center', gap: 6, color: 'var(--teal)', fontWeight: 600, fontSize: 12.5, marginTop: 2}}>
                  Run simulation <I.ArrowRight size={13}/>
                </div>
              </button>
            );
          })}
        </div>
      </div>
    );
  }

  // -- Active scenario view -------------------------------------------------
  // Build a 3-email inbox: 1 decoy before, the scenario, 1 decoy after.
  const decoyBefore = { id: 'db', sender: 'Lab Results — Cardiology', subject: 'Weekly cardiology lab batch — 42 results ready', time: '08:14' };
  const decoyAfter  = { id: 'da', sender: 'Dr. Mikheil Beridze',      subject: 'Re: 3B staffing for Fri night shift',              time: '08:37' };

  return (
    <div className="page-enter">
      <div className="row-between" style={{marginBottom: 12, alignItems: 'flex-start', flexWrap: 'wrap', gap: 10}}>
        <div>
          <button className="btn btn-ghost btn-sm" onClick={backToPicker} style={{padding: 0, marginBottom: 6}}>
            <I.ChevronLeft size={13}/> Back to campaigns
          </button>
          <h1>{active.title}</h1>
          <p className="muted" style={{fontSize: 12.5}}>{active.theme} · {active.audience} · {difficultyLabel(active.difficulty)}</p>
        </div>
        <div style={{display: 'flex', gap: 8, alignItems: 'center'}}>
          <span className="chip chip-outline"><I.Clock size={12}/> Campaign Q2 · Wave 3</span>
          <span className="chip chip-green"><I.Activity size={12}/> Live</span>
        </div>
      </div>

      <div className="sim-banner" style={{marginBottom: 16}}>
        <I.AlertTriangle size={18}/>
        <span><b>Simulation — not a real threat.</b> Your actions are tracked for learning only.</span>
      </div>

      <div className="sim-layout">
        <div className="card" style={{overflow: 'hidden'}}>
          <div className="card-header">
            <h2 style={{margin: 0}}>Inbox</h2>
            <span className="muted" style={{fontSize: 12}}>3 messages</span>
          </div>
          <div>
            {[decoyBefore, { id: active.id, sender: active.sender, subject: active.subject, time: active.time, sim: true, unread: true }, decoyAfter].map(e => (
              <div key={e.id} className={`inbox-item ${e.unread ? 'unread' : ''} ${e.sim ? 'selected' : ''}`}>
                <div style={{width: 28, height: 28, borderRadius: '50%', background: e.sim ? 'var(--coral-100)' : 'var(--teal-100)', color: e.sim ? 'var(--coral)' : 'var(--teal)', display: 'grid', placeItems: 'center'}}>
                  {e.sim ? <I.AlertTriangle size={14}/> : <I.Mail size={14}/>}
                </div>
                <div className="inbox-sender">{e.sender}</div>
                <div className="inbox-subject">{e.subject}</div>
                <div className="inbox-time">{e.time}</div>
              </div>
            ))}
          </div>
        </div>

        <div className="card">
          <div>
            <div style={{padding: '20px 24px', borderBottom: '1px solid var(--border-2)'}}>
              <div style={{display: 'flex', gap: 8, alignItems: 'center', marginBottom: 8, flexWrap: 'wrap'}}>
                <span className="chip chip-coral"><I.AlertTriangle size={11}/> Simulation</span>
                <span className="muted" style={{fontSize: 12}}>Received {active.time}</span>
              </div>
              <div style={{fontSize: 18, fontWeight: 600, color: 'var(--navy)', marginBottom: 10}}>{active.subject}</div>
              <div style={{fontSize: 13, color: 'var(--ink-2)', display: 'flex', flexWrap: 'wrap', gap: 12}}>
                <span>
                  <b style={{color: 'var(--navy)'}}>From:</b> {active.sender} &lt;<span className="flag" data-flag={active.senderTooltip}>{active.senderEmail}</span>&gt;
                </span>
                {active.replyTo && (
                  <span>
                    <b style={{color: 'var(--navy)'}}>Reply-to:</b> <span className="flag" data-flag={active.replyTooltip}>{active.replyTo}</span>
                  </span>
                )}
              </div>
            </div>
            <div style={{padding: 24, lineHeight: 1.7, color: 'var(--ink-2)', fontSize: 14}}>
              {active.body(flag)}
            </div>

            {!outcome && (
              <div style={{padding: 20, borderTop: '1px solid var(--border-2)', background: 'var(--bg)'}}>
                <div style={{fontSize: 12.5, color: 'var(--ink-2)', marginBottom: 12, fontWeight: 500}}>What will you do?</div>
                <div style={{display: 'flex', gap: 10, flexWrap: 'wrap'}}>
                  <button className="btn btn-primary" onClick={report}><I.Flag size={15}/> Report as phishing</button>
                  <button className="btn btn-outline" onClick={click}><I.Link size={15}/> Click the link</button>
                  <button className="btn btn-ghost" onClick={ignore}><I.Archive size={15}/> Ignore</button>
                </div>
              </div>
            )}

            {outcome === 'report' && (
              <div style={{padding: 24, borderTop: '1px solid var(--border-2)', background: 'var(--green-100)'}}>
                <div style={{display: 'flex', gap: 14, alignItems: 'flex-start'}}>
                  <div style={{width: 42, height: 42, borderRadius: 10, background: 'var(--green)', color: 'white', display: 'grid', placeItems: 'center', flexShrink: 0}}>
                    <I.CheckCircle size={22}/>
                  </div>
                  <div>
                    <div style={{fontWeight: 600, color: 'var(--green)', fontSize: 14}}>Reported in {reportTime} seconds.</div>
                    <div style={{color: 'var(--green)', fontSize: 12.5, marginTop: 6, lineHeight: 1.55}}>
                      The Security Operations Center has been notified. Indicators of compromise from this simulated campaign have been logged to your training record for audit purposes.
                    </div>
                    <div style={{display: 'flex', gap: 8, marginTop: 14, flexWrap: 'wrap'}}>
                      <button className="btn btn-sm btn-primary" onClick={backToPicker}>Try another campaign</button>
                      <button className="btn btn-sm btn-outline" onClick={() => onNavigate('dashboard')}>Back to dashboard</button>
                    </div>
                  </div>
                </div>
              </div>
            )}

            {outcome === 'click' && (
              <div style={{padding: 24, borderTop: '1px solid var(--border-2)', background: 'var(--coral-100)'}}>
                <div style={{display: 'flex', gap: 14, alignItems: 'flex-start'}}>
                  <div style={{width: 42, height: 42, borderRadius: 10, background: 'var(--coral)', color: 'white', display: 'grid', placeItems: 'center', flexShrink: 0}}>
                    <I.AlertTriangle size={22}/>
                  </div>
                  <div>
                    <div style={{fontWeight: 600, color: '#7A1F18', fontSize: 15}}>{active.clickConsequence.headline}</div>
                    <div style={{color: '#7A1F18', fontSize: 13, marginTop: 6, lineHeight: 1.55}}>
                      {active.clickConsequence.body}
                    </div>
                    <div style={{display: 'flex', gap: 8, marginTop: 14, flexWrap: 'wrap'}}>
                      <button className="btn btn-sm btn-primary" onClick={() => { setOutcome(null); startRef.current = Date.now(); }}>Try again</button>
                      <button className="btn btn-sm btn-outline" onClick={backToPicker}>Back to campaigns</button>
                    </div>
                  </div>
                </div>
              </div>
            )}

            {outcome === 'ignore' && (
              <div style={{padding: 24, borderTop: '1px solid var(--border-2)', background: 'var(--amber-100)'}}>
                <div style={{display: 'flex', gap: 14, alignItems: 'flex-start'}}>
                  <div style={{width: 42, height: 42, borderRadius: 10, background: 'var(--amber)', color: 'white', display: 'grid', placeItems: 'center', flexShrink: 0}}>
                    <I.Info size={22}/>
                  </div>
                  <div>
                    <div style={{fontWeight: 600, color: '#7C4A06', fontSize: 15}}>Ignoring doesn't protect others.</div>
                    <div style={{color: '#7C4A06', fontSize: 13, marginTop: 6, lineHeight: 1.55}}>
                      {active.ignoreMessage}
                    </div>
                    <div style={{display: 'flex', gap: 8, marginTop: 14, flexWrap: 'wrap'}}>
                      <button className="btn btn-sm btn-primary" onClick={() => { setOutcome(null); startRef.current = Date.now(); }}>Try again</button>
                      <button className="btn btn-sm btn-outline" onClick={backToPicker}>Back to campaigns</button>
                    </div>
                  </div>
                </div>
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

window.PhishingPage = PhishingPage;
