PageSourceSearch

https://assetmarketcap.com/pricing

html assetmarketcap.com collected 2026-09-24 13:24:24 UTC 227,479 bytes, 5,088 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3<head>
4  <title>Pricing | AssetMarketCap.com</title>
5  <!-- Google tag (gtag.js) -->
vendor: 64 bytes, lines 5-6
5
6<script async src="https://www.googletagmanager.com/gtag/js?id=
6G-0Y08EV6WYH
vendor: 12 bytes, line 6
6"></script>
7<script>
8  
vendor: 134 bytes, lines 8-12
8window.dataLayer = window.dataLayer || [];
9  function gtag(){dataLayer.push(arguments);}
10  gtag('js', new Date());
11
12  gtag('config', '
12G-0Y08EV6WYH
vendor: 4 bytes, line 12
12');
13</script>
13
14
15<script>
16(function () {
17  const key = 'prefers_dark_mode';
18  // Server-side preference for logged-in users (null if not logged in or not set)
19  var serverDark = null;
20
21  var shouldBeDark;
22  if (serverDark !== null) {
23    // Use server preference and sync localStorage
24    shouldBeDark = serverDark;
25    localStorage.setItem(key, shouldBeDark ? '1' : '0');
26  } else {
27    // Fall back to localStorage
28    shouldBeDark = (localStorage.getItem(key) === '1');
29  }
30
31  if (shouldBeDark) document.documentElement.classList.add('dark-mode');
32})();
33</script>
33
34
35<meta charset="UTF-8">
36<meta name="viewport" content="width=980, viewport-fit=cover">
37
38<script>
39/* Native-app (Capacitor webview) detection - the bridge is injected at
40   documentStart, so this runs before first paint and the safe-area CSS
41   below applies immediately. iap.js also adds this class on /pro and
42   /account; this is the global copy. */
43(function () {
44  try {
45    if (window.Capacitor && Capacitor.isNativePlatform && Capacitor.isNativePlatform()) {
46      document.documentElement.classList.add('is-native-app');
47    }
48  } catch (e) { /* never block paint */ }
49})();
50</script>
50
51<style>
52  /* ── Safe-area handling inside the mobile apps ─────────────────────
53     The iOS webview is edge-to-edge (the native inset in
54     MainViewController.swift never worked: Capacitor 8 makes the webview
55     the root view, so its safe-area constraints are self-referential
56     no-ops). Fix is web-side: viewport-fit=cover (meta above) activates
57     env(safe-area-inset-*), then we pad. In desktop/mobile browsers and
58     in the Android app the insets are 0, so all of this no-ops.
59     The bottom tab bar (mobile_nav.html) already carries its own
60     env(safe-area-inset-bottom) padding. */
61  html.is-native-app body {
62    padding-top: env(safe-area-inset-top, 0px);
63  }
64  /* No third-party sign-in inside the apps. Offering Google or Facebook
65     login in the iOS app obliges us to also offer Sign in with Apple
66     (App Store guideline 4.8), and Google blocks OAuth in embedded
67     webviews anyway. Email and password sign-in is unaffected, and the
68     website keeps social login. */
69  html.is-native-app .social-auth {
70    display: none !important;
71  }
72  /* Opaque strip behind the status bar so scrolled content doesn't
73     collide with the clock/battery text. Sits under the auth modal
74     (z-index 99999) but over page content. */
75  html.is-native-app body::before {
76    content: "";
77    position: fixed;
78    top: 0; left: 0; right: 0;
79    height: env(safe-area-inset-top, 0px);
80    background: var(--color-surface, #ffffff);
81    z-index: 99990;
82    pointer-events: none;
83  }
84  /* Full-screen mobile drawer opens from the very top - pad its inner
85     content down too. */
86  html.is-native-app .m-drawer {
87    padding-top: env(safe-area-inset-top, 0px);
88  }
89</style>
90
91<script>
92/* Early-init: density + sidebar prefs before first paint. Narrow viewports
93   default to Comfortable until the user picks a density (see table.js). */
94(function () {
95  var NARROW_DENSITY_MAX = 1100; /* matches global.css sidebar/mobile breakpoint */
96  window.__amcNARROW_DENSITY_MAX = NARROW_DENSITY_MAX;
97  window.__amcDensityUserHasChosen = function () {
98    try { return localStorage.getItem('table_density') !== null; } catch (e) { return true; }
99  };
100  window.__amcIsNarrowViewport = function () {
101    try {
102      if (window.matchMedia && window.matchMedia('(max-width: ' + NARROW_DENSITY_MAX + 'px)').matches) {
103        return true;
104      }
105    } catch (e) { /* ignore */ }
106    return window.innerWidth <= NARROW_DENSITY_MAX;
107  };
108  window.__amcApplyNarrowDensity = function () {
109    if (window.__amcDensityUserHasChosen()) return;
110    if (window.__amcIsNarrowViewport()) {
111      document.documentElement.setAttribute('data-density', 'comfortable');
112    } else {
113      document.documentElement.removeAttribute('data-density');
114    }
115  };
116  try {
117    var d = localStorage.getItem('table_density');
118    if (d === 'compact' || d === 'comfortable') {
119      document.documentElement.setAttribute('data-density', d);
120    } else if (d === 'normal') {
121      document.documentElement.removeAttribute('data-density');
122    } else {
123      window.__amcApplyNarrowDensity();
124    }
125    if (localStorage.getItem('sidebar_collapsed') === '1') {
126      document.documentElement.classList.add('sidebar-collapsed');
127    }
128  } catch (e) { /* localStorage blocked — silently fall back to defaults */ }
129  function syncNarrowDensityAfterLayout() {
130    if (window.__amcApplyNarrowDensity) window.__amcApplyNarrowDensity();
131  }
132  if (document.readyState === 'loading') {
133    document.addEventListener('DOMContentLoaded', syncNarrowDensityAfterLayout);
134  } else {
135    syncNarrowDensityAfterLayout();
136  }
137})();
138</script>
138
139
140<script>
141/* Back-to-top button — injects a fixed-position circle into <body>
142   once the DOM is ready. Becomes visible after the user has scrolled
143   ~300px and smooth-scrolls back to the top on click. */
144(function () {
145  function init() {
146    if (document.getElementById('backToTop')) return;
147    var btn = document.createElement('button');
148    btn.id = 'backToTop';
149    btn.type = 'button';
150    btn.setAttribute('aria-label', 'Back to top');
151    btn.title = 'Back to top';
152    btn.innerHTML =
153      '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" ' +
154        'stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
155        '<line x1="12" y1="19" x2="12" y2="5"/>' +
156        '<polyline points="5 12 12 5 19 12"/>' +
157      '</svg>';
158    document.body.appendChild(btn);
159    btn.addEventListener('click', function () {
160      window.scrollTo({ top: 0, behavior: 'smooth' });
161    });
162    var threshold = 300;
163    function onScroll() {
164      var y = window.pageYOffset || document.documentElement.scrollTop || 0;
165      btn.classList.toggle('is-visible', y > threshold);
166    }
167    window.addEventListener('scroll', onScroll, { passive: true });
168    onScroll();
169  }
170  if (document.readyState === 'loading') {
171    document.addEventListener('DOMContentLoaded', init);
172  } else {
173    init();
174  }
175})();
176</script>
176
177
178
179<script>
180  // Single-flight pre-fetch of the basic leaderboard JSON.
181  // Both the flippenings ticker and the main table need this 60KB
182  // payload; wrapping it once here means a single network request
183  // is in flight before DataTables even loads from CDN. Both
184  // consumers await window.__basicDataPromise.
185  window.__basicDataPromise = fetch("/data/basic/daily.json", { credentials: 'same-origin' })
186    .then(function (r) { return r.ok ? r.json() : null; })
187    .then(function (json) {
188      if (json && window.__amcApplyNarrowDensity) window.__amcApplyNarrowDensity();
189      return json;
190    })
191    .catch(function () { return null; });
192
193  // Always-live basic snapshot. In Time-Machine mode the table (above) loads a
194  // historical archive, but the header totals, H2 narrative, dominance bar and
195  // the Market Overview / Highlights sidebar must keep showing CURRENT data.
196  // In live mode this is the same payload, so just alias it (no extra fetch).
197  
198  window.__liveBasicPromise = window.__basicDataPromise;
199  
200</script>
200
201
202<meta name="robots" content="index, follow">
203
204
205
206  <meta name="description" content="Track 35,000+ assets ranked by market cap. Live prices, charts and data for stocks, crypto, commodities and currencies." />
207
208  <meta property="og:type" content="website" />
209  <meta property="og:site_name" content="AssetMarketCap"/>
210  <meta property="og:url" content="https://assetmarketcap.com/" />
211  <meta property="og:title" content="Assets Ranked by Market Cap | AssetMarketCap" />
212  <meta property="og:description" content="Track 35,000+ assets ranked by market capitalization. Live prices, charts and data for stocks, crypto, commodities and currencies." />
213  <meta property="og:image" content="https://assetmarketcap.com/static/preview.jpg" />
214  <meta property="og:image:width" content="1200" />
215  <meta property="og:image:height" content="630" />
216
217  <meta name="twitter:card" content="summary_large_image" />
218  <meta name="twitter:site" content="@assetmarketcap" />
219  <meta name="twitter:title" content="Assets Ranked by Market Cap | AssetMarketCap" />
220  <meta name="twitter:description" content="Track 35,000+ assets ranked by market capitalization. Live prices, charts and data for stocks, crypto, commodities and currencies." />
221  <meta name="twitter:image" content="https://assetmarketcap.com/static/preview.jpg" />
222
223
224<!-- Apple touch icon -->
225<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png?v=3">
226
227<meta http-equiv='cache-control' content='no-cache'>
228<meta http-equiv='expires' content='0'>
229<meta http-equiv='pragma' content='no-cache'>
230
231<script type="application/ld+json">
232{
233  "@context": "https://schema.org",
234  "@type": "WebSite",
235  "name": "AssetMarketCap",
236  "alternateName": "Asset Market Cap",
237  "url": "https://assetmarketcap.com/",
238  "description": "Track 35,000+ assets ranked by market capitalization. Live prices, charts and data for stocks, crypto, commodities and currencies.",
239  "potentialAction": {
240    "@type": "SearchAction",
241    "target": "https://assetmarketcap.com/?q={search_term_string}",
242    "query-input": "required name=search_term_string"
243  }
244}
245</script>
vendor: 1 bytes, line 245
245
246<script type="application/ld+json">
247{
248  "@context": "https://schema.org",
249  "@type": "Organization",
250  "name": "AssetMarketCap",
251  "url": "https://assetmarketcap.com",
252  "logo": "https://assetmarketcap.com/static/logo-dark.png",
253  "sameAs": [
254    "https://x.com/assetmarketcap",
255    "https://www.youtube.com/@assetmarketcap",
256    "https://www.facebook.com/assetmarketcap",
257    "https://instagram.com/assetmarketcap",
258    "https://discord.gg/KKDAMNbStQ",
259    "https://reddit.com/r/assetmarketcap"
260  ]
261}
262</script>
vendor: 1 bytes, line 262
262
263<script type="application/ld+json">
264{
265  "@context": "https://schema.org",
266  "@type": "SiteNavigationElement",
267  "name": ["News", "Learn", "Deals", "Community", "Merch", "Newsletter", "Pricing", "Pro", "API", "Support"],
268  "url": [
269    "https://assetmarketcap.com/news",
270    "https://assetmarketcap.com/learn",
271    "https://assetmarketcap.com/deals",
272    "https://discord.gg/KKDAMNbStQ",
273    "https://merch.assetmarketcap.com",
274    "https://assetmarketcap.com/newsletter",
275    "https://assetmarketcap.com/pricing",
276    "https://assetmarketcap.com/pro",
277    "https://assetmarketcap.com/api-info",
278    "https://assetmarketcap.com/support"
279  ]
280}
281</script>
281
282
283<!------ Google Fonts ---------->
284<link rel="preconnect" href="https://fonts.googleapis.com">
285<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
286<link rel="preconnect" href="https://cdn.datatables.net" crossorigin>
287<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
288<link rel="preload" href="https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap" as="style">
289<link href="https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap" rel="stylesheet">
290
291<!------ Favicon & icons ---------->
292<link rel="icon" type="image/x-icon" href="/favicon.ico?v=2">
293<link rel="icon" type="image/png" sizes="192x192" href="/static/favicon-192.png?v=3">
294<link rel="canonical" href="https://assetmarketcap.com/pricing" />
295
296
297
298<!------ for the footer ---------->
299<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
300<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
301
302
303
304<!-- DataTables CSS -->
305<link rel="stylesheet" href="https://cdn.datatables.net/1.13.11/css/jquery.dataTables.min.css">
306<!------ CSS - must come after Bootstrap to avoid overrides ---------->
307<link rel="stylesheet" href="/static/css/global.css?v=2026062201">
308
309<!-- Responsive extension -->
310<link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.5.0/css/responsive.dataTables.min.css">
311
312<!-- ColReorder extension (column drag-reorder) -->
313<link rel="stylesheet" href="https://cdn.datatables.net/colreorder/1.7.0/css/colReorder.dataTables.min.css">
314
315<script defer src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
vendor: 1 bytes, line 315
315
316<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js"></script>
vendor: 1 bytes, line 316
316
317<script defer src="https://cdn.jsdelivr.net/npm/luxon@3/build/global/luxon.min.js"></script>
vendor: 1 bytes, line 317
317
318<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chartjs-adapter-luxon.umd.min.js"></script>
318
319
320
321
322
323
324<!-- Trustpilot invitation script (integration key registered site-wide,
325     2026-07-22). Loads async from invitejs.trustpilot.com; used to send
326     review invitations via tp('trigger', ...) events. -->
327<script>
328  (function(w,d,s,r,n){w.TrustpilotObject=n;w[n]=w[n]||function(){(w[n].q=w[n].q||[]).push(arguments)};
329      a=d.createElement(s);a.async=1;a.src=r;a.type='text/java'+s;f=d.getElementsByTagName(s)[0];
330      f.parentNode.insertBefore(a,f)})(window,document,'script', 'https://invitejs.trustpilot.com/tp.min.js', 'tp');
331      tp('register', 'HfViG6gtA0OwevMi');
332</script>
332
333
334<!-- TrustBox script (widget bootstrap - per TP docs this belongs in <head>;
335     the Review Collector TrustBox on the homepage banner depends on it) -->
336<script type="text/javascript" src="//widget.trustpilot.com/bootstrap/v5/tp.widget.bootstrap.min.js" async></script>
336
337<!-- End TrustBox script -->
338
339<!-- Native in-app purchases. No-ops in a normal browser; inside the Capacitor
340     webview it hides the web billing UI and replaces the Stripe checkout forms
341     with the App Store / Play Store purchase sheet. Loaded globally because the
342     subscribe forms appear on /pro, /pricing, /account AND in the auth modal
343     that header.html includes on every page (App Store guideline 3.1.1). -->
344<script src="/static/js/iap.js?v=3" defer></script>
344
345  
345<script type="application/ld+json">
346  {
347    "@context": "https://schema.org",
348    "@type": "BreadcrumbList",
349    "itemListElement": [
350      { "@type": "ListItem", "position": 1, "name": "Home", "item": "https://assetmarketcap.com/" },
351      { "@type": "ListItem", "position": 2, "name": "Pricing", "item": "https://assetmarketcap.com/pricing" }
352    ]
353  }
354  </script>
354
355  <meta name="description" content="AssetMarketCap pricing - Free, Pro and Pro Plus plans. The full 35,000+ asset dataset is free. Upgrade for ad-free browsing, premium news, the Net Worth Tracker with live prices, Time Machine archive back to 2010, JSON/CSV downloads, and unlimited tools.">
356  <style>
357    /* ============================================================
358       PRICING 2026 - Apple monochrome (shares token system with /pro)
359       ============================================================ */
360    .x-page{
361      --x-bg:           #ffffff;
362      --x-bg-soft:      #f5f5f7;
363      --x-bg-card:      #ffffff;
364
365      --x-text:         #1d1d1f;
366      --x-text-muted:   #6e6e73;
367      --x-text-faint:   #86868b;
368
369      --x-border:       rgba(0,0,0,0.10);
370      --x-border-soft:  rgba(0,0,0,0.06);
371      --x-divider:      rgba(0,0,0,0.10);
372
373      --x-cta-fill:     #1d1d1f;
374      --x-cta-fill-h:   #000000;
375      --x-cta-on:       #ffffff;
376
377      background: var(--x-bg);
378      color: var(--x-text);
379      font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Nunito", "Helvetica Neue", Arial, sans-serif;
380      -webkit-font-smoothing: antialiased;
381      -moz-osx-font-smoothing: grayscale;
382    }
383    html.dark-mode .x-page{
384      --x-bg:           #000000;
385      --x-bg-soft:      #161617;
386      --x-bg-card:      #1d1d1f;
387
388      --x-text:         #f5f5f7;
389      --x-text-muted:   #a1a1a6;
390      --x-text-faint:   #86868b;
391
392      --x-border:       rgba(255,255,255,0.12);
393      --x-border-soft:  rgba(255,255,255,0.08);
394      --x-divider:      rgba(255,255,255,0.12);
395
396      --x-cta-fill:     #f5f5f7;
397      --x-cta-fill-h:   #ffffff;
398      --x-cta-on:       #1d1d1f;
399    }
400    .x-page *{ box-sizing: border-box; }
401    .x-wrap{ max-width: 1180px; margin: 0 auto; padding: 0 22px; }
402    .x-band{ background: var(--x-bg); }
403    .x-band--soft{ background: var(--x-bg-soft); }
404
405    /* Typography ----------------------------------------- */
406    .x-eyebrow{ text-align: center; font-size: 0.82rem; font-weight: 600; color: var(--x-text-muted); margin: 0 0 14px; }
407    .x-eyebrow--left{ text-align: left; }
408    .x-eyebrow strong{ color: var(--x-text); font-weight: 600; }
409    .x-h1{
410      text-align: center; max-width: 920px; margin: 0 auto 18px;
411      font-size: clamp(2.6rem, 6vw, 4.6rem); font-weight: 600;
412      letter-spacing: -0.035em; line-height: 1.04; color: var(--x-text);
413    }
414    .x-h2{
415      text-align: center; max-width: 800px; margin: 0 auto 14px;
416      font-size: clamp(2rem, 4vw, 3.2rem); font-weight: 600;
417      letter-spacing: -0.025em; line-height: 1.08; color: var(--x-text);
418    }
419    .x-lede{
420      text-align: center; max-width: 660px; margin: 0 auto 32px;
421      font-size: clamp(1.08rem, 1.5vw, 1.28rem); line-height: 1.45;
422      color: var(--x-text-muted);
423    }
424    .x-sub{
425      text-align: center; color: var(--x-text-muted);
426      max-width: 640px; margin: 0 auto 48px;
427      font-size: 1.08rem; line-height: 1.5;
428    }
429    .x-sec{ padding: 110px 0; }
430    .x-sec--md{ padding: 80px 0; }
431    .x-hero{ text-align: center; padding: 120px 0 50px; }
432    @media (max-width: 720px){
433      .x-sec{ padding: 70px 0; }
434      .x-hero{ padding: 80px 0 30px; }
435    }
436
437    /* CTAs ----------------------------------------------- */
438    .x-cta{
439      display: inline-flex; align-items: center; justify-content: center; gap: 6px;
440      padding: 12px 22px; border-radius: 980px;
441      border: 1px solid var(--x-cta-fill); background: var(--x-cta-fill);
442      color: var(--x-cta-on);
443      font: 600 1rem/1.2 inherit; letter-spacing: -0.005em;
444      cursor: pointer; text-decoration: none;
445      transition: background 0.18s, border-color 0.18s, color 0.18s;
446      white-space: nowrap;
447    }
448    .x-cta:hover{ background: var(--x-cta-fill-h); border-color: var(--x-cta-fill-h); color: var(--x-cta-on); }
449    .x-cta--lg{ padding: 14px 28px; font-size: 1.06rem; }
450    .x-cta--ghost{ background: transparent; border-color: var(--x-text); color: var(--x-text); }
451    .x-cta--ghost:hover{ background: var(--x-text); color: var(--x-bg); border-color: var(--x-text); }
452    .x-link{
453      display: inline-flex; align-items: center; gap: 4px;
454      color: var(--x-text); font: 600 1rem/1 inherit;
455      text-decoration: none; padding: 12px 0; letter-spacing: -0.005em;
456    }
457    .x-link::after{ content: "\203A"; font-weight: 400; font-size: 1.15em; transition: transform 0.18s; display: inline-block; }
458    .x-link:hover::after{ transform: translateX(3px); }
459
460    /* Billing toggle ------------------------------------- */
461    .x-bill{
462      display: inline-flex; align-items: center;
463      padding: 4px; border-radius: 999px;
464      background: var(--x-bg-card);
465      border: 1px solid var(--x-border-soft);
466      position: relative;
467    }
468    .x-bill button{
469      appearance: none; border: 0; background: transparent;
470      color: var(--x-text-muted);
471      font: 600 0.9rem/1 inherit; letter-spacing: -0.005em;
472      padding: 10px 22px; border-radius: 999px; cursor: pointer;
473      transition: color 0.2s;
474      position: relative; z-index: 2;
475    }
476    .x-bill button.is-on{ color: var(--x-cta-on); }
477    .x-bill-thumb{
478      position: absolute; top: 4px; bottom: 4px;
479      border-radius: 999px;
480      background: var(--x-cta-fill);
481      transition: left 0.24s cubic-bezier(.5,1.4,.4,1), width 0.24s cubic-bezier(.5,1.4,.4,1);
482      z-index: 1;
483    }
484    .x-bill-save{ color: var(--x-text-muted); font-size: 0.78rem; font-weight: 500; }
485
486    /* Plan cards (3-up) ---------------------------------- */
487    .x-plans{ display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; max-width: 1100px; margin: 0 auto; }
488    @media (max-width: 980px){ .x-plans{ grid-template-columns: 1fr; max-width: 460px; } }
489    .x-plan{
490      position: relative; padding: 36px 32px;
491      border-radius: 22px;
492      background: var(--x-bg-card);
493      border: 1px solid var(--x-border);
494      display: flex; flex-direction: column;
495    }
496    .x-plan--featured{ border-color: var(--x-text); border-width: 2px; padding: 35px 31px; }
497    .x-plan-tag{
498      position: absolute; top: -14px; left: 24px;
499      padding: 5px 12px; border-radius: 999px;
500      background: var(--x-cta-fill); color: var(--x-cta-on);
501      font: 600 0.72rem/1 inherit; letter-spacing: 0.04em; text-transform: uppercase;
502      white-space: nowrap;
503    }
504    .x-plan-name{ font-size: 0.82rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--x-text-faint); margin-bottom: 14px; }
505    .x-plan-price{ display: flex; align-items: baseline; gap: 3px; margin-bottom: 8px; min-height: 56px; }
506    .x-plan-cur{ font-size: 1.4rem; font-weight: 600; color: var(--x-text); align-self: flex-start; margin-top: 8px; }
507    .x-plan-amt{ font-size: clamp(2.8rem, 4.5vw, 3.4rem); font-weight: 600; letter-spacing: -0.025em; line-height: 1; color: var(--x-text); }
508    .x-plan-per{ font-size: 1rem; color: var(--x-text-muted); margin-left: 6px; }
509    .x-plan-tag-line{ color: var(--x-text-muted); font-size: 0.96rem; line-height: 1.5; margin: 6px 0 24px 0; min-height: 48px; }
510    .x-plan-feats{ list-style: none; padding: 0; margin: 0 0 28px 0; display: flex; flex-direction: column; gap: 12px; font-size: 0.95rem; }
511    .x-plan-feats li{ display: flex; gap: 11px; align-items: flex-start; line-height: 1.45; color: var(--x-text); }
512    .x-plan-feats li::before{
513      content: ""; flex: 0 0 16px; height: 16px; margin-top: 2px;
514      background: var(--x-text);
515      mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>") center / 80% no-repeat;
516      -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>") center / 80% no-repeat;
517    }
518    .x-plan-cta-wrap{ margin-top: auto; }
519    .x-plan-cta-wrap .x-cta{ width: 100%; }
520
521    /* Personas ------------------------------------------- */
522    .x-personas{ display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--x-divider); border: 1px solid var(--x-divider); border-radius: 18px; overflow: hidden; }
523    @media (max-width: 920px){ .x-personas{ grid-template-columns: 1fr; } }
524    .x-persona{ padding: 32px 28px; background: var(--x-bg); }
525    .x-persona-ico{ width: 40px; height: 40px; margin-bottom: 22px; color: var(--x-text); }
526    .x-persona-ico svg{ width: 100%; height: 100%; display: block; }
527    .x-persona-label{ font-size: 0.75rem; font-weight: 600; letter-spacing: 0.10em; text-transform: uppercase; color: var(--x-text-muted); margin-bottom: 6px; }
528    .x-persona h3{ margin: 0 0 10px 0; font-size: 1.22rem; font-weight: 600; color: var(--x-text); letter-spacing: -0.005em; }
529    .x-persona p{ margin: 0 0 16px 0; color: var(--x-text-muted); font-size: 0.98rem; line-height: 1.5; }
530
531    /* Compare table -------------------------------------- */
532    .x-compare{
533      border-radius: 18px;
534      background: var(--x-bg-card);
535      border: 1px solid var(--x-border);
536      overflow: hidden;
537    }
538    .x-ct{ width: 100%; border-collapse: collapse; font-size: 0.98rem; color: var(--x-text); }
539    .x-ct thead th{
540      padding: 24px 16px;
541      font: 600 0.78rem/1 inherit; text-transform: uppercase; letter-spacing: 0.08em;
542      color: var(--x-text-muted); text-align: center;
543      border-bottom: 1px solid var(--x-divider);
544      background: var(--x-bg-soft);
545    }
546    .x-ct thead th:first-child{ text-align: left; padding-left: 28px; color: var(--x-text); }
547    .x-ct thead th.is-feat{ color: var(--x-text); position: relative; }
548    .x-ct thead th.is-feat::after{
549      content: ""; position: absolute; bottom: -1px; left: 0; right: 0; height: 2px;
550      background: var(--x-text);
551    }
552    .x-ct td{
553      padding: 16px;
554      text-align: center;
555      border-bottom: 1px solid var(--x-border-soft);
556    }
557    .x-ct td:first-child{ text-align: left; padding-left: 28px; font-weight: 500; }
558    .x-ct td.is-feat{ background: var(--x-bg-soft); }
559    .x-ct tbody tr:last-child td{ border-bottom: none; }
560    .x-tick{
561      display: inline-flex; width: 22px; height: 22px;
562      align-items: center; justify-content: center;
563      color: var(--x-text);
564    }
565    .x-tick svg{ width: 18px; height: 18px; display: block; }
566    .x-cross{ color: var(--x-text-faint); font-size: 0.95rem; }
567    .x-pill-cell{ color: var(--x-text-muted); font-size: 0.92rem; }
568    .x-pill-cell--good{
569      display: inline-block; padding: 4px 12px; border-radius: 999px;
570      background: var(--x-cta-fill); color: var(--x-cta-on);
571      font: 600 0.84rem/1.4 inherit;
572    }
573    @media (max-width: 760px){
574      .x-ct{ font-size: 0.84rem; }
575      .x-ct thead th, .x-ct td{ padding: 12px 8px; }
576      .x-ct thead th:first-child, .x-ct td:first-child{ padding-left: 14px; }
577    }
578
579    /* FAQ ------------------------------------------------- */
580    .x-faq{ max-width: 820px; margin: 0 auto; border-top: 1px solid var(--x-divider); }
581    .x-faq-item{ border-bottom: 1px solid var(--x-divider); }
582    .x-faq-item summary{
583      list-style: none; cursor: pointer;
584      padding: 26px 52px 26px 4px; position: relative;
585      font: 600 1.12rem/1.3 inherit;
586      color: var(--x-text);
587      letter-spacing: -0.005em;
588    }
589    .x-faq-item summary::-webkit-details-marker{ display: none; }
590    .x-faq-item summary i.x-faq-icon{
591      position: absolute; right: 8px; top: 50%; width: 14px; height: 14px;
592      margin-top: -7px; display: block; pointer-events: none;
593    }
594    .x-faq-item summary i.x-faq-icon::before,
595    .x-faq-item summary i.x-faq-icon::after{
596      content: ""; position: absolute; left: 0; top: 50%; width: 14px; height: 1.5px;
597      margin-top: -0.75px; background: var(--x-text); border-radius: 1px;
598      transition: opacity 0.2s, transform 0.2s;
599    }
600    .x-faq-item summary i.x-faq-icon::after{ transform: rotate(90deg); }
601    .x-faq-item[open] summary i.x-faq-icon::after{ transform: rotate(0deg); opacity: 0; }
602    .x-faq-body{ padding: 0 52px 28px 4px; color: var(--x-text-muted); font-size: 1rem; line-height: 1.55; }
603
604    /* Final ---------------------------------------------- */
605    .x-final{ max-width: 880px; margin: 0 auto; padding: 100px 30px 110px; text-align: center; }
606    .x-final h2{ font-size: clamp(2.2rem, 4.5vw, 3.4rem); font-weight: 600; letter-spacing: -0.03em; margin: 0 0 18px 0; line-height: 1.05; color: var(--x-text); }
607    .x-final p{ color: var(--x-text-muted); font-size: 1.18rem; line-height: 1.5; max-width: 540px; margin: 0 auto 36px; }
608    .x-final-cta{ display: inline-flex; gap: 20px; flex-wrap: wrap; justify-content: center; align-items: center; }
609    .x-disclaimer{ max-width: 820px; margin: 0 auto; padding: 0 22px 80px; color: var(--x-text-faint); font-size: 0.82rem; line-height: 1.55; text-align: center; }
610  </style>
611</head>
612<body>
613  
614
615
616<div class="top-bar">
617  <div class="col-lg-10 col-lg-offset-1 top-bar-inner">
618
619    
620    <div class="upper-header stats-strip top-bar-stats">
621      <div class="upper-categories">
622        <div class="upper-block">
623          <a href="#" class="category-link" data-table-category="">
624            total assets (<span id="noOfAssets_All">38,592</span>):
625            <span class="marketcap-value" id="MarketCaps_All">$1,083.80T</span>
626          </a>
627        </div>
628        <div class="upper-block">
629          
630          <a href="#" class="category-link" data-table-category="real-estate">
631            real estate:
632            <span class="marketcap-value" id="MarketCaps_RealEstate">$448.91T</span>
633          </a>
634        </div>
635        <div class="upper-block">
636          <a href="#" class="category-link" data-table-category="Commodity">
637            commodities (<span id="noOfAssets_Comms">7</span>):
638            <span class="marketcap-value" id="MarketCaps_Comms">$225.33T</span>
639          </a>
640        </div>
641        <div class="upper-block">
642          <a href="#" class="category-link" data-table-category="Company">
643            companies (<span id="noOfAssets_Companies">20,655</span>):
644            <span class="marketcap-value" id="MarketCaps_Companies">$149.86T</span>
645          </a>
646        </div>
647        <div class="upper-block">
648          <a href="#" class="category-link" data-table-category="Currency">
649            currencies (<span id="noOfAssets_Currs">113</span>):
650            <span class="marketcap-value" id="MarketCaps_Currs">$139.77T</span>
651          </a>
652        </div>
653        <div class="upper-block">
654          <a href="#" class="category-link" data-table-category="Bond">
655            govt bonds (<span id="noOfAssets_Bonds">177</span>):
656            <span class="marketcap-value" id="MarketCaps_Bonds">$116.98T</span>
657          </a>
658        </div>
659        <div class="upper-block">
660          <a href="#" class="category-link" data-table-category="Cryptocurrency">
661            cryptos (<span id="noOfAssets_Cryptos">12,154</span>):
662            <span class="marketcap-value" id="MarketCaps_Cryptos">$2.95T</span>
663          </a>
664        </div>
665        <span class="stats-scroll-hint" aria-hidden="true">&#8250;</span>
666      </div>
667    </div>
668    
668<script>
669    (function () {
670      // Toggle a right-edge chevron on the assets strip whenever there's more
671      // content to scroll to (and hide it once scrolled to the end).
672      var strip = document.querySelector('.top-bar-stats');
673      if (!strip) return;
674      function sync() {
675        var more = strip.scrollWidth - strip.clientWidth - strip.scrollLeft > 4;
676        strip.classList.toggle('can-scroll-right', more);
677      }
678      strip.addEventListener('scroll', sync, { passive: true });
679      window.addEventListener('resize', sync);
680      // Re-check after the market-cap numbers fill in (they load async).
681      sync();
682      setTimeout(sync, 800);
683      setTimeout(sync, 2500);
684    })();
685    </script>
685
686
687    
688    <div class="top-bar-actions">
689
690      
691      <a href="/advertise" class="nav-pill nav-pill--ghost nav-advertise-pill" title="Advertise with us">
692        <svg class="nav-pill-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
693          <path d="m3 11 18-5v12L3 14v-3z"/>
694          <path d="M11.6 16.8a3 3 0 1 1-5.8-1.6"/>
695        </svg>
696        <span class="nav-pill-label">Advertise</span>
697      </a>
698
699      
700      <div class="unit-dropdown nav-currency">
701        <label for="unit-select" class="sr-only">Currency</label>
702        <select id="unit-select" required class="unit-select">
703          <option value="USD" selected>USD ($)</option>
704          <option value="GOLD">Gold (oz)</option>
705          <option value="BTC">Bitcoin (₿)</option>
706          <option value="SATS">Bitcoin (sats)</option>
707          
708          <option value="SILVER" hidden disabled>Silver (oz)</option>
709          <option value="mBTC"   hidden disabled>mBitcoin (m₿)</option>
710          <option value="uBTC"   hidden disabled>μBitcoin (μ₿)</option>
711        </select>
712        <img id="unit-logo"
713             src="/static/icons/flags/us.png"
714             alt="Selected currency icon"
715             class="unit-logo-icon">
716      </div>
717
718      
719      <div class="nav-dropdown nav-help-dropdown">
720        <button type="button" class="nav-icon-btn nav-dropdown-trigger nav-help-trigger"
721                aria-haspopup="true" aria-expanded="false" aria-label="Help">
722          <i class="fa-solid fa-question"></i>
723        </button>
724        <ul class="nav-dropdown-menu nav-help-menu" role="menu">
725          <li role="none"><a href="/faqs" role="menuitem"><i class="fa-regular fa-circle-question"></i> FAQs</a></li>
726          <li role="none"><a href="/support" role="menuitem"><i class="fa-regular fa-life-ring"></i> Support</a></li>
727        </ul>
728      </div>
729
730      
731      <div class="nav-dropdown nav-mobile-dropdown">
732        <button type="button" id="openAppPopup" class="nav-icon-btn nav-dropdown-trigger js-open-app-popup nav-mobile-trigger"
733                aria-haspopup="true" aria-expanded="false" aria-label="Get the app">
734          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
735            <rect x="5" y="2" width="14" height="20" rx="2.5" ry="2.5"/>
736            <line x1="12" y1="18" x2="12" y2="18"/>
737          </svg>
738        </button>
739        <div class="nav-dropdown-menu nav-mobile-menu" role="menu" aria-label="Scan to download the app">
740          <div class="nav-mobile-title">Scan to get the app</div>
741          <img class="nav-mobile-qr"
742               src="https://api.qrserver.com/v1/create-qr-code/?size=180x180&margin=0&data=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Dcom.assetmarketcap.app"
743               alt="Google Play QR code" width="160" height="160" loading="lazy">
744          <div class="nav-mobile-sub">Android available now. iOS coming soon.</div>
745        </div>
746      </div>
747
748      
749      <button id="darkModeBtn" class="dark-mode-btn nav-icon-btn" type="button" aria-label="Toggle dark mode">
750        <svg class="dm-icon dm-icon-moon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
751             fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
752          <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
753        </svg>
754        <svg class="dm-icon dm-icon-sun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
755             fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
756          <circle cx="12" cy="12" r="4.5"/>
757          <line x1="12" y1="2"   x2="12" y2="5"/>
758          <line x1="12" y1="19"  x2="12" y2="22"/>
759          <line x1="4.22" y1="4.22" x2="6.34" y2="6.34"/>
760          <line x1="17.66" y1="17.66" x2="19.78" y2="19.78"/>
761          <line x1="2"  y1="12"  x2="5"  y2="12"/>
762          <line x1="19" y1="12"  x2="22" y2="12"/>
763          <line x1="4.22" y1="19.78" x2="6.34" y2="17.66"/>
764          <line x1="17.66" y1="6.34" x2="19.78" y2="4.22"/>
765        </svg>
766      </button>
767
768      
769      <div class="nav-dropdown nav-settings-dropdown">
770        <button type="button" class="nav-icon-btn nav-dropdown-trigger nav-settings-trigger"
771                aria-haspopup="true" aria-expanded="false" aria-label="Settings">
772          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
773            <circle cx="12" cy="12" r="3"/>
774            <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 
7740 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
775          </svg>
776        </button>
777        <div class="nav-dropdown-menu nav-settings-menu" role="menu">
778          <div class="nav-settings-section">
779            <div class="nav-settings-label">Language</div>
780            <div class="nav-settings-row">
781              <select class="nav-settings-select" id="settingsLanguage" aria-label="Language">
782                <option value="en" selected>English</option>
783                <option value="es" disabled>Español (soon)</option>
784                <option value="de" disabled>Deutsch (soon)</option>
785                <option value="fr" disabled>Français (soon)</option>
786                <option value="zh" disabled>中文 (soon)</option>
787              </select>
788            </div>
789          </div>
790          <div class="nav-settings-divider"></div>
791          <div class="nav-settings-section">
792            <div class="nav-settings-label">Theme</div>
793            <div class="nav-theme-toggle" role="radiogroup" aria-label="Theme">
794              <button type="button" class="nav-theme-btn" data-theme="dark"   role="radio" aria-checked="false">
795                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
796                <span>Dark</span>
797              </button>
798              <button type="button" class="nav-theme-btn" data-theme="light"  role="radio" aria-checked="false">
799                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="4.5"/><line x1="12" y1="2" x2="12" y2="5"/><line x1="12" y1="19" x2="12" y2="22"/><line x1="4.22" y1="4.22" x2="6.34" y2="6.34"/><line x1="17.66" y1="17.66" x2="19.78" y2="19.78"/><line x1="2" y1="12" x2="5" y2="12"/><line x1="19" y1="12" x2="22" y2="12"/><line x1="4.22" y1="19.78" x2="6.34" y2="17.66"/><line x1="17.66" y1="6.34" x2="19.78" y2="4.22"/></svg>
800                <span>Light</span>
801              </button>
802              <button type="button" class="nav-theme-btn" data-theme="system" role="radio" aria-checked="true">
803                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
804                <span>System</span>
805              </button>
806            </div>
807          </div>
808        </div>
809      </div>
810
811      
812      <input id="darkModeToggle" type="checkbox" style="display:none;">
813
814      <div class="auth-links">
815        
816          <a href="/login"               id="openAuth"   class="auth-link auth-link-login">Log in</a>
817          <a href="/login?view=register" id="openSignup" class="auth-link auth-link-primary">Sign up</a>
818        
819      </div>
820
821    </div>
822  </div>
823</div>
824
825
826<div class="navbar-wrapper navbar-wrapper--compact">
827<nav class="navbar-header" aria-label="Main navigation">
828  <div class="col-lg-10 col-lg-offset-1">
829    <div class="navbar">
830
831      <a href="/" class="nav-logo" aria-label="AssetMarketCap home">
832        <picture>
833          <img src="/static/logo.png"      class="nav-logo-img nav-logo-img--light" width="180" height="30" alt="AssetMarketCap">
834          <img src="/static/logo-dark.png" class="nav-logo-img nav-logo-img--dark"  width="180" height="30" alt="" aria-hidden="true">
835        </picture>
836        
837      </a>
838
839      <div class="nav-left">
840        <ul>
841          <li class="nav-dropdown">
842            <a href="#" class="nav-dropdown-trigger" aria-haspopup="true" aria-expanded="false">Learn <i class="fa-solid fa-chevron-down nav-dropdown-caret" aria-hidden="true"></i></a>
843            <ul class="nav-dropdown-menu" role="menu">
844              <li role="none"><a href="/learn" role="menuitem">Education Articles</a></li>
845              <li role="none"><a href="/news" role="menuitem">Latest News</a></li>
846              <li role="none"><a href="/deals" role="menuitem">Deals</a></li>
847            </ul>
848          </li>
849          <li class="nav-dropdown">
850            <a href="#" class="nav-dropdown-trigger" aria-haspopup="true" aria-expanded="false">Products <i class="fa-solid fa-chevron-down nav-dropdown-caret" aria-hidden="true"></i></a>
851            <ul class="nav-dropdown-menu" role="menu">
852              <li role="none"><a href="/pro" role="menuitem">Pro</a></li>
853              <li role="none"><a href="https://merch.assetmarketcap.com" role="menuitem">Merchandise</a></li>
854              <li role="none"><a href="/advertise" role="menuitem">Advertise</a></li>
855            </ul>
856          </li>
857          <li class="nav-dropdown">
858            <a href="#" class="nav-dropdown-trigger" aria-haspopup="true" aria-expanded="false">Tools <i class="fa-solid fa-chevron-down nav-dropdown-caret" aria-hidden="true"></i></a>
859            <ul class="nav-dropdown-menu" role="menu">
860              <li role="none"><a href="/flippener" role="menuitem">Flippener Tool</a></li>
861              <li role="none"><a href="/compare" role="menuitem">Comparator Tool</a></li>
862              <li role="none"><a href="/net-worth-tracker" role="menuitem">Net-Worth Tracker</a></li>
863              
864              
865            </ul>
866          </li>
867          <li><a href="/pricing" id="openPricing">Pricing</a></li>
868          <li><a href="/api-info" id="openApi">API</a></li>
869        </ul>
870      </div>
871
872      
873      <div class="navbar-right">
874        <a href="/net-worth-tracker" class="nav-pill nav-pill--ghost" title="Net-Worth Tracker">
875          <svg class="nav-pill-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
876            <path d="M3 17l5-5 4 4 8-8"/>
877            <path d="M14 8h6v6"/>
878          </svg>
879          <span class="nav-pill-label">Net-Worth</span>
880        </a>
881
882        <a href="/login?view=register"
883           class="nav-pill nav-pill--ghost nav-favourites-trigger" title="Your favourites">
884          <svg class="nav-pill-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
885            <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>
886          </svg>
887          <span class="nav-pill-label">Favourites</span>
888        </a>
889
890        <form class="nav-search" role="search" action="/search" method="GET" autocomplete="off">
891          <i class="fa-solid fa-magnifying-glass nav-search-icon" aria-hidden="true"></i>
892          <input type="search" name="q" id="navGlobalSearch"
893                 class="nav-search-input"
894                 placeholder="Search assets, articles, news…"
895                 aria-label="Search">
896          <kbd class="nav-search-kbd" aria-hidden="true">/</kbd>
897        </form>
898
899      </div>
900
901    </div>
902  </div>
903</nav>
904</div>
905
906
907<!-- ═══════════════════════════════════════════════════════════
908     PRICING MODAL
909     ═══════════════════════════════════════════════════════════ -->
910<div id="pricingOverlay" class="auth-overlay" aria-hidden="true">
911  <div class="auth-backdrop" data-close-modal="pricingOverlay"></div>
912  <section class="auth-modal" role="dialog" aria-modal="true">
913    <button class="auth-close" data-close-modal="pricingOverlay" type="button" aria-label="Close">&times;</button>
914
915    <div class="auth-modal-left">
916      <div style="position:relative; z-index:1; display:flex; flex-direction:column; height:100%;">
917        <div class="auth-badge">Pro Plans</div>
918        <h2 class="auth-hero-title">Go beyond the data</h2>
919        <p class="auth-hero-copy">Everyone gets the full 35k+ dataset. Pro adds premium content and an ad-free experience.</p>
920        <div class="auth-feature-list">
921          <div class="auth-feature-item">Full 35,000+ asset dataset, free for everyone</div>
922          <div class="auth-feature-item">Education library on sign-up</div>
923          <div class="auth-feature-item">Filter by Country &amp; Sector on sign-up</div>
924          <div class="auth-feature-item">Ad-Free Mobile App Experience</div>
925          <div class="auth-feature-item">News Article Access</div>
926          <div class="auth-feature-item">Favourites, Flippener Tool &amp; Comparator Tool</div>
927        </div>
928      </div>
929    </div>
930
931    <div class="auth-modal-right">
932      
933        
934        <h3 class="auth-modal-heading">Pricing</h3>
935        <p class="auth-subtitle">The full 35k+ dataset is free for everyone. Sign up for favourites, or upgrade to Pro for premium features.</p>
936
937        <table class="auth-compare-table">
938          <thead>
939            <tr>
940              <th class="auth-compare-feature-col">Feature</th>
941              <th>Free</th>
942              <th>Sign Up</th>
943              <th>Pro</th>
944              <th class="auth-compare-highlight">Pro+</th>
945            </tr>
946          </thead>
947          <tbody>
948            <tr><td>35,000+ assets</td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
949            <tr><td>Education library</td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td>
949<span class="auth-compare-tick">&#10003;</span></td></tr>
950            <tr><td>Filter by Country &amp; Sector</td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
951            <tr><td>Ad-Free Mobile App Experience</td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
952            <tr><td>News Article Access</td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
953            <tr><td>Favourites</td><td class="auth-compare-text">3</td><td class="auth-compare-text">15</td><td class="auth-compare-text">50/mo</td><td class="auth-compare-text">Unlimited</td></tr>
954            <tr><td>Flippener Tool</td><td class="auth-compare-text">3</td><td class="auth-compare-text">10</td><td class="auth-compare-text">30/mo</td><td class="auth-compare-text">Unlimited</td></tr>
955            <tr><td>Comparator Tool</td><td class="auth-compare-text">3</td><td class="auth-compare-text">5</td><td class="auth-compare-text">15/mo</td><td class="auth-compare-text">Unlimited</td></tr>
956            <tr class="auth-compare-price-row">
957              <td>Price</td>
958              <td class="auth-compare-text">Free</td>
959              <td class="auth-compare-text">Sign Up</td>
960              <td class="auth-compare-text"><span data-info-pro-price>$3.99<small>/mo</small></span></td>
961              <td class="auth-compare-text"><span data-info-proplus-price>$9.99<small>/mo</small></span></td>
962            </tr>
963          </tbody>
964        </table>
965
966        <a href="/login?view=register" class="auth-submit" style="margin-top:18px; display:block; text-align:center; text-decoration:none;">Create a free account</a>
967        <div style="margin-top:12px; text-align:center;">
968          <a href="/login" class="auth-inline-link">Already have an account? Log in</a>
969        </div>
970      
971    </div>
972  </section>
973</div>
974
975
976<!-- ═══════════════════════════════════════════════════════════
977     API MODAL
978     ═══════════════════════════════════════════════════════════ -->
979<div id="apiOverlay" class="auth-overlay" aria-hidden="true">
980  <div class="auth-backdrop" data-close-modal="apiOverlay"></div>
981  <section class="auth-modal" role="dialog" aria-modal="true">
982    <button class="auth-close" data-close-modal="apiOverlay" type="button" aria-label="Close">&times;</button>
983
984    <div class="auth-modal-left">
985      <div style="position:relative; z-index:1; display:flex; flex-direction:column; height:100%;">
986        <div class="auth-badge">REST API</div>
987        <h2 class="auth-hero-title">Build with the API</h2>
988        <p class="auth-hero-copy">
989          Programmatic access for apps, scripts, and integrations. Every account includes a free API key with the top 100 assets. Upgrade for the full 35k+ dataset, fundamentals, and historical data.
990        </p>
991        <div class="auth-feature-list">
992          <div class="auth-feature-item">Top 100 assets free with every account</div>
993          <div class="auth-feature-item">Full 35,000+ asset dataset</div>
994          <div class="auth-feature-item">Individual asset fundamentals</div>
995          <div class="auth-feature-item">Historical market cap &amp; price data</div>
996          <div class="auth-feature-item">Up to 1 million API calls per month</div>
997          <div class="auth-feature-item">Plans from $19.99/mo</div>
998        </div>
999      </div>
1000    </div>
1001
1002    <div class="auth-modal-right">
1003      
1004        
1005        <h3 class="auth-modal-heading">API access</h3>
1006        <p class="auth-subtitle">Register for your free API key (top 100 assets included). Subscribe for the full 35k+ dataset, fundamentals, and historical data.</p>
1007
1008        <table class="auth-compare-table">
1009          <thead>
1010            <tr>
1011              <th class="auth-compare-feature-col">Feature</th>
1012              <th>Free</th>
1013              <th>Starter</th>
1014              <th>Growth</th>
1015              <th class="auth-compare-highlight">Scale</th>
1016            </tr>
1017          </thead>
1018          <tbody>
1019            <tr><td>Top 100 assets</td><td>
1019<span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
1020            <tr><td>Full 35k+ asset list</td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
1021            <tr><td>Fundamentals</td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
1022            <tr><td>Historical data</td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
1023            <tr><td>Calls / month</td><td class="auth-compare-text">1,000</td><td class="auth-compare-text">10k</td><td class="auth-compare-text">100k</td><td class="auth-compare-text">1M</td></tr>
1024            <tr class="auth-compare-price-row">
1025              <td>Price</td>
1026              <td class="auth-compare-text">Free</td>
1027              <td class="auth-compare-text">$19.99<small>/mo</small></td>
1028              <td class="auth-compare-text">$49.99<small>/mo</small></td>
1029              <td class="auth-compare-text">$99.99<small>/mo</small></td>
1030            </tr>
1031          </tbody>
1032        </table>
1033
1034        <a href="/login?view=register" class="auth-submit" style="margin-top:18px; display:block; text-align:center; text-decoration:none;">Register for your Free API Key</a>
1035        <div style="margin-top:14px;">
1036          <a href="/API" class="auth-inline-link">View API documentation &#8594;</a>
1037        </div>
1038      
1039    </div>
1040  </section>
1041</div>
1042
1043
1044<!-- ═══════════════════════════════════════════════════════════
1045     NEWSLETTER MODAL
1046     ═══════════════════════════════════════════════════════════ -->
1047<div id="newsletterOverlay" class="auth-overlay" aria-hidden="true">
1048  <div class="auth-backdrop" data-close-modal="newsletterOverlay"></div>
1049  <section class="auth-modal" role="dialog" aria-modal="true">
1050    <button class="auth-close" data-close-modal="newsletterOverlay" type="button" aria-label="Close">&times;</button>
1051
1052    <div class="auth-modal-left">
1053      <div style="position:relative; z-index:1; display:flex; flex-direction:column; height:100%;">
1054        <div class="auth-badge">Newsletter</div>
1055        <h2 class="auth-hero-title">Stay ahead of the market</h2>
1056        <p class="auth-hero-copy">
1057          Weekly insights on market caps, asset rankings, and macro trends, straight to your inbox.
1058        </p>
1059        <div class="auth-feature-list">
1060          <div class="auth-feature-item">Weekly market cap rankings recap</div>
1061          <div class="auth-feature-item">Asset class breakdowns &amp; analysis</div>
1062          <div class="auth-feature-item">Bitcoin &amp; crypto market updates</div>
1063          <div class="auth-feature-item">Unsubscribe any time</div>
1064        </div>
1065      </div>
1066    </div>
1067
1068    <div class="auth-modal-right">
1069      
1070        <h3 class="auth-modal-heading">Newsletter</h3>
1071        <p class="auth-subtitle">Get weekly market insights delivered to your inbox. No account required.</p>
1072        <form method="POST" action="/subscribe-newsletter" class="auth-form" id="newsletterForm">
1073          <input name="email" type="email" placeholder="Email address" required autocomplete="email">
1074          <button type="submit" class="auth-submit">Subscribe</button>
1075        </form>
1076      
1077      <p style="font-size:11px; color:rgba(255,255,255,0.4); line-height:1.45; margin:14px 0 0; text-align:center;">
1078        We'll never share your email. Unsubscribe any time.
1079      </p>
1080    </div>
1081  </section>
1082</div>
1083
1084
1085<!-- ===========================================================
1086     SIGNUP GATE MODAL - unclosable, fires after activity threshold
1087     Only rendered for logged-out users; controlled by JS below.
1088     =========================================================== -->
1089
1090<div id="signupGateOverlay" class="auth-overlay signup-gate" aria-hidden="true">
1091  <div class="auth-backdrop signup-gate-backdrop" data-close-modal="signupGateOverlay"></div>
1092  <section class="auth-modal signup-gate-modal" role="dialog" aria-modal="true" aria-labelledby="signupGateTitle">
1093
1094    <button class="auth-close signup-gate-close" data-close-modal="signupGateOverlay" type="button" aria-label="Close">&times;</button>
1095
1096    <div class="auth-modal-left">
1097      <div style="position:relative; z-index:1; display:flex; flex-direction:column; height:100%;">
1098        <div class="auth-badge">Free Account</div>
1099        <h2 class="auth-hero-title" id="signupGateTitle">Keep exploring 35,000+ assets</h2>
1100        <p class="auth-hero-copy">You're clearly getting value out of the data. Create a free account in seconds to keep going - no credit card required.</p>
1101        <div class="auth-feature-list">
1102          <div class="auth-feature-item">Free access to the full 35,000+ dataset</div>
1103          <div class="auth-feature-item">Education library &amp; news article access</div>
1104          <div class="auth-feature-item">Filter by Country &amp; Sector</div>
1105          <div class="auth-feature-item">Save favourites &amp; build watchlists</div>
1106          <div class="auth-feature-item">Free API key included</div>
1107        </div>
1108      </div>
1109    </div>
1110
1111    <div class="auth-modal-right">
1112      <h3 class="auth-modal-heading">Create your free account</h3>
1113      <p class="auth-subtitle">It takes about 15 seconds. No card, no spam - just full access to everything on AssetMarketCap.</p>
1114
1115      <a href="/login?view=register" class="auth-submit signup-gate-cta" style="margin-top:18px; display:block; text-align:center; text-decoration:none;">Create a free account</a>
1116
1117      <div style="margin-top:14px; text-align:center;">
1118        <a href="/login" class="auth-inline-link">Already have an account? Log in</a>
1119      </div>
1120
1121      <p style="font-size:11px; color:rgba(255,255,255,0.4); line-height:1.45; margin:22px 0 0; text-align:center;">
1122        By creating an account you agree to our <a href="/privacy" class="auth-inline-link">Privacy Policy</a>.
1123      </p>
1124    </div>
1125  </section>
1126</div>
1127
1128
1129
1130<!-- ═══════════════════════════════════════════════════════════
1131     MODAL JS - shared open/close + feature-specific logic
1132     ═══════════════════════════════════════════════════════════ -->
1133<script>
1134(function () {
1135  // ── Generic open/close for all modals ──────────────────────
1136  function openModal(id) {
1137    var el = document.getElementById(id);
1138    if (!el) return;
1139    el.classList.add("open");
1140    el.setAttribute("aria-hidden", "false");
1141    document.body.style.overflow = "hidden";
1142    // Load API usage when API modal opens
1143    if (id === "apiOverlay") loadApiUsage();
1144  }
1145
1146  function closeModal(id) {
1147    var el = document.getElementById(id);
1148    if (!el) return;
1149    el.classList.remove("open");
1150    el.setAttribute("aria-hidden", "true");
1151    document.body.style.overflow = "";
1152  }
1153
1154  // Close buttons (backdrop + X button)
1155  document.querySelectorAll("[data-close-modal]").forEach(function (el) {
1156    el.addEventListener("click", function () {
1157      closeModal(el.getAttribute("data-close-modal"));
1158    });
1159  });
1160
1161  // Escape key closes any open modal
1162  document.addEventListener("keydown", function (e) {
1163    if (e.key === "Escape") {
1164      ["pricingOverlay", "apiOverlay", "newsletterOverlay"].forEach(closeModal);
1165    }
1166  });
1167
1168  // ── Nav link triggers ──────────────────────────────────────
1169  
1170    var isAuthed = false;
1171  
1172
1173  var openPro     = document.getElementById("openPro");
1174  var openPricing = document.getElementById("openPricing");
1175  var openApi     = document.getElementById("openApi");
1176  var openNewsletterNav = document.getElementById("openNewsletterNav");
1177
1178  // Pro / Pricing nav links navigate to the full pages now (we
1179  // converted these from modal overlays to standalone marketing
1180  // pages). The only special-case left: logged-in users clicking
1181  // "Pro" go straight to their account subscriptions section
1182  // instead of the marketing page — they already have the info.
1183  if (openPro) {
1184    openPro.addEventListener("click", function (e) {
1185      if (isAuthed) {
1186        e.preventDefault();
1187        window.location.href = "/account#subscriptions";
1188      }
1189      // Otherwise let the <a href="/pro"> navigate normally.
1190    });
1191  }
1192  // Pricing link: no interceptor — the <a href="/pricing"> handles it.
1193
1194  // API: route to the standalone /api-info documentation page (no modal).
1195  // The <a href="/api-info" id="openApi"> in header.html handles navigation
1196  // natively now that the docs live on a full page.
1197
1198  // Newsletter
1199  if (openNewsletterNav) {
1200    openNewsletterNav.addEventListener("click", function (e) {
1201      e.preventDefault();
1202      openModal("newsletterOverlay");
1203    });
1204  }
1205
1206  // Footer newsletter button (loaded after this script, so use delegation)
1207  document.addEventListener("click", function (e) {
1208    var el = e.target.closest("#openNewsletter");
1209    if (el) { e.preventDefault(); openModal("newsletterOverlay"); }
1210  });
1211
1212  // Login/Register link: go to /login page
1213  var openAuth = document.getElementById("openAuth");
1214  if (openAuth) {
1215    openAuth.addEventListener("click", function (e) {
1216      e.preventDefault();
1217      window.location.href = "/login";
1218    });
1219  }
1220
1221  // Auto-open modal when returning from a flow that asked for it.
1222  // The pricing/pro auto-open was dropped after those moved to full
1223  // pages — Stripe cancel now redirects to /pricing directly.
1224  var modalParam = new URLSearchParams(window.location.search).get("modal");
1225  if (modalParam === "api" || modalParam === "api-info") openModal("apiOverlay");
1226  if (modalParam === "newsletter") openModal("newsletterOverlay");
1227
1228  // ── Billing toggle helper ──────────────────────────────────
1229  function setupBillingToggle(toggleEl, onChange) {
1230    if (!toggleEl) return;
1231    var sw = toggleEl.querySelector(".billing-toggle-switch");
1232    var labels = toggleEl.querySelectorAll(".billing-toggle-label");
1233    var isAnnual = false;
1234
1235    function update() {
1236      toggleEl.classList.toggle("billing-toggle--annual", isAnnual);
1237      labels.forEach(function (l) {
1238        l.classList.toggle("billing-toggle-label--active", l.dataset.interval === (isAnnual ? "annual" : "monthly"));
1239      });
1240      onChange(isAnnual ? "annual" : "monthly");
1241    }
1242
1243    if (sw) sw.addEventListener("click", function () { isAnnual = !isAnnual; update(); });
1244    labels.forEach(function (l) {
1245      l.addEventListener("click", function () { isAnnual = l.dataset.interval === "annual"; update(); });
1246    });
1247  }
1248
1249  // ── Pro plan card selection ────────────────────────────────
1250  var proCards = document.querySelectorAll("#pricingOverlay .auth-plan-option[data-pro-plan]");
1251  var proForm  = document.getElementById("proSubscribeForm");
1252  var proBtn   = document.getElementById("proSubscribeBtn");
1253  var proIntervalInput = document.getElementById("proInterval");
1254
1255  function updateProCardPrices(interval) {
1256    proCards.forEach(function (card) {
1257      var amount = card.querySelector("[data-price-amount]");
1258      var cents  = card.querySelector("[data-price-cents]");
1259      var period = card.querySelector("[data-price-period]");
1260      if (interval === "annual") {
1261        if (amount) amount.textContent = card.dataset.annualAmount;
1262        if (cents)  cents.textContent  = card.dataset.annualCents;
1263        if (period) period.textContent = card.dataset.annualPeriod;
1264        card.dataset.proLabel = card.dataset.proLabelAnnual;
1265      } else {
1266        if (amount) amount.textContent = card.dataset.monthlyAmount;
1267        if (cents)  cents.textContent  = card.dataset.monthlyCents;
1268        if (period) period.textContent = card.dataset.monthlyPeriod;
1269        card.dataset.proLabel = card.dataset.proLabelMonthly;
1270      }
1271    });
1272    var selectedCard = document.querySelector("#pricingOverlay .auth-plan-option.selected");
1273    if (selectedCard && proBtn) proBtn.textContent = selectedCard.dataset.proLabel;
1274  }
1275
1276  setupBillingToggle(document.getElementById("proBillingToggle"), function (interval) {
1277    if (proIntervalInput) proIntervalInput.value = interval;
1278    updateProCardPrices(interval);
1279  });
1280
1281  proCards.forEach(function (card) {
1282    card.addEventListener("click", function () {
1283      proCards.forEach(function (c) { c.classList.remove("selected"); });
1284      card.classList.add("selected");
1285      if (proForm) proForm.setAttribute("action", card.dataset.proAction);
1286      if (proBtn)  proBtn.textContent = card.dataset.proLabel;
1287    });
1288  });
1289
1290  // ── Pro upgrade toggle ─────────────────────────────────────
1291  var proUpgradeBtn      = document.getElementById("proUpgradeBtn");
1292  var proUpgradeBadge    = document.getElementById("proUpgradeBadge");
1293  var proUpgradeInterval = document.getElementById("proUpgradeInterval");
1294
1295  setupBillingToggle(document.getElementById("proUpgradeBillingToggle"), function (interval) {
1296    if (proUpgradeInterval) proUpgradeInterval.value = interval;
1297    if (interval === "annual") {
1298      if (proUpgradeBadge) proUpgradeBadge.textContent = "Pro Plus - $99.99/yr";
1299      if (proUpgradeBtn)   proUpgradeBtn.textContent   = "Upgrade to Pro Plus - $99.99/yr";
1300    } else {
1301      if (proUpgradeBadge) proUpgradeBadge.textContent = "Pro Plus - $9.99/mo";
1302      if (proUpgradeBtn)   proUpgradeBtn.textContent   = "Upgrade to Pro Plus - $9.99/mo";
1303    }
1304  });
1305
1306  // ── API plan card selection ────────────────────────────────
1307  var apiAllCards       = document.querySelectorAll("#apiPlanCards .api-plan-card[data-plan]");
1308  var selectedPlanInput = document.getElementById("apiSelectedPlan");
1309  var apiSignupForm     = document.getElementById("apiSignupForm");
1310  var apiSubscribeBtn   = document.getElementById("apiSubscribeBtn");
1311  var apiEnterpriseBtn  = document.getElementById("apiEnterpriseBtn");
1312  var apiIntervalInput  = document.getElementById("apiInterval");
1313  var currentApiInterval = "monthly";
1314
1315  var apiPlanLabels = {
1316    starter: { monthly: "Subscribe - Starter $19.99/mo",  annual: "Subscribe - Starter $99.99/yr" },
1317    growth:  { monthly: "Subscribe - Growth $49.99/mo",   annual: "Subscribe - Growth $499.99/yr" },
1318    scale:   { monthly: "Subscribe - Scale $99.99/mo",    annual: "Subscribe - Scale $999.99/yr" }
1319  };
1320
1321  function updateApiCardLimits(interval) {
1322    apiAllCards.forEach(function (card) {
1323      if (card.dataset.plan === "enterprise") return;
1324      var limitEl = card.querySelector("[data-api-limit]");
1325      if (limitEl) limitEl.textContent = card.dataset["limit" + interval.charAt(0).toUpperCase() + interval.slice(1)] || "";
1326    });
1327    var selectedCard = document.querySelector("#apiPlanCards .api-plan-card--selected");
1328    if (selectedCard && selectedCard.dataset.plan !== "enterprise" && apiSubscribeBtn) {
1329      var plan = selectedCard.dataset.plan;
1330      apiSubscribeBtn.textContent = (apiPlanLabels[plan] && apiPlanLabels[plan][interval]) || "Subscribe to API plan";
1331    }
1332  }
1333
1334  setupBillingToggle(document.getElementById("apiBillingToggle"), function (interval) {
1335    currentApiInterval = interval;
1336    if (apiIntervalInput) apiIntervalInput.value = interval;
1337    updateApiCardLimits(interval);
1338  });
1339
1340  apiAllCards.forEach(function (card) {
1341    card.addEventListener("click", function () {
1342      apiAllCards.forEach(function (c) { c.classList.remove("api-plan-card--selected"); });
1343      card.classList.add("api-plan-card--selected");
1344      var plan = card.dataset.plan;
1345      if (plan === "enterprise") {
1346        if (apiSignupForm)    apiSignupForm.style.display = "none";
1347        if (apiEnterpriseBtn) apiEnterpriseBtn.style.display = "block";
1348      } else {
1349        if (selectedPlanInput) selectedPlanInput.value = plan;
1350        if (apiSubscribeBtn)   apiSubscribeBtn.textContent = (apiPlanLabels[plan] && apiPlanLabels[plan][currentApiInterval]) || "Subscribe to API plan";
1351        if (apiSignupForm)     apiSignupForm.style.display = "";
1352        if (apiEnterpriseBtn)  apiEnterpriseBtn.style.display = "none";
1353      }
1354    });
1355  });
1356
1357  // ── Copy API key ──────────────────────────────────────────
1358  // 2026-07-05: apiKeyText now shows only the key PREFIX (keys are stored
1359  // hashed, plaintext is shown once at creation on the account page), so
1360  // the old click-to-copy handler was removed - copying a prefix would
1361  // only produce broken curl commands.
1362
1363  // ── API usage meter ───────────────────────────────────────
1364  function loadApiUsage() {
1365    var block = document.getElementById("apiUsageBlock");
1366    if (!block) return;
1367    fetch("/api-usage")
1368      .then(function (r) { return r.ok ? r.json() : null; })
1369      .then(function (data) {
1370        if (!data) return;
1371        var label = document.getElementById("apiUsageLabel");
1372        var fill  = document.getElementById("apiUsageFill");
1373        var reset = document.getElementById("apiUsageReset");
1374        if (label) label.textContent = data.used.toLocaleString() + " / " + data.limit.toLocaleString() + " calls this month";
1375        if (fill) {
1376          var pct = Math.min(100, Math.round((data.used / data.limit) * 100));
1377          fill.style.width = pct + "%";
1378          fill.classList.toggle("api-usage-bar-fill--warning", pct >= 80);
1379          fill.classList.toggle("api-usage-bar-fill--danger",  pct >= 95);
1380        }
1381        if (reset && data.reset_date) {
1382          var d = new Date(data.reset_date + "T00:00:00");
1383          reset.textContent = "Resets " + d.toLocaleDateString(undefined, { month: "short", day: "
1383numeric", year: "numeric" });
1384        }
1385      })
1386      .catch(function () {});
1387  }
1388
1389  // ── Stripe loading spinner ────────────────────────────────
1390  var stripeActions = [
1391    "/create-checkout-session", "/create-pro-plus-checkout-session",
1392    "/create-customer-portal-session", "/create-pro-plus-customer-portal-session",
1393    "/create-api-checkout-session", "/create-api-customer-portal-session",
1394    "/cancel-subscription", "/cancel-pro-plus-subscription",
1395    "/cancel-api-subscription", "/switch-api-plan"
1396  ];
1397
1398  document.querySelectorAll(".auth-form").forEach(function (form) {
1399    if (!stripeActions.includes(form.getAttribute("action"))) return;
1400    form.addEventListener("submit", function () {
1401      var btn = form.querySelector(".auth-submit, .api-plan-card");
1402      if (btn) { btn.classList.add("auth-submit--loading"); btn.disabled = true; }
1403    });
1404  });
1405
1406  window.addEventListener("pageshow", function (event) {
1407    if (event.persisted) {
1408      document.querySelectorAll(".auth-submit--loading").forEach(function (btn) {
1409        btn.classList.remove("auth-submit--loading");
1410        btn.disabled = false;
1411      });
1412    }
1413  });
1414
1415
1416  // == Signup gate (unclosable, 24hr cooldown) ==================
1417  (function setupSignupGate() {
1418    var overlay = document.getElementById("signupGateOverlay");
1419    if (!overlay) return; // not rendered (user is authenticated)
1420
1421    var STORAGE_KEY = "amc_signup_gate_v1";
1422    var CLICK_THRESHOLD = 5;
1423    var SCROLL_THRESHOLD = Infinity; // scroll trigger disabled for now (click trigger still active)
1424    var COOLDOWN_MS = 24 * 60 * 60 * 1000;
1425    var SCROLL_BURST_GAP_MS = 700; // collapse rapid wheel events into one "scroll"
1426
1427    // Skip on the login page itself - the modal's CTAs already point there
1428    var path = window.location.pathname || "";
1429    if (path === "/login" || path.indexOf("/login/") === 0 || path.indexOf("/login?") === 0) return;
1430
1431    // Skip for crawlers, bots and link-preview fetchers - keeps the modal out
1432    // of Googlebot's rendered DOM and out of social link previews (which fetch
1433    // pages to extract og:image etc).
1434    var ua = navigator.userAgent || "";
1435    if (/bot|crawl|spider|slurp|mediapartners|googlebot|bingbot|baiduspider|yandex|duckduckbot|applebot|petalbot|semrushbot|ahrefsbot|facebookexternalhit|embedly|preview|skypeuripreview|telegrambot|whatsapp|discordbot|linkedinbot|twitterbot|slackbot/i.test(ua)) return;
1436
1437    // Skip when the user arrived from a search engine - avoids Google's
1438    // intrusive-interstitial penalty on the landing page. (Once they
1439    // navigate to a second page, document.referrer is our own domain and
1440    // counting resumes normally.)
1441    var ref = document.referrer || "";
1442    if (ref) {
1443      try {
1444        var refHost = new URL(ref).hostname.toLowerCase();
1445        if (/(^|\.)(google|bing|duckduckgo|yahoo|yandex|baidu|ecosia|qwant|brave|kagi|startpage)\./.test(refHost)) return;
1446      } catch (e) { /* malformed referrer - ignore */ }
1447    }
1448
1449    function readState() {
1450      try {
1451        var raw = localStorage.getItem(STORAGE_KEY);
1452        if (!raw) return { clicks: 0, scrolls: 0, seenAt: 0 };
1453        var s = JSON.parse(raw);
1454        return {
1455          clicks: s.clicks | 0,
1456          scrolls: s.scrolls | 0,
1457          seenAt: parseInt(s.seenAt, 10) || 0
1458        };
1459      } catch (e) {
1460        return { clicks: 0, scrolls: 0, seenAt: 0 };
1461      }
1462    }
1463
1464    function writeState(s) {
1465      try { localStorage.setItem(STORAGE_KEY, JSON.stringify(s)); } catch (e) {}
1466    }
1467
1468    var state = readState();
1469    var now = Date.now();
1470
1471    // Within 24hr cooldown from a prior show? Stay quiet.
1472    if (state.seenAt && (now - state.seenAt) < COOLDOWN_MS) return;
1473
1474    // Cooldown expired - reset counters so the gate has to be re-earned.
1475    if (state.seenAt && (now - state.seenAt) >= COOLDOWN_MS) {
1476      state = { clicks: 0, scrolls: 0, seenAt: 0 };
1477      writeState(state);
1478    }
1479
1480    function closeGate() {
1481      overlay.classList.remove("open");
1482      overlay.setAttribute("aria-hidden", "true");
1483      document.body.style.overflow = "";
1484      document.documentElement.style.overflow = "";
1485    }
1486
1487    function showGate() {
1488      overlay.classList.add("open");
1489      overlay.setAttribute("aria-hidden", "false");
1490      document.body.style.overflow = "hidden";
1491      document.documentElement.style.overflow = "hidden";
1492
1493      // Stamp seenAt so subsequent navigations within 24hr stay quiet.
1494      state.seenAt = Date.now();
1495      writeState(state);
1496
1497      // Wire close button + backdrop click + Escape key.
1498      overlay.querySelectorAll('[data-close-modal="signupGateOverlay"]').forEach(function (el) {
1499        if (!el.dataset.closeBound) {
1500          el.dataset.closeBound = "1";
1501          el.addEventListener("click", closeGate);
1502        }
1503      });
1504      document.addEventListener("keydown", function onEsc(e) {
1505        if (e.key === "Escape") {
1506          closeGate();
1507          document.removeEventListener("keydown", onEsc);
1508        }
1509      });
1510
1511      removeListeners();
1512    }
1513
1514    function checkAndMaybeShow() {
1515      if (state.clicks >= CLICK_THRESHOLD || state.scrolls >= SCROLL_THRESHOLD) {
1516        showGate();
1517      }
1518    }
1519
1520    function onLinkClick(e) {
1521      var a = e.target.closest && e.target.closest("a");
1522      if (!a) return;
1523      if (overlay.contains(a)) return; // ignore links inside the gate
1524      var href = a.getAttribute("href");
1525      if (!href) return;
1526      if (href.charAt(0) === "#") return;
1527      if (/^(javascript:|mailto:|tel:)/i.test(href)) return;
1528      state.clicks++;
1529      writeState(state);
1530      checkAndMaybeShow();
1531    }
1532
1533    var lastScrollBurst = 0;
1534    function onScroll() {
1535      var t = Date.now();
1536      if (t - lastScrollBurst < SCROLL_BURST_GAP_MS) return;
1537      lastScrollBurst = t;
1538      state.scrolls++;
1539      writeState(state);
1540      checkAndMaybeShow();
1541    }
1542
1543    function addListeners() {
1544      document.addEventListener("click", onLinkClick, true);
1545      // scroll trigger disabled for now:
1546      // window.addEventListener("scroll", onScroll, { passive: true });
1547    }
1548    function removeListeners() {
1549      document.removeEventListener("click", onLinkClick, true);
1550      window.removeEventListener("scroll", onScroll);
1551    }
1552
1553    // If counters already crossed the threshold on a previous page-load,
1554    // open immediately (e.g. they hit it just before navigating).
1555    if (state.clicks >= CLICK_THRESHOLD || state.scrolls >= SCROLL_THRESHOLD) {
1556      showGate();
1557    } else {
1558      addListeners();
1559    }
1560  })();
1561
1562})();
1563</script>
1563
1564
1565
1566
1567<style>
1568/* ── Flippenings row ───────────────────────────────────── */
1569.flippenings-wrap {
1570  width: 100%;
1571  background: var(--color-background2);
1572  padding: 12px 0;
1573  margin-top: 6px;
1574  margin-bottom: clamp(14px, 1.5vw, 24px);
1575  transition: background-color .25s ease;
1576}
1577/* Six equal containers always on one horizontal row — 5 asset cells +
1578   1 tool cell. The tool cell never wraps below the asset row. Content
1579   that doesn't fit (e.g. "Real Estate $634.9T" at a narrow viewport)
1580   is handled by font-size scaling in the media queries below, and by
1581   hiding the mcap on the narrowest phones where even small fonts
1582   can't squeeze it in. */
1583.flippenings-inner {
1584  display: grid;
1585  grid-template-columns: repeat(6, minmax(0, 1fr));
1586  gap: 8px 10px;
1587  align-items: center;
1588  box-sizing: border-box;
1589}
1590.header-press-strip {
1591  clear: both;
1592  margin-top: 0;
1593  margin-bottom: 12px;
1594  padding: 9px 15px 12px;
1595  background: var(--color-background);
1596  box-sizing: border-box;
1597}
1598.header-press-strip__title {
1599  margin: 0 auto 6px;
1600  color: var(--color-neutral-500);
1601  font-size: 0.78rem;
1602  font-weight: 700;
1603  letter-spacing: 0;
1604  line-height: 1;
1605  text-align: center;
1606  text-transform: uppercase;
1607}
1608.header-press-row {
1609  display: block;
1610  margin: 0 auto;
1611}
1612.header-press-carousel {
1613  width: 100%;
1614  overflow: hidden;
1615  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
1616  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
1617}
1618.header-press-track {
1619  display: flex;
1620  align-items: center;
1621  width: max-content;
1622  animation: headerPressScroll 54s linear infinite;
1623}
1624.header-press-set {
1625  display: flex;
1626  align-items: center;
1627  gap: clamp(24px, 4vw, 54px);
1628  padding-right: clamp(24px, 4vw, 54px);
1629}
1630.header-press-logo {
1631  display: block;
1632  width: auto;
1633  max-width: 150px;
1634  height: 34px;
1635  object-fit: contain;
1636  opacity: 0.86;
1637}
1638.header-press-logo:hover {
1639  opacity: 1;
1640}
1641@keyframes headerPressScroll {
1642  from { transform: translateX(0); }
1643  to { transform: translateX(-25%); }
1644}
1645.flip-row {
1646  display: flex;
1647  align-items: center;
1648  justify-content: center;
1649  gap: 6px;
1650  min-width: 0;
1651  overflow: hidden;   /* last-resort guard: clip at cell edge instead of
1652                         bleeding into the next cell if content overflows */
1653}
1654/* Two-row cell: head (label + mcap) on top, meter (bar + pct) below.
1655   Cells never overflow because the grid uses auto-fit with a 160px
1656   minimum (wide enough for "Real Estate $634.9T") — on narrow viewports
1657   fewer cells fit per row and the rest wrap to a new row. */
1658.flip-cell {
1659  display: flex;
1660  flex-direction: column;
1661  align-items: center;
1662  row-gap: 2px;
1663  min-width: 0;
1664}
1665.flip-head {
1666  display: inline-flex;
1667  align-items: baseline;
1668  gap: 4px;
1669  white-space: nowrap;
1670}
1671.flip-meter {
1672  display: inline-flex;
1673  align-items: center;
1674  gap: 6px;
1675  white-space: nowrap;
1676}
1677a.flip-row-link {
1678  text-decoration: none;
1679  color: inherit;
1680  border-radius: 6px;
1681  padding: 4px 6px;
1682  margin: -4px -6px;
1683  transition: background 0.15s;
1684}
1685a.flip-row-link:hover {
1686  background: rgba(99,102,241,0.08);
1687}
1688a.flip-row-link:hover .flip-label {
1689  color: var(--color-primary);
1690}
1691.flip-logo {
1692  width: 22px;
1693  height: 22px;
1694  border-radius: 50%;
1695  flex-shrink: 0;
1696  object-fit: cover;
1697}
1698.flip-label {
1699  font-size: 0.95rem;
1700  font-weight: 700;
1701  white-space: nowrap;
1702  color: var(--color-text);
1703}
1704.flip-bar {
1705  display: inline-block;
1706  width: 60px;
1707  height: 8px;
1708  background: var(--color-neutral-200);
1709  border-radius: 4px;
1710  overflow: hidden;
1711  flex-shrink: 0;
1712}
1713.flip-fill {
1714  display: block;
1715  height: 100%;
1716  border-radius: 4px;
1717  background: var(--color-neutral-400);
1718  transition: width 0.6s ease;
1719  width: 0%;
1720}
1721.flip-fill-btc {
1722  background: #f7931a;
1723}
1724.flip-mcap {
1725  font-size: 0.88rem;
1726  font-weight: 600;
1727  color: var(--color-neutral-500);
1728  white-space: nowrap;
1729}
1730.flip-pct {
1731  font-size: 0.82rem;
1732  font-weight: 700;
1733  color: var(--color-text);
1734  min-width: 34px;
1735  text-align: right;
1736}
1737/* Sixth grid cell — side-by-side buttons when the cell is wide enough,
1738   one-under-the-other when it isn't. The tool CELL itself stays in its
1739   grid column (never wraps below the asset row); only its contents
1740   wrap internally. */
1741.flip-tools {
1742  display: flex;
1743  flex-wrap: wrap;
1744  gap: 4px 6px;
1745  align-items: center;
1746  justify-content: center;
1747  min-width: 0;
1748}
1749.flip-tool-btn {
1750  padding: 4px 10px;
1751  font-size: 0.72rem;
1752  font-weight: 700;
1753  border: 2px solid var(--color-primary);
1754  border-radius: var(--radius-full);
1755  background: transparent;
1756  color: var(--color-primary);
1757  cursor: pointer;
1758  white-space: nowrap;
1759  transition: all 0.15s ease;
1760}
1761.flip-tool-btn:hover {
1762  background: var(--color-primary);
1763  color: #fff;
1764}
1765
1766/* Font-size scaling so all 6 cells keep fitting on one row as the
1767   viewport narrows. The grid stays fixed at 6 columns — only the content
1768   inside each cell shrinks. On the narrowest phones the mcap is hidden
1769   entirely (label + meter still visible) because no sensible font size
1770   would keep it readable in the cell width. */
1771@media (max-width: 1100px) {
1772  .flip-label { font-size: 0.78rem; }
1773  .flip-mcap  { font-size: 0.72rem; }
1774  .flip-pct   { font-size: 0.72rem; }
1775  .flip-bar   { width: 45px; }
1776}
1777@media (max-width: 900px) {
1778  .flippenings-wrap {
1779    padding: 4px 0 2px;
1780    margin-top: 2px;
1781    margin-bottom: 12px;
1782  }
1783  .flip-label { font-size: 0.72rem; }
1784  .flip-mcap  { font-size: 0.64rem; }
1785  .flip-pct   { font-size: 0.64rem; }
1786  .flip-bar   { width: 38px; }
1787  .flip-logo  { width: 20px; height: 20px; }
1788  .flip-tool-btn { padding: 3px 8px; font-size: 0.64rem; border-width: 2px; }
1789}
1790@media (max-width: 700px) {
1791  .flip-label { font-size: 0.65rem; }
1792  .flip-mcap  { font-size: 0.58rem; }
1793  .flip-pct   { font-size: 0.58rem; }
1794  .flip-bar   { width: 28px; height: 6px; }
1795  .flip-logo  { width: 18px; height: 18px; }
1796  .flippenings-inner { gap: 6px 6px; }
1797}
1798@media (max-width: 500px) {
1799  .header-press-strip {
1800    margin-top: 0;
1801    margin-bottom: 10px;
1802    padding: 8px 12px 10px;
1803  }
1804  .header-press-strip__title {
1805    font-size: 0.68rem;
1806    margin-bottom: 6px;
1807  }
1808  .header-press-track {
1809    animation-duration: 42s;
1810  }
1811  .header-press-set {
1812    gap: 26px;
1813    padding-right: 26px;
1814  }
1815  .header-press-logo {
1816    max-width: 116px;
1817    height: 26px;
1818  }
1819  .flip-mcap  { display: none; }          /* no room at this width */
1820  .flip-label { font-size: 0.6rem; }
1821  .flip-pct   { font-size: 0.55rem; }
1822  .flip-bar   { width: 22px; height: 5px; }
1823  .flip-logo  { width: 16px; height: 16px; }
1824  .flip-tool-btn { padding: 2px 6px; font-size: 0.55rem; border-width: 1px; }
1825  .flippenings-inner { gap: 4px 4px; }
1826}
1827
1828/* ── Shared dropdown styles ──────────────────────────── */
1829.flippener-drop-sep { height: 1px; background: var(--color-neutral-200); margin: 2px 0; }
1830.cmp-drop-sep, .fp-drop-sep { height: 1px; background: var(--color-neutral-200); margin: 2px 0; }
1831.cmp-drop-item.cdi-class, .fp-drop-item.fpdi-class { background: rgba(99,102,241,0.04); }
1832.cmp-drop-item.cdi-class .cdi-name, .fp-drop-item.fpdi-class .fpdi-name { color: var(--color-primary); }
1833.flip-tool-btn--link {
1834  text-decoration: none; display: inline-flex; align-items: center;
1835}
1836
1837/* Free usage badge */
1838.free-usage-badge {
1839  display: inline-block;
1840  font-size: 0.72rem;
1841  font-weight: 600;
1842  color: var(--color-neutral-500);
1843  background: var(--color-neutral-50);
1844  border: 1px solid var(--color-neutral-200);
1845  border-radius: 20px;
1846  padding: 4px 12px;
1847  margin: 8px auto 0;
1848  text-align: center;
1849}
1850.free-usage-badge .fub-count { color: var(--color-primary); font-weight: 700; }
1851.free-usage-badge.fub-warn { border-color: #f59e0b; color: #b45309; background: #fef3c7; }
1852.free-usage-badge.fub-limit { border-color: #ef4444; color: #dc2626; background: #fef2f2; }
1853</style>
1854
1855
1856<script>
1857/* Flippenings bar loader moved to templates/html/flippenings.html so
1858   it ships alongside the markup — guarantees the #flippenings element
1859   exists in the DOM by the time the loader runs, no matter where the
1860   include lands on the page. */
1861
1862// Global auth flag (used by dark mode sync, favourites, etc.)
1863if (typeof window.__isLoggedIn === 'undefined') {
1864  window.__isLoggedIn = false;
1865}
1866// Global user tier: 'free' | 'signup' | 'pro' | 'proplus'
1867window.__userTier = (function() {
1868  
1869    return 'free';
1870  
1871})();
1872
1873// Asset class synthetic rows for Flippener/Comparator dropdowns
1874(function() {
1875  function _pm(s) {
1876    if (!s) return 0;
1877    s = String(s).replace(/[$,]/g, '');
1878    var m = 1;
1879    if (s.endsWith('T')) { m = 1e12; s = s.slice(0, -1); }
1880    else if (s.endsWith('B')) { m = 1e9; s = s.slice(0, -1); }
1881    else if (s.endsWith('M')) { m = 1e6; s = s.slice(0, -1); }
1882    return parseFloat(s) * m || 0;
1883  }
1884  window.__assetClasses = [
1885    { Name: 'All Assets', Ticker: '__all__', MarketCap: _pm('$1,083.80T'), Logo: '/static/logo.png', AssetType: 'Asset Class', _isClass: true },
1886    { Name: 'All Commodities', Ticker: '__commodities__', MarketCap: _pm('$225.33T'), Logo: '/static/icons/commodities/gc=f.png', AssetType: 'Asset Class', _isClass: true },
1887    { Name: 'All Currencies', Ticker: '__currencies__', MarketCap: _pm('$139.77T'), Logo: '/static/icons/flags/us.png', AssetType: 'Asset Class', _isClass: true },
1888    { Name: 'All Companies', Ticker: '__companies__', MarketCap: _pm('$149.86T'), Logo: '/static/icons/companies/AAPL.png', AssetType: 'Asset Class', _isClass: true },
1889    { Name: 'All Crypto', Ticker: '__crypto__', MarketCap: _pm('$2.95T'), Logo: '/static/icons/cryptos/BTC-USD.png', AssetType: 'Asset Class', _isClass: true }
1890  ];
1891})();
1892// ── Usage limits per tier ─────────────────────────────────
1893// Limits: { type: { free, signup, pro, proplus } }
1894// -1 means unlimited, positive = total (free/signup) or per month (pro)
1895window.__freeUsage = (function() {
1896  var TIER_LIMITS = {
1897    favourite:  { free: 3,  signup: 15, pro: 50, proplus: -1 },
1898    flippener:  { free: 3,  signup: 10, pro: 30, proplus: -1 },
1899    comparator: { free: 3,  signup: 5,  pro: 15, proplus: -1 }
1900  };
1901  var KEY = 'amc_usage';
1902  var tier = window.__userTier || 'free';
1903
1904  function _load() {
1905    try { return JSON.parse(localStorage.getItem(KEY)) || {}; } catch(e) { return {}; }
1906  }
1907  function _save(d) { try { localStorage.setItem(KEY, JSON.stringify(d)); } catch(e) {} }
1908
1909  // Monthly reset key: "2026-04" etc
1910  function _monthKey() {
1911    var d = new Date();
1912    return d.getFullYear() + '-' + String(d.getMonth()+1).padStart(2,'0');
1913  }
1914
1915  // For pro/proplus, counts reset monthly. For free/signup, counts are lifetime.
1916  function _getStorageKey(type) {
1917    if (tier === 'pro' || tier === 'proplus') return type + ':' + _monthKey();
1918    return type;
1919  }
1920
1921  function getCount(type) {
1922    var d = _load();
1923    return d[_getStorageKey(type)] || 0;
1924  }
1925
1926  function getLimit(type) {
1927    var limits = TIER_LIMITS[type];
1928    if (!limits) return 3;
1929    var lim = limits[tier];
1930    return (lim === undefined) ? 3 : lim;
1931  }
1932
1933  function getRemaining(type) {
1934    var lim = getLimit(type);
1935    if (lim === -1) return -1; // unlimited
1936    return Math.max(0, lim - getCount(type));
1937  }
1938
1939  function increment(type) {
1940    var d = _load();
1941    var sk = _getStorageKey(type);
1942    d[sk] = (d[sk] || 0) + 1;
1943    _save(d);
1944    // Also notify server for logged-in users
1945    if (window.__isLoggedIn) {
1946      fetch('/api/usage/increment', {
1947        method: 'POST',
1948        headers: { 'Content-Type': 'application/json' },
1949        body: JSON.stringify({ type: type })
1950      }).catch(function(){});
1951    }
1952    return d[sk];
1953  }
1954
1955  function isLimitReached(type) {
1956    var lim = getLimit(type);
1957    if (lim === -1) return false;
1958    return getCount(type) >= lim;
1959  }
1960
1961  // Reason-driven CTA: the title changes to WHY the user was gated, e.g.
1962  // 'Save your Favourites with a Free Account'. Uses the closable signup-gate
1963  // overlay (free-account CTA) if present, else the pricing overlay, else /login.
1964  var GATE_TITLES = {
1965    favourite:  'Save your Favourites with a Free Account',
1966    networth:   'Track your Net Worth with a Free Account',
1967    comparator: 'Keep Comparing with a Free Account',
1968    flippener:  'Keep using the Flippener with a Free Account',
1969    article:    'Read this article with a Free Account',
1970    'default':  'Create your Free Account'
1971  };
1972  function openSignupGate(reason) {
1973    var title = GATE_TITLES[reason] || GATE_TITLES['default'];
1974    var overlay = document.getElementById('pricingOverlay');
1975    if (overlay) {
1976      var th = overlay.querySelector('.auth-hero-title');
1977      if (th) th.textContent = title;   // retitle to WHY they were gated
1978      overlay.classList.add('open');
1979      overlay.setAttribute('aria-hidden', 'false');
1980      document.body.style.overflow = 'hidden';
1981    } else {
1982      window.location.href = '/login?view=register';
1983    }
1984  }
1985
1986  function tryUse(type) {
1987    if (tier === 'proplus') return true; // unlimited
1988    if (isLimitReached(type)) {
1989      openSignupGate(type);   // pass the feature so the CTA title matches
1990      return false;
1991    }
1992    increment(type);
1993    return true;
1994  }
1995
1996  // Whether counts are monthly (vs lifetime total)
1997  function isMonthly() { return tier === 'pro' || tier === 'proplus'; }
1998
1999  return {
2000    getCount: getCount, getLimit: getLimit, getRemaining: getRemaining,
2001    increment: increment, isLimitReached: isLimitReached,
2002    tryUse: tryUse, openSignupGate: openSignupGate, isMonthly: isMonthly,
2003    TIER_LIMITS: TIER_LIMITS
2004  };
2005})();
2006
2007// Render usage badges for all tiers
2008window.__updateUsageBadge = function(elId, type, label) {
2009  var el = document.getElementById(elId);
2010  if (!el) return;
2011  var fu = window.__freeUsage;
2012  var limit = fu.getLimit(type);
2013
2014  // Pro Plus = unlimited, hide badge
2015  if (limit === -1) { el.style.display = 'none'; return; }
2016
2017  var used = fu.getCount(type);
2018  var remaining = Math.max(0, limit - used);
2019  var period = fu.isMonthly() ? '/month' : '';
2020  var tier = window.__userTier;
2021
2022  var upgradeText;
2023  if (tier === 'free') upgradeText = '<a href="/login?view=register" style="color:#dc2626;font-weight:700;text-decoration:underline;">sign up</a> for more';
2024  else if (tier === 'signup') upgradeText = '<a href="/login?view=pro" style="color:#dc2626;font-weight:700;text-decoration:underline;">upgrade to Pro</a> for more';
2025  else upgradeText = '<a href="/login?view=pro-plus" style="color:#dc2626;font-weight:700;text-decoration:underline;">upgrade to Pro Plus</a> for unlimited';
2026
2027  if (remaining <= 0) {
2028    el.className = 'free-usage-badge fub-limit';
2029    el.innerHTML = label + ' limit reached — ' + upgradeText;
2030  } else if (remaining <= Math.ceil(limit * 0.25)) {
2031    el.className = 'free-usage-badge fub-warn';
2032    el.innerHTML = '<span class="fub-count">' + remaining + '</span> of ' + limit + ' ' + label + period + ' remaining';
2033  } else {
2034    el.className = 'free-usage-badge';
2035    el.innerHTML = '<span class="fub-count">' + remaining + '</span> of ' + limit + ' ' + label + period + ' remaining';
2036  }
2037  el.style.display = '';
2038};
2039
2040// Sync server-side usage counts for logged-in users
2041if (window.__isLoggedIn && window.__userTier !== 'free') {
2042  fetch('/api/usage')
2043    .then(function(r) { return r.ok ? r.json() : null; })
2044    .then(function(data) {
2045      if (!data) return;
2046      // Overwrite localStorage with authoritative server counts
2047      var KEY = 'amc_usage';
2048      var month = (function(){ var d=new Date(); return d.getFullYear()+'-'+String(d.getMonth()+1).padStart(2,'0'); })();
2049      var stored = {};
2050      try { stored = JSON.parse(localStorage.getItem(KEY)) || {}; } catch(e) {}
2051      var isMonthly = data.tier === 'pro' || data.tier === 'proplus';
2052      ['flippener','comparator'].forEach(function(k) {
2053        if (data[k]) {
2054          var sk = isMonthly ? (k+':'+month) : k;
2055          stored[sk] = data[k].used;
2056        }
2057      });
2058      if (data.favourite) {
2059        var sk = isMonthly ? ('favourite:'+month) : 'favourite';
2060        stored[sk] = data.favourite.used;
2061      }
2062      try { localStorage.setItem(KEY, JSON.stringify(stored)); } catch(e) {}
2063    })
2064    .catch(function(){});
2065}
2066
2067const DARK_KEY  = 'prefers_dark_mode';   // legacy: '0' / '1'
2068const THEME_KEY = 'theme_mode';
2068          // new: 'dark' / 'light' / 'system'
2069
2070// Resolve which theme should currently be applied given the stored mode.
2071// 'system' -> follows prefers-color-scheme; 'dark'/'light' force.
2072function resolveTheme(mode) {
2073  if (mode === 'dark')  return 'dark';
2074  if (mode === 'light') return 'light';
2075  // 'system' is now an EXPLICIT opt-in only (no longer the default) - follow the OS.
2076  return (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light';
2077}
2078
2079function getStoredThemeMode() {
2080  try {
2081    var v = localStorage.getItem(THEME_KEY);
2082    if (v === 'dark' || v === 'light' || v === 'system') return v;
2083    // Migration: respect legacy DARK_KEY if no new key set yet
2084    var legacy = localStorage.getItem(DARK_KEY);
2085    if (legacy === '1') return 'dark';
2086    if (legacy === '0') return 'light';
2087  } catch(e) {}
2088  // DEFAULT = light. Previously 'system', which followed prefers-color-scheme and
2089  // silently gave dark-OS visitors a dark site on first load. Dark/System are now
2090  // opt-in only (via the quick toggle or the Settings 3-way picker).
2091  return 'light';
2092}
2093
2094function setTheme(mode) {
2095  try { localStorage.setItem(THEME_KEY, mode); } catch(e) {}
2096  var resolved = resolveTheme(mode);
2097  applyDarkMode(resolved === 'dark', { skipModeStore: true });
2098  // Reflect the picker state in the Settings UI
2099  document.querySelectorAll('.nav-theme-btn').forEach(function (b) {
2100    var on = b.dataset.theme === mode;
2101    b.classList.toggle('is-active', on);
2102    b.setAttribute('aria-checked', on ? 'true' : 'false');
2103  });
2104}
2105
2106function applyDarkMode(isDark, opts) {
2107  document.documentElement.classList.toggle('dark-mode', isDark);
2108  // Legacy key kept for any code that still reads it
2109  localStorage.setItem(DARK_KEY, isDark ? '1' : '0');
2110
2111  // When the user clicks the quick toggle (not the Settings 3-way),
2112  // promote to an explicit dark/light selection so it doesn't snap back
2113  // when System changes.
2114  if (!opts || !opts.skipModeStore) {
2115    try { localStorage.setItem(THEME_KEY, isDark ? 'dark' : 'light'); } catch(e) {}
2116  }
2117
2118  const toggle = document.getElementById('darkModeToggle');
2119  if (toggle) toggle.checked = isDark;
2120
2121  // Persist to server for logged-in users
2122  if (window.__isLoggedIn) {
2123    fetch('/account/dark-mode', {
2124      method: 'POST',
2125      headers: { 'Content-Type': 'application/json' },
2126      body: JSON.stringify({ dark: isDark })
2127    }).catch(function () {});
2128  }
2129}
2130
2131function darkModeFunction() {
2132  const isDark = !document.documentElement.classList.contains('dark-mode');
2133  applyDarkMode(isDark);
2134}
2135
2136// Initial paint: apply the stored mode immediately (before DOMContentLoaded
2137// so there's no flash). Re-resolves if user is on System and the OS theme
2138// changes during the session.
2139(function bootTheme() {
2140  var mode = getStoredThemeMode();
2141  var resolved = resolveTheme(mode);
2142  document.documentElement.classList.toggle('dark-mode', resolved === 'dark');
2143  if (window.matchMedia) {
2144    var mql = window.matchMedia('(prefers-color-scheme: dark)');
2145    var onChange = function () {
2146      if (getStoredThemeMode() === 'system') {
2147        document.documentElement.classList.toggle('dark-mode', mql.matches);
2148      }
2149    };
2150    if (mql.addEventListener) mql.addEventListener('change', onChange);
2151    else if (mql.addListener) mql.addListener(onChange);
2152  }
2153})();
2154
2155document.addEventListener('DOMContentLoaded', () => {
2156  const toggle = document.getElementById('darkModeToggle');
2157  const btn    = document.getElementById('darkModeBtn');
2158
2159  // Sync hidden checkbox to current mode
2160  if (toggle) toggle.checked = document.documentElement.classList.contains('dark-mode');
2161
2162  // Icon button click → toggle
2163  if (btn) btn.addEventListener('click', darkModeFunction);
2164
2165  // Settings → Theme picker (Dark / Light / System)
2166  document.querySelectorAll('.nav-theme-btn').forEach(function (b) {
2167    var on = b.dataset.theme === getStoredThemeMode();
2168    b.classList.toggle('is-active', on);
2169    b.setAttribute('aria-checked', on ? 'true' : 'false');
2170    b.addEventListener('click', function (e) {
2171      e.preventDefault();
2172      e.stopPropagation();
2173      setTheme(b.dataset.theme);
2174    });
2175  });
2176
2177  // Overflow auth triggers in logo bar → proxy to real buttons (skip avatar links, they're direct <a href>)
2178  document.querySelectorAll('.overflow-auth-trigger:not(.nav-avatar-link)').forEach(function (el) {
2179    el.addEventListener('click', function (e) {
2180      e.preventDefault();
2181      var target = el.dataset.open;
2182      var real = document.getElementById(target === 'account' ? 'openAccount' : 'openAuth');
2183      if (real) real.click();
2184    });
2185  });
2186
2187  // Detect navbar overflow → swap buttons to logo bar
2188  var wrapper = document.querySelector('.navbar-wrapper');
2189  var navbar  = document.querySelector('.navbar');
2190
2191  function checkNavOverflow() {
2192    // Collapse-into-logo-bar behavior disabled: FAQs / Support / dark-mode
2193    // should always live in .nav-right, regardless of width.
2194    if (wrapper) wrapper.classList.remove('nav-overflowed');
2195  }
2196
2197  checkNavOverflow();
2198  window.addEventListener('resize', checkNavOverflow);
2199
2200  // ── Tap-to-toggle for nav dropdowns (Learn, Products, Help) ─────────
2201  // Covers navbar-row dropdowns AND the top-bar Help dropdown. Selector
2202  // is broad: any .nav-dropdown inside .navbar-header or .top-bar-actions.
2203  var DD_SCOPE = '.navbar-header .nav-dropdown, .top-bar-actions .nav-dropdown';
2204  document.querySelectorAll(DD_SCOPE).forEach(function (dd) {
2205    var trigger = dd.querySelector(':scope > .nav-dropdown-trigger');
2206    if (!trigger) return;
2207    trigger.addEventListener('click', function (e) {
2208      e.preventDefault();
2209      e.stopPropagation();
2210      document.querySelectorAll(DD_SCOPE).forEach(function (other) {
2211        if (other !== dd && other.classList.contains('open')) {
2212          other.classList.remove('open');
2213          var t = other.querySelector(':scope > .nav-dropdown-trigger');
2214          if (t) t.setAttribute('aria-expanded', 'false');
2215        }
2216      });
2217      var isOpen = dd.classList.toggle('open');
2218      trigger.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
2219    });
2220  });
2221  document.addEventListener('click', function (e) {
2222    document.querySelectorAll(DD_SCOPE).forEach(function (dd) {
2223      if (!dd.classList.contains('open')) return;
2224      if (!dd.contains(e.target)) {
2225        dd.classList.remove('open');
2226        var t = dd.querySelector(':scope > .nav-dropdown-trigger');
2227        if (t) t.setAttribute('aria-expanded', 'false');
2228      }
2229    });
2230  });
2231  document.addEventListener('keydown', function (e) {
2232    if (e.key !== 'Escape') return;
2233    document.querySelectorAll(DD_SCOPE).forEach(function (dd) {
2234      dd.classList.remove('open');
2235      var t = dd.querySelector(':scope > .nav-dropdown-trigger');
2236      if (t) t.setAttribute('aria-expanded', 'false');
2237    });
2238  });
2239
2240  // ── App download popup ────────────────────────────────────
2241  var appPopup   = document.getElementById('appDownloadPopup');
2242  var appClose   = document.getElementById('closeAppPopup');
2243  var appBackdrop = document.getElementById('appPopupBackdrop');
2244  var appPopupTitle = document.getElementById('appPopupTitle');
2245  var appPopupCopy = document.getElementById('appPopupCopy');
2246
2247  function openApp(e) {
2248    if (e) e.preventDefault();
2249    var appleSoon = e && e.currentTarget && e.currentTarget.dataset.appleSoon === 'true';
2250    if (appPopupTitle) appPopupTitle.textContent = appleSoon ? 'App Store Coming Soon' : 'Get the App';
2251    if (appPopupCopy) appPopupCopy.textContent = appleSoon ? 'AssetMarketCap for iPhone is coming soon.' : 'Track 35,000+ assets on the go.';
2252    if (appPopup) appPopup.classList.add('open');
2253  }
2254  function closeApp() {
2255    if (appPopup) appPopup.classList.remove('open');
2256  }
2257
2258  // Mobile button click routing:
2259  //  Android  → straight to Play Store
2260  //  iOS      → "App Store coming soon" popup (uses the existing modal)
2261  //  Desktop  → open the popup with QR (existing behavior)
2262  function detectPlatform() {
2263    var ua = navigator.userAgent || '';
2264    if (/android/i.test(ua)) return 'android';
2265    if (/iPad|iPhone|iPod/.test(ua) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) return 'ios';
2266    return 'desktop';
2267  }
2268  document.querySelectorAll('.js-open-app-popup').forEach(function (el) {
2269    el.addEventListener('click', function (e) {
2270      // If this was triggered by an actual tap/click (not the dropdown's
2271      // own click-to-toggle), route by platform.
2272      var plat = detectPlatform();
2273      if (plat === 'android') {
2274        e.preventDefault();
2275        window.location.href = 'https://play.google.com/store/apps/details?id=com.assetmarketcap.app';
2276        return;
2277      }
2278      if (plat === 'ios') {
2279        e.preventDefault();
2280        if (appPopupTitle) appPopupTitle.textContent = 'App Store Coming Soon';
2281        if (appPopupCopy)  appPopupCopy.textContent  = 'AssetMarketCap for iPhone is on the way. Use the web app for now — it works great on iOS.';
2282        if (appPopup) appPopup.classList.add('open');
2283        return;
2284      }
2285      // Desktop: keep the QR popover (hover) behavior. The dropdown JS
2286      // already opens the menu on click for tap devices. Open the big
2287      // modal too as a fallback for users who want a larger QR.
2288      openApp(e);
2289    });
2290  });
2291  if (appClose)   appClose.addEventListener('click', closeApp);
2292  if (appBackdrop) appBackdrop.addEventListener('click', closeApp);
2293  document.addEventListener('keydown', function (e) { if (e.key === 'Escape') closeApp(); });
2294
2295  // ── "/" keyboard shortcut focuses the global search ────────
2296  // CoinGecko-style. Ignore if user is already in an input/textarea
2297  // so it doesn't hijack typing in form fields.
2298  var navSearch = document.getElementById('navGlobalSearch');
2299  if (navSearch) {
2300    document.addEventListener('keydown', function (e) {
2301      if (e.key !== '/') return;
2302      var t = e.target;
2303      var inField = t && (t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.isContentEditable);
2304      if (inField) return;
2305      e.preventDefault();
2306      navSearch.focus();
2307      navSearch.select();
2308    });
2309
2310    // On the homepage, mirror typing into the DataTables filter so the
2311    // table updates as the user types in the global search. Form submit
2312    // still goes to /search for a full-text search across pages.
2313    var dtFilter = document.querySelector('.dataTables_filter input[type="search"], .dataTables_filter input');
2314    if (dtFilter) {
2315      navSearch.addEventListener('input', function () {
2316        var v = navSearch.value;
2317        dtFilter.value = v;
2318        // Fire the events DataTables listens for
2319        dtFilter.dispatchEvent(new Event('keyup', { bubbles: true }));
2320        dtFilter.dispatchEvent(new Event('input', { bubbles: true }));
2321      });
2322    }
2323  }
2324
2325  // ── Favourites pill: toggle the table's "favourites-only" filter ──
2326  // Logged-in users get the same behaviour as clicking the header
2327  // star (toggleStarFilter is exposed at top level of table.js). The
2328  // header star and the pill share state via syncStarHeaderUI, which
2329  // also paints the pill icon yellow when the filter is active.
2330  // Logged-out users keep the original anchor (→ /login?view=register).
2331  var favPill = document.querySelector('.nav-favourites-trigger');
2332  if (favPill && favPill.getAttribute('href') === '#favourites') {
2333    favPill.addEventListener('click', function (e) {
2334      if (typeof window.toggleStarFilter === 'function') {
2335        e.preventDefault();
2336        window.toggleStarFilter();
2337      }
2338    });
2339  }
2340
2341  // ── Sidebar toggle ────────────────────────────────────────────
2342  // Two trigger points share one handler — visually they look like a
2343  // single button that "jumps" between two homes:
2344  //   #sidebarCloseBtn — sidebar's top-right corner (visible while
2345  //                      the sidebar is expanded)
2346  //   #sidebarShowBtn  — right side of the dominance bar (visible
2347  //                      only when the sidebar is collapsed)
2348  // Both flip html.sidebar-collapsed which hides .page-side and
2349  // collapses .page-grid to a single column. Preference persists.
2350  // We tag html.has-sidebar when a .page-side actually exists so the
2351  // dominance-bar Show button only ever appears on pages where it
2352  // would do something meaningful.
2353  if (document.querySelector('.page-side')) {
2354    document.documentElement.classList.add('has-sidebar');
2355  }
2356  var sidebarClose = document.getElementById('sidebarCloseBtn');
2357  var sidebarShow  = document.getElementById('sidebarShowBtn');
2358  function toggleSidebar() {
2359    var collapsed = document.documentElement.classList.toggle('sidebar-collapsed');
2360    try { localStorage.setItem('sidebar_collapsed', collapsed ? '1' : '0'); } catch (e) {}
2361    // Let DataTables re-measure now that the main column changed width, then
2362    // re-run the responsive column fit so collapsing the sidebar re-shows the
2363    // columns that now fit (e.g. Country), and expanding re-hides as needed.
2364    function _reflow() {
2365      if (window.__assetTable && typeof window.__assetTable.columns === 'function') {
2366        try { window.__assetTable.columns.adjust(); } catch (e) {}
2367      }
2368      if (typeof window.__amcRefitColumns === 'function') {
2369        try { window.__amcRefitColumns(); } catch (e) {}
2370      }
2371    }
2372    _reflow();
2373    // The grid width transition takes a moment; re-fit again once it settles.
2374    setTimeout(_reflow, 260);
2375  }
2376  if (sidebarClose) sidebarClose.addEventListener('click', toggleSidebar);
2377  if (sidebarShow)  sidebarShow .addEventListener('click', toggleSidebar);
2378});
2379</script>
2379
2380
2381<!-- App download popup -->
2382<div id="appDownloadPopup" class="app-popup-overlay">
2383  <div class="app-popup-backdrop" id="appPopupBackdrop"></div>
2384  <div class="app-popup">
2385    <button class="app-popup-close" id="closeAppPopup" type="button" aria-label="Close">&times;</button>
2386    <div class="app-popup-icon">
2387      <i class="fa-solid fa-mobile-screen-button"></i>
2388    </div>
2389    <h3 class="app-popup-title" id="appPopupTitle">Get the App</h3>
2390    <p class="app-popup-copy" id="appPopupCopy">Scan with your phone to download. 35,000+ assets in your pocket.</p>
2391
2392    
2393    <div class="app-popup-qrs">
2394      <div class="app-popup-qr">
2395        <a href="https://play.google.com/store/apps/details?id=com.assetmarketcap.app"
2396           target="_blank" rel="noopener" class="app-popup-qr-link">
2397          <img class="app-popup-qr-img"
2398               src="https://api.qrserver.com/v1/create-qr-code/?size=180x180&margin=0&data=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Dcom.assetmarketcap.app"
2399               alt="Google Play QR code" width="160" height="160" loading="lazy">
2400          <span class="app-popup-qr-label">
2401            <i class="fa-brands fa-google-play"></i>
2402            Google Play
2403          </span>
2404        </a>
2405      </div>
2406      <div class="app-popup-qr app-popup-qr--soon">
2407        <div class="app-popup-qr-placeholder" aria-hidden="true">
2408          <i class="fa-brands fa-apple"></i>
2409          <span>Coming soon</span>
2410        </div>
2411        <span class="app-popup-qr-label app-popup-qr-label--muted">
2412          <i class="fa-brands fa-apple"></i>
2413          App Store
2414        </span>
2415      </div>
2416    </div>
2417  </div>
2418</div>
2419
2420<style>
2421.app-popup-overlay {
2422  position: fixed;
2423  inset: 0;
2424  z-index: 99998;
2425  display: none;
2426  align-items: center;
2427  justify-content: center;
2428  padding: 24px;
2429}
2430.app-popup-overlay.open {
2431  display: flex;
2432}
2433.app-popup-backdrop {
2434  position: fixed;
2435  inset: 0;
2436  background: rgba(4, 2, 20, 0.65);
2437  backdrop-filter: blur(12px);
2438  -webkit-backdrop-filter: blur(12px);
2439}
2440.app-popup {
2441  position: relative;
2442  z-index: 2;
2443  width: min(400px, 92vw);
2444  padding: 36px 32px 32px;
2445  border-radius: 24px;
2446  background: rgba(14, 8, 40, 0.88);
2447  backdrop-filter: blur(40px) saturate(180%);
2448  -webkit-backdrop-filter: blur(40px) saturate(180%);
2449  border: 1px solid rgba(255, 255, 255, 0.1);
2450  box-shadow:
2451    0 0 0 1px rgba(255, 255, 255, 0.05) inset,
2452    0 40px 80px rgba(0, 0, 0, 0.5),
2453    0 0 80px rgba(99, 102, 241, 0.1);
2454  text-align: center;
2455}
2456.app-popup-close {
2457  position: absolute;
2458  top: 12px;
2459  right: 12px;
2460  width: 32px;
2461  height: 32px;
2462  border: 1px solid rgba(255, 255, 255, 0.12);
2463  border-radius: 50%;
2464  background: rgba(255, 255, 255, 0.08);
2465  color: rgba(255, 255, 255, 0.7);
2466  font-size: 1.15rem;
2467  cursor: pointer;
2468  display: flex;
2469  align-items: center;
2470  justify-content: center;
2471  line-height: 1;
2472  transition: background 0.15s;
2473}
2474.app-popup-close:hover {
2475  background: rgba(255, 255, 255, 0.16);
2476  color: white;
2477}
2478.app-popup-icon {
2479  font-size: 2.2rem;
2480  color: #a78bfa;
2481  margin-bottom: 14px;
2482}
2483.app-popup-title {
2484  margin: 0 0 6px;
2485  font-size: 1.25rem;
2486  font-weight: 800;
2487  color: white;
2488  letter-spacing: -0.01em;
2489}
2490.app-popup-copy {
2491  margin: 0 0 24px;
2492  font-size: 0.82rem;
2493  color: rgba(255, 255, 255, 0.55);
2494}
2495.app-popup-buttons {
2496  display: flex;
2497  flex-direction: column;
2498  gap: 10px;
2499}
2500.app-popup-btn {
2501  display: flex;
2502  align-items: center;
2503  gap: 12px;
2504  padding: 14px 20px;
2505  border-radius: 14px;
2506  text-decoration: none;
2507  color: white;
2508  font-family: "Nunito", system-ui, sans-serif;
2509  transition: all 0.18s ease;
2510}
2511.app-popup-btn i {
2512  font-size: 1.6rem;
2513  flex-shrink: 0;
2514  width: 28px;
2515  text-align: center;
2516}
2517.app-popup-btn span {
2518  display: flex;
2519  flex-direction: column;
2520  text-align: left;
2521  line-height: 1.2;
2522  font-size: 1rem;
2523  font-weight: 700;
2524}
2525.app-popup-btn span small {
2526  font-size: 0.65rem;
2527  font-weight: 500;
2528  color: rgba(255, 255, 255, 0.6);
2529  letter-spacing: 0.02em;
2530}
2531.app-popup-btn--apple {
2532  background: rgba(255, 255, 255, 0.1);
2533  border: 1px solid rgba(255, 255, 255, 0.15);
2534}
2535.app-popup-btn--apple:hover {
2536  background: rgba(255, 255, 255, 0.16);
2537  transform: translateY(-1px);
2538  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
2539}
2540.app-popup-btn--google {
2541  background: rgba(255, 255, 255, 0.1);
2542  border: 1px solid rgba(255, 255, 255, 0.15);
2543}
2544.app-popup-btn--google:hover {
2545  background: rgba(255, 255, 255, 0.16);
2546  transform: translateY(-1px);
2547  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
2548}
2549.app-popup-btn.is-disabled {
2550  cursor: not-allowed;
2551  opacity: 0.55;
2552  pointer-events: none;
2553  user-select: none;
2554}
2555.app-popup-btn.is-disabled:hover {
2556  background: rgba(255, 255, 255, 0.1);
2557  transform: none;
2558  box-shadow: none;
2559}
2560
2561/* Make the active nav link's indigo background fill the entire navbar
2562   height including the 1px bottom border, so there's no dark strip
2563   below it. */
2564.navbar-header .navbar { align-items: stretch; }
2565.navbar-header .nav-left,
2566.navbar-header .nav-left ul,
2567.navbar-header .nav-left li,
2568.navbar-header .nav-left li a {
2569  height: 100%;
2570  align-self: stretch;
2571}
2572.navbar-header .nav-left li a {
2573  box-sizing: border-box;
2574}
2575.navbar-header .active {
2576  margin-bottom: -1px;       /* overlap the 1px bottom border on the nav row */
2577}
2578
2579/* AssetMarketCap logo — bump removed in v5 refresh; logo now sits
2580   naturally in a compact 72px-height navbar instead of the old 180px
2581   black hero block. Margin handled by .logo-top rule in global.css. */
2582
2583/* ── Navbar overflow collapse — DISABLED ──────────────────────────────────
2584   FAQs / Support / Dark-mode always live in .nav-right. The overflow copy
2585   in .navbar-wrapper-actions stays hidden at every width. */
2586.navbar-wrapper-actions,
2587.nav-overflowed .navbar-wrapper-actions { display: none !important; }
2588.nav-overflowed .nav-right { display: flex !important; }
2589
2590/* ── Navbar hover dropdowns (Learn, Products) ─────────────────────────── */
2591/* Allow dropdowns to escape the nav ul, which sets overflow:hidden. */
2592.navbar-header ul { overflow: visible !important; }
2593.navbar-header .navbar { overflow: visible; }
2594.navbar-header .nav-left { overflow: visible; }
2595
2596.navbar-header li.nav-dropdown { position: relative; }
2597
2598.navbar-header li.nav-dropdown > .nav-dropdown-trigger {
2599  display: flex;
2600  align-items: center;
2601  gap: 6px;
2602  cursor: pointer;
2603}
2604.nav-dropdown-caret {
2605  font-size: 0.65em;
2606  opacity: 0.75;
2607  transition: transform 0.15s ease;
2608}
2609.navbar-header li.nav-dropdown:hover > .nav-dropdown-trigger .nav-dropdown-caret,
2610.navbar-header li.nav-dropdown:focus-within > .nav-dropdown-trigger .nav-dropdown-caret,
2611.navbar-header li.nav-dropdown.open > .nav-dropdown-trigger .nav-dropdown-caret {
2612  transform: rotate(180deg);
2613}
2614
2615.navbar-header .nav-dropdown-menu {
2616  position: absolute;
2617  top: 100%;
2618  left: 0;
2619  min-width: 220px;
2620  margin: 0;
2621  padding: 6px 0;
2622  list-style: none;
2623  display: none;
2624  /* Earlier rule `.navbar-header .nav-left ul { height: 100%; align-self: stretch }`
2625     pins the dropdown to the nav row's height — kill it so the menu grows
2626     to fit its items. */
2627  height: auto !important;
2628  align-self: auto !important;
2629  /* Force a vertical stack — .navbar-header ul sets flex-direction:row
2630     which would line items up horizontally with no background fill. */
2631  flex-direction: column !important;
2632  align-items: stretch !important;
2633  z-index: 1000;
2634  overflow: hidden;          /* keep rounded corners on hover backgrounds */
2635  /* Background / border / shadow handled by v5 refresh rules in global.css */
2636}
2637.navbar-header li.nav-dropdown:hover > .nav-dropdown-menu,
2638.navbar-header li.nav-dropdown:focus-within > .nav-dropdown-menu,
2639.navbar-header li.nav-dropdown.open > .nav-dropdown-menu {
2640  display: flex !important;
2641}
2642/* Inner LIs are block-level, not stretched flex children.
2643   Clobber the `.nav-left li { height: 100% }` rule from earlier so each
2644   item is just tall enough for its own anchor — otherwise every item is
2645   stretched to the row's height and the menu only shows the first one. */
2646.navbar-header .nav-dropdown-menu > li {
2647  display: block !important;
2648  width: 100%;
2649  height: auto !important;
2650  align-self: auto !important;
2651  align-items: initial;
2652  background: transparent;
2653}
2654.navbar-header .nav-dropdown-menu > li > a {
2655  display: block !important;
2656  width: 100%;
2657  height: auto !important;
2658  align-self: auto !important;
2659  font-size: 0.85rem !important;
2660  white-space: nowrap;
2661  text-align: left !important;
2662  /* Colors / padding / hover-bg handled by v5 refresh in global.css */
2663}
2664
2665/* Login / Register pill — visual styling moved to v5 refresh in
2666   global.css (Bitcoin orange). Inline rule kept minimal so the
2667   tap-highlight reset (mobile-specific) still applies. */
2668a.auth-link-primary {
2669  outline: none !important;
2670  text-decoration: none !important;
2671  -webkit-tap-highlight-color: transparent !important;
2672}
2673</style>
2674
2675
2676<style>
2677  .m-tabbar { display: none; }
2678  html.m-nav-on .m-tabbar { display: flex; }
2679  html.m-nav-on body { padding-bottom: 150px; }
2680  @media (max-width: 640px) {
2681    .m-tabbar { display: flex; }
2682    body { padding-bottom: 150px; }
2683  }
2684  /* Cookie banner is hidden entirely on phones (it covered the tab bar). */
2685  html.m-nav-on .cookie-banner { display: none !important; }
2686
2687  .m-tabbar {
2688    position: fixed; left: 0; right: 0; bottom: 0; z-index: 9000;
2689    background: var(--color-background, #ffffff);
2690    border-top: 1px solid var(--color-neutral-200, #e7eaee);
2691    padding-bottom: env(safe-area-inset-bottom, 0px);
2692    box-shadow: 0 -2px 16px rgba(0,0,0,0.12);
2693  }
2694  .m-tab {
2695    flex: 1; display: flex; flex-direction: column; align-items: center;
2696    justify-content: center; gap: 9px; padding: 22px 4px 18px;
2697    background: none; border: 0; cursor: pointer; text-decoration: none;
2698    color: var(--color-neutral-600, #555555); font-size: 1.45rem;
2699    font-weight: 600; font-family: inherit; line-height: 1;
2700  }
2701  .m-tab i { font-size: 3rem; }
2702  .m-tab.is-active { color: var(--color-primary, #6366f1); }
2703  html.dark-mode .m-tabbar { background: #1c1d22; border-top-color: #2a2d35; }
2704  html.dark-mode .m-tab { color: #a9adb6; }
2705
2706  .m-drawer-backdrop {
2707    display: none; position: fixed; inset: 0; z-index: 9500;
2708    background: rgba(0,0,0,0.5); opacity: 0; pointer-events: none;
2709    transition: opacity .2s ease;
2710  }
2711  .m-drawer-backdrop.open { display: block; opacity: 1; pointer-events: auto; }
2712  .m-drawer {
2713    display: flex; flex-direction: column; position: fixed; inset: 0;
2714    width: 100vw; z-index: 9600; overflow-y: auto;
2715    -webkit-overflow-scrolling: touch; background: var(--color-background, #ffffff);
2716    color: var(--color-text, #1d1d1f); transform: translateX(100%);
2717    transition: transform .25s ease;
2718  }
2719  .m-drawer.open { transform: translateX(0); }
2720  html.dark-mode .m-drawer { background: #1c1d22; color: #eeeeee; }
2721  .m-drawer-head {
2722    display: flex; align-items: center; justify-content: space-between;
2723    padding: 26px 28px; border-bottom: 1px solid var(--color-neutral-200, #e7eaee);
2724  }
2725  .m-drawer-head img { height: 56px; width: auto; }
2726  .m-drawer-head .nav-logo-img--dark { display: none; }
2727  html.dark-mode .m-drawer-head .nav-logo-img--light { display: none; }
2728  html.dark-mode .m-drawer-head .nav-logo-img--dark { display: inline; }
2729  .m-drawer-close {
2730    background: none; border: 0; font-size: 3.6rem; line-height: 1; color: inherit;
2731    cursor: pointer; padding: 0 12px;
2732  }
2733  .m-drawer-body { padding: 4px 0 60px; }
2734
2735  /* Accordion main menus (Learn / Products / Tools / Help) — tap to expand,
2736     mirroring the homepage nav dropdowns. */
2737  .m-acc {
2738    display: flex; align-items: center; justify-content: space-between; width: 100%;
2739    background: none; border: 0; cursor: pointer; font-family: inherit; text-align: left;
2740    color: inherit; padding: 24px 30px; font-size: 1.95rem; font-weight: 600;
2741    border-bottom: 1px solid var(--color-neutral-100, #eef0f2);
2742  }
2743  html.dark-mode .m-acc { border-bottom-color: #2a2d35; }
2744  .m-acc-caret { font-size: 1.4rem; opacity: .55; transition: transform .2s ease; margin-left: 14px; }
2745  .m-acc.open .m-acc-caret { transform: rotate(180deg); }
2746  .m-acc-panel { display: none; background: var(--color-neutral-50, #f7f8fa); }
2747  .m-acc-panel.open { display: block; }
2748  html.dark-mode .m-acc-panel { background: rgba(255,255,255,0.035); }
2749  .m-acc-panel .m-link { padding: 18px 30px 18px 48px; font-size: 1.65rem; }
2750
2751  /* Top-level standalone links (Pricing, API) styled like the accordion rows. */
2752  .m-link-top {
2753    display: block; padding: 24px 30px; color: inherit; text-decoration: none;
2754    font-size: 1.95rem; font-weight: 600;
2755    border-bottom: 1px solid var(--color-neutral-100, #eef0f2);
2756  }
2757  html.dark-mode .m-link-top { border-bottom-color: #2a2d35; }
2758
2759  .m-link { display: block; padding: 22px 30px; color: inherit; text-decoration: none; font-size: 1.9rem; }
2760  .m-link:active, .m-link:hover { background: var(--color-neutral-100, #f3f4f6); }
2761  html.dark-mode .m-link:active, html.dark-mode .m-link:hover { background: #26282f; }
2762  .m-sec-title {
2763    font-size: 1.3rem; text-transform: uppercase; letter-spacing: .05em;
2764    color: var(--color-neutral-500, #888888); padding: 30px 30px 10px; font-weight: 700;
2765  }
2766  .m-auth { display: flex; flex-direction: column; gap: 14px; padding: 26px 30px 10px; }
2767  .m-btn { display: block; text-align: center; padding: 22px; border-radius: 12px;
2768    font-weight: 700; text-decoration: none; font-size: 1.8rem; }
2769  .m-btn-primary { background: var(--color-primary, #6366f1); color: #ffffff; }
2770  .m-btn-ghost { border: 1px solid var(--color-neutral-300, #cccccc); color: inherit; }
2771  .m-util { display: flex; flex-wrap: wrap; gap: 12px; padding: 12px 30px 0; align-items: center; }
2772  .m-util select { flex: 1; min-width: 150px; padding: 16px; border-radius: 8px; font-family: inherit; font-size: 1.4rem;
2773    border: 1px solid var(--color-neutral-300, #cccccc); background: var(--color-background, #fff); color: inherit; }
2774  .m-theme { display: flex; gap: 10px; width: 100%; }
2775  .m-theme button { flex: 1; padding: 16px; border-radius: 8px; cursor: pointer; font-size: 1.3rem;
2776    border: 1px solid var(--color-neutral-300, #cccccc); background: none; color: inherit; font-family: inherit; }
2777  .m-theme button.active { border-color: var(--color-primary, #6366f1); color: var(--color-primary, #6366f1); }
2778
2779  .m-search { display: none; position: fixed; inset: 0; z-index: 9700; background: var(--color-background, #fff); }
2780  .m-search.open { display: block; }
2781  html.dark-mode .m-search { background: #1c1d22; }
2782  .m-search-bar { display: flex; align-items: center; gap: 14px; padding: 24px 24px;
2783    border-bottom: 1px solid var(--color-neutral-200, #e7eaee); }
2784  .m-search-bar input { flex: 1; padding: 20px; font-size: 1.7rem; border-radius: 12px; font-family: inherit;
2785    border: 1px solid var(--color-neutral-300, #cccccc); background: var(--color-background, #fff); color: inherit; }
2786  .m-search-cancel { background: none; border: 0; color: var(--color-primary, #6366f1); font-weight: 600; cursor: pointer; font-size: 1.6rem; }
2787</style>
2788
2789<nav class="m-tabbar" aria-label="Mobile navigation">
2790  <a class="m-tab " href="/"><i class="fa-solid fa-house" aria-hidden="true"></i><span>Home</span></a>
2791  <a class="m-tab " href="/net-worth-tracker"><i class="fa-solid fa-chart-line" aria-hidden="true"></i><span>Net-Worth</span></a>
2792  <button class="m-tab" type="button" id="mTabSearch"><i class="fa-solid fa-magnifying-glass" aria-hidden="true"></i><span>Search</span></button>
2793  
2794  <a class="m-tab" href="/login?view=register"><i class="fa-solid fa-user-plus" aria-hidden="true"></i><span>Sign Up</span></a>
2795  
2796  <button class="m-tab" type="button" id="mTabMenu"><i class="fa-solid fa-bars" aria-hidden="true"></i><span>Menu</span></button>
2797</nav>
2798
2799<div class="m-drawer-backdrop" id="mDrawerBackdrop"></div>
2800<aside class="m-drawer" id="mDrawer" aria-label="Menu" aria-hidden="true">
2801  <div class="m-drawer-head">
2802    <a href="/" aria-label="AssetMarketCap home">
2803      <img src="/static/logo.png" class="nav-logo-img--light" alt="AssetMarketCap">
2804      <img src="/static/logo-dark.png" class="nav-logo-img--dark" alt="" aria-hidden="true">
2805    </a>
2806    <button class="m-drawer-close" id="mDrawerClose" type="button" aria-label="Close menu">&times;</button>
2807  </div>
2808  <div class="m-drawer-body">
2809    <button class="m-acc" type="button" aria-expanded="false">Learn <i class="fa-solid fa-chevron-down m-acc-caret" aria-hidden="true"></i></button>
2810    <div class="m-acc-panel">
2811      <a class="m-link" href="/learn">Education Articles</a>
2812      <a class="m-link" href="/news">Latest News</a>
2813      <a class="m-link" href="/deals">Deals</a>
2814    </div>
2815
2816    <button class="m-acc" type="button" aria-expanded="false">Products <i class="fa-solid fa-chevron-down m-acc-caret" aria-hidden="true"></i></button>
2817    <div class="m-acc-panel">
2818      <a class="m-link" href="/pro">Pro</a>
2819      <a class="m-link" href="https://merch.assetmarketcap.com">Merchandise</a>
2820    </div>
2821
2822    <button class="m-acc" type="button" aria-expanded="false">Tools <i class="fa-solid fa-chevron-down m-acc-caret" aria-hidden="true"></i></button>
2823    <div class="m-acc-panel">
2824      <a class="m-link" href="/flippener">Flippener Tool</a>
2825      <a class="m-link" href="/compare">Comparator Tool</a>
2826      <a class="m-link" href="/net-worth-tracker">Net-Worth Tracker</a>
2827    </div>
2828
2829    <a class="m-link-top" href="/pricing">Pricing</a>
2830    <a class="m-link-top" href="/api-info">API</a>
2831    <a class="m-link-top" href="/advertise">Advertise</a>
2832
2833    <button class="m-acc" type="button" aria-expanded="false">Help <i class="fa-solid fa-chevron-down m-acc-caret" aria-hidden="true"></i></button>
2834    <div class="m-acc-panel">
2835      <a class="m-link" href="/faqs">FAQs</a>
2836      <a class="m-link" href="/support">Support</a>
2837      <a class="m-link" href="https://play.google.com/store/apps/details?id=com.assetmarketcap.app">Get the App</a>
2838    </div>
2839
2840    
2841    <div class="m-auth">
2842      <a class="m-btn m-btn-primary" href="/login?view=register">Create account</a>
2843      <a class="m-btn m-btn-ghost" href="/login">Log in</a>
2844    </div>
2845    
2846
2847    <div class="m-sec-title">Settings</div>
2848    <div class="m-util">
2849      <select id="mCurrency" aria-label="Currency">
2850        <option value="USD">USD ($)</option>
2851        <option value="GOLD">Gold (oz)</option>
2852        <option value="BTC">Bitcoin</option>
2853        <option value="SATS">Bitcoin (sats)</option>
2854      </select>
2855      <select aria-label="Language"><option selected>English</option></select>
2856    </div>
2857    <div class="m-util">
2858      <div class="m-theme" id="mTheme">
2859        <button type="button" data-theme="light">Light</button>
2860        <button type="button" data-theme="dark">Dark</button>
2861        <button type="button" data-theme="system">System</button>
2862      </div>
2863    </div>
2864  </div>
2865</aside>
2866
2867<div class="m-search" id="mSearch">
2868  <form class="m-search-bar" role="search" action="/search" method="GET">
2869    <input type="search" name="q" id="mSearchInput" placeholder="Search assets, articles, news..." aria-label="Search" autocomplete="off">
2870    <button class="m-search-cancel" type="button" id="mSearchCancel">Cancel</button>
2871  </form>
2872</div>
2873
2874<script>
2875(function () {
2876  try {
2877    var touch = ("ontouchstart" in window) || (navigator.maxTouchPoints || 0) > 0;
2878    var minDim = Math.min(window.screen.width || 9999, window.screen.height || 9999);
2879    if (touch && minDim <= 700) document.documentElement.classList.add("m-nav-on");
2880  } catch (e) {}
2881
2882  var drawer = document.getElementById('mDrawer'),
2883      backdrop = document.getElementById('mDrawerBackdrop');
2884  function openDrawer() {
2885    drawer.classList.add('open'); backdrop.classList.add('open');
2886    drawer.setAttribute('aria-hidden', 'false'); document.body.style.overflow = 'hidden';
2887  }
2888  function closeDrawer() {
2889    drawer.classList.remove('open'); backdrop.classList.remove('open');
2890    drawer.setAttribute('aria-hidden', 'true'); document.body.style.overflow = '';
2891  }
2892  var menuBtn = document.getElementById('mTabMenu');
2893  if (menuBtn) menuBtn.addEventListener('click', openDrawer);
2894  var closeBtn = document.getElementById('mDrawerClose');
2895  if (closeBtn) closeBtn.addEventListener('click', closeDrawer);
2896  if (backdrop) backdrop.addEventListener('click', closeDrawer);
2897
2898  // Accordion main menus (Learn / Products / Tools / Help).
2899  Array.prototype.forEach.call(document.querySelectorAll('#mDrawer .m-acc'), function (btn) {
2900    btn.addEventListener('click', function () {
2901      var panel = btn.nextElementSibling;
2902      var willOpen = !btn.classList.contains('open');
2903      btn.classList.toggle('open', willOpen);
2904      btn.setAttribute('aria-expanded', willOpen ? 'true' : 'false');
2905      if (panel && panel.classList.contains('m-acc-panel')) panel.classList.toggle('open', willOpen);
2906    });
2907  });
2908
2909  var srch = document.getElementById('mSearch'),
2910      sBtn = document.getElementById('mTabSearch'),
2911      sCancel = document.getElementById('mSearchCancel'),
2912      sInput = document.getElementById('mSearchInput');
2913  if (sBtn) sBtn.addEventListener('click', function () {
2914    srch.classList.add('open');
2915    if (sInput) setTimeout(function () { sInput.focus(); }, 50);
2916  });
2917  if (sCancel) sCancel.addEventListener('click', function () { srch.classList.remove('open'); });
2918
2919  var mc = document.getElementById('mCurrency'),
2920      real = document.getElementById('unit-select');
2921  if (mc && real) {
2922    mc.value = real.value || 'USD';
2923    mc.addEventListener('change', function () {
2924      real.value = mc.value;
2925      real.dispatchEvent(new Event('change', { bubbles: true }));
2926    });
2927  }
2928
2929  var mt = document.getElementById('mTheme');
2930  if (mt) {
2931    mt.addEventListener('click', function (e) {
2932      var b = e.target.closest('button[data-theme]');
2933      if (!b) return;
2934      var t = b.dataset.theme;
2935      try {
2936        // Record the choice in theme_mode (the key header.html's bootTheme reads);
2937        // the legacy prefers_dark_mode key is kept in sync for older code paths.
2938        // Without the explicit 'system' write, picking System would fall through
2939        // to the default on reload - which is now 'light', not 'system'.
2940        if (t === 'dark') { localStorage.setItem('theme_mode', 'dark'); localStorage.setItem('prefers_dark_mode', '1'); document.documentElement.classList.add('dark-mode'); }
2941        else if (t === 'light') { localStorage.setItem('theme_mode', 'light'); localStorage.setItem('prefers_dark_mode', '0'); document.documentElement.classList.remove('dark-mode'); }
2942        else { localStorage.setItem('theme_mode', 'system'); localStorage.removeItem('prefers_dark_mode');
2943               var d = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
2944               document.documentElement.classList.toggle('dark-mode', !!d); }
2945      } catch (_) {}
2946      mt.querySelectorAll('button').forEach(function (x) { x.classList.toggle('active', x === b); });
2947    });
2948  }
2949})();
2950</script>
2950
2951
2952  <main class="x-page">
2953
2954    <!-- BILLING TOGGLE (above plan cards) =============== -->
2955    <section class="x-band" aria-label="Billing interval" style="padding: 100px 0 36px;">
2956      <div class="x-wrap" style="display: flex; align-items: center; gap: 14px; justify-content: center; flex-wrap: wrap;">
2957        <div class="x-bill" id="xBilling" role="tablist" aria-label="Billing interval">
2958          <div class="x-bill-thumb" id="xBillThumb"></div>
2959          <button type="button" class="is-on" data-interval="monthly" role="tab" aria-selected="true">Monthly</button>
2960          <button type="button" data-interval="annual" role="tab" aria-selected="false">Annual</button>
2961        </div>
2962        <span class="x-bill-save">Save ~17% annually</span>
2963      </div>
2964    </section>
2965
2966    <!-- PLAN CARDS ======================================== -->
2967    <section class="x-band" aria-label="Plan options" style="padding: 0 0 90px;">
2968      <div class="x-wrap">
2969        <div class="x-plans">
2970
2971          <article class="x-plan">
2972            <div class="x-plan-name">Free</div>
2973            <div class="x-plan-price">
2974              <span class="x-plan-amt">$0</span>
2975              <span class="x-plan-per">forever</span>
2976            </div>
2977            <p class="x-plan-tag-line">The full dataset, no strings. Browse 35,000+ assets, no card required.</p>
2978            <ul class="x-plan-feats">
2979              <li>35,000+ assets, live</li>
2980              <li>Full market cap rankings</li>
2981              <li>Flippener &amp; comparator (limited)</li>
2982              <li>Up to 3 favourites</li>
2983              <li>Net Worth Tracker - 5 assets, daily prices</li>
2984              <li>Top 100 JSON / CSV downloads (signed in)</li>
2985            </ul>
2986            <div class="x-plan-cta-wrap">
2987              <a href="/" class="x-cta x-cta--ghost">Browse free</a>
2988            </div>
2989          </article>
2990
2991          <article class="x-plan x-plan--featured"
2992                   data-plan="pro"
2993                   data-monthly-amount="3.99" data-monthly-period="/mo"
2994                   data-annual-amount="39.99" data-annual-period="/yr"
2995                   data-cta-monthly="Subscribe to Pro - $3.99/mo"
2996                   data-cta-annual="Subscribe to Pro - $39.99/yr">
2997            <span class="x-plan-tag">Most popular</span>
2998            <div class="x-plan-name">Pro</div>
2999            <div class="x-plan-price">
3000              <span class="x-plan-cur">$</span>
3001              <span class="x-plan-amt" data-price-amount>3.99</span>
3002              <span class="x-plan-per" data-price-period>/mo</span>
3003            </div>
3004            <p class="x-plan-tag-line">Ad-free, premium news, premium education. The sweet spot for everyday use.</p>
3005            <ul class="x-plan-feats">
3006              <li>Everything in Free</li>
3007              <li>Ad-free mobile app experience</li>
3008              <li>Filter by Country &amp; Sector</li>
3009              <li>Premium news articles &amp; videos</li>
3010              <li>Premium education guides</li>
3011              <li>Up to 50 favourites &amp; 30 flippenings / mo</li>
3012              <li>Net Worth Tracker - 10 assets, live prices</li>
3013              <li>Time Machine - rewind the table up to 1 year</li>
3014              <li>1 table screenshot per day</li>
3015              <li>Top 100 JSON / CSV downloads</li>
3016            </ul>
3017            <div class="x-plan-cta-wrap">
3018              
3019                <a href="/login?view=register&amp;next=/pricing" class="x-cta">Get Pro</a>
3020              
3021            </div>
3022          </article>
3023
3024          <article class="x-plan"
3025                   data-plan="pro-plus"
3026                   data-monthly-amount="9.99" data-monthly-period="/mo"
3027                   data-annual-amount="99.99" data-annual-period="/yr"
3028                   data-cta-monthly="Subscribe to Pro Plus - $9.99/mo"
3029                   data-cta-annual="Subscribe to Pro Plus - $99.99/yr">
3030            <div class="x-plan-name">Pro Plus</div>
3031            <div class="x-plan-price">
3032              <span class="x-plan-cur">$</span>
3033              <span class="x-plan-amt" data-price-amount>9.99</span>
3034              <span class="x-plan-per" data-price-period>/mo</span>
3035            </div>
3036            <p class="x-plan-tag-line">Everything in Pro plus unlimited tools and exclusive research. For power users.</p>
3037            <ul class="x-plan-feats">
3038              <li>Everything in Pro</li>
3039              <li>Unlimited favourites</li>
3040              <li>Unlimited flippener &amp; comparator</li>
3041              <li>Net Worth Tracker - unlimited assets, live prices</li>
3042              <li>Time Machine - full archive back to 2010 (15+ years)</li>
3043              <li>Unlimited table screenshots</li>
3044              <li>Full 35k+ JSON / CSV downloads</li>
3045              <li>Exclusive research reports</li>
3046              <li>Priority support</li>
3047              <li>Early access to new features</li>
3048            </ul>
3049            <div class="x-plan-cta-wrap">
3050              
3051                <a href="/login?view=register&amp;next=/pricing" class="x-cta">Get Pro Plus</a>
3052              
3053            </div>
3054          </article>
3055
3056        </div>
3057
3058        <p style="text-align:center; margin-top:18px;">
3059          <button type="button" class="x-link iap-restore" hidden
3060                  style="background:none; border:none; cursor:pointer; display:none;">Restore purchases</button>
3061        </p>
3062
3063        <p class="x-sub-legal" style="text-align:center; margin-top:18px; font-size:0.82rem; line-height:1.5; opacity:.72;">
3064          <span data-native-billing-only hidden>
3065            Payment is charged to your Apple Account at confirmation of purchase.
3066            The subscription renews automatically for the same period unless it is
3067            cancelled at least 24 hours before the end of the current period. Manage
3068            or cancel it in Settings &rsaquo; Apple Account &rsaquo; Subscriptions.
3069            <br>
3070            <a href="https://www.apple.com/legal/internet-services/itunes/dev/stdeula/">Terms of Use (EULA)</a>
3071            &middot;
3072            <a href="/privacy">Privacy Policy</a>
3073          </span>
3074          <span data-web-billing-only>
3075            Subscriptions renew automatically until cancelled. Cancel anytime from your account.
3076            &middot;
3077            <a href="/privacy">Privacy Policy</a>
3078          </span>
3079        </p>
3080      </div>
3081    </section>
3082
3083    <!-- PRICING INTRO (moved below the plan cards) ====== -->
3084    <section class="x-band--soft x-sec" aria-label="Pricing intro">
3085      <div class="x-wrap">
3086        <p class="x-eyebrow"><strong>Plans &amp; pricing.</strong></p>
3087        <h1 class="x-h1">Simple pricing.<br>Made for serious investors.</h1>
3088        <p class="x-lede" style="margin-bottom: 0;">The full 35,000+ asset dataset is free, forever. Upgrade for ad-free browsing, premium news, premium research, and unlimited tools - cancel anytime.</p>
3089      </div>
3090    </section>
3091
3092    <!-- PERSONAS ========================================== -->
3093    <section class="x-band x-sec" aria-label="Which plan fits you">
3094      <div class="x-wrap">
3095        <p class="x-eyebrow">Not sure which to pick?</p>
3096        <h2 class="x-h2">Choose the plan that matches how you actually use the app.</h2>
3097        <p class="x-sub">Three quick personas. Pick the one that sounds most like you.</p>
3098
3099        <div class="x-personas">
3100          <div class="x-persona">
3101            <div class="x-persona-ico">
3102              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
3103            </div>
3104            <div class="x-persona-label">Free</div>
3105            <h3>The casual checker</h3>
3106            <p>You glance at Bitcoin and a handful of stocks a few times a month. You don't need filters or research - just a clean ranked list.</p>
3107            <a href="/" class="x-link">Browse free</a>
3108          </div>
3109          <div class="x-persona">
3110            <div class="x-persona-ico">
3111              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v18h18"/><path d="M7 13l3-3 4 4 5-5"/></svg>
3112            </div>
3113            <div class="x-persona-label">Pro</div>
3114            <h3>The everyday investor</h3>
3115            <p>You're in the app weekly. You want ads gone, country/sector filters, and premium news that doesn't waste your time.</p>
3116            <a href="#plans" class="x-link">Get Pro</a>
3117          </div>
3118          <div class="x-persona">
3119            <div class="x-persona-ico">
3120              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>
3121            </div>
3122            <div class="x-persona-label">Pro Plus</div>
3123            <h3>The power user</h3>
3124            <p>You're running flippenings and comparisons daily. You want exclusive monthly research and a human on priority support.</p>
3125            <a href="#plans" class="x-link">Get Pro Plus</a>
3126          </div>
3127        </div>
3128      </div>
3129    </section>
3130
3131    <!-- COMPARE TABLE ==================================== -->
3132    <section class="x-band--soft x-sec" aria-label="Feature comparison">
3133      <div class="x-wrap">
3134        <p class="x-eyebrow">Side by side</p>
3135        <h2 class="x-h2">Every feature, every plan.</h2>
3136        <p class="x-sub">No surprises at checkout. Everything that's in each plan, laid out cleanly.</p>
3137
3138        <div class="x-compare">
3139          <table class="x-ct">
3140            <thead>
3141              <tr>
3142                <th>Feature</th>
3143                <th>Free</th>
3144                <th class="is-feat">Pro</th>
3145                <th>Pro Plus</th>
3146              </tr>
3147            </thead>
3148            <tbody>
3149              <tr><td>35,000+ assets</td>           <td><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td><td class="is-feat"><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td><td><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td></tr>
3150              <tr><td>Live market cap rankings</td> <td><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td><td class="is-feat"><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td><td><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td></tr>
3151              <tr><td>Education library</td>        <td><span class="x-cross">&mdash;</span></td><td class="is-feat"><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td><td><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td></tr>
3152              <tr><td>Country &amp; sector filters</td><td><span class="x-cross">&mdash;</span></td><td class="is-feat"><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td><td><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td></tr>
3153              <tr><td>Ad-free mobile app</td>       <td><span class="x-cross">&mdash;</span></td><td class="is-feat"><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td><td><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td></tr>
3154              <tr><td>Premium news articles &amp; videos</td><td><span class="x-cross">&mdash;</span></td><td class="is-feat"><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td><td><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td></tr>
3155              <tr><td>Premium education &amp; research</td><td><span class="x-cross">&mdash;</span></td><td class="is-feat"><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td><td>
3155<span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td></tr>
3156              <tr><td>Exclusive research reports</td><td><span class="x-cross">&mdash;</span></td><td class="is-feat"><span class="x-cross">&mdash;</span></td><td><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td></tr>
3157              <tr><td>Priority support</td>         <td><span class="x-cross">&mdash;</span></td><td class="is-feat"><span class="x-cross">&mdash;</span></td><td><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td></tr>
3158              <tr><td>Favourites</td>      <td class="x-pill-cell">3</td>        <td class="is-feat x-pill-cell">50 / mo</td>  <td><span class="x-pill-cell--good">Unlimited</span></td></tr>
3159              <tr><td>Flippener tool</td>  <td class="x-pill-cell">3</td>        <td class="is-feat x-pill-cell">30 / mo</td>  <td><span class="x-pill-cell--good">Unlimited</span></td></tr>
3160              <tr><td>Comparator tool</td> <td class="x-pill-cell">3</td>        <td class="is-feat x-pill-cell">15 / mo</td>  <td><span class="x-pill-cell--good">Unlimited</span></td></tr>
3161              <tr><td>Net Worth Tracker</td><td class="x-pill-cell">5 assets, daily</td><td class="is-feat x-pill-cell">10 assets, live</td><td><span class="x-pill-cell--good">Unlimited, live</span></td></tr>
3162              <tr><td>Time Machine</td><td><span class="x-cross">&mdash;</span></td><td class="is-feat x-pill-cell">1 year back</td><td><span class="x-pill-cell--good">Back to 2010 (15+ years)</span></td></tr>
3163              <tr><td>Table screenshots</td><td><span class="x-cross">&mdash;</span></td><td class="is-feat x-pill-cell">1 / day</td><td><span class="x-pill-cell--good">Unlimited</span></td></tr>
3164              <tr><td>Top 100 JSON / CSV download</td><td class="x-pill-cell">Signed in</td><td class="is-feat"><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td><td><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td></tr>
3165              <tr><td>Full 35k JSON / CSV download</td><td><span class="x-cross">&mdash;</span></td><td class="is-feat"><span class="x-cross">&mdash;</span></td><td><span class="x-tick"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span></td></tr>
3166              <tr>
3167                <td><strong>Price</strong></td>
3168                <td class="x-pill-cell">Free</td>
3169                <td class="is-feat x-pill-cell"><span data-compare-pro>$3.99/mo</span></td>
3170                <td class="x-pill-cell"><span data-compare-proplus>$9.99/mo</span></td>
3171              </tr>
3172            </tbody>
3173          </table>
3174        </div>
3175      </div>
3176    </section>
3177
3178    <!-- FAQ =============================================== -->
3179    <section class="x-band x-sec" aria-label="Questions answered">
3180      <div class="x-wrap">
3181        <p class="x-eyebrow">Questions</p>
3182        <h2 class="x-h2">Everything you might want to know.</h2>
3183        <p class="x-sub">Quick answers to the most common questions before subscribing.</p>
3184
3185        <div class="x-faq">
3186          <details class="x-faq-item">
3187            <summary>Is the free plan actually free?<i class="x-faq-icon"></i></summary>
3188            <div class="x-faq-body">Yes. All 35,000+ assets, full rankings, and the core tools (Flippener, Comparator) are free with no credit card. The free plan caps a few power-user features so you can decide whether Pro is worth it.</div>
3189          </details>
3190          <details class="x-faq-item">
3191            <summary>Can I cancel any time?<i class="x-faq-icon"></i></summary>
3192            <div class="x-faq-body">Of course. Subscriptions are managed through Stripe - open your account page and hit "Manage billing" to cancel, pause, or change plan. No emails, no friction.</div>
3193          </details>
3194          <details class="x-faq-item">
3195            <summary>Monthly vs. annual - what's the difference?<i class="x-faq-icon"></i></summary>
3196            <div class="x-faq-body">Annual billing saves about 17% vs. paying monthly. Same features, just tw
3196o months free if you commit for a year.</div>
3197          </details>
3198          <details class="x-faq-item">
3199            <summary>What's the difference between Pro and Pro Plus?<i class="x-faq-icon"></i></summary>
3200            <div class="x-faq-body">Pro removes ads, unlocks premium news + education, and unlocks country/sector filters with generous monthly limits on favourites, flippenings, and comparisons. Pro Plus removes those limits entirely and adds exclusive research reports + priority support.</div>
3201          </details>
3202          <details class="x-faq-item">
3203            <summary>Do you offer student or non-profit pricing?<i class="x-faq-icon"></i></summary>
3204            <div class="x-faq-body">Not formally yet - but if you're a student, journalist, or non-profit and want to use the data, email us through the contact form and we'll figure something out.</div>
3205          </details>
3206          <details class="x-faq-item">
3207            <summary>How is my data handled?<i class="x-faq-icon"></i></summary>
3208            <div class="x-faq-body">Payments are processed by Stripe - we never see your card details. Your account stores an email and a hashed password and nothing else. See the privacy page for the full picture.</div>
3209          </details>
3210        </div>
3211      </div>
3212    </section>
3213
3214    <!-- FINAL ============================================ -->
3215    <section class="x-band" aria-label="Sign up">
3216      <div class="x-final">
3217        <h2>Start with Free.<br>Upgrade when it pays off.</h2>
3218        <p>Create a free account in under 30 seconds - no card needed. Pro and Pro Plus are one click away.</p>
3219        <div class="x-final-cta">
3220          
3221            <a href="/login?view=register&amp;next=/pricing" class="x-cta x-cta--lg">Create free account</a>
3222            <a href="/login" class="x-link">Log in</a>
3223          
3224        </div>
3225      </div>
3226      <p class="x-disclaimer">
3227        Not financial advice. Market data is provided for informational purposes only.
3228        Prices shown in USD. Taxes may apply based on your billing region.
3229      </p>
3230    </section>
3231
3232  </main>
3233
3234  
3235
3236<style>
3237  .upper-footer-press {
3238    clear: both;
3239    display: flow-root;
3240    float: none;
3241    width: 100%;
3242    margin-top: 0;
3243    margin-bottom: 0;
3244  }
3245  .upper-footer-press::after {
3246    content: "";
3247    display: table;
3248    clear: both;
3249  }
3250  .upper-footer-press .header-press-strip {
3251    float: none;
3252    clear: both;
3253    width: calc(83.33333333% - 30px);
3254    max-width: 1558px;
3255    margin-left: auto;
3256    margin-right: auto;
3257    margin-bottom: 15px !important;
3258    background: transparent;
3259  }
3260  .upper-footer-press + .webintern-footer {
3261    margin-top: 0;
3262  }
3263  @media (max-width: 700px) {
3264    .upper-footer-press {
3265      margin-top: 0;
3266    }
3267    .upper-footer-press .header-press-strip {
3268      width: calc(100% - 24px);
3269    }
3270  }
3271
3272/* Subscribe button visual styling moved to v5 refresh in global.css
3273   (Bitcoin orange to match Login/Register pill and cookie Accept). */
3274
3275/* Inline subscribe form — email input + Subscribe button side by side,
3276   replacing the old modal trigger. */
3277.footer-subscribe-form {
3278  display: flex;
3279  align-items: stretch;
3280  gap: 8px;
3281  margin-top: 10px;
3282  max-width: 420px;
3283}
3284.footer-subscribe-input {
3285  flex: 1 1 auto;
3286  min-width: 0;
3287  padding: 10px 14px;
3288  border-radius: 999px;
3289  border: 1px solid rgba(255, 255, 255, 0.18);
3290  background: rgba(255, 255, 255, 0.06);
3291  color: #fff;
3292  font-size: 0.85rem;
3293  outline: none;
3294  transition: border-color 0.15s ease, background 0.15s ease;
3295}
3296.footer-subscribe-input::placeholder { color: rgba(255,255,255,0.30); }
3297.footer-subscribe-input:focus {
3298  border-color: rgba(124, 58, 237, 0.7);
3299  background: rgba(255, 255, 255, 0.10);
3300}
3301.footer-subscribe-btn {
3302  flex: 0 0 auto;
3303  padding: 10px 22px !important;
3304  border-radius: 999px !important;
3305  font-size: 0.85rem;
3306  cursor: pointer;
3307  display: inline-flex;
3308  align-items: center;
3309  justify-content: center;
3310  line-height: 1;
3311}
3312</style>
3313<div class="upper-footer-press">
3314  <div class="header-press-strip" role="region" aria-label="As seen on">
3315    <div class="header-press-strip__title">&mdash;&mdash; As Seen On &mdash;&mdash;</div>
3316    <div class="header-press-row" aria-hidden="true">
3317      <div class="header-press-carousel">
3318        <div class="header-press-track">
3319          
3320            <div class="header-press-set">
3321              
3322                
3323                <img src="/static/asSeenOn/abc-news.png" alt="abc news" class="header-press-logo" decoding="async">
3324              
3325                
3326                <img src="/static/asSeenOn/AP-news.png" alt="AP news" class="header-press-logo" decoding="async">
3327              
3328                
3329                <img src="/static/asSeenOn/CBS-news-logo.png" alt="CBS news logo" class="header-press-logo" decoding="async">
3330              
3331                
3332                <img src="/static/asSeenOn/fox-news-logo.png" alt="fox news logo" class="header-press-logo" decoding="async">
3333              
3334                
3335                <img src="/static/asSeenOn/international-business-times-uk-logo.jpg" alt="international business times uk logo" class="header-press-logo" decoding="async">
3336              
3337                
3338                <img src="/static/asSeenOn/MorningNews-logo.png" alt="MorningNews logo" class="header-press-logo" decoding="async">
3339              
3340                
3341                <img src="/static/asSeenOn/NBC-logo.png" alt="NBC logo" class="header-press-logo" decoding="async">
3342              
3343                
3344                <img src="/static/asSeenOn/USA-News-logo.jpg" alt="USA News logo" class="header-press-logo" decoding="async">
3345              
3346            </div>
3347          
3348            <div class="header-press-set">
3349              
3350                
3351                <img src="/static/asSeenOn/abc-news.png" alt="abc news" class="header-press-logo" decoding="async">
3352              
3353                
3354                <img src="/static/asSeenOn/AP-news.png" alt="AP news" class="header-press-logo" decoding="async">
3355              
3356                
3357                <img src="/static/asSeenOn/CBS-news-logo.png" alt="CBS news logo" class="header-press-logo" decoding="async">
3358              
3359                
3360                <img src="/static/asSeenOn/fox-news-logo.png" alt="fox news logo" class="header-press-logo" decoding="async">
3361              
3362                
3363                <img src="/static/asSeenOn/international-business-times-uk-logo.jpg" alt="international business times uk logo" class="header-press-logo" decoding="async">
3364              
3365                
3366                <img src="/static/asSeenOn/MorningNews-logo.png" alt="MorningNews logo" class="header-press-logo" decoding="async">
3367              
3368                
3369                <img src="/static/asSeenOn/NBC-logo.png" alt="NBC logo" class="header-press-logo" decoding="async">
3370              
3371                
3372                <img src="/static/asSeenOn/USA-News-logo.jpg" alt="USA News logo" class="header-press-logo" decoding="async">
3373              
3374            </div>
3375          
3376            <div class="header-press-set">
3377              
3378                
3379                <img src="/static/asSeenOn/abc-news.png" alt="abc news" class="header-press-logo" decoding="async">
3380              
3381                
3382                <img src="/static/asSeenOn/AP-news.png" alt="AP news" class="header-press-logo" decoding="async">
3383              
3384                
3385                <img src="/static/asSeenOn/CBS-news-logo.png" alt="CBS news logo" class="header-press-logo" decoding="async">
3386              
3387                
3388                <img src="/static/asSeenOn/fox-news-logo.png" alt="fox news logo" class="header-press-logo" decoding="async">
3389              
3390                
3391                <img src="/static/asSeenOn/international-business-times-uk-logo.jpg" alt="international business times uk logo" class="header-press-logo" decoding="async">
3392              
3393                
3394                <img src="/static/asSeenOn/MorningNews-logo.png" alt="MorningNews logo" class="header-press-logo" decoding="async">
3395              
3396                
3397                <img src="/static/asSeenOn/NBC-logo.png" alt="NBC logo" class="header-press-logo" decoding="async">
3398              
3399                
3400                <img src="/static/asSeenOn/USA-News-logo.jpg" alt="USA News logo" class="header-press-logo" decoding="async">
3401              
3402            </div>
3403          
3404            <div class="header-press-set">
3405              
3406                
3407                <img src="/static/asSeenOn/abc-news.png" alt="abc news" class="header-press-logo" decoding="async">
3408              
3409                
3410                <img src="/static/asSeenOn/AP-news.png" alt="AP news" class="header-press-logo" decoding="async">
3411              
3412                
3413                <img src="/static/asSeenOn/CBS-news-logo.png" alt="CBS news logo" class="header-press-logo" decoding="async">
3414              
3415                
3416                <img src="/static/asSeenOn/fox-news-logo.png" alt="fox news logo" class="header-press-logo" decoding="async">
3417              
3418                
3419                <img src="/static/asSeenOn/international-business-times-uk-logo.jpg" alt="international business times uk logo" class="header-press-logo" decoding="async">
3420              
3421                
3422                <img src="/static/asSeenOn/MorningNews-logo.png" alt="MorningNews logo" class="header-press-logo" decoding="async">
3423              
3424                
3425                <img src="/static/asSeenOn/NBC-logo.png" alt="NBC logo" class="header-press-logo" decoding="async">
3426              
3427                
3428                <img src="/static/asSeenOn/USA-News-logo.jpg" alt="USA News logo" class="header-press-logo" decoding="async">
3429              
3430            </div>
3431          
3432        </div>
3433      </div>
3434    </div>
3435  </div>
3436</div>
3437
3438
3439<footer class="webintern-footer">
3440
3441  <div class="webintern-footer-inner">
3442    <div class="footer-grid">
3443
3444      <!-- Column 1: Logo + methodology -->
3445      <div class="footer-col footer-brand">
3446        <a href="/">
3447          <img src="/static/logo-dark.png" class="logo-bottom" width="200" height="33" alt="AssetMarketCap" loading="lazy">
3448        </a>
3449        <p class="footer-blurb">Market capitalization is typically calculated by multiplying an asset's cir
3449culating supply by its current market price. For commodities, circulating supply is estimated using proven reserves (for oil and gas) or above-ground stock estimates (for precious metals). For currencies, supply is based on M2 money supply data sourced from TradingEconomics.com. The real estate market value is an inflation-adjusted estimate derived from a historical baseline, with data sourced from Statista.com. Values denoted by ~ are best estimates based on the most recent available data and may not reflect exact figures.</p>
3450      </div>
3451
3452      <!-- Column 2: Quick links (two sub-columns) -->
3453      <div class="footer-col footer-col-center">
3454        <p class="footer-heading">Quick Links</p>
3455        <div class="footer-links-grid">
3456          
3457          <ul class="footer-links">
3458            <li><a href="#" class="footer-open-app">App</a></li>
3459            <li><a href="/deals">Deals</a></li>
3460            <li><a href="/learn">Education Articles</a></li>
3461            <li><a href="/news">Latest News</a></li>
3462            <li><a href="/faqs">FAQs</a></li>
3463            <li><a href="/support">Support</a></li>
3464            <li><a href="https://merch.assetmarketcap.com">Merchandise</a></li>
3465          </ul>
3466          <ul class="footer-links">
3467            <li><a href="/pricing" class="footer-open-pricing">Pricing</a></li>
3468            <li><a href="/pro" class="footer-open-pro">Pro</a></li>
3469            <li><a href="/api-info" class="footer-open-api">API</a></li>
3470            <li><a href="/flippener">Flippener Tool</a></li>
3471            <li><a href="/compare">Comparator Tool</a></li>
3472            <li><a href="/net-worth-tracker">Net-Worth Tracker</a></li>
3473            <li><a href="/advertise">Advertise</a></li>
3474          </ul>
3475        </div>
3476      </div>
3477
3478      <!-- Column 3: Partners -->
3479      <div class="footer-col footer-col-center">
3480        <p class="footer-heading">Our Partners</p>
3481        <ul class="footer-links">
3482          <li><a href="https://kraken.pxf.io/EE69A4">Kraken</a></li>
3483          <li><a href="https://www.bybit.com/invite?ref=EPBGD1">ByBit</a></li>
3484          <li><a href="https://shop.ledger.com/pages/referral-program?referral_code=GZ8J1XRHRK32N">Ledger</a></li>
3485          <li><a href="https://ref.nordvpn.com/UzltTVopBvG">NordVPN</a></li>
3486          <li><a href="https://www.tradingview.com/?aff_id=135662">TradingView</a></li>
3487        </ul>
3488      </div>
3489
3490      <!-- Column 4: Newsletter + socials -->
3491      <div class="footer-col footer-newsletter">
3492        <p class="footer-heading">Newsletter</p>
3493        <p class="footer-newsletter-text">Stay informed with market insights, asset analysis, and the latest developments across crypto, equities, commodities, and more, delivered straight to your inbox.</p>
3494        <form class="footer-subscribe-form" action="/subscribe-newsletter" method="POST" aria-label="Subscribe to newsletter">
3495          <input type="email" name="email" class="footer-subscribe-input" placeholder="Enter your email address" required aria-label="Email address">
3496          <button type="submit" class="subscribe-button footer-subscribe-btn">Subscribe</button>
3497        </form>
3498
3499        <p class="footer-heading footer-heading--community">Community</p>
3500        <div class="footer-socials">
3501          <a href="https://www.youtube.com/@assetmarketcap" aria-label="YouTube"><i class="fa-brands fa-youtube"></i></a>
3502          <a href="https://www.facebook.com/assetmarketcap" aria-label="Facebook"><i class="fa-brands fa-facebook"></i></a>
3503          <a href="https://instagram.com/assetmarketcap" aria-label="Instagram"><i class="fa-brands fa-instagram"></i></a>
3504          <a href="https://tiktok.com/@assetmarketcap" aria-label="TikTok"><i class="fa-brands fa-tiktok"></i></a>
3505          <a href="https://x.com/assetmarketcap" aria-label="X"><i class="fa-solid fa-x"></i></a>
3506          <a href="https://telegram.me/assetmarketcap" aria-label="Telegram"><i class="fa-brands fa-telegram"></i></a>
3507          <a href="https://discord.gg/KKDAMNbStQ" aria-label="Discord"><i class="fa-brands fa-discord"></i></a>
3508          <a href="https://reddit.com/r/assetmarketcap" aria-label="Reddit"><i class="fa-brands fa-reddit"></i></a>
3509        </div>
3510
3511        <!-- App store badges sit under the social links inside Community -->
3512        <div class="app-store-badges" aria-label="Download AssetMarketCap app">
3513          <a href="https://play.google.com/store/apps/details?id=com.assetmarketcap.app"
3514             class="app-store-badge"
3515             target="_blank"
3516             rel="noopener"
3517             aria-label="Get AssetMarketCap on Google Play">
3518            <img src="/static/App-Store-Logo-Google.svg" alt="Get it on Google Play" loading="lazy">
3519          </a>
3520          <span class="app-store-badge app-store-badge--coming-soon"
3521                role="img"
3522                aria-disabled="true"
3523                aria-label="AssetMarketCap on the App Store - coming soon">
3524            <span class="app-store-badge__crop">
3525              <img src="/static/App-Store-Logo-Apple.svg" alt="Download on the App Store" loading="lazy">
3526              <span class="app-store-badge__ribbon" aria-hidden="true">Coming Soon</span>
3527            </span>
3528          </span>
3529        </div>
3530      </div>
3531
3532    </div>
3533  </div>
3534
3535  <!-- Disclaimer -->
3536  <div class="footer-disclaimer">
3537    <div class="footer-disclaimer-inner">
3538      <p><strong>Disclaimer:</strong> The content on AssetMarketCap is for informational and educational purposes only and does not constitute financial, investment, tax, or legal advice. Trading and investing in financial instruments, including cryptocurrencies, carries a high level of risk and may not be suitable for all investors. Always conduct your own research and consult a qualified financial advisor before making any investment decisions. Past performance is not indicative of future results. <a href="/privacy" class="footer-privacy-link">Privacy</a></p>
3539    </div>
3540  </div>
3541
3542  <!-- Copyright -->
3543  <div class="footer-copyright">
3544    <span class="copy-left">&copy; AssetMarketCap.com 
3544<script>document.write(new Date().getFullYear());</script>
3544. All rights reserved.</span>
3545    <span class="copy-right">Bitcoin Donations: bc1q5dsmgwd5nl4g33jkf7sh5r8r6n3exncteesadd</span>
3546  </div>
3547
3548  <!-- Wire footer modal links to navbar triggers -->
3549  
3549<script>
3550    document.addEventListener("DOMContentLoaded", function () {
3551      var map = {
3552        // .footer-open-pricing and .footer-open-pro removed — the
3553        // pricing and pro routes are full pages now, so the footer
3554        // links navigate via their own href without proxying through
3555        // a navbar trigger.
3556        ".footer-open-api": "openApi",
3557        ".footer-open-app": "openAppPopup"
3558      };
3559      for (var sel in map) {
3560        (function (selector, targetId) {
3561          var el = document.querySelector(selector);
3562          if (el) {
3563            el.addEventListener("click", function (e) {
3564              e.preventDefault();
3565              var target = document.getElementById(targetId);
3566              if (target) target.click();
3567            });
3568          }
3569        })(sel, map[sel]);
3570      }
3571    });
3572  </script>
3572
3573</footer>
3574
3575  <!-- ═══════════════════════════════════════════════════════════
3576     PRICING MODAL
3577     ═══════════════════════════════════════════════════════════ -->
3578<div id="pricingOverlay" class="auth-overlay" aria-hidden="true">
3579  <div class="auth-backdrop" data-close-modal="pricingOverlay"></div>
3580  <section class="auth-modal" role="dialog" aria-modal="true">
3581    <button class="auth-close" data-close-modal="pricingOverlay" type="button" aria-label="Close">&times;</button>
3582
3583    <div class="auth-modal-left">
3584      <div style="position:relative; z-index:1; display:flex; flex-direction:column; height:100%;">
3585        <div class="auth-badge">Pro Plans</div>
3586        <h2 class="auth-hero-title">Go beyond the data</h2>
3587        <p class="auth-hero-copy">Everyone gets the full 35k+ dataset. Pro adds premium content and an ad-free experience.</p>
3588        <div class="auth-feature-list">
3589          <div class="auth-feature-item">Full 35,000+ asset dataset, free for everyone</div>
3590          <div class="auth-feature-item">Education library on sign-up</div>
3591          <div class="auth-feature-item">Filter by Country &amp; Sector on sign-up</div>
3592          <div class="auth-feature-item">Ad-Free Mobile App Experience</div>
3593          <div class="auth-feature-item">News Article Access</div>
3594          <div class="auth-feature-item">Favourites, Flippener Tool &amp; Comparator Tool</div>
3595        </div>
3596      </div>
3597    </div>
3598
3599    <div class="auth-modal-right">
3600      
3601        
3602        <h3 class="auth-modal-heading">Pricing</h3>
3603        <p class="auth-subtitle">The full 35k+ dataset is free for everyone. Sign up for favourites, or upgrade to Pro for premium features.</p>
3604
3605        <table class="auth-compare-table">
3606          <thead>
3607            <tr>
3608              <th class="auth-compare-feature-col">Feature</th>
3609              <th>Free</th>
3610              <th>Sign Up</th>
3611              <th>Pro</th>
3612              <th class="auth-compare-highlight">Pro+</th>
3613            </tr>
3614          </thead>
3615          <tbody>
3616            <tr><td>35,000+ assets</td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
3617            <tr><td>Education library</td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
3618            <tr><td>Filter by Country &amp; Sector</td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
3619            <tr><td>Ad-Free Mobile App Experience</td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
3620            <tr><td>News Article Access</td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
3621            <tr><td>Favourites</td><td class="auth-compare-text">3</td><td class="auth-compare-text">15</td><td class="auth-compare-text">50/mo</td><td class="auth-compare-text">Unlimited</td></tr>
3622            <tr><td>Flippener Tool</td><td class="auth-compare-text">3</td><td class="auth-compare-text">10</td><td class="auth-compare-text">30/mo</td><td class="auth-compare-text">Unlimited</td></tr>
3623            <tr><td>Comparator Tool</td><td class="auth-compare-text">3</td><td class="auth-compare-text">5</td><td class="auth-compare-text">15/mo</td><td class="auth-compare-text">Unlimited</td></tr>
3624            <tr class="auth-compare-price-row">
3625              <td>Price</td>
3626              <td class="auth-compare-text">Free</td>
3627              <td class="auth-compare-text">Sign Up</td>
3628              <td class="auth-compare-text"><span data-info-pro-price>$3.99<small>/mo</small></span></td>
3629              <td class="auth-compare-text"><span data-info-proplus-price>$9.99<small>/mo</small></span></td>
3630            </tr>
3631          </tbody>
3632        </table>
3633
3634        <a href="/login?view=register" class="auth-submit" style="margin-top:18px; display:block; text-align:center; text-decoration:none;">Create a free account</a>
3635        <div style="margin-top:12px; text-align:center;">
3636          <a href="/login" class="auth-inline-link">Already have an account? Log in</a>
3637        </div>
3638      
3639    </div>
3640  </section>
3641</div>
3642
3643
3644<!-- ═══════════════════════════════════════════════════════════
3645     API MODAL
3646     ═══════════════════════════════════════════════════════════ -->
3647<div id="apiOverlay" class="auth-overlay" aria-hidden="true">
3648  <div class="auth-backdrop" data-close-modal="apiOverlay"></div>
3649  <section class="auth-modal" role="dialog" aria-modal="true">
3650    <button class="auth-close" data-close-modal="apiOverlay" type="button" aria-label="Close">&times;</button>
3651
3652    <div class="auth-modal-left">
3653      <div style="position:relative; z-index:1; display:flex; flex-direction:column; height:100%;">
3654        <div class="auth-badge">REST API</div>
3655        <h2 class="auth-hero-title">Build with the API</h2>
3656        <p class="auth-hero-copy">
3657          Programmatic access for apps, scripts, and integrations. Every account includes a free API key with the top 100 assets. Upgrade for the full 35k+ dataset, fundamentals, and historical data.
3658        </p>
3659        <div class="auth-feature-list">
3660          <div class="auth-feature-item">Top 100 assets free with every account</div>
3661          <div class="auth-feature-item">Full 35,000+ asset dataset</div>
3662          <div class="auth-feature-item">Individual asset fundamentals</div>
3663          <div class="auth-feature-item">Historical market cap &amp; price data</div>
3664          <div class="auth-feature-item">Up to 1 million API calls per month</div>
3665          <div class="auth-feature-item">Plans from $19.99/mo</div>
3666        </div>
3667      </div>
3668    </div>
3669
3670    <div class="auth-modal-right">
3671      
3672        
3673        <h3 class="auth-modal-heading">API access</h3>
3674        <p class="auth-subtitle">Register for your free API key (top 100 assets included). Subscribe for the full 35k+ dataset, fundamentals, and historical data.</p>
3675
3676        <table class="auth-compare-table">
3677          <thead>
3678            <tr>
3679              <th class="auth-compare-feature-col">Feature</th>
3680              <th>Free</th>
3681              <th>Starter</th>
3682              <th>Growth</th>
3683              <th class="auth-compare-highlight">Scale</th>
3684            </tr>
3685          </thead>
3686          <tbody>
3687            <tr><td>Top 100 assets</td><td>
3687<span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
3688            <tr><td>Full 35k+ asset list</td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
3689            <tr><td>Fundamentals</td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
3690            <tr><td>Historical data</td><td><span class="auth-compare-cross">&#10007;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td><td><span class="auth-compare-tick">&#10003;</span></td></tr>
3691            <tr><td>Calls / month</td><td class="auth-compare-text">1,000</td><td class="auth-compare-text">10k</td><td class="auth-compare-text">100k</td><td class="auth-compare-text">1M</td></tr>
3692            <tr class="auth-compare-price-row">
3693              <td>Price</td>
3694              <td class="auth-compare-text">Free</td>
3695              <td class="auth-compare-text">$19.99<small>/mo</small></td>
3696              <td class="auth-compare-text">$49.99<small>/mo</small></td>
3697              <td class="auth-compare-text">$99.99<small>/mo</small></td>
3698            </tr>
3699          </tbody>
3700        </table>
3701
3702        <a href="/login?view=register" class="auth-submit" style="margin-top:18px; display:block; text-align:center; text-decoration:none;">Register for your Free API Key</a>
3703        <div style="margin-top:14px;">
3704          <a href="/API" class="auth-inline-link">View API documentation &#8594;</a>
3705        </div>
3706      
3707    </div>
3708  </section>
3709</div>
3710
3711
3712<!-- ═══════════════════════════════════════════════════════════
3713     NEWSLETTER MODAL
3714     ═══════════════════════════════════════════════════════════ -->
3715<div id="newsletterOverlay" class="auth-overlay" aria-hidden="true">
3716  <div class="auth-backdrop" data-close-modal="newsletterOverlay"></div>
3717  <section class="auth-modal" role="dialog" aria-modal="true">
3718    <button class="auth-close" data-close-modal="newsletterOverlay" type="button" aria-label="Close">&times;</button>
3719
3720    <div class="auth-modal-left">
3721      <div style="position:relative; z-index:1; display:flex; flex-direction:column; height:100%;">
3722        <div class="auth-badge">Newsletter</div>
3723        <h2 class="auth-hero-title">Stay ahead of the market</h2>
3724        <p class="auth-hero-copy">
3725          Weekly insights on market caps, asset rankings, and macro trends, straight to your inbox.
3726        </p>
3727        <div class="auth-feature-list">
3728          <div class="auth-feature-item">Weekly market cap rankings recap</div>
3729          <div class="auth-feature-item">Asset class breakdowns &amp; analysis</div>
3730          <div class="auth-feature-item">Bitcoin &amp; crypto market updates</div>
3731          <div class="auth-feature-item">Unsubscribe any time</div>
3732        </div>
3733      </div>
3734    </div>
3735
3736    <div class="auth-modal-right">
3737      
3738        <h3 class="auth-modal-heading">Newsletter</h3>
3739        <p class="auth-subtitle">Get weekly market insights delivered to your inbox. No account required.</p>
3740        <form method="POST" action="/subscribe-newsletter" class="auth-form" id="newsletterForm">
3741          <input name="email" type="email" placeholder="Email address" required autocomplete="email">
3742          <button type="submit" class="auth-submit">Subscribe</button>
3743        </form>
3744      
3745      <p style="font-size:11px; color:rgba(255,255,255,0.4); line-height:1.45; margin:14px 0 0; text-align:center;">
3746        We'll never share your email. Unsubscribe any time.
3747      </p>
3748    </div>
3749  </section>
3750</div>
3751
3752
3753<!-- ===========================================================
3754     SIGNUP GATE MODAL - unclosable, fires after activity threshold
3755     Only rendered for logged-out users; controlled by JS below.
3756     =========================================================== -->
3757
3758<div id="signupGateOverlay" class="auth-overlay signup-gate" aria-hidden="true">
3759  <div class="auth-backdrop signup-gate-backdrop" data-close-modal="signupGateOverlay"></div>
3760  <section class="auth-modal signup-gate-modal" role="dialog" aria-modal="true" aria-labelledby="signupGateTitle">
3761
3762    <button class="auth-close signup-gate-close" data-close-modal="signupGateOverlay" type="button" aria-label="Close">&times;</button>
3763
3764    <div class="auth-modal-left">
3765      <div style="position:relative; z-index:1; display:flex; flex-direction:column; height:100%;">
3766        <div class="auth-badge">Free Account</div>
3767        <h2 class="auth-hero-title" id="signupGateTitle">Keep exploring 35,000+ assets</h2>
3768        <p class="auth-hero-copy">You're clearly getting value out of the data. Create a free account in seconds to keep going - no credit card required.</p>
3769        <div class="auth-feature-list">
3770          <div class="auth-feature-item">Free access to the full 35,000+ dataset</div>
3771          <div class="auth-feature-item">Education library &amp; news article access</div>
3772          <div class="auth-feature-item">Filter by Country &amp; Sector</div>
3773          <div class="auth-feature-item">Save favourites &amp; build watchlists</div>
3774          <div class="auth-feature-item">Free API key included</div>
3775        </div>
3776      </div>
3777    </div>
3778
3779    <div class="auth-modal-right">
3780      <h3 class="auth-modal-heading">Create your free account</h3>
3781      <p class="auth-subtitle">It takes about 15 seconds. No card, no spam - just full access to everything on AssetMarketCap.</p>
3782
3783      <a href="/login?view=register" class="auth-submit signup-gate-cta" style="margin-top:18px; display:block; text-align:center; text-decoration:none;">Create a free account</a>
3784
3785      <div style="margin-top:14px; text-align:center;">
3786        <a href="/login" class="auth-inline-link">Already have an account? Log in</a>
3787      </div>
3788
3789      <p style="font-size:11px; color:rgba(255,255,255,0.4); line-height:1.45; margin:22px 0 0; text-align:center;">
3790        By creating an account you agree to our <a href="/privacy" class="auth-inline-link">Privacy Policy</a>.
3791      </p>
3792    </div>
3793  </section>
3794</div>
3795
3796
3797
3798<!-- ═══════════════════════════════════════════════════════════
3799     MODAL JS - shared open/close + feature-specific logic
3800     ═══════════════════════════════════════════════════════════ -->
3801<script>
3802(function () {
3803  // ── Generic open/close for all modals ──────────────────────
3804  function openModal(id) {
3805    var el = document.getElementById(id);
3806    if (!el) return;
3807    el.classList.add("open");
3808    el.setAttribute("aria-hidden", "false");
3809    document.body.style.overflow = "hidden";
3810    // Load API usage when API modal opens
3811    if (id === "apiOverlay") loadApiUsage();
3812  }
3813
3814  function closeModal(id) {
3815    var el = document.getElementById(id);
3816    if (!el) return;
3817    el.classList.remove("open");
3818    el.setAttribute("aria-hidden", "true");
3819    document.body.style.overflow = "";
3820  }
3821
3822  // Close buttons (backdrop + X button)
3823  document.querySelectorAll("[data-close-modal]").forEach(function (el) {
3824    el.addEventListener("click", function () {
3825      closeModal(el.getAttribute("data-close-modal"));
3826    });
3827  });
3828
3829  // Escape key closes any open modal
3830  document.addEventListener("keydown", function (e) {
3831    if (e.key === "Escape") {
3832      ["pricingOverlay", "apiOverlay", "newsletterOverlay"].forEach(closeModal);
3833    }
3834  });
3835
3836  // ── Nav link triggers ──────────────────────────────────────
3837  
3838    var isAuthed = false;
3839  
3840
3841  var openPro     = document.getElementById("openPro");
3842  var openPricing = document.getElementById("openPricing");
3843  var openApi     = document.getElementById("openApi");
3844  var openNewsletterNav = document.getElementById("openNewsletterNav");
3845
3846  // Pro / Pricing nav links navigate to the full pages now (we
3847  // converted these from modal overlays to standalone marketing
3848  // pages). The only special-case left: logged-in users clicking
3849  // "Pro" go straight to their account subscriptions section
3850  // instead of the marketing page — they already have the info.
3851  if (openPro) {
3852    openPro.addEventListener("click", function (e) {
3853      if (isAuthed) {
3854        e.preventDefault();
3855        window.location.href = "/account#subscriptions";
3856      }
3857      // Otherwise let the <a href="/pro"> navigate normally.
3858    });
3859  }
3860  // Pricing link: no interceptor — the <a href="/pricing"> handles it.
3861
3862  // API: route to the standalone /api-info documentation page (no modal).
3863  // The <a href="/api-info" id="openApi"> in header.html handles navigation
3864  // natively now that the docs live on a full page.
3865
3866  // Newsletter
3867  if (openNewsletterNav) {
3868    openNewsletterNav.addEventListener("click", function (e) {
3869      e.preventDefault();
3870      openModal("newsletterOverlay");
3871    });
3872  }
3873
3874  // Footer newsletter button (loaded after this script, so use delegation)
3875  document.addEventListener("click", function (e) {
3876    var el = e.target.closest("#openNewsletter");
3877    if (el) { e.preventDefault(); openModal("newsletterOverlay"); }
3878  });
3879
3880  // Login/Register link: go to /login page
3881  var openAuth = document.getElementById("openAuth");
3882  if (openAuth) {
3883    openAuth.addEventListener("click", function (e) {
3884      e.preventDefault();
3885      window.location.href = "/login";
3886    });
3887  }
3888
3889  // Auto-open modal when returning from a flow that asked for it.
3890  // The pricing/pro auto-open was dropped after those moved to full
3891  // pages — Stripe cancel now redirects to /pricing directly.
3892  var modalParam = new URLSearchParams(window.location.search).get("modal");
3893  if (modalParam === "api" || modalParam === "api-info") openModal("apiOverlay");
3894  if (modalParam === "newsletter") openModal("newsletterOverlay");
3895
3896  // ── Billing toggle helper ──────────────────────────────────
3897  function setupBillingToggle(toggleEl, onChange) {
3898    if (!toggleEl) return;
3899    var sw = toggleEl.querySelector(".billing-toggle-switch");
3900    var labels = toggleEl.querySelectorAll(".billing-toggle-label");
3901    var isAnnual = false;
3902
3903    function update() {
3904      toggleEl.classList.toggle("billing-toggle--annual", isAnnual);
3905      labels.forEach(function (l) {
3906        l.classList.toggle("billing-toggle-label--active", l.dataset.interval === (isAnnual ? "annual" : "monthly"));
3907      });
3908      onChange(isAnnual ? "annual" : "monthly");
3909    }
3910
3911    if (sw) sw.addEventListener("click", function () { isAnnual = !isAnnual; update(); });
3912    labels.forEach(function (l) {
3913      l.addEventListener("click", function () { isAnnual = l.dataset.interval === "annual"; update(); });
3914    });
3915  }
3916
3917  // ── Pro plan card selection ────────────────────────────────
3918  var proCards = document.querySelectorAll("#pricingOverlay .auth-plan-option[data-pro-plan]");
3919  var proForm  = document.getElementById("proSubscribeForm");
3920  var proBtn   = document.getElementById("proSubscribeBtn");
3921  var proIntervalInput = document.getElementById("proInterval");
3922
3923  function updateProCardPrices(interval) {
3924    proCards.forEach(function (card) {
3925      var amount = card.querySelector("[data-price-amount]");
3926      var cents  = card.querySelector("[data-price-cents]");
3927      var period = card.querySelector("[data-price-period]");
3928      if (interval === "annual") {
3929        if (amount) amount.textContent = card.dataset.annualAmount;
3930        if (cents)  cents.textContent  = card.dataset.annualCents;
3931        if (period) period.textContent = card.dataset.annualPeriod;
3932        card.dataset.proLabel = card.dataset.proLabelAnnual;
3933      } else {
3934        if (amount) amount.textContent = card.dataset.monthlyAmount;
3935        if (cents)  cents.textContent  = card.dataset.monthlyCents;
3936        if (period) period.textContent = card.dataset.monthlyPeriod;
3937        card.dataset.proLabel = card.dataset.proLabelMonthly;
3938      }
3939    });
3940    var selectedCard = document.querySelector("#pricingOverlay .auth-plan-option.selected");
3941    if (selectedCard && proBtn) proBtn.textContent = selectedCard.dataset.proLabel;
3942  }
3943
3944  setupBillingToggle(document.getElementById("proBillingToggle"), function (interval) {
3945    if (proIntervalInput) proIntervalInput.value = interval;
3946    updateProCardPrices(interval);
3947  });
3948
3949  proCards.forEach(function (card) {
3950    card.addEventListener("click", function () {
3951      proCards.forEach(function (c) { c.classList.remove("selected"); });
3952      card.classList.add("selected");
3953      if (proForm) proForm.setAttribute("action", card.dataset.proAction);
3954      if (proBtn)  proBtn.textContent = card.dataset.proLabel;
3955    });
3956  });
3957
3958  // ── Pro upgrade toggle ─────────────────────────────────────
3959  var proUpgradeBtn      = document.getElementById("proUpgradeBtn");
3960  var proUpgradeBadge    = document.getElementById("proUpgradeBadge");
3961  var proUpgradeInterval = document.getElementById("proUpgradeInterval");
3962
3963  setupBillingToggle(document.getElementById("proUpgradeBillingToggle"), function (interval) {
3964    if (proUpgradeInterval) proUpgradeInterval.value = interval;
3965    if (interval === "annual") {
3966      if (proUpgradeBadge) proUpgradeBadge.textContent = "Pro Plus - $99.99/yr";
3967      if (proUpgradeBtn)   proUpgradeBtn.textContent   = "Upgrade to Pro Plus - $99.99/yr";
3968    } else {
3969      if (proUpgradeBadge) proUpgradeBadge.textContent = "Pro Plus - $9.99/mo";
3970      if (proUpgradeBtn)   proUpgradeBtn.textContent   = "Upgrade to Pro Plus - $9.99/mo";
3971    }
3972  });
3973
3974  // ── API plan card selection ────────────────────────────────
3975  var apiAllCards       = document.querySelectorAll("#apiPlanCards .api-plan-card[data-plan]");
3976  var selectedPlanInput = document.getElementById("apiSelectedPlan");
3977  var apiSignupForm     = document.getElementById("apiSignupForm");
3978  var apiSubscribeBtn   = document.getElementById("apiSubscribeBtn");
3979  var apiEnterpriseBtn  = document.getElementById("apiEnterpriseBtn");
3980  var apiIntervalInput  = document.getElementById("apiInterval");
3981  var currentApiInterval = "monthly";
3982
3983  var apiPlanLabels = {
3984    starter: { monthly: "Subscribe - Starter $19.99/mo",  annual: "Subscribe - Starter $99.99/yr" },
3985    growth:  { monthly: "Subscribe - Growth $49.99/mo",   annual: "Subscribe - Growth $499.99/yr" },
3986    scale:   { monthly: "Subscribe - Scale $99.99/mo",    annual: "Subscribe - Scale $999.99/yr" }
3987  };
3988
3989  function updateApiCardLimits(interval) {
3990    apiAllCards.forEach(function (card) {
3991      if (card.dataset.plan === "enterprise") return;
3992      var limitEl = card.querySelector("[data-api-limit]");
3993      if (limitEl) limitEl.textContent = card.dataset["limit" + interval.charAt(0).toUpperCase() + interval.slice(1)] || "";
3994    });
3995    var selectedCard = document.querySelector("#apiPlanCards .api-plan-card--selected");
3996    if (selectedCard && selectedCard.dataset.plan !== "enterprise" && apiSubscribeBtn) {
3997      var plan = selectedCard.dataset.plan;
3998      apiSubscribeBtn.textContent = (apiPlanLabels[plan] && apiPlanLabels[plan][interval]) || "Subscribe to API plan";
3999    }
4000  }
4001
4002  setupBillingToggle(document.getElementById("apiBillingToggle"), function (interval) {
4003    currentApiInterval = interval;
4004    if (apiIntervalInput) apiIntervalInput.value = interval;
4005    updateApiCardLimits(interval);
4006  });
4007
4008  apiAllCards.forEach(function (card) {
4009    card.addEventListener("click", function () {
4010      apiAllCards.forEach(function (c) { c.classList.remove("api-plan-card--selected"); });
4011      card.classList.add("api-plan-card--selected");
4012      var plan = card.dataset.plan;
4013      if (plan === "enterprise") {
4014        if (apiSignupForm)    apiSignupForm.style.display = "none";
4015        if (apiEnterpriseBtn) apiEnterpriseBtn.style.display = "block";
4016      } else {
4017        if (selectedPlanInput) selectedPlanInput.value = plan;
4018        if (apiSubscribeBtn)   apiSubscribeBtn.textContent = (apiPlanLabels[plan] && apiPlanLabels[plan][currentApiInterval]) || "Subscribe to API plan";
4019        if (apiSignupForm)     apiSignupForm.style.display = "";
4020        if (apiEnterpriseBtn)  apiEnterpriseBtn.style.display = "none";
4021      }
4022    });
4023  });
4024
4025  // ── Copy API key ──────────────────────────────────────────
4026  // 2026-07-05: apiKeyText now shows only the key PREFIX (keys are stored
4027  // hashed, plaintext is shown once at creation on the account page), so
4028  // the old click-to-copy handler was removed - copying a prefix would
4029  // only produce broken curl commands.
4030
4031  // ── API usage meter ───────────────────────────────────────
4032  function loadApiUsage() {
4033    var block = document.getElementById("apiUsageBlock");
4034    if (!block) return;
4035    fetch("/api-usage")
4036      .then(function (r) { return r.ok ? r.json() : null; })
4037      .then(function (data) {
4038        if (!data) return;
4039        var label = document.getElementById("apiUsageLabel");
4040        var fill  = document.getElementById("apiUsageFill");
4041        var reset = document.getElementById("apiUsageReset");
4042        if (label) label.textContent = data.used.toLocaleString() + " / " + data.limit.toLocaleString() + " calls this month";
4043        if (fill) {
4044          var pct = Math.min(100, Math.round((data.used / data.limit) * 100));
4045          fill.style.width = pct + "%";
4046          fill.classList.toggle("api-usage-bar-fill--warning", pct >= 80);
4047          fill.classList.toggle("api-usage-bar-fill--danger",  pct >= 95);
4048        }
4049        if (reset && data.reset_date) {
4050          var d = new Date(data.reset_date + "T00:00:00");
4051          reset.textContent = "Resets " + d.toLocaleDateString(undefined, { month: "short", day: "
4051numeric", year: "numeric" });
4052        }
4053      })
4054      .catch(function () {});
4055  }
4056
4057  // ── Stripe loading spinner ────────────────────────────────
4058  var stripeActions = [
4059    "/create-checkout-session", "/create-pro-plus-checkout-session",
4060    "/create-customer-portal-session", "/create-pro-plus-customer-portal-session",
4061    "/create-api-checkout-session", "/create-api-customer-portal-session",
4062    "/cancel-subscription", "/cancel-pro-plus-subscription",
4063    "/cancel-api-subscription", "/switch-api-plan"
4064  ];
4065
4066  document.querySelectorAll(".auth-form").forEach(function (form) {
4067    if (!stripeActions.includes(form.getAttribute("action"))) return;
4068    form.addEventListener("submit", function () {
4069      var btn = form.querySelector(".auth-submit, .api-plan-card");
4070      if (btn) { btn.classList.add("auth-submit--loading"); btn.disabled = true; }
4071    });
4072  });
4073
4074  window.addEventListener("pageshow", function (event) {
4075    if (event.persisted) {
4076      document.querySelectorAll(".auth-submit--loading").forEach(function (btn) {
4077        btn.classList.remove("auth-submit--loading");
4078        btn.disabled = false;
4079      });
4080    }
4081  });
4082
4083
4084  // == Signup gate (unclosable, 24hr cooldown) ==================
4085  (function setupSignupGate() {
4086    var overlay = document.getElementById("signupGateOverlay");
4087    if (!overlay) return; // not rendered (user is authenticated)
4088
4089    var STORAGE_KEY = "amc_signup_gate_v1";
4090    var CLICK_THRESHOLD = 5;
4091    var SCROLL_THRESHOLD = Infinity; // scroll trigger disabled for now (click trigger still active)
4092    var COOLDOWN_MS = 24 * 60 * 60 * 1000;
4093    var SCROLL_BURST_GAP_MS = 700; // collapse rapid wheel events into one "scroll"
4094
4095    // Skip on the login page itself - the modal's CTAs already point there
4096    var path = window.location.pathname || "";
4097    if (path === "/login" || path.indexOf("/login/") === 0 || path.indexOf("/login?") === 0) return;
4098
4099    // Skip for crawlers, bots and link-preview fetchers - keeps the modal out
4100    // of Googlebot's rendered DOM and out of social link previews (which fetch
4101    // pages to extract og:image etc).
4102    var ua = navigator.userAgent || "";
4103    if (/bot|crawl|spider|slurp|mediapartners|googlebot|bingbot|baiduspider|yandex|duckduckbot|applebot|petalbot|semrushbot|ahrefsbot|facebookexternalhit|embedly|preview|skypeuripreview|telegrambot|whatsapp|discordbot|linkedinbot|twitterbot|slackbot/i.test(ua)) return;
4104
4105    // Skip when the user arrived from a search engine - avoids Google's
4106    // intrusive-interstitial penalty on the landing page. (Once they
4107    // navigate to a second page, document.referrer is our own domain and
4108    // counting resumes normally.)
4109    var ref = document.referrer || "";
4110    if (ref) {
4111      try {
4112        var refHost = new URL(ref).hostname.toLowerCase();
4113        if (/(^|\.)(google|bing|duckduckgo|yahoo|yandex|baidu|ecosia|qwant|brave|kagi|startpage)\./.test(refHost)) return;
4114      } catch (e) { /* malformed referrer - ignore */ }
4115    }
4116
4117    function readState() {
4118      try {
4119        var raw = localStorage.getItem(STORAGE_KEY);
4120        if (!raw) return { clicks: 0, scrolls: 0, seenAt: 0 };
4121        var s = JSON.parse(raw);
4122        return {
4123          clicks: s.clicks | 0,
4124          scrolls: s.scrolls | 0,
4125          seenAt: parseInt(s.seenAt, 10) || 0
4126        };
4127      } catch (e) {
4128        return { clicks: 0, scrolls: 0, seenAt: 0 };
4129      }
4130    }
4131
4132    function writeState(s) {
4133      try { localStorage.setItem(STORAGE_KEY, JSON.stringify(s)); } catch (e) {}
4134    }
4135
4136    var state = readState();
4137    var now = Date.now();
4138
4139    // Within 24hr cooldown from a prior show? Stay quiet.
4140    if (state.seenAt && (now - state.seenAt) < COOLDOWN_MS) return;
4141
4142    // Cooldown expired - reset counters so the gate has to be re-earned.
4143    if (state.seenAt && (now - state.seenAt) >= COOLDOWN_MS) {
4144      state = { clicks: 0, scrolls: 0, seenAt: 0 };
4145      writeState(state);
4146    }
4147
4148    function closeGate() {
4149      overlay.classList.remove("open");
4150      overlay.setAttribute("aria-hidden", "true");
4151      document.body.style.overflow = "";
4152      document.documentElement.style.overflow = "";
4153    }
4154
4155    function showGate() {
4156      overlay.classList.add("open");
4157      overlay.setAttribute("aria-hidden", "false");
4158      document.body.style.overflow = "hidden";
4159      document.documentElement.style.overflow = "hidden";
4160
4161      // Stamp seenAt so subsequent navigations within 24hr stay quiet.
4162      state.seenAt = Date.now();
4163      writeState(state);
4164
4165      // Wire close button + backdrop click + Escape key.
4166      overlay.querySelectorAll('[data-close-modal="signupGateOverlay"]').forEach(function (el) {
4167        if (!el.dataset.closeBound) {
4168          el.dataset.closeBound = "1";
4169          el.addEventListener("click", closeGate);
4170        }
4171      });
4172      document.addEventListener("keydown", function onEsc(e) {
4173        if (e.key === "Escape") {
4174          closeGate();
4175          document.removeEventListener("keydown", onEsc);
4176        }
4177      });
4178
4179      removeListeners();
4180    }
4181
4182    function checkAndMaybeShow() {
4183      if (state.clicks >= CLICK_THRESHOLD || state.scrolls >= SCROLL_THRESHOLD) {
4184        showGate();
4185      }
4186    }
4187
4188    function onLinkClick(e) {
4189      var a = e.target.closest && e.target.closest("a");
4190      if (!a) return;
4191      if (overlay.contains(a)) return; // ignore links inside the gate
4192      var href = a.getAttribute("href");
4193      if (!href) return;
4194      if (href.charAt(0) === "#") return;
4195      if (/^(javascript:|mailto:|tel:)/i.test(href)) return;
4196      state.clicks++;
4197      writeState(state);
4198      checkAndMaybeShow();
4199    }
4200
4201    var lastScrollBurst = 0;
4202    function onScroll() {
4203      var t = Date.now();
4204      if (t - lastScrollBurst < SCROLL_BURST_GAP_MS) return;
4205      lastScrollBurst = t;
4206      state.scrolls++;
4207      writeState(state);
4208      checkAndMaybeShow();
4209    }
4210
4211    function addListeners() {
4212      document.addEventListener("click", onLinkClick, true);
4213      // scroll trigger disabled for now:
4214      // window.addEventListener("scroll", onScroll, { passive: true });
4215    }
4216    function removeListeners() {
4217      document.removeEventListener("click", onLinkClick, true);
4218      window.removeEventListener("scroll", onScroll);
4219    }
4220
4221    // If counters already crossed the threshold on a previous page-load,
4222    // open immediately (e.g. they hit it just before navigating).
4223    if (state.clicks >= CLICK_THRESHOLD || state.scrolls >= SCROLL_THRESHOLD) {
4224      showGate();
4225    } else {
4226      addListeners();
4227    }
4228  })();
4229
4230})();
4231</script>
4231
4232  <!-- ═══════════════════════════════════════════════════════════
4233     Buy Bitcoin Modal
4234     ═══════════════════════════════════════════════════════════ -->
4235<div id="btcOverlay" class="auth-overlay" aria-hidden="true">
4236  <div class="auth-backdrop" id="closeBtcBackdrop"></div>
4237
4238  <section class="btc-modal" role="dialog" aria-modal="true" aria-labelledby="btcModalTitle">
4239    <button class="auth-close" id="closeBtcBtn" type="button" aria-label="Close">&times;</button>
4240
4241    <!-- ── Left panel ── -->
4242    <div class="btc-modal-left">
4243      <div class="auth-badge">Buy Bitcoin</div>
4244      <h2 class="auth-hero-title">Purchase Bitcoin instantly</h2>
4245      <p class="auth-hero-copy">
4246        Buy BTC securely through our Stripe-powered on-ramp. Your card is saved for one-time use and a small commission is applied after purchase.
4247      </p>
4248      
4249      <div class="auth-feature-list">
4250        <div class="auth-feature-item">
4251          <div class="auth-feature-text">
4252            <strong>No sign-up required</strong>
4253            <span class="auth-feature-sub">private and secure</span>
4254          </div>
4255        </div>
4256        <div class="auth-feature-item">
4257          <div class="auth-feature-text">
4258            <strong>Non-custodian service</strong>
4259            <span class="auth-feature-sub">no 3rd parties</span>
4260          </div>
4261        </div>
4262        <div class="auth-feature-item">
4263          <div class="auth-feature-text">
4264            <strong>Funds stay in your wallet</strong>
4265            <span class="auth-feature-sub">stay in control</span>
4266          </div>
4267        </div>
4268        <div class="auth-feature-item">
4269          <div class="auth-feature-text">
4270            <strong>No additional KYC required</strong>
4271            <span class="auth-feature-sub">as long as you've signed up to a Stripe service before (AI subscription etc.)</span>
4272          </div>
4273        </div>
4274      </div>
4275
4276      
4277      <div class="btc-commission-note">
4278        AssetMarketCap charges a commission of <strong>2.99%</strong> on your completed purchase amount, in addition to any Stripe processing fees and Bitcoin network fees. Total fees will vary depending on network conditions and payment method.
4279      </div>
4280    </div>
4281
4282    <!-- ── Right panel ── -->
4283    <div class="btc-modal-right">
4284      <h2 class="auth-form-title" id="btcModalTitle">Buy Bitcoin</h2>
4285      <p class="btc-subtitle">Enter the amount you'd like to spend in EUR.</p>
4286
4287      <div class="btc-form-group">
4288        <label class="btc-label" for="btcAmount">Amount (EUR)</label>
4289        <input
4290          id="btcAmount"
4291          class="auth-input"
4292          type="number"
4293          min="1"
4294          step="0.01"
4295          placeholder="e.g. 100.00"
4296        />
4297      </div>
4298
4299      <div id="btcFee" class="btc-fee-text"></div>
4300
4301      <button id="btcBuyBtn" class="auth-submit" type="button">
4302        Continue
4303      </button>
4304
4305      <p style="font-size:10px; color:rgba(255,255,255,0.35); line-height:1.5; margin:12px 0 0; text-align:center;">
4306        This service is not financial advice. AssetMarketCap does not provide investment, tax, or legal recommendations. Cryptocurrency is volatile and you may lose some or all of your investment.
4307      </p>
4308
4309      <p class="btc-powered">Secure checkout powered by Stripe</p>
4310    </div>
4311  </section>
4312</div>
4313
4314<script>
4315(function () {
4316  const overlay  = document.getElementById("btcOverlay");
4317  const backdrop = document.getElementById("closeBtcBackdrop");
4318  const closeBtn = document.getElementById("closeBtcBtn");
4319  const buyBtn   = document.getElementById("btcBuyBtn");
4320  const amtInput = document.getElementById("btcAmount");
4321  const feeText  = document.getElementById("btcFee");
4322
4323  const COMMISSION = 2.99;
4324
4325  /* ── open / close helpers ── */
4326  window.openBtcModal = function () {
4327    overlay.classList.add("open");
4328    overlay.setAttribute("aria-hidden", "false");
4329    document.body.style.overflow = "hidden";
4330    amtInput.value = "";
4331    feeText.textContent = "";
4332    setTimeout(function () { amtInput.focus(); }, 120);
4333  };
4334
4335  function closeBtcModal() {
4336    overlay.classList.remove("open");
4337    overlay.setAttribute("aria-hidden", "true");
4338    document.body.style.overflow = "";
4339  }
4340
4341  backdrop.addEventListener("click", closeBtcModal);
4342  closeBtn.addEventListener("click", closeBtcModal);
4343  document.addEventListener("keydown", function (e) {
4344    if (e.key === "Escape" && overlay.classList.contains("open")) closeBtcModal();
4345  });
4346
4347  /* ── live fee preview ── */
4348  amtInput.addEventListener("input", function () {
4349    var value = parseFloat(amtInput.value || "0");
4350    if (!value || value <= 0) { feeText.textContent = ""; return; }
4351    var fee = (value * COMMISSION / 100).toFixed(2);
4352    feeText.textContent = "Estimated commission: \u20AC" + fee;
4353  });
4354
4355  /* ── submit ── */
4356  buyBtn.addEventListener("click", async function () {
4357    var value = parseFloat(amtInput.value || "0");
4358    if (!value || value <= 0) { alert("Please enter a valid amount"); return; }
4359
4360    var amount = Math.round(value * 100);
4361    buyBtn.disabled = true;
4362    buyBtn.classList.add("auth-submit--loading");
4363    buyBtn.textContent = "Processing\u2026";
4364
4365    var params = new URLSearchParams(window.location.search);
4366    var country = params.get("country");
4367    var qs = country ? "?country=" + encodeURIComponent(country) : "";
4368
4369    try {
4370      var res = await fetch("/create-card-setup" + qs, {
4371        method: "POST",
4372        headers: { "Content-Type": "application/json" },
4373        body: JSON.stringify({ amount: amount })
4374      });
4375      var data = await res.json();
4376      if (!res.ok) { alert(data.error || "Failed"); return; }
4377      window.location.href = data.checkoutUrl;
4378    } catch (err) {
4379      alert("Something went wrong. Please try again.");
4380    } finally {
4381      buyBtn.disabled = false;
4382      buyBtn.classList.remove("auth-submit--loading");
4383      buyBtn.textContent = "Continue";
4384    }
4385  });
4386})();
4387</script>
4387
4388  <!-- ═══════════════════════════════════════════════════════════
4389     Cookie Consent Banner + Settings Modal
4390     ═══════════════════════════════════════════════════════════ -->
4391<style>
4392  /* ── Cookie banner (compact, bottom-right corner) ──────── */
4393  .cookie-banner {
4394    position: fixed;
4395    right: 16px;
4396    bottom: 16px;
4397    left: auto;
4398    z-index: 99998;
4399    display: none;
4400    animation: cookieSlideUp 0.32s cubic-bezier(0.16, 1, 0.3, 1);
4401  }
4402  .cookie-banner.show { display: block; }
4403
4404  .cookie-card {
4405    width: 320px;
4406    max-width: calc(100vw - 32px);
4407    background: rgba(14, 8, 40, 0.82);
4408    color: white;
4409    border: 1px solid rgba(255, 255, 255, 0.1);
4410    border-radius: 16px;
4411    backdrop-filter: blur(60px) saturate(200%);
4412    -webkit-backdrop-filter: blur(60px) saturate(200%);
4413    box-shadow:
4414      0 0 0 1px rgba(255, 255, 255, 0.05) inset,
4415      0 20px 40px rgba(0, 0, 0, 0.45),
4416      0 8px 16px rgba(0, 0, 0, 0.3),
4417      0 0 40px rgba(99, 102, 241, 0.08);
4418    padding: 14px 16px;
4419    display: flex;
4420    flex-direction: column;
4421    gap: 12px;
4422    font-family: "Nunito", system-ui, sans-serif;
4423  }
4424
4425  .cookie-text { flex: 1 1 auto; min-width: 0; }
4426
4427  .cookie-title {
4428    font-size: 13px;
4429    font-weight: 800;
4430    margin: 0 0 3px;
4431    color: white;
4432    letter-spacing: -0.01em;
4433  }
4434
4435  .cookie-description {
4436    margin: 0;
4437    font-size: 12px;
4438    line-height: 1.45;
4439    color: rgba(255, 255, 255, 0.55);
4440  }
4441
4442  .cookie-description a {
4443    color: rgba(167, 139, 250, 0.9);
4444    text-decoration: none;
4445    font-weight: 600;
4446    transition: color 0.15s;
4447  }
4448  .cookie-description a:hover {
4449    color: #a78bfa;
4450    text-decoration: underline;
4451  }
4452
4453  .cookie-actions {
4454    display: flex;
4455    gap: 6px;
4456    flex-wrap: wrap;
4457  }
4458
4459  .cookie-btn {
4460    border: 0;
4461    border-radius: 10px;
4462    padding: 7px 12px;
4463    font-size: 12px;
4464    font-weight: 700;
4465    font-family: "Nunito", system-ui, sans-serif;
4466    cursor: pointer;
4467    transition: all 0.18s ease;
4468    letter-spacing: 0.01em;
4469    flex: 1 1 auto;
4470    white-space: nowrap;
4471  }
4472
4473  .cookie-btn.accept {
4474    background: linear-gradient(135deg, #6366f1 0%, #7c3aed 100%);
4475    color: white;
4476    box-shadow: 0 8px 24px rgba(99, 102, 241, 0.35),
4477                inset 0 1px 0 rgba(255, 255, 255, 0.2);
4478  }
4479  .cookie-btn.accept:hover {
4480    transform: translateY(-1px);
4481    box-shadow: 0 12px 32px rgba(99, 102, 241, 0.45),
4482                inset 0 1px 0 rgba(255, 255, 255, 0.2);
4483  }
4484
4485  .cookie-btn.reject,
4486  .cookie-btn.settings {
4487    background: rgba(255, 255, 255, 0.07);
4488    color: rgba(255, 255, 255, 0.75);
4489    border: 1px solid rgba(255, 255, 255, 0.12);
4490  }
4491  .cookie-btn.reject:hover,
4492  .cookie-btn.settings:hover {
4493    background: rgba(255, 255, 255, 0.12);
4494    border-color: rgba(255, 255, 255, 0.2);
4495    color: white;
4496  }
4497
4498  @keyframes cookieSlideUp {
4499    from { opacity: 0; transform: translateY(18px) scale(0.98); }
4500    to   { opacity: 1; transform: translateY(0) scale(1); }
4501  }
4502
4503  @media (max-width: 480px) {
4504    .cookie-banner { right: 8px; bottom: 8px; left: 8px; }
4505    .cookie-card { width: auto; padding: 12px 14px; border-radius: 14px; }
4506    .cookie-btn { padding: 6px 10px; font-size: 11.5px; }
4507  }
4508
4509  /* ── Cookie settings modal ─────────────────────────────── */
4510  .cookie-settings-overlay {
4511    position: fixed;
4512    inset: 0;
4513    z-index: 99999;
4514    display: none;
4515    overflow-y: auto;
4516    padding: 24px 16px 40px;
4517  }
4518  .cookie-settings-overlay.open { display: block; }
4519
4520  .cookie-settings-backdrop {
4521    position: fixed;
4522    inset: 0;
4523    background: rgba(0, 0, 0, 0.6);
4524    backdrop-filter: blur(6px);
4525    -webkit-backdrop-filter: blur(6px);
4526  }
4527
4528  .cookie-settings-modal {
4529    position: relative;
4530    z-index: 2;
4531    width: min(560px, 96vw);
4532    margin: 60px auto;
4533    background: rgba(18, 18, 34, 0.92);
4534    backdrop-filter: blur(48px) saturate(1.6);
4535    -webkit-backdrop-filter: blur(48px) saturate(1.6);
4536    border: 1px solid rgba(255, 255, 255, 0.08);
4537    border-radius: 24px;
4538    box-shadow: 0 32px 72px rgba(0, 0, 0, 0.5),
4539                inset 0 1px 0 rgba(255, 255, 255, 0.06);
4540    padding: 36px 32px 28px;
4541    color: white;
4542    font-family: "Nunito", system-ui, sans-serif;
4543    animation: cookieSlideUp 0.3s cubic-bezier(0.16, 1, 0.3, 1);
4544  }
4545
4546  .cookie-settings-close {
4547    position: absolute;
4548    top: 16px;
4549    right: 18px;
4550    width: 36px;
4551    height: 36px;
4552    border-radius: 50%;
4553    border: 1px solid rgba(255, 255, 255, 0.1);
4554    background: rgba(255, 255, 255, 0.06);
4555    color: rgba(255, 255, 255, 0.5);
4556    font-size: 20px;
4557    cursor: pointer;
4558    display: flex;
4559    align-items: center;
4560    justify-content: center;
4561    transition: all 0.15s ease;
4562  }
4563  .cookie-settings-close:hover {
4564    background: rgba(255, 255, 255, 0.12);
4565    color: white;
4566  }
4567
4568  .cookie-settings-heading {
4569    margin: 0 0 6px;
4570    font-size: 22px;
4571    font-weight: 800;
4572    letter-spacing: -0.02em;
4573  }
4574
4575  .cookie-settings-modal > p {
4576    margin: 0 0 24px;
4577    font-size: 14px;
4578    color: rgba(255, 255, 255, 0.5);
4579    line-height: 1.6;
4580  }
4581
4582  /* Category rows */
4583  .cookie-category {
4584    display: flex;
4585    align-items: flex-start;
4586    justify-content: space-between;
4587    gap: 16px;
4588    padding: 16px 0;
4589    border-top: 1px solid rgba(255, 255, 255, 0.07);
4590  }
4591
4592  .cookie-category-info { flex: 1; }
4593
4594  .cookie-category-name {
4595    font-size: 15px;
4596    font-weight: 700;
4597    margin: 0 0 4px;
4598    color: white;
4599  }
4600
4601  .cookie-category-desc {
4602    font-size: 13px;
4603    color: rgba(255, 255, 255, 0.45);
4604    line-height: 1.5;
4605    margin: 0;
4606  }
4607
4608  /* Toggle switch */
4609  .cookie-toggle {
4610    position: relative;
4611    flex-shrink: 0;
4612    width: 44px;
4613    height: 24px;
4614    margin-top: 2px;
4615  }
4616
4617  .cookie-toggle input {
4618    opacity: 0;
4619    width: 0;
4620    height: 0;
4621    position: absolute;
4622  }
4623
4624  .cookie-toggle-track {
4625    position: absolute;
4626    inset: 0;
4627    border-radius: 12px;
4628    background: rgba(255, 255, 255, 0.1);
4629    border: 1px solid rgba(255, 255, 255, 0.12);
4630    cursor: pointer;
4631    transition: background 0.2s ease, border-color 0.2s ease;
4632  }
4633
4634  .cookie-toggle-track::after {
4635    content: "";
4636    position: absolute;
4637    top: 2px;
4638    left: 2px;
4639    width: 18px;
4640    height: 18px;
4641    border-radius: 50%;
4642    background: rgba(255, 255, 255, 0.5);
4643    transition: transform 0.2s ease, background 0.2s ease;
4644  }
4645
4646  .cookie-toggle input:checked + .cookie-toggle-track {
4647    background: linear-gradient(135deg, #6366f1, #7c3aed);
4648    border-color: rgba(99, 102, 241, 0.4);
4649  }
4650
4651  .cookie-toggle input:checked + .cookie-toggle-track::after {
4652    transform: translateX(20px);
4653    background: white;
4654  }
4655
4656  .cookie-toggle input:disabled + .cookie-toggle-track {
4657    opacity: 0.5;
4658    cursor: not-allowed;
4659  }
4660
4661  .cookie-always-on {
4662    font-size: 12px;
4663    font-weight: 700;
4664    color: rgba(52, 211, 153, 0.8);
4665    text-transform: uppercase;
4666    letter-spacing: 0.06em;
4667    margin-top: 6px;
4668    flex-shrink: 0;
4669  }
4670
4671  /* Save button */
4672  .cookie-settings-save {
4673    width: 100%;
4674    margin-top: 24px;
4675    border: 0;
4676    border-radius: 14px;
4677    padding: 14px 18px;
4678    font-size: 15px;
4679    font-weight: 700;
4680    font-family: "Nunito", system-ui, sans-serif;
4681    background: linear-gradient(135deg, #6366f1 0%, #7c3aed 100%);
4682    color: white;
4683    cursor: pointer;
4684    transition: all 0.2s ease;
4685    box-shadow: 0 8px 24px rgba(99, 102, 241, 0.3),
4686                inset 0 1px 0 rgba(255, 255, 255, 0.2);
4687  }
4688  .cookie-settings-save:hover {
4689    transform: translateY(-1px);
4690    box-shadow: 0 12px 32px rgba(99, 102, 241, 0.45),
4691                inset 0 1px 0 rgba(255, 255, 255, 0.2);
4692  }
4693
4694  /* ── Full-width compact cookie bar ─────────────────────────── */
4695  .cookie-banner {
4696    right: 0 !important;
4697    bottom: 0 !important;
4698    left: 0 !important;
4699  }
4700  .cookie-card {
4701    width: 100% !important;
4702    max-width: none !important;
4703    border-radius: 0 !important;
4704    border-left: 0 !important;
4705    border-right: 0 !important;
4706    border-bottom: 0 !important;
4707    padding: 8px 24px !important;
4708    flex-direction: row !important;
4709    align-items: center !important;
4710    gap: 16px !important;
4711  }
4712  .cookie-card .cookie-text { flex: 1 1 auto; min-width: 0; }
4713  .cookie-card .cookie-title { display: none; }  /* save vertical space */
4714  .cookie-card .cookie-description {
4715    font-size: 12px !important;
4716    line-height: 1.35 !important;
4717  }
4718  .cookie-card .cookie-actions {
4719    flex: 0 0 auto !important;
4720    flex-wrap: nowrap !important;
4721    gap: 8px !important;
4722  }
4723  .cookie-card .cookie-btn {
4724    flex: 0 0 auto !important;
4725    padding: 6px 14px !important;
4726    font-size: 12px !important;
4727  }
4728  @media (max-width: 600px) {
4729    .cookie-card {
4730      padding: 8px 12px !important;
4731      gap: 10px !important;
4732    }
4733    .cookie-card .cookie-description { font-size: 11.5px !important; }
4734    .cookie-card .cookie-btn { padding: 5px 10px !important; font-size: 11.5px !important; }
4735  }
4736
4737  /* ── Always-black cookie banner ─────────────────────────────────
4738     The original .cookie-card uses rgba(14,8,40,0.82) with a heavy
4739     backdrop-filter glass effect — designed for a corner card over
4740     varied content. As a full-width bottom strip with a white page
4741     background behind it, the glass picked up white and the bar
4742     looked pale. Force a solid black background + drop the blur so
4743     the bar reads as black regardless of dark/light mode. */
4744  .cookie-banner .cookie-card {
4745    background: #0b0a14 !important;
4746    backdrop-filter: none !important;
4747    -webkit-backdrop-filter: none !important;
4748    border: 1px solid rgba(255, 255, 255, 0.08) !important;
4749    color: #ffffff !important;
4750  }
4751  .cookie-banner .cookie-title { color: #ffffff !important; }
4752  .cookie-banner .cookie-description { color: rgba(255, 255, 255, 0.65) !important; }
4753  .cookie-banner .cookie-description a {
4754    color: rgba(167, 139, 250, 0.9) !important;
4755    text-decoration: none !important;
4756  }
4757  .cookie-banner .cookie-btn.reject,
4758  .cookie-banner .cookie-btn.settings {
4759    background: rgba(255, 255, 255, 0.07) !important;
4760    color: rgba(255, 255, 255, 0.85) !important;
4761    border: 1px solid rgba(255, 255, 255, 0.14) !important;
4762  }
4763  .cookie-banner .cookie-btn.reject:hover,
4764  .cookie-banner .cookie-btn.settings:hover {
4765    background: rgba(255, 255, 255, 0.14) !important;
4766    color: #ffffff !important;
4767  }
4768
4769  /* ── Accept Cookies button — white ─────────────────────────── */
4770  .cookie-banner .cookie-btn.accept {
4771    background: #ffffff !important;
4772    color: #0f172a !important;
4773    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25),
4774                inset 0 1px 0 rgba(255, 255, 255, 0.4) !important;
4775    border: 1px solid rgba(255, 255, 255, 0.5) !important;
4776  }
4777  .cookie-banner .cookie-btn.accept:hover {
4778    background: #f1f5f9 !important;
4779    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35),
4780                inset 0 1px 0 rgba(255, 255, 255, 0.4) !important;
4781  }
4782</style>
4783
4784<!-- ── Banner ── -->
4785<div id="cookieBanner" class="cookie-banner" role="dialog" aria-live="polite" aria-label="Cookie consent banner">
4786  <div class="cookie-card">
4787    <div class="cookie-text">
4788      <p class="cookie-title">We use cookies</p>
4789      <p class="cookie-description">
4790        We use essential cookies to make this site work and optional cookies to improve your experience.
4791        Read our <a href="/privacy">Privacy Policy</a>.
4792      </p>
4793    </div>
4794    <div class="cookie-actions">
4795      <button class="cookie-btn settings" type="button" id="cookieSettingsOpen">Settings</button>
4796      <button class="cookie-btn reject"   type="button" id="cookieRejectBtn">Reject all</button>
4797      <button class="cookie-btn accept"   type="button" id="cookieAcceptBtn">Accept all</button>
4798    </div>
4799  </div>
4800</div>
4801
4802<!-- ── Settings modal ── -->
4803<div id="cookieSettingsOverlay" class="cookie-settings-overlay" aria-hidden="true">
4804  <div class="cookie-settings-backdrop" id="cookieSettingsBackdrop"></div>
4805
4806  <div class="cookie-settings-modal" role="dialog" aria-modal="true" aria-labelledby="cookieSettingsTitle">
4807    <button class="cookie-settings-close" id="cookieSettingsClose" type="button" aria-label="Close">&times;</button>
4808
4809    <p id="cookieSettingsTitle" class="cookie-settings-heading">Cookie settings</p>
4810    <p>Choose which cookies you'd like to allow. Essential cookies cannot be disabled as they are required for the site to function.</p>
4811
4812    <!-- Essential - always on -->
4813    <div class="cookie-category">
4814      <div class="cookie-category-info">
4815        <p class="cookie-category-name">Essential</p>
4816        <p class="cookie-category-desc">Required for core site functionality such as login, security, and session management. These cannot be turned off.</p>
4817      </div>
4818      <span class="cookie-always-on">Always on</span>
4819    </div>
4820
4821    <!-- Analytics -->
4822    <div class="cookie-category">
4823      <div class="cookie-category-info">
4824        <p class="cookie-category-name">Analytics</p>
4825        <p class="cookie-category-desc">Help us understand how visitors interact with the site so we can improve the experience. Includes Google Analytics.</p>
4826      </div>
4827      <label class="cookie-toggle">
4828        <input type="checkbox" id="cookieAnalytics" checked>
4829        <span class="cookie-toggle-track"></span>
4830      </label>
4831    </div>
4832
4833    <!-- Functional -->
4834    <div class="cookie-category">
4835      <div class="cookie-category-info">
4836        <p class="cookie-category-name">Functional</p>
4837        <p class="cookie-category-desc">Enable personalised features like remembering your preferences, dark mode setting, and favourites.</p>
4838      </div>
4839      <label class="cookie-toggle">
4840        <input type="checkbox" id="cookieFunctional" checked>
4841        <span class="cookie-toggle-track"></span>
4842      </label>
4843    </div>
4844
4845    <!-- Marketing -->
4846    <div class="cookie-category">
4847      <div class="cookie-category-info">
4848        <p class="cookie-category-name">Marketing</p>
4849        <p class="cookie-category-desc">Used by our advertising partners to show you relevant ads and measure campaign effectiveness.</p>
4850      </div>
4851      <label class="cookie-toggle">
4852        <input type="checkbox" id="cookieMarketing">
4853        <span class="cookie-toggle-track"></span>
4854      </label>
4855    </div>
4856
4857    <button class="cookie-settings-save" type="button" id="cookieSettingsSave">Save preferences</button>
4858  </div>
4859</div>
4860
4861<script>
4862(function () {
4863  var CONSENT_KEY  = "cookie_consent";
4864  var PREFS_KEY    = "cookie_preferences";
4865
4866  var banner   = document.getElementById("cookieBanner");
4867  var overlay  = document.getElementById("cookieSettingsOverlay");
4868  var backdrop = document.getElementById("cookieSettingsBackdrop");
4869
4870  /* Inside the Capacitor apps we never grant the Google advertising signals.
4871     ad_user_data / ad_personalization would be "tracking" under Apple's
4872     definition and would require an App Tracking Transparency prompt plus a
4873     tracking declaration in App Privacy. Analytics stays consent-driven; only
4874     the advertising half is forced off, and the Marketing choice is hidden so
4875     we are not offering a toggle that does nothing. */
4876  var IS_NATIVE = !!(window.Capacitor && window.Capacitor.isNativePlatform &&
4877                     window.Capacitor.isNativePlatform());
4878  if (IS_NATIVE) {
4879    var mkt = document.getElementById("cookieMarketing");
4880    var cat = mkt && mkt.closest(".cookie-category");
4881    if (cat) cat.style.display = "none";
4882  }
4883
4884  /* ── Helpers ── */
4885  function showBanner()  { if (banner) banner.classList.add("show"); }
4886  function hideBanner()  { if (banner) banner.classList.remove("show"); }
4887
4888  function openSettings() {
4889    overlay.classList.add("open");
4890    overlay.setAttribute("aria-hidden", "false");
4891    document.body.style.overflow = "hidden";
4892
4893    // Pre-fill toggles from saved prefs
4894    var prefs = getPrefs();
4895    document.getElementById("cookieAnalytics").checked  = prefs.analytics;
4896    document.getElementById("cookieFunctional").checked  = prefs.functional;
4897    document.getElementById("cookieMarketing").checked   = prefs.marketing;
4898  }
4899
4900  function closeSettings() {
4901    overlay.classList.remove("open");
4902    overlay.setAttribute("aria-hidden", "true");
4903    document.body.style.overflow = "";
4904  }
4905
4906  function getPrefs() {
4907    try {
4908      var raw = localStorage.getItem(PREFS_KEY);
4909      if (raw) return JSON.parse(raw);
4910    } catch (e) {}
4911    return { analytics: true, functional: true, marketing: false };
4912  }
4913
4914  function savePrefs(prefs) {
4915    localStorage.setItem(PREFS_KEY, JSON.stringify(prefs));
4916  }
4917
4918  function setConsent(value, prefs) {
4919    localStorage.setItem(CONSENT_KEY, value);
4920    if (prefs) savePrefs(prefs);
4921    hideBanner();
4922    closeSettings();
4923    applyConsent();
4924  }
4925
4926  /* ── Apply consent - enable/disable scripts based on prefs ── */
4927  function applyConsent() {
4928    var consent = localStorage.getItem(CONSENT_KEY);
4929    if (!consent) return;
4930
4931    var prefs = getPrefs();
4932
4933    // Google Analytics (gtag) - already loaded in head.html
4934    // Respect analytics consent via gtag consent mode
4935    if (typeof gtag === "function") {
4936      if (consent === "accepted" && prefs.analytics) {
4937        gtag("consent", "update", {
4938          analytics_storage: "granted"
4939        });
4940      } else {
4941        gtag("consent", "update", {
4942          analytics_storage: "denied"
4943        });
4944      }
4945    }
4946
4947    // Marketing
4948    if (typeof gtag === "function") {
4949      if (!IS_NATIVE && consent === "accepted" && prefs.marketing) {
4950        gtag("consent", "update", {
4951          ad_storage: "granted",
4952          ad_user_data: "granted",
4953          ad_personalization: "granted"
4954        });
4955      } else {
4956        gtag("consent", "update", {
4957          ad_storage: "denied",
4958          ad_user_data: "denied",
4959          ad_personalization: "denied"
4960        });
4961      }
4962    }
4963  }
4964
4965  /* ── Button handlers ── */
4966  document.getElementById("cookieAcceptBtn").addEventListener("click", function () {
4967    setConsent("accepted", { analytics: true, functional: true, marketing: !IS_NATIVE });
4968  });
4969
4970  document.getElementById("cookieRejectBtn").addEventListener("click", function () {
4971    setConsent("rejected", { analytics: false, functional: false, marketing: false });
4972  });
4973
4974  document.getElementById("cookieSettingsOpen").addEventListener("click", openSettings);
4975  document.getElementById("cookieSettingsClose").addEventListener("click", closeSettings);
4976  backdrop.addEventListener("click", closeSettings);
4977
4978  document.addEventListener("keydown", function (e) {
4979    if (e.key === "Escape" && overlay.classList.contains("open")) closeSettings();
4980  });
4981
4982  document.getElementById("cookieSettingsSave").addEventListener("click", function () {
4983    var prefs = {
4984      analytics:  document.getElementById("cookieAnalytics").checked,
4985      functional: document.getElementById("cookieFunctional").checked,
4986      marketing:  IS_NATIVE ? false : document.getElementById("cookieMarketing").checked
4987    };
4988    setConsent("accepted", prefs);
4989  });
4990
4991  /* ── Init ── */
4992  // Set default consent mode to denied until user acts
4993  if (typeof gtag === "function") {
4994    gtag("consent", "default", {
4995      analytics_storage: "denied",
4996      ad_storage: "denied",
4997      ad_user_data: "denied",
4998      ad_personalization: "denied"
4999    });
5000  }
5001
5002  var consent = localStorage.getItem(CONSENT_KEY);
5003  if (!consent) {
5004    showBanner();
5005  } else {
5006    applyConsent();
5007  }
5008})();
5009</script>
5009
5010
5011  
5011<script>
5012    window.__isPro = false;
5013    window.__isLoggedIn = false;
5014  </script>
5014
5015  
5016<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
vendor: 1 bytes, line 5016
5016
5017<script src="https://cdn.datatables.net/1.13.11/js/jquery.dataTables.min.js"></script>
vendor: 1 bytes, line 5017
5017
5018<script src="https://cdn.datatables.net/responsive/2.5.0/js/dataTables.responsive.min.js"></script>
5018
5019<!-- ColReorder (column drag-reorder API) — build matched to DataTables 1.13 -->
5020<script src="https://cdn.datatables.net/colreorder/1.7.0/js/dataTables.colReorder.min.js"></script>
5020
5021<!-- SortableJS — drag-and-drop for the Columns manager panel -->
5022<script src="https://cdn.jsdelivr.net/npm/[email protected]/Sortable.min.js"></script>
5022
5023
5024
5025<!-- Dark mode toggle is handled by header.html (uses document.documentElement + prefers_dark_mode key) -->
5026
5027
5028
5029  
5029<script>
5030  (function(){
5031    var billing = document.getElementById("xBilling");
5032    if (!billing) return;
5033    var thumb = document.getElementById("xBillThumb");
5034    var buttons = billing.querySelectorAll("button[data-interval]");
5035    var planCards = document.querySelectorAll(".x-plan[data-plan]");
5036    var planForms = document.querySelectorAll(".x-plan-form");
5037    var comparePro = document.querySelector("[data-compare-pro]");
5038    var compareProPlus = document.querySelector("[data-compare-proplus]");
5039
5040    function moveThumb(activeBtn){
5041      if (!thumb || !activeBtn) return;
5042      var bRect = billing.getBoundingClientRect();
5043      var aRect = activeBtn.getBoundingClientRect();
5044      thumb.style.left = (aRect.left - bRect.left) + "px";
5045      thumb.style.width = aRect.width + "px";
5046    }
5047    function setBillingInterval(interval){
5048      var activeBtn = null;
5049      buttons.forEach(function(b){
5050        var on = b.dataset.interval === interval;
5051        b.classList.toggle("is-on", on);
5052        b.setAttribute("aria-selected", on ? "true" : "false");
5053        if (on) activeBtn = b;
5054      });
5055      moveThumb(activeBtn);
5056      planCards.forEach(function(card){
5057        var amount = card.querySelector("[data-price-amount]");
5058        var period = card.querySelector("[data-price-period]");
5059        var cta    = card.querySelector("[data-cta-text]");
5060        if (amount) amount.textContent = card.dataset[interval + "Amount"];
5061        if (period) period.textContent = card.dataset[interval + "Period"];
5062        if (cta) cta.textContent = card.dataset["cta" + (interval === "annual" ? "Annual" : "Monthly")];
5063      });
5064      planForms.forEach(function(f){
5065        var i = f.querySelector("input[name=interval]");
5066        if (i) i.value = interval;
5067      });
5068      if (comparePro)     comparePro.textContent     = interval === "annual" ? "$39.99/yr" : "$3.99/mo";
5069      if (compareProPlus) compareProPlus.textContent = interval === "annual" ? "$99.99/yr" : "$9.99/mo";
5070    }
5071    buttons.forEach(function(b){
5072      b.addEventListener("click", function(){ setBillingInterval(b.dataset.interval); });
5073    });
5074    requestAnimationFrame(function(){ moveThumb(billing.querySelector("button.is-on")); });
5075    window.addEventListener("resize", function(){ moveThumb(billing.querySelector("button.is-on")); });
5076    if (document.fonts && document.fonts.ready) {
5077      document.fonts.ready.then(function(){ moveThumb(billing.querySelector("button.is-on")); });
5078    }
5079    document.querySelectorAll(".x-plan-form").forEach(function(form){
5080      form.addEventListener("submit", function(){
5081        var btn = form.querySelector("button[type=submit]");
5082        if (btn){ btn.disabled = true; btn.textContent = "Loading..."; }
5083      });
5084    });
5085  })();
5086  </script>
5086
5087</body>
5088</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.