/* DONA_FAMILY_UI_V1: non-destructive augmentation of the installed Glass V1 dashboard. */
(() => {
'use strict';
let attempts=0;
function init(){
const root=document.getElementById('alfredMainV1');
if(!root){if(++attempts<40)setTimeout(init,150);return;}
if(root.dataset.donaFamily==='ready')return;
const $=id=>document.getElementById(id);
const head=root.querySelector('.av-header-right');
const weather=root.querySelector('.av-weather');
const hero=root.querySelector('.av-voice-hero');
const shortcuts=root.querySelector('.av-shortcuts');
if(!head||!weather||!hero||!shortcuts)return;
root.dataset.donaFamily='ready';document.body.classList.add('dona-family-v1');
// Move the EXISTING weather widget: old JS keeps updating the SAME IDs.
weather.classList.add('dona-inline-weather');
weather.setAttribute('title','Ouvrir les détails météo');
head.prepend(weather);
// Child link is supplementary; all old admin/navigation functions remain.
const kid=document.createElement('a');kid.href='/enfant';kid.className='dona-child-link';kid.textContent='⭐ Espace enfant';
kid.setAttribute('aria-label','Ouvrir le chat enfant, écrit uniquement');
head.insertBefore(kid,head.querySelector('.av-head-actions'));
const toolsGrid=root.querySelector('#avMoreDialog .av-more-grid');
if(toolsGrid&&!toolsGrid.querySelector('a[href="/enfant"]')){
const a=document.createElement('a');a.href='/enfant';a.textContent='⭐ Espace enfant';toolsGrid.append(a);
}
// New expressive centre; old controls stay in DOM so audio event listeners work.
const display=document.createElement('div');display.className='dona-art-center';
display.innerHTML='
Prêt à vous aider';
hero.prepend(display);
const oldVoice=root.querySelector('.av-voice-center');
if(oldVoice){display.append(oldVoice);}
// Move shortcuts into a collapsed tray, instead of removing their controls.
const tools=document.createElement('details');tools.className='dona-tools-tray';
const summary=document.createElement('summary');summary.textContent='☷ Raccourcis';
shortcuts.parentNode.insertBefore(tools,shortcuts);tools.append(summary,shortcuts);
// Minimal permanent one-row text field: no expandable tray, send at right.
const compose=document.createElement('div');compose.className='dona-compose dona-compose-compact';
compose.innerHTML=``;
root.append(compose);
const body=$('donaComposeBody'),input=$('donaComposeInput'),send=$('donaComposeSend'),status=$('donaComposeStatus');
input.addEventListener('keydown',e=>{if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();body.requestSubmit();}});
body.addEventListener('submit',async e=>{
e.preventDefault();let message=input.value.trim();if(!message)return;
send.disabled=true;status.textContent='Envoi à Hermes…';
try{
const r=await fetch('/api/dona/texte',{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/json','X-Alfred-Request':'1'},body:JSON.stringify({message})});
let d={};try{d=await r.json();}catch(_){}
if(!r.ok)throw Error(d.error||'Erreur '+r.status);
input.value='';status.textContent='Hermes prépare sa réponse…';
}catch(err){status.textContent=err.message;}
finally{send.disabled=false;}
});
const modeText={idle:'Prêt à vous aider',waiting:'Prêt à vous aider',listening:'Je vous écoute…',thinking:'Je réfléchis…',speaking:'Je vous réponds…',error:'Un problème est survenu'};
function setMode(mode){root.dataset.familyMode=mode;const t=$('donaArtSubtitle');if(t)t.textContent=modeText[mode]||'Prêt à vous aider';if(mode==='idle'&&status.textContent==='Hermes prépare sa réponse…')status.textContent='Réponse reçue';}
function setName(value){const name=String(value||$('avName')?.textContent||'Dona').trim();$('donaArtName').textContent=name;}
setName();setMode(root.dataset.mode||'idle');
const socket=window.alfredSocket;
socket?.on('alfred_state',s=>{setMode(String(s.mode||'idle').toLowerCase());setName(s.assistant_name||s.title||$('avName')?.textContent);});
socket?.on('alfred_render',()=>{if(status.textContent==='Hermes prépare sa réponse…')status.textContent='Réponse reçue';});
fetch('/api/state',{cache:'no-store'}).then(r=>r.ok?r.json():null).then(s=>{if(s){setMode(s.mode||'idle');setName(s.assistant_name||s.title);}}).catch(()=>{});
// Animated multi-layer liquid orb using canvas, independent of server state.
const canvas=$('donaOrganicCanvas'),ctx=canvas.getContext('2d');
if(!ctx)return;
let w=320,h=320,phase=0,raf=0,last=0;
const reduce=matchMedia('(prefers-reduced-motion: reduce)').matches;
function resize(){const rect=canvas.getBoundingClientRect();const dpr=Math.min(devicePixelRatio||1,2);w=Math.max(150,rect.width);h=Math.max(150,rect.height);canvas.width=Math.floor(w*dpr);canvas.height=Math.floor(h*dpr);ctx.setTransform(dpr,0,0,dpr,0,0);}
window.addEventListener('resize',resize,{passive:true});resize();
function path(radius,layer){const n=130;ctx.beginPath();for(let k=0;k<=n;k++){
const a=k/n*Math.PI*2;const modulation=1+0.067*Math.sin(a*3+phase*.72+layer*.64)+0.044*Math.cos(a*5-phase*.39+layer)+0.021*Math.sin(a*8+phase*.55);
const r=radius*modulation;const x=Math.cos(a)*r,y=Math.sin(a)*r;
if(k===0)ctx.moveTo(x,y);else ctx.lineTo(x,y);
}ctx.closePath();}
function frame(now){raf=requestAnimationFrame(frame);if(document.hidden||now-last<30)return;last=now;
const mode=root.dataset.familyMode||'idle';const speed=mode==='listening'?1.7:mode==='thinking'?1.38:mode==='speaking'?1.5:.75;
if(!reduce)phase+=.024*speed;
ctx.clearRect(0,0,w,h);ctx.save();ctx.translate(w/2,h/2);const r=Math.min(w,h)*.33;
const bloom=ctx.createRadialGradient(-r*.2,-r*.15,r*.1,0,0,r*1.45);
bloom.addColorStop(0,'rgba(238,117,160,.11)');bloom.addColorStop(.7,'rgba(139,112,246,.14)');bloom.addColorStop(1,'rgba(37,180,255,0)');ctx.fillStyle=bloom;ctx.beginPath();ctx.arc(0,0,r*1.48,0,Math.PI*2);ctx.fill();
for(let layer=3;layer>=0;layer--){const waveR=r*(1+layer*.025);path(waveR,layer);
const g=ctx.createLinearGradient(-r*.9,r*.8,r*.9,-r*.85);
if(layer%2===0){g.addColorStop(0,'rgba(47,196,244,.76)');g.addColorStop(.36,'rgba(68,94,198,.88)');g.addColorStop(.62,'rgba(244,138,173,.74)');g.addColorStop(1,'rgba(255,176,71,.9)');}
else {g.addColorStop(0,'rgba(59,164,255,.65)');g.addColorStop(.4,'rgba(196,119,245,.48)');g.addColorStop(.7,'rgba(241,125,146,.52)');g.addColorStop(1,'rgba(255,185,95,.76)');}
ctx.globalAlpha=layer===0?.76:.25;ctx.fillStyle=g;ctx.fill();
ctx.globalAlpha=layer===0?.92:.31;ctx.strokeStyle=g;ctx.lineWidth=layer===0?2.5:1.8;ctx.shadowBlur=layer===0?23:13;ctx.shadowColor=layer%2?'#bd80ec':'#ffc685';ctx.stroke();ctx.shadowBlur=0;
}
const ribbon=ctx.createLinearGradient(-r,r*.4,r,-r*.3);ribbon.addColorStop(0,'rgba(67,219,255,.0)');ribbon.addColorStop(.48,'rgba(255,231,197,.56)');ribbon.addColorStop(1,'rgba(255,181,103,.01)');
ctx.beginPath();for(let i=0;i<=100;i++){const x=-r+i/100*r*2;const y=Math.sin(i/100*Math.PI*2+phase*.35)*r*.25+Math.cos(i/100*Math.PI*3-phase*.45)*r*.11;if(i===0)ctx.moveTo(x,y);else ctx.lineTo(x,y);}ctx.lineWidth=r*.26;ctx.strokeStyle=ribbon;ctx.globalAlpha=.38;ctx.stroke();ctx.restore();
}
raf=requestAnimationFrame(frame);window.addEventListener('pagehide',()=>cancelAnimationFrame(raf),{once:true});
}
init();
})();