Greasy Fork

Greasy Fork is available in English.

更好的 Greasy Fork

通过多项改进使Greasy Fork更加实用且美观:在标题旁添加脚本图标;实现用于编辑描述和评论的完整HTML工具栏;创建新的脚本直接下载按钮;允许通过元数据进行自定义(颜色、版权、社交图标);以及其他界面和可用性优化。

当前为 2025-11-07 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name                Better Greasy Fork
// @name:pt-BR          Greasy Fork Aprimorado
// @name:zh-CN          更好的 Greasy Fork
// @name:zh-TW          更好的 Greasy Fork
// @name:en             Better Greasy Fork
// @name:es             Greasy Fork Mejorado
// @name:ja             改良版 Greasy Fork
// @name:ko             향상된 Greasy Fork
// @name:de             Verbesserter Greasy Fork
// @name:fr             Greasy Fork Amélioré
// @namespace           https://github.com/0H4S
// @version             1.7
// @description         Makes Greasy Fork more functional and visually appealing through various improvements: adds script icons next to titles; implements a complete HTML toolbar for editing descriptions and comments; creates a new direct script download button; allows customizations via metadata (colors, copyright, social icons); plus other interface and usability optimizations.
// @description:pt-BR   Torna o Greasy Fork mais funcional e visualmente agradável através de várias melhorias: adiciona ícones de scripts ao lado dos títulos; implementa uma barra de ferramentas HTML completa para editar descrições e comentários; cria um novo botão de download direto de scripts; permite personalizações via metadados (cores, copyright, ícones sociais); além de outras otimizações de interface e usabilidade.
// @description:zh-CN   通过多项改进使Greasy Fork更加实用且美观:在标题旁添加脚本图标;实现用于编辑描述和评论的完整HTML工具栏;创建新的脚本直接下载按钮;允许通过元数据进行自定义(颜色、版权、社交图标);以及其他界面和可用性优化。
// @description:zh-TW   透過多項改進使Greasy Fork更加實用且美觀:在標題旁新增腳本圖示;實作用於編輯描述和留言的完整HTML工具列;建立新的腳本直接下載按鈕;允許透過中繼資料進行自訂(顏色、版權、社群圖示);以及其他介面和可用性最佳化。
// @description:en      Makes Greasy Fork more functional and visually appealing through various improvements: adds script icons next to titles; implements a complete HTML toolbar for editing descriptions and comments; creates a new direct script download button; allows customizations via metadata (colors, copyright, social icons); plus other interface and usability optimizations.
// @description:es      Hace que Greasy Fork sea más funcional y visualmente atractivo mediante diversas mejoras: añade iconos de scripts junto a los títulos; implementa una barra de herramientas HTML completa para editar descripciones y comentarios; crea un nuevo botón de descarga directa de scripts; permite personalizaciones mediante metadatos (colores, copyright, iconos sociales); además de otras optimizaciones de interfaz y usabilidad.
// @description:ja      複数の改善によりGreasy Forkをより機能的で視覚的に魅力的にします:タイトルの横にスクリプトアイコンを追加、説明文やコメントを編集するための完全なHTMLツールバーを実装、スクリプトの新しい直接ダウンロードボタンを作成、メタデータによるカスタマイズ(色、著作権、ソーシャルアイコン)を可能にし、その他のインターフェースとユーザビリティの最適化も提供します。
// @description:ko      다양한 개선을 통해 Greasy Fork를 더욱 기능적이고 시각적으로 매력적으로 만듭니다: 제목 옆에 스크립트 아이콘 추가, 설명 및 댓글 편집을 위한 완전한 HTML 도구 모음 구현, 새로운 스크립트 직접 다운로드 버튼 생성, 메타데이터를 통한 사용자 지정(색상, 저작권, 소셜 아이콘) 허용, 기타 인터페이스 및 사용성 최적화 제공.
// @description:de      Macht Greasy Fork funktionaler und optisch ansprechender durch verschiedene Verbesserungen: fügt Script-Icons neben Titeln hinzu; implementiert eine vollständige HTML-Symbolleiste zum Bearbeiten von Beschreibungen und Kommentaren; erstellt eine neue Schaltfläche für direkten Script-Download; ermöglicht Anpassungen über Metadaten (Farben, Urheberrecht, Social-Icons); sowie weitere Interface- und Usability-Optimierungen.
// @description:fr      Rend Greasy Fork plus fonctionnel et visuellement agréable grâce à diverses améliorations : ajoute des icônes de scripts à côté des titres ; implémente une barre d'outils HTML complète pour éditer les descriptions et commentaires ; crée un nouveau bouton de téléchargement direct de scripts ; permet des personnalisations via les métadonnées (couleurs, copyright, icônes sociales) ; ainsi que d'autres optimisations d'interface et d'utilisabilité.
// @author              OHAS
// @license             CC-BY-NC-ND-4.0
// @copyright           2025 OHAS. All Rights Reserved.
// @match               http://greasyfork.icu/*
// @icon                data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMDAiIGhlaWdodD0iMjAwIiB2aWV3Qm94PSIwIDAgMjQgMjQiIG92ZXJmbG93PSJ2aXNpYmxlIj4KICAgIDxzdHlsZT4KICAgICAgICAuZGVzZW5oYXItY29udG9ybm8gewogICAgICAgICAgICBzdHJva2UtZGFzaGFycmF5OiAxMDA7CiAgICAgICAgICAgIHN0cm9rZS1kYXNob2Zmc2V0OiAxMDA7CiAgICAgICAgICAgIGFuaW1hdGlvbjogZGVzZW5oYXItY29udG9ybm8gMTBzIGVhc2UtaW4tb3V0IGluZmluaXRlOwogICAgICAgIH0KCiAgICAgICAgLm9uZGEtcHJlZW5jaGltZW50byB7CiAgICAgICAgICAgIGFuaW1hdGlvbjogb25kYS1wcmVlbmNoaW1lbnRvIDEwcyBlYXNlLWluLW91dCBpbmZpbml0ZTsKICAgICAgICB9CgogICAgICAgIEBrZXlmcmFtZXMgZGVzZW5oYXItY29udG9ybm8gewogICAgICAgICAgICAwJSB7CiAgICAgICAgICAgICAgICBzdHJva2UtZGFzaG9mZnNldDogMTAwOwogICAgICAgICAgICAgICAgc3Ryb2tlOiAjZmZmZmZmZmY7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgMjUlIHsKICAgICAgICAgICAgICAgIHN0cm9rZS1kYXNob2Zmc2V0OiAwOwogICAgICAgICAgICAgICAgc3Ryb2tlOiAjZmZmZmZmZmY7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgNzUlIHsKICAgICAgICAgICAgICAgIHN0cm9rZS1kYXNob2Zmc2V0OiAwOwogICAgICAgICAgICAgICAgc3Ryb2tlOiAjZmZmZmZmZmY7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgMTAwJSB7CiAgICAgICAgICAgICAgICBzdHJva2UtZGFzaG9mZnNldDogLTEwMDsKICAgICAgICAgICAgICAgIHN0cm9rZTogI2ZmZmZmZmZmOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBAa2V5ZnJhbWVzIG9uZGEtcHJlZW5jaGltZW50byB7CiAgICAgICAgICAgIDAlIHsKICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgyNHB4KTsKICAgICAgICAgICAgICAgIGZpbGw6ICNmZmZmZmZmZjsKICAgICAgICAgICAgfQogICAgICAgICAgICAyNSUgewogICAgICAgICAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDBweCk7CiAgICAgICAgICAgICAgICBmaWxsOiAjZmZmZmZmZmY7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgNzUlIHsKICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgwcHgpOwogICAgICAgICAgICAgICAgZmlsbDogI2ZmZmZmZmZmOwogICAgICAgICAgICB9CiAgICAgICAgICAgIDEwMCUgewogICAgICAgICAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDI0cHgpOwogICAgICAgICAgICAgICAgZmlsbDogI2ZmZmZmZmZmOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgPC9zdHlsZT4KICAgIDxkZWZzPgogICAgICAgIDxjbGlwUGF0aCBpZD0ibW9sZGUtZ2FyZm8iPgogICAgICAgICAgICA8cGF0aCBkPSJNNS44OSAyLjIyN2EuMjguMjggMCAwIDEgLjI2Ni4wNzZsNS4wNjMgNS4wNjJjLjU0LjU0LjUwOSAxLjY1Mi0uMDMxIDIuMTkybDguNzcxIDguNzdjMS4zNTYgMS4zNTUtLjM2IDMuMDk3LTEuNzMgMS43MjhsLTguNzcyLTguNzdjLS41NC41NC0xLjY1MS41NzEtMi4xOTEuMDMxbC01LjA2My01LjA2Yy0uMzA0LS4zMDQuMzA0LS45MTEuNjA4LS42MDhsMy43MTQgMy43MTNMNy41OSA4LjI5N0wzLjg3NSA0LjU4MmMtLjMwNC0uMzA0LjMwNC0uOTExLjYwNy0uNjA3bDMuNzE1IDMuNzE0bDEuMDY3LTEuMDY2TDUuNTQ5IDIuOTFjLS4yMjgtLjIyOC4wNTctLjYyNi4zNDItLjY4M1oiLz4KICAgICAgICA8L2NsaXBQYXRoPgogICAgPC9kZWZzPgogICAgPGc+CiAgICAgICAgPHBhdGggZmlsbD0iIzAwMDAwMGZmIiBkPSJNMTIgMEM1LjM3NCAwIDAgNS4zNzUgMCAxMnM1LjM3NCAxMiAxMiAxMmM2LjYyNSAwIDEyLTUuMzc1IDEyLTEyUzE4LjYyNSAwIDEyIDAiLz4KICAgICAgICA8ZyBjbGlwLXBhdGg9InVybCgjbW9sZGUtZ2FyZm8pIj4KICAgICAgICAgICAgPHBhdGggY2xhc3M9Im9uZGEtcHJlZW5jaGltZW50byIgCiAgICAgICAgICAgICAgICAgIGQ9Ik0gLTIsMjQgTCAtMiwwIGMgNiwtNSA2LDUgMTIsMCBzIDYsLTUgMTIsMCBzIDYsLTUgMTIsMCBMIDMwLDI0IFoiLz4KICAgICAgICA8L2c+CiAgICAgICAgPHBhdGggY2xhc3M9ImRlc2VuaGFyLWNvbnRvcm5vIiBmaWxsPSJub25lIiBzdHJva2Utd2lkdGg9IjAuNSIgZD0iTTUuODkgMi4yMjdhLjI4LjI4IDAgMCAxIC4yNjYuMDc2bDUuMDYzIDUuMDYyYy41NC41NC41MDkgMS42NTItLjAzMSAyLjE5Mmw4Ljc3MSA4Ljc3YzEuMzU2IDEuMzU1LS4zNiAzLjA5Ny0xLjczIDEuNzI4bC04Ljc3Mi04Ljc3Yy0uNTQuNTQtMS42NTEuNTcxLTIuMTkxLjAzMWwtNS4wNjMtNS4wNmMtLjMwNC0uMzA0LjMwNC0uOTExLjYwOC0uNjA4bDMuNzE0IDMuNzEzTDcuNTkgOC4yOTdMMy44NzUgNC41ODJjLS4zMDQtLjMwNC4zMDQtLjkxMS42MDctLjYwN2wzLjcxNSAzLjcxNGwxLjA2Ny0xLjA2Nkw1LjU0OSAyLjkxYy0uMjI4LS4yMjguMDU3LS42MjYuMzQyLS42ODNaIi8+CiAgICA8L2c+Cjwvc3ZnPg==
// @resource            customCSS https://cdn.jsdelivr.net/gh/0H4S/Better-Greasy-Fork/estilo.css
// @resource            iconsJSON https://cdn.jsdelivr.net/gh/0H4S/Better-Greasy-Fork/icones.json
// @require             https://update.greasyfork.icu/scripts/549920.js
// @connect             gist.github.com
// @connect             update.greasyfork.org
// @grant               GM_addStyle
// @grant               GM_getValue
// @grant               GM_setValue
// @grant               GM_deleteValue
// @grant               GM_xmlhttpRequest
// @grant               GM_getResourceText
// @grant               GM_registerMenuCommand
// @run-at              document-idle
// @noframes
// @compatible          chrome
// @compatible          firefox
// @compatible          edge
// @compatible          opera
// @bgf-colorLT         #0059ffff
// @bgf-colorDT         #ffffffff
// @bgf-copyright       [2025 OHAS. All Rights Reserved.](https://gist.github.com/0H4S/ae2fa82957a089576367e364cbf02438)
// @bgf-compatible      brave, mobile
// @bgf-social          https://github.com/0H4S, https://www.instagram.com/o_h_a_s
// @contributionURL     https://linktr.ee/0H4S
// ==/UserScript==

