Meta Description" name="description" />

Share this result

Previews are deleted daily. Get a permanent share link sent to your inbox:
Script
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1" /> <title>Sorry β€” A Cute Card</title> <style> :root{ --bg:#fff5f7; --card:#ffffff; --accent:#ff6b81; --muted:#6b6b6b; --shadow: 0 8px 30px rgba(99, 39, 62, 0.12); font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial; } *{box-sizing:border-box} body{ margin:0; min-height:100vh; display:grid; place-items:center; background:linear-gradient(180deg,var(--bg),#fffaf0); padding:28px; } .card{ width:min(720px,96vw); background:var(--card); border-radius:18px; padding:28px; box-shadow:var(--shadow); display:grid; grid-template-columns:1fr 320px; gap:18px; align-items:center; overflow:hidden; position:relative; } .left{ padding:12px 8px; } h1{ margin:0 0 8px 0; font-size:22px; color: #401f2b; letter-spacing:0.2px; } p.lead{ margin:0 0 14px 0; color:var(--muted); line-height:1.45; } label{font-size:13px;color:#4b2a33;display:block;margin-bottom:6px} input{ width:100%; padding:10px 12px; border-radius:10px; border:1px solid #f0d7db; background:#fff7f9; font-size:15px; outline:none; transition:transform .12s ease, box-shadow .12s; } input:focus{transform:translateY(-2px); box-shadow:0 6px 20px rgba(99,39,62,0.06)} .btn{ display:inline-flex; align-items:center; gap:8px; background:linear-gradient(90deg,var(--accent),#ff8aa0); color:white; border:none; padding:10px 14px; border-radius:12px; cursor:pointer; font-weight:600; margin-top:12px; box-shadow:0 8px 20px rgba(255,107,129,0.18); } .btn:active{transform:translateY(1px)} .small{font-size:13px;color:#7a4a54;margin-top:8px} .right{ background:linear-gradient(135deg, rgba(255,107,129,0.06), rgba(255,138,160,0.03)); border-radius:12px; padding:14px; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:10px; min-height:220px; text-align:center; } .card-visual{ width:120px; height:120px; border-radius:16px; display:grid; place-items:center; background:linear-gradient(180deg,#fff0f2,#fff6f7); border:1px solid rgba(255,107,129,0.08); } .heart{ width:72px;height:72px; display:inline-block; transform-origin:center; transition:transform .35s; } .heart svg{width:100%;height:100%} .heart.beat{animation:beat .8s ease 3} @keyframes beat { 0%{transform:scale(1)} 25%{transform:scale(1.15)} 50%{transform:scale(0.95)} 75%{transform:scale(1.07)} 100%{transform:scale(1)} } .message{ font-size:16px; color:#4b2a33; min-height:64px; display:flex; align-items:center; justify-content:center; padding:10px; } /* confetti canvas covers card */ canvas.confetti{ position:absolute; inset:0; pointer-events:none; } @media (max-width:720px){ .card{grid-template-columns:1fr; padding:18px} .right{order:-1} } </style> </head> <body> <div class="card" role="application" aria-label="Cute sorry card"> <canvas class="confetti"></canvas> <div class="left"> <h1>Make it small. Make it true.</h1> <p class="lead">Type names and press the button β€” the card will show a short, heartfelt apology that sounds gentle and genuine.</p> <label for="yourName">Your name</label> <input id="yourName" placeholder="e.g. Aashu" autocomplete="off"> <label for="exName" style="margin-top:10px">Their name</label> <input id="exName" placeholder="e.g. Meera" autocomplete="off"> <div style="display:flex;gap:10px;align-items:center;"> <button class="btn" id="sayBtn" aria-live="polite">πŸ’Œ Say Sorry</button> <button class="btn" id="resetBtn" style="background:#f3f3f4;color:#401f2b;box-shadow:none">Reset</button> </div> <div class="small">Tip: keep it short, honest, and avoid blame. This little card nudges the rest.</div> </div> <div class="right"> <div class="card-visual" aria-hidden="true"> <div class="heart" id="heart"> <!-- cute heart svg --> <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 21s-7.5-4.7-9.3-7.1C-1 8.6 5.2 4 7.5 6.1 9 7.6 12 10.8 12 10.8s3-3.2 4.5-4.7C18.8 4 25 8.6 21.3 13.9 19.5 16.3 12 21 12 21z" fill="#ff6b81" opacity="0.95"/> </svg> </div> </div> <div class="message" id="message">A gentle space for a small, honest sorry β€” ready?</div> </div> </div> <script> /* Friendly, tiny apology card logic. No external libs. Works in modern browsers. */ const btn = document.getElementById('sayBtn'); const reset = document.getElementById('resetBtn'); const your = document.getElementById('yourName'); const ex = document.getElementById('exName'); const msg = document.getElementById('message'); const heart = document.getElementById('heart'); const canvas = document.querySelector('canvas.confetti'); const ctx = canvas.getContext('2d'); function resizeCanvas(){ canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; } resizeCanvas(); window.addEventListener('resize', resizeCanvas); /* small confetti engine */ let confettiPieces = []; function spawnConfetti(){ confettiPieces = []; const w = canvas.width, h = canvas.height; for(let i=0;i<64;i++){ confettiPieces.push({ x: Math.random()*w, y: -Math.random()*h, r: Math.random()*6+4, vx: (Math.random()-0.5)*2.6, vy: Math.random()*3+2, rot: Math.random()*360, vr: (Math.random()-0.5)*6, color: `hsl(${Math.random()*30 + 340},80%,60%)` }); } stepConfetti(); } let confAni; function stepConfetti(){ cancelAnimationFrame(confAni); ctx.clearRect(0,0,canvas.width, canvas.height); for(let p of confettiPieces){ p.x += p.vx; p.y += p.vy; p.rot += p.vr; p.vy += 0.03; ctx.save(); ctx.translate(p.x,p.y); ctx.rotate(p.rot*Math.PI/180); ctx.fillStyle = p.color; ctx.fillRect(-p.r/2, -p.r/2, p.r*1.6, p.r); ctx.restore(); } confettiPieces = confettiPieces.filter(p => p.y < canvas.height + 50); if(confettiPieces.length) confAni = requestAnimationFrame(stepConfetti); } /* small beep using WebAudio for feedback */ function tinyBeep(){ try{ const a = new (window.AudioContext || window.webkitAudioContext)(); const o = a.createOscillator(); const g = a.createGain(); o.type = 'sine'; o.frequency.value = 880; g.gain.value = 0.0001; o.connect(g); g.connect(a.destination); o.start(); // soft attack g.gain.exponentialRampToValueAtTime(0.03, a.currentTime + 0.02); g.gain.exponentialRampToValueAtTime(0.0001, a.currentTime + 0.35); o.stop(a.currentTime + 0.36); setTimeout(()=>a.close(),500); }catch(e){ /* ignore on unsupported */ } } /* apology templates β€” short & plain, keep respectful */ const templates = [ (s,t)=>`Hey ${t || 'there'}, I'm sorry. I messed up and I wish I had handled things better. β€” ${s}`, (s,t)=>`${t || 'Friend'}, I'm sorry. I miss the easy parts of us. I take responsibility and I'm really sorry. β€” ${s}`, (s,t)=>`I owe you a sorry, ${t || ''}. Not excuses β€” just truth: I'm sorry. β€” ${s}`, (s,t)=>`Sorry, ${t || ''}. I should've listened better. If you can, I'd like to make things right. β€” ${s}`, (s,t)=>`Small sorry, big meaning: I'm sorry. Thank you for the times; I'm sorry I hurt you. β€” ${s}` ]; function pickTemplate(){ return templates[Math.floor(Math.random()*templates.length)]; } btn.addEventListener('click', () => { const s = (your.value || 'Someone').trim(); const t = (ex.value || '').trim(); const apology = pickTemplate()(s,t); // update visuals msg.textContent = apology; heart.classList.remove('beat'); // reflow to restart animation void heart.offsetWidth; heart.classList.add('beat'); spawnConfetti(); tinyBeep(); // subtle polite aria notification btn.setAttribute('aria-label', 'Apology shown'); }); /* reset */ reset.addEventListener('click', () => { your.value = ''; ex.value = ''; msg.textContent = 'A gentle space for a small, honest sorry β€” ready?'; cancelAnimationFrame(confAni); ctx.clearRect(0,0,canvas.width,canvas.height); heart.classList.remove('beat'); btn.setAttribute('aria-label', 'Say Sorry'); }); /* a small UX nudge: press Enter in exName to activate */ ex.addEventListener('keydown', (e)=>{ if(e.key === 'Enter') btn.click(); }); your.addEventListener('keydown', (e)=>{ if(e.key === 'Enter') ex.focus(); }); /* accessibility: focus first input */ your.focus(); </script> </body> </html>
Landing Page
This ad does not have a landing page available
Network Timeline
Performance Summary

1

Requests

1

Domains

9KB

Transfer Size

9KB

Content Size

285.0ms

Dom Content Loaded

400.0ms

First Paint

287.0ms

Load Time
Domain Breakdown
Transfer Size (bytes)
Loading...
Content Size (bytes)
Loading...
Header Size (bytes)
Loading...
Requests
Loading...
Timings (ms)
Loading...
Total Time
Loading...
Content Breakdown
Transfer Size (bytes)
Loading...
Content Size (bytes)
Loading...
Header Size (bytes)
Loading...
Requests
Loading...