
(function($) {
    'use strict';

    window.instinctorToast = function(message, type) {
        type = type || 'info';
        var $toast = $('<div class="instinctor-toast instinctor-toast-' + type + '">' + message + '</div>');
        
        if (!$('#instinctor-toast-container').length) {
            $('body').append('<div id="instinctor-toast-container"></div>');
        }
        
        $('#instinctor-toast-container').append($toast);
        
        setTimeout(function() {
            $toast.addClass('show');
        }, 10);
        
        setTimeout(function() {
            $toast.removeClass('show');
            setTimeout(function() { $toast.remove(); }, 300);
        }, 3000);
    };

    const InstinctorAdmin = {
        init: function() {
            this.bindEvents();
            this.loadDashboard();
            this.initMediaUploader();
            this.initTabs();
            this.initGlobalSearch();
            this.initKeyboardShortcuts();
            this.initInlineEdit();
            this.initTooltips();
            this.initNoticeAutoDismiss();

            

            this.initCanonicalSlug();
            this.initBrandLogoSwatch();
            this.initCompactPalette();
            this.initMobileQr();
            this.initStaticQr();
            this.initHfLauncher();
        },

        

        
        initStaticQr: function() {
            if (!window.InstinctorQR) return;
            var els = document.querySelectorAll('[data-instinctor-qr]');
            for (var i = 0; i < els.length; i++) {
                var el = els[i];
                var text = el.getAttribute('data-instinctor-qr');
                if (!text) continue;
                var size = parseInt(el.getAttribute('data-qr-size'), 10) || 96;
                window.InstinctorQR.render(el, text, { ecc: 'M', size: size, margin: 1, moduleColor: '#1d2327', bgColor: '#ffffff' });
            }
        },

        

        
        initCanonicalSlug: function() {
            var el = document.querySelector('[data-canonical-slug]');
            if (!el) return;
            var slug = el.getAttribute('data-canonical-slug');
            if (!slug) return;
            try {
                var u = new URL(location.href);
                u.searchParams.set('p', slug);
                window.history.replaceState(null, '', u.toString());
            } catch (e) {}
        },

        
        
        initBrandLogoSwatch: function() {
            if (window._brandSwatchesWired) return;
            if (!document.getElementById('settings-brand-logo-btn')) return;
            window._brandSwatchesWired = true;
            jQuery(document).on('click', '.settings-brand-pick', function() {
                var label = jQuery(this).data('label') || 'Select image';
                if (!window.openImglibPicker) return;
                window.openImglibPicker({ label: label }, function(att) {
                    if (!att || !att.url) return;
                    jQuery('#settings-brand-logo-url').val(att.url).trigger('change');
                    var $preview = jQuery('#settings-brand-logo-preview');
                    $preview.replaceWith('<img id="settings-brand-logo-preview" src="' + att.url + '" style="max-width:100%;max-height:46px;object-fit:contain">');
                    jQuery('#settings-brand-logo-clear').css('display', 'flex');
                });
            });
            jQuery(document).on('click', '.settings-brand-clear', function(e) {
                e.stopPropagation();
                jQuery('#settings-brand-logo-url').val('').trigger('change');
                jQuery('#settings-brand-logo-preview').replaceWith('<span id="settings-brand-logo-preview">+ Site Logo</span>');
                jQuery(this).hide();
            });
        },

        
        
        initCompactPalette: function() {
            if (!document.querySelector('.impulse-compact-toggle')) return;
            var KEY = 'instinctor_editor_compact';
            function panel() {
                var b = document.querySelector('.impulse-compact-toggle');
                return b ? b.closest('.impulse-panel-left') : null;
            }
            function apply(on) {
                var p = panel(); if (!p) return;
                p.classList.toggle('impulse-compact', !!on);
                var btn = document.querySelector('.impulse-compact-toggle');
                if (btn) {
                    btn.setAttribute('aria-pressed', on ? 'true' : 'false');
                    btn.title = on ? 'Expand palette' : 'Compact palette';
                }
            }
            var on = false;
            try { on = localStorage.getItem(KEY) === '1'; } catch (e) {}
            if (on) apply(true);
            document.addEventListener('click', function (e) {
                var t = e.target && e.target.closest && e.target.closest('.impulse-compact-toggle');
                if (!t) return;
                e.preventDefault();
                var p = panel(); if (!p) return;
                var next = !p.classList.contains('impulse-compact');
                apply(next);
                try { localStorage.setItem(KEY, next ? '1' : '0'); } catch (e2) {}
            });
        },

        

        initMobileQr: function() {
            var $tabs = document.getElementById('impulse-device-tabs');
            if (!$tabs) return;
            var $qrBtn = document.getElementById('impulse-mobile-qr-btn');
            var $pop   = document.getElementById('impulse-mobile-qr-popover');
            var $canvas = document.getElementById('impulse-mobile-qr-canvas');
            var $urlLbl = document.getElementById('impulse-mobile-qr-url');
            if (!$qrBtn || !$pop) return;

            function refreshVis() {
                var active = $tabs.querySelector('.impulse-device-tab.active');
                $qrBtn.style.display = (active && active.dataset.device === 'mobile') ? 'inline-flex' : 'none';
                if (!active || active.dataset.device !== 'mobile') $pop.style.display = 'none';
            }
            $tabs.addEventListener('click', function() { setTimeout(refreshVis, 50); });
            refreshVis();

            function pageUrl() {
                var pid = (window.Impulse && Impulse.pageId) || 0;
                if (!pid) return null;
                try {
                    var iframe = document.getElementById('impulse-iframe');
                    if (iframe && iframe.contentDocument) {
                        var bd = iframe.contentDocument.body;
                        if (bd && bd.dataset && bd.dataset.previewPublicUrl) return bd.dataset.previewPublicUrl;
                    }
                } catch (e) {}
                var origin = (window.Impulse && Impulse.frontendOrigin) || window.location.origin;
                var page = (window.Impulse && Impulse.pages || []).find(function(p){return String(p.id)===String(pid);});
                var slug = page && page.slug;
                if (slug) {
                    return origin + '/' + slug;
                }
                return origin + '/?p=' + pid;
            }

            function drawQr(text) {
                
                if (window.InstinctorQR) {
                    window.InstinctorQR.render($canvas, text, { ecc: 'M', size: 176, margin: 2, moduleColor: '#000000', bgColor: '#ffffff' });
                } else {
                    $canvas.textContent = text;
                }
                $urlLbl.textContent = text;
            }

            $qrBtn.addEventListener('click', function(e) {
                e.stopPropagation();
                if ($pop.style.display === 'block') { $pop.style.display = 'none'; return; }
                var url = pageUrl();
                if (!url) { $urlLbl.textContent = 'Save the page first'; $canvas.innerHTML = ''; $pop.style.display = 'block'; return; }
                drawQr(url);
                $pop.style.display = 'block';
            });
            document.addEventListener('click', function(e) {
                if (!$pop.contains(e.target) && e.target !== $qrBtn) $pop.style.display = 'none';
            });
        },

        

        
        
        initHfLauncher: function() {
            var $ = jQuery;
            var launcher = document.querySelector('.impulse-hf-launcher');
            if (!launcher) return;

            
            
            if (typeof upgradeCheckboxes === 'function') {
                upgradeCheckboxes(document.querySelector('.impulse-wrap') || document.body);
            }

            

            (function() {
                if (document.getElementById('impulse-tip')) return; 
                var $tip = $('<div id="impulse-tip"></div>').appendTo('body');
                var tipEl = $tip[0];
                var showTimer, hideTimer;

                function convertTitlesToTips(root) {
                    (root || document).querySelectorAll('[title]:not([data-tip])').forEach(function(el) {
                        var t = el.getAttribute('title');
                        if (t && t.trim()) {
                            el.setAttribute('data-tip', t);
                            el.removeAttribute('title');
                        }
                    });
                }
                convertTitlesToTips();

                new MutationObserver(function(mutations) {
                    mutations.forEach(function(m) {
                        m.addedNodes.forEach(function(n) {
                            if (n.nodeType === 1) convertTitlesToTips(n.parentElement || n);
                        });
                    });
                }).observe(document.body, { childList: true, subtree: true });

                function showTip(el, text) {
                    clearTimeout(hideTimer);
                    tipEl.textContent = text;
                    tipEl.style.display = 'block';
                    tipEl.style.whiteSpace = 'normal';
                    tipEl.style.width = '200px';
                    positionTip(el);
                    clearTimeout(showTimer);
                    showTimer = setTimeout(function() { tipEl.classList.add('visible'); }, 80);
                }

                function hideTip() {
                    clearTimeout(showTimer);
                    tipEl.classList.remove('visible');
                    hideTimer = setTimeout(function() { tipEl.style.display = 'none'; }, 120);
                }

                function positionTip(el) {
                    var r   = el.getBoundingClientRect();
                    var tw  = tipEl.offsetWidth  || 180;
                    var th  = tipEl.offsetHeight || 24;
                    var pos = el.getAttribute('data-tip-pos') || 'top';
                    var vw  = window.innerWidth;
                    var vh  = window.innerHeight;
                    var left, top;

                    if (pos === 'bottom' || r.top - th - 10 < 0) {
                        top  = r.bottom + 6;
                        pos  = 'bottom';
                    } else {
                        top  = r.top - th - 6;
                    }

                    left = r.left + r.width / 2 - tw / 2;
                    
                    left = Math.max(8, Math.min(left, vw - tw - 8));
                    
                    if (pos === 'bottom' && top + th > vh - 8) top = r.top - th - 6;

                    tipEl.style.left = left + 'px';
                    tipEl.style.top  = top  + 'px';
                }

                $(document).on('mouseenter.impulsetip', '[data-tip]', function() {
                    var text = this.getAttribute('data-tip');
                    if (text && text.trim()) showTip(this, text);
                }).on('mouseleave.impulsetip focus.impulsetip blur.impulsetip click.impulsetip', '[data-tip]', hideTip);

                $(window).on('scroll.impulsetip resize.impulsetip', hideTip);
            })();

            
            var editBase   = launcher.getAttribute('data-edit-base-url') || '';
            var createUrl  = launcher.getAttribute('data-create-url') || '';
            var restNonce  = launcher.getAttribute('data-rest-nonce') || '';
            $('.impulse-hf-edit').on('click', function() {
                var type = $(this).data('type');
                var pageId = $(this).data('id');
                var $btn = $(this);

                if (pageId) {
                    
                    window.location.href = editBase + pageId;
                } else {
                    
                    $btn.prop('disabled', true).text('Creating...');

                    $.ajax({
                        url: createUrl,
                        method: 'POST',
                        headers: { 'X-WP-Nonce': restNonce },
                        contentType: 'application/json',
                        data: JSON.stringify({ type: type }),
                        success: function(response) {
                            if (response.id) {
                                window.location.href = editBase + response.id;
                            }
                        },
                        error: function() {
                            $btn.prop('disabled', false).text('Create ' + (type === 'global_header' ? 'Header' : 'Footer'));
                            window.showToast && window.showToast('Error creating page. Please try again.', 'error');
                        }
                    });
                }
            });
        },
        
        initNoticeAutoDismiss: function() {
            
            $('.instinctor-wrap .notice.is-dismissible, .instinctor-admin-wrap .notice.is-dismissible').each(function() {
                var $notice = $(this);
                setTimeout(function() {
                    $notice.fadeOut(300, function() {
                        $(this).remove();
                    });
                }, 4000);
            });
        },

        initKeyboardShortcuts: function() {
            $(document).on('keydown', function(e) {
                
                if ($(e.target).is('input, textarea, select')) return;
                
                var isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
                var cmdKey = isMac ? e.metaKey : e.ctrlKey;

                if (cmdKey && e.key === 's') {
                    e.preventDefault();
                    var $form = $('form.instinctor-form, #instinctor-product-form, form[method="post"]').first();
                    if ($form.length) {
                        $form.find('button[type="submit"], input[type="submit"]').first().click();
                        instinctorToast('Saving...', 'info');
                    }
                }

                if (cmdKey && e.key === 'n' && !e.shiftKey) {
                    e.preventDefault();
                    window.location.href = (window.instinctorAdmin ? instinctorAdmin.adminUrl : '/wp-admin/admin.php') + '?page=instinctor-products&action=new';
                }

                if (cmdKey && e.shiftKey && e.key === 'N') {
                    e.preventDefault();
                    window.location.href = (window.instinctorAdmin ? instinctorAdmin.adminUrl : '/wp-admin/admin.php') + '?page=instinctor-orders&action=new';
                }

                if (e.key === '/' && !cmdKey) {
                    e.preventDefault();
                    $('#instinctor-global-search input').focus();
                }

                if (e.key === 'Escape') {
                    $('.instinctor-modal').hide();
                    $('#instinctor-global-search .instinctor-search-results').hide();
                }

                if (e.key === '?' && e.shiftKey) {
                    e.preventDefault();
                    InstinctorAdmin.showShortcutsHelp();
                }
            });
        },
        
        showShortcutsHelp: function() {
            var isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
            var cmd = isMac ? '⌘' : 'Ctrl';
            var tooltipsHidden = localStorage.getItem('instinctor_hide_tooltips') === '1';

            $('.instinctor-modal-overlay').remove();
            
            var html = '<div class="instinctor-modal-overlay">' +
                '<div class="instinctor-shortcuts-modal">' +
                '<h2>Keyboard Shortcuts</h2>' +
                '<h4>Global</h4>' +
                '<table>' +
                '<tr><td><kbd>' + cmd + '</kbd> + <kbd>S</kbd></td><td>Save current form</td></tr>' +
                '<tr><td><kbd>' + cmd + '</kbd> + <kbd>N</kbd></td><td>New product</td></tr>' +
                '<tr><td><kbd>' + cmd + '</kbd> + <kbd>Shift</kbd> + <kbd>N</kbd></td><td>New order</td></tr>' +
                '<tr><td><kbd>/</kbd></td><td>Focus search</td></tr>' +
                '<tr><td><kbd>Esc</kbd></td><td>Close modal / Cancel</td></tr>' +
                '<tr><td><kbd>?</kbd></td><td>Show this help</td></tr>' +
                '</table>' +
                '<h4>Finance Page</h4>' +
                '<table>' +
                '<tr><td><kbd>R</kbd></td><td>Refresh data</td></tr>' +
                '<tr><td><kbd>E</kbd></td><td>Export to CSV</td></tr>' +
                '<tr><td><kbd>P</kbd></td><td>Print report</td></tr>' +
                '</table>' +
                '<h4>Products Page</h4>' +
                '<table>' +
                '<tr><td><kbd>J</kbd> / <kbd>K</kbd></td><td>Navigate rows</td></tr>' +
                '<tr><td><kbd>Enter</kbd></td><td>Edit selected</td></tr>' +
                '</table>' +
                '<div class="instinctor-shortcuts-options" style="margin-top:16px;padding-top:16px;border-top:1px solid #e0e0e0;">' +
                '<label style="display:flex;align-items:center;gap:8px;cursor:pointer;font-size:13px;">' +
                '<input type="checkbox" id="instinctor-toggle-tooltips" ' + (tooltipsHidden ? 'checked' : '') + '>' +
                '<span>Hide tooltips</span>' +
                '</label>' +
                '</div>' +
                '</div></div>';
            
            $('body').append(html);

            $('.instinctor-modal-overlay').on('click', function(e) {
                if ($(e.target).hasClass('instinctor-modal-overlay')) {
                    $(this).remove();
                }
            });

            $('#instinctor-toggle-tooltips').on('change', function() {
                if (this.checked) {
                    localStorage.setItem('instinctor_hide_tooltips', '1');
                    $('body').addClass('instinctor-tooltips-hidden');
                } else {
                    localStorage.removeItem('instinctor_hide_tooltips');
                    $('body').removeClass('instinctor-tooltips-hidden');
                }
            });
        },
        
        showReportForm: function() {
            
            $('.instinctor-modal-overlay').remove();
            
            var currentPage = window.location.href;
            var html = '<div class="instinctor-modal-overlay">' +
                '<div class="instinctor-report-modal" style="max-width:500px;">' +
                '<h2>Report a Problem</h2>' +
                '<p style="color:#666;font-size:13px;margin-bottom:16px;">Help us improve Instinctor by reporting bugs or issues you encounter.</p>' +
                '<form id="instinctor-report-form">' +
                '<div style="margin-bottom:12px;">' +
                '<label style="display:block;font-weight:500;margin-bottom:4px;">Issue Type</label>' +
                '<select name="issue_type" style="width:100%;padding:8px;border:1px solid #d2d2d7;border-radius:4px;">' +
                '<option value="bug">Bug / Something broken</option>' +
                '<option value="ui">UI / Design issue</option>' +
                '<option value="feature">Feature request</option>' +
                '<option value="other">Other</option>' +
                '</select>' +
                '</div>' +
                '<div style="margin-bottom:12px;">' +
                '<label style="display:block;font-weight:500;margin-bottom:4px;">Description</label>' +
                '<textarea name="description" rows="4" style="width:100%;padding:8px;border:1px solid #d2d2d7;border-radius:4px;resize:vertical;" placeholder="Please describe the issue in detail..."></textarea>' +
                '</div>' +
                '<div style="margin-bottom:12px;">' +
                '<label style="display:block;font-weight:500;margin-bottom:4px;">Steps to Reproduce (optional)</label>' +
                '<textarea name="steps" rows="3" style="width:100%;padding:8px;border:1px solid #d2d2d7;border-radius:4px;resize:vertical;" placeholder="1. Go to...\n2. Click on...\n3. See error..."></textarea>' +
                '</div>' +
                '<input type="hidden" name="page_url" value="' + currentPage + '">' +
                '<input type="hidden" name="browser" value="' + navigator.userAgent + '">' +
                '<div style="display:flex;gap:8px;justify-content:flex-end;margin-top:16px;">' +
                '<button type="button" class="button instinctor-close-report">Cancel</button>' +
                '<button type="submit" class="button button-primary">Submit Report</button>' +
                '</div>' +
                '</form>' +
                '</div></div>';
            
            $('body').append(html);

            $('.instinctor-modal-overlay').on('click', function(e) {
                if ($(e.target).hasClass('instinctor-modal-overlay')) {
                    $(this).remove();
                }
            });

            $('.instinctor-close-report').on('click', function() {
                $('.instinctor-modal-overlay').remove();
            });

            $('#instinctor-report-form').on('submit', function(e) {
                e.preventDefault();
                var $form = $(this);
                var $btn = $form.find('button[type="submit"]');
                
                $btn.prop('disabled', true).text('Submitting...');
                
                $.post(ajaxurl, {
                    action: 'instinctor_submit_report',
                    issue_type: $form.find('[name="issue_type"]').val(),
                    description: $form.find('[name="description"]').val(),
                    steps: $form.find('[name="steps"]').val(),
                    page_url: $form.find('[name="page_url"]').val(),
                    browser: $form.find('[name="browser"]').val(),
                    nonce: instinctorAdmin.adminNonce
                }, function(response) {
                    if (response.success) {
                        $('.instinctor-modal-overlay').remove();
                        instinctorToast('Report submitted. Thank you!', 'success');
                    } else {
                        $btn.prop('disabled', false).text('Submit Report');
                        instinctorToast(response.data || 'Error submitting report', 'error');
                    }
                }).fail(function() {
                    $btn.prop('disabled', false).text('Submit Report');
                    instinctorToast('Connection error', 'error');
                });
            });
        },
        
        initInlineEdit: function() {
            
            $(document).on('dblclick', '.instinctor-inline-editable', function() {
                var $cell = $(this);
                var currentValue = $cell.data('value') || $cell.text().replace(/[^0-9.]/g, '');
                var field = $cell.data('field');
                var id = $cell.data('id');
                
                if ($cell.find('input').length) return;
                
                var $input = $('<input type="text" class="instinctor-inline-input" value="' + currentValue + '">');
                $cell.html($input);
                $input.focus().select();
                
                $input.on('blur keydown', function(e) {
                    if (e.type === 'keydown' && e.key !== 'Enter' && e.key !== 'Escape') return;
                    if (e.key === 'Escape') {
                        $cell.text($cell.data('display') || currentValue);
                        return;
                    }
                    
                    var newValue = $input.val();
                    
                    $.post(ajaxurl, {
                        action: 'instinctor_inline_update',
                        id: id,
                        field: field,
                        value: newValue,
                        nonce: instinctorAdmin.adminNonce
                    }, function(response) {
                        if (response.success) {
                            $cell.data('value', newValue);
                            $cell.text(response.data.display || newValue);
                            instinctorToast('Updated!', 'success');
                        } else {
                            $cell.text($cell.data('display') || currentValue);
                            instinctorToast('Error updating', 'error');
                        }
                    });
                });
            });
        },

        initGlobalSearch: function() {
            
            if ($('.instinctor-admin-wrap').length && !$('#instinctor-shortcuts-hint').length) {
                var hintHtml = '<div id="instinctor-shortcuts-hint" style="position:fixed;bottom:30px;left:180px;z-index:9998;display:flex;gap:8px;">' +
                    '<button type="button" class="instinctor-shortcuts-btn instinctor-report-btn" title="Report a Problem">' +
                    '<span style="font-size:12px;">Report Issue</span>' +
                    '</button>' +
                    '<button type="button" class="instinctor-shortcuts-btn" title="Keyboard Shortcuts">' +
                    '<span style="font-size:14px;">?</span>' +
                    '</button>' +
                    '</div>';
                $('body').append(hintHtml);
                
                $('#instinctor-shortcuts-hint .instinctor-shortcuts-btn:not(.instinctor-report-btn)').on('click', function() {
                    InstinctorAdmin.showShortcutsHelp();
                });
                
                $('#instinctor-shortcuts-hint .instinctor-report-btn').on('click', function() {
                    InstinctorAdmin.showReportForm();
                });
            }

            var currentPage = new URLSearchParams(window.location.search).get('page') || '';
            var currentAction = new URLSearchParams(window.location.search).get('action') || '';
            var currentTab = new URLSearchParams(window.location.search).get('tab') || '';
            var showSearchPages = ['instinctor-orders', 'instinctor-customers'];
            var hasNoSearchClass = $('.instinctor-no-search').length > 0;
            var isListPage = showSearchPages.indexOf(currentPage) !== -1 && 
                            (currentAction === '' || currentAction === 'list');
            
            if (!$('#instinctor-global-search').length && $('.instinctor-admin-wrap').length && isListPage && !hasNoSearchClass) {
                var searchHtml = '<div id="instinctor-global-search">' +
                    '<input type="text" placeholder="Search...">' +
                    '<div class="instinctor-search-results"></div>' +
                    '</div>';

                var $header = $('.instinctor-finance-header, .instinctor-page-header').first();
                var $headerActions = $header.find('.header-actions');
                
                if ($headerActions.length) {
                    $headerActions.append(searchHtml);
                } else if ($header.length) {
                    $header.append(searchHtml);
                } else {
                    
                    $('body').append('<div id="instinctor-global-search" style="position:fixed;top:46px;right:20px;z-index:9999;">' +
                        '<input type="text" placeholder="Search...">' +
                        '<div class="instinctor-search-results"></div>' +
                        '</div>');
                }
                
                var searchTimeout;
                $('#instinctor-global-search input').on('input', function() {
                    var query = $(this).val();
                    clearTimeout(searchTimeout);
                    
                    if (query.length < 2) {
                        $('#instinctor-global-search .instinctor-search-results').hide();
                        return;
                    }
                    
                    searchTimeout = setTimeout(function() {
                        $.post(ajaxurl, {
                            action: 'instinctor_global_search',
                            query: query,
                            nonce: instinctorAdmin.nonce || ''
                        }, function(response) {
                            if (response.success && response.data.html) {
                                $('#instinctor-global-search .instinctor-search-results').html(response.data.html).show();
                            }
                        });
                    }, 300);
                });

                $(document).on('click', function(e) {
                    if (!$(e.target).closest('#instinctor-global-search').length) {
                        $('#instinctor-global-search .instinctor-search-results').hide();
                    }
                });
            }
        },

        initTabs: function() {
            
            $(document).on('click', '.instinctor-tab', function(e) {
                e.preventDefault();
                var target = $(this).attr('href');

                $(this).closest('.instinctor-tabs').find('.instinctor-tab').removeClass('active');
                $(this).addClass('active');

                var $container = $(this).closest('.wrap, .instinctor-admin');
                $container.find('.instinctor-tab-content').removeClass('active').hide();
                $(target).addClass('active').show();
            });
        },

        bindEvents: function() {
            
            $(document).on('submit', '#instinctor-product-form', this.saveProduct);

            $(document).on('click', '.instinctor-delete-product', this.deleteProduct);

            $(document).on('change', '.instinctor-order-status-select', this.updateOrderStatus);

            $(document).on('change', '#is-preorder', function() {
                $('#preorder-options').toggle(this.checked);
            });

            $(document).on('change', '#membership-required', function() {
                $('#membership-tiers').toggle(this.checked);
            });

            $(document).on('click', '#add-volume-tier', function() {
                var html = '<div class="instinctor-volume-tier" style="display:flex;gap:8px;margin-bottom:8px;align-items:center;">' +
                    '<input type="number" name="volume_min[]" placeholder="Min" style="width:60px;" min="2">' +
                    '<span>+</span>' +
                    '<input type="number" name="volume_discount[]" placeholder="%" style="width:60px;" min="1" max="100">' +
                    '<span>% off</span>' +
                    '<button type="button" class="button button-small instinctor-remove-volume-tier" style="color:#dc2626;">&times;</button>' +
                    '</div>';
                $('#volume-tiers').append(html);
            });
            
            $(document).on('click', '.instinctor-remove-volume-tier', function() {
                $(this).closest('.instinctor-volume-tier').remove();
            });
        },

        initMediaUploader: function() {
            var frame;

            $(document).on('click', '#instinctor-featured-image', function(e) {
                if ($(e.target).is('#instinctor-remove-image')) return;
                
                e.preventDefault();
                
                if (frame) {
                    frame.open();
                    return;
                }
                
                frame = wp.media({
                    title: 'Select Product Image',
                    button: { text: 'Use Image' },
                    multiple: false
                });
                
                frame.on('select', function() {
                    var attachment = frame.state().get('selection').first().toJSON();
                    var imgUrl = attachment.sizes.thumbnail ? attachment.sizes.thumbnail.url : attachment.url;
                    
                    $('#product-featured-image').val(attachment.id);
                    $('#instinctor-featured-image').html(
                        '<img src="' + imgUrl + '" class="instinctor-image-upload-preview" id="instinctor-image-preview">' +
                        '<input type="hidden" id="product-featured-image" name="featured_image" value="' + attachment.id + '">' +
                        '<button type="button" class="button button-small" id="instinctor-remove-image">Remove</button>'
                    );
                });
                
                frame.open();
            });

            $(document).on('click', '#instinctor-remove-image', function(e) {
                e.preventDefault();
                e.stopPropagation();
                $('#instinctor-featured-image').html(
                    '<div class="instinctor-image-upload-text">Click to add image</div>' +
                    '<input type="hidden" id="product-featured-image" name="featured_image" value="">'
                );
            });
        },

        loadDashboard: function() {
            if ($('#instinctor-dashboard-stats').length === 0) {
                return;
            }

            this.apiGet('stats').then(function(response) {
                if (response.data) {
                    InstinctorAdmin.renderStats(response.data);
                }
            });
        },

        renderStats: function(stats) {
            $('#instinctor-stat-orders').text(stats.total_orders);
            $('#instinctor-stat-revenue').text(InstinctorAdmin.formatCurrency(stats.total_revenue));
            $('#instinctor-stat-products').text(stats.total_products);
            $('#instinctor-stat-customers').text(stats.total_customers);

            if (stats.recent_orders && stats.recent_orders.length > 0) {
                let html = '';
                stats.recent_orders.forEach(function(order) {
                    html += '<tr>';
                    html += '<td>#' + order.order_number + '</td>';
                    html += '<td>' + InstinctorAdmin.formatDate(order.created_at) + '</td>';
                    html += '<td><span class="instinctor-status instinctor-status-' + order.status + '">' + order.status + '</span></td>';
                    html += '<td>' + InstinctorAdmin.formatCurrency(order.total) + '</td>';
                    html += '</tr>';
                });
                $('#instinctor-recent-orders tbody').html(html);
            } else {
                $('#instinctor-recent-orders tbody').html(
                    '<tr><td colspan="4" class="instinctor-empty">No orders yet</td></tr>'
                );
            }
        },

        saveProduct: function(e) {
            e.preventDefault();
            
            const $form = $(this);
            const $submit = $form.find('button[type="submit"]');
            const productId = $form.data('product-id');
            
            $submit.prop('disabled', true).text('Saving...');

            const categories = [];
            $('input[name="categories[]"]:checked').each(function() {
                categories.push(parseInt($(this).val()));
            });

            const currencyPrices = {};
            $('input[name^="currency_prices["]').each(function() {
                const name = $(this).attr('name');
                const match = name.match(/currency_prices\[([^\]]+)\]/);
                if (match && $(this).val()) {
                    currencyPrices[match[1]] = parseFloat($(this).val());
                }
            });

            const data = {
                name: $('#product-name').val(),
                description: $('#product-description').val(),
                short_description: $('#product-short-description').val(),
                product_type: $('#product-type').val(),
                status: $('input[name="status"]:checked').val() || 'draft',
                price: $('#product-price').val(),
                sale_price: $('#product-sale-price').val(),
                sku: $('#product-sku').val(),
                stock_quantity: $('#product-stock').val(),
                manage_stock: $('#product-manage-stock').is(':checked'),
                featured_image: $('#product-featured-image').val() || null,
                gallery_images: $('#gallery-images-input').val() || '[]',
                categories: categories,
                currency_prices: currencyPrices,
                
                is_bookable: $('#is-bookable').is(':checked'),
                booking_duration: $('input[name="booking_duration"]').val() || 60,
                booking_buffer_before: $('input[name="booking_buffer_before"]').val() || 0,
                booking_buffer_after: $('input[name="booking_buffer_after"]').val() || 15,
                booking_max_per_slot: $('input[name="booking_max_per_slot"]').val() || 1
            };

            const method = productId ? 'PUT' : 'POST';
            const endpoint = productId ? 'products/' + productId : 'products';

            InstinctorAdmin.apiRequest(method, endpoint, data)
                .then(function(response) {
                    if (response.data) {
                        
                        if (!productId) {
                            window.location.href = instinctorAdmin.adminUrl + '?page=instinctor-products';
                        } else {
                            $submit.prop('disabled', false).text('Update Product');
                            InstinctorAdmin.showNotice('Product saved successfully.', 'success');
                        }
                    }
                })
                .catch(function(error) {
                    $submit.prop('disabled', false).text(productId ? 'Update Product' : 'Create Product');
                    InstinctorAdmin.showNotice(error.message || 'Error saving product.', 'error');
                });
        },

        deleteProduct: function(e) {
            e.preventDefault();

            const $btn = $(this);
            const productId = $btn.data('product-id');

            InstinctorAdmin.apiRequest('DELETE', 'products/' + productId)
                .then(function() {
                    $btn.closest('tr').fadeOut(function() {
                        $(this).remove();
                    });
                })
                .catch(function() {
                    InstinctorAdmin.showNotice('Error deleting product.', 'error');
                });
        },

        updateOrderStatus: function() {
            const $select = $(this);
            const orderId = $select.data('order-id');
            const status = $select.val();

            InstinctorAdmin.apiRequest('PUT', 'orders/' + orderId, { status: status })
                .then(function() {
                    InstinctorAdmin.showNotice('Order status updated.', 'success');
                })
                .catch(function() {
                    InstinctorAdmin.showNotice('Error updating order.', 'error');
                });
        },

        apiGet: function(endpoint) {
            return this.apiRequest('GET', endpoint);
        },

        apiRequest: function(method, endpoint, data) {
            return $.ajax({
                url: instinctorAdmin.apiUrl + endpoint,
                method: method,
                data: data ? JSON.stringify(data) : undefined,
                contentType: 'application/json',
                beforeSend: function(xhr) {
                    xhr.setRequestHeader('X-WP-Nonce', instinctorAdmin.nonce);
                }
            });
        },

        formatCurrency: function(amount) {
            const currency = instinctorAdmin.currency || 'USD';
            const symbols = {
                'USD': '$', 'EUR': '€', 'GBP': '£', 'CAD': '$', 
                'AUD': '$', 'JPY': '¥', 'CNY': '¥', 'INR': '₹'
            };
            const symbol = symbols[currency] || '$';
            return symbol + parseFloat(amount).toFixed(2);
        },

        formatDate: function(dateString) {
            const date = new Date(dateString);
            return date.toLocaleDateString();
        },

        showNotice: function(message, type) {
            const $notice = $('<div class="notice notice-' + type + ' is-dismissible"><p>' + message + '</p></div>');
            $('.instinctor-admin-wrap').prepend($notice);
            
            setTimeout(function() {
                $notice.fadeOut(function() {
                    $(this).remove();
                });
            }, 3000);
        },

        initTooltips: function() {
            
            if (localStorage.getItem('instinctor_hide_tooltips') === '1') {
                $('body').addClass('instinctor-tooltips-hidden');
            }

            $(document).on('mouseenter', '.instinctor-tip', function() {
                var $tip = $(this);
                var $content = $tip.find('.instinctor-tip-content');
                if (!$content.length) return;
                
                var tipRect = this.getBoundingClientRect();
                var viewportWidth = window.innerWidth;
                var viewportHeight = window.innerHeight;
                var contentWidth = 240;

                $content.css({'visibility': 'hidden', 'opacity': '0', 'transform': 'scaleX(1)'});
                var contentHeight = $content.outerHeight();
                $content.css({'visibility': '', 'opacity': '', 'transform': ''});
                
                $tip.removeClass('tip-left tip-up');

                
                var spaceOnRight = viewportWidth - tipRect.left;
                if (spaceOnRight < contentWidth + 30) {
                    $tip.addClass('tip-left');
                }

                if (tipRect.bottom + contentHeight + 10 > viewportHeight) {
                    $tip.addClass('tip-up');
                }

                $tip.css('--line-height', contentHeight + 'px');
            });
        }
    };

    $(document).ready(function() {
        InstinctorAdmin.init();
    });

    window.InstinctorAdmin = InstinctorAdmin;

})(jQuery);

