/**
 * Attention Capture - Smart Engagement System (Niwa Interface version)
 * Displays contextual bubble messages above chat launcher at key behavioral moments.
 * Updated selectors: #za-launcher -> #niwaMorph/#niwaCenter, .za-attention -> .niwa-attention
 * Uses Niwa.MorphController.open() instead of F.positioning.openFlyout()
 * No jQuery dependency for core functionality (jQuery used only for WC events if available).
 */

(function(){
    'use strict';

    var F = window.NiwaAIFrontend || {};

    // Exit if Attention Capture is not enabled or config is missing
    if (!window.NiwaAC || !window.NiwaAC.welcome_enabled && !window.NiwaAC.wakeup_enabled && !window.NiwaAC.objection_slayer_enabled && !window.NiwaAC.checkout_incentive_enabled && !window.NiwaAC.checkout_finish_enabled) {
        return;
    }

    var config = window.NiwaAC;
    if (isAttentionCaptureIgnored()) {
        return;
    }

    var STORAGE_PREFIX = 'niwa_ai_ac_shown_';

    var activeBubbles = [];
    var pendingBubbles = [];
    var chatWasOpen = false;
    var inactivityTimer = null;
    var lastActivity = Date.now();

    function getTrackNonce() {
        if (config.nonce) return config.nonce;
        if (window.NiwaAI && window.NiwaAI.nonce) return window.NiwaAI.nonce;
        return '';
    }

    function getTrackAjaxUrl() {
        if (config.ajax_url) return config.ajax_url;
        if (window.NiwaAI && window.NiwaAI.ajax) return window.NiwaAI.ajax;
        return '';
    }

    function getSessionId() {
        if (window.Niwa && window.Niwa.Utils && typeof window.Niwa.Utils.getSession === 'function') {
            return window.Niwa.Utils.getSession();
        }
        if (typeof F.getSessionId === 'function') return F.getSessionId();
        return '';
    }

    function requestAiProductObjection() {
        var ajaxUrl = getTrackAjaxUrl();
        var nonce = getTrackNonce();
        var productId = Number(config.product_id || 0);
        if (!config.nudge_os1_ai_enabled || !ajaxUrl || !nonce || productId <= 0) {
            return Promise.resolve('');
        }

        var fd = new FormData();
        fd.append('action', config.ai_objection_action || 'niwa_ai_ac_generate_product_objection');
        fd.append('nonce', nonce);
        fd.append('product_id', String(productId));

        return fetch(ajaxUrl, { method: 'POST', body: fd })
            .then(function(response) {
                if (!response.ok) return null;
                return response.json();
            })
            .then(function(payload) {
                return payload && payload.success && payload.data && payload.data.message
                    ? String(payload.data.message).trim()
                    : '';
            })
            .catch(function() { return ''; });
    }

    function trackEvent(eventType, messageType, meta) {
        var ajaxUrl = getTrackAjaxUrl();
        var nonce = getTrackNonce();
        if (!ajaxUrl || !nonce) return;

        var fd = new FormData();
        fd.append('action', config.track_action || 'niwa_ai_ac_track_event');
        fd.append('nonce', nonce);
        fd.append('event_type', eventType);
        fd.append('message_type', messageType || '');
        fd.append('page_url', window.location.href);
        fd.append('session', getSessionId());
        if (meta) fd.append('meta', JSON.stringify(meta));

        fetch(ajaxUrl, { method: 'POST', body: fd }).catch(function() {});
    }

    function getProductName() {
        var titleEl = document.querySelector('.product_title, h1.product_title');
        if (titleEl) return titleEl.textContent.trim();

        var schemaEl = document.querySelector('[itemtype="http://schema.org/Product"] [itemprop="name"]');
        if (schemaEl) return schemaEl.textContent.trim();

        var ogTitle = document.querySelector('meta[property="og:title"]');
        if (ogTitle) return ogTitle.getAttribute('content').trim();

        if (document.body.classList.contains('single-product')) {
            return document.title.split('|')[0].split('-')[0].trim();
        }

        return '';
    }

    function replacePlaceholders(message) {
        if (!message || typeof message !== 'string') return message;
        if (message.indexOf('{product}') !== -1) {
            var productName = getProductName();
            message = message.replace(/{product}/g, productName || 'this product');
        }
        return message;
    }

    function normalizeForCompare(value) {
        return String(value || '').replace(/\/+$/, '');
    }

    function getCurrentPathWithQuery() {
        return (window.location.pathname || '/') + (window.location.search || '');
    }

    function ruleMatchesCurrentUrl(rule) {
        var rawPattern = (rule && rule.url || '').trim();
        if (!rawPattern) return false;

        var href = window.location.href || '';
        var path = getCurrentPathWithQuery();
        var matchType = (rule.match_type || 'contains').toLowerCase();

        if (matchType === 'equals') {
            var normalizedPattern = normalizeForCompare(rawPattern);
            return normalizeForCompare(href) === normalizedPattern ||
                normalizeForCompare(path) === normalizedPattern;
        }
        if (matchType === 'regex') {
            try {
                var re = new RegExp(rawPattern, 'i');
                return re.test(href) || re.test(path);
            } catch (e) {
                return false;
            }
        }
        return href.indexOf(rawPattern) !== -1 || path.indexOf(rawPattern) !== -1;
    }

    function isAttentionCaptureIgnored() {
        if (!config || !config.ignore_pages || !config.ignore_pages.length) return false;

        for (var i = 0; i < config.ignore_pages.length; i++) {
            var page = config.ignore_pages[i];
            if (!page || page.enabled === false || page.enabled === 0 || page.enabled === '0') continue;
            if (ruleMatchesCurrentUrl(page)) return true;
        }

        return false;
    }

    function getBubbleAvatarUrl() {
        if (config.avatar_url) return config.avatar_url;
        if (window.NiwaAI && window.NiwaAI.avatar_url) return window.NiwaAI.avatar_url;
        if (config.default_avatar_url) return config.default_avatar_url;
        if (window.NiwaAI && window.NiwaAI.default_avatar_url) return window.NiwaAI.default_avatar_url;
        if (window.NiwaAI && window.NiwaAI.pluginURL) {
            return window.NiwaAI.pluginURL + 'assets/img/niwa-admin-personal-assistant.png';
        }
        if (config.pluginURL) {
            return config.pluginURL + 'assets/img/niwa-admin-personal-assistant.png';
        }
        return '';
    }

    function hasBeenShown(messageType) {
        if (config.test_mode) return false;
        try { return sessionStorage.getItem(STORAGE_PREFIX + messageType) === '1'; } catch (e) { return false; }
    }

    function markAsShown(messageType) {
        try { sessionStorage.setItem(STORAGE_PREFIX + messageType, '1'); } catch (e) { /* ignore */ }
    }

    // Get launcher element (new morph system)
    function getLauncherEl() {
        return document.getElementById('niwaMorph')
            || document.getElementById('niwaMorphLeft')
            || document.getElementById('niwaCenter');
    }

    function getLauncherPosition() {
        var launcher = getLauncherEl();
        if (!launcher) return null;

        var rect = launcher.getBoundingClientRect();
        var isCenterstage = !!(window.NiwaAI && window.NiwaAI.centerstage_mode);

        return {
            bottom: window.innerHeight - rect.top,
            left: rect.left,
            right: window.innerWidth - rect.right,
            width: rect.width,
            isCenterstage: isCenterstage,
            launcher: launcher
        };
    }

    function createBubble(message, messageType, buttonConfig) {
        var bubble = document.createElement('div');
        bubble.className = 'niwa-attention-bubble';
        bubble.setAttribute('data-type', messageType);
        bubble.setAttribute('role', 'alert');
        bubble.setAttribute('aria-live', 'polite');

        // Sync theme from widget so CSS token overrides and theme selectors work
        // (bubble lives outside .niwa-widget in document.body)
        var widgetEl = document.querySelector('.niwa-widget');
        if (widgetEl) {
            var theme = widgetEl.getAttribute('data-niwa-theme') || 'light';
            bubble.setAttribute('data-niwa-theme', theme);
        }

        var headerDiv = document.createElement('div');
        headerDiv.className = 'niwa-bubble-header';

        var avatarDiv = document.createElement('div');
        avatarDiv.className = 'niwa-bubble-avatar';
        var iconUrl = getBubbleAvatarUrl();
        if (iconUrl) {
            var img = document.createElement('img');
            img.src = iconUrl;
            img.alt = 'Niwa AI';
            avatarDiv.appendChild(img);
        }

        var titleDiv = document.createElement('div');
        titleDiv.className = 'niwa-bubble-title';
        titleDiv.textContent = 'Niwa AI';

        headerDiv.appendChild(avatarDiv);
        headerDiv.appendChild(titleDiv);

        var textDiv = document.createElement('div');
        textDiv.className = 'niwa-bubble-text';
        textDiv.textContent = message;

        var closeBtn = document.createElement('button');
        closeBtn.className = 'niwa-bubble-close';
        closeBtn.innerHTML = '&times;';
        closeBtn.setAttribute('aria-label', 'Close');
        closeBtn.onclick = function(e) {
            e.stopPropagation();
            bubble._consumed = true;
            trackEvent('bubble_dismissed', messageType, { source: 'close_button' });
            removeBubble(bubble);
        };

        bubble.appendChild(closeBtn);
        bubble.appendChild(headerDiv);
        bubble.appendChild(textDiv);

        if (buttonConfig && buttonConfig.text) {
            var buttonContainer = document.createElement('div');
            buttonContainer.className = 'niwa-bubble-button-container';
            buttonContainer.style.cssText = 'display:none;margin-top:12px;';

            var actionBtn = document.createElement('button');
            actionBtn.className = 'niwa-bubble-action-btn';
            actionBtn.textContent = buttonConfig.text;
            actionBtn.onclick = function(e) {
                e.stopPropagation();
                bubble._consumed = true;
                trackEvent('action_button_clicked', messageType, { source: 'action_button' });
                handleBubbleClick(message, messageType, bubble);
                if (buttonConfig.replyText) {
                    sendButtonReplyToChat(buttonConfig.replyText, messageType);
                }
                removeBubble(bubble);
            };

            buttonContainer.appendChild(actionBtn);
            bubble.appendChild(buttonContainer);

            bubble._buttonTimeout = setTimeout(function() {
                if (document.body.contains(bubble)) {
                    buttonContainer.style.display = 'block';
                    bubble.classList.add('niwa-bubble-with-button');
                    setTimeout(repositionAllBubbles, 50);
                }
            }, (buttonConfig.timeout || 5) * 1000);
        }

        bubble.onclick = function(e) {
            if (e.target.classList.contains('niwa-bubble-action-btn')) return;
            bubble._consumed = true;
            trackEvent('bubble_clicked', messageType, { source: 'bubble' });
            handleBubbleClick(message, messageType, bubble);
            removeBubble(bubble);
        };

        return bubble;
    }

    function alignBubbleToLauncher(bubble, launcherPos) {
        if (!bubble || !launcherPos || !launcherPos.launcher) return;

        if (launcherPos.isCenterstage) {
            bubble.setAttribute('data-niwa-centerstage', 'true');
            bubble.style.setProperty('--niwa-attention-center-width', Math.round(launcherPos.width) + 'px');
            bubble.style.left = '50%';
            bubble.style.right = 'auto';
            bubble.style.removeProperty('transform');
            return;
        }

        bubble.removeAttribute('data-niwa-centerstage');
        bubble.style.removeProperty('--niwa-attention-center-width');
        bubble.style.removeProperty('transform');

        var styles = window.getComputedStyle(launcherPos.launcher);
        if (styles.right !== 'auto' && styles.right !== '0px') {
            bubble.style.right = styles.right;
            bubble.style.left = 'auto';
        } else {
            bubble.style.left = styles.left;
            bubble.style.right = 'auto';
        }
    }

    function positionBubble(bubble) {
        var launcherPos = getLauncherPosition();
        if (!launcherPos || !launcherPos.launcher) return false;

        var gapFromLauncher = 8;
        var bottomOffset = launcherPos.bottom + gapFromLauncher;

        for (var i = 0; i < activeBubbles.length; i++) {
            if (document.body.contains(activeBubbles[i])) {
                bottomOffset += activeBubbles[i].offsetHeight + 10;
            }
        }

        bubble.style.bottom = bottomOffset + 'px';
        alignBubbleToLauncher(bubble, launcherPos);

        return true;
    }

    function repositionAllBubbles() {
        var launcherPos = getLauncherPosition();
        if (!launcherPos) return;

        var gapFromLauncher = 8;
        var bottomOffset = launcherPos.bottom + gapFromLauncher;

        for (var i = 0; i < activeBubbles.length; i++) {
            if (document.body.contains(activeBubbles[i])) {
                activeBubbles[i].style.bottom = bottomOffset + 'px';
                alignBubbleToLauncher(activeBubbles[i], launcherPos);
                bottomOffset += activeBubbles[i].offsetHeight + 10;
            }
        }
    }

    function isChatOpen() {
        return !!(window.Niwa && window.Niwa.MorphController && window.Niwa.MorphController.isOpen());
    }

    function showBubble(message, messageType, isCbMini, buttonConfig) {
        if (hasBeenShown(messageType)) return;

        message = replacePlaceholders(message);

        // Reserve the trigger now so it can't fire twice while it waits in the queue.
        markAsShown(messageType);

        var spec = {
            message: message,
            messageType: messageType,
            isCbMini: !!isCbMini,
            buttonConfig: buttonConfig
        };

        // When the chat is open, attention bubbles must not overlap it — they
        // wait in the queue and are released once the chat is closed again.
        if (isChatOpen()) {
            queueBubble(spec);
            return;
        }

        showBubbleNow(spec);
    }

    function queueBubble(spec) {
        if (!spec || !spec.messageType) return;
        for (var i = 0; i < pendingBubbles.length; i++) {
            if (pendingBubbles[i].messageType === spec.messageType) return;
        }
        pendingBubbles.push(spec);
    }

    function showBubbleNow(spec) {
        // Never display while the chat is open — re-queue and bail.
        if (isChatOpen()) {
            queueBubble(spec);
            return;
        }

        var bubble = createBubble(spec.message, spec.messageType, spec.buttonConfig);
        if (spec.isCbMini) bubble.setAttribute('data-cb-mini', 'true');
        bubble._spec = spec;

        document.body.appendChild(bubble);
        if (!positionBubble(bubble)) {
            bubble.remove();
            return;
        }

        activeBubbles.push(bubble);

        setTimeout(function() {
            bubble.classList.add('niwa-bubble-visible');
        }, 10);

        trackEvent('bubble_shown', spec.messageType, { cb_mini: !!spec.isCbMini });

        bubble._autoRemoveTimeout = setTimeout(function() {
            removeBubble(bubble);
        }, 10000);
    }

    // Chat opened: pull any visible (non-consumed) bubbles back into the queue
    // so they never sit on top of the open chat window.
    function onChatOpened() {
        for (var i = 0; i < activeBubbles.length; i++) {
            var b = activeBubbles[i];
            if (!b || !document.body.contains(b)) continue;
            if (b._buttonTimeout) clearTimeout(b._buttonTimeout);
            if (b._autoRemoveTimeout) clearTimeout(b._autoRemoveTimeout);
            if (!b._consumed && b._spec) queueBubble(b._spec);
            b.remove();
        }
        activeBubbles = [];
    }

    // Chat closed: after a short beat, release queued bubbles one stacked group.
    function onChatClosed() {
        if (!pendingBubbles.length) return;
        setTimeout(function() {
            if (isChatOpen()) return;
            var queue = pendingBubbles.slice();
            pendingBubbles = [];
            for (var i = 0; i < queue.length; i++) {
                showBubbleNow(queue[i]);
            }
        }, 1200);
    }

    function handleChatStateChange() {
        var open = isChatOpen();
        if (open === chatWasOpen) return;
        chatWasOpen = open;
        if (open) {
            onChatOpened();
            checkAndInjectMessage();
        } else {
            onChatClosed();
        }
    }

    function removeBubble(bubble) {
        if (!bubble || !document.body.contains(bubble)) return;
        if (bubble._buttonTimeout) clearTimeout(bubble._buttonTimeout);
        if (bubble._autoRemoveTimeout) clearTimeout(bubble._autoRemoveTimeout);

        bubble.classList.remove('niwa-bubble-visible');

        setTimeout(function() {
            if (document.body.contains(bubble)) bubble.remove();
            activeBubbles = activeBubbles.filter(function(b) {
                return b !== bubble && document.body.contains(b);
            });
            repositionAllBubbles();
        }, 300);
    }

    function handleBubbleClick(message, messageType, bubble) {
        var isCbMini = bubble && bubble.getAttribute('data-cb-mini') === 'true';

        if (isCbMini) {
            triggerCbMiniFlow(message);
            return;
        }

        // Inject message into chat
        if (window.Niwa && window.Niwa.MessageRenderer) {
            window.Niwa.MessageRenderer.injectAssistantMessage(message, 'AttentionCapture');
        } else if (F.animations && typeof F.animations.injectAssistantMessage === 'function') {
            F.animations.injectAssistantMessage(message, 'AttentionCapture');
        }
    }

    function sendButtonReplyToChat(replyText, messageType) {
        if (!replyText || !replyText.trim()) return;

        setTimeout(function() {
            if (window.niwaAI && typeof window.niwaAI.sendMessage === 'function') {
                window.niwaAI.sendMessage(replyText);
                return;
            }

            if (window.Niwa && window.Niwa.MorphController) {
                window.Niwa.MorphController.open();
            }

            setTimeout(function() {
                if (window.Niwa && window.Niwa.ChatClient) {
                    window.Niwa.ChatClient.sendMessage(replyText);
                }
            }, 200);
        }, 400);
    }

    function triggerCbMiniFlow(initialMessage) {
        trackEvent('cb_mini_started', 'nudge_os3', { source: 'objection_slayer_3' });

        var attempts = 0;
        var maxAttempts = 20;

        function tryActivateCB() {
            attempts++;

            if (F.cb && typeof F.cb.startMiniFlow === 'function') {
                F.cb.startMiniFlow(initialMessage);
            } else if (attempts < maxAttempts) {
                setTimeout(tryActivateCB, 100);
            } else {
                if (window.Niwa && window.Niwa.MessageRenderer) {
                    window.Niwa.MessageRenderer.injectAssistantMessage(initialMessage, 'ObjectionSlayer3');
                }
            }
        }

        tryActivateCB();
    }

    // === TRIGGER DETECTORS ===

    function initWelcomeTrigger() {
        if (!config.welcome_enabled) return;
        var triggered = false;

        function onScroll() {
            if (triggered || hasBeenShown('welcome')) return;
            triggered = true;
            showBubble(config.welcome_message, 'welcome');
            window.removeEventListener('scroll', onScroll);
        }

        window.addEventListener('scroll', onScroll, { passive: true });
    }

    function initWakeupTrigger() {
        if (!config.wakeup_enabled) return;

        function resetInactivityTimer() {
            lastActivity = Date.now();
            if (inactivityTimer) clearTimeout(inactivityTimer);

            if (!hasBeenShown('wakeup')) {
                inactivityTimer = setTimeout(function() {
                    showBubble(config.wakeup_message, 'wakeup');
                }, config.wakeup_timeout * 1000);
            }
        }

        var events = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart', 'click'];
        for (var i = 0; i < events.length; i++) {
            document.addEventListener(events[i], resetInactivityTimer, { passive: true });
        }

        resetInactivityTimer();
    }

    function initNudgeTrigger() {
        if (!config.objection_slayer_enabled) return;

        var isProductPage = document.body.classList.contains('single-product') ||
                            document.body.classList.contains('product-template-default');

        var os1MessageType = config.nudge_os1_ai_enabled && Number(config.product_id || 0) > 0
            ? 'nudge_os1_ai_' + Number(config.product_id)
            : 'nudge_os1';
        var shouldRunOs1 = isProductPage && config.nudge_os1_enabled &&
            (config.nudge_os1_ai_enabled || config.nudge_sitewide_message) && !hasBeenShown(os1MessageType);
        var aiObjectionPromise = shouldRunOs1 && config.nudge_os1_ai_enabled
            ? requestAiProductObjection()
            : null;

        if (shouldRunOs1) {
            setTimeout(function() {
                if (hasBeenShown(os1MessageType)) return;
                if (!aiObjectionPromise) {
                    showBubble(config.nudge_sitewide_message, os1MessageType);
                    return;
                }
                aiObjectionPromise.then(function(message) {
                    message = message || config.nudge_sitewide_message || '';
                    if (message && !hasBeenShown(os1MessageType)) {
                        showBubble(message, os1MessageType);
                    }
                });
            }, config.nudge_timeout * 1000);
        }

        function scheduleObjectionSlayer(os) {
            var messageType = os.message_type || ('nudge_os' + os.level);
            if (hasBeenShown(messageType)) return;

            setTimeout(function() {
                if (!hasBeenShown(messageType)) {
                    var buttonConfig = null;
                    if (os.button_text) {
                        buttonConfig = {
                            text: os.button_text,
                            timeout: os.button_timeout || 5,
                            replyText: os.button_reply_text || os.button_text || ''
                        };
                    }
                    showBubble(os.message, messageType, !!os.is_cb_mini, buttonConfig);
                }
            }, os.timeout * 1000);
        }

        if (config.objection_slayers && config.objection_slayers.length > 0) {
            var allProductsRules = [];
            var matchedCustomRules = [];

            for (var i = 0; i < config.objection_slayers.length; i++) {
                var os = config.objection_slayers[i];
                if (os.type === 'all_products') {
                    if (isProductPage) allProductsRules.push(os);
                } else if (os.type === 'url' && ruleMatchesCurrentUrl(os)) {
                    matchedCustomRules.push(os);
                }
            }

            matchedCustomRules.sort(function(a, b) {
                var pa = Number.isFinite(Number(a.priority)) ? Number(a.priority) : 9999;
                var pb = Number.isFinite(Number(b.priority)) ? Number(b.priority) : 9999;
                return pa - pb;
            });

            var rulesToRun = allProductsRules.slice();
            if (matchedCustomRules.length > 0) {
                rulesToRun.push(matchedCustomRules[0]);
            }

            for (var j = 0; j < rulesToRun.length; j++) {
                scheduleObjectionSlayer(rulesToRun[j]);
            }
        }
    }

    function initCheckoutIncentiveTrigger() {
        if (!config.checkout_incentive_enabled || !config.wc_active) return;

        // Use native event listener + jQuery fallback for WC events
        if (typeof jQuery !== 'undefined') {
            jQuery(document.body).on('added_to_cart', function() {
                if (hasBeenShown('checkout_incentive')) return;
                setTimeout(function() {
                    if (!hasBeenShown('checkout_incentive')) {
                        showBubble(config.checkout_incentive_message, 'checkout_incentive');
                    }
                }, config.checkout_incentive_timeout * 1000);
            });
        }
    }

    function initCheckoutFinishTrigger() {
        if (!config.checkout_finish_enabled || !config.wc_active) return;

        var isOrderReceivedPage = window.location.href.indexOf('order-received') !== -1 ||
                                  document.body.classList.contains('woocommerce-order-received');

        if (isOrderReceivedPage && !hasBeenShown('checkout_finish')) {
            setTimeout(function() {
                showBubble(config.checkout_finish_message, 'checkout_finish');
            }, 2000);
        }
    }

    // Handle launcher click
    function handleLauncherClick() {
        if (activeBubbles.length > 0) {
            var firstBubble = activeBubbles[0];
            if (document.body.contains(firstBubble)) {
                var bubbleType = firstBubble.getAttribute('data-type') || '';
                trackEvent('launcher_click', bubbleType, { source: 'launcher' });

                var messageTextEl = firstBubble.querySelector('.niwa-bubble-text');
                if (messageTextEl && messageTextEl.textContent) {
                    window._niwa_ac_pending_message = messageTextEl.textContent;

                    for (var i = 0; i < activeBubbles.length; i++) {
                        if (document.body.contains(activeBubbles[i])) {
                            activeBubbles[i].remove();
                        }
                    }
                    activeBubbles = [];
                }
            }
        }
    }

    // Inject pending message when chat opens
    function checkAndInjectMessage() {
        if (isChatOpen() && window._niwa_ac_pending_message) {
            var message = window._niwa_ac_pending_message;
            delete window._niwa_ac_pending_message;

            setTimeout(function() {
                if (window.Niwa && window.Niwa.MessageRenderer) {
                    window.Niwa.MessageRenderer.injectAssistantMessage(message, 'AttentionCapture');
                }
            }, 400);
        }
    }

    function init() {
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', init);
            return;
        }

        window.addEventListener('resize', repositionAllBubbles);

        // Wait for launcher (morph element) to be available
        var checkLauncher = setInterval(function() {
            if (getLauncherEl()) {
                clearInterval(checkLauncher);
                initWelcomeTrigger();
                initWakeupTrigger();
                initNudgeTrigger();
                initCheckoutIncentiveTrigger();
                initCheckoutFinishTrigger();
            }
        }, 100);

        setTimeout(function() { clearInterval(checkLauncher); }, 10000);

        // Click handler on morph pill area
        document.addEventListener('click', function(e) {
            var launcher = e.target.closest('.niwa-morph__pill, .niwa-center__pill, #niwaChathead, #niwaChatheadLeft, #niwaCenterPill');
            if (launcher) handleLauncherClick();
        }, true);

        // Monitor morph for opening (class change)
        if (typeof MutationObserver !== 'undefined') {
            var morphEl = getLauncherEl();
            if (morphEl) {
                var observer = new MutationObserver(function(mutations) {
                    for (var i = 0; i < mutations.length; i++) {
                        if (mutations[i].type === 'attributes' && mutations[i].attributeName === 'class') {
                            handleChatStateChange();
                        }
                    }
                });
                observer.observe(morphEl, { attributes: true });

                window.addEventListener('beforeunload', function() {
                    observer.disconnect();
                });
            }
        }
    }

    init();

})();
