/* abilities.css — janela de Habilidades (js/ui/windows/abilities.js; docs/specs/ui-gameplay.md §5.1). Medidas em px de arte:
   calc(N * var(--px)).
   Janela 480×276 no lobby e 480×250 na corrida → corpo 468×232 e 468×206 (rodapé de 16). O corpo é uma coluna com vão 3:
   [recado da Torre 16, só lobby com `fromTower`] · a LINHA DO MEIO (flexível) · a BARRA (cabeçalho 10 + 1 + slot 36 + 1 +
   chip 16 = 64). A linha do meio é `Ativas` + `Passivas` (258 de largura) | vão 5 | o DETALHE (filete 1 + respiro 4 + miolo
   200). ORÇAMENTO VERTICAL das grades: 10 + 1 + 73 (7×2) + 3 + 10 + 1 + 36 (7×1) = 134 — cabe nos 139 da corrida (206 − 3 −
   64) e nos 165 do lobby (232 − 3 − 64); com o recado da Torre o lobby fica com 146. A conta de antes (147 + 1 + 53 + 9 =
   210, feita para 254) não fechava nos 250 da corrida e a 4.ª fileira da árvore saía cortada e desbotada (sh 147 / ch 142).
   'Quando usar' é uma FOLHA sobre a linha do meio inteira (468×165 no lobby, 468×139 na corrida): a barra fica à vista. */

.abilities-body {
  display: flex;
  flex-direction: column;
  gap: calc(3 * var(--px));
  overflow: hidden;
}
/* Pedido em voo: o bloco apaga, mas o ponteiro CHEGA — cada controle trava com "Aguardando o servidor…"
   (`widgets/button.js › lockBusy`); `pointer-events: none` aqui deixava o mouse atravessar sem motivo. */
.abilities-body.is-pending { opacity: 0.6; }

/* Pontos, na faixa do título: PULSA em 2 degraus só quando há onde gastar (`abilityView.js › pointsState`); ponto parado
   (tudo no máximo, ou a próxima só abre num nível à frente) fica apagado, e o gesto diz até quando. */
.abilities-points {
  align-self: center;
  margin-right: calc(4 * var(--px));
  color: var(--c-text-dim);
  white-space: nowrap;
}
.abilities-points.is-pulsing { color: var(--c-gold); animation: points-pulse 1s steps(2, jump-none) infinite; }
@keyframes points-pulse {
  from { filter: brightness(1.35); }
  to   { filter: brightness(0.8); }
}

/* ---- recado da Torre (`args.fromTower`, só lobby): 16 de altura no topo do corpo ------------------------------ */
.ab-recado {
  flex: none;
  display: flex;
  align-items: center;
  gap: calc(4 * var(--px));
  min-height: calc(16 * var(--px));
  color: var(--c-gold);
}
.ab-recado > span { flex: 1; min-width: 0; line-height: calc(9 * var(--px)); }

/* ---- linha do meio: as duas seções | o detalhe; a folha "Quando usar" por cima dela ---------------------------- */
.ab-mid {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
  gap: calc(5 * var(--px));
}
.ab-left {
  flex: none;
  width: calc(258 * var(--px));
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: calc(3 * var(--px));
}
.ab-sec { flex: none; display: flex; flex-direction: column; gap: calc(1 * var(--px)); min-height: 0; }
/* Cabeçalho de UMA palavra, linha de 10, texto apagado. Nas seções ele é a PISTA (`.has-more`, a regra da seção no gesto):
   `align-self: flex-start` para o pontilhado acabar onde a palavra acaba (num bloco de largura cheia ele vira régua). */
.ab-sec-head {
  flex: none;
  display: flex;
  align-items: center;
  gap: calc(4 * var(--px));
  height: calc(10 * var(--px));
  line-height: calc(10 * var(--px));
  color: var(--c-text-dim);
  white-space: nowrap;
}
.ab-sec > .ab-sec-head { align-self: flex-start; }
.ab-sec-head:focus-visible, .ab-bar-hint:focus-visible, .ab-cond-phrase:focus-visible { outline: var(--px) solid var(--c-gold); }

/* A GRADE: 7 colunas de 36 com vão 1 (7×36 + 6 = 258). As ativas mostram 2 fileiras (73), as passivas 1 (36) — hoje no
   máximo 14 + 7 (arqueiro) e tudo cabe sem rolar. Quantas são é DADO: passando disso a seção ROLA com o `scroll-fade`
   (`windows/abilities.js › syncOverflow` acende `is-scrollable` MEDINDO, nunca comparando com 14 ou 7). Dois ajustes do
   mecanismo, os mesmos da árvore de antes: `--scroll-fade-pad: 0` (a caixa acaba no fim de uma fileira — a folga de 6 faria a
   grade que cabe rolar 6 px à toa) e `--scroll-fade: 0` enquanto NÃO transborda (o degradê sempre aceso comeria os 12 px de
   baixo dos ícones da última fileira). O `:not()` pesa mais que o `.ab-grid` de `scroll-fade.css`, carregada depois. */
