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

De Wiki Gla
Ir para navegação Ir para pesquisar
m
Etiqueta: Revertido
m
Etiqueta: Reversão manual
Linha 151: Linha 151:
                 v.style.aspectRatio = '16/9';
                 v.style.aspectRatio = '16/9';
                 v.style.objectFit = 'cover';
                 v.style.objectFit = 'cover';
                // create source and set MIME based on extension (avoid forcing webm for mp4 files)
                 const source = document.createElement('source');
                 const source = document.createElement('source');
                 source.src = src;
                 source.src = src;
                 const ext = (src.split('?')[0].split('.').pop() || '').toLowerCase();
                 source.type = 'video/webm';
                if (ext === 'mp4') source.type = 'video/mp4';
                else if (ext === 'webm') source.type = 'video/webm';
                // prefer metadata only to trigger loadedmetadata quickly (dimensions) and reduce bandwidth
                v.setAttribute('preload', 'metadata');
                // allow crossorigin if server supports it (helps some hosts)
                v.crossOrigin = 'anonymous';
                 v.appendChild(source);
                 v.appendChild(source);
                // fallback: if browser errors due to incorrect/mismatched type, try removing type and reload once
                const tryTypeFallback = (ev) => {
                    // only attempt once
                    if (source.getAttribute('data-fallback-tried')) return;
                    source.setAttribute('data-fallback-tried', '1');
                    if (source.hasAttribute('type')) {
                        source.removeAttribute('type');
                        try { v.load(); } catch (e) { /* ignore */ }
                    }
                };
                v.addEventListener('error', tryTypeFallback, { once: true });


                 v.addEventListener('canplay', () => {
                 v.addEventListener('canplay', () => {
Linha 216: Linha 197:


             el.title = name;
             el.title = name;
            // styled tooltip uses data-title (keeps native title for accessibility)
            el.setAttribute('data-title', name);
             el.addEventListener('click', () => {
             el.addEventListener('click', () => {
                 // update description area
                 // update description area
Linha 680: Linha 658:
         --icon-radius: 8px;
         --icon-radius: 8px;
         --icon-idle: #bbb;
         --icon-idle: #bbb;
         --icon-active: #f0c842; /* pleasant yellow */
         --icon-active: #156bc7;
         --icon-active-glow: rgba(240,200,66,0.28);
         --icon-active-ring: rgba(21, 107, 199, .35);
     }
     }


Linha 691: Linha 669:
         flex: 0 0 auto;
         flex: 0 0 auto;
         border-radius: var(--icon-radius);
         border-radius: var(--icon-radius);
         overflow: visible; /* allow tooltip (::before) to escape the box */
         overflow: hidden;
         margin-top: 0;
         margin-top: 0;
         display: flex;
         display: flex;
Linha 697: Linha 675:
         justify-content: center;
         justify-content: center;
     }
     }
   
 
    /* concrete image clipping — use border-radius on the image itself and avoid absolute bleed */
     .icon-bar .skill-icon img {
     .icon-bar .skill-icon img {
         position: relative;
         position: absolute;
        inset: 0;
         width: 100%;
         width: 100%;
         height: 100%;
         height: 100%;
         object-fit: cover;
         object-fit: cover;
         border-radius: var(--icon-radius) !important; /* force rounded corners */
         border-radius: var(--icon-radius);
        box-shadow: none !important; /* remove internal shine */
         -webkit-clip-path: inset(0 round var(--icon-radius));
        display: block;
         clip-path: inset(0 round var(--icon-radius));
         -webkit-clip-path: none;
         clip-path: none;
     }
     }


    /* decorative ring (idle) kept in ::after — box-sizing prevents half-pixel overflow */
     .icon-bar .skill-icon::after {
     .icon-bar .skill-icon::after {
         content: "";
         content: "";
         position: absolute;
         position: absolute;
         inset: 0;
         inset: 0;
         border-radius: inherit;
         border-radius: var(--icon-radius);
         border: 2px solid var(--icon-idle);
         border: 2px solid var(--icon-idle);
        /* removed inset highlight to avoid inner shiny edge */
         box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .25);
         box-shadow: none;
         pointer-events: none;
         pointer-events: none;
         z-index: 2;
         z-index: 2;
        box-sizing: border-box;
        transition: border-color .15s ease, box-shadow .18s ease, transform .12s ease;
     }
     }


    /* hover subtle highlight */
     .icon-bar .skill-icon:hover::after {
     .icon-bar .skill-icon:hover::after {
         border-color: rgba(255,255,255,0.95);
         border-color: #e0e0e0;
        box-shadow: inset 0 0 0 1px #e0e0e0;
     }
     }


    /* active state: pleasant yellow + soft glow */
     .icon-bar .skill-icon.active::after {
     .icon-bar .skill-icon.active::after {
         border-color: var(--icon-active);
         border-color: var(--icon-active);
         box-shadow:
         box-shadow: 0 0 0 2px var(--icon-active), 0 0 0 4px var(--icon-active-ring);
        0 6px 18px var(--icon-active-glow),
        0 0 0 3px rgba(240,200,66,0.10);
        transform: translateY(-1px);
     }
     }


    /* small press feedback when clicking non-active icons */
     .icon-bar .skill-icon:active:not(.active) {
     .icon-bar .skill-icon:active:not(.active) {
         transform: translateY(1px);
         transform: translateY(1px);
     }
     }


     /* Custom tooltip (styled) — uses data-title set by JS. Keeps native title for accessibility/browser tooltips. */
     @media (prefers-reduced-motion: reduce) {
    .icon-bar .skill-icon::before {
         .icon-bar .skill-icon {
        content: attr(data-title);
            transition: none;
        position: absolute;
         }
        left: 50%;
        transform: translateX(-50%) translateY(6px);
        bottom: 100%;
        background: rgba(18,18,18,0.95);
        color: #fff;
        padding: 6px 8px;
        border-radius: 6px;
        font-size: 12px;
        white-space: nowrap;
        box-shadow: 0 6px 18px rgba(0,0,0,0.45);
        opacity: 0;
        pointer-events: none;
        z-index: 12;
        transition: opacity .12s ease, transform .12s ease;
        transform-origin: bottom center;
    }
 
    /* show tooltip on hover/focus */
    .icon-bar .skill-icon:hover::before,
    .icon-bar .skill-icon:focus::before,
    .icon-bar .skill-icon:focus-within::before {
        opacity: 1;
        transform: translateX(-50%) translateY(0);
    }
 
    /* tiny caret */
    .icon-bar .skill-icon::after,
    .icon-bar .skill-icon::before { /* ensure tooltip sits above ring */
         z-index: 3;
    }
    .icon-bar .skill-icon::before { z-index: 14; }
 
    /* ensure focus styles for keyboard accessibility */
    .icon-bar .skill-icon:focus {
        outline: none;
         box-shadow: 0 0 0 3px rgba(240,200,66,0.10);
     }
     }


Linha 835: Linha 766:
         letter-spacing: .01em;
         letter-spacing: .01em;
         /* preferred CSS fallback — JS will override to the video height when possible */
         /* preferred CSS fallback — JS will override to the video height when possible */
         max-height: clamp(10rem, 37vh, 21rem);
         max-height = clamp(10rem, 37vh, 21rem);
         /* keep scrollbar gutter stable to avoid layout shift of background/content */
         /* keep scrollbar gutter stable to avoid layout shift of background/content */
         overflow-y: auto;
         overflow-y: auto;
Linha 1 211: Linha 1 142:
     --icon-size: 56px;  /* desktop icons larger */
     --icon-size: 56px;  /* desktop icons larger */
     --icon-radius: 10px;
     --icon-radius: 10px;
    --icon-active: #f0c842; /* pleasant yellow */
    --icon-active-glow: rgba(240,200,66,0.28);
}
}


Linha 1 219: Linha 1 148:
     width: var(--icon-size) !important;
     width: var(--icon-size) !important;
     height: var(--icon-size) !important;
     height: var(--icon-size) !important;
    position: relative;
    overflow: hidden; /* ensure image never escapes the rounded container */
    border-radius: var(--icon-radius);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
}


