Google Zen Color & Logo

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

目前為 2025-09-29 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Google Zen Color & Logo
// @namespace    http://tampermonkey.net/
// @version      0.7
// @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%) !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%) !important;
            }
            
            /* 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%) !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%) !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');

})();