@mae_arcade · 6/20/2026, 2:18:35 AM
Initial version — all lines are new.
+<style>+ html,body{height:100%;margin:0;overflow:hidden;background:#0d3b2e;}+ *{box-sizing:border-box;}+ #wrap{position:relative;height:100%;width:100%;display:flex;flex-direction:column;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;background:radial-gradient(120% 80% at 50% 0%,#15573f 0%,#0e4733 55%,#0a3527 100%);-webkit-tap-highlight-color:transparent;touch-action:manipulation;user-select:none;-webkit-user-select:none;color:#fff;}+ #head{padding:.95rem 1.2rem .2rem;}+ #head h1{margin:0;font-family:"Instrument Serif",Georgia,"Times New Roman",serif;font-weight:400;font-size:2rem;line-height:1;color:#fff;}+ #tabs{display:inline-flex;margin-top:.5rem;background:rgba(0,0,0,.25);border:1px solid rgba(255,255,255,.14);border-radius:999px;padding:3px;}+ .tab{border:0;background:transparent;color:rgba(255,255,255,.7);font-size:.78rem;font-weight:800;padding:.34rem .9rem;border-radius:999px;cursor:pointer;}+ .tab.on{background:#fff;color:#0e4733;}+ #hud{display:flex;gap:8px;padding:.45rem 1.2rem .2rem;flex-wrap:wrap;}+ .pill{background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.18);border-radius:999px;font-size:.72rem;font-weight:800;padding:.32rem .7rem;}+ .mode{flex:1;min-height:0;display:flex;flex-direction:column;}+ /* ---- collect ---- */+ #albumWrap{flex:1;min-height:0;overflow-y:auto;padding:.6rem 1rem 1rem;-webkit-overflow-scrolling:touch;}+ #album{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;}+ .slot{position:relative;aspect-ratio:3/4;border-radius:11px;background:rgba(0,0,0,.22);border:1px dashed rgba(255,255,255,.16);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;overflow:hidden;}+ .slot.got{background:linear-gradient(160deg,#1d6b4d,#124e38);border:1px solid rgba(255,255,255,.22);box-shadow:0 4px 12px rgba(0,0,0,.25);}+ .slot.foil.got{background:linear-gradient(160deg,#7a5e12,#a8841f 45%,#5e470c);border-color:#ffd86b;box-shadow:0 0 14px rgba(255,200,80,.4);}+ .slot .fl{font-size:2rem;line-height:1;filter:grayscale(1) opacity(.18);}+ .slot.got .fl{filter:none;}+ .slot .cc{font-size:.58rem;font-weight:800;letter-spacing:.04em;color:rgba(255,255,255,.35);}+ .slot.got .cc{color:#eafff2;}+ .slot.foil.got::after{content:"";position:absolute;inset:0;background:linear-gradient(115deg,transparent 30%,rgba(255,255,255,.55) 48%,transparent 66%);background-size:250% 100%;animation:shine 2.6s linear infinite;pointer-events:none;}+ @keyframes shine{0%{background-position:140% 0}100%{background-position:-40% 0}}+ .slot .num{position:absolute;top:3px;left:5px;font-size:.5rem;font-weight:800;color:rgba(255,255,255,.3);}+ .slot.got .num{color:rgba(255,255,255,.6);}+ /* ---- team / pitch ---- */+ #teamWrap{padding:.5rem 1rem 1rem;}+ #pitch{position:relative;flex:1;min-height:0;border-radius:16px;overflow:hidden;border:2px solid rgba(255,255,255,.18);+ background:repeating-linear-gradient(0deg,#1c7a4f 0 11%,#198047 11% 22%);}+ #pitch::before{content:"";position:absolute;left:8%;right:8%;top:50%;height:2px;background:rgba(255,255,255,.3);}+ #pitch .circle{position:absolute;left:50%;top:50%;width:26%;aspect-ratio:1;border:2px solid rgba(255,255,255,.3);border-radius:50%;transform:translate(-50%,-50%);}+ #pitch .box{position:absolute;left:24%;right:24%;height:11%;border:2px solid rgba(255,255,255,.28);}+ #pitch .box.top{top:0;border-top:0;}+ #pitch .box.bot{bottom:0;border-bottom:0;}+ .pos{position:absolute;transform:translate(-50%,-50%);display:flex;flex-direction:column;align-items:center;gap:3px;cursor:pointer;width:22%;}+ .av{width:54px;height:54px;border-radius:50%;background:rgba(0,0,0,.35) center/cover no-repeat;border:2px solid rgba(255,255,255,.5);display:flex;align-items:center;justify-content:center;position:relative;box-shadow:0 3px 8px rgba(0,0,0,.35);}+ .av .plus{font-size:1.5rem;font-weight:300;color:rgba(255,255,255,.8);line-height:1;}+ .av .sh{position:absolute;bottom:-4px;right:-4px;min-width:18px;height:18px;padding:0 3px;border-radius:9px;background:#ffd24d;color:#3a2400;font-size:.6rem;font-weight:900;display:flex;align-items:center;justify-content:center;border:1px solid rgba(0,0,0,.15);}+ .pos .nm{font-size:.6rem;font-weight:800;text-shadow:0 1px 3px rgba(0,0,0,.6);max-width:70px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center;}+ .pos .ro{font-size:.52rem;font-weight:700;color:rgba(255,255,255,.65);}+ #foot{padding:.5rem 1.2rem max(1rem,env(safe-area-inset-bottom));display:flex;justify-content:center;align-items:center;min-height:3.2rem;}+ #open{border:0;border-radius:999px;background:linear-gradient(135deg,#ffd24d,#ff8a1f);color:#3a2400;font-weight:900;font-size:1rem;padding:.9rem 1.8rem;cursor:pointer;box-shadow:0 10px 26px rgba(255,140,30,.4);}+ #open:active{transform:scale(.96);}+ #open:disabled{opacity:.5;}+ #shareBtn{border:0;border-radius:999px;background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.25);color:#fff;font-weight:800;font-size:.92rem;padding:.8rem 1.5rem;cursor:pointer;display:flex;align-items:center;gap:.4rem;}+ #shareBtn:active{transform:scale(.96);}+ /* ---- share preview ---- */+ #shareView{position:absolute;inset:0;z-index:14;display:none;flex-direction:column;align-items:center;justify-content:center;background:rgba(4,18,13,.9);backdrop-filter:blur(8px);padding:1.1rem;}+ #shareImg{max-width:100%;max-height:74%;border-radius:14px;box-shadow:0 16px 40px rgba(0,0,0,.5);display:none;}+ #shareLoad{color:rgba(255,255,255,.7);font-size:.85rem;font-weight:700;}+ #shareCap{color:rgba(255,255,255,.75);font-size:.78rem;font-weight:600;text-align:center;margin:.9rem 0 .2rem;max-width:18rem;line-height:1.35;}+ #shareRow{display:flex;gap:.6rem;margin-top:.8rem;}+ #shareRow button{border:0;border-radius:999px;font-weight:800;font-size:.88rem;padding:.7rem 1.4rem;cursor:pointer;}+ #shareNative{background:#ffd24d;color:#3a2400;}+ #shareClose{background:rgba(255,255,255,.15);color:#fff;}+ /* ---- reveal / done ---- */+ #reveal{position:absolute;inset:0;z-index:10;display:none;flex-direction:column;align-items:center;justify-content:center;background:rgba(6,28,21,.82);backdrop-filter:blur(6px);padding:1.2rem;text-align:center;}+ #card{width:60%;max-width:210px;aspect-ratio:3/4;border-radius:18px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.4rem;position:relative;overflow:hidden;box-shadow:0 18px 50px rgba(0,0,0,.5);transform:scale(.6);opacity:0;transition:transform .35s cubic-bezier(.2,1.3,.5,1),opacity .25s;}+ #card.in{transform:scale(1);opacity:1;}+ #card .bigfl{font-size:5rem;line-height:1;}+ #card .name{font-size:1.05rem;font-weight:800;}+ #card.common{background:linear-gradient(160deg,#1d6b4d,#0f4733);border:2px solid rgba(255,255,255,.2);}+ #card.foil{background:linear-gradient(160deg,#8a6a14,#c79a23 45%,#6b520e);border:2px solid #ffd86b;}+ #card.foil::after{content:"";position:absolute;inset:0;background:linear-gradient(115deg,transparent 35%,rgba(255,255,255,.6) 50%,transparent 65%);background-size:250% 100%;animation:shine 2s linear infinite;}+ #tag{margin-top:1rem;font-weight:900;font-size:1.05rem;min-height:1.3em;}+ #tag.dupe{color:#ffcaa8;}+ #tag.new{color:#9dffc8;}+ #revHint{margin-top:.5rem;font-size:.72rem;color:rgba(255,255,255,.6);font-weight:600;}+ #count{margin-top:.6rem;font-size:.7rem;color:rgba(255,255,255,.45);font-weight:700;}+ #done{position:absolute;inset:0;z-index:11;display:none;flex-direction:column;align-items:center;justify-content:center;background:rgba(6,28,21,.85);backdrop-filter:blur(6px);text-align:center;padding:1.4rem;}+ #done h2{font-family:"Instrument Serif",Georgia,serif;font-style:italic;font-size:2.2rem;margin:0;color:#ffe08a;}+ #done p{color:#cfe;font-size:.85rem;margin:.5rem 0 1.2rem;}+ #done button{border:0;border-radius:999px;background:#fff;color:#0e4733;font-weight:800;font-size:.9rem;padding:.7rem 1.4rem;cursor:pointer;}+ .cf{position:absolute;width:8px;height:8px;border-radius:2px;pointer-events:none;z-index:12;}+ /* ---- player editor sheet ---- */+ #sheet{position:absolute;inset:0;z-index:13;display:none;align-items:flex-end;background:rgba(4,20,15,.55);backdrop-filter:blur(3px);}+ #sheetIn{width:100%;background:#0e4733;border-top:1px solid rgba(255,255,255,.15);border-radius:18px 18px 0 0;padding:1rem 1.1rem max(1.1rem,env(safe-area-inset-bottom));box-shadow:0 -12px 30px rgba(0,0,0,.4);}+ #sheetHd{display:flex;align-items:center;gap:.7rem;margin-bottom:.8rem;}+ #sheetAv{width:64px;height:64px;border-radius:50%;background:rgba(0,0,0,.3) center/cover no-repeat;border:2px solid rgba(255,255,255,.4);display:flex;align-items:center;justify-content:center;font-size:1.6rem;color:rgba(255,255,255,.7);flex:0 0 auto;}+ #sheetRole{font-size:.95rem;font-weight:800;}+ #sheetRole small{display:block;font-weight:600;color:rgba(255,255,255,.6);font-size:.72rem;margin-top:2px;}+ .field{display:flex;gap:.6rem;margin-bottom:.7rem;}+ .field input{flex:1;background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.2);color:#fff;border-radius:11px;padding:.6rem .75rem;font-size:.9rem;font-family:inherit;}+ .field input#nmNum{flex:0 0 64px;text-align:center;}+ .field input::placeholder{color:rgba(255,255,255,.45);}+ .sBtn{border:0;border-radius:11px;font-weight:800;font-size:.85rem;padding:.7rem 1rem;cursor:pointer;}+ #pickBtn{width:100%;background:rgba(255,255,255,.14);color:#fff;margin-bottom:.7rem;}+ #sheetRow{display:flex;gap:.6rem;}+ #rm{flex:0 0 auto;background:rgba(255,120,120,.18);color:#ffd4d4;}+ #sheetDone{flex:1;background:#ffd24d;color:#3a2400;}+</style>+<div id="wrap">+ <div id="head">+ <h1>Sticker Album</h1>+ <div id="tabs">+ <button class="tab on" id="tabCollect">Collect</button>+ <button class="tab" id="tabTeam">My XI</button>+ </div>+ </div>+ <div id="hud">+ <span class="pill" id="pctPill">0/32</span>+ <span class="pill" id="repPill">0 dupes</span>+ <span class="pill" id="packPill">0 packs</span>+ <span class="pill" id="teamPill" style="display:none">0/11 picked</span>+ </div>++ <div id="collectWrap" class="mode"><div id="albumWrap"><div id="album"></div></div></div>+ <div id="teamWrap" class="mode" style="display:none"><div id="pitch"></div></div>++ <div id="foot">+ <button id="open">Open a pack ⚽</button>+ <button id="shareBtn" style="display:none">📷 Share lineup</button>+ </div>++ <div id="reveal">+ <div id="card"></div>+ <div id="tag"></div>+ <div id="revHint">tap to keep going</div>+ <div id="count"></div>+ </div>+ <div id="done">+ <h2>Album complete!</h2>+ <p>All 32 stickers collected. Legend.</p>+ <button id="restart">start a new album</button>+ </div>++ <div id="sheet">+ <div id="sheetIn">+ <div id="sheetHd">+ <div id="sheetAv">+</div>+ <div id="sheetRole">Player<small id="sheetSub"></small></div>+ </div>+ <input id="pick" type="file" accept="image/*" hidden>+ <button class="sBtn" id="pickBtn">Choose a photo</button>+ <div class="field">+ <input id="nm" placeholder="Name" maxlength="18">+ <input id="nmNum" type="number" inputmode="numeric" placeholder="#" min="0" max="99">+ </div>+ <div id="sheetRow">+ <button class="sBtn" id="rm">Remove</button>+ <button class="sBtn" id="sheetDone">Done</button>+ </div>+ </div>+ </div>++ <div id="shareView">+ <div id="shareLoad">Rendering your lineup…</div>+ <img id="shareImg" alt="My starting XI">+ <p id="shareCap">Press & hold the image to save it, then share anywhere 📷</p>+ <div id="shareRow">+ <button id="shareNative" style="display:none">Share…</button>+ <button id="shareClose">Done</button>+ </div>+ </div>+</div>+<script>+(function(){+ var LL=window.liveloop||null;+ var muted = LL ? LL.muted : true;+ if(LL && LL.onMute){ try{ LL.onMute(function(m){ muted=m; }); }catch(e){} }+ if(LL && LL.declareMedia){ try{ LL.declareMedia({sound:true}); }catch(e){} }+ var _ac=null;+ function actx(){ if(!_ac){ try{ _ac=new (window.AudioContext||window.webkitAudioContext)(); }catch(e){ _ac=null; } } return _ac; }+ function blip(f,type,vol,dur){+ if(muted) return; var c=actx(); if(!c) return;+ var t=c.currentTime, o=c.createOscillator(), g=c.createGain();+ o.type=type||'triangle'; o.frequency.setValueAtTime(f,t);+ g.gain.setValueAtTime(0.0001,t); g.gain.exponentialRampToValueAtTime(vol||0.12,t+0.01);+ g.gain.exponentialRampToValueAtTime(0.0001,t+(dur||0.18));+ o.connect(g); g.connect(c.destination); o.start(t); o.stop(t+(dur||0.18)+0.04);+ }+ function rip(){+ if(muted) return; var c=actx(); if(!c) return;+ var t=c.currentTime, n=Math.floor(c.sampleRate*0.18), b=c.createBuffer(1,n,c.sampleRate), d=b.getChannelData(0);+ for(var i=0;i<n;i++){ d[i]=(Math.random()*2-1)*Math.pow(1-i/n,1.2); }+ var s=c.createBufferSource(); s.buffer=b; var f=c.createBiquadFilter(); f.type='highpass'; f.frequency.value=1800;+ var g=c.createGain(); g.gain.value=0.12; s.connect(f); f.connect(g); g.connect(c.destination); s.start(t);+ }+ function sparkle(){ blip(880,'sine',0.09,0.3); setTimeout(function(){blip(1318.5,'sine',0.08,0.4);},90); setTimeout(function(){blip(1760,'sine',0.07,0.5);},190); }+ function fanfare(){ var n=[523.25,659.25,783.99,1046.5,1318.5]; for(var i=0;i<n.length;i++){ (function(i){ setTimeout(function(){ blip(n[i],'triangle',0.13,0.5); },i*100); })(i); } }++ var STICKERS=[+ {f:'🇧🇷',c:'BRA',L:1},{f:'🇦🇷',c:'ARG',L:1},{f:'🇫🇷',c:'FRA',L:1},{f:'🇩🇪',c:'GER',L:1},+ {f:'🇪🇸',c:'ESP',L:1},{f:'🇵🇹',c:'POR',L:1},{f:'🇮🇹',c:'ITA',L:1},{f:'🇳🇱',c:'NED',L:1},+ {f:'🇬🇧',c:'ENG',L:0},{f:'🇧🇪',c:'BEL',L:0},{f:'🇭🇷',c:'CRO',L:0},{f:'🇺🇾',c:'URU',L:0},+ {f:'🇲🇽',c:'MEX',L:0},{f:'🇺🇸',c:'USA',L:0},{f:'🇯🇵',c:'JPN',L:0},{f:'🇰🇷',c:'KOR',L:0},+ {f:'🇲🇦',c:'MAR',L:0},{f:'🇸🇳',c:'SEN',L:0},{f:'🇬🇭',c:'GHA',L:0},{f:'🇨🇲',c:'CMR',L:0},+ {f:'🇨🇴',c:'COL',L:0},{f:'🇨🇱',c:'CHI',L:0},{f:'🇪🇨',c:'ECU',L:0},{f:'🇵🇾',c:'PAR',L:0},+ {f:'🇨🇭',c:'SUI',L:0},{f:'🇩🇰',c:'DEN',L:0},{f:'🇵🇱',c:'POL',L:0},{f:'🇷🇸',c:'SRB',L:0},+ {f:'🇦🇺',c:'AUS',L:0},{f:'🇨🇦',c:'CAN',L:0},{f:'🇳🇬',c:'NGA',L:0},{f:'🇶🇦',c:'QAT',L:0}+ ];+ var N=STICKERS.length;+ // The cup ends 19 Jul 2026. After that the album stays viewable with what+ // you've collected, but no more packs open. Building your XI is never gated.+ var DEADLINE=Date.UTC(2026,6,20,0,0,0); // 00:00 UTC 20 Jul = end of the 19th+ function expired(){ try{ return Date.now()>=DEADLINE; }catch(e){ return false; } }+ var commons=[], legends=[];+ for(var i=0;i<N;i++){ (STICKERS[i].L?legends:commons).push(i); }++ // 4-3-3 on a vertical pitch (attack at top, keeper at bottom)+ var FORMATION=[+ {k:'st', ro:'ST', num:9, x:50,y:13},+ {k:'lw', ro:'LW', num:11,x:19,y:22},+ {k:'rw', ro:'RW', num:7, x:81,y:22},+ {k:'cm1',ro:'CM', num:8, x:27,y:43},+ {k:'am', ro:'CAM',num:10,x:50,y:38},+ {k:'cm2',ro:'CM', num:6, x:73,y:43},+ {k:'lb', ro:'LB', num:3, x:15,y:65},+ {k:'cb1',ro:'CB', num:4, x:38,y:68},+ {k:'cb2',ro:'CB', num:2, x:62,y:68},+ {k:'rb', ro:'RB', num:5, x:85,y:65},+ {k:'gk', ro:'GK', num:1, x:50,y:87}+ ];++ var owned={}, repeats=0, packs=0, team={}, albumDone=false;+ function load(){+ try{ if(LL && LL.storage && LL.storage.get){ LL.storage.get().then(function(s){+ if(s){ owned=s.owned||{}; repeats=s.repeats||0; packs=s.packs||0; team=s.team||{}; } renderAll();+ }).catch(renderAll); } else renderAll(); }catch(e){ renderAll(); }+ }+ function save(){ try{ if(LL && LL.storage && LL.storage.set) LL.storage.set({owned:owned,repeats:repeats,packs:packs,team:team}); }catch(e){} }++ var albumEl=document.getElementById('album'), pitchEl=document.getElementById('pitch');+ var pctPill=document.getElementById('pctPill'), repPill=document.getElementById('repPill'), packPill=document.getElementById('packPill'), teamPill=document.getElementById('teamPill');+ var openBtn=document.getElementById('open'), shareBtn=document.getElementById('shareBtn');+ var shareView=document.getElementById('shareView'), shareImg=document.getElementById('shareImg'),+ shareLoad=document.getElementById('shareLoad'), shareNative=document.getElementById('shareNative');+ var revealEl=document.getElementById('reveal'), cardEl=document.getElementById('card'), tagEl=document.getElementById('tag'), countEl=document.getElementById('count');+ var doneEl=document.getElementById('done');+ var wrap=document.getElementById('wrap');+ var collectWrap=document.getElementById('collectWrap'), teamWrap=document.getElementById('teamWrap');+ var tabCollect=document.getElementById('tabCollect'), tabTeam=document.getElementById('tabTeam');++ /* ============ collect mode ============ */+ function buildAlbum(){+ albumEl.innerHTML='';+ for(var i=0;i<N;i++){ (function(i){+ var s=STICKERS[i];+ var d=document.createElement('div'); d.className='slot'+(s.L?' foil':'')+(owned[i]?' got':'');+ d.innerHTML='<span class="num">'+(i+1)+'</span><span class="fl">'+s.f+'</span><span class="cc">'+s.c+'</span>';+ d.id='slot'+i; albumEl.appendChild(d);+ })(i); }+ }+ function ownedCount(){ var n=0; for(var k in owned) if(owned[k]) n++; return n; }+ function renderHud(){+ var n=ownedCount();+ pctPill.textContent=n+'/'+N;+ repPill.textContent=repeats+' dupe'+(repeats===1?'':'s');+ packPill.textContent=packs+' pack'+(packs===1?'':'s');+ teamPill.textContent=teamCount()+'/11 picked';+ }+ function refreshOpen(){+ if(expired()){ openBtn.disabled=true; openBtn.textContent='Tournament over ⚽'; }+ }++ function pickOne(){+ var pool = (Math.random()<0.16 && legends.length) ? legends : commons;+ return pool[Math.floor(Math.random()*pool.length)];+ }+ var queue=[], showing=false;+ function openPack(){+ if(showing || expired()) return;+ packs++; rip();+ queue=[]; for(var k=0;k<5;k++) queue.push(pickOne());+ showNext(); save();+ }+ function showNext(){+ if(queue.length===0){ showing=false; revealEl.style.display='none';+ if(ownedCount()>=N && !albumDone){ albumDone=true; doneEl.style.display='flex'; fanfare(); confetti(); }+ return;+ }+ showing=true; revealEl.style.display='flex';+ var idx=queue.shift(), s=STICKERS[idx], isNew=!owned[idx];+ cardEl.className=s.L?'foil':'common';+ cardEl.innerHTML='<span class="bigfl">'+s.f+'</span><span class="name">'+s.c+'</span>';+ cardEl.classList.remove('in'); void cardEl.offsetWidth; cardEl.classList.add('in');+ if(s.L) sparkle(); else blip(660,'triangle',0.1,0.18);+ if(isNew){ owned[idx]=1; tagEl.textContent=s.L?'★ LEGEND! got it':'Got it!'; tagEl.className='new';+ var slot=document.getElementById('slot'+idx); if(slot){ slot.className='slot'+(s.L?' foil':'')+' got'; }+ } else { repeats++; tagEl.textContent='Repetida…'; tagEl.className='dupe'; }+ countEl.textContent=queue.length+' left in the pack';+ renderHud(); save();+ }++ /* ============ team mode ============ */+ function teamCount(){ var n=0; for(var k in team){ if(team[k] && (team[k].photo||team[k].name)) n++; } return n; }+ function buildPitch(){+ pitchEl.innerHTML='<div class="box top"></div><div class="box bot"></div><div class="circle"></div>';+ for(var i=0;i<FORMATION.length;i++){ (function(p){+ var el=document.createElement('div'); el.className='pos'; el.id='pos_'+p.k;+ el.style.left=p.x+'%'; el.style.top=p.y+'%';+ el.addEventListener('pointerdown',function(e){ e.stopPropagation(); openSheet(p); });+ pitchEl.appendChild(el); renderPos(p);+ })(FORMATION[i]); }+ }+ function renderPos(p){+ var el=document.getElementById('pos_'+p.k); if(!el) return;+ var t=team[p.k]||{}; var num=(t.num!=null&&t.num!=='')?t.num:p.num;+ var avStyle=t.photo?('background-image:url('+t.photo+')'):'';+ el.innerHTML=+ '<div class="av" style="'+avStyle+'">'+(t.photo?'':'<span class="plus">+</span>')+'<span class="sh">'+num+'</span></div>'++ '<div class="nm">'+(t.name?esc(t.name):p.ro)+'</div>'++ (t.name?'<div class="ro">'+p.ro+'</div>':'');+ }+ function esc(s){ return String(s).replace(/[&<>"]/g,function(c){return {'&':'&','<':'<','>':'>','"':'"'}[c];}); }++ // ---- player editor sheet ----+ var sheet=document.getElementById('sheet'), sheetAv=document.getElementById('sheetAv'),+ sheetRole=document.getElementById('sheetRole'), sheetSub=document.getElementById('sheetSub'),+ pick=document.getElementById('pick'), nm=document.getElementById('nm'), nmNum=document.getElementById('nmNum');+ var editKey=null, editPos=null;+ function openSheet(p){+ editKey=p.k; editPos=p; var t=team[p.k]||{};+ sheetRole.childNodes[0].nodeValue=p.ro; sheetSub.textContent='photo · name · number';+ nm.value=t.name||''; nmNum.value=(t.num!=null&&t.num!=='')?t.num:p.num;+ if(t.photo){ sheetAv.style.backgroundImage='url('+t.photo+')'; sheetAv.textContent=''; }+ else { sheetAv.style.backgroundImage=''; sheetAv.textContent='+'; }+ sheet.style.display='flex'; blip(560,'sine',0.06,0.12);+ }+ function closeSheet(){ sheet.style.display='none'; editKey=null; editPos=null; }+ function ensure(){ if(!team[editKey]) team[editKey]={}; return team[editKey]; }++ document.getElementById('pickBtn').addEventListener('pointerdown',function(e){ e.preventDefault(); pick.click(); });+ pick.addEventListener('change',function(){+ var f=pick.files&&pick.files[0]; if(!f) return;+ var rd=new FileReader();+ rd.onload=function(){+ var im=new Image();+ im.onload=function(){+ var S=96, cv=document.createElement('canvas'); cv.width=S; cv.height=S;+ var ctx=cv.getContext('2d');+ var sc=Math.max(S/im.width,S/im.height), sw=S/sc, sh=S/sc;+ ctx.drawImage(im,(im.width-sw)/2,(im.height-sh)/2,sw,sh,0,0,S,S);+ // 11 stickers share a ~64KB liveloop.storage budget, so cap each photo+ // to ~4.8KB (step quality down for busy images) — else a full XI silently+ // overflows and never persists.+ var q=0.55, data=cv.toDataURL('image/jpeg',q);+ while(data.length>4800 && q>0.3){ q-=0.1; data=cv.toDataURL('image/jpeg',q); }+ ensure().photo=data;+ sheetAv.style.backgroundImage='url('+data+')'; sheetAv.textContent='';+ save();+ };+ im.src=rd.result;+ };+ rd.readAsDataURL(f);+ pick.value='';+ });+ nm.addEventListener('input',function(){ ensure().name=nm.value; });+ nmNum.addEventListener('input',function(){ var v=nmNum.value; ensure().num=(v===''?'':Math.max(0,Math.min(99,parseInt(v,10)||0))); });+ document.getElementById('rm').addEventListener('pointerdown',function(e){+ e.stopPropagation(); delete team[editKey]; if(editPos) renderPos(editPos); renderHud(); save(); closeSheet();+ });+ document.getElementById('sheetDone').addEventListener('pointerdown',function(e){+ e.stopPropagation();+ var t=team[editKey];+ if(t && !t.photo && !(t.name&&t.name.trim())){ delete team[editKey]; } // nothing entered → leave empty+ if(editPos) renderPos(editPos); renderHud(); save();+ blip(720,'triangle',0.1,0.18); closeSheet();+ });+ sheet.addEventListener('pointerdown',function(e){ if(e.target===sheet){ document.getElementById('sheetDone').dispatchEvent(new Event('pointerdown')); } });++ /* ============ shared ============ */+ function renderAll(){ albumDone=(ownedCount()>=N); buildAlbum(); buildPitch(); renderHud(); refreshOpen(); }++ var mode='collect';+ function setMode(m){+ mode=m;+ var collect=(m==='collect');+ tabCollect.classList.toggle('on',collect); tabTeam.classList.toggle('on',!collect);+ collectWrap.style.display=collect?'flex':'none';+ teamWrap.style.display=collect?'none':'flex';+ pctPill.style.display=collect?'':'none'; repPill.style.display=collect?'':'none'; packPill.style.display=collect?'':'none';+ teamPill.style.display=collect?'none':'';+ openBtn.style.display=collect?'':'none'; shareBtn.style.display=collect?'none':'';+ blip(collect?520:660,'sine',0.05,0.1);+ }+ tabCollect.addEventListener('pointerdown',function(){ setMode('collect'); });+ tabTeam.addEventListener('pointerdown',function(){ setMode('team'); });++ revealEl.addEventListener('pointerdown',function(){ if(showing) showNext(); });+ openBtn.addEventListener('pointerdown',function(e){ e.preventDefault(); openPack(); });+ document.getElementById('restart').addEventListener('pointerdown',function(e){+ e.stopPropagation(); owned={}; repeats=0; packs=0; doneEl.style.display='none'; save(); renderAll();+ });++ /* ---- share lineup as an image ---- */+ function loadImg(src){ return new Promise(function(res){ var im=new Image(); im.onload=function(){res(im);}; im.onerror=function(){res(null);}; im.src=src; }); }+ function roundRect(ctx,x,y,w,h,r){ ctx.beginPath(); ctx.moveTo(x+r,y); ctx.arcTo(x+w,y,x+w,y+h,r); ctx.arcTo(x+w,y+h,x,y+h,r); ctx.arcTo(x,y+h,x,y,r); ctx.arcTo(x,y,x+w,y,r); ctx.closePath(); }+ function paintLineup(ctx,W,H,list){+ ctx.fillStyle='#0e4733'; ctx.fillRect(0,0,W,H);+ ctx.textAlign='center'; ctx.textBaseline='middle';+ ctx.fillStyle='#fff'; ctx.font='italic 700 62px Georgia, "Times New Roman", serif';+ ctx.fillText('My Starting XI', W/2, 78);+ var px=40,py=148,pw=W-80,ph=H-228;+ ctx.save(); roundRect(ctx,px,py,pw,ph,28); ctx.clip();+ var bands=7; for(var i=0;i<bands;i++){ ctx.fillStyle=(i%2)?'#198047':'#1c7a4f'; ctx.fillRect(px,py+ph*i/bands,pw,ph/bands+1); }+ ctx.strokeStyle='rgba(255,255,255,.32)'; ctx.lineWidth=4;+ ctx.beginPath(); ctx.moveTo(px,py+ph/2); ctx.lineTo(px+pw,py+ph/2); ctx.stroke();+ ctx.beginPath(); ctx.arc(px+pw/2,py+ph/2,pw*0.13,0,Math.PI*2); ctx.stroke();+ var bw=pw*0.52,bh=ph*0.11,bx=px+(pw-bw)/2;+ ctx.strokeRect(bx,py,bw,bh); ctx.strokeRect(bx,py+ph-bh,bw,bh);+ ctx.restore();+ ctx.strokeStyle='rgba(255,255,255,.4)'; ctx.lineWidth=5; roundRect(ctx,px,py,pw,ph,28); ctx.stroke();+ list.forEach(function(o){+ var p=o.p, t=team[p.k]||{}, cx=px+p.x/100*pw, cy=py+p.y/100*ph, R=62;+ ctx.save(); ctx.beginPath(); ctx.arc(cx,cy,R,0,Math.PI*2); ctx.closePath();+ if(o.im){ ctx.clip(); var s=Math.max(2*R/o.im.width,2*R/o.im.height), sw=2*R/s, sh=2*R/s;+ ctx.drawImage(o.im,(o.im.width-sw)/2,(o.im.height-sh)/2,sw,sh,cx-R,cy-R,2*R,2*R); }+ else { ctx.fillStyle='rgba(0,0,0,.4)'; ctx.fill(); }+ ctx.restore();+ ctx.strokeStyle='rgba(255,255,255,.85)'; ctx.lineWidth=5; ctx.beginPath(); ctx.arc(cx,cy,R,0,Math.PI*2); ctx.stroke();+ if(!o.im){ ctx.fillStyle='rgba(255,255,255,.78)'; ctx.font='700 28px system-ui,sans-serif'; ctx.fillText(p.ro,cx,cy); }+ var num=(t.num!=null&&t.num!=='')?t.num:p.num;+ ctx.beginPath(); ctx.arc(cx+R*0.74,cy+R*0.74,25,0,Math.PI*2); ctx.fillStyle='#ffd24d'; ctx.fill();+ ctx.fillStyle='#3a2400'; ctx.font='900 26px system-ui,sans-serif'; ctx.fillText(String(num),cx+R*0.74,cy+R*0.76);+ var label=t.name?t.name:p.ro;+ ctx.fillStyle='#fff'; ctx.font='800 28px system-ui,sans-serif';+ ctx.shadowColor='rgba(0,0,0,.6)'; ctx.shadowBlur=8; ctx.shadowOffsetY=2;+ ctx.fillText(label.length>16?label.slice(0,16):label, cx, cy+R+30);+ ctx.shadowColor='transparent';+ });+ ctx.fillStyle='rgba(255,255,255,.55)'; ctx.font='600 25px system-ui,sans-serif';+ ctx.fillText('made on liveloop', W/2, H-38);+ }+ function shareLineup(){+ shareView.style.display='flex'; shareImg.style.display='none'; shareLoad.style.display='block';+ shareNative.style.display='none';+ var W=1080,H=1440, cv=document.createElement('canvas'); cv.width=W; cv.height=H;+ var ctx=cv.getContext('2d');+ var jobs=FORMATION.map(function(p){ var t=team[p.k]||{};+ return t.photo?loadImg(t.photo).then(function(im){return {p:p,im:im};}):Promise.resolve({p:p,im:null}); });+ Promise.all(jobs).then(function(list){+ paintLineup(ctx,W,H,list);+ shareImg.src=cv.toDataURL('image/jpeg',0.9);+ shareImg.style.display='block'; shareLoad.style.display='none';+ blip(720,'triangle',0.1,0.2);+ // opportunistic native share (often blocked in a sandboxed iframe — fall back silently)+ try{+ if(navigator.canShare){ cv.toBlob(function(b){+ if(!b) return; var file=new File([b],'lineup.jpg',{type:'image/jpeg'});+ try{ if(navigator.canShare({files:[file]})){+ shareNative.style.display=''; shareNative.onclick=function(){ try{ navigator.share({files:[file],title:'My Starting XI'}); }catch(e){} };+ } }catch(e){}+ },'image/jpeg',0.9); }+ }catch(e){}+ });+ }+ shareBtn.addEventListener('pointerdown',function(e){ e.preventDefault(); shareLineup(); });+ document.getElementById('shareClose').addEventListener('pointerdown',function(e){ e.stopPropagation(); shareView.style.display='none'; });++ function confetti(){+ var COLS=['#ffd24d','#ff8a1f','#9dffc8','#7C5CFF','#fff'];+ var r=wrap.getBoundingClientRect();+ for(var i=0;i<32;i++){ (function(i){+ var p=document.createElement('span'); p.className='cf'; p.style.background=COLS[i%COLS.length];+ p.style.left=(r.width/2)+'px'; p.style.top=(r.height*0.4)+'px'; wrap.appendChild(p);+ var a=Math.random()*Math.PI*2, v=3+Math.random()*5, vx=Math.cos(a)*v, vy=Math.sin(a)*v-4, x=0,y=0,rot=0,life=0;+ function step(){ life+=16; x+=vx; y+=vy; vy+=0.25; rot+=9;+ p.style.transform='translate('+x+'px,'+y+'px) rotate('+rot+'deg)'; p.style.opacity=String(Math.max(0,1-life/1100));+ if(life<1100) requestAnimationFrame(step); else p.remove(); }+ requestAnimationFrame(step);+ })(i); }+ }++ load();+})();+</script>