My Prompt

Save, edit, delete, import, and export your custom prompts directly in ChatGPT, DeepSeek, Google AI Studio, Qwen, Z.ai, Gemini, LMArena, and Kimi.

تثبيت هذا البرنامج النصي؟
سكربت موصى به للمؤلف

ربما يعجبك أيضا CodeDown.

تثبيت هذا البرنامج النصي
// ==UserScript==
// @name               My Prompt
// @name:en            My Prompt
// @name:pt-BR         Meu Prompt
// @name:es            Mi Prompt
// @name:zh-CN         我的提示
// @namespace          https://github.com/0H4S
// @version            1.4
// @description        Save, edit, delete, import, and export your custom prompts directly in ChatGPT, DeepSeek, Google AI Studio, Qwen, Z.ai, Gemini, LMArena, and Kimi.
// @description:en     Save, edit, delete, import, and export your custom prompts directly in ChatGPT, DeepSeek, Google AI Studio, Qwen, Z.ai, Gemini, LMArena, and Kimi.
// @description:pt-BR  Salve, edite, exclua, importe e exporte seus prompts personalizados diretamente no ChatGPT, DeepSeek, Google AI Studio, Qwen, Z.ai, Gemini, LMArena e Kimi.
// @description:es     Guarda, edita, elimina, importa y exporta tus prompts personalizados directamente en ChatGPT, DeepSeek, Google AI Studio, Qwen, Z.ai, Gemini, LMArena y Kimi.
// @description:zh-CN  直接在 ChatGPT、DeepSeek、Google AI Studio、Qwen、Z.ai、Gemini、LMArena 和 Kimi 中保存、编辑、删除、导入和导出您的自定义提示。
// @author             OHAS
// @homepage           https://github.com/0H4S
// @icon               https://cdn-icons-png.flaticon.com/512/4997/4997543.png
// @license            CC-BY-NC-ND-4.0
// @copyright          2025 OHAS. All Rights Reserved.
// @match              https://chatgpt.com/*
// @match              https://chat.deepseek.com/*
// @match              https://aistudio.google.com/*
// @match              https://chat.qwen.ai/*
// @match              https://chat.z.ai/*
// @match              https://gemini.google.com/*
// @match              https://lmarena.ai/*
// @match              https://www.kimi.com/*
// @require            https://update.greasyfork.org/scripts/549920/Script%20Notifier.js
// @connect            gist.githubusercontent.com
// @grant              GM_getValue
// @grant              GM_setValue
// @grant              GM_registerMenuCommand
// @grant              GM_xmlhttpRequest
// @run-at             document-end
// @compatible         chrome
// @compatible         firefox
// @compatible         edge
// ==/UserScript==

