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

    /* Tabs */
    .tab { padding: 10px 18px; border-radius: 10px; font-weight: 600; color: #94a3b8; cursor: pointer; transition: all 0.18s; user-select: none; }
    .tab:hover { color: #e2e8f0; background: rgba(255,255,255,0.04); }
    .tab.active { color: #fff; background: linear-gradient(135deg, rgba(59,130,246,0.18), rgba(139,92,246,0.18)); border: 1px solid rgba(96,165,250,0.3); }

    /* Filter chips */
    .chip { padding: 5px 12px; border-radius: 100px; font-size: 0.75rem; font-weight: 600; cursor: pointer; transition: all 0.18s; user-select: none; border: 1px solid rgba(255,255,255,0.08); color: #94a3b8; background: rgba(255,255,255,0.03); }
    .chip:hover { color: #e2e8f0; border-color: rgba(255,255,255,0.18); }
    .chip.active { color: #fff; background: linear-gradient(135deg, rgba(59,130,246,0.22), rgba(139,92,246,0.22)); border-color: rgba(96,165,250,0.4); }

    /* Anchor cloud */
    .anchor-bubble { display:inline-flex; align-items:center; gap:8px; padding: 8px 14px; border-radius: 100px; margin: 4px; transition: transform 0.15s; border: 1px solid rgba(255,255,255,0.08); background: rgba(255,255,255,0.03); }
    .anchor-bubble:hover { transform: translateY(-2px); border-color: rgba(96,165,250,0.4); cursor: pointer; }

    /* Anchor category dots */
    .cat-branded   { background:#22d3ee; }
    .cat-naked     { background:#a78bfa; }
    .cat-generic   { background:#fbbf24; }
    .cat-topical   { background:#34d399; }
    .cat-image     { background:#f472b6; }
    .cat-empty     { background:#64748b; }
    .cat-dot { width:8px; height:8px; border-radius:50%; display:inline-block; }

    /* Position badges */
    .pos-content  { background:rgba(34,197,94,0.15); color:#4ade80; }
    .pos-nav      { background:rgba(251,191,36,0.15); color:#fbbf24; }
    .pos-footer   { background:rgba(248,113,113,0.15); color:#f87171; }
    .pos-header   { background:rgba(167,139,250,0.15); color:#a78bfa; }
    .pos-sidebar  { background:rgba(96,165,250,0.15); color:#60a5fa; }

    /* Status badges */
    .status-live  { background:rgba(34,197,94,0.15); color:#4ade80; }
    .status-lost  { background:rgba(148,163,184,0.15); color:#94a3b8; }

    .surround { font-size: 0.75rem; color: #64748b; font-style: italic; padding: 6px 10px; background: rgba(0,0,0,0.2); border-radius: 6px; border-left: 2px solid rgba(96,165,250,0.4); margin-top: 4px; }
  </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>

  <!-- Tabs -->
  <div class="flex gap-2 mb-5 flex-wrap">
    <div class="tab active" data-tab="overview" onclick="switchTab('overview')">Overview</div>
    <div class="tab" data-tab="backlinks" onclick="switchTab('backlinks')">Backlinks Detail</div>
    <div class="tab" data-tab="anchors" onclick="switchTab('anchors')">Anchor Cloud</div>
    <div class="tab" data-tab="positions" onclick="switchTab('positions')">Positions & Quality</div>
  </div>

  <!-- TAB: Overview (legacy referring-domains view) -->
  <div id="tab-overview" class="tab-pane">
    <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>

  <!-- TAB: Backlinks Detail (Ahrefs-style per-link with anchor) -->
  <div id="tab-backlinks" class="tab-pane hidden">
    <!-- Stats summary -->
    <div id="backlinkStatsBar" class="grid grid-cols-2 md:grid-cols-5 gap-3 mb-5"></div>

    <!-- Filters -->
    <div class="card p-5 mb-5">
      <div class="flex items-center gap-3 mb-3">
        <svg class="w-4 h-4 text-slate-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2a1 1 0 01-.293.707L14 13.414V19a1 1 0 01-.553.894l-4 2A1 1 0 018 21v-7.586L3.293 6.707A1 1 0 013 6V4z"/></svg>
        <span class="text-sm font-semibold text-slate-300">Filters</span>
      </div>

      <div class="space-y-3">
        <div class="flex items-center gap-2 flex-wrap">
          <span class="text-xs uppercase tracking-wide text-slate-500 mr-1">Type:</span>
          <span class="chip filter-chip active" data-group="rel" data-value="dofollow">dofollow</span>
          <span class="chip filter-chip active" data-group="rel" data-value="nofollow">nofollow</span>
          <span class="chip filter-chip" data-group="rel" data-value="ugc">ugc</span>
          <span class="chip filter-chip" data-group="rel" data-value="sponsored">sponsored</span>
        </div>

        <div class="flex items-center gap-2 flex-wrap">
          <span class="text-xs uppercase tracking-wide text-slate-500 mr-1">Position:</span>
          <span class="chip filter-chip active" data-group="pos" data-value="content">content</span>
          <span class="chip filter-chip" data-group="pos" data-value="nav">nav</span>
          <span class="chip filter-chip" data-group="pos" data-value="footer">footer</span>
          <span class="chip filter-chip" data-group="pos" data-value="header">header</span>
          <span class="chip filter-chip" data-group="pos" data-value="sidebar">sidebar</span>
        </div>

        <div class="flex items-center gap-2 flex-wrap">
          <span class="text-xs uppercase tracking-wide text-slate-500 mr-1">Anchor:</span>
          <span class="chip filter-chip" data-group="cat" data-value="branded">branded</span>
          <span class="chip filter-chip" data-group="cat" data-value="naked">naked</span>
          <span class="chip filter-chip" data-group="cat" data-value="topical">topical</span>
          <span class="chip filter-chip" data-group="cat" data-value="generic">generic</span>
          <span class="chip filter-chip" data-group="cat" data-value="image">image</span>
          <span class="chip filter-chip" data-group="cat" data-value="empty">empty</span>
        </div>

        <div class="flex items-center gap-3 flex-wrap pt-1">
          <label class="flex items-center gap-2 text-sm text-slate-400 cursor-pointer">
            <input type="checkbox" id="filterOnlyLive" class="accent-blue-500"/>
            <span>Only live (last 30 days)</span>
          </label>
          <label class="flex items-center gap-2 text-sm text-slate-400 ml-4">
            <span>Min source DR:</span>
            <input type="number" id="filterMinDR" min="0" max="100" step="1" placeholder="0"
              class="w-16 px-2 py-1 rounded bg-white/5 border border-white/10 text-slate-200"/>
          </label>
          <button onclick="applyBacklinkFilters()" class="btn-primary px-5 py-1.5 text-sm text-white">Apply →</button>
        </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">Backlink Detail</h3>
        <span id="backlinkDetailCount" class="text-sm text-slate-500">—</span>
      </div>
      <div id="backlinkDetailLoading" class="hidden text-center py-8 text-slate-500">
        <div class="inline-flex items-center gap-2">
          <svg class="animate-spin w-4 h-4" 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="text-sm">Loading backlink details...</span>
        </div>
      </div>
      <div id="backlinkDetailEmpty" class="hidden text-center py-8 text-slate-500 text-sm">
        No backlinks match these filters yet. The backlink-detail-builder service may still be populating data for this domain — re-check in a few minutes.
      </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">Source page</th>
              <th class="pb-3 text-center">DR</th>
              <th class="pb-3">Anchor</th>
              <th class="pb-3 text-center">Position</th>
              <th class="pb-3 text-center">Type</th>
              <th class="pb-3 text-center">Status</th>
              <th class="pb-3 text-right pr-2">Last seen</th>
            </tr>
          </thead>
          <tbody id="backlinkDetailTable" class="divide-y divide-white/5"></tbody>
        </table>
      </div>
      <div class="mt-4 flex items-center justify-between text-xs text-slate-500">
        <span id="backlinkDetailPager">—</span>
        <div class="flex gap-2">
          <button id="bdPrev" onclick="bdPageChange(-1)" class="px-3 py-1.5 rounded bg-white/5 hover:bg-white/10 text-slate-300 disabled:opacity-30 disabled:cursor-not-allowed">← Prev</button>
          <button id="bdNext" onclick="bdPageChange(+1)" class="px-3 py-1.5 rounded bg-white/5 hover:bg-white/10 text-slate-300 disabled:opacity-30 disabled:cursor-not-allowed">Next →</button>
        </div>
      </div>
    </div>
  </div>

  <!-- TAB: Anchor Cloud -->
  <div id="tab-anchors" class="tab-pane hidden">
    <div class="card p-6">
      <div class="flex items-center justify-between mb-5">
        <div>
          <h3 class="text-lg font-semibold">Anchor Text Cloud</h3>
          <p class="text-xs text-slate-500 mt-1">How other sites describe this domain when linking to it. Sorted by referring domain count.</p>
        </div>
        <div class="flex items-center gap-3 text-xs text-slate-400">
          <span class="flex items-center gap-1"><span class="cat-dot cat-branded"></span>branded</span>
          <span class="flex items-center gap-1"><span class="cat-dot cat-topical"></span>topical</span>
          <span class="flex items-center gap-1"><span class="cat-dot cat-generic"></span>generic</span>
          <span class="flex items-center gap-1"><span class="cat-dot cat-naked"></span>naked</span>
          <span class="flex items-center gap-1"><span class="cat-dot cat-image"></span>image</span>
        </div>
      </div>
      <div id="anchorCloudLoading" class="hidden text-center py-8 text-slate-500 text-sm">Loading anchors...</div>
      <div id="anchorCloud" class="flex flex-wrap"></div>
    </div>
  </div>

  <!-- TAB: Positions & Quality -->
  <div id="tab-positions" class="tab-pane hidden">
    <div class="card p-6 mb-5">
      <h3 class="text-lg font-semibold mb-1">Link Position Breakdown</h3>
      <p class="text-xs text-slate-500 mb-5">Google heavily discounts <span class="text-amber-400">nav</span> and <span class="text-red-400">footer</span> boilerplate links. Domains with most of their backlinks in <span class="text-emerald-400">content</span> are receiving genuine editorial endorsements.</p>
      <div id="positionBars" class="space-y-3"></div>
    </div>

    <div class="card p-6">
      <h3 class="text-lg font-semibold mb-1">Anchor Quality Profile</h3>
      <p class="text-xs text-slate-500 mb-5">Distribution of anchor categories. A healthy profile is ~30-40% branded, ~10-20% naked URL, &lt;5% generic, rest topical.</p>
      <div id="anchorCategoryBars" class="space-y-3"></div>
    </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();
}

// Active search context — used by tabs that lazy-load their data.
let CURRENT_DOMAIN = null;
let CURRENT_DOMAIN_DATA = null;
let bdOffset = 0;
let bdLimit = 25;

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

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

  // Reset tab state on fresh search
  switchTab('overview', /*loadOnly*/true);
  bdOffset = 0;

  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;
    CURRENT_DOMAIN = d.registeredDomain;
    CURRENT_DOMAIN_DATA = d;
    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;
  }
}

// ─────────────── Tab switching ───────────────
function switchTab(name, loadOnly) {
  document.querySelectorAll('.tab').forEach(t => t.classList.toggle('active', t.dataset.tab === name));
  document.querySelectorAll('.tab-pane').forEach(p => p.classList.toggle('hidden', p.id !== `tab-${name}`));
  if (loadOnly) return;
  // Lazy-load tab data when shown
  if (!CURRENT_DOMAIN) return;
  if (name === 'backlinks') loadBacklinkStatsAndDetail();
  if (name === 'anchors') loadAnchorCloud();
  if (name === 'positions') loadPositionAndQuality();
}

// ─────────────── Backlinks tab ───────────────
function collectFilters() {
  const filter = {};
  ['rel','pos','cat'].forEach(group => {
    const vals = Array.from(document.querySelectorAll(`.filter-chip[data-group="${group}"].active`))
      .map(el => el.dataset.value);
    if (group === 'rel' && vals.length > 0) filter.rel = vals;
    if (group === 'pos' && vals.length > 0) filter.linkPosition = vals;
    if (group === 'cat' && vals.length > 0) filter.anchorCategory = vals;
  });
  const minDR = parseFloat(document.getElementById('filterMinDR').value);
  if (!isNaN(minDR) && minDR > 0) filter.minSrcDR = minDR;
  if (document.getElementById('filterOnlyLive').checked) filter.onlyLive = true;
  return filter;
}

function applyBacklinkFilters() {
  bdOffset = 0;
  loadBacklinkStatsAndDetail();
}

function bdPageChange(delta) {
  bdOffset = Math.max(0, bdOffset + delta * bdLimit);
  loadBacklinkStatsAndDetail();
}

async function loadBacklinkStatsAndDetail() {
  if (!CURRENT_DOMAIN) return;
  show('backlinkDetailLoading');
  hide('backlinkDetailEmpty');
  document.getElementById('backlinkDetailTable').innerHTML = '';

  const filter = collectFilters();
  const QUERY = `
    query($name: String!, $filter: BacklinkFilter, $limit: Int!, $offset: Int!) {
      domain(name: $name) {
        backlinkStats {
          totalBacklinks liveBacklinks lostBacklinks
          dofollowBacklinks nofollowBacklinks
          referringDomains referringPages
          contentBacklinks navBacklinks footerBacklinks
        }
        backlinkDetails(filter: $filter, limit: $limit, offset: $offset) {
          srcURL srcDomain srcDomainRating dstURL anchorText anchorCategory
          surroundingText rel linkType linkPosition srcOutboundCount
          firstSeen lastSeen status nObservations
        }
      }
    }`;
  try {
    const data = await gql(QUERY, { name: CURRENT_DOMAIN, filter, limit: bdLimit, offset: bdOffset });
    hide('backlinkDetailLoading');
    if (!data.domain) return;

    renderBacklinkStats(data.domain.backlinkStats);
    renderBacklinkDetail(data.domain.backlinkDetails);
  } catch(e) {
    hide('backlinkDetailLoading');
    document.getElementById('backlinkDetailEmpty').textContent = 'Failed to load: ' + e.message;
    show('backlinkDetailEmpty');
  }
}

function renderBacklinkStats(s) {
  if (!s) return;
  const bar = document.getElementById('backlinkStatsBar');
  const total = s.totalBacklinks || 0;
  const dofollowPct = total > 0 ? Math.round(s.dofollowBacklinks / total * 100) : 0;
  bar.innerHTML = `
    <div class="card p-4 text-center">
      <div class="text-2xl font-bold text-blue-400">${fmt(s.totalBacklinks)}</div>
      <div class="text-xs text-slate-500 mt-1">Total backlinks</div>
    </div>
    <div class="card p-4 text-center">
      <div class="text-2xl font-bold text-emerald-400">${fmt(s.liveBacklinks)}</div>
      <div class="text-xs text-slate-500 mt-1">Live (last 30d)</div>
    </div>
    <div class="card p-4 text-center">
      <div class="text-2xl font-bold text-slate-400">${fmt(s.lostBacklinks)}</div>
      <div class="text-xs text-slate-500 mt-1">Lost / stale</div>
    </div>
    <div class="card p-4 text-center">
      <div class="text-2xl font-bold text-purple-400">${dofollowPct}%</div>
      <div class="text-xs text-slate-500 mt-1">Dofollow rate</div>
    </div>
    <div class="card p-4 text-center">
      <div class="text-2xl font-bold text-pink-400">${fmt(s.referringDomains)}</div>
      <div class="text-xs text-slate-500 mt-1">Ref. domains</div>
    </div>
  `;
}

function renderBacklinkDetail(rows) {
  const tbody = document.getElementById('backlinkDetailTable');
  const counter = document.getElementById('backlinkDetailCount');
  const pager = document.getElementById('backlinkDetailPager');
  tbody.innerHTML = '';
  if (!rows || rows.length === 0) {
    show('backlinkDetailEmpty');
    counter.textContent = '0';
    pager.textContent = 'No results';
    document.getElementById('bdPrev').disabled = bdOffset === 0;
    document.getElementById('bdNext').disabled = true;
    return;
  }
  hide('backlinkDetailEmpty');
  counter.textContent = `Showing ${rows.length} backlinks (offset ${bdOffset})`;
  pager.textContent = `Page ${Math.floor(bdOffset / bdLimit) + 1}`;
  document.getElementById('bdPrev').disabled = bdOffset === 0;
  document.getElementById('bdNext').disabled = rows.length < bdLimit;

  rows.forEach(b => {
    const drVal = b.srcDomainRating != null ? b.srcDomainRating.toFixed(1) : '—';
    const drStyle = b.srcDomainRating != null ? drBadgeClass(b.srcDomainRating) : 'background:rgba(255,255,255,0.05);color:#64748b';
    const lastSeen = new Date(b.lastSeen).toLocaleDateString('en-US',{month:'short',day:'numeric',year:'numeric'});
    const posClass = 'pos-' + b.linkPosition;
    const statusClass = b.status === 'LIVE' ? 'status-live' : 'status-lost';
    const relTag = b.rel === 'dofollow' ? 'tag-dofollow' : 'tag-nofollow';
    const catDot = 'cat-' + b.anchorCategory;
    const surround = b.surroundingText && b.surroundingText.trim() ? `<div class="surround">…${escapeHtml(b.surroundingText)}…</div>` : '';
    const anchorDisplay = b.anchorText ? escapeHtml(b.anchorText) : '<span class="text-slate-500 italic">(empty)</span>';

    tbody.innerHTML += `
      <tr class="table-row align-top">
        <td class="py-4 pl-2 max-w-xs">
          <div class="flex items-start gap-2">
            <img src="https://www.google.com/s2/favicons?domain=${b.srcDomain}&sz=16" class="w-4 h-4 rounded-sm opacity-80 mt-0.5" onerror="this.style.display='none'"/>
            <div class="flex-1 min-w-0">
              <div class="text-slate-200 font-medium truncate" title="${escapeHtml(b.srcURL)}">${escapeHtml(b.srcDomain)}</div>
              <a href="${escapeHtml(b.srcURL)}" target="_blank" rel="noopener noreferrer" class="text-xs text-blue-400 hover:underline truncate block">${escapeHtml(b.srcURL.replace(/^https?:\/\/[^\/]+/, '').slice(0, 60) || '/')}</a>
            </div>
          </div>
        </td>
        <td class="py-4 text-center"><span class="badge-dr" style="${drStyle}">${drVal}</span></td>
        <td class="py-4 max-w-xs">
          <div class="flex items-center gap-2">
            <span class="cat-dot ${catDot}" title="${b.anchorCategory}"></span>
            <span class="text-slate-200 truncate" title="${escapeHtml(b.anchorText)}">${anchorDisplay}</span>
          </div>
          ${surround}
        </td>
        <td class="py-4 text-center">
          <span class="text-xs font-semibold px-2 py-0.5 rounded ${posClass}">${b.linkPosition}</span>
        </td>
        <td class="py-4 text-center">
          <span class="${relTag}">${b.rel}</span>
        </td>
        <td class="py-4 text-center">
          <span class="text-xs font-semibold px-2 py-0.5 rounded ${statusClass}">${b.status}</span>
        </td>
        <td class="py-4 text-right text-slate-500 text-xs pr-2 whitespace-nowrap">${lastSeen}</td>
      </tr>
    `;
  });
}

// ─────────────── Anchor Cloud tab ───────────────
async function loadAnchorCloud() {
  if (!CURRENT_DOMAIN) return;
  show('anchorCloudLoading');
  const QUERY = `
    query($name: String!) {
      domain(name: $name) {
        anchorCloud(limit: 80) {
          anchorText anchorCategory nBacklinks nReferringDomains
        }
      }
    }`;
  try {
    const data = await gql(QUERY, { name: CURRENT_DOMAIN });
    hide('anchorCloudLoading');
    const cloud = document.getElementById('anchorCloud');
    cloud.innerHTML = '';
    const buckets = data.domain?.anchorCloud || [];
    if (buckets.length === 0) {
      cloud.innerHTML = '<p class="text-slate-500 text-sm py-4">No anchor data yet — backlink-detail-builder is still indexing.</p>';
      return;
    }
    const maxRefs = Math.max(...buckets.map(b => b.nReferringDomains));
    buckets.forEach(b => {
      const ratio = b.nReferringDomains / maxRefs;
      const size = 0.85 + ratio * 0.6; // 0.85x..1.45x
      const opacity = 0.4 + ratio * 0.6;
      const catDot = 'cat-' + b.anchorCategory;
      const text = b.anchorText || '(empty)';
      cloud.innerHTML += `
        <span class="anchor-bubble" style="font-size:${size}em;opacity:${opacity}" title="${escapeHtml(text)} — ${b.nReferringDomains} domains, ${b.nBacklinks} pages">
          <span class="cat-dot ${catDot}"></span>
          <span class="text-slate-200">${escapeHtml(text.length > 40 ? text.slice(0,40)+'…' : text)}</span>
          <span class="text-slate-500 text-xs">${fmt(b.nReferringDomains)}</span>
        </span>
      `;
    });
  } catch(e) {
    hide('anchorCloudLoading');
    document.getElementById('anchorCloud').innerHTML = `<p class="text-red-400 text-sm py-4">Failed to load: ${escapeHtml(e.message)}</p>`;
  }
}

// ─────────────── Positions & Quality tab ───────────────
async function loadPositionAndQuality() {
  if (!CURRENT_DOMAIN) return;
  const QUERY = `
    query($name: String!) {
      domain(name: $name) {
        backlinkStats {
          contentBacklinks navBacklinks footerBacklinks totalBacklinks
        }
        anchorCloud(limit: 500) {
          anchorCategory nReferringDomains
        }
      }
    }`;
  try {
    const data = await gql(QUERY, { name: CURRENT_DOMAIN });
    if (!data.domain) return;

    // Position bars (we only have content/nav/footer in stats — header/sidebar
    // are inferred from "other"). Total is the canonical denominator.
    const s = data.domain.backlinkStats || {};
    const total = s.totalBacklinks || 0;
    const positions = [
      { name: 'Content', value: s.contentBacklinks||0, cls: 'pos-content', desc: 'Editorial endorsement' },
      { name: 'Sidebar / Header / Other', value: Math.max(0, total - (s.contentBacklinks||0) - (s.navBacklinks||0) - (s.footerBacklinks||0)), cls: 'pos-sidebar', desc: 'Mixed signal' },
      { name: 'Navigation', value: s.navBacklinks||0, cls: 'pos-nav', desc: 'Site-wide template link — partial discount' },
      { name: 'Footer', value: s.footerBacklinks||0, cls: 'pos-footer', desc: 'Boilerplate — heavy discount by Google' },
    ];
    const posBars = document.getElementById('positionBars');
    posBars.innerHTML = positions.map(p => {
      const pct = total > 0 ? Math.round(p.value / total * 100) : 0;
      return `
        <div>
          <div class="flex justify-between items-baseline mb-1">
            <span class="text-sm font-semibold text-slate-200">${p.name}</span>
            <span class="text-xs text-slate-500">${fmt(p.value)} (${pct}%)</span>
          </div>
          <div class="w-full bg-white/5 rounded-full h-2 overflow-hidden">
            <div class="${p.cls} h-2 rounded-full" style="width: ${pct}%; transition: width 0.6s"></div>
          </div>
          <div class="text-xs text-slate-500 mt-1">${p.desc}</div>
        </div>
      `;
    }).join('');

    // Anchor category distribution from the full anchorCloud
    const categs = {};
    let categTotal = 0;
    (data.domain.anchorCloud || []).forEach(b => {
      categs[b.anchorCategory] = (categs[b.anchorCategory] || 0) + b.nReferringDomains;
      categTotal += b.nReferringDomains;
    });
    const ordered = ['branded','topical','naked','generic','image','empty']
      .filter(c => categs[c] > 0)
      .map(c => ({ name: c, value: categs[c], cls: 'cat-'+c }));
    const catBars = document.getElementById('anchorCategoryBars');
    if (categTotal === 0) {
      catBars.innerHTML = '<p class="text-slate-500 text-sm py-4">No anchor data yet — re-check shortly.</p>';
    } else {
      catBars.innerHTML = ordered.map(c => {
        const pct = Math.round(c.value / categTotal * 100);
        return `
          <div>
            <div class="flex justify-between items-baseline mb-1">
              <div class="flex items-center gap-2">
                <span class="cat-dot ${c.cls}"></span>
                <span class="text-sm font-semibold text-slate-200 capitalize">${c.name}</span>
              </div>
              <span class="text-xs text-slate-500">${fmt(c.value)} (${pct}%)</span>
            </div>
            <div class="w-full bg-white/5 rounded-full h-2 overflow-hidden">
              <div class="${c.cls} h-2 rounded-full" style="width: ${pct}%; transition: width 0.6s"></div>
            </div>
          </div>
        `;
      }).join('');
    }
  } catch(e) {
    console.warn('positions tab error:', e);
  }
}

// Wire up filter chip toggles
document.addEventListener('click', e => {
  if (e.target.classList && e.target.classList.contains('filter-chip')) {
    e.target.classList.toggle('active');
  }
});

function escapeHtml(s) {
  if (s == null) return '';
  return String(s)
    .replaceAll('&', '&amp;')
    .replaceAll('<', '&lt;')
    .replaceAll('>', '&gt;')
    .replaceAll('"', '&quot;')
    .replaceAll("'", '&#039;');
}

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>