.ab-grid {
  display: grid;
  grid-template-columns: repeat(7, calc(36 * var(--px)));
  grid-auto-rows: calc(36 * var(--px));
  gap: calc(1 * var(--px));
  align-content: start;
  flex: none;
  --scroll-fade-pad: 0px;
}
#ab-grid-active { height: calc(73 * var(--px)); }
#ab-grid-passive { height: calc(36 * var(--px)); }
.ab-grid:not(.is-scrollable) { --scroll-fade: 0px; }

/* ---- ladrilho 36×36 (ícone 32): os quatro cantos têm dono e nunca se somam --------------------------------------
   ↖ o número do slot da barra (`.ab-tile-slot`) OU a marca de ouro "pode aprender" (`.ab-ready`) · ↗ o cadeado · ↘ o rank ou
   `Nv N`. As marcas moram na caixa interna do `.slot` (dentro da borda de 4), como o `.item-icon` (−2 → 2 px da borda). */
.ab-tile { cursor: pointer; touch-action: auto; }
.ab-tile:not(.is-learned) .item-icon { filter: saturate(0.45) brightness(0.72); }
.ab-tile.is-locked .item-icon { filter: grayscale(1) brightness(0.5); }
.ab-tile.is-locked .ability-card-lock { display: block; }
/* armada pela vaga: as ativas aprendidas acendem como ALVO, o resto apaga (passivas, não aprendidas, trancadas) */
.ab-tile.is-target, .ab-cell.is-target > .ab-cell-slot { outline: var(--px) dashed var(--c-gold); outline-offset: calc(-1 * var(--px)); }
.ab-tile.is-dim { opacity: 0.4; }
.ab-tile-slot, .ab-cell-num {
  position: absolute;
  left: calc(1 * var(--px));
  top: 0;
  z-index: 1;
  color: var(--c-gold);
  line-height: calc(8 * var(--px));
  text-shadow: var(--px) var(--px) 0 #000;
  pointer-events: none;
}
/* "Dá para APRENDER agora" (não aprendida, nível alcançado, ponto no bolso): 5×5 de ouro com contorno escuro de 1, ACIMA do
   ícone (`z-index`). Antes era um `::before`, que pinta ANTES do `.item-icon` absoluto (nine-slice.css) — o ícone o cobria e
   sobrava 1 px na quina transparente. Só no aprendível, nunca em todo rank possível: com 85 pontos ele acenderia em quase
   todo ladrilho, e selo que nunca apaga se aprende a ignorar (política de selo, ui-gameplay.md §9). */
.ab-ready {
  position: absolute;
  left: calc(-1 * var(--px));
  top: calc(-1 * var(--px));
  width: calc(5 * var(--px));
  height: calc(5 * var(--px));
  z-index: 1;
  background: var(--c-gold);
  box-shadow: 0 0 0 var(--px) #000;
  animation: ready-pulse 1s steps(2, jump-none) infinite;
  pointer-events: none;
}
@keyframes ready-pulse {
  from { filter: brightness(1.3); }
  to   { filter: brightness(0.75); }
}
.ab-tile-badge {
  position: absolute;
  right: calc(1 * var(--px));
  bottom: 0;
  z-index: 1;
  padding: 0 var(--px);
  color: var(--c-gold);
  line-height: calc(8 * var(--px));
  background: rgba(10, 8, 14, 0.75);
  text-shadow: var(--px) var(--px) 0 #000;
  pointer-events: none;
  white-space: nowrap;
}
.ab-tile-badge.is-level { color: var(--c-text-dim); }

/* Cadeado da trancada (ui/icons/ico_lock.png, 8×8 ampliado 2×), no canto ↗. */
.ability-card-lock {
  display: none;
  position: absolute;
  right: calc(-2 * var(--px));
  top: calc(-2 * var(--px));
  z-index: 1;
  width: calc(16 * var(--px));
  height: calc(16 * var(--px));
  background: var(--ui-ico_lock) no-repeat center / 100% 100%;
  image-rendering: pixelated;
  pointer-events: none;
}

/* ---- detalhe: UMA coluna que rola como bloco só, com os botões PRESOS embaixo ------------------------------------
   Filete de 1 + respiro de 4 + miolo de 200. Some a caixa de 27 px que rolava a descrição POR DENTRO (a 3.ª linha saía
   fatiada; a guarda do arqueiro escondia 42 px): quem rola é `.ab-dscroll` inteira, com o degradê do mecanismo, e a fila de
   botões fica fora da rolagem — quebra em duas linhas se não couber, roubando a altura da rolagem, nunca a dos botões. */