(function() {
    'use strict';
    if (window.top !== window.self) return;
    const translations = {
            'en': {
                langName: 'English',
                prompt: 'Prompt',
                prompts: 'Prompts',
                newPrompt: 'New Prompt',
                editPrompt: 'Edit Prompt',
                title: 'Title',
                text: 'Prompt',
                save: 'Save',
                close: 'Close',
                edit: 'Edit',
                delete: 'Delete',
                noSavedPrompts: 'No saved prompts.',
                addPrompt: 'Add prompt',
                import: 'Import',
                export: 'Export',
                confirmDelete: 'Delete prompt "{title}"?',
                noPromptsToExport: 'No prompts to export.',
                promptsImported: '{count} prompts imported successfully!',
                errorImporting: 'Error importing file: {error}',
                requiredFields: 'Title and prompt are required.',
                editorNotFound: 'Could not find the text area for {platform}.',
                languageSettings: '🌐 Language',
                fileName: 'My Prompts.json'
            },
            'es': {
                langName: 'Español',
                prompt: 'Prompt',
                prompts: 'Prompts',
                newPrompt: 'Nuevo Prompt',
                editPrompt: 'Editar Prompt',
                title: 'Título',
                text: 'Prompt',
                save: 'Guardar',
                close: 'Cerrar',
                edit: 'Editar',
                delete: 'Eliminar',
                noSavedPrompts: 'No hay prompts guardados.',
                addPrompt: 'Añadir prompt',
                import: 'Importar',
                export: 'Exportar',
                confirmDelete: '¿Eliminar prompt "{title}"?',
                noPromptsToExport: 'No hay prompts para exportar.',
                promptsImported: '¡{count} prompts importados con éxito!',
                errorImporting: 'Error al importar el archivo: {error}',
                requiredFields: 'El título y el prompt son obligatorios.',
                editorNotFound: 'No se pudo encontrar el área de texto para {platform}.',
                languageSettings: '🌐 Idioma',
                fileName: 'Mis Prompts.json'
            },
            'pt-BR': {
                langName: 'Português (BR)',
                prompt: 'Prompt',
                prompts: 'Prompts',
                newPrompt: 'Novo Prompt',
                editPrompt: 'Editar Prompt',
                title: 'Título',
                text: 'Prompt',
                save: 'Salvar',
                close: 'Fechar',
                edit: 'Editar',
                delete: 'Excluir',
                noSavedPrompts: 'Nenhum prompt salvo.',
                addPrompt: 'Adicionar prompt',
                import: 'Importar',
                export: 'Exportar',
                confirmDelete: 'Excluir prompt "{title}"?',
                noPromptsToExport: 'Não há prompts para exportar.',
                promptsImported: '{count} prompts importados com sucesso!',
                errorImporting: 'Erro ao importar o arquivo: {error}',
                requiredFields: 'Título e prompt são obrigatórios.',
                editorNotFound: 'Não foi possível encontrar a área de texto para {platform}.',
                languageSettings: '🌐 Idioma',
                fileName: 'Meus Prompts.json'
            },
            'zh-CN': {
                langName: '简体中文',
                prompt: '提示',
                prompts: '提示',
                newPrompt: '新建提示',
                editPrompt: '编辑提示',
                title: '标题',
                text: '提示内容',
                save: '保存',
                close: '关闭',
                edit: '编辑',
                delete: '删除',
                noSavedPrompts: '没有已保存的提示。',
                addPrompt: '添加提示',
                import: '导入',
                export: '导出',
                confirmDelete: '确定要删除提示 "{title}" 吗?',
                noPromptsToExport: '沒有可導出的提示。',
                promptsImported: '成功导入 {count} 个提示!',
                errorImporting: '导入文件时出错: {error}',
                requiredFields: '标题和提示内容为必填项。',
                editorNotFound: '未能找到 {platform} 的文本输入区域。',
                languageSettings: '🌐 语言',
                fileName: '我的提示.json'
            }
    };
    const LANG_STORAGE_KEY = 'UserScriptLang';
    let currentLang = 'en';

    const SCRIPT_CONFIG = {
        notificationsUrl: 'https://gist.githubusercontent.com/0H4S/40b2a2feb2ba18d0bf63a1943ba5cec3/raw/my_prompt_notifications.json',
        scriptVersion: '1.4',
    };
    const notifier = new ScriptNotifier(SCRIPT_CONFIG);
    notifier.run();

    const PROMPT_STORAGE_KEY = 'Prompts';
    let isInitialized = false;
    let isInitializing = false;
    let currentButton = null;
    let currentPlatform = null;
    let pageObserver = null;
    let currentMenu = null;
    let currentModal = null;
    let languageModal = null;

    const scriptPolicy = window.trustedTypes
        ? window.trustedTypes.createPolicy('MyPromptPolicy', { createHTML: (input) => input })
        : null;

    function setSafeInnerHTML(element, html) {
        if (!element) return;
        if (scriptPolicy) {
            element.innerHTML = scriptPolicy.createHTML(html);
        } else {
            element.innerHTML = html;
        }
    }

    function getTranslation(key, replacements = {}) {
        let text = translations[currentLang]?.[key] || translations.en[key];
        Object.entries(replacements).forEach(([p, v]) => text = text.replace(`{${p}}`, v));
        return text;
    }

    async function determineLanguage() {
        const savedLang = await GM_getValue(LANG_STORAGE_KEY);
        if (savedLang && translations[savedLang]) {
            currentLang = savedLang;
            return;
        }
        const browserLang = (navigator.language || navigator.userLanguage).toLowerCase();
        if (browserLang.startsWith('pt')) currentLang = 'pt-BR';
        else if (browserLang.startsWith('es')) currentLang = 'es';
        else if (browserLang.startsWith('zh')) currentLang = 'zh-CN';
        else currentLang = 'en';
    }

    function waitFor(selector, timeout = 8000) {
        return new Promise((resolve, reject) => {
            const el = document.querySelector(selector);
            if (el) { resolve(el); return; }
            const timer = setTimeout(() => { obs.disconnect(); reject(`Timeout esperando por ${selector}`); }, timeout);
            const obs = new MutationObserver(() => {
                const target = document.querySelector(selector);
                if (target) { clearTimeout(timer); obs.disconnect(); resolve(target); }
            });
            if (document.body) obs.observe(document.body, { childList: true, subtree: true });
            else document.addEventListener('DOMContentLoaded', () => obs.observe(document.body, { childList: true, subtree: true }));
        });
    }

    const debounce = (func, wait) => {
        let timeout;
        return (...args) => {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    };

    async function getAll() { return await GM_getValue(PROMPT_STORAGE_KEY, []); }
    async function addItem(item) {
        const prompts = await getAll();
        prompts.unshift(item);
        await GM_setValue(PROMPT_STORAGE_KEY, prompts);
    }
    async function update(index, item) {
        let prompts = await getAll();
        if (prompts[index]) {
            prompts[index] = item;
            await GM_setValue(PROMPT_STORAGE_KEY, prompts);
        }
    }
    async function remove(index) {
        let prompts = await getAll();
        prompts.splice(index, 1);
        await GM_setValue(PROMPT_STORAGE_KEY, prompts);
    }

    function createCustomTooltip(button, text, position = 'top') {
        let tooltipElement = null;
		const showTooltip = () => {
		  if (tooltipElement) return;
		  tooltipElement = document.createElement('div');
          tooltipElement.className = 'mp-tooltip';
		  tooltipElement.textContent = text;
		  
		  document.body.appendChild(tooltipElement);
		  const btnRect = button.getBoundingClientRect();
		  const tooltipRect = tooltipElement.getBoundingClientRect();
		  let top;
		  const margin = 8;
		  if (position === 'bottom') {
			top = btnRect.bottom + margin;
			if (top + tooltipRect.height > window.innerHeight) {
			  top = btnRect.top - tooltipRect.height - margin;
			}
		  } else {
			top = btnRect.top - tooltipRect.height - margin;
			if (top < 0) {
			  top = btnRect.bottom + margin;
			}
		  }
		  let left = btnRect.left + (btnRect.width / 2) - (tooltipRect.width / 2);
		  if (left < 0) { left = margin; }
		  if (left + tooltipRect.width > window.innerWidth) { left = window.innerWidth - tooltipRect.width - margin; }
		  tooltipElement.style.left = `${left}px`;
		  tooltipElement.style.top = `${top}px`;

          requestAnimationFrame(() => {
			tooltipElement.classList.add('visible');
		  });
		};
		const hideTooltip = () => {
		  if (!tooltipElement) return;
		  const el = tooltipElement;
		  tooltipElement = null;
		  el.classList.remove('visible');
		  setTimeout(() => {
			if (document.body.contains(el)) {
			  document.body.removeChild(el);
			}
		  }, 150);
		};
		button.addEventListener('mouseenter', showTooltip);
		button.addEventListener('mouseleave', hideTooltip);
		button.addEventListener('mousedown', hideTooltip);
    }

    function createChatGPTButton() {
        const btn = document.createElement('button');
        btn.type = 'button';
        btn.setAttribute('data-testid', 'composer-button-prompts');
        btn.className = 'composer-btn';
        setSafeInnerHTML(btn, `<svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M4 5h12M4 10h12M4 15h12" stroke="currentColor" stroke-width="2"/></svg>`);
        createCustomTooltip(btn, getTranslation('prompts'));
        return btn;
    }

    function createDeepSeekButton() {
        const btn = document.createElement('button');
        btn.setAttribute('data-testid', 'composer-button-prompts');
        setSafeInnerHTML(btn, `<div class="ds-icon" style="font-size: 17px; width: 17px; height: 17px; color: currentColor; margin-right: 6px;"><svg width="20" height="20" fill="currentColor" viewBox="0 0 20 20"><path d="M4 5h12M4 10h12M4 15h12" stroke="currentColor" stroke-width="2"/></svg></div><span><span class="_6dbc175">${getTranslation('prompt')}</span></span>`);
        return btn;
    }

    function createGoogleStudioButton() {
        const styleId = 'my-prompt-gstudio-hover-fix';
        if (!document.getElementById(styleId)) {
            const styleElement = document.createElement('style');
            styleElement.id = styleId;
            setSafeInnerHTML(styleElement, `
                button[data-testid="composer-button-prompts"]:hover {
                background-color: rgba(60, 64, 67, 0.08) !important;
                }
                @media (prefers-color-scheme: dark) {
                    button[data-testid="composer-button-prompts"]:hover {
                        background-color: rgba(232, 234, 237, 0.08) !important;
                    }
                }
            `);
            document.head.appendChild(styleElement);
        }
        const btn = document.createElement('button');
        btn.setAttribute('data-testid', 'composer-button-prompts');
        btn.type = 'button';
        btn.style.backgroundColor = 'transparent';
        btn.style.border = 'none';
        btn.style.boxShadow = 'none';
        btn.style.borderRadius = '50%';
        btn.style.width = '48px';
        btn.style.height = '48px';
        btn.style.padding = '0';
        btn.style.margin = '0';
        btn.style.cursor = 'pointer';
        btn.style.display = 'inline-flex';
        btn.style.alignItems = 'center';
        btn.style.justifyContent = 'center';
        btn.style.transition = 'background-color 150ms ease-in-out';
        setSafeInnerHTML(btn, `<svg fill="currentColor" style="width: 24px; height: 24px;" viewBox="0 0 100 100"><g><path d="M17.563,30.277h0.012c0,1.245,1.004,2.254,2.246,2.267v0.002h60.359v-0.001c1.248-0.006,2.259-1.018,2.259-2.268h0.01 l0-10.459h0c-0.002-1.251-1.017-2.265-2.269-2.265l0,0H19.821v0c0,0,0,0,0,0c-1.253,0-2.269,1.017-2.269,2.269 c0,0.039,0.01,0.076,0.012,0.115L17.563,30.277z"/><path d="M80.179,42.504L80.179,42.504H19.821v0c0,0,0,0,0,0c-1.253,0-2.269,1.017-2.269,2.269c0,0.039,0.01,0.076,0.012,0.115 l0,10.34h0.012c0,1.245,1.004,2.254,2.246,2.267v0.002h60.359v-0.001c1.248-0.006,2.259-1.018,2.259-2.268h0.01l0-10.459h0 C82.446,43.518,81.431,42.504,80.179,42.504z"/><path d="M80.179,67.454L80.179,67.454H19.821l0,0c0,0,0,0,0,0c-1.253,0-2.269,1.017-2.269,2.269c0,0.039,0.01,0.076,0.012,0.115 l0,10.34h0.012c0,1.245,1.004,2.254,2.246,2.267v0.002h60.359v-0.001c1.248-0.006,2.259-1.019,2.259-2.269h0.01l0-10.459h0 C82.446,68.468,81.431,67.454,80.179,67.454z"/></g></svg>`);
        createCustomTooltip(btn, getTranslation('prompts'));
        return btn;
    }

    function createQwenButton() {
        const btn = document.createElement('button');
        btn.className = 'chat-input-feature-btn';
        btn.setAttribute('data-testid', 'composer-button-prompts');
        setSafeInnerHTML(btn, `<svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg" class="chat-input-feature-btn-icon" style="font-size: 16px;"><path d="M4 5h12M4 10h12M4 15h12" stroke="currentColor" stroke-width="2"/></svg><span class="chat-input-feature-btn-text">${getTranslation('prompt')}</span>`);
        return btn;
    }

    function createZaiButton() {
        const btnWrapper = document.createElement('div');
        setSafeInnerHTML(btnWrapper, `<button type="button" class="px-2 @xl:px-3 py-1.5 flex gap-1.5 items-center text-sm rounded-lg border transition-colors duration-300 focus:outline-hidden max-w-full overflow-hidden bg-transparent dark:text-gray-300 border-[#E5E5E5] dark:border-[#3C3E3F] hover:bg-black/5 dark:hover:bg-white/5"><svg class=" size-4" stroke-width="2" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9 17L3 12L9 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 17L21 12L15 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="hidden @sm:block whitespace-nowrap overflow-hidden text-ellipsis translate-y-[0.5px] mr-0.5">${getTranslation('prompt')}</span></button>`);
        const btn = btnWrapper.firstElementChild;
        btn.setAttribute('data-testid', 'composer-button-prompts');
        return btn;
    }

    function createGeminiButton() {
        const btn = document.createElement('button');
        btn.setAttribute('data-testid', 'composer-button-prompts');
        btn.className = 'mdc-icon-button mat-mdc-icon-button mat-mdc-button-base mat-primary mat-mdc-tooltip-trigger';
        const svgHTML = `<span class="mat-mdc-button-persistent-ripple mdc-icon-button__ripple"></span><span class="mat-icon notranslate" style="display: inline-flex; align-items: center; justify-content: center;"><svg style="width: 24px; height: 24px;" viewBox="0 0 20 20" fill="currentColor"><path d="M4 5h12M4 10h12M4 15h12" stroke="currentColor" stroke-width="2"></path></svg></span><span class="mat-focus-indicator"></span><span class="mat-mdc-button-touch-target"></span><span class="mat-ripple mat-mdc-button-ripple"></span>`;

        setSafeInnerHTML(btn, svgHTML);
        createCustomTooltip(btn, getTranslation('prompt'), 'bottom');
        return btn;
    }

    function createLmarenaButton() {
        const btn = document.createElement('button');
        btn.setAttribute('data-testid', 'composer-button-prompts');
        btn.className = 'inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ring-offset-2 focus-visible:ring-offset-surface-primary disabled:pointer-events-none disabled:opacity-50 text-interactive-active border border-border-faint bg-transparent hover:text-interactive-normal active:text-text-tertiary h-8 w-8 p-2 rounded-md active:scale-[0.96] active:transition-transform active:duration-75 transition-colors duration-150 ease-out hover:shadow-sm hover:bg-interactive-normal/10 hover:border-interactive-normal/10';
        btn.type = 'button';
        setSafeInnerHTML(btn, `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 20 20" fill="currentColor" class="w-4 h-4"><path d="M4 5h12M4 10h12M4 15h12" stroke="currentColor" stroke-width="2"/></svg>`);
        createCustomTooltip(btn, getTranslation('prompt'));
        return btn;
    }

    function createKimiButton() {
        const referenceButton = document.querySelector('.deep-research-switch.normal');
        if (!referenceButton) {
            console.warn('My Prompt: Botão de referência para clonagem não encontrado no Kimi.');
            return null;
        }
        const btn = referenceButton.cloneNode(true);
        btn.setAttribute('data-testid', 'composer-button-prompts');
        const oldSvg = btn.querySelector('svg');
        const textSpan = btn.querySelector('span');
        const newSvgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
        if (oldSvg) newSvgElement.setAttribute('class', oldSvg.getAttribute('class'));
        newSvgElement.setAttribute('width', '1em');
        newSvgElement.setAttribute('height', '1em');
        newSvgElement.setAttribute('viewBox', '0 0 20 20');
        newSvgElement.setAttribute('fill', 'currentColor');
        setSafeInnerHTML(newSvgElement, `<path d="M4 5h12M4 10h12M4 15h12" stroke="currentColor" stroke-width="2"/>`);
        if (oldSvg) {
            oldSvg.replaceWith(newSvgElement);
        }
        if (textSpan) {
            textSpan.textContent = getTranslation('prompt');
        }
        return btn;
    }

    function injectGlobalStyles() {
        const styleId='my-prompt-styles';
        if (document.getElementById(styleId)) return;

        const styleElement=document.createElement('style');
        styleElement.id=styleId;
        setSafeInnerHTML(styleElement, ` @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');

        :root {
            --mp-font-family-base: 'Inter', sans-serif;
            --mp-bg-primary: #fff;
            --mp-bg-secondary: #f8f9fa;
            --mp-bg-tertiary: #f1f3f5;
            --mp-bg-overlay: rgba(10, 10, 10, .5);
            --mp-text-primary: #212529;
            --mp-text-secondary: #495057;
            --mp-text-tertiary: #868e96;
            --mp-border-primary: #dee2e6;
            --mp-border-secondary: #ced4da;
            --mp-accent-primary: #7071fc;
            --mp-accent-primary-hover: #595ac9;
            --mp-accent-yellow: #fab005;
            --mp-accent-yellow-hover: #f08c00;
            --mp-accent-red: #f03e3e;
            --mp-accent-red-hover: #c92a2a;
            --mp-shadow-sm: 0 1px 2px rgba(0, 0, 0, .04);
            --mp-shadow-md: 0 4px 12px rgba(0, 0, 0, .1);
            --mp-shadow-lg: 0 10px 30px rgba(0, 0, 0, .1);
            --mp-border-radius-sm: 4px;
            --mp-border-radius-md: 8px;
            --mp-border-radius-lg: 16px;
            --mp-transition-fast: .2s cubic-bezier(.25, 1, .5, 1)
        }

        @media (prefers-color-scheme:dark) {
            :root {
                --mp-bg-primary: #212529;
                --mp-bg-secondary: #2c2c30;
                --mp-bg-tertiary: #343a40;
                --mp-bg-overlay: rgba(0, 0, 0, .6);
                --mp-text-primary: #f8f9fa;
                --mp-text-secondary: #e9ecef;
                --mp-text-tertiary: #adb5bd;
                --mp-border-primary: #495057;
                --mp-border-secondary: #868e96;
                --mp-shadow-sm: 0 1px 2px rgba(0, 0, 0, .15);
                --mp-shadow-md: 0 4px 12px rgba(0, 0, 0, .25);
                --mp-shadow-lg: 0 10px 30px rgba(0, 0, 0, .3)
            }
        }

        .mp-hidden {
            display: none !important;
        }

        .mp-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: var(--mp-bg-overlay);
            z-index: 2147483647;
            display: flex;
            justify-content: center;
            align-items: center;
            backdrop-filter: blur(4px);
            opacity: 0;
            visibility: hidden;
            transition: opacity var(--mp-transition-fast), visibility var(--mp-transition-fast);
        }

        .mp-overlay.visible {
            opacity: 1;
            visibility: visible;
        }

        .mp-modal-box {
            font-family: var(--mp-font-family-base);
            background-color: var(--mp-bg-primary);
            color: var(--mp-text-primary);
            border-radius: var(--mp-border-radius-lg);
            padding: 24px;
            box-shadow: var(--mp-shadow-lg);
            width: min(90vw, 520px);
            border: 1px solid var(--mp-border-primary);
            transform: scale(.95) translateY(10px);
            opacity: 0;
            transition: transform var(--mp-transition-fast), opacity var(--mp-transition-fast);
            position: relative;
        }

        .mp-overlay.visible .mp-modal-box {
            transform: scale(1) translateY(0);
            opacity: 1;
        }

        .mp-modal-close-btn {
            position: absolute;
            top: 12px;
            right: 12px;
            background: none;
            border: none;
            color: var(--mp-text-tertiary);
            font-size: 22px;
            cursor: pointer;
            width: 32px;
            height: 32px;
            border-radius: 50%;
            transition: transform .3s ease, color .3s ease, background-color .3s ease;
            display: flex;
            justify-content: center;
            align-items: center;
            line-height: 1;
        }

        .mp-modal-close-btn:hover {
            transform: rotate(90deg);
            color: var(--mp-accent-red);
            background-color: color-mix(in srgb, var(--mp-accent-red) 15%, transparent);
        }

        .prompt-menu {
            position: fixed;
            min-width: 320px;
            max-width: 420px;
            background-color: var(--mp-bg-primary);
            border: 1px solid var(--mp-border-primary);
            border-radius: var(--mp-border-radius-lg);
            box-shadow: var(--mp-shadow-lg);
            z-index: 2147483647;
            display: flex;
            flex-direction: column;
            user-select: none;
            color: var(--mp-text-primary);
            font-family: var(--mp-font-family-base);
            overflow: hidden;
            opacity: 0;
            visibility: hidden;
            transform: scale(.95);
            transform-origin: top left;
            transition: opacity .2s ease, transform .2s ease, visibility 0s linear .2s;
        }

        .prompt-menu.visible {
            opacity: 1;
            visibility: visible;
            transform: scale(1);
            transition-delay: 0s;
        }

        .prompt-menu-list {
            max-height: 220px;
            overflow-y: auto;
            padding: 4px;
        }

        .prompt-item-row {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 8px 12px;
            border-radius: var(--mp-border-radius-md);
            cursor: pointer;
            transition: background-color .15s ease-in-out;
        }

        .prompt-item-row:hover {
            background-color: var(--mp-bg-tertiary);
        }

        .prompt-title {
            font-size: 14px;
            font-weight: 500;
            flex: 1;
            padding-right: 12px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            color: var(--mp-text-secondary);
        }

        .prompt-item-row:hover .prompt-title {
            color: var(--mp-text-primary);
        }

        .prompt-actions {
            display: flex;
            align-items: center;
            gap: 4px;
        }

        .action-btn {
            background: 0 0;
            border: none;
            cursor: pointer;
            font-size: 13px;
            font-weight: 500;
            padding: 4px 8px;
            border-radius: var(--mp-border-radius-sm);
            transition: background-color .15s ease-in-out, color .15s ease-in-out;
            font-family: var(--mp-font-family-base);
        }

        .action-btn.edit {
            color: var(--mp-accent-yellow);
        }

        .action-btn.edit:hover {
            background-color: var(--mp-accent-yellow);
            color: var(--mp-bg-primary);
        }

        .action-btn.delete {
            color: var(--mp-accent-red);
        }

        .action-btn.delete:hover {
            background-color: var(--mp-accent-red);
            color: var(--mp-bg-primary);
        }

        .menu-footer,
        .menu-section {
            border-top: 1px solid var(--mp-border-primary);
            padding: 4px;
        }

        .menu-button {
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 8px 12px;
            cursor: pointer;
            transition: background-color .15s ease-in-out;
            color: var(--mp-text-secondary);
            border-radius: var(--mp-border-radius-md);
            font-size: 14px;
            font-weight: 500;
        }

        .menu-button:hover {
            background-color: var(--mp-bg-tertiary);
            color: var(--mp-text-primary);
        }

        .menu-button svg {
            margin-right: 8px;
        }

        .import-export-container {
            display: flex;
        }

        .import-export-container .menu-button {
            flex: 1;
        }

        .divider {
            border-left: 1px solid var(--mp-border-primary);
            height: 24px;
            align-self: center;
        }

        .empty-state {
            padding: 24px 16px;
            text-align: center;
            color: var(--mp-text-tertiary);
            font-size: 14px;
        }

        .form-group {
            display: flex;
            flex-direction: column;
            margin-bottom: 16px;
        }

        .form-label {
            margin-bottom: 6px;
            font-size: 13px;
            font-weight: 500;
            color: var(--mp-text-secondary);
        }

        .form-input {
            background-color: var(--mp-bg-secondary);
            color: var(--mp-text-primary);
            border: 1px solid var(--mp-border-primary) !important;
            border-radius: var(--mp-border-radius-md);
            padding: 10px;
            width: 100%;
            box-sizing: border-box;
            transition: border-color .2s, box-shadow .2s;
            outline: 0 !important;
            font-family: var(--mp-font-family-base);
            font-size: 14px
        }

        .form-textarea {
            background-color: var(--mp-bg-secondary);
            color: var(--mp-text-primary);
            border: 1px solid var(--mp-border-primary) !important;
            border-radius: var(--mp-border-radius-md);
            padding: 10px;
            width: 100%;
            box-sizing: border-box;
            outline: 0 !important;
            font-family: var(--mp-font-family-base);
            font-size: 14px;
            height: 140px;
            resize: vertical;
            transition: border-color .2s, box-shadow .2s;
        }

        .form-input:focus,
        .form-textarea:focus {
            border-color: var(--mp-accent-primary) !important;
            box-shadow: 0 0 0 3px color-mix(in srgb, var(--mp-accent-primary) 25%, transparent) !important;
        }

        .modal-title {
            font-size: 18px;
            font-weight: 600;
            margin: 0 0 24px;
            text-align: center;
            color: var(--mp-text-primary);
        }

        .modal-footer {
            display: flex;
            justify-content: flex-end;
        }

        .save-button {
            padding: 10px 28px;
            border-radius: var(--mp-border-radius-md);
            background-color: var(--mp-accent-primary);
            color: #fff;
            border: none;
            font-weight: 600;
            cursor: pointer;
            transition: all .2s ease-in-out;
            font-family: var(--mp-font-family-base);
        }

        .save-button:hover {
            background-color: var(--mp-accent-primary-hover);
            transform: translateY(-1px);
        }

        .lang-box {
            width: min(90vw, 320px);
        }

        .lang-buttons-container {
            display: flex;
            flex-direction: column;
            gap: 12px;
        }

        @keyframes mp-fade-in-up {
            from {
                opacity: 0;
                transform: translateY(10px);
            }

            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        .lang-button {
            all: unset;
            box-sizing: border-box;
            display: block;
            width: 100%;
            padding: 12px 20px;
            border-radius: var(--mp-border-radius-md);
            background-color: var(--mp-bg-secondary);
            color: var(--mp-text-primary);
            border: 1px solid var(--mp-border-primary);
            font-weight: 500;
            cursor: pointer;
            text-align: center;
            opacity: 0;
            animation: mp-fade-in-up .4s ease forwards;
            transition: transform .2s ease, box-shadow .2s ease, background-color .2s ease;
            font-family: var(--mp-font-family-base);
        }

        .lang-button:hover {
            transform: translateY(-3px);
            box-shadow: var(--mp-shadow-md);
            background-color: var(--mp-bg-tertiary);
        }

        .lang-button:active {
            transform: translateY(0);
            transition-duration: .1s;
        }

        .prompt-menu-list {
            scrollbar-width: thin;
            scrollbar-color: var(--mp-border-secondary) var(--mp-bg-tertiary);
        }

        .prompt-menu-list::-webkit-scrollbar {
            width: 10px !important;
            height: 10px !important;
        }

        .prompt-menu-list::-webkit-scrollbar-track {
            background-color: var(--mp-bg-tertiary) !important;
            border-radius: 10px !important;
            border: none !important;
        }

        .prompt-menu-list::-webkit-scrollbar-thumb {
            background-color: var(--mp-border-secondary) !important;
            border-radius: 10px !important;
            border: 2px solid var(--mp-bg-primary) !important;
        }

        .prompt-menu-list::-webkit-scrollbar-thumb:hover {
            background-color: var(--mp-text-tertiary) !important;
        }

        .mp-tooltip {
            position: fixed;
            z-index: 2147483647;
            border-radius: var(--mp-border-radius-sm);
            padding: 6px 12px;
            pointer-events: none;
            white-space: nowrap;
            font-family: var(--mp-font-family-base);
            font-size: 14px;
            font-weight: 500;
            background-color: var(--mp-text-primary);
            color: var(--mp-bg-primary);
            box-shadow: var(--mp-shadow-md);
            border: 1px solid var(--mp-bg-tertiary);
            opacity: 0;
            transform: scale(0.95);
            transition: opacity 150ms cubic-bezier(0.4, 0, 0.2, 1), transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
        }

        .mp-tooltip.visible {
            opacity: 1;
            transform: scale(1);
        }

        `);
        
        document.head.appendChild(styleElement);
    }

    function createPromptMenu() {
        const menu = document.createElement('div');
        menu.className = 'prompt-menu';
        menu.id = 'prompt-menu-container';
        return menu;
    }

    function createPromptModal() {
        const overlay = document.createElement('div');
        overlay.className = 'mp-overlay mp-hidden';
        overlay.id = '__ap_modal_overlay';

        const box = document.createElement('div');
        box.className = 'mp-modal-box';
        box.onclick = e => e.stopPropagation();

        const modalContentHTML = `
            <button id="__ap_close_prompt" class="mp-modal-close-btn" aria-label="${getTranslation('close')}">✕</button>
            <h2 class="modal-title">${getTranslation('newPrompt')}</h2>
            <div class="form-group">
                <label for="__ap_title" class="form-label">${getTranslation('title')}</label>
                <input id="__ap_title" class="form-input" />
            </div>
            <div class="form-group">
                <label for="__ap_text" class="form-label">${getTranslation('text')}</label>
                <textarea id="__ap_text" class="form-textarea"></textarea>
            </div>
            <div class="modal-footer">
                <button id="__ap_save" class="save-button">${getTranslation('save')}</button>
            </div>
        `;
        setSafeInnerHTML(box, modalContentHTML);
        overlay.appendChild(box);
        return overlay;
    }

    function createLanguageModal() {
        const overlay = document.createElement('div');
        overlay.className = 'mp-overlay mp-hidden lang-overlay';
        overlay.id = '__ap_lang_modal_overlay';
        overlay.onclick = () => hideModal(overlay);

        const box = document.createElement('div');
        box.className = 'mp-modal-box lang-box';
        box.onclick = (e) => e.stopPropagation();

        const buttonsContainer = document.createElement('div');
        buttonsContainer.className = 'lang-buttons-container';

        Object.keys(translations).forEach((langKey, index) => {
            const btn = document.createElement('button');
            btn.className = 'lang-button';
            btn.textContent = translations[langKey].langName;
            btn.style.animationDelay = `${index * 60}ms`;
            btn.onclick = async () => {
                await GM_setValue(LANG_STORAGE_KEY, langKey);
                window.location.reload();
            };
            buttonsContainer.appendChild(btn);
        });

        box.appendChild(buttonsContainer);
        overlay.appendChild(box);
        return overlay;
    }

    function showModal(modal) {
        if (!modal) return;
        modal.classList.remove('mp-hidden');
        setTimeout(() => modal.classList.add('visible'), 10);
    }

    function hideModal(modal) {
        if (!modal) return;
        modal.classList.remove('visible');
        setTimeout(() => modal.classList.add('mp-hidden'), 200);
    }

    function openPromptModal(item = null, index = -1) {
        if (!currentModal) return;
        const isEditing = !!item;
        currentModal.dataset.index = index;
        currentModal.querySelector('.modal-title').textContent = isEditing ? getTranslation('editPrompt') : getTranslation('newPrompt');
        document.getElementById('__ap_title').value = item?.title || '';
        document.getElementById('__ap_text').value = item?.text || '';
        showModal(currentModal);
        setTimeout(() => document.getElementById('__ap_title').focus(), 100);
    }

    function moveCursorToEnd(editor) {
        setTimeout(() => {
            try {
                editor.focus();

                if (currentPlatform === 'gemini') {
                    const selection = window.getSelection();
                    const range = document.createRange();
                    range.selectNodeContents(editor);
                    range.collapse(false);
                    selection.removeAllRanges();
                    selection.addRange(range);
                    editor.scrollTop = editor.scrollHeight;

                } else if (currentPlatform === 'chatgpt') {
                    const selection = window.getSelection();
                    const range = document.createRange();
                    range.selectNodeContents(editor);
                    range.collapse(false);
                    selection.removeAllRanges();
                    selection.addRange(range);
                    const scrollContainer = editor.parentElement;
                    if (scrollContainer) {
                        scrollContainer.scrollTop = scrollContainer.scrollHeight;
                    }

                } else if (currentPlatform === 'googlestudio') {
                    const textLength = editor.value.length;
                    editor.selectionStart = editor.selectionEnd = textLength;
                    let scrollContainer = editor.parentElement;
                    let i = 0;
                    while (scrollContainer && i < 10) {
                        const style = window.getComputedStyle(scrollContainer);
                        if (style.overflowY === 'auto' || style.overflowY === 'scroll') {
                            break;
                        }
                        scrollContainer = scrollContainer.parentElement;
                        i++;
                    }

                    if (scrollContainer) {
                        scrollContainer.scrollTop = scrollContainer.scrollHeight;
                    }
                
                } else {
                    const textLength = editor.value.length;
                    editor.selectionStart = editor.selectionEnd = textLength;
                    editor.scrollTop = editor.scrollHeight;
                }

            } catch (e) {
            }
        }, 10);
    }

    function closeMenu() {
        if (currentMenu && currentMenu.classList.contains('visible')) {
            currentMenu.classList.remove('visible');
        }
    }

    function positionMenu(menu, button) {
        const btnRect = button.getBoundingClientRect();
        const menuHeight = menu.offsetHeight;
        const menuWidth = menu.offsetWidth;
        const viewportHeight = window.innerHeight;
        const viewportWidth = window.innerWidth;
        const margin = 8;
        let top, left;
        const spaceBelow = viewportHeight - btnRect.bottom - margin;
        const spaceAbove = btnRect.top - margin;

        if (spaceBelow >= menuHeight) {
            top = btnRect.bottom + margin;
        } else if (spaceAbove >= menuHeight) {
            top = btnRect.top - menuHeight - margin;
        } else {
            top = Math.max(margin, viewportHeight - menuHeight - margin);
        }
        const spaceRight = viewportWidth - btnRect.left - margin;
        const spaceLeft = btnRect.right - margin;

        if (spaceRight >= menuWidth) {
            left = btnRect.left;
        } else if (spaceLeft >= menuWidth) {
            left = btnRect.right - menuWidth;
        } else {
            left = (viewportWidth - menuWidth) / 2;
        }
        menu.style.top = `${Math.max(margin, Math.min(top, viewportHeight - menuHeight - margin))}px`;
        menu.style.left = `${Math.max(margin, Math.min(left, viewportWidth - menuWidth - margin))}px`;
    }


    async function refreshMenu() {
        if (!currentMenu) return;

        const listContainer = document.createElement('div');
        listContainer.className = 'prompt-menu-list';
        const items = await getAll();
        if (!items.length) {
            setSafeInnerHTML(listContainer, `<div class="empty-state">${getTranslation('noSavedPrompts')}</div>`);
        } else {
            items.forEach((p, index) => {
                const row = document.createElement('div');
                row.className = 'prompt-item-row';
                const titleDiv = document.createElement('div');
                titleDiv.className = 'prompt-title';
                titleDiv.textContent = p.title;
                titleDiv.onclick = (e) => { e.stopPropagation(); insertPrompt(p, index); closeMenu(); };
                const actionsDiv = document.createElement('div');
                actionsDiv.className = 'prompt-actions';
                const btnE = document.createElement('button');
                btnE.textContent = getTranslation('edit');
                btnE.className = 'action-btn edit';
                btnE.onclick = (e) => { e.stopPropagation(); openPromptModal(p, index); };
                const btnD = document.createElement('button');
                btnD.textContent = getTranslation('delete');
                btnD.className = 'action-btn delete';
                btnD.onclick = (e) => { e.stopPropagation(); if (confirm(getTranslation('confirmDelete', { title: p.title }))) remove(index).then(refreshMenu); };
                actionsDiv.appendChild(btnE);
                actionsDiv.appendChild(btnD);
                row.appendChild(titleDiv);
                row.appendChild(actionsDiv);
                listContainer.appendChild(row);
            });
        }

        const addSection = document.createElement('div');
        addSection.className = 'menu-section';
        const addBtn = document.createElement('div');
        addBtn.className = 'menu-button';
        setSafeInnerHTML(addBtn, `<svg width="16" height="16" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /></svg>${getTranslation('addPrompt')}`);
        addBtn.onclick = (e) => { e.stopPropagation(); openPromptModal(); };
        addSection.appendChild(addBtn);

        const footer = document.createElement('div');
        footer.className = 'menu-footer';
        const importExportContainer = document.createElement('div');
        importExportContainer.className = 'import-export-container';
        const exportBtn = document.createElement('div');
        exportBtn.className = 'menu-button';
        exportBtn.textContent = getTranslation('export');
        exportBtn.onclick = (e) => { e.stopPropagation(); exportPrompts(); };
        const importBtn = document.createElement('div');
        importBtn.className = 'menu-button';
        importBtn.textContent = getTranslation('import');
        importBtn.onclick = (e) => { e.stopPropagation(); importPrompts(); };
        const divider = document.createElement('div');
        divider.className = 'divider';
        importExportContainer.appendChild(exportBtn);
        importExportContainer.appendChild(divider);
        importExportContainer.appendChild(importBtn);
        footer.appendChild(importExportContainer);

        setSafeInnerHTML(currentMenu, '');
        currentMenu.appendChild(listContainer);
        currentMenu.appendChild(addSection);
        currentMenu.appendChild(footer);
    }

    function detectPlatform() {
        const hostname = window.location.hostname;
        if (hostname.includes('chatgpt.com')) return 'chatgpt';
        if (hostname.includes('deepseek.com')) return 'deepseek';
        if (hostname.includes('aistudio.google.com')) return 'googlestudio';
        if (hostname.includes('chat.qwen.ai')) return 'qwen';
        if (hostname.includes('chat.z.ai')) return 'zai';
        if (hostname.includes('gemini.google.com')) return 'gemini';
        if (hostname.includes('lmarena.ai')) return 'lmarena';
        if (hostname.includes('kimi.com')) return 'kimi';
        return null;
    }

    async function insertPrompt(promptItem, index) {
        const platformSelectors = { 
            chatgpt: '#prompt-textarea', 
            deepseek: 'textarea[placeholder="Message DeepSeek"]', 
            googlestudio: 'ms-autosize-textarea textarea', 
            qwen: 'textarea#chat-input', 
            zai: 'textarea#chat-input', 
            gemini: 'div.ql-editor[contenteditable="true"]', 
            lmarena: 'textarea[name="message"]',
            kimi: 'div.chat-input-editor[contenteditable="true"]'
        };

        const editor = document.querySelector(platformSelectors[currentPlatform]);
        if (!editor) { alert(getTranslation('editorNotFound', { platform: currentPlatform })); return; }
        editor.focus();
        setTimeout(() => {
            const isFirefox = navigator.userAgent.toLowerCase().includes('firefox');
            if (isFirefox && currentPlatform === 'kimi') {
                document.execCommand('selectAll', false, null);
                document.execCommand('insertText', false, promptItem.text);
            } else if (currentPlatform === 'gemini' || (isFirefox && currentPlatform === 'chatgpt')) {
                let p = editor.querySelector('p') || document.createElement('p');
                setSafeInnerHTML(editor, '');
                p.textContent = promptItem.text;
                editor.appendChild(p);
                editor.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
            } else {
                const dt = new DataTransfer();
                dt.setData('text/plain', promptItem.text);
                editor.dispatchEvent(new ClipboardEvent('paste', { clipboardData: dt, bubbles: true, cancelable: true }));
                if (editor.value !== undefined && editor.value !== promptItem.text) {
                    const setter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value').set;
                    setter.call(editor, promptItem.text);
                    editor.dispatchEvent(new Event('input', { bubbles: true }));
                }
            }
            moveCursorToEnd(editor);
        }, 100);

        let prompts = await getAll();
        if (index > 0) {
            const item = prompts.splice(index, 1)[0];
            prompts.unshift(item);
            await GM_setValue(PROMPT_STORAGE_KEY, prompts);
        }
    }

    async function exportPrompts() {
        const prompts = await getAll();
        if(prompts.length===0){alert(getTranslation('noPromptsToExport'));return}
        const a=document.createElement('a');
        a.href=URL.createObjectURL(new Blob([JSON.stringify(prompts,null,2)],{type:'application/json'}));
        a.download=getTranslation('fileName');
        a.click();
        URL.revokeObjectURL(a.href);
        closeMenu();
    }
    function importPrompts() {
        const input=document.createElement('input');
        input.type='file';
        input.accept='.json';
        input.onchange=e=>{
            const file=e.target.files[0];
            if(!file)return;
            const reader=new FileReader();
            reader.onload=async event=>{
                try{
                    const imported=JSON.parse(event.target.result);
                    if(!Array.isArray(imported))throw new Error("Not an array.");
                    const current=await getAll();
                    const newPrompts=imported.map(p=>({title:p.title||'No Title',text:p.text||''}));
                    await GM_setValue(PROMPT_STORAGE_KEY,[...current,...newPrompts]);
                    await refreshMenu();
                    alert(getTranslation('promptsImported',{count:newPrompts.length}));
                }catch(err){alert(getTranslation('errorImporting',{error:err.message}))}
            };
            reader.readAsText(file);
        };
        input.click();
        closeMenu();
    }

    function cleanup() {
        if (currentButton) { currentButton.remove(); currentButton = null; }
        if (currentMenu) { currentMenu.remove(); currentMenu = null; }
        if (currentModal) { currentModal.remove(); currentModal = null; }
        if (languageModal) { languageModal.remove(); languageModal = null; }
        isInitialized = false;
    }

    async function initUI() {
        if (pageObserver) pageObserver.disconnect();
        cleanup();
        currentPlatform = detectPlatform();
        if (!currentPlatform) return;

        try {
            let btn, elementToInsert, insertionPoint, insertionMethod = 'before';
            if (currentPlatform === 'chatgpt') {
                insertionPoint = await waitFor('div[class*="[grid-area:leading]"]');
                insertionPoint.style.display = 'flex';
                insertionPoint.style.alignItems = 'center';
                btn = createChatGPTButton();
                elementToInsert = btn;
                insertionMethod = 'append';
            } else if (currentPlatform === 'deepseek') {
                const container = await waitFor('.ec4f5d61');
                insertionPoint = container.querySelector('.bf38813a');
                const allButtons = Array.from(container.querySelectorAll('button'));
                const refBtn = allButtons.find(b => b.textContent.trim() === 'Search');
                if (!refBtn || !insertionPoint) throw new Error('DeepSeek UI reference button "Search" not found.');
                btn = createDeepSeekButton();
                btn.className = refBtn.className;
                elementToInsert = btn;
            } else if (currentPlatform === 'googlestudio') {
                insertionPoint = await waitFor('ms-add-chunk-menu', 5000).then(el => el.closest('.button-wrapper'));
                const wrapper = document.createElement('div');
                wrapper.className = 'button-wrapper';
                btn = createGoogleStudioButton();
                wrapper.appendChild(btn);
                elementToInsert = wrapper;
                const parent = insertionPoint.closest('.prompt-input-wrapper-container');
                if (parent) parent.style.alignItems = 'center';
            } else if (currentPlatform === 'qwen') {
                const referenceButton = await waitFor('button.websearch_button', 5000);
                const buttonContainer = referenceButton.parentElement;
                if (!buttonContainer) throw new Error('Qwen button container not found.');
                insertionPoint = buttonContainer.firstChild;
                insertionMethod = 'before';
                btn = createQwenButton();
                elementToInsert = btn;
                const qwenPositionObserver = new MutationObserver(() => {
                    const myButton = buttonContainer.querySelector('button[data-testid="composer-button-prompts"]');
                    if (myButton && buttonContainer.firstElementChild !== myButton) {
                        buttonContainer.prepend(myButton);
                    }
                });
                qwenPositionObserver.observe(buttonContainer, { childList: true });
            } else if (currentPlatform === 'zai') {
                const referenceElement = await waitFor('svg path[d="M2.6499 4.48322H13.3166"]', 8000).then(p => p.closest('button'));
                if (!referenceElement) throw new Error('Z.ai reference element not found.');
                insertionPoint = referenceElement.closest('div.flex.gap-\\[8px\\]');
                if (!insertionPoint) throw new Error('Z.ai button container not found.');
                btn = createZaiButton();
                elementToInsert = btn;
                insertionMethod = 'append';
            } else if (currentPlatform === 'gemini') {
                insertionPoint = await waitFor('uploader', 8000);
                btn = createGeminiButton();
                elementToInsert = btn;
                insertionMethod = 'after';
                const wrapper = insertionPoint.parentElement;
                if (wrapper) {
                    wrapper.style.display = 'flex';
                    wrapper.style.alignItems = 'center';
                    wrapper.style.gap = '3px';
                }
            } else if (currentPlatform === 'lmarena') {
                insertionPoint = await waitFor('div[data-sentry-component="SelectChatModality"]', 8000);
                btn = createLmarenaButton();
                elementToInsert = btn;
                insertionMethod = 'append';
            } else if (currentPlatform === 'kimi') {
                insertionPoint = await waitFor('div.left-area', 8000);
                btn = createKimiButton();
                if (!btn) return;
                elementToInsert = btn;
                
                const ensureButtonIsPresent = () => {
                    if (!insertionPoint.contains(elementToInsert)) {
                        insertionPoint.appendChild(elementToInsert);
                    }
                };

                ensureButtonIsPresent();
                const guardianObserver = new MutationObserver(ensureButtonIsPresent);
                guardianObserver.observe(insertionPoint, { childList: true });
                
                insertionMethod = 'handled_by_kimi_guardian';
            }

            if (!btn || !insertionPoint) return;
            currentButton = elementToInsert;
            const clickable = btn;

            if (insertionMethod === 'append') {
                insertionPoint.appendChild(elementToInsert);
            } else if (insertionMethod === 'before') {
                insertionPoint.parentNode.insertBefore(elementToInsert, insertionPoint);
            } else if (insertionMethod === 'after') {
                insertionPoint.parentNode.insertBefore(elementToInsert, insertionPoint.nextSibling);
            }

            currentMenu = createPromptMenu();
            currentModal = createPromptModal();
            languageModal = createLanguageModal();
            document.body.appendChild(currentMenu);
            document.body.appendChild(currentModal);
            document.body.appendChild(languageModal);

            clickable.addEventListener('click', e => {
                e.stopPropagation();
                e.preventDefault();
                const menu = currentMenu;
                if (menu.classList.contains('visible')) {
                    closeMenu();
                    return;
                }
                refreshMenu().then(() => {
                    positionMenu(menu, clickable);
                    menu.classList.add('visible');
                });
            });

            currentModal.querySelector('#__ap_save').onclick = async (e) => {
                e.stopPropagation();
                const index = Number(currentModal.dataset.index) || -1;
                const title = document.getElementById('__ap_title').value.trim();
                const text = document.getElementById('__ap_text').value.trim();
                if (!title || !text) { alert(getTranslation('requiredFields')); return; }
                const op = index > -1 ? update(index, { title, text }) : addItem({ title, text });
                op.then(() => { hideModal(currentModal); refreshMenu(); });
            };

            currentModal.querySelector('#__ap_close_prompt').onclick = (e) => {
                e.stopPropagation();
                hideModal(currentModal);
            };

            isInitialized = true;
        } catch (error) {
            cleanup();
        } finally {
            setupPageObserver();
        }
    }

    const debouncedTryInit = debounce(tryInit, 500);
    function setupPageObserver() {
        if (pageObserver) pageObserver.disconnect();
        pageObserver = new MutationObserver(() => {
            if (!document.body.contains(currentButton)) {
                debouncedTryInit();
            }
        });
        pageObserver.observe(document.body, { childList: true, subtree: true });
    }

    function setupGlobalEventListeners() {
        document.addEventListener('click', ev => {
            if (!currentMenu || !currentButton) return;
            if (ev.target.closest('#prompt-menu-container, [data-testid="composer-button-prompts"]')) return;
            closeMenu();
        });

        document.addEventListener('keydown', ev => {
            if (ev.key === 'Escape') {
                closeMenu();
                if (currentModal && currentModal.classList.contains('visible')) hideModal(currentModal);
                if (languageModal && languageModal.classList.contains('visible')) hideModal(languageModal);
            }
        });

        window.addEventListener('resize', debounce(() => {
            if (currentMenu && currentMenu.classList.contains('visible')) {
                positionMenu(currentMenu, currentButton);
            }
        }, 100));
    }

    function tryInit() {
        if (isInitializing) return;
        if (isInitialized && currentButton && document.body.contains(currentButton) && currentPlatform === detectPlatform()) {
            return;
        }
        isInitializing = true;
        initUI().finally(() => { isInitializing = false; });
    }

    async function start() {
        await determineLanguage();
        injectGlobalStyles();
        setupGlobalEventListeners();
        GM_registerMenuCommand(getTranslation('languageSettings'), () => {
            if (!languageModal) {
                languageModal = createLanguageModal();
                document.body.appendChild(languageModal);
            }
            showModal(languageModal);
        });
        tryInit();
    }

    start();

})();