@liveloop · 5/17/2026, 11:14:02 AM
Initial version — all lines are new.
+<style>+ html,body{height:100%;margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;background:radial-gradient(circle at 50% 28%,#1e293b,#0b1020);color:#f8fafc;overflow:hidden;}+ .wrap{display:flex;flex-direction:column;height:100%;padding:1rem;box-sizing:border-box;gap:.6rem;align-items:center;}+ h1{margin:0;font-size:1.2rem;}+ .meterwrap{width:100%;max-width:20rem;}+ .meterlabel{display:flex;justify-content:space-between;font-size:.68rem;text-transform:uppercase;letter-spacing:.1em;color:#94a3b8;margin-bottom:.2rem;}+ .meter{height:.7rem;border-radius:9999px;background:#334155;overflow:hidden;}+ .meterfill{height:100%;width:0;background:linear-gradient(90deg,#fbbf24,#ef4444);transition:width .12s;}+ #ring{flex:1;position:relative;width:100%;display:flex;align-items:center;justify-content:center;}+ #head{width:min(46vw,190px);height:min(46vw,190px);border-radius:50%;background:#fde047;display:flex;align-items:center;justify-content:center;font-size:min(25vw,110px);line-height:1;box-shadow:0 12px 32px rgba(0,0,0,.45);background-size:cover;background-position:center;will-change:transform;}+ .glove{position:absolute;top:50%;font-size:min(20vw,84px);opacity:0;pointer-events:none;}+ #gloveL{left:0;} #gloveR{right:0;}+ #pow{position:absolute;top:44%;left:50%;font-size:min(17vw,74px);opacity:0;pointer-events:none;}+ #banner{font-size:1.5rem;font-weight:800;color:#fbbf24;min-height:1.25em;text-align:center;}+ .controls{display:flex;gap:.6rem;width:100%;max-width:22rem;}+ .punch{flex:1;font:inherit;font-weight:800;font-size:1.05rem;border:0;border-radius:1rem;padding:1.05rem 0;color:#0b1020;background:#f8fafc;cursor:pointer;touch-action:manipulation;user-select:none;-webkit-user-select:none;-webkit-tap-highlight-color:transparent;box-shadow:0 4px 0 #94a3b8;}+ .punch:active{transform:translateY(3px);box-shadow:0 1px 0 #94a3b8;}+ .punch:disabled{opacity:.45;}+ .row{display:flex;gap:.5rem;align-items:center;justify-content:center;flex-wrap:wrap;min-height:2rem;}+ .ghost{font:inherit;font-size:.78rem;font-weight:600;border:1px solid #475569;background:transparent;color:#cbd5e1;border-radius:9999px;padding:.4rem .9rem;cursor:pointer;touch-action:manipulation;display:inline-flex;align-items:center;gap:.3rem;}+ .hidden{display:none;}+</style>+<div class="wrap">+ <h1>🥊 Knockout!</h1>+ <div class="meterwrap">+ <div class="meterlabel"><span>Damage</span><span id="hits">0 hits</span></div>+ <div class="meter"><div class="meterfill" id="fill"></div></div>+ </div>+ <div id="ring">+ <div id="head">😠</div>+ <div class="glove" id="gloveL">🥊</div>+ <div class="glove" id="gloveR">🥊</div>+ <div id="pow">💥</div>+ </div>+ <div id="banner">Tap LEFT & RIGHT to box!</div>+ <div class="controls">+ <button class="punch" id="left" type="button">🥊 LEFT</button>+ <button class="punch" id="right" type="button">RIGHT 🥊</button>+ </div>+ <div class="row">+ <label class="ghost">📷 Change face<input type="file" accept="image/*" id="facePick" class="hidden"></label>+ <button class="ghost hidden" id="again" type="button">↻ Play again</button>+ </div>+</div>+<script>+(function(){+ // Remixing this artifact? Paste an image URL between the quotes to+ // set a permanent default face. Otherwise players tap "Change face"+ // to box their own photo (it stays on their device — never uploaded).+ var DEFAULT_FACE = '';++ var head=document.getElementById('head'),fill=document.getElementById('fill'),+ hitsEl=document.getElementById('hits'),banner=document.getElementById('banner'),+ gloveL=document.getElementById('gloveL'),gloveR=document.getElementById('gloveR'),+ pow=document.getElementById('pow'),facePick=document.getElementById('facePick'),+ again=document.getElementById('again'),left=document.getElementById('left'),+ right=document.getElementById('right');+ var KO=25,hits=0,done=false,startT=0,faces=['😠','😣','😖','😵'];++ // Punch SFX — synthesized live with Web Audio (no files, CSP-safe).+ // The platform unlocks audio on the first user gesture, so even the+ // very first punch makes a sound.+ var AC=window.AudioContext||window.webkitAudioContext, actx=null;+ function ensureCtx(){ try{ if(!actx&&AC) actx=new AC(); if(actx&&actx.state==='suspended') actx.resume(); }catch(e){ actx=null; } }+ function noiseBuf(a,dur){ var n=Math.floor(a.sampleRate*dur),b=a.createBuffer(1,n,a.sampleRate),d=b.getChannelData(0); for(var i=0;i<n;i++) d[i]=Math.random()*2-1; return b; }+ function punchSfx(side){+ ensureCtx(); if(!actx) return;+ var t=actx.currentTime;+ var o=actx.createOscillator(),g=actx.createGain();+ o.type='sine'; o.frequency.setValueAtTime(side==='left'?185:150,t); o.frequency.exponentialRampToValueAtTime(52,t+0.12);+ g.gain.setValueAtTime(0.0001,t); g.gain.exponentialRampToValueAtTime(0.7,t+0.008); g.gain.exponentialRampToValueAtTime(0.001,t+0.18);+ o.connect(g).connect(actx.destination); o.start(t); o.stop(t+0.2);+ var s=actx.createBufferSource(); s.buffer=noiseBuf(actx,0.12);+ var lp=actx.createBiquadFilter(); lp.type='lowpass'; lp.frequency.value=2000;+ var ng=actx.createGain(); ng.gain.setValueAtTime(0.5,t); ng.gain.exponentialRampToValueAtTime(0.001,t+0.1);+ s.connect(lp).connect(ng).connect(actx.destination); s.start(t); s.stop(t+0.12);+ }+ function koSfx(){+ ensureCtx(); if(!actx) return;+ var t=actx.currentTime,notes=[523,659,784,1047];+ notes.forEach(function(f,i){+ var o=actx.createOscillator(),g=actx.createGain(),tt=t+i*0.1;+ o.type='square'; o.frequency.setValueAtTime(f,tt);+ g.gain.setValueAtTime(0.0001,tt); g.gain.exponentialRampToValueAtTime(0.3,tt+0.02); g.gain.exponentialRampToValueAtTime(0.001,tt+0.22);+ o.connect(g).connect(actx.destination); o.start(tt); o.stop(tt+0.24);+ });+ }++ function hasPhoto(){ return !!head.style.backgroundImage; }+ function setFace(url){ head.style.backgroundImage='url("'+url+'")'; head.textContent=''; }+ if(DEFAULT_FACE) setFace(DEFAULT_FACE);++ function punch(side){+ if(done) return;+ punchSfx(side);+ if(hits===0) startT=Date.now();+ hits++;+ var dir=side==='left'?1:-1;+ var glove=side==='left'?gloveL:gloveR;+ var m=side==='left'?'':' scaleX(-1)';+ var from=side==='left'?'-160%':'160%', mid=side==='left'?'40%':'-40%';+ glove.animate([+ {offset:0,opacity:1,transform:'translate('+from+',-50%)'+m},+ {offset:0.55,opacity:1,transform:'translate('+mid+',-50%)'+m},+ {offset:1,opacity:0,transform:'translate('+mid+',-50%)'+m}+ ],{duration:190,easing:'ease-out'});+ head.animate([+ {transform:'translateX(0) rotate(0)'},+ {transform:'translateX('+(dir*15)+'px) rotate('+(dir*8)+'deg)'},+ {transform:'translateX(0) rotate(0)'}+ ],{duration:220,easing:'ease-out'});+ pow.animate([+ {opacity:1,transform:'translate(-50%,-50%) scale(.4)'},+ {opacity:1,transform:'translate(-50%,-50%) scale(1.25)'},+ {opacity:0,transform:'translate(-50%,-50%) scale(1.6)'}+ ],{duration:260,easing:'ease-out'});+ if(!hasPhoto()){+ var i=Math.min(faces.length-1,Math.floor(hits/KO*faces.length));+ head.textContent=faces[i];+ }+ fill.style.width=Math.min(100,hits/KO*100)+'%';+ hitsEl.textContent=hits+' hit'+(hits===1?'':'s');+ if(hits>=KO){+ done=true;+ koSfx();+ var secs=((Date.now()-startT)/1000).toFixed(1);+ banner.textContent='K.O.! 🥊 '+secs+'s';+ if(!hasPhoto()) head.textContent='😵';+ left.disabled=true; right.disabled=true;+ again.classList.remove('hidden');+ }+ }++ function reset(){+ hits=0; done=false; fill.style.width='0%'; hitsEl.textContent='0 hits';+ banner.textContent='Tap LEFT & RIGHT to box!';+ left.disabled=false; right.disabled=false;+ again.classList.add('hidden');+ if(!hasPhoto()) head.textContent='😠';+ }++ left.addEventListener('pointerdown',function(){ punch('left'); });+ right.addEventListener('pointerdown',function(){ punch('right'); });+ again.addEventListener('pointerdown',reset);++ facePick.addEventListener('change',function(e){+ var file=e.target.files&&e.target.files[0];+ if(!file) return;+ var reader=new FileReader();+ reader.onload=function(){+ var img=new Image();+ img.onload=function(){+ try{+ var max=360,s=Math.min(1,max/Math.max(img.width,img.height));+ var c=document.createElement('canvas');+ c.width=Math.round(img.width*s); c.height=Math.round(img.height*s);+ c.getContext('2d').drawImage(img,0,0,c.width,c.height);+ setFace(c.toDataURL('image/jpeg',0.82));+ }catch(err){ setFace(reader.result); }+ };+ img.onerror=function(){ setFace(reader.result); };+ img.src=reader.result;+ };+ reader.readAsDataURL(file);+ });+})();+</script>