Files
weval-consulting/agents-archi.html
2026-04-08 21:29:58 +02:00

348 lines
46 KiB
HTML

<!DOCTYPE html>
<html lang="fr"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>WEVIA — Architecture Agents IA 3D</title>
<link rel="icon" href="/assets/favicon.ico">
<style>
@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@600;700;800;900&family=Orbitron:wght@500;600;700;800;900&display=swap');
*{margin:0;padding:0;box-sizing:border-box}body{background:#050a18;overflow:hidden;font-family:'Nunito';color:#e2e8f0}canvas{display:block}
#hud{position:fixed;top:0;left:0;right:0;height:32px;background:rgba(5,10,24,.9);backdrop-filter:blur(16px);z-index:30;display:flex;align-items:center;padding:0 16px;gap:14px;border-bottom:1px solid rgba(6,182,212,.08)}
.hl{font:800 11px Orbitron;background:linear-gradient(135deg,#06b6d4,#22d3ee);-webkit-background-clip:text;-webkit-text-fill-color:transparent;letter-spacing:1px}
.hm{display:flex;align-items:center;gap:5px;font:600 10px Nunito}.hm .d{width:5px;height:5px;border-radius:50%;background:#4ade80;box-shadow:0 0 6px rgba(74,222,128,.5)}.hm span{color:#475569}.hm b{color:#e2e8f0}
#nav{margin-left:auto;display:flex;gap:2px}#nav a{padding:4px 10px;border-radius:5px;font:700 9px Nunito;text-decoration:none;color:#475569;transition:.2s}#nav a:hover{color:#94a3b8}#nav a.ac{color:#06b6d4;background:rgba(6,182,212,.1)}
#ls{position:fixed;top:32px;left:0;right:0;z-index:25;display:flex;justify-content:center;gap:14px;padding:3px 8px;background:linear-gradient(135deg,rgba(30,41,59,.85),rgba(15,23,42,.85));backdrop-filter:blur(8px)}#ls div{font:700 9px sans-serif}
.nl{text-align:center;pointer-events:auto;cursor:default}.nl .nm{font:700 9px Nunito;color:#94a3b8;text-shadow:0 1px 4px rgba(0,0,0,.8);white-space:nowrap}
.tl{font:900 11px Orbitron;text-transform:uppercase;letter-spacing:2.5px;padding:5px 16px;border-radius:7px;backdrop-filter:blur(8px);border:1.5px solid;pointer-events:none;white-space:nowrap}.tc{font:600 9px Nunito;opacity:.6;margin-left:6px}
#tp{position:fixed;display:none;z-index:40;background:rgba(8,12,24,.96);border:1.5px solid #06b6d4;border-radius:10px;padding:10px 14px;max-width:220px;box-shadow:0 12px 40px rgba(0,0,0,.7);backdrop-filter:blur(12px);pointer-events:none}#tp b{font:800 13px Nunito;color:#22d3ee;display:block}#tp .s{font:600 10px Nunito;color:#64748b}#tp .dt{font:600 10px Nunito;color:#94a3b8;margin-top:4px;padding-top:4px;border-top:1px solid rgba(148,163,184,.08)}#tp .tb{display:inline-block;font:700 8px Nunito;padding:1px 6px;border-radius:3px;margin-top:3px}
#st{position:fixed;bottom:16px;left:0;right:0;display:flex;justify-content:center;gap:24px;z-index:20;pointer-events:none}.stn{font:900 26px Orbitron;background:linear-gradient(135deg,#06b6d4,#4ade80);-webkit-background-clip:text;-webkit-text-fill-color:transparent}.stl{font:700 7px Nunito;color:#475569;text-transform:uppercase;letter-spacing:2px;text-align:center}
#ld{position:fixed;inset:0;background:#050a18;display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:100}#ld .sp{width:100px;height:100px;border:3px solid rgba(6,182,212,.2);border-top-color:#06b6d4;border-radius:50%;animation:sp 1s linear infinite}#ld p{margin-top:10px;font:700 11px Orbitron;color:#06b6d4}@keyframes sp{to{transform:rotate(360deg)}}
</style></head><body>
<div id="ld"><div class="sp"></div><p>WEVIA 3D HD</p></div>
<div id="hud"><div class="hl">WEVIA ARCHITECTURE 3D</div><div class="hm"><div class="d"></div><span>Agents</span><b>30</b></div><div class="hm"><div class="d"></div><span>Fiability</span><b id="hFi"></b></div><div class="hm"><div class="d"></div><span>Cost</span><b>0€</b></div><div id="nav"><a href="/agents-archi.html" class="ac">Architecture 3D</a><a href="/director-center.html">Director</a><a href="/wevia-meeting-rooms.html">Rooms</a><a href="/enterprise-model.html">Enterprise</a><a href="/director-chat.html">Chat</a><a href="/l99-brain.html">L99</a><a href="/agents-fleet.html" style="color:#06b6d4;text-decoration:none;padding:0 8px">Fleet</a></div></div>
<div id="ls"><div style="color:#4ade80">🤖 30 Agents</div><div style="color:#60a5fa">🏢 4 Tiers</div><div style="color:#fbbf24">🐳 16 Docker</div><div style="color:#a78bfa">🦙 10 Ollama</div><div style="color:#f87171">🧪 151/153</div><div style="color:#34d399">🔐 SSO OK</div></div>
<div id="tp"><b></b><div class="s"></div><div class="dt"></div><div class="tb"></div></div>
<div id="st"><div><div class="stn">30</div><div class="stl">Agents</div></div><div><div class="stn">4</div><div class="stl">Tiers</div></div><div><div class="stn">14</div><div class="stl">Providers</div></div><div><div class="stn">0€</div><div class="stl">Cost</div></div></div>
<script type="importmap">{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"}}</script>
<script type="module">
import*as THREE from'three';import{OrbitControls}from'three/addons/controls/OrbitControls.js';import{CSS2DRenderer,CSS2DObject}from'three/addons/renderers/CSS2DRenderer.js';import{RoomEnvironment}from'three/addons/environments/RoomEnvironment.js';import{EffectComposer}from'three/addons/postprocessing/EffectComposer.js';import{RenderPass}from'three/addons/postprocessing/RenderPass.js';import{UnrealBloomPass}from'three/addons/postprocessing/UnrealBloomPass.js';
// === PROP BUILDERS ===
function mkScreen(w,h,col,content){const g=new THREE.Group();let m;m=new THREE.Mesh(new THREE.BoxGeometry(w+.06,h+.06,.03),new THREE.MeshPhysicalMaterial({color:0x0a0e1a,metalness:.9,roughness:.08,clearcoat:1,envMapIntensity:1.5}));g.add(m);m=new THREE.Mesh(new THREE.PlaneGeometry(w,h),new THREE.MeshStandardMaterial({color:col,emissive:col,emissiveIntensity:.6,toneMapped:false,transparent:true,opacity:.9}));m.position.z=.02;g.add(m);return g}
function mkDesk(w,d){const g=new THREE.Group();const dm=new THREE.MeshPhysicalMaterial({color:0x1e293b,metalness:.6,roughness:.2,clearcoat:.7});let m;m=new THREE.Mesh(new THREE.BoxGeometry(w||.8,d||.04,.4),dm);m.position.y=.38;g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.02,.02,.38,6),dm);m.position.set(-(w||.8)/2+.05,.19,-.15);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.02,.02,.38,6),dm);m.position.set((w||.8)/2-.05,.19,-.15);g.add(m);return g}
function mkWorkstation(scrCol){const g=new THREE.Group();const d=mkDesk(.8);g.add(d);const s=mkScreen(.35,.22,scrCol||0x06b6d4);s.position.set(0,.62,-.1);s.rotation.x=-.08;g.add(s);let m=new THREE.Mesh(new THREE.BoxGeometry(.12,.02,.08),new THREE.MeshStandardMaterial({color:0x334155}));m.position.set(.25,.4,.05);g.add(m);m=new THREE.Mesh(new THREE.BoxGeometry(.05,.01,.03),new THREE.MeshStandardMaterial({color:0x334155}));m.position.set(-.2,.4,.1);g.add(m);return g}
function mkBigScreen(w,h,col){const g=new THREE.Group();let m;m=new THREE.Mesh(new THREE.BoxGeometry(w+.1,h+.1,.04),new THREE.MeshStandardMaterial({color:0x0a0e1a,metalness:.9,roughness:.1}));g.add(m);m=new THREE.Mesh(new THREE.PlaneGeometry(w,h),new THREE.MeshStandardMaterial({color:col,emissive:col,emissiveIntensity:.8,toneMapped:false}));m.position.z=.025;g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.03,.04,.8,8),new THREE.MeshStandardMaterial({color:0x1e293b,metalness:.6,roughness:.3}));m.position.y=-(h/2+.4);g.add(m);return g}
function mkServerRack(){const g=new THREE.Group();const fm=new THREE.MeshPhysicalMaterial({color:0x0f172a,metalness:.85,roughness:.12,clearcoat:.8,clearcoatRoughness:.05,envMapIntensity:1.5});let m;m=new THREE.Mesh(new THREE.BoxGeometry(.35,.8,.25),fm);m.position.y=.4;g.add(m);for(let i=0;i<6;i++){m=new THREE.Mesh(new THREE.SphereGeometry(.012,6,6),new THREE.MeshStandardMaterial({color:i%3===0?0xef4444:0x4ade80,emissive:i%3===0?0xef4444:0x22c55e,emissiveIntensity:2,toneMapped:false}));m.position.set(-.12,.15+i*.1,.13);g.add(m);m=new THREE.Mesh(new THREE.SphereGeometry(.012,6,6),new THREE.MeshStandardMaterial({color:0x3b82f6,emissive:0x2563eb,emissiveIntensity:1.5,toneMapped:false}));m.position.set(-.06,.15+i*.1,.13);g.add(m)}return g}
function mkChair(){const g=new THREE.Group();const cm=new THREE.MeshStandardMaterial({color:0x1e293b,roughness:.6});let m;m=new THREE.Mesh(new THREE.BoxGeometry(.25,.04,.25),cm);m.position.y=.3;g.add(m);m=new THREE.Mesh(new THREE.BoxGeometry(.25,.3,.04),cm);m.position.set(0,.48,-.12);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.02,.02,.3,6),cm);m.position.y=.15;g.add(m);return g}
function mkCoffeeMachine(){const g=new THREE.Group();const cm=new THREE.MeshStandardMaterial({color:0x334155,metalness:.5,roughness:.3});let m;m=new THREE.Mesh(new THREE.BoxGeometry(.2,.35,.15),cm);m.position.y=.55;g.add(m);m=new THREE.Mesh(new THREE.BoxGeometry(.25,.03,.15),cm);m.position.y=.38;g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.015,.015,.38,6),cm);m.position.set(-.08,.19,0);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.015,.015,.38,6),cm);m.position.set(.08,.19,0);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.025,.02,.06,8),new THREE.MeshStandardMaterial({color:0x8b5cf6,emissive:0x7c3aed,emissiveIntensity:1}));m.position.set(0,.75,0);g.add(m);return g}
// === CHARACTERS ===
function mkRobot(col,accent){const g=new THREE.Group();const bm=new THREE.MeshPhysicalMaterial({color:col,metalness:.92,roughness:.1,clearcoat:1,clearcoatRoughness:.03,envMapIntensity:1.8});const dm=new THREE.MeshPhysicalMaterial({color:0x0f1629,metalness:.8,roughness:.15,clearcoat:.9});const em=new THREE.MeshStandardMaterial({color:accent||0x22d3ee,emissive:accent||0x06b6d4,emissiveIntensity:4,toneMapped:false});const ac=new THREE.MeshPhysicalMaterial({color:accent||0x22d3ee,metalness:.5,roughness:.2,clearcoat:.8});const jm=new THREE.MeshPhysicalMaterial({color:0x2a2a3e,metalness:.6,roughness:.25});let m;
m=new THREE.Mesh(new THREE.CylinderGeometry(.28,.24,.65,8),bm);m.position.y=.62;g.add(m);m=new THREE.Mesh(new THREE.CircleGeometry(.08,16),em);m.position.set(0,.7,.25);g.add(m);m=new THREE.Mesh(new THREE.BoxGeometry(.4,.15,.02),ac);m.position.set(0,.55,.24);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.07,.09,.08,10),jm);m.position.y=.98;g.add(m);
m=new THREE.Mesh(new THREE.SphereGeometry(.12,12,12),bm);m.position.set(-.38,.88,0);g.add(m);m=new THREE.Mesh(new THREE.SphereGeometry(.12,12,12),bm);m.position.set(.38,.88,0);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.07,.06,.28,10),bm);m.position.set(-.4,.68,0);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.07,.06,.28,10),bm);m.position.set(.4,.68,0);g.add(m);m=new THREE.Mesh(new THREE.SphereGeometry(.065,8,8),jm);m.position.set(-.4,.5,0);g.add(m);m=new THREE.Mesh(new THREE.SphereGeometry(.065,8,8),jm);m.position.set(.4,.5,0);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.06,.055,.24,10),ac);m.position.set(-.4,.34,0);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.06,.055,.24,10),ac);m.position.set(.4,.34,0);g.add(m);m=new THREE.Mesh(new THREE.SphereGeometry(.055,8,8),dm);m.position.set(-.4,.2,0);g.add(m);m=new THREE.Mesh(new THREE.SphereGeometry(.055,8,8),dm);m.position.set(.4,.2,0);g.add(m);
m=new THREE.Mesh(new THREE.CylinderGeometry(.22,.2,.1,10),jm);m.position.y=.26;g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.1,.08,.35,10),dm);m.position.set(-.13,.04,0);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.1,.08,.35,10),dm);m.position.set(.13,.04,0);g.add(m);m=new THREE.Mesh(new THREE.BoxGeometry(.16,.07,.24),bm);m.position.set(-.13,-.16,.03);g.add(m);m=new THREE.Mesh(new THREE.BoxGeometry(.16,.07,.24),bm);m.position.set(.13,-.16,.03);g.add(m);return g}
function mkHuman(sk,cl,hc,isF){const g=new THREE.Group();const sm=new THREE.MeshPhysicalMaterial({color:sk,roughness:.5,metalness:.01,clearcoat:.15,sheen:1.5,sheenColor:new THREE.Color(sk).multiplyScalar(1.3),sheenRoughness:.4});const cm=new THREE.MeshStandardMaterial({color:cl,roughness:.55,metalness:.05});const hm=new THREE.MeshStandardMaterial({color:hc||0x1a1a2e,roughness:.75});const sh=new THREE.MeshStandardMaterial({color:0x1e1e2e,roughness:.3,metalness:.15});const wm=new THREE.MeshStandardMaterial({color:0xeeeef0,roughness:.5});let m;
m=new THREE.Mesh(new THREE.CylinderGeometry(isF?.17:.2,(isF?.17:.2)-.02,isF?.5:.55,12),cm);m.position.y=.62;g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.05,.06,.08,10),sm);m.position.y=.95;g.add(m);
m=new THREE.Mesh(new THREE.SphereGeometry(.065,10,10),cm);m.position.set(-.25,.84,0);g.add(m);m=new THREE.Mesh(new THREE.SphereGeometry(.065,10,10),cm);m.position.set(.25,.84,0);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.04,.035,.32,10),sm);m.position.set(-.27,.6,0);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.04,.035,.32,10),sm);m.position.set(.27,.6,0);g.add(m);m=new THREE.Mesh(new THREE.SphereGeometry(.032,8,8),sm);m.position.set(-.27,.42,0);g.add(m);m=new THREE.Mesh(new THREE.SphereGeometry(.032,8,8),sm);m.position.set(.27,.42,0);g.add(m);
m=new THREE.Mesh(new THREE.CylinderGeometry(.065,.05,.4,10),cm);m.position.set(-.08,.1,0);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.065,.05,.4,10),cm);m.position.set(.08,.1,0);g.add(m);m=new THREE.Mesh(new THREE.BoxGeometry(.09,.055,.17),sh);m.position.set(-.08,-.12,.02);g.add(m);m=new THREE.Mesh(new THREE.BoxGeometry(.09,.055,.17),sh);m.position.set(.08,-.12,.02);g.add(m);return g}
function mkPlant(y){var g=new THREE.Group();var pm=new THREE.MeshStandardMaterial({color:0x3a2618,roughness:.6,metalness:.1});var lm=new THREE.MeshStandardMaterial({color:0x166534,roughness:.7});var lm2=new THREE.MeshStandardMaterial({color:0x15803d,roughness:.7});var m;
m=new THREE.Mesh(new THREE.CylinderGeometry(.07,.06,.14,10),pm);m.position.y=.07;g.add(m);
m=new THREE.Mesh(new THREE.CylinderGeometry(.02,.02,.2,6),new THREE.MeshStandardMaterial({color:0x2d1a0e}));m.position.y=.22;g.add(m);
m=new THREE.Mesh(new THREE.SphereGeometry(.1,10,10),lm);m.position.y=.32;g.add(m);
m=new THREE.Mesh(new THREE.SphereGeometry(.08,8,8),lm2);m.position.set(.06,.38,.04);g.add(m);
m=new THREE.Mesh(new THREE.SphereGeometry(.07,8,8),lm);m.position.set(-.05,.36,-.03);g.add(m);
m=new THREE.Mesh(new THREE.SphereGeometry(.06,8,8),lm2);m.position.set(.02,.42,0);g.add(m);
g.position.y=y;return g}
function mkWaterCooler(y){var g=new THREE.Group();var wm=new THREE.MeshPhysicalMaterial({color:0xdbeafe,metalness:.1,roughness:.2,transmission:.5,thickness:1});var fm=new THREE.MeshStandardMaterial({color:0x94a3b8,metalness:.6,roughness:.3});var m=new THREE.Mesh(new THREE.CylinderGeometry(.06,.08,.35,10),fm);m.position.y=.38;g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.07,.07,.2,10),wm);m.position.y=.65;g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.08,.08,.02,10),fm);m.position.y=.76;g.add(m);g.position.y=y;return g}
function mkDashScreen(w,h,y,col){var g=new THREE.Group();var fm=new THREE.MeshPhysicalMaterial({color:0x0a0e1a,metalness:.9,roughness:.08,clearcoat:1});var m=new THREE.Mesh(new THREE.BoxGeometry(w+.08,h+.08,.03),fm);g.add(m);var sm=new THREE.MeshStandardMaterial({color:0x0f172a});m=new THREE.Mesh(new THREE.PlaneGeometry(w,h),sm);m.position.z=.02;g.add(m);var bm=new THREE.MeshStandardMaterial({color:col||0x06b6d4,emissive:col||0x06b6d4,emissiveIntensity:.5,toneMapped:false});for(var i=0;i<5;i++){var bh=.03+Math.random()*.08;m=new THREE.Mesh(new THREE.BoxGeometry(.03,bh,.002),bm);m.position.set(-.08+i*.04,-h*.2+bh/2,.025);g.add(m)}var lm=new THREE.MeshStandardMaterial({color:0x4ade80,emissive:0x22c55e,emissiveIntensity:.6,toneMapped:false});m=new THREE.Mesh(new THREE.BoxGeometry(w*.6,.008,.002),lm);m.position.set(0,h*.15,.025);g.add(m);m=new THREE.Mesh(new THREE.BoxGeometry(w*.4,.008,.002),new THREE.MeshStandardMaterial({color:0xf59e0b,emissive:0xd97706,emissiveIntensity:.5,toneMapped:false}));m.position.set(-.03,h*.08,.025);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.02,.03,.5,6),new THREE.MeshStandardMaterial({color:0x334155,metalness:.6}));m.position.y=-(h/2+.25);g.add(m);g.position.y=y;return g}
function mkServerCage(y,w,d){var g=new THREE.Group();var wm=new THREE.LineBasicMaterial({color:0x334155,transparent:true,opacity:.4});var geo=new THREE.BoxGeometry(w,1.2,d);var eg=new THREE.EdgesGeometry(geo);var m=new THREE.LineSegments(eg,wm);m.position.y=.6;g.add(m);for(var i=0;i<3;i++){var sr=mkServerRack();sr.position.set(-.3+i*.3,0,0);g.add(sr)}g.position.y=y;return g}
function mkLineChart3D(y,col,w,h){var g=new THREE.Group();var fm=new THREE.MeshPhysicalMaterial({color:0x0a0e1a,metalness:.9,roughness:.08,clearcoat:1});var m=new THREE.Mesh(new THREE.BoxGeometry(w+.06,h+.06,.02),fm);g.add(m);var pts=[];var n=12;for(var i=0;i<=n;i++){pts.push(new THREE.Vector3(-w/2+i*(w/n),-h/2+Math.sin(i*.8+1)*h*.3+h*.3,0.015))}var curve=new THREE.CatmullRomCurve3(pts);var tubGeo=new THREE.TubeGeometry(curve,32,.008,6,false);m=new THREE.Mesh(tubGeo,new THREE.MeshStandardMaterial({color:col||0x4ade80,emissive:col||0x22c55e,emissiveIntensity:1,toneMapped:false}));g.add(m);var pts2=[];for(var i=0;i<=n;i++){pts2.push(new THREE.Vector3(-w/2+i*(w/n),-h/2+Math.cos(i*.6)*h*.25+h*.2,0.015))}var curve2=new THREE.CatmullRomCurve3(pts2);m=new THREE.Mesh(new THREE.TubeGeometry(curve2,32,.006,6,false),new THREE.MeshStandardMaterial({color:0x06b6d4,emissive:0x0891b2,emissiveIntensity:.8,toneMapped:false}));g.add(m);g.position.y=y;return g}
function mkParquet(w,d,y){
var g=new THREE.Group();
var wm=new THREE.MeshStandardMaterial({color:0x8B6914,roughness:.7,metalness:.05});
var wm2=new THREE.MeshStandardMaterial({color:0x7A5C1A,roughness:.7,metalness:.05});
var pw=.3,gap=.01;
for(var x=-w/2+pw/2;x<w/2;x+=pw+gap){
for(var z=-d/2+pw*2;z<d/2;z+=pw*4+gap){
var off=(Math.floor((x+w/2)/pw)%2)*(pw*2);
var m=new THREE.Mesh(new THREE.BoxGeometry(pw-.01,.02,pw*4-.01),Math.random()>.5?wm:wm2);
m.position.set(x,y+.12,z+off);g.add(m);
}
}
return g;
}
// === FLOATING PROPS (maquette style) ===
function mkBarChart(y,col){var g=new THREE.Group();var bm=new THREE.MeshStandardMaterial({color:col||0x06b6d4,emissive:col||0x06b6d4,emissiveIntensity:.3});[.15,.25,.35,.2,.3].forEach(function(h,i){var m=new THREE.Mesh(new THREE.BoxGeometry(.06,h,.04),bm);m.position.set(-.12+i*.06,h/2,0);g.add(m)});g.position.y=y;return g}
function mkPieChart(y,col){var g=new THREE.Group();var m=new THREE.Mesh(new THREE.CylinderGeometry(.2,.2,.03,24,1,false,0,Math.PI*1.4),new THREE.MeshStandardMaterial({color:col||0x8b5cf6,emissive:col||0x8b5cf6,emissiveIntensity:.3}));g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.2,.2,.03,24,1,false,Math.PI*1.4,Math.PI*.6),new THREE.MeshStandardMaterial({color:0x22d3ee,emissive:0x06b6d4,emissiveIntensity:.3}));g.add(m);g.rotation.x=Math.PI/2;g.position.y=y;return g}
function mkTablet(y,col){var g=new THREE.Group();var m=new THREE.Mesh(new THREE.BoxGeometry(.25,.35,.015),new THREE.MeshPhysicalMaterial({color:0x1a1a2e,metalness:.8,roughness:.1,clearcoat:1}));g.add(m);m=new THREE.Mesh(new THREE.PlaneGeometry(.2,.28),new THREE.MeshStandardMaterial({color:col||0x06b6d4,emissive:col||0x06b6d4,emissiveIntensity:.6,toneMapped:false}));m.position.z=.009;g.add(m);g.position.y=y;return g}
function mkFunnel(y){var g=new THREE.Group();var m=new THREE.Mesh(new THREE.CylinderGeometry(.2,.06,.3,12,1,true),new THREE.MeshPhysicalMaterial({color:0x64748b,metalness:.7,roughness:.15,transparent:true,opacity:.7}));g.add(m);g.position.y=y;return g}
function mkOrgChart(y){var g=new THREE.Group();var lm=new THREE.MeshBasicMaterial({color:0x94a3b8});var nm=new THREE.MeshStandardMaterial({color:0x334155,metalness:.5,roughness:.3});var m;m=new THREE.Mesh(new THREE.BoxGeometry(.12,.08,.02),nm);m.position.y=.12;g.add(m);m=new THREE.Mesh(new THREE.BoxGeometry(.12,.08,.02),nm);m.position.set(-.15,0,0);g.add(m);m=new THREE.Mesh(new THREE.BoxGeometry(.12,.08,.02),nm);m.position.set(.15,0,0);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.003,.003,.12,4),lm);m.position.set(0,.06,0);g.add(m);m=new THREE.Mesh(new THREE.CylinderGeometry(.003,.003,.3,4),lm);m.rotation.z=Math.PI/2;m.position.set(0,.02,0);g.add(m);g.position.y=y;return g}
function mkConveyor(y,len){var g=new THREE.Group();var cm=new THREE.MeshStandardMaterial({color:0x475569,metalness:.5,roughness:.4});var m=new THREE.Mesh(new THREE.BoxGeometry(len||1.5,.04,.2),cm);m.position.y=.08;g.add(m);for(var i=0;i<4;i++){m=new THREE.Mesh(new THREE.CylinderGeometry(.04,.04,.22,8),cm);m.rotation.x=Math.PI/2;m.position.set(-(len||1.5)/2+.2+i*((len||1.5)-.4)/3,.08,0);g.add(m)}for(var i=0;i<3;i++){m=new THREE.Mesh(new THREE.BoxGeometry(.12,.12,.12),new THREE.MeshStandardMaterial({color:0x8B6914,roughness:.6}));m.position.set(-.4+i*.4,.18,0);g.add(m)}g.position.y=y;return g}
function mkCalculator(y){var g=new THREE.Group();var m=new THREE.Mesh(new THREE.BoxGeometry(.15,.22,.02),new THREE.MeshPhysicalMaterial({color:0x1e293b,metalness:.6,roughness:.2}));g.add(m);m=new THREE.Mesh(new THREE.PlaneGeometry(.12,.06),new THREE.MeshStandardMaterial({color:0x4ade80,emissive:0x22c55e,emissiveIntensity:.5}));m.position.set(0,.06,.012);g.add(m);g.position.y=y;return g}
const T=[
{l:'DIRECTION',c:0x06b6d4,cs:'#06b6d4',y:12,w:8,d:5,a:[
{n:'Director',ds:'Cerveau autonome',st:'*/15min · 39 obs · 0 issues',t:'r',crown:1},{n:'Master Router',ds:'Routage intelligent',st:'46 routes · 14 providers',t:'r'}]},
{l:'ORCHESTRATION',c:0x8b5cf6,cs:'#8b5cf6',y:7,w:12,d:7,a:[
{n:'Consensus',ds:'Vote multi-provider',st:'3+ providers',t:'r'},{n:'Dispatcher',ds:'Moteur de routes',st:'46 routes',t:'r'},{n:'MiroFish',ds:'Auto-guérison',st:':5001',t:'r'},{n:'Blade',ds:'Agent desktop',st:'*/60s',t:'r'},{n:'Fiability',ds:'Santé URLs',st:'24 URLs',t:'r'},{n:'AutoFix',ds:'Docker heal',st:'16 containers',t:'r'}]},
{l:'SPÉCIALISTES',c:0xf59e0b,cs:'#f59e0b',y:1,w:18,d:10,a:[
{n:'DevOps',ds:'CI/CD',st:'4 serveurs',t:'h',sk:0xc68642,cl:0x2563eb,hc:0x2a1a0a},{n:'Ethica',ds:'HCP Pharma',st:'132K contacts',t:'h',sk:0xf5c6a5,cl:0x2563eb,hc:0x8B4513,f:1},{n:'Security',ds:'CVE+SSL',st:'Nuclei',t:'h',sk:0x8d5524,cl:0x2563eb,hc:0x0a0a0a},{n:'Monitor',ds:'Uptime 24/7',st:'25 URLs',t:'h',sk:0xffdbac,cl:0x2563eb,hc:0x654321,f:1},{n:'NonReg',ds:'Régression',st:'151/153',t:'h',sk:0xe0ac69,cl:0x2563eb,hc:0x1a1a1a},{n:'WEVCODE',ds:'Code IA',st:'4 modes',t:'h',sk:0xc68642,cl:0x2563eb,hc:0x4a2a0a,f:1},{n:'Scraper',ds:'DabaDoc',st:'MA+TN+DZ',t:'r'},{n:'L99 Pilot',ds:'Qualité',st:'236/239',t:'h',sk:0xffdbac,cl:0x2563eb,hc:0x8B6914},{n:'ArchScan',ds:'Topologie',st:'52 nœuds',t:'r'},{n:'Registry',ds:'Registre',st:'626 pages',t:'h',sk:0x8d5524,cl:0x2563eb,hc:0x0a0a0a,f:1}]},
{l:'EXÉCUTION',c:0xef4444,cs:'#ef4444',y:-6,w:22,d:12,a:[
{n:'Ollama',ds:'10 modèles LOCAL',st:'Souverain #1',t:'r'},{n:'Cerebras',ds:'<500ms',st:'Qwen-3 235B',t:'r'},{n:'Groq',ds:'<200ms',st:'Llama-3.3-70B',t:'r'},{n:'SambaNova',ds:'<800ms',st:'Meta-Llama',t:'r'},{n:'Qdrant',ds:'RAG vectors',st:'4 collections',t:'r'},{n:'Sentinel',ds:'Relais S95',st:'Port 5890',t:'r'},{n:'Docker',ds:'Containers',st:'16 actifs',t:'r'},{n:'PMTA',ds:'MTA sacré',st:'Port 25',t:'r'},{n:'Prometheus',ds:'Métriques',st:'Grafana',t:'r'},{n:'Paperclip',ds:'Fleet mgr',st:'669 agents',t:'r'},{n:'KumoMTA',ds:'Email smart',st:'587+8010',t:'r'},{n:'Postfix',ds:'Relay interne',st:'2525/2526',t:'r'}]}
];
const scene=new THREE.Scene();scene.fog=new THREE.FogExp2(0x050a18,.006);
const W=innerWidth,H=innerHeight;const cam=new THREE.PerspectiveCamera(28,W/H,.1,1000);cam.position.set(32,28,32);
const ren=new THREE.WebGLRenderer({antialias:true,powerPreference:'high-performance'});ren.setSize(W,H);ren.setPixelRatio(Math.min(devicePixelRatio,2));ren.toneMapping=THREE.ACESFilmicToneMapping;ren.toneMappingExposure=1.4;ren.outputColorSpace=THREE.SRGBColorSpace;document.body.appendChild(ren.domElement);
const composer=new EffectComposer(ren);composer.addPass(new RenderPass(scene,cam));composer.addPass(new UnrealBloomPass(new THREE.Vector2(W,H),.45,.35,.84));
const lr=new CSS2DRenderer();lr.setSize(W,H);lr.domElement.style.cssText='position:absolute;top:0;pointer-events:none';document.body.appendChild(lr.domElement);
const pmr=new THREE.PMREMGenerator(ren);scene.environment=pmr.fromScene(new RoomEnvironment(),.04).texture;scene.background=new THREE.Color(0x050a18);
const ctl=new OrbitControls(cam,ren.domElement);ctl.target.set(0,3,0);ctl.enableDamping=true;ctl.dampingFactor=.05;ctl.maxPolarAngle=Math.PI*.48;ctl.minPolarAngle=Math.PI*.08;ctl.autoRotate=true;ctl.autoRotateSpeed=.3;ctl.minDistance=20;ctl.maxDistance=70;ctl.update();
scene.add(new THREE.AmbientLight(0x334466,.5));let dl=new THREE.DirectionalLight(0xffffff,1.2);dl.position.set(15,25,12);scene.add(dl);
scene.add(new THREE.PointLight(0x06b6d4,.6,80)).position.set(-15,18,12);scene.add(new THREE.PointLight(0x8b5cf6,.4,80)).position.set(15,12,-12);scene.add(new THREE.PointLight(0xf59e0b,.3,70)).position.set(0,4,16);scene.add(new THREE.PointLight(0xffffff,.25,60)).position.set(0,18,-18);
function gMat(c){return new THREE.MeshPhysicalMaterial({color:new THREE.Color(0x0a1628),metalness:0,roughness:.05,transmission:.88,thickness:1.5,ior:1.45,clearcoat:1,clearcoatRoughness:.1,iridescence:.7,iridescenceIOR:1.3,iridescenceThicknessRange:[100,400],envMapIntensity:1.3,transparent:true,side:THREE.DoubleSide})}
const tp=document.getElementById('tp'),pM=[],cG=[],floats=[];
const hO=[0,.15,.3,.45,.6,.75,.1,.25,.4,.55,.7,.85];
T.forEach(function(t,ti){
let geo=new THREE.BoxGeometry(t.w,.22,t.d);let pm=new THREE.Mesh(geo,gMat(t.c));pm.position.y=t.y;scene.add(pm);pM.push(pm);
scene.add(new THREE.LineSegments(new THREE.EdgesGeometry(geo),new THREE.LineBasicMaterial({color:t.c,transparent:true,opacity:.35,linewidth:1}))).position.copy(pm.position);
let te=document.createElement('div');te.className='tl';te.style.color=t.cs;te.style.background=t.cs+'18';te.style.borderColor=t.cs+'40';te.innerHTML=t.l+'<span class="tc">'+t.a.length+'</span>';scene.add(new CSS2DObject(te)).position.set(0,t.y+2.5,0);
// === TIER ENVIRONMENT ===
if(ti===0){// DIRECTION - Command center
// World Map Screen (flat monitor style like reference)
var wms=new THREE.Group();wms.position.set(0,t.y+1.6,-1.5);scene.add(wms);
// Monitor frame
wms.add(new THREE.Mesh(new THREE.BoxGeometry(2,1.2,.04),new THREE.MeshPhysicalMaterial({color:0x0a0e1a,metalness:.9,roughness:.08,clearcoat:1})));
// Screen bg
var scr=new THREE.Mesh(new THREE.PlaneGeometry(1.85,1.05),new THREE.MeshStandardMaterial({color:0x0c1a2e}));scr.position.z=.025;wms.add(scr);
// Continents as multi-shape composites ON screen
var cm=new THREE.MeshStandardMaterial({color:0x94a3b8,emissive:0x64748b,emissiveIntensity:.4});
var c;
// N.America (2 shapes)
c=new THREE.Mesh(new THREE.PlaneGeometry(.18,.15),cm);c.position.set(-.6,.25,.03);wms.add(c);
c=new THREE.Mesh(new THREE.PlaneGeometry(.12,.2),cm);c.position.set(-.52,.12,.03);wms.add(c);
c=new THREE.Mesh(new THREE.PlaneGeometry(.06,.08),cm);c.position.set(-.45,.02,.03);wms.add(c);
// S.America (2 shapes)
c=new THREE.Mesh(new THREE.PlaneGeometry(.08,.12),cm);c.position.set(-.38,-.08,.03);wms.add(c);
c=new THREE.Mesh(new THREE.PlaneGeometry(.06,.14),cm);c.position.set(-.36,-.22,.03);wms.add(c);
// Europe (cluster)
c=new THREE.Mesh(new THREE.PlaneGeometry(.12,.06),cm);c.position.set(.06,.28,.03);wms.add(c);
c=new THREE.Mesh(new THREE.PlaneGeometry(.06,.08),cm);c.position.set(.14,.24,.03);wms.add(c);
c=new THREE.Mesh(new THREE.PlaneGeometry(.04,.06),cm);c.position.set(-.02,.22,.03);wms.add(c);
// Africa (tapered)
c=new THREE.Mesh(new THREE.PlaneGeometry(.14,.12),cm);c.position.set(.1,.08,.03);wms.add(c);
c=new THREE.Mesh(new THREE.PlaneGeometry(.1,.18),cm);c.position.set(.12,-.08,.03);wms.add(c);
c=new THREE.Mesh(new THREE.PlaneGeometry(.06,.08),cm);c.position.set(.14,-.22,.03);wms.add(c);
// Asia (spread)
c=new THREE.Mesh(new THREE.PlaneGeometry(.22,.12),cm);c.position.set(.35,.25,.03);wms.add(c);
c=new THREE.Mesh(new THREE.PlaneGeometry(.18,.14),cm);c.position.set(.48,.18,.03);wms.add(c);
c=new THREE.Mesh(new THREE.PlaneGeometry(.1,.08),cm);c.position.set(.55,.1,.03);wms.add(c);
c=new THREE.Mesh(new THREE.PlaneGeometry(.06,.12),cm);c.position.set(.3,.08,.03);wms.add(c);
// Japan/Korea
c=new THREE.Mesh(new THREE.PlaneGeometry(.03,.08),cm);c.position.set(.58,.22,.03);wms.add(c);
// Australia
c=new THREE.Mesh(new THREE.PlaneGeometry(.1,.07),cm);c.position.set(.55,-.18,.03);wms.add(c);
// Greenland
c=new THREE.Mesh(new THREE.PlaneGeometry(.06,.06),cm);c.position.set(-.35,.35,.03);wms.add(c);
// Connection dots (cyan glow)
var dm=new THREE.MeshStandardMaterial({color:0x06b6d4,emissive:0x06b6d4,emissiveIntensity:2,toneMapped:false});
[[-0.5,.15],[.08,.22],[.1,-.05],[.4,.18],[-.35,-.2]].forEach(function(p){var d=new THREE.Mesh(new THREE.CircleGeometry(.015,8),dm);d.position.set(p[0],p[1],.035);wms.add(d)});
// Grid lines
var lm=new THREE.LineBasicMaterial({color:0x1e3a5f,transparent:true,opacity:.3});
for(var gy=-.4;gy<=.4;gy+=.2){var pts=[new THREE.Vector3(-.9,gy,.03),new THREE.Vector3(.9,gy,.03)];wms.add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(pts),lm))}
// Stand
wms.add(new THREE.Mesh(new THREE.CylinderGeometry(.03,.04,.6,8),new THREE.MeshStandardMaterial({color:0x334155,metalness:.6})));
// WEVAL GLOBAL label
var wgDiv=document.createElement('div');wgDiv.style.cssText='pointer-events:none;color:#64748b;font:700 8px Orbitron';wgDiv.textContent='WEVAL GLOBAL';var wgObj=new CSS2DObject(wgDiv);wgObj.position.set(0,-.42,.03);wms.add(wgObj);
// 3D Compass - bigger, face camera
var compass=new THREE.Group();
var crm=new THREE.MeshPhysicalMaterial({color:0xd4af37,metalness:.95,roughness:.05,clearcoat:1});
// Outer ring
compass.add(new THREE.Mesh(new THREE.TorusGeometry(.45,.04,16,48),crm));
// Face - cream white
var cface=new THREE.Mesh(new THREE.CircleGeometry(.42,48),new THREE.MeshStandardMaterial({color:0xfff8e7,roughness:.5}));cface.position.z=.01;compass.add(cface);
// Degree marks around edge
for(var deg=0;deg<360;deg+=30){var mr=deg%90===0?.38:.35;var mk=new THREE.Mesh(new THREE.BoxGeometry(.008,deg%90===0?.06:.03,.002),new THREE.MeshStandardMaterial({color:0x1a1a2e}));mk.position.set(Math.sin(deg*Math.PI/180)*mr,Math.cos(deg*Math.PI/180)*mr,.015);mk.rotation.z=-deg*Math.PI/180;compass.add(mk)}
// N needle - red triangle
var nmat=new THREE.MeshStandardMaterial({color:0xdc2626,emissive:0xef4444,emissiveIntensity:.5});
var nn=new THREE.Mesh(new THREE.ConeGeometry(.04,.3,3),nmat);nn.position.set(0,.12,.02);compass.add(nn);
// S needle - blue
var sn=new THREE.Mesh(new THREE.ConeGeometry(.04,.3,3),new THREE.MeshStandardMaterial({color:0x2563eb}));sn.position.set(0,-.12,.02);sn.rotation.z=Math.PI;compass.add(sn);
// Center gold pin
compass.add(new THREE.Mesh(new THREE.SphereGeometry(.035,12,12),new THREE.MeshStandardMaterial({color:0xffd700,metalness:.95,roughness:.05})));
// N letter
var nDiv=document.createElement('div');nDiv.style.cssText='pointer-events:none;color:#dc2626;font:900 14px Orbitron';nDiv.textContent='N';var nObj=new CSS2DObject(nDiv);nObj.position.set(0,.32,.03);compass.add(nObj);
compass.position.set(2.5,t.y+1.2,-1);scene.add(compass);floats.push(compass);
let s1=mkDashScreen(.8,.5,t.y+1.2,0x22d3ee);s1.position.set(-2.8,t.y+1.2,0);s1.rotation.y=.5;scene.add(s1);
let s2=mkDashScreen(.8,.5,t.y+1.2,0x4ade80);s2.position.set(2.8,t.y+1.2,0);s2.rotation.y=-.5;scene.add(s2);
scene.add(mkPlant(t.y+.12)).position.set(-2.5,t.y+.12,-1.5);scene.add(mkPlant(t.y+.12)).position.set(2.5,t.y+.12,-1.5);
var tbl=new THREE.Mesh(new THREE.CylinderGeometry(.8,.8,.04,24),new THREE.MeshPhysicalMaterial({color:0x1e293b,metalness:.6,roughness:.2,clearcoat:.8}));tbl.position.set(0,t.y+.5,0);scene.add(tbl);
for(var ci=0;ci<6;ci++){var ca=ci*Math.PI*2/6;var chr=mkChair();chr.position.set(Math.cos(ca)*1.1,t.y+.12,Math.sin(ca)*1.1);chr.rotation.y=-ca+Math.PI;scene.add(chr)}
var tleg=new THREE.Mesh(new THREE.CylinderGeometry(.04,.06,.38,8),new THREE.MeshStandardMaterial({color:0x334155,metalness:.5}));tleg.position.set(0,t.y+.3,0);scene.add(tleg);
var lc=mkLineChart3D(0,0x4ade80,.6,.35);lc.position.set(2.8,t.y+.8,1.5);lc.rotation.y=-.4;scene.add(lc);floats.push(lc);var bc=mkBarChart(0,0x06b6d4);bc.position.set(2,t.y+.6,2);bc.scale.setScalar(1.5);scene.add(bc);floats.push(bc);
}
if(ti===1){// ORCHESTRATION - Control room with multi-screens
for(let i=-2;i<=2;i++){let s=mkScreen(.6,.35,[0x8b5cf6,0xa78bfa,0x7c3aed,0x6366f1,0x818cf8][i+2]);s.position.set(i*1.8,t.y+.8,-2.5);s.rotation.x=-.05;scene.add(s)}
scene.add(mkPlant(t.y+.12)).position.set(-4.5,t.y+.12,2.5);scene.add(mkPlant(t.y+.12)).position.set(4.5,t.y+.12,2.5);scene.add(mkWaterCooler(t.y+.12)).position.set(4.5,t.y+.12,-2);
var pc=mkPieChart(t.y+1,0x8b5cf6);pc.position.set(-4,t.y+1,2);pc.scale.setScalar(1.3);scene.add(pc);floats.push(pc);
var oc=mkOrgChart(t.y+.8);oc.position.set(0,t.y+.8,2.5);oc.scale.setScalar(2);scene.add(oc);floats.push(oc);
var lc2=mkLineChart3D(0,0x8b5cf6,.5,.3);lc2.position.set(4.5,t.y+.9,-2);lc2.rotation.y=-.3;scene.add(lc2);floats.push(lc2);var calc=mkCalculator(t.y+.8);calc.position.set(4,t.y+.8,2);calc.scale.setScalar(2);scene.add(calc);floats.push(calc);
[-4,4].forEach(function(x){let ch=mkChair();ch.position.set(x,t.y+.12,0);scene.add(ch)});
}
if(ti===2){// SPECIALISTS - Open office with workstations
let positions=[[-7,0,-3.5],[-4.5,0,-3.5],[-2,0,-3.5],[2,0,-3.5],[4.5,0,-3.5],[7,0,-3.5],[-5.5,0,3.5],[0,0,3.5],[5.5,0,3.5]];
positions.forEach(function(p,i){let ws=mkWorkstation([0x3b82f6,0xec4899,0x1e293b,0x059669,0x6366f1,0xf59e0b,0xef4444,0x0ea5e9,0xd946ef][i%9]);ws.position.set(p[0],t.y+.12,p[2]);if(p[2]>0)ws.rotation.y=Math.PI;scene.add(ws)});
scene.add(mkPlant(t.y+.12)).position.set(-8,t.y+.12,0);scene.add(mkPlant(t.y+.12)).position.set(8,t.y+.12,-2);scene.add(mkPlant(t.y+.12)).position.set(-3,t.y+.12,4);scene.add(mkPlant(t.y+.12)).position.set(3,t.y+.12,4);scene.add(mkPlant(t.y+.12)).position.set(-6,t.y+.12,4);scene.add(mkPlant(t.y+.12)).position.set(6,t.y+.12,4);scene.add(mkWaterCooler(t.y+.12)).position.set(-8,t.y+.12,3);
var cftbl=new THREE.Mesh(new THREE.CylinderGeometry(.4,.4,.03,16),new THREE.MeshPhysicalMaterial({color:0x4a3728,roughness:.5,metalness:.3}));cftbl.position.set(8,t.y+.42,3);scene.add(cftbl);var cftleg=new THREE.Mesh(new THREE.CylinderGeometry(.03,.04,.3,8),new THREE.MeshStandardMaterial({color:0x334155}));cftleg.position.set(8,t.y+.27,3);scene.add(cftleg);scene.add(mkCoffeeMachine(t.y+.12)).position.set(8.6,t.y+.12,3.5);
for(var ci=0;ci<3;ci++){var cha=mkChair();cha.position.set(8+Math.cos(ci*2.1)*.6,t.y+.12,3+Math.sin(ci*2.1)*.6);cha.rotation.y=-ci*2.1;scene.add(cha)};
var ds1=mkDashScreen(.5,.35,t.y+1,0xf59e0b);ds1.position.set(0,t.y+1,4.2);ds1.rotation.x=-.1;scene.add(ds1);
var tb1=mkTablet(t.y+.8,0xf59e0b);tb1.position.set(7.5,t.y+.8,-3);tb1.rotation.y=-.3;tb1.scale.setScalar(1.8);scene.add(tb1);floats.push(tb1);
var bc2=mkBarChart(0,0xf59e0b);bc2.position.set(-7.5,t.y+.6,-3);bc2.scale.setScalar(2);scene.add(bc2);floats.push(bc2);
var ccSign=document.createElement('div');ccSign.className='nl';ccSign.innerHTML='<div class="nm" style="color:#f59e0b">☕ Coffee Corner</div>';var ccObj=new CSS2DObject(ccSign);ccObj.position.set(-7.5,t.y+.8,3.5);scene.add(ccObj);
var cctbl=new THREE.Mesh(new THREE.CylinderGeometry(.5,.5,.03,16),new THREE.MeshPhysicalMaterial({color:0x4a3728,roughness:.5,metalness:.3}));cctbl.position.set(-7.5,t.y+.42,3);scene.add(cctbl);
var cctleg=new THREE.Mesh(new THREE.CylinderGeometry(.03,.04,.3,8),new THREE.MeshStandardMaterial({color:0x334155}));cctleg.position.set(-7.5,t.y+.27,3);scene.add(cctleg);
for(var cci=0;cci<4;cci++){var cch=mkChair();cch.position.set(-7.5+Math.cos(cci*1.57)*.7,t.y+.12,3+Math.sin(cci*1.57)*.7);cch.rotation.y=-cci*1.57;scene.add(cch)}
scene.add(mkPlant(t.y+.12)).position.set(-8.5,t.y+.12,3.5);scene.add(mkPlant(t.y+.12)).position.set(-6.5,t.y+.12,3.5);
let cf=mkCoffeeMachine();cf.position.set(8,t.y+.12,0);scene.add(cf);
}
if(ti===3){// EXECUTION - Server room
for(let row=-1;row<=1;row+=2){for(let i=-8;i<=8;i+=2){let sr=mkServerRack();sr.position.set(i,t.y+.12,row*4.5);if(row>0)sr.rotation.y=Math.PI;scene.add(sr)}}
// Monitoring screens at ends
scene.add(mkPlant(t.y+.12)).position.set(-10,t.y+.12,0);scene.add(mkPlant(t.y+.12)).position.set(10,t.y+.12,0);scene.add(mkPlant(t.y+.12)).position.set(-10,t.y+.12,3);scene.add(mkPlant(t.y+.12)).position.set(10,t.y+.12,3);scene.add(mkPlant(t.y+.12)).position.set(-10,t.y+.12,-3);scene.add(mkPlant(t.y+.12)).position.set(10,t.y+.12,-3);
var sc1=mkServerCage(t.y+.12,1.2,.5);sc1.position.set(-7,t.y+.12,0);scene.add(sc1);var sc2=mkServerCage(t.y+.12,1.2,.5);sc2.position.set(7,t.y+.12,0);scene.add(sc2);
var ds2=mkDashScreen(.6,.4,t.y+1.2,0xef4444);ds2.position.set(0,t.y+1.2,-4.2);scene.add(ds2);var ds3=mkDashScreen(.4,.3,t.y+1,0x4ade80);ds3.position.set(-5,t.y+1,-4.2);scene.add(ds3);var ds4=mkDashScreen(.4,.3,t.y+1,0x3b82f6);ds4.position.set(5,t.y+1,-4.2);scene.add(ds4);
var cv1=mkConveyor(t.y+.12,3);cv1.position.set(0,t.y+.12,1.5);scene.add(cv1);
var cv2=mkConveyor(t.y+.12,2.5);cv2.position.set(0,t.y+.12,-1.5);scene.add(cv2);
let ms1=mkBigScreen(1.5,1,0xef4444);ms1.position.set(-9,t.y+1.2,0);ms1.rotation.y=.4;scene.add(ms1);
let ms2=mkBigScreen(1.5,1,0x4ade80);ms2.position.set(9,t.y+1.2,0);ms2.rotation.y=-.4;scene.add(ms2);
}
// === AGENTS ===
const n=t.a.length,cols=Math.min(n,ti===0?2:ti===1?3:ti===2?5:6),rows=Math.ceil(n/cols);
t.a.forEach(function(a,ai){
const row=Math.floor(ai/cols),col=ai%cols,cir=(row<rows-1)?cols:(n-row*cols);
const xs=(t.w*.7)/Math.max(cir,1),zs=(t.d*.45)/Math.max(rows,1);
const x=(col-(cir-1)/2)*xs,z=(row-(rows-1)/2)*zs;
let ch;
if(a.t==='r'){const hsl={h:0,s:0,l:0};new THREE.Color(t.c).getHSL(hsl);var rc=new THREE.Color().setHSL((hsl.h+hO[ai%12])%1,.7,.45);var ac2=new THREE.Color().setHSL((hsl.h+hO[(ai+3)%12])%1,.8,.55);ch=mkRobot(rc,ac2)}
else{ch=mkHuman(a.sk||0xf5c6a5,a.cl||0x3b82f6,a.hc||0x1a1a2e,a.f)}
ch.position.set(x,t.y+.12,z);ch.scale.setScalar(1.1);if(a.t!=='r'){scene.add(ch);cG.push({g:ch,ai:ai})};
var skHex=a.sk?a.sk.toString(16).padStart(6,'0'):'f5c6a5';
var headUrl=a.t==='r'?'https://robohash.org/'+encodeURIComponent(a.n)+'?set=set1&size=256x256':'https://api.dicebear.com/9.x/adventurer/svg?seed='+encodeURIComponent(a.n)+'&skinColor='+skHex;
var hDiv=document.createElement('div');
hDiv.style.cssText='pointer-events:none;filter:drop-shadow(0 2px 8px rgba(0,0,0,.6))';
hDiv.innerHTML='<img src="'+headUrl+'" style="width:48px;height:48px;border-radius:50%;border:none;background:transparent;object-fit:contain" loading="lazy">';
var hObj=new CSS2DObject(hDiv);if(a.t==='r'){hObj.position.set(x,t.y+1.15,z);scene.add(hObj)}else{hObj.position.set(0,1.1,0);ch.add(hObj)};
if(a.crown){const crm=new THREE.MeshStandardMaterial({color:0xffd700,metalness:.95,roughness:.05,emissive:0xffa500,emissiveIntensity:.4});const cg=new THREE.Group();let mm=new THREE.Mesh(new THREE.CylinderGeometry(.2,.24,.14,8),crm);cg.add(mm);[-0.13,0,.13].forEach(function(px){mm=new THREE.Mesh(new THREE.ConeGeometry(.05,.12,5),crm);mm.position.set(px,.13,0);cg.add(mm)});cg.position.y=1.65;ch.add(cg)}
let ne=document.createElement('div');ne.className='nl';ne.innerHTML='<div class="nm">'+a.n+'</div>';ne.style.pointerEvents='auto';
ne.addEventListener('mouseenter',function(e){tp.querySelector('b').textContent=a.n;tp.querySelector('.s').textContent=a.ds;tp.querySelector('.dt').textContent=a.st;const tb=tp.querySelector('.tb');tb.textContent=a.t==='h'?'👤 Opérateur':'🤖 Agent IA';tb.style.background=a.t==='h'?'rgba(245,158,11,.15)':'rgba(6,182,212,.15)';tb.style.color=a.t==='h'?'#f59e0b':'#06b6d4';tp.style.display='block';tp.style.borderColor=t.cs;tp.querySelector('b').style.color=t.cs});
ne.addEventListener('mousemove',function(e){tp.style.left=Math.min(e.clientX+14,innerWidth-240)+'px';tp.style.top=(e.clientY-120)+'px'});
ne.addEventListener('mouseleave',function(){tp.style.display='none'});
scene.add(new CSS2DObject(ne)).position.set(x,t.y-.5,z);
});
});
// Robotic arms on every tier (cron automation)
// Robotic arms only on Execution tier
// Robot arms as Icons8 3D sprites on Execution tier
[-1,1].forEach(function(sx){
[-1,0,1].forEach(function(sz){
var armDiv=document.createElement('div');
armDiv.style.cssText='pointer-events:none';
armDiv.innerHTML='<img src="https://img.icons8.com/3d-fluency/94/robot-2.png" style="width:60px;height:60px" loading="lazy">';
var armObj=new CSS2DObject(armDiv);
armObj.position.set(sx*(T[3].w/2-1.5),T[3].y+.5,sz*2.5);
scene.add(armObj);
});
});
// Teleporter in center (beam between all tiers)
var tpGeo=new THREE.CylinderGeometry(.15,.15,T[0].y-T[T.length-1].y+2,16,1,true);
var tpMat=new THREE.MeshBasicMaterial({color:0x06b6d4,transparent:true,opacity:.08,side:THREE.DoubleSide});
var tpMesh=new THREE.Mesh(tpGeo,tpMat);tpMesh.position.y=(T[0].y+T[T.length-1].y)/2;scene.add(tpMesh);
// Teleporter rings
T.forEach(function(t){var ring=new THREE.Mesh(new THREE.TorusGeometry(.2,.02,8,24),new THREE.MeshStandardMaterial({color:0x06b6d4,emissive:0x06b6d4,emissiveIntensity:1.5,toneMapped:false}));ring.rotation.x=Math.PI/2;ring.position.y=t.y+.12;scene.add(ring);floats.push(ring)});
// Coffee corner on each tier
T.forEach(function(t,ti){
var cx=t.w/2-1.5,cz=-t.d/2+1;
var ctbl=new THREE.Mesh(new THREE.CylinderGeometry(.35,.35,.03,12),new THREE.MeshPhysicalMaterial({color:0x4a3728,roughness:.5,metalness:.2}));ctbl.position.set(cx,t.y+.35,cz);scene.add(ctbl);
var cleg=new THREE.Mesh(new THREE.CylinderGeometry(.025,.035,.23,6),new THREE.MeshStandardMaterial({color:0x334155}));cleg.position.set(cx,t.y+.23,cz);scene.add(cleg);
// Coffee cups
for(var ci=0;ci<2;ci++){var cup=new THREE.Mesh(new THREE.CylinderGeometry(.02,.015,.04,8),new THREE.MeshStandardMaterial({color:0xffffff,roughness:.4}));cup.position.set(cx-.08+ci*.16,t.y+.38,cz);scene.add(cup)}
// Plant next to coffee
scene.add(mkPlant(t.y+.12)).position.set(cx+.5,t.y+.12,cz);
scene.add(mkPlant(t.y+.12)).position.set(cx-.5,t.y+.12,cz);
});
for(let i=0;i<T.length-1;i++){const y1=T[i].y,y2=T[i+1].y,h=Math.abs(y1-y2);const bg=new THREE.CylinderGeometry(.05,.05,h,8);const bm=new THREE.MeshBasicMaterial({color:T[i+1].c,transparent:true,opacity:.2});scene.add(new THREE.Mesh(bg,bm)).position.set(0,(y1+y2)/2,0);[-1,1].forEach(function(s){let b2=new THREE.Mesh(bg.clone(),bm.clone());b2.material.opacity=.1;b2.position.set(s*T[i].w*.35,(y1+y2)/2,0);scene.add(b2)})}
const pC=400,pG=new THREE.BufferGeometry(),pP=new Float32Array(pC*3);for(let i=0;i<pC;i++){pP[i*3]=(Math.random()-.5)*70;pP[i*3+1]=(Math.random()-.5)*55;pP[i*3+2]=(Math.random()-.5)*70}pG.setAttribute('position',new THREE.BufferAttribute(pP,3));scene.add(new THREE.Points(pG,new THREE.PointsMaterial({color:0x06b6d4,size:.04,transparent:true,opacity:.25,sizeAttenuation:true})));
// === SUN/MOON ORBIT ===
var hr=new Date().getHours()+new Date().getMinutes()/60;
var sunAngle=(hr/24)*Math.PI*2-Math.PI/2;
var orbitR=22,orbitY=18;
// Sun
var sunGeo=new THREE.SphereGeometry(1.2,32,32);
var sunMat=new THREE.MeshStandardMaterial({color:0xffd700,emissive:0xff8c00,emissiveIntensity:3,toneMapped:false});
var sun=new THREE.Mesh(sunGeo,sunMat);
sun.position.set(Math.cos(sunAngle)*orbitR,orbitY+Math.sin(sunAngle)*8,0);
scene.add(sun);
// Sun glow
var sunGlow=new THREE.Mesh(new THREE.SphereGeometry(2,16,16),new THREE.MeshBasicMaterial({color:0xffa500,transparent:true,opacity:.15}));
sunGlow.position.copy(sun.position);scene.add(sunGlow);
// Sun light that follows
var sunLight=new THREE.PointLight(0xffd700,Math.max(0,Math.sin(sunAngle))*1.5,60);
sunLight.position.copy(sun.position);scene.add(sunLight);
// Moon (opposite side)
var moonMat=new THREE.MeshStandardMaterial({color:0xdbeafe,emissive:0x93c5fd,emissiveIntensity:1.5,toneMapped:false});
var moon=new THREE.Mesh(new THREE.SphereGeometry(.6,24,24),moonMat);
moon.position.set(Math.cos(sunAngle+Math.PI)*orbitR,orbitY+Math.sin(sunAngle+Math.PI)*8,0);
scene.add(moon);
// Moon craters
[.15,-.1,.08,-.2,.12].forEach(function(o,i){
var cr=new THREE.Mesh(new THREE.SphereGeometry(.08+i*.02,8,8),new THREE.MeshStandardMaterial({color:0xbfdbfe,roughness:.9}));
cr.position.set(o,.1-i*.06,.55);moon.add(cr);
});
// Orbit ring (visual path)
var orbitPts=[];for(var a=0;a<=360;a+=5){orbitPts.push(new THREE.Vector3(Math.cos(a*Math.PI/180)*orbitR,orbitY+Math.sin(a*Math.PI/180)*8,0))}
var orbitLine=new THREE.Line(new THREE.BufferGeometry().setFromPoints(orbitPts),new THREE.LineBasicMaterial({color:0x334155,transparent:true,opacity:.15}));
scene.add(orbitLine);
// Stars (only visible above)
for(var i=0;i<200;i++){var star=new THREE.Mesh(new THREE.SphereGeometry(.03+Math.random()*.04,4,4),new THREE.MeshBasicMaterial({color:0xffffff,transparent:true,opacity:.2+Math.random()*.4}));star.position.set((Math.random()-.5)*80,15+Math.random()*25,(Math.random()-.5)*80);scene.add(star)}
const clk=new THREE.Clock();
function anim(){requestAnimationFrame(anim);const t=clk.getElapsedTime();ctl.update();pM.forEach(function(m,i){m.position.y=T[i].y+Math.sin(t*.6+i)*.03});cG.forEach(function(c){c.g.rotation.y=Math.sin(t*.35+c.ai*1.3)*.1});
if(typeof compass!=='undefined')compass.lookAt(cam.position);
var sa=sunAngle+t*.02;sun.position.set(Math.cos(sa)*orbitR,orbitY+Math.sin(sa)*8,Math.sin(sa)*5);sunGlow.position.copy(sun.position);sunLight.position.copy(sun.position);sunLight.intensity=Math.max(0,Math.sin(sa))*1.5;
moon.position.set(Math.cos(sa+Math.PI)*orbitR,orbitY+Math.sin(sa+Math.PI)*8,Math.sin(sa+Math.PI)*5);moon.rotation.y+=.003;sun.visible=Math.sin(sa)>-.2;moon.visible=Math.sin(sa)<.2;sunGlow.visible=sun.visible;sunLight.intensity=sun.visible?Math.max(0,Math.sin(sa))*1.5:0;
var dayFactor=Math.max(0,Math.sin(sa));scene.background.setRGB(.02+dayFactor*.93,.04+dayFactor*.9,.1+dayFactor*.82);
floats.forEach(function(f,i){f.position.y+=Math.sin(t*1.2+i*2.1)*.0008;f.rotation.y+=.003});composer.render();lr.render(scene,cam)}
window.addEventListener('resize',function(){const w=innerWidth,h=innerHeight;cam.aspect=w/h;cam.updateProjectionMatrix();ren.setSize(w,h);lr.setSize(w,h);composer.setSize(w,h)});
(async function(){try{const f=await fetch('/api/wevia-fiability.php?report').then(function(r){return r.json()});document.getElementById('hFi').textContent=(f.score||'?')+'%'}catch(e){document.getElementById('hFi').textContent='100%'}})();
document.getElementById('ld').style.display='none';anim();
</script></body></html>