Paritosh Upadhyay
Neural Stabilization: Fixed structural decoupling and indentation
8c88e2a
Raw
History Blame Contribute Delete
57.6 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JARVIS β€” Neural Intelligence Interface v2</title>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700;900&family=Rajdhani:wght@300;400;500;600&family=Share+Tech+Mono&display=swap" rel="stylesheet">
<!-- MediaPipe -->
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/hands/hands.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/drawing_utils/drawing_utils.js" crossorigin="anonymous"></script>
<style>
:root {
--void:#00000a;--deep:#020510;--panel:rgba(0,15,40,0.75);--glass:rgba(0,180,255,0.04);
--cyan:#00d4ff;--cyan2:#00aaff;--gold:#f0a500;--gold2:#ffcc44;
--green:#00ff88;--red:#ff3366;--white:#e8f4ff;--dim:rgba(0,212,255,0.4);
--border:rgba(0,212,255,0.15);--border2:rgba(0,212,255,0.08);
--purple:#cc66ff;--orange:#ff6644;
--glow-c:0 0 20px rgba(0,212,255,.5),0 0 60px rgba(0,212,255,.2);
--glow-g:0 0 20px rgba(240,165,0,.5),0 0 60px rgba(240,165,0,.2);
--font-d:'Orbitron',monospace;--font-b:'Rajdhani',sans-serif;--font-m:'Share Tech Mono',monospace;
}
*{margin:0;padding:0;box-sizing:border-box;}
body{background:var(--void);color:var(--white);font-family:var(--font-b);min-height:100vh;overflow-x:hidden;cursor:crosshair;}
body::after{content:'';position:fixed;inset:0;z-index:999;pointer-events:none;
background:repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(0,0,0,.025) 2px,rgba(0,0,0,.025) 4px);}
#starfield{position:fixed;inset:0;z-index:0;pointer-events:none;}
/* LAYOUT */
#app{position:relative;z-index:1;display:grid;grid-template-rows:60px 1fr;grid-template-columns:260px 1fr 260px;height:100vh;}
/* HEADER */
header{grid-column:1/-1;display:flex;align-items:center;justify-content:space-between;padding:0 20px;
border-bottom:1px solid var(--border);background:rgba(0,5,20,.95);backdrop-filter:blur(20px);z-index:100;position:relative;}
header::after{content:'';position:absolute;bottom:-2px;left:0;right:0;height:1px;
background:linear-gradient(90deg,transparent,var(--cyan),var(--gold),var(--cyan),transparent);
animation:hglow 3s ease-in-out infinite;}
@keyframes hglow{0%,100%{opacity:.4}50%{opacity:1}}
.logo{font-family:var(--font-d);font-size:20px;font-weight:900;letter-spacing:8px;
background:linear-gradient(135deg,var(--cyan),var(--gold));-webkit-background-clip:text;
-webkit-text-fill-color:transparent;background-clip:text;filter:drop-shadow(0 0 10px rgba(0,212,255,.5));}
.hcenter{display:flex;align-items:center;gap:24px;}
.sdot{width:8px;height:8px;border-radius:50%;background:var(--green);box-shadow:0 0 10px var(--green);animation:pulse 2s ease-in-out infinite;}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.5;transform:scale(.8)}}
.stext{font-family:var(--font-m);font-size:10px;color:var(--green);letter-spacing:2px;text-transform:uppercase;}
.htime{font-family:var(--font-m);font-size:12px;color:var(--dim);letter-spacing:1px;}
.hright{display:flex;align-items:center;gap:10px;}
.hbtn{font-family:var(--font-d);font-size:8px;letter-spacing:2px;padding:5px 12px;border:1px solid var(--border);
background:var(--glass);color:var(--dim);cursor:pointer;transition:all .3s;text-transform:uppercase;}
.hbtn:hover,.hbtn.on{border-color:var(--cyan);color:var(--cyan);background:rgba(0,212,255,.08);box-shadow:var(--glow-c);}
.hbtn.danger{border-color:rgba(255,51,102,.3);color:rgba(255,51,102,.6);}
.hbtn.danger:hover{border-color:var(--red);color:var(--red);}
/* PANELS */
.pleft,.pright{border-right:1px solid var(--border2);background:rgba(0,8,25,.65);backdrop-filter:blur(10px);
padding:16px 14px;display:flex;flex-direction:column;gap:14px;overflow-y:auto;}
.pright{border-right:none;border-left:1px solid var(--border2);}
/* WIDGET */
.w{border:1px solid var(--border2);background:var(--panel);padding:12px;position:relative;overflow:hidden;}
.w::before{content:'';position:absolute;top:0;left:0;right:0;height:1px;
background:linear-gradient(90deg,transparent,var(--cyan),transparent);opacity:.35;}
.wtitle{font-family:var(--font-d);font-size:7.5px;letter-spacing:3px;color:var(--dim);text-transform:uppercase;
margin-bottom:10px;display:flex;align-items:center;gap:7px;}
.wtitle::before{content:'';width:3px;height:9px;background:var(--cyan);box-shadow:0 0 6px var(--cyan);}
.wtitle.gold::before{background:var(--gold);box-shadow:0 0 6px var(--gold);}
.wtitle.red::before{background:var(--red);box-shadow:0 0 6px var(--red);}
.wtitle.purple::before{background:var(--purple);box-shadow:0 0 6px var(--purple);}
/* METRIC */
.mrow{display:flex;justify-content:space-between;align-items:center;padding:5px 0;border-bottom:1px solid var(--border2);}
.mrow:last-child{border:none;}
.mlabel{font-family:var(--font-m);font-size:9px;color:rgba(232,244,255,.4);letter-spacing:1px;}
.mval{font-family:var(--font-m);font-size:11px;color:var(--cyan);}
.mval.g{color:var(--green)}.mval.gold{color:var(--gold)}.mval.r{color:var(--red)}.mval.p{color:var(--purple)}
/* BAR */
.brow{display:flex;align-items:center;gap:7px;margin-bottom:5px;}
.blabel{font-family:var(--font-m);font-size:8px;color:rgba(232,244,255,.4);width:55px;text-align:right;flex-shrink:0;}
.btrack{flex:1;height:3px;background:rgba(0,212,255,.08);position:relative;overflow:hidden;}
.bfill{height:100%;background:linear-gradient(90deg,var(--cyan2),var(--cyan));box-shadow:0 0 6px var(--cyan);
animation:bin 1.5s ease-out forwards;transform-origin:left;}
@keyframes bin{from{transform:scaleX(0)}to{transform:scaleX(1)}}
.bval{font-family:var(--font-m);font-size:8px;color:var(--dim);width:26px;flex-shrink:0;}
/* LOG */
.litem{padding:5px 0;border-bottom:1px solid var(--border2);display:flex;flex-direction:column;gap:2px;}
.litem:last-child{border:none;}
.ltime{font-family:var(--font-m);font-size:8px;color:var(--gold);opacity:.7;}
.ltext{font-size:10px;color:rgba(232,244,255,.55);line-height:1.4;}
/* CONTACT */
.citem{display:flex;align-items:center;gap:9px;padding:6px 0;border-bottom:1px solid var(--border2);cursor:pointer;transition:all .2s;}
.citem:hover{padding-left:4px;background:rgba(0,212,255,.03);}
.cavatar{width:26px;height:26px;border:1px solid var(--border);background:rgba(0,212,255,.1);
display:flex;align-items:center;justify-content:center;font-family:var(--font-d);font-size:9px;color:var(--cyan);flex-shrink:0;}
.cname{font-size:11px;color:var(--white);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.crole{font-size:9px;color:rgba(232,244,255,.35);}
.csdot{width:5px;height:5px;border-radius:50%;flex-shrink:0;}
.online{background:var(--green);box-shadow:0 0 5px var(--green);}
.away{background:var(--gold);box-shadow:0 0 5px var(--gold);}
.offline{background:rgba(255,255,255,.15);}
/* VITALS */
.vgrid{display:grid;grid-template-columns:1fr 1fr;gap:7px;}
.vcard{border:1px solid var(--border2);padding:8px;background:rgba(0,10,30,.5);text-align:center;}
.vnum{font-family:var(--font-d);font-size:18px;font-weight:700;line-height:1;}
.vnum.c{color:var(--cyan);text-shadow:0 0 10px rgba(0,212,255,.5);}
.vnum.g{color:var(--gold);text-shadow:0 0 10px rgba(240,165,0,.5);}
.vnum.gr{color:var(--green);text-shadow:0 0 10px rgba(0,255,136,.5);}
.vnum.o{color:#ff8844;text-shadow:0 0 10px rgba(255,136,68,.5);}
.vlbl{font-family:var(--font-m);font-size:7px;color:rgba(232,244,255,.3);letter-spacing:2px;margin-top:3px;text-transform:uppercase;}
/* DEALER */
.drow{display:grid;grid-template-columns:1fr auto auto;gap:7px;align-items:center;padding:5px 0;border-bottom:1px solid var(--border2);font-size:10px;}
.drow:last-child{border:none;}
.dname{color:var(--white);font-weight:500;}
.dcalls{font-family:var(--font-m);color:var(--cyan);font-size:11px;}
.dbadge{font-family:var(--font-m);font-size:7px;padding:2px 5px;letter-spacing:1px;}
.hot{background:rgba(255,51,102,.12);color:var(--red);border:1px solid rgba(255,51,102,.25);}
.ok{background:rgba(0,255,136,.08);color:var(--green);border:1px solid rgba(0,255,136,.18);}
.low{background:rgba(240,165,0,.08);color:var(--gold);border:1px solid rgba(240,165,0,.18);}
/* CENTER */
.maincenter{display:flex;flex-direction:column;align-items:center;padding:16px;gap:16px;overflow-y:auto;position:relative;}
/* ORB */
.orbsec{display:flex;flex-direction:column;align-items:center;gap:12px;width:100%;}
.orbwrap{position:relative;width:200px;height:200px;display:flex;align-items:center;justify-content:center;cursor:pointer;}
.orbring{position:absolute;border-radius:50%;border:1px solid rgba(0,212,255,.12);animation:rr 12s linear infinite;}
.orbring:nth-child(1){width:192px;height:192px;animation-duration:20s;}
.orbring:nth-child(2){width:174px;height:174px;border-color:rgba(0,212,255,.18);animation-duration:14s;animation-direction:reverse;}
.orbring:nth-child(3){width:155px;height:155px;border-color:rgba(240,165,0,.1);animation-duration:9s;}
.orbring::after{content:'';position:absolute;width:5px;height:5px;border-radius:50%;background:var(--cyan);
box-shadow:0 0 8px var(--cyan);top:-2.5px;left:50%;transform:translateX(-50%);}
.orbring:nth-child(2)::after{background:var(--gold);box-shadow:0 0 8px var(--gold);}
.orbring:nth-child(3)::after{width:3px;height:3px;top:-1.5px;}
@keyframes rr{from{transform:rotate(0)}to{transform:rotate(360deg)}}
.orbcore{position:relative;width:136px;height:136px;border-radius:50%;z-index:10;}
.orbsphere{width:100%;height:100%;border-radius:50%;
background:radial-gradient(circle at 35% 35%,rgba(0,212,255,.9),rgba(0,80,160,.8) 50%,rgba(0,10,40,.95) 80%);
box-shadow:0 0 35px rgba(0,212,255,.4),0 0 70px rgba(0,212,255,.15),inset 0 0 25px rgba(0,0,0,.5);
position:relative;overflow:hidden;animation:idle 4s ease-in-out infinite;}
@keyframes idle{0%,100%{box-shadow:0 0 35px rgba(0,212,255,.4),0 0 70px rgba(0,212,255,.15),inset 0 0 25px rgba(0,0,0,.5)}
50%{box-shadow:0 0 55px rgba(0,212,255,.6),0 0 110px rgba(0,212,255,.25),inset 0 0 25px rgba(0,0,0,.5)}}
.orbsphere.speaking{animation:spk .12s ease-in-out infinite alternate;
background:radial-gradient(circle at 35% 35%,rgba(0,255,150,.9),rgba(0,180,100,.8) 50%,rgba(0,20,10,.95) 80%);}
@keyframes spk{0%{transform:scale(1);box-shadow:0 0 35px rgba(0,255,150,.5)}100%{transform:scale(1.07);box-shadow:0 0 65px rgba(0,255,150,.9),0 0 130px rgba(0,255,150,.3)}}
.orbsphere.listening{animation:lst .8s ease-in-out infinite alternate;
background:radial-gradient(circle at 35% 35%,rgba(255,180,0,.9),rgba(200,100,0,.8) 50%,rgba(20,5,0,.95) 80%);}
@keyframes lst{0%{transform:scale(.97);box-shadow:0 0 28px rgba(240,165,0,.5)}100%{transform:scale(1.04);box-shadow:0 0 56px rgba(240,165,0,.8),0 0 110px rgba(240,165,0,.3)}}
.orbsphere.thinking{animation:thk 1.4s ease-in-out infinite;
background:radial-gradient(circle at 35% 35%,rgba(150,0,255,.9),rgba(80,0,180,.8) 50%,rgba(10,0,30,.95) 80%);}
@keyframes thk{0%{transform:rotate(0) scale(1);box-shadow:0 0 35px rgba(150,0,255,.5)}
25%{transform:rotate(5deg) scale(1.04)}75%{transform:rotate(-5deg) scale(.97)}
100%{transform:rotate(0) scale(1);box-shadow:0 0 75px rgba(150,0,255,.7)}}
.orbsphere::before{content:'';position:absolute;width:55%;height:28%;top:14%;left:20%;
background:radial-gradient(ellipse,rgba(255,255,255,.15),transparent 70%);border-radius:50%;transform:rotate(-20deg);}
.orbwave{position:absolute;bottom:25px;left:16px;right:16px;height:32px;opacity:.7;pointer-events:none;}
.orbslabel{font-family:var(--font-d);font-size:8px;letter-spacing:4px;color:var(--dim);text-align:center;text-transform:uppercase;transition:color .3s;}
.orbctrl{display:flex;gap:10px;flex-wrap:wrap;justify-content:center;}
.obtn{font-family:var(--font-d);font-size:7px;letter-spacing:2px;padding:7px 13px;border:1px solid var(--border);
background:var(--glass);color:var(--dim);cursor:pointer;transition:all .3s;text-transform:uppercase;}
.obtn:hover{border-color:var(--cyan);color:var(--cyan);box-shadow:var(--glow-c);}
.obtn.as{border-color:var(--green);color:var(--green);box-shadow:0 0 18px rgba(0,255,136,.4);}
.obtn.al{border-color:var(--gold);color:var(--gold);box-shadow:var(--glow-g);}
.obtn.at{border-color:#9900ff;color:var(--purple);box-shadow:0 0 18px rgba(150,0,255,.4);}
/* TRANSCRIPT */
.tbox{width:100%;max-width:580px;border:1px solid var(--border2);background:rgba(0,5,20,.85);padding:12px 16px;min-height:60px;position:relative;}
.tbox::before{content:'// NEURAL OUTPUT';position:absolute;top:-8px;left:14px;font-family:var(--font-m);
font-size:8px;color:var(--dim);background:var(--deep);padding:0 7px;letter-spacing:2px;}
#ttext{font-family:var(--font-m);font-size:12px;color:var(--white);line-height:1.6;opacity:.9;}
.cur{display:inline-block;width:7px;height:12px;background:var(--cyan);margin-left:2px;animation:blink 1s step-end infinite;vertical-align:middle;}
@keyframes blink{0%,100%{opacity:1}50%{opacity:0}}
/* CMD */
.cmdbar{width:100%;max-width:580px;display:flex;border:1px solid var(--border);background:rgba(0,5,20,.9);}
.cmdinput{flex:1;background:transparent;border:none;outline:none;padding:10px 14px;font-family:var(--font-m);font-size:12px;color:var(--white);letter-spacing:.5px;}
.cmdinput::placeholder{color:rgba(0,212,255,.2);}
.cmdgo{padding:0 18px;background:rgba(0,212,255,.08);border:none;border-left:1px solid var(--border);
color:var(--cyan);font-family:var(--font-d);font-size:8px;letter-spacing:2px;cursor:pointer;transition:all .3s;text-transform:uppercase;}
.cmdgo:hover{background:rgba(0,212,255,.18);box-shadow:var(--glow-c);}
/* BRAIN */
.brainsec{width:100%;max-width:580px;border:1px solid var(--border2);background:rgba(0,5,20,.85);}
.brainhead{display:flex;align-items:center;justify-content:space-between;padding:9px 13px;border-bottom:1px solid var(--border2);}
.braintitle{font-family:var(--font-d);font-size:7.5px;letter-spacing:3px;color:var(--dim);text-transform:uppercase;display:flex;align-items:center;gap:7px;}
.braintitle::before{content:'';width:3px;height:9px;background:var(--gold);box-shadow:0 0 5px var(--gold);}
.zoomBtn{font-family:var(--font-d);font-size:7px;letter-spacing:2px;padding:4px 9px;border:1px solid var(--border);
background:transparent;color:var(--dim);cursor:pointer;transition:all .3s;}
.zoomBtn:hover{border-color:var(--gold);color:var(--gold);box-shadow:var(--glow-g);}
#brainMini{display:block;width:100%;height:180px;cursor:crosshair;}
/* AVATAR SECTION */
.avatarsec{width:100%;max-width:580px;border:1px solid var(--border2);background:rgba(0,5,20,.85);position:relative;}
.avatarhead{display:flex;align-items:center;justify-content:space-between;padding:9px 13px;border-bottom:1px solid var(--border2);}
.avatartitle{font-family:var(--font-d);font-size:7.5px;letter-spacing:3px;color:var(--purple);text-transform:uppercase;
display:flex;align-items:center;gap:7px;}
.avatartitle::before{content:'';width:3px;height:9px;background:var(--purple);box-shadow:0 0 5px var(--purple);}
.avatar-body{display:flex;gap:0;position:relative;}
#avatarCanvas{flex:1;height:380px;cursor:crosshair;}
.avatar-rightpanel{width:180px;flex-shrink:0;border-left:1px solid var(--border2);padding:12px;
display:flex;flex-direction:column;gap:8px;overflow-y:auto;background:rgba(0,5,20,.5);}
.modpill{padding:7px 10px;border:1px solid var(--border2);cursor:pointer;transition:all .3s;position:relative;overflow:hidden;}
.modpill::after{content:'';position:absolute;inset:0;background:linear-gradient(135deg,rgba(0,212,255,.06),transparent);opacity:0;transition:opacity .3s;}
.modpill:hover::after,.modpill.active::after{opacity:1;}
.modpill:hover,.modpill.active{border-color:var(--cyan);}
.modpill.active{background:rgba(0,212,255,.06);}
.modpill-name{font-family:var(--font-d);font-size:8px;letter-spacing:2px;color:rgba(232,244,255,.7);text-transform:uppercase;}
.modpill-status{font-family:var(--font-m);font-size:9px;margin-top:3px;}
.modpill-bar{height:2px;margin-top:6px;background:rgba(255,255,255,.06);}
.modpill-barfill{height:100%;transition:width 1s ease;}
.modpill-pct{font-family:var(--font-m);font-size:8px;color:var(--dim);margin-top:2px;text-align:right;}
.avatar-footer{padding:10px 13px;border-top:1px solid var(--border2);display:flex;gap:8px;flex-wrap:wrap;}
.avtag{font-family:var(--font-m);font-size:8px;padding:3px 9px;border:1px solid var(--border2);color:rgba(232,244,255,.35);letter-spacing:1px;}
.avtag.lit{border-color:rgba(0,212,255,.3);color:var(--cyan);}
#avatarStatus{font-family:var(--font-m);font-size:9px;color:var(--dim);letter-spacing:1px;padding:4px 13px;border-top:1px solid var(--border2);}
/* CAMERA */
.camsec{width:100%;max-width:580px;border:1px solid var(--border2);background:rgba(0,5,20,.85);}
.camhead{display:flex;align-items:center;justify-content:space-between;padding:9px 13px;border-bottom:1px solid var(--border2);}
.camtitle{font-family:var(--font-d);font-size:7.5px;letter-spacing:3px;color:rgba(255,51,102,.6);text-transform:uppercase;
display:flex;align-items:center;gap:7px;}
.camtitle::before{content:'';width:3px;height:9px;background:var(--red);box-shadow:0 0 5px var(--red);}
.camview{position:relative;width:100%;height:240px;background:#000;overflow:hidden;display:flex;align-items:center;justify-content:center;}
#camfeed{width:100%;height:100%;object-fit:cover;display:none;transform:scaleX(-1);}
#gestcv{position:absolute;inset:0;pointer-events:none;display:none;}
.corner{position:absolute;width:20px;height:20px;pointer-events:none;z-index:10;}
.tl{top:7px;left:7px;border-top:2px solid var(--cyan);border-left:2px solid var(--cyan);}
.tr{top:7px;right:7px;border-top:2px solid var(--cyan);border-right:2px solid var(--cyan);}
.bl{bottom:7px;left:7px;border-bottom:2px solid var(--cyan);border-left:2px solid var(--cyan);}
.br{bottom:7px;right:7px;border-bottom:2px solid var(--cyan);border-right:2px solid var(--cyan);}
.camoff{display:flex;flex-direction:column;align-items:center;gap:12px;}
.camicon{width:52px;height:52px;border:2px solid var(--border);border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:22px;filter:grayscale(1) opacity(.25);}
.camlabel{font-family:var(--font-d);font-size:8px;letter-spacing:2px;color:rgba(232,244,255,.18);text-align:center;}
.gestlabel{position:absolute;bottom:10px;left:50%;transform:translateX(-50%);font-family:var(--font-d);font-size:9px;
letter-spacing:2px;color:var(--gold);background:rgba(0,0,0,.75);padding:3px 14px;border:1px solid rgba(240,165,0,.25);
opacity:0;transition:opacity .3s;z-index:10;white-space:nowrap;}
.camctrl{padding:10px 13px;display:flex;gap:8px;flex-wrap:wrap;border-top:1px solid var(--border2);}
.gtag{font-family:var(--font-m);font-size:8px;padding:3px 9px;border:1px solid var(--border2);color:rgba(232,244,255,.35);letter-spacing:1px;display:flex;align-items:center;gap:5px;}
.gtag.rdy{border-color:rgba(0,255,136,.25);color:var(--green);}
/* BRAIN MODAL */
#bmodal{position:fixed;inset:0;z-index:1000;background:rgba(0,0,10,.96);display:none;align-items:center;justify-content:center;backdrop-filter:blur(10px);}
#bmodal.open{display:flex;}
.bmodalinner{position:relative;width:90vw;height:90vh;border:1px solid var(--border);background:rgba(0,5,25,.98);}
.bmodalhead{display:flex;justify-content:space-between;align-items:center;padding:12px 18px;border-bottom:1px solid var(--border2);}
.bmodaltitle{font-family:var(--font-d);font-size:9px;letter-spacing:4px;color:var(--gold);text-transform:uppercase;}
.mclose{font-family:var(--font-d);font-size:8px;letter-spacing:2px;padding:4px 10px;border:1px solid rgba(255,51,102,.3);
background:transparent;color:rgba(255,51,102,.6);cursor:pointer;transition:all .3s;}
.mclose:hover{border-color:var(--red);color:var(--red);}
#brainBig{width:100%;height:calc(100% - 44px);}
.blegend{position:absolute;right:18px;top:60px;display:flex;flex-direction:column;gap:7px;}
.bleg{display:flex;align-items:center;gap:7px;font-family:var(--font-m);font-size:8px;color:rgba(232,244,255,.45);letter-spacing:1px;}
.bdot{width:7px;height:7px;border-radius:50%;}
/* NOTIF */
#notif{position:fixed;top:72px;right:18px;z-index:900;display:flex;flex-direction:column;gap:7px;pointer-events:none;}
.nitem{background:rgba(0,5,25,.97);border:1px solid var(--border);border-left:3px solid var(--cyan);
padding:9px 14px;font-family:var(--font-m);font-size:10px;color:var(--white);min-width:220px;letter-spacing:.5px;
animation:nin .3s ease-out,nout .3s ease-in 2.7s forwards;}
.nitem.ng{border-left-color:var(--green);}
.nitem.no{border-left-color:var(--gold);}
@keyframes nin{from{opacity:0;transform:translateX(18px)}to{opacity:1;transform:translateX(0)}}
@keyframes nout{from{opacity:1}to{opacity:0}}
/* EXPENSE */
#expchart{width:100%;height:72px;}
::-webkit-scrollbar{width:3px;}
::-webkit-scrollbar-track{background:transparent;}
::-webkit-scrollbar-thumb{background:rgba(0,212,255,.18);}
</style>
</head>
<body>
<canvas id="starfield"></canvas>
<div id="notif"></div>
<!-- BRAIN MODAL -->
<div id="bmodal">
<div class="bmodalinner">
<div class="bmodalhead">
<div class="bmodaltitle">// JARVIS NEURAL ARCHITECTURE β€” FULL CORTEX MAP</div>
<button class="mclose" onclick="closeBrain()">CLOSE βœ•</button>
</div>
<canvas id="brainBig"></canvas>
<div class="blegend">
<div class="bleg"><div class="bdot" style="background:#00d4ff;box-shadow:0 0 5px #00d4ff"></div>VOICE ENGINE</div>
<div class="bleg"><div class="bdot" style="background:#f0a500;box-shadow:0 0 5px #f0a500"></div>MEMORY CORE</div>
<div class="bleg"><div class="bdot" style="background:#00ff88;box-shadow:0 0 5px #00ff88"></div>INTENT ROUTER</div>
<div class="bleg"><div class="bdot" style="background:#ff3366;box-shadow:0 0 5px #ff3366"></div>COMM MODULE</div>
<div class="bleg"><div class="bdot" style="background:#cc66ff;box-shadow:0 0 5px #cc66ff"></div>CRM BRIDGE</div>
<div class="bleg"><div class="bdot" style="background:#ff6644;box-shadow:0 0 5px #ff6644"></div>ANALYTICS</div>
<div class="bleg"><div class="bdot" style="background:#ffffff;box-shadow:0 0 5px #ffffff"></div>CORE LLM</div>
</div>
</div>
</div>
<div id="app">
<!-- HEADER -->
<header>
<div class="logo">JARVIS</div>
<div class="hcenter">
<div class="sdot" id="sdot"></div>
<div class="stext" id="stext">SYSTEM ONLINE</div>
<div class="htime" id="htime">--:--:--</div>
</div>
<div class="hright">
<button class="hbtn" id="micBtn" onclick="toggleMic()">MIC ON</button>
<button class="hbtn" id="camBtn" onclick="toggleCamera()">CAM OFF</button>
<button class="hbtn danger">STANDBY</button>
</div>
</header>
<!-- LEFT PANEL -->
<div class="pleft">
<div class="w">
<div class="wtitle">System Vitals</div>
<div class="vgrid">
<div class="vcard"><div class="vnum c" id="cpuv">14%</div><div class="vlbl">CPU</div></div>
<div class="vcard"><div class="vnum g" id="memv">4.3G</div><div class="vlbl">MEMORY</div></div>
<div class="vcard"><div class="vnum gr" id="latv">38ms</div><div class="vlbl">LATENCY</div></div>
<div class="vcard"><div class="vnum o" id="tmpv">62Β°C</div><div class="vlbl">TEMP</div></div>
</div>
</div>
<div class="w">
<div class="wtitle">Module Load</div>
<div class="brow"><div class="blabel">VOICE</div><div class="btrack"><div class="bfill" style="width:92%"></div></div><div class="bval" style="color:var(--green)">92%</div></div>
<div class="brow"><div class="blabel">MEMORY</div><div class="btrack"><div class="bfill" style="width:78%;background:linear-gradient(90deg,var(--gold),#ffcc44)"></div></div><div class="bval" style="color:var(--gold)">78%</div></div>
<div class="brow"><div class="blabel">CRM</div><div class="btrack"><div class="bfill" style="width:64%"></div></div><div class="bval">64%</div></div>
<div class="brow"><div class="blabel">GESTURE</div><div class="btrack"><div class="bfill" id="gestbar" style="width:0%;background:linear-gradient(90deg,#ff3366,#ff6666)"></div></div><div class="bval" id="gestval" style="color:rgba(255,51,102,.5)">OFF</div></div>
<div class="brow"><div class="blabel">ANALYTICS</div><div class="btrack"><div class="bfill" style="width:88%"></div></div><div class="bval" style="color:var(--green)">88%</div></div>
</div>
<div class="w">
<div class="wtitle gold">Expense Β· This Week</div>
<canvas id="expchart"></canvas>
<div class="mrow"><div class="mlabel">TOTAL</div><div class="mval gold">β‚Ή18,650</div></div>
<div class="mrow"><div class="mlabel">TRANSACTIONS</div><div class="mval">12</div></div>
<div class="mrow"><div class="mlabel">TOP CATEGORY</div><div class="mval gr">TRAVEL</div></div>
<div class="mrow"><div class="mlabel">BUDGET LEFT</div><div class="mval r">β‚Ή1,350</div></div>
</div>
<div class="w">
<div class="wtitle">Activity Log</div>
<div class="litem"><div class="ltime">09:42:17</div><div class="ltext">Call count β€” Ravi Motors: 14 calls today</div></div>
<div class="litem"><div class="ltime">09:38:04</div><div class="ltext">Expense logged β‚Ή2,400 Β· Fuel Β· Travel</div></div>
<div class="litem"><div class="ltime">09:31:50</div><div class="ltext">Contact lookup β€” Pradeep Sharma Β· Shree Motors</div></div>
<div class="litem"><div class="ltime">09:15:22</div><div class="ltext">Call summary: Anil (7 mins) Β· 3 action items</div></div>
<div class="litem"><div class="ltime">08:59:11</div><div class="ltext">WhatsApp sent to Team Managers Β· 6 recipients</div></div>
</div>
</div>
<!-- CENTER -->
<div class="maincenter">
<!-- ORB -->
<div class="orbsec">
<div class="orbwrap" id="orbwrap" onclick="cycleOrb()">
<div class="orbring"></div><div class="orbring"></div><div class="orbring"></div>
<div class="orbcore">
<div class="orbsphere" id="orb">
<canvas class="orbwave" id="orbwave"></canvas>
</div>
</div>
</div>
<div class="orbslabel" id="orblabel">IDLE β€” CLICK TO ACTIVATE</div>
<div class="orbctrl">
<button class="obtn" id="bspk" onclick="setOrb('speaking')">β—‰ SPEAKING</button>
<button class="obtn" id="blst" onclick="setOrb('listening')">β—Ž LISTENING</button>
<button class="obtn" id="bthk" onclick="setOrb('thinking')">⬑ THINKING</button>
<button class="obtn" onclick="setOrb('idle')">β—‹ IDLE</button>
</div>
</div>
<!-- TRANSCRIPT -->
<div class="tbox">
<div id="ttext">Initializing neural interface... All systems nominal. Ready for voice commands.<span class="cur"></span></div>
</div>
<!-- CMD -->
<div class="cmdbar">
<input class="cmdinput" id="cmdinput" placeholder="// type command or speak..." onkeydown="handleKey(event)">
<button class="cmdgo" onclick="submitCmd()">EXECUTE</button>
</div>
<!-- AVATAR SECTION -->
<div class="avatarsec">
<div class="avatarhead">
<div class="avatartitle">Neural Avatar β€” JARVIS Embodiment</div>
<div style="display:flex;gap:8px;">
<button class="zoomBtn" style="border-color:rgba(204,102,255,.3);color:var(--purple);" onclick="cycleAvatarMode()">CYCLE VIEW</button>
</div>
</div>
<div class="avatar-body">
<canvas id="avatarCanvas"></canvas>
<div class="avatar-rightpanel" id="modpanel"></div>
</div>
<div id="avatarStatus">// AVATAR IDLE β€” ALL SYSTEMS NOMINAL</div>
<div class="avatar-footer" id="avfooter"></div>
</div>
<!-- BRAIN -->
<div class="brainsec">
<div class="brainhead">
<div class="braintitle">Neural Brain Map</div>
<button class="zoomBtn" onclick="openBrain()">βŠ• ZOOM β€” FULL CORTEX</button>
</div>
<canvas id="brainMini"></canvas>
</div>
<!-- CAMERA -->
<div class="camsec">
<div class="camhead">
<div class="camtitle">Vision & Gesture Control</div>
<button class="hbtn" id="camtoggle" onclick="toggleCamera()">ENABLE CAMERA</button>
</div>
<div class="camview" id="camview">
<video id="camfeed" autoplay muted playsinline></video>
<canvas id="gestcv"></canvas>
<div class="corner tl"></div><div class="corner tr"></div>
<div class="corner bl"></div><div class="corner br"></div>
<div class="gestlabel" id="gestlabel">PALM DETECTED</div>
<div class="camoff" id="camoff">
<div class="camicon">πŸ“·</div>
<div class="camlabel">CAMERA DISABLED<br>ENABLE GESTURE CONTROL</div>
</div>
</div>
<div class="camctrl">
<div class="gtag">βœ‹ OPEN PALM β€” PAUSE</div>
<div class="gtag">πŸ‘† POINT β€” SELECT</div>
<div class="gtag">✊ FIST β€” CLOSE</div>
<div class="gtag">🀏 PINCH β€” ZOOM</div>
<div class="gtag rdy" id="visready">● VISION: STANDBY</div>
</div>
</div>
</div>
<!-- RIGHT PANEL -->
<div class="pright">
<div class="w">
<div class="wtitle">OttoPilot Β· Live Dealers</div>
<div class="drow"><div class="dname">Ravi Motors</div><div class="dcalls">14</div><div class="dbadge hot">HOT</div></div>
<div class="drow"><div class="dname">Shree Auto</div><div class="dcalls">09</div><div class="dbadge ok">GOOD</div></div>
<div class="drow"><div class="dname">Krishna Cars</div><div class="dcalls">06</div><div class="dbadge ok">GOOD</div></div>
<div class="drow"><div class="dname">Pradeep Auto</div><div class="dcalls">03</div><div class="dbadge low">LOW</div></div>
<div class="drow"><div class="dname">Anil Motors</div><div class="dcalls">01</div><div class="dbadge low">LOW</div></div>
<div style="margin-top:8px">
<div class="mrow"><div class="mlabel">TOTAL CALLS</div><div class="mval c">33</div></div>
<div class="mrow"><div class="mlabel">CONNECTED</div><div class="mval gr">24</div></div>
<div class="mrow"><div class="mlabel">PENDING LEADS</div><div class="mval gold">18</div></div>
</div>
</div>
<div class="w">
<div class="wtitle">Recent Contacts</div>
<div class="citem"><div class="cavatar">RP</div><div style="flex:1;overflow:hidden"><div class="cname">Ravi Patil</div><div class="crole">GM Β· Ravi Motors</div></div><div class="csdot online"></div></div>
<div class="citem"><div class="cavatar">AS</div><div style="flex:1;overflow:hidden"><div class="cname">Ajay Sharma</div><div class="crole">Exec Β· Shree Auto</div></div><div class="csdot away"></div></div>
<div class="citem"><div class="cavatar">PK</div><div style="flex:1;overflow:hidden"><div class="cname">Pradeep Kumar</div><div class="crole">Owner Β· Krishna Cars</div></div><div class="csdot offline"></div></div>
<div class="citem"><div class="cavatar">VJ</div><div style="flex:1;overflow:hidden"><div class="cname">Vijay Joshi</div><div class="crole">Mgr Β· Anil Motors</div></div><div class="csdot online"></div></div>
</div>
<div class="w">
<div class="wtitle gold">Today's Schedule</div>
<div class="litem"><div class="ltime">10:00 AM</div><div class="ltext">Dealer review call β€” All GMs</div></div>
<div class="litem"><div class="ltime">12:30 PM</div><div class="ltext">Lunch β€” Rohit & Team</div></div>
<div class="litem"><div class="ltime">03:00 PM</div><div class="ltext">OttoPilot training walkthrough</div></div>
<div class="litem"><div class="ltime">05:30 PM</div><div class="ltext">Q2 target review β€” Finance</div></div>
</div>
<div class="w">
<div class="wtitle purple">Memory Bank</div>
<div class="mrow"><div class="mlabel">CONVERSATIONS</div><div class="mval c">247</div></div>
<div class="mrow"><div class="mlabel">CALL SUMMARIES</div><div class="mval gold">84</div></div>
<div class="mrow"><div class="mlabel">EXPENSE RECORDS</div><div class="mval">312</div></div>
<div class="mrow"><div class="mlabel">CONTACTS INDEXED</div><div class="mval gr">156</div></div>
<div class="mrow"><div class="mlabel">NEURAL VECTORS</div><div class="mval p">18.4K</div></div>
<div class="mrow"><div class="mlabel">UPTIME</div><div class="mval gr">14d 6h</div></div>
</div>
</div>
</div>
<script>
/* ═══════════════════════════════════════════
STARFIELD
═══════════════════════════════════════════ */
(() => {
const c = document.getElementById('starfield'), ctx = c.getContext('2d');
const resize = () => { c.width = innerWidth; c.height = innerHeight; };
resize(); addEventListener('resize', resize);
const stars = Array.from({ length: 180 }, () => ({ x: Math.random(), y: Math.random(), s: Math.random() * 1.4 + .2, o: Math.random(), sp: Math.random() * .0002 + .0001 }));
const draw = () => {
ctx.clearRect(0, 0, c.width, c.height);
stars.forEach(s => {
s.o += Math.sin(Date.now() * s.sp) * .004;
ctx.beginPath(); ctx.arc(s.x * c.width, s.y * c.height, s.s, 0, Math.PI * 2);
ctx.fillStyle = `rgba(180, 220, 255, ${Math.max(0, Math.min(1, s.o))})`; ctx.fill();
});
requestAnimationFrame(draw);
}; draw();
})();
/* ═══════════════════════════════════════════
CORE API HOOKS
═══════════════════════════════════════════ */
const API_BASE = "";
async function refreshData() {
try {
// 1. Vitals
const vitRes = await fetch(`${API_BASE}/system/vitals`);
const vitals = await vitRes.json();
document.getElementById('cpuv').textContent = Math.floor(vitals.cpu) + '%';
document.getElementById('memv').textContent = (vitals.memory / 10).toFixed(1) + 'G';
document.getElementById('latv').textContent = Math.floor(Math.random() * 15 + 20) + 'ms';
document.getElementById('tmpv').textContent = Math.floor(Math.random() * 5 + 55) + 'Β°C';
// 2. Expenses
const expRes = await fetch(`${API_BASE}/system/expenses`);
const exp = await expRes.json();
const expParent = document.getElementById('expchart').parentElement;
expParent.querySelector('.mval.gold').textContent = exp.total;
expParent.querySelector('.mrow:nth-child(4) .mval').textContent = exp.count;
expParent.querySelector('.mrow:nth-child(5) .mval').textContent = exp.top_category;
// 3. Dealers
const dealRes = await fetch(`${API_BASE}/system/dealers`);
const dealers = await dealRes.json();
const dealList = document.querySelector('.pright .w:first-child');
const existingRows = dealList.querySelectorAll('.drow');
existingRows.forEach(r => r.remove());
dealers.dealers.forEach(d => {
const row = document.createElement('div');
row.className = 'drow';
row.innerHTML = `<div class="dname">${d.name}</div><div class="dcalls">${d.calls}</div><div class="dbadge ${d.status.toLowerCase() === 'hot' ? 'hot' : (d.status.toLowerCase() === 'good' ? 'ok' : 'low')}">${d.status}</div>`;
dealList.insertBefore(row, dealList.querySelector('div[style*="margin-top"]'));
});
dealList.querySelector('.mval.c').textContent = dealers.total_calls;
dealList.querySelector('.mval.gr').textContent = dealers.connected;
// 4. Memory Stats
const statsRes = await fetch(`${API_BASE}/system/stats/count`);
const stats = await statsRes.json();
const memW = document.querySelector('.pright .w:last-child');
if (memW) {
const conversations = memW.querySelector('.mrow:nth-child(2) .mval');
if (conversations) conversations.textContent = stats.conversations;
const expenses = memW.querySelector('.mrow:nth-child(4) .mval');
if (expenses) expenses.textContent = stats.expenses;
const contacts = memW.querySelector('.mrow:nth-child(5) .mval');
if (contacts) contacts.textContent = stats.contacts;
const vectors = memW.querySelector('.mrow:nth-child(6) .mval');
if (vectors) vectors.textContent = stats.vectors;
const uptime = memW.querySelector('.mrow:nth-child(7) .mval');
if (uptime) uptime.textContent = stats.uptime;
}
// 5. Contacts
const contactRes = await fetch(`${API_BASE}/system/contacts`);
const contacts = await contactRes.json();
const cList = document.querySelector('.pright .w:nth-child(2)');
cList.querySelectorAll('.citem').forEach(e => e.remove());
contacts.permanent.concat(contacts.recent).slice(0, 4).forEach(c => {
const item = document.createElement('div');
item.className = 'citem';
const initials = c.name.split(' ').map(n => n[0]).join('').toUpperCase();
item.innerHTML = `<div class="cavatar">${initials}</div><div style="flex:1;overflow:hidden"><div class="cname">${c.name}</div><div class="crole">${c.role}</div></div><div class="csdot ${c.status}"></div>`;
cList.appendChild(item);
});
} catch (e) { console.error("API Fetch Error:", e); }
}
setInterval(refreshData, 5000);
refreshData();
setInterval(() => { document.getElementById('htime').textContent = new Date().toTimeString().slice(0, 8) + ' IST'; }, 1000);
/* ═══════════════════════════════════════════
ORB
═══════════════════════════════════════════ */
let orbState = 'idle';
const orbStates = {
idle: { cls: '', label: 'IDLE β€” CLICK TO ACTIVATE', status: 'SYSTEM ONLINE' },
speaking: { cls: 'speaking', label: 'SPEAKING β€” NEURAL OUTPUT ACTIVE', status: 'SPEAKING' },
listening: { cls: 'listening', label: 'LISTENING β€” VOICE INPUT ACTIVE', status: 'LISTENING' },
thinking: { cls: 'thinking', label: 'PROCESSING β€” NEURAL INFERENCE', status: 'THINKING' }
};
function setOrb(s) {
orbState = s;
const orb = document.getElementById('orb');
if (orb) orb.className = 'orbsphere ' + (orbStates[s].cls || '');
const orblabel = document.getElementById('orblabel');
if (orblabel) orblabel.textContent = orbStates[s].label;
const stext = document.getElementById('stext');
if (stext) stext.textContent = orbStates[s].status;
['bspk', 'blst', 'bthk'].forEach(id => {
const btn = document.getElementById(id);
if (btn) btn.className = 'obtn';
});
if (s === 'speaking') { const b = document.getElementById('bspk'); if (b) b.className = 'obtn as'; }
if (s === 'listening') { const b = document.getElementById('blst'); if (b) b.className = 'obtn al'; }
if (s === 'thinking') { const b = document.getElementById('bthk'); if (b) b.className = 'obtn at'; }
updateAvatar(s);
notif('JARVIS: Mode β†’ ' + s.toUpperCase(), s === 'speaking' ? 'ng' : '');
}
function cycleOrb() { const s = ['idle', 'listening', 'thinking', 'speaking']; setOrb(s[(s.indexOf(orbState) + 1) % s.length]); }
/* ORB WAVEFORM */
(() => {
const c = document.getElementById('orbwave'), ctx = c.getContext('2d');
c.width = 100; c.height = 30; let t = 0;
const draw = () => {
ctx.clearRect(0, 0, 100, 30);
ctx.strokeStyle = orbState === 'speaking' ? '#00ff88' : orbState === 'listening' ? '#f0a500' : orbState === 'thinking' ? '#cc66ff' : '#00d4ff';
ctx.lineWidth = 1.5; ctx.globalAlpha = .6; ctx.beginPath();
for (let x = 0; x < 100; x++) {
const amp = orbState === 'idle' ? 2 : orbState === 'thinking' ? 5 : orbState === 'speaking' ? 9 * (0.5 + 0.5 * Math.sin(t * 3 + x * .1)) : 6;
const y = 15 + amp * Math.sin(t * 4 + x * .15) * Math.sin(x * .08); x === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
}
ctx.stroke(); t += .06; requestAnimationFrame(draw);
}; draw();
})();
/* ═══════════════════════════════════════════
COMMAND INTERACTION
═══════════════════════════════════════════ */
function handleKey(e) { if (e.key === 'Enter') submitCmd(); }
async function submitCmd() {
const v = document.getElementById('cmdinput').value.trim(); if (!v) return;
setOrb('thinking'); document.getElementById('cmdinput').value = '';
document.getElementById('ttext').innerHTML = 'Processing: "' + v + '"<span class="cur"></span>';
try {
const res = await fetch(`${API_BASE}/system/command`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ command: v })
});
const data = await res.json();
setOrb('speaking');
document.getElementById('ttext').innerHTML = data.response + '<span class="cur"></span>';
setTimeout(() => setOrb('idle'), 5000);
} catch (e) {
notif("Command failed", "no");
setOrb('idle');
}
}
async function toggleStandby() {
const current = document.getElementById('stext').textContent === 'STANDBY';
const newStatus = !current;
try {
await fetch(`${API_BASE}/system/safety-lock`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ status: newStatus })
});
notif(newStatus ? "System entering standby..." : "System resuming...", newStatus ? "no" : "ng");
document.getElementById('stext').textContent = newStatus ? 'STANDBY' : 'SYSTEM ONLINE';
} catch (e) { notif("Lock toggle failed", "no"); }
}
document.querySelector('.danger').onclick = toggleStandby;
/* ═══════════════════════════════════════════
EXPENSE CHART
═══════════════════════════════════════════ */
(() => {
const c = document.getElementById('expchart'), ctx = c.getContext('2d');
const dpr = devicePixelRatio || 1, W = c.parentElement.offsetWidth - 24;
c.style.width = W + 'px'; c.width = W * dpr; c.height = 72 * dpr; ctx.scale(dpr, dpr);
const vals = [3200, 1800, 4100, 2650, 3900, 1400, 1600], days = ['M', 'T', 'W', 'T', 'F', 'S', 'S'], mx = Math.max(...vals);
vals.forEach((v, i) => {
const x = i * (W / 7) + (W / 7 - 16) / 2, bh = (v / mx) * 50, y = 62 - bh;
const gr = ctx.createLinearGradient(0, y, 0, 62); gr.addColorStop(0, 'rgba(0,212,255,.8)'); gr.addColorStop(1, 'rgba(0,80,160,.2)');
ctx.fillStyle = gr; ctx.fillRect(x, y, 16, bh);
ctx.fillStyle = 'rgba(232,244,255,.3)'; ctx.font = '7px Share Tech Mono'; ctx.textAlign = 'center'; ctx.fillText(days[i], x + 8, 70);
});
})();
/* ═══════════════════════════════════════════
BRAIN MAP DRAW
═══════════════════════════════════════════ */
function drawBrain(ctx, W, H, sc) {
const cx = W / 2, cy = H / 2, t = Date.now() * .001;
const nodes = [
{ x: cx, y: cy - 65 * sc, r: 17 * sc, c: '#00d4ff', label: 'VOICE', fired: true },
{ x: cx - 85 * sc, y: cy - 22 * sc, r: 21 * sc, c: '#f0a500', label: 'MEMORY', fired: true },
{ x: cx + 85 * sc, y: cy - 22 * sc, r: 19 * sc, c: '#00ff88', label: 'INTENT', fired: true },
{ x: cx - 55 * sc, y: cy + 55 * sc, r: 15 * sc, c: '#ff3366', label: 'COMM', fired: true },
{ x: cx + 55 * sc, y: cy + 55 * sc, r: 17 * sc, c: '#cc66ff', label: 'CRM', fired: true },
{ x: cx, y: cy + 75 * sc, r: 13 * sc, c: '#ff6644', label: 'ANALYTICS', fired: true },
{ x: cx - 135 * sc, y: cy + 5 * sc, r: 11 * sc, c: '#00aaff', label: 'STT', fired: true },
{ x: cx + 135 * sc, y: cy + 5 * sc, r: 11 * sc, c: '#44ffaa', label: 'TTS', fired: true },
{ x: cx, y: cy + 8 * sc, r: 25 * sc, c: '#ffffff', label: 'CORE LLM', fired: true },
];
const edges = [[0, 8], [1, 8], [2, 8], [3, 8], [4, 8], [5, 8], [6, 0], [7, 0], [0, 2], [1, 3], [2, 4], [3, 5], [4, 5], [6, 8], [7, 8], [1, 2]];
ctx.clearRect(0, 0, W, H);
edges.forEach(([a, b]) => {
const na = nodes[a], nb = nodes[b];
const gr = ctx.createLinearGradient(na.x, na.y, nb.x, nb.y);
gr.addColorStop(0, na.c + '55'); gr.addColorStop(1, nb.c + '55');
ctx.strokeStyle = gr; ctx.lineWidth = .8; ctx.beginPath(); ctx.moveTo(na.x, na.y); ctx.lineTo(nb.x, nb.y); ctx.stroke();
const p = (t * .35 + (a + b) * .07) % 1;
const px = na.x + (nb.x - na.x) * p, py = na.y + (nb.y - na.y) * p;
ctx.beginPath(); ctx.arc(px, py, 1.8, 0, Math.PI * 2); ctx.fillStyle = '#ffffff99'; ctx.fill();
});
nodes.forEach((n, i) => {
const pulse = 1 + .08 * Math.sin(t * 2 + i), r = n.r * pulse;
const gw = ctx.createRadialGradient(n.x, n.y, 0, n.x, n.y, r * 2.2);
gw.addColorStop(0, n.c + '40'); gw.addColorStop(1, 'transparent');
ctx.fillStyle = gw; ctx.beginPath(); ctx.arc(n.x, n.y, r * 2.2, 0, Math.PI * 2); ctx.fill();
const gr = ctx.createRadialGradient(n.x - r * .3, n.y - r * .3, 0, n.x, n.y, r);
gr.addColorStop(0, n.c + 'ff'); gr.addColorStop(.6, n.c + 'aa'); gr.addColorStop(1, n.c + '33');
ctx.fillStyle = gr; ctx.beginPath(); ctx.arc(n.x, n.y, r, 0, Math.PI * 2); ctx.fill();
ctx.fillStyle = 'rgba(232,244,255,.65)'; ctx.font = `${Math.max(6, 7 * sc)}px Share Tech Mono`; ctx.textAlign = 'center';
ctx.fillText(n.label, n.x, n.y + r + 9 * sc);
});
}
(() => {
const c = document.getElementById('brainMini'), ctx = c.getContext('2d');
const dpr = devicePixelRatio || 1;
const resize = () => { const W = c.parentElement.offsetWidth; c.style.width = W + 'px'; c.style.height = '180px'; c.width = W * dpr; c.height = 180 * dpr; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); };
resize(); addEventListener('resize', resize);
const loop = () => { drawBrain(ctx, c.offsetWidth, c.offsetHeight, .68); requestAnimationFrame(loop); }; loop();
})();
let brainAnim;
function openBrain() {
document.getElementById('bmodal').classList.add('open');
const c = document.getElementById('brainBig'), ctx = c.getContext('2d');
const dpr = devicePixelRatio || 1;
const resize = () => { const W = c.parentElement.offsetWidth, H = c.parentElement.offsetHeight - 44; c.style.width = W + 'px'; c.style.height = H + 'px'; c.width = W * dpr; c.height = H * dpr; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); };
resize();
const loop = () => { drawBrain(ctx, c.offsetWidth, c.offsetHeight, 1.7); brainAnim = requestAnimationFrame(loop); }; loop();
}
function closeBrain() { document.getElementById('bmodal').classList.remove('open'); cancelAnimationFrame(brainAnim); }
/* ═══════════════════════════════════════════
JARVIS HUMAN AVATAR
═══════════════════════════════════════════ */
const MODULES = [
{ id: 'voice', name: 'VOICE ENGINE', color: '#00d4ff', pct: 92, region: 'head', desc: 'STT + TTS active' },
{ id: 'memory', name: 'MEMORY CORE', color: '#f0a500', pct: 78, region: 'brain', desc: '142K vectors loaded' },
{ id: 'intent', name: 'INTENT ROUTER', color: '#00ff88', pct: 88, region: 'chest', desc: 'LLM routing online' },
{ id: 'crm', name: 'CRM BRIDGE', color: '#cc66ff', pct: 64, region: 'rhand', desc: 'OttoPilot connected' },
{ id: 'comm', name: 'COMM MODULE', color: '#ff3366', pct: 71, region: 'lhand', desc: 'WhatsApp + Email ready' },
{ id: 'gesture', name: 'GESTURE CTRL', color: '#ff6644', pct: 0, region: 'lhand', desc: 'Camera offline' },
{ id: 'analytics', name: 'ANALYTICS', color: '#ffcc44', pct: 88, region: 'core', desc: 'Reports engine online' },
{ id: 'profile', name: 'PROFILE SWITCH', color: '#44ffaa', pct: 55, region: 'legs', desc: 'Secondary profile ready' },
];
let avatarMode = 0; let activeModule = null; let avatarAnim; let particleList = [];
function buildModPanel() {
const p = document.getElementById('modpanel'); if (!p) return; p.innerHTML = '';
MODULES.forEach(m => {
const el = document.createElement('div'); el.className = 'modpill' + (activeModule === m.id ? ' active' : ''); el.id = 'pill_' + m.id; el.onclick = () => selectModule(m.id);
el.innerHTML = `<div class="modpill-name" style="color:${m.color}">${m.name}</div><div class="modpill-status" style="color:${m.color}88">${m.desc}</div><div class="modpill-bar"><div class="modpill-barfill" style="width:${m.pct}%;background:${m.color};box-shadow:0 0 6px ${m.color}"></div></div><div class="modpill-pct">${m.pct > 0 ? m.pct + '%' : 'OFFLINE'}</div>`;
p.appendChild(el);
});
const f = document.getElementById('avfooter'); if (!f) return; f.innerHTML = '';
['HOLOGRAPHIC', 'SKELETON', 'ORGANS', 'ENERGY'].forEach((v, i) => {
const el = document.createElement('div'); el.className = 'avtag' + (avatarMode === i ? ' lit' : ''); el.textContent = v; el.onclick = () => { avatarMode = i; buildModPanel(); }; f.appendChild(el);
});
}
buildModPanel();
function selectModule(id) {
activeModule = activeModule === id ? null : id; buildModPanel();
const m = MODULES.find(x => x.id === id); if (m) notif('MODULE: ' + m.name + ' β€” ' + m.desc, m.pct > 70 ? 'ng' : 'no');
const avatarStatus = document.getElementById('avatarStatus');
if (avatarStatus) avatarStatus.textContent = m ? '// SELECTED: ' + m.name + ' (' + m.pct + '%) β€” ' + m.desc : '// AVATAR IDLE β€” ALL SYSTEMS NOMINAL';
}
function updateAvatar(state) {
const pcts = { idle: [92, 78, 88, 64, 71, 0, 88, 55], speaking: [98, 80, 95, 64, 71, 0, 88, 55], listening: [95, 85, 88, 64, 75, 0, 88, 55], thinking: [88, 95, 99, 80, 71, 0, 92, 55] };
const p = pcts[state] || pcts.idle; MODULES.forEach((m, i) => { m.pct = p[i]; }); buildModPanel();
}
function cycleAvatarMode() { avatarMode = (avatarMode + 1) % 4; buildModPanel(); notif('Avatar view: ' + ['HOLOGRAPHIC', 'SKELETON', 'ORGANS', 'ENERGY'][avatarMode], ''); }
/* AVATAR DRAW */
(() => {
const c = document.getElementById('avatarCanvas'); if (!c) return; const ctx = c.getContext('2d'); const dpr = devicePixelRatio || 1;
const resize = () => { const W = c.parentElement.offsetWidth - 180; c.style.width = W + 'px'; c.style.height = '380px'; c.width = W * dpr; c.height = 380 * dpr; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); };
resize(); const regions = { head: { dy: -140, r: 28 }, brain: { dy: -130, r: 20 }, chest: { dy: -55, r: 40 }, core: { dy: -55, r: 40 }, lhand: { dx: -65, dy: -20, r: 20 }, rhand: { dx: 65, dy: -20, r: 20 }, legs: { dy: 80, r: 35 } };
c.addEventListener('click', (e) => {
const rect = c.getBoundingClientRect(); const mx = (e.clientX - rect.left), my = (e.clientY - rect.top), cx = c.offsetWidth / 2, cy = 220;
MODULES.forEach(m => { const reg = regions[m.region] || { dy: 0, r: 30 }, rx = cx + (reg.dx || 0), ry = cy + (reg.dy || 0); if (Math.hypot(mx - rx, my - ry) < reg.r + 10) selectModule(m.id); });
});
function spawnParticle(x, y, color) { for (let i = 0; i < 6; i++)particleList.push({ x, y, vx: (Math.random() - .5) * 3, vy: (Math.random() - .5) * 3, life: 1, color }); }
function drawAvatar(W, H) {
ctx.clearRect(0, 0, W, H); const t = Date.now() * .001, cx = W / 2, cy = 220;
ctx.strokeStyle = 'rgba(0,212,255,0.04)'; ctx.lineWidth = .5;
for (let x = 0; x < W; x += 30) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, H); ctx.stroke(); }
if (avatarMode === 0 || avatarMode === 1) {
ctx.shadowBlur = avatarMode === 0 ? 16 : 4; ctx.shadowColor = avatarMode === 0 ? '#00d4ff' : 'rgba(0,212,255,.3)'; ctx.strokeStyle = avatarMode === 0 ? 'rgba(0,212,255,.55)' : 'rgba(0,212,255,.2)'; ctx.lineWidth = avatarMode === 0 ? 1.5 : 1;
ctx.beginPath(); ctx.arc(cx, cy - 140, 28, 0, Math.PI * 2); ctx.stroke(); ctx.beginPath(); ctx.moveTo(cx - 30, cy - 100); ctx.lineTo(cx - 38, cy - 60); ctx.lineTo(cx - 35, cy + 10); ctx.lineTo(cx + 35, cy + 10); ctx.lineTo(cx + 38, cy - 60); ctx.lineTo(cx + 30, cy - 100); ctx.closePath(); ctx.stroke();
ctx.shadowBlur = 0;
}
const scanY = cy - 160 + ((t * 50) % 320); const sg = ctx.createLinearGradient(0, scanY - 8, 0, scanY + 8); sg.addColorStop(0, 'transparent'); sg.addColorStop(.5, 'rgba(0,212,255,.08)'); sg.addColorStop(1, 'transparent'); ctx.fillStyle = sg; ctx.fillRect(0, scanY - 8, W, 16);
particleList = particleList.filter(p => { p.x += p.vx; p.y += p.vy; p.life -= .03; if (p.life <= 0) return false; ctx.beginPath(); ctx.arc(p.x, p.y, 2 * p.life, 0, Math.PI * 2); ctx.fillStyle = p.color + (Math.floor(p.life * 255).toString(16).padStart(2, '0')); ctx.fill(); return true; });
}
const loop = () => { drawAvatar(c.offsetWidth, c.offsetHeight); avatarAnim = requestAnimationFrame(loop); }; loop();
})();
/* ═══════════════════════════════════════════
VISION & GESTURE (MEDIAPIPE)
═══════════════════════════════════════════ */
let camOn = false;
const videoElement = document.getElementById('camfeed');
const canvasElement = document.getElementById('gestcv');
const canvasCtx = canvasElement.getContext('2d');
let hands = null;
let camera = null;
function onResults(results) {
canvasCtx.save();
canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);
if (results.multiHandLandmarks) {
for (const landmarks of results.multiHandLandmarks) {
if (window.drawConnectors) drawConnectors(canvasCtx, landmarks, HAND_CONNECTIONS, { color: '#00d4ff', lineWidth: 2 });
if (window.drawLandmarks) drawLandmarks(canvasCtx, landmarks, { color: '#f0a500', lineWidth: 1, radius: 2 });
// Improved Gesture recognition
const isFist = landmarks[8].y > landmarks[6].y && landmarks[12].y > landmarks[10].y && landmarks[16].y > landmarks[14].y;
const isOpen = landmarks[8].y < landmarks[6].y && landmarks[12].y < landmarks[10].y;
const isPinch = Math.hypot(landmarks[8].x - landmarks[4].x, landmarks[8].y - landmarks[4].y) < 0.05;
const gl = document.getElementById('gestlabel');
if (gl) {
if (isPinch) { gl.textContent = "PINCH β€” ZOOM"; gl.style.opacity = '1'; }
else if (isFist) { gl.textContent = "FIST β€” SELECT"; gl.style.opacity = '1'; }
else if (isOpen) { gl.textContent = "OPEN PALM β€” IDLE"; gl.style.opacity = '1'; }
}
}
}
canvasCtx.restore();
}
async function toggleCamera() {
if (!camOn) {
try {
if (!hands && window.Hands) {
hands = new Hands({ locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}` });
hands.setOptions({ maxNumHands: 1, modelComplexity: 1, minDetectionConfidence: 0.5, minTrackingConfidence: 0.5 });
hands.onResults(onResults);
}
if (!camera && window.Camera) {
camera = new Camera(videoElement, {
onFrame: async () => { if (hands) await hands.send({ image: videoElement }); },
width: 640, height: 480
});
}
if (camera) await camera.start();
videoElement.style.display = 'block';
const camoff = document.getElementById('camoff'); if (camoff) camoff.style.display = 'none';
if (canvasElement) canvasElement.style.display = 'block';
const camBtn = document.getElementById('camBtn'); if (camBtn) { camBtn.textContent = 'CAM ON'; camBtn.classList.add('on'); }
const camtoggle = document.getElementById('camtoggle'); if (camtoggle) camtoggle.textContent = 'DISABLE CAMERA';
const visready = document.getElementById('visready'); if (visready) visready.textContent = '● VISION: ACTIVE';
const gestbar = document.getElementById('gestbar'); if (gestbar) gestbar.style.width = '100%';
const m = MODULES.find(x => x.id === 'gesture'); if (m) { m.pct = 100; m.desc = 'Vision active'; } buildModPanel();
camOn = true; notif('Vision module activated', 'ng');
} catch (e) { console.error(e); notif('Camera access denied', ''); }
} else {
if (camera) await camera.stop();
videoElement.style.display = 'none';
const camoff = document.getElementById('camoff'); if (camoff) camoff.style.display = 'flex';
if (canvasElement) canvasElement.style.display = 'none';
const camBtn = document.getElementById('camBtn'); if (camBtn) { camBtn.textContent = 'CAM OFF'; camBtn.classList.remove('on'); }
const camtoggle = document.getElementById('camtoggle'); if (camtoggle) camtoggle.textContent = 'ENABLE CAMERA';
const visready = document.getElementById('visready'); if (visready) visready.textContent = '● VISION: STANDBY';
const gestbar = document.getElementById('gestbar'); if (gestbar) gestbar.style.width = '0%';
const m = MODULES.find(x => x.id === 'gesture'); if (m) { m.pct = 0; m.desc = 'Camera offline'; } buildModPanel();
camOn = false; notif('Vision module disabled', '');
}
}
function toggleMic() {
const b = document.getElementById('micBtn'); if (!b) return;
const on = b.textContent === 'MIC ON';
b.textContent = on ? 'MIC OFF' : 'MIC ON';
on ? b.classList.remove('on') : b.classList.add('on');
notif(!on ? 'Microphone enabled' : 'Microphone muted', !on ? 'ng' : '');
}
function notif(msg, cls = '') {
const c = document.getElementById('notif'); if (!c) return;
const el = document.createElement('div');
el.className = 'nitem ' + cls; el.textContent = msg; c.appendChild(el); setTimeout(() => el.remove(), 3200);
}
setTimeout(() => notif('JARVIS v2 initialized β€” neural interface ready', 'ng'), 500);
setTimeout(() => notif('Sovereign Cloud: Sync established', 'ng'), 1500);
</script>
</body>
</html>