/* concrete image clipping — use border-radius on the image itself and avoid absolute bleed */
/* attributes: same sizing on desktop + mobile, more visible */
.icon-bar .skill-icon img {
.desc-box .attr-label {
     position: relative;
     font-size: 1.08rem !important;   /* label */
    width: 100%;
     font-weight: 800;
    height: 100%;
     color: #f0c87b;
    object-fit: cover;
    border-radius: inherit; /* match parent rounding */
     display: block;
    -webkit-clip-path: none;
     clip-path: none;
}
}


/* decorative ring (idle) kept in ::after — box-sizing prevents half-pixel overflow */
.desc-box .attr-value {
.icon-bar .skill-icon::after {
     font-size: 1.28rem !important;   /* value noticeably larger */
     content: "";
     font-weight: 900;
    position: absolute;
     color: #fff;
    inset: 0;
    border-radius: inherit;
    border: 2px solid var(--icon-idle);
    box-shadow: inset 0 0 0 1px rgba(255,255,255,.08);
     pointer-events: none;
     z-index: 2;
    box-sizing: border-box;
    transition: border-color .15s ease, box-shadow .18s ease, transform .12s ease;
}
}


/* hover subtle highlight */
/* slightly larger description text and comfortable line-height */
.icon-bar .skill-icon:hover::after {
.desc {
     border-color: rgba(255,255,255,0.95);
    font-size: 1.32em !important;
     line-height: 1.7 !important;
}
}


