Google Zen Color & Logo

Replace Google logo with custom logo, apply grayscale to service logos, supports dark mode

// ==UserScript==
// @name         Google Zen Color & Logo
// @namespace    http://tampermonkey.net/
// @version      0.8
// @description  Replace Google logo with custom logo, apply grayscale to service logos, supports dark mode
// @author       djshigel
// @license      MIT
// @match        https://www.google.com/*
// @match        https://www.google.com/webhp*
// @match        https://www.google.com/search*
// @match        https://google.com/*
// @match        https://myaccount.google.com/*
// @match        https://maps.google.com/*
// @match        https://news.google.com/*
// @match        https://mail.google.com/*
// @match        https://meet.google.com/*
// @match        https://chat.google.com/*
// @match        https://contacts.google.com/*
// @match        https://drive.google.com/*
// @match        https://calendar.google.com/*
// @match        https://play.google.com/*
// @match        https://translate.google.com/*
// @match        https://photos.google.com/*
// @match        https://www.google.com/shopping*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // ===================== Configuration =====================
    const CONFIG = {
        // Control replacement when Doodle is displayed
        REPLACE_ON_DOODLE: false, // true: always replace, false: keep Doodle
        
        // Logo Base64 data (500x150px) - paste actual data here
        LOGO_BASE64: 'data:image/png;base64,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',
        
        // Check interval for logo replacement (milliseconds)
        CHECK_INTERVAL: 500,
        
        // Throttle for MutationObserver callbacks
        MUTATION_THROTTLE: 100
    };

    // ===================== State Management =====================
    const state = {
        lastMutationTime: 0,
        intervalId: null,
        fastIntervalId: null,
        forceReplaceCount: 0,
        maxForceReplace: 15,
        pageLoadTime: Date.now(),
        stylesInjected: false
    };

    // ===================== Utility Functions =====================
    
    // Check if dark mode is enabled
    function isDarkMode() {
        return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
    }

    // Get filter for dark mode (invert brightness)
    function getDarkModeFilter() {
        return isDarkMode() ? 'invert(1)' : 'none';
    }

    // Check if Doodle is present
    function hasDoodle() {
        const pictureElement = document.querySelector('picture');
        if (pictureElement) {
            const img = pictureElement.querySelector('img#hplogo');
            if (img && img.src && !img.src.startsWith('data:')) return true;
        }
        
        const logoLink = document.querySelector('a#logo > img');
        if (logoLink && logoLink.src && !logoLink.src.includes('googlelogo') && !logoLink.src.startsWith('data:')) {
            return true;
        }
        
        return false;
    }
    
    // Normalize tagName for comparison (always uppercase)
    function normalizeTagName(element) {
        return element.tagName ? element.tagName.toUpperCase() : '';
    }

    // Create cropped logo container for icon use
    function createCroppedLogoContainer(size) {
        const container = document.createElement('div');
        container.className = 'custom-logo-cropped';
        container.style.width = size + 'px';
        container.style.height = size + 'px';
        container.style.overflow = 'hidden';
        container.style.position = 'relative';
        container.style.display = 'inline-block';
        container.style.verticalAlign = 'middle';
        
        const img = document.createElement('img');
        img.src = CONFIG.LOGO_BASE64;
        img.style.position = 'absolute';
        img.style.left = '0';
        img.style.top = '0';
        img.style.width = Math.round(500 * (size / 120)) + 'px';
        img.style.height = Math.round(150 * (size / 120)) + 'px';
        img.style.filter = getDarkModeFilter();
        img.style.imageRendering = 'auto';
        
        container.appendChild(img);
        return container;
    }

    // ===================== Style Injection =====================
    
    // Inject CSS styles for service logos
    function injectServiceStyles() {
        if (state.stylesInjected) return;
        
        const styleElement = document.createElement('style');
        styleElement.id = 'google-zen-styles';
        styleElement.textContent = `
            /* Google logo when scrolling */
            div.minidiv #hplogo {
                width: 120px !important;
                margin-top: -6px;
            }
            
            div.minidiv #logo {
                top: -6px;
                right: 7px;
            }
            
            div.minidiv > div:not(:has(div)) {
                background: ${isDarkMode() ? 'rgb(31, 31, 31) !important' : ''};
            }
            
            div.minidiv >[role="navigation"] {
                background: ${isDarkMode() ? '#202124 !important' : ''};
            }
            
            /* AI mode logo replacement*/
            [data-xid="aim-zero-state"] div:has(div > [role="heading"]) > div > div:not(:has([role="heading"])) {
                display: none;
            }
            
            [data-xid="aim-zero-state"] div:has(div > [role="heading"]) > div > div:has([role="heading"])::before {
                content: url(${CONFIG.LOGO_BASE64}) !important;
                zoom: 0.544;
                background-size: contain;
                filter: ${getDarkModeFilter()} !important;
                margin-bottom: 47px;
                transition: opacity 1s ease-in-out !important;
            }
            
            body > header > header > div > a > div > img {
                opacity: 0;
                transition: opacity 1s ease-in-out !important;
            }
            
            body:has([data-xid="aim-mars-turn-root"] [data-processed="true"]) header > header > div > a > div > img {
                opacity: 1 !important;
            }
            
            body > header > header > div > a > div > img:hover {
                transition: opacity .2s ease-in-out !important;
                opacity: 1 !important;
            }
            
            /* Mobile */
            
            #gb-main img#hplogo {
                width: 163px !important;
            }
            
            header > div > a[aria-label="Google"] > svg {
                display: none;
            }
            
            header > div > a[aria-label="Google"]::before {
                content: url(${CONFIG.LOGO_BASE64}) !important;
                filter: ${getDarkModeFilter()} !important;
                zoom: 0.2;
            }
            
            /* Common Bento menu iframe grayscale */
            iframe[src*="ogs.google.com"] {
                filter: grayscale(100%)contrast(150%) !important;
            }
            
            /* Hide Chrome recommendations */
            body > c-wiz:has(a[href^="https://www.google.com/url?q=https://www.google.com/chrome/"]) {
                display: none !important;
            }
            
            /* Footer opacity control on homepage */
            div[role="contentinfo"], #fbar {
                opacity: 0 !important;
                transition: opacity .2s ease-in-out !important;
            }
            
            div[role="contentinfo"]:hover, #fbar:hover {
                opacity: 1 !important;
            }
            
            /* Pattern 1 - Services with span[role="presentation"] */
            #gb > div > div > div > div > a:has(span[role="presentation"]) > span:not([role="presentation"]) {
                font-family: serif !important;
                font-weight: bold !important;
            }
            
            #gb > div > div > div > div > a > span[role="presentation"] {
                background-image: url(${CONFIG.LOGO_BASE64}) !important;
                background-size: contain !important;
                background-repeat: no-repeat !important;
                background-position: center !important;
                filter: ${getDarkModeFilter()} !important;
            }
            
            #gb > div > div > div > div > a > span[role="presentation"]::before {
                content: "" !important;
                background-image: none !important;
            }
            
            /* Pattern 2 - Services with img[role="presentation"] */
            #gb > div > div > div > div > a:has(img[role="presentation"]) > span:not([role="presentation"]), 
            #gb > div > div > div > div > span:has(img[role="presentation"]) > span:not([role="presentation"]) {
                font-family: serif !important;
                font-weight: bold !important;
            }
            
            #gb > div > div > div > div > a > img[role="presentation"], 
            #gb > div > div > div > div > span > img[role="presentation"] {
                filter: grayscale(100%)contrast(150%) !important;
                width: 40px !important;;
                object-fit: cover;
                object-position: left;
            }
            
            /* Google Maps specific */
            #settings > div > div > ul > div > div > img {
                content: url(${CONFIG.LOGO_BASE64}) !important;
                filter: ${getDarkModeFilter()} !important;
            }
            
            /* Google Play specific */
            body > c-wiz > header > nav > a {
                filter: grayscale(100%)contrast(150%) !important;
            }
            
            body > c-wiz > header > nav > a > span:not([role="presentation"]) {
                font-family: serif !important;
                font-weight: bold !important;
            }
            
            /* Google Photos specific */
            body > div > div > c-wiz > c-wiz > div > div > div > div > div > div > a > span:not([title="Google"]) {
                font-family: serif !important;
                font-weight: bold !important;
            }
            
            body > div > div > c-wiz > c-wiz > div > div > div > div > div > div > a > span[title="Google"] {
                background-image: url(${CONFIG.LOGO_BASE64}) !important;
                background-size: contain !important;
                background-repeat: no-repeat !important;
                background-position: center !important;
                filter: ${getDarkModeFilter()} !important;
            }
            
            body > div > div > c-wiz > c-wiz > div > div > div > div > div > div > a > span[title="Google"]::before {
                content: "" !important;
                background-image: none !important;
            }
            
            /* Google Shopping specific */
            body > div > div > div > img {
                filter: grayscale(100%)contrast(150%) !important;
            }
        `;
        
        if (document.head) {
            document.head.appendChild(styleElement);
            state.stylesInjected = true;
            console.log('[Google Zen] Styles injected');
        } else {
            // Wait for head element
            setTimeout(injectServiceStyles, 100);
        }
    }

    // ===================== Logo Replacement Functions =====================
    
    // Replace main page logo
    function replaceMainPageLogo() {
        // Multiple selectors for main page logo - svg[aria-label="Google"]を優先
        const selectors = [
            'svg[aria-label="Google"]',
            'img#hplogo',
            'picture > img#hplogo', 
            'picture > svg#hplogo',
            'div[data-hveid] img[alt="Google"]',
            'img[alt="Google"][height="92"]'
        ];
        
        let hplogo = null;
        for (const selector of selectors) {
            hplogo = document.querySelector(selector);
            if (hplogo) break;
        }
        
        if (!hplogo) return false;
        
        const tagName = normalizeTagName(hplogo);
        
        // Check if already replaced
        if (tagName === 'IMG' && hplogo.src === CONFIG.LOGO_BASE64) {
            // Ensure parent styles
            const pictureElement = hplogo.closest('picture');
            if (pictureElement) {
                const parentDiv = pictureElement.parentElement?.parentElement;
                if (parentDiv && normalizeTagName(parentDiv) === 'DIV') {
                    parentDiv.style.height = 'auto';
                }
            }
            return false;
        }
        
        if (!CONFIG.REPLACE_ON_DOODLE && hasDoodle()) {
            console.log('[Google Zen] Doodle detected, skipping main logo');
            return false;
        }
        
        if (tagName === 'SVG' || tagName === 'IMG') {
            const img = document.createElement('img');
            img.id = 'hplogo';
            img.src = CONFIG.LOGO_BASE64;
            img.style.width = '272px';
            img.style.height = 'auto';
            img.style.setProperty('filter', getDarkModeFilter(), 'important');
            img.dataset.customLogo = 'true';
            img.alt = 'Google';
            
            hplogo.parentElement.replaceChild(img, hplogo);
            
            // Set parent styles
            const pictureElement = img.closest('picture');
            if (pictureElement) {
                const parentDiv = pictureElement.parentElement?.parentElement;
                if (parentDiv && normalizeTagName(parentDiv) === 'DIV') {
                    parentDiv.style.height = 'auto';
                }
            }
            
            console.log('[Google Zen] Main page logo replaced');
            return true;
        }
        
        return false;
    }

    // Replace search results page header logo
    function replaceSearchPageLogo() {
        const selectors = [
            'a#logo',
        ];
        
        let logoLink = null;
        for (const selector of selectors) {
            logoLink = document.querySelector(selector);
            if (logoLink && logoLink.id === 'logo') break;
            if (logoLink) {
                const hasLogoContent = logoLink.querySelector('svg, img') || 
                                      logoLink.children.length > 0;
                if (hasLogoContent) break;
            }
        }
        
        if (!logoLink) return false;
        
        const existingCustom = logoLink.querySelector('img[data-custom-logo="true"]');
        const needsReplacement = !existingCustom || 
                                existingCustom.src !== CONFIG.LOGO_BASE64 ||
                                existingCustom.style.width !== '120px' ||
                                state.forceReplaceCount > 0;
        
        if (needsReplacement) {
            const targetElement = logoLink.querySelector('svg, img:not([data-custom-logo])') ||
                                logoLink.children[0];
            
            if (!CONFIG.REPLACE_ON_DOODLE && targetElement && normalizeTagName(targetElement) === 'IMG' && hasDoodle()) {
                console.log('[Google Zen] Doodle detected in search page');
                return false;
            }
            
            const img = document.createElement('img');
            img.src = CONFIG.LOGO_BASE64;
            img.style.width = '120px';  
            img.style.height = '36px';   
            img.style.objectFit = 'contain';
            img.style.filter = getDarkModeFilter();
            img.style.display = 'block';
            img.dataset.customLogo = 'true';  
            
            logoLink.innerHTML = '';
            logoLink.appendChild(img);
            
            console.log('[Google Zen] Search page logo replaced');
            return true;
        }
        
        return false;
    }

    // Replace AI mode (udm=50) single character logo - 簡易化されたセレクタ
    function replaceAIModeLogo() {
        if (!window.location.search.includes('udm=50')) {
            return false;
        }
        
        const selectors = [
            'body > header > header > div > a:not([role="button"])',
            'body > header > header > a:has(svg[focusable="false"])'
        ];
        
        let aiLogoLink = null;
        for (const selector of selectors) {
            const elem = document.querySelector(selector);
            if (elem) {
                // 簡易化された条件:子要素があるか確認するだけ
                if (elem.querySelector('svg, img, div > img') || elem.children.length > 0) {
                    aiLogoLink = elem;
                    break;
                }
            }
        }
        
        if (!aiLogoLink) return false;
        
        // Apply styles to parent div
        const parentDiv = aiLogoLink.parentElement?.parentElement;
        if (parentDiv && normalizeTagName(parentDiv) === 'DIV') {
            parentDiv.style.left = '21px';
            parentDiv.style.top = '33px';
            //parentDiv.style.position = 'absolute';
        }
        
        // Apply styles to link
        aiLogoLink.style.display = 'inline-block';
        aiLogoLink.style.width = '34px';
        aiLogoLink.style.height = '34px';
        aiLogoLink.style.verticalAlign = 'middle';
        aiLogoLink.style.position = 'relative';
        
        const existingCustom = aiLogoLink.querySelector('.custom-logo-cropped');
        const existingImg = existingCustom?.querySelector('img');
        const needsReplacement = !existingCustom || 
                                !existingImg ||
                                existingImg.src !== CONFIG.LOGO_BASE64 ||
                                aiLogoLink.style.width !== '34px' ||
                                state.forceReplaceCount > 0;
        
        if (needsReplacement) {
            const targetElement = aiLogoLink.querySelector('svg, img:not(.custom-logo-cropped img), div > img') ||
                                aiLogoLink.children[0];
            
            if (!CONFIG.REPLACE_ON_DOODLE && targetElement && normalizeTagName(targetElement) === 'IMG' && targetElement.width > 34) {
                console.log('[Google Zen] Doodle detected in AI mode');
                return false;
            }
            
            const croppedLogo = createCroppedLogoContainer(34);
            croppedLogo.style.position = 'relative';
            croppedLogo.style.verticalAlign = 'middle';
            
            aiLogoLink.innerHTML = '';
            aiLogoLink.appendChild(croppedLogo);
            
            aiLogoLink.style.display = 'inline-block';
            aiLogoLink.style.width = '34px';
            aiLogoLink.style.height = '34px';
            aiLogoLink.style.verticalAlign = 'middle';
            aiLogoLink.style.position = 'relative';
            
            console.log('[Google Zen] AI mode logo replaced with cropped image');
            return true;
        } else if (existingCustom) {
            aiLogoLink.style.display = 'inline-block';
            aiLogoLink.style.width = '34px';
            aiLogoLink.style.height = '34px';
            aiLogoLink.style.verticalAlign = 'middle';
            aiLogoLink.style.position = 'relative';
        }
        
        return false;
    }

    // Replace Google Maps logo
    function replaceGoogleMapsLogo() {
        if (!window.location.hostname.includes('maps.google.com')) return false;
        
        const logoImg = document.querySelector('#settings > div > div > ul > div > div > img');
        if (logoImg && logoImg.src !== CONFIG.LOGO_BASE64) {
            logoImg.src = CONFIG.LOGO_BASE64;
            logoImg.style.filter = getDarkModeFilter();
            console.log('[Google Zen] Google Maps logo replaced');
            return true;
        }
        return false;
    }

    // Replace all logos
    function replaceAllLogos() {
        if (state.forceReplaceCount > 0) {
            state.forceReplaceCount--;
            console.log(`[Google Zen] Force replace mode: ${state.forceReplaceCount} remaining`);
        }
        
        const mainResult = replaceMainPageLogo();
        const searchResult = replaceSearchPageLogo();
        const aiResult = replaceAIModeLogo();
        const mapsResult = replaceGoogleMapsLogo();
        
        if (state.forceReplaceCount > 0 || (searchResult || aiResult || mapsResult)) {
            console.log(`[Google Zen] Status - Main: ${mainResult}, Search: ${searchResult}, AI: ${aiResult}, Maps: ${mapsResult}`);
        }
        
        if (!searchResult && document.querySelector('a#logo, div.logo')) {
            setTimeout(() => {
                replaceSearchPageLogo();
            }, 100);
        }
        
        if (!aiResult && window.location.search.includes('udm=50')) {
            setTimeout(() => {
                replaceAIModeLogo();
            }, 100);
        }
    }

    // ===================== Execution Control =====================
    
    // Initialize logo replacer with DOM monitoring
    function initLogoReplacer() {
        // Inject styles
        injectServiceStyles();
        
        // Reset force replacement counter
        state.forceReplaceCount = state.maxForceReplace;
        
        // Initial execution
        replaceAllLogos();
        
        // Set up fast checking for first 3 seconds
        if (state.fastIntervalId) {
            clearInterval(state.fastIntervalId);
        }
        state.fastIntervalId = setInterval(() => {
            replaceAllLogos();
        }, 200);
        
        setTimeout(() => {
            if (state.fastIntervalId) {
                clearInterval(state.fastIntervalId);
                state.fastIntervalId = null;
                console.log('[Google Zen] Fast checking stopped');
            }
        }, 3000);
        
        // Set up regular periodic checking
        if (state.intervalId) {
            clearInterval(state.intervalId);
        }
        state.intervalId = setInterval(replaceAllLogos, CONFIG.CHECK_INTERVAL);
        
        // Monitor DOM changes with MutationObserver
        const observer = new MutationObserver((mutations) => {
            const now = Date.now();
            if (now - state.lastMutationTime < CONFIG.MUTATION_THROTTLE) {
                return;
            }
            state.lastMutationTime = now;
            
            let shouldReplace = false;
            let navigationDetected = false;
            
            for (const mutation of mutations) {
                if (mutation.type === 'childList') {
                    const addedNodes = Array.from(mutation.addedNodes);
                    for (const node of addedNodes) {
                        if (node.nodeType === 1) {
                            const hasLogoElements = 
                                (node.id === 'hplogo' || node.id === 'logo') ||
                                (node.querySelector && (
                                    node.querySelector('#hplogo') ||
                                    node.querySelector('#logo') ||
                                    node.querySelector('a#logo') ||
                                    node.querySelector('picture') ||
                                    node.querySelector('svg[aria-label="Google"]')
                                ));
                            
                            const nodeTag = normalizeTagName(node);
                            if (nodeTag === 'HEADER' || nodeTag === 'MAIN' || 
                                node.classList?.contains('logo')) {
                                navigationDetected = true;
                            }
                            
                            if (hasLogoElements) {
                                shouldReplace = true;
                                break;
                            }
                        }
                    }
                }
                
                if (shouldReplace) break;
            }
            
            if (navigationDetected) {
                state.forceReplaceCount = state.maxForceReplace;
                console.log('[Google Zen] Navigation detected, resetting force replace');
                
                if (state.fastIntervalId) {
                    clearInterval(state.fastIntervalId);
                }
                state.fastIntervalId = setInterval(() => {
                    replaceAllLogos();
                }, 200);
                setTimeout(() => {
                    if (state.fastIntervalId) {
                        clearInterval(state.fastIntervalId);
                        state.fastIntervalId = null;
                    }
                }, 3000);
            }
            
            if (shouldReplace || navigationDetected) {
                setTimeout(replaceAllLogos, 50);
            }
        });
        
        if (document.body) {
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        } else {
            const bodyObserver = new MutationObserver(() => {
                if (document.body) {
                    observer.observe(document.body, {
                        childList: true,
                        subtree: true
                    });
                    bodyObserver.disconnect();
                    replaceAllLogos();
                }
            });
            bodyObserver.observe(document.documentElement, {
                childList: true,
                subtree: true
            });
        }
    }

    // Monitor dark mode changes
    if (window.matchMedia) {
        window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
            console.log('[Google Zen] Dark mode changed:', e.matches);
            state.forceReplaceCount = state.maxForceReplace;
            
            if (state.fastIntervalId) {
                clearInterval(state.fastIntervalId);
            }
            state.fastIntervalId = setInterval(() => {
                replaceAllLogos();
            }, 200);
            setTimeout(() => {
                if (state.fastIntervalId) {
                    clearInterval(state.fastIntervalId);
                    state.fastIntervalId = null;
                }
            }, 3000);
            
            replaceAllLogos();
        });
    }

    // Execute when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => {
            state.forceReplaceCount = state.maxForceReplace;
            replaceAllLogos();
        });
    } else {
        state.forceReplaceCount = state.maxForceReplace;
        replaceAllLogos();
    }
    
    // Also monitor readyState changes
    document.addEventListener('readystatechange', () => {
        if (document.readyState === 'interactive' || document.readyState === 'complete') {
            console.log(`[Google Zen] Document ready state: ${document.readyState}`);
            setTimeout(replaceAllLogos, 100);
        }
    });

    // Clean up on page unload
    window.addEventListener('unload', () => {
        if (state.intervalId) {
            clearInterval(state.intervalId);
        }
        if (state.fastIntervalId) {
            clearInterval(state.fastIntervalId);
        }
    });
    
    // Handle browser back/forward navigation
    window.addEventListener('popstate', () => {
        console.log('[Google Zen] Browser navigation detected');
        state.forceReplaceCount = state.maxForceReplace;
        
        if (state.fastIntervalId) {
            clearInterval(state.fastIntervalId);
        }
        state.fastIntervalId = setInterval(() => {
            replaceAllLogos();
        }, 200);
        setTimeout(() => {
            if (state.fastIntervalId) {
                clearInterval(state.fastIntervalId);
                state.fastIntervalId = null;
            }
        }, 3000);
        
        setTimeout(replaceAllLogos, 100);
    });

    // Initialize
    initLogoReplacer();
    
    // Monitor URL changes (for SPA navigation)
    let lastUrl = location.href;
    new MutationObserver(() => {
        const url = location.href;
        if (url !== lastUrl) {
            lastUrl = url;
            console.log('[Google Zen] URL changed, resetting force replace');
            state.forceReplaceCount = state.maxForceReplace;
            
            if (state.fastIntervalId) {
                clearInterval(state.fastIntervalId);
            }
            state.fastIntervalId = setInterval(() => {
                replaceAllLogos();
            }, 200);
            setTimeout(() => {
                if (state.fastIntervalId) {
                    clearInterval(state.fastIntervalId);
                    state.fastIntervalId = null;
                }
            }, 3000);
            
            setTimeout(replaceAllLogos, 100);
        }
    }).observe(document, {subtree: true, childList: true});
    
    console.log('[Google Zen] Script initialized v0.3.1');

})();