Widget:Teste

De Wiki Gla
Revisão de 02h24min de 1 de setembro de 2025 por Gurren1 (discussão | contribs)
Ir para navegação Ir para pesquisar

<script>

   (function () {
       const $ = (s, root = document) => root.querySelector(s);
       const $$ = (s, root = document) => Array.from(root.querySelectorAll(s));
       const ensureRemoved = sel => { Array.from(document.querySelectorAll(sel)).forEach(n => n.remove()); };
       const onceFlag = (el, key) => { if (!el) return false; if (el.dataset[key]) return false; el.dataset[key] = '1'; return true; };
       const skillsTab = $('#skills');
       const skinsTab = $('#skins');
       ensureRemoved('.top-rail');
       ensureRemoved('.content-card');
       ensureRemoved('.video-placeholder');
       Array.from(document.querySelectorAll('.card-skins-title, .card-skins .card-skins-title, .cardskins-title, .rail-title')).forEach(t => {
           if ((t.textContent || ).trim().toLowerCase().includes('skins')) {
               t.remove();
           }
       });
       if (skillsTab) {
           const iconBar = skillsTab.querySelector('.icon-bar');
           if (iconBar) {
               const rail = document.createElement('div');
               rail.className = 'top-rail skills';
               rail.appendChild(iconBar);
               skillsTab.prepend(rail);
           }
       }
       if (skinsTab) {
           const wrapper = skinsTab.querySelector('.skins-carousel-wrapper');
           const rail = document.createElement('div');
           rail.className = 'top-rail skins';
           const title = document.createElement('div');
           title.className = 'rail-title';
           title.textContent = 'Skins & Spotlights';
           rail.appendChild(title);
           if (wrapper) {
               const card = document.createElement('div');
               card.className = 'content-card';
               card.appendChild(wrapper);
               skinsTab.prepend(rail);
               skinsTab.appendChild(card);
           } else {
               skinsTab.prepend(rail);
           }
       }
       if (skillsTab) {
           const details = skillsTab.querySelector('.skills-details');
           const videoContainer = skillsTab.querySelector('.video-container');
           const card = document.createElement('div');
           card.className = 'content-card skills-grid';
           if (details) card.appendChild(details);
           if (videoContainer) card.appendChild(videoContainer);
           skillsTab.appendChild(card);
       }
       const iconsBar = $('#skills') ? $('.icon-bar', $('#skills')) : null;
       const iconItems = iconsBar ? Array.from(iconsBar.querySelectorAll('.skill-icon')) : [];
       const descBox = $('#skills') ? $('.desc-box', $('#skills')) : null;
       const videoBox = $('#skills') ? $('.video-container', $('#skills')) : null;
       const videosCache = new Map();
       let totalVideos = 0, loadedVideos = 0, autoplay = false;
       let placeholder = videoBox ? videoBox.querySelector('.video-placeholder') : null;
       let placeholderCreatedOnLoad = false;
       let placeholderConsumed = false;
       if (!placeholder && videoBox) {
           placeholder = document.createElement('div');
           placeholder.className = 'video-placeholder';
           placeholder.innerHTML = '<img src="/images/d/d5/Icon_gla.png" alt="Carregando...">';
           videoBox.appendChild(placeholder);
           placeholderCreatedOnLoad = true;
       } else if (placeholder) {
           placeholderCreatedOnLoad = true;
       }
       if (!placeholder) placeholderConsumed = true;
       const removePlaceholderSmooth = () => {
           if (!placeholder) return;
           if (placeholder.classList.contains('fade-out')) return;
           placeholder.classList.add('fade-out');
           const onEnd = () => {
               try { placeholder.style.display = 'none'; } catch (e) { }
               placeholder.removeEventListener('transitionend', onEnd);
           };
           placeholder.addEventListener('transitionend', onEnd, { once: true });
           setTimeout(() => { try { placeholder.style.display = 'none'; } catch (e) { } }, 600);
       };
       const showPlaceholder = () => {
           if (!videoBox) return;
           if (!placeholder || !placeholderCreatedOnLoad) return;
           if (placeholderConsumed) return;
           placeholder.classList.remove('fade-out');
           placeholder.style.display = 'flex';
           void placeholder.offsetWidth;
       };
       const addOnce = (el, ev, fn) => {
           if (!el) return;
           const attr = `data-wired-${ev}`;
           if (el.hasAttribute(attr)) return;
           el.addEventListener(ev, fn);
           el.setAttribute(attr, '1');
       };
       if (iconItems.length && videoBox) {
           iconItems.forEach(el => {
               const src = (el.dataset.video || ).trim();
               const idx = el.dataset.index || ;
               if (!src || videosCache.has(idx)) return;
               totalVideos++;
               const v = document.createElement('video');
               v.className = 'skill-video';
               v.setAttribute('controls', );
               v.setAttribute('preload', 'auto');
               v.setAttribute('playsinline', );
               v.style.display = 'none';
               v.dataset.index = idx;
               v.style.width = '100%';
               v.style.maxWidth = '100%';
               v.style.height = 'auto';
               v.style.aspectRatio = '16/9';
               v.style.objectFit = 'cover';
               const source = document.createElement('source');
               source.src = src;
               source.type = 'video/webm';
               v.appendChild(source);
               v.addEventListener('canplay', () => {
                   loadedVideos++;
                   if (loadedVideos === 1) { try { v.pause(); v.currentTime = 0; } catch (e) { } }
                   const active = $('.skill-icon.active', iconsBar);
                   if (active && active.dataset.index === idx) {
                       if (!placeholderConsumed) {
                           setTimeout(() => { removePlaceholderSmooth(); placeholderConsumed = true; }, 180);
                       }
                   }
                   if (loadedVideos === totalVideos) autoplay = true;
               });
               v.addEventListener('error', () => {
                   loadedVideos++;
                   removePlaceholderSmooth();
                   if (loadedVideos === totalVideos) autoplay = true;
               });
               videoBox.appendChild(v);
               videosCache.set(idx, v);
           });
       }
       if (totalVideos === 0 && placeholder) {
           placeholder.style.display = 'none';
           placeholder.classList.add('fade-out');
       }
       iconItems.forEach(el => {
           if (el.dataset.wired) return;
           el.dataset.wired = '1';
           const name = el.dataset.nome || el.dataset.name || ;
           const desc = (el.dataset.desc || ).replace(/(.*?)/g, '$1');
           const attrs = el.dataset.atr || el.dataset.attrs || ;
           const idx = el.dataset.index || ;
           const hasVideo = !!(el.dataset.video && el.dataset.video.trim() !== );
           el.title = name;
           el.addEventListener('click', () => {
               if (descBox) {
                   descBox.innerHTML = `

${name}

 ${renderAttributes(attrs)}
${desc}

`;

               }
               videosCache.forEach(v => { try { v.pause(); } catch (e) { } v.style.display = 'none'; });
               if (videoBox) {
                   if (hasVideo && videosCache.has(idx)) {
                       const v = videosCache.get(idx);
                       videoBox.style.display = 'block';
                       v.style.display = 'block';
                       try { v.currentTime = 0; } catch (e) { }
                       if (v.readyState >= 3) {
                           if (!placeholderConsumed) { removePlaceholderSmooth(); placeholderConsumed = true; }
                       } else {
                           if (!placeholderConsumed) {
                               showPlaceholder();
                               const canplayHandler = () => { removePlaceholderSmooth(); placeholderConsumed = true; v.removeEventListener('canplay', canplayHandler); };
                               v.addEventListener('canplay', canplayHandler);
                           }
                       }
                       if (autoplay) v.play().catch(() => { });
                   } else {
                       videoBox.style.display = 'none';
                       if (placeholder) {
                           placeholder.style.display = 'none';
                           placeholder.classList.add('fade-out');
                       }
                   }
               }
               iconItems.forEach(i => i.classList.remove('active'));
               el.classList.add('active');
               if (!autoplay && loadedVideos > 0) autoplay = true;
           });
       });
       (function initSkillTooltip() {
           if (document.querySelector('.skill-tooltip')) return;
           const tip = document.createElement('div');
           tip.className = 'skill-tooltip';
           tip.setAttribute('role', 'tooltip');
           tip.setAttribute('aria-hidden', 'true');
           document.body.appendChild(tip);
           function measureAndPos(el) {
               if (!el || tip.getAttribute('aria-hidden') === 'true') return;
               tip.style.left = '0px';
               tip.style.top = '0px';
               const rect = el.getBoundingClientRect();
               const tr = tip.getBoundingClientRect();
               let left = Math.round(rect.left + (rect.width - tr.width) / 2);
               left = Math.max(8, Math.min(left, window.innerWidth - tr.width - 8));
               let top = Math.round(rect.top - tr.height - 8);
               if (top < 8) top = Math.round(rect.bottom + 8);
               tip.style.left = left + 'px';
               tip.style.top = top + 'px';
           }
           function show(el, text) {
               tip.textContent = text || ;
               tip.setAttribute('aria-hidden', 'false');
               tip.style.opacity = '1';
               measureAndPos(el);
           }
           function hide() {
               tip.setAttribute('aria-hidden', 'true');
               tip.style.opacity = '0';
           }
           Array.from(document.querySelectorAll('.icon-bar .skill-icon')).forEach(icon => {
               if (icon.dataset.tipwired) return;
               icon.dataset.tipwired = '1';
               const label = icon.dataset.nome || icon.dataset.name || icon.title || ;
               icon.addEventListener('mouseenter', () => show(icon, label));
               icon.addEventListener('mousemove', () => measureAndPos(icon));
               icon.addEventListener('mouseleave', hide);
           });
           window.addEventListener('scroll', () => {
               const visible = document.querySelector('.skill-tooltip[aria-hidden="false"]');
               if (!visible) return;
               const hover = document.querySelector('.icon-bar .skill-icon:hover') || document.querySelector('.icon-bar .skill-icon.active');
               measureAndPos(hover);
           }, true);
           window.addEventListener('resize', () => {
               const hover = document.querySelector('.icon-bar .skill-icon:hover') || document.querySelector('.icon-bar .skill-icon.active');
               measureAndPos(hover);
           });
       })();
       if (iconItems.length) {
           const first = iconItems[0];
           if (first) {
               if (!first.classList.contains('active')) first.classList.add('active');
               setTimeout(() => first.click(), 0);
           }
       }
       (function initTabs() {
           const tabs = Array.from(document.querySelectorAll('.tab-btn'));
           if (!tabs.length) return;
           const contents = Array.from(document.querySelectorAll('.tab-content'));
           tabs.forEach(btn => {
               if (btn.dataset.wiredTab) return;
               btn.dataset.wiredTab = '1';
               btn.addEventListener('click', () => {
                   const target = btn.getAttribute('data-tab');
                   tabs.forEach(b => b.classList.toggle('active', b === btn));
                   contents.forEach(c => c.classList.toggle('active', c.id === target));
                   Promise.resolve().then(() => {
                       syncDescHeight();
                       if (target === 'skins') {
                           videosCache.forEach(v => { try { v.pause(); } catch (e) { } v.style.display = 'none'; });
                           if (videoBox && placeholder) { placeholder.style.display = 'none'; placeholder.classList.add('fade-out'); }
                       } else {
                           const activeIcon = document.querySelector('.icon-bar .skill-icon.active');
                           if (activeIcon) activeIcon.click();
                       }
                   });
               });
           });
       })();
       (function initSkillTooltip() {
           if (document.querySelector('.skill-tooltip')) return;
           const tip = document.createElement('div');
           tip.className = 'skill-tooltip';
           tip.setAttribute('role', 'tooltip');
           tip.setAttribute('aria-hidden', 'true');
           document.body.appendChild(tip);
           function measureAndPos(el) {
               if (!el || tip.getAttribute('aria-hidden') === 'true') return;
               tip.style.left = '0px';
               tip.style.top = '0px';
               const rect = el.getBoundingClientRect();
               const tr = tip.getBoundingClientRect();
               let left = Math.round(rect.left + (rect.width - tr.width) / 2);
               left = Math.max(8, Math.min(left, window.innerWidth - tr.width - 8));
               let top = Math.round(rect.top - tr.height - 8);
               if (top < 8) top = Math.round(rect.bottom + 8);
               tip.style.left = left + 'px';
               tip.style.top = top + 'px';
           }
           function show(el, text) {
               tip.textContent = text || ;
               tip.setAttribute('aria-hidden', 'false');
               tip.style.opacity = '1';
               measureAndPos(el);
           }
           function hide() {
               tip.setAttribute('aria-hidden', 'true');
               tip.style.opacity = '0';
           }
           Array.from(document.querySelectorAll('.icon-bar .skill-icon')).forEach(icon => {
               if (icon.dataset.tipwired) return;
               icon.dataset.tipwired = '1';
               const label = icon.dataset.nome || icon.dataset.name || icon.title || ;
               icon.addEventListener('mouseenter', () => show(icon, label));
               icon.addEventListener('mousemove', () => measureAndPos(icon));
               icon.addEventListener('mouseleave', hide);
           });
           window.addEventListener('scroll', () => {
               const visible = document.querySelector('.skill-tooltip[aria-hidden="false"]');
               if (!visible) return;
               const hover = document.querySelector('.icon-bar .skill-icon:hover') || document.querySelector('.icon-bar .skill-icon.active');
               measureAndPos(hover);
           });
           window.addEventListener('resize', () => {
               const hover = document.querySelector('.icon-bar .skill-icon:hover') || document.querySelector('.icon-bar .skill-icon.active');
               measureAndPos(hover);
           });
       })();
       if (iconItems.length) {
           const first = iconItems[0];
           if (first) {
               if (!first.classList.contains('active')) first.classList.add('active');
               setTimeout(() => first.click(), 0);
           }
       }
       (function initTabs() {
           const tabs = Array.from(document.querySelectorAll('.tab-btn'));
           if (!tabs.length) return;
           const contents = Array.from(document.querySelectorAll('.tab-content'));
           tabs.forEach(btn => {
               if (btn.dataset.wiredTab) return;
               btn.dataset.wiredTab = '1';
               btn.addEventListener('click', () => {
                   const target = btn.getAttribute('data-tab');
                   tabs.forEach(b => b.classList.toggle('active', b === btn));
                   contents.forEach(c => c.classList.toggle('active', c.id === target));
                   Promise.resolve().then(() => {
                       syncDescHeight();
                       if (target === 'skins') {
                           videosCache.forEach(v => { try { v.pause(); } catch (e) { } v.style.display = 'none'; });
                           if (videoBox && placeholder) { placeholder.style.display = 'none'; placeholder.classList.add('fade-out'); }
                       } else {
                           const activeIcon = document.querySelector('.icon-bar .skill-icon.active');
                           if (activeIcon) activeIcon.click();
                       }
                   });
               });
           });
       })();
       function syncDescHeight() {
           // no-op on purpose
       }
       window.addEventListener('resize', syncDescHeight);
       if (videoBox) new ResizeObserver(syncDescHeight).observe(videoBox);
       iconItems.forEach(el => {
           const wired = !!el.dataset._sync_wired;
           if (wired) return;
           el.dataset._sync_wired = '1';
           el.addEventListener('click', () => {
               Promise.resolve().then(syncDescHeight);
           });
       });
       if (iconsBar) addOnce(iconsBar, 'wheel', (e) => {
           if (e.deltaY) {
               e.preventDefault();
               iconsBar.scrollLeft += e.deltaY;
           }
       });
       (function initSkinsArrows() {
           const carousel = $('.skins-carousel');
           const wrapper = $('.skins-carousel-wrapper');
           const left = $('.skins-arrow.left');
           const right = $('.skins-arrow.right');
           if (!carousel || !left || !right || !wrapper) return;
           if (wrapper.dataset.wired) return;
           wrapper.dataset.wired = '1';
           const scrollAmt = () => Math.round(carousel.clientWidth * 0.6);
           function setState() {
               const max = carousel.scrollWidth - carousel.clientWidth;
               const x = carousel.scrollLeft;
               const hasLeft = x > 5, hasRight = x < max - 5;
               left.style.display = hasLeft ? 'inline-block' : 'none';
               right.style.display = hasRight ? 'inline-block' : 'none';
               wrapper.classList.toggle('has-left', hasLeft);
               wrapper.classList.toggle('has-right', hasRight);
               carousel.style.justifyContent = (!hasLeft && !hasRight) ? 'center' : ;
           }
           function go(dir) {
               const max = carousel.scrollWidth - carousel.clientWidth;
               const next = dir < 0
                   ? Math.max(0, carousel.scrollLeft - scrollAmt())
                   : Math.min(max, carousel.scrollLeft + scrollAmt());
               carousel.scrollTo({ left: next, behavior: 'smooth' });
           }
           left.addEventListener('click', () => go(-1));
           right.addEventListener('click', () => go(1));
           carousel.addEventListener('scroll', setState);
           new ResizeObserver(setState).observe(carousel);
           setState();
       })();
       function renderAttributes(str) {
           const vals = (str || ).split(',').map(v => v.trim());
           const pve = parseInt(vals[0], 10);
           const pvp = parseInt(vals[1], 10);
           const ene = parseInt(vals[2], 10);
           const cd = parseInt(vals[3], 10);
           const recargaVal = isNaN(cd) ? '-' : cd;
           const energiaLabel = isNaN(ene) ? 'Energia' : (ene >= 0 ? 'Ganho de energia' : 'Custo de energia');
           const energiaVal = isNaN(ene) ? '-' : Math.abs(ene);
           const poderVal = isNaN(pve) ? '-' : pve;
           const poderPvpVal = isNaN(pvp) ? '-' : pvp;
           const rows = [
               ['Recarga', recargaVal],
               [energiaLabel, energiaVal],
               ['Poder', poderVal],
               ['Poder PvP', poderPvpVal],
           ];
           const visible = rows.filter(([, v]) => v !== '-');
           if (visible.length === 0) return ;
           const visibleHtml = visible.map(([label, value]) => `
                   ${label}:
                   ${value}
           `).join();

return `

${visibleHtml}

`;

       }
       (function localizeSkillsTab() {
           const lang = (document.documentElement.lang || navigator.language || ).toLowerCase();
           const code = lang.split('-')[0];
           const map = {
               en: 'Skills',
               'pt': 'Habilidades',
               'pt-br': 'Habilidades',
               'es': 'Habilidades',
               pl: 'Umiejętności'
           };
           const key = map[lang] ? lang : (map[code] ? code : 'en');
           const label = map[key] || map.en;
           let btn = document.querySelector('.character-tabs .tab-btn[data-tab="skills"]') ||
               Array.from(document.querySelectorAll('.character-tabs .tab-btn')).find(b => /skill|habil|umiej/i.test(b.textContent || ));
           if (btn) btn.textContent = label;
       })();
       setTimeout(() => {
           Array.from(document.querySelectorAll('.skill-icon')).forEach(el => {
               console.log('icon', el.dataset.index, 'data-video=', el.dataset.video);
           });
           videosCache.forEach((v, idx) => {
               const src = v.querySelector('source') ? v.querySelector('source').src : v.src;
               console.log('video element', idx, 'src=', src, 'readyState=', v.readyState);
               v.addEventListener('error', (ev) => {
                   console.error('VIDEO ERROR idx=', idx, 'src=', src, 'error=', v.error);
               });
               v.addEventListener('loadedmetadata', () => {
                   console.log('loadedmetadata idx=', idx, 'dimensions=', v.videoWidth, 'x', v.videoHeight);
               });
           });
       }, 600);
   })();