/* active state: pleasant yellow + soft glow */
/* ---------------------------
.icon-bar .skill-icon.active::after {
  Fixed background (scoped to article content only)
     border-color: var(--icon-active);
  --------------------------- */
     box-shadow:
/* aplicar o background apenas quando .character-box estiver dentro do conteúdo do artigo */
        0 6px 18px var(--icon-active-glow),
.mw-body-content .character-box {
        0 0 0 3px rgba(240,200,66,0.10);
     background-image: url("https://i.imgur.com/RktmgO8.png");
     transform: translateY(-1px);
    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;
}
}


/* small press feedback when clicking non-active icons */
/* overlay interno (escuro) acima do background mas abaixo do conteúdo da caixa */
.icon-bar .skill-icon:active:not(.active) {
.mw-body-content .character-box::before {
    transform: translateY(1px);
     content: "";
}
 
/* Custom tooltip (styled) — uses data-title set by JS. Keeps native title for accessibility/browser tooltips. */
.icon-bar .skill-icon::before {
     content: attr(data-title);
     position: absolute;
     position: absolute;
     left: 50%;
     inset: 0;
    transform: translateX(-50%) translateY(6px);
    bottom: 100%;
    background: rgba(18,18,18,0.95);
    color: #fff;
    padding: 6px 8px;
    border-radius: 6px;
    font-size: 12px;
    white-space: nowrap;
    box-shadow: 0 6px 18px rgba(0,0,0,0.45);
    opacity: 0;
     pointer-events: none;
     pointer-events: none;
     z-index: 12;
     background: linear-gradient(to bottom, rgba(0,0,0,.45), rgba(0,0,0,.60));
    transition: opacity .12s ease, transform .12s ease;
     z-index: 0; /* abaixo do conteúdo (.character-box deve ter z-index > 0) */
    transform-origin: bottom center;
}
 
/* show tooltip on hover/focus */
.icon-bar .skill-icon:hover::before,
.icon-bar .skill-icon:focus::before,
.icon-bar .skill-icon:focus-within::before {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}
 
/* tiny caret */
.icon-bar .skill-icon::after,
.icon-bar .skill-icon::before { /* ensure tooltip sits above ring */
    z-index: 3;
}
.icon-bar .skill-icon::before { z-index: 14; }
 
/* ensure focus styles for keyboard accessibility */
.icon-bar .skill-icon:focus {
    outline: none;
    box-shadow: 0 0 0 3px rgba(240,200,66,0.10);
}
 
/* 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;
        overflow: visible;
        text-shadow: none;
        /* allow description area to grow but not force whole card height */
        height: auto;
        min-height: 0;
    }
 
    .desc-box h3 {
        font-size: 2.7em;
        margin: 0;
        text-align: center;
        padding-top: 0;
    }
 
    .desc {
        font-size: 1.32em !important;
        line-height: 1.7 !important;
        letter-spacing: .01em;
        /* preferred CSS fallback — JS will override to the video height when possible */
        max-height: clamp(10rem, 37vh, 21rem);
        /* keep scrollbar gutter stable to avoid layout shift of background/content */
        overflow-y: auto;
        scrollbar-gutter: stable;
        margin-top: 10px;
        padding-right: 8px;
        color: #f1efe9;
        /* allow long words/URLs to wrap instead of pushing layout */
        overflow-wrap: anywhere;
        word-break: break-word;
        white-space: normal;
    }
 
    .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 {
        visibility: hidden;
    }
 
    .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;
    }
}
}


/* ===========================
/* remove any previous global fixed rules that targeted body.character-bg .character-box
  Base — mobile/overflow guards
  NOTE: original reset removed the background we want; removed to keep .character-box background. */
  =========================== */
