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

De Wiki Gla
Ir para navegação Ir para pesquisar
m
 
(18 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 1: Linha 1:
<div class="gla-conquistas-headerbox">
<includeonly>
  <div class="gla-conquistas-header">
    <!--
    <h2>Conquistas</h2>
      Widget:Conquistas — depende de Widget:Item.
    <p>Acompanhe as conquistas disponíveis no Grand Line Adventures.</p>
  </div>


  <div class="gla-conquistas-tabs">
      Uso obrigatório na página da wiki:
    <span class="gla-conquistas-tab is-active" data-tab="geral">Geral</span>
          {{#widget:Item}}
    <span class="gla-conquistas-tab" data-tab="personagens">Personagens</span>
          {{#widget:Conquistas}}
    <span class="gla-conquistas-tab" data-tab="missao">Missão</span>
          {{#invoke:Conquistas|renderAll}}
    <span class="gla-conquistas-tab" data-tab="bau">Baú</span>
    <span class="gla-conquistas-tab" data-tab="navegacao">Navegação</span>
    <span class="gla-conquistas-tab" data-tab="pvp">PvP</span>
    <span class="gla-conquistas-tab" data-tab="pve">PvE</span>
    <span class="gla-conquistas-tab" data-tab="coliseu">Coliseu</span>
    <span class="gla-conquistas-tab" data-tab="poneglyph">Poneglyph</span>
    <span class="gla-conquistas-tab" data-tab="indicacao">Indicação</span>
    <span class="gla-conquistas-tab" data-tab="celular">Celular</span>
    <span class="gla-conquistas-tab" data-tab="bossrush">Boss Rush</span>
  </div>
</div>


<style>
      Widget:Item é quem traz a CSS dos ícones (.reward-wrapper,
.gla-conquistas-headerbox {
      .item-wrapper, .item-count) e o JS do tooltip — mesmo padrão da
  max-width: 1100px;
      Predefinição:Reward que faz {{#widget:Item}}{{#invoke:Reward|exibir}}.
  margin: 0 auto 20px;
      Sem ele, os rewards aparecem como wikitext cru e sem tooltip.
  padding: 20px;
    -->
  border-radius: 16px;
    <!--
  background: #ffffff;
      Atributos no root:
  border: 1px solid #e5e7eb;
}


.gla-conquistas-header h2 {
      data-hidden-style controla o MARCADOR visual das conquistas hidden=true.
  margin: 0;
      Valores aceitos: "badge" | "stripes" | "ribbon" | "stamp" | "subtle".
  font-size: 26px;
      Default escolhido: "ribbon" (fita diagonal cinza "SECRETA" no canto).
  font-weight: 700;
  color: #020617;
}


.gla-conquistas-header p {
      data-reveal-mode controla a CENSURA do conteúdo das hidden=true. O
  margin: 4px 0 16px;
      conteúdo continua no HTML — só fica visualmente coberto até o jogador
  color: #64748b;
      clicar pra revelar (anti-spoiler). Valores aceitos:
  font-size: 14px;
        "none"        — sem censura
}
        "blur"        — título e descrição borrados (default)
        "redacted"    — tarjas escuras estilo doc classificado
        "placeholder" — texto substituído por "???"
        "veil"        — card inteiro coberto por overlay com CTA "clique"


.gla-conquistas-tabs {
      Pra trocar qualquer um, edita o atributo abaixo.
  display: flex;
    -->
  flex-wrap: wrap;
    <div class="gla-conquistas-root" data-hidden-style="ribbon" data-reveal-mode="blur">
  gap: 8px;
        <div class="gla-conquistas-headerbox">
}
            <div class="gla-conquistas-header">
                <h2>Conquistas</h2>
                <p>Acompanhe as conquistas disponíveis no Grand Line Adventures.</p>
            </div>


.gla-conquistas-tab {
            <div class="gla-conquistas-toolbar">
  display: inline-block;
                <div class="gla-conquistas-tabs-scroll">
  padding: 8px 14px;
                    <div class="gla-conquistas-tabs">
  border-radius: 999px;
                        <span class="gla-conquistas-tab is-active" data-tab="geral">Geral</span>
  border: 1px solid #cbd5e1;
                        <span class="gla-conquistas-tab" data-tab="personagens">Personagens</span>
  background: #f8fafc;
                        <span class="gla-conquistas-tab" data-tab="missao">Missão</span>
  cursor: pointer;
                        <span class="gla-conquistas-tab" data-tab="bau">Baú</span>
  font-size: 13px;
                        <span class="gla-conquistas-tab" data-tab="navegacao">Navegação</span>
  font-weight: 600;
                        <span class="gla-conquistas-tab" data-tab="pvp">PvP</span>
  color: #0f172a;
                        <span class="gla-conquistas-tab" data-tab="pve">PvE</span>
}
                        <span class="gla-conquistas-tab" data-tab="coliseu">Coliseu</span>
                        <span class="gla-conquistas-tab" data-tab="poneglyph">Poneglyph</span>
                        <span class="gla-conquistas-tab" data-tab="indicacao">Indicação</span>
                        <span class="gla-conquistas-tab" data-tab="celular">Celular</span>
                        <span class="gla-conquistas-tab" data-tab="bossrush">Boss Rush</span>
                    </div>
                </div>


.gla-conquistas-tab:hover {
                <div class="gla-conquistas-controls">
  background: #e2e8f0;
                    <input type="text" class="gla-conquistas-search" placeholder="Buscar conquista...">
}
                    <div class="gla-conquistas-filters" id="gla-filter-default" style="display:none">
                        <span class="gla-conquistas-filter is-active" data-filter="all">Todas</span>
                        <span class="gla-conquistas-filter" data-filter="normal">Normal</span>
                        <span class="gla-conquistas-filter" data-filter="hidden">Secreta</span>
                    </div>
                    <div class="gla-conquistas-filters" id="gla-filter-coliseu" style="display:none">
                        <span class="gla-conquistas-filter is-active" data-filter="all">Todas</span>
                        <span class="gla-conquistas-filter" data-filter="onemany">One Man Army</span>
                        <span class="gla-conquistas-filter" data-filter="corrida">Corrida Colosseum</span>
                    </div>
                </div>
            </div>
        </div>


.gla-conquistas-tab.is-active {
        <!--
  background: #0f172a;
          Painéis vazios. O Módulo:Conquistas (#invoke renderAll) emite os
  color: #ffffff;
          cards FORA do widget (Smarty não reparsa wikitext, então não dá pra
  border-color: #0f172a;
          passar como parâmetro). O JS abaixo move cada card pro painel certo
}
          a partir do data-tab.


/* PAINEL */
          Uso na página da wiki:
.gla-conquistas-panel {
              {{#widget:Conquistas}}
  max-width: 1100px;
              {{#invoke:Conquistas|renderAll}}
  margin: 20px auto 0;
        -->
  display: none;
        <div class="gla-conquistas-panel is-active" data-tab-content="geral">
}
            <div class="gla-list"></div>
        </div>
        <div class="gla-conquistas-panel" data-tab-content="personagens">
            <div class="gla-list"></div>
        </div>
        <div class="gla-conquistas-panel" data-tab-content="missao">
            <div class="gla-list"></div>
        </div>
        <div class="gla-conquistas-panel" data-tab-content="bau">
            <div class="gla-list"></div>
        </div>
        <div class="gla-conquistas-panel" data-tab-content="navegacao">
            <div class="gla-list"></div>
        </div>
        <div class="gla-conquistas-panel" data-tab-content="pvp">
            <div class="gla-list"></div>
        </div>
        <div class="gla-conquistas-panel" data-tab-content="pve">
            <div class="gla-list"></div>
        </div>
        <div class="gla-conquistas-panel" data-tab-content="coliseu">
            <div class="gla-list"></div>
        </div>
        <div class="gla-conquistas-panel" data-tab-content="poneglyph">
            <div class="gla-list"></div>
        </div>
        <div class="gla-conquistas-panel" data-tab-content="indicacao">
            <div class="gla-list"></div>
        </div>
        <div class="gla-conquistas-panel" data-tab-content="celular">
            <div class="gla-list"></div>
        </div>
        <div class="gla-conquistas-panel" data-tab-content="bossrush">
            <div class="gla-list"></div>
        </div>
    </div>


.gla-conquistas-panel.is-active {
    <style>
  display: block;
        /* Fonte para labels pequenos em maiúsculas — sem isso o navegador usa
}
          a sans-serif do skin, que fica fininha demais a 11px com tracking. */
        @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@600;700&display=swap');


/* LISTA */
        /* ─── Variáveis ──────────────────────────────────────────────────────── */
.gla-list {
        /* Tema branco fixo. Azul fica reservado para detalhes (tab/filtro ativo,
  display: flex;
          foco da busca, label da recompensa, chevron, hover). Sem dark mode
  flex-direction: column;
          automático — o widget deve manter o mesmo visual independente do skin. */
  gap: 10px;
        .gla-conquistas-root {
}
            color-scheme: light;


/* ITEM */
            /* Texto */
.gla-item {
            --gla-ink: #0f172a;
  display: flex;
            /* slate-900 — título e texto principal */
  align-items: center;
            --gla-ink-2: #475569;
  justify-content: space-between;
            /* slate-600 — texto secundário */
  gap: 16px;
            --gla-dim: #94a3b8;
  padding: 12px 14px;
            /* slate-400 — placeholder */
  border-radius: 12px;
            --gla-dim-2: #cbd5e1;
  border: 1px solid #e5e7eb;
            /* slate-300 — bordas sutis */
  background: #f8fafc;
}


/* LADO ESQUERDO */
            /* Superfícies (todas claras) */
.gla-item-left {
            --gla-paper: #ffffff;
  display: flex;
            --gla-paper-2: #f8fafc;
  align-items: center;
            /* slate-50 — hover sutil */
  gap: 12px;
            --gla-paper-3: #f1f5f9;
}
            /* slate-100 — chip recompensa */
            --gla-rule: #e2e8f0;
            /* slate-200 — bordas/divisores */


/* ICONE */
            /* Accent azul (só pra detalhes) */
.gla-item-icon img {
            --gla-accent: #2563eb;
  width: 56px;
            /* blue-600 */
  height: 56px;
            --gla-accent-soft: #60a5fa;
  object-fit: cover;
            /* blue-400 */
            --gla-accent-bg: #eff6ff;
            /* blue-50 — focus ring */


  /* REMOVE BORDA DO MEDIAWIKI */
            /* Sombra discreta */
  border: none !important;
            --gla-shadow: 0 1px 2px rgba(15, 23, 42, 0.04),
  padding: 0 !important;
                0 1px 3px rgba(15, 23, 42, 0.06);
  background: none !important;
        }
  box-shadow: none !important;
}


/* fallback extra */
        /* Força tema claro mesmo se o skin/OS estiver em dark — o widget tem
.thumbimage {
          identidade visual própria e não deve trocar de cor com o ambiente. */
  border: none !important;
        .gla-conquistas-root,
  padding: 0 !important;
        .gla-conquistas-root * {
  background: none !important;
            color-scheme: light;
}
        }


/* TEXTO */
        /* ─── Layout principal ───────────────────────────────────────────────── */
.gla-item-title {
        .gla-conquistas-root {
  font-weight: 700;
            color: var(--gla-ink);
  font-size: 15px;
        }
  color: #0f172a;
}


.gla-item-desc {
        .gla-conquistas-headerbox {
  font-size: 13px;
            margin: 0 0 16px;
  color: #64748b;
            padding: 0;
  margin-top: 2px;
            background: transparent;
}
            border: none;
        }


/* RECOMPENSA */
        .gla-conquistas-header {
.gla-item-reward {
            display: none;
  font-size: 13px;
        }
  color: #2563eb;
  font-weight: 600;
}
</style>


<script>
        /* ─── Toolbar (tabs + busca) ─────────────────────────────────────────── */
document.addEventListener("DOMContentLoaded", function () {
        /* Sem chrome próprio — só agrupa tabs e controles. */
  var tabs = document.querySelectorAll(".gla-conquistas-tab");
        .gla-conquistas-toolbar {
  var panels = document.querySelectorAll(".gla-conquistas-panel");
            display: block;
            width: 100%;
            background: transparent;
            border: none;
            border-radius: 0;
            box-shadow: none;
            padding: 0;
        }


  function abrirAba(nome) {
        /* ─── Wrapper das abas ───────────────────────────────────────────────── */
    tabs.forEach(function(t) {
        /* Sem scroll horizontal. As abas usam flex-wrap pra quebrar linha
      t.classList.remove("is-active");
          naturalmente em telas estreitas. */
    });
        .gla-conquistas-tabs-scroll {
            position: relative;
            overflow: visible;
            padding: 0;
            background: transparent;
            border: none;
            border-radius: 0;
        }


    panels.forEach(function(p) {
        .gla-conquistas-tabs {
      p.classList.remove("is-active");
            display: flex;
    });
            flex-wrap: wrap;
            gap: 6px;
            padding: 0;
            width: 100%;
            min-width: 0;
            box-sizing: border-box;
            margin: 0 0 12px;
        }


    var tab = document.querySelector('.gla-conquistas-tab[data-tab="' + nome + '"]');
        /* ─── Tab pill / botão ───────────────────────────────────────────────── */
    var panel = document.querySelector('.gla-conquistas-panel[data-tab-content="' + nome + '"]');
        /* Botões redondos clean: branco com borda cinza, hover sutil,
          ativo em azul sólido. Sem fichário, sem stripe. */
        .gla-conquistas-tab {
            flex: 0 0 auto;
            text-align: center;
            white-space: nowrap;
            font-size: 13px;
            font-weight: 600;
            padding: 7px 14px;
            border: 1px solid var(--gla-rule);
            border-radius: 999px;
            background: var(--gla-paper);
            color: var(--gla-ink-2);
            cursor: pointer;
            box-sizing: border-box;
            user-select: none;
            transition: background 0.15s, color 0.15s, border-color 0.15s, box-shadow 0.15s;
        }


    if (tab) tab.classList.add("is-active");
        .gla-conquistas-tab:hover {
    if (panel) panel.classList.add("is-active");
            background: var(--gla-paper-2);
  }
            color: var(--gla-ink);
            border-color: var(--gla-dim-2);
        }


  tabs.forEach(function(tab) {
        .gla-conquistas-tab.is-active {
    tab.addEventListener("click", function() {
            background: var(--gla-accent);
      abrirAba(tab.getAttribute("data-tab"));
            color: #ffffff;
    });
            border-color: var(--gla-accent);
  });
            box-shadow: 0 1px 2px rgba(37, 99, 235, 0.25);
        }


   abrirAba("geral");
        .gla-conquistas-tab.is-active:hover {
});
            background: var(--gla-accent);
</script>
            color: #ffffff;
            border-color: var(--gla-accent);
        }
 
        /* ─── Controles (busca + filtros) ────────────────────────────────────── */
        .gla-conquistas-controls {
            display: flex;
            align-items: center;
            gap: 10px;
            flex-wrap: wrap;
            width: 100%;
            box-sizing: border-box;
            background: transparent;
            border: none;
            padding: 0;
            margin: 0;
        }
 
        /* Cresce no espaço livre até max-width; os filtros ficam encostados à
          direita dela em vez de no fim da linha. */
        .gla-conquistas-search {
            flex: 1 1 auto;
            min-width: 160px;
            max-width: 360px;
            padding: 8px 16px;
            border: 1px solid var(--gla-rule);
            border-radius: 999px;
            font-size: 13px;
            background: var(--gla-paper);
            color: var(--gla-ink);
            outline: none;
            font-family: inherit;
            transition: box-shadow 0.15s, border-color 0.15s;
        }
 
        .gla-conquistas-search::placeholder {
            color: var(--gla-dim);
        }
 
        .gla-conquistas-search:focus {
            box-shadow: 0 0 0 3px var(--gla-accent-bg);
            border-color: var(--gla-accent);
        }
 
        /* ─── Filtros ────────────────────────────────────────────────────────── */
        /* Encostados na search via gap natural do .gla-conquistas-controls. */
        .gla-conquistas-filters {
            display: flex;
            gap: 6px;
            flex-wrap: wrap;
        }
 
        .gla-conquistas-filter {
            padding: 6px 14px;
            border: 1px solid var(--gla-rule);
            border-radius: 999px;
            background: var(--gla-paper);
            font-size: 12px;
            font-weight: 600;
            color: var(--gla-ink-2);
            cursor: pointer;
            transition: background 0.15s, color 0.15s, border-color 0.15s;
        }
 
        .gla-conquistas-filter:hover {
            background: var(--gla-paper-2);
            color: var(--gla-ink);
            border-color: var(--gla-dim-2);
        }
 
        .gla-conquistas-filter.is-active {
            background: var(--gla-accent);
            color: #ffffff;
            border-color: var(--gla-accent);
        }
 
        /* ─── Painéis ────────────────────────────────────────────────────────── */
        .gla-conquistas-panel {
            margin: 14px 0 0;
            display: none;
        }
 
        .gla-conquistas-panel.is-active {
            display: block;
        }
 
        .gla-conquistas-source {
            display: none;
        }
 
        .gla-list {
            display: flex;
            flex-direction: column;
            gap: 10px;
        }
 
        /* ─── Card ───────────────────────────────────────────────────────────── */
        /* Branco com borda cinza. Hover marca borda azul (detalhe). */
        .gla-item {
            display: flex;
            flex-direction: column;
            background: var(--gla-paper);
            border: 1px solid var(--gla-rule);
            border-radius: 12px;
            box-shadow: var(--gla-shadow);
            transition: border-color 0.15s, box-shadow 0.15s;
        }
 
        .gla-item.has-spoiler:hover {
            border-color: var(--gla-accent-soft);
            box-shadow: 0 2px 8px -2px rgba(37, 99, 235, 0.18);
        }
 
        .gla-item-main {
            display: flex;
            align-items: center;
            gap: 16px;
            padding: 14px 18px;
            min-height: 76px;
            position: relative;
        }
 
        /* Abinha do spoiler vive sobreposta ao bottom da linha de conteúdo,
          sem adicionar padding-bottom — assim cards com ou sem spoiler
          têm exatamente a mesma altura. */
 
        .gla-item-left {
            display: flex;
            align-items: center;
            gap: 14px;
            flex: 1;
            min-width: 0;
        }
 
        .gla-item-icon {
            flex: 0 0 auto;
            display: flex;
            align-items: center;
            justify-content: center;
        }
 
        /* Ícone respeita o tamanho do arquivo na wiki (recomendado: 52×52).
          Sem dimensões fixas. */
        .gla-item-icon img {
            object-fit: contain;
            border: none !important;
            padding: 0 !important;
            background: none !important;
            box-shadow: none !important;
            display: block;
        }
 
        /* Título preto (sem azul). Azul fica só nos detalhes. */
        .gla-item-title {
            font-size: 15px;
            font-weight: 700;
            color: var(--gla-ink);
            line-height: 1.25;
        }
 
        .gla-conquistas-root .gla-item-title {
            color: var(--gla-ink);
        }
 
        .gla-item-desc {
            font-size: 13px;
            color: var(--gla-ink-2);
            margin-top: 2px;
            line-height: 1.4;
        }
 
        /* ─── Recompensa ─────────────────────────────────────────────────────── */
        /* Bloco externo: NÃO tem chrome próprio — só agrupa o label (acima)
          e o chip de itens (.reward-wrapper). Label fora da box pra não ser
          comprimido quando o chip encolhe com poucos itens. */
        .gla-item-reward {
            flex-shrink: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 6px;
            background: transparent;
            border: none;
            padding: 0;
            align-self: center;
            margin-top: -4px;
            position: relative;
            /* ancora pro popover "+M" */
        }
 
        .gla-item-reward-label {
            font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
            font-size: 14px;
            font-weight: 700;
            letter-spacing: 0.14em;
            text-transform: uppercase;
            color: var(--gla-accent);
            white-space: nowrap;
        }
 
        /* Chip de itens — agora é o .reward-wrapper (emitido pelo Lua/Widget:Item).
          padding-bottom maior porque cada .item-wrapper do Widget:Item tem
          um .item-count posicionado em bottom:-10px (badge "x999" pendurado
          abaixo do ícone). Sem espaço extra, o badge encosta na borda. */
        .gla-item-reward .reward-wrapper {
            display: block;
            background: var(--gla-paper-3);
            border: 1px solid var(--gla-rule);
            border-radius: 10px;
            padding: 9px 8px 18px;
            min-width: 64px;
            /* 4×(32 wrapper + 12 margin) + chip 32 = 220 + folga */
            max-width: 260px;
            width: fit-content;
            box-sizing: border-box;
        }
 
        /* Wrapper do texto — title + desc + (eventual) toggle de spoiler.
          min-width:0 pra que o flex do .gla-item-left consiga truncar texto
          longo sem empurrar o botão pra direita. */
        .gla-item-text {
            min-width: 0;
            display: flex;
            flex-direction: column;
            align-items: flex-start;
        }
 
        /* ─── Botão spoiler ──────────────────────────────────────────────────── */
        /* Fluir abaixo da descrição, alinhado com o início do texto (não
          com o ícone). Antes era absolute em left:84px fixo e o ícone real
          da wiki (que pode ser ~100px) cobria o botão. */
        .gla-item-spoiler-toggle {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            margin: 8px 0 0;
            border: 1px solid var(--gla-rule);
            background: var(--gla-paper);
            border-radius: 999px;
            padding: 2px 12px 3px;
            font: inherit;
            color: var(--gla-ink-2);
            cursor: pointer;
            transition: background 0.15s, border-color 0.15s, color 0.15s;
            user-select: none;
            align-self: flex-start;
        }
 
        .gla-item-spoiler-toggle:hover {
            background: var(--gla-accent-bg);
            border-color: var(--gla-accent-soft);
            color: var(--gla-accent);
        }
 
        .gla-item-spoiler-toggle:hover .gla-item-chevron {
            color: var(--gla-accent);
        }
 
        .gla-item-spoiler-text {
            font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
            font-size: 11px;
            font-weight: 700;
            letter-spacing: 0.1em;
            text-transform: uppercase;
        }
 
        /* ─── Chevron (desenhado via border-corner) ─────────────────────────── */
        /* O caractere `›` que o Lua emite não é centralizado dentro do seu
          glifo — girar como texto fica torto. Em vez disso esconde o texto
          (font-size 0) e desenha o chevron via pseudo-elemento com
          border-right + border-top a 45°. Esse shape é perfeitamente simé-
          trico, então rotacionar o span pai em volta do centro funciona. */
        .gla-item-chevron {
            position: relative;
            display: inline-block;
            width: 12px;
            height: 12px;
            font-size: 0;
            line-height: 0;
            color: var(--gla-accent);
            flex-shrink: 0;
            transform-origin: 50% 50%;
            /* Curva elástica leve — chega no destino com um micro-overshoot
              em vez de parar seco no 90°. */
            transition: transform 0.42s cubic-bezier(0.34, 1.56, 0.64, 1),
                color 0.15s ease;
            user-select: none;
        }
 
        .gla-item-chevron::before {
            content: "";
            position: absolute;
            top: 50%;
            left: 50%;
            width: 6px;
            height: 6px;
            border-top: 2px solid currentColor;
            border-right: 2px solid currentColor;
            transform: translate(-65%, -50%) rotate(45deg);
        }
 
        .gla-item.has-spoiler.is-open .gla-item-chevron {
            transform: rotate(90deg);
        }
 
        /* ─── Spoiler aberto ─────────────────────────────────────────────────── */
        .gla-item-spoiler {
            display: none;
            border-top: 1px solid var(--gla-rule);
            background: var(--gla-paper-2);
            padding: 14px 18px;
            gap: 18px;
            flex-direction: row;
            align-items: flex-start;
            border-radius: 0 0 12px 12px;
        }
 
        .gla-item.is-open .gla-item-spoiler {
            display: flex;
            animation: gla-spoiler-in 0.35s cubic-bezier(0.22, 1, 0.36, 1);
        }
 
        @keyframes gla-spoiler-in {
            from {
                opacity: 0;
                transform: translateY(-6px);
            }
 
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }
 
        .gla-item-spoiler-info {
            flex: 1;
            font-size: 14px;
            color: var(--gla-ink-2);
            line-height: 1.55;
            min-width: 0;
        }
 
        .gla-item-spoiler-info a {
            color: var(--gla-accent);
        }
 
        .gla-item-spoiler-media {
            flex: 0 0 360px;
            max-width: 480px;
        }
 
        .gla-item-spoiler-media img,
        .gla-item-spoiler-media video {
            width: 100%;
            height: auto;
            border-radius: 8px;
            border: 1px solid var(--gla-rule) !important;
            display: block;
        }
 
        /* ─── Card "secreta no jogo" ────────────────────────────────────────────
          O estado "oculta" não esconde nada — só marca visualmente que ESSA
          conquista aparece como ??? no jogo. O marcador precisa ser legível
          pra que o jogador pareando game ↔ wiki entenda de imediato "ah,
          por isso que essa não aparece pra mim no client".
 
          Cinco variantes selecionáveis via data-hidden-style no root:
            - badge  : pill "Oculta no jogo" inline ao lado do título
            - stripes : padrão diagonal sutil + tag flutuante no topo
            - ribbon  : fita diagonal cinza "SECRETA" no canto top-left  ← default
            - stamp   : carimbo translúcido "OCULTA" sobreposto à direita
            - subtle  : só italic + cinza (controle: o que existia antes)
 
          Acento dos marcadores: slate (cinza neutro). Mantém o tema
          branco+azul "limpo" — o cinza só sinaliza estado "secreta" sem
          competir com o azul institucional. */
 
        .gla-conquistas-root {
            --gla-secret: #475569;
            /* slate-600 — ink/fill escuro */
            --gla-secret-bg: #f1f5f9;
            /* slate-100 — fill claro */
            --gla-secret-line: #cbd5e1;
            /* slate-300 — borda */
            --gla-secret-soft: #f8fafc;
            /* slate-50  — bg do card */
        }
 
        /* Baseline: card oculto recebe leve tint slate quase imperceptível.
          Não diminui contraste do conteúdo (título preto, desc slate-600
          normal); só serve de "tinta de fundo" pra o card parecer um pouco
          diferente mesmo antes do marcador específico da variante. */
        .gla-item.is-hidden,
        .gla-item[data-hidden="true"] {
            background: var(--gla-secret-soft);
            border-color: var(--gla-secret-line);
            position: relative;
        }
 
        .gla-item.is-hidden:hover,
        .gla-item[data-hidden="true"]:hover {
            border-color: var(--gla-secret);
            box-shadow: 0 2px 8px -2px rgba(71, 85, 105, 0.18);
        }
 
        .gla-item.is-hidden .gla-item-reward .reward-wrapper,
        .gla-item[data-hidden="true"] .gla-item-reward .reward-wrapper {
            background: #ffffff;
            border-color: var(--gla-secret-line);
        }
 
        .gla-item.is-hidden .gla-item-reward-label,
        .gla-item[data-hidden="true"] .gla-item-reward-label {
            color: var(--gla-secret);
        }
 
        /* ─── Reveal modes ──────────────────────────────────────────────────────
          Independente do marcador (badge/ribbon/etc), o conteúdo do card
          pode vir "censurado" e ser revelado ao clique — útil pra quem
          entra na wiki querendo evitar spoiler. Click em qualquer parte do
          card (menos chip de recompensa, links, botão de spoiler) adiciona
          .is-revealed via JS.
 
            "none"        — sem censura
            "blur"        — título+desc borrados (default)
            "redacted"    — tarjas slate (estilo doc classificado)
            "placeholder" — texto vira "???"
            "veil"        — overlay total com CTA "clique para revelar"
 
          O marcador (badge/ribbon/etc) continua visível em blur/redacted/
          placeholder — o jogador SABE que é secreta, só não vê o conteúdo.
          No veil até o marcador é coberto. */
 
        .gla-conquistas-root[data-reveal-mode="blur"] .gla-item[data-hidden="true"]:not(.is-revealed),
        .gla-conquistas-root[data-reveal-mode="redacted"] .gla-item[data-hidden="true"]:not(.is-revealed),
        .gla-conquistas-root[data-reveal-mode="placeholder"] .gla-item[data-hidden="true"]:not(.is-revealed),
        .gla-conquistas-root[data-reveal-mode="veil"] .gla-item[data-hidden="true"]:not(.is-revealed) {
            cursor: pointer;
        }
 
        /* Censura ABSOLUTA: enquanto não revelado, todo o conteúdo do card
          fica click-through (pointer-events:none na .gla-item-main) E é
          coberto por um overlay transparente (::after no .gla-item) que
          absorve hover/click e tira do alcance os tooltips nativos do
          browser (title/alt) — sem o overlay, alguns navegadores ainda
          exibem o tooltip de elementos com pointer-events:none.
          O ::after fica logo acima do conteúdo (z-index 6) e abaixo do
          ribbon/stamp (z-index 2). Como não tem title/alt nem children,
          hover sobre ele não gera tooltip nenhum. Click bubbla pro
          .gla-item e o listener global revela. */
        .gla-conquistas-root[data-reveal-mode="blur"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-main,
        .gla-conquistas-root[data-reveal-mode="redacted"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-main,
        .gla-conquistas-root[data-reveal-mode="placeholder"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-main,
        .gla-conquistas-root[data-reveal-mode="veil"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-main {
            pointer-events: none;
        }
 
        .gla-conquistas-root[data-reveal-mode="blur"] .gla-item[data-hidden="true"]:not(.is-revealed),
        .gla-conquistas-root[data-reveal-mode="redacted"] .gla-item[data-hidden="true"]:not(.is-revealed),
        .gla-conquistas-root[data-reveal-mode="placeholder"] .gla-item[data-hidden="true"]:not(.is-revealed),
        .gla-conquistas-root[data-reveal-mode="veil"] .gla-item[data-hidden="true"]:not(.is-revealed) {
            pointer-events: auto;
            position: relative;
        }
 
        /* Overlay transparente que captura hover/click — apenas em blur,
          redacted e placeholder. (Veil tem o seu próprio ::after estilizado
          logo abaixo, e o seletor mais específico de baixo sobrescreve.) */
        .gla-conquistas-root[data-reveal-mode="blur"] .gla-item[data-hidden="true"]:not(.is-revealed)::after,
        .gla-conquistas-root[data-reveal-mode="redacted"] .gla-item[data-hidden="true"]:not(.is-revealed)::after,
        .gla-conquistas-root[data-reveal-mode="placeholder"] .gla-item[data-hidden="true"]:not(.is-revealed)::after {
            content: "";
            position: absolute;
            inset: 0;
            background: transparent;
            pointer-events: auto;
            z-index: 6;
        }
 
        /* Anula QUALQUER interação dentro do card censurado: tooltip dos
          rewards (JS do Widget:Item), tooltip nativo de alt/title em imagens,
          seleção de texto, hover de links na descrição. pointer-events:none
          torna os filhos "transparentes" pra eventos do mouse — o click sobe
          pro .gla-item pai, que dispara o reveal. */
        .gla-conquistas-root[data-reveal-mode="blur"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-main,
        .gla-conquistas-root[data-reveal-mode="redacted"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-main,
        .gla-conquistas-root[data-reveal-mode="placeholder"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-main,
        .gla-conquistas-root[data-reveal-mode="veil"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-main {
            pointer-events: none;
            user-select: none;
            -webkit-user-select: none;
        }
 
        .gla-item[data-hidden="true"] .gla-item-main,
        .gla-item[data-hidden="true"] .gla-item-title,
        .gla-item[data-hidden="true"] .gla-item-desc {
            transition: filter 0.25s ease, background-color 0.25s ease, color 0.25s ease;
        }
 
        /* — BLUR
          Aplicado no .gla-item-main (pai que envolve icon + title + desc +
          reward + spoiler-toggle) — borra TUDO de uma vez. Antes só borrava
          título e descrição, mas o ícone da conquista também entregava a
          secreta. O ribbon "SECRETA" tá no ::before do .gla-item (fora do
          main), então continua nítido. */
        .gla-conquistas-root[data-reveal-mode="blur"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-main {
            filter: blur(5px);
            user-select: none;
        }
 
        /* — REDACTED (tarjas estilo doc classificado) */
        .gla-conquistas-root[data-reveal-mode="redacted"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-title,
        .gla-conquistas-root[data-reveal-mode="redacted"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-desc {
            background: #334155;
            color: transparent;
            border-radius: 3px;
            user-select: none;
            width: max-content;
            max-width: 100%;
        }
 
        .gla-conquistas-root[data-reveal-mode="redacted"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-title::after {
            display: none;
        }
 
        /* — PLACEHOLDER ("???") */
        .gla-conquistas-root[data-reveal-mode="placeholder"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-title {
            color: transparent;
            font-size: 0 !important;
            line-height: 1.25;
            position: relative;
        }
 
        .gla-conquistas-root[data-reveal-mode="placeholder"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-title::before {
            content: "???";
            font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
            font-size: 18px;
            font-weight: 700;
            letter-spacing: 0.2em;
            color: var(--gla-dim);
        }
 
        .gla-conquistas-root[data-reveal-mode="placeholder"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-title::after {
            display: none;
        }
 
        .gla-conquistas-root[data-reveal-mode="placeholder"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-desc {
            color: transparent;
            font-size: 0 !important;
            line-height: 1.4;
            position: relative;
        }
 
        .gla-conquistas-root[data-reveal-mode="placeholder"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-desc::before {
            content: "??? ??? ??? ???";
            font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
            font-size: 13px;
            letter-spacing: 0.15em;
            color: var(--gla-dim);
        }
 
        /* — VEIL (overlay total cobrindo o card) */
        .gla-conquistas-root[data-reveal-mode="veil"] .gla-item[data-hidden="true"]:not(.is-revealed) {
            overflow: hidden;
        }
 
        .gla-conquistas-root[data-reveal-mode="veil"] .gla-item[data-hidden="true"]:not(.is-revealed)::after {
            content: "";
            position: absolute;
            inset: 0;
            background: rgba(248, 250, 252, 0.92);
            backdrop-filter: blur(4px);
            -webkit-backdrop-filter: blur(4px);
            z-index: 6;
            /* auto — overlay captura hover/click. Sem isso, mesmo coberto
              visualmente, os items embaixo ainda recebiam hover e o browser
              mostrava tooltip nativo (title/alt). */
            pointer-events: auto;
            transition: opacity 0.25s ease;
        }
 
        .gla-conquistas-root[data-reveal-mode="veil"] .gla-item[data-hidden="true"]:not(.is-revealed) .gla-item-main::before {
            content: "Conquista secreta — clique para revelar";
            position: absolute;
            inset: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
            font-size: 12px;
            font-weight: 700;
            letter-spacing: 0.14em;
            text-transform: uppercase;
            color: var(--gla-secret);
            z-index: 5;
            padding-left: 36px;
            background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23475569' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><rect width='18' height='11' x='3' y='11' rx='2' ry='2'/><path d='M7 11V7a5 5 0 0 1 10 0v4'/></svg>");
            background-repeat: no-repeat;
            background-position: calc(50% - 105px) 50%;
            background-size: 16px 16px;
            pointer-events: none;
        }
 
        /* Quando revelado: fade-in suave do conteúdo */
        .gla-item[data-hidden="true"].is-revealed .gla-item-title,
        .gla-item[data-hidden="true"].is-revealed .gla-item-desc {
            animation: gla-reveal 0.4s ease;
        }
 
        @keyframes gla-reveal {
            from {
                opacity: 0;
            }
 
            to {
                opacity: 1;
            }
        }
 
        /* ─── Variante A — BADGE (default fallback) ─────────────────────────── */
        /* Pill cinza inline ao lado do título com ícone eye-off. Direto e
          legível, não rouba real estate do card. */
        .gla-conquistas-root[data-hidden-style="badge"] .gla-item[data-hidden="true"] .gla-item-left>div:not(.gla-item-icon) {
            flex: 1;
            min-width: 0;
        }
 
        .gla-conquistas-root[data-hidden-style="badge"] .gla-item[data-hidden="true"] .gla-item-title {
            display: flex;
            align-items: center;
            flex-wrap: wrap;
            gap: 4px 8px;
        }
 
        .gla-conquistas-root[data-hidden-style="badge"] .gla-item[data-hidden="true"] .gla-item-title::after {
            content: "Oculta no jogo";
            display: inline-flex;
            align-items: center;
            padding: 2px 9px 2px 22px;
            background: var(--gla-secret-bg);
            color: var(--gla-secret);
            border: 1px solid var(--gla-secret-line);
            font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
            font-size: 10px;
            font-weight: 700;
            letter-spacing: 0.08em;
            text-transform: uppercase;
            line-height: 1;
            border-radius: 999px;
            white-space: nowrap;
            background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23475569' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><path d='M9.88 9.88a3 3 0 1 0 4.24 4.24'/><path d='M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68'/><path d='M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61'/><line x1='2' x2='22' y1='2' y2='22'/></svg>");
            background-repeat: no-repeat;
            background-position: 6px 50%;
            background-size: 12px 12px;
            background-color: var(--gla-secret-bg);
        }
 
        /* ─── Variante B — STRIPES ─────────────────────────────────────────── */
        .gla-conquistas-root[data-hidden-style="stripes"] .gla-item[data-hidden="true"] {
            background-image:
                repeating-linear-gradient(-45deg,
                    transparent 0 14px,
                    rgba(71, 85, 105, 0.06) 14px 16px);
            background-color: var(--gla-secret-soft);
        }
 
        .gla-conquistas-root[data-hidden-style="stripes"] .gla-item[data-hidden="true"] .gla-item-main::before {
            content: "Oculta no jogo";
            position: absolute;
            top: -1px;
            left: 18px;
            transform: translateY(-50%);
            background: var(--gla-secret);
            color: #fff;
            font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
            font-size: 10px;
            font-weight: 700;
            letter-spacing: 0.12em;
            text-transform: uppercase;
            line-height: 1;
            padding: 4px 10px 5px 24px;
            border-radius: 999px;
            white-space: nowrap;
            z-index: 2;
            background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><path d='M9.88 9.88a3 3 0 1 0 4.24 4.24'/><path d='M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68'/><path d='M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61'/><line x1='2' x2='22' y1='2' y2='22'/></svg>");
            background-repeat: no-repeat;
            background-position: 7px 50%;
            background-size: 12px 12px;
        }
 
        .gla-conquistas-root[data-hidden-style="stripes"] .gla-item[data-hidden="true"] .gla-item-main {
            padding-top: 20px;
        }
 
        /* ─── Variante C — RIBBON (default) ─────────────────────────────────── */
        /* Fita diagonal cinza "SECRETA" no canto top-left. */
        .gla-conquistas-root[data-hidden-style="ribbon"] .gla-item[data-hidden="true"] {
            overflow: hidden;
        }
 
        .gla-conquistas-root[data-hidden-style="ribbon"] .gla-item[data-hidden="true"]::before {
            content: "SECRETA";
            position: absolute;
            top: 14px;
            left: -38px;
            width: 140px;
            transform: rotate(-45deg);
            background: var(--gla-secret);
            color: #fff;
            font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
            font-size: 10px;
            font-weight: 700;
            letter-spacing: 0.18em;
            text-align: center;
            line-height: 1;
            padding: 4px 0 5px;
            box-shadow: 0 1px 2px rgba(71, 85, 105, 0.25);
            z-index: 2;
            pointer-events: none;
        }
 
        .gla-conquistas-root[data-hidden-style="ribbon"] .gla-item[data-hidden="true"] .gla-item-main {
            padding-left: 38px;
        }
 
        @media (max-width: 720px) {
            .gla-conquistas-root[data-hidden-style="ribbon"] .gla-item[data-hidden="true"] .gla-item-main {
                padding-left: 38px;
            }
        }
 
        /* ─── Variante D — STAMP ─────────────────────────────────────────────── */
        .gla-conquistas-root[data-hidden-style="stamp"] .gla-item[data-hidden="true"]::before {
            content: "OCULTA";
            position: absolute;
            top: 50%;
            right: 240px;
            transform: translateY(-50%) rotate(-12deg);
            font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
            font-size: 28px;
            font-weight: 700;
            letter-spacing: 0.25em;
            color: var(--gla-secret);
            opacity: 0.18;
            border: 3px solid var(--gla-secret);
            border-radius: 6px;
            padding: 4px 12px;
            pointer-events: none;
            white-space: nowrap;
            z-index: 1;
        }
 
        @media (max-width: 720px) {
            .gla-conquistas-root[data-hidden-style="stamp"] .gla-item[data-hidden="true"]::before {
                top: 14px;
                right: 14px;
                transform: rotate(-12deg);
                font-size: 22px;
            }
        }
 
        /* ─── Variante E — SUBTLE ────────────────────────────────────────────── */
        .gla-conquistas-root[data-hidden-style="subtle"] .gla-item[data-hidden="true"] {
            background: var(--gla-paper-2);
            border-color: var(--gla-dim-2);
        }
 
        .gla-conquistas-root[data-hidden-style="subtle"] .gla-item[data-hidden="true"] .gla-item-title {
            color: var(--gla-ink-2);
            font-style: italic;
        }
 
        .gla-conquistas-root[data-hidden-style="subtle"] .gla-item[data-hidden="true"] .gla-item-desc {
            color: var(--gla-dim);
        }
 
        .gla-conquistas-root[data-hidden-style="subtle"] .gla-item[data-hidden="true"] .gla-item-reward .reward-wrapper {
            background: var(--gla-paper-3);
            border-color: var(--gla-dim-2);
        }
 
        .gla-conquistas-root[data-hidden-style="subtle"] .gla-item[data-hidden="true"] .gla-item-reward-label {
            color: var(--gla-dim);
        }
 
        .gla-conquistas-root[data-hidden-style="subtle"] .gla-item[data-hidden="true"]:hover {
            border-color: var(--gla-dim);
            box-shadow: var(--gla-shadow);
        }
 
        .gla-conquistas-root[data-hidden-style="subtle"] .gla-item[data-hidden="true"] .gla-item-title::after,
        .gla-conquistas-root[data-hidden-style="subtle"] .gla-item[data-hidden="true"]::before {
            content: none;
        }
 
        /* ─── Reward items (Widget:Item) ─────────────────────────────────────── */
        .gla-item-reward .item-wrapper-special {
            filter: none !important;
        }
 
        .gla-item-reward .reward-items {
            display: flex !important;
            /* nowrap = trava a altura. O JS abaixo move itens excedentes pra
              dentro do chip "+M" depois do MAX_VISIBLE-ésimo. */
            flex-wrap: nowrap !important;
            justify-content: flex-start;
            align-items: flex-start;
            gap: 0;
            width: 100%;
        }
 
        /* ─── Chip "+M" (overflow) ─────────────────────────────────────────── */
        /* Botão de overflow com reticências (⋯). Círculo 32×32 sutil — mesma
          altura dos sprites pra encaixar na linha, mas borda/fundo accent
          pra ler como CTA, não como outro slot de item. margin-top: 5px
          alinha com o centro visual do conjunto sprite+badge dos rewards
          (o badge .item-count fica em bottom:-10px do .item-wrapper, então
          o "centro real" do item fica ~5px abaixo do centro do sprite). */
        .gla-item-reward .reward-more-chip {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 32px;
            height: 32px;
            margin: 5px 6px 0;
            padding: 0 0 4px;
            border: 1px solid var(--gla-accent-soft);
            border-radius: 999px;
            background: var(--gla-accent-bg);
            color: var(--gla-accent);
            font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
            font-size: 22px;
            font-weight: 700;
            line-height: 1;
            letter-spacing: 0;
            cursor: pointer;
            flex-shrink: 0;
            box-sizing: border-box;
            transition: background 0.15s, border-color 0.15s, color 0.15s;
        }
 
        .gla-item-reward .reward-more-chip:hover,
        .gla-item-reward .reward-more-chip[aria-expanded="true"] {
            background: var(--gla-accent);
            border-color: var(--gla-accent);
            color: #ffffff;
        }
 
        /* Popover ancorado no chip via JS — vive em document.body com
          position:fixed pra escapar o overflow:hidden de cards com ribbon
          (e qualquer outro contexto de clipping). Tooltips dos itens
          dentro saem livremente. */
        .reward-overflow-popover {
            position: fixed;
            display: flex;
            flex-wrap: wrap;
            justify-content: flex-start;
            align-items: flex-start;
            gap: 0;
            /* padding-bottom extra pelo mesmo motivo do .reward-wrapper:
              .item-count fica em bottom:-10px e precisa de espaço. */
            padding: 10px 6px 18px;
            background: var(--gla-paper, #ffffff);
            border: 1px solid var(--gla-rule, #e2e8f0);
            border-radius: 10px;
            box-shadow: 0 6px 18px -4px rgba(15, 23, 42, 0.18),
                0 2px 6px -2px rgba(15, 23, 42, 0.08);
            z-index: 9999;
            max-width: 260px;
            animation: gla-popover-in 0.18s ease;
        }
 
        .reward-overflow-popover[hidden] {
            display: none;
        }
 
        @keyframes gla-popover-in {
            from {
                opacity: 0;
                transform: translateY(-4px);
            }
 
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }
 
        /* ─── Responsivo ─────────────────────────────────────────────────────── */
        @media (max-width: 720px) {
            .gla-conquistas-tab {
                font-size: 12px;
                padding: 6px 11px;
            }
 
            .gla-item-main {
                flex-wrap: wrap;
                padding: 12px 14px;
            }
 
            .gla-item-left {
                padding-right: 0;
                flex: 1 1 100%;
            }
 
            .gla-item-reward {
                flex: 1 1 100%;
                flex-direction: row;
                justify-content: flex-start;
                max-width: none;
                margin-top: 0;
                align-self: stretch;
            }
 
            /* No mobile o spoiler já flui dentro do .gla-item-text, só
              reduz o padding pra ficar levemente mais compacto. */
            .gla-item-spoiler-toggle {
                padding: 2px 11px 3px;
            }
 
            .gla-item-spoiler {
                flex-direction: column;
            }
 
            .gla-item-spoiler-media {
                flex: 1 1 100%;
                max-width: 100%;
            }
        }
    </style>
 
    <script>
        document.addEventListener("DOMContentLoaded", function () {
            var root = document.querySelector(".gla-conquistas-root");
            if (!root) return;
 
            setTimeout(function () {
                var probe = document.querySelector(".item-wrapper");
                if (probe) {
                    var cs = window.getComputedStyle(probe);
                    if (cs && cs.position !== "relative" && console && console.warn) {
                        console.warn("[Widget:Conquistas] Widget:Item não detectado. Adicione {{#widget:Item}} antes de {{#widget:Conquistas}}.");
                    }
                }
            }, 200);
 
            var tabs = root.querySelectorAll(".gla-conquistas-tab");
            var panels = root.querySelectorAll(".gla-conquistas-panel");
 
            var validTabs = {};
            panels.forEach(function (p) {
                var name = p.getAttribute("data-tab-content");
                if (name) validTabs[name] = p.querySelector(".gla-list");
            });
 
            // Move cards do invoke source para os painéis corretos
            document.querySelectorAll(".gla-item[data-tab]").forEach(function (card) {
                if (root.contains(card)) return;
                var tag = (card.getAttribute("data-tab") || "").toLowerCase();
                var list = validTabs[tag] || validTabs["geral"];
                if (list) list.appendChild(card);
            });
 
            document.querySelectorAll(".gla-conquistas-source").forEach(function (src) {
                if (src.parentNode) src.parentNode.removeChild(src);
            });
 
            // Estado global
            var currentSearch = "";
            var currentFilter = "all";
            var currentTab = "geral";
            var searchTimeout = null;
 
            var filterDefault = root.querySelector("#gla-filter-default");
            var filterColiseu = root.querySelector("#gla-filter-coliseu");
            var searchInput = root.querySelector(".gla-conquistas-search");
 
            function countHiddenInTab(tabName) {
                var panel = root.querySelector('.gla-conquistas-panel[data-tab-content="' + tabName + '"]');
                if (!panel) return 0;
                var n = 0;
                panel.querySelectorAll(".gla-item").forEach(function (card) {
                    if (card.getAttribute("data-hidden") === "true") n++;
                });
                return n;
            }
 
            // Mostra a barra de filtros só quando faz sentido: na aba Coliseu mostra
            // o subset (One Man Army / Corrida). Nas outras, só mostra o filtro
            // normal/hidden se a aba tiver pelo menos uma conquista oculta —
            // se não tiver, esconde pra não poluir.
            function syncFilterBarForTab(tabName) {
                var hiddenCount = countHiddenInTab(tabName);
 
                if (filterColiseu) {
                    filterColiseu.style.display = tabName === "coliseu" ? "" : "none";
                }
                if (filterDefault) {
                    if (tabName === "coliseu") {
                        filterDefault.style.display = "none";
                    } else {
                        filterDefault.style.display = hiddenCount > 0 ? "" : "none";
                    }
                }
 
                if (tabName !== "coliseu" && hiddenCount === 0) {
                    if (currentFilter === "hidden" || currentFilter === "normal") {
                        currentFilter = "all";
                    }
                    if (filterDefault) {
                        filterDefault.querySelectorAll(".gla-conquistas-filter").forEach(function (p) {
                            p.classList.toggle("is-active", p.getAttribute("data-filter") === "all");
                        });
                    }
                }
            }
 
            // Normalização pra busca: lowercase + remove acentos (NFD divide
            // base+diacrítico, regex remove os diacríticos). Assim "voce"
            // acha "você", "missao" acha "missão", etc.
            function normalize(s) {
                return (s || "")
                    .toLowerCase()
                    .normalize("NFD")
                    .replace(/[̀-ͯ]/g, "");
            }
 
            // Cacheia o "haystack" (title + desc normalizados) no próprio card
            // pra não recalcular a cada keystroke. Recomputa só se o conteúdo
            // do card mudar (não acontece na vida do widget — é estático).
            function getHaystack(card) {
                var cached = card.__glaHaystack;
                if (cached) return cached;
                var titleEl = card.querySelector(".gla-item-title");
                var descEl = card.querySelector(".gla-item-desc");
                var titleText = titleEl ? titleEl.textContent : "";
                var descText = descEl ? descEl.textContent : "";
                cached = normalize(titleText + " " + descText);
                card.__glaHaystack = cached;
                return cached;
            }
 
            function applyVisibility() {
                var panel = root.querySelector('.gla-conquistas-panel[data-tab-content="' + currentTab + '"]');
                if (!panel) return;
 
                // Token-based search: divide a query em palavras e exige que
                // TODAS apareçam no haystack (title + desc), em qualquer
                // ordem. "voce grand" → tokens ["voce", "grand"] → casa com
                // "Você entrou na Grand Line pela primeira vez". Acentos e
                // case são ignorados via normalize().
                var tokens = normalize(currentSearch).split(/\s+/).filter(Boolean);
 
                panel.querySelectorAll(".gla-item").forEach(function (card) {
                    var matchSearch = true;
                    if (tokens.length > 0) {
                        var hay = getHaystack(card);
                        for (var i = 0; i < tokens.length; i++) {
                            if (hay.indexOf(tokens[i]) === -1) { matchSearch = false; break; }
                        }
                    }
 
                    var hidden = card.getAttribute("data-hidden") === "true";
                    var subtype = (card.getAttribute("data-subtype") || "").toLowerCase();
                    var matchFilter = true;
                    if (currentFilter === "normal") matchFilter = !hidden;
                    else if (currentFilter === "hidden") matchFilter = hidden;
                    else if (currentFilter === "onemany") matchFilter = subtype === "onemany";
                    else if (currentFilter === "corrida") matchFilter = subtype === "corrida";
 
                    card.style.display = (matchSearch && matchFilter) ? "" : "none";
                });
            }
 
            // Busca com debounce
            if (searchInput) {
                searchInput.addEventListener("input", function () {
                    clearTimeout(searchTimeout);
                    searchTimeout = setTimeout(function () {
                        currentSearch = searchInput.value.trim();
                        applyVisibility();
                    }, 240);
                });
            }
 
            // Filtros (normal / oculta / subtype)
            root.querySelectorAll(".gla-conquistas-filter").forEach(function (pill) {
                pill.addEventListener("click", function () {
                    pill.parentNode.querySelectorAll(".gla-conquistas-filter").forEach(function (p) {
                        p.classList.remove("is-active");
                    });
                    pill.classList.add("is-active");
                    currentFilter = pill.getAttribute("data-filter");
                    applyVisibility();
                });
            });
 
            // Spoiler — abre/fecha só no botão "Spoiler".
            // O Lua emite <span role="button"> (MediaWiki não aceita <button>
            // em wikitext), por isso aceitamos click + Enter/Space pra
            // preservar semântica de botão acessível.
            function toggleSpoiler(toggle) {
                var card = toggle.closest(".gla-item.has-spoiler");
                if (!card) return;
                var isOpen = card.classList.contains("is-open");
                root.querySelectorAll(".gla-item.is-open").forEach(function (c) {
                    c.classList.remove("is-open");
                });
                root.querySelectorAll(".gla-item-spoiler-toggle").forEach(function (btn) {
                    btn.setAttribute("aria-expanded", "false");
                });
                if (!isOpen) {
                    card.classList.add("is-open");
                    toggle.setAttribute("aria-expanded", "true");
                }
            }
 
            root.addEventListener("click", function (e) {
                var toggle = e.target.closest(".gla-item-spoiler-toggle");
                if (!toggle) return;
                if (e.target.closest(".item-wrapper")) return;
                e.preventDefault();
                toggleSpoiler(toggle);
            });
 
            root.addEventListener("keydown", function (e) {
                if (e.key !== "Enter" && e.key !== " ") return;
                var toggle = e.target.closest(".gla-item-spoiler-toggle");
                if (!toggle) return;
                e.preventDefault();
                toggleSpoiler(toggle);
            });
 
            // ─── Reveal + persistência ────────────────────────────────────────
            // Click no card hidden remove a censura (anti-spoiler) e o estado
            // é salvo no localStorage. Próxima visita à página, conquistas que
            // o jogador já revelou voltam reveladas — não precisa clicar de novo.
            //
            // Chave: "glaConquistasRevealed" → JSON com array de data-id.
            // Robusto a localStorage indisponível (modo privado, cookies
            // bloqueados) — só falha silenciosamente.
            var REVEAL_STORAGE_KEY = "glaConquistasRevealed";
 
            function loadRevealed() {
                try {
                    var raw = window.localStorage.getItem(REVEAL_STORAGE_KEY);
                    if (!raw) return {};
                    var arr = JSON.parse(raw);
                    if (!Array.isArray(arr)) return {};
                    var set = {};
                    for (var i = 0; i < arr.length; i++) {
                        if (arr[i] != null) set[String(arr[i])] = true;
                    }
                    return set;
                } catch (e) {
                    return {};
                }
            }
 
            function saveRevealed(set) {
                try {
                    var arr = Object.keys(set);
                    window.localStorage.setItem(REVEAL_STORAGE_KEY, JSON.stringify(arr));
                } catch (e) { /* localStorage indisponível — ok */ }
            }
 
            var revealedSet = loadRevealed();
 
            // Re-aplica .is-revealed nos cards que já tavam revelados em
            // sessões anteriores. Roda agora (depois do JS já ter movido os
            // cards do source pros painéis).
            root.querySelectorAll('.gla-item[data-hidden="true"][data-id]').forEach(function (card) {
                if (revealedSet[card.getAttribute("data-id")]) {
                    card.classList.add("is-revealed");
                }
            });
 
            // Click — revela e persiste. Só ativa se data-reveal-mode no root
            // estiver definido como blur/redacted/placeholder/veil.
            //
            // O CSS aplica `pointer-events: none` no .gla-item-main enquanto
            // a censura está ativa — então click em qualquer ponto interno
            // (icon/title/desc/items/spoiler/chip+N) cai direto no .gla-item.
            // Aqui não precisamos mais filtrar interativos: enquanto censurado,
            // tudo é "click pra revelar"; depois que revela, os filtros internos
            // voltam ao normal porque o seletor :not(.is-revealed) deixa de bater.
            root.addEventListener("click", function (e) {
                var mode = root.getAttribute("data-reveal-mode") || "none";
                if (mode === "none") return;
                var card = e.target.closest('.gla-item[data-hidden="true"]');
                if (!card) return;
                if (card.classList.contains("is-revealed")) return;
                card.classList.add("is-revealed");
 
                var id = card.getAttribute("data-id");
                if (id) {
                    revealedSet[id] = true;
                    saveRevealed(revealedSet);
                }
            });
 
            function abrirAba(nome) {
                currentTab = nome;
                currentFilter = "all";
 
                tabs.forEach(function (t) { t.classList.remove("is-active"); });
                panels.forEach(function (p) { p.classList.remove("is-active"); });
 
                var tab = root.querySelector('.gla-conquistas-tab[data-tab="' + nome + '"]');
                var panel = root.querySelector('.gla-conquistas-panel[data-tab-content="' + nome + '"]');
                if (tab) tab.classList.add("is-active");
                if (panel) panel.classList.add("is-active");
 
                syncFilterBarForTab(nome);
 
                root.querySelectorAll(".gla-conquistas-filter").forEach(function (p) {
                    if (p.offsetParent !== null && p.style.display !== "none") {
                        p.classList.toggle("is-active", p.getAttribute("data-filter") === "all");
                    }
                });
 
                applyVisibility();
            }
 
            tabs.forEach(function (tab) {
                tab.addEventListener("click", function () {
                    abrirAba(tab.getAttribute("data-tab"));
                });
            });
 
            abrirAba("geral");
        });
    </script>
 
    <!-- ─── Overflow das recompensas: "+M" chip + popover ─────────────────────
        Para cada .reward-items com mais de MAX itens, esconde do (MAX+1)º em
        diante, joga os escondidos num popover, e planta um chip "+M" no fim
        da linha. Clique no chip abre o popover ancorado abaixo do chip.
        Click fora fecha. Esc fecha.
        É responsabilidade do widget — o Lua não precisa mudar, já que
        .reward-items vem do Widget:Item igual à Predefinição:Reward.
    ─────────────────────────────────────────────────────────────────────── -->
    <script>
        (function () {
            var MAX_VISIBLE = 4;
            // Container portal: vive direto em document.body, fora de
            // qualquer .gla-item / .gla-item-reward. Necessário pra que
            // cards com overflow:hidden (ex.: variante "ribbon") não
            // recortem o popover nem os tooltips dos itens dentro dele.
            var portal = null;
 
            function ensurePortal() {
                if (portal && portal.isConnected) return portal;
                portal = document.querySelector(".gla-conquistas-portal");
                if (!portal) {
                    portal = document.createElement("div");
                    portal.className = "gla-conquistas-portal";
                    portal.style.position = "absolute";
                    portal.style.top = "0";
                    portal.style.left = "0";
                    portal.style.width = "0";
                    portal.style.height = "0";
                    portal.style.pointerEvents = "none";
                    portal.style.zIndex = "9998";
                    document.body.appendChild(portal);
                }
                return portal;
            }
 
            function positionPopover(popover, chip) {
                var rect = chip.getBoundingClientRect();
                var pw = popover.offsetWidth || 240;
                var vpW = window.innerWidth || document.documentElement.clientWidth;
                // Alinha pela direita do chip; clampa pra não vazar viewport.
                var left = rect.right - pw;
                if (left < 8) left = 8;
                if (left + pw > vpW - 8) left = vpW - 8 - pw;
                popover.style.left = left + "px";
                popover.style.top = (rect.bottom + 6) + "px";
                popover.style.pointerEvents = "auto";
            }
 
            function processOne(reward) {
                if (reward.dataset.glaOverflow === "done") return;
                var line = reward.querySelector(".reward-items");
                if (!line) return;
 
                var items = [];
                for (var i = 0; i < line.children.length; i++) {
                    var c = line.children[i];
                    if (c.classList && c.classList.contains("item-wrapper")) items.push(c);
                }
                if (items.length <= MAX_VISIBLE) {
                    reward.dataset.glaOverflow = "done";
                    return;
                }
 
                var hidden = items.slice(MAX_VISIBLE);
 
                var popover = document.createElement("div");
                popover.className = "reward-overflow-popover";
                popover.hidden = true;
                hidden.forEach(function (el) { popover.appendChild(el); });
 
                var chip = document.createElement("button");
                chip.type = "button";
                chip.className = "reward-more-chip";
                chip.setAttribute("aria-expanded", "false");
                chip.setAttribute("aria-label", "Ver mais " + hidden.length + " recompensa(s)");
                chip.title = "Ver mais " + hidden.length;
                // Reticências midline (U+22EF) — sinaliza "tem mais" sem
                // poluir visualmente com número. O aria-label e o title
                // informam a quantidade exata pra acessibilidade/hover.
                chip.textContent = "⋯";
                line.appendChild(chip);
 
                // Anexa o popover ao portal global (não ao card) — escapa
                // overflow:hidden de qualquer ancestral.
                ensurePortal().appendChild(popover);
 
                chip.addEventListener("click", function (e) {
                    e.stopPropagation();
                    var open = chip.getAttribute("aria-expanded") === "true";
                    closeAll();
                    if (!open) {
                        popover.hidden = false;
                        // Render primeiro (offsetWidth precisa do layout),
                        // depois posiciona.
                        positionPopover(popover, chip);
                        chip.setAttribute("aria-expanded", "true");
                        chip.__glaPopover = popover;
                    }
                });
 
                reward.dataset.glaOverflow = "done";
            }
 
            function closeAll() {
                document.querySelectorAll(".reward-overflow-popover").forEach(function (p) {
                    p.hidden = true;
                    p.style.pointerEvents = "none";
                });
                document.querySelectorAll(".reward-more-chip").forEach(function (c) {
                    c.setAttribute("aria-expanded", "false");
                });
            }
 
            // Reposiciona qualquer popover aberto em scroll/resize.
            function repositionOpen() {
                document.querySelectorAll(".reward-more-chip[aria-expanded=\"true\"]").forEach(function (chip) {
                    var pop = chip.__glaPopover;
                    if (pop && !pop.hidden) positionPopover(pop, chip);
                });
            }
            window.addEventListener("resize", repositionOpen);
            window.addEventListener("scroll", repositionOpen, true);
 
            // Click fora do chip e do popover fecha tudo.
            document.addEventListener("click", function (e) {
                if (e.target.closest(".reward-more-chip")) return;
                if (e.target.closest(".reward-overflow-popover")) return;
                closeAll();
            });
            document.addEventListener("keydown", function (e) {
                if (e.key === "Escape") closeAll();
            });
 
            function processAll() {
                document.querySelectorAll(".gla-item-reward").forEach(processOne);
            }
 
            if (document.readyState === "loading") {
                document.addEventListener("DOMContentLoaded", processAll);
            } else {
                processAll();
            }
 
            document.addEventListener("click", function (e) {
                if (e.target.closest(".reward-overflow-popover, .reward-more-chip")) return;
                closeAll();
            });
 
            document.addEventListener("keydown", function (e) {
                if (e.key === "Escape") closeAll();
            });
        })();
    </script>
</includeonly>

Edição atual tal como às 01h09min de 21 de maio de 2026