Center Claude AI Prompt Header

Centers the Claude AI prompt header

// ==UserScript==
// @name         Center Claude AI Prompt Header
// @description  Centers the Claude AI prompt header
// @author       NWP
// @namespace    https://greasyfork.org/users/877912
// @version      0.1
// @license      MIT
// @match        https://claude.ai/chat*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const DEBUG_MODE = false;

    function logDebug(message, ...args) {
        if (DEBUG_MODE) {
            console.log('Claude AI Centering:', message, ...args);
        }
    }

    logDebug('Starting Claude AI prompt header centering script');

    const DEBOUNCE_DELAY = 250;
    const POLLING_INTERVAL = 5000;
    const MUTATION_DEBOUNCE_DELAY = 100;

    let styleApplyTimeout;
    let mutationTimeout;
    let urlCheckTimeout;
    let currentUrl = window.location.href;
    let isProcessing = false;

    function debouncedApplyStyles(delay = DEBOUNCE_DELAY) {
        if (styleApplyTimeout) {
            clearTimeout(styleApplyTimeout);
        }

        styleApplyTimeout = setTimeout(() => {
            if (!isProcessing) {
                applyCenteringStyles();
            }
        }, delay);
    }

    function debouncedMutationHandler() {
        if (mutationTimeout) {
            clearTimeout(mutationTimeout);
        }

        mutationTimeout = setTimeout(() => {
            logDebug('Prompt header mutation detected (debounced), reapplying styles');
            debouncedApplyStyles(MUTATION_DEBOUNCE_DELAY);
        }, MUTATION_DEBOUNCE_DELAY);
    }

    function debouncedUrlChangeHandler() {
        if (urlCheckTimeout) {
            clearTimeout(urlCheckTimeout);
        }

        urlCheckTimeout = setTimeout(() => {
            if (window.location.href !== currentUrl) {
                currentUrl = window.location.href;
                logDebug('URL changed to:', currentUrl);
                debouncedApplyStyles(500);
            }
        }, 100);
    }

    function injectCenteringCSS() {
        const styleId = 'claude-ai-center-style';
        if (document.getElementById(styleId)) {
            logDebug('CSS already injected');
            return;
        }

        const style = document.createElement('style');
        style.id = styleId;
        style.innerHTML = `
            header > div.flex.w-full.items-center {
                justify-content: center !important;
            }

            header div.flex.min-w-0.flex-1 {
                justify-content: center !important;
                margin: 0 auto !important;
            }

            header div[class*="flex"] {
                justify-content: center !important;
            }

            header > div:first-child {
                justify-content: center !important;
            }
        `;

        document.head.appendChild(style);
        logDebug('Injected centering CSS');
    }

    function applyCenteringStyles() {
        if (isProcessing) {
            logDebug('Already processing, skipping...');
            return;
        }

        isProcessing = true;
        logDebug('Applying centering styles');

        try {
            const headerContent = document.querySelector('header > div.flex.w-full.items-center');
            if (headerContent) {
                headerContent.style.setProperty('justify-content', 'center', 'important');
                logDebug('Applied styles to prompt header content');
            }

            const flexContainers = document.querySelectorAll('header div.flex.min-w-0.flex-1');
            flexContainers.forEach(container => {
                container.style.setProperty('justify-content', 'center', 'important');
                container.style.setProperty('margin', '0 auto', 'important');
            });

            if (flexContainers.length > 0) {
                logDebug(`Applied styles to ${flexContainers.length} flex containers`);
            }

            const allHeaderFlexDivs = document.querySelectorAll('header div[class*="flex"]');
            allHeaderFlexDivs.forEach(div => {
                div.style.setProperty('justify-content', 'center', 'important');
            });

            const headerFirstChild = document.querySelector('header > div:first-child');
            if (headerFirstChild) {
                headerFirstChild.style.setProperty('justify-content', 'center', 'important');
                logDebug('Applied styles to prompt header first child');
            }

            logDebug('Finished applying centering styles');
        } catch (error) {
            logDebug('Error applying styles:', error);
        } finally {
            isProcessing = false;
        }
    }

    injectCenteringCSS();

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => {
            logDebug('DOM loaded, applying styles');
            debouncedApplyStyles(100);
        });
    } else {
        logDebug('DOM already loaded, applying styles immediately');
        debouncedApplyStyles(100);
    }

    const observer = new MutationObserver((mutations) => {
        debouncedUrlChangeHandler();

        const headerModified = mutations.some(mutation =>
            mutation.target.tagName === 'HEADER' ||
            mutation.target.closest('header') ||
            Array.from(mutation.addedNodes).some(node =>
                node.tagName === 'HEADER' ||
                (node.querySelector && node.querySelector('header'))
            )
        );

        if (headerModified) {
            debouncedMutationHandler();
        }
    });

    const startObserver = () => {
        if (document.body) {
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
            logDebug('Started mutation observer');
        } else {
            setTimeout(startObserver, 100);
        }
    };

    startObserver();

    const intervalId = setInterval(() => {
        debouncedUrlChangeHandler();
        if (!isProcessing && !styleApplyTimeout) {
            debouncedApplyStyles(0);
        }
    }, POLLING_INTERVAL);

    window.claudeHeaderCenteringCleanup = () => {
        if (styleApplyTimeout) clearTimeout(styleApplyTimeout);
        if (mutationTimeout) clearTimeout(mutationTimeout);
        if (urlCheckTimeout) clearTimeout(urlCheckTimeout);
        if (intervalId) clearInterval(intervalId);
        observer.disconnect();
        logDebug('Cleaned up Claude AI prompt header centering script');
    };

    setTimeout(() => {
        logDebug('Fallback timeout triggered');
        debouncedApplyStyles(0);
    }, 1000);

})();