Files
html/growth-engine-v2.html

1964 lines
160 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Growth Engine v3 — WEVAL Consulting</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=Outfit:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
:root{--bg:#06090f;--bg2:#0c1120;--bg3:#131b2e;--bg4:#1a2540;--gold:#d4a853;--gold2:#e8c36a;--gd:rgba(212,168,83,.12);--em:#34d399;--ed:rgba(52,211,153,.12);--sa:#3b82f6;--sd:rgba(59,130,246,.12);--co:#f97066;--cld:rgba(249,112,102,.12);--vi:#a78bfa;--vd:rgba(167,139,250,.12);--cy:#22d3ee;--cyd:rgba(34,211,238,.12);--ro:#fb7185;--rd:rgba(251,113,133,.12);--am:#fbbf24;--ad:rgba(251,191,36,.12);--t1:#f0ece4;--t2:#9ca3af;--t3:#4b5563;--brd:#1e293b;--r:10px;--fd:'DM Serif Display',Georgia,serif;--fb:'Outfit',system-ui,sans-serif;--fm:'JetBrains Mono',monospace}
*{box-sizing:border-box;margin:0;padding:0}body{font-family:var(--fb);background:var(--bg);color:var(--t1);min-height:100vh;overflow-x:hidden}
.amb{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}.orb{position:absolute;border-radius:50%;filter:blur(120px);opacity:.12;animation:dr 20s ease-in-out infinite}.o1{width:600px;height:600px;background:var(--gold);top:-10%;left:-5%}.o2{width:500px;height:500px;background:var(--sa);bottom:-10%;right:-5%;animation-delay:-7s}.o3{width:400px;height:400px;background:var(--em);top:40%;left:50%;animation-delay:-14s}@keyframes dr{0%,100%{transform:translate(0,0)}33%{transform:translate(30px,-20px)}66%{transform:translate(-20px,30px)}}
.nz{position:fixed;inset:0;z-index:1;pointer-events:none;opacity:.03;background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}
.wr{position:relative;z-index:2}
.hd{display:flex;align-items:center;gap:14px;padding:12px 20px;background:rgba(12,17,32,.9);backdrop-filter:blur(20px);border-bottom:1px solid var(--brd);position:relative;z-index:10}
.hd-l{font-family:var(--fd);font-size:20px;color:var(--gold)}.hd-l span{color:var(--t3);font-size:11px;font-family:var(--fb);margin-left:6px}
.hd-k{display:flex;gap:10px;margin-left:auto}.hd-k a{color:var(--t3);font-size:9px;text-decoration:none;font-weight:600;letter-spacing:.5px;text-transform:uppercase;transition:.2s}.hd-k a:hover{color:var(--gold)}
.sb{padding:5px 12px;border-radius:6px;border:1px solid var(--gd);background:var(--gd);color:var(--gold);font-size:10px;font-family:var(--fb);font-weight:600;cursor:pointer;transition:.3s;display:flex;align-items:center;gap:4px}.sb:hover{background:var(--gold);color:var(--bg)}.sb .ic{transition:transform .4s}.sb:hover .ic{transform:rotate(180deg)}
.nv{display:flex;gap:0;padding:0 12px;background:rgba(12,17,32,.7);backdrop-filter:blur(12px);border-bottom:1px solid var(--brd);overflow-x:auto}.nv::-webkit-scrollbar{display:none}
.vt{padding:9px 12px;font-size:10px;color:var(--t3);cursor:pointer;border-bottom:2px solid transparent;transition:.2s;white-space:nowrap;font-weight:500;display:flex;align-items:center;gap:4px}.vt .dt{width:4px;height:4px;border-radius:50%}.vt.on{color:var(--t1);border-bottom-color:var(--gold);font-weight:600}.vt:hover{color:var(--t1)}.vt .ct{font-size:8px;font-family:var(--fm);background:var(--bg4);padding:1px 4px;border-radius:3px}
.mn{max-width:1440px;margin:0 auto;padding:18px 20px}.sc{display:none}.sc.on{display:block;animation:fi .3s ease}@keyframes fi{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}
.mr{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:7px;margin-bottom:18px}.mc{background:var(--bg2);border:1px solid var(--brd);border-radius:8px;padding:10px;position:relative;overflow:hidden}.mc::before{content:'';position:absolute;top:0;left:0;right:0;height:2px}
.mc.g::before{background:linear-gradient(90deg,var(--gold),transparent)}.mc.e::before{background:linear-gradient(90deg,var(--em),transparent)}.mc.s::before{background:linear-gradient(90deg,var(--sa),transparent)}.mc.c::before{background:linear-gradient(90deg,var(--co),transparent)}.mc.v::before{background:linear-gradient(90deg,var(--vi),transparent)}.mc.cy::before{background:linear-gradient(90deg,var(--cy),transparent)}.mc.r::before{background:linear-gradient(90deg,var(--ro),transparent)}.mc.a::before{background:linear-gradient(90deg,var(--am),transparent)}
.mc-l{font-size:8px;text-transform:uppercase;letter-spacing:.6px;color:var(--t3);margin-bottom:3px;font-weight:600}.mc-v{font-size:20px;font-weight:700;font-family:var(--fm);line-height:1}.mc-s{font-size:8px;color:var(--t2);margin-top:3px}
.cg{display:grid;grid-template-columns:repeat(auto-fill,minmax(270px,1fr));gap:9px;margin-bottom:18px}.cd{background:var(--bg2);border:1px solid var(--brd);border-radius:8px;padding:12px;transition:.2s}.cd:hover{border-color:rgba(212,168,83,.25);transform:translateY(-1px);box-shadow:0 4px 16px rgba(0,0,0,.25)}.cd-h{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:5px}.cd-t{font-size:12px;font-weight:600}.cd-d{font-size:9px;color:var(--t2);line-height:1.5;margin-bottom:7px}
.bd{font-size:8px;padding:2px 6px;border-radius:4px;font-weight:600}.bw{background:var(--gd);color:var(--gold)}.bp{background:var(--sd);color:var(--sa)}.bi{background:var(--vd);color:var(--vi)}.bh{background:var(--cld);color:var(--co)}.bs{background:var(--ed);color:var(--em)}
.rv{display:flex;align-items:center;gap:5px;margin-top:5px}.rv-b{flex:1;height:3px;border-radius:2px;background:var(--bg4);overflow:hidden}.rv-f{height:100%;border-radius:2px;transition:width .5s}.rv-v{font-size:9px;font-family:var(--fm);color:var(--gold);min-width:35px;text-align:right}
.ca{margin-top:6px;display:flex;flex-wrap:wrap;gap:3px}.at{font-size:8px;padding:2px 5px;border-radius:3px;background:var(--bg3);color:var(--t2);cursor:pointer;transition:.15s;border:1px solid transparent}.at:hover{border-color:var(--gold);color:var(--gold)}.at.dn{text-decoration:line-through;opacity:.3}
.kb{display:grid;grid-template-columns:repeat(4,1fr);gap:7px;margin-bottom:18px}@media(max-width:900px){.kb{grid-template-columns:1fr 1fr}}@media(max-width:600px){.kb{grid-template-columns:1fr}}
.kc{background:var(--bg2);border:1px solid var(--brd);border-radius:8px;overflow:hidden}.kh{padding:8px 9px;border-bottom:1px solid var(--brd);display:flex;align-items:center;gap:4px;font-size:10px;font-weight:600}.kh .n{font-family:var(--fm);font-size:8px;color:var(--t3);margin-left:auto}.kh.si{border-left:3px solid var(--vi)}.kh.sp{border-left:3px solid var(--sa)}.kh.sw{border-left:3px solid var(--gold)}.kh.ss{border-left:3px solid var(--em)}
.ki{padding:5px 9px;border-bottom:1px solid rgba(30,41,59,.25);font-size:9px;color:var(--t2);transition:.12s}.ki:hover{background:var(--bg3);color:var(--t1)}.ki .tg{font-size:7px;padding:1px 3px;border-radius:2px;margin-left:2px;background:rgba(255,255,255,.04);color:var(--t3)}
.cns{display:grid;grid-template-columns:repeat(auto-fill,minmax(165px,1fr));gap:5px;margin-bottom:18px}.cn{background:var(--bg2);border:1px solid var(--brd);border-radius:7px;padding:8px;display:flex;align-items:center;gap:7px;transition:.15s;font-size:10px}.cn:hover{border-color:var(--em)}.cn-d{width:5px;height:5px;border-radius:50%;flex-shrink:0}.cn-d.up{background:var(--em);box-shadow:0 0 4px var(--em)}.cn-d.dn{background:var(--co);box-shadow:0 0 4px var(--co)}.cn-d.wr{background:var(--gold);box-shadow:0 0 4px var(--gold)}.cn-n{font-weight:500}.cn-p{font-size:8px;font-family:var(--fm);color:var(--t3);margin-left:auto}
.cb{background:var(--bg2);border:1px solid var(--brd);border-radius:8px;margin-bottom:18px;overflow:hidden}.ch{padding:10px 12px;border-bottom:1px solid var(--brd);display:flex;align-items:center;gap:6px;font-size:11px;font-weight:600}.ch .lv{width:5px;height:5px;border-radius:50%;background:var(--em);animation:gl 2s infinite}@keyframes gl{0%,100%{box-shadow:0 0 2px var(--em)}50%{box-shadow:0 0 7px var(--em)}}
.cm{padding:10px 12px;max-height:220px;overflow-y:auto;font-size:10px;line-height:1.6}.cm::-webkit-scrollbar{width:2px}.cm::-webkit-scrollbar-thumb{background:var(--bg4)}.mg{margin-bottom:7px;padding:6px 9px;border-radius:5px;animation:mi .2s ease}.mg.sy{background:var(--bg3);color:var(--t3);font-size:9px}.mg.ai{background:rgba(212,168,83,.05);border-left:2px solid var(--gold)}.mg.us{background:var(--bg4);text-align:right}@keyframes mi{from{opacity:0;transform:translateX(-4px)}to{opacity:1;transform:translateX(0)}}
.ci{display:flex;gap:6px;padding:8px 12px;border-top:1px solid var(--brd)}.ci input{flex:1;background:var(--bg3);border:1px solid var(--brd);border-radius:5px;padding:7px 9px;color:var(--t1);font-size:10px;font-family:var(--fb);outline:none;transition:.2s}.ci input:focus{border-color:var(--gold)}.ci button{padding:7px 14px;border-radius:5px;border:none;background:var(--gold);color:var(--bg);font-weight:600;font-size:10px;cursor:pointer}.ci button:hover{background:var(--gold2)}
.st{font-family:var(--fd);font-size:15px;color:var(--t1);margin-bottom:12px;display:flex;align-items:center;gap:6px}.st .ln{flex:1;height:1px;background:var(--brd)}
.tbl{width:100%;border-collapse:collapse;margin-bottom:14px;font-size:9px}.tbl th{text-align:left;padding:6px 7px;font-size:7px;text-transform:uppercase;letter-spacing:.6px;color:var(--t3);border-bottom:1px solid var(--brd);font-weight:600}.tbl td{padding:6px 7px;border-bottom:1px solid rgba(30,41,59,.25);color:var(--t2)}.tbl tr:hover td{background:var(--bg3);color:var(--t1)}
.sr{background:var(--bg2);border:1px solid var(--brd);border-radius:8px;padding:10px;margin-bottom:18px}.si2{padding:6px 0;border-bottom:1px solid rgba(30,41,59,.2)}.si2:last-child{border:none}.si2-t{font-size:10px;font-weight:500;color:var(--sa)}.si2-u{font-size:7px;font-family:var(--fm);color:var(--t3)}.si2-s{font-size:9px;color:var(--t2);margin-top:2px;line-height:1.4}
.spnr{display:inline-block;width:10px;height:10px;border:2px solid var(--brd);border-top-color:var(--gold);border-radius:50%;animation:spi .5s linear infinite}@keyframes spi{to{transform:rotate(360deg)}}
/* Plan90 */
.p90-w{margin-bottom:14px}.p90-h{font-weight:600;font-size:11px;color:var(--gold);margin-bottom:6px;padding-bottom:4px;border-bottom:1px solid var(--brd)}.p90-a{display:flex;align-items:center;gap:6px;padding:4px 0;font-size:9px;color:var(--t2)}.p90-a input{accent-color:var(--gold)}.p90-a.done{text-decoration:line-through;opacity:.4}
/* Social */
.soc{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:8px;margin-bottom:18px}.soc-c{background:var(--bg2);border:1px solid var(--brd);border-radius:8px;padding:12px;transition:.2s}.soc-c:hover{border-color:var(--sa)}.soc-h{font-size:11px;font-weight:600;margin-bottom:6px;display:flex;align-items:center;gap:6px}.soc-h .soc-ico{font-size:14px}.soc-stat{font-size:9px;color:var(--t2);line-height:1.6}.soc-api{font-size:8px;font-family:var(--fm);color:var(--t3);margin-top:6px;padding-top:4px;border-top:1px solid var(--brd)}
@media(max-width:768px){.hd{padding:8px 12px}.hd-l{font-size:16px}.hd-k{display:none}.nv{padding:0 8px}.vt{padding:7px 7px;font-size:9px}.mn{padding:10px}.mr{grid-template-columns:repeat(2,1fr)}.cg{grid-template-columns:1fr}}
/*WAVE-REPAIR-23AVR-V1-opus · patch minimal doctrine enrichir pas ecraser*/
html,body{overflow-x:hidden;overflow-y:auto;scrollbar-width:auto;scrollbar-color:#d4a853 #0c1120}
html::-webkit-scrollbar,body::-webkit-scrollbar{width:14px;height:14px}
html::-webkit-scrollbar-track,body::-webkit-scrollbar-track{background:#0c1120;border-left:1px solid rgba(212,168,83,.1)}
html::-webkit-scrollbar-thumb,body::-webkit-scrollbar-thumb{background:linear-gradient(180deg,#d4a853,#a57f2e);border-radius:7px;border:2px solid #0c1120;box-shadow:inset 0 0 3px rgba(0,0,0,.3)}
html::-webkit-scrollbar-thumb:hover,body::-webkit-scrollbar-thumb:hover{background:linear-gradient(180deg,#e6ba6a,#b8923a)}
.mn{padding-bottom:100px;overflow:visible}
#s-advisor{padding-bottom:160px;overflow:visible}
#s-advisor > div{overflow:visible}
#s-advisor pre{max-height:min(60vh,500px);overflow:auto;overscroll-behavior:auto;scrollbar-width:thin;scrollbar-color:#d4a853 #1a1f2e}
#s-advisor pre::-webkit-scrollbar{width:8px;height:8px}
#s-advisor pre::-webkit-scrollbar-track{background:#1a1f2e}
#s-advisor pre::-webkit-scrollbar-thumb{background:#d4a853;border-radius:4px}
/* Relax max-height v2 aggressifs (pour que contenus scrollables ne bloquent pas) */
#s-advisor [style*="max-height"]{max-height:none!important;overscroll-behavior:auto!important}
/* PAS DE background/border/padding sur #advisor-content > div !!! */
/* Laisse buildAdvisor garder ses styles inline */
/*/WAVE-REPAIR-23AVR-V1-opus*/
/* WAVE 306 opus-x-btn hide - doctrine zero chevauchement TR/BR */
.opus-x-btn{display:none!important;visibility:hidden!important;pointer-events:none!important}
/* WAVE 306 opus-x-btn hide - doctrine zero chevauchement TR/BR */
.opus-x-btn{display:none!important;visibility:hidden!important;pointer-events:none!important}
</style>
<script src="/widgets/audit-banner.js" defer></script>
<!-- DOCTRINE-60-UX-ENRICH direct-inject-20260424-130137 -->
<style id="doctrine60-ux-direct">
/* DOCTRINE-60-UX-ENRICH injected-direct */
body::before {
content: '';
position: fixed;
top: 0; left: 0; width: 100vw; height: 100vh;
background: radial-gradient(circle at 50% 50%, rgba(100,180,255,0.08), transparent 60%);
pointer-events: none;
z-index: -1;
}
.card, .kpi, .panel, .btn {
transition: all 0.3s cubic-bezier(0.2,0,0.1,1);
}
.card:hover, .kpi:hover, .panel:hover {
box-shadow: 0 4px 20px rgba(100,180,255,0.2);
border-color: rgba(100,180,255,0.5);
}
@keyframes pulseD60 {
0%,100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.7; transform: scale(1.05); }
}
.pulse, .live-indicator, .active, .online {
animation: pulseD60 3s ease-in-out infinite;
}
.modal, .chat, .speech, .overlay {
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
}
.enter-stagger {
animation: enterStagD60 0.5s cubic-bezier(0.2,0,0.1,1) forwards;
}
@keyframes enterStagD60 {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
<!-- DOCTRINE-222-KILL-PULSED60 -->
<style>
@keyframes pulseD60 { 0%,100%,50% { opacity: 1; transform: scale(1); } }
.pulse, .live-indicator, .active, .online { animation: none !important; }
</style>
<!-- END-DOCTRINE-222 -->
</head>
<body>
<div class="amb"><div class="orb o1"></div><div class="orb o2"></div><div class="orb o3"></div></div>
<div class="nz"></div>
<div class="wr">
<div class="hd">
<div class="hd-l">Growth Engine <span>v3 — WEVAL Consulting</span></div>
<div class="hd-k"><a href="/wevia-master.html">Master</a><a href="/director.html">Director</a><a href="/crm.html">CRM</a><a href="/growth-engine.html">v1</a><a href="/growth-advisor-v3.html" style="color:#d4a853;font-weight:600">Advisor v3</a></div>
<button class="sb" onclick="fullScan()"><span class="ic">&#x21BB;</span> Scan All</button>
</div>
<div class="nv" id="nav"></div>
<div class="mn" id="mn"></div>
</div>
<script>
const API='/api/growth-engine-api.php',WV='/api/wevia-master-api.php';
const SN={idea:'Idées',plan:'Planifié',wip:'En cours',sign:'Signé'};
const SC={idea:'si',plan:'sp',wip:'sw',sign:'ss'};
// ═══════════ 8 VERTICALS — ENRICHED FROM V1+V2+ARCHI ═══════════
const V={
consulting:{l:'Consulting',ic:'em',o:[
{n:'Vistex SAP Maghreb',d:'Lead protection + conseil SAP pricing. Cosumar, Carrefour, OCP. Addendum Section 8.B + Section 3.d. Contacts: Olga Vanurina, Joe Golemba, Udo Hannemann.',r:200000,s:'wip',b:'bh',a:['Signer Lead Protection Addendum','RDV Olga Vanurina','Proposition Cosumar','Section 6.c.i Portal argument']},
{n:'Audit Maturité Digitale PME',d:'Framework McKinsey DQ adapté Maroc. Assessment 0-100 benchmark sectoriel. BCG DAI + DQ combo.',r:80000,s:'plan',b:'bp',a:['Framework scoring','Landing page','LinkedIn prospection','Template rapport']},
{n:'Consulting Cloud Migration',d:'Migration on-prem → cloud. Arrow/Scaleway partnership. Omar Belchkar, Julien Bossu contacts.',r:120000,s:'wip',b:'bw',a:['Onboarding ArrowSphere','Offre packagée','3 prospects','Cheikh Gassama Scaleway']},
{n:'Conseil Stratégie IA PME',d:'Diagnostic IA + roadmap. 50K MAD/mission. Cible: industriels Maghreb.',r:60000,s:'idea',b:'bi',a:['Offre diagnostic','3 PME pilotes','Webinaire CGEM']},
{n:'Value Stream Mapping',d:'VSM consulting pour optimisation processus. Page VSM existante dans Arsenal.',r:40000,s:'idea',b:'bi',a:['Connecter vsm-pipelines.html','Template VSM client','Offre packagée 30K']}
],m:[{l:'Pipeline',v:'500K',s:'5 deals',c:'e'},{l:'Partenaires',v:'3',s:'Vistex·Arrow·Scaleway',c:'g'},{l:'Conversion',v:'40%',s:'2/5 closing',c:'s'}]},
digital:{l:'Digital',ic:'sa',o:[
{n:'WEVIA SaaS freemium',d:'Arena multi-LLM + chat autonome. 626 tools. Free 100 msgs → 99€/mois. Blade v2.0 connecté.',r:200000,s:'plan',b:'bp',a:['Landing WeviaAI.ma','Setup Stripe','Beta 10 users','Blade v2 demo']},
{n:'API HCP Maghreb (Ethica)',d:'157K HCPs, 120K emails, 18K phones, 64K Google verified. 3000€/15K/mois. Pilot DRY_RUN prêt 7611 MG DZ.',r:300000,s:'wip',b:'bh',a:['Enrichir spécialités DZ','Scraper CNAM TN + CROMC','3 labos pilotes Kaouther','Consent.wevup.app']},
{n:'White-label WEVIA',d:'WEVIA brandé pour cabinets RH/legal/finance. Setup 5000€ + 500€/mois.',r:80000,s:'idea',b:'bi',a:['Package technique','Mockup client','5 cabinets cibles']},
{n:'SEO Module Hub',d:'Audit SEO auto via Plausible + SearXNG. Rapport client automatique.',r:40000,s:'plan',b:'bp',a:['SEO Module Hub page','Plausible bearer token','Template rapport']},
{n:'Dev Apps sur mesure',d:'Apps web/mobile stack WEVAL (React, Node, PG). 3000 MAD/jour.',r:100000,s:'idea',b:'bi',a:['Portfolio case-studies.html','Pricing grid','Landing développement']},
{n:'Solution Finder IA',d:'solution-finder.html existant. Recommandation IA des solutions WEVAL pour prospects.',r:30000,s:'plan',b:'bp',a:['Enrichir solution-finder','Connecter WEVIA Master','A/B test conversion']}
],m:[{l:'Pipeline',v:'750K',s:'6 opportunités',c:'s'},{l:'HCPs',v:'157K',s:'120K emails · 72K verified',c:'e'},{l:'Pages',v:'279',s:'+ 488 Arsenal = 767 total',c:'g'},{l:'APIs',v:'730',s:'Toutes live',c:'v'}]},
cloud:{l:'Cloud & Infra',ic:'cy',o:[
{n:'Arrow/Scaleway Reseller',d:'1er partenaire Scaleway Maroc via Arrow. Marge 15-25%. ArrowSphere onboarding.',r:100000,s:'wip',b:'bw',a:['Finaliser ArrowSphere','Offre packagée','10 prospects','Julien Bossu contact']},
{n:'Managed Hosting',d:'Hébergement managé Hetzner/OVH. Kuma + Prometheus + Grafana monitoring.',r:50000,s:'plan',b:'bp',a:['Pricing S/M/L','SLA document','Dashboard client Kuma']},
{n:'IaC Consulting',d:'DevOps/IaC PME. 17 Docker, CI/CD, Gitea, monitoring souverain.',r:60000,s:'idea',b:'bi',a:['Template Docker Compose','Workshop DevOps','3 prospects']},
{n:'Résolution Huawei Cloud',d:'Litige facturation. Comptes gelés + overconsumption. Ray Wu, Chris Cen, Yanhao.',r:0,s:'wip',b:'bh',a:['Document facturation anormale','Escalade Ray Wu','Deadline résolution']},
{n:'Cloudflare Management',d:'~25 comptes CF Brahim. Service gestion DNS/CDN/WAF pour clients.',r:30000,s:'idea',b:'bi',a:['Packager offre CF','Dashboard multi-compte','5 clients cibles']}
],m:[{l:'Pipeline',v:'240K',s:'5 opps',c:'cy'},{l:'Serveurs',v:'6+',s:'S95·S204·4 ECS Huawei',c:'e'},{l:'Docker',v:'19',s:'Tous UP',c:'s'},{l:'Uptime',v:'99.7%',s:'Kuma 24/7',c:'g'}]},
ia:{l:'IA & Data',ic:'vi',o:[
{n:'IA Souveraine aaS',d:'LiteLLM cascade 0€: Cerebras 5ms + Groq 12ms + Mistral + Gemini. Sovereign-api port 4000.',r:120000,s:'plan',b:'bp',a:['Offre cascade packagée','Benchmark latence','Landing IA Souveraine','HF Space yace222 déployé']},
{n:'Agent Builder WEVIA',d:'74 agents live. Blade v2.0 agent loop. Qdrant 5 collections. 199€/mois.',r:150000,s:'idea',b:'bi',a:['Interface builder drag&drop','5 templates agents','Doc API agents']},
{n:'Data Enrichment Service',d:'Ethica stack: RichScraper Playwright DabaDoc 50 TN/min. 8 crons actifs.',r:80000,s:'wip',b:'bw',a:['API enrichissement REST','Pricing volume','3 clients pilotes']},
{n:'Qdrant RAG Service',d:'5 collections Qdrant + 5751 training dataset HF. RAG clé-en-main B2B.',r:40000,s:'idea',b:'bi',a:['Package RAG','Demo searchable KB','Pricing tiers']},
{n:'WEVIA Deep Research',d:'wevia-deep-research.php existant. Rapports IA approfondis pour clients.',r:50000,s:'plan',b:'bp',a:['Packager deep research','Interface client','Pricing par rapport']}
],m:[{l:'Pipeline',v:'440K',s:'5 opps',c:'v'},{l:'Providers',v:'7',s:'Cascade 0€ 24/7',c:'e'},{l:'Agents',v:'74',s:'Live + Arena',c:'g'},{l:'Ollama',v:'5',s:'brain-v3·qwen3·nomic·minilm',c:'s'},{l:'Tools',v:'275',s:'Dynamic Resolver v7.1',c:'a'}]},
marketing:{l:'Marketing',ic:'co',o:[
{n:'Ethica Email Campaigns',d:'HCP Maghreb. 3000€/15K/mois. Contrat Kaouther Najar actif. Pilot DRY_RUN 7611.',r:180000,s:'wip',b:'bh',a:['Lancer pilot MG+DZ','Enrichir consent','Rapport ROI','ecm.py 4 actions']},
{n:'WEVADS Brain Engine',d:'646 configs, 9 SACRED winners. O365 PMTA 97% inbox. 77K emails/j capacité.',r:200000,s:'wip',b:'bw',a:['Volume warmup 1783 comptes','Conversions pull auto','Optimiser 9 winners','VMTAs 186-189']},
{n:'Newsletter B2B Premium',d:'Newsletter IA+pharma+tech Maghreb. LinkedIn + Telegram distribution.',r:30000,s:'idea',b:'bi',a:['Template newsletter','500 subscribers','2 sponsors','Telegram @wevia_cyber_bot']},
{n:'Social Media B2B',d:'LinkedIn scraper B2B (DSI/CTO Maroc). YouTube Factory. WhatsApp Business API.',r:60000,s:'plan',b:'bp',a:['LinkedIn B2B scraper actif','YouTube Factory setup','WhatsApp Business','Plausible tracking']},
{n:'MedReach Campaigns',d:'medreach-dashboard.html + medreach-campaign.html existants. Campagnes pharma ciblées.',r:50000,s:'plan',b:'bp',a:['Activer MedReach','Connecter Ethica data','Template campagne pharma']}
],m:[{l:'Pipeline',v:'520K',s:'5 opps',c:'c'},{l:'Brain Configs',v:'646',s:'9 SACRED winners',c:'g'},{l:'Emails/j',v:'77K',s:'Warmup 1783 comptes',c:'s'},{l:'Inbox Rate',v:'97%',s:'O365 PMTA',c:'e'}]},
recruitment:{l:'Recrutement',ic:'ro',o:[
{n:'Recrutement DevOps/Cloud',d:'LinkedIn B2B scraper DSI/CTO/DG Maroc actif. Fee 15-20% annuel.',r:100000,s:'plan',b:'bp',a:['LinkedIn scraper pw_linkedin_b2b.py','Base CV','Partenariat APEBI','5 postes']},
{n:'IA/Data Scientists',d:'ML Engineers, Data Scientists, NLP. Fee premium 25%. Marché tendu.',r:80000,s:'idea',b:'bi',a:['Mapping Maroc/TN/DZ','Partnership universités','Pipeline candidats']},
{n:'Portage Salarial Tech',d:'Portage freelances tech. Marge 8-12%. Structure juridique nécessaire.',r:50000,s:'idea',b:'bi',a:['Structure juridique','Contrat type','Prospection freelances']},
{n:'Talent Assessment IA',d:'Assessment via WEVIA (tests techniques + soft skills IA). 49€/test.',r:60000,s:'idea',b:'bi',a:['Tests techniques auto','Scoring IA WEVIA','Landing assessment']}
],m:[{l:'Pipeline',v:'290K',s:'4 opps',c:'r'},{l:'LinkedIn Scraper',v:'Actif',s:'DSI/CTO/DG Maroc',c:'e'},{l:'Fee moyen',v:'20%',s:'Annuel',c:'g'}]},
erp:{l:'ERP & SAP',ic:'am',o:[
{n:'Vistex SAP Pricing',d:'Extension Vistex. SAP pricing industriels Maghreb. OCP, Cosumar, Carrefour.',r:200000,s:'wip',b:'bh',a:['Addendum Section 8.B','Prospects OCP/Cosumar','Formation Vistex','Section 3.d']},
{n:'ERP Cloud Migration',d:'Migration legacy → cloud (S/4HANA, Odoo). PME 100-500 employés.',r:150000,s:'plan',b:'bp',a:['Partnership Odoo Maroc','Benchmark S/4 vs Odoo','3 prospects industriels']},
{n:'Process Optimization',d:'Audit processus + ERP. Value Stream Mapping (vsm-pipelines.html).',r:60000,s:'idea',b:'bi',a:['Template audit','Connecter VSM','Offre packagée']},
{n:'Integration API ERP-CRM',d:'Twenty CRM ↔ ERP clients. Middleware WEVAL. booking.html existant.',r:40000,s:'idea',b:'bi',a:['Connecteur Twenty↔SAP','API middleware','Demo intégration']}
],m:[{l:'Pipeline',v:'450K',s:'4 opps',c:'a'},{l:'Partnership',v:'Vistex',s:'SAP Pricing Maghreb',c:'g'},{l:'Prospects',v:'3',s:'OCP·Cosumar·Carrefour',c:'e'}]},
formation:{l:'Formation',ic:'gold',o:[
{n:'IA pour Dirigeants',d:'Programme 2j pratique WEVIA. DG/DSI privé. 15K MAD/session.',r:90000,s:'plan',b:'bp',a:['Programme 2j','Salle Casa','Prospection CGEM','Support WEVIA Arena']},
{n:'Bootcamp DevOps/Cloud',d:'5j Docker, CI/CD, K8s, monitoring. Stack souveraine WEVAL. 8K MAD/participant.',r:60000,s:'idea',b:'bi',a:['Curriculum 5j','Lab Docker WEVAL','Certification']},
{n:'Email Marketing Pro',d:'Formation WEVADS Brain Engine 2j. Deliverability + PMTA. 12K MAD.',r:40000,s:'idea',b:'bi',a:['Contenu deliverability','Cas pratiques','Support post-formation']},
{n:'Academy WEVAL Online',d:'E-learning IA, Cloud, Data, DevOps. 29€/mois. LMS à déployer.',r:80000,s:'idea',b:'bi',a:['Plateforme LMS','5 cours','Landing academy.weval.ma']},
{n:'Certification WEVIA Expert',d:'Certif consultants partenaires. 500€/certification. Réseau.',r:30000,s:'idea',b:'bi',a:['Programme certif','Examen online','Réseau certifiés']}
],m:[{l:'Pipeline',v:'300K',s:'5 opps',c:'g'},{l:'Programmes',v:'5',s:'IA·DevOps·Email·LMS·Certif',c:'a'},{l:'Cible',v:'CGEM',s:'+APEBI+universités',c:'s'}]}
};
// PLAN 90 JOURS (from V1 enriched)
const P90=[
{w:'Semaine 1-2',acts:['Signer Vistex Lead Protection Addendum','Lancer Ethica Pilot DRY_RUN 7611 MG+DZ','Finaliser onboarding ArrowSphere','LinkedIn B2B scraper 50 profils DSI','Landing page WeviaAI.ma mockup','Résolution Huawei Cloud: documenter + escalade']},
{w:'Semaine 3-4',acts:['3 labos pilotes Ethica (Kaouther)','Offre Scaleway packagée + 10 prospects','Setup Stripe pour WEVIA SaaS','Programme formation IA 2j finalisé','MedReach: connecter Ethica data','Package consulting Cloud Migration']},
{w:'Semaine 5-6',acts:['Beta WEVIA SaaS 10 users','SEO Module Hub live + Plausible API','Newsletter B2B: template + 500 subs','Framework Audit Maturité Digitale','Bootcamp DevOps: curriculum 5j','WhatsApp Business API activer']},
{w:'Semaine 7-8',acts:['WEVIA White-label: mockup client','ERP Cloud Migration: partnership Odoo','Deep Research: packager offre','Certification WEVIA: programme','Talent Assessment IA: tests auto','Academy WEVAL: plateforme LMS']},
{w:'Semaine 9-10',acts:['Prospection CGEM 3 formations','Qdrant RAG: package + demo','Cloudflare management: offre client','YouTube Factory: premiers contenus','Value Stream Mapping: offre client','LinkedIn posts: stratégie B2B content']},
{w:'Semaine 11-12',acts:['Bilan Q1: pipeline signé vs objectif','Ajuster pricing toutes offres','Scale WEVADS: +5 winners brain','Réseau certifiés WEVIA: 5 premiers','Solution Finder: A/B test conversion','Growth Engine v4: auto-enrichissement IA']}
];
// SOCIAL CHANNELS
const SOC=[
{name:'LinkedIn B2B',ico:'🔗',status:'Actif',desc:'Scraper Playwright pw_linkedin_b2b.py. Cibles: DSI, CTO, DG Maghreb. DuckDuckGo/Bing profiles sans login.',api:'pw_linkedin_b2b.py + linkedin-posts.php',color:'var(--sa)'},
{name:'YouTube Factory',ico:'▶',status:'Setup',desc:'youtube-factory.php + youtube-factory/api.php. Production contenu IA/Cloud/Consulting.',api:'youtube-factory.php (mode demo)',color:'var(--co)'},
{name:'Telegram Bot',ico:'✈',status:'Actif',desc:'@wevia_cyber_bot, chat_id 7605775322. Alertes monitoring + notifications.',api:'blade-telegram.php + wedroid-telegram-alert.php',color:'var(--sa)'},
{name:'WhatsApp Business',ico:'💬',status:'Config',desc:'Meta Graph API v22.0. Actions: status, send, send_bulk, templates.',api:'whatsapp-api.php (4 actions)',color:'var(--em)'},
{name:'Mattermost',ico:'💜',status:'Live',desc:'Docker port 8065. Communication interne équipe + webhooks.',api:'blade-mattermost.php',color:'var(--vi)'},
{name:'Email Marketing',ico:'📧',status:'Live',desc:'WEVADS Brain Engine 646 configs. PMTA O365. 8 seeds Videotron+T-Online.',api:'wevia-email-api.php + Brain Engine',color:'var(--gold)'},
{name:'Plausible Analytics',ico:'📊',status:'Live',desc:'Docker port 8000. Analytics souverain. Nécessite bearer token config.',api:'Plausible API :8000',color:'var(--em)'},
{name:'Twenty CRM',ico:'🏢',status:'Live',desc:'Docker port 3000. CRM complet pour pipeline commercial.',api:'Twenty :3000 (GraphQL)',color:'var(--cy)'}
];
// CONNECTIONS (21 services)
const CN=[
{n:'Twenty CRM',p:':3000',s:'up'},{n:'Plausible',p:':8000',s:'up'},{n:'SearXNG',p:':8888',s:'up'},
{n:'Mattermost',p:':8065',s:'up'},{n:'Vaultwarden',p:':8222',s:'up'},{n:'Uptime Kuma',p:':3001',s:'up'},
{n:'Qdrant',p:':6333',s:'up'},{n:'Langfuse',p:':3100',s:'up'},{n:'Gitea',p:':3400',s:'up'},
{n:'Prometheus',p:':9090',s:'up'},{n:'WEVIA Master',p:':5899',s:'up'},{n:'Sentinel',p:':5890',s:'up'},
{n:'LiteLLM',p:':4001',s:'up'},{n:'Sovereign API',p:':4000',s:'up'},{n:'PostgreSQL',p:':5432',s:'up'},
{n:'Brain Engine',p:':5821',s:'up'},{n:'Arsenal',p:':5890',s:'up'},{n:'Paperclip',p:'—',s:'dn'},
{n:'MiroFish',p:'—',s:'dn'},{n:'n8n',p:':5678',s:'wr'},{n:'Ollama 5 mod.',p:':11434',s:'up'}
];
const TABS=['dashboard','advisor','consulting','digital','cloud','ia','marketing','recruitment','erp','formation','pipeline','plan90','social','scout','predict','connections'];
function mc(m){return `<div class="mc ${m.c}" data-k="${m.k||m.l}" onclick="v87Drill(this.dataset.k)" style="cursor:pointer;transition:transform .15s"><div class="mc-l">${m.l}</div><div class="mc-v">${m.v}</div><div class="mc-s">${m.s}</div></div>`;}/*V87-drill*/
function cd(o,mx){
const p=mx?Math.round(o.r/mx*100):0;
const cl=o.b==='bh'?'var(--co)':o.b==='bw'?'var(--gold)':o.b==='bp'?'var(--sa)':'var(--vi)';
let aa='';if(o.a)o.a.forEach(x=>{aa+=`<span class="at" onclick="this.classList.toggle('dn')">${x}</span>`;});
return `<div class="cd"><div class="cd-h"><div class="cd-t">${o.n}</div><span class="bd ${o.b}">${SN[o.s]||o.s}</span></div><div class="cd-d">${o.d}</div>${o.r?`<div class="rv"><div class="rv-b"><div class="rv-f" style="width:${p}%;background:${cl}"></div></div><div class="rv-v">${(o.r/1000|0)}K</div></div>`:''}<div class="ca">${aa}</div></div>`;
}
function buildKB(ops){
const by={idea:[],plan:[],wip:[],sign:[]};ops.forEach(o=>{if(by[o.s])by[o.s].push(o);});
let h='<div class="kb">';
['idea','plan','wip','sign'].forEach(k=>{
const it=by[k]||[];
h+=`<div class="kc"><div class="kh ${SC[k]}">${SN[k]} <span class="n">${it.length}</span></div>`;
it.forEach(o=>{h+=`<div class="ki">${o.n}${o.vl?`<span class="tg">${o.vl}</span>`:''}</div>`;});
if(!it.length)h+=`<div class="ki" style="color:var(--t3)">—</div>`;h+=`</div>`;
});return h+'</div>';
}
function build(){
const nav=document.getElementById('nav');
const tabLabels={dashboard:'Dashboard',advisor:'🎯 Conversion Advisor',pipeline:'Pipeline CRM',plan90:'Plan 90J',social:'Réseaux & Canaux',scout:'Dark Scout',predict:'WePredict',connections:'Connexions'};
const tabColors={dashboard:'var(--gold)',advisor:'#22d3ee',pipeline:'var(--em)',plan90:'var(--am)',social:'var(--sa)',scout:'var(--cy)',predict:'var(--ro)',connections:'var(--vi)'};/*V86*/
let nh='';
TABS.forEach((t,i)=>{
const on=i===0?' on':'';
if(V[t])nh+=`<div class="vt${on}" data-v="${t}"><span class="dt" style="background:var(--${V[t].ic})"></span>${V[t].l} <span class="ct">${V[t].o.length}</span></div>`;
else nh+=`<div class="vt${on}" data-v="${t}"><span class="dt" style="background:${tabColors[t]||'var(--t3)'}"></span>${tabLabels[t]||t}</div>`;
});
nav.innerHTML=nh;
nav.querySelectorAll('.vt').forEach(t=>{t.onclick=()=>{
nav.querySelectorAll('.vt').forEach(x=>x.classList.remove('on'));t.classList.add('on');
document.querySelectorAll('.sc').forEach(s=>s.classList.remove('on'));
const s=document.getElementById('s-'+t.dataset.v);if(s){s.classList.add('on');window.scrollTo({top:0,behavior:'smooth'});setTimeout(function(){var n=document.getElementById('nav');if(n){var y=n.getBoundingClientRect().bottom+window.scrollY;window.scrollTo({top:y-8,behavior:'smooth'});}},180);}
};});
const mn=document.getElementById('mn');
const all=Object.entries(V).flatMap(([k,v])=>v.o.map(o=>({...o,vl:v.l})));
const tot=all.reduce((s,o)=>s+o.r,0);
const byS={idea:0,plan:0,wip:0,sign:0};all.forEach(o=>{if(byS[o.s]!==undefined)byS[o.s]++;});
const VC={consulting:'var(--em)',digital:'var(--sa)',cloud:'var(--cy)',ia:'var(--vi)',marketing:'var(--co)',recruitment:'var(--ro)',erp:'var(--am)',formation:'var(--gold)'};
let h=`<div class="sc on" id="s-dashboard">`;
h+=`<div class="mr">${mc({k:'pipeline_total',l:'Pipeline Total',v:(tot/1000|0)+'K MAD',s:all.length+' opps · 8 verticaux',c:'g'})}${mc({k:'en_cours',l:'En cours',v:byS.wip+'',s:'Deals actifs',c:'e'})}${mc({k:'planifie',l:'Planifié',v:byS.plan+'',s:'Préparation',c:'s'})}${mc({k:'idees',l:'Idées',v:byS.idea+'',s:'À explorer',c:'v'})}${mc({k:'hcps_ethica',l:'HCPs Ethica',v:'157K',s:'120K emails · 72K verified',c:'c'})}${mc({k:'docker',l:'Docker',v:'19',s:'Tous UP',c:'cy'})}${mc({k:'tools_wevia',l:'Tools WEVIA',v:'626',s:'Resolver v8 · DP+V57+V60',c:'v'})}${mc({k:'pages_apis',l:'Pages + APIs',v:'656',s:'279 pages · 730 APIs',c:'a'})}${mc({k:'ia_cascade',l:'IA Cascade',v:'0€',s:'17 providers 24/7',c:'r'})}${mc({k:'crons',l:'Crons',v:'34',s:'Actifs S95+S204',c:'g'})}</div>`;
h+=`<div class="cb"><div class="ch"><span class="lv"></span> WEVIA Master — Growth Advisor</div><div class="cm" id="cM"><div class="mg sy">Connecté — 8 verticaux · 626 tools · 730 APIs · 17 providers IA · 157K HCPs. Question ?</div></div><div class="ci"><input id="cI" placeholder="Pricing API HCP ? ROI formation ? Plan recrutement ? Stratégie ERP ?" onkeydown="if(event.key==='Enter')chat()"><button onclick="chat()">Envoyer</button></div></div>`;
h+=`<div class="st">Pipeline global <span class="ln"></span></div>${buildKB(all)}`;
h+=`<div class="st">Revenus par vertical <span class="ln"></span></div>`;
Object.entries(V).forEach(([k,v])=>{
const vr=v.o.reduce((s,o)=>s+o.r,0);const p=tot?Math.round(vr/tot*100):0;
h+=`<div style="display:flex;align-items:center;gap:7px;margin-bottom:5px"><span style="font-size:10px;min-width:75px;color:var(--t2)">${v.l}</span><div class="rv-b" style="flex:1"><div class="rv-f" style="width:${p}%;background:${VC[k]}"></div></div><span class="rv-v">${(vr/1000|0)}K</span></div>`;
});h+=`</div>`;
// VERTICAL SECTIONS
Object.entries(V).forEach(([k,v])=>{
const mx=Math.max(...v.o.map(o=>o.r),1);
h+=`<div class="sc" id="s-${k}"><div class="st">${v.l} <span class="ln"></span></div><div class="mr">${v.m.map(m=>mc(m)).join('')}</div><div class="cg">${v.o.map(o=>cd(o,mx)).join('')}</div></div>`;
});
// CONVERSION ADVISOR container (fix overlap: fallback body>div sinon)
h+=`<div class="sc" id="s-advisor"><div style="padding:24px;color:#22d3ee">Loading Deep Conversion Advisor...</div></div>`;
// PIPELINE CRM
h+=`<div class="sc" id="s-pipeline"><div class="st">Pipeline Commercial — Twenty CRM + WEVAL CRM <span class="ln"></span></div>${buildKB(all)}`;
h+=`<div class="st">Top opportunités par revenu <span class="ln"></span></div><table class="tbl"><thead><tr><th>Opportunité</th><th>Vertical</th><th>Valeur</th><th>Stage</th></tr></thead><tbody>`;
all.filter(o=>o.r>0).sort((a,b)=>b.r-a.r).forEach(o=>{
h+=`<tr><td style="color:var(--t1);font-weight:500">${o.n}</td><td>${o.vl}</td><td style="font-family:var(--fm);color:var(--gold)">${(o.r/1000|0)}K</td><td><span class="bd ${o.b}">${SN[o.s]}</span></td></tr>`;
});h+=`</tbody></table></div>`;
// PLAN 90J
h+=`<div class="sc" id="s-plan90"><div class="st">Plan d'Action — 90 Jours <span class="ln"></span></div>`;
P90.forEach(w=>{
h+=`<div class="p90-w"><div class="p90-h">${w.w}</div>`;
w.acts.forEach(a=>{h+=`<div class="p90-a"><input type="checkbox" onchange="this.parentElement.classList.toggle('done')"><span>${a}</span></div>`;});
h+=`</div>`;
});h+=`</div>`;
// SOCIAL & CHANNELS
h+=`<div class="sc" id="s-social"><div class="st">Réseaux Sociaux & Canaux de Distribution <span class="ln"></span></div><div class="soc">`;
SOC.forEach(s=>{
const stCls=s.status==='Actif'||s.status==='Live'?'bs':s.status==='Setup'||s.status==='Config'?'bw':'bi';
h+=`<div class="soc-c"><div class="soc-h"><span class="soc-ico">${s.ico}</span>${s.name}<span class="bd ${stCls}" style="margin-left:auto">${s.status}</span></div><div class="soc-stat">${s.desc}</div><div class="soc-api">API: ${s.api}</div></div>`;
});h+=`</div></div>`;
// DARK SCOUT
h+=`<div class="sc" id="s-scout"><div class="st">Dark Scout — SearXNG Intelligence <span class="ln"></span></div><div style="display:flex;gap:6px;margin-bottom:12px"><input id="sQ" placeholder="consulting SAP Maroc, email pharma, recrutement DevOps, ERP migration..." style="flex:1;background:var(--bg3);border:1px solid var(--brd);border-radius:5px;padding:7px 9px;color:var(--t1);font-size:10px;font-family:var(--fb);outline:none" onkeydown="if(event.key==='Enter')scout()"><button onclick="scout()" style="padding:7px 14px;border-radius:5px;border:none;background:var(--sa);color:#fff;font-weight:600;font-size:10px;cursor:pointer">Scan</button></div><div class="sr" id="sR"><div style="color:var(--t3);font-size:10px">SearXNG: veille concurrentielle multi-sources</div></div></div>`;
// V86 WEPREDICT DASHBOARD
h+=`<div class="sc" id="s-predict"><div class="st"> WePredict Predictive Analytics <span class="ln"></span></div>
<div class="mr" id="predictKPIs">
<div class="mc" style="border-left:3px solid var(--ro)"><div class="mcl">Load Predicted (next 1h)</div><div class="mcv" id="predLoad">...</div><div class="mcs" id="predLoadSub">regression slope</div></div>
<div class="mc" style="border-left:3px solid var(--am)"><div class="mcl">Alert Threshold</div><div class="mcv" id="predAlert">...</div><div class="mcs">auto-heal armed</div></div>
<div class="mc" style="border-left:3px solid var(--cy)"><div class="mcl">Cache Hit Rate</div><div class="mcv" id="predCache">...</div><div class="mcs" id="predCacheSub">hits/gets</div></div>
<div class="mc" style="border-left:3px solid var(--em)"><div class="mcl">Samples Analyzed</div><div class="mcv" id="predSamples">...</div><div class="mcs">rolling window</div></div>
<div class="mc" style="border-left:3px solid var(--vi)"><div class="mcl">Top Patterns</div><div class="mcv" id="predPatterns">...</div><div class="mcs">auto-learned</div></div>
<div class="mc" style="border-left:3px solid var(--sa)"><div class="mcl">Trend</div><div class="mcv" id="predTrend">...</div><div class="mcs" id="predTrendSub">slope direction</div></div>
</div>
<div class="st" style="margin-top:15px">Top 5 Query Patterns (auto-learned) <span class="ln"></span></div>
<div id="predPatternsList" style="background:var(--bg3);padding:12px;border-radius:6px;font-family:var(--fm);font-size:10px;color:var(--t2)">Loading WePredict data...</div>
<div class="st" style="margin-top:15px">Recommended Actions <span class="ln"></span></div>
<div id="predActions" style="background:var(--bg3);padding:12px;border-radius:6px;font-size:11px;color:var(--t2)">Loading...</div>
</div>`;
// CONNECTIONS
h+=`<div class="sc" id="s-connections"><div class="st">21 Services connectés <span class="ln"></span></div><div class="cns">${CN.map(c=>`<div class="cn"><div class="cn-d ${c.s}"></div><div class="cn-n">${c.n}</div><div class="cn-p">${c.p}</div></div>`).join('')}</div>`;
h+=`<div class="st">Assets Registry (${new Date().toLocaleDateString('fr')}) <span class="ln"></span></div><table class="tbl"><thead><tr><th>Asset</th><th>Type</th><th>Status</th><th>Mat.</th></tr></thead><tbody id="aB"><tr><td colspan="4" style="color:var(--t3)"><span class="spnr"></span> Chargement registry...</td></tr></tbody></table></div>`;
mn.innerHTML=h;
}
async function loadAssets(){try{const r=await fetch(API+'?action=registry');const d=await r.json();if(d.assets){const b=document.getElementById('aB');if(b)b.innerHTML=d.assets.map(a=>`<tr><td style="color:var(--t1);font-weight:500">${a.name}</td><td>${a.type||'?'}</td><td><span class="bd ${a.status==='live'||a.status==='up'?'bs':'bh'}">${a.status}</span></td><td style="font-family:var(--fm)">${a.maturity||'?'}%</td></tr>`).join('');}}catch(e){}}
async function chat(){const inp=document.getElementById('cI'),q=inp.value.trim();if(!q)return;inp.value='';const m=document.getElementById('cM');m.innerHTML+=`<div class="mg us">${q}</div><div class="mg ai" id="cL"><span class="spnr"></span></div>`;m.scrollTop=m.scrollHeight;try{const r=await fetch(WV,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:q,context:'Growth Engine v3. 8 verticaux (consulting/digital/cloud/IA/marketing/recrutement/ERP/formation). Pipeline '+(Object.values(V).reduce((s,v)=>s+v.o.reduce((ss,o)=>ss+o.r,0),0)/1000|0)+'K MAD. 279 pages, 730 APIs, 626 tools, 17 Docker, 57 crons, 7 IA providers 0€, 157K HCPs, 74 agents, 5 Ollama models. Partenaires: Vistex SAP, Arrow/Scaleway, Ethica Kaouther. Social: LinkedIn scraper, YouTube Factory, Telegram bot, WhatsApp Business, Mattermost.',session:'growth-v3'})});const d=await r.json();const el=document.getElementById('cL');if(el)el.outerHTML=`<div class="mg ai">${(d.content||d.response||'—').replace(/\n/g,'<br>')}</div>`;}catch(e){const el=document.getElementById('cL');if(el)el.outerHTML=`<div class="mg ai" style="color:var(--co)">Erreur WEVIA</div>`;}m.scrollTop=m.scrollHeight;}
async function scout(){const q=document.getElementById('sQ').value.trim();if(!q)return;const b=document.getElementById('sR');b.innerHTML='<span class="spnr"></span> SearXNG...';try{const r=await fetch(API+'?action=dark_scout&q='+encodeURIComponent(q));const d=await r.json();if(d.results&&d.results.length)b.innerHTML=d.results.map(r=>`<div class="si2"><div class="si2-t">${r.title||''}</div><div class="si2-u">${r.url||''}</div><div class="si2-s">${r.content||r.snippet||''}</div></div>`).join('');else b.innerHTML=`<div style="color:var(--t3)">0 résultats</div>`;}catch(e){b.innerHTML=`<div style="color:var(--co)">Erreur</div>`;}}
async function fullScan(){const btn=document.querySelector('.sb');btn.innerHTML='<span class="spnr"></span>';btn.disabled=true;try{const r=await fetch(API+'?action=scan');const d=await r.json();const m=document.getElementById('cM');if(m&&d){m.innerHTML+=`<div class="mg ai"><strong>Scan ✓</strong><br>${(d.proposal||d.summary||JSON.stringify(d).substring(0,500)).replace(/\n/g,'<br>')}</div>`;m.scrollTop=m.scrollHeight;}}catch(e){}btn.innerHTML='<span class="ic">&#x21BB;</span> Scan All';btn.disabled=false;loadAssets();loadPredict();/*V86*/}
build();loadAssets();
</script>
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
<script>
(function(){
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
var d = document;
var m = d.createElement('div');
m.id = 'opus-udrill';
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
var inner = d.createElement('div');
inner.id = 'opus-udrill-in';
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
inner.addEventListener('click', function(e){ e.stopPropagation(); });
m.appendChild(inner);
m.addEventListener('click', function(){ m.style.display='none'; });
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
(d.body || d.documentElement).appendChild(m);
function openCard(card) {
// Clone card content + show close btn + increase font-size
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
inner.innerHTML = html;
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
m.style.display = 'flex';
}
function wire(root) {
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
var cards = root.querySelectorAll(sels);
for (var i = 0; i < cards.length; i++) {
var c = cards[i];
if (c.__opusWired) continue;
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
var r = c.getBoundingClientRect();
if (r.width < 60 || r.height < 40) continue;
c.__opusWired = true;
c.style.cursor = 'pointer';
c.setAttribute('role','button');
c.setAttribute('tabindex','0');
c.addEventListener('click', function(ev){
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
if (ev.target.closest('a,button,input,select')) return;
ev.preventDefault(); ev.stopPropagation();
openCard(this);
});
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
}
}
// Initial + mutation observer
var initRun = function(){ wire(d.body || d.documentElement); };
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
else initRun();
var mo = new MutationObserver(function(muts){
var newCard = false;
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
if (newCard) initRun();
});
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
})();
// V86 WePredict loader
async function loadPredict(){
try{
const r=await fetch('/api/dsh-predict-api.php');
const d=await r.json();
if(!d || !d.ok) return;
const loadData=d.load||{};
const cacheData=d.cache||{};
const el=(id,v)=>{const e=document.getElementById(id);if(e)e.textContent=v;};
el('predLoad', (loadData.predicted_next_hour||0).toFixed(2));
el('predLoadSub', 'slope: '+(loadData.regression_slope||0).toExponential(2));
el('predAlert', (loadData.threshold||5)+' '+(loadData.alert?'ARMED':'OK'));
el('predCache', (cacheData.hit_rate_pct||0).toFixed(1)+'%');
el('predCacheSub', (cacheData.hits||0)+' / '+(cacheData.gets||0));
el('predSamples', loadData.n_samples||0);
el('predPatterns', cacheData.patterns_count||0);
const slope=loadData.regression_slope||0;
el('predTrend', slope<0?'DECLINING':slope>0?'RISING':'STABLE');
el('predTrendSub', 'n='+(loadData.n_samples||0));
const plEl=document.getElementById('predPatternsList');
if(plEl && cacheData.top_patterns){
const tp=Object.entries(cacheData.top_patterns).slice(0,5);
plEl.innerHTML=tp.map(([q,cnt],i)=>`<div style="padding:4px 0;border-bottom:1px solid var(--brd)">${i+1}. <span style="color:var(--t1)">${q}</span> <span style="color:var(--gold)">(${cnt} hits)</span></div>`).join('');
}
const acEl=document.getElementById('predActions');
if(acEl){
const acts=loadData.recommended_actions||[];
acEl.innerHTML=acts.length>0 ? acts.map(a=>`<div style="padding:4px 0">${loadData.alert?'ALERT':''} <code style="color:var(--cy)">${a}</code></div>`).join('') : '<span style="color:var(--t3)">No actions needed - system healthy</span>';
}
}catch(e){console.error('WePredict load error:',e);}
}
// Auto-load on tab switch
const _origShow=window.show;window.show=function(k){if(_origShow)_origShow(k);if(k==='predict')loadPredict();};
// Auto-load on first render
setTimeout(loadPredict, 1500);
</script>
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
<div id="v87-modal" style="position:fixed;inset:0;background:rgba(0,0,0,.85);backdrop-filter:blur(4px);z-index:999999;display:none;align-items:center;justify-content:center;padding:20px"><div style="background:var(--bg2);border:1px solid var(--brd);border-radius:12px;padding:24px;max-width:720px;width:100%;max-height:85vh;overflow-y:auto"><div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px"><div id="v87-title" style="font-size:18px;font-weight:700;color:var(--t1)">Drill-down</div><button onclick="v87Close()" style="background:none;border:0;color:var(--t3);font-size:28px;cursor:pointer;line-height:1">&times;</button></div><div id="v87-content" style="color:var(--t2);font-size:12px;line-height:1.7"><span class="spnr"></span> Loading...</div></div></div><script>
const V87_DRILL_MAP={pipeline_total:{title:'Pipeline Total 3490K MAD',intent:'drill toc'},en_cours:{title:'Deals En cours (9)',intent:'drill funnel'},planifie:{title:'Opportunites Planifiees (12)',intent:'drill funnel'},idees:{title:'Ideas a explorer (18)',intent:'implement plan'},hcps_ethica:{title:'157K HCPs Ethica',intent:'ethica live'},docker:{title:'19 Docker containers UP',intent:'v82 unified status'},tools_wevia:{title:'626 Tools WEVIA',intent:'v77 oss discovery enriched'},pages_apis:{title:'656 Pages + APIs',intent:'drill hub'},ia_cascade:{title:'IA Cascade 17 providers 0eur',intent:'sovereign status'},crons:{title:'34 Crons actifs',intent:'cron failed'}};
async function v87Drill(key){
const map=V87_DRILL_MAP[key]||{title:key,intent:key};
const modal=document.getElementById('v87-modal');
document.getElementById('v87-title').textContent=map.title;
const content=document.getElementById('v87-content');
modal.style.display='flex';
content.innerHTML='<span class="spnr"></span> Querying WEVIA Master...';
try{
const r=await fetch('/api/wevia-autonomous.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:map.intent,session:'growth-drill'})});
const raw=await r.text();
// Parse SSE or JSON
let answer='';
raw.split('\n').forEach(l=>{if(l.startsWith('data: ')){try{const j=JSON.parse(l.slice(6));if(j.type==='answer'||j.text||j.content)answer+=(j.text||j.content||'');}catch(e){}}});
if(!answer)answer=raw.slice(0,2000);
let pretty=answer;
try{const j=JSON.parse(answer);pretty='<pre style=\"background:var(--bg3);padding:14px;border-radius:6px;overflow-x:auto;font-size:11px\">'+JSON.stringify(j,null,2)+'</pre>';}catch(e){pretty='<div style=\"white-space:pre-wrap\">'+answer.replace(/</g,'&lt;')+'</div>';}
content.innerHTML='<div style=\"margin-bottom:10px;font-size:11px;color:var(--t3)\">via WEVIA intent: <code style=\"color:var(--cy)\">'+map.intent+'</code></div>'+pretty;
}catch(e){content.innerHTML='<div style=\"color:var(--co)\">Error: '+e.message+'</div>';}
}
function v87Close(){document.getElementById('v87-modal').style.display='none';}
document.addEventListener('keydown',e=>{if(e.key==='Escape')v87Close();});
document.addEventListener('click',e=>{if(e.target.id==='v87-modal')v87Close();});
document.addEventListener('DOMContentLoaded',()=>{const s=document.createElement('style');s.textContent='.mc[data-k]:hover{transform:translateY(-2px);border-color:var(--gold)!important;box-shadow:0 4px 12px rgba(212,175,55,.2)}';document.head.appendChild(s);});
</script>
<script src="/api/a11y-auto-enhancer.js" defer></script>
<!-- WTP_UDOCK_V1 (Opus 21-avr t32b4) --><script src="/wtp-unified-dock.js" defer></script>
<script src="/opus-antioverlap-doctrine.js?v=1777045903" defer></script>
<!-- WAVE 229 · Deep Conversion Advisor V2 LIVE -->
<script>
(function(){
if (window.__wevalAdvisorV3Init) return;
window.__wevalAdvisorV3Init = true;
function renderAdvisor() {
var content = document.getElementById('s-advisor');
if (!content) content = document.getElementById('content') || document.querySelector('.content, main, body > div');
if (!content) return;
content.innerHTML = '<div style="padding:24px"><div id="advisor-loading" style="color:#22d3ee">Loading Deep Conversion Advisor V2 LIVE · fetching Paperclip + Dark Scout + WePredict + LLM…</div><div id="advisor-content"></div></div>';
// Main fetch (fast - no LLM)
fetch('/api/growth-conversion-advisor.php?cb='+Date.now())
.then(function(r){return r.json();})
.then(function(d){
var loading = document.getElementById('advisor-loading');
if (loading) loading.remove();
var body = document.getElementById('advisor-content');
if (body) body.innerHTML = buildAdvisor(d);
// Trigger LLM reco async (slower ~20-40s)
var llmBox = document.getElementById('advisor-llm-box');
if (llmBox) {
llmBox.innerHTML = '<div style="color:#a855f7;padding:8px"><span class="spnr"></span> Querying Cerebras → Groq → Mistral cascade…</div>';
fetch('/api/growth-conversion-advisor.php?llm=1&cb='+Date.now())
.then(function(r){return r.json();})
.then(function(dd){
var reco = dd.llm_reco;
if (reco && reco.raw) {
var raw = reco.raw;
// Try parse JSON
var match = raw.match(/\{[\s\S]*\}/);
if (match) {
try {
var j = JSON.parse(match[0]);
var html = '<div style="font-size:11px;color:#c4b5fd;margin-bottom:10px">✨ Provider: <b>'+reco.provider+'</b></div>';
(j.actions||[]).forEach(function(a){
html += '<div style="padding:10px;margin-bottom:8px;background:rgba(168,85,247,.08);border:1px solid rgba(168,85,247,.25);border-radius:8px">';
html += '<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px"><b style="color:#a855f7;font-size:16px">#'+a.rank+'</b><span style="color:#ddd6fe;font-weight:700;font-size:13px">'+(a.title||'?')+'</span><span style="margin-left:auto;color:#fde68a;font-size:11px">'+(a.revenue_est_mad?Math.round(a.revenue_est_mad/1000)+'K MAD':'')+'</span></div>';
html += '<div style="font-size:10.5px;color:#94a3b8;margin-bottom:4px">⏱ '+(a.timeline||'')+'</div>';
(a.steps||[]).forEach(function(s){
html += '<div style="font-size:11px;color:#e0e7ff;padding:3px 8px 3px 16px;position:relative"><span style="position:absolute;left:4px;color:#10b981">→</span>'+s+'</div>';
});
html += '</div>';
});
llmBox.innerHTML = html;
return;
} catch(e){}
}
llmBox.innerHTML = '<div style="font-size:11px;color:#c4b5fd;margin-bottom:8px">✨ '+reco.provider+'</div><pre style="white-space:pre-wrap;color:#ddd6fe;font-size:11px;max-height:280px;overflow-y:auto">'+raw.slice(0,2000)+'</pre>';
} else {
llmBox.innerHTML = '<div style="color:#94a3b8;font-size:11px;padding:8px">LLM cascade unavailable - add ?llm=1 manually</div>';
}
})
.catch(function(e){
llmBox.innerHTML = '<div style="color:#ef4444;font-size:11px;padding:8px">LLM err: '+e.message+'</div>';
});
}
})
.catch(function(e){
var body = document.getElementById('advisor-content');
if (body) body.innerHTML = '<div style="color:#ef4444">Err: '+e.message+'</div>';
});
}
function oppRow(o, col) {
var emoji = {in_progress:'🟡', plan:'🔵', idea:'💡'}[o.status] || '⚪';
var llBadge = '';
if (o.live_lead) {
var mql = o.live_lead.mql;
var bgcol = mql>=90?'#10b981':(mql>=70?'#fbbf24':'#94a3b8');
llBadge = ' <span style="padding:1px 5px;border-radius:6px;background:'+bgcol+'22;color:'+bgcol+';font-size:9px;font-weight:700" title="MQL score from Paperclip DB">MQL '+mql+(o.live_lead.sql_qualified?' ✅SQL':'')+'</span>';
}
return '<div style="padding:6px 8px;margin-bottom:4px;background:rgba(0,0,0,.25);border-radius:4px;font-size:11px">'
+ '<div style="display:flex;align-items:center;gap:6px;color:#e0e7ff">'+emoji+' <b>'+o.name+'</b>'+llBadge
+ '<span style="margin-left:auto;color:'+col+';font-weight:700">'+Math.round(o.revenue_mad/1000)+'K MAD</span></div>'
+ '<div style="font-size:10px;color:#94a3b8;margin-top:2px">effort '+o.effort+'/10 · impact '+o.impact+'/10 · ~'+o.time_days+'j</div>'
+ '</div>';
}
function buildAdvisor(d) {
var ll = d.live_leads || {};
var sc = d.live_scout || {};
var pr = d.live_predict || {};
var cap = d.capacity_plan || {};
var h = '<div style="display:flex;align-items:center;gap:12px;margin-bottom:16px;flex-wrap:wrap">';
h += '<h2 style="margin:0;color:#22d3ee;font-size:20px;font-weight:700">🎯 Deep Conversion Advisor V2 · LIVE</h2>';
h += '<span style="padding:4px 12px;border-radius:12px;background:linear-gradient(135deg,#22d3ee,#a855f7);color:#fff;font-size:10px;font-weight:800">WAVE 229</span>';
h += '<span style="margin-left:auto;color:#94a3b8;font-size:12px">'+ll.total+' leads · '+sc.total_scans+' scout scans · patterns '+pr.patterns+'</span>';
h += '</div>';
// === LIVE FEEDS row (new wave 229) ===
h += '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:10px;margin-bottom:16px">';
// Paperclip leads live
h += '<div style="padding:14px;background:linear-gradient(135deg,rgba(16,185,129,.15),rgba(16,185,129,.05));border:1px solid rgba(16,185,129,.3);border-radius:10px">';
h += '<div style="font-size:10px;color:#6ee7b7;text-transform:uppercase;font-weight:700">📊 Paperclip Leads LIVE</div>';
h += '<div style="font-size:24px;color:#10b981;font-weight:800">'+ll.total+'</div>';
h += '<div style="font-size:11px;color:#6ee7b7">avg MQL '+ll.avg_mql+' · '+Object.keys(ll.by_country||{}).length+' pays · '+(ll.active_customer||0)+' actifs</div>';
h += '</div>';
// WePredict live
var alertBg = pr.alert ? 'rgba(239,68,68,.15)' : 'rgba(34,211,238,.15)';
var alertBd = pr.alert ? 'rgba(239,68,68,.3)' : 'rgba(34,211,238,.3)';
var alertCol = pr.alert ? '#ef4444' : '#22d3ee';
h += '<div style="padding:14px;background:linear-gradient(135deg,'+alertBg+','+alertBg.replace('.15','.05')+');border:1px solid '+alertBd+';border-radius:10px">';
h += '<div style="font-size:10px;color:#a5f3fc;text-transform:uppercase;font-weight:700">⚡ WePredict LIVE</div>';
h += '<div style="font-size:24px;color:'+alertCol+';font-weight:800">load '+(pr.load_next_hour!==null?pr.load_next_hour:'?')+'</div>';
h += '<div style="font-size:11px;color:#a5f3fc">'+(pr.alert?'🚨 ALERT: '+(cap.plan_recommendation||'scale up'):'✅ OK : capacity normal')+'</div>';
h += '</div>';
// Dark Scout live
h += '<div style="padding:14px;background:linear-gradient(135deg,rgba(139,92,246,.15),rgba(139,92,246,.05));border:1px solid rgba(139,92,246,.3);border-radius:10px">';
h += '<div style="font-size:10px;color:#c4b5fd;text-transform:uppercase;font-weight:700">🕵 Dark Scout LIVE</div>';
h += '<div style="font-size:24px;color:#a855f7;font-weight:800">'+sc.total_scans+'</div>';
h += '<div style="font-size:11px;color:#c4b5fd">scans · '+Object.keys(sc.presets||{}).length+' presets actifs</div>';
h += '</div>';
// Revenue totals
h += '<div style="padding:14px;background:linear-gradient(135deg,rgba(251,191,36,.15),rgba(251,191,36,.05));border:1px solid rgba(251,191,36,.3);border-radius:10px">';
h += '<div style="font-size:10px;color:#fde68a;text-transform:uppercase;font-weight:700">💰 Pipeline MAD</div>';
h += '<div style="font-size:24px;color:#fbbf24;font-weight:800">'+Math.round(((d.matrix_revenue.quick_wins_mad||0)+(d.matrix_revenue.big_bets_mad||0))/1000)+'K</div>';
h += '<div style="font-size:11px;color:#fde68a">QW '+Math.round(d.matrix_revenue.quick_wins_mad/1000)+'K + BB '+Math.round(d.matrix_revenue.big_bets_mad/1000)+'K</div>';
h += '</div>';
h += '</div>';
// === TOP 5 ===
h += '<div style="padding:16px;background:rgba(0,0,0,.35);border:1px solid rgba(34,211,238,.2);border-radius:10px;margin-bottom:16px">';
h += '<div style="font-size:12px;color:#22d3ee;text-transform:uppercase;font-weight:700;margin-bottom:10px">🚀 TOP 5 actions prioritaires</div>';
(d.recommendations||[]).forEach(function(r){
h += '<div style="display:grid;grid-template-columns:40px 1fr;gap:10px;padding:8px;border-bottom:1px solid rgba(255,255,255,.04)">';
h += '<div style="font-size:20px;font-weight:800;color:#22d3ee">#'+r.rank+'</div>';
h += '<div><div style="font-size:13px;color:#e0f2fe;font-weight:600">'+r.action+'</div><div style="font-size:11px;color:#94a3b8;margin-top:2px">'+r.why+'</div><div style="font-size:10px;color:#64748b">🔗 '+r.deps+'</div></div>';
h += '</div>';
});
h += '</div>';
// === LLM-powered reco (new wave 229) ===
h += '<div style="padding:16px;background:linear-gradient(135deg,rgba(168,85,247,.08),rgba(34,211,238,.08));border:1px solid rgba(168,85,247,.25);border-radius:10px;margin-bottom:16px">';
h += '<div style="display:flex;align-items:center;gap:8px;margin-bottom:10px">';
h += '<div style="font-size:12px;color:#a855f7;text-transform:uppercase;font-weight:700">🤖 LLM-powered recommendations</div>';
h += '<span style="padding:2px 6px;border-radius:8px;background:rgba(168,85,247,.2);color:#c4b5fd;font-size:9.5px;font-weight:700">Cerebras → Groq → Mistral</span>';
h += '</div>';
h += '<div id="advisor-llm-box">loading async…</div>';
h += '</div>';
// === Social Signals Hub (NEW WAVE 230) ===
h += '<div style="padding:16px;background:linear-gradient(135deg,rgba(59,130,246,.12),rgba(168,85,247,.08));border:1px solid rgba(59,130,246,.25);border-radius:10px;margin-bottom:16px">';
h += '<div style="display:flex;align-items:center;gap:8px;margin-bottom:10px">';
h += '<div style="font-size:12px;color:#60a5fa;text-transform:uppercase;font-weight:700">📡 Social Signals Hub · conversion ideas adaptées</div>';
h += '<span style="padding:2px 6px;border-radius:8px;background:rgba(59,130,246,.2);color:#93c5fd;font-size:9.5px;font-weight:700">WAVE 230</span>';
h += '<button onclick="refreshSocialHub()" style="margin-left:auto;padding:4px 10px;border-radius:8px;background:rgba(59,130,246,.15);color:#bfdbfe;border:1px solid rgba(59,130,246,.3);font-size:10px;cursor:pointer;font-weight:600">🔄 Refresh + LLM</button>';
h += '</div>';
h += '<div id="advisor-social-box" style="font-size:11px;color:#94a3b8">Loading LinkedIn + HackerNews + Reddit + YouTube signals…</div>';
h += '</div>';
// === WAVE 254 · MULTI-AGENT ORCHESTRATOR BADGE ===
h += '<div id="wevia-multiagent-badge" style="padding:12px 14px;background:linear-gradient(90deg,rgba(16,185,129,.15),rgba(34,211,238,.15),rgba(168,85,247,.12));border:1px solid rgba(16,185,129,.4);border-radius:10px;margin-bottom:12px;display:flex;align-items:center;gap:10px;flex-wrap:wrap">';
h += '<span style="font-size:15px">✅🧠</span>';
h += '<span style="font-size:12px;color:#67e8f9;font-weight:700">WEVIA Master · Multi-Agent Orchestrator · 0 hallucination</span>';
h += '<span style="font-size:10px;color:#94a3b8">Pattern CLAUDE 7 phases (Thinking→Plan→Dispatch PARALLEL→Ground→Synthesize→Tests→Response)</span>';
h += '<button onclick="testMultiAgent()" style="margin-left:auto;padding:4px 10px;border-radius:6px;background:rgba(34,211,238,.25);color:#67e8f9;border:1px solid rgba(34,211,238,.5);font-size:10px;cursor:pointer;font-weight:700">🧪 Test multiagent</button>';
h += '<button onclick="testWeviaGrounded()" style="padding:4px 10px;border-radius:6px;background:rgba(16,185,129,.2);color:#6ee7b7;border:1px solid rgba(16,185,129,.4);font-size:10px;cursor:pointer;font-weight:700">🔍 Grounding</button>';
h += '<button onclick="launchMaxParallel()" style="padding:4px 10px;border-radius:6px;background:linear-gradient(135deg,rgba(236,72,153,.3),rgba(168,85,247,.3));color:#fbcfe8;border:1px solid rgba(236,72,153,.5);font-size:10px;cursor:pointer;font-weight:800">🚀 MAX 30 Agents</button>';
h += '</div>';
// === WAVE 253 · WEVIA GROUNDED BADGE (anti-hallucination proof) ===
h += '<div id="wevia-grounded-badge" style="padding:10px 14px;background:linear-gradient(90deg,rgba(16,185,129,.15),rgba(34,211,238,.08));border:1px solid rgba(16,185,129,.35);border-radius:8px;margin-bottom:12px;display:flex;align-items:center;gap:10px;flex-wrap:wrap">';
h += '<span style="font-size:14px">✅</span>';
h += '<span style="font-size:12px;color:#6ee7b7;font-weight:700">WEVIA Master · Grounded data · 0 hallucination</span>';
h += '<span style="font-size:10px;color:#94a3b8">Chat WEVIA connecté live à Paperclip (48 leads) + Scanner (10 solutions) + DB tasks · wave 253</span>';
h += '<button onclick="testWeviaGrounded()" style="margin-left:auto;padding:3px 10px;border-radius:6px;background:rgba(16,185,129,.2);color:#6ee7b7;border:1px solid rgba(16,185,129,.4);font-size:10px;cursor:pointer;font-weight:700">🧪 Test grounding</button>';
h += '</div>';
// === WAVE 252 · PREDICTIVE SOLUTION SCANNER ===
h += '<div style="padding:20px;background:linear-gradient(135deg,rgba(34,211,238,.15),rgba(168,85,247,.08),rgba(16,185,129,.08));border:2px solid rgba(34,211,238,.4);border-radius:14px;margin-bottom:18px;box-shadow:0 10px 40px rgba(34,211,238,.12)">';
h += '<div style="display:flex;align-items:center;gap:10px;margin-bottom:14px;flex-wrap:wrap">';
h += '<div style="font-size:16px;color:#67e8f9;text-transform:uppercase;font-weight:800;letter-spacing:.5px">🧠 Système Décisionnel · Predictive Solution Scanner</div>';
h += '<span style="padding:4px 10px;border-radius:10px;background:linear-gradient(135deg,#22d3ee,#a855f7);color:#fff;font-size:10px;font-weight:800;letter-spacing:.5px">WAVE 252 · AI PREDICT</span>';
h += '<button onclick="loadSolutionScanner()" style="margin-left:auto;padding:5px 12px;border-radius:8px;background:rgba(34,211,238,.2);color:#67e8f9;border:1px solid rgba(34,211,238,.4);font-size:11px;cursor:pointer;font-weight:700">🔄 Ré-analyser</button>';
h += '</div>';
h += '<div style="font-size:11px;color:#94a3b8;margin-bottom:12px">WePredict analyse tes 48 leads Paperclip + maturité produits + capabilities gaps → dit QUOI développer, QUOI lancer, combien de jours dev, gaps à combler pour ready multi-user web</div>';
h += '<div id="advisor-solution-scanner" style="color:#94a3b8">Loading predictive analysis…</div>';
h += '</div>';
// === WAVE 251 · DECISIONAL MATRIX · Effort vs Rendement + Benchmarks concurrence ===
h += '<div style="padding:18px;background:linear-gradient(135deg,rgba(236,72,153,.12),rgba(168,85,247,.08),rgba(16,185,129,.05));border:2px solid rgba(236,72,153,.4);border-radius:14px;margin-bottom:16px;box-shadow:0 8px 32px rgba(236,72,153,.1)">';
h += '<div style="display:flex;align-items:center;gap:10px;margin-bottom:14px">';
h += '<div style="font-size:15px;color:#f0abfc;text-transform:uppercase;font-weight:800;letter-spacing:.5px">🎯 Décisionnel · Solutions les plus matures à sortir au marché</div>';
h += '<span style="padding:3px 10px;border-radius:10px;background:linear-gradient(135deg,#ec4899,#a855f7);color:#fff;font-size:10px;font-weight:800;letter-spacing:.5px">WAVE 251 · BENCHMARK</span>';
h += '<span style="margin-left:auto;font-size:10px;color:#94a3b8">Classement: effort ↗ · rendement ↗ · maturité marché</span>';
h += '</div>';
// Build decisional matrix with real benchmarks
h += '<div id="advisor-decisional-matrix" style="color:#94a3b8"></div>';
h += '</div>';
// === WAVE 246 · KPI Dashboard Charts ===
h += '<div style="padding:16px;background:linear-gradient(135deg,rgba(16,185,129,.1),rgba(251,191,36,.05));border:1px solid rgba(16,185,129,.25);border-radius:10px;margin-bottom:16px">';
h += '<div style="display:flex;align-items:center;gap:8px;margin-bottom:10px">';
h += '<div style="font-size:12px;color:#10b981;text-transform:uppercase;font-weight:700">📊 KPI Dashboard · live charts</div>';
h += '<span style="padding:2px 6px;border-radius:8px;background:rgba(16,185,129,.2);color:#6ee7b7;font-size:9.5px;font-weight:700">WAVE 246</span>';
h += '<button onclick="loadKpiDashboard()" style="margin-left:auto;padding:4px 10px;border-radius:8px;background:rgba(16,185,129,.15);color:#6ee7b7;border:1px solid rgba(16,185,129,.3);font-size:10px;cursor:pointer;font-weight:600">🔄 Refresh</button>';
h += '</div>';
h += '<div id="advisor-kpi-box" style="color:#94a3b8">Loading KPI charts…</div>';
h += '</div>';
// === WAVE 247 · Kanban Board (NEW) ===
h += '<div style="padding:16px;background:linear-gradient(135deg,rgba(168,85,247,.08),rgba(34,211,238,.05));border:1px solid rgba(168,85,247,.25);border-radius:10px;margin-bottom:16px">';
h += '<div style="display:flex;align-items:center;gap:8px;margin-bottom:10px">';
h += '<div style="font-size:12px;color:#a855f7;text-transform:uppercase;font-weight:700">📋 Kanban Board · tasks par status</div>';
h += '<span style="padding:2px 6px;border-radius:8px;background:rgba(168,85,247,.2);color:#c4b5fd;font-size:9.5px;font-weight:700">WAVE 247</span>';
h += '<button onclick="loadKanban()" style="margin-left:auto;padding:4px 10px;border-radius:8px;background:rgba(168,85,247,.15);color:#c4b5fd;border:1px solid rgba(168,85,247,.3);font-size:10px;cursor:pointer;font-weight:600">🔄 Refresh</button>';
h += '</div>';
h += '<div id="advisor-kanban-box" style="color:#94a3b8">Loading kanban…</div>';
h += '</div>';
// === WAVE 248 · Pipeline Stages (NEW) ===
h += '<div style="padding:16px;background:linear-gradient(135deg,rgba(59,130,246,.1),rgba(16,185,129,.05));border:1px solid rgba(59,130,246,.25);border-radius:10px;margin-bottom:16px">';
h += '<div style="display:flex;align-items:center;gap:8px;margin-bottom:10px">';
h += '<div style="font-size:12px;color:#60a5fa;text-transform:uppercase;font-weight:700">🔁 Pipeline Stages · deal flow</div>';
h += '<span style="padding:2px 6px;border-radius:8px;background:rgba(59,130,246,.2);color:#93c5fd;font-size:9.5px;font-weight:700">WAVE 248</span>';
h += '<button onclick="loadPipelineStages()" style="margin-left:auto;padding:4px 10px;border-radius:8px;background:rgba(59,130,246,.15);color:#bfdbfe;border:1px solid rgba(59,130,246,.3);font-size:10px;cursor:pointer;font-weight:600">🔄 Refresh</button>';
h += '</div>';
h += '<div id="advisor-pipeline-box" style="color:#94a3b8">Loading pipeline…</div>';
h += '</div>';
// === WAVE 249 · Activity Timeline (NEW) ===
h += '<div style="padding:16px;background:linear-gradient(135deg,rgba(251,191,36,.08),rgba(236,72,153,.05));border:1px solid rgba(251,191,36,.25);border-radius:10px;margin-bottom:16px">';
h += '<div style="display:flex;align-items:center;gap:8px;margin-bottom:10px">';
h += '<div style="font-size:12px;color:#fbbf24;text-transform:uppercase;font-weight:700">🕒 Activity Timeline · unified feed</div>';
h += '<span style="padding:2px 6px;border-radius:8px;background:rgba(251,191,36,.2);color:#fde68a;font-size:9.5px;font-weight:700">WAVE 249</span>';
h += '<button onclick="loadActivityTimeline()" style="margin-left:auto;padding:4px 10px;border-radius:8px;background:rgba(251,191,36,.15);color:#fde68a;border:1px solid rgba(251,191,36,.3);font-size:10px;cursor:pointer;font-weight:600">🔄 Refresh</button>';
h += '</div>';
h += '<div id="advisor-timeline-box" style="color:#94a3b8">Loading timeline…</div>';
h += '</div>';
// === WAVE 250 · Task Search (NEW) ===
h += '<div style="padding:16px;background:linear-gradient(135deg,rgba(236,72,153,.08),rgba(34,211,238,.05));border:1px solid rgba(236,72,153,.25);border-radius:10px;margin-bottom:16px">';
h += '<div style="display:flex;align-items:center;gap:8px;margin-bottom:10px">';
h += '<div style="font-size:12px;color:#ec4899;text-transform:uppercase;font-weight:700">🔎 Task Search · filter by text/status/MAD</div>';
h += '<span style="padding:2px 6px;border-radius:8px;background:rgba(236,72,153,.2);color:#fbcfe8;font-size:9.5px;font-weight:700">WAVE 250</span>';
h += '</div>';
h += '<div style="display:flex;gap:6px;margin-bottom:10px;flex-wrap:wrap">';
h += '<input type="text" id="search-q" placeholder="🔎 title or opportunity…" style="flex:1;min-width:180px;padding:7px 10px;border-radius:6px;background:rgba(0,0,0,.4);color:#e0e7ff;border:1px solid rgba(236,72,153,.3);font-size:12px" onkeydown="if(event.key===\'Enter\')runSearch()">';
h += '<select id="search-status" style="padding:7px 10px;border-radius:6px;background:rgba(0,0,0,.4);color:#e0e7ff;border:1px solid rgba(236,72,153,.3);font-size:12px"><option value="">All statuses</option><option value="proposed">proposed</option><option value="in_progress">in_progress</option><option value="done">done</option><option value="cancelled">cancelled</option><option value="blocked">blocked</option></select>';
h += '<input type="number" id="search-min-mad" placeholder="Min MAD" style="width:100px;padding:7px 10px;border-radius:6px;background:rgba(0,0,0,.4);color:#e0e7ff;border:1px solid rgba(236,72,153,.3);font-size:12px">';
h += '<button onclick="runSearch()" style="padding:7px 14px;border-radius:6px;background:rgba(236,72,153,.2);color:#fbcfe8;border:1px solid rgba(236,72,153,.4);font-size:11px;cursor:pointer;font-weight:700">Search</button>';
h += '</div>';
h += '<div id="advisor-search-results" style="color:#94a3b8;font-size:11px">Type a query + enter to search…</div>';
h += '</div>';
// === Matrix ===
h += '<div style="padding:16px;background:rgba(0,0,0,.35);border:1px solid rgba(168,85,247,.2);border-radius:10px;margin-bottom:16px">';
h += '<div style="font-size:12px;color:#a855f7;text-transform:uppercase;font-weight:700;margin-bottom:10px">📊 Matrice Effort × Impact (Eisenhower)</div>';
h += '<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">';
h += '<div style="padding:12px;background:rgba(16,185,129,.08);border:1px solid rgba(16,185,129,.25);border-radius:8px"><div style="font-size:11px;color:#6ee7b7;font-weight:700;margin-bottom:6px">✅ QUICK WINS · FAIS MAINTENANT</div>'+(d.matrix.quick_wins||[]).map(function(o){return oppRow(o,'#10b981');}).join('')+'</div>';
h += '<div style="padding:12px;background:rgba(168,85,247,.08);border:1px solid rgba(168,85,247,.25);border-radius:8px"><div style="font-size:11px;color:#c4b5fd;font-weight:700;margin-bottom:6px">🎯 BIG BETS · PLANIFIE</div>'+(d.matrix.big_bets||[]).map(function(o){return oppRow(o,'#a855f7');}).join('')+'</div>';
h += '<div style="padding:12px;background:rgba(251,191,36,.08);border:1px solid rgba(251,191,36,.25);border-radius:8px"><div style="font-size:11px;color:#fde68a;font-weight:700;margin-bottom:6px">💡 FILL-INS · DELEGUE</div>'+((d.matrix.fill_ins||[]).length?(d.matrix.fill_ins||[]).map(function(o){return oppRow(o,'#fbbf24');}).join(''):'<div style="color:#94a3b8;font-size:11px">(aucune)</div>')+'</div>';
h += '<div style="padding:12px;background:rgba(239,68,68,.08);border:1px solid rgba(239,68,68,.25);border-radius:8px"><div style="font-size:11px;color:#fca5a5;font-weight:700;margin-bottom:6px">⛔ THANKLESS · EVITE</div>'+((d.matrix.thankless||[]).length?(d.matrix.thankless||[]).map(function(o){return oppRow(o,'#ef4444');}).join(''):'<div style="color:#94a3b8;font-size:11px">(aucune)</div>')+'</div>';
h += '</div></div>';
// === Sovereign IA 9 cards ===
h += '<div style="padding:16px;background:rgba(0,0,0,.35);border:1px solid rgba(251,191,36,.2);border-radius:10px;margin-bottom:16px">';
h += '<div style="font-size:12px;color:#fbbf24;text-transform:uppercase;font-weight:700;margin-bottom:10px">🧠 '+d.sovereign_ia_count+' IA Souveraines · live state</div>';
h += '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:10px">';
(d.sovereign_ia||[]).forEach(function(s){
h += '<div style="padding:12px;background:rgba(0,0,0,.25);border:1px solid rgba(251,191,36,.15);border-radius:8px">';
h += '<div style="display:flex;align-items:center;gap:6px;margin-bottom:4px"><a href="'+s.url+'" target="_blank" style="color:#fde68a;font-weight:700;font-size:13px;text-decoration:none">'+s.name+' ↗</a><span style="margin-left:auto;padding:1px 6px;border-radius:8px;background:rgba(16,185,129,.2);color:#6ee7b7;font-size:9.5px;font-weight:700">live</span></div>';
h += '<div style="font-size:10px;color:#94a3b8;text-transform:uppercase;margin-bottom:3px">'+s.category+'</div>';
h += '<div style="font-size:11px;color:#fde68a;margin-bottom:4px">'+s.capability+'</div>';
if (s.live_state) h += '<div style="font-size:10px;color:#22d3ee;padding:3px 5px;background:rgba(34,211,238,.05);border-radius:3px;margin-bottom:4px">🔴 '+s.live_state+'</div>';
h += '<div style="font-size:10.5px;color:#10b981;padding:3px 5px;background:rgba(16,185,129,.05);border-radius:3px;border-left:2px solid #10b981">💡 '+s.use_for_conversion+'</div>';
h += '<div style="margin-top:4px;height:3px;background:rgba(255,255,255,.04);border-radius:2px;overflow:hidden"><div style="height:100%;width:'+s.maturity+'%;background:linear-gradient(90deg,#fbbf24,#10b981)"></div></div>';
h += '</div>';
});
h += '</div></div>';
// === Competitors enriched with Dark Scout scans ===
h += '<div style="padding:16px;background:rgba(0,0,0,.35);border:1px solid rgba(236,72,153,.2);border-radius:10px;margin-bottom:16px">';
h += '<div style="font-size:12px;color:#ec4899;text-transform:uppercase;font-weight:700;margin-bottom:10px">🥊 Concurrence · scout scans integrated</div>';
h += '<div style="display:flex;flex-direction:column;gap:6px">';
(d.competitors||[]).forEach(function(c){
var tc = {low:'#10b981', medium:'#fbbf24', high:'#ef4444'}[c.threat] || '#94a3b8';
h += '<div style="padding:9px 11px;background:rgba(0,0,0,.2);border:1px solid rgba(236,72,153,.15);border-left:3px solid '+tc+';border-radius:6px">';
h += '<div style="display:flex;align-items:center;gap:8px;flex-wrap:wrap"><b style="color:#fbcfe8;font-size:12px">'+c.category+'</b><span style="padding:1px 6px;border-radius:8px;background:'+tc+'22;color:'+tc+';font-size:9px;font-weight:700">threat '+c.threat+'</span>';
if (c.scout_scans) h += '<span style="padding:1px 6px;border-radius:8px;background:rgba(139,92,246,.15);color:#c4b5fd;font-size:9px;font-weight:700">🕵 '+c.scout_scans+' scout scans</span>';
h += '</div>';
h += '<div style="font-size:11px;color:#94a3b8;margin-top:3px">vs: '+c.competitors.join(' · ')+'</div>';
h += '<div style="font-size:11px;color:#6ee7b7;margin-top:3px">💪 edge: '+c.weval_edge+'</div>';
h += '</div>';
});
h += '</div></div>';
// === Leads preview (new wave 229) ===
if (ll.top_leads && ll.top_leads.length) {
h += '<div style="padding:16px;background:rgba(0,0,0,.35);border:1px solid rgba(16,185,129,.2);border-radius:10px;margin-bottom:16px">';
h += '<div style="font-size:12px;color:#10b981;text-transform:uppercase;font-weight:700;margin-bottom:10px">📋 Top 10 leads · Paperclip live</div>';
h += '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:8px">';
ll.top_leads.forEach(function(l){
var mc = l.mql>=90?'#10b981':(l.mql>=70?'#fbbf24':'#94a3b8');
h += '<div style="padding:8px 10px;background:rgba(0,0,0,.2);border:1px solid rgba(255,255,255,.04);border-left:3px solid '+mc+';border-radius:6px">';
h += '<div style="display:flex;align-items:center;gap:6px"><b style="color:#e0e7ff;font-size:12px">'+l.company+'</b><span style="margin-left:auto;font-size:11px;color:'+mc+';font-weight:700">MQL '+l.mql+(l.sql_qualified?' ✅':'')+'</span></div>';
h += '<div style="font-size:10px;color:#94a3b8;margin-top:2px">'+l.contact+' · '+l.industry+' · '+l.country+'</div>';
if (l.notes) h += '<div style="font-size:10px;color:#64748b;margin-top:2px">'+l.notes.slice(0,80)+'</div>';
h += '</div>';
});
h += '</div></div>';
}
// === Ask WEVIA prompts ===
h += '<div style="padding:14px;background:linear-gradient(135deg,rgba(34,211,238,.08),rgba(168,85,247,.08));border:1px solid rgba(34,211,238,.25);border-radius:10px">';
h += '<div style="font-size:12px;color:#22d3ee;font-weight:700;margin-bottom:8px">💬 Ask WEVIA Master (orchestration multi-agent)</div>';
h += '<div style="display:flex;flex-wrap:wrap;gap:6px">';
var prompts = [
['→ Plan 7j Vistex Cosumar','Plan 7 jours pour closer Vistex Cosumar: objections + contre-propositions + steps','#6ee7b7'],
['→ Pricing API HCP','Pricing API HCP Maghreb 3 tiers + Stripe integration','#c4b5fd'],
['→ LinkedIn outbound','Séquence LinkedIn outbound Blade+WEVADS 9 winners 20 prospects','#a5f3fc'],
['→ Freemium plan','Plan lancement SaaS Freemium: landing + pricing + onboarding 45j','#fde68a'],
['→ Scout pharma','Dark Scout intelligence pharma Maroc + concurrent signals','#fbcfe8']
];
prompts.forEach(function(p){
h += '<button onclick="var i=document.getElementById(\'cI\');if(i){i.value=\''+p[1].replace(/\x27/g,"\\\x27")+'\';i.focus();}" style="padding:6px 12px;border-radius:8px;background:'+p[2]+'22;color:'+p[2]+';border:1px solid '+p[2]+'55;font-size:11px;cursor:pointer;font-weight:600">'+p[0]+'</button>';
});
h += '</div></div>';
return h;
}
document.addEventListener('click', function(e) {
var t = e.target.closest && e.target.closest('[data-v="advisor"]');
if (t) setTimeout(renderAdvisor, 200);
});
// Also expose global for debug
function refreshSocialHub() {
var box = document.getElementById('advisor-social-box');
if (!box) return;
box.innerHTML = '<div style="color:#60a5fa">🔍 Scanning LinkedIn + HackerNews + Reddit + YouTube + LLM cascade (15-30s)…</div>';
fetch('/api/social-signals-hub.php?llm=1&topics=SaaS%20conversion,LinkedIn%20outbound,pharma%20digital&cb='+Date.now())
.then(function(r){return r.json();})
.then(function(d){ box.innerHTML = buildSocialHub(d); })
.catch(function(e){ box.innerHTML = '<div style="color:#ef4444">Err: '+e.message+'</div>'; });
}
function buildSocialHub(d) {
var html = '';
// Channel summary cards
html += '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:8px;margin-bottom:12px">';
var icons = {linkedin:'💼', hackernews:'🟧', reddit:'🔴', youtube:'📹'};
var cols = {linkedin:'#60a5fa', hackernews:'#f97316', reddit:'#ef4444', youtube:'#dc2626'};
Object.keys(d.channels || {}).forEach(function(ch){
var c = d.channels[ch];
html += '<div style="padding:8px;background:rgba(0,0,0,.25);border:1px solid '+(cols[ch]||'#94a3b8')+'33;border-radius:6px">';
html += '<div style="font-size:10px;color:'+(cols[ch]||'#94a3b8')+';font-weight:700">'+(icons[ch]||'●')+' '+ch+'</div>';
html += '<div style="font-size:18px;color:#e0e7ff;font-weight:800">'+(c.count||0)+'</div>';
html += '<div style="font-size:9px;color:#64748b">'+(c.source||'')+'</div>';
html += '</div>';
});
html += '</div>';
// LLM conversion ideas (if any)
var llm = d.llm_conversion_ideas;
if (llm && llm.raw) {
html += '<div style="padding:12px;background:rgba(139,92,246,.08);border:1px solid rgba(139,92,246,.25);border-radius:8px;margin-bottom:12px">';
html += '<div style="font-size:11px;color:#a855f7;font-weight:700;margin-bottom:8px">✨ LLM Conversion Ideas ('+llm.provider+')</div>';
var m = llm.raw.match(/\{[\s\S]*\}/);
if (m) {
try {
var j = JSON.parse(m[0]);
(j.ideas || []).forEach(function(idea){
html += '<div style="padding:9px;margin-bottom:6px;background:rgba(0,0,0,.25);border-left:3px solid #a855f7;border-radius:6px" data-idea-idx="'+idea.rank+'">';
html += '<div style="display:flex;align-items:center;gap:6px"><b style="color:#c4b5fd;font-size:12px">#'+idea.rank+' '+idea.title+'</b>';
html += '<span style="margin-left:auto;color:#fbbf24;font-size:11px;font-weight:700">'+(idea.estimated_mad?Math.round(idea.estimated_mad/1000)+'K MAD':'')+'</span>';
html += '<button onclick="createTaskFromIdea('+JSON.stringify(idea).replace(/"/g,"&quot;")+')" style="padding:3px 8px;margin-left:4px;border-radius:6px;background:rgba(16,185,129,.2);color:#6ee7b7;border:1px solid rgba(16,185,129,.4);font-size:10px;cursor:pointer;font-weight:700">+ Task</button>';
html += '<button onclick="askWeviaFromIdea('+JSON.stringify(idea).replace(/"/g,"&quot;")+')" style="padding:3px 8px;margin-left:4px;border-radius:6px;background:rgba(34,211,238,.2);color:#a5f3fc;border:1px solid rgba(34,211,238,.4);font-size:10px;cursor:pointer;font-weight:700">💬 Ask WEVIA</button>';
html += '</div>';
html += '<div style="font-size:10px;color:#94a3b8;margin-top:3px">🎯 '+(idea.opportunity||'')+' · 📡 '+(idea.channel||'')+'</div>';
html += '<div style="font-size:10px;color:#64748b;margin-top:2px">🔧 '+((idea.tools_used||[]).join(' · '))+'</div>';
(idea.first_steps||[]).forEach(function(s){
html += '<div style="font-size:10.5px;color:#e0e7ff;padding:2px 0 2px 14px;position:relative"><span style="position:absolute;left:2px;color:#10b981">→</span>'+s+'</div>';
});
if (idea.kpi) html += '<div style="font-size:10px;color:#6ee7b7;margin-top:2px">📊 KPI: '+idea.kpi+'</div>';
if (idea.inspired_by) html += '<div style="font-size:9.5px;color:#60a5fa;margin-top:2px;font-style:italic">💡 inspired: '+idea.inspired_by+'</div>';
html += '</div>';
});
} catch(e) { html += '<pre style="color:#ddd6fe;white-space:pre-wrap;font-size:10px;max-height:220px;overflow-y:auto">'+llm.raw.slice(0,1800)+'</pre>'; }
} else { html += '<pre style="color:#ddd6fe;white-space:pre-wrap;font-size:10px;max-height:220px;overflow-y:auto">'+llm.raw.slice(0,1800)+'</pre>'; }
html += '</div>';
}
// Top signals 4 channels horizontal
html += '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px">';
Object.keys(d.channels || {}).forEach(function(ch){
var c = d.channels[ch];
if (!c.items || !c.items.length) return;
html += '<div style="padding:10px;background:rgba(0,0,0,.25);border:1px solid rgba(255,255,255,.04);border-radius:6px">';
html += '<div style="font-size:10px;color:'+(cols[ch]||'#94a3b8')+';font-weight:700;margin-bottom:6px">'+(icons[ch]||'●')+' '+ch.toUpperCase()+' TOP</div>';
c.items.slice(0,5).forEach(function(item){
var meta = '';
if (item.points !== undefined) meta = '★'+item.points;
else if (item.likes !== undefined) meta = '♥'+item.likes+' 👁'+(item.views||0);
else if (item.score !== undefined) meta = '↑'+item.score;
html += '<a href="'+(item.url||'#')+'" target="_blank" style="display:block;padding:4px 0;border-bottom:1px solid rgba(255,255,255,.04);color:#cbd5e1;font-size:10.5px;text-decoration:none">';
html += (item.title||'').slice(0,70);
if (meta) html += ' <span style="color:#64748b;font-size:9px">'+meta+'</span>';
html += '</a>';
});
html += '</div>';
});
html += '</div>';
return html;
}
// Auto-load social hub when advisor tab opened - call after buildAdvisor
var origRender = renderAdvisor;
renderAdvisor = function() {
origRender();
setTimeout(refreshSocialHub, 800);
};
// Wave 231: Auto-create Paperclip task from LLM idea
window.createTaskFromIdea = function(idea) {
var btn = event && event.target;
if (btn) { btn.disabled = true; btn.textContent = '...'; }
fetch('/api/social-signals-hub.php?action=create_task', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
title: idea.title,
source: 'advisor-wave231',
source_ref: 'growth-engine-v2',
category: idea.channel || 'conversion',
opportunity: idea.opportunity || '',
tools_used: idea.tools_used || [],
first_steps: idea.first_steps || [],
kpi: idea.kpi || '',
estimated_mad: idea.estimated_mad || 0,
inspired_by: idea.inspired_by || '',
})
})
.then(function(r){return r.json();})
.then(function(d){
if (btn) {
btn.textContent = d.ok ? '✓ #' + d.task_id : '✗ err';
btn.style.background = d.ok ? 'rgba(16,185,129,.4)' : 'rgba(239,68,68,.3)';
}
setTimeout(loadWave231Tasks, 500);
})
.catch(function(e){
if (btn) { btn.textContent = '✗'; btn.style.background = 'rgba(239,68,68,.3)'; }
});
};
window.loadWave231Tasks = function() {
var box = document.getElementById('wave231Tasks');
if (!box) return;
box.innerHTML = '<div style="color:#94a3b8;font-size:11px">Loading Paperclip tasks…</div>';
fetch('/api/social-signals-hub.php?action=list_tasks&cb='+Date.now())
.then(function(r){return r.json();})
.then(function(d){
if (!d.ok || !d.tasks.length) {
box.innerHTML = '<div style="color:#64748b;font-size:11px;padding:8px">No tasks yet · click + Task on any LLM idea above to create</div>';
return;
}
var html = '<div style="font-size:11px;color:#6ee7b7;margin-bottom:8px;font-weight:700">📋 '+d.count+' tasks · ';
if (d.by_status) {
Object.keys(d.by_status).forEach(function(s){
var c = {proposed:'#fbbf24',in_progress:'#22d3ee',done:'#10b981',cancelled:'#94a3b8',blocked:'#ef4444'}[s] || '#94a3b8';
html += '<span style="padding:1px 6px;margin-right:4px;border-radius:6px;background:'+c+'22;color:'+c+';font-size:10px">'+s+': '+d.by_status[s]+'</span>';
});
}
html += '</div>';
d.tasks.forEach(function(t){
var colStatus = {proposed:'#fbbf24',in_progress:'#22d3ee',done:'#10b981',cancelled:'#94a3b8',blocked:'#ef4444'}[t.status] || '#94a3b8';
html += '<div class="wave232StatusBtns" style="padding:8px 10px;margin-bottom:4px;background:rgba(0,0,0,.2);border:1px solid rgba(16,185,129,.15);border-left:3px solid '+colStatus+';border-radius:6px">';
html += '<div style="display:flex;align-items:center;gap:6px;flex-wrap:wrap"><b style="color:#e0e7ff;font-size:11.5px">#'+t.id+' '+t.title+'</b>';
html += '<span style="margin-left:auto;padding:1px 6px;border-radius:6px;background:'+colStatus+'22;color:'+colStatus+';font-size:9px;font-weight:700">'+t.status+'</span></div>';
html += '<div style="font-size:10px;color:#94a3b8;margin-top:3px">🎯 '+(t.opportunity||'')+' · '+(t.estimated_mad?Math.round(t.estimated_mad/1000)+'K MAD':'')+' · '+((t.created_at||'').slice(0,16))+'</div>';
if (t.tools_used) html += '<div style="font-size:10px;color:#64748b;margin-top:2px">🔧 '+t.tools_used.replace(/\|/g,' · ')+'</div>';
if (t.kpi) html += '<div style="font-size:10px;color:#6ee7b7;margin-top:2px">📊 '+t.kpi+'</div>';
// Wave 232: status workflow buttons
html += '<div style="display:flex;gap:4px;margin-top:5px;flex-wrap:wrap">';
['proposed','in_progress','done','cancelled','blocked'].forEach(function(s){
if (s === t.status) return;
var sc = {proposed:'#fbbf24',in_progress:'#22d3ee',done:'#10b981',cancelled:'#94a3b8',blocked:'#ef4444'}[s];
html += '<button onclick="updateTaskStatus('+t.id+', \''+s+'\')" style="padding:2px 7px;border-radius:5px;background:'+sc+'15;color:'+sc+';border:1px solid '+sc+'44;font-size:9px;cursor:pointer;font-weight:600">→ '+s+'</button>';
});
html += '</div>';
html += '</div>';
});
box.innerHTML = html;
})
.catch(function(e){
box.innerHTML = '<div style="color:#ef4444;font-size:11px">Err: '+e.message+'</div>';
});
};
// Wave 232: Update task status workflow
window.updateTaskStatus = function(taskId, newStatus) {
fetch('/api/social-signals-hub.php?action=update_status', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({task_id: taskId, status: newStatus})
})
.then(function(r){return r.json();})
.then(function(d){
if (d.ok) { setTimeout(loadWave231Tasks, 300); }
});
};
// Wave 232: SSE stream visualization
window.startWave232SSE = function() {
var sseBox = document.getElementById('wave232SSE');
if (!sseBox) return;
sseBox.innerHTML = '<div style="color:#a855f7;font-size:11px">🔴 SSE stream connecting…</div>';
try {
var es = new EventSource('/api/social-signals-hub.php?action=stream&cb='+Date.now());
var events = [];
function render() {
var html = '<div style="font-size:11px;color:#c4b5fd;margin-bottom:6px">🔴 Live stream · '+events.length+' events</div>';
events.slice(-8).forEach(function(e){
var col = {hello:'#10b981',channel:'#22d3ee',tasks:'#fbbf24',done:'#a855f7'}[e.event] || '#94a3b8';
html += '<div style="padding:4px 8px;margin-bottom:3px;border-left:2px solid '+col+';background:rgba(0,0,0,.2);font-size:10px;color:#e0e7ff"><span style="color:'+col+';font-weight:700">'+e.event+'</span> · ';
if (e.data.name) html += '<b>'+e.data.name+'</b> count='+(e.data.count||0)+' · '+(e.data.top||'').slice(0,50);
else if (e.data.by_status) html += 'tasks: '+JSON.stringify(e.data.by_status);
else if (e.data.msg) html += e.data.msg;
else if (e.data.total_channels) html += 'done · '+e.data.total_channels+' channels streamed';
html += '</div>';
});
sseBox.innerHTML = html;
}
['hello','channel','tasks','done'].forEach(function(evName){
es.addEventListener(evName, function(e){
events.push({event: evName, data: JSON.parse(e.data)});
render();
if (evName === 'done') setTimeout(function(){es.close();}, 1000);
});
});
es.onerror = function(){ sseBox.innerHTML += '<div style="color:#94a3b8;font-size:10px">stream closed</div>'; es.close(); };
} catch(e) {
sseBox.innerHTML = '<div style="color:#ef4444">SSE err: '+e.message+'</div>';
}
};
// Inject tasks section after advisor renders
var origBuildSocial = buildSocialHub;
buildSocialHub = function(d) {
var h = origBuildSocial(d);
h += '<div style="margin-top:14px;padding:12px;background:rgba(16,185,129,.06);border:1px solid rgba(16,185,129,.25);border-radius:8px">';
h += '<div style="display:flex;align-items:center;gap:8px;margin-bottom:8px"><b style="color:#10b981;font-size:11px;text-transform:uppercase">📋 Paperclip Tasks · Auto-created</b>';
h += '<span style="padding:2px 6px;border-radius:6px;background:rgba(16,185,129,.2);color:#6ee7b7;font-size:9px;font-weight:700">WAVE 231</span>';
h += '<button onclick="loadWave231Tasks()" style="margin-left:auto;padding:3px 8px;border-radius:6px;background:rgba(16,185,129,.15);color:#6ee7b7;border:1px solid rgba(16,185,129,.3);font-size:10px;cursor:pointer">🔄 Refresh</button></div>';
h += '<div id="wave231Tasks">loading…</div>';
h += '</div>';
// Wave 232: SSE live stream panel
h += '<div style="margin-top:12px;padding:12px;background:rgba(168,85,247,.06);border:1px solid rgba(168,85,247,.25);border-radius:8px">';
h += '<div style="display:flex;align-items:center;gap:8px;margin-bottom:8px"><b style="color:#a855f7;font-size:11px;text-transform:uppercase">🔴 Live SSE Stream · channels + tasks</b>';
h += '<span style="padding:2px 6px;border-radius:6px;background:rgba(168,85,247,.2);color:#c4b5fd;font-size:9px;font-weight:700">WAVE 232</span>';
h += '<button onclick="startWave232SSE()" style="margin-left:auto;padding:3px 8px;border-radius:6px;background:rgba(168,85,247,.15);color:#c4b5fd;border:1px solid rgba(168,85,247,.3);font-size:10px;cursor:pointer">▶ Start stream</button></div>';
h += '<div id="wave232SSE"><div style="color:#64748b;font-size:10px">Click ▶ Start stream to connect SSE endpoint</div></div>';
h += '</div>';
setTimeout(loadWave231Tasks, 600);
return h;
};
// WAVE 233: Toast notification system
window.__wevalToast = function(msg, color) {
color = color || '#10b981';
var t = document.createElement('div');
t.style.cssText = 'position:fixed;bottom:20px;right:20px;padding:12px 18px;border-radius:10px;background:rgba(0,0,0,.9);color:'+color+';border:2px solid '+color+';font-size:13px;font-weight:600;z-index:99999;box-shadow:0 8px 24px rgba(0,0,0,.5);transition:opacity .3s;max-width:400px';
t.textContent = msg;
document.body.appendChild(t);
setTimeout(function(){ t.style.opacity = '0'; setTimeout(function(){ t.remove(); }, 400); }, 3500);
};
// WAVE 233: Ask WEVIA button handler
window.askWeviaFromIdea = function(idea) {
var btn = event && event.target;
if (btn) { btn.disabled = true; btn.textContent = '💬 ...'; }
__wevalToast('💬 Querying WEVIA Master multi-agent...', '#22d3ee');
fetch('/api/social-signals-hub.php?action=ask_wevia', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({idea: idea})
})
.then(function(r){return r.json();})
.then(function(d){
if (btn) { btn.textContent = '💬 Ask WEVIA'; btn.disabled = false; }
if (!d.ok) { __wevalToast('WEVIA err: '+(d.error||'?'), '#ef4444'); return; }
// Open modal with WEVIA response
var resp = d.wevia_response;
var respText = '';
if (typeof resp === 'string') respText = resp;
else if (resp && resp.response) respText = resp.response;
else respText = JSON.stringify(resp, null, 2);
var overlay = document.createElement('div');
overlay.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.85);z-index:99998;display:flex;align-items:center;justify-content:center;padding:20px';
overlay.onclick = function(e){ if(e.target===overlay) overlay.remove(); };
var modal = document.createElement('div');
modal.style.cssText = 'max-width:800px;max-height:85vh;overflow:auto;background:#0e1424;border:2px solid #22d3ee;border-radius:14px;padding:20px;color:#e0e7ff;box-shadow:0 20px 60px rgba(0,0,0,.8)';
modal.innerHTML = '<div style="display:flex;align-items:center;gap:10px;margin-bottom:14px;border-bottom:1px solid rgba(34,211,238,.25);padding-bottom:10px"><h3 style="margin:0;color:#22d3ee;font-size:16px">💬 WEVIA Master · Plan exécutable</h3><span style="padding:2px 8px;border-radius:8px;background:rgba(34,211,238,.2);color:#a5f3fc;font-size:10px;font-weight:700">'+(d.fallback||'WEVIA Master')+'</span><button onclick="this.closest(\'div[style*=inset]\').remove()" style="margin-left:auto;padding:6px 12px;border-radius:8px;background:rgba(239,68,68,.2);color:#fca5a5;border:1px solid rgba(239,68,68,.4);font-size:12px;cursor:pointer;font-weight:700">✕ Fermer</button></div><div style="font-size:11px;color:#94a3b8;margin-bottom:10px;padding:8px;background:rgba(0,0,0,.3);border-radius:6px;border-left:3px solid #22d3ee"><b>Contexte idea:</b> '+(idea.title||'')+' · '+(idea.opportunity||'')+' · '+(idea.estimated_mad?Math.round(idea.estimated_mad/1000)+'K MAD':'')+'</div><pre style="white-space:pre-wrap;font-family:system-ui;font-size:12.5px;line-height:1.6;color:#e0e7ff;margin:0">'+respText.replace(/</g,'&lt;')+'</pre>';
overlay.appendChild(modal);
document.body.appendChild(overlay);
__wevalToast('✓ WEVIA plan généré', '#10b981');
})
.catch(function(e){
if (btn) { btn.textContent = '💬 Ask WEVIA'; btn.disabled = false; }
__wevalToast('Err: '+e.message, '#ef4444');
});
};
// WAVE 233: Patch createTaskFromIdea for toast + auto-refresh tasks
var origCreateTask = window.createTaskFromIdea;
window.createTaskFromIdea = function(idea) {
var btn = event && event.target;
if (btn) { btn.disabled = true; btn.textContent = '...'; }
fetch('/api/social-signals-hub.php?action=create_task', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
title: idea.title, source: 'advisor-wave233', source_ref: 'growth-engine-v2',
category: idea.channel || 'conversion', opportunity: idea.opportunity || '',
tools_used: idea.tools_used || [], first_steps: idea.first_steps || [],
kpi: idea.kpi || '', estimated_mad: idea.estimated_mad || 0, inspired_by: idea.inspired_by || ''
})
})
.then(function(r){return r.json();})
.then(function(d){
if (btn) {
btn.textContent = d.ok ? '✓ #'+d.task_id : '✗';
btn.style.background = d.ok ? 'rgba(16,185,129,.4)' : 'rgba(239,68,68,.3)';
}
if (d.ok) {
var msg = 'Task #'+d.task_id+' created';
if (d.lead_linked) msg += ' · 📌 Linked: '+d.lead_linked.company+' (MQL '+d.lead_linked.mql_score+')';
__wevalToast('✓ '+msg, '#10b981');
}
setTimeout(loadWave231Tasks, 400);
})
.catch(function(e){
if (btn) { btn.textContent = '✗'; btn.style.background = 'rgba(239,68,68,.3)'; }
__wevalToast('Err: '+e.message, '#ef4444');
});
};
// WAVE 233: Add workflow status buttons + lead badges to task cards
var origLoadTasks = window.loadWave231Tasks;
window.loadWave231Tasks = function() {
var box = document.getElementById('wave231Tasks');
if (!box) return;
box.innerHTML = '<div style="color:#94a3b8;font-size:11px">Loading Paperclip tasks…</div>';
fetch('/api/social-signals-hub.php?action=list_tasks&cb='+Date.now())
.then(function(r){return r.json();})
.then(function(d){
if (!d.ok || !d.tasks.length) {
box.innerHTML = '<div style="color:#64748b;font-size:11px;padding:8px">No tasks yet</div>';
return;
}
var agg = d.by_status || {};
var aggStr = Object.keys(agg).map(function(k){return k+':'+agg[k];}).join(' · ');
var linked = d.linked_count || 0;
var html = '<div style="font-size:11px;color:#6ee7b7;margin-bottom:8px;font-weight:700">📋 '+d.count+' tasks '+(aggStr?('· '+aggStr):'')+(linked?' · 📌 '+linked+' linked':'')+'</div>';
d.tasks.forEach(function(t){
var colStatus = {proposed:'#fbbf24',in_progress:'#22d3ee',done:'#10b981',cancelled:'#94a3b8',blocked:'#ef4444'}[t.status] || '#94a3b8';
html += '<div style="padding:8px 10px;margin-bottom:4px;background:rgba(0,0,0,.2);border:1px solid rgba(16,185,129,.15);border-left:3px solid '+colStatus+';border-radius:6px">';
html += '<div style="display:flex;align-items:center;gap:6px;flex-wrap:wrap"><b style="color:#e0e7ff;font-size:11.5px">#'+t.id+' '+(t.title||'?').slice(0,60)+'</b>';
html += '<span style="padding:1px 6px;border-radius:6px;background:'+colStatus+'22;color:'+colStatus+';font-size:9px;font-weight:700">'+t.status+'</span>';
// WAVE 233: lead badge
if (t.lead_company) {
var mql = parseInt(t.lead_mql||0);
var mqlCol = mql>=90?'#10b981':(mql>=70?'#fbbf24':'#94a3b8');
html += '<span style="padding:1px 6px;border-radius:6px;background:'+mqlCol+'22;color:'+mqlCol+';font-size:9px;font-weight:700">📌 '+t.lead_company+' MQL '+mql+(t.lead_sql==='t'?' ✅':'')+'</span>';
}
html += '<span style="margin-left:auto;color:#fbbf24;font-size:10px;font-weight:700">'+(t.estimated_mad?Math.round(t.estimated_mad/1000)+'K':'')+'</span></div>';
html += '<div style="font-size:10px;color:#94a3b8;margin-top:3px">🎯 '+(t.opportunity||'')+' · '+((t.created_at||'').slice(5,16))+'</div>';
if (t.tools_used) html += '<div style="font-size:10px;color:#64748b;margin-top:2px">🔧 '+t.tools_used.replace(/\|/g,' · ')+'</div>';
if (t.kpi) html += '<div style="font-size:10px;color:#6ee7b7;margin-top:2px">📊 '+t.kpi+'</div>';
// Workflow buttons
html += '<div style="margin-top:6px;display:flex;gap:4px;flex-wrap:wrap">';
['proposed','in_progress','done','cancelled','blocked'].forEach(function(s){
if (s === t.status) return;
var c = {proposed:'#fbbf24',in_progress:'#22d3ee',done:'#10b981',cancelled:'#94a3b8',blocked:'#ef4444'}[s];
html += '<button onclick="updateTaskStatus('+t.id+',\''+s+'\')" style="padding:2px 6px;border-radius:4px;background:'+c+'11;color:'+c+';border:1px solid '+c+'33;font-size:9px;cursor:pointer">→ '+s+'</button>';
});
html += '</div></div>';
});
box.innerHTML = html;
})
.catch(function(e){ box.innerHTML = '<div style="color:#ef4444;font-size:11px">Err: '+e.message+'</div>'; });
};
// WAVE 233: Update task status with toast
window.updateTaskStatus = function(taskId, newStatus) {
fetch('/api/social-signals-hub.php?action=update_status', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({task_id: taskId, status: newStatus})
})
.then(function(r){return r.json();})
.then(function(d){
if (d.ok) {
__wevalToast('Task #'+taskId+' → '+d.new_status, '#22d3ee');
setTimeout(loadWave231Tasks, 300);
} else { __wevalToast('Err: '+(d.error||'?'), '#ef4444'); }
})
.catch(function(e){ __wevalToast('Err: '+e.message, '#ef4444'); });
};
// WAVE 233: Auto-poll tasks every 30s
if (!window.__w233TaskPoller) {
window.__w233TaskPoller = setInterval(function(){
if (document.getElementById('wave231Tasks')) { loadWave231Tasks(); }
}, 30000);
}
// WAVE 233: Add CSV export button
window.exportTasksCsv = function() {
window.open('/api/social-signals-hub.php?action=export_csv', '_blank');
__wevalToast('📥 CSV download started', '#10b981');
};
// =====================================================================
// WAVE 246-250: NEW UI functions consuming new endpoints
// =====================================================================
// WAVE 255: MAX parallel launch · 12 agents mobilisés en même temps via Factory
window.launchMaxParallel = function() {
var badge = document.getElementById('wevia-multiagent-badge');
if (badge) badge.style.background = 'linear-gradient(90deg,rgba(236,72,153,.3),rgba(168,85,247,.3),rgba(34,211,238,.2))';
__wevalToast && __wevalToast('🚀 Launching MAX 12 agents in parallel...', '#ec4899');
var t0 = Date.now();
fetch('/api/wevia-factory.php?action=run', {
method:'POST',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({
message: "Audit complet global: solutions · leads · tasks · social · predict · enterprise · quality · infrastructure",
max_agents: 30,
session: "max-"+Date.now()
})
})
.then(function(r){return r.json();})
.then(function(d){
var dur = Date.now() - t0;
var overlay = document.createElement('div');
overlay.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.9);z-index:99999;display:flex;align-items:center;justify-content:center;padding:15px';
overlay.onclick = function(e){ if(e.target===overlay) overlay.remove(); };
var modal = document.createElement('div');
modal.style.cssText = 'max-width:1100px;width:100%;background:#0a0f1a;border:2px solid #ec4899;border-radius:14px;padding:22px;color:#e0e7ff;max-height:90vh;overflow:auto;box-shadow:0 20px 80px rgba(236,72,153,.3)';
var html = '<div style="display:flex;align-items:center;gap:12px;margin-bottom:14px;padding-bottom:10px;border-bottom:2px solid rgba(236,72,153,.3)">';
html += '<span style="font-size:24px">🚀</span>';
html += '<h3 style="margin:0;color:#fbcfe8;font-size:17px">MAX Parallel Launch · '+d.agents_parallel+' agents mobilisés (12 builtin + 18 custom)</h3>';
html += '<span style="padding:4px 10px;border-radius:12px;background:'+(d.grade==="A"?"#10b981":"#fbbf24")+';color:#0a0f1a;font-size:12px;font-weight:800">grade '+d.grade+'</span>';
html += '<span style="padding:4px 10px;border-radius:12px;background:rgba(34,211,238,.2);color:#a5f3fc;font-size:11px;font-weight:700">'+d.total_duration_ms+'ms total</span>';
html += '<span style="padding:4px 10px;border-radius:12px;background:rgba(16,185,129,.2);color:#6ee7b7;font-size:11px;font-weight:700">grounding '+d.grounding_pct+'%</span>';
html += '<button onclick="this.closest(\'div[style*=inset]\').remove()" style="margin-left:auto;padding:6px 14px;border-radius:8px;background:rgba(239,68,68,.25);color:#fca5a5;border:1px solid rgba(239,68,68,.5);cursor:pointer;font-weight:700">✕ Fermer</button></div>';
// Parallel agents grid
html += '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:6px;margin-bottom:14px">';
var plan = d.phases.plan || {};
(plan.agents_to_call || []).forEach(function(a, idx){
html += '<div style="padding:8px;background:linear-gradient(135deg,rgba(34,211,238,.15),rgba(168,85,247,.1));border-left:3px solid #22d3ee;border-radius:6px;font-size:11px;color:#e0e7ff"><b>#'+(idx+1)+'</b> 🤖 '+a+'</div>';
});
html += '</div>';
// 7 Phases timeline
html += '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:4px;margin-bottom:14px">';
var phases = [
{k:"thinking", label:"1. THINK", icon:"🧠", color:"#a855f7"},
{k:"plan", label:"2. PLAN", icon:"📋", color:"#fbbf24"},
{k:"dispatch", label:"3. DISPATCH", icon:"⚡", color:"#22d3ee"},
{k:"ground", label:"4. GROUND", icon:"🔗", color:"#10b981"},
{k:"synthesize", label:"5. SYNTH", icon:"✨", color:"#ec4899"},
{k:"tests", label:"6. TESTS", icon:"🔬", color:"#60a5fa"}
];
phases.forEach(function(p){
var ph = d.phases[p.k] || {};
var dur = ph.duration_ms || 0;
html += '<div style="padding:8px;background:rgba(0,0,0,.3);border-left:3px solid '+p.color+';border-radius:4px"><div style="font-size:9px;color:'+p.color+';font-weight:700">'+p.icon+' '+p.label+'</div><div style="font-size:11px;color:#e0e7ff">'+dur+'ms</div></div>';
});
html += '</div>';
// Dispatch success
var disp = d.phases.dispatch || {};
html += '<div style="padding:10px;background:rgba(16,185,129,.1);border-left:3px solid #10b981;border-radius:6px;margin-bottom:10px;font-size:12px">';
html += '<b style="color:#6ee7b7">⚡ Dispatch PARALLEL:</b> '+disp.succeeded+'/'+disp.total+' agents succeeded · '+disp.duration_ms+'ms';
html += '</div>';
// Response
html += '<div style="padding:16px;background:linear-gradient(135deg,rgba(236,72,153,.08),rgba(168,85,247,.05));border:1px solid rgba(236,72,153,.3);border-radius:10px">';
html += '<div style="font-size:10px;color:#fbcfe8;font-weight:800;margin-bottom:8px;text-transform:uppercase">✨ Synthesized by '+(d.provider||"?")+' · natural language · 0 hallucination</div>';
html += '<div style="font-size:12.5px;color:#e0e7ff;line-height:1.75;white-space:pre-wrap">'+(d.response||"").replace(/</g,"&lt;")+'</div>';
html += '</div>';
modal.innerHTML = html;
overlay.appendChild(modal);
document.body.appendChild(overlay);
if (badge) badge.style.background = 'linear-gradient(90deg,rgba(16,185,129,.2),rgba(34,211,238,.2),rgba(168,85,247,.15))';
__wevalToast && __wevalToast('✓ '+d.agents_parallel+' agents PARALLEL · '+d.grade+' · grounding '+d.grounding_pct+'%', d.grade==="A"?"#10b981":"#fbbf24");
})
.catch(function(e){ __wevalToast && __wevalToast('Err: '+e.message, '#ef4444'); });
};
// WAVE 254: Test Multi-Agent Orchestrator · pattern CLAUDE 7 phases
window.testMultiAgent = function() {
var badge = document.getElementById('wevia-multiagent-badge');
if (badge) badge.style.background = 'linear-gradient(90deg,rgba(251,191,36,.3),rgba(34,211,238,.2))';
__wevalToast && __wevalToast('🧠 Dispatching to multi-agents in parallel...', '#22d3ee');
var t0 = Date.now();
fetch('/api/multiagent-orchestrator.php', {
method:'POST',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({
message: "Quelle solution prioriser cette semaine? Quel lead pharma relancer? Quelle concurrence surveiller?",
session: "mao-test-"+Date.now()
})
})
.then(function(r){return r.json();})
.then(function(d){
var dur = Date.now() - t0;
var overlay = document.createElement('div');
overlay.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.85);z-index:99999;display:flex;align-items:center;justify-content:center;padding:20px';
overlay.onclick = function(e){ if(e.target===overlay) overlay.remove(); };
var modal = document.createElement('div');
modal.style.cssText = 'max-width:900px;background:#0e1424;border:2px solid #22d3ee;border-radius:14px;padding:20px;color:#e0e7ff;max-height:85vh;overflow:auto';
var html = '<div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;border-bottom:1px solid rgba(34,211,238,.3);padding-bottom:10px">';
html += '<h3 style="margin:0;color:#67e8f9;font-size:16px">🧠 Multi-Agent Orchestrator · Pattern CLAUDE</h3>';
html += '<span style="padding:3px 10px;border-radius:10px;background:'+(d.grade==="A"?"#10b981":"#fbbf24")+';color:#0a0f1a;font-size:11px;font-weight:800">grade '+d.grade+'</span>';
html += '<span style="padding:3px 10px;border-radius:10px;background:rgba(34,211,238,.2);color:#a5f3fc;font-size:10px;font-weight:700">'+d.total_duration_ms+'ms</span>';
html += '<button onclick="this.closest(\'div[style*=inset]\').remove()" style="margin-left:auto;padding:6px 12px;border-radius:6px;background:rgba(239,68,68,.2);color:#fca5a5;border:1px solid rgba(239,68,68,.4);cursor:pointer">✕</button>';
html += '</div>';
// 7 phases timeline
html += '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:4px;margin-bottom:14px">';
var phases = [
{k:"thinking", label:"1. THINKING", icon:"🧠", color:"#a855f7"},
{k:"plan", label:"2. PLAN", icon:"📋", color:"#fbbf24"},
{k:"dispatch", label:"3. DISPATCH", icon:"⚡", color:"#22d3ee"},
{k:"ground", label:"4. GROUND", icon:"🔗", color:"#10b981"},
{k:"synthesize", label:"5. SYNTH", icon:"✨", color:"#ec4899"},
{k:"tests", label:"6. TESTS", icon:"🔬", color:"#60a5fa"},
{k:"response", label:"7. RESP", icon:"📤", color:"#f0abfc"}
];
phases.forEach(function(p){
var ph = d.phases[p.k];
var dur = ph ? (ph.duration_ms || 0) : 0;
html += '<div style="padding:8px;background:rgba(0,0,0,.3);border-left:3px solid '+p.color+';border-radius:4px">';
html += '<div style="font-size:9px;color:'+p.color+';font-weight:700">'+p.icon+' '+p.label+'</div>';
html += '<div style="font-size:11px;color:#e0e7ff">'+dur+'ms</div>';
html += '</div>';
});
html += '</div>';
// Agents mobilized
html += '<div style="padding:10px;background:rgba(34,211,238,.1);border-left:3px solid #22d3ee;border-radius:6px;margin-bottom:10px">';
html += '<div style="font-size:11px;color:#a5f3fc;font-weight:700;margin-bottom:4px">⚡ '+d.agents_parallel+' Agents Mobilisés en PARALLÈLE (succeeded: '+d.agents_succeeded+')</div>';
html += '<div style="font-size:11px;color:#e0e7ff">'+(d.agents_used||[]).map(function(a){return "<span style=\"padding:2px 8px;margin:2px;border-radius:12px;background:rgba(34,211,238,.2);color:#67e8f9;font-size:10px;font-weight:700;display:inline-block\">🤖 "+a+"</span>";}).join(" ")+'</div>';
html += '</div>';
// Grounding score
html += '<div style="padding:10px;background:rgba(16,185,129,.1);border-left:3px solid #10b981;border-radius:6px;margin-bottom:10px">';
html += '<div style="font-size:11px;color:#6ee7b7;font-weight:700">🔗 Grounding: '+d.grounding_score+'% · No hallucination: '+(d.phases.tests.tests.no_hallucination?"✓ YES":"✗ NO")+'</div>';
html += '</div>';
// Response
html += '<div style="padding:14px;background:rgba(0,0,0,.35);border:1px solid rgba(236,72,153,.3);border-radius:8px">';
html += '<div style="font-size:10px;color:#fbcfe8;font-weight:700;margin-bottom:6px;text-transform:uppercase">✨ Response (synthesized by '+(d.provider||"?")+')</div>';
html += '<div style="font-size:12.5px;color:#e0e7ff;line-height:1.7;white-space:pre-wrap">'+(d.response||"").replace(/</g,"&lt;")+'</div>';
html += '</div>';
modal.innerHTML = html;
overlay.appendChild(modal);
document.body.appendChild(overlay);
if (badge) badge.style.background = d.grade==="A" ? 'linear-gradient(90deg,rgba(16,185,129,.2),rgba(34,211,238,.2),rgba(168,85,247,.15))' : 'linear-gradient(90deg,rgba(251,191,36,.2),rgba(34,211,238,.15))';
__wevalToast && __wevalToast('✓ '+d.agents_parallel+' agents · '+d.grade+' · '+dur+'ms', d.grade==="A"?"#10b981":"#fbbf24");
})
.catch(function(e){ __wevalToast && __wevalToast('Err: '+e.message, '#ef4444'); });
};
// WAVE 253: Test WEVIA Master grounding (anti-hallucination)
window.testWeviaGrounded = function() {
var badge = document.getElementById('wevia-grounded-badge');
if (badge) badge.style.background = 'linear-gradient(90deg,rgba(251,191,36,.2),rgba(34,211,238,.1))';
__wevalToast && __wevalToast('🧪 Testing WEVIA Master grounding...', '#22d3ee');
fetch('/api/saas-chat.php', {
method:'POST',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({
message: "Combien de leads dans Paperclip, top 3 industries, et nom de la solution #1 selon le scanner?",
session: "test-ground-"+Date.now()
})
})
.then(function(r){return r.json();})
.then(function(d){
var resp = (d.response || '').toLowerCase();
var hasLeads = resp.includes('48');
var hasPharma = resp.includes('pharma');
var hasEthica = resp.includes('ethica');
var score = (hasLeads?1:0) + (hasPharma?1:0) + (hasEthica?1:0);
var overlay = document.createElement('div');
overlay.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.85);z-index:99999;display:flex;align-items:center;justify-content:center;padding:20px';
overlay.onclick = function(e){ if(e.target===overlay) overlay.remove(); };
var grade = score===3?'A+':(score===2?'B':(score===1?'C':'F'));
var gradeCol = score===3?'#10b981':(score>=1?'#fbbf24':'#ef4444');
var modal = document.createElement('div');
modal.style.cssText = 'max-width:700px;background:#0e1424;border:2px solid '+gradeCol+';border-radius:14px;padding:20px;color:#e0e7ff;max-height:85vh;overflow:auto';
var html = '<div style="display:flex;align-items:center;gap:12px;margin-bottom:14px">';
html += '<div style="width:60px;height:60px;border-radius:50%;background:'+gradeCol+';color:#0a0f1a;display:flex;align-items:center;justify-content:center;font-size:28px;font-weight:800">'+grade+'</div>';
html += '<div><h3 style="margin:0;color:'+gradeCol+';font-size:18px">Test Grounding · score '+score+'/3</h3>';
html += '<div style="font-size:11px;color:#94a3b8">Provider: '+(d.provider||'?')+' · leads_count grounding: '+(d.grounding&&d.grounding.leads_count)+' · wave '+((d.grounding||{}).wave)+'</div></div>';
html += '<button onclick="this.closest(\'div[style*=inset]\').remove()" style="margin-left:auto;padding:6px 12px;border-radius:8px;background:rgba(239,68,68,.2);color:#fca5a5;border:1px solid rgba(239,68,68,.4);cursor:pointer">Fermer</button></div>';
html += '<div style="font-size:11px;color:#94a3b8;margin-bottom:10px">Tests: <span style="color:'+(hasLeads?'#10b981':'#ef4444')+'">'+(hasLeads?'✓':'✗')+' mentionne 48 leads</span> · <span style="color:'+(hasPharma?'#10b981':'#ef4444')+'">'+(hasPharma?'✓':'✗')+' Pharma</span> · <span style="color:'+(hasEthica?'#10b981':'#ef4444')+'">'+(hasEthica?'✓':'✗')+' Ethica</span></div>';
html += '<div style="padding:12px;background:rgba(0,0,0,.4);border-radius:6px;border-left:3px solid '+gradeCol+';font-size:12.5px;line-height:1.6;white-space:pre-wrap">'+(d.response||'').replace(/</g,'&lt;')+'</div>';
modal.innerHTML = html;
overlay.appendChild(modal);
document.body.appendChild(overlay);
if (badge) badge.style.background = score===3 ? 'linear-gradient(90deg,rgba(16,185,129,.2),rgba(34,211,238,.12))' : 'linear-gradient(90deg,rgba(239,68,68,.15),rgba(251,191,36,.1))';
__wevalToast && __wevalToast('✓ Grounding '+grade+' · '+score+'/3', gradeCol);
})
.catch(function(e){ __wevalToast && __wevalToast('Err: '+e.message, '#ef4444'); });
};
// WAVE 252: Predictive Solution Scanner with WePredict-style market scoring
window.loadSolutionScanner = function() {
var box = document.getElementById('advisor-solution-scanner');
if (!box) return;
box.innerHTML = '<div style="color:#67e8f9;font-size:12px;padding:10px">🧠 WePredict analyzing market signals + capabilities gaps...</div>';
fetch('/api/solution-scanner.php?action=full_analysis&cb='+Date.now())
.then(function(r){return r.json();})
.then(function(d){
if (!d.ok) { box.innerHTML = '<div style="color:#ef4444">Error: '+(d.error||'?')+'</div>'; return; }
var s = d.summary;
var sols = d.solutions;
var gaps = d.top_gaps;
// SUMMARY KPI bar
var html = '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:8px;margin-bottom:14px">';
html += '<div style="padding:10px;background:rgba(16,185,129,.12);border-left:3px solid #10b981;border-radius:6px"><div style="font-size:9px;color:#6ee7b7;text-transform:uppercase;font-weight:700">🚀 SHIP IT</div><div style="font-size:24px;font-weight:800;color:#10b981">'+s.ship_it+'</div><div style="font-size:9px;color:#6ee7b7">ready launch multi-user</div></div>';
html += '<div style="padding:10px;background:rgba(251,191,36,.12);border-left:3px solid #fbbf24;border-radius:6px"><div style="font-size:9px;color:#fde68a;text-transform:uppercase;font-weight:700">⚡ ACCELERATE</div><div style="font-size:24px;font-weight:800;color:#fbbf24">'+s.accelerate+'</div><div style="font-size:9px;color:#fde68a">push urgently</div></div>';
html += '<div style="padding:10px;background:rgba(34,211,238,.12);border-left:3px solid #22d3ee;border-radius:6px"><div style="font-size:9px;color:#a5f3fc;text-transform:uppercase;font-weight:700">🛠 DEV SPRINT</div><div style="font-size:24px;font-weight:800;color:#22d3ee">'+s.dev_sprint+'</div><div style="font-size:9px;color:#a5f3fc">needs capabilities</div></div>';
html += '<div style="padding:10px;background:rgba(168,85,247,.12);border-left:3px solid #a855f7;border-radius:6px"><div style="font-size:9px;color:#c4b5fd;text-transform:uppercase;font-weight:700">🌱 NURTURE</div><div style="font-size:24px;font-weight:800;color:#a855f7">'+s.nurture+'</div><div style="font-size:9px;color:#c4b5fd">low market fit</div></div>';
html += '<div style="padding:10px;background:rgba(239,68,68,.12);border-left:3px solid #ef4444;border-radius:6px"><div style="font-size:9px;color:#fca5a5;text-transform:uppercase;font-weight:700">⛔ PIVOT</div><div style="font-size:24px;font-weight:800;color:#ef4444">'+s.pivot+'</div><div style="font-size:9px;color:#fca5a5">kill or reposition</div></div>';
html += '</div>';
// Overall cost/time
html += '<div style="padding:12px;background:rgba(0,0,0,.35);border-radius:8px;margin-bottom:14px">';
html += '<div style="font-size:11px;color:#67e8f9;font-weight:700;margin-bottom:6px">💰 GLOBAL EFFORT to bring ALL 10 to production multi-user</div>';
html += '<div style="display:flex;gap:14px;flex-wrap:wrap;font-size:12px;color:#e0e7ff">';
html += '<span>📅 <b style="color:#fbbf24">'+s.total_dev_days+'</b> dev-days</span>';
html += '<span>💸 <b style="color:#fbbf24">'+Math.round(s.total_dev_cost_mad/1000)+'K MAD</b> dev cost</span>';
html += '<span>💰 <b style="color:#10b981">'+Math.round(s.total_mad_pipeline/1000)+'K MAD</b> pipeline</span>';
var roi = ((s.total_mad_pipeline - s.total_dev_cost_mad) / s.total_dev_cost_mad * 100).toFixed(0);
html += '<span>🚀 ROI net: <b style="color:#10b981">'+roi+'%</b></span>';
html += '</div></div>';
// RANKED SOLUTIONS
html += '<div style="margin-bottom:8px;font-size:12px;color:#67e8f9;font-weight:700;text-transform:uppercase">🏆 Classement par winning_score (prediction + ICE + maturité + dev_effort)</div>';
html += '<div style="display:flex;flex-direction:column;gap:8px">';
sols.forEach(function(sol){
var decColors = {SHIP_IT:'#10b981', ACCELERATE:'#fbbf24', DEV_SPRINT:'#22d3ee', NURTURE:'#a855f7', PIVOT_OR_PARK:'#ef4444'};
var decIcons = {SHIP_IT:'🚀', ACCELERATE:'⚡', DEV_SPRINT:'🛠', NURTURE:'🌱', PIVOT_OR_PARK:'⛔'};
var dc = decColors[sol.decision] || '#94a3b8';
var dIcon = decIcons[sol.decision] || '?';
var pred = sol.market_prediction;
var dev = sol.dev_effort;
html += '<div style="padding:12px 14px;background:rgba(0,0,0,.35);border-left:4px solid '+dc+';border-radius:8px">';
// Header
html += '<div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:8px">';
html += '<div style="width:40px;height:40px;border-radius:50%;background:'+dc+';color:#0a0f1a;display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:800">'+sol.winning_score+'</div>';
html += '<div><div style="font-size:13.5px;color:#e0e7ff;font-weight:700">'+sol.name+'</div>';
html += '<div style="font-size:10px;color:#94a3b8">'+sol.category+' · '+sol.target_segment+' · status '+sol.status+'</div></div>';
html += '<span style="padding:4px 12px;border-radius:20px;background:'+dc+';color:#0a0f1a;font-size:11px;font-weight:800;margin-left:8px">'+dIcon+' '+sol.decision.replace(/_/g,' ')+'</span>';
html += '<span style="margin-left:auto;font-size:16px;color:#fbbf24;font-weight:800">'+Math.round(sol.mad_est/1000)+'K MAD</span>';
html += '</div>';
// Metrics grid
html += '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;margin-bottom:8px">';
html += '<div style="padding:6px 8px;background:rgba(16,185,129,.1);border-radius:4px"><div style="font-size:9px;color:#6ee7b7">📊 Predict</div><div style="font-size:14px;color:#10b981;font-weight:700">'+pred.score+'/100</div><div style="font-size:9px;color:#94a3b8">'+pred.recommendation+'</div></div>';
html += '<div style="padding:6px 8px;background:rgba(251,191,36,.1);border-radius:4px"><div style="font-size:9px;color:#fde68a">🎯 ICE</div><div style="font-size:14px;color:#fbbf24;font-weight:700">'+sol.ice_score+'</div></div>';
html += '<div style="padding:6px 8px;background:rgba(34,211,238,.1);border-radius:4px"><div style="font-size:9px;color:#a5f3fc">⚙ Maturité</div><div style="font-size:14px;color:#22d3ee;font-weight:700">'+sol.maturity+'%</div></div>';
html += '<div style="padding:6px 8px;background:rgba(168,85,247,.1);border-radius:4px"><div style="font-size:9px;color:#c4b5fd">✅ Capabilities</div><div style="font-size:14px;color:#a855f7;font-weight:700">'+dev.completion_pct+'%</div></div>';
html += '<div style="padding:6px 8px;background:rgba(236,72,153,.1);border-radius:4px"><div style="font-size:9px;color:#fbcfe8">🛠 Dev calendar</div><div style="font-size:14px;color:#ec4899;font-weight:700">'+dev.calendar_days_est+'j</div><div style="font-size:9px;color:#94a3b8">'+dev.total_dev_days+'d total</div></div>';
html += '<div style="padding:6px 8px;background:rgba(99,102,241,.1);border-radius:4px"><div style="font-size:9px;color:#a5b4fc">💸 Dev cost</div><div style="font-size:14px;color:#818cf8;font-weight:700">'+Math.round(dev.dev_cost_mad/1000)+'K</div></div>';
html += '</div>';
// Market signals
html += '<div style="padding:8px 10px;background:rgba(16,185,129,.08);border-left:2px solid #10b981;border-radius:4px;margin-bottom:6px;font-size:10.5px">';
html += '<b style="color:#6ee7b7">📡 Market signals:</b> <span style="color:#cbd5e1">'+(sol.signals||[]).join(' · ')+'</span>';
html += '</div>';
// WePredict breakdown
html += '<div style="padding:8px 10px;background:rgba(34,211,238,.08);border-left:2px solid #22d3ee;border-radius:4px;margin-bottom:6px;font-size:10.5px">';
html += '<b style="color:#a5f3fc">🧠 WePredict breakdown:</b> ';
html += '<span style="color:#cbd5e1">lead_density '+pred.breakdown.lead_density+'% · avg_MQL '+pred.breakdown.avg_mql+' · SQL '+pred.breakdown.sql_pct+'% · leads in target '+pred.breakdown.leads_in_target+' (SQL '+pred.breakdown.sql_qualified_in_target+')</span>';
html += '</div>';
// Capabilities TODO (critical path)
if ((sol.capabilities_todo||[]).length) {
html += '<div style="padding:8px 10px;background:rgba(239,68,68,.08);border-left:2px solid #ef4444;border-radius:4px;font-size:10.5px">';
html += '<b style="color:#fca5a5">⚠ To ship multi-user production (MISSING):</b> <span style="color:#cbd5e1">';
html += sol.capabilities_todo.map(function(cap){
var cl = d.mup_checklist[cap];
return '<span style="display:inline-block;padding:1px 6px;border-radius:4px;background:'+(cl && cl.critical ? 'rgba(239,68,68,.2)' : 'rgba(148,163,184,.15)')+';margin:1px;font-size:10px;color:'+(cl && cl.critical?'#fca5a5':'#cbd5e1')+'">'+(cl ? cl.name : cap)+' ·'+(cl?cl.dev_days:0)+'d</span>';
}).join(' ');
html += '</span></div>';
}
html += '</div>'; // card end
});
html += '</div>'; // solutions end
// TOP GAPS section
html += '<div style="margin-top:14px;padding:14px;background:rgba(239,68,68,.08);border:1px dashed rgba(239,68,68,.4);border-radius:10px">';
html += '<div style="font-size:12px;color:#fca5a5;font-weight:700;text-transform:uppercase;margin-bottom:10px">🔴 TOP 15 Gaps à combler (si 1 fix → impact N solutions)</div>';
html += '<div style="display:flex;flex-direction:column;gap:4px">';
gaps.forEach(function(g){
var barW = Math.round(g.missing_in_solutions/10*100);
var col = g.critical ? '#ef4444' : '#94a3b8';
html += '<div style="display:flex;align-items:center;gap:8px;font-size:11px">';
html += '<span style="width:220px;color:#cbd5e1">'+(g.critical?'🔴':'⚪')+' '+g.name+'</span>';
html += '<div style="flex:1;height:12px;background:rgba(255,255,255,.05);border-radius:2px;position:relative;overflow:hidden"><div style="position:absolute;left:0;top:0;bottom:0;width:'+barW+'%;background:'+col+'"></div></div>';
html += '<span style="width:90px;color:'+col+';font-weight:700;text-align:right">'+g.missing_in_solutions+'/10 · '+g.dev_days+'d</span>';
html += '</div>';
});
html += '</div>';
html += '<div style="margin-top:8px;font-size:10px;color:#94a3b8;font-style:italic">💡 Tip: Implémenter les gaps critiques communs (ex: billing Stripe) débloque simultanément plusieurs produits multi-user</div>';
html += '</div>';
box.innerHTML = html;
})
.catch(function(e){ box.innerHTML = '<div style="color:#ef4444">Err: '+e.message+'</div>'; });
};
// Auto-load when advisor tab rendered
setTimeout(function(){
if (document.getElementById('advisor-solution-scanner')) loadSolutionScanner();
}, 500);
// WAVE 251: Decisional Matrix with real-world competitor benchmarks
window.decisionalMatrix = function() {
// Real benchmark data: WEVAL solutions vs market competitors with maturity score
var solutions = [
{
rank: 1, name: "Ethica HCP Database MENA", category: "Pharma",
effort: 2, reward: 9, mad_est: 600000, days: 28,
maturity: 95, status: "PROD", ice: 270,
competitors: [{name:"IQVIA", price_idx:10, strength:"Global", weakness:"No MENA focus"}, {name:"Veeva OpenData", price_idx:9, strength:"Pharma-native", weakness:"Expensive"}, {name:"Doctolib Pro", price_idx:5, strength:"EU brand", weakness:"No pharma depth"}],
weval_edge: "157K HCPs · 87% email · consent-first · 0€ infra sovereign",
market_tam: "12M€ MENA HCP data market",
quadrant: "STAR"
},
{
rank: 2, name: "WEVAL SaaS Freemium", category: "AI Platform",
effort: 6, reward: 9, mad_est: 800000, days: 45,
maturity: 70, status: "BETA", ice: 120,
competitors: [{name:"Make.com", price_idx:7, strength:"Visual builder", weakness:"Cloud lock-in"}, {name:"Zapier", price_idx:8, strength:"Ecosystem", weakness:"Pricing scales bad"}, {name:"n8n cloud", price_idx:6, strength:"Self-host option", weakness:"Steep learning"}],
weval_edge: "WEVIA Master 269 tools · 17 providers cascade · 0€ inference Cerebras/Groq",
market_tam: "8M€ MA+MENA AI automation",
quadrant: "BIG_BET"
},
{
rank: 3, name: "WEVADS Brain Outreach", category: "Email Engine",
effort: 3, reward: 8, mad_est: 450000, days: 21,
maturity: 92, status: "PROD", ice: 120,
competitors: [{name:"Mailgun", price_idx:7, strength:"Reputation", weakness:"GDPR MENA fuzzy"}, {name:"SendGrid", price_idx:8, strength:"Scale", weakness:"Shared IPs"}, {name:"Mailjet", price_idx:6, strength:"FR root", weakness:"Limited APIs"}],
weval_edge: "PMTA+Kumo+Postfix triple MTA · 9 winners · 95%+ delivery · own IPs",
market_tam: "4M€ MA+MENA cold outreach",
quadrant: "QUICK_WIN"
},
{
rank: 4, name: "DocuSeal E-signature MENA", category: "Legal Tech",
effort: 2, reward: 7, mad_est: 250000, days: 14,
maturity: 85, status: "PROD", ice: 87.5,
competitors: [{name:"DocuSign", price_idx:10, strength:"Global brand", weakness:"Expensive per seat"}, {name:"Yousign", price_idx:7, strength:"EU/FR", weakness:"No MENA office"}, {name:"HelloSign", price_idx:6, strength:"Dropbox backed", weakness:"Limited MENA"}],
weval_edge: "Self-hosted 0€ · data sovereignty MENA · unlimited users",
market_tam: "3.5M€ MA+MENA e-signature",
quadrant: "QUICK_WIN"
},
{
rank: 5, name: "Dark Scout Intel", category: "Competitive Intel",
effort: 4, reward: 7, mad_est: 300000, days: 30,
maturity: 75, status: "PROD", ice: 52.5,
competitors: [{name:"Recorded Future", price_idx:10, strength:"OSINT leader", weakness:"Not MENA specific"}, {name:"Crayon", price_idx:8, strength:"Battlecards", weakness:"B2B SaaS only"}, {name:"Klue", price_idx:7, strength:"Enterprise", weakness:"No dark web"}],
weval_edge: "34 scans · multi-engine · dark web + clearnet · 3 presets",
market_tam: "2M€ MENA intelligence",
quadrant: "BIG_BET"
},
{
rank: 6, name: "WEVIA Master Orchestrator", category: "AI Orchestration",
effort: 5, reward: 9, mad_est: 700000, days: 60,
maturity: 65, status: "BETA", ice: 126,
competitors: [{name:"Claude Desktop", price_idx:8, strength:"Anthropic brand", weakness:"No sovereignty"}, {name:"ChatGPT Enterprise", price_idx:10, strength:"OpenAI", weakness:"Data leaves org"}, {name:"LangGraph", price_idx:5, strength:"Framework", weakness:"Dev-only"}],
weval_edge: "269 tools · multi-agents · 0€ inference · self-host · French/MENA fluent",
market_tam: "15M€ MENA enterprise AI",
quadrant: "BIG_BET"
},
{
rank: 7, name: "Blade AI Web Agent", category: "Automation",
effort: 3, reward: 6, mad_est: 200000, days: 21,
maturity: 80, status: "PROD", ice: 40,
competitors: [{name:"Browse AI", price_idx:7, strength:"No-code", weakness:"Cloud only"}, {name:"Multion", price_idx:6, strength:"Consumer agent", weakness:"No enterprise"}, {name:"Anthropic Computer Use", price_idx:9, strength:"Research-grade", weakness:"API only"}],
weval_edge: "Selenium+Chrome · 232 tasks automated · heartbeat monitoring",
market_tam: "1.5M€ MENA automation",
quadrant: "QUICK_WIN"
},
{
rank: 8, name: "WePredict AI Cockpits", category: "Predictive Analytics",
effort: 4, reward: 7, mad_est: 350000, days: 35,
maturity: 72, status: "BETA", ice: 61.25,
competitors: [{name:"Salesforce Einstein", price_idx:10, strength:"CRM native", weakness:"Expensive"}, {name:"HubSpot AI", price_idx:7, strength:"PMF", weakness:"SMB focus"}, {name:"Pipedrive AI", price_idx:6, strength:"Simple", weakness:"Basic models"}],
weval_edge: "16 cockpits · 64 predictions · load monitoring · deal close probability",
market_tam: "3M€ MENA sales intelligence",
quadrant: "BIG_BET"
},
{
rank: 9, name: "WEVAL Arena Command Center", category: "Multi-LLM",
effort: 3, reward: 6, mad_est: 180000, days: 14,
maturity: 88, status: "PROD", ice: 36,
competitors: [{name:"OpenRouter", price_idx:6, strength:"Model routing", weakness:"Pay-per-token"}, {name:"LiteLLM", price_idx:4, strength:"Open-source", weakness:"DIY"}, {name:"Portkey", price_idx:7, strength:"Enterprise", weakness:"Expensive"}],
weval_edge: "409 options · 715 agents · best LLM per use case · 17 providers",
market_tam: "1M€ MENA LLM orchestration",
quadrant: "QUICK_WIN"
},
{
rank: 10, name: "Paperclip PM + CRM", category: "Project Mgmt",
effort: 6, reward: 5, mad_est: 150000, days: 45,
maturity: 60, status: "BETA", ice: 12.5,
competitors: [{name:"Asana", price_idx:8, strength:"Market leader", weakness:"Expensive"}, {name:"Monday", price_idx:9, strength:"UX polish", weakness:"Pricing"}, {name:"Notion", price_idx:7, strength:"Flexibility", weakness:"Not PM native"}],
weval_edge: "48 leads tracked · self-host · integrated WEVIA + WEVADS",
market_tam: "800K€ MA PM tools",
quadrant: "FILL_IN"
}
];
var box = document.getElementById('advisor-decisional-matrix');
if (!box) return;
// Top KPIs bar
var totalMad = solutions.reduce(function(s,x){return s+x.mad_est;},0);
var avgMaturity = Math.round(solutions.reduce(function(s,x){return s+x.maturity;},0)/solutions.length);
var prodCount = solutions.filter(function(x){return x.status==='PROD';}).length;
var html = '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:10px;margin-bottom:14px">';
html += '<div style="padding:10px;background:rgba(0,0,0,.3);border-left:3px solid #f0abfc;border-radius:6px"><div style="font-size:9px;color:#fbcfe8;text-transform:uppercase;font-weight:700">💰 Pipeline total</div><div style="font-size:22px;font-weight:800;color:#f0abfc">'+Math.round(totalMad/1000)+'K<span style="font-size:12px"> MAD</span></div></div>';
html += '<div style="padding:10px;background:rgba(0,0,0,.3);border-left:3px solid #10b981;border-radius:6px"><div style="font-size:9px;color:#6ee7b7;text-transform:uppercase;font-weight:700">✅ PROD ready</div><div style="font-size:22px;font-weight:800;color:#10b981">'+prodCount+'<span style="font-size:12px">/10</span></div></div>';
html += '<div style="padding:10px;background:rgba(0,0,0,.3);border-left:3px solid #22d3ee;border-radius:6px"><div style="font-size:9px;color:#a5f3fc;text-transform:uppercase;font-weight:700">📈 Maturité moy</div><div style="font-size:22px;font-weight:800;color:#22d3ee">'+avgMaturity+'<span style="font-size:12px">%</span></div></div>';
html += '<div style="padding:10px;background:rgba(0,0,0,.3);border-left:3px solid #fbbf24;border-radius:6px"><div style="font-size:9px;color:#fde68a;text-transform:uppercase;font-weight:700">🎯 Solutions</div><div style="font-size:22px;font-weight:800;color:#fbbf24">'+solutions.length+'</div></div>';
html += '</div>';
// Effort vs Reward SCATTER PLOT (inline SVG)
html += '<div style="padding:14px;background:rgba(0,0,0,.35);border-radius:10px;margin-bottom:14px">';
html += '<div style="font-size:11px;color:#f0abfc;font-weight:700;margin-bottom:10px;text-transform:uppercase">📈 Matrice Effort × Rendement (BCG quadrants)</div>';
html += '<svg viewBox="0 0 700 400" style="width:100%;max-width:700px;height:auto;display:block;margin:auto">';
// Grid + quadrants
html += '<rect x="40" y="20" width="640" height="340" fill="rgba(0,0,0,.2)" stroke="rgba(255,255,255,.08)" stroke-width="1"/>';
// Quadrant backgrounds
html += '<rect x="40" y="20" width="320" height="170" fill="rgba(16,185,129,.08)" />'; // QUICK_WIN top-left
html += '<rect x="360" y="20" width="320" height="170" fill="rgba(59,130,246,.08)" />'; // BIG_BET top-right
html += '<rect x="40" y="190" width="320" height="170" fill="rgba(251,191,36,.05)" />'; // FILL_IN bottom-left
html += '<rect x="360" y="190" width="320" height="170" fill="rgba(239,68,68,.05)" />'; // THANKLESS bottom-right
// Axes
html += '<line x1="40" y1="190" x2="680" y2="190" stroke="rgba(255,255,255,.2)" stroke-width="1" stroke-dasharray="4,4"/>';
html += '<line x1="360" y1="20" x2="360" y2="360" stroke="rgba(255,255,255,.2)" stroke-width="1" stroke-dasharray="4,4"/>';
// Axis labels
html += '<text x="360" y="385" text-anchor="middle" fill="#94a3b8" font-size="12" font-weight="700">Effort →</text>';
html += '<text x="20" y="190" text-anchor="middle" fill="#94a3b8" font-size="12" font-weight="700" transform="rotate(-90, 20, 190)">← Rendement</text>';
// Quadrant labels
html += '<text x="200" y="38" text-anchor="middle" fill="#10b981" font-size="10" font-weight="800">🎯 QUICK WIN</text>';
html += '<text x="520" y="38" text-anchor="middle" fill="#3b82f6" font-size="10" font-weight="800">💎 BIG BET</text>';
html += '<text x="200" y="355" text-anchor="middle" fill="#fbbf24" font-size="10" font-weight="800">⚙ FILL-IN</text>';
html += '<text x="520" y="355" text-anchor="middle" fill="#ef4444" font-size="10" font-weight="800">⛔ THANKLESS</text>';
// Plot points
solutions.forEach(function(s){
// effort 0-10 → x 40-680 (range 640)
var x = 40 + (s.effort / 10) * 640;
var y = 360 - (s.reward / 10) * 340;
// Size by MAD (50k=6r, 800k=22r)
var r = 6 + Math.min(16, s.mad_est / 50000);
var colors = {STAR:'#f0abfc', PROD:'#10b981', BETA:'#fbbf24'};
var col = colors[s.status] || '#94a3b8';
html += '<circle cx="'+x+'" cy="'+y+'" r="'+r+'" fill="'+col+'" fill-opacity="0.7" stroke="'+col+'" stroke-width="2"/>';
html += '<text x="'+x+'" y="'+(y+3)+'" text-anchor="middle" fill="#0a0f1a" font-size="10" font-weight="800">'+s.rank+'</text>';
});
html += '</svg>';
html += '<div style="display:flex;gap:14px;margin-top:8px;justify-content:center;font-size:10px;color:#94a3b8">';
html += '<span><span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:#f0abfc;margin-right:3px"></span> STAR</span>';
html += '<span><span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:#10b981;margin-right:3px"></span> PROD</span>';
html += '<span><span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:#fbbf24;margin-right:3px"></span> BETA</span>';
html += '<span>⭕ Taille = pipeline MAD</span>';
html += '</div>';
html += '</div>';
// Ranked solutions list with benchmarks
html += '<div style="display:flex;flex-direction:column;gap:8px">';
solutions.forEach(function(s){
var qCol = {QUICK_WIN:'#10b981', BIG_BET:'#3b82f6', FILL_IN:'#fbbf24', STAR:'#f0abfc', THANKLESS:'#ef4444'}[s.quadrant] || '#94a3b8';
var statusCol = {PROD:'#10b981', BETA:'#fbbf24', ALPHA:'#ef4444'}[s.status] || '#94a3b8';
html += '<div style="padding:12px 14px;background:rgba(0,0,0,.3);border-left:4px solid '+qCol+';border-radius:8px;transition:all .2s" onmouseover="this.style.background=\'rgba(0,0,0,.45)\'" onmouseout="this.style.background=\'rgba(0,0,0,.3)\'">';
// Header
html += '<div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:8px">';
html += '<div style="width:32px;height:32px;border-radius:50%;background:'+qCol+';color:#0a0f1a;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:800">'+s.rank+'</div>';
html += '<div style="font-size:13.5px;color:#e0e7ff;font-weight:700">'+s.name+'</div>';
html += '<span style="padding:2px 8px;border-radius:10px;background:'+qCol+'33;color:'+qCol+';font-size:9px;font-weight:700">'+s.quadrant+'</span>';
html += '<span style="padding:2px 8px;border-radius:10px;background:'+statusCol+'33;color:'+statusCol+';font-size:9px;font-weight:700">'+s.status+'</span>';
html += '<span style="padding:2px 8px;border-radius:10px;background:rgba(148,163,184,.15);color:#94a3b8;font-size:9px;font-weight:700">'+s.category+'</span>';
html += '<span style="margin-left:auto;font-size:15px;color:#fbbf24;font-weight:800">'+Math.round(s.mad_est/1000)+'K MAD</span>';
html += '</div>';
// Stats row
html += '<div style="display:flex;gap:14px;flex-wrap:wrap;margin-bottom:8px;font-size:11px">';
html += '<span style="color:#94a3b8">⚡ Effort <b style="color:#fbbf24">'+s.effort+'/10</b></span>';
html += '<span style="color:#94a3b8">🚀 Rendement <b style="color:#10b981">'+s.reward+'/10</b></span>';
html += '<span style="color:#94a3b8">🎯 ICE <b style="color:#f0abfc">'+s.ice+'</b></span>';
html += '<span style="color:#94a3b8">⏱ Durée <b style="color:#22d3ee">'+s.days+'j</b></span>';
html += '<span style="color:#94a3b8">📊 Maturité <b style="color:'+(s.maturity>=85?'#10b981':(s.maturity>=65?'#fbbf24':'#ef4444'))+'">'+s.maturity+'%</b></span>';
html += '<span style="color:#94a3b8">💰 TAM <b style="color:#6ee7b7">'+s.market_tam+'</b></span>';
html += '</div>';
// WEVAL edge
html += '<div style="padding:8px 10px;background:rgba(16,185,129,.1);border-left:2px solid #10b981;border-radius:4px;margin-bottom:8px;font-size:11px;color:#6ee7b7"><b>💪 Edge WEVAL:</b> '+s.weval_edge+'</div>';
// Benchmark competitors
html += '<div style="padding:8px 10px;background:rgba(239,68,68,.08);border-left:2px solid #ef4444;border-radius:4px;font-size:10.5px">';
html += '<div style="color:#fca5a5;font-weight:700;margin-bottom:4px">🥊 Benchmark concurrence:</div>';
s.competitors.forEach(function(c){
var bars = '█'.repeat(c.price_idx) + '░'.repeat(10-c.price_idx);
html += '<div style="display:flex;gap:8px;margin-bottom:2px;color:#cbd5e1"><span style="width:120px;font-weight:600">'+c.name+'</span><span style="color:#fbbf24;font-family:monospace;font-size:9px">'+bars+'</span><span style="color:#94a3b8;font-size:10px">✅ '+c.strength+' · ⚠ '+c.weakness+'</span></div>';
});
html += '</div>';
html += '</div>'; // card end
});
html += '</div>'; // list end
box.innerHTML = html;
};
// Auto-load on advisor render
setTimeout(function(){
if (document.getElementById('advisor-decisional-matrix')) decisionalMatrix();
}, 800);
// WAVE 246: KPI Dashboard with inline SVG charts
window.loadKpiDashboard = function() {
var box = document.getElementById('advisor-kpi-box');
if (!box) return;
box.innerHTML = '<div style="color:#10b981;font-size:11px">🔍 Loading KPIs + rendering charts...</div>';
fetch('/api/social-signals-hub.php?action=kpi_dashboard&cb='+Date.now())
.then(function(r){return r.json();})
.then(function(d){
var html = '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px">';
// Top KPI cards
var leads = d.leads || {};
var tasks = d.tasks || {};
html += '<div style="padding:12px;background:rgba(0,0,0,.3);border-left:3px solid #10b981;border-radius:6px"><div style="font-size:10px;color:#6ee7b7;text-transform:uppercase;font-weight:700">Leads · MQL avg</div><div style="font-size:22px;font-weight:800;color:#10b981">'+(leads.n||0)+' · <span style="font-size:14px">M'+(leads.avg_mql||0)+'</span></div><div style="font-size:10px;color:#6ee7b7">'+(leads.sql_q||0)+' SQL qualified</div></div>';
html += '<div style="padding:12px;background:rgba(0,0,0,.3);border-left:3px solid #fbbf24;border-radius:6px"><div style="font-size:10px;color:#fde68a;text-transform:uppercase;font-weight:700">Tasks · Pipeline MAD</div><div style="font-size:22px;font-weight:800;color:#fbbf24">'+(tasks.n||0)+' · <span style="font-size:14px">'+Math.round((tasks.total_mad||0)/1000)+'K</span></div><div style="font-size:10px;color:#fde68a">'+Object.keys(d.tasks_by_status||{}).length+' statuses</div></div>';
html += '<div style="padding:12px;background:rgba(0,0,0,.3);border-left:3px solid #22d3ee;border-radius:6px"><div style="font-size:10px;color:#a5f3fc;text-transform:uppercase;font-weight:700">Countries</div><div style="font-size:22px;font-weight:800;color:#22d3ee">'+Object.keys(d.leads_by_country||{}).length+'</div><div style="font-size:10px;color:#a5f3fc">'+Object.keys(d.leads_by_country||{}).slice(0,3).join(' · ')+'</div></div>';
html += '<div style="padding:12px;background:rgba(0,0,0,.3);border-left:3px solid #a855f7;border-radius:6px"><div style="font-size:10px;color:#c4b5fd;text-transform:uppercase;font-weight:700">Industries</div><div style="font-size:22px;font-weight:800;color:#a855f7">'+Object.keys(d.industries||{}).length+'</div><div style="font-size:10px;color:#c4b5fd">'+Object.keys(d.industries||{}).slice(0,3).join(' · ')+'</div></div>';
html += '</div>';
// Inline SVG bar chart: leads_by_country
html += '<div style="margin-top:14px;padding:12px;background:rgba(0,0,0,.25);border-radius:6px"><div style="font-size:11px;color:#6ee7b7;font-weight:700;margin-bottom:8px">🗺 Leads par pays</div>';
var countries = Object.entries(d.leads_by_country||{}).sort(function(a,b){return b[1]-a[1];}).slice(0,8);
var maxC = Math.max.apply(null, countries.map(function(c){return c[1];}).concat([1]));
countries.forEach(function(c){
var pct = Math.round(c[1]/maxC*100);
html += '<div style="display:flex;align-items:center;gap:8px;margin-bottom:3px;font-size:11px"><span style="width:40px;color:#94a3b8">'+c[0]+'</span><div style="flex:1;background:rgba(255,255,255,.04);height:16px;border-radius:3px;position:relative;overflow:hidden"><div style="position:absolute;left:0;top:0;bottom:0;width:'+pct+'%;background:linear-gradient(90deg,#10b981,#6ee7b7)"></div><span style="position:relative;padding-left:6px;color:#e0e7ff;font-weight:700;line-height:16px">'+c[1]+'</span></div></div>';
});
html += '</div>';
// Industries bar chart
html += '<div style="margin-top:10px;padding:12px;background:rgba(0,0,0,.25);border-radius:6px"><div style="font-size:11px;color:#c4b5fd;font-weight:700;margin-bottom:8px">🏭 Industries</div>';
var inds = Object.entries(d.industries||{}).sort(function(a,b){return b[1]-a[1];});
var maxI = Math.max.apply(null, inds.map(function(x){return x[1];}).concat([1]));
inds.forEach(function(it){
var pct = Math.round(it[1]/maxI*100);
html += '<div style="display:flex;align-items:center;gap:8px;margin-bottom:3px;font-size:11px"><span style="width:80px;color:#94a3b8">'+it[0]+'</span><div style="flex:1;background:rgba(255,255,255,.04);height:16px;border-radius:3px;position:relative;overflow:hidden"><div style="position:absolute;left:0;top:0;bottom:0;width:'+pct+'%;background:linear-gradient(90deg,#a855f7,#c4b5fd)"></div><span style="position:relative;padding-left:6px;color:#e0e7ff;font-weight:700;line-height:16px">'+it[1]+'</span></div></div>';
});
html += '</div>';
// Tasks by status
html += '<div style="margin-top:10px;padding:12px;background:rgba(0,0,0,.25);border-radius:6px"><div style="font-size:11px;color:#fde68a;font-weight:700;margin-bottom:8px">📋 Tasks par status + MAD</div>';
Object.entries(d.tasks_by_status||{}).forEach(function(t){
var s = t[0]; var v = t[1];
var cs = {proposed:'#fbbf24',in_progress:'#22d3ee',done:'#10b981',cancelled:'#94a3b8',blocked:'#ef4444'}[s]||'#94a3b8';
html += '<div style="display:flex;align-items:center;gap:8px;margin-bottom:3px;font-size:11px"><span style="width:100px;color:'+cs+';font-weight:700">'+s+'</span><span style="color:#e0e7ff">'+v.count+' tasks · '+Math.round((v.mad||0)/1000)+'K MAD</span></div>';
});
html += '</div>';
box.innerHTML = html;
})
.catch(function(e){ box.innerHTML = '<div style="color:#ef4444">Err: '+e.message+'</div>'; });
};
// WAVE 247: Kanban board
window.loadKanban = function() {
var box = document.getElementById('advisor-kanban-box');
if (!box) return;
box.innerHTML = '<div style="color:#a855f7">Loading kanban…</div>';
fetch('/api/social-signals-hub.php?action=kanban&cb='+Date.now())
.then(function(r){return r.json();})
.then(function(d){
var html = '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:8px">';
var statuses = ['proposed','in_progress','done','cancelled','blocked'];
var cols = {proposed:'#fbbf24',in_progress:'#22d3ee',done:'#10b981',cancelled:'#94a3b8',blocked:'#ef4444'};
statuses.forEach(function(s){
var cards = (d.columns||{})[s] || [];
var mad = (d.mad_by_status||{})[s] || 0;
html += '<div style="padding:10px;background:rgba(0,0,0,.3);border-top:3px solid '+cols[s]+';border-radius:6px;min-height:100px">';
html += '<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;font-size:10px;font-weight:700;color:'+cols[s]+';text-transform:uppercase">'+s+' <span style="opacity:.8">'+cards.length+' · '+Math.round(mad/1000)+'K</span></div>';
cards.forEach(function(c){
html += '<div style="padding:6px;margin-bottom:4px;background:rgba(0,0,0,.35);border-left:2px solid '+cols[s]+';border-radius:3px">';
html += '<div style="font-size:10.5px;color:#e0e7ff;font-weight:600">#'+c.id+' '+(c.title||'?').slice(0,40)+'</div>';
if (c.lead_company) html += '<div style="font-size:9px;color:#22d3ee;margin-top:2px">📌 '+c.lead_company+' MQL '+(c.lead_mql||'?')+'</div>';
if (c.estimated_mad) html += '<div style="font-size:9px;color:#fbbf24;margin-top:2px">'+Math.round(c.estimated_mad/1000)+'K MAD</div>';
html += '</div>';
});
if (!cards.length) html += '<div style="color:#64748b;font-size:10px;text-align:center;padding:8px">empty</div>';
html += '</div>';
});
html += '</div>';
box.innerHTML = html;
})
.catch(function(e){ box.innerHTML = '<div style="color:#ef4444">Err: '+e.message+'</div>'; });
};
// WAVE 248: Pipeline stages
window.loadPipelineStages = function() {
var box = document.getElementById('advisor-pipeline-box');
if (!box) return;
box.innerHTML = '<div style="color:#60a5fa">Loading pipeline…</div>';
fetch('/api/social-signals-hub.php?action=pipeline_stages&cb='+Date.now())
.then(function(r){return r.json();})
.then(function(d){
var html = '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:6px">';
var totalMad = Object.values(d.stages||{}).reduce(function(s,x){return s+(x.mad||0);},0);
Object.entries(d.stages||{}).forEach(function(e){
var s = e[0], v = e[1];
var pct = totalMad ? Math.round(v.mad/totalMad*100) : 0;
html += '<div style="padding:10px;background:rgba(0,0,0,.3);border-bottom:3px solid '+v.color+';border-radius:6px">';
html += '<div style="font-size:10px;color:'+v.color+';font-weight:700;text-transform:uppercase">'+v.name+'</div>';
html += '<div style="font-size:18px;color:#e0e7ff;font-weight:800">'+v.count+'</div>';
html += '<div style="font-size:10px;color:#94a3b8">'+Math.round(v.mad/1000)+'K MAD ('+pct+'%)</div>';
html += '<div style="height:4px;margin-top:4px;background:rgba(255,255,255,.05);border-radius:2px;overflow:hidden"><div style="height:100%;width:'+pct+'%;background:'+v.color+'"></div></div>';
html += '</div>';
});
html += '</div>';
box.innerHTML = html;
})
.catch(function(e){ box.innerHTML = '<div style="color:#ef4444">Err: '+e.message+'</div>'; });
};
// WAVE 249: Activity timeline
window.loadActivityTimeline = function() {
var box = document.getElementById('advisor-timeline-box');
if (!box) return;
box.innerHTML = '<div style="color:#fbbf24">Loading timeline…</div>';
fetch('/api/social-signals-hub.php?action=activity_timeline&cb='+Date.now())
.then(function(r){return r.json();})
.then(function(d){
var html = '<div style="font-size:10px;color:#fde68a;margin-bottom:8px">'+(d.count||0)+' events</div>';
(d.events||[]).forEach(function(e){
var icon = e.type === 'task_created' ? '📋' : (e.type === 'lead_created' ? '👤' : '⚡');
var color = e.type === 'task_created' ? '#22d3ee' : '#10b981';
html += '<div style="padding:8px 10px;margin-bottom:4px;background:rgba(0,0,0,.25);border-left:3px solid '+color+';border-radius:4px">';
html += '<div style="display:flex;align-items:center;gap:6px"><span style="font-size:13px">'+icon+'</span><b style="font-size:11px;color:#e0e7ff">'+(e.title||'?').slice(0,60)+'</b><span style="margin-left:auto;font-size:9px;color:#64748b">'+(e.ts||'').slice(5,16)+'</span></div>';
var meta = e.meta || {};
var metaStr = Object.entries(meta).map(function(x){return x[0]+':'+x[1];}).join(' · ');
if (metaStr) html += '<div style="font-size:9px;color:#94a3b8;margin-top:3px">'+metaStr+'</div>';
html += '</div>';
});
box.innerHTML = html;
})
.catch(function(e){ box.innerHTML = '<div style="color:#ef4444">Err: '+e.message+'</div>'; });
};
// WAVE 250: Search tasks
window.runSearch = function() {
var box = document.getElementById('advisor-search-results');
if (!box) return;
var q = document.getElementById('search-q').value;
var st = document.getElementById('search-status').value;
var mm = document.getElementById('search-min-mad').value;
var url = '/api/social-signals-hub.php?action=search_tasks';
if (q) url += '&q=' + encodeURIComponent(q);
if (st) url += '&status=' + encodeURIComponent(st);
if (mm) url += '&min_mad=' + encodeURIComponent(mm);
url += '&cb=' + Date.now();
box.innerHTML = '<div style="color:#ec4899">Searching…</div>';
fetch(url)
.then(function(r){return r.json();})
.then(function(d){
if (!d.ok || !d.tasks.length) { box.innerHTML = '<div style="color:#94a3b8">No results · '+(d.count||0)+'</div>'; return; }
var html = '<div style="font-size:11px;color:#fbcfe8;margin-bottom:6px">✓ '+d.count+' results for "'+(d.query||'')+'"</div>';
d.tasks.forEach(function(t){
var cs = {proposed:'#fbbf24',in_progress:'#22d3ee',done:'#10b981',cancelled:'#94a3b8',blocked:'#ef4444'}[t.status]||'#94a3b8';
html += '<div style="padding:6px 8px;margin-bottom:3px;background:rgba(0,0,0,.25);border-left:2px solid '+cs+';border-radius:4px">';
html += '<div style="display:flex;align-items:center;gap:6px"><b style="font-size:11px;color:#e0e7ff">#'+t.id+' '+(t.title||'').slice(0,60)+'</b><span style="padding:1px 5px;border-radius:4px;background:'+cs+'22;color:'+cs+';font-size:9px">'+t.status+'</span>';
if (t.estimated_mad) html += '<span style="margin-left:auto;color:#fbbf24;font-size:10px;font-weight:700">'+Math.round(t.estimated_mad/1000)+'K</span>';
html += '</div>';
if (t.lead_company) html += '<div style="font-size:9px;color:#22d3ee;margin-top:2px">📌 '+t.lead_company+' MQL '+(t.lead_mql||'?')+'</div>';
html += '</div>';
});
box.innerHTML = html;
})
.catch(function(e){ box.innerHTML = '<div style="color:#ef4444">Err: '+e.message+'</div>'; });
};
// Auto-load all new sections when advisor tab opens
var origBuildSocialHub = buildSocialHub;
// Already wraps in wave 230 - extend further
setTimeout(function(){
if (document.getElementById('advisor-kpi-box')) {
loadKpiDashboard();
loadKanban();
loadPipelineStages();
loadActivityTimeline();
}
}, 1500);
window.refreshSocialHub = refreshSocialHub;
window.renderAdvisorV2 = renderAdvisor;
})();
</script>
<!-- DOCTRINE-60-UX-JS --><script id="doctrine60-ux-js-direct">
// DOCTRINE-60-UX-JS staggered entrance
(function(){
if (!('IntersectionObserver' in window)) return;
const obs = new IntersectionObserver((entries) => {
entries.forEach((e, i) => {
if (e.isIntersecting) {
setTimeout(() => e.target.classList.add('enter-stagger'), i * 80);
obs.unobserve(e.target);
}
});
});
document.querySelectorAll('.card, .kpi, .panel').forEach(el => obs.observe(el));
})();
</script>
</body>
</html>