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

De Wiki Gla
Ir para navegação Ir para pesquisar
(Criou página com '<!-- SKINS SYSTEM --> <script> (function initSkinsPodiumUI() { 'use strict'; const podium = document.querySelector('.skins-podium'); if (!podium ||...')
 
m
 
(9 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 1: Linha 1:
<!-- SKINS SYSTEM -->
<!-- SKINS SYSTEM - Layout Isométrico -->
<script>
<script>
     (function initSkinsPodiumUI() {
     (function initSkinsPodiumUI() {
        'use strict';
         const podium = document.querySelector('.skins-podium');
         const podium = document.querySelector('.skins-podium');
         if (!podium || podium.dataset.wired === '1') return;
         if (!podium || podium.dataset.wired === '1') return;
         podium.dataset.wired = '1';
         podium.dataset.wired = '1';


        // ---------- Função para aplicar offset_x individualmente em cada skin ----------
        // IMPORTANTE: Usa margin-left em vez de transform para afetar o layout do flexbox
         function applyOffsetX() {
         function applyOffsetX() {
             const allSlots = podium.querySelectorAll('.podium-slot');
             const allSlots = podium.querySelectorAll('.podium-slot');
             allSlots.forEach((slot) => {
             allSlots.forEach((slot, index) => {
                // Lê o atributo data-offset-x diretamente do elemento
                 const offsetXAttr = slot.getAttribute('data-offset-x');
                 const offsetXAttr = slot.getAttribute('data-offset-x');
                 if (offsetXAttr !== null && offsetXAttr !== '' && offsetXAttr !== 'undefined') {
                 if (offsetXAttr !== null && offsetXAttr !== '' && offsetXAttr !== 'undefined') {
                     const numOffset = parseFloat(offsetXAttr);
                     const numOffset = parseFloat(offsetXAttr);
                     if (!isNaN(numOffset) && numOffset !== 0) {
                     if (!isNaN(numOffset) && numOffset !== 0) {
                        // Usa margin-left negativo para afetar o layout do flexbox
                        // Isso faz com que o elemento realmente se aproxime dos outros
                         const currentStyle = slot.getAttribute('style') || '';
                         const currentStyle = slot.getAttribute('style') || '';
                        // Remove qualquer margin-left anterior e transform (legado)
                         const cleanedStyle = currentStyle
                         const cleanedStyle = currentStyle
                             .replace(/margin-left\s*:[^;]+;?/gi, '')
                             .replace(/margin-left\s*:[^;]+;?/gi, '')
                             .replace(/transform\s*:[^;]+;?/gi, '')
                             .replace(/transform\s*:[^;]+;?/gi, '')
                             .trim();
                             .trim();
                        // Aplica o margin-left preservando outros estilos (como z-index)
                         const newMargin = `margin-left: ${numOffset}px`;
                         const newMargin = `margin-left: ${numOffset}px`;
                         if (cleanedStyle && cleanedStyle.length > 0) {
                         if (cleanedStyle && cleanedStyle.length > 0) {
Linha 24: Linha 31:
                         } else {
                         } else {
                             slot.setAttribute('style', newMargin + ';');
                             slot.setAttribute('style', newMargin + ';');
                        }
                        // Força a atualização do layout
                        slot.offsetHeight;
                    } else {
                        // Se o offset for 0 ou inválido, remove margin-left e transform
                        const currentStyle = slot.getAttribute('style') || '';
                        const cleanedStyle = currentStyle
                            .replace(/margin-left\s*:[^;]+;?/gi, '')
                            .replace(/transform\s*:[^;]+;?/gi, '')
                            .trim();
                        if (cleanedStyle) {
                            slot.setAttribute('style', cleanedStyle + (cleanedStyle.endsWith(';') ? '' : ';'));
                        } else {
                            slot.removeAttribute('style');
                         }
                         }
                    }
                } else {
                    // Se não tem offset_x, remove margin-left e transform (preserva outros estilos)
                    const currentStyle = slot.getAttribute('style') || '';
                    const cleanedStyle = currentStyle
                        .replace(/margin-left\s*:[^;]+;?/gi, '')
                        .replace(/transform\s*:[^;]+;?/gi, '')
                        .trim();
                    if (cleanedStyle) {
                        slot.setAttribute('style', cleanedStyle + (cleanedStyle.endsWith(';') ? '' : ';'));
                    } else {
                        slot.removeAttribute('style');
                     }
                     }
                 }
                 }
Linha 30: Linha 63:
         }
         }


        // Flag para evitar múltiplas execuções simultâneas
        let isApplying = false;
        function applyOffsetXOnce() {
            if (isApplying) return;
            isApplying = true;
            applyOffsetX();
            requestAnimationFrame(() => {
                isApplying = false;
            });
        }
        // Aplica usando requestAnimationFrame para garantir que o DOM esteja renderizado
         requestAnimationFrame(() => {
         requestAnimationFrame(() => {
             applyOffsetX();
             applyOffsetXOnce();
             setTimeout(applyOffsetX, 50);
            // Reaplica após pequenos delays para garantir
             setTimeout(applyOffsetX, 200);
             setTimeout(applyOffsetXOnce, 50);
             setTimeout(applyOffsetXOnce, 200);
         });
         });


        // Também aplica quando o DOM estiver pronto
         if (document.readyState === 'loading') {
         if (document.readyState === 'loading') {
             document.addEventListener('DOMContentLoaded', () => {
             document.addEventListener('DOMContentLoaded', () => {
                 requestAnimationFrame(applyOffsetX);
                 requestAnimationFrame(applyOffsetXOnce);
             });
             });
         }
         }


         // YouTube integration
         // Observa mudanças no DOM para reaplicar se necessário (apenas para novos elementos)
         podium.querySelectorAll('.podium-slot[data-youtube]').forEach(slot => {
         if (window.MutationObserver) {
             if (slot.dataset.youtubeWired === '1') return;
            const observer = new MutationObserver((mutations) => {
             slot.dataset.youtubeWired = '1';
                // Só reaplica se houver mudanças relevantes
             const youtube = slot.getAttribute('data-youtube');
                const hasRelevantChanges = mutations.some(m =>
             if (!youtube) return;
                    m.type === 'childList' ||
                    (m.type === 'attributes' && (m.attributeName === 'data-offset-x' || m.attributeName === 'style'))
                );
                if (hasRelevantChanges) {
                    clearTimeout(observer.timeout);
                    observer.timeout = setTimeout(applyOffsetXOnce, 50);
                }
            });
            observer.observe(podium, {
                childList: true,
                subtree: false, // Apenas observa filhos diretos
                attributes: true,
                attributeFilter: ['data-offset-x']
            });
        }
 
        // ---------- Tooltip único ----------
        function ensureTip() {
            let tip = document.querySelector('.skin-tooltip');
            if (!tip) {
                tip = document.createElement('div');
                tip.className = 'skin-tooltip';
                tip.setAttribute('role', 'tooltip');
                tip.setAttribute('aria-hidden', 'true');
                tip.style.position = 'fixed';
                tip.style.transform = 'translate(-9999px,-9999px)';
                tip.style.opacity = '0';
                tip.style.transition = 'opacity .15s ease';
                document.body.appendChild(tip);
            }
            return tip;
        }
 
        const tip = ensureTip();
        let hoveredSlot = null;
 
        function place(card) {
             if (!card || tip.getAttribute('aria-hidden') === 'true') return;
 
            // Calcula nova posição - tooltip centralizada em relação à imagem do piso
            tip.style.transform = 'translate(-9999px,-9999px)';
            const tr = tip.getBoundingClientRect();
 
            // Pega a posição da imagem do tile (piso) para centralizar
            const platformImg = card.querySelector('.podium-platform-top img');
             let platformRect = card.getBoundingClientRect(); // Fallback para o card se não encontrar
            if (platformImg) {
                platformRect = platformImg.getBoundingClientRect();
            } else {
                // Se não encontrar a img, tenta o container do tile
                const platform = card.querySelector('.podium-platform');
                if (platform) {
                    platformRect = platform.getBoundingClientRect();
                }
            }
 
            // Centraliza horizontalmente baseado na imagem do tile
            let leftPos = Math.round(platformRect.left + (platformRect.width - tr.width) / 2);
            leftPos = Math.max(8, Math.min(leftPos, window.innerWidth - tr.width - 8));
 
            // Posiciona logo abaixo da imagem do tile, com pequeno espaçamento
            let top = Math.round(platformRect.bottom + 15);
 
            // Se não couber embaixo, coloca em cima
            if (top + tr.height > window.innerHeight - 8) {
                top = Math.round(platformRect.top - tr.height - 15);
                if (top < 8) top = 8; // Fallback se não couber em cima também
            }
 
            tip.style.transform = `translate(${leftPos}px, ${top}px)`;
        }
 
        function show(card) {
             const tooltipText = card.getAttribute('data-skin-tooltip') || '';
             tip.innerHTML = tooltipText;
            tip.setAttribute('aria-hidden', 'false');
            place(card);
            tip.style.opacity = '1';
        }
 
        function hide() {
            tip.setAttribute('aria-hidden', 'true');
            tip.style.opacity = '0';
            tip.style.transform = 'translate(-9999px,-9999px)';
        }


             slot.addEventListener('click', () => {
        // Função para restaurar z-index original baseado na posição do slot
                window.open(youtube, '_blank', 'noopener,noreferrer');
        function restoreOriginalZIndex(slot) {
            if (!slot) return;
 
            // Determina a posição do slot (1, 2, 3, 4, etc)
            const allSlots = Array.from(podium.querySelectorAll('.podium-slot'));
            const slotIndex = allSlots.indexOf(slot);
 
            // Z-index: esquerda (0) = menor, direita (último) = maior (direita passa na frente)
            const originalZIndex = slotIndex + 1;
            const originalSpriteZIndex = (slotIndex + 1) * 10;
 
            slot.style.zIndex = originalZIndex.toString();
            const spriteContainer = slot.querySelector('.podium-sprite-container');
            if (spriteContainer) spriteContainer.style.zIndex = originalSpriteZIndex.toString();
 
            // CRÍTICO: Garante que TODOS os tiles sempre fiquem atrás de TODAS as sprites
            // Força z-index negativo nos tiles de todos os slots
            const platform = slot.querySelector('.podium-platform');
            const platformTop = slot.querySelector('.podium-platform-top');
            const platformImg = slot.querySelector('.podium-platform-top img');
            if (platform) platform.style.zIndex = '-1';
            if (platformTop) platformTop.style.zIndex = '-2';
            if (platformImg) platformImg.style.zIndex = '-2';
        }
 
        function setHovered(card) {
            if (hoveredSlot === card) {
                // Se já está hovered, não reposiciona - mantém posição fixa
                return;
            }
 
            // Remove hover anterior e restaura z-index original
            if (hoveredSlot) {
                hoveredSlot.classList.remove('hovered');
                restoreOriginalZIndex(hoveredSlot);
                // Garante que tiles continuem atrás após restaurar z-index
                forceTilesBehind();
            }
 
            podium.classList.remove('hovering');
            podium.querySelectorAll('.podium-slot.dim').forEach(n => n.classList.remove('dim'));
 
             if (!card) {
                hoveredSlot = null;
                hide();
                return;
            }
 
            hoveredSlot = card;
            hoveredSlot.classList.add('hovered');
            podium.classList.add('hovering');
            podium.querySelectorAll('.podium-slot').forEach(n => { if (n !== hoveredSlot) n.classList.add('dim'); });
 
            // Qualquer skin com hover fica acima de tudo
            card.style.zIndex = '9999';
            const spriteContainer = card.querySelector('.podium-sprite-container');
            if (spriteContainer) spriteContainer.style.zIndex = '9999';
 
            // CRÍTICO: Garante que tiles continuem atrás mesmo durante hover
            forceTilesBehind();
 
            show(card);
        }
 
        // Função para verificar se o pixel na posição do mouse é transparente
        function isPixelTransparent(img, x, y) {
            if (!img.complete || img.naturalWidth === 0) return true;
 
            try {
                const canvas = document.createElement('canvas');
                canvas.width = img.naturalWidth;
                canvas.height = img.naturalHeight;
                const ctx = canvas.getContext('2d');
                ctx.drawImage(img, 0, 0);
 
                // Calcula a posição relativa na imagem
                const rect = img.getBoundingClientRect();
                const scaleX = img.naturalWidth / rect.width;
                const scaleY = img.naturalHeight / rect.height;
                const imgX = Math.floor((x - rect.left) * scaleX);
                const imgY = Math.floor((y - rect.top) * scaleY);
 
                // Verifica se está dentro dos limites
                if (imgX < 0 || imgX >= img.naturalWidth || imgY < 0 || imgY >= img.naturalHeight) {
                    return true;
                }
 
                // Obtém o pixel
                const pixelData = ctx.getImageData(imgX, imgY, 1, 1).data;
                const alpha = pixelData[3]; // Canal alpha
 
                return alpha < 10; // Considera transparente se alpha < 10
            } catch (e) {
                return false; // Em caso de erro, permite o hover
            }
        }
 
        // ---------- Clique YouTube (sem duplicar) ----------
        podium.addEventListener('click', (ev) => {
            const slot = ev.target?.closest('.podium-slot[data-youtube]');
            if (!slot) return;
            const url = (slot.dataset.youtube || '').trim();
            if (!url) return;
            if (slot.dataset._opening === '1') return;
            slot.dataset._opening = '1';
            ev.preventDefault();
            ev.stopPropagation();
            ev.stopImmediatePropagation();
            try { window.open(url, '_blank', 'noopener,noreferrer'); }
            catch (e) { location.href = url; }
            setTimeout(() => { delete slot.dataset._opening; }, 500);
        }, { capture: true });
 
        podium.addEventListener('keydown', (ev) => {
            if (ev.key !== 'Enter' && ev.key !== ' ') return;
            const slot = ev.target?.closest('.podium-slot[data-youtube]');
            if (!slot) return;
            const url = (slot.dataset.youtube || '').trim();
            if (!url) return;
            if (slot.dataset._opening === '1') return;
            slot.dataset._opening = '1';
            ev.preventDefault();
            ev.stopPropagation();
            ev.stopImmediatePropagation();
            try { window.open(url, '_blank', 'noopener,noreferrer'); }
            catch (e) { location.href = url; }
            setTimeout(() => { delete slot.dataset._opening; }, 500);
        }, { capture: true });
 
        // ---------- Hitbox pixel-perfect por sprite ----------
        // CRÍTICO: Move tiles para fora do sprite-container para separar contexto de empilhamento
        function moveTilesOutOfSpriteContainer() {
            const allSlots = Array.from(podium.querySelectorAll('.podium-slot'));
            allSlots.forEach(slot => {
                const spriteContainer = slot.querySelector('.podium-sprite-container');
                const platform = slot.querySelector('.podium-platform');
 
                // Se o tile ainda está dentro do sprite-container, move para o slot
                if (platform && spriteContainer && spriteContainer.contains(platform)) {
                    // Salva os estilos inline atuais antes de mover
                    const currentRight = platform.style.right || '';
                    const currentBottom = platform.style.bottom || '';
                    const computedRight = getComputedStyle(platform).right;
                    const computedBottom = getComputedStyle(platform).bottom;
 
                    // Move o tile para fora do sprite-container, mas mantém dentro do slot
                    slot.appendChild(platform);
 
                    // Restaura a posição (os valores já estão corretos, apenas precisa manter)
                    platform.style.position = 'absolute';
                    if (currentRight) {
                        platform.style.right = currentRight;
                    } else if (computedRight && computedRight !== 'auto') {
                        platform.style.right = computedRight;
                    } else {
                        // Usa o valor padrão do CSS
                        platform.style.right = '-25px';
                    }
 
                    if (currentBottom) {
                        platform.style.bottom = currentBottom;
                    } else if (computedBottom && computedBottom !== 'auto') {
                        platform.style.bottom = computedBottom;
                    } else {
                        // Usa o valor padrão do CSS
                        platform.style.bottom = '-15px';
                    }
                }
             });
             });
        }


             slot.addEventListener('keydown', (e) => {
        // CRÍTICO: Força todos os tiles a terem z-index negativo na inicialização
                 if (e.key === 'Enter' || e.key === ' ') {
        function forceTilesBehind() {
                     e.preventDefault();
             const allSlots = Array.from(podium.querySelectorAll('.podium-slot'));
                     window.open(youtube, '_blank', 'noopener,noreferrer');
            allSlots.forEach(slot => {
                 const platform = slot.querySelector('.podium-platform');
                const platformTop = slot.querySelector('.podium-platform-top');
                const platformImg = slot.querySelector('.podium-platform-top img');
 
                if (platform) {
                    platform.style.zIndex = '0';
                    platform.style.setProperty('z-index', '0', 'important');
                }
                if (platformTop) {
                     platformTop.style.zIndex = '0';
                    platformTop.style.setProperty('z-index', '0', 'important');
                }
                if (platformImg) {
                    platformImg.style.zIndex = '0';
                     platformImg.style.setProperty('z-index', '0', 'important');
                 }
                 }
             });
             });
        }
        // Move tiles para fora do sprite-container primeiro
        moveTilesOutOfSpriteContainer();
        setTimeout(moveTilesOutOfSpriteContainer, 10);
        setTimeout(moveTilesOutOfSpriteContainer, 100);
        // Depois força z-index negativo
        forceTilesBehind();
        setTimeout(forceTilesBehind, 10);
        setTimeout(forceTilesBehind, 100);
        const slots = Array.from(podium.querySelectorAll('.podium-slot'));
        slots.forEach(slot => {
            const spriteImg = slot.querySelector('.podium-sprite img');
            // Hitbox apenas na imagem do sprite, verificando transparência
            if (spriteImg) {
                spriteImg.addEventListener('pointermove', (ev) => {
                    if (!slot.hasAttribute('data-skin-tooltip')) return;
                    // Verifica se o pixel é transparente
                    if (isPixelTransparent(spriteImg, ev.clientX, ev.clientY)) {
                        // Se for transparente e estiver hovered, remove o hover
                        if (hoveredSlot === slot) {
                            setHovered(null);
                        }
                        return;
                    }
                    // Se não for transparente, ativa o hover
                    if (hoveredSlot !== slot) {
                        setHovered(slot);
                    }
                }, { passive: true });
                spriteImg.addEventListener('pointerenter', (ev) => {
                    if (!slot.hasAttribute('data-skin-tooltip')) return;
                    // Verifica transparência no enter também
                    if (!isPixelTransparent(spriteImg, ev.clientX, ev.clientY)) {
                        setHovered(slot);
                    }
                }, { passive: true });
                spriteImg.addEventListener('pointerleave', (ev) => {
                    const toCard = ev.relatedTarget && ev.relatedTarget.closest && ev.relatedTarget.closest('.podium-slot');
                    if (toCard && podium.contains(toCard)) {
                        // Se está indo para outro slot, verifica transparência
                        const otherImg = toCard.querySelector('.podium-sprite img');
                        if (otherImg && ev.relatedTarget && !isPixelTransparent(otherImg, ev.clientX, ev.clientY)) {
                            return; // Não remove hover se está indo para pixel não-transparente
                        }
                    }
                    setHovered(null);
                }, { passive: true });
            }
         });
         });


         // Tooltip i18n
         podium.addEventListener('pointerleave', () => { setHovered(null); }, { passive: true });
         const tooltipEl = document.createElement('div');
 
         tooltipEl.className = 'skin-tooltip';
        // Só atualiza em scroll/resize, não em mousemove
        tooltipEl.style.display = 'none';
         window.addEventListener('scroll', () => { if (hoveredSlot) place(hoveredSlot); }, true);
        document.body.appendChild(tooltipEl);
        window.addEventListener('resize', () => { if (hoveredSlot) place(hoveredSlot); });
 
         // Função para ajustar sombra ao tamanho exato da imagem do tile
        function updateShadows() {
            const platformTops = document.querySelectorAll('.podium-platform-top');
            platformTops.forEach((top, index) => {
                const img = top.querySelector('img');
                if (img) {
                    const updateShadow = () => {
                        // Usa naturalWidth/naturalHeight primeiro (mais rápido)
                        let imgWidth = img.naturalWidth || img.offsetWidth || 0;
                        let imgHeight = img.naturalHeight || img.offsetHeight || 0;
 
                        // Se ainda não tem dimensões, tenta forçar o carregamento
                        if (imgWidth === 0 || imgHeight === 0) {
                            // Força o recálculo das dimensões
                            imgWidth = img.naturalWidth || img.width || img.offsetWidth || 0;
                            imgHeight = img.naturalHeight || img.height || img.offsetHeight || 0;
                        }


        function getLangKey() {
                        if (imgWidth > 0 && imgHeight > 0) {
            const raw = (document.documentElement.lang || 'pt').toLowerCase();
                            top.style.setProperty('--img-width', imgWidth + 'px');
            return raw === 'pt-br' ? 'pt' : (raw.split('-')[0] || 'pt');
                            top.style.setProperty('--img-height', imgHeight + 'px');
        }
                        } else {
                            // Se ainda não tem dimensões, agenda nova tentativa
                            // Especialmente importante para a última skin que pode carregar por último
                            setTimeout(() => {
                                const retryWidth = img.naturalWidth || img.offsetWidth || img.width || 0;
                                const retryHeight = img.naturalHeight || img.offsetHeight || img.height || 0;
                                if (retryWidth > 0 && retryHeight > 0) {
                                    top.style.setProperty('--img-width', retryWidth + 'px');
                                    top.style.setProperty('--img-height', retryHeight + 'px');
                                }
                            }, 100 + (index * 20)); // Delay progressivo para cada tile
                        }
                    };


        podium.querySelectorAll('.podium-slot').forEach(slot => {
                    // Tenta atualizar imediatamente
            if (slot.dataset.tooltipWired === '1') return;
                    updateShadow();
            slot.dataset.tooltipWired = '1';


            const tooltipRaw = slot.getAttribute('data-skin-tooltip') || '';
                    // Se a imagem já carregou, atualiza novamente para garantir
            const tooltipI18n = slot.getAttribute('data-skin-tooltip-i18n');
                    if (img.complete && img.naturalWidth > 0) {
                        requestAnimationFrame(updateShadow);
                    } else {
                        // Usa 'load' e também verifica periodicamente
                        img.addEventListener('load', () => {
                            requestAnimationFrame(updateShadow);
                        }, { once: true });


            function showTooltip(e) {
                        // Fallback: verifica após um tempo curto (com delay progressivo para última skin)
                const lang = getLangKey();
                        setTimeout(() => {
                let text = tooltipRaw;
                            if (img.complete || img.naturalWidth > 0) {
                                requestAnimationFrame(updateShadow);
                            }
                        }, 50 + (index * 10));


                if (tooltipI18n) {
                        // Fallback adicional para garantir que a última skin seja atualizada
                    try {
                        if (index === platformTops.length - 1) {
                        const pack = JSON.parse(tooltipI18n);
                            setTimeout(() => {
                        text = pack[lang] || pack.pt || pack.en || pack.es || pack.pl || tooltipRaw;
                                updateShadow();
                    } catch (e) {
                            }, 200);
                         // fallback to raw
                            setTimeout(() => {
                                updateShadow();
                            }, 500);
                         }
                     }
                     }
                 }
                 }
            });
        }


                if (!text) return;
        // Executa imediatamente e também após DOMContentLoaded
        updateShadows();


                tooltipEl.innerHTML = text;
        if (document.readyState === 'loading') {
                tooltipEl.style.display = 'block';
            document.addEventListener('DOMContentLoaded', updateShadows);
                const rect = slot.getBoundingClientRect();
            window.addEventListener('load', updateShadows);
                tooltipEl.style.left = rect.left + 'px';
        } else {
                tooltipEl.style.top = (rect.top - tooltipEl.offsetHeight - 10) + 'px';
            // Se já carregou, executa imediatamente e depois de um frame
             }
            requestAnimationFrame(updateShadows);
        }
 
        // Garante que todas as imagens dos tiles sejam atualizadas após o carregamento completo
        window.addEventListener('load', () => {
            setTimeout(updateShadows, 100);
            setTimeout(updateShadows, 300);
            setTimeout(updateShadows, 500);
        });
 
        // Observa mudanças nas imagens
        if ('MutationObserver' in window) {
            const observer = new MutationObserver(() => {
                updateShadows();
            });
             observer.observe(podium, { childList: true, subtree: true });
        }


             function hideTooltip() {
        // Observa quando imagens dos tiles são carregadas
                 tooltipEl.style.display = 'none';
        const tileImages = document.querySelectorAll('.podium-platform-top img');
        tileImages.forEach((img, index) => {
             if (img.complete) {
                 // Se já carregou, força atualização
                setTimeout(() => updateShadows(), 50 + (index * 20));
            } else {
                img.addEventListener('load', () => {
                    updateShadows();
                }, { once: true });
             }
             }
            slot.addEventListener('mouseenter', showTooltip);
            slot.addEventListener('mouseleave', hideTooltip);
         });
         });
     })();
     })();
</script>
</script>
<style>
    /* Container escuro para área de skins - igual ao content-card */
    .card-skins {
        width: min(1600px, 96vw);
        max-width: 96vw;
        margin: 10px auto;
        background: rgba(28, 28, 34, .95);
        border-radius: 12px;
        box-shadow: 0 8px 24px rgba(0, 0, 0, .30);
        padding: 18px;
        z-index: 2;
        box-sizing: border-box;
        overflow-x: hidden;
        overflow-y: visible;
    }
    /* Regras globais para filhos do card-skins - igual ao content-card */
    .card-skins,
    .skins-podium {
        box-sizing: border-box;
        max-width: 100%;
    }
    .card-skins * {
        max-width: 100%;
        box-sizing: border-box;
    }
    /* Exceção: imagens do tile e sprite mantêm tamanho natural (exceto no mobile) */
    .podium-platform-top img,
    .podium-sprite img {
        max-width: none;
    }
    /* Podium de skins - layout isométrico */
    .skins-podium {
        display: flex;
        align-items: flex-end;
        /* Alinha todos os slots pelo bottom */
        justify-content: center;
        gap: 30px;
        padding: 20px 0 50px 0;
        /* Padding extra na parte inferior para os tiles */
        position: relative;
        width: 100%;
        flex-wrap: wrap;
        box-sizing: border-box;
        overflow-x: hidden;
        overflow-y: visible;
    }
    .podium-slot {
        position: relative;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: flex-end;
        /* Alinha pelo bottom */
        cursor: pointer;
        transition: filter 0.14s ease, box-shadow 0.14s ease;
        flex-shrink: 0;
        max-width: 100%;
        box-sizing: border-box;
        overflow: visible;
        /* Permite que os tiles saiam do slot se necessário */
        /* Permite margin-left negativo para offset_x */
    }
    /* Z-index: sprites da direita passam na frente das da esquerda */
    /* Aplicado dinamicamente via JS, mas CSS base para primeiros slots */
    .podium-slot:nth-child(1) {
        z-index: 1;
        /* Esquerda: mais atrás */
    }
    .podium-slot:nth-child(2) {
        z-index: 2;
    }
    .podium-slot:nth-child(3) {
        z-index: 3;
    }
    .podium-slot:nth-child(4) {
        z-index: 4;
        /* Direita: mais na frente */
    }
    /* Z-index para sprite-containers: direita passa na frente da esquerda */
    /* IMPORTANTE: z-index alto para garantir que sprites sempre fiquem acima dos tiles (z-index negativo) */
    .podium-slot:nth-child(1) .podium-sprite-container {
        z-index: 1000 !important;
        /* Esquerda: mais atrás */
    }
    .podium-slot:nth-child(2) .podium-sprite-container {
        z-index: 2000 !important;
    }
    .podium-slot:nth-child(3) .podium-sprite-container {
        z-index: 3000 !important;
    }
    .podium-slot:nth-child(4) .podium-sprite-container {
        z-index: 4000 !important;
        /* Direita: mais na frente, acima de todos os tiles */
    }
    /* Hitbox baseada na imagem, não no container */
    .podium-slot>* {
        pointer-events: none;
    }
    /* Apenas a imagem do sprite tem hitbox - container não interfere */
    .podium-sprite img {
        pointer-events: auto;
    }
    /* Container e sprite não têm hitbox para não interferir */
    .podium-sprite-container,
    .podium-sprite {
        pointer-events: none;
    }
    /* Piso nunca tem hitbox */
    .podium-platform,
    .podium-platform-top,
    .podium-platform-top img {
        pointer-events: none !important;
    }
    /* Container do sprite - tamanho natural, não afetado pelo tile */
    .podium-sprite-container {
        position: relative;
        z-index: 10;
        display: flex;
        flex-direction: column;
        align-items: flex-end;
        /* Alinha pelo bottom (pés) - horizontalmente */
        justify-content: center;
        /* Centraliza horizontalmente */
        filter: drop-shadow(0 6px 20px rgba(0, 0, 0, 0.5));
        transform: none !important;
        flex-shrink: 0;
        max-width: 100%;
        box-sizing: border-box;
        /* REMOVIDO isolation: isolate - estava criando contexto que impedia tiles de ficarem atrás */
    }
    /* Garante que TODAS as sprites fiquem acima de TODOS os tiles */
    /* IMPORTANTE: z-index mínimo de 1 para garantir que sprites sempre fiquem acima dos tiles (z-index negativo) */
    .podium-slot .podium-sprite-container {
        position: relative;
        z-index: 1 !important;
    }
    .podium-sprite {
        display: block;
        position: relative;
        transform: none !important;
        flex-shrink: 0;
    }
    .podium-sprite img {
        width: auto;
        height: auto;
        max-width: none;
        max-height: none;
        image-rendering: pixelated;
        image-rendering: -moz-crisp-edges;
        image-rendering: -webkit-optimize-contrast;
        image-rendering: crisp-edges;
        display: block;
        position: relative;
        z-index: 10 !important;
        /* Imagem sempre acima do piso (z-index maior que tiles) */
        transform: none !important;
        will-change: auto;
        flex-shrink: 0;
    }
    /* Tile isométrico nos pés da sprite - atrás da sprite */
    /* IMPORTANTE: z-index 0 para ficar acima do background do card-skins, mas abaixo das sprites (z-index 10-40) */
    .podium-platform {
        position: absolute;
        width: auto;
        height: auto;
        bottom: -15px;
        right: -25px;
        z-index: 0 !important;
        /* z-index 0 fica acima do background do card-skins, mas abaixo das sprites */
    }
    /* Todos os pisos com z-index 0 - acima do background, mas abaixo das sprites */
    .podium-slot .podium-platform {
        z-index: 0 !important;
    }
    /* CRÍTICO: Garante que tiles fiquem acima do background do card, mas abaixo de TODAS as sprites */
    .podium-slot .podium-platform,
    .podium-slot .podium-platform-top,
    .podium-slot .podium-platform-top img {
        /* z-index 0 garante que fiquem acima do background do card-skins */
        /* mas as sprites têm z-index 10-40, então ficam na frente */
        z-index: 0 !important;
    }
    /* Tile - usando imagem no tamanho natural */
    .podium-platform-top {
        position: absolute;
        width: auto;
        height: auto;
        transform-origin: center bottom;
        transform: rotateX(15deg);
        /* Inclinação fixa em 15 graus */
        z-index: 0 !important;
        /* z-index 0 fica acima do background do card, mas abaixo das sprites */
    }
    .podium-platform-top img {
        display: block;
        width: auto;
        height: auto;
        max-width: none;
        max-height: none;
        image-rendering: pixelated;
        image-rendering: -moz-crisp-edges;
        image-rendering: -webkit-optimize-contrast;
        image-rendering: crisp-edges;
        position: relative;
        z-index: 0 !important;
        /* z-index 0 fica acima do background do card, mas abaixo das sprites (z-index 10-40) */
        border: none !important;
        outline: none;
        box-shadow: none;
        opacity: 1 !important;
        /* Garante que a imagem do tile sempre esteja visível */
    }
    /* Sombra quadrada sólida - perfeitamente alinhada com a imagem */
    .podium-platform-top::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        width: var(--img-width, 100%);
        height: var(--img-height, 100%);
        background: rgba(0, 0, 0, 0.5);
        z-index: -1 !important;
        /* z-index -1 para ficar atrás da imagem do tile, mas ainda acima do background do card */
        transform: translate(3px, 3px);
        pointer-events: none;
        opacity: 0;
        transition: opacity 0.1s ease;
    }
    /* Mostra a sombra quando as dimensões estão definidas */
    .podium-platform-top[style*="--img-width"]::before {
        opacity: 1;
    }
    /* Sistema de hover - dim outras skins, destaque na hovered */
    .skins-podium.hovering .podium-slot.dim {
        filter: brightness(.55) saturate(.85);
        transition: filter .14s ease;
    }
    .skins-podium.hovering .podium-slot.hovered {
        filter: none;
    }
    /* CRÍTICO: Remove efeito de hover da imagem do piso (sem "borda fantasma") */
    .skins-podium.hovering .podium-slot.dim .podium-platform-top,
    .skins-podium.hovering .podium-slot.hovered .podium-platform-top,
    .skins-podium.hovering .podium-slot.dim .podium-platform-top img,
    .skins-podium.hovering .podium-slot.hovered .podium-platform-top img {
        filter: none !important;
        box-shadow: none !important;
    }
    /* Borda no tile quando hovered - apenas no container, não na imagem */
    .skins-podium.hovering .podium-slot.hovered .podium-platform-top {
        box-shadow:
            0 0 0 2px rgba(255, 255, 255, .12),
            0 10px 28px rgba(0, 0, 0, .45);
    }
    /* Remove sombra da imagem do tile no hover */
    .skins-podium.hovering .podium-slot.hovered .podium-platform-top img {
        box-shadow: none !important;
        filter: none !important;
    }
    /* Tooltip */
    .skin-tooltip {
        position: fixed;
        z-index: 9999;
        left: 0;
        top: 0;
        pointer-events: none;
        padding: 10px 12px;
        border-radius: 8px;
        background: rgba(28, 28, 34, .98);
        color: #eaeaea;
        font-size: 13px;
        line-height: 1.4;
        box-shadow: 0 8px 24px rgba(0, 0, 0, .5), inset 0 0 0 1px rgba(255, 255, 255, .06);
        transform: translate(-9999px, -9999px);
        opacity: 0;
        transition: opacity .15s ease;
        text-align: center;
        white-space: normal;
        max-width: 280px;
        min-width: 200px;
    }
    .skin-tooltip b {
        color: #fff;
    }
    .podium-slot.is-clickable {
        cursor: pointer;
    }
    .podium-slot.is-clickable:focus {
        outline: 2px solid #156bc7;
        outline-offset: 2px;
    }
    /* Responsivo */
    @media (max-width: 1100px) {
        .skins-podium {
            gap: 24px;
        }
    }
    @media (max-width: 768px) {
        .card-skins {
            padding: 14px;
        }
        .skins-podium {
            gap: 20px;
            padding: 15px 0;
        }
    }
    @media (max-width: 600px) {
        .card-skins {
            box-sizing: border-box;
            max-width: calc(100vw - env(safe-area-inset-left) - env(safe-area-inset-right) - 16px);
            width: 100%;
            margin: 10px auto;
            padding: 12px;
            border-radius: 10px;
            overflow-x: hidden;
            overflow-y: visible;
        }
        .skins-podium {
            gap: 16px;
            padding: 10px 8px 50px 8px;
            /* Padding extra na parte inferior para os tiles */
            justify-content: center;
            overflow-y: visible;
        }
        .podium-slot {
            max-width: calc(50% - 8px);
            flex: 0 0 auto;
            min-width: 0;
        }
        .podium-sprite-container {
            max-width: 100%;
            min-width: 0;
        }
        .podium-sprite img {
            max-width: 100%;
            height: auto;
        }
        .podium-platform-top img {
            max-width: 100%;
            height: auto;
        }
    }
    @media (max-width: 400px) {
        .skins-podium {
            gap: 12px;
            padding-left: 4px;
            padding-right: 4px;
        }
        .podium-slot {
            max-width: calc(50% - 6px);
        }
    }
</style>

Edição atual tal como às 23h26min de 3 de janeiro de 2026

<script>

   (function initSkinsPodiumUI() {
       const podium = document.querySelector('.skins-podium');
       if (!podium || podium.dataset.wired === '1') return;
       podium.dataset.wired = '1';
       // ---------- Função para aplicar offset_x individualmente em cada skin ----------
       // IMPORTANTE: Usa margin-left em vez de transform para afetar o layout do flexbox
       function applyOffsetX() {
           const allSlots = podium.querySelectorAll('.podium-slot');
           allSlots.forEach((slot, index) => {
               // Lê o atributo data-offset-x diretamente do elemento
               const offsetXAttr = slot.getAttribute('data-offset-x');
               if (offsetXAttr !== null && offsetXAttr !==  && offsetXAttr !== 'undefined') {
                   const numOffset = parseFloat(offsetXAttr);
                   if (!isNaN(numOffset) && numOffset !== 0) {
                       // Usa margin-left negativo para afetar o layout do flexbox
                       // Isso faz com que o elemento realmente se aproxime dos outros
                       const currentStyle = slot.getAttribute('style') || ;
                       // Remove qualquer margin-left anterior e transform (legado)
                       const cleanedStyle = currentStyle
                           .replace(/margin-left\s*:[^;]+;?/gi, )
                           .replace(/transform\s*:[^;]+;?/gi, )
                           .trim();
                       // Aplica o margin-left preservando outros estilos (como z-index)
                       const newMargin = `margin-left: ${numOffset}px`;
                       if (cleanedStyle && cleanedStyle.length > 0) {
                           slot.setAttribute('style', cleanedStyle + (cleanedStyle.endsWith(';') ? ' ' : '; ') + newMargin + ';');
                       } else {
                           slot.setAttribute('style', newMargin + ';');
                       }
                       // Força a atualização do layout
                       slot.offsetHeight;
                   } else {
                       // Se o offset for 0 ou inválido, remove margin-left e transform
                       const currentStyle = slot.getAttribute('style') || ;
                       const cleanedStyle = currentStyle
                           .replace(/margin-left\s*:[^;]+;?/gi, )
                           .replace(/transform\s*:[^;]+;?/gi, )
                           .trim();
                       if (cleanedStyle) {
                           slot.setAttribute('style', cleanedStyle + (cleanedStyle.endsWith(';') ?  : ';'));
                       } else {
                           slot.removeAttribute('style');
                       }
                   }
               } else {
                   // Se não tem offset_x, remove margin-left e transform (preserva outros estilos)
                   const currentStyle = slot.getAttribute('style') || ;
                   const cleanedStyle = currentStyle
                       .replace(/margin-left\s*:[^;]+;?/gi, )
                       .replace(/transform\s*:[^;]+;?/gi, )
                       .trim();
                   if (cleanedStyle) {
                       slot.setAttribute('style', cleanedStyle + (cleanedStyle.endsWith(';') ?  : ';'));
                   } else {
                       slot.removeAttribute('style');
                   }
               }
           });
       }
       // Flag para evitar múltiplas execuções simultâneas
       let isApplying = false;
       function applyOffsetXOnce() {
           if (isApplying) return;
           isApplying = true;
           applyOffsetX();
           requestAnimationFrame(() => {
               isApplying = false;
           });
       }
       // Aplica usando requestAnimationFrame para garantir que o DOM esteja renderizado
       requestAnimationFrame(() => {
           applyOffsetXOnce();
           // Reaplica após pequenos delays para garantir
           setTimeout(applyOffsetXOnce, 50);
           setTimeout(applyOffsetXOnce, 200);
       });
       // Também aplica quando o DOM estiver pronto
       if (document.readyState === 'loading') {
           document.addEventListener('DOMContentLoaded', () => {
               requestAnimationFrame(applyOffsetXOnce);
           });
       }
       // Observa mudanças no DOM para reaplicar se necessário (apenas para novos elementos)
       if (window.MutationObserver) {
           const observer = new MutationObserver((mutations) => {
               // Só reaplica se houver mudanças relevantes
               const hasRelevantChanges = mutations.some(m =>
                   m.type === 'childList' ||
                   (m.type === 'attributes' && (m.attributeName === 'data-offset-x' || m.attributeName === 'style'))
               );
               if (hasRelevantChanges) {
                   clearTimeout(observer.timeout);
                   observer.timeout = setTimeout(applyOffsetXOnce, 50);
               }
           });
           observer.observe(podium, {
               childList: true,
               subtree: false, // Apenas observa filhos diretos
               attributes: true,
               attributeFilter: ['data-offset-x']
           });
       }
       // ---------- Tooltip único ----------
       function ensureTip() {
           let tip = document.querySelector('.skin-tooltip');
           if (!tip) {
               tip = document.createElement('div');
               tip.className = 'skin-tooltip';
               tip.setAttribute('role', 'tooltip');
               tip.setAttribute('aria-hidden', 'true');
               tip.style.position = 'fixed';
               tip.style.transform = 'translate(-9999px,-9999px)';
               tip.style.opacity = '0';
               tip.style.transition = 'opacity .15s ease';
               document.body.appendChild(tip);
           }
           return tip;
       }
       const tip = ensureTip();
       let hoveredSlot = null;
       function place(card) {
           if (!card || tip.getAttribute('aria-hidden') === 'true') return;
           // Calcula nova posição - tooltip centralizada em relação à imagem do piso
           tip.style.transform = 'translate(-9999px,-9999px)';
           const tr = tip.getBoundingClientRect();
           // Pega a posição da imagem do tile (piso) para centralizar
           const platformImg = card.querySelector('.podium-platform-top img');
           let platformRect = card.getBoundingClientRect(); // Fallback para o card se não encontrar
           if (platformImg) {
               platformRect = platformImg.getBoundingClientRect();
           } else {
               // Se não encontrar a img, tenta o container do tile
               const platform = card.querySelector('.podium-platform');
               if (platform) {
                   platformRect = platform.getBoundingClientRect();
               }
           }
           // Centraliza horizontalmente baseado na imagem do tile
           let leftPos = Math.round(platformRect.left + (platformRect.width - tr.width) / 2);
           leftPos = Math.max(8, Math.min(leftPos, window.innerWidth - tr.width - 8));
           // Posiciona logo abaixo da imagem do tile, com pequeno espaçamento
           let top = Math.round(platformRect.bottom + 15);
           // Se não couber embaixo, coloca em cima
           if (top + tr.height > window.innerHeight - 8) {
               top = Math.round(platformRect.top - tr.height - 15);
               if (top < 8) top = 8; // Fallback se não couber em cima também
           }
           tip.style.transform = `translate(${leftPos}px, ${top}px)`;
       }
       function show(card) {
           const tooltipText = card.getAttribute('data-skin-tooltip') || ;
           tip.innerHTML = tooltipText;
           tip.setAttribute('aria-hidden', 'false');
           place(card);
           tip.style.opacity = '1';
       }
       function hide() {
           tip.setAttribute('aria-hidden', 'true');
           tip.style.opacity = '0';
           tip.style.transform = 'translate(-9999px,-9999px)';
       }
       // Função para restaurar z-index original baseado na posição do slot
       function restoreOriginalZIndex(slot) {
           if (!slot) return;
           // Determina a posição do slot (1, 2, 3, 4, etc)
           const allSlots = Array.from(podium.querySelectorAll('.podium-slot'));
           const slotIndex = allSlots.indexOf(slot);
           // Z-index: esquerda (0) = menor, direita (último) = maior (direita passa na frente)
           const originalZIndex = slotIndex + 1;
           const originalSpriteZIndex = (slotIndex + 1) * 10;
           slot.style.zIndex = originalZIndex.toString();
           const spriteContainer = slot.querySelector('.podium-sprite-container');
           if (spriteContainer) spriteContainer.style.zIndex = originalSpriteZIndex.toString();
           // CRÍTICO: Garante que TODOS os tiles sempre fiquem atrás de TODAS as sprites
           // Força z-index negativo nos tiles de todos os slots
           const platform = slot.querySelector('.podium-platform');
           const platformTop = slot.querySelector('.podium-platform-top');
           const platformImg = slot.querySelector('.podium-platform-top img');
           if (platform) platform.style.zIndex = '-1';
           if (platformTop) platformTop.style.zIndex = '-2';
           if (platformImg) platformImg.style.zIndex = '-2';
       }
       function setHovered(card) {
           if (hoveredSlot === card) {
               // Se já está hovered, não reposiciona - mantém posição fixa
               return;
           }
           // Remove hover anterior e restaura z-index original
           if (hoveredSlot) {
               hoveredSlot.classList.remove('hovered');
               restoreOriginalZIndex(hoveredSlot);
               // Garante que tiles continuem atrás após restaurar z-index
               forceTilesBehind();
           }
           podium.classList.remove('hovering');
           podium.querySelectorAll('.podium-slot.dim').forEach(n => n.classList.remove('dim'));
           if (!card) {
               hoveredSlot = null;
               hide();
               return;
           }
           hoveredSlot = card;
           hoveredSlot.classList.add('hovered');
           podium.classList.add('hovering');
           podium.querySelectorAll('.podium-slot').forEach(n => { if (n !== hoveredSlot) n.classList.add('dim'); });
           // Qualquer skin com hover fica acima de tudo
           card.style.zIndex = '9999';
           const spriteContainer = card.querySelector('.podium-sprite-container');
           if (spriteContainer) spriteContainer.style.zIndex = '9999';
           // CRÍTICO: Garante que tiles continuem atrás mesmo durante hover
           forceTilesBehind();
           show(card);
       }
       // Função para verificar se o pixel na posição do mouse é transparente
       function isPixelTransparent(img, x, y) {
           if (!img.complete || img.naturalWidth === 0) return true;
           try {
               const canvas = document.createElement('canvas');
               canvas.width = img.naturalWidth;
               canvas.height = img.naturalHeight;
               const ctx = canvas.getContext('2d');
               ctx.drawImage(img, 0, 0);
               // Calcula a posição relativa na imagem
               const rect = img.getBoundingClientRect();
               const scaleX = img.naturalWidth / rect.width;
               const scaleY = img.naturalHeight / rect.height;
               const imgX = Math.floor((x - rect.left) * scaleX);
               const imgY = Math.floor((y - rect.top) * scaleY);
               // Verifica se está dentro dos limites
               if (imgX < 0 || imgX >= img.naturalWidth || imgY < 0 || imgY >= img.naturalHeight) {
                   return true;
               }
               // Obtém o pixel
               const pixelData = ctx.getImageData(imgX, imgY, 1, 1).data;
               const alpha = pixelData[3]; // Canal alpha
               return alpha < 10; // Considera transparente se alpha < 10
           } catch (e) {
               return false; // Em caso de erro, permite o hover
           }
       }
       // ---------- Clique YouTube (sem duplicar) ----------
       podium.addEventListener('click', (ev) => {
           const slot = ev.target?.closest('.podium-slot[data-youtube]');
           if (!slot) return;
           const url = (slot.dataset.youtube || ).trim();
           if (!url) return;
           if (slot.dataset._opening === '1') return;
           slot.dataset._opening = '1';
           ev.preventDefault();
           ev.stopPropagation();
           ev.stopImmediatePropagation();
           try { window.open(url, '_blank', 'noopener,noreferrer'); }
           catch (e) { location.href = url; }
           setTimeout(() => { delete slot.dataset._opening; }, 500);
       }, { capture: true });
       podium.addEventListener('keydown', (ev) => {
           if (ev.key !== 'Enter' && ev.key !== ' ') return;
           const slot = ev.target?.closest('.podium-slot[data-youtube]');
           if (!slot) return;
           const url = (slot.dataset.youtube || ).trim();
           if (!url) return;
           if (slot.dataset._opening === '1') return;
           slot.dataset._opening = '1';
           ev.preventDefault();
           ev.stopPropagation();
           ev.stopImmediatePropagation();
           try { window.open(url, '_blank', 'noopener,noreferrer'); }
           catch (e) { location.href = url; }
           setTimeout(() => { delete slot.dataset._opening; }, 500);
       }, { capture: true });
       // ---------- Hitbox pixel-perfect por sprite ----------
       // CRÍTICO: Move tiles para fora do sprite-container para separar contexto de empilhamento
       function moveTilesOutOfSpriteContainer() {
           const allSlots = Array.from(podium.querySelectorAll('.podium-slot'));
           allSlots.forEach(slot => {
               const spriteContainer = slot.querySelector('.podium-sprite-container');
               const platform = slot.querySelector('.podium-platform');
               // Se o tile ainda está dentro do sprite-container, move para o slot
               if (platform && spriteContainer && spriteContainer.contains(platform)) {
                   // Salva os estilos inline atuais antes de mover
                   const currentRight = platform.style.right || ;
                   const currentBottom = platform.style.bottom || ;
                   const computedRight = getComputedStyle(platform).right;
                   const computedBottom = getComputedStyle(platform).bottom;
                   // Move o tile para fora do sprite-container, mas mantém dentro do slot
                   slot.appendChild(platform);
                   // Restaura a posição (os valores já estão corretos, apenas precisa manter)
                   platform.style.position = 'absolute';
                   if (currentRight) {
                       platform.style.right = currentRight;
                   } else if (computedRight && computedRight !== 'auto') {
                       platform.style.right = computedRight;
                   } else {
                       // Usa o valor padrão do CSS
                       platform.style.right = '-25px';
                   }
                   if (currentBottom) {
                       platform.style.bottom = currentBottom;
                   } else if (computedBottom && computedBottom !== 'auto') {
                       platform.style.bottom = computedBottom;
                   } else {
                       // Usa o valor padrão do CSS
                       platform.style.bottom = '-15px';
                   }
               }
           });
       }
       // CRÍTICO: Força todos os tiles a terem z-index negativo na inicialização
       function forceTilesBehind() {
           const allSlots = Array.from(podium.querySelectorAll('.podium-slot'));
           allSlots.forEach(slot => {
               const platform = slot.querySelector('.podium-platform');
               const platformTop = slot.querySelector('.podium-platform-top');
               const platformImg = slot.querySelector('.podium-platform-top img');
               if (platform) {
                   platform.style.zIndex = '0';
                   platform.style.setProperty('z-index', '0', 'important');
               }
               if (platformTop) {
                   platformTop.style.zIndex = '0';
                   platformTop.style.setProperty('z-index', '0', 'important');
               }
               if (platformImg) {
                   platformImg.style.zIndex = '0';
                   platformImg.style.setProperty('z-index', '0', 'important');
               }
           });
       }
       // Move tiles para fora do sprite-container primeiro
       moveTilesOutOfSpriteContainer();
       setTimeout(moveTilesOutOfSpriteContainer, 10);
       setTimeout(moveTilesOutOfSpriteContainer, 100);
       // Depois força z-index negativo
       forceTilesBehind();
       setTimeout(forceTilesBehind, 10);
       setTimeout(forceTilesBehind, 100);
       const slots = Array.from(podium.querySelectorAll('.podium-slot'));
       slots.forEach(slot => {
           const spriteImg = slot.querySelector('.podium-sprite img');
           // Hitbox apenas na imagem do sprite, verificando transparência
           if (spriteImg) {
               spriteImg.addEventListener('pointermove', (ev) => {
                   if (!slot.hasAttribute('data-skin-tooltip')) return;
                   // Verifica se o pixel é transparente
                   if (isPixelTransparent(spriteImg, ev.clientX, ev.clientY)) {
                       // Se for transparente e estiver hovered, remove o hover
                       if (hoveredSlot === slot) {
                           setHovered(null);
                       }
                       return;
                   }
                   // Se não for transparente, ativa o hover
                   if (hoveredSlot !== slot) {
                       setHovered(slot);
                   }
               }, { passive: true });
               spriteImg.addEventListener('pointerenter', (ev) => {
                   if (!slot.hasAttribute('data-skin-tooltip')) return;
                   // Verifica transparência no enter também
                   if (!isPixelTransparent(spriteImg, ev.clientX, ev.clientY)) {
                       setHovered(slot);
                   }
               }, { passive: true });
               spriteImg.addEventListener('pointerleave', (ev) => {
                   const toCard = ev.relatedTarget && ev.relatedTarget.closest && ev.relatedTarget.closest('.podium-slot');
                   if (toCard && podium.contains(toCard)) {
                       // Se está indo para outro slot, verifica transparência
                       const otherImg = toCard.querySelector('.podium-sprite img');
                       if (otherImg && ev.relatedTarget && !isPixelTransparent(otherImg, ev.clientX, ev.clientY)) {
                           return; // Não remove hover se está indo para pixel não-transparente
                       }
                   }
                   setHovered(null);
               }, { passive: true });
           }
       });
       podium.addEventListener('pointerleave', () => { setHovered(null); }, { passive: true });
       // Só atualiza em scroll/resize, não em mousemove
       window.addEventListener('scroll', () => { if (hoveredSlot) place(hoveredSlot); }, true);
       window.addEventListener('resize', () => { if (hoveredSlot) place(hoveredSlot); });
       // Função para ajustar sombra ao tamanho exato da imagem do tile
       function updateShadows() {
           const platformTops = document.querySelectorAll('.podium-platform-top');
           platformTops.forEach((top, index) => {
               const img = top.querySelector('img');
               if (img) {
                   const updateShadow = () => {
                       // Usa naturalWidth/naturalHeight primeiro (mais rápido)
                       let imgWidth = img.naturalWidth || img.offsetWidth || 0;
                       let imgHeight = img.naturalHeight || img.offsetHeight || 0;
                       // Se ainda não tem dimensões, tenta forçar o carregamento
                       if (imgWidth === 0 || imgHeight === 0) {
                           // Força o recálculo das dimensões
                           imgWidth = img.naturalWidth || img.width || img.offsetWidth || 0;
                           imgHeight = img.naturalHeight || img.height || img.offsetHeight || 0;
                       }
                       if (imgWidth > 0 && imgHeight > 0) {
                           top.style.setProperty('--img-width', imgWidth + 'px');
                           top.style.setProperty('--img-height', imgHeight + 'px');
                       } else {
                           // Se ainda não tem dimensões, agenda nova tentativa
                           // Especialmente importante para a última skin que pode carregar por último
                           setTimeout(() => {
                               const retryWidth = img.naturalWidth || img.offsetWidth || img.width || 0;
                               const retryHeight = img.naturalHeight || img.offsetHeight || img.height || 0;
                               if (retryWidth > 0 && retryHeight > 0) {
                                   top.style.setProperty('--img-width', retryWidth + 'px');
                                   top.style.setProperty('--img-height', retryHeight + 'px');
                               }
                           }, 100 + (index * 20)); // Delay progressivo para cada tile
                       }
                   };
                   // Tenta atualizar imediatamente
                   updateShadow();
                   // Se a imagem já carregou, atualiza novamente para garantir
                   if (img.complete && img.naturalWidth > 0) {
                       requestAnimationFrame(updateShadow);
                   } else {
                       // Usa 'load' e também verifica periodicamente
                       img.addEventListener('load', () => {
                           requestAnimationFrame(updateShadow);
                       }, { once: true });
                       // Fallback: verifica após um tempo curto (com delay progressivo para última skin)
                       setTimeout(() => {
                           if (img.complete || img.naturalWidth > 0) {
                               requestAnimationFrame(updateShadow);
                           }
                       }, 50 + (index * 10));
                       // Fallback adicional para garantir que a última skin seja atualizada
                       if (index === platformTops.length - 1) {
                           setTimeout(() => {
                               updateShadow();
                           }, 200);
                           setTimeout(() => {
                               updateShadow();
                           }, 500);
                       }
                   }
               }
           });
       }
       // Executa imediatamente e também após DOMContentLoaded
       updateShadows();
       if (document.readyState === 'loading') {
           document.addEventListener('DOMContentLoaded', updateShadows);
           window.addEventListener('load', updateShadows);
       } else {
           // Se já carregou, executa imediatamente e depois de um frame
           requestAnimationFrame(updateShadows);
       }
       // Garante que todas as imagens dos tiles sejam atualizadas após o carregamento completo
       window.addEventListener('load', () => {
           setTimeout(updateShadows, 100);
           setTimeout(updateShadows, 300);
           setTimeout(updateShadows, 500);
       });
       // Observa mudanças nas imagens
       if ('MutationObserver' in window) {
           const observer = new MutationObserver(() => {
               updateShadows();
           });
           observer.observe(podium, { childList: true, subtree: true });
       }
       // Observa quando imagens dos tiles são carregadas
       const tileImages = document.querySelectorAll('.podium-platform-top img');
       tileImages.forEach((img, index) => {
           if (img.complete) {
               // Se já carregou, força atualização
               setTimeout(() => updateShadows(), 50 + (index * 20));
           } else {
               img.addEventListener('load', () => {
                   updateShadows();
               }, { once: true });
           }
       });
   })();

</script> <style>

   /* Container escuro para área de skins - igual ao content-card */
   .card-skins {
       width: min(1600px, 96vw);
       max-width: 96vw;
       margin: 10px auto;
       background: rgba(28, 28, 34, .95);
       border-radius: 12px;
       box-shadow: 0 8px 24px rgba(0, 0, 0, .30);
       padding: 18px;
       z-index: 2;
       box-sizing: border-box;
       overflow-x: hidden;
       overflow-y: visible;
   }
   /* Regras globais para filhos do card-skins - igual ao content-card */
   .card-skins,
   .skins-podium {
       box-sizing: border-box;
       max-width: 100%;
   }
   .card-skins * {
       max-width: 100%;
       box-sizing: border-box;
   }
   /* Exceção: imagens do tile e sprite mantêm tamanho natural (exceto no mobile) */
   .podium-platform-top img,
   .podium-sprite img {
       max-width: none;
   }
   /* Podium de skins - layout isométrico */
   .skins-podium {
       display: flex;
       align-items: flex-end;
       /* Alinha todos os slots pelo bottom */
       justify-content: center;
       gap: 30px;
       padding: 20px 0 50px 0;
       /* Padding extra na parte inferior para os tiles */
       position: relative;
       width: 100%;
       flex-wrap: wrap;
       box-sizing: border-box;
       overflow-x: hidden;
       overflow-y: visible;
   }
   .podium-slot {
       position: relative;
       display: flex;
       flex-direction: column;
       align-items: center;
       justify-content: flex-end;
       /* Alinha pelo bottom */
       cursor: pointer;
       transition: filter 0.14s ease, box-shadow 0.14s ease;
       flex-shrink: 0;
       max-width: 100%;
       box-sizing: border-box;
       overflow: visible;
       /* Permite que os tiles saiam do slot se necessário */
       /* Permite margin-left negativo para offset_x */
   }
   /* Z-index: sprites da direita passam na frente das da esquerda */
   /* Aplicado dinamicamente via JS, mas CSS base para primeiros slots */
   .podium-slot:nth-child(1) {
       z-index: 1;
       /* Esquerda: mais atrás */
   }
   .podium-slot:nth-child(2) {
       z-index: 2;
   }
   .podium-slot:nth-child(3) {
       z-index: 3;
   }
   .podium-slot:nth-child(4) {
       z-index: 4;
       /* Direita: mais na frente */
   }
   /* Z-index para sprite-containers: direita passa na frente da esquerda */
   /* IMPORTANTE: z-index alto para garantir que sprites sempre fiquem acima dos tiles (z-index negativo) */
   .podium-slot:nth-child(1) .podium-sprite-container {
       z-index: 1000 !important;
       /* Esquerda: mais atrás */
   }
   .podium-slot:nth-child(2) .podium-sprite-container {
       z-index: 2000 !important;
   }
   .podium-slot:nth-child(3) .podium-sprite-container {
       z-index: 3000 !important;
   }
   .podium-slot:nth-child(4) .podium-sprite-container {
       z-index: 4000 !important;
       /* Direita: mais na frente, acima de todos os tiles */
   }
   /* Hitbox baseada na imagem, não no container */
   .podium-slot>* {
       pointer-events: none;
   }
   /* Apenas a imagem do sprite tem hitbox - container não interfere */
   .podium-sprite img {
       pointer-events: auto;
   }
   /* Container e sprite não têm hitbox para não interferir */
   .podium-sprite-container,
   .podium-sprite {
       pointer-events: none;
   }
   /* Piso nunca tem hitbox */
   .podium-platform,
   .podium-platform-top,
   .podium-platform-top img {
       pointer-events: none !important;
   }
   /* Container do sprite - tamanho natural, não afetado pelo tile */
   .podium-sprite-container {
       position: relative;
       z-index: 10;
       display: flex;
       flex-direction: column;
       align-items: flex-end;
       /* Alinha pelo bottom (pés) - horizontalmente */
       justify-content: center;
       /* Centraliza horizontalmente */
       filter: drop-shadow(0 6px 20px rgba(0, 0, 0, 0.5));
       transform: none !important;
       flex-shrink: 0;
       max-width: 100%;
       box-sizing: border-box;
       /* REMOVIDO isolation: isolate - estava criando contexto que impedia tiles de ficarem atrás */
   }
   /* Garante que TODAS as sprites fiquem acima de TODOS os tiles */
   /* IMPORTANTE: z-index mínimo de 1 para garantir que sprites sempre fiquem acima dos tiles (z-index negativo) */
   .podium-slot .podium-sprite-container {
       position: relative;
       z-index: 1 !important;
   }
   .podium-sprite {
       display: block;
       position: relative;
       transform: none !important;
       flex-shrink: 0;
   }
   .podium-sprite img {
       width: auto;
       height: auto;
       max-width: none;
       max-height: none;
       image-rendering: pixelated;
       image-rendering: -moz-crisp-edges;
       image-rendering: -webkit-optimize-contrast;
       image-rendering: crisp-edges;
       display: block;
       position: relative;
       z-index: 10 !important;
       /* Imagem sempre acima do piso (z-index maior que tiles) */
       transform: none !important;
       will-change: auto;
       flex-shrink: 0;
   }
   /* Tile isométrico nos pés da sprite - atrás da sprite */
   /* IMPORTANTE: z-index 0 para ficar acima do background do card-skins, mas abaixo das sprites (z-index 10-40) */
   .podium-platform {
       position: absolute;
       width: auto;
       height: auto;
       bottom: -15px;
       right: -25px;
       z-index: 0 !important;
       /* z-index 0 fica acima do background do card-skins, mas abaixo das sprites */
   }
   /* Todos os pisos com z-index 0 - acima do background, mas abaixo das sprites */
   .podium-slot .podium-platform {
       z-index: 0 !important;
   }
   /* CRÍTICO: Garante que tiles fiquem acima do background do card, mas abaixo de TODAS as sprites */
   .podium-slot .podium-platform,
   .podium-slot .podium-platform-top,
   .podium-slot .podium-platform-top img {
       /* z-index 0 garante que fiquem acima do background do card-skins */
       /* mas as sprites têm z-index 10-40, então ficam na frente */
       z-index: 0 !important;
   }
   /* Tile - usando imagem no tamanho natural */
   .podium-platform-top {
       position: absolute;
       width: auto;
       height: auto;
       transform-origin: center bottom;
       transform: rotateX(15deg);
       /* Inclinação fixa em 15 graus */
       z-index: 0 !important;
       /* z-index 0 fica acima do background do card, mas abaixo das sprites */
   }
   .podium-platform-top img {
       display: block;
       width: auto;
       height: auto;
       max-width: none;
       max-height: none;
       image-rendering: pixelated;
       image-rendering: -moz-crisp-edges;
       image-rendering: -webkit-optimize-contrast;
       image-rendering: crisp-edges;
       position: relative;
       z-index: 0 !important;
       /* z-index 0 fica acima do background do card, mas abaixo das sprites (z-index 10-40) */
       border: none !important;
       outline: none;
       box-shadow: none;
       opacity: 1 !important;
       /* Garante que a imagem do tile sempre esteja visível */
   }
   /* Sombra quadrada sólida - perfeitamente alinhada com a imagem */
   .podium-platform-top::before {
       content: ;
       position: absolute;
       top: 0;
       left: 0;
       width: var(--img-width, 100%);
       height: var(--img-height, 100%);
       background: rgba(0, 0, 0, 0.5);
       z-index: -1 !important;
       /* z-index -1 para ficar atrás da imagem do tile, mas ainda acima do background do card */
       transform: translate(3px, 3px);
       pointer-events: none;
       opacity: 0;
       transition: opacity 0.1s ease;
   }
   /* Mostra a sombra quando as dimensões estão definidas */
   .podium-platform-top[style*="--img-width"]::before {
       opacity: 1;
   }
   /* Sistema de hover - dim outras skins, destaque na hovered */
   .skins-podium.hovering .podium-slot.dim {
       filter: brightness(.55) saturate(.85);
       transition: filter .14s ease;
   }
   .skins-podium.hovering .podium-slot.hovered {
       filter: none;
   }
   /* CRÍTICO: Remove efeito de hover da imagem do piso (sem "borda fantasma") */
   .skins-podium.hovering .podium-slot.dim .podium-platform-top,
   .skins-podium.hovering .podium-slot.hovered .podium-platform-top,
   .skins-podium.hovering .podium-slot.dim .podium-platform-top img,
   .skins-podium.hovering .podium-slot.hovered .podium-platform-top img {
       filter: none !important;
       box-shadow: none !important;
   }
   /* Borda no tile quando hovered - apenas no container, não na imagem */
   .skins-podium.hovering .podium-slot.hovered .podium-platform-top {
       box-shadow:
           0 0 0 2px rgba(255, 255, 255, .12),
           0 10px 28px rgba(0, 0, 0, .45);
   }
   /* Remove sombra da imagem do tile no hover */
   .skins-podium.hovering .podium-slot.hovered .podium-platform-top img {
       box-shadow: none !important;
       filter: none !important;
   }
   /* Tooltip */
   .skin-tooltip {
       position: fixed;
       z-index: 9999;
       left: 0;
       top: 0;
       pointer-events: none;
       padding: 10px 12px;
       border-radius: 8px;
       background: rgba(28, 28, 34, .98);
       color: #eaeaea;
       font-size: 13px;
       line-height: 1.4;
       box-shadow: 0 8px 24px rgba(0, 0, 0, .5), inset 0 0 0 1px rgba(255, 255, 255, .06);
       transform: translate(-9999px, -9999px);
       opacity: 0;
       transition: opacity .15s ease;
       text-align: center;
       white-space: normal;
       max-width: 280px;
       min-width: 200px;
   }
   .skin-tooltip b {
       color: #fff;
   }
   .podium-slot.is-clickable {
       cursor: pointer;
   }
   .podium-slot.is-clickable:focus {
       outline: 2px solid #156bc7;
       outline-offset: 2px;
   }
   /* Responsivo */
   @media (max-width: 1100px) {
       .skins-podium {
           gap: 24px;
       }
   }
   @media (max-width: 768px) {
       .card-skins {
           padding: 14px;
       }
       .skins-podium {
           gap: 20px;
           padding: 15px 0;
       }
   }
   @media (max-width: 600px) {
       .card-skins {
           box-sizing: border-box;
           max-width: calc(100vw - env(safe-area-inset-left) - env(safe-area-inset-right) - 16px);
           width: 100%;
           margin: 10px auto;
           padding: 12px;
           border-radius: 10px;
           overflow-x: hidden;
           overflow-y: visible;
       }
       .skins-podium {
           gap: 16px;
           padding: 10px 8px 50px 8px;
           /* Padding extra na parte inferior para os tiles */
           justify-content: center;
           overflow-y: visible;
       }
       .podium-slot {
           max-width: calc(50% - 8px);
           flex: 0 0 auto;
           min-width: 0;
       }
       .podium-sprite-container {
           max-width: 100%;
           min-width: 0;
       }
       .podium-sprite img {
           max-width: 100%;
           height: auto;
       }
       .podium-platform-top img {
           max-width: 100%;
           height: auto;
       }
   }
   @media (max-width: 400px) {
       .skins-podium {
           gap: 12px;
           padding-left: 4px;
           padding-right: 4px;
       }
       .podium-slot {
           max-width: calc(50% - 6px);
       }
   }

</style>