Mudanças entre as edições de "Widget:C.Translator"

De Wiki Gla
Ir para navegação Ir para pesquisar
m
m
 
(2 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 1: Linha 1:
<!-- WEAPON TOGGLE SYSTEM - Estado global + popup i18n -->
<!-- CHARACTER TRANSLATOR SYSTEM -->
<script>
<script>
    (() => {
  (() => {
        let modalListenersBound = false;
    let __langReqSeq = 0;


        // Variável global para o ícone do weapon toggle
    // ---------- helpers ----------
        let globalWeaponToggleIcon = null;
    const normalizeLang = (s) => {
      s = (s || "").toLowerCase();
      if (s === "pt-br" || s === "pt_br" || s === "ptbr") return "pt";
      return s.split("-")[0] || "pt";
    };


        // Função helper para construir URL de arquivo (mesmo sistema usado em Character.Skills.html)
    const markActive = (langFull) => {
        function filePathURL(fileName) {
      const lang = (langFull || "pt-br").toLowerCase();
            // Evita requisições para Nada.png que não existe
      document.querySelectorAll(".char-flag[data-lang]").forEach((b) => {
            if (!fileName || fileName.trim() === '' || fileName === 'Nada.png' || fileName.toLowerCase() === 'nada.png') {
        b.classList.toggle("active", b.dataset.lang === lang);
                return '';
      });
            }
    };
            const f = encodeURIComponent(fileName.replace(/^Arquivo:|^File:/, ''));
            const base = (window.mw && mw.util && typeof mw.util.wikiScript === 'function') ? mw.util.wikiScript() : (window.mw && window.mw.config ? (mw.config.get('wgScript') || '/index.php') : '/index.php');
            // Garante HTTPS para evitar Mixed Content
            let url = `${base}?title=Especial:FilePath/${f}`;
            if (window.location.protocol === 'https:' && url.startsWith('http://')) {
                url = url.replace('http://', 'https://');
            }
            return url;
        }
 
        // Função para resolver o ícone do weapon toggle do character-box
        function resolveCharacterWeaponIcon() {
            const root = document.querySelector('.character-box');
            if (!root) return;
            const raw = root.dataset.weaponicon;
            if (!raw || raw.trim() === '' || raw === 'Nada.png') {
                globalWeaponToggleIcon = null;
                return;
            }
            globalWeaponToggleIcon = filePathURL(raw.trim());
            // console.log('[WeaponToggle] Resolved weaponicon:', raw, '->', globalWeaponToggleIcon);
        }
 
        // Textos i18n para o popup
        const i18nTexts = {
            pt: {
                title: 'Visualização com Arma Especial',
                body1: 'Este modo ativa a visualização do personagem equipado com sua <strong>arma especial</strong>.',
                body2: 'Algumas habilidades são diferentes enquanto estão com a arma equipada, essas habilidades ficam <strong>destacadas com borda vermelha</strong>.',
                dontShow: 'Não mostrar novamente',
                ok: 'Entendi',
                weaponLink: 'Ver página da arma:'
            },
            en: {
                title: 'Special Weapon View',
                body1: 'This mode activates the view of the character equipped with their <strong>special weapon</strong>.',
                body2: 'Some abilities are different while equipped with the weapon, these abilities are <strong>highlighted with a red border</strong>.',
                dontShow: "Don't show again",
                ok: 'Got it',
                weaponLink: 'View weapon page:'
            },
            es: {
                title: 'Visualización con Arma Especial',
                body1: 'Este modo activa la visualización del personaje equipado con su <strong>arma especial</strong>.',
                body2: 'Algunas habilidades son diferentes mientras están con el arma equipada, estas habilidades quedan <strong>destacadas con borde rojo</strong>.',
                dontShow: 'No mostrar de nuevo',
                ok: 'Entendido',
                weaponLink: 'Ver página del arma:'
            },
            pl: {
                title: 'Widok z Bronią Specjalną',
                body1: 'Ten tryb aktywuje widok postaci wyposażonej w <strong>broń specjalną</strong>.',
                body2: 'Niektóre umiejętności różnią się podczas posiadania broni, te umiejętności są <strong>podświetlone czerwoną obwódką</strong>.',
                dontShow: 'Nie pokazuj ponownie',
                ok: 'Rozumiem',
                weaponLink: 'Zobacz stronę broni:'
            }
        };
 
        const getCurrentLang = () => {
            const html = document.documentElement.lang || 'pt-br';
            const norm = html.toLowerCase().split('-')[0];
            return i18nTexts[norm] ? norm : 'pt';
        };
 
        const bindModalEvents = () => {
            if (modalListenersBound) return;
            modalListenersBound = true;
            document.addEventListener('click', (ev) => {
                if (ev.target.closest('.weapon-modal-close') || ev.target.closest('.weapon-modal-btn')) {
                    const checkbox = document.getElementById('weapon-dont-show');
                    if (checkbox && checkbox.checked) {
                        try { localStorage.setItem('glaWeaponPopupDismissed', '1'); } catch (x) { }
                    }
                    hidePopup();
                    return;
                }
                if (ev.target.classList.contains('weapon-modal-overlay')) {
                    hidePopup();
                }
            });
        };
 
        const applyWeaponState = (enabled) => {
            if (typeof window.__setGlobalWeaponEnabled === 'function') {
                window.__setGlobalWeaponEnabled(enabled);
            }
 
            try {
                localStorage.setItem('glaWeaponEnabled', enabled ? '1' : '0');
            } catch (x) { }
 
            // Dispara evento para atualizar subskills
            window.dispatchEvent(new CustomEvent('gla:weaponToggled', { detail: { enabled } }));
 
            // SISTEMA UNIFICADO: Aplica toggle em skills E subskills
            // Skills principais e subskills usam data-weapon (padronizado)
            document.querySelectorAll('.skill-icon[data-weapon], .subicon[data-weapon]').forEach(el => {
                if (enabled) {
                    el.classList.add('has-weapon-available');
                } else {
                    el.classList.remove('has-weapon-available');
                    el.classList.remove('weapon-equipped');
                    el.style.removeProperty('--weapon-badge-url');
                    const ind = el.querySelector('.weapon-indicator');
                    if (ind) ind.remove();
                }
            });
 
            // Atualiza descrição da skill/subskill selecionada (se houver) para refletir estado da arma
            // Aguarda um pouco mais para garantir que o estado global foi sincronizado
            setTimeout(() => {
                // Atualiza skill principal se houver - força reativação completa incluindo vídeo
                const sel = document.querySelector('.skill-icon.active:not(.weapon-bar-toggle)');
                if (sel) {
                    // Força uma reativação completa da skill para garantir que vídeo seja atualizado
                    if (typeof window.__subskills !== 'undefined' && window.__subskills.hideAll) {
                        const videoBox = document.querySelector('.video-container') || document.querySelector('.skills-video-box');
                        if (videoBox) window.__subskills.hideAll(videoBox);
                    }
                    // Reativa a skill para atualizar vídeo, descrição e atributos
                    if (typeof window.__lastActiveSkillIcon !== 'undefined' && window.__lastActiveSkillIcon === sel) {
                        sel.dispatchEvent(new Event('click', { bubbles: true }));
                    } else {
                        sel.dispatchEvent(new Event('click', { bubbles: true }));
                    }
                }
                // Atualiza subskill ativa se houver - força reativação completa incluindo vídeo
                const activeSub = document.querySelector('.subicon.active');
                if (activeSub) {
                    activeSub.dispatchEvent(new Event('click', { bubbles: true }));
                }
            }, 100);
        };
 
        const updateModalTexts = (modal) => {
            const lang = getCurrentLang();
            const t = i18nTexts[lang];


            const title = modal.querySelector('.weapon-modal-header h3');
    const updateSkillsTabLabel = (norm) => {
            if (title) title.textContent = t.title;
      const map = {
        en: "Skills",
        pt: "Habilidades",
        es: "Habilidades",
        pl: "Umiejętności",
      };
      const btn =
        document.querySelector('.character-tabs .tab-btn[data-tab="skills"]') ||
        Array.from(document.querySelectorAll(".character-tabs .tab-btn")).find(
          (b) => /skill|habil|umiej/i.test(b.textContent || "")
        );
      if (btn) btn.textContent = map[norm] || map.pt;
    };


            const body = modal.querySelector('.weapon-modal-body');
    // ---------- skills ----------
            if (body) {
    const pickDescFor = (icon, norm) => {
                const p1 = body.querySelector('p:first-child');
      const keyMap = { pt: "descPt", en: "descEn", es: "descEs", pl: "descPl" };
                const p2 = body.querySelector('p:nth-child(2)');
      const order = [
                if (p1) p1.innerHTML = t.body1;
        keyMap[norm],
                if (p2) p2.innerHTML = t.body2;
        "descPt",
            }
        "descEn",
        "descEs",
        "descPl",
      ].filter(Boolean);
      for (const k of order) {
        const v = (icon.dataset[k] || "").trim();
        if (v) return v;
      }
      return "";
    };


            const checkbox = modal.querySelector('.weapon-modal-checkbox span');
    const updateAllSkillDescs = (norm) => {
            if (checkbox) checkbox.textContent = t.dontShow;
      document.querySelectorAll(".icon-bar .skill-icon").forEach((icon) => {
        icon.dataset.desc = pickDescFor(icon, norm);
      });
    };


            const btn = modal.querySelector('.weapon-modal-btn');
    // ---------- tier & tags ----------
            if (btn) btn.textContent = t.ok;
    const updateTierAndTags = (norm) => {
 
      const cont = document.querySelector(".class-tags");
            // Atualiza link da arma se existir
      if (!cont) return;
            try {
                const firstWithWeapon = document.querySelector('.skill-icon[data-weapon]');
                if (firstWithWeapon) {
                    const raw = firstWithWeapon.getAttribute('data-weapon');
                    const obj = JSON.parse(raw || '{}');
                    const nm = (obj && obj.name) ? String(obj.name).trim() : '';
                    if (nm) {
                        const linkHost = (window.mw && mw.util && typeof mw.util.getUrl === 'function') ? mw.util.getUrl(nm) : ('/index.php?title=' + encodeURIComponent(nm));
                        const holder = modal.querySelector('.weapon-info-link');
                        if (holder) {
                            holder.style.display = 'block';
                            holder.innerHTML = `<a href="${linkHost}">${t.weaponLink} ${nm}</a>`;
                        }
                    }
                }
            } catch (_) { }
        };
 
        const ensureModal = () => {
            let modal = document.getElementById('weapon-info-modal');
            if (modal) {
                updateModalTexts(modal);
                return modal;
            }
 
            // Insere dentro da character-box para isolar completamente
            const container = document.querySelector('.character-box') || document.querySelector('#mw-content-text') || document.body;
 
            modal = document.createElement('div');
            modal.id = 'weapon-info-modal';
            modal.className = 'weapon-modal';
            modal.innerHTML = `
            <div class="weapon-modal-overlay"></div>
            <div class="weapon-modal-content">
                <div class="weapon-modal-header">
                    <h3></h3>
                    <button class="weapon-modal-close" type="button" aria-label="Fechar">&times;</button>
                </div>
                <div class="weapon-modal-body">
                    <p></p>
                    <p></p>
                    <p class="weapon-info-link"></p>
                </div>
                <div class="weapon-modal-footer">
                    <label class="weapon-modal-checkbox">
                        <input type="checkbox" id="weapon-dont-show">
                        <span></span>
                    </label>
                    <button class="weapon-modal-btn" type="button"></button>
                </div>
            </div>
        `;
            container.appendChild(modal);
            updateModalTexts(modal);
            bindModalEvents();
            return modal;
        };
 
        const showPopup = () => {
            const modal = ensureModal();
            if (modal) {
                updateModalTexts(modal);
                // Força reflow antes de adicionar classe para garantir transição
                void modal.offsetHeight;
                modal.classList.add('show');
            }
        };


        const hidePopup = () => {
      const tier = cont.querySelector(".class-tag.tier");
            const m = document.getElementById('weapon-info-modal');
      if (tier) {
            if (m) m.classList.remove('show');
        const t =
         };
          tier.getAttribute("data-tier-" + norm) ||
          tier.getAttribute("data-tier-pt") ||
          tier.getAttribute("data-tier-en") ||
          tier.getAttribute("data-tier-es") ||
          tier.getAttribute("data-tier-pl") ||
          "";
         if (t) tier.textContent = t;
      }


        window.__applyWeaponState = applyWeaponState;
      let tags = [];
        window.__glaWeaponShowPopup = showPopup;
      const pack = cont.getAttribute("data-tags-i18n");
        window.__glaWeaponHidePopup = hidePopup;
      if (pack) {
         try {
         try {
             window.dispatchEvent(new CustomEvent('weapon:ready', { detail: { applyWeaponState, showPopup, hidePopup } }));
          const obj = JSON.parse(pack);
         } catch (err) {
          const arr =
        }
             obj?.[norm] || obj?.pt || obj?.en || obj?.es || obj?.pl || [];
          if (Array.isArray(arr)) tags = arr;
         } catch (e) { }
      }


        // Escuta mudanças de idioma
      if (!tags.length) {
        window.addEventListener('gla:langChanged', () => {
        const raw =
            const modal = document.getElementById('weapon-info-modal');
          cont.getAttribute("data-tags-" + norm) ||
            if (modal) updateModalTexts(modal);
          cont.getAttribute("data-tags-pt") ||
        });
          cont.getAttribute("data-tags-en") ||
 
          cont.getAttribute("data-tags-es") ||
        // Função para obter o nome da arma
          cont.getAttribute("data-tags-pl") ||
         function getWeaponName() {
          "";
            let weaponName = 'Arma Especial';
         if (raw) {
            try {
          try {
                const firstWithWeapon = document.querySelector('.skill-icon[data-weapon]');
            const maybe = JSON.parse(raw);
                if (firstWithWeapon) {
            if (Array.isArray(maybe)) tags = maybe;
                    const raw = firstWithWeapon.getAttribute('data-weapon');
          } catch (e) { }
                    const obj = JSON.parse(raw || '{}');
          if (!tags.length && typeof raw === "string") {
                    if (obj && obj.name) {
            tags = raw
                        weaponName = String(obj.name).trim();
              .split(",")
                    }
              .map((s) => s.trim())
                }
              .filter(Boolean);
            } catch (e) { }
          }
            return weaponName;
         }
         }
      }


        // Função para criar o novo toggle abaixo do char-translator
      if (!tags.length) return;
        function createWeaponToggle() {
            // Remove toggle antigo se existir
            const oldToggle = document.querySelector('.weapon-bar-toggle');
            if (oldToggle) oldToggle.remove();


            const existingContainer = document.querySelector('.weapon-toggle-container');
      // Tags invisíveis (não devem ser exibidas na wiki)
            if (existingContainer) return existingContainer;
      const HIDDEN_TAGS = {
        mulher: true,
        woman: true,
        mujer: true,
        kobieta: true,
      };


            const characterHeader = document.querySelector('.character-header');
      cont
            if (!characterHeader) return null;
        .querySelectorAll(".class-tag:not(.tier)")
        .forEach((el) => el.remove());
      tags.forEach((t) => {
        // Filtra tags invisíveis
        const normalized = (t || "").toLowerCase().trim();
        if (HIDDEN_TAGS[normalized]) return;


            // Resolve o ícone
        const chip = document.createElement("span");
            resolveCharacterWeaponIcon();
        chip.className = "class-tag";
            const weaponName = getWeaponName();
        chip.textContent = t;
        cont.appendChild(chip);
      });
    };


            // Cria o container do toggle
    // ---------- FLAGS: tooltips i18n ----------
            const container = document.createElement('div');
    const updateFlagTooltips = (norm) => {
            container.className = 'weapon-toggle-container';
      const skillsRoot = document.querySelector("#skills");
            container.setAttribute('role', 'button');
      if (!skillsRoot) return;
            container.setAttribute('aria-pressed', 'false');
      let pack = {};
            container.setAttribute('aria-label', weaponName);
      try {
        pack = JSON.parse(skillsRoot.dataset.i18nFlags || "{}");
      } catch (e) { }
      const dict = pack[norm] || pack.pt || {};
      const tooltip = window.__globalSkillTooltip;
      if (!tooltip) return;


            // Cria o sprite (círculo com imagem)
      document
            const sprite = document.createElement('div');
        .querySelectorAll(".skill-flags .skill-flag[data-flag]")
            sprite.className = 'weapon-toggle-sprite';
        .forEach((el) => {
          delete el.dataset.flagTipWired;
        });


            if (globalWeaponToggleIcon) {
      const descBoxes = document.querySelectorAll(".desc-box");
                const img = document.createElement('img');
      descBoxes.forEach((box) => {
                img.src = globalWeaponToggleIcon;
        if (box.querySelector(".skill-flags")) {
                img.alt = weaponName;
          const flags = box.querySelectorAll(
                img.className = 'weapon-toggle-icon';
            ".skill-flags .skill-flag[data-flag]"
                img.decoding = 'async';
          );
                img.loading = 'eager'; // Ícone do toggle é crítico - carrega imediatamente
          flags.forEach((el) => {
                img.width = 50;
            const key = el.getAttribute("data-flag");
                img.height = 50;
            const tip = (dict && dict[key]) || "";
                img.onerror = function () {
            if (!tip) return;
                    // console.error('[WeaponToggle] Erro ao carregar imagem:', globalWeaponToggleIcon);
            delete el.dataset.flagTipWired;
                };
            el.setAttribute("aria-label", tip);
                img.onload = function () {
            if (el.hasAttribute("title")) el.removeAttribute("title");
                    // console.log('[WeaponToggle] Imagem carregada com sucesso:', globalWeaponToggleIcon);
                };
                sprite.appendChild(img);
            }


             // Cria a barra com texto
             el.addEventListener("mouseenter", () => {
            const bar = document.createElement('div');
              const tipEl = document.querySelector(".skill-tooltip");
            bar.className = 'weapon-toggle-bar';
              if (tipEl) tipEl.classList.add("flag-tooltip");
            const nameSpan = document.createElement('span');
              tooltip.show(el, tip);
             nameSpan.className = 'weapon-toggle-name';
             });
             nameSpan.setAttribute('data-lang', getCurrentLang());
             el.addEventListener("mousemove", () => {
            bar.appendChild(nameSpan);
              if (performance.now() >= tooltip.lockUntil.value) {
 
                tooltip.measureAndPos(el);
            container.appendChild(sprite);
              }
            container.appendChild(bar);
             });
 
             el.addEventListener("click", () => {
             // Adiciona evento de clique
              tooltip.lockUntil.value = performance.now() + 240;
             container.addEventListener('click', () => {
              tooltip.measureAndPos(el);
                let currentState = false;
            });
                try {
            el.addEventListener("mouseleave", () => {
                    currentState = localStorage.getItem('glaWeaponEnabled') === '1';
              const tipEl = document.querySelector(".skill-tooltip");
                } catch (e) { }
              if (tipEl) tipEl.classList.remove("flag-tooltip");
                const nextState = !currentState;
              tooltip.hide();
                if (nextState) {
                    // Verifica se o popup foi dispensado antes de mostrar
                    let shouldShowPopup = true;
                    try {
                        if (localStorage.getItem('glaWeaponPopupDismissed') === '1') {
                            shouldShowPopup = false;
                        }
                    } catch (e) { }
                    if (shouldShowPopup && typeof window.__glaWeaponShowPopup === 'function') {
                        window.__glaWeaponShowPopup();
                    }
                }
                if (typeof window.__applyWeaponState === 'function') {
                    window.__applyWeaponState(nextState);
                }
             });
             });
 
             el.dataset.flagTipWired = "1";
            // Insere no container de controles (character-header-controls)
          });
            const controlsContainer = document.querySelector('.character-header-controls');
            if (controlsContainer) {
                controlsContainer.appendChild(container);
            } else {
                // Fallback: insere no character-header se o container não existir
                characterHeader.appendChild(container);
            }
 
            // Atualiza estado visual inicial
            updateToggleVisualState();
 
             return container;
        }
 
        // Função para atualizar o estado visual do toggle
        function updateToggleVisualState() {
            const container = document.querySelector('.weapon-toggle-container');
            if (!container) return;
 
            let isEnabled = false;
            try {
                isEnabled = localStorage.getItem('glaWeaponEnabled') === '1';
            } catch (e) { }
 
            if (isEnabled) {
                container.classList.add('weapon-active');
                container.setAttribute('aria-pressed', 'true');
            } else {
                container.classList.remove('weapon-active');
                container.setAttribute('aria-pressed', 'false');
            }
 
            // Atualiza idioma do texto
            const nameSpan = container.querySelector('.weapon-toggle-name');
            if (nameSpan) {
                nameSpan.setAttribute('data-lang', getCurrentLang());
            }
         }
         }
      });
    };


        // Observa quando o container de controles é criado para posicionar o toggle
    // ---------- SKINS: tooltips i18n ----------
        function observeCharacterHeader() {
    const updateSkinTooltips = (norm) => {
            const controlsContainer = document.querySelector('.character-header-controls');
      const root = document.querySelector("#skins");
            const characterHeader = document.querySelector('.character-header');
      if (!root) return;
            if (controlsContainer || characterHeader) {
      const slots = root.querySelectorAll(".podium-slot");
                createWeaponToggle();
      if (!slots.length) return;
            } else {
                // Tenta novamente após um delay
                setTimeout(observeCharacterHeader, 100);
            }
        }


        // Observa mudanças no DOM para detectar quando o container de controles é criado
      slots.forEach((slot) => {
        function observeDOMForHeader() {
        const title = slot.getAttribute("data-skin-title") || "";
            const observer = new MutationObserver((mutations) => {
        const pack = slot.getAttribute("data-skin-tooltip-i18n");
                mutations.forEach((mutation) => {
        const titleHtml = title
                    mutation.addedNodes.forEach((node) => {
          ? '<div class="skin-tooltip-title" style="margin:0">' +
                        if (node.nodeType === 1) {
          title +
                            if (node.classList && (node.classList.contains('character-header-controls') || node.classList.contains('character-header'))) {
          "</div>"
                                setTimeout(() => createWeaponToggle(), 10);
          : "";
                            } else if (node.querySelector && (node.querySelector('.character-header-controls') || node.querySelector('.character-header'))) {
                                setTimeout(() => createWeaponToggle(), 10);
                            }
                        }
                    });
                });
            });


             observer.observe(document.body, { childList: true, subtree: true });
        if (pack) {
          let chosen = "";
          try {
            const obj = JSON.parse(pack);
            chosen = (
              obj[norm] ||
              obj.pt ||
              obj.en ||
              obj.es ||
              obj.pl ||
              ""
            ).trim();
          } catch (e) { }
          if (chosen) {
             let bodyHtml = chosen
              .replace(/'''([^']+)'''/g, "<b>$1</b>")
              .replace(/\n/g, "<br>");
            bodyHtml = "<b>" + bodyHtml + "</b>";
            slot.setAttribute("data-skin-tooltip", titleHtml + bodyHtml);
          }
          return;
         }
         }


         const boot = () => {
         if (title) {
            // Resolve o ícone do character antes de tudo
          const current = slot.getAttribute("data-skin-tooltip") || "";
            resolveCharacterWeaponIcon();
          if (!/skin-tooltip-title/.test(current)) {
 
             let bodyHtml = current;
            // Verificar se existe alguma skill ou subskill com arma
             if (!/^<b>[\s\S]*<\/b>$/.test(bodyHtml)) {
            function checkHasAnyWeapon() {
              bodyHtml = "<b>" + bodyHtml + "</b>";
                // Verifica skills principais
                if (document.querySelectorAll('.skill-icon[data-weapon]').length > 0) {
                    return true;
                }
                // Verifica subskills
                const skillIcons = document.querySelectorAll('.skill-icon[data-subs]');
                for (const el of skillIcons) {
                    try {
                        const subs = JSON.parse(el.getAttribute('data-subs') || '[]');
                        if (Array.isArray(subs) && subs.some(s => s && s.weapon)) {
                            return true;
                        }
                    } catch (e) { }
                }
                return false;
             }
            const hasAnyWeapon = checkHasAnyWeapon();
 
             if (!hasAnyWeapon) {
                // Limpar estado visual para chars sem arma (previne cache entre páginas)
                const topRail = document.querySelector('.top-rail.skills');
                if (topRail) {
                    topRail.classList.remove('weapon-mode-on');
                }
                document.querySelectorAll('.skill-icon.has-weapon-available').forEach(el => {
                    el.classList.remove('has-weapon-available');
                    el.classList.remove('weapon-equipped');
                    el.style.removeProperty('--weapon-badge-url');
                    const ind = el.querySelector('.weapon-indicator');
                    if (ind) ind.remove();
                });
                // Remover toggle se existir
                const toggleContainer = document.querySelector('.weapon-toggle-container');
                if (toggleContainer) toggleContainer.remove();
                // Atualizar estado global para desligado
                if (typeof window.__setGlobalWeaponEnabled === 'function') {
                    window.__setGlobalWeaponEnabled(false);
                }
                return;
             }
             }
 
             slot.setAttribute("data-skin-tooltip", titleHtml + bodyHtml);
            ensureModal();
          }
 
             // Cria o novo toggle
            observeCharacterHeader();
            observeDOMForHeader();
 
            // Remove qualquer toggle antigo que apareça nas barras de skills/subskills
            function removeOldToggles() {
                document.querySelectorAll('.weapon-bar-toggle').forEach(toggle => {
                    toggle.remove();
                });
            }
 
            // Observa mudanças nas barras de ícones para remover toggles antigos
            const iconBarObserver = new MutationObserver(() => {
                removeOldToggles();
            });
 
            // Observa todas as barras de ícones existentes e futuras
            const observeAllIconBars = () => {
                document.querySelectorAll('.icon-bar').forEach(bar => {
                    iconBarObserver.observe(bar, { childList: true, subtree: true });
                });
            };
 
            // Remove toggles antigos imediatamente
            removeOldToggles();
 
            // Observa barras existentes
            observeAllIconBars();
 
            // Observa criação de novas barras
            const bodyObserver = new MutationObserver((mutations) => {
                mutations.forEach((mutation) => {
                    mutation.addedNodes.forEach((node) => {
                        if (node.nodeType === 1) {
                            if (node.classList && node.classList.contains('icon-bar')) {
                                iconBarObserver.observe(node, { childList: true, subtree: true });
                                removeOldToggles();
                            } else if (node.querySelector && node.querySelector('.icon-bar')) {
                                observeAllIconBars();
                                removeOldToggles();
                            }
                        }
                    });
                });
            });
 
            bodyObserver.observe(document.body, { childList: true, subtree: true });
 
            // Escuta mudanças no estado do weapon para atualizar visual
            window.addEventListener('gla:weaponToggled', () => {
                setTimeout(updateToggleVisualState, 50);
            });
 
            // Escuta mudanças de idioma
            window.addEventListener('gla:langChanged', () => {
                updateToggleVisualState();
            });
 
            // Estado inicial do toggle
            let init = false;
            try {
                if (localStorage.getItem('glaWeaponEnabled') === '1') init = true;
            } catch (x) { }
            setTimeout(() => {
                applyWeaponState(init);
                updateToggleVisualState();
            }, 150);
        };
 
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', boot);
        } else {
            boot();
         }
         }
    })();
      });
</script>
<style>
    /* Character-box precisa de position relative para conter o modal */
    .character-box {
        position: relative;
    }
 
    /* Modal posicionado dentro da character-box */
    .weapon-modal {
        position: absolute;
        inset: 0;
        z-index: 100;
        display: flex;
        align-items: center;
        justify-content: center;
        pointer-events: none;
    }
 
    .weapon-modal.show {
        pointer-events: all;
    }
 
    /* Overlay escurece apenas a character-box - aparece PRIMEIRO */
    .weapon-modal-overlay {
        position: absolute;
        inset: 0;
        background: rgba(0, 0, 0, .65);
        -webkit-backdrop-filter: blur(4px);
        backdrop-filter: blur(4px);
        opacity: 0;
        transition: opacity .15s ease;
    }
 
    .weapon-modal.show .weapon-modal-overlay {
        opacity: 1;
    }
 
    /* Conteúdo aparece DEPOIS do overlay */
    .weapon-modal-content {
        position: relative;
        z-index: 1;
        transform: scale(0.96);
        background: linear-gradient(145deg, #2d1a1a, #1e1212);
        border: 1px solid rgba(255, 100, 100, .2);
        border-radius: 14px;
        max-width: 420px;
        width: 90%;
        opacity: 0;
        transition: transform .18s ease .08s, opacity .15s ease .08s;
        overflow: hidden;
    }
 
    .weapon-modal.show .weapon-modal-content {
        transform: scale(1);
        opacity: 1;
    }
 
    .weapon-modal-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 16px 20px;
        border-bottom: 1px solid rgba(255, 100, 100, .12);
        background: linear-gradient(90deg, rgba(255, 80, 80, .06), transparent);
    }
 
    .weapon-modal-header h3 {
        margin: 0;
        font-size: 16px;
        font-weight: 600;
        color: #fff;
    }
 
    .weapon-modal-close {
        background: transparent;
        border: 1px solid rgba(255, 255, 255, .1);
        color: rgba(255, 255, 255, .5);
        font-size: 18px;
        font-family: Arial, sans-serif;
        line-height: 1;
        cursor: pointer;
        padding: 0;
        width: 28px;
        height: 28px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        text-align: center;
        border-radius: 6px;
        transition: background .15s, color .15s, border-color .15s;
    }
 
    .weapon-modal-close:hover {
        background: rgba(255, 80, 80, .15);
        border-color: rgba(255, 80, 80, .3);
        color: #FF7043;
    }
 
    .weapon-modal-body {
        padding: 20px;
        color: rgba(255, 255, 255, .85);
        line-height: 1.65;
        font-size: 14px;
    }
 
    .weapon-modal-body p {
        margin: 0 0 12px;
        display: block !important;
    }
 
    .weapon-modal-body p:last-child,
    .weapon-modal-body p.weapon-info-link {
        margin: 0;
    }
 
    .weapon-modal-body p.weapon-info-link:empty {
        display: none !important;
    }
 
    .weapon-modal-body strong {
        color: #FF7043;
        font-weight: 600;
    }
 
    .weapon-modal-body .weapon-info-link a {
        color: #FF7043;
        text-decoration: none;
        font-weight: 600;
    }
 
    .weapon-modal-body .weapon-info-link a:hover {
        text-decoration: underline;
    }


    .weapon-modal-footer {
      const hovered = root.querySelector(".podium-slot.hovered");
        display: flex;
      const liveTip = document.querySelector(
         align-items: center;
         '.skin-tooltip[aria-hidden="false"], .skin-tooltip.show'
        justify-content: space-between;
      );
        padding: 14px 20px;
      if (hovered && liveTip) {
        border-top: 1px solid rgba(255, 100, 100, .1);
         liveTip.innerHTML = hovered.getAttribute("data-skin-tooltip") || "";
         background: rgba(0, 0, 0, .1);
      }
        gap: 12px;
     };
     }


     .weapon-modal-checkbox {
     // ---------- APPLY ----------
        display: inline-flex;
    const applyLang = (langFull) => {
        align-items: center;
      const myReq = ++__langReqSeq;
        gap: 6px;
      const norm = normalizeLang(langFull);
        font-size: 12px;
      const langTag = (langFull || "pt-br").toLowerCase();
        color: rgba(255, 255, 255, .5);
        cursor: pointer;
        transition: color .15s;
    }
 
    .weapon-modal-checkbox:hover {
        color: rgba(255, 255, 255, .75);
    }
 
    .weapon-modal-checkbox input[type="checkbox"] {
        accent-color: #FF5722;
        margin: 0;
        flex-shrink: 0;
    }
 
    .weapon-modal-checkbox span {
        line-height: 1;
    }


    .weapon-modal-btn {
      markActive(langFull);
        background: #BF360C;
      document.documentElement.lang = langTag;
        border: none;
      try {
        color: #fff;
         localStorage.setItem("glaLang", langTag);
        padding: 10px 24px;
      } catch (e) { }
        border-radius: 6px;
        font-weight: 600;
        font-size: 13px;
        line-height: 1;
         cursor: pointer;
        transition: background .15s;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }


    .weapon-modal-btn:hover {
      updateSkillsTabLabel(norm);
        background: #D84315;
      updateAllSkillDescs(norm);
    }
      updateTierAndTags(norm);
      updateSkinTooltips(norm);
      updateFlagTooltips(norm);


    .weapon-modal-btn:active {
      try {
         background: #A52714;
        window.dispatchEvent(
    }
          new CustomEvent("gla:langChanged", { detail: { norm } })
         );
      } catch (e) { }


    @media (max-width: 600px) {
      document.body.dataset.suppressSkillPlay = "1";
         .weapon-modal-content {
      requestAnimationFrame(() => {
            width: 92%;
         if (myReq !== __langReqSeq) {
            max-width: none;
          delete document.body.dataset.suppressSkillPlay;
          return;
         }
         }
 
         const lastIcon = window.__lastActiveSkillIcon;
         .weapon-modal-header,
         if (lastIcon && typeof lastIcon.click === "function") {
         .weapon-modal-body,
          lastIcon.click();
        .weapon-modal-footer {
            padding: 14px 16px;
         }
         }
        setTimeout(() => {
          if (myReq === __langReqSeq)
            delete document.body.dataset.suppressSkillPlay;
        }, 120);
      });
    };


        .weapon-modal-footer {
    // ---------- BOOT ----------
            flex-direction: column;
    const ensureControlsPosition = () => {
            gap: 12px;
      const controls = document.querySelector(".character-header-controls");
         }
      const header = document.querySelector(".character-header");
      if (controls && header && !header.contains(controls)) {
        header.appendChild(controls);
         return true;
      }
      return false;
    };


         .weapon-modal-btn {
    const boot = () => {
             width: 100%;
      // Tenta mover o character-header-controls para dentro do character-header
      // Se não conseguir, tenta novamente após um delay
      const tryMove = () => {
         const controls = document.querySelector(".character-header-controls");
        const header = document.querySelector(".character-header");
        if (controls && header) {
          if (!header.contains(controls)) {
             header.appendChild(controls);
          }
          return true;
         }
         }
    }
         return false;
 
      };
    /* =========================== NOVO WEAPON TOGGLE =========================== */
    .weapon-toggle-container {
        display: flex;
        align-items: center;
        z-index: 10;
        background: transparent;
        padding: 0;
        border-radius: 0;
         border: none;
        box-shadow: none;
        cursor: pointer;
        transition: transform .08s ease;
        overflow: visible;
        height: 44px;
        box-sizing: border-box;
    }
 
    .weapon-toggle-container:hover {
        transform: translateY(-1px);
    }


    .weapon-toggle-sprite {
      if (!tryMove()) {
         width: 44px;
         let attempts = 0;
        height: 44px;
         const maxAttempts = 20;
        flex-shrink: 0;
         const checkInterval = setInterval(() => {
         border-radius: 50%;
          attempts++;
         overflow: visible;
          if (tryMove() || attempts >= maxAttempts) {
        position: relative;
            clearInterval(checkInterval);
        background: rgb(40, 40, 48);
          }
        border: 2px solid rgba(255, 255, 255, 0.15);
         }, 100);
        display: flex;
      }
        align-items: center;
        justify-content: center;
        z-index: 2;
        margin: 0;
        padding: 0;
        box-sizing: border-box;
        box-shadow: 0 4px 12px rgba(0, 0, 0, .4);
        transition: background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.15s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.15s cubic-bezier(0.4, 0, 0.2, 1);
         will-change: background-color;
    }


    .weapon-toggle-sprite img {
      document.addEventListener("click", (ev) => {
         width: 50px;
         const btn = ev.target.closest(".char-flag[data-lang]");
        height: 50px;
         if (!btn) return;
        display: block;
         ev.preventDefault();
        image-rendering: pixelated;
         applyLang(btn.dataset.lang || "pt-br");
        image-rendering: -moz-crisp-edges;
      });
         image-rendering: -webkit-optimize-contrast;
         image-rendering: crisp-edges;
         -ms-interpolation-mode: nearest-neighbor;
        /* Suporte Edge */
        object-fit: contain;
    }


    .weapon-toggle-bar {
      let start = "pt-br";
         background: rgb(40, 40, 48);
      try {
         padding: 5px 14px 5px 28px;
         const saved = localStorage.getItem("glaLang");
        border-radius: 0 7px 7px 0;
         if (saved) start = saved;
        border: 2px solid rgba(255, 255, 255, 0.15);
      } catch (e) { }
        border-left: none;
      applyLang(start);
        display: flex;
     };
        align-items: center;
        width: 180px;
        position: relative;
        overflow: hidden;
        margin: 0;
        margin-left: -22px;
        height: 34px;
        box-sizing: border-box;
        box-shadow: 0 4px 12px rgba(0, 0, 0, .4);
        transition: background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1), background-image 0.15s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
        will-change: background-color, background-image;
     }


     .weapon-toggle-name {
     if (document.readyState === "loading") {
        color: #fff;
      document.addEventListener("DOMContentLoaded", boot);
        font-size: 14px;
     } else {
        font-weight: 600;
      boot();
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
        position: relative;
        z-index: 2;
        letter-spacing: 0.3px;
        display: inline-block;
    }
 
    /* Textos i18n - usando ::after para mostrar o texto baseado no data-lang e estado */
    .weapon-toggle-name::after {
        content: "Equipar Arma";
        /* Default PT */
     }
 
    .weapon-toggle-name[data-lang="pt"]::after {
        content: "Equipar Arma";
     }
     }
  })();
