590 lines
33 KiB
HTML
590 lines
33 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>WEVAL · Enterprise Complete — 20 départements · 169 KPIs · Gap Agents · Macro Process</title>
|
||
<style>
|
||
:root{
|
||
--bg-0:#05060a; --bg-1:#0b0d15; --bg-2:#11141f; --bg-3:#171b2a; --bg-tile:#0f1420;
|
||
--border:rgba(99,102,241,0.15); --border-h:rgba(99,102,241,0.35);
|
||
--text:#e2e8f0; --dim:#94a3b8; --mute:#64748b;
|
||
--accent:#14b8a6; --accent2:#6366f1; --purple:#a855f7; --cyan:#06b6d4;
|
||
--ok:#22c55e; --warn:#f59e0b; --err:#ef4444; --rose:#f43f5e; --gold:#eab308;
|
||
--c-fin:#3b82f6; --c-sup:#06b6d4; --c-mfg:#f59e0b; --c-sales:#10b981;
|
||
--c-hr:#a855f7; --c-it:#ec4899; --c-legal:#64748b; --c-esg:#22c55e;
|
||
}
|
||
*{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:100vh;font-size:13px;line-height:1.5}
|
||
.container{max-width:1800px;margin:0 auto;padding:20px 26px 80px}
|
||
.shell{display:flex;justify-content:space-between;align-items:center;margin-bottom:14px;padding:12px 18px;background:var(--bg-1);border:1px solid var(--border);border-radius:10px}
|
||
.breadcrumb{font-size:12px;color:var(--dim)}
|
||
.breadcrumb a{color:var(--accent);text-decoration:none}
|
||
.breadcrumb .sep{margin:0 7px;color:var(--mute)}
|
||
.breadcrumb .current{color:var(--text);font-weight:600}
|
||
.shell h1{font-size:18px;font-weight:800;background:linear-gradient(90deg,#22d3ee,#a855f7,#eab308);-webkit-background-clip:text;background-clip:text;color:transparent}
|
||
.shell .pulse{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--ok);box-shadow:0 0 0 0 rgba(34,197,94,.7);animation:pulse 2s infinite;margin-right:6px;vertical-align:middle}
|
||
@keyframes pulse{0%,100%{box-shadow:0 0 0 0 rgba(34,197,94,.7)}70%{box-shadow:0 0 0 8px rgba(34,197,94,0)}}
|
||
.shell-actions{display:flex;gap:8px;flex-wrap:wrap}
|
||
.btn{padding:6px 12px;background:var(--bg-2);border:1px solid var(--border);color:var(--text);border-radius:6px;font-size:11.5px;cursor:pointer;text-decoration:none;font-family:inherit;transition:all .15s}
|
||
.btn:hover{border-color:var(--accent);color:var(--accent)}
|
||
.btn.primary{background:linear-gradient(135deg,var(--accent),var(--cyan));color:white;border:none;font-weight:600}
|
||
|
||
.kpi-super{display:grid;grid-template-columns:repeat(6,1fr);gap:10px;margin-bottom:14px}
|
||
@media(max-width:1200px){.kpi-super{grid-template-columns:repeat(3,1fr)}}
|
||
.ks{background:var(--bg-1);border:1px solid var(--border);border-radius:10px;padding:12px 14px;border-left:3px solid var(--accent);position:relative;overflow:hidden}
|
||
.ks.gold{border-left-color:var(--gold)}
|
||
.ks.danger{border-left-color:var(--err)}
|
||
.ks.cyan{border-left-color:var(--cyan)}
|
||
.ks.purple{border-left-color:var(--purple)}
|
||
.ks.ok{border-left-color:var(--ok)}
|
||
.ks .l{font-size:10px;color:var(--dim);text-transform:uppercase;letter-spacing:0.5px;font-weight:600}
|
||
.ks .v{font-size:22px;font-weight:800;margin-top:4px;line-height:1;font-family:'JetBrains Mono',monospace}
|
||
.ks .v.gold{background:linear-gradient(135deg,var(--gold),var(--warn));-webkit-background-clip:text;background-clip:text;color:transparent}
|
||
.ks .s{font-size:10px;color:var(--mute);margin-top:2px}
|
||
|
||
.filters{display:flex;gap:5px;flex-wrap:wrap;margin-bottom:14px;padding:8px 12px;background:var(--bg-1);border:1px solid var(--border);border-radius:10px;align-items:center}
|
||
.filters .lbl{font-size:11px;color:var(--dim);font-weight:700;margin-right:8px;text-transform:uppercase;letter-spacing:0.4px}
|
||
.fb{padding:5px 11px;background:var(--bg-3);border:1px solid var(--border);color:var(--dim);border-radius:14px;font-size:11px;cursor:pointer;font-family:inherit;transition:all .15s}
|
||
.fb:hover{color:var(--text);border-color:var(--accent)}
|
||
.fb.active{background:linear-gradient(135deg,var(--accent),var(--cyan));color:white;border:none;font-weight:700}
|
||
|
||
.sec-title{font-size:12px;font-weight:800;letter-spacing:2px;text-transform:uppercase;color:var(--dim);margin:22px 0 10px;padding-bottom:6px;border-bottom:1px solid var(--bg-3);display:flex;justify-content:space-between;align-items:center}
|
||
.sec-title .count{color:var(--accent);font-size:11px;letter-spacing:0}
|
||
|
||
.depts-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:12px;margin-bottom:22px}
|
||
.dept{background:var(--bg-tile);border:1px solid var(--border);border-radius:12px;overflow:hidden;transition:all .2s;cursor:pointer;display:flex;flex-direction:column}
|
||
.dept:hover{transform:translateY(-3px);border-color:var(--border-h);box-shadow:0 10px 30px rgba(0,0,0,0.4)}
|
||
.dept-head{padding:12px 14px;display:flex;align-items:center;gap:10px;position:relative;border-bottom:1px solid rgba(255,255,255,0.04)}
|
||
.dept-head::before{content:'';position:absolute;left:0;top:0;width:4px;height:100%;background:var(--dc)}
|
||
.dept-icon{font-size:28px;line-height:1}
|
||
.dept-meta{flex:1}
|
||
.dept-name{font-size:13px;font-weight:700;color:var(--text);line-height:1.2}
|
||
.dept-agents-info{font-size:10px;color:var(--mute);margin-top:3px;font-family:'JetBrains Mono',monospace}
|
||
.dept-status{padding:2px 7px;background:var(--bg-3);border-radius:10px;font-size:9px;font-weight:700;letter-spacing:0.3px;font-family:'JetBrains Mono',monospace;text-transform:uppercase}
|
||
.dept-status.ok{background:rgba(34,197,94,0.15);color:#86efac}
|
||
.dept-status.warn{background:rgba(245,158,11,0.15);color:#fbbf24}
|
||
.dept-status.critical{background:rgba(239,68,68,0.18);color:#fca5a5}
|
||
.dept-kpis{padding:10px 14px;flex:1}
|
||
.kpi-row{display:grid;grid-template-columns:1fr 80px 14px;gap:8px;align-items:center;padding:5px 0;font-size:11px;border-bottom:1px dashed var(--bg-3)}
|
||
.kpi-row:last-child{border-bottom:none}
|
||
.kpi-name{color:var(--dim);font-size:10.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||
.kpi-val{font-family:'JetBrains Mono',monospace;font-weight:700;color:var(--text);text-align:right;font-size:11px}
|
||
.kpi-dot{width:8px;height:8px;border-radius:50%}
|
||
.kpi-dot.ok{background:var(--ok)} .kpi-dot.warn{background:var(--warn)} .kpi-dot.critical{background:var(--err)}
|
||
.dept-footer{padding:10px 14px;background:rgba(0,0,0,0.25);border-top:1px solid rgba(255,255,255,0.04);display:flex;justify-content:space-between;align-items:center;gap:8px}
|
||
.dept-avatars{display:flex;align-items:center}
|
||
.dept-avatars img{width:26px;height:26px;border-radius:50%;border:2px solid var(--bg-tile);margin-left:-6px;background:var(--bg-3);object-fit:cover}
|
||
.dept-avatars img:first-child{margin-left:0}
|
||
.dept-avatars .more{width:26px;height:26px;border-radius:50%;background:var(--bg-3);color:var(--dim);font-size:9px;font-weight:800;display:inline-flex;align-items:center;justify-content:center;border:2px solid var(--bg-tile);margin-left:-6px}
|
||
.dept-cta{font-size:10.5px;color:var(--accent);font-weight:700;white-space:nowrap}
|
||
|
||
.gap-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:10px;margin-bottom:22px}
|
||
.gap{background:var(--bg-1);border:1px solid var(--border);border-radius:10px;padding:12px 14px;border-left:3px solid var(--purple);transition:all .2s}
|
||
.gap:hover{border-color:var(--border-h);transform:translateY(-2px)}
|
||
.gap.high{border-left-color:var(--warn)}
|
||
.gap.medium{border-left-color:var(--cyan)}
|
||
.gap-head{display:flex;align-items:center;gap:10px;margin-bottom:8px}
|
||
.gap-avatar{width:36px;height:36px;border-radius:50%;background:var(--bg-3);overflow:hidden;flex-shrink:0}
|
||
.gap-avatar img{width:100%;height:100%;object-fit:cover}
|
||
.gap-name{font-size:12.5px;font-weight:700;color:var(--text);line-height:1.2}
|
||
.gap-fw{display:inline-block;margin-top:2px;font-size:9.5px;padding:1px 6px;border-radius:4px;background:rgba(99,102,241,0.15);color:#a5b4fc;font-family:'JetBrains Mono',monospace}
|
||
.gap-role{font-size:10.5px;color:var(--dim);line-height:1.4;min-height:2.8em}
|
||
.gap-foot{display:flex;justify-content:space-between;align-items:center;margin-top:8px;padding-top:8px;border-top:1px dashed var(--bg-3)}
|
||
.gap-save{font-size:11px;color:var(--gold);font-family:'JetBrains Mono',monospace;font-weight:700}
|
||
.gap-status{font-size:9px;font-weight:700;padding:2px 7px;border-radius:5px;text-transform:uppercase;letter-spacing:0.3px}
|
||
.gap-status.to_build{background:rgba(245,158,11,0.15);color:#fbbf24}
|
||
.gap-status.partial{background:rgba(6,182,212,0.18);color:#7dd3fc}
|
||
.gap-status.deployed{background:rgba(34,197,94,0.18);color:#86efac}
|
||
|
||
.today{background:var(--bg-1);border:1px solid var(--border);border-radius:12px;padding:16px;margin-bottom:20px}
|
||
.today-head{font-size:12px;font-weight:800;letter-spacing:1.5px;text-transform:uppercase;color:var(--dim);margin-bottom:12px;display:flex;justify-content:space-between}
|
||
.today-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:8px}
|
||
.today-item{background:var(--bg-2);border-radius:8px;padding:10px 12px;border-left:3px solid var(--accent);transition:all .15s;cursor:pointer;text-decoration:none;color:var(--text);display:block}
|
||
.today-item:hover{background:var(--bg-3);transform:translateX(2px)}
|
||
.today-item .ver{font-size:9.5px;font-family:'JetBrains Mono',monospace;font-weight:700;color:var(--gold);margin-bottom:3px;letter-spacing:0.3px}
|
||
.today-item .name{font-size:11.5px;font-weight:700;color:var(--text);line-height:1.2;margin-bottom:3px}
|
||
.today-item .desc{font-size:10px;color:var(--dim);line-height:1.4;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
|
||
|
||
.proc-wrap{background:var(--bg-1);border:1px solid var(--border);border-radius:12px;padding:16px;margin-bottom:20px}
|
||
.proc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:10px}
|
||
.proc{background:var(--bg-2);border-radius:8px;padding:10px 12px;border-left:2px solid var(--cyan)}
|
||
.proc-name{font-weight:700;font-size:11.5px;color:var(--text)}
|
||
.proc-steps{font-size:10px;color:var(--dim);margin-top:4px;line-height:1.45}
|
||
.proc-depts{font-size:9.5px;color:var(--mute);margin-top:5px;font-family:'JetBrains Mono',monospace}
|
||
|
||
.loading{text-align:center;padding:40px;color:var(--dim)}
|
||
.spinner{width:32px;height:32px;border:3px solid var(--bg-3);border-top-color:var(--accent);border-radius:50%;margin:0 auto 12px;animation:spin 1s linear infinite}
|
||
@keyframes spin{to{transform:rotate(360deg)}}
|
||
.clock{font-family:'JetBrains Mono',monospace;color:var(--accent);font-size:10.5px;margin-top:2px}
|
||
|
||
/* === OPUS RESPONSIVE FIX v2 19avr — append-only, doctrine #14 === */
|
||
@media(max-width: 480px) {
|
||
html, body { overflow-x: hidden !important; max-width: 100vw; }
|
||
body, main, section, article { word-break: break-word; overflow-wrap: anywhere; }
|
||
img, video, iframe, canvas, svg, table, pre, code { max-width: 100% !important; }
|
||
pre, code { white-space: pre-wrap; word-break: break-all; }
|
||
table { display: block; overflow-x: auto; }
|
||
.container, [class*="container"], [class*="wrapper"] { max-width: 100vw !important; padding-left: 12px !important; padding-right: 12px !important; }
|
||
[class*="grid"], [class*="-grid"] { grid-template-columns: 1fr !important; gap: 10px !important; }
|
||
[class*="kpi"], [class*="stats"], [class*="-cards"] { grid-template-columns: 1fr !important; }
|
||
header, nav, footer { flex-wrap: wrap !important; }
|
||
header > *, nav > *, footer > * { max-width: 100%; }
|
||
h1 { font-size: 22px !important; word-break: break-word; }
|
||
h2 { font-size: 18px !important; }
|
||
.pitch, [class*="pitch"], [class*="hero"] { word-break: break-word; overflow-wrap: anywhere; }
|
||
}
|
||
/* === OPUS RESPONSIVE FIX v2 END === */
|
||
|
||
/* V8.4 FIX OVERFLOW agent names (doctrine 14 additive) */
|
||
.dept-avatars img { color: transparent; font-size: 0 !important; line-height: 0 !important; }
|
||
.dept-avatars img::before { content: ""; display: block; width: 100%; height: 100%; background: var(--bg-3); border-radius: 50%; }
|
||
.dept-avatars { max-height: 32px; overflow: hidden; }
|
||
.dept-footer { overflow: hidden; max-height: 50px; }
|
||
.dept { overflow: hidden !important; }
|
||
|
||
</style>
|
||
<script src="/api/weval-avatar-helper.js?v=d91" defer></script>
|
||
|
||
<style id="d91-persona-style">
|
||
/* ------ D91 PERSONA AVATARS ------ */
|
||
.p-av{display:inline-flex;align-items:center;justify-content:center;border-radius:50%;
|
||
background:#ffffff0a;border:1.5px solid #6366f1;flex-shrink:0;
|
||
font-family:Apple Color Emoji,Segoe UI Emoji,Noto Color Emoji,sans-serif;line-height:1;
|
||
box-shadow:0 2px 6px #0006,inset 0 1px 0 #ffffff18}
|
||
.p-av[data-persona="master"]{background:linear-gradient(135deg,#f59e0b22,#dc262622);border-color:#f59e0b;box-shadow:0 0 10px #f59e0b44}
|
||
.p-av[data-persona="tool"]{background:#64748b15;border-color:#64748b;border-style:dashed}
|
||
.p-av[data-persona="human"]{background:#8b5cf611;border-color:#6366f1}
|
||
.dept-avatars .p-av{width:28px;height:28px;font-size:17px;margin-left:-6px;border-width:2px;border-color:var(--bg-tile,#0f1420)}
|
||
.dept-avatars .p-av:first-child{margin-left:0}
|
||
.dept-avatars .p-av:hover{transform:translateY(-2px);z-index:2;transition:all .2s}
|
||
.gap-avatar .p-av{width:100%;height:100%;font-size:22px;border:none;box-shadow:none;background:transparent}
|
||
.today-item .p-av{width:22px;height:22px;font-size:13px}
|
||
/* tooltip on hover */
|
||
.p-av{position:relative;cursor:default}
|
||
.p-av:hover::after{content:attr(data-name);position:absolute;top:100%;left:50%;transform:translateX(-50%);
|
||
background:#0a0c14ee;color:#e2e8f0;padding:3px 8px;border-radius:4px;font:600 10px Nunito,sans-serif;
|
||
white-space:nowrap;z-index:100;margin-top:4px;pointer-events:none;border:1px solid #6366f144}
|
||
</style>
|
||
<!-- WEVAL-D91-PERSONA-AVATAR -->
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
|
||
<div class="shell">
|
||
<div>
|
||
<div class="breadcrumb">
|
||
<a href="/weval-technology-platform.html">🏠 WTP</a>
|
||
<span class="sep">›</span>
|
||
<span class="current">Enterprise Complete · V73</span>
|
||
</div>
|
||
<h1 style="margin-top:4px"><span class="pulse"></span>🏢 Enterprise Complete — 20 dépts · 169 KPIs · SAP/Oracle/Sage-class</h1>
|
||
<div class="clock" id="clock">—</div>
|
||
</div>
|
||
<div class="shell-actions">
|
||
<a href="/agents-archi.html" class="btn">🤖 Agents 3D</a>
|
||
<a href="/wevia-meeting-rooms.html" class="btn">👥 Meeting Rooms</a>
|
||
<a href="/enterprise-model.html" class="btn">🏢 Model</a>
|
||
<a href="/dg-command-center.html" class="btn">🎖 DG Center</a>
|
||
<a href="/sales-hub.html" class="btn primary">🚀 Sales Hub</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="kpi-super">
|
||
<div class="ks gold"><div class="l">Départements</div><div class="v gold" id="k-depts">—</div><div class="s">macro entreprise</div></div>
|
||
<div class="ks cyan"><div class="l">KPIs tracés</div><div class="v" id="k-kpis">—</div><div class="s">all-in-one ERP</div></div>
|
||
<div class="ks purple"><div class="l">Gap agents méthode</div><div class="v" id="k-gap">—</div><div class="s">Scrum/SAFe/Agile/DevOps</div></div>
|
||
<div class="ks ok"><div class="l">Agents déployés</div><div class="v" id="k-agents">—</div><div class="s">fleet WEVAL</div></div>
|
||
<div class="ks danger"><div class="l">Integrations ready</div><div class="v" id="k-int">—</div><div class="s">ERP/CRM/SaaS/DB</div></div>
|
||
<div class="ks"><div class="l">Innovations 24h</div><div class="v" id="k-inn">—</div><div class="s">WEVL Predict</div></div>
|
||
</div>
|
||
|
||
<div class="filters">
|
||
<span class="lbl">Catégorie</span>
|
||
<button class="fb active" data-cat="all">Tous (20)</button>
|
||
<button class="fb" data-cat="finance">💰 Finance (6)</button>
|
||
<button class="fb" data-cat="supply">📦 Supply (2)</button>
|
||
<button class="fb" data-cat="mfg">🏭 Production (3)</button>
|
||
<button class="fb" data-cat="sales">💼 Sales (3)</button>
|
||
<button class="fb" data-cat="hr">👥 RH (2)</button>
|
||
<button class="fb" data-cat="it">💻 IT (2)</button>
|
||
<button class="fb" data-cat="legal">⚖️ Legal (2)</button>
|
||
</div>
|
||
|
||
<div class="today">
|
||
<div class="today-head">
|
||
<span>⚡ Créations du jour · innovations WEVAL 18 avr 2026</span>
|
||
<span id="innov-count" style="font-family:'JetBrains Mono',monospace;font-weight:700;color:var(--accent)">—</span>
|
||
</div>
|
||
<div class="today-grid" id="today-grid"><div class="loading"><div class="spinner"></div></div></div>
|
||
</div>
|
||
|
||
<div class="sec-title">
|
||
<span>📊 Les 20 départements · KPIs macro + agents unifiés + status live</span>
|
||
<span class="count" id="depts-count">—</span>
|
||
</div>
|
||
<div class="depts-grid" id="depts-grid"><div class="loading"><div class="spinner"></div></div></div>
|
||
|
||
<div class="sec-title">
|
||
<span>🎭 Gap Agents Méthode · Scrum/SAFe/Agile/DevOps/OKR — à développer Q2</span>
|
||
<span class="count" id="gap-count">—</span>
|
||
</div>
|
||
<div class="gap-grid" id="gap-grid"><div class="loading"><div class="spinner"></div></div></div>
|
||
|
||
<div class="sec-title">
|
||
<span>⚙️ Macro processes par département · base SCOR + APQC</span>
|
||
<span class="count">8 macro streams</span>
|
||
</div>
|
||
<div class="proc-wrap">
|
||
<div class="proc-grid" id="proc-grid"></div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<script>
|
||
const API_V70 = '/api/wevia-v70-enterprise-complete.php';
|
||
const API_V71 = '/api/wevia-v71-intelligence-growth.php';
|
||
const AVATAR_API = '/api/agent-avatars.json';
|
||
|
||
let DATA70 = null, DATA71 = null, AVATARS = {};
|
||
let filter = 'all';
|
||
|
||
const DEPT_META = {
|
||
finance_general: {cat:'finance', color:'var(--c-fin)'},
|
||
controlling: {cat:'finance', color:'var(--c-fin)'},
|
||
treasury: {cat:'finance', color:'var(--c-fin)'},
|
||
billing_ar: {cat:'finance', color:'var(--c-fin)'},
|
||
accounts_payable: {cat:'finance', color:'var(--c-fin)'},
|
||
tax_compliance: {cat:'finance', color:'var(--c-fin)'},
|
||
supply_chain: {cat:'supply', color:'var(--c-sup)'},
|
||
procurement: {cat:'supply', color:'var(--c-sup)'},
|
||
manufacturing: {cat:'mfg', color:'var(--c-mfg)'},
|
||
quality_qhse: {cat:'mfg', color:'var(--c-mfg)'},
|
||
rd_innovation: {cat:'mfg', color:'var(--c-mfg)'},
|
||
sales: {cat:'sales', color:'var(--c-sales)'},
|
||
marketing: {cat:'sales', color:'var(--c-sales)'},
|
||
customer_success: {cat:'sales', color:'var(--c-sales)'},
|
||
hr: {cat:'hr', color:'var(--c-hr)'},
|
||
payroll: {cat:'hr', color:'var(--c-hr)'},
|
||
dsi_it: {cat:'it', color:'var(--c-it)'},
|
||
cybersecurity: {cat:'it', color:'var(--c-it)'},
|
||
legal_compliance: {cat:'legal', color:'var(--c-legal)'},
|
||
esg: {cat:'legal', color:'var(--c-esg)'}
|
||
};
|
||
|
||
const DEPT_AGENTS = {
|
||
finance_general: ['Fast Close Orchestrator','Cash Flow Predictor AI','Budget Variance Watchdog'],
|
||
controlling: ['Budget Variance Watchdog','Forecast AI'],
|
||
treasury: ['Cash Flow Predictor AI','FX Hedger'],
|
||
billing_ar: ['Collection AI Agent','Dunning Router'],
|
||
accounts_payable: ['Invoice Auto-Match','Duplicate Payment Detector'],
|
||
tax_compliance: ['Tax Validator','Audit Trail Watcher'],
|
||
supply_chain: ['Demand Forecast Pro','Stockout Prevention','OTD Optimizer'],
|
||
procurement: ['Supplier Risk Monitor','Contract Compliance'],
|
||
manufacturing: ['OEE Live','Predictive Maintenance','Takt Time Monitor'],
|
||
quality_qhse: ['CAPA Closer','Incident Watcher'],
|
||
rd_innovation: ['Patent Scanner','PoC Tracker'],
|
||
sales: ['Pipeline Scorer','Lead Qualifier','CPQ AI'],
|
||
marketing: ['Content Generator','CAC Optimizer'],
|
||
customer_success: ['Churn Predictor','NPS Analyzer'],
|
||
hr: ['Talent Scout','Attrition Predictor','Skills Matcher'],
|
||
payroll: ['Payroll Accuracy AI','Compliance Checker'],
|
||
dsi_it: ['DevOps','AutoFix','Fiability','Monitor'],
|
||
cybersecurity: ['Security','Fraud Detection Agent','MFA Enforcer'],
|
||
legal_compliance: ['Contract Watcher','GDPR Auditor'],
|
||
esg: ['Carbon Tracker','Sustainability Reporter']
|
||
};
|
||
|
||
const MACRO_PROCESSES = [
|
||
{name:'Record-to-Report (R2R)', steps:'Journal → Reconciliation → Close → Report', depts:['finance_general','controlling']},
|
||
{name:'Order-to-Cash (O2C)', steps:'Quote → Order → Ship → Invoice → Collect', depts:['sales','billing_ar']},
|
||
{name:'Procure-to-Pay (P2P)', steps:'Requisition → PO → Receipt → Invoice → Pay', depts:['procurement','accounts_payable']},
|
||
{name:'Plan-to-Produce', steps:'Demand → MRP → Production → QC → Stock', depts:['manufacturing','quality_qhse']},
|
||
{name:'Hire-to-Retire (H2R)', steps:'Recruit → Onboard → Manage → Separate', depts:['hr','payroll']},
|
||
{name:'Market-to-Lead (M2L)', steps:'Campaign → Traffic → MQL → SQL → Handoff', depts:['marketing','sales']},
|
||
{name:'Design-to-Deploy (D2D)', steps:'Ideate → Spec → Build → Test → Release', depts:['rd_innovation','dsi_it']},
|
||
{name:'Risk-to-Remediate', steps:'Identify → Assess → Mitigate → Monitor', depts:['legal_compliance','cybersecurity']}
|
||
];
|
||
|
||
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 avatarUrl(name) {
|
||
// D91 deprecated — kept for backward compat; use avatarPill() instead
|
||
if (AVATARS && AVATARS[name]) return AVATARS[name];
|
||
return 'https://api.dicebear.com/9.x/adventurer/svg?seed=' + encodeURIComponent(name || 'default');
|
||
}
|
||
function avatarPill(name, size){
|
||
size = size || 26;
|
||
// Prefer v2 registry via WevalAvatar (persona emojis)
|
||
if (window.WevalAvatar && WevalAvatar.isReady && WevalAvatar.isReady()){
|
||
const e = WevalAvatar.get(name);
|
||
const bg = (e.color||'#6366f1')+'22';
|
||
return '<span class="p-av" data-persona="'+(e.persona||'human')+'" data-name="'+esc(name)+'" '+
|
||
'style="width:'+size+'px;height:'+size+'px;font-size:'+Math.round(size*0.62)+'px;border-color:'+(e.color||'#6366f1')+';background:'+bg+'">'+e.emoji+'</span>';
|
||
}
|
||
// fallback: img dicebear
|
||
return '<img src="'+avatarUrl(name)+'" alt="" title="'+esc(name)+'" data-agent="'+esc(name)+'" style="width:'+size+'px;height:'+size+'px;border-radius:50%;vertical-align:middle" onerror="this.style.display=\'none\'">';
|
||
}
|
||
function esc(s){ return String(s||'').replace(/[&<>"]/g,function(c){return{'&':'&','<':'<','>':'>','"':'"'}[c];}); }
|
||
|
||
|
||
async function load() {
|
||
try {
|
||
const [av, d70, d71] = await Promise.all([
|
||
fetch(AVATAR_API+'?t='+Date.now()).then(r=>r.json()).catch(()=>({})),
|
||
fetch(API_V70+'?t='+Date.now()).then(r=>r.json()).catch(()=>null),
|
||
fetch(API_V71+'?t='+Date.now()).then(r=>r.json()).catch(()=>null)
|
||
]);
|
||
AVATARS = av || {};
|
||
DATA70 = d70;
|
||
DATA71 = d71;
|
||
render();
|
||
} catch(e){console.error('load err',e);}
|
||
}
|
||
|
||
function render() {
|
||
if (!DATA70) return;
|
||
const s70 = DATA70.summary;
|
||
document.getElementById('k-depts').textContent = s70.departments;
|
||
document.getElementById('k-kpis').textContent = s70.kpis_total;
|
||
document.getElementById('k-gap').textContent = DATA71 ? DATA71.summary.agility_agents_gap : '—';
|
||
// TRUTH SYNC (Opus Yacine 19avr) · fetch dynamically
|
||
document.getElementById('k-agents').textContent = 950; // fallback
|
||
fetch('/api/source-of-truth.json?t=' + Date.now(), {cache:'no-store'})
|
||
.then(r => r.json())
|
||
.then(d => {
|
||
var n = d.agents_count || d.agents_total || 950;
|
||
var el = document.getElementById('k-agents');
|
||
if (el) el.textContent = n;
|
||
})
|
||
.catch(e => {});
|
||
document.getElementById('k-int').textContent = s70.integrations_total;
|
||
document.getElementById('k-inn').textContent = DATA71 ? DATA71.summary.innovations_last_24h : '—';
|
||
|
||
// Today
|
||
if (DATA71) {
|
||
const innovs = DATA71.wevl_predict_innovations.innovations.filter(i => i.date === '2026-04-18');
|
||
document.getElementById('innov-count').textContent = innovs.length + ' créations aujourd\'hui';
|
||
document.getElementById('today-grid').innerHTML = innovs.map(i => `
|
||
<a href="${i.url}" class="today-item" target="_blank">
|
||
<div class="ver">${(i.type||'').toUpperCase()} · ${'★'.repeat(i.novelty||3)}</div>
|
||
<div class="name">${i.name}</div>
|
||
<div class="desc">${i.description||''}</div>
|
||
</a>
|
||
`).join('');
|
||
}
|
||
|
||
// Depts
|
||
const depts = DATA70.enterprise_departments;
|
||
const entries = Object.entries(depts);
|
||
const filtered = filter === 'all' ? entries : entries.filter(([k,v]) => (DEPT_META[k]||{}).cat === filter);
|
||
document.getElementById('depts-count').textContent = filtered.length + ' affichés / ' + entries.length;
|
||
|
||
document.getElementById('depts-grid').innerHTML = filtered.map(([key, d]) => {
|
||
const meta = DEPT_META[key] || {cat:'other', color:'var(--accent)'};
|
||
const agents = (DEPT_AGENTS[key] || []).slice(0,5);
|
||
const critCount = (d.kpis||[]).filter(k => k.s === 'critical').length;
|
||
const warnCount = (d.kpis||[]).filter(k => k.s === 'warn').length;
|
||
const status = critCount > 2 ? 'critical' : (warnCount > (d.kpis||[]).length/2 ? 'warn' : 'ok');
|
||
const topKpis = (d.kpis||[]).slice(0,4);
|
||
return `<div class="dept" style="--dc:${meta.color}" onclick="window.open('/dg-command-center.html','_blank')">
|
||
<div class="dept-head">
|
||
<span class="dept-icon">${d.icon||'📊'}</span>
|
||
<div class="dept-meta">
|
||
<div class="dept-name">${d.label}</div>
|
||
<div class="dept-agents-info">${(d.kpis||[]).length} KPIs · ${agents.length} agents · ${(d.integrations||[]).length} ERPs</div>
|
||
</div>
|
||
<span class="dept-status ${status}">${status}</span>
|
||
</div>
|
||
<div class="dept-kpis">
|
||
${topKpis.map(k => `<div class="kpi-row">
|
||
<div class="kpi-name" title="${k.k}">${k.k}</div>
|
||
<div class="kpi-val">${k.v}${k.u||''}</div>
|
||
<div class="kpi-dot ${k.s||'ok'}"></div>
|
||
</div>`).join('')}
|
||
</div>
|
||
<div class="dept-footer">
|
||
<div class="dept-avatars">
|
||
${agents.slice(0,4).map(a => avatarPill(a,28)).join('')}
|
||
${agents.length > 4 ? `<span class="more">+${agents.length-4}</span>` : ''}
|
||
</div>
|
||
<span class="dept-cta">→ pilotage</span>
|
||
</div>
|
||
</div>`;
|
||
}).join('');
|
||
|
||
// Gap agents
|
||
if (DATA71) {
|
||
const gaps = DATA71.agility_agents_gap.agents || [];
|
||
document.getElementById('gap-count').textContent = gaps.length + ' agents · ' + DATA71.agility_agents_gap.total_fte_saved_year + ' FTE savings/an';
|
||
document.getElementById('gap-grid').innerHTML = gaps.map(g => `
|
||
<div class="gap ${g.priority||'medium'}">
|
||
<div class="gap-head">
|
||
<div class="gap-avatar">${avatarPill(g.name, 36)}</div>
|
||
<div style="flex:1">
|
||
<div class="gap-name">${g.name}</div>
|
||
<span class="gap-fw">${g.framework||''}</span>
|
||
</div>
|
||
</div>
|
||
<div class="gap-role">${g.role||''}</div>
|
||
<div class="gap-foot">
|
||
<span class="gap-save">💰 ${g.savings_fte_year||0} FTE/an</span>
|
||
<span class="gap-status ${g.status||'to_build'}">${(g.status||'to_build').replace('_',' ')}</span>
|
||
</div>
|
||
</div>
|
||
`).join('');
|
||
}
|
||
|
||
// Macro processes
|
||
document.getElementById('proc-grid').innerHTML = MACRO_PROCESSES.map(p => {
|
||
const deptLabels = p.depts.map(d => (depts[d]||{}).label || d).join(' + ');
|
||
return `<div class="proc">
|
||
<div class="proc-name">${p.name}</div>
|
||
<div class="proc-steps">${p.steps}</div>
|
||
<div class="proc-depts">${deptLabels}</div>
|
||
</div>`;
|
||
}).join('');
|
||
}
|
||
|
||
document.querySelectorAll('.fb').forEach(b => b.onclick = e => {
|
||
filter = e.target.dataset.cat;
|
||
document.querySelectorAll('.fb').forEach(x => x.classList.toggle('active', x.dataset.cat === filter));
|
||
render();
|
||
});
|
||
|
||
load();
|
||
setInterval(load, 60000);
|
||
</script>
|
||
|
||
<script id="d91-rerender">
|
||
(function(){
|
||
const wait = setInterval(function(){
|
||
if (window.WevalAvatar && WevalAvatar.isReady && WevalAvatar.isReady()){
|
||
clearInterval(wait);
|
||
if (typeof render === 'function') render();
|
||
}
|
||
}, 120);
|
||
setTimeout(function(){clearInterval(wait);},8000);
|
||
})();
|
||
</script>
|
||
<script>
|
||
/* V75 AVATAR UNIFIER — Meeting-rooms emoji style (Opus 19avr) */
|
||
(function() {
|
||
if (window.__WEVAL_AVATAR_V75) return;
|
||
window.__WEVAL_AVATAR_V75 = true;
|
||
const REG_URL = '/api/agent-avatars-v75.json';
|
||
const SVG_EP = '/api/agent-avatar-svg.php';
|
||
function emojiSVGUrl(name, emoji) {
|
||
return SVG_EP + '?n=' + encodeURIComponent(name) + '&e=' + encodeURIComponent(emoji);
|
||
}
|
||
fetch(REG_URL + '?t=' + Date.now()).then(r => r.json()).then(REG => {
|
||
function getAvatarUrl(name) {
|
||
const rec = REG[name];
|
||
if (!rec) return null;
|
||
if (typeof rec === 'object' && rec.svg) return rec.svg;
|
||
if (typeof rec === 'object' && rec.emoji) return emojiSVGUrl(name, rec.emoji);
|
||
return typeof rec === 'string' ? rec : null;
|
||
}
|
||
function findCI(key) {
|
||
const lower = key.toLowerCase();
|
||
for (const k of Object.keys(REG)) if (k.toLowerCase() === lower) return k;
|
||
return null;
|
||
}
|
||
function apply() {
|
||
document.querySelectorAll('img').forEach(img => {
|
||
const key = img.alt || img.dataset.agent || img.dataset.name || img.title || '';
|
||
if (!key) return;
|
||
let url = getAvatarUrl(key);
|
||
if (!url) { const alt = findCI(key); if (alt) url = getAvatarUrl(alt); }
|
||
if (url && img.src !== url && !img.src.endsWith(url)) {
|
||
img.src = url;
|
||
img.setAttribute('data-weval-v75', '1');
|
||
}
|
||
});
|
||
document.querySelectorAll('[data-agent]:not([data-weval-v75-applied])').forEach(el => {
|
||
const name = el.dataset.agent;
|
||
const url = getAvatarUrl(name);
|
||
if (!url) return;
|
||
const img = document.createElement('img');
|
||
img.src = url; img.alt = name; img.title = name;
|
||
img.className = 'v75-avatar';
|
||
img.style.cssText = 'width:32px;height:32px;border-radius:50%;object-fit:cover;vertical-align:middle;background:transparent';
|
||
el.setAttribute('data-weval-v75-applied', '1');
|
||
el.prepend(img);
|
||
});
|
||
}
|
||
apply();
|
||
setTimeout(apply, 400); setTimeout(apply, 1200); setTimeout(apply, 3000);
|
||
const mo = new MutationObserver(() => apply());
|
||
mo.observe(document.body, {childList: true, subtree: true});
|
||
setTimeout(() => mo.disconnect(), 20000);
|
||
console.log('[V75 AvatarUnifier] applied from', Object.keys(REG).length, 'agents');
|
||
}).catch(e => console.warn('[V75] fetch failed', e));
|
||
})();
|
||
</script>
|
||
|
||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||
<script>
|
||
(function(){
|
||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||
var d = document;
|
||
var m = d.createElement('div');
|
||
m.id = 'opus-udrill';
|
||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||
var inner = d.createElement('div');
|
||
inner.id = 'opus-udrill-in';
|
||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||
m.appendChild(inner);
|
||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||
(d.body || d.documentElement).appendChild(m);
|
||
function openCard(card) {
|
||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||
inner.innerHTML = html;
|
||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||
m.style.display = 'flex';
|
||
}
|
||
function wire(root) {
|
||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||
var cards = root.querySelectorAll(sels);
|
||
for (var i = 0; i < cards.length; i++) {
|
||
var c = cards[i];
|
||
if (c.__opusWired) continue;
|
||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||
var r = c.getBoundingClientRect();
|
||
if (r.width < 60 || r.height < 40) continue;
|
||
c.__opusWired = true;
|
||
c.style.cursor = 'pointer';
|
||
c.setAttribute('role','button');
|
||
c.setAttribute('tabindex','0');
|
||
c.addEventListener('click', function(ev){
|
||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||
if (ev.target.closest('a,button,input,select')) return;
|
||
ev.preventDefault(); ev.stopPropagation();
|
||
openCard(this);
|
||
});
|
||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||
}
|
||
}
|
||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||
else initRun();
|
||
var mo = new MutationObserver(function(muts){
|
||
var newCard = false;
|
||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||
if (newCard) initRun();
|
||
});
|
||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||
})();
|
||
</script>
|
||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||
|
||
|
||
<script src="/api/a11y-auto-enhancer.js" defer></script>
|
||
</body>
|
||
</html>
|
||
|