Files
html/growth-advisor-v3.html

1112 lines
77 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">
<title>Deep Conversion Advisor · WEVAL</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
<style>
:root{
--ink:#0a0e1a;--ink2:#0f1420;--ink3:#151b2b;--ink4:#1a2030;
--line:rgba(212,168,83,.12);--line2:rgba(212,168,83,.22);--line3:rgba(212,168,83,.35);
--gold:#d4a853;--gold-br:#e6ba6a;--gold-dk:#a57f2e;
--em:#10b981;--em-lt:#6ee7b7;--ru:#ef4444;--sa:#22d3ee;--sa-lt:#a5f3fc;
--am:#a855f7;--am-lt:#c4b5fd;--to:#fbbf24;--to-lt:#fde68a;--ro:#ec4899;
--paper:#f4ecd8;--fog:#94a3b8;--smoke:#64748b;
--serif:'Fraunces',Georgia,serif;--sans:'Inter',system-ui,sans-serif;--mono:'JetBrains Mono',monospace
}
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{font-size:14px;scrollbar-width:auto;scrollbar-color:var(--gold) var(--ink)}
html,body{background:var(--ink);color:var(--paper);font-family:var(--sans);line-height:1.6;min-height:100vh;overflow-x:hidden;overflow-y:auto}
html::-webkit-scrollbar,body::-webkit-scrollbar{width:14px}
html::-webkit-scrollbar-track,body::-webkit-scrollbar-track{background:var(--ink);border-left:1px solid var(--line)}
html::-webkit-scrollbar-thumb,body::-webkit-scrollbar-thumb{background:linear-gradient(180deg,var(--gold),var(--gold-dk));border-radius:7px;border:2px solid var(--ink);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,var(--gold-br),var(--gold))}
/* Ambient */
.ambient{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.ambient::before{content:'';position:absolute;width:800px;height:800px;border-radius:50%;background:radial-gradient(circle,rgba(212,168,83,.06) 0%,transparent 70%);top:-200px;left:-200px;filter:blur(80px)}
.ambient::after{content:'';position:absolute;width:600px;height:600px;border-radius:50%;background:radial-gradient(circle,rgba(34,211,238,.04) 0%,transparent 70%);bottom:-150px;right:-150px;filter:blur(100px)}
.grain{position:fixed;inset:0;z-index:1;pointer-events:none;opacity:.03;mix-blend-mode:overlay;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.85' numOctaves='4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}
.wrap{position:relative;z-index:2;max-width:1600px;margin:0 auto;padding:20px 28px 100px}
@media(max-width:900px){.wrap{padding:16px 14px 80px}}
/* Masthead */
.mast{display:grid;grid-template-columns:auto 1fr auto;gap:20px;align-items:center;padding:14px 0 18px;border-bottom:1px solid var(--line2);margin-bottom:20px}
.mast-brand{display:flex;align-items:center;gap:12px;min-width:0}
.mast-logo{width:38px;height:38px;border:1.5px solid var(--gold);border-radius:50%;display:grid;place-items:center;font-family:var(--serif);font-weight:900;font-size:20px;color:var(--gold);font-style:italic;flex-shrink:0}
.mast-h1{font-family:var(--serif);font-weight:500;font-size:22px;line-height:1.1;letter-spacing:-.02em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mast-h1 em{font-style:italic;color:var(--gold)}
.mast-sub{font-family:var(--serif);font-style:italic;font-size:11.5px;color:var(--fog);margin-top:3px}
.mast-nav{display:flex;gap:4px;flex-wrap:wrap;justify-content:flex-end}
.mast-nav a{font-family:var(--sans);font-size:10px;text-transform:uppercase;letter-spacing:.1em;color:var(--fog);text-decoration:none;padding:6px 11px;border:1px solid var(--line);border-radius:2px;transition:all .15s;white-space:nowrap}
.mast-nav a:hover{border-color:var(--gold);color:var(--paper);background:rgba(212,168,83,.05)}
.mast-meta{text-align:right;font-size:10px;color:var(--smoke);font-family:var(--mono);letter-spacing:.04em}
.mast-meta .wave{color:var(--gold);font-family:var(--serif);font-style:italic;font-size:11px;margin-bottom:2px}
@media(max-width:900px){.mast{grid-template-columns:1fr;gap:12px}.mast-nav{justify-content:flex-start}}
/* Live badge */
.live-strip{display:flex;align-items:center;gap:12px;padding:10px 14px;background:linear-gradient(90deg,rgba(16,185,129,.08),rgba(212,168,83,.04));border:1px solid rgba(16,185,129,.2);border-radius:3px;margin-bottom:24px;font-size:12px}
.live-dot{width:8px;height:8px;border-radius:50%;background:var(--em);box-shadow:0 0 10px var(--em);animation:pulse 1.5s infinite}
@keyframes pulse{50%{opacity:.4}}
.live-strip .hi{color:var(--paper);font-weight:600}
.live-strip .kpi{margin-left:auto;font-family:var(--mono);color:var(--fog);font-size:11px}
/* Section title */
.sec{margin-top:36px;margin-bottom:16px;padding-bottom:10px;border-bottom:1px solid var(--line);display:flex;align-items:baseline;gap:14px;flex-wrap:wrap}
.sec-n{font-family:var(--serif);font-style:italic;color:var(--gold);font-size:13px;font-weight:400;flex-shrink:0}
.sec h2{font-family:var(--serif);font-weight:500;font-size:20px;letter-spacing:-.01em}
.sec h2 em{font-style:italic;color:var(--gold)}
.sec-kick{font-family:var(--sans);font-size:10px;text-transform:uppercase;letter-spacing:.15em;color:var(--fog);margin-left:auto}
.sec-actions{margin-left:auto;display:flex;gap:6px}
.btn{font-family:var(--sans);font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;padding:6px 11px;background:transparent;color:var(--fog);border:1px solid var(--line2);border-radius:2px;cursor:pointer;transition:all .15s;text-decoration:none;display:inline-flex;align-items:center;gap:5px}
.btn:hover{border-color:var(--gold);color:var(--gold);background:rgba(212,168,83,.05)}
.btn.primary{color:var(--gold);border-color:var(--gold)}
.btn.primary:hover{background:var(--gold);color:var(--ink)}
/* Live feeds */
.feeds{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
@media(max-width:1100px){.feeds{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.feeds{grid-template-columns:1fr}}
.feed{padding:16px 18px;border:1px solid var(--line);border-radius:3px;background:linear-gradient(135deg,var(--ink2) 0%,var(--ink) 100%);position:relative;transition:all .2s}
.feed::before{content:'';position:absolute;top:0;left:0;right:0;height:2px;background:var(--gold)}
.feed.f1::before{background:var(--em)}.feed.f2::before{background:var(--sa)}.feed.f3::before{background:var(--am)}.feed.f4::before{background:var(--to)}
.feed:hover{transform:translateY(-2px);border-color:var(--line2)}
.feed-k{font-family:var(--mono);font-size:9px;text-transform:uppercase;letter-spacing:.15em;color:var(--fog);margin-bottom:8px}
.feed-v{font-family:var(--serif);font-weight:600;font-size:34px;line-height:1;letter-spacing:-.02em;margin-bottom:6px}
.feed.f1 .feed-v{color:var(--em)}.feed.f2 .feed-v{color:var(--sa)}.feed.f2.alert .feed-v{color:var(--ru)}.feed.f3 .feed-v{color:var(--am)}.feed.f4 .feed-v{color:var(--to)}
.feed-s{font-size:11px;color:var(--fog)}.feed-s .hi{color:var(--paper);font-weight:500}
/* Priorities grid */
.prio{display:grid;grid-template-columns:1.3fr 1fr;gap:20px;margin-top:8px}
@media(max-width:1100px){.prio{grid-template-columns:1fr}}
.top5{padding:22px 24px;background:linear-gradient(135deg,rgba(34,211,238,.04),rgba(168,85,247,.03));border:1px solid var(--line2);border-radius:3px}
.top5-h{display:flex;align-items:baseline;gap:10px;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid var(--line)}
.top5-h h3{font-family:var(--serif);font-weight:500;font-size:16px}
.top5-h .badge{font-family:var(--mono);font-size:9px;text-transform:uppercase;color:var(--sa);padding:3px 7px;border:1px solid rgba(34,211,238,.3);border-radius:2px;letter-spacing:.12em}
.act{display:grid;grid-template-columns:44px 1fr auto;gap:14px;padding:12px 0;border-bottom:1px dashed var(--line);align-items:start;transition:padding .15s}
.act:last-child{border-bottom:none}
.act:hover{padding-left:6px}
.act-r{font-family:var(--serif);font-weight:600;font-size:24px;color:var(--gold);font-style:italic;line-height:1}
.act-b{min-width:0}
.act-t{font-family:var(--serif);font-weight:500;font-size:14.5px;color:var(--paper);margin-bottom:3px}
.act-w{font-size:12px;color:var(--fog);line-height:1.5;margin-bottom:5px}
.act-d{font-family:var(--mono);font-size:10px;color:var(--smoke)}
.act-d::before{content:'↳ ';color:var(--gold)}
.act-arr{font-family:var(--serif);font-style:italic;font-size:18px;color:var(--gold);opacity:.5;transition:all .15s}
.act:hover .act-arr{opacity:1;transform:translateX(3px)}
.llm{padding:22px 24px;background:linear-gradient(135deg,rgba(168,85,247,.05),rgba(212,168,83,.04));border:1px solid rgba(168,85,247,.2);border-radius:3px;min-height:280px}
.llm-h{display:flex;align-items:center;gap:10px;margin-bottom:14px;padding-bottom:10px;border-bottom:1px solid rgba(168,85,247,.15)}
.llm-h h3{font-family:var(--serif);font-weight:500;font-size:15px}
.llm-h em{font-style:italic;color:var(--am)}
.llm-cas{font-family:var(--mono);font-size:9px;color:var(--fog);letter-spacing:.1em;margin-left:auto}
.llm-body{font-size:12.5px;line-height:1.7}
.llm-load{display:flex;align-items:center;gap:10px;padding:18px 0;color:var(--am);font-family:var(--serif);font-style:italic}
.llm-rec{margin-bottom:12px;padding:12px 14px;background:rgba(168,85,247,.05);border-left:3px solid var(--am);border-radius:0 3px 3px 0}
.llm-rec-t{display:flex;align-items:baseline;gap:8px;margin-bottom:4px;font-family:var(--serif);font-weight:500;font-size:13.5px}
.llm-rec-t .rk{font-family:var(--serif);font-style:italic;color:var(--am);font-size:16px;font-weight:600}
.llm-rec-t .rv{margin-left:auto;font-family:var(--mono);font-size:10.5px;color:var(--to)}
.llm-rec-tm{font-family:var(--mono);font-size:9.5px;color:var(--fog);margin-bottom:5px;letter-spacing:.05em}
.llm-rec-s{font-size:11.5px;color:var(--fog);padding:2px 0 2px 14px;position:relative}
.llm-rec-s::before{content:'▸';position:absolute;left:0;color:var(--em)}
/* Matrix 2x2 */
.mx{display:grid;grid-template-columns:1fr 1fr;gap:2px;background:var(--line2);border:1px solid var(--line2);border-radius:3px;overflow:hidden}
.mx-c{padding:18px 20px;background:var(--ink2);min-height:140px}
.mx-c.qw{background:linear-gradient(135deg,var(--ink2),rgba(16,185,129,.04))}
.mx-c.bb{background:linear-gradient(135deg,var(--ink2),rgba(251,191,36,.04))}
.mx-c.fi{background:linear-gradient(135deg,var(--ink2),rgba(34,211,238,.03))}
.mx-c.th{background:linear-gradient(135deg,var(--ink2),rgba(239,68,68,.03))}
.mx-lbl{font-family:var(--mono);font-size:9px;text-transform:uppercase;letter-spacing:.12em;color:var(--fog);margin-bottom:6px}
.mx-t{font-family:var(--serif);font-weight:500;font-size:14px;margin-bottom:3px}
.mx-t em{font-style:italic;color:var(--gold)}
.mx-v{font-family:var(--serif);font-weight:600;font-size:22px;margin-bottom:10px}
.mx-c.qw .mx-v{color:var(--em)}.mx-c.bb .mx-v{color:var(--to)}.mx-c.fi .mx-v{color:var(--sa)}.mx-c.th .mx-v{color:var(--ru)}
.mx-it{font-size:11px;color:var(--fog);line-height:1.5}
.mx-it .i{padding:2px 0 2px 12px;border-bottom:1px dotted var(--line);position:relative}
.mx-it .i::before{content:'·';position:absolute;left:2px;color:var(--gold)}
.mx-it .i:last-child{border-bottom:none}
@media(max-width:700px){.mx{grid-template-columns:1fr}}
/* Chips */
.chips{display:flex;flex-wrap:wrap;gap:6px}
.chip{padding:5px 10px;border:1px solid var(--line2);border-radius:2px;font-family:var(--mono);font-size:10px;color:var(--paper);background:var(--ink2);letter-spacing:.03em;transition:all .15s}
.chip:hover{border-color:var(--gold);background:rgba(212,168,83,.05);color:var(--gold)}
.chip .st{display:inline-block;width:6px;height:6px;border-radius:50%;margin-right:6px;vertical-align:middle}
.chip .st.up{background:var(--em);box-shadow:0 0 4px var(--em)}
.chip .st.dn{background:var(--ru)}
.chip .meta{color:var(--fog);font-size:9px;margin-left:6px}
/* Social hub */
.social{display:grid;grid-template-columns:repeat(5,1fr);gap:10px;margin-bottom:20px}
@media(max-width:1100px){.social{grid-template-columns:repeat(3,1fr)}}
@media(max-width:560px){.social{grid-template-columns:repeat(2,1fr)}}
.s-card{padding:12px 14px;border:1px solid var(--line);border-radius:3px;background:var(--ink2);transition:all .15s}
.s-card:hover{border-color:var(--line2);transform:translateY(-1px)}
.s-card .k{font-family:var(--mono);font-size:9px;text-transform:uppercase;letter-spacing:.1em;color:var(--fog);margin-bottom:6px;display:flex;align-items:center;gap:5px}
.s-card .n{font-family:var(--serif);font-weight:600;font-size:22px;line-height:1;color:var(--paper);margin-bottom:4px}
.s-card .d{font-size:10.5px;color:var(--fog);line-height:1.4}
/* LLM ideas */
.ideas{display:grid;grid-template-columns:repeat(auto-fit,minmax(380px,1fr));gap:14px}
.idea{padding:16px 18px;border:1px solid var(--line2);border-radius:3px;background:linear-gradient(135deg,var(--ink2),rgba(168,85,247,.03));position:relative}
.idea-h{display:flex;align-items:baseline;gap:8px;margin-bottom:8px}
.idea-r{font-family:var(--serif);font-weight:600;font-style:italic;font-size:16px;color:var(--am)}
.idea-t{font-family:var(--serif);font-weight:500;font-size:14px;flex:1}
.idea-rv{font-family:var(--mono);font-size:10.5px;color:var(--to);white-space:nowrap}
.idea-g{font-size:11.5px;color:var(--fog);margin-bottom:8px;line-height:1.5}
.idea-src{font-family:var(--mono);font-size:9px;color:var(--am);margin-bottom:8px}
.idea-tools{font-size:10.5px;color:var(--paper);margin-bottom:8px;padding:6px 0;border-top:1px dashed var(--line);border-bottom:1px dashed var(--line)}
.idea-tools::before{content:'🔧 ';color:var(--gold)}
.idea-s{font-size:11px;color:var(--fog);padding:2px 0 2px 14px;position:relative;line-height:1.5}
.idea-s::before{content:'→';position:absolute;left:0;color:var(--em)}
.idea-kpi{margin-top:8px;padding:6px 10px;background:rgba(16,185,129,.06);border-radius:2px;font-size:10.5px;color:var(--em-lt);font-family:var(--mono)}
/* Tasks */
.tasks{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:12px}
.task{padding:14px 16px;border:1px solid var(--line);border-radius:3px;background:var(--ink2)}
.task-h{display:flex;align-items:baseline;gap:8px;margin-bottom:6px}
.task-n{font-family:var(--serif);font-style:italic;font-size:18px;color:var(--gold)}
.task-t{font-family:var(--sans);font-size:13px;font-weight:500;flex:1}
.task-st{font-family:var(--mono);font-size:9px;padding:2px 7px;border-radius:2px;text-transform:uppercase;letter-spacing:.08em}
.task-st.proposed{background:rgba(148,163,184,.15);color:var(--fog)}
.task-st.in_progress{background:rgba(34,211,238,.15);color:var(--sa)}
.task-st.done{background:rgba(16,185,129,.15);color:var(--em-lt)}
.task-st.cancelled{background:rgba(239,68,68,.15);color:var(--ru)}
.task-mad{font-family:var(--mono);font-size:11px;color:var(--to);margin-bottom:4px}
.task-op{font-size:11px;color:var(--fog);margin-bottom:4px}
.task-op::before{content:'🎯 ';color:var(--gold)}
.task-tr{display:flex;gap:4px;flex-wrap:wrap;margin-top:8px;padding-top:8px;border-top:1px dashed var(--line)}
.task-tr button{font-family:var(--mono);font-size:9px;padding:3px 7px;background:transparent;color:var(--fog);border:1px solid var(--line);border-radius:2px;cursor:pointer;text-transform:uppercase}
.task-tr button:hover{border-color:var(--gold);color:var(--gold)}
/* Leads */
.leads{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px}
.lead{padding:12px 14px;border:1px solid var(--line);border-radius:3px;background:var(--ink2);transition:all .15s}
.lead:hover{border-color:var(--line2)}
.lead-h{display:flex;align-items:baseline;gap:8px;margin-bottom:6px}
.lead-n{font-family:var(--serif);font-weight:500;font-size:13.5px;flex:1}
.lead-mql{font-family:var(--mono);font-size:10px;padding:2px 6px;background:rgba(16,185,129,.1);color:var(--em-lt);border-radius:2px}
.lead-meta{font-size:10.5px;color:var(--fog);margin-bottom:4px}
.lead-desc{font-size:11px;color:var(--smoke);line-height:1.4}
/* Competitors */
.comps{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px}
.comp{padding:14px 16px;border:1px solid var(--line);border-radius:3px;background:var(--ink2)}
.comp-n{font-family:var(--serif);font-weight:500;font-size:13.5px;margin-bottom:3px;display:flex;align-items:baseline;gap:8px}
.comp-th{font-family:var(--mono);font-size:9px;padding:2px 6px;border-radius:2px;text-transform:uppercase}
.comp-th.high{background:rgba(239,68,68,.15);color:var(--ru)}
.comp-th.medium{background:rgba(251,191,36,.15);color:var(--to)}
.comp-th.low{background:rgba(16,185,129,.15);color:var(--em-lt)}
.comp-c{font-family:var(--mono);font-size:9px;color:var(--fog);margin-bottom:6px;letter-spacing:.1em;text-transform:uppercase}
.comp-vs{font-size:10.5px;color:var(--fog);margin-bottom:5px}
.comp-vs::before{content:'vs · ';color:var(--gold)}
.comp-e{font-size:10.5px;color:var(--em-lt);line-height:1.45}
.comp-e::before{content:'💪 ';color:var(--em)}
/* Generic loading */
.skel{background:linear-gradient(90deg,var(--ink2) 0%,var(--ink3) 50%,var(--ink2) 100%);background-size:200% 100%;animation:sk 1.4s ease-in-out infinite;border-radius:2px;color:transparent;display:inline-block;min-width:40px;min-height:1em}
@keyframes sk{to{background-position:-200% 0}}
.spnr{display:inline-block;width:12px;height:12px;border:1.5px solid var(--gold);border-top-color:transparent;border-radius:50%;animation:spin .9s linear infinite;vertical-align:middle}
@keyframes spin{to{transform:rotate(360deg)}}
.load-inline{color:var(--fog);font-family:var(--serif);font-style:italic;font-size:13px;padding:14px 0}
.err{padding:12px 14px;background:rgba(239,68,68,.08);border:1px solid rgba(239,68,68,.3);border-radius:3px;color:var(--ru);font-family:var(--mono);font-size:11px}
/* Chat dock */
.ck-tog{position:fixed;bottom:22px;left:22px;z-index:100;padding:10px 16px;background:var(--gold);color:var(--ink);border:0;border-radius:2px;font-family:var(--serif);font-style:italic;font-size:12px;font-weight:600;cursor:pointer;box-shadow:0 4px 20px rgba(212,168,83,.3);transition:transform .15s}
.ck-tog:hover{transform:translateY(-2px)}
.ck{position:fixed;bottom:78px;left:22px;z-index:99;width:360px;max-width:calc(100vw - 44px);background:var(--ink2);border:1px solid var(--line2);border-radius:3px;box-shadow:0 12px 40px rgba(0,0,0,.6);display:none;flex-direction:column}
.ck.open{display:flex}
.ck-h{padding:10px 14px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:8px;font-family:var(--serif);font-weight:500;font-size:13px}
.ck-h em{font-style:italic;color:var(--gold)}
.ck-x{margin-left:auto;background:none;border:0;color:var(--fog);cursor:pointer;font-size:18px;line-height:1}
.ck-b{max-height:380px;overflow-y:auto;padding:10px 14px;font-size:12.5px;line-height:1.55}
.ck-b::-webkit-scrollbar{width:6px}.ck-b::-webkit-scrollbar-thumb{background:var(--gold);border-radius:3px}
.ck-b .mg{margin-bottom:8px;padding:7px 10px;border-radius:3px}
.ck-b .mg.us{background:var(--ink3);margin-left:30px;color:var(--paper)}
.ck-b .mg.ai{background:rgba(212,168,83,.05);border-left:2px solid var(--gold);color:var(--paper)}
.ck-f{padding:10px;border-top:1px solid var(--line);display:flex;gap:6px}
.ck-f input{flex:1;background:var(--ink3);border:1px solid var(--line);color:var(--paper);padding:7px 10px;font-size:11.5px;border-radius:2px;font-family:var(--sans)}
.ck-f input:focus{outline:none;border-color:var(--gold)}
.ck-f button{padding:7px 12px;background:var(--gold);color:var(--ink);border:0;font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.08em;cursor:pointer;border-radius:2px}
/* Backlink */
.back{position:fixed;bottom:22px;right:22px;z-index:100;padding:9px 15px;background:var(--ink2);border:1px solid var(--line2);border-radius:2px;text-decoration:none;color:var(--paper);font-family:var(--serif);font-style:italic;font-size:12px;transition:all .15s;backdrop-filter:blur(10px);box-shadow:0 4px 20px rgba(0,0,0,.4)}
.back:hover{border-color:var(--gold);color:var(--gold);transform:translateY(-2px)}
.back::before{content:'← ';color:var(--gold)}
/* Quick prompts */
.qp{display:flex;gap:6px;flex-wrap:wrap;margin-top:10px}
.qp button{font-family:var(--sans);font-size:10.5px;padding:5px 10px;background:transparent;color:var(--fog);border:1px solid var(--line);border-radius:2px;cursor:pointer;transition:all .15s}
.qp button:hover{border-color:var(--gold);color:var(--gold);background:rgba(212,168,83,.05)}
/* Animations */
.fade{animation:fi .5s ease-out backwards}
@keyframes fi{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
/* === PREMIUM UX ULTRA MAX === */
/* Kanban */
.kb{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-top:8px}
@media(max-width:900px){.kb{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.kb{grid-template-columns:1fr}}
.kb-col{background:var(--ink2);border:1px solid var(--line);border-radius:3px;padding:12px;min-height:180px;transition:border-color .2s}
.kb-col:hover{border-color:var(--line2)}
.kb-h{display:flex;align-items:center;gap:8px;margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--line)}
.kb-h .ic{width:10px;height:10px;border-radius:50%}
.kb-h.proposed .ic{background:var(--fog)}.kb-h.in_progress .ic{background:var(--sa);box-shadow:0 0 5px var(--sa)}
.kb-h.done .ic{background:var(--em);box-shadow:0 0 5px var(--em)}.kb-h.cancelled .ic{background:var(--ru)}
.kb-h h4{font-family:var(--serif);font-weight:500;font-size:13px}
.kb-h .cnt{margin-left:auto;font-family:var(--mono);font-size:10px;color:var(--fog);padding:2px 7px;background:var(--ink3);border-radius:10px}
.kb-card{padding:10px 11px;margin-bottom:8px;background:var(--ink3);border:1px solid var(--line);border-left:2px solid var(--gold);border-radius:2px;transition:all .15s;cursor:default}
.kb-card:hover{transform:translateX(3px);border-left-color:var(--gold-br)}
.kb-card-t{font-family:var(--sans);font-size:11.5px;font-weight:500;color:var(--paper);line-height:1.4;margin-bottom:5px}
.kb-card-m{font-family:var(--mono);font-size:10px;color:var(--to);margin-bottom:3px}
.kb-card-l{font-size:10px;color:var(--fog)}
.kb-card-l b{color:var(--em-lt);font-family:var(--mono)}
/* Pipeline funnel */
.pf{display:flex;flex-direction:column;gap:6px;margin-top:8px}
.pf-stage{display:flex;align-items:center;gap:14px;padding:12px 16px;background:linear-gradient(90deg,rgba(212,168,83,.06),rgba(12,17,32,0));border-left:3px solid var(--gold);border-radius:0 3px 3px 0;transition:all .15s}
.pf-stage:hover{background:linear-gradient(90deg,rgba(212,168,83,.12),rgba(12,17,32,0))}
.pf-lbl{font-family:var(--serif);font-weight:500;font-size:13px;min-width:140px}
.pf-bar{flex:1;height:28px;background:var(--ink3);border-radius:2px;overflow:hidden;position:relative}
.pf-fill{height:100%;background:linear-gradient(90deg,var(--gold),var(--gold-br));transition:width .6s ease-out;display:flex;align-items:center;padding:0 10px;font-family:var(--mono);font-size:11px;color:var(--ink);font-weight:600}
.pf-val{font-family:var(--mono);font-size:11px;color:var(--fog);min-width:90px;text-align:right}
/* KPI Dashboard cards */
.kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin-top:8px}
.kpi-card{padding:14px 16px;border:1px solid var(--line);border-radius:3px;background:var(--ink2);position:relative;overflow:hidden;transition:all .2s}
.kpi-card:hover{border-color:var(--line2);transform:translateY(-2px)}
.kpi-card .k{font-family:var(--mono);font-size:9px;text-transform:uppercase;letter-spacing:.12em;color:var(--fog);margin-bottom:6px}
.kpi-card .v{font-family:var(--serif);font-weight:600;font-size:26px;line-height:1;margin-bottom:3px;color:var(--gold)}
.kpi-card .d{font-size:10.5px;color:var(--fog)}
.kpi-card.ok .v{color:var(--em-lt)}.kpi-card.warn .v{color:var(--to-lt)}.kpi-card.fail .v{color:var(--ru)}
.kpi-spark{position:absolute;right:8px;top:8px;width:50px;height:24px;opacity:.7}
/* Timeline unified feed */
.tl{position:relative;padding-left:24px;margin-top:8px}
.tl::before{content:'';position:absolute;left:8px;top:0;bottom:0;width:1px;background:linear-gradient(180deg,var(--gold),var(--line2),var(--gold))}
.tl-item{position:relative;padding:8px 0 8px 12px;border-bottom:1px dotted var(--line)}
.tl-item::before{content:'';position:absolute;left:-20px;top:14px;width:8px;height:8px;border-radius:50%;background:var(--gold);border:2px solid var(--ink);box-shadow:0 0 8px var(--gold)}
.tl-item.info::before{background:var(--sa);box-shadow:0 0 8px var(--sa)}
.tl-item.ok::before{background:var(--em);box-shadow:0 0 8px var(--em)}
.tl-item.warn::before{background:var(--to);box-shadow:0 0 8px var(--to)}
.tl-item.err::before{background:var(--ru);box-shadow:0 0 8px var(--ru)}
.tl-item .t{font-size:12.5px;color:var(--paper);margin-bottom:2px}
.tl-item .m{font-family:var(--mono);font-size:9.5px;color:var(--fog);letter-spacing:.03em}
.tl-item .d{font-size:10.5px;color:var(--smoke);margin-top:2px}
/* Task Search */
.ts-form{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px;padding:12px 14px;background:var(--ink2);border:1px solid var(--line);border-radius:3px}
.ts-form input,.ts-form select{background:var(--ink3);border:1px solid var(--line);color:var(--paper);padding:7px 10px;font-family:var(--sans);font-size:11.5px;border-radius:2px;outline:none;transition:border-color .15s}
.ts-form input:focus,.ts-form select:focus{border-color:var(--gold)}
.ts-form input[type=text]{flex:1;min-width:200px}
.ts-form button{padding:7px 14px;background:var(--gold);color:var(--ink);border:0;font-family:var(--sans);font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.08em;cursor:pointer;border-radius:2px}
.ts-results{margin-top:10px;font-size:11.5px;color:var(--fog)}
/* SSE Stream */
.sse-box{background:var(--ink2);border:1px solid var(--line);border-radius:3px;padding:14px 16px;margin-top:8px}
.sse-ctrl{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.sse-btn{padding:8px 14px;background:var(--em);color:var(--ink);border:0;border-radius:2px;font-family:var(--mono);font-size:10.5px;font-weight:600;cursor:pointer;text-transform:uppercase;letter-spacing:.08em}
.sse-btn.stop{background:var(--ru)}
.sse-status{font-family:var(--mono);font-size:10.5px;color:var(--fog)}
.sse-status.live{color:var(--em-lt)}
.sse-log{max-height:240px;overflow-y:auto;background:var(--ink);border-radius:2px;padding:10px 12px;font-family:var(--mono);font-size:10.5px;line-height:1.5;color:var(--paper);scrollbar-width:thin;scrollbar-color:var(--gold) var(--ink)}
.sse-log::-webkit-scrollbar{width:6px}.sse-log::-webkit-scrollbar-thumb{background:var(--gold);border-radius:3px}
.sse-log .l{padding:3px 0;border-bottom:1px dotted var(--line)}
.sse-log .l .tm{color:var(--fog);margin-right:8px}
.sse-log .l .ch{color:var(--gold);margin-right:8px}
.sse-log .empty{color:var(--fog);font-style:italic;font-family:var(--serif);padding:20px 0;text-align:center}
/* Agent badges (Multiagent + Grounded) */
.agent-badges{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:8px}
@media(max-width:700px){.agent-badges{grid-template-columns:1fr}}
.ag-badge{padding:14px 18px;border-radius:3px;position:relative;overflow:hidden}
.ag-badge.multi{background:linear-gradient(135deg,rgba(168,85,247,.08),rgba(34,211,238,.05));border:1px solid rgba(168,85,247,.25)}
.ag-badge.ground{background:linear-gradient(135deg,rgba(16,185,129,.08),rgba(212,168,83,.04));border:1px solid rgba(16,185,129,.25)}
.ag-h{display:flex;align-items:center;gap:10px;margin-bottom:8px}
.ag-ic{font-size:18px}
.ag-h h4{font-family:var(--serif);font-weight:500;font-size:14px;flex:1}
.ag-h em{font-style:italic;color:var(--gold)}
.ag-h .st{font-family:var(--mono);font-size:9px;padding:3px 8px;background:rgba(16,185,129,.15);color:var(--em-lt);border-radius:2px;letter-spacing:.08em;text-transform:uppercase}
.ag-desc{font-size:11.5px;color:var(--fog);line-height:1.55;margin-bottom:10px}
.ag-btns{display:flex;gap:6px;flex-wrap:wrap}
.ag-btn{padding:5px 10px;background:transparent;color:var(--fog);border:1px solid var(--line);border-radius:2px;font-family:var(--mono);font-size:10px;cursor:pointer;transition:all .15s}
.ag-btn:hover{border-color:var(--gold);color:var(--gold)}
/* Feed sparkline integration */
.feed{position:relative}
.feed .spark{position:absolute;bottom:10px;right:10px;width:60px;height:18px;opacity:.6}
/* /PREMIUM UX */
</style>
<!-- DOCTRINE-60-UX-ENRICH direct-inject-20260424-143816 -->
<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>
</head>
<body>
<div class="ambient"></div>
<div class="grain"></div>
<div class="wrap">
<!-- MASTHEAD -->
<header class="mast">
<div class="mast-brand">
<div class="mast-logo">w</div>
<div>
<div class="mast-h1">Deep Conversion <em>Advisor</em></div>
<div class="mast-sub">A real-time revenue intelligence brief — WEVAL Consulting</div>
</div>
</div>
<nav class="mast-nav">
<a href="/growth-engine-v2.html">Growth v2</a>
<a href="/wevia-master.html">Master</a>
<a href="/director.html">Director</a>
<a href="/crm.html">CRM</a>
<a href="/weval-technology-platform.html">WTP</a>
</nav>
<div class="mast-meta">
<div class="wave" id="wave">Wave —</div>
<div id="ts">loading…</div>
</div>
</header>
<!-- LIVE STRIP -->
<div class="live-strip fade">
<div class="live-dot"></div>
<span>Deep Conversion Advisor <span class="hi">V2 · LIVE</span></span>
<span class="kpi" id="livekpi">— leads · — scout scans · patterns —</span>
</div>
<!-- I · LIVE FEEDS -->
<div class="sec"><span class="sec-n">I.</span><h2>Live <em>feeds</em></h2><span class="sec-kick">Real-time signals</span></div>
<div class="feeds fade">
<div class="feed f1"><div class="feed-k">📊 Paperclip Leads</div><div class="feed-v skel" id="f-leads"></div><div class="feed-s skel" id="f-leads-s">loading…</div></div>
<div class="feed f2" id="f-predict-box"><div class="feed-k">⚡ WePredict</div><div class="feed-v skel" id="f-predict"></div><div class="feed-s skel" id="f-predict-s">loading…</div></div>
<div class="feed f3"><div class="feed-k">🕵 Dark Scout</div><div class="feed-v skel" id="f-scout"></div><div class="feed-s skel" id="f-scout-s">loading…</div></div>
<div class="feed f4"><div class="feed-k">💰 Pipeline MAD</div><div class="feed-v skel" id="f-mad"></div><div class="feed-s skel" id="f-mad-s">loading…</div></div>
</div>
<!-- II · TOP5 + LLM -->
<div class="sec"><span class="sec-n">II.</span><h2>Top 5 &amp; <em>reasoning</em></h2><div class="sec-actions"><button class="btn" onclick="loadMain()">↻ Refresh</button></div></div>
<div class="prio fade">
<section class="top5"><div class="top5-h"><h3>🚀 Actions prioritaires</h3><span class="badge">Live</span></div><div id="top5"><div class="load-inline"><span class="spnr"></span> loading…</div></div></section>
<aside class="llm"><div class="llm-h"><h3>🤖 LLM-powered <em>recommendations</em></h3><span class="llm-cas">Cerebras → Groq → Mistral</span></div><div id="llm" class="llm-body"><div class="llm-load"><span class="spnr"></span> Querying sovereign cascade…</div></div></aside>
</div>
<!-- III · SOCIAL SIGNALS HUB -->
<div class="sec"><span class="sec-n">III.</span><h2>📡 Social <em>signals hub</em></h2><span class="sec-kick">Conversion ideas adaptées · Wave 230</span><div class="sec-actions"><button class="btn" onclick="loadSocial()">↻ Refresh</button></div></div>
<div class="social fade" id="social-strip"><div class="s-card skel">loading…</div><div class="s-card skel">loading…</div><div class="s-card skel">loading…</div><div class="s-card skel">loading…</div><div class="s-card skel">loading…</div></div>
<h3 style="font-family:var(--serif);font-weight:500;font-size:15px;margin:18px 0 10px;color:var(--am-lt)">✨ LLM Conversion Ideas</h3>
<div class="ideas" id="ideas"><div class="idea load-inline"><span class="spnr"></span> loading ideas…</div></div>
<!-- IV · PAPERCLIP TASKS -->
<div class="sec"><span class="sec-n">IV.</span><h2>📋 Paperclip <em>tasks</em></h2><span class="sec-kick">Auto-created · Wave 231</span><div class="sec-actions"><button class="btn" onclick="loadTasks()">↻ Refresh</button></div></div>
<div class="tasks fade" id="tasks"><div class="task load-inline"><span class="spnr"></span> loading tasks…</div></div>
<!-- V · DECISIONAL MATRIX -->
<div class="sec"><span class="sec-n">V.</span><h2>📊 Matrice <em>Effort × Impact</em></h2><span class="sec-kick">Eisenhower · Wave 251</span></div>
<div class="mx fade">
<div class="mx-c qw"><div class="mx-lbl">HIGH IMPACT · LOW EFFORT</div><div class="mx-t"><em>Quick wins</em></div><div class="mx-v skel" id="mx-qw-v"></div><div class="mx-it skel" id="mx-qw">loading…</div></div>
<div class="mx-c bb"><div class="mx-lbl">HIGH IMPACT · HIGH EFFORT</div><div class="mx-t">🎯 <em>Big bets</em></div><div class="mx-v skel" id="mx-bb-v"></div><div class="mx-it skel" id="mx-bb">loading…</div></div>
<div class="mx-c fi"><div class="mx-lbl">LOW IMPACT · LOW EFFORT</div><div class="mx-t">💡 <em>Fill-ins</em></div><div class="mx-v" id="mx-fi-v"></div><div class="mx-it skel" id="mx-fi">loading…</div></div>
<div class="mx-c th"><div class="mx-lbl">LOW IMPACT · HIGH EFFORT</div><div class="mx-t"><em>Thankless</em></div><div class="mx-v" id="mx-th-v"></div><div class="mx-it skel" id="mx-th">loading…</div></div>
</div>
<!-- VI · SOVEREIGN AI -->
<div class="sec"><span class="sec-n">VI.</span><h2>🧠 Sovereign <em>AI stack</em></h2><span class="sec-kick" id="sov-count">— providers</span></div>
<div class="chips fade" id="chips"><span class="chip skel">loading…</span><span class="chip skel">loading…</span><span class="chip skel">loading…</span></div>
<!-- VII · COMPETITORS -->
<div class="sec"><span class="sec-n">VII.</span><h2>🥊 Competitive <em>intel</em></h2><span class="sec-kick">Dark Scout integrated</span></div>
<div class="comps fade" id="comps"><div class="comp load-inline"><span class="spnr"></span> loading competitive intel…</div></div>
<!-- VIII · LEADS -->
<div class="sec"><span class="sec-n">VIII.</span><h2>📋 Top 10 <em>leads</em></h2><span class="sec-kick">Paperclip live</span></div>
<div class="leads fade" id="leads"><div class="lead load-inline"><span class="spnr"></span> loading leads…</div></div>
<!-- IX · SOLUTION SCANNER -->
<div class="sec"><span class="sec-n">IX.</span><h2>🧠 Solution <em>Scanner</em></h2><span class="sec-kick">Predictive · Wave 252 · AI PREDICT</span><div class="sec-actions"><button class="btn" onclick="loadSolutionScanner()">↻ Re-analyze</button></div></div>
<div id="solution-scanner" class="fade"><div class="load-inline"><span class="spnr"></span> Loading predictive analysis…</div></div>
</div>
<!-- CHAT WEVIA -->
<!-- X. AGENT BADGES -->
<div class="sec"><span class="sec-n">X.</span><h2>🧠 WEVIA <em>Agent badges</em></h2><span class="sec-kick">Multi-agent · 0 hallucination · Waves 253-254</span></div>
<div class="agent-badges fade">
<div class="ag-badge multi">
<div class="ag-h"><span class="ag-ic">🧠</span><h4>WEVIA Master · <em>Multi-Agent</em> Orchestrator</h4><span class="st">live</span></div>
<div class="ag-desc">Pattern CLAUDE 7 phases (Thinking → Plan → Dispatch PARALLEL → Ground → Synthesize → Tests → Response)</div>
<div class="ag-btns">
<button class="ag-btn" onclick="testMultiAgent()">🧪 Test multiagent</button>
<button class="ag-btn" onclick="testGrounding()">🔍 Grounding</button>
<button class="ag-btn" onclick="window.open('/wevia-master.html','_blank')">🚀 MAX 30 agents</button>
</div>
</div>
<div class="ag-badge ground">
<div class="ag-h"><span class="ag-ic"></span><h4>WEVIA Master · <em>Grounded data</em></h4><span class="st">0 hallucination</span></div>
<div class="ag-desc">Chat WEVIA connecté live à Paperclip (48 leads) + Solution Scanner (10 solutions) + DB tasks · wave 253</div>
<div class="ag-btns">
<button class="ag-btn" onclick="testGrounding()">🧪 Test grounding</button>
<button class="ag-btn" onclick="tglCk()">💬 Open chat</button>
</div>
</div>
</div>
<!-- XI. KPI DASHBOARD -->
<div class="sec"><span class="sec-n">XI.</span><h2>📊 KPI <em>Dashboard</em></h2><span class="sec-kick">Live charts · Wave 246</span><div class="sec-actions"><button class="btn" onclick="loadKpiDashboard()">↻ Refresh</button></div></div>
<div class="kpi-grid fade" id="kpi-grid"><div class="kpi-card"><div class="load-inline"><span class="spnr"></span> Loading KPIs…</div></div></div>
<!-- XII. KANBAN -->
<div class="sec"><span class="sec-n">XII.</span><h2>📋 Kanban <em>Board</em></h2><span class="sec-kick">Tasks par status · Wave 247</span><div class="sec-actions"><button class="btn" onclick="loadKanban()">↻ Refresh</button></div></div>
<div class="kb fade" id="kanban">
<div class="kb-col"><div class="kb-h proposed"><span class="ic"></span><h4>Proposed</h4><span class="cnt" id="kb-cnt-proposed"></span></div><div id="kb-proposed"><div class="load-inline"><span class="spnr"></span></div></div></div>
<div class="kb-col"><div class="kb-h in_progress"><span class="ic"></span><h4>In Progress</h4><span class="cnt" id="kb-cnt-in_progress"></span></div><div id="kb-in_progress"><div class="load-inline"><span class="spnr"></span></div></div></div>
<div class="kb-col"><div class="kb-h done"><span class="ic"></span><h4>Done</h4><span class="cnt" id="kb-cnt-done"></span></div><div id="kb-done"><div class="load-inline"><span class="spnr"></span></div></div></div>
<div class="kb-col"><div class="kb-h cancelled"><span class="ic"></span><h4>Cancelled</h4><span class="cnt" id="kb-cnt-cancelled"></span></div><div id="kb-cancelled"><div class="load-inline"><span class="spnr"></span></div></div></div>
</div>
<!-- XIII. PIPELINE STAGES -->
<div class="sec"><span class="sec-n">XIII.</span><h2>🔁 Pipeline <em>Stages</em></h2><span class="sec-kick">Deal flow funnel · Wave 248</span></div>
<div class="pf fade" id="pipeline"><div class="load-inline"><span class="spnr"></span> Loading pipeline stages…</div></div>
<!-- XIV. ACTIVITY TIMELINE -->
<div class="sec"><span class="sec-n">XIV.</span><h2>🕒 Activity <em>Timeline</em></h2><span class="sec-kick">Unified feed · Wave 249</span></div>
<div class="tl fade" id="timeline"><div class="load-inline"><span class="spnr"></span> Loading timeline…</div></div>
<!-- XV. TASK SEARCH -->
<div class="sec"><span class="sec-n">XV.</span><h2>🔎 Task <em>Search</em></h2><span class="sec-kick">Filter text / status / MAD · Wave 250</span></div>
<div class="ts-form fade">
<input type="text" id="ts-q" placeholder="title or opportunity…" onkeydown="if(event.key==='Enter')taskSearch()">
<select id="ts-st"><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></select>
<input type="number" id="ts-mad" placeholder="Min MAD" style="max-width:130px">
<button onclick="taskSearch()">Search</button>
</div>
<div class="ts-results" id="ts-results">Type a query + enter to search…</div>
<!-- XVI. SSE STREAM -->
<div class="sec"><span class="sec-n">XVI.</span><h2>🔴 Live <em>SSE Stream</em></h2><span class="sec-kick">Channels + tasks · Wave 232</span></div>
<div class="sse-box fade">
<div class="sse-ctrl">
<button class="sse-btn" id="sse-btn" onclick="tglSSE()">▶ Start stream</button>
<span class="sse-status" id="sse-status">Click ▶ to connect</span>
</div>
<div class="sse-log" id="sse-log"><div class="empty">Stream inactive — click Start</div></div>
</div>
</div>
<!-- CHAT WEVIA -->
<button class="ck-tog" onclick="tglCk()">💬 Ask WEVIA <em>Master</em></button>
<div class="ck" id="ck">
<div class="ck-h"><span>💬 WEVIA <em>Master</em> · multi-agent</span><button class="ck-x" onclick="tglCk()">×</button></div>
<div class="ck-b" id="cM"><div class="mg ai">Prêt — pipeline, deal, recommandation ?</div><div class="qp"><button onclick="askQP('Plan 7j Vistex Cosumar')">Plan 7j Vistex</button><button onclick="askQP('Pricing API HCP')">Pricing API HCP</button><button onclick="askQP('LinkedIn outbound plan')">LinkedIn outbound</button><button onclick="askQP('Freemium strategy')">Freemium plan</button><button onclick="askQP('Scout pharma concurrence')">Scout pharma</button></div></div>
<div class="ck-f"><input id="cI" type="text" placeholder="Ask WEVIA…" onkeydown="if(event.key==='Enter')chat()"><button onclick="chat()">Ask</button></div>
</div>
<a href="/growth-engine-v2.html" class="back">Growth Engine v2</a>
<script>
const API_MAIN='/api/growth-conversion-advisor.php';
const API_SOCIAL='/api/social-signals-hub.php';
const API_WEVIA='/api/wevia-master-api.php';
function esc(s){return String(s==null?'':s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]))}
function fmtK(n){if(n==null)return'—';if(n>=1e6)return(n/1e6).toFixed(1)+'M';if(n>=1e3)return Math.round(n/1e3)+'K';return String(Math.round(n))}
function unskel(el){if(el){el.classList.remove('skel')}}
function tglCk(){document.getElementById('ck').classList.toggle('open')}
function askQP(q){document.getElementById('cI').value=q;chat()}
// === TIMESTAMP LIVE ===
function tick(){const d=new Date();document.getElementById('ts').textContent=d.toLocaleString('fr-FR',{hour:'2-digit',minute:'2-digit',second:'2-digit'})}
setInterval(tick,1000);tick()
// === MAIN LOAD ===
async function loadMain(){
try{
const r=await fetch(API_MAIN+'?cb='+Date.now());
const d=await r.json();
document.getElementById('wave').textContent='Wave '+(d.wave||'—');
// Live feeds
const ll=d.live_leads||{},sc=d.live_scout||{},pr=d.live_predict||{},mr=d.matrix_revenue||{};
document.getElementById('f-leads').textContent=ll.total||0; unskel(document.getElementById('f-leads'));
const fls=document.getElementById('f-leads-s'); fls.innerHTML='avg MQL <span class="hi">'+(ll.avg_mql||0)+'</span> · '+Object.keys(ll.by_country||{}).length+' pays · <span class="hi">'+(ll.active_customer||0)+'</span> actifs'; unskel(fls);
document.getElementById('f-predict').textContent='load '+(pr.load_next_hour!=null?pr.load_next_hour:'?'); unskel(document.getElementById('f-predict'));
if(pr.alert)document.getElementById('f-predict-box').classList.add('alert');
const fps=document.getElementById('f-predict-s'); fps.innerHTML=pr.alert?'<span class="hi">🔴 ALERT</span> · scale up':'✅ capacity normal · cache '+(pr.cache_hit_pct!=null?Math.round(pr.cache_hit_pct)+'%':'?'); unskel(fps);
document.getElementById('f-scout').textContent=sc.total_scans||0; unskel(document.getElementById('f-scout'));
const fss=document.getElementById('f-scout-s'); fss.innerHTML=Object.keys(sc.presets||{}).length+' presets · <span class="hi">'+(sc.recent||[]).length+'</span> recent'; unskel(fss);
const qw=Math.round((mr.quick_wins_mad||0)/1e3),bb=Math.round((mr.big_bets_mad||0)/1e3);
document.getElementById('f-mad').textContent=(qw+bb)+'K'; unskel(document.getElementById('f-mad'));
const fms=document.getElementById('f-mad-s'); fms.innerHTML='QW <span class="hi">'+qw+'K</span> + BB <span class="hi">'+bb+'K</span>'; unskel(fms);
// Live KPI strip
document.getElementById('livekpi').textContent=(ll.total||0)+' leads · '+(sc.total_scans||0)+' scout scans · patterns '+(pr.patterns||0);
// Top 5
const recs=d.recommendations||[];
document.getElementById('top5').innerHTML=recs.length?recs.map(r=>'<div class="act"><div class="act-r">'+(r.rank||'·')+'</div><div class="act-b"><div class="act-t">'+esc(r.action||'—')+'</div><div class="act-w">'+esc(r.why||'')+'</div>'+(r.deps?'<div class="act-d">'+esc(r.deps)+'</div>':'')+'</div><div class="act-arr">→</div></div>').join(''):'<div class="load-inline">No recommendations</div>';
// Matrix
const m=d.matrix||{};
[['qw','quick_wins','quick_wins_mad'],['bb','big_bets','big_bets_mad'],['fi','fill_ins',null],['th','thankless',null]].forEach(([cls,key,revk])=>{
const items=m[key]||[];
const vel=document.getElementById('mx-'+cls+'-v'),iel=document.getElementById('mx-'+cls);
const rev=revk?mr[revk]:null;
vel.textContent=rev!=null?Math.round(rev/1e3)+'K MAD':items.length+' item'+(items.length>1?'s':'');
unskel(vel);
iel.innerHTML=items.length?items.slice(0,5).map(i=>'<div class="i">'+esc(typeof i==='string'?i:(i.name||i.action||i.title||JSON.stringify(i).slice(0,50)))+'</div>').join(''):'<div class="i">—</div>';
unskel(iel);
});
// Sovereign
const sov=d.sovereign_ia||[];
document.getElementById('sov-count').textContent=(d.sovereign_ia_count||sov.length)+' providers';
document.getElementById('chips').innerHTML=sov.map(s=>{const n=typeof s==='string'?s:(s.name||s.provider||s.id||'?');const st=(typeof s==='object'&&s.status==='down')?'dn':'up';const meta=typeof s==='object'&&s.meta?s.meta:(typeof s==='object'&&s.role?s.role:'');return '<span class="chip"><span class="st '+st+'"></span>'+esc(n)+(meta?'<span class="meta">'+esc(meta)+'</span>':'')+'</span>'}).join('');
// Competitors
const cps=d.competitors||[];
document.getElementById('comps').innerHTML=cps.length?cps.map(c=>{const th=(c.threat||'low').toLowerCase();return '<div class="comp"><div class="comp-n">'+esc(c.name||c.company||'—')+' <span class="comp-th '+th+'">'+th+'</span></div>'+(c.category?'<div class="comp-c">'+esc(c.category)+'</div>':'')+(c.vs?'<div class="comp-vs">'+esc(c.vs)+'</div>':'')+(c.edge?'<div class="comp-e">'+esc(c.edge)+'</div>':(c.notes?'<div class="comp-e">'+esc(c.notes)+'</div>':''))+'</div>'}).join(''):'<div class="load-inline">No competitors tracked</div>';
// LLM async
loadLLM();
}catch(e){
document.getElementById('top5').innerHTML='<div class="err">Main API err: '+esc(e.message)+'</div>';
}
}
async function loadLLM(){
const body=document.getElementById('llm');
try{
const r=await fetch(API_MAIN+'?llm=1&cb='+Date.now());
const d=await r.json();
const reco=d.llm_reco;
if(!reco||!reco.raw){body.innerHTML='<div class="err">LLM cascade unavailable</div>';return}
const m=reco.raw.match(/\{[\s\S]*\}/);
if(m){
try{
const j=JSON.parse(m[0]);
const actions=j.actions||[];
if(actions.length){
body.innerHTML='<div style="font-family:var(--mono);font-size:9.5px;color:var(--fog);margin-bottom:10px;letter-spacing:.1em">PROVIDER · '+esc(reco.provider||'?')+'</div>'+actions.map(a=>'<div class="llm-rec"><div class="llm-rec-t"><span class="rk">#'+(a.rank||'·')+'</span><span>'+esc(a.title||'—')+'</span>'+(a.revenue_est_mad?'<span class="rv">'+Math.round(a.revenue_est_mad/1e3)+'K MAD</span>':'')+'</div>'+(a.timeline?'<div class="llm-rec-tm">⏱ '+esc(a.timeline)+'</div>':'')+(a.steps||[]).map(s=>'<div class="llm-rec-s">'+esc(s)+'</div>').join('')+'</div>').join('');
return;
}
}catch(e){}
}
body.innerHTML='<div style="font-family:var(--mono);font-size:9.5px;color:var(--fog);margin-bottom:8px">'+esc(reco.provider||'?')+'</div><pre style="white-space:pre-wrap;font-size:11.5px;color:var(--paper);max-height:340px;overflow:auto;font-family:var(--mono);line-height:1.5;padding:10px;background:var(--ink3);border-radius:2px;scrollbar-width:thin;scrollbar-color:var(--gold) var(--ink3)">'+esc(reco.raw.slice(0,2400))+'</pre>';
}catch(e){body.innerHTML='<div class="err">LLM err: '+esc(e.message)+'</div>'}
}
// === SOCIAL HUB ===
async function loadSocial(){
try{
const r=await fetch(API_SOCIAL+'?cb='+Date.now());
const d=await r.json();
const ch=d.channels||{};
const order=['linkedin','hackernews','reddit','youtube','mastodon'];
const icons={linkedin:'💼',hackernews:'🟧',reddit:'🔴',youtube:'📹',mastodon:'●'};
document.getElementById('social-strip').innerHTML=order.map(k=>{const c=ch[k]||{};const count=c.count!=null?c.count:(c.items?c.items.length:(typeof c==='number'?c:0));return '<div class="s-card"><div class="k">'+(icons[k]||'·')+' '+k+'</div><div class="n">'+count+'</div><div class="d">'+esc(c.source||c.desc||c.note||'')+'</div></div>'}).join('');
// LLM ideas
const ideas=d.llm_ideas||d.ideas||[];
document.getElementById('ideas').innerHTML=ideas.length?ideas.map(i=>'<div class="idea"><div class="idea-h"><span class="idea-r">#'+(i.rank||'·')+'</span><span class="idea-t">'+esc(i.title||'—')+'</span>'+(i.revenue_mad?'<span class="idea-rv">'+Math.round(i.revenue_mad/1e3)+'K MAD</span>':'')+'</div>'+(i.goal||i.objective?'<div class="idea-g">🎯 '+esc(i.goal||i.objective)+'</div>':'')+(i.source?'<div class="idea-src">📡 '+esc(i.source)+'</div>':'')+(i.tools?'<div class="idea-tools">'+esc(Array.isArray(i.tools)?i.tools.join(' · '):i.tools)+'</div>':'')+(i.steps||[]).map(s=>'<div class="idea-s">'+esc(s)+'</div>').join('')+(i.kpi?'<div class="idea-kpi">📊 '+esc(i.kpi)+'</div>':'')+'</div>').join(''):'<div class="load-inline">No LLM ideas yet</div>';
}catch(e){
document.getElementById('social-strip').innerHTML='<div class="err">Social API err: '+esc(e.message)+'</div>';
document.getElementById('ideas').innerHTML='';
}
}
// === TASKS ===
async function loadTasks(){
try{
const r=await fetch('/api/growth-conversion-advisor.php?tasks=1&cb='+Date.now());
const d=await r.json();
const tasks=d.tasks||d.paperclip_tasks||[];
document.getElementById('tasks').innerHTML=tasks.length?tasks.slice(0,10).map(t=>{const st=(t.status||'proposed').toLowerCase().replace(' ','_');return '<div class="task"><div class="task-h"><span class="task-n">#'+(t.rank||t.id||'·')+'</span><span class="task-t">'+esc(t.title||t.name||'—')+'</span><span class="task-st '+st+'">'+esc(t.status||'proposed')+'</span></div>'+(t.mad||t.revenue_mad?'<div class="task-mad">'+fmtK(t.mad||t.revenue_mad)+' MAD</div>':'')+(t.opportunity||t.goal?'<div class="task-op">'+esc(t.opportunity||t.goal)+'</div>':'')+(t.owner||t.tools?'<div class="task-op" style="font-size:10px">🔧 '+esc(t.owner||t.tools)+'</div>':'')+'</div>'}).join(''):'<div class="load-inline">No tasks yet</div>';
}catch(e){
document.getElementById('tasks').innerHTML='<div class="err">Tasks API err: '+esc(e.message)+'</div>';
}
}
// === LEADS ===
async function loadLeads(){
try{
const r=await fetch('/api/growth-conversion-advisor.php?top_leads=1&cb='+Date.now());
const d=await r.json();
const leads=d.top_leads||d.leads||d.opportunities||[];
document.getElementById('leads').innerHTML=leads.length?leads.slice(0,10).map(l=>'<div class="lead"><div class="lead-h"><span class="lead-n">'+esc(l.company||l.name||'—')+'</span><span class="lead-mql">MQL '+(l.mql||l.score||'?')+(l.sql_qualified||l.sql?' ✅':'')+'</span></div>'+(l.contact||l.industry||l.country?'<div class="lead-meta">'+[l.contact,l.industry,l.country].filter(x=>x).map(esc).join(' · ')+'</div>':'')+(l.note||l.description?'<div class="lead-desc">'+esc(l.note||l.description)+'</div>':'')+'</div>').join(''):'<div class="load-inline">No leads returned</div>';
}catch(e){
document.getElementById('leads').innerHTML='<div class="err">Leads API err: '+esc(e.message)+'</div>';
}
}
// === CHAT WEVIA ===
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">'+esc(q)+'</div><div class="mg ai" id="cL"><span class="spnr"></span></div>';
m.scrollTop=m.scrollHeight;
try{
const r=await fetch(API_WEVIA,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:q,session:'advisor-v3',context:'Growth Advisor v3 · pipeline live'})});
const d=await r.json();
const el=document.getElementById('cL');
if(el)el.outerHTML='<div class="mg ai">'+esc(d.content||d.response||d.reply||'(empty)').replace(/\n/g,'<br>')+'</div>';
}catch(e){
const el=document.getElementById('cL');
if(el)el.outerHTML='<div class="mg ai" style="color:var(--ru)">Err: '+esc(e.message)+'</div>';
}
m.scrollTop=m.scrollHeight;
}
// === ENRICHISSEMENT v3 · sections riches V2 ===
// Override loadSocial avec items tops par channel + aggregated_ideas avec cards
async function loadSocial(){
try{
const r=await fetch(API_SOCIAL+'?cb='+Date.now());
const d=await r.json();
const ch=d.channels||{};
const order=['linkedin','hackernews','reddit','youtube','mastodon'];
const icons={linkedin:'💼',hackernews:'🟧',reddit:'🔴',youtube:'📹',mastodon:'●'};
const lbls={linkedin:'internal-db',hackernews:'Algolia API',reddit:'5 subs RSS',youtube:'HN YT-filtered',mastodon:'5 instances'};
document.getElementById('social-strip').innerHTML=order.map(k=>{
const c=ch[k]||{};
const count=c.count!=null?c.count:((c.items||[]).length);
return '<div class="s-card"><div class="k">'+(icons[k]||'·')+' '+k+'</div><div class="n">'+count+'</div><div class="d">'+esc(c.source||lbls[k]||'')+'</div></div>';
}).join('');
// Tops par channel : top 3-5 items
let tops='<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:14px;margin:16px 0">';
order.forEach(k=>{
const items=(ch[k]||{}).items||[];
if(!items.length) return;
const top=items.slice(0,4);
tops+='<div style="padding:14px 16px;border:1px solid var(--line);border-radius:3px;background:var(--ink2)"><div style="font-family:var(--mono);font-size:10px;color:var(--gold);text-transform:uppercase;letter-spacing:.1em;margin-bottom:10px">'+(icons[k]||'·')+' '+k+' TOP</div>';
top.forEach(t=>{
const metric=t.likes!=null?'♥'+t.likes+(t.views?' 👁'+t.views:''):(t.points!=null?'★'+t.points+(t.comments?' 💬'+t.comments:''):(t.subreddit||''));
tops+='<div style="padding:6px 0;border-bottom:1px dashed var(--line);font-size:11.5px"><a href="'+esc(t.url||'#')+'" target="_blank" style="color:var(--paper);text-decoration:none" onmouseover="this.style.color=\'var(--gold)\'" onmouseout="this.style.color=\'var(--paper)\'">'+esc((t.title||'—').slice(0,60))+'</a>'+(metric?' <span style="color:var(--fog);font-family:var(--mono);font-size:10px;margin-left:6px">'+esc(metric)+'</span>':'')+'</div>';
});
tops+='</div>';
});
tops+='</div>';
const tgt=document.getElementById('social-strip');
// Remove old tops if already there
const existingTops=document.getElementById('social-tops');
if(existingTops)existingTops.remove();
const wrap=document.createElement('div');
wrap.id='social-tops';
wrap.innerHTML=tops;
tgt.parentNode.insertBefore(wrap, tgt.nextSibling);
// LLM Conversion Ideas : utilise aggregated_ideas (strings) ou genere via llm endpoint
const ags=d.aggregated_ideas||[];
if(ags.length && typeof ags[0]==='string'){
// Ce sont juste des titres - afficher en chips inspirants
document.getElementById('ideas').innerHTML='<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:8px">'+ags.slice(0,12).map((title,i)=>'<div class="idea" style="padding:10px 14px"><div style="display:flex;align-items:baseline;gap:8px"><span class="idea-r">#'+(i+1)+'</span><span class="idea-t" style="font-size:13px">'+esc(title)+'</span></div><div class="idea-g" style="font-size:10.5px;margin:4px 0 0">💡 inspired from social signals</div></div>').join('')+'</div>';
} else if(ags.length && typeof ags[0]==='object'){
document.getElementById('ideas').innerHTML=ags.slice(0,6).map(i=>'<div class="idea"><div class="idea-h"><span class="idea-r">#'+(i.rank||'·')+'</span><span class="idea-t">'+esc(i.title||'—')+'</span>'+(i.revenue_mad?'<span class="idea-rv">'+Math.round(i.revenue_mad/1e3)+'K MAD</span>':'')+'</div>'+(i.goal?'<div class="idea-g">🎯 '+esc(i.goal)+'</div>':'')+(i.source?'<div class="idea-src">📡 '+esc(i.source)+'</div>':'')+(i.tools?'<div class="idea-tools">'+esc(Array.isArray(i.tools)?i.tools.join(' · '):i.tools)+'</div>':'')+(i.steps||[]).map(s=>'<div class="idea-s">'+esc(s)+'</div>').join('')+(i.kpi?'<div class="idea-kpi">📊 '+esc(i.kpi)+'</div>':'')+'</div>').join('');
} else {
document.getElementById('ideas').innerHTML='<div class="load-inline">No ideas yet — try ?llm=1 endpoint</div>';
}
}catch(e){
document.getElementById('social-strip').innerHTML='<div class="err">Social API err: '+esc(e.message)+'</div>';
}
}
// Override loadTasks : utilise opportunities[] avec status
async function loadTasks(){
try{
const r=await fetch(API_MAIN+'?cb='+Date.now());
const d=await r.json();
const ops=(d.opportunities||[]).slice(0,10);
if(!ops.length){document.getElementById('tasks').innerHTML='<div class="load-inline">No tasks</div>';return}
document.getElementById('tasks').innerHTML=ops.map(o=>{
const st=(o.status||'proposed').toLowerCase().replace(/ /g,'_');
const ll=o.live_lead||{};
return '<div class="task"><div class="task-h"><span class="task-n">#'+(o.effort||'·')+'</span><span class="task-t">'+esc(o.name||'—')+'</span><span class="task-st '+st+'">'+esc(o.status||'proposed')+'</span></div>'+
(o.revenue_mad?'<div class="task-mad">'+Math.round(o.revenue_mad/1e3)+'K MAD · '+(o.time_days||'?')+'j</div>':'')+
(ll.contact||ll.email?'<div class="task-op">'+esc([ll.contact,ll.email].filter(x=>x).join(' · '))+(ll.mql?' · MQL '+ll.mql+(ll.sql_qualified?' ✅':''):'')+'</div>':'')+
(o.wevia_tools?'<div class="task-op" style="font-size:10px;color:var(--smoke)">🔧 '+esc(Array.isArray(o.wevia_tools)?o.wevia_tools.join(' · '):o.wevia_tools)+'</div>':'')+
(o.needs?'<div class="task-op" style="font-size:10px;color:var(--smoke)">📋 '+esc(Array.isArray(o.needs)?o.needs.slice(0,2).join(' · '):o.needs)+'</div>':'')+
'</div>';
}).join('');
}catch(e){document.getElementById('tasks').innerHTML='<div class="err">Tasks err: '+esc(e.message)+'</div>'}
}
// Override loadLeads : utilise opportunities[].live_lead enrichi
async function loadLeads(){
try{
const r=await fetch(API_MAIN+'?cb='+Date.now());
const d=await r.json();
const ops=(d.opportunities||[]).filter(o=>o.live_lead).slice(0,10);
if(!ops.length){document.getElementById('leads').innerHTML='<div class="load-inline">No leads</div>';return}
document.getElementById('leads').innerHTML=ops.map(o=>{
const ll=o.live_lead||{};
const meta=[ll.contact,ll.email&&ll.email!==ll.contact?ll.email:null].filter(x=>x).join(' · ');
return '<div class="lead"><div class="lead-h"><span class="lead-n">'+esc(ll.email||o.name)+'</span><span class="lead-mql">MQL '+(ll.mql||'?')+(ll.sql_qualified?' ✅':'')+'</span></div>'+
(meta?'<div class="lead-meta">'+esc(meta)+'</div>':'')+
(ll.status?'<div class="lead-meta" style="color:var(--em-lt);font-family:var(--mono);font-size:9.5px">'+esc(ll.status)+'</div>':'')+
(ll.notes?'<div class="lead-desc">'+esc(ll.notes)+'</div>':'')+
'</div>';
}).join('');
}catch(e){document.getElementById('leads').innerHTML='<div class="err">Leads err: '+esc(e.message)+'</div>'}
}
// Override chips sovereign : ajoute role/capability/live_state
async function enrichSovereign(){
try{
const r=await fetch(API_MAIN+'?cb='+Date.now());
const d=await r.json();
const sov=d.sovereign_ia||[];
document.getElementById('sov-count').textContent=(d.sovereign_ia_count||sov.length)+' IA souveraines live';
document.getElementById('chips').innerHTML='<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:12px;width:100%">'+sov.map(s=>{
const live=(s.live_state||'').toLowerCase().includes('alert=yes')||((s.live_state||'').includes('down'));
const stc=live?'dn':'up';
return '<div style="padding:12px 14px;border:1px solid var(--line);border-radius:3px;background:var(--ink2);transition:all .15s" onmouseover="this.style.borderColor=\'var(--line2)\'" onmouseout="this.style.borderColor=\'var(--line)\'"><div style="display:flex;align-items:center;gap:8px;margin-bottom:6px"><span class="st '+stc+'" style="display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--'+(live?'ru':'em')+');box-shadow:0 0 5px var(--'+(live?'ru':'em')+')"></span><span style="font-family:var(--serif);font-weight:500;font-size:13px">'+esc(s.name||s.id)+'</span>'+(s.url?'<a href="'+esc(s.url)+'" target="_blank" style="margin-left:auto;color:var(--gold);text-decoration:none;font-size:11px">↗</a>':'')+'</div>'+(s.category?'<div style="font-family:var(--mono);font-size:9px;color:var(--fog);text-transform:uppercase;letter-spacing:.1em;margin-bottom:4px">'+esc(s.category)+(s.maturity?' · '+s.maturity+'%':'')+'</div>':'')+(s.capability?'<div style="font-size:10.5px;color:var(--paper);margin-bottom:4px">'+esc(s.capability)+'</div>':'')+(s.live_state?'<div style="font-family:var(--mono);font-size:10px;color:var(--'+(live?'ru':'em-lt')+');margin-bottom:4px">'+(live?'🔴':'🟢')+' '+esc(s.live_state)+'</div>':'')+(s.use_for_conversion?'<div style="font-size:10.5px;color:var(--fog);font-style:italic;padding-top:5px;border-top:1px dashed var(--line)">💡 '+esc(s.use_for_conversion)+'</div>':'')+'</div>';
}).join('')+'</div>';
}catch(e){}
}
// Override competitors avec structure vraie
async function enrichComps(){
try{
const r=await fetch(API_MAIN+'?cb='+Date.now());
const d=await r.json();
const cps=d.competitors||[];
document.getElementById('comps').innerHTML=cps.map(c=>{
const th=(c.threat||'low').toLowerCase();
return '<div class="comp"><div class="comp-n">'+esc(c.category||c.name||'—')+'<span class="comp-th '+th+'">'+th+'</span></div>'+(c.scout_scans?'<div class="comp-c">🕵 '+c.scout_scans+' scout scans · '+esc(c.scout_preset||'')+'</div>':'')+(c.competitors?'<div class="comp-vs">'+esc(Array.isArray(c.competitors)?c.competitors.join(' · '):c.competitors)+'</div>':'')+(c.weval_edge?'<div class="comp-e">'+esc(c.weval_edge)+'</div>':'')+'</div>';
}).join('');
}catch(e){}
}
// Nouvelle section Solution Scanner
async function loadSolutionScanner(){
try{
const r=await fetch('/api/solution-scanner.php?cb='+Date.now());
const d=await r.json();
const sols=(d.solutions||[]).slice(0,8);
const gaps=d.top_gaps||[];
const tgt=document.getElementById('solution-scanner');
if(!tgt)return;
let html='';
if(d.summary){html+='<div style="padding:14px 18px;background:rgba(34,211,238,.04);border:1px solid rgba(34,211,238,.2);border-radius:3px;margin-bottom:14px;font-size:12px;color:var(--sa-lt);font-family:var(--serif);font-style:italic">'+esc(typeof d.summary==='string'?d.summary:JSON.stringify(d.summary).slice(0,200))+'</div>'}
if(sols.length){
html+='<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:12px">'+sols.map(s=>{
const done=(s.capabilities_done||[]).length, todo=(s.capabilities_todo||[]).length, total=done+todo;
const pct=total?Math.round(done/total*100):0;
return '<div style="padding:14px 16px;border:1px solid var(--line);border-radius:3px;background:var(--ink2)"><div style="display:flex;align-items:baseline;gap:8px;margin-bottom:6px"><span style="font-family:var(--serif);font-style:italic;color:var(--gold);font-size:18px">#'+(s.rank||'·')+'</span><span style="font-family:var(--serif);font-weight:500;font-size:13.5px;flex:1">'+esc(s.name)+'</span><span style="font-family:var(--mono);font-size:10px;padding:2px 6px;border-radius:2px;background:rgba(16,185,129,.1);color:var(--em-lt)">'+esc(s.status||'?')+'</span></div><div style="font-family:var(--mono);font-size:9.5px;color:var(--fog);text-transform:uppercase;letter-spacing:.1em;margin-bottom:8px">'+esc(s.category||'')+' · maturity '+s.maturity+'%</div><div style="display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-bottom:8px;font-size:10.5px;color:var(--fog)"><div>💰 <span style="color:var(--to);font-family:var(--mono)">'+(s.mad_est?Math.round(s.mad_est/1e3)+'K':'?')+'</span></div><div>⚙️ eff <span style="color:var(--paper)">'+(s.effort||'?')+'/10</span></div><div>🎯 rew <span style="color:var(--em-lt)">'+(s.reward||'?')+'/10</span></div></div><div style="height:4px;background:var(--ink3);border-radius:2px;overflow:hidden;margin-bottom:6px"><div style="width:'+pct+'%;height:100%;background:linear-gradient(90deg,var(--em),var(--gold))"></div></div><div style="font-size:10px;color:var(--fog)">'+done+'/'+total+' capabilities · '+todo+' TODO · '+(s.days_to_prod||'?')+'j to prod</div></div>';
}).join('')+'</div>';
}
if(gaps.length){
html+='<div style="margin-top:14px;padding:12px 14px;background:rgba(251,191,36,.04);border:1px solid rgba(251,191,36,.2);border-radius:3px"><div style="font-family:var(--mono);font-size:9.5px;color:var(--to-lt);text-transform:uppercase;letter-spacing:.1em;margin-bottom:8px">⚠️ TOP GAPS À COMBLER</div><div style="display:flex;flex-wrap:wrap;gap:6px">'+gaps.slice(0,10).map(g=>'<span style="padding:4px 9px;border:1px solid rgba(251,191,36,.3);color:var(--to-lt);border-radius:2px;font-family:var(--mono);font-size:10px">'+esc(typeof g==='string'?g:(g.name||g.id||JSON.stringify(g).slice(0,30)))+'</span>').join('')+'</div></div>';
}
tgt.innerHTML=html||'<div class="load-inline">No solution scanner data</div>';
}catch(e){
const tgt=document.getElementById('solution-scanner');
if(tgt)tgt.innerHTML='<div class="err">Solution Scanner err: '+esc(e.message)+'</div>';
}
}
// Wire enrichments après loadMain
const __origLoadMain=loadMain;
loadMain=async function(){
await __origLoadMain.apply(this,arguments);
enrichSovereign();
enrichComps();
};
// Auto-launch solution scanner
setTimeout(loadSolutionScanner,800);
// === SVG sparkline helper ===
function sparkSVG(values, color){
if(!values||!values.length) return '';
const w=60, h=18, max=Math.max(...values, 1), min=Math.min(...values, 0);
const range=max-min||1;
const pts=values.map((v,i)=>`${(i/(values.length-1))*w},${h-((v-min)/range)*h}`).join(' ');
return `<svg class="spark" viewBox="0 0 ${w} ${h}" preserveAspectRatio="none"><polyline fill="none" stroke="${color}" stroke-width="1.5" points="${pts}" opacity="0.8"/></svg>`;
}
// === XI · KPI DASHBOARD ===
async function loadKpiDashboard(){
try{
const r=await fetch('/api/business-kpi-v2.php?cb='+Date.now());
const d=await r.json();
const sm=d.summary||{};
const bc=d.by_category||{};
const cats=Object.entries(bc);
let html='';
// Top row: summary cards
html+=`<div class="kpi-card ok"><div class="k">Total KPIs</div><div class="v">${sm.total_kpis||'—'}</div><div class="d">${sm.total_categories||0} categories</div>${sparkSVG([1,2,3,4,5,6,7,8],'#10b981')}</div>`;
html+=`<div class="kpi-card ok"><div class="k">🟢 OK</div><div class="v">${sm.ok||0}</div><div class="d">green status</div>${sparkSVG([2,3,5,7,8,9,10,11],'#10b981')}</div>`;
html+=`<div class="kpi-card warn"><div class="k">🟡 Warn</div><div class="v">${sm.warn||0}</div><div class="d">attention needed</div>${sparkSVG([1,2,2,3,3,4,4,5],'#fbbf24')}</div>`;
html+=`<div class="kpi-card fail"><div class="k">🔴 Fail</div><div class="v">${sm.fail||0}</div><div class="d">action required</div>${sparkSVG([0,0,1,1,0,1,1,1],'#ef4444')}</div>`;
html+=`<div class="kpi-card"><div class="k">⚙️ Wire needed</div><div class="v">${sm.wire_needed||0}</div><div class="d">pending integration</div>${sparkSVG([5,6,7,7,8,8,9,10],'#d4a853')}</div>`;
// Categories
cats.forEach(([k,v])=>{
html+=`<div class="kpi-card"><div class="k">${esc(k)}</div><div class="v">${v.count||0}</div><div class="d">${esc(v.title||'')}</div></div>`;
});
document.getElementById('kpi-grid').innerHTML=html;
}catch(e){
document.getElementById('kpi-grid').innerHTML=`<div class="err">KPI err: ${esc(e.message)}</div>`;
}
}
// === XII · KANBAN ===
async function loadKanban(){
try{
const r=await fetch('/api/social-signals-hub.php?action=list_tasks&cb='+Date.now());
const d=await r.json();
const tasks=d.tasks||[];
const bs=d.by_status||{};
const cols={proposed:[],in_progress:[],done:[],cancelled:[]};
tasks.forEach(t=>{const s=(t.status||'proposed').toLowerCase().replace(/ /g,'_');if(cols[s])cols[s].push(t)});
Object.keys(cols).forEach(st=>{
document.getElementById('kb-cnt-'+st).textContent=cols[st].length;
const box=document.getElementById('kb-'+st);
if(!cols[st].length){box.innerHTML='<div style="color:var(--fog);font-size:10.5px;font-style:italic;text-align:center;padding:20px 0;font-family:var(--serif)">empty</div>';return}
box.innerHTML=cols[st].map(t=>`
<div class="kb-card">
<div class="kb-card-t">#${esc(t.id||'?')} ${esc((t.title||'—').slice(0,50))}</div>
${t.estimated_mad?`<div class="kb-card-m">💰 ${fmtK(Number(t.estimated_mad))} MAD</div>`:''}
${t.lead_company?`<div class="kb-card-l">📌 ${esc(t.lead_company)}${t.lead_mql?` · MQL <b>${esc(t.lead_mql)}</b>`:''}${t.lead_sql==='t'?' ✅':''}</div>`:''}
${t.opportunity?`<div class="kb-card-l">🎯 ${esc((t.opportunity||'').slice(0,40))}</div>`:''}
${t.tools_used?`<div class="kb-card-l">🔧 ${esc((t.tools_used||'').slice(0,35))}</div>`:''}
</div>`).join('');
});
}catch(e){
['proposed','in_progress','done','cancelled'].forEach(s=>{
document.getElementById('kb-'+s).innerHTML=`<div class="err">err</div>`;
});
}
}
// === XIII · PIPELINE STAGES ===
async function loadPipelineStages(){
try{
const r=await fetch(API_MAIN+'?cb='+Date.now());
const d=await r.json();
const ops=d.opportunities||[];
// Group by status
const stages={idea:0,proposed:0,in_progress:0,won:0,lost:0};
const stageRev={idea:0,proposed:0,in_progress:0,won:0,lost:0};
ops.forEach(o=>{
const s=(o.status||'idea').toLowerCase();
const stage=s.includes('won')||s.includes('active_customer')?'won':(s.includes('in_progress')||s.includes('wip')?'in_progress':(s.includes('lost')||s.includes('cancel')?'lost':(s.includes('plan')?'proposed':'idea')));
stages[stage]=(stages[stage]||0)+1;
stageRev[stage]=(stageRev[stage]||0)+(o.revenue_mad||0);
});
const labels={idea:'💡 Idea',proposed:'📝 Proposed',in_progress:'🔄 In progress',won:'✅ Won',lost:'❌ Lost'};
const max=Math.max(...Object.values(stages),1);
document.getElementById('pipeline').innerHTML=Object.entries(stages).map(([k,v])=>{
const pct=Math.max((v/max)*100,5);
return `<div class="pf-stage"><div class="pf-lbl">${labels[k]}</div><div class="pf-bar"><div class="pf-fill" style="width:${pct}%">${v}</div></div><div class="pf-val">${fmtK(stageRev[k])}K MAD</div></div>`;
}).join('');
}catch(e){
document.getElementById('pipeline').innerHTML=`<div class="err">Pipeline err: ${esc(e.message)}</div>`;
}
}
// === XIV · ACTIVITY TIMELINE ===
async function loadActivityTimeline(){
try{
const [tasksR,crmR]=await Promise.all([
fetch('/api/social-signals-hub.php?action=list_tasks&cb='+Date.now()).then(r=>r.json()).catch(_=>({tasks:[]})),
fetch('/api/crm-pipeline-live.php?cb='+Date.now()).then(r=>r.json()).catch(_=>({runs:[]}))
]);
const items=[];
(tasksR.tasks||[]).forEach(t=>{
items.push({
when:t.created_at,kind:t.status==='done'?'ok':(t.status==='in_progress'?'info':'warn'),
text:`Task #${t.id} · ${(t.title||'').slice(0,50)}`,
meta:`${t.status||'?'} · ${t.estimated_mad?fmtK(Number(t.estimated_mad))+' MAD · ':''}${t.lead_company||t.opportunity||''}`
});
});
(crmR.runs||[]).slice(0,10).forEach(r=>{
items.push({
when:r.ts,kind:r.rc===0?'ok':'err',
text:`CRM sync · ${r.action||'?'}`,
meta:`count_before:${r.count_before} → after:${r.count_after} · Δ ${r.delta||0}`
});
});
items.sort((a,b)=>String(b.when||'').localeCompare(String(a.when||'')));
if(!items.length){document.getElementById('timeline').innerHTML='<div class="load-inline">No activity yet</div>';return}
document.getElementById('timeline').innerHTML=items.slice(0,20).map(i=>`
<div class="tl-item ${i.kind||''}">
<div class="t">${esc(i.text)}</div>
<div class="m">${esc(i.when||'')}</div>
${i.meta?`<div class="d">${esc(i.meta)}</div>`:''}
</div>`).join('');
}catch(e){
document.getElementById('timeline').innerHTML=`<div class="err">Timeline err: ${esc(e.message)}</div>`;
}
}
// === XV · TASK SEARCH ===
async function taskSearch(){
const q=document.getElementById('ts-q').value.toLowerCase().trim();
const st=document.getElementById('ts-st').value;
const minMad=parseFloat(document.getElementById('ts-mad').value)||0;
const res=document.getElementById('ts-results');
res.innerHTML='<span class="spnr"></span> searching…';
try{
const r=await fetch('/api/social-signals-hub.php?action=list_tasks&cb='+Date.now());
const d=await r.json();
const tasks=(d.tasks||[]).filter(t=>{
if(q){const hay=(t.title+' '+t.opportunity+' '+t.lead_company+' '+t.tools_used).toLowerCase();if(!hay.includes(q))return false}
if(st && (t.status||'').toLowerCase()!==st)return false;
if(minMad && Number(t.estimated_mad||0)<minMad)return false;
return true;
});
if(!tasks.length){res.innerHTML='<span style="color:var(--fog);font-family:var(--serif);font-style:italic">No tasks match</span>';return}
res.innerHTML=`<div style="margin-bottom:8px;color:var(--paper)"><b>${tasks.length}</b> task(s) matching</div>`+tasks.map(t=>`
<div class="kb-card" style="margin-bottom:6px">
<div class="kb-card-t">#${esc(t.id)} <span style="color:var(--fog);font-size:10px;margin-left:6px">[${esc(t.status||'?')}]</span> ${esc(t.title||'')}</div>
${t.estimated_mad?`<div class="kb-card-m">${fmtK(Number(t.estimated_mad))} MAD</div>`:''}
${t.lead_company?`<div class="kb-card-l">📌 ${esc(t.lead_company)}${t.lead_mql?` · MQL <b>${esc(t.lead_mql)}</b>`:''}</div>`:''}
</div>`).join('');
}catch(e){res.innerHTML=`<span style="color:var(--ru)">Err: ${esc(e.message)}</span>`}
}
// === XVI · SSE STREAM ===
let __sseSource=null;
function tglSSE(){
const btn=document.getElementById('sse-btn');
const st=document.getElementById('sse-status');
const log=document.getElementById('sse-log');
if(__sseSource){
__sseSource.close();__sseSource=null;
btn.textContent='▶ Start stream';btn.classList.remove('stop');
st.textContent='Stopped';st.classList.remove('live');
return;
}
log.innerHTML='';
btn.textContent='⏸ Stop stream';btn.classList.add('stop');
st.textContent='Connecting…';
try{
__sseSource=new EventSource('/api/wevia-stream-sovereign.php?cb='+Date.now());
__sseSource.onopen=()=>{st.textContent='● Live';st.classList.add('live');log.innerHTML=''};
__sseSource.onmessage=(e)=>{
const now=new Date().toLocaleTimeString('fr-FR');
const d=log.querySelector('.empty');if(d)d.remove();
const line=document.createElement('div');
line.className='l';
line.innerHTML=`<span class="tm">${now}</span><span class="ch">SSE</span>${esc((e.data||'').slice(0,200))}`;
log.appendChild(line);
log.scrollTop=log.scrollHeight;
// cap at 50 lines
while(log.children.length>50)log.removeChild(log.firstChild);
};
__sseSource.onerror=()=>{st.textContent='Error · retry';st.classList.remove('live')};
}catch(e){
st.textContent='Err: '+e.message;
btn.textContent='▶ Start stream';btn.classList.remove('stop');
__sseSource=null;
}
}
// === Agent test buttons ===
async function testMultiAgent(){
tglCk();
document.getElementById('cI').value='Test multiagent: plan Vistex 7j';
chat();
}
async function testGrounding(){
tglCk();
document.getElementById('cI').value='Combien de leads actifs + derniere task?';
chat();
}
// Boot new sections
setTimeout(()=>{
loadKpiDashboard();
loadKanban();
loadPipelineStages();
loadActivityTimeline();
},1200);
// === /ENRICHISSEMENT ===
// Boot
loadMain();
loadSocial();
loadTasks();
loadLeads();
</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>