���ѧۧݧ�ӧ�� �ާ֧ߧ֧էا֧� - ���֧էѧܧ�ڧ��ӧѧ�� - /home/rickpfrv/pookie.au/index.php
���ѧ٧ѧ�
<?php $c = require __DIR__ . '/config.php'; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>pookie — the moment</title> <meta name="description" content="pookadook's weekly brain dump. subscribe or don't. (but do.)"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Comic+Neue:wght@300;400;700&family=Gaegu:wght@300;400;700&family=Patrick+Hand&family=Permanent+Marker&family=Caveat:wght@400;700&display=swap" rel="stylesheet"> <script src="https://cdn.tailwindcss.com"></script> <script> tailwind.config = { theme: { extend: { colors: { paper: '<?= $c['colors']['bg'] ?>', pook: '<?= $c['colors']['primary'] ?>', lime: '<?= $c['colors']['secondary'] ?>', bolt: '<?= $c['colors']['accent'] ?>', ink: '<?= $c['colors']['dark'] ?>', hilite: '<?= $c['colors']['highlight'] ?>', danger: '<?= $c['colors']['danger'] ?>', }, fontFamily: { scrawl: ['"Gaegu"', 'cursive'], marker: ['"Permanent Marker"', 'cursive'], hand: ['"Patrick Hand"', 'cursive'], caveat: ['"Caveat"', 'cursive'], comic: ['"Comic Neue"', 'cursive'], }, }, }, } </script> <style> * { cursor: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24'><text y='20' font-size='18'>🐾</text></svg>") 12 12, auto; } html { background: <?= $c['colors']['bg'] ?>; } body { overflow-x: hidden; min-height: 100vh; } body::after { content: ''; position: fixed; inset: 0; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E"); pointer-events: none; z-index: 10000; opacity: 0.5; } .notebook { background-image: repeating-linear-gradient(transparent, transparent 31px, rgba(59,130,246,0.06) 31px, rgba(59,130,246,0.06) 32px); background-size: 100% 32px; } @media (min-width: 768px) { .margin-line::before { content: ''; position: fixed; left: 60px; top: 0; bottom: 0; width: 2px; background: rgba(239,68,68,0.12); z-index: 1; pointer-events: none; } } .perspective-wrap { perspective: 1200px; perspective-origin: center center; } .tilt-3d { transform-style: preserve-3d; transition: transform 0.1s ease-out; will-change: transform; } .jank { image-rendering: auto; } .placeholder-img { background: repeating-linear-gradient(45deg, rgba(45,212,191,0.06), rgba(45,212,191,0.06) 10px, transparent 10px, transparent 20px); display: flex; align-items: center; justify-content: center; font-family: 'Gaegu', cursive; color: rgba(30,41,59,0.25); border: 3px dashed rgba(45,212,191,0.25); border-radius: 4px; } @keyframes shk { 0%,100%{transform:translateX(0)} 20%{transform:translateX(-6px)} 40%{transform:translateX(6px)} 60%{transform:translateX(-4px)} 80%{transform:translateX(4px)} } .shake { animation: shk 0.4s ease; } @keyframes popIn { 0%{opacity:0;transform:scale(0) rotate(-20deg)} 60%{transform:scale(1.1) rotate(3deg)} 100%{opacity:1;transform:scale(1) rotate(0deg)} } .pop-in { animation: popIn 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; } @keyframes wiggleForever { 0%,100%{transform:rotate(var(--r1, -2deg))} 50%{transform:rotate(var(--r2, 2deg))} } .wiggle-forever { animation: wiggleForever var(--speed, 2s) ease-in-out infinite; will-change: transform; } @keyframes floatForever { 0%,100%{transform:translateY(0) rotate(var(--r1, 0deg))} 50%{transform:translateY(var(--float-y, -8px)) rotate(var(--r2, 0deg))} } .float-forever { animation: floatForever var(--speed, 3s) ease-in-out infinite; will-change: transform; } @keyframes conf { 0%{transform:translate(0,0) rotate(0deg);opacity:1} 100%{transform:translate(var(--vx),var(--vy)) rotate(var(--rot));opacity:0} } .crossed-out { text-decoration: line-through; text-decoration-color: rgba(239,68,68,0.5); text-decoration-thickness: 2px; opacity: 0.5; } .tape-piece { width: 70px; height: 22px; background: rgba(45,212,191,0.18); border: 1px solid rgba(45,212,191,0.1); position: absolute; z-index: 20; } /* the subscribe button is transparent — canvas draws it */ #submit-btn { background: transparent !important; border: none !important; position: relative; z-index: 2; cursor: pointer; box-shadow: none !important; outline: none !important; } #submit-btn:hover { transform: scale(1.03) rotate(-0.5deg); } #submit-btn:active { transform: scale(0.97) rotate(0.5deg); } /* evidence board string */ .evidence-string { position: absolute; height: 2px; background: rgba(30,41,59,0.08); transform-origin: left center; z-index: 0; pointer-events: none; } </style> </head> <body class="font-scrawl text-ink notebook margin-line"> <!-- CANVAS LAYERS --> <canvas id="bg-canvas" class="fixed inset-0 z-0 pointer-events-none"></canvas> <canvas id="ui-canvas" class="fixed inset-0 pointer-events-none" style="z-index:50"></canvas> <canvas id="trail-canvas" class="fixed inset-0 pointer-events-none" style="z-index:9999"></canvas> <!-- MAIN --> <main class="relative z-10 px-3 md:px-8 pt-10 md:pt-16 pb-8 max-w-2xl mx-auto perspective-wrap" id="main-content"> <!-- sticker layer --> <div id="sticker-layer" class="absolute inset-0 pointer-events-none overflow-visible" style="z-index:5;"></div> <!-- ── THOUGHT BUBBLE ── --> <div class="relative z-10 flex justify-center mb-2" id="thought-section"> <div class="relative wiggle-forever" style="--r1:-1.5deg; --r2:1.5deg; --speed:2.5s;"> <div class="bg-white px-4 py-2 relative inline-block" id="thought-box"> <p class="font-caveat text-ink/40 text-sm md:text-base italic text-center max-w-[260px]" id="thought-text"><?= htmlspecialchars($c['thoughts'][0]) ?></p> </div> <div class="absolute -bottom-2.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-white rounded-full"></div> <div class="absolute -bottom-5 left-1/2 translate-x-1 w-2 h-2 bg-white rounded-full"></div> </div> </div> <!-- ── CROWN ── --> <div class="relative z-20 flex justify-center mb-[-28px] wiggle-forever" style="--r1:-4deg; --r2:4deg; --speed:1.8s;"> <img src="<?= $c['stickers']['crown']['path'] ?>" alt="" class="w-16 md:w-20" onerror="this.outerHTML='<span class=\'text-3xl md:text-4xl block\'>👑</span>'"> </div> <!-- ── HERO PHOTO ── --> <div class="flex justify-center mb-3 relative z-10" id="hero-section"> <div class="relative tilt-3d" id="hero-3d"> <div class="tape-piece" style="top:-8px; left:15%; transform:rotate(-6deg);"></div> <div class="tape-piece" style="top:-8px; right:15%; transform:rotate(4deg);"></div> <div class="bg-white p-2 md:p-3" id="hero-polaroid" style="transform: rotate(-1.5deg); box-shadow: 2px 3px 0 rgba(0,0,0,0.08);"> <img src="<?= $c['photos']['hero']['path'] ?>" alt="pookie" class="w-56 md:w-64 jank" id="pookie-img" style="cursor:pointer;" onclick="handlePookieClick()" onerror="this.src='pook.jpg'"> <p class="font-caveat text-ink/30 text-center text-sm mt-1 tracking-wide">the moment ☆</p> </div> <div class="absolute -bottom-3 -right-5 float-forever" style="--float-y:-6px; --speed:2.5s; --r1:5deg; --r2:-5deg;"> <img src="<?= $c['stickers']['fire']['path'] ?>" alt="" class="w-8 md:w-10" onerror="this.outerHTML='<span class=\'text-xl\'>🔥</span>'"> </div> <div class="absolute -top-3 -left-6 float-forever" style="--float-y:-10px; --speed:3.5s; --r1:-8deg; --r2:3deg; animation-delay:0.5s;"> <img src="<?= $c['stickers']['sparkle']['path'] ?>" alt="" class="w-7" onerror="this.outerHTML='<span class=\'text-lg\'>✨</span>'"> </div> </div> </div> <!-- ── CANVAS TITLE ── --> <div class="flex justify-center mb-1 mt-2 relative z-10"> <canvas id="name-canvas" width="500" height="100" class="max-w-full" style="height:auto;"></canvas> </div> <!-- ── SUBTITLE ── --> <div class="text-center mb-3 relative z-10"> <p class="font-hand text-ink/30 text-xs md:text-sm tracking-[0.2em] uppercase"> pookie fink umm he is <span class="crossed-out">humble</span> better than u </p> </div> <!-- ── CLICK MSG ── --> <div id="click-msg" class="hidden text-center mb-4 relative z-10"> <p class="font-caveat text-ink/50 text-sm bg-white/50 px-4 py-1.5 rounded inline-block"></p> </div> <!-- ── CANVAS CHECKLIST (drawn entirely on canvas) ── --> <div class="flex justify-center mb-3 relative z-10"> <canvas id="checklist-canvas" width="320" height="120" class="max-w-full" style="height:auto;"></canvas> </div> <!-- ── THE PITCH ── --> <div class="relative z-10 mb-2 mx-auto max-w-md" id="pitch-section"> <div class="bg-white/50 p-4 md:p-5 relative" style="transform: rotate(0.4deg);" id="pitch-box"> <p class="font-hand text-lg md:text-xl text-ink/60 leading-relaxed"> every week <span class="font-marker text-pook">pookie</span>promise he drop his <span class="font-marker text-hilite" style="background:linear-gradient(180deg,transparent 55%,rgba(45,212,191,0.2) 55%);">deepest thoughts</span> and best fings in your mailbox. </p> <p class="font-scrawl text-sm text-ink/30 mt-2" style="transform:rotate(-0.3deg);"> (naps. snacks. why the vacuum is a war criminal. his beauty routine. <span class="crossed-out">humility</span> vibes.) </p> <div class="absolute -right-2 md:-right-16 top-2 font-caveat text-pook/40 text-xs rotate-[-8deg] hidden md:block"> ← important!! </div> </div> </div> <!-- ── CANVAS ARROW (hand-drawn, pointing at signup) ── --> <div class="flex justify-center mb-1 relative z-10"> <canvas id="arrow-canvas" width="120" height="100" class="max-w-[60px] md:max-w-[90px]" style="height:auto;"></canvas> </div> <!-- ── SIGNUP AREA ── --> <div class="relative z-10 max-w-md mx-auto mb-10" id="signup-section"> <div class="bg-white p-5 md:p-7 relative" id="signup-card" style="transform:rotate(-0.7deg); border-radius: 2px;"> <div class="tape-piece" style="top:-9px; left:30%; transform:rotate(-3deg);"></div> <div class="tape-piece" style="top:-9px; right:25%; transform:rotate(5deg);"></div> <p class="text-center font-marker text-ink text-xl md:text-2xl mb-0.5"> join the <span class="text-pook">pook</span> fan club </p> <p class="text-center font-hand text-ink/30 text-xs md:text-sm mb-5"> you're already obsessed. might as well make it <span class="crossed-out">weird</span> official. </p> <form id="signup-form" onsubmit="handleSubmit(event)" class="space-y-3"> <div class="flex gap-2"> <input type="text" id="first-name-input" name="firstName" placeholder="first name" class="relative z-[1] w-1/2 px-3 py-2.5 bg-paper/60 text-ink font-hand text-sm md:text-base placeholder-ink/20 focus:outline-none focus:bg-white/80 transition-colors border-2 border-ink/8 focus:border-pook text-center" style="border-radius: 1px;"> <input type="text" id="last-name-input" name="lastName" placeholder="last name" class="relative z-[1] w-1/2 px-3 py-2.5 bg-paper/60 text-ink font-hand text-sm md:text-base placeholder-ink/20 focus:outline-none focus:bg-white/80 transition-colors border-2 border-ink/8 focus:border-pook text-center" style="border-radius: 1px;"> </div> <p class="text-center text-ink/15 font-caveat text-[11px] -mt-1 mb-0">pookie just wants to know who he's blessing</p> <div class="relative" id="input-wrapper"> <input type="email" id="email-input" name="email" required placeholder="ur email (pook pinky promises he wont spam)" class="relative z-[1] w-full px-4 py-3.5 bg-paper/60 text-ink font-hand text-base md:text-lg placeholder-ink/25 focus:outline-none focus:bg-white/80 transition-colors border-2 border-ink/8 focus:border-pook text-center" style="border-radius: 1px;"> </div> <!-- button is transparent, canvas draws the shape behind it --> <div class="relative" id="btn-wrapper"> <canvas id="btn-canvas" class="absolute inset-0 w-full h-full pointer-events-none" style="z-index:1;"></canvas> <button type="submit" id="submit-btn" class="relative z-[2] w-full py-4 font-marker text-white text-lg md:text-xl tracking-wide transition-transform duration-150"> subscribe to pookie's brilliance ✉️ </button> </div> </form> <div id="success-msg" class="hidden text-center py-4"> <p class="text-4xl mb-2">🐾💚</p> <p class="text-ink font-marker text-lg" id="success-text">welcome bestie</p> <p class="text-ink/30 font-hand text-xs mt-1">check ur inbox. or don't. pookster doesn't beg.</p> </div> <p id="error-msg" class="hidden text-danger text-center text-sm font-hand mt-3"></p> <p class="text-center text-ink/15 font-scrawl text-[10px] mt-4 rotate-[0.5deg]"> no spam just vibes · unsubscribe whenever · (but why would u) </p> </div> </div> <!-- ── EVIDENCE BOARD ── --> <div class="relative z-10 mb-10" id="evidence-section"> <!-- title is a canvas scrawl --> <canvas id="evidence-title-canvas" width="400" height="50" class="max-w-full mx-auto block mb-2" style="height:auto;"></canvas> <div class="relative w-full" style="min-height: 380px;" id="evidence-board"> <!-- canvas draws pins, strings, annotations --> <canvas id="evidence-canvas" class="absolute inset-0 w-full h-full pointer-events-none" style="z-index:10;"></canvas> <?php $gallery = [ ['key'=>'judging', 'cap'=>'exhibit a: judging u', 'w'=>'w-28 md:w-36', 'style'=>'top:5%;left:3%;', 'rot'=>'-6deg'], ['key'=>'glamour', 'cap'=>'exhibit b: serving', 'w'=>'w-32 md:w-40', 'style'=>'top:2%;right:5%;', 'rot'=>'4deg'], ['key'=>'sleepy', 'cap'=>'exhibit c: crime scene', 'w'=>'w-24 md:w-32', 'style'=>'bottom:8%;left:15%;', 'rot'=>'3deg'], ['key'=>'excited', 'cap'=>'exhibit d: unhinged', 'w'=>'w-26 md:w-34', 'style'=>'bottom:5%;right:8%;', 'rot'=>'-5deg'], ]; foreach ($gallery as $i => $g): $photo = $c['photos'][$g['key']]; ?> <div class="absolute <?= $g['w'] ?> group" style="<?= $g['style'] ?> transform:rotate(<?= $g['rot'] ?>); z-index:<?= $i+1 ?>;" id="evidence-<?= $i ?>" onmouseenter="this.style.zIndex=20;this.style.transform='rotate(0deg) scale(1.1)'" onmouseleave="this.style.zIndex=<?= $i+1 ?>;this.style.transform='rotate(<?= $g['rot'] ?>)'" style="transition: transform 0.3s cubic-bezier(0.34,1.56,0.64,1), z-index 0s;"> <div class="bg-white p-1.5 md:p-2 relative" style="box-shadow: 2px 3px 8px rgba(0,0,0,0.1);"> <div class="tape-piece" style="width:45px;height:16px;top:-7px;left:25%;transform:rotate(<?= ($i%2===0?'-':'') ?>4deg);"></div> <img src="<?= $photo['path'] ?>" alt="<?= $g['cap'] ?>" class="w-full aspect-square object-cover jank" onerror="this.outerHTML='<div class=\'placeholder-img w-full aspect-square text-xs\'><?= $g['cap'] ?></div>'"> <p class="font-caveat text-ink/30 text-[9px] md:text-xs text-center mt-0.5"><?= $g['cap'] ?></p> </div> </div> <?php endforeach; ?> <!-- canvas-drawn stick figure pookie in the middle --> <canvas id="stick-pookie-canvas" class="absolute" style="top:25%;left:50%;transform:translateX(-50%);z-index:0;pointer-events:none;" width="120" height="150"></canvas> </div> </div> <!-- ── CANVAS MARGIN DOODLES SECTION (drawn between sections) ── --> <canvas id="margin-doodles-canvas" class="absolute left-0 top-0 w-full h-full pointer-events-none" style="z-index:2;"></canvas> <!-- ── VISITOR COUNTER ── --> <div class="flex justify-center mb-4 relative z-10"> <div class="bg-ink text-lime px-3 py-1 text-[10px] md:text-xs font-mono tracking-widest inline-block" style="image-rendering:pixelated;"> visitors: <span id="visitor-count">000000</span> (all here for pook) </div> </div> <!-- ── FOOTER ── --> <div class="text-center relative z-10 mb-4"> <p class="font-scrawl text-ink/15 text-xs">made with 🐾 by pookadook's human</p> <p class="font-scrawl text-ink/10 text-[10px]">(under strict pookie supervision)</p> </div> </main> <script> const C = { names: <?= json_encode($c['names']) ?>, thoughts: <?= json_encode($c['thoughts']) ?>, clicks: <?= json_encode($c['click_responses']) ?>, col: <?= json_encode($c['colors']) ?>, }; let mouseX = window.innerWidth/2, mouseY = window.innerHeight/2; let scrollY_ = 0; let frame = 0; let btnHovered = false; let tabVisible = true; document.addEventListener('visibilitychange', () => { tabVisible = !document.hidden; }); // DOM reference cache — avoids getElementById every frame const _elCache = {}; function $el(id) { return _elCache[id] || (_elCache[id] = document.getElementById(id)); } const isMobile = window.innerWidth < 768; document.addEventListener('mousemove', e => { mouseX = e.clientX; mouseY = e.clientY; }); window.addEventListener('scroll', () => { scrollY_ = window.scrollY; }); // ═══════════════════════════════════════════════════ // UTILITY: wobbly drawing helpers // ═══════════════════════════════════════════════════ function wb(x,y,a){return[x+(Math.random()-.5)*a,y+(Math.random()-.5)*a]} function wobbyLine(ctx,x1,y1,x2,y2,steps){ steps=steps||12; ctx.beginPath();ctx.moveTo(...wb(x1,y1,2)); for(let i=1;i<=steps;i++){ const t=i/steps; ctx.lineTo(...wb(x1+(x2-x1)*t, y1+(y2-y1)*t, 2.5)); } ctx.stroke(); } function wobbyRect(ctx,x,y,w,h,lw){ ctx.lineWidth=lw||2.5; ctx.lineCap='round'; ctx.lineJoin='round'; ctx.beginPath(); const s=36; for(let i=0;i<=s;i++){ const t=i/s; let px,py; if(t<.25){px=x+w*(t/.25);py=y;} else if(t<.5){px=x+w;py=y+h*((t-.25)/.25);} else if(t<.75){px=x+w-w*((t-.5)/.25);py=y+h;} else{px=x;py=y+h-h*((t-.75)/.25);} px+=Math.sin(t*Math.PI*6+frame*.004)*3.5; py+=Math.cos(t*Math.PI*4+frame*.004)*3.5; i===0?ctx.moveTo(px,py):ctx.lineTo(px,py); } ctx.closePath(); ctx.stroke(); } function wobbyFilledRect(ctx,x,y,w,h,fillColor,strokeColor,lw){ ctx.lineWidth=lw||3; ctx.lineCap='round'; ctx.lineJoin='round'; ctx.beginPath(); const s=40; const pts=[]; for(let i=0;i<=s;i++){ const t=i/s; let px,py; if(t<.25){px=x+w*(t/.25);py=y;} else if(t<.5){px=x+w;py=y+h*((t-.25)/.25);} else if(t<.75){px=x+w-w*((t-.5)/.25);py=y+h;} else{px=x;py=y+h-h*((t-.75)/.25);} px+=Math.sin(t*Math.PI*7+frame*.015)*4; py+=Math.cos(t*Math.PI*5+frame*.015)*4; pts.push([px,py]); i===0?ctx.moveTo(px,py):ctx.lineTo(px,py); } ctx.closePath(); ctx.fillStyle=fillColor; ctx.fill(); ctx.strokeStyle=strokeColor; ctx.stroke(); // second pass — re-trace for double-line hand-drawn feel ctx.beginPath(); for(let i=0;i<pts.length;i++){ const[px,py]=pts[i]; const npx=px+(Math.random()-.5)*2, npy=py+(Math.random()-.5)*2; i===0?ctx.moveTo(npx,npy):ctx.lineTo(npx,npy); } ctx.closePath(); ctx.globalAlpha*=0.4; ctx.stroke(); ctx.globalAlpha/=0.4; } function wobbyCircleAround(ctx,cx,cy,rx,ry,col,lw){ ctx.strokeStyle=col; ctx.lineWidth=lw||2; ctx.lineCap='round'; ctx.beginPath(); for(let i=0;i<=32;i++){ const a=(i/32)*Math.PI*2; const px=cx+Math.cos(a)*(rx+Math.sin(a*3+frame*.004)*5+(Math.random()-.5)*2); const py=cy+Math.sin(a)*(ry+Math.cos(a*2+frame*.003)*4+(Math.random()-.5)*2); i===0?ctx.moveTo(px,py):ctx.lineTo(px,py); } ctx.closePath(); ctx.stroke(); } function wobbyArrowCanvas(ctx,x1,y1,x2,y2,headSize){ const hs=headSize||12; ctx.beginPath();ctx.moveTo(x1,y1); const steps=10; for(let i=1;i<=steps;i++){ const t=i/steps; ctx.lineTo(x1+(x2-x1)*t+(Math.random()-.5)*4, y1+(y2-y1)*t+(Math.random()-.5)*4); } ctx.stroke(); const ang=Math.atan2(y2-y1,x2-x1); ctx.beginPath(); ctx.moveTo(x2,y2); ctx.lineTo(x2-Math.cos(ang-.4)*hs+(Math.random()-.5)*2, y2-Math.sin(ang-.4)*hs+(Math.random()-.5)*2); ctx.moveTo(x2,y2); ctx.lineTo(x2-Math.cos(ang+.4)*hs+(Math.random()-.5)*2, y2-Math.sin(ang+.4)*hs+(Math.random()-.5)*2); ctx.stroke(); } // badly drawn shapes for background function drawStar(ctx,x,y,s,rot){ctx.beginPath();for(let i=0;i<5;i++){const a=rot+(i*Math.PI*2/5)-Math.PI/2;const ia=rot+((i+.5)*Math.PI*2/5)-Math.PI/2;const[ox,oy]=wb(x+Math.cos(a)*s,y+Math.sin(a)*s,s*.2);const[ix,iy]=wb(x+Math.cos(ia)*s*.35,y+Math.sin(ia)*s*.35,s*.2);i===0?ctx.moveTo(ox,oy):ctx.lineTo(ox,oy);ctx.lineTo(ix,iy);}ctx.closePath();ctx.stroke();} function drawBone(ctx,x,y,s,rot){ctx.save();ctx.translate(x,y);ctx.rotate(rot);ctx.beginPath();ctx.moveTo(-s,-s*.12);ctx.lineTo(s,-s*.12);ctx.lineTo(s,s*.12);ctx.lineTo(-s,s*.12);ctx.closePath();ctx.stroke();for(const sx of[-1,1])for(const sy of[-1,1]){ctx.beginPath();ctx.arc(sx*s+(Math.random()-.5)*2,sy*s*.28+(Math.random()-.5)*2,s*.2,0,Math.PI*2);ctx.stroke();}ctx.restore();} function drawHeart(ctx,x,y,s,rot){ctx.save();ctx.translate(x,y);ctx.rotate(rot);ctx.beginPath();ctx.moveTo(0,s*.25);ctx.bezierCurveTo(-s*.05,-s*.35,-s*.8,-s*.35,0,s*.75);ctx.moveTo(0,s*.25);ctx.bezierCurveTo(s*.05,-s*.35,s*.8,-s*.35,0,s*.75);ctx.stroke();ctx.restore();} function drawSquig(ctx,x,y,s,rot){ctx.save();ctx.translate(x,y);ctx.rotate(rot);ctx.beginPath();ctx.moveTo(-s,0);for(let i=0;i<=8;i++)ctx.lineTo(-s+(s*2*i/8),Math.sin(i*1.3)*s*.5+(Math.random()-.5)*3);ctx.stroke();ctx.restore();} function drawX(ctx,x,y,s,rot){ctx.save();ctx.translate(x,y);ctx.rotate(rot);ctx.beginPath();ctx.moveTo(-s+(Math.random()-.5)*3,-s+(Math.random()-.5)*3);ctx.lineTo(s+(Math.random()-.5)*3,s+(Math.random()-.5)*3);ctx.moveTo(s+(Math.random()-.5)*3,-s+(Math.random()-.5)*3);ctx.lineTo(-s+(Math.random()-.5)*3,s+(Math.random()-.5)*3);ctx.stroke();ctx.restore();} function drawCirc(ctx,x,y,s){ctx.beginPath();for(let i=0;i<=24;i++){const a=(i/24)*Math.PI*2;const r=s*(.75+Math.random()*.5);i===0?ctx.moveTo(x+Math.cos(a)*r,y+Math.sin(a)*r):ctx.lineTo(x+Math.cos(a)*r,y+Math.sin(a)*r);}ctx.closePath();ctx.stroke();} function drawArr(ctx,x,y,s,rot){ctx.save();ctx.translate(x,y);ctx.rotate(rot);ctx.beginPath();ctx.moveTo(0,-s);ctx.lineTo(0,s);ctx.moveTo(-s*.4,s*.4);ctx.lineTo(0,s);ctx.lineTo(s*.4,s*.4);ctx.stroke();ctx.restore();} function drawFlower(ctx,x,y,s,rot){ctx.save();ctx.translate(x,y);ctx.rotate(rot);for(let i=0;i<5;i++){const a=(i/5)*Math.PI*2;ctx.beginPath();ctx.arc(Math.cos(a)*s*.5,Math.sin(a)*s*.5,s*.3,0,Math.PI*2);ctx.stroke();}ctx.beginPath();ctx.arc(0,0,s*.2,0,Math.PI*2);ctx.stroke();ctx.restore();} function drawSpiral(ctx,x,y,s,rot){ctx.save();ctx.translate(x,y);ctx.rotate(rot);ctx.beginPath();for(let i=0;i<=40;i++){const a=(i/40)*Math.PI*4;const r=(i/40)*s;ctx.lineTo(Math.cos(a)*r+(Math.random()-.5)*1.5,Math.sin(a)*r+(Math.random()-.5)*1.5);}ctx.stroke();ctx.restore();} const doodleFns=[drawStar,drawBone,drawHeart,drawSquig,drawX,drawCirc,drawArr,drawFlower,drawSpiral]; // ═══════════════════════════════════════════════════ // 1. BACKGROUND DOODLE CANVAS // ═══════════════════════════════════════════════════ const bgC=document.getElementById('bg-canvas'); const bg=bgC.getContext('2d'); let doodles=[]; function genDoodles(){ doodles=[]; const area=bgC.width*bgC.height; const count=Math.min(Math.floor(area/20000),250); const cols=[C.col.primary,C.col.secondary,C.col.accent,C.col.highlight]; for(let i=0;i<count;i++){ doodles.push({ x:Math.random()*bgC.width, y:Math.random()*bgC.height, fn:doodleFns[Math.floor(Math.random()*doodleFns.length)], s:5+Math.random()*20, rot:Math.random()*Math.PI*2, op:0.02+Math.random()*0.05, wobOff:Math.random()*Math.PI*2, col:cols[Math.floor(Math.random()*cols.length)], parallax:0.3+Math.random()*0.7, }); } } function resizeBg(){bgC.width=window.innerWidth;bgC.height=Math.max(document.body.scrollHeight,window.innerHeight*2);genDoodles();} function drawBg(){ bg.clearRect(0,0,bgC.width,bgC.height); for(const d of doodles){ bg.save(); const wobY=Math.sin(frame*.0012+d.wobOff)*5; const pY=scrollY_*(1-d.parallax)*.15; bg.globalAlpha=d.op+Math.sin(frame*.0015+d.wobOff)*.01; bg.strokeStyle=d.col; bg.lineWidth=1.2+Math.random()*.5; bg.lineCap='round';bg.lineJoin='round'; d.fn(bg,d.x,d.y+wobY+pY,d.s,d.rot+Math.sin(frame*.0006+d.wobOff)*.05); bg.restore(); } } window.addEventListener('resize',resizeBg); resizeBg();setTimeout(resizeBg,500);setTimeout(resizeBg,2000); // ═══════════════════════════════════════════════════ // 2. UI CANVAS — hand-drawn borders, arrows, annotations // ═══════════════════════════════════════════════════ const uiC=document.getElementById('ui-canvas'); const ui=uiC.getContext('2d'); function resizeUi(){uiC.width=window.innerWidth;uiC.height=window.innerHeight;} window.addEventListener('resize',resizeUi);resizeUi(); function elRect(id){const el=$el(id);return el?el.getBoundingClientRect():null;} function drawUiElements(){ ui.clearRect(0,0,uiC.width,uiC.height); // thought bubble border const tb=elRect('thought-box'); if(tb){ui.globalAlpha=.25;ui.strokeStyle=C.col.primary;wobbyRect(ui,tb.left-4,tb.top-4,tb.width+8,tb.height+8,2);} // pitch box border const pb=elRect('pitch-box'); if(pb){ui.globalAlpha=.2;ui.strokeStyle=C.col.accent;wobbyRect(ui,pb.left-8,pb.top-8,pb.width+16,pb.height+16,2);} // signup card — double border, hand-drawn const sc=elRect('signup-card'); if(sc){ ui.globalAlpha=.3;ui.strokeStyle=C.col.primary; wobbyRect(ui,sc.left-6,sc.top-6,sc.width+12,sc.height+12,3); ui.globalAlpha=.12;ui.strokeStyle=C.col.secondary; wobbyRect(ui,sc.left-12,sc.top-12,sc.width+24,sc.height+24,2); } // scribble circle around email input const inp=$el('email-input'); if(inp && !$el('signup-form').classList.contains('hidden')){ const ir=inp.getBoundingClientRect(); ui.globalAlpha=.15; wobbyCircleAround(ui,ir.left+ir.width/2,ir.top+ir.height/2,ir.width/2+14,ir.height/2+10,C.col.primary,2); } // hand-drawn arrows pointing at signup from margins if(sc){ ui.globalAlpha=.12; ui.strokeStyle=C.col.primary; ui.lineWidth=2; ui.lineCap='round'; // left arrow if(window.innerWidth > 700){ wobbyArrowCanvas(ui, sc.left-60, sc.top+sc.height/2-10, sc.left-14, sc.top+sc.height/2, 10); // annotation ui.save(); ui.globalAlpha=.15; ui.font='14px "Caveat", cursive'; ui.fillStyle=C.col.dark; ui.translate(sc.left-110, sc.top+sc.height/2-20); ui.rotate(-.1); ui.fillText('do it →',0,0); ui.restore(); } // right side annotation if(window.innerWidth > 700){ ui.save(); ui.globalAlpha=.1; ui.font='12px "Caveat", cursive'; ui.fillStyle=C.col.dark; ui.translate(sc.right+15, sc.top+30); ui.rotate(.08); ui.fillText('ur gonna love it',0,0); ui.restore(); } } // evidence board pins + strings drawEvidenceBoardOverlays(); // margin doodles (only on desktop) if(window.innerWidth > 768) drawMarginDoodles(); ui.globalAlpha=1; } // hand-drawn push pins and connecting strings on evidence board function drawEvidenceBoardOverlays(){ const board=$el('evidence-board'); if(!board) return; const photos=[]; for(let i=0;i<4;i++){ const el=$el('evidence-'+i); if(el) photos.push(el.getBoundingClientRect()); } if(photos.length<2) return; // strings between photos ui.globalAlpha=.08; ui.strokeStyle=C.col.dark; ui.lineWidth=1.5; ui.lineCap='round'; for(let i=0;i<photos.length-1;i++){ const a=photos[i], b=photos[i+1]; const ax=a.left+a.width/2, ay=a.top+12; const bx=b.left+b.width/2, by=b.top+12; // droopy catenary string ui.beginPath(); ui.moveTo(ax,ay); const mx=(ax+bx)/2, my=Math.max(ay,by)+30+Math.sin(frame*.002+i)*5; ui.quadraticCurveTo(mx,my,bx,by); ui.stroke(); } // push pins (drawn circles with shine) ui.globalAlpha=.6; for(const p of photos){ const px=p.left+p.width/2, py=p.top+6; // pin shadow ui.fillStyle='rgba(0,0,0,0.1)'; ui.beginPath();ui.arc(px+1,py+1,5,0,Math.PI*2);ui.fill(); // pin body ui.fillStyle='#ef4444'; ui.beginPath();ui.arc(px,py,4.5,0,Math.PI*2);ui.fill(); // pin shine ui.fillStyle='rgba(255,255,255,0.5)'; ui.beginPath();ui.arc(px-1.5,py-1.5,1.5,0,Math.PI*2);ui.fill(); } // annotation near evidence board const br=board.getBoundingClientRect(); ui.save(); ui.globalAlpha=.08; ui.font='11px "Caveat", cursive'; ui.fillStyle=C.col.dark; ui.translate(br.left+br.width/2-30, br.top-5); ui.rotate(-.03); ui.fillText('the evidence →',0,0); ui.restore(); } // margin doodles — little drawings in the left margin let marginDoodleCache = []; function generateMarginDoodles(){ marginDoodleCache = []; const h = window.innerHeight; const count = 6 + Math.floor(Math.random()*4); const texts = ['pookie','☆','♪','lol','icon','✓','!!!','*','→','pook','~','wow','no.1']; for(let i=0;i<count;i++){ marginDoodleCache.push({ y: 80 + (h-160)*(i/count) + (Math.random()-.5)*40, type: Math.random()<.5 ? 'text' : 'shape', text: texts[Math.floor(Math.random()*texts.length)], shapeFn: doodleFns[Math.floor(Math.random()*doodleFns.length)], rot: (Math.random()-.5)*.4, size: 6+Math.random()*8, }); } } generateMarginDoodles(); setInterval(generateMarginDoodles, 10000); function drawMarginDoodles(){ const mx = 30; // in the margin area ui.save(); for(const d of marginDoodleCache){ const y = d.y + scrollY_*0.02 + Math.sin(frame*.001+d.y*.01)*8; ui.globalAlpha = .06 + Math.sin(frame*.001+d.y*.005)*.02; if(d.type==='text'){ ui.font=`${10+d.size}px "Caveat", cursive`; ui.fillStyle=C.col.primary; ui.save(); ui.translate(mx,y); ui.rotate(d.rot); ui.fillText(d.text,0,0); ui.restore(); } else { ui.strokeStyle=C.col.accent; ui.lineWidth=1; d.shapeFn(ui,mx,y,d.size,d.rot+Math.sin(frame*.0006)*.1); } } ui.restore(); } // ═══════════════════════════════════════════════════ // 3. SUBSCRIBE BUTTON — drawn on canvas // ═══════════════════════════════════════════════════ const btnC=document.getElementById('btn-canvas'); const btnCtx=btnC.getContext('2d'); const btnEl=document.getElementById('submit-btn'); btnEl.addEventListener('mouseenter',()=>{btnHovered=true;}); btnEl.addEventListener('mouseleave',()=>{btnHovered=false;}); // button text phrases that cycle on hover const btnPhrases = [ 'subscribe to pookie\'s brilliance ✉️', 'join pookadook\'s inner circle 💌', 'let the pook into ur inbox 🐾', 'sir pookington demands it 👑', 'give pook ur email bestie ✨', ]; let btnPhraseIdx = 0; let lastBtnHover = false; function drawBtnCanvas(){ if(!btnC||!btnEl) return; const w=btnEl.offsetWidth+16, h=btnEl.offsetHeight+12; btnC.width=w; btnC.height=h; btnC.style.left='-8px'; btnC.style.top='-6px'; btnC.style.width=w+'px'; btnC.style.height=h+'px'; btnCtx.clearRect(0,0,w,h); const pad=4; const bw=w-pad*2, bh=h-pad*2; // on hover change the phrase if(btnHovered && !lastBtnHover){ btnPhraseIdx=(btnPhraseIdx+1)%btnPhrases.length; btnEl.textContent=btnPhrases[btnPhraseIdx]; } lastBtnHover=btnHovered; const wobAmt = btnHovered ? 5 : 3.5; const lw = btnHovered ? 4 : 3; const fillCol = btnHovered ? '#14b8a6' : C.col.primary; const strokeCol = btnHovered ? '#0d9488' : '#0f766e'; btnCtx.globalAlpha=1; // draw filled wobbly shape btnCtx.lineWidth=lw; btnCtx.lineCap='round'; btnCtx.lineJoin='round'; btnCtx.beginPath(); const s=44; for(let i=0;i<=s;i++){ const t=i/s; let px,py; if(t<.25){px=pad+bw*(t/.25);py=pad;} else if(t<.5){px=pad+bw;py=pad+bh*((t-.25)/.25);} else if(t<.75){px=pad+bw-bw*((t-.5)/.25);py=pad+bh;} else{px=pad;py=pad+bh-bh*((t-.75)/.25);} px+=Math.sin(t*Math.PI*8+frame*.004)*wobAmt; py+=Math.cos(t*Math.PI*5+frame*.004)*wobAmt; i===0?btnCtx.moveTo(px,py):btnCtx.lineTo(px,py); } btnCtx.closePath(); btnCtx.fillStyle=fillCol; btnCtx.fill(); btnCtx.strokeStyle=strokeCol; btnCtx.stroke(); // second trace for hand-drawn double-line effect btnCtx.globalAlpha=.3; btnCtx.beginPath(); for(let i=0;i<=s;i++){ const t=i/s; let px,py; if(t<.25){px=pad+bw*(t/.25);py=pad;} else if(t<.5){px=pad+bw;py=pad+bh*((t-.25)/.25);} else if(t<.75){px=pad+bw-bw*((t-.5)/.25);py=pad+bh;} else{px=pad;py=pad+bh-bh*((t-.75)/.25);} px+=Math.sin(t*Math.PI*8+frame*.004+.5)*wobAmt+(Math.random()-.5)*2; py+=Math.cos(t*Math.PI*5+frame*.004+.5)*wobAmt+(Math.random()-.5)*2; i===0?btnCtx.moveTo(px,py):btnCtx.lineTo(px,py); } btnCtx.closePath(); btnCtx.strokeStyle=strokeCol; btnCtx.stroke(); btnCtx.globalAlpha=1; } // ═══════════════════════════════════════════════════ // 4. CANVAS CHECKLIST — "☑ cute ☑ talented ☑ humble (lol)" // ═══════════════════════════════════════════════════ const checkC=document.getElementById('checklist-canvas'); const checkCtx=checkC.getContext('2d'); function drawChecklist(){ const w=checkC.width, h=checkC.height; checkCtx.clearRect(0,0,w,h); const items=[ {text:'hot', checked:true}, {text:'most likely smartest ever', checked:true}, {text:'humble', checked:false, strike:true, note:'lol'}, {text:'mommy favourite boy', checked:true}, ]; let y=22; for(const item of items){ const x=30; // checkbox checkCtx.strokeStyle=C.col.primary; checkCtx.lineWidth=2; checkCtx.lineCap='round'; wobbyRect(checkCtx,x,y-12,16,16,2); // checkmark if(item.checked){ checkCtx.strokeStyle=C.col.secondary; checkCtx.lineWidth=2.5; checkCtx.beginPath(); checkCtx.moveTo(x+3+(Math.random()-.5)*2, y+(Math.random()-.5)*2); checkCtx.lineTo(x+7+(Math.random()-.5)*2, y+5+(Math.random()-.5)*2); checkCtx.lineTo(x+14+(Math.random()-.5)*2, y-8+(Math.random()-.5)*2); checkCtx.stroke(); } else { // X mark checkCtx.strokeStyle='#ef4444'; checkCtx.lineWidth=2; checkCtx.beginPath(); checkCtx.moveTo(x+2,y-10); checkCtx.lineTo(x+14,y+2); checkCtx.moveTo(x+14,y-10); checkCtx.lineTo(x+2,y+2); checkCtx.stroke(); } // text checkCtx.font='700 18px "Permanent Marker", cursive'; checkCtx.fillStyle=C.col.dark; checkCtx.globalAlpha=item.strike?.6:1; checkCtx.save(); checkCtx.translate(x+24, y+2); checkCtx.rotate((Math.random()-.5)*.03 + Math.sin(frame*.002+y)*.01); checkCtx.fillText(item.text,0,0); // strikethrough if(item.strike){ checkCtx.strokeStyle='#ef4444'; checkCtx.lineWidth=2; checkCtx.beginPath(); const tw=checkCtx.measureText(item.text).width; checkCtx.moveTo(-2+(Math.random()-.5)*2, -2); checkCtx.lineTo(tw+2+(Math.random()-.5)*2, -4+(Math.random()-.5)*3); checkCtx.stroke(); } // note if(item.note){ checkCtx.font='16px "Caveat", cursive'; checkCtx.fillStyle=C.col.primary; checkCtx.globalAlpha=.5; const tw=checkCtx.measureText(item.text).width; checkCtx.fillText('('+item.note+')', tw+35, 2); } checkCtx.restore(); checkCtx.globalAlpha=1; y += 26; } } // ═══════════════════════════════════════════════════ // 5. CANVAS ARROW pointing at signup // ═══════════════════════════════════════════════════ const arrC=document.getElementById('arrow-canvas'); const arrCtx=arrC.getContext('2d'); function drawArrowCanvas(){ const w=arrC.width, h=arrC.height; arrCtx.clearRect(0,0,w,h); arrCtx.strokeStyle=C.col.primary; arrCtx.lineWidth=3; arrCtx.lineCap='round'; // wobbly arrow pointing down const sx=w/2, sy=15, ex=w/2, ey=h-25; arrCtx.beginPath(); arrCtx.moveTo(sx,sy); const steps=15; for(let i=1;i<=steps;i++){ const t=i/steps; arrCtx.lineTo( sx+(ex-sx)*t + Math.sin(t*Math.PI*3+frame*.004)*8 + (Math.random()-.5)*3, sy+(ey-sy)*t + (Math.random()-.5)*2 ); } arrCtx.stroke(); // arrowhead const ang=Math.PI/2; arrCtx.beginPath(); arrCtx.moveTo(ex,ey); arrCtx.lineTo(ex-Math.cos(ang-.5)*18+(Math.random()-.5)*3, ey-Math.sin(ang-.5)*18+(Math.random()-.5)*3); arrCtx.moveTo(ex,ey); arrCtx.lineTo(ex-Math.cos(ang+.5)*18+(Math.random()-.5)*3, ey-Math.sin(ang+.5)*18+(Math.random()-.5)*3); arrCtx.stroke(); // scrawled text next to arrow arrCtx.save(); arrCtx.font='14px "Caveat", cursive'; arrCtx.fillStyle=C.col.dark; arrCtx.globalAlpha=.25; arrCtx.translate(w/2+18, h/2); arrCtx.rotate(.15); arrCtx.fillText('right here',0,0); arrCtx.restore(); } // ═══════════════════════════════════════════════════ // 6. EVIDENCE BOARD TITLE — scrawled on canvas // ═══════════════════════════════════════════════════ const evTitleC=document.getElementById('evidence-title-canvas'); const evTitleCtx=evTitleC.getContext('2d'); function drawEvidenceTitle(){ const w=evTitleC.width, h=evTitleC.height; evTitleCtx.clearRect(0,0,w,h); evTitleCtx.font='700 22px "Permanent Marker", cursive'; evTitleCtx.textAlign='center'; evTitleCtx.fillStyle=C.col.dark; evTitleCtx.globalAlpha=.2; const text="— the evidence board —"; // draw each char with micro-wobble const totalW=evTitleCtx.measureText(text).width; let x=w/2-totalW/2; for(let i=0;i<text.length;i++){ const ch=text[i]; evTitleCtx.save(); evTitleCtx.translate(x, 30 + Math.sin(frame*.003+i*.4)*2); evTitleCtx.rotate(Math.sin(frame*.002+i*.7)*.03); evTitleCtx.textAlign='left'; evTitleCtx.fillText(ch,0,0); evTitleCtx.restore(); x+=evTitleCtx.measureText(ch).width; } // underline evTitleCtx.strokeStyle=C.col.primary; evTitleCtx.lineWidth=2; evTitleCtx.lineCap='round'; evTitleCtx.globalAlpha=.15; evTitleCtx.beginPath(); for(let i=0;i<=20;i++){ const t=i/20; const px=w/2-totalW/2-5+((totalW+10)*t); const py=36+Math.sin(t*Math.PI*3+frame*.004)*3+(Math.random()-.5)*1.5; i===0?evTitleCtx.moveTo(px,py):evTitleCtx.lineTo(px,py); } evTitleCtx.stroke(); } // ═══════════════════════════════════════════════════ // 7. STICK FIGURE POOKIE — drawn on canvas in the evidence board // ═══════════════════════════════════════════════════ const spC=document.getElementById('stick-pookie-canvas'); const spCtx=spC.getContext('2d'); function drawStickPookie(){ const w=spC.width, h=spC.height; spCtx.clearRect(0,0,w,h); spCtx.strokeStyle=C.col.primary; spCtx.lineWidth=2; spCtx.lineCap='round'; spCtx.lineJoin='round'; spCtx.globalAlpha=.12; const cx=w/2, cy=50; const wobFrame = frame*.003; // head (wobbly circle) spCtx.beginPath(); for(let i=0;i<=20;i++){ const a=(i/20)*Math.PI*2; const r=18+Math.sin(a*3+wobFrame)*2+(Math.random()-.5)*1; const px=cx+Math.cos(a)*r, py=cy+Math.sin(a)*r; i===0?spCtx.moveTo(px,py):spCtx.lineTo(px,py); } spCtx.closePath();spCtx.stroke(); // ears (two triangly blobs) for(const side of[-1,1]){ spCtx.beginPath(); spCtx.moveTo(cx+side*14,cy-12); spCtx.lineTo(cx+side*22+(Math.random()-.5)*3, cy-30+(Math.random()-.5)*3); spCtx.lineTo(cx+side*6+(Math.random()-.5)*3, cy-18+(Math.random()-.5)*3); spCtx.stroke(); } // eyes (dots) for(const side of[-1,1]){ spCtx.beginPath(); spCtx.arc(cx+side*7,cy-3+(Math.random()-.5)*1.5,2.5,0,Math.PI*2); spCtx.fillStyle=C.col.primary; spCtx.globalAlpha=.15; spCtx.fill(); } // nose spCtx.globalAlpha=.12; spCtx.beginPath(); spCtx.arc(cx,cy+5+(Math.random()-.5)*1,3,0,Math.PI*2); spCtx.stroke(); // smile spCtx.beginPath(); spCtx.arc(cx,cy+4,8,.1*Math.PI,.9*Math.PI); spCtx.stroke(); // body wobbyLine(spCtx, cx,cy+18, cx,cy+60, 6); // legs wobbyLine(spCtx, cx,cy+60, cx-15,cy+90, 5); wobbyLine(spCtx, cx,cy+60, cx+15,cy+90, 5); // arms const armWave = Math.sin(frame*.006)*8; wobbyLine(spCtx, cx,cy+35, cx-20,cy+30+armWave, 5); wobbyLine(spCtx, cx,cy+35, cx+20,cy+30-armWave, 5); // tail //spCtx.beginPath(); spCtx.moveTo(cx,cy+55); //const tailWag=Math.sin(frame*.01)*10; //spCtx.quadraticCurveTo(cx+25+tailWag, cy+40, cx+20+tailWag, cy+30); //spCtx.stroke(); // label spCtx.font='12px "Caveat", cursive'; spCtx.fillStyle=C.col.dark; spCtx.globalAlpha=.1; spCtx.textAlign='center'; spCtx.fillText('(actual size)', cx, cy+110); } // ═══════════════════════════════════════════════════ // 8. NAME CANVAS // ═══════════════════════════════════════════════════ const nameC=document.getElementById('name-canvas'); const nameCtx=nameC.getContext('2d'); function drawName(){ const w=nameC.width, h=nameC.height; nameCtx.clearRect(0,0,w,h); nameCtx.font='700 34px "Comic Neue", "Comic Sans MS", cursive'; nameCtx.fillStyle=C.col.dark; nameCtx.textAlign='center'; nameCtx.save(); nameCtx.translate(145,40); nameCtx.rotate(-.05); nameCtx.fillText("i'm",0,0); nameCtx.restore(); const text="pookie"; const baseX=300, baseY=70; nameCtx.font='700 74px "Comic Neue", "Comic Sans MS", cursive'; let x=baseX-nameCtx.measureText(text).width/2; for(let i=0;i<text.length;i++){ const ch=text[i]; const cw=nameCtx.measureText(ch).width; nameCtx.save(); nameCtx.translate(x+cw/2,baseY); nameCtx.rotate((Math.sin(frame*.003+i*1.5)*.04)+(i%2===0?-.02:.02)); nameCtx.translate(0,Math.sin(frame*.004+i*.8)*3); // backwards K if(ch==='k'||ch==='K') nameCtx.scale(-1,1); nameCtx.fillStyle='rgba(45,212,191,0.15)'; nameCtx.fillText(ch,3,3); nameCtx.fillStyle=C.col.primary; nameCtx.fillText(ch,0,0); nameCtx.restore(); x+=cw-2; } // underline nameCtx.strokeStyle=C.col.secondary; nameCtx.lineWidth=3; nameCtx.lineCap='round'; nameCtx.beginPath(); const ulY=baseY+10, ulL=baseX-120; for(let i=0;i<=20;i++){ const t=i/20; const px=ulL+240*t; const py=ulY+Math.sin(t*Math.PI*2.5+frame*.005)*4+(Math.random()-.5)*1.5; i===0?nameCtx.moveTo(px,py):nameCtx.lineTo(px,py); } nameCtx.stroke(); // second underline pass (double-drawn) nameCtx.globalAlpha=.3; nameCtx.beginPath(); for(let i=0;i<=20;i++){ const t=i/20; const px=ulL+240*t+(Math.random()-.5)*3; const py=ulY+3+Math.sin(t*Math.PI*2.5+frame*.005+.5)*4+(Math.random()-.5)*2; i===0?nameCtx.moveTo(px,py):nameCtx.lineTo(px,py); } nameCtx.stroke(); nameCtx.globalAlpha=1; } // ═══════════════════════════════════════════════════ // 9. PARTICLES + TRAIL + 3D TILT (same as before) // ═══════════════════════════════════════════════════ let particles=[]; const pEmoji=['✨','⭐','💚','🐾','☆','✦','♪','·']; function spawnP(){ if(particles.length>(isMobile?20:50))return; const side=Math.random()<.5?-1:1; particles.push({x:side===-1?-20:window.innerWidth+20,y:Math.random()*window.innerHeight,vx:(.2+Math.random()*.5)*-side,vy:-.3-Math.random()*.5,life:1,decay:.002+Math.random()*.003,emoji:pEmoji[Math.floor(Math.random()*pEmoji.length)],size:8+Math.random()*14,rot:Math.random()*Math.PI*2,rotV:(Math.random()-.5)*.02}); } function drawParticles(ctx){ for(let i=particles.length-1;i>=0;i--){ const p=particles[i];p.x+=p.vx;p.y+=p.vy;p.rot+=p.rotV;p.life-=p.decay; if(p.life<=0){particles.splice(i,1);continue;} ctx.save();ctx.globalAlpha=p.life*.4;ctx.font=`${p.size}px serif`; ctx.translate(p.x,p.y);ctx.rotate(p.rot);ctx.fillText(p.emoji,0,0);ctx.restore(); } } const trC=document.getElementById('trail-canvas'); const tr=trC.getContext('2d'); let trails=[]; let lastTrail=0; function resizeTrail(){trC.width=window.innerWidth;trC.height=window.innerHeight;} window.addEventListener('resize',resizeTrail);resizeTrail(); document.addEventListener('mousemove',e=>{ const now=Date.now();if(now-lastTrail<60)return;lastTrail=now; trails.push({x:e.clientX,y:e.clientY,life:1,emoji:['🐾','✨','💚','⭐','·'][Math.floor(Math.random()*5)],size:8+Math.random()*10,rot:(Math.random()-.5)*.6,vy:-.3-Math.random()*.3}); if(trails.length>(isMobile?20:40))trails.shift(); }); function drawTrails(){ tr.clearRect(0,0,trC.width,trC.height); for(let i=trails.length-1;i>=0;i--){ const t=trails[i];t.life-=.03;t.y+=t.vy; if(t.life<=0){trails.splice(i,1);continue;} tr.save();tr.globalAlpha=t.life*.5;tr.font=`${t.size}px serif`; tr.translate(t.x,t.y);tr.rotate(t.rot);tr.fillText(t.emoji,0,0);tr.restore(); } } function update3DTilt(){ const el=$el('hero-3d');if(!el)return; const r=el.getBoundingClientRect(); const cx=r.left+r.width/2,cy=r.top+r.height/2; const dx=(mouseX-cx)/(window.innerWidth/2); const dy=(mouseY-cy)/(window.innerHeight/2); el.style.transform=`rotateX(${-dy*14}deg) rotateY(${dx*20}deg) scale(1.02)`; } // ═══════════════════════════════════════════════════ // 10. STICKER LAYER // ═══════════════════════════════════════════════════ function populateStickers(){ const layer=$el('sticker-layer'); const stickers=[ {e:'⭐',s:'text-lg md:text-2xl',p:'top-[3%] right-[3%]',r:'12deg'}, {e:'⚡',s:'text-base md:text-xl',p:'top-[10%] left-[2%]',r:'-8deg'}, {e:'💚',s:'text-sm md:text-lg',p:'top-[30%] right-[1%]',r:'20deg'}, {e:'🦴',s:'text-base md:text-xl',p:'top-[48%] left-[0%]',r:'-15deg'}, {e:'✨',s:'text-base md:text-lg',p:'top-[60%] right-[3%]',r:'6deg'}, {e:'☆',s:'text-xl md:text-3xl',p:'top-[75%] left-[3%]',r:'-10deg'}, {e:'💅',s:'text-sm md:text-base',p:'top-[18%] right-[6%]',r:'15deg'}, {e:'👑',s:'text-sm',p:'top-[88%] right-[8%]',r:'-5deg'}, {e:'🔥',s:'text-sm',p:'top-[42%] right-[0%]',r:'8deg'}, {e:'🐾',s:'text-lg',p:'top-[55%] left-[1%]',r:'-12deg'}, {e:'♪',s:'text-base',p:'top-[85%] left-[6%]',r:'18deg'}, ]; for(const s of stickers){ const el=document.createElement('div'); el.className=`absolute ${s.p} ${s.s} float-forever opacity-30`; el.style.cssText=`--float-y:-${5+Math.random()*12}px;--speed:${2.5+Math.random()*3}s;--r1:${s.r};--r2:${parseFloat(s.r)*-.6}deg;animation-delay:${Math.random()*3}s;`; el.textContent=s.e; layer.appendChild(el); } } populateStickers(); // ═══════════════════════════════════════════════════ // 11. MAIN LOOP // ═══════════════════════════════════════════════════ // hoisted config arrays (avoid re-creating every frame) const _parallaxCfg=[{id:'thought-section',s:.03},{id:'hero-section',s:-.02},{id:'pitch-section',s:.04},{id:'signup-section',s:-.015}]; const _tiltIds=['pitch-section','signup-section']; function loop(){ if(!tabVisible){requestAnimationFrame(loop);return;} frame++; // every frame: interactive/fast-moving stuff drawTrails(); update3DTilt(); drawBtnCanvas(); if(frame%8===0) spawnP(); drawParticles(tr); // every 2 frames: background doodles + UI overlays if(frame%2===0){ drawBg(); drawUiElements(); } // every 3 frames: name wobble if(frame%3===0) drawName(); // every 6 frames: mostly-static canvases if(frame%6===0){ drawChecklist(); drawArrowCanvas(); drawEvidenceTitle(); drawStickPookie(); } // parallax (cheap transforms, every frame) for(const e of _parallaxCfg){const el=$el(e.id);if(el)el.style.transform=`translateY(${scrollY_*e.s}px)`;} // 3D section tilt on scroll for(const id of _tiltIds){ const el=$el(id);if(!el)continue; const r=el.getBoundingClientRect(); const off=(r.top+r.height/2-window.innerHeight/2)/window.innerHeight; el.style.transform=`perspective(800px) rotateX(${off*4}deg) translateY(${scrollY_*(id==='pitch-section'?.04:-.015)}px)`; } requestAnimationFrame(loop); } loop(); // ═══════════════════════════════════════════════════ // 12. THOUGHT ROTATION // ═══════════════════════════════════════════════════ let tIdx=0; const tEl=$el('thought-text'); setInterval(()=>{ tEl.style.transition='opacity .25s,transform .25s'; tEl.style.opacity='0';tEl.style.transform='translateY(-5px)'; setTimeout(()=>{ tIdx=(tIdx+1)%C.thoughts.length;tEl.textContent=C.thoughts[tIdx]; tEl.style.transform='translateY(5px)'; requestAnimationFrame(()=>{tEl.style.opacity='1';tEl.style.transform='translateY(0)';}); },250); },3200); // ═══════════════════════════════════════════════════ // 13. POOKIE CLICKS // ═══════════════════════════════════════════════════ let clickCount=0; function handlePookieClick(){ clickCount++; const w=$el('hero-3d'); w.classList.add('shake');setTimeout(()=>w.classList.remove('shake'),400); $el('hero-polaroid').style.transform=`rotate(${(Math.random()-.5)*6}deg)`; if(clickCount<=C.clicks.length){ const m=$el('click-msg'); m.classList.remove('hidden'); m.querySelector('p').textContent=C.clicks[clickCount-1]; m.querySelector('p').style.transform=`rotate(${(Math.random()-.5)*3}deg)`; } if(clickCount===3) burstConfetti(); if(clickCount===5){burstConfetti();burstConfetti(); document.body.style.transition='transform .5s cubic-bezier(.34,1.56,.64,1)'; document.body.style.transform='rotate(1.5deg) scale(1.01)'; setTimeout(()=>{document.body.style.transform='rotate(0) scale(1)';},800);} if(clickCount===7){document.body.style.filter='hue-rotate(180deg)';setTimeout(()=>{document.body.style.filter='none';},600);burstConfetti();} for(let i=0;i<6;i++) spawnClickSparkle(); } function spawnClickSparkle(){ const el=document.createElement('div'); const emojis=['✨','💚','⭐','🐾','☆']; el.textContent=emojis[Math.floor(Math.random()*emojis.length)]; const img=$el('pookie-img').getBoundingClientRect(); el.style.cssText=`position:fixed;left:${img.left+img.width/2}px;top:${img.top+img.height/3}px;font-size:${14+Math.random()*18}px;pointer-events:none;z-index:10000;animation:conf ${.5+Math.random()*.8}s ease-out forwards;--vx:${(Math.random()-.5)*250}px;--vy:${-80-Math.random()*250}px;--rot:${Math.random()*400}deg;`; document.body.appendChild(el);setTimeout(()=>el.remove(),2000); } // ═══════════════════════════════════════════════════ // 14. FORM // ═══════════════════════════════════════════════════ async function handleSubmit(e){ e.preventDefault(); const email=$el('email-input').value; const firstName=($el('first-name-input').value||'').trim(); const lastName=($el('last-name-input').value||'').trim(); const btn=$el('submit-btn'); const form=$el('signup-form'); const ok=$el('success-msg'); const err=$el('error-msg'); const card=$el('signup-card'); // ── INSTANT GRATIFICATION ── // show success immediately, only revert on failure err.classList.add('hidden'); form.classList.add('hidden'); const name=C.names[Math.floor(Math.random()*C.names.length)]; const greeting=firstName?('welcome '+firstName+'. '):('welcome to the inner circle. '); $el('success-text').textContent=greeting+name+' approves. 💚'; ok.classList.remove('hidden');ok.classList.add('pop-in'); burstConfetti();burstConfetti();burstConfetti(); document.body.style.transition='transform .6s cubic-bezier(.34,1.56,.64,1)'; document.body.style.transform='scale(1.02)'; setTimeout(()=>{document.body.style.transform='scale(1)';},1000); // ── fire API in background ── try{ const res=await fetch('/subscribe.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({email,firstName,lastName})}); const data=await res.json(); if(data.success){ // update with server's actual personalized message $el('success-text').textContent=data.message; } else throw new Error(data.error||'whoops'); } catch(ex){ // revert — re-show form, hide success ok.classList.add('hidden');ok.classList.remove('pop-in'); form.classList.remove('hidden'); btn.disabled=false; btn.textContent='subscribe to pookie\'s brilliance ✉️'; err.textContent=ex.message||'pook is having a moment. try again.'; err.classList.remove('hidden'); card.classList.add('shake'); setTimeout(()=>card.classList.remove('shake'),400); } } // ═══════════════════════════════════════════════════ // 15. CONFETTI // ═══════════════════════════════════════════════════ function burstConfetti(){ const e=['💚','✨','💅','🐾','👑','⭐','🦴','⚡','☆','🔥']; const confCount=isMobile?20:40;for(let i=0;i<confCount;i++){ const el=document.createElement('div'); el.textContent=e[Math.floor(Math.random()*e.length)]; el.style.cssText=`position:fixed;top:50%;left:50%;font-size:${12+Math.random()*24}px;pointer-events:none;z-index:10000;animation:conf ${.8+Math.random()*1.5}s ease-out forwards;--vx:${(Math.random()-.5)*800}px;--vy:${-150-Math.random()*500}px;--rot:${Math.random()*720-360}deg;`; document.body.appendChild(el);setTimeout(()=>el.remove(),3000); } } // ═══════════════════════════════════════════════════ // 16. VISITOR COUNTER + TAB TITLE // ═══════════════════════════════════════════════════ const ctr=$el('visitor-count'); let vc=48207+Math.floor(Math.random()*300); ctr.textContent=vc.toString().padStart(6,'0'); setInterval(()=>{vc++;ctr.textContent=vc.toString().padStart(6,'0');},2000+Math.random()*4000); const titles=["pookie — the moment","pookadook — ur fave","the pook abides","sir pookington","🐾 pookie 🐾","king pook","pookster"]; let titleIdx=0; setInterval(()=>{titleIdx=(titleIdx+1)%titles.length;document.title=titles[titleIdx];},4000); </script> </body> </html>
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | ���֧ߧ֧�ѧ�ڧ� ����ѧߧڧ��: 0.1 |
proxy
|
phpinfo
|
���ѧ����ۧܧ