const socket=io(), content=document.querySelector('#content'), modeEl=document.querySelector('#mode'); const canvas=document.querySelector('#waveCanvas'), ctx=canvas.getContext('2d'); let mode='idle',level=.02,t=0; function resize(){canvas.width=canvas.clientWidth*devicePixelRatio;canvas.height=canvas.clientHeight*devicePixelRatio} addEventListener('resize',resize);resize(); function draw(){t+=.035;ctx.clearRect(0,0,canvas.width,canvas.height);ctx.strokeStyle='rgba(255,255,255,.85)';ctx.lineWidth=2*devicePixelRatio;ctx.beginPath();let mid=canvas.height/2,amp=(mode==='idle'?1:mode==='thinking'?8:Math.max(5,level*45))*devicePixelRatio;for(let x=0;x{content.innerHTML=html;content.classList.remove('swap')},260)} function render(d){if(d.type==='image') swap(`${d.alt||''}

${d.caption||''}

`);else if(d.type==='cards') swap(`
${(d.items||[]).map(i=>`

${i.title||''}

${i.text||''}

`).join('')}
`);else swap(`

${d.title||''}

${d.text||''}

`)} socket.on('alfred_state',s=>{mode=s.mode||'idle';modeEl.textContent=mode;if(s.content)render(s.content)});socket.on('alfred_render',render);socket.on('audio_level',d=>level=d.level||0);