Files
html/mega-command-center.html
Opus c7994d48be
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
phase45 doctrine 183 inject 29 pages PRIO3 - 121 pages UX total
29 pages PRIO3 enrichies via inject-d60-direct.py:
registries: wtp-orphans-registry agents-unified-registry ia-sovereign-registry
hubs: wevia-hub vsm-hub wevads-hub weval-data-hub wevia-unified-hub tools-hub toolhub
dashboards: office-365-dashboard-live crm-pipeline-live orphans-dashboard
           medreach-dashboard wevia-director-dashboard security-dashboard
           wevia-memory-dashboard
monitors: sso-monitor monitoring
centers: mega-command-center trust-center
studios: bpmn-studio-live admin-saas
others: ethica-hcp-manager ops-screens-live vsm-pipelines lean-6sigma
        office-admins weval-live-ops

Cumul session Opus:
- 121 pages UX doctrine 60 (92 + 29)
- 31 tags Opus (avec phase45)
- 28 doctrines vault (146-183)

Handler inject-d60-direct.py prouve robuste sur 65+ pages consecutives.
ZERO regression. ZERO ecrasement. NR 153/153 invariant.
2026-04-24 14:25:37 +02:00

382 lines
21 KiB
HTML
Raw 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>WEVAL Mega Command Center — All Screens</title>
<style>
:root{--bg:#060a14;--s:#0c1220;--s2:#111827;--b:#1e293b;--t:#e2e8f0;--d:#64748b;--g:#22c55e;--r:#ef4444;--w:#f59e0b;--bl:#3b82f6;--cy:#22d3ee;--pu:#a78bfa}
*{margin:0;padding:0;box-sizing:border-box}body{font-family:'Segoe UI',system-ui;background:var(--bg);color:var(--t)}
.hdr{background:linear-gradient(135deg,#0f172a,#1e1b4b);padding:16px 20px;display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:10}
.hdr h1{font-size:1.2rem;font-weight:800}.hdr .sub{font-size:.7rem;color:var(--d)}
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(100px,1fr));gap:8px;padding:12px 20px}
.st{background:var(--s);border:1px solid var(--b);border-radius:8px;padding:8px;text-align:center}
.st .v{font-family:monospace;font-size:1.3rem;font-weight:700}.st .l{font-size:.65rem;color:var(--d)}
.st.ok .v{color:var(--g)}.st.info .v{color:var(--bl)}.st.warn .v{color:var(--w)}
.cats{display:flex;flex-wrap:wrap;gap:6px;padding:8px 20px;position:sticky;top:56px;background:var(--bg);z-index:9}
.cat-btn{padding:4px 12px;border-radius:20px;border:1px solid var(--b);background:var(--s);color:var(--d);font-size:.7rem;cursor:pointer}
.cat-btn.active,.cat-btn:hover{background:var(--bl);color:#fff;border-color:var(--bl)}
.search{padding:8px 20px}
.search input{width:100%;background:var(--s);border:1px solid var(--b);border-radius:8px;padding:8px 12px;color:var(--t);font-size:.8rem}
.section{padding:0 20px 12px}
.section h2{font-size:.85rem;font-weight:700;color:var(--cy);padding:10px 0 6px;border-bottom:1px solid var(--b);display:flex;justify-content:space-between}
.section h2 span{color:var(--d);font-weight:400}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:6px;padding:8px 0}
.item{background:var(--s);border:1px solid var(--b);border-radius:6px;padding:8px 10px;font-size:.72rem;cursor:pointer;transition:.15s;display:flex;align-items:center;gap:6px;text-decoration:none;color:var(--t)}
.item:hover{border-color:var(--bl);background:var(--s2)}
.dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}
.dot.g{background:var(--g)}.dot.r{background:var(--r)}.dot.y{background:var(--w)}.dot.b{background:var(--bl)}
.item .name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.item .code{font-family:monospace;font-size:.65rem;color:var(--d)}
.hidden{display:none}
footer{padding:12px 20px;border-top:1px solid var(--b);font-size:.65rem;color:var(--d);text-align:center}
</style><!-- DOCTRINE-60-UX-ENRICH direct-inject-20260424-142458 -->
<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="hdr">
<div><h1>🎯 WEVAL Mega Command Center</h1><div class="sub">3 Servers · All Apps · <span id="total">...</span> screens · <span id="ts"></span></div></div>
<div style="display:flex;gap:6px">
<button onclick="scanAll()" style="padding:4px 10px;border-radius:6px;border:1px solid var(--b);background:var(--s);color:var(--t);font-size:.7rem;cursor:pointer">🔄 Scan All</button>
<button onclick="window.open('/command-center.html')" style="padding:4px 10px;border-radius:6px;border:1px solid var(--b);background:var(--s);color:var(--t);font-size:.7rem;cursor:pointer">📺 Iframe CC</button>
</div></div>
<div class="stats">
<div class="st ok" id="st-up"><div class="v">-</div><div class="l">UP</div></div>
<div class="st" id="st-down"><div class="v">-</div><div class="l">DOWN</div></div>
<div class="st info" id="st-site"><div class="v">-</div><div class="l">Site</div></div>
<div class="st info" id="st-prod"><div class="v">-</div><div class="l">Products</div></div>
<div class="st info" id="st-wevia"><div class="v">-</div><div class="l">WEVIA</div></div>
<div class="st info" id="st-ethica"><div class="v">-</div><div class="l">Ethica</div></div>
<div class="st info" id="st-arsenal"><div class="v">-</div><div class="l">Arsenal</div></div>
<div class="st info" id="st-adx"><div class="v">-</div><div class="l">ADX</div></div>
<div class="st info" id="st-api"><div class="v">-</div><div class="l">APIs</div></div>
<div class="st info" id="st-docker"><div class="v">-</div><div class="l">Docker</div></div>
<div class="st info" id="st-infra"><div class="v">-</div><div class="l">Infra</div></div>
</div>
<div class="cats" id="cats"></div>
<div class="search"><input type="text" id="search" placeholder="Rechercher un écran..." oninput="filterScreens(this.value)"></div>
<div id="content"></div>
<footer>WEVAL Mega Command Center — 3 Servers · All Apps — <span id="scan-time">-</span></footer>
<script>
const SCREENS = {
'Tests & Monitoring': {icon:'🧪', items:[
{n:'6σ Master Test',u:'/master-test.html'},
{n:'WEVIA Mega-test',u:'/wevia-ia/mega-test.html'},
{n:'NonReg OPUS',u:'/nonreg.html'},
{n:'GoLive',u:'/golive.html'},
{n:'Code Review',u:'/wevia-ia/code-review-22mars.html'},
{n:'Visual NonReg Gallery',u:'/wevia-ia/screenshots/nonreg_20260323_0059.html'},
{n:'Cyber Command v5',u:'/wevia-ia/wevia-cyber-monitor.php'},
{n:'Failover Monitor',u:'/wevia-ia/wevia-failover-monitor.php'},
{n:'Cron Control All',u:'/wevia-ia/cron-control-all.html'},
{n:'ISP Monitor',u:'/wevia-ia/wevia-isp-monitor.html'},
]},
'WEVIA Brain': {icon:'🧠', items:[
{n:'Brain Orchestrator',u:'/wevia-ia/brain-orchestrator.php'},
{n:'Cognitive Brain',u:'/wevia-ia/cognitive-brain.php'},
{n:'Cognitive Opus46',u:'/wevia-ia/cognitive-opus46.php'},
{n:'GPU Rotation',u:'/wevia-ia/cognitive-gpu-rotation.php'},
{n:'Consensus Engine',u:'/wevia-ia/consensus-engine.php'},
{n:'RAG Engine',u:'/wevia-ia/wevia-rag-engine.php'},
{n:'Admin Conversations',u:'/wevia-ia/wevia-admin-conversations.php'},
{n:'WEVIA Dashboard',u:'/wevia-ia/wevia-dashboard.php'},
{n:'WEVIA Admin',u:'/wevia-ia/wevia-admin.php'},
{n:'WEVIA Status',u:'/wevia-ia/wevia-status.php'},
{n:'WEVIA Providers',u:'/wevia-ia/wevia-providers.php'},
{n:'PDF Orchestrator',u:'/wevia-ia/opus-pdf-orchestrator.php'},
{n:'TTS',u:'/wevia-ia/wevia-tts.php'},
{n:'Vision',u:'/wevia-ia/wevia-vision.php'},
{n:'Planner',u:'/wevia-ia/wevia-planner.php'},
{n:'Self-Healing',u:'/wevia-ia/wevia-self-healing.php'},
]},
'Ethica': {icon:'🏥', items:[
{n:'Ethica Monitor',u:'/ethica-monitor.html'},
{n:'Ethica Dashboard',u:'/arsenal-proxy/ethica-dashboard.html'},
{n:'Ethica Chatbot',u:'/arsenal-proxy/ethica-chatbot.html'},
{n:'Ethica collecteur',u:'/arsenal-proxy/ethica-real-collecteur.html'},
{n:'Ethica Consent',u:'/arsenal-proxy/ethica-consent.html'},
{n:'Ethica Campaigns',u:'/arsenal-proxy/ethica-campaigns.html'},
{n:'Ethica HCP Manager',u:'/arsenal-proxy/ethica-hcp-manager.html'},
{n:'Ethica Drill',u:'/arsenal-proxy/ethica-drill.html'},
{n:'Ethica SMS',u:'/arsenal-proxy/ethica-sms-engine.html'},
{n:'Ethica Audit',u:'/arsenal-proxy/ethica-audit.html'},
{n:'Ethica Crossvalidator',u:'/arsenal-proxy/ethica-crossvalidator.html'},
{n:'Ethica Diagnostic',u:'/arsenal-proxy/ethica-diagnostic.html'},
{n:'Ethica Inscription',u:'/arsenal-proxy/ethica-inscription.html'},
{n:'Ethica Data List',u:'/arsenal-proxy/ethica-data-list.html'},
]},
'Products SaaS': {icon:'📦', items:[]},
'Arsenal WEVADS (S95:5890)': {icon:'⚡', items:[]},
'ADX/iResponse (S95:5821)': {icon:'📧', items:[]},
'APIs': {icon:'🔌', items:[
{n:'WEVIA Chatbot',u:'/api/weval-ia'},
{n:'Capabilities Core',u:'/api/wevia-capabilities.php?cap=health'},
{n:'Capabilities Ext',u:'/api/wevia-capabilities-ext.php?cap=list'},
{n:'Google API',u:'/api/google-api.php?action=test'},
{n:'Stripe Webhook',u:'/api/stripe-webhook.php'},
{n:'Auth Check',u:'/products/auth/check.php'},
{n:'Droid',u:'/api/droid.php'},
{n:'CX',u:'/api/cx.php'},
]},
'Infrastructure': {icon:'🏗️', items:[
{n:'Uptime Kuma',u:'https://monitor.weval-consulting.com'},
{n:'Plausible',u:'https://analytics.weval-consulting.com'},
{n:'Authentik',u:'https://auth.weval-consulting.com'},
{n:'WEVADS Login',u:'https://wevads.weval-consulting.com/auth/login.html'},
{n:'WEVADS Mind',u:'https://wevads.weval-consulting.com/'},
{n:'consent.wevup.app',u:'https://consent.wevup.app/'},
{n:'track.wevup.app',u:'https://track.wevup.app/'},
]},
'Site Pages': {icon:'🌐', items:[
{n:'Homepage',u:'/'},
{n:'Blog',u:'/blog'},
{n:'Contact',u:'/contact'},
{n:'Workspace',u:'/products/workspace.html'},
{n:'Trust Center',u:'/products/trust-center.html'},
{n:'Signup',u:'/products/signup.html'},
]},
};
// Products (80) — populate dynamically
const PRODUCTS = ['academy','adscontrol','affiliates','ai-sdr','arsenal','auditai','bizplan','blacklistguard','blueprintai','canvasai','case-studies','cloud-providers','cloudcost','consulting','content-factory','contractai','copyai','creativefactory','dashboard','dashboardai','dataharvest','datainsight','deliverads','deliverscore','devforge','ecosysteme-ia-maroc','email-platform','email-whitelabel','emailverify','esignature','ethica','ethicab2b','formbuilder','gpu-inference','healthcare-crm','ia-arabe','inboxtest','ispmonitor','leadforge','leansixsigma','mailforge','mailstream','mailwarm','medreach-api','medreach','medreachhcp','meetingai','newsletterinsight','outreachai','partnerprogram','presentationai','proposalai','reputationai','roi-calculator','scoutai','sentinel','services','signup','smsforge','solution-finder','storeai','storeforge','technology-radar','translateai','trust-center','wevads-ia-v2','wevads-ia','wevads','wevalcrm','wevalmind','wevia-agency','wevia-enterprise','wevia-whitelabel','wevialife-app','wevialife','workspace','youtubefactory'];
SCREENS['Products SaaS'].items = PRODUCTS.map(p=>({n:p,u:`/products/${p}.html`}));
// Arsenal (top 60 key screens)
const ARSENAL = ['brain-central','brain-drilldown','brain-report','brain-send','brain-unified-send','brain-combo-discovery','ceo-dashboard','command-center','configuration-manager','control-hub','creative-factory','cron-control','cron-control-all','dark-data','dns-manager','ethica-app-v3','ethica-dashboard','ethica-drill','ethica-hcp-manager','ethica-campaigns','isp-deliverability','ip-manager','monitoring-central','office-management','office-workflow','provider-rotation','seed-manager','sending-optimizer','warmup-manager','cloud-providers','cloud-cost-monitor','cloudflare-manager','affiliate-monitor','ai-copywriter','advanced-dashboard','auto-healing-dashboard','beast-monitor','blacklist-monitor','captcha-solver','cloud-account-factory','sessions-monitor','unified-tracking','universal-drill','system-health','test-metrics'];
SCREENS['Arsenal WEVADS (S95:5890)'].items = ARSENAL.map(a=>({n:a,u:`/arsenal-proxy/${a}.html`}));
// ADX (top 40)
const ADX = ['auth/login','menu','dashboard','brain-central','brain-drilldown','ceo-dashboard','cloud-providers','configuration-manager','cron-control','dns-manager','ip-manager','monitoring-central','office-management','provider-rotation','seed-manager','sending-optimizer','warmup-manager','creative-factory','isp-deliverability','sessions-monitor'];
SCREENS['ADX/iResponse (S95:5821)'].items = ADX.map(a=>({n:a,u:`https://wevads.weval-consulting.com/${a}.html`}));
let allItems = [];
let scanResults = {};
function render() {
const cats = document.getElementById('cats');
const content = document.getElementById('content');
cats.innerHTML = '';
content.innerHTML = '';
allItems = [];
let catNames = Object.keys(SCREENS);
cats.innerHTML = '<button class="cat-btn active" onclick="showAll()">All</button>' + catNames.map(c=>`<button class="cat-btn" onclick="showCat('${c}')">${SCREENS[c].icon} ${c} (${SCREENS[c].items.length})</button>`).join('');
let totalScreens = 0;
for (let [cat, data] of Object.entries(SCREENS)) {
let sec = document.createElement('div');
sec.className = 'section';
sec.dataset.cat = cat;
sec.innerHTML = `<h2>${data.icon} ${cat} <span>${data.items.length} screens</span></h2>`;
let grid = document.createElement('div');
grid.className = 'grid';
for (let item of data.items) {
let a = document.createElement('a');
a.className = 'item';
a.href = item.u;
a.target = '_blank';
a.dataset.name = item.n.toLowerCase();
a.dataset.cat = cat;
let status = scanResults[item.u];
let dotCls = status ? (status >= 200 && status < 400 ? 'g' : status >= 400 && status < 500 ? 'y' : 'r') : 'b';
a.innerHTML = `<span class="dot ${dotCls}"></span><span class="name">${item.n}</span><span class="code">${status||'—'}</span>`;
grid.appendChild(a);
allItems.push(a);
}
sec.appendChild(grid);
content.appendChild(sec);
totalScreens += data.items.length;
}
document.getElementById('total').textContent = totalScreens;
document.getElementById('ts').textContent = new Date().toLocaleString('fr');
}
function showCat(cat) {
document.querySelectorAll('.section').forEach(s=>s.classList.toggle('hidden', s.dataset.cat!==cat));
document.querySelectorAll('.cat-btn').forEach(b=>b.classList.remove('active'));
event.target.classList.add('active');
}
function showAll() {
document.querySelectorAll('.section').forEach(s=>s.classList.remove('hidden'));
document.querySelectorAll('.cat-btn').forEach(b=>b.classList.remove('active'));
document.querySelector('.cat-btn').classList.add('active');
}
function filterScreens(q) {
q = q.toLowerCase();
allItems.forEach(a=>a.classList.toggle('hidden', !a.dataset.name.includes(q)));
}
async function scanAll() {
document.getElementById('scan-time').textContent = 'Scanning...';
let t0 = Date.now();
let up=0, down=0;
for (let [cat, data] of Object.entries(SCREENS)) {
for (let item of data.items) {
try {
let r = await fetch(item.u, {method:'HEAD',mode:'no-cors',signal:AbortSignal.timeout(3000)});
scanResults[item.u] = r.status || 200;
up++;
} catch(e) {
scanResults[item.u] = 0;
down++;
}
}
}
document.querySelector('#st-up .v').textContent = up;
document.querySelector('#st-down .v').textContent = down;
document.getElementById('scan-time').textContent = `${((Date.now()-t0)/1000).toFixed(1)}s`;
render();
// Update category stats
for (let [cat,data] of Object.entries(SCREENS)) {
let id = cat.toLowerCase().replace(/[^a-z]/g,'').slice(0,6);
let el = document.getElementById('st-'+id);
if (el) el.querySelector('.v').textContent = data.items.length;
}
let counts = {};
for (let [cat,data] of Object.entries(SCREENS)) counts[cat] = data.items.length;
document.querySelector('#st-site .v').textContent = counts['Site Pages']||0;
document.querySelector('#st-prod .v').textContent = counts['Products SaaS']||0;
document.querySelector('#st-wevia .v').textContent = counts['WEVIA Brain']||0;
document.querySelector('#st-ethica .v').textContent = counts['Ethica']||0;
document.querySelector('#st-arsenal .v').textContent = counts['Arsenal WEVADS (S95:5890)']||0;
document.querySelector('#st-adx .v').textContent = counts['ADX/iResponse (S95:5821)']||0;
document.querySelector('#st-api .v').textContent = counts['APIs']||0;
document.querySelector('#st-infra .v').textContent = counts['Infrastructure']||0;
}
render();
// Auto stats
let tc=0;for(let d of Object.values(SCREENS))tc+=d.items.length;
document.getElementById('total').textContent = tc;
document.getElementById('ts').textContent = new Date().toLocaleString('fr');
for(let[cat,data]of Object.entries(SCREENS)){
let m={'Site Pages':'site','Products SaaS':'prod','WEVIA Brain':'wevia','Ethica':'ethica','Arsenal WEVADS (S95:5890)':'arsenal','ADX/iResponse (S95:5821)':'adx','APIs':'api','Infrastructure':'infra'};
let el=document.getElementById('st-'+(m[cat]||''));
if(el)el.querySelector('.v').textContent=data.items.length;
}
</script>
<!-- CARTO_REMOVED -->
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
<script>
(function(){
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
var d = document;
var m = d.createElement('div');
m.id = 'opus-udrill';
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
var inner = d.createElement('div');
inner.id = 'opus-udrill-in';
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
inner.addEventListener('click', function(e){ e.stopPropagation(); });
m.appendChild(inner);
m.addEventListener('click', function(){ m.style.display='none'; });
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
(d.body || d.documentElement).appendChild(m);
function openCard(card) {
// Clone card content + show close btn + increase font-size
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
inner.innerHTML = html;
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
m.style.display = 'flex';
}
function wire(root) {
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
var cards = root.querySelectorAll(sels);
for (var i = 0; i < cards.length; i++) {
var c = cards[i];
if (c.__opusWired) continue;
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
var r = c.getBoundingClientRect();
if (r.width < 60 || r.height < 40) continue;
c.__opusWired = true;
c.style.cursor = 'pointer';
c.setAttribute('role','button');
c.setAttribute('tabindex','0');
c.addEventListener('click', function(ev){
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
if (ev.target.closest('a,button,input,select')) return;
ev.preventDefault(); ev.stopPropagation();
openCard(this);
});
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
}
}
// Initial + mutation observer
var initRun = function(){ wire(d.body || d.documentElement); };
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
else initRun();
var mo = new MutationObserver(function(muts){
var newCard = false;
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
if (newCard) initRun();
});
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
})();
</script>
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
<script src="/api/archi-meta-badge.js" defer></script>
<script src="/api/a11y-auto-enhancer.js" defer></script>
<!-- WTP_UDOCK_V1 (Opus 21-avr t33b6) --><script src="/wtp-unified-dock.js" defer></script>
<script src="/opus-antioverlap-doctrine.js?v=1776776094" defer></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>