Sunday, August 17, 2025

LOVE MATCH, LOVE GRUE

 <!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>


No comments:

Post a Comment

LOVE MATCH, LOVE GRUE

 <!DOCTYPE html> <html lang="en"> <head>   <meta charset="utf-8" />   <meta name="viewpo...