(function bootInstagentHelp(){
    'use strict';
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', bootInstagentHelp);
        return;
    }
    if (window.__InstagentHelpBound) return;
    window.__InstagentHelpBound = true;

    var trigger; 
    function getTrigger(){ return document.getElementById('impulse-instagent-help-toggle'); }

    var panel   = document.getElementById('instagent-help-panel');
    var closeBtn= document.getElementById('instagent-help-close');
    var msgsEl  = document.getElementById('instagent-help-messages');
    var inputEl = document.getElementById('instagent-help-input');
    var sendBtn = document.getElementById('instagent-help-send');
    var ctxRow  = document.getElementById('instagent-help-context');
    var ctxVal  = document.getElementById('instagent-help-context-value');

    if (!panel) { console.warn('[Instagent Help] panel not found'); return; }

    

    

    

    
    var BROWSE = [
        { label: 'Layout', items: [
            { slug: 'blocks/section',  label: 'Section' },
            { slug: 'blocks/grid',     label: 'Grid' },
            { slug: 'blocks/rows',     label: 'Rows' },
            { slug: 'blocks/columns',  label: 'Columns' },
        ]},
        { label: 'Blocks', items: [
            { slug: 'blocks/animator',  label: 'Title' },
            { slug: 'blocks/text',      label: 'Text' },
            { slug: 'blocks/image',     label: 'Image' },
            { slug: 'blocks/video',     label: 'Video' },
            { slug: 'blocks/button',    label: 'Button' },
            { slug: 'blocks/divider',   label: 'Divider' },
            { slug: 'blocks/icon-card', label: 'Icon Card' },
            { slug: 'blocks/table',     label: 'Table' },
            { slug: 'blocks/carousel',  label: 'Carousel' },
            { slug: 'blocks/flip-box',  label: 'Flip Box' },
            { slug: 'blocks/map',       label: 'Map' },
            { slug: 'blocks/social',    label: 'Social' },
            { slug: 'blocks/code',      label: 'Code' },
            { slug: 'blocks/chart',     label: 'Chart' },
            { slug: 'blocks/unfold',    label: 'Unfold' },
            { slug: 'blocks/modal',     label: 'Modal' },
            { slug: 'blocks/shape',     label: 'Shape' },
        ]},
        { label: 'Store Tools', items: [
            { slug: 'blocks/products',   label: 'Products' },
            { slug: 'blocks/bundle',     label: 'Bundle' },
            { slug: 'blocks/cart',       label: 'Cart' },
            { slug: 'blocks/plans',      label: 'Plans' },
            { slug: 'blocks/price-list', label: 'Price List' },
            { slug: 'blocks/receipt',    label: 'Receipt' },
            { slug: 'blocks/account',    label: 'Account' },
            { slug: 'blocks/booking',    label: 'Booking' },
            { slug: 'blocks/checkout',   label: 'Checkout' },
        ]},
        { label: 'Forms', items: [
            { slug: 'blocks/contact',  label: 'Contact' },
            { slug: 'blocks/login',    label: 'Login' },
            { slug: 'blocks/register', label: 'Register' },
        ]},
        { label: 'Site', items: [
            { slug: 'blocks/header', label: 'Header' },
            { slug: 'blocks/footer', label: 'Footer' },
        ]},
        { label: 'Concepts', items: [
            { slug: 'concepts/responsive-overrides', label: 'Per-device overrides' },
            { slug: 'concepts/page-overlay',         label: 'Page Overlay' },
        ]},
    ];

    var CHUNK_CACHE = {};

    var inFlight = false;

    function readEditorContext() {
        var ctx = {page_mode:'',selected_block:'',active_tab:'',selected_control:'',page_slug:''};
        var selType = window.selectedElementType || '';
        if (selType) ctx.selected_block = String(selType);
        var activeStab = document.querySelector('.impulse-section-tab.active[data-stab]');
        if (activeStab) {

            
            var stab = activeStab.getAttribute('data-stab') || '';
            var TAB_LABELS = { 'effects': 'animation', 'layout': 'layout' };
            ctx.active_tab = TAB_LABELS[stab] || stab;
        }
        if (window.Impulse && Impulse.page) {
            ctx.page_mode = 'scene';
            if (Impulse.page.slug) ctx.page_slug = String(Impulse.page.slug);
        }
        return ctx;
    }

    function renderContextBar() {
        var ctx = readEditorContext();
        var bits = [];
        if (ctx.selected_block) bits.push('Block: <strong>' + esc(ctx.selected_block) + '</strong>');
        if (ctx.active_tab)     bits.push('Tab: <strong>' + esc(ctx.active_tab) + '</strong>');
        if (ctx.page_mode)      bits.push('Mode: <strong>' + esc(ctx.page_mode) + '</strong>');
        if (bits.length) { ctxRow.style.display = 'flex'; ctxVal.innerHTML = bits.join('  ·  '); }
        else { ctxRow.style.display = 'none'; }
    }

    function openPanel() {
        renderContextBar();
        panel.classList.add('open');
        if (msgsEl.children.length === 0) renderEmpty();
        setTimeout(function(){ inputEl.focus(); }, 50);
    }
    function closePanel() { panel.classList.remove('open'); }

    function bindTrigger() {
        var t = getTrigger();
        if (!t || t.dataset.instagentHelpBound) return;
        t.dataset.instagentHelpBound = '1';
        t.addEventListener('click', function() {
            panel.classList.contains('open') ? closePanel() : openPanel();
        });
    }
    bindTrigger();
    
    setTimeout(bindTrigger, 100);
    setTimeout(bindTrigger, 500);

    closeBtn.addEventListener('click', closePanel);
    document.addEventListener('keydown', function(e) {
        if (e.key === 'Escape' && panel.classList.contains('open')) closePanel();
    });

    function renderEmpty() {
        msgsEl.innerHTML = '';
        var wrap = document.createElement('div');
        wrap.className = 'instagent-help-empty';

        var html = '<div class="intro">'
            + '<div class="heading">Ask Instagent.</div>'
            + '<div class="body">Browse the topics below, or type a question for anything I don\'t cover.</div>'
            + '</div>';

        BROWSE.forEach(function(section, i) {

            
            var key = 'instagent-browse-' + section.label;
            var stored = sessionStorage.getItem(key);
            var open = stored === null ? (i === 0) : (stored === '1');
            html += '<div class="browse-section' + (open ? ' open' : '') + '" data-key="' + esc(key) + '">'
                  +   '<button type="button" class="browse-section-header">'
                  +     '<span>' + esc(section.label) + '</span>'
                  +     '<svg class="browse-caret" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="6 9 12 15 18 9"/></svg>'
                  +   '</button>'
                  +   '<div class="browse-items">';
            section.items.forEach(function(item) {
                html += '<div class="browse-item-wrap">'
                      +   '<button type="button" class="browse-item" '
                      +     'data-slug="' + esc(item.slug) + '">'
                      +     '<span>' + esc(item.label) + '</span>'
                      +     '<svg class="browse-item-caret" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="6 9 12 15 18 9"/></svg>'
                      +   '</button>'
                      +   '<div class="browse-item-content"></div>'
                      + '</div>';
            });
            html += '</div></div>';
        });
        wrap.innerHTML = html;

        wrap.querySelectorAll('.browse-section-header').forEach(function(btn) {
            btn.addEventListener('click', function() {
                var section = btn.closest('.browse-section');
                section.classList.toggle('open');
                sessionStorage.setItem(section.getAttribute('data-key'),
                    section.classList.contains('open') ? '1' : '0');
            });
        });

        wrap.querySelectorAll('.browse-item').forEach(function(btn) {
            btn.addEventListener('click', function() {
                toggleItem(btn);
            });
        });

        msgsEl.appendChild(wrap);
    }

    function toggleItem(btn) {
        var wrap    = btn.closest('.browse-item-wrap');
        var content = wrap.querySelector('.browse-item-content');
        var slug    = btn.getAttribute('data-slug');

        if (wrap.classList.contains('open')) {
            wrap.classList.remove('open');
            return;
        }

        wrap.classList.add('open');

        function renderArticle(md) {
            content.innerHTML = renderArticleAccordion(md);
            wireArticleAccordion(content);
        }

        if (CHUNK_CACHE[slug] !== undefined) {
            if (CHUNK_CACHE[slug] === null) {
                content.innerHTML = '<div class="browse-item-error">Couldn\'t load this article. Try again later.</div>';
            } else {
                renderArticle(CHUNK_CACHE[slug]);
            }
            return;
        }

        content.innerHTML = '<div class="browse-item-loading"><span></span><span></span><span></span></div>';

        var fd = new FormData();
        fd.append('action', 'instinctor_help_chunk');
        fd.append('slug', slug);

        var ajaxUrl = (window.Impulse && window.Impulse.ajaxUrl) ? window.Impulse.ajaxUrl : '/wp-admin/admin-ajax.php';
        fetch(ajaxUrl, { method: 'POST', body: fd, credentials: 'same-origin' })
            .then(function(r){ return r.json(); })
            .then(function(d) {
                if (d && d.success && typeof d.content === 'string') {
                    CHUNK_CACHE[slug] = d.content;
                    renderArticle(d.content);
                } else {
                    CHUNK_CACHE[slug] = null;
                    content.innerHTML = '<div class="browse-item-error">'
                        + esc(d && d.message ? d.message : "I couldn't load this article.")
                        + '</div>';
                }
            })
            .catch(function() {
                CHUNK_CACHE[slug] = null;
                content.innerHTML = '<div class="browse-item-error">Network error. Try again.</div>';
            });
    }

    

    function renderArticleAccordion(md) {
        var lines = String(md).replace(/\r\n?/g, '\n').split('\n');

        
        
        var startIdx = 0;
        if (lines.length && lines[0].trim() === '---') {
            for (var fmI = 1; fmI < lines.length; fmI++) {
                if (lines[fmI].trim() === '---') { startIdx = fmI + 1; break; }
            }
            lines = lines.slice(startIdx);
        }

        var sections = [];      
        var intro = [];         
        var current = null;     
        var skipFirstH1 = true;

        for (var i = 0; i < lines.length; i++) {
            var line = lines[i];
            if (skipFirstH1 && /^#\s+/.test(line)) { skipFirstH1 = false; continue; }
            var h2 = line.match(/^##\s+(.+)$/);
            if (h2) {
                if (current) sections.push(current);
                current = { title: h2[1].trim(), body: [] };
            } else if (current) {
                current.body.push(line);
            } else {
                intro.push(line);
            }
        }
        if (current) sections.push(current);

        

        
        var HIDDEN_SECTIONS = ["Don't", 'Related'];

        var html = '';
        var introMd = intro.join('\n').trim();
        if (introMd) html += '<div class="article-intro">' + renderMarkdown(introMd) + '</div>';

        sections.forEach(function(sec) {
            if (HIDDEN_SECTIONS.indexOf(sec.title) !== -1) return;
            var bodyMd = sec.body.join('\n').trim();
            if (!bodyMd) return;
            html += '<div class="article-section">'
                  +   '<button type="button" class="article-section-header">'
                  +     '<span>' + esc(sec.title) + '</span>'
                  +     '<svg class="article-section-caret" width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="6 9 12 15 18 9"/></svg>'
                  +   '</button>'
                  +   '<div class="article-section-body">' + renderMarkdown(bodyMd) + '</div>'
                  + '</div>';
        });
        return html;
    }

    function wireArticleAccordion(container) {
        container.querySelectorAll('.article-section-header').forEach(function(btn) {
            btn.addEventListener('click', function(e) {
                e.stopPropagation();
                btn.parentNode.classList.toggle('open');
            });
        });
    }

    function send() {
        if (inFlight) return;
        var q = (inputEl.value || '').trim();
        if (!q) return;

        var empty = msgsEl.querySelector('.instagent-help-empty');
        if (empty) empty.remove();

        var userMsg = document.createElement('div');
        userMsg.className = 'instagent-help-msg user';
        userMsg.textContent = q;
        msgsEl.appendChild(userMsg);

        inputEl.value = '';
        inputEl.style.height = '26px';
        scrollDown();

        var typing = document.createElement('div');
        typing.className = 'instagent-help-typing';
        typing.innerHTML = '<span></span><span></span><span></span>';
        msgsEl.appendChild(typing);
        scrollDown();

        inFlight = true;
        sendBtn.disabled = true;

        var ctx = readEditorContext();
        var fd = new FormData();
        fd.append('action', 'instinctor_help_ask');
        fd.append('question', q);
        Object.keys(ctx).forEach(function(k) { fd.append(k, ctx[k]); });

        var ajaxUrl = (window.Impulse && window.Impulse.ajaxUrl) ? window.Impulse.ajaxUrl : '/wp-admin/admin-ajax.php';
        fetch(ajaxUrl, { method: 'POST', body: fd, credentials: 'same-origin' })
            .then(function(r){ return r.json(); })
            .then(function(d) {
                typing.remove();
                inFlight = false;
                sendBtn.disabled = false;
                if (d && d.success && d.answer) {
                    appendBotAnswer(d.answer, d.sources || []);
                } else {
                    appendBotAnswer((d && d.message) ? d.message
                        : "I couldn't answer that. Try again, or open Settings → Contact Support.", []);
                }
            })
            .catch(function() {
                typing.remove();
                inFlight = false;
                sendBtn.disabled = false;
                appendBotAnswer("I couldn't reach the help service. Check your connection and try again.", []);
            });
    }

    function appendBotAnswer(answer ) {
        var bot = document.createElement('div');
        bot.className = 'instagent-help-msg bot';
        bot.innerHTML = renderMarkdown(answer);
        msgsEl.appendChild(bot);
        scrollDown();
    }

    sendBtn.addEventListener('click', send);
    inputEl.addEventListener('keydown', function(e) {
        if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); }
    });
    inputEl.addEventListener('input', function() {
        inputEl.style.height = '26px';
        var h = Math.min(120, inputEl.scrollHeight);
        inputEl.style.height = h + 'px';
    });

    function scrollDown() { msgsEl.scrollTop = msgsEl.scrollHeight; }

    
    
    function renderMarkdown(md) {
        var lines = String(md).replace(/\r\n?/g, '\n').split('\n');
        var html = '';
        var inOL = false, inUL = false;
        function closeLists() {
            if (inOL) { html += '</ol>'; inOL = false; }
            if (inUL) { html += '</ul>'; inUL = false; }
        }
        var paraBuf = [];
        function flushPara() {
            if (paraBuf.length) { html += '<p>' + inlineMd(paraBuf.join(' ')) + '</p>'; paraBuf = []; }
        }
        for (var i = 0; i < lines.length; i++) {
            var line = lines[i];
            var h1 = line.match(/^#\s+(.+)$/);
            var h2 = line.match(/^##\s+(.+)$/);
            var h3 = line.match(/^###\s+(.+)$/);
            var hr = line.match(/^---+\s*$/);
            var olm = line.match(/^\s*(\d+)\.\s+(.+)$/);
            var ulm = line.match(/^\s*[-*]\s+(.+)$/);

            if (h3) {
                flushPara(); closeLists();
                html += '<h3>' + inlineMd(h3[1]) + '</h3>';
            } else if (h2) {
                flushPara(); closeLists();
                html += '<h2>' + inlineMd(h2[1]) + '</h2>';
            } else if (h1) {
                flushPara(); closeLists();
                html += '<h1>' + inlineMd(h1[1]) + '</h1>';
            } else if (hr) {
                flushPara(); closeLists();
                html += '<hr>';
            } else if (olm) {
                flushPara();
                if (!inOL) { closeLists(); html += '<ol>'; inOL = true; }
                html += '<li>' + inlineMd(olm[2]) + '</li>';
            } else if (ulm) {
                flushPara();
                if (!inUL) { closeLists(); html += '<ul>'; inUL = true; }
                html += '<li>' + inlineMd(ulm[1]) + '</li>';
            } else if (line.trim() === '') {
                flushPara(); closeLists();
            } else {
                if (inOL || inUL) { closeLists(); }
                paraBuf.push(line.trim());
            }
        }
        flushPara(); closeLists();
        return html;
    }
    function inlineMd(s) {
        s = esc(s);
        s = s.replace(/\*\*([^\*]+)\*\*/g, '<strong>$1</strong>');
        s = s.replace(/(^|\W)\*([^\*]+)\*(?=\W|$)/g, '$1<em>$2</em>');
        s = s.replace(/`([^`]+)`/g, '<code>$1</code>');
        return s;
    }
    function esc(s) {
        return String(s == null ? '' : s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
    }
})();