</script> <style>

   /* ===========================
  Base
  =========================== */
   img {
       pointer-events: none;
       user-select: none;
   }
   /* video baseline; specific skill video sizing overridden below */
   video {
       max-height: none;
   }
   .mw-body {
       padding: unset !important;
   }
   /* precisa de !important p/ MediaWiki */
   .mw-body-content {
       line-height: 1.5;
   }
   .mw-body-content p {
       display: none;
   }
   /* ===========================
  Banner
  =========================== */
   /* Hide the original banner element (we'll use the image as the template background)
      and keep the selector so existing markup doesn't break. */
   .banner {
       display: none !important;
   }
   /* Use the banner image as the background for the template container and add
      a subtle dark overlay via ::before to improve text contrast. */
   .character-box {
       /* ...existing properties... */
       background-image: url(https://i.imgur.com/RktmgO8.png);
       background-position: center top;
       background-repeat: no-repeat;
       background-size: cover;
       position: relative;
       /* ensure positioning context for ::before */
       z-index: 1;
       /* base layer for the box content */
   }
   /* overlay sits above the background image but below the content; darker bottom-to-top gradient */
   .character-box::before {
       content: "";
       position: absolute;
       inset: 0;
       pointer-events: none;
       background: linear-gradient(to bottom, rgba(0, 0, 0, .45), rgba(0, 0, 0, .60));
       z-index: 0;
       /* overlay: below content (content kept at z-index:1) */
   }
   /* ===========================
  Character topbar
  =========================== */
   .character-box {
       color: #000;
       font-family: 'Noto Sans', sans-serif;
       width: 100%;
       margin: auto;
       position: relative;
       user-select: none;
   }
   .character-box p {
       display: unset;
   }
   .character-topbar {
       display: flex;
       flex-direction: column;
       align-items: flex-start;
       padding: 8px 20px 0;
       z-index: 1;
       /* topbar above overlay */
   }
   .character-name-box {
       display: flex;
       align-items: center;
       gap: 14px;
   }
   .topbar-icon {
       margin-top: 8px;
       width: 100px;
       height: 100px;
       object-fit: none;
   }
   .character-name {
       color: #fff;
       font-size: 56px;
       font-family: 'Orbitron', sans-serif;
       font-weight: 900;
       text-shadow: 0 0 6px #000, 0 0 9px #000;
   }
   .topbar-description {
       display: none;
   }
   /* ===========================
  Header / Artwork
  =========================== */
   .character-header {
       position: relative;
       overflow: hidden;
       /* artwork must not 'vazar' */
       display: flex;
       gap: 10px;
       flex-direction: column;
       z-index: 1;
       /* header/topbar layer */
   }
   /* artwork removed from layout (server still accepts param but we ignore rendering).
      ensure it doesn't reserve space if present in legacy markup */
   .character-art {
       display: none !important;
       width: 0 !important;
       height: 0 !important;
       overflow: hidden !important;
   }
   /* Class / tier chips */
   .class-tags {
       display: flex;
       gap: 9px;
       flex-wrap: wrap;
       margin-left: .28rem;
   }
   .class-tag {
       background: #353420;
       color: #fff;
       outline: 2px solid #000;
       padding: 1px 6px;
       border-radius: 4px;
       font-size: .9em;
       font-weight: 700;
       box-shadow: 0 0 2px rgb(0 0 0 / 70%);
   }
   .character-info .tier,
   .character-info .class-tag {
       font-size: 18px;
       color: #bbb;
   }
   /* ===========================
  Tabs
  =========================== */
   .character-tabs {
       margin: 4px 0 4px 8px;
       display: flex;
       gap: 12px;
   }
   .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, border-color .15s;
   }
   .tab-btn.active {
       background: #156bc7;
       border-color: #156bc7;
   }
   .tab-content {
       display: none;
       padding: 0 8px 8px;
       position: relative;
       z-index: 2;
       /* content layer */
   }
   .tab-content.active {
       display: block;
   }
   /* ===========================
  Skills 
  =========================== */
   .skills-container {
       display: flex;
       gap: 20px;
   }
   .skills-details {
       flex: 1;
       display: flex;
       flex-direction: column;
       gap: 10px;
       width: auto;
       /* let grid control widths */
       justify-content: center;
   }
   .icon-bar {
       display: flex;
       flex-wrap: nowrap;
       gap: 10px;
       width: 100%;
       overflow-x: auto;
       overflow-y: hidden;
       padding: 6px 6px;
       /* centraliza melhor verticalmente */
       margin-bottom: 6px;
       scrollbar-width: thin;
       scrollbar-color: #ababab transparent;
       scroll-behavior: smooth;
       justify-content: flex-start;
       align-items: center;
       /* centraliza os ícones verticalmente dentro da barra */
       position: relative;
       z-index: 4;
   }
   .icon-bar::-webkit-scrollbar {
       height: 6px;
   }
   .icon-bar::-webkit-scrollbar-track {
       background: transparent;
   }
   .icon-bar::-webkit-scrollbar-thumb {
       background: #151515;
       border-radius: 3px;
   }
   :root {
       --icon-size: 39px;
       --icon-radius: 8px;
       /* ring width and colors (icons-only overrides) */
       --icon-ring-w: 2px;
       --icon-idle: #bbb;
       --icon-active: #FFD257;
       /* amarelo agradável */
       --icon-active-ring: rgba(255, 210, 87, .45);
       --icon-active-glow: rgba(255, 210, 87, .35);
   }
   /* ensure each icon is vertically centered inside the bar */
   .icon-bar .skill-icon {
       /* keep original sizing and alignment but ensure perfect clipping */
       width: var(--icon-size);
       height: var(--icon-size);
       position: relative;
       flex: 0 0 auto;
       border-radius: var(--icon-radius);
       overflow: hidden;
       /* hard clip the image */
       contain: paint;
       /* reduce subpixel leakage */
       margin-top: 0;
       display: flex;
       align-items: center;
       justify-content: center;
       -webkit-tap-highlight-color: transparent;
       background-clip: padding-box;
   }
   .icon-bar .skill-icon img {
       display: block;
       width: 100%;
       height: 100%;
       object-fit: cover;
       border-radius: inherit;
       clip-path: inset(0 round var(--icon-radius));
       -webkit-clip-path: inset(0 round var(--icon-radius));
       will-change: transform;
       backface-visibility: hidden;
       transform: translateZ(0);
       transition: transform .12s ease;
   }
   /* internal ring implemented via inset box-shadow to avoid border layout changes */
   .icon-bar .skill-icon::after {
       content: "";
       position: absolute;
       inset: 0;
       border-radius: inherit;
       /* internal ring keeps constant thickness between states */
       box-shadow: inset 0 0 0 var(--icon-ring-w) var(--icon-idle);
       pointer-events: none;
       z-index: 2;
       transition: box-shadow .14s ease;
   }
   /* subtle hover color change without changing ring width */
   .icon-bar .skill-icon:hover::after {
       box-shadow: inset 0 0 0 var(--icon-ring-w) #e0e0e0;
   }
   /* separate pseudo for glow so ring thickness does not change */
   .icon-bar .skill-icon::before {
       content: "";
       position: absolute;
       inset: 0;
       border-radius: inherit;
       pointer-events: none;
       z-index: 1;
       box-shadow: none;
       opacity: 0;
       transition: opacity .14s ease, box-shadow .14s ease;
   }
   .icon-bar .skill-icon.active::after {
       box-shadow: inset 0 0 0 var(--icon-ring-w) var(--icon-active);
   }
   .icon-bar .skill-icon.active::before {
       /* glow only (does not change inner ring thickness) */
       box-shadow: 0 0 10px 2px var(--icon-active-glow), 0 0 0 4px var(--icon-active-ring);
       opacity: 1;
   }
   /* smooth zoom on the image only (keeps ring aligned) */
   .icon-bar .skill-icon.active img {
       transform: scale(1.10);
   }
   @media (prefers-reduced-motion: reduce) {
       .icon-bar .skill-icon {
           transition: none;
       }
   }
   /* Title description */
   .skill-title {
       margin: 0 0 12px;
       display: flex;
       justify-content: center;
       align-items: center;
   }
   .skill-title h3 {
       margin: 0;
       width: 100%;
       text-align: center;
       font-size: 1.6em;
       color: #fff;
   }
   /* Description */
   /* Description box: remove own card background/shadow so it doesn't stack
      on top of the outer .content-card. The .content-card remains the main
      visual container. Keep padding and readable colors. */
   .desc-box {
       padding: 12px 18px;
       /* breathing room */
       background: transparent;
       border-radius: 6px;
       position: relative;
       box-shadow: none;
       color: #fff;
       transition: all .3s ease;
       z-index: 2;
       /* keep inner layout stable and let .desc scroll internally */
       display: flex;
       flex-direction: column;
       overflow: hidden;
       text-shadow: none;
       height: auto;
       min-height: 0;
   }
   .desc-box h3 {
       font-size: 2.7em;
       margin: 0;
       text-align: center;
       padding-top: 0;
   }
   .desc {
       /* tamanho de fonte padronizado para todas as viewports */
       font-size: 1.2em !important;
       line-height: 1.7 !important;
       letter-spacing: .01em;
       /* REMOVED: previously forced infinite expansion and conflicted with the 400px limit
          max-height: none !important;
          overflow-y: visible !important;
       */
       overflow-x: hidden;
       -webkit-overflow-scrolling: touch;
       scrollbar-gutter: stable;
       margin-top: 10px;
       padding-right: 8px;
       color: #f1efe9;
       /* prevenir muito longas palavras de forçar layout */
       overflow-wrap: anywhere;
       word-break: break-word;
       white-space: normal;
       /* evitar que flex force comportamento de preenchimento da coluna */
       flex: 0 0 auto !important;
   }
   .desc b,
   .desc strong {
       font-weight: 700;
       color: #fff;
   }
   .desc::-webkit-scrollbar {
       width: 7px;
       height: 7px;
   }
   .desc::-webkit-scrollbar-thumb {
       background: #156bc7;
       border-radius: 10px;
   }
   .desc::-webkit-scrollbar-track {
       background: #151515a8;
       border-radius: 10px;
   }
   /* Attributes list */
   .attrs,
   .attr-list {
       display: block;
       margin: 6px 0 12px;
   }
   .desc-box .attrs,
   .desc-box .attr-list,
   .desc-box .attrs *,
   .desc-box .attr-list * {
       text-shadow: none;
       font-family: 'Noto Sans', sans-serif;
   }
   .attrs__row,
   .attr-row {
       display: flex;
       align-items: baseline;
       gap: 8px;
       min-height: 22px;
       line-height: 1.2;
   }
   .attrs__row--empty,
   .attr-row.is-empty {
       display: none;
   }
   .attrs__label,
   .attr-label {
       font-weight: 700;
       color: #f0c87b;
       font-size: .98rem;
       white-space: nowrap;
       margin: 0;
   }
   .attrs__value,
   .attr-value {
       color: #fff;
       font-weight: 800;
       /* equal size with label for consistent centering */
       font-size: .98rem;
       letter-spacing: .01em;
       margin: 0;
   }
   /* ensure rows center both label & value (value vertically centered on label) */
   .attr-row {
       align-items: center;
   }
   /* remove fixed skill pane height and let content decide height */
   :root {
       --skill-pane-height: unset;
   }
   .skills-container {
       align-items: flex-start;
   }
   /* Video container: allow the video to display at its original size
      while keeping it responsive (max-width:100%). Remove extra inner
      shadows so the .content-card is the primary card. Center content. */
   .video-container {
       position: relative;
       width: 100%;
       max-width: 100%;
       background: transparent;
       display: flex;
       align-items: center;
       justify-content: center;
       border-radius: 10px;
       box-shadow: none;
       overflow: hidden;
       /* rounded corners */
       padding: 0;
       z-index: 2;
   }
   /* ensure every skill video has consistent visible size to avoid tiny thumbnails;
       videos fill the video column (responsive) using 16:9 to avoid layout jumps */
   .video-container>video {
       /* Preencher a coluna do vídeo; mostrar conteúdo inteiro sem recorte */
       width: 100%;
       max-width: 100%;
       height: auto;
       aspect-ratio: 16 / 9;
       object-fit: contain;
       object-position: center;
       z-index: 2;
       display: block;
       border-radius: 6px;
       background: #000;
   }
   /* Center the placeholder/logo while videos load. Keep it as an overlay
      so it doesn't shift layout. */
   .video-placeholder {
       position: absolute;
       inset: 0;
       z-index: 6;
       display: flex;
       align-items: center;
       justify-content: center;
       pointer-events: none;
       opacity: 1;
       transition: opacity .28s ease;
       background: linear-gradient(rgba(0, 0, 0, 0.0), rgba(0, 0, 0, 0.0));
       /* transparent overlay but keeps stacking context */
   }
   .video-placeholder img {
       max-width: 160px;
       width: auto;
       height: auto;
       opacity: 0.98;
       display: block;
   }
   /* fade-out helper used by JS removePlaceholder() */
   .video-placeholder.fade-out {
       opacity: 0;
   }
   @media (max-width:1100px) {
       .top-rail {
           flex-direction: column;
           align-items: stretch;
       }
       .top-rail .icon-bar {
           order: 2;
           width: 100%;
           flex-wrap: wrap;
       }
       .content-card.skills-grid {
           grid-template-columns: 1fr;
       }
   }
   @media (max-aspect-ratio: 3/4) {
       .character-header .character-art {
           display: none;
       }
       .video-container {
           width: 80%;
           border-radius: 3%;
           margin-top: 2%;
           align-self: center;
       }
   }


   /* Tiers */
   .tier-bronze .topbar-icon,
   .tier-bronze .tier {
       outline: 2px solid #7b4e2f;
   }
   .tier-silver .topbar-icon,
   .tier-silver .tier {
       outline: 2px solid #d6d2d2;
   }
   .tier-gold .topbar-icon,
   .tier-gold .tier {
       outline: 2px solid #fcd300;
   }
   .tier-diamond .topbar-icon,
   .tier-diamond .tier {
       outline: 2px solid #60dae2;
   }
   /* Top rail: created dynamically by JS; styles for tabs header */
   .top-rail {
       display: flex;
       align-items: center;
       justify-content: center;
       width: max-content;
       max-width: 96vw;
       margin: 8px auto;
       padding: 8px 12px;
       background: rgba(0, 0, 0, .55);
       border: 2px solid rgba(255, 255, 255, .08);
       border-radius: 12px;
       box-shadow: 0 4px 12px rgba(0, 0, 0, .25);
       -webkit-backdrop-filter: blur(2px);
       backdrop-filter: blur(2px);
   }
   /* hide title by default (skills rail won't show it) */
   .top-rail .rail-title {
       display: none;
   }
   /* skins variant shows the title at left */
   .top-rail.skins .rail-title {
       display: block;
       font-weight: 800;
       font-size: clamp(20px, 2.2vw, 28px);
       color: #fff;
       margin-right: auto;
   }
   /* center icons and keep scroll behavior if overflow */
   .top-rail .icon-bar {
       width: auto;
       justify-content: center;
       margin: 0;
       overflow-x: auto;
       /* preserve horizontal scroll */
   }
   /* Card sizing: larger but constrained to viewport; padding included via box-sizing */
   .content-card {
       width: min(1600px, 96vw);
       max-width: 96vw;
       margin: 10px auto;
       background: #26211C;
       border-radius: 12px;
       box-shadow: 0 8px 24px rgba(0, 0, 0, .30);
       padding: 18px;
       z-index: 2;
       /* above overlay */
   }
   /* layout specific for skills card: larger grid */
   /* Make the video column wider so the video has more space.
       minmax garante largura mínima para o vídeo e permite expansão até 70% do card. */
   .content-card.skills-grid {
       display: grid;
       /* user requested layout for testing: description column wider, video a bit smaller */
       grid-template-columns: minmax(320px, 60%) minmax(320px, 45%);
       gap: 16px;
       /* menor gap para evitar overflow */
       align-items: start;
       /* don't stretch items vertically */
       grid-auto-rows: auto;
       margin: 10px auto 0;
   }
   @media (max-width:1100px) {
       .top-rail {
           flex-direction: column;
           align-items: stretch;
       }
       .top-rail .icon-bar {
           order: 2;
           width: 100%;
           flex-wrap: wrap;
       }
       .content-card.skills-grid {
           grid-template-columns: 1fr;
           gap: 12px;
       }
       .video-container {
           width: 80%;
           max-width: 820px;
           align-self: center;
       }
   }
   @media (max-width:600px) {
       /* Make the card fit symmetrically on small screens (same left/right limit) */
       .content-card {
           box-sizing: border-box;
           /* limitar ao viewport menos safe-area + margem interna */
           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: hidden;
           /* evita scroll horizontal causado por filhos */
       }
       /* ensure the skills grid collapses to single column and doesn't overflow */
       .content-card.skills-grid {
           grid-template-columns: 1fr;
           gap: 12px;
       }
       /* top-rail full width, icon bar flush edge-to-edge */
       .top-rail {
           width: calc(100vw - env(safe-area-inset-left) - env(safe-area-inset-right));
           max-width: 100%;
           margin: 0 auto 8px;
           padding: 6px 8px;
           border-radius: 0;
           box-sizing: border-box;
           overflow: hidden;
       }
       .top-rail .icon-bar {
           width: 100%;
           padding: 0 6px;
           gap: 12px;
           justify-content: flex-start;
           overflow-x: auto;
           -webkit-overflow-scrolling: touch;
       }
       /* larger, more visible icons on mobile */
       :root {
           --icon-size: 92px;
       }
       /* overrides default on mobile */
       .icon-bar .skill-icon {
           width: var(--icon-size);
           height: var(--icon-size);
           flex: 0 0 auto;
       }
       /* limitar explicitamente elementos do vídeo/skins para não extrapolarem */
       .video-container,
       .skins-carousel-wrapper,
       .skins-carousel {
           max-width: calc(100vw - env(safe-area-inset-left) - env(safe-area-inset-right) - 16px);
           box-sizing: border-box;
       }
       .video-container>video,
       .video-container img,
       .skins-carousel img {
           max-width: 100%;
           width: 100%;
           height: auto;
       }
       /* extra safety: prevent horizontal scroll coming from other elements using 100vw */
       html,
       body,
       .mw-body,
       .mw-body-content {
           overflow-x: hidden;
       }
   }
   /* ===========================
  Base — mobile/overflow guards
  =========================== */
   /* evitar qualquer elemento extrapolar o viewport e respeitar safe-area (iPhone notch) */
   html,
   body,
   .mw-body,
   .mw-body-content {
       box-sizing: border-box;
       max-width: 100vw;
       overflow-x: hidden;
       -webkit-overflow-scrolling: touch;
   }
   /* garantir imagens / vídeos internos não forçarem overflow */
   .content-card,
   .top-rail,
   .video-container,
   .skins-carousel-wrapper,
   .skins-carousel {
       box-sizing: border-box;
       max-width: 100%;
   }
   /* impedir filhos de extrapolarem a coluna do card */
   .content-card *,
   .top-rail *,
   .video-container * {
       max-width: 100%;
       box-sizing: border-box;
   }
   /* ---------------------------
  Visual tweaks: icons, attrs, desc
  --------------------------- */
   /* override base icon size (desktop) */
   :root {
       --icon-size: 56px;
       /* desktop icons larger */
       --icon-radius: 10px;
   }
   /* make skill icons use the variable (safety if other rules exist) */
   .icon-bar .skill-icon {
       width: var(--icon-size) !important;
       height: var(--icon-size) !important;
   }
   /* Fix: melhorar visual dos ícones (neutro + ativo) */
   :root {
       /* neutro mais suave e menos "feio" */
       --icon-idle: #cfcfcf;
       /* amarelo ativo (visível em fundos escuros) */
       --icon-active: #FFD95A;
       --icon-active-ring: rgba(255, 217, 90, 0.45);
       --icon-active-glow: rgba(255, 217, 90, 0.30);
       --icon-ring-w: 2px;
   }
   /* garantir pseudo-elementos consistentes (força prioridade para evitar conflitos) */
   .icon-bar .skill-icon::after {
       content: "";
       position: absolute;
       inset: 0;
       border-radius: inherit;
       pointer-events: none;
       z-index: 2;
       box-shadow: inset 0 0 0 var(--icon-ring-w) var(--icon-idle) !important;
       transition: box-shadow .12s ease, border-color .12s ease;
   }
   /* halo / glow externo */
   .icon-bar .skill-icon::before {
       content: "";
       position: absolute;
       inset: -4px;
       border-radius: calc(var(--icon-radius) + 4px);
       pointer-events: none;
       z-index: 1;
       box-shadow: none;
       opacity: 0;
       transition: opacity .12s ease, box-shadow .12s ease;
   }
   /* estado ativo: manter ring interno e adicionar halo externo */
   .icon-bar .skill-icon.active::after {
       box-shadow: inset 0 0 0 var(--icon-active) !important;
   }
   .icon-bar .skill-icon.active::before {
       opacity: 1;
       box-shadow:
           0 0 12px 3px var(--icon-active-glow),
           0 0 0 calc(var(--icon-ring-w) * 2) var(--icon-active-ring) !important;
   }
   /* prevenir que regras anteriores escondam o efeito */
   .icon-bar .skill-icon,
   .icon-bar .skill-icon img {
       /* garantir que o contorno pseudo fique visível ao redor da imagem */
       backface-visibility: hidden;
       -webkit-backface-visibility: hidden;
       transform: translateZ(0);
   }
   /* opcional: ligeiro contraste no hover */
   .icon-bar .skill-icon:hover::after {
       box-shadow: inset 0 0 0 var(--icon-ring-w) #e6e6e6 !important;
   }
   /* Tooltip style (single global tooltip attached to body to avoid clipping) */
   .skill-tooltip {
       position: fixed;
       z-index: 9999;
       pointer-events: none;
       padding: 6px 8px;
       border-radius: 6px;
       background: rgba(17, 17, 17, .9);
       color: #fff;
       font-size: 14px;
       box-shadow: 0 4px 12px rgba(0, 0, 0, .5);
       opacity: 0;
       transition: opacity .12s ease, transform .08s ease;
       white-space: nowrap;
   }
   /* Icon clipping, ring and active halo (overrides; scoped to icons only) */
   :root {
       --icon-ring-w: 2px;
       --icon-idle: #bbb;
       --icon-active: #FFD95A;
       /* amarelo mais visível */
       --icon-active-ring: rgba(255, 217, 90, .50);
       --icon-active-glow: rgba(255, 217, 90, .38);
   }
   .icon-bar .skill-icon {
       position: relative;
       border: none !important;
       outline: none !important;
       overflow: hidden;
       border-radius: var(--icon-radius);
       contain: paint;
       isolation: isolate;
       will-change: transform;
       transform: translateZ(0);
       /* keep original sizing/flow from existing rules (do not change --icon-size) */
   }
   .icon-bar .skill-icon img {
       display: block;
       width: 100%;
       height: 100%;
       object-fit: cover;
       border-radius: inherit;
       -webkit-clip-path: inset(0 round var(--icon-radius));
       clip-path: inset(0 round var(--icon-radius));
       transition: transform .12s ease;
       backface-visibility: hidden;
       transform: translateZ(0);
   }
   .icon-bar .skill-icon::after {
       content: "";
       position: absolute;
       inset: 0;
       border-radius: inherit;
       pointer-events: none;
       z-index: 2;
       /* internal ring that NEVER changes thickness between states */
       box-shadow: inset 0 0 0 var(--icon-ring-w) var(--icon-idle);
       transition: box-shadow .12s ease;
   }
   .icon-bar .skill-icon::before {
       content: "";
       position: absolute;
       inset: -2px;
       border-radius: calc(var(--icon-radius) + 2px);
       pointer-events: none;
       z-index: 1;
       box-shadow: none;
       opacity: 0;
       transition: opacity .12s ease, box-shadow .12s ease;
   }
   /* Active state: gentle scale + yellow ring + halo. No change in ring thickness. */
   .icon-bar .skill-icon.active {
       transform: scale(1.08);
   }
   .icon-bar .skill-icon.active::after {
       box-shadow: inset 0 0 0 var(--icon-active);
   }
   .icon-bar .skill-icon.active::before {
       opacity: 1;
       box-shadow:
           0 0 12px 3px var(--icon-active-glow),
           0 0 0 4px var(--icon-active-ring);
   }
   .icon-bar .skill-icon.active img {
       transform: scale(1.08);
   }
   /* Hover should never change ring thickness — only color hint */
   .icon-bar .skill-icon:hover:not(.active)::after {
       box-shadow: inset 0 0 0 var(--icon-ring-w) #e0e0e0;
   }
   /* ===========================
  Fixed background (scoped to article content only)
  =========================== */
   /* aplicar o background apenas quando .character-box estiver dentro do conteúdo do artigo */
   .mw-body-content .character-box {
       background-image: url("https://i.imgur.com/RktmgO8.png");
       background-position: center top;
       background-repeat: no-repeat;
       /* keep the visual background stable when content height changes.
      using fixed attachment prevents the artwork from scaling as the box grows. */
       background-size: cover;
       background-attachment: fixed;
       position: relative;
       /* stacking context para pseudo-elementos */
       z-index: 1;
   }
   /* overlay interno (escuro) acima do background mas abaixo do conteúdo da caixa */
   .mw-body-content .character-box::before {
       content: "";
       position: absolute;
       inset: 0;
       pointer-events: none;
       background: linear-gradient(to bottom, rgba(0, 0, 0, .45), rgba(0, 0, 0, .60));
       z-index: 0;
       /* abaixo do conteúdo (.character-box deve ter z-index > 0) */
   }
   /* remove any previous global fixed rules that targeted body.character-bg .character-box
  NOTE: original reset removed the background we want; removed to keep .character-box background. */
   /* (reset removed) */
   /* skins "card" visuals: show sprite on top of a darker art/background like a trading card */
   /* grid of square skin-cards — no ugly horizontal scroll; min square 120x120 */
   .card-skins,
   .skins-carousel {
       display: grid;
       grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
       gap: 12px;
       align-items: start;
       justify-items: center;
       width: 100%;
       padding: 8px 4px;
       box-sizing: border-box;
       overflow-x: hidden;
   }
   .skin-card {
       position: relative;
       width: 100%;
       max-width: 240px;
       min-width: 120px;
       aspect-ratio: 1 / 1;
       border-radius: 12px;
       overflow: hidden;
       box-shadow: 7px 5px 10px rgb(0 0 0 / 45%);
       background: #0f0f12;
       display: grid;
       place-items: center;
       box-sizing: border-box;
   }
   .skin-card .skin-banner {
       position: absolute;
       inset: 0;
       z-index: 0;
       overflow: hidden;
   }
   .skin-card .skin-banner img {
       width: 110%;
       height: 110%;
       object-fit: cover;
       object-position: center;
       transform: scale(1.30);
       filter: brightness(.36) saturate(.8) contrast(.9);
       display: block;
   }
   .skin-card .skin-sprite {
       position: relative;
       z-index: 2;
       display: flex;
       align-items: center;
       justify-content: center;
       width: 90%;
       height: 90%;
       pointer-events: none;
   }
   .skin-card .skin-sprite img {
       width: 100%;
       height: 100%;
       object-fit: contain;
       transform-origin: center;
       transform: scale(1.02);
       display: block;
       filter: drop-shadow(0 8px 18px rgba(0, 0, 0, .6));
       box-shadow: 0 0 0 2px rgba(200,200,200,0.85);
       border-radius: 8px;
   }
   @media (max-width: 820px) {
       .card-skins,
       .skins-carousel {
           grid-template-columns: repeat(auto-fill, minmax(120px, 160px));
           justify-content: center;
       }
       .skin-card {
           max-width: 200px;
       }
   }
   /* Mobile: garantir vídeo centralizado dentro do card/coluna */
   @media (max-width: 1100px) {
       .video-container {
           margin: 0 auto;
           /* centra horizontalmente */
           justify-self: center;
           align-self: center;
           display: flex;
           justify-content: center;
           /* centro do conteúdo interno (video) */
       }
       .video-container>video {
           margin: 0 auto;
           display: block;
       }
   }
   @media (max-width: 600px) {
       /* remove internal scrolling: deixe a descrição expandir a página */
       .desc {
           /* Previously this forced expansion on small screens. Keep commented so only
              the intentional mobile behavior below (if any) can be enabled separately.
              max-height: none !important;
              overflow-y: visible !important;
              flex: 0 0 auto !important;
           */
       }
       /* permita que o box expanda com o conteúdo */
       .desc-box {
           overflow: visible !important;
           height: auto !important;
           min-height: 0 !important;
           align-items: stretch !important;
       }
       /* garantir que o card possa crescer com a descrição (evita scroll interno/clipping) */
       .content-card {
           overflow: visible !important;
       }
       /* já existiam regras para .desc/.desc-box; reforçar para evitar qualquer overflow
          (kept desc commented above to avoid contradicting fixed 400px limit) */
       .desc {
           /* max-height: none !important;
              overflow-y: visible !important;
              flex: 0 0 auto !important;
           */
       }
       .desc-box {
           overflow: visible !important;
           height: auto !important;
           min-height: 0 !important;
           align-items: stretch !important;
       }
   }
   /* Forçar cores / bordas dos ícones por cima de regras duplicadas */
   :root {
       --icon-idle: #d0d0d0;
       /* neutro mais suave */
       --icon-active: #FFD95A;
       /* amarelo ativo */
       --icon-active-ring: rgba(255, 217, 90, 0.50);
       --icon-active-glow: rgba(255, 217, 90, 0.30);
       --icon-ring-w: 2px;
   }
   /* garantir anel interno consistente (usa --icon-ring-w) */
   .icon-bar .skill-icon::after {
       box-shadow: inset 0 0 0 var(--icon-ring-w) var(--icon-idle) !important;
       transition: box-shadow .12s ease !important;
   }
   /* halo/contorno ativo — usar largura fixa do ring e halo externo */
   .icon-bar .skill-icon.active::after {
       box-shadow: inset 0 0 0 var(--icon-ring-w) var(--icon-active) !important;
   }
   .icon-bar .skill-icon::before {
       inset: -4px;
       border-radius: calc(var(--icon-radius) + 4px);
       opacity: 0;
       transition: opacity .12s ease, box-shadow .12s ease;
   }
   .icon-bar .skill-icon.active::before {
       opacity: 1 !important;
       box-shadow:
           0 0 14px 4px var(--icon-active-glow),
           0 0 0 calc(var(--icon-ring-w) * 2) var(--icon-active-ring) !important;
   }
   /* garantir visibilidade mesmo quando outras regras conflitarem */
   .icon-bar .skill-icon,
   .icon-bar .skill-icon img,
   .icon-bar .skill-icon::after,
   .icon-bar .skill-icon::before {
       -webkit-backface-visibility: hidden;
       backface-visibility: hidden;
       transform: translateZ(0);
   }
   /* hover não muda a espessura do anel */
   .icon-bar .skill-icon:hover:not(.active)::after {
       box-shadow: inset 0 0 0 var(--icon-ring-w) #e6e6e6 !important;
   }

