{"id":1475,"date":"2026-06-22T13:02:21","date_gmt":"2026-06-22T13:02:21","guid":{"rendered":"https:\/\/360bizbrokers.com\/?page_id=1475"},"modified":"2026-06-22T13:33:35","modified_gmt":"2026-06-22T13:33:35","slug":"deals-sourcing-v2","status":"publish","type":"page","link":"https:\/\/360bizbrokers.com\/pt\/deals-sourcing-v2\/","title":{"rendered":"AI Assisted Deals Sourcing &#8211; External User"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"1475\" class=\"elementor elementor-1475\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-a091a68 e-flex e-con-boxed e-con e-parent\" data-id=\"a091a68\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-c140cef elementor-widget elementor-widget-html\" data-id=\"c140cef\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<title>AI Assisted Deals Sourcing Pro\u2122 | v2.10 WordPress Login Only + User AI API Key | Powered by 360 Biz Brokers<\/title>\n<!-- v2.10 WordPress Login Only + User AI API Key: removed separate workspace password prompts; WordPress login is the only password. Hidden technical AI endpoint fields from member interface. -->\n<!-- v2.9 Member Login + User AI API Key: added WordPress member gate and one-time per-user AI service API key setup. -->\n<!-- v2.8 Advanced Follow-Up Automation: added daily priority command center, cadence creation, overdue follow-up alerts, next-best-action intelligence, and productivity metrics. -->\n<!-- v2.7 Sales Navigator Companion: added Apollo fallback workflow, LinkedIn\/Sales Navigator search guidance, manual owner capture, and owner discovery success metrics. -->\n<!-- v2.6 AI Listing Readiness Engine: added seller-readiness scoring, readiness priority dashboard, risk\/driver analysis, outreach timing recommendations, and prospect readiness ranking. -->\n<!-- v2.4 Pipeline & Follow-Up Manager: added prospect status tracking, next follow-up management, dashboard metrics, activity timeline, quick actions, and AI follow-up suggestions. -->\n<!-- AI Outreach v2.3: Apollo contact-aware outreach package, follow-up sequence, and activity logging. -->\n<!-- Workspace UX patch: renamed vault wording, added auto-prompt on existing encrypted records, and Sign Out \/ Lock Workspace wording. -->\n<!-- Vault storage patch: sends encrypted_data + data payload; uses deals_sourcing record key when backend default is present. -->\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Anton&family=Lato:ital,wght@0,400;0,700;0,900;1,400;1,700&display=swap\" rel=\"stylesheet\">\n<style>\n*{box-sizing:border-box;margin:0;padding:0}\n:root{--G:#B8960C;--G2:#C9A84C;--Gbg:#f5eed5;--B:#111;--W:#fff;--bg:#f0ede6;--card:#fff;--card2:#f7f5f0;--txt:#1a1a18;--txt2:#5a5a55;--txt3:#9a9a95;--bdr:rgba(0,0,0,.09);--bdrm:rgba(0,0,0,.16);--green:#2d7a4f;--red:#b33a2f;--blue:#185FA5;--amber:#8a5a00;--r:9px;--rl:14px;--fH:'Anton',Impact,sans-serif;--fB:'Lato',Arial,sans-serif}\nbody{font-family:var(--fB);background:var(--bg);color:var(--txt);font-size:14px;line-height:1.55;min-height:100vh}\n.wrap{max-width:1240px;margin:0 auto;padding:18px 14px 60px}\n.topbar{background:var(--B);border-radius:var(--rl);padding:14px 18px;display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:18px}\n.brand h1{font:900 24px var(--fH);color:var(--G2);letter-spacing:.04em;text-transform:uppercase;line-height:1}\n.brand p{color:rgba(255,255,255,.62);font-size:12px;letter-spacing:.08em;text-transform:uppercase;margin-top:4px}\n.badge{background:rgba(201,168,76,.15);border:1px solid rgba(201,168,76,.45);color:var(--G2);border-radius:999px;padding:6px 12px;font-weight:900;font-size:11px;text-transform:uppercase;letter-spacing:.06em}\n.nav{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:16px}\n.tab{border:1px solid var(--bdrm);background:#fff;border-radius:999px;padding:8px 13px;font-weight:900;font-size:12px;cursor:pointer}\n.tab.active{background:var(--B);color:var(--G2);border-color:var(--G2)}\n.grid{display:grid;grid-template-columns:360px 1fr;gap:16px}\n.card{background:var(--card);border:1px solid var(--bdr);border-radius:var(--rl);padding:18px;margin-bottom:16px;box-shadow:0 8px 22px rgba(0,0,0,.04)}\n.card h2{font:900 18px var(--fH);text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px}\n.card h3{font-size:14px;text-transform:uppercase;letter-spacing:.06em;color:#654d00;border-bottom:2px solid var(--G2);padding-bottom:6px;margin:16px 0 10px}\n.help{background:var(--Gbg);border-left:4px solid var(--G2);padding:11px 13px;border-radius:0 var(--r) var(--r) 0;color:var(--txt2);font-size:13px;margin-bottom:14px}\n.notice{background:#fff8e6;border:1px solid var(--G2);border-radius:var(--r);padding:10px 12px;color:#6c4b00;font-weight:700;font-size:12px;margin-bottom:12px}\n.field{margin-bottom:11px}\n.field label{display:block;font-weight:900;font-size:12px;color:var(--txt2);margin-bottom:4px}\ninput,select,textarea{width:100%;border:1px solid var(--bdrm);border-radius:var(--r);padding:9px 10px;font:400 13px var(--fB);background:#fff;color:var(--txt)}\ntextarea{min-height:86px;resize:vertical}\n.two{display:grid;grid-template-columns:1fr 1fr;gap:10px}\n.three{display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px}\n.actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}\nbutton{border:0;border-radius:var(--r);padding:10px 15px;font-weight:900;cursor:pointer;font-family:var(--fB)}\n.primary{background:var(--B);color:var(--G2);border:2px solid var(--G2)}\n.secondary{background:var(--Gbg);color:var(--B);border:1px solid var(--G2)}\n.light{background:#fff;color:var(--B);border:1px solid var(--bdrm)}\n.danger{background:#fff0ee;color:var(--red);border:1px solid #e0aaa3}\n.prospect-list{display:grid;gap:8px}\n.prospect{border:1px solid var(--bdr);border-radius:var(--r);padding:11px;background:#fff;cursor:pointer}\n.prospect.active{border:2px solid var(--G2);background:var(--Gbg)}\n.prospect b{display:block}.prospect small{color:var(--txt3)}\n.pill{display:inline-block;border-radius:999px;padding:5px 10px;font-weight:900;font-size:11px;margin:2px;background:var(--Gbg);color:#654d00}\n.pill.green{background:#e4f4e9;color:var(--green)}.pill.red{background:#fff0ee;color:var(--red)}.pill.blue{background:#e6f1fb;color:#0c447c}.pill.amber{background:#fff3d5;color:#7a5100}\n.output{background:var(--card2);border-radius:var(--r);padding:14px;white-space:pre-wrap;line-height:1.55;font-size:13px;border-left:4px solid var(--G2)}\n.outgrid{display:grid;grid-template-columns:1fr;gap:10px}\n.langs{display:flex;gap:7px;margin-bottom:10px;flex-wrap:wrap}\n.lang{padding:6px 11px;border-radius:999px;border:1px solid var(--bdrm);background:#fff;cursor:pointer;font-weight:900;font-size:11px}\n.lang.active{background:var(--B);color:var(--G2);border-color:var(--G2)}\n.metric-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:14px}\n.metric{background:var(--card2);border-radius:var(--r);padding:13px;text-align:center}\n.metric span{display:block;color:var(--txt3);font-size:10px;text-transform:uppercase;font-weight:900;letter-spacing:.06em}\n.metric b{display:block;font-size:26px;margin-top:4px}\n.scorebox{background:var(--B);border-radius:var(--rl);padding:18px;color:#fff;display:flex;justify-content:space-between;align-items:center;gap:20px;margin-bottom:14px}\n.scorebox .score{font:900 54px var(--fH);color:var(--G2);line-height:1}\n.q{display:grid;grid-template-columns:1fr 150px;gap:12px;align-items:center;padding:10px 0;border-bottom:1px solid var(--bdr)}\n.q:last-child{border-bottom:0}.q p{font-weight:700;font-size:13px;line-height:1.35}.q small{display:block;color:var(--txt3);font-weight:400;margin-top:2px}\n.stage{display:flex;gap:6px;flex-wrap:wrap}.stage button{padding:7px 9px;font-size:11px}\n.history{display:grid;gap:8px}.hist{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:10px}\n.report{background:#fff;border-radius:var(--rl);padding:24px;border:1px solid var(--bdr)}\n.report h2{font:900 24px var(--fH);color:#111;text-transform:uppercase;border-bottom:4px solid var(--G2);padding-bottom:8px;margin-bottom:14px}\n.hide{display:none}\n@media(max-width:900px){.grid{grid-template-columns:1fr}.metric-grid{grid-template-columns:1fr 1fr}.two,.three{grid-template-columns:1fr}.q{grid-template-columns:1fr}.scorebox{display:block}.scorebox .score{margin-top:10px}}\n@media print{body{background:#fff}.topbar,.nav,.leftcol,.actions,.langs,.notice{display:none!important}.wrap{max-width:none;padding:0}.grid{display:block}.card{box-shadow:none;border:none}.report{border:none;padding:0}}\n\n.kanban{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-top:12px}\n.kanban-col{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:10px;min-height:120px}\n.kanban-col h4{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--txt2);margin-bottom:8px}\n.kcard{background:#fff;border:1px solid var(--bdr);border-radius:8px;padding:9px;margin-bottom:8px;cursor:pointer}\n.kcard b{display:block;font-size:13px}\n.kcard small{color:var(--txt3)}\n.queue{display:grid;gap:8px;margin-top:10px}\n.queue-item{display:grid;grid-template-columns:52px 1fr auto;gap:10px;align-items:center;background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:10px}\n.priority-score{width:42px;height:42px;border-radius:50%;background:var(--B);color:var(--G2);display:flex;align-items:center;justify-content:center;font-weight:900}\n.alert-row{display:grid;gap:8px;margin-top:10px}\n.alert{border-left:4px solid var(--G2);background:#fff8e6;border-radius:0 var(--r) var(--r) 0;padding:10px}\n.quick-actions{display:flex;gap:6px;flex-wrap:wrap}\n.quick-actions button{padding:6px 9px;font-size:11px}\n@media(max-width:900px){.kanban{grid-template-columns:1fr}.queue-item{grid-template-columns:1fr}.priority-score{width:auto;border-radius:999px;padding:7px 10px}}\n\n\n.copybar{display:flex;justify-content:flex-end;margin:6px 0}\n.copybtn{padding:5px 9px;font-size:10px;background:#fff;border:1px solid var(--bdrm);color:var(--txt2)}\n.copybtn:hover{background:var(--Gbg);color:var(--B)}\n.empty-state{background:#fff;border:1px dashed var(--bdrm);border-radius:var(--r);padding:16px;color:var(--txt3);text-align:center}\n.toolbar-row{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}\n.demo-note{font-size:11px;color:var(--txt3);margin-top:8px}\n.report-cover{background:var(--B);color:#fff;border-radius:var(--rl);padding:22px;margin-bottom:20px;border-bottom:5px solid var(--G2)}\n.report-cover h2{color:var(--G2)!important;border-bottom:0!important;margin-bottom:4px!important;padding-bottom:0!important}\n.report-meta-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin:14px 0}\n.report-meta-grid div{background:#fffdf7;border:1px solid var(--G2);border-radius:var(--r);padding:10px}\n.section-kicker{font-size:10px;font-weight:900;text-transform:uppercase;letter-spacing:.08em;color:var(--txt3);margin-bottom:2px}\n.status-good{color:var(--green);font-weight:900}\n.status-warn{color:var(--amber);font-weight:900}\n.status-risk{color:var(--red);font-weight:900}\n@media print{.copybar,.toolbar-row,.demo-note{display:none!important}.report-cover{background:#111!important;color:#fff!important;-webkit-print-color-adjust:exact;print-color-adjust:exact}}\n\n\n.analytics-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin:14px 0}\n.chart-card{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:14px}\n.chart-card h4{font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--txt2);margin-bottom:10px}\n.bar-row{display:grid;grid-template-columns:140px 1fr 42px;gap:8px;align-items:center;margin:8px 0;font-size:12px}\n.bar-track{height:12px;background:#e9e4d7;border-radius:999px;overflow:hidden}\n.bar-fill{height:100%;background:var(--G2);border-radius:999px}\n.report-table{width:100%;border-collapse:collapse;background:#fff;border-radius:var(--r);overflow:hidden;margin-top:10px}\n.report-table th,.report-table td{border-bottom:1px solid var(--bdr);padding:9px 10px;text-align:left;font-size:12px}\n.report-table th{background:var(--B);color:var(--G2);text-transform:uppercase;letter-spacing:.05em;font-size:10px}\n.report-table tr:last-child td{border-bottom:0}\n.analytics-summary{background:#111;color:#fff;border-radius:var(--rl);padding:16px;margin-bottom:14px}\n.analytics-summary h3{color:var(--G2)!important;border-bottom:0!important;margin:0 0 8px!important;padding:0!important}\n.analytics-summary p{color:rgba(255,255,255,.78)}\n@media(max-width:900px){.analytics-grid{grid-template-columns:1fr}.bar-row{grid-template-columns:1fr}}\n\n\n.workflow-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}\n.task-card{background:#fff;border:1px solid var(--bdr);border-left:4px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:12px;margin-bottom:8px}\n.task-card.high{border-left-color:var(--red)}\n.task-card.medium{border-left-color:var(--amber)}\n.task-card.low{border-left-color:var(--blue)}\n.task-card b{display:block;margin-bottom:4px}\n.task-meta{font-size:11px;color:var(--txt3);margin-bottom:6px}\n.task-actions{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}\n.task-actions button{padding:5px 8px;font-size:10px}\n.workflow-rule{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:12px;margin-bottom:8px}\n.workflow-rule h4{font-size:12px;text-transform:uppercase;letter-spacing:.06em;margin-bottom:4px;color:var(--txt2)}\n.automation-banner{background:linear-gradient(135deg,#111,#2a2206);color:#fff;border-radius:var(--rl);padding:16px;margin-bottom:14px;border-bottom:4px solid var(--G2)}\n.automation-banner h3{color:var(--G2)!important;border-bottom:0!important;margin:0 0 6px!important;padding:0!important}\n@media(max-width:900px){.workflow-grid{grid-template-columns:1fr}}\n\n\n.discovery-layout{display:grid;grid-template-columns:330px 1fr;gap:14px}\n.discovery-card{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:14px;margin-bottom:10px}\n.discovery-result{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:14px;margin-bottom:10px;display:grid;grid-template-columns:1fr auto;gap:12px}\n.discovery-result:hover{border-color:var(--G2);box-shadow:0 6px 18px rgba(0,0,0,.06)}\n.seller-score{width:70px;height:70px;border-radius:50%;background:var(--B);color:var(--G2);display:flex;align-items:center;justify-content:center;font:900 24px var(--fH)}\n.discovery-meta{display:flex;gap:6px;flex-wrap:wrap;margin:7px 0}\n.api-status{font-size:12px;border-radius:var(--r);padding:9px 11px;background:#fff8e6;border:1px solid var(--G2);color:#6c4b00;margin-top:10px}\n.discovery-actions{display:flex;gap:6px;flex-wrap:wrap;margin-top:10px}\n.discovery-actions button{padding:7px 10px;font-size:11px}\n.source-pill{display:inline-block;border-radius:999px;background:#e6f1fb;color:#0c447c;font-weight:900;font-size:10px;padding:4px 8px;margin-left:4px}\n@media(max-width:900px){.discovery-layout{grid-template-columns:1fr}.discovery-result{grid-template-columns:1fr}.seller-score{width:auto;border-radius:999px;padding:7px 12px}}\n\n\n.presentation-doc{background:#fff;border:1px solid var(--bdr);border-radius:var(--rl);padding:28px;max-width:900px;margin:auto}\n.pres-cover{background:#111;color:#fff;border-radius:var(--rl);padding:28px;margin-bottom:22px;border-bottom:6px solid var(--G2)}\n.pres-cover h1{font:900 32px var(--fH);color:var(--G2);text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px}\n.pres-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:14px 0}\n.pres-box{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:14px}\n.pres-score{font:900 38px var(--fH);color:var(--G);line-height:1}\n.pres-section{margin-top:20px;padding-top:12px;border-top:2px solid var(--G2)}\n.pres-section h3{border-bottom:0!important;margin:0 0 8px!important;padding:0!important;color:#111!important}\n@media(max-width:900px){.pres-grid{grid-template-columns:1fr}}\n@media print{.presentation-doc{border:none;padding:0}.pres-cover{background:#111!important;color:#fff!important;-webkit-print-color-adjust:exact;print-color-adjust:exact}}\n\n\n.qa-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}\n.qa-item{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:12px;display:flex;gap:10px;align-items:flex-start}\n.qa-status{width:24px;height:24px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:900;flex-shrink:0}\n.qa-status.pass{background:#e4f4e9;color:var(--green)}\n.qa-status.warn{background:#fff3d5;color:var(--amber)}\n.release-box{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:14px;margin:10px 0}\n.release-box h4{font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--txt2);margin-bottom:6px}\n.codebox{background:#111;color:#fff;border-radius:var(--r);padding:12px;font-family:monospace;font-size:12px;white-space:pre-wrap}\n@media(max-width:900px){.qa-grid{grid-template-columns:1fr}}\n\n.api-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}\n.api-card{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:14px;margin-bottom:10px}\n.api-card h4{font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--txt2);margin-bottom:6px}\n.endpoint-test{background:#111;color:#fff;border-radius:var(--r);padding:12px;font-family:monospace;font-size:12px;white-space:pre-wrap;overflow:auto}\n.status-box{border-radius:var(--r);padding:12px;margin-top:10px;background:#fff8e6;border:1px solid var(--G2);color:#6c4b00}\n@media(max-width:900px){.api-grid{grid-template-columns:1fr}}\n\n.scanner-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}\n.scanner-card{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:14px;margin-bottom:10px}\n.scanner-rank{font:900 52px var(--fH);color:var(--G);line-height:1}\n.scanner-scorebox{background:#111;color:#fff;border-radius:var(--rl);padding:18px;display:grid;grid-template-columns:120px 1fr;gap:18px;align-items:center;margin-bottom:14px}\n.scanner-scorebox h3{color:var(--G2)!important;border-bottom:0!important;margin:0!important;padding:0!important}\n.scanner-list{display:grid;gap:8px}\n.scanner-item{background:#fff;border:1px solid var(--bdr);border-left:5px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:12px;cursor:pointer}\n.scanner-item.aplus{border-left-color:#2d7a4f}.scanner-item.a{border-left-color:#5fa35f}.scanner-item.b{border-left-color:#c9a84c}.scanner-item.c{border-left-color:#b36b2f}.scanner-item.d{border-left-color:#b33a2f}\n.scanner-badge{display:inline-block;border-radius:999px;background:var(--Gbg);color:#654d00;font-weight:900;font-size:10px;padding:4px 8px;margin:2px}\n.scanner-badge.hot{background:#e4f4e9;color:var(--green)}.scanner-badge.warn{background:#fff3d5;color:var(--amber)}.scanner-badge.risk{background:#fff0ee;color:var(--red)}\n@media(max-width:900px){.scanner-grid{grid-template-columns:1fr}.scanner-scorebox{grid-template-columns:1fr}}\n\n\n.sequence-grid{display:grid;grid-template-columns:330px 1fr;gap:14px}\n.sequence-card{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:14px;margin-bottom:10px}\n.sequence-output{background:var(--card2);border-left:4px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:14px;white-space:pre-wrap;margin-bottom:10px}\n.sequence-actions{display:flex;gap:6px;flex-wrap:wrap;margin:6px 0 12px}\n.sequence-actions button{padding:6px 9px;font-size:10px}\n.angle-pill{display:inline-block;border-radius:999px;background:#111;color:var(--G2);font-weight:900;font-size:10px;padding:5px 9px;margin:2px}\n@media(max-width:900px){.sequence-grid{grid-template-columns:1fr}}\n\n\n.succession-grid{display:grid;grid-template-columns:330px 1fr;gap:14px}\n.succession-card{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:14px;margin-bottom:10px}\n.persona-card{background:#111;color:#fff;border-radius:var(--rl);padding:18px;border-bottom:5px solid var(--G2);margin-bottom:14px}\n.persona-card h3{color:var(--G2)!important;border-bottom:0!important;margin:0 0 6px!important;padding:0!important}\n.persona-score{font:900 48px var(--fH);color:var(--G2);line-height:1}\n.intel-pill{display:inline-block;border-radius:999px;background:var(--Gbg);color:#654d00;font-weight:900;font-size:10px;padding:5px 9px;margin:2px}\n.intel-pill.hot{background:#e4f4e9;color:var(--green)}\n.intel-pill.risk{background:#fff0ee;color:var(--red)}\n.intel-pill.blue{background:#e6f1fb;color:#0c447c}\n.question-list{background:var(--card2);border-left:4px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:14px;white-space:pre-wrap}\n@media(max-width:900px){.succession-grid{grid-template-columns:1fr}}\n\n\n.buyer-grid{display:grid;grid-template-columns:340px 1fr;gap:14px}\n.buyer-card{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:14px;margin-bottom:10px}\n.match-card{background:#fff;border:1px solid var(--bdr);border-left:5px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:13px;margin-bottom:10px}\n.match-score{font:900 34px var(--fH);color:var(--G);line-height:1}\n.match-pill{display:inline-block;border-radius:999px;background:var(--Gbg);color:#654d00;font-weight:900;font-size:10px;padding:5px 9px;margin:2px}\n.match-pill.hot{background:#e4f4e9;color:var(--green)}\n.match-pill.blue{background:#e6f1fb;color:#0c447c}\n.match-pill.risk{background:#fff0ee;color:var(--red)}\n@media(max-width:900px){.buyer-grid{grid-template-columns:1fr}}\n\n\n.rollup-grid{display:grid;grid-template-columns:340px 1fr;gap:14px}\n.rollup-card{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:14px;margin-bottom:10px}\n.cluster-card{background:#fff;border:1px solid var(--bdr);border-left:5px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:13px;margin-bottom:10px}\n.cluster-score{font:900 34px var(--fH);color:var(--G);line-height:1}\n.rollup-pill{display:inline-block;border-radius:999px;background:var(--Gbg);color:#654d00;font-weight:900;font-size:10px;padding:5px 9px;margin:2px}\n.rollup-pill.hot{background:#e4f4e9;color:var(--green)}\n.rollup-pill.blue{background:#e6f1fb;color:#0c447c}\n.rollup-pill.risk{background:#fff0ee;color:var(--red)}\n@media(max-width:900px){.rollup-grid{grid-template-columns:1fr}}\n\n\n.master-hero{background:linear-gradient(135deg,#111,#2b2309);color:#fff;border-radius:var(--rl);padding:20px;margin-bottom:16px;border-bottom:5px solid var(--G2)}\n.master-hero h2{color:var(--G2)!important;border:0!important;margin:0 0 6px!important;padding:0!important}\n.master-hero p{color:rgba(255,255,255,.75)}\n.master-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin:14px 0}\n.master-tile{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:14px}\n.master-tile span{display:block;font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--txt3);font-weight:900}\n.master-tile b{display:block;font:900 28px var(--fH);color:var(--B);line-height:1.1;margin-top:4px}\n.master-workflow{display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin:14px 0}\n.workflow-step{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:12px;text-align:center}\n.workflow-step b{display:block;color:#654d00}\n.master-action-card{background:#fff;border:1px solid var(--bdr);border-left:5px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:12px;margin-bottom:8px}\n.master-action-card.hot{border-left-color:var(--green)}\n.master-action-card.warn{border-left-color:var(--amber)}\n.master-action-card.risk{border-left-color:var(--red)}\n.master-detail{background:var(--card2);border-radius:var(--r);padding:14px;white-space:pre-wrap;border-left:4px solid var(--G2)}\n.master-score{font:900 44px var(--fH);color:var(--G);line-height:1}\n.master-quick{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}\n.master-quick button{padding:6px 9px;font-size:10px}\n@media(max-width:900px){.master-grid,.master-workflow{grid-template-columns:1fr 1fr}}\n\n\n.pursuit-grid{display:grid;grid-template-columns:340px 1fr;gap:14px}\n.pursuit-card{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:14px;margin-bottom:10px}\n.plan-phase{background:#fff;border:1px solid var(--bdr);border-left:5px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:14px;margin-bottom:12px}\n.plan-phase h4{font-size:13px;text-transform:uppercase;letter-spacing:.06em;color:#654d00;margin-bottom:6px}\n.plan-task{background:var(--card2);border-radius:var(--r);padding:10px;margin:7px 0}\n.plan-task b{display:block}\n.plan-pill{display:inline-block;border-radius:999px;background:var(--Gbg);color:#654d00;font-weight:900;font-size:10px;padding:5px 9px;margin:2px}\n.plan-pill.hot{background:#e4f4e9;color:var(--green)}\n.plan-pill.warn{background:#fff3d5;color:var(--amber)}\n.plan-pill.risk{background:#fff0ee;color:var(--red)}\n.pursuit-score{font:900 44px var(--fH);color:var(--G);line-height:1}\n@media(max-width:900px){.pursuit-grid{grid-template-columns:1fr}}\n\n\n.followup-grid{display:grid;grid-template-columns:340px 1fr;gap:14px}\n.followup-card{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:14px;margin-bottom:10px}\n.momentum-panel{background:#111;color:#fff;border-radius:var(--rl);padding:18px;border-bottom:5px solid var(--G2);margin-bottom:12px}\n.momentum-score{font:900 52px var(--fH);color:var(--G2);line-height:1}\n.status-chip{display:inline-block;border-radius:999px;font-weight:900;font-size:10px;padding:5px 10px;margin:3px;background:var(--Gbg);color:#654d00}\n.status-chip.hot{background:#e4f4e9;color:var(--green)}\n.status-chip.warm{background:#fff3d5;color:var(--amber)}\n.status-chip.nurture{background:#e6f1fb;color:#0c447c}\n.status-chip.dormant{background:#fff0ee;color:var(--red)}\n.follow-task{background:#fff;border:1px solid var(--bdr);border-left:5px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:12px;margin-bottom:9px}\n.follow-task.today{border-left-color:var(--amber)}\n.follow-task.future{border-left-color:var(--blue)}\n.activity-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin:10px 0}\n.activity-button{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:10px;text-align:center;cursor:pointer;font-weight:900}\n.activity-button:hover{border-color:var(--G2)}\n@media(max-width:900px){.followup-grid{grid-template-columns:1fr}.activity-grid{grid-template-columns:1fr 1fr}}\n\n\n.follow-message-box{background:var(--card2);border-left:4px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:14px;white-space:pre-wrap;margin-bottom:10px}\n.follow-message-actions{display:flex;gap:6px;flex-wrap:wrap;margin:8px 0 12px}\n.follow-message-actions button{padding:7px 10px;font-size:11px}\n.activity-grid.v242{grid-template-columns:repeat(3,1fr)}\n.activity-button.v242{min-height:54px;display:flex;align-items:center;justify-content:center;line-height:1.2}\n.activity-button.v242.meeting{background:#e4f4e9;color:var(--green);border-color:var(--green)}\n@media(max-width:900px){.activity-grid.v242{grid-template-columns:1fr 1fr}.activity-button.v242{min-height:48px}}\n\n\n.market-hero{background:linear-gradient(135deg,#111,#2b2309);color:#fff;border-radius:var(--rl);padding:20px;margin-bottom:16px;border-bottom:5px solid var(--G2)}\n.market-hero h2{color:var(--G2)!important;border:0!important;margin:0 0 6px!important;padding:0!important}\n.market-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}\n.market-card{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:14px;margin-bottom:10px}\n.market-row{display:grid;grid-template-columns:1fr 90px 90px 90px;gap:8px;align-items:center;border-bottom:1px solid var(--bdr);padding:9px 0;font-size:12px}\n.market-row:last-child{border-bottom:0}\n.market-row.head{font-weight:900;text-transform:uppercase;letter-spacing:.06em;color:var(--txt2);font-size:10px}\n.market-score{font:900 32px var(--fH);color:var(--G);line-height:1}\n.market-pill{display:inline-block;border-radius:999px;background:var(--Gbg);color:#654d00;font-weight:900;font-size:10px;padding:5px 9px;margin:2px}\n.market-pill.hot{background:#e4f4e9;color:var(--green)}\n.market-pill.warn{background:#fff3d5;color:var(--amber)}\n.market-pill.risk{background:#fff0ee;color:var(--red)}\n.whitespace-item{background:#fff;border:1px solid var(--bdr);border-left:5px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:12px;margin-bottom:8px}\n.heat-item{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:12px;margin-bottom:8px;display:grid;grid-template-columns:70px 1fr;gap:10px;align-items:center}\n.productivity-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin:10px 0}\n.productivity-box{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:12px;text-align:center}\n.productivity-box span{display:block;font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--txt3);font-weight:900}\n.productivity-box b{display:block;font-size:24px;margin-top:4px}\n@media(max-width:900px){.market-grid{grid-template-columns:1fr}.market-row{grid-template-columns:1fr}.productivity-grid{grid-template-columns:1fr 1fr}.heat-item{grid-template-columns:1fr}}\n\n\n.pro-topbar{padding:16px 20px}\n.pro-brand{display:flex;align-items:center;gap:16px}\n.brand-logo{width:86px;height:86px;object-fit:contain}\n.brand-logo-lite{flex:0 0 86px;display:flex;flex-direction:column;align-items:center;justify-content:center;border-radius:14px;background:linear-gradient(135deg,#1a1a1a,#000);border:2px solid var(--G2);box-shadow:0 0 0 1px rgba(255,255,255,.08) inset,0 6px 16px rgba(0,0,0,.22)}\n.brand-logo-lite span{font:900 30px var(--fH);line-height:1;color:var(--G2);letter-spacing:.02em;text-shadow:0 2px 8px rgba(201,168,76,.35)}\n.brand-logo-lite small{font:900 8px var(--fB);color:#fff;letter-spacing:.06em;margin-top:3px}\n.pro-topbar{background:#111!important;border-bottom:4px solid var(--G2)}\n.pro-brand h1{color:var(--G2)!important;text-shadow:none!important}\n.pro-brand p{color:#fff!important}\n.pro-brand h1{font-size:28px}\n.pro-brand p{font-size:13px;color:rgba(255,255,255,.78)}\n.workflow-nav{background:#fff;border:1px solid var(--bdr);border-radius:var(--rl);padding:14px;margin-bottom:16px;box-shadow:0 8px 22px rgba(0,0,0,.04)}\n.workflow-title{font:900 14px var(--fH);letter-spacing:.06em;text-transform:uppercase;color:#111;margin-bottom:10px}\n.workflow-steps{display:grid;grid-template-columns:repeat(10,1fr);gap:8px}\n.workflow-pill{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:9px 8px;text-align:center;cursor:pointer;min-height:68px;display:flex;flex-direction:column;justify-content:center}\n.workflow-pill:hover{border-color:var(--G2);background:var(--Gbg)}\n.workflow-pill.active{background:#111;color:var(--G2);border-color:var(--G2)}\n.workflow-pill span{font-size:10px;font-weight:900;text-transform:uppercase;color:var(--txt3)}\n.workflow-pill.active span{color:rgba(201,168,76,.9)}\n.workflow-pill b{font-size:11px;line-height:1.2;margin-top:3px}\n.nav-section-label{width:100%;font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--txt3);font-weight:900;margin:8px 0 0}\n.footer-brand{text-align:center;color:var(--txt3);font-size:11px;margin-top:24px}\n.report-logo{max-width:82px;height:auto;margin-bottom:8px}\n@media(max-width:900px){.workflow-steps{grid-template-columns:1fr 1fr}.brand-logo{width:64px;height:64px}.pro-brand h1{font-size:22px}.topbar{display:block}.badge{display:inline-block;margin-top:10px}}\n@media print{.workflow-nav{display:none!important}.brand-logo{width:70px;height:70px}}\n\n\n.launch-checklist{background:#fff;border:1px solid var(--bdr);border-radius:var(--rl);padding:16px;margin-bottom:16px}\n.launch-checklist h3{font-size:14px;text-transform:uppercase;letter-spacing:.06em;color:#654d00;border-bottom:2px solid var(--G2);padding-bottom:6px;margin-bottom:10px}\n.launch-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}\n.launch-item{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:12px}\n.launch-item b{display:block;color:#111}\n.launch-item small{color:var(--txt2)}\n.live-source-panel{background:#111;color:#fff;border-radius:var(--rl);padding:14px;border-bottom:4px solid var(--G2);margin-bottom:12px}\n.live-source-panel h3{color:var(--G2)!important;border:0!important;margin:0 0 6px!important;padding:0!important}\n.live-source-panel p{color:rgba(255,255,255,.78);font-size:12px}\n.live-source-badge{display:inline-block;border-radius:999px;background:#e4f4e9;color:var(--green);font-weight:900;font-size:10px;padding:5px 9px;margin:2px}\n.live-source-badge.warn{background:#fff3d5;color:var(--amber)}\n.live-source-badge.blue{background:#e6f1fb;color:#0c447c}\n@media(max-width:900px){.launch-grid{grid-template-columns:1fr 1fr}}\n\n\n.cloud-storage-panel{background:#fff;border:1px solid var(--bdr);border-radius:var(--rl);padding:14px;margin-bottom:16px;box-shadow:0 8px 22px rgba(0,0,0,.04)}\n.cloud-storage-panel h3{font-size:14px;text-transform:uppercase;letter-spacing:.06em;color:#654d00;border-bottom:2px solid var(--G2);padding-bottom:6px;margin-bottom:10px}\n.cloud-status{display:flex;gap:8px;flex-wrap:wrap;align-items:center}\n.cloud-badge{display:inline-block;border-radius:999px;background:#e6f1fb;color:#0c447c;font-weight:900;font-size:10px;padding:6px 10px}\n.cloud-badge.ok{background:#e4f4e9;color:var(--green)}\n.cloud-badge.warn{background:#fff3d5;color:var(--amber)}\n.cloud-badge.risk{background:#fff0ee;color:var(--red)}\n.cloud-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}\n.cloud-actions button{padding:7px 10px;font-size:11px}\n\n\n.launch-hero-dashboard{background:linear-gradient(135deg,#111,#2b2309);color:#fff;border-radius:var(--rl);padding:20px;margin-bottom:16px;border-bottom:5px solid var(--G2);box-shadow:0 10px 26px rgba(0,0,0,.08)}\n.launch-hero-top{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap}\n.launch-hero-dashboard h2{font:900 24px var(--fH);color:var(--G2);text-transform:uppercase;letter-spacing:.04em;margin:0}\n.launch-hero-dashboard p{color:rgba(255,255,255,.75);margin-top:4px}\n.launch-member-name{font-weight:900;color:#fff}\n.launch-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:10px;margin-top:14px}\n.launch-kpi{background:rgba(255,255,255,.08);border:1px solid rgba(201,168,76,.35);border-radius:var(--r);padding:12px;text-align:center}\n.launch-kpi span{display:block;color:rgba(255,255,255,.62);font-size:10px;text-transform:uppercase;font-weight:900;letter-spacing:.06em}\n.launch-kpi b{display:block;font-size:24px;color:var(--G2);margin-top:4px}\n.launch-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:14px}\n.launch-actions button{padding:9px 12px;font-size:12px}\n.sync-dot{display:inline-block;width:9px;height:9px;border-radius:50%;background:var(--amber);margin-right:6px}\n.sync-dot.ok{background:var(--green)}\n.sync-dot.risk{background:var(--red)}\n.privacy-center{background:#fff;border:1px solid var(--bdr);border-radius:var(--rl);padding:16px;margin-bottom:16px;box-shadow:0 8px 22px rgba(0,0,0,.04)}\n.privacy-center h3{font-size:14px;text-transform:uppercase;letter-spacing:.06em;color:#654d00;border-bottom:2px solid var(--G2);padding-bottom:6px;margin-bottom:10px}\n.privacy-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:8px}\n.privacy-item{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:10px;text-align:center;font-size:12px;font-weight:900}\n.privacy-note{font-size:12px;color:var(--txt2);margin-top:10px;line-height:1.45}\n.cloud-storage-panel.launch-mode .cloud-actions{display:flex}\n.cloud-storage-panel.launch-mode .demo-note{display:block}\n.cloud-storage-panel.launch-mode{padding:12px}\n@media(max-width:900px){.launch-kpis{grid-template-columns:1fr 1fr}.privacy-grid{grid-template-columns:1fr 1fr}.launch-hero-dashboard h2{font-size:21px}}\n\n\n\/* Performance fix: keep hidden tabs from doing layout work *\/\n.card.hide{display:none!important}\n.tab,.workflow-pill,button{touch-action:manipulation}\n\n\n\/* Vault unlock visibility fix *\/\n.cloud-storage-panel.launch-mode .cloud-actions{display:flex!important}\n.cloud-storage-panel.launch-mode .demo-note{display:block!important}\n.launch-actions button:first-child{background:#C9A84C!important;color:#111!important;border:2px solid #C9A84C!important}\n#cloudStorageStatus{cursor:pointer}\n\n\n\/* v2.6 AI Listing Readiness Engine *\/\n.readiness-card{background:#fff;border:1px solid var(--bdr);border-left:5px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:12px;margin-bottom:8px}\n.readiness-card.high{border-left-color:var(--green)}\n.readiness-card.medium{border-left-color:var(--amber)}\n.readiness-card.low{border-left-color:var(--red)}\n.readiness-score{width:48px;height:48px;border-radius:50%;background:var(--B);color:var(--G2);display:flex;align-items:center;justify-content:center;font-weight:900}\n\n\/* v2.4 Pipeline & Follow-Up Manager *\/\n.pipeline-manager-grid{display:grid;grid-template-columns:330px 1fr;gap:14px;margin-top:14px}\n.pipeline-action-panel{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:14px;margin-bottom:10px}\n.pipeline-status-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:10px 0}\n.pipeline-status-card{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:10px;text-align:center}\n.pipeline-status-card span{display:block;font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--txt3);font-weight:900}\n.pipeline-status-card b{display:block;font-size:22px;margin-top:4px}\n.timeline-item{background:#fff;border:1px solid var(--bdr);border-left:4px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:10px;margin-bottom:8px}\n.timeline-item b{display:block}\n.timeline-item small{color:var(--txt3)}\n.ai-suggestion{background:#fff8e6;border:1px solid var(--G2);border-left:5px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:12px;margin-bottom:8px}\n.ai-suggestion strong{color:#654d00}\n.pipeline-quick-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px}\n.pipeline-quick-grid button{padding:8px 10px;font-size:11px}\n.pipeline-mini-note{font-size:12px;color:var(--txt2);margin-top:6px}\n@media(max-width:900px){.pipeline-manager-grid{grid-template-columns:1fr}.pipeline-status-grid,.pipeline-quick-grid{grid-template-columns:1fr}}\n\n\n\/* v2.7 Sales Navigator Companion *\/\n.salesnav-grid{display:grid;grid-template-columns:340px 1fr;gap:14px;margin-top:14px}\n.salesnav-card{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:14px;margin-bottom:10px}\n.salesnav-hero{background:linear-gradient(135deg,#111,#2b2309);color:#fff;border-radius:var(--rl);padding:18px;margin-bottom:14px;border-bottom:5px solid var(--G2)}\n.salesnav-hero h3{color:var(--G2)!important;border:0!important;margin:0 0 6px!important;padding:0!important}\n.salesnav-hero p{color:rgba(255,255,255,.78)}\n.salesnav-query{background:var(--card2);border-left:4px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:14px;white-space:pre-wrap;margin-bottom:10px}\n.salesnav-metric-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin:12px 0}\n.salesnav-metric{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:12px;text-align:center}\n.salesnav-metric span{display:block;font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--txt3);font-weight:900}\n.salesnav-metric b{display:block;font-size:24px;margin-top:4px}\n.salesnav-tip{background:#fff8e6;border:1px solid var(--G2);border-left:5px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:12px;margin-bottom:8px}\n.salesnav-tip strong{color:#654d00}\n.salesnav-link{display:inline-block;text-decoration:none;border-radius:var(--r);padding:10px 15px;font-weight:900;background:var(--B);color:var(--G2);border:2px solid var(--G2);margin:4px 6px 4px 0}\n@media(max-width:900px){.salesnav-grid{grid-template-columns:1fr}.salesnav-metric-grid{grid-template-columns:1fr}}\n\n\n\/* v2.8 Advanced Follow-Up Automation *\/\n.automation28-hero{background:linear-gradient(135deg,#111,#2b2309);color:#fff;border-radius:var(--rl);padding:18px;margin-bottom:14px;border-bottom:5px solid var(--G2)}\n.automation28-hero h3{color:var(--G2)!important;border:0!important;margin:0 0 6px!important;padding:0!important}\n.automation28-hero p{color:rgba(255,255,255,.78)}\n.automation28-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin:12px 0}\n.automation28-kpi{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:12px;text-align:center}\n.automation28-kpi span{display:block;font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--txt3);font-weight:900}\n.automation28-kpi b{display:block;font-size:25px;margin-top:4px}\n.automation28-row{background:#fff;border:1px solid var(--bdr);border-left:5px solid var(--G2);border-radius:0 var(--r) var(--r) 0;padding:12px;margin-bottom:8px;display:grid;grid-template-columns:1fr auto;gap:10px;align-items:center}\n.automation28-row.overdue{border-left-color:var(--red)}\n.automation28-row.today{border-left-color:var(--amber)}\n.automation28-row.priority{border-left-color:var(--green)}\n.automation28-row b{display:block}\n.automation28-row small{color:var(--txt3)}\n.automation28-actions{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}\n.automation28-actions button{padding:6px 9px;font-size:10px}\n.automation28-board{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:12px}\n.automation28-panel{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:12px}\n.automation28-panel h4{font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--txt2);margin-bottom:8px}\n.cadence-step{background:#fff;border:1px solid var(--bdr);border-radius:var(--r);padding:10px;margin-bottom:7px}\n.cadence-step.done{background:#e4f4e9;border-color:rgba(45,122,79,.35)}\n.cadence-step.due{background:#fff3d5;border-color:rgba(138,90,0,.35)}\n.cadence-step.overdue{background:#fff0ee;border-color:rgba(179,58,47,.35)}\n@media(max-width:900px){.automation28-grid,.automation28-board{grid-template-columns:1fr}.automation28-row{grid-template-columns:1fr}.automation28-actions{justify-content:flex-start}}\n\n\n\n\/* v2.9 Member Login + User AI API Key Layer *\/\n.member-auth-gate{display:none;background:#fff;border:1px solid var(--bdr);border-radius:var(--rl);padding:18px;margin-bottom:16px;box-shadow:0 8px 22px rgba(0,0,0,.04)}\n.member-auth-gate.show{display:block}\n.member-auth-hero{background:linear-gradient(135deg,#111,#2b2309);color:#fff;border-radius:var(--rl);padding:18px;border-bottom:5px solid var(--G2);margin-bottom:14px}\n.member-auth-hero h2{font:900 22px var(--fH);color:var(--G2);text-transform:uppercase;letter-spacing:.04em;margin:0 0 5px}\n.member-auth-hero p{color:rgba(255,255,255,.76)}\n.member-auth-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}\n.member-auth-card{background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:14px}\n.member-auth-card h3{font-size:13px;text-transform:uppercase;letter-spacing:.06em;color:#654d00;border-bottom:2px solid var(--G2);padding-bottom:6px;margin-bottom:10px}\n.api-key-panel{background:#fff;border:1px solid var(--bdr);border-radius:var(--rl);padding:16px;margin-bottom:16px;box-shadow:0 8px 22px rgba(0,0,0,.04)}\n.api-key-panel.locked{border-color:#e0aaa3;background:#fff8f7}\n.api-key-status{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:8px 0 0}\n.api-key-note{font-size:12px;color:var(--txt2);margin-top:8px}\n.api-key-mask{font-family:monospace;background:var(--card2);border:1px solid var(--bdr);border-radius:var(--r);padding:9px 10px;color:var(--txt2)}\nbody.ads-member-blocked .workflow-nav,body.ads-member-blocked .launch-hero-dashboard,body.ads-member-blocked .privacy-center,body.ads-member-blocked .cloud-storage-panel,body.ads-member-blocked .nav,body.ads-member-blocked .grid{display:none!important}\nbody.ads-ai-key-required .launch-hero-dashboard{border-color:var(--red)}\n@media(max-width:900px){.member-auth-grid{grid-template-columns:1fr}}\n@media print{.member-auth-gate,.api-key-panel{display:none!important}}\n\n\n\/* v2.10 member simplification: hide technical\/admin-only endpoint setup from end users *\/\n.ads-admin-only,#apiSetupTab{display:none!important}\n#userApiKeyPanel .api-key-note{max-width:900px}\n\n<\/style>\n<\/head>\n<body>\n<div class=\"wrap\">\n\n<div id=\"memberAuthGate\" class=\"member-auth-gate\">\n  <div class=\"member-auth-hero\">\n    <h2>Member Login Required<\/h2>\n    <p>This version uses your WordPress subscriber portal. Members sign in with the username\/email and password you create for them in WordPress.<\/p>\n  <\/div>\n  <div class=\"member-auth-grid\">\n    <div class=\"member-auth-card\">\n      <h3>WordPress Subscriber Login<\/h3>\n      <div class=\"field\"><label>User ID \/ Email<\/label><input id=\"memberLoginUser\" autocomplete=\"username\" placeholder=\"your@email.com\"><\/div>\n      <div class=\"field\"><label>Password<\/label><input id=\"memberLoginPass\" type=\"password\" autocomplete=\"current-password\" placeholder=\"WordPress password\"><\/div>\n      <div class=\"actions\">\n        <button class=\"primary\" onclick=\"adsMemberLogin()\">Login<\/button>\n        <button class=\"light\" onclick=\"adsOpenWpLogin()\">Open WordPress Login<\/button>\n      <\/div>\n      <div id=\"memberLoginStatus\" class=\"api-key-note\">Members use only their WordPress login. No separate workspace password is required.<\/div>\n    <\/div>\n    <div class=\"member-auth-card\">\n      <h3>Portal Requirement<\/h3>\n      <p class=\"api-key-note\">Protect this page with your existing WordPress subscriber\/member access. If the member is not signed in, the tool sends them to the normal WordPress login page and returns them here after login.<\/p>\n    <\/div>\n  <\/div>\n<\/div>\n\n<div id=\"userApiKeyPanel\" class=\"api-key-panel locked\">\n  <h3>User AI Service API Key<\/h3>\n  <div class=\"notice\">Each member must add their own AI service API key one time on their first device\/browser access. The key is saved locally on that member's browser and can also be included inside the encrypted workspace after the workspace is opened.<\/div>\n  <div class=\"two\">\n    <div class=\"field\"><label>AI Service Provider<\/label><select id=\"adsAiProvider\"><option value=\"openai\" selected>OpenAI-compatible<\/option><option value=\"anthropic\">Anthropic-compatible<\/option><option value=\"custom\">Custom HTTPS API<\/option><\/select><\/div>\n    <div class=\"field\"><label>Model \/ Endpoint Model Name<\/label><input id=\"adsAiModel\" value=\"gpt-4.1-mini\" placeholder=\"gpt-4.1-mini\"><\/div>\n  <\/div>\n  <div class=\"field\"><label>AI Service API Key<\/label><input id=\"adsAiApiKey\" type=\"password\" autocomplete=\"off\" placeholder=\"Paste your API key once\"><\/div>\n  <input id=\"adsAiEndpoint\" type=\"hidden\" value=\"\/wp-json\/ai-deal-sourcing\/v1\/ai-complete\">\n  <div class=\"actions\">\n    <button class=\"primary\" onclick=\"adsSaveUserApiKey()\">Save My API Key<\/button>\n    <button class=\"light\" onclick=\"adsForgetUserApiKey()\">Forget Key<\/button>\n  <\/div>\n  <div class=\"api-key-status\">\n    <span id=\"adsAiKeyStatus\" class=\"cloud-badge risk\">AI key required<\/span>\n    <span id=\"adsMemberStatus\" class=\"cloud-badge warn\">Checking member login<\/span>\n  <\/div>\n  <div id=\"adsAiKeyMask\" class=\"api-key-mask\">No API key saved on this browser.<\/div>\n  <div class=\"api-key-note\">Your AI key is saved only for this WordPress member on this browser. You will only need to enter it again if you clear browser storage or use a different device.<\/div>\n<\/div>\n\n\n<div class=\"topbar pro-topbar\">\n  <div class=\"brand pro-brand\">\n    <div class=\"brand-logo brand-logo-lite\" aria-label=\"360 Biz Brokers logo\"><span>360<\/span><small>BIZ BROKERS<\/small><\/div>\n    <div>\n      <h1>AI Assisted Deals Sourcing Pro\u2122<\/h1>\n      <p>Powered by 360 Biz Brokers<\/p>\n    <\/div>\n  <\/div>\n  <div class=\"badge\">Deal Origination OS<\/div>\n<\/div>\n\n<div class=\"workflow-nav\">\n  <div class=\"workflow-title\">Deal Origination Workflow<\/div>\n  <div class=\"workflow-steps\">\n    <div class=\"workflow-pill\" data-step-tab=\"discovery\" onclick=\"goWorkflowStep('discovery',this)\"><span>Step 1<\/span><b>Source Prospects<\/b><\/div>\n    <div class=\"workflow-pill\" data-step-tab=\"apollo\" onclick=\"goWorkflowStep('apollo',this)\"><span>Step 2A<\/span><b>Find Owner<\/b><\/div>\n    <div class=\"workflow-pill\" data-step-tab=\"scanner\" onclick=\"goWorkflowStep('scanner',this)\"><span>Step 2<\/span><b>Scan Opportunities<\/b><\/div>\n    <div class=\"workflow-pill\" data-step-tab=\"sequence\" onclick=\"goWorkflowStep('sequence',this)\"><span>Step 3<\/span><b>Generate Outreach<\/b><\/div>\n    <div class=\"workflow-pill\" data-step-tab=\"succession\" onclick=\"goWorkflowStep('succession',this)\"><span>Step 4<\/span><b>Analyze Succession<\/b><\/div>\n    <div class=\"workflow-pill\" data-step-tab=\"buyers\" onclick=\"goWorkflowStep('buyers',this)\"><span>Step 5<\/span><b>Match Buyers<\/b><\/div>\n    <div class=\"workflow-pill\" data-step-tab=\"pursuit\" onclick=\"goWorkflowStep('pursuit',this)\"><span>Step 6<\/span><b>Build Pursuit Plan<\/b><\/div>\n    <div class=\"workflow-pill\" data-step-tab=\"pipeline\" onclick=\"goWorkflowStep('pipeline',this)\"><span>Step 7<\/span><b>Manage Pipeline<\/b><\/div>\n    <div class=\"workflow-pill\" data-step-tab=\"followup\" onclick=\"goWorkflowStep('followup',this)\"><span>Step 8<\/span><b>Execute Follow-Up<\/b><\/div>\n    <div class=\"workflow-pill\" data-step-tab=\"market\" onclick=\"goWorkflowStep('market',this)\"><span>Step 9<\/span><b>Market Domination<\/b><\/div>\n  <\/div>\n<\/div>\n\n\n\n\n\n<div class=\"launch-hero-dashboard\">\n  <div class=\"launch-hero-top\">\n    <div>\n      <h2>Member Command Dashboard<\/h2>\n      <p>Welcome, <span id=\"launchMemberName\" class=\"launch-member-name\">Member<\/span>. Your private workspace is protected by encrypted cloud storage.<\/p>\n    <\/div>\n    <div class=\"badge\"><span id=\"launchSyncDot\" class=\"sync-dot\"><\/span><span id=\"launchCloudStatus\">Checking Cloud<\/span><\/div>\n  <\/div>\n  <div class=\"launch-kpis\">\n    <div class=\"launch-kpi\"><span>Prospects<\/span><b id=\"launchProspects\">0<\/b><\/div>\n    <div class=\"launch-kpi\"><span>Active Pipeline<\/span><b id=\"launchPipeline\">0<\/b><\/div>\n    <div class=\"launch-kpi\"><span>Hot Opportunities<\/span><b id=\"launchHot\">0<\/b><\/div>\n    <div class=\"launch-kpi\"><span>Follow-Ups Due<\/span><b id=\"launchDue\">0<\/b><\/div>\n    <div class=\"launch-kpi\"><span>Last Sync<\/span><b id=\"launchLastSync\">\u2014<\/b><\/div>\n    <div class=\"launch-kpi\"><span>Meetings<\/span><b id=\"launchMeetings\">0<\/b><\/div>\n    <div class=\"launch-kpi\"><span>Listings<\/span><b id=\"launchListings\">0<\/b><\/div>\n    <div class=\"launch-kpi\"><span>Won<\/span><b id=\"launchWon\">0<\/b><\/div>\n    <div class=\"launch-kpi\"><span>High Readiness<\/span><b id=\"launchReadiness\">0<\/b><\/div>\n  <\/div>\n  <div class=\"launch-actions\">\n    <button class=\"primary\" onclick=\"vaultUnlock()\">Open Member Workspace<\/button>\n    <button class=\"primary\" onclick=\"goWorkflowStep('discovery',document.querySelector('[data-step-tab=discovery]'))\">Source Prospects<\/button>\n    <button class=\"secondary\" onclick=\"goWorkflowStep('pipeline',document.querySelector('[data-step-tab=pipeline]'))\">Continue Pipeline<\/button>\n    <button class=\"light\" onclick=\"goWorkflowStep('sequence',document.querySelector('[data-step-tab=sequence]'))\">Generate Outreach<\/button>\n  <\/div>\n<\/div>\n\n<div class=\"privacy-center\">\n  <h3>Private Member Workspace<\/h3>\n  <div class=\"privacy-grid\">\n    <div class=\"privacy-item\">\u2713 Encrypted Storage<\/div>\n    <div class=\"privacy-item\">\u2713 Member-Isolated Records<\/div>\n    <div class=\"privacy-item\">\u2713 Cloud Backup<\/div>\n    <div class=\"privacy-item\">\u2713 Export Your Data<\/div>\n    <div class=\"privacy-item\">\u2713 Delete Your Data<\/div>\n  <\/div>\n  <div class=\"privacy-note\">Your prospect records, pipeline activity, notes, and reports are private to your logged-in account and stored in encrypted form. Other members cannot access your workspace.<\/div>\n<\/div>\n\n<div class=\"cloud-storage-panel launch-mode\">\n<h3>Cloud Sync<\/h3>\n<div class=\"cloud-status\">\n  <span id=\"cloudStorageStatus\" class=\"cloud-badge warn\" onclick=\"vaultUnlock()\" style=\"cursor:pointer\">Member Workspace locked<\/span>\n  <span class=\"cloud-badge\">End-to-End Encrypted<\/span>\n  <span class=\"cloud-badge\">Private Workspace<\/span>\n<\/div>\n<div class=\"cloud-actions\">\n  <button class=\"secondary\" onclick=\"vaultUnlock()\">Open Member Workspace<\/button>\n  <button class=\"secondary\" onclick=\"cloudLoadNow()\">Load Encrypted Data<\/button>\n  <button class=\"secondary\" onclick=\"cloudSaveNow()\">Save Encrypted Data<\/button>\n  <button class=\"light\" onclick=\"vaultLock()\">Sign Out \/ Lock Workspace<\/button>\n  <button class=\"light\" onclick=\"cloudMigrateLocal()\">Migrate Old Browser Records<\/button>\n<\/div>\n<div class=\"demo-note\">Cloud records are tied to the logged-in WordPress user. Browser records are not automatically copied unless you click \u201cMigrate Browser Records.\u201d<\/div>\n<\/div>\n\n<div class=\"nav\">\n<div class=\"nav-section-label\">Core Workflow<\/div>\n<button class=\"tab active\" onclick=\"showTab('dashboard',event)\">Command Center<\/button>\n<button class=\"tab\" onclick=\"showTab('discovery',event)\">Prospect Sourcing<\/button>\n<button class=\"tab\" onclick=\"showTab('apollo',event)\">Owner Discovery<\/button>\n<button class=\"tab\" onclick=\"showTab('salesnav',event)\">Sales Navigator<\/button>\n<button class=\"tab\" onclick=\"showTab('scanner',event)\">Opportunity Scanner<\/button>\n<button class=\"tab\" onclick=\"showTab('sequence',event)\">Outreach Sequence<\/button>\n<button class=\"tab\" onclick=\"showTab('succession',event)\">Succession<\/button>\n<button class=\"tab\" onclick=\"showTab('buyers',event)\">Buyer Match<\/button>\n<button class=\"tab\" onclick=\"showTab('pursuit',event)\">Pursuit Planner<\/button>\n<button class=\"tab\" onclick=\"showTab('pipeline',event)\">Pipeline<\/button>\n<button class=\"tab\" onclick=\"showTab('followup',event)\">Follow-Up Engine<\/button>\n<button class=\"tab\" onclick=\"showTab('market',event)\">Market Domination<\/button>\n<div class=\"nav-section-label\">Advanced Tools<\/div>\n<button class=\"tab\" onclick=\"showTab('master',event)\">Master Dashboard<\/button>\n<button class=\"tab\" onclick=\"showTab('rollup',event)\">Roll-Up Intelligence<\/button>\n<button class=\"tab\" onclick=\"showTab('outreach',event)\">Outreach Generator<\/button>\n<button class=\"tab\" onclick=\"showTab('coach',event)\">Conversation Coach<\/button>\n<button class=\"tab\" onclick=\"showTab('scorecard',event)\">Opportunity Scorecard<\/button>\n<button class=\"tab\" onclick=\"showTab('assessment',event)\">Exit Assessment<\/button>\n<button class=\"tab\" onclick=\"showTab('report',event)\">Seller Report<\/button>\n<button class=\"tab\" onclick=\"showTab('analytics',event)\">Analytics<\/button>\n<button class=\"tab\" onclick=\"showTab('intelligence',event)\">Listing Readiness<\/button>\n<button class=\"tab\" onclick=\"showTab('workflow',event)\">Workflow<\/button>\n<button class=\"tab\" onclick=\"showTab('conversion',event)\">Conversion<\/button>\n<button class=\"tab\" onclick=\"showTab('presentation',event)\">Listing Presentation<\/button>\n<button class=\"tab\" onclick=\"showTab('release',event)\">System QA<\/button>\n<button class=\"tab ads-admin-only\" onclick=\"showTab('apiSetup',event)\">API Setup<\/button>\n<\/div>\n\n<div class=\"grid\">\n<div class=\"leftcol\">\n<div class=\"card\">\n<h2>Prospect Record<\/h2>\n<div class=\"help\">Create or select a prospect. All modules save to your private encrypted vault after you unlock it.<\/div>\n<div class=\"field\"><label>Business Name<\/label><input id=\"bizName\" placeholder=\"Tampa HVAC Services\"><\/div>\n<div class=\"two\"><div class=\"field\"><label>Industry<\/label><input id=\"industry\" placeholder=\"HVAC, restaurant, auto repair\"><\/div><div class=\"field\"><label>Location<\/label><input id=\"location\" placeholder=\"City, State\"><\/div><\/div>\n<div class=\"two\"><div class=\"field\"><label>Owner Name<\/label><input id=\"owner\" placeholder=\"Optional\"><\/div><div class=\"field\"><label>Revenue Range<\/label><select id=\"revenue\"><option>Under $500K<\/option><option>$500K\u2013$1M<\/option><option selected>$1M\u2013$3M<\/option><option>$3M\u2013$10M<\/option><option>$10M+<\/option><\/select><\/div><\/div>\n<div class=\"two\"><div class=\"field\"><label>Years in Business<\/label><input id=\"years\" type=\"number\" min=\"0\" placeholder=\"18\"><\/div><div class=\"field\"><label>Employees<\/label><input id=\"employees\" type=\"number\" min=\"0\" placeholder=\"12\"><\/div><\/div>\n<div class=\"field\"><label>Known Seller Signals \/ Context<\/label><textarea id=\"context\" placeholder=\"Retirement, burnout, declining reviews, succession issues, recent job posting, etc.\"><\/textarea><\/div>\n<div class=\"field\"><label>Pipeline Stage<\/label><select id=\"stage\"><option>New Prospect<\/option><option>Identified<\/option><option>Researched<\/option><option>Owner Identified<\/option><option>Outreach Generated<\/option><option>Contacted<\/option><option>Follow-Up Scheduled<\/option><option>Interested<\/option><option>Conversation Started<\/option><option>Meeting Scheduled<\/option><option>Meeting Booked<\/option><option>Listing Opportunity<\/option><option>Listing Agreement<\/option><option>Active Listing<\/option><option>Under Contract<\/option><option>Closed Won<\/option><option>Closed Lost<\/option><option>Closed<\/option><\/select><\/div>\n<div class=\"two\"><div class=\"field\"><label>Next Action<\/label><input id=\"nextAction\" placeholder=\"Call owner\"><\/div><div class=\"field\"><label>Due Date<\/label><input id=\"dueDate\" type=\"date\"><\/div><\/div>\n<div class=\"actions\"><button class=\"primary\" onclick=\"saveProspect()\">Save Prospect<\/button><button class=\"light\" onclick=\"clearForm()\">Clear<\/button><\/div>\n<\/div>\n\n<div class=\"card\">\n<h2>Saved Prospects<\/h2>\n<div id=\"prospectList\" class=\"prospect-list\"><\/div>\n<div class=\"actions\"><button class=\"secondary\" onclick=\"exportData()\">Export Backup<\/button><button class=\"light\" onclick=\"exportCSV()\">Export CSV<\/button><button class=\"light\" onclick=\"loadDemoData()\">Load Demo Data<\/button><button class=\"danger\" onclick=\"resetDemoData()\">Reset All<\/button><button class=\"light\" onclick=\"document.getElementById('importFile').click()\">Import<\/button><input id=\"importFile\" type=\"file\" accept=\".json\" style=\"display:none\" onchange=\"importData(event)\"><\/div><div class=\"demo-note\">Member workspace mode: data is tied to the logged-in WordPress user. No separate workspace password is required.<\/div>\n<\/div>\n<\/div>\n\n<div>\n\n\n\n\n\n\n<div id=\"rollupTab\" class=\"card hide\">\n<h2>Roll-Up Intelligence<\/h2>\n<div class=\"notice\">Analyzes saved and sourced prospects to identify industries and markets where multiple businesses could support a buyer roll-up, add-on acquisition, or consolidation strategy.<\/div>\n\n<div class=\"metric-grid\">\n<div class=\"metric\"><span>Roll-Up Clusters<\/span><b id=\"ruClusters\">0<\/b><\/div>\n<div class=\"metric\"><span>Strong Add-Ons<\/span><b id=\"ruStrong\">0<\/b><\/div>\n<div class=\"metric\"><span>Platform Candidates<\/span><b id=\"ruPlatform\">0<\/b><\/div>\n<div class=\"metric\"><span>Avg Cluster Score<\/span><b id=\"ruAvg\">0<\/b><\/div>\n<\/div>\n\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"generateRollupIntel()\">Generate Roll-Up Intelligence<\/button>\n<button class=\"secondary\" onclick=\"saveRollupIntel()\">Save Selected Cluster Insight<\/button>\n<button class=\"light\" onclick=\"exportRollupIntel()\">Export Roll-Up Report<\/button>\n<\/div>\n\n<div class=\"rollup-grid\" style=\"margin-top:14px\">\n<div>\n<div class=\"rollup-card\">\n<h3>Roll-Up Settings<\/h3>\n<div class=\"field\"><label>Cluster By<\/label><select id=\"rollupClusterBy\"><option value=\"industry\" selected>Industry<\/option><option value=\"location\">Location<\/option><option value=\"industryLocation\">Industry + Location<\/option><\/select><\/div>\n<div class=\"field\"><label>Minimum Cluster Size<\/label><select id=\"rollupMin\"><option value=\"2\" selected>2 Prospects<\/option><option value=\"3\">3 Prospects<\/option><option value=\"5\">5 Prospects<\/option><\/select><\/div>\n<div class=\"field\"><label>Buyer Strategy<\/label><select id=\"rollupStrategy\"><option value=\"addon\" selected>Add-On Acquisition<\/option><option value=\"platform\">Platform + Add-Ons<\/option><option value=\"territory\">Territory Consolidation<\/option><option value=\"strategic\">Strategic Buyer Expansion<\/option><\/select><\/div>\n<\/div>\n<div class=\"rollup-card\">\n<h3>Selected Cluster<\/h3>\n<div id=\"rollupSelected\" class=\"output\">Generate roll-up intelligence to view clusters.<\/div>\n<\/div>\n<\/div>\n\n<div>\n<h3>Roll-Up Clusters<\/h3>\n<div id=\"rollupClusters\"><\/div>\n\n<h3>Roll-Up Strategy Memo<\/h3>\n<div id=\"rollupMemo\" class=\"output\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<div id=\"buyersTab\" class=\"card hide\">\n<h2>Buyer Matching Engine<\/h2>\n<div class=\"notice\">Matches the selected seller prospect to likely buyer types and recommends an acquisition positioning strategy.<\/div>\n\n<div class=\"metric-grid\">\n<div class=\"metric\"><span>Strategic Buyers<\/span><b id=\"bmStrategic\">0<\/b><\/div>\n<div class=\"metric\"><span>Owner Operators<\/span><b id=\"bmOwnerOps\">0<\/b><\/div>\n<div class=\"metric\"><span>Search Funds<\/span><b id=\"bmSearch\">0<\/b><\/div>\n<div class=\"metric\"><span>PE \/ Family Office<\/span><b id=\"bmPE\">0<\/b><\/div>\n<\/div>\n\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"generateBuyerMatches()\">Generate Buyer Matches<\/button>\n<button class=\"secondary\" onclick=\"saveBuyerMatch()\">Save Buyer Match Insight<\/button>\n<button class=\"light\" onclick=\"exportBuyerMatch()\">Export Buyer Match<\/button>\n<\/div>\n\n<div class=\"buyer-grid\" style=\"margin-top:14px\">\n<div>\n<div class=\"buyer-card\">\n<h3>Selected Prospect<\/h3>\n<div id=\"buyerSelected\" class=\"output\">Select a prospect first.<\/div>\n<\/div>\n<div class=\"buyer-card\">\n<h3>Buyer Match Settings<\/h3>\n<div class=\"field\"><label>Preferred Buyer Strategy<\/label><select id=\"buyerStrategy\"><option value=\"best\" selected>Best Fit<\/option><option value=\"strategic\">Strategic Buyer<\/option><option value=\"owneroperator\">Owner Operator<\/option><option value=\"searchfund\">Search Fund<\/option><option value=\"pe\">Private Equity \/ Family Office<\/option><\/select><\/div>\n<div class=\"field\"><label>Geography Preference<\/label><select id=\"buyerGeo\"><option value=\"local\" selected>Local \/ Regional<\/option><option value=\"state\">Statewide<\/option><option value=\"national\">National<\/option><\/select><\/div>\n<\/div>\n<\/div>\n\n<div>\n<h3>Recommended Buyer Types<\/h3>\n<div id=\"buyerMatches\"><\/div>\n\n<h3>Buyer Positioning Memo<\/h3>\n<div id=\"buyerMemo\" class=\"output\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<div id=\"successionTab\" class=\"card hide\">\n<h2>Succession Intelligence<\/h2>\n<div class=\"notice\">Classifies the selected prospect into an owner exit persona, estimates transition timeline, and generates conversation intelligence for succession, retirement, lifestyle, and legacy discussions.<\/div>\n\n<div class=\"metric-grid\">\n<div class=\"metric\"><span>Retirement Candidates<\/span><b id=\"succRetire\">0<\/b><\/div>\n<div class=\"metric\"><span>Legacy Sellers<\/span><b id=\"succLegacy\">0<\/b><\/div>\n<div class=\"metric\"><span>Strategic Sellers<\/span><b id=\"succStrategic\">0<\/b><\/div>\n<div class=\"metric\"><span>Exit Ready<\/span><b id=\"succReady\">0<\/b><\/div>\n<\/div>\n\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"generateSuccessionIntel()\">Generate Succession Intelligence<\/button>\n<button class=\"secondary\" onclick=\"saveSuccessionIntel()\">Save to Prospect<\/button>\n<button class=\"light\" onclick=\"exportSuccessionIntel()\">Export Intelligence<\/button>\n<\/div>\n\n<div class=\"succession-grid\" style=\"margin-top:14px\">\n<div>\n<div class=\"succession-card\">\n<h3>Selected Prospect<\/h3>\n<div id=\"successionSelected\" class=\"output\">Select a prospect first.<\/div>\n<\/div>\n<div class=\"succession-card\">\n<h3>Conversation Settings<\/h3>\n<div class=\"field\"><label>Conversation Style<\/label><select id=\"succStyle\"><option value=\"relationship\" selected>Relationship First<\/option><option value=\"education\">Educational Advisor<\/option><option value=\"valuation\">Valuation Led<\/option><option value=\"succession\">Succession Planning<\/option><\/select><\/div>\n<div class=\"field\"><label>Broker Goal<\/label><select id=\"succGoal\"><option value=\"discovery\" selected>Discovery Call<\/option><option value=\"valuation\">Valuation Meeting<\/option><option value=\"assessment\">Exit Readiness Assessment<\/option><option value=\"listing\">Listing Strategy Conversation<\/option><\/select><\/div>\n<\/div>\n<\/div>\n\n<div>\n<div id=\"successionPersona\" class=\"persona-card\">\n<h3>Exit Persona<\/h3>\n<p>Generate intelligence to classify the prospect.<\/p>\n<\/div>\n\n<h3>Broker Guidance<\/h3>\n<div id=\"successionGuidance\" class=\"question-list\"><\/div>\n\n<h3>Conversation Questions<\/h3>\n<div id=\"successionQuestions\" class=\"question-list\"><\/div>\n\n<h3>Likely Objections & Responses<\/h3>\n<div id=\"successionObjections\" class=\"question-list\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<div id=\"sequenceTab\" class=\"card hide\">\n<h2>Outreach Sequence Generator<\/h2>\n<div class=\"notice\">Generates a contact-aware outreach package using the selected prospect, saved Apollo owner contact, opportunity profile, and follow-up goal. Save the Apollo contact first for best personalization.<\/div>\n\n<div class=\"sequence-grid\">\n<div>\n<div class=\"sequence-card\">\n<h3>Outreach Strategy<\/h3>\n<div id=\"sequenceStrategy\" class=\"output\">Select a prospect and click Generate Sequence.<\/div>\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"generateSmartSequence()\">Generate Sequence<\/button>\n<button class=\"secondary\" onclick=\"saveSmartSequence()\">Save to Prospect<\/button>\n<button class=\"light\" onclick=\"exportSmartSequence()\">Export Text<\/button>\n<button class=\"light\" onclick=\"copyText('seqEmail1')\">Copy First Email<\/button>\n<\/div>\n<\/div>\n\n<div class=\"sequence-card\">\n<h3>Contact Used<\/h3>\n<div id=\"seqContactContext\" class=\"output\">Save an Apollo contact to a prospect, then generate outreach.<\/div>\n<div class=\"actions\">\n<button class=\"secondary\" onclick=\"markSequenceActivity('Email Sent')\">Mark Email Sent<\/button>\n<button class=\"secondary\" onclick=\"markSequenceActivity('LinkedIn Touch')\">Mark LinkedIn Touch<\/button>\n<button class=\"secondary\" onclick=\"markSequenceActivity('Call Made')\">Mark Call Made<\/button>\n<\/div>\n<\/div>\n\n<div class=\"sequence-card\">\n<h3>Sequence Settings<\/h3>\n<div class=\"field\"><label>Tone<\/label><select id=\"seqTone\"><option value=\"professional\" selected>Professional<\/option><option value=\"warm\">Warm \/ Relationship-Based<\/option><option value=\"direct\">Direct<\/option><option value=\"educational\">Educational<\/option><\/select><\/div>\n<div class=\"field\"><label>Primary Goal<\/label><select id=\"seqGoal\"><option value=\"conversation\" selected>Start a Conversation<\/option><option value=\"valuation\">Schedule Valuation Discussion<\/option><option value=\"succession\">Discuss Succession Planning<\/option><option value=\"listing\">Move Toward Listing Strategy<\/option><\/select><\/div>\n<div class=\"field\"><label>Follow-Up Cadence<\/label><select id=\"seqCadence\"><option value=\"7\" selected>Every 7 Days<\/option><option value=\"10\">Every 10 Days<\/option><option value=\"14\">Every 14 Days<\/option><option value=\"30\">Monthly Nurture<\/option><\/select><\/div>\n<\/div>\n<\/div>\n\n<div>\n<h3>Email #1 \u2014 Initial Contact<\/h3>\n<div class=\"sequence-actions\"><button class=\"copybtn\" onclick=\"copyText('seqEmail1')\">Copy<\/button><\/div>\n<div id=\"seqEmail1\" class=\"sequence-output\"><\/div>\n\n<h3>Email #2 \u2014 Value Follow-Up<\/h3>\n<div class=\"sequence-actions\"><button class=\"copybtn\" onclick=\"copyText('seqEmail2')\">Copy<\/button><\/div>\n<div id=\"seqEmail2\" class=\"sequence-output\"><\/div>\n\n<h3>Email #3 \u2014 Final Soft Follow-Up<\/h3>\n<div class=\"sequence-actions\"><button class=\"copybtn\" onclick=\"copyText('seqEmail3')\">Copy<\/button><\/div>\n<div id=\"seqEmail3\" class=\"sequence-output\"><\/div>\n\n<h3>LinkedIn Connection Message<\/h3>\n<div class=\"sequence-actions\"><button class=\"copybtn\" onclick=\"copyText('seqLinkedIn')\">Copy<\/button><\/div>\n<div id=\"seqLinkedIn\" class=\"sequence-output\"><\/div>\n\n<h3>Cold Call Script<\/h3>\n<div class=\"sequence-actions\"><button class=\"copybtn\" onclick=\"copyText('seqPhone')\">Copy<\/button><\/div>\n<div id=\"seqPhone\" class=\"sequence-output\"><\/div>\n\n<h3>Voicemail Script<\/h3>\n<div class=\"sequence-actions\"><button class=\"copybtn\" onclick=\"copyText('seqVoicemail')\">Copy<\/button><\/div>\n<div id=\"seqVoicemail\" class=\"sequence-output\"><\/div>\n\n<h3>Succession \/ Exit Conversation Guide<\/h3>\n<div class=\"sequence-actions\"><button class=\"copybtn\" onclick=\"copyText('seqGuide')\">Copy<\/button><\/div>\n<div id=\"seqGuide\" class=\"sequence-output\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<div id=\"scannerTab\" class=\"card hide\">\n<h2>Opportunity Scanner<\/h2>\n<div class=\"notice\">This scanner ranks sourced and saved prospects by seller probability, opportunity type, priority grade, and recommended broker approach.<\/div>\n\n<div class=\"metric-grid\">\n<div class=\"metric\"><span>High Probability Sellers<\/span><b id=\"scanHigh\">0<\/b><\/div>\n<div class=\"metric\"><span>Succession Candidates<\/span><b id=\"scanSuccession\">0<\/b><\/div>\n<div class=\"metric\"><span>Strategic Acquisitions<\/span><b id=\"scanStrategic\">0<\/b><\/div>\n<div class=\"metric\"><span>A+ Opportunities<\/span><b id=\"scanAplus\">0<\/b><\/div>\n<\/div>\n\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"runOpportunityScanner()\">Run Scanner<\/button>\n<button class=\"secondary\" onclick=\"saveScannerInsight()\">Save Insight to Selected Prospect<\/button>\n<button class=\"light\" onclick=\"exportScannerCSV()\">Export Scanner CSV<\/button>\n<\/div>\n\n<div class=\"scanner-grid\" style=\"margin-top:14px\">\n<div>\n<h3>Ranked Seller Opportunities<\/h3>\n<div id=\"scannerResults\" class=\"scanner-list\"><\/div>\n<\/div>\n<div>\n<h3>Selected Prospect Scan<\/h3>\n<div id=\"scannerDetail\" class=\"output\">Select a prospect or run the scanner.<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<div id=\"discoveryTab\" class=\"card hide\">\n<h2>Prospect Sourcing <span class=\"source-pill\">Live Data Ready<\/span><\/h2>\n<div class=\"notice\">Search for local businesses using any combination of fields. You can use only one field, such as ZIP code, or combine multiple fields, such as County + Industry + Radius. Blank fields are ignored.<\/div>\n\n<div class=\"live-source-panel\">\n<h3>Prospect Data Source Status<\/h3>\n<p>This module is designed to use your secure WordPress backend endpoint for Google Places and enrichment data. Use Demo Results only for training or demonstrations.<\/p>\n<span class=\"live-source-badge\">Google Places Ready<\/span>\n<span class=\"live-source-badge blue\">Backend Endpoint Supported<\/span>\n<span class=\"live-source-badge warn\">API Keys Stay Server-Side<\/span>\n<\/div>\n\n\n<div class=\"discovery-layout\">\n<div>\n<div class=\"discovery-card\">\n<h3>Search Criteria<\/h3>\n<div class=\"field\"><label>Industry \/ Category<\/label><input id=\"discIndustry\" placeholder=\"HVAC, plumbing, auto repair, restaurant\"><\/div>\n<div class=\"two\"><div class=\"field\"><label>City<\/label><input id=\"discCity\" placeholder=\"Tampa\"><\/div><div class=\"field\"><label>State<\/label><input id=\"discState\" placeholder=\"FL\"><\/div><\/div>\n<div class=\"two\"><div class=\"field\"><label>Zip Code<\/label><input id=\"discZip\" placeholder=\"33626\"><\/div><div class=\"field\"><label>County<\/label><input id=\"discCounty\" placeholder=\"Hillsborough County\"><\/div><\/div>\n<div class=\"two\"><div class=\"field\"><label>Search Radius<\/label><select id=\"discRadius\"><option value=\"5\">5 Miles<\/option><option value=\"10\">10 Miles<\/option><option value=\"25\" selected>25 Miles<\/option><option value=\"50\">50 Miles<\/option><option value=\"100\">100 Miles<\/option><\/select><\/div><div class=\"field\"><label>Result Count<\/label><select id=\"discCount\"><option>5<\/option><option selected>10<\/option><option>15<\/option><\/select><\/div><\/div>\n<div class=\"two\"><div class=\"field\"><label>Minimum Rating<\/label><select id=\"discRating\"><option value=\"0\">Any<\/option><option value=\"3.5\">3.5+<\/option><option value=\"4\" selected>4.0+<\/option><option value=\"4.5\">4.5+<\/option><\/select><\/div><div class=\"field\"><label>Minimum Years in Business<\/label><select id=\"discYearsMin\"><option value=\"0\" selected>Any<\/option><option value=\"5\">5+ Years<\/option><option value=\"10\">10+ Years<\/option><option value=\"15\">15+ Years<\/option><option value=\"20\">20+ Years<\/option><\/select><\/div><\/div>\n<div class=\"two\"><div class=\"field\"><label>Business Size<\/label><select id=\"discSize\"><option value=\"any\" selected>Any<\/option><option value=\"1-5\">1\u20135 Employees<\/option><option value=\"6-20\">6\u201320 Employees<\/option><option value=\"21-50\">21\u201350 Employees<\/option><option value=\"50+\">50+ Employees<\/option><\/select><\/div><div class=\"field\"><label>Mode<\/label><select id=\"discMode\"><option value=\"demo\" selected>Demo Results \/ Training<\/option><option value=\"api\">Live Data \/ Google Places Endpoint<\/option><\/select><\/div><\/div>\n<div class=\"field\"><label>Backend Endpoint<\/label><input id=\"discEndpoint\" value=\"\/wp-json\/ai-deal-sourcing\/v1\/prospect-search\" placeholder=\"\/wp-json\/ai-deal-sourcing\/v1\/prospect-search\"><\/div>\n<div class=\"api-status\"><strong>Security note:<\/strong> Google Places API keys stay on your secure WordPress backend\/server, not inside this HTML page.<\/div>\n<div class=\"actions\"><button class=\"primary\" onclick=\"runDiscovery()\">Source Prospects<\/button><button class=\"light\" onclick=\"clearDiscovery()\">Clear Results<\/button><\/div>\n<\/div>\n\n<div class=\"discovery-card\">\n<h3>Seller Readiness Formula<\/h3>\n<p style=\"font-size:12px;color:var(--txt2)\">Demo scoring considers rating quality, review count, estimated business age, local category, website presence, and possible owner-transition signals.<\/p>\n<\/div>\n<\/div>\n\n<div>\n<h3>Sourcing Results<\/h3>\n<div id=\"discoverySummary\" class=\"output\">Run a search to source business prospects.<\/div>\n<div id=\"discoveryResults\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n\n\n<div id=\"apolloTab\" class=\"card hide\">\n<h2>Owner Discovery <span class=\"source-pill\">Apollo Ready<\/span><\/h2>\n<div class=\"notice\">Find likely owners, founders, presidents, CEOs, managing partners, and principals for the selected prospect. Apollo runs through a secure WordPress endpoint so the API key is not exposed inside this HTML page.<\/div>\n\n<div class=\"api-grid\">\n<div>\n<div class=\"api-card\">\n<h4>Selected Prospect<\/h4>\n<div id=\"apolloSelected\" class=\"output\">Select a prospect first, or enter company information below.<\/div>\n<\/div>\n\n<div class=\"api-card\">\n<h4>Apollo Search Criteria<\/h4>\n<div class=\"field\"><label>Company Name<\/label><input id=\"apolloCompany\" placeholder=\"ABC Manufacturing\"><\/div>\n<div class=\"field\"><label>Company Website \/ Domain<\/label><input id=\"apolloDomain\" placeholder=\"example.com\"><\/div>\n<div class=\"field\"><label>Company Location<\/label><input id=\"apolloLocation\" placeholder=\"Tampa, FL\"><\/div>\n<div class=\"field\"><label>Target Titles<\/label><input id=\"apolloTitles\" value=\"owner, founder, president, ceo, chief executive officer, managing partner, principal\"><\/div>\n<div class=\"field\"><label>WordPress Apollo Endpoint<\/label><input id=\"apolloEndpoint\" value=\"\/wp-json\/brokers-pro-suite\/v1\/apollo\/owner-search\"><\/div>\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"apolloSearchOwners()\">Find Owner Contacts<\/button>\n<button class=\"secondary\" onclick=\"apolloFillFromSelected()\">Use Selected Prospect<\/button>\n<button class=\"light\" onclick=\"apolloClearResults()\">Clear<\/button>\n<\/div>\n<div class=\"demo-note\">Tip: website\/domain improves owner matching. Apollo people search may return names, titles, LinkedIn URLs, and company details. Email reveal depends on your Apollo plan and snippet settings.<\/div>\n<\/div>\n<\/div>\n\n<div>\n<h3>Owner Discovery Results<\/h3>\n<div id=\"apolloStatus\" class=\"output\">Run a search to find likely decision makers.<\/div>\n<div id=\"apolloResults\"><\/div>\n\n<h3>Selected Contact<\/h3>\n<div id=\"apolloSelectedContact\" class=\"output\">No contact selected yet.<\/div>\n<div class=\"actions\">\n<button class=\"secondary\" onclick=\"apolloEnrichSelected()\">Enrich Selected Contact<\/button>\n<button class=\"primary\" onclick=\"apolloSaveSelectedContact()\">Save Contact to Prospect<\/button>\n<button class=\"light\" onclick=\"showTab('sequence',{target:document.querySelector('[onclick*=sequence]')})\">Generate Outreach<\/button>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<div id=\"salesnavTab\" class=\"card hide\">\n<h2>Sales Navigator Companion <span class=\"source-pill\">Apollo Fallback<\/span><\/h2>\n<div class=\"notice\">Use this when Apollo returns no contacts or weak matches. The companion creates a Sales Navigator search plan, gives copy-ready search strings, and lets the broker manually save the owner\/contact back to the prospect.<\/div>\n\n<div class=\"salesnav-hero\">\n<h3>No Dead-End Owner Discovery<\/h3>\n<p>Apollo is still the first stop. When Apollo has weak coverage for small owner-operated businesses, Sales Navigator becomes the research assistant path.<\/p>\n<\/div>\n\n<div class=\"salesnav-metric-grid\">\n<div class=\"salesnav-metric\"><span>Apollo Owners<\/span><b id=\"snApolloOwners\">0<\/b><\/div>\n<div class=\"salesnav-metric\"><span>Manual Owners<\/span><b id=\"snManualOwners\">0<\/b><\/div>\n<div class=\"salesnav-metric\"><span>No Owner Yet<\/span><b id=\"snNoOwner\">0<\/b><\/div>\n<\/div>\n\n<div class=\"salesnav-grid\">\n<div>\n<div class=\"salesnav-card\">\n<h3>Selected Prospect<\/h3>\n<div id=\"snSelected\" class=\"output\">Select a prospect first.<\/div>\n<div class=\"actions\">\n<button class=\"secondary\" onclick=\"salesNavFillFromSelected()\">Use Selected Prospect<\/button>\n<button class=\"light\" onclick=\"showTab('apollo',{target:document.querySelector('[onclick*=apollo]')})\">Back to Apollo<\/button>\n<\/div>\n<\/div>\n\n<div class=\"salesnav-card\">\n<h3>Sales Navigator Search Setup<\/h3>\n<div class=\"field\"><label>Company Name<\/label><input id=\"snCompany\" placeholder=\"Ace Pack and Ship\"><\/div>\n<div class=\"field\"><label>Location<\/label><input id=\"snLocation\" placeholder=\"Winter Garden, FL\"><\/div>\n<div class=\"field\"><label>Website \/ Domain<\/label><input id=\"snDomain\" placeholder=\"acepacknship.com\"><\/div>\n<div class=\"field\"><label>Target Titles<\/label><input id=\"snTitles\" value=\"Owner, Founder, President, CEO, Managing Partner, Principal\"><\/div>\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"generateSalesNavigatorCompanion()\">Generate Search Plan<\/button>\n<button class=\"secondary\" onclick=\"copyText('snSearchPlan')\">Copy Plan<\/button>\n<a class=\"salesnav-link\" href=\"https:\/\/www.linkedin.com\/sales\/search\/people\" target=\"_blank\" rel=\"noopener\">Open Sales Navigator<\/a>\n<\/div>\n<\/div>\n\n<div class=\"salesnav-card\">\n<h3>Manual Owner Capture<\/h3>\n<div class=\"field\"><label>Owner \/ Contact Name<\/label><input id=\"snOwnerName\" placeholder=\"John Smith\"><\/div>\n<div class=\"field\"><label>Title<\/label><input id=\"snOwnerTitle\" placeholder=\"Owner \/ President\"><\/div>\n<div class=\"field\"><label>LinkedIn URL<\/label><input id=\"snLinkedIn\" placeholder=\"https:\/\/www.linkedin.com\/in\/... or Sales Navigator profile link\"><\/div>\n<div class=\"two\"><div class=\"field\"><label>Email<\/label><input id=\"snEmail\" placeholder=\"Optional\"><\/div><div class=\"field\"><label>Phone<\/label><input id=\"snPhone\" placeholder=\"Optional\"><\/div><\/div>\n<div class=\"actions\"><button class=\"primary\" onclick=\"saveSalesNavOwner()\">Save Manual Owner<\/button><\/div>\n<\/div>\n<\/div>\n\n<div>\n<h3>Recommended Search Plan<\/h3>\n<div id=\"snSearchPlan\" class=\"salesnav-query\">Select a prospect and generate the Sales Navigator search plan.<\/div>\n\n<h3>Search Guidance<\/h3>\n<div id=\"snGuidance\" class=\"salesnav-tip\">When Apollo returns no match, search Sales Navigator by company name, city, and owner-level titles. If the exact company does not appear, search the business name in regular LinkedIn and Google, then capture the owner manually here.<\/div>\n\n<h3>Copy-Ready Searches<\/h3>\n<div id=\"snCopySearches\" class=\"output\">\u2014<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<div id=\"followupTab\" class=\"card hide\">\n<h2>Automated Deal Pursuit & Follow-Up Engine<\/h2>\n<div class=\"notice\">Tracks activity, classifies deal momentum, creates a follow-up cadence, and recommends the next best action for each prospect.<\/div>\n\n<div class=\"automation28-hero\">\n<h3>Advanced Follow-Up Automation v2.8<\/h3>\n<p>Daily priority queue, overdue alerts, cadence creation, and next-best-action guidance to help brokers avoid missed follow-ups.<\/p>\n<\/div>\n\n<div class=\"automation28-grid\">\n<div class=\"automation28-kpi\"><span>Due Today<\/span><b id=\"faDueToday\">0<\/b><\/div>\n<div class=\"automation28-kpi\"><span>Overdue<\/span><b id=\"faOverdue\">0<\/b><\/div>\n<div class=\"automation28-kpi\"><span>Priority Targets<\/span><b id=\"faPriority\">0<\/b><\/div>\n<div class=\"automation28-kpi\"><span>Completed Touches<\/span><b id=\"faCompleted\">0<\/b><\/div>\n<\/div>\n\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"createDefaultCadenceForSelected()\">Create Default Cadence<\/button>\n<button class=\"secondary\" onclick=\"renderFollowupAutomation()\">Refresh Daily Priorities<\/button>\n<button class=\"light\" onclick=\"exportFollowupAutomationCSV()\">Export Follow-Up Queue<\/button>\n<\/div>\n\n<div class=\"automation28-board\">\n<div class=\"automation28-panel\"><h4>Today's Priorities<\/h4><div id=\"faPriorityQueue\">\u2014<\/div><\/div>\n<div class=\"automation28-panel\"><h4>Selected Prospect Cadence<\/h4><div id=\"faSelectedCadence\">Select a prospect to see its cadence.<\/div><\/div>\n<\/div>\n\n<div class=\"metric-grid\">\n<div class=\"metric\"><span>Hot Deals<\/span><b id=\"fuHot\">0<\/b><\/div>\n<div class=\"metric\"><span>Warm Deals<\/span><b id=\"fuWarm\">0<\/b><\/div>\n<div class=\"metric\"><span>Nurture<\/span><b id=\"fuNurture\">0<\/b><\/div>\n<div class=\"metric\"><span>Dormant<\/span><b id=\"fuDormant\">0<\/b><\/div>\n<\/div>\n\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"generateFollowupEngine()\">Generate Follow-Up Plan<\/button>\n<button class=\"secondary\" onclick=\"saveFollowupEngine()\">Save Follow-Up Plan<\/button>\n<button class=\"light\" onclick=\"exportFollowupPlan()\">Export Follow-Up Plan<\/button>\n<\/div>\n\n<div class=\"followup-grid\" style=\"margin-top:14px\">\n<div>\n<div class=\"followup-card\">\n<h3>Selected Prospect<\/h3>\n<div id=\"fuSelected\" class=\"output\">Select a prospect first.<\/div>\n<\/div>\n\n<div class=\"followup-card\">\n<h3>Log Activity<\/h3>\n<div class=\"activity-grid v242\">\n<div class=\"activity-button v242\" onclick=\"logActivity('Email Sent')\">Email<br>Sent<\/div>\n<div class=\"activity-button v242\" onclick=\"logActivity('Call Made')\">Call<br>Made<\/div>\n<div class=\"activity-button v242\" onclick=\"logActivity('Voicemail Left')\">Voicemail<br>Left<\/div>\n<div class=\"activity-button v242\" onclick=\"logActivity('LinkedIn Touch')\">LinkedIn<br>Touch<\/div>\n<div class=\"activity-button v242 meeting\" onclick=\"logActivity('Meeting Booked')\">Meeting<br>Booked<\/div>\n<div class=\"activity-button v242\" onclick=\"logActivity('Response Received')\">Response<br>Received<\/div>\n<\/div>\n<div class=\"field\"><label>Activity Note<\/label><textarea id=\"fuActivityNote\" placeholder=\"Optional details about the activity...\"><\/textarea><\/div>\n<\/div>\n\n<div class=\"followup-card\">\n<h3>Cadence Settings<\/h3>\n<div class=\"field\"><label>Cadence Type<\/label><select id=\"fuCadenceType\"><option value=\"standard\" selected>Standard: 1 \/ 7 \/ 14 \/ 30 \/ 60 days<\/option><option value=\"aggressive\">Aggressive: 1 \/ 3 \/ 7 \/ 14 \/ 30 days<\/option><option value=\"nurture\">Nurture: 14 \/ 30 \/ 60 \/ 90 \/ 180 days<\/option><\/select><\/div>\n<div class=\"field\"><label>Starting Action<\/label><select id=\"fuStartAction\"><option value=\"Email\" selected>Email<\/option><option value=\"Phone Call\">Phone Call<\/option><option value=\"LinkedIn\">LinkedIn<\/option><option value=\"Direct Mail\">Direct Mail<\/option><\/select><\/div>\n<\/div>\n<\/div>\n\n<div>\n<div id=\"fuMomentum\" class=\"momentum-panel\">\n<div class=\"momentum-score\">\u2014<\/div>\n<p>Select a prospect and generate the follow-up plan.<\/p>\n<\/div>\n\n<h3>Next Best Action<\/h3>\n<div id=\"fuNextBest\" class=\"output\">\u2014<\/div>\n\n<h3>Generate Follow-Up Message<\/h3>\n<div class=\"follow-message-actions\">\n<button class=\"primary\" onclick=\"generateFollowupMessage('email')\">Follow-Up Email<\/button>\n<button class=\"secondary\" onclick=\"generateFollowupMessage('phone')\">Phone Script<\/button>\n<button class=\"secondary\" onclick=\"generateFollowupMessage('linkedin')\">LinkedIn Message<\/button>\n<button class=\"light\" onclick=\"copyText('fuMessageOutput')\">Copy Message<\/button>\n<button class=\"light\" onclick=\"saveFollowupMessage()\">Save Message<\/button>\n<\/div>\n<div id=\"fuMessageOutput\" class=\"follow-message-box\">Generate a follow-up message after selecting a prospect.<\/div>\n\n<h3>Follow-Up Schedule<\/h3>\n<div id=\"fuSchedule\"><\/div>\n\n<h3>Activity Summary<\/h3>\n<div id=\"fuActivitySummary\" class=\"output\">\u2014<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<div id=\"pursuitTab\" class=\"card hide\">\n<h2>Deal Pursuit Planner<\/h2>\n<div class=\"notice\">Creates a 30\/60\/90-day pursuit plan for the selected prospect using opportunity score, succession intelligence, buyer match, roll-up potential, pipeline stage, and next action.<\/div>\n\n<div class=\"metric-grid\">\n<div class=\"metric\"><span>High Priority Plans<\/span><b id=\"ppHigh\">0<\/b><\/div>\n<div class=\"metric\"><span>Valuation Candidates<\/span><b id=\"ppValuation\">0<\/b><\/div>\n<div class=\"metric\"><span>Buyer Research Needed<\/span><b id=\"ppBuyer\">0<\/b><\/div>\n<div class=\"metric\"><span>Outreach Ready<\/span><b id=\"ppOutreach\">0<\/b><\/div>\n<\/div>\n\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"generatePursuitPlan()\">Generate Pursuit Plan<\/button>\n<button class=\"secondary\" onclick=\"savePursuitPlan()\">Save Plan to Prospect<\/button>\n<button class=\"light\" onclick=\"exportPursuitPlan()\">Export Pursuit Plan<\/button>\n<\/div>\n\n<div class=\"pursuit-grid\" style=\"margin-top:14px\">\n<div>\n<div class=\"pursuit-card\">\n<h3>Selected Opportunity<\/h3>\n<div id=\"pursuitSelected\" class=\"output\">Select a prospect first.<\/div>\n<\/div>\n\n<div class=\"pursuit-card\">\n<h3>Planner Settings<\/h3>\n<div class=\"field\"><label>Primary Objective<\/label><select id=\"pursuitGoal\"><option value=\"seller\" selected>Start Seller Conversation<\/option><option value=\"valuation\">Move Toward Valuation<\/option><option value=\"listing\">Move Toward Listing<\/option><option value=\"buyer\">Research Buyers<\/option><option value=\"rollup\">Build Roll-Up Thesis<\/option><\/select><\/div>\n<div class=\"field\"><label>Intensity<\/label><select id=\"pursuitIntensity\"><option value=\"normal\" selected>Normal<\/option><option value=\"aggressive\">Aggressive<\/option><option value=\"nurture\">Long-Term Nurture<\/option><\/select><\/div>\n<\/div>\n<\/div>\n\n<div>\n<h3>Deal Pursuit Summary<\/h3>\n<div id=\"pursuitSummary\" class=\"output\"><\/div>\n\n<h3>30 \/ 60 \/ 90-Day Action Plan<\/h3>\n<div id=\"pursuitPlan\"><\/div>\n\n<h3>Broker Notes<\/h3>\n<div id=\"pursuitNotes\" class=\"output\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n<div id=\"marketTab\" class=\"card hide\">\n<div class=\"market-hero\">\n<h2>Market Domination Dashboard<\/h2>\n<p>Executive view of county coverage, industry penetration, white-space opportunities, market heat, and broker productivity.<\/p>\n<\/div>\n\n<div class=\"metric-grid\">\n<div class=\"metric\"><span>Markets Covered<\/span><b id=\"mdMarkets\">0<\/b><\/div>\n<div class=\"metric\"><span>Hot Markets<\/span><b id=\"mdHotMarkets\">0<\/b><\/div>\n<div class=\"metric\"><span>White-Space Gaps<\/span><b id=\"mdGaps\">0<\/b><\/div>\n<div class=\"metric\"><span>Penetration Score<\/span><b id=\"mdPenetration\">0<\/b><\/div>\n<\/div>\n\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"renderMarketDomination()\">Refresh Market Dashboard<\/button>\n<button class=\"secondary\" onclick=\"exportMarketDomination()\">Export Market Report<\/button>\n<\/div>\n\n<div class=\"market-grid\" style=\"margin-top:14px\">\n<div>\n<div class=\"market-card\"><h3>County Coverage<\/h3><div id=\"countyCoverage\"><\/div><\/div>\n<div class=\"market-card\"><h3>Industry Coverage<\/h3><div id=\"industryCoverage\"><\/div><\/div>\n<div class=\"market-card\"><h3>Broker Productivity<\/h3><div id=\"brokerProductivity\"><\/div><\/div>\n<\/div>\n<div>\n<div class=\"market-card\"><h3>Opportunity Heat Ranking<\/h3><div id=\"marketHeat\"><\/div><\/div>\n<div class=\"market-card\"><h3>White-Space Opportunities<\/h3><div id=\"whiteSpace\"><\/div><\/div>\n<div class=\"market-card\"><h3>Executive Summary<\/h3><div id=\"marketExecutiveSummary\" class=\"output\">Refresh the Market Dashboard to generate summary.<\/div><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<div id=\"masterTab\" class=\"card hide\">\n<div class=\"master-hero\">\n<h2>Master Dashboard<\/h2>\n<p>A consolidated command center for sourcing, scoring, prioritizing, pursuing, and converting seller opportunities.<\/p>\n<\/div>\n\n<div class=\"master-grid\">\n<div class=\"master-tile\"><span>Prospects Sourced<\/span><b id=\"msTotal\">0<\/b><\/div>\n<div class=\"master-tile\"><span>A+ Opportunities<\/span><b id=\"msAplus\">0<\/b><\/div>\n<div class=\"master-tile\"><span>Retirement \/ Succession<\/span><b id=\"msSuccession\">0<\/b><\/div>\n<div class=\"master-tile\"><span>Roll-Up Clusters<\/span><b id=\"msRollup\">0<\/b><\/div>\n<\/div>\n\n<h3>One-Click Acquisition Workflow<\/h3>\n<div class=\"master-workflow\">\n<div class=\"workflow-step\"><b>1. Source<\/b><small>Find businesses<\/small><\/div>\n<div class=\"workflow-step\"><b>2. Scan<\/b><small>Rank sellers<\/small><\/div>\n<div class=\"workflow-step\"><b>3. Match<\/b><small>Buyer fit<\/small><\/div>\n<div class=\"workflow-step\"><b>4. Engage<\/b><small>Outreach<\/small><\/div>\n<div class=\"workflow-step\"><b>5. Convert<\/b><small>Pipeline<\/small><\/div>\n<\/div>\n\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"runMasterAnalysis()\">Analyze Selected Prospect<\/button>\n<button class=\"secondary\" onclick=\"runMasterDemo()\">Run Demo Mode<\/button>\n<button class=\"light\" onclick=\"exportMasterReport()\">Export Master Report<\/button>\n<\/div>\n\n<h3>Hot Deal Origination Queue<\/h3>\n<div id=\"masterQueue\"><\/div>\n\n<h3>Selected Prospect Deal Profile<\/h3>\n<div id=\"masterProfile\" class=\"master-detail\">Select a prospect, then click Analyze Selected Prospect.<\/div>\n<\/div>\n\n<div id=\"dashboardTab\" class=\"card\">\n<h2>Command Center<\/h2>\n<div class=\"notice\">This dashboard ranks prospects by priority using opportunity score, exit readiness score, pipeline status, follow-up date, and activity history.<\/div>\n\n<div class=\"metric-grid\">\n<div class=\"metric\"><span>Total Prospects<\/span><b id=\"mTotal\">0<\/b><\/div>\n<div class=\"metric\"><span>Hot Prospects<\/span><b id=\"mHot\">0<\/b><\/div>\n<div class=\"metric\"><span>Follow-Ups Due<\/span><b id=\"mDue\">0<\/b><\/div>\n<div class=\"metric\"><span>Assessments<\/span><b id=\"mAssess\">0<\/b><\/div>\n<div class=\"metric\"><span>Meetings Scheduled<\/span><b id=\"mMeetings\">0<\/b><\/div>\n<div class=\"metric\"><span>Listings Pending<\/span><b id=\"mListings\">0<\/b><\/div>\n<div class=\"metric\"><span>Listings Won<\/span><b id=\"mWon\">0<\/b><\/div>\n<div class=\"metric\"><span>High Readiness Targets<\/span><b id=\"mReadiness\">0<\/b><\/div>\n<div class=\"metric\"><span>Overdue Actions<\/span><b id=\"mOverdue28\">0<\/b><\/div>\n<div class=\"metric\"><span>Priority Targets<\/span><b id=\"mPriority28\">0<\/b><\/div>\n<\/div>\n\n<h3>Priority Work Queue<\/h3>\n<div id=\"priorityQueue\" class=\"queue\"><\/div>\n\n<h3>Hot Prospect Alerts<\/h3>\n<div id=\"hotAlerts\" class=\"alert-row\"><\/div>\n\n<h3>Pipeline Board<\/h3>\n<div id=\"pipelineBoard\" class=\"kanban\"><\/div>\n\n<h3>Upcoming Actions<\/h3>\n<div id=\"upcomingActions\" class=\"queue\"><\/div>\n\n<h3>Recent Activity Timeline<\/h3>\n<div id=\"recentActivity\" class=\"history\"><\/div>\n\n<h3>Selected Prospect Intelligence<\/h3>\n<div id=\"selectedSummary\" class=\"output\">Select a prospect to begin.<\/div>\n<\/div>\n\n<div id=\"outreachTab\" class=\"card hide\">\n<h2>AI Outreach Message Generator<\/h2>\n<div class=\"notice\">Generates English, Portuguese, and Spanish outreach content. Messages are draft-style and can be copied\/sent manually.<\/div>\n<div class=\"langs\"><button class=\"lang active\" onclick=\"setLang('en',event)\">English<\/button><button class=\"lang\" onclick=\"setLang('pt',event)\">Portugu\u00eas<\/button><button class=\"lang\" onclick=\"setLang('es',event)\">Espa\u00f1ol<\/button><\/div>\n<div class=\"actions\"><button class=\"primary\" onclick=\"generateOutreach()\">Generate Outreach Package<\/button><button class=\"secondary\" onclick=\"saveOutreach()\">Save to History<\/button><\/div>\n<h3>Email Variation 1 \u2014 Soft Introduction<\/h3><div class=\"copybar\"><button class=\"copybtn\" onclick=\"copyText('email1')\">Copy<\/button><\/div><div id=\"email1\" class=\"output\"><\/div>\n<h3>Email Variation 2 \u2014 Direct Value Proposition<\/h3><div class=\"copybar\"><button class=\"copybtn\" onclick=\"copyText('email2')\">Copy<\/button><\/div><div id=\"email2\" class=\"output\"><\/div>\n<h3>Email Variation 3 \u2014 Referral-Style Warm Approach<\/h3><div class=\"copybar\"><button class=\"copybtn\" onclick=\"copyText('email3')\">Copy<\/button><\/div><div id=\"email3\" class=\"output\"><\/div>\n<h3>LinkedIn Connection Note<\/h3><div class=\"copybar\"><button class=\"copybtn\" onclick=\"copyText('linkedin1')\">Copy<\/button><\/div><div id=\"linkedin1\" class=\"output\"><\/div>\n<h3>LinkedIn Follow-Up DM<\/h3><div class=\"copybar\"><button class=\"copybtn\" onclick=\"copyText('linkedin2')\">Copy<\/button><\/div><div id=\"linkedin2\" class=\"output\"><\/div>\n<h3>Direct Mail Letter<\/h3><div class=\"copybar\"><button class=\"copybtn\" onclick=\"copyText('letter')\">Copy<\/button><\/div><div id=\"letter\" class=\"output\"><\/div>\n<h3>4-Message Follow-Up Sequence<\/h3><div class=\"copybar\"><button class=\"copybtn\" onclick=\"copyText('sequence')\">Copy<\/button><\/div><div id=\"sequence\" class=\"output\"><\/div>\n<\/div>\n\n<div id=\"pipelineTab\" class=\"card hide\">\n<h2>Pipeline & Follow-Up Manager<\/h2>\n<div class=\"notice\">Manage each prospect through the pre-listing workflow: status, next follow-up, activity history, quick actions, and AI-recommended next steps.<\/div>\n\n<div class=\"pipeline-status-grid\">\n<div class=\"pipeline-status-card\"><span>Current Status<\/span><b id=\"pmCurrentStatus\">\u2014<\/b><\/div>\n<div class=\"pipeline-status-card\"><span>Next Follow-Up<\/span><b id=\"pmNextFollowUp\">\u2014<\/b><\/div>\n<div class=\"pipeline-status-card\"><span>Last Activity<\/span><b id=\"pmLastActivity\">\u2014<\/b><\/div>\n<\/div>\n\n<div class=\"pipeline-manager-grid\">\n<div>\n<div class=\"pipeline-action-panel\">\n<h3>Selected Prospect<\/h3>\n<div id=\"pipelineDetail\" class=\"output\">Select a prospect to view pipeline history.<\/div>\n<\/div>\n\n<div class=\"pipeline-action-panel\">\n<h3>Quick Stage Update<\/h3>\n<div class=\"stage\" id=\"stageBtns\"><\/div>\n<\/div>\n\n<div class=\"pipeline-action-panel\">\n<h3>Schedule Next Follow-Up<\/h3>\n<div class=\"field\"><label>Next Action<\/label><input id=\"pmNextAction\" placeholder=\"Call owner \/ Send follow-up email\"><\/div>\n<div class=\"field\"><label>Follow-Up Date<\/label><input id=\"pmDueDate\" type=\"date\"><\/div>\n<div class=\"actions\"><button class=\"primary\" onclick=\"pmScheduleFollowUp()\">Save Follow-Up<\/button><\/div>\n<div class=\"pipeline-mini-note\">This updates the prospect record and encrypted workspace auto-save.<\/div>\n<\/div>\n\n<div class=\"pipeline-action-panel\">\n<h3>Quick Actions<\/h3>\n<div class=\"pipeline-quick-grid\">\n<button class=\"secondary\" onclick=\"pmQuickAction('Email Sent')\">Mark Email Sent<\/button>\n<button class=\"secondary\" onclick=\"pmQuickAction('LinkedIn Touch')\">LinkedIn Touch<\/button>\n<button class=\"secondary\" onclick=\"pmQuickAction('Call Made')\">Call Completed<\/button>\n<button class=\"secondary\" onclick=\"pmQuickAction('Response Received')\">Response Received<\/button>\n<button class=\"secondary\" onclick=\"pmMoveStage('Interested')\">Move to Interested<\/button>\n<button class=\"secondary\" onclick=\"pmMoveStage('Meeting Scheduled')\">Meeting Scheduled<\/button>\n<button class=\"secondary\" onclick=\"pmMoveStage('Listing Opportunity')\">Listing Opportunity<\/button>\n<button class=\"secondary\" onclick=\"pmMoveStage('Closed Won')\">Closed Won<\/button>\n<\/div>\n<\/div>\n\n<div class=\"pipeline-action-panel\">\n<h3>Internal Notes<\/h3>\n<div class=\"field\"><textarea id=\"noteText\" placeholder=\"Add call notes, next steps, seller feedback, etc.\"><\/textarea><\/div>\n<div class=\"actions\"><button class=\"primary\" onclick=\"saveNote()\">Save Note<\/button><\/div>\n<\/div>\n<\/div>\n\n<div>\n<h3>AI Follow-Up Suggestions<\/h3>\n<div id=\"pmAISuggestions\"><\/div>\n\n<h3>Activity Timeline<\/h3>\n<div id=\"historyList\" class=\"history\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<div id=\"coachTab\" class=\"card hide\">\n<h2>Seller Conversation Coach<\/h2>\n<div class=\"actions\"><button class=\"primary\" onclick=\"generateCoach()\">Generate Call Prep<\/button><button class=\"secondary\" onclick=\"saveCoach()\">Save Coach Output<\/button><\/div>\n<h3>Customized Call Script<\/h3><div class=\"copybar\"><button class=\"copybtn\" onclick=\"copyText('callScript')\">Copy<\/button><\/div><div id=\"callScript\" class=\"output\"><\/div>\n<h3>Likely Objections & Responses<\/h3><div class=\"copybar\"><button class=\"copybtn\" onclick=\"copyText('objections')\">Copy<\/button><\/div><div id=\"objections\" class=\"output\"><\/div>\n<h3>Qualification Questions<\/h3><div class=\"copybar\"><button class=\"copybtn\" onclick=\"copyText('qualQuestions')\">Copy<\/button><\/div><div id=\"qualQuestions\" class=\"output\"><\/div>\n<h3>Post-Call Follow-Up Email<\/h3><div class=\"copybar\"><button class=\"copybtn\" onclick=\"copyText('postEmail')\">Copy<\/button><\/div><div id=\"postEmail\" class=\"output\"><\/div>\n<\/div>\n\n<div id=\"scorecardTab\" class=\"card hide\">\n<h2>Seller Opportunity Scorecard<\/h2>\n<div class=\"three\"><div class=\"field\"><label>Seller Motivation<\/label><select id=\"motivation\"><option value=\"20\">Low<\/option><option value=\"50\" selected>Moderate<\/option><option value=\"85\">High<\/option><\/select><\/div><div class=\"field\"><label>Business Quality<\/label><select id=\"quality\"><option value=\"30\">Weak<\/option><option value=\"60\" selected>Average<\/option><option value=\"90\">Strong<\/option><\/select><\/div><div class=\"field\"><label>Deal Potential<\/label><select id=\"dealpot\"><option value=\"30\">Low<\/option><option value=\"60\" selected>Medium<\/option><option value=\"90\">High<\/option><\/select><\/div><\/div>\n<div class=\"actions\"><button class=\"primary\" onclick=\"calculateOpportunity()\">Calculate Opportunity<\/button><button class=\"secondary\" onclick=\"saveOpportunity()\">Save Scorecard<\/button><\/div>\n<div id=\"oppResults\" class=\"hide\"><div class=\"scorebox\"><div><p>Combined Opportunity Score<\/p><div class=\"score\" id=\"oppScore\">0<\/div><\/div><div><p><strong id=\"oppCat\">\u2014<\/strong><\/p><p id=\"oppApproach\">\u2014<\/p><\/div><\/div><h3>Suggested Messaging Angle<\/h3><div id=\"oppAngle\" class=\"output\"><\/div><\/div>\n<\/div>\n\n<div id=\"assessmentTab\" class=\"card hide\">\n<h2>Exit Readiness Assessment<\/h2>\n<div class=\"notice\">Use 1 for weak\/not ready and 5 for strong\/ready.<\/div>\n<h3>Financial Readiness<\/h3><div id=\"financialQs\"><\/div>\n<h3>Operational Readiness<\/h3><div id=\"operationalQs\"><\/div>\n<h3>Market Readiness<\/h3><div id=\"marketQs\"><\/div>\n<h3>Personal Exit Readiness<\/h3><div id=\"personalQs\"><\/div>\n<div class=\"actions\"><button class=\"primary\" onclick=\"calculateAssessment()\">Generate Exit Readiness Analysis<\/button><button class=\"secondary\" onclick=\"saveAssessment()\">Save Assessment<\/button><\/div>\n<div id=\"assessmentResults\" class=\"hide\" style=\"margin-top:18px\">\n<div class=\"scorebox\"><div><p>Exit Readiness Score<\/p><div class=\"score\" id=\"exitScore\">0<\/div><\/div><div><p><strong id=\"exitCat\">\u2014<\/strong><\/p><p id=\"exitTimeline\">\u2014<\/p><\/div><\/div>\n<div class=\"metric-grid\"><div class=\"metric\"><span>Financial<\/span><b id=\"financialScore\">0<\/b><\/div><div class=\"metric\"><span>Operational<\/span><b id=\"operationalScore\">0<\/b><\/div><div class=\"metric\"><span>Market<\/span><b id=\"marketScore\">0<\/b><\/div><div class=\"metric\"><span>Personal<\/span><b id=\"personalScore\">0<\/b><\/div><\/div>\n<h3>Broker Opportunity Summary<\/h3><div id=\"assessmentSummary\" class=\"output\"><\/div>\n<h3>Recommended Value Enhancement Plan<\/h3><div id=\"assessmentRecs\" class=\"output\"><\/div>\n<\/div>\n<\/div>\n\n\n\n\n\n\n\n\n<div id=\"apiSetupTab\" class=\"card hide\">\n<h2>API Integration Setup<\/h2>\n<div class=\"notice\">This tab prepares the tool for secure Prospect Sourcing API integration. API keys should never be stored inside this HTML file. Use a backend endpoint that stores keys securely and returns clean prospect data.<\/div>\n\n<div class=\"api-card\">\n<h4>Member AI Key Settings<\/h4>\n<p class=\"api-key-note\">This second-version build requires every logged-in WordPress subscriber to save their own AI service API key before using AI-assisted features. The same settings panel also appears near the top of the tool.<\/p>\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"document.getElementById('adsAiApiKey').focus();window.scrollTo({top:0,behavior:'smooth'})\">Add \/ Update My API Key<\/button>\n<button class=\"secondary\" onclick=\"adsTestUserApiKey()\">Test Saved Key<\/button>\n<button class=\"light\" onclick=\"adsForgetUserApiKey()\">Forget Saved Key<\/button>\n<\/div>\n<div id=\"apiKeySetupStatus\" class=\"status-box\">AI key status has not been checked yet.<\/div>\n<\/div>\n\n\n<div class=\"api-grid\">\n<div>\n<div class=\"api-card\">\n<h4>Backend Endpoint<\/h4>\n<div class=\"field\"><label>Prospect Search Endpoint<\/label><input id=\"apiEndpointTest\" value=\"\/wp-json\/ai-deal-sourcing\/v1\/prospect-search\"><\/div>\n<div class=\"two\"><div class=\"field\"><label>Industry<\/label><input id=\"apiTestIndustry\" value=\"HVAC\"><\/div><div class=\"field\"><label>Zip Code<\/label><input id=\"apiTestZip\" value=\"33626\"><\/div><\/div>\n<div class=\"two\"><div class=\"field\"><label>County<\/label><input id=\"apiTestCounty\" value=\"Hillsborough\"><\/div><div class=\"field\"><label>Radius<\/label><select id=\"apiTestRadius\"><option>5<\/option><option>10<\/option><option selected>25<\/option><option>50<\/option><option>100<\/option><\/select><\/div><\/div>\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"testApiEndpoint()\">Test Endpoint<\/button>\n<button class=\"secondary\" onclick=\"copyApiSpec()\">Copy API Spec<\/button>\n<\/div>\n<div id=\"apiTestStatus\" class=\"status-box\">Endpoint not tested yet.<\/div>\n<\/div>\n\n<div class=\"api-card\">\n<h4>Recommended API Build Order<\/h4>\n<ol>\n<li>Google Places API backend proxy<\/li>\n<li>Business website enrichment<\/li>\n<li>Review\/signal enrichment<\/li>\n<li>Domain\/website age checks<\/li>\n<li>Marketplace monitoring integrations<\/li>\n<\/ol>\n<\/div>\n<\/div>\n\n<div>\n<div class=\"api-card\">\n<h4>Expected JSON Response<\/h4>\n<div class=\"endpoint-test\" id=\"apiSpecBox\">[\n  {\n    \"name\": \"ABC HVAC Services\",\n    \"industry\": \"HVAC\",\n    \"address\": \"123 Main St, Tampa, FL 33626\",\n    \"city\": \"Tampa\",\n    \"state\": \"FL\",\n    \"zip\": \"33626\",\n    \"county\": \"Hillsborough\",\n    \"phone\": \"(813) 555-1212\",\n    \"website\": \"https:\/\/example.com\",\n    \"rating\": 4.6,\n    \"reviews\": 187,\n    \"years\": 18,\n    \"employees\": 14,\n    \"signal\": \"Long operating history; possible succession angle\",\n    \"source\": \"Google Places\",\n    \"score\": 82\n  }\n]<\/div>\n<\/div>\n\n<div class=\"api-card\">\n<h4>Security Rules<\/h4>\n<ul>\n<li>Never place Google Places API keys in this HTML file.<\/li>\n<li>Use a server-side endpoint to call Google Places.<\/li>\n<li>Restrict API keys by domain\/IP in Google Cloud.<\/li>\n<li>Rate-limit searches by user\/account.<\/li>\n<li>Log usage for cost control.<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<div id=\"releaseTab\" class=\"card hide\">\n<h2>Deal Origination QA & WordPress Deployment<\/h2>\n<div class=\"notice\">Use this screen before installing the tool in your Tools Portal. It checks browser functionality and gives you a deployment checklist.<\/div>\n\n<div class=\"metric-grid\">\n<div class=\"metric\"><span>Product<\/span><b>Pro<\/b><\/div>\n<div class=\"metric\"><span>Storage<\/span><b id=\"qaStorage\">\u2014<\/b><\/div>\n<div class=\"metric\"><span>Prospects<\/span><b id=\"qaProspects\">0<\/b><\/div>\n<div class=\"metric\"><span>Modules<\/span><b>13<\/b><\/div>\n<\/div>\n\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"runReleaseQA()\">Run QA Check<\/button>\n<button class=\"secondary\" onclick=\"downloadReleaseNotes()\">Download Release Notes<\/button><button class=\"light\" onclick=\"exportLaunchReadinessReport()\">Launch Readiness Report<\/button>\n<button class=\"light\" onclick=\"loadDemoData()\">Load Demo Data<\/button>\n<\/div>\n\n<h3>Functional QA Checklist<\/h3>\n<div id=\"qaChecklist\" class=\"qa-grid\"><\/div>\n\n<h3>WordPress Deployment Checklist<\/h3>\n<div class=\"release-box\"><h4>Recommended installation method<\/h4><p>Create a hidden WordPress test page first. Paste the full HTML into the same type of block or page method used for the other portal tools. Test it before adding it to the public tools menu.<\/p><\/div>\n<div class=\"release-box\"><h4>Test steps<\/h4><ol><li>Open the tool in WordPress.<\/li><li>Load demo data.<\/li><li>Confirm Command Center metrics populate.<\/li><li>Run Prospect Sourcing and add a prospect to pipeline.<\/li><li>Generate Outreach, Coach, Scorecard, Exit Assessment, Workflow, Conversion, and Listing Presentation.<\/li><li>Print or save the seller report as PDF.<\/li><li>Reload the page and confirm saved data persists.<\/li><\/ol><\/div>\n<div class=\"release-box\"><h4>Important storage note<\/h4><p>This portal version supports encrypted member vault storage. Records are encrypted in the user's browser before being saved to WordPress. The vault password is not stored by 360 Biz Brokers and cannot be recovered if forgotten.<\/p><\/div>\n<div class=\"release-box\"><h4>Future API endpoint target<\/h4><div class=\"codebox\">\/wp-json\/ai-deal-sourcing\/v1\/prospect-search?industry=HVAC&zip=33626&county=Hillsborough&radius=25<\/div><\/div>\n<\/div>\n\n<div id=\"presentationTab\" class=\"card hide\">\n<h2>Deal Origination<\/h2>\n<div class=\"notice\">Generate a seller-facing presentation using the selected prospect's sourcing, scoring, intelligence, workflow, and conversion data.<\/div>\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"generatePresentation()\">Generate Presentation<\/button>\n<button class=\"secondary\" onclick=\"copyPresentation()\">Copy Presentation Text<\/button>\n<button class=\"light\" onclick=\"window.print()\">Print \/ Save as PDF<\/button>\n<\/div>\n<div id=\"presentationOutput\" class=\"presentation-doc\" style=\"margin-top:14px\">\n<div class=\"empty-state\">Select a prospect, then click Generate Presentation.<\/div>\n<\/div>\n<\/div>\n\n<div id=\"conversionTab\" class=\"card hide\">\n<h2>Deal Origination<\/h2>\n<div class=\"notice\">Identifies which prospects are closest to becoming signed listings and which are ready for valuation.<\/div>\n\n<div class=\"metric-grid\">\n<div class=\"metric\"><span>Listing Candidates<\/span><b id=\"cCandidates\">0<\/b><\/div>\n<div class=\"metric\"><span>Valuation Ready<\/span><b id=\"cValuation\">0<\/b><\/div>\n<div class=\"metric\"><span>Ready for Engagement<\/span><b id=\"cEngage\">0<\/b><\/div>\n<div class=\"metric\"><span>Avg Conversion %<\/span><b id=\"cAvg\">0%<\/b><\/div>\n<\/div>\n\n<h3>Conversion Queue<\/h3>\n<div id=\"conversionQueue\" class=\"output\"><\/div>\n\n<h3>Conversion Funnel<\/h3>\n<div id=\"conversionFunnel\" class=\"output\"><\/div>\n<\/div>\n\n<div id=\"workflowTab\" class=\"card hide\">\n<h2>Workflow Automation Layer<\/h2>\n<div class=\"automation-banner\">\n<h3>Deal Sourcing Assistant<\/h3>\n<p>This layer reviews each prospect's stage, scores, due dates, and activity history, then recommends the next workflow action.<\/p>\n<\/div>\n\n<div class=\"metric-grid\">\n<div class=\"metric\"><span>Open Tasks<\/span><b id=\"wOpen\">0<\/b><\/div>\n<div class=\"metric\"><span>High Priority<\/span><b id=\"wHigh\">0<\/b><\/div>\n<div class=\"metric\"><span>Due Today<\/span><b id=\"wDue\">0<\/b><\/div>\n<div class=\"metric\"><span>Auto Suggestions<\/span><b id=\"wSuggest\">0<\/b><\/div>\n<\/div>\n\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"generateWorkflowTasks()\">Generate Workflow Tasks<\/button>\n<button class=\"secondary\" onclick=\"saveTopWorkflowTask()\">Save Top Task to Selected Prospect<\/button>\n<button class=\"light\" onclick=\"exportWorkflowCSV()\">Export Workflow CSV<\/button>\n<\/div>\n\n<div class=\"workflow-grid\">\n<div>\n<h3>Recommended Work Queue<\/h3>\n<div id=\"workflowQueue\"><\/div>\n<\/div>\n<div>\n<h3>Automation Rules Used<\/h3>\n<div id=\"workflowRules\">\n<div class=\"workflow-rule\"><h4>High Priority Listing Candidate<\/h4><p>Priority 80+ or strong opportunity + exit readiness \u2192 schedule valuation consultation.<\/p><\/div>\n<div class=\"workflow-rule\"><h4>Follow-Up Due<\/h4><p>Prospects with due dates today or overdue move to the top of the workflow queue.<\/p><\/div>\n<div class=\"workflow-rule\"><h4>Missing Assessment<\/h4><p>Prospects with opportunity scores but no exit readiness assessment get an assessment task.<\/p><\/div>\n<div class=\"workflow-rule\"><h4>Early Stage Prospect<\/h4><p>Identified or researched prospects get outreach, scoring, and conversation-prep tasks.<\/p><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<h3>Selected Prospect Workflow Guidance<\/h3>\n<div id=\"selectedWorkflow\" class=\"output\">Select a prospect or generate tasks to see workflow guidance.<\/div>\n<\/div>\n\n<div id=\"intelligenceTab\" class=\"card hide\">\n<h2>AI Listing Readiness Engine <span class=\"source-pill\">v2.6<\/span><\/h2>\n<div class=\"notice\">Scores which prospects are most likely to become valuable listing opportunities using business age, review strength, industry buyer demand, owner signals, Apollo contact quality, pipeline activity, and follow-up readiness.<\/div>\n\n<div class=\"metric-grid\">\n<div class=\"metric\"><span>Readiness Score<\/span><b id=\"aiPriority\">0<\/b><\/div>\n<div class=\"metric\"><span>Listing Probability<\/span><b id=\"aiListing\">0%<\/b><\/div>\n<div class=\"metric\"><span>Priority Tier<\/span><b id=\"aiUrgency\">Low<\/b><\/div>\n<div class=\"metric\"><span>Recommended Action<\/span><b id=\"aiAction\">\u2014<\/b><\/div>\n<\/div>\n\n<div class=\"actions\">\n<button class=\"primary\" onclick=\"renderIntelligence()\">Analyze Selected Prospect<\/button>\n<button class=\"secondary\" onclick=\"saveListingReadinessToProspect()\">Save Readiness Insight<\/button>\n<button class=\"light\" onclick=\"exportListingReadinessReport()\">Export Readiness Report<\/button>\n<\/div>\n\n<h3>Listing Readiness Recommendation<\/h3>\n<div id=\"aiRecommendation\" class=\"output\">Select a prospect to generate listing readiness intelligence.<\/div>\n\n<h3>Readiness Drivers<\/h3>\n<div id=\"aiDrivers\" class=\"output\">\u2014<\/div>\n\n<h3>Risks \/ Missing Signals<\/h3>\n<div id=\"aiRisks\" class=\"output\">\u2014<\/div>\n\n<h3>Next Best Actions<\/h3>\n<div id=\"aiNextSteps\" class=\"output\">\u2014<\/div>\n\n<h3>Readiness Ranking Queue<\/h3>\n<div id=\"listingReadinessQueue\" class=\"queue\"><\/div>\n<\/div>\n\n<div id=\"analyticsTab\" class=\"card hide\">\n<h2>Analytics & Broker Reporting<\/h2>\n<div class=\"analytics-summary\">\n<h3>Pipeline Health Summary<\/h3>\n<p id=\"analyticsNarrative\">Load or create prospect records to generate broker-level analytics.<\/p>\n<\/div>\n\n<div class=\"metric-grid\">\n<div class=\"metric\"><span>Average Priority<\/span><b id=\"aPriority\">0<\/b><\/div>\n<div class=\"metric\"><span>Average Opportunity<\/span><b id=\"aOpp\">0<\/b><\/div>\n<div class=\"metric\"><span>Average Exit<\/span><b id=\"aExit\">0<\/b><\/div>\n<div class=\"metric\"><span>Overdue Follow-Ups<\/span><b id=\"aOverdue\">0<\/b><\/div>\n<\/div>\n\n<div class=\"analytics-grid\">\n<div class=\"chart-card\">\n<h4>Pipeline by Stage<\/h4>\n<div id=\"stageChart\"><\/div>\n<\/div>\n<div class=\"chart-card\">\n<h4>Prospects by Industry<\/h4>\n<div id=\"industryChart\"><\/div>\n<\/div>\n<div class=\"chart-card\">\n<h4>Activity Mix<\/h4>\n<div id=\"activityChart\"><\/div>\n<\/div>\n<\/div>\n\n<h3>Top Opportunities<\/h3>\n<div id=\"topOpportunityTable\"><\/div>\n\n<h3>Broker Activity Report<\/h3>\n<div id=\"brokerActivityReport\" class=\"output\"><\/div>\n\n<div class=\"actions\">\n<button class=\"secondary\" onclick=\"exportAnalyticsCSV()\">Export Analytics CSV<\/button>\n<button class=\"light\" onclick=\"window.print()\">Print Broker Report<\/button>\n<\/div>\n<\/div>\n\n<div id=\"reportTab\" class=\"card hide\">\n<div class=\"report\" id=\"sellerReport\">\n<div class=\"report-cover\">\n<h2>AI Assisted Deals Sourcing Pro\u2122 Pro\u2122 Report<\/h2>\n<p>Confidential prospect intelligence summary prepared for broker review.<\/p>\n<\/div>\n<div class=\"report-meta-grid\">\n<div><div class=\"section-kicker\">Business<\/div><strong id=\"rBiz\">Not selected<\/strong><\/div>\n<div><div class=\"section-kicker\">Industry<\/div><strong id=\"rIndustry\">\u2014<\/strong><\/div>\n<div><div class=\"section-kicker\">Location<\/div><strong id=\"rLocation\">\u2014<\/strong><\/div>\n<div><div class=\"section-kicker\">Pipeline Stage<\/div><strong id=\"rStage\">\u2014<\/strong><\/div>\n<\/div>\n<h3>Latest Opportunity Score<\/h3><p id=\"rOpp\">\u2014<\/p>\n<h3>Latest Exit Readiness<\/h3><p id=\"rExit\">\u2014<\/p>\n<h3>Recommended Next Steps<\/h3><p id=\"rNext\">Generate scorecards and assessments to populate recommendations.<\/p>\n<h3>Broker Disclaimer<\/h3>\n<p style=\"font-size:12px;color:#666\">This report is a planning aid and does not constitute a formal valuation, appraisal, legal advice, tax advice, or a representation that a transaction will occur. All information should be verified before broker reliance or seller presentation.<\/p>\n<\/div>\n<div class=\"actions\"><button class=\"light\" onclick=\"window.print()\">Print \/ Save as PDF<\/button><\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"footer-brand\">\u00a9 2026 360 Biz Brokers \u00b7 AI Assisted Deals Sourcing Pro\u2122 \u00b7 Powered by 360 Biz Brokers<\/div>\n<\/div>\n\n<script>\nconst stages=['New Prospect','Identified','Researched','Owner Identified','Outreach Generated','Contacted','Follow-Up Scheduled','Interested','Conversation Started','Meeting Scheduled','Meeting Booked','Listing Opportunity','Listing Agreement','Active Listing','Under Contract','Closed Won','Closed Lost','Closed'];\nlet prospects=[];\nlet selectedId=null,lastOutreach=null,lastCoach=null,lastOpp=null,lastAssessment=null,currentLang='en';\n\nconst questions={\nfinancial:[['financials','Financial statements are current and available','P&L, balance sheet, and cash flow reports are accessible.'],['monthly','Monthly reporting is consistent','The owner can review performance monthly, not only at tax time.'],['books','Bookkeeping is clean and reliable','Income, expenses, payroll, and add-backs are organized.'],['tax','Tax returns are organized','At least three years of returns can be provided quickly.'],['addbacks','Owner add-backs are explainable','Personal\/discretionary expenses can be clearly documented.']],\noperational:[['sops','SOPs and processes are documented','A buyer can understand how the business runs.'],['management','Management team is in place','Business is not completely dependent on the owner.'],['employees','Key employee risk is controlled','Critical employees are stable and likely to remain.'],['systems','Systems and records are organized','CRM, billing, inventory, vendors, and customer records are usable.'],['ownerdep','Owner dependency is low','The owner does not need to be involved in every daily decision.']],\nmarket:[['recurring','Revenue is predictable or recurring','Repeat customers, contracts, subscriptions, or maintenance plans exist.'],['concentration','Customer concentration is low','No single customer creates excessive risk.'],['advantage','Competitive advantage is clear','Reputation, location, niche, relationships, licenses, or systems are defensible.'],['growth','Growth opportunities are identifiable','A buyer can see practical ways to grow revenue or margin.'],['reviews','Reputation supports buyer confidence','Reviews, referrals, and local reputation are positive.']],\npersonal:[['timeline','Owner has a realistic exit timeline','Seller has thought through when they want to transition.'],['price','Price expectations are realistic','Owner has a market-grounded view of business value.'],['transition','Owner is willing to support transition','Seller can stay for training or a defined handoff period.'],['motivation2','Motivation to sell is clear','Retirement, burnout, succession, diversification, or other motivation exists.'],['family','Family or partner issues are manageable','Decision makers are aligned enough to explore a sale.']]\n};\n\nfunction $(id){return document.getElementById(id)}\nfunction val(id){return $(id).value.trim()}\nfunction p(){return selectedId?prospects.find(x=>x.id===selectedId):null}\nfunction persist(){\n  if(window.ADS_CLOUD_STORAGE&&window.ADS_CLOUD_STORAGE.enabled&&window.adsVaultUnlocked){\n    clearTimeout(window.adsCloudSaveTimer);\n    window.adsCloudSaveTimer=setTimeout(()=>cloudSaveNow(true),700);\n  }\n}\nfunction ensureArrays(x){['history','outreach','coach','opportunities','assessments'].forEach(k=>x[k]=x[k]||[]);return x}\n\nfunction saveProspect(){\n let data={id:selectedId||Date.now().toString(),bizName:val('bizName')||'Unnamed Prospect',industry:val('industry'),location:val('location'),owner:val('owner'),revenue:val('revenue'),years:val('years'),employees:val('employees'),context:val('context'),stage:val('stage'),nextAction:val('nextAction'),dueDate:val('dueDate')};\n let ex=prospects.find(x=>x.id===data.id);\n if(ex){Object.assign(ex,data);ensureArrays(ex)}else{ensureArrays(data);data.history.unshift(hist('Prospect Created','Initial prospect record created.'));prospects.unshift(data)}\n selectedId=data.id;persist();renderAll();selectProspect(data.id);\n}\nfunction hist(type,text){return{date:new Date().toLocaleString(),type,text}}\nfunction renderProspects(){\n const box=$('prospectList'); box.innerHTML=prospects.length?'':'<div class=\"notice\">No saved prospects yet.<\/div>';\n prospects.forEach(x=>{ensureArrays(x);let latest=x.assessments[0];box.innerHTML+=`<div class=\"prospect ${x.id===selectedId?'active':''}\" onclick=\"selectProspect('${x.id}')\"><b>${x.bizName}<\/b><small>${x.industry||'Industry not set'} \u00b7 ${x.location||'Location not set'}<\/small><br><span class=\"pill blue\">${x.stage||'Identified'}<\/span>${latest?`<span class=\"pill green\">Exit ${latest.score}<\/span>`:''}<\/div>`});\n}\nfunction selectProspect(id){selectedId=id;let x=p();if(!x)return;ensureArrays(x);['bizName','industry','location','owner','revenue','years','employees','context','stage','nextAction','dueDate'].forEach(k=>$(k).value=x[k]||'');lastOpp=x.opportunities[0]||lastOpp;lastAssessment=x.assessments[0]||lastAssessment;renderAll();}\nfunction clearForm(){selectedId=null;['bizName','industry','location','owner','years','employees','context','nextAction','dueDate'].forEach(k=>$(k).value='');renderAll()}\n\n\nfunction escapeCSV(v){\n  v=(v===undefined||v===null)?'':String(v);\n  return '\"' + v.replace(\/\"\/g,'\"\"') + '\"';\n}\nfunction copyText(id){\n  const el=$(id);\n  if(!el)return;\n  const text=el.innerText||el.textContent||'';\n  navigator.clipboard?.writeText(text).then(()=>alert('Copied.')).catch(()=>{\n    const t=document.createElement('textarea');t.value=text;document.body.appendChild(t);t.select();document.execCommand('copy');document.body.removeChild(t);alert('Copied.');\n  });\n}\nfunction exportCSV(){\n  const headers=['Business Name','Industry','Location','Owner','Revenue','Years','Employees','Stage','Next Action','Due Date','Priority Score','Latest Opportunity Score','Latest Exit Readiness Score'];\n  const rows=prospects.map(x=>{\n    ensureArrays(x);\n    return [\n      x.bizName,x.industry,x.location,x.owner,x.revenue,x.years,x.employees,x.stage,x.nextAction,x.dueDate,\n      priorityScore(x),x.opportunities?.[0]?.score||'',x.assessments?.[0]?.score||''\n    ].map(escapeCSV).join(',');\n  });\n  const csv=[headers.map(escapeCSV).join(','),...rows].join('\\n');\n  const blob=new Blob([csv],{type:'text\/csv;charset=utf-8'});\n  const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='ai-deal-sourcing-prospects.csv';a.click();\n}\nfunction loadDemoData(){\n  if(prospects.length && !confirm('Load demo data? This will add sample prospects to your existing records.'))return;\n  const now=new Date();\n  const today=now.toISOString().slice(0,10);\n  const tomorrow=new Date(now.getTime()+86400000).toISOString().slice(0,10);\n  const samples=[\n    {bizName:'Tampa Bay HVAC Services',industry:'HVAC',location:'Tampa, FL',owner:'Robert Miller',revenue:'$3M\u2013$10M',years:'22',employees:'18',context:'Owner nearing retirement; strong recurring maintenance contracts; possible succession gap.',stage:'Conversation Started',nextAction:'Schedule confidential valuation call',dueDate:today,opportunities:[{date:new Date().toLocaleString(),score:88,category:'Very High',approach:'Immediate Outreach',angle:'Lead with retirement planning, valuation, and buyer demand.'}],assessments:[{date:new Date().toLocaleString(),score:82,category:'Premium Exit Candidate',timeline:'Immediate to 6 months',summary:'Strong exit candidate with recurring revenue and retirement motivation.',recs:'Prepare valuation package and discuss confidential listing timeline.'}]},\n    {bizName:'Gulf Coast Auto Repair',industry:'Auto Repair',location:'St. Petersburg, FL',owner:'Maria Alvarez',revenue:'$1M\u2013$3M',years:'16',employees:'9',context:'Good reputation, owner fatigue, needs better financial cleanup before market.',stage:'Researched',nextAction:'Send exit readiness assessment',dueDate:tomorrow,opportunities:[{date:new Date().toLocaleString(),score:73,category:'High',approach:'Priority Follow-Up',angle:'Lead with preparation and value improvement.'}],assessments:[{date:new Date().toLocaleString(),score:61,category:'Developing',timeline:'1\u20132 years',summary:'Promising but needs preparation.',recs:'Improve reporting and reduce owner dependency.'}]},\n    {bizName:'Orlando Specialty Restaurant',industry:'Restaurant',location:'Orlando, FL',owner:'James Chen',revenue:'$500K\u2013$1M',years:'11',employees:'14',context:'Recent review decline and manager turnover. Owner may be burned out.',stage:'Outreach Sent',nextAction:'Follow up on LinkedIn manually',dueDate:today,opportunities:[{date:new Date().toLocaleString(),score:67,category:'High',approach:'Priority Follow-Up',angle:'Lead with burnout, transition planning, and confidential market perspective.'}],assessments:[]}\n  ].map(s=>ensureArrays({...s,id:'demo_'+Date.now()+Math.random().toString(16).slice(2),history:[hist('Demo Prospect','Sample record loaded.')],outreach:[],coach:[]}));\n  prospects=[...samples,...prospects];\n  persist();renderAll();alert('Demo data loaded.');\n}\nfunction resetDemoData(){\n  if(!confirm('This will permanently clear all locally saved prospects in this browser. Continue?'))return;\n  prospects=[];selectedId=null;persist();clearForm();renderAll();\n}\n\nfunction todayDateOnly(){\n  const d=new Date(); d.setHours(0,0,0,0); return d;\n}\nfunction isDue(d){\n  if(!d)return false;\n  const due=new Date(d+\"T00:00:00\"); due.setHours(0,0,0,0);\n  return due<=todayDateOnly();\n}\nfunction daysUntil(d){\n  if(!d)return null;\n  const due=new Date(d+\"T00:00:00\"); due.setHours(0,0,0,0);\n  return Math.round((due-todayDateOnly())\/86400000);\n}\nfunction priorityScore(x){\n  ensureArrays(x);\n  let opp=x.opportunities?.[0]?.score||0;\n  let exit=x.assessments?.[0]?.score||0;\n  let stageBoost={'New Prospect':4,'Identified':5,'Researched':10,'Owner Identified':14,'Outreach Generated':16,'Outreach Sent':18,'Contacted':20,'Follow-Up Scheduled':23,'Interested':30,'Conversation Started':32,'Meeting Scheduled':38,'Meeting Booked':40,'Listing Opportunity':48,'Listing Agreement':55,'Active Listing':58,'Under Contract':60,'Closed Won':65,'Closed Lost':10,'Closed':55}[x.stage||'New Prospect']||5;\n  let dueBoost=isDue(x.dueDate)?20:0;\n  let activityBoost=Math.min((x.history?.length||0)*2,12);\n  return Math.min(100,Math.round((opp*.36)+(exit*.34)+stageBoost+dueBoost+activityBoost));\n}\nfunction sortedByPriority(){\n  return [...prospects].map(x=>({p:x,score:priorityScore(x)})).sort((a,b)=>b.score-a.score);\n}\nfunction renderCommandCenter(){\n  renderPriorityQueue();\n  renderHotAlerts();\n  renderPipelineBoard();\n  renderUpcomingActions();\n  renderRecentActivity();\n}\nfunction goModule(tab,id){\n  if(id)selectProspect(id);\n  const fake={target:[...document.querySelectorAll('.tab')].find(b=>b.textContent.toLowerCase().includes(tab==='dashboard'?'command':tab))||document.querySelector('.tab')};\n  showTab(tab,fake);\n}\nfunction renderPriorityQueue(){\n  const box=$('priorityQueue'); if(!box)return;\n  const rows=sortedByPriority().slice(0,8);\n  if(!rows.length){box.innerHTML='<div class=\"notice\">No prospects yet. Add a prospect to build your daily work queue.<\/div>';return}\n  box.innerHTML=rows.map(r=>{\n    const x=r.p, opp=x.opportunities?.[0]?.score, ex=x.assessments?.[0]?.score;\n    return `<div class=\"queue-item\"><div class=\"priority-score\">${r.score}<\/div><div><b>${x.bizName}<\/b><br><small>${x.stage||'Identified'} \u00b7 ${x.industry||'Industry not set'} \u00b7 ${x.location||'Location not set'}<\/small><br><span class=\"pill blue\">Opp ${opp||'\u2014'}<\/span><span class=\"pill green\">Exit ${ex||'\u2014'}<\/span>${isDue(x.dueDate)?'<span class=\"pill red\">Follow-Up Due<\/span>':''}<\/div><div class=\"quick-actions\"><button class=\"light\" onclick=\"goModule('outreach','${x.id}')\">Outreach<\/button><button class=\"light\" onclick=\"goModule('coach','${x.id}')\">Coach<\/button><button class=\"light\" onclick=\"goModule('assessment','${x.id}')\">Assess<\/button><\/div><\/div>`\n  }).join('');\n}\nfunction renderHotAlerts(){\n  const box=$('hotAlerts'); if(!box)return;\n  const hot=sortedByPriority().filter(r=>r.score>=70).slice(0,5);\n  if(!hot.length){box.innerHTML='<div class=\"notice\">No hot alerts yet. Scores of 70+ will appear here.<\/div>';return}\n  box.innerHTML=hot.map(r=>{\n    const x=r.p;\n    let reason=[];\n    if((x.opportunities?.[0]?.score||0)>=70)reason.push('high opportunity score');\n    if((x.assessments?.[0]?.score||0)>=70)reason.push('strong exit readiness');\n    if(isDue(x.dueDate))reason.push('follow-up due');\n    return `<div class=\"alert\"><b>${x.bizName}<\/b> \u00b7 Priority ${r.score}<br><small>Reason: ${reason.join(', ')||'strong overall activity'}<\/small><br>Suggested action: ${isDue(x.dueDate)?'Complete the scheduled follow-up today.':'Open the prospect and move the next conversation forward.'}<\/div>`\n  }).join('');\n}\nfunction renderPipelineBoard(){\n  const box=$('pipelineBoard'); if(!box)return;\n  const showStages=['Identified','Researched','Outreach Sent','Conversation Started','Meeting Booked','Listing Agreement','Under Contract','Closed'];\n  box.innerHTML=showStages.map(s=>{\n    const items=prospects.filter(x=>(x.stage||'Identified')===s).slice(0,6);\n    return `<div class=\"kanban-col\"><h4>${s} (${prospects.filter(x=>(x.stage||'Identified')===s).length})<\/h4>${items.map(x=>`<div class=\"kcard\" onclick=\"selectProspect('${x.id}')\"><b>${x.bizName}<\/b><small>${x.industry||'\u2014'} \u00b7 Priority ${priorityScore(x)}<\/small><\/div>`).join('')||'<small>No prospects<\/small>'}<\/div>`\n  }).join('');\n}\nfunction renderUpcomingActions(){\n  const box=$('upcomingActions'); if(!box)return;\n  const rows=prospects.filter(x=>x.nextAction||x.dueDate).sort((a,b)=>(a.dueDate||'9999').localeCompare(b.dueDate||'9999')).slice(0,8);\n  if(!rows.length){box.innerHTML='<div class=\"notice\">No upcoming actions. Add a next action and due date on a prospect record.<\/div>';return}\n  box.innerHTML=rows.map(x=>{\n    const d=daysUntil(x.dueDate);\n    let label=!x.dueDate?'No date':d<0?'Overdue':d===0?'Due Today':d===1?'Due Tomorrow':`Due in ${d} days`;\n    return `<div class=\"queue-item\"><div class=\"priority-score\">${priorityScore(x)}<\/div><div><b>${x.nextAction||'Follow up'}<\/b><br><small>${x.bizName} \u00b7 ${label}<\/small><\/div><div class=\"quick-actions\"><button class=\"light\" onclick=\"goModule('pipeline','${x.id}')\">Open<\/button><\/div><\/div>`\n  }).join('');\n}\nfunction renderRecentActivity(){\n  const box=$('recentActivity'); if(!box)return;\n  let rows=[];\n  prospects.forEach(x=>ensureArrays(x).history.forEach(h=>rows.push({...h,bizName:x.bizName,id:x.id})));\n  rows=rows.sort((a,b)=>new Date(b.date)-new Date(a.date)).slice(0,10);\n  if(!rows.length){box.innerHTML='<div class=\"notice\">No activity yet.<\/div>';return}\n  box.innerHTML=rows.map(h=>`<div class=\"hist\" onclick=\"selectProspect('${h.id}')\"><b>${h.bizName} \u00b7 ${h.type}<\/b><br><small>${h.date}<\/small><p>${h.text}<\/p><\/div>`).join('');\n}\n\nfunction renderMetrics(){\n  let hot=prospects.filter(x=>priorityScore(x)>=70).length;\n  let due=prospects.filter(x=>isDue(x.dueDate)).length;\n  let highReadiness=prospects.filter(x=>listingReadinessScore(x).score>=80).length;\n  $('mTotal').textContent=prospects.length;\n  $('mHot').textContent=hot;\n  if($('mDue'))$('mDue').textContent=due;\n  $('mAssess').textContent=prospects.reduce((a,x)=>a+(x.assessments?.length||0),0);\n  if($('mReadiness'))$('mReadiness').textContent=highReadiness;\n  if($('mOverdue28')){let od=0;prospects.forEach(x=>{ensureCadence(x);(x.followupCadence||[]).forEach(s=>{if(s.status!=='Done'&&faCadenceStatus(s)==='overdue')od++;});});$('mOverdue28').textContent=od;}\n  if($('mPriority28'))$('mPriority28').textContent=highReadiness;\n}\nfunction renderSelected(){let x=p();if(!x){$('selectedSummary').textContent='Select a prospect to begin.';return}$('selectedSummary').textContent=`${x.bizName}\\nIndustry: ${x.industry||'\u2014'}\\nLocation: ${x.location||'\u2014'}\\nStage: ${x.stage||'Identified'}\\nNext Action: ${x.nextAction||'\u2014'} ${x.dueDate?`(${x.dueDate})`:''}\\nLatest Opportunity: ${x.opportunities?.[0]?x.opportunities[0].score+'\/100 \u2014 '+x.opportunities[0].category:'\u2014'}\\nLatest Exit Readiness: ${x.assessments?.[0]?x.assessments[0].score+'\/100 \u2014 '+x.assessments[0].category:'\u2014'}`;}\nfunction renderPipeline(){let x=p();$('pipelineDetail').textContent=x?`Business: ${x.bizName}\\nStage: ${x.stage||'Identified'}\\nNext Action: ${x.nextAction||'\u2014'}\\nDue Date: ${x.dueDate||'\u2014'}`:'Select a prospect to view pipeline history.';$('stageBtns').innerHTML=stages.map(s=>`<button class=\"${x&&x.stage===s?'primary':'light'}\" onclick=\"setStage('${s}')\">${s}<\/button>`).join('');$('historyList').innerHTML=x?(x.history||[]).map(h=>`<div class=\"hist\"><b>${h.type}<\/b><br><small>${h.date}<\/small><p>${h.text}<\/p><\/div>`).join(''):'';\n}\nfunction setStage(s){let x=p();if(!x)return;ensureArrays(x);x.stage=s;$('stage').value=s;x.history.unshift(hist('Stage Updated','Pipeline stage changed to '+s+'.'));persist();renderAll();}\nfunction saveNote(){let x=p();if(!x){saveProspect();x=p()}ensureArrays(x);let t=val('noteText');if(!t)return;x.history.unshift(hist('Note',t));$('noteText').value='';persist();renderAll();}\n\nfunction masterDealScore(x){\n  if(!x)return 0;\n  let scan = typeof scanProspect==='function' ? scanProspect(x) : {score:priorityScore(x),grade:'C',probability:'Medium',type:'General Prospect'};\n  let succ = typeof successionAnalyze==='function' ? successionAnalyze(x) : {readiness:50,persona:'General Prospect',timeline:'Unknown'};\n  let buyer = typeof buyerMatchAnalyze==='function' ? buyerMatchAnalyze(x) : {top:{score:50,type:'Unknown Buyer'}};\n  let baseScore = Math.round((scan.score*.45)+(succ.readiness*.30)+(buyer.top.score*.25));\n  if((x.stage||'')==='Conversation Started')baseScore+=3;\n  if((x.stage||'')==='Meeting Booked')baseScore+=6;\n  if((x.stage||'')==='Listing Agreement')baseScore+=10;\n  return Math.min(100,baseScore);\n}\nfunction masterGrade(score){\n  if(score>=90)return 'A+';\n  if(score>=80)return 'A';\n  if(score>=70)return 'B';\n  if(score>=55)return 'C';\n  return 'D';\n}\nfunction renderMasterDashboard(){\n  if(!$('masterTab'))return;\n  const rows=prospects.map(x=>({p:x,score:masterDealScore(x)})).sort((a,b)=>b.score-a.score);\n  $('msTotal').textContent=prospects.length;\n  $('msAplus').textContent=rows.filter(r=>masterGrade(r.score)==='A+').length;\n  $('msSuccession').textContent=prospects.filter(x=>{\n    const s=typeof successionAnalyze==='function'?successionAnalyze(x):null;\n    return s && (s.persona.includes('Retirement')||s.persona.includes('Succession')||s.persona.includes('Legacy'));\n  }).length;\n  let clusters=0;\n  try{\n    if(typeof rollupIntel!=='undefined' && rollupIntel && rollupIntel.clusters) clusters=rollupIntel.clusters.length;\n  }catch(e){}\n  $('msRollup').textContent=clusters;\n\n  const q=$('masterQueue');\n  if(!rows.length){q.innerHTML='<div class=\"empty-state\">No prospects yet. Use Prospect Sourcing to add prospects.<\/div>';return;}\n  q.innerHTML=rows.slice(0,10).map(r=>{\n    const x=r.p;\n    const scan=typeof scanProspect==='function'?scanProspect(x):{probability:'\u2014',type:'\u2014'};\n    const buyer=typeof buyerMatchAnalyze==='function'?buyerMatchAnalyze(x):{top:{type:'\u2014',score:'\u2014'}};\n    const cls=r.score>=85?'hot':r.score>=70?'warn':'';\n    return `<div class=\"master-action-card ${cls}\">\n      <b>${x.bizName}<\/b> <span class=\"pill ${r.score>=85?'green':'blue'}\">${masterGrade(r.score)} \u00b7 ${r.score}<\/span>\n      <p><strong>Seller:<\/strong> ${scan.probability} \u00b7 ${scan.type}<br><strong>Buyer:<\/strong> ${buyer.top.type} (${buyer.top.score}\/100)<br><strong>Next:<\/strong> ${x.nextAction||'Analyze and generate outreach'}<\/p>\n      <div class=\"master-quick\">\n        <button class=\"light\" onclick=\"selectProspect('${x.id}');runMasterAnalysis()\">Analyze<\/button>\n        <button class=\"light\" onclick=\"goModule('sequence','${x.id}')\">Outreach<\/button>\n        <button class=\"light\" onclick=\"goModule('buyers','${x.id}')\">Buyer Match<\/button>\n        <button class=\"light\" onclick=\"goModule('pipeline','${x.id}')\">Pipeline<\/button>\n      <\/div>\n    <\/div>`;\n  }).join('');\n}\nfunction runMasterAnalysis(){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return}\n  let scan=typeof scanProspect==='function'?scanProspect(x):{score:priorityScore(x),grade:'C',probability:'Medium',type:'General Prospect',approach:'Review prospect',timing:'Follow up'};\n  let succ=typeof successionAnalyze==='function'?successionAnalyze(x):{readiness:50,persona:'General Prospect',timeline:'Unknown',style:'Relationship First'};\n  let buyer=typeof buyerMatchAnalyze==='function'?buyerMatchAnalyze(x):{top:{score:50,type:'Unknown Buyer'},memo:'Buyer match not available.'};\n  let score=masterDealScore(x);\n  $('masterProfile').innerHTML=`<div class=\"master-score\">${score}<\/div>\nDeal Origination Score: ${masterGrade(score)}\n\nBusiness:\n${x.bizName}\n\nSeller Opportunity:\n${scan.grade} \u00b7 ${scan.score}\/100 \u00b7 ${scan.probability}\nType: ${scan.type}\nRecommended Approach: ${scan.approach}\nTiming: ${scan.timing}\n\nSuccession Intelligence:\nPersona: ${succ.persona}\nReadiness: ${succ.readiness}%\nTimeline: ${succ.timeline}\nStyle: ${succ.style}\n\nBuyer Intelligence:\nBest Buyer Type: ${buyer.top.type}\nBuyer Match Score: ${buyer.top.score}\/100\n\nRecommended Next Action:\n${score>=90?'Immediate owner outreach and valuation-readiness conversation.':score>=80?'Generate outreach and schedule confidential discovery call.':score>=70?'Complete additional research and start educational outreach.':'Keep in watchlist and continue sourcing stronger candidates.'}\n\nQuick Workflow:\n1. Save scanner\/succession insight\n2. Generate AI Outreach Sequence\n3. Research likely buyer type\n4. Update pipeline stage\n5. Schedule next follow-up`;\n  ensureArrays(x);\n  x.history.unshift(hist('Master Deal Analysis',`Deal Origination Score ${score}\/100 (${masterGrade(score)}). Seller: ${scan.probability}. Buyer: ${buyer.top.type}.`));\n  x.nextAction=score>=85?'Send personalized owner outreach':'Complete follow-up research';\n  $('nextAction').value=x.nextAction;\n  persist();renderAll();\n}\nfunction runMasterDemo(){\n  if(typeof loadDemoData==='function')loadDemoData();\n  renderMasterDashboard();\n  alert('Demo data loaded. Open Prospect Sourcing for live searches or use the Master Dashboard queue.');\n}\nfunction exportMasterReport(){\n  const rows=prospects.map(x=>{\n    const scan=typeof scanProspect==='function'?scanProspect(x):{probability:'',type:'',grade:''};\n    const succ=typeof successionAnalyze==='function'?successionAnalyze(x):{persona:'',readiness:'',timeline:''};\n    const buyer=typeof buyerMatchAnalyze==='function'?buyerMatchAnalyze(x):{top:{type:'',score:''}};\n    const score=masterDealScore(x);\n    return `${x.bizName}\nDeal Origination Score: ${score} (${masterGrade(score)})\nSeller: ${scan.probability} \u00b7 ${scan.type} \u00b7 ${scan.grade}\nSuccession: ${succ.persona} \u00b7 ${succ.readiness}% \u00b7 ${succ.timeline}\nBuyer: ${buyer.top.type} \u00b7 ${buyer.top.score}\/100\nStage: ${x.stage||'Identified'}\nNext Action: ${x.nextAction||'\u2014'}`;\n  }).join('\\n\\n---\\n\\n');\n  const text=`AI Assisted Deals Sourcing Pro\u2122 Pro\u2122 \u2014 Master Report\n\nGenerated: ${new Date().toLocaleString()}\n\n${rows}`;\n  const blob=new Blob([text],{type:'text\/plain;charset=utf-8'});\n  const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='ai-deal-sourcing-master-report.txt';a.click();\n}\n\n\nlet pursuitPlanIntel=null;\n\nfunction pursuitAnalyze(x){\n  if(!x)return null;\n  ensureArrays(x);\n  const scan=typeof scanProspect==='function'?scanProspect(x):{score:priorityScore(x),grade:'C',probability:'Medium',type:'General Prospect',approach:'Review prospect',timing:'Follow up'};\n  const succ=typeof successionAnalyze==='function'?successionAnalyze(x):{readiness:50,persona:'General Prospect',timeline:'Unknown',style:'Relationship First'};\n  const buyer=typeof buyerMatchAnalyze==='function'?buyerMatchAnalyze(x):{top:{score:50,type:'Unknown Buyer'},memo:'Buyer match not available'};\n  const dealScore=typeof masterDealScore==='function'?masterDealScore(x):Math.round((scan.score+succ.readiness+buyer.top.score)\/3);\n  const grade=typeof masterGrade==='function'?masterGrade(dealScore):(dealScore>=90?'A+':dealScore>=80?'A':dealScore>=70?'B':'C');\n  const goal=val('pursuitGoal')||'seller';\n  const intensity=val('pursuitIntensity')||'normal';\n\n  let mainObjective='Start a confidential seller conversation';\n  if(goal==='valuation')mainObjective='Move prospect toward valuation readiness';\n  if(goal==='listing')mainObjective='Move prospect toward listing strategy conversation';\n  if(goal==='buyer')mainObjective='Research likely buyers and acquisition positioning';\n  if(goal==='rollup')mainObjective='Build market roll-up thesis and buyer strategy';\n\n  let cadence=intensity==='aggressive'?'weekly':intensity==='nurture'?'monthly':'every 10-14 days';\n\n  const nowTasks=[\n    `Confirm decision-maker and owner contact details for ${x.bizName}.`,\n    `Review website, Google profile, reviews, and visible ownership signals.`,\n    `Run or update Opportunity Scanner, Succession Intelligence, and Buyer Match.`,\n    `Prepare outreach angle: ${scan.approach}.`,\n    `Set next action in pipeline and due date.`\n  ];\n\n  if(dealScore>=85)nowTasks.push('Prioritize direct owner outreach within 14 days.');\n  if(succ.readiness>=75)nowTasks.push('Prepare a valuation or succession-planning conversation.');\n  if(buyer.top.score>=75)nowTasks.push(`Research ${buyer.top.type} targets before first serious seller call.`);\n\n  const thirty=[\n    'Send first personalized outreach.',\n    `Follow up on a ${cadence} cadence if no response.`,\n    'Log all activity in prospect history.',\n    'If response received, qualify motivation, timing, valuation expectations, and confidentiality concerns.',\n    'If no response, move to multi-channel outreach: email, phone, LinkedIn, direct mail.'\n  ];\n\n  const sixty=[\n    'Complete exit readiness assessment or seller discovery call if engaged.',\n    'Prepare confidential value-readiness snapshot.',\n    `Build preliminary buyer positioning around ${buyer.top.type}.`,\n    'Identify 3-5 possible strategic or financial buyer categories.',\n    'Update pipeline stage based on engagement level.'\n  ];\n\n  const ninety=[\n    'If seller is engaged, transition to valuation or listing strategy conversation.',\n    'If seller is not ready, move to nurture sequence with quarterly check-ins.',\n    'If buyer interest appears strong, prepare buyer-demand talking points.',\n    'If cluster opportunity exists, connect prospect to roll-up thesis.',\n    'Decide: pursue now, nurture, or archive\/watchlist.'\n  ];\n\n  return {x,scan,succ,buyer,dealScore,grade,goal,intensity,mainObjective,cadence,nowTasks,thirty,sixty,ninety};\n}\n\nfunction generatePursuitPlan(){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return}\n  const a=pursuitAnalyze(x);\n  pursuitPlanIntel={date:new Date().toLocaleString(),...a};\n\n  $('pursuitSelected').textContent=`${x.bizName}\nIndustry: ${x.industry||'\u2014'}\nLocation: ${x.location||'\u2014'}\nStage: ${x.stage||'Identified'}\nNext Action: ${x.nextAction||'\u2014'}`;\n\n  $('pursuitSummary').innerHTML=`<div class=\"pursuit-score\">${a.dealScore}<\/div>\nDeal Origination Score: ${a.grade}\n\nPrimary Objective:\n${a.mainObjective}\n\nSeller Profile:\n${a.scan.probability} \u00b7 ${a.scan.type}\nSuccession Persona: ${a.succ.persona}\nTransition Timeline: ${a.succ.timeline}\n\nBuyer Fit:\n${a.buyer.top.type} \u00b7 ${a.buyer.top.score}\/100\n\nRecommended Cadence:\n${a.cadence}`;\n\n  function phase(title,items,tag){\n    return `<div class=\"plan-phase\"><h4>${title}<\/h4>${items.map((t,i)=>`<div class=\"plan-task\"><b>${i+1}. ${t}<\/b><span class=\"plan-pill ${tag||''}\">${title}<\/span><\/div>`).join('')}<\/div>`;\n  }\n  $('pursuitPlan').innerHTML=\n    phase('Immediate \/ This Week',a.nowTasks,'hot')+\n    phase('30-Day Plan',a.thirty,'')+\n    phase('60-Day Plan',a.sixty,'warn')+\n    phase('90-Day Plan',a.ninety,'risk');\n\n  $('pursuitNotes').textContent=`Broker Guidance:\n${a.dealScore>=85?'Treat this as a top-tier pursuit. Move quickly but keep the tone confidential and advisory.':a.dealScore>=70?'Good opportunity. Complete research and start measured outreach.':'Keep in nurture\/watchlist unless new seller signals appear.'}\n\nSuggested Opening Position:\n${a.scan.approach}\n\nLikely Conversation Style:\n${a.succ.style}\n\nBuyer Strategy:\n${a.buyer.top.type} is currently the best buyer-fit category. Use this to frame buyer demand, not to pressure the seller.`;\n  renderPursuitMetrics();\n}\nfunction renderPursuitMetrics(){\n  if(!$('ppHigh'))return;\n  const rows=prospects.map(pursuitAnalyze).filter(Boolean);\n  $('ppHigh').textContent=rows.filter(r=>r.dealScore>=80).length;\n  $('ppValuation').textContent=rows.filter(r=>r.succ.readiness>=75).length;\n  $('ppBuyer').textContent=rows.filter(r=>r.buyer.top.score>=75).length;\n  $('ppOutreach').textContent=rows.filter(r=>r.scan.score>=70).length;\n}\nfunction savePursuitPlan(){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return}\n  if(!pursuitPlanIntel)generatePursuitPlan();\n  ensureArrays(x);\n  x.history.unshift(hist('Deal Pursuit Plan',`Generated pursuit plan. Deal Score ${pursuitPlanIntel.dealScore}\/100 (${pursuitPlanIntel.grade}). Objective: ${pursuitPlanIntel.mainObjective}.`));\n  x.nextAction=pursuitPlanIntel.dealScore>=85?'Execute top-tier owner outreach plan':'Begin pursuit plan research and outreach';\n  $('nextAction').value=x.nextAction;\n  persist();renderAll();\n  alert('Deal pursuit plan saved to prospect history.');\n}\nfunction exportPursuitPlan(){\n  if(!pursuitPlanIntel)generatePursuitPlan();\n  if(!pursuitPlanIntel)return;\n  const a=pursuitPlanIntel;\n  const text=`Deal Pursuit Planner\n\nBusiness: ${a.x.bizName}\nDeal Origination Score: ${a.dealScore} (${a.grade})\nPrimary Objective: ${a.mainObjective}\nSeller Profile: ${a.scan.probability} \u00b7 ${a.scan.type}\nSuccession Persona: ${a.succ.persona}\nBuyer Fit: ${a.buyer.top.type} \u00b7 ${a.buyer.top.score}\/100\n\nIMMEDIATE \/ THIS WEEK\n${a.nowTasks.map((t,i)=>`${i+1}. ${t}`).join('\\n')}\n\n30-DAY PLAN\n${a.thirty.map((t,i)=>`${i+1}. ${t}`).join('\\n')}\n\n60-DAY PLAN\n${a.sixty.map((t,i)=>`${i+1}. ${t}`).join('\\n')}\n\n90-DAY PLAN\n${a.ninety.map((t,i)=>`${i+1}. ${t}`).join('\\n')}\n\nBROKER NOTES\n${$('pursuitNotes').innerText}`;\n  const blob=new Blob([text],{type:'text\/plain;charset=utf-8'});\n  const aTag=document.createElement('a');aTag.href=URL.createObjectURL(blob);aTag.download='ai-deal-pursuit-plan.txt';aTag.click();\n}\n\n\nlet followupIntel=null;\n\nfunction ensureFollowupFields(x){\n  ensureArrays(x);\n  x.activities=x.activities||[];\n  return x;\n}\nfunction getActivityRows(x){\n  ensureFollowupFields(x);\n  return x.activities||[];\n}\nfunction activityCounts(x){\n  const rows=getActivityRows(x);\n  const c={'Email Sent':0,'Call Made':0,'Voicemail Left':0,'LinkedIn Touch':0,'Meeting Booked':0,'Response Received':0};\n  rows.forEach(a=>{c[a.type]=(c[a.type]||0)+1});\n  return c;\n}\nfunction lastActivityAge(x){\n  const rows=getActivityRows(x);\n  if(!rows.length)return 999;\n  const latest=rows.map(a=>new Date(a.date)).sort((a,b)=>b-a)[0];\n  return Math.floor((new Date()-latest)\/86400000);\n}\nfunction followupAnalyze(x){\n  ensureFollowupFields(x);\n  const scan=typeof scanProspect==='function'?scanProspect(x):{score:priorityScore(x),probability:'Medium',type:'General Prospect',grade:'C'};\n  const succ=typeof successionAnalyze==='function'?successionAnalyze(x):{readiness:50,persona:'General Prospect'};\n  const buyer=typeof buyerMatchAnalyze==='function'?buyerMatchAnalyze(x):{top:{score:50,type:'Unknown Buyer'}};\n  const pursuit=typeof masterDealScore==='function'?masterDealScore(x):priorityScore(x);\n  const counts=activityCounts(x);\n  const age=lastActivityAge(x);\n\n  let activityScore=0;\n  activityScore+=Math.min((counts['Email Sent']||0)*5,15);\n  activityScore+=Math.min((counts['Call Made']||0)*7,18);\n  activityScore+=Math.min((counts['Voicemail Left']||0)*4,10);\n  activityScore+=Math.min((counts['LinkedIn Touch']||0)*4,10);\n  activityScore+=(counts['Meeting Booked']||0)?25:0;\n  activityScore+=(counts['Response Received']||0)?20:0;\n  if(age<=7)activityScore+=10;\n  else if(age<=30)activityScore+=4;\n  else if(age>=90)activityScore-=15;\n\n  let momentum=Math.round((pursuit*.45)+(scan.score*.25)+(succ.readiness*.15)+(buyer.top.score*.15)+activityScore*.25);\n  momentum=Math.min(100,Math.max(0,momentum));\n\n  let status='Nurture';\n  if(age>=90 && !getActivityRows(x).length)status='Nurture';\n  else if(age>=90)status='Dormant';\n  else if(momentum>=85 || (counts['Meeting Booked']||0)>0)status='Hot';\n  else if(momentum>=68 || (counts['Response Received']||0)>0)status='Warm';\n  else if(momentum<45)status='Dormant';\n\n  let next='Send follow-up email';\n  if(status==='Hot')next='Call today and move toward valuation or meeting';\n  else if(status==='Warm')next='Send personalized follow-up and ask for a short call';\n  else if(status==='Nurture')next='Send educational nurture touch';\n  else if(status==='Dormant')next='Re-activate with new market insight or move to watchlist';\n\n  if(!(counts['Email Sent']||0))next='Send initial personalized outreach';\n  else if(!(counts['Call Made']||0) && momentum>=70)next='Make first phone call';\n  else if((counts['Meeting Booked']||0)>0)next='Prepare meeting agenda and valuation questions';\n\n  return {scan,succ,buyer,pursuit,counts,age,momentum,status,next};\n}\nfunction cadenceDays(){\n  const t=val('fuCadenceType')||'standard';\n  if(t==='aggressive')return [1,3,7,14,30];\n  if(t==='nurture')return [14,30,60,90,180];\n  return [1,7,14,30,60];\n}\nfunction generateFollowupSchedule(x,a){\n  const start=val('fuStartAction')||'Email';\n  const days=cadenceDays();\n  const labels=[\n    start==='Email'?'Initial personalized outreach':start,\n    'Follow-up email with value angle',\n    'Phone call \/ voicemail',\n    'Educational exit planning touch',\n    'Long-term nurture check-in'\n  ];\n  return days.map((d,i)=>{\n    const date=new Date();\n    date.setDate(date.getDate()+d);\n    return {day:d,date:date.toISOString().slice(0,10),action:labels[i]||'Follow up',status:d<=1?'Immediate':d<=14?'Near Term':'Nurture'};\n  });\n}\nfunction generateFollowupEngine(){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return}\n  const a=followupAnalyze(x);\n  const schedule=generateFollowupSchedule(x,a);\n  followupIntel={date:new Date().toLocaleString(),business:x.bizName,analysis:a,schedule};\n\n  $('fuSelected').textContent=`${x.bizName}\nIndustry: ${x.industry||'\u2014'}\nStage: ${x.stage||'Identified'}\nCurrent Next Action: ${x.nextAction||'\u2014'}\nLast Activity: ${a.age===999?'No activity logged':a.age+' days ago'}`;\n\n  const cls=a.status==='Hot'?'hot':a.status==='Warm'?'warm':a.status==='Dormant'?'dormant':'nurture';\n  $('fuMomentum').innerHTML=`<div class=\"momentum-score\">${a.momentum}<\/div>\n<p><span class=\"status-chip ${cls}\">${a.status}<\/span><span class=\"status-chip\">${a.scan.probability}<\/span><span class=\"status-chip\">${a.buyer.top.type}<\/span><\/p>\n<p>Deal Momentum Score combines deal quality, seller probability, buyer fit, succession readiness, recent activity, and engagement.<\/p>`;\n\n  $('fuNextBest').textContent=`Next Best Action:\n${a.next}\n\nWhy:\nSeller profile is ${a.scan.probability}; opportunity type is ${a.scan.type}; buyer fit is ${a.buyer.top.type} (${a.buyer.top.score}\/100); activity age is ${a.age===999?'not yet logged':a.age+' days'}.\n\nRecommended Status:\n${a.status}`;\n\n  $('fuSchedule').innerHTML=schedule.map(s=>{\n    const cls=s.day<=1?'today':s.day<=14?'future':'';\n    return `<div class=\"follow-task ${cls}\">\n      <b>Day ${s.day}: ${s.action}<\/b>\n      <p>Target Date: ${s.date}<br>Status: ${s.status}<\/p>\n    <\/div>`;\n  }).join('');\n\n  $('fuActivitySummary').textContent=`Activity Summary:\nEmails Sent: ${a.counts['Email Sent']||0}\nCalls Made: ${a.counts['Call Made']||0}\nVoicemails Left: ${a.counts['Voicemail Left']||0}\nLinkedIn Touches: ${a.counts['LinkedIn Touch']||0}\nMeetings Booked: ${a.counts['Meeting Booked']||0}\nResponses Received: ${a.counts['Response Received']||0}`;\n  renderFollowupMetrics();\n}\nfunction logActivity(type){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return}\n  ensureFollowupFields(x);\n  const note=val('fuActivityNote');\n  x.activities.unshift({date:new Date().toLocaleString(),type,note});\n  x.history.unshift(hist(type,note||`${type} logged from Follow-Up Engine.`));\n  if(type==='Meeting Booked')x.stage='Meeting Booked';\n  if(type==='Call Made' && x.stage==='Outreach Sent')x.stage='Conversation Started';\n  $('stage').value=x.stage||'Identified';\n  $('fuActivityNote').value='';\n  persist();renderAll();generateFollowupEngine();\n}\nfunction saveFollowupEngine(){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return}\n  if(!followupIntel)generateFollowupEngine();\n  ensureFollowupFields(x);\n  x.followupPlan=followupIntel;\n  x.history.unshift(hist('Follow-Up Plan',`Generated follow-up plan. Momentum ${followupIntel.analysis.momentum}\/100. Status: ${followupIntel.analysis.status}. Next: ${followupIntel.analysis.next}.`));\n  x.nextAction=followupIntel.analysis.next;\n  const first=followupIntel.schedule[0];\n  if(first)x.dueDate=first.date;\n  $('nextAction').value=x.nextAction;\n  $('dueDate').value=x.dueDate||'';\n  persist();renderAll();\n  alert('Follow-up plan saved to prospect history.');\n}\nfunction exportFollowupPlan(){\n  if(!followupIntel)generateFollowupEngine();\n  if(!followupIntel)return;\n  const a=followupIntel.analysis;\n  const text=`Automated Follow-Up Engine\n\nBusiness: ${followupIntel.business}\nMomentum Score: ${a.momentum}\nStatus: ${a.status}\nNext Best Action: ${a.next}\n\nActivity Summary:\nEmails Sent: ${a.counts['Email Sent']||0}\nCalls Made: ${a.counts['Call Made']||0}\nVoicemails Left: ${a.counts['Voicemail Left']||0}\nLinkedIn Touches: ${a.counts['LinkedIn Touch']||0}\nMeetings Booked: ${a.counts['Meeting Booked']||0}\n\nFollow-Up Schedule:\n${followupIntel.schedule.map(s=>`Day ${s.day} (${s.date}) - ${s.action}`).join('\\n')}`;\n  const blob=new Blob([text],{type:'text\/plain;charset=utf-8'});\n  const aTag=document.createElement('a');aTag.href=URL.createObjectURL(blob);aTag.download='follow-up-engine-plan.txt';aTag.click();\n}\n\nfunction followupMessageContext(){\n  const x=p();\n  if(!x)return null;\n  const a=followupAnalyze(x);\n  const owner=x.owner||'Business Owner';\n  const biz=x.bizName||'your business';\n  const industry=x.industry||'your industry';\n  return {x,a,owner,biz,industry};\n}\nfunction generateFollowupMessage(kind){\n  const c=followupMessageContext();\n  if(!c){alert('Select a prospect first.');return}\n  let msg='';\n  if(kind==='email'){\n    msg=`Subject: Quick follow-up regarding ${c.biz}\n\nHi ${c.owner},\n\nI wanted to follow up on ${c.biz}. I work with established ${c.industry} owners who want to understand their options before making any public decision about selling or transitioning.\n\nBased on what I can see, this may be a good time to have a confidential conversation around value, timing, buyer demand, and succession planning.\n\nThis is not meant to pressure you into selling. The goal would simply be to help you understand what your options could look like.\n\nWould a brief confidential conversation next week be reasonable?\n\nBest,\n[Broker Name]`;\n  }else if(kind==='phone'){\n    msg=`Phone Follow-Up Script \u2014 ${c.biz}\n\nHi ${c.owner}, this is [Broker Name]. I work with local business owners in the ${c.industry} space on confidential exit planning, valuation conversations, and buyer demand.\n\nI am not calling to pressure you into selling. I wanted to see if you would be open to a short conversation about what businesses like ${c.biz} are seeing in today's market and what a future transition could look like.\n\nIf now is not the right time, that's completely fine. I would still be happy to be a resource when planning becomes relevant.`;\n  }else{\n    msg=`Hi ${c.owner}, I wanted to follow up briefly. I work with established ${c.industry} business owners who want to understand business value, buyer demand, and confidential transition options before making any public decision. Happy to be a resource if useful.`;\n  }\n  $('fuMessageOutput').textContent=msg;\n  return msg;\n}\nfunction saveFollowupMessage(){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return}\n  const msg=($('fuMessageOutput')?.innerText||'').trim();\n  if(!msg || msg.includes('Generate a follow-up message')){alert('Generate a follow-up message first.');return}\n  ensureFollowupFields(x);\n  x.history.unshift(hist('Follow-Up Message Generated',msg));\n  persist();renderAll();\n  alert('Follow-up message saved to prospect history.');\n}\n\nfunction renderFollowupMetrics(){\n  if(!$('fuHot'))return;\n  const rows=prospects.map(followupAnalyze);\n  $('fuHot').textContent=rows.filter(r=>r.status==='Hot').length;\n  $('fuWarm').textContent=rows.filter(r=>r.status==='Warm').length;\n  $('fuNurture').textContent=rows.filter(r=>r.status==='Nurture').length;\n  $('fuDormant').textContent=rows.filter(r=>r.status==='Dormant').length;\n}\n\n\nfunction mdCounty(x){\n  const raw=[x.county,x.location,x.address].filter(Boolean).join(' ').toLowerCase();\n  const known=['hillsborough','pinellas','pasco','hernando','manatee','sarasota','polk','orange','seminole','broward','miami-dade','palm beach','lee','collier'];\n  for(const k of known){if(raw.includes(k))return k.split(' ').map(w=>w.charAt(0).toUpperCase()+w.slice(1)).join(' ')+' County'}\n  if((x.location||'').includes(','))return x.location.split(',')[0].trim()+' Area';\n  return x.location||'Unknown Market';\n}\nfunction mdIndustry(x){return (x.industry||'Unknown Industry').toString().trim()||'Unknown Industry'}\nfunction mdActivityCounts(){\n  const totals={'Email Sent':0,'Call Made':0,'Voicemail Left':0,'LinkedIn Touch':0,'Meeting Booked':0,'Response Received':0};\n  prospects.forEach(x=>{\n    if(typeof ensureFollowupFields==='function')ensureFollowupFields(x); else ensureArrays(x);\n    (x.activities||[]).forEach(a=>{totals[a.type]=(totals[a.type]||0)+1});\n  });\n  return totals;\n}\nfunction mdDealScore(x){return typeof masterDealScore==='function'?masterDealScore(x):(typeof priorityScore==='function'?priorityScore(x):50)}\nfunction mdStatus(x){\n  if(typeof followupAnalyze==='function')return followupAnalyze(x).status;\n  const s=mdDealScore(x);\n  if(s>=85)return 'Hot';\n  if(s>=70)return 'Warm';\n  return 'Nurture';\n}\nfunction mdGroupBy(fn){\n  const groups={};\n  prospects.forEach(x=>{const k=fn(x);groups[k]=groups[k]||[];groups[k].push(x)});\n  return groups;\n}\nfunction mdAnalyzeGroup(name,items){\n  const total=items.length;\n  const hot=items.filter(x=>mdStatus(x)==='Hot'||mdDealScore(x)>=85).length;\n  const meetings=items.filter(x=>(x.stage||'')==='Meeting Booked').length;\n  const active=items.filter(x=>!['Closed','Under Contract'].includes(x.stage||'')).length;\n  const avg=total?Math.round(items.reduce((a,x)=>a+mdDealScore(x),0)\/total):0;\n  const penetration=Math.min(100,Math.round((total*12)+(hot*10)+(meetings*12)+(active*4)));\n  return {name,total,hot,meetings,active,avg,penetration,items};\n}\nfunction mdRenderCoverage(targetId,groups){\n  const rows=Object.entries(groups).map(([k,v])=>mdAnalyzeGroup(k,v)).sort((a,b)=>b.total-a.total||b.avg-a.avg);\n  const box=$(targetId);\n  if(!box)return rows;\n  if(!rows.length){box.innerHTML='<div class=\"empty-state\">No prospect data yet.<\/div>';return rows}\n  box.innerHTML='<div class=\"market-row head\"><div>Market<\/div><div>Prospects<\/div><div>Hot<\/div><div>Score<\/div><\/div>'+\n    rows.map(r=>`<div class=\"market-row\"><div><b>${r.name}<\/b><br><small>${r.active} active \u00b7 ${r.meetings} meetings<\/small><\/div><div>${r.total}<\/div><div>${r.hot}<\/div><div>${r.penetration}<\/div><\/div>`).join('');\n  return rows;\n}\nfunction mdMarketHeatRows(){\n  const groups={};\n  prospects.forEach(x=>{\n    const k=mdCounty(x)+' \u00b7 '+mdIndustry(x);\n    groups[k]=groups[k]||[];\n    groups[k].push(x);\n  });\n  return Object.entries(groups).map(([k,v])=>mdAnalyzeGroup(k,v)).sort((a,b)=>b.penetration-a.penetration||b.avg-a.avg);\n}\nfunction renderMarketDomination(){\n  if(!$('marketTab'))return;\n  const countyRows=mdRenderCoverage('countyCoverage',mdGroupBy(mdCounty));\n  const industryRows=mdRenderCoverage('industryCoverage',mdGroupBy(mdIndustry));\n  const heat=mdMarketHeatRows();\n  const activities=mdActivityCounts();\n  const counties=countyRows.map(r=>r.name);\n  const industries=industryRows.map(r=>r.name).filter(x=>!x.includes('Unknown'));\n  const gaps=[];\n  counties.forEach(c=>industries.forEach(i=>{if(!prospects.some(x=>mdCounty(x)===c&&mdIndustry(x)===i))gaps.push({county:c,industry:i})}));\n  const hotMarkets=heat.filter(r=>r.penetration>=70).length;\n  const avgPen=heat.length?Math.round(heat.reduce((a,r)=>a+r.penetration,0)\/heat.length):0;\n  $('mdMarkets').textContent=heat.length;\n  $('mdHotMarkets').textContent=hotMarkets;\n  $('mdGaps').textContent=Math.min(gaps.length,99);\n  $('mdPenetration').textContent=avgPen;\n  $('marketHeat').innerHTML=heat.length?heat.slice(0,10).map((r,i)=>{\n    const cls=r.penetration>=80?'hot':r.penetration>=55?'warn':'risk';\n    return `<div class=\"heat-item\"><div class=\"market-score\">${r.penetration}<\/div><div><b>${i+1}. ${r.name}<\/b><br><span class=\"market-pill ${cls}\">${r.total} prospects<\/span><span class=\"market-pill\">${r.hot} hot<\/span><span class=\"market-pill\">${r.meetings} meetings<\/span><p>Avg Deal Score: ${r.avg}\/100<\/p><\/div><\/div>`;\n  }).join(''):'<div class=\"empty-state\">No market heat yet.<\/div>';\n  $('whiteSpace').innerHTML=gaps.length?gaps.slice(0,12).map(g=>`<div class=\"whitespace-item\"><b>${g.industry} in ${g.county}<\/b><br><small>No saved prospects in this market\/industry combination.<\/small><br><span class=\"market-pill\">Recommended: run Prospect Sourcing<\/span><\/div>`).join(''):'<div class=\"empty-state\">No white-space gaps found from current counties and industries.<\/div>';\n  $('brokerProductivity').innerHTML=`<div class=\"productivity-grid\">\n    <div class=\"productivity-box\"><span>Emails<\/span><b>${activities['Email Sent']||0}<\/b><\/div>\n    <div class=\"productivity-box\"><span>Calls<\/span><b>${activities['Call Made']||0}<\/b><\/div>\n    <div class=\"productivity-box\"><span>Meetings<\/span><b>${activities['Meeting Booked']||0}<\/b><\/div>\n    <div class=\"productivity-box\"><span>Responses<\/span><b>${activities['Response Received']||0}<\/b><\/div>\n  <\/div>`;\n  const topCounty=countyRows[0]?.name||'No county yet';\n  const topIndustry=industryRows[0]?.name||'No industry yet';\n  const topHeat=heat[0]?.name||'No hot market yet';\n  $('marketExecutiveSummary').textContent=`Market Domination Summary\n\nTotal Prospects:\n${prospects.length}\n\nStrongest County \/ Market:\n${topCounty}\n\nStrongest Industry:\n${topIndustry}\n\nTop Market Opportunity:\n${topHeat}\n\nAverage Market Penetration:\n${avgPen}\/100\n\nWhite-Space Opportunities:\n${gaps.length}\n\nRecommended Broker Owner Action:\n${gaps.length?'Use the white-space list to direct the next Prospect Sourcing campaign.':'Continue expanding coverage by adding more prospects across counties and industries.'}`;\n}\nfunction exportMarketDomination(){\n  renderMarketDomination();\n  const heat=mdMarketHeatRows();\n  const activities=mdActivityCounts();\n  const text=`Market Domination Dashboard Report\n\nGenerated: ${new Date().toLocaleString()}\n\nTotal Prospects: ${prospects.length}\n\nTop Markets:\n${heat.map((r,i)=>`${i+1}. ${r.name} - Penetration ${r.penetration}, Prospects ${r.total}, Hot ${r.hot}, Meetings ${r.meetings}`).join('\\n')}\n\nBroker Productivity:\nEmails Sent: ${activities['Email Sent']||0}\nCalls Made: ${activities['Call Made']||0}\nVoicemails Left: ${activities['Voicemail Left']||0}\nLinkedIn Touches: ${activities['LinkedIn Touch']||0}\nMeetings Booked: ${activities['Meeting Booked']||0}\nResponses Received: ${activities['Response Received']||0}\n\nExecutive Summary:\n${$('marketExecutiveSummary')?.innerText||''}`;\n  const blob=new Blob([text],{type:'text\/plain;charset=utf-8'});\n  const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='market-domination-dashboard-report.txt';a.click();\n}\n\n\nfunction goWorkflowStep(tab,el){\n  const navButton=[...document.querySelectorAll('.tab')].find(b=>b.getAttribute('onclick')&&b.getAttribute('onclick').includes(\"'\" + tab + \"'\"));\n  showTab(tab,{target:navButton||el});\n  document.querySelectorAll('.workflow-pill').forEach(x=>x.classList.remove('active'));\n  if(el)el.classList.add('active');\n}\nfunction syncWorkflowActive(tab){\n  document.querySelectorAll('.workflow-pill').forEach(x=>x.classList.toggle('active',x.getAttribute('data-step-tab')===tab));\n}\n\n\nfunction exportLaunchReadinessReport(){\n  const text=`AI Assisted Deals Sourcing Pro\u2122 \u2014 Launch Readiness Report\n\nPowered by 360 Biz Brokers\n\nChecklist:\n1. Confirm Prospect Sourcing works in the Tools Portal.\n2. Confirm Live Data \/ Google Places Endpoint mode works when selected.\n3. Confirm saved prospects remain after browser refresh.\n4. Confirm Pipeline history logs activity.\n5. Confirm Export Backup downloads a JSON backup.\n6. Confirm Seller Report and Market Report exports work.\n7. Confirm no visible development version labels appear.\n\nImportant:\nProspects are stored in the encrypted member vault after the vault is unlocked. Export Backup remains available as a user-controlled backup option.`;\n  const blob=new Blob([text],{type:'text\/plain;charset=utf-8'});\n  const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='launch-readiness-report.txt';a.click();\n}\n\n\nasync function cloudRequest(url,options={}){\n  const cfg=window.ADS_CLOUD_STORAGE;\n  if(!cfg||!cfg.enabled)throw new Error('Encrypted storage is not available. Please log into WordPress.');\n  options.credentials='same-origin';\n  options.headers=Object.assign({'X-WP-Nonce':cfg.nonce||''},options.headers||{});\n  const res=await fetch(url,options);\n  const data=await res.json().catch(()=>({}));\n  if(!res.ok)throw new Error(data.message||('HTTP '+res.status));\n  return data;\n}\nfunction cloudSetStatus(text,type='warn'){\n  const el=document.getElementById('cloudStorageStatus');\n  if(!el)return;\n  el.textContent=text;\n  el.className='cloud-badge '+(type||'warn');\n  if(typeof launchSetCloudStatus==='function'){launchSetCloudStatus(text,(type==='ok'?'ok':type==='risk'?'risk':''));}\n  if(typeof updateLaunchDashboard==='function'){updateLaunchDashboard(new Date().toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'}));}\n}\n\nfunction cloudVaultRecordKey(){\n  const cfg=window.ADS_CLOUD_STORAGE||{};\n  const key=(cfg.recordKey||'').toString().trim();\n  return key && key !== 'default' ? key : 'deals_sourcing';\n}\nfunction cloudExtractEncrypted(result){\n  let encrypted=result&&result.encrypted_data?result.encrypted_data:(result&&result.data?result.data:null);\n  if(typeof encrypted==='string'){\n    try{encrypted=JSON.parse(encrypted);}catch(e){}\n  }\n  if(Array.isArray(encrypted))return null;\n  if(encrypted&&encrypted.encrypted_data)encrypted=encrypted.encrypted_data;\n  if(encrypted&&encrypted.data&&encrypted.data.ciphertext)encrypted=encrypted.data;\n  return encrypted&&encrypted.ciphertext?encrypted:null;\n}\nfunction vaultBytesToBase64(bytes){let bin=''; bytes=new Uint8Array(bytes); for(let i=0;i<bytes.length;i++)bin+=String.fromCharCode(bytes[i]); return btoa(bin);}\nfunction vaultBase64ToBytes(b64){const bin=atob(b64||''); const out=new Uint8Array(bin.length); for(let i=0;i<bin.length;i++)out[i]=bin.charCodeAt(i); return out;}\nasync function vaultDeriveKey(password,salt){\n  const enc=new TextEncoder();\n  const baseKey=await crypto.subtle.importKey('raw',enc.encode(password),'PBKDF2',false,['deriveKey']);\n  return crypto.subtle.deriveKey({name:'PBKDF2',salt,iterations:250000,hash:'SHA-256'},baseKey,{name:'AES-GCM',length:256},false,['encrypt','decrypt']);\n}\nasync function vaultEncryptObject(obj,password,existingSalt){\n  const enc=new TextEncoder();\n  const salt=existingSalt?vaultBase64ToBytes(existingSalt):crypto.getRandomValues(new Uint8Array(16));\n  const iv=crypto.getRandomValues(new Uint8Array(12));\n  const key=await vaultDeriveKey(password,salt);\n  const cipher=await crypto.subtle.encrypt({name:'AES-GCM',iv},key,enc.encode(JSON.stringify(obj)));\n  return {version:1,algorithm:'AES-GCM',kdf:'PBKDF2-SHA256',iterations:250000,salt:vaultBytesToBase64(salt),iv:vaultBytesToBase64(iv),ciphertext:vaultBytesToBase64(cipher),updatedAt:new Date().toISOString()};\n}\nasync function vaultDecryptObject(payload,password){\n  if(!payload||!payload.ciphertext)throw new Error('No encrypted vault data found.');\n  const dec=new TextDecoder();\n  const salt=vaultBase64ToBytes(payload.salt), iv=vaultBase64ToBytes(payload.iv), cipher=vaultBase64ToBytes(payload.ciphertext);\n  const key=await vaultDeriveKey(password,salt);\n  const plain=await crypto.subtle.decrypt({name:'AES-GCM',iv},key,cipher);\n  return JSON.parse(dec.decode(plain));\n}\nasync function vaultPromptPassword(mode){\n  const msg=mode==='create'\n    ? 'Create a Secure Workspace Password. IMPORTANT: If you forget it, nobody can recover your saved data.'\n    : 'Enter your Secure Workspace Password to unlock your encrypted workspace.';\n  const pw=prompt(msg);\n  if(!pw)return '';\n  if(pw.length<8){alert('Please use at least 8 characters. A longer passphrase is safer.');return '';}\n  if(mode==='create'){\n    const confirmPw=prompt('Re-enter the same Secure Workspace Password to confirm.');\n    if(pw!==confirmPw){alert('The Workspace Passwords did not match.');return '';}\n  }\n  return pw;\n}\nasync function vaultUnlock(){\n  try{\n    if(!(window.ADS_CLOUD_STORAGE&&window.ADS_CLOUD_STORAGE.enabled)){\n      cloudSetStatus('Login required before vault unlock','risk');\n      alert('Please log into the Brokers Pro Suite first.');\n      return;\n    }\n    const cfg=window.ADS_CLOUD_STORAGE;\n    const url=cfg.loadUrl+'?record_key='+encodeURIComponent(cloudVaultRecordKey());\n    const result=await cloudRequest(url);\n    const encrypted=cloudExtractEncrypted(result);\n    if(encrypted&&encrypted.ciphertext){\n      const pw=await vaultPromptPassword('unlock');\n      if(!pw)return;\n      const obj=await vaultDecryptObject(encrypted,pw);\n      window.adsVaultPassword=pw;\n      window.adsVaultSalt=encrypted.salt;\n      window.adsVaultUnlocked=true;\n      prospects=Array.isArray(obj.prospects)?obj.prospects:[];\n      selectedId=null;\n      renderAll();\n      cloudSetStatus('Workspace opened: '+prospects.length+' records','ok');\n    }else{\n      const pw=await vaultPromptPassword('create');\n      if(!pw)return;\n      window.adsVaultPassword=pw;\n      window.adsVaultSalt=null;\n      window.adsVaultUnlocked=true;\n      prospects=[];\n      selectedId=null;\n      renderAll();\n      await cloudSaveNow(true);\n      cloudSetStatus('New secure workspace created','ok');\n    }\n  }catch(err){\n    window.adsVaultUnlocked=false;\n    cloudSetStatus('Workspace unlock failed','risk');\n    alert('Workspace unlock failed. The password may be incorrect, or storage is not configured. '+err.message);\n  }\n}\nfunction vaultLock(){\n  if(!confirm('Lock this secure workspace on this device now? Unsaved changes should already be auto-saved if the vault was unlocked.'))return;\n  window.adsVaultPassword='';\n  window.adsVaultUnlocked=false;\n  prospects=[];\n  selectedId=null;\n  renderAll();\n  cloudSetStatus('Member Workspace locked','warn');\n}\nasync function cloudLoadNow(silent=false){\n  if(!window.adsVaultUnlocked){\n    if(!silent)await vaultUnlock();\n    return;\n  }\n  try{\n    const cfg=window.ADS_CLOUD_STORAGE;\n    const url=cfg.loadUrl+'?record_key='+encodeURIComponent(cloudVaultRecordKey());\n    const result=await cloudRequest(url);\n    const encrypted=cloudExtractEncrypted(result);\n    if(!encrypted||!encrypted.ciphertext){prospects=[];}else{\n      const obj=await vaultDecryptObject(encrypted,window.adsVaultPassword);\n      prospects=Array.isArray(obj.prospects)?obj.prospects:[];\n      window.adsVaultSalt=encrypted.salt;\n    }\n    selectedId=null;\n    renderAll();\n    cloudSetStatus('Encrypted data loaded: '+prospects.length+' records','ok');\n    if(!silent)alert('Encrypted records loaded.');\n  }catch(err){\n    cloudSetStatus('Encrypted load failed','risk');\n    if(!silent)alert('Encrypted load failed: '+err.message);\n  }\n}\nasync function cloudSaveNow(silent=false){\n  try{\n    if(!(window.ADS_CLOUD_STORAGE&&window.ADS_CLOUD_STORAGE.enabled)){\n      cloudSetStatus('Login required for encrypted sync','risk');\n      return;\n    }\n    if(!window.adsVaultUnlocked||!window.adsVaultPassword){\n      cloudSetStatus('Open workspace to save','warn');\n      if(!silent)alert('Please open your Secure Workspace before saving.');\n      return;\n    }\n    const cfg=window.ADS_CLOUD_STORAGE;\n    const encrypted=await vaultEncryptObject({tool:'deals_sourcing',prospects,updatedAt:new Date().toISOString()},window.adsVaultPassword,window.adsVaultSalt);\n    window.adsVaultSalt=encrypted.salt;\n    await cloudRequest(cfg.saveUrl+'?record_key='+encodeURIComponent(cloudVaultRecordKey()),{\n      method:'POST',\n      headers:{'Content-Type':'application\/json'},\n      body:JSON.stringify({encrypted_data:encrypted,data:encrypted,payload:encrypted})\n    });\n    cloudSetStatus('Encrypted auto-save: '+prospects.length+' records','ok');\n    if(!silent)alert('Encrypted data saved.');\n  }catch(err){\n    cloudSetStatus('Encrypted save failed','risk');\n    if(!silent)alert('Encrypted save failed: '+err.message);\n  }\n}\nasync function cloudMigrateLocal(){\n  let local=[];\n  try{local=JSON.parse(localStorage.getItem('ads_v5_complete_prospects')||'[]');}catch(e){local=[];}\n  if(!local.length){alert('No old browser records found to migrate.');return}\n  if(!window.adsVaultUnlocked){await vaultUnlock();}\n  if(!window.adsVaultUnlocked)return;\n  if(!confirm('Copy '+local.length+' old browser records into this encrypted vault? After confirming the save, you may clear old browser storage.'))return;\n  prospects=local;\n  selectedId=null;\n  renderAll();\n  await cloudSaveNow(false);\n}\nasync function cloudHasEncryptedRecord(){\n  try{\n    if(!(window.ADS_CLOUD_STORAGE&&window.ADS_CLOUD_STORAGE.enabled))return false;\n    const cfg=window.ADS_CLOUD_STORAGE;\n    const url=cfg.loadUrl+'?record_key='+encodeURIComponent(cloudVaultRecordKey());\n    const result=await cloudRequest(url);\n    const encrypted=cloudExtractEncrypted(result);\n    return !!(encrypted&&encrypted.ciphertext);\n  }catch(e){\n    return false;\n  }\n}\nfunction cloudInit(){\n  window.adsVaultUnlocked=false;\n  window.adsVaultPassword='';\n  if(window.ADS_CLOUD_STORAGE&&window.ADS_CLOUD_STORAGE.enabled){\n    cloudSetStatus('Member Workspace locked \u2014 click Open Member Workspace','warn');\n    setTimeout(async function(){\n      try{\n        if(window.adsVaultUnlocked)return;\n        const hasRecord=await cloudHasEncryptedRecord();\n        if(hasRecord && !sessionStorage.getItem('ads_workspace_prompted_this_session')){\n          sessionStorage.setItem('ads_workspace_prompted_this_session','1');\n          await vaultUnlock();\n        }\n      }catch(e){}\n    },700);\n  }else{\n    cloudSetStatus('Login required for encrypted storage','warn');\n  }\n}\n\n\nfunction launchMemberLabel(){\n  const cfg=window.ADS_CLOUD_STORAGE||{};\n  if(cfg.userDisplayName)return cfg.userDisplayName;\n  if(cfg.userId)return 'Member #' + cfg.userId;\n  return 'Member';\n}\nfunction updateLaunchDashboard(syncText){\n  if(!$('launchProspects'))return;\n  const active=prospects.filter(x=>!['Closed','Under Contract'].includes(x.stage||'')).length;\n  const hot=prospects.filter(x=>priorityScore(x)>=70).length;\n  const due=prospects.filter(x=>isDue(x.dueDate)).length;\n  $('launchMemberName').textContent=launchMemberLabel();\n  $('launchProspects').textContent=prospects.length;\n  $('launchPipeline').textContent=active;\n  $('launchHot').textContent=hot;\n  $('launchDue').textContent=due;\n  if($('launchReadiness'))$('launchReadiness').textContent=prospects.filter(x=>listingReadinessScore(x).score>=80).length;\n  if(syncText)$('launchLastSync').textContent=syncText;\n}\nfunction launchSetCloudStatus(text,type){\n  const status=$('launchCloudStatus'),dot=$('launchSyncDot');\n  if(status)status.textContent=text||'Cloud Sync';\n  if(dot){dot.className='sync-dot '+(type||'');}\n}\n\n\nlet apolloOwnerResults=[];\nlet apolloSelectedContact=null;\n\nfunction apolloExtractDomain(input){\n  input=(input||'').trim();\n  if(!input)return '';\n  input=input.replace(\/^https?:\\\/\\\/\/i,'').replace(\/^www\\.\/i,'').split('\/')[0].replace(\/^@\/,'');\n  return input.toLowerCase();\n}\n\nfunction apolloScoreClass(score){return score>=85?'green':score>=70?'blue':score>=50?'amber':'red'}\n\nfunction apolloDisplayName(c){\n  const full=(c.name||c.full_name||'').trim();\n  if(full && full.toLowerCase()!=='unknown contact')return full;\n  const built=[c.first_name,c.last_name].filter(Boolean).join(' ').trim();\n  if(built)return built;\n  if(c.email)return c.email.split('@')[0];\n  return 'Contact name not returned';\n}\nfunction apolloTitleScore(title){\n  const t=(title||'').toLowerCase();\n  if(\/\\b(owner|business owner|principal owner)\\b\/.test(t))return 100;\n  if(\/\\b(founder|co-founder|co founder)\\b\/.test(t))return 98;\n  if(\/\\b(chief executive officer|ceo)\\b\/.test(t))return 95;\n  if(\/\\bpresident\\b\/.test(t))return 95;\n  if(\/\\bmanaging partner\\b\/.test(t))return 92;\n  if(\/\\bprincipal\\b\/.test(t))return 90;\n  if(\/\\bpartner\\b\/.test(t))return 80;\n  if(\/\\b(general manager|operator)\\b\/.test(t))return 72;\n  if(\/\\b(vp|vice president)\\b\/.test(t))return 65;\n  if(\/\\bdirector\\b\/.test(t))return 60;\n  if(\/\\bmanager\\b\/.test(t))return 40;\n  return 25;\n}\nfunction apolloOrgMatchScore(c){\n  const wantedDomain=apolloExtractDomain(val('apolloDomain'));\n  const wantedName=(val('apolloCompany')||'').toLowerCase().replace(\/[^a-z0-9 ]\/g,' ').replace(\/\\s+\/g,' ').trim();\n  const orgName=(c.organization_name||'').toLowerCase();\n  const orgDomain=apolloExtractDomain(c.organization_website_url||c.organization_domain||c.organization_primary_domain||'');\n\n  if(wantedDomain && orgDomain && wantedDomain===orgDomain)return {score:35,label:'Current company domain match'};\n  if(wantedDomain && orgDomain && (orgDomain.includes(wantedDomain)||wantedDomain.includes(orgDomain)))return {score:28,label:'Related domain match'};\n  if(wantedDomain && !orgDomain && orgName && wantedName && orgName.includes(wantedName))return {score:18,label:'Company name match; domain not returned'};\n  if(wantedName && orgName && (orgName.includes(wantedName)||wantedName.includes(orgName)))return {score:16,label:'Company name match'};\n  if(wantedDomain)return {score:-10,label:'Domain not confirmed'};\n  return {score:0,label:'No domain supplied'};\n}\nfunction apolloIsNoisyLargeCompany(c){\n  const company=(val('apolloCompany')||'').toLowerCase().trim();\n  const domain=apolloExtractDomain(val('apolloDomain'));\n  const title=(c.title||'').toLowerCase();\n  const org=(c.organization_name||'').toLowerCase();\n\n  const commonEnterpriseDomains=['apple.com','google.com','microsoft.com','amazon.com','meta.com','facebook.com','tesla.com','walmart.com'];\n  const enterprise = commonEnterpriseDomains.includes(domain) || ['apple','google','microsoft','amazon','meta','facebook','tesla','walmart'].includes(company);\n\n  if(!enterprise)return false;\n  if(\/advisor|academic|member|board member|consultant|student|assistant\/i.test(title))return true;\n  if(domain && !apolloExtractDomain(c.organization_website_url||'').includes(domain.replace(\/^www\\.\/,'')) && org.indexOf(company)===-1)return true;\n  return false;\n}\nfunction apolloConfidence(c){\n  const titleScore=apolloTitleScore(c.title);\n  const org=apolloOrgMatchScore(c);\n  let score=20 + Math.round(titleScore*.45) + org.score;\n  const reasons=[];\n  reasons.push(org.label);\n  reasons.push('Title signal: '+(c.title||'not returned'));\n  if(c.linkedin_url){score+=8;reasons.push('LinkedIn profile returned');}\n  if(c.email_status==='verified'){score+=7;reasons.push('Verified email status');}\n  if(c.seniority){reasons.push('Seniority: '+c.seniority);}\n  if(apolloIsNoisyLargeCompany(c)){score-=25;reasons.push('Large-company noise filter applied');}\n  score=Math.max(0,Math.min(100,score));\n  let tier=score>=85?'High':score>=65?'Medium':score>=45?'Low':'Very Low';\n  return {score,tier,reasons};\n}\nfunction apolloOwnerFit(c){\n  return apolloConfidence(c).score;\n}\nfunction apolloRankContacts(list){\n  return (list||[])\n    .filter(c=>c && (c.title||c.name||c.first_name||c.linkedin_url||c.organization_name))\n    .map(c=>({...c,_confidence:apolloConfidence(c)}))\n    .sort((a,b)=>(b._confidence.score-a._confidence.score) || (apolloTitleScore(b.title)-apolloTitleScore(a.title)));\n}\nfunction apolloSalesNavigatorHelp(){\n  const company=val('apolloCompany')||'Selected Company';\n  const location=val('apolloLocation')||'Company Location';\n  const titles=val('apolloTitles')||'Owner, Founder, President, CEO, Managing Partner, Principal';\n  return `<div class=\"notice\">\n    <b>No strong Apollo match?<\/b><br>\n    Use Sales Navigator Companion Search:<br><br>\n    <b>Company:<\/b> ${company}<br>\n    <b>Location:<\/b> ${location}<br>\n    <b>Titles:<\/b> ${titles}<br><br>\n    Recommended Sales Navigator search: <b>${company} ${location} owner founder president CEO<\/b><br><br>\n    <button class=\"secondary\" onclick=\"openSalesNavFromApollo()\">Open Sales Navigator Companion<\/button>\n  <\/div>`;\n}\nfunction apolloFillFromSelected(){\n  const x=p();\n  if(!x){alert('Select a prospect first, or type the company information manually.');return;}\n  $('apolloCompany').value=x.bizName||'';\n  $('apolloLocation').value=x.location||'';\n  const website=x.website||x.url||x.domain||x.organization_website_url||'';\n  if(website)$('apolloDomain').value=apolloExtractDomain(website);\n  renderApolloOwnerDiscovery();\n}\nfunction renderApolloOwnerDiscovery(){\n  const x=p();\n  if($('apolloSelected')){\n    $('apolloSelected').textContent=x?`${x.bizName}\\nIndustry: ${x.industry||'\u2014'}\\nLocation: ${x.location||'\u2014'}\\nWebsite\/Domain: ${x.website||x.domain||'\u2014'}\\nCurrent Owner Field: ${x.owner||'\u2014'}`:'Select a prospect first, or enter company information manually.';\n  }\n  if(x && !$('apolloCompany').value){apolloFillFromSelected();}\n}\nfunction apolloClearResults(){\n  apolloOwnerResults=[];apolloSelectedContact=null;\n  if($('apolloResults'))$('apolloResults').innerHTML='';\n  if($('apolloStatus'))$('apolloStatus').textContent='Run a search to find likely decision makers.';\n  if($('apolloSelectedContact'))$('apolloSelectedContact').textContent='No contact selected yet.';\n}\nfunction apolloContactSummary(c){\n  const conf=apolloConfidence(c);\n  return `${apolloDisplayName(c)}\\nTitle: ${c.title||'\u2014'}\\nCompany: ${c.organization_name||'\u2014'}\\nOwner Confidence: ${conf.score}\/100 (${conf.tier})\\nReason: ${conf.reasons.join('; ')}\\nLinkedIn: ${c.linkedin_url||'\u2014'}\\nEmail: ${c.email||'Not revealed'}\\nEmail Status: ${c.email_status||'\u2014'}\\nApollo ID: ${c.id||'\u2014'}`;\n}\nfunction apolloSelectContact(index){\n  apolloSelectedContact=apolloOwnerResults[index]||null;\n  if($('apolloSelectedContact'))$('apolloSelectedContact').textContent=apolloSelectedContact?apolloContactSummary(apolloSelectedContact):'No contact selected yet.';\n}\nfunction apolloSearchTips(data){\n  const parts=[];\n  if(data.organization_used&&data.organization_used.name)parts.push('Company matched in Apollo: '+data.organization_used.name+(data.organization_used.domain?' ('+data.organization_used.domain+')':''));\n  if(data.note)parts.push(data.note);\n  if(data.search_strategy)parts.push('Search strategy: '+data.search_strategy);\n  return parts.length?'\\n\\n'+parts.join('\\n'):'';\n}\nasync function apolloSearchOwners(){\n  try{\n    const endpoint=val('apolloEndpoint')||'\/wp-json\/brokers-pro-suite\/v1\/apollo\/owner-search';\n    const titles=(val('apolloTitles')||'owner, founder, president, ceo, chief executive officer, managing partner, principal').split(',').map(x=>x.trim()).filter(Boolean);\n    const payload={company_name:val('apolloCompany'),domain:apolloExtractDomain(val('apolloDomain')),location:val('apolloLocation'),titles};\n    $('apolloStatus').textContent='Searching Apollo for likely owners and decision makers...';\n    const headers=adsAiHeaders({'Content-Type':'application\/json'});\n    if(window.ADS_CLOUD_STORAGE&&window.ADS_CLOUD_STORAGE.nonce)headers['X-WP-Nonce']=window.ADS_CLOUD_STORAGE.nonce;\n    const res=await fetch(endpoint,{method:'POST',credentials:'same-origin',headers,body:JSON.stringify(payload)});\n    const data=await res.json().catch(()=>({}));\n    if(!res.ok)throw new Error(data.message||('HTTP '+res.status));\n    apolloOwnerResults=apolloRankContacts(Array.isArray(data.people)?data.people:[]);\n    apolloSelectedContact=null;\n    const strong=apolloOwnerResults.filter(c=>apolloConfidence(c).score>=70).length;\n    $('apolloStatus').textContent=`Apollo returned ${apolloOwnerResults.length} possible contact${apolloOwnerResults.length===1?'':'s'} (${strong} strong match${strong===1?'':'es'}).`+apolloSearchTips(data);\n    if(!apolloOwnerResults.length){$('apolloResults').innerHTML='<div class=\"empty-state\">No Apollo contacts found. Try adding the company website\/domain, simplifying the company name, removing location, or widening target titles.<\/div>'+apolloSalesNavigatorHelp();return;}\n    $('apolloResults').innerHTML=apolloOwnerResults.map((c,i)=>{\n      const conf=apolloConfidence(c), cls=apolloScoreClass(conf.score), name=apolloDisplayName(c);\n      const link=c.linkedin_url?`<a href=\"${c.linkedin_url}\" target=\"_blank\" rel=\"noopener\">Open LinkedIn Profile<\/a>`:'No LinkedIn URL returned.';\n      const reason=conf.reasons.slice(0,3).join(' \u00b7 ');\n      return `<div class=\"discovery-result\"><div><b>${name}<\/b><br><small>${c.title||'\u2014'} \u00b7 ${c.organization_name||'\u2014'}<\/small><div class=\"discovery-meta\"><span class=\"pill ${cls}\">Confidence ${conf.score}<\/span><span class=\"pill ${cls}\">${conf.tier}<\/span><span class=\"pill blue\">Apollo<\/span>${c.linkedin_url?'<span class=\"pill green\">LinkedIn Found<\/span>':''}${c.email_status?`<span class=\"pill amber\">${c.email_status}<\/span>`:''}${c.email?'<span class=\"pill green\">Email Found<\/span>':'<span class=\"pill amber\">Email Not Revealed<\/span>'}<\/div><p><strong>Reason:<\/strong> ${reason}<\/p><p>${link}<\/p><\/div><div class=\"discovery-actions\"><button class=\"secondary\" onclick=\"apolloSelectContact(${i})\">Select<\/button><\/div><\/div>`;\n    }).join('') + (strong?'' : apolloSalesNavigatorHelp());\n  }catch(err){\n    $('apolloStatus').textContent='Apollo search failed: '+err.message;\n  }\n}\nasync function apolloEnrichSelected(){\n  try{\n    if(!apolloSelectedContact){alert('Select a contact first.');return;}\n    const endpoint='\/wp-json\/brokers-pro-suite\/v1\/apollo\/enrich-contact';\n    const payload={...apolloSelectedContact,company_name:val('apolloCompany'),domain:apolloExtractDomain(val('apolloDomain'))};\n    $('apolloSelectedContact').textContent='Enriching selected contact through Apollo...';\n    const headers=adsAiHeaders({'Content-Type':'application\/json'});\n    if(window.ADS_CLOUD_STORAGE&&window.ADS_CLOUD_STORAGE.nonce)headers['X-WP-Nonce']=window.ADS_CLOUD_STORAGE.nonce;\n    const res=await fetch(endpoint,{method:'POST',credentials:'same-origin',headers,body:JSON.stringify(payload)});\n    const data=await res.json().catch(()=>({}));\n    if(!res.ok)throw new Error(data.message||('HTTP '+res.status));\n    if(data.person&&(data.person.name||data.person.first_name||data.person.linkedin_url||data.person.email_status)){apolloSelectedContact={...apolloSelectedContact,...data.person};}\n    $('apolloSelectedContact').textContent=apolloContactSummary(apolloSelectedContact)+(data.email_reveal_enabled?'':'\\n\\nNote: Email reveal is currently disabled in the WordPress snippet to protect Apollo credits.');\n  }catch(err){\n    $('apolloSelectedContact').textContent='Apollo enrichment failed: '+err.message;\n  }\n}\nfunction apolloSaveSelectedContact(){\n  const x=p();\n  if(!x){alert('Select or save a prospect first.');return;}\n  if(!apolloSelectedContact){alert('Select a contact first.');return;}\n  ensureArrays(x);\n  x.apolloContacts=x.apolloContacts||[];\n  const c={...apolloSelectedContact,name:apolloDisplayName(apolloSelectedContact),ownerFitScore:apolloOwnerFit(apolloSelectedContact),ownerConfidence:apolloConfidence(apolloSelectedContact),savedAt:new Date().toLocaleString()};\n  x.apolloContacts.unshift(c);\n  if(c.name && c.name!=='Contact name not returned'){x.owner=c.name;$('owner').value=c.name;}\n  if(c.email)x.ownerEmail=c.email;\n  if(c.linkedin_url)x.ownerLinkedIn=c.linkedin_url;\n  x.ownerTitle=c.title||x.ownerTitle||'';\n  x.history.unshift(hist('Apollo Owner Discovery',`Saved ${c.name||'contact'} (${c.title||'title not returned'}) from Apollo. Owner Confidence ${c.ownerFitScore}\/100.`));\n  x.nextAction=x.nextAction||'Prepare owner outreach';\n  persist();renderAll();\n  alert('Apollo contact saved to this prospect.');\n}\n\n\n\nfunction salesNavPreferredContact(x){\n  if(!x)return null;\n  const apollo=(x.apolloContacts&&x.apolloContacts[0])?x.apolloContacts[0]:null;\n  if(apollo)return {source:'Apollo',contact:apollo};\n  if(x.salesNavOwner)return {source:'Sales Navigator \/ Manual',contact:x.salesNavOwner};\n  if(x.owner)return {source:'Owner Field',contact:{name:x.owner,title:x.ownerTitle||'',email:x.ownerEmail||'',linkedin_url:x.ownerLinkedIn||''}};\n  return null;\n}\nfunction renderSalesNavMetrics(){\n  if(!$('snApolloOwners'))return;\n  const apollo=prospects.filter(x=>x.apolloContacts&&x.apolloContacts.length).length;\n  const manual=prospects.filter(x=>x.salesNavOwner).length;\n  const none=prospects.filter(x=>!salesNavPreferredContact(x)).length;\n  $('snApolloOwners').textContent=apollo;\n  $('snManualOwners').textContent=manual;\n  $('snNoOwner').textContent=none;\n}\nfunction salesNavDomainFromProspect(x){\n  if(!x)return '';\n  const raw=x.website||x.url||x.domain||x.organization_website_url||x.websiteUrl||'';\n  if(raw)return apolloExtractDomain(raw);\n  const ctx=(x.context||'');\n  const m=ctx.match(\/https?:\\\/\\\/[^\\s,;]+|www\\.[^\\s,;]+|[a-z0-9-]+\\.(com|net|org|co|biz|us)\\b\/i);\n  return m?apolloExtractDomain(m[0]):'';\n}\nfunction salesNavFillFromSelected(){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return;}\n  $('snCompany').value=x.bizName||'';\n  $('snLocation').value=x.location||'';\n  const d=salesNavDomainFromProspect(x);\n  if(d)$('snDomain').value=d;\n  renderSalesNavigatorCompanion();\n}\nfunction salesNavBuildSearch(){\n  const company=val('snCompany')||'Selected Company';\n  const location=val('snLocation')||'Selected Location';\n  const domain=apolloExtractDomain(val('snDomain'));\n  const titles=val('snTitles')||'Owner, Founder, President, CEO, Managing Partner, Principal';\n  const titleWords=titles.split(',').map(x=>x.trim()).filter(Boolean);\n  const broad=`${company} ${location} owner founder president CEO`;\n  const exactCompany=`\"${company}\" (owner OR founder OR president OR CEO OR principal OR \"managing partner\")`;\n  const webSearch=domain?`site:linkedin.com\/in ${company} ${domain} owner founder president`:`site:linkedin.com\/in ${company} ${location} owner founder president`;\n  return {company,location,domain,titles,titleWords,broad,exactCompany,webSearch};\n}\nfunction generateSalesNavigatorCompanion(){\n  const q=salesNavBuildSearch();\n  $('snSearchPlan').textContent=`Sales Navigator Companion Search Plan\n\nCompany:\n${q.company}\n\nLocation:\n${q.location}\n\nWebsite \/ Domain:\n${q.domain||'Not supplied'}\n\nTarget Titles:\n${q.titles}\n\nSuggested Sales Navigator Steps:\n1. Open Sales Navigator.\n2. Search people using the company name first.\n3. Add geography\/location filter: ${q.location}.\n4. Add current title keywords one at a time: Owner, Founder, President, CEO, Managing Partner, Principal.\n5. If the exact company does not appear, search LinkedIn or Google using the copy-ready searches below.\n6. Capture the best owner\/contact in the Manual Owner Capture form.`;\n  $('snGuidance').innerHTML=`<strong>Recommended fallback:<\/strong> Apollo did not provide a strong enough owner match, so use Sales Navigator to confirm the owner\/operator manually. Small local businesses often have better owner clues on LinkedIn, Google, company websites, or state business records than in Apollo.`;\n  $('snCopySearches').textContent=`Sales Navigator People Search:\n${q.broad}\n\nLinkedIn Boolean Search:\n${q.exactCompany}\n\nGoogle Search:\n${q.webSearch}\n\nAlternative Google Search:\n${q.company} ${q.location} owner president founder LinkedIn`;\n}\nfunction renderSalesNavigatorCompanion(){\n  if(!$('salesnavTab'))return;\n  const x=p();\n  $('snSelected').textContent=x?`${x.bizName}\nIndustry: ${x.industry||'\u2014'}\nLocation: ${x.location||'\u2014'}\nWebsite\/Domain: ${salesNavDomainFromProspect(x)||x.website||x.domain||'\u2014'}\nCurrent Owner: ${x.owner||'\u2014'}\nOwner Source: ${salesNavPreferredContact(x)?.source||'No owner captured yet'}`:'Select a prospect first.';\n  if(x && !$('snCompany').value)salesNavFillFromSelected();\n  renderSalesNavMetrics();\n}\nfunction openSalesNavFromApollo(){\n  const x=p();\n  if(x){\n    if($('snCompany'))$('snCompany').value=val('apolloCompany')||x.bizName||'';\n    if($('snLocation'))$('snLocation').value=val('apolloLocation')||x.location||'';\n    if($('snDomain'))$('snDomain').value=val('apolloDomain')||salesNavDomainFromProspect(x)||'';\n  }\n  showTab('salesnav',{target:document.querySelector('[onclick*=salesnav]')});\n  generateSalesNavigatorCompanion();\n}\nfunction saveSalesNavOwner(){\n  const x=p();\n  if(!x){alert('Select or save a prospect first.');return;}\n  const name=val('snOwnerName');\n  if(!name){alert('Enter the owner\/contact name first.');return;}\n  ensureArrays(x);\n  const owner={name,title:val('snOwnerTitle'),linkedin_url:val('snLinkedIn'),email:val('snEmail'),phone:val('snPhone'),source:'Sales Navigator \/ Manual',savedAt:new Date().toLocaleString()};\n  x.salesNavOwner=owner;\n  x.owner=name;\n  x.ownerTitle=owner.title;\n  if(owner.email)x.ownerEmail=owner.email;\n  if(owner.linkedin_url)x.ownerLinkedIn=owner.linkedin_url;\n  x.stage=(x.stage==='New Prospect'||x.stage==='Identified'||!x.stage)?'Owner Identified':x.stage;\n  x.history.unshift(hist('Sales Navigator Owner Capture',`Saved manual owner\/contact ${name}${owner.title?' ('+owner.title+')':''}.`));\n  x.nextAction=x.nextAction||'Generate owner outreach';\n  $('owner').value=x.owner;\n  $('stage').value=x.stage;\n  persist();renderAll();\n  alert('Manual owner\/contact saved to this prospect.');\n}\n\n\/* v2.8 Advanced Follow-Up Automation *\/\nfunction faDateOnly(d){const x=new Date(d);x.setHours(0,0,0,0);return x}\nfunction faISODateOffset(days){const d=new Date();d.setDate(d.getDate()+days);return d.toISOString().slice(0,10)}\nfunction ensureCadence(x){ensureFollowupFields(x);x.followupCadence=x.followupCadence||[];return x}\nfunction defaultCadenceSteps(startAction){\n  const start=(startAction||'Email').toLowerCase();\n  return [\n    {day:0,type:start==='phone call'?'Phone Call':'Initial Email',action:start==='phone call'?'Make first owner call':'Send initial owner outreach',offset:0},\n    {day:7,type:'Follow-Up #1',action:'Send follow-up #1 with value angle',offset:7},\n    {day:14,type:'Follow-Up #2',action:'Send follow-up #2 or LinkedIn touch',offset:14},\n    {day:30,type:'Phone Call',action:'Call owner \/ leave voicemail',offset:30},\n    {day:45,type:'Final Touch',action:'Send final soft-touch message or move to nurture',offset:45}\n  ];\n}\nfunction createDefaultCadenceForSelected(){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return}\n  ensureCadence(x);\n  const replace=!x.followupCadence.length || confirm('Replace existing follow-up cadence for this prospect?');\n  if(!replace)return;\n  x.followupCadence=defaultCadenceSteps(val('fuStartAction')||'Email').map(s=>({\n    id:'cad_'+Date.now()+'_'+Math.random().toString(16).slice(2),\n    day:s.day,type:s.type,action:s.action,dueDate:faISODateOffset(s.offset),status:'Open',createdAt:new Date().toLocaleString(),completedAt:''\n  }));\n  x.nextAction=x.followupCadence[0].action;\n  x.dueDate=x.followupCadence[0].dueDate;\n  x.stage=x.stage==='New Prospect'?'Outreach Generated':(x.stage||'Outreach Generated');\n  x.history.unshift(hist('Follow-Up Cadence Created','Created default 0\/7\/14\/30\/45-day follow-up cadence.'));\n  $('nextAction').value=x.nextAction;$('dueDate').value=x.dueDate;$('stage').value=x.stage;\n  persist();renderAll();alert('Default follow-up cadence created.');\n}\nfunction faCadenceStatus(step){\n  if(step.status==='Done')return 'done';\n  if(!step.dueDate)return '';\n  const diff=daysUntil(step.dueDate);\n  if(diff<0)return 'overdue';\n  if(diff===0)return 'due';\n  return '';\n}\nfunction completeCadenceStep(pid,stepId){\n  const x=prospects.find(a=>a.id===pid);if(!x)return;\n  ensureCadence(x);\n  const st=x.followupCadence.find(s=>s.id===stepId);if(!st)return;\n  st.status='Done';st.completedAt=new Date().toLocaleString();\n  ensureFollowupFields(x);\n  x.activities.unshift({date:new Date().toLocaleString(),type:st.type,note:st.action});\n  x.history.unshift(hist('Follow-Up Completed',st.type+': '+st.action));\n  const next=x.followupCadence.find(s=>s.status!=='Done');\n  if(next){x.nextAction=next.action;x.dueDate=next.dueDate;}\n  else{x.nextAction='Cadence complete \u2014 review outcome';x.dueDate='';}\n  persist();renderAll();\n}\nfunction faNextBestAction(x){\n  ensureCadence(x);\n  const read=typeof listingReadinessScore==='function'?listingReadinessScore(x).score:priorityScore(x);\n  const open=(x.followupCadence||[]).filter(s=>s.status!=='Done');\n  const due=open.find(s=>faCadenceStatus(s)==='overdue'||faCadenceStatus(s)==='due');\n  if(due)return due.action;\n  if(!x.owner && !(x.apolloContacts&&x.apolloContacts.length) && !x.salesNavOwner)return 'Find or capture owner contact';\n  if(!(x.outreach&&x.outreach.length) && !(x.history||[]).some(h=>(h.type||'').includes('Outreach')))return 'Generate outreach sequence';\n  if(read>=80)return 'Prioritize direct owner follow-up';\n  if(open[0])return open[0].action;\n  return x.nextAction||'Review and schedule next follow-up';\n}\nfunction faPriorityRows(){\n  const rows=[];\n  prospects.forEach(x=>{\n    ensureCadence(x);\n    const read=typeof listingReadinessScore==='function'?listingReadinessScore(x).score:priorityScore(x);\n    const open=(x.followupCadence||[]).filter(s=>s.status!=='Done');\n    let dueStep=open.find(s=>faCadenceStatus(s)==='overdue'||faCadenceStatus(s)==='due');\n    let urgency=priorityScore(x);\n    if(dueStep&&faCadenceStatus(dueStep)==='overdue')urgency+=30;\n    if(dueStep&&faCadenceStatus(dueStep)==='due')urgency+=20;\n    if(read>=80)urgency+=12;\n    if(!x.owner&&!x.salesNavOwner&&!(x.apolloContacts&&x.apolloContacts.length))urgency+=8;\n    rows.push({x,read,urgency:Math.min(100,urgency),dueStep,next:faNextBestAction(x)});\n  });\n  return rows.sort((a,b)=>b.urgency-a.urgency);\n}\nfunction renderFollowupAutomation(){\n  if(!$('faDueToday'))return;\n  let dueToday=0,overdue=0,completed=0,priority=0;\n  prospects.forEach(x=>{\n    ensureCadence(x);\n    const read=typeof listingReadinessScore==='function'?listingReadinessScore(x).score:priorityScore(x);\n    if(read>=80)priority++;\n    (x.followupCadence||[]).forEach(s=>{\n      if(s.status==='Done')completed++;\n      else if(faCadenceStatus(s)==='due')dueToday++;\n      else if(faCadenceStatus(s)==='overdue')overdue++;\n    });\n  });\n  $('faDueToday').textContent=dueToday;\n  $('faOverdue').textContent=overdue;\n  $('faPriority').textContent=priority;\n  $('faCompleted').textContent=completed;\n  if($('mOverdue28'))$('mOverdue28').textContent=overdue;\n  if($('mPriority28'))$('mPriority28').textContent=priority;\n  const rows=faPriorityRows().slice(0,10);\n  $('faPriorityQueue').innerHTML=rows.length?rows.map(r=>{\n    const st=r.dueStep?faCadenceStatus(r.dueStep):'';\n    const cls=st==='overdue'?'overdue':st==='due'?'today':r.read>=80?'priority':'';\n    return `<div class=\"automation28-row ${cls}\"><div><b>${r.x.bizName}<\/b><small>${r.x.stage||'Identified'} \u00b7 Readiness ${r.read}\/100 \u00b7 Priority ${r.urgency}<\/small><br>${r.next}${r.dueStep?`<br><small>Due: ${r.dueStep.dueDate} \u00b7 ${r.dueStep.type}<\/small>`:''}<\/div><div class=\"automation28-actions\"><button class=\"light\" onclick=\"selectProspect('${r.x.id}');showTab('followup',{target:document.querySelector('[onclick*=followup]')})\">Open<\/button>${r.dueStep?`<button class=\"secondary\" onclick=\"completeCadenceStep('${r.x.id}','${r.dueStep.id}')\">Mark Done<\/button>`:''}<\/div><\/div>`;\n  }).join(''):'<div class=\"empty-state\">No prospects in the follow-up queue yet.<\/div>';\n  renderSelectedCadence28();\n}\nfunction renderSelectedCadence28(){\n  if(!$('faSelectedCadence'))return;\n  const x=p();\n  if(!x){$('faSelectedCadence').innerHTML='Select a prospect to see its cadence.';return}\n  ensureCadence(x);\n  if(!x.followupCadence.length){$('faSelectedCadence').innerHTML='<div class=\"empty-state\">No cadence yet. Click Create Default Cadence.<\/div>';return}\n  $('faSelectedCadence').innerHTML=x.followupCadence.map(s=>{\n    const cls=faCadenceStatus(s);\n    return `<div class=\"cadence-step ${cls}\"><b>${s.type}<\/b><br><small>Due: ${s.dueDate} \u00b7 Status: ${s.status}<\/small><br>${s.action}<div class=\"automation28-actions\">${s.status!=='Done'?`<button class=\"secondary\" onclick=\"completeCadenceStep('${x.id}','${s.id}')\">Mark Done<\/button>`:''}<\/div><\/div>`;\n  }).join('');\n}\nfunction exportFollowupAutomationCSV(){\n  const headers=['Business','Stage','Owner','Readiness Score','Priority Score','Next Best Action','Cadence Step','Due Date','Status'];\n  const rows=[];\n  prospects.forEach(x=>{\n    ensureCadence(x);\n    const read=typeof listingReadinessScore==='function'?listingReadinessScore(x).score:priorityScore(x);\n    const base=[x.bizName,x.stage||'',x.owner||'',read,priorityScore(x),faNextBestAction(x)];\n    if(x.followupCadence&&x.followupCadence.length){x.followupCadence.forEach(s=>rows.push([...base,s.type,s.dueDate,s.status].map(escapeCSV).join(',')));}\n    else rows.push([...base,'No cadence','',''].map(escapeCSV).join(','));\n  });\n  const csv=[headers.map(escapeCSV).join(','),...rows].join('\\n');\n  const blob=new Blob([csv],{type:'text\/csv;charset=utf-8'});\n  const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='follow-up-automation-queue.csv';a.click();\n}\n\nfunction renderAll(){if(typeof updateLaunchDashboard==='function')updateLaunchDashboard();renderProspects();renderMetrics();renderCommandCenter();renderSelected();renderPipeline();updateReport();renderAnalytics();renderIntelligence();generateWorkflowTasks();renderSelectedWorkflow();renderConversion();runOpportunityScanner();renderSuccessionMetrics();renderBuyerMetrics();generateRollupIntel();renderMasterDashboard();renderPursuitMetrics();renderFollowupMetrics();renderMarketDomination();renderSalesNavMetrics();renderFollowupAutomation();}\n\nfunction showTab(t,e){if(typeof syncWorkflowActive==='function')syncWorkflowActive(t);document.querySelectorAll('.tab').forEach(x=>x.classList.remove('active'));if(e)e.target.classList.add('active');['dashboard','master','market','pursuit','followup','discovery','apollo','salesnav','scanner','sequence','succession','buyers','rollup','outreach','pipeline','coach','scorecard','assessment','report','analytics','intelligence','workflow','conversion','presentation','release','apiSetup'].forEach(k=>$(k+'Tab').classList.toggle('hide',k!==t));if(t==='report')updateReport();if(t==='analytics')renderAnalytics();if(t==='workflow'){generateWorkflowTasks();renderWorkflow();}if(t==='discovery'){renderDiscovery();}if(t==='apollo'){renderApolloOwnerDiscovery();}if(t==='salesnav'){renderSalesNavigatorCompanion();}if(t==='scanner'){runOpportunityScanner();}if(t==='sequence'){if(selectedId)generateSmartSequence();}if(t==='succession'){renderSuccessionMetrics();if(selectedId)generateSuccessionIntel();}if(t==='buyers'){renderBuyerMetrics();if(selectedId)generateBuyerMatches();}if(t==='rollup'){generateRollupIntel();}if(t==='master'){renderMasterDashboard();}if(t==='market'){renderMarketDomination();}if(t==='pursuit'){renderPursuitMetrics();if(selectedId)generatePursuitPlan();}if(t==='followup'){renderFollowupMetrics();if(selectedId)generateFollowupEngine();renderFollowupAutomation();}}\nfunction setLang(l,e){currentLang=l;document.querySelectorAll('.lang').forEach(x=>x.classList.remove('active'));if(e)e.target.classList.add('active');if(lastOutreach)generateOutreach(false);}\n\nfunction base(){let x=p()||{};return {name:x.bizName||val('bizName')||'the business',industry:x.industry||val('industry')||'your industry',loc:x.location||val('location')||'your area',owner:x.owner||val('owner')||'Business Owner',years:x.years||val('years')||'many',ctx:x.context||val('context')||'potential transition planning'}}\nfunction phrase(en,pt,es){return currentLang==='pt'?pt:currentLang==='es'?es:en}\nfunction generateOutreach(show=true){let b=base();let intro=phrase(`I noticed ${b.name} has been serving ${b.loc} in the ${b.industry} space for ${b.years} years. I help business owners quietly understand exit options before they ever decide to sell.`,`${b.name} atua em ${b.loc} no setor de ${b.industry} h\u00e1 ${b.years} anos. Eu ajudo empres\u00e1rios a entender op\u00e7\u00f5es de sa\u00edda de forma confidencial antes de decidir vender.`,`Vi que ${b.name} opera en ${b.loc} en el sector de ${b.industry} desde hace ${b.years} a\u00f1os. Ayudo a empresarios a entender opciones de salida de forma confidencial antes de decidir vender.`);\n$('email1').textContent=`Subject: A confidential question about ${b.name}\\n\\n${intro}\\n\\nWould you be open to a brief conversation about what businesses like yours are currently worth and how owners prepare for a future transition?`;\n$('email2').textContent=`Subject: Exit planning for ${b.industry} owners\\n\\n${phrase('Many owners wait too long to prepare for a sale. A short valuation conversation can uncover timing, buyer demand, and value improvement opportunities.','Muitos empres\u00e1rios esperam demais para se preparar para uma venda. Uma conversa r\u00e1pida pode revelar valor, demanda de compradores e oportunidades de melhoria.','Muchos due\u00f1os esperan demasiado para prepararse para una venta. Una conversaci\u00f3n breve puede revelar valor, demanda de compradores y oportunidades de mejora.')}\\n\\n${phrase('Would next week be a bad time to compare notes?','A pr\u00f3xima semana seria um mau momento para conversarmos?','\u00bfLa pr\u00f3xima semana ser\u00eda un mal momento para conversar?')}`;\n$('email3').textContent=`Subject: Quick introduction\\n\\n${phrase('I work with local business owners who are thinking through retirement, succession, or future exit planning.','Trabalho com empres\u00e1rios locais que est\u00e3o pensando em aposentadoria, sucess\u00e3o ou planejamento de sa\u00edda.','Trabajo con empresarios locales que est\u00e1n evaluando jubilaci\u00f3n, sucesi\u00f3n o planificaci\u00f3n de salida.')}\\n\\n${phrase('If this is relevant, I can share a confidential market perspective.','Se isso for relevante, posso compartilhar uma perspectiva de mercado confidencial.','Si esto es relevante, puedo compartir una perspectiva confidencial del mercado.')}`;\n$('linkedin1').textContent=`${phrase('I help business owners plan confidential exits and understand market value. Thought it may be useful to connect.','Ajudo empres\u00e1rios a planejar sa\u00eddas confidenciais e entender valor de mercado. Achei que seria \u00fatil conectar.','Ayudo a due\u00f1os de negocios a planificar salidas confidenciales y entender valor de mercado. Pens\u00e9 que ser\u00eda \u00fatil conectar.')}`.slice(0,300);\n$('linkedin2').textContent=`${phrase('Thanks for connecting. I work with owners who want to understand business value, buyer demand, and exit timing before making any public decision. Happy to be a resource if useful.','Obrigado por conectar. Trabalho com empres\u00e1rios que querem entender valor, demanda de compradores e momento de sa\u00edda antes de qualquer decis\u00e3o p\u00fablica. Fico \u00e0 disposi\u00e7\u00e3o.','Gracias por conectar. Trabajo con due\u00f1os que quieren entender valor, demanda de compradores y tiempo de salida antes de tomar una decisi\u00f3n p\u00fablica. Con gusto puedo ser un recurso.')}`;\n$('letter').textContent=`Dear ${b.owner},\\n\\n${intro}\\n\\nA confidential exit-readiness conversation can help identify value drivers, potential buyer interest, and steps that may increase saleability over time.\\n\\nRespectfully,\\n[Broker Name]`;\n$('sequence').textContent=`1. Initial introduction\\n2. Value\/market perspective follow-up after 5\u20137 days\\n3. Educational exit planning message after 2 weeks\\n4. Final soft close offering a confidential readiness review after 3\u20134 weeks`;\nlastOutreach={date:new Date().toLocaleString(),lang:currentLang,email1:$('email1').textContent,email2:$('email2').textContent,email3:$('email3').textContent,linkedin1:$('linkedin1').textContent,linkedin2:$('linkedin2').textContent,letter:$('letter').textContent,sequence:$('sequence').textContent};\n}\nfunction saveOutreach(){let x=p();if(!x){saveProspect();x=p()}if(!lastOutreach)generateOutreach();ensureArrays(x);x.outreach.unshift(lastOutreach);x.history.unshift(hist('Outreach Generated','Generated outreach package in '+currentLang+'.'));persist();renderAll();alert('Outreach saved.');}\n\nfunction generateCoach(){let b=base();$('callScript').textContent=`Opening: ${b.owner}, I appreciate your time. My goal is not to pressure you into selling, but to help you understand what a future transition could look like for ${b.name}.\\n\\nBridge: Owners in ${b.industry} often start with questions around value, timing, employees, confidentiality, and what buyers actually look for.\\n\\nClose: Would it be useful if I prepared a confidential exit-readiness snapshot for you?`;\n$('objections').textContent=`1. \"I'm not ready to sell.\" \u2014 Completely understandable. Many owners start planning 1\u20133 years before a sale.\\n2. \"I don't know what it's worth.\" \u2014 That's exactly where a confidential valuation discussion helps.\\n3. \"I don't want employees to know.\" \u2014 Confidentiality is central to the process.\\n4. \"The business depends on me.\" \u2014 We can identify steps to reduce owner dependency.\\n5. \"I need a certain price.\" \u2014 We can compare that expectation with current buyer demand.`;\n$('qualQuestions').textContent=`1. What prompted you to start thinking about the future of the business?\\n2. How involved are you in daily operations?\\n3. Who manages the business when you are away?\\n4. What timeline would feel ideal for a transition?\\n5. What would make a sale successful for you personally?`;\n$('postEmail').textContent=`Subject: Good speaking with you\\n\\nThank you for the conversation about ${b.name}. Based on what we discussed, the next helpful step would be a confidential readiness review covering value drivers, buyer concerns, and preparation steps.\\n\\nBest,\\n[Broker Name]`;\nlastCoach={date:new Date().toLocaleString(),script:$('callScript').textContent,objections:$('objections').textContent,questions:$('qualQuestions').textContent,email:$('postEmail').textContent};\n}\nfunction saveCoach(){let x=p();if(!x){saveProspect();x=p()}if(!lastCoach)generateCoach();ensureArrays(x);x.coach.unshift(lastCoach);x.history.unshift(hist('Conversation Coach','Generated seller conversation prep.'));persist();renderAll();alert('Coach output saved.');}\n\nfunction calculateOpportunity(){let m=+val('motivation'),q=+val('quality'),d=+val('dealpot');let score=Math.round(m*.35+q*.3+d*.35);let cat=score>=80?'Very High':score>=65?'High':score>=45?'Medium':'Low';let approach=score>=80?'Immediate Outreach':score>=65?'Priority Follow-Up':score>=45?'Educational Nurture':'Long-Term Pipeline';let angle=score>=65?'Lead with confidential valuation, succession planning, and buyer demand.':'Lead with education, preparation steps, and long-term exit planning.';$('oppResults').classList.remove('hide');$('oppScore').textContent=score;$('oppCat').textContent=cat+' Opportunity';$('oppApproach').textContent='Recommended approach: '+approach;$('oppAngle').textContent=angle;lastOpp={date:new Date().toLocaleString(),score,category:cat,approach,angle};}\nfunction saveOpportunity(){let x=p();if(!x){saveProspect();x=p()}if(!lastOpp)calculateOpportunity();ensureArrays(x);x.opportunities.unshift(lastOpp);x.history.unshift(hist('Opportunity Scorecard',`Score ${lastOpp.score}\/100 \u2014 ${lastOpp.category}.`));persist();renderAll();alert('Opportunity scorecard saved.');}\n\nfunction renderQs(){for(const s in questions){let box=$(s+'Qs');box.innerHTML='';questions[s].forEach(q=>{box.innerHTML+=`<div class=\"q\"><div><p>${q[1]}<\/p><small>${q[2]}<\/small><\/div><select id=\"${q[0]}\" data-sec=\"${s}\"><option value=\"1\">1 - Weak<\/option><option value=\"2\">2 - Below Average<\/option><option value=\"3\" selected>3 - Fair<\/option><option value=\"4\">4 - Good<\/option><option value=\"5\">5 - Strong<\/option><\/select><\/div>`})}}\nfunction sectionScore(s){let ids=questions[s].map(q=>q[0]);return Math.round(ids.reduce((a,id)=>a+(+$(id).value),0)\/(ids.length*5)*100)}\nfunction calculateAssessment(){let scores={financial:sectionScore('financial'),operational:sectionScore('operational'),market:sectionScore('market'),personal:sectionScore('personal')};let score=Math.round(scores.financial*.28+scores.operational*.28+scores.market*.22+scores.personal*.22);let cat=score>=82?'Premium Exit Candidate':score>=68?'Market Ready':score>=48?'Developing':'Needs Preparation';let timeline=score>=82?'Immediate to 6 months':score>=68?'6\u201312 months':score>=48?'1\u20132 years':'2+ years';$('assessmentResults').classList.remove('hide');$('exitScore').textContent=score;$('exitCat').textContent=cat;$('exitTimeline').textContent='Estimated sale timeline: '+timeline;$('financialScore').textContent=scores.financial;$('operationalScore').textContent=scores.operational;$('marketScore').textContent=scores.market;$('personalScore').textContent=scores.personal;let name=base().name;$('assessmentSummary').textContent=`${name} currently scores ${score}\/100 and falls into the \"${cat}\" category. This suggests the broker should position the conversation around ${score>=68?'valuation, buyer readiness, and timing':'preparation, value improvement, and future exit planning'}.` ;let recs=[];if(scores.financial<70)recs.push('Improve financial reporting, tax return organization, and add-back documentation.');if(scores.operational<70)recs.push('Reduce owner dependency, document SOPs, and strengthen management coverage.');if(scores.market<70)recs.push('Clarify competitive advantage, reduce customer concentration, and strengthen recurring revenue.');if(scores.personal<70)recs.push('Align owner timeline, price expectations, transition willingness, and decision makers.');if(!recs.length)recs.push('Prepare valuation package, begin confidential buyer-readiness discussion, and consider listing timing.');$('assessmentRecs').textContent=recs.join('\\n\\n');lastAssessment={date:new Date().toLocaleString(),score,category:cat,timeline,scores,summary:$('assessmentSummary').textContent,recs:$('assessmentRecs').textContent};}\nfunction saveAssessment(){let x=p();if(!x){saveProspect();x=p()}if(!lastAssessment)calculateAssessment();ensureArrays(x);x.assessments.unshift(lastAssessment);x.history.unshift(hist('Exit Readiness Assessment',`Score ${lastAssessment.score}\/100 \u2014 ${lastAssessment.category}.`));persist();renderAll();alert('Exit readiness assessment saved.');}\n\n\nfunction avg(nums){\n  const valid=nums.filter(n=>typeof n==='number'&&!isNaN(n));\n  return valid.length?Math.round(valid.reduce((a,b)=>a+b,0)\/valid.length):0;\n}\nfunction countBy(items,fn){\n  const o={};\n  items.forEach(x=>{const k=fn(x)||'Not Set';o[k]=(o[k]||0)+1});\n  return o;\n}\nfunction renderBars(targetId,data,total){\n  const box=$(targetId); if(!box)return;\n  const entries=Object.entries(data).sort((a,b)=>b[1]-a[1]);\n  if(!entries.length){box.innerHTML='<div class=\"empty-state\">No data yet.<\/div>';return}\n  box.innerHTML=entries.map(([label,count])=>{\n    const pct=total?Math.round(count\/total*100):0;\n    return `<div class=\"bar-row\"><div>${label}<\/div><div class=\"bar-track\"><div class=\"bar-fill\" style=\"width:${pct}%\"><\/div><\/div><div>${count}<\/div><\/div>`;\n  }).join('');\n}\nfunction renderAnalytics(){\n  if(!$('analyticsTab'))return;\n  const total=prospects.length;\n  const priorities=prospects.map(x=>priorityScore(x));\n  const oppScores=prospects.map(x=>x.opportunities?.[0]?.score).filter(Boolean);\n  const exitScores=prospects.map(x=>x.assessments?.[0]?.score).filter(Boolean);\n  const overdue=prospects.filter(x=>x.dueDate && isDue(x.dueDate)).length;\n  const hot=prospects.filter(x=>priorityScore(x)>=70).length;\n\n  $('aPriority').textContent=avg(priorities);\n  $('aOpp').textContent=avg(oppScores);\n  $('aExit').textContent=avg(exitScores);\n  $('aOverdue').textContent=overdue;\n\n  const stageData=countBy(prospects,x=>x.stage||'Identified');\n  const industryData=countBy(prospects,x=>x.industry||'Not Set');\n  const activityData={\n    'Outreach':prospects.reduce((a,x)=>a+(x.outreach?.length||0),0),\n    'Coach':prospects.reduce((a,x)=>a+(x.coach?.length||0),0),\n    'Opportunity Scores':prospects.reduce((a,x)=>a+(x.opportunities?.length||0),0),\n    'Exit Assessments':prospects.reduce((a,x)=>a+(x.assessments?.length||0),0),\n    'Notes\/History':prospects.reduce((a,x)=>a+(x.history?.length||0),0)\n  };\n  renderBars('stageChart',stageData,total);\n  renderBars('industryChart',industryData,total);\n  renderBars('activityChart',activityData,Object.values(activityData).reduce((a,b)=>a+b,0));\n\n  const top=sortedByPriority().slice(0,10);\n  $('topOpportunityTable').innerHTML=top.length?`<table class=\"report-table\"><thead><tr><th>Rank<\/th><th>Business<\/th><th>Stage<\/th><th>Priority<\/th><th>Opp<\/th><th>Exit<\/th><th>Next Action<\/th><\/tr><\/thead><tbody>${top.map((r,i)=>{\n    const x=r.p;\n    return `<tr><td>${i+1}<\/td><td>${x.bizName}<\/td><td>${x.stage||'Identified'}<\/td><td>${r.score}<\/td><td>${x.opportunities?.[0]?.score||'\u2014'}<\/td><td>${x.assessments?.[0]?.score||'\u2014'}<\/td><td>${x.nextAction||'\u2014'}<\/td><\/tr>`;\n  }).join('')}<\/tbody><\/table>`:'<div class=\"empty-state\">No prospects yet.<\/div>';\n\n  let narrative='No prospect data yet. Load demo data or create records to generate analytics.';\n  if(total){\n    narrative=`Current pipeline includes ${total} prospect${total===1?'':'s'}, with ${hot} hot prospect${hot===1?'':'s'} scoring 70+ priority and ${overdue} overdue or due follow-up${overdue===1?'':'s'}. Average priority score is ${avg(priorities)}\/100.`;\n    if(avg(oppScores)) narrative += ` Average opportunity score is ${avg(oppScores)}\/100.`;\n    if(avg(exitScores)) narrative += ` Average exit readiness score is ${avg(exitScores)}\/100.`;\n  }\n  $('analyticsNarrative').textContent=narrative;\n  $('brokerActivityReport').textContent=`Broker Activity Snapshot\nTotal Prospects: ${total}\nHot Prospects: ${hot}\nFollow-Ups Due\/Overdue: ${overdue}\nAverage Priority Score: ${avg(priorities)}\/100\nAverage Opportunity Score: ${avg(oppScores)}\/100\nAverage Exit Readiness Score: ${avg(exitScores)}\/100\nOutreach Packages Generated: ${activityData['Outreach']}\nConversation Coach Outputs: ${activityData['Coach']}\nOpportunity Scorecards: ${activityData['Opportunity Scores']}\nExit Readiness Assessments: ${activityData['Exit Assessments']}\n\nRecommended Management Focus:\n${overdue>0?'- Clear overdue follow-ups first.':'- No overdue follow-ups currently.'}\n${hot>0?'- Prioritize hot prospects with 70+ priority scores.':'- Build opportunity and exit readiness scoring for more prospects.'}\n${avg(exitScores)<60?'- Improve readiness work by using the Exit Assessment module more consistently.':'- Maintain readiness reviews and move qualified prospects toward seller conversations.'}`;\n}\nfunction exportAnalyticsCSV(){\n  const headers=['Business','Industry','Location','Stage','Priority Score','Opportunity Score','Exit Readiness Score','Next Action','Due Date','Outreach Count','Coach Count','History Count'];\n  const rows=prospects.map(x=>[\n    x.bizName,x.industry,x.location,x.stage,priorityScore(x),x.opportunities?.[0]?.score||'',x.assessments?.[0]?.score||'',x.nextAction,x.dueDate,x.outreach?.length||0,x.coach?.length||0,x.history?.length||0\n  ].map(escapeCSV).join(','));\n  const csv=[headers.map(escapeCSV).join(','),...rows].join('\\n');\n  const blob=new Blob([csv],{type:'text\/csv;charset=utf-8'});\n  const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='ai-deal-sourcing-analytics.csv';a.click();\n}\n\n\n\n\n\n\n\n\n\nlet rollupIntel=null;\nlet selectedRollupKey=null;\n\nfunction normClusterText(v){\n  return (v||'Not Set').toString().trim() || 'Not Set';\n}\nfunction rollupKeyFor(x,mode){\n  const industry=normClusterText(x.industry);\n  const location=normClusterText(x.location);\n  if(mode==='location')return location;\n  if(mode==='industryLocation')return industry+' \u00b7 '+location;\n  return industry;\n}\nfunction rollupAnalyzeCluster(key,items){\n  const scans=items.map(x=>typeof scanProspect==='function'?scanProspect(x):{score:50,type:'General Prospect',grade:'C'});\n  const buyerRows=items.map(x=>typeof buyerMatchAnalyze==='function'?buyerMatchAnalyze(x):null).filter(Boolean);\n  const avgScan=Math.round(scans.reduce((a,b)=>a+b.score,0)\/Math.max(1,scans.length));\n  const avgPriority=Math.round(items.reduce((a,x)=>a+(typeof priorityScore==='function'?priorityScore(x):50),0)\/Math.max(1,items.length));\n  const strong=items.filter((x,i)=>(scans[i]?.score||0)>=70).length;\n  const platform=items.filter((x,i)=>(scans[i]?.score||0)>=80 || (x.employees&&parseInt(x.employees,10)>=20)).length;\n  let score=Math.min(100,Math.round(avgScan*.45 + avgPriority*.35 + Math.min(items.length*8,20)));\n  if(strong>=2)score+=6;\n  if(platform>=1)score+=6;\n  score=Math.min(100,score);\n\n  let thesis='Potential add-on acquisition cluster';\n  if(platform>=1 && items.length>=3)thesis='Platform plus add-on roll-up opportunity';\n  else if(items.length>=5)thesis='Market consolidation opportunity';\n  else if(strong>=2)thesis='Strong add-on acquisition cluster';\n\n  const buyerType=buyerRows[0]?.top?.type||'Strategic Buyer';\n  const risks=[];\n  if(items.length<3)risks.push('Small cluster; more sourcing recommended.');\n  if(strong<2)risks.push('Limited number of high-probability seller candidates.');\n  if(platform<1)risks.push('No clear platform candidate identified yet.');\n  if(!risks.length)risks.push('No major roll-up gaps from current prospect data.');\n\n  const drivers=[];\n  drivers.push(`${items.length} prospects in cluster`);\n  if(strong)drivers.push(`${strong} strong seller opportunities`);\n  if(platform)drivers.push(`${platform} possible platform candidate(s)`);\n  drivers.push(`Likely buyer type: ${buyerType}`);\n\n  return {key,items,score,avgScan,avgPriority,strong,platform,thesis,buyerType,drivers,risks};\n}\nfunction generateRollupIntel(){\n  const mode=val('rollupClusterBy')||'industry';\n  const min=parseInt(val('rollupMin')||'2',10);\n  const groups={};\n  prospects.forEach(x=>{\n    const k=rollupKeyFor(x,mode);\n    if(!groups[k])groups[k]=[];\n    groups[k].push(x);\n  });\n  const clusters=Object.entries(groups)\n    .filter(([k,items])=>items.length>=min)\n    .map(([k,items])=>rollupAnalyzeCluster(k,items))\n    .sort((a,b)=>b.score-a.score);\n  rollupIntel={date:new Date().toLocaleString(),mode,min,clusters};\n  selectedRollupKey=clusters[0]?.key||null;\n  renderRollupIntel();\n}\nfunction renderRollupIntel(){\n  if(!$('rollupTab'))return;\n  if(!rollupIntel)generateRollupIntel();\n  const clusters=rollupIntel?.clusters||[];\n  $('ruClusters').textContent=clusters.length;\n  $('ruStrong').textContent=clusters.reduce((a,c)=>a+c.strong,0);\n  $('ruPlatform').textContent=clusters.reduce((a,c)=>a+c.platform,0);\n  $('ruAvg').textContent=clusters.length?Math.round(clusters.reduce((a,c)=>a+c.score,0)\/clusters.length):0;\n  const box=$('rollupClusters');\n  if(!clusters.length){box.innerHTML='<div class=\"empty-state\">No roll-up clusters yet. Source or add more prospects in the same industry or geography.<\/div>';$('rollupMemo').textContent='Add more prospects to identify roll-up opportunities.';return}\n  box.innerHTML=clusters.map(c=>`<div class=\"cluster-card\" onclick=\"selectRollupCluster('${c.key.replace(\/'\/g,\"\\\\'\")}')\">\n    <div class=\"cluster-score\">${c.score}<\/div>\n    <b>${c.key}<\/b><br>\n    <span class=\"rollup-pill hot\">${c.thesis}<\/span>\n    <span class=\"rollup-pill blue\">${c.items.length} prospects<\/span>\n    <span class=\"rollup-pill\">${c.strong} strong<\/span>\n    <span class=\"rollup-pill\">${c.platform} platform<\/span>\n    <p><strong>Likely Buyer:<\/strong> ${c.buyerType}<\/p>\n  <\/div>`).join('');\n  selectRollupCluster(selectedRollupKey||clusters[0].key);\n}\nfunction selectRollupCluster(key){\n  selectedRollupKey=key;\n  const c=(rollupIntel?.clusters||[]).find(x=>x.key===key);\n  if(!c)return;\n  $('rollupSelected').textContent=`${c.key}\nCluster Score: ${c.score}\/100\nThesis: ${c.thesis}\nProspects: ${c.items.length}\nStrong Opportunities: ${c.strong}\nPlatform Candidates: ${c.platform}\nLikely Buyer Type: ${c.buyerType}`;\n\n  $('rollupMemo').textContent=`Acquisition Roll-Up Strategy Memo\n\nCluster:\n${c.key}\n\nRoll-Up Thesis:\n${c.thesis}\n\nCluster Score:\n${c.score}\/100\n\nProspects in Cluster:\n${c.items.map(x=>'- '+x.bizName+' ('+(x.stage||'Identified')+')').join('\\n')}\n\nValue Drivers:\n${c.drivers.map(d=>'- '+d).join('\\n')}\n\nRisks \/ Gaps:\n${c.risks.map(r=>'- '+r).join('\\n')}\n\nRecommended Broker Strategy:\n${c.thesis.includes('Platform')?'Identify the strongest platform candidate first, then position smaller businesses as add-ons.':c.thesis.includes('consolidation')?'Build a market map and approach owners with a consolidation\/buyer-demand thesis.':'Use the cluster as proof of buyer demand and create targeted outreach around acquisition interest.'}\n\nNext Actions:\n1. Research owners and websites for each company in this cluster.\n2. Run Opportunity Scanner on each prospect.\n3. Generate tailored outreach for the top 3 candidates.\n4. Prepare buyer positioning notes for likely acquirers.\n5. Track responses in pipeline.`;\n}\nfunction saveRollupIntel(){\n  if(!selectedRollupKey||!rollupIntel){alert('Generate and select a cluster first.');return}\n  const c=rollupIntel.clusters.find(x=>x.key===selectedRollupKey);\n  if(!c)return;\n  c.items.forEach(x=>{\n    ensureArrays(x);\n    x.history.unshift(hist('Roll-Up Intelligence',`${c.thesis} \u00b7 Cluster ${c.key} \u00b7 Score ${c.score}\/100.`));\n  });\n  persist();renderAll();\n  alert('Roll-up insight saved to all prospects in selected cluster.');\n}\nfunction exportRollupIntel(){\n  if(!rollupIntel)generateRollupIntel();\n  const clusters=rollupIntel?.clusters||[];\n  const text=`Deal Origination Report\n\nGenerated: ${new Date().toLocaleString()}\n\n${clusters.map(c=>`CLUSTER: ${c.key}\nScore: ${c.score}\/100\nThesis: ${c.thesis}\nLikely Buyer: ${c.buyerType}\nProspects:\n${c.items.map(x=>'- '+x.bizName).join('\\n')}\nDrivers:\n${c.drivers.map(d=>'- '+d).join('\\n')}\nRisks:\n${c.risks.map(r=>'- '+r).join('\\n')}`).join('\\n\\n---\\n\\n')}`;\n  const blob=new Blob([text],{type:'text\/plain;charset=utf-8'});\n  const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='acquisition-rollup-intelligence.txt';a.click();\n}\n\nlet buyerMatchIntel=null;\n\nfunction buyerMatchAnalyze(x){\n  ensureArrays(x);\n  const scan=typeof scanProspect==='function'?scanProspect(x):{score:50,type:'General Prospect',grade:'C',probability:'Medium'};\n  const industry=(x.industry||'').toLowerCase();\n  const location=x.location||'';\n  const employees=parseInt(x.employees||0,10)||0;\n  const opp=x.opportunities?.[0]?.score||0;\n  const exit=x.assessments?.[0]?.score||0;\n  const priority=typeof priorityScore==='function'?priorityScore(x):50;\n\n  const service=['hvac','plumbing','electrical','roofing','landscaping','pest','pool','cleaning','auto repair'].some(k=>industry.includes(k));\n  const food=['restaurant','cafe','bar','bakery','food'].some(k=>industry.includes(k));\n  const professional=['accounting','legal','insurance','agency','marketing','consulting'].some(k=>industry.includes(k));\n\n  const matches=[];\n  let strategic=55, ownerop=55, search=50, pe=35;\n\n  if(service){strategic+=20; search+=15; pe+=10}\n  if(food){ownerop+=20; strategic+=5}\n  if(professional){strategic+=15; search+=15}\n  if(employees>=5&&employees<=30){ownerop+=15; search+=12}\n  if(employees>=20&&employees<=75){strategic+=15; pe+=20}\n  if(scan.score>=80){strategic+=10; search+=10; pe+=8}\n  if(opp>=70){strategic+=8; search+=8; pe+=8}\n  if(exit>=70){ownerop+=8; search+=8}\n  if(priority>=75){strategic+=8; search+=8}\n\n  matches.push({type:'Strategic Buyer',score:Math.min(100,strategic),fit:'Existing company seeking expansion, territory growth, customer base, or add-on acquisition.',approach:'Position the business as a platform or add-on acquisition with local reputation and customer relationships.'});\n  matches.push({type:'Owner Operator',score:Math.min(100,ownerop),fit:'Individual buyer seeking an established local business to operate directly.',approach:'Emphasize cash flow stability, training, seller transition support, and operational simplicity.'});\n  matches.push({type:'Search Fund \/ Independent Sponsor',score:Math.min(100,search),fit:'Acquisition entrepreneur looking for a durable, locally defensible business.',approach:'Emphasize recurring demand, defensible niche, management handoff, and growth runway.'});\n  matches.push({type:'Private Equity \/ Family Office',score:Math.min(100,pe),fit:'Institutional buyer or family office seeking scalable platform or add-on opportunity.',approach:'Emphasize systems, management depth, EBITDA potential, and consolidation strategy.'});\n\n  matches.sort((a,b)=>b.score-a.score);\n\n  const top=matches[0];\n  const memo=`Buyer Match Summary for ${x.bizName}\n\nBest Buyer Type:\n${top.type} (${top.score}\/100 fit)\n\nWhy:\n${top.fit}\n\nRecommended Positioning:\n${top.approach}\n\nIndustry:\n${x.industry||'\u2014'}\n\nLocation:\n${location||'\u2014'}\n\nSeller Opportunity Context:\n${scan.type} \u00b7 ${scan.grade} \u00b7 ${scan.probability} seller probability\n\nSuggested Broker Action:\n${top.type==='Strategic Buyer'?'Research regional competitors and adjacent operators that may want territory or customer expansion.':top.type==='Owner Operator'?'Prepare owner-operator friendly summary emphasizing training, transition, and cash-flow story.':top.type==='Search Fund \/ Independent Sponsor'?'Frame the opportunity around durable demand, transitionability, and growth runway.':'Confirm financial quality and management depth before positioning to institutional buyers.'}`;\n\n  return {matches,memo,top,scan};\n}\n\nfunction generateBuyerMatches(){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return}\n  buyerMatchIntel={date:new Date().toLocaleString(),business:x.bizName,...buyerMatchAnalyze(x)};\n  $('buyerSelected').textContent=`${x.bizName}\nIndustry: ${x.industry||'\u2014'}\nLocation: ${x.location||'\u2014'}\nEmployees: ${x.employees||'\u2014'}\nPipeline Stage: ${x.stage||'Identified'}`;\n\n  $('buyerMatches').innerHTML=buyerMatchIntel.matches.map(m=>`<div class=\"match-card\">\n<div class=\"match-score\">${m.score}<\/div>\n<b>${m.type}<\/b><br>\n<span class=\"match-pill ${m.score>=75?'hot':'blue'}\">${m.score>=75?'Strong Fit':'Possible Fit'}<\/span>\n<p><strong>Fit:<\/strong> ${m.fit}<\/p>\n<p><strong>Positioning:<\/strong> ${m.approach}<\/p>\n<\/div>`).join('');\n\n  $('buyerMemo').textContent=buyerMatchIntel.memo;\n  renderBuyerMetrics();\n}\nfunction renderBuyerMetrics(){\n  if(!$('bmStrategic'))return;\n  const rows=prospects.map(buyerMatchAnalyze);\n  $('bmStrategic').textContent=rows.filter(r=>r.top.type==='Strategic Buyer').length;\n  $('bmOwnerOps').textContent=rows.filter(r=>r.top.type==='Owner Operator').length;\n  $('bmSearch').textContent=rows.filter(r=>r.top.type==='Search Fund \/ Independent Sponsor').length;\n  $('bmPE').textContent=rows.filter(r=>r.top.type==='Private Equity \/ Family Office').length;\n}\nfunction saveBuyerMatch(){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return}\n  if(!buyerMatchIntel)generateBuyerMatches();\n  ensureArrays(x);\n  x.history.unshift(hist('Buyer Match Engine',`Best buyer type: ${buyerMatchIntel.top.type} (${buyerMatchIntel.top.score}\/100 fit).`));\n  x.nextAction=`Research ${buyerMatchIntel.top.type} targets`;\n  $('nextAction').value=x.nextAction;\n  persist();renderAll();\n  alert('Buyer match insight saved.');\n}\nfunction exportBuyerMatch(){\n  if(!buyerMatchIntel)generateBuyerMatches();\n  if(!buyerMatchIntel)return;\n  const text=`Deal Origination\nBusiness: ${buyerMatchIntel.business}\n\n${buyerMatchIntel.memo}\n\nBuyer Type Rankings:\n${buyerMatchIntel.matches.map(m=>`${m.type}: ${m.score}\/100\nFit: ${m.fit}\nPositioning: ${m.approach}`).join('\\n\\n')}`;\n  const blob=new Blob([text],{type:'text\/plain;charset=utf-8'});\n  const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='buyer-match-intelligence.txt';a.click();\n}\n\nlet successionIntel=null;\n\nfunction successionAnalyze(x){\n  ensureArrays(x);\n  const scan=typeof scanProspect==='function'?scanProspect(x):{score:50,type:'General Prospect',grade:'C',probability:'Medium',approach:'Educational Exit Planning Conversation'};\n  const ctx=(x.context||'').toLowerCase();\n  const industry=(x.industry||'').toLowerCase();\n  const years=parseInt(x.years||0,10)||0;\n  const exitScore=x.assessments?.[0]?.score||0;\n  const opp=x.opportunities?.[0]?.score||0;\n  let readiness=Math.min(100,Math.round(scan.score*.45 + (exitScore||50)*.30 + (opp||50)*.25));\n\n  let persona='General Exit Planning Prospect';\n  if(ctx.includes('retirement')||years>=25) persona='Retirement Seller';\n  else if(ctx.includes('succession')||ctx.includes('family')||years>=18) persona='Family Succession Candidate';\n  else if(ctx.includes('burnout')||ctx.includes('owner fatigue')) persona='Lifestyle Seller';\n  else if(ctx.includes('no website')||ctx.includes('website: \u2014')) persona='Growth Ceiling Seller';\n  else if(scan.type==='Strategic Acquisition'||['hvac','plumbing','electrical','roofing','pest','auto repair','pool'].some(k=>industry.includes(k))) persona='Strategic Seller';\n  else if(scan.type==='Legacy Exit'||scan.score>=80) persona='Legacy Preservation Seller';\n\n  let timeline='Long-Term (5+ Years)';\n  if(readiness>=82) timeline='Immediate to Near-Term (0-12 Months)';\n  else if(readiness>=68) timeline='Near-Term (12-24 Months)';\n  else if(readiness>=50) timeline='Mid-Term (24-60 Months)';\n\n  let style='Relationship First';\n  if(persona==='Strategic Seller') style='Market Opportunity \/ Buyer Demand';\n  if(persona==='Growth Ceiling Seller') style='Value Improvement Advisor';\n  if(persona==='Retirement Seller'||persona==='Family Succession Candidate'||persona==='Legacy Preservation Seller') style='Legacy and Succession Advisor';\n  if(persona==='Lifestyle Seller') style='Freedom and Lifestyle Planning';\n\n  let likelyObjection='I am not ready to sell.';\n  if(persona==='Retirement Seller') likelyObjection='I have not decided when I want to retire.';\n  if(persona==='Family Succession Candidate') likelyObjection='I may pass the business to family.';\n  if(persona==='Growth Ceiling Seller') likelyObjection='The business could still grow if I had the right help.';\n  if(persona==='Strategic Seller') likelyObjection='I do not know if buyers would really be interested.';\n  if(persona==='Lifestyle Seller') likelyObjection='I am too busy to think about selling right now.';\n\n  return {persona,readiness,timeline,style,likelyObjection,scan};\n}\n\nfunction generateSuccessionIntel(){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return}\n  const a=successionAnalyze(x);\n  const goal=val('succGoal')||'discovery';\n  const customStyle=val('succStyle')||'relationship';\n  successionIntel={date:new Date().toLocaleString(),business:x.bizName,...a,goal,customStyle};\n\n  $('successionSelected').textContent=`${x.bizName}\nIndustry: ${x.industry||'\u2014'}\nLocation: ${x.location||'\u2014'}\nYears in Business: ${x.years||'\u2014'}\nCurrent Stage: ${x.stage||'Identified'}`;\n\n  $('successionPersona').innerHTML=`<h3>${a.persona}<\/h3>\n<div class=\"persona-score\">${a.readiness}%<\/div>\n<p>Exit Readiness Probability<\/p>\n<p><span class=\"intel-pill hot\">${a.timeline}<\/span><span class=\"intel-pill blue\">${a.style}<\/span><span class=\"intel-pill\">${a.scan.grade}<\/span><\/p>`;\n\n  $('successionGuidance').textContent=`Recommended Approach:\n${a.style}\n\nTransition Timeline:\n${a.timeline}\n\nConversation Priority:\n${a.scan.grade} \u00b7 ${a.scan.probability} Seller Probability\n\nBroker Positioning:\n${a.persona==='Retirement Seller'?'Position yourself as a confidential retirement and wealth-transition advisor, not a salesperson.':a.persona==='Family Succession Candidate'?'Focus on options: family transfer, partial sale, management transition, or outside buyer.':a.persona==='Lifestyle Seller'?'Lead with reducing owner stress, creating flexibility, and exploring transition options.':a.persona==='Growth Ceiling Seller'?'Frame the conversation around unlocking value before the business plateaus further.':a.persona==='Strategic Seller'?'Lead with buyer demand, consolidation trends, and strategic acquisition interest.':'Lead with legacy, confidential planning, and protecting employees\/customers.'}\n\nRecommended Next Step:\n${goal==='valuation'?'Invite the owner to a confidential valuation discussion.':goal==='assessment'?'Offer an exit readiness assessment.':goal==='listing'?'Prepare a listing strategy conversation if motivation is confirmed.':'Start with a confidential discovery call.'}`;\n\n  $('successionQuestions').textContent=`Opening Questions:\n1. Have you thought about what the next chapter of ${x.bizName} could look like?\n2. What would make a transition successful for you personally?\n3. Is your goal to eventually exit, slow down, bring in a successor, or keep growing?\n\nLegacy Questions:\n4. What would you want protected if the business changed hands?\n5. How important are employees, customers, and reputation in a future transition?\n6. Would you prefer a buyer who preserves the company culture?\n\nTiming Questions:\n7. If you could choose the ideal timeline, what would it be?\n8. What would need to happen before you felt ready?\n9. Are there personal, family, or market factors influencing timing?\n\nValuation Questions:\n10. Have you ever had a realistic market valuation completed?\n11. Do you know what buyers would consider strengths and risks?\n12. Would it be useful to understand what the business could be worth today versus after preparation?`;\n\n  $('successionObjections').textContent=`Likely Objection:\n\"${a.likelyObjection}\"\n\nSuggested Response:\nThat makes complete sense. My goal is not to push you into a sale. The best outcomes usually come from understanding options early, before there is any pressure to act.\n\nAdditional Responses:\n\u2022 This can simply be a planning conversation.\n\u2022 You do not need to be ready to sell to understand what creates value.\n\u2022 A confidential review helps you protect the future of what you have built.\n\u2022 If family succession is possible, we can compare that with other options.\n\u2022 If timing is not right, we can build a preparation roadmap.`;\n}\nfunction saveSuccessionIntel(){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return}\n  if(!successionIntel)generateSuccessionIntel();\n  ensureArrays(x);\n  x.history.unshift(hist('Succession Intelligence',`${successionIntel.persona} \u00b7 ${successionIntel.readiness}% readiness \u00b7 ${successionIntel.timeline}. Recommended style: ${successionIntel.style}.`));\n  x.nextAction=successionIntel.readiness>=75?'Schedule succession planning conversation':'Send educational exit planning outreach';\n  $('nextAction').value=x.nextAction;\n  persist();renderAll();\n  alert('Succession intelligence saved to prospect history.');\n}\nfunction exportSuccessionIntel(){\n  if(!successionIntel)generateSuccessionIntel();\n  if(!successionIntel)return;\n  const text=`Deal Origination\nBusiness: ${successionIntel.business}\nExit Persona: ${successionIntel.persona}\nExit Readiness Probability: ${successionIntel.readiness}%\nTransition Timeline: ${successionIntel.timeline}\nRecommended Style: ${successionIntel.style}\nLikely Objection: ${successionIntel.likelyObjection}\n\nBROKER GUIDANCE\n${$('successionGuidance').innerText}\n\nCONVERSATION QUESTIONS\n${$('successionQuestions').innerText}\n\nOBJECTIONS & RESPONSES\n${$('successionObjections').innerText}`;\n  const blob=new Blob([text],{type:'text\/plain;charset=utf-8'});\n  const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='succession-intelligence.txt';a.click();\n}\nfunction renderSuccessionMetrics(){\n  if(!$('succRetire'))return;\n  const rows=prospects.map(successionAnalyze);\n  $('succRetire').textContent=rows.filter(r=>r.persona==='Retirement Seller').length;\n  $('succLegacy').textContent=rows.filter(r=>r.persona.includes('Legacy')||r.persona.includes('Succession')).length;\n  $('succStrategic').textContent=rows.filter(r=>r.persona==='Strategic Seller').length;\n  $('succReady').textContent=rows.filter(r=>r.readiness>=75).length;\n}\n\nlet smartSequence=null;\n\nfunction selectedScan(){\n  const x=p();\n  if(!x)return null;\n  if(typeof scanProspect==='function')return scanProspect(x);\n  return {score:50,grade:'C',probability:'Medium',type:'General Prospect',approach:'Educational Exit Planning Conversation',timing:'Follow up within 30 days',drivers:['Needs qualification'],risks:['Needs research']};\n}\nfunction sequenceTheme(scan){\n  const type=scan?.type||'General Prospect';\n  if(type==='Retirement Candidate')return {\n    theme:'Retirement Planning',\n    subject:'Planning the next chapter for your business',\n    angle:'A confidential conversation about retirement, timing, and preserving the value you have built.'\n  };\n  if(type==='Succession Opportunity')return {\n    theme:'Legacy Preservation',\n    subject:'Protecting the legacy of your business',\n    angle:'A conversation about preserving the company legacy and preparing for a future transition.'\n  };\n  if(type==='Strategic Acquisition')return {\n    theme:'Buyer Demand',\n    subject:'Buyer interest in businesses like yours',\n    angle:'A market-based conversation about current buyer demand and strategic acquisition interest.'\n  };\n  if(type==='Lifestyle Seller')return {\n    theme:'Lifestyle Transition',\n    subject:'Reducing owner dependence and planning options',\n    angle:'A confidential discussion about owner freedom, lifestyle goals, and transition options.'\n  };\n  if(type==='Growth Ceiling')return {\n    theme:'Value Improvement',\n    subject:'Unlocking value before a future transition',\n    angle:'A practical conversation about growth constraints, value improvement, and future saleability.'\n  };\n  if(type==='Legacy Exit')return {\n    theme:'Legacy Exit',\n    subject:'Preserving what you have built',\n    angle:'A conversation about legacy, market value, and the right timing for a confidential transition plan.'\n  };\n  return {\n    theme:'Exit Planning',\n    subject:'A confidential question about your business',\n    angle:'A low-pressure conversation about market value, buyer demand, and future exit planning.'\n  };\n}\nfunction latestApolloContact(x){\n  if(!x)return null;\n  const list=Array.isArray(x.apolloContacts)?x.apolloContacts:[];\n  return list.length?list[0]:null;\n}\nfunction contactFirstName(name){\n  name=(name||'').trim();\n  if(!name)return 'there';\n  return name.split(\/\\s+\/)[0]||name;\n}\nfunction smartBase(){\n  const x=p();\n  const scan=selectedScan();\n  const theme=sequenceTheme(scan);\n  const contact=latestApolloContact(x);\n  return {x,contact,scan,theme,tone:val('seqTone')||'professional',goal:val('seqGoal')||'conversation',cadence:val('seqCadence')||'7'};\n}\nfunction outreachCredentialLine(){\n  return 'I work with business owners on confidential valuation, buyer-demand, succession, and exit-planning conversations before anything is ever taken to market.';\n}\nfunction buildSequenceDates(cadence){\n  const n=parseInt(cadence||'7',10)||7;\n  const today=new Date();\n  const d1=new Date(today.getTime()+n*86400000);\n  const d2=new Date(today.getTime()+n*2*86400000);\n  const d3=new Date(today.getTime()+n*3*86400000);\n  return [d1,d2,d3].map(d=>d.toISOString().slice(0,10));\n}\nfunction generateSmartSequence(){\n  const b=smartBase();\n  if(!b.x){alert('Select a prospect first.');return}\n  const x=b.x, c=b.contact, s=b.scan, t=b.theme;\n  const owner=(c&&c.name)||x.owner||'Business Owner';\n  const first=contactFirstName(owner);\n  const ownerTitle=(c&&c.title)||x.ownerTitle||'Owner';\n  const ownerEmail=(c&&c.email)||x.ownerEmail||'';\n  const ownerLinkedIn=(c&&c.linkedin_url)||x.ownerLinkedIn||'';\n  const biz=x.bizName||'your business';\n  const industry=x.industry||'your industry';\n  const location=x.location||'your market';\n  const years=x.years||'many';\n  const score=s.score||priorityScore(x)||0;\n  const goalLine=b.goal==='valuation'?'compare notes on value, buyer demand, and current market timing':b.goal==='succession'?'talk through succession, transition options, and owner-dependence planning':b.goal==='listing'?'discuss what a confidential listing strategy could look like if the timing ever made sense':'start a brief confidential conversation';\n  const cadence=b.cadence;\n  const dates=buildSequenceDates(cadence);\n  const contactQuality=c?'Apollo contact saved':'No Apollo contact saved';\n  const emailLine=ownerEmail?`Email: ${ownerEmail}`:'Email: not saved or not revealed';\n  const linkedInLine=ownerLinkedIn?`LinkedIn: ${ownerLinkedIn}`:'LinkedIn: not saved or not returned';\n\n  if($('seqContactContext'))$('seqContactContext').textContent=`Contact used:\n${owner}\nTitle: ${ownerTitle}\n${emailLine}\n${linkedInLine}\nSource: ${contactQuality}\n\nProspect:\n${biz}\n${industry} \u00b7 ${location}\nOpportunity: ${s.grade} \u00b7 ${s.probability} \u00b7 ${s.type}\nSuggested cadence: every ${cadence} days`;\n\n  $('sequenceStrategy').innerHTML=`<span class=\"angle-pill\">${s.grade}<\/span><span class=\"angle-pill\">${s.probability}<\/span><span class=\"angle-pill\">${s.type}<\/span><span class=\"angle-pill\">${t.theme}<\/span><span class=\"angle-pill\">${contactQuality}<\/span>\n\nRecommended Approach:\n${s.approach}\n\nOutreach Angle:\n${t.angle}\n\nRecommended Timing:\n${s.timing}\n\nFollow-Up Schedule:\nEmail #1: Today\nEmail #2: ${dates[0]}\nEmail #3: ${dates[1]}\nCall \/ LinkedIn Touch: ${dates[2]}`;\n\n  $('seqEmail1').textContent=`Subject: ${t.subject}\n\nHi ${first},\n\nI came across ${biz} while reviewing established ${industry} businesses in ${location}. ${biz} stood out because companies with local presence, operating history, and owner-led reputation often attract interest from buyers long before the owner is actively thinking about a sale.\n\n${outreachCredentialLine()}\n\nI am not assuming you are looking to sell. My reason for reaching out is simpler: many owners benefit from understanding what their options could look like before timing becomes urgent.\n\nWould you be open to a brief confidential conversation to ${goalLine}?\n\nBest,\n[Broker Name]`;\n\n  $('seqEmail2').textContent=`Subject: A practical thought on preparation\n\nHi ${first},\n\nI wanted to follow up on my note regarding ${biz}.\n\nIn my experience, owners who prepare early usually have more control over value, timing, employees, confidentiality, and buyer selection. Waiting until there is pressure to act often limits options.\n\nFor an established ${industry} business in ${location}, a short confidential review could help clarify:\n\n\u2022 Current buyer demand\n\u2022 Likely value drivers\n\u2022 Buyer concerns before due diligence\n\u2022 Whether succession or transition planning should start now\n\u2022 Steps that could improve value before any future sale\n\nWould a 15-minute conversation be reasonable?`;\n\n  $('seqEmail3').textContent=`Subject: Should I close the loop?\n\nHi ${first},\n\nI do not want to keep filling your inbox, so I will close the loop for now.\n\nIf valuation, succession, retirement, growth capital, or future transition planning ever becomes relevant for ${biz}, I would be happy to be a confidential resource.\n\nEven if now is not the right time, an early conversation can help an owner understand what buyers look for and what preparation steps can improve future options.\n\nBest,\n[Broker Name]`;\n\n  $('seqLinkedIn').textContent=`Hi ${first}, I work with owners of established ${industry} businesses on confidential valuation, buyer-demand, and transition planning. ${biz} stood out while reviewing companies in ${location}. Thought it may be useful to connect.`;\n\n  $('seqPhone').textContent=`Cold Call Script \u2014 ${biz}\n\nOpening:\nHi ${first}, this is [Broker Name]. I work with owners of established ${industry} businesses on confidential valuation, buyer-demand, and exit-planning conversations.\n\nReason for call:\nI came across ${biz} while reviewing businesses in ${location}. I am not calling to ask if you are selling today. I am calling because companies with operating history and local reputation often benefit from understanding their options before timing becomes urgent.\n\nBridge:\nMany owners start exploring value, buyer demand, succession, or transition planning years before making a public decision.\n\nQuestion:\nHave you ever had a confidential conversation about what ${biz} might be worth or what a future transition could look like?\n\nClose:\nWould a short 15-minute conversation next week be reasonable?`;\n\n  $('seqVoicemail').textContent=`Hi ${first}, this is [Broker Name]. I work with owners of established ${industry} businesses on confidential valuation and transition planning. ${biz} stood out as a company where a private market perspective may be useful. No pressure and no assumption that you are selling \u2014 I simply wanted to offer a brief confidential conversation about value and future options. You can reach me at [phone].`;\n\n  $('seqGuide').textContent=`Succession \/ Exit Conversation Guide for ${biz}\n\nContact:\n${owner}${ownerTitle?' \u00b7 '+ownerTitle:''}\n${ownerEmail?ownerEmail:''}\n${ownerLinkedIn?ownerLinkedIn:''}\n\n1. Opening Question\nHave you thought about what the next chapter of the business might look like over the next few years?\n\n2. Motivation Question\nWhat would make you consider a transition \u2014 retirement, lifestyle, family succession, growth capital, or something else?\n\n3. Owner Dependence\nHow involved are you in daily operations today?\n\n4. Transition Readiness\nIf the right opportunity came along, how prepared would the business be for buyer due diligence?\n\n5. Value Expectations\nHave you ever had a realistic market valuation completed?\n\n6. Legacy Question\nWhat would be most important to protect if you eventually transitioned the business?\n\n7. Next Step\nWould it make sense to prepare a confidential value and readiness snapshot so you can understand your options?`;\n\n  smartSequence={\n    date:new Date().toLocaleString(),\n    prospect:x.bizName,\n    contactName:owner,\n    contactTitle:ownerTitle,\n    contactEmail:ownerEmail,\n    contactLinkedIn:ownerLinkedIn,\n    scannerScore:s.score,\n    grade:s.grade,\n    probability:s.probability,\n    type:s.type,\n    theme:t.theme,\n    cadence,\n    schedule:{email1:'Today',email2:dates[0],email3:dates[1],callLinkedIn:dates[2]},\n    email1:$('seqEmail1').textContent,\n    email2:$('seqEmail2').textContent,\n    email3:$('seqEmail3').textContent,\n    linkedin:$('seqLinkedIn').textContent,\n    phone:$('seqPhone').textContent,\n    voicemail:$('seqVoicemail').textContent,\n    guide:$('seqGuide').textContent\n  };\n}\nfunction saveSmartSequence(){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return}\n  if(!smartSequence)generateSmartSequence();\n  ensureArrays(x);\n  x.outreach.unshift(smartSequence);\n  x.history.unshift(hist('AI Outreach Sequence',`Generated ${smartSequence.theme} sequence for ${smartSequence.contactName||'selected contact'} (${smartSequence.grade}, ${smartSequence.probability}).`));\n  x.stage=x.stage==='Identified'||x.stage==='Researched'?'Outreach Sent':x.stage;\n  x.nextAction='Send first personalized outreach';\n  const dates=smartSequence.schedule||{};\n  if(dates.email2)x.dueDate=dates.email2;\n  $('stage').value=x.stage;\n  $('nextAction').value=x.nextAction;\n  if($('dueDate'))$('dueDate').value=x.dueDate||'';\n  persist();renderAll();\n  alert('AI outreach sequence saved to prospect history.');\n}\nfunction markSequenceActivity(type){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return}\n  ensureArrays(x);\n  x.activities=x.activities||[];\n  x.activities.unshift({date:new Date().toLocaleString(),type,note:'Logged from AI Outreach Sequence tab.'});\n  x.history.unshift(hist(type,'Logged from AI Outreach Sequence tab.'));\n  if(type==='Email Sent')x.stage='Outreach Sent';\n  if(type==='Call Made' && x.stage==='Outreach Sent')x.stage='Conversation Started';\n  x.nextAction=type==='Email Sent'?'Send follow-up or LinkedIn touch':type==='LinkedIn Touch'?'Call owner or send follow-up email':'Log call notes and schedule next follow-up';\n  persist();renderAll();\n  generateSmartSequence();\n  alert(type+' saved to prospect activity.');\n}\nfunction exportSmartSequence(){\n  if(!smartSequence)generateSmartSequence();\n  if(!smartSequence)return;\n  const text=`AI Outreach Sequence\nProspect: ${smartSequence.prospect}\nContact: ${smartSequence.contactName||'\u2014'}\nTitle: ${smartSequence.contactTitle||'\u2014'}\nEmail: ${smartSequence.contactEmail||'\u2014'}\nLinkedIn: ${smartSequence.contactLinkedIn||'\u2014'}\nScanner Score: ${smartSequence.scannerScore}\nGrade: ${smartSequence.grade}\nSeller Probability: ${smartSequence.probability}\nOpportunity Type: ${smartSequence.type}\nTheme: ${smartSequence.theme}\nCadence: Every ${smartSequence.cadence} days\n\nSCHEDULE\nEmail #1: Today\nEmail #2: ${smartSequence.schedule?.email2||'\u2014'}\nEmail #3: ${smartSequence.schedule?.email3||'\u2014'}\nCall \/ LinkedIn Touch: ${smartSequence.schedule?.callLinkedIn||'\u2014'}\n\nEMAIL 1\n${smartSequence.email1}\n\nEMAIL 2\n${smartSequence.email2}\n\nEMAIL 3\n${smartSequence.email3}\n\nLINKEDIN\n${smartSequence.linkedin}\n\nPHONE SCRIPT\n${smartSequence.phone}\n\nVOICEMAIL\n${smartSequence.voicemail}\n\nCONVERSATION GUIDE\n${smartSequence.guide}`;\n  const blob=new Blob([text],{type:'text\/plain;charset=utf-8'});\n  const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='ai-outreach-sequence.txt';a.click();\n}\n\nlet scannerResults=[];\n\nfunction scanProspect(x){\n  ensureArrays(x);\n  const ctx=(x.context||'').toLowerCase();\n  const industry=(x.industry||'').toLowerCase();\n  const opp=x.opportunities?.[0]?.score||0;\n  const exit=x.assessments?.[0]?.score||0;\n  const priority=typeof priorityScore==='function'?priorityScore(x):Math.max(opp,exit,40);\n  let score=35;\n  const ratingMatch=(x.context||'').match(\/Rating:\\s*([0-9.]+)\/i);\n  const reviewMatch=(x.context||'').match(\/Reviews:\\s*([0-9]+)\/i);\n  const yearsVal=parseInt(x.years||0,10)||0;\n  const employeesVal=parseInt(x.employees||0,10)||0;\n  const rating=ratingMatch?parseFloat(ratingMatch[1]):0;\n  const reviews=reviewMatch?parseInt(reviewMatch[1],10):0;\n  if(rating>=4.6)score+=14; else if(rating>=4.2)score+=10; else if(rating>=3.8)score+=6;\n  if(reviews>=150)score+=14; else if(reviews>=75)score+=10; else if(reviews>=25)score+=6;\n  if(yearsVal>=20)score+=16; else if(yearsVal>=15)score+=12; else if(yearsVal>=10)score+=8;\n  if(employeesVal>=5&&employeesVal<=50)score+=8;\n  if(ctx.includes('no website')||ctx.includes('website: \u2014'))score+=8;\n  const strongIndustries=['hvac','plumbing','electric','electrical','roofing','landscaping','pest','auto repair','pool','cleaning','restaurant'];\n  if(strongIndustries.some(k=>industry.includes(k)))score+=10;\n  if(ctx.includes('retirement'))score+=14;\n  if(ctx.includes('succession'))score+=14;\n  if(ctx.includes('burnout'))score+=10;\n  if(ctx.includes('owner-operated')||ctx.includes('owner managed'))score+=8;\n  if(ctx.includes('strong review')||ctx.includes('strong local reputation'))score+=8;\n  score+=Math.round(priority*.12);\n  score+=Math.round(opp*.10);\n  score+=Math.round(exit*.08);\n  score=Math.min(100,Math.max(0,score));\n\n  let probability='Low';\n  if(score>=85)probability='Very High';\n  else if(score>=70)probability='High';\n  else if(score>=50)probability='Medium';\n\n  let grade='D';\n  if(score>=90)grade='A+';\n  else if(score>=80)grade='A';\n  else if(score>=65)grade='B';\n  else if(score>=50)grade='C';\n\n  let type='General Prospect';\n  if(ctx.includes('retirement'))type='Retirement Candidate';\n  else if(ctx.includes('succession')||yearsVal>=20)type='Succession Opportunity';\n  else if(strongIndustries.some(k=>industry.includes(k))&&reviews>=75)type='Strategic Acquisition';\n  else if(ctx.includes('burnout'))type='Lifestyle Seller';\n  else if(ctx.includes('no website')||ctx.includes('website: \u2014'))type='Growth Ceiling';\n  else if(reviews>=150&&rating>=4.4)type='Legacy Exit';\n\n  let approach='Educational Exit Planning Conversation';\n  if(type==='Retirement Candidate')approach='Retirement and Wealth Transition Conversation';\n  if(type==='Succession Opportunity')approach='Legacy Preservation Conversation';\n  if(type==='Strategic Acquisition')approach='Strategic Buyer Demand Conversation';\n  if(type==='Lifestyle Seller')approach='Freedom and Lifestyle Transition Conversation';\n  if(type==='Growth Ceiling')approach='Value Improvement and Growth Ceiling Conversation';\n  if(type==='Legacy Exit')approach='Protecting Business Legacy Conversation';\n\n  let timing='Quarterly nurture';\n  if(score>=85)timing='Contact within 14 days';\n  else if(score>=70)timing='Contact within 30 days';\n  else if(score>=50)timing='Educational follow-up within 60 days';\n\n  const drivers=[];\n  if(rating>=4.4)drivers.push('Strong local rating');\n  if(reviews>=75)drivers.push('Significant review footprint');\n  if(yearsVal>=15)drivers.push('Mature business \/ succession potential');\n  if(employeesVal>=5&&employeesVal<=50)drivers.push('Brokerage-size employee profile');\n  if(strongIndustries.some(k=>industry.includes(k)))drivers.push('Acquisition-friendly service industry');\n  if(ctx.includes('no website')||ctx.includes('website: \u2014'))drivers.push('Weak digital presence may indicate untapped growth');\n  if(!drivers.length)drivers.push('Needs additional manual qualification');\n\n  const risks=[];\n  if(!rating)risks.push('No rating data detected');\n  if(!reviews)risks.push('No review volume detected');\n  if(!yearsVal)risks.push('Years in business not verified');\n  if(!employeesVal)risks.push('Employee count not verified');\n  if(!x.nextAction)risks.push('No next action scheduled');\n  if(!risks.length)risks.push('No major sourcing risks from current data');\n\n  return {id:x.id,bizName:x.bizName,score,probability,grade,type,approach,timing,drivers,risks,priority,opp,exit};\n}\nfunction runOpportunityScanner(){\n  scannerResults=prospects.map(scanProspect).sort((a,b)=>b.score-a.score);\n  renderOpportunityScanner();\n}\nfunction renderOpportunityScanner(){\n  if(!$('scannerTab'))return;\n  if(!scannerResults.length)scannerResults=prospects.map(scanProspect).sort((a,b)=>b.score-a.score);\n  $('scanHigh').textContent=scannerResults.filter(r=>r.probability==='High'||r.probability==='Very High').length;\n  $('scanSuccession').textContent=scannerResults.filter(r=>r.type.includes('Succession')||r.type.includes('Retirement')||r.type.includes('Legacy')).length;\n  $('scanStrategic').textContent=scannerResults.filter(r=>r.type==='Strategic Acquisition').length;\n  $('scanAplus').textContent=scannerResults.filter(r=>r.grade==='A+').length;\n  const box=$('scannerResults');\n  if(!scannerResults.length){box.innerHTML='<div class=\"empty-state\">No prospects yet. Use Prospect Sourcing to add prospects first.<\/div>';return}\n  box.innerHTML=scannerResults.slice(0,20).map(r=>{\n    const cls=r.grade==='A+'?'aplus':r.grade.toLowerCase().replace('+','');\n    return `<div class=\"scanner-item ${cls}\" onclick=\"selectProspect('${r.id}');renderScannerDetail('${r.id}')\">\n      <b>${r.bizName}<\/b>\n      <div><span class=\"scanner-badge hot\">Score ${r.score}<\/span><span class=\"scanner-badge\">${r.grade}<\/span><span class=\"scanner-badge\">${r.probability}<\/span><span class=\"scanner-badge warn\">${r.type}<\/span><\/div>\n      <small>${r.approach} \u00b7 ${r.timing}<\/small>\n    <\/div>`;\n  }).join('');\n  if(selectedId)renderScannerDetail(selectedId);\n}\nfunction renderScannerDetail(id){\n  const r=(scannerResults.length?scannerResults:prospects.map(scanProspect)).find(x=>x.id===id);\n  const box=$('scannerDetail');\n  if(!r){box.textContent='Select a prospect or run the scanner.';return}\n  box.innerHTML=`<div class=\"scanner-scorebox\"><div class=\"scanner-rank\">${r.grade}<\/div><div><h3>${r.bizName}<\/h3><p>Opportunity Score: ${r.score}\/100<br>Seller Probability: ${r.probability}<br>Opportunity Type: ${r.type}<\/p><\/div><\/div>\nRecommended Approach:\n${r.approach}\n\nRecommended Timing:\n${r.timing}\n\nOutreach Theme:\n${r.type==='Succession Opportunity'?'Protecting the business legacy and planning the next chapter.':r.type==='Strategic Acquisition'?'Understanding current buyer demand for companies in this category.':r.type==='Growth Ceiling'?'Unlocking value and growth options before a future sale.':'Confidential exit planning and business value conversation.'}\n\nTop Value Drivers:\n${r.drivers.map(d=>'\u2022 '+d).join('\\n')}\n\nTop Risks \/ Research Gaps:\n${r.risks.map(d=>'\u2022 '+d).join('\\n')}\n\nNext Best Action:\n${r.score>=85?'Prepare highly personalized outreach and attempt direct owner conversation.':r.score>=70?'Generate outreach sequence and schedule follow-up.':r.score>=50?'Add to nurture sequence and complete research.':'Keep in long-term watchlist.'}`;\n}\nfunction saveScannerInsight(){\n  if(!selectedId){alert('Select a prospect first.');return}\n  const x=p(); if(!x)return;\n  const r=scanProspect(x);\n  ensureArrays(x);\n  x.history.unshift(hist('Opportunity Scanner',`Score ${r.score}\/100 \u00b7 ${r.grade} \u00b7 ${r.probability} seller probability \u00b7 ${r.type}. Recommended approach: ${r.approach}.`));\n  x.nextAction=r.score>=85?'Direct owner outreach':r.score>=70?'Generate personalized outreach':r.score>=50?'Complete additional research':'Long-term nurture';\n  $('nextAction').value=x.nextAction;\n  persist();renderAll();renderOpportunityScanner();\n  alert('Scanner insight saved to prospect history.');\n}\nfunction exportScannerCSV(){\n  if(!scannerResults.length)runOpportunityScanner();\n  const headers=['Business','Scanner Score','Grade','Seller Probability','Opportunity Type','Recommended Approach','Timing','Priority Score','Opportunity Score','Exit Score'];\n  const rows=scannerResults.map(r=>[r.bizName,r.score,r.grade,r.probability,r.type,r.approach,r.timing,r.priority,r.opp,r.exit].map(escapeCSV).join(','));\n  const csv=[headers.map(escapeCSV).join(','),...rows].join('\\n');\n  const blob=new Blob([csv],{type:'text\/csv;charset=utf-8'});\n  const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='ai-seller-opportunity-scanner.csv';a.click();\n}\n\nlet discoveryResults=[];\n\nfunction demoBusinessNames(industry, city){\n  const cleanIndustry=(industry||'Business').trim();\n  const base=[\n    `${city} Premier ${cleanIndustry}`,\n    `Gulf Coast ${cleanIndustry} Services`,\n    `Legacy ${cleanIndustry} Group`,\n    `Sunshine State ${cleanIndustry}`,\n    `Family First ${cleanIndustry}`,\n    `Bay Area ${cleanIndustry} Co.`,\n    `Trusted Local ${cleanIndustry}`,\n    `Old Town ${cleanIndustry}`,\n    `ProLine ${cleanIndustry} & Repair`,\n    `Neighborhood ${cleanIndustry} Specialists`,\n    `Heritage ${cleanIndustry} Company`,\n    `Elite ${cleanIndustry} Solutions`,\n    `Central Florida ${cleanIndustry}`,\n    `Owner's Choice ${cleanIndustry}`,\n    `Main Street ${cleanIndustry}`\n  ];\n  return base;\n}\nfunction readinessForResult(r){\n  let score=0;\n  if(r.years>=20)score+=26; else if(r.years>=15)score+=21; else if(r.years>=10)score+=14; else score+=7;\n  if(r.rating>=4.6)score+=18; else if(r.rating>=4.2)score+=14; else if(r.rating>=3.8)score+=10; else score+=5;\n  if(r.reviews>=150)score+=16; else if(r.reviews>=75)score+=12; else if(r.reviews>=25)score+=8; else score+=4;\n  if(r.hasWebsite)score+=8; else score+=12;\n  if(r.signal.includes('retirement')||r.signal.includes('succession'))score+=18;\n  if(r.signal.includes('owner fatigue')||r.signal.includes('management'))score+=12;\n  if(['HVAC','Plumbing','Auto Repair','Restaurant','Cleaning','Landscaping'].some(k=>(r.industry||'').toLowerCase().includes(k.toLowerCase())))score+=8;\n  return Math.min(100,score);\n}\nfunction clean(v){return (v||'').toString().trim()}\nfunction flexibleLocationLabel(city,state,zip,county){\n  const parts=[];\n  if(city)parts.push(city);\n  if(county)parts.push(county);\n  if(state)parts.push(state);\n  if(zip)parts.push(zip);\n  return parts.length?parts.join(', '):'Selected Market';\n}\nfunction matchesFlexibleCriteria(r,criteria){\n  if(criteria.industry && !r.industry.toLowerCase().includes(criteria.industry.toLowerCase()) && !r.name.toLowerCase().includes(criteria.industry.toLowerCase())) return false;\n  if(criteria.city && !r.city.toLowerCase().includes(criteria.city.toLowerCase()) && !r.address.toLowerCase().includes(criteria.city.toLowerCase())) return false;\n  if(criteria.state && !r.state.toLowerCase().includes(criteria.state.toLowerCase()) && !r.address.toLowerCase().includes(criteria.state.toLowerCase())) return false;\n  if(criteria.zip && !(r.zip||'').toLowerCase().includes(criteria.zip.toLowerCase()) && !r.address.toLowerCase().includes(criteria.zip.toLowerCase())) return false;\n  if(criteria.county && !(r.county||'').toLowerCase().includes(criteria.county.toLowerCase())) return false;\n  if(r.rating < criteria.minRating) return false;\n  if(r.years < criteria.minYears) return false;\n  if(criteria.size!=='any'){\n    if(criteria.size==='1-5' && !(r.employees>=1&&r.employees<=5)) return false;\n    if(criteria.size==='6-20' && !(r.employees>=6&&r.employees<=20)) return false;\n    if(criteria.size==='21-50' && !(r.employees>=21&&r.employees<=50)) return false;\n    if(criteria.size==='50+' && !(r.employees>=50)) return false;\n  }\n  return true;\n}\nfunction buildDemoResults(){\n  const criteria={\n    industry:clean(val('discIndustry')),\n    city:clean(val('discCity')),\n    state:clean(val('discState')),\n    zip:clean(val('discZip')),\n    county:clean(val('discCounty')),\n    radius:clean(val('discRadius'))||'25',\n    minYears:+val('discYearsMin')||0,\n    size:val('discSize')||'any',\n    minRating:+val('discRating')||0,\n    count:+val('discCount')||10\n  };\n\n  const industry=criteria.industry||'Local Business';\n  const locationLabel=flexibleLocationLabel(criteria.city,criteria.state,criteria.zip,criteria.county);\n  const city=criteria.city||criteria.county||criteria.zip||'Market';\n  const state=criteria.state||'';\n  const county=criteria.county||'';\n  const zip=criteria.zip||'';\n\n  const names=demoBusinessNames(industry,city);\n  const signals=[\n    'Long operating history; possible retirement or succession planning angle',\n    'Strong reviews; owner-operated profile likely',\n    'Website appears dated; possible owner fatigue signal',\n    'High review count; good reputation and buyer appeal',\n    'Management hiring signal; owner may be stepping back',\n    'Family-owned language; possible succession discussion',\n    'Stable local presence; educational nurture recommended',\n    'No obvious signal; needs manual research',\n    'Reputation strong but web presence weak',\n    'Established operator; valuation conversation angle',\n    'Owner-managed business; strong referral base',\n    'Mature operation; potential succession gap',\n    'Good local reputation; possible strategic buyer interest',\n    'Long-term family business; exit planning angle',\n    'High service demand area; strong buyer appeal'\n  ];\n\n  let rows=names.concat(demoBusinessNames(industry,locationLabel)).slice(0,Math.max(criteria.count,15)).map((name,i)=>{\n    const rating=+(3.6+((i*7)%16)\/10).toFixed(1);\n    const years=5+((i*5)%28);\n    const reviews=18+((i*37)%260);\n    const employees=[3,8,14,22,37,58,11,6,44,19,27,75,9,16,33][i%15];\n    const r={\n      id:'disc_'+Date.now()+'_'+i,\n      name,\n      industry,\n      city:criteria.city||city,\n      state,\n      zip,\n      county,\n      radius:criteria.radius,\n      employees,\n      size:criteria.size,\n      address:`${100+i*17} Main Street${criteria.city?', '+criteria.city:''}${criteria.county?', '+criteria.county:''}${state?', '+state:''}${zip?' '+zip:''}`,\n      phone:`(813) 555-${String(1200+i*37).slice(0,4)}`,\n      website:i%4===0?'':`https:\/\/example-${i+1}.com`,\n      rating,\n      reviews,\n      years,\n      signal:signals[i%signals.length],\n      source:'Demo Data'\n    };\n    r.score=readinessForResult(r);\n    return r;\n  });\n\n  rows=rows.filter(r=>matchesFlexibleCriteria(r,criteria)).slice(0,criteria.count);\n\n  \/\/ If strict filters produce no demo rows, create flexible fallback rows that honor the fields the user supplied.\n  if(!rows.length){\n    rows=names.slice(0,criteria.count).map((name,i)=>{\n      const employees=criteria.size==='50+'?60:criteria.size==='21-50'?30:criteria.size==='6-20'?12:criteria.size==='1-5'?4:12+i;\n      const years=Math.max(criteria.minYears,10+i);\n      const rating=Math.max(criteria.minRating,4.1);\n      const r={\n        id:'disc_fallback_'+Date.now()+'_'+i,\n        name,\n        industry,\n        city:criteria.city||city,\n        state,\n        zip,\n        county,\n        radius:criteria.radius,\n        employees,\n        size:criteria.size,\n        address:`${200+i*11} Business Ave${criteria.city?', '+criteria.city:''}${criteria.county?', '+criteria.county:''}${state?', '+state:''}${zip?' '+zip:''}`,\n        phone:`(813) 555-${String(2200+i*41).slice(0,4)}`,\n        website:i%3===0?'':`https:\/\/sample-${i+1}.com`,\n        rating,\n        reviews:55+i*19,\n        years,\n        signal:criteria.industry?'Industry-targeted prospect sourced from flexible criteria':'Geography-targeted prospect sourced from flexible criteria',\n        source:'Demo Data'\n      };\n      r.score=readinessForResult(r);\n      return r;\n    });\n  }\n  return rows;\n}\nasync function runDiscovery(){\n  const mode=val('discMode');\n  $('discoveryResults').innerHTML='<div class=\"notice\">Searching prospects...<\/div>';\n  if(mode==='api'){\n    const endpoint=val('discEndpoint')||'\/wp-json\/ai-deal-sourcing\/v1\/prospect-search';\n    const params={industry:val('discIndustry'),city:val('discCity'),state:val('discState'),zip:val('discZip'),county:val('discCounty'),radius:val('discRadius'),minYears:val('discYearsMin'),businessSize:val('discSize'),count:val('discCount')};\n    Object.keys(params).forEach(k=>{if(!params[k])delete params[k]});\n    const q=new URLSearchParams(params);\n    try{\n      const headers=adsAiHeaders({});\n      if(window.ADS_CLOUD_STORAGE&&window.ADS_CLOUD_STORAGE.nonce)headers['X-WP-Nonce']=window.ADS_CLOUD_STORAGE.nonce;\n      const res=await fetch(endpoint+'?'+q.toString(),{credentials:'same-origin',headers});\n      if(!res.ok)throw new Error('API endpoint not available');\n      discoveryResults=await res.json();\n      discoveryResults=discoveryResults.map((r,i)=>({...r,id:r.id||'api_'+Date.now()+'_'+i,source:r.source||'API',score:r.score||readinessForResult(r)}));\n    }catch(err){\n      $('discoverySummary').textContent='API endpoint is not connected yet. Showing demo results instead. Future backend should return JSON business records from Google Places or another source.';\n      discoveryResults=buildDemoResults();\n    }\n  }else{\n    discoveryResults=buildDemoResults();\n  }\n  renderDiscovery();\n}\nfunction renderDiscovery(){\n  const box=$('discoveryResults');\n  const summary=$('discoverySummary');\n  if(!discoveryResults.length){\n    summary.textContent='No matching prospects found. Try using fewer filters, lowering the rating filter, or broadening the geography.';\n    box.innerHTML='';\n    return;\n  }\n  const avg=Math.round(discoveryResults.reduce((a,b)=>a+b.score,0)\/discoveryResults.length);\n  summary.textContent=`Found ${discoveryResults.length} prospects. Average Seller Readiness Score: ${avg}\/100. Click \"Add to Pipeline\" to convert any discovery result into a saved prospect.`;\n  box.innerHTML=discoveryResults.sort((a,b)=>b.score-a.score).map(r=>`<div class=\"discovery-result\">\n    <div>\n      <h3 style=\"margin-top:0\">${r.name} <span class=\"source-pill\">${r.source||'Demo'}<\/span><\/h3>\n      <div class=\"discovery-meta\">\n        <span class=\"pill blue\">${r.industry}<\/span>\n        <span class=\"pill green\">${r.rating}\u2605 \u00b7 ${r.reviews} reviews<\/span>\n        <span class=\"pill amber\">${r.years} yrs est.<\/span>\n        <span class=\"pill\">${r.employees||'\u2014'} employees est.<\/span>\n        ${r.zip?`<span class=\"pill blue\">ZIP ${r.zip}<\/span>`:''}\n        ${r.county?`<span class=\"pill blue\">${r.county}<\/span>`:''}\n        ${r.radius?`<span class=\"pill\">Radius ${r.radius} mi<\/span>`:''}\n        ${r.website?'<span class=\"pill\">Website<\/span>':'<span class=\"pill red\">No Website Found<\/span>'}\n      <\/div>\n      <p><strong>Address:<\/strong> ${r.address||'\u2014'}<\/p>\n      <p><strong>Phone:<\/strong> ${r.phone||'\u2014'}<\/p>\n      <p><strong>Signal:<\/strong> ${r.signal||'Needs manual research'}<\/p>\n      <div class=\"discovery-actions\">\n        <button class=\"primary\" onclick=\"addDiscoveryToPipeline('${r.id}')\">Add to Pipeline<\/button>\n        <button class=\"light\" onclick=\"previewDiscoveryOutreach('${r.id}')\">Preview Outreach Angle<\/button>\n      <\/div>\n    <\/div>\n    <div class=\"seller-score\">${r.score}<\/div>\n  <\/div>`).join('');\n}\nfunction clearDiscovery(){\n  discoveryResults=[];\n  $('discoveryResults').innerHTML='';\n  $('discoverySummary').textContent='Run a search to source business prospects.';\n}\nfunction addDiscoveryToPipeline(id){\n  const r=discoveryResults.find(x=>x.id===id);\n  if(!r)return;\n  const prospect=ensureArrays({\n    id:'prospect_'+Date.now(),\n    bizName:r.name,\n    industry:r.industry,\n    location:`${r.city}, ${r.state}`,\n    owner:'',\n    revenue:'$1M\u2013$3M',\n    years:r.years,\n    employees:'',\n    context:`Discovered via Prospect Sourcing. Rating: ${r.rating}. Reviews: ${r.reviews}. Phone: ${r.phone||'\u2014'}. Website: ${r.website||'\u2014'}. Signal: ${r.signal}`,\n    stage:'Identified',\n    nextAction:'Research owner and generate outreach',\n    dueDate:'',\n    history:[hist('Prospect Discovered',`Added from Prospect Sourcing with Seller Readiness Score ${r.score}\/100.`)],\n    opportunities:[{date:new Date().toLocaleString(),score:r.score,category:r.score>=80?'Very High':r.score>=65?'High':r.score>=45?'Medium':'Low',approach:r.score>=75?'Immediate Outreach':'Research and Nurture',angle:r.signal||'Local business prospecting angle.'}],\n    assessments:[],\n    outreach:[],\n    coach:[]\n  });\n  prospects.unshift(prospect);\n  selectedId=prospect.id;\n  persist();\n  renderAll();\n  selectProspect(prospect.id);\n  alert('Prospect added to pipeline.');\n}\nfunction previewDiscoveryOutreach(id){\n  const r=discoveryResults.find(x=>x.id===id);\n  if(!r)return;\n  $('discoverySummary').textContent=`Suggested angle for ${r.name}: ${r.score>=75?'Lead with confidential valuation, succession planning, and market demand.':'Lead with educational exit planning and a low-pressure readiness conversation.'} Signal: ${r.signal}`;\n}\n\nlet workflowTasks=[];\n\nfunction makeTask(x){\n  ensureArrays(x);\n  const priority=priorityScore(x);\n  const opp=x.opportunities?.[0]?.score||0;\n  const exit=x.assessments?.[0]?.score||0;\n  const hasAssessment=(x.assessments?.length||0)>0;\n  const hasOutreach=(x.outreach?.length||0)>0;\n  const due=isDue(x.dueDate);\n  let title='Review Prospect';\n  let action='Open prospect record and update next action.';\n  let severity='low';\n  let module='pipeline';\n\n  if(due){\n    title='Complete Follow-Up';\n    action=x.nextAction||'Follow up with seller\/prospect.';\n    severity='high';\n    module='pipeline';\n  } else if(priority>=80){\n    title='Schedule Valuation Consultation';\n    action='Move this prospect toward a confidential valuation or seller discovery conversation.';\n    severity='high';\n    module='coach';\n  } else if(opp>=70 && !hasAssessment){\n    title='Send Exit Readiness Assessment';\n    action='Use the Exit Assessment module to qualify seller readiness and timeline.';\n    severity='medium';\n    module='assessment';\n  } else if(!hasOutreach && (x.stage==='Identified'||x.stage==='Researched'||!x.stage)){\n    title='Generate First Outreach';\n    action='Create personalized email, LinkedIn, and direct mail outreach.';\n    severity='medium';\n    module='outreach';\n  } else if((x.stage==='Outreach Sent') && !(x.coach?.length)){\n    title='Prepare Seller Conversation';\n    action='Use the Conversation Coach before calling or meeting the owner.';\n    severity='medium';\n    module='coach';\n  } else if(!opp){\n    title='Calculate Opportunity Score';\n    action='Score this prospect to determine pursuit priority.';\n    severity='low';\n    module='scorecard';\n  } else if(!hasAssessment){\n    title='Complete Exit Readiness Review';\n    action='Assess whether the seller is market-ready or needs preparation.';\n    severity='low';\n    module='assessment';\n  }\n\n  return {\n    id:x.id,\n    bizName:x.bizName,\n    title,\n    action,\n    severity,\n    module,\n    priority,\n    stage:x.stage||'Identified',\n    dueDate:x.dueDate||'',\n    nextAction:x.nextAction||'',\n    opp,\n    exit\n  };\n}\nfunction generateWorkflowTasks(){\n  workflowTasks=sortedByPriority().map(r=>makeTask(r.p)).sort((a,b)=>{\n    const sev={high:3,medium:2,low:1};\n    return (sev[b.severity]-sev[a.severity]) || (b.priority-a.priority);\n  });\n  renderWorkflow();\n}\nfunction renderWorkflow(){\n  if(!$('workflowTab'))return;\n  if(!workflowTasks.length) workflowTasks=sortedByPriority().map(r=>makeTask(r.p));\n  const high=workflowTasks.filter(t=>t.severity==='high').length;\n  const due=workflowTasks.filter(t=>t.dueDate&&isDue(t.dueDate)).length;\n  $('wOpen').textContent=workflowTasks.length;\n  $('wHigh').textContent=high;\n  $('wDue').textContent=due;\n  $('wSuggest').textContent=workflowTasks.length;\n\n  const box=$('workflowQueue');\n  if(!workflowTasks.length){box.innerHTML='<div class=\"empty-state\">No workflow tasks yet. Add prospects or load demo data.<\/div>';return}\n  box.innerHTML=workflowTasks.slice(0,12).map(t=>`<div class=\"task-card ${t.severity}\">\n    <b>${t.title}<\/b>\n    <div class=\"task-meta\">${t.bizName} \u00b7 Priority ${t.priority} \u00b7 ${t.stage} ${t.dueDate?`\u00b7 Due ${t.dueDate}`:''}<\/div>\n    <p>${t.action}<\/p>\n    <div class=\"task-actions\">\n      <button class=\"light\" onclick=\"goModule('${t.module}','${t.id}')\">Open ${t.module}<\/button>\n      <button class=\"light\" onclick=\"selectProspect('${t.id}')\">Select<\/button>\n      <button class=\"secondary\" onclick=\"applyWorkflowTask('${t.id}','${t.title.replace(\/'\/g,\"\\\\'\")}')\">Save Task<\/button>\n    <\/div>\n  <\/div>`).join('');\n  renderSelectedWorkflow();\n}\nfunction renderSelectedWorkflow(){\n  const x=p();\n  const box=$('selectedWorkflow');\n  if(!box)return;\n  if(!x){box.textContent='Select a prospect or generate tasks to see workflow guidance.';return}\n  const t=makeTask(x);\n  box.textContent=`Recommended Workflow for ${x.bizName}\n\nPriority Score: ${t.priority}\/100\nCurrent Stage: ${t.stage}\nRecommended Task: ${t.title}\nAction: ${t.action}\n\nSuggested Module: ${t.module}\nOpportunity Score: ${t.opp||'Not calculated'}\nExit Readiness Score: ${t.exit||'Not calculated'}\n\nWorkflow Logic:\n${t.severity==='high'?'This prospect requires immediate attention because it is either high-priority or has a due\/overdue action.':t.severity==='medium'?'This prospect should be advanced through the next qualification or outreach step.':'This prospect needs foundational scoring, outreach, or qualification before becoming a priority.'}`;\n}\nfunction applyWorkflowTask(id,title){\n  selectProspect(id);\n  const x=p(); if(!x)return;\n  ensureArrays(x);\n  x.nextAction=title;\n  x.history.unshift(hist('Workflow Task Added',title));\n  $('nextAction').value=title;\n  persist();renderAll();\n  alert('Workflow task saved to prospect.');\n}\nfunction saveTopWorkflowTask(){\n  if(!workflowTasks.length)generateWorkflowTasks();\n  const t=workflowTasks[0];\n  if(!t){alert('No workflow task available.');return}\n  applyWorkflowTask(t.id,t.title);\n}\nfunction exportWorkflowCSV(){\n  if(!workflowTasks.length)generateWorkflowTasks();\n  const headers=['Business','Task','Action','Severity','Priority','Stage','Due Date','Module','Opportunity','Exit Readiness'];\n  const rows=workflowTasks.map(t=>[t.bizName,t.title,t.action,t.severity,t.priority,t.stage,t.dueDate,t.module,t.opp,t.exit].map(escapeCSV).join(','));\n  const csv=[headers.map(escapeCSV).join(','),...rows].join('\\n');\n  const blob=new Blob([csv],{type:'text\/csv;charset=utf-8'});\n  const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='ai-deal-sourcing-workflow.csv';a.click();\n}\n\n\n\n\n\nfunction apiSpecText(){\n return `Secure Prospect Search API Contract\n\nEndpoint:\nGET \/wp-json\/ai-deal-sourcing\/v1\/prospect-search\n\nQuery Parameters:\nindustry, city, state, zip, county, radius, minYears, businessSize, count\n\nExample:\nGET \/wp-json\/ai-deal-sourcing\/v1\/prospect-search?industry=HVAC&zip=33626&county=Hillsborough&radius=25\n\nExpected Response:\n[\n  {\n    \"name\": \"ABC HVAC Services\",\n    \"industry\": \"HVAC\",\n    \"address\": \"123 Main St, Tampa, FL 33626\",\n    \"city\": \"Tampa\",\n    \"state\": \"FL\",\n    \"zip\": \"33626\",\n    \"county\": \"Hillsborough\",\n    \"phone\": \"(813) 555-1212\",\n    \"website\": \"https:\/\/example.com\",\n    \"rating\": 4.6,\n    \"reviews\": 187,\n    \"years\": 18,\n    \"employees\": 14,\n    \"signal\": \"Long operating history; possible succession angle\",\n    \"source\": \"Google Places\",\n    \"score\": 82\n  }\n]\n\nSecurity:\n- Keep API keys server-side.\n- Do not expose API keys in HTML or JavaScript.\n- Restrict Google API keys.\n- Rate limit requests.\n- Return only cleaned prospect data to the frontend.`;\n}\nfunction copyApiSpec(){\n const text=apiSpecText();\n navigator.clipboard?.writeText(text).then(()=>alert('API spec copied.')).catch(()=>alert(text));\n}\nasync function testApiEndpoint(){\n const endpoint=$('apiEndpointTest').value.trim()||'\/wp-json\/ai-deal-sourcing\/v1\/prospect-search';\n const params={\n  industry:$('apiTestIndustry').value.trim(),\n  zip:$('apiTestZip').value.trim(),\n  county:$('apiTestCounty').value.trim(),\n  radius:$('apiTestRadius').value.trim()\n };\n Object.keys(params).forEach(k=>{if(!params[k])delete params[k]});\n const url=endpoint+'?'+new URLSearchParams(params).toString();\n $('apiTestStatus').textContent='Testing endpoint: '+url;\n try{\n  const res=await fetch(url,{credentials:'same-origin',headers:adsAiHeaders({})});\n  if(!res.ok)throw new Error('HTTP '+res.status);\n  const data=await res.json();\n  $('apiTestStatus').textContent='Success. Endpoint returned '+(Array.isArray(data)?data.length:'non-array')+' record(s).';\n }catch(err){\n  $('apiTestStatus').textContent='Endpoint not connected yet or blocked in local\/WordPress test. This is expected until the backend proxy is created. Error: '+err.message;\n }\n}\n\nfunction runReleaseQA(){\n const checks=[\n  ['Browser localStorage available',(()=>{try{localStorage.setItem('qa_test','1');localStorage.removeItem('qa_test');return true}catch(e){return false}})()],\n  ['Prospect records can be stored',Array.isArray(prospects)],\n  ['Command Center module present',!!$('dashboardTab')],\n  ['Prospect Sourcing module present',!!$('discoveryTab')],\n  ['Outreach Generator module present',!!$('outreachTab')],\n  ['Pipeline module present',!!$('pipelineTab')],\n  ['Conversation Coach module present',!!$('coachTab')],\n  ['Opportunity Scorecard module present',!!$('scorecardTab')],\n  ['Exit Assessment module present',!!$('assessmentTab')],\n  ['Analytics module present',!!$('analyticsTab')],\n  ['AI Intelligence module present',!!$('intelligenceTab')],\n  ['Workflow Automation module present',!!$('workflowTab')],\n  ['Listing Conversion module present',!!$('conversionTab')],\n  ['Listing Presentation module present',!!$('presentationTab')]\n ];\n $('qaStorage').textContent=checks[0][1]?'OK':'Issue';\n $('qaProspects').textContent=prospects.length;\n $('qaChecklist').innerHTML=checks.map(c=>`<div class=\"qa-item\"><div class=\"qa-status ${c[1]?'pass':'warn'}\">${c[1]?'\u2713':'!'}<\/div><div><b>${c[0]}<\/b><br><small>${c[1]?'Passed':'Needs attention during WordPress test'}<\/small><\/div><\/div>`).join('');\n}\nfunction downloadReleaseNotes(){\n const notes=`AI Assisted Deals Sourcing Pro\u2122  Deal Origination\n\nIncluded Modules:\n- Command Center\n- Prospect Sourcing\n- Prospect Pipeline\n- Outreach Generator\n- Seller Conversation Coach\n- Opportunity Scorecard\n- Exit Readiness Assessment\n- Seller Report\n- Analytics\n- AI Deal Intelligence\n- Workflow Automation\n- Listing Conversion Engine\n- Listing Presentation Generator\n- System QA\n\nDeployment Notes:\n- Standalone HTML file for WordPress embedding.\n- Stores data in browser localStorage.\n- Prospect Sourcing currently supports demo\/mock data and API-ready endpoint structure.\n- Do not place Google Places API keys directly in this HTML file.\n- Future API integration should use a secure backend endpoint.\n\nRecommended Test:\n1. Install on hidden WordPress test page.\n2. Load demo data.\n3. Test every tab.\n4. Confirm data persists after reload.\n5. Check mobile layout.\n6. Create punch list before public release.`;\n const blob=new Blob([notes],{type:'text\/plain;charset=utf-8'});\n const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='AI-Assisted-Deal-Sourcing--Release-Notes.txt';a.click();\n}\n\nfunction getConversionForSelected(){\n const x=p();\n if(!x)return {pct:0,cls:'Not Classified'};\n return conversionData(x);\n}\nfunction generatePresentation(){\n const x=p();\n const box=$('presentationOutput');\n if(!x){box.innerHTML='<div class=\"empty-state\">Select a prospect first.<\/div>';return;}\n ensureArrays(x);\n const opp=x.opportunities?.[0]||{};\n const exit=x.assessments?.[0]||{};\n const conv=conversionData(x);\n const pri=priorityScore(x);\n const recommendation=conv.pct>=85?'Prepare engagement agreement and move toward listing strategy.':conv.pct>=75?'Schedule listing presentation and valuation discussion.':conv.pct>=65?'Launch valuation workflow and clarify seller expectations.':'Continue nurturing and complete missing qualification steps.';\n const risks=[];\n if(!exit.score)risks.push('Exit readiness assessment has not been completed.');\n if(!opp.score)risks.push('Opportunity scorecard has not been completed.');\n if(!x.nextAction)risks.push('No next action is currently scheduled.');\n if((x.history?.length||0)<3)risks.push('Limited activity history with this prospect.');\n if(!risks.length)risks.push('No major conversion blockers identified from current data.');\n const strengths=[];\n if((opp.score||0)>=70)strengths.push('Strong opportunity score indicates attractive prospect profile.');\n if((exit.score||0)>=70)strengths.push('Exit readiness indicates seller may be prepared for market conversations.');\n if(pri>=70)strengths.push('High priority score supports near-term broker attention.');\n if(x.stage&&x.stage!=='Identified')strengths.push('Prospect has progressed beyond initial identification.');\n if(!strengths.length)strengths.push('Additional qualification can reveal value drivers and seller motivation.');\n box.innerHTML=`<div class=\"pres-cover\">\n <h1>Confidential Listing Opportunity Review<\/h1>\n <p>Prepared for broker\/seller conversation using AI Assisted Deals Sourcing Pro\u2122 intelligence.<\/p>\n <\/div>\n <h2>${x.bizName}<\/h2>\n <p><strong>Industry:<\/strong> ${x.industry||'\u2014'}<br><strong>Location:<\/strong> ${x.location||'\u2014'}<br><strong>Pipeline Stage:<\/strong> ${x.stage||'Identified'}<\/p>\n <div class=\"pres-grid\">\n <div class=\"pres-box\"><div class=\"section-kicker\">Priority Score<\/div><div class=\"pres-score\">${pri}<\/div><\/div>\n <div class=\"pres-box\"><div class=\"section-kicker\">Listing Conversion<\/div><div class=\"pres-score\">${conv.pct}%<\/div><p>${conv.cls}<\/p><\/div>\n <div class=\"pres-box\"><div class=\"section-kicker\">Opportunity Score<\/div><div class=\"pres-score\">${opp.score||'\u2014'}<\/div><p>${opp.category||'Not scored'}<\/p><\/div>\n <div class=\"pres-box\"><div class=\"section-kicker\">Exit Readiness<\/div><div class=\"pres-score\">${exit.score||'\u2014'}<\/div><p>${exit.category||'Not assessed'}<\/p><\/div>\n <\/div>\n <div class=\"pres-section\"><h3>Executive Summary<\/h3><p>${x.bizName} is currently classified as <strong>${conv.cls}<\/strong> with an estimated listing conversion probability of <strong>${conv.pct}%<\/strong>. ${recommendation}<\/p><\/div>\n <div class=\"pres-section\"><h3>Seller \/ Business Context<\/h3><p>${x.context||'No additional context has been entered yet.'}<\/p><\/div>\n <div class=\"pres-section\"><h3>Key Strengths<\/h3><ul>${strengths.map(s=>`<li>${s}<\/li>`).join('')}<\/ul><\/div>\n <div class=\"pres-section\"><h3>Conversion Risks<\/h3><ul>${risks.map(s=>`<li>${s}<\/li>`).join('')}<\/ul><\/div>\n <div class=\"pres-section\"><h3>Recommended Listing Strategy<\/h3><p>${recommendation}<\/p><\/div>\n <div class=\"pres-section\"><h3>Recommended Next Steps<\/h3><ol><li>Confirm seller motivation, timing, and expectations.<\/li><li>Use the existing 360 Business Valuation Tool when the prospect is ready for valuation.<\/li><li>Prepare confidential seller materials and listing strategy.<\/li><li>Move qualified candidates toward engagement discussion.<\/li><\/ol><\/div>\n <div class=\"pres-section\"><p style=\"font-size:12px;color:#666\">Disclaimer: This presentation is a planning aid and does not replace a formal valuation, legal advice, tax advice, or a signed engagement agreement.<\/p><\/div>`;\n}\nfunction copyPresentation(){\n const box=$('presentationOutput');\n const text=box.innerText||box.textContent||'';\n if(!text.trim()){alert('Generate a presentation first.');return;}\n navigator.clipboard?.writeText(text).then(()=>alert('Presentation copied.')).catch(()=>alert('Copy failed.'));\n}\n\nfunction conversionData(x){\n const opp=x.opportunities?.[0]?.score||0;\n const exit=x.assessments?.[0]?.score||0;\n const pri=priorityScore(x);\n const pct=Math.min(95,Math.round(opp*0.35+exit*0.35+pri*0.3));\n let cls='Cold Prospect';\n if(pct>=85) cls='Ready for Engagement';\n else if(pct>=75) cls='Listing Candidate';\n else if(pct>=65) cls='Valuation Candidate';\n else if(pct>=50) cls='Qualified Seller';\n else if(pct>=35) cls='Warm Prospect';\n return {pct,cls};\n}\nfunction renderConversion(){\n if(!$('conversionTab')) return;\n const rows=prospects.map(p=>({p,...conversionData(p)})).sort((a,b)=>b.pct-a.pct);\n $('cCandidates').textContent=rows.filter(r=>r.pct>=75).length;\n $('cValuation').textContent=rows.filter(r=>r.pct>=65).length;\n $('cEngage').textContent=rows.filter(r=>r.pct>=85).length;\n $('cAvg').textContent=(rows.length?Math.round(rows.reduce((a,b)=>a+b.pct,0)\/rows.length):0)+'%';\n $('conversionQueue').innerHTML=rows.slice(0,15).map(r=>`${r.p.bizName} \u2014 ${r.cls} (${r.pct}%)`).join('<br>') || 'No prospects.';\n const funnel=['Cold Prospect','Warm Prospect','Qualified Seller','Valuation Candidate','Listing Candidate','Ready for Engagement'];\n $('conversionFunnel').innerHTML=funnel.map(f=>`${f}: ${rows.filter(r=>r.cls===f).length}`).join('<br>');\n}\n\nfunction listingReadinessIndustryDemand(industry){\n  const i=(industry||'').toLowerCase();\n  if(\/hvac|plumb|electrical|electrician|roof|manufactur|machine|logistics|distribution|medical|dental|accounting|insurance|fire|security|pest|landscap|floor|garage|auto repair|collision|pack|ship|mail\/.test(i))return {score:18,label:'High buyer-demand industry \/ service category'};\n  if(\/restaurant|retail|salon|spa|fitness|printing|cleaning|realty|real estate|brokerage\/.test(i))return {score:12,label:'Moderate buyer-demand industry'};\n  if(i)return {score:9,label:'Industry identified; buyer demand requires research'};\n  return {score:4,label:'Industry missing'};\n}\nfunction listingReadinessReviewSignals(x){\n  const text=((x.context||'')+' '+(x.signal||'')).toLowerCase();\n  const ratingMatch=text.match(\/rating[:\\s]*([0-5](?:\\.\\d)?)\/i);\n  const reviewMatch=text.match(\/reviews?[:\\s]*([0-9,]+)\/i);\n  const rating=ratingMatch?parseFloat(ratingMatch[1]):(x.rating?parseFloat(x.rating):0);\n  const reviews=reviewMatch?parseInt(reviewMatch[1].replace(\/,\/g,''),10):(x.reviews?parseInt(x.reviews,10):0);\n  let score=0,reasons=[];\n  if(rating>=4.5){score+=10;reasons.push('Excellent public rating');}\n  else if(rating>=4){score+=7;reasons.push('Strong public rating');}\n  else if(rating>0){score+=3;reasons.push('Rating present but needs review');}\n  if(reviews>=100){score+=10;reasons.push('Large review footprint');}\n  else if(reviews>=30){score+=7;reasons.push('Meaningful review footprint');}\n  else if(reviews>0){score+=3;reasons.push('Some review history');}\n  if(\/strong review|strong local reputation|excellent reputation|local reputation\/.test(text)){score+=5;reasons.push('Reputation signal detected');}\n  return {score:Math.min(20,score),label:reasons.join('; ')||'Review\/reputation data missing'};\n}\nfunction listingReadinessOwnerSignals(x){\n  let score=0,reasons=[];\n  const ownerText=((x.owner||'')+' '+(x.ownerTitle||'')+' '+(x.context||'')+' '+JSON.stringify(x.apolloContacts||[])).toLowerCase();\n  if(x.owner){score+=8;reasons.push('Owner identified');}\n  if(\/owner|founder|president|ceo|chief executive|principal|managing partner\/.test(ownerText)){score+=9;reasons.push('Decision-maker title signal');}\n  if(x.ownerEmail){score+=5;reasons.push('Owner email available');}\n  if(x.ownerLinkedIn){score+=4;reasons.push('LinkedIn profile available');}\n  if(\/retirement|succession|burnout|fatigue|transition|legacy|exit\/.test(ownerText)){score+=7;reasons.push('Seller-transition signal detected');}\n  return {score:Math.min(25,score),label:reasons.join('; ')||'Owner\/succession signal missing'};\n}\nfunction listingReadinessScore(x){\n  if(!x)return {score:0,tier:'Low',probability:0,drivers:[],risks:[],action:'Select Prospect'};\n  ensureArrays(x);\n  let score=0,drivers=[],risks=[];\n  const years=parseInt(x.years||'0',10)||0;\n  const employees=parseInt(x.employees||'0',10)||0;\n  if(years>=20){score+=18;drivers.push('20+ years in business suggests possible transition horizon');}\n  else if(years>=10){score+=14;drivers.push('10+ years in business indicates established operation');}\n  else if(years>=5){score+=8;drivers.push('5+ years in business');}\n  else risks.push('Business age is missing or short');\n  if(employees>=8 && employees<=50){score+=12;drivers.push('Employee count suggests transferable operating base');}\n  else if(employees>50){score+=10;drivers.push('Larger employee base may appeal to strategic buyers');}\n  else if(employees>0){score+=5;drivers.push('Small owner-operated employee base');}\n  else risks.push('Employee count missing');\n  const demand=listingReadinessIndustryDemand(x.industry); score+=demand.score; drivers.push(demand.label);\n  const reviews=listingReadinessReviewSignals(x); score+=reviews.score; if(reviews.score)drivers.push(reviews.label); else risks.push(reviews.label);\n  const owner=listingReadinessOwnerSignals(x); score+=owner.score; if(owner.score)drivers.push(owner.label); else risks.push(owner.label);\n  const opp=x.opportunities?.[0]?.score||0;\n  const exit=x.assessments?.[0]?.score||0;\n  if(opp>=75){score+=8;drivers.push('High saved opportunity score');}\n  else if(opp>=60){score+=5;drivers.push('Moderate saved opportunity score');}\n  if(exit>=75){score+=8;drivers.push('Strong exit readiness assessment');}\n  else if(exit>=60){score+=5;drivers.push('Moderate exit readiness assessment');}\n  if(!opp)risks.push('Opportunity scorecard not completed');\n  if(!exit)risks.push('Exit readiness assessment not completed');\n  if(isDue(x.dueDate)){score+=4;drivers.push('Follow-up is due now');}\n  if((x.history||[]).length>=3){score+=3;drivers.push('Healthy activity history');}\n  score=Math.max(0,Math.min(100,Math.round(score)));\n  const tier=score>=85?'Very High':score>=75?'High':score>=60?'Medium':'Low';\n  const probability=Math.min(95,Math.max(15,Math.round(score*.92)));\n  let action='Educational Follow-Up';\n  if(score>=85)action='Call Within 7 Days';\n  else if(score>=75)action='Generate Outreach and Schedule Follow-Up';\n  else if(score>=60)action='Research Owner and Nurture';\n  return {score,tier,probability,drivers,risks,action};\n}\nfunction renderListingReadinessQueue(){\n  const box=$('listingReadinessQueue');\n  if(!box)return;\n  const rows=[...prospects].map(x=>({x,lr:listingReadinessScore(x)})).sort((a,b)=>b.lr.score-a.lr.score).slice(0,10);\n  if(!rows.length){box.innerHTML='<div class=\"empty-state\">No prospects yet.<\/div>';return;}\n  box.innerHTML=rows.map(r=>{\n    const cls=r.lr.score>=75?'high':r.lr.score>=60?'medium':'low';\n    return `<div class=\"queue-item readiness-card ${cls}\"><div class=\"readiness-score\">${r.lr.score}<\/div><div><b>${r.x.bizName}<\/b><br><small>${r.x.industry||'\u2014'} \u00b7 ${r.x.location||'\u2014'} \u00b7 ${r.lr.tier} readiness<\/small><br><span class=\"pill green\">${r.lr.probability}% listing probability<\/span><span class=\"pill blue\">${r.lr.action}<\/span><\/div><div class=\"quick-actions\"><button class=\"light\" onclick=\"selectProspect('${r.x.id}');showTab('intelligence',{target:document.querySelector('[onclick*=intelligence]')})\">Analyze<\/button><\/div><\/div>`;\n  }).join('');\n}\nfunction renderIntelligence(){\n  if(!$('intelligenceTab')) return;\n  renderListingReadinessQueue();\n  const x=p();\n  if(!x){\n    $('aiRecommendation').textContent='Select a prospect to generate listing readiness intelligence.';\n    $('aiPriority').textContent='0';\n    $('aiListing').textContent='0%';\n    $('aiUrgency').textContent='Low';\n    $('aiAction').textContent='\u2014';\n    $('aiRisks').textContent='\u2014';\n    $('aiDrivers').textContent='\u2014';\n    $('aiNextSteps').textContent='\u2014';\n    return;\n  }\n  const lr=listingReadinessScore(x);\n  $('aiPriority').textContent=lr.score;\n  $('aiListing').textContent=lr.probability+'%';\n  $('aiUrgency').textContent=lr.tier;\n  $('aiAction').textContent=lr.action;\n\n  $('aiRecommendation').textContent =\n    `${x.bizName} has a Listing Readiness Score of ${lr.score}\/100 (${lr.tier}) and an estimated ${lr.probability}% listing-probability profile.\\n\\nRecommended broker action: ${lr.action}.\\n\\nInterpretation: ${lr.score>=85?'This is a top-priority target. Move quickly with owner-specific outreach and a confidential valuation\/readiness conversation.':lr.score>=75?'This is a strong target. Complete owner research, generate outreach, and schedule a follow-up.':lr.score>=60?'This is a workable target. Continue research, add missing data, and nurture with education.':'This prospect needs more research before heavy pursuit.'}`;\n\n  $('aiDrivers').textContent = lr.drivers.length ? lr.drivers.map(d=>'\u2022 '+d).join('\\n') : 'No strong readiness drivers detected yet.';\n  $('aiRisks').textContent = lr.risks.length ? lr.risks.map(d=>'\u2022 '+d).join('\\n') : 'No major missing signals detected.';\n\n  $('aiNextSteps').textContent =\n    `1. ${lr.action}\\n2. ${x.owner?'Use saved owner\/contact details in outreach.':'Run Owner Discovery or Sales Navigator companion search.'}\\n3. ${x.opportunities?.length?'Refresh the opportunity score if new information is found.':'Complete the Opportunity Scorecard.'}\\n4. ${x.assessments?.length?'Use readiness findings in the seller conversation.':'Complete the Exit Readiness Assessment.'}\\n5. Update pipeline status and next follow-up date after the next interaction.`;\n}\nfunction saveListingReadinessToProspect(){\n  const x=p();\n  if(!x){alert('Select a prospect first.');return;}\n  const lr=listingReadinessScore(x);\n  x.listingReadiness=x.listingReadiness||[];\n  x.listingReadiness.unshift({date:new Date().toLocaleString(),...lr});\n  x.history.unshift(hist('AI Listing Readiness',`Listing Readiness ${lr.score}\/100 (${lr.tier}). Recommended action: ${lr.action}.`));\n  x.nextAction=lr.action;\n  $('nextAction').value=x.nextAction;\n  persist();renderAll();\n  alert('Listing readiness insight saved to this prospect.');\n}\nfunction exportListingReadinessReport(){\n  const rows=[...prospects].map(x=>({x,lr:listingReadinessScore(x)})).sort((a,b)=>b.lr.score-a.lr.score);\n  const selected=p();\n  const selectedText=selected?`\\nSELECTED PROSPECT\\n${selected.bizName}\\n${$('aiRecommendation')?.innerText||''}\\n\\nDRIVERS\\n${$('aiDrivers')?.innerText||''}\\n\\nRISKS\\n${$('aiRisks')?.innerText||''}\\n`:'';\n  const text=`AI Listing Readiness Engine v2.6 Report\\nGenerated: ${new Date().toLocaleString()}\\n\\nREADINESS RANKING\\n${rows.map((r,i)=>`${i+1}. ${r.x.bizName} \u2014 ${r.lr.score}\/100 (${r.lr.tier}) \u2014 ${r.lr.action}`).join('\\n')}\\n${selectedText}`;\n  const blob=new Blob([text],{type:'text\/plain;charset=utf-8'});\n  const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='ai-listing-readiness-report.txt';a.click();\n}\n\n\nfunction updateReport(){let x=p();$('rBiz').textContent=x?.bizName||val('bizName')||'Not selected';$('rIndustry').textContent=x?.industry||val('industry')||'\u2014';$('rLocation').textContent=x?.location||val('location')||'\u2014';$('rStage').textContent=x?.stage||val('stage')||'\u2014';let o=x?.opportunities?.[0]||lastOpp;let a=x?.assessments?.[0]||lastAssessment;$('rOpp').textContent=o?`${o.score}\/100 \u2014 ${o.category} \u2014 ${o.approach}`:'\u2014';$('rExit').textContent=a?`${a.score}\/100 \u2014 ${a.category} \u2014 ${a.timeline}`:'\u2014';$('rNext').textContent=a?.recs||o?.angle||'Generate scorecards and assessments to populate recommendations.'}\nfunction exportData(){let blob=new Blob([JSON.stringify(prospects,null,2)],{type:'application\/json'});let a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='ai-deal-sourcing-v5-complete-backup.json';a.click()}\nfunction importData(e){let f=e.target.files[0];if(!f)return;let r=new FileReader();r.onload=()=>{try{prospects=JSON.parse(r.result);persist();renderAll();alert('Import complete.')}catch(err){alert('Import failed.')}};r.readAsText(f)}\n\n\/* ===== v2.4 Pipeline & Follow-Up Manager ===== *\/\nfunction pmEnsure(x){\n  ensureArrays(x);\n  x.activities=x.activities||[];\n  if(!x.stage)x.stage='New Prospect';\n  return x;\n}\nfunction pmStageIs(x,names){return names.includes((x.stage||'').trim());}\nfunction pmLastActivityText(x){\n  pmEnsure(x);\n  const rows=[];\n  (x.activities||[]).forEach(a=>rows.push({date:a.date,type:a.type,text:a.note||''}));\n  (x.history||[]).forEach(h=>rows.push({date:h.date,type:h.type,text:h.text||''}));\n  if(!rows.length)return 'None';\n  rows.sort((a,b)=>new Date(b.date)-new Date(a.date));\n  return rows[0].date||'Recent';\n}\nfunction pmDaysSinceLastActivity(x){\n  pmEnsure(x);\n  const dates=[];\n  (x.activities||[]).forEach(a=>{if(a.date)dates.push(new Date(a.date))});\n  (x.history||[]).forEach(h=>{if(h.date)dates.push(new Date(h.date))});\n  if(!dates.length)return 999;\n  dates.sort((a,b)=>b-a);\n  return Math.max(0,Math.floor((new Date()-dates[0])\/86400000));\n}\nfunction pmCounts(){\n  const c={meetings:0,listings:0,won:0,lost:0,followups:0,contacted:0,interested:0};\n  prospects.forEach(x=>{\n    pmEnsure(x);\n    if(pmStageIs(x,['Meeting Scheduled','Meeting Booked']))c.meetings++;\n    if(pmStageIs(x,['Listing Opportunity','Listing Agreement','Active Listing','Under Contract']))c.listings++;\n    if(pmStageIs(x,['Closed Won','Closed']))c.won++;\n    if(pmStageIs(x,['Closed Lost']))c.lost++;\n    if(x.dueDate && isDue(x.dueDate))c.followups++;\n    if(pmStageIs(x,['Contacted','Follow-Up Scheduled','Interested','Conversation Started','Meeting Scheduled','Meeting Booked','Listing Opportunity','Listing Agreement','Active Listing','Under Contract','Closed Won','Closed Lost','Closed']))c.contacted++;\n    if(pmStageIs(x,['Interested','Conversation Started','Meeting Scheduled','Meeting Booked','Listing Opportunity','Listing Agreement','Active Listing','Under Contract','Closed Won']))c.interested++;\n  });\n  return c;\n}\nfunction pmSuggestedAction(x){\n  if(!x)return ['Select a prospect to view AI suggestions.'];\n  pmEnsure(x);\n  const days=pmDaysSinceLastActivity(x);\n  const due=x.dueDate && isDue(x.dueDate);\n  const pri=priorityScore(x);\n  const suggestions=[];\n  if(!x.apolloContacts || !x.apolloContacts.length){suggestions.push('Find and save an owner contact using Owner Discovery before launching outreach.');}\n  if(!x.outreach || !x.outreach.length){suggestions.push('Generate an outreach sequence and save it to this prospect.');}\n  if(due){suggestions.push('Follow-up is due now. Complete the scheduled next action: '+(x.nextAction||'follow up with the owner')+'.');}\n  if(days>=21 && !pmStageIs(x,['Closed Won','Closed Lost','Closed'])){suggestions.push('No recent activity for 21+ days. Send Follow-Up Email #2 or use LinkedIn touch.');}\n  if(pmStageIs(x,['New Prospect','Identified','Researched']) && pri>=70){suggestions.push('High-priority prospect still early-stage. Move to Contacted after first outreach.');}\n  if(pmStageIs(x,['Contacted','Follow-Up Scheduled']) && days>=7){suggestions.push('Contacted but no recent response. Use call + LinkedIn follow-up.');}\n  if(pmStageIs(x,['Interested','Conversation Started'])){suggestions.push('Interest detected. Schedule a discovery or valuation-readiness call.');}\n  if(pmStageIs(x,['Meeting Scheduled','Meeting Booked'])){suggestions.push('Prepare meeting agenda, seller questions, and valuation discussion points.');}\n  if(pmStageIs(x,['Listing Opportunity'])){suggestions.push('Move toward listing strategy: gather financials, seller goals, and confidentiality constraints.');}\n  if(!suggestions.length){suggestions.push('Continue normal cadence and keep the next action\/date updated.');}\n  return suggestions;\n}\nfunction pmMoveStage(stage){\n  const x=p(); if(!x){alert('Select a prospect first.');return;}\n  pmEnsure(x); x.stage=stage; $('stage').value=stage;\n  x.history.unshift(hist('Pipeline Status Updated','Status changed to '+stage+'.'));\n  persist(); renderAll();\n}\nfunction pmQuickAction(type){\n  const x=p(); if(!x){alert('Select a prospect first.');return;}\n  pmEnsure(x);\n  const note='Quick action logged from Pipeline Manager.';\n  x.activities.unshift({date:new Date().toLocaleString(),type,note});\n  x.history.unshift(hist(type,note));\n  if(type==='Email Sent' && ['New Prospect','Identified','Researched','Owner Identified','Outreach Generated'].includes(x.stage||''))x.stage='Contacted';\n  if(type==='LinkedIn Touch' && ['New Prospect','Identified','Researched','Owner Identified','Outreach Generated'].includes(x.stage||''))x.stage='Contacted';\n  if(type==='Call Made' && ['Contacted','Follow-Up Scheduled','Outreach Generated'].includes(x.stage||''))x.stage='Conversation Started';\n  if(type==='Response Received')x.stage='Interested';\n  $('stage').value=x.stage||'New Prospect';\n  persist(); renderAll();\n}\nfunction pmScheduleFollowUp(){\n  const x=p(); if(!x){alert('Select a prospect first.');return;}\n  pmEnsure(x);\n  const action=(val('pmNextAction')||val('nextAction')||'Follow up with owner').trim();\n  const date=val('pmDueDate')||val('dueDate');\n  if(!date){alert('Choose a follow-up date.');return;}\n  x.nextAction=action;\n  x.dueDate=date;\n  if(['Contacted','Outreach Generated','Conversation Started'].includes(x.stage||''))x.stage='Follow-Up Scheduled';\n  $('nextAction').value=action; $('dueDate').value=date; $('stage').value=x.stage||'Follow-Up Scheduled';\n  x.history.unshift(hist('Follow-Up Scheduled',action+' on '+date+'.'));\n  persist(); renderAll();\n}\nfunction pmRenderAISuggestions(x){\n  const box=$('pmAISuggestions'); if(!box)return;\n  if(!x){box.innerHTML='<div class=\"empty-state\">Select a prospect to see AI follow-up suggestions.<\/div>';return;}\n  const items=pmSuggestedAction(x);\n  box.innerHTML=items.map((s,i)=>`<div class=\"ai-suggestion\"><strong>Suggestion ${i+1}:<\/strong><br>${s}<\/div>`).join('');\n}\nfunction pmRenderTimeline(x){\n  const box=$('historyList'); if(!box)return;\n  if(!x){box.innerHTML='';return;}\n  pmEnsure(x);\n  const rows=[];\n  (x.history||[]).forEach(h=>rows.push({date:h.date,type:h.type,text:h.text||''}));\n  (x.activities||[]).forEach(a=>rows.push({date:a.date,type:a.type,text:a.note||'Activity logged.'}));\n  rows.sort((a,b)=>new Date(b.date)-new Date(a.date));\n  box.innerHTML=rows.length?rows.slice(0,40).map(h=>`<div class=\"timeline-item\"><b>${h.type}<\/b><small>${h.date}<\/small><p>${h.text||''}<\/p><\/div>`).join(''):'<div class=\"empty-state\">No activity yet. Use Quick Actions or add notes to build the timeline.<\/div>';\n}\nfunction pmNextFollowUpLabel(x){\n  if(!x||!x.dueDate)return '\u2014';\n  const d=daysUntil(x.dueDate);\n  if(d===null)return '\u2014';\n  if(d<0)return 'Overdue';\n  if(d===0)return 'Today';\n  if(d===1)return 'Tomorrow';\n  return x.dueDate;\n}\n\n\/* Override selected renderers for v2.4 *\/\nconst _v23RenderMetrics=renderMetrics;\nrenderMetrics=function(){\n  _v23RenderMetrics();\n  const c=pmCounts();\n  if($('mMeetings'))$('mMeetings').textContent=c.meetings;\n  if($('mListings'))$('mListings').textContent=c.listings;\n  if($('mWon'))$('mWon').textContent=c.won;\n};\nconst _v23UpdateLaunchDashboard=updateLaunchDashboard;\nupdateLaunchDashboard=function(syncText){\n  _v23UpdateLaunchDashboard(syncText);\n  const c=pmCounts();\n  if($('launchMeetings'))$('launchMeetings').textContent=c.meetings;\n  if($('launchListings'))$('launchListings').textContent=c.listings;\n  if($('launchWon'))$('launchWon').textContent=c.won;\n};\nrenderPipeline=function(){\n  const x=p();\n  if($('pipelineDetail'))$('pipelineDetail').textContent=x?`Business: ${x.bizName}\\nStatus: ${x.stage||'New Prospect'}\\nOwner: ${x.owner||'\u2014'}${x.ownerTitle?' \u2014 '+x.ownerTitle:''}\\nNext Action: ${x.nextAction||'\u2014'}\\nDue Date: ${x.dueDate||'\u2014'}\\nPriority Score: ${priorityScore(x)}\/100`:'Select a prospect to view pipeline history.';\n  if($('stageBtns'))$('stageBtns').innerHTML=stages.map(s=>`<button class=\"${x&&x.stage===s?'primary':'light'}\" onclick=\"setStage('${s}')\">${s}<\/button>`).join('');\n  if($('pmCurrentStatus'))$('pmCurrentStatus').textContent=x?(x.stage||'New Prospect'):'\u2014';\n  if($('pmNextFollowUp'))$('pmNextFollowUp').textContent=pmNextFollowUpLabel(x);\n  if($('pmLastActivity'))$('pmLastActivity').textContent=x?pmLastActivityText(x):'\u2014';\n  if(x){ if($('pmNextAction'))$('pmNextAction').value=x.nextAction||''; if($('pmDueDate'))$('pmDueDate').value=x.dueDate||''; }\n  pmRenderAISuggestions(x);\n  pmRenderTimeline(x);\n};\nconst _v23RenderPipelineBoard=renderPipelineBoard;\nrenderPipelineBoard=function(){\n  const box=$('pipelineBoard'); if(!box)return;\n  const showStages=['New Prospect','Owner Identified','Contacted','Follow-Up Scheduled','Interested','Meeting Scheduled','Listing Opportunity','Active Listing','Closed Won','Closed Lost'];\n  box.innerHTML=showStages.map(s=>{\n    const stageItems=prospects.filter(x=>(x.stage||'New Prospect')===s);\n    const items=stageItems.slice(0,6);\n    return `<div class=\"kanban-col\"><h4>${s} (${stageItems.length})<\/h4>${items.map(x=>`<div class=\"kcard\" onclick=\"selectProspect('${x.id}')\"><b>${x.bizName}<\/b><small>${x.industry||'\u2014'} \u00b7 Priority ${priorityScore(x)} \u00b7 ${x.dueDate?pmNextFollowUpLabel(x):'No follow-up'}<\/small><\/div>`).join('')||'<small>No prospects<\/small>'}<\/div>`;\n  }).join('');\n};\nconst _v23RenderPriorityQueue=renderPriorityQueue;\nrenderPriorityQueue=function(){\n  const box=$('priorityQueue'); if(!box)return;\n  const rows=sortedByPriority().slice(0,8);\n  if(!rows.length){box.innerHTML='<div class=\"notice\">No prospects yet. Add a prospect to build your daily work queue.<\/div>';return;}\n  box.innerHTML=rows.map(r=>{\n    const x=r.p, opp=x.opportunities?.[0]?.score, ex=x.assessments?.[0]?.score;\n    const suggestion=pmSuggestedAction(x)[0];\n    return `<div class=\"queue-item\"><div class=\"priority-score\">${r.score}<\/div><div><b>${x.bizName}<\/b><br><small>${x.stage||'New Prospect'} \u00b7 ${x.industry||'Industry not set'} \u00b7 ${x.location||'Location not set'}<\/small><br><span class=\"pill blue\">Opp ${opp||'\u2014'}<\/span><span class=\"pill green\">Exit ${ex||'\u2014'}<\/span>${isDue(x.dueDate)?'<span class=\"pill red\">Follow-Up Due<\/span>':''}<p style=\"font-size:12px;margin-top:6px\"><strong>AI Next:<\/strong> ${suggestion}<\/p><\/div><div class=\"quick-actions\"><button class=\"light\" onclick=\"goModule('pipeline','${x.id}')\">Manage<\/button><button class=\"light\" onclick=\"goModule('sequence','${x.id}')\">Outreach<\/button><button class=\"light\" onclick=\"goModule('followup','${x.id}')\">Follow-Up<\/button><\/div><\/div>`;\n  }).join('');\n};\n\n\n\/* v2.9 Member Login + User AI API Key Integration *\/\nwindow.ADS_USER_AI_SETTINGS=window.ADS_USER_AI_SETTINGS||{};\nfunction adsLocalKeyName(){\n  const cfg=window.ADS_CLOUD_STORAGE||{};\n  const uid=cfg.userId||cfg.user_id||'guest';\n  return 'ads_user_ai_key_'+uid;\n}\nfunction adsSettingsName(){return adsLocalKeyName()+'_settings';}\nfunction adsIsWordPressLoggedIn(){\n  const cfg=window.ADS_CLOUD_STORAGE||{};\n  return !!(cfg.enabled||cfg.userId||cfg.user_id||cfg.nonce||(window.wpApiSettings&&window.wpApiSettings.nonce)||document.body.classList.contains('logged-in')||document.querySelector('#wpadminbar'));\n}\nfunction adsGetSavedApiSettings(){\n  try{return JSON.parse(localStorage.getItem(adsSettingsName())||'{}')||{};}catch(e){return {};}\n}\nfunction adsGetSavedApiKey(){\n  try{return localStorage.getItem(adsLocalKeyName())||'';}catch(e){return '';}\n}\nfunction adsMaskedKey(key){return key?key.slice(0,4)+'\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022'+key.slice(-4):'No API key saved on this browser.';}\nfunction adsRequireMember(){\n  const ok=adsIsWordPressLoggedIn();\n  document.body.classList.toggle('ads-member-blocked',!ok);\n  const gate=$('memberAuthGate'); if(gate)gate.classList.toggle('show',!ok);\n  const st=$('adsMemberStatus'); if(st){st.textContent=ok?'WordPress member detected':'WordPress login required';st.className='cloud-badge '+(ok?'ok':'risk');}\n  return ok;\n}\nfunction adsRequireAiKey(silent=false){\n  const key=adsGetSavedApiKey();\n  document.body.classList.toggle('ads-ai-key-required',!key);\n  const panel=$('userApiKeyPanel'); if(panel)panel.classList.toggle('locked',!key);\n  const st=$('adsAiKeyStatus'); if(st){st.textContent=key?'AI key saved':'AI key required';st.className='cloud-badge '+(key?'ok':'risk');}\n  const mask=$('adsAiKeyMask'); if(mask)mask.textContent=adsMaskedKey(key);\n  const setup=$('apiKeySetupStatus'); if(setup)setup.textContent=key?'AI key is saved for this logged-in member\/browser.':'AI key is required before AI-assisted API calls.';\n  if(!key&&!silent)alert('Please add your AI service API key first.');\n  return !!key;\n}\nfunction adsLoadAiFields(){\n  const cfg=adsGetSavedApiSettings();\n  if($('adsAiProvider'))$('adsAiProvider').value=cfg.provider||'openai';\n  if($('adsAiModel'))$('adsAiModel').value=cfg.model||'gpt-4.1-mini';\n  if($('adsAiEndpoint'))$('adsAiEndpoint').value=cfg.endpoint||'';\n  if($('adsAiApiKey'))$('adsAiApiKey').value='';\n}\nfunction adsSaveUserApiKey(){\n  if(!adsRequireMember())return;\n  const key=val('adsAiApiKey')||adsGetSavedApiKey();\n  if(!key){alert('Paste your AI service API key first.');return;}\n  const settings={provider:val('adsAiProvider')||'openai',model:val('adsAiModel')||'gpt-4.1-mini',endpoint:val('adsAiEndpoint'),savedAt:new Date().toISOString()};\n  try{\n    localStorage.setItem(adsLocalKeyName(),key);\n    localStorage.setItem(adsSettingsName(),JSON.stringify(settings));\n    window.ADS_USER_AI_SETTINGS={...settings,apiKey:key};\n    if(window.adsVaultUnlocked&&window.adsVaultPassword){window.adsMemberAiSettings=settings;window.adsMemberAiKeySaved=true;cloudSaveNow(true);}\n    if($('adsAiApiKey'))$('adsAiApiKey').value='';\n    adsRequireAiKey(true);\n    alert('AI service API key saved for this member on this browser.');\n  }catch(e){alert('Could not save API key in this browser: '+e.message);}\n}\nfunction adsForgetUserApiKey(){\n  if(!confirm('Forget the saved AI API key on this browser?'))return;\n  try{localStorage.removeItem(adsLocalKeyName());localStorage.removeItem(adsSettingsName());}catch(e){}\n  window.ADS_USER_AI_SETTINGS={};\n  adsRequireAiKey(true);adsLoadAiFields();\n}\nfunction adsAiHeaders(extra={}){\n  const key=adsGetSavedApiKey();\n  const settings=adsGetSavedApiSettings();\n  const h=Object.assign({},extra);\n  if(key){h['Authorization']='Bearer '+key;h['X-AI-Service-API-Key']=key;}\n  if(settings.provider)h['X-AI-Service-Provider']=settings.provider;\n  if(settings.model)h['X-AI-Service-Model']=settings.model;\n  return h;\n}\nasync function adsAIRequest(endpoint,payload={}){\n  if(!adsRequireMember()||!adsRequireAiKey())throw new Error('Member login and AI API key are required.');\n  const settings=adsGetSavedApiSettings();\n  const url=endpoint||settings.endpoint||'\/wp-json\/ai-deal-sourcing\/v1\/ai-complete';\n  const headers=adsAiHeaders({'Content-Type':'application\/json'});\n  if(window.ADS_CLOUD_STORAGE&&window.ADS_CLOUD_STORAGE.nonce)headers['X-WP-Nonce']=window.ADS_CLOUD_STORAGE.nonce;\n  const res=await fetch(url,{method:'POST',credentials:'same-origin',headers,body:JSON.stringify({...payload,model:payload.model||settings.model})});\n  const data=await res.json().catch(()=>({}));\n  if(!res.ok)throw new Error(data.message||('HTTP '+res.status));\n  return data;\n}\nasync function adsTestUserApiKey(){\n  if(!adsRequireMember()||!adsRequireAiKey())return;\n  const settings=adsGetSavedApiSettings();\n  const endpoint=settings.endpoint||'\/wp-json\/ai-deal-sourcing\/v1\/ai-complete';\n  const setup=$('apiKeySetupStatus'); if(setup)setup.textContent='Testing AI key through '+endpoint+' ...';\n  try{\n    const data=await adsAIRequest(endpoint,{prompt:'Return the word OK only.',max_tokens:5});\n    if(setup)setup.textContent='AI key test completed. Response received from endpoint.';\n    alert('AI key test completed.');\n  }catch(err){\n    if(setup)setup.textContent='AI key test failed or endpoint not installed yet: '+err.message;\n    alert('AI key test failed or endpoint is not installed yet: '+err.message);\n  }\n}\nasync function adsMemberLogin(){\n  const user=val('memberLoginUser'), pass=val('memberLoginPass');\n  if(!user||!pass){alert('Enter your WordPress user ID\/email and password.');return;}\n  const status=$('memberLoginStatus'); if(status)status.textContent='Logging in through WordPress...';\n  try{\n    const res=await fetch('\/wp-json\/ai-deal-sourcing\/v1\/member-login',{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application\/json'},body:JSON.stringify({username:user,password:pass})});\n    const data=await res.json().catch(()=>({}));\n    if(!res.ok)throw new Error(data.message||('HTTP '+res.status));\n    if(status)status.textContent='Login successful. Reloading workspace...';\n    location.reload();\n  }catch(err){\n    if(status)status.textContent='Portal login endpoint is not available or login failed. Use your normal WordPress login page. '+err.message;\n    alert('Login endpoint unavailable or login failed. Use the normal WordPress portal login if this endpoint is not installed.');\n  }\n}\nfunction adsOpenWpLogin(){\n  const next=encodeURIComponent(location.href);\n  location.href='\/wp-login.php?redirect_to='+next;\n}\nconst _adsOriginalCloudSaveNow=cloudSaveNow;\ncloudSaveNow=async function(silent=false){\n  if(window.adsVaultUnlocked&&window.adsVaultPassword){\n    window.adsMemberAiSettings=adsGetSavedApiSettings();\n    window.adsMemberAiKeySaved=!!adsGetSavedApiKey();\n  }\n  return _adsOriginalCloudSaveNow(silent);\n};\nconst _adsOriginalVaultEncryptObject=vaultEncryptObject;\nvaultEncryptObject=async function(obj,password,existingSalt){\n  obj=obj||{};\n  obj.aiSettings=window.adsMemberAiSettings||adsGetSavedApiSettings();\n  obj.aiKeySaved=!!adsGetSavedApiKey();\n  return _adsOriginalVaultEncryptObject(obj,password,existingSalt);\n};\nconst _adsOriginalVaultUnlock=vaultUnlock;\nvaultUnlock=async function(){\n  await _adsOriginalVaultUnlock();\n  adsRequireMember();adsRequireAiKey(true);adsLoadAiFields();\n};\nfunction adsInitAccessLayer(){\n  adsRequireMember();adsLoadAiFields();adsRequireAiKey(true);\n  setTimeout(function(){adsRequireMember();adsRequireAiKey(true);},600);\n}\n\n\n\/* v2.10 WordPress-login-only workspace override\n   WordPress membership is the only password. The app derives an internal browser-side workspace key\n   from the logged-in WordPress user context so members are never asked to create a second password. *\/\nfunction adsMemberWorkspaceSecret(){\n  const cfg=window.ADS_CLOUD_STORAGE||{};\n  const user=(cfg.userId||cfg.user_id||cfg.userEmail||cfg.user_email||cfg.recordKey||'wp-member').toString();\n  const host=(location&&location.host?location.host:'wordpress-site');\n  return 'ads-member-workspace-v2.10|'+host+'|'+user+'|360-biz-brokers';\n}\n\nvaultPromptPassword=async function(mode){\n  return adsMemberWorkspaceSecret();\n};\n\nvaultUnlock=async function(){\n  try{\n    if(!adsRequireMember())return;\n    if(!(window.ADS_CLOUD_STORAGE&&window.ADS_CLOUD_STORAGE.enabled)){\n      window.adsVaultPassword=adsMemberWorkspaceSecret();\n      window.adsVaultUnlocked=true;\n      cloudSetStatus('Member workspace ready','ok');\n      renderAll();\n      return;\n    }\n    const cfg=window.ADS_CLOUD_STORAGE;\n    const url=cfg.loadUrl+'?record_key='+encodeURIComponent(cloudVaultRecordKey());\n    const result=await cloudRequest(url);\n    const encrypted=cloudExtractEncrypted(result);\n    const pw=adsMemberWorkspaceSecret();\n    if(encrypted&&encrypted.ciphertext){\n      try{\n        const obj=await vaultDecryptObject(encrypted,pw);\n        window.adsVaultPassword=pw;\n        window.adsVaultSalt=encrypted.salt;\n        window.adsVaultUnlocked=true;\n        prospects=Array.isArray(obj.prospects)?obj.prospects:[];\n        if(obj.aiSettings&&!localStorage.getItem(adsSettingsName()))localStorage.setItem(adsSettingsName(),JSON.stringify(obj.aiSettings));\n        selectedId=null;\n        renderAll();\n        cloudSetStatus('Member workspace opened: '+prospects.length+' records','ok');\n      }catch(decryptErr){\n        alert('This workspace was created with the older separate Workspace Password version. Export\/import or reset that old vault once, then this WordPress-login-only version will use only the member login going forward.');\n        cloudSetStatus('Older workspace password detected','risk');\n      }\n    }else{\n      window.adsVaultPassword=pw;\n      window.adsVaultSalt=null;\n      window.adsVaultUnlocked=true;\n      prospects=[];\n      selectedId=null;\n      renderAll();\n      await cloudSaveNow(true);\n      cloudSetStatus('New member workspace created','ok');\n    }\n    adsRequireMember();adsRequireAiKey(true);adsLoadAiFields();\n  }catch(err){\n    window.adsVaultUnlocked=false;\n    cloudSetStatus('Member workspace open failed','risk');\n    alert('Member workspace could not open. Please confirm the WordPress user is logged in and storage is configured. '+err.message);\n  }\n};\n\nvaultLock=function(){\n  if(!confirm('Lock this member workspace on this device now?'))return;\n  window.adsVaultPassword='';\n  window.adsVaultUnlocked=false;\n  prospects=[];\n  selectedId=null;\n  renderAll();\n  cloudSetStatus('Member Workspace locked','warn');\n};\n\nconst _adsV210OriginalMemberLogin=adsMemberLogin;\nadsMemberLogin=function(){\n  adsOpenWpLogin();\n};\n\nfunction adsTestUserApiKey(){\n  alert('Your AI key is saved when you click Save My API Key. No endpoint test is needed for members.');\n}\n\n\nrenderQs();renderAll();\nif(typeof cloudInit==='function'){cloudInit();}\nif(typeof adsInitAccessLayer==='function'){adsInitAccessLayer();}\n\ndocument.addEventListener('DOMContentLoaded',function(){\n  try{\n    const wpName=document.querySelector('#wp-admin-bar-my-account .display-name');\n    if(wpName&&window.ADS_CLOUD_STORAGE&&!window.ADS_CLOUD_STORAGE.userDisplayName){\n      window.ADS_CLOUD_STORAGE.userDisplayName=wpName.textContent.trim();\n    }\n    if(typeof updateLaunchDashboard==='function')updateLaunchDashboard();\n  }catch(e){}\n});\n\n<\/script>\n<\/body>\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>AI Assisted Deals Sourcing Pro\u2122 | v2.10 WordPress Login Only + User AI API Key | Powered by 360 Biz Brokers Member Login Required This&#8230;<\/p>","protected":false},"author":3,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1475","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.5 (Yoast SEO v26.5) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>AI Assisted Deals Sourcing - External User - 360 Biz Brokers<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/360bizbrokers.com\/pt\/deals-sourcing-v2\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"AI Assisted Deals Sourcing - External User\" \/>\n<meta property=\"og:description\" content=\"AI Assisted Deals Sourcing Pro\u2122 | v2.10 WordPress Login Only + User AI API Key | Powered by 360 Biz Brokers Member Login Required This...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/360bizbrokers.com\/pt\/deals-sourcing-v2\/\" \/>\n<meta property=\"og:site_name\" content=\"360 Biz Brokers\" \/>\n<meta property=\"article:modified_time\" content=\"2026-06-22T13:33:35+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. tempo de leitura\" \/>\n\t<meta name=\"twitter:data1\" content=\"65 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/360bizbrokers.com\/deals-sourcing-v2\/\",\"url\":\"https:\/\/360bizbrokers.com\/deals-sourcing-v2\/\",\"name\":\"AI Assisted Deals Sourcing - External User - 360 Biz Brokers\",\"isPartOf\":{\"@id\":\"https:\/\/360bizbrokers.com\/#website\"},\"datePublished\":\"2026-06-22T13:02:21+00:00\",\"dateModified\":\"2026-06-22T13:33:35+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/360bizbrokers.com\/deals-sourcing-v2\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/360bizbrokers.com\/deals-sourcing-v2\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/360bizbrokers.com\/deals-sourcing-v2\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/360bizbrokers.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"AI Assisted Deals Sourcing &#8211; External User\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/360bizbrokers.com\/#website\",\"url\":\"https:\/\/360bizbrokers.com\/\",\"name\":\"Florida 360 Business Brokers\",\"description\":\"Buy &amp; Sell Businesses Advisory\",\"publisher\":{\"@id\":\"https:\/\/360bizbrokers.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/360bizbrokers.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pt-BR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/360bizbrokers.com\/#organization\",\"name\":\"Florida 360 Business Brokers\",\"url\":\"https:\/\/360bizbrokers.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/360bizbrokers.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/360bizbrokers.com\/wp-content\/uploads\/2025\/12\/LOGO-FLORIDA-360-BUSINESS-BROKERS.jpg\",\"contentUrl\":\"https:\/\/360bizbrokers.com\/wp-content\/uploads\/2025\/12\/LOGO-FLORIDA-360-BUSINESS-BROKERS.jpg\",\"width\":1080,\"height\":1080,\"caption\":\"Florida 360 Business Brokers\"},\"image\":{\"@id\":\"https:\/\/360bizbrokers.com\/#\/schema\/logo\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"AI Assisted Deals Sourcing - External User - 360 Biz Brokers","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/360bizbrokers.com\/pt\/deals-sourcing-v2\/","og_locale":"pt_BR","og_type":"article","og_title":"AI Assisted Deals Sourcing - External User","og_description":"AI Assisted Deals Sourcing Pro\u2122 | v2.10 WordPress Login Only + User AI API Key | Powered by 360 Biz Brokers Member Login Required This...","og_url":"https:\/\/360bizbrokers.com\/pt\/deals-sourcing-v2\/","og_site_name":"360 Biz Brokers","article_modified_time":"2026-06-22T13:33:35+00:00","twitter_card":"summary_large_image","twitter_misc":{"Est. tempo de leitura":"65 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/360bizbrokers.com\/deals-sourcing-v2\/","url":"https:\/\/360bizbrokers.com\/deals-sourcing-v2\/","name":"AI Assisted Deals Sourcing - External User - 360 Biz Brokers","isPartOf":{"@id":"https:\/\/360bizbrokers.com\/#website"},"datePublished":"2026-06-22T13:02:21+00:00","dateModified":"2026-06-22T13:33:35+00:00","breadcrumb":{"@id":"https:\/\/360bizbrokers.com\/deals-sourcing-v2\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/360bizbrokers.com\/deals-sourcing-v2\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/360bizbrokers.com\/deals-sourcing-v2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/360bizbrokers.com\/"},{"@type":"ListItem","position":2,"name":"AI Assisted Deals Sourcing &#8211; External User"}]},{"@type":"WebSite","@id":"https:\/\/360bizbrokers.com\/#website","url":"https:\/\/360bizbrokers.com\/","name":"Florida 360 Business Brokers","description":"Buy &amp; Sell Businesses Advisory","publisher":{"@id":"https:\/\/360bizbrokers.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/360bizbrokers.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pt-BR"},{"@type":"Organization","@id":"https:\/\/360bizbrokers.com\/#organization","name":"Florida 360 Business Brokers","url":"https:\/\/360bizbrokers.com\/","logo":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/360bizbrokers.com\/#\/schema\/logo\/image\/","url":"https:\/\/360bizbrokers.com\/wp-content\/uploads\/2025\/12\/LOGO-FLORIDA-360-BUSINESS-BROKERS.jpg","contentUrl":"https:\/\/360bizbrokers.com\/wp-content\/uploads\/2025\/12\/LOGO-FLORIDA-360-BUSINESS-BROKERS.jpg","width":1080,"height":1080,"caption":"Florida 360 Business Brokers"},"image":{"@id":"https:\/\/360bizbrokers.com\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/360bizbrokers.com\/pt\/wp-json\/wp\/v2\/pages\/1475","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/360bizbrokers.com\/pt\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/360bizbrokers.com\/pt\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/360bizbrokers.com\/pt\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/360bizbrokers.com\/pt\/wp-json\/wp\/v2\/comments?post=1475"}],"version-history":[{"count":0,"href":"https:\/\/360bizbrokers.com\/pt\/wp-json\/wp\/v2\/pages\/1475\/revisions"}],"wp:attachment":[{"href":"https:\/\/360bizbrokers.com\/pt\/wp-json\/wp\/v2\/media?parent=1475"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}