function initDashboard() {
    function commaFormat(n) {
        return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    }

    function escapeHtml(text) {
        if (text == null) return '';
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    // State
    let infiniteScrollState = null;
    let isLoadingMore = false;
    let searchQuery = '';
    let domainFilter = 'all';  // all, pass, skip, hold, dead
    // Feed filter: multi-select with ALL as exclusion toggle
    // When allSelected=true, selected items are EXCLUDED; when false, selected items are INCLUDED
    let feedFilter = { allSelected: false, statuses: [], types: [] };
    let currentOpenTLD = null;  // Track which TLD is currently open

    // Smart sticky header - scroll normally, show fixed on scroll up
    let lastScrollY = 0;
    const topSection = document.getElementById('topSection');
    const spacer = document.getElementById('topSectionSpacer');
    let headerHeight = topSection.offsetHeight;
    let isFixed = false;

    window.addEventListener('scroll', () => {
        const currentScrollY = window.scrollY;

        // If at top, return to normal flow
        if (currentScrollY <= 0) {
            topSection.classList.remove('fixed', 'hidden');
            spacer.classList.remove('active');
            isFixed = false;
            lastScrollY = currentScrollY;
            return;
        }

        // Only activate fixed mode after scrolling past the header
        if (currentScrollY > headerHeight) {
            if (currentScrollY < lastScrollY) {
                // Scrolling up - show fixed header
                if (!isFixed) {
                    spacer.style.height = headerHeight + 'px';
                    spacer.classList.add('active');
                    topSection.classList.add('fixed');
                    // Start hidden, then show
                    topSection.classList.add('hidden');
                    requestAnimationFrame(() => {
                        topSection.classList.remove('hidden');
                    });
                    isFixed = true;
                } else {
                    topSection.classList.remove('hidden');
                }
            } else if (currentScrollY > lastScrollY && isFixed) {
                // Scrolling down while fixed - hide it
                topSection.classList.add('hidden');
            }
        }

        lastScrollY = currentScrollY;
    }, { passive: true });

    // Stat card click handler
    document.addEventListener('click', (e) => {
        const card = e.target.closest('.card.clickable');
        if (!card) return;

        const filterType = card.dataset.filter;
        const status = card.dataset.status;
        const type = card.dataset.type;

        if (filterType === 'domain') {
            // Remove active from domain cards only
            document.querySelectorAll('.card.clickable[data-filter="domain"]').forEach(c => c.classList.remove('active'));
            card.classList.add('active');
            domainFilter = status || 'all';

            // Update placeholder
            const searchInput = document.getElementById('searchInput');
            searchInput.placeholder = domainFilter === 'all' ? 'Search domains...' : `Showing ${domainFilter} domains...`;

            // Reload TLD list with new filter
            loadFeeds(searchQuery);
        } else if (filterType === 'feed') {
            const wasActive = card.classList.contains('active');

            if (status === 'all') {
                // ALL card toggles exclusion mode
                if (wasActive) {
                    card.classList.remove('active');
                    feedFilter.allSelected = false;
                } else {
                    card.classList.add('active');
                    feedFilter.allSelected = true;
                }
            } else if (status) {
                // Status card (pass, skip, hold, dead) - multi-select
                if (wasActive) {
                    card.classList.remove('active');
                    feedFilter.statuses = feedFilter.statuses.filter(s => s !== status);
                } else {
                    card.classList.add('active');
                    feedFilter.statuses.push(status);
                }
            } else if (type) {
                // Type card (rss, atom, json, unknown, empty) - multi-select
                if (wasActive) {
                    card.classList.remove('active');
                    feedFilter.types = feedFilter.types.filter(t => t !== type);
                } else {
                    card.classList.add('active');
                    feedFilter.types.push(type);
                }
            }

            // Reload TLD list with feed filter
            loadFeeds(searchQuery);
        }
    });

    // Refresh only expanded TLD sections with new domain filter
    function refreshExpandedTLDs() {
        const expandedContainer = document.getElementById('expandedTLDContent');
        if (expandedContainer && expandedContainer.style.display !== 'none' && expandedContainer.dataset.tld) {
            // Mark as needing reload and reload
            expandedContainer.dataset.loaded = 'false';
            loadTLDDomains(expandedContainer, searchQuery);
        }
    }

    // Apply feed filter to currently visible feeds
    function applyFeedFilter() {
        document.querySelectorAll('.inline-feed-block').forEach(block => {
            const feedStatus = block.dataset.status || 'hold';
            const feedType = block.dataset.type || 'unknown';

            let show = true;
            if (feedFilter.status !== 'all' && feedStatus !== feedFilter.status) {
                show = false;
            }
            if (feedFilter.type && feedType !== feedFilter.type) {
                show = false;
            }

            block.style.display = show ? 'block' : 'none';
        });
    }

    // Event delegation for domain-spacer clicks (toggle feeds)
    document.addEventListener('click', (e) => {
        const spacer = e.target.closest('.domain-spacer');
        if (spacer) {
            const block = spacer.closest('.domain-block');
            if (block) {
                const feedsDiv = block.querySelector('.domain-feeds');
                if (feedsDiv) {
                    const isVisible = feedsDiv.style.display !== 'none';
                    feedsDiv.style.display = isVisible ? 'none' : 'block';
                    if (!isVisible) {
                        feedsDiv.querySelectorAll('.inline-feed-block').forEach(feedBlock => {
                            const itemsDiv = feedBlock.querySelector('.feed-items');
                            if (itemsDiv && !itemsDiv.dataset.loaded) {
                                itemsDiv.dataset.loaded = 'true';
                                loadFeedItems(feedBlock.dataset.url, itemsDiv);
                            }
                        });
                    }
                }
            }
        }
    });

    // Event delegation for feed-url-toggle clicks (toggle feed info)
    document.addEventListener('click', (e) => {
        const urlToggle = e.target.closest('.feed-url-toggle');
        if (urlToggle) {
            const feedBlock = urlToggle.closest('.inline-feed-block');
            if (feedBlock) {
                const infoDiv = feedBlock.querySelector('.feed-info');
                if (infoDiv) {
                    const isVisible = infoDiv.style.display !== 'none';
                    infoDiv.style.display = isVisible ? 'none' : 'block';
                    if (!isVisible && !infoDiv.dataset.loaded) {
                        infoDiv.dataset.loaded = 'true';
                        loadFeedInfo(feedBlock.dataset.url, infoDiv);
                    }
                }
            }
        }
    });

    // Event delegation for feed-title-toggle and feed-filler-toggle clicks (toggle items)
    document.addEventListener('click', (e) => {
        const titleToggle = e.target.closest('.feed-title-toggle');
        const fillerToggle = e.target.closest('.feed-filler-toggle');
        if (titleToggle || fillerToggle) {
            const feedBlock = (titleToggle || fillerToggle).closest('.inline-feed-block');
            if (feedBlock) {
                const itemsDiv = feedBlock.querySelector('.feed-items');
                if (itemsDiv) {
                    const isVisible = itemsDiv.style.display !== 'none';
                    itemsDiv.style.display = isVisible ? 'none' : 'block';
                }
            }
        }
    });

    // Load feed info
    async function loadFeedInfo(feedUrl, infoDiv) {
        infoDiv.innerHTML = '<span style="color: #666;">Loading...</span>';
        try {
            const resp = await fetch(`/api/feedInfo?url=${encodeURIComponent(feedUrl)}`);
            if (!resp.ok) throw new Error('Failed to load');
            const f = await resp.json();

            let html = '<div style="display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; color: #888;">';
            const fields = [
                ['URL', f.url],
                ['Title', f.title],
                ['Description', f.description],
                ['Type', f.type],
                ['Language', f.language],
                ['Site URL', f.siteUrl],
                ['Status', f.status],
                ['Last Error', f.lastError],
                ['Item Count', f.itemCount],
                ['Oldest Item', f.oldestItemDate],
                ['Newest Item', f.newestItemDate],
                ['Discovered', f.discoveredAt],
                ['Last Checked', f.lastCheckedAt],
                ['Next Check', f.nextCheckAt],
                ['Publish Status', f.publishStatus],
                ['Publish Account', f.publishAccount],
            ];
            fields.forEach(([label, value]) => {
                if (value != null && value !== '' && value !== 0) {
                    html += `<span style="color: #666;">${escapeHtml(label)}:</span><span style="color: #fff;">${escapeHtml(String(value))}</span>`;
                }
            });
            html += '</div>';
            infoDiv.innerHTML = html;
        } catch (err) {
            infoDiv.innerHTML = `<span style="color: #f66;">Error: ${escapeHtml(err.message)}</span>`;
        }
    }

    // Load feed items
    async function loadFeedItems(feedUrl, itemsDiv) {
        itemsDiv.innerHTML = '<span style="color: #666;">Loading...</span>';
        try {
            const resp = await fetch(`/api/feedItems?url=${encodeURIComponent(feedUrl)}&limit=50`);
            if (!resp.ok) throw new Error('Failed to load');
            const items = await resp.json();

            if (!items || items.length === 0) {
                // Just clear the items area, keep the feed visible
                itemsDiv.innerHTML = '';
                return;
            }

            let html = '';
            items.forEach(item => {
                const date = item.pub_date ? new Date(item.pub_date).toLocaleDateString() : '';
                html += `<div style="padding: 2px 0; border-bottom: 1px solid #1a1a1a; overflow: hidden;">`;
                html += `<div style="float: left; width: 6em; white-space: nowrap; margin-right: 6px; color: #666; text-align: right;">${escapeHtml(date)}&nbsp;</div>`;
                if (item.link) {
                    html += `<a href="${escapeHtml(item.link)}" target="_blank" style="color: #0af; text-decoration: none;">${escapeHtml(item.title || item.link)}</a>`;
                } else {
                    html += `<span style="color: #fff;">${escapeHtml(item.title || '(no title)')}</span>`;
                }
                html += '</div>';
            });
            itemsDiv.innerHTML = html;
        } catch (err) {
            itemsDiv.innerHTML = `<span style="color: #f66;">Error: ${escapeHtml(err.message)}</span>`;
        }
    }

    // Status colors
    const statusConfig = {
        hold: { color: '#f90', bg: '#330', border: '#550' },
        skip: { color: '#f66', bg: '#400', border: '#600' },
        pass: { color: '#0f0', bg: '#040', border: '#060' }
    };

    // Render status buttons
    function renderStatusBtns(currentStatus, type, id) {
        const order = ['pass', 'hold', 'skip'];
        let html = '<div class="status-btn-group" style="display: inline-flex; margin-right: 10px;">';
        order.forEach((s, i) => {
            const cfg = statusConfig[s];
            const isActive = s === currentStatus;
            const bg = isActive ? cfg.bg : '#1a1a1a';
            const border = isActive ? cfg.border : '#333';
            const color = isActive ? cfg.color : '#ccc';
            html += `<button class="status-btn" data-type="${type}" data-id="${escapeHtml(id)}" data-status="${s}"
                style="padding: 2px 6px; background: ${bg}; border: 1px solid ${border}; border-radius: 3px;
                color: ${color}; cursor: pointer; margin-left: ${i > 0 ? '1px' : '0'};">${s}</button>`;
        });
        html += '</div>';
        return html;
    }

    // Render TLD section header
    function renderTLDHeader(tld) {
        return `<div class="tld-section" data-tld="${escapeHtml(tld)}">
            <div class="tld-header" style="display: flex; align-items: center; padding: 10px; background: #1a1a1a; border-bottom: 1px solid #333; cursor: pointer; user-select: none;">
                <span style="color: #0af; font-weight: bold; font-size: 1.1em;">.${escapeHtml(tld)}</span>
            </div>
            <div class="tld-content" style="display: block;">`;
    }

    function renderTLDFooter(tld) {
        return `<div class="tld-footer" style="display: flex; align-items: center; justify-content: flex-start; padding: 6px 10px; background: #1a1a1a; border-top: 1px solid #333; cursor: pointer; user-select: none;">
                <span style="color: #666; font-size: 0.9em;">▲ .${escapeHtml(tld)}</span>
            </div>`;
    }

    function closeTLDSection(container, tld) {
        const tldContent = container.querySelector(`.tld-section[data-tld="${tld}"] .tld-content`);
        if (tldContent) {
            tldContent.insertAdjacentHTML('beforeend', renderTLDFooter(tld));
        }
    }

    // Event delegation for TLD clicks (toggle section)
    document.addEventListener('click', (e) => {
        const tldHeader = e.target.closest('.tld-header');
        const tldFooter = e.target.closest('.tld-footer');
        const expandedContainer = document.getElementById('expandedTLDContent');

        // Handle clicks in expanded container header
        if (tldHeader && tldHeader.closest('#expandedTLDContent')) {
            // Close the expanded content
            const currentSection = document.querySelector('.tld-section.expanded');
            if (currentSection) {
                currentSection.classList.remove('expanded');
            }
            expandedContainer.style.display = 'none';
            expandedContainer.innerHTML = '';
            currentOpenTLD = null;
            // Show TLD list again
            const domainList = document.querySelector('.domain-list');
            if (domainList) domainList.style.display = '';
            updateStats(); // Revert to search or all stats
            return;
        }

        // Handle clicks on TLD cards
        if (tldHeader || tldFooter) {
            const section = (tldHeader || tldFooter).closest('.tld-section');
            if (section) {
                const tld = section.dataset.tld;
                const isExpanded = section.classList.contains('expanded');

                if (isExpanded) {
                    // Closing this TLD
                    section.classList.remove('expanded');
                    expandedContainer.style.display = 'none';
                    expandedContainer.innerHTML = '';
                    currentOpenTLD = null;
                    // Show TLD list again
                    const domainList = document.querySelector('.domain-list');
                    if (domainList) domainList.style.display = '';
                    updateStats(); // Revert to search or all stats
                } else {
                    // Close any other open TLD first
                    document.querySelectorAll('.tld-section.expanded').forEach(s => {
                        s.classList.remove('expanded');
                    });

                    // Opening this TLD
                    section.classList.add('expanded');
                    currentOpenTLD = tld;
                    // Hide TLD list
                    const domainList = document.querySelector('.domain-list');
                    if (domainList) domainList.style.display = 'none';
                    // Show TLD stats (filtered by search if active)
                    const currentSearch = document.getElementById('searchInput').value.trim();
                    updateStatsForTLD(tld, currentSearch);

                    // Set up expanded container with header
                    expandedContainer.innerHTML = `
                        <div class="tld-header">
                            <span class="tld-name">.${escapeHtml(tld)}</span>
                        </div>
                        <div class="tld-content">
                            <div class="tld-loading" style="padding: 10px; color: #666;">Loading...</div>
                        </div>
                    `;
                    expandedContainer.style.display = 'block';
                    expandedContainer.dataset.tld = tld;
                    expandedContainer.dataset.loaded = 'false';

                    // Load domains
                    loadTLDDomains(expandedContainer, searchQuery);

                    // Scroll to expanded container
                    expandedContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
                }
            }
        }
    });

    // Update stats for a specific TLD (optionally filtered by search)
    async function updateStatsForTLD(tld, search = '') {
        try {
            let url = `/api/tldStats?tld=${encodeURIComponent(tld)}`;
            if (search) {
                url += `&search=${encodeURIComponent(search)}`;
            }
            const resp = await fetch(url);
            if (!resp.ok) return;
            const stats = await resp.json();

            document.getElementById('totalDomains').textContent = commaFormat(stats.total_domains || 0);
            document.getElementById('passDomains').textContent = commaFormat(stats.pass_domains || 0);
            document.getElementById('skipDomains').textContent = commaFormat(stats.skip_domains || 0);
            document.getElementById('holdDomains').textContent = commaFormat(stats.hold_domains || 0);
            document.getElementById('deadDomains').textContent = commaFormat(stats.dead_domains || 0);

            document.getElementById('totalFeeds').textContent = commaFormat(stats.total_feeds || 0);
            document.getElementById('aliveFeeds').textContent = commaFormat(stats.alive_feeds || 0);
            document.getElementById('publishFeeds').textContent = commaFormat(stats.publish_feeds || 0);
            document.getElementById('skipFeeds').textContent = commaFormat(stats.skip_feeds || 0);
            document.getElementById('holdFeeds').textContent = commaFormat(stats.hold_feeds || 0);
            document.getElementById('deadFeeds').textContent = commaFormat(stats.dead_feeds || 0);
            document.getElementById('emptyFeeds').textContent = commaFormat(stats.empty_feeds || 0);
            document.getElementById('rssFeeds').textContent = commaFormat(stats.rss_feeds || 0);
            document.getElementById('atomFeeds').textContent = commaFormat(stats.atom_feeds || 0);
            document.getElementById('jsonFeeds').textContent = commaFormat(stats.json_feeds || 0);
            document.getElementById('unknownFeeds').textContent = commaFormat(stats.unknown_feeds || 0);

            document.getElementById('updatedAt').textContent = search ? `Search "${search}" in .${tld}` : `Stats for .${tld}`;
        } catch (err) {
            console.error('TLD stats update failed:', err);
        }
    }

    // Update stats for search results
    async function updateStatsForSearch(query) {
        try {
            const resp = await fetch(`/api/searchStats?search=${encodeURIComponent(query)}`);
            if (!resp.ok) {
                console.error('Search stats failed:', resp.status);
                return;
            }
            const stats = await resp.json();

            document.getElementById('totalDomains').textContent = commaFormat(stats.total_domains || 0);
            document.getElementById('passDomains').textContent = commaFormat(stats.pass_domains || 0);
            document.getElementById('skipDomains').textContent = commaFormat(stats.skip_domains || 0);
            document.getElementById('holdDomains').textContent = commaFormat(stats.hold_domains || 0);
            document.getElementById('deadDomains').textContent = commaFormat(stats.dead_domains || 0);

            document.getElementById('totalFeeds').textContent = commaFormat(stats.total_feeds || 0);
            document.getElementById('aliveFeeds').textContent = commaFormat(stats.alive_feeds || 0);
            document.getElementById('publishFeeds').textContent = commaFormat(stats.publish_feeds || 0);
            document.getElementById('skipFeeds').textContent = commaFormat(stats.skip_feeds || 0);
            document.getElementById('holdFeeds').textContent = commaFormat(stats.hold_feeds || 0);
            document.getElementById('deadFeeds').textContent = commaFormat(stats.dead_feeds || 0);
            document.getElementById('emptyFeeds').textContent = commaFormat(stats.empty_feeds || 0);
            document.getElementById('rssFeeds').textContent = commaFormat(stats.rss_feeds || 0);
            document.getElementById('atomFeeds').textContent = commaFormat(stats.atom_feeds || 0);
            document.getElementById('jsonFeeds').textContent = commaFormat(stats.json_feeds || 0);
            document.getElementById('unknownFeeds').textContent = commaFormat(stats.unknown_feeds || 0);

            document.getElementById('updatedAt').textContent = `Search: "${query}"`;
        } catch (err) {
            console.error('Search stats update failed:', err);
        }
    }

    // Render domain row with feeds
    function renderDomainRow(d) {
        const status = d.status || 'hold';

        const fullDomain = d.tld ? d.host + '.' + d.tld : d.host;
        let html = `<div class="domain-block" data-host="${escapeHtml(fullDomain)}" data-status="${status}">`;
        html += `<div class="domain-row" style="display: flex; align-items: center; padding: 8px 10px; border-bottom: 1px solid #202020;">`;
        html += renderStatusBtns(status, 'domain', fullDomain);
        html += `<a class="domain-name" href="https://${escapeHtml(fullDomain)}" target="_blank" style="color: #0af; text-decoration: none;">${escapeHtml(fullDomain)}</a>`;

        if (d.last_error) {
            html += `<span class="domain-spacer" style="color: #f66; margin-left: 10px; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer;" title="${escapeHtml(d.last_error)}">${escapeHtml(d.last_error)}</span>`;
        } else {
            html += '<span class="domain-spacer" style="flex: 1; cursor: pointer;">&nbsp;</span>';
        }
        html += '</div>';

        // Feeds (shown by default in this view)
        if (d.feeds && d.feeds.length > 0) {
            html += '<div class="domain-feeds" style="display: block; margin-left: 10px; border-left: 2px solid #333; padding-left: 6px;">';
            d.feeds.forEach(f => {
                const feedStatus = f.publish_status || 'hold';
                const feedType = f.type || 'unknown';
                html += `<div class="inline-feed-block" data-url="${escapeHtml(f.url)}" data-status="${feedStatus}" data-type="${feedType}">`;
                html += `<div class="feed-row" style="display: flex; align-items: center; padding: 4px 0;">`;

                html += `<span style="width: 48px; flex-shrink: 0; white-space: nowrap; margin-right: 6px; color: #666; text-align: center;">${escapeHtml(f.language || '')}&nbsp;</span>`;
                html += renderStatusBtns(feedStatus, 'feed', f.url);

                if (f.item_count > 0) {
                    html += `<span style="color: #888; width: 55px; margin-right: 6px; text-align: center;">${commaFormat(f.item_count)}</span>`;
                } else {
                    html += `<span style="width: 55px; margin-right: 6px;"></span>`;
                }

                let feedPath = f.url;
                try {
                    const urlObj = new URL(f.url.startsWith('http') ? f.url : 'https://' + f.url);
                    feedPath = urlObj.pathname + urlObj.search;
                } catch (e) {}
                html += `<span class="feed-url-toggle" style="color: #0af; margin-right: 8px; white-space: nowrap; cursor: pointer;" title="Click to show feed info">${escapeHtml(feedPath)}</span>`;

                if (f.title) {
                    html += `<span class="feed-title-toggle" style="color: #fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer;">${escapeHtml(f.title)}</span>`;
                }
                html += '<span class="feed-filler-toggle" style="flex: 1; cursor: pointer;">&nbsp;</span>';
                html += '</div>';
                html += '<div class="feed-info" style="display: none; padding: 6px 10px; margin-left: 10px; border-left: 2px solid #444; background: #0a0a0a;"></div>';
                html += '<div class="feed-items" style="display: block; padding: 4px 10px; margin-left: 10px; border-left: 2px solid #333;"></div>';
                html += '</div>';
            });
            html += '<div style="height: 8px;"></div>';
            html += '</div>';
        }
        html += '</div>';
        return html;
    }

    // Attach status button handlers
    function attachStatusHandlers(container) {
        container.querySelectorAll('.status-btn:not(.btn-handled)').forEach(btn => {
            btn.classList.add('btn-handled');
            btn.addEventListener('click', async (e) => {
                e.stopPropagation();
                const type = btn.dataset.type;
                const id = btn.dataset.id;
                const newStatus = btn.dataset.status;

                const endpoint = type === 'domain' ? '/api/setDomainStatus' : '/api/setPublishStatus';
                const param = type === 'domain' ? 'host' : 'url';

                try {
                    const resp = await fetch(`${endpoint}?${param}=${encodeURIComponent(id)}&status=${newStatus}`);
                    if (resp.ok) {
                        const group = btn.closest('.status-btn-group');
                        group.querySelectorAll('.status-btn').forEach(b => {
                            const s = b.dataset.status;
                            const cfg = statusConfig[s];
                            const isActive = s === newStatus;
                            b.style.background = isActive ? cfg.bg : '#111';
                            b.style.borderColor = isActive ? cfg.border : '#333';
                            b.style.color = isActive ? cfg.color : '#444';
                        });
                        const block = btn.closest(type === 'domain' ? '.domain-block' : '.inline-feed-block');
                        if (block) block.dataset.status = newStatus;
                    }
                } catch (err) {
                    console.error('Status update failed:', err);
                }
            });
        });
    }

    // Infinite scroll
    function setupInfiniteScroll(loadMoreFn) {
        infiniteScrollState = { loadMore: loadMoreFn, ended: false };
    }

    function clearInfiniteScroll() {
        infiniteScrollState = null;
    }

    async function checkInfiniteScroll() {
        if (!infiniteScrollState || infiniteScrollState.ended || isLoadingMore) return;
        const scrollY = window.scrollY + window.innerHeight;
        const docHeight = document.documentElement.scrollHeight;
        if (scrollY > docHeight - 500) {
            isLoadingMore = true;
            await infiniteScrollState.loadMore();
            isLoadingMore = false;
        }
    }

    window.addEventListener('scroll', checkInfiniteScroll);

    // Load and display feeds with lazy-loading TLD sections
    let tldObserver = null;

    async function loadFeeds(query = '') {
        const output = document.getElementById('output');
        output.innerHTML = '<div class="domain-list"></div><div id="expandedTLDContent" style="display: none;"></div><div id="infiniteLoader" style="text-align: center; padding: 10px; color: #666;">Loading TLDs...</div>';

        // Disconnect previous observer if any
        if (tldObserver) {
            tldObserver.disconnect();
        }

        try {
            // Fetch TLDs with optional domain status filter, feed filter, and search
            let tldsUrl = '/api/tlds';
            const params = [];
            if (domainFilter !== 'all') {
                params.push(`status=${domainFilter}`);
            }
            // Add feed filter params if any are selected
            if (feedFilter.allSelected || feedFilter.statuses.length > 0 || feedFilter.types.length > 0) {
                if (feedFilter.allSelected) {
                    params.push('feedMode=exclude');
                } else {
                    params.push('feedMode=include');
                }
                if (feedFilter.statuses.length > 0) {
                    params.push(`feedStatuses=${feedFilter.statuses.join(',')}`);
                }
                if (feedFilter.types.length > 0) {
                    params.push(`feedTypes=${feedFilter.types.join(',')}`);
                }
            }
            if (query) {
                params.push(`search=${encodeURIComponent(query)}`);
            }
            if (params.length > 0) {
                tldsUrl += '?' + params.join('&');
            }
            const tldsResp = await fetch(tldsUrl);
            if (!tldsResp.ok) {
                const errText = await tldsResp.text();
                throw new Error(`HTTP ${tldsResp.status}: ${errText}`);
            }
            const tlds = await tldsResp.json();

            if (!tlds || tlds.length === 0) {
                // Update stats for empty results
                if (query) {
                    await updateStatsForSearch(query);
                } else {
                    await updateStats();
                }
                document.getElementById('infiniteLoader').textContent = query ? 'No matches found' : 'No feeds found';
                return;
            }

            const container = output.querySelector('.domain-list');

            // Render all TLD sections as card placeholders
            tlds.forEach(t => {
                const tld = t.tld || 'unknown';
                container.insertAdjacentHTML('beforeend', `
                    <div class="tld-section" data-tld="${escapeHtml(tld)}" data-loaded="false">
                        <div class="tld-header">
                            <span class="tld-name">.${escapeHtml(tld)}</span>
                        </div>
                        <div class="tld-content" style="display: none;">
                            <div class="tld-loading" style="padding: 10px; color: #666;">Loading...</div>
                        </div>
                    </div>
                `);
            });

            document.getElementById('infiniteLoader').textContent = '';

            // Auto-expand if single TLD match, otherwise update stats for search/all
            if (tlds.length === 1) {
                const tld = tlds[0].tld;
                const expandedContainer = document.getElementById('expandedTLDContent');
                const section = output.querySelector('.tld-section');

                if (section && expandedContainer) {
                    // Mark as expanded
                    section.classList.add('expanded');
                    currentOpenTLD = tld;
                    // Hide TLD list
                    const domainList = document.querySelector('.domain-list');
                    if (domainList) domainList.style.display = 'none';

                    // Set up expanded container
                    expandedContainer.innerHTML = `
                        <div class="tld-header">
                            <span class="tld-name">.${escapeHtml(tld)}</span>
                        </div>
                        <div class="tld-content">
                            <div class="tld-loading" style="padding: 10px; color: #666;">Loading...</div>
                        </div>
                    `;
                    expandedContainer.style.display = 'block';
                    expandedContainer.dataset.tld = tld;
                    expandedContainer.dataset.loaded = 'false';

                    // Load domains
                    loadTLDDomains(expandedContainer, query);

                    // Show TLD stats (filtered by search if active)
                    await updateStatsForTLD(tld, query);
                }
            } else {
                // Multiple TLDs - show search or global stats
                if (query) {
                    await updateStatsForSearch(query);
                } else {
                    await updateStats();
                }
            }

        } catch (err) {
            document.getElementById('infiniteLoader').textContent = 'Error: ' + err.message;
        }
    }

    // Load domains for a specific TLD section
    async function loadTLDDomains(section, query = '') {
        const tld = section.dataset.tld;
        section.dataset.loaded = 'loading';

        try {
            let url = `/api/domains?tld=${encodeURIComponent(tld)}&limit=500`;
            if (domainFilter !== 'all') {
                url += `&status=${domainFilter}`;
            }
            if (query) {
                url += `&search=${encodeURIComponent(query)}`;
            }
            // Apply feed filter if any feed cards are selected
            if (feedFilter.allSelected || feedFilter.statuses.length > 0 || feedFilter.types.length > 0) {
                if (feedFilter.allSelected) {
                    url += '&feedMode=exclude';
                } else {
                    url += '&feedMode=include';
                }
                if (feedFilter.statuses.length > 0) {
                    url += `&feedStatuses=${feedFilter.statuses.join(',')}`;
                }
                if (feedFilter.types.length > 0) {
                    url += `&feedTypes=${feedFilter.types.join(',')}`;
                }
            }

            const resp = await fetch(url);
            if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
            const domains = await resp.json();

            const content = section.querySelector('.tld-content');
            content.innerHTML = '';

            if (!domains || domains.length === 0) {
                content.innerHTML = '<div style="padding: 10px; color: #666;">No domains with feeds</div>';
            } else {
                domains.forEach(d => {
                    content.insertAdjacentHTML('beforeend', renderDomainRow(d));
                });
                // Add footer
                content.insertAdjacentHTML('beforeend', renderTLDFooter(tld));
                attachStatusHandlers(content);

                // Load items for all feeds
                content.querySelectorAll('.inline-feed-block').forEach(feedBlock => {
                    const itemsDiv = feedBlock.querySelector('.feed-items');
                    if (itemsDiv && !itemsDiv.dataset.loaded) {
                        itemsDiv.dataset.loaded = 'true';
                        loadFeedItems(feedBlock.dataset.url, itemsDiv);
                    }
                });
            }

            section.dataset.loaded = 'true';
        } catch (err) {
            const content = section.querySelector('.tld-content');
            content.innerHTML = `<div style="padding: 10px; color: #f66;">Error: ${escapeHtml(err.message)}</div>`;
            section.dataset.loaded = 'false';
        }
    }

    // Search handler
    const searchInput = document.getElementById('searchInput');
    function doSearch() {
        searchQuery = searchInput.value.trim();
        loadFeeds(searchQuery);
    }

    // Search on button click
    document.getElementById('searchBtn').addEventListener('click', doSearch);

    // Clear button - clears search and resets all filters
    document.getElementById('clearBtn').addEventListener('click', () => {
        searchInput.value = '';
        searchQuery = '';
        // Reset filters to default
        domainFilter = 'all';
        feedFilter = { allSelected: false, statuses: [], types: [] };
        // Reset active card styling
        document.querySelectorAll('.card.clickable.active').forEach(c => c.classList.remove('active'));
        document.querySelector('.card.clickable[data-filter="domain"][data-status="all"]')?.classList.add('active');
        searchInput.placeholder = 'Search domains...';
        // Close any expanded TLD
        currentOpenTLD = null;
        const expandedContainer = document.getElementById('expandedTLDContent');
        if (expandedContainer) {
            expandedContainer.style.display = 'none';
            expandedContainer.innerHTML = '';
        }
        // Show TLD list if hidden
        const domainList = document.querySelector('.domain-list');
        if (domainList) domainList.style.display = '';
        // Reload and update stats
        loadFeeds();
    });

    // Search on Enter key
    searchInput.addEventListener('keydown', (e) => {
        if (e.key === 'Enter') {
            e.preventDefault();
            doSearch();
        }
    });

    // Initial load - set default active cards and load
    document.querySelector('.card.clickable[data-filter="domain"][data-status="all"]')?.classList.add('active');
    loadFeeds();

    // Update stats periodically
    async function updateStats() {
        // Check actual input value for current search state
        const currentSearch = document.getElementById('searchInput')?.value.trim() || '';

        // Priority: open TLD > search query > all
        if (currentOpenTLD) {
            updateStatsForTLD(currentOpenTLD, currentSearch);
            return;
        }
        if (currentSearch) {
            updateStatsForSearch(currentSearch);
            return;
        }

        try {
            const resp = await fetch('/api/stats');
            if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
            const stats = await resp.json();
            document.getElementById('totalDomains').textContent = commaFormat(stats.total_domains);
            document.getElementById('holdDomains').textContent = commaFormat(stats.hold_domains);
            document.getElementById('passDomains').textContent = commaFormat(stats.pass_domains);
            document.getElementById('skipDomains').textContent = commaFormat(stats.skip_domains);
            document.getElementById('deadDomains').textContent = commaFormat(stats.dead_domains);
            document.getElementById('domainCheckRate').textContent = commaFormat(stats.domain_check_rate);
            document.getElementById('feedCrawlRate').textContent = commaFormat(stats.feed_crawl_rate);
            document.getElementById('feedCheckRate').textContent = commaFormat(stats.feed_check_rate);
            document.getElementById('totalFeeds').textContent = commaFormat(stats.total_feeds);
            document.getElementById('aliveFeeds').textContent = commaFormat(stats.alive_feeds);
            document.getElementById('publishFeeds').textContent = commaFormat(stats.publish_feeds);
            document.getElementById('skipFeeds').textContent = commaFormat(stats.skip_feeds);
            document.getElementById('holdFeeds').textContent = commaFormat(stats.hold_feeds);
            document.getElementById('deadFeeds').textContent = commaFormat(stats.dead_feeds);
            document.getElementById('emptyFeeds').textContent = commaFormat(stats.empty_feeds);
            document.getElementById('rssFeeds').textContent = commaFormat(stats.rss_feeds);
            document.getElementById('atomFeeds').textContent = commaFormat(stats.atom_feeds);
            document.getElementById('jsonFeeds').textContent = commaFormat(stats.json_feeds);
            document.getElementById('unknownFeeds').textContent = commaFormat(stats.unknown_feeds);
            document.getElementById('updatedAt').textContent = 'All TLDs - ' + new Date().toLocaleTimeString();
        } catch (err) {
            console.error('Stats update failed:', err);
        }
    }

    setInterval(updateStats, 60000);
}

document.addEventListener('DOMContentLoaded', initDashboard);
