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

De Wiki Gla
Ir para navegação Ir para pesquisar
(Criou página com '<!-- TRANSLATOR SYSTEM --> <script> (() => { 'use strict'; const normalizeLang = (s) => { s = (s || '').toLowerCase(); if (s === 'p...')
 
m
 
(2 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 1: Linha 1:
<!-- TRANSLATOR SYSTEM -->
<!-- CHARACTER TRANSLATOR SYSTEM -->
<script>
<script>
     (() => {
     (() => {
         'use strict';
         let __langReqSeq = 0;
 
        // ---------- helpers ----------
         const normalizeLang = (s) => {
         const normalizeLang = (s) => {
             s = (s || '').toLowerCase();
             s = (s || '').toLowerCase();
             if (s === 'pt-br' || s === 'pt_br' || s === 'ptbr') return 'pt';
             if (s === 'pt-br' || s === 'pt_br' || s === 'ptbr') return 'pt';
             return (s.split('-')[0] || '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 updateSkillsTabLabel = (norm) => {
             const map = { en: 'Skills', pt: 'Habilidades', es: 'Habilidades', pl: 'Umiejętności' };
             const map = { en: 'Skills', pt: 'Habilidades', es: 'Habilidades', pl: 'Umiejętności' };
             const btn = document.querySelector('.character-tabs .tab-btn[data-tab="skills"]');
             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;
             if (btn) btn.textContent = map[norm] || map.pt;
         };
         };


        // ---------- skills ----------
         const pickDescFor = (icon, norm) => {
         const pickDescFor = (icon, norm) => {
             const keyMap = { pt: 'descPt', en: 'descEn', es: 'descEs', pl: 'descPl' };
             const keyMap = { pt: 'descPt', en: 'descEn', es: 'descEs', pl: 'descPl' };
Linha 31: Linha 42:
         };
         };


        // ---------- tier & tags ----------
         const updateTierAndTags = (norm) => {
         const updateTierAndTags = (norm) => {
             const cont = document.querySelector('.class-tags');
             const cont = document.querySelector('.class-tags');
Linha 53: Linha 65:
                     if (Array.isArray(arr)) tags = arr;
                     if (Array.isArray(arr)) tags = arr;
                 } catch (e) { }
                 } 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);
                    }
                }
             }
             }


Linha 66: Linha 96:
         };
         };


        // ---------- FLAGS: tooltips i18n ----------
         const updateFlagTooltips = (norm) => {
         const updateFlagTooltips = (norm) => {
             const skillsRoot = document.querySelector('#skills');
             const skillsRoot = document.querySelector('#skills');
             if (!skillsRoot) return;
             if (!skillsRoot) return;
             let pack = {};
             let pack = {};
             try {
             try { pack = JSON.parse(skillsRoot.dataset.i18nFlags || '{}'); } catch (e) { }
                pack = JSON.parse(skillsRoot.dataset.i18nFlags || '{}');
            } catch (e) { }
             const dict = pack[norm] || pack.pt || {};
             const dict = pack[norm] || pack.pt || {};
            const tooltip = window.__globalSkillTooltip;
            if (!tooltip) return;
             document.querySelectorAll('.skill-flags .skill-flag[data-flag]').forEach(el => {
             document.querySelectorAll('.skill-flags .skill-flag[data-flag]').forEach(el => {
                 const key = el.getAttribute('data-flag');
                 delete el.dataset.flagTipWired;
                const tip = (dict && dict[key]) || '';
            });
                if (tip) el.setAttribute('aria-label', tip);
 
            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 ? ('<div class="skin-tooltip-title" style="margin:0">' + title + '</div>') : '';
 
                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;
                }
 
                if (title) {
                    const current = slot.getAttribute('data-skin-tooltip') || '';
                    if (!/skin-tooltip-title/.test(current)) {
                        let bodyHtml = current;
                        if (!/^<b>[\s\S]*<\/b>$/.test(bodyHtml)) {
                            bodyHtml = '<b>' + bodyHtml + '</b>';
                        }
                        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') || '';
            }
         };
         };


         const updateAll = (langFull) => {
        // ---------- APPLY ----------
         const applyLang = (langFull) => {
            const myReq = ++__langReqSeq;
             const norm = normalizeLang(langFull);
             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);
             updateSkillsTabLabel(norm);
             updateAllSkillDescs(norm);
             updateAllSkillDescs(norm);
             updateTierAndTags(norm);
             updateTierAndTags(norm);
            updateSkinTooltips(norm);
             updateFlagTooltips(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;
         };
         };


         // Listen to language changes
         const boot = () => {
        document.querySelectorAll('.char-flag[data-lang]').forEach(btn => {
            // Tenta mover o character-header-controls para dentro do character-header
             btn.addEventListener('click', () => {
            // Se não conseguir, tenta novamente após um delay
                 const lang = btn.getAttribute('data-lang');
            const tryMove = () => {
                 updateAll(lang);
                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');
             });
             });
        });


         // Initial update
            let start = 'pt-br';
         const currentLang = document.documentElement.lang || 'pt-br';
            try {
         updateAll(currentLang);
                const saved = localStorage.getItem('glaLang');
                if (saved) start = saved;
            } catch (e) { }
            applyLang(start);
         };
 
         if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', boot);
         } else {
            boot();
        }
     })();
     })();
</script>
</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, .35);
        --ct-bd: rgba(255, 255, 255, .15);
        --ct-active: #3b82f6;
        --ct-active-bg: rgba(59, 130, 246, .14);
        --ct-active-bd: rgba(59, 130, 246, .45);
        --ct-hover-bd: rgba(255, 255, 255, .30);
    }
    .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, .25);
    }
    .char-flag {
        width: 32px;
        height: 24px;
        padding: 0;
        border-radius: 6px;
        border: 1px solid rgba(255, 255, 255, .18);
        background: rgba(255, 255, 255, .06);
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        overflow: hidden;
        transition: transform .08s ease, border-color .15s ease, background .15s ease, outline-color .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>

Edição atual tal como às 00h44min de 8 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;
           cont.querySelectorAll('.class-tag:not(.tier)').forEach(el => el.remove());
           tags.forEach(t => {
               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, .35);
       --ct-bd: rgba(255, 255, 255, .15);
       --ct-active: #3b82f6;
       --ct-active-bg: rgba(59, 130, 246, .14);
       --ct-active-bd: rgba(59, 130, 246, .45);
       --ct-hover-bd: rgba(255, 255, 255, .30);
   }
   .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, .25);
   }
   .char-flag {
       width: 32px;
       height: 24px;
       padding: 0;
       border-radius: 6px;
       border: 1px solid rgba(255, 255, 255, .18);
       background: rgba(255, 255, 255, .06);
       display: flex;
       align-items: center;
       justify-content: center;
       cursor: pointer;
       overflow: hidden;
       transition: transform .08s ease, border-color .15s ease, background .15s ease, outline-color .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>