.ab-detail {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: calc(2 * var(--px));
  padding-left: calc(4 * var(--px));
  border-left: var(--px) solid rgba(176, 168, 152, 0.3);
}
.ab-detail.is-empty > * { visibility: hidden; }
.ab-dscroll { flex: 1; display: flex; flex-direction: column; gap: calc(2 * var(--px)); }
.ab-dscroll > * { flex: none; }
.ab-dhead { display: flex; align-items: flex-start; gap: calc(4 * var(--px)); }
.ab-det-icon { flex: none; }
.ab-det-icon.is-locked > .item-icon { filter: grayscale(1) brightness(0.5); }
.ab-det-icon.is-unlearned > .item-icon { filter: saturate(0.45) brightness(0.72); }
.ab-det-title { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: calc(2 * var(--px)); }
/* o nome inteiro, em ouro: quebra se precisar (nunca reticências) */
.ab-det-name { color: var(--c-gold); line-height: calc(9 * var(--px)); overflow-wrap: anywhere; text-shadow: var(--px) var(--px) 0 #000; }
.ab-det-meta { line-height: calc(9 * var(--px)); }
.ab-desc { color: var(--c-text-dim); line-height: calc(9 * var(--px)); overflow-wrap: anywhere; }
/* o `*nome*` de condição das guardas de classe (B126): destaque em ouro, sem o asterisco do dicionário */
.ab-desc-em { color: var(--c-gold); }

/* Números do rank: rótulo apagado + valor claro; o do PRÓXIMO rank em verde, depois da seta. */
.ability-card-stats {
  display: flex;
  flex-wrap: wrap;
  column-gap: calc(6 * var(--px));
  line-height: calc(9 * var(--px));
}
/* G1 (docs/ux-casos.md §22) — o rótulo "Mana"/"Recarga" virou o ícone da peça que já existe (`ico_mana`,
   `ico_stat_cooldown_reduction`): a ficha é `inline-flex` para o desenho e o número andarem juntos. "Dano" e
   "Alvos" continuam palavra — a série não tem peça que diga essas duas ideias sem roubar a de outra.
   ESTE BLOCO É COMPARTILHADO: o tooltip da barra do HUD usa a mesma ficha (`widgets/abilityStat.js`, hud.css). */
.ability-stat { display: inline-flex; align-items: center; gap: calc(2 * var(--px)); white-space: nowrap; color: var(--c-text); }
.ability-stat-ico {
  display: inline-block;
  flex: none;
  width: calc(8 * var(--px));
  height: calc(8 * var(--px));
  background-repeat: no-repeat;
  background-size: 100% 100%;
  image-rendering: pixelated;
}
/* a ampulheta da série de stats é 16×16; aqui ela desce para a altura da linha de 9 px */
.ability-stat[data-stat="cooldown"] > .ability-stat-ico { width: calc(9 * var(--px)); height: calc(9 * var(--px)); }
.ability-stat-label { color: var(--c-text-dim); }
.ability-stat-arrow { color: var(--c-text-dim); }
.ability-stat-next { color: var(--c-ok); }
.ability-stat.is-mod { color: #8fd0ff; }
.ability-stat.has-hint { cursor: help; }
.ability-stat.has-hint:focus-visible { outline: var(--px) solid var(--c-gold); }

/* Uma linha por primitiva de efeito; o efeito interno de trigger/consume entra recuado. */
.ab-det-effects { display: flex; flex-direction: column; line-height: calc(9 * var(--px)); }
.ab-eff { color: var(--c-text); }
.ab-eff.is-inner { padding-left: calc(6 * var(--px)); }
.ab-eff.is-mod { color: #8fd0ff; }
/* a seta "atual → próximo" é um `<span>` próprio (o verde é só do próximo): o respiro em volta dela é daqui */
.ab-eff > .ability-stat-arrow { margin: 0 calc(2 * var(--px)); }

/* a fila presa: 3 botões nos 200 do miolo (`Subir +1` · `Máx +N` · `Pôr na barra`|`Mover`); com a fonte 25 % mais larga ela
   quebra em duas (−18 px na coluna que rola) */
.ab-dactions {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(2 * var(--px));
  min-height: calc(16 * var(--px));
}

/* ---- a folha "Quando usar" (sobre a linha do meio inteira; a barra fica à vista, com o chip do slot aceso) ------- */
.ab-sheet {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: calc(2 * var(--px));
  background: var(--c-panel-fill);
}
.ab-cond-title {
  flex: none;
  height: calc(10 * var(--px));
  line-height: calc(10 * var(--px));
  color: var(--c-gold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 9 respostas em 3 colunas de 154×20 (vão 3 × 2 = 6: 3 × 154 + 6 = 468) */
.ab-cond-list {
  flex: none;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: calc(20 * var(--px));
  column-gap: calc(3 * var(--px));
  row-gap: calc(1 * var(--px));
}
.ab-cond-opt {
  display: block;
  min-width: 0;
  min-height: 0;
  height: calc(20 * var(--px));
  padding: 0 calc(3 * var(--px));
  text-align: left;
  line-height: calc(12 * var(--px));
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.ab-cond-opt.is-active { color: var(--c-gold); }
.ab-cond-valuerow { flex: none; display: flex; align-items: center; gap: calc(3 * var(--px)); min-height: calc(16 * var(--px)); }
.ab-cond-step { min-width: calc(16 * var(--px)); min-height: calc(16 * var(--px)); justify-content: center; padding: 0; }
.ab-cond-value { min-width: calc(30 * var(--px)); text-align: center; }
.ab-cond-phrase { flex: none; line-height: calc(9 * var(--px)); }
/* a pista é um pontilhado: tem de acabar onde o texto acaba */
.ab-cond-phrase.has-more { align-self: flex-start; }
.ab-cond-actions { flex: none; display: flex; justify-content: flex-end; gap: calc(4 * var(--px)); margin-top: auto; }

/* ---- a barra: a ordem dos slots é a prioridade do automático --------------------------------------------------- */
.ab-barbox { flex: none; display: flex; flex-direction: column; gap: calc(1 * var(--px)); }
.ab-bar-guide { color: var(--c-gold); }
.ab-bar-hint { color: var(--c-text-dim); }
.ab-bar { display: flex; gap: calc(2 * var(--px)); }
/* uma célula por `classes[].abilitySlots` (dado): 90 de base, e com mais slots elas encolhem por igual —
   (468 − 2(n − 1)) / n — sem passar da linha */
.ab-cell {
  flex: 0 1 calc(90 * var(--px));
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(1 * var(--px));
}
.ab-cell-slot { cursor: pointer; touch-action: manipulation; }
.ab-cell.is-empty .ab-cell-slot { opacity: 0.7; }
.ab-cell.is-empty.is-target .ab-cell-slot, .ab-cell.is-armed .ab-cell-slot { opacity: 1; }
.ab-cell.is-selected > .ab-cell-slot { outline: var(--px) solid var(--c-gold); outline-offset: calc(-1 * var(--px)); }
.ab-cell.is-source > .ab-cell-slot { outline: var(--px) solid var(--c-text-dim); outline-offset: calc(-1 * var(--px)); }
.ab-cell.is-armed > .ab-cell-slot { outline: var(--px) dashed var(--c-gold); outline-offset: calc(-1 * var(--px)); }
.ab-cell-cond {
  display: block;
  width: 100%;
  /* 16 de caixa (borda 4 + texto 8 + 4, a medida do `.btn`) */
  min-height: calc(16 * var(--px));
  height: calc(16 * var(--px));
  padding: 0 calc(2 * var(--px));
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  text-align: center;
  line-height: calc(8 * var(--px));
}
/* condição sugerida pelo dado e `Só manual` ficam apagadas; escolhida pelo jogador, clara; a do slot com a folha aberta, ouro */
.ab-cell-cond.is-suggested, .ab-cell-cond.is-manual { color: var(--c-text-dim); }
.ab-cell-cond.is-active { color: var(--c-gold); }
/* G5: slot vazio mostra UMA marca de ausência (`—`), apagada — e só porque ali se age (o toque arma a vaga). */
.ab-cell-cond.is-empty { color: var(--c-text-dim); }

/* ---- rodapé: `Redistribuir [moeda] preço` e, à direita, o recibo ou o erro ------------------------------------- */
.ab-footer { min-height: calc(16 * var(--px)); }
#ab-reset > .gold-label { color: inherit; }
/* a moeda tem 9 de altura e o miolo do botão, 8: sem o −1 em cima e embaixo o botão media 17 e o rodapé roubava 1 px da linha do
   meio (medido no navegador; o molde do `Receber [moeda]` do Bestiário) */
#ab-reset > .gold-label > .ico-gold { margin: calc(-1 * var(--px)) 0; }
.ab-msg {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--c-text-dim);
}
.ab-msg.is-error { color: var(--c-danger); }
.ab-reset-body p { margin: 0 0 calc(4 * var(--px)); line-height: calc(10 * var(--px)); }

@media (prefers-reduced-motion: reduce) {
  .abilities-points.is-pulsing, .ab-ready { animation: none; }
}
