function e04Portrait(c,x,y,w,h){
 if(!c)return;
 let b=e04PortraitBounds.get(c);const now=performance.now();
 if(!b||now>b.refresh){
  // Bounds use the existing rendered portrait, never a replacement asset.
  const pixels=c.getContext('2d').getImageData(0,0,c.width,c.height).data;
  let left=c.width,top=c.height,right=-1,bottom=-1;
  for(let yy=0;yy<c.height;yy++)for(let xx=0;xx<c.width;xx++)if(pixels[(yy*c.width+xx)*4+3]>128){left=Math.min(left,xx);right=Math.max(right,xx);top=Math.min(top,yy);bottom=Math.max(bottom,yy);}
  b={left,top,w:right-left+1,h:bottom-top+1,refresh:now+1000};e04PortraitBounds.set(c,b);
 }
 if(b.w<=0||b.h<=0){sprite('question0',x+(w-16)/2,y+(h-16)/2);return;}
 const scale=Math.min(w/b.w,h/b.h),dw=Math.max(1,Math.floor(b.w*scale)),dh=Math.max(1,Math.floor(b.h*scale));
 ctx.drawImage(c,b.left,b.top,b.w,b.h,Math.floor(x+(w-dw)/2),Math.floor(y+(h-dh)/2),dw,dh);
}
