Files
html/agents-hd.html
2026-04-21 12:50:03 +02:00

488 lines
21 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WEVAL — Agents Command</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Rajdhani:wght@400;600;700&family=JetBrains+Mono:wght@400;700&display=swap');
*{margin:0;padding:0;box-sizing:border-box}
body{background:#020408;overflow:hidden;cursor:crosshair}
canvas{display:block}
#tip{position:fixed;pointer-events:none;display:none;z-index:99}
#tip .box{background:rgba(4,8,20,.92);border:1px solid rgba(6,182,212,.4);border-radius:10px;padding:14px 18px;backdrop-filter:blur(12px);min-width:240px;box-shadow:0 0 40px rgba(6,182,212,.12),inset 0 0 30px rgba(6,182,212,.03)}
#tip .nm{font-family:'Orbitron',sans-serif;font-size:1rem;color:#fff;font-weight:700;letter-spacing:1px}
#tip .tp{font-family:'Rajdhani',sans-serif;font-size:.72rem;text-transform:uppercase;letter-spacing:2px;margin:4px 0 8px;padding:2px 8px;display:inline-block;border-radius:4px}
#tip .ds{font-family:'Rajdhani',sans-serif;color:#8899b8;font-size:.85rem;line-height:1.4;margin-bottom:6px}
#tip .pr{font-family:'JetBrains Mono',monospace;font-size:.72rem;color:#f59e0b;border-top:1px solid rgba(255,255,255,.06);padding-top:6px;margin-top:4px}
#tip .bar{height:3px;border-radius:2px;margin-top:8px;background:#111;overflow:hidden}
#tip .bar i{display:block;height:100%;border-radius:2px;animation:pulse 1.5s ease infinite}
@keyframes pulse{0%,100%{opacity:.7}50%{opacity:1}}
#hud{position:fixed;top:0;left:0;right:0;padding:14px 20px;display:flex;justify-content:space-between;align-items:center;z-index:10;background:linear-gradient(180deg,rgba(2,4,8,.95) 0%,transparent 100%);pointer-events:none}
#hud *{pointer-events:auto}
.logo{font-family:'Orbitron',sans-serif;font-size:1.1rem;font-weight:900;letter-spacing:3px;color:#06b6d4;text-shadow:0 0 20px rgba(6,182,212,.4)}
.logo span{color:#a855f7}
.hud-stats{display:flex;gap:20px}
.hs{text-align:center}
.hs-v{font-family:'Orbitron',sans-serif;font-size:1.4rem;font-weight:700;background:linear-gradient(135deg,#06b6d4,#a855f7);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
.hs-l{font-family:'Rajdhani',sans-serif;font-size:.6rem;text-transform:uppercase;letter-spacing:2px;color:#4a5a78}
#bot-hud{position:fixed;bottom:0;left:0;right:0;padding:10px 20px;z-index:10;background:linear-gradient(0deg,rgba(2,4,8,.9) 0%,transparent 100%);pointer-events:none}
.zones-bar{display:flex;justify-content:center;gap:4px}
.zb{font-family:'Rajdhani',sans-serif;font-size:.68rem;padding:4px 12px;border-radius:4px;color:#5a6a88;border:1px solid #111828;cursor:pointer;pointer-events:auto;transition:.2s;letter-spacing:1px}
.zb:hover,.zb.lit{color:#06b6d4;border-color:#06b6d4;background:rgba(6,182,212,.06);text-shadow:0 0 8px rgba(6,182,212,.3)}
</style>
</head>
<body>
<!-- CANONICAL BANNER doctrine 103 -->
<div id="canonical-banner-v103" style="position:fixed;top:0;left:0;right:0;z-index:99990;background:linear-gradient(90deg,#1e293b,#0f172a);border-bottom:1px solid rgba(99,102,241,0.3);padding:8px 16px;display:flex;align-items:center;justify-content:space-between;font-family:Inter,system-ui,sans-serif;font-size:12px;backdrop-filter:blur(8px)">
<span style="color:#94a3b8">Variante agents-* <span id="canonical-this-page" style="color:#64748b">(cette page)</span></span>
<a href="/agents-archi.html" style="color:#a5b4fc;text-decoration:none;padding:4px 12px;background:rgba(99,102,241,0.15);border-radius:6px;border:1px solid rgba(99,102,241,0.25)">Voir canonical : agents-archi</a>
<button type="button" aria-label="Fermer banner" onclick="this.parentElement.style.display='none'" style="background:transparent;border:none;color:#64748b;font-size:16px;cursor:pointer;padding:0 8px">&times;</button>
</div>
<style>#canonical-banner-v103+*{margin-top:36px!important}</style>
<script>
(function(){
var el = document.getElementById('canonical-this-page');
if(el) el.textContent = '(' + location.pathname.split('/').pop() + ')';
})();
</script>
<!-- END CANONICAL BANNER -->
<canvas id="c"></canvas>
<div id="tip"><div class="box"><div class="nm"></div><div class="tp"></div><div class="ds"></div><div class="pr"></div><div class="bar"><i></i></div></div></div>
<div id="hud">
<div class="logo">WEVAL <span>COMMAND</span></div>
<div class="hud-stats">
<div class="hs"><div class="hs-v">31</div><div class="hs-l">Agents</div></div>
<div class="hs"><div class="hs-v">8</div><div class="hs-l">Zones</div></div>
<div class="hs"><div class="hs-v" id="fps">60</div><div class="hs-l">FPS</div></div>
</div>
</div>
<div id="bot-hud"><div class="zones-bar" id="zbar"></div></div>
<script>
const C=document.getElementById('c'),X=C.getContext('2d');
let W,H,mx=-1,my=-1,hov=null,frame=0,camX=0,camTargetX=0;
const dpr=Math.min(devicePixelRatio,2);
function resize(){W=innerWidth;H=innerHeight;C.width=W*dpr;C.height=H*dpr;X.scale(dpr,dpr)}
addEventListener('resize',resize);resize();
const ZN=[
{id:'prospect',lbl:'PROSPECTION',icon:'🎯',clr:'#2563eb',x:0},
{id:'consult',lbl:'CONSULTING',icon:'💼',clr:'#7c3aed',x:0},
{id:'dev',lbl:'DÉVELOPPEMENT',icon:'⚡',clr:'#10b981',x:0},
{id:'infra',lbl:'INFRASTRUCTURE',icon:'🏗️',clr:'#f59e0b',x:0},
{id:'security',lbl:'SÉCURITÉ',icon:'🛡️',clr:'#ef4444',x:0},
{id:'delivery',lbl:'LIVRAISON',icon:'🚀',clr:'#06b6d4',x:0},
{id:'pharma',lbl:'PHARMA',icon:'💊',clr:'#d946ef',x:0},
{id:'monitor',lbl:'MONITORING',icon:'📡',clr:'#eab308',x:0},
];
const AG=[
{n:'Ethica',e:'💊',z:0,t:'pharma',d:'HCP scraping DabaDoc+LinkedIn',p:'131K+ médecins DZ/MA/TN'},
{n:'Analyst',e:'🔍',z:0,t:'cognitive',d:'Analyse besoins & requirements',p:'Specs, études marché'},
{n:'Writer',e:'✍️',z:0,t:'cognitive',d:'Rédaction emails & proposals',p:'Cold emails, articles B2B'},
{n:'CEO',e:'👔',z:1,t:'autonomous',d:'Agent autonome stratégique',p:'Décisions, budget, hiring'},
{n:'Architect',e:'🏗️',z:1,t:'cognitive',d:'Architecture technique',p:'Diagrammes, blueprints'},
{n:'Planner',e:'📋',z:1,t:'cognitive',d:'Roadmaps & milestones',p:'Sprint plans, Gantt'},
{n:'DeerFlow',e:'🦌',z:1,t:'research',d:'Deep research multi-sources',p:'Synthèses R&D, rapports'},
{n:'Critic',e:'⚖️',z:1,t:'cognitive',d:'Validation & risques',p:'Reviews, alertes risques'},
{n:'Executor',e:'⚡',z:2,t:'cognitive',d:'Exécution & déploiement',p:'Scripts, migrations'},
{n:'Debugger',e:'🐛',z:2,t:'cognitive',d:'Root cause analysis',p:'Fixes, traces, patches'},
{n:'Reviewer',e:'👁️',z:2,t:'cognitive',d:'Code review expert',p:'PR reviews, scores qualité'},
{n:'Designer',e:'🎨',z:2,t:'cognitive',d:'UI/UX design system',p:'Mockups, composants'},
{n:'WEDROID',e:'🤖',z:2,t:'backend',d:'Auto-diagnostic backend v5',p:'DB fix, API repair auto'},
{n:'Simplifier',e:'✂️',z:2,t:'cognitive',d:'Refactoring & clean code',p:'Code -40% complexité'},
{n:'Watchdog',e:'🐕',z:3,t:'monitor',d:'Service monitor */3min',p:'Auto-restart + Telegram'},
{n:'Guardian',e:'🛡️',z:3,t:'monitor',d:'Protection fichiers système',p:'chattr +i, lockdown'},
{n:'Blade',e:'💻',z:3,t:'desktop',d:'Agent Razer Blade desktop',p:'PowerShell, sync, tasks'},
{n:'Git-Master',e:'🌿',z:3,t:'cognitive',d:'Git flow & releases',p:'Tags, merges, deploys'},
{n:'Security',e:'🔐',z:4,t:'cognitive',d:'Audit OWASP & pentests',p:'Rapports vulnérabilités'},
{n:'Verifier',e:'✅',z:4,t:'cognitive',d:'Conformité ISO/RGPD',p:'Checks PCI-DSS, audits'},
{n:'QA-Test',e:'🧪',z:5,t:'cognitive',d:'Tests E2E & couverture',p:'148 NonReg, Playwright'},
{n:'TestEng',e:'🧰',z:5,t:'cognitive',d:'CI/CD pipelines',p:'Automatisation tests'},
{n:'Tracer',e:'🔦',z:5,t:'cognitive',d:'Log tracing & debug',p:'Stack traces, analysis'},
{n:'Scientist',e:'🔬',z:5,t:'cognitive',d:'Benchmarks & métriques',p:'AI Benchmark 182 modèles'},
{n:'Explore',e:'🧭',z:6,t:'cognitive',d:'Exploration R&D pharma',p:'Nouvelles sources HCP'},
{n:'DocSpec',e:'📝',z:6,t:'cognitive',d:'Documentation technique',p:'Templates, guides'},
{n:'MiroFish',e:'🐟',z:6,t:'research',d:'Creative AI multi-agent',p:'Contenu, brainstorm'},
{n:'TaskMgr',e:'📋',z:7,t:'cognitive',d:'Suivi tâches & deadlines',p:'Kanban, alertes retard'},
{n:'Brain',e:'💡',z:7,t:'cognitive',d:'Brainstorming créatif',p:'Idées, innovation'},
{n:'Intro',e:'🧠',z:7,t:'cognitive',d:'Méta-analyse & réflexion',p:'Auto-amélioration IA'},
{n:'Orch',e:'🎯',z:7,t:'cognitive',d:'Orchestration multi-agent',p:'Coordination workflows'},
];
const TC={cognitive:'#3b82f6',autonomous:'#a855f7',backend:'#22c55e',monitor:'#f59e0b',pharma:'#ec4899',research:'#06b6d4',desktop:'#64748b'};
// ═══ INIT AGENTS ═══
const groundY=H*.56;
AG.forEach((a,i)=>{
a.x=0;a.y=0;a.tx=0;a.ty=0;a.bob=Math.random()*6.28;a.walk=Math.random()*6.28;
a.timer=Math.random()*200;a.speed=.8+Math.random()*.4;a.scale=1;a.glow=0;
a.breathe=Math.random()*6.28;a.eyeBlink=0;a.blinkTimer=100+Math.random()*300;
});
// ═══ PARTICLES ═══
const PTS=[];for(let i=0;i<120;i++)PTS.push({x:Math.random()*4000-500,y:Math.random()*H,r:Math.random()*1.8+.3,a:Math.random()*.2+.03,s:Math.random()*.4+.08,ph:Math.random()*6.28});
// ═══ ZONE LIGHTS ═══
const ZLIGHTS=[];ZN.forEach(z=>{for(let i=0;i<3;i++)ZLIGHTS.push({zx:0,ox:(Math.random()-.5)*80,oy:Math.random()*-40-20,r:40+Math.random()*60,a:.04+Math.random()*.04,clr:z.clr,z:z});});
function layZones(){
const gap=(W*1.1)/ZN.length;
ZN.forEach((z,i)=>{z.x=gap*.55+i*gap;});
// Init agent positions
AG.forEach(a=>{const z=ZN[a.z];if(z){const ais=AG.filter(b=>b.z===a.z);const mi=ais.indexOf(a);const spread=Math.min(gap*.35,100);a.x=z.x+(mi-ais.length/2)*26;a.y=groundY-10+Math.random()*15;a.tx=a.x;a.ty=a.y;}});
}
layZones();
// ═══ DRAW BACKGROUND ═══
function drawBg(){
// Gradient sky
const g=X.createLinearGradient(0,0,0,H);
g.addColorStop(0,'#020408');g.addColorStop(.3,'#040810');g.addColorStop(.55,'#060c18');g.addColorStop(1,'#030608');
X.fillStyle=g;X.fillRect(0,0,W,H);
// Grid floor
X.save();
X.globalAlpha=.08;
const gy=groundY+24;
for(let i=-20;i<40;i++){
const x=i*60-((frame*.3)%60);
X.strokeStyle='#06b6d4';X.lineWidth=.5;
X.beginPath();X.moveTo(x,gy);X.lineTo(x+(W*.3),H);X.stroke();
}
for(let j=0;j<12;j++){
const y=gy+j*((H-gy)/12);
X.beginPath();X.moveTo(0,y);X.lineTo(W,y);X.stroke();
}
X.restore();
}
// ═══ DRAW ZONE ═══
function drawZone(z,idx){
const x=z.x, y=groundY;
// Pillar glow
const g=X.createRadialGradient(x,y-30,5,x,y-30,120);
g.addColorStop(0,z.clr+'18');g.addColorStop(1,'transparent');
X.fillStyle=g;X.beginPath();X.arc(x,y-30,120,0,6.28);X.fill();
// Platform
X.fillStyle=z.clr+'15';
X.beginPath();
X.ellipse(x,y+22,70,10,0,0,6.28);
X.fill();
X.strokeStyle=z.clr+'40';X.lineWidth=1;
X.beginPath();X.ellipse(x,y+22,70,10,0,0,6.28);X.stroke();
// Label
X.font='900 10px Orbitron';X.textAlign='center';
X.fillStyle=z.clr+'90';
X.fillText(z.lbl,x,y+48);
// Icon
X.font='20px sans-serif';
X.fillText(z.icon,x,y-60);
// Connector to next
if(idx<ZN.length-1){
const nx=ZN[idx+1].x;
X.strokeStyle='#0a1428';X.lineWidth=2;X.setLineDash([6,10]);
X.beginPath();X.moveTo(x+72,y+22);X.lineTo(nx-72,y+22);X.stroke();
X.setLineDash([]);
// Animated dot
const t=(frame*1.5+idx*40)%((nx-x));
X.fillStyle=z.clr+'60';
X.beginPath();X.arc(x+72+t,y+22,2.5,0,6.28);X.fill();
}
}
// ═══ DRAW AGENT CHARACTER ═══
function drawAgent(a){
const c=TC[a.t]||'#6080a0';
const s=16*(a.scale);
const bob=Math.sin(a.bob)*2.5;
const leg=Math.sin(a.walk)*5;
const breath=Math.sin(a.breathe)*.5;
const isHov=a===hov;
X.save();
X.translate(a.x,a.y+bob);
// Shadow
X.fillStyle='rgba(0,0,0,.25)';
X.beginPath();X.ellipse(0,s*.6,s*.5,s*.15,0,0,6.28);X.fill();
if(isHov){
// Selection ring
X.strokeStyle=c;X.lineWidth=1.5;X.globalAlpha=.3+Math.sin(frame*.08)*.2;
X.beginPath();X.ellipse(0,s*.6,s*.8,s*.2,0,0,6.28);X.stroke();
X.globalAlpha=1;
// Glow
X.shadowColor=c;X.shadowBlur=24;
}
// ═ BODY (capsule shape) ═
X.fillStyle=c+'30';X.strokeStyle=c;X.lineWidth=1.8;
// Torso
X.beginPath();
X.moveTo(-s*.3,-s*1.5+breath);
X.quadraticCurveTo(-s*.35,-s*.6, -s*.25,-s*.2);
X.lineTo(s*.25,-s*.2);
X.quadraticCurveTo(s*.35,-s*.6, s*.3,-s*1.5+breath);
X.closePath();
X.fill();X.stroke();
// Head
const hr=s*.45;
X.beginPath();X.arc(0,-s*1.9,hr,0,6.28);
X.fillStyle=c+'20';X.fill();
X.strokeStyle=c;X.stroke();
// Visor / face glow
X.beginPath();X.arc(0,-s*1.9,hr*.6,-.4,.4);
X.strokeStyle=c+'80';X.lineWidth=2;X.stroke();
// Emoji
X.font=`${Math.round(s*.55)}px sans-serif`;X.textAlign='center';X.textBaseline='middle';
X.fillText(a.e,0,-s*1.9);
// Eyes blink
if(a.eyeBlink>0){
X.fillStyle='#020408';
X.fillRect(-s*.2,-s*2,s*.4,s*.12);
}
// Arms
X.strokeStyle=c;X.lineWidth=1.8;X.lineCap='round';
X.beginPath();
X.moveTo(-s*.5,-s*1.1+Math.sin(a.walk+1)*3);
X.lineTo(-s*.3,-s*1.3);
X.lineTo(s*.3,-s*1.3);
X.lineTo(s*.5,-s*1.1-Math.sin(a.walk+1)*3);
X.stroke();
// Legs
X.beginPath();
X.moveTo(-s*.3+leg*.4, s*.4);
X.lineTo(-s*.1, -s*.2);
X.lineTo(s*.1, -s*.2);
X.lineTo(s*.3-leg*.4, s*.4);
X.stroke();
// Boots
X.fillStyle=c+'50';
X.beginPath();X.ellipse(-s*.3+leg*.4,s*.45,s*.12,s*.06,0,0,6.28);X.fill();
X.beginPath();X.ellipse(s*.3-leg*.4,s*.45,s*.12,s*.06,0,0,6.28);X.fill();
// Name tag
if(isHov||true){
X.font=`${isHov?'700':'600'} ${isHov?10:8}px Rajdhani`;
X.textAlign='center';
X.fillStyle=isHov?'#fff':c+'70';
X.fillText(a.n,0,s*.8);
}
// Activity indicator (small orbiting dot)
const oA=frame*.04+a.bob;
const ox=Math.cos(oA)*s*.7, oy=-s*1.9+Math.sin(oA)*s*.35;
X.fillStyle=c;X.globalAlpha=.5;
X.beginPath();X.arc(ox,oy,1.5,0,6.28);X.fill();
X.globalAlpha=1;
X.restore();
}
// ═══ UPDATE ═══
function update(dt){
frame++;
AG.forEach(a=>{
a.bob+=dt*2.8*a.speed;
a.walk+=dt*(a.speed*5);
a.breathe+=dt*1.5;
a.timer-=dt*60;
a.blinkTimer-=dt*60;
if(a.blinkTimer<=0){a.eyeBlink=8;a.blinkTimer=120+Math.random()*400;}
if(a.eyeBlink>0)a.eyeBlink-=dt*60;
if(a.timer<=0){
a.timer=120+Math.random()*350;
const z=ZN[a.z];
const ais=AG.filter(b=>b.z===a.z);
const mi=ais.indexOf(a);
a.tx=z.x+(mi-ais.length/2)*24+(Math.random()-.5)*30;
a.ty=groundY-12+(Math.random()-.5)*18;
// Rare visit to neighbor
if(Math.random()<.04){
const nz=Math.max(0,Math.min(ZN.length-1,a.z+(Math.random()<.5?-1:1)));
a.tx=ZN[nz].x+(Math.random()-.5)*50;
a.ty=groundY-12+(Math.random()-.5)*14;
}
}
a.x+=(a.tx-a.x)*.018*a.speed;
a.y+=(a.ty-a.y)*.018*a.speed;
// Hover scale
a.scale+=(a===hov?1.35:1-a.scale)*.1;
a.glow+=(a===hov?1:0-a.glow)*.1;
});
}
// ═══ TOOLTIP ═══
function showTip(){
const t=document.getElementById('tip');
if(!hov){t.style.display='none';return;}
t.style.display='block';
t.style.left=Math.min(mx+20,W-280)+'px';
t.style.top=Math.max(my-160,10)+'px';
const c=TC[hov.t]||'#6080a0';
t.querySelector('.nm').textContent=hov.e+' '+hov.n;
t.querySelector('.tp').textContent=hov.t;
t.querySelector('.tp').style.background=c+'25';
t.querySelector('.tp').style.color=c;
t.querySelector('.ds').textContent=hov.d;
t.querySelector('.pr').textContent='→ '+hov.p;
t.querySelector('.bar i').style.background=`linear-gradient(90deg,${c},${c}80)`;
t.querySelector('.bar i').style.width='100%';
}
// ═══ HIT TEST ═══
function hitTest(){
hov=null;
AG.forEach(a=>{
if(Math.abs(mx-a.x)<20&&Math.abs(my-a.y+10)<30)hov=a;
});
}
// ═══ PARTICLES ═══
function drawPts(){
PTS.forEach(p=>{
p.y-=p.s;p.ph+=.01;
p.x+=Math.sin(p.ph)*.2;
if(p.y<-5){p.y=H+5;p.x=Math.random()*W*1.2-100;}
X.fillStyle=`rgba(6,182,212,${p.a})`;
X.beginPath();X.arc(p.x,p.y,p.r,0,6.28);X.fill();
});
}
// ═══ ZONE BAR ═══
function initZbar(){
const el=document.getElementById('zbar');
el.innerHTML=ZN.map(z=>`<div class="zb" onmouseenter="litZone('${z.id}')" onmouseleave="unlitZone()">${z.icon} ${z.lbl}</div>`).join('');
}
let litZ=null;
window.litZone=id=>{litZ=id;document.querySelectorAll('.zb').forEach((b,i)=>b.classList.toggle('lit',ZN[i].id===id));};
window.unlitZone=()=>{litZ=null;document.querySelectorAll('.zb').forEach(b=>b.classList.remove('lit'));};
initZbar();
// ═══ MAIN LOOP ═══
let lt=0,fpsC=0,fpsT=0;
function loop(t){
const dt=Math.min((t-lt)/1000,.04);lt=t;
fpsC++;if(t-fpsT>1000){document.getElementById('fps').textContent=fpsC;fpsC=0;fpsT=t;}
X.clearRect(0,0,W,H);
drawBg();
drawPts();
// Zone lights
ZLIGHTS.forEach(l=>{
const g=X.createRadialGradient(l.z.x+l.ox,groundY+l.oy,0,l.z.x+l.ox,groundY+l.oy,l.r);
g.addColorStop(0,l.clr+Math.round(l.a*255).toString(16).padStart(2,'0'));
g.addColorStop(1,'transparent');
X.fillStyle=g;X.beginPath();X.arc(l.z.x+l.ox,groundY+l.oy,l.r,0,6.28);X.fill();
});
ZN.forEach((z,i)=>drawZone(z,i));
update(dt);
// Draw agents (sorted by Y for depth)
const sorted=[...AG].sort((a,b)=>a.y-b.y);
sorted.forEach(a=>{
// Dim if zone filter active
if(litZ){const zIdx=ZN.findIndex(z=>z.id===litZ);X.globalAlpha=a.z===zIdx?1:.15;}
drawAgent(a);
X.globalAlpha=1;
});
hitTest();
showTip();
requestAnimationFrame(loop);
}
C.addEventListener('mousemove',e=>{mx=e.clientX;my=e.clientY});
C.addEventListener('mouseleave',()=>{mx=my=-1});
addEventListener('resize',()=>{resize();layZones()});
requestAnimationFrame(loop);
</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/a11y-auto-enhancer.js" defer></script>
</body>
</html>