<!-- wp:html --> <!-- Replace the entire old Custom HTML block with this code. --> <iframe title="Lucky random name picker" style="display:block;width:100%;max-width:1220px;height:1250px;margin:24px auto;border:0;border-radius:22px;" srcdoc="<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Lucky — Leave it to the wheel</title> <style> :root{color-scheme:dark;--bg:#101014;--card:#1a1a21;--line:#303039;--text:#f5f3fc;--muted:#9997aa;--lime:#d6fb79;--purple:#a79afa}*{box-sizing:border-box}body{margin:0;background:radial-gradient(ellipse at 60% 35%,#28203966,transparent 55%),var(--bg);color:var(--text);font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;min-height:0}button,input,textarea{font:inherit}button{cursor:pointer}button:disabled{cursor:not-allowed;opacity:.4}button:focus-visible,input:focus-visible,textarea:focus-visible{outline:2px solid var(--lime);outline-offset:4px}header{max-width:1320px;margin:auto;padding:30px 44px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #ffffff0d}.brand{font-size:27px;font-weight:800;letter-spacing:-1.4px;display:flex;align-items:center;gap:10px}.brand-icon{font-size:30px;color:var(--lime)}.pill{font-size:11px;font-weight:700;letter-spacing:1px;border:1px solid var(--line);border-radius:30px;padding:9px 14px;color:#bab7cb}.dot{display:inline-block;width:6px;height:6px;background:var(--lime);border-radius:50%;margin-right:8px}main{max-width:1220px;margin:0 auto;padding:42px 36px 24px}.intro .eyebrow{font-size:11px;letter-spacing:2.7px;color:var(--purple);font-weight:700}.intro h1{font-size:clamp(32px,4vw,48px);letter-spacing:-2px;margin:12px 0 10px;line-height:1.12}.intro h1 span{color:var(--lime)}.intro p{color:var(--muted);margin:0;font-size:14px}.workspace{display:grid;grid-template-columns:350px minmax(0,1fr);gap:40px;margin-top:32px;align-items:start}.panel{background:linear-gradient(140deg,#202027,#19191f);border:1px solid var(--line);border-radius:22px;padding:24px}.panel-title{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.panel h2{font-size:16px;margin:0;letter-spacing:-.3px}.count{background:#a79afa20;color:#c6bbff;padding:4px 9px;border-radius:7px;font-size:12px}.hint{color:var(--muted);font-size:12px;line-height:1.6;margin:8px 0 18px}label{display:block;font-size:12px;font-weight:600;margin-bottom:9px}textarea{resize:vertical;min-height:87px;max-height:200px;width:100%;border:1px solid #3a3945;border-radius:11px;background:#141419;color:var(--text);padding:12px;font-size:13px;line-height:1.5}textarea::placeholder{color:#6f6c80}.add{width:100%;padding:11px;background:#a99afa;color:#171122;border:0;border-radius:10px;font-weight:700;margin-top:10px;font-size:13px}.listhead{display:flex;justify-content:space-between;align-items:center;margin:24px 0 12px;font-size:10px;letter-spacing:1.5px;color:var(--muted)}.textbutton{border:0;background:none;color:#b1a5eb;font-size:11px;padding:5px;letter-spacing:0}.names{max-height:211px;overflow:auto;list-style:none;margin:0;padding:0;scrollbar-width:thin}.names li{display:flex;align-items:center;gap:10px;min-height:38px;border-bottom:1px solid #ffffff06;font-size:13px}.swatch{width:8px;height:8px;border-radius:50%;flex-shrink:0}.name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.remove{color:#777486;background:none;border:0;font-size:19px;padding:5px 8px}.remove:hover{color:#ffafba}.option{border-top:1px solid var(--line);margin-top:20px;padding-top:18px;display:flex;align-items:center;justify-content:space-between;gap:12px}.option label{margin:0;font-weight:500;font-size:12px}.option small{display:block;color:var(--muted);font-size:10px;margin-top:5px}.option input{width:32px;height:18px;accent-color:var(--lime);cursor:pointer}.stage{text-align:center;padding-top:0;min-width:0}.stage-top{display:flex;gap:9px;align-items:center;justify-content:center;font-size:10px;letter-spacing:2px;color:var(--muted);margin:4px 0 19px}.wheel-wrap{width:min(100%,418px);aspect-ratio:1;margin:0 auto;position:relative;filter:drop-shadow(0 12px 36px #0005)}.wheel-ring{width:100%;height:100%;border-radius:50%;padding:10px;background:linear-gradient(140deg,#4f4b65,#27242f);box-shadow:0 0 0 1px #72658a40,0 0 65px #a692ff0b}canvas#wheel{display:block;width:100%;height:100%;border-radius:50%;border:4px solid #17131f}.pointer{position:absolute;top:-9px;left:50%;transform:translateX(-50%);width:27px;height:38px;background:#f9f7ff;clip-path:polygon(0 0,100% 0,100% 48%,50% 100%,0 48%);filter:drop-shadow(0 3px 3px #0008);z-index:2}.hub{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:72px;height:72px;border-radius:50%;background:#19151f;border:6px solid #ffffffdc;display:grid;place-items:center;box-shadow:0 5px 16px #0005;font-size:29px;color:var(--lime)}.spin{margin-top:27px;background:var(--lime);color:#1a2510;border:0;border-radius:13px;padding:16px 48px;font-weight:800;font-size:16px;box-shadow:0 5px 25px #d6fb7910;transition:transform .2s}.spin:hover:enabled{transform:translateY(-2px)}.spin span{margin-right:9px}.status{font-size:12px;color:var(--muted);min-height:20px;margin:12px 0 0}.history{margin-top:32px;border-top:1px solid var(--line);padding:22px 0 4px;display:flex;align-items:center;gap:20px}.history-title{font-size:10px;letter-spacing:1.8px;color:var(--muted);white-space:nowrap}.history-list{display:flex;gap:8px;flex-wrap:wrap;list-style:none;padding:0;margin:0;font-size:12px}.history-list li{background:#24232c;border:1px solid #34313e;border-radius:8px;padding:8px 12px;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.empty-history{font-size:12px;color:#6e6b7d}footer{display:flex;justify-content:space-between;gap:12px;color:#696677;font-size:10px;padding:24px 0 10px}.message{font-size:12px;color:var(--lime);min-height:0;margin-top:9px}.message:empty{display:none}dialog{background:#23212c;color:var(--text);border:1px solid #5c526a;border-radius:26px;width:min(420px,calc(100% - 32px));padding:38px;text-align:center;box-shadow:0 20px 100px #0009}dialog::backdrop{background:#08070ebd;backdrop-filter:blur(8px)}.winner-icon{font-size:48px}.winner-label{color:var(--lime);letter-spacing:2px;font-size:11px;margin-top:20px}#winnerName{font-size:36px;overflow-wrap:anywhere;margin:12px 0;letter-spacing:-1px}dialog p{color:var(--muted);font-size:13px}dialog button{background:var(--lime);border:0;border-radius:12px;padding:13px 28px;font-weight:700;margin-top:13px;color:#1a2510}#confetti{position:fixed;inset:0;pointer-events:none;width:100%;height:100%;z-index:9}@media(min-width:1000px){.stage{padding-right:24px}}@media(max-width:760px){header{padding:20px 22px}main{padding:28px 20px}.workspace{grid-template-columns:1fr;gap:26px}.stage{grid-row:1}.wheel-wrap{width:min(80vw,360px)}.intro{text-align:center}.intro h1{letter-spacing:-1.2px}.intro p{line-height:1.6}.panel{padding:22px}.history{align-items:flex-start;flex-direction:column;gap:12px}footer{line-height:1.6}.pill{font-size:9px;padding:8px 10px}.spin{margin-top:24px}.names{max-height:190px}}@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important;transition:none!important}} </style> </head> <body> <header><div class="brand"><span class="brand-icon" aria-hidden="true">✳</span> lucky<span style="color:var(--lime)">.</span></div><div class="pill"><span class="dot"></span>A LITTLE CHANCE. A LOT OF FUN.</div></header> <main><div class="intro"><div class="eyebrow">THE RANDOM NAME PICKER</div><h1>Good names. <span>Great chances.</span></h1><p>Add your people, give it a spin, and let a little luck decide.</p></div> <div class="workspace"><section class="panel" aria-labelledby="namesTitle"><div class="panel-title"><h2 id="namesTitle">Who's in the mix?</h2><span id="count" class="count">0 names</span></div><p class="hint">Your next volunteer, giveaway winner, or lucky pick.</p><form id="addForm"><label for="entry">Add names</label><textarea id="entry" placeholder="e.g. Alex, Emma, Sam&#10;One per line or separated by commas" maxlength="12000"></textarea><button class="add" id="add" type="submit">+ Add to the wheel</button></form><div class="message" id="message" role="status"></div><div class="listhead">ON THE WHEEL <button class="textbutton" id="clear" type="button">Clear all</button></div><ul class="names" id="names"></ul><div class="option"><label for="noRepeat">Remove winner after each spin<small>Give everyone a turn in the spotlight.</small></label><input type="checkbox" id="noRepeat"></div></section> <section class="stage" aria-label="Random name wheel"><div class="stage-top"><span class="dot"></span>LET FATE TAKE A TURN</div><div class="wheel-wrap"><div class="pointer" aria-hidden="true"></div><div class="wheel-ring"><canvas id="wheel" width="900" height="900" aria-label="Wheel with equal-sized segments for each name"></canvas></div><div class="hub" aria-hidden="true">✳</div></div><button id="spin" class="spin"><span aria-hidden="true">↻</span> Spin the wheel</button><p id="status" class="status" role="status">Every name. An equal chance.</p></section></div> <section class="history" aria-label="Recent winners"><div class="history-title">✧ RECENT PICKS</div><ul id="history" class="history-list"></ul><span id="emptyHistory" class="empty-history">Your lucky streak starts here.</span></section><footer><span>Made for the moments you just can't decide.</span><span>No sign-up. Just a spin. ✳</span></footer></main> <dialog id="result"><div class="winner-icon" aria-hidden="true">✦</div><div class="winner-label">THE WHEEL HAS SPOKEN</div><h2 id="winnerName"></h2><p>A little luck brought you here.</p><button id="closeResult">Keep the good luck going</button></dialog><canvas id="confetti" aria-hidden="true"></canvas> <script> 'use strict'; const $=id=>document.getElementById(id),colors=['#c1afff','#d8f58b','#f7b6bc','#9cd8d4','#f6d59e','#a7bdfa','#ddbbdf','#b5d5a4']; let names=['Alex','Emma','Sam','Olivia','Noah','Mia'],history=[],angle=0,busy=false,pendingRemoval=null; try{const saved=JSON.parse(localStorage.getItem('lucky-v1'));if(saved&&Array.isArray(saved.names))names=saved.names.filter(n=>typeof n==='string'&&n.trim()).map(n=>n.slice(0,60)).slice(0,100);if(saved&&Array.isArray(saved.history))history=saved.history.filter(n=>typeof n==='string').map(n=>n.slice(0,60)).slice(0,8);$('noRepeat').checked=!!saved?.noRepeat;}catch{} function save(){try{localStorage.setItem('lucky-v1',JSON.stringify({names,history,noRepeat:$('noRepeat').checked}));}catch{}} function randomInt(n){const a=new Uint32Array(1),limit=4294967296-(4294967296%n);do{crypto.getRandomValues(a);}while(a[0]>=limit);return a[0]%n;} function draw(){const ctx=$('wheel').getContext('2d'),s=900,r=450;ctx.clearRect(0,0,s,s);ctx.save();ctx.translate(r,r);ctx.rotate(angle);const n=names.length||1,step=2*Math.PI/n;for(let i=0;i<n;i++){const start=-Math.PI/2+i*step;ctx.beginPath();ctx.moveTo(0,0);ctx.arc(0,0,r,start,start+step);ctx.closePath();ctx.fillStyle=names.length?colors[i%colors.length]:'#35303f';ctx.fill();ctx.strokeStyle='#18141d22';ctx.lineWidth=2;ctx.stroke();if(names.length){ctx.save();ctx.rotate(start+step/2);ctx.textAlign='right';ctx.textBaseline='middle';ctx.fillStyle='#272234';ctx.font=`600 ${n>35?12:n>20?18:n>12?23:30}px system-ui`;const max=n>20?16:22;let label=names[i];if(label.length>max)label=label.slice(0,max-1)+'…';ctx.fillText(label,r-34,0,290);ctx.restore();}}ctx.restore();} function render(){const list=$('names');list.replaceChildren();names.forEach((name,i)=>{const li=document.createElement('li'),dot=document.createElement('span'),label=document.createElement('span'),button=document.createElement('button');dot.className='swatch';dot.style.background=colors[i%colors.length];label.className='name';label.textContent=name;label.title=name;button.className='remove';button.textContent='×';button.setAttribute('aria-label','Remove '+name);button.disabled=busy;button.onclick=()=>{if(busy)return;names.splice(i,1);angle=0;save();render();};li.append(dot,label,button);list.append(li);});$('count').textContent=names.length+' name'+(names.length===1?'':'s');$('spin').disabled=busy||names.length===0;$('add').disabled=busy;$('clear').disabled=busy||names.length===0;$('entry').disabled=busy;$('noRepeat').disabled=busy;$('history').replaceChildren();history.forEach((name,i)=>{const li=document.createElement('li');li.textContent=(i===0?'✦ ':'')+name;li.title=name;$('history').append(li);});$('emptyHistory').hidden=history.length>0;if(!busy)$('status').textContent=names.length?`Every name. An equal chance. (${(100/names.length).toFixed(1)}% each)`:'Add a name to get things spinning.';draw();} $('addForm').onsubmit=e=>{e.preventDefault();if(busy)return;const entries=$('entry').value.split(/[,\n]+/).map(n=>n.trim()).filter(Boolean);let added=0,duplicates=0,limited=0;for(let name of entries){name=name.slice(0,60);if(names.some(n=>n.toLocaleLowerCase()===name.toLocaleLowerCase())){duplicates++;continue;}if(names.length>=100){limited++;continue;}names.push(name);added++;}$('message').textContent=entries.length?`${added} added.${duplicates?' Duplicate names skipped.':''}${limited?' Maximum 100 names.':''}`:'Type a name first.';if(added)$('entry').value='';angle=0;save();render();}; $('clear').onclick=()=>{if(busy)return;names=[];angle=0;$('message').textContent='Wheel cleared. Add your own names.';save();render();$('entry').focus();};$('noRepeat').onchange=save; $('spin').onclick=()=>{if(busy||!names.length)return;busy=true;$('message').textContent='';const index=randomInt(names.length),winner=names[index],step=2*Math.PI/names.length,target=(2*Math.PI-(index+.5)*step)%(2*Math.PI),start=angle%(2*Math.PI),distance=((target-start+2*Math.PI)%(2*Math.PI))+2*Math.PI*(6+randomInt(3));angle=start;render();$('status').textContent='A little suspense…';$('spin').textContent='Spinning…';const reduced=matchMedia('(prefers-reduced-motion: reduce)').matches,duration=reduced?150:4700,t0=performance.now();function tick(now){const p=Math.min((now-t0)/duration,1),ease=1-Math.pow(1-p,5);angle=start+distance*ease;draw();if(p<1){requestAnimationFrame(tick);return;}angle=target;draw();history.unshift(winner);history=history.slice(0,8);pendingRemoval=$('noRepeat').checked?index:null;$('winnerName').textContent=winner;$('result').showModal();$('status').textContent=winner+' is the lucky pick!';save();if(!reduced)celebrate();}requestAnimationFrame(tick);}; $('closeResult').onclick=()=>$('result').close();$('result').addEventListener('close',()=>{if(pendingRemoval!==null){names.splice(pendingRemoval,1);pendingRemoval=null;angle=0;}busy=false;$('spin').innerHTML='<span aria-hidden="true">↻</span> Spin the wheel';save();render();$('spin').focus();}); function celebrate(){const c=$('confetti'),ctx=c.getContext('2d');c.width=innerWidth;c.height=innerHeight;const pieces=Array.from({length:100},()=>({x:Math.random()*c.width,y:-Math.random()*c.height*.7,v:2+Math.random()*4,s:4+Math.random()*6,a:Math.random()*6,c:colors[Math.floor(Math.random()*colors.length)]})),start=performance.now();function frame(t){ctx.clearRect(0,0,c.width,c.height);for(const p of pieces){p.y+=p.v;p.x+=Math.sin(p.a+=.035);ctx.save();ctx.translate(p.x,p.y);ctx.rotate(p.a);ctx.globalAlpha=Math.max(0,1-(t-start)/3200);ctx.fillStyle=p.c;ctx.fillRect(-p.s/2,-p.s/2,p.s,p.s*1.5);ctx.restore();}if(t-start<3200)requestAnimationFrame(frame);else ctx.clearRect(0,0,c.width,c.height);}requestAnimationFrame(frame);} render(); </script><script> (function () { function fit() { if (!window.frameElement) return; const content = document.querySelector('main'); if (content) window.frameElement.style.height = Math.ceil(content.getBoundingClientRect().bottom + window.scrollY + 24) + 'px'; } new ResizeObserver(fit).observe(document.body); window.addEventListener('load', fit); fit(); })(); </script></body></html> "></iframe> <!-- /wp:html -->