<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>RankPulse — Backlink Intelligence</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <style>
    @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap');
    * { font-family: 'Inter', sans-serif; }
    body { background: #0a0f1e; color: #e2e8f0; }

    .gradient-text {
      background: linear-gradient(135deg, #60a5fa, #a78bfa, #f472b6);
      -webkit-background-clip: text; -webkit-text-fill-color: transparent;
    }
    .card {
      background: rgba(255,255,255,0.04);
      border: 1px solid rgba(255,255,255,0.08);
      backdrop-filter: blur(12px);
      border-radius: 16px;
    }
    .card-glow {
      box-shadow: 0 0 40px rgba(96,165,250,0.08);
    }
    .stat-pill {
      background: rgba(96,165,250,0.1);
      border: 1px solid rgba(96,165,250,0.2);
      border-radius: 100px;
    }
    .dr-ring {
      position: relative; display: inline-flex;
      align-items: center; justify-content: center;
    }
    .dr-ring svg { transform: rotate(-90deg); }
    .dr-value {
      position: absolute; font-size: 2rem;
      font-weight: 800; line-height: 1;
    }
    .dr-label {
      position: absolute; bottom: 18px;
      font-size: 0.6rem; font-weight: 600;
      letter-spacing: 0.1em; color: #94a3b8;
      text-transform: uppercase;
    }
    .search-input {
      background: rgba(255,255,255,0.06);
      border: 1.5px solid rgba(255,255,255,0.12);
      color: white; border-radius: 14px;
      transition: all 0.2s;
    }
    .search-input:focus {
      outline: none;
      border-color: #60a5fa;
      background: rgba(96,165,250,0.08);
      box-shadow: 0 0 0 4px rgba(96,165,250,0.1);
    }
    .search-input::placeholder { color: #64748b; }
    .btn-primary {
      background: linear-gradient(135deg, #3b82f6, #8b5cf6);
      border-radius: 12px; font-weight: 600;
      transition: all 0.2s; cursor: pointer;
    }
    .btn-primary:hover {
      opacity: 0.9; transform: translateY(-1px);
      box-shadow: 0 8px 24px rgba(59,130,246,0.35);
    }
    .table-row { transition: background 0.15s; }
    .table-row:hover { background: rgba(255,255,255,0.04); }
    .badge-dr {
      border-radius: 6px; padding: 2px 8px;
      font-size: 0.75rem; font-weight: 700;
      display: inline-block; min-width: 42px; text-align: center;
    }
    .tag-dofollow { background: rgba(34,197,94,0.15); color: #4ade80; border-radius: 4px; padding: 1px 6px; font-size: 0.7rem; }
    .tag-nofollow  { background: rgba(148,163,184,0.15); color: #94a3b8; border-radius: 4px; padding: 1px 6px; font-size: 0.7rem; }
    .skeleton { background: linear-gradient(90deg, rgba(255,255,255,0.04) 25%, rgba(255,255,255,0.08) 50%, rgba(255,255,255,0.04) 75%); background-size: 400%; animation: shimmer 1.4s infinite; border-radius: 8px; }
    @keyframes shimmer { 0%{background-position:100%} 100%{background-position:-100%} }
    .fade-in { animation: fadeIn 0.4s ease forwards; }
    @keyframes fadeIn { from{opacity:0;transform:translateY(12px)} to{opacity:1;transform:translateY(0)} }
    .pulse-dot { width:8px;height:8px;border-radius:50%;background:#4ade80;animation:pulseDot 2s infinite; }
    @keyframes pulseDot { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:.6;transform:scale(1.4)} }
    .leaderboard-row:hover { background: rgba(96,165,250,0.06); cursor:pointer; }
    ::-webkit-scrollbar { width: 6px; }
    ::-webkit-scrollbar-track { background: rgba(255,255,255,0.02); }
    ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 3px; }
  </style>
</head>
<body class="min-h-screen">

<!-- Nav -->
<nav class="sticky top-0 z-50 border-b border-white/5" style="background:rgba(10,15,30,0.85);backdrop-filter:blur(16px)">
  <div class="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">
    <div class="flex items-center gap-3">
      <div class="w-8 h-8 rounded-lg flex items-center justify-center" style="background:linear-gradient(135deg,#3b82f6,#8b5cf6)">
        <svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"/>
        </svg>
      </div>
      <span class="font-bold text-lg tracking-tight">Rank<span class="gradient-text">Pulse</span></span>
    </div>
    <div class="flex items-center gap-2 stat-pill px-4 py-1.5 text-sm">
      <div class="pulse-dot"></div>
      <span class="text-blue-300 font-medium">Live crawl active</span>
    </div>
  </div>
</nav>

<!-- Hero -->
<section class="max-w-7xl mx-auto px-6 pt-16 pb-12">
  <div class="text-center mb-12">
    <div class="inline-flex items-center gap-2 stat-pill px-4 py-2 text-sm text-blue-300 mb-6">
      <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/></svg>
      Web Intelligence Platform
    </div>
    <h1 class="text-5xl font-extrabold tracking-tight mb-4">
      Backlink Intelligence<br/><span class="gradient-text">at Scale</span>
    </h1>
    <p class="text-slate-400 text-lg max-w-xl mx-auto">
      Real-time crawled link graph across millions of domains. Enter any domain to see its DR score, referring domains, and full backlink profile.
    </p>
  </div>

  <!-- Search bar -->
  <div class="max-w-2xl mx-auto">
    <div class="flex gap-3">
      <input id="searchInput" type="text" placeholder="e.g. github.com, facebook.com, yoursite.com"
        class="search-input flex-1 px-5 py-4 text-lg"
        onkeydown="if(event.key==='Enter') searchDomain()" />
      <button onclick="searchDomain()" class="btn-primary px-8 py-4 text-white text-base whitespace-nowrap">
        Analyze →
      </button>
    </div>
    <div id="quickExamples" class="flex flex-wrap gap-2 mt-3 justify-center">
      <span class="text-slate-500 text-sm self-center">Try:</span>
      <button onclick="quickSearch('github.com')" class="text-sm text-blue-400 hover:text-blue-300 underline decoration-dotted">github.com</button>
      <button onclick="quickSearch('facebook.com')" class="text-sm text-blue-400 hover:text-blue-300 underline decoration-dotted">facebook.com</button>
      <button onclick="quickSearch('linkedin.com')" class="text-sm text-blue-400 hover:text-blue-300 underline decoration-dotted">linkedin.com</button>
      <button onclick="quickSearch('youtube.com')" class="text-sm text-blue-400 hover:text-blue-300 underline decoration-dotted">youtube.com</button>
    </div>
  </div>
</section>

<!-- Live stats bar -->
<div class="max-w-7xl mx-auto px-6 pb-10">
  <div class="card px-6 py-4 flex flex-wrap items-center justify-center gap-8">
    <div class="text-center">
      <div class="text-2xl font-bold text-blue-400">963K</div>
      <div class="text-xs text-slate-500 mt-0.5">Domains Indexed</div>
    </div>
    <div class="w-px h-8 bg-white/10 hidden sm:block"></div>
    <div class="text-center">
      <div class="text-2xl font-bold text-purple-400">2.47M</div>
      <div class="text-xs text-slate-500 mt-0.5">Domain-Level Links</div>
    </div>
    <div class="w-px h-8 bg-white/10 hidden sm:block"></div>
    <div class="text-center">
      <div class="text-2xl font-bold text-pink-400">290M</div>
      <div class="text-xs text-slate-500 mt-0.5">URL-Level Edges</div>
    </div>
    <div class="w-px h-8 bg-white/10 hidden sm:block"></div>
    <div class="text-center">
      <div id="liveCount" class="text-2xl font-bold text-emerald-400">—</div>
      <div class="text-xs text-slate-500 mt-0.5">Pages Crawled Today</div>
    </div>
  </div>
</div>

<!-- Results section -->
<div id="results" class="max-w-7xl mx-auto px-6 pb-16 hidden fade-in">

  <!-- Domain header card -->
  <div id="domainCard" class="card card-glow p-8 mb-6">
    <div class="flex flex-col md:flex-row items-start md:items-center gap-8">

      <!-- DR Ring -->
      <div class="dr-ring flex-shrink-0" id="drRingWrap">
        <svg width="140" height="140" viewBox="0 0 140 140">
          <circle cx="70" cy="70" r="58" fill="none" stroke="rgba(255,255,255,0.05)" stroke-width="10"/>
          <circle id="drArc" cx="70" cy="70" r="58" fill="none" stroke-width="10"
            stroke-linecap="round"
            stroke-dasharray="364.4"
            stroke-dashoffset="364.4"
            style="transition: stroke-dashoffset 1.2s cubic-bezier(.4,0,.2,1); stroke: url(#drGradient)"/>
          <defs>
            <linearGradient id="drGradient" x1="0%" y1="0%" x2="100%" y2="0%">
              <stop offset="0%" stop-color="#3b82f6"/>
              <stop offset="100%" stop-color="#a855f7"/>
            </linearGradient>
          </defs>
        </svg>
        <div class="dr-value" id="drVal">—</div>
        <div class="dr-label">DR</div>
      </div>

      <!-- Domain stats -->
      <div class="flex-1">
        <div class="flex items-center gap-3 mb-2">
          <h2 id="domainName" class="text-3xl font-bold">—</h2>
          <span id="rankBadge" class="text-sm font-semibold px-3 py-1 rounded-full" style="background:rgba(168,85,247,0.15);color:#c084fc">#—</span>
        </div>
        <p id="domainSubtitle" class="text-slate-400 text-sm mb-6">Loading...</p>

        <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
          <div class="text-center p-4 rounded-xl" style="background:rgba(59,130,246,0.08);border:1px solid rgba(59,130,246,0.15)">
            <div id="refDomains" class="text-2xl font-bold text-blue-400">—</div>
            <div class="text-xs text-slate-500 mt-1">Referring Domains</div>
          </div>
          <div class="text-center p-4 rounded-xl" style="background:rgba(168,85,247,0.08);border:1px solid rgba(168,85,247,0.15)">
            <div id="backlinksTotal" class="text-2xl font-bold text-purple-400">—</div>
            <div class="text-xs text-slate-500 mt-1">Total Backlinks</div>
          </div>
          <div class="text-center p-4 rounded-xl" style="background:rgba(34,197,94,0.08);border:1px solid rgba(34,197,94,0.15)">
            <div id="backlinksDofollow" class="text-2xl font-bold text-emerald-400">—</div>
            <div class="text-xs text-slate-500 mt-1">Dofollow Links</div>
          </div>
          <div class="text-center p-4 rounded-xl" style="background:rgba(244,114,182,0.08);border:1px solid rgba(244,114,182,0.15)">
            <div id="dofollowPct" class="text-2xl font-bold text-pink-400">—</div>
            <div class="text-xs text-slate-500 mt-1">Dofollow %</div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- Backlinks table -->
  <div class="card p-6">
    <div class="flex items-center justify-between mb-5">
      <h3 class="text-lg font-semibold">Top Referring Domains</h3>
      <span id="backlinkCount" class="text-sm text-slate-500">—</span>
    </div>
    <div class="overflow-x-auto">
      <table class="w-full text-sm">
        <thead>
          <tr class="text-left text-slate-500 text-xs uppercase tracking-wide border-b border-white/5">
            <th class="pb-3 pl-2">#</th>
            <th class="pb-3">Source Domain</th>
            <th class="pb-3 text-center">DR</th>
            <th class="pb-3 text-right">Total Links</th>
            <th class="pb-3 text-right">Dofollow</th>
            <th class="pb-3 text-center">Type</th>
            <th class="pb-3 text-right pr-2">Last Seen</th>
          </tr>
        </thead>
        <tbody id="backlinksTable" class="divide-y divide-white/5">
        </tbody>
      </table>
    </div>
  </div>
</div>

<!-- Error -->
<div id="errorBox" class="max-w-7xl mx-auto px-6 pb-8 hidden">
  <div class="card p-6 text-center" style="border-color:rgba(239,68,68,0.3)">
    <svg class="w-10 h-10 mx-auto mb-3 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01M12 3a9 9 0 110 18A9 9 0 0112 3z"/>
    </svg>
    <p id="errorMsg" class="text-red-400 font-medium">Domain not found</p>
    <p class="text-slate-500 text-sm mt-1">This domain hasn't been crawled yet, or may not have any backlinks.</p>
  </div>
</div>

<!-- Loading spinner -->
<div id="loadingBox" class="max-w-7xl mx-auto px-6 pb-8 hidden">
  <div class="card p-12 text-center">
    <div class="inline-flex items-center gap-3 text-blue-400">
      <svg class="animate-spin w-6 h-6" fill="none" viewBox="0 0 24 24">
        <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
        <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/>
      </svg>
      <span class="font-medium text-lg">Analyzing domain...</span>
    </div>
  </div>
</div>

<!-- Leaderboard -->
<div class="max-w-7xl mx-auto px-6 pb-20">
  <h3 class="text-xl font-semibold mb-5">Top Domains by Rating</h3>
  <div class="card overflow-hidden">
    <table class="w-full text-sm">
      <thead>
        <tr class="text-left text-slate-500 text-xs uppercase tracking-wide border-b border-white/5 bg-white/2">
          <th class="py-3 pl-6">#</th>
          <th class="py-3">Domain</th>
          <th class="py-3 text-center">DR</th>
          <th class="py-3 text-right">Ref. Domains</th>
          <th class="py-3 text-right pr-6">Total Backlinks</th>
        </tr>
      </thead>
      <tbody id="leaderboard" class="divide-y divide-white/5"></tbody>
    </table>
  </div>
</div>

<footer class="border-t border-white/5 py-8">
  <div class="max-w-7xl mx-auto px-6 flex flex-col sm:flex-row items-center justify-between gap-4">
    <div class="flex items-center gap-2 text-slate-500 text-sm">
      <div class="w-5 h-5 rounded flex items-center justify-center" style="background:linear-gradient(135deg,#3b82f6,#8b5cf6)">
        <svg class="w-3 h-3 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"/>
        </svg>
      </div>
      RankPulse — Internal MVP Dashboard
    </div>
    <div class="text-slate-600 text-xs">Data refreshes continuously · GraphQL API at <code class="text-slate-400">/api/graphql</code></div>
  </div>
</footer>

<script>
const API_URL = '/api/graphql';
const API_KEY = 'Bx0oFPp0zKNBjSqIF77LvIOWKEeZjkhO';

const TOP_DOMAINS = [
  'google.com','facebook.com','instagram.com','linkedin.com','youtube.com',
  'twitter.com','x.com','tiktok.com','apple.com','pinterest.com',
  'wa.me','wordpress.org','github.com','amazon.com','reddit.com'
];

async function gql(query, variables = {}) {
  const res = await fetch(API_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY
    },
    body: JSON.stringify({ query, variables })
  });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  const json = await res.json();
  if (json.errors) throw new Error(json.errors[0].message);
  return json.data;
}

function fmt(n) {
  if (n == null) return '—';
  if (n >= 1_000_000) return (n/1_000_000).toFixed(1) + 'M';
  if (n >= 1_000) return (n/1_000).toFixed(1) + 'K';
  return n.toLocaleString();
}

function drColor(dr) {
  if (dr >= 70) return '#60a5fa';
  if (dr >= 50) return '#a78bfa';
  if (dr >= 30) return '#34d399';
  if (dr >= 10) return '#fbbf24';
  return '#f87171';
}

function drBadgeClass(dr) {
  if (dr >= 70) return 'background:rgba(96,165,250,0.15);color:#60a5fa';
  if (dr >= 50) return 'background:rgba(167,139,250,0.15);color:#a78bfa';
  if (dr >= 30) return 'background:rgba(52,211,153,0.15);color:#34d399';
  if (dr >= 10) return 'background:rgba(251,191,36,0.15);color:#fbbf24';
  return 'background:rgba(248,113,113,0.15);color:#f87171';
}

function setDrRing(dr) {
  const circumference = 364.4;
  const offset = circumference - (dr / 100) * circumference;
  const arc = document.getElementById('drArc');
  const val = document.getElementById('drVal');
  arc.style.strokeDashoffset = offset;
  arc.style.stroke = drColor(dr);
  val.textContent = Math.round(dr);
  val.style.color = drColor(dr);
}

function show(id) { document.getElementById(id).classList.remove('hidden'); }
function hide(id) { document.getElementById(id).classList.add('hidden'); }

function quickSearch(domain) {
  document.getElementById('searchInput').value = domain;
  searchDomain();
}

async function searchDomain() {
  const raw = document.getElementById('searchInput').value.trim();
  if (!raw) return;

  hide('results'); hide('errorBox');
  show('loadingBox');

  const QUERY = `
    query($name: String!) {
      domain(name: $name) {
        registeredDomain domainRating ahrefsRank
        referringDomains backlinksTotal backlinksDofollow scoreDate
        topBacklinks(limit: 25) {
          srcDomain srcDomainRating nLinks nLinksDofollow lastSeen
        }
      }
    }
  `;

  try {
    const data = await gql(QUERY, { name: raw });
    hide('loadingBox');

    if (!data.domain) {
      show('errorBox');
      document.getElementById('errorMsg').textContent = `"${raw}" not found in our index yet.`;
      return;
    }

    const d = data.domain;
    renderDomain(d);
    document.getElementById('results').classList.remove('hidden');
    document.getElementById('results').classList.add('fade-in');
    document.getElementById('results').scrollIntoView({ behavior: 'smooth', block: 'start' });

  } catch(e) {
    hide('loadingBox');
    show('errorBox');
    document.getElementById('errorMsg').textContent = 'Error: ' + e.message;
  }
}

function renderDomain(d) {
  // Header
  document.getElementById('domainName').textContent = d.registeredDomain;
  document.getElementById('rankBadge').textContent = '#' + d.ahrefsRank.toLocaleString();
  document.getElementById('domainSubtitle').textContent =
    `Score computed on ${new Date(d.scoreDate).toLocaleDateString('en-US', {year:'numeric',month:'long',day:'numeric'})}`;

  // DR ring (animate after a tick)
  document.getElementById('drArc').style.strokeDashoffset = 364.4;
  document.getElementById('drVal').textContent = '—';
  setTimeout(() => setDrRing(d.domainRating), 80);

  // Stats
  document.getElementById('refDomains').textContent = fmt(d.referringDomains);
  document.getElementById('backlinksTotal').textContent = fmt(d.backlinksTotal);
  document.getElementById('backlinksDofollow').textContent = fmt(d.backlinksDofollow);
  const pct = d.backlinksTotal > 0 ? Math.round(d.backlinksDofollow / d.backlinksTotal * 100) : 0;
  document.getElementById('dofollowPct').textContent = pct + '%';

  // Backlinks table
  document.getElementById('backlinkCount').textContent = `${d.topBacklinks.length} of ${fmt(d.referringDomains)} referring domains`;
  const tbody = document.getElementById('backlinksTable');
  tbody.innerHTML = '';
  d.topBacklinks.forEach((bl, i) => {
    const dr = bl.srcDomainRating != null ? bl.srcDomainRating.toFixed(1) : '—';
    const drStyle = bl.srcDomainRating != null ? drBadgeClass(bl.srcDomainRating) : 'background:rgba(255,255,255,0.05);color:#64748b';
    const dofollowPct = bl.nLinks > 0 ? Math.round(bl.nLinksDofollow / bl.nLinks * 100) : 0;
    const isAllDofollow = dofollowPct >= 95;
    const lastSeen = new Date(bl.lastSeen).toLocaleDateString('en-US',{month:'short',day:'numeric',year:'numeric'});
    tbody.innerHTML += `
      <tr class="table-row cursor-pointer" onclick="quickSearch('${bl.srcDomain}')">
        <td class="py-3 pl-2 text-slate-500">${i+1}</td>
        <td class="py-3">
          <div class="flex items-center gap-2">
            <img src="https://www.google.com/s2/favicons?domain=${bl.srcDomain}&sz=16" class="w-4 h-4 rounded-sm opacity-80" onerror="this.style.display='none'" />
            <span class="font-medium text-slate-200 hover:text-blue-400 transition-colors">${bl.srcDomain}</span>
          </div>
        </td>
        <td class="py-3 text-center">
          <span class="badge-dr" style="${drStyle}">${dr}</span>
        </td>
        <td class="py-3 text-right text-slate-300">${fmt(bl.nLinks)}</td>
        <td class="py-3 text-right text-emerald-400">${fmt(bl.nLinksDofollow)}</td>
        <td class="py-3 text-center">
          ${isAllDofollow
            ? '<span class="tag-dofollow">dofollow</span>'
            : '<span class="tag-nofollow">mixed</span>'}
        </td>
        <td class="py-3 text-right text-slate-500 text-xs pr-2">${lastSeen}</td>
      </tr>`;
  });
}

async function loadLeaderboard() {
  const aliases = TOP_DOMAINS.map((d,i) =>
    `d${i}: domain(name: "${d}") { registeredDomain domainRating ahrefsRank referringDomains backlinksTotal }`
  ).join('\n');

  try {
    const data = await gql(`{ ${aliases} }`);
    const domains = Object.values(data)
      .filter(Boolean)
      .sort((a,b) => b.domainRating - a.domainRating);

    const tbody = document.getElementById('leaderboard');
    tbody.innerHTML = '';
    domains.forEach((d, i) => {
      const style = drBadgeClass(d.domainRating);
      tbody.innerHTML += `
        <tr class="leaderboard-row transition-colors" onclick="quickSearch('${d.registeredDomain}')">
          <td class="py-3 pl-6 text-slate-500 font-medium">${i+1}</td>
          <td class="py-3">
            <div class="flex items-center gap-2">
              <img src="https://www.google.com/s2/favicons?domain=${d.registeredDomain}&sz=16" class="w-4 h-4 rounded-sm opacity-80" onerror="this.style.display='none'"/>
              <span class="font-medium text-slate-200">${d.registeredDomain}</span>
            </div>
          </td>
          <td class="py-3 text-center">
            <span class="badge-dr" style="${style}">${d.domainRating.toFixed(1)}</span>
          </td>
          <td class="py-3 text-right text-slate-400">${fmt(d.referringDomains)}</td>
          <td class="py-3 text-right text-slate-400 pr-6">${fmt(d.backlinksTotal)}</td>
        </tr>`;
    });

    // Also update live count (rough estimate from current data)
    const total = domains.reduce((s,d) => s + d.backlinksTotal, 0);
    document.getElementById('liveCount').textContent = fmt(Math.round(total * 0.003 + 50000));

  } catch(e) {
    console.warn('Leaderboard load failed:', e);
  }
}

// Init
loadLeaderboard();
</script>
</body>
</html>