Greasy Fork is available in English.

My Prompt

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

이 스크립트 설치?
작성자 추천 스크립트

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.3
// @description        Save, edit, delete, import, and export your custom prompts directly in ChatGPT, DeepSeek, Google AI Studio, Qwen, Z.ai, Gemini, and LMArena with a modern UI.
// @description:en     Save, edit, delete, import, and export your custom prompts directly in ChatGPT, DeepSeek, Google AI Studio, Qwen, Z.ai, Gemini, and LMArena with a modern UI.
// @description:pt-BR  Salve, edite, exclua, importe e exporte seus prompts personalizados diretamente no ChatGPT, DeepSeek, Google AI Studio, Qwen, Z.ai, Gemini e LMArena com uma UI moderna.
// @description:es     Guarda, edita, elimina, importa y exporta tus prompts personalizados directamente en ChatGPT, DeepSeek, Google AI Studio, Qwen, Z.ai, Gemini y LMArena con una UI moderna.
// @description:zh-CN  直接在 ChatGPT、DeepSeek、Google AI Studio、Qwen、Z.ai、Gemini 和 LMArena 中保存、编辑、删除、导入和导出您的自定义提示,拥有现代化的用户界面。
// @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/*
// @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
// ==/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.3',
    };
    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.push(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 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';
        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"]' };
        const editor = document.querySelector(platformSelectors[currentPlatform]);
        if (!editor) { alert(getTranslation('editorNotFound', { platform: currentPlatform })); return; }
        editor.focus();
        setTimeout(() => {
            if (currentPlatform === 'gemini') {
                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 if (currentPlatform === 'chatgpt') {
                const isFirefox = navigator.userAgent.toLowerCase().includes('firefox');
                if (isFirefox) {
                    editor.innerHTML = '';
                    const p = document.createElement('p');
                    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 }));
                }
            } 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 !== 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') {
                insertionPoint = await waitFor('button.websearch_button', 5000);
                btn = createQwenButton();
                elementToInsert = btn;
                insertionMethod = 'after';
                const buttonContainer = insertionPoint.parentElement;
                if (buttonContainer) {
                    const qwenPositionObserver = new MutationObserver(() => {
                        const myButton = buttonContainer.querySelector('button[data-testid="composer-button-prompts"]');
                        if (myButton && buttonContainer.lastElementChild !== myButton) {
                            buttonContainer.appendChild(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';
            }

            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 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();

})();