</script>
<div class="character-header-controls">
  <div id="char-translator" class="char-translator" role="group" aria-label="Language switch">
    <button class="char-flag" data-lang="pt-br" title="Português (Brasil)" aria-label="Português (Brasil)">
      <img src="https://wiki.gla.com.br/images/8/8c/Brazil.png" alt="Português (Brasil)" />
    </button>
    <button class="char-flag" data-lang="en" title="English" aria-label="English">
      <img src="https://wiki.gla.com.br/images/0/0a/Usa.png" alt="English" />
    </button>
    <button class="char-flag" data-lang="es" title="Español" aria-label="Español">
      <img src="https://wiki.gla.com.br/images/5/58/Spain.png" alt="Español" />
    </button>
    <button class="char-flag" data-lang="pl" title="Polski" aria-label="Polski">
      <img src="https://wiki.gla.com.br/images/9/99/Poland.png" alt="Polski" />
    </button>
  </div>
</div>
<style>
  :root {
    --ct-bg: rgba(0, 0, 0, 0.35);
    --ct-bd: rgba(255, 255, 255, 0.15);
    --ct-active: #3b82f6;
    --ct-active-bg: rgba(59, 130, 246, 0.14);
    --ct-active-bd: rgba(59, 130, 246, 0.45);
    --ct-hover-bd: rgba(255, 255, 255, 0.3);
  }


    .weapon-toggle-name[data-lang="en"]::after {
  .character-box .character-header {
        content: "Equip Weapon";
    position: relative;
    }
  }


    .weapon-toggle-name[data-lang="es"]::after {
  /* Container para organizar translator e weapon toggle em blocos separados */
        content: "Equipar Arma";
  .character-header-controls {
     }
    position: absolute;
    top: 8px;
    right: 8px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    z-index: 10;
     align-items: flex-end;
  }


     .weapon-toggle-name[data-lang="pl"]::after {
  .char-translator {
        content: "Wyposaż Broń";
    display: flex;
     }
    gap: 6px;
     background: var(--ct-bg);
    padding: 4px;
    border-radius: 8px;
    border: 1px solid var(--ct-bd);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
     box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
  }


     /* Estado ATIVO (arma equipada) - muda o texto */
  .char-flag {
     .weapon-toggle-container.weapon-active .weapon-toggle-name::after {
    width: 32px;
        content: "Desequipar Arma";
    height: 24px;
        /* Default PT */
     padding: 0;
    }
    border-radius: 6px;
    border: 1px solid rgba(255, 255, 255, 0.18);
     background: rgba(255, 255, 255, 0.06);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    overflow: hidden;
    transition: transform 0.08s ease, border-color 0.15s ease,
      background 0.15s ease, outline-color 0.15s ease;
    outline: 2px solid transparent;
    box-sizing: border-box;
  }


    .weapon-toggle-container.weapon-active .weapon-toggle-name[data-lang="pt"]::after {
  .char-flag:hover {
        content: "Desequipar Arma";
    border-color: var(--ct-hover-bd);
    }
    transform: translateY(-1px);
  }


    .weapon-toggle-container.weapon-active .weapon-toggle-name[data-lang="en"]::after {
  .char-flag:focus-visible {
        content: "Unequip Weapon";
    outline-color: var(--ct-active);
    }
    outline-offset: 2px;
  }


    .weapon-toggle-container.weapon-active .weapon-toggle-name[data-lang="es"]::after {
  .char-flag img {
        content: "Desequipar Arma";
    width: 100%;
    }
    height: 100%;
    object-fit: cover;
    display: block;
    pointer-events: none;
  }


     .weapon-toggle-container.weapon-active .weapon-toggle-name[data-lang="pl"]::after {
  .char-flag.active {
        content: "Zdjęć Broń";
     outline-color: var(--ct-active);
    }
    background: var(--ct-active-bg);
    border-color: var(--ct-active-bd);
  }


    /* Estado ativo - destaque vermelho */
  @media (max-width: 600px) {
     .weapon-toggle-container.weapon-active .weapon-toggle-sprite {
     .character-header-controls {
        background-color: rgb(200, 60, 40) !important;
      top: 6px;
        border: 2px solid rgba(255, 255, 255, 0.15);
      right: 6px;
        box-shadow: 0 4px 12px rgba(0, 0, 0, .4);
      gap: 6px;
     }
     }


     .weapon-toggle-container.weapon-active .weapon-toggle-bar {
     .char-translator {
        background-color: rgb(200, 60, 40);
      gap: 4px;
        background-image: linear-gradient(135deg, rgb(200, 60, 40), rgb(160, 45, 30));
      padding: 3px;
        border-color: rgba(255, 87, 34, 0.3);
        border-left: none;
        border-radius: 0 7px 7px 0;
     }
     }


     .weapon-toggle-container.weapon-active .weapon-toggle-name {
     .char-flag {
        color: #fff;
      width: 28px;
        text-shadow: 0 0 4px rgba(255, 87, 34, 0.5);
      height: 20px;
      padding: 0;
      border-radius: 5px;
     }
     }
  }
