💪Anaboler Tagger+

Schnelle Buttons zum Umbenennen und Einfaerben eingehender Angriffe bei Die Staemme.

Tento skript by nemal byť nainštalovaný priamo. Je to knižnica pre ďalšie skripty, ktorú by mali používať cez meta príkaz // @require https://update.greasyfork.org/scripts/587738/1880003/%F0%9F%92%AAAnaboler%20Tagger%2B.js

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         💪Anaboler Tagger+
// @namespace    intellifarm.tw.tagger
// @version      1.0.1
// @description  Schnelle Buttons zum Umbenennen und Einfaerben eingehender Angriffe bei Die Staemme.
// @icon         data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJnIiBjeD0iMzAlIiBjeT0iMzAlIj48c3RvcCBvZmZzZXQ9IjAlIiBzdG9wLWNvbG9yPSIjZThjODczIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjN2E1YzFlIi8+PC9yYWRpYWxHcmFkaWVudD48L2RlZnM+PGNpcmNsZSBjeD0iMzIiIGN5PSIzMiIgcj0iMzAiIGZpbGw9InVybCgjZykiIHN0cm9rZT0iIzJhMjQxMCIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMzIiIHk9IjQzIiBmb250LXNpemU9IjMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMmEyNDEwIiBmb250LWZhbWlseT0iQXJpYWwsIHNhbnMtc2VyaWYiIGZvbnQtd2VpZ2h0PSJib2xkIj5UPC90ZXh0Pjwvc3ZnPg==
// @include      *://*.die-staemme.de/game.php*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(() => {
    "use strict";

    // Hub-Check: respektiert den Ein/Aus-Schalter im Anaboles Hub (id: 'taggerplus')
    function isEnabledInHub() {
        try {
            const reg = JSON.parse(localStorage.getItem('intellifarm_registry') || '{}');
            return reg.taggerplus !== false; // Default: aktiviert, falls Hub fehlt/Eintrag fehlt
        } catch { return true; }
    }
    if (!isEnabledInHub()) return;

    const SCRIPT_ID = "anaboler-tagger-plus";
    const STYLE_ID = `${SCRIPT_ID}-style`;
    const STORAGE_KEY = `${SCRIPT_ID}-config-v1`;
    const CONFIG_BUTTON_ID = `${SCRIPT_ID}-config-button`;
    const CONFIG_MODAL_ID = `${SCRIPT_ID}-config-modal`;
    const CONFIG_DIALOG_ID = "anabolerTaggerPlus";

    const CONFIG_PADRAO = {
        tamanhoLetraPx: 8,
        tamanhoBotaoPx: 18,
        paddingHorizontalBotaoPx: 3,
        paginaDeAtaques: "coluna", // Modos: coluna, linha, texto, nada
        mostrarBotoesNoMapa: false,
        intervaloFallbackMs: 2500,
        timeoutEdicaoMs: 1200,
        intervaloEsperaInputMs: 40,
        manterInfoAtacante: true,
        realcarTexto: true,
        realcarInformacoesTabela: true,
        ocultarBotoesApoios: true,
        ocultarBotoesAmigos: true,
        mostrarBotaoReset: true,
        botoesOcultos: [],
        tribosAliadasIds: [],
    };
    const CONFIG = {
        ...CONFIG_PADRAO,
        botoesOcultos: [...CONFIG_PADRAO.botoesOcultos],
        tribosAliadasIds: [...CONFIG_PADRAO.tribosAliadasIds],
    };

    const CORES = {
        red: { top: "#e20606", bottom: "#ff0000" },
        green: { top: "#31c908", bottom: "#228c05" },
        blue: { top: "#0d83dd", bottom: "#0860a3" },
        yellow: { top: "#ffd91c", bottom: "#e8c30d" },
        orange: { top: "#ef8b10", bottom: "#d3790a" },
        lblue: { top: "#22e5db", bottom: "#0cd3c9" },
        lime: { top: "#ffd400", bottom: "#ffd400" },
        white: { top: "#ffffff", bottom: "#dbdbdb" },
        black: { top: "#000000", bottom: "#000000" },
        gray: { top: "#adb6c6", bottom: "#828891" },
        dorange: { top: "#9232a8", bottom: "#9232a8" },
        dark: { top: "#40434e", bottom: "#40434e" },
        pink: { top: "#ffc0cb", bottom: "#ffc0cb" },
        brown: { top: "#892929", bottom: "#892929" },
        dblue: { top: "#00007f", bottom: "#00007f" },
        dgreen: { top: "#004c00", bottom: "#004c00" },
        lgreen: { top: "#93cf82", bottom: "#93cf82" },
    };

    const COMANDOS = [
        { tag: "[Tot]", label: "T", corBotao: "green", corTexto: "white", modo: "substituir" },
        { tag: "[Umgeleitet]", label: "U!", corBotao: "orange", corTexto: "white", modo: "substituir" },
        { tag: "[Umleiten]", label: "U", corBotao: "dorange", corTexto: "white", modo: "substituir" },
        { tag: "[Zurueckerobern]", label: "Z", corBotao: "gray", corTexto: "white", modo: "substituir" },
        { tag: "[Zurueckerobert]", label: "Z!", corBotao: "white", corTexto: "black", modo: "substituir" },
        { tag: "[Gesnipt]", label: "G!", corBotao: "lblue", corTexto: "white", modo: "substituir" },
        { tag: "[Snipe]", label: "S", corBotao: "blue", corTexto: "white", modo: "substituir" },
        { tag: "[Verkackt]", label: "VK", corBotao: "dgreen", corTexto: "white", modo: "substituir" },
        { tag: "[Snipe Cancel]", label: "SC", corBotao: "red", corTexto: "white", modo: "substituir" },
        { tag: "[Fake]", label: "F", corBotao: "pink", corTexto: "black", modo: "substituir" },
        {
            tag: "[Evtl. Full]",
            aliases: ["[Evtl Full]", "[Evtl. full]"],
            label: "EF",
            corBotao: "dblue",
            corTexto: "white",
            modo: "substituir",
        },
        {
            tag: "[Verst\u00e4rken]",
            aliases: ["[Verstaerken]", "[Verst\u00c3\u00a4rken]"],
            label: "VS",
            corBotao: "black",
            corTexto: "white",
            modo: "substituir",
        },
        { tag: " | Abziehen", label: "A!", corBotao: "dgreen", corTexto: "white", modo: "acrescentar" },
        { tag: " | Beobachten", label: "B!", corBotao: "yellow", corTexto: "black", modo: "acrescentar" },
        {
            tag: " | \u2713",
            aliases: [" | \u00e2\u0153\u201c"],
            label: "\u2713",
            corBotao: "lgreen",
            corTexto: "black",
            modo: "acrescentar",
        },
    ];

    const SELETORES = {
        linhasAtaques: "#incomings_table tr",
        linhasComandos: "#commands_incomings .command-row, #commands_incomings tr, #commands_outgoings .command-row, #commands_outgoings tr, .command-row",
        quickedit: ".quickedit-content",
        etiquetaNome: ".quickedit-label",
        iconeRenomear: ".rename-icon",
        inputNome: 'input[type="text"]',
        areaEdicao: ".quickedit-edit",
        botoesGuardar: 'input[type="button"], input[type="submit"], button[type="submit"]',
        linkAldeia: 'a[href*="screen=info_village"]',
        linkJogador: 'a[href*="screen=info_player"]',
    };

    let execucaoAgendada = false;
    const mapasCabecalhoTabela = new WeakMap();
    const relacoesJogadores = new Map();
    let tribosAliadasCache = null;
    let tribosAliadasPromise = null;
    let configButtonPositionFrame = 0;
    let configFormRoot = null;

    function carregarConfiguracao() {
        try {
            const guardada = JSON.parse(localStorage.getItem(STORAGE_KEY) || "{}");
            aplicarValoresConfiguracao(guardada);
        } catch (erro) {
            console.warn("[Anaboler Tagger+] Gespeicherte Einstellungen ungueltig:", erro);
        }
    }

    function aplicarValoresConfiguracao(valores) {
        const booleanos = [
            "mostrarBotoesNoMapa",
            "manterInfoAtacante",
            "realcarTexto",
            "realcarInformacoesTabela",
            "ocultarBotoesApoios",
            "ocultarBotoesAmigos",
            "mostrarBotaoReset",
        ];

        booleanos.forEach((chave) => {
            if (typeof valores?.[chave] === "boolean") CONFIG[chave] = valores[chave];
        });

        if (["coluna", "linha", "texto", "nada"].includes(valores?.paginaDeAtaques)) {
            CONFIG.paginaDeAtaques = valores.paginaDeAtaques;
        }

        CONFIG.tamanhoLetraPx = limitarNumero(
            valores?.tamanhoLetraPx,
            4,
            14,
            CONFIG.tamanhoLetraPx,
        );
        CONFIG.tamanhoBotaoPx = limitarNumero(
            valores?.tamanhoBotaoPx,
            12,
            30,
            CONFIG.tamanhoBotaoPx,
        );
        CONFIG.paddingHorizontalBotaoPx = limitarNumero(
            valores?.paddingHorizontalBotaoPx,
            0,
            8,
            CONFIG.paddingHorizontalBotaoPx,
        );

        if (Array.isArray(valores?.tribosAliadasIds)) {
            CONFIG.tribosAliadasIds = [...new Set(
                valores.tribosAliadasIds
                    .map(Number)
                    .filter((id) => Number.isInteger(id) && id > 0),
            )];
        }

        if (Array.isArray(valores?.botoesOcultos)) {
            CONFIG.botoesOcultos = [...new Set(
                valores.botoesOcultos
                    .map(Number)
                    .filter((index) => Number.isInteger(index) && index >= 0 && index < COMANDOS.length),
            )];
        }
    }

    function guardarConfiguracao() {
        const valores = {
            tamanhoLetraPx: CONFIG.tamanhoLetraPx,
            tamanhoBotaoPx: CONFIG.tamanhoBotaoPx,
            paddingHorizontalBotaoPx: CONFIG.paddingHorizontalBotaoPx,
            paginaDeAtaques: CONFIG.paginaDeAtaques,
            mostrarBotoesNoMapa: CONFIG.mostrarBotoesNoMapa,
            manterInfoAtacante: CONFIG.manterInfoAtacante,
            realcarTexto: CONFIG.realcarTexto,
            realcarInformacoesTabela: CONFIG.realcarInformacoesTabela,
            ocultarBotoesApoios: CONFIG.ocultarBotoesApoios,
            ocultarBotoesAmigos: CONFIG.ocultarBotoesAmigos,
            mostrarBotaoReset: CONFIG.mostrarBotaoReset,
            botoesOcultos: [...CONFIG.botoesOcultos],
            tribosAliadasIds: [...CONFIG.tribosAliadasIds],
        };

        localStorage.setItem(STORAGE_KEY, JSON.stringify(valores));
    }

    function limitarNumero(valor, minimo, maximo, fallback) {
        const numero = Number(valor);
        if (!Number.isFinite(numero)) return fallback;

        return Math.min(maximo, Math.max(minimo, Math.round(numero)));
    }

    function iniciar() {
        if (!document.body) {
            setTimeout(iniciar, 100);
            return;
        }

        carregarConfiguracao();
        aplicarEstilos();
        criarBotaoConfiguracao();
        executar();

        const observer = new MutationObserver(agendarExecucao);
        observer.observe(document.body, { childList: true, subtree: true });

        window.addEventListener("resize", agendarPosicaoBotaoConfiguracao);
        window.addEventListener("orientationchange", agendarPosicaoBotaoConfiguracao);
        agendarPosicaoBotaoConfiguracao();
        setTimeout(agendarPosicaoBotaoConfiguracao, 250);
        setTimeout(agendarPosicaoBotaoConfiguracao, 1000);

        setInterval(executar, CONFIG.intervaloFallbackMs);
        console.log("[Anaboler Tagger+] Skript geladen:", location.href);
    }

    function agendarExecucao() {
        if (execucaoAgendada) return;

        execucaoAgendada = true;
        requestAnimationFrame(() => {
            execucaoAgendada = false;
            executar();
            agendarPosicaoBotaoConfiguracao();
        });
    }

    function criarBotaoConfiguracao() {
        if (document.getElementById(CONFIG_BUTTON_ID)) return;

        const botao = document.createElement("button");
        botao.id = CONFIG_BUTTON_ID;
        botao.type = "button";
        botao.className = "ra-tp-config-button";
        botao.title = "💪 Anaboler Tagger+";
        botao.setAttribute("aria-label", "Anaboler Tagger+ oeffnen");
        botao.innerHTML = `
            <span class="ra-tp-config-button-icon" aria-hidden="true">💪</span>
            <span class="ra-tp-config-button-label">Anaboler Tagger+</span>
        `;
        botao.addEventListener("click", abrirPainelConfiguracao);

        document.body.appendChild(botao);
        criarModalConfiguracao();
        agendarPosicaoBotaoConfiguracao();
    }

    function agendarPosicaoBotaoConfiguracao() {
        if (configButtonPositionFrame) cancelAnimationFrame(configButtonPositionFrame);

        configButtonPositionFrame = requestAnimationFrame(() => {
            configButtonPositionFrame = 0;
            posicionarBotaoConfiguracao();
        });
    }

    function posicionarBotaoConfiguracao() {
        const botao = document.getElementById(CONFIG_BUTTON_ID);
        if (!botao) return;

        const layout =
            document.querySelector("#main_layout td.maincell")
            || document.querySelector("td.maincell")
            || document.querySelector("#contentContainer")
            || document.querySelector("#content_value");

        let left = 12;
        const top = 310;

        if (layout) {
            const rectLayout = layout.getBoundingClientRect();
            if (rectLayout.width > 0) left = Math.max(4, Math.round(rectLayout.left - 55));
        }

        botao.style.setProperty("left", `${left}px`, "important");
        botao.style.setProperty("right", "auto", "important");
        botao.style.setProperty("top", `${top}px`, "important");
        botao.style.setProperty("bottom", "auto", "important");
    }

    function criarModalConfiguracao() {
        if (document.getElementById(CONFIG_MODAL_ID)) return;

        const modal = document.createElement("div");
        modal.id = CONFIG_MODAL_ID;
        modal.className = "ra-tp-config-overlay";
        modal.hidden = true;
        modal.innerHTML = `
            <div class="ra-tp-config-dialog" role="dialog" aria-modal="true" aria-labelledby="${SCRIPT_ID}-config-title">
                <button type="button" class="ra-tp-config-close" data-ra-config-action="fechar" aria-label="Schliessen">&times;</button>
                <div class="ra-tp-config-frame" data-ra-config-form="template">
                    <div class="ra-tp-config-header">
                        <h3 id="${SCRIPT_ID}-config-title">💪 Anaboler Tagger+</h3>
                        <span>Schnelle Buttons, Farben und Organisation der Befehle bei Die Staemme.</span>
                    </div>
                    <div class="ra-tp-config-body">
                        <section class="ra-tp-config-section ra-tp-config-appearance">
                            <div class="ra-tp-config-section-copy">
                                <div class="ra-tp-config-section-title">Erscheinungsbild</div>
                                <div class="ra-tp-config-section-desc">Steuert Hintergruende, Groessen und Abstaende der Buttons.</div>
                            </div>
                            <div class="ra-tp-config-section-options ra-tp-config-fields-grid">
                                <label class="ra-tp-config-field">
                                    <span>Faerbung der Angriffe</span>
                                    <select id="${SCRIPT_ID}-config-pagina">
                                        <option value="coluna">Befehlsspalte</option>
                                        <option value="linha">Ganze Zeile</option>
                                        <option value="texto">Nur Button-Text</option>
                                        <option value="nada">Kein Hintergrund</option>
                                    </select>
                                </label>
                                <label class="ra-tp-config-field">
                                    <span>Schriftgroesse</span>
                                    <input id="${SCRIPT_ID}-config-letra" type="number" min="4" max="14" step="1">
                                </label>
                                <label class="ra-tp-config-field">
                                    <span>Button-Groesse</span>
                                    <input id="${SCRIPT_ID}-config-botao" type="number" min="12" max="30" step="1">
                                </label>
                                <label class="ra-tp-config-field">
                                    <span>Seitlicher Abstand</span>
                                    <input id="${SCRIPT_ID}-config-padding" type="number" min="0" max="8" step="1">
                                </label>
                            </div>
                        </section>
                        <section class="ra-tp-config-section ra-tp-config-content">
                            <div class="ra-tp-config-section-copy">
                                <div class="ra-tp-config-section-title">Inhalt</div>
                                <div class="ra-tp-config-section-desc">Waehlt die angezeigten Informationen und Hervorhebungen.</div>
                            </div>
                            <div class="ra-tp-config-section-options">
                                ${criarToggleConfigHtml("info-atacante", "Angreifer und Herkunft behalten")}
                                ${criarToggleConfigHtml("realce-texto", "Befehlstext hervorheben")}
                                ${criarToggleConfigHtml("realce-tabela", "Tabelleninformationen hervorheben")}
                            </div>
                        </section>
                        <section class="ra-tp-config-section ra-tp-config-buttons">
                            <div class="ra-tp-config-section-copy">
                                <div class="ra-tp-config-section-title">Buttons</div>
                                <div class="ra-tp-config-section-desc">Legt fest, welche Buttons sichtbar sind und wo sie erscheinen.</div>
                            </div>
                            <div class="ra-tp-config-section-options">
                                <div id="${SCRIPT_ID}-config-comandos" class="ra-tp-config-command-list">
                                    ${criarListaBotoesConfigHtml()}
                                </div>
                                <div class="ra-tp-config-toggle-grid">
                                    ${criarToggleConfigHtml("botao-reset", "RS-Button anzeigen")}
                                    ${criarToggleConfigHtml("botoes-mapa", "Buttons auf der Karte anzeigen")}
                                    ${criarToggleConfigHtml("ocultar-apoios", "Buttons bei Unterstuetzungen ausblenden")}
                                    ${criarToggleConfigHtml("ocultar-amigos", "Bei Verbuendeten und eigenem Stamm ausblenden")}
                                </div>
                                <label class="ra-tp-config-field ra-tp-config-field-wide">
                                    <span>Zusaetzliche IDs verbuendeter Staemme</span>
                                    <input id="${SCRIPT_ID}-config-aliados" type="text" placeholder="123, 456">
                                </label>
                            </div>
                        </section>
                        <section class="ra-tp-config-section ra-tp-config-actions">
                            <div class="ra-tp-config-section-copy">
                                <div class="ra-tp-config-section-title">Aktionen</div>
                                <div class="ra-tp-config-section-desc">Speichert, verwirft oder stellt die Standardwerte wieder her.</div>
                            </div>
                            <div class="ra-tp-config-section-options ra-tp-config-footer">
                                <button type="button" class="ra-tp-config-secondary" data-ra-config-action="restaurar">Standardwerte</button>
                                <button type="button" class="ra-tp-config-secondary" data-ra-config-action="fechar">Abbrechen</button>
                                <button type="button" class="ra-tp-config-primary" data-ra-config-action="guardar">Speichern</button>
                            </div>
                        </section>
                    </div>
                </div>
            </div>
        `;

        vincularEventosConfiguracao(modal);

        document.addEventListener("keydown", (evento) => {
            if (evento.key === "Escape" && !modal.hidden) fecharPainelConfiguracao();
        });

        document.body.appendChild(modal);
    }

    function vincularEventosConfiguracao(root) {
        if (!root || root.dataset.raConfigBound === "1") return;
        root.dataset.raConfigBound = "1";

        root.addEventListener("click", (evento) => {
            const acao = evento.target.closest("[data-ra-config-action]")?.dataset.raConfigAction;

            if (acao === "fechar") fecharPainelConfiguracao();
            if (acao === "restaurar") preencherFormularioConfiguracao(CONFIG_PADRAO);
            if (acao === "guardar") guardarFormularioConfiguracao();
            if (evento.target === root && root.id === CONFIG_MODAL_ID) fecharPainelConfiguracao();
        });
    }

    function criarListaBotoesConfigHtml() {
        return COMANDOS.map((comando, index) => `
            <label class="ra-tp-config-command">
                <input type="checkbox" data-ra-config-command="${index}">
                <span>${escapeHtml(comando.label)} - ${escapeHtml(comando.tag.trim())}</span>
            </label>
        `).join("");
    }

    function escapeHtml(valor) {
        return String(valor || "")
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#039;");
    }

    function criarToggleConfigHtml(sufixo, label) {
        return `
            <label class="ra-tp-config-toggle">
                <input id="${SCRIPT_ID}-config-${sufixo}" type="checkbox">
                <span>${label}</span>
            </label>
        `;
    }

    function abrirPainelConfiguracao() {
        const modal = document.getElementById(CONFIG_MODAL_ID);
        if (!modal) return;

        const dialog = obterDialogNativo();
        const frame = modal.querySelector('[data-ra-config-form="template"]');

        if (dialog && typeof dialog.show === "function" && frame) {
            const html = frame.outerHTML.replace(
                'data-ra-config-form="template"',
                'data-ra-config-form="dialog"',
            );

            dialog.show(CONFIG_DIALOG_ID, html);

            const formularios = document.querySelectorAll('[data-ra-config-form="dialog"]');
            const formulario = formularios[formularios.length - 1];

            if (formulario) {
                configFormRoot = formulario;
                vincularEventosConfiguracao(formulario);
                preencherFormularioConfiguracao(CONFIG);
                formulario.querySelector("select, input, button")?.focus();
                return;
            }
        }

        configFormRoot = modal;
        preencherFormularioConfiguracao(CONFIG);
        modal.hidden = false;
        modal.querySelector("select, input, button")?.focus();
    }

    function fecharPainelConfiguracao() {
        if (configFormRoot?.matches('[data-ra-config-form="dialog"]')) {
            const dialog = obterDialogNativo();
            if (dialog && typeof dialog.close === "function") {
                dialog.close(CONFIG_DIALOG_ID);
                configFormRoot = null;
                return;
            }
        }

        const modal = document.getElementById(CONFIG_MODAL_ID);
        if (modal) modal.hidden = true;
        configFormRoot = null;
    }

    function obterDialogNativo() {
        return window.Dialog || null;
    }

    function preencherFormularioConfiguracao(valores) {
        obterCampoConfig("pagina").value = valores.paginaDeAtaques;
        obterCampoConfig("letra").value = valores.tamanhoLetraPx;
        obterCampoConfig("botao").value = valores.tamanhoBotaoPx;
        obterCampoConfig("padding").value = valores.paddingHorizontalBotaoPx;
        obterCampoConfig("info-atacante").checked = valores.manterInfoAtacante;
        obterCampoConfig("realce-texto").checked = valores.realcarTexto;
        obterCampoConfig("realce-tabela").checked = valores.realcarInformacoesTabela;
        obterCampoConfig("botao-reset").checked = valores.mostrarBotaoReset;
        obterCampoConfig("botoes-mapa").checked = valores.mostrarBotoesNoMapa;
        obterCampoConfig("ocultar-apoios").checked = valores.ocultarBotoesApoios;
        obterCampoConfig("ocultar-amigos").checked = valores.ocultarBotoesAmigos;
        obterCampoConfig("aliados").value = (valores.tribosAliadasIds || []).join(", ");

        obterRaizFormularioConfiguracao().querySelectorAll("[data-ra-config-command]").forEach((checkbox) => {
            checkbox.checked = !(valores.botoesOcultos || []).includes(Number(checkbox.dataset.raConfigCommand));
        });
    }

    function guardarFormularioConfiguracao() {
        const valores = {
            paginaDeAtaques: obterCampoConfig("pagina").value,
            tamanhoLetraPx: obterCampoConfig("letra").value,
            tamanhoBotaoPx: obterCampoConfig("botao").value,
            paddingHorizontalBotaoPx: obterCampoConfig("padding").value,
            manterInfoAtacante: obterCampoConfig("info-atacante").checked,
            realcarTexto: obterCampoConfig("realce-texto").checked,
            realcarInformacoesTabela: obterCampoConfig("realce-tabela").checked,
            mostrarBotaoReset: obterCampoConfig("botao-reset").checked,
            mostrarBotoesNoMapa: obterCampoConfig("botoes-mapa").checked,
            ocultarBotoesApoios: obterCampoConfig("ocultar-apoios").checked,
            ocultarBotoesAmigos: obterCampoConfig("ocultar-amigos").checked,
            botoesOcultos: [...obterRaizFormularioConfiguracao().querySelectorAll("[data-ra-config-command]")]
                .filter((checkbox) => !checkbox.checked)
                .map((checkbox) => Number(checkbox.dataset.raConfigCommand)),
            tribosAliadasIds: obterCampoConfig("aliados").value
                .split(/[\s,;]+/)
                .filter(Boolean)
                .map(Number),
        };

        aplicarValoresConfiguracao(valores);
        guardarConfiguracao();
        reiniciarCachesRelacoes();
        aplicarConfiguracaoNaPagina();
        fecharPainelConfiguracao();
    }

    function obterCampoConfig(sufixo) {
        return obterRaizFormularioConfiguracao().querySelector(`#${SCRIPT_ID}-config-${sufixo}`);
    }

    function obterRaizFormularioConfiguracao() {
        return configFormRoot || document.getElementById(CONFIG_MODAL_ID) || document;
    }

    function reiniciarCachesRelacoes() {
        relacoesJogadores.clear();
        tribosAliadasCache = null;
        tribosAliadasPromise = null;
    }

    function aplicarConfiguracaoNaPagina() {
        aplicarEstilos();

        obterLinhasValidas().forEach((linha) => {
            removerBotoes(linha);
            limparPintura(linha);
            restaurarTextoSemRealce(linha);
            limparRealceInformacoesLinha(linha);
        });

        executar();
    }

    function restaurarTextoSemRealce(linha) {
        const label = linha.querySelector(SELETORES.etiquetaNome);
        if (!label) return;

        const texto = normalizarEspacos(label.textContent);
        label.textContent = texto;
        delete label.dataset.raTpRealceTexto;
        delete label.dataset.raTpRealceEscuro;
    }

    function limparRealceInformacoesLinha(linha) {
        linha.querySelectorAll("[data-ra-tp-info-realce]").forEach((celula) => {
            celula.style.removeProperty("color");
            celula.style.removeProperty("font-weight");
            celula.style.removeProperty("text-shadow");
            delete celula.dataset.raTpInfoRealce;
        });

        linha.querySelectorAll("[data-ra-tp-info-elemento]").forEach((elemento) => {
            elemento.style.removeProperty("color");
            elemento.style.removeProperty("font-weight");
            elemento.style.removeProperty("text-shadow");
            delete elemento.dataset.raTpInfoElemento;
        });
    }

    function executar() {
        const contexto = obterContextoPagina();
        const linhas = obterLinhasValidas();

        linhas.forEach((linha) => {
            const relacaoAmigavel = obterRelacaoAmigavelSincrona(linha);
            const ocultarNoMapa = contexto.isMapa && !CONFIG.mostrarBotoesNoMapa;
            const ocultarApoio = CONFIG.ocultarBotoesApoios && isApoio(linha);
            const ocultarComandoProprio = isComandoProprio(linha);

            if (ocultarNoMapa || ocultarApoio || ocultarComandoProprio || relacaoAmigavel === true) {
                removerBotoes(linha);
            } else if (relacaoAmigavel === null) {
                removerBotoes(linha);
                void verificarRelacaoAmigavel(linha);
            } else {
                inserirBotoes(linha);
            }

            aplicarCorAtaque(linha);
            realcarTextoLinha(linha);
            realcarInformacoesLinha(linha);
        });

        agendarPosicaoBotaoConfiguracao();
    }

    function obterContextoPagina() {
        const params = new URLSearchParams(location.search);
        const screen = params.get("screen") || "";

        return {
            isMapa: screen === "map" || location.href.includes("screen=map"),
        };
    }

    function obterLinhasValidas() {
        const linhas = [
            ...document.querySelectorAll(SELETORES.linhasAtaques),
            ...document.querySelectorAll(SELETORES.linhasComandos),
        ];

        return [...new Set(linhas)].filter((linha) => (
            linha.querySelector(SELETORES.etiquetaNome)
            && linha.querySelector(SELETORES.iconeRenomear)
        ));
    }

    function obterRelacaoAmigavelSincrona(linha) {
        if (!CONFIG.ocultarBotoesAmigos) return false;

        const linkJogador = obterLinkJogadorAtacante(linha);
        const jogadorId = obterIdDeLink(linkJogador);
        const jogadorAtualId = obterJogadorAtualId();

        if (jogadorId && jogadorAtualId && jogadorId === jogadorAtualId) return false;
        if (temMarcadorRelacaoAmigavel(linha, linkJogador)) return true;

        const triboId = obterTriboIdDaLinha(linha, linkJogador);
        const triboAtualId = obterTriboAtualId();

        if (triboId && triboAtualId && triboId === triboAtualId) return true;
        if (triboId && tribosAliadasCache?.has(triboId)) return true;

        if (jogadorId) {
            const estado = relacoesJogadores.get(jogadorId);
            if (estado === true || estado === false) return estado;
            return null;
        }

        if (triboId && tribosAliadasCache === null) return null;
        return false;
    }

    async function verificarRelacaoAmigavel(linha) {
        if (!CONFIG.ocultarBotoesAmigos || !linha.isConnected) return;

        const linkJogador = obterLinkJogadorAtacante(linha);
        const jogadorId = obterIdDeLink(linkJogador);
        const jogadorAtualId = obterJogadorAtualId();
        const triboIdDireta = obterTriboIdDaLinha(linha, linkJogador);

        if (jogadorId && jogadorAtualId && jogadorId === jogadorAtualId) {
            relacoesJogadores.set(jogadorId, false);
            return;
        }

        if (jogadorId && relacoesJogadores.get(jogadorId) === "pending") return;
        if (jogadorId) relacoesJogadores.set(jogadorId, "pending");

        try {
            let triboId = triboIdDireta;

            if (!triboId && linkJogador?.href) {
                triboId = await obterTriboIdDoPerfil(linkJogador.href);
            }

            const amigavel = triboId ? await isTriboAmiga(triboId) : false;
            if (jogadorId) relacoesJogadores.set(jogadorId, amigavel);
        } catch (erro) {
            if (jogadorId) relacoesJogadores.set(jogadorId, false);
            console.warn("[Anaboler Tagger+] Fehler bei der Beziehungspruefung:", erro);
        } finally {
            agendarExecucao();
        }
    }

    function temMarcadorRelacaoAmigavel(linha, linkJogador) {
        const elementos = [linha, linkJogador, linkJogador?.closest("td")].filter(Boolean);
        const textoTecnico = elementos.map((elemento) => [
            elemento.className || "",
            elemento.getAttribute?.("title") || "",
            elemento.getAttribute?.("data-relation") || "",
            elemento.getAttribute?.("data-diplomacy") || "",
            elemento.getAttribute?.("data-status") || "",
        ].join(" ")).join(" ");
        const normalizado = normalizarSemAcentos(textoTecnico);

        return /(^|[\s_-])(ally|allied|friend|friendly|same[_-]?tribe|tribe[_-]?member|aliad[oa]s?|amig[oa]s?|verbund(?:e[nt])?|freund(?:e|lich)?|verbuendet)(?=$|[\s_-])/.test(normalizado);
    }

    function obterTriboIdDaLinha(linha, linkJogador) {
        const celulaJogador = linkJogador?.closest("td");
        const linkTribo = celulaJogador?.querySelector('a[href*="screen=info_ally"][href*="id="]');
        const idDoLink = obterIdDeLink(linkTribo);
        if (idDoLink) return idDoLink;

        const elementos = [linkJogador, celulaJogador, linha].filter(Boolean);
        for (const elemento of elementos) {
            const candidatos = [
                elemento.getAttribute?.("data-ally-id"),
                elemento.getAttribute?.("data-tribe-id"),
                elemento.getAttribute?.("data-ally"),
            ];

            const id = candidatos.map(Number).find((valor) => Number.isInteger(valor) && valor > 0);
            if (id) return id;
        }

        return 0;
    }

    async function obterTriboIdDoPerfil(urlPerfil) {
        const resposta = await fetch(urlPerfil, { credentials: "same-origin" });
        if (!resposta.ok) throw new Error(`Profil HTTP ${resposta.status}`);

        const html = await resposta.text();
        const doc = new DOMParser().parseFromString(html, "text/html");
        const linkTribo = doc.querySelector('a[href*="screen=info_ally"][href*="id="]');

        return obterIdDeLink(linkTribo);
    }

    async function isTriboAmiga(triboId) {
        const triboAtualId = obterTriboAtualId();
        if (triboAtualId && triboId === triboAtualId) return true;

        const tribosAliadas = await obterTribosAliadas();
        return tribosAliadas.has(triboId);
    }

    function obterTribosAliadas() {
        if (tribosAliadasCache) return Promise.resolve(tribosAliadasCache);
        if (tribosAliadasPromise) return tribosAliadasPromise;

        tribosAliadasPromise = carregarTribosAliadas()
            .then((ids) => {
                tribosAliadasCache = ids;
                return ids;
            })
            .catch((erro) => {
                console.warn("[Anaboler Tagger+] Fehler beim Laden der Verbuendeten:", erro);
                tribosAliadasCache = criarSetTribosConfiguradas();
                return tribosAliadasCache;
            })
            .finally(() => {
                tribosAliadasPromise = null;
            });

        return tribosAliadasPromise;
    }

    async function carregarTribosAliadas() {
        const ids = criarSetTribosConfiguradas();
        if (!obterTriboAtualId()) return ids;

        const resposta = await fetch(criarUrlRelacoesTribo(), { credentials: "same-origin" });
        if (!resposta.ok) throw new Error(`Beziehungen HTTP ${resposta.status}`);

        const html = await resposta.text();
        const doc = new DOMParser().parseFromString(html, "text/html");

        doc.querySelectorAll([
            '[data-relation="ally"] a[href*="screen=info_ally"]',
            '[data-relation="allied"] a[href*="screen=info_ally"]',
            ".relation-ally a[href*='screen=info_ally']",
            ".relation_allied a[href*='screen=info_ally']",
            "tr.ally a[href*='screen=info_ally']",
            "tr.allied a[href*='screen=info_ally']",
        ].join(",")).forEach((link) => adicionarIdTribo(ids, link));

        doc.querySelectorAll('a[href*="screen=info_ally"][href*="id="]').forEach((link) => {
            const contexto = obterContextoDiplomacia(link);
            const isAliado = /\b(aliad[oa]s?|ally|allies|allied|verbuendet[e]?|verbundete)\b/.test(contexto);
            const isOutraRelacao = /\b(inimig[oa]s?|enemy|enemies|nap|pna|neutral|feind[e]?|krieg)\b/.test(contexto);

            if (isAliado && !isOutraRelacao) adicionarIdTribo(ids, link);
        });

        return ids;
    }

    function criarSetTribosConfiguradas() {
        return new Set(
            CONFIG.tribosAliadasIds
                .map(Number)
                .filter((id) => Number.isInteger(id) && id > 0),
        );
    }

    function obterContextoDiplomacia(link) {
        const partes = [];
        const linha = link.closest("tr, li");
        const container = linha?.closest("table, ul, ol, section, div");

        [link, linha, container].filter(Boolean).forEach((elemento) => {
            partes.push(elemento.className || "");
            partes.push(elemento.getAttribute?.("data-relation") || "");
            partes.push(elemento.getAttribute?.("title") || "");
        });

        if (linha) {
            partes.push(linha.textContent || "");
            let anterior = linha.previousElementSibling;

            for (let i = 0; anterior && i < 5; i += 1) {
                const texto = anterior.textContent || "";
                partes.push(texto);
                if (/\b(aliad|all(?:y|ies|ied)|inimig|enem|nap|pna|verbuendet|feind)\b/i.test(normalizarSemAcentos(texto))) break;
                anterior = anterior.previousElementSibling;
            }
        }

        if (container) {
            partes.push(container.querySelector("caption, thead, h2, h3, h4")?.textContent || "");
            partes.push(container.previousElementSibling?.textContent || "");
        }

        return normalizarSemAcentos(partes.join(" "));
    }

    function adicionarIdTribo(set, link) {
        const id = obterIdDeLink(link);
        if (id) set.add(id);
    }

    function obterIdDeLink(link) {
        if (!link?.href) return 0;

        try {
            return Number(new URL(link.href, location.href).searchParams.get("id")) || 0;
        } catch {
            return 0;
        }
    }

    function obterGameDataSeguro() {
        try {
            return window.TribalWars?.getGameData?.() || window.game_data || {};
        } catch {
            return window.game_data || {};
        }
    }

    function obterJogadorAtualId() {
        return Number(obterGameDataSeguro().player?.id) || 0;
    }

    function obterTriboAtualId() {
        return Number(obterGameDataSeguro().player?.ally) || 0;
    }

    function criarUrlRelacoesTribo() {
        const gameData = obterGameDataSeguro();
        const url = new URL(location.href);

        url.search = "";
        if (gameData.village?.id) url.searchParams.set("village", gameData.village.id);
        url.searchParams.set("screen", "ally");
        url.searchParams.set("mode", "relations");

        return url.href;
    }

    function inserirBotoes(linha) {
        if (isComandoProprio(linha)) {
            removerBotoes(linha);
            return;
        }

        const containerDestino = obterContainerBotoes(linha);
        if (!containerDestino || linha.querySelector(".ra-tp-botoes")) return;

        const container = document.createElement("span");
        container.className = "ra-tp-botoes";

        COMANDOS.forEach((comando, index) => {
            if (!comando.tag || !comando.label || CONFIG.botoesOcultos.includes(index)) return;

            const botao = criarBotao(comando.label, comando.tag.trim(), comando.corBotao, comando.corTexto);
            botao.dataset.comandoIndex = String(index);
            botao.addEventListener("click", (evento) => {
                evento.preventDefault();
                evento.stopPropagation();
                editarNomeLinha(linha, (valorAtual) => construirNome(valorAtual, comando, linha));
            });

            container.appendChild(botao);
        });

        if (CONFIG.mostrarBotaoReset) {
            const reset = criarBotao("RS", "Etiketten zuruecksetzen", "dark", "white");
            reset.classList.add("ra-tp-reset");
            reset.addEventListener("click", (evento) => {
                evento.preventDefault();
                evento.stopPropagation();
                editarNomeLinha(linha, (valorAtual) => limparEtiquetas(valorAtual, linha));
            });
            container.appendChild(reset);
        }

        if (container.childElementCount) containerDestino.appendChild(container);
    }

    function obterContainerBotoes(linha) {
        const quickedit = linha.querySelector(SELETORES.quickedit);
        if (quickedit) return quickedit;

        const label = linha.querySelector(SELETORES.etiquetaNome);
        return label?.closest("td") || label?.parentElement || null;
    }

    function criarBotao(label, titulo, corBotao, corTexto) {
        const botao = document.createElement("button");
        const background = obterCor(corBotao, "brown");
        const texto = obterCor(corTexto, "white");

        botao.type = "button";
        botao.className = "btn ra-tp-botao";
        if (isCorEscura(corBotao)) {
            botao.classList.add("ra-tp-botao-escuro");
            botao.style.setProperty("border-color", "rgba(255, 255, 255, 0.98)", "important");
            botao.style.setProperty("outline", "1px solid rgba(255, 255, 255, 0.85)");
        }
        botao.title = titulo;
        botao.textContent = label;
        botao.style.setProperty("font-size", `${CONFIG.tamanhoLetraPx || 12}px`, "important");
        botao.style.color = texto.top;
        botao.style.background = `linear-gradient(to bottom, ${background.top} 35%, ${background.bottom} 100%)`;

        return botao;
    }

    function isCorEscura(nomeCor) {
        return ["black", "dark"].includes(String(nomeCor || "").toLowerCase());
    }

    async function editarNomeLinha(linha, transformarNome) {
        if (linha.dataset.raTpEditando === "1") return;

        linha.dataset.raTpEditando = "1";

        try {
            const icone = linha.querySelector(SELETORES.iconeRenomear);
            if (!icone) return;

            icone.click();

            const input = await esperarPor(
                () => linha.querySelector(SELETORES.inputNome),
                CONFIG.timeoutEdicaoMs,
                CONFIG.intervaloEsperaInputMs,
            );

            if (!input) return;

            const novoNome = transformarNome(input.value);

            const botaoGuardar = obterBotaoGuardar(linha, input);
            if (novoNome !== input.value) {
                input.value = novoNome;
                input.dispatchEvent(new Event("input", { bubbles: true }));
                input.dispatchEvent(new Event("change", { bubbles: true }));
            }

            if (botaoGuardar) {
                botaoGuardar.click();
            } else if (input.form && typeof input.form.requestSubmit === "function") {
                input.form.requestSubmit();
            }

            refrescarLinhaDepois(linha);
        } finally {
            setTimeout(() => {
                delete linha.dataset.raTpEditando;
            }, 500);
        }
    }

    function obterBotaoGuardar(linha, input) {
        const areaEdicao = input.closest(SELETORES.areaEdicao);
        if (areaEdicao) {
            const botao = areaEdicao.querySelector(SELETORES.botoesGuardar);
            if (botao) return botao;
        }

        return linha.querySelector(`${SELETORES.areaEdicao} ${SELETORES.botoesGuardar}`);
    }

    function refrescarLinhaDepois(linha) {
        [250, 900].forEach((atraso) => {
            setTimeout(() => {
                limparRealceTextoLinha(linha);
                removerBotoes(linha);
                inserirBotoes(linha);
                aplicarCorAtaque(linha);
                realcarTextoLinha(linha);
                realcarInformacoesLinha(linha);
            }, atraso);
        });
    }

    function construirNome(valorAtual, comando, linha) {
        const sufixoInfo = obterSufixoInfoParaNome(valorAtual, linha);
        const atual = prepararNomeParaInfoAtacante(valorAtual, sufixoInfo);

        if (comando.modo === "acrescentar") {
            if (comandoExisteNoNome(atual, comando)) return aplicarInfoAtacanteComSufixo(atual, sufixoInfo);
            return aplicarInfoAtacanteComSufixo(`${atual}${comando.tag}`, sufixoInfo);
        }

        const sufixosAtivos = COMANDOS
            .filter((item) => item.modo === "acrescentar" && comandoExisteNoNome(atual, item))
            .map((item) => item.tag)
            .join("");
        const base = removerTags(atual, () => true);

        return aplicarInfoAtacanteComSufixo(`${base} ${comando.tag}${sufixosAtivos}`, sufixoInfo);
    }

    function limparEtiquetas(valorAtual, linha) {
        const sufixoInfo = obterSufixoInfoParaNome(valorAtual, linha);
        const atual = prepararNomeParaInfoAtacante(valorAtual, sufixoInfo);
        const limpo = removerTags(atual, () => true);

        return aplicarInfoAtacanteComSufixo(normalizarEspacos(limpo) || "Angriff", sufixoInfo);
    }

    function prepararNomeParaInfoAtacante(nome, sufixoInfo) {
        const normalizado = normalizarEspacos(nome);
        if (!sufixoInfo) return normalizado;

        return removerInfoAtacanteAuto(normalizado);
    }

    function aplicarInfoAtacante(nome, linha) {
        return aplicarInfoAtacanteComSufixo(nome, construirSufixoInfoAtacante(linha));
    }

    function aplicarInfoAtacanteComSufixo(nome, sufixoInfo) {
        const base = normalizarEspacos(nome);
        if (!sufixoInfo) return base;

        return normalizarEspacos(`${removerInfoAtacanteAuto(base)}${sufixoInfo}`);
    }

    function obterSufixoInfoParaNome(nome, linha) {
        return construirSufixoInfoAtacante(linha) || extrairSufixoInfoAtacanteDoNome(nome);
    }

    function construirSufixoInfoAtacante(linha) {
        if (!CONFIG.manterInfoAtacante) return "";

        const info = obterInfoAtacante(linha);
        const partes = [];

        if (info.jogador) partes.push(`Angreifer: ${info.jogador}`);
        if (info.aldeia) partes.push(`Herkunft: ${info.aldeia}`);

        return partes.length ? ` / ${partes.join(" / ")}` : "";
    }

    function extrairSufixoInfoAtacanteDoNome(nome) {
        const match = String(nome || "").match(/\s*(?:\||\/)\s*(?:Atacante|Angreifer|Origem|Herkunft):\s*.*$/i);
        if (!match) return "";

        return normalizarEspacos(match[0]).replace(/^\|\s*/, "/ ");
    }

    function removerInfoAtacanteAuto(nome) {
        return normalizarEspacos(
            String(nome || "")
                .replace(/\s*(?:\||\/)\s*(?:Atacante|Angreifer):\s*.*?(?=\s*(?:\||\/)\s*(?:Atacante|Angreifer|Origem|Herkunft):|$)/gi, "")
                .replace(/\s*(?:\||\/)\s*(?:Origem|Herkunft):\s*.*$/gi, ""),
        );
    }

    function obterInfoAtacante(linha) {
        return {
            jogador: obterTextoLink(obterLinkJogadorAtacante(linha)),
            aldeia: obterTextoLink(obterLinkAldeiaOrigem(linha)),
        };
    }

    function obterLinkJogadorAtacante(linha) {
        const celulaPreferida = linha.children[3];
        const linkPreferido = celulaPreferida?.querySelector(SELETORES.linkJogador);
        if (linkPreferido) return linkPreferido;

        return [...linha.querySelectorAll(SELETORES.linkJogador)]
            .find((link) => !link.closest(SELETORES.quickedit)) || null;
    }

    function obterLinkAldeiaOrigem(linha) {
        const celulaPreferida = linha.children[2];
        const linkPreferido = celulaPreferida?.querySelector(SELETORES.linkAldeia);
        if (linkPreferido) return linkPreferido;

        const linksAldeia = [...linha.querySelectorAll(SELETORES.linkAldeia)]
            .filter((link) => !link.closest(SELETORES.quickedit));
        const linksComCoordenadas = linksAldeia.filter((link) => /\b\d{3}\|\d{3}\b/.test(obterTextoLink(link)));

        if (linksComCoordenadas.length > 1) return linksComCoordenadas[1];
        if (linksComCoordenadas.length === 1) return linksComCoordenadas[0];

        return linksAldeia[1] || linksAldeia[0] || null;
    }

    function obterTextoLink(link) {
        return normalizarEspacos(link?.textContent || "");
    }

    function realcarTextoLinha(linha) {
        if (!CONFIG.realcarTexto || isApoio(linha)) {
            restaurarTextoSemRealce(linha);
            return;
        }

        const label = linha.querySelector(SELETORES.etiquetaNome);
        if (!label) return;

        const texto = normalizarEspacos(label.textContent);
        const temComandoReconhecido = Boolean(obterComandoPrincipalRealce(texto));
        const temInfoAtacanteOuOrigem = /\/\s*(Atacante|Angreifer|Origem|Herkunft):\s*/i.test(texto);

        if (!temComandoReconhecido && !temInfoAtacanteOuOrigem) {
            restaurarTextoSemRealce(linha);
            return;
        }

        const linhaEscura = linha.dataset.raTpLinhaEscura === "1";
        if (
            !texto
            || (
                label.dataset.raTpRealceTexto === texto
                && label.dataset.raTpRealceEscuro === String(linhaEscura)
            )
        ) return;

        label.textContent = "";
        label.appendChild(criarFragmentoRealceTexto(texto, linhaEscura));
        label.dataset.raTpRealceTexto = texto;
        label.dataset.raTpRealceEscuro = String(linhaEscura);
    }

    function limparRealceTextoLinha(linha) {
        const label = linha.querySelector(SELETORES.etiquetaNome);
        if (label) {
            delete label.dataset.raTpRealceTexto;
            delete label.dataset.raTpRealceEscuro;
        }
    }

    function criarFragmentoRealceTexto(texto, linhaEscura) {
        const fragmento = document.createDocumentFragment();
        const regexInfo = /\/\s*(Atacante|Angreifer|Origem|Herkunft):\s*/gi;
        const marcadores = [...texto.matchAll(regexInfo)];
        const comandoPrincipal = obterComandoPrincipalRealce(texto);

        if (!marcadores.length) {
            acrescentarTextoComTags(fragmento, texto, linhaEscura, comandoPrincipal, true);
            return fragmento;
        }

        let posicao = 0;
        marcadores.forEach((marcador, index) => {
            acrescentarTextoComTags(
                fragmento,
                texto.slice(posicao, marcador.index),
                linhaEscura,
                comandoPrincipal,
                index === 0,
            );

            const tipo = marcador[1].toLowerCase();
            const inicioValor = marcador.index + marcador[0].length;
            const fimValor = marcadores[index + 1]?.index ?? texto.length;

            acrescentarSpan(fragmento, marcador[0], (tipo === "atacante" || tipo === "angreifer") ? "infoLabelAtacante" : "infoLabelOrigem", null, linhaEscura);
            if (tipo === "origem" || tipo === "herkunft") {
                acrescentarValorOrigem(fragmento, texto.slice(inicioValor, fimValor), linhaEscura);
            } else {
                acrescentarSpan(fragmento, texto.slice(inicioValor, fimValor), "infoValorAtacante", null, linhaEscura);
            }

            posicao = fimValor;
        });

        acrescentarTextoComTags(fragmento, texto.slice(posicao), linhaEscura, comandoPrincipal, false);
        return fragmento;
    }

    function acrescentarTextoComTags(fragmento, texto, linhaEscura, comandoPrincipal, realcarUnidade) {
        const valor = String(texto || "");
        if (!valor) return;

        const tags = obterTagsParaRealce();
        const regexTags = new RegExp(tags.map((item) => escapeRegExp(item.tag)).join("|"), "g");
        let posicao = 0;
        let match;

        while ((match = regexTags.exec(valor)) !== null) {
            acrescentarSpan(
                fragmento,
                valor.slice(posicao, match.index),
                realcarUnidade && posicao === 0 && comandoPrincipal ? "unidade" : "base",
                comandoPrincipal,
                linhaEscura,
            );
            acrescentarSpan(fragmento, match[0], "tag", tags.find((item) => item.tag === match[0])?.comando, linhaEscura);
            posicao = match.index + match[0].length;
        }

        acrescentarSpan(
            fragmento,
            valor.slice(posicao),
            realcarUnidade && posicao === 0 && comandoPrincipal ? "unidade" : "base",
            comandoPrincipal,
            linhaEscura,
        );
    }

    function acrescentarValorOrigem(fragmento, texto, linhaEscura) {
        const valor = String(texto || "");
        if (!valor) return;

        const regexPartes = /(\b\d{3}\|\d{3}\b|\bK\d{1,3}\b)/g;
        let posicao = 0;
        let match;

        while ((match = regexPartes.exec(valor)) !== null) {
            acrescentarSpan(fragmento, valor.slice(posicao, match.index), "infoValorOrigem", null, linhaEscura);
            acrescentarSpan(
                fragmento,
                match[0],
                match[0].startsWith("K") ? "infoContinente" : "infoCoordenadas",
                null,
                linhaEscura,
            );
            posicao = match.index + match[0].length;
        }

        acrescentarSpan(fragmento, valor.slice(posicao), "infoValorOrigem", null, linhaEscura);
    }

    function acrescentarSpan(fragmento, texto, tipo, comando, linhaEscura) {
        if (!texto) return;

        const span = document.createElement("span");
        const estilo = obterEstiloRealce(tipo, comando, linhaEscura);

        span.textContent = texto;
        span.dataset.raTpHighlight = tipo;
        span.style.setProperty("color", estilo.cor, "important");
        span.style.setProperty("font-weight", estilo.peso);
        span.style.setProperty("text-shadow", estilo.sombra, "important");

        fragmento.appendChild(span);
    }

    function obterTagsParaRealce() {
        return COMANDOS
            .flatMap((comando) => obterTagsComAliases(comando).map((tag) => ({ tag, comando })))
            .filter((item) => item.tag)
            .sort((a, b) => b.tag.length - a.tag.length);
    }

    function obterComandoPrincipalRealce(texto) {
        return COMANDOS.find((comando) => comando.modo === "substituir" && comandoExisteNoNome(texto, comando))
            || COMANDOS.find((comando) => comandoExisteNoNome(texto, comando))
            || null;
    }

    function obterEstiloRealce(tipo, comando, linhaEscura) {
        const sombraForte = "-1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000";
        const sombraLeve = "0 1px 0 #000, 0 0 2px #000";

        if ((tipo === "tag" || tipo === "unidade") && comando) {
            if (isCorEscura(comando.corBotao)) {
                return {
                    cor: "#111111",
                    peso: "900",
                    sombra: "-1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff, 1px 1px 0 #fff, 0 0 2px #fff",
                };
            }

            return {
                cor: obterCorTextoRealce(comando.corBotao),
                peso: "800",
                sombra: sombraForte,
            };
        }

        if (CONFIG.paginaDeAtaques === "texto") {
            return { cor: "inherit", peso: "inherit", sombra: "none" };
        }

        const infoLabel = { cor: "#ffe66d", peso: "800", sombra: sombraForte };
        const estilos = {
            infoLabelAtacante: infoLabel,
            infoValorAtacante: infoLabel,
            infoLabelOrigem: infoLabel,
            infoValorOrigem: infoLabel,
            infoCoordenadas: infoLabel,
            infoContinente: infoLabel,
            base: infoLabel,
        };

        return estilos[tipo] || estilos.base;
    }

    function obterCorTextoRealce(nomeCor) {
        const coresTexto = {
            red: "#ff4a4a",
            green: "#65ff65",
            blue: "#4db8ff",
            yellow: "#ffe66d",
            orange: "#ffb347",
            lblue: "#5ffff7",
            lime: "#eaff4d",
            white: "#ffffff",
            black: "#111111",
            gray: "#dce4f2",
            dorange: "#d47cff",
            dark: "#ffffff",
            pink: "#ff8ed8",
            brown: "#d98585",
            dblue: "#8fa8ff",
            dgreen: "#62e66b",
            lgreen: "#b9ff9f",
        };

        return coresTexto[String(nomeCor || "").toLowerCase()] || "#ffffff";
    }

    function realcarInformacoesLinha(linha) {
        if (
            !CONFIG.realcarInformacoesTabela
            || CONFIG.paginaDeAtaques === "texto"
            || isApoio(linha)
        ) {
            limparRealceInformacoesLinha(linha);
            return;
        }
        if (!linha.closest("#incomings_table")) return;

        const mapa = obterMapaCabecalhos(linha);
        const fallback = {
            destino: 1,
            origem: 2,
            jogador: 3,
            distancia: 4,
            chegada: 5,
            chegaEm: 6,
        };

        aplicarRealceCelulaInfo(linha.children[obterIndiceColuna(mapa, fallback, "destino")], "destino");
        aplicarRealceCelulaInfo(linha.children[obterIndiceColuna(mapa, fallback, "origem")], "origem");
        aplicarRealceCelulaInfo(linha.children[obterIndiceColuna(mapa, fallback, "jogador")], "jogador");
        aplicarRealceCelulaInfo(linha.children[obterIndiceColuna(mapa, fallback, "distancia")], "distancia");
        aplicarRealceCelulaInfo(linha.children[obterIndiceColuna(mapa, fallback, "chegada")], "chegada");

        const celulaTempo = linha.children[obterIndiceColuna(mapa, fallback, "chegaEm")];
        aplicarRealceCelulaInfo(celulaTempo, obterTipoTempoRestante(celulaTempo));
    }

    function obterMapaCabecalhos(linha) {
        const tabela = linha.closest("table");
        if (!tabela) return {};
        if (mapasCabecalhoTabela.has(tabela)) return mapasCabecalhoTabela.get(tabela);

        const mapa = {};
        const linhaCabecalho = [...tabela.querySelectorAll("tr")].find((tr) => {
            const texto = normalizarSemAcentos(tr.textContent);
            return (texto.includes("destino") || texto.includes("ziel"))
                && (texto.includes("origem") || texto.includes("herkunft"))
                && (texto.includes("jogador") || texto.includes("spieler"))
                && (texto.includes("chegada") || texto.includes("ankunft"));
        });

        if (linhaCabecalho) {
            [...linhaCabecalho.children].forEach((celula, index) => {
                const texto = normalizarSemAcentos(celula.textContent);

                if (texto.includes("destino") || texto.includes("ziel")) mapa.destino = index;
                else if (texto.includes("origem") || texto.includes("herkunft")) mapa.origem = index;
                else if (texto.includes("jogador") || texto.includes("spieler")) mapa.jogador = index;
                else if (texto.includes("distancia") || texto.includes("entfernung")) mapa.distancia = index;
                else if (texto.includes("chega em") || texto.includes("ankunft in")) mapa.chegaEm = index;
                else if (texto.includes("chegada") || texto.includes("ankunft")) mapa.chegada = index;
            });
        }

        mapasCabecalhoTabela.set(tabela, mapa);
        return mapa;
    }

    function obterIndiceColuna(mapa, fallback, tipo) {
        return Number.isInteger(mapa[tipo]) ? mapa[tipo] : fallback[tipo];
    }

    function aplicarRealceCelulaInfo(celula, tipo) {
        if (!celula) return;

        const estilo = obterEstiloInfoTabela(tipo);
        celula.dataset.raTpInfoRealce = tipo;
        celula.style.setProperty("color", estilo.cor, "important");
        celula.style.setProperty("font-weight", estilo.peso);
        celula.style.setProperty("text-shadow", estilo.sombra, "important");

        celula.querySelectorAll("a, span").forEach((elemento) => {
            if (deveIgnorarRealceInfo(elemento)) return;

            elemento.dataset.raTpInfoElemento = "1";
            elemento.style.setProperty("color", estilo.cor, "important");
            elemento.style.setProperty("font-weight", estilo.peso);
            elemento.style.setProperty("text-shadow", estilo.sombra, "important");
        });
    }

    function deveIgnorarRealceInfo(elemento) {
        return Boolean(elemento.closest(".ra-tp-botoes, button, input, select, textarea"));
    }

    function obterTipoTempoRestante(celula) {
        const segundos = obterSegundosDeTempo(celula?.textContent || "");
        if (segundos === null) return "chegaEm";
        if (segundos <= 5 * 60) return "tempoCritico";
        if (segundos <= 15 * 60) return "tempoAviso";

        return "tempoOk";
    }

    function obterSegundosDeTempo(texto) {
        const match = String(texto || "").match(/\b(\d{1,2}):(\d{2}):(\d{2})\b/);
        if (!match) return null;

        return (Number(match[1]) * 3600) + (Number(match[2]) * 60) + Number(match[3]);
    }

    function obterEstiloInfoTabela(tipo) {
        const sombra = "0 1px 0 rgba(255, 255, 255, 0.75), 0 0 1px rgba(0, 0, 0, 0.35)";
        const infoPadrao = { cor: "#6b3500", peso: "800", sombra };
        const estilos = {
            destino: infoPadrao,
            origem: infoPadrao,
            jogador: infoPadrao,
            distancia: infoPadrao,
            chegada: infoPadrao,
            chegaEm: infoPadrao,
            tempoOk: infoPadrao,
            tempoAviso: { cor: "#a45200", peso: "900", sombra },
            tempoCritico: { cor: "#b00020", peso: "900", sombra },
        };

        return estilos[tipo] || estilos.chegaEm;
    }

    function aplicarCorAtaque(linha) {
        limparPintura(linha);

        if (
            CONFIG.paginaDeAtaques === "nada"
            || CONFIG.paginaDeAtaques === "texto"
            || isApoio(linha)
            || isComandoProprio(linha)
        ) return;

        const nome = obterNomeLinha(linha);
        const comandosEncontrados = COMANDOS.filter((comando) => comandoExisteNoNome(nome, comando));

        if (comandosEncontrados.length >= 2) {
            const cor1 = obterCor(comandosEncontrados[0].corBotao, "red").top;
            const cor2 = obterCor(comandosEncontrados[1].corBotao, "red").top;
            pintarLinha(
                linha,
                `repeating-linear-gradient(45deg, ${cor1}, ${cor1} 10px, ${cor2} 10px, ${cor2} 20px)`,
            );
            return;
        }

        if (comandosEncontrados.length === 1) {
            pintarLinha(linha, obterCor(comandosEncontrados[0].corBotao, "red").top);
            return;
        }

        pintarLinha(linha, obterCor("red", "red").bottom);
    }

    function pintarLinha(linha, background) {
        const colunaNome = linha.querySelector(SELETORES.etiquetaNome)?.closest("td");
        if (!colunaNome) return;

        linha.dataset.raTpLinhaEscura = isFundoEscuro(background) ? "1" : "0";

        if (CONFIG.paginaDeAtaques === "linha") {
            linha.querySelectorAll("td").forEach((td) => aplicarFundo(td, background));
            linha.querySelectorAll("a, .quickedit-label").forEach(aplicarTextoAtaque);
            return;
        }

        if (CONFIG.paginaDeAtaques === "coluna") {
            aplicarFundo(colunaNome, background);
            colunaNome.querySelectorAll("a, .quickedit-label").forEach(aplicarTextoAtaque);
        }
    }

    function aplicarFundo(elemento, background) {
        elemento.dataset.raTpFundo = "1";
        elemento.style.setProperty("background", background, "important");
    }

    function aplicarTextoAtaque(elemento) {
        elemento.dataset.raTpTexto = "1";
        elemento.style.setProperty("color", "white", "important");
        elemento.style.setProperty(
            "text-shadow",
            "-1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000",
            "important",
        );
    }

    function limparPintura(linha) {
        delete linha.dataset.raTpLinhaEscura;

        linha.querySelectorAll("[data-ra-tp-fundo='1']").forEach((elemento) => {
            elemento.style.removeProperty("background");
            delete elemento.dataset.raTpFundo;
        });

        linha.querySelectorAll("[data-ra-tp-texto='1']").forEach((elemento) => {
            elemento.style.removeProperty("color");
            elemento.style.removeProperty("text-shadow");
            delete elemento.dataset.raTpTexto;
        });
    }

    function isFundoEscuro(background) {
        const hex = String(background || "").match(/#[0-9a-f]{6}/i)?.[0];
        if (!hex) return false;

        const r = parseInt(hex.slice(1, 3), 16);
        const g = parseInt(hex.slice(3, 5), 16);
        const b = parseInt(hex.slice(5, 7), 16);
        const luminancia = (0.299 * r) + (0.587 * g) + (0.114 * b);

        return luminancia < 80;
    }

    function removerBotoes(linha) {
        linha.querySelectorAll(".ra-tp-botoes").forEach((elemento) => elemento.remove());
    }

    function obterNomeLinha(linha) {
        return normalizarEspacos(linha.querySelector(SELETORES.etiquetaNome)?.textContent || "");
    }

    function comandoExisteNoNome(nome, comando) {
        return obterTagsComAliases(comando).some((tag) => nome.includes(tag));
    }

    function removerTags(nome, filtroComando) {
        let resultado = normalizarEspacos(nome);

        COMANDOS.filter(filtroComando).forEach((comando) => {
            obterTagsComAliases(comando).forEach((tag) => {
                resultado = resultado.replace(new RegExp(escapeRegExp(tag), "g"), "");
            });
        });

        return normalizarEspacos(resultado);
    }

    function obterTagsComAliases(comando) {
        return [comando.tag, ...(comando.aliases || [])].filter(Boolean);
    }

    function isApoio(linha) {
        const temIconeApoio = [...linha.querySelectorAll("img")].some((img) => {
            const texto = `${img.src || ""} ${img.alt || ""} ${img.title || ""}`.toLowerCase();
            return texto.includes("support") || texto.includes("apoio") || texto.includes("suporte") || texto.includes("unterstutzung");
        });
        if (temIconeApoio) return true;

        const textoLinha = normalizarSemAcentos(linha.textContent);
        return /\b(apoio|suporte|support|unterstutzung)\b/.test(textoLinha);
    }

    function isComandoProprio(linha) {
        const tabela = linha.closest("table");
        if (!tabela) return false;

        const textoCabecalhos = [...tabela.querySelectorAll("th")]
            .map((cabecalho) => normalizarSemAcentos(cabecalho.textContent))
            .join(" ");

        return /\b(os seus comandos|seus comandos|your commands|own commands|eigene befehle|ihre befehle)\b/.test(textoCabecalhos);
    }

    function obterCor(nome, fallback) {
        return CORES[String(nome || "").toLowerCase()] || CORES[fallback] || CORES.white;
    }

    function normalizarEspacos(valor) {
        return String(valor || "").replace(/\s+/g, " ").trim();
    }

    function normalizarSemAcentos(valor) {
        return normalizarEspacos(valor)
            .normalize("NFD")
            .replace(/[\u0300-\u036f]/g, "")
            .toLowerCase();
    }

    function escapeRegExp(valor) {
        return String(valor).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
    }

    function esperarPor(obterValor, timeoutMs, intervaloMs) {
        const inicio = Date.now();

        return new Promise((resolve) => {
            const tick = () => {
                const valor = obterValor();
                if (valor) {
                    resolve(valor);
                    return;
                }

                if (Date.now() - inicio >= timeoutMs) {
                    resolve(null);
                    return;
                }

                setTimeout(tick, intervaloMs);
            };

            tick();
        });
    }

    function aplicarEstilos() {
        let style = document.getElementById(STYLE_ID);
        if (!style) {
            style = document.createElement("style");
            style.id = STYLE_ID;
            document.head.appendChild(style);
        }

        style.textContent = `
            .ra-tp-botoes {
                float: right;
                display: inline-flex;
                flex-wrap: wrap;
                gap: 1px;
                align-items: center;
                justify-content: flex-end;
                margin-left: 4px;
                max-width: 100%;
                vertical-align: middle;
            }

            .ra-tp-botao {
                display: inline-flex !important;
                align-items: center !important;
                justify-content: center !important;
                flex: 0 0 ${CONFIG.tamanhoBotaoPx}px;
                width: ${CONFIG.tamanhoBotaoPx}px;
                min-width: ${CONFIG.tamanhoBotaoPx}px;
                max-width: ${CONFIG.tamanhoBotaoPx}px;
                height: ${CONFIG.tamanhoBotaoPx}px;
                padding: 0 ${CONFIG.paddingHorizontalBotaoPx}px !important;
                border: 1px solid rgba(0, 0, 0, 0.45) !important;
                border-radius: 3px;
                line-height: 1 !important;
                font-weight: 600;
                text-align: center !important;
                text-indent: 0 !important;
                white-space: nowrap !important;
                cursor: pointer;
                box-sizing: border-box;
                box-shadow:
                    inset 0 1px 0 rgba(255, 255, 255, 0.42),
                    inset 0 -1px 0 rgba(0, 0, 0, 0.18),
                    0 1px 1px rgba(0, 0, 0, 0.22);
                text-shadow: 0 1px 0 rgba(0, 0, 0, 0.7);
                transition: filter 100ms ease, transform 100ms ease, box-shadow 100ms ease;
                vertical-align: middle;
            }

            .ra-tp-botao:hover {
                filter: brightness(1.12) saturate(1.08);
                transform: translateY(-1px);
                box-shadow:
                    inset 0 1px 0 rgba(255, 255, 255, 0.5),
                    inset 0 -1px 0 rgba(0, 0, 0, 0.2),
                    0 2px 2px rgba(0, 0, 0, 0.24);
            }

            .ra-tp-botao:active {
                filter: brightness(0.96);
                transform: translateY(0);
                box-shadow:
                    inset 0 1px 2px rgba(0, 0, 0, 0.38),
                    0 1px 1px rgba(0, 0, 0, 0.18);
            }

            .ra-tp-botao:focus {
                outline: 1px solid rgba(255, 255, 255, 0.75);
                outline-offset: 1px;
            }

            .ra-tp-botao-escuro {
                border-color: rgba(255, 255, 255, 0.95) !important;
                box-shadow:
                    inset 0 1px 0 rgba(255, 255, 255, 0.3),
                    inset 0 -1px 0 rgba(0, 0, 0, 0.25),
                    0 0 0 1px rgba(0, 0, 0, 0.5),
                    0 1px 1px rgba(0, 0, 0, 0.22);
            }

            .ra-tp-reset {
                margin-left: 3px !important;
            }

            .ra-tp-config-button {
                position: fixed;
                left: 12px;
                right: auto;
                top: 310px;
                bottom: auto;
                z-index: 2147483647;
                box-sizing: border-box !important;
                width: 30px !important;
                min-width: 30px !important;
                max-width: min(244px, calc(100vw - 8px)) !important;
                height: 28px !important;
                display: flex !important;
                align-items: center !important;
                justify-content: flex-start !important;
                gap: 0 !important;
                overflow: hidden !important;
                cursor: pointer !important;
                border: 1px solid #3b1e00 !important;
                border-radius: 2px !important;
                background: linear-gradient(to bottom, #c8a050, #9a5000 55%, #7a3e00) !important;
                color: #fff !important;
                font-size: 12px !important;
                font-weight: bold !important;
                line-height: 1 !important;
                text-align: center !important;
                text-shadow: 1px 1px 1px #000 !important;
                white-space: nowrap !important;
                padding: 0 6px !important;
                transition:
                    width 180ms ease,
                    min-width 180ms ease,
                    padding 180ms ease,
                    gap 180ms ease,
                    background 180ms ease !important;
                box-shadow:
                    inset 0 1px 0 rgba(255, 255, 255, 0.35),
                    inset 0 -1px 0 rgba(0, 0, 0, 0.35),
                    0 2px 5px rgba(0, 0, 0, 0.45) !important;
            }

            .ra-tp-config-button:hover,
            .ra-tp-config-button:focus-visible {
                width: 244px !important;
                min-width: 244px !important;
                gap: 8px !important;
                padding: 0 9px !important;
                background: linear-gradient(to bottom, #e0b860, #a05000 55%, #7a3e00) !important;
            }

            .ra-tp-config-button-icon {
                display: inline-flex !important;
                flex: 0 0 16px !important;
                width: 16px !important;
                height: 16px !important;
                align-items: center !important;
                justify-content: center !important;
                box-sizing: border-box !important;
                border: 1px solid #f0d080 !important;
                border-radius: 2px !important;
                background: radial-gradient(circle at 30% 30%, #e8c873 0%, #c9a14a 55%, #7a5c1e 100%) !important;
                color: #fff !important;
                font-size: 9px !important;
                font-weight: 900 !important;
                line-height: 14px !important;
                text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8) !important;
                box-shadow:
                    inset 0 1px 0 rgba(255, 255, 255, 0.42),
                    inset 0 -1px 0 rgba(0, 0, 0, 0.2),
                    0 1px 1px rgba(0, 0, 0, 0.75) !important;
            }

            .ra-tp-config-button-label {
                display: inline-block !important;
                max-width: 0 !important;
                opacity: 0 !important;
                overflow: hidden !important;
                font-size: 12px !important;
                line-height: 26px !important;
                transform: translateX(-4px) !important;
                white-space: nowrap !important;
                transition:
                    max-width 180ms ease,
                    opacity 140ms ease,
                    transform 180ms ease !important;
            }

            .ra-tp-config-button:hover .ra-tp-config-button-label,
            .ra-tp-config-button:focus-visible .ra-tp-config-button-label {
                max-width: 198px !important;
                opacity: 1 !important;
                transform: translateX(0) !important;
            }

            .ra-tp-config-overlay[hidden] {
                display: none !important;
            }

            .ra-tp-config-overlay {
                position: fixed !important;
                inset: 0 !important;
                z-index: 2147483646 !important;
                display: flex !important;
                align-items: center !important;
                justify-content: center !important;
                padding: 20px !important;
                background: rgba(0, 0, 0, 0.58) !important;
                box-sizing: border-box !important;
                font-family: Arial, Verdana, sans-serif !important;
            }

            .ra-tp-config-dialog {
                position: relative !important;
                width: min(850px, calc(100vw - 48px)) !important;
                max-width: calc(100vw - 42px) !important;
                max-height: calc(100vh - 72px) !important;
                overflow: visible !important;
                padding: 8px !important;
                border: 1px solid #2a2118 !important;
                border-radius: 4px !important;
                background: #9f9174 !important;
                color: #3b2508 !important;
                box-sizing: border-box !important;
                box-shadow:
                    0 0 0 1px #efe3c5,
                    0 0 0 3px #5c5141,
                    0 0 0 4px #b9ad94,
                    0 3px 12px rgba(0, 0, 0, 0.55) !important;
            }

            .ra-tp-config-dialog::before {
                content: none !important;
            }

            .ra-tp-config-frame {
                width: 820px;
                max-width: calc(100vw - 48px);
                border: 2px solid #7a3e00;
                border-radius: 4px;
                background: #f4e4b8;
                color: #3b2508;
                font-family: Arial, Verdana, sans-serif;
                box-sizing: border-box;
                overflow: hidden;
            }

            .ra-tp-config-header {
                padding: 12px 14px 9px;
                border-bottom: 1px solid #c98c48;
                background: linear-gradient(to bottom, #f7e8c1 0%, #edd49a 100%);
            }

            .ra-tp-config-header h3 {
                margin: 0;
                color: #7a3e00;
                font-size: 16px;
                line-height: 20px;
            }

            .ra-tp-config-header span {
                display: block;
                margin-top: 2px;
                color: #5e3b16;
                font-size: 12px;
                line-height: 15px;
            }

            .ra-tp-config-close {
                position: absolute !important;
                top: -12px !important;
                right: -12px !important;
                z-index: 3 !important;
                width: 19px !important;
                height: 19px !important;
                padding: 0 !important;
                border: 2px solid #2a2118 !important;
                border-radius: 3px !important;
                background: #f3dfaa !important;
                color: #110705 !important;
                font-size: 18px !important;
                font-weight: bold !important;
                line-height: 15px !important;
                text-align: center !important;
                cursor: pointer !important;
                box-shadow:
                    inset 0 0 0 1px #fff0c8,
                    0 1px 2px rgba(0, 0, 0, 0.55) !important;
            }

            .ra-tp-config-body {
                padding: 10px 12px 14px;
            }

            .ra-tp-config-section {
                display: grid;
                grid-template-columns: minmax(190px, 230px) minmax(0, 1fr);
                gap: 10px 18px;
                margin: 0;
                padding: 11px 0 12px 10px;
                border-top: 1px solid #d5b579;
                border-left: 4px solid #9b6a2f;
            }

            .ra-tp-config-section:first-child {
                border-top: 0;
            }

            .ra-tp-config-appearance { border-left-color: #c9a14a; }
            .ra-tp-config-content { border-left-color: #1f9ac5; }
            .ra-tp-config-buttons { border-left-color: #e0a51d; }
            .ra-tp-config-actions { border-left-color: #8a6424; }

            .ra-tp-config-section-copy,
            .ra-tp-config-section-options {
                min-width: 0;
            }

            .ra-tp-config-section-title {
                margin: 0 0 4px;
                color: #7a3e00;
                font-size: 13px;
                font-weight: bold;
                line-height: 16px;
                text-transform: uppercase;
            }

            .ra-tp-config-section-desc {
                color: #5e3b16;
                font-size: 11px;
                line-height: 14px;
            }

            .ra-tp-config-section-options {
                display: grid;
                gap: 8px;
            }

            .ra-tp-config-fields-grid {
                grid-template-columns: repeat(2, minmax(0, 1fr));
            }

            .ra-tp-config-field {
                display: grid;
                gap: 3px;
                min-width: 0;
                color: #2b1b08;
                font-size: 11px;
                font-weight: 700;
            }

            .ra-tp-config-field input,
            .ra-tp-config-field select {
                width: 100% !important;
                min-width: 0 !important;
                height: 28px !important;
                padding: 4px 7px !important;
                border: 1px solid #b57d2e !important;
                border-radius: 2px !important;
                background: #fff6d7 !important;
                color: #241006 !important;
                font-size: 11px !important;
                box-sizing: border-box !important;
                box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.12) !important;
            }

            .ra-tp-config-field input:focus,
            .ra-tp-config-field select:focus {
                outline: 2px solid rgba(122, 62, 0, 0.25) !important;
                border-color: #7a3e00 !important;
            }

            .ra-tp-config-toggle {
                display: grid;
                grid-template-columns: 18px minmax(0, 1fr);
                gap: 6px;
                align-items: start;
                min-height: 22px;
                color: #2b1b08;
                font-size: 12px;
                font-weight: bold;
                line-height: 15px;
                cursor: pointer;
            }

            .ra-tp-config-toggle input {
                width: 14px;
                height: 14px;
                margin: 0;
                margin-top: 1px;
                accent-color: #7a3e00;
            }

            .ra-tp-config-toggle-grid {
                display: grid;
                grid-template-columns: repeat(2, minmax(0, 1fr));
                gap: 5px 12px;
            }

            .ra-tp-config-command-list {
                display: grid;
                grid-template-columns: repeat(3, minmax(0, 1fr));
                gap: 5px 10px;
                padding-bottom: 8px;
                border-bottom: 1px solid #d5b579;
            }

            .ra-tp-config-command {
                display: grid;
                grid-template-columns: 16px minmax(0, 1fr);
                gap: 5px;
                align-items: start;
                min-width: 0;
                font-size: 11px;
                font-weight: 700;
                line-height: 14px;
                cursor: pointer;
            }

            .ra-tp-config-command input {
                width: 14px;
                height: 14px;
                margin: 0;
                accent-color: #7a3e00;
            }

            .ra-tp-config-command span {
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            }

            .ra-tp-config-footer {
                display: flex;
                flex-wrap: wrap;
                align-items: center;
                justify-content: flex-start;
                gap: 8px;
            }

            .ra-tp-config-primary,
            .ra-tp-config-secondary {
                flex: 0 0 118px !important;
                width: 118px !important;
                min-width: 118px !important;
                height: 24px !important;
                min-height: 24px !important;
                padding: 1px 8px !important;
                border: 1px solid #3b1e00 !important;
                border-radius: 3px !important;
                background: linear-gradient(to bottom, #c8a050, #9a5000 55%, #7a3e00) !important;
                color: #fff !important;
                font-size: 11px !important;
                font-weight: bold !important;
                line-height: 16px !important;
                text-shadow: 1px 1px 1px #000 !important;
                cursor: pointer !important;
                box-sizing: border-box !important;
                box-shadow:
                    inset 0 1px 0 rgba(255, 255, 255, 0.25),
                    inset 0 -1px 0 rgba(0, 0, 0, 0.3) !important;
            }

            .ra-tp-config-primary:hover,
            .ra-tp-config-secondary:hover {
                background: linear-gradient(to bottom, #e0b860, #a05000 55%, #7a3e00) !important;
            }

            .ra-tp-config-secondary {
                background: linear-gradient(to bottom, #8a6424, #6b4d1a 55%, #4a350f) !important;
                border-color: #3b1e00 !important;
            }

            @media (max-width: 760px) {
                .ra-tp-config-dialog {
                    width: calc(100vw - 28px) !important;
                    max-height: calc(100vh - 36px) !important;
                }

                .ra-tp-config-section {
                    grid-template-columns: 1fr;
                    gap: 8px;
                }

                .ra-tp-config-command-list {
                    grid-template-columns: repeat(2, minmax(0, 1fr));
                }
            }

            @media (max-width: 480px) {
                .ra-tp-config-fields-grid,
                .ra-tp-config-toggle-grid,
                .ra-tp-config-command-list {
                    grid-template-columns: 1fr;
                }
            }
        `;
    }

    if (document.readyState === "loading") {
        document.addEventListener("DOMContentLoaded", iniciar, { once: true });
    } else {
        iniciar();
    }
})();