1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="fo-verify" content="7c1b2d98-52dc-49f3-95fc-792906ed2a9b" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"> 8 <meta http-equiv="Pragma" content="no-cache"> 9 <title>CardCompass â Find Your Perfect Credit Card</title> 10 11 <!-- Favicon & PWA --> 12 <link rel="icon" href="images/logo-icon.svg" type="image/png"> 13 <link rel="icon" href="favicon.svg" type="image/svg+xml"> 14 <link rel="manifest" href="site.webmanifest"> 15 <meta name="theme-color" content="#071E4A"> 16 17 <!-- SEO --> 18 <meta name="description" content="CardCompass finds your best credit card in 60 seconds. Compare cash back, travel rewards, and hotel points cards â personalized to your spending habits."> 19 <link rel="canonical" href="https://cardcompass.app/"> 20 21 <!-- Open Graph --> 22 <meta property="og:type" content="website"> 23 <meta property="og:url" content="https://cardcompass.app/"> 24 <meta property="og:title" content="CardCompass â Find Your Perfect Credit Card"> 25 <meta property="og:description" content="Stop leaving money on the table. CardCompass matches you with the best credit card for your spending in under 60 seconds."> 26 <meta property="og:image" content="https://cardcompass.app/og-image.png"> 27 <meta property="og:site_name" content="CardCompass"> 28 29 <!-- Twitter Card --> 30 <meta name="twitter:card" content="summary_large_image"> 31 <meta name="twitter:title" content="CardCompass â Find Your Perfect Credit Card"> 32 <meta name="twitter:description" content="Find the best credit card for your spending in 60 seconds."> 33 <meta name="twitter:image" content="https://cardcompass.app/og-image.png"> 34 35 <!-- Structured Data --> 36
36<script type="application/ld+json"> 37 { 38 "@context": "https://schema.org", 39 "@type": "Organization", 40 "name": "CardCompass", 41 "url": "https://cardcompass.app", 42 "description": "Credit card comparison and recommendation tool that helps consumers find the best credit card for their spending habits.", 43 "contactPoint": { "@type": "ContactPoint", "email": "[email protected]", "contactType": "customer service" }, 44 "sameAs": ["https://www.instagram.com/cardcompassapp/", "https://www.facebook.com/cardcompassapp"] 45 } 46 </script>
46 47 48
48<script type="application/ld+json"> 49 { 50 "@context": "https://schema.org", 51 "@type": "WebSite", 52 "name": "CardCompass", 53 "url": "https://cardcompass.app", 54 "description": "Credit card comparison and recommendation tool that helps consumers find the best credit card for their spending habits." 55 } 56 </script>
56 57 58 <!-- Google Analytics 4 (consent-gated) -->
vendor: 66 bytes, lines 58-59
58 59 <script async src="https://www.googletagmanager.com/gtag/js?id=
59G-CYNSKD3EBQ
vendor: 14 bytes, lines 59-60
59"></script> 60
60<script> 61 window.dataLayer = window.dataLayer || []; 62 function gtag(){dataLayer.push(arguments);} 63 gtag('js', new Date()); 64 // EU/UK visitors (Europe/* timezone): opt-in (GDPR). Everyone else: on by default with opt-out (US state law model). 65 gtag('consent', 'default', { analytics_storage: (function () { try { var s = localStorage.getItem('cc_consent'); if (s) return s; return /^Europe\//.test(Intl.DateTimeFormat().resolvedOptions().timeZone) ? 'denied' : 'granted'; } catch (e) { return 'denied'; } })() }); 66 gtag('config', 'G-CYNSKD3EBQ'); 67 </script>
67 68 69 <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet"> 70 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer"> 71
71<script src="cards-data.js?v=13"></script>
71 72
72<script src="recommend-engine.js?v=4"></script>
72 73
73<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
73 74 <link rel="stylesheet" href="/styles.css?v=2"> 75 <style> 76/* âââ NAVBAR âââ */ 77 .navbar { position: sticky; top: 0; z-index: 1000; background: var(--primary-dark); box-shadow: 0 2px 12px rgba(0,0,0,0.35); } 78 .nav-inner { max-width: 1280px; margin: 0 auto; padding: 0 24px; display: flex; align-items: center; height: 64px; gap: 28px; } 79 .logo { display: flex; align-items: center; gap: 10px; text-decoration: none; flex-shrink: 0; } 80 .logo-icon { width: 40px; height: 40px; border-radius: 50%; overflow: hidden; flex-shrink: 0; display: flex; align-items: center; justify-content: center; } 81 .logo-icon img { width: 100%; height: 100%; object-fit: cover; display: block; } 82 .logo-text { font-size: 20px; font-weight: 800; color: #fff; letter-spacing: -0.5px; } 83 .logo-text span { color: var(--accent-light); } 84 .nav-links { display: flex; align-items: center; gap: 2px; flex: 1; } 85 .nav-item { position: relative; } 86 .nav-link { display: flex; align-items: center; gap: 5px; padding: 8px 14px; color: rgba(255,255,255,.85); font-size: 14px; font-weight: 500; text-decoration: none; border-radius: 6px; transition: all .2s; white-space: nowrap; cursor: pointer; background: none; border: none; font-family: inherit; } 87 .nav-link i { font-size: 10px; opacity: .7; } 88 .nav-link:hover { color: #fff; background: rgba(255,255,255,.1); } 89 .dropdown { position: absolute; top: calc(100% + 8px); left: 0; background: #fff; border-radius: var(--r-md); box-shadow: var(--shadow-lg); padding: 12px; min-width: 230px; opacity: 0; visibility: hidden; transform: translateY(-8px); transition: all .2s; border: 1px solid var(--border); max-height: calc(100vh - 80px); overflow-y: auto; } 90 .nav-item:hover .dropdown { opacity: 1; visibility: visible; transform: translateY(0); } 91 .dropdown a { display: flex; align-items: center; gap: 10px; padding: 9px 12px; color: var(--text-dark); text-decoration: none; font-size: 14px; border-radius: var(--r-sm); transition: background .15s; } 92 .dropdown a:hover { background: var(--bg-light); color: var(--primary); } 93 .dropdown a i { width: 18px; color: var(--accent); font-size: 13px; } 94 .nav-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; } 95 .btn-outline { padding: 8px 18px; border: 1.5px solid rgba(255,255,255,.4); color: #fff; background: transparent; border-radius: 6px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all .2s; text-decoration: none; font-family: inherit; } 96 .btn-outline:hover { border-color: #fff; background: rgba(255,255,255,.1); } 97 .btn-primary { padding: 8px 18px; background: var(--accent); color: #fff; border: none; border-radius: 6px; font-size: 14px; font-weight: 600; cursor: pointer; transition: all .2s; text-decoration: none; font-family: inherit; } 98 .btn-primary:hover { background: var(--accent-light); transform: translateY(-1px); } 99 100 /* âââ SHARED âââ */ 101 .section { padding: 76px 24px; } 102 .section-alt { background: var(--bg-light); } 103 .section-inner { max-width: 1280px; margin: 0 auto; } 104 .section-label { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 1.5px; color: var(--accent); margin-bottom: 10px; } 105 .section-title { font-size: 36px; font-weight: 800; color: var(--text-dark); letter-spacing: -.5px; line-height: 1.2; } 106 .section-sub { font-size: 16px; color: var(--text-gray); margin-top: 10px; } 107 .section-hd { margin-bottom: 44px; } 108 109 /* âââ COMPARISON TABLE âââ */ 110 .comp-section { background: var(--primary-dark); padding: 76px 24px; color: #fff; } 111 .comp-section .section-title { color: #fff; } 112 .comp-section .section-sub { color: rgba(255,255,255,.6); } 113 .comp-section .section-label { color: var(--accent-light); } 114 115 /* âââ CATEGORY TABS (Best Cards section) âââ */ 116 .comp-tabs-wrap { overflow-x: auto; scrollbar-width: none; margin-bottom: 28px; padding-bottom: 4px; } 117 .comp-tabs-wrap::-webkit-scrollbar { display: none; } 118 .comp-tabs { display: flex; gap: 8px; white-space: nowrap; } 119 .comp-tab { padding: 9px 18px; border: 1.5px solid rgba(255,255,255,.2); background: rgba(255,255,255,.06); color: rgba(255,255,255,.7); border-radius: 100px; font-size: 13px; font-weight: 600; cursor: pointer; transition: all .2s; font-family: inherit; white-space: nowrap; } 120 .comp-tab:hover { background: rgba(255,255,255,.14); color: #fff; border-color: rgba(255,255,255,.4); } 121 .comp-tab.active { background: var(--accent); color: #fff; border-color: var(--accent); } 122 .comp-table-loading { text-align: center; padding: 40px; color: rgba(255,255,255,.45); font-size: 15px; } 123 .comp-table { background: rgba(255,255,255,.05); border-radius: var(--r-lg); overflow: hidden; border: 1px solid rgba(255,255,255,.1); } 124 .comp-header, .comp-row { display: grid; grid-template-columns: 2.2fr 1.1fr 1fr .9fr auto; gap: 16px; padding: 18px 28px; align-items: center; } 125 .comp-header { background: rgba(255,255,255,.08); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: rgba(255,255,255,.45); } 126 .comp-row { border-top: 1px solid rgba(255,255,255,.07); transition: background .2s; cursor: pointer; } 127 .comp-row:hover { background: rgba(255,255,255,.06); } 128 .comp-info { display: flex; align-items: center; gap: 14px; } 129 .comp-card-img { width: 90px; height: 57px; border-radius: 8px; overflow: hidden; flex-shrink: 0; position: relative; box-shadow: 0 3px 10px rgba(0,0,0,.4); } 130 .comp-card-img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 8px; display: block; } 131 /* Brand-accurate card badges â Chase Sapphire (navy), Amex Gold (gold), Cap One Venture X (dark), Discover (orange), Citi (blue) */ 132 .ci-chase { background: linear-gradient(135deg,#0A2342 0%,#0F3D70 100%); border:1px solid rgba(255,255,255,.18); } 133 .ci-amex { background: linear-gradient(135deg,#C9951A 0%,#9A7215 55%,#C9951A 100%); } 134 .ci-citi { background: linear-gradient(135deg,#003B70 0%,#0057A8 100%); } 135 .ci-cap { background: linear-gradient(135deg,#1A1A2E 0%,#2D1B4E 100%); border:1px solid rgba(209,48,39,.5); } 136 .ci-disc { background: linear-gradient(135deg,#F76F20 0%,#E85D11 100%); } 137 .comp-name { font-size: 15px; font-weight: 600; } 138 .comp-sub { font-size: 12px; color: rgba(255,255,255,.45); margin-top: 2px; } 139 .comp-cell { font-size: 14px; color: rgba(255,255,255,.82); font-weight: 500; } 140 .comp-cell .hi { color: var(--accent-gold); font-weight: 700; } 141 .comp-cell .tiny { font-size: 11px; color: rgba(255,255,255,.4); } 142 .comp-cell .badge { background: rgba(30,127,212,.25); color: var(--accent-light); padding: 3px 9px; border-radius: 5px; font-size: 12px; font-weight: 600; } 143 .comp-btn { background: var(--accent); color: #fff; border: none; border-radius: 6px; padding: 9px 18px; font-size: 13px; font-weight: 600; cursor: pointer; transition: all .2s; font-family: inherit; white-space: nowrap; } 144 .comp-btn:hover { background: var(--accent-light); transform: translateY(-1px); } 145 /* âââ COMP PAGINATION & FOOTER âââ */ 146 .comp-footer { display: flex; align-items: center; justify-content: space-between; margin-top: 24px; gap: 16px; flex-wrap: wrap; } 147 .comp-pagination { display: flex; align-items: center; gap: 6px; } 148 .comp-pager-btn { width: 36px; height: 36px; border-radius: 8px; border: 1.5px solid rgba(255,255,255,.2); background: rgba(255,255,255,.06); color: rgba(255,255,255,.75); font-size: 13px; cursor: pointer; transition: all .2s; display: inline-flex; align-items: center; justify-content: center; font-family: inherit; } 149 .comp-pager-btn:hover:not([disabled]) { background: rgba(255,255,255,.15); color: #fff; border-color: rgba(255,255,255,.4); } 150 .comp-pager-btn[disabled] { opacity: .28;
150 cursor: not-allowed; } 151 .comp-pager-num { width: 36px; height: 36px; border-radius: 8px; border: 1.5px solid transparent; background: transparent; color: rgba(255,255,255,.6); font-size: 14px; font-weight: 600; cursor: pointer; transition: all .2s; display: inline-flex; align-items: center; justify-content: center; font-family: inherit; } 152 .comp-pager-num:hover { background: rgba(255,255,255,.08); color: #fff; } 153 .comp-pager-num.active { background: var(--accent); color: #fff; border-color: var(--accent); } 154 .comp-see-all { display: inline-flex; align-items: center; gap: 8px; background: rgba(255,255,255,.1); border: 1.5px solid rgba(255,255,255,.25); color: #fff; padding: 9px 20px; border-radius: 8px; font-size: 14px; font-weight: 600; text-decoration: none; transition: all .2s; white-space: nowrap; } 155 .comp-see-all:hover { background: rgba(255,255,255,.18); border-color: rgba(255,255,255,.45); transform: translateY(-1px); } 156 157 /* âââ FOOTER âââ */ 158 footer { background: var(--primary-dark); color: rgba(255,255,255,.65); padding: 60px 24px 28px; } 159 .footer-inner { max-width: 1280px; margin: 0 auto; } 160 .footer-top { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 48px; padding-bottom: 48px; border-bottom: 1px solid rgba(255,255,255,.1); } 161 .footer-brand p { font-size: 14px; line-height: 1.75; margin-top: 14px; color: rgba(255,255,255,.5); } 162 .footer-col h4 { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: rgba(255,255,255,.9); margin-bottom: 18px; } 163 .footer-col a { display: block; font-size: 14px; color: rgba(255,255,255,.5); text-decoration: none; margin-bottom: 11px; transition: color .2s; } 164 .footer-col a:hover { color: rgba(255,255,255,.9); } 165 .footer-bottom { padding-top: 26px; display: flex; justify-content: space-between; align-items: center; font-size: 12px; color: rgba(255,255,255,.3); flex-wrap: wrap; gap: 12px; } 166 .footer-bottom a { color: rgba(255,255,255,.3); text-decoration: none; } 167 .footer-bottom a:hover { color: rgba(255,255,255,.6); } 168 .foot-links { display: flex; gap: 20px; } 169 170 /* âââ SCROLL TOP âââ */ 171 .scroll-top { position: fixed; bottom: 24px; right: 24px; width: 46px; height: 46px; background: var(--primary); color: #fff; border: none; border-radius: 50%; font-size: 17px; cursor: pointer; box-shadow: var(--shadow-md); display: flex; align-items: center; justify-content: center; transition: all .2s; z-index: 999; } 172 .scroll-top:hover { background: var(--primary-light); transform: translateY(-2px); } 173 174 /* ââââââââââââââââââââââââââââââââââââââââ 175 NEW CSS ADDITIONS 176 ââââââââââââââââââââââââââââââââââââââââ */ 177 178 /* âââ REVEAL ANIMATIONS âââ */ 179 .reveal { opacity: 0; transform: translateY(28px); transition: opacity .65s ease, transform .65s ease; } 180 .reveal.visible { opacity: 1; transform: translateY(0); } 181 .reveal-d1 { transition-delay: .08s; } 182 .reveal-d2 { transition-delay: .16s; } 183 .reveal-d3 { transition-delay: .24s; } 184 .reveal-d4 { transition-delay: .32s; } 185 .reveal-d5 { transition-delay: .40s; } 186 .reveal-d6 { transition-delay: .48s; } 187 .reveal-d7 { transition-delay: .56s; } 188 189 /* âââ HAMBURGER âââ */ 190 .hamburger { display: none; flex-direction: column; justify-content: center; align-items: center; width: 40px; height: 40px; background: none; border: none; cursor: pointer; gap: 5px; padding: 6px; border-radius: 6px; transition: background .2s; margin-left: auto; flex-shrink: 0; } 191 .hamburger:hover { background: rgba(255,255,255,.1); } 192 .hamburger span { display: block; width: 22px; height: 2px; background: rgba(255,255,255,.85); border-radius: 2px; transition: all .3s ease; } 193 .hamburger.open span:nth-child(1) { transform: rotate(45deg) translate(5px, 5px); } 194 .hamburger.open span:nth-child(2) { opacity: 0; transform: scaleX(0); } 195 .hamburger.open span:nth-child(3) { transform: rotate(-45deg) translate(5px, -5px); } 196 197 /* âââ MOBILE NAV âââ */ 198 .nav-links.mobile-open { display: flex !important; flex-direction: column; align-items: flex-start; position: absolute; top: 64px; left: 0; right: 0; background: var(--primary-dark); padding: 12px 16px 20px; border-top: 1px solid rgba(255,255,255,.1); box-shadow: 0 8px 32px rgba(0,0,0,.3); z-index: 999; max-height: calc(100vh - 64px); overflow-y: auto; } 199 .nav-links.mobile-open .nav-link { width: 100%; padding: 12px 16px; } 200 .nav-links.mobile-open .nav-item { width: 100%; } 201 .nav-links.mobile-open .dropdown { position: static; opacity: 1; visibility: visible; transform: none; box-shadow: none; background: rgba(255,255,255,.06); border-color: rgba(255,255,255,.1); margin-top: 4px; } 202 .nav-links.mobile-open .dropdown a { color: rgba(255,255,255,.75); } 203 .nav-links.mobile-open .dropdown a:hover { background: rgba(255,255,255,.08); color: #fff; } 204 .nav-links.mobile-open .dropdown a i { color: var(--accent-light); } 205 @media (max-width: 640px) { .logo-text { display: none; } .nav-inner { gap: 8px; padding: 0 16px; } } 206 207 /* âââ NEWSLETTER âââ */ 208 .newsletter-section { background: var(--bg-light); padding: 64px 24px; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); } 209 .newsletter-inner { max-width: 640px; margin: 0 auto; text-align: center; } 210 .newsletter-icon { font-size: 42px; margin-bottom: 16px; display: block; } 211 .newsletter-inner h2 { font-size: 28px; font-weight: 800; letter-spacing: -.5px; margin-bottom: 10px; } 212 .newsletter-inner > p { font-size: 16px; color: var(--text-gray); margin-bottom: 28px; line-height: 1.65; } 213 .newsletter-form { display: flex; gap: 10px; margin-bottom: 14px; } 214 .newsletter-input { flex: 1; padding: 13px 16px; border: 1.5px solid var(--border); border-radius: var(--r-sm); font-size: 15px; outline: none; transition: border-color .2s; font-family: inherit; background: #fff; } 215 .newsletter-input:focus { border-color: var(--accent); } 216 .newsletter-submit { padding: 13px 22px; background: var(--primary); color: #fff; border: none; border-radius: var(--r-sm); font-size: 15px; font-weight: 700; cursor: pointer; transition: all .2s; font-family: inherit; white-space: nowrap; } 217 .newsletter-submit:hover { background: var(--primary-light); transform: translateY(-1px); } 218 .newsletter-error { color: #DC2626; font-size: 13px; margin-bottom: 10px; display: none; } 219 .newsletter-meta { font-size: 13px; color: var(--text-light); display: flex; gap: 20px; justify-content: center; flex-wrap: wrap; } 220 .newsletter-meta span { display: flex; align-items: center; gap: 5px; } 221 .newsletter-success { display: none; background: #ECFDF5; border-radius: var(--r-md); border: 1px solid #6EE7B7; padding: 24px; } 222 .newsletter-success h3 { font-size: 18px; font-weight: 700; color: #059669; margin-bottom: 6px; } 223 .newsletter-success p { font-size: 14px; color: #065F46; } 224 .newsletter-already { display: none; background: #EBF4FF; border-radius: var(--r-md); border: 1px solid var(--accent-light); padding: 16px 20px; font-size: 14px; color: var(--primary); font-weight: 500; } 225 226 /* âââ CARD DRAWER âââ */ 227 .drawer-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.52); z-index: 1100; opacity: 0; visibility: hidden; transition: all .3s; } 228 .drawer-overlay.open { opacity: 1; visibility: visible; } 229 .drawer { position: fixed; top: 0; right: 0; width: 440px; height: 100vh; background: #fff; z-index: 1101; overflow-y: auto; transform: translateX(100%); transition: transform .35s cubic-bezier(.4,0,.2,1); box-shadow: -8px 0 40px rgba(0,0,0,.2); } 230 .drawer.open { transform: translateX(0); } 231 .drawer-header { display: flex; align-items: center; justify-content: space-between; padding: 18px 24px; border-bottom: 1px solid var(--border); position: sticky; top: 0; background: #fff; z-index: 2; } 232 .drawer-header span { font-size: 13px; color: var(--text-gray); } 233 .drawer-close { width: 32px; height: 32px; background: var(--bg-light); border: none; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 14px; color: var(--text-gray); transition: all .2s; }
234 .drawer-close:hover { background: var(--border); color: var(--text-dark); } 235 .drawer-body { padding: 24px; } 236 .drawer-card-hd { display: flex; align-items: center; gap: 16px; margin-bottom: 18px; } 237 .drawer-card-img { width: 72px; height: 46px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; flex-shrink: 0; } 238 .drawer-card-name { font-size: 18px; font-weight: 800; line-height: 1.3; } 239 .drawer-card-sub { font-size: 13px; color: var(--text-gray); margin-top: 3px; } 240 .drawer-score-bar { display: flex; align-items: center; gap: 10px; background: var(--bg-light); border-radius: var(--r-sm); padding: 10px 14px; margin-bottom: 20px; } 241 .drawer-stars { color: var(--accent-gold); font-size: 15px; letter-spacing: 1px; } 242 .drawer-score-val { font-size: 15px; font-weight: 700; } 243 .drawer-score-lbl { font-size: 13px; color: var(--text-gray); } 244 .drawer-divider { height: 1px; background: var(--border); margin: 18px 0; } 245 .drawer-details { display: flex; flex-direction: column; gap: 11px; } 246 .drawer-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; } 247 .drawer-lbl { font-size: 13px; color: var(--text-gray); font-weight: 500; } 248 .drawer-val { font-size: 14px; font-weight: 600; color: var(--text-dark); text-align: right; } 249 .drawer-val.gold { color: #D97706; } 250 .drawer-proscons { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; } 251 .drawerpc h5 { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .8px; margin-bottom: 10px; } 252 .pros-title { color: #059669; } 253 .cons-title { color: #DC2626; } 254 .drawerpc ul { list-style: none; display: flex; flex-direction: column; gap: 8px; } 255 .drawerpc ul li { font-size: 13px; color: var(--text-gray); display: flex; gap: 7px; align-items: flex-start; line-height: 1.4; } 256 .drawerpc ul li span { flex-shrink: 0; font-size: 12px;
256 margin-top: 1px; } 257 .drawer-actions { display: flex; gap: 12px; position: sticky; bottom: 0; background: #fff; padding: 16px 24px; border-top: 1px solid var(--border); margin: 0 -24px -24px; } 258 .drawer-apply { flex: 1; padding: 13px; background: var(--primary); color: #fff; border: none; border-radius: var(--r-sm); font-size: 15px; font-weight: 700; cursor: pointer; transition: all .2s; font-family: inherit; } 259 .drawer-apply:hover { background: var(--primary-light); } 260 .drawer-learn { padding: 13px 18px; background: var(--bg-light); color: var(--text-dark); border: 1.5px solid var(--border); border-radius: var(--r-sm); font-size: 14px; font-weight: 600; cursor: pointer; transition: all .2s; font-family: inherit; white-space: nowrap; } 261 .drawer-learn:hover { border-color: var(--accent); color: var(--accent); } 262 263 /* ââââââââââââââââââââââââââââââââââââââââ 264 RESPONSIVE 265 ââââââââââââââââââââââââââââââââââââââââ */ 266 @media (max-width: 1024px) { 267 .nav-links { display: none; } 268 .hamburger { display: flex; } 269 .nav-actions { gap: 6px; } 270 .nav-actions .btn-primary, .nav-actions .btn-outline { padding: 7px 10px; font-size: 12px; white-space: nowrap; } 271 .navbar { position: relative; } 272 .comp-header { display: none; } 273 .comp-row { grid-template-columns: 1fr 1fr; gap: 10px; padding: 16px 20px; } 274 .comp-info { grid-column: 1 / -1; } 275 .footer-top { grid-template-columns: 1fr 1fr; gap: 36px; } 276 .drawer { width: 100%; max-width: 440px; } 277 } 278 @media (max-width: 768px) { 279 .section { padding: 52px 20px; } 280 .section-title { font-size: 26px; } 281 .comp-row { grid-template-columns: 1fr; } 282 .footer-top { grid-template-columns: 1fr; gap: 28px; } 283 .footer-bottom { flex-direction: column; align-items: flex-start; gap: 10px; } 284 .newsletter-form { flex-direction: column; } 285 .newsletter-submit { width: 100%; } 286 .drawer { width: 100%; } 287 } 288 289 /* âââ SKIP LINK âââ */ 290 .skip-link { position: absolute; top: -100%; left: 16px; background: var(--accent); color: #fff; padding: 10px 18px; border-radius: 0 0 var(--r-sm) var(--r-sm); font-size: 14px; font-weight: 700; text-decoration: none; z-index: 9999; transition: top .2s; } 291 .skip-link:focus { top: 0; } 292 293 /* âââ ADVERTISER DISCLOSURE BAR âââ */ 294 .adv-bar { background: #FFFBEB; border-bottom: 1px solid #FDE68A; padding: 10px 24px; } 295 .adv-bar-inner { max-width: 1280px; margin: 0 auto; font-size: 13px; color: #78350F; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; } 296 .adv-bar-inner i { color: #D97706; flex-shrink: 0; } 297 .adv-bar-inner a { color: #92400E; font-weight: 700; text-decoration: underline; } 298 .adv-bar-inner a:hover { color: #78350F; } 299 300 /* âââ COOKIE BANNER âââ */ 301 .cookie-banner { position: fixed; bottom: 0; left: 0; right: 0; background: var(--primary-dark); border-top: 1px solid rgba(255,255,255,.15); padding: 16px 24px; z-index: 2000; display: flex; align-items: center; gap: 20px; flex-wrap: wrap; box-shadow: 0 -4px 24px rgba(0,0,0,.3); animation: slideUp .35s ease; } 302 .cookie-banner.hidden { display: none; } 303 @keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } } 304 .cookie-banner p { font-size: 14px; color: rgba(255,255,255,.8); flex: 1; min-width: 200px; line-height: 1.5; margin: 0; } 305 .cookie-banner p a { color: var(--accent-light); text-decoration: underline; } 306 .cookie-actions { display: flex; gap: 10px; flex-shrink: 0; } 307 .cookie-accept { padding: 9px 20px; background: var(--accent); color: #fff; border: none; border-radius: 6px; font-size: 14px; font-weight: 700; cursor: pointer; transition: background .2s; font-family: inherit; } 308 .cookie-accept:hover { background: var(--accent-light); } 309 .cookie-decline { padding: 9px 16px; background: transparent; color: rgba(255,255,255,.65); border: 1px solid rgba(255,255,255,.25); border-radius: 6px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all .2s; font-family: inherit; } 310 .cookie-decline:hover { border-color: rgba(255,255,255,.6); color: #fff; } 311 312 /* âââ USER NAV (logged-in state) âââ */ 313 .user-nav { position: relative; } 314 .user-btn { display: flex; align-items: center; gap: 9px; padding: 5px 12px 5px 6px; background: rgba(255,255,255,.1); border: 1.5px solid rgba(255,255,255,.22); border-radius: 100px; cursor: pointer; transition: all .2s; color: #fff; font-family: inherit; font-size: 14px; font-weight: 600; } 315 .user-btn:hover { background: rgba(255,255,255,.18); border-color: rgba(255,255,255,.45); } 316 .user-avatar-sm { width: 30px; height: 30px; background: var(--accent); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 800; color: #fff; flex-shrink: 0; letter-spacing: -.5px; } 317 .user-name-sm { max-width: 100px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } 318 .user-btn .fa-chevron-down { font-size: 10px; opacity: .65; } 319 .user-dropdown { position: absolute; top: calc(100% + 10px); right: 0; background: #fff; border-radius: var(--r-md); box-shadow: var(--shadow-lg); border: 1px solid var(--border); min-width: 226px; padding: 10px; opacity: 0; visibility: hidden; transform: translateY(-8px); transition: all .2s; z-index: 2000; } 320 .user-nav.open .user-dropdown { opacity: 1; visibility: visible; transform: translateY(0); } 321 .user-dropdown-header { padding: 10px 12px 14px; border-bottom: 1px solid var(--border); margin-bottom: 8px; } 322 .user-dropdown-name { font-size: 15px; font-weight: 700; color: var(--text-dark); } 323 .user-dropdown-email { font-size: 12px; color: var(--text-gray); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 190px; } 324 .user-dropdown a { display: flex; align-items: center; gap: 10px; padding: 9px 12px; color: var(--text-dark); text-decoration: none; font-size: 14px; border-radius: var(--r-sm); transition: background .15s; } 325 .user-dropdown a:hover { background: var(--bg-light); color: var(--primary); } 326 .user-dropdown a i { width: 16px; color: var(--accent); font-size: 13px; text-align: center; } 327 .user-dropdown-divider { height: 1px; background: var(--border); margin: 8px 0; } 328 .user-signout { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 12px; color: #DC2626; background: none; border: none; font-size: 14px; cursor: pointer; border-radius: var(--r-sm); transition: background .15s; font-family: inherit; text-align: left; } 329 .user-signout:hover { background: #FEF2F2; } 330 .user-signout i { width: 16px; font-size: 13px; text-align: center; } 331 332 /* âââ PERSONAL MATCH BANNER (logged-in) âââ */ 333 .personal-banner { background: linear-gradient(135deg, #071E4A 0%, #0C2660 100%); border-bottom: 2px solid rgba(30,127,212,.6); padding: 13px 24px; } 334 .personal-banner.hidden { display: none; } 335 .personal-banner-inner { max-width: 1280px; margin: 0 auto; display: flex; align-items: center; gap: 16px; flex-wrap: wrap; } 336 .pb-greeting { font-size: 14px; color: rgba(255,255,255,.65); white-space: nowrap; flex-shrink: 0; } 337 .pb-greeting b { color: #fff; font-weight: 700; } 338 .pb-sep { width: 1px;
338 height: 26px; background: rgba(255,255,255,.14); flex-shrink: 0; } 339 .pb-label { font-size: 11px; color: rgba(255,255,255,.45); white-space: nowrap; flex-shrink: 0; font-weight: 600; text-transform: uppercase; letter-spacing: .8px; } 340 .pb-match { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; } 341 .pb-badge { width: 78px; height: 49px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 8px; font-weight: 700; flex-shrink: 0; overflow: hidden; } 342 .pb-card-name { font-size: 14px; font-weight: 700; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } 343 .pb-card-rate { font-size: 12px; color: rgba(255,255,255,.45); margin-top: 1px; white-space: nowrap; } 344 .pb-earn { font-size: 20px; font-weight: 800; color: var(--accent-gold); white-space: nowrap; flex-shrink: 0; line-height: 1; } 345 .pb-earn small { font-size: 10px; color: rgba(255,255,255,.4); font-weight: 400; display: block; margin-top: 2px; } 346 .pb-actions { display: flex; gap: 8px; align-items: center; flex-shrink: 0; } 347 .pb-acct-btn { padding: 7px 13px; background: rgba(255,255,255,.1); color: rgba(255,255,255,.85); border: 1px solid rgba(255,255,255,.2); border-radius: 6px; font-size: 12px; font-weight: 600; text-decoration: none; transition: all .2s; white-space: nowrap; display: inline-flex; align-items: center; gap: 5px; } 348 .pb-acct-btn:hover { background: rgba(255,255,255,.18); color: #fff; border-color: rgba(255,255,255,.45); } 349 .pb-retake { padding: 7px 13px; background: var(--accent); color: #fff; border: none; border-radius: 6px; font-size: 12px; font-weight: 600; cursor: pointer; transition: background .2s; font-family: inherit; white-space: nowrap; } 350 .pb-retake:hover { background: var(--accent-light); } 351 @media (max-width: 768px) { .pb-sep { display: none; } .pb-label { display: none; } .pb-earn { font-size: 17px; } } 352 353 /* âââ HERO: SPEND CALCULATOR âââ */ 354 .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } 355 .hx-inner { max-width: 1280px; margin: 0 auto; } 356 /* the hand: photo tinted into the navy, small line, five real cards fanned across the seam */ 357 .hx { position: relative; overflow: hidden; } 358 .hand { position: relative; overflow: hidden; background: var(--primary-dark); height: 640px; } 359 .hand::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 44px; z-index: 2; background: linear-gradient(to bottom right, transparent 49.5%, #fff 50.5%); } 360 .hand-photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 60% 40%; } 361 .hand-scrim { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(7,30,74,.8) 0, rgba(7,30,74,.8) 200px, rgba(7,30,74,.68) 300px, rgba(7,30,74,.68) 380px, var(--primary-dark) 520px); } 362 .hand-copy { position: relative; z-index: 3; padding: 36px 24px 0; } 363 .hand-copy h1 { font-size: 26px; font-weight: 800; color: #fff; line-height: 1.3; letter-spacing: -.5px; } 364 .hand-actions { display: flex; align-items: center; gap: 22px; margin-top: 16px; flex-wrap: wrap; } 365 .hand-go { display: inline-flex; align-items: center; height: 46px; padding: 0 20px; border: 1.5px solid rgba(255,255,255,.55); border-radius: 6px; color: #fff; font-size: 15px; font-weight: 600; text-decoration: none; } 366 .hand-go:hover { border-color: #fff; background: rgba(255,255,255,.08); } 367 .hand-all { display: inline-flex; align-items: center; min-height: 44px; color: #fff; font-size: 15px; font-weight: 600; } 368 /* the fan sits outside the clipped band so its lowest cards cross the seam onto the white */ 369 .hand-fan { position: absolute; left: 50%; top: 400px; width: 1060px; height: 520px; margin-left: -530px; z-index: 2; pointer-events: none; } 370 .hf { position: absolute; transform-origin: 50% 160%; } 371 .hf img { display: block; width: 460px; height: 290px; object-fit: cover; border-radius: 24px; box-shadow: 0 8px 20px rgba(0,0,0,.5); } 372 .hf1 { left: 0; top: 70px; transform: rotate(-28deg); } 373 .hf2 { left: 150px; top: 22px; transform: rotate(-14deg); }
374 .hf3 { left: 300px; top: 0; z-index: 1; } 375 .hf4 { left: 450px; top: 22px; transform: rotate(14deg); } 376 .hf5 { left: 600px; top: 70px; transform: rotate(28deg); } 377 .hx-calc-hd { padding: 290px 24px 0; } 378 .hx-calc-hd h2 { font-size: 52px; font-weight: 800; color: var(--primary-dark); line-height: 1.13; letter-spacing: -1.5px; font-variant-numeric: tabular-nums; } 379 .hero-badge { display: inline-flex; align-items: center; gap: 8px; background: rgba(255,255,255,.11); border: 1px solid rgba(255,255,255,.2); color: var(--accent-light); padding: 6px 14px; border-radius: 100px; font-size: 13px; font-weight: 500; margin-bottom: 18px; } 380 .hero-badge[hidden] { display: none; } 381 .hx-body { display: grid; grid-template-columns: minmax(0, 11fr) minmax(0, 13fr); gap: 72px; padding: 4px 24px 56px; align-items: start; } 382 383 .hx-head { display: flex; justify-content: space-between; padding-bottom: 10px; border-bottom: 1.5px solid var(--primary-dark); font-size: 13px; color: var(--text-gray); } 384 .hx-row { display: grid; grid-template-columns: 124px minmax(0, 1fr) 92px; align-items: center; gap: 16px; padding: 10px 0; border-bottom: 1px solid var(--border); } 385 .hx-row-label { font-size: 15px; font-weight: 600; color: var(--primary-dark); } 386 .hx-row-label small { display: block; font-size: 12px; font-weight: 400; line-height: 1.3; color: var(--text-gray); } 387 .hx-seg { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; border: 1px solid #CBD5E0; border-radius: 6px; overflow: hidden; } 388 .hx-seg button { height: 44px; padding: 0; border: 0; border-left: 1px solid #CBD5E0; background: #fff; color: var(--primary-dark); font: 600 14px/1 inherit; font-variant-numeric: tabular-nums; cursor: pointer; } 389 .hx-seg button:first-child { border-left: 0; } 390 .hx-seg button:hover { background: var(--bg-light); } 391 .hx-seg button[aria-pressed="true"] { background: var(--primary); color: #fff; } 392 .hx-seg button:focus-visible, .hx-tabs button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; } 393 .hx-earn { text-align: right; font-size: 14px; color: var(--text-gray); white-space: nowrap; font-variant-numeric: tabular-nums; } 394 .hx-earn strong { color: var(--primary-dark); font-weight: 700; } 395 .hx-note { margin-top: 16px; font-size: 13px; line-height: 1.6; color: var(--text-gray); } 396 .hx-note a, .hx-legal a { color: inherit; } 397 398 .hx-tabs { display: flex; gap: 24px; border-bottom: 1.5px solid var(--primary-dark); } 399 .hx-tabs button { height: 44px; padding: 0; border: 0; border-bottom: 3px solid transparent; margin-bottom: -1.5px; background: none; color: var(--text-gray); font: 600 14px/1 inherit; cursor: pointer; } 400 .hx-tabs button[aria-pressed="true"] { color: var(--primary-dark); border-bottom-color: var(--accent); } 401 .hx-stage { position: relative; height: 296px; margin-top: 8px; } 402 .hx-art { position: absolute; display: block; } 403 .hx-art img { display: block; width: 100%; height: 100%; } 404 /* Issuer art is a flat JPEG with white corners: clip them. 8.25% = 5.2% x the card's 1.586 ratio. */ 405 .hx-art.flat img, .cc-thumb.flat img { object-fit: cover; border-radius: 5.2% / 8.25%; } 406 .hx-art.flat img { box-shadow: 0 2px 3px rgba(7,30,74,.25), 14px 30px 56px rgba(7,30,74,.3); } 407 .hx-art.asis img, .cc-thumb.asis img { object-fit: contain; } 408 .hx-art.asis img { filter: drop-shadow(8px 18px 22px rgba(7,30,74,.28)); } 409 /* The Amex Gold art is two cards on a white field: blend the white away, never clip or shadow it. */ 410 .hx-art.gold img, .cc-thumb.gold img { object-fit: contain; mix-blend-mode: multiply; } 411 .hx-win { left: 0; top: 30px; width: 352px; height: 222px; transform: rotate(-8deg); z-index: 3; transition: transform .25s ease; } 412 .hx-win:hover { transform: rotate(-8deg) translateY(-6px); } 413 .hx-win.gold { transform: none; } 414 .hx-r2 { left: 206px; top: 14px; width: 280px; height: 177px; z-index: 2; } 415 .hx-r3 { left: 318px; top: 42px; width: 280px; height: 177px; transform: rotate(9deg); z-index: 1; } 416 .hx-meta { font-size: 13px; color: var(--text-gray); } 417 .hx-name { margin-top: 2px; font-size: 28px; font-weight: 800; letter-spacing: -.6px; line-height: 1.2; } 418 .hx-name a { color: var(--primary-dark); text-decoration: none; } 419 .hx-name a:hover { text-decoration: underline; } 420 .hx-figrow { display: flex; align-items: baseline; gap: 12px; margin-top: 10px; flex-wrap: wrap; } 421 .hx-fig { font-size: 64px; font-weight: 800; letter-spacing: -2.1px; line-height: 1; color: var(--primary-dark); font-variant-numeric: tabular-nums; } 422 .hx-figlabel { font-size: 15px; font-weight: 600; color: var(--text-gray); } 423 .hx-recip { margin-left: auto; font-size: 14px; color: var(--text-gray); font-variant-numeric: tabular-nums; } 424 .hx-recip strong { color: var(--primary-dark); } 425 .hx-ledger { margin-top: 14px; border-top: 1px solid var(--border); font-size: 14px; font-variant-numeric: tabular-nums; } 426 .hx-ledger div { display: flex; justify-content: space-between; gap: 16px; padding: 8px 0; border-bottom: 1px solid var(--border); color: var(--text-gray); } 427 .hx-ledger strong { color: var(--primary-dark); white-space: nowrap; } 428 .hx-worth { margin-top: 10px; font-size: 13px; line-height: 1.5; color: var(--text-gray); } 429 .hx-next { display: flex; gap: 8px 24px; flex-wrap: wrap; margin-top: 12px; font-size: 14px; color: var(--text-gray); font-variant-numeric: tabular-nums; } 430 .hx-next strong { color: var(--primary-dark); } 431 .hx-actions { display: flex; align-items: center; gap: 18px; margin-top: 16px; flex-wrap: wrap; } 432 .hx-cta { display: inline-flex; align-items: center; height: 48px; padding: 0 26px; background: var(--primary); color: #fff; border-radius: 6px; font-size: 15px; font-weight: 700; text-decoration: none; } 433 .hx-cta:hover { background: var(--primary-light); } 434 .hx-actions span { font-size: 14px; color: var(--text-gray); } 435 .hx-links { display: flex; flex-wrap: wrap; gap: 4px 22px; margin-top: 6px; font-size: 14px; font-weight: 600; } 436 .hx-links a { display: inline-flex; align-items: center; min-height: 44px; color: var(--primary); } 437 .hx-legal { margin-top: 10px; padding-top: 12px; border-top: 1px solid var(--border); font-size: 12px; line-height: 1.5; color: var(--text-gray); } 438 439 /* âââ HOMEPAGE SECTIONS âââ */ 440 .hp { padding: 0 24px; } 441 .hp-inner { max-width: 1280px; margin: 0 auto; padding: 56px 0 64px; border-top: 1px solid var(--border); } 442 .hp-first .hp-inner { border-top: 0; } 443 .hp-hd { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; margin-bottom: 24px; } 444 .hp-hd h2 { font-size: 36px; font-weight: 800; letter-spacing: -1px; line-height: 1.2; color: var(--primary-dark); } 445 .hp-hd > a, .hp-hd > span { font-size: 15px; white-space: nowrap; } 446 .hp-hd > a { display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; color: var(--primary); } 447 .hp-hd > span { color: var(--text-gray); } 448 .cc-thumb { display: block; flex-shrink: 0; } 449 .cc-thumb img { display: block; width: 100%; height: 100%; } 450 .cc-thumb.flat img { box-shadow: 0 1px 2px rgba(7,30,74,.25), 4px 8px 16px rgba(7,30,74,.2); } 451 452 .tools { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 72px; align-items: start; } 453 .cmp-row { display: grid; grid-template-columns: 150px repeat(3, minmax(0, 1fr)); column-gap: 20px; align-items: baseline; padding: 13px 0; border-bottom: 1px solid var(--border); font-size: 15px; font-variant-numeric: tabular-nums; } 454 .cmp-row > span:first-child { font-size: 14px; color: var(--text-gray); } 455 .cmp-row > span + span { font-weight: 600; color: var(--primary-dark); } 456 .cmp-head { align-items: end; padding: 0 0 14px; border-bottom: 1.5px solid var(--primary-dark); } 457 .cmp-head > span:first-child { font-size: 13px; } 458 .cmp-card { display: flex; flex-direction: column; gap: 10px; font-weight: 700; line-height: 1.3; } 459 .cmp-card .cc-thumb { width: 132px; height: 83px; } 460 .quiz-q { padding-bottom: 14px; border-bottom: 1.5px solid var(--primary-dark); font-size: 17px; font-weight: 700; line-height: 1.4; color: var(--primary-dark); } 461 .quiz-opt { display: flex; align-items: center; justify-content: space-between; min-height: 52px; border-bottom: 1px solid var(--border); font-size: 15px; font-weight: 500; color: var(--primary-dark); text-decoration: none; } 462 .quiz-opt:hover { color: var(--accent); } 463 .quiz-foot { margin-top: 14px; font-size: 13px; color: var(--text-gray); } 464 465 .off-row { display: grid; grid-template-columns: 88px minmax(0, 1.1fr) minmax(0, 1.5fr) 96px 96px 104px; column-gap: 24px; align-items: center; padding: 12px 0; border-bottom: 1px solid var(--border); font-size: 15px; color: var(--primary-dark); text-decoration: none; font-variant-numeric: tabular-nums; } 466 a.off-row:hover .off-name { text-decoration: underline; } 467 .off-head { padding: 0 0 8px; border-bottom: 1.5px solid var(--primary-dark); font-size: 13px; color: var(--text-gray); } 468 .off-row .cc-thumb { width: 88px; height: 55px; } 469 .off-name { font-weight: 700; line-height: 1.3; } 470 .off-issuer { display: block; font-size: 13px; font-weight: 400; color: var(--text-gray); } 471 .off-desc { color: var(--text-gray); line-height: 1.4; } 472 .off-val { font-size: 22px; font-weight: 800; letter-spacing: -.5px; } 473 .off-r { text-align: right; } 474 475 .lanes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; } 476 .lane { display: flex; flex-direction: column; justify-content: space-between; gap: 20px; padding: 24px; border: 1px solid var(--border); border-radius: var(--r-sm); color: var(--primary-dark); text-decoration: none; overflow: hidden; } 477 .lane:hover { border-color: var(--primary); } 478 .lane-art { position: relative; height: 128px; } 479 .lane-art .cc-thumb { position: absolute; width: 170px; height: 107px; } 480 .lane-art .cc-thumb:first-child { left: 0; top: 18px; transform: rotate(-5deg); z-index: 1; } 481 .lane-art .cc-thumb + .cc-thumb { left: 96px; top: 0; transform: rotate(6deg); } 482 .lane-ft { display: flex; justify-content: space-between; align-items: baseline; } 483 .lane-ft strong { font-size: 22px; font-weight: 800; letter-spacing: -.4px; } 484 .lane-ft span { font-size: 14px; color: var(--text-gray); } 485 486 .issuers { padding: 20px 24px; background: var(--bg-light); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); } 487 .issuers p { max-width: 1280px; margin: 0 auto; display: flex; flex-wrap: wrap; gap: 6px 28px; align-items: baseline; font-size: 15px; font-weight: 700; color: var(--primary-dark); } 488 .issuers p span:first-child { font-size: 13px; font-weight: 400; color: var(--text-gray); margin-right: 8px; } 489 490 .guides { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 72px; } 491 .guides a { color: var(--primary-dark); text-decoration: none; } 492 .guides a:hover h3 { text-decoration: underline; } 493 .g-tag { font-size: 13px; color: var(--accent); font-weight: 600; } 494 .g-meta { font-size: 13px; color: var(--text-gray); } 495 .g-lead { display: flex; flex-direction: column; gap: 14px; padding-top: 20px; border-top: 1.5px solid var(--primary-dark); } 496 .g-lead h3 { font-size: 34px; font-weight: 800; letter-spacing: -.9px; line-height: 1.18; } 497 .g-lead p { font-size: 17px; line-height: 1.6; color: var(--text-gray); } 498 .g-item { display: flex; flex-direction: column; gap: 6px; padding: 20px 0; border-top: 1px solid var(--border); } 499 .g-item:first-child { border-top: 1.5px solid var(--primary-dark); } 500 .g-item h3 { font-size: 19px; font-weight: 700; letter-spacing: -.2px; line-height: 1.3; } 501 .g-item p { font-size: 14px; line-height: 1.55; color: var(--text-gray); } 502 503 @media (max-width: 1024px) { 504 .hx-body { grid-template-columns: minmax(0, 1fr); gap: 40px; } 505 .hx-result { order: -1; } 506 .tools, .guides { grid-template-columns: minmax(0, 1fr); gap: 48px; } 507 .off-row { grid-template-columns: 88px minmax(0, 1fr) 96px 104px; } 508 .off-desc, .off-fee { display: none; } 509 } 510 @media (max-width: 640px) { 511 .hand { height: 500px; } 512 .hand::after { height: 24px; } 513 .hand-scrim { background: linear-gradient(180deg, rgba(7,30,74,.8) 0, rgba(7,30,74,.8) 150px, rgba(7,30,74,.68) 210px, rgba(7,30,74,.68) 290px, var(--primary-dark) 400px); } 514 .hand-copy { padding: 28px 20px 0; } 515 .hand-copy h1 { font-size: 24px; line-height: 1.25; max-width: 300px; } 516 .hand-actions { gap: 4px 18px; margin-top: 12px; } 517 .hand-go { height: 44px; padding: 0 18px; font-size: 14px; }
518 .hand-fan { top: 236px; width: 390px; height: 330px; margin-left: -195px; } 519 .hf { transform-origin: 50% 130%; } 520 .hf img { width: 210px; height: 132px; border-radius: 11px; } 521 .hf1, .hf5 { display: none; } 522 .hf2 { left: 40px; top: 44px; transform: rotate(-13deg); } 523 .hf3 { left: 90px; top: 0; } 524 .hf4 { left: 140px; top: 44px; transform: rotate(13deg); } 525 .hx-calc-hd { padding: 36px 20px 0; } 526 .hx-calc-hd h2 { font-size: 28px; letter-spacing: -.8px; } 527 .hx-body { padding: 0 20px 40px; } 528 .hx-row { grid-template-columns: minmax(0, 1fr) auto; gap: 8px 12px; } 529 .hx-seg { grid-column: 1 / -1; grid-row: 2; } 530 .hx-stage { height: 226px; } 531 .hx-win { width: 290px; height: 183px; top: 18px; } 532 .hx-r2 { left: 150px; top: 6px; width: 200px; height: 126px; } 533 .hx-r3 { display: none; } 534 .hx-fig { font-size: 56px; letter-spacing: -1.8px; } 535 .hx-recip { margin-left: 0; flex-basis: 100%; } 536 .hx-cta { width: 100%; justify-content: center; } 537 .hp { padding: 0 20px; } 538 .hp-inner { padding: 40px 0 44px; } 539 .hp-hd h2 { font-size: 26px; letter-spacing: -.6px; } 540 .cmp-row { grid-template-columns: 96px repeat(3, minmax(0, 1fr)); column-gap: 10px; font-size: 13px; } 541 .cmp-row > span:first-child { font-size: 12px; } 542 .cmp-card .cc-thumb { width: 100%; height: auto; aspect-ratio: 1.586; } 543 .off-row { grid-template-columns: 72px minmax(0, 1fr) auto; column-gap: 14px; } 544 .off-row .cc-thumb { width: 72px; height: 45px; } 545 .off-checked { display: none; } 546 .lanes { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; } 547 .lane { padding: 16px; gap: 14px; } 548 .lane-art { height: 84px; } 549 .lane-art .cc-thumb { width: 112px; height: 71px; } 550 .lane-art .cc-thumb + .cc-thumb { display: none; } 551 .lane-ft { flex-direction: column; gap: 2px; } 552 .lane-ft strong { font-size: 18px; } 553 .g-lead h3 { font-size: 24px; letter-spacing: -.5px; } 554 .g-lead p { font-size: 15px; } 555 } 556 @media (max-width: 1024px) and (min-width: 641px) { .hand-fan { transform: scale(.78); transform-origin: 50% 100%; } } 557 @media (prefers-reduced-motion: reduce) { 558 *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; scroll-behavior: auto !important; } 559 .reveal { opacity: 1 !important; transform: none !important; } 560 } 561 </style> 562
562<script src="nav-search.js?v=2"></script>
562 563</head> 564<body> 565<a href="#main-content" class="skip-link">Skip to main content</a> 566 567<!-- âââââââââââ NAVBAR âââââââââââ --> 568<nav class="navbar"> 569 <div class="nav-inner"> 570 <a href="/" class="logo"> 571 <div class="logo-icon"> 572 <img src="images/logo-icon.svg" alt="CardCompass compass logo" width="40" height="40"> 573 </div> 574 <span class="logo-text">Card<span>Compass</span></span> 575 </a> 576 577 <div class="nav-links" id="nav-links"> 578 <div class="nav-item"> 579 <button class="nav-link" aria-expanded="false" aria-haspopup="true">Credit Cards <i class="fas fa-chevron-down"></i></button> 580 <div class="dropdown"> 581 <a href="/all-cards" style="font-weight:700"><i class="fas fa-th-list"></i> All Credit Cards</a> 582 <div style="height:1px;background:#E2E8F0;margin:6px 0;"></div> 583 <a href="/bonus-offers"><i class="fas fa-gift"></i> Current Bonus Offers</a> 584 <a href="/cards?cat=cashback"><i class="fas fa-star"></i> Best Cash Back Cards</a> 585 <a href="/cards?cat=travel"><i class="fas fa-plane"></i> Best Travel Cards</a> 586 <a href="/cards?cat=hotel"><i class="fas fa-hotel"></i> Best Hotel Cards</a> 587 <a href="/cards?cat=airline"><i class="fas fa-plane-departure"></i> Best Airline Cards</a> 588 <a href="/cards?cat=gas"><i class="fas fa-gas-pump"></i> Best Gas Cards</a> 589 <a href="/cards?cat=dining"><i class="fas fa-utensils"></i> Best Dining Cards</a> 590 <a href="/cards?cat=nofee"><i class="fas fa-shield-alt"></i> No Annual Fee Cards</a> 591 <a href="/cards?cat=balancetransfer"><i class="fas fa-sync-alt"></i> Balance Transfer Cards</a> 592 <a href="/cards?cat=business"><i class="fas fa-briefcase"></i> Best Business Cards</a> 593 <a href="/cards?cat=student"><i class="fas fa-graduation-cap"></i> Student Cards</a> 594 <a href="/cards?cat=secured"><i class="fas fa-lock"></i> Build Credit / Secured</a> 595 </div> 596 </div> 597 <div class="nav-item"> 598 <button class="nav-link" aria-expanded="false" aria-haspopup="true">Rewards <i class="fas fa-chevron-down"></i></button> 599 <div class="dropdown"> 600 <a href="/rewards-calculator"><i class="fas fa-calculator"></i> Points Calculator</a> 601 <a href="/rewards-partners"><i class="fas fa-exchange-alt"></i> Transfer Partners</a> 602 <a href="/rewards-maximize"><i class="fas fa-chart-line"></i> Maximize Your Points</a> 603 <a href="/rewards-award-travel"><i class="fas fa-suitcase"></i> Award Travel Guide</a> 604 <a href="/rewards-optimizer"><i class="fas fa-dollar-sign"></i> Cash Back Optimizer</a> 605 <a href="/balance-transfer-calculator"><i class="fas fa-sync-alt"></i> Balance Transfer Calc</a> 606 </div> 607 </div> 608 <div class="nav-item"> 609 <button class="nav-link" aria-expanded="false" aria-haspopup="true">Airlines <i class="fas fa-chevron-down"></i></button> 610 <div class="dropdown"> 611 <a href="/airlines" style="font-weight:700"><i class="fas fa-plane"></i> All Airlines</a> 612 <div style="height:1px;background:#E2E8F0;margin:6px 0;"></div> 613 <a href="/airline-transfer-matrix"><i class="fas fa-table"></i> Transfer Partner Matrix</a> 614 <a href="/airline-search-programs"><i class="fas fa-search"></i> Search All 23 Programs</a> 615 <div style="height:1px;background:#E2E8F0;margin:6px 0;"></div> 616 <a href="/airlines/united"><i class="fas fa-plane-departure"></i> United MileagePlus</a> 617 <a href="/airlines/delta"><i class="fas fa-plane-departure"></i> Delta SkyMiles</a> 618 <a href="/airlines/american"><i class="fas fa-plane-departure"></i> American AAdvantage</a> 619 <a href="/airlines/southwest"><i class="fas fa-plane-departure"></i> Southwest Rapid Rewards</a> 620 <a href="/airlines/alaska"><i class="fas fa-plane-departure"></i> Alaska Mileage Plan</a> 621 <a href="/airlines/jetblue"><i class="fas fa-plane-departure"></i> JetBlue TrueBlue</a> 622 <a href="/airlines/hawaiian"><i class="fas fa-plane-departure"></i> Hawaiian Miles</a> 623 </div> 624 </div> 625 <a href="/quiz" class="nav-link">Card Quiz</a> 626 <a href="/compare" class="nav-link">Compare Cards</a> 627 <a href="/my-current-wallet" class="nav-link">My Current Wallet</a> 628 <a href="/guides" class="nav-link">Guides</a> 629 </div> 630 631 <div class="nav-actions"> 632 <a href="/login" class="btn-outline">Log In</a> 633 <a href="/get-started" class="btn-primary">Get Started Free</a> 634 </div> 635 <button class="hamburger" id="hamburger" aria-label="Toggle menu">
636 <span></span><span></span><span></span> 637 </button> 638 </div> 639</nav> 640 641<!-- âââââââââââ HERO: SPEND CALCULATOR âââââââââââ --> 642<section class="hx" id="main-content"> 643 <div class="hand"> 644 <img class="hand-photo" src="https://images.unsplash.com/photo-1556740738-b6a63e27c4df?w=1600&q=75&auto=format&fit=crop&monochrome=071e4a&con=-35&exp=8&blend=071e4a&bm=normal&blend-alpha=40" alt="" aria-hidden="true" fetchpriority="low"> 645 <div class="hand-scrim" aria-hidden="true"></div> 646 <div class="hx-inner hand-copy"> 647 <div class="hero-badge" id="hero-src-badge" hidden><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="var(--accent-gold)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="m16.24 7.76-1.804 5.411a2 2 0 0 1-1.265 1.265L7.76 16.24l1.804-5.411a2 2 0 0 1 1.265-1.265z"/></svg>Welcome to CardCompass. Start with a rough month of spending.</div> 648
648<script>(function(){try{var q=new URLSearchParams(location.search),s=(q.get('utm_source')||(q.get('gclid')||q.get('gbraid')||q.get('wbraid')?'google':q.get('fbclid')?'facebook':q.get('ref'))||'').toLowerCase();if(s)sessionStorage.setItem('cc_src',s);if(sessionStorage.getItem('cc_src'))document.getElementById('hero-src-badge').hidden=false;}catch(e){}})();</script>
648 649 <h1 id="hx-h1">Find the card that fits how you spend.</h1> 650 <p class="hand-actions"><a class="hand-go" href="#calc">Start with your spending</a><a class="hand-all" href="/all-cards">All <span data-card-count>114</span> cards</a></p> 651 </div> 652 </div> 653 <div class="hand-fan" aria-hidden="true"> 654 <span class="hf hf1"><img src="https://cdn.prodstatic.com/shared/images/cards/500x315/083f25c0-504f-11f0-962e-072d632f0110.png" alt="" loading="eager" decoding="async"></span> 655 <span class="hf hf2"><img src="https://cdn.prodstatic.com/shared/images/cards/500x315/8cd47490-949f-11f0-832a-f3f3309a1b0c.png" alt="" loading="eager" decoding="async"></span> 656 <span class="hf hf3"><img src="https://cdn.prodstatic.com/shared/images/cards/500x315/ae837480-ed19-11ee-b6aa-83dad90afdcd.png" alt="" loading="eager" decoding="async"></span> 657 <span class="hf hf4"><img src="https://cdn.prodstatic.com/shared/images/cards/500x315/a5c974a0-eb11-11f0-8b83-5b931725a212.png" alt="" loading="eager" decoding="async"></span> 658 <span class="hf hf5"><img src="https://cdn.prodstatic.com/shared/images/cards/500x315/4f675c90-7268-11e9-8bc5-4d4394516d65.png" alt="" loading="eager" decoding="async"></span> 659 </div> 660 <div class="hx-inner hx-calc-hd" id="calc"> 661 <h2 id="hx-calc-h2">What <span id="hx-total">$1,650</span> a month earns on a credit card</h2> 662 </div> 663 <div class="hx-inner hx-body"> 664 <div class="hx-inputs"> 665 <div class="hx-head"><span>Per month, roughly</span><span>Earns per year</span></div> 666 <div id="hx-rows" role="group" aria-label="Monthly spending"></div> 667 <p class="hx-note">Points counted at 1 cent each. Welcome offers counted at a conservative value, and only when this spending meets the offer's requirement. This ranks general rewards and cash back cards. Hotel, airline, business and credit-building cards are in <a href="/quiz">the quiz</a>.</p> 668 </div> 669 <div class="hx-result"> 670 <div class="hx-tabs" role="group" aria-label="Period"> 671 <button type="button" data-mode="yearOne" aria-pressed="true">Year one</button> 672 <button type="button" data-mode="after" aria-pressed="false">Every year after</button> 673 </div> 674 <div class="hx-stage" id="hx-stage"></div> 675 <div id="hx-detail"></div> 676 <p class="hx-legal">Rates and fees apply. Offers can change. We may earn a commission when you apply through our links and are approved. <a href="/advertiser-disclosure">Advertiser disclosure</a></p> 677 <div class="sr-only" role="status" id="hx-status"></div> 678 </div> 679 </div> 680</section> 681 682<!-- âââââââââââ ADVERTISER DISCLOSURE BAR âââââââââââ --> 683<div class="adv-bar"> 684 <div class="adv-bar-inner"> 685 <i class="fas fa-info-circle"></i> 686 <span><a href="/advertiser-disclosure">Advertiser Disclosure</a> â CardCompass may earn a commission when you apply through our links. This does not affect our ratings or rankings.</span> 687 </div> 688</div> 689 690<!-- âââââââââââ PERSONAL MATCH BANNER (logged-in) âââââââââââ --> 691<div class="personal-banner hidden" id="personal-banner"> 692 <div class="personal-banner-inner"> 693 <div class="pb-greeting"><i class="fas fa-hand"></i> Hey, <b id="pb-name">there</b></div> 694 <div class="pb-sep"></div> 695 <div class="pb-label">Your top match</div> 696 <div class="pb-match"> 697 <div class="pb-badge" id="pb-badge"></div> 698 <div> 699 <div class="pb-card-name" id="pb-card-name"></div> 700 <div class="pb-card-rate" id="pb-card-rate"></div> 701 </div> 702 </div> 703 <div class="pb-earn" id="pb-earn"><small>est. yearly value</small></div> 704 <div class="pb-actions"> 705 <a href="/account" class="pb-acct-btn"><i class="fas fa-user"></i> My Account</a> 706 <button class="pb-retake" onclick="location.href='/quiz'"><i class="fas fa-bullseye"></i> Update Preferences</button> 707 </div> 708 </div> 709</div> 710 711<!-- âââââââââââ TOOLS: COMPARE + QUIZ âââââââââââ --> 712<section class="hp hp-first" id="quiz"> 713 <div class="hp-inner tools"> 714 <div> 715 <div class="hp-hd" id="compare"><h2>Compare Cards</h2><a href="/compare" id="cmp-link">Compare these three</a></div> 716 <div id="cmp-table" role="table" aria-label="Your top three cards, side by side"></div> 717 </div> 718 <div> 719 <div class="hp-hd"><h2>Card Quiz</h2><span>7 questions</span></div> 720 <p class="quiz-q">What's your primary goal with a new credit card?</p> 721 <div id="quiz-opts"> 722 <a class="quiz-opt" href="/quiz?goal=travel" data-goal="travel">Earn travel rewards<i class="fas fa-chevron-right" aria-hidden="true" style="font-size:12px;color:var(--text-gray)"></i></a> 723 <a class="quiz-opt" href="/quiz?goal=cashback" data-goal="cashback">Maximize cash back<i class="fas fa-chevron-right" aria-hidden="true" style="font-size:12px;color:var(--text-gray)"></i></a> 724 <a class="quiz-opt" href="/quiz?goal=airline" data-goal="airline">Earn airline miles<i class="fas fa-chevron-right" aria-hidden="true" style="font-size:12px;color:var(--text-gray)"></i></a> 725 <a class="quiz-opt" href="/quiz?goal=hotel" data-goal="hotel">Earn hotel points<i class="fas fa-chevron-right" aria-hidden="true" style="font-size:12px;color:var(--text-gray)"></i></a> 726 <a class="quiz-opt" href="/quiz?goal=credit" data-goal="credit">Build or improve my credit<i class="fas fa-chevron-right" aria-hidden="true" style="font-size:12px;color:var(--text-gray)"></i></a> 727 <a class="quiz-opt" href="/quiz?goal=business" data-goal="business">Business card for my company<i class="fas fa-chevron-right" aria-hidden="true" style="font-size:12px;color:var(--text-gray)"></i></a> 728 </div> 729 <p class="quiz-foot">It picks up the spending you entered above.</p> 730 </div> 731 </div> 732</section> 733 734<!-- âââââââââââ CURRENT BONUS OFFERS âââââââââââ --> 735<section class="hp">
736 <div class="hp-inner"> 737 <div class="hp-hd"><h2>Current Bonus Offers</h2><a href="/bonus-offers">All bonus offers</a></div> 738 <div id="off-table" role="table" aria-label="Welcome offers, by our value"></div> 739 </div> 740</section> 741 742<!-- âââââââââââ CARDS BY TYPE âââââââââââ --> 743<section class="hp" id="categories"> 744 <div class="hp-inner"> 745 <div class="hp-hd"><h2><span data-card-count>114</span> cards, by type</h2><a href="/all-cards">All cards</a></div> 746 <div class="lanes" id="lanes"></div> 747 </div> 748</section> 749 750<!-- âââââââââââ ISSUERS âââââââââââ --> 751<div class="issuers"><p id="issuers"></p></div> 752 753<!-- âââââââââââ GUIDES âââââââââââ --> 754<section class="hp hp-first"> 755 <div class="hp-inner"> 756 <div class="hp-hd"><h2>Guides</h2><a href="/guides">All guides</a></div> 757 <div class="guides"> 758 <a class="g-lead" href="/guides/marriott-bonvoy-credit-cards-2026"> 759 <span class="g-tag">Hotel Cards</span> 760 <h3>Marriott Bonvoy Credit Cards 2026: Bold vs. Boundless vs. Brilliant vs. Business</h3> 761 <p>Four cards, two issuers, a $0 to $650 fee range. Here's which Bonvoy card's Free Night Award actually covers its own annual fee.</p> 762 <span class="g-meta">September 4, 2026 · 9 min read</span> 763 </a> 764 <div> 765 <a class="g-item" href="/guides/marriott-bonvoy-points-value-2026"> 766 <span class="g-tag">Rewards Strategy</span> 767 <h3>Marriott Bonvoy Points Value in 2026: What Your Points Are Really Worth</h3> 768 <p>A 100,000-point balance sounds like $1,000. It's closer to $750. Here's the formula to check any redemption before you book it.</p> 769 <span class="g-meta">September 4, 2026 · 7 min read</span> 770 </a> 771 <a class="g-item" href="/guides/best-business-travel-credit-cards-2026"> 772 <span class="g-tag">Business Cards</span> 773 <h3>Best Business Credit Cards for Travel in 2026</h3> 774 <p>Free employee cards, higher limits, and spend that stays off your personal credit report. Here’s which airline and hotel business co-brands are worth the fee.</p> 775 <span class="g-meta">September 3, 2026 · 10 min read</span> 776 </a> 777 <a class="g-item" href="/guides/best-hotel-credit-cards-2026"> 778 <span class="g-tag">Hotel Cards</span> 779 <h3>Best Hotel Credit Cards in 2026</h3> 780 <p>Most hotel cards are bought for the points and kept for the free night certificate. Here’s which certificates actually cover their own annual fee.</p> 781 <span class="g-meta">August 31, 2026 · 10 min read</span> 782 </a> 783 </div> 784 </div> 785 </div> 786</section> 787 788<!-- âââââââââââ NEWSLETTER âââââââââââ --> 789<section class="newsletter-section"> 790 <div class="newsletter-inner reveal"> 791 <span class="newsletter-icon"><i class="fas fa-envelope-open-text" style="color:var(--accent-gold)"></i></span> 792 <h2>Get the best card deals in your inbox</h2> 793 <p>An alert when we add a card or a welcome bonus jumps, and a roundup on the 1st of each month. No spam, ever.</p> 794 <div id="newsletter-wrap"> 795 <div class="newsletter-form"> 796 <input type="email" class="newsletter-input" id="nl-email" placeholder="[email protected]" autocomplete="email"> 797 <button class="newsletter-submit" onclick="submitNewsletter()">Subscribe Free â</button> 798 </div> 799 <div class="cf-turnstile" data-sitekey="0x4AAAAAADiVOynXw_ZhYDP0" style="margin:14px 0;"></div> 800 <div class="newsletter-error" id="nl-error">Please enter a valid email address.</div> 801 <div class="newsletter-meta" style="justify-content:center;"> 802 <span><i class="fas fa-check"></i> Unsubscribe anytime</span> 803 <span><i class="fas fa-check"></i> No spam, ever</span> 804 </div> 805 </div> 806 <div class="newsletter-success" id="nl-success"> 807 <h3><i class="fas fa-champagne-glasses"></i> You're in!</h3> 808 <p>Check your inbox to confirm your subscription. Your first deal alert is on the way.</p> 809 </div> 810 <div class="newsletter-already" id="nl-already"> 811 <i class="fas fa-check" style="color:#22c55e"></i> You're already subscribed â we'll keep sending you the best card deal
811s each month. 812 </div> 813 </div> 814</section> 815 816<!-- âââââââââââ FOOTER âââââââââââ --> 817<footer> 818 <div class="footer-inner"> 819 <div class="footer-top"> 820 <div class="footer-brand"> 821 <a href="/" class="logo"> 822 <div class="logo-icon"> 823 <img src="images/logo-icon.svg" alt="CardCompass compass logo" width="40" height="40"> 824 </div> 825 <span class="logo-text">Card<span>Compass</span></span> 826 </a> 827 <p>CardCompass helps you navigate the crowded world of credit cards with honest, data-driven recommendations â so you earn more on every dollar you spend.</p> 828 </div> 829 <div class="footer-col"> 830 <h4>Credit Cards</h4> 831 <a href="/cards?cat=cashback">Best Cash Back</a><a href="/cards?cat=travel">Best Travel Cards</a><a href="/cards?cat=hotel">Best Hotel Cards</a><a href="/cards?cat=airline">Best Airline Cards</a><a href="/cards?cat=nofee">No Annual Fee</a><a href="/cards?cat=balancetransfer">Balance Transfer</a><a href="/cards?cat=business">Business Cards</a><a href="/cards?cat=student">Student Cards</a><a href="/cards?cat=secured">Build Credit</a> 832 </div> 833 <div class="footer-col"> 834 <h4>Rewards</h4> 835 <a href="/rewards-calculator">Points Calculator</a><a href="/rewards-partners">Transfer Partners</a><a href="/rewards-award-travel">Award Travel Guide</a><a href="/rewards-maximize">Maximize Rewards</a><a href="/airlines">Airport Lounge Access</a><a href="/my-current-wallet">My Current Wallet</a> 836 </div> 837 <div class="footer-col"> 838 <h4>Company</h4> 839 <a href="/guides">Guides</a><a href="/about">About Us</a><a href="/about#methodology">How We Rate Cards</a><a href="/editorial-policy">Editorial Policy</a><a href="/advertiser-disclosure">Advertiser Disclosure</a><a href="/contact">Contact Us</a> 840 <a href="/account" id="footer-account-link" style="display:none;">My Account</a> 841 </div> 842 </div> 843 <div class="footer-bottom"> 844 <span>© 2026 CardCompass, Inc. CardCompass may receive compensation through credit card issuer partnerships. This does not influence our ratings or recommendations. <span class="footer-social" style="display:inline-flex;align-items:center;gap:14px;vertical-align:middle;margin-left:10px;"><a href="https://www.instagram.com/cardcompassapp/" target="_blank" rel="noopener" aria-label="CardCompass on Instagram" style="display:inline-flex;margin:0;"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="20" height="20" x="2" y="2" rx="5" ry="5"/><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/><line x1="17.5" x2="17.51" y1="6.5" y2="6.5"/></svg></a><a href="https://www.facebook.com/cardcompassapp" target="_blank" rel="noopener" aria-label="CardCompass on Facebook" style="display:inline-flex;margin:0;"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"/></svg></a></span></span> 845 <div class="foot-links"><a href="/privacy-policy">Privacy Policy</a><a href="/terms">Terms of Service</a><a href="/advertiser-disclosure">Advertiser Disclosure</a></div> 846 </div> 847 </div> 848</footer> 849 850<button class="scroll-top" onclick="window.scrollTo({top:0,behavior:'smooth'})" aria-label="Back to top"> 851 <i class="fas fa-arrow-up"></i> 852</button> 853 854<!-- âââââââââââ DRAWER âââââââââââ --> 855<div class="drawer-overlay" id="drawer-overlay" onclick="closeDrawer()"></div> 856<div class="drawer" id="card-drawer"> 857 <div class="drawer-header"> 858 <span>Card Details</span> 859 <button class="drawer-close" onclick="closeDrawer()" aria-label="Close">×</button> 860 </div> 861 <div class="drawer-body"> 862 <div class="drawer-card-hd"> 863 <div class="drawer-card-img" id="d-img"></div> 864 <div>
864<div class="drawer-card-name" id="d-name"></div><div class="drawer-card-sub" id="d-sub"></div></div> 865 </div> 866 <div class="drawer-score-bar"> 867 <span class="drawer-stars" id="d-stars"></span> 868 <span class="drawer-score-val" id="d-score"></span> 869 <span class="drawer-score-lbl">/ 5 â CardCompass Score</span> 870 </div> 871 <div class="drawer-divider"></div> 872 <div class="drawer-details" id="d-details"></div> 873 <div class="drawer-divider"></div> 874 <div class="drawer-proscons" id="d-proscons"></div> 875 </div> 876 <div class="drawer-actions"> 877 <button class="drawer-apply" id="drawer-apply-btn">Apply Now â</button> 878 <button class="drawer-learn" onclick="closeDrawer()">Close</button> 879 </div> 880</div> 881 882<!-- âââââââââââ COOKIE CONSENT BANNER âââââââââââ --> 883<div class="cookie-banner hidden" id="cookie-banner" role="dialog" aria-label="Cookie consent"> 884 <p>We use cookies to analyze site traffic and improve your experience. See our <a href="/privacy-policy">Privacy Policy</a> for details.</p> 885 <div class="cookie-actions"> 886 <button class="cookie-accept" onclick="acceptCookies()">Accept</button> 887 <button class="cookie-decline" onclick="declineCookies()">Decline</button> 888 </div> 889</div> 890
891<script src="nav-auth.js?v=2"></script>
vendor: 1 bytes, line 891
891
892<script> 893/* âââââââââââââââââââââââââââââââââââââââââââ 894 DATA â full card pool now comes from cards-data.js / 895 recommend-engine.js (window.ALL_CARDS / window.CCEngine), not a 896 hardcoded 5-card subset. See cardBadgeHtml() below for the shared 897 image-or-issuer-badge renderer used by the quiz results, banner, and 898 drawer instead of the old per-card badgeClass/badgeText fields. 899âââââââââââââââââââââââââââââââââââââââââââ */ 900// Fills whatever sized container it's placed in (.banner-card-img, 901// .drawer-card-img, .qrc-img all already set width/height via CSS). 902function cardBadgeHtml(c) { 903 if (c.cardImage) { 904 return '<img src="' + c.cardImage + '" alt="' + c.name + '" style="width:100%;height:100%;object-fit:cover;border-radius:6px;" onerror="this.style.display=\'none\'">'; 905 } 906 const bg = (c.cardArt && c.cardArt.bg) || 'linear-gradient(135deg,#1A3F6F 0%,#0D2A4A 100%)'; 907 const label = (c.issuer || '').substring(0, 4).toUpperCase(); 908 return '<div style="width:100%;height:100%;background:' + bg + ';color:#fff;font-size:10px;font-weight:800;display:flex;align-items:center;justify-content:center;border-radius:6px;">' + label + '</div>'; 909} 910 911/* âââââââââââââââââââââââââââââââââââââââââââ 912 AFFILIATE APPLY NOW 913âââââââââââââââââââââââââââââââââââââââââââ */ 914let currentBannerCardId = null; 915 916function applyNow(cardId, source) { 917 const allCards = window.ALL_CARDS || window.CCEngine.getCardPool(); 918 const c = allCards.find(x => x.id === cardId); 919 if (!c) return; 920 if (typeof gtag === 'function') { 921 gtag('event', 'apply_click', { card_name: c.name, card_issuer: c.issuer, source: source }); 922 } 923 window.open(window.getApplyUrl ? window.getApplyUrl(c) : c.applyUrl, '_blank', 'noopener,noreferrer'); 924} 925 926const REVIEWS = [ 927 { name: 'Sarah K.', initials: 'SK', av: 'av-blue', card: 'Chase Sapphire Preferred®', rating: 5, quote: 'Earned over $1,200 in travel rewards my first year. The sign-up bonus alone paid for a round-trip flight to Europe.' }, 928 { name: 'Marcus T.', initials: 'MT', av: 'av-accent', card: 'Amex Gold Card', rating: 5, quote: 'Best dining card I\'ve ever had. The 4à points at restaurants adds up incredibly fast â I earned enough for a free flight in 6 months.' }, 929 { name: 'Priya L.', initials: 'PL', av: 'av-gold', card: 'Citi Double Cash®', rating: 4, quote: 'Perfect for someone who doesn\'t want to think about categories. Flat 2% on everything, no annual fee. Simple and effective.' }, 930 { name: 'James R.', initials: 'JR', av: 'av-red', card: 'Capital One Venture X', rating: 5, quote: 'The lounge access alone justifies the fee. Free Priority Pass plus the $300 travel credit â it basically pays for itself year after year.' }, 931 { name: 'Emily C.', initials: 'EC', av: 'av-green', card: 'Discover it® Cash Back', rating: 4, quote: 'Great starter card. The Cashback Match in year one was a game changer â I made $400 cash back my first year with zero annual fee.' }, 932 { name: 'David M.', initials: 'DM', av: 'av-blue', card: 'Chase Sapphire Preferred®', rating: 5, quote: 'CardCompass matched me to this card based on my spending. Projected $1,100/year â I\'m actually earning $1,350. Incredible tool.' }, 933 { name: 'Rachel H.', initials: 'RH', av: 'av-accent', card: 'Amex Platinum', rating: 5, quote: 'After the $200 airline fee credit, $200 hotel credit, and Centurion lounge access, I\'m paying around $300 net for benefits worth well over $2,000.' }, 934 { name: 'Tyler B.', initials: 'TB', av: 'av-purple', card: 'Chase Freedom Unlimited', rating: 5, quote: 'No annual fee and I\'m earning $580 a year. CardCompass showed me I was leaving money on the table with my old card â switched immediately.' }, 935 { name: 'Natalie W.', initials: 'NW', av: 'av-teal', card: 'World of Hyatt Card', rating: 4, quote: 'Hyatt points are worth 2â3à more than Marriott. CardCompass\'s comparison made it obvious. I got a free 5-night stay in my first year.' }, 936 { name: 'Kevin S.', initials: 'KS', av: 'av-gold', card: 'Capital One Venture', rating: 5, quote: 'Transferred 80,000 miles to Air Canada and flew business class to London. Would have been $4,800 to buy the seat outright. This card is unreal.' }, 937 { name: 'Aisha J.', initials: 'AJ', av: 'av-green', card: 'Amex Gold Card', rating: 5, quote: 'I spend a lot on groceries and restaurants. The 4à categories earn me $900+ per year in points. The $120 dining credit covers Uber Eats monthly.' }, 938 { name: 'Michael T.', initials: 'MT', av: 'av-red', card: 'Citi Custom Cash®', rating: 5, quote: 'Automatically earns 5% on my top spend category each month. I don\'t have to think about it â it just optimizes itself. Best no-fee card I\'ve had.' }, 939 { name: 'Lauren P.', initials: 'LP', av: 'av-blue', card: 'Chase Sapphire Reserve®', rating: 5, quote: 'The $300 travel credit drops the effective fee to $250. Add Priority Pass, TSA PreCheck reimbursement, and 3à on travel â it pays for itself easily.' } 940]; 941 942/* âââââââââââââââââââââââââââââââââââââââââââ 943 CARD DRAWER 944âââââââââââââââââââââââââââââââââââââââââââ */ 945let drawerTriggerEl = null; 946let drawerCardId = null; 947 948const MIN_CREDIT_LABELS = {
949 poor: 'Poor â Fair (under 640)', fair: 'Fair â Good (640+)', building: 'Building Credit', 950 good: 'Good â Excellent (700+)', verygood: 'Very Good (740+)', excellent: 'Excellent (750+)' 951}; 952 953function openDrawer(id) { 954 const allCards = window.ALL_CARDS || window.CCEngine.getCardPool(); 955 const c = allCards.find(x => x.id === id); 956 if (!c) return; 957 958 drawerCardId = id; 959 drawerTriggerEl = document.activeElement; 960 961 document.getElementById('d-img').className = 'drawer-card-img'; 962 document.getElementById('d-img').innerHTML = cardBadgeHtml(c); 963 document.getElementById('d-name').textContent = c.name; 964 document.getElementById('d-sub').textContent = 'Best for: ' + c.bestFor; 965 966 const fullStars = Math.round(c.cardScore || 4); 967 const dStarFull = '<i class="fas fa-star" style="color:#F5A623"></i>'; 968 const dStarEmpty = '<i class="fas fa-star" style="color:#F5A623;opacity:.25"></i>'; 969 document.getElementById('d-stars').innerHTML = dStarFull.repeat(fullStars) + dStarEmpty.repeat(5 - fullStars); 970 document.getElementById('d-score').textContent = (c.cardScore || 4).toFixed(1); 971 972 document.getElementById('d-details').innerHTML = ` 973 <div class="drawer-row"><span class="drawer-lbl">Welcome Bonus</span><span class="drawer-val gold">${c.bonusDesc || c.bonusShort || 'See terms'}</span></div> 974 <div class="drawer-row"><span class="drawer-lbl">Annual Fee</span><span class="drawer-val">${c.annualFee > 0 ? '$' + c.annualFee + ' / year' : 'None'}</span></div> 975 <div class="drawer-row"><span class="drawer-lbl">Best Rewards Rate</span><span class="drawer-val">${c.rateLabel}</span></div> 976 <div class="drawer-row"><span class="drawer-lbl">Foreign Transaction Fee</span><span class="drawer-val">${c.foreignFee}</span></div> 977 <div class="drawer-row"><span class="drawer-lbl">Recommended Credit</span><span class="drawer-val">${MIN_CREDIT_LABELS[c.minScore] || 'Good â Excellent (700+)'}</span></div> 978 `; 979 980 const pros = c.pros.map(p => `<li><span><i class="fas fa-check-circle" style="color:#22c55e"></i></span>${p}</li>`).join(''); 981 const cons = c.cons.map(p => `<li><span><i class="fas fa-times-circle" style="color:#ef4444"></i></span>${p}</li>`).join(''); 982 document.getElementById('d-proscons').innerHTML = ` 983 <div class="drawerpc pros-col"><h5 class="pros-title">Pros</h5><ul>${pros}</ul></div> 984 <div class="drawerpc cons-col"><h5 class="cons-title">Cons</h5><ul>${cons}</ul></div> 985 `; 986 987 // Wire Apply Now button 988 const applyBtn = document.getElementById('drawer-apply-btn'); 989 applyBtn.onclick = () => applyNow(id, 'drawer'); 990 991 document.getElementById('drawer-overlay').classList.add('open'); 992 const drawer = document.getElementById('card-drawer'); 993 drawer.classList.add('open'); 994 document.body.style.overflow = 'hidden'; 995 996 // Focus the close button after transition 997 setTimeout(() => { 998 const closeBtn = drawer.querySelector('.drawer-close'); 999 if (closeBtn) closeBtn.focus(); 1000 }, 350); 1001 1002 if (typeof gtag === 'function') { 1003 gtag('event', 'card_detail_view', { card_name: c.name, card_issuer: c.issuer }); 1004 } 1005 1006 // Focus trap 1007 const FOCUSABLE = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'; 1008 drawer.addEventListener('keydown', trapFocus); 1009 function trapFocus(e) { 1010 if (e.key !== 'Tab') return; 1011 const focusable = Array.from(drawer.querySelectorAll(FOCUSABLE)).filter(el => !el.disabled); 1012 if (!focusable.length) { e.preventDefault(); return; } 1013 const first = focusable[0], last = focusable[focusable.length - 1]; 1014 if (e.shiftKey) { if (document.activeElement === first) { e.preventDefault(); last.focus(); } } 1015 else { if (document.activeElement === last) { e.preventDefault(); first.focus(); } } 1016 } 1017 drawer._trapFocus = trapFocus; 1018} 1019 1020function closeDrawer() { 1021 const drawer = document.getElementById('card-drawer'); 1022 if (drawer._trapFocus) { drawer.removeEventListener('keydown', drawer._trapFocus); delete drawer._trapFocus; } 1023 document.getElementById('drawer-overlay').classList.remove('open'); 1024 drawer.classList.remove('open'); 1025 document.body.style.overflow = ''; 1026 if (drawerTriggerEl) { drawerTriggerEl.focus(); drawerTriggerEl = null; } 1027} 1028 1029document.addEventListener('keydown', e => { if (e.key === 'Escape') closeDrawer(); }); 1030 1031/* âââââââââââââââââââââââââââââââââââââââââââ 1032 REVIEWS CAROUSEL 1033âââââââââââââââââââââââââââââââââââââââââââ */ 1034let carouselIndex = 0; 1035let carouselTimer; 1036 1037function getPerPage() { 1038 return window.innerWidth < 768 ? 1 : window.innerWidth < 1024 ? 2 : 3; 1039} 1040 1041function renderTrack() { 1042 const track = document.getElementById('reviews-track'); 1043 if (!track) return; 1044 const rvStarFull = '<i class="fas fa-star" style="color:#F5A623"></i>'; 1045 const rvStarEmpty = '<i class="fas fa-star" style="color:#F5A623;opacity:.25"></i>'; 1046 track.innerHTML = REVIEWS.map(r => { 1047 const stars = rvStarFull.repeat(r.rating) + rvStarEmpty.repeat(5 - r.rating); 1048 return `<div class="review-card"> 1049 <div class="review-stars">${stars}</div> 1050 <div class="review-quote">${r.quote}</div> 1051 <div class="review-author"> 1052 <div class="review-avatar ${r.av}">${r.initials}</div> 1053 <div><div class="review-name">${r.name}</div><div class="review-card-name">${r.card}</div></div> 1054 </div> 1055 </div>`; 1056 }).join(''); 1057} 1058 1059function slideToPage(page) { 1060 const perPage = getPerPage(); 1061 const track = document.getElementById('reviews-track'); 1062 if (!track) return; 1063 const card = track.querySelector('.review-card'); 1064 if (!card) return; 1065 const cardW = card.offsetWidth; 1066 const gap = 24;
1067 const maxPage = Math.ceil(REVIEWS.length / perPage) - 1; 1068 const safePage = Math.min(page, maxPage); 1069 track.style.transform = `translateX(-${safePage * perPage * (cardW + gap)}px)`; 1070} 1071 1072function updateDots() { 1073 const perPage = getPerPage(); 1074 const pages = Math.ceil(REVIEWS.length / perPage); 1075 const dots = document.getElementById('carousel-dots'); 1076 if (!dots) return; 1077 dots.innerHTML = ''; 1078 for (let i = 0; i < pages; i++) { 1079 const d = document.createElement('button'); 1080 d.className = 'carousel-dot' + (i === carouselIndex ? ' active' : ''); 1081 d.setAttribute('aria-label', `Page ${i + 1}`); 1082 d.onclick = () => { carouselIndex = i; slideToPage(i); updateDots(); resetTimer(); }; 1083 dots.appendChild(d); 1084 } 1085} 1086 1087function carousel(dir) { 1088 const perPage = getPerPage(); 1089 const pages = Math.ceil(REVIEWS.length / perPage); 1090 carouselIndex = (carouselIndex + dir + pages) % pages; 1091 slideToPage(carouselIndex); 1092 updateDots(); 1093 resetTimer(); 1094} 1095 1096function resetTimer() { 1097 clearInterval(carouselTimer); 1098 carouselTimer = setInterval(() => carousel(1), 5000); 1099} 1100 1101 1102/* âââââââââââââââââââââââââââââââââââââââââââ 1103 SCROLL ANIMATIONS (IntersectionObserver) 1104âââââââââââââââââââââââââââââââââââââââââââ */ 1105const revealObserver = new IntersectionObserver((entries) => { 1106 entries.forEach(el => { 1107 if (el.isIntersecting) { el.target.classList.add('visible'); revealObserver.unobserve(el.target); } 1108 }); 1109}, { threshold: 0.12 }); 1110 1111document.querySelectorAll('.reveal').forEach(el => revealObserver.observe(el)); 1112 1113 1114/* âââââââââââââââââââââââââââââââââââââââââââ 1115 COUNTER ANIMATION 1116âââââââââââââââââââââââââââââââââââââââââââ */ 1117function animateCount(el) { 1118 const target = parseInt(el.dataset.target); 1119 const divisor = parseInt(el.dataset.divisor) || 1; 1120 const suffix = el.dataset.suffix || ''; 1121 const prefix = el.dataset.prefix || ''; 1122 const duration = 1500; 1123 const start = performance.now(); 1124 1125 function step(now) { 1126 const progress = Math.min((now - start) / duration, 1); 1127 const ease = 1 - Math.pow(1 - progress, 3); 1128 const val = Math.round(target * ease / divisor); 1129 el.textContent = prefix + val.toLocaleString() + suffix; 1130 if (progress < 1) requestAnimationFrame(step); 1131 else el.textContent = el.dataset.final; 1132 } 1133 1134 el.dataset.final = el.textContent; 1135 requestAnimationFrame(step); 1136} 1137 1138const counterObserver = new IntersectionObserver((entries) => { 1139 entries.forEach(e => { 1140 if (e.isIntersecting) { animateCount(e.target); counterObserver.unobserve(e.target); } 1141 }); 1142}, { threshold: 0.5 }); 1143 1144document.querySelectorAll('[data-card-count]').forEach(el => { 1145 el.textContent = window.ALL_CARDS.length; 1146 if (el.dataset.target) el.dataset.target = window.ALL_CARDS.length; 1147}); 1148document.querySelectorAll('.trust-item .num[data-target]').forEach(el => counterObserver.observe(el)); 1149 1150/* âââââââââââââââââââââââââââââââââââââââââââ 1151 HAMBURGER (MOBILE NAV) 1152âââââââââââââââââââââââââââââââââââââââââââ */ 1153const hamburger = document.getElementById('hamburger'); 1154const navLinks = document.getElementById('nav-links'); 1155 1156hamburger.addEventListener('click', () => { 1157 const open = hamburger.classList.toggle('open'); 1158 navLinks.classList.toggle('mobile-open', open); 1159 hamburger.setAttribute('aria-expanded', open ? 'true' : 'false'); 1160}); 1161 1162document.addEventListener('click', e => { 1163 if (!hamburger.contains(e.target) && !navLinks.contains(e.target)) { 1164 hamburger.classList.remove('open'); 1165 navLinks.classList.remove('mobile-open'); 1166 } 1167}); 1168 1169/* âââââââââââââââââââââââââââââââââââââââââââ 1170 NEWSLETTER 1171âââââââââââââââââââââââââââââââââââââââââââ */ 1172async function submitNewsletter() { 1173 const emailEl = document.getElementById('nl-email'); 1174 const errEl = document.getElementById('nl-error'); 1175 const btn = document.querySelector('.newsletter-submit'); 1176 const email = emailEl.value.trim(); 1177 errEl.style.display = 'none'; 1178 1179 if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { 1180 errEl.style.display = 'block'; 1181 emailEl.focus(); 1182 return; 1183 } 1184 1185 const token = window.turnstile?.getResponse(); 1186 if (!token) { 1187 errEl.textContent = 'Please complete the verification below.'; 1188 errEl.style.display = 'block'; 1189 return; 1190 } 1191 1192 btn.disabled = true; 1193 btn.textContent = 'Subscribingâ¦'; 1194 1195 try { 1196 const res = await fetch('/api/subscribe', { 1197 method: 'POST', 1198 headers: { 'Content-Type': 'application/json' }, 1199 body: JSON.stringify({ email, cfToken: token }) 1200 }); 1201 const data = await res.json(); 1202 1203 if (data.status === 'subscribed') { 1204 localStorage.setItem('cc_subscribed', email); 1205 document.getElementById('newsletter-wrap').style.display = 'none'; 1206 document.getElementById('nl-success').style.display = 'block'; 1207 if (typeof gtag === 'function') gtag('event', 'newsletter_signup'); 1208 } else { 1209 throw new Error('bad response'); 1210 } 1211 } catch { 1212 errEl.textContent = 'Something went wrong â please try again.'; 1213 errEl.style.display = 'block'; 1214 btn.disabled = false;
1215 btn.textContent = 'Subscribe Free â'; 1216 window.turnstile?.reset(); 1217 } 1218} 1219 1220(function checkSubscribed() { 1221 if (localStorage.getItem('cc_subscribed')) { 1222 document.getElementById('newsletter-wrap').style.display = 'none'; 1223 document.getElementById('nl-already').style.display = 'block'; 1224 } 1225})(); 1226 1227/* âââââââââââââââââââââââââââââââââââââââââââ 1228 NAV SCROLL HELPERS 1229âââââââââââââââââââââââââââââââââââââââââââ */ 1230 1231/* âââââââââââââââââââââââââââââââââââââââââââ 1232 WELCOME TOAST (post-login redirect) 1233âââââââââââââââââââââââââââââââââââââââââââ */ 1234(function () { 1235 const msg = sessionStorage.getItem('cc_welcome'); 1236 if (!msg) return; 1237 sessionStorage.removeItem('cc_welcome'); 1238 const t = document.createElement('div'); 1239 t.style.cssText = 'position:fixed;bottom:28px;left:50%;transform:translateX(-50%) translateY(80px);background:#1A1A2E;color:#fff;padding:13px 22px;border-radius:12px;font-size:14px;font-weight:500;z-index:9999;opacity:0;transition:all .35s cubic-bezier(.4,0,.2,1);max-width:calc(100vw - 32px);width:max-content;text-align:center;box-shadow:0 8px 28px rgba(0,0,0,.25);font-family:Inter,sans-serif;'; 1240 // msg carries the user's name, so it goes in as text, not HTML. 1241 t.innerHTML = '<i class="fas fa-hand" style="margin-right:6px"></i>'; 1242 t.append(msg); 1243 document.body.appendChild(t); 1244 setTimeout(() => { t.style.opacity = '1'; t.style.transform = 'translateX(-50%) translateY(0)'; }, 100); 1245 setTimeout(() => { t.style.opacity = '0'; t.style.transform = 'translateX(-50%) translateY(80px)'; }, 4000); 1246 setTimeout(() => t.remove(), 4500); 1247})(); 1248 1249/* âââââââââââââââââââââââââââââââââââââââââââ 1250 BEST CARDS TABLE â DYNAMIC CATEGORY TABS 1251âââââââââââââââââââââââââââââââââââââââââââ */ 1252const ISSUER_BADGE = { 1253 'Chase': 'ci-chase', 1254 'American Express': 'ci-amex', 1255 'Citi': 'ci-citi', 1256 'Capital One': 'ci-cap', 1257 'Discover': 'ci-disc', 1258}; 1259function issuerBadge(issuer) { 1260 return ISSUER_BADGE[issuer] || 'ci-chase'; 1261} 1262 1263const COMP_PAGE_SIZE = 6; 1264let _compCat = 'bestoffers'; 1265 1266function _getFilteredCards(cat) { 1267 const allCards = window.ALL_CARDS || window.CCEngine.getCardPool(); 1268 let filtered = [...allCards] 1269 .filter(c => (c.categories || []).includes(cat)) 1270 .sort((a, b) => (b.cardScore || 0) - (a.cardScore || 0)); 1271 // Fallback: if no cards match, show top-rated overall 1272 if (!filtered.length) { 1273 filtered = [...allCards].sort((a, b) => (b.cardScore || 0) - (a.cardScore || 0)); 1274 } 1275 return filtered; 1276} 1277 1278function renderCompTable(cat, page) { 1279 page = (page === undefined) ? 0 : page; 1280 _compCat = cat; 1281 1282 const filtered = _getFilteredCards(cat); 1283 const totalPages = Math.max(1, Math.ceil(filtered.length / COMP_PAGE_SIZE)); 1284 const safePage = Math.min(Math.max(0, page), totalPages - 1); 1285 const pageCards = filtered.slice(safePage * COMP_PAGE_SIZE, (safePage + 1) * COMP_PAGE_SIZE); 1286 1287 const tbody = document.getElementById('comp-table-body'); 1288 if (!tbody) return; 1289 const header = `<div class="comp-header"> 1290 <span></span><span>Card</span><span>Welcome Bonus</span><span>Best Rate</span><span>Annual Fee</span><span></span> 1291 </div>`; 1292 1293 const rows = pageCards.map(c => { 1294 const badge = issuerBadge(c.issuer); 1295 const imgHtml = c.cardImage 1296 ? `<img src="${c.cardImage}" alt="${c.name}" loading="lazy" style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border-radius:8px;" onerror="this.style.display='none'">` 1297 : ''; 1298 const bonusShort = c.bonusShort || (c.bonusDesc ? c.bonusDesc.split(' after')[0] : 'â'); 1299 const bonusVal = c.bonusValue ? `â $${c.bonusValue.toLocaleStr
1299ing()} value` : ' '; 1300 const feeLabel = c.annualFee === 0 1301 ? '<span style="color:#10B981;font-weight:700;">$0/yr</span>' 1302 : `$${c.annualFee}/yr`; 1303 return `<div class="comp-row" onclick="openDrawer('${c.id}')"> 1304 <div class="comp-info"> 1305 <div class="comp-card-img ${badge}" style="position:relative;">${imgHtml}</div> 1306 <div> 1307 <div class="comp-name">${c.name}</div> 1308 <div class="comp-sub">${c.bestFor || ''}</div> 1309 </div> 1310 </div> 1311 <div class="comp-cell"><span class="hi">${bonusShort}</span><br><span class="tiny">${bonusVal}</span></div> 1312 <div class="comp-cell"><span class="badge">${c.rateLabel || 'â'}</span></div> 1313 <div class="comp-cell">${feeLabel}</div> 1314 <div class="comp-cell"><button class="comp-btn" onclick="event.stopPropagation();applyNow('${c.id}','comp_table')">Apply Now</button></div> 1315 </div>`; 1316 }).join(''); 1317 1318 tbody.innerHTML = header + rows; 1319 tbody.classList.add('visible'); 1320 1321 // Render pagination controls 1322 const pg = document.getElementById('comp-pagination'); 1323 if (pg) { 1324 if (totalPages <= 1) { 1325 pg.innerHTML = ''; 1326 } else { 1327 let pgHtml = `<button class="comp-pager-btn" onclick="renderCompTable('${cat}',${safePage - 1})" ${safePage === 0 ? 'disabled' : ''}><i class="fas fa-chevron-left"></i></button>`; 1328 for (let i = 0; i < totalPages; i++) { 1329 pgHtml += `<button class="comp-pager-num${i === safePage ? ' active' : ''}" onclick="renderCompTable('${cat}',${i})">${i + 1}</button>`; 1330 } 1331 pgHtml += `<button class="comp-pager-btn" onclick="renderCompTable('${cat}',${safePage + 1})" ${safePage === totalPages - 1 ? 'disabled' : ''}><i class="fas fa-chevron-right"></i></button>`; 1332 pg.innerHTML = pgHtml; 1333 } 1334 } 1335} 1336 1337// Wire up the category tabs â resets to page 0 on every tab switch 1338(function initCompTabs() { 1339 const tabs = document.querySelectorAll('.comp-tab'); 1340 renderCompTable('bestoffers', 0);
1341 tabs.forEach(btn => { 1342 btn.addEventListener('click', () => { 1343 tabs.forEach(t => t.classList.remove('active')); 1344 btn.classList.add('active'); 1345 renderCompTable(btn.dataset.cat, 0); 1346 }); 1347 }); 1348})(); 1349 1350/* âââââââââââââââââââââââââââââââââââââââââââ 1351 AUTH â PERSONAL BANNER (scores the full window.ALL_CARDS pool via 1352 window.CCEngine â this used to only ever consider 5 hardcoded cards) 1353âââââââââââââââââââââââââââââââââââââââââââ */ 1354(function updateBannerForAuth() { 1355 if (!localStorage.getItem('cc_token')) return; 1356 let user = null; 1357 try { user = JSON.parse(localStorage.getItem('cc_user') || 'null'); } catch(e) {} 1358 if (!user || !user.prefs) return; 1359 1360 const prefs = user.prefs; 1361 const profile = window.CCEngine.profileFromQuickForm(prefs.goal, prefs.spend, prefs.credit, prefs.maxFee); 1362 const maxFee = parseFloat(prefs.maxFee) || 9999; 1363 1364 const scored = window.CCEngine.rankCards(profile, { limit: 20 }) 1365 .filter(c => c.annualFee <= maxFee) 1366 .map(c => { 1367 const yearly = Object.keys(profile.spend).reduce( 1368 (sum, cat) => sum + window.CCEngine.estimateEarn(c, cat, profile.spend[cat]) * 12, 0); 1369 const net = Math.round(yearly + (c.bonusValue / 2) - c.annualFee); 1370 return Object.assign({}, c, { yearly: Math.round(yearly), net: net }); 1371 }) 1372 .sort((a, b) => b.net - a.net); 1373 1374 if (!scored.length) return; 1375 const top = scored[0]; 1376 const fname = user.fname || 'there'; 1377 document.getElementById('pb-name').textContent = fname; 1378 const badge = document.getElementById('pb-badge'); 1379 badge.className = 'pb-badge'; 1380 badge.innerHTML = cardBadgeHtml(top); 1381 document.getElementById('pb-card-name').textContent = top.name; 1382 document.getElementById('pb-card-rate').textContent = top.rateLabel + (top.annualFee > 0 ? ' · $' + top.annualFee + '/yr' : ' · No fee'); 1383 document.getElementById('pb-earn').innerHTML = '$' + top.net.toLocaleString() + '<small>est. yearly value</small>'; 1384 document.getElementById('personal-banner').classList.remove('hidden'); 1385})(); 1386 1387function toggleUserDropdown() { 1388 const nav = document.getElementById('user-nav'); 1389 if (!nav) return; 1390 const open = nav.classList.toggle('open'); 1391 document.getElementById('user-btn').setAttribute('aria-expanded', open ? 'true' : 'false'); 1392} 1393 1394/* Close dropdown on outside click */ 1395document.addEventListener('click', function(e) { 1396 const nav = document.getElementById('user-nav'); 1397 if (nav && !nav.contains(e.target)) { 1398 nav.classList.remove('open'); 1399 const btn = document.getElementById('user-btn'); 1400 if (btn) btn.setAttribute('aria-expanded', 'false'); 1401 } 1402}); 1403 1404// signOut() is provided by nav-auth.js (window.signOut) â it clears cc_token/cc_user 1405// and calls /api/auth/logout. Not redefined here so that shared implementation wins. 1406 1407/* âââââââââââââââââââââââââââââââââââââââââââ 1408 COOKIE CONSENT 1409âââââââââââââââââââââââââââââââââââââââââââ */ 1410function acceptCookies() { 1411 localStorage.setItem('cc_consent', 'granted'); 1412 document.getElementById('cookie-banner').classList.add('hidden'); 1413 if (typeof gtag === 'function') { 1414 gtag('consent', 'update', { analytics_storage: 'granted' }); 1415 } 1416} 1417 1418function declineCookies() { 1419 localStorage.setItem('cc_consent', 'denied'); 1420 document.getElementById('cookie-banner').classList.add('hidden'); 1421 if (typeof gtag === 'function') { 1422 gtag('consent', 'update', { analytics_storage: 'denied' }); 1423 } 1424} 1425 1426(function initCookieBanner() { 1427 if (localStorage.getItem('cc_consent')) return; 1428 const eu = /^Europe\//.test(Intl.DateTimeFormat().resolvedOptions().timeZone); 1429 const banner = document.getElementById('cookie-banner'); 1430 if (!eu) { 1431 banner.querySelector('p').innerHTML = 'We use analytics cookies to understand site traffic and improve CardCompass. You can opt out anytime â see our <a href="/privacy-policy">Privacy Policy</a>.'; 1432 banner.querySelector('.cookie-accept').textContent = 'OK'; 1433 banner.querySelector('.cookie-decline').textContent = 'Opt out'; 1434 }
1435 // Show banner after a short delay so page renders first 1436 setTimeout(() => banner.classList.remove('hidden'), 1500); 1437})(); 1438 1439/* âââââââââââââââââââââââââââââââââââââââââââ 1440 HOMEPAGE: SPEND CALCULATOR, COMPARE, OFFERS, LANES 1441 All ranking is window.CCEngine.rankBySpend (recommend-engine.js). 1442 Spend options are quiz.html's own buckets, so /quiz?grocery=450... 1443 pre-fills its spending question exactly. 1444âââââââââââââââââââââââââââââââââââââââââââ */ 1445(function homepage() { 1446 const cards = window.ALL_CARDS || []; 1447 const E = window.CCEngine; 1448 if (!cards.length || !E || !E.rankBySpend) return; 1449 1450 const CATS = [ 1451 ['grocery', 'Groceries', [0, 200, 450, 800]], 1452 ['dining', 'Dining out', [0, 200, 450, 800]], 1453 ['travel', 'Travel', [0, 200, 450, 800], 'booked through the cardâs portal'], 1454 ['gas', 'Gas', [0, 200, 450, 800]], 1455 ['other', 'Everything else', [200, 450, 800, 1500]] 1456 ]; 1457 const spend = { grocery: 450, dining: 200, travel: 0, gas: 200, other: 800 }; 1458 let mode = 'yearOne'; 1459 let touched = false; 1460 1461 const $ = id => document.getElementById(id); 1462 const esc = s => String(s).replace(/[&<>"]/g, ch => ({ '&': '&', '<': '<', '>': '>', '"': '"' }[ch])); 1463 const money = n => (n < 0 ? 'â$' : '$') + Math.abs(Math.round(n)).toLocaleString('en-US'); 1464 const short = c => c.name.replace(/[®â¢â ]/g, '').replace(/\s+(Credit )?Card( from .*)?$/i, '').trim(); 1465 const rate = (r, k) => (r.rates[k] || 0) + ((r.card.categories || []).includes('cashback') ? '%' : 'Ã'); 1466 const day = iso => new Date(iso + 'T12:00:00').toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); 1467 const track = cta => { if (typeof gtag === 'function') gtag('event', 'hero_cta_click', { cta: cta }); }; 1468 1469 // The site stores 219px issuer art; the same host serves 500px. Art from anywhere 1470 // else is shown as supplied (it is often angled or transparent). 1471 const COMPOSITE = ['amex-gold']; 1472 function art(c, cls, tag) { 1473 const src = (c.cardImage || '').replace('/cards/219x139/', '/cards/500x315/'); 1474 const kind = COMPOSITE.includes(c.id) ? 'gold' : /cdn\.prodstatic\.com/.test(src) ? 'flat' : 'asis'; 1475 const img = '<img src="' + esc(src) + '" alt="' + (tag === 'a' ? esc(c.name) : '') + '" loading="lazy">'; 1476 return tag === 'a' 1477 ? '<a class="' + cls + ' ' + kind + '" href="/card/' + c.id + '" data-cta="card">' + img + '</a>' 1478 : '<span class="' + cls + ' ' + kind + '" aria-hidden="true">' + img + '</span>'; 1479 } 1480 1481 function render() { 1482 const ranked = E.rankBySpend(spend, { mode: mode }); 1483 const top = ranked[0], c = top.card; 1484 const total = CATS.reduce((s, x) => s + spend[x[0]], 0); 1485 const after = mode === 'after'; 1486 $('hx-total').textContent = money(total); 1487 1488 $('hx-rows').innerHTML = CATS.map(([k, label, opts, sub]) => 1489 '<div class="hx-row"><span class="hx-row-label">' + label + (sub ? '<small>' + sub + '</small>' : '') + '</span>' + 1490 '<div class="hx-seg" role="group" aria-label="' + label + ' per month">' + 1491 opts.map(v => '<button type="button" data-cat="' + k + '" data-val="' + v + '" aria-pressed="' + (spend[k] === v) + '">' + money(v) + '</button>').join('') + 1492 '</div><span class="hx-earn">' + rate(top, k) + ' <strong>' + money(top.perCat[k]) + '</strong></span></div>').join(''); 1493 1494 // Two cards fan out behind the winner. Composite art cannot sit in a fan, so the 1495 // fan skips it; "Next best" below still names the true second and third. 1496 const fan = COMPOSITE.includes(c.id) ? [] : ranked.slice(1).filter(r => !COMPOSITE.includes(r.card.id)).slice(0, 2); 1497 $('hx-stage').innerHTML = art(c, 'hx-art hx-win', 'a') + 1498 (fan[0] ? art(fan[0].card, 'hx-art hx-r2') : '') + (fan[1] ? art(fan[1].card, 'hx-art hx-r3') : ''); 1499 1500 const q = new URLSearchParams(spend).toString(); 1501 const three = ranked.slice(0, 3).map(r => r.card); 1502 const cmpHref = '/compare?' + three.map((x, i) => 'abc'[i] + '=' + x.id).join('&'); 1503 const welcome = top.met 1504 ? '<div><span>Welcome offer: ' + esc(c.bonusDesc || c.bonusShort || '') + '</span><strong>+' + money(top.welcome) + '</strong></div>' 1505 : '<div><span>Welcome offer needs ' + money(top.req.amount) + ' in ' + top.req.months + ' months, not counted at this spending</span><strong>$0</strong></div>'; 1506 $('hx-detail').innerHTML = 1507 '<div class="hx-meta">' + esc(c.issuer) + (top.checked ? ' · Offer checked ' + day(top.checked) : '') + '</div>' + 1508 '<h2 class="hx-name"><a href="/card/' + c.id + '" data-cta="card">' + esc(c.name) + '</a></h2>' + 1509 '<div class="hx-figrow"><span class="hx-fig">' + money(after ? top.after : top.yearOne) + '</span>' + 1510 '<span class="hx-figlabel">' + (after ? 'every year after' : 'in year one') + '</span>' + 1511 '<span class="hx-recip"><strong>' + money(after ? top.yearOne : top.after) + '</strong> ' + (after ? 'in year one' : 'every year after') + '</span></div>' + 1512 '<div class="hx-actions"><a class="hx-cta" href="/quiz?' + q + '" data-cta="quiz">Continue in the quiz</a>' + 1513 '<span>Your numbers carry over. It ranks all ' + cards.length + ' cards.<
1513/span></div>' + 1514 '<div class="hx-ledger"><div><span>Rewards on this spending</span><strong>' + money(top.rewards) + '</strong></div>' + 1515 (after ? '' : welcome) + 1516 '<div><span>Annual fee</span><strong>' + (top.fee ? 'â' + money(top.fee) : '$0') + '</strong></div></div>' + 1517 (c.note ? '<p class="hx-worth">' + esc(c.note) + '</p>' : '') + 1518 '<div class="hx-next"><span>Next best</span>' + ranked.slice(1, 3).map(r => 1519 '<span>' + esc(short(r.card)) + ' <strong>' + money(after ? r.after : r.yearOne) + '</strong></span>').join('') + '</div>' + 1520 '<p class="hx-links"><a href="' + cmpHref + '" data-cta="compare">Compare these three side by side</a>' + 1521 '<a href="/card/' + c.id + '" data-cta="card">Card details</a>' + 1522 (c.guideUrl ? '<a href="' + esc(c.guideUrl) + '" data-cta="guide">Our guide</a>' : '') + '</p>'; 1523 $('hx-status').textContent = c.name + ', ' + money(after ? top.after : top.yearOne) + (after ? ' every year after.' : ' in year one.'); 1524 1525 // Compare Cards follows the same three. 1526 const row = (label, f) => '<div class="cmp-row" role="row"><span role="rowheader">' + label + '</span>' + three.map(x => '<span role="cell">' + f(x) + '</span>').join('') + '</div>'; 1527 const floor = x => { const r = ranked.find(y => y.card === x); return r.offer ? money(r.offer) : 'None'; }; 1528 $('cmp-table').innerHTML = 1529 '<div class="cmp-row cmp-head" role="row"><span role="columnheader">Your top three, from the numbers above</span>' + 1530 three.map(x => '<span class="cmp-card" role="columnheader">' + art(x, 'cc-thumb') + esc(short(x)) + '</span>').join('') + '</div>' + 1531 row('Welcome offer', x => esc(x.bonusShort || 'None')) + row('Our value', floor) + 1532 row('Annual fee', x => money(x.annualFee || 0)) + 1533 CATS.map(([k, label]) => row(label, x => rate(ranked.find(y => y.card === x), k))).join(''); 1534 $('cmp-link').href = cmpHref; 1535 document.querySelectorAll('#quiz-opts a').forEach(a => { a.href = '/quiz?goal=' + a.dataset.goal + '&' + q; }); 1536 } 1537 1538 $('hx-rows').addEventListener('click', e => { 1539 const b = e.target.closest('button[data-cat]'); 1540 if (!b) return; 1541 spend[b.dataset.cat] = +b.dataset.val; 1542 if (!touched && typeof gtag === 'function') gtag('event', 'hero_calc_use', { category: b.dataset.cat }); 1543 touched = true; 1544 render(); 1545 const again = $('hx-rows').querySelector('[data-cat="' + b.dataset.cat + '"][data-val="' + b.dataset.val + '"]'); 1546 if (again) again.focus(); // the rows re-render; keep the keyboard user's place 1547 }); 1548 document.querySelectorAll('.hx-tabs button').forEach(b => b.addEventListener('click', () => { 1549 mode = b.dataset.mode; 1550 document.querySelectorAll('.hx-tabs button').forEach(x => x.setAttribute('aria-pressed', String(x === b))); 1551 render(); 1552 })); 1553 document.querySelector('.hx').addEventListener('click', e => { 1554 const a = e.target.closest('a[data-cta]'); 1555 if (a) track(a.dataset.cta); 1556 }); 1557 render(); 1558 1559 /* ââ Current Bonus Offers: the conservative floor, never the headline; stale offers are skipped ââ */ 1560 const F = window.CARD_FRESHNESS || {}; 1561 const offers = cards 1562 .filter(x => F[x.id] && F[x.id].bonusFloor > 0 && !(window.getBonusDisplay && window.getBonusDisplay(x).stale)) 1563 .sort((a, b) => F[b.id].bonusFloor - F[a.id].bonusFloor || (a.annualFee || 0) - (b.annualFee || 0)) 1564 .slice(0, 7); 1565 $('off-table').innerHTML = 1566 '<div class="off-row off-head" role="row"><span></span><span role="columnheader">Card</span><span class="off-desc" role="columnheader">Welcome offer</span>' + 1567 '<span class="off-r" role="columnheader">Our value</span><span class="off-r off-fee" role="columnheader">Annual fee</span><span class="off-r off-checked" role="columnheader">Last checked</span></div>' + 1568 offers.map(x => '<a class="off-row" role="row" href="/card/' + x.id + '">' + art(x, 'cc-thumb') + 1569 '<span class="off-name" role="cell">' + esc(x.name) + '<span class="off-issuer">' + esc(x.issuer) + '</span></span>' + 1570 '<span class="off-desc" role="cell">' + esc(x.bonusDesc || x.bonusShort || '') + '</span>' + 1571 '<span class="off-val off-r" role="cell">' + money(F[x.id].bonusFloor) + '</span>' + 1572 '<span class="off-r off-fee" role="cell">' + money(x.annualFee || 0) + '</span>' + 1573 '<span class="off-r off-checked" role="cell">' + day(F[x.id].bonusUpdated) + '</span></a>').join(''); 1574 1575 /* ââ Cards by type: live counts, the two best-scored cards of each lane as art ââ */ 1576 const LANES = [['travel', 'Travel'], ['cashback', 'Cash back'], ['dining', 'Dining'], ['nofee', 'No annual fee'], ['secured', 'Build credit'], ['business', 'Business']]; 1577 const used = new Set(); 1578 $('lanes').innerHTML = LANES.map(([k, label]) => { 1579 const inLane = cards.filter(x => (x.categories || []).includes(k)); 1580 const pics = inLane.filter(x => /cdn\.prodstatic\.com/.test(x.cardImage || '') && !COMPOSITE.includes(x.id) && !used.has(x.id) 1581 && (k === 'business' || !(x.categories || []).includes('business'))) // consumer lanes show consumer cards 1582 .sort((a, b) => (b.cardScore || 0) - (a.cardScore || 0)).slice(0, 2); 1583 pics.forEach(x => used.add(x.id)); 1584 return '<a class="lane" href="/cards?cat=' + k + '"><div class="lane-art">' + pics.map(x => art(x, 'cc-thumb')).join('') + '</div>' + 1585 '<div class="lane-ft"><strong>' + label + '</strong><span>' + inLane.length + ' cards</span></div></a>'; 1586 }).join(''); 1587 1588 /* ââ Issuers ââ */ 1589 const byIssuer = {}; 1590 cards.forEach(x =>
1590 { byIssuer[x.issuer] = (byIssuer[x.issuer] || 0) + 1; }); 1591 const names = Object.keys(byIssuer).sort((a, b) => byIssuer[b] - byIssuer[a]); 1592 $('issuers').innerHTML = '<span>' + cards.length + ' cards from ' + names.length + ' issuers</span>' + names.slice(0, 9).map(n => '<span>' + esc(n) + '</span>').join(''); 1593})(); 1594</script>
vendor: 1 bytes, line 1594
1594
1595<script src="/newsletter-popup.js" defer></script>
vendor: 1 bytes, line 1595
1595
1596<script>(function(){function c(){var b=a.contentDocument||(a.contentWindow&&a.contentWindow.document);if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'a4027cbb9a8b36b2',t:'MTc5MDI2MDIyOA=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script>
1596<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"e79d8b0449fb411087aba9b1640e3938","r":1,"spa":2}' crossorigin="anonymous"></script>
1596 1597</body> 1598</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.