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

De Wiki Gla
Ir para navegação Ir para pesquisar
m
m
 
(12 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 1: Linha 1:
<includeonly>
<includeonly>
     <div class="gla-conquistas-root">
    <!--
      Widget:Conquistas — depende de Widget:Item.
 
      Uso obrigatório na página da wiki:
          {{#widget:Item}}
          {{#widget:Conquistas}}
          {{#invoke:Conquistas|renderAll}}
 
      Widget:Item é quem traz a CSS dos ícones (.reward-wrapper,
      .item-wrapper, .item-count) e o JS do tooltip — mesmo padrão da
      Predefinição:Reward que faz {{#widget:Item}}{{#invoke:Reward|exibir}}.
      Sem ele, os rewards aparecem como wikitext cru e sem tooltip.
    -->
    <!--
      Atributos no root:
 
      data-hidden-style controla o MARCADOR visual das conquistas hidden=true.
      Valores aceitos: "badge" | "stripes" | "ribbon" | "stamp" | "subtle".
      Default escolhido: "ribbon" (fita diagonal cinza "SECRETA" no canto).
 
      data-reveal-mode controla a CENSURA do conteúdo das hidden=true. O
      conteúdo continua no HTML — só fica visualmente coberto até o jogador
      clicar pra revelar (anti-spoiler). Valores aceitos:
        "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"
 
      Pra trocar qualquer um, edita o atributo abaixo.
    -->
     <div class="gla-conquistas-root" data-hidden-style="ribbon" data-reveal-mode="blur">
         <div class="gla-conquistas-headerbox">
         <div class="gla-conquistas-headerbox">
             <div class="gla-conquistas-header">
             <div class="gla-conquistas-header">
Linha 7: Linha 38:
             </div>
             </div>


             <div class="gla-conquistas-tabs">
             <div class="gla-conquistas-toolbar">
                <span class="gla-conquistas-tab is-active" data-tab="geral">Geral</span>
                <div class="gla-conquistas-tabs-scroll">
                <span class="gla-conquistas-tab" data-tab="personagens">Personagens</span>
                    <div class="gla-conquistas-tabs">
                <span class="gla-conquistas-tab" data-tab="missao">Missão</span>
                        <span class="gla-conquistas-tab is-active" data-tab="geral">Geral</span>
                <span class="gla-conquistas-tab" data-tab="bau">Baú</span>
                        <span class="gla-conquistas-tab" data-tab="personagens">Personagens</span>
                <span class="gla-conquistas-tab" data-tab="navegacao">Navegação</span>
                        <span class="gla-conquistas-tab" data-tab="missao">Missão</span>
                <span class="gla-conquistas-tab" data-tab="pvp">PvP</span>
                        <span class="gla-conquistas-tab" data-tab="bau">Baú</span>
                <span class="gla-conquistas-tab" data-tab="pve">PvE</span>
                        <span class="gla-conquistas-tab" data-tab="navegacao">Navegação</span>
                <span class="gla-conquistas-tab" data-tab="coliseu">Coliseu</span>
                        <span class="gla-conquistas-tab" data-tab="pvp">PvP</span>
                <span class="gla-conquistas-tab" data-tab="poneglyph">Poneglyph</span>
                        <span class="gla-conquistas-tab" data-tab="pve">PvE</span>
                <span class="gla-conquistas-tab" data-tab="indicacao">Indicação</span>
                        <span class="gla-conquistas-tab" data-tab="coliseu">Coliseu</span>
                <span class="gla-conquistas-tab" data-tab="celular">Celular</span>
                        <span class="gla-conquistas-tab" data-tab="poneglyph">Poneglyph</span>
                <span class="gla-conquistas-tab" data-tab="bossrush">Boss Rush</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>
 
                <div class="gla-conquistas-controls">
                    <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>
         </div>
         </div>


        <!--
          Painéis vazios. O Módulo:Conquistas (#invoke renderAll) emite os
          cards FORA do widget (Smarty não reparsa wikitext, então não dá pra
          passar como parâmetro). O JS abaixo move cada card pro painel certo
          a partir do data-tab.
          Uso na página da wiki:
              {{#widget:Conquistas}}
              {{#invoke:Conquistas|renderAll}}
        -->
         <div class="gla-conquistas-panel is-active" data-tab-content="geral">
         <div class="gla-conquistas-panel is-active" data-tab-content="geral">
             <div class="gla-list"></div>
             <div class="gla-list"></div>
Linha 59: Linha 118:
             <div class="gla-list"></div>
             <div class="gla-list"></div>
         </div>
         </div>
     </div>
     </div>


     <style>
     <style>
        /* 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');
        /* ─── Variáveis ──────────────────────────────────────────────────────── */
        /* Tema branco fixo. Azul fica reservado para detalhes (tab/filtro ativo,
          foco da busca, label da recompensa, chevron, hover). Sem dark mode
          automático — o widget deve manter o mesmo visual independente do skin. */
        .gla-conquistas-root {
            color-scheme: light;
            /* Texto */
            --gla-ink: #0f172a;
            /* slate-900 — título e texto principal */
            --gla-ink-2: #475569;
            /* slate-600 — texto secundário */
            --gla-dim: #94a3b8;
            /* slate-400 — placeholder */
            --gla-dim-2: #cbd5e1;
            /* slate-300 — bordas sutis */
            /* Superfícies (todas claras) */
            --gla-paper: #ffffff;
            --gla-paper-2: #f8fafc;
            /* slate-50 — hover sutil */
            --gla-paper-3: #f1f5f9;
            /* slate-100 — chip recompensa */
            --gla-rule: #e2e8f0;
            /* slate-200 — bordas/divisores */
            /* Accent azul (só pra detalhes) */
            --gla-accent: #2563eb;
            /* blue-600 */
            --gla-accent-soft: #60a5fa;
            /* blue-400 */
            --gla-accent-bg: #eff6ff;
            /* blue-50 — focus ring */
            /* Sombra discreta */
            --gla-shadow: 0 1px 2px rgba(15, 23, 42, 0.04),
                0 1px 3px rgba(15, 23, 42, 0.06);
        }
        /* Força tema claro mesmo se o skin/OS estiver em dark — o widget tem
          identidade visual própria e não deve trocar de cor com o ambiente. */
        .gla-conquistas-root,
        .gla-conquistas-root * {
            color-scheme: light;
        }
        /* ─── Layout principal ───────────────────────────────────────────────── */
        .gla-conquistas-root {
            color: var(--gla-ink);
        }
         .gla-conquistas-headerbox {
         .gla-conquistas-headerbox {
             max-width: 1100px;
             margin: 0 0 16px;
             margin: 0 auto 20px;
             padding: 0;
             padding: 20px;
             background: transparent;
             border-radius: 16px;
             border: none;
            background: #ffffff;
        }
             border: 1px solid #e5e7eb;
 
        .gla-conquistas-header {
             display: none;
         }
         }


         .gla-conquistas-header h2 {
        /* ─── Toolbar (tabs + busca) ─────────────────────────────────────────── */
             margin: 0;
        /* Sem chrome próprio — só agrupa tabs e controles. */
             font-size: 26px;
         .gla-conquistas-toolbar {
             font-weight: 700;
             display: block;
             color: #020617;
            width: 100%;
            background: transparent;
            border: none;
             border-radius: 0;
             box-shadow: none;
             padding: 0;
         }
         }


         .gla-conquistas-header p {
        /* ─── Wrapper das abas ───────────────────────────────────────────────── */
             margin: 4px 0 16px;
        /* Sem scroll horizontal. As abas usam flex-wrap pra quebrar linha
             color: #64748b;
          naturalmente em telas estreitas. */
             font-size: 14px;
         .gla-conquistas-tabs-scroll {
             position: relative;
            overflow: visible;
            padding: 0;
             background: transparent;
             border: none;
            border-radius: 0;
         }
         }


Linha 88: Linha 214:
             display: flex;
             display: flex;
             flex-wrap: wrap;
             flex-wrap: wrap;
             gap: 8px;
             gap: 6px;
            padding: 0;
            width: 100%;
            min-width: 0;
            box-sizing: border-box;
            margin: 0 0 12px;
         }
         }


        /* ─── Tab pill / botão ───────────────────────────────────────────────── */
        /* Botões redondos clean: branco com borda cinza, hover sutil,
          ativo em azul sólido. Sem fichário, sem stripe. */
         .gla-conquistas-tab {
         .gla-conquistas-tab {
             display: inline-block;
             flex: 0 0 auto;
             padding: 8px 14px;
            text-align: center;
            white-space: nowrap;
            font-size: 13px;
            font-weight: 600;
             padding: 7px 14px;
            border: 1px solid var(--gla-rule);
             border-radius: 999px;
             border-radius: 999px;
             border: 1px solid #cbd5e1;
             background: var(--gla-paper);
             background: #f8fafc;
             color: var(--gla-ink-2);
             cursor: pointer;
             cursor: pointer;
            box-sizing: border-box;
            user-select: none;
            transition: background 0.15s, color 0.15s, border-color 0.15s, box-shadow 0.15s;
        }
        .gla-conquistas-tab:hover {
            background: var(--gla-paper-2);
            color: var(--gla-ink);
            border-color: var(--gla-dim-2);
        }
        .gla-conquistas-tab.is-active {
            background: var(--gla-accent);
            color: #ffffff;
            border-color: var(--gla-accent);
            box-shadow: 0 1px 2px rgba(37, 99, 235, 0.25);
        }
        .gla-conquistas-tab.is-active:hover {
            background: var(--gla-accent);
            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;
             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;
             font-weight: 600;
             color: #0f172a;
             color: var(--gla-ink-2);
            cursor: pointer;
            transition: background 0.15s, color 0.15s, border-color 0.15s;
         }
         }


         .gla-conquistas-tab:hover {
         .gla-conquistas-filter:hover {
             background: #e2e8f0;
             background: var(--gla-paper-2);
            color: var(--gla-ink);
            border-color: var(--gla-dim-2);
         }
         }


         .gla-conquistas-tab.is-active {
         .gla-conquistas-filter.is-active {
             background: #0f172a;
             background: var(--gla-accent);
             color: #ffffff;
             color: #ffffff;
             border-color: #0f172a;
             border-color: var(--gla-accent);
         }
         }


         /* PAINEL */
         /* ─── Painéis ────────────────────────────────────────────────────────── */
         .gla-conquistas-panel {
         .gla-conquistas-panel {
            max-width: 1100px;
             margin: 14px 0 0;
             margin: 20px auto 0;
             display: none;
             display: none;
         }
         }
Linha 124: Linha 343:
         }
         }


         /* LISTA */
         .gla-conquistas-source {
            display: none;
        }
 
         .gla-list {
         .gla-list {
             display: flex;
             display: flex;
Linha 131: Linha 353:
         }
         }


         /* ITEM */
         /* ─── Card ───────────────────────────────────────────────────────────── */
        /* Branco com borda cinza. Hover marca borda azul (detalhe). */
         .gla-item {
         .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;
             display: flex;
             align-items: center;
             align-items: center;
            justify-content: space-between;
             gap: 16px;
             gap: 16px;
             padding: 12px 14px;
             padding: 14px 18px;
             border-radius: 12px;
             min-height: 76px;
             border: 1px solid #e5e7eb;
             position: relative;
            background: #f8fafc;
         }
         }


         /* LADO ESQUERDO */
         /* 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 {
         .gla-item-left {
             display: flex;
             display: flex;
             align-items: center;
             align-items: center;
             gap: 12px;
             gap: 14px;
            flex: 1;
            min-width: 0;
         }
         }


        /* ICONE */
         .gla-item-icon {
         .gla-item-icon img {
             flex: 0 0 auto;
             width: 56px;
             display: flex;
             height: 56px;
             align-items: center;
             object-fit: cover;
             justify-content: center;
            border: none !important;
            padding: 0 !important;
            background: none !important;
             box-shadow: none !important;
         }
         }


         /* fallback extra */
         /* Ícone respeita o tamanho do arquivo na wiki (recomendado: 52×52).
         .gla-item-icon .thumbimage,
          Sem dimensões fixas. */
        .gla-item-icon .thumb,
         .gla-item-icon img {
        .gla-item-icon a {
            object-fit: contain;
             border: none !important;
             border: none !important;
             padding: 0 !important;
             padding: 0 !important;
             background: none !important;
             background: none !important;
             box-shadow: none !important;
             box-shadow: none !important;
            display: block;
         }
         }


         /* TEXTO */
         /* Título preto (sem azul). Azul fica só nos detalhes. */
         .gla-item-title {
         .gla-item-title {
            font-size: 15px;
             font-weight: 700;
             font-weight: 700;
             font-size: 15px;
             color: var(--gla-ink);
             color: #0f172a;
            line-height: 1.25;
        }
 
        .gla-conquistas-root .gla-item-title {
             color: var(--gla-ink);
         }
         }


         .gla-item-desc {
         .gla-item-desc {
             font-size: 13px;
             font-size: 13px;
             color: #64748b;
             color: var(--gla-ink-2);
             margin-top: 2px;
             margin-top: 2px;
            line-height: 1.4;
         }
         }


         /* RECOMPENSA */
         /* ─── 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 {
         .gla-item-reward {
             font-size: 13px;
             flex-shrink: 0;
            color: #2563eb;
            font-weight: 600;
             display: flex;
             display: flex;
            flex-direction: column;
             align-items: center;
             align-items: center;
             gap: 6px;
             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: 11px;
            font-weight: 700;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--gla-accent);
            white-space: nowrap;
         }
         }


        /* Chip de itens — agora é o .reward-wrapper (emitido pelo Lua/Widget:Item).
          Encolhe com a quantidade (min-width pra 1 item, max-width pra caber
          5 + chip "+M" sem wrap). */
         .gla-item-reward .reward-wrapper {
         .gla-item-reward .reward-wrapper {
            display: block;
            background: var(--gla-paper-3);
            border: 1px solid var(--gla-rule);
            border-radius: 10px;
            padding: 7px 12px 9px;
            min-width: 72px;
            /* 285 = espaço pra 4 ícones (4×48 + 3×4) + chip "+M" (48) + gaps + padding. */
            max-width: 285px;
            width: fit-content;
            box-sizing: border-box;
        }
        /* ─── Botão spoiler (abinha no bottom-center) ────────────────────────── */
        /* Posicionado absolutamente no bottom-center do .gla-item-main.
          Pequeno e horizontalmente centralizado — fica no "corredor" central
          livre entre o título/desc à esquerda e a recompensa à direita,
          sem aumentar a altura do card. */
        .gla-item-spoiler-toggle {
            position: absolute;
            /* main padding-left (18) + icon (52) + gap (14) = 84 → alinhado com o começo do título.
              A versão anterior usava left:50% (centrado), mas o chip da recompensa
              encavalava em telas mais apertadas. Ancorar à esquerda elimina a colisão. */
            left: 84px;
            bottom: 6px;
             display: inline-flex;
             display: inline-flex;
             align-items: center;
             align-items: center;
            gap: 6px;
            margin: 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;
            z-index: 1;
            transition: background 0.15s, border-color 0.15s, color 0.15s;
        }
        .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;
        }
        .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: 4;
            pointer-events: none;
            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 5º. */
            flex-wrap: nowrap !important;
            justify-content: center;
            gap: 4px;
            width: 100%;
        }
        /* ─── Chip "+M" (overflow) ─────────────────────────────────────────── */
        /* Mesmo tamanho/forma do .item-wrapper pra alinhar visualmente com os
          ícones, mas com texto "+N" no centro. Click abre o popover com os
          itens escondidos. */
        .gla-item-reward .reward-more-chip {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 48px;
            height: 48px;
            padding: 0;
            border: 1px solid var(--gla-rule);
            border-radius: 8px;
            background: var(--gla-paper);
            color: var(--gla-accent);
            font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
            font-size: 18px;
            font-weight: 700;
            line-height: 1;
            letter-spacing: -0.02em;
            cursor: pointer;
            flex-shrink: 0;
            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-bg);
            border-color: var(--gla-accent-soft);
        }
        /* Popover ancorado no chip — drop-down dos itens escondidos. */
        .gla-item-reward .reward-overflow-popover {
            position: absolute;
            top: calc(100% + 6px);
            right: 0;
            display: flex;
            flex-wrap: wrap;
            justify-content: flex-end;
            gap: 4px;
            padding: 8px;
            background: var(--gla-paper);
            border: 1px solid var(--gla-rule);
            border-radius: 10px;
            box-shadow: 0 6px 18px -4px rgba(15, 23, 42, 0.15),
                0 2px 6px -2px rgba(15, 23, 42, 0.08);
            z-index: 10;
            max-width: 268px;
            animation: gla-popover-in 0.18s ease;
        }
        .gla-item-reward .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 stack vertical empurra o "bottom" do .gla-item-main
              pra cima da recompensa — o spoiler absoluto colidiria com o chip.
              Saindo do absoluto e deixando ele fluir como 3º item do flex-wrap. */
            .gla-item-spoiler-toggle {
                position: static;
                transform: none;
                align-self: flex-start;
                margin: 4px 0 0;
                padding: 2px 11px 3px;
            }
            .gla-item-spoiler {
                flex-direction: column;
            }
            .gla-item-spoiler-media {
                flex: 1 1 100%;
                max-width: 100%;
            }
         }
         }
     </style>
     </style>
Linha 204: Linha 1 125:
             var root = document.querySelector(".gla-conquistas-root");
             var root = document.querySelector(".gla-conquistas-root");
             if (!root) return;
             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 tabs = root.querySelectorAll(".gla-conquistas-tab");
             var panels = root.querySelectorAll(".gla-conquistas-panel");
             var panels = root.querySelectorAll(".gla-conquistas-panel");
             var validTabs = {};
             var validTabs = {};
             panels.forEach(function (p) {
             panels.forEach(function (p) {
                 validTabs[p.getAttribute("data-tab-content")] = true;
                 var name = p.getAttribute("data-tab-content");
                if (name) validTabs[name] = p.querySelector(".gla-list");
             });
             });


             // Procura cards .gla-item na PAGINA INTEIRA (fora do widget) e move pro painel correto.
             // Move cards do invoke source para os painéis corretos
            // Isso evita aninhar widgets, que quebraria o {{Reward}} e [[File:]].
             document.querySelectorAll(".gla-item[data-tab]").forEach(function (card) {
             document.querySelectorAll(".gla-item[data-tab]").forEach(function (card) {
                if (root.contains(card)) return;
                 var tag = (card.getAttribute("data-tab") || "").toLowerCase();
                 var tag = (card.getAttribute("data-tab") || "").toLowerCase();
                 if (!validTabs[tag]) {
                 var list = validTabs[tag] || validTabs["geral"];
                    if (tag) {
                if (list) list.appendChild(card);
                        console.warn("[Conquistas] tag desconhecida: '" + tag + "' caindo em 'geral'.");
            });
 
            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";
                     }
                     }
                    tag = "geral";
                 }
                 }
                 var list = root.querySelector('.gla-conquistas-panel[data-tab-content="' + tag + '"] .gla-list');
 
                 if (list) list.appendChild(card);
                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");
                        });
                    }
                }
            }
 
            function applyVisibility() {
                 var panel = root.querySelector('.gla-conquistas-panel[data-tab-content="' + currentTab + '"]');
                if (!panel) return;
                var search = currentSearch.toLowerCase();
                panel.querySelectorAll(".gla-item").forEach(function (card) {
                    var titleEl = card.querySelector(".gla-item-title");
                    var descEl = card.querySelector(".gla-item-desc");
                    var titleText = titleEl ? titleEl.textContent : "";
                    var descText = descEl ? descEl.textContent : "";
                    var matchSearch = !search ||
                        titleText.toLowerCase().indexOf(search) >= 0 ||
                        descText.toLowerCase().indexOf(search) >= 0;
 
                    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"
            root.addEventListener("click", function (e) {
                var toggle = e.target.closest(".gla-item-spoiler-toggle");
                if (!toggle) return;
                if (e.target.closest(".item-wrapper")) return;
                var card = toggle.closest(".gla-item.has-spoiler");
                if (!card) return;
                e.preventDefault();
 
                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");
                }
            });
 
            // ─── 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. Ignora
            // clicks em interativos dentro do card (botão de spoiler, ícones
            // de reward com tooltip, links na descrição, chip "+N" de overflow).
            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;
                if (e.target.closest(".gla-item-spoiler-toggle, .item-wrapper, a, .reward-more-chip, .reward-overflow-popover")) return;
                card.classList.add("is-revealed");
 
                var id = card.getAttribute("data-id");
                if (id) {
                    revealedSet[id] = true;
                    saveRevealed(revealedSet);
                }
             });
             });


             function abrirAba(nome) {
             function abrirAba(nome) {
                 tabs.forEach(function (t) {
                 currentTab = nome;
                    t.classList.remove("is-active");
                currentFilter = "all";
                });


                 panels.forEach(function (p) {
                tabs.forEach(function (t) { t.classList.remove("is-active"); });
                    p.classList.remove("is-active");
                 panels.forEach(function (p) { p.classList.remove("is-active"); });
                });


                 var tab = root.querySelector('.gla-conquistas-tab[data-tab="' + nome + '"]');
                 var tab = root.querySelector('.gla-conquistas-tab[data-tab="' + nome + '"]');
                 var panel = root.querySelector('.gla-conquistas-panel[data-tab-content="' + nome + '"]');
                 var panel = root.querySelector('.gla-conquistas-panel[data-tab-content="' + nome + '"]');
                 if (tab) tab.classList.add("is-active");
                 if (tab) tab.classList.add("is-active");
                 if (panel) panel.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();
             }
             }


Linha 250: Linha 1 372:
             abrirAba("geral");
             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;
            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.textContent = "+" + hidden.length;
                line.appendChild(chip);
                reward.appendChild(popover);
                chip.addEventListener("click", function (e) {
                    e.stopPropagation();
                    var open = chip.getAttribute("aria-expanded") === "true";
                    closeAll();
                    if (!open) {
                        popover.hidden = false;
                        chip.setAttribute("aria-expanded", "true");
                    }
                });
                reward.dataset.glaOverflow = "done";
            }
            function closeAll() {
                document.querySelectorAll(".reward-overflow-popover").forEach(function (p) {
                    p.hidden = true;
                });
                document.querySelectorAll(".reward-more-chip").forEach(function (c) {
                    c.setAttribute("aria-expanded", "false");
                });
            }
            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>
     </script>
</includeonly>
</includeonly>

Edição atual tal como às 21h42min de 20 de maio de 2026