<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Jiminssi Β· Velvet Birthday πŸ’‹</title>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,600;1,500&family=Great+Vibes&display=swap" rel="stylesheet">
<style>
:root{box-sizing:border-box;padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px);color-scheme:dark;
--bg:#14020a;--bg2:#3a0614;--red:#ff1744;--rose:#ff5c7a;--gold:#f6c177;--ink:#ffe9ee;--glass:rgba(255,23,68,.10)}
html{scroll-behavior:smooth;scroll-padding-top:env(safe-area-inset-top,0px)}
*,*:before,*:after{box-sizing:inherit}
body{margin:0;background:radial-gradient(ellipse at 50% -10%,var(--bg2),var(--bg) 65%) fixed;color:var(--ink);font-family:'Playfair Display',Georgia,serif;text-align:center;overflow-x:hidden}
canvas#fx{position:fixed;inset:0;width:100%;height:100%;pointer-events:none;z-index:5}
section{position:relative;max-width:720px;margin:0 auto;padding:70px 20px;z-index:2}
.script{font-family:'Great Vibes','Brush Script MT',cursive;font-weight:400}
h1{font-size:clamp(3.4rem,17vw,7rem);margin:0;line-height:1;color:#fff;text-shadow:0 0 12px var(--red),0 0 34px var(--red),0 0 70px #c4002f;animation:glow 2.6s ease-in-out infinite alternate}
@keyframes glow{from{text-shadow:0 0 8px var(--red),0 0 22px var(--red),0 0 44px #c4002f}to{text-shadow:0 0 16px var(--rose),0 0 46px var(--red),0 0 96px #c4002f}}
h2{font-style:italic;font-weight:500;color:var(--gold);font-size:2rem;margin:0 0 .3em}
.eyebrow{letter-spacing:.35em;text-transform:uppercase;font-size:.8rem;color:var(--rose)}
p{line-height:1.7}
#typed{font-style:italic;min-height:3.4em;font-size:1.15rem;color:var(--ink)}
button{font:inherit;cursor:pointer;border:1px solid var(--rose);color:#fff;background:linear-gradient(135deg,#ff1744,#a1002b);border-radius:999px;padding:13px 30px;font-size:1.05rem;box-shadow:0 0 22px rgba(255,23,68,.5);transition:transform .15s,box-shadow .2s}
button:hover{transform:translateY(-2px);box-shadow:0 0 36px rgba(255,23,68,.85)}button:active{transform:scale(.94)}
.glass{background:var(--glass);border:1px solid rgba(255,92,122,.35);border-radius:24px;padding:26px;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}
/* gate */
#gate{position:fixed;inset:0;z-index:100;background:radial-gradient(circle,#4a0618,#0d0106);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;transition:opacity 1s,visibility 1s;padding:20px}
#gate.go{opacity:0;visibility:hidden}
#lock{font-size:5rem;animation:beat 1.2s infinite;cursor:pointer;background:none;border:0;box-shadow:none;padding:0}
@keyframes beat{0%,100%{transform:scale(1)}20%{transform:scale(1.2)}40%{transform:scale(1)}60%{transform:scale(1.14)}}
/* heat */
.lips{font-size:4.6rem;background:none;border:0;box-shadow:none;padding:6px;animation:beat 1.6s infinite;filter:drop-shadow(0 0 16px var(--red))}
.lips:hover{box-shadow:none}
.meter{height:18px;border-radius:99px;background:rgba(255,255,255,.1);overflow:hidden;max-width:380px;margin:12px auto;border:1px solid rgba(255,92,122,.4)}
#heat{height:100%;width:0;background:linear-gradient(90deg,#ff5c7a,#ff1744,#ffb199);transition:width .25s;box-shadow:0 0 14px var(--red)}
#heatMsg{min-height:3em;font-style:italic;color:var(--gold);font-size:1.1rem}
/* scratch */
.sw{position:relative;width:320px;max-width:100%;height:150px;margin:18px auto;border-radius:18px;overflow:hidden;box-shadow:0 0 30px rgba(255,23,68,.45)}
.sw .under{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:16px;background:linear-gradient(135deg,#7a0020,#ff1744);font-style:italic;font-size:1.15rem}
#sc{position:absolute;inset:0;width:100%;height:100%;touch-action:none;cursor:crosshair}
/* gifts */
.boxes{display:flex;gap:14px;justify-content:center;flex-wrap:wrap;margin:18px 0}
.box{font-size:3.4rem;padding:18px 24px;border-radius:22px;background:var(--glass);border:1px solid rgba(255,92,122,.45);box-shadow:none}
.box.dim{opacity:.18;pointer-events:none}
#coupon{min-height:4em;font-size:1.15rem;font-style:italic;color:var(--gold)}
/* letter */
#env{font-size:5rem;background:none;border:0;box-shadow:none;cursor:pointer;padding:0;transition:transform .4s}
#letter{max-height:0;opacity:0;overflow:hidden;transition:max-height 1.2s,opacity 1s,padding .6s;font-size:1.2rem;text-align:left;padding:0 24px}
#letter.open{max-height:560px;opacity:1;padding:24px}
#letter .script{font-size:2rem;color:var(--rose)}
footer{padding:50px 20px 70px;color:var(--rose);position:relative;z-index:2}
</style>
</head>
<body>
<canvas id="fx"></canvas>

<section id="hero">
  <div class="eyebrow">It's your day, baby</div>
  <h1 class="script">Happy Birthday<br>Jiminssi</h1>
  <p id="typed"></p>
  <button onclick="document.getElementById('heatS').scrollIntoView()">Come closer ↓</button>
</section>

<section id="heatS">
  <h2>Turn up the heat πŸ”₯</h2>
  <p>Tap the lips and see how hot this gets. Careful, it cools down if you stop…</p>
  <button class="lips" id="lips" aria-label="Kiss">πŸ’‹</button>
  <div class="meter"><div id="heat"></div></div>
  <div id="heatMsg">Come closer…</div>
</section>

<section>
  <h2>Scratch your secret πŸ’Œ</h2>
  <p>Use your finger (or mouse) to reveal what I'm thinking about you.</p>
  <div class="sw"><div class="under" id="secret">I can't stop thinking about your lips, your eyes, your touch… 😏</div><canvas id="sc" width="320" height="150"></canvas></div>
</section>

<section>
  <h2>Pick your birthday gift 🎁</h2>
  <p>Three boxes. Only one is yours. Choose with your heart.</p>
  <div class="boxes" id="boxes"></div>
  <div id="coupon"></div>
  <button id="again" class="ghost" style="display:none;margin-top:10px">Choose again</button>
</section>

<section>
  <h2>A letter, just for you πŸ’‹</h2>
  <button id="env" aria-label="Open letter">πŸ’Œ</button>
  <p style="opacity:.7">Tap the envelope</p>
  <div id="letter" class="glass">
    <div class="script">My dearest Jiminssi,</div>
    <p>Every time you look at me, the whole room gets warmer. You walk in and my heart forgets how to behave. Your smile is dangerous, your voice is my favourite sound, and your touch makes everything else disappear.</p>
    <p>Today the world celebrates you, but tonight, I want to celebrate you slowly, with candlelight, soft music, and all my attention on you.</p>
    <p>Happy Birthday, my love. You are my favourite temptation. πŸ”₯</p>
    <div class="script" style="text-align:right">Yours, always ❀️</div>
  </div>
</section>

<footer class="script" style="font-size:1.8rem">Happy Birthday, Jiminssi Β· made with love & a little mischief πŸ’‹</footer>

<script>
var cv=document.getElementById('fx'),cx=cv.getContext('2d'),P=[],W,H,dpr=Math.min(devicePixelRatio||1,2);
function size(){W=innerWidth;H=innerHeight;cv.width=W*dpr;cv.height=H*dpr;cx.setTransform(dpr,0,0,dpr,0,0)}
size();addEventListener('resize',size);
var glyphs=['❀','πŸ’‹','β™₯','🌹','πŸ’—','πŸ”₯'];
function petal(){P.push({t:0,x:Math.random()*W,y:-20,vx:(Math.random()-.5)*.8,vy:.8+Math.random()*1.4,r:6+Math.random()*9,a:Math.random()*6,va:(Math.random()-.5)*.06,l:1})}
function heart(x,y,v){var a=Math.random()*6.28,s=v||(1+Math.random()*4);P.push({t:1,g:glyphs[Math.floor(Math.random()*glyphs.length)],x:x,y:y,vx:Math.cos(a)*s,vy:Math.sin(a)*s-1.5,r:14+Math.random()*18,a:0,va:0,l:1})}
function burst(x,y,n){for(var i=0;i<n;i++)heart(x,y)}
setInterval(function(){if(P.length<110)petal()},220);
(function loop(){
  cx.clearRect(0,0,W,H);
  for(var i=P.length-1;i>=0;i--){
    var p=P[i];p.x+=p.vx;p.y+=p.vy;p.a+=p.va;
    if(p.t){p.vy+=.06;p.l-=.012}
    cx.save();cx.globalAlpha=Math.max(p.l,0);cx.translate(p.x,p.y);cx.rotate(p.a);
    if(p.t){cx.font=p.r+'px serif';cx.textAlign='center';cx.fillText(p.g,0,0)}
    else{cx.fillStyle='rgba(255,'+(23+Math.floor(p.r*3))+',68,.8)';cx.beginPath();cx.ellipse(0,0,p.r,p.r*.55,0,0,6.28);cx.fill()}
    cx.restore();
    if(p.l<=0||p.y>H+30)P.splice(i,1);
  }
  requestAnimationFrame(loop);
})();
var last=0;
addEventListener('pointermove',function(e){var n=Date.now();if(n-last>70){last=n;heart(e.clientX,e.clientY,.6)}});
addEventListener('pointerdown',function(e){burst(e.clientX,e.clientY,7)});

/* gate + typing */
var lines=["You walk in, and the whole room gets warmer.","Your smile is dangerous. Your eyes are worse.","Tonight, you're the only thing I want to celebrate. πŸ”₯"],li=0,ci=0,te=document.getElementById('typed');
function type(){var s=lines[li];te.textContent=s.slice(0,ci++);if(ci<=s.length)setTimeout(type,48);else setTimeout(function(){li=(li+1)%lines.length;ci=0;type()},2200)}
type();setTimeout(function(){burst(innerWidth/2,innerHeight/2,50)},500);

/* heat */
var heat=0,hb=document.getElementById('heat'),hm=document.getElementById('heatMsg');
var hl=[[0,"Come closer…"],[20,"Mmm, someone's blushing 😘"],[45,"You're making me hot, Jiminssi πŸ”₯"],[70,"Careful… I might not let go 😏"],[100,"Happy Birthday, my love. Tonight, you're all mine. πŸ’‹πŸ”₯"]];
function setHeat(v){heat=Math.max(0,Math.min(100,v));hb.style.width=heat+'%';for(var i=hl.length-1;i>=0;i--)if(heat>=hl[i][0]){hm.textContent=hl[i][1];break}}
document.getElementById('lips').onclick=function(e){var was=heat;setHeat(heat+5);var r=e.currentTarget.getBoundingClientRect();burst(r.left+r.width/2,r.top+r.height/2,10);if(heat>=100&&was<100)for(var i=0;i<6;i++)setTimeout(function(){burst(Math.random()*W,H*.5,25)},i*180)};
setInterval(function(){if(heat>0&&heat<100)setHeat(heat-1)},900);

/* scratch */
var sc=document.getElementById('sc'),g=sc.getContext('2d'),down=false,done=false,moves=0;
var gr=g.createLinearGradient(0,0,320,150);gr.addColorStop(0,'#d4a65a');gr.addColorStop(.5,'#f6e0a8');gr.addColorStop(1,'#b98a3e');
g.fillStyle=gr;g.fillRect(0,0,320,150);g.fillStyle='#7a0020';g.font='italic 22px Georgia';g.textAlign='center';g.fillText('Scratch me… πŸ’‹',160,82);
function scr(e){if(!down||done)return;var r=sc.getBoundingClientRect(),x=(e.clientX-r.left)*320/r.width,y=(e.clientY-r.top)*150/r.height;
  g.globalCompositeOperation='destination-out';g.beginPath();g.arc(x,y,20,0,6.28);g.fill();
  if(++moves%12===0){var d=g.getImageData(0,0,320,150).data,c=0;for(var i=3;i<d.length;i+=64)if(d[i]===0)c++;
    if(c/(d.length/64)>.5){done=true;sc.style.transition='opacity .8s';sc.style.opacity=0;burst(innerWidth/2,sc.getBoundingClientRect().top+60,45)}}}
sc.addEventListener('pointerdown',function(e){down=true;sc.setPointerCapture(e.pointerId);scr(e)});
sc.addEventListener('pointermove',scr);
sc.addEventListener('pointerup',function(){down=false});

/* gifts */
var gifts=["A slow dance, just us, no music needed. πŸ’ƒ","A kiss for every candle, plus one extra for luck. πŸ’‹","A candlelit dinner, and I'll feed you dessert. πŸ“"],bx=document.getElementById('boxes'),cp=document.getElementById('coupon'),ag=document.getElementById('again');
function boxes(){bx.innerHTML='';cp.textContent='';ag.style.display='none';
  gifts.slice().sort(function(){return Math.random()-.5}).forEach(function(t,i){
    var b=document.createElement('button');b.className='box';b.textContent='🎁';
    b.onclick=function(){[].forEach.call(bx.children,function(o){if(o!==b)o.classList.add('dim')});b.textContent='πŸ’';cp.textContent='Coupon: '+t+' Valid forever, redeemable tonight.';ag.style.display='inline-block';var r=b.getBoundingClientRect();burst(r.left+r.width/2,r.top,35)};
    bx.appendChild(b)})}
ag.onclick=boxes;boxes();

/* letter */
document.getElementById('env').onclick=function(e){var l=document.getElementById('letter');l.classList.toggle('open');this.textContent=l.classList.contains('open')?'πŸ’‹':'πŸ’Œ';var r=this.getBoundingClientRect();burst(r.left+r.width/2,r.top+30,25)};
</script>
</body>
</html>