(function () {
    'use strict';
    // ================
    // #region GLOBAL
    // ================
    const allTranslations = {
        "en": {
            "langName":                         "English",
            "languageSettings":                 "🌐 Language",
            "close":                            "Close",
            "confirm":                          "Confirm",
            "cancel":                           "Cancel",
            "download":                         "Download",
            "compatible_with":                  "Compatible with",
            "force_update":                     "🔄️ Force Update",
            "force_update_alert":               "Cache cleared. The page will reload to fetch the updated data.",
            "titles":                           "Headings",
            "title_placeholder":                "Heading",
            "bold":                             "Bold",
            "bold_placeholder":                 "bold text",
            "italic":                           "Italic",
            "italic_placeholder":               "italic text",
            "underline":                        "Underline",
            "underline_placeholder":            "underlined text",
            "strikethrough":                    "Strikethrough",
            "strikethrough_placeholder":        "strikethrough text",
            "unordered_list":                   "Unordered List",
            "ordered_list":                     "Ordered List",
            "list_item_placeholder":            "Item",
            "quote":                            "Quote",
            "inline_code":                      "Inline Code",
            "inline_code_placeholder":          "code",
            "code_block":                       "Code Block",
            "code_block_placeholder":           "code here",
            "horizontal_line":                  "Horizontal Line",
            "horizontal_line_style":            "Horizontal Line Style",
            "prompt_hr_size":                   "Size (px)",
            "prompt_hr_color":                  "Color",
            "link":                             "Link",
            "prompt_insert_url":                "Enter the URL:",
            "link_text_placeholder":            "link text",
            "image":                            "Image",
            "prompt_insert_image_url":          "Enter the image URL (https):",
            "prompt_image_title":               "Image title (optional):",
            "image_title_placeholder":          "e.g. My beautiful image",
            "prompt_image_width":               "Width (optional):",
            "prompt_image_height":              "Height (optional):",
            "video":                            "Video",
            "prompt_video_type":                "Video Type",
            "video_type_embed":                 "Embed (YouTube, Bilibili)",
            "video_type_html5":                 "HTML5 Video (Direct URL)",
            "prompt_video_poster_url":          "Poster Image URL",
            "prompt_insert_video_url":          "Enter the video URL:",
            "prompt_video_width":               "Width (optional):",
            "prompt_video_height":              "Height (optional):",
            "alert_invalid_video_url":          "Invalid or unsupported video URL.",
            "table":                            "Table",
            "prompt_columns":                   "Number of columns:",
            "prompt_rows":                      "Number of rows:",
            "table_header_placeholder":         "Header",
            "table_cell_placeholder":           "Cell",
            "subscript":                        "Subscript",
            "subscript_placeholder":            "sub",
            "superscript":                      "Superscript",
            "superscript_placeholder":          "sup",
            "highlight":                        "Highlight",
            "highlight_placeholder":            "highlighted",
            "keyboard":                         "Keyboard",
            "keyboard_placeholder":             "Ctrl+C",
            "abbreviation":                     "Abbreviation",
            "prompt_abbreviation_meaning":      "What does the abbreviation stand for?",
            "abbreviation_placeholder":         "HTML",
            "text_color":                       "Text Color",
            "colored_text_placeholder":         "colored text",
            "background_color":                 "Background Color",
            "colored_background_placeholder":   "colored background",
            "details":                          "Collapsible section",
            "details_summary_placeholder":      "Summary or Title",
            "details_content_placeholder":      "Content to be hidden...",
            "center":                           "Center Align",
            "center_placeholder":               "centered text",
            "notFound":                         "Code not found!",
            "scriptIdNotFound":                 "Could not identify the script ID.",
            "downloading":                      "Downloading...",
            "downloadError":                    "An error occurred while downloading the script.",
            "downloadTimeout":                  "The script download timed out.",
            "info_tooltip":                     "Shortcuts",
            "info_shortcuts_title":             "Keyboard Shortcuts",
            "info_header_shortcut":             "Shortcut",
            "info_header_action":               "Action",
            "info_shortcut_tab":                "Inserts a tab space.",
            "info_shortcut_shift_enter":        "Inserts a line break <br>.",
            "info_shortcut_ctrl_d":             "Wraps the selection in a <div> tag.",
            "info_shortcut_ctrl_p":             "Wraps the selection in a <p> paragraph.",
            "info_shortcut_ctrl_m":             "Wraps the selection in a markdown code block.",
            "info_shortcut_ctrl_space":         "Inserts a non-breaking space  .",
            "prompt_link_text":                 "Link text:",
            "prompt_abbreviation_text":         "Abbreviation text:",
            "border_style":                     "Border Style",
            "prompt_border_size":               "Border size (px)",
            "prompt_border_color":              "Border color",
            "prompt_border_text":               "Text",
            "prompt_border_tag_type":           "Tag Type",
            "border_text_placeholder":          "Text"
        },
        "pt-BR": {
            "langName":                         "Português (BR)",
            "languageSettings":                 "🌐 Idioma",
            "close":                            "Fechar",
            "confirm":                          "Confirmar",
            "cancel":                           "Cancelar",
            "download":                         "Baixar",
            "compatible_with":                  "Compatível com",
            "force_update":                     "🔄️ Forçar Atualização",
            "force_update_alert":               "O cache foi limpo. A página será recarregada para buscar os dados atualizados.",
            "titles":                           "Títulos",
            "title_placeholder":                "Título",
            "bold":                             "Negrito",
            "bold_placeholder":                 "negrito",
            "italic":                           "Itálico",
            "italic_placeholder":               "itálico",
            "underline":                        "Sublinhado",
            "underline_placeholder":            "sublinhado",
            "strikethrough":                    "Riscado",
            "strikethrough_placeholder":        "riscado",
            "unordered_list":                   "Lista não ordenada",
            "ordered_list":                     "Lista ordenada",
            "list_item_placeholder":            "Item",
            "quote":                            "Citação",
            "inline_code":                      "Código Inline",
            "inline_code_placeholder":          "código",
            "code_block":                       "Bloco de Código",
            "code_block_placeholder":           "código aqui",
            "horizontal_line":                  "Linha Horizontal",
            "horizontal_line_style":            "Estilo da Linha Horizontal",
            "prompt_hr_size":                   "Tamanho (px)",
            "prompt_hr_color":                  "Cor",
            "link":                             "Link",
            "prompt_insert_url":                "Insira a URL:",
            "link_text_placeholder":            "texto do link",
            "image":                            "Imagem",
            "prompt_insert_image_url":          "Insira a URL da imagem (https):",
            "prompt_image_title":               "Título da imagem (opcional):",
            "image_title_placeholder":          "ex: Minha bela imagem",
            "prompt_image_width":               "Largura (opcional):",
            "prompt_image_height":              "Altura (opcional):",
            "video":                            "Vídeo",
            "prompt_video_type":                "Tipo de Vídeo",
            "video_type_embed":                 "Incorporado (YouTube, Bilibili)",
            "video_type_html5":                 "Vídeo HTML5 (URL direta)",
            "prompt_video_poster_url":          "URL da Imagem de Capa (poster)",
            "prompt_insert_video_url":          "Insira a URL do vídeo:",
            "prompt_video_width":               "Largura (opcional):",
            "prompt_video_height":              "Altura (opcional):",
            "alert_invalid_video_url":          "URL de vídeo inválida ou não suportada.",
            "table":                            "Tabela",
            "prompt_columns":                   "Número de colunas:",
            "prompt_rows":                      "Número de linhas:",
            "table_header_placeholder":         "Cabeçalho",
            "table_cell_placeholder":           "Célula",
            "subscript":                        "Subscrito",
            "subscript_placeholder":            "sub",
            "superscript":                      "Sobrescrito",
            "superscript_placeholder":          "sup",
            "highlight":                        "Marcação",
            "highlight_placeholder":            "marcado",
            "keyboard":                         "Teclado",
            "keyboard_placeholder":             "Ctrl+C",
            "abbreviation":                     "Abreviação",
            "prompt_abbreviation_meaning":      "Qual o significado da abreviação?",
            "abbreviation_placeholder":         "HTML",
            "text_color":                       "Cor do Texto",
            "colored_text_placeholder":         "texto colorido",
            "background_color":                 "Cor de Fundo",
            "colored_background_placeholder":   "fundo colorido",
            "details":                          "Seção Recolhível",
            "details_summary_placeholder":      "Resumo ou Título",
            "details_content_placeholder":      "Conteúdo a ser ocultado...",
            "center":                           "Centralizar",
            "center_placeholder":               "texto centralizado",
            "notFound":                         "Código não encontrado!",
            "scriptIdNotFound":                 "Não foi possível identificar o ID do script.",
            "downloading":                      "Baixando...",
            "downloadError":                    "Ocorreu um erro ao baixar o script.",
            "downloadTimeout":                  "O tempo para baixar o script esgotou.",
            "info_tooltip":                     "Atalhos",
            "info_shortcuts_title":             "Atalhos do Teclado",
            "info_header_shortcut":             "Atalho",
            "info_header_action":               "Ação",
            "info_shortcut_tab":                "Insere um espaço de tabulação.",
            "info_shortcut_shift_enter":        "Insere uma quebra de linha <br>.",
            "info_shortcut_ctrl_d":             "Envolve a seleção em uma tag <div>.",
            "info_shortcut_ctrl_p":             "Envolve a seleção em um parágrafo <p>.",
            "info_shortcut_ctrl_m":             "Envolve a seleção em um bloco de código markdown.",
            "info_shortcut_ctrl_space":         "Insere um espaço não separável  .",
            "prompt_link_text":                 "Texto do link:",
            "prompt_abbreviation_text":         "Texto da abreviação:",
            "border_style":                     "Estilo da Borda",
            "prompt_border_size":               "Tamanho da borda (px)",
            "prompt_border_color":              "Cor da borda",
            "prompt_border_text":               "Texto",
            "prompt_border_tag_type":           "Tipo de Tag",
            "border_text_placeholder":          "Texto"
        },
        "es": {
            "langName":                         "Español",
            "languageSettings":                 "🌐 Idioma",
            "close":                            "Cerrar",
            "confirm":                          "Confirmar",
            "cancel":                           "Cancelar",
            "download":                         "Descargar",
            "compatible_with":                  "Compatible con",
            "force_update":                     "🔄️ Forzar actualización",
            "force_update_alert":               "La caché se limpió. La página se recargará para obtener los datos actualizados.",
            "titles":                           "Títulos",
            "title_placeholder":                "Título",
            "bold":                             "Negrita",
            "bold_placeholder":                 "texto en negrita",
            "italic":                           "Cursiva",
            "italic_placeholder":               "texto en cursiva",
            "underline":                        "Subrayado",
            "underline_placeholder":            "texto subrayado",
            "strikethrough":                    "Tachado",
            "strikethrough_placeholder":        "texto tachado",
            "unordered_list":                   "Lista sin ordenar",
            "ordered_list":                     "Lista ordenada",
            "list_item_placeholder":            "Elemento",
            "quote":                            "Cita",
            "inline_code":                      "Código en línea",
            "inline_code_placeholder":          "código",
            "code_block":                       "Bloque de código",
            "code_block_placeholder":           "código aquí",
            "horizontal_line":                  "Línea horizontal",
            "horizontal_line_style":            "Estilo de Línea Horizontal",
            "prompt_hr_size":                   "Tamaño (px)",
            "prompt_hr_color":                  "Color",
            "link":                             "Enlace",
            "prompt_insert_url":                "Introduzca la URL:",
            "link_text_placeholder":            "texto del enlace",
            "image":                            "Imagen",
            "prompt_insert_image_url":          "Introduzca la URL de la imagen (https):",
            "prompt_image_title":               "Título de la imagen (opcional):",
            "image_title_placeholder":          "ej: Mi hermosa imagen",
            "prompt_image_width":               "Ancho (opcional):",
            "prompt_image_height":              "Alto (opcional):",
            "video":                            "Video",
            "prompt_video_type":                "Tipo de Video",
            "video_type_embed":                 "Incrustado (YouTube, Bilibili)",
            "video_type_html5":                 "Video HTML5 (URL directa)",
            "prompt_video_poster_url":          "URL de la imagen de portada (póster)",
            "prompt_insert_video_url":          "Introduzca la URL del video:",
            "prompt_video_width":               "Ancho (opcional):",
            "prompt_video_height":              "Alto (opcional):",
            "alert_invalid_video_url":          "URL de video no válida o no compatible.",
            "table":                            "Tabla",
            "prompt_columns":                   "Número de columnas:",
            "prompt_rows":                      "Número de filas:",
            "table_header_placeholder":         "Encabezado",
            "table_cell_placeholder":           "Celda",
            "subscript":                        "Subíndice",
            "subscript_placeholder":            "sub",
            "superscript":                      "Superíndice",
            "superscript_placeholder":          "sup",
            "highlight":                        "Resaltado",
            "highlight_placeholder":            "resaltado",
            "keyboard":                         "Teclado",
            "keyboard_placeholder":             "Ctrl+C",
            "abbreviation":                     "Abreviatura",
            "prompt_abbreviation_meaning":      "¿Qué significa la abreviação?",
            "abbreviation_placeholder":         "HTML",
            "text_color":                       "Color del texto",
            "colored_text_placeholder":         "texto coloreado",
            "background_color":                 "Color de fondo",
            "colored_background_placeholder":   "fondo coloreado",
            "details":                          "Sección Plegable",
            "details_summary_placeholder":      "Resumen o Título",
            "details_content_placeholder":      "Contenido a ocultar...",
            "center":                           "Centrar",
            "center_placeholder":               "texto centrado",
            "notFound":                         "¡Código no encontrado!",
            "scriptIdNotFound":                 "No se pudo identificar el ID del script.",
            "downloading":                      "Descargando...",
            "downloadError":                    "Ocurrió un error al descargar el script.",
            "downloadTimeout":                  "Se agotó el tiempo de espera para la descarga del script.",
            "info_tooltip":                     "Atajos",
            "info_shortcuts_title":             "Atajos de Teclado",
            "info_header_shortcut":             "Atajo",
            "info_header_action":               "Acción",
            "info_shortcut_tab":                "Inserta un espacio de tabulación.",
            "info_shortcut_shift_enter":        "Inserta un salto de línea <br>.",
            "info_shortcut_ctrl_d":             "Envuelve la selección en una etiqueta <div>.",
            "info_shortcut_ctrl_p":             "Envuelve la selección en un párrafo <p>.",
            "info_shortcut_ctrl_m":             "Envuelve la selección en un bloque de código markdown.",
            "info_shortcut_ctrl_space":         "Inserta un espacio no separable  .",
            "prompt_link_text":                 "Texto del enlace:",
            "prompt_abbreviation_text":         "Texto de la abreviatura:",
            "border_style":                     "Estilo de Borde",
            "prompt_border_size":               "Tamaño del borde (px)",
            "prompt_border_color":              "Color del borde",
            "prompt_border_text":               "Texto",
            "prompt_border_tag_type":           "Tipo de Etiqueta",
            "border_text_placeholder":          "Texto"
        },
        "fr": {
            "langName":                         "Français",
            "languageSettings":                 "🌐 Langue",
            "close":                            "Fermer",
            "confirm":                          "Confirmer",
            "cancel":                           "Annuler",
            "download":                         "Télécharger",
            "compatible_with":                  "Compatible avec",
            "force_update":                     "🔄️ Forcer la mise à jour",
            "force_update_alert":               "Cache vidé. La page va se recharger pour récupérer les données mises à jour.",
            "titles":                           "Titres",
            "title_placeholder":                "Titre",
            "bold":                             "Gras",
            "bold_placeholder":                 "texte en gras",
            "italic":                           "Italique",
            "italic_placeholder":               "texte en italique",
            "underline":                        "Souligné",
            "underline_placeholder":            "texte souligné",
            "strikethrough":                    "Barré",
            "strikethrough_placeholder":        "texte barré",
            "unordered_list":                   "Liste non ordonnée",
            "ordered_list":                     "Liste ordonnée",
            "list_item_placeholder":            "Élément",
            "quote":                            "Citation",
            "inline_code":                      "Code en ligne",
            "inline_code_placeholder":          "code",
            "code_block":                       "Bloc de code",
            "code_block_placeholder":           "code ici",
            "horizontal_line":                  "Ligne horizontale",
            "horizontal_line_style":            "Style de ligne horizontale",
            "prompt_hr_size":                   "Taille (px)",
            "prompt_hr_color":                  "Couleur",
            "link":                             "Lien",
            "prompt_insert_url":                "Entrez l'URL :",
            "link_text_placeholder":            "texte du lien",
            "image":                            "Image",
            "prompt_insert_image_url":          "Entrez l'URL de l'image (https) :",
            "prompt_image_title":               "Titre de l'image (facultatif) :",
            "image_title_placeholder":          "ex. Ma belle image",
            "prompt_image_width":               "Largeur (facultatif) :",
            "prompt_image_height":              "Hauteur (facultatif) :",
            "video":                            "Vidéo",
            "prompt_video_type":                "Type de vidéo",
            "video_type_embed":                 "Intégrée (YouTube, Bilibili)",
            "video_type_html5":                 "Vidéo HTML5 (URL directe)",
            "prompt_video_poster_url":          "URL de l'image d'affiche",
            "prompt_insert_video_url":          "Entrez l'URL de la vidéo :",
            "prompt_video_width":               "Largeur (facultatif) :",
            "prompt_video_height":              "Hauteur (facultatif) :",
            "alert_invalid_video_url":          "URL de vidéo invalide ou non prise en charge.",
            "table":                            "Tableau",
            "prompt_columns":                   "Nombre de colonnes :",
            "prompt_rows":                      "Nombre de lignes :",
            "table_header_placeholder":         "En-tête",
            "table_cell_placeholder":           "Cellule",
            "subscript":                        "Indice",
            "subscript_placeholder":            "ind",
            "superscript":                      "Exposant",
            "superscript_placeholder":          "exp",
            "highlight":                        "Surligner",
            "highlight_placeholder":            "surligné",
            "keyboard":                         "Clavier",
            "keyboard_placeholder":             "Ctrl+C",
            "abbreviation":                     "Abréviation",
            "prompt_abbreviation_meaning":      "Que signifie l'abréviation ?",
            "abbreviation_placeholder":         "HTML",
            "text_color":                       "Couleur du texte",
            "colored_text_placeholder":         "texte coloré",
            "background_color":                 "Couleur de fond",
            "colored_background_placeholder":   "fond coloré",
            "details":                          "Section réductible",
            "details_summary_placeholder":      "Résumé ou Titre",
            "details_content_placeholder":      "Contenu à masquer...",
            "center":                           "Aligner au centre",
            "center_placeholder":               "texte centré",
            "notFound":                         "Code non trouvé !",
            "scriptIdNotFound":                 "Impossible d'identifier l'ID du script.",
            "downloading":                      "Téléchargement en cours...",
            "downloadError":                    "Une erreur s'est produite lors du téléchargement du script.",
            "downloadTimeout":                  "Le téléchargement du script a expiré.",
            "info_tooltip":                     "Raccourcis",
            "info_shortcuts_title":             "Raccourcis clavier",
            "info_header_shortcut":             "Raccourci",
            "info_header_action":               "Action",
            "info_shortcut_tab":                "Insère une tabulation.",
            "info_shortcut_shift_enter":        "Insère un saut de ligne <br>.",
            "info_shortcut_ctrl_d":             "Enveloppe la sélection dans une balise <div>.",
            "info_shortcut_ctrl_p":             "Enveloppe la sélection dans un paragraphe <p>.",
            "info_shortcut_ctrl_m":             "Enveloppe la sélection dans un bloc de code markdown.",
            "info_shortcut_ctrl_space":         "Insère un espace insécable  .",
            "prompt_link_text":                 "Texte du lien :",
            "prompt_abbreviation_text":         "Texte de l'abréviation :",
            "border_style":                     "Style de bordure",
            "prompt_border_size":               "Taille de la bordure (px)",
            "prompt_border_color":              "Couleur de la bordure",
            "prompt_border_text":               "Texte",
            "prompt_border_tag_type":           "Type de balise",
            "border_text_placeholder":          "Texte"
        },
        "zh-CN": {
            "langName":                         "简体中文",
            "languageSettings":                 "🌐 语言",
            "close":                            "关闭",
            "confirm":                          "确认",
            "cancel":                           "取消",
            "download":                         "下载",
            "compatible_with":                  "兼容",
            "force_update":                     "🔄️ 强制更新",
            "force_update_alert":               "缓存已清除。页面将重新加载以获取最新数据。",
            "titles":                           "标题",
            "title_placeholder":                "标题",
            "bold":                             "粗体",
            "bold_placeholder":                 "粗体文本",
            "italic":                           "斜体",
            "italic_placeholder":               "斜体文本",
            "underline":                        "下划线",
            "underline_placeholder":            "下划线文本",
            "strikethrough":                    "删除线",
            "strikethrough_placeholder":        "删除线文本",
            "unordered_list":                   "无序列表",
            "ordered_list":                     "有序列表",
            "list_item_placeholder":            "项目",
            "quote":                            "引用",
            "inline_code":                      "行内代码",
            "inline_code_placeholder":          "代码",
            "code_block":                       "代码块",
            "code_block_placeholder":           "在此处编写代码",
            "horizontal_line":                  "水平线",
            "horizontal_line_style":            "水平线样式",
            "prompt_hr_size":                   "大小 (px)",
            "prompt_hr_color":                  "颜色",
            "link":                             "链接",
            "prompt_insert_url":                "请输入网址:",
            "link_text_placeholder":            "链接文本",
            "image":                            "图片",
            "prompt_insert_image_url":          "请输入图片网址 (https):",
            "prompt_image_title":               "图片标题(可选):",
            "image_title_placeholder":          "例如:我美丽的图片",
            "prompt_image_width":               "宽度(可选):",
            "prompt_image_height":              "高度(可选):",
            "video":                            "视频",
            "prompt_video_type":                "视频类型",
            "video_type_embed":                 "嵌入 (YouTube, 哔哩哔哩)",
            "video_type_html5":                 "HTML5 视频 (直接链接)",
            "prompt_video_poster_url":          "封面图片链接 (poster)",
            "prompt_insert_video_url":          "请输入视频网址:",
            "prompt_video_width":               "宽度(可选):",
            "prompt_video_height":              "高度(可选):",
            "alert_invalid_video_url":          "无效或不支持的视频网址。",
            "table":                            "表格",
            "prompt_columns":                   "列数:",
            "prompt_rows":                      "行数:",
            "table_header_placeholder":         "标题",
            "table_cell_placeholder":           "单元格",
            "subscript":                        "下标",
            "subscript_placeholder":            "下标",
            "superscript":                      "上标",
            "superscript_placeholder":          "上标",
            "highlight":                        "标记",
            "highlight_placeholder":            "标记",
            "keyboard":                         "键盘",
            "keyboard_placeholder":             "Ctrl+C",
            "abbreviation":                     "缩写",
            "prompt_abbreviation_meaning":      "缩写的含义是什么?",
            "abbreviation_placeholder":         "HTML",
            "text_color":                       "文字颜色",
            "colored_text_placeholder":         "彩色文本",
            "background_color":                 "背景颜色",
            "colored_background_placeholder":   "彩色背景",
            "details":                          "可折叠部分",
            "details_summary_placeholder":      "摘要或标题",
            "details_content_placeholder":      "要隐藏的内容...",
            "center":                           "居中",
            "center_placeholder":               "居中文字",
            "notFound":                         "未找到代码!",
            "scriptIdNotFound":                 "无法识别脚本 ID。",
            "downloading":                      "下载中...",
            "downloadError":                    "下载脚本时发生错误。",
            "downloadTimeout":                  "脚本下载超时。",
            "info_tooltip":                     "快捷方式",
            "info_shortcuts_title":             "键盘快捷键",
            "info_header_shortcut":             "快捷键",
            "info_header_action":               "功能",
            "info_shortcut_tab":                "插入一个制表符。",
            "info_shortcut_shift_enter":        "插入一个换行符 <br>。",
            "info_shortcut_ctrl_d":             "将所选内容包裹在 <div> 标签中。",
            "info_shortcut_ctrl_p":             "将所选内容包裹在 <p> 段落中。",
            "info_shortcut_ctrl_m":             "将所选内容包裹在 markdown 代码块中。",
            "info_shortcut_ctrl_space":         "插入不间断空格  。",
            "prompt_link_text":                 "链接文本:",
            "prompt_abbreviation_text":         "缩写文本:",
            "border_style":                     "边框样式",
            "prompt_border_size":               "边框大小 (px)",
            "prompt_border_color":              "边框颜色",
            "prompt_border_text":               "文本",
            "prompt_border_tag_type":           "标签类型",
            "border_text_placeholder":          "文本"
        },
        "ja": {
            "langName":                         "日本語",
            "languageSettings":                 "🌐 言語",
            "close":                            "閉じる",
            "confirm":                          "確認",
            "cancel":                           "キャンセル",
            "download":                         "ダウンロード",
            "compatible_with":                  "互換性:",
            "force_update":                     "🔄️ 強制アップデート",
            "force_update_alert":               "キャッシュがクリアされました。ページがリロードされ、更新されたデータが取得されます。",
            "titles":                           "見出し",
            "title_placeholder":                "見出し",
            "bold":                             "太字",
            "bold_placeholder":                 "太字のテキスト",
            "italic":                           "斜体",
            "italic_placeholder":               "斜体のテキスト",
            "underline":                        "下線",
            "underline_placeholder":            "下線付きテキスト",
            "strikethrough":                    "取り消し線",
            "strikethrough_placeholder":        "取り消し線付きテキスト",
            "unordered_list":                   "順序なしリスト",
            "ordered_list":                     "順序付きリスト",
            "list_item_placeholder":            "アイテム",
            "quote":                            "引用",
            "inline_code":                      "インラインコード",
            "inline_code_placeholder":          "コード",
            "code_block":                       "コードブロック",
            "code_block_placeholder":           "ここにコード",
            "horizontal_line":                  "水平線",
            "horizontal_line_style":            "水平線のスタイル",
            "prompt_hr_size":                   "サイズ (px)",
            "prompt_hr_color":                  "色",
            "link":                             "リンク",
            "prompt_insert_url":                "URLを入力してください:",
            "link_text_placeholder":            "リンクテキスト",
            "image":                            "画像",
            "prompt_insert_image_url":          "画像URLを入力してください (https):",
            "prompt_image_title":               "画像のタイトル (任意):",
            "image_title_placeholder":          "例: 私の美しい画像",
            "prompt_image_width":               "幅 (任意):",
            "prompt_image_height":              "高さ (任意):",
            "video":                            "動画",
            "prompt_video_type":                "動画タイプ",
            "video_type_embed":                 "埋め込み (YouTube, Bilibili)",
            "video_type_html5":                 "HTML5 ビデオ (直接URL)",
            "prompt_video_poster_url":          "ポスター画像のURL",
            "prompt_insert_video_url":          "動画URLを入力してください:",
            "prompt_video_width":               "幅 (任意):",
            "prompt_video_height":              "高さ (任意):",
            "alert_invalid_video_url":          "無効またはサポートされていない動画URLです。",
            "table":                            "表",
            "prompt_columns":                   "列数:",
            "prompt_rows":                      "行数:",
            "table_header_placeholder":         "ヘッダー",
            "table_cell_placeholder":           "セル",
            "subscript":                        "下付き文字",
            "subscript_placeholder":            "下付き",
            "superscript":                      "上付き文字",
            "superscript_placeholder":          "上付き",
            "highlight":                        "ハイライト",
            "highlight_placeholder":            "ハイライトされたテキスト",
            "keyboard":                         "キーボード",
            "keyboard_placeholder":             "Ctrl+C",
            "abbreviation":                     "略語",
            "prompt_abbreviation_meaning":      "この略語は何の略ですか?",
            "abbreviation_placeholder":         "HTML",
            "text_color":                       "文字色",
            "colored_text_placeholder":         "色付きテキスト",
            "background_color":                 "背景色",
            "colored_background_placeholder":   "色付き背景",
            "details":                          "折りたたみ可能なセクション",
            "details_summary_placeholder":      "概要またはタイトル",
            "details_content_placeholder":      "非表示にするコンテンツ...",
            "center":                           "中央揃え",
            "center_placeholder":               "中央揃えのテキスト",
            "notFound":                         "コードが見つかりません!",
            "scriptIdNotFound":                 "スクリプトIDを特定できませんでした。",
            "downloading":                      "ダウンロード中...",
            "downloadError":                    "スクリプトのダウンロード中にエラーが発生しました。",
            "downloadTimeout":                  "スクリプトのダウンロードがタイムアウトしました。",
            "info_tooltip":                     "ショートカット",
            "info_shortcuts_title":             "キーボードショートカット",
            "info_header_shortcut":             "ショートカット",
            "info_header_action":               "アクション",
            "info_shortcut_tab":                "タブスペースを挿入します。",
            "info_shortcut_shift_enter":        "改行 <br> を挿入します。",
            "info_shortcut_ctrl_d":             "選択範囲を <div> タグで囲みます。",
            "info_shortcut_ctrl_p":             "選択範囲を <p> 段落で囲みます。",
            "info_shortcut_ctrl_m":             "選択範囲を Markdown コードブロックで囲みます。",
            "info_shortcut_ctrl_space":         "改行しないスペース   を挿入します。",
            "prompt_link_text":                 "リンクテキスト:",
            "prompt_abbreviation_text":         "略語テキスト:",
            "border_style":                     "枠線のスタイル",
            "prompt_border_size":               "枠線のサイズ (px)",
            "prompt_border_color":              "枠線の色",
            "prompt_border_text":               "テキスト",
            "prompt_border_tag_type":           "タグタイプ",
            "border_text_placeholder":          "テキスト"
        },
        "ko": {
            "langName":                         "한국어",
            "languageSettings":                 "🌐 언어",
            "close":                            "닫기",
            "confirm":                          "확인",
            "cancel":                           "취소",
            "download":                         "다운로드",
            "compatible_with":                  "호환 가능:",
            "force_update":                     "🔄️ 강제 업데이트",
            "force_update_alert":               "캐시가 지워졌습니다. 페이지를 새로고침하여 업데이트된 데이터를 가져옵니다.",
            "titles":                           "제목",
            "title_placeholder":                "제목",
            "bold":                             "굵게",
            "bold_placeholder":                 "굵은 텍스트",
            "italic":                           "기울임꼴",
            "italic_placeholder":               "기울임꼴 텍스트",
            "underline":                        "밑줄",
            "underline_placeholder":            "밑줄 친 텍스트",
            "strikethrough":                    "취소선",
            "strikethrough_placeholder":        "취소선 텍스트",
            "unordered_list":                   "순서 없는 목록",
            "ordered_list":                     "순서 있는 목록",
            "list_item_placeholder":            "항목",
            "quote":                            "인용",
            "inline_code":                      "인라인 코드",
            "inline_code_placeholder":          "코드",
            "code_block":                       "코드 블록",
            "code_block_placeholder":           "여기에 코드",
            "horizontal_line":                  "가로줄",
            "horizontal_line_style":            "가로줄 스타일",
            "prompt_hr_size":                   "크기 (px)",
            "prompt_hr_color":                  "색상",
            "link":                             "링크",
            "prompt_insert_url":                "URL을 입력하세요:",
            "link_text_placeholder":            "링크 텍스트",
            "image":                            "이미지",
            "prompt_insert_image_url":          "이미지 URL을 입력하세요 (https):",
            "prompt_image_title":               "이미지 제목 (선택 사항):",
            "image_title_placeholder":          "예: 내 아름다운 이미지",
            "prompt_image_width":               "너비 (선택 사항):",
            "prompt_image_height":              "높이 (선택 사항):",
            "video":                            "동영상",
            "prompt_video_type":                "비디오 유형",
            "video_type_embed":                 "임베드 (YouTube, Bilibili)",
            "video_type_html5":                 "HTML5 비디오 (직접 URL)",
            "prompt_video_poster_url":          "포스터 이미지 URL",
            "prompt_insert_video_url":          "동영상 URL을 입력하세요:",
            "prompt_video_width":               "너비 (선택 사항):",
            "prompt_video_height":              "높이 (선택 사항):",
            "alert_invalid_video_url":          "잘못되었거나 지원되지 않는 동영상 URL입니다.",
            "table":                            "표",
            "prompt_columns":                   "열 수:",
            "prompt_rows":                      "행 수:",
            "table_header_placeholder":         "헤더",
            "table_cell_placeholder":           "셀",
            "subscript":                        "아래 첨자",
            "subscript_placeholder":            "아래 첨자",
            "superscript":                      "위 첨자",
            "superscript_placeholder":          "위 첨자",
            "highlight":                        "강조",
            "highlight_placeholder":            "강조된 텍스트",
            "keyboard":                         "키보드",
            "keyboard_placeholder":             "Ctrl+C",
            "abbreviation":                     "약어",
            "prompt_abbreviation_meaning":      "이 약어는 무엇을 의미합니까?",
            "abbreviation_placeholder":         "HTML",
            "text_color":                       "텍스트 색상",
            "colored_text_placeholder":         "색깔 있는 텍스트",
            "background_color":                 "배경색",
            "colored_background_placeholder":   "색깔 있는 배경",
            "details":                          "접을 수 있는 섹션",
            "details_summary_placeholder":      "요약 또는 제목",
            "details_content_placeholder":      "숨길 내용...",
            "center":                           "가운데 정렬",
            "center_placeholder":               "가운데 정렬된 텍스트",
            "notFound":                         "코드를 찾을 수 없습니다!",
            "scriptIdNotFound":                 "스크립트 ID를 식별할 수 없습니다.",
            "downloading":                      "다운로드 중...",
            "downloadError":                    "스크립트를 다운로드하는 동안 오류가 발생했습니다.",
            "downloadTimeout":                  "스크립트 다운로드 시간이 초과되었습니다.",
            "info_tooltip":                     "단축키",
            "info_shortcuts_title":             "키보드 단축키",
            "info_header_shortcut":             "단축키",
            "info_header_action":               "동작",
            "info_shortcut_tab":                "탭 공백을 삽입합니다.",
            "info_shortcut_shift_enter":        "줄 바꿈 <br>을 삽입합니다.",
            "info_shortcut_ctrl_d":             "선택 항목을 <div> 태그로 래핑합니다.",
            "info_shortcut_ctrl_p":             "선택한 내용을 <p> 문단으로 감쌉니다.",
            "info_shortcut_ctrl_m":             "선택한 내용을 마크다운 코드 블록으로 감쌉니다.",
            "info_shortcut_ctrl_space":         "줄 바꿈되지 않는 공백   을 삽입합니다.",
            "prompt_link_text":                 "링크 텍스트:",
            "prompt_abbreviation_text":         "약어 텍스트:",
            "border_style":                     "테두리 스타일",
            "prompt_border_size":               "테두리 크기 (px)",
            "prompt_border_color":              "테두리 색상",
            "prompt_border_text":               "텍스트",
            "prompt_border_tag_type":           "태그 유형",
            "border_text_placeholder":          "텍스트"
        }
    };

    const translations = allTranslations;
    const icons = JSON.parse(GM_getResourceText("iconsJSON"));
    const myCss = GM_getResourceText("customCSS");

    GM_addStyle(myCss);

    function capitalizeCompatItem(item) {
        return item.replace(/\b\w/g, char => char.toUpperCase());
    }

    let currentLang         = 'en';
    let languageModal       = null;
    const CACHE_KEY         = 'Values';
    const LANG_STORAGE_KEY  = 'UserScriptLang';
    const LAST_TAG_TYPE_KEY = 'Tag';
    const LAST_COLOR_KEY    = 'Color';

    const SCRIPT_CONFIG = {
    notificationsUrl:   'https://gist.github.com/0H4S/d55d216b4487d64c606abb5d4f097fe0',
    scriptVersion:      '1.7',
    };
    const notifier = new ScriptNotifier(SCRIPT_CONFIG);
    notifier.run();

    function getTranslation(key) {
        return translations[currentLang] ?.[key] || translations.en[key];
    }

    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('zh')) currentLang = 'zh-CN';
        else if (browserLang.startsWith('en')) currentLang = 'en';
        else if (browserLang.startsWith('es')) currentLang = 'es';
        else if (browserLang.startsWith('fr')) currentLang = 'fr';
        else if (browserLang.startsWith('ja')) currentLang = 'ja';
        else if (browserLang.startsWith('ko')) currentLang = 'ko';
        else currentLang = 'en';
    }

    function registerLanguageMenu() {
        GM_registerMenuCommand(getTranslation('languageSettings'), () => {
            showModal(languageModal);
        });
    }

    function registerForceUpdateMenu() {
        GM_registerMenuCommand(getTranslation('force_update'), forceUpdate);
    }

    function showModal(modal) {
        if (!modal) return;
        modal.style.display = 'flex';
        setTimeout(() => {
            const box = modal.querySelector('.lang-modal-box');
            box.style.opacity = '1';
            box.style.transform = 'scale(1)';
        }, 10);
    }

    function hideModal(modal) {
        if (!modal) return;
        const box = modal.querySelector('.lang-modal-box');
        box.style.opacity = '0';
        box.style.transform = 'scale(0.95)';
        setTimeout(() => {
            modal.style.display = 'none';
        }, 200);
    }

    function createLanguageModal() {
        const overlay = document.createElement('div');
        overlay.className = 'lang-modal-overlay';
        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) {
                hideModal(overlay);
            }
        });
        const box = document.createElement('div');
        box.className = 'lang-modal-box';
        const buttonsContainer = document.createElement('div');
        buttonsContainer.className = 'lang-modal-buttons';
        Object.keys(translations).forEach(langKey => {
            const btn = document.createElement('button');
            btn.textContent = translations[langKey].langName;
            btn.onclick = async () => {
                await GM_setValue(LANG_STORAGE_KEY, langKey);
                window.location.reload();
            };
            buttonsContainer.appendChild(btn);
        });
        box.appendChild(buttonsContainer);
        overlay.appendChild(box);
        const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');

        function applyTheme(isDark) {
            box.classList.toggle('dark-theme', isDark);
            box.classList.toggle('light-theme', !isDark);
        }
        applyTheme(mediaQuery.matches);
        mediaQuery.addEventListener('change', e => applyTheme(e.matches));
        return overlay;
    }

    async function forceUpdate() {
        alert(getTranslation('force_update_alert'));
        await GM_deleteValue(CACHE_KEY);
        window.location.reload();
    }
    // #endregion

    // ================
    // #region ESTILIZAR
    // ================

    function isScriptPage() {
        const path = window.location.pathname;
        return /^\/([a-z]{2}(-[A-Z]{2})?\/)?scripts\/\d+-[^/]+$/.test(path);
    }

    function addAdditionalInfoSeparator() {
        const additionalInfo = document.getElementById('additional-info');
        if (additionalInfo && !additionalInfo.previousElementSibling?.matches('hr.bgs-info-separator')) {
            const hr = document.createElement('hr');
            hr.className = 'bgs-info-separator';
            additionalInfo.before(hr);
        }
    }

    function highlightScriptDescription() {
        const descriptionElements = document.querySelectorAll('#script-description, .script-description.description');
        descriptionElements.forEach(element => {
            const scriptLink = element.closest('article, li')?.querySelector('a.script-link');
            const path = scriptLink ? normalizeScriptPath(new URL(scriptLink.href).pathname) : normalizeScriptPath(window.location.pathname);
            if (element && element.parentElement.tagName !== 'BLOCKQUOTE') {
                const blockquoteWrapper = document.createElement('blockquote');
                blockquoteWrapper.className = 'script-description-blockquote';
                if (path) {
                    blockquoteWrapper.dataset.bgfPath = path;
                }
                element.parentNode.insertBefore(blockquoteWrapper, element);
                blockquoteWrapper.appendChild(element);
            }
        });
    }

    function makeDiscussionClickable() {
        document.querySelectorAll('.discussion-list-container').forEach(container => {
            container.removeEventListener('click', handleDiscussionClick);
            container.addEventListener('click', handleDiscussionClick);
        });
    }

    function handleDiscussionClick(e) {
        if (e.target.tagName === 'A' ||
            e.target.closest('a') ||
            e.target.closest('.user-link') ||
            e.target.closest('.badge-author') ||
            e.target.closest('.rating-icon')) {
            return;
        }
        const discussionLink = this.querySelector('.discussion-title');
        if (discussionLink && discussionLink.href) {
            window.location.href = discussionLink.href;
        }
    }

    function applySyntaxHighlighting() {
        document.querySelectorAll('pre code').forEach(block => {
            if (block.dataset.highlighted === 'true') { return; }
            const code = block.textContent;
            block.innerHTML = highlight(code);
            block.dataset.highlighted = 'true';
        });
    }

    function escapeHtml(str) {
        return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
    }

    function highlight(code) {
        const keywords = new Set(['const', 'let', 'var', 'function', 'return', 'if', 'else', 'for', 'while', 'of', 'in', 'async', 'await', 'try', 'catch', 'new', 'import', 'export', 'from', 'class', 'extends', 'super', 'true', 'false', 'null', 'undefined', 'document', 'window']);
        const tokens = [];
        let cursor = 0;

        const tokenDefinitions = [
            { type: 'url',              regex: /^(https?:\/\/[^\s"'`<>]+)/ },
            { type: 'comment-special',  regex: /^(\/\/[^\r\n]*)/ },
            { type: 'comment',          regex: /^(\/\*[\s\S]*?\*\/|<!--[\s\S]*?-->)/ },
            { type: 'string',           regex: /^(`(?:\\.|[^`])*`|"(?:\\.|[^"])*"|'(?:\\.|[^'])*')/ },
            { type: 'tag-punctuation',  regex: /^(&lt;\/?|\/&gt;|&gt;)/ },
            { type: 'tag-name',         regex: /^([\w-]+)/, context: (t) => { const l=t[t.length-1]; return l&&l.type==='tag-punctuation'&&l.content.startsWith('&lt;') }},
            { type: 'attribute',        regex: /^([\w-]+)/, context: (t) => { for(let i=t.length-1;i>=0;i--){const n=t[i];if(n.type==='tag-punctuation'&&n.content.includes('&gt;'))return!1;if(n.type==='tag-name')return!0;if(n.type==='whitespace')continue}return!1 }},
            { type: 'regex',            regex: /^(\/(?!\*)(?:[^\r\n/\\]|\\.)+\/[gimyus]*)/ },
            { type: 'number',           regex: /^\b-?(\d+(\.\d+)?)\b/ },
            { type: 'keyword',          regex: new RegExp(`^\\b(${Array.from(keywords).join('|')})\\b`) },
            { type: 'function',         regex: /^([a-zA-Z_][\w_]*)(?=\s*\()/ },
            { type: 'property',         regex: /^\.([a-zA-Z_][\w_]*)/ },
            { type: 'operator',         regex: /^(==?=?|!=?=?|=>|[+\-*/%&|^<>]=?|\?|:|=)/ },
            { type: 'punctuation',      regex: /^([,;(){}[\]])/ },
            { type: 'whitespace',       regex: /^\s+/ },
            { type: 'unknown',          regex: /^./ },
        ];
        let processedCode = escapeHtml(code);
        while (cursor < processedCode.length) {
            let matched = false;
            for (const def of tokenDefinitions) {
                if (def.context && !def.context(tokens)) { continue; }
                const match = def.regex.exec(processedCode.slice(cursor));
                if (match) {
                    const content = match[0];
                    if (def.type === 'function' && keywords.has(content)) { continue; }
                    tokens.push({ type: def.type, content });
                    cursor += content.length;
                    matched = true;
                    break;
                }
            }
            if (!matched) {
                 tokens.push({ type: 'unknown', content: processedCode[cursor] });
                 cursor++;
            }
        }
        for (let i = 0; i < tokens.length; i++) {
            if (tokens[i].type === 'string') {
                let nextToken = null;
                for(let j=i+1;j<tokens.length;j++){if(tokens[j].type!=='whitespace'){nextToken=tokens[j];break}}
                if (nextToken && nextToken.content === ':') { tokens[i].type = 'json-key'; }
            }
        }
        return tokens.map(token => {
            if (['whitespace', 'unknown', 'url'].includes(token.type)) return token.content;
            if (token.type === 'property') return `<span class="sh-punctuation">.</span><span class="sh-property">${token.content.slice(1)}</span>`;
            return `<span class="sh-${token.type}">${token.content}</span>`;
        }).join('');
    }
    // #endregion

    // ================
    // #region ÍCONES
    // ================

    let iconCache;
    const processedKeys = new Set();

    async function saveCache() {
        await GM_setValue(CACHE_KEY, iconCache);
    }

    function normalizeScriptPath(pathname) {
        let withoutLocale = pathname.replace(/^\/[a-z]{2}(?:-[A-Z]{2})?\//, '/');
        const match = withoutLocale.match(/^\/scripts\/\d+-.+?(?=\/|$)/);
        return match ? match[0] : null;
    }

    function extractScriptIdFromNormalizedPath(normalized) {
        const match = normalized.match(/\/scripts\/(\d+)-/);
        return match ? match[1] : null;
    }

    function createIconElement(src, isHeader = false) {
        const img = document.createElement('img');
        img.src = src;
        img.alt = '';
        if (isHeader) {
            img.style.cssText = `
                width: 80px;
                height: 80px;
                margin-right: 10px;
                vertical-align: middle;
                border-radius: 4px;
                object-fit: contain;
                pointer-events: none;
            `;
        } else {
            img.style.cssText = `
                width: 40px;
                height: 40px;
                margin-right: 8px;
                vertical-align: middle;
                border-radius: 3px;
                object-fit: contain;
                pointer-events: none;
            `;
        }
        img.loading = 'lazy';
        return img;
    }

    function extractMetadataFromContent(content) {
        if (typeof content !== 'string') return {};
        const metadata = {};
        const lines = content.split('\n');
        const supportedTags = new Set([ '@icon', '@bgf-colorLT', '@bgf-colorDT', '@bgf-compatible', '@bgf-copyright', '@bgf-social' ]);
        for (const line of lines) {
            const trimmedLine = line.trim();
            if (trimmedLine.startsWith('// ==/UserScript==')) break;
            if (!trimmedLine.startsWith('// @')) continue;
            const match = trimmedLine.match(/\/\/\s*(@[a-zA-Z0-9-]+)\s+(.+)/);
            if (!match) continue;
            const key = match[1];
            let value = match[2].trim();
            if (supportedTags.has(key) && !metadata.hasOwnProperty(key)) {
                if (key === '@bgf-colorLT' || key === '@bgf-colorDT') {
                    const colorRegex = /(#[0-9a-fA-F]{3,8}|(?:rgba?|hsla?)\s*\([^)]+\))/;
                    const colorMatch = value.match(colorRegex);
                    if (colorMatch) {
                        value = colorMatch[0];
                    } else {
                        value = value.split(',')[0].trim();
                    }
                }
                metadata[key] = value;
            }
        }
        return metadata;
    }

    function isValidIconUrl(url) {
        return url && (url.startsWith('http') || url.startsWith(''));
    }

    async function processScript(normalizedPath, targetElement, isHeader = false) {
        if (processedKeys.has(normalizedPath) && isHeader) {
            applyBfgFeatures(iconCache[normalizedPath]);
        }
        if (processedKeys.has(normalizedPath) && !isHeader) {
            const cached = iconCache[normalizedPath];
            if (cached && isValidIconUrl(cached.iconUrl)) {
                targetElement.prepend(createIconElement(cached.iconUrl, isHeader));
            }
            return;
        }
        processedKeys.add(normalizedPath);
        const cached = iconCache[normalizedPath];
        const now = Date.now();
        const applyColorToBlockquote = (metadata) => {
            const blockquotes = document.querySelectorAll(`blockquote.script-description-blockquote[data-bgf-path="${normalizedPath}"]`);
            if (blockquotes.length === 0) return;

            const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
            const colorToApply = isDarkMode ? metadata.bgfColorDT : metadata.bgfColorLT;

            blockquotes.forEach(bq => {
                if (colorToApply) {
                    bq.style.setProperty('border-left-color', colorToApply, 'important');
                } else {
                    bq.style.removeProperty('border-left-color');
                }
            });
        };
        if (cached && now - cached.ts < 7 * 24 * 60 * 60 * 1000) {
            if (isValidIconUrl(cached.iconUrl)) {
                targetElement.prepend(createIconElement(cached.iconUrl, isHeader));
            }
            applyColorToBlockquote(cached);
            if (isHeader) {
                applyBfgFeatures(cached);
            }
            return;
        }
        const scriptId = extractScriptIdFromNormalizedPath(normalizedPath);
        if (!scriptId) {
            iconCache[normalizedPath] = { ts: now };
            await saveCache();
            return;
        }
        const scriptUrl = `https://update.greasyfork.icu/scripts/${scriptId}.js`;
        GM_xmlhttpRequest({
            method: 'GET',
            url: scriptUrl,
            timeout: 6000,
            onload: async function (res) {
                if (typeof res.responseText !== 'string') {
                    iconCache[normalizedPath] = { ts: now };
                    await saveCache();
                    return;
                }
                const rawMetadata = extractMetadataFromContent(res.responseText);
                const metadata = {
                    iconUrl:        rawMetadata['@icon']            || null,
                    bgfColorLT:     rawMetadata['@bgf-colorLT']     || null,
                    bgfColorDT:     rawMetadata['@bgf-colorDT']     || null,
                    bgfCompatible:  rawMetadata['@bgf-compatible']  || null,
                    bgfCopyright:   rawMetadata['@bgf-copyright']   || null,
                    bgfSocial:      rawMetadata['@bgf-social']      || null,
                    ts:             now
                };
                iconCache[normalizedPath] = metadata;
                await saveCache();
                if (isValidIconUrl(metadata.iconUrl)) {
                    targetElement.prepend(createIconElement(metadata.iconUrl, isHeader));
                }
                applyColorToBlockquote(metadata);
                if (isHeader) {
                    applyBfgFeatures(metadata);
                }
            },
            onerror: async function () {
                iconCache[normalizedPath] = { ts: now };
                await saveCache();
            }
        });
    }

    function handleScriptLink(linkEl) {
        if (linkEl._handled) return;
        linkEl._handled = true;
        const href = linkEl.getAttribute('href');
        if (!href || !href.startsWith('/')) return;
        try {
            const url = new URL(href, window.location.origin);
            const normalized = normalizeScriptPath(url.pathname);
            if (!normalized) return;
            setTimeout(() => processScript(normalized, linkEl, false), 0);
        } catch (e) {}
    }

    function handleMainHeaderH2() {
        const headers = document.querySelectorAll('header');
        for (const header of headers) {
            const h2 = header.querySelector('h2');
            const desc = header.querySelector('p.script-description');
            if (h2 && desc && !h2._handled) {
                h2._handled = true;
                const normalized = normalizeScriptPath(window.location.pathname);
                if (!normalized) return;
                setTimeout(() => processScript(normalized, h2, true), 0);
                break;
            }
        }
    }

    function processIconElements() {
        document.querySelectorAll('a.script-link:not([data-icon-processed])')
            .forEach(el => {
                el.setAttribute('data-icon-processed', '1');
                handleScriptLink(el);
            });
        handleMainHeaderH2();
    }
    // #endregion

    // ================
    // #region METADADOS
    // ================

    function applyBfgFeatures(metadata) {
        if (!metadata) return;
        applyBfgCompatibility(metadata.bgfCompatible);
        applyBfgCopyright(metadata.bgfCopyright);
        applyBfgSocial(metadata.bgfSocial);
    }

    function applyBfgCompatibility(compatValue) {
        if (!compatValue) return;
        const compatDd = document.querySelector('dd.script-show-compatibility');
        if (!compatDd) {
            return;
        }
        let compatContainer = compatDd.querySelector('span');
        if (!compatContainer) {
            compatContainer = document.createElement('span');
            compatDd.innerHTML = '';
            compatDd.appendChild(compatContainer);
        }
        const compatItems = compatValue.split(',').map(item => item.trim().toLowerCase());
        compatItems.forEach(item => {
            if (!icons[item] || compatContainer.querySelector(`.bgf-compat-${item}`)) {
                return;
            }
            const img = document.createElement('img');
            img.className = `browser-compatible bgf-compat-${item}`;
            const displayName = capitalizeCompatItem(item);
            img.alt = `${getTranslation('compatible_with')} ${displayName}`;
            img.title = `${getTranslation('compatible_with')} ${displayName}`;
            img.style.marginLeft = '1px';
            img.src = `data:image/svg+xml;utf8,${encodeURIComponent(icons[item])}`;
            compatContainer.appendChild(img);
        });
    }

    function reapplyAllBlockquoteColors() {
        const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
        const allBlockquotes = document.querySelectorAll('blockquote.script-description-blockquote[data-bgf-path]');
        allBlockquotes.forEach(bq => {
            const path = bq.dataset.bgfPath;
            if (!path || !iconCache[path]) return;
            const metadata = iconCache[path];
            const colorToApply = isDarkMode ? metadata.bgfColorDT : metadata.bgfColorLT;
            if (colorToApply) {
                bq.style.setProperty('border-left-color', colorToApply, 'important');
            } else {
                bq.style.removeProperty('border-left-color');
            }
        });
    }

    function setupThemeChangeListener() {
        const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
        mediaQuery.addEventListener('change', reapplyAllBlockquoteColors);
    }

    function applyBfgCopyright(copyrightValue) {
        if (!copyrightValue || document.querySelector('.script-show-copyright')) return;
        const copyrightRegex = /\[(.{1,50})\]\((https:\/\/gist\.github\.com\/[^)]+)\)/;
        const match = copyrightValue.match(copyrightRegex);
        if (!match) return;
        const licenseDd = document.querySelector('dd.script-show-license');
        if (!licenseDd) return;
        const text = match[1];
        const url = match[2];
        const copyrightDt = document.createElement('dt');
        copyrightDt.className = 'script-show-copyright';
        copyrightDt.innerHTML = '<span>Copyright</span>';
        const copyrightDd = document.createElement('dd');
        copyrightDd.className = 'script-show-copyright';
        copyrightDd.style.alignSelf = 'center';
        const link = document.createElement('a');
        link.href = url;
        link.textContent = text;
        link.target = '_blank';
        link.rel = 'noopener noreferrer';
        const span = document.createElement('span');
        span.appendChild(link);
        copyrightDd.appendChild(span);
        licenseDd.after(copyrightDt, copyrightDd);
    }

    function applyBfgSocial(socialValue) {
        if (!socialValue || document.querySelector('.script-show-social')) return;
        const authorDd = document.querySelector('dd.script-show-author');
        if (!authorDd) return;
        const socialDomainMap = {
            'instagram.com':    { icon: icons.instagram,    name: 'Instagram'   },
            'facebook.com':     { icon: icons.facebook,     name: 'Facebook'    },
            'x.com':            { icon: icons.x,            name: 'X / Twitter' },
            'youtube.com':      { icon: icons.youtube,      name: 'YouTube'     },
            'bilibili.com':     { icon: icons.bilibili,     name: 'Bilibili'    },
            'tiktok.com':       { icon: icons.tiktok,       name: 'TikTok'      },
            'douyin.com':       { icon: icons.tiktok,       name: 'Douyin'      },
            'github.com':       { icon: icons.github,       name: 'GitHub'      },
            'linkedin.com':     { icon: icons.linkedin,     name: 'LinkedIn'    },
        };
        const urls = socialValue.split(',').map(url => url.trim());
        const validLinks = [];
        let tiktokFamilyProcessed = false;
        urls.forEach(url => {
            try {
                const domain = new URL(url).hostname.replace('www.', '');
                if (socialDomainMap[domain]) {
                    if (domain === 'tiktok.com' || domain === 'douyin.com') {
                        if (tiktokFamilyProcessed) return;
                        tiktokFamilyProcessed = true;
                    }
                    validLinks.push({ url, ...socialDomainMap[domain] });
                }
            } catch (e) {}
        });
        if (validLinks.length === 0) return;
        const socialDt = document.createElement('dt');
        socialDt.className = 'script-show-social';
        socialDt.innerHTML = '<span>Social</span>';
        const socialDd = document.createElement('dd');
        socialDd.className = 'script-show-social';
        socialDd.style.cssText = 'display: flex; gap: 8px; align-items: center; align-self: center; z-index: 10;';
        validLinks.forEach(linkInfo => {
            const link = document.createElement('a');
            link.href = linkInfo.url;
            link.title = linkInfo.name;
            link.target = '_blank';
            link.rel = 'noopener noreferrer';
            link.innerHTML = linkInfo.icon;
            const svg = link.querySelector('svg');
            if (svg) {
                svg.style.width = '20px';
                svg.style.height = '20px';
                svg.style.verticalAlign = 'middle';
            }
            socialDd.appendChild(link);
        });
        authorDd.after(socialDt, socialDd);
    }
    // #endregion

    // ================
    // #region EDITOR HTML
    // ================

    function insertText(textarea, prefix, suffix = '', placeholder = '') {
        const start = textarea.selectionStart;
        const end = textarea.selectionEnd;
        const selected = textarea.value.substring(start, end);
        const text = selected || placeholder;
        if (!selected && !placeholder) {
            textarea.setRangeText(prefix + suffix, start, end);
            const cursorPosition = start + prefix.length;
            textarea.setSelectionRange(cursorPosition, cursorPosition);
        } else {
            textarea.setRangeText(prefix + text + suffix, start, end, selected ? 'end' : 'select');
        }
        textarea.focus();
    }

    function createToolbarButton(def) {
        const btn = document.createElement('button');
        btn.type = 'button';
        btn.className = 'txt-editor-toolbar-button';
        btn.dataset.tooltip = def.title;
        btn.innerHTML = def.icon || def.label;
        btn.addEventListener('click', e => {
            e.preventDefault();
            def.action();
        });
        return btn;
    }

    function showCustomAlert(message) {
        const overlay = document.createElement('div');
        overlay.className = 'custom-prompt-overlay';
        const modal = document.createElement('div');
        modal.className = 'custom-prompt-box custom-alert-box';
        const editorContainer = document.querySelector('.txt-editor-container');
        modal.classList.add(editorContainer && editorContainer.classList.contains('dark-theme') ? 'dark-theme' : 'light-theme');
        const messageP = document.createElement('p');
        messageP.textContent = message;
        const closeBtn = document.createElement('button');
        closeBtn.textContent = getTranslation('close');
        closeBtn.className = 'custom-prompt-confirm';
        closeBtn.onclick = () => document.body.removeChild(overlay);
        modal.append(messageP, closeBtn);
        overlay.appendChild(modal);
        document.body.appendChild(overlay);
        closeBtn.focus();
    }

    function showCustomPrompt({ inputs, onConfirm }) {
        const overlay = document.createElement('div');
        overlay.className = 'custom-prompt-overlay';
        const modal = document.createElement('div');
        modal.className = 'custom-prompt-box';
        const editorContainer = document.querySelector('.txt-editor-container');
        modal.classList.add(editorContainer && editorContainer.classList.contains('dark-theme') ? 'dark-theme' : 'light-theme');
        const form = document.createElement('form');
        const inputsMap = new Map();
        inputs.forEach(config => {
            const label = document.createElement('label');
            label.textContent = config.label;
            let field;
            if (config.type === 'select') {
                field = document.createElement('select');
                (config.options || []).forEach(opt => {
                    const option = document.createElement('option');
                    option.value = opt.value;
                    option.textContent = opt.text;
                    if (config.value && opt.value === config.value) {
                        option.selected = true;
                    }
                    field.appendChild(option);
                });
            } else {
                field = document.createElement('input');
                field.type = config.type || 'text';
                field.placeholder = config.placeholder || '';
                field.value = config.value || '';
                field.required = config.required !== false;
                if (config.type === 'number') field.min = '1';
            }
            label.appendChild(field);
            form.appendChild(label);
            inputsMap.set(config.id, field);
        });
        const buttons = document.createElement('div');
        buttons.className = 'custom-prompt-buttons';
        const confirmBtn = document.createElement('button');
        confirmBtn.type = 'submit';
        confirmBtn.textContent = getTranslation('confirm');
        confirmBtn.className = 'custom-prompt-confirm';
        const cancelBtn = document.createElement('button');
        cancelBtn.type = 'button';
        cancelBtn.textContent = getTranslation('cancel');
        cancelBtn.className = 'custom-prompt-cancel';
        cancelBtn.onclick = () => document.body.removeChild(overlay);
        form.onsubmit = (e) => {
            e.preventDefault();
            const results = {};
            for (const [id, inputElement] of inputsMap.entries()) {
                results[id] = inputElement.value;
            }
            onConfirm(results);
            document.body.removeChild(overlay);
        };
        buttons.append(confirmBtn, cancelBtn);
        form.appendChild(buttons);
        modal.appendChild(form);
        overlay.appendChild(modal);
        document.body.appendChild(overlay);
        inputsMap.values().next().value.focus();
    }

    function showInfoModal() {
        const overlay = document.createElement('div');
        overlay.className = 'custom-prompt-overlay info-modal-overlay';
        overlay.style.display = 'flex';
        const modal = document.createElement('div');
        modal.className = 'custom-prompt-box info-modal-box';
        const editorContainer = document.querySelector('.txt-editor-container');
        modal.classList.add(editorContainer && editorContainer.classList.contains('dark-theme') ? 'dark-theme' : 'light-theme');
        modal.innerHTML = `
            <h2>${getTranslation('info_shortcuts_title')}</h2>
            <div class="info-shortcuts">
                <table>
                    <thead>
                        <tr>
                            <th>${getTranslation('info_header_shortcut')}</th>
                            <th>${getTranslation('info_header_action')}</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td><code>Tab</code></td>
                            <td>${getTranslation('info_shortcut_tab')}</td>
                        </tr>
                        <tr>
                            <td><code>Shift + Enter</code></td>
                            <td>${getTranslation('info_shortcut_shift_enter')}</td>
                        </tr>
                        <tr>
                            <td><code>Ctrl + D</code></td>
                            <td>${getTranslation('info_shortcut_ctrl_d')}</td>
                        </tr>
                        <tr>
                            <td><code>Ctrl + P</code></td>
                            <td>${getTranslation('info_shortcut_ctrl_p')}</td>
                        </tr>
                        <tr>
                            <td><code>Ctrl + M</code></td>
                            <td>${getTranslation('info_shortcut_ctrl_m')}</td>
                        </tr>
                        <tr>
                            <td><code>Ctrl + Space</code></td>
                            <td>${getTranslation('info_shortcut_ctrl_space')}</td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <div class="custom-prompt-buttons">
                <button class="custom-prompt-cancel">${getTranslation('close')}</button>
            </div>
        `;
        overlay.appendChild(modal);
        document.body.appendChild(overlay);
        overlay.querySelector('.custom-prompt-cancel').onclick = () => document.body.removeChild(overlay);
        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) {
                document.body.removeChild(overlay);
            }
        });
    }

    async function createTextStyleEditor(textarea) {
        if (textarea.dataset.editorApplied) return;
        textarea.dataset.editorApplied = 'true';
        textarea.addEventListener('keydown', function(e) {
            if (e.key === 'Tab') {
                e.preventDefault();
                const start = this.selectionStart;
                const end = this.selectionEnd;
                this.setRangeText('   ', start, end, 'end');
            }
            if (e.shiftKey && e.key === 'Enter') {
                e.preventDefault();
                const start = this.selectionStart;
                const end = this.selectionEnd;
                this.setRangeText('\n<br>\n', start, end, 'end');
            }
            if (e.ctrlKey && !e.shiftKey && e.key.toLowerCase() === 'd') {
                e.preventDefault();
                insertText(this, '<div>\n', '\n</div>', '');
            }
            if (e.ctrlKey && !e.shiftKey && e.key.toLowerCase() === 'p') {
                e.preventDefault();
                insertText(this, '<p>', '</p>', '');
            }
            if (e.ctrlKey && !e.shiftKey && e.key.toLowerCase() === 'm') {
                e.preventDefault();
                insertText(this, '```\n', '\n```', '');
            }
            if (e.ctrlKey && !e.shiftKey && e.key === ' ') {
                e.preventDefault();
                insertText(this, '&nbsp;', '', '');
            }
        });
        const container = document.createElement('div');
        container.className = 'txt-editor-container';
        const toolbar = document.createElement('div');
        toolbar.className = 'txt-editor-toolbar';
        const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');

        function applyTheme(isDark) {
            container.classList.toggle('dark-theme', isDark);
            container.classList.toggle('light-theme', !isDark);
        }
        applyTheme(mediaQuery.matches);
        mediaQuery.addEventListener('change', e => applyTheme(e.matches));
        const tools = [
            { type: 'select', title: getTranslation('titles'), options: { 'H1': '1', 'H2': '2', 'H3': '3', 'H4': '4', 'H5': '5', 'H6': '6' }, action: (val) => insertText(textarea, `<h${val}>`, `</h${val}>`, getTranslation('title_placeholder')) },
            { type: 'divider' },
            { title: getTranslation('bold'),            icon:   icons.bold,             action: () => insertText(textarea, '<strong>', '</strong>',         getTranslation('bold_placeholder')) },
            { title: getTranslation('italic'),          icon:   icons.italic,           action: () => insertText(textarea, '<em>', '</em>',                 getTranslation('italic_placeholder')) },
            { title: getTranslation('underline'),       icon:   icons.underline,        action: () => insertText(textarea, '<u>', '</u>',                   getTranslation('underline_placeholder')) },
            { title: getTranslation('strikethrough'),   icon:   icons.strikethrough,    action: () => insertText(textarea, '<s>', '</s>',                   getTranslation('strikethrough_placeholder')) },
            { type: 'divider' },
            { title: getTranslation('unordered_list'),  icon:   icons.ul,               action: () => { const start = textarea.selectionStart; const end = textarea.selectionEnd; const selection = textarea.value.substring(start, end); const items = selection ? selection.split('\n').map(line => `  <li>${line}</li>`).join('\n') : `  <li>${getTranslation('list_item_placeholder')}</li>`; const listHtml = `<ul>\n${items}\n</ul>`; textarea.setRangeText(listHtml, start, end, 'select'); textarea.focus(); } },
            { title: getTranslation('ordered_list'),    icon:   icons.ol,               action: () => { const start = textarea.selectionStart; const end = textarea.selectionEnd; const selection = textarea.value.substring(start, end); const items = selection ? selection.split('\n').map(line => `  <li>${line}</li>`).join('\n') : `  <li>${getTranslation('list_item_placeholder')}</li>`; const listHtml = `<ol>\n${items}\n</ol>`; textarea.setRangeText(listHtml, start, end, 'select');textarea.focus(); } },
            { title: getTranslation('details'),         label:  icons.details,          action: () => insertText(textarea, '\n<details>\n  <summary>' +     getTranslation('details_summary_placeholder') + '</summary>\n\n  ' + getTranslation('details_content_placeholder') + '\n\n</details>\n') },
            { title: getTranslation('center'),          label:  icons.center,           action: () => insertText(textarea, '\n<center>\n', '\n</center>',   getTranslation('center_placeholder')) },
            { type: 'divider' },
            { title: getTranslation('quote'),           icon:   icons.quote,            action: () => { const start = textarea.selectionStart; const end = textarea.selectionEnd; const selection = textarea.value.substring(start, end); const content = selection ? selection.replace(/\n/g, '<br>\n  ') : getTranslation('quote'); const quoteHtml = `\n<blockquote>\n  ${content}\n</blockquote>\n`; textarea.setRangeText(quoteHtml, start, end, 'select'); textarea.focus(); } },
            { title: getTranslation('inline_code'),     icon:   icons.code,             action: () => insertText(textarea, '<code>', '</code>',             getTranslation('inline_code_placeholder')) },
            { title: getTranslation('code_block'),      label:  icons.code_block,       action: () => insertText(textarea, '<pre><code>', '</code></pre>',  getTranslation('code_block_placeholder')) },
            { title: getTranslation('horizontal_line'), icon:   icons.hr,               action: () => insertText(textarea, '\n<hr>\n') },
            { type: 'divider' },
            { title: getTranslation('link'),            icon:   icons.link,             action: () => { const start = textarea.selectionStart; const end = textarea.selectionEnd; const selectedText = textarea.value.substring(start, end); showCustomPrompt({ inputs: [ { id: 'url', label: getTranslation('prompt_insert_url'), placeholder: 'https://', type: 'url', required: true }, { id: 'text', label: getTranslation('prompt_link_text'), placeholder: getTranslation('link_text_placeholder'), value: selectedText, required: false } ], onConfirm: ({ url, text }) => { if (url) { const linkText = text || selectedText || url; const selectionMode = selectedText ? 'end' : 'select'; textarea.setRangeText(`<a href="${url}">${linkText}</a>`, start, end, selectionMode); textarea.focus(); } } }); } },
            { title: getTranslation('image'),           icon:   icons.image,            action: () => showCustomPrompt({ inputs: [ { id: 'src', label:      getTranslation('prompt_insert_image_url'), placeholder: 'https://', type: 'url' }, { id: 'title', label: getTranslation('prompt_image_title'), placeholder: getTranslation('image_title_placeholder'), required: false }, { id: 'width', label: getTranslation('prompt_image_width'), placeholder: '500px', type: 'number', required: false }, { id: 'height', label: getTranslation('prompt_image_height'), placeholder: '500px', type: 'number', required: false } ], onConfirm: ({ src, title, width, height }) => { if (src) { const titleAttr = title ? ` title="${title}"` : ''; const widthAttr = width ? ` width="${width}"` : ''; const heightAttr = height ? ` height="${height}"` : ''; insertText(textarea, `<img src="${src}"${titleAttr}${widthAttr}${heightAttr}>`); } } }) },
            { title: getTranslation('table'),           icon:   icons.table,            action: () => showCustomPrompt({ inputs: [ { id: 'cols', label:     getTranslation('prompt_columns'), type: 'number', value: '3' }, { id: 'rows', label: getTranslation('prompt_rows'), type: 'number', value: '2' } ], onConfirm: ({ cols, rows }) => { const numCols = parseInt(cols, 10) || 3; const numRows = parseInt(rows, 10) || 2; let table = '<table>\n  <thead>\n    <tr>\n'; table += '      ' + Array(numCols).fill(`<th>${getTranslation('table_header_placeholder')}</th>`).join('\n      ') + '\n    </tr>\n  </thead>\n  <tbody>\n'; for (let i = 0; i < numRows; i++) { table += '    <tr>\n'; table += '      ' + Array(numCols).fill(`<td>${getTranslation('table_cell_placeholder')}</td>`).join('\n      ') + '\n    </tr>\n'; } table += '  </tbody>\n</table>'; insertText(textarea, `\n${table}\n`); } }) },
            { title: getTranslation('video'),           icon:   icons.video,            action: () => showCustomPrompt({ inputs: [ { id: 'type', label:     getTranslation('prompt_video_type'), type: 'select', options: [ { value: 'embed', text: getTranslation('video_type_embed') }, { value: 'html5', text: getTranslation('video_type_html5') } ]}, { id: 'url', label: getTranslation('prompt_insert_video_url'), placeholder: 'https://', type: 'url' }, { id: 'poster', label: getTranslation('prompt_video_poster_url'), placeholder: 'https://image.jpg', type: 'url', required: false }, { id: 'width', label: getTranslation('prompt_video_width'), placeholder: '560', type: 'number', required: false }, { id: 'height', label: getTranslation('prompt_video_height'), placeholder: '315', type: 'number', required: false } ], onConfirm: ({ type, url, poster, width, height }) => { if (!url) return; const widthAttr = width ? ` width="${width}"` : ''; const heightAttr = height ? ` height="${height}"` : ''; if (type === 'html5') { const posterAttr = poster ? ` poster="${poster}"` : ''; const videoTag = `\n<video src="${url}"${posterAttr}${widthAttr}${heightAttr} controls></video>\n`; insertText(textarea, videoTag); } else { let src = ''; try { if (url.includes('youtube.com/watch?v=')) { src = `https://www.youtube.com/embed/${new URL(url).searchParams.get('v')}`; } else if (url.includes('youtu.be/')) { src = `https://www.youtube.com/embed/${new URL(url).pathname.substring(1)}`; } else if (url.includes('bilibili.com/video/')) { src = `https://player.bilibili.com/player.html?bvid=${new URL(url).pathname.split('/')[2]}`; } } catch { src = ''; } if (src) { insertText(textarea, `\n<iframe src="${src}"${widthAttr}${heightAttr} allowfullscreen></iframe>\n`); } else { showCustomAlert(getTranslation('alert_invalid_video_url')); } } } }) },
            { type: 'divider' },
            { title: getTranslation('subscript'),       label:  icons.subscript,        action: () => insertText(textarea, '<sub>', '</sub>',               getTranslation('subscript_placeholder')) },
            { title: getTranslation('superscript'),     label:  icons.superscript,      action: () => insertText(textarea, '<sup>', '</sup>',               getTranslation('superscript_placeholder')) },
            { title: getTranslation('highlight'),       label:  icons.highlight,        action: () => insertText(textarea, '<mark>', '</mark>',             getTranslation('highlight_placeholder')) },
            { title: getTranslation('keyboard'),        label:  icons.keyboard,         action: () => insertText(textarea, '<kbd>', '</kbd>',               getTranslation('keyboard_placeholder')) },
            { title: getTranslation('abbreviation'),    label:  icons.abbreviation,     action: () => { const start = textarea.selectionStart; const end = textarea.selectionEnd; const selectedText = textarea.value.substring(start, end); showCustomPrompt({ inputs: [ { id: 'title', label: getTranslation('prompt_abbreviation_meaning'), required: true }, { id: 'text', label: getTranslation('prompt_abbreviation_text'), placeholder: getTranslation('abbreviation_placeholder'), value: selectedText, required: true } ], onConfirm: ({ title, text }) => { if (title && text) { const selectionMode = selectedText ? 'end' : 'select'; textarea.setRangeText(`<abbr title="${title}">${text}</abbr>`, start, end, selectionMode); textarea.focus(); } } }); } },
            { type: 'color-picker' }
        ];
        for (const tool of tools) {
            if (tool.type === 'divider') {
                const div = document.createElement('div');
                div.className = 'txt-editor-toolbar-divider';
                toolbar.appendChild(div);
            } else if (tool.type === 'select') {
                const container = document.createElement('span');
                container.className = 'txt-editor-toolbar-button';
                container.dataset.tooltip = tool.title;
                container.style.position = 'relative';
                container.style.display = 'flex';
                container.style.alignItems = 'center';
                container.style.justifyContent = 'center';
                container.innerHTML = icons.h;
                const select = document.createElement('select');
                select.className = 'txt-editor-toolbar-select';
                select.style.cssText = ` -webkit-appearance: none; appearance: none; background: transparent; border: none; color: transparent; position: absolute; top: 0; left: 0; width: 100%; height: 100%; cursor: pointer; `;
                const placeholderOpt = document.createElement('option');
                placeholderOpt.value = '';
                placeholderOpt.textContent = '';
                placeholderOpt.disabled = true;
                placeholderOpt.selected = true;
                placeholderOpt.style.display = 'none';
                select.appendChild(placeholderOpt);
                Object.keys(tool.options).forEach(key => {
                    const opt = document.createElement('option');
                    opt.value = tool.options[key];
                    opt.textContent = key;
                    select.appendChild(opt);
                });
                select.addEventListener('change', () => {
                    if (select.value) tool.action(select.value);
                    select.selectedIndex = 0;
                });
                container.appendChild(select);
                toolbar.appendChild(container);
            } else if (tool.type === 'color-picker') {
                const colorContainer = document.createElement('div');
                colorContainer.className = 'txt-color-picker-container';
                const input = document.createElement('input');
                input.type = 'color';
                input.className = 'txt-color-picker-input';
                const lastColor = await GM_getValue(LAST_COLOR_KEY, '#58a6ff');
                input.value = lastColor;
                input.addEventListener('input', async (e) => {
                    await GM_setValue(LAST_COLOR_KEY, e.target.value);
                });
                const colorBtn = createToolbarButton({
                    title: getTranslation('text_color'),
                    label: icons.text_color,
                    action: () => insertText(textarea, `<span style="color: ${input.value};">`, '</span>', getTranslation('colored_text_placeholder'))
                });
                const bgBtn = createToolbarButton({
                    title: getTranslation('background_color'),
                    label: icons.background_color,
                    action: async () => {
                        const start = textarea.selectionStart;
                        const end = textarea.selectionEnd;
                        const selectedText = textarea.value.substring(start, end);
                        const lastTag = await GM_getValue(LAST_TAG_TYPE_KEY, 'span');
                        showCustomPrompt({
                            inputs: [
                                { id: 'text',  label: getTranslation('prompt_border_text'),     type: 'text',   value: selectedText || getTranslation('colored_background_placeholder') },
                                { id: 'color', label: getTranslation('background_color'),       type: 'text',   value: input.value },
                                { id: 'tag',   label: getTranslation('prompt_border_tag_type'), type: 'select', value: lastTag, options: [ { value: 'span', text: '<span>' }, { value: 'div', text: '<div>' } ] }
                            ],
                            onConfirm: async ({ text, color, tag }) => {
                                await GM_setValue(LAST_TAG_TYPE_KEY, tag);
                                let newElement;
                                if (tag === 'div') {
                                    newElement = `\n<div style="background-color: ${color};">\n   ${text}\n</div>\n`;
                                } else {
                                    newElement = `<span style="background-color: ${color};">${text}</span>`;
                                }
                                textarea.setRangeText(newElement, start, end, selectedText ? 'end' : 'select');
                                textarea.focus();
                            }
                        });
                    }
                });
                const hrStyleBtn = createToolbarButton({
                    title: getTranslation('horizontal_line_style'),
                    label: icons.hr_style,
                    action: () => {
                        const start = textarea.selectionStart;
                        const end = textarea.selectionEnd;
                        const selectedText = textarea.value.substring(start, end).trim();
                        let currentSize = '1';
                        let currentColor = input.value;
                        const hrRegex = /<hr\s+style="border:\s*(\d+)px\s+solid\s+([^;"]+)/i;
                        const match = selectedText.match(hrRegex);
                        if (match && selectedText.startsWith('<hr')) {
                            currentSize = match[1];
                            currentColor = match[2];
                        }
                        showCustomPrompt({
                            inputs: [
                                { id: 'size',  label: getTranslation('prompt_hr_size'),     type: 'number', value: currentSize  },
                                { id: 'color', label: getTranslation('prompt_hr_color'),    type: 'text',   value: currentColor }
                            ],
                            onConfirm: ({ size, color }) => {
                                const newHr = `<hr style="border: ${size}px solid ${color};">`;
                                textarea.setRangeText(newHr, start, end, 'select');
                                textarea.focus();
                            }
                        });
                    }
                });
                const borderStyleBtn = createToolbarButton({
                    title: getTranslation('border_style'),
                    label: icons.border,
                    action: async () => {
                        const start = textarea.selectionStart;
                        const end = textarea.selectionEnd;
                        const selectedText = textarea.value.substring(start, end);
                        const lastTag = await GM_getValue(LAST_TAG_TYPE_KEY, 'span');
                        showCustomPrompt({
                            inputs: [
                                { id: 'text',  label: getTranslation('prompt_border_text'),     type: 'text',   value: selectedText || getTranslation('border_text_placeholder') },
                                { id: 'size',  label: getTranslation('prompt_border_size'),     type: 'number', value: '1' },
                                { id: 'color', label: getTranslation('prompt_border_color'),    type: 'text',   value: input.value },
                                { id: 'tag',   label: getTranslation('prompt_border_tag_type'), type: 'select', value: lastTag, options: [ { value: 'span', text: '<span>' }, { value: 'div', text: '<div>' } ] }
                            ],
                            onConfirm: async ({ text, size, color, tag }) => {
                                await GM_setValue(LAST_TAG_TYPE_KEY, tag);
                                let newElement;
                                if (tag === 'div') {
                                    newElement = `\n<div style="border: ${size}px solid ${color};">\n   ${text}\n</div>`;
                                } else {
                                    newElement = `<span style="border: ${size}px solid ${color};">${text}</span>`;
                                }
                                textarea.setRangeText(newElement, start, end, selectedText ? 'end' : 'select');
                                textarea.focus();
                            }
                        });
                    }
                });

                colorContainer.append(input, colorBtn, bgBtn, hrStyleBtn, borderStyleBtn);
                toolbar.appendChild(colorContainer);
            } else {
                toolbar.appendChild(createToolbarButton(tool));
            }
        }
        const infoButton = createToolbarButton({
            title: getTranslation('info_tooltip'),
            icon: icons.info,
            action: showInfoModal
        });
        infoButton.style.marginLeft = 'auto';
        toolbar.appendChild(infoButton);
        textarea.parentNode.insertBefore(container, textarea);
        container.append(toolbar, textarea);
    }

    function applyToAllTextareas() {
        const textareas = document.querySelectorAll('textarea:not(#script_version_code):not([data-editor-applied])');
        textareas.forEach(createTextStyleEditor);
    }

    function enableSourceEditorCheckbox() {
        const enableCheckbox = () => {
            const checkbox = document.getElementById('enable-source-editor-code');
            if (checkbox && !checkbox.checked) {
                checkbox.checked = true;
                const event = new Event('change', {
                    bubbles: true
                });
                checkbox.dispatchEvent(event);
            }
        };
        enableCheckbox();
        const observer = new MutationObserver((mutationsList, observer) => {
            for (const mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    const checkbox = document.getElementById('enable-source-editor-code');
                    if (checkbox) {
                        enableCheckbox();
                        observer.disconnect();
                        break;
                    }
                }
            }
        });
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }

    function isMarkdownPage() {
        const path = window.location.pathname;
        const markdownSegments = [ '/new', '/edit', '/feedback', '/discussions' ];
        if (path.includes('/sets/')) {
            return false;
        }
        return markdownSegments.some(segment => path.includes(segment));
    }
    // #endregion

    // ================
    // #region DOWNLOAD
    // ================

    function isCodePage() {
        return /^\/([a-z]{2}(-[A-Z]{2})?\/)?scripts\/\d+-.+\/code/.test(window.location.pathname);
    }

    function initializeDownloadButton() {
        const waitFor = (sel) =>
            new Promise((resolve) => {
                const el = document.querySelector(sel);
                if (el) return resolve(el);
                const obs = new MutationObserver(() => {
                    const el = document.querySelector(sel);
                    if (el) {
                        obs.disconnect();
                        resolve(el);
                    }
                });
                obs.observe(document, { childList: true, subtree: true });
            });

        waitFor('label[for="wrap-lines"]').then((label) => {
            const wrapLinesCheckbox = document.getElementById('wrap-lines');
            if (wrapLinesCheckbox) {
                wrapLinesCheckbox.checked = false;
            }
            const toolbar = label.parentElement;
            const btn = document.createElement('button');
            btn.className = 'btn';
            btn.textContent = getTranslation('download');
            btn.style.marginLeft = '12px';
            btn.style.backgroundColor = '#005200';
            btn.style.color = 'white';
            btn.style.border = 'none';
            btn.style.padding = '6px 16px';
            btn.style.borderRadius = '4px';
            btn.style.cursor = 'pointer';
            btn.addEventListener('mouseenter', () => btn.style.backgroundColor = '#1e971e');
            btn.addEventListener('mouseleave', () => btn.style.backgroundColor = '#005200');

            btn.addEventListener('click', () => {
                const normalizedPath = normalizeScriptPath(window.location.pathname);
                const scriptId = extractScriptIdFromNormalizedPath(normalizedPath);

                if (!scriptId) {
                    alert(getTranslation('scriptIdNotFound'));
                    return;
                }

                const scriptUrl = `https://update.greasyfork.icu/scripts/${scriptId}.js`;

                btn.disabled = true;
                btn.textContent = getTranslation('downloading');

                GM_xmlhttpRequest({
                    method: 'GET',
                    url: scriptUrl,
                    onload: function (res) {
                        const code = res.responseText;
                        if (!code) {
                            alert(getTranslation('notFound'));
                            return;
                        }
                        const nameMatch = code.match(/\/\/\s*@name\s+(.+)/i);
                        const fileName = nameMatch ? `${nameMatch[1].trim()}.user.js` : 'script.user.js';
                        const blob = new Blob([code], { type: 'application/javascript;charset=utf-8' });
                        const url = URL.createObjectURL(blob);
                        const a = document.createElement('a');
                        a.href = url;
                        a.download = fileName;
                        document.body.appendChild(a);
                        a.click();
                        document.body.removeChild(a);
                        URL.revokeObjectURL(url);
                    },
                    onerror: function (res) {
                        alert(getTranslation('downloadError'));
                    },
                    ontimeout: function () {
                        alert(getTranslation('downloadTimeout'));
                    },
                    onloadend: function () {
                        btn.disabled = false;
                        btn.textContent = getTranslation('download');
                    }
                });
            });
            toolbar.appendChild(btn);
            const spacer = document.createElement('div');
            spacer.style.height = '12px';
            toolbar.appendChild(spacer);
        });
    }
    // #endregion

    // ================
    // #region INICIALIZAR
    // ================

    async function start() {
        iconCache = await GM_getValue(CACHE_KEY, {});
        await determineLanguage();
        languageModal = createLanguageModal();
        document.body.appendChild(languageModal);
        registerLanguageMenu();
        registerForceUpdateMenu();
        setupThemeChangeListener();
        if (isMarkdownPage()) {
            applyToAllTextareas();
            enableSourceEditorCheckbox();
        }
        if (isCodePage()){
            initializeDownloadButton();
        }
        processIconElements();
        highlightScriptDescription();
        if (isScriptPage()) {
            addAdditionalInfoSeparator();
        }
        makeDiscussionClickable();
        applySyntaxHighlighting();
        const observer = new MutationObserver(() => {
            processIconElements();
            highlightScriptDescription();
            if (isScriptPage()) {
                addAdditionalInfoSeparator();
            }
            if (isMarkdownPage()) {
                applyToAllTextareas();
            }
            makeDiscussionClickable();
            applySyntaxHighlighting();
        });
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }
    start();
    // #endregion
})();