/* (reset removed) */
/* evitar qualquer elemento extrapolar o viewport e respeitar safe-area (iPhone notch) */
</style>
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;
}
 
/* ===== Overrides finais: scope dentro de .character-box para não afetar o resto do site ===== */
.character-box .icon-bar .skill-icon {
    overflow: hidden !important;            /* garantir que a imagem seja cortada pelos cantos arredondados */
    border-radius: var(--icon-radius) !important;
    box-shadow: none !important;
}
 
/* força cantos arredondados na imagem e remove qualquer brilho interno */
.character-box .icon-bar .skill-icon img {
    border-radius: var(--icon-radius) !important;
    -webkit-border-radius: var(--icon-radius) !important;
    box-shadow: none !important;
    display: block;
}
 
/* remove qualquer inset/shine do anel decorativo */
.character-box .icon-bar .skill-icon::after {
    box-shadow: none !important;
}
 
/* remover tooltip estilizado (usar apenas title nativo do elemento) */
.character-box .icon-bar .skill-icon::before {
    display: none !important;
    content: none !important;
    pointer-events: none !important;
}
 
/* evitar que description overflow quebre fundo/layout */
.character-box .desc-box {
    overflow: hidden !important;
}
 
/* garantia: estilos mais específicos para casos mobile/desktop onde haja duplicatas */
.character-box .icon-bar .skill-icon:focus {
    outline: none;
    box-shadow: 0 0 0 3px rgba(240,200,66,0.10) !important;
}

Edição das 02h31min de 25 de agosto de 2025

