
(function() {
    var platform = window.pywebview.platform;
    var disableText = false;  // Always allow text selection
    var disableTextCss = 'body {-webkit-user-select: none; -khtml-user-select: none; -ms-user-select: none; user-select: none; cursor: default;}'

    if (platform == 'mshtml') {
        window.alert = function(msg) {
            window.external.alert(msg);
        }
    } else if (platform == 'edgechromium') {
        window.alert = function (message) {
            window.chrome.webview.postMessage(['_pywebviewAlert', pywebview.stringify(message), 'alert']);
        }
    } else if (platform == 'gtkwebkit2') {
        window.alert = function (message) {
            window.webkit.messageHandlers.jsBridge.postMessage(pywebview.stringify({funcName: '_pywebviewAlert', params: message, id: 'alert'}));
        }
    } else if (platform == 'cocoa') {
        window.print = function() {
            window.webkit.messageHandlers.browserDelegate.postMessage('print');
        }
    } else if (platform === 'qtwebengine') {
        window.alert = function (message) {
            window.pywebview._QWebChannel.objects.external.call('_pywebviewAlert', pywebview.stringify(message), 'alert');
        }
    } else if (platform === 'qtwebkit') {
        window.alert = function (message) {
            window.external.invoke(JSON.stringify(['_pywebviewAlert', message, 'alert']));
        }
    }

    if (disableText) {
        var css = document.createElement("style");
        css.type = "text/css";
        css.innerHTML = disableTextCss;
        document.head.appendChild(css);
    }

    function disableTouchEvents() {
        var initialX = 0;
        var initialY = 0;

        function onMouseMove(ev) {
            var x = ev.screenX - initialX;
            var y = ev.screenY - initialY;
            window.pywebview._jsApiCallback('pywebviewMoveWindow', [x, y], 'move');
        }

        function onMouseUp() {
            window.removeEventListener('mousemove', onMouseMove);
            window.removeEventListener('mouseup', onMouseUp);
        }

        function onMouseDown(ev) {
            if (
                '%(drag_region_direct_target_only)s' === 'True' &&
                !ev.target.matches('%(drag_selector)s')
            ) {
                return
            }

            initialX = ev.clientX;
            initialY = ev.clientY;
            window.addEventListener('mouseup', onMouseUp);
            window.addEventListener('mousemove', onMouseMove);
        }

        function onBodyMouseDown(event) {
            var target = event.target;
            var dragSelectorElements = document.querySelectorAll('%(drag_selector)s');

            while (target && target !== document.body && target !== document.documentElement) {
                if (target.nodeType === 1) {
                    // Check if target matches the drag selector
                    for (var i = 0; i < dragSelectorElements.length; i++) {
                        if (dragSelectorElements[i] === target) {
                            onMouseDown(event);
                            return;
                        }
                    }
                }

                // If it doesn't match, continue up the DOM tree
                target = target.parentNode;
            }
        }

        document.body.addEventListener('mousedown', onBodyMouseDown);

            // easy drag for edge chromium
        if ('%(easy_drag)s' === 'True') {
            window.addEventListener('mousedown', onMouseDown);
        }

        if ('%(zoomable)s' === 'False') {
            document.body.addEventListener('touchstart', function(e) {
                if ((e.touches.length > 1) || e.targetTouches.length > 1) {
                    e.preventDefault();
                    e.stopPropagation();
                    e.stopImmediatePropagation();
                }
            }, {passive: false});

            window.addEventListener('wheel', function (e) {
                if (e.ctrlKey) {
                    e.preventDefault();
                }
            }, {passive: false});
        }

        // draggable
        if ('%(draggable)s' === 'False') {
            document.addEventListener('dragstart', function(e) {
                if (e.target.tagName === 'IMG' || e.target.tagName === 'A') {
                    e.preventDefault();
                }
            });
        }
    }

    disableTouchEvents();

    // ---- Synerx: CSS overrides for sidebar-bottom buttons (match Vexty style) ----
    var synerxBtnCss = document.createElement('style');
    synerxBtnCss.type = 'text/css';
    synerxBtnCss.textContent =
        '.classic-stop-btn, .chat-stop-btn { display: none !important; }' +
        '.classic-input-row { position: relative !important; gap: 0 !important; align-items: stretch !important; }' +
        '.classic-attach-btn { width: 36px !important; height: 36px !important; font-size: 16px !important; position: absolute !important; left: 10px !important; bottom: 10px !important; z-index: 2 !important; }' +
        '.classic-input-actions { flex-direction: row !important; gap: 4px !important; position: absolute !important; right: 8px !important; bottom: 8px !important; z-index: 2 !important; }' +
        '.classic-input-row textarea { padding: 12px 56px 12px 16px !important; text-align: left !important; box-sizing: border-box !important; }' +
        '.classic-input-row textarea::placeholder { text-align: left !important; }' +
        '.classic-send-btn { width: 36px !important; height: 36px !important; }' +
        '.chat-sidebar-bottom { padding: 6px 16px !important; gap: 16px !important; align-items: center !important; justify-content: center !important; border-top: none !important; }' +
        '.chat-sidebar-bottom .sidebar-bottom-btn { padding: 6px 10px !important; align-items: center !important; font-size: 14px !important; }' +
        '.chat-sidebar-bottom .lang-btn { font-size: 14px !important; padding: 6px 10px !important; border: none !important; border-radius: 6px !important; border-bottom: none !important; font-weight: normal !important; display: flex !important; align-items: center !important; gap: 4px !important; }' +
        '.tab-lang-wrap { margin-left: 0 !important; }' +
        '.lang-btn { font-size: 14px !important; padding: 10px 20px !important; border: none !important; border-radius: 0 !important; background: none !important; font-weight: 500 !important; border-bottom: 2px solid transparent !important; color: var(--subtext) !important; }' +
        '.lang-btn:hover { color: var(--text) !important; background: none !important; }' +
        'body.hide-model .chat-model-label, body.hide-model .classic-model-label, body.hide-model #modelNameDisplay { display: none !important; }' +
        '.chat-top-bar { border-bottom: none !important; }' +
        'body.light-theme .chat-top-bar { border-bottom: none !important; }';
    (document.head || document.documentElement).appendChild(synerxBtnCss);

    // ---- Synerx: Enhanced Markdown Rendering + Code Syntax Highlighting ----
    // Add CSS for syntax highlighting
    var synerxMdCss = document.createElement('style');
    synerxMdCss.type = 'text/css';
    synerxMdCss.textContent =
        // Code block enhancements
        '.md-code-block { position: relative !important; }' +
        '.md-code-block .code-lang-label { position: absolute; top: 4px; right: 8px; font-size: 11px; color: rgba(255,255,255,0.35); text-transform: uppercase; pointer-events: none; font-family: sans-serif; }' +
        '.md-code-block .code-copy-btn { position: absolute; top: 4px; right: 60px; font-size: 12px; color: rgba(255,255,255,0.5); background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.1); border-radius: 4px; padding: 2px 8px; cursor: pointer; font-family: sans-serif; transition: background 0.2s; }' +
        '.md-code-block .code-copy-btn:hover { background: rgba(255,255,255,0.18); color: rgba(255,255,255,0.8); }' +
        // Syntax token colors (dark theme - Catppuccin Mocha inspired)
        '.sx-kw { color: #cba6f7; }' +   // keywords: purple
        '.sx-str { color: #a6e3a1; }' +   // strings: green
        '.sx-num { color: #fab387; }' +    // numbers: peach
        '.sx-cm { color: #6c7086; font-style: italic; }' + // comments: gray italic
        '.sx-fn { color: #89b4fa; }' +     // functions: blue
        '.sx-op { color: #89dceb; }' +     // operators: teal
        '.sx-type { color: #f9e2af; }' +   // types: yellow
        '.sx-bool { color: #fab387; }' +   // booleans: peach
        '.sx-dec { color: #f38ba8; }' +    // decorators: red
        '.sx-tag { color: #f38ba8; }' +    // HTML tags: red
        '.sx-attr { color: #fab387; }' +   // HTML attributes: peach
        '.sx-val { color: #a6e3a1; }' +    // attribute values: green
        '.sx-punc { color: #9399b2; }' +   // punctuation: gray
        '.sx-re { color: #f38ba8; }' +     // regex: red
        // Light theme overrides
        'body.light-theme .sx-kw { color: #8839ef; }' +
        'body.light-theme .sx-str { color: #40a02b; }' +
        'body.light-theme .sx-num { color: #fe640b; }' +
        'body.light-theme .sx-cm { color: #9ca0b0; font-style: italic; }' +
        'body.light-theme .sx-fn { color: #1e66f5; }' +
        'body.light-theme .sx-op { color: #179299; }' +
        'body.light-theme .sx-type { color: #df8e1d; }' +
        'body.light-theme .sx-bool { color: #fe640b; }' +
        'body.light-theme .sx-dec { color: #d20f39; }' +
        'body.light-theme .sx-tag { color: #d20f39; }' +
        'body.light-theme .sx-attr { color: #fe640b; }' +
        'body.light-theme .sx-val { color: #40a02b; }' +
        'body.light-theme .sx-punc { color: #7c7f93; }' +
        'body.light-theme .sx-re { color: #d20f39; }' +
        'body.light-theme .md-code-block .code-lang-label { color: rgba(0,0,0,0.3); }' +
        'body.light-theme .md-code-block .code-copy-btn { color: rgba(0,0,0,0.4); background: rgba(0,0,0,0.05); border-color: rgba(0,0,0,0.1); }' +
        'body.light-theme .md-code-block .code-copy-btn:hover { background: rgba(0,0,0,0.12); color: rgba(0,0,0,0.7); }' +
        // Table styles
        '.md-content table.md-table { border-collapse: collapse; width: auto; min-width: 50%%; margin: 0.5em 0; font-size: 0.92em; }' +
        '.md-content table.md-table th, .md-content table.md-table td { border: 1px solid var(--surface2); padding: 6px 12px; text-align: left; }' +
        '.md-content table.md-table th { background: var(--surface0); font-weight: 600; color: var(--text); }' +
        '.md-content table.md-table tr:nth-child(even) { background: rgba(255,255,255,0.02); }' +
        'body.light-theme .md-content table.md-table tr:nth-child(even) { background: rgba(0,0,0,0.02); }' +
        // Enhanced code block padding for lang label
        '.md-content pre.md-code-block { padding-top: 28px !important; }' +
        // Checkbox list items
        '.md-content .md-checkbox { margin-right: 6px; pointer-events: none; }' +
        '';
    (document.head || document.documentElement).appendChild(synerxMdCss);

    // Syntax highlighter - lightweight, handles common languages
    function _sxHighlight(code, lang) {
        if (!code) return code;
        lang = (lang || '').toLowerCase();

        // HTML-escaped code is input; we need to work with it carefully
        // Define language-specific regex rules
        var rules = [];

        if (lang === 'html' || lang === 'xml' || lang === 'svg' || lang === 'vue') {
            // HTML/XML: tags, attributes, values, comments
            rules = [
                { re: /(&lt;!--[\s\S]*?--&gt;)/g, cls: 'cm' },           // comments
                { re: /(&lt;\/?)([\w-]+)/g, rep: '<span class="sx-punc">$1</span><span class="sx-tag">$2</span>' },  // tags
                { re: /([\w-]+)(=)(&quot;[^&]*&quot;|&#39;[^&]*&#39;|"[^"]*"|'[^']*')/g, rep: '<span class="sx-attr">$1</span><span class="sx-punc">$2</span><span class="sx-val">$3</span>' }, // attrs
                { re: /(&gt;)/g, cls: 'punc' }
            ];
        } else if (lang === 'css' || lang === 'scss' || lang === 'less') {
            rules = [
                { re: /(\/\*[\s\S]*?\*\/)/g, cls: 'cm' },
                { re: /(\/\/[^\n]*)/g, cls: 'cm' },
                { re: /([.#][\w-]+)/g, cls: 'fn' },         // selectors
                { re: /\b([\w-]+)\s*:/g, rep: '<span class="sx-attr">$1</span>:' }, // properties
                { re: /:\s*([^;{}\n]+)/g, rep: ': <span class="sx-val">$1</span>' }, // values
                { re: /(@[\w-]+)/g, cls: 'dec' },
                { re: /(&quot;[^&]*&quot;|&#39;[^&]*&#39;|"[^"]*"|'[^']*')/g, cls: 'str' }
            ];
        } else if (lang === 'json' || lang === 'jsonc') {
            rules = [
                { re: /(&quot;[^&]*&quot;|"[^"]*")\s*:/g, rep: '<span class="sx-attr">$1</span>:' },  // keys
                { re: /:\s*(&quot;[^&]*&quot;|"[^"]*")/g, rep: ': <span class="sx-str">$1</span>' },  // string values
                { re: /\b(true|false|null)\b/g, cls: 'bool' },
                { re: /\b(\d+\.?\d*)\b/g, cls: 'num' }
            ];
        } else if (lang === 'bash' || lang === 'sh' || lang === 'shell' || lang === 'zsh' || lang === 'powershell' || lang === 'ps1' || lang === 'bat' || lang === 'cmd') {
            rules = [
                { re: /(#[^\n]*)/g, cls: 'cm' },
                { re: /(&quot;[^&]*&quot;|&#39;[^&]*&#39;|"[^"]*"|'[^']*')/g, cls: 'str' },
                { re: /\b(if|then|else|elif|fi|for|while|do|done|case|esac|function|return|in|echo|export|source|alias|cd|ls|rm|cp|mv|mkdir|grep|sed|awk|cat|chmod|chown|sudo|apt|pip|npm|yarn|git|docker|curl|wget)\b/g, cls: 'kw' },
                { re: /(\$[\w{}]+)/g, cls: 'fn' },
                { re: /\b(\d+)\b/g, cls: 'num' }
            ];
        } else {
            // Generic: Python/JS/TS/Java/C/C++/C#/Go/Rust/Ruby/PHP etc.
            rules = [
                // Multi-line comments
                { re: /(\/\*[\s\S]*?\*\/)/g, cls: 'cm' },
                // Single-line comments (// or #)
                { re: /((?:\/\/|#)[^\n]*)/g, cls: 'cm' },
                // Decorators (@something)
                { re: /(@[\w.]+)/g, cls: 'dec' },
                // Strings - unescaped quotes (from renderMarkdown path)
                { re: /("(?:[^"\\]|\\.)*")/g, cls: 'str' },
                { re: /('(?:[^'\\]|\\.)*')/g, cls: 'str' },
                { re: /(`(?:[^`\\]|\\.)*`)/g, cls: 'str' },
                // Strings - HTML-escaped quotes (from retroactive highlight path)
                { re: /(&quot;(?:[^&]|&(?!quot;))*?&quot;)/g, cls: 'str' },
                { re: /(&#39;(?:[^&]|&(?!#39;))*?&#39;)/g, cls: 'str' },
                { re: /(&#96;(?:[^&]|&(?!#96;))*?&#96;)/g, cls: 'str' },
                // Numbers
                { re: /\b(0x[0-9a-fA-F]+|0b[01]+|0o[0-7]+|\d+\.?\d*(?:[eE][+-]?\d+)?)\b/g, cls: 'num' },
                // Keywords (broad set covering Python/JS/TS/Java/C/C++/C#/Go/Rust)
                { re: /\b(def|class|import|from|return|if|elif|else|for|while|break|continue|try|except|finally|raise|with|as|yield|lambda|async|await|pass|assert|del|global|nonlocal|function|const|let|var|new|this|typeof|instanceof|void|delete|throw|catch|switch|case|default|extends|implements|interface|abstract|static|public|private|protected|final|override|virtual|struct|enum|trait|impl|match|fn|pub|mod|use|crate|mut|move|ref|unsafe|where|package|main|select|chan|go|defer|panic|recover|nil|type|map|range|make|append|len|print|println|printf|fmt|self|super|True|False|None|true|false|null|undefined|NaN|Infinity|int|float|str|bool|list|dict|tuple|set|string|number|boolean|any|object|void|never|unknown|array)\b/g, cls: 'kw' },
                // Built-in types
                { re: /\b(String|Integer|Float|Double|Boolean|Array|Object|Map|Set|List|Dict|Tuple|Optional|Promise|Future|Vector|HashMap|HashSet|Box|Arc|Rc|Vec|Result|Option|Console|Math|Date|Error|RegExp|JSON|Symbol|BigInt|Buffer|Stream|File|Path|Process|Thread|Exception|RuntimeError|ValueError|TypeError|KeyError|IndexError|IOError)\b/g, cls: 'type' },
                // Function calls
                { re: /\b([a-zA-Z_]\w*)\s*\(/g, rep: '<span class="sx-fn">$1</span>(' },
                // Operators
                { re: /(===|!==|==|!=|&lt;=|&gt;=|=&gt;|&lt;&lt;|&gt;&gt;|&amp;&amp;|\|\||[+\-*]={0,1}|\.{3})/g, cls: 'op' }
            ];
        }

        // Apply rules sequentially with placeholder protection
        // Each rule's output is replaced with a placeholder to prevent subsequent rules
        // from matching inside already-highlighted tokens (e.g., matching '-' in 'sx-kw')
        var result = code;
        var tokens = [];
        for (var i = 0; i < rules.length; i++) {
            var rule = rules[i];
            if (rule.rep) {
                // Custom replacement - wrap entire match result in placeholder
                result = result.replace(rule.re, function() {
                    var args = arguments;
                    var replaced = rule.rep.replace(/\$(\d)/g, function(m, n) { return args[parseInt(n)] || ''; });
                    var idx = tokens.length;
                    tokens.push(replaced);
                    return '\x00TK' + idx + '\x00';
                });
            } else {
                result = result.replace(rule.re, function(m, g1) {
                    var idx = tokens.length;
                    tokens.push('<span class="sx-' + rule.cls + '">' + g1 + '</span>');
                    return '\x00TK' + idx + '\x00';
                });
            }
        }
        // Restore all tokens
        for (var i = 0; i < tokens.length; i++) {
            result = result.replace('\x00TK' + i + '\x00', tokens[i]);
        }
        return result;
    }

    // Enhanced renderMarkdown function
    function _synerxRenderMarkdown(text) {
        if (!text) return '';
        // Escape HTML
        var html = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');

        // Extract code blocks first (protect from further processing)
        var codeBlocks = [];
        html = html.replace(/```(\w*)\n([\s\S]*?)```/g, function(m, lang, code) {
            var idx = codeBlocks.length;
            var highlighted = _sxHighlight(code.trim(), lang);
            var langLabel = lang ? '<span class="code-lang-label">' + lang + '</span>' : '';
            var copyBtn = '<span class="code-copy-btn" onclick="(function(b){var c=b.parentElement.querySelector(\'code\');if(c){var t=c.innerText||c.textContent;if(typeof _synerxExecCopy===\'function\'){_synerxExecCopy(t)}else if(navigator.clipboard){navigator.clipboard.writeText(t)}}b.textContent=\'\u2713 Copied\';setTimeout(function(){b.textContent=\'Copy\'},1500)})(this)">Copy</span>';
            codeBlocks.push('<pre class="md-code-block">' + langLabel + copyBtn + '<code class="lang-' + (lang || 'text') + '">' + highlighted + '</code></pre>');
            return '\x00CB' + idx + '\x00';
        });

        // Inline code
        html = html.replace(/`([^`\n]+)`/g, '<code class="md-inline-code">$1</code>');

        // Tables (|col1|col2| format)
        html = html.replace(/((?:^\|.+\|$\n?)+)/gm, function(tableBlock) {
            var rows = tableBlock.trim().split('\n');
            if (rows.length < 2) return tableBlock;
            var tableHtml = '<table class="md-table">';
            for (var r = 0; r < rows.length; r++) {
                var row = rows[r].trim();
                if (!row.match(/^\|/)) continue;
                // Skip separator row (|---|---|)
                if (row.match(/^\|[\s\-:|]+\|$/)) continue;
                var cells = row.split('|').filter(function(c, idx, arr) { return idx > 0 && idx < arr.length - 1; });
                var tag = r === 0 ? 'th' : 'td';
                tableHtml += '<tr>';
                for (var c = 0; c < cells.length; c++) {
                    tableHtml += '<' + tag + '>' + cells[c].trim() + '</' + tag + '>';
                }
                tableHtml += '</tr>';
            }
            tableHtml += '</table>';
            return tableHtml;
        });

        // Headers
        html = html.replace(/^#### (.+)$/gm, '<h4 class="md-h3">$1</h4>');
        html = html.replace(/^### (.+)$/gm, '<h3 class="md-h3">$1</h3>');
        html = html.replace(/^## (.+)$/gm, '<h2 class="md-h2">$1</h2>');
        html = html.replace(/^# (.+)$/gm, '<h1 class="md-h1">$1</h1>');

        // Bold + Italic (***text***)
        html = html.replace(/\*\*\*([^*]+)\*\*\*/g, '<strong><em>$1</em></strong>');
        // Bold
        html = html.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
        html = html.replace(/__([^_]+)__/g, '<strong>$1</strong>');
        // Italic
        html = html.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, '<em>$1</em>');
        html = html.replace(/(?<!_)_([^_]+)_(?!_)/g, '<em>$1</em>');
        // Strikethrough
        html = html.replace(/~~([^~]+)~~/g, '<del>$1</del>');

        // Checkbox list items
        html = html.replace(/^[\-\*] \[x\] (.+)$/gm, '<li class="md-li"><input type="checkbox" checked class="md-checkbox" disabled>$1</li>');
        html = html.replace(/^[\-\*] \[ \] (.+)$/gm, '<li class="md-li"><input type="checkbox" class="md-checkbox" disabled>$1</li>');
        // Unordered lists
        html = html.replace(/^[\-\*] (.+)$/gm, '<li class="md-li">$1</li>');
        html = html.replace(/((?:<li class="md-li">.*<\/li>\n?)+)/g, '<ul class="md-ul">$1</ul>');
        // Ordered lists
        html = html.replace(/^\d+\. (.+)$/gm, '<li class="md-oli">$1</li>');
        html = html.replace(/((?:<li class="md-oli">.*<\/li>\n?)+)/g, '<ol class="md-ol">$1</ol>');

        // Links
        html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener" class="md-link">$1</a>');
        // Images
        html = html.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1" style="max-width:100%%;border-radius:8px;margin:0.3em 0;">');

        // Horizontal rule
        html = html.replace(/^[\-\*]{3,}$/gm, '<hr class="md-hr">');
        // Blockquote
        html = html.replace(/^&gt; (.+)$/gm, '<blockquote class="md-blockquote">$1</blockquote>');

        // Clean up newlines between block elements
        html = html.replace(/<\/li>\n<li/g, '</li><li');
        html = html.replace(/<\/(h[1234]|ul|ol|pre|blockquote|hr|table)>\n/g, '</$1>');
        html = html.replace(/\n<(h[1234]|ul|ol|pre|blockquote|hr|table)/g, '<$1');

        // Paragraphs
        html = html.replace(/\n\n/g, '</p><p class="md-p">');
        // Single newlines to <br>
        html = html.replace(/\n/g, '<br>');

        // Restore code blocks
        for (var i = 0; i < codeBlocks.length; i++) {
            html = html.replace('\x00CB' + i + '\x00', codeBlocks[i]);
        }

        return '<div class="md-content"><p class="md-p">' + html + '</p></div>';
    }

    // Override renderMarkdown after server JS loads
    window.addEventListener('pywebviewready', function() {
        // Replace the server's renderMarkdown with our enhanced version
        if (typeof window.renderMarkdown === 'function') {
            window.renderMarkdown = _synerxRenderMarkdown;
        }
        // Apply syntax highlighting to any code blocks already rendered by old renderMarkdown
        setTimeout(function() {
            if (typeof window.renderMarkdown === 'function' && window.renderMarkdown !== _synerxRenderMarkdown) {
                window.renderMarkdown = _synerxRenderMarkdown;
            }
            // Retroactively enhance existing code blocks that lack our highlighting
            var codeBlocks = document.querySelectorAll('.md-code-block code');
            for (var i = 0; i < codeBlocks.length; i++) {
                var codeEl = codeBlocks[i];
                if (codeEl.querySelector('.sx-kw, .sx-str, .sx-cm, .sx-num')) continue; // already highlighted
                var lang = '';
                var pre = codeEl.parentElement;
                if (pre) {
                    // Try to detect language from previous sibling or class
                    var prev = pre.previousElementSibling;
                    if (prev && prev.classList && prev.classList.contains('md-code-lang')) {
                        lang = prev.textContent.trim().toLowerCase();
                    }
                    // Also try lang-* class on <code> itself
                    if (!lang) {
                        var cls = codeEl.className || '';
                        var m = cls.match(/lang-(\w+)/);
                        if (m && m[1] !== 'text') lang = m[1];
                    }
                }
                // textContent gives unescaped text; re-escape for _sxHighlight
                var raw = codeEl.textContent;
                var escaped = raw.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
                codeEl.innerHTML = _sxHighlight(escaped, lang);
            }
        }, 300);
    });

    // ---- Synerx: Fix clipboard in WebView2 ----
    // Classic mode copy works with execCommand('copy'), but bubble mode uses
    // navigator.clipboard.writeText() inside an IIFE (cannot override the function).
    // Solution: 1) Override clipboard API, 2) Intercept bubble copy button clicks directly.
    function _synerxExecCopy(text) {
        var ta = document.createElement('textarea');
        ta.value = text;
        ta.style.cssText = 'position:fixed;top:0;left:0;width:2px;height:2px;padding:0;border:none;outline:none;opacity:0.01;z-index:100000;';
        document.body.appendChild(ta);
        ta.focus();
        ta.select();
        ta.setSelectionRange(0, text.length);
        var ok = false;
        try { ok = document.execCommand('copy'); } catch(e) {}
        document.body.removeChild(ta);
        return ok;
    }
    // Make _synerxExecCopy accessible globally for code block copy buttons
    window._synerxExecCopy = _synerxExecCopy;
    // Try multiple methods to override navigator.clipboard.writeText
    (function() {
        if (!navigator.clipboard || !navigator.clipboard.writeText) return;
        var _myWriteText = function(text) {
            return new Promise(function(resolve) {
                _synerxExecCopy(text);
                resolve();
            });
        };
        // Method 1: Direct assignment
        try { navigator.clipboard.writeText = _myWriteText; } catch(e) {}
        // Method 2: Object.defineProperty on instance
        if (navigator.clipboard.writeText !== _myWriteText) {
            try {
                Object.defineProperty(navigator.clipboard, 'writeText', {
                    value: _myWriteText, writable: true, configurable: true
                });
            } catch(e) {}
        }
        // Method 3: Override on Clipboard.prototype
        if (navigator.clipboard.writeText !== _myWriteText && typeof Clipboard !== 'undefined') {
            try {
                Object.defineProperty(Clipboard.prototype, 'writeText', {
                    value: _myWriteText, writable: true, configurable: true
                });
            } catch(e) {}
        }
    })();

    // Direct click interceptor for bubble mode copy buttons (capture phase)
    // This ensures copy works even if clipboard API override fails
    document.addEventListener('click', function(e) {
        var btn = e.target.closest('.msg-action-btn');
        if (!btn) return;
        // Only intercept copy buttons (title='复制' or has the copy SVG)
        var isCopy = btn.title === '\u590D\u5236' || (btn.querySelector('svg rect') && btn.querySelector('svg path'));
        if (!isCopy) return;
        // Find the message text from the bubble's content div
        var bubble = btn.closest('.chat-bubble');
        if (!bubble) return;
        var contentDiv = bubble.querySelector('.summary-markdown');
        if (!contentDiv) return;
        _synerxExecCopy(contentDiv.innerText);
    }, true); // capture phase - runs before the server's handler

    // ---- Synerx: i18n helper ----
    var SYNERX_LANGS = ['ar','bg','bn','cs','da','de','el','en','en-AU','en-SG','es','fa','fi','fil','fr','he','hi','hr','hu','id','it','ja','ko','ms','nb','nl','pl','pt','ro','ru','sk','sv','sw','ta','th','tr','uk','vi','zh-CN','zh-TW'];
    var SYNERX_I18N = {
        lang: ['\u0627\u0644\u0639\u0631\u0628\u064a\u0629','\u0415\u0437\u0438\u043a','\u09ac\u09be\u0982\u09b2\u09be','\u010Ce\u0161tina','Dansk','Sprache','\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac','Language','Language','Language','Idioma','\u0632\u0628\u0627\u0646','Suomi','Filipino','Langue','\u05e9\u05e4\u05d4','\u0939\u093f\u0928\u094d\u0926\u0940','Jezik','Magyar','Bahasa','Lingua','\u8a00\u8a9e','\uc5b8\uc5b4','Bahasa','Norsk Bokm\u00E5l','Taal','J\u0119zyk','Idioma','Rom\u00E2n\u0103','\u042f\u0437\u044b\u043a','Jazyk','Spr\u00e5k','Lugha','\u0bae\u0bca\u0bb4\u0bbf','\u0e20\u0e32\u0e29\u0e32','Dil','\u041c\u043e\u0432\u0430','Ng\u00f4n ng\u1eef','\u8bed\u8a00','\u8a9e\u8a00'],
        settings: ['\u2699\ufe0f \u0627\u0644\u0625\u0639\u062f\u0627\u062f\u0627\u062a','\u2699\ufe0f \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438','\u09b8\u09c7\u099f\u09bf\u0982\u09b8','\u2699\uFE0F Nastaven\u00ED','\u2699\uFE0F Indstillinger','\u2699\ufe0f Einstellungen','\u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2','\u2699\ufe0f Settings','\u2699\ufe0f Settings','\u2699\ufe0f Settings','\u2699\ufe0f Ajustes','\u2699\ufe0f \u062a\u0646\u0638\u06cc\u0645\u0627\u062a','\u2699\uFE0F Asetukset','Mga Setting','\u2699\ufe0f Param\u00e8tres','\u2699\ufe0f \u05d4\u05d2\u05d3\u05e8\u05d5\u05ea','\u0938\u0947\u091f\u093f\u0902\u0917\u094d\u0938','\u2699\ufe0f Postavke','\u2699\uFE0F Be\u00E1ll\u00EDt\u00E1sok','\u2699\ufe0f Pengaturan','\u2699\ufe0f Impostazioni','\u2699\ufe0f \u8a2d\u5b9a','\u2699\ufe0f \uc124\uc815','\u2699\ufe0f Tetapan','\u2699\uFE0F Innstillinger','\u2699\ufe0f Instellingen','\u2699\ufe0f Ustawienia','\u2699\ufe0f Configura\u00e7\u00f5es','\u2699\uFE0F Set\u0103ri','\u2699\ufe0f \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438','\u2699\ufe0f Nastavenia','\u2699\ufe0f Inst\u00e4llningar','\u2699\ufe0f Mipangilio','\u2699\ufe0f \u0b85\u0bae\u0bc8\u0baa\u0bcd\u0baa\u0bc1\u0b95\u0bb3\u0bcd','\u2699\ufe0f \u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32','\u2699\ufe0f Ayarlar','\u2699\ufe0f \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f','\u2699\ufe0f C\u00e0i \u0111\u1eb7t','\u2699\ufe0f \u8bbe\u7f6e','\u2699\ufe0f \u8a2d\u7f6e'],
        about: ['\u2139\ufe0f \u062d\u0648\u0644','\u041e\u0442\u043d\u043e\u0441\u043d\u043e','\u09b8\u09ae\u09cd\u09aa\u09b0\u09cd\u0995\u09c7','\u2139\uFE0F O aplikaci','\u2139\uFE0F Om','\u2139\ufe0f \u00dcber','\u03a3\u03c7\u03b5\u03c4\u03b9\u03ba\u03ac','\u2139\ufe0f About','\u2139\ufe0f About','\u2139\ufe0f About','\u2139\ufe0f Acerca de','\u062f\u0631\u0628\u0627\u0631\u0647','\u2139\uFE0F Tietoja','Tungkol','\u2139\ufe0f \u00c0 propos','\u05d0\u05d5\u05d3\u05d5\u05ea','\u091c\u093e\u0928\u0915\u093e\u0930\u0940','O programu','\u2139\uFE0F N\u00E9vjegy','\u2139\ufe0f Tentang','\u2139\ufe0f Info','\u2139\ufe0f \u306b\u3064\u3044\u3066','\u2139\ufe0f \uc815\ubcf4','\u2139\ufe0f Perihal','\u2139\uFE0F Om','\u2139\ufe0f Over','\u2139\ufe0f O programie','\u2139\ufe0f Sobre','\u2139\uFE0F Despre','\u2139\ufe0f \u041e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435','O aplik\u00e1cii','\u2139\ufe0f Om','Kuhusu','\u0baa\u0bb1\u0bcd\u0bb1\u0bbf','\u2139\ufe0f \u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a','\u2139\ufe0f Hakk\u0131nda','\u2139\ufe0f \u041f\u0440\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443','\u2139\ufe0f Gi\u1edbi thi\u1ec7u','\u2139\ufe0f \u5173\u4e8e','\u2139\ufe0f \u95dc\u65bc'],
        model_display: ['\u0639\u0631\u0636 \u0627\u0644\u0646\u0645\u0648\u0630\u062c','\u041f\u043e\u043a\u0430\u0437\u0432\u0430\u043d\u0435 \u043d\u0430 \u043c\u043e\u0434\u0435\u043b','\u09ae\u09a1\u09c7\u09b2 \u09aa\u09cd\u09b0\u09a6\u09b0\u09cd\u09b6\u09a8','Model','Model','Modellanzeige','\u0395\u03bc\u03c6\u03ac\u03bd\u03b9\u03c3\u03b7 \u03bc\u03bf\u03bd\u03c4\u03ad\u03bb\u03bf\u03c5','Model Display','Model Display','Model Display','Mostrar modelo','\u0646\u0645\u0627\u06cc\u0634 \u0645\u062f\u0644','Malli','Model Display','Affichage du mod\u00e8le','\u05ea\u05e6\u05d5\u05d2\u05ea \u05de\u05d5\u05d3\u05dc','\u092e\u0949\u0921\u0932 \u092a\u094d\u0930\u0926\u0930\u094d\u0936\u0928','Prikaz modela','Modell','Tampilan Model','Visualizzazione modello','\u30e2\u30c7\u30eb\u8868\u793a','\ubaa8\ub378 \ud45c\uc2dc','Paparan model','Modell','Modelweergave','Wy\u015bwietlanie Modelu','Exibi\u00e7\u00e3o do modelo','Model','\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438','Zobrazenie modelu','Modellvisning','Onyesho la Modeli','\u0bae\u0bbe\u0ba4\u0bbf\u0bb0\u0bbf \u0b95\u0bbe\u0b9f\u0bcd\u0b9a\u0bbf','\u0e41\u0e2a\u0e14\u0e07\u0e23\u0e38\u0e48\u0e19','Model G\u00f6r\u00fcnt\u00fcleme','\u0412\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u043c\u043e\u0434\u0435\u043b\u0456','Hi\u1ec3n th\u1ecb m\u00f4 h\u00ecnh','\u6a21\u578b\u663e\u793a','\u6a21\u578b\u986f\u793a'],
        model_display_desc: ['\u0639\u0631\u0636 \u0627\u0633\u0645 \u0648\u0631\u0645\u0632 \u0646\u0645\u0648\u0630\u062c AI \u0641\u064a \u0634\u0631\u064a\u0637 \u0627\u0644\u062d\u0627\u0644\u0629','\u041f\u043e\u043a\u0430\u0436\u0438 \u0438\u043c\u0435\u0442\u043e \u043d\u0430 \u043c\u043e\u0434\u0435\u043b\u0430 \u0432 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u043d\u0430 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0442\u043e','\u09b8\u09cd\u099f\u09cd\u09af\u09be\u099f\u09be\u09b8 \u09ac\u09be\u09b0\u09c7 \u09ae\u09a1\u09c7\u09b2\u09c7\u09b0 \u09a8\u09be\u09ae \u09aa\u09cd\u09b0\u09a6\u09b0\u09cd\u09b6\u09a8 \u0995\u09b0\u09c1\u09a8','N\u00E1zev modelu zobrazen\u00FD na stavov\u00E9m \u0159\u00E1dku','Modelnavn vist p\u00E5 statuslinjen','AI-Modellname und Symbol anzeigen','\u0395\u03bc\u03c6\u03ac\u03bd\u03b9\u03c3\u03b7 \u03bf\u03bd\u03cc\u03bc\u03b1\u03c4\u03bf\u03c2 \u03bc\u03bf\u03bd\u03c4\u03ad\u03bb\u03bf\u03c5 \u03c3\u03c4\u03b7 \u03b3\u03c1\u03b1\u03bc\u03bc\u03ae \u03ba\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7\u03c2','Show AI model name and icon on the interface','Show AI model name and icon on the interface','Show AI model name and icon on the interface','Mostrar nombre e icono del modelo AI','\u0646\u0645\u0627\u06cc\u0634 \u0646\u0627\u0645 \u0645\u062f\u0644 \u062f\u0631 \u0646\u0648\u0627\u0631 \u0648\u0636\u0639\u06cc\u062a','Tilarivill\u00E4 n\u00E4ytett\u00E4v\u00E4 mallin nimi','Ipakita ang pangalan ng AI model sa status bar','Afficher le nom et l\x27ic\u00f4ne du mod\u00e8le IA','\u05d4\u05e6\u05d2 \u05e9\u05dd \u05de\u05d5\u05d3\u05dc \u05d1\u05e9\u05d5\u05e8\u05ea \u05d4\u05de\u05e6\u05d1','\u0938\u094d\u091f\u0947\u091f\u0938 \u092c\u093e\u0930 \u092e\u0947\u0902 AI \u092e\u0949\u0921\u0932 \u0928\u093e\u092e \u0926\u093f\u0916\u093e\u090f\u0901','Prika\u017ei naziv modela u traci stanja','Az \u00E1llapotsoron megjelen\u00EDtett modell neve','Tampilkan nama dan ikon model AI','Mostra nome e icona del modello IA','\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30fc\u30b9\u306bAI\u30e2\u30c7\u30eb\u540d\u3068\u30a2\u30a4\u30b3\u30f3\u3092\u8868\u793a','\uc778\ud130\ud398\uc774\uc2a4\uc5d0 AI \ubaa8\ub378\uba85\uacfc \uc544\uc774\ucf58 \ud45c\uc2dc','Paparkan nama dan ikon model AI','Modellnavn vist p\u00E5 statuslinjen','AI-modelnaam en pictogram tonen','Poka\u017c nazw\u0119 i ikon\u0119 modelu AI','Mostrar nome e \u00edcone do modelo IA','Numele modelului afi\u0219at pe bara de stare','\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0438 \u0437\u043d\u0430\u0447\u043e\u043a \u043c\u043e\u0434\u0435\u043b\u0438 \u0418\u0418','Zobrazi\u0165 n\u00e1zov modelu v stavovom riadku','Visa AI-modellnamn och ikon','Onyesha jina la modeli kwenye upau wa hali','\u0ba8\u0bbf\u0bb2\u0bc8\u0baa\u0bcd\u0baa\u0b9f\u0bcd\u0b9f\u0bbf\u0baf\u0bbf\u0bb2\u0bcd \u0bae\u0bbe\u0ba4\u0bbf\u0bb0\u0bbf \u0baa\u0bc6\u0baf\u0bb0\u0bc8\u0b95\u0bcd \u0b95\u0bbe\u0b9f\u0bcd\u0b9f\u0bc1','\u0e41\u0e2a\u0e14\u0e07\u0e0a\u0e37\u0e48\u0e2d\u0e41\u0e25\u0e30\u0e44\u0e2d\u0e04\u0e2d\u0e19\u0e23\u0e38\u0e48\u0e19 AI','AI model ad\u0131n\u0131 ve simgesini g\u00f6ster','\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u043d\u0430\u0437\u0432\u0443 \u0442\u0430 \u0456\u043a\u043e\u043d\u043a\u0443 \u043c\u043e\u0434\u0435\u043b\u0456 AI','Hi\u1ec3n th\u1ecb t\u00ean v\u00e0 bi\u1ec3u t\u01b0\u1ee3ng m\u00f4 h\u00ecnh AI','\u5728\u754c\u9762\u4e0a\u663e\u793a AI \u6a21\u578b\u540d\u79f0\u548c\u56fe\u6807','\u5728\u754c\u9762\u4e0a\u986f\u793a AI \u6a21\u578b\u540d\u7a31\u548c\u5716\u6a19'],
        about_title: ['\u2139\ufe0f \u062d\u0648\u0644 Synerx AI','\u041e\u0442\u043d\u043e\u0441\u043d\u043e Synerx AI','\u09b8\u09ae\u09cd\u09aa\u09b0\u09cd\u0995\u09c7','O aplikaci','Om','\u2139\ufe0f \u00dcber Synerx AI','\u03a3\u03c7\u03b5\u03c4\u03b9\u03ba\u03ac \u03bc\u03b5','\u2139\ufe0f About Synerx AI','\u2139\ufe0f About Synerx AI','\u2139\ufe0f About Synerx AI','\u2139\ufe0f Acerca de Synerx AI','\u062f\u0631\u0628\u0627\u0631\u0647 Synerx AI','Tietoja','Tungkol sa Synerx AI','\u2139\ufe0f \u00c0 propos de Synerx AI','\u05d0\u05d5\u05d3\u05d5\u05ea Synerx AI','Synerx AI \u0915\u0947 \u092c\u093e\u0930\u0947 \u092e\u0947\u0902','O Synerx AI','N\u00E9vjegy','\u2139\ufe0f Tentang Synerx AI','\u2139\ufe0f Info su Synerx AI','\u2139\ufe0f Synerx AI \u306b\u3064\u3044\u3066','\u2139\ufe0f Synerx AI \uc815\ubcf4','\u2139\ufe0f Perihal Synerx AI','Om','\u2139\ufe0f Over Synerx AI','\u2139\ufe0f O Synerx AI','\u2139\ufe0f Sobre o Synerx AI','Despre','\u2139\ufe0f \u041e Synerx AI','O Synerx AI','\u2139\ufe0f Om Synerx AI','Kuhusu Synerx AI','Synerx AI \u0baa\u0bb1\u0bcd\u0bb1\u0bbf','\u2139\ufe0f \u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a Synerx AI','\u2139\ufe0f Synerx AI Hakk\u0131nda','\u2139\ufe0f \u041f\u0440\u043e Synerx AI','\u2139\ufe0f V\u1ec1 Synerx AI','\u2139\ufe0f \u5173\u4e8e Synerx AI','\u2139\ufe0f \u95dc\u65bc Synerx AI'],
        about_version: ['\u0627\u0644\u0625\u0635\u062f\u0627\u0631','\u0412\u0435\u0440\u0441\u0438\u044f','\u09b8\u0982\u09b8\u09cd\u0995\u09b0\u09a3','Verze','Version','Version','\u0388\u03ba\u03b4\u03bf\u03c3\u03b7','Version','Version','Version','Versi\u00f3n','\u0646\u0633\u062e\u0647','Versio','Bersyon','Version','\u05d2\u05e8\u05e1\u05d4','\u0938\u0902\u0938\u094d\u0915\u0930\u0923','Verzija','Verzi\u00F3','Versi','Versione','\u30d0\u30fc\u30b8\u30e7\u30f3','\ubc84\uc804','Versi','Versjon','Versie','Wersja','Vers\u00e3o','Versiune','\u0412\u0435\u0440\u0441\u0438\u044f','Verzia','Version','Toleo','\u0baa\u0ba4\u0bbf\u0baa\u0bcd\u0baa\u0bc1','\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e0a\u0e31\u0e19','S\u00fcr\u00fcm','\u0412\u0435\u0440\u0441\u0456\u044f','Phi\u00ean b\u1ea3n','\u7248\u672c','\u7248\u672c'],
        about_desc_label: ['\u0627\u0644\u0648\u0635\u0641','\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435','\u09ac\u09bf\u09ac\u09b0\u09a3','Popis','Beskrivelse','Beschreibung','\u03a0\u03b5\u03c1\u03b9\u03b3\u03c1\u03b1\u03c6\u03ae','Description','Description','Description','Descripci\u00f3n','\u062a\u0648\u0636\u06cc\u062d\u0627\u062a','Kuvaus','Paglalarawan','Description','\u05ea\u05d9\u05d0\u05d5\u05e8','\u0935\u093f\u0935\u0930\u0923','Opis','Le\u00EDr\u00E1s','Deskripsi','Descrizione','\u8aac\u660e','\uc124\uba85','Penerangan','Beskrivelse','Beschrijving','Opis','Descri\u00e7\u00e3o','Descriere','\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435','Popis','Beskrivning','Maelezo','\u0bb5\u0bbf\u0bb5\u0bb0\u0bae\u0bcd','\u0e04\u0e33\u0e2d\u0e18\u0e34\u0e1a\u0e32\u0e22','A\u00e7\u0131klama','\u041e\u043f\u0438\u0441','M\u00f4 t\u1ea3','\u8bf4\u660e','\u8aaa\u660e'],
        about_desc_text: ['Synerx AI \u0647\u0648 \u0645\u0633\u0627\u0639\u062f AI \u064a\u062a\u0643\u0627\u0645\u0644 \u0628\u0633\u0644\u0627\u0633\u0629 \u0645\u0639 VS Code.','Synerx AI \u0435 AI \u0430\u0441\u0438\u0441\u0442\u0435\u043d\u0442, \u0441\u044a\u0437\u0434\u0430\u0434\u0435\u043d \u043e\u0442 \u0435\u043a\u0441\u043f\u0435\u0440\u0442\u0438. \u041f\u043e\u043c\u0430\u0433\u0430 \u043a\u0430\u0442\u043e \u0440\u044a\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u0437\u0430 \u0440\u0435\u0448\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0438 \u0441 \u043a\u043e\u0434.','\u0986\u09aa\u09a8\u09be\u09b0 \u09a1\u09c7\u09b8\u09cd\u0995\u099f\u09aa AI \u09b8\u09b9\u0995\u09be\u09b0\u09c0','Synerx AI \u2014 Inteligentn\u00ED v\u00FDvojov\u00FD n\u00E1stroj poh\u00E1n\u011Bn\u00FD AI','Synerx AI \u2014 Intelligent AI-drevet udviklingsv\u00E6rkt\u00F8j','Synerx AI ist ein Open-Source MCP-Server f\u00fcr interaktives AI-Agent-Feedback.','\u039f AI \u03b2\u03bf\u03b7\u03b8\u03cc\u03c2 \u03c3\u03b1\u03c2 \u03c3\u03b5 desktop','Synerx AI is an open-source MCP (Model Context Protocol) server that provides AI Agent interactive feedback. Supports text and image feedback to help AI better understand your needs.','Synerx AI is an open-source MCP (Model Context Protocol) server that provides AI Agent interactive feedback. Supports text and image feedback to help AI better understand your needs.','Synerx AI is an open-source MCP (Model Context Protocol) server that provides AI Agent interactive feedback. Supports text and image feedback to help AI better understand your needs.','Synerx AI es un servidor MCP de c\u00f3digo abierto para retroalimentaci\u00f3n interactiva de AI Agent.','Synerx AI \u06cc\u06a9 \u062f\u0633\u062a\u06cc\u0627\u0631 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0627\u0633\u062a \u06a9\u0647 \u062a\u0648\u0633\u0637 \u0645\u062a\u062e\u0635\u0635\u0627\u0646 \u0633\u0627\u062e\u062a\u0647 \u0634\u062f\u0647 \u0627\u0633\u062a. \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0631\u0627\u0647\u0646\u0645\u0627\u06cc \u062d\u0644 \u0645\u0634\u06a9\u0644\u0627\u062a \u06a9\u062f\u0646\u0648\u06cc\u0633\u06cc \u06a9\u0645\u06a9 \u0645\u06cc\u200c\u06a9\u0646\u062f.','Synerx AI \u2014 \u00C4lyk\u00E4s teko\u00E4lypohjainen kehitysty\u00F6kalu','Ang Synerx AI ay isang AI assistant na seamlessly nag-iintegrate sa VS Code.','Synerx AI est un serveur MCP open-source pour le feedback interactif d\x27AI Agent.','Synerx AI \u05d4\u05d5\u05d0 \u05e2\u05d5\u05d6\u05e8 AI \u05e9\u05e0\u05d1\u05e0\u05d4 \u05e2\u05dc \u05d9\u05d3\u05d9 \u05de\u05d5\u05de\u05d7\u05d9\u05dd. \u05de\u05e1\u05d9\u05d9\u05e2 \u05db\u05de\u05d3\u05e8\u05d9\u05da \u05dc\u05e4\u05ea\u05e8\u05d5\u05df \u05d1\u05e2\u05d9\u05d5\u05ea \u05e7\u05d5\u05d3.','Synerx AI \u090f\u0915 AI \u0938\u0939\u093e\u092f\u0915 \u0939\u0948 \u091c\u094b VS Code \u0915\u0947 \u0938\u093e\u0925 \u0928\u093f\u0930\u094d\u092c\u093e\u0927 \u0930\u0942\u092a \u0938\u0947 \u090f\u0915\u0940\u0915\u0943\u0924 \u0939\u094b\u0924\u093e \u0939\u0948\u0964','Synerx AI je AI asistent koji su izradili stru\u010dnjaci. Poma\u017ee kao vodi\u010d za rje\u0161avanje problema s kodom.','Synerx AI \u2014 Intelligens AI-vez\u00E9relt fejleszt\u0151eszk\u00F6z','Synerx AI adalah server MCP sumber terbuka untuk umpan balik interaktif AI Agent.','Synerx AI \u00e8 un server MCP open-source per il feedback interattivo di AI Agent.','Synerx AI\u306f\u30aa\u30fc\u30d7\u30f3\u30bd\u30fc\u30b9\u306eMCP\u30b5\u30fc\u30d0\u30fc\u3067\u3001AI Agent\u306e\u30a4\u30f3\u30bf\u30e9\u30af\u30c6\u30a3\u30d6\u30d5\u30a3\u30fc\u30c9\u30d0\u30c3\u30af\u6a5f\u80fd\u3092\u63d0\u4f9b\u3057\u307e\u3059\u3002','Synerx AI\ub294 AI Agent \uc778\ud130\ub799\ud2f0\ube0c \ud53c\ub4dc\ubc31\uc744 \uc81c\uacf5\ud558\ub294 \uc624\ud508\uc18c\uc2a4 MCP \uc11c\ubc84\uc785\ub2c8\ub2e4.','Synerx AI ialah pelayan MCP sumber terbuka untuk maklum balas interaktif AI Agent.','Synerx AI \u2014 Intelligent AI-drevet utviklingsverkt\u00F8y','Synerx AI is een open-source MCP-server voor interactieve AI Agent-feedback.','Synerx AI to serwer MCP open-source do interaktywnej informacji zwrotnej AI Agent.','Synerx AI \u00e9 um servidor MCP de c\u00f3digo aberto para feedback interativo de AI Agent.','Synerx AI \u2014 Instrument de dezvoltare inteligent alimentat de AI','Synerx AI \u2014 open-source MCP-\u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438 AI Agent.','Synerx AI je AI asistent vytvoren\u00fd odborn\u00edkmi. Pom\u00e1ha ako sprievodca rie\u0161en\u00edm probl\u00e9mov s k\u00f3dom.','Synerx AI \u00e4r en MCP-server med \u00f6ppen k\u00e4llkod f\u00f6r interaktiv AI Agent-feedback.','Synerx AI ni msaidizi wa AI aliyeundwa na wataalamu. Anasaidia kama mwongozo wa kutatua matatizo ya msimbo.','Synerx AI \u0b92\u0bb0\u0bc1 \u0ba8\u0bbf\u0baa\u0bc1\u0ba3\u0bb0\u0bcd\u0b95\u0bb3\u0bbe\u0bb2\u0bcd \u0b89\u0bb0\u0bc1\u0bb5\u0bbe\u0b95\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0b9f\u0bcd\u0b9f AI \u0b89\u0ba4\u0bb5\u0bbf\u0baf\u0bbe\u0bb3\u0bb0\u0bcd. \u0b89\u0b99\u0bcd\u0b95\u0bb3\u0bcd \u0b95\u0bc1\u0bb1\u0bbf\u0baf\u0bc0\u0b9f\u0bcd\u0b9f\u0bc1 \u0ba4\u0bc0\u0bb0\u0bcd\u0bb5\u0bc1\u0b95\u0bb3\u0bbf\u0ba9\u0bcd \u0bb5\u0bb4\u0bbf\u0b95\u0bbe\u0b9f\u0bcd\u0b9f\u0bbf\u0baf\u0bbe\u0b95 \u0b89\u0ba4\u0bb5\u0bc1\u0b95\u0bbf\u0bb1\u0ba4\u0bc1.','Synerx AI \u0e40\u0e1b\u0e47\u0e19\u0e40\u0e0b\u0e34\u0e23\u0e4c\u0e1f\u0e40\u0e27\u0e2d\u0e23\u0e4c MCP \u0e42\u0e2d\u0e40\u0e1e\u0e19\u0e0b\u0e2d\u0e23\u0e4c\u0e2a','Synerx AI,AI Agent etkile\u015fimli geri bildirimi i\u00e7in a\u00e7\u0131k kaynakl\u0131 bir MCP sunucusudur.','Synerx AI \u2014 \u0446\u0435 MCP-\u0441\u0435\u0440\u0432\u0435\u0440 \u0437 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438\u043c \u043a\u043e\u0434\u043e\u043c \u0434\u043b\u044f \u0456\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0437\u0432\u043e\u0440\u043e\u0442\u043d\u043e\u0433\u043e \u0437\u0432\x27\u044f\u0437\u043a\u0443 AI Agent.','Synerx AI l\u00e0 m\u00e1y ch\u1ee7 MCP m\u00e3 ngu\u1ed3n m\u1edf cho ph\u1ea3n h\u1ed3i t\u01b0\u01a1ng t\u00e1c AI Agent.','Synerx AI \u662f\u4e00\u4e2a\u5f00\u6e90\u7684 MCP (Model Context Protocol) \u670d\u52a1\u5668\uff0c\u63d0\u4f9b AI Agent \u4ea4\u4e92\u5f0f\u53cd\u9988\u529f\u80fd\u3002\u652f\u6301\u6587\u5b57\u548c\u56fe\u7247\u53cd\u9988\uff0c\u5e2e\u52a9 AI \u66f4\u597d\u5730\u7406\u89e3\u60a8\u7684\u9700\u6c42\u3002','Synerx AI \u662f\u4e00\u500b\u958b\u6e90\u7684 MCP (Model Context Protocol) \u670d\u52a1\u5668\uff0c\u63d0\u4f9b AI Agent \u4e92\u52d5\u5f0f\u56de\u994b\u529f\u80fd\u3002'],
        about_license: ['\u0627\u0644\u062a\u0631\u062e\u064a\u0635','\u041b\u0438\u0446\u0435\u043d\u0437','\u09b2\u09be\u0987\u09b8\u09c7\u09a8\u09cd\u09b8','Licence','Licens','Lizenz','\u0386\u03b4\u03b5\u03b9\u03b1','License','License','License','Licencia','\u0645\u062c\u0648\u0632','Lisenssi','Lisensya','Licence','\u05e8\u05d9\u05e9\u05d9\u05d5\u05df','\u0932\u093e\u0907\u0938\u0947\u0902\u0938','Licenca','Licenc','Lisensi','Licenza','\u30e9\u30a4\u30bb\u30f3\u30b9','\ub77c\uc774\uc120\uc2a4','Lesen','Lisens','Licentie','Licencja','Licen\u00e7a','Licen\u021B\u0103','\u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f','Licencia','Licens','Leseni','\u0b89\u0bb0\u0bbf\u0bae\u0bae\u0bcd','\u0e25\u0e34\u0e02\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c','Lisans','\u041b\u0456\u0446\u0435\u043d\u0437\u0456\u044f','Gi\u1ea5y ph\u00e9p','\u5f00\u6e90\u534f\u8bae','\u958b\u6e90\u5354\u8b70'],
        about_license_desc: ['\u0647\u0630\u0627 \u0627\u0644\u0645\u0646\u062a\u062c \u0628\u0631\u0646\u0627\u0645\u062c \u062a\u062c\u0627\u0631\u064a. \u062c\u0645\u064a\u0639 \u0627\u0644\u062d\u0642\u0648\u0642 \u0645\u062d\u0641\u0648\u0638\u0629.','\u0412\u0441\u0438\u0447\u043a\u0438 \u043b\u0438\u0446\u0435\u043d\u0437\u0438 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0430\u0442 \u043d\u0430 \u0441\u044a\u043e\u0442\u0432\u0435\u0442\u043d\u0438\u0442\u0435 \u0438\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u0438\u0446\u0438.','\u09ac\u09cd\u09af\u0995\u09cd\u09a4\u09bf\u0997\u09a4 \u09ac\u09cd\u09af\u09ac\u09b9\u09be\u09b0','Propriet\u00E1rn\u00ED software \u00B7 V\u0161echna pr\u00E1va vyhrazena','Propriet\u00E6r software \u00B7 Alle rettigheder forbeholdt','MIT License - Frei nutzbar,\u00e4nderbar und verteilbar','\u0399\u03b4\u03b9\u03c9\u03c4\u03b9\u03ba\u03ae \u03c7\u03c1\u03ae\u03c3\u03b7','MIT License - Free to use,modify and distribute','MIT License - Free to use,modify and distribute','MIT License - Free to use,modify and distribute','MIT License - Libre para usar,modificar y distribuir','\u062a\u0645\u0627\u0645 \u0645\u062c\u0648\u0632\u0647\u0627 \u0645\u062a\u0639\u0644\u0642 \u0628\u0647 \u0635\u0627\u062d\u0628\u0627\u0646 \u0645\u0631\u0628\u0648\u0637\u0647 \u0622\u0646\u0647\u0627\u0633\u062a.','Kaupallinen ohjelmisto \u00B7 Kaikki oikeudet pid\u00E4tet\u00E4\u00E4n','Ang produktong ito ay komersyal na software. Lahat ng karapatan ay nakalaan.','MIT License - Libre d\x27utilisation,modification et distribution','\u05db\u05dc \u05d4\u05e8\u05d9\u05e9\u05d9\u05d5\u05e0\u05d5\u05ea \u05e9\u05d9\u05d9\u05db\u05d9\u05dd \u05dc\u05d1\u05e2\u05dc\u05d9\u05d4\u05dd \u05d4\u05de\u05ea\u05d0\u05d9\u05de\u05d9\u05dd.','\u092f\u0939 \u0909\u0924\u094d\u092a\u093e\u0926 \u0935\u093e\u0923\u093f\u091c\u094d\u092f\u093f\u0915 \u0938\u0949\u092b\u093c\u094d\u091f\u0935\u0947\u092f\u0930 \u0939\u0948\u0964 \u0938\u092d\u0940 \u0905\u0927\u093f\u0915\u093e\u0930 \u0938\u0941\u0930\u0915\u094d\u0937\u093f\u0924\u0964','Sve licence pripadaju odgovaraju\u0107im vlasnicima.','V\u00E9dett szoftver \u00B7 Minden jog fenntartva','MIT License - Bebas digunakan,dimodifikasi,dan didistribusikan','MIT License - Libero per utilizzo,modifica e distribuzione','MIT License - \u81ea\u7531\u306b\u4f7f\u7528\u3001\u4fee\u6b63\u3001\u914d\u5e03\u53ef\u80fd','MIT License - \uc790\uc720\ub86d\uac8c \uc0ac\uc6a9,\uc218\uc815 \ubc0f \ubc30\ud3ec \uac00\ub2a5','MIT License - Bebas guna,ubah suai dan edar','Propriet\u00E6r programvare \u00B7 Alle rettigheter forbeholdt','MIT License - Vrij te gebruiken,wijzigen en verspreiden','MIT License - Swobodne u\u017cytkowanie,modyfikacja i dystrybucja','MIT License - Livre para usar,modificar e distribuir','Software proprietar \u00B7 Toate drepturile rezervate','MIT License \u2014 \u0421\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435,\u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0438 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u0435','V\u0161etky licencie patria pr\u00edslu\u0161n\u00fdm vlastn\u00edkom.','MIT License - Fri anv\u00e4ndning,modifiering och distribution','Leseni zote ni mali ya wamiliki wao husika.','\u0b85\u0ba9\u0bc8\u0ba4\u0bcd\u0ba4\u0bc1 \u0b89\u0bb0\u0bbf\u0bae\u0bc8\u0b95\u0bb3\u0bc1\u0bae\u0bcd \u0b85\u0bb5\u0bb0\u0bb5\u0bb0\u0bcd \u0b89\u0b9f\u0bae\u0bc8\u0baf\u0bbe\u0bb3\u0bb0\u0bcd\u0b95\u0bb3\u0bc8\u0b9a\u0bcd \u0b9a\u0bc7\u0bb0\u0bcd\u0ba8\u0bcd\u0ba4\u0ba4\u0bc1.','MIT License - \u0e43\u0e0a\u0e49 \u0e41\u0e01\u0e49\u0e44\u0e02 \u0e41\u0e25\u0e30\u0e41\u0e08\u0e01\u0e08\u0e48\u0e32\u0e22\u0e44\u0e14\u0e49\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e2d\u0e34\u0e2a\u0e23\u0e30','MIT License - \u00d6zg\u00fcrce kullan\u0131m,de\u011fi\u015ftirme ve da\u011f\u0131t\u0131m','MIT License - \u0412\u0456\u043b\u044c\u043d\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u043d\u044f,\u043c\u043e\u0434\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u044f \u0442\u0430 \u0440\u043e\u0437\u043f\u043e\u0432\u0441\u044e\u0434\u0436\u0435\u043d\u043d\u044f','MIT License - T\u1ef1 do s\u1eed d\u1ee5ng,s\u1eeda \u0111\u1ed5i v\u00e0 ph\u00e2n ph\u1ed1i','MIT License - \u81ea\u7531\u4f7f\u7528\u3001\u4fee\u6539\u548c\u5206\u53d1','MIT License - \u81ea\u7531\u4f7f\u7528\u3001\u4fee\u6539\u548c\u5206\u767c'],
        classic_waiting: ['\u0641\u064a \u0627\u0646\u062a\u0638\u0627\u0631 \u0631\u062f AI...','\u0418\u0437\u0447\u0430\u043a\u0432\u0430\u043d\u0435 \u043d\u0430 \u043e\u0442\u0433\u043e\u0432\u043e\u0440 \u043e\u0442 AI...','AI \u0989\u09a4\u09cd\u09a4\u09b0\u09c7\u09b0 \u099c\u09a8\u09cd\u09af \u0985\u09aa\u09c7\u0995\u09cd\u09b7\u09be \u0995\u09b0\u099b\u09c7...','\u010Cek\u00E1n\u00ED na odpov\u011B\u010F AI...','Venter p\u00E5 AI-svar...','Warte auf AI-Bericht...','\u0391\u03bd\u03b1\u03bc\u03bf\u03bd\u03ae \u03b1\u03c0\u03ac\u03bd\u03c4\u03b7\u03c3\u03b7\u03c2 AI...','Waiting for AI report...','Waiting for AI report...','Waiting for AI report...','\u200bEsperando informe AI...','\u062f\u0631 \u0627\u0646\u062a\u0638\u0627\u0631 \u067e\u0627\u0633\u062e AI...','Odotetaan AI-vastausta...','Naghihintay ng AI na sagot...','En attente du rapport IA...','\u05de\u05de\u05ea\u05d9\u05df \u05dc\u05ea\u05d2\u05d5\u05d1\u05ea AI...','AI \u0909\u0924\u094d\u0924\u0930 \u0915\u0940 \u092a\u094d\u0930\u0924\u0940\u0915\u094d\u0937\u093e \u092e\u0947\u0902...','\u010cekanje odgovora AI...','V\u00E1rakoz\u00E1s az AI v\u00E1lasz\u00E1ra...','Menunggu laporan AI...','In attesa del rapporto IA...','\u200bAI\u30ec\u30dd\u30fc\u30c8\u3092\u5f85\u6a5f\u4e2d...','AI \ub9ac\ud3ec\ud2b8 \ub300\uae30 \uc911...','Menunggu laporan AI...','Venter p\u00E5 AI-svar...','Wachten op AI-rapport...','Oczekiwanie na raport AI...','Aguardando relat\u00f3rio IA...','Se a\u0219teapt\u0103 r\u0103spunsul AI...','\u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u043e\u0442\u0447\u0451\u0442\u0430 \u0418\u0418...','\u010cak\u00e1 sa na odpove\u010f AI...','V\u00e4ntar p\u00e5 AI-rapport...','Inasubiri jibu la AI...','AI \u0baa\u0ba4\u0bbf\u0bb2\u0bc1\u0b95\u0bcd\u0b95\u0bbe\u0b95 \u0b95\u0bbe\u0ba4\u0bcd\u0ba4\u0bbf\u0bb0\u0bc1\u0b95\u0bcd\u0b95\u0bbf\u0bb1\u0ba4\u0bc1...','\u0e23\u0e2d\u0e23\u0e32\u0e22\u0e07\u0e32\u0e19 AI...','AI raporu bekleniyor...','\u041e\u0447\u0456\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0432\u0456\u0442\u0443 AI...','\u0110ang ch\u1edd b\u00e1o c\u00e1o AI...','\u7b49\u5f85 AI \u5373\u65f6\u62a5\u544a...','\u7b49\u5f85 AI \u5373\u6642\u5831\u544a...']
    };
    function sxt(key) {
        var lang = (typeof currentLang !== 'undefined') ? currentLang : 'zh-CN';
        var idx = SYNERX_LANGS.indexOf(lang);
        if (idx < 0) idx = 0;
        return (SYNERX_I18N[key] && SYNERX_I18N[key][idx]) || (SYNERX_I18N[key] && SYNERX_I18N[key][0]) || key;
    }

    // ---- Synerx: Reorder tabs, rename, fix language button ----
    function initSynerxTabs() {
        var tabContainer = document.querySelector('.tab-buttons');
        if (!tabContainer) {
            if (initSynerxTabs._retries < 10) {
                initSynerxTabs._retries++;
                setTimeout(initSynerxTabs, 500);
            }
            return;
        }
        var btns = tabContainer.querySelectorAll('.tab-button');
        var langWrap = tabContainer.querySelector('.tab-lang-wrap');
        var chatBtn = null, settingsBtn = null, aboutBtn = null, historyBtn = null;
        for (var i = 0; i < btns.length; i++) {
            var dt = btns[i].getAttribute('data-tab');
            if (dt === 'combined') chatBtn = btns[i];
            else if (dt === 'settings') settingsBtn = btns[i];
            else if (dt === 'about') aboutBtn = btns[i];
            else historyBtn = btns[i];
        }
        if (settingsBtn) settingsBtn.textContent = sxt('settings');
        if (langWrap) {
            var langBtn = langWrap.querySelector('.lang-btn');
            if (langBtn) langBtn.innerHTML = '\uD83C\uDF10 ' + sxt('lang');
        }
        // Reorder: chat, history, language, settings, about
        if (chatBtn) tabContainer.appendChild(chatBtn);
        if (historyBtn) tabContainer.appendChild(historyBtn);
        if (langWrap) tabContainer.appendChild(langWrap);
        if (settingsBtn) tabContainer.appendChild(settingsBtn);
        if (aboutBtn) tabContainer.appendChild(aboutBtn);
    }
    initSynerxTabs._retries = 0;
    setTimeout(initSynerxTabs, 1000);

    // ---- Synerx: Fix chat mode sidebar bottom buttons ----
    function initSynerxSidebarBtns() {
        var sidebar = document.querySelector('.chat-sidebar-bottom');
        if (!sidebar) {
            if (initSynerxSidebarBtns._retries < 10) {
                initSynerxSidebarBtns._retries++;
                setTimeout(initSynerxSidebarBtns, 500);
            }
            return;
        }
        var btns = sidebar.querySelectorAll('.sidebar-bottom-btn');
        var langBtn = sidebar.querySelector('.lang-btn');
        var settingsBtn = null, aboutBtn = null;
        for (var i = 0; i < btns.length; i++) {
            var oc = btns[i].getAttribute('onclick') || '';
            if (oc.indexOf('settings') !== -1) settingsBtn = btns[i];
            else if (oc.indexOf('about') !== -1) aboutBtn = btns[i];
        }
        if (settingsBtn) {
            settingsBtn.innerHTML = sxt('settings');
            settingsBtn.style.fontSize = '14px';
        }
        if (aboutBtn) {
            aboutBtn.innerHTML = sxt('about');
            aboutBtn.style.fontSize = '14px';
        }
        if (langBtn) {
            langBtn.innerHTML = '\uD83C\uDF10 ' + sxt('lang');
            langBtn.style.fontSize = '14px';
            langBtn.style.padding = '6px 8px';
        }
        // Reorder: language, settings, about
        if (langBtn) sidebar.appendChild(langBtn);
        if (settingsBtn) sidebar.appendChild(settingsBtn);
        if (aboutBtn) sidebar.appendChild(aboutBtn);
    }
    initSynerxSidebarBtns._retries = 0;
    setTimeout(initSynerxSidebarBtns, 1000);

    // ---- Synerx: Move attach/send buttons inside textarea (match Vexty layout) ----
    function initSynerxClassicInput() {
        // Find the visible classic-input-row (may be multiple in DOM)
        var rows = document.querySelectorAll('.classic-input-row');
        if (!rows.length) {
            if (initSynerxClassicInput._retries < 20) {
                initSynerxClassicInput._retries++;
                setTimeout(initSynerxClassicInput, 500);
            }
            return;
        }
        for (var ri = 0; ri < rows.length; ri++) {
            var row = rows[ri];
            var ta = row.querySelector('textarea');
            var attachBtn = row.querySelector('.classic-attach-btn');
            var actions = row.querySelector('.classic-input-actions');
            if (!ta) continue;
            row.style.setProperty('display', 'flex', 'important');
            row.style.setProperty('position', 'relative', 'important');
            row.style.setProperty('gap', '0', 'important');
            row.style.setProperty('align-items', 'stretch', 'important');
            ta.style.setProperty('flex', '1', 'important');
            ta.style.setProperty('padding', '12px 56px 12px 16px', 'important');
            ta.style.setProperty('text-align', 'left', 'important');
            ta.style.setProperty('width', '100%%', 'important');
            ta.style.setProperty('box-sizing', 'border-box', 'important');
            if (attachBtn) {
                attachBtn.style.setProperty('position', 'absolute', 'important');
                attachBtn.style.setProperty('left', '10px', 'important');
                attachBtn.style.setProperty('bottom', '10px', 'important');
                attachBtn.style.setProperty('z-index', '2', 'important');
                attachBtn.style.setProperty('width', '36px', 'important');
                attachBtn.style.setProperty('height', '36px', 'important');
                attachBtn.style.setProperty('font-size', '16px', 'important');
            }
            if (actions) {
                actions.style.setProperty('position', 'absolute', 'important');
                actions.style.setProperty('right', '8px', 'important');
                actions.style.setProperty('bottom', '8px', 'important');
                actions.style.setProperty('z-index', '2', 'important');
                actions.style.setProperty('flex-direction', 'row', 'important');
                actions.style.setProperty('gap', '4px', 'important');
            }
            var sendBtn = actions ? actions.querySelector('.classic-send-btn') : null;
            if (sendBtn) {
                sendBtn.style.setProperty('width', '36px', 'important');
                sendBtn.style.setProperty('height', '36px', 'important');
            }
            var stopBtn = actions ? actions.querySelector('.classic-stop-btn') : null;
            if (stopBtn) {
                stopBtn.style.setProperty('display', 'none', 'important');
            }
        }
    }
    initSynerxClassicInput._retries = 0;
    setTimeout(initSynerxClassicInput, 1500);

    // ---- Synerx: Update buttons on language change ----
    function updateSynerxI18n() {
        // Update elements with data-sxt attribute
        var sxtEls = document.querySelectorAll('[data-sxt]');
        for (var i = 0; i < sxtEls.length; i++) {
            var key = sxtEls[i].getAttribute('data-sxt');
            sxtEls[i].textContent = sxt(key);
        }
        // Update About page
        var aboutCards = document.querySelectorAll('.settings-card-title');
        for (var i = 0; i < aboutCards.length; i++) {
            var text = aboutCards[i].textContent;
            if (text.indexOf('Synerx AI') !== -1 && (text.indexOf('\u5173\u4e8e') !== -1 || text.indexOf('\u95dc\u65bc') !== -1 || text.indexOf('About') !== -1 || text.indexOf('\u306b\u3064\u3044\u3066') !== -1 || text.indexOf('\uc815\ubcf4') !== -1 || aboutCards[i].getAttribute('data-sxt') === 'about_title')) {
                aboutCards[i].textContent = sxt('about_title');
                aboutCards[i].setAttribute('data-sxt', 'about_title');
                var card = aboutCards[i].closest('.settings-card') || aboutCards[i].parentElement;
                if (card) {
                    var labels = card.querySelectorAll('.setting-label');
                    var descs = card.querySelectorAll('.setting-description');
                    if (labels.length >= 3 && descs.length >= 3) {
                        labels[0].textContent = sxt('about_version');
                        labels[1].textContent = sxt('about_desc_label');
                        labels[2].textContent = sxt('about_license');
                        descs[1].textContent = sxt('about_desc_text');
                        descs[2].textContent = sxt('about_license_desc');
                    }
                }
                break;
            }
        }
        // Update classic waiting text
        var waitingEls = document.querySelectorAll('#combinedSummaryContent span');
        for (var i = 0; i < waitingEls.length; i++) {
            var t = waitingEls[i].textContent;
            if (t.indexOf('AI') !== -1 && (t.indexOf('\u7b49\u5f85') !== -1 || t.indexOf('Waiting') !== -1 || t.indexOf('\u5f85\u6a5f') !== -1 || t.indexOf('\ub300\uae30') !== -1 || t.indexOf('Warte') !== -1 || waitingEls[i].getAttribute('data-sxt') === 'classic_waiting')) {
                waitingEls[i].textContent = sxt('classic_waiting');
                waitingEls[i].setAttribute('data-sxt', 'classic_waiting');
            }
        }
    }
    function hookSynerxLangChange() {
        var origSelectLang = window.selectLang;
        if (typeof origSelectLang === 'function') {
            window.selectLang = function(lang) {
                origSelectLang(lang);
                setTimeout(function() {
                    initSynerxSidebarBtns._retries = 0;
                    initSynerxSidebarBtns();
                    initSynerxTabs._retries = 0;
                    initSynerxTabs();
                    updateSynerxI18n();
                }, 300);
            };
        }
    }
    setTimeout(hookSynerxLangChange, 2000);
    // Initial translation of About page and waiting text
    setTimeout(updateSynerxI18n, 2000);

    // ---- Synerx: Right-click context menu for classic mode summary area ----
    function synerxCopyText(text) {
        _synerxExecCopy(text);
    }
    function initSynerxContextMenu() {
        var summaryEl = document.getElementById('combinedSummaryContent');
        if (!summaryEl) {
            if (initSynerxContextMenu._retries < 10) {
                initSynerxContextMenu._retries++;
                setTimeout(initSynerxContextMenu, 500);
            }
            return;
        }

        summaryEl.addEventListener('contextmenu', function(e) {
            var existingMenu = document.getElementById('customCtxMenu');
            if (existingMenu && existingMenu.classList.contains('show')) return;

            e.preventDefault();
            e.stopPropagation();

            var sel = window.getSelection();
            var selectedText = (sel && sel.toString().trim().length > 0) ? sel.toString() : '';

            var menu = document.getElementById('synerxCtxMenu');
            if (!menu) {
                menu = document.createElement('div');
                menu.id = 'synerxCtxMenu';
                menu.style.cssText = 'position:fixed;z-index:99999;background:#313244;border:1px solid #585b70;border-radius:8px;padding:4px 0;min-width:140px;box-shadow:0 8px 24px rgba(0,0,0,0.4);display:none;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;';
                document.body.appendChild(menu);

                document.addEventListener('click', function(evt) {
                    if (!evt.target.closest('#synerxCtxMenu')) menu.style.display = 'none';
                });
                document.addEventListener('scroll', function() { menu.style.display = 'none'; }, true);
            }

            var itemStyle = 'padding:8px 16px;cursor:pointer;color:#cdd6f4;font-size:13px;display:flex;align-items:center;gap:8px;';
            var disabledStyle = itemStyle + 'opacity:0.4;cursor:default;';
            menu.innerHTML = '<div class="sctx-item' + (selectedText ? '' : ' sctx-disabled') + '" data-action="copy" style="' + (selectedText ? itemStyle : disabledStyle) + '"><span>\uD83D\uDCCB</span>\u590D\u5236</div>'
                + '<div style="height:1px;background:#585b70;margin:4px 0;"></div>'
                + '<div class="sctx-item" data-action="selectAll" style="' + itemStyle + '"><span>\u2606</span>\u5168\u9009</div>';

            var items = menu.querySelectorAll('.sctx-item:not(.sctx-disabled)');
            for (var i = 0; i < items.length; i++) {
                items[i].onmouseenter = function() { this.style.background = 'rgba(137,180,250,0.15)'; };
                items[i].onmouseleave = function() { this.style.background = 'transparent'; };
            }

            menu.style.left = Math.min(e.clientX, window.innerWidth - 160) + 'px';
            menu.style.top = Math.min(e.clientY, window.innerHeight - 100) + 'px';
            menu.style.display = 'block';

            // Store text for use in click handler (selection may be cleared by click)
            menu._savedText = selectedText;

            menu.onclick = function(evt) {
                var target = evt.target.closest('.sctx-item');
                if (!target || target.classList.contains('sctx-disabled')) return;
                var action = target.dataset.action;
                if (action === 'copy') {
                    var text = menu._savedText || '';
                    if (text) {
                        synerxCopyText(text);
                    }
                } else if (action === 'selectAll') {
                    var range = document.createRange();
                    range.selectNodeContents(summaryEl);
                    var s = window.getSelection();
                    s.removeAllRanges();
                    s.addRange(range);
                }
                menu.style.display = 'none';
            };
        }, true);
    }
    initSynerxContextMenu._retries = 0;
    setTimeout(initSynerxContextMenu, 1000);

    // ---- Synerx: Model display toggle (injected into settings page) ----
    function initSynerxModelToggle() {
        // Find the Interface Settings card body
        var settingsCards = document.querySelectorAll('.settings-card-body');
        if (!settingsCards.length) {
            if (initSynerxModelToggle._retries < 15) {
                initSynerxModelToggle._retries++;
                setTimeout(initSynerxModelToggle, 500);
            }
            return;
        }
        // Find the card that contains setting-chat_style or setting-bg_color (Interface card)
        var targetCard = null;
        for (var i = 0; i < settingsCards.length; i++) {
            if (settingsCards[i].querySelector('#setting-chat_style') || settingsCards[i].querySelector('#setting-bg_color')) {
                targetCard = settingsCards[i];
                break;
            }
        }
        if (!targetCard) {
            if (initSynerxModelToggle._retries < 15) {
                initSynerxModelToggle._retries++;
                setTimeout(initSynerxModelToggle, 500);
            }
            return;
        }
        // Check if already injected
        if (document.getElementById('setting-synerx_model_display')) return;

        // Create the setting-item HTML
        var item = document.createElement('div');
        item.className = 'setting-item';
        item.style.borderBottom = 'none';
        item.innerHTML = '<div class="setting-info">' +
            '<div class="setting-label" data-sxt="model_display">' + sxt('model_display') + '</div>' +
            '<div class="setting-description" data-sxt="model_display_desc">' + sxt('model_display_desc') + '</div>' +
            '</div>' +
            '<div class="setting-control">' +
            '<label class="toggle-switch">' +
            '<input type="checkbox" id="setting-synerx_model_display" checked>' +
            '<span class="toggle-slider"></span>' +
            '</label>' +
            '</div>';
        targetCard.appendChild(item);

        // Restore saved state
        var saved = localStorage.getItem('synerxShowModel');
        var checkbox = document.getElementById('setting-synerx_model_display');
        if (saved === '0') {
            document.body.classList.add('hide-model');
            if (checkbox) checkbox.checked = false;
        }

        // Add change handler
        if (checkbox) {
            checkbox.addEventListener('change', function() {
                var show = this.checked;
                document.body.classList.toggle('hide-model', !show);
                localStorage.setItem('synerxShowModel', show ? '1' : '0');
            });
        }
    }
    initSynerxModelToggle._retries = 0;
    setTimeout(initSynerxModelToggle, 1500);

    // Apply saved model visibility on page load (before settings card renders)
    (function() {
        var saved = localStorage.getItem('synerxShowModel');
        if (saved === '0') {
            document.body.classList.add('hide-model');
        }
    })();

    // ---- Synerx: Replace Claude "//" icon with starburst ----
    var _synerxStarburst = '<g stroke="#d4a27f" stroke-width="2.8" stroke-linecap="round"><line x1="12" y1="12" x2="12" y2="1.5"/><line x1="12" y1="12" x2="16.9" y2="4.4"/><line x1="12" y1="12" x2="21.5" y2="7.7"/><line x1="12" y1="12" x2="20.2" y2="14.2"/><line x1="12" y1="12" x2="18" y2="19.3"/><line x1="12" y1="12" x2="12.9" y2="22"/><line x1="12" y1="12" x2="7.5" y2="19.8"/><line x1="12" y1="12" x2="2.5" y2="16.4"/><line x1="12" y1="12" x2="4.3" y2="9.9"/><line x1="12" y1="12" x2="5.9" y2="4.7"/></g>';
    var _synerxFullSvg = '<svg class="chat-model-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">' + _synerxStarburst + '</svg>';
    function _synerxFixClaudeIcons() {
        try {
            var all = document.querySelectorAll('svg.chat-model-icon');
            for (var i = 0; i < all.length; i++) {
                if (all[i].innerHTML.indexOf('M17.308') !== -1) {
                    all[i].innerHTML = _synerxStarburst;
                }
            }
            if (typeof window.getModelIcon === 'function' && !window._synerxIconPatched) {
                window._synerxIconPatched = true;
                var _origIcon = window.getModelIcon;
                window.getModelIcon = function(m) {
                    if (m) {
                        var n = m.toLowerCase();
                        if (n.indexOf('claude') !== -1 || n.indexOf('anthropic') !== -1) {
                            return _synerxFullSvg;
                        }
                    }
                    return _origIcon(m);
                };
            }
        } catch(e) {}
    }
    setInterval(_synerxFixClaudeIcons, 800);
    setTimeout(_synerxFixClaudeIcons, 200);
    setTimeout(_synerxFixClaudeIcons, 500);
  })();
    setTimeout(_synerxFixClaudeIcons, 500);
