27:18Gemini 4 Hydrogen: Cheaper Tokens, More Expensive Answers?
Nov 13, 2026 · YouTube
18:40ERNIE 5.5 Flash Preview vs GLM 5.3 Flash: Baidu's new model is very impressive!
Nov 11, 2026 · YouTube
36:22Fable 5.2 robbing me blind, plus: Nex AGI's N2.6 vs GLM 5.3 Flash
Nov 11, 2026 · YouTube
14:03Gemini 4 Carbon: Can it handle my challenges? (First look with one-shot coding tests)
Nov 10, 2026 · YouTube
47:51Ranking major U.S. Open-Weights Models. (Where does Ripple 65B fit in?)
Nov 6, 2026 · YouTube
10:57"Crouton Alpha": the latest super-efficient coding model by Meta?
Nov 3, 2026 · YouTube
38:58Testing Particle-1: a post-trained DeepSeek V4.1 Flash specializing in coding and efficiency
Oct 28, 2026 · YouTube
22:14GPT-6.1 Terra Pro vs Terra: How Much Better Is Pro?
Oct 27, 2026 · YouTube
29:55Kimi K3.1 Pro Looked Incredible. Then I Kept Testing.
Oct 26, 2026 · YouTube
31:28Is this company reselling GPT Sol 6.1 at a loss (for non-agentic/text-only)?🤔 Is this sustainable?
Oct 20, 2026 · YouTube
17:58Nemotron 3.5 Super VL vs Opus 5.5: Testing NVIDIA’s new coding juggernaut
Oct 15, 2026 · YouTube
16:04Testing a *massive* new open-weights model 🤯: Muse Spark Open (vs. Nemotron, Opus 5.5, and more)
Oct 15, 2026 · YouTube
16:43Gemini 4 Argon: Great 🐈 Animation, but a broken escalator. (Coding challenge vs Opus 5.5, Sol 6.1)
Oct 13, 2026 · YouTube
16:37Meta's new "Muse Wonder" AI is impressive... but can it compete with Anthropic's models?
Oct 12, 2026 · YouTube
11:12WOW... Haiku 5.5 is very impressive. RIP OpenAI?
Oct 7, 2026 · YouTube
22:47Mistral Large 4 Is Cheap. But Is It Good Enough to Compete?
Oct 6, 2026 · YouTube
22:02Is Pareto 26.10 Preview Just Routing to GPT Sol? I Tested It Against Sol 6.1 Pro
Oct 1, 2026 · YouTube
11:22I Tested Sonnet 5.5 Against Opus 5.5. Is It Actually Cheaper?
Sep 28, 2026 · YouTube
30:00Did Elon Musk's team "train the gay away"... and make Grok 4.7 worse?
Sep 26, 2026 · YouTube
19:21I Tested the Stealth "Space Bunny Alpha" Model Before It Went Offline
Sep 23, 2026 · YouTube
10:58So... how much better is Claude Opus 5.5 vs. GPT-6 Sol, really?
Sep 23, 2026 · YouTube
9:38Claude Opus 5.5... the BEST new model for coding!! 🤩
Sep 22, 2026 · YouTube
29:00Grok 4.7: improved, but GLM 5.3 FlashX beat it anyway (benchmark against Gemini, Sol, etc.)
Sep 22, 2026 · YouTube
You make short animated pieces for the web.
Build me a single HTML page: a bird, breakdancing.
data: URIs are fine.localStorage, sessionStorage, cookies or indexedDB — sandboxed frame, they throw.html block.Two sentences: what the bird is, and the look you went for.
The single fenced html block.
Three bullets.
A street pigeon — the patron saint of head-bobbing — running a solo breaking set on a sheet of cardboard. The look is a three-ink risograph print: cream stock, deep blue-slate linework, safety-orange accents, static grain pressed over everything, and a hand-sprayed "COO!" tag bleeding on the wall behind it.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>PIGEON BREAK</title>
<style>
:root{ --paper:#ece3cd; --ink:#262b3f; --acc:#ee5622; }
*{ box-sizing:border-box; }
html,body{ margin:0; height:100%; overflow:hidden; background:var(--ink); }
body{ font-family:"Courier New",Courier,monospace; user-select:none; -webkit-user-select:none; }
canvas{ position:fixed; inset:0; display:block; }
#brand{ position:fixed; top:18px; left:18px; color:var(--ink); background:var(--paper);
border:3px solid var(--ink); outline:2px solid var(--ink); outline-offset:3px;
padding:10px 16px 12px; transform:rotate(-1.6deg); pointer-events:none; }
#brand h1{ margin:0; font-size:25px; font-weight:900; letter-spacing:.24em; }
#brand h1 em{ font-style:normal; color:var(--acc); }
#brand p{ margin:7px 0 0; font-size:10.5px; letter-spacing:.18em; text-transform:uppercase; opacity:.72; }
#bar{ position:fixed; left:0; right:0; bottom:0; display:flex; align-items:center;
gap:9px; flex-wrap:wrap; padding:12px 16px; pointer-events:none; }
#bar>*{ pointer-events:auto; }
.btn{ font-family:inherit; font-weight:700; font-size:11px; letter-spacing:.13em;
text-transform:uppercase; color:var(--ink); background:var(--paper);
border:2.5px solid var(--ink); padding:8px 11px; cursor:pointer;
box-shadow:3px 3px 0 var(--ink); transition:transform .07s, box-shadow .07s; }
.btn:hover{ transform:translate(-1px,-1px); box-shadow:4px 4px 0 var(--ink); }
.btn:active{ transform:translate(2px,2px); box-shadow:0 0 0 var(--ink); }
.btn.on{ background:var(--acc); color:var(--paper); }
.btn.live{ background:var(--ink); color:var(--paper); }
.btn .k{ opacity:.5; margin-right:6px; }
#tempo{ display:flex; align-items:center; gap:9px; margin-left:auto;
font-size:10.5px; font-weight:700; letter-spacing:.14em; color:var(--ink); }
input[type=range]{ -webkit-appearance:none; appearance:none; width:118px; height:3px;
background:var(--ink); outline:none; }
input[type=range]::-webkit-slider-thumb{ -webkit-appearance:none; width:15px; height:15px;
background:var(--acc); border:2.5px solid var(--ink); cursor:ew-resize; }
input[type=range]::-moz-range-thumb{ width:11px; height:11px; border-radius:0;
background:var(--acc); border:2.5px solid var(--ink); cursor:ew-resize; }
#hint{ font-size:9.5px; letter-spacing:.12em; opacity:.55; color:var(--ink); text-transform:uppercase; }
#colo{ position:fixed; left:18px; bottom:76px; font-size:9px; letter-spacing:.2em;
color:var(--ink); opacity:.5; text-transform:uppercase; pointer-events:none; }
</style>
</head>
<body>
<canvas id="cv"></canvas>
<div id="brand">
<h1>PIGEON <em>BREAK</em></h1>
<p>all-city coo-down · live from the ledge</p>
</div>
<div id="bar">
<button class="btn" data-move="toprock"><span class="k">1</span>Toprock</button>
<button class="btn" data-move="footwork"><span class="k">2</span>Footwork</button>
<button class="btn" data-move="freeze"><span class="k">3</span>Freeze</button>
<button class="btn" data-move="windmill"><span class="k">4</span>Windmill</button>
<button class="btn" data-move="headspin"><span class="k">5</span>Headspin</button>
<div id="tempo">
<span id="bpmLab">102 BPM</span>
<input id="bpm" type="range" min="84" max="126" value="102">
<button class="btn" id="beatBtn">Beat: off</button>
</div>
<span id="hint">1–5 call moves · B beat · tap floor = surprise</span>
</div>
<div id="colo">three-ink riso · recycled cardboard · no pigeons harmed</div>
<script>
"use strict";
/* ============ constants & tiny utils ============ */
const PAPER="#ece3cd", FLOOR="#e3d6b8", TAN="#d8c294", TAND="#c2aa7a",
INK="#262b3f", GRAY="#8b93a6", GRAYD="#5d6478", BELLY="#b9bfcc",
CREAM="#f2ead6", ACC="#ee5622", GRN="#4a8f5c";
const PAL ={f1:GRAY, f2:BELLY, w:"#79818f", line:INK, band:CREAM, beak:"#3c4157",
grn:GRN, acc:ACC, legN:"#d9552e", legF:GRAYD, sil:false};
const SPECT={f1:"#7b8294", f2:"#8d94a4", w:"#6f7686", line:"#333849", band:"#a9aeb9",
beak:"#4a4f60", grn:"#5d8a6a", acc:"#c96a3f", legN:"#8a5f4c", legF:"#5d5348", sil:false};
const G=150, TILT=0.35, TAU=Math.PI*2;
const X=document.getElementById('cv').getContext('2d');
const cv=document.getElementById('cv');
let W=0,H=0,DPR=1,SCL=1;
const clamp=(v,a,b)=>v<a?a:v>b?b:v;
const lerp=(a,b,u)=>a+(b-a)*u;
function S(x,a,b){ return x<=a?0:x>=b?1:(x-a)/(b-a); }
const EO=u=>1-Math.pow(1-u,3);
const EI=u=>u*u*u;
const EIO=u=>u<.5?4*u*u*u:1-Math.pow(-2*u+2,3)/2;
const OB=u=>{const c=1.6,e=u-1;return 1+(c+1)*e*e*e+c*e*e;};
const sm01=(a,b,x)=>{const t=S(x,a,b);return t*t*(3-2*t);};
/* ============ pose ============ */
function defPose(){return{x:0,h:53,rot:0,sq:0,headRot:0,neck:1,beak:0,tailRot:0,
tailSpread:0,look:0,eye:1,wNa:0,wNb:0,wNe:0,wFa:0,wFb:0,wFe:0,
lNh:.12,lNsh:.05,lNtoe:0,lFh:-.12,lFsh:.05,lFtoe:0,gy:G,_ns:0};}
const clonePose=p=>Object.assign({},p);
function mixPose(a,b,u){for(const k in a){if(k==='_ns'){a[k]=Math.max(a[k],b[k]);continue;}a[k]+=(b[k]-a[k])*u;}return a;}
/* local (bird space) -> world, mirroring the draw transform exactly */
function locW(P,px,py){
const c=Math.cos(TILT),s=Math.sin(TILT);
let x=px*c-py*s, y=px*s+py*c;
x*=1+P.sq*.55; y*=1-P.sq;
const cr=Math.cos(P.rot),sr=Math.sin(P.rot);
return [P.x+(x*cr-y*sr), G-P.h+(x*sr+y*cr)];
}
function wingTipLocal(a,b){
const p1x=20+Math.cos(a)*30,p1y=-22+Math.sin(a)*30,a2=a+b;
return [p1x+Math.cos(a2)*44,p1y+Math.sin(a2)*44];
}
function setPiv(P,pv,hl,rot){
P.rot=rot;
const c=Math.cos(rot),s=Math.sin(rot);
P.x=pv.x-(hl[0]*c-hl[1]*s);
P.h=G+(hl[0]*s+hl[1]*c)-pv.y;
}
/* feet / planted wing / chest / back must never sink through the floor:
lift the body until the lowest contact point rests on the ground. */
function groundSolve(P){
let pen=0;
const legs=[[P.lNh,P.lNsh],[P.lFh,P.lFsh]];
for(const L of legs){
const kx=2+Math.sin(L[0])*15, ky=20+Math.cos(L[0])*15;
const ax=kx+Math.sin(L[0]+L[1])*15, ay=ky+Math.cos(L[0]+L[1])*15;
pen=Math.max(pen,locW(P,ax,ay+3)[1]-G);
}
if(P.wNe>.6){const t=wingTipLocal(P.wNa,P.wNb);pen=Math.max(pen,locW(P,t[0],t[1])[1]-G+2);}
pen=Math.max(pen,locW(P,28,24)[1]-(G-2)); /* chest */
pen=Math.max(pen,locW(P,0,-30)[1]-(G-2)); /* back (for lying on it) */
if(pen>0)P.h+=Math.min(pen,60);
}
/* ============ canvas / world ============ */
let bg=null,scuff=null,scx=null,grainPat=null;
let shake=0,shakeX=0,shakeY=0;
function resize(){
DPR=Math.min(2,window.devicePixelRatio||1);
W=innerWidth; H=innerHeight;
cv.width=Math.ceil(W*DPR); cv.height=Math.ceil(H*DPR);
cv.style.width=W+'px'; cv.style.height=H+'px';
SCL=Math.min(1.55,Math.min(W/1060,H/680));
buildBG();
}
function rr(g,x,y,w,h,r){g.beginPath();g.moveTo(x+r,y);g.arcTo(x+w,y,x+w,y+h,r);
g.arcTo(x+w,y+h,x,y+h,r);g.arcTo(x,y+h,x,y,r);g.arcTo(x,y,x+w,y,r);g.closePath();}
function drawTag(g){
g.save(); g.translate(-10,-108); g.rotate(-.05);
g.font="900 148px 'Courier New',monospace"; g.textAlign='center'; g.textBaseline='middle';
g.globalAlpha=.8; g.fillStyle=GRN; g.fillText('COO!',7,9); /* misregistered pass */
g.globalAlpha=.95; g.fillStyle=ACC;
g.shadowColor=ACC; g.shadowBlur=16; /* spray softness */
g.fillText('COO!',0,0); g.shadowBlur=0; g.fillText('COO!',0,0);
g.globalAlpha=.5; g.strokeStyle=INK; g.lineWidth=2.5; g.strokeText('COO!',0,0);
g.globalAlpha=.85; g.strokeStyle=ACC; g.fillStyle=ACC;
[[-88,38,54],[-16,42,30],[58,32,62]].forEach(d=>{ /* drips */
g.lineWidth=5; g.beginPath(); g.moveTo(d[0],d[1]); g.lineTo(d[0],d[1]+d[2]); g.stroke();
g.beginPath(); g.arc(d[0],d[1]+d[2]+3,3.6,0,7); g.fill(); });
g.globalAlpha=1; g.restore();
}
function buildBG(){
bg=document.createElement('canvas'); bg.width=Math.ceil(W*DPR); bg.height=Math.ceil(H*DPR);
const g=bg.getContext('2d'); g.scale(DPR,DPR);
g.fillStyle=PAPER; g.fillRect(0,0,W,H);
g.translate(W/2,H/2-12); g.scale(SCL,SCL);
g.fillStyle=FLOOR; g.fillRect(-560,40,1120,320);
g.strokeStyle=INK; g.globalAlpha=.15; g.lineWidth=1.5; /* floor cracks */
g.beginPath(); g.moveTo(-470,90); g.lineTo(-420,110); g.lineTo(-430,140); g.stroke();
g.beginPath(); g.moveTo(470,240); g.lineTo(430,258); g.lineTo(445,286); g.stroke();
g.globalAlpha=1;
g.fillStyle=INK; /* halftone band */
for(let r=0;r<5;r++){const y=14+r*5.5,rad=1+r*.42;
for(let x=-540+(r%2)*3.5;x<540;x+=7){g.globalAlpha=.05+r*.018;
g.beginPath();g.arc(x,y,rad,0,7);g.fill();}}
g.globalAlpha=.85; g.strokeStyle=INK; g.lineWidth=3.5; /* baseboard */
g.beginPath(); g.moveTo(-560,40); g.lineTo(560,40); g.stroke();
g.globalAlpha=.3; g.lineWidth=1.5;
g.beginPath(); g.moveTo(-560,47); g.lineTo(560,47); g.stroke();
g.globalAlpha=1;
drawTag(g);
g.save(); g.translate(-206,136); g.rotate(.42); /* discarded spray can */
g.fillStyle=ACC; g.strokeStyle=INK; g.lineWidth=2;
rr(g,-13,-6,26,12,2); g.fill(); g.stroke();
g.fillStyle=GRAYD; rr(g,9,-5,7,10,1); g.fill(); g.stroke();
g.fillStyle=PAPER; g.beginPath(); g.arc(-4,0,3.4,0,7); g.fill(); g.stroke();
g.restore();
scuff=document.createElement('canvas'); scuff.width=1120; scuff.height=136;
scx=scuff.getContext('2d');
g.fillStyle=TAN; g.strokeStyle=INK; g.lineWidth=3; /* the cardboard stage */
g.beginPath(); g.moveTo(-272,148); g.lineTo(252,148); g.lineTo(264,196); g.lineTo(-256,196);
g.closePath(); g.fill(); g.stroke();
g.fillStyle=TAND; g.lineWidth=2.5;
g.beginPath(); g.moveTo(-256,196); g.lineTo(264,196); g.lineTo(266,205); g.lineTo(-258,205);
g.closePath(); g.fill(); g.stroke();
g.globalAlpha=.35; g.lineWidth=1.2;
for(let x=-250;x<258;x+=9){g.beginPath();g.moveTo(x,197);g.lineTo(x+1,204);g.stroke();}
g.globalAlpha=.28; g.strokeStyle=INK; g.lineWidth=1.6;
g.beginPath(); g.moveTo(-266,172); g.lineTo(258,172); g.stroke();
g.globalAlpha=1;
const tape=(tx,ty,ang)=>{g.save();g.translate(tx,ty);g.rotate(ang);
g.fillStyle=CREAM; g.globalAlpha=.75; g.fillRect(-32,-8,64,16);
g.globalAlpha=.5; g.strokeStyle=INK; g.lineWidth=1.4; g.strokeRect(-32,-8,64,16);
g.globalAlpha=1; g.restore();};
tape(-90,166,-.035); tape(120,180,.05);
g.fillStyle=CREAM; g.strokeStyle=INK; g.lineWidth=2; /* corner curl */
g.beginPath(); g.moveTo(252,196); g.lineTo(264,196); g.lineTo(258,182); g.closePath();
g.fill(); g.stroke();
g.fillStyle=INK; g.globalAlpha=.5; /* crumbs */
[[152,157],[164,155],[158,162]].forEach(c=>{g.beginPath();g.arc(c[0],c[1],1.6,0,7);g.fill();});
g.globalAlpha=1;
}
function buildGrain(){
const c=document.createElement('canvas'); c.width=c.height=180;
const g=c.getContext('2d');
for(let i=0;i<5200;i++){
g.fillStyle=Math.random()<.5
?'rgba(38,43,63,'+(.02+Math.random()*.05)+')'
:'rgba(255,250,235,'+(.02+Math.random()*.05)+')';
g.fillRect(Math.random()*180,Math.random()*180,1.3,1.3);
}
grainPat=X.createPattern(c,'repeat');
}
function stampScuff(x,y,p){
if(!scx)return;
scx.save(); scx.scale(2,2); scx.translate(x+280,y-142);
scx.strokeStyle=INK; scx.globalAlpha=.045+.05*p; scx.lineWidth=2+Math.random()*2;
scx.lineCap='round';
for(let i=0;i<3;i++){ scx.beginPath();
const a=Math.random()*TAU,l=6+Math.random()*14;
scx.moveTo((Math.random()-.5)*10,(Math.random()-.5)*6);
scx.lineTo(Math.cos(a)*l,Math.sin(a)*l*.35); scx.stroke(); }
scx.restore();
}
/* ============ drawing the pigeon ============ */
function tailFeather(g,C){
g.beginPath(); g.moveTo(0,-4);
g.quadraticCurveTo(20,-5.5,34,-1); g.quadraticCurveTo(36,0,34,1);
g.quadraticCurveTo(20,5.5,0,4); g.closePath();
g.fillStyle=C.f1; g.fill();
g.strokeStyle=C.line; g.lineWidth=2.2; g.stroke();
if(!C.sil){g.fillStyle=C.band; g.fillRect(22,-3.6,5,7.2);}
}
function foldedWing(g,C,al){
g.save(); g.globalAlpha*=al;
g.beginPath(); g.moveTo(20,-22);
g.bezierCurveTo(-4,-24,-26,-8,-34,14);
g.bezierCurveTo(-20,10,0,4,16,-12); g.closePath();
g.fillStyle=C.w; g.fill();
g.strokeStyle=C.line; g.lineWidth=2.6; g.stroke();
if(!C.sil){g.strokeStyle=C.band; g.lineWidth=4;
g.beginPath(); g.moveTo(-2,-19); g.lineTo(-16,2); g.stroke();}
g.restore();
}
function drawWing(g,a,b,C,far,al){
const sx=20,sy=-22,L1=30,L2=26;
const p1x=sx+Math.cos(a)*L1, p1y=sy+Math.sin(a)*L1, a2=a+b;
const p2x=p1x+Math.cos(a2)*L2, p2y=p1y+Math.sin(a2)*L2;
g.save(); g.globalAlpha*=al; if(far)g.globalAlpha*=.92;
g.lineJoin='round'; g.lineCap='round';
const seg=(x0,y0,x1,y1,w0,w1)=>{
const pa=Math.atan2(y1-y0,x1-x0)+Math.PI/2;
g.beginPath();
g.moveTo(x0+Math.cos(pa)*w0,y0+Math.sin(pa)*w0);
g.lineTo(x1+Math.cos(pa)*w1,y1+Math.sin(pa)*w1);
g.lineTo(x1-Math.cos(pa)*w1,y1-Math.sin(pa)*w1);
g.lineTo(x0-Math.cos(pa)*w0,y0-Math.sin(pa)*w0);
g.closePath(); g.fillStyle=C.w; g.fill();
g.strokeStyle=C.line; g.lineWidth=2.6; g.stroke(); };
seg(sx,sy,p1x,p1y,9,6.5);
seg(p1x,p1y,p2x,p2y,6.5,4);
for(let i=-1;i<=1;i++){ /* primary feathers */
const fa=a2+i*.28, fx=p2x+Math.cos(fa)*19, fy=p2y+Math.sin(fa)*19;
seg(p2x,p2y,fx,fy,3.4,2); }
if(!C.sil){ const pa=a+Math.PI/2;
g.strokeStyle=C.band; g.lineWidth=3.6;
g.beginPath();
g.moveTo(sx+Math.cos(a)*10+Math.cos(pa)*3, sy+Math.sin(a)*10+Math.sin(pa)*3);
g.lineTo(p1x-Math.cos(a)*4+Math.cos(pa)*3, p1y-Math.sin(a)*4+Math.sin(pa)*3);
g.stroke(); }
g.restore();
}
function drawLeg(g,th,sh,toe,C,col){
const kx=2+Math.sin(th)*15, ky=20+Math.cos(th)*15;
const ax=kx+Math.sin(th+sh)*15, ay=ky+Math.cos(th+sh)*15;
const fa=Math.PI/2+(toe||0);
g.lineCap='round';
g.strokeStyle=C.line; g.lineWidth=7.4;
g.beginPath(); g.moveTo(2,17); g.lineTo(kx,ky); g.lineTo(ax,ay); g.stroke();
g.beginPath(); g.moveTo(ax,ay);
g.lineTo(ax+Math.sin(fa+Math.PI)*4.5, ay+Math.cos(fa+Math.PI)*4.5); g.stroke();
for(let i=-1;i<=1;i++){const ta=fa+i*.34;
g.beginPath(); g.moveTo(ax,ay); g.lineTo(ax+Math.sin(ta)*11, ay+Math.cos(ta)*11); g.stroke();}
g.strokeStyle=col; g.lineWidth=4.4;
g.beginPath(); g.moveTo(2,17); g.lineTo(kx,ky); g.lineTo(ax,ay); g.stroke();
for(let i=-1;i<=1;i++){const ta=fa+i*.34;
g.beginPath(); g.moveTo(ax,ay); g.lineTo(ax+Math.sin(ta)*11, ay+Math.cos(ta)*11); g.stroke();}
}
function drawHead(g,P,C){
const th0=-1.12+P.headRot, L=25*P.neck, nbx=18, nby=-26;
const hx=nbx+Math.cos(th0)*L, hy=nby+Math.sin(th0)*L;
g.strokeStyle=C.line; g.lineWidth=19;
g.beginPath(); g.moveTo(nbx-3,nby+5); g.lineTo(hx,hy); g.stroke();
g.strokeStyle=C.f1; g.lineWidth=14.5;
g.beginPath(); g.moveTo(nbx-3,nby+5); g.lineTo(hx,hy); g.stroke();
g.beginPath(); g.arc(hx,hy,14.5,0,7);
g.fillStyle=C.f1; g.fill();
g.strokeStyle=C.line; g.lineWidth=3; g.stroke();
if(!C.sil){
g.save(); g.translate((nbx+hx)/2+3,(nby+hy)/2-1); g.rotate(th0+Math.PI/2);
g.fillStyle=C.grn; g.beginPath(); g.ellipse(0,0,5.5,9,0,0,7); g.fill(); g.restore();
}
const bd=th0+1.5, px=bd+Math.PI/2;
const bxc=hx+Math.cos(bd)*8, byc=hy+Math.sin(bd)*8, op=1.6+4.2*(P.beak||0);
g.fillStyle=C.beak; g.strokeStyle=C.line; g.lineWidth=2;
g.beginPath();
g.moveTo(bxc+Math.cos(px)*4.6,byc+Math.sin(px)*4.6);
g.lineTo(bxc-Math.cos(px)*4.6,byc-Math.sin(px)*4.6);
g.lineTo(hx+Math.cos(bd)*23-Math.cos(px)*op*.35,hy+Math.sin(bd)*23-Math.sin(px)*op*.35);
g.closePath(); g.fill(); g.stroke();
g.beginPath();
g.moveTo(bxc+Math.cos(px)*3.9,byc+Math.sin(px)*3.9);
g.lineTo(bxc-Math.cos(px)*3.9,byc-Math.sin(px)*3.9);
g.lineTo(hx+Math.cos(bd)*22+Math.cos(px)*op,hy+Math.sin(bd)*22+Math.sin(px)*op);
g.closePath(); g.fill(); g.stroke();
if(!C.sil){
g.fillStyle=C.band; g.beginPath();
g.ellipse(hx+Math.cos(bd)*9,hy+Math.sin(bd)*9-3.4,4.4,2.8,.3,0,7); g.fill();
g.strokeStyle=C.line; g.lineWidth=1.5; g.stroke();
}
const ex=hx+Math.cos(bd)*7.2, ey=hy+Math.sin(bd)*7.2-4.4+P.headRot*2.2;
if(C.sil){ g.fillStyle=PAPER; g.beginPath(); g.arc(ex,ey,2.1,0,7); g.fill(); }
else{
g.fillStyle=C.acc; g.beginPath(); g.arc(ex,ey,4.6,0,7); g.fill();
g.strokeStyle=C.line; g.lineWidth=1.4; g.stroke();
const lx=(P.look||0)*1.8;
g.fillStyle=INK; g.beginPath(); g.arc(ex+lx,ey,2.3,0,7); g.fill();
g.fillStyle=PAPER; g.beginPath(); g.arc(ex+lx-1,ey-1.4,.9,0,7); g.fill();
if((P.eye||1)<.97){ g.fillStyle=C.f1; g.beginPath();
g.ellipse(ex,ey,5.2,5.2*(1-P.eye)+.5,0,0,7); g.fill(); }
}
}
function drawBird(P,C,face,size){
const g=X;
g.save();
g.translate(P.x,(P.gy||G)-P.h);
g.scale(face*size,size);
g.rotate(P.rot);
g.scale(1+P.sq*.55,1-P.sq);
g.save(); g.rotate(TILT);
g.lineJoin='round'; g.lineCap='round';
g.save(); g.translate(-36,-10);
for(let i=-2;i<=2;i++){ g.save(); g.rotate(2.75+P.tailRot+i*.13*(1+P.tailSpread));
tailFeather(g,C); g.restore(); }
g.restore();
if(P.wFe>.18)drawWing(g,P.wFa,P.wFb,C,true,sm01(.18,.5,P.wFe));
drawLeg(g,P.lFh,P.lFsh,P.lFtoe,C,C.legF);
g.beginPath(); g.ellipse(0,0,45,34,0,0,7);
g.fillStyle=C.f1; g.fill();
if(!C.sil){ g.beginPath(); g.ellipse(4,9,30,21,.15,0,7); g.fillStyle=C.f2; g.fill(); }
g.strokeStyle=C.line; g.lineWidth=3;
g.beginPath(); g.ellipse(0,0,45,34,0,0,7); g.stroke();
const foN=1-sm01(.18,.5,P.wNe);
if(foN>.03)foldedWing(g,C,foN);
if(P.wNe>.18)drawWing(g,P.wNa,P.wNb,C,false,sm01(.18,.5,P.wNe));
drawHead(g,P,C);
g.restore();
g.restore();
}
function drawShadow(P,gy,size){
const k=clamp(1-(53-P.h)/170,.25,1);
X.save(); X.translate(P.x,gy+4); X.scale(size,size);
X.fillStyle=INK; X.globalAlpha=(.05+.13*k)*(1-Math.abs(P.sq)*.5);
X.beginPath(); X.ellipse(0,0,46*k+16,9*k+2.5,0,0,7); X.fill();
X.restore();
}
/* ============ particles ============ */
const parts=[];
function spawnDust(x,y,n,pow){
for(let i=0;i<n;i++)parts.push({tp:'dust',x:x+(Math.random()-.5)*30*Math.max(.5,pow),
y:y-2,vx:(Math.random()-.5)*170*Math.max(.4,pow),vy:-(30+Math.random()*140*Math.max(.3,pow)),
r:2.5+Math.random()*4*Math.max(.5,pow),life:.4+Math.random()*.35,t:0});}
function spawnFea(x,y){for(let i=0;i<3;i++)parts.push({tp:'fea',x:x+(Math.random()-.5)*30,
y:y-40,vx:(Math.random()-.5)*130,vy:-(60+Math.random()*80),
rot:Math.random()*TAU,ph:Math.random()*TAU,life:2.4,t:0});}
function spawnArc(x,y,r,ang){parts.push({tp:'arc',x,y,r,ang,t:0,life:.3});}
function spawnRing(x,y){parts.push({tp:'ring',x,y,t:0,life:.45});}
function spawnLab(x,y,txt){parts.push({tp:'lab',x,y,txt,t:0,life:1.15});}
function spawnBurst(x,y){parts.push({tp:'burst',x,y,rot:Math.random()*TAU,t:0,life:.32});}
function updateParts(dt){
for(let i=parts.length-1;i>=0;i--){const p=parts[i];p.t+=dt;
if(p.tp==='dust'){p.x+=p.vx*dt;p.y+=p.vy*dt;p.vy+=520*dt;p.vx*=1-1.5*dt;}
else if(p.tp==='fea'){p.x+=p.vx*dt+Math.sin(p.t*5+p.ph)*22*dt;p.y+=p.vy*dt;
p.vy=Math.min(60,p.vy+70*dt);p.rot+=Math.sin(p.t*3+p.ph)*1.8*dt;}