diff --git a/api/em-live-inject.js b/api/em-live-inject.js
new file mode 100644
index 000000000..c272a4be5
--- /dev/null
+++ b/api/em-live-inject.js
@@ -0,0 +1,182 @@
+/* ═══ WEVAL Enterprise Management — Live KPI Injector ═══
+ ENRICHIT sans écraser. Ajouté par session Opus 17avr.
+ Fetch /api/em-live-kpi.php et met à jour les KPIs visuels.
+*/
+(function(){
+ const API = '/api/em-live-kpi.php';
+
+ async function loadLiveKPI() {
+ try {
+ const r = await fetch(API, {signal: AbortSignal.timeout(12000)});
+ const d = await r.json();
+
+ // 1. Mettre à jour les stat-cards existantes
+ const el = id => document.getElementById(id);
+ if (el('statPages')) el('statPages').textContent = d.assets?.html_pages || '–';
+ if (el('statApis')) el('statApis').textContent = d.assets?.php_apis || '–';
+ if (el('statWiki')) el('statWiki').textContent = d.assets?.wiki_entries || '–';
+ if (el('statVault')) el('statVault').textContent = d.assets?.vault_doctrines || '–';
+ if (el('statSvc')) el('statSvc').textContent = (d.services?.filter(s=>s.status==='UP').length || 0);
+ if (el('statIntents')) el('statIntents').textContent = '20+';
+ if (el('statGrand')) el('statGrand').textContent = d.grand_total || '–';
+ if (el('statHealth')) el('statHealth').textContent = (d.health?.pct || 0) + '%';
+
+ // 2. Injecter la section LIVE DASHBOARD si elle n'existe pas
+ if (!document.getElementById('liveKpiSection')) {
+ const section = document.createElement('div');
+ section.id = 'liveKpiSection';
+ section.className = 'section';
+ section.innerHTML = buildLiveDashboard(d);
+ // Insérer après le hero-stats
+ const heroStats = document.querySelector('.hero-stats');
+ if (heroStats && heroStats.parentNode) {
+ heroStats.parentNode.insertBefore(section, heroStats.nextSibling);
+ }
+ } else {
+ document.getElementById('liveKpiSection').innerHTML = buildLiveDashboard(d);
+ }
+
+ console.log('[EM-LIVE] KPIs loaded in ' + d.elapsed_ms + 'ms');
+ } catch(e) {
+ console.warn('[EM-LIVE] KPI fetch failed:', e);
+ }
+ }
+
+ function buildLiveDashboard(d) {
+ const svc = (d.services||[]).map(s =>
+ `${s.name}`
+ ).join('');
+
+ const providers = (d.sovereign?.providers||[]).map(p =>
+ `${p}`
+ ).join('');
+
+ const countries = (d.ethica?.by_country||[]).map(c =>
+ `
+ ${c.country==='DZ'?'🇩🇿':c.country==='MA'?'🇲🇦':c.country==='TN'?'🇹🇳':'🌍'}
+ ${c.country}
+ ${Number(c.t||0).toLocaleString()} HCPs
+ ${Number(c.e||0).toLocaleString()} emails
+
`
+ ).join('');
+
+ const pmta = (d.pmta||[]).map(p =>
+ `${p.name}`
+ ).join('');
+
+ const docker = (d.docker||[]).slice(0,10).map(c =>
+ `${c.name}${c.status.split(' ')[0]} ${c.status.split(' ')[1]||''}
`
+ ).join('');
+
+ return `
+
+ 📊 Live Infrastructure — temps réel LIVE
+
+
+
+
+
🖥️ S204 — WEVIA + Ethica
+
${d.s204?.load || '?'}
+
Load avg · ${d.s204?.cpu_cores || 8} CPU · ${d.s204?.ram_total_mb || 0}MB RAM
+
RAM libre: ${d.s204?.ram_free_mb?.toLocaleString() || '?'}MB · Disk: ${d.s204?.disk_pct || '?'}
+
FPM: ${d.s204?.fpm_workers || '?'} workers · Docker: ${d.s204?.docker_containers || '?'}
+
+
+
+
+
+
🖥️ S95 — WEVADS + Arsenal
+
${d.s95?.load || '?'}
+
Load avg · ${d.s95?.ram_total_mb?.toLocaleString() || '?'}MB RAM · Disk: ${d.s95?.disk_pct || '?'}
+
Status: ${d.s95?.status || '?'}
+
+
+
+
+
+
🧠 Sovereign IA — ${d.sovereign?.cost || '0€'}
+
${d.sovereign?.active || 0}/${d.sovereign?.total || 0}
+
Providers actifs · Primary: ${d.sovereign?.primary || '?'}
+
${providers}
+
+
+
+
+
💊 Ethica HCPs — Maghreb
+
${Number(d.ethica?.total_hcps||0).toLocaleString()}
+
${Number(d.ethica?.with_email||0).toLocaleString()} emails (${d.ethica?.pct_email||0}%) · ${Number(d.ethica?.with_phone||0).toLocaleString()} phones (${d.ethica?.pct_phone||0}%)
+
Gap email: ${Number(d.ethica?.gap_email||0).toLocaleString()}
+
${countries}
+
+
+
+
+
⚡ Services Live
+
${svc}
+
PMTA ECS: ${pmta}
+
+
+
+
+
🐳 Docker Containers
+ ${docker}
+
+
+
+
+
+
+
+
🎙️ Whisper.cpp
+
Binary: ${d.whisper?.binary||'?'}
+
Model: ${d.whisper?.model||'?'}
+
+
+
+
+
📦 Git
+
HEAD: ${d.git?.head?.substring(0,30) || '?'}
+
Status: ${d.git?.status||'?'}
+
+
+
+
+
🧪 NonReg Playwright
+
${d.nonreg?.passed||0}/${d.nonreg?.total||0}
+
Score: ${d.nonreg?.score||'?'}
+
+
+
+ Dernière mise à jour: ${d.ts || '?'} · API: ${d.elapsed_ms||'?'}ms · Auto-refresh: 60s
+ `;
+ }
+
+ // Load immédiat + refresh toutes les 60s
+ loadLiveKPI();
+ setInterval(loadLiveKPI, 60000);
+})();
diff --git a/weval-enterprise-management.html b/weval-enterprise-management.html
index 20697e619..fd8e8d328 100644
--- a/weval-enterprise-management.html
+++ b/weval-enterprise-management.html
@@ -594,5 +594,65 @@ loadData();
// Refresh health every 60s
setInterval(() => { checkHealth(); }, 60000);
+
+
+