PageSourceSearch

https://quonn.com/favorites

html quonn.com collected 2026-09-28 01:45:41 UTC 187,888 bytes, 3,341 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3<head>
4    <meta charset="UTF-8">
5    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, shrink-to-fit=no, viewport-fit=cover">
6    <title>Your Saved Names | Nameoffice.com</title>
7<meta name="description" content="View your saved business names, compare favorites, and jump back into the NameOffice catalog when you are ready to buy."><link rel="canonical" href="https://quonn.com/favorites">    <link rel="alternate" href="https://quonn.com/favorites" hreflang="en">
8    <link rel="alternate" href="https://quonn.com/favorites" hreflang="x-default">
9
10<meta property="og:type" content="website">
11<meta property="og:site_name" content="NameOffice">
12<meta property="og:title" content="Your Saved Names | Nameoffice.com">
13<meta property="og:description" content="View your saved business names, compare favorites, and jump back into the NameOffice catalog when you are ready to buy."><meta property="og:url" content="https://quonn.com/favorites">    <meta property="og:image" content="https://quonn.com/build/img/nameoffice-logo-og.png">
14    <meta property="og:image:secure_url" content="https://quonn.com/build/img/nameoffice-logo-og.png">
15                
16<meta name="twitter:card" content="summary_large_image">
17<meta name="twitter:title" content="Your Saved Names | Nameoffice.com">
18<meta name="twitter:description" content="View your saved business names, compare favorites, and jump back into the NameOffice catalog when you are ready to buy.">    <meta name="twitter:image" content="https://quonn.com/build/img/nameoffice-logo-og.png">
19    
20    <link rel="icon" type="image/png" href="/brand/nameoffice-symbol.png">
21    
21<script src="https://cdn.tailwindcss.com"></script>
21
22    <link rel="preconnect" href="https://fonts.googleapis.com">
23    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
24    <link href="https://fonts.googleapis.com/css2?family=Inter:[email protected]&display=swap" rel="stylesheet">
25    <link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.8/css/line.css">
26    <link rel="stylesheet" href="/build/front.fa79a3e3.css">
27    
27<script>
28        tailwind.config = { theme: { extend: {
29            colors: { navy: { DEFAULT: '#01102E', deep: '#080e1f' }, mint: { DEFAULT: '#74F7B2' } },
30            fontFamily: { sans: ['Inter','system-ui','sans-serif'] },
31        }}}
32    </script>
32
33    <style> body { font-feature-settings:"ss01","cv11"; -webkit-font-smoothing:antialiased; } </style>
34        
34<script>
35    window.dataLayer = window.dataLayer || [];
36    function gtag(){ dataLayer.push(arguments); }
37
38    // Must run before gtag.js loads, otherwise the first hit ignores consent.
39    // Denied by default where prior opt-in is required, granted where consent
40    // is implied until the visitor declines. Decided server side from the
41    // country, the same call the banner and the pixel make.
42    (function () {
43        var requireOptIn = true;
44        var start = requireOptIn ? 'denied' : 'granted';
45
46        gtag('consent', 'default', {
47            ad_storage: start,
48            ad_user_data: start,
49            ad_personalization: start,
50            analytics_storage: start,
51            functionality_storage: start,
52            personalization_storage: start,
53            security_storage: 'granted',
54            wait_for_update: 500
55        });
56    })();
57
58    (function () {
59        function readConsent() {
60            var m = document.cookie.match('(^|;)\\s*cookie_consent\\s*=\\s*([^;]+)');
61            if (!m) return null;
62            try { return JSON.parse(decodeURIComponent(m[2])); } catch (e) { return null; }
63        }
64
65        function apply(consent) {
66            if (!consent) return;
67            var analytics = consent.analytics ? 'granted' : 'denied';
68            // No marketing category yet means ads storage stays denied. When a
69            // marketing toggle is added, `consent.marketing` drives these three.
70            var marketing = consent.marketing ? 'granted' : 'denied';
71            gtag('consent', 'update', {
72                analytics_storage: analytics,
73                functionality_storage: analytics,
74                personalization_storage: marketing,
75                ad_storage: marketing,
76                ad_user_data: marketing,
77                ad_personalization: marketing
78            });
79        }
80
81        apply(readConsent());
82        window.addEventListener('cookieconsent:changed', function (e) { apply(e.detail || readConsent()); });
83    })();
84
85    gtag('js', new Date());
86    gtag('config', 'G-R1P1T58PSS');
87</script>
vendor: 64 bytes, lines 87-88
87
88<script async src="https://www.googletagmanager.com/gtag/js?id=
88G-R1P1T58PSS
vendor: 13 bytes, lines 88-89
88"></script>
89
90<script>
91(function () {
92    var PIXEL_ID = "1386794040301436";
93    var loaded = false;
94
95    /* Read the consent cookie directly rather than window.cookieConsent.
96       This partial runs in the head and the consent script runs at the end of
97       the body, so that global does not exist yet. A returning visitor who
98       already agreed would otherwise never get the pixel, because the change
99       event only fires when someone changes their mind. */
100    /* Decided server side, the same way the banner decides it, so the two can
101       never disagree about whether this visitor has to be asked first. */
102    var REQUIRE_OPTIN = true;
103
104    function allowed() {
105        try {
106            if (window.cookieConsent) return !!window.cookieConsent.marketing;
107
108            var m = document.cookie.match('(^|;)\\s*cookie_consent\\s*=\\s*([^;]+)');
109            if (m) {
110                var c = JSON.parse(decodeURIComponent(m[2]));
111                return !!(c && c.v === 1 && c.marketing);
112            }
113
114            /* No stored choice. Where prior opt-in is required that means no,
115               and it keeps meaning no until they say otherwise. */
116            return !REQUIRE_OPTIN;
117        } catch (e) {
118            return false;
119        }
120    }
121
122    function load() {
123        if (loaded || !allowed()) return;
124        loaded = true;
125
126        /* Meta's standard loader. */
127        !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
128        n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
129        n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
130        t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
131        document,'script','https://connect.facebook.net/en_US/fbevents.js');
132
133        fbq('init', PIXEL_ID);
134        fbq('track', 'PageView');
135
136        /* Anything queued before consent, such as a purchase on this very page,
137           is sent once rather than lost. */
138        var pending = window.__fbPending || [];
139        window.__fbPending = null;
140        pending.forEach(function (args) {
141            try { fbq.apply(null, args); } catch (e) {}
142        });
143    }
144
145    /* Queue an event whether or not the pixel is up yet. Callers do not have to
146       know about consent, which keeps that decision in one place. */
147    window.fbTrack = function () {
148        var args = Array.prototype.slice.call(arguments);
149        if (loaded && window.fbq) {
150            try { fbq.apply(null, args); } catch (e) {}
151            return;
152        }
153        window.__fbPending = window.__fbPending || [];
154        window.__fbPending.push(args);
155    };
156
157    load();
158    window.addEventListener('cookieconsent:changed', load);
159})();
160</script>
vendor: 1 bytes, line 160
160
161<script>
162(function () {
163    var PIXEL_ID = "a2_jqulur9sdzbk";
164    var MATCH = null;
165    var loaded = false;
166
167    /* Read the consent cookie directly rather than window.cookieConsent. This
168       partial runs in the head and the consent script runs at the end of the
169       body, so that global does not exist yet. A returning visitor who already
170       agreed would otherwise never get the pixel, because the change event only
171       fires when someone changes their mind. */
172    /* Decided server side, the same way the banner decides it, so the two can
173       never disagree about whether this visitor has to be asked first. */
174    var REQUIRE_OPTIN = true;
175
176    function allowed() {
177        try {
178            if (window.cookieConsent) return !!window.cookieConsent.marketing;
179
180            var m = document.cookie.match('(^|;)\\s*cookie_consent\\s*=\\s*([^;]+)');
181            if (m) {
182                var c = JSON.parse(decodeURIComponent(m[2]));
183                return !!(c && c.v === 1 && c.marketing);
184            }
185
186            /* No stored choice. Where prior opt-in is required that means no,
187               and it keeps meaning no until they say otherwise. */
188            return !REQUIRE_OPTIN;
189        } catch (e) {
190            return false;
191        }
192    }
193
194    function load() {
195        if (loaded || !allowed()) return;
196        loaded = true;
197
198        /* Reddit's standard loader, with the id read from a variable instead of
199           hard-coded into the query string. */
200        !function(w,d){if(!w.rdt){var p=w.rdt=function(){p.sendEvent?p.sendEvent.apply(p,arguments):p.callQueue.push(arguments)};p.callQueue=[];
201        var t=d.createElement("script");t.src="https://www.redditstatic.com/ads/pixel.js?pixel_id="+encodeURIComponent(PIXEL_ID),t.async=!0;
202        var s=d.getElementsByTagName("script")[0];s.parentNode.insertBefore(t,s)}}(window,document);
203
204        /* Reddit only accepts the third argument when there is something in it. */
205        if (MATCH) {
206            rdt('init', PIXEL_ID, MATCH);
207        } else {
208            rdt('init', PIXEL_ID);
209        }
210        rdt('track', 'PageVisit');
211
212        /* Anything queued before consent, such as a purchase on this very page,
213           is sent once rather than lost. */
214        var pending = window.__rdtPending || [];
215        window.__rdtPending = null;
216        pending.forEach(function (args) {
217            try { rdt.apply(null, args); } catch (e) {}
218        });
219    }
220
221    /* Queue an event whether or not the pixel is up yet. Callers do not have to
222       know about consent, which keeps that decision in one place. */
223    window.rdtTrack = function () {
224        var args = Array.prototype.slice.call(arguments);
225        if (loaded && window.rdt) {
226            try { rdt.apply(null, args); } catch (e) {}
227            return;
228        }
229        window.__rdtPending = window.__rdtPending || [];
230        window.__rdtPending.push(args);
231    };
232
233    load();
234    window.addEventListener('cookieconsent:changed', load);
235})();
236</script>
236
237</head>
238<body class="min-h-screen bg-[#f8f8fa] font-sans text-[#1a1a2e]">
239    
240    <header class="topbar-v2">
241    <div class="topbar-v2__main">
242        <div class="topbar-v2__inner">
243            <a href="/" class="topbar-v2__logo">
244                <img src="/brand/nameoffice-logo.png" alt="NameOffice">
245            </a>
246
247            <nav class="topbar-v2__nav">
248                <a href="/business-names"
249                   class="">
250                    Browse Names
251                </a>
252                <a href="/guides"
253                   class="">
254                    Guides
255                </a>
256                <a href="/reviews"
257                   class="">
258                    Reviews
259                </a>
260                <a href="/contact"
261                   class="">
262                    Contact
263                </a>
264                <a href="/about"
265                   class="">
266                    About NameOffice
267                </a>
268            </nav>
269
270            <div class="topbar-v2__actions">
271                <details class="topbar-v2__phone-menu">
272                                        <summary class="topbar-v2__phone-trigger" aria-label="Call or text NameOffice">
273                        <svg class="topbar-v2__phone-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2.1 4.2 2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .4 1.9.7 2.8a2 2 0 0 1-.5 2.1L8.1 9.9a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2.1-.4c.9.3 1.8.5 2.8.6a2 2 0 0 1 1.7 2Z"/></svg>
274                        <span class="topbar-v2__phone-number">(972) 914-8485</span>
275                    </summary>
276                    <div class="topbar-v2__phone-panel">
277                        <a href="tel:+19729148485" class="topbar-v2__phone-link">
278                            <span class="topbar-v2__phone-link-label">Call NameOffice</span>
279                            <span>(972) 914-8485</span>
280                        </a>
281                        <a href="sms:+19729148485" class="topbar-v2__phone-link">
282                            <span class="topbar-v2__phone-link-label">Text NameOffice</span>
283                            <span>(972) 914-8485</span>
284                        </a>
285                    </div>
286                </details>
287                <a href="/favorites" class="topbar-v2__icon-btn" aria-label="Favorites" id="v2-fav-btn" data-favorites-link="true">
288                    <i class="uil uil-heart"></i>
289                    <span class="topbar-v2__badge topbar-v2__badge--hidden" id="v2-fav-badge">0</span>
290                </a>
291                <a href="/cart" class="topbar-v2__icon-btn" aria-label="Cart" id="v2-cart-btn">
292                    <i class="uil uil-shopping-bag"></i>
293                    <span class="topbar-v2__badge topbar-v2__badge--hidden" id="v2-cart-badge">0</span>
294                </a>
295            </div>
296        </div>
297
298    </div>
299
300    <div class="topbar-v2__sub" role="navigation" aria-label="Secondary navigation">
301        <div class="topbar-v2__sub-inner">
302                        <nav class="topbar-v2__mobile-links" aria-label="Primary site links">
303                <a href="/business-names" class="">Browse</a>
304                <a href="/guides" class="">Guides</a>
305                <a href="/reviews" class="">Reviews</a>
306                <a href="/contact" class="">Contact</a>
307                <a href="/about" class="">About</a>
308            </nav>
309            <p class="topbar-v2__sub-line">
310                Department of Premium Names
311                <span class="topbar-v2__sub-sep" aria-hidden="true">|</span>
312                Est. 2014
313            </p>
314        </div>
315    </div>
316</header>
317
318<script>
319(function() {
320    var marketplaceBaseUrl = "";
321    var limits = { cartDomains: 25, shortlistedDomains: 100 };
322
323    function getCookie(name) {
324        if (marketplaceBaseUrl) return null;
325        var m = document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)');
326        return m ? decodeURIComponent(m[2]) : null;
327    }
328
329    function normalizeList(values, limit) {
330        if (!Array.isArray(values)) return [];
331        var seen = {};
332        return values.map(function(value) { return parseInt(value, 10) || 0; })
333            .filter(function(value) {
334                if (!value || seen[value]) return false;
335                seen[value] = true;
336                return true;
337            })
338            .slice(0, limit);
339    }
340
341    function readList(name) {
342        if (marketplaceBaseUrl) return [];
343        var raw = getCookie(name);
344        if (!raw) return [];
345        if (raw.length > 3800) {
346            writeList(name, []);
347            return [];
348        }
349        try {
350            var values = JSON.parse(raw);
351            var normalized = normalizeList(values, limits[name] || 25);
352            if (!Array.isArray(values) || JSON.stringify(values) !== JSON.stringify(normalized)) {
353                writeList(name, normalized);
354            }
355            return normalized;
356        } catch (e) {
357            writeList(name, []);
358            return [];
359        }
360    }
361
362    function writeList(name, values) {
363        if (marketplaceBaseUrl) return [];
364        var normalized = normalizeList(values, limits[name] || 25);
365        var expires = new Date(Date.now() + 365 * 24 * 60 * 60 * 1000);
366        var secure = location.protocol === 'https:' ? ';Secure' : '';
367        document.cookie = name + '=' + encodeURIComponent(JSON.stringify(normalized))
368            + ';expires=' + expires.toUTCString() + ';path=/;SameSite=Lax' + secure;
369        return normalized;
370    }
371
372    window.NameOfficeSelectionState = {
373        read: readList,
374        write: writeList,
375        limits: limits
376    };
377
378    function updateBadge(id, count) {
379        var el = document.getElementById(id);
380        if (!el) return;
381        if (count > 0) {
382            el.textContent = count;
383            el.classList.remove('topbar-v2__badge--hidden');
384        } else {
385            el.classList.add('topbar-v2__badge--hidden');
386        }
387    }
388    function refresh() {
389        // Favourites are stored in this hostname's cookie and the heart now links
390        // to this hostname's list, so the count is meaningful on a pointed domain
391        // too — it used to bail out here and the badge simply never appeared.
392        updateBadge('v2-fav-badge', readList('shortlistedDomains').length);
393
394        // The cart still hands off to the marketplace to check out, so its cookie
395        // lives over there and there is nothing local to count.
396        if (!marketplaceBaseUrl) {
397            updateBadge('v2-cart-badge', readList('cartDomains').length);
398        }
399    }
400
401    document.addEventListener('click', function(event) {
402        document.querySelectorAll('.topbar-v2__phone-menu[open]').forEach(function(menu) {
403            if (!menu.contains(event.target)) {
404                menu.removeAttribute('open');
405            }
406        });
407    });
408
409    document.addEventListener('keydown', function(event) {
410        if (event.key !== 'Escape') {
411            return;
412        }
413        document.querySelectorAll('.topbar-v2__phone-menu[open]').forEach(function(menu) {
414            menu.removeAttribute('open');
415        });
416    });
417
418    refresh();
419    document.addEventListener('shortlist:update', refresh);
420    document.addEventListener('cart:update', refresh);
421})();
422</script>
422
423
424        <main class="mx-auto max-w-7xl px-5 py-12 md:px-8 md:py-16">
425        <div class="mb-8">
426            <div class="text-xs uppercase tracking-[0.28em] text-gray-400">Your shortlist</div>
427            <h1 class="mt-2 text-3xl font-semibold tracking-tight md:text-4xl">Saved names</h1>
428            <p id="resultCount" class="mt-1 text-sm text-gray-500">Loading…</p>
429        </div>
430
431                    <section
432                id="favorites-share-tools"
433                class="mb-6 rounded-[26px] border border-[#d7e5f6] bg-[linear-gradient(180deg,rgba(255,255,255,0.94)_0%,rgba(244,249,255,0.98)_100%)] p-4 shadow-[0_18px_38px_rgba(7,23,51,0.06)] sm:p-5"
434                data-create-url="/api/favorites/share-links"
435                data-share-url-template="/api/favorites/share-links/00000000000000000000000000000000/share"
436                data-share-token-placeholder="00000000000000000000000000000000"
437                data-initial-expanded="0">
438                <div id="favorites-share-summary" class="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
439                    <div class="flex flex-wrap items-center gap-2">
440                        <button type="button" id="favorites-share-toggle" aria-expanded="false" class="inline-flex items-center gap-2 rounded-full bg-navy px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.18em] text-white shadow-[0_10px_24px_rgba(1,16,46,0.18)] transition hover:bg-[#011845]">
441                            Share favorites
442                            <span id="favorites-share-toggle-icon" aria-hidden="true" class="shrink-0">
443                                <svg width="12" height="12" viewBox="0 0 20 20" fill="none"><path d="M5 7.5 10 12.5l5-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
444                            </span>
445                        </button>
446                        <span class="rounded-full border border-[#d7e5f6] bg-white/90 px-3 py-1 text-xs font-medium text-[#62708a]">Private shareable shortlist link</span>
447                    </div>
448                    <div class="text-sm text-[#62708a] lg:text-right">Send your saved names to a partner, client, or teammate.</div>
449                </div>
450
451                <div id="favorites-share-panel" class="mt-4 hidden border-t border-[#dbe6f3] pt-4">
452                    <div class="max-w-2xl">
453                        <h2 class="font-display text-xl font-bold tracking-tight text-gray-900">Share this exact shortlist with one private link</h2>
454                        <p class="mt-1.5 text-sm leading-relaxed text-gray-500">Generate a link that opens this same selection of saved names. Useful for sending your shortlist to a partner, client, or team member.</p>
455                    </div>
456
457                    <div class="mt-4 flex flex-wrap items-center gap-3">
458                        <button type="button" id="favorites-share-create" class="inline-flex items-center gap-2 rounded-xl bg-navy px-4 py-3 text-sm font-bold text-white transition hover:brightness-110">
459                            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#74F7B2" stroke-width="2"><path d="M10 13a5 5 0 0 0 7.07 0l1.41-1.41a5 5 0 0 0-7.07-7.07L10.59 5"/><path d="M14 11a5 5 0 0 0-7.07 0L5.5 12.43a5 5 0 1 0 7.07 7.07L13.41 19"/></svg>
460                            Create shareable link
461                        </button>
462                        <div class="text-xs text-[#72819a]">Creates a private URL for your current saved names only.</div>
463                    </div>
464
465                    <div id="favorites-share-result" class="mt-4 hidden rounded-[22px] border border-[#d7e5f6] bg-white/85 p-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.92)]">
466                        <label for="favorites-share-url" class="mb-2 block text-[11px] font-semibold uppercase tracking-[0.16em] text-[#8b97ad]">Share URL</label>
467                        <div class="flex flex-col gap-2 lg:flex-row">
468                            <input id="favorites-share-url" type="text" readonly class="min-w-0 flex-1 rounded-xl border border-[#d7e5f6] bg-[#f8fbff] px-4 py-3 text-sm font-medium text-navy outline-none focus:border-navy/40" value="">
469                            <div class="flex flex-wrap gap-2">
470                                <button type="button" id="favorites-share-copy" class="inline-flex items-center gap-2 rounded-xl border border-[#d1dcec] bg-white px-4 py-3 text-sm font-semibold text-[#62708a] transition hover:border-navy/30 hover:text-navy">
471                                    Copy link
472                                </button>
473                                <button type="button" id="favorites-share-native" class="inline-flex items-center gap-2 rounded-xl border border-[#d1dcec] bg-white px-4 py-3 text-sm font-semibold text-[#62708a] transition hover:border-navy/30 hover:text-navy">
474                                    Share
475                                </button>
476                                <a id="favorites-share-open" href="#" target="_blank" rel="noopener" class="inline-flex items-center gap-2 rounded-xl border border-[#d1dcec] bg-white px-4 py-3 text-sm font-semibold text-[#62708a] transition hover:border-navy/30 hover:text-navy">
477                                    Open link
478                                </a>
479                            </div>
480                        </div>
481                        <p id="favorites-share-status" class="mt-3 text-sm text-gray-500">Create a private link, then copy or share it from here.</p>
482                    </div>
483                </div>
484            </section>
485        
486        <div id="grid" class="grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4"></div>
487
488        <div id="sentinel" class="h-12"></div>
489        <div id="loadingRow" class="hidden py-8 text-center text-sm text-gray-400">Loading more…</div>
490        <div id="emptyRow" class="hidden rounded-3xl border border-dashed border-gray-200 bg-white p-16 text-center">
491            <p class="text-sm text-gray-500">You haven't saved any names yet.</p>
492            <a href="/business-names" class="mt-3 inline-block text-sm font-semibold text-navy underline underline-offset-4">Browse domains →</a>
493        </div>
494    </main>
495
496    <footer class="footer-v2">
497    <div class="footer-v2__inner">
498                <div class="footer-v2__top">
499            <a href="/" class="footer-v2__logo">
500                <img src="/brand/nameoffice-symbol.png" alt="NameOffice icon">
501                <span>NameOffice</span>
502            </a>
503            <p class="footer-v2__tagline">Curated premium domains for ambitious brands.</p>
504        </div>
505
506                <section class="footer-landing" aria-labelledby="footer-landing-title">
507            <div class="footer-landing__head">
508                <p class="footer-landing__kicker">Explore by topic</p>
509                <h3 id="footer-landing-title">Business naming pages, guides &amp; buying paths</h3>
510                <p class="footer-landing__intro">Pick a category to browse the NameOffice landing-page library, then jump into the live catalog for the names you want next.</p>
511            </div>
512
513            <div class="footer-landing__tabs" role="tablist" aria-label="Landing page categories">
514                                                <button type="button"
515                        class="footer-landing__tab is-active"
516                        role="tab"
517                        id="footer-landing-tab-1"
518                        aria-controls="footer-landing-panel-1"
519                        aria-selected="true"
520                        tabindex="0"
521                        data-footer-landing-tab="1">
522                    <span class="footer-landing__tab-label">Business Name Ideas</span>
523                    <span class="footer-landing__tab-count">44</span>
524                </button>
525                                                <button type="button"
526                        class="footer-landing__tab"
527                        role="tab"
528                        id="footer-landing-tab-2"
529                        aria-controls="footer-landing-panel-2"
530                        aria-selected="false"
531                        tabindex="-1"
532                        data-footer-landing-tab="2">
533                    <span class="footer-landing__tab-label">Buy Domain Names</span>
534                    <span class="footer-landing__tab-count">14</span>
535                </button>
536                                                <button type="button"
537                        class="footer-landing__tab"
538                        role="tab"
539                        id="footer-landing-tab-3"
540                        aria-controls="footer-landing-panel-3"
541                        aria-selected="false"
542                        tabindex="-1"
543                        data-footer-landing-tab="3">
544                    <span class="footer-landing__tab-label">Name Generators</span>
545                    <span class="footer-landing__tab-count">15</span>
546                </button>
547                                                <button type="button"
548                        class="footer-landing__tab"
549                        role="tab"
550                        id="footer-landing-tab-4"
551                        aria-controls="footer-landing-panel-4"
552                        aria-selected="false"
553                        tabindex="-1"
554                        data-footer-landing-tab="4">
555                    <span class="footer-landing__tab-label">Naming Guides</span>
556                    <span class="footer-landing__tab-count">17</span>
557                </button>
558                            </div>
559
560            <div class="footer-landing__panels">
561                                                <div class="footer-landing__panel is-active"
562                     role="tabpanel"
563                     id="footer-landing-panel-1"
564                     aria-labelledby="footer-landing-tab-1"
565                     data-footer-landing-panel="1">
566                    <ul class="footer-landing__links">
567                                                <li>
568                            <a href="/businesses-names">
569                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
570                                <span>Businesses Names</span>
571                            </a>
572                        </li>
573                                                <li>
574                            <a href="/candy-shop-name-ideas">
575                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
576                                <span>Candy Shop Name Ideas</span>
577                            </a>
578                        </li>
579                                                <li>
580                            <a href="/car-lot-names">
581                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
582                                <span>Car Lot Names</span>
583                            </a>
584                        </li>
585                                                <li>
586                            <a href="/catchy-business-name-suggestions">
587                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
588                                <span>Catchy Business Name Suggestions</span>
589                            </a>
590                        </li>
591                                                <li>
592                            <a href="/catering-company-name-ideas">
593                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
594                                <span>Catering Company Name Ideas</span>
595                            </a>
596                        </li>
597                                                <li>
598                            <a href="/clever-business-names">
599                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
600                                <span>Clever Business Names</span>
601                            </a>
602                        </li>
603                                                <li>
604                            <a href="/club-name-suggestions">
605                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
606                                <span>Club Name Suggestions</span>
607                            </a>
608                        </li>
609                                                <li>
610                            <a href="/coffee-name-suggestions">
611                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
612                                <span>Coffee Name Suggestions</span>
613                            </a>
614                        </li>
615                                                <li>
616                            <a href="/company-name-examples">
617                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
618                                <span>Company Name Examples</span>
619                            </a>
620                        </li>
621                                                <li>
622                            <a href="/consulting-company-name-suggestions">
623                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
624                                <span>Consulting Company Name Suggestions</span>
625                            </a>
626                        </li>
627                                                <li>
628                            <a href="/consulting-llc-names">
629                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
630                                <span>Consulting Llc Names</span>
631                            </a>
632                        </li>
633                                                <li>
634                            <a href="/cool-travel-agency-names">
635                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
636                                <span>Cool Travel Agency Names</span>
637                            </a>
638                        </li>
639                                                <li>
640                            <a href="/cosmetic-name-ideas">
641                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
642                                <span>Cosmetic Name Ideas</span>
643                            </a>
644                        </li>
645                                                <li>
646                            <a href="/cute-brand-names">
647                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
648                                <span>Cute Brand Names</span>
649                            </a>
650                        </li>
651                                                <li>
652                            <a href="/dating-app-logos-and-names">
653                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
654                                <span>Dating App Logos And Names</span>
655                            </a>
656                        </li>
657                                                <li>
658                            <a href="/design-business-names">
659                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
660                                <span>Design Business Names</span>
661                            </a>
662                        </li>
663                                                <li>
664                            <a href="/event-planner-business-names">
665                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
666                                <span>Event Planner Business Names</span>
667                            </a>
668                        </li>
669                                                <li>
670                            <a href="/fashion-line-name-ideas">
671                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
672                                <span>Fashion Line Name Ideas</span>
673                            </a>
674                        </li>
675                                                <li>
676                            <a href="/find-me-a-company-name">
677                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
678                                <span>Find Me A Company Name</span>
679                            </a>
680                        </li>
681                                                <li>
682                            <a href="/firm-name-suggestion">
683                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
684                                <span>Firm Name Suggestion</span>
685                            </a>
686                        </li>
687                                                <li>
688                            <a href="/gambling-names">
689                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
690                                <span>Gambling Names</span>
691                            </a>
692                        </li>
693                                                <li>
694                            <a href="/good-app-names">
695                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
696                                <span>Good App Names</span>
697                            </a>
698                        </li>
699                                                <li>
700                            <a href="/good-names-for-a-company">
701                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
702                                <span>Good Names For A Company</span>
703                            </a>
704                        </li>
705                                                <li>
706                            <a href="/good-title-for-dating-site">
707                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
708                                <span>Good Title For Dating Site</span>
709                            </a>
710                        </li>
711                                                <li>
712                            <a href="/hardware-shop-name">
713                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
714                                <span>Hardware Shop Name</span>
715                            </a>
716                        </li>
717                                                <li>
718                            <a href="/home-care-business-names">
719                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
720                                <span>Home Care Business Names</span>
721                            </a>
722                        </li>
723                                                <li>
724                            <a href="/ideas-for-non-profit-organization-names">
725                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
726                                <span>Ideas For Non Profit Organization Names</span>
727                            </a>
728                        </li>
729                                                <li>
730                            <a href="/ideas-for-product-names">
731                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
732                                <span>Ideas For Product Names</span>
733                            </a>
734                        </li>
735                                                <li>
736                            <a href="/list-of-company-name-ideas">
737                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
738                                <span>List Of Company Name Ideas</span>
739                            </a>
740                        </li>
741                                                <li>
742                            <a href="/made-up-business-names">
743                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
744                                <span>Made Up Business Names</span>
745                            </a>
746                        </li>
747                                                <li>
748                            <a href="/name-for-small-business">
749                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
750                                <span>Name For Small Business</span>
751                            </a>
752                        </li>
753                                                <li>
754                            <a href="/name-ideas-for-companies">
755                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
756                                <span>Name Ideas For Companies</span>
757                            </a>
758                        </li>
759                                                <li>
760                            <a href="/names-for-a-cafe">
761                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
762                                <span>Names For A Cafe</span>
763                            </a>
764                        </li>
765                                                <li>
766                            <a href="/names-for-corporations">
767                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
768                                <span>Names For Corporations</span>
769                            </a>
770                        </li>
771                                                <li>
772                            <a href="/names-for-home-health-care-business">
773                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
774                                <span>Names For Home Health Care Business</span>
775                            </a>
776                        </li>
777                                                <li>
778                            <a href="/names-for-investment-companies">
779                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
780                                <span>Names For Investment Companies</span>
781                            </a>
782                        </li>
783                                                <li>
784                            <a href="/names-for-it-companies-with-meaning">
785                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
786                                <span>Names For It Companies With Meaning</span>
787                            </a>
788                        </li>
789                                                <li>
790                            <a href="/renovation-company-names">
791                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
792                                <span>Renovation Company Names</span>
793                            </a>
794                        </li>
795                                                <li>
796                            <a href="/staffing-agency-names">
797                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
798                                <span>Staffing Agency Names</span>
799                            </a>
800                        </li>
801                                                <li>
802                            <a href="/tech-company-name-suggestions">
803                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
804                                <span>Tech Company Name Suggestions</span>
805                            </a>
806                        </li>
807                                                <li>
808                            <a href="/transport-company-names">
809                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
810                                <span>Transport Company Names</span>
811                            </a>
812                        </li>
813                                                <li>
814                            <a href="/unique-project-names-list">
815                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
816                                <span>Unique Project Names List</span>
817                            </a>
818                        </li>
819                                                <li>
820                            <a href="/what-should-i-name-my-company">
821                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
822                                <span>What Should I Name My Company</span>
823                            </a>
824                        </li>
825                                                <li>
826                            <a href="/whats-a-good-company-name">
827                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
828                                <span>Whats A Good Company Name</span>
829                            </a>
830                        </li>
831                                            </ul>
832                    <button type="button" class="footer-landing__more" data-footer-landing-more aria-expanded="false" hidden>
833                        <span class="footer-landing__more-show">Show all 44 business name ideas</span>
834                        <span class="footer-landing__more-hide">Show fewer</span>
835                        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
836                    </button>
837                </div>
838                                                <div class="footer-landing__panel"
839                     role="tabpanel"
840                     id="footer-landing-panel-2"
841                     aria-labelledby="footer-landing-tab-2"
842                     data-footer-landing-panel="2">
843                    <ul class="footer-landing__links">
844                                                <li>
845                            <a href="/buy-a-site">
846                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
847                                <span>Buy A Site</span>
848                            </a>
849                        </li>
850                                                <li>
851                            <a href="/buy-brand-name">
852                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
853                                <span>Buy Brand Name</span>
854                            </a>
855                        </li>
856                                                <li>
857                            <a href="/buy-your-domain">
858                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
859                                <span>Buy Your Domain</span>
860                            </a>
861                        </li>
862                                                <li>
863                            <a href="/company-names-not-taken">
864                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
865                                <span>Company Names Not Taken</span>
866                            </a>
867                        </li>
868                                                <li>
869                            <a href="/cool-web-domain-names">
870                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
871                                <span>Cool Web Domain Names</span>
872                            </a>
873                        </li>
874                                                <li>
875                            <a href="/creative-domain-names">
876                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
877                                <span>Creative Domain Names</span>
878                            </a>
879                        </li>
880                                                <li>
881                            <a href="/domain-selling-sites">
882                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
883                                <span>Domain Selling Sites</span>
884                            </a>
885                        </li>
886                                                <li>
887                            <a href="/how-do-i-buy-a-taken-domain-name">
888                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
889                                <span>How Do I Buy A Taken Domain Name</span>
890                            </a>
891                        </li>
892                                                <li>
893                            <a href="/most-expensive-domain-names-for-sale">
894                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
895                                <span>Most Expensive Domain Names For Sale</span>
896                            </a>
897                        </li>
898                                                <li>
899                            <a href="/premium-domain-checker">
900                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
901                                <span>Premium Domain Checker</span>
902                            </a>
903                        </li>
904                                                <li>
905                            <a href="/purchase-my-domain-name">
906                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
907                                <span>Purchase My Domain Name</span>
908                            </a>
909                        </li>
910                                                <li>
911                            <a href="/short-domains-for-sale">
912                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
913                                <span>Short Domains For Sale</span>
914                            </a>
915                        </li>
916                                                <li>
917                            <a href="/where-can-i-buy-domains">
918                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
919                                <span>Where Can I Buy Domains</span>
920                            </a>
921                        </li>
922                                                <li>
923                            <a href="/where-to-buy-website-domains">
924                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
925                                <span>Where To Buy Website Domains</span>
926                            </a>
927                        </li>
928                                            </ul>
929                    <button type="button" class="footer-landing__more" data-footer-landing-more aria-expanded="false" hidden>
930                        <span class="footer-landing__more-show">Show all 14 buy domain names</span>
931                        <span class="footer-landing__more-hide">Show fewer</span>
932                        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
933                    </button>
934                </div>
935                                                <div class="footer-landing__panel"
936                     role="tabpanel"
937                     id="footer-landing-panel-3"
938                     aria-labelledby="footer-landing-tab-3"
939                     data-footer-landing-panel="3">
940                    <ul class="footer-landing__links">
941                                                <li>
942                            <a href="/catchy-website-name-generator">
943                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
944                                <span>Catchy Website Name Generator</span>
945                            </a>
946                        </li>
947                                                <li>
948                            <a href="/company-name-generator-from-keywords">
949                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
950                                <span>Company Name Generator From Keywords</span>
951                            </a>
952                        </li>
953                                                <li>
954                            <a href="/corporate-name-generator">
955                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
956                                <span>Corporate Name Generator</span>
957                            </a>
958                        </li>
959                                                <li>
960                            <a href="/create-business-name-generator">
961                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
962                                <span>Create Business Name Generator</span>
963                            </a>
964                        </li>
965                                                <li>
966                            <a href="/ecommerce-name-generator">
967                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
968                                <span>Ecommerce Name Generator</span>
969                            </a>
970                        </li>
971                                                <li>
972                            <a href="/generate-a-name-for-my-business">
973                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
974                                <span>Generate A Name For My Business</span>
975                            </a>
976                        </li>
977                                                <li>
978                            <a href="/handmade-business-name-generator">
979                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
980                                <span>Handmade Business Name Generator</span>
981                            </a>
982                        </li>
983                                                <li>
984                            <a href="/new-business-name-generator">
985                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
986                                <span>New Business Name Generator</span>
987                            </a>
988                        </li>
989                                                <li>
990                            <a href="/product-name-generator-free">
991                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
992                                <span>Product Name Generator Free</span>
993                            </a>
994                        </li>
995                                                <li>
996                            <a href="/product-namer">
997                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
998                                <span>Product Namer</span>
999                            </a>
1000                        </li>
1001                                                <li>
1002                            <a href="/real-estate-business-name-generator">
1003                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1004                                <span>Real Estate Business Name Generator</span>
1005                            </a>
1006                        </li>
1007                                                <li>
1008                            <a href="/software-name-generator">
1009                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1010                                <span>Software Name Generator</span>
1011                            </a>
1012                        </li>
1013                                                <li>
1014                            <a href="/startup-business-name-generator">
1015                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1016                                <span>Startup Business Name Generator</span>
1017                            </a>
1018                        </li>
1019                                                <li>
1020                            <a href="/travel-company-names-generator">
1021                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1022                                <span>Travel Company Names Generator</span>
1023                            </a>
1024                        </li>
1025                                                <li>
1026                            <a href="/web-name-generator">
1027                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1028                                <span>Web Name Generator</span>
1029                            </a>
1030                        </li>
1031                                            </ul>
1032                    <button type="button" class="footer-landing__more" data-footer-landing-more aria-expanded="false" hidden>
1033                        <span class="footer-landing__more-show">Show all 15 name generators</span>
1034                        <span class="footer-landing__more-hide">Show fewer</span>
1035                        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
1036                    </button>
1037                </div>
1038                                                <div class="footer-landing__panel"
1039                     role="tabpanel"
1040                     id="footer-landing-panel-4"
1041                     aria-labelledby="footer-landing-tab-4"
1042                     data-footer-landing-panel="4">
1043                    <ul class="footer-landing__links">
1044                                                <li>
1045                            <a href="/coming-up-with-business-name">
1046                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1047                                <span>Coming Up With Business Name</span>
1048                            </a>
1049                        </li>
1050                                                <li>
1051                            <a href="/company-name-services">
1052                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1053                                <span>Company Name Services</span>
1054                            </a>
1055                        </li>
1056                                                <li>
1057                            <a href="/company-naming-agency">
1058                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1059                                <span>Company Naming Agency</span>
1060                            </a>
1061                        </li>
1062                                                <li>
1063                            <a href="/creating-a-brand-name">
1064                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1065                                <span>Creating A Brand Name</span>
1066                            </a>
1067                        </li>
1068                                                <li>
1069                            <a href="/for-seo-should-my-company-name-be-in-html">
1070                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1071                                <span>For Seo Should My Company Name Be In Html</span>
1072                            </a>
1073                        </li>
1074                                                <li>
1075                            <a href="/good-project-names">
1076                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1077                                <span>Good Project Names</span>
1078                            </a>
1079                        </li>
1080                                                <li>
1081                            <a href="/how-do-i-pick-a-name-for-my-business">
1082                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1083                                <span>How Do I Pick A Name For My Business</span>
1084                            </a>
1085                        </li>
1086                                                <li>
1087                            <a href="/how-to-choose-business-name">
1088                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1089                                <span>How To Choose Business Name</span>
1090                            </a>
1091                        </li>
1092                                                <li>
1093                            <a href="/how-to-come-up-with-business-names">
1094                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1095                                <span>How To Come Up With Business Names</span>
1096                            </a>
1097                        </li>
1098                                                <li>
1099                            <a href="/how-to-pick-a-name-for-my-business">
1100                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1101                                <span>How To Pick A Name For My Business</span>
1102                            </a>
1103                        </li>
1104                                                <li>
1105                            <a href="/how-to-think-of-a-business-name">
1106                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1107                                <span>How To Think Of A Business Name</span>
1108                            </a>
1109                        </li>
1110                                                <li>
1111                            <a href="/make-brand-name">
1112                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1113                                <span>Make Brand Name</span>
1114                            </a>
1115                        </li>
1116                                                <li>
1117                            <a href="/naming-a-marketing-agency">
1118                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1119                                <span>Naming A Marketing Agency</span>
1120                            </a>
1121                        </li>
1122                                                <li>
1123                            <a href="/picking-a-name-for-your-business">
1124                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1125                                <span>Picking A Name For Your Business</span>
1126                            </a>
1127                        </li>
1128                                                <li>
1129                            <a href="/what-is-a-business-name">
1130                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1131                                <span>What Is A Business Name</span>
1132                            </a>
1133                        </li>
1134                                                <li>
1135                            <a href="/what-to-name-a-company">
1136                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1137                                <span>What To Name A Company</span>
1138                            </a>
1139                        </li>
1140                                                <li>
1141                            <a href="/what-to-name-my-business">
1142                                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
1143                                <span>What To Name My Business</span>
1144                            </a>
1145                        </li>
1146                                            </ul>
1147                    <button type="button" class="footer-landing__more" data-footer-landing-more aria-expanded="false" hidden>
1148                        <span class="footer-landing__more-show">Show all 17 naming guides</span>
1149                        <span class="footer-landing__more-hide">Show fewer</span>
1150                        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
1151                    </button>
1152                </div>
1153                            </div>
1154
1155            
1155<script>
1156            (function () {
1157                var root = document.querySelector('.footer-landing');
1158                if (!root || root.dataset.footerLandingInit) { return; }
1159                root.dataset.footerLandingInit = '1';
1160                root.classList.add('footer-landing--js');
1161
1162                var CAP = 184;
1163                var tabs = Array.prototype.slice.call(root.querySelectorAll('[data-footer-landing-tab]'));
1164                var panels = Array.prototype.slice.call(root.querySelectorAll('[data-footer-landing-panel]'));
1165
1166                function panelFor(id) { return root.querySelector('[data-footer-landing-panel="' + id + '"]'); }
1167
1168                function syncMore(panel) {
1169                    if (!panel) { return; }
1170                    var links = panel.querySelector('.footer-landing__links');
1171                    var more = panel.querySelector('[data-footer-landing-more]');
1172                    if (!links || !more) { return; }
1173                    panel.classList.remove('is-clamped');
1174                    var overflowing = links.scrollHeight > CAP + 8;
1175                    if (overflowing && !panel.classList.contains('is-expanded')) {
1176                        panel.classList.add('is-clamped');
1177                    }
1178                    more.hidden = !overflowing;
1179                }
1180
1181                function activate(id, focusTab) {
1182                    tabs.forEach(function (t) {
1183                        var on = t.dataset.footerLandingTab === id;
1184                        t.classList.toggle('is-active', on);
1185                        t.setAttribute('aria-selected', on ? 'true' : 'false');
1186                        t.setAttribute('tabindex', on ? '0' : '-1');
1187                        if (on && focusTab) { t.focus(); }
1188                    });
1189                    panels.forEach(function (p) {
1190                        p.classList.toggle('is-active', p.dataset.footerLandingPanel === id);
1191                    });
1192                    syncMore(panelFor(id));
1193                }
1194
1195                tabs.forEach(function (tab) {
1196                    tab.addEventListener('click', function () { activate(tab.dataset.footerLandingTab); });
1197                    tab.addEventListener('keydown', function (e) {
1198                        var i = tabs.indexOf(tab);
1199                        if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {
1200                            e.preventDefault();
1201                            activate(tabs[(i + 1) % tabs.length].dataset.footerLandingTab, true);
1202                        } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {
1203                            e.preventDefault();
1204                            activate(tabs[(i - 1 + tabs.length) % tabs.length].dataset.footerLandingTab, true);
1205                        }
1206                    });
1207                });
1208
1209                panels.forEach(function (panel) {
1210                    var more = panel.querySelector('[data-footer-landing-more]');
1211                    if (!more) { return; }
1212                    more.addEventListener('click', function () {
1213                        var expanded = panel.classList.toggle('is-expanded');
1214                        more.setAttribute('aria-expanded', expanded ? 'true' : 'false');
1215                        if (expanded) { panel.classList.remove('is-clamped'); }
1216                        else { syncMore(panel); }
1217                    });
1218                });
1219
1220                syncMore(root.querySelector('.footer-landing__panel.is-active'));
1221                var resizeTimer;
1222                window.addEventListener('resize', function () {
1223                    window.clearTimeout(resizeTimer);
1224                    resizeTimer = window.setTimeout(function () {
1225                        var active = root.querySelector('.footer-landing__panel.is-active');
1226                        if (active && !active.classList.contains('is-expanded')) { syncMore(active); }
1227                    }, 150);
1228                });
1229            })();
1230            </script>
1230
1231        </section>
1232        
1233                <div class="footer-v2__columns">
1234            <div class="footer-v2__col">
1235                <h4>Products &amp; Pricing</h4>
1236                <ul>
1237                    <li><a href="/business-names">Domain Names</a></li>
1238                </ul>
1239            </div>
1240
1241            <div class="footer-v2__col">
1242                <h4>Learn</h4>
1243                <ul>
1244                    <li><a href="/guides">Naming Guides</a></li>
1245                </ul>
1246            </div>
1247
1248            <div class="footer-v2__col">
1249                <h4>What is NameOffice?</h4>
1250                <ul>
1251                    <li><a href="/about">About Us</a></li>
1252                    <li><a href="/faq">FAQ</a></li>
1253                    <li><a href="/contact">Contact</a></li>
1254                </ul>
1255            </div>
1256
1257            <div class="footer-v2__col">
1258                <h4>Follow Us</h4>
1259                <ul>
1260                    <li><a href="mailto:[email protected]" target="_blank" rel="noopener noreferrer">Email</a></li>
1261                    <li><a href="https://x.com/nameOffice" target="_blank" rel="noopener noreferrer">Twitter / X</a></li>
1262                    <li><a href="https://www.linkedin.com/company/nameoffice" target="_blank" rel="noopener noreferrer">LinkedIn</a></li>
1263                    <li><a href="https://www.facebook.com/nameoffices" target="_blank" rel="noopener noreferrer">Facebook</a></li>
1264                </ul>
1265            </div>
1266        </div>
1267
1268                <div class="footer-v2__bottom">
1269            <span>&copy; 2026 NameOffice LLC. All rights reserved.</span>
1270            <span class="footer-v2__legal">
1271                <a href="/terms">Terms</a>
1272                <a href="/privacy-policy">Privacy</a>
1273                <a href="/cookie-policy">Cookie Policy</a>
1274                                    <button type="button" data-cc-action="open-settings">Cookie settings</button>
1275                            </span>
1276        </div>
1277    </div>
1278</footer>
1279
1280    <div id="cookie-consent" class="cookie-consent" hidden role="region" aria-label="Cookie consent">
1281    <div class="cookie-consent__inner">
1282        <div class="cookie-consent__text">
1283            <strong>We value your privacy</strong>
1284                                        <p>
1285                    We use cookies to run the site, remember your cart and saved names, and understand how the
1286                    site is used. Nothing beyond the essentials runs until you choose. You can accept all,
1287                    reject non-essential cookies, or pick what to allow.
1288                    Read our <a href="/cookie-policy">Cookie Policy</a>.
1289                </p>
1290                    </div>
1291        <div class="cookie-consent__actions">
1292            <button type="button" class="cookie-btn cookie-btn--ghost" data-cc-action="customize">Customize</button>
1293            <button type="button" class="cookie-btn cookie-btn--outline" data-cc-action="reject">Reject all</button>
1294            <button type="button" class="cookie-btn cookie-btn--mint" data-cc-action="accept">Accept all</button>
1295        </div>
1296    </div>
1297</div>
1298
1299<div id="cookie-prefs" class="cookie-prefs" hidden role="dialog" aria-modal="true" aria-labelledby="cookie-prefs-title">
1300    <div class="cookie-prefs__backdrop" data-cc-action="close-prefs"></div>
1301    <div class="cookie-prefs__panel" role="document">
1302        <div class="cookie-prefs__head">
1303            <h2 id="cookie-prefs-title">Cookie preferences</h2>
1304            <button type="button" class="cookie-prefs__close" data-cc-action="close-prefs" aria-label="Close">&times;</button>
1305        </div>
1306        <p class="cookie-prefs__intro">
1307            Choose which cookies NameOffice can use. Strictly necessary cookies are always on because the site
1308            cannot work without them. You can change your choice anytime from the &ldquo;Cookie settings&rdquo;
1309            link in the footer.
1310        </p>
1311
1312        <div class="cookie-prefs__group">
1313            <div class="cookie-prefs__group-head">
1314                <span class="cookie-prefs__group-title">Strictly necessary</span>
1315                <span class="cookie-prefs__always">Always on</span>
1316            </div>
1317            <p>Required for core features such as your cart, saved names, and secure checkout. These do not track you for advertising.</p>
1318        </div>
1319
1320        <div class="cookie-prefs__group">
1321            <div class="cookie-prefs__group-head">
1322                <label class="cookie-prefs__group-title" for="cc-analytics">Analytics</label>
1323                <label class="cookie-switch">
1324                    <input type="checkbox" id="cc-analytics">
1325                    <span class="cookie-switch__slider"></span>
1326                </label>
1327            </div>
1328            <p>Help us understand which names and pages are popular so we can improve the site. Set only with your consent.</p>
1329        </div>
1330
1331        <div class="cookie-prefs__group">
1332            <div class="cookie-prefs__group-head">
1333                <label class="cookie-prefs__group-title" for="cc-marketing">Marketing</label>
1334                <label class="cookie-switch">
1335                    <input type="checkbox" id="cc-marketing">
1336                    <span class="cookie-switch__slider"></span>
1337                </label>
1338            </div>
1339            <p>Let us show you the names you looked at in ads on other sites, and measure whether those ads work. Set only with your consent.</p>
1340        </div>
1341
1342        <div class="cookie-prefs__foot">
1343            <button type="button" class="cookie-btn cookie-btn--outline" data-cc-action="reject">Reject all</button>
1344            <button type="button" class="cookie-btn cookie-btn--mint" data-cc-action="save">Save preferences</button>
1345        </div>
1346    </div>
1347</div>
1348
1349<script>
1350(function(){
1351    /* Set server side from Cloudflare's country header. Inside the EU, EEA,
1352       UK and Switzerland nothing non-essential may run before someone agrees.
1353       Elsewhere it runs on arrival and they may decline. */
1354    var REQUIRE_OPTIN = true;
1355    var COOKIE_NAME = 'cookie_consent';
1356    var PROMPT_NAME = 'cookie_consent_prompted';
1357    var VERSION = 1;
1358    var MAX_AGE = 60 * 60 * 24 * 365; // 1 year
1359    var REVEAL_DELAY_MS = 4000;
1360    var ANIMATION_MS = 1050;
1361    var bannerTimer = null;
1362
1363    /* The visitor's stored choice, or null if they have not made one. */
1364    function storedConsent(){
1365        var m = document.cookie.match('(^|;)\\s*' + COOKIE_NAME + '\\s*=\\s*([^;]+)');
1366        if (!m) return null;
1367        try {
1368            var c = JSON.parse(decodeURIComponent(m[2]));
1369            return (c && c.v === VERSION) ? c : null;
1370        } catch (e) { return null; }
1371    }
1372
1373    /* What applies right now. Where prior opt-in is not required, no stored
1374       choice means consent is implied until they say otherwise, and the
1375       implied flag marks it so nothing mistakes it for a decision they made. */
1376    function readConsent(){
1377        var stored = storedConsent();
1378        if (stored) return stored;
1379        if (REQUIRE_OPTIN) return null;
1380
1381        return { v: VERSION, necessary: true, analytics: true, marketing: true, implied: true };
1382    }
1383
1384    function hasPrompted(){
1385        return document.cookie.indexOf(PROMPT_NAME + '=1') !== -1;
1386    }
1387
1388    function markPrompted(){
1389        var secure = location.protocol === 'https:' ? ';Secure' : '';
1390        document.cookie = PROMPT_NAME + '=1;Max-Age=' + MAX_AGE + ';Path=/;SameSite=Lax' + secure;
1391    }
1392
1393    function writeConsent(consent){
1394        consent.v = VERSION;
1395        consent.ts = Date.now();
1396        consent.necessary = true;
1397        var secure = location.protocol === 'https:' ? ';Secure' : '';
1398        document.cookie = COOKIE_NAME + '=' + encodeURIComponent(JSON.stringify(consent)) +
1399            ';Max-Age=' + MAX_AGE + ';Path=/;SameSite=Lax' + secure;
1400        window.cookieConsent = consent;
1401        // Other scripts (e.g. analytics, added later) can listen for this.
1402        window.dispatchEvent(new CustomEvent('cookieconsent:changed', { detail: consent }));
1403    }
1404
1405    var banner = document.getElementById('cookie-consent');
1406    var prefs  = document.getElementById('cookie-prefs');
1407    var analyticsToggle = document.getElementById('cc-analytics');
1408    var marketingToggle = document.getElementById('cc-marketing');
1409
1410    function hideBanner(){
1411        if (!banner) return;
1412        if (bannerTimer) {
1413            window.clearTimeout(bannerTimer);
1414            bannerTimer = null;
1415        }
1416        banner.classList.remove('is-in');           // slide down
1417        setTimeout(function(){ banner.hidden = true; }, ANIMATION_MS);
1418    }
1419    function showBanner(){
1420        bannerTimer = null;
1421        if (!banner || storedConsent() || hasPrompted()) return;
1422        // Record that we've prompted this visitor so the banner only ever
1423        // appears once per user, even if they ignore it.
1424        markPrompted();
1425        banner.hidden = false; // in layout but translated off-screen via CSS
1426        // Two frames guarantee the off-screen state paints before the slow
1427        // upward transition starts.
1428        window.requestAnimationFrame(function () {
1429            window.requestAnimationFrame(function () {
1430                banner.classList.add('is-in');
1431            });
1432        });
1433    }
1434    // Let visitors see and begin using the page before asking for consent.
1435    function scheduleBanner(){
1436        var go = function(){ bannerTimer = window.setTimeout(showBanner, REVEAL_DELAY_MS); };
1437        if (document.readyState === 'complete') go();
1438        else window.addEventListener('load', go, { once: true });
1439    }
1440    function openPrefs(){
1441        var c = readConsent();
1442        if (analyticsToggle) analyticsToggle.checked = c ? !!c.analytics : false;
1443        if (marketingToggle) marketingToggle.checked = c ? !!c.marketing : false;
1444        if (prefs) { prefs.hidden = false; document.body.style.overflow = 'hidden'; }
1445    }
1446    function closePrefs(){ if (prefs) { prefs.hidden = true; document.body.style.overflow = ''; } }
1447
1448    function acceptAll(){ writeConsent({ analytics: true, marketing: true }); hideBanner(); closePrefs(); }
1449    function rejectAll(){ writeConsent({ analytics: false, marketing: false }); hideBanner(); closePrefs(); }
1450    function savePrefs(){
1451        writeConsent({
1452            analytics: analyticsToggle ? !!analyticsToggle.checked : false,
1453            marketing: marketingToggle ? !!marketingToggle.checked : false
1454        });
1455        hideBanner(); closePrefs();
1456    }
1457
1458    document.addEventListener('click', function(e){
1459        var el = e.target.closest('[data-cc-action]');
1460        if (!el) return;
1461        var a = el.getAttribute('data-cc-action');
1462        if (a === 'accept') acceptAll();
1463        else if (a === 'reject') rejectAll();
1464        else if (a === 'customize') openPrefs();
1465        else if (a === 'save') savePrefs();
1466        else if (a === 'close-prefs') closePrefs();
1467        else if (a === 'open-settings') { e.preventDefault(); openPrefs(); }
1468    });
1469    document.addEventListener('keydown', function(e){ if (e.key === 'Escape') closePrefs(); });
1470
1471    // Expose current consent so other scripts can read it.
1472    window.cookieConsent = readConsent();
1473
1474    // Show once per visitor: only if they have neither made a choice nor been
1475    // prompted before. Animates up after the page has loaded.
1476    if (!storedConsent() && !hasPrompted()) scheduleBanner();
1477})();
1478</script>
1478
1479
1480    <div id="mobileMenu" class="fixed left-0 right-0 z-50 hidden border-b border-white/10 bg-navy-deep md:hidden">
1481    <nav class="mx-auto flex max-w-7xl flex-col gap-1 px-5 py-3 text-sm text-white/85 md:px-8">
1482        <a class="rounded-lg px-2 py-2.5 transition hover:bg-white/5" href="/business-names">Browse</a>
1483        <a class="rounded-lg px-2 py-2.5 transition hover:bg-white/5" href="/favorites">Favorites</a>
1484        <a class="rounded-lg px-2 py-2.5 transition hover:bg-white/5" href="/cart">Cart</a>
1485        <a class="rounded-lg px-2 py-2.5 transition hover:bg-white/5" href="/guides">Guides</a>
1486        <a class="rounded-lg px-2 py-2.5 transition hover:bg-white/5" href="/reviews">Reviews</a>
1487        <a class="rounded-lg px-2 py-2.5 transition hover:bg-white/5" href="/contact">Contact</a>
1488    </nav>
1489</div>
1490<script>
1491    (function () {
1492        var btn = document.getElementById('mobileMenuBtn');
1493        var menu = document.getElementById('mobileMenu');
1494        if (!btn || !menu) return;
1495        var hdr = document.querySelector('header');
1496        btn.addEventListener('click', function () {
1497            if (menu.classList.contains('hidden')) {
1498                if (hdr) menu.style.top = hdr.getBoundingClientRect().bottom + 'px';
1499                menu.classList.remove('hidden');
1500            } else {
1501                menu.classList.add('hidden');
1502            }
1503        });
1504    })();
1505</script>
1505
1506
1507
1508        
1508<script>
1509    (function () {
1510        function count(name, decode) {
1511            try {
1512                var m = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)'));
1513                if (!m) return 0;
1514                var v = decode ? decodeURIComponent(m[1]) : m[1];
1515                var a = JSON.parse(v);
1516                return Array.isArray(a) ? a.length : 0;
1517            } catch (e) { return 0; }
1518        }
1519        function setBadge(id, n) {
1520            var b = document.getElementById(id);
1521            if (!b) return;
1522            if (n > 0) { b.textContent = n; b.classList.remove('topbar-v2__badge--hidden'); }
1523            else { b.classList.add('topbar-v2__badge--hidden'); }
1524        }
1525        window.refreshCartBadge = function () { setBadge('v2-cart-badge', count('cartDomains', true)); };
1526        window.refreshFavBadge  = function () { setBadge('v2-fav-badge',  count('shortlistedDomains', true)); };
1527        function run(){ window.refreshCartBadge(); window.refreshFavBadge(); }
1528        if (document.readyState !== 'loading') run();
1529        else document.addEventListener('DOMContentLoaded', run);
1530    })();
1531</script>
1531
1532
1533
1534        <style>
1535    .dcard .reveal-top { transform: translateY(-100%); transition: transform .5s ease; }
1536    .dcard .reveal-bottom { transform: translateY(100%); transition: transform .5s ease; }
1537    .dcard .logo-wrap { transition: all .5s ease; }
1538
1539    /* Card header: name + category tag, with the favorite button overlapping the
1540       top-right corner. The tag used to be shown/hidden on viewport width, but the
1541       grid runs 2 -> 3 -> 4 columns, so card width does not track viewport: cards at
1542       1024px (4 cols) are narrower than at 1023px (3 cols). The tag could not shrink,
1543       so the row overflowed its reserved right padding and slid under the heart.
1544       Size the tag off the card itself instead. */
1545    [data-domain-card] { container-type: inline-size; container-name: dcard; }
1546    .dcard-head { min-width: 0; }
1547    .dcard-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1548    .dcard-tag {
1549        display: none;          /* shown only when the card is wide enough (below) */
1550        flex: none;             /* never let it squeeze the name */
1551        max-width: 60%;
1552        overflow: hidden;
1553        text-overflow: ellipsis;
1554        white-space: nowrap;
1555    }
1556    /* name (~84px) + gap (12px) + tag (~86px) needs ~182px of content box, and the
1557       content box is cardWidth - 20 (left pad) - 64 (right pad reserved for the heart). */
1558    @container dcard (min-width: 268px) {
1559        .dcard-tag { display: inline-flex; }
1560    }
1561
1562    @media (min-width: 1024px) and (hover: hover) and (pointer: fine) {
1563        .dcard:hover .reveal-top { transform: translateY(0); }
1564        .dcard:hover .reveal-bottom { transform: translateY(0); }
1565        .dcard:hover .logo-wrap { top: 60px !important; bottom: 184px !important; }
1566        .dcard:hover { box-shadow: 0 40px 80px -15px rgba(1,16,46,0.18); }
1567    }
1568
1569    /* Bootstrap compatibility: on pages that also load Bootstrap (base_v2),
1570       Bootstrap's !important spacing/position utilities (.p-5, .mb-4, .py-3,
1571       .top-0/.bottom-0) clobber the card's Tailwind utilities, inflating the
1572       panels and pinning .logo-wrap so it can't reveal the logo on hover.
1573       Re-assert the intended Tailwind values. No-op where Bootstrap is absent. */
1574    .dcard .reveal-top { padding: 1.25rem !important; padding-right: 4rem !important; }
1575    .dcard .reveal-bottom { padding: 1.25rem !important; }
1576    .dcard .reveal-bottom .line-clamp-2 { margin-bottom: 1rem !important; }
1577    .dcard [data-buy] { padding-top: 0.75rem !important; padding-bottom: 0.75rem !important; }
1578    .dcard { border-color: rgba(0,0,0,0.05) !important; }
1579
1580    /* Below desktop: no hover, cards are expanded by default so all info shows.
1581       Use position:relative (not static) so the panels' z-index is honored and
1582       they stay above the full-bleed background image on logo-less cards. */
1583    @media (max-width: 1023px) {
1584        .dcard { aspect-ratio: auto !important; }
1585        .dcard .reveal-top,
1586        .dcard .reveal-bottom { position: relative !important; transform: none !important; }
1587        .dcard .logo-wrap { position: relative !important; inset: auto !important; top: auto !important; bottom: auto !important; min-height: 150px; padding: 1.25rem 0 !important; }
1588        .dcard:hover .logo-wrap { top: auto !important; bottom: auto !important; }
1589    }
1590</style>
1591
1592<script>
1593window.NameOfficeGrid = (function () {
1594    function esc(s){ return (s||'').replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c])); }
1595    function money(n){ return '$' + (n||0).toLocaleString(); }
1596
1597    function getFavs(){ return window.NameOfficeSelectionState ? window.NameOfficeSelectionState.read('shortlistedDomains') : []; }
1598    function setFavs(a){ return window.NameOfficeSelectionState ? window.NameOfficeSelectionState.write('shortlistedDomains', a) : []; }
1599    function getCart(){ return window.NameOfficeSelectionState ? window.NameOfficeSelectionState.read('cartDomains') : []; }
1600    function setCart(a){ return window.NameOfficeSelectionState ? window.NameOfficeSelectionState.write('cartDomains', a) : []; }
1601    function trackDomain(id, type, action){
1602        if (window.NameOfficeAnalytics && window.NameOfficeAnalytics.trackDomainInteraction) {
1603            return window.NameOfficeAnalytics.trackDomainInteraction(id, type, action);
1604        }
1605        return Promise.resolve(null);
1606    }
1607
1608    function refreshCartBadge(){ if (window.refreshCartBadge) window.refreshCartBadge(); }
1609
1610    function buyNow(id){ const c=getCart(); if(!c.includes(id)) c.push(id); setCart(c); trackDomain(id, 'cart', 'add'); window.location.href='/cart'; }
1611
1612    // GA4 add_to_cart. Reads name/price off the card so it works for both the
1613    // server-rendered cards and the ones this file builds during infinite scroll.
1614    function gaAddToCart(id, cardEl){
1615        if (typeof gtag !== 'function') return;
1616        let name = '', price = 0;
1617        if (cardEl){
1618            const nameEl = cardEl.querySelector('.dcard-name');
1619            if (nameEl) name = nameEl.textContent.trim();
1620            const priceEl = cardEl.querySelector('.reveal-bottom span');
1621            if (priceEl) price = Number(String(priceEl.textContent).replace(/[^0-9.]/g, '')) || 0;
1622        }
1623        gtag('event', 'add_to_cart', {
1624            currency: 'USD',
1625            value: price,
1626            items: [{ item_id: name || String(id), item_name: name || String(id), price: price, quantity: 1 }]
1627        });
1628    }
1629
1630    // Add to cart WITHOUT leaving the page (used by the gallery's lean-back mode).
1631    function addToCart(id){ const c=getCart(); const had=c.includes(id); if(!had) c.push(id); setCart(c); if (!had) trackDomain(id, 'cart', 'add'); if (window.refreshCartBadge) window.refreshCartBadge(); return !had; }
1632
1633    // Re-paint every visible card heart from the shortlist cookie. Lets changes
1634    // made inside the gallery show up on the grid behind it.
1635    function syncFavButtons(){
1636        const favs = getFavs();
1637        document.querySelectorAll('[data-fav]').forEach(btn => {
1638            const on = favs.includes(parseInt(btn.dataset.fav));
1639            btn.classList.toggle('text-rose-500', on);
1640            btn.classList.toggle('text-black/30', !on);
1641            const s = btn.querySelector('svg'); if (s) s.setAttribute('fill', on ? 'currentColor' : 'none');
1642        });
1643    }
1644    function toggleFav(id, btn){
1645        let f=getFavs();
1646        const removing=f.includes(id);
1647        if(removing){
1648            f=f.filter(x=>x!==id);
1649            if(btn){
1650                btn.classList.remove('text-rose-500');
1651                const s=btn.querySelector('svg'); if(s) s.setAttribute('fill','none');
1652            }
1653            trackDomain(id, 'favorite', 'remove');
1654        } else {
1655            f.push(id);
1656            if(btn){
1657                btn.classList.add('text-rose-500');
1658                const s=btn.querySelector('svg'); if(s) s.setAttribute('fill','currentColor');
1659            }
1660            trackDomain(id, 'favorite', 'add');
1661        }
1662        setFavs(f);
1663        if (!btn) syncFavButtons();
1664        if (window.refreshFavBadge) window.refreshFavBadge();
1665        return !removing;
1666    }
1667
1668    function cardHTML(d){
1669        const fav = getFavs().includes(d.id);
1670        const desc = d.shortDescription ? esc(d.shortDescription) : '';
1671        const hasLogo = !!d.logoPath;
1672        const nameNoTld = d.rootName || d.formattedName || '';
1673
1674        // Center area: a real logo on white, or the category image filling the
1675        // card with the domain name overlaid in the middle.
1676        const centerInner = hasLogo
1677            ? `<img src="/${esc(d.logoPath)}" alt="${esc(d.imageSeoTitle || d.formattedName)}" title="${esc(d.imageSeoTitle || d.formattedName)}" loading="lazy" class="h-auto w-[80%] max-w-[240px] rounded-lg object-contain">`
1678            : `<span class="px-3 text-center text-2xl font-bold tracking-tight text-white" style="text-shadow:0 2px 12px rgba(0,0,0,0.55)">${esc(nameNoTld)}</span>`;
1679
1680        // Full-bleed category background + scrim, only when there's no logo.
1681        const bgLayer = hasLogo ? '' : `
1682          <div class="absolute inset-0 z-0">
1683            <img src="${esc(d.categoryImagePath || '/categoryImages/default.jpg')}" alt="" loading="lazy" class="h-full w-full object-cover">
1684            <div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/25 to-black/40"></div>
1685          </div>`;
1686
1687        return `
1688        <article data-domain-card class="dcard group relative aspect-[3/4] overflow-hidden rounded-2xl border border-black/5 bg-white transition-all duration-700">
1689          ${bgLayer}
1690          <button type="button" data-fav="${d.id}" aria-label="Save favorite" class="absolute right-4 top-4 z-30 grid h-9 w-9 place-items-center rounded-full bg-white/80 backdrop-blur transition-colors hover:text-rose-500 ${fav?'text-rose-500':'text-black/30'}">
1691            <svg width="16" height="16" viewBox="0 0 24 24" fill="${fav?'currentColor':'none'}" stroke="currentColor" stroke-width="2"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>
1692          </button>
1693          <div class="reveal-top absolute left-0 right-0 top-0 z-20 border-b border-black/5 bg-white p-5 pr-16">
1694            <div class="dcard-head flex items-center justify-between gap-3">
1695              <a href="${esc(d.path)}" class="dcard-name text-[10px] font-semibold uppercase tracking-[0.2em] text-black/50 underline-offset-2 hover:underline">${esc(d.formattedName)}</a>
1696              <span class="dcard-tag rounded-full bg-mint/20 px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider text-navy">${esc(d.categoryName||'Premium')}</span>
1697            </div>
1698          </div>
1699          <div class="logo-wrap pointer-events-none absolute inset-x-0 top-0 bottom-0 z-10 flex items-center justify-center px-4">
1700            <a href="${esc(d.path)}" class="pointer-events-auto flex w-full items-center justify-center">
1701              ${centerInner}
1702            </a>
1703          </div>
1704          <div class="reveal-bottom absolute bottom-0 left-0 right-0 z-20 border-t border-black/5 bg-white p-5">
1705            <div class="mb-2 flex items-center justify-between">
1706              <button type="button" data-gallery="${d.id}" aria-label="Play this name in the gallery" class="inline-flex items-center gap-1.5 text-[11px] font-semibold text-black/60 transition-colors hover:text-emerald-600">
1707                <svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M6 4l14 8-14 8z"/></svg>
1708                Gallery
1709              </button>
1710              <button type="button" data-inquire="${esc(d.name)}" data-inquire-name="${esc(d.formattedName)}" class="inline-flex items-center gap-0.5 text-[11px] font-semibold text-black/60 transition-colors hover:text-navy hover:underline">
1711                Inquire
1712                <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M7 17 17 7M7 7h10v10"/></svg>
1713              </button>
1714            </div>
1715            <p class="mb-4 line-clamp-2 text-xs leading-relaxed text-black/60">${desc}</p>
1716            <div class="flex items-stretch justify-between gap-2">
1717              <span class="flex items-center px-1 text-lg font-bold tracking-tight">${money(d.price)}</span>
1718              <button type="button" data-buy="${d.id}" class="inline-flex shrink-0 items-center justify-center whitespace-nowrap rounded-md bg-navy px-3 py-3 text-[10px] font-bold uppercase tracking-[0.12em] text-white transition-colors hover:bg-[#011845] sm:px-4 sm:text-[11px] sm:tracking-[0.15em]">Buy Now</button>
1719            </div>
1720          </div>
1721        </article>`;
1722    }
1723
1724    // Switchable vibe facets (values mirror the backend enums).
1725    // Single-select "character" facets, shown as dropdowns.
1726    const CHARACTER_FACETS = [
1727        { key: 'soundWeight', label: 'Sound', options: ['hard','balanced','soft'] },
1728        { key: 'soundBrightness', label: 'Tone', options: ['bright','neutral','dark'] },
1729        { key: 'soundEnergy', label: 'Energy', options: ['punchy','steady','flowing'] },
1730        { key: 'premiumFeel', label: 'Feel', options: ['everyday','professional','premium','luxury'] },
1731        { key: 'formality', label: 'Style', options: ['playful','neutral','professional'] },
1732    ];
1733    const PERSONALITY_OPTIONS = ['innovative','trustworthy','bold','friendly','premium','playful','minimal','technical','human','authoritative'];
1734    const NAME_TYPES = [
1735        { value: 'abstract', label: 'Abstract' },
1736        { value: 'evocative', label: 'Evocative' },
1737        { value: 'lexical', label: 'Lexical' },
1738    ];
1739    const QUICK_TLDS = [
1740        { value: '', label: 'All' },
1741        { value: 'com', label: '.com' },
1742        { value: 'ai', label: '.ai' },
1743    ];
1744    const cap = function(s){ return s ? s.charAt(0).toUpperCase() + s.slice(1) : s; };
1745
1746    function create(opts){
1747        const cfg = Object.assign({
1748            apiUrl: '/names-api', limit: 24, countLabel: 'curated identities',
1749            grid: 'grid', sentinel: 'sentinel', loadingRow: 'loadingRow', emptyRow: 'emptyRow', countEl: 'resultCount', filterEl: 'vibeFilter',
1750        }, opts || {});
1751
1752        const grid = document.getElementById(cfg.grid);
1753        const sentinel = document.getElementById(cfg.sentinel);
1754        const loadingRow = document.getElementById(cfg.loadingRow);
1755        const emptyRow = document.getElementById(cfg.emptyRow);
1756        const countEl = cfg.countEl ? document.getElementById(cfg.countEl) : null;
1757        const filterEl = cfg.filterEl ? document.getElementById(cfg.filterEl) : null;
1758        function formatCount(total){ return Number(total || 0).toLocaleString() + (cfg.countLabel ? ' ' + cfg.countLabel : ''); }
1759        function renderedDomainCount(){
1760            return grid ? grid.querySelectorAll('[data-domain-card]').length : 0;
1761        }
1762
1763        const hasInitialItems = Number.isFinite(cfg.initialPage) && cfg.initialPage > 0;
1764        const initialPage = hasInitialItems ? cfg.initialPage : 0;
1765        const initialTotal = Number.isFinite(cfg.initialTotal) ? cfg.initialTotal : 0;
1766        const initialRenderedCount = Number.isFinite(cfg.initialRenderedCount) ? cfg.initialRenderedCount : 0;
1767        const state = {
1768            page: hasInitialItems ? initialPage + 1 : 1,
1769            params: cfg.params || {},
1770            loading: false,
1771            reloadPending: false,
1772            done: hasInitialItems ? initialRenderedCount >= initialTotal : false,
1773            total: hasInitialItems ? initialTotal : 0,
1774            // Live list of every loaded domain object, in grid order. Seeded with
1775            // the server-rendered initial items so the gallery has data before any
1776            // API call. Kept in sync as infinite scroll loads more.
1777            items: Array.isArray(cfg.initialItems) ? cfg.initialItems.slice() : [],
1778            overrides: cfg.initialOverrides ? Object.assign({}, cfg.initialOverrides) : {},
1779            vibe: cfg.vibe || null,
1780            abstractness: Array.isArray(cfg.initialAbstractness) && cfg.initialAbstractness.length
1781                ? cfg.initialAbstractness.slice()
1782                : NAME_TYPES.map(function(t){ return t.value; }), // all name types shown by default
1783            tld: typeof cfg.initialTld === 'string' && cfg.initialTld ? cfg.initialTld.toLowerCase() : null,
1784            filterExpanded: false,
1785        };
1786        const itemsListeners = [];
1787        function emitItemsChanged(){ itemsListeners.forEach(fn => { try { fn(state.items, state.done); } catch(e){} }); }
1788
1789        if (countEl && hasInitialItems) {
1790            countEl.textContent = formatCount(state.total);
1791        }
1792        if (emptyRow && hasInitialItems && initialRenderedCount === 0) {
1793            emptyRow.classList.remove('hidden');
1794        }
1795
1796        function buildUrl(){
1797            let u = cfg.apiUrl + (cfg.apiUrl.includes('?') ? '&' : '?') + 'page=' + state.page + '&limit=' + cfg.limit;
1798            if (state.params.term) u += '&term=' + encodeURIComponent(state.params.term);
1799            (state.params.types || []).forEach(t => { u += '&type[]=' + encodeURIComponent(t); });
1800            if (state.tld) u += '&tld=' + encodeURIComponent(state.tld);
1801            Object.keys(state.overrides).forEach(function(key){
1802                const val = state.overrides[key];
1803                if (key === 'personality'){ (val || []).forEach(function(x){ u += '&personality[]=' + encodeURIComponent(x); }); }
1804                else if (val){ u += '&' + encodeURIComponent(key) + '=' + encodeURIComponent(val); }
1805            });
1806            if (state.abstractness && state.abstractness.length && state.abstractness.length < NAME_TYPES.length){
1807                state.abstractness.forEach(function(v){ u += '&abstractness[]=' + encodeURIComponent(v); });
1808            }
1809            return u;
1810        }
1811
1812        // ---- Refine filter ----
1813        function currentFacet(key){
1814            if (state.overrides[key] != null) return state.overrides[key];
1815            return state.vibe ? state.vibe[key] : null;
1816        }
1817        function personalityActive(opt){
1818            const p = (state.overrides.personality && state.overrides.personality.length)
1819                ? state.overrides.personality
1820                : (state.vibe && state.vibe.personality ? state.vibe.personality : []);
1821            return p.indexOf(opt) >= 0;
1822        }
1823
1824        function renderFilter(){
1825            if (!filterEl) return;
1826            const v = state.vibe;
1827            filterEl.classList.remove('hidden');
1828            const isCustom = !!(v && v.source === 'custom');
1829            const hasManualState = Object.keys(state.overrides).length > 0 || state.abstractness.length < NAME_TYPES.length || !!state.tld;
1830            const canReset = isCustom || hasManualState;
1831            const hasVibe = !!(v && (v.soundWeight || v.soundBrightness || v.soundEnergy || v.premiumFeel || v.formality || (v.personality && v.personality.length)));
1832            const isExpanded = !!state.filterExpanded;
1833            const chevron = isExpanded
1834                ? '<svg width="12" height="12" viewBox="0 0 20 20" fill="none" aria-hidden="true" class="shrink-0"><path d="M5 12.5 10 7.5l5 5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'
1835                : '<svg width="12" height="12" viewBox="0 0 20 20" fill="none" aria-hidden="true" class="shrink-0"><path d="M5 7.5 10 12.5l5-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
1836
1837            let h = '<div class="rounded-[26px] border border-[#d7e5f6] bg-[linear-gradient(180deg,rgba(255,255,255,0.94)_0%,rgba(244,249,255,0.98)_100%)] p-4 shadow-[0_18px_38px_rgba(7,23,51,0.06)] sm:p-5">';
1838
1839            h += '<div class="' + (isExpanded ? 'mb-4 border-b border-[#dbe6f3] pb-4 ' : '') + 'flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">';
1840            h += '<div class="flex flex-wrap items-center gap-2">';
1841            h += '<button type="button" data-refine-toggle aria-expanded="' + (isExpanded ? 'true' : 'false') + '" class="inline-flex items-center gap-2 rounded-full bg-navy px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.18em] text-white shadow-[0_10px_24px_rgba(1,16,46,0.18)] transition hover:bg-[#011845]">Refine ' + chevron + '</button>';
1842            if (state.params.term) h += '<span class="rounded-full border border-[#d7e5f6] bg-white/90 px-3 py-1 text-xs font-medium text-[#62708a]">' + (hasVibe ? 'Suggested for ' : 'Search term ') + '&ldquo;' + esc(state.params.termLabel || state.params.term) + '&rdquo;</span>';
1843            h += '</div>';
1844            h += '<div class="flex flex-wrap items-center gap-2">';
1845            h += '<span class="mr-0.5 text-[10px] font-semibold uppercase tracking-[0.16em] text-[#8b97ad]">Domain ending</span>';
1846            QUICK_TLDS.forEach(function(option){
1847                const active = (state.tld || '') === option.value;
1848                const cls = active
1849                    ? 'border-navy bg-navy text-white shadow-[0_8px_20px_rgba(1,16,46,0.16)]'
1850                    : 'border-[#cbd8e8] bg-white text-[#52627d] hover:border-navy/35 hover:text-navy';
1851                h += '<button type="button" data-tld-filter="' + option.value + '" aria-pressed="' + (active ? 'true' : 'false') + '" class="inline-flex min-h-9 items-center justify-center rounded-full border px-3.5 py-1.5 text-xs font-bold transition ' + cls + '">' + option.label + '</button>';
1852            });
1853            if (canReset) h += '<button type="button" data-vibe-reset class="ml-1 inline-flex min-h-9 items-center justify-center rounded-full border border-[#d1dcec] bg-white px-3 py-1.5 text-[11px] font-semibold uppercase tracking-[0.16em] text-[#62708a] transition hover:border-navy/20 hover:text-navy">Reset</button>';
1854            h += '</div>';
1855            h += '</div>';
1856
1857            if (isExpanded) {
1858                h += '<div class="mb-2 text-[11px] font-semibold uppercase tracking-[0.18em] text-[#8b97ad]">Character</div>';
1859                h += '<div class="mb-4 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-5">';
1860                CHARACTER_FACETS.forEach(function(f){
1861                    const cur = currentFacet(f.key);
1862                    h += '<label class="flex flex-col gap-1.5 rounded-[18px] border border-[#d7e5f6] bg-white/85 p-3 shadow-[inset_0_1px_0_rgba(255,255,255,0.92)]"><span class="text-[11px] font-semibold uppercase tracking-[0.14em] text-[#72819a]">' + f.label + '</span>';
1863                    h += '<select data-facet-select="' + f.key + '" class="rounded-xl border border-[#d7e5f6] bg-[#f8fbff] px-3 py-2 text-sm font-semibold text-navy focus:border-navy/40 focus:outline-none">';
1864                    h += '<option value=""' + (cur ? '' : ' selected') + '>Any</option>';
1865                    f.options.forEach(function(opt){
1866                        h += '<option value="' + opt + '"' + (cur === opt ? ' selected' : '') + '>' + cap(opt) + '</option>';
1867                    });
1868                    h += '</select></label>';
1869                });
1870                h += '</div>';
1871
1872                h += '<div class="mb-2 text-[11px] font-semibold uppercase tracking-[0.18em] text-[#8b97ad]">Personality</div>';
1873                h += '<div class="mb-4 flex flex-wrap gap-2">';
1874                PERSONALITY_OPTIONS.forEach(function(opt){
1875                    const cls = personalityActive(opt)
1876                        ? 'rounded-full bg-navy px-3 py-1.5 text-xs font-semibold text-white capitalize shadow-[0_10px_24px_rgba(1,16,46,0.18)]'
1877                        : 'rounded-full border border-[#d1dcec] bg-white/90 px-3 py-1.5 text-xs font-semibold text-[#62708a] capitalize transition hover:border-navy/30 hover:text-navy';
1878                    h += '<button type="button" class="' + cls + '" data-facet="personality" data-opt="' + opt + '">' + opt + '</button>';
1879                });
1880                h += '</div>';
1881
1882                h += '<div class="border-t border-[#dbe6f3] pt-4">';
1883                h += '<div class="mb-2 text-[11px] font-semibold uppercase tracking-[0.18em] text-[#8b97ad]">Name type <span class="font-normal normal-case tracking-normal text-[#aab4c5]">&middot; all shown by default</span></div>';
1884                h += '<div class="flex flex-wrap gap-2">';
1885                NAME_TYPES.forEach(function(t){
1886                    const on = state.abstractness.indexOf(t.value) >= 0;
1887                    const cls = on
1888                        ? 'inline-flex items-center gap-1 rounded-full bg-navy px-3 py-1.5 text-xs font-semibold text-white shadow-[0_10px_24px_rgba(1,16,46,0.18)]'
1889                        : 'inline-flex items-center gap-1 rounded-full border border-[#d1dcec] bg-white/90 px-3 py-1.5 text-xs font-semibold text-[#62708a] transition hover:border-navy/30 hover:text-navy';
1890                    h += '<button type="button" class="' + cls + '" data-type-toggle="' + t.value + '">' + (on ? '<span aria-hidden="true">&#10003;</span> ' : '') + t.label + '</button>';
1891                });
1892                h += '</div></div>';
1893            }
1894
1895            h += '</div>';
1896            filterEl.innerHTML = h;
1897        }
1898
1899        function toggleFilterExpanded(){
1900            state.filterExpanded = !state.filterExpanded;
1901            renderFilter();
1902        }
1903        function setFacetValue(key, value){ if (value) state.overrides[key] = value; else delete state.overrides[key]; load(true); }
1904        function togglePersonality(opt){
1905            let base = (state.overrides.personality && state.overrides.personality.length)
1906                ? state.overrides.personality.slice()
1907                : ((state.vibe && state.vibe.personality) ? state.vibe.personality.slice() : []);
1908            const i = base.indexOf(opt);
1909            if (i >= 0) base.splice(i, 1); else base.push(opt);
1910            state.overrides.personality = base;
1911            load(true);
1912        }
1913        function setFacet(key, opt){ if (key === 'personality') togglePersonality(opt); else setFacetValue(key, opt); }
1914        function setTld(value){ state.tld = value || null; load(true); }
1915        function toggleType(value){
1916            const i = state.abstractness.indexOf(value);
1917            if (i >= 0){ if (state.abstractness.length > 1) state.abstractness.splice(i, 1); } // keep at least one
1918            else state.abstractness.push(value);
1919            load(true);
1920        }
1921        function resetFacets(){
1922            state.overrides = {};
1923            state.abstractness = NAME_TYPES.map(function(t){ return t.value; });
1924            state.tld = null;
1925            load(true);
1926        }
1927
1928        if (filterEl){
1929            filterEl.addEventListener('change', function(e){
1930                const sel = e.target.closest('select[data-facet-select]');
1931                if (sel){ setFacetValue(sel.dataset.facetSelect, sel.value); }
1932            });
1933            filterEl.addEventListener('click', function(e){
1934                const toggle = e.target.closest('[data-refine-toggle]');
1935                if (toggle){ e.preventDefault(); toggleFilterExpanded(); return; }
1936                const reset = e.target.closest('[data-vibe-reset]');
1937                if (reset){ e.preventDefault(); resetFacets(); return; }
1938                const tld = e.target.closest('[data-tld-filter]');
1939                if (tld){ e.preventDefault(); setTld(tld.dataset.tldFilter); return; }
1940                const type = e.target.closest('[data-type-toggle]');
1941                if (type){ e.preventDefault(); toggleType(type.dataset.typeToggle); return; }
1942                const chip = e.target.closest('[data-facet="personality"]');
1943                if (chip){ e.preventDefault(); togglePersonality(chip.dataset.opt); }
1944            });
1945        }
1946        renderFilter();
1947
1948        async function load(reset){
1949            if (state.loading){
1950                if (reset) state.reloadPending = true;
1951                return;
1952            }
1953            if (state.done && !reset) return;
1954            if (reset){ state.page = 1; state.done = false; grid.innerHTML = ''; state.items = []; emitItemsChanged(); }
1955            state.loading = true;
1956            if (loadingRow) loadingRow.classList.remove('hidden');
1957            if (emptyRow) emptyRow.classList.add('hidden');
1958            try {
1959                const res = await fetch(buildUrl());
1960                const data = await res.json();
1961                state.total = data.totalItemCount || 0;
1962                if (typeof data.vibe !== 'undefined') { state.vibe = data.vibe; renderFilter(); }
1963                if (countEl) countEl.textContent = formatCount(state.total);
1964                if (data.items && data.items.length){
1965                    grid.insertAdjacentHTML('beforeend', data.items.map(cardHTML).join(''));
1966                    state.items.push.apply(state.items, data.items);
1967                    state.page++;
1968                    if (renderedDomainCount() >= state.total) state.done = true;
1969                    emitItemsChanged();
1970                } else {
1971                    state.done = true;
1972                    emitItemsChanged();
1973                }
1974                if (renderedDomainCount() === 0 && emptyRow) emptyRow.classList.remove('hidden');
1975            } catch(e){ console.error(e); }
1976            state.loading = false;
1977            if (loadingRow) loadingRow.classList.add('hidden');
1978            if (state.reloadPending){
1979                state.reloadPending = false;
1980                load(true);
1981                return;
1982            }
1983            if (!state.done && document.body.offsetHeight <= window.innerHeight + 400){ setTimeout(()=>load(false), 50); }
1984        }
1985
1986        // Infinite scroll
1987        function maybeLoadMore(){ if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 900) load(false); }
1988        window.addEventListener('scroll', maybeLoadMore, { passive: true });
1989        if (sentinel) new IntersectionObserver(es => { if (es[0].isIntersecting) load(false); }, { rootMargin: '800px' }).observe(sentinel);
1990
1991        // Delegated card actions
1992        grid.addEventListener('click', (e)=>{
1993            const fav = e.target.closest('[data-fav]');
1994            const buy = e.target.closest('[data-buy]');
1995            const gallery = e.target.closest('[data-gallery]');
1996            const inquire = e.target.closest('[data-inquire]');
1997            if (inquire){ e.preventDefault(); if (window.NameOfficeInquiry) window.NameOfficeInquiry.open(inquire.dataset.inquire, inquire.dataset.inquireName); }
1998            else if (gallery){ e.preventDefault(); if (window.NameOfficeGallery) window.NameOfficeGallery.openById(parseInt(gallery.dataset.gallery)); }
1999            else if (fav){
2000                e.preventDefault();
2001                const id = parseInt(fav.dataset.fav);
2002                toggleFav(id, fav);
2003                // On the favorites page, un-saving a name takes it off the list.
2004                if (cfg.removeOnUnfavorite && !getFavs().includes(id)){
2005                    const card = fav.closest('[data-domain-card]');
2006                    if (card){
2007                        card.style.transition = 'opacity .2s, transform .2s';
2008                        card.style.opacity = '0';
2009                        card.style.transform = 'scale(.96)';
2010                        setTimeout(()=>{
2011                            card.remove();
2012                            state.items = state.items.filter(x => x.id !== id);
2013                            if (state.total > 0) state.total--;
2014                            if (countEl) countEl.textContent = formatCount(state.total);
2015                            if (renderedDomainCount() === 0 && emptyRow) emptyRow.classList.remove('hidden');
2016                        }, 200);
2017                    }
2018                }
2019            }
2020            else if (buy){
2021                e.preventDefault();
2022                const id = parseInt(buy.dataset.buy);
2023                gaAddToCart(id, buy.closest('[data-domain-card]'));
2024                buyNow(id);
2025            }
2026        });
2027
2028        refreshCartBadge();
2029        if (hasInitialItems) {
2030            if (!state.done && document.body.offsetHeight <= window.innerHeight + 400) {
2031                setTimeout(()=>load(false), 50);
2032            }
2033        } else {
2034            load(true);
2035        }
2036
2037        const api = {
2038            setParams(p){ state.params = p || {}; load(true); },
2039            reload(){ load(true); },
2040            getItems(){ return state.items; },
2041            isDone(){ return state.done; },
2042            isLoading(){ return state.loading; },
2043            loadMore(){ return load(false); },
2044            onItemsChanged(fn){ if (typeof fn === 'function') itemsListeners.push(fn); },
2045            setFacet(key, opt){ setFacet(key, opt); },
2046            resetFacets(){ resetFacets(); },
2047        };
2048        // Expose the most recently created grid so the gallery (and others) can
2049        // read the live, filtered item set without re-fetching.
2050        window.nameOfficeGrid = api;
2051        return api;
2052    }
2053
2054    return { create, cardHTML, refreshCartBadge, buyNow, addToCart, toggleFav, setFavs, getFavs, getCart, setCart, syncFavButtons };
2055})();
2056</script>
2056
2057
2058    <style>
2059    .nog-overlay { position: fixed; inset: 0; z-index: 9999; display: flex; align-items: center; justify-content: center; background: rgba(0,0,0,.92); }
2060    .nog-overlay[hidden] { display: none; }
2061
2062    .nog-frame { position: relative; height: 92vh; max-height: 900px; width: min(92vw, 480px); overflow: hidden; border-radius: 28px; box-shadow: 0 50px 120px -20px rgba(0,0,0,.6); background:#0b1020; }
2063    .nog-stage { position: absolute; inset: 0; overflow-y: scroll; overflow-x: hidden; scroll-snap-type: y mandatory; overscroll-behavior: contain; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
2064    .nog-stage::-webkit-scrollbar { display: none; }
2065
2066    .nog-slide { position: relative; height: 100%; overflow: hidden; scroll-snap-align: start; scroll-snap-stop: always; container-type: inline-size; }
2067    .nog-slide__scrim { position:absolute; inset:0; background: radial-gradient(circle at 50% 28%, rgba(255,255,255,.10), transparent 60%); }
2068    .nog-slide__inner { position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center; padding: 64px 32px 168px; text-align:center; }
2069    .nog-logo { display:flex; align-items:center; justify-content:center; height: 13.5rem; width: 13.5rem; max-width: 62%; border-radius: 24px; background:#fff; padding:14px; box-shadow:0 24px 60px -12px rgba(0,0,0,.5); margin-bottom: 28px; }
2070    .nog-logo img { height:100%; width:100%; object-fit:contain; border-radius:12px; }
2071    .nog-name { color:#fff; font-weight:600; letter-spacing:-.02em; line-height:1.05; font-size: clamp(1.7rem, 8cqw, 3rem); word-break: break-word; text-decoration:none; }
2072    .nog-name .tld { color: rgba(255,255,255,.4); font-weight:600; }
2073    .nog-pron { margin-top:8px; font-family: ui-monospace, 'SFMono-Regular', Menlo, monospace; font-size:13px; letter-spacing:.04em; color: rgba(255,255,255,.55); }
2074    .nog-cat { margin-top:10px; font-size:11px; text-transform:uppercase; letter-spacing:.28em; color: rgba(255,255,255,.5); }
2075    .nog-desc { margin-top: 22px; max-width: 36ch; font-size: 15px; line-height:1.65; color: rgba(255,255,255,.82); }
2076    .nog-tags { margin-top: 20px; display:flex; flex-wrap:wrap; gap:6px; justify-content:center; }
2077    .nog-tag { border-radius:999px; background: rgba(255,255,255,.10); padding:4px 10px; font-size:11px; font-weight:500; color: rgba(255,255,255,.78); backdrop-filter: blur(4px); }
2078
2079    .nog-strip { position:absolute; inset-inline:0; bottom:0; z-index:20; border-top:1px solid rgba(255,255,255,.12); background: rgba(0,0,0,.34); backdrop-filter: blur(10px); padding:18px; }
2080    .nog-strip__meta { display:flex; align-items:center; justify-content:space-between; font-size:12px; color: rgba(255,255,255,.72); margin-bottom:12px; }
2081    .nog-strip__price { color:#fff; font-weight:600; font-variant-numeric: tabular-nums; }
2082    .nog-strip__dot { margin:0 8px; color: rgba(255,255,255,.3); }
2083    .nog-details { display:inline-flex; align-items:center; gap:4px; color: rgba(255,255,255,.72); text-decoration:none; }
2084    .nog-details:hover { color:#fff; text-decoration:underline; text-underline-offset:4px; }
2085    .nog-claim { display:block; width:100%; border:none; cursor:pointer; border-radius:14px; background:#fff; padding:14px; font-size:14px; font-weight:600; letter-spacing:.01em; color:#01102E; box-shadow:0 12px 30px -10px rgba(0,0,0,.5); transition: background .15s, transform .1s; }
2086    .nog-claim:hover { background:#74F7B2; }
2087    .nog-claim:active { transform: scale(.99); }
2088
2089    /* Right action rail — fixed over the scroller */
2090    .nog-rail { position:absolute; right:12px; bottom: 188px; z-index:30; display:flex; flex-direction:column; align-items:center; gap:18px; }
2091    .nog-railbtn { display:flex; flex-direction:column; align-items:center; gap:5px; background:none; border:none; cursor:pointer; color:#fff; }
2092    .nog-railbtn__icon { display:grid; place-items:center; height:48px; width:48px; border-radius:50%; background: rgba(255,255,255,.12); backdrop-filter: blur(4px); transition: background .15s, transform .12s; }
2093    .nog-railbtn:hover .nog-railbtn__icon { background: rgba(255,255,255,.22); }
2094    .nog-railbtn:active .nog-railbtn__icon { transform: scale(.92); }
2095    .nog-railbtn.is-active .nog-railbtn__icon { background: rgba(255,255,255,.22); }
2096    .nog-railbtn__label { font-size:10px; font-weight:500; color: rgba(255,255,255,.72); }
2097    .nog-railbtn .heart-on { display:none; }
2098    .nog-railbtn.is-active .heart-on { display:block; }
2099    .nog-railbtn.is-active .heart-off { display:none; }
2100
2101    /* Chrome: close, counter, dots, desktop nav, hint */
2102    .nog-close, .nog-counter { position:absolute; top:16px; z-index:50; }
2103    .nog-close { left:16px; display:grid; place-items:center; height:40px; width:40px; border-radius:50%; border:none; cursor:pointer; background: rgba(255,255,255,.12); color:#fff; backdrop-filter: blur(4px); transition: background .15s; }
2104    .nog-close:hover { background: rgba(255,255,255,.22); }
2105    .nog-counter { right:16px; border-radius:999px; background: rgba(255,255,255,.12); padding:6px 12px; font-size:12px; font-variant-numeric: tabular-nums; color: rgba(255,255,255,.82); backdrop-filter: blur(4px); }
2106    .nog-dots { position:absolute; left:10px; top:50%; transform: translateY(-50%); z-index:30; display:flex; flex-direction:column; gap:5px; pointer-events:none; }
2107    .nog-dots span { border-radius:999px; background: rgba(255,255,255,.3); height:6px; width:6px; transition: all .25s; }
2108    .nog-dots span.is-active { height:16px; background:#fff; }
2109    .nog-nav { position:absolute; right:16px; top:50%; transform: translateY(-50%); z-index:40; display:none; flex-direction:column; gap:10px; }
2110    .nog-navbtn { display:grid; place-items:center; height:44px; width:44px; border-radius:50%; border:none; cursor:pointer; background: rgba(255,255,255,.12); color:#fff; backdrop-filter: blur(4px); transition: background .15s; }
2111    .nog-navbtn:hover { background: rgba(255,255,255,.22); }
2112    .nog-navbtn:disabled { opacity:.3; cursor:default; }
2113    .nog-hint { position:absolute; bottom:14px; left:50%; transform: translateX(-50%); z-index:40; display:none; gap:12px; align-items:center; font-size:11px; text-transform:uppercase; letter-spacing:.2em; color: rgba(255,255,255,.4); white-space:nowrap; }
2114    .nog-hint span.sep { color: rgba(255,255,255,.2); }
2115    @media (min-width: 768px) { .nog-nav { display:flex; } .nog-hint { display:flex; } .nog-rail { right:16px; } }
2116
2117    .nog-toast { position: fixed; left:50%; top:24px; transform: translateX(-50%) translateY(-12px); z-index:10000; background:#01102E; color:#fff; border:1px solid rgba(255,255,255,.12); border-radius:12px; padding:10px 16px; font-size:13px; box-shadow:0 16px 40px -12px rgba(0,0,0,.5); opacity:0; transition: opacity .2s, transform .2s; pointer-events:none; }
2118    .nog-toast.is-show { opacity:1; transform: translateX(-50%) translateY(0); }
2119    .nog-toast b { color:#74F7B2; }
2120
2121    /* Slide content stays hidden until its slide is the active one, so you never
2122       see it pre-animation (no "show -> flash -> fade"). It fades in quickly the
2123       moment the slide becomes active while scrolling. The bottom strip is not
2124       animated so price/CTA are always present. */
2125    @keyframes nogFadeIn { from { opacity:0; transform: translateY(10px);} to { opacity:1; transform: translateY(0);} }
2126    .nog-slide__inner { opacity: 0; }
2127    .nog-slide.is-active .nog-slide__inner { animation: nogFadeIn 280ms ease-out both; }
2128    @media (prefers-reduced-motion: reduce) {
2129        .nog-slide__inner { opacity: 1; }
2130        .nog-slide.is-active .nog-slide__inner { animation: none; }
2131        .nog-stage { scroll-behavior: auto; }
2132    }
2133</style>
2134
2135<script>
2136window.NameOfficeGallery = (function () {
2137    var TINTS = [
2138        'linear-gradient(135deg,#0f172a,#1e1b4b,#0f172a)',
2139        'linear-gradient(135deg,#0c2340,#134e4a,#0c2340)',
2140        'linear-gradient(135deg,#1a1a2e,#3b0764,#1a1a2e)',
2141        'linear-gradient(135deg,#0d0d0d,#2d2d2d,#0d0d0d)',
2142        'linear-gradient(135deg,#1e3a5f,#0c2340,#1e3a5f)',
2143        'linear-gradient(135deg,#3a1a1a,#5c2018,#3a1a1a)'
2144    ];
2145    var LOAD_AHEAD = 3;   // request more when this close to the end
2146
2147    var G = window.NameOfficeGrid;
2148    var overlay = null, frame = null, stage = null, counterEl = null, dotsEl = null,
2149        prevBtn = null, nextBtn = null, toastEl = null;
2150    var items = [], index = 0, total = 0, renderedCount = 0;
2151    var toastTimer = null, keyHandler = null, prevOverflow = '', scrollRaf = null, settleTimer = null;
2152
2153    function esc(s){ return (s||'').replace(/[&<>"']/g, function(c){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c]; }); }
2154    function money(n){ return '$' + (Number(n)||0).toLocaleString(); }
2155    function nameNoTld(item){
2156        if (item && typeof item === 'object' && item.rootName) return item.rootName;
2157        var fn = item && typeof item === 'object' ? item.formattedName : item;
2158        return (fn || '').replace(/\.[a-z0-9]+$/i, '');
2159    }
2160    function tld(item){
2161        if (item && typeof item === 'object' && item.tld) return '.' + String(item.tld).toLowerCase();
2162        var fn = item && typeof item === 'object' ? item.formattedName : item;
2163        var m = (fn || '').match(/\.([a-z0-9]+)$/i);
2164        return m ? '.' + m[1].toLowerCase() : '.com';
2165    }
2166    function gridDone(){ return window.nameOfficeGrid && window.nameOfficeGrid.isDone ? window.nameOfficeGrid.isDone() : true; }
2167
2168    function refreshItems(){
2169        items = (G && window.nameOfficeGrid && window.nameOfficeGrid.getItems) ? window.nameOfficeGrid.getItems() : [];
2170        total = items.length;
2171    }
2172
2173    function toast(html){
2174        if (!toastEl) return;
2175        toastEl.innerHTML = html;
2176        toastEl.classList.add('is-show');
2177        clearTimeout(toastTimer);
2178        toastTimer = setTimeout(function(){ toastEl.classList.remove('is-show'); }, 2200);
2179    }
2180
2181    function isFav(id){ return G.getFavs().indexOf(id) !== -1; }
2182
2183    function toggleFav(id){
2184        return G.toggleFav(id);
2185    }
2186
2187    function addToCart(id){
2188        return G.addToCart(id);
2189    }
2190
2191    function slideHTML(i){
2192        var d = items[i];
2193        if (!d) return '';
2194        var name = nameNoTld(d);
2195        var t = tld(d);
2196        var visual = d.logoPath
2197            ? '<div class="nog-logo"><img src="/' + esc(d.logoPath) + '" alt="' + esc(d.imageSeoTitle || d.formattedName) + '" loading="lazy"></div>'
2198            : '';
2199        var len = name.length;
2200        return ''
2201          + '<div class="nog-slide" data-i="' + i + '" style="background:' + TINTS[i % TINTS.length] + ';">'
2202          +   '<div class="nog-slide__scrim"></div>'
2203          +   '<div class="nog-slide__inner">'
2204          +     visual
2205          +     '<a class="nog-name" href="' + esc(d.path) + '">' + esc(name) + '<span class="tld">' + esc(t) + '</span></a>'
2206          +     (d.pronunciation ? '<div class="nog-pron">/' + esc(d.pronunciation) + '/</div>' : '')
2207          +     '<div class="nog-cat">' + esc(d.categoryName || 'Premium') + '</div>'
2208          +     (d.shortDescription ? '<p class="nog-desc">' + esc(d.shortDescription) + '</p>' : '')
2209          +     '<div class="nog-tags">'
2210          +       '<span class="nog-tag">' + esc(d.categoryName || 'Premium') + '</span>'
2211          +       '<span class="nog-tag">' + len + ' chars</span>'
2212          +       '<span class="nog-tag">' + esc(t) + '</span>'
2213          +     '</div>'
2214          +   '</div>'
2215          +   '<div class="nog-strip">'
2216          +     '<div class="nog-strip__meta">'
2217          +       '<span><span class="nog-strip__price">' + money(d.price) + '</span><span class="nog-strip__dot">·</span>' + esc(t) + '<span class="nog-strip__dot">·</span>' + len + ' chars</span>'
2218          +       '<a class="nog-details" href="' + esc(d.path) + '">
2218Details <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M7 17 17 7M7 7h10v10"/></svg></a>'
2219          +     '</div>'
2220          +     '<button type="button" class="nog-claim" data-claim="' + d.id + '">Claim ' + esc(name) + esc(t) + '</button>'
2221          +   '</div>'
2222          + '</div>';
2223    }
2224
2225    // Append slide elements for any items not yet rendered.
2226    function renderSlides(){
2227        if (renderedCount >= total) return;
2228        var html = '';
2229        for (var i = renderedCount; i < total; i++){ html += slideHTML(i); }
2230        stage.insertAdjacentHTML('beforeend', html);
2231        renderedCount = total;
2232    }
2233
2234    function rebuildSlides(){
2235        stage.innerHTML = '';
2236        renderedCount = 0;
2237        refreshItems();
2238        renderSlides();
2239    }
2240
2241    // Mark the current slide active (re-triggers its entrance animation).
2242    function markActive(){
2243        var slides = stage.querySelectorAll('.nog-slide');
2244        for (var k = 0; k < slides.length; k++){
2245            slides[k].classList.toggle('is-active', parseInt(slides[k].dataset.i) === index);
2246        }
2247    }
2248
2249    function updateChrome(){
2250        var done = gridDone();
2251        counterEl.textContent = (index + 1) + ' / ' + (done ? total : total + '+');
2252        var lo = Math.max(0, index - 2), hi = Math.min(total - 1, index + 2);
2253        var d = '';
2254        for (var i = lo; i <= hi; i++){ d += '<span class="' + (i === index ? 'is-active' : '') + '"></span>'; }
2255        dotsEl.innerHTML = d;
2256        prevBtn.disabled = index === 0;
2257        nextBtn.disabled = index >= total - 1 && done;
2258        var cur = items[index];
2259        var likeBtn = overlay.querySelector('[data-rail="like"]');
2260        if (cur && likeBtn) likeBtn.classList.toggle('is-active', isFav(cur.id));
2261    }
2262
2263    function maybeLoadAhead(){
2264        if (index >= total - 1 - LOAD_AHEAD){
2265            var inst = window.nameOfficeGrid;
2266            if (inst && inst.loadMore && !inst.isDone() && !inst.isLoading()){ inst.loadMore(); }
2267        }
2268    }
2269
2270    // Current-slide tracking via scroll position. Computed synchronously (cheap)
2271    // so it stays in sync even where rAF is throttled.
2272    function onScroll(){
2273        if (!stage.clientHeight) return;
2274        var i = Math.round(stage.scrollTop / stage.clientHeight);
2275        i = Math.max(0, Math.min(i, total - 1));
2276        if (i !== index){
2277            // Fire the fade-in the instant we land on a new slide while scrolling,
2278            // not after the scroll settles (that caused a flash on the already
2279            // hidden->shown content).
2280            index = i;
2281            markActive();
2282            updateChrome();
2283            maybeLoadAhead();
2284        }
2285    }
2286
2287    function scrollToIndex(i, smooth){
2288        var target = Math.max(0, Math.min(i, total - 1));
2289        stage.scrollTo({ top: target * stage.clientHeight, behavior: smooth ? 'smooth' : 'auto' });
2290    }
2291
2292    function go(dir){
2293        var next = index + dir;
2294        if (next < 0) return;
2295        if (next >= total){
2296            if (gridDone()) return;
2297            maybeLoadAhead();
2298            refreshItems();
2299            renderSlides();
2300            if (next >= total) return;
2301        }
2302        scrollToIndex(next, true);
2303    }
2304
2305    /* ---- build / open / close ---- */
2306    function build(){
2307        overlay = document.createElement('div');
2308        overlay.className = 'nog-overlay';
2309        overlay.setAttribute('role', 'dialog');
2310        overlay.setAttribute('aria-modal', 'true');
2311        overlay.setAttribute('aria-label', 'Name gallery');
2312        overlay.innerHTML = ''
2313          + '<button type="button" class="nog-close" data-close aria-label="Close gallery"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6 6 18M6 6l12 12"/></svg></button>'
2314          + '<div class="nog-counter"></div>'
2315          + '<div class="nog-frame">'
2316          +   '<div class="nog-stage"></div>'
2317          +   '<div class="nog-dots"></div>'
2318          +   '<div class="nog-rail">'
2319          +     '<button type="button" class="nog-railbtn" data-rail="like" aria-label="Like"><span class="nog-railbtn__icon">'
2320          +       '<svg class="heart-off" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>'
2321          +       '<svg class="heart-on" width="22" height="22" viewBox="0 0 24 24" fill="#f43f5e" stroke="#f43f5e" stroke-width="2"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>'
2322          +     '</span><span class="nog-railbtn__label">Like</span></button>'
2323          +     '<button type="button" class="nog-railbtn" data-rail="cart" aria-label="Add to cart"><span class="nog-railbtn__icon"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"/></svg></span><span class="nog-railbtn__label">
2323Cart</span></button>'
2324          +     '<button type="button" class="nog-railbtn" data-rail="share" aria-label="Share"><span class="nog-railbtn__icon"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="m8.59 13.51 6.83 3.98M15.41 6.51l-6.82 3.98"/></svg></span><span class="nog-railbtn__label">Share</span></button>'
2325          +   '</div>'
2326          + '</div>'
2327          + '<div class="nog-nav">'
2328          +   '<button type="button" class="nog-navbtn" data-prev aria-label="Previous name"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m18 15-6-6-6 6"/></svg></button>'
2329          +   '<button type="button" class="nog-navbtn" data-next aria-label="Next name"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m6 9 6 6 6-6"/></svg></button>'
2330          + '</div>'
2331          + '<div class="nog-hint"><span>↑ ↓ or swipe</span><span class="sep">·</span><span>L to like</span><span class="sep">·</span><span>Esc to close</span></div>';
2332
2333        document.body.appendChild(overlay);
2334        toastEl = document.createElement('div');
2335        toastEl.className = 'nog-toast';
2336        document.body.appendChild(toastEl);
2337
2338        frame = overlay.querySelector('.nog-frame');
2339        stage = overlay.querySelector('.nog-stage');
2340        counterEl = overlay.querySelector('.nog-counter');
2341        dotsEl = overlay.querySelector('.nog-dots');
2342        prevBtn = overlay.querySelector('[data-prev]');
2343        nextBtn = overlay.querySelector('[data-next]');
2344
2345        stage.addEventListener('scroll', onScroll, { passive: true });
2346
2347        overlay.addEventListener('click', function(e){
2348            if (e.target.closest('[data-close]')) { close(); return; }
2349            if (e.target === overlay) { close(); return; }
2350            if (e.target.closest('[data-prev]')) { go(-1); return; }
2351            if (e.target.closest('[data-next]')) { go(1); return; }
2352            var rail = e.target.closest('[data-rail]');
2353            if (rail) { handleRail(rail.dataset.rail); return; }
2354            var claim = e.target.closest('[data-claim]');
2355            if (claim) { e.preventDefault(); doCart(parseInt(claim.dataset.claim)); return; }
2356        });
2357
2358        keyHandler = function(e){
2359            if (overlay.hidden) return;
2360            if (e.key === 'Escape') close();
2361            else if (e.key === 'ArrowDown' || e.key === 'ArrowRight' || e.key === ' ') { e.preventDefault(); go(1); }
2362            else if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') { e.preventDefault(); go(-1); }
2363            else if (e.key.toLowerCase() === 'l') { if (items[index]) handleRail('like'); }
2364            else if (e.key.toLowerCase() === 'c') { if (items[index]) doCart(items[index].id); }
2365        };
2366        document.addEventListener('keydown', keyHandler);
2367
2368        // Append new slides + refresh counter as the grid streams in more items.
2369        if (window.nameOfficeGrid && window.nameOfficeGrid.onItemsChanged){
2370            window.nameOfficeGrid.onItemsChanged(function(){
2371                if (overlay && !overlay.hidden){ refreshItems(); renderSlides(); updateChrome(); }
2372            });
2373        }
2374    }
2375
2376    function handleRail(kind){
2377        var cur = items[index];
2378        if (!cur) return;
2379        if (kind === 'like'){
2380            var on = toggleFav(cur.id);
2381            var btn = overlay.querySelector('[data-rail="like"]');
2382            if (btn) btn.classList.toggle('is-active', on);
2383            toast(on ? 'Saved <b>' + esc(nameNoTld(cur)) + '</b>' : 'Removed from saved');
2384        } else if (kind === 'cart'){
2385            doCart(cur.id);
2386        } else if (kind === 'share'){
2387            // Always the canonical landing-page URL for this name.
2388            var url = location.origin + cur.path;
2389            var isTouch = window.matchMedia && window.matchMedia('(pointer: coarse)').matches;
2390            // On touch devices the native share sheet is genuinely useful. On
2391            // desktop, copy the link straight to the clipboard so "share" reliably
2392            // puts the landing-page URL there (the OS sheet's "Copy" is not).
2393            if (navigator.share && isTouch){
2394                navigator.share({ title: cur.formattedName, url: url }).catch(function(){});
2395            } else {
2396                copyLink(url);
2397            }
2398        }
2399    }
2400
2401    // Copy a link to the clipboard, with a fallback for non-secure contexts.
2402    function copyLink(url){
2403        function done(){ toast('Link copied'); }
2404        if (navigator.clipboard && navigator.clipboard.writeText){
2405            navigator.clipboard.writeText(url).then(done).catch(function(){ legacyCopy(url); done(); });
2406        } else {
2407            legacyCopy(url); done();
2408        }
2409    }
2410    function legacyCopy(url){
2411        try {
2412            var ta = document.createElement('textarea');
2413            ta.value = url;
2414            ta.setAttribute('readonly', '');
2415            ta.style.position = 'fixed';
2416            ta.style.opacity = '0';
2417            document.body.appendChild(ta);
2418            ta.select();
2419            document.execCommand('copy');
2420            document.body.removeChild(ta);
2421        } catch (e) {}
2422    }
2423
2424    function doCart(id){
2425        var cur = (items[index] && items[index].id === id) ? items[index] : (items.filter(function(x){ return x.id === id; })[0]);
2426        var added = addToCart(id);
2427        toast(added ? 'Added <b>' + esc(nameNoTld(cur || {})) + '</b> to cart' : 'Already in your cart');
2428    }
2429
2430    function openAt(i){
2431        refreshItems();
2432        if (!total) return;
2433        if (!overlay) build();
2434        if (overlay.hidden) { prevOverflow = document.body.style.overflow; }
2435        document.body.style.overflow = 'hidden';
2436        overlay.hidden = false;
2437        index = Math.max(0, Math.min(i || 0, total - 1));
2438        rebuildSlides();
2439        // The frame has a fixed height, so layout is known synchronously — set
2440        // everything now (don't depend on rAF, which is paused in hidden tabs).
2441        updateChrome();
2442        markActive();
2443        scrollToIndex(index, false);
2444        maybeLoadAhead();
2445        // One more frame later in case fonts/images shift the metrics.
2446        requestAnimationFrame(function(){ scrollToIndex(index, false); });
2447    }
2448
2449    function close(){
2450        if (!overlay) return;
2451        overlay.hidden = true;
2452        document.body.style.overflow = prevOverflow;
2453        if (G && G.syncFavButtons) G.syncFavButtons();
2454    }
2455
2456    return {
2457        open: function(i){ openAt(i); },
2458        openById: function(id){ refreshItems(); var i = items.findIndex(function(x){ return x.id === id; }); if (i < 0) i = 0; openAt(i); },
2459        close: close
2460    };
2461})();
2462</script>
2462
2463
2464    <style>
2465    .noi { position: fixed; inset: 0; z-index: 9998; display: none; align-items: center; justify-content: center; padding: 20px; font-family: 'Inter','Noto Sans',sans-serif; }
2466    .noi.is-open { display: flex; }
2467    .noi__backdrop { position: absolute; inset: 0; background: rgba(1,16,46,.62); backdrop-filter: blur(3px); }
2468    .noi__card { position: relative; width: 100%; max-width: 520px; max-height: 92vh; overflow-y: auto; background: #fff; border-radius: 24px; box-shadow: 0 40px 120px -28px rgba(0,0,0,.55); animation: noiIn 320ms cubic-bezier(.22,1,.36,1) both; }
2469    @keyframes noiIn { from { opacity: 0; transform: translateY(16px) scale(.98); } to { opacity: 1; transform: none; } }
2470    .noi__close { position: absolute; top: 16px; right: 16px; appearance: none; background: none; border: none; font-size: 26px; line-height: 1; color: #b3b9c4; cursor: pointer; z-index: 2; }
2471    .noi__close:hover { color: #01102E; }
2472
2473    .noi__head { padding: 28px 30px 0; }
2474    .noi__eyebrow { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .2em; color: #4aa77c; }
2475    .noi__title { margin: 8px 0 4px; font-size: 22px; font-weight: 700; letter-spacing: -.01em; color: #01102E; }
2476    .noi__sub { font-size: 13.5px; line-height: 1.6; color: #5b6880; }
2477    .noi__sub b { color: #01102E; }
2478
2479    .noi__form { padding: 18px 30px 28px; }
2480    .noi__row { display: grid; gap: 14px; grid-template-columns: 1fr 1fr; }
2481    @media (max-width: 520px) { .noi__row { grid-template-columns: 1fr; } }
2482    .noi__field { margin-bottom: 14px; }
2483    .noi__hp { position: absolute !important; left: -10000px !important; top: auto !important; width: 1px !important; height: 1px !important; overflow: hidden !important; }
2484    .noi__label { display: block; font-size: 12.5px; font-weight: 600; color: #01102E; margin-bottom: 6px; }
2485    .noi__input, .noi__textarea {
2486        width: 100%; border: 1px solid #e8eaee; border-radius: 12px; background: #fff; padding: 11px 13px;
2487        font-size: 14px; font-family: inherit; color: #01102E; transition: border-color .15s, box-shadow .15s;
2488    }
2489    .noi__input::placeholder, .noi__textarea::placeholder { color: #aab0bb; }
2490    .noi__input:focus, .noi__textarea:focus { outline: none; border-color: #74F7B2; box-shadow: 0 0 0 3px rgba(116,247,178,.25); }
2491    .noi__textarea { min-height: 96px; resize: vertical; }
2492
2493    .noi__subjects { display: flex; flex-wrap: wrap; gap: 8px; }
2494    .noi__chip { display: inline-flex; align-items: center; gap: 7px; border: 1px solid #e8eaee; border-radius: 999px; padding: 8px 14px; font-size: 13px; color: #4a5160; cursor: pointer; transition: all .15s; }
2495    .noi__chip input { accent-color: #01102E; margin: 0; }
2496    .noi__chip:has(input:checked) { border-color: #01102E; background: #01102E; color: #fff; }
2497
2498    .noi__btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; width: 100%; margin-top: 6px; background: #74F7B2; color: #01102E; border: none; border-radius: 999px; padding: 14px 24px; font-size: 14px; font-weight: 700; cursor: pointer; transition: filter .15s; }
2499    .noi__btn:hover { filter: brightness(1.05); }
2500    .noi__btn[disabled] { opacity: .85; cursor: default; }
2501    .noi__error { display: none; margin-top: 12px; font-size: 13px; color: #d23f3f; text-align: center; }
2502    .noi__error.is-show { display: block; }
2503
2504    .noi__dots { display: inline-flex; align-items: center; gap: 6px; height: 1em; }
2505    .noi__dots span { width: 7px; height: 7px; border-radius: 50%; background: #01102E; opacity: .35; animation: noiDot 1.2s infinite ease-in-out both; }
2506    .noi__dots span:nth-child(1){ animation-delay: -.24s; } .noi__dots span:nth-child(2){ animation-delay: -.12s; }
2507    @keyframes noiDot { 0%,80%,100%{ opacity:.25; transform: translateY(0); } 40%{ opacity:1; transform: translateY(-4px); } }
2508
2509    .noi__success { display: none; padding: 40px 32px; text-align: center; }
2510    .noi.is-done .noi__head, .noi.is-done .noi__form { display: none; }
2511    .noi.is-done .noi__success { display: block; }
2512    .noi__check { display: grid; place-items: center; width: 60px; height: 60px; margin: 0 auto 18px; border-radius: 50%; background: rgba(116,247,178,.18); color: #0f7a4f; }
2513    .noi__success h3 { margin: 0 0 10px; font-size: 22px; font-weight: 700; color: #01102E; }
2514    .noi__success p { margin: 0 auto; max-width: 38ch; font-size: 14.5px; line-height: 1.7; color: #5b6880; }
2515    .noi__done-btn { margin-top: 22px; background: #01102E; color: #fff; border: none; border-radius: 999px; padding: 12px 26px; font-size: 13.5px; font-weight: 600; cursor: pointer; }
2516    .noi__done-btn:hover { background: #011845; }
2517</style>
2518
2519
2520
2521<div class="noi" id="inquiryModal" role="dialog" aria-modal="true" aria-labelledby="noiTitle">
2522    <div class="noi__backdrop" data-noi-close></div>
2523    <div class="noi__card">
2524        <button type="button" class="noi__close" data-noi-close aria-label="Close">&times;</button>
2525
2526        <div class="noi__head">
2527            <div class="noi__eyebrow">Domain inquiry</div>
2528            <h2 class="noi__title" id="noiTitle">Ask about this name</h2>
2529            <p class="noi__sub">You're inquiring about <b data-noi-domain>this domain</b>. Send us a note and a real person will reply, usually within a couple of hours.</p>
2530        </div>
2531
2532        <form class="noi__form" id="inquiryForm" data-analytics-context="true" novalidate>
2533            <input type="hidden" name="_analytics[sessionToken]" data-analytics-field="sessionToken">
2534<input type="hidden" name="_analytics[pageViewToken]" data-analytics-field="pageViewToken">
2535<input type="hidden" name="_analytics[path]" data-analytics-field="path">
2536<input type="hidden" name="_analytics[previousPath]" data-analytics-field="previousPath">
2537<input type="hidden" name="_analytics[landingPath]" data-analytics-field="landingPath">
2538<input type="hidden" name="_analytics[entryReferrer]" data-analytics-field="entryReferrer">
2539
2540            <div class="noi__row">
2541                <div class="noi__field">
2542                    <label class="noi__label" for="noi-first">First name</label>
2543                    <input class="noi__input" id="noi-first" name="inquiry[firstName]" type="text" placeholder="Jane" required>
2544                </div>
2545                <div class="noi__field">
2546                    <label class="noi__label" for="noi-last">Last name</label>
2547                    <input class="noi__input" id="noi-last" name="inquiry[lastName]" type="text" placeholder="Doe" required>
2548                </div>
2549            </div>
2550            <div class="noi__row">
2551                <div class="noi__field">
2552                    <label class="noi__label" for="noi-email">Email</label>
2553                    <input class="noi__input" id="noi-email" name="inquiry[email]" type="email" placeholder="[email protected]" required>
2554                </div>
2555                <div class="noi__field">
2556                    <label class="noi__label" for="noi-phone">Phone</label>
2557                    <input class="noi__input" id="noi-phone" name="inquiry[phoneNumber]" type="tel" placeholder="+1 012 3456 789" required>
2558                </div>
2559            </div>
2560
2561            <div class="noi__field">
2562                <span class="noi__label">Subject</span>
2563                <div class="noi__subjects">
2564                    <label class="noi__chip"><input type="radio" name="inquiry[subject]" value="Domain Name" checked> Domain Name</label>
2565                    <label class="noi__chip"><input type="radio" name="inquiry[subject]" value="General Inquiry"> General Inquiry</label>
2566                    <label class="noi__chip"><input type="radio" name="inquiry[subject]" value="Logo Design"> Logo Design</label>
2567                </div>
2568            </div>
2569
2570            <div class="noi__field">
2571                <label class="noi__label" for="noi-message">Message</label>
2572                <textarea class="noi__textarea" id="noi-message" name="inquiry[content]" placeholder="Write your message..." required></textarea>
2573            </div>
2574
2575            <div class="noi__hp" aria-hidden="true">
2576                <input class="noi__input" id="noi-website" name="inquiry[website]" type="text" autocomplete="new-password" tabindex="-1" aria-hidden="true" spellcheck="false" autocapitalize="off" data-lpignore="true" data-1p-ignore="true" data-form-type="other">
2577            </div>
2578
2579            
2580            <button type="submit" class="noi__btn" id="noiSubmit">Send message</button>
2581            <div class="noi__error" id="noiError">Something went wrong. Please try again or email [email protected].</div>
2582        </form>
2583
2584        <div class="noi__success">
2585            <div class="noi__check">
2586                <svg width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M20 6 9 17l-5-5"/></svg>
2587            </div>
2588            <h3>Thanks for reaching out.</h3>
2589            <p>We've got your message about <b data-noi-domain-success>this domain</b> and a real person will get back to you shortly.</p>
2590            <button type="button" class="noi__done-btn" data-noi-close>Keep browsing</button>
2591        </div>
2592    </div>
2593</div>
2594
2595<script>
2596window.NameOfficeInquiry = (function () {
2597    var SITE_KEY = null;
2598    var ACTION_TEMPLATE = "\/name\/__DOMAIN__\/inquire";
2599    var modal, form, submitBtn, errorEl, captchaEl, domainEls, domainSuccessEls, defaultErrorMessage;
2600    var currentName = null;
2601
2602    function init() {
2603        modal = document.getElementById('inquiryModal');
2604        if (!modal) return false;
2605        form = document.getElementById('inquiryForm');
2606        submitBtn = document.getElementById('noiSubmit');
2607        errorEl = document.getElementById('noiError');
2608        defaultErrorMessage = errorEl ? errorEl.textContent : 'Something went wrong. Please try again or email [email protected].';
2609        captchaEl = document.getElementById('noi-captcha');
2610        domainEls = modal.querySelectorAll('[data-noi-domain]');
2611        domainSuccessEls = modal.querySelectorAll('[data-noi-domain-success]');
2612
2613        modal.addEventListener('click', function (e) {
2614            if (e.target.closest('[data-noi-close]')) close();
2615        });
2616        document.addEventListener('keydown', function (e) {
2617            if (e.key === 'Escape' && modal.classList.contains('is-open')) close();
2618        });
2619        form.addEventListener('submit', onSubmit);
2620        return true;
2621    }
2622
2623    function open(name, display, prefill) {
2624        if (!modal && !init()) return;
2625        currentName = name;
2626        form.action = ACTION_TEMPLATE.replace('__DOMAIN__', encodeURIComponent(name));
2627        var label = display || name;
2628        domainEls.forEach(function (el) { el.textContent = label; });
2629        domainSuccessEls.forEach(function (el) { el.textContent = label; });
2630        modal.classList.remove('is-done');
2631        errorEl.classList.remove('is-show');
2632        errorEl.textContent = defaultErrorMessage;
2633        form.reset();
2634        if (window.NameOfficeAnalytics && window.NameOfficeAnalytics.fillForm) {
2635            window.NameOfficeAnalytics.fillForm(form);
2636        }
2637        // Optional prefill, used by the offer prompt so the visitor lands on a
2638        // part-written offer rather than an empty box. Applied after reset().
2639        if (prefill && typeof prefill === 'object') {
2640            if (prefill.subject) {
2641                var subjectInput = form.querySelector('input[name="inquiry[subject]"][value="' + prefill.subject + '"]');
2642                if (subjectInput) subjectInput.checked = true;
2643            }
2644            if (prefill.message) {
2645                var messageEl = document.getElementById('noi-message');
2646                if (messageEl) messageEl.value = prefill.message;
2647            }
2648        }
2649
2650        document.body.style.overflow = 'hidden';
2651        modal.classList.add('is-open');
2652        // With a prefilled message the name fields are what still need filling.
2653        var first = document.getElementById('noi-first');
2654        if (first) setTimeout(function () { first.focus(); }, 50);
2655    }
2656
2657    function close() {
2658        if (!modal) return;
2659        modal.classList.remove('is-open');
2660        document.body.style.overflow = '';
2661    }
2662
2663    function setLoading(on) {
2664        submitBtn.disabled = on;
2665        submitBtn.innerHTML = on
2666            ? '<span class="noi__dots"><span></span><span></span><span></span></span>'
2667            : 'Send message';
2668    }
2669
2670    function showError(message) {
2671        if (!errorEl) return;
2672        errorEl.textContent = message || defaultErrorMessage;
2673        errorEl.classList.add('is-show');
2674    }
2675
2676    function getToken() {
2677        return new Promise(function (resolve) {
2678            if (!SITE_KEY || typeof grecaptcha === 'undefined' || !grecaptcha.execute) { resolve(''); return; }
2679            try {
2680                grecaptcha.ready(function () {
2681                    grecaptcha.execute(SITE_KEY, { action: 'inquiry' }).then(resolve).catch(function () { resolve(''); });
2682                });
2683            } catch (e) { resolve(''); }
2684        });
2685    }
2686
2687    function onSubmit(e) {
2688        e.preventDefault();
2689        if (submitBtn.disabled) return;
2690        if (!form.checkValidity()) { form.reportValidity(); return; }
2691        errorEl.classList.remove('is-show');
2692        setLoading(true);
2693
2694        getToken().then(function (token) {
2695            if (captchaEl) {
2696                captchaEl.value = token;
2697            }
2698            return fetch(form.action, {
2699                method: 'POST',
2700                headers: { 'X-Requested-With': 'XMLHttpRequest' },
2701                body: new FormData(form)
2702            });
2703        }).then(function (res) {
2704            return res.json().then(function (data) { return { ok: res.ok, data: data }; });
2705        }).then(function (r) {
2706            setLoading(false);
2707            if (r.ok && r.data && r.data.ok) {
2708                modal.classList.add('is-done');
2709                /* Reddit's Lead, on the server's confirmation rather than the
2710                   click, so a rejected or spam-filtered enquiry is not a lead. */
2711                if (typeof window.rdtTrack === 'function') {
2712                    window.rdtTrack('track', 'Lead');
2713                }
2714            } else {
2715                showError(r.data && Array.isArray(r.data.errors) && r.data.errors.length ? r.data.errors[0] : defaultErrorMessage);
2716            }
2717        }).catch(function () {
2718            setLoading(false);
2719            showError(defaultErrorMessage);
2720        });
2721    }
2722
2723    if (document.readyState !== 'loading') init();
2724    else document.addEventListener('DOMContentLoaded', init);
2725
2726    return { open: open, close: close };
2727})();
2728</script>
2728
2729
2730
2731    
2731<script>
2732        NameOfficeGrid.create({ apiUrl: '/favorites-api', countLabel: 'saved names', removeOnUnfavorite: true });
2733    </script>
2733
2734        
2734<script>
2735        (function () {
2736            var root = document.getElementById('favorites-share-tools');
2737            if (!root) return;
2738
2739            var panel = document.getElementById('favorites-share-panel');
2740            var toggleBtn = document.getElementById('favorites-share-toggle');
2741            var toggleIcon = document.getElementById('favorites-share-toggle-icon');
2742            var createBtn = document.getElementById('favorites-share-create');
2743            var result = document.getElementById('favorites-share-result');
2744            var input = document.getElementById('favorites-share-url');
2745            var copyBtn = document.getElementById('favorites-share-copy');
2746            var nativeBtn = document.getElementById('favorites-share-native');
2747            var openBtn = document.getElementById('favorites-share-open');
2748            var status = document.getElementById('favorites-share-status');
2749            var createUrl = root.getAttribute('data-create-url') || '';
2750            var shareUrlTemplate = root.getAttribute('data-share-url-template') || '';
2751            var placeholderToken = root.getAttribute('data-share-token-placeholder') || '';
2752            var currentToken = '';
2753            var isExpanded = root.getAttribute('data-initial-expanded') === '1';
2754
2755            function renderExpandedState() {
2756                if (!panel || !toggleBtn || !toggleIcon) return;
2757                panel.classList.toggle('hidden', !isExpanded);
2758                toggleBtn.setAttribute('aria-expanded', isExpanded ? 'true' : 'false');
2759                toggleIcon.innerHTML = isExpanded
2760                    ? '<svg width="12" height="12" viewBox="0 0 20 20" fill="none"><path d="M5 12.5 10 7.5l5 5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'
2761                    : '<svg width="12" height="12" viewBox="0 0 20 20" fill="none"><path d="M5 7.5 10 12.5l5-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
2762            }
2763
2764            function analyticsPayload() {
2765                try {
2766                    if (window.NameOfficeAnalytics && typeof window.NameOfficeAnalytics.getContext === 'function') {
2767                        return window.NameOfficeAnalytics.getContext();
2768                    }
2769                } catch (e) {}
2770                return {};
2771            }
2772
2773            function setStatus(message, tone) {
2774                if (!status) return;
2775                status.textContent = message;
2776                status.className = 'mt-3 text-sm ' + (tone === 'success'
2777                    ? 'text-emerald-700'
2778                    : tone === 'error'
2779                        ? 'text-red-600'
2780                        : 'text-gray-500');
2781            }
2782
2783            function applyShareLink(url, token) {
2784                currentToken = token || '';
2785                if (input) input.value = url || '';
2786                if (openBtn) openBtn.href = url || '#';
2787                if (result) result.classList.remove('hidden');
2788                isExpanded = true;
2789                renderExpandedState();
2790            }
2791
2792            async function postShareAction() {
2793                if (!currentToken || !shareUrlTemplate || !placeholderToken || !window.fetch) return;
2794
2795                try {
2796                    await fetch(shareUrlTemplate.replace(placeholderToken, currentToken), {
2797                        method: 'POST',
2798                        headers: { 'Content-Type': 'application/json' },
2799                        body: JSON.stringify(analyticsPayload()),
2800                        keepalive: true
2801                    });
2802                } catch (e) {}
2803            }
2804
2805            async function copyCurrentLink() {
2806                if (!input || !input.value) return false;
2807
2808                try {
2809                    if (navigator.clipboard && navigator.clipboard.writeText) {
2810                        await navigator.clipboard.writeText(input.value);
2811                    } else {
2812                        input.focus();
2813                        input.select();
2814                        input.setSelectionRange(0, input.value.length);
2815                        document.execCommand('copy');
2816                    }
2817                    return true;
2818                } catch (e) {
2819                    try {
2820                        input.focus();
2821                        input.select();
2822                        input.setSelectionRange(0, input.value.length);
2823                    } catch (selectionError) {}
2824                    return false;
2825                }
2826            }
2827
2828            if (!navigator.share && nativeBtn) {
2829                nativeBtn.classList.add('hidden');
2830            }
2831
2832            renderExpandedState();
2833
2834            if (toggleBtn) {
2835                toggleBtn.addEventListener('click', function () {
2836                    isExpanded = !isExpanded;
2837                    renderExpandedState();
2838                });
2839            }
2840
2841            if (createBtn) {
2842                createBtn.addEventListener('click', async function () {
2843                    if (!createUrl || !window.fetch) return;
2844
2845                    createBtn.disabled = true;
2846                    createBtn.classList.add('opacity-60', 'cursor-not-allowed');
2847                    setStatus('Creating your private favorites link…', 'neutral');
2848
2849                    try {
2850                        var response = await fetch(createUrl, {
2851                            method: 'POST',
2852                            headers: { 'Content-Type': 'application/json' },
2853                            body: JSON.stringify(analyticsPayload())
2854                        });
2855                        var data = await response.json();
2856                        if (!response.ok || !data.shareUrl || !data.token) {
2857                            throw new Error(data.error || 'Could not create a shareable link.');
2858                        }
2859
2860                        applyShareLink(data.shareUrl, data.token);
2861                        setStatus('Share link ready. Copy it or send it directly from here.', 'success');
2862                    } catch (error) {
2863                        setStatus(error && error.message ? error.message : 'Could not create the share link right now. Please try again.', 'error');
2864                    } finally {
2865                        createBtn.disabled = false;
2866                        createBtn.classList.remove('opacity-60', 'cursor-not-allowed');
2867                    }
2868                });
2869            }
2870
2871            if (copyBtn) {
2872                copyBtn.addEventListener('click', async function () {
2873                    var copied = await copyCurrentLink();
2874                    if (copied) {
2875                        setStatus('Link copied. Anyone with it can open this exact shortlist.', 'success');
2876                    } else {
2877                        setStatus('The link is selected. Copy it manually from the field above.', 'neutral');
2878                    }
2879                    postShareAction();
2880                });
2881            }
2882
2883            if (nativeBtn) {
2884                nativeBtn.addEventListener('click', async function () {
2885                    if (!navigator.share || !input || !input.value) return;
2886
2887                    try {
2888                        await navigator.share({
2889                            title: 'NameOffice saved names',
2890                            text: 'Premium domain shortlist from NameOffice',
2891                            url: input.value
2892                        });
2893                        setStatus('Share sheet opened for this shortlist link.', 'success');
2894                        postShareAction();
2895                    } catch (error) {}
2896                });
2897            }
2898        })();
2899    </script>
2899
2900        <div id="page-loader" class="page-loader" aria-hidden="true">
2901    <img class="page-loader__symbol" src="/brand/nameoffice-symbol.png" alt="" width="56" height="56">
2902</div>
2903<style>
2904    .page-loader {
2905        position: fixed;
2906        inset: 0;
2907        z-index: 99999;
2908        display: flex;
2909        align-items: center;
2910        justify-content: center;
2911        background: rgba(0, 0, 0, 0.5);
2912        opacity: 0;
2913        visibility: hidden;
2914        pointer-events: none;
2915        transition: opacity .18s ease, visibility .18s ease;
2916    }
2917    .page-loader.is-active { opacity: 1; visibility: visible; pointer-events: auto; }
2918    .page-loader__symbol {
2919        width: 56px;
2920        height: 56px;
2921        animation: page-loader-spin .9s linear infinite;
2922    }
2923    @keyframes page-loader-spin { to { transform: rotate(360deg); } }
2924    @media (prefers-reduced-motion: reduce) {
2925        .page-loader__symbol { animation-duration: 2.4s; }
2926    }
2927</style>
2928<script>
2929(function () {
2930    var loader = document.getElementById('page-loader');
2931    if (!loader) return;
2932    var safetyTimer = null;
2933
2934    function show() {
2935        loader.classList.add('is-active');
2936        window.clearTimeout(safetyTimer);
2937        // Failsafe: if navigation never happens (JS-handled action), hide it.
2938        safetyTimer = window.setTimeout(hide, 12000);
2939    }
2940    function hide() {
2941        loader.classList.remove('is-active');
2942        window.clearTimeout(safetyTimer);
2943    }
2944
2945    // Bubble phase so anything that calls preventDefault (modals, carousels,
2946    // drag handlers) marks the event as handled before we see it.
2947    document.addEventListener('click', function (e) {
2948        if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
2949        var a = e.target.closest('a');
2950        if (!a) return;
2951        var href = a.getAttribute('href');
2952        if (!href || href.charAt(0) === '#') return;
2953        if (a.target === '_blank' || a.hasAttribute('download')) return;
2954        var schemeMatch = href.match(/^([a-z][a-z0-9+.-]*):/i);
2955        if (schemeMatch && !/^https?$/i.test(schemeMatch[1])) return;
2956        if (a.host && a.host !== window.location.host) return; // external link
2957        show();
2958    });
2959
2960    document.addEventListener('submit', function (e) {
2961        if (e.defaultPrevented) return;
2962        var form = e.target;
2963        if (form && form.hasAttribute && form.hasAttribute('data-no-loader')) return; // form shows its own progress
2964        show();
2965    });
2966
2967    // Page restored from back/forward cache: make sure the loader is cleared.
2968    window.addEventListener('pageshow', function (e) { if (e.persisted) hide(); });
2969})();
2970</script>
2970
2971    
2971<script>
2972(function () {
2973    if (window.NameOfficeAnalytics && window.NameOfficeAnalytics.__initialized) return;
2974    if (!('sendBeacon' in navigator) && !('fetch' in window)) return;
2975
2976    var SESSION_TIMEOUT_MS = 30 * 60 * 1000;
2977    var LS_PREFIX = 'nameoffice.analytics.';
2978    var SS_LAST_PATH = 'nameoffice.analytics.last_path';
2979
2980    function uuid() {
2981        if (window.crypto && crypto.randomUUID) return crypto.randomUUID();
2982        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
2983            var r = (Math.random() * 16) | 0, v = c === 'x' ? r : (r & 0x3) | 0x8;
2984            return v.toString(16);
2985        });
2986    }
2987
2988    function read(storage, key) {
2989        try { return storage.getItem(key) || ''; } catch (e) { return ''; }
2990    }
2991
2992    function write(storage, key, value) {
2993        try { storage.setItem(key, value); } catch (e) {}
2994    }
2995
2996    function sameHost(a, b) {
2997        return String(a || '').replace(/^www\./i, '').toLowerCase() === String(b || '').replace(/^www\./i, '').toLowerCase();
2998    }
2999
3000    function currentPath() {
3001        return window.location.pathname + window.location.search;
3002    }
3003
3004    function externalReferrer(url) {
3005        if (!url) return '';
3006        try {
3007            var parsed = new URL(url, window.location.origin);
3008            if (!/^https?:$/i.test(parsed.protocol)) return '';
3009            if (sameHost(parsed.host, window.location.host)) return '';
3010            return parsed.href;
3011        } catch (e) {
3012            return '';
3013        }
3014    }
3015
3016    function ensureSession(pathNow) {
3017        var token = read(window.localStorage, LS_PREFIX + 'session_token');
3018        var lastSeen = parseInt(read(window.localStorage, LS_PREFIX + 'last_seen_at') || '0', 10) || 0;
3019        var isFresh = token && (Date.now() - lastSeen) < SESSION_TIMEOUT_MS;
3020        var created = false;
3021
3022        if (!isFresh) {
3023            token = uuid();
3024            created = true;
3025            write(window.localStorage, LS_PREFIX + 'session_token', token);
3026            write(window.localStorage, LS_PREFIX + 'started_at', String(Date.now()));
3027            write(window.localStorage, LS_PREFIX + 'landing_path', pathNow);
3028            write(window.localStorage, LS_PREFIX + 'entry_referrer', externalReferrer(document.referrer));
3029        } else {
3030            if (!read(window.localStorage, LS_PREFIX + 'landing_path')) {
3031                write(window.localStorage, LS_PREFIX + 'landing_path', pathNow);
3032            }
3033        }
3034
3035        write(window.localStorage, LS_PREFIX + 'last_seen_at', String(Date.now()));
3036
3037        return {
3038            created: created,
3039            sessionToken: token,
3040            landingPath: read(window.localStorage, LS_PREFIX + 'landing_path') || pathNow,
3041            entryReferrer: read(window.localStorage, LS_PREFIX + 'entry_referrer') || ''
3042        };
3043    }
3044
3045    var path = currentPath();
3046    var session = ensureSession(path);
3047    var previousPath = session.created ? '' : read(window.sessionStorage, SS_LAST_PATH);
3048    if (previousPath === path) previousPath = '';
3049    write(window.sessionStorage, SS_LAST_PATH, path);
3050
3051    var token = uuid();
3052    var viewUrl = "\/api\/track\/view";
3053    var pingUrl = "\/api\/track\/ping";
3054
3055    var active = 0;          // accumulated active seconds
3056    var lastSent = -1;       // last duration value we pushed
3057
3058    function send(url, body) {
3059        var json = JSON.stringify(body);
3060        try {
3061            if (navigator.sendBeacon) {
3062                navigator.sendBeacon(url, new Blob([json], { type: 'application/json' }));
3063                return;
3064            }
3065        } catch (e) { /* fall through to fetch */ }
3066        if (window.fetch) {
3067            fetch(url, { method: 'POST', body: json, keepalive: true, headers: { 'Content-Type': 'application/json' } });
3068        }
3069    }
3070
3071    function context() {
3072        write(window.localStorage, LS_PREFIX + 'last_seen_at', String(Date.now()));
3073        return {
3074            token: token,
3075            pageViewToken: token,
3076            sessionToken: session.sessionToken || null,
3077            path: path,
3078            previousPath: previousPath || null,
3079            landingPath: read(window.localStorage, LS_PREFIX + 'landing_path') || path,
3080            entryReferrer: read(window.localStorage, LS_PREFIX + 'entry_referrer') || ''
3081        };
3082    }
3083
3084    function fillForm(form) {
3085        if (!form) return;
3086        var data = context();
3087        form.querySelectorAll('[data-analytics-field]').forEach(function (input) {
3088            var field = input.getAttribute('data-analytics-field');
3089            if (!field) return;
3090            input.value = data[field] || '';
3091        });
3092    }
3093
3094    function bindForms(root) {
3095        (root || document).querySelectorAll('form[data-analytics-context]').forEach(function (form) {
3096            if (form.dataset.analyticsBound === '1') return;
3097            form.dataset.analyticsBound = '1';
3098            fillForm(form);
3099            form.addEventListener('submit', function () {
3100                fillForm(form);
3101            });
3102        });
3103    }
3104
3105    function trackDomainInteraction(domainId, type, action) {
3106        /* Reddit's AddToCart. Reported here rather than at each button because
3107           every path into the cart comes through this function, so a new one
3108           gets the event without anybody remembering to add it. rdtTrack queues
3109           until the pixel is up, and drops the event if consent never comes. */
3110        if (type === 'cart' && (action || 'add') === 'add' && typeof window.rdtTrack === 'function') {
3111            window.rdtTrack('track', 'AddToCart', {
3112                itemCount: 1,
3113                products: [{ id: String(domainId) }]
3114            });
3115        }
3116
3117        if (!window.fetch) return Promise.resolve(null);
3118        var body = context();
3119        body.type = type;
3120        body.action = action || 'add';
3121        return fetch('/api/domain/' + domainId + '/interact', {
3122            method: 'POST',
3123            keepalive: true,
3124            headers: { 'Content-Type': 'application/json' },
3125            body: JSON.stringify(body)
3126        }).then(function (response) {
3127            return response.ok ? response.json() : null;
3128        }).catch(function () {
3129            return null;
3130        });
3131    }
3132
3133    window.NameOfficeAnalytics = {
3134        __initialized: true,
3135        getContext: context,
3136        fillForm: fillForm,
3137        bindForms: bindForms,
3138        trackDomainInteraction: trackDomainInteraction
3139    };
3140
3141    // Register the view as soon as possible.
3142    send(viewUrl, context());
3143
3144    // Count a second of attention only while the tab is actually visible.
3145    window.setInterval(function () {
3146        if (document.visibilityState === 'visible') active += 1;
3147    }, 1000);
3148
3149    function flush() {
3150        if (active === lastSent) return;
3151        lastSent = active;
3152        send(pingUrl, { token: token, seconds: active });
3153    }
3154
3155    // Send time-on-page only when the visitor leaves or hides the tab. No
3156    // periodic polling, so each page view costs just two small requests (the
3157    // initial view + one duration report) instead of one every few seconds.
3158    document.addEventListener('visibilitychange', function () {
3159        if (document.visibilityState === 'hidden') flush();
3160    });
3161    window.addEventListener('pagehide', flush);
3162
3163    if (document.readyState !== 'loading') bindForms(document);
3164    else document.addEventListener('DOMContentLoaded', function () { bindForms(document); });
3165})();
3166</script>
3166
3167    <div id="no-sold-toast" class="no-sold-toast" role="status" aria-live="polite">
3168    <div class="no-sold-toast__logo" data-toast-logo aria-hidden="true"></div>
3169    <div class="no-sold-toast__body">
3170        <div class="no-sold-toast__msg" data-toast-msg></div>
3171        <div class="no-sold-toast__sub"><span class="no-sold-toast__dot"></span>Verified sale on NameOffice</div>
3172    </div>
3173    <button type="button" class="no-sold-toast__close" data-toast-close aria-label="Dismiss notification">&times;</button>
3174</div>
3175<style>
3176.no-sold-toast{position:fixed;left:20px;bottom:20px;z-index:9990;display:flex;align-items:center;gap:13px;width:352px;max-width:calc(100vw - 40px);padding:12px 42px 12px 14px;background:#fff;border:1px solid rgba(1,16,46,.08);border-radius:14px;box-shadow:0 14px 38px rgba(1,16,46,.20);font-family:'Inter',system-ui,-apple-system,sans-serif;transform:translateY(150%);opacity:0;transition:transform .5s cubic-bezier(.16,1,.3,1),opacity .4s ease;pointer-events:none;}
3177.no-sold-toast.is-visible{transform:translateY(0);opacity:1;pointer-events:auto;}
3178.no-sold-toast__logo{flex:none;display:flex;align-items:center;justify-content:center;min-width:54px;}
3179.no-sold-toast__logo img{height:54px;width:auto;max-width:112px;object-fit:contain;display:block;}
3180.no-sold-toast__logo.is-mono{width:54px;height:54px;border-radius:12px;background:#01102E;color:#74F7B2;font-weight:700;font-size:22px;line-height:1;}
3181.no-sold-toast__body{min-width:0;}
3182.no-sold-toast__msg{font-size:14px;color:#101828;line-height:1.35;}
3183.no-sold-toast__msg strong{font-weight:600;}
3184.no-sold-toast__sub{margin-top:3px;font-size:11px;color:#15803d;font-weight:600;display:flex;align-items:center;gap:5px;}
3185.no-sold-toast__dot{width:7px;height:7px;border-radius:50%;background:#22c55e;box-shadow:0 0 0 0 rgba(34,197,94,.6);animation:noSoldPulse 2s infinite;}
3186@keyframes noSoldPulse{0%{box-shadow:0 0 0 0 rgba(34,197,94,.55)}70%{box-shadow:0 0 0 7px rgba(34,197,94,0)}100%{box-shadow:0 0 0 0 rgba(34,197,94,0)}}
3187.no-sold-toast__close{position:absolute;top:8px;right:8px;width:24px;height:24px;border:none;background:rgba(1,16,46,.05);border-radius:50%;color:#98a2b3;font-size:19px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0;transition:background .15s,color .15s;}
3188.no-sold-toast__close:hover{background:rgba(1,16,46,.11);color:#101828;}
3189@media (max-width:480px){.no-sold-toast{left:12px;right:12px;width:auto;bottom:12px;}}
3190</style>
3191<script>
3192(function () {
3193    var el = document.getElementById('no-sold-toast');
3194    if (!el) return;
3195
3196    var DATA_URL = '/recent-sales.json';
3197    var DISMISS_URL = '/recent-sales/dismiss';
3198    var SECOND_AFTER_MS = 5 * 60 * 1000;   // second toast only if the visit passes 5 min
3199    var MAX_PER_SESSION = 2;
3200
3201    // Pop sound. Browsers block audio before any user gesture, so we prime it on
3202    // the first interaction; playSound() is a silent no-op if still blocked.
3203    var SOUND_URL = '/sounds/ui_click.wav';
3204    var sound = null;
3205    try { sound = new Audio(SOUND_URL); sound.preload = 'auto'; sound.volume = 0.45; } catch (e) {}
3206    function primeSound(){
3207        if (!sound) return;
3208        try {
3209            sound.muted = true;
3210            var p = sound.play();
3211            if (p && p.then) { p.then(function(){ sound.pause(); sound.currentTime = 0; sound.muted = false; }).catch(function(){ sound.muted = false; }); }
3212        } catch (e) { sound.muted = false; }
3213    }
3214    ['pointerdown','keydown','touchstart'].forEach(function(ev){ document.addEventListener(ev, primeSound, { once: true, passive: true }); });
3215    function playSound(){ if (!sound) return; try { sound.currentTime = 0; var p = sound.play(); if (p && p.catch) p.catch(function(){}); } catch (e) {} }
3216
3217    var SEEN_KEY = 'no_sold_seen';          // localStorage: names already shown (across visits)
3218    var SS_START = 'no_sold_start';         // sessionStorage: visit start timestamp
3219    var SS_SHOWN = 'no_sold_shown';         // sessionStorage: how many shown this visit
3220    var SS_FIRST = 'no_sold_first_at';      // sessionStorage: scheduled time for the first toast
3221    var SS_DONE = 'no_sold_done';           // sessionStorage: nothing left to show this visit
3222
3223    function lsArr(k){ try { return JSON.parse(localStorage.getItem(k)) || []; } catch (e) { return []; } }
3224    function lsSet(k,v){ try { localStorage.setItem(k, JSON.stringify(v)); } catch (e) {} }
3225    function ss(k){ try { return sessionStorage.getItem(k); } catch (e) { return null; } }
3226    function ssSet(k,v){ try { sessionStorage.setItem(k, v); } catch (e) {} }
3227    function looksInvalidSale(s){
3228        if (!s || !s.name || !s.logo) return true;
3229        var name = String(s.name).toLowerCase();
3230        var formatted = String(s.formattedName || '').toLowerCase();
3231        return name.indexOf('.old') !== -1 || formatted.indexOf('.old') !== -1;
3232    }
3233    function markSeen(name){
3234        if (!name) return;
3235        var seen = lsArr(SEEN_KEY);
3236        if (seen.indexOf(name) !== -1) return;
3237        seen.push(name);
3238        if (seen.length > 100) seen = seen.slice(seen.length - 100);
3239        lsSet(SEEN_KEY, seen);
3240    }
3241
3242    var now = Date.now();
3243    var start = parseInt(ss(SS_START) || '0', 10);
3244    if (!start) { start = now; ssSet(SS_START, String(start)); }
3245    var firstAt = parseInt(ss(SS_FIRST) || '0', 10);
3246    if (!firstAt) { firstAt = start + 4000 + Math.floor(Math.random() * 5000); ssSet(SS_FIRST, String(firstAt)); } // 4-9s
3247
3248    var logoEl = el.querySelector('[data-toast-logo]');
3249    var msgEl = el.querySelector('[data-toast-msg]');
3250    var closeBtn = el.querySelector('[data-toast-close]');
3251    var sales = null;      // fetched once per page
3252    var timer = null;
3253    var currentName = null;
3254
3255    function shownCount(){ return parseInt(ss(SS_SHOWN) || '0', 10); }
3256
3257    function mono(sale){ return String(sale.formattedName || sale.name || '?').charAt(0).toUpperCase(); }
3258
3259    function fetchSales(cb){
3260        if (sales){ cb(sales); return; }
3261        fetch(DATA_URL, { credentials: 'same-origin' })
3262            .then(function(r){ return r.json(); })
3263            .then(function(d){
3264                sales = ((d && d.sales) || []).filter(function(s){ return !looksInvalidSale(s); });
3265                cb(sales);
3266            })
3267            .catch(function(){ cb([]); });
3268    }
3269
3270    // Newest first, not random. The server already returns these ordered by
3271    // sold_at DESC, so taking the first unseen one means a visitor's first
3272    // toast is the most recent sale — picking at random surfaced a sale from
3273    // weeks ago while a fresh one sat unused, which reads as stale.
3274    function pick(list){
3275        var seen = lsArr(SEEN_KEY);
3276        var avail = list.filter(function(s){
3277            return !looksInvalidSale(s) && seen.indexOf(s.name) === -1;
3278        });
3279        return avail.length ? avail[0] : null;
3280    }
3281
3282    function show(sale){
3283        if (looksInvalidSale(sale)) return;
3284        currentName = sale.name;
3285        logoEl.innerHTML = '';
3286        logoEl.classList.remove('is-mono');
3287        var img = document.createElement('img');
3288        img.src = sale.logo; img.alt = '';
3289        img.onerror = function(){
3290            markSeen(sale.name);
3291            currentName = null;
3292            attempt();
3293        };
3294        logoEl.appendChild(img);
3295        msgEl.innerHTML = '<strong></strong> just sold!';
3296        msgEl.querySelector('strong').textContent = sale.formattedName || sale.name;
3297        el.classList.add('is-visible');
3298        playSound();
3299
3300        markSeen(sale.name);
3301        ssSet(SS_SHOWN, String(shownCount() + 1));
3302        schedule();
3303    }
3304
3305    function attempt(){
3306        fetchSales(function(list){
3307            var sale = pick(list);
3308            if (sale) { show(sale); }
3309            else { ssSet(SS_DONE, '1'); } // seen them all — stop for this visit
3310        });
3311    }
3312
3313    function schedule(){
3314        if (timer){ clearTimeout(timer); timer = null; }
3315        if (ss(SS_DONE) === '1') return;
3316        var count = shownCount();
3317        if (count >
3317= MAX_PER_SESSION) return;
3318        var target = count === 0 ? firstAt : (start + SECOND_AFTER_MS);
3319        timer = setTimeout(attempt, Math.max(500, target - Date.now()));
3320    }
3321
3322    closeBtn.addEventListener('click', function(){
3323        el.classList.remove('is-visible');
3324        if (currentName){
3325            try {
3326                var body = 'name=' + encodeURIComponent(currentName);
3327                if (navigator.sendBeacon){
3328                    navigator.sendBeacon(DISMISS_URL, new Blob([body], { type: 'application/x-www-form-urlencoded' }));
3329                } else {
3330                    fetch(DISMISS_URL, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: body, keepalive: true });
3331                }
3332            } catch (e) {}
3333        }
3334        currentName = null;
3335    });
3336
3337    schedule();
3338})();
3339</script>
3339
3340</body>
3341</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.