Widget:C.Skins

De Wiki Gla
Ir para navegação Ir para pesquisar

<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>