@@ -0,0 +1,440 @@
<!DOCTYPE html>
< html lang = "fr" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width,initial-scale=1" >
< title > WEVAL · Sales Hub — Tout piloter depuis ici< / title >
< style >
: root { --bg-0 : #05060a ; --bg-1 : #0b0d15 ; --bg-2 : #11141f ; --bg-3 : #171b2a ; --border : rgba ( 99 , 102 , 241 , 0.18 ) ; --border-h : rgba ( 99 , 102 , 241 , 0.38 ) ; --text : #e2e8f0 ; --dim : #94a3b8 ; --mute : #64748b ; --accent : #14b8a6 ; --accent2 : #6366f1 ; --purple : #a855f7 ; --cyan : #06b6d4 ; --ok : #22c55e ; --warn : #f59e0b ; --err : #ef4444 ; --rose : #f43f5e ; --gold : #eab308 }
* { box-sizing : border-box ; margin : 0 ; padding : 0 }
body { font-family : 'Inter' , system-ui , sans-serif ; background : radial-gradient ( ellipse at top , #0f1420 , #05060a 60 % ) ; color : var ( - - text ) ; min-height : 100 vh ; font-size : 13 px ; line-height : 1.5 }
. container { max-width : 1760 px ; margin : 0 auto ; padding : 22 px 26 px 80 px }
/* Header */
header { display : flex ; justify-content : space-between ; align-items : flex-start ; margin-bottom : 16 px ; padding-bottom : 14 px ; border-bottom : 1 px solid var ( - - border ) }
h1 { font-size : 24 px ; font-weight : 800 ; background : linear-gradient ( 90 deg , #22d3ee , #a855f7 , #eab308 ) ; -webkit- background-clip : text ; background-clip : text ; color : transparent }
. sub { color : var ( - - dim ) ; font-size : 12.5 px ; margin-top : 4 px }
. clock { font-family : 'JetBrains Mono' , monospace ; color : var ( - - accent ) ; font-size : 11 px ; margin-top : 3 px }
. actions { display : flex ; gap : 8 px }
. btn { padding : 7 px 13 px ; background : var ( - - bg -2 ) ; border : 1 px solid var ( - - border ) ; color : var ( - - text ) ; border-radius : 8 px ; font-size : 11.5 px ; cursor : pointer ; text-decoration : none ; font-family : inherit ; transition : all .2 s }
. btn : hover { border-color : var ( - - accent ) ; color : var ( - - accent ) }
. pulse { display : inline-block ; width : 8 px ; height : 8 px ; border-radius : 50 % ; background : var ( - - ok ) ; box-shadow : 0 0 0 0 rgba ( 34 , 197 , 94 , .7 ) ; animation : pulse 2 s infinite ; margin-right : 6 px }
@ keyframes pulse { 0 % , 100 % { box-shadow : 0 0 0 0 rgba ( 34 , 197 , 94 , .7 ) } 70 % { box-shadow : 0 0 0 8 px rgba ( 34 , 197 , 94 , 0 ) } }
/* Priority strip */
. prio-banner { background : linear-gradient ( 135 deg , rgba ( 239 , 68 , 68 , 0.1 ) , rgba ( 245 , 158 , 11 , 0.08 ) ) ; border : 1 px solid rgba ( 239 , 68 , 68 , 0.3 ) ; border-radius : 12 px ; padding : 14 px 18 px ; margin-bottom : 18 px ; display : flex ; align-items : center ; justify-content : space-between ; flex-wrap : wrap ; gap : 12 px }
. prio-banner . title { font-weight : 800 ; color : #fca5a5 ; font-size : 13 px }
. prio-banner . stat { font-size : 22 px ; font-weight : 800 ; color : var ( - - gold ) ; font-family : 'JetBrains Mono' , monospace }
. prio-banner . sub { color : var ( - - dim ) ; font-size : 11.5 px }
/* KPI strip */
. kpi-strip { display : grid ; grid-template-columns : repeat ( 5 , 1 fr ) ; gap : 10 px ; margin-bottom : 18 px }
@ media ( max-width : 1100px ) { . kpi-strip { grid-template-columns : repeat ( 2 , 1 fr ) } }
. kpi { background : var ( - - bg -1 ) ; border : 1 px solid var ( - - border ) ; border-radius : 10 px ; padding : 13 px 15 px ; border-left : 3 px solid var ( - - accent ) }
. kpi . gold { border-left-color : var ( - - gold ) }
. kpi . danger { border-left-color : var ( - - err ) }
. kpi . cyan { border-left-color : var ( - - cyan ) }
. kpi . purple { border-left-color : var ( - - purple ) }
. kpi-lbl { font-size : 10 px ; color : var ( - - dim ) ; text-transform : uppercase ; letter-spacing : 0.5 px ; font-weight : 600 }
. kpi-val { font-size : 22 px ; font-weight : 800 ; margin-top : 4 px ; line-height : 1 ; font-family : 'JetBrains Mono' , monospace }
. kpi-val . gold { background : linear-gradient ( 135 deg , var ( - - gold ) , var ( - - warn ) ) ; -webkit- background-clip : text ; background-clip : text ; color : transparent }
. kpi-sub { font-size : 10 px ; color : var ( - - mute ) ; margin-top : 2 px }
/* Main layout */
. layout { display : grid ; grid-template-columns : 1.3 fr 1 fr ; gap : 16 px }
@ media ( max-width : 1200px ) { . layout { grid-template-columns : 1 fr } }
/* Card */
. card { background : var ( - - bg -1 ) ; border : 1 px solid var ( - - border ) ; border-radius : 12 px ; padding : 16 px ; margin-bottom : 16 px }
. card-head { display : flex ; align-items : center ; justify-content : space-between ; margin-bottom : 12 px ; padding-bottom : 10 px ; border-bottom : 1 px solid var ( - - bg -3 ) }
. card-title { font-size : 14 px ; font-weight : 700 ; color : var ( - - text ) ; display : flex ; align-items : center ; gap : 8 px }
. card-badge { font-size : 10 px ; padding : 3 px 8 px ; border-radius : 8 px ; font-weight : 700 ; background : rgba ( 20 , 184 , 166 , 0.15 ) ; color : #5eead4 }
. card-badge . gold { background : rgba ( 234 , 179 , 8 , 0.18 ) ; color : #fde047 }
. card-badge . danger { background : rgba ( 239 , 68 , 68 , 0.2 ) ; color : #fca5a5 }
/* Opps urgent cards */
. opps-grid { display : grid ; grid-template-columns : repeat ( 2 , 1 fr ) ; gap : 10 px }
@ media ( max-width : 900px ) { . opps-grid { grid-template-columns : 1 fr } }
. opp { background : var ( - - bg -2 ) ; border-radius : 10 px ; padding : 14 px ; border-left : 3 px solid var ( - - dim ) ; transition : all .2 s }
. opp . critical { border-left-color : var ( - - err ) ; background : linear-gradient ( 135 deg , rgba ( 239 , 68 , 68 , 0.06 ) , var ( - - bg -2 ) ) }
. opp . high { border-left-color : var ( - - warn ) }
. opp : hover { transform : translateY ( -2 px ) ; border-color : var ( - - border - h ) }
. opp-head { display : flex ; justify-content : space-between ; align-items : flex-start ; margin-bottom : 6 px }
. opp-src { font-size : 9.5 px ; padding : 1 px 6 px ; border-radius : 4 px ; background : rgba ( 168 , 85 , 247 , 0.15 ) ; color : #d4a7fa ; text-transform : uppercase ; letter-spacing : 0.3 px ; font-weight : 700 }
. opp-val { font-family : 'JetBrains Mono' , monospace ; font-size : 15 px ; font-weight : 800 ; background : linear-gradient ( 135 deg , var ( - - gold ) , var ( - - warn ) ) ; -webkit- background-clip : text ; background-clip : text ; color : transparent }
. opp-signal { font-weight : 600 ; font-size : 12.5 px ; color : var ( - - text ) ; margin-top : 6 px }
. opp-action { font-size : 11 px ; color : var ( - - dim ) ; margin-top : 4 px ; line-height : 1.4 }
. opp-action :: before { content : '→ ' ; color : var ( - - accent ) }
. opp-cta { display : flex ; gap : 6 px ; margin-top : 10 px }
. opp-cta a , . opp-cta button { padding : 5 px 10 px ; background : var ( - - bg -3 ) ; border : 1 px solid var ( - - border ) ; color : var ( - - text ) ; border-radius : 5 px ; font-size : 10.5 px ; cursor : pointer ; text-decoration : none ; font-family : inherit ; transition : all .2 s }
. opp-cta a : hover , . opp-cta button : hover { border-color : var ( - - accent ) ; color : var ( - - accent ) }
. opp-cta . primary { background : linear-gradient ( 135 deg , var ( - - accent ) , var ( - - cyan ) ) ; color : white ; border : none ; font-weight : 600 }
/* Quick actions */
. qa-grid { display : grid ; grid-template-columns : repeat ( 3 , 1 fr ) ; gap : 8 px }
@ media ( max-width : 800px ) { . qa-grid { grid-template-columns : 1 fr 1 fr } }
. qa { background : var ( - - bg -2 ) ; border-radius : 10 px ; padding : 12 px ; border-top : 2 px solid var ( - - accent ) ; transition : all .2 s ; cursor : pointer ; text-decoration : none ; color : var ( - - text ) ; display : block }
. qa : hover { background : var ( - - bg -3 ) ; transform : translateY ( -2 px ) }
. qa . gold { border-top-color : var ( - - gold ) }
. qa . purple { border-top-color : var ( - - purple ) }
. qa . cyan { border-top-color : var ( - - cyan ) }
. qa-icon { font-size : 24 px ; margin-bottom : 6 px }
. qa-title { font-size : 13 px ; font-weight : 700 ; color : var ( - - text ) ; margin-bottom : 3 px }
. qa-desc { font-size : 11 px ; color : var ( - - dim ) ; line-height : 1.4 }
/* SDR messages preview */
. sdr-msg { background : var ( - - bg -2 ) ; border-radius : 8 px ; padding : 10 px 12 px ; margin-bottom : 6 px ; border-left : 2 px solid var ( - - cyan ) ; cursor : pointer ; transition : all .2 s }
. sdr-msg : hover { background : var ( - - bg -3 ) ; border-left-color : var ( - - accent ) }
. sdr-head { display : flex ; justify-content : space-between ; font-size : 11 px }
. sdr-target { font-weight : 700 ; color : var ( - - text ) }
. sdr-val { color : var ( - - gold ) ; font-family : 'JetBrains Mono' , monospace ; font-weight : 700 }
. sdr-preview { font-size : 10.5 px ; color : var ( - - dim ) ; margin-top : 4 px ; line-height : 1.4 ; max-height : 3 em ; overflow : hidden }
/* Templates */
. tpl { background : var ( - - bg -2 ) ; border-radius : 8 px ; padding : 12 px ; margin-bottom : 8 px }
. tpl-head { font-weight : 700 ; color : var ( - - accent ) ; font-size : 11.5 px ; margin-bottom : 6 px ; text-transform : uppercase ; letter-spacing : 0.4 px }
. tpl-body { font-size : 11 px ; color : var ( - - dim ) ; line-height : 1.5 ; white-space : pre-line ; font-family : 'JetBrains Mono' , monospace ; background : var ( - - bg -3 ) ; padding : 8 px 10 px ; border-radius : 5 px ; max-height : 200 px ; overflow : auto }
. tpl-copy { background : var ( - - accent ) ; color : white ; border : none ; padding : 5 px 10 px ; border-radius : 5 px ; font-size : 10.5 px ; cursor : pointer ; margin-top : 6 px ; font-family : inherit ; font-weight : 600 ; transition : all .2 s }
. tpl-copy : hover { background : var ( - - cyan ) }
. tpl-copy . copied { background : var ( - - ok ) }
/* Iframe roi */
. roi-wrap { position : relative ; background : var ( - - bg -2 ) ; border-radius : 10 px ; overflow : hidden }
. roi-frame { width : 100 % ; height : 540 px ; border : none ; display : block }
/* Stats table */
. stats-tbl { width : 100 % ; border-collapse : collapse ; font-size : 11.5 px }
. stats-tbl td { padding : 6 px 8 px ; border-bottom : 1 px solid var ( - - bg -3 ) }
. stats-tbl td : first-child { color : var ( - - dim ) ; width : 60 % }
. stats-tbl td : last-child { color : var ( - - text ) ; font-family : 'JetBrains Mono' , monospace ; font-weight : 700 ; text-align : right }
/* Loading */
. loading { text-align : center ; padding : 30 px ; color : var ( - - dim ) }
. spinner { width : 32 px ; height : 32 px ; border : 3 px solid var ( - - bg -3 ) ; border-top-color : var ( - - accent ) ; border-radius : 50 % ; margin : 0 auto 10 px ; animation : spin 1 s linear infinite }
@ keyframes spin { to { transform : rotate ( 360 deg ) } }
/* Toast */
. toast { position : fixed ; bottom : 20 px ; right : 20 px ; background : var ( - - ok ) ; color : white ; padding : 10 px 18 px ; border-radius : 8 px ; font-size : 12 px ; font-weight : 700 ; z-index : 1000 ; opacity : 0 ; transition : opacity .3 s ; pointer-events : none ; box-shadow : 0 4 px 20 px rgba ( 34 , 197 , 94 , 0.3 ) }
. toast . show { opacity : 1 }
< / style >
< / head >
< body >
< div class = "container" >
< header >
< div >
< h1 > < span class = "pulse" > < / span > 💼 Sales Hub — Tout piloter depuis ici< / h1 >
< div class = "sub" > Opportunities urgent · SDR messages prêts · ROI Simulator · Board Pack · Templates · Pipeline live< / div >
< div class = "clock" id = "clock" > —< / div >
< / div >
< div class = "actions" >
< a href = "/weval-technology-platform.html" class = "btn" > 🏠 WTP< / a >
< a href = "/dg-command-center.html" class = "btn" > 🎖 DG Center< / a >
< a href = "/intelligence-growth.html" class = "btn" > 🌐 Intel& Growth< / a >
< a href = "/pitch.html" class = "btn" target = "_blank" > 📄 Pitch public< / a >
< button class = "btn" onclick = "load()" > ↻< / button >
< / div >
< / header >
<!-- PRIO BANNER -->
< div class = "prio-banner" >
< div >
< div class = "title" > 🚨 PRIORITÉ ABSOLUE — Cette semaine< / div >
< div class = "sub" style = "margin-top:3px" > Contacter les 4 opportunities urgent. Utiliser le ROI Simulator en discovery.< / div >
< / div >
< div style = "text-align:right" >
< div class = "stat" id = "urgent-val" > —< / div >
< div class = "sub" > pipeline urgent à activer< / div >
< / div >
< / div >
<!-- KPI STRIP -->
< div class = "kpi-strip" >
< div class = "kpi gold" > < div class = "kpi-lbl" > 💰 Pipeline total< / div > < div class = "kpi-val gold" id = "k-pipe" > —< / div > < div class = "kpi-sub" > opps watch< / div > < / div >
< div class = "kpi danger" > < div class = "kpi-lbl" > 🔴 Urgent< / div > < div class = "kpi-val" id = "k-urg" > —< / div > < div class = "kpi-sub" > critical + high< / div > < / div >
< div class = "kpi cyan" > < div class = "kpi-lbl" > 💬 Messages SDR prêts< / div > < div class = "kpi-val" id = "k-sdr" > —< / div > < div class = "kpi-sub" > copy-paste manuel< / div > < / div >
< div class = "kpi purple" > < div class = "kpi-lbl" > 🎖 Competitors trackés< / div > < div class = "kpi-val" id = "k-comp" > —< / div > < div class = "kpi-sub" > DarkScout live< / div > < / div >
< div class = "kpi" > < div class = "kpi-lbl" > ⚡ Innovations 24h< / div > < div class = "kpi-val" id = "k-innov" > —< / div > < div class = "kpi-sub" > WEVL Predict< / div > < / div >
< / div >
<!-- QUICK ACTIONS -->
< div class = "card" >
< div class = "card-head" > < div class = "card-title" > ⚡ Quick Actions< / div > < div class = "card-badge" > 6 assets prêts< / div > < / div >
< div class = "qa-grid" >
< a href = "/pitch.html" target = "_blank" class = "qa gold" >
< div class = "qa-icon" > 📄< / div >
< div class = "qa-title" > Pitch 1 écran< / div >
< div class = "qa-desc" > Landing page prospect · V67 simulator embedded< / div >
< / a >
< a href = "/agent-roi-simulator.html" target = "_blank" class = "qa" >
< div class = "qa-icon" > 🧮< / div >
< div class = "qa-title" > ROI Simulator< / div >
< div class = "qa-desc" > Discovery call live · scaling par prospect< / div >
< / a >
< a href = "/downloads/weval-board-pack-2026-04-18.pdf" target = "_blank" class = "qa purple" >
< div class = "qa-icon" > 📊< / div >
< div class = "qa-title" > Board Pack PDF< / div >
< div class = "qa-desc" > 5 slides · Problème · Solution · Différenciateurs< / div >
< / a >
< a href = "#" class = "qa cyan" onclick = "loadSDR();return false;" >
< div class = "qa-icon" > 💬< / div >
< div class = "qa-title" > Messages SDR< / div >
< div class = "qa-desc" > 7 messages personnalisés · copy-paste manuel< / div >
< / a >
< a href = "/pain-points-atlas.html" target = "_blank" class = "qa" >
< div class = "qa-icon" > 🗺️< / div >
< div class = "qa-title" > Pain Points Atlas< / div >
< div class = "qa-desc" > 25 ERPs · 35 pain points · commercial assets< / div >
< / a >
< a href = "/erp-gap-fill-offer.html" target = "_blank" class = "qa gold" >
< div class = "qa-icon" > 💰< / div >
< div class = "qa-title" > Offre ERP Gap-Fill< / div >
< div class = "qa-desc" > Matrice 5× 5 · 4 services pricing · 7 verticaux< / div >
< / a >
< / div >
< / div >
<!-- MAIN LAYOUT -->
< div class = "layout" >
< div >
<!-- OPPS URGENT -->
< div class = "card" >
< div class = "card-head" >
< div class = "card-title" > 🎯 Opportunities Urgent — Action cette semaine< / div >
< div class = "card-badge danger" id = "opps-count" > —< / div >
< / div >
< div class = "opps-grid" id = "opps-grid" > < div class = "loading" > < div class = "spinner" > < / div > < / div > < / div >
< / div >
<!-- ROI SIMULATOR inline -->
< div class = "card" >
< div class = "card-head" > < div class = "card-title" > 🧮 ROI Simulator (interactif) — partager écran en call< / div > < div class = "card-badge" > iframe live< / div > < / div >
< div class = "roi-wrap" >
< iframe class = "roi-frame" src = "/agent-roi-simulator.html" loading = "lazy" > < / iframe >
< / div >
< / div >
<!-- Templates -->
< div class = "card" >
< div class = "card-head" > < div class = "card-title" > 📧 Email Templates WEVAL< / div > < div class = "card-badge" > 3 prêts< / div > < / div >
< div id = "templates" > < / div >
< / div >
< / div >
< div >
<!-- SDR preview -->
< div class = "card" >
< div class = "card-head" >
< div class = "card-title" > 💬 Messages SDR du jour< / div >
< div class = "card-badge" id = "sdr-count" > —< / div >
< / div >
< div style = "font-size:10.5px;color:var(--dim);margin-bottom:10px;padding:6px 10px;background:rgba(234,179,8,0.08);border-radius:4px" > ⚠️ Doctrine : copy-paste manuel · ZERO send auto · personnalisation 1 phrase obligatoire< / div >
< div id = "sdr-list" > < div class = "loading" > < div class = "spinner" > < / div > < / div > < / div >
< div style = "margin-top:10px;text-align:center" >
< a href = "/downloads/weval-sdr-outreach-20260418.md" target = "_blank" style = "color:var(--accent);font-size:11.5px;font-weight:700;text-decoration:none" > 📄 Voir fichier complet des messages →< / a >
< / div >
< / div >
<!-- Commercial stats -->
< div class = "card" >
< div class = "card-head" > < div class = "card-title" > 📊 Commercial Live Stats< / div > < div class = "card-badge" > auto-refresh 60s< / div > < / div >
< table class = "stats-tbl" id = "stats-tbl" > < / table >
< / div >
<!-- DarkScout quick -->
< div class = "card" >
< div class = "card-head" > < div class = "card-title" > 🎖 DarkScout — 3 threats majeures< / div > < div class = "card-badge" > live< / div > < / div >
< div id = "darkscout-top" > < / div >
< div style = "margin-top:10px;text-align:center" >
< a href = "/intelligence-growth.html#darkscout" target = "_blank" style = "color:var(--accent);font-size:11.5px;font-weight:700;text-decoration:none" > → Voir les 8 compétiteurs complets< / a >
< / div >
< / div >
< / div >
< / div >
< / div >
< div class = "toast" id = "toast" > Copié !< / div >
< script >
const API _V71 = '/api/wevia-v71-intelligence-growth.php' ;
let DATA = null ;
function clockTick ( ) { const d = new Date ( ) ; document . getElementById ( 'clock' ) . textContent = d . toLocaleDateString ( 'fr-FR' ) + ' · ' + d . toLocaleTimeString ( 'fr-FR' ) + ' · auto-refresh 60s' ; }
setInterval ( clockTick , 1000 ) ; clockTick ( ) ;
function fmt ( n ) { if ( ! n && n !== 0 ) return '—' ; if ( Math . abs ( n ) >= 1000000 ) return ( n / 1000000 ) . toFixed ( 1 ) + 'M' ; if ( Math . abs ( n ) >= 1000 ) return ( n / 1000 ) . toFixed ( 1 ) + 'k' ; return Math . round ( n ) ; }
function toast ( msg ) { const t = document . getElementById ( 'toast' ) ; t . textContent = msg ; t . classList . add ( 'show' ) ; setTimeout ( ( ) => t . classList . remove ( 'show' ) , 2000 ) ; }
async function load ( ) {
try {
const r = await fetch ( API _V71 + '?t=' + Date . now ( ) ) ;
DATA = await r . json ( ) ;
render ( ) ;
} catch ( e ) { console . error ( e ) ; }
}
function render ( ) {
if ( ! DATA ) return ;
const s = DATA . summary ;
// KPIs
document . getElementById ( 'k-pipe' ) . textContent = fmt ( s . opportunities _total _value _keur * 1000 ) + '€' ;
document . getElementById ( 'k-urg' ) . textContent = s . opportunities _high _urgency ;
document . getElementById ( 'k-sdr' ) . textContent = s . opportunities _total _value _keur > 0 ? DATA . opportunities _watch . opportunities . length : 0 ;
document . getElementById ( 'k-comp' ) . textContent = s . competitors _tracked ;
document . getElementById ( 'k-innov' ) . textContent = s . innovations _last _24h ;
// Urgent pipeline value
const urgOpps = DATA . opportunities _watch . opportunities . filter ( o => [ 'critical' , 'high' ] . includes ( o . urgency ) ) ;
const urgVal = urgOpps . reduce ( ( sum , o ) => sum + ( o . estimated _value _keur || 0 ) , 0 ) ;
document . getElementById ( 'urgent-val' ) . textContent = fmt ( urgVal * 1000 ) + '€' ;
// Opps urgent cards
document . getElementById ( 'opps-count' ) . textContent = urgOpps . length + ' urgent' ;
document . getElementById ( 'opps-grid' ) . innerHTML = urgOpps . map ( o => `
<div class="opp ${ o . urgency } ">
<div class="opp-head">
<div class="opp-src"> ${ o . source } </div>
<div class="opp-val"> ${ o . estimated _value _keur ? fmt ( o . estimated _value _keur * 1000 ) + '€' : '—' } </div>
</div>
<div class="opp-signal"> ${ o . signal } </div>
<div class="opp-action"> ${ o . action } </div>
<div class="opp-cta">
<a href="https://www.linkedin.com/search/results/people/?keywords= ${ encodeURIComponent ( o . signal ) } " target="_blank">🔍 LinkedIn</a>
<button onclick="copyTpl(' ${ o . id } ',' ${ o . source } ')">📋 Message</button>
<a href="/pitch.html" target="_blank" class="primary">Envoyer pitch</a>
</div>
</div>
` ) . join ( '' ) ;
// SDR list (use V71 opps as source)
const allOpps = DATA . opportunities _watch . opportunities ;
document . getElementById ( 'sdr-count' ) . textContent = allOpps . length + ' messages' ;
document . getElementById ( 'sdr-list' ) . innerHTML = allOpps . slice ( 0 , 7 ) . map ( o => `
<div class="sdr-msg" onclick="copyTpl(' ${ o . id } ',' ${ o . source } ')">
<div class="sdr-head">
<span class="sdr-target"> ${ o . id } · ${ o . signal . substring ( 0 , 40 ) } ${ o . signal . length > 40 ? '...' : '' } </span>
<span class="sdr-val"> ${ o . estimated _value _keur ? fmt ( o . estimated _value _keur * 1000 ) + '€' : '—' } </span>
</div>
<div class="sdr-preview">→ ${ o . action } · Click pour copier le template</div>
</div>
` ) . join ( '' ) ;
// Stats tbl
const tpl = document . querySelector ( '.roi-frame' ) . src ;
document . getElementById ( 'stats-tbl' ) . innerHTML = `
<tr><td>Pipeline total</td><td> ${ fmt ( s . opportunities _total _value _keur * 1000 ) } €</td></tr>
<tr><td>Pipeline urgent (crit+high)</td><td> ${ fmt ( urgVal * 1000 ) } €</td></tr>
<tr><td>Opportunities totales</td><td> ${ allOpps . length } </td></tr>
<tr><td>Competitors DarkScout</td><td> ${ s . competitors _tracked } </td></tr>
<tr><td>Compétiteurs HIGH threat</td><td> ${ s . competitors _high _threat } </td></tr>
<tr><td>Innovations 24h</td><td> ${ s . innovations _last _24h } </td></tr>
<tr><td>Chatbots déployés</td><td> ${ s . chatbots _deployed } / ${ s . chatbots _total } </td></tr>
<tr><td>Agility agents gap</td><td> ${ s . agility _agents _gap } ( ${ s . agility _fte _savings _year } FTE)</td></tr>
` ;
// DarkScout top 3 high threat
const highThreat = DATA . darkscout _competitors . competitors . filter ( c => c . threat _level === 'high' ) . slice ( 0 , 3 ) ;
document . getElementById ( 'darkscout-top' ) . innerHTML = highThreat . map ( c => `
<div style="background:var(--bg-2);border-radius:6px;padding:10px;margin-bottom:6px;border-left:3px solid var(--err)">
<div style="font-weight:700;font-size:12px">🎯 vs ${ c . name } </div>
<div style="font-size:10.5px;color:#5eead4;margin-top:4px"> ${ c . weval _differentiator } </div>
</div>
` ) . join ( '' ) ;
}
// Email templates (3 templates WEVAL)
const TEMPLATES = [
{
name : 'LinkedIn Intro Froid' ,
body : ` Bonjour [Prénom],
[Signal spécifique à eux] — WEVAL a construit une plateforme de 35 agents IA souverains qui comblent exactement ce type de gap sur votre ERP.
3 points concrets :
• Déployé en 4 semaines (vs 12 mois Palantir)
• ROI contractuel : 17M€ savings/an (ref Ethica · 146k HCPs live)
• Souveraineté EU/Maghreb · 13 providers LLM
Simulateur ROI (2 min) : https://weval-consulting.com/agent-roi-simulator.html
30 min cette semaine ?
Yacine Mahboub
WEVAL Consulting · https://weval-consulting.com/pitch.html `
} ,
{
name : 'Email Follow-up RFP' ,
body : ` Bonjour [Prénom],
J'ai vu votre appel d'offres [ERP/sujet] — WEVAL peut y répondre avec une approche différente :
• Pas de consulting facturé au jour-homme
• Agents métier prêts à plugger (35 au catalogue)
• Savings contractuels, pas estimés
• Déploiement 4 sem vs 6-12 mois standard
Je vous joins :
- Pitch 1 écran : https://weval-consulting.com/pitch.html
- Pain Points Atlas : https://weval-consulting.com/pain-points-atlas.html
- Board Pack 5 slides : https://weval-consulting.com/downloads/weval-board-pack-2026-04-18.pdf
30 min pour vous présenter le dossier ?
Yacine `
} ,
{
name : 'Warm Intro Referral' ,
body : ` Bonjour [Prénom],
[Contact commun] m'a parlé de vos enjeux — rapidement :
WEVAL = 35 agents IA souverains compatibles SAP/Oracle/Sage/tous ERPs.
Savings documentés : 17M€/an par client. ROI 4 mois.
ROI Simulator direct : https://weval-consulting.com/agent-roi-simulator.html
Pitch complet : https://weval-consulting.com/pitch.html
Dispo 30 min quand vous voulez.
Yacine `
}
] ;
function renderTemplates ( ) {
const wrap = document . getElementById ( 'templates' ) ;
wrap . innerHTML = TEMPLATES . map ( ( t , i ) => `
<div class="tpl">
<div class="tpl-head"> ${ t . name } </div>
<div class="tpl-body"> ${ t . body } </div>
<button class="tpl-copy" onclick="copyToClipboard( \` ${ t . body . replace ( /`/g , '\\`' ) } \` , this)">📋 Copier</button>
</div>
` ) . join ( '' ) ;
}
function copyToClipboard ( text , btn ) {
navigator . clipboard . writeText ( text ) . then ( ( ) => {
if ( btn ) { btn . textContent = '✓ Copié' ; btn . classList . add ( 'copied' ) ; setTimeout ( ( ) => { btn . textContent = '📋 Copier' ; btn . classList . remove ( 'copied' ) ; } , 2000 ) ; }
toast ( 'Copié dans le presse-papier' ) ;
} ) ;
}
function copyTpl ( oppId , source ) {
const o = DATA . opportunities _watch . opportunities . find ( x => x . id === oppId ) ;
if ( ! o ) return ;
const tpl = TEMPLATES [ source === 'Referral' ? 2 : ( source === 'Web' ? 1 : 0 ) ] ;
const msg = tpl . body . replace ( '[Signal spécifique à eux]' , o . signal ) . replace ( '[ERP/sujet]' , o . signal ) ;
copyToClipboard ( msg ) ;
}
function loadSDR ( ) {
window . open ( '/downloads/weval-sdr-outreach-20260418.md' , '_blank' ) ;
}
renderTemplates ( ) ;
load ( ) ;
setInterval ( load , 60000 ) ;
< / script >
< / body >
< / html >