Mudanças entre as edições de "Widget:Teste"

De Wiki Gla
Ir para navegação Ir para pesquisar
m
Etiqueta: Revertido
m
Etiquetas: Reversão manual Revertido
Linha 1: Linha 1:
local p = {}
<script>
    (function () {
        const buttons = document.querySelectorAll('.tab-btn');
        const contents = document.querySelectorAll('.tab-content');
        const cuadrosContainer = document.querySelector('.cuadros-container');
        const descripcionContainer = document.querySelector('.descripcion-container');
        const videoContainer = document.querySelector('.video-container');
        const cuadros = [...cuadrosContainer.querySelectorAll('.cuadro')];
        const mwBody = document.querySelector('.personaje-box');
        let totalVideos = 0;
        let loadedVideos = 0;
        const videosCache = {};
        let autoplayEnabled = false;


function p.skin(frame)
        activarFlechasCarrusel();
    local a = frame.args
 
     local obj = {
        const placeholder = document.createElement('div');
        sprite = a.sprite or '',
        placeholder.className = 'video-placeholder';
         background = a.background or '',
        placeholder.innerHTML = `<img src="/images/d/d5/Icon_gla.png" alt="Cargando...">`;
         tooltip = a.tooltip or ''
        videoContainer.appendChild(placeholder);
 
        function removePlaceholderSmooth() {
            placeholder.classList.add('fade-out');
            placeholder.addEventListener('transitionend', () => placeholder.remove(), { once: true });
        }
 
        function checkAllVideosLoaded() {
            if (loadedVideos === totalVideos && totalVideos > 0) {
                autoplayEnabled = true;
            }
        }
 
        // Pré-carregar todos os vídeos
        cuadros.forEach(div => {
            const videoSrc = div.dataset.video;
            const index = div.dataset.index;
 
            if (videoSrc && videoSrc.trim() !== '' && !videosCache[index]) {
                totalVideos++;
 
                const videoEl = document.createElement('video');
                videoEl.setAttribute('width', '100%');
                videoEl.setAttribute('controls', '');
                videoEl.setAttribute('preload', 'auto');
                videoEl.setAttribute('playsinline', '');
                videoEl.dataset.index = index;
                videoEl.style.display = 'none';
 
                const source = document.createElement('source');
                source.src = videoSrc;
                source.type = 'video/webm';
                videoEl.appendChild(source);
 
                // Quando o vídeo já estiver pronto, remover placeholder
                videoEl.addEventListener('canplay', () => {
                    loadedVideos++;
                    if (loadedVideos === 1) {
                        videoEl.pause();
                        videoEl.currentTime = 0;
                    }
                    const activeCuadro = document.querySelector('.cuadro.activo');
                    if (activeCuadro && activeCuadro.dataset.index === videoEl.dataset.index) {
                        setTimeout(removePlaceholderSmooth, 200);
                    }
                    checkAllVideosLoaded();
                });
 
 
 
                videoEl.addEventListener('error', () => {
                    loadedVideos++;
                    removePlaceholderSmooth();
                    checkAllVideosLoaded();
                });
 
                videoContainer.appendChild(videoEl);
                videosCache[index] = videoEl;
            }
        });
 
        // Se não houver vídeos, ocultar imediatamente
        if (totalVideos === 0) {
            placeholder.remove();
        }
 
        buttons.forEach(btn => btn.addEventListener('click', () => {
            buttons.forEach(b => b.classList.remove('active'));
            contents.forEach(c => c.classList.remove('active'));
            btn.classList.add('active');
            document.getElementById(btn.dataset.tab).classList.add('active');
        }));
 
        cuadros.forEach(div => {
            const nome = div.dataset.nome;
            const desc = div.dataset.desc.replace(/'''(.*?)'''/g, '<b>$1</b>');
            const atr = div.dataset.atr;
            const index = div.dataset.index;
            const hasVideo = div.dataset.video && div.dataset.video.trim() !== '';
 
            div.title = nome;
 
            div.addEventListener('click', () => {
                if (!autoplayEnabled && loadedVideos > 0) {
                    autoplayEnabled = true;
                }
                descripcionContainer.innerHTML = `
                <div class="titulo-habilidad">
                    <h3>${nome}</h3>
                </div>
                ${generarHTMLAtributos(atr)}
                <div class="desc">${desc}</div>
            `;
 
                Object.values(videosCache).forEach(v => {
                    v.pause();
                    v.style.display = 'none';
                });
 
                // Gerenciar habilidades com/sem vídeo
                if (hasVideo) {
                    const videoEl = videosCache[index];
                    if (videoEl) {
                        videoContainer.style.display = 'block';
                        videoEl.style.display = 'block';
                        videoEl.currentTime = 0;
                        if (autoplayEnabled) {
                            videoEl.play().catch(e => console.log('Autoplay bloqueado:', e));
                        }
                    }
 
                } else {
                    videoContainer.style.display = 'none';
                }
 
                cuadros.forEach(c => c.classList.remove('activo'));
                div.classList.add('activo');
            });
            ['data-nome', 'data-desc', 'data-atr', 'data-video'].forEach(attr => div.removeAttribute(attr));
        });
 
        if (Object.keys(videosCache).length === 0) {
            videoContainer.style.display = 'none';
        }
 
        if (cuadros.length) cuadros[0].click();
 
        cuadrosContainer.addEventListener('wheel', e => {
            if (e.deltaY) {
                e.preventDefault();
                cuadrosContainer.scrollLeft += e.deltaY;
            }
        });
 
        function activarFlechasCarrusel() {
            const carousel = document.querySelector('.skins-carousel');
            const wrapper = document.querySelector('.skins-carousel-wrapper');
            const [leftBtn, rightBtn] = ['.skins-arrow.left', '.skins-arrow.right'].map(sel => document.querySelector(sel));
            let isPredictingScroll = false, isAutoScrolling = false;
 
            const getScrollAmount = () => carousel.clientWidth * 0.6;
 
            const hideArrow = btn => {
                if (!btn.classList.contains('desapareciendo') && btn.style.display !== 'none') {
                    btn.classList.add('desapareciendo');
                    setTimeout(() => {
                        btn.style.display = 'none';
                        btn.classList.remove('desapareciendo');
                    }, 300);
                }
            };
 
            const showArrow = btn => {
                if (btn.style.display === 'none') {
                    btn.style.display = 'inline-block';
                    void btn.offsetWidth;
                }
                btn.classList.remove('desapareciendo');
            };
 
            const setArrowsState = scrollLeft => {
                const maxScroll = carousel.scrollWidth - carousel.clientWidth;
                const hasLeft = scrollLeft > 5, hasRight = scrollLeft < maxScroll - 5;
                hasLeft ? showArrow(leftBtn) : hideArrow(leftBtn);
                hasRight ? showArrow(rightBtn) : hideArrow(rightBtn);
                wrapper.classList.toggle('has-left', hasLeft);
                wrapper.classList.toggle('has-right', hasRight);
                if (!hasLeft && !hasRight) { carousel.style.justifyContent = 'center'; } else { carousel.style.justifyContent = ''; }
            };
 
            const handleArrowClick = dir => {
                isPredictingScroll = true;
                const scrollLeft = carousel.scrollLeft, maxScroll = carousel.scrollWidth - carousel.clientWidth;
                const nextScroll = dir === 'left' ? Math.max(0, scrollLeft - getScrollAmount()) : Math.min(maxScroll, scrollLeft + getScrollAmount());
 
                setArrowsState(nextScroll);
                carousel.scrollTo({ left: nextScroll, behavior: 'smooth' });
 
                let last = -1, still = 0;
                const wait = setInterval(() => {
                    const current = Math.round(carousel.scrollLeft);
                    if (current === last) {
                        if (++still >= 2) {
                            clearInterval(wait);
                            isPredictingScroll = false;
                            setArrowsState(current);
                        }
                    } else {
                        last = current;
                        still = 0;
                    }
                }, 50);
            };
 
            carousel.addEventListener('scroll', () => {
                if (!isPredictingScroll) setArrowsState(carousel.scrollLeft);
            });
 
            new ResizeObserver(() => {
                if (!isPredictingScroll) setArrowsState(carousel.scrollLeft);
            }).observe(carousel);
 
            leftBtn.addEventListener('click', () => handleArrowClick('left'));
            rightBtn.addEventListener('click', () => handleArrowClick('right'));
            setArrowsState(carousel.scrollLeft);
        }
        // Resolve o arquivo de forma confiável (cai no /images/... certo)
        function resolveFile(name) {
            if (window.mw && mw.util && typeof mw.util.getUrl === 'function') {
                return mw.util.getUrl('Special:FilePath/' + encodeURIComponent(name));
            }
            return '/index.php/Special:FilePath/' + encodeURIComponent(name);
        }
 
 
        function generarHTMLAtributos(str) {
            const vals = (str || '').split(',').map(v => v.trim());
            const labels = ['Poder PVE', 'Poder PVP', 'Energia', 'Recarga'];
            const icons = ['Attr_PVE.png', 'Attr_PVP.png', 'Attr_Energia.png', 'Attr_Recarga.png'];
 
            // usa Special:FilePath (resolve pro /images/... automaticamente)
            const file = name => '/wiki/Special:FilePath/' + encodeURIComponent(name);
 
            return `
     <div class="attr-cards">
      ${labels.map((t, i) => {
                const raw = vals[i] ?? '-';
                let v = raw === '-' ? '-' : parseInt(raw, 10);
                if (i === 2 && v !== '-' && !Number.isNaN(v)) v = (v > 0 ? '+' : '') + v;    // energia com sinal
                const suf = (i === 3 && raw !== '-' && !Number.isNaN(parseInt(raw, 10))) ? ' seg' : '';
                return `
          <div class="attr-card">
            <div class="attr-card__header">
              <img class="attr-card__icon" src="${file(icons[i])}" alt="${t}" width="28" height="28" loading="lazy" decoding="async">
              <span class="attr-card__label">${t}</span>
            </div>
            <div class="attr-card__value">${v}${suf}</div>
          </div>
        `;
            }).join('')}
    </div>`;
        }
 
    })();
</script>
 
<style>
    /* --------- Resetzinhos úteis ---------- */
    img {
        pointer-events: none;
        user-select: none;
    }
 
    video {
        max-height: 33.25em;
        object-fit: fill;
    }
 
    .mw-body {
        padding: unset !important;
    }
 
    .mw-body-content {
        line-height: 1.5 !important;
    }
 
    .mw-body-content p {
        display: none;
    }
 
    /* --------- Banner de fundo do topo ---------- */
    .banner {
        position: absolute;
        z-index: -9;
        width: 100%;
        height: 100%;
        background-image: url(https://i.imgur.com/OVGhLvl.png);
        background-size: cover;
    }
 
    .banner-personaje {
        width: 100%;
        height: auto;
    }
 
    .banner::before {
        content: "";
        position: absolute;
        inset: 0;
         background: linear-gradient(to right, rgba(0, 0, 0, .6), rgba(0, 0, 0, .2));
    }
 
    /* --------- Caixa geral ---------- */
    .personaje-box {
        padding: unset !important;
        color: #000;
        font-family: 'Noto Sans', sans-serif !important;
        width: 100%;
        margin: auto;
        position: relative;
        user-select: none;
    }
 
    .personaje-box p {
        display: unset;
    }
 
    /* --------- Topbar ---------- */
    .personaje-topbar {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        padding: 8px 20px;
        padding-top: 4px;
    }
 
    .personaje-nome-box {
        display: flex;
        align-items: center;
        gap: 14px;
    }
 
    .topbar-icon {
        margin-top: 8px;
        width: 100px;
        height: 100px;
        object-fit: none;
    }
 
    .nome {
        text-shadow: 0 0 6px #000, 0 0 9px #000;
        color: #fff;
        font-size: 56px;
        font-family: 'Orbitron', sans-serif;
        font-weight: 900;
    }
 
    .topbar-description {
        display: none !important;
        font-size: 16px;
        margin-top: 6px;
        width: fit-content;
        padding-inline: 16px;
        border-radius: 0 10px 10px 0;
        box-shadow: 0 0 2px rgb(0 0 0 / 70%);
    }
 
    .personaje-header {
        position: relative;
        overflow: hidden;
        display: flex;
        gap: 10px;
        flex-direction: column;
    }
 
    /* Arte do personagem – fica dentro do header e por trás do conteúdo */
    .art-personaje {
        width: 34.3vw;
        height: auto;
        position: absolute;
        right: 3.5rem;
        top: -3.1rem;
        z-index: 1;
        pointer-events: none;
    }
 
    .classes {
        display: flex;
        gap: 9px;
        flex-wrap: wrap;
        margin-left: .28rem;
    }
 
    .classe {
        background: #353420;
        color: #fff;
        outline: 2px solid #000;
        padding: 1px 6px;
        border-radius: 4px;
        font-size: .9em;
        font-weight: bold;
        box-shadow: 0 0 2px rgb(0 0 0 / 70%);
    }
 
    .personaje-info {
        user-select: none;
    }
 
    .personaje-info .tier,
    .personaje-info .classe {
        font-size: 18px;
        color: #bbb;
    }
 
    /* --------- Abas ---------- */
    .personaje-tabs {
        margin: 4px 0 4px 8px;
        display: flex;
        gap: 12px;
        justify-content: flex-start;
    }
 
    .tab-btn {
        padding: 5px 20px;
        background: #333;
        color: #fff;
        border: 2px solid transparent;
        border-radius: 8px;
        font-size: 20px;
        cursor: pointer;
        font-weight: 600;
        line-height: 1;
        transition: background .15s ease, border-color .15s ease;
    }
 
    .tab-btn.active {
        background: #156bc7;
        border-color: #156bc7;
    }
 
    .tab-content {
        display: none;
        background: #26211cd6;
        padding: 0 8px 8px;
        position: relative;
        z-index: 3;
    }
 
    .tab-content.active {
        display: block;
    }
 
    /* --------- Habilidades ---------- */
    .habilidades-container {
        display: flex;
        gap: 20px;
    }
 
    .habilidades-details {
        flex: 1;
        display: flex;
        flex-direction: column;
        gap: 10px;
        width: 50%;
        justify-content: center;
    }
 
    /* Barra dos ícones – ocupa toda a largura e fica acima da arte */
    .cuadros-container {
        display: flex;
        flex-wrap: nowrap;
        gap: 10px;
        width: 100%;
        overflow-x: auto;
        overflow-y: hidden;
        padding: 10px 0 3px 1px;
        position: relative;
        z-index: 4;
        margin-bottom: 6px;
        scrollbar-width: thin;
        scrollbar-color: #ababab transparent;
        scroll-behavior: smooth;
        justify-content: flex-start;
    }
 
    .cuadros-container::-webkit-scrollbar {
        height: 6px;
    }
 
    .cuadros-container::-webkit-scrollbar-track {
        background: transparent;
    }
 
    .cuadros-container::-webkit-scrollbar-thumb {
        background-color: #151515;
        border-radius: 3px;
    }
 
    .cuadros-container .cuadro {
        flex: 0 0 auto;
        width: 50px;
        height: 50px;
        border-radius: 5px;
        cursor: pointer;
        transition: transform .2s, box-shadow .2s;
    }
 
    .cuadros-container .cuadro.activo {
        box-shadow: 0 0 0 1.5px #FFD700;
    }
 
    .cuadro img {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }
 
    /* Título e tooltip */
    .titulo-habilidad {
        position: relative;
        display: flex;
        justify-content: center;
        align-items: center;
        margin-bottom: 8px;
        padding-right: 32px;
    }
 
    .titulo-habilidad h3 {
        font-size: 1.6em;
        color: #fff;
        text-align: center;
        margin: 0;
        width: 100%;
    }
 
    .tooltip-container {
        position: absolute;
        right: 0;
        top: 50%;
        transform: translateY(-50%);
    }
 
    .info-btn {
        border: none;
        color: #D3DBDC;
        background: #787878;
        font-weight: bold;
        border-radius: 50%;
        width: 44px;
        height: 44px;
        font-family: 'Noto Sans';
        cursor: pointer;
        transition: .2s;
        box-shadow: 0 0 3px #000;
        font-size: 40px;
        padding: 0;
        line-height: 24px;
        text-align: center;
    }
 
    .tooltip-text {
        visibility: hidden;
        width: 220px;
        background: #222;
        color: #fff;
        text-align: left;
        padding: 8px 10px;
        border-radius: 8px;
        position: absolute;
        z-index: 10;
        bottom: 130%;
        left: 50%;
        transform: translate(-85%, 110%);
        opacity: 0;
        transition: opacity .3s;
        font-size: 12px;
         box-shadow: 0 2px 10px rgba(0, 0, 0, .5);
        pointer-events: none;
    }
 
    .tooltip-container:hover .tooltip-text {
        visibility: visible;
        opacity: 1;
    }
 
    /* Descrição da habilidade */
    .descripcion-container {
        min-height: 27.5rem;
        height: 100%;
        padding: 4px 16px !important;
        background: #26211C;
        border-radius: 8px;
        position: relative;
        box-shadow: 0 6px 18px rgba(0, 0, 0, .28);
        color: #fff;
        backdrop-filter: blur(2px);
        transition: all .3s ease;
        text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
        padding-top: 0 !important;
        z-index: 99;
    }
 
    .descripcion-container h3 {
        font-size: 2.7em;
        margin: 0;
        text-align: center;
        padding-top: 0;
    }
 
    .descripcion-container p,
    .desc {
        font-size: 1.2em;
        margin: 0;
    }
 
    .desc {
        overflow-y: auto !important;
        max-height: inherit;
        margin-top: 10px;
    }
 
    .desc * {
        font-size: inherit !important;
        line-height: inherit;
    }
 
    .descripcion-container .descLevel {
        margin-top: 5px;
        font-weight: bold;
    }
 
    .descripcion-container .desc::-webkit-scrollbar,
    .tabSkill--container::-webkit-scrollbar {
        width: 7px;
        height: 7px;
    }
 
    .descripcion-container .desc::-webkit-scrollbar-thumb,
    .tabSkill--container::-webkit-scrollbar-thumb {
        background-color: rgb(71 153 255);
        border-radius: 10px;
    }
 
    .descripcion-container .desc::-webkit-scrollbar-track,
    .tabSkill--container::-webkit-scrollbar-track {
        background-color: #151515a8;
        border-radius: 10px;
    }
 
    /* Tiers */
    .tier-bronze .topbar-icon,
    .tier-bronze .tier {
        outline: 2px solid #7b4e2f !important;
    }
 
    .tier-silver .topbar-icon,
    .tier-silver .tier {
        outline: 2px solid #d6d2d2 !important;
    }
 
    .tier-gold .topbar-icon,
    .tier-gold .tier {
        outline: 2px solid #fcd300 !important;
    }
 
    .tier-diamond .topbar-icon,
    .tier-diamond .tier {
        outline: 2px solid #60dae2 !important;
    }
 
    /* Vídeo da habilidade */
    video::-webkit-media-controls {
        opacity: 0;
        transition: opacity .3s;
    }
 
    video:hover::-webkit-media-controls {
        opacity: 1;
    }
 
    .video-container {
        position: relative;
        width: 43%;
        background: #000;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 2%;
        box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
        overflow: hidden;
        z-index: 999;
    }
 
    .video-placeholder {
        position: absolute;
        inset: 0;
        background: #000;
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 2;
        opacity: 1;
        transition: opacity .9s ease;
    }
 
    .video-placeholder img {
        width: 120px;
        height: auto;
        animation: breathe 2.5s ease-in-out infinite;
        filter: drop-shadow(0 0 6px rgba(255, 255, 255, .3));
    }
 
    .video-placeholder.fade-out {
        opacity: 0;
    }
 
    @keyframes breathe {
 
        0%,
        100% {
            transform: scale(1);
            opacity: 1;
        }
 
        50% {
            transform: scale(1.07);
            opacity: .85;
        }
    }
 
    /* ===== Atributos (cards) ===== */
    .attr-cards {
        display: flex;
        flex-wrap: wrap;
        gap: 16px;
        justify-content: center;
        margin: 6px 0 12px;
    }
 
    .descripcion-container .attr-card {
        background: #3b312f;
        border: 1px solid rgba(0, 0, 0, .25);
        border-radius: 12px;
        padding: 10px 12px;
        min-width: 150px;
        box-shadow: 0 4px 10px rgba(0, 0, 0, .25);
        text-shadow: none;
        font-family: 'Noto Sans', sans-serif;
    }
 
    .descripcion-container .attr-card * {
        text-shadow: none;
    }
 
    .attr-card__header {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 8px;
        line-height: 1;
    }
 
    .attr-card__icon {
        width: 28px;
        height: 28px;
        display: block;
        flex: 0 0 28px;
    }
 
    .attr-card__label {
        color: #fff;
        font-weight: 700;
        letter-spacing: .2px;
        font-size: 1rem;
    }
 
    .attr-card__value {
        margin-top: 8px;
        text-align: center;
        color: #fff;
        font-weight: 800;
        font-size: 1.25rem;
        letter-spacing: .02em;
    }
 
    /* Mobile / telas altas: pode ocultar ícone e aumentar fontes */
    @media (max-aspect-ratio: 3/4) {
        .attr-card__icon {
            display: none;
        }
 
        .attr-card__label {
            font-size: 1.3rem;
        }
 
        .attr-card__value {
            font-size: 1.5rem;
        }
    }
 
    /* --------- Skins ---------- */
    .attribute-title,
    .card-skins-title {
        font-size: 1.4em;
        text-align: center;
        letter-spacing: 1px;
        font-family: 'Noto Sans', sans-serif !important;
        border-bottom: 2px solid #9d9c9c;
        color: #fff !important;
        padding-bottom: 8px;
        margin-bottom: 16px;
        width: 75%;
    }
 
    .card-skins {
        padding-block: 12px;
        border-radius: 12px;
        user-select: none;
    }
 
    .skins-carousel-wrapper {
        min-height: 21.1rem;
        max-height: 60%;
        padding: 0 16px 1px !important;
        background: #26211C;
        border-radius: 8px;
        position: relative;
        box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
        color: #fff;
        backdrop-filter: blur(2px);
        transition: all .3s ease;
        text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
        flex: 1;
        display: flex;
        flex-direction: row;
        gap: 10px;
        justify-content: center;
        align-items: center;
        overflow: visible;
        z-index: 99;
    }
 
    /* Gradientes laterais quando houver rolagem */
    .skins-carousel-wrapper::before,
    .skins-carousel-wrapper::after {
        content: '';
        position: absolute;
        top: 0;
        width: 60px;
        height: 100%;
        pointer-events: none;
        opacity: 0;
        transition: opacity .4s ease;
        z-index: 3;
    }
 
    .skins-carousel-wrapper::before {
        left: 0;
        background: linear-gradient(to right, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 100%);
    }
 
    .skins-carousel-wrapper::after {
        right: 0;
        background: linear-gradient(to left, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 100%);
    }
 
    .skins-carousel-wrapper.has-left::before,
    .skins-carousel-wrapper.has-right::after {
        opacity: 1;
    }
 
    .has-left {
        padding-left: 60px;
    }
 
    .has-left .skins-carousel {
        mask-image: linear-gradient(to right, transparent 0px, black 40px, black 100%);
    }
 
    .has-right {
        padding-right: 60px;
    }
 
    .has-right .skins-carousel {
        mask-image: linear-gradient(to right, black 0px, black calc(100% - 40px), transparent 100%);
    }
 
    .card-skins-title {
        display: block;
        border-bottom: unset;
        font-size: 40px;
        font-weight: bold;
        padding-bottom: unset;
        margin-bottom: 10px;
        width: 47%;
    }
 
    .skins-carousel {
        display: flex;
        gap: 1vw;
        overflow-x: auto;
        scroll-behavior: smooth;
        padding: 10px 0;
        flex-grow: 1;
    }
 
    .skins-carousel.both-mask {
        mask-image: linear-gradient(to right, transparent 0px, black 40px, black calc(100% - 40px), transparent 100%);
    }
 
    .skins-carousel.left-mask {
        mask-image: linear-gradient(to right, transparent 0px, black 40px, black 100%);
    }
 
    .skins-carousel.right-mask {
        mask-image: linear-gradient(to right, black 0px, black calc(100% - 40px), transparent 100%);
     }
     }
    return mw.text.jsonEncode(obj)
end


function p.skill(frame)
    .skins-carousel.no-mask {
    local a = frame.args
         mask-image: none;
    local obj = {
         name = a.name or a.nome or '',
        icon = a.icon or '',
        level = tonumber(a.level) or nil,
        desc = a.desc or '',
        energy = a.energy or nil,
        powerpve = a.powerpve or nil,
        powerpvp = a.powerpvp or nil,
        cooldown = a.cooldown or nil,
        video = a.video or ''
     }
     }
    return mw.text.jsonEncode(obj)
end


function p.generate(frame)
     .skins-carousel::-webkit-scrollbar {
     local args = frame:getParent().args
         display: none;
    local html = mw.html.create('div')
    local function getVideoURL(filename)
        return tostring(mw.uri.fullUrl('Special:FilePath/' .. filename))
    end
    local tier = (args.tier or ""):lower()
    local tierMap = {
        bronze = "tier-bronze",
        bronce = "tier-bronze",
         silver = "tier-silver",
        prata = "tier-silver",
        gold = "tier-gold",
        ouro = "tier-gold",
        diamond = "tier-diamond",
        diamante = "tier-diamond"
     }
     }
    local tierClass = tierMap[tier]
    local box = html:tag('div'):addClass('personaje-box')
    if tierClass then
        box:addClass(tierClass)
    end
    local header = box:tag('div'):addClass('personaje-header')
    local topbar = header:tag('div'):addClass('personaje-topbar')
    local nomeBox = topbar:tag('div'):addClass('personaje-nome-box')


     local avatarImg = args.avatar or 'Franky_ts_medal.png'
     .skins-arrow {
    nomeBox:wikitext(string.format('[[Arquivo:%s|class=topbar-icon|link=|alt=Medal]]', avatarImg))
        background: none;
        border: none;
        color: #fff;
        font-size: 36px;
        cursor: pointer;
        padding: 8px;
        z-index: 5;
        transition: opacity .3s ease, transform .3s ease;
    }


     local nomeCat = nomeBox:tag('div'):addClass('personaje-nome-category')
     .skins-arrow.left {
    nomeCat:tag('div'):addClass('nome'):wikitext(args.nome or 'Franky (TS)')
        margin-right: 8px;
    local classesDiv = nomeCat:tag('div'):addClass('classes')
     }
    -- Dividir clases por "/"
 
     local classeString = args.classe or ''
     .skins-arrow.right {
    local tierUpper = tier:gsub("^%l", string.upper)
         margin-left: 8px;
     classesDiv:tag('div'):addClass('classe tier'):wikitext(tierUpper)
     }
    for classe in mw.text.gsplit(classeString, '/', true) do
         classesDiv:tag('div'):addClass('classe'):wikitext(classe)
     end


     header:tag('div'):addClass('topbar-description'):wikitext(args.desc)
     .skins-arrow.hidden {
        opacity: 0;
        transform: scale(.8);
        pointer-events: none;
        visibility: hidden;
    }


     local banner = args.banner or ''
     .skin-card {
    local bannerFile = mw.title.new('Arquivo:' .. banner)
        position: relative;
    if bannerFile and bannerFile.exists then
        width: 12vw;
         header:tag('div'):addClass('banner'):wikitext(string.format(
         height: 39vh;
            '[[Arquivo:%s|class=banner-personaje|link=|alt=Artwork do personagem]]', banner))
        flex: 0 0 auto;
    else
        border: 2px solid #697EC9 !important;
         header:tag('div'):addClass('banner')
        border-radius: 8px;
     end
        overflow: hidden;
         box-shadow: 0 2px 10px rgba(0, 0, 0, .25);
        background: #111;
     }


     local tabs = header:tag('div'):addClass('personaje-tabs')
     .skin-card::before {
    tabs:tag('div'):addClass('tab-btn active'):attr('data-tab', 'habilidades'):wikitext('Habilidades')
        content: '';
    tabs:tag('div'):addClass('tab-btn'):attr('data-tab', 'skins'):wikitext('Skins')
        position: absolute;
        inset: 0;
        pointer-events: none;
        border-radius: inherit;
        z-index: 2;
        box-shadow: inset 0 0 8px rgba(180, 180, 180, .18);
    }


     local artImg = args.artwork or 'Franky_ts_splash.png'
     .skins--imageBanner {
    header:tag('div'):css('text-align', 'center'):wikitext(string.format(
        width: 100%;
         '[[Arquivo:%s|class=art-personaje|link=|alt=Arte do personagem]]', artImg))
         height: 109%;
    }


     -- HABILIDADE
     .skins--imageBanner img {
    local habilidadesTab = box:tag('div'):addClass('tab-content active'):attr('id', 'habilidades')
        width: 100%;
    local cuadros = habilidadesTab:tag('div'):addClass('cuadros-container')
        height: 100%;
     local habilidadesContainer = habilidadesTab:tag('div'):addClass('habilidades-container')
        object-fit: cover;
        filter: brightness(.5);
        scale: 1.1;
     }


     local details = habilidadesContainer:tag('div'):addClass('habilidades-details')
     .skins--imageSkin img {
    local descripcionContainer = details:tag('div'):addClass('descripcion-container')
        position: absolute;
    -- ====== NOVO: bloco de skills via subtemplate ======
        bottom: 10px;
    local skillsPacked = args.skills
         left: 50%;
    local usedSkills = false
         transform: translateX(-50%);
    if skillsPacked and skillsPacked:match("{") then
         height: 140px;
         -- Concat de objetos JSON: ...}{...}{...  -> ...},{...},{...
         width: auto;
         local arr = "[" .. skillsPacked:gsub("}%s*{", "},{") .. "]"
        z-index: 2;
         local ok, parsed = pcall(mw.text.jsonDecode, arr)
        transition: transform .2s;
         if ok and type(parsed) == "table" and #parsed > 0 then
    }
            usedSkills = true
            for i, sk in ipairs(parsed) do
                local nome = sk.name or sk.nome
                if nome and nome ~= "" then
                    local icon = sk.icon or ""
                    local level = sk.level or ""
                    local desc = sk.desc or ""
                    -- monta a string de atributos no formato esperado pelo JS:
                    -- PVE, PVP, Energia, Recarga
                    local atr = table.concat({sk.powerpve or "-", sk.powerpvp or "-", sk.energy or "-",
                                              sk.cooldown or "-"}, ", ")


                    local rawVideo = sk.video or ""
    /* --------- Responsivo (tela “alta”/mobile) ---------- */
                    local videoURL = rawVideo ~= "" and getVideoURL(rawVideo) or ""
    @media (max-aspect-ratio: 3/4) {
        .desc {
            font-size: 26px;
            line-height: 1.5;
            overflow-y: auto !important;
            max-height: inherit;
            margin: 0;
            width: 100%;
            margin-top: 8px;
        }


                    cuadros:tag('div'):addClass('cuadro'):attr('data-index', i):attr('data-nome', nome):attr(
        .desc * {
                        'data-desc', desc):attr('data-atr', atr):attr('data-video', videoURL):attr('data-video-preload',
            font-size: inherit !important;
                        'auto'):wikitext(string.format("[[Arquivo:%s|class=habilidad-icon|link=]]", icon))
            line-height: inherit;
        }


                    descripcionContainer:tag('div'):addClass('habilidad-descripcion'):attr('data-index', i)
        .habilidades-container {
                end
            display: flex;
            end
            gap: 20px;
         end
            flex-direction: column-reverse;
    end
         }


    -- ====== Fallback: mantém suporte aos hab1..hab21 se não usar 'skills' ======
        .habilidades-details {
    if not usedSkills then
            flex: 1;
        for i = 1, 21 do
             display: flex;
             local nome = args['hab' .. i .. '-nome']
             flex-direction: column;
             if nome then
            width: 96%;
                local icon = args['hab' .. i .. '-icon'] or ''
            align-self: center;
                local level = args['hab' .. i .. '-level'] or ''
        }
                local desc = args['hab' .. i .. '-desc'] or ''
                local atr = args['hab' .. i .. '-atr'] or ''
                local rawVideo = args['hab' .. i .. '-video'] or ''
                local videoURL = rawVideo ~= '' and getVideoURL(rawVideo) or ''


                cuadros:tag('div'):addClass('cuadro'):attr('data-index', i):attr('data-nome', nome):attr('data-desc',
        .video-container {
                    desc):attr('data-atr', atr):attr('data-video', videoURL):attr('data-video-preload', 'auto')
            width: 80%;
                    :wikitext(string.format("[[Arquivo:%s|class=habilidad-icon|link=]]", icon))
            border-radius: 3%;
            margin-top: 2%;
            align-self: center;
        }


                descripcionContainer:tag('div'):addClass('habilidad-descripcion'):attr('data-index', i)
        .art-personaje {
             end
            display: none;
         end
            width: 370px;
    end
            height: 290px;
            position: absolute;
            right: .5rem;
            top: 1.1rem;
            z-index: 1;
             pointer-events: none;
         }


    for i = 1, 21 do
         .topbar-description {
        local nome = args['hab' .. i .. '-nome']
             font-size: 22px;
         if nome then
        }
            local icon = args['hab' .. i .. '-icon'] or ''
             local level = args['hab' .. i .. '-level'] or ''
            local desc = args['hab' .. i .. '-desc'] or ''
            local atr = args['hab' .. i .. '-atr'] or ''
            local rawVideo = args['hab' .. i .. '-video'] or ''
            local videoURL = rawVideo ~= '' and getVideoURL(rawVideo) or ''


            cuadros:tag('div'):addClass('cuadro'):attr('data-index', i):attr('data-nome', nome):attr('data-desc', desc)
        .personaje-info .tier,
                :attr('data-atr', atr):attr('data-video', videoURL):attr('data-video-preload', 'auto'):wikitext(
        .personaje-info .classe {
                    string.format("[[Arquivo:%s|class=habilidad-icon|link=]]", icon))
            font-size: 30px;
        }


             descripcionContainer:tag('div'):addClass('habilidad-descripcion'):attr('data-index', i)
        .cuadros-container {
         end
             width: 98%;
    end
            place-self: center;
            padding: 10px 0 16px 1px;
         }


    details:done()
        .cuadros-container .cuadro {
    habilidadesContainer:tag('div'):addClass('video-container'):done()
            width: 80px;
    habilidadesTab:done()
            height: 80px;
        }


    -- SKINS
        .descripcion-container h3 {
    local skinsTab = box:tag('div'):addClass('tab-content'):attr('id', 'skins')
            font-size: 3.6em;
    local cardSkins = skinsTab:tag('div'):addClass('card-skins')
            margin-top: -14px;
        }


    cardSkins:tag('span'):addClass('card-skins-title'):wikitext('SKINS & SPOTLIGHTS')
        .descripcion-container p {
            font-size: 2.3em;
            margin-bottom: 5px;
        }


    local wrapper = cardSkins:tag('div'):addClass('skins-carousel-wrapper')
        .descripcion-container {
    wrapper:tag('div'):addClass('skins-arrow left'):wikitext('«')
            padding: 22px !important;
        }


    local carousel = wrapper:tag('div'):addClass('skins-carousel')
        .tab-btn {
    -- ====== NOVO: bloco de skins via subtemplate (robusto) ======
            padding: 10px 20px;
    local skinsPacked = args.skins
            font-size: 26px;
    local usedSkins = false
         }
    if skinsPacked and skinsPacked:find("{", 1, true) then
        local count = 0
         for obj in skinsPacked:gmatch("%b{}") do
            local ok, sk = pcall(mw.text.jsonDecode, obj)
            if ok and type(sk) == "table" then
                count = count + 1
                local banner = sk.background or ''
                local image = sk.sprite or ''
                local tooltipRaw = sk.tooltip or ''
                local tooltipHtml = tooltipRaw:gsub("'''([^']+)'''", "<b>%1</b>"):gsub("\n", "<br>")


                local skinCard = carousel:tag('div'):addClass(
        .tab-content {
                    'skin-card simple-tooltip simple-tooltip-inline tooltipstered'):attr('data-simple-tooltip',
            position: relative;
                    tooltipHtml)
            z-index: 1;
            padding: 0 8px 20px;
        }


                skinCard:tag('div'):addClass('skins--imageBanner'):wikitext(banner ~= '' and
        .classe {
                                                                                string.format("[[Arquivo:%s|link=]]",
            padding: 0 5px;
                        banner) or ''):attr('alt', 'banner')
            font-size: 1.4em;
        }


                skinCard:tag('div'):addClass('skins--imageSkin'):wikitext(image ~= '' and
        /* chips maiores no mobile */
                                                                              string.format("[[Arquivo:%s|link=]]",
        .attr-chips {
                        image) or ''):attr('alt', 'skin')
             gap: 14px;
             end
         }
         end
        if count > 0 then
            usedSkins = true
        end
    end


    -- ====== Fallback antigo (só roda se não vierem skins novas) ======
         .attr-chip {
    if not usedSkins then
             padding: 10px 14px;
         for j = 1, 11 do
            border-radius: 12px;
            local image = args['skin' .. j .. '-image']
        }
             if image then
                local banner = args['skin' .. j .. '-banner'] or ''
                local tooltipRaw = args['skin' .. j .. '-tooltip'] or ''
                local tooltipHtml = tooltipRaw:gsub("'''([^']+)'''", "<b>%1</b>"):gsub("\n", "<br>")


                local skinCard = carousel:tag('div'):addClass(
        .attr-label,
                    'skin-card simple-tooltip simple-tooltip-inline tooltipstered'):attr('data-simple-tooltip',
        .attr-value {
                    tooltipHtml)
            font-size: 1.3rem;
        }


                skinCard:tag('div'):addClass('skins--imageBanner'):wikitext(banner ~= '' and
        .skins-carousel {
                                                                                string.format("[[Arquivo:%s|link=]]",
            gap: 20px;
                        banner) or ''):attr('alt', 'banner')
        }


                skinCard:tag('div'):addClass('skins--imageSkin'):wikitext(string.format("[[Arquivo:%s|link=]]", image))
        .skin-card {
                    :attr('alt', 'skin')
            width: 236px;
             end
             height: 400px;
         end
         }
    end


    for j = 1, 11 do
         .skins--imageSkin img {
         local image = args['skin' .. j .. '-image']
             height: 170px;
        if image then
        }
            local banner = args['skin' .. j .. '-banner'] or ''
             local tooltip = args['skin' .. j .. '-tooltip'] or ''
            local tooltipRaw = args['skin' .. j .. '-tooltip'] or ''
            local tooltipHtml = tooltipRaw:gsub("'''([^']+)'''", "<b>%1</b>")
            tooltipHtml = tooltipHtml:gsub("\n", "<br>")


             local skinCard = carousel:tag('div')
        .tooltipster-content {
                :addClass('skin-card simple-tooltip simple-tooltip-inline tooltipstered'):attr('data-simple-tooltip',
             font-size: 26px;
                    tooltipHtml)
        }


            skinCard:tag('div'):addClass('skins--imageBanner'):wikitext(string.format("[[Arquivo:%s|link=]]", banner))
        .attribute-title,
                :attr('alt', 'banner')
        .card-skins-title {
            width: 100% !important;
        }


            skinCard:tag('div'):addClass('skins--imageSkin'):wikitext(string.format("[[Arquivo:%s|link=]]", image))
        .skins-arrow {
                :attr('alt', 'skin')
            display: none !important;
         end
         }
    end


    wrapper:tag('div'):addClass('skins-arrow right'):wikitext('»')
        .skins-carousel-wrapper::after,
        .skins-carousel-wrapper::before {
            background: unset;
        }


    return tostring(html)
        video::-webkit-media-controls {
end
            opacity: unset;
            transition: unset;
        }


return p
        video:hover::-webkit-media-controls {
            opacity: unset;
        }
    }
</style>

Edição das 22h42min de 18 de agosto de 2025

<script>

   (function () {
       const buttons = document.querySelectorAll('.tab-btn');
       const contents = document.querySelectorAll('.tab-content');
       const cuadrosContainer = document.querySelector('.cuadros-container');
       const descripcionContainer = document.querySelector('.descripcion-container');
       const videoContainer = document.querySelector('.video-container');
       const cuadros = [...cuadrosContainer.querySelectorAll('.cuadro')];
       const mwBody = document.querySelector('.personaje-box');
       let totalVideos = 0;
       let loadedVideos = 0;
       const videosCache = {};
       let autoplayEnabled = false;
       activarFlechasCarrusel();
       const placeholder = document.createElement('div');
       placeholder.className = 'video-placeholder';
       placeholder.innerHTML = `<img src="/images/d/d5/Icon_gla.png" alt="Cargando...">`;
       videoContainer.appendChild(placeholder);
       function removePlaceholderSmooth() {
           placeholder.classList.add('fade-out');
           placeholder.addEventListener('transitionend', () => placeholder.remove(), { once: true });
       }
       function checkAllVideosLoaded() {
           if (loadedVideos === totalVideos && totalVideos > 0) {
               autoplayEnabled = true;
           }
       }
       // Pré-carregar todos os vídeos
       cuadros.forEach(div => {
           const videoSrc = div.dataset.video;
           const index = div.dataset.index;
           if (videoSrc && videoSrc.trim() !==  && !videosCache[index]) {
               totalVideos++;
               const videoEl = document.createElement('video');
               videoEl.setAttribute('width', '100%');
               videoEl.setAttribute('controls', );
               videoEl.setAttribute('preload', 'auto');
               videoEl.setAttribute('playsinline', );
               videoEl.dataset.index = index;
               videoEl.style.display = 'none';
               const source = document.createElement('source');
               source.src = videoSrc;
               source.type = 'video/webm';
               videoEl.appendChild(source);
               // Quando o vídeo já estiver pronto, remover placeholder
               videoEl.addEventListener('canplay', () => {
                   loadedVideos++;
                   if (loadedVideos === 1) {
                       videoEl.pause();
                       videoEl.currentTime = 0;
                   }
                   const activeCuadro = document.querySelector('.cuadro.activo');
                   if (activeCuadro && activeCuadro.dataset.index === videoEl.dataset.index) {
                       setTimeout(removePlaceholderSmooth, 200);
                   }
                   checkAllVideosLoaded();
               });


               videoEl.addEventListener('error', () => {
                   loadedVideos++;
                   removePlaceholderSmooth();
                   checkAllVideosLoaded();
               });
               videoContainer.appendChild(videoEl);
               videosCache[index] = videoEl;
           }
       });
       // Se não houver vídeos, ocultar imediatamente
       if (totalVideos === 0) {
           placeholder.remove();
       }
       buttons.forEach(btn => btn.addEventListener('click', () => {
           buttons.forEach(b => b.classList.remove('active'));
           contents.forEach(c => c.classList.remove('active'));
           btn.classList.add('active');
           document.getElementById(btn.dataset.tab).classList.add('active');
       }));
       cuadros.forEach(div => {
           const nome = div.dataset.nome;
           const desc = div.dataset.desc.replace(/(.*?)/g, '$1');
           const atr = div.dataset.atr;
           const index = div.dataset.index;
           const hasVideo = div.dataset.video && div.dataset.video.trim() !== ;
           div.title = nome;
           div.addEventListener('click', () => {
               if (!autoplayEnabled && loadedVideos > 0) {
                   autoplayEnabled = true;
               }
               descripcionContainer.innerHTML = `

${nome}

               ${generarHTMLAtributos(atr)}
${desc}
           `;
               Object.values(videosCache).forEach(v => {
                   v.pause();
                   v.style.display = 'none';
               });
               // Gerenciar habilidades com/sem vídeo
               if (hasVideo) {
                   const videoEl = videosCache[index];
                   if (videoEl) {
                       videoContainer.style.display = 'block';
                       videoEl.style.display = 'block';
                       videoEl.currentTime = 0;
                       if (autoplayEnabled) {
                           videoEl.play().catch(e => console.log('Autoplay bloqueado:', e));
                       }
                   }
               } else {
                   videoContainer.style.display = 'none';
               }
               cuadros.forEach(c => c.classList.remove('activo'));
               div.classList.add('activo');
           });
           ['data-nome', 'data-desc', 'data-atr', 'data-video'].forEach(attr => div.removeAttribute(attr));
       });
       if (Object.keys(videosCache).length === 0) {
           videoContainer.style.display = 'none';
       }
       if (cuadros.length) cuadros[0].click();
       cuadrosContainer.addEventListener('wheel', e => {
           if (e.deltaY) {
               e.preventDefault();
               cuadrosContainer.scrollLeft += e.deltaY;
           }
       });
       function activarFlechasCarrusel() {
           const carousel = document.querySelector('.skins-carousel');
           const wrapper = document.querySelector('.skins-carousel-wrapper');
           const [leftBtn, rightBtn] = ['.skins-arrow.left', '.skins-arrow.right'].map(sel => document.querySelector(sel));
           let isPredictingScroll = false, isAutoScrolling = false;
           const getScrollAmount = () => carousel.clientWidth * 0.6;
           const hideArrow = btn => {
               if (!btn.classList.contains('desapareciendo') && btn.style.display !== 'none') {
                   btn.classList.add('desapareciendo');
                   setTimeout(() => {
                       btn.style.display = 'none';
                       btn.classList.remove('desapareciendo');
                   }, 300);
               }
           };
           const showArrow = btn => {
               if (btn.style.display === 'none') {
                   btn.style.display = 'inline-block';
                   void btn.offsetWidth;
               }
               btn.classList.remove('desapareciendo');
           };
           const setArrowsState = scrollLeft => {
               const maxScroll = carousel.scrollWidth - carousel.clientWidth;
               const hasLeft = scrollLeft > 5, hasRight = scrollLeft < maxScroll - 5;
               hasLeft ? showArrow(leftBtn) : hideArrow(leftBtn);
               hasRight ? showArrow(rightBtn) : hideArrow(rightBtn);
               wrapper.classList.toggle('has-left', hasLeft);
               wrapper.classList.toggle('has-right', hasRight);
               if (!hasLeft && !hasRight) { carousel.style.justifyContent = 'center'; } else { carousel.style.justifyContent = ; }
           };
           const handleArrowClick = dir => {
               isPredictingScroll = true;
               const scrollLeft = carousel.scrollLeft, maxScroll = carousel.scrollWidth - carousel.clientWidth;
               const nextScroll = dir === 'left' ? Math.max(0, scrollLeft - getScrollAmount()) : Math.min(maxScroll, scrollLeft + getScrollAmount());
               setArrowsState(nextScroll);
               carousel.scrollTo({ left: nextScroll, behavior: 'smooth' });
               let last = -1, still = 0;
               const wait = setInterval(() => {
                   const current = Math.round(carousel.scrollLeft);
                   if (current === last) {
                       if (++still >= 2) {
                           clearInterval(wait);
                           isPredictingScroll = false;
                           setArrowsState(current);
                       }
                   } else {
                       last = current;
                       still = 0;
                   }
               }, 50);
           };
           carousel.addEventListener('scroll', () => {
               if (!isPredictingScroll) setArrowsState(carousel.scrollLeft);
           });
           new ResizeObserver(() => {
               if (!isPredictingScroll) setArrowsState(carousel.scrollLeft);
           }).observe(carousel);
           leftBtn.addEventListener('click', () => handleArrowClick('left'));
           rightBtn.addEventListener('click', () => handleArrowClick('right'));
           setArrowsState(carousel.scrollLeft);
       }
       // Resolve o arquivo de forma confiável (cai no /images/... certo)
       function resolveFile(name) {
           if (window.mw && mw.util && typeof mw.util.getUrl === 'function') {
               return mw.util.getUrl('Special:FilePath/' + encodeURIComponent(name));
           }
           return '/index.php/Special:FilePath/' + encodeURIComponent(name);
       }


       function generarHTMLAtributos(str) {
           const vals = (str || ).split(',').map(v => v.trim());
           const labels = ['Poder PVE', 'Poder PVP', 'Energia', 'Recarga'];
           const icons = ['Attr_PVE.png', 'Attr_PVP.png', 'Attr_Energia.png', 'Attr_Recarga.png'];
           // usa Special:FilePath (resolve pro /images/... automaticamente)
           const file = name => '/wiki/Special:FilePath/' + encodeURIComponent(name);
           return `
     ${labels.map((t, i) => {
               const raw = vals[i] ?? '-';
               let v = raw === '-' ? '-' : parseInt(raw, 10);
               if (i === 2 && v !== '-' && !Number.isNaN(v)) v = (v > 0 ? '+' : ) + v;    // energia com sinal
               const suf = (i === 3 && raw !== '-' && !Number.isNaN(parseInt(raw, 10))) ? ' seg' : ;
               return `
             <img class="attr-card__icon" src="${file(icons[i])}" alt="${t}" width="28" height="28" loading="lazy" decoding="async">
             ${t}
${v}${suf}
       `;
           }).join()}

`;

       }
   })();

</script>

<style>

   /* --------- Resetzinhos úteis ---------- */
   img {
       pointer-events: none;
       user-select: none;
   }
   video {
       max-height: 33.25em;
       object-fit: fill;
   }
   .mw-body {
       padding: unset !important;
   }
   .mw-body-content {
       line-height: 1.5 !important;
   }
   .mw-body-content p {
       display: none;
   }
   /* --------- Banner de fundo do topo ---------- */
   .banner {
       position: absolute;
       z-index: -9;
       width: 100%;
       height: 100%;
       background-image: url(https://i.imgur.com/OVGhLvl.png);
       background-size: cover;
   }
   .banner-personaje {
       width: 100%;
       height: auto;
   }
   .banner::before {
       content: "";
       position: absolute;
       inset: 0;
       background: linear-gradient(to right, rgba(0, 0, 0, .6), rgba(0, 0, 0, .2));
   }
   /* --------- Caixa geral ---------- */
   .personaje-box {
       padding: unset !important;
       color: #000;
       font-family: 'Noto Sans', sans-serif !important;
       width: 100%;
       margin: auto;
       position: relative;
       user-select: none;
   }
   .personaje-box p {
       display: unset;
   }
   /* --------- Topbar ---------- */
   .personaje-topbar {
       display: flex;
       flex-direction: column;
       align-items: flex-start;
       padding: 8px 20px;
       padding-top: 4px;
   }
   .personaje-nome-box {
       display: flex;
       align-items: center;
       gap: 14px;
   }
   .topbar-icon {
       margin-top: 8px;
       width: 100px;
       height: 100px;
       object-fit: none;
   }
   .nome {
       text-shadow: 0 0 6px #000, 0 0 9px #000;
       color: #fff;
       font-size: 56px;
       font-family: 'Orbitron', sans-serif;
       font-weight: 900;
   }
   .topbar-description {
       display: none !important;
       font-size: 16px;
       margin-top: 6px;
       width: fit-content;
       padding-inline: 16px;
       border-radius: 0 10px 10px 0;
       box-shadow: 0 0 2px rgb(0 0 0 / 70%);
   }
   .personaje-header {
       position: relative;
       overflow: hidden;
       display: flex;
       gap: 10px;
       flex-direction: column;
   }
   /* Arte do personagem – fica dentro do header e por trás do conteúdo */
   .art-personaje {
       width: 34.3vw;
       height: auto;
       position: absolute;
       right: 3.5rem;
       top: -3.1rem;
       z-index: 1;
       pointer-events: none;
   }
   .classes {
       display: flex;
       gap: 9px;
       flex-wrap: wrap;
       margin-left: .28rem;
   }
   .classe {
       background: #353420;
       color: #fff;
       outline: 2px solid #000;
       padding: 1px 6px;
       border-radius: 4px;
       font-size: .9em;
       font-weight: bold;
       box-shadow: 0 0 2px rgb(0 0 0 / 70%);
   }
   .personaje-info {
       user-select: none;
   }
   .personaje-info .tier,
   .personaje-info .classe {
       font-size: 18px;
       color: #bbb;
   }
   /* --------- Abas ---------- */
   .personaje-tabs {
       margin: 4px 0 4px 8px;
       display: flex;
       gap: 12px;
       justify-content: flex-start;
   }
   .tab-btn {
       padding: 5px 20px;
       background: #333;
       color: #fff;
       border: 2px solid transparent;
       border-radius: 8px;
       font-size: 20px;
       cursor: pointer;
       font-weight: 600;
       line-height: 1;
       transition: background .15s ease, border-color .15s ease;
   }
   .tab-btn.active {
       background: #156bc7;
       border-color: #156bc7;
   }
   .tab-content {
       display: none;
       background: #26211cd6;
       padding: 0 8px 8px;
       position: relative;
       z-index: 3;
   }
   .tab-content.active {
       display: block;
   }
   /* --------- Habilidades ---------- */
   .habilidades-container {
       display: flex;
       gap: 20px;
   }
   .habilidades-details {
       flex: 1;
       display: flex;
       flex-direction: column;
       gap: 10px;
       width: 50%;
       justify-content: center;
   }
   /* Barra dos ícones – ocupa toda a largura e fica acima da arte */
   .cuadros-container {
       display: flex;
       flex-wrap: nowrap;
       gap: 10px;
       width: 100%;
       overflow-x: auto;
       overflow-y: hidden;
       padding: 10px 0 3px 1px;
       position: relative;
       z-index: 4;
       margin-bottom: 6px;
       scrollbar-width: thin;
       scrollbar-color: #ababab transparent;
       scroll-behavior: smooth;
       justify-content: flex-start;
   }
   .cuadros-container::-webkit-scrollbar {
       height: 6px;
   }
   .cuadros-container::-webkit-scrollbar-track {
       background: transparent;
   }
   .cuadros-container::-webkit-scrollbar-thumb {
       background-color: #151515;
       border-radius: 3px;
   }
   .cuadros-container .cuadro {
       flex: 0 0 auto;
       width: 50px;
       height: 50px;
       border-radius: 5px;
       cursor: pointer;
       transition: transform .2s, box-shadow .2s;
   }
   .cuadros-container .cuadro.activo {
       box-shadow: 0 0 0 1.5px #FFD700;
   }
   .cuadro img {
       width: 100%;
       height: 100%;
       object-fit: cover;
   }
   /* Título e tooltip */
   .titulo-habilidad {
       position: relative;
       display: flex;
       justify-content: center;
       align-items: center;
       margin-bottom: 8px;
       padding-right: 32px;
   }
   .titulo-habilidad h3 {
       font-size: 1.6em;
       color: #fff;
       text-align: center;
       margin: 0;
       width: 100%;
   }
   .tooltip-container {
       position: absolute;
       right: 0;
       top: 50%;
       transform: translateY(-50%);
   }
   .info-btn {
       border: none;
       color: #D3DBDC;
       background: #787878;
       font-weight: bold;
       border-radius: 50%;
       width: 44px;
       height: 44px;
       font-family: 'Noto Sans';
       cursor: pointer;
       transition: .2s;
       box-shadow: 0 0 3px #000;
       font-size: 40px;
       padding: 0;
       line-height: 24px;
       text-align: center;
   }
   .tooltip-text {
       visibility: hidden;
       width: 220px;
       background: #222;
       color: #fff;
       text-align: left;
       padding: 8px 10px;
       border-radius: 8px;
       position: absolute;
       z-index: 10;
       bottom: 130%;
       left: 50%;
       transform: translate(-85%, 110%);
       opacity: 0;
       transition: opacity .3s;
       font-size: 12px;
       box-shadow: 0 2px 10px rgba(0, 0, 0, .5);
       pointer-events: none;
   }
   .tooltip-container:hover .tooltip-text {
       visibility: visible;
       opacity: 1;
   }
   /* Descrição da habilidade */
   .descripcion-container {
       min-height: 27.5rem;
       height: 100%;
       padding: 4px 16px !important;
       background: #26211C;
       border-radius: 8px;
       position: relative;
       box-shadow: 0 6px 18px rgba(0, 0, 0, .28);
       color: #fff;
       backdrop-filter: blur(2px);
       transition: all .3s ease;
       text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
       padding-top: 0 !important;
       z-index: 99;
   }
   .descripcion-container h3 {
       font-size: 2.7em;
       margin: 0;
       text-align: center;
       padding-top: 0;
   }
   .descripcion-container p,
   .desc {
       font-size: 1.2em;
       margin: 0;
   }
   .desc {
       overflow-y: auto !important;
       max-height: inherit;
       margin-top: 10px;
   }
   .desc * {
       font-size: inherit !important;
       line-height: inherit;
   }
   .descripcion-container .descLevel {
       margin-top: 5px;
       font-weight: bold;
   }
   .descripcion-container .desc::-webkit-scrollbar,
   .tabSkill--container::-webkit-scrollbar {
       width: 7px;
       height: 7px;
   }
   .descripcion-container .desc::-webkit-scrollbar-thumb,
   .tabSkill--container::-webkit-scrollbar-thumb {
       background-color: rgb(71 153 255);
       border-radius: 10px;
   }
   .descripcion-container .desc::-webkit-scrollbar-track,
   .tabSkill--container::-webkit-scrollbar-track {
       background-color: #151515a8;
       border-radius: 10px;
   }
   /* Tiers */
   .tier-bronze .topbar-icon,
   .tier-bronze .tier {
       outline: 2px solid #7b4e2f !important;
   }
   .tier-silver .topbar-icon,
   .tier-silver .tier {
       outline: 2px solid #d6d2d2 !important;
   }
   .tier-gold .topbar-icon,
   .tier-gold .tier {
       outline: 2px solid #fcd300 !important;
   }
   .tier-diamond .topbar-icon,
   .tier-diamond .tier {
       outline: 2px solid #60dae2 !important;
   }
   /* Vídeo da habilidade */
   video::-webkit-media-controls {
       opacity: 0;
       transition: opacity .3s;
   }
   video:hover::-webkit-media-controls {
       opacity: 1;
   }
   .video-container {
       position: relative;
       width: 43%;
       background: #000;
       display: flex;
       align-items: center;
       justify-content: center;
       border-radius: 2%;
       box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
       overflow: hidden;
       z-index: 999;
   }
   .video-placeholder {
       position: absolute;
       inset: 0;
       background: #000;
       display: flex;
       align-items: center;
       justify-content: center;
       z-index: 2;
       opacity: 1;
       transition: opacity .9s ease;
   }
   .video-placeholder img {
       width: 120px;
       height: auto;
       animation: breathe 2.5s ease-in-out infinite;
       filter: drop-shadow(0 0 6px rgba(255, 255, 255, .3));
   }
   .video-placeholder.fade-out {
       opacity: 0;
   }
   @keyframes breathe {
       0%,
       100% {
           transform: scale(1);
           opacity: 1;
       }
       50% {
           transform: scale(1.07);
           opacity: .85;
       }
   }
   /* ===== Atributos (cards) ===== */
   .attr-cards {
       display: flex;
       flex-wrap: wrap;
       gap: 16px;
       justify-content: center;
       margin: 6px 0 12px;
   }
   .descripcion-container .attr-card {
       background: #3b312f;
       border: 1px solid rgba(0, 0, 0, .25);
       border-radius: 12px;
       padding: 10px 12px;
       min-width: 150px;
       box-shadow: 0 4px 10px rgba(0, 0, 0, .25);
       text-shadow: none;
       font-family: 'Noto Sans', sans-serif;
   }
   .descripcion-container .attr-card * {
       text-shadow: none;
   }
   .attr-card__header {
       display: flex;
       align-items: center;
       justify-content: center;
       gap: 8px;
       line-height: 1;
   }
   .attr-card__icon {
       width: 28px;
       height: 28px;
       display: block;
       flex: 0 0 28px;
   }
   .attr-card__label {
       color: #fff;
       font-weight: 700;
       letter-spacing: .2px;
       font-size: 1rem;
   }
   .attr-card__value {
       margin-top: 8px;
       text-align: center;
       color: #fff;
       font-weight: 800;
       font-size: 1.25rem;
       letter-spacing: .02em;
   }
   /* Mobile / telas altas: pode ocultar ícone e aumentar fontes */
   @media (max-aspect-ratio: 3/4) {
       .attr-card__icon {
           display: none;
       }
       .attr-card__label {
           font-size: 1.3rem;
       }
       .attr-card__value {
           font-size: 1.5rem;
       }
   }
   /* --------- Skins ---------- */
   .attribute-title,
   .card-skins-title {
       font-size: 1.4em;
       text-align: center;
       letter-spacing: 1px;
       font-family: 'Noto Sans', sans-serif !important;
       border-bottom: 2px solid #9d9c9c;
       color: #fff !important;
       padding-bottom: 8px;
       margin-bottom: 16px;
       width: 75%;
   }
   .card-skins {
       padding-block: 12px;
       border-radius: 12px;
       user-select: none;
   }
   .skins-carousel-wrapper {
       min-height: 21.1rem;
       max-height: 60%;
       padding: 0 16px 1px !important;
       background: #26211C;
       border-radius: 8px;
       position: relative;
       box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
       color: #fff;
       backdrop-filter: blur(2px);
       transition: all .3s ease;
       text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
       flex: 1;
       display: flex;
       flex-direction: row;
       gap: 10px;
       justify-content: center;
       align-items: center;
       overflow: visible;
       z-index: 99;
   }
   /* Gradientes laterais quando houver rolagem */
   .skins-carousel-wrapper::before,
   .skins-carousel-wrapper::after {
       content: ;
       position: absolute;
       top: 0;
       width: 60px;
       height: 100%;
       pointer-events: none;
       opacity: 0;
       transition: opacity .4s ease;
       z-index: 3;
   }
   .skins-carousel-wrapper::before {
       left: 0;
       background: linear-gradient(to right, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 100%);
   }
   .skins-carousel-wrapper::after {
       right: 0;
       background: linear-gradient(to left, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 100%);
   }
   .skins-carousel-wrapper.has-left::before,
   .skins-carousel-wrapper.has-right::after {
       opacity: 1;
   }
   .has-left {
       padding-left: 60px;
   }
   .has-left .skins-carousel {
       mask-image: linear-gradient(to right, transparent 0px, black 40px, black 100%);
   }
   .has-right {
       padding-right: 60px;
   }
   .has-right .skins-carousel {
       mask-image: linear-gradient(to right, black 0px, black calc(100% - 40px), transparent 100%);
   }
   .card-skins-title {
       display: block;
       border-bottom: unset;
       font-size: 40px;
       font-weight: bold;
       padding-bottom: unset;
       margin-bottom: 10px;
       width: 47%;
   }
   .skins-carousel {
       display: flex;
       gap: 1vw;
       overflow-x: auto;
       scroll-behavior: smooth;
       padding: 10px 0;
       flex-grow: 1;
   }
   .skins-carousel.both-mask {
       mask-image: linear-gradient(to right, transparent 0px, black 40px, black calc(100% - 40px), transparent 100%);
   }
   .skins-carousel.left-mask {
       mask-image: linear-gradient(to right, transparent 0px, black 40px, black 100%);
   }
   .skins-carousel.right-mask {
       mask-image: linear-gradient(to right, black 0px, black calc(100% - 40px), transparent 100%);
   }
   .skins-carousel.no-mask {
       mask-image: none;
   }
   .skins-carousel::-webkit-scrollbar {
       display: none;
   }
   .skins-arrow {
       background: none;
       border: none;
       color: #fff;
       font-size: 36px;
       cursor: pointer;
       padding: 8px;
       z-index: 5;
       transition: opacity .3s ease, transform .3s ease;
   }
   .skins-arrow.left {
       margin-right: 8px;
   }
   .skins-arrow.right {
       margin-left: 8px;
   }
   .skins-arrow.hidden {
       opacity: 0;
       transform: scale(.8);
       pointer-events: none;
       visibility: hidden;
   }
   .skin-card {
       position: relative;
       width: 12vw;
       height: 39vh;
       flex: 0 0 auto;
       border: 2px solid #697EC9 !important;
       border-radius: 8px;
       overflow: hidden;
       box-shadow: 0 2px 10px rgba(0, 0, 0, .25);
       background: #111;
   }
   .skin-card::before {
       content: ;
       position: absolute;
       inset: 0;
       pointer-events: none;
       border-radius: inherit;
       z-index: 2;
       box-shadow: inset 0 0 8px rgba(180, 180, 180, .18);
   }
   .skins--imageBanner {
       width: 100%;
       height: 109%;
   }
   .skins--imageBanner img {
       width: 100%;
       height: 100%;
       object-fit: cover;
       filter: brightness(.5);
       scale: 1.1;
   }
   .skins--imageSkin img {
       position: absolute;
       bottom: 10px;
       left: 50%;
       transform: translateX(-50%);
       height: 140px;
       width: auto;
       z-index: 2;
       transition: transform .2s;
   }
   /* --------- Responsivo (tela “alta”/mobile) ---------- */
   @media (max-aspect-ratio: 3/4) {
       .desc {
           font-size: 26px;
           line-height: 1.5;
           overflow-y: auto !important;
           max-height: inherit;
           margin: 0;
           width: 100%;
           margin-top: 8px;
       }
       .desc * {
           font-size: inherit !important;
           line-height: inherit;
       }
       .habilidades-container {
           display: flex;
           gap: 20px;
           flex-direction: column-reverse;
       }
       .habilidades-details {
           flex: 1;
           display: flex;
           flex-direction: column;
           width: 96%;
           align-self: center;
       }
       .video-container {
           width: 80%;
           border-radius: 3%;
           margin-top: 2%;
           align-self: center;
       }
       .art-personaje {
           display: none;
           width: 370px;
           height: 290px;
           position: absolute;
           right: .5rem;
           top: 1.1rem;
           z-index: 1;
           pointer-events: none;
       }
       .topbar-description {
           font-size: 22px;
       }
       .personaje-info .tier,
       .personaje-info .classe {
           font-size: 30px;
       }
       .cuadros-container {
           width: 98%;
           place-self: center;
           padding: 10px 0 16px 1px;
       }
       .cuadros-container .cuadro {
           width: 80px;
           height: 80px;
       }
       .descripcion-container h3 {
           font-size: 3.6em;
           margin-top: -14px;
       }
       .descripcion-container p {
           font-size: 2.3em;
           margin-bottom: 5px;
       }
       .descripcion-container {
           padding: 22px !important;
       }
       .tab-btn {
           padding: 10px 20px;
           font-size: 26px;
       }
       .tab-content {
           position: relative;
           z-index: 1;
           padding: 0 8px 20px;
       }
       .classe {
           padding: 0 5px;
           font-size: 1.4em;
       }
       /* chips maiores no mobile */
       .attr-chips {
           gap: 14px;
       }
       .attr-chip {
           padding: 10px 14px;
           border-radius: 12px;
       }
       .attr-label,
       .attr-value {
           font-size: 1.3rem;
       }
       .skins-carousel {
           gap: 20px;
       }
       .skin-card {
           width: 236px;
           height: 400px;
       }
       .skins--imageSkin img {
           height: 170px;
       }
       .tooltipster-content {
           font-size: 26px;
       }
       .attribute-title,
       .card-skins-title {
           width: 100% !important;
       }
       .skins-arrow {
           display: none !important;
       }
       .skins-carousel-wrapper::after,
       .skins-carousel-wrapper::before {
           background: unset;
       }
       video::-webkit-media-controls {
           opacity: unset;
           transition: unset;
       }
       video:hover::-webkit-media-controls {
           opacity: unset;
       }
   }

</style>