<script>

   (function () {
       const $ = (s, root = document) => root.querySelector(s);
       const $$ = (s, root = document) => Array.from(root.querySelectorAll(s));
       // Idempotent helpers
       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; };
       // Basic DOM nodes
       const skillsTab = $('#skills');
       const skinsTab = $('#skins');
       // Clean up legacy nodes/titles/placeholders before building
       ensureRemoved('.top-rail');
       ensureRemoved('.content-card');
       ensureRemoved('.video-placeholder');
       // remove old duplicated skins titles (text match)
       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')) {
               // keep only if it's inside a future top-rail.skins we will create; remove for now
               t.remove();
           }
       });
       // Build top-rail for skills (only icon-bar, centered)
       if (skillsTab) {
           const iconBar = skillsTab.querySelector('.icon-bar');
           if (iconBar) {
               const rail = document.createElement('div');
               rail.className = 'top-rail skills';
               // center icon bar inside rail
               rail.appendChild(iconBar);
               skillsTab.prepend(rail);
           }
       }
       // Build top-rail for skins (single title + keep carousel wrapper)
       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);
           }
       }
       // Create content-card for skills (description + video) and move nodes in
       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);
       }
       // ----- Elements after build
       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;
       // Video cache and state
       const videosCache = new Map();
       let totalVideos = 0, loadedVideos = 0, autoplay = false;
       // Single placeholder node: create once at page load and never re-create later.
       let placeholder = videoBox ? videoBox.querySelector('.video-placeholder') : null;
       let placeholderCreatedOnLoad = false;
       // true once the single placeholder was used/consumed (only show for the first active video)
       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) {
           // If a placeholder already exists in DOM (legacy), mark it as created on load.
           placeholderCreatedOnLoad = true;
       }
       if (!placeholder) placeholderConsumed = true; // nothing to show
       // Robust hide/show: fade-out hides the single placeholder but keeps it in DOM
       // so it can be reused without duplication. Removal (DOM delete) is avoided.
       const removePlaceholderSmooth = () => {
           if (!placeholder) return;
           if (placeholder.classList.contains('fade-out')) return;
           placeholder.classList.add('fade-out');
           // when transition completes, keep node but hide it so showPlaceholder can reuse.
           const onEnd = () => {
               try { placeholder.style.display = 'none'; } catch (e) { /* ignore */ }
               placeholder.removeEventListener('transitionend', onEnd);
           };
           placeholder.addEventListener('transitionend', onEnd, { once: true });
           // fallback ensure it's hidden
           setTimeout(() => { try { placeholder.style.display = 'none'; } catch (e) {} }, 600);
       };
       // showPlaceholder: shows the single placeholder created at load (no new nodes).
       const showPlaceholder = () => {
           if (!videoBox) return;
           if (!placeholder || !placeholderCreatedOnLoad) return;
           if (placeholderConsumed) return; // never show again after first use
           placeholder.classList.remove('fade-out');
           placeholder.style.display = 'flex';
           // force reflow to ensure transition apply on hide later
           void placeholder.offsetWidth;
       };
       // Utility: attach listener only once per element
       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');
       };
       // Preload videos (idempotent: skip if present in map)
       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;
               // prefer consistent sizing: width 100% inside video container, and use 16:9 to avoid layout jumps
               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) {
                       // remove placeholder for the active video (only once)
                       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) {
           // no videos: hide placeholder but keep the node for idempotence
           placeholder.style.display = 'none';
           placeholder.classList.add('fade-out');
       }
       // Attach skill icon click handlers once
       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', () => {
               // update description area
               if (descBox) {
                   descBox.innerHTML = `

${name}

 ${renderAttributes(attrs)}
${desc}

`;

               }
               // switch videos: hide all, show selected (if any)
               videosCache.forEach(v => { try { v.pause(); } catch (e) { } v.style.display = 'none'; });
               if (videoBox) {
                   if (hasVideo && videosCache.has(idx)) {
                       const v = videosCache.get(idx);
                       // ensure video container visible and video fills container consistently
                       videoBox.style.display = 'block';
                       v.style.display = 'block';
                       try { v.currentTime = 0; } catch (e) {}
                       // show the (single) placeholder until this video can play
                       if (v.readyState >= 3) {
                           if (!placeholderConsumed) { removePlaceholderSmooth(); placeholderConsumed = true; }
                       } else {
                           // show placeholder only if it hasn't been used yet
                           if (!placeholderConsumed) {
                               showPlaceholder();
                               const canplayHandler = () => { removePlaceholderSmooth(); placeholderConsumed = true; v.removeEventListener('canplay', canplayHandler); };
                               v.addEventListener('canplay', canplayHandler);
                           }
                       }
                       if (autoplay) v.play().catch(() => { });
                   } else {
                       // no video for this skill: hide video area and hide placeholder
                       videoBox.style.display = 'none';
                       if (placeholder) {
                           placeholder.style.display = 'none';
                           placeholder.classList.add('fade-out');
                       }
                   }
               }
               // active state
               iconItems.forEach(i => i.classList.remove('active'));
               el.classList.add('active');
               if (!autoplay && loadedVideos > 0) autoplay = true;
           });
       });
       // Select first skill by default (dispatch click once)
       if (iconItems.length) {
           const first = iconItems[0];
           if (first) {
               // ensure default active visual & trigger behavior
               if (!first.classList.contains('active')) first.classList.add('active');
               // trigger click after microtask so videos are ready to be shown
               setTimeout(() => first.click(), 0);
           }
       }
       // Keep .desc max-height synced to the visible video height so long descriptions
       // scroll instead of pushing the layout and stretching the background.
       function syncDescHeight() {
           if (!descBox || !videoBox) return;
           const descEl = descBox.querySelector('.desc');
           if (!descEl) return;
           // if video area hidden, restore CSS fallback (clamp)
           const computedDisplay = getComputedStyle(videoBox).display;
           if (computedDisplay === 'none') {
               descEl.style.maxHeight = ;
               return;
           }
           // prefer measuring video element if present, fallback to videoBox
           const v = videoBox.querySelector('video');
           const targetHeight = (v && v.offsetHeight > 0) ? v.offsetHeight : videoBox.clientHeight;
           if (!targetHeight || targetHeight <= 0) {
               descEl.style.maxHeight = ;
               return;
           }
           // subtract vertical padding on desc element to keep inner scroll consistent
           const cs = getComputedStyle(descEl);
           const padTop = parseFloat(cs.paddingTop) || 0;
           const padBottom = parseFloat(cs.paddingBottom) || 0;
           const maxH = Math.max(64, targetHeight - padTop - padBottom); // ensure a minimum
           descEl.style.maxHeight = `${maxH}px`;
       }
       // keep in sync on resize and when videos change layout
       window.addEventListener('resize', syncDescHeight);
       if (videoBox) new ResizeObserver(syncDescHeight).observe(videoBox);
       // call sync after each icon click (desc is rebuilt there)
       // patch: wrap existing click wiring to call syncDescHeight after updating DOM
       iconItems.forEach(el => {
           const wired = !!el.dataset._sync_wired;
           if (wired) return;
           el.dataset._sync_wired = '1';
           // find existing click handler we attached earlier and chain sync
           el.addEventListener('click', () => {
               // run in next microtask so DOM update from earlier handler is settled
               Promise.resolve().then(syncDescHeight);
           });
       });
       // horizontal scroll on wheel (attach once)
       if (iconsBar) addOnce(iconsBar, 'wheel', (e) => {
           if (e.deltaY) {
               e.preventDefault();
               iconsBar.scrollLeft += e.deltaY;
           }
       });
       // skins carousel arrows init (idempotent)
       (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();
       })();
       // Render attributes function (keeps empty rows above visible ones)
       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 !== '-');
           const empties = rows.length - visible.length;
           const emptyHtml = Array.from({ length: empties }).map(() => `
                    
                    
           `).join();
           const visibleHtml = visible.map(([label, value]) => `
                   ${label}:
                   ${value}
           `).join();
           if (visible.length === 0) {
               // still keep one empty row to preserve spacing but on top

return `

${emptyHtml || `\n
\n  \n  \n
\n `}

`;

           }