</style>
</style>

Edição atual tal como às 14h18min de 22 de janeiro de 2026

<script>

 (() => {
   let __langReqSeq = 0;
   // ---------- helpers ----------
   const normalizeLang = (s) => {
     s = (s || "").toLowerCase();
     if (s === "pt-br" || s === "pt_br" || s === "ptbr") return "pt";
     return s.split("-")[0] || "pt";
   };
   const markActive = (langFull) => {
     const lang = (langFull || "pt-br").toLowerCase();
     document.querySelectorAll(".char-flag[data-lang]").forEach((b) => {
       b.classList.toggle("active", b.dataset.lang === lang);
     });
   };
   const updateSkillsTabLabel = (norm) => {
     const map = {
       en: "Skills",
       pt: "Habilidades",
       es: "Habilidades",
       pl: "Umiejętności",
     };
     const btn =
       document.querySelector('.character-tabs .tab-btn[data-tab="skills"]') ||
       Array.from(document.querySelectorAll(".character-tabs .tab-btn")).find(
         (b) => /skill|habil|umiej/i.test(b.textContent || "")
       );
     if (btn) btn.textContent = map[norm] || map.pt;
   };
   // ---------- skills ----------
   const pickDescFor = (icon, norm) => {
     const keyMap = { pt: "descPt", en: "descEn", es: "descEs", pl: "descPl" };
     const order = [
       keyMap[norm],
       "descPt",
       "descEn",
       "descEs",
       "descPl",
     ].filter(Boolean);
     for (const k of order) {
       const v = (icon.dataset[k] || "").trim();
       if (v) return v;
     }
     return "";
   };
   const updateAllSkillDescs = (norm) => {
     document.querySelectorAll(".icon-bar .skill-icon").forEach((icon) => {
       icon.dataset.desc = pickDescFor(icon, norm);
     });
   };
   // ---------- tier & tags ----------
   const updateTierAndTags = (norm) => {
     const cont = document.querySelector(".class-tags");
     if (!cont) return;
     const tier = cont.querySelector(".class-tag.tier");
     if (tier) {
       const t =
         tier.getAttribute("data-tier-" + norm) ||
         tier.getAttribute("data-tier-pt") ||
         tier.getAttribute("data-tier-en") ||
         tier.getAttribute("data-tier-es") ||
         tier.getAttribute("data-tier-pl") ||
         "";
       if (t) tier.textContent = t;
     }
     let tags = [];
     const pack = cont.getAttribute("data-tags-i18n");
     if (pack) {
       try {
         const obj = JSON.parse(pack);
         const arr =
           obj?.[norm] || obj?.pt || obj?.en || obj?.es || obj?.pl || [];
         if (Array.isArray(arr)) tags = arr;
       } catch (e) { }
     }
     if (!tags.length) {
       const raw =
         cont.getAttribute("data-tags-" + norm) ||
         cont.getAttribute("data-tags-pt") ||
         cont.getAttribute("data-tags-en") ||
         cont.getAttribute("data-tags-es") ||
         cont.getAttribute("data-tags-pl") ||
         "";
       if (raw) {
         try {
           const maybe = JSON.parse(raw);
           if (Array.isArray(maybe)) tags = maybe;
         } catch (e) { }
         if (!tags.length && typeof raw === "string") {
           tags = raw
             .split(",")
             .map((s) => s.trim())
             .filter(Boolean);
         }
       }
     }
     if (!tags.length) return;
     // Tags invisíveis (não devem ser exibidas na wiki)
     const HIDDEN_TAGS = {
       mulher: true,
       woman: true,
       mujer: true,
       kobieta: true,
     };
     cont
       .querySelectorAll(".class-tag:not(.tier)")
       .forEach((el) => el.remove());
     tags.forEach((t) => {
       // Filtra tags invisíveis
       const normalized = (t || "").toLowerCase().trim();
       if (HIDDEN_TAGS[normalized]) return;
       const chip = document.createElement("span");
       chip.className = "class-tag";
       chip.textContent = t;
       cont.appendChild(chip);
     });
   };
   // ---------- FLAGS: tooltips i18n ----------
   const updateFlagTooltips = (norm) => {
     const skillsRoot = document.querySelector("#skills");
     if (!skillsRoot) return;
     let pack = {};
     try {
       pack = JSON.parse(skillsRoot.dataset.i18nFlags || "{}");
     } catch (e) { }
     const dict = pack[norm] || pack.pt || {};
     const tooltip = window.__globalSkillTooltip;
     if (!tooltip) return;
     document
       .querySelectorAll(".skill-flags .skill-flag[data-flag]")
       .forEach((el) => {
         delete el.dataset.flagTipWired;
       });
     const descBoxes = document.querySelectorAll(".desc-box");
     descBoxes.forEach((box) => {
       if (box.querySelector(".skill-flags")) {
         const flags = box.querySelectorAll(
           ".skill-flags .skill-flag[data-flag]"
         );
         flags.forEach((el) => {
           const key = el.getAttribute("data-flag");
           const tip = (dict && dict[key]) || "";
           if (!tip) return;
           delete el.dataset.flagTipWired;
           el.setAttribute("aria-label", tip);
           if (el.hasAttribute("title")) el.removeAttribute("title");
           el.addEventListener("mouseenter", () => {
             const tipEl = document.querySelector(".skill-tooltip");
             if (tipEl) tipEl.classList.add("flag-tooltip");
             tooltip.show(el, tip);
           });
           el.addEventListener("mousemove", () => {
             if (performance.now() >= tooltip.lockUntil.value) {
               tooltip.measureAndPos(el);
             }
           });
           el.addEventListener("click", () => {
             tooltip.lockUntil.value = performance.now() + 240;
             tooltip.measureAndPos(el);
           });
           el.addEventListener("mouseleave", () => {
             const tipEl = document.querySelector(".skill-tooltip");
             if (tipEl) tipEl.classList.remove("flag-tooltip");
             tooltip.hide();
           });
           el.dataset.flagTipWired = "1";
         });
       }
     });
   };
   // ---------- SKINS: tooltips i18n ----------
   const updateSkinTooltips = (norm) => {
     const root = document.querySelector("#skins");
     if (!root) return;
     const slots = root.querySelectorAll(".podium-slot");
     if (!slots.length) return;
     slots.forEach((slot) => {
       const title = slot.getAttribute("data-skin-title") || "";
       const pack = slot.getAttribute("data-skin-tooltip-i18n");
       const titleHtml = title

 ? '

' +
         title +
"

"

         : "";
       if (pack) {
         let chosen = "";
         try {
           const obj = JSON.parse(pack);
           chosen = (
             obj[norm] ||
             obj.pt ||
             obj.en ||
             obj.es ||
             obj.pl ||
             ""
           ).trim();
         } catch (e) { }
         if (chosen) {
           let bodyHtml = chosen
             .replace(/([^']+)/g, "$1")
             .replace(/\n/g, "
"); bodyHtml = "" + bodyHtml + ""; slot.setAttribute("data-skin-tooltip", titleHtml + bodyHtml); } return; }
       if (title) {
         const current = slot.getAttribute("data-skin-tooltip") || "";
         if (!/skin-tooltip-title/.test(current)) {
           let bodyHtml = current;
           if (!/^[\s\S]*<\/b>$/.test(bodyHtml)) {
             bodyHtml = "" + bodyHtml + "";
           }
           slot.setAttribute("data-skin-tooltip", titleHtml + bodyHtml);
         }
       }
     });
     const hovered = root.querySelector(".podium-slot.hovered");
     const liveTip = document.querySelector(
       '.skin-tooltip[aria-hidden="false"], .skin-tooltip.show'
     );
     if (hovered && liveTip) {
       liveTip.innerHTML = hovered.getAttribute("data-skin-tooltip") || "";
     }
   };
   // ---------- APPLY ----------
   const applyLang = (langFull) => {
     const myReq = ++__langReqSeq;
     const norm = normalizeLang(langFull);
     const langTag = (langFull || "pt-br").toLowerCase();
     markActive(langFull);
     document.documentElement.lang = langTag;
     try {
       localStorage.setItem("glaLang", langTag);
     } catch (e) { }
     updateSkillsTabLabel(norm);
     updateAllSkillDescs(norm);
     updateTierAndTags(norm);
     updateSkinTooltips(norm);
     updateFlagTooltips(norm);
     try {
       window.dispatchEvent(
         new CustomEvent("gla:langChanged", { detail: { norm } })
       );
     } catch (e) { }
     document.body.dataset.suppressSkillPlay = "1";
     requestAnimationFrame(() => {
       if (myReq !== __langReqSeq) {
         delete document.body.dataset.suppressSkillPlay;
         return;
       }
       const lastIcon = window.__lastActiveSkillIcon;
       if (lastIcon && typeof lastIcon.click === "function") {
         lastIcon.click();
       }
       setTimeout(() => {
         if (myReq === __langReqSeq)
           delete document.body.dataset.suppressSkillPlay;
       }, 120);
     });
   };
   // ---------- BOOT ----------
   const ensureControlsPosition = () => {
     const controls = document.querySelector(".character-header-controls");
     const header = document.querySelector(".character-header");
     if (controls && header && !header.contains(controls)) {
       header.appendChild(controls);
       return true;
     }
     return false;
   };
   const boot = () => {
     // Tenta mover o character-header-controls para dentro do character-header
     // Se não conseguir, tenta novamente após um delay
     const tryMove = () => {
       const controls = document.querySelector(".character-header-controls");
       const header = document.querySelector(".character-header");
       if (controls && header) {
         if (!header.contains(controls)) {
           header.appendChild(controls);
         }
         return true;
       }
       return false;
     };
     if (!tryMove()) {
       let attempts = 0;
       const maxAttempts = 20;
       const checkInterval = setInterval(() => {
         attempts++;
         if (tryMove() || attempts >= maxAttempts) {
           clearInterval(checkInterval);
         }
       }, 100);
     }
     document.addEventListener("click", (ev) => {
       const btn = ev.target.closest(".char-flag[data-lang]");
       if (!btn) return;
       ev.preventDefault();
       applyLang(btn.dataset.lang || "pt-br");
     });
     let start = "pt-br";
     try {
       const saved = localStorage.getItem("glaLang");
       if (saved) start = saved;
     } catch (e) { }
     applyLang(start);
   };
   if (document.readyState === "loading") {
     document.addEventListener("DOMContentLoaded", boot);
   } else {
     boot();
   }
 })();

</script>

   <button class="char-flag" data-lang="pt-br" title="Português (Brasil)" aria-label="Português (Brasil)">
     <img src="https://wiki.gla.com.br/images/8/8c/Brazil.png" alt="Português (Brasil)" />
   </button>
   <button class="char-flag" data-lang="en" title="English" aria-label="English">
     <img src="https://wiki.gla.com.br/images/0/0a/Usa.png" alt="English" />
   </button>
   <button class="char-flag" data-lang="es" title="Español" aria-label="Español">
     <img src="https://wiki.gla.com.br/images/5/58/Spain.png" alt="Español" />
   </button>
   <button class="char-flag" data-lang="pl" title="Polski" aria-label="Polski">
     <img src="https://wiki.gla.com.br/images/9/99/Poland.png" alt="Polski" />
   </button>

<style>

 :root {
   --ct-bg: rgba(0, 0, 0, 0.35);
   --ct-bd: rgba(255, 255, 255, 0.15);
   --ct-active: #3b82f6;
   --ct-active-bg: rgba(59, 130, 246, 0.14);
   --ct-active-bd: rgba(59, 130, 246, 0.45);
   --ct-hover-bd: rgba(255, 255, 255, 0.3);
 }
 .character-box .character-header {
   position: relative;
 }
 /* Container para organizar translator e weapon toggle em blocos separados */
 .character-header-controls {
   position: absolute;
   top: 8px;
   right: 8px;
   display: flex;
   flex-direction: column;
   gap: 8px;
   z-index: 10;
   align-items: flex-end;
 }
 .char-translator {
   display: flex;
   gap: 6px;
   background: var(--ct-bg);
   padding: 4px;
   border-radius: 8px;
   border: 1px solid var(--ct-bd);
   -webkit-backdrop-filter: blur(2px);
   backdrop-filter: blur(2px);
   box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
 }
 .char-flag {
   width: 32px;
   height: 24px;
   padding: 0;
   border-radius: 6px;
   border: 1px solid rgba(255, 255, 255, 0.18);
   background: rgba(255, 255, 255, 0.06);
   display: flex;
   align-items: center;
   justify-content: center;
   cursor: pointer;
   overflow: hidden;
   transition: transform 0.08s ease, border-color 0.15s ease,
     background 0.15s ease, outline-color 0.15s ease;
   outline: 2px solid transparent;
   box-sizing: border-box;
 }
 .char-flag:hover {
   border-color: var(--ct-hover-bd);
   transform: translateY(-1px);
 }
 .char-flag:focus-visible {
   outline-color: var(--ct-active);
   outline-offset: 2px;
 }
 .char-flag img {
   width: 100%;
   height: 100%;
   object-fit: cover;
   display: block;
   pointer-events: none;
 }
 .char-flag.active {
   outline-color: var(--ct-active);
   background: var(--ct-active-bg);
   border-color: var(--ct-active-bd);
 }
 @media (max-width: 600px) {
   .character-header-controls {
     top: 6px;
     right: 6px;
     gap: 6px;
   }
   .char-translator {
     gap: 4px;
     padding: 3px;
   }
   .char-flag {
     width: 28px;
     height: 20px;
     padding: 0;
     border-radius: 5px;
   }
 }

</style>