</style>

<style>

   /* apply at larger breakpoint so narrow desktop + mobile are covered */
   @media (max-width:1200px) {
       /* COMMENTED OUT: this override allowed .desc to expand infinitely and conflicted
          with the intended 400px max-height rule at the end of file.
       .mw-body-content #skills .desc {
           max-height: none !important;
           overflow-y: visible !important;
           flex: 0 0 auto !important;
       }
       */
       .mw-body-content #skills .desc-box {
           overflow: visible !important;
           height: auto !important;
           min-height: 0 !important;
           align-items: stretch !important;
       }
       .mw-body-content #skills .content-card {
           overflow: visible !important;
       }
       /* keep top-rail safe (no side effects) */
       .mw-body-content #skills .top-rail {
           overflow: hidden;
       }
   }

</style>

<style>

   .mw-body-content #skills .desc {
       max-height: 300px;
       overflow-y: auto;
       overflow-x: hidden;
       -webkit-overflow-scrolling: touch;
   }
   /* make scrollbar slim and visually consistent */
   .mw-body-content #skills .desc::-webkit-scrollbar {
       width: 8px;
   }
   .mw-body-content #skills .desc::-webkit-scrollbar-thumb {
       background: rgba(21, 107, 199, 0.9);
       border-radius: 8px;
   }
   .mw-body-content #skills .desc::-webkit-scrollbar-track {
       background: transparent;
   }

</style>