@nova_builds · 6/9/2026, 10:51:33 PM
Initial version — all lines are new.
+<style>+ html,body{height:100%;margin:0;overflow:hidden;background:#FBF4E8;}+ *{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(110% 80% at 50% 0%,#FFFCF4 0%,#F8EEDB 75%,#F2E4C9 100%);-webkit-tap-highlight-color:transparent;touch-action:manipulation;user-select:none;-webkit-user-select:none;}+ #head{padding:1.15rem 1.25rem .3rem;}+ #head h1{margin:0;font-family:"Instrument Serif",Georgia,"Times New Roman",serif;font-weight:400;font-size:2.35rem;line-height:1;color:#43384f;}+ #head p{margin:.2rem 0 0;font-size:.8rem;color:#a3906f;font-weight:500;}+ #stage{flex:1;display:flex;align-items:center;justify-content:center;min-height:0;padding:.3rem 1.15rem;}+ #pickWrap{text-align:center;}+ #pick{border:0;border-radius:999px;background:linear-gradient(135deg,#7C5CFF,#FF5A1F);color:#fff;font-weight:700;font-size:1rem;padding:.95rem 1.7rem;cursor:pointer;box-shadow:0 10px 26px rgba(124,92,255,.35);}+ #pick:active{transform:scale(.96);}+ #pickNote{margin-top:.7rem;font-size:.72rem;color:#a3906f;font-weight:600;}+ #card{display:none;width:100%;max-width:300px;background:#FFFEFA;border-radius:18px;box-shadow:0 16px 40px rgba(90,60,30,.22);padding:12px 12px 14px;}+ #photo{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:12px;display:block;background:#eee;}+ #sw{display:flex;gap:6px;margin-top:10px;}+ .s{flex:1;border-radius:9px;height:46px;position:relative;}+ .s b{position:absolute;left:50%;bottom:4px;transform:translateX(-50%);font-size:.5rem;font-weight:700;letter-spacing:.02em;color:rgba(255,255,255,.92);text-shadow:0 1px 2px rgba(0,0,0,.4);font-family:ui-monospace,Menlo,monospace;}+ #vibe{margin:.8rem 0 .1rem;text-align:center;font-family:"Instrument Serif",Georgia,serif;font-style:italic;font-size:1.5rem;line-height:1.15;color:#43384f;}+ #sub{text-align:center;font-size:.62rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:#b2a183;}+ #foot{display:flex;gap:10px;justify-content:center;padding:.7rem 1.1rem 1.15rem;}+ #foot button{display:none;border:0;border-radius:999px;font-weight:700;font-size:.85rem;padding:.7rem 1.2rem;cursor:pointer;}+ #shuffle{background:rgba(255,255,255,.75);color:#6a5440;border:1px solid rgba(120,90,50,.25)!important;}+ #poster{background:#43384f;color:#FBF4E8;}+ #another{background:rgba(255,255,255,.75);color:#6a5440;border:1px solid rgba(120,90,50,.25)!important;}+ #file{display:none;}+ #resWrap{position:absolute;inset:0;z-index:5;display:none;flex-direction:column;align-items:center;justify-content:center;background:rgba(50,40,25,.55);backdrop-filter:blur(5px);padding:1.2rem;}+ #res{max-width:80%;max-height:70%;border-radius:12px;box-shadow:0 18px 44px rgba(0,0,0,.4);}+ #resWrap p{color:#FFF3DC;font-size:.78rem;font-weight:600;margin:.8rem 0 .5rem;}+ #back{border:0;border-radius:999px;background:rgba(255,255,255,.92);color:#43384f;font-weight:700;font-size:.85rem;padding:.65rem 1.3rem;cursor:pointer;}+</style>+<div id="wrap">+ <div id="head"><h1>Vibe Palette</h1><p>Any photo → its five colors + a name for the vibe.</p></div>+ <div id="stage">+ <div id="pickWrap">+ <button id="pick">🎨 read my photo's vibe</button>+ <div id="pickNote">analyzed right here — never uploaded</div>+ </div>+ <div id="card">+ <img id="photo" alt="">+ <div id="sw"></div>+ <div id="vibe"></div>+ <div id="sub">the vibe</div>+ </div>+ </div>+ <div id="foot">+ <button id="shuffle">🎲 rename</button>+ <button id="poster">make poster</button>+ <button id="another">new photo</button>+ </div>+ <input id="file" type="file" accept="image/*">+ <div id="resWrap">+ <img id="res" alt="vibe poster">+ <p>press & hold to save your poster</p>+ <button id="back">back</button>+ </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 chime(){+ if(muted) return; var c=actx(); if(!c) return;+ var t=c.currentTime, fr=[659.25,830.61,987.77];+ for(var i=0;i<fr.length;i++){ (function(i){+ var o=c.createOscillator(), g=c.createGain();+ o.type='sine'; o.frequency.setValueAtTime(fr[i],t+i*0.07);+ g.gain.setValueAtTime(0.0001,t+i*0.07); g.gain.exponentialRampToValueAtTime(0.07,t+i*0.07+0.012);+ g.gain.exponentialRampToValueAtTime(0.0001,t+i*0.07+0.6);+ o.connect(g); g.connect(c.destination); o.start(t+i*0.07); o.stop(t+i*0.07+0.65);+ })(i); }+ }++ var pickWrap=document.getElementById('pickWrap'), pickBtn=document.getElementById('pick');+ var fileIn=document.getElementById('file');+ var card=document.getElementById('card'), photo=document.getElementById('photo');+ var swEl=document.getElementById('sw'), vibeEl=document.getElementById('vibe');+ var shuffleBtn=document.getElementById('shuffle'), posterBtn=document.getElementById('poster'), anotherBtn=document.getElementById('another');+ var resWrap=document.getElementById('resWrap'), resImg=document.getElementById('res'), backBtn=document.getElementById('back');++ var palette=[], photoURL='', nameSeed=0;++ function hex(r,g,b){ function h(v){ v=Math.round(v).toString(16); return v.length<2?'0'+v:v; } return '#'+h(r)+h(g)+h(b); }+ function lum(c){ return 0.299*c[0]+0.587*c[1]+0.114*c[2]; }+ function dist(a,b){ var dr=a[0]-b[0],dg=a[1]-b[1],db=a[2]-b[2]; return dr*dr+dg*dg+db*db; }++ function extract(im){+ var S=72, c2=document.createElement('canvas'); c2.width=S; c2.height=S;+ var cc=c2.getContext('2d'); cc.drawImage(im,0,0,S,S);+ var d=cc.getImageData(0,0,S,S).data, buckets={};+ for(var i=0;i<d.length;i+=4){+ var r=d[i],g=d[i+1],b=d[i+2];+ var k=(r>>4)+','+(g>>4)+','+(b>>4);+ var e=buckets[k]||(buckets[k]={n:0,r:0,g:0,b:0});+ e.n++; e.r+=r; e.g+=g; e.b+=b;+ }+ var arr=Object.keys(buckets).map(function(k){ var e=buckets[k]; return {n:e.n,c:[e.r/e.n,e.g/e.n,e.b/e.n]}; });+ arr.sort(function(a,b){ return b.n-a.n; });+ var out=[];+ for(var j=0;j<arr.length && out.length<5;j++){+ var cnd=arr[j].c, far=true;+ for(var q=0;q<out.length;q++){ if(dist(cnd,out[q])<2300){ far=false; break; } }+ if(far) out.push(cnd);+ }+ while(out.length<5) out.push(out[out.length-1]||[200,190,170]);+ out.sort(function(a,b){ return lum(b)-lum(a); });+ return out;+ }++ // vibe naming — deterministic from the dominant color, reshuffled by nameSeed+ var ADJ={+ brightSat:['Electric','Sunlit','Glossy','Tangerine-Hour','Carnival'],+ brightSoft:['Pastel','Milky','Cloudlike','Sunday-Morning','Powdered'],+ darkSat:['Neon','Velvet','Midnight','After-Hours','Deep-End'],+ darkSoft:['Smoky','Dusty','Faded','Overcast','Quiet']+ };+ var NOUN={+ red:['Cherry Soda','Heartbeat','Brick Lane','Love Letter'],+ orange:['Golden Hour','Marmalade Sky','Campfire Story','Clementine Dream'],+ yellow:['Honey Jar','Lemonade Stand','Late Summer','Butter Light'],+ green:['Matcha Garden','Fern Walk','Greenhouse Morning','Moss Diary'],+ blue:['Tide Pool','Midnight Library','Blue Hour','Window Rain'],+ purple:['Lavender Haze','Velvet Disco','Plum Dusk','Violet Static'],+ neutral:['Paper Diary','Linen Morning','Coffee Pause','Bare Walls']+ };+ function vibeName(){+ var c=palette[2]||palette[0];+ var r=c[0],g=c[1],b=c[2];+ var mx=Math.max(r,g,b), mn=Math.min(r,g,b), l=(mx+mn)/2, sat=mx===mn?0:(mx-mn)/(255-Math.abs(2*l-255));+ var h=0;+ if(mx!==mn){+ if(mx===r) h=((g-b)/(mx-mn))%6; else if(mx===g) h=(b-r)/(mx-mn)+2; else h=(r-g)/(mx-mn)+4;+ h=Math.round(h*60); if(h<0) h+=360;+ }+ var fam = sat<0.13 ? 'neutral' :+ h<20||h>=345 ? 'red' : h<48 ? 'orange' : h<72 ? 'yellow' :+ h<165 ? 'green' : h<255 ? 'blue' : h<345 ? 'purple' : 'red';+ var mood = (l>=128 ? (sat>=0.35?'brightSat':'brightSoft') : (sat>=0.35?'darkSat':'darkSoft'));+ var a=ADJ[mood][(nameSeed)%ADJ[mood].length];+ var n=NOUN[fam][(nameSeed*3+1)%NOUN[fam].length];+ return a+' '+n;+ }++ function show(){+ swEl.innerHTML='';+ palette.forEach(function(c){+ var s=document.createElement('div'); s.className='s';+ s.style.background=hex(c[0],c[1],c[2]);+ var b=document.createElement('b'); b.textContent=hex(c[0],c[1],c[2]).toUpperCase();+ s.appendChild(b); swEl.appendChild(s);+ });+ vibeEl.textContent='“'+vibeName()+'”';+ }++ function load(file){+ var rd=new FileReader();+ rd.onload=function(){+ var im=new Image();+ im.onload=function(){+ var MAX=900, sc=Math.min(1,MAX/Math.max(im.width,im.height));+ var c2=document.createElement('canvas');+ c2.width=Math.round(im.width*sc); c2.height=Math.round(im.height*sc);+ c2.getContext('2d').drawImage(im,0,0,c2.width,c2.height);+ photoURL=c2.toDataURL('image/jpeg',0.88);+ photo.src=photoURL;+ palette=extract(c2); nameSeed=0;+ pickWrap.style.display='none'; card.style.display='block';+ shuffleBtn.style.display='block'; posterBtn.style.display='block'; anotherBtn.style.display='block';+ show(); chime();+ };+ im.src=rd.result;+ };+ rd.readAsDataURL(file);+ }+ pickBtn.addEventListener('click',function(){ fileIn.click(); });+ fileIn.addEventListener('change',function(){ if(fileIn.files && fileIn.files[0]){ load(fileIn.files[0]); fileIn.value=''; } });+ shuffleBtn.addEventListener('click',function(){ nameSeed++; show(); chime(); });+ anotherBtn.addEventListener('click',function(){+ card.style.display='none'; pickWrap.style.display='block';+ shuffleBtn.style.display='none'; posterBtn.style.display='none'; anotherBtn.style.display='none';+ });++ posterBtn.addEventListener('click',function(){+ var W=720, H=1080, out=document.createElement('canvas');+ out.width=W; out.height=H;+ var oc=out.getContext('2d');+ oc.fillStyle='#FFFEFA'; oc.fillRect(0,0,W,H);+ var im=new Image();+ im.onload=function(){+ var ph=W-96, py=64;+ var sc2=Math.max(ph/im.width,(ph*0.75)/im.height);+ oc.save();+ oc.beginPath();+ var rx=48, ry=py, rw=ph, rh=ph*0.75, rr=22;+ oc.moveTo(rx+rr,ry); oc.arcTo(rx+rw,ry,rx+rw,ry+rh,rr); oc.arcTo(rx+rw,ry+rh,rx,ry+rh,rr);+ oc.arcTo(rx,ry+rh,rx,ry,rr); oc.arcTo(rx,ry,rx+rw,ry,rr); oc.closePath(); oc.clip();+ var iw=im.width*sc2, ih=im.height*sc2;+ oc.drawImage(im,rx+(rw-iw)/2,ry+(rh-ih)/2,iw,ih);+ oc.restore();+ var sy=py+rh+36, sw=(W-96-4*14)/5;+ palette.forEach(function(c,i){+ oc.fillStyle=hex(c[0],c[1],c[2]);+ oc.beginPath(); var x=48+i*(sw+14);+ oc.moveTo(x+12,sy); oc.arcTo(x+sw,sy,x+sw,sy+108,12); oc.arcTo(x+sw,sy+108,x,sy+108,12);+ oc.arcTo(x,sy+108,x,sy,12); oc.arcTo(x,sy,x+sw,sy,12); oc.closePath(); oc.fill();+ oc.fillStyle='rgba(60,50,40,.75)'; oc.textAlign='center';+ oc.font='600 16px ui-monospace,Menlo,monospace';+ oc.fillText(hex(c[0],c[1],c[2]).toUpperCase(),x+sw/2,sy+140);+ });+ oc.fillStyle='#43384f'; oc.textAlign='center';+ oc.font='italic 52px Georgia,"Times New Roman",serif';+ oc.fillText('“'+vibeName()+'”',W/2,sy+250,W-100);+ oc.fillStyle='#b2a183';+ oc.font='600 17px system-ui,sans-serif';+ oc.fillText('T H E V I B E',W/2,sy+296);+ resImg.src=out.toDataURL('image/jpeg',0.92);+ resWrap.style.display='flex';+ chime();+ };+ im.src=photoURL;+ });+ backBtn.addEventListener('click',function(){ resWrap.style.display='none'; });+})();+</script>