return `

${emptyHtml}${visibleHtml}

`;

       }
       // language-aware tab label for Skills
       (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'
           };
           // prefer full match (pt-br) then base code
           const key = map[lang] ? lang : (map[code] ? code : 'en');
           const label = map[key] || map.en;
           // try well-known selector first, fallback to searching for english-like text
           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;
       })();
       // DEBUG: log video sources and errors
       setTimeout(() => {
           console.log('DEBUG: totalVideos=', totalVideos);
           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 0; /* 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;
       --icon-idle: #bbb;
       --icon-active: #156bc7;
       --icon-active-ring: rgba(21, 107, 199, .35);
   }
   /* ensure each icon is vertically centered inside the bar */
   .icon-bar .skill-icon {
       width: var(--icon-size);
       height: var(--icon-size);
       position: relative;
       flex: 0 0 auto;
       border-radius: var(--icon-radius);
       overflow: hidden;
       margin-top: 0;
       display: flex;
       align-items: center;
       justify-content: center;
   }
   .icon-bar .skill-icon img {
       position: absolute;
       inset: 0;
       width: 100%;
       height: 100%;
       object-fit: cover;
       border-radius: var(--icon-radius);
       -webkit-clip-path: inset(0 round var(--icon-radius));
       clip-path: inset(0 round var(--icon-radius));
   }
   .icon-bar .skill-icon::after {
       content: "";
       position: absolute;
       inset: 0;
       border-radius: var(--icon-radius);
       border: 2px solid var(--icon-idle);
       box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .25);
       pointer-events: none;
       z-index: 2;
   }
   .icon-bar .skill-icon:hover::after {
       border-color: #e0e0e0;
       box-shadow: inset 0 0 0 1px #e0e0e0;
   }
   .icon-bar .skill-icon.active::after {
       border-color: var(--icon-active);
       box-shadow: 0 0 0 2px var(--icon-active), 0 0 0 4px var(--icon-active-ring);
   }
   .icon-bar .skill-icon:active:not(.active) {
       transform: translateY(1px);
   }
   @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;
       overflow: visible;
       text-shadow: none;
       /* allow description area to grow but not force whole card height */
       height: auto;
       min-height: 0;
   }
   .desc-box h3 {
       font-size: 2.7em;
       margin: 0;
       text-align: center;
       padding-top: 0;
   }
   .desc {
       font-size: 1.32em !important;
       line-height: 1.7 !important;
       letter-spacing: .01em;
       /* preferred CSS fallback — JS will override to the video height when possible */
       max-height = clamp(10rem, 37vh, 21rem);
       /* keep scrollbar gutter stable to avoid layout shift of background/content */
       overflow-y: auto;
       scrollbar-gutter: stable;
       margin-top: 10px;
       padding-right: 8px;
       color: #f1efe9;
       /* allow long words/URLs to wrap instead of pushing layout */
       overflow-wrap: anywhere;
       word-break: break-word;
       white-space: normal;
   }
   .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 {
       visibility: hidden;
   }
   .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;

}

/* attributes: same sizing on desktop + mobile, more visible */ .desc-box .attr-label {

   font-size: 1.08rem !important;    /* label */
   font-weight: 800;
   color: #f0c87b;

}

.desc-box .attr-value {

   font-size: 1.28rem !important;    /* value noticeably larger */
   font-weight: 900;
   color: #fff;

}

/* slightly larger description text and comfortable line-height */ .desc {

   font-size: 1.32em !important;
   line-height: 1.7 !important;

}

/* ---------------------------

  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) */ </style>