<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Love Match % Calculator</title>
<style>
:root {
--bg: #0f0f12;
--card: #16161b;
--text: #e9e9ef;
--muted: #9aa0aa;
--accent: #ff3b6d;
--accent-2: #7c5cff;
--ring: rgba(255,59,109,.45);
--ok: #22c55e;
--warn: #f59e0b;
--bad: #ef4444;
}
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
margin: 0;
font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
background: radial-gradient(1200px 800px at 10% -10%, rgba(124,92,255,.15), transparent 40%),
radial-gradient(1000px 700px at 110% 10%, rgba(255,59,109,.12), transparent 40%),
var(--bg);
color: var(--text);
display: grid;
place-items: center;
padding: 24px;
}
.wrap {
width: 100%;
max-width: 680px;
background: linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,0)) border-box,
linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,0)) padding-box,
var(--card);
border: 1px solid rgba(255,255,255,.08);
border-radius: 24px;
padding: 24px;
box-shadow: 0 10px 30px rgba(0,0,0,.45), 0 0 0 8px rgba(255,59,109,.03);
}
h1 {
margin: 0 0 8px;
font-size: clamp(24px, 4vw, 36px);
letter-spacing: .2px;
line-height: 1.15;
display: flex; gap: 10px; align-items: center; justify-content: center;
}
h1 .heart {
display: inline-block;
transform: translateY(2px);
filter: drop-shadow(0 6px 12px rgba(255,59,109,.45));
animation: thump 1.35s ease-in-out infinite;
}
@keyframes thump { 0%, 100% { transform: scale(1) translateY(2px);} 30% { transform: scale(1.12) translateY(2px);} }
p.sub { margin: 0 0 18px; color: var(--muted); text-align: center; }
form { display: grid; grid-template-columns: 1fr; gap: 14px; }
.row { display: grid; gap: 12px; }
@media (min-width: 640px){ .row { grid-template-columns: 1fr 1fr; } }
label { font-size: 13px; color: var(--muted); display: block; margin-bottom: 6px; }
.field { position: relative; }
input[type="text"], input[type="date"] {
width: 100%;
padding: 14px 14px 14px 44px;
border-radius: 14px;
border: 1px solid rgba(255,255,255,.12);
background: rgba(255,255,255,.03);
color: var(--text);
outline: none;
transition: box-shadow .2s, border-color .2s, background .2s;
}
input::placeholder { color: #8b8f99; }
input:focus { border-color: var(--ring); box-shadow: 0 0 0 4px rgba(255,59,109,.12), 0 8px 20px rgba(0,0,0,.25); background: rgba(255,255,255,.06); }
.icon {
position: absolute; inset: 0 auto 0 12px; display: grid; place-items: center; pointer-events: none; opacity: .9;
}
.actions { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; margin-top: 6px; }
button {
appearance: none; border: 0; cursor: pointer; border-radius: 999px; padding: 12px 18px; font-weight: 700;
background: linear-gradient(135deg, var(--accent), var(--accent-2)); color: white; box-shadow: 0 8px 20px rgba(124,92,255,.3);
transition: transform .06s ease, filter .2s ease, box-shadow .2s ease;
}
button:hover { filter: brightness(1.05); box-shadow: 0 10px 26px rgba(124,92,255,.36); }
button:active { transform: translateY(1px); }
button.secondary { background: transparent; color: var(--text); border: 1px solid rgba(255,255,255,.14); box-shadow: none; }
.note { margin-top: 14px; font-size: 12px; color: var(--muted); text-align: center; }
.result {
margin-top: 18px; padding: 18px; border-radius: 18px; border: 1px dashed rgba(255,255,255,.16);
background: rgba(255,255,255,.03); text-align: center; display: none;
}
.result.show { display: block; animation: pop .3s ease; }
@keyframes pop { from { transform: scale(.98); opacity:.0 } to { transform: scale(1); opacity:1 } }
.percent { font-size: clamp(42px, 10vw, 72px); font-weight: 900; letter-spacing: -1px; margin: 4px 0 6px; }
.bar { height: 10px; border-radius: 999px; background: rgba(255,255,255,.08); overflow: hidden; }
.bar > i { display: block; height: 100%; width: 0%; background: linear-gradient(90deg, var(--bad), var(--warn), var(--ok)); transition: width .8s ease; }
.msg { margin-top: 10px; font-size: 14px; color: var(--muted); }
.share {
margin-top: 12px; display: flex; gap: 10px; justify-content: center; flex-wrap: wrap;
}
.share button { padding: 10px 14px; font-weight: 600; }
.hidden { display: none; }
</style>
</head>
<body>
<div class="wrap" role="application" aria-label="Love Match Percent Calculator">
<h1>
<svg class="heart" width="28" height="28" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M12 21s-6.716-4.35-9.428-7.061A6.5 6.5 0 1 1 12 5.5 6.5 6.5 0 1 1 21.428 13.94C18.716 16.65 12 21 12 21z" fill="url(#g)"/>
<defs>
<linearGradient id="g" x1="0" y1="0" x2="24" y2="24" gradientUnits="userSpaceOnUse">
<stop stop-color="#ff3b6d"/>
<stop offset="1" stop-color="#7c5cff"/>
</linearGradient>
</defs>
</svg>
Love Match % Calculator
</h1>
<p class="sub">Fun, privacy-friendly, and 100% client‑side. No data leaves the page.</p>
<form id="loveForm">
<div class="row">
<div class="field">
<label for="nameA">Your Name</label>
<span class="icon" aria-hidden="true">💁♀️</span>
<input id="nameA" name="nameA" type="text" placeholder="e.g., Ayesha" required />
</div>
<div class="field">
<label for="nameB">Partner's Name</label>
<span class="icon" aria-hidden="true">💁♂️</span>
<input id="nameB" name="nameB" type="text" placeholder="e.g., Usman" required />
</div>
</div>
<details>
<summary style="cursor:pointer; color: var(--muted);">Optional: add birthdays for a tiny bonus tweak 🎂</summary>
<div class="row" style="margin-top:12px;">
<div class="field">
<label for="dobA">Your Birthday</label>
<span class="icon" aria-hidden="true">📅</span>
<input id="dobA" name="dobA" type="date" />
</div>
<div class="field">
<label for="dobB">Partner's Birthday</label>
<span class="icon" aria-hidden="true">📅</span>
<input id="dobB" name="dobB" type="date" />
</div>
</div>
</details>
<div class="actions">
<button type="submit" id="calcBtn" aria-label="Calculate love match percentage">Calculate 💘</button>
<button type="button" id="resetBtn" class="secondary" aria-label="Reset form">Reset</button>
</div>
</form>
<div id="result" class="result" aria-live="polite" aria-atomic="true">
<div class="percent" id="percent">0%</div>
<div class="bar"><i id="bar"></i></div>
<div class="msg" id="message">Enter names to see your love score!</div>
<div class="share">
<button id="copyBtn" class="secondary" type="button">Copy Result</button>
<button id="shareBtn" class="secondary" type="button">Share</button>
</div>
</div>
<p class="note">⚠️ This is just for fun—relationships are complex and beautiful beyond numbers!</p>
</div>
<script>
const form = document.getElementById('loveForm');
const nameA = document.getElementById('nameA');
const nameB = document.getElementById('nameB');
const dobA = document.getElementById('dobA');
const dobB = document.getElementById('dobB');
const percentEl = document.getElementById('percent');
const bar = document.getElementById('bar');
const message = document.getElementById('message');
const result = document.getElementById('result');
const copyBtn = document.getElementById('copyBtn');
const shareBtn = document.getElementById('shareBtn');
const resetBtn = document.getElementById('resetBtn');
// Simple symmetric, deterministic hash → 0–100
function lovePercent(a, b, aDOB, bDOB){
// Normalize & make order-independent
const A = (a||'').trim().toLowerCase();
const B = (b||'').trim().toLowerCase();
const [x, y] = [A, B].sort();
let str = `${x}❤${y}`;
// djb2 hash
let hash = 5381;
for (let i = 0; i < str.length; i++) hash = ((hash << 5) + hash) + str.charCodeAt(i);
// Optional birthdays nudge (very tiny)
if (aDOB && bDOB){
const da = new Date(aDOB), db = new Date(bDOB);
if (!isNaN(+da) && !isNaN(+db)){
const deltaDays = Math.abs(da - db) / (1000*60*60*24);
hash += Math.floor(deltaDays) % 17; // tiny deterministic variation
}
}
// Map to 1..100 for nicer look
let pct = Math.abs(hash) % 100 + 1; // 1–100
return pct;
}
function bucketMessage(p){
if (p >= 90) return "Soulmate vibes! Keep nurturing this 💞";
if (p >= 75) return "Strong potential—great chemistry and growth ahead ✨";
if (p >= 60) return "Sweet match! With effort and care, this can flourish 🌱";
if (p >= 45) return "Cute spark. Communicate openly and see where it goes 😊";
if (p >= 30) return "Different energies—compromise will be key 🧩";
return "Opposites attract? Focus on respect and shared values first 🤝";
}
function updateUI(p){
percentEl.textContent = p + '%';
bar.style.width = p + '%';
message.textContent = bucketMessage(p);
result.classList.add('show');
}
form.addEventListener('submit', (e)=>{
e.preventDefault();
const a = nameA.value; const b = nameB.value;
if (!a || !b) return;
const pct = lovePercent(a, b, dobA.value, dobB.value);
updateUI(pct);
});
resetBtn.addEventListener('click', ()=>{
form.reset();
result.classList.remove('show');
bar.style.width = '0%';
message.textContent = 'Enter names to see your love score!';
});
copyBtn.addEventListener('click', async ()=>{
const a = nameA.value.trim();
const b = nameB.value.trim();
const txt = `💘 Love Match: ${a} + ${b} = ${percentEl.textContent} — ${message.textContent}`;
try{ await navigator.clipboard.writeText(txt); copyBtn.textContent = 'Copied!'; setTimeout(()=>copyBtn.textContent='Copy Result', 1500);}catch{}
});
shareBtn.addEventListener('click', async ()=>{
const a = nameA.value.trim();
const b = nameB.value.trim();
const txt = `Love Match: ${a} + ${b} = ${percentEl.textContent} — ${message.textContent}`;
const url = location.href;
if (navigator.share){
try{ await navigator.share({ title: 'Love Match %', text: txt, url }); }catch{}
} else {
try{ await navigator.clipboard.writeText(txt + "\n" + url); shareBtn.textContent = 'Link Copied!'; setTimeout(()=>shareBtn.textContent='Share', 1500);}catch{}
}
});
// Allow pressing Enter to submit in any field
[nameA, nameB, dobA, dobB].forEach(el=>{
el.addEventListener('keydown', e=>{ if(e.key==='Enter'){ e.preventDefault(); form.requestSubmit(); } });
});
</script>
</body>
</html>