/* hud.css — HUD da Exploração (js/ui/screens/explorationHud.js): HP/MP/exp/nível/kills, combo, feed de loot, efeitos
   ativos, barra de habilidades + poções, mochila, botões. Dona: trilha K2c (ui-gameplay.md §5.2, §12).
   Barras animam por CSS transition; a cena escreve no store no máximo a 10 Hz (architecture.md §3.2).
   Os blocos superiores ficam sobre o céu claro do bioma e o feed sobre a terra: nada de texto solto — painel 9-slice
   em cima (`.panel` de nine-slice.css, windows/panel.png) e faixa escura por linha embaixo. */

.hud {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* Contorno de 1 px de arte nos 4 lados: número sobre ícone colorido continua legível em 1×. */
  --hud-outline: var(--px) 0 0 #000, calc(-1 * var(--px)) 0 0 #000, 0 var(--px) 0 #000, 0 calc(-1 * var(--px)) 0 #000, var(--px) var(--px) 0 #000;
}
.hud > * { pointer-events: auto; }

/* Painel do HUD = `.panel` (borda 8 px de arte, dos quais ~4 são moldura visível e o resto miolo). O corpo entra
   2 px na faixa da borda para o painel não ficar gordo; os cantos ornamentados (gold) continuam livres. */
.hud-panel { padding: 0; }
.hud-panel-body { margin: calc(-2 * var(--px)); }

.hud-top-left {
  position: absolute;
  top: calc(4 * var(--px));
  left: calc(4 * var(--px));
  width: calc(136 * var(--px));
}
.hud-top-left .hud-panel-body {
  display: flex;
  flex-direction: column;
  gap: calc(2 * var(--px));
}

.hud-name {
  display: flex;
  justify-content: space-between;
  gap: calc(4 * var(--px));
  color: var(--c-gold);
  text-shadow: var(--px) var(--px) 0 #000;
  white-space: nowrap;
  overflow: hidden;
}
/* `nome Nv N ··· classe` (ui-gameplay.md §5.2): o nível cola à direita do nome e a classe fica no canto direito, numa
   linha de 124 px de arte. PRIORIDADE nome > nível > classe: quem cede é a CLASSE — ela ocupa a sobra (`flex: 1 1`,
   alinhada à direita) e corta com reticências (a inteira no `title`); se sobrar menos que o toco de 24 px (~4 letras),
   ela QUEBRA para a 2ª linha, que a altura fixa de uma linha esconde (continua no DOM para o leitor de tela — G7).
   O nome só corta no último recurso (nome + nível mais largos que a linha inteira): nunca com 16 letras comuns + Nv 100.
   Antes o nível roubava o espaço do NOME e todo nome de 11+ letras cortava (revisor da trilha H, 2026-09-30). */
.hud-top-left .hud-name {
  flex-wrap: wrap;
  align-content: flex-start;
  height: calc(10 * var(--px));
  line-height: calc(10 * var(--px));
}
.hud-top-left .hud-name-who {
  display: flex;
  gap: calc(4 * var(--px));
  min-width: 0;
}
.hud-top-left .hud-name-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hud-top-left .hud-name-level { flex: none; color: var(--c-text); }
.hud-top-left .hud-name-level:empty { display: none; }
.hud-top-left .hud-name-class {
  flex: 1 1 calc(24 * var(--px));
  min-width: calc(24 * var(--px));
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Barras HP/MP/EXP com 10 de altura (a peça padrão tem 8): o rótulo de 8 ocupava a caixa inteira e os dois anéis da
   moldura riscavam o topo e o pé dos dígitos ("97,5K / 97,5K" parecia tachado). Com 10 o texto fica no miolo; o vão
   entre as barras cai de 1 para 0 (a moldura já separa), e o painel cresce só 3 px. Mesma regra nas barras do replay. */
.hud-bars .bar, .replay-side .bar { height: calc(10 * var(--px)); }
.hud-bars .bar + .bar { margin-top: 0; }
.hud-bars .bar:first-child { margin-top: calc(1 * var(--px)); }

/* Contador de ganho (js/ui/widgets/gainTicker.js): EXP e ouro da janela, colados à barra de EXP que eles enchem.
   Vieram do rastro do herói, onde disputavam a mesma coluna do dano sofrido e do ERROU (roadmap §1.18). Linha de
   altura fixa: acender e apagar não empurra a moldura do painel nem mexe nas barras. */
.hud-gain {
  display: flex;
  gap: calc(4 * var(--px));
  height: calc(9 * var(--px));
  line-height: calc(9 * var(--px));
  white-space: nowrap;
  overflow: hidden;
  text-shadow: var(--px) var(--px) 0 #000;
  opacity: 0;
  transition: opacity 0.25s ease-out;
}
.hud-gain.is-on { opacity: 1; }
.hud-gain-exp { color: #84c8f7; }
.hud-gain-gold { color: var(--c-gold); }
.hud-gain > span:empty { display: none; }

.hud-top-right {
  position: absolute;
  /* ACIMA das janelas (z 10 + i, windowManager.js): aqui mora o único controle do auto-avanço (o interruptor "Subir
     sozinho"), e uma janela arrastada para cá não pode cobri-lo nem roubar o clique dele. A tabela do
     `windowLayout.js` já não deixa nenhuma janela NASCER passando de x 514; isto é a rede para o arrasto. */
  z-index: 12;
  top: calc(4 * var(--px));
  right: calc(4 * var(--px));
  min-width: calc(96 * var(--px));
  text-align: right;
  text-shadow: var(--px) var(--px) 0 #000;
}
.hud-stats {
  display: flex;
  flex-direction: column;
  gap: calc(1 * var(--px));
}
.hud-stats > div { white-space: nowrap; }
.hud-stats > div:empty { display: none; }

.hud-level { color: var(--c-text); }
.hud-kills { color: var(--c-text-dim); }

/* Combo: aparece no centro-alto, cresce em passos e some.
   (C31) ESCADA DE MARCOS. Os degraus são os de `game/juice/combo.js` (10/50/100/500) e chegam aqui como classe
   (`ui/widgets/comboView.js` → `is-t0`…`is-t4`). Antes desta onda, 8× e 1502× eram o MESMO pixel: mesmo dourado,
   mesmo tamanho. Aqui cada degrau ganha cor e corpo, e o instante em que o marco é cruzado ganha o estalo grande
   (`is-milestone`) — o número só muda de cara NOS marcos, para a cor não piscar a cada abate. */
:root {
  --c-combo-t1: #e0b040; /* = --c-gold, o combo de sempre: 10× */
  --c-combo-t2: #ff9b2f; /* 50×: esquenta */
  --c-combo-t3: #ff5a3c; /* 100×: brasa */
  --c-combo-t4: #fff0b8; /* 500×: branco-quente, com halo dourado */
}
.hud-combo {
  position: absolute;
  top: calc(40 * var(--px));
  left: 50%;
  transform: translateX(-50%);
  font-size: calc(10 * var(--px));
  color: var(--c-text-dim);
  text-shadow: var(--px) var(--px) 0 #000;
  pointer-events: none;
  opacity: 0;
}
.hud-combo.is-t1 { font-size: var(--text-2); color: var(--c-combo-t1); }
.hud-combo.is-t2 { font-size: calc(20 * var(--px)); color: var(--c-combo-t2); }
.hud-combo.is-t3 { font-size: calc(24 * var(--px)); color: var(--c-combo-t3); }
.hud-combo.is-t4 {
  font-size: calc(28 * var(--px));
  color: var(--c-combo-t4);
  text-shadow: var(--px) var(--px) 0 #000, 0 0 calc(4 * var(--px)) var(--c-combo-t3), 0 0 calc(8 * var(--px)) var(--c-combo-t1);
}
.hud-combo.is-active { opacity: 1; animation: combo-pop 0.12s steps(2); }
/* o cruzamento do marco: estalo maior e mais longo que o pop de cada abate */
.hud-combo.is-active.is-milestone { animation: combo-milestone 0.42s steps(6); }
@keyframes combo-pop {
  from { transform: translateX(-50%) scale(1.25); }
  to   { transform: translateX(-50%) scale(1); }
}
@keyframes combo-milestone {
  from { transform: translateX(-50%) scale(2); }
  60%  { transform: translateX(-50%) scale(1.2); }
  to   { transform: translateX(-50%) scale(1); }
}

/* Feed de loot / abates no canto inferior esquerdo, sobre a terra do chão: cada linha ganha uma faixa escura
   translúcida e uma etiqueta à esquerda na cor da linha (qualidade do item, ouro no level up, apagada no abate). */
.loot-feed {
  position: absolute;
  left: calc(4 * var(--px));
  bottom: calc(4 * var(--px));
  display: flex;
  flex-direction: column-reverse;
  align-items: flex-start;
  gap: calc(1 * var(--px));
  pointer-events: none;
  text-shadow: var(--px) var(--px) 0 #000;
}
.loot-feed-item {
  padding: 0 calc(3 * var(--px)) 0 calc(2 * var(--px));
  border-left: calc(2 * var(--px)) solid currentColor;
  background: rgba(10, 8, 14, 0.72);
  line-height: calc(10 * var(--px));
  white-space: nowrap;
  animation: loot-feed-in 0.15s steps(3) both;
}
.loot-feed-item.is-kill { color: var(--c-text); border-left-color: var(--c-text-dim); }
/* --- run-life --- encontro: texto em ouro com a etiqueta CLARA — a subida de nível é ouro/ouro e o abate é
   claro/apagado, então esta combinação não se repete e a linha se lê de relance. */
.loot-feed-item.is-encounter { color: var(--c-gold); border-left-color: var(--c-text); }
.loot-feed-item.is-leaving { opacity: 0; transition: opacity 0.4s steps(4); }
/* --- ultimate --- (docs/specs/ultimate.md §6.1) Com o medidor na tela (x 132…180 · y 308…356, css/ult.css) o feed vira uma coluna
   de 124 × 64 (x 4…128 · y 292…356): 4 px antes do medidor e 2 px abaixo do botão do chat e da pilha de rendimentos, que assentam
   em y 290 (chat.css, work.css). A linha que passa de 124 QUEBRA e o nome segue inteiro (UX-GRAMATICA §3: com reticências, 215 dos
   647 nomes de item perdiam o fim). O DOM vem da mais velha à mais nova (`lootFeed.js`) e a tela as empilha com a mais nova em
   cima; aqui o `order` põe a mais nova PRIMEIRO no fluxo (de cima para baixo, `column`) e o `flex-end` assenta o bloco no pé — a
   mesma pilha de sempre —, e a coluna guarda as mais novas que cabem INTEIRAS: a mais velha que não cabe vai para a 2.ª coluna do
   `wrap`, que o `column-gap` de 640 joga para fora da caixa e o `overflow` esconde (some inteira, nunca cortada ao meio). As 5
   linhas de uma (54 px, `killFeed.js › max`) cabem como antes; os 64 dão lugar a uma quebra. */
#hud:has(.hud-ult-pin:not(.hidden)) .loot-feed {
  flex-direction: column;
  justify-content: flex-end;
  flex-wrap: wrap;
  width: calc(124 * var(--px));
  height: calc(64 * var(--px));
  column-gap: calc(640 * var(--px));
  overflow: hidden;
}
#hud:has(.hud-ult-pin:not(.hidden)) .loot-feed-item {
  max-width: 100%;
  white-space: normal;
  overflow-wrap: break-word;
}
#hud:has(.hud-ult-pin:not(.hidden)) .loot-feed-item:nth-last-child(2) { order: 1; }
#hud:has(.hud-ult-pin:not(.hidden)) .loot-feed-item:nth-last-child(3) { order: 2; }
#hud:has(.hud-ult-pin:not(.hidden)) .loot-feed-item:nth-last-child(4) { order: 3; }
#hud:has(.hud-ult-pin:not(.hidden)) .loot-feed-item:nth-last-child(n+5) { order: 4; }
@keyframes loot-feed-in {
  from { transform: translateX(calc(-8 * var(--px))); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* Canto inferior direito em duas linhas — [Habilidades][Mochila] sobre [2×][Auto][Sair] (--- vip ---: o 2× só para quem é ou foi
   VIP; o Auto é interruptor, sem "ligado/desligado" escrito — B362): numa linha só os botões invadiriam a barra de habilidades. */
.hud-actions {
  position: absolute;
  right: calc(4 * var(--px));
  bottom: calc(4 * var(--px));
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: calc(2 * var(--px));
}
.hud-actions-row { display: flex; align-items: stretch; gap: calc(2 * var(--px)); }
/* --- taskbar --- A fila DE CIMA (`#hud-actions-top`, y 288…312, alinhada à direita; ui-gameplay-habilidades.md §5.2): o modo faixa
   (`#btn-taskbar`, só no app Windows) e, no canto, o botão do serviçal (outra frente: ele se acrescenta DEPOIS). Vão de 4; sem filho
   à vista a fila não existe (o normal não se pinta, G5). Esconder é a classe `.hidden`, dos dois lados. */
.hud-actions-top { gap: calc(4 * var(--px)); }
.hud-actions-top:not(:has(> :not(.hidden))) { display: none; }

/* Botão Habilidades (`#btn-abilities`, tecla K): selo dourado com os pontos a gastar (§5.1). */
.hud-abilities-btn { position: relative; }
/* no canto SUPERIOR ESQUERDO (avaliação de UX, rodada 2): no direito ele ficava sob a etiqueta "Mochila cheia" e sobre
   o canto do botão da Mochila, vizinho */
.hud-badge {
  position: absolute;
  left: calc(-6 * var(--px));
  top: calc(-8 * var(--px));
  min-width: calc(9 * var(--px));
  height: calc(9 * var(--px));
  padding: 0 calc(2 * var(--px));
  background: var(--c-gold);
  color: var(--c-text-dark);
  box-shadow: 0 0 0 var(--px) #000;
  font-size: var(--text-1);
  line-height: calc(9 * var(--px));
  text-align: center;
  text-shadow: none;
  animation: badge-pulse 1s steps(2, jump-none) infinite;
}
@keyframes badge-pulse {
  from { filter: brightness(1.3); }
  to   { filter: brightness(0.95); }
}

/* Barra de habilidades + poções (ui-gameplay.md §5.2; widgets abilityBar.js / quickUse.js): embaixo ao centro,
   `slots × 38 − 2 + 6 + 74` de largura (3 slots → 192 → x 224…416). Centralização por flex (left/right 0) para a
   posição cair em px de arte inteiros — sem transform. */
.hud-bottom {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(4 * var(--px));
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: calc(6 * var(--px));
  pointer-events: none;
}
.hud-bottom > * { pointer-events: auto; }
.hud-abilities, .quick-use { display: flex; gap: calc(2 * var(--px)); }
/* A coluna da barra: o selo da corrida com build própria (`widgets/buildSeal.js › createRunSeal`, loadouts.md §8) logo acima
   dela, alinhado à esquerda; escondido, a coluna é só a barra (nada se move fora dessa corrida). Ela não recebe toque nos
   vãos (a barra e o selo, sim). */
.hud-bar-col { display: flex; flex-direction: column; align-items: flex-start; gap: calc(2 * var(--px)); pointer-events: none; }
.hud-bar-col > * { pointer-events: auto; }
.hud-run-seal { text-shadow: none; }
/* O selo mora em y 300…318, DENTRO da faixa das janelas da corrida: todas acabam entre y 300 e 310 (windowLayout.js, a regra
   do teto 312), e com a Mochila aberta 10 dos 18 px dele ficavam sob a borda dela — o selo saía cortado ao meio —, com
   Habilidades 8 (verificação integrada de 2026-10-02). Janela aberta na corrida = o selo sai de vista, sem mover a barra
   (`visibility`, não `display`); a Mochila (sob o trilho) e Habilidades (`#ab-run-seal`) mostram o mesmo selo, com o motivo no
   gesto. As janelas da corrida são filhas diretas de `#hud` (`windowManager.js`, a camada é o HUD). Preso por
   client/tests/ui/runSealWindows.test.js. */
#hud:has(> .window) .hud-run-seal { visibility: hidden; }
/* --- buildexp --- (prova da onda 2, 2026-10-03, 844×390) Com a build da Exploração o selo chegou à corrida que encontra o
   MERCADOR: com a vitrine aberta o cartão da subida desce para y 277 (a regra do `--- auto-avanco ---`, abaixo) e, com o
   "Ficar neste nível", vai até y 313 — por cima do selo (300…318), que ficava só com a borda do ícone à vista. Vitrine
   aberta = o selo sai de vista, como com janela aberta (docs/specs/loadouts.md §8). Preso por runSealWindows.test.js. */
#ui-root:has(#merchant-window:not(.hidden)) .hud-run-seal { visibility: hidden; }

.ability-slot, .quick-slot {
  position: relative;
  left: 0;
  width: calc(36 * var(--px));
  height: calc(36 * var(--px));
}
/* Filhos absolutos do botão medem a partir da caixa interna (dentro da borda de 4): −2 → área do ícone 32×32. */
.ability-icon {
  position: absolute;
  inset: calc(-2 * var(--px));
  display: grid;
  place-items: center;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  image-rendering: pixelated;
  font-size: var(--text-2);
  color: var(--c-text-dim);
  pointer-events: none;
}
.ability-icon.is-missing {
  background-image: repeating-conic-gradient(#ff00ff 0 25%, #1a001a 0 50%);
  background-size: calc(8 * var(--px)) calc(8 * var(--px));
  background-repeat: repeat;
}
.btn-ability:hover > .ability-icon { filter: brightness(1.15); }
.btn-ability:active > .ability-icon { top: calc(-1 * var(--px)); bottom: calc(-3 * var(--px)); }
.ability-slot.is-empty .ability-icon { opacity: 0.5; }
.ability-slot.is-empty > .btn-ability:hover > .ability-icon { opacity: 1; color: var(--c-gold); }
/* Sem poção: silhueta da poção do grupo. */
.quick-slot.is-empty .ability-icon { filter: grayscale(1) brightness(0.3); opacity: 0.7; }
.quick-slot.is-empty > .btn-ability { cursor: default; }

.ability-key {
  position: absolute;
  left: calc(-2 * var(--px));
  top: calc(-3 * var(--px));
  font-size: var(--text-1);
  line-height: 1;
  color: var(--c-text);
  text-shadow: var(--hud-outline);
  pointer-events: none;
}
.ability-cost, .quick-qty {
  position: absolute;
  right: calc(-2 * var(--px));
  bottom: calc(-3 * var(--px));
  font-size: var(--text-1);
  line-height: 1;
  color: #8fd0ff;
  text-shadow: var(--hud-outline);
  pointer-events: none;
}
.quick-qty { color: var(--c-text); }

/* Sem mana (claramente — tolerância de 1 ponto, abilityView.isNoMana): ícone apagado, custo em vermelho. */
.ability-slot.is-nomana .ability-cost { color: var(--c-danger); }
.ability-slot.is-nomana .ability-icon { filter: grayscale(1) brightness(0.7); }

/* Varredura de recarga: `--cd` = fração restante quantizada em 1/16 (o JS escreve no .ability-slot/.quick-slot). */
.ability-cd {
  display: none;
  position: absolute;
  inset: calc(-2 * var(--px));
  background: conic-gradient(transparent calc((1 - var(--cd, 0)) * 1turn), rgba(0, 0, 0, 0.7) 0);
  pointer-events: none;
}
.is-cooldown > .btn-ability > .ability-cd { display: block; }
.ability-cd-text {
  display: none;
  position: absolute;
  inset: calc(-2 * var(--px));
  place-items: center;
  font-size: var(--text-2);
  line-height: 1;
  color: var(--c-text);
  text-shadow: var(--hud-outline);
  pointer-events: none;
}
.is-cooldown > .btn-ability > .ability-cd-text { display: grid; }

/* Pedido manual em espera no server (≤ 500 ms): aro dourado. */
.ability-slot.is-queued > .btn-ability { outline: var(--px) solid var(--c-gold); outline-offset: calc(-2 * var(--px)); }

/* Recarga acabou: *pop* de 120 ms em 2 degraus + clarão. */
.ability-flash {
  display: none;
  position: absolute;
  inset: calc(-2 * var(--px));
  background: #fff;
  mix-blend-mode: screen;
  pointer-events: none;
}
.is-ready-pop > .btn-ability { outline: var(--px) solid var(--c-gold); outline-offset: 0; }
.is-ready-pop > .btn-ability > .ability-flash { display: block; animation: ability-pop 0.12s steps(2, jump-none) both; }
@keyframes ability-pop {
  from { opacity: 0.85; }
  to   { opacity: 0.25; }
}

/* *Deny*: tremor de 2 px por 150 ms (`left` e não margem: os vizinhos não andam). Sem frase, exceto na recusa do pedido
   manual (B32), onde o toast é o único retorno de quem tem `prefers-reduced-motion` ligado. */
.is-deny { animation: deny-shake 0.15s steps(3, jump-none); }
@keyframes deny-shake {
  0%   { left: calc(2 * var(--px)); }
  50%  { left: calc(-2 * var(--px)); }
  100% { left: 0; }
}

/* Herói morto / sem conexão. */
.is-disabled > .btn-ability > .ability-icon { filter: grayscale(1) brightness(0.45); }
.is-disabled > .btn-ability > .ability-cost,
.is-disabled > .btn-ability > .quick-qty,
.is-disabled > .btn-ability > .ability-key { color: var(--c-text-dim); }

/* Selo AUTO (ui/icons/ico_auto.png, 8×8): IRMÃO do botão (nada interativo dentro de <button>), área clicável 12×12 no
   canto superior direito. Aceso = AUTO ligado; cinza claro = ligado mas a chave geral está desligada; escuro = desligado. */
.ability-auto {
  position: absolute;
  right: calc(-2 * var(--px));
  top: calc(-2 * var(--px));
  width: calc(12 * var(--px));
  height: calc(12 * var(--px));
  padding: 0;
  border: 0;
  background: var(--ui-ico_auto) no-repeat center / calc(8 * var(--px)) calc(8 * var(--px));
  image-rendering: pixelated;
  filter: grayscale(1) brightness(0.45);
  cursor: pointer;
}
.is-auto > .ability-auto { filter: none; }
.is-auto.is-auto-off > .ability-auto { filter: grayscale(1) brightness(0.95); }
button.ability-auto:hover { filter: brightness(1.35); }
.ability-auto.is-pending { opacity: 0.5; } /* trava com motivo: `widgets/abilityBar.js › toggleAuto` */
.ability-auto.is-fixed { cursor: default; pointer-events: none; }
.ability-auto:focus-visible { outline: var(--px) solid var(--c-text); outline-offset: calc(-1 * var(--px)); }

/* --- pocao --- (ui-gameplay-habilidades.md §5.2) O botão de poção (`widgets/quickUse.js`, modelo `ui/potionView.js`) tem UM
   relógio: o rosto (a varredura `.ability-cd` acima, que trava) mostra a recarga de qualquer gole, da mão ou da automática
   (--- pocao-recarga ---, decisão do dono em 2026-10-05: sem o anel dourado). O selo diz se a automática pode beber: apagado
   (o cinza do AUTO de habilidade com a chave geral desligada) enquanto o rosto corre; ao reacender, um clarão de 140 ms
   (nenhum com `prefers-reduced-motion`). */
.quick-slot.is-auto-wait > .ability-auto { filter: grayscale(1) brightness(0.95); }
.quick-slot.is-auto-ready > .ability-auto { animation: auto-ready 0.14s steps(2, jump-none) both; }
@keyframes auto-ready {
  from { filter: brightness(2); }
  to   { filter: none; }
}
/* --- /pocao --- */

/* Tooltip da barra: moldura `tooltip` (nine-slice.css), 168 de largura, 4 px acima dos botões; nunca captura ponteiro. */
.ability-tip {
  position: absolute;
  bottom: calc(40 * var(--px));
  width: calc(168 * var(--px));
  z-index: 40;
  display: flex;
  flex-direction: column;
  gap: calc(2 * var(--px));
  pointer-events: none;
  text-align: left;
}
.ability-tip-head { display: flex; justify-content: space-between; gap: calc(4 * var(--px)); white-space: nowrap; }
/* Números em grade de 2 colunas (um por célula): alinhados, sem pontuação solta na quebra de linha. */
.ability-tip-stats { display: grid; grid-template-columns: 1fr 1fr; column-gap: calc(6 * var(--px)); }
.ability-tip-stats .ability-stat { white-space: nowrap; }
.ability-tip-stats .ability-stat.is-mod { grid-column: 1 / -1; color: #8fd0ff; }
/* Condição do slot e uma linha por primitiva de efeito (as 8 do pacote 17): quebram, ao contrário dos números. */
.ability-tip-cond, .ability-tip-eff { line-height: calc(9 * var(--px)); }
.ability-tip-eff.is-inner { padding-left: calc(5 * var(--px)); }
.ability-tip-hint { color: #8a8478; }

/* Botão da mochila (`#btn-bag`): ico_bag 16×16 + usadas/size; `is-pop` no bagArrive (cor da qualidade em --bag-flash). */
.hud-bag { position: relative; left: 0; gap: calc(3 * var(--px)); padding: 0 calc(3 * var(--px)) 0 calc(1 * var(--px)); }
.bag-icon {
  width: calc(16 * var(--px));
  height: calc(16 * var(--px));
  margin: calc(-2 * var(--px)) 0;
  background: var(--ui-ico_bag) no-repeat center / 100% 100%;
  image-rendering: pixelated;
}
.hud-actions-row > .btn { min-height: calc(20 * var(--px)); }
.hud-bag.is-nearly-full .bag-count { color: var(--c-gold); }
.hud-bag.is-full .bag-count { color: #a3231a; animation: bag-full-blink 0.8s steps(2) infinite; }
/* cheia: o botão NÃO esmaece (o piscar por opacidade deixava o "60/60" rosa sobre o cinza-claro do botão quase ilegível);
   só o número pisca entre dois vermelhos escuros, que contrastam com o miolo claro */
@keyframes bag-full-blink {
  from { color: #a3231a; }
  to   { color: #5e140e; }
}
@keyframes hud-blink {
  from { opacity: 1; }
  to   { opacity: 0.35; }
}
.hud-bag.is-pop { animation: bag-pop 0.2s steps(2, jump-none); }
.hud-bag.is-pop .bag-icon { animation: bag-icon-pop 0.2s steps(2, jump-none); }
@keyframes bag-pop {
  from { filter: brightness(1.6) drop-shadow(0 0 calc(2 * var(--px)) var(--bag-flash, var(--c-gold))); }
  to   { filter: brightness(1.2) drop-shadow(0 0 calc(1 * var(--px)) var(--bag-flash, var(--c-gold))); }
}
@keyframes bag-icon-pop {
  from { margin-top: calc(-5 * var(--px)); margin-bottom: calc(1 * var(--px)); }
  to   { margin-top: calc(-3 * var(--px)); margin-bottom: calc(-1 * var(--px)); }
}
.hud-bag.is-overflow { animation: deny-shake 0.15s steps(3, jump-none); }
/* --- durability --- a MESMA marca do slot, no botão da Mochila da corrida: acesa enquanto algum EQUIPADO estiver desgastado
   (âmbar) ou quebrado (vermelho). 9×9 entre o ícone e o número, sem texto: o "12/60" continua sendo o das células. */
.bag-dur { width: calc(9 * var(--px)); height: calc(9 * var(--px)); background: none no-repeat 0 0 / 100% 100%; image-rendering: pixelated; display: none; }
.hud-bag.is-dur-worn .bag-dur { display: inline-block; background-image: var(--ui-ico_dur_worn, none); }
.hud-bag.is-dur-broken .bag-dur { display: inline-block; background-image: var(--ui-ico_dur_broken, none); }
/* --- /durability --- */

/* Efeitos ativos (statusChips): faixa sob as barras; cada efeito = caixa 18×18 (ícone 16 = redução inteira 2:1 do
   32×32) com o tempo restante EMBAIXO (sobre o ícone ele tapava metade do frasco). O chip tem a largura do rótulo MAIS
   LONGO, "14:43" (5 × 4,8 = 24 de arte na fonte de 8, avanço 0,6 em) + folga: passo 28 + 2 → 4 por linha no miolo de
   124 (118); do 5º em diante quebra para a 2ª linha (máx. 8 = 2 linhas). Com 22 o rótulo vazava 1 de cada lado e dois
   elixires liam "14:4314:51" (revisão de 2026-10-06: com o automático sempre, 2–5 chips de elixir são o caso normal). */
.status-chips {
  display: flex;
  flex-wrap: wrap;
  gap: calc(2 * var(--px));
  margin-top: calc(2 * var(--px));
}
.status-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(1 * var(--px));
  width: calc(28 * var(--px));
}
.status-chip:focus-visible { outline: var(--px) solid var(--c-gold); }
.status-chip-box {
  position: relative;
  width: calc(18 * var(--px));
  height: calc(18 * var(--px));
  background: #0a080e;
  box-shadow: inset 0 0 0 var(--px) #4a4458;
  image-rendering: pixelated;
}
.status-chip-icon {
  position: absolute;
  left: calc(1 * var(--px));
  top: calc(1 * var(--px));
  width: calc(16 * var(--px));
  height: calc(16 * var(--px));
  background-repeat: no-repeat;
  background-size: 100% 100%;
  image-rendering: pixelated;
}
.status-chip-icon.is-missing {
  background-image: repeating-conic-gradient(#ff00ff 0 25%, #1a001a 0 50%);
  background-size: calc(8 * var(--px)) calc(8 * var(--px));
  background-repeat: repeat;
}
.status-chip-time {
  font-size: var(--text-1);
  line-height: calc(8 * var(--px));
  text-align: center;
  color: var(--c-text);
  text-shadow: var(--px) var(--px) 0 #000;
  white-space: nowrap;
  pointer-events: none;
}
/* --- torre-chefes --- o número de acúmulos, no canto inferior direito do chip; vazio com 1 acúmulo. */
.status-chip-stacks {
  position: absolute;
  right: 0;
  bottom: 0;
  line-height: calc(6 * var(--px));
  color: var(--c-gold);
  text-shadow: var(--px) var(--px) 0 #000;
  pointer-events: none;
}
.status-chip.is-new .status-chip-box { animation: chip-in 0.2s steps(2, jump-none); }
@keyframes chip-in {
  from { filter: brightness(2.2); box-shadow: inset 0 0 0 var(--px) var(--c-gold); }
  to   { filter: brightness(1.4); box-shadow: inset 0 0 0 var(--px) var(--c-gold); }
}
.status-chip.is-ending .status-chip-time { color: var(--c-danger); }
.status-chip.is-ending .status-chip-icon { animation: hud-blink 0.5s steps(2) infinite; }

@media (prefers-reduced-motion: reduce) {
  .is-deny, .hud-bag.is-pop, .hud-bag.is-pop .bag-icon, .hud-bag.is-overflow, .status-chip.is-new .status-chip-box, .status-chip.is-ending .status-chip-icon, .hud-badge,
  /* (C31) sem estalo, mas a ESCADA fica: cor e tamanho do marco não são animação */
  .hud-combo.is-active, .hud-combo.is-active.is-milestone,
  .is-ready-pop > .btn-ability > .ability-flash,
  /* --- pocao --- o selo da poção reacende sem clarão */
  .quick-slot.is-auto-ready > .ability-auto { animation: none; }
  .hud-gain { transition: none; }
}

/* Aviso de conexão / de dados (reconectando, desconectado, "Os dados do jogo foram atualizados"). Nasceu no topo ao
   centro, e ali caía em cima do rastreador de missões e da faixa de encontro (corrida) e da 2.ª linha da faixa do
   personagem (lobby). Uma linha, fundo opaco, acima das janelas (z 55) e fora da faixa x 200…440 do topo:
   - lobby (`.screen-lobby > .hud-net` e o aviso global de ui.js): no canto inferior direito, na linha da barra de modos,
     por cima do selo dos conectados (`#lobby-online.is-corner`, x … 636, y 338…354 — o canto voltou a ele com a carteira de duas
     moedas, docs/specs/focus.md §8) — número que, sem conexão, está velho de qualquer forma. Centrado
     ele caía sobre o título e o × das janelas que nascem em y 46; em (4, 47) apagava o título de toda janela do lobby
     (Mochila, Clã, Banqueiro… — B51: a rodada 1 da avaliação de UX desceu o aviso e as janelas continuaram em 46).
     Dentro da faixa do personagem ele atravessava a moldura dela, cuja largura segue o texto. Ali embaixo a barra de
     modos acaba em x 424 e a pilha de toasts termina em y 332: nada é coberto;
   - corrida (`#hud > .hud-net` e o aviso global): x 4, logo abaixo do painel superior esquerdo — que cresce com as
     barras de efeito (1 fileira até 5 efeitos, 2 do 6.º em diante), daí os `:has`. O aviso global traz `top` inline
     (ui.js), por isso o `!important` só nele. */
.hud-net {
  position: absolute;
  z-index: 55;
  top: calc(48 * var(--px));
  left: 50%;
  transform: translateX(-50%);
  max-width: calc(300 * var(--px));
  padding: calc(1 * var(--px)) calc(3 * var(--px));
  line-height: calc(10 * var(--px));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  background: #0e0c14;
  box-shadow: 0 0 0 var(--px) #4a4458;
  color: var(--c-danger);
}
#screen-lobby > .hud-net,
#ui-root:has(#screen-lobby) #ui-overlay > .hud-net {
  /* ancorado pelo PÉ (y 352, a linha da barra de modos) e não pelo topo: com duas linhas a faixa cresce para CIMA,
     dentro do palco — presa em `top: 338` a 2.ª linha caía fora dos 360 px, na tarja preta do letterbox. */
  top: auto !important;
  bottom: calc(8 * var(--px));
  left: auto;
  right: calc(4 * var(--px));
  transform: none;
  max-width: calc(200 * var(--px));
  /* `nowrap` + reticências herdados cortavam 3 dos 7 avisos ("Sua conta entrou em outro lugar. Esta j…") — e um aviso
     que não se lê inteiro não é aviso. Duas linhas, como a regra da corrida logo abaixo já faz; a faixa sobe em vez
     de crescer para o lado, e a 2.ª linha cai em y 328, acima da barra de modos (avaliação de UX, rodada 2). */
  white-space: normal;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}
#hud > .hud-net,
#ui-root:has(#hud) #ui-overlay > .hud-net {
  --net-top: calc(74 * var(--px));
  left: calc(4 * var(--px));
  transform: none;
  /* 92 (x 4…96), a coluna dos toasts: com 136 o aviso passava de x 100 e cobria o título das janelas da corrida
     ("Configurações", clã, amigos nascem em x 100). Frase longa quebra em até 2 linhas em vez de sumir na reticência. */
  max-width: calc(92 * var(--px));
  white-space: normal;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  top: var(--net-top) !important;
}
#hud > .hud-net.hidden, #ui-root:has(#hud) #ui-overlay > .hud-net.hidden { display: none; }
#ui-root:has(#hud .status-chips:not(.hidden) > .status-chip) #hud > .hud-net,
#ui-root:has(#hud .status-chips:not(.hidden) > .status-chip) #ui-overlay > .hud-net { --net-top: calc(105 * var(--px)); }
/* a 2ª linha de chips começa no 5º (4 por linha: `.status-chip`) */
#ui-root:has(#hud .status-chips:not(.hidden) > .status-chip:nth-child(5)) #hud > .hud-net,
#ui-root:has(#hud .status-chips:not(.hidden) > .status-chip:nth-child(5)) #ui-overlay > .hud-net { --net-top: calc(134 * var(--px)); }

/* Toast na run: a pilha global (windows.css: canto inferior direito) nascia em cima de "Auto: ligado" e "Sair"; depois
   foi para o centro, acima da barra de habilidades — e ali três avisos do bestiário empilhavam em cima do herói e
   cobriam o rodapé das janelas ("Restaurar padrão desta aba" das Configurações). Agora ela desce do canto superior
   esquerdo, logo abaixo do painel do personagem (mesma âncora do aviso de conexão, 24 px abaixo dele quando ele está
   aceso), numa coluna de 92 (x 4…96): as janelas da corrida começam em x ≥ 100 (Configurações, clã, amigos), então
   o aviso nunca cobre título, rótulo nem rodapé de janela, e o herói corre em x ≥ 150. Frase longa quebra em até
   3 linhas. z 90 como no lobby. */
/* Largura 160, não 92 (rodada 1): numa coluna de 92 px cada aviso quebrava em 2 a 8 linhas e quatro avisos viravam
   um bloco de 184 px de altura sobre o palco. A pilha CONTINUA no canto superior esquerdo, e não volta para o centro
   acima da barra de habilidades como o comentário do toast.js promete: lá ela cobria o herói e o rodapé das janelas,
   que é o defeito que a rodada 1 consertou. Em 160 a frase mais longa cabe em 2 linhas; a pilha é passageira e fica
   acima das janelas (z 90), então cruzar o canto delas por alguns segundos é o preço menor (rodada 2). */
.toast-stack.is-explore {
  --toast-top: calc(74 * var(--px));
  left: calc(4 * var(--px));
  right: auto;
  bottom: auto;
  top: var(--toast-top);
  max-width: calc(160 * var(--px));
  align-items: flex-start;
}
#ui-root:has(#hud .status-chips:not(.hidden) > .status-chip) .toast-stack.is-explore { --toast-top: calc(105 * var(--px)); }
#ui-root:has(#hud .status-chips:not(.hidden) > .status-chip:nth-child(5)) .toast-stack.is-explore { --toast-top: calc(134 * var(--px)); }
#ui-root:has(#hud > .hud-net:not(.hidden)) .toast-stack.is-explore,
#ui-root:has(#ui-overlay > .hud-net:not(.hidden)) .toast-stack.is-explore { top: calc(var(--toast-top) + 24 * var(--px)); } /* aviso de até 2 linhas (10 + 10 + 2 de respiro + 2) */

/* --- tower --- (01c-telas §3) Na Torre o combo desce para y 52, com a mesma regra da Masmorra: a barra de chefe
   ocupa y 4…21 a incursão inteira. */
.scene-tower .hud-combo { top: calc(64 * var(--px)); } /* 52 cruzava a 2.ª linha do rastreador de missões (41…59) */
/* --- /tower --- */

/* --- run-life --- (05-client-eventos §5.3) Aviso de ENCONTRO em andamento, na mesma faixa livre do topo que a barra
   de chefe usa em masmorra/torre (x 200…440, y 4…22). A barra esvazia por ANIMAÇÃO, com a duração que veio do
   servidor (`--dur`, calculada de `ticks ÷ tickRate`): o client não conta tique nenhum, e se o servidor calar ela
   chega a zero sozinha em vez de congelar cheia. */
/* Visto no E2E do pacote 14 (2026-09-22): na Exploração a faixa y 4…22 é do rastreador de missões (`quests.css
   .hud-quests`, duas linhas de 9 px) e os dois textos se sobrepunham. O encontro só existe na Exploração, então ele
   mora logo abaixo do rastreador, y 23…39, antes do `COMBO` (y 40). */
.hud-encounter {
  position: absolute;
  top: calc(23 * var(--px));
  left: 50%;
  width: calc(240 * var(--px));
  margin-left: calc(-120 * var(--px));
  height: calc(16 * var(--px));
  pointer-events: none;
  text-shadow: var(--px) var(--px) 0 #000;
}
.hud-encounter-text {
  height: calc(10 * var(--px));
  line-height: calc(10 * var(--px));
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  color: var(--c-gold);
}
.hud-encounter-bar {
  margin-top: var(--px);
  height: calc(4 * var(--px));
  background: rgba(0, 0, 0, 0.6);
  box-shadow: inset 0 0 0 var(--px) rgba(244, 240, 230, 0.28);
}
.hud-encounter-fill {
  height: 100%;
  width: 100%;
  background: var(--c-gold);
}
.hud-encounter-fill.is-draining { animation: encounter-drain var(--dur, 1s) linear forwards; }
@keyframes encounter-drain {
  from { width: 100%; }
  to   { width: 0%; }
}
/* --- /run-life --- */

/* --- run-life --- Vitrine do mercador ambulante (windows/merchant.js; estilo inline, daí os `!important`).
   (1) Com a vitrine aberta ela fica ACIMA das janelas (z 10+): a mochila compacta (x 390…632) cobria o 3.º cartão —
   nome, preço e "Comprar" sumiam — e clicar no mercador não o trazia para a frente. É um modal curto, que some sozinho.
   (2) Cartão em coluna com "Comprar" no pé: nome longo quebrando em 3 linhas desalinhava os botões (y 366 × 346). */
#merchant-window:not(.hidden) { z-index: 45 !important; }
#merchant-window .merchant-cards { align-items: stretch; }
#merchant-window .merchant-card { justify-content: flex-start !important; }
#merchant-window .merchant-name, #merchant-window .merchant-price { text-align: center; }
#merchant-window .merchant-card > .btn, #merchant-window .merchant-card > .merchant-sold { margin-top: auto; }
/* --- mercador --- (docs/specs/run-life.md §2.5) A PEÇA à venda (slot, nome e preço) é uma caixa com a largura do cartão: é o
   alvo do tooltip, que pousa AO LADO dela e nunca cobre o "Comprar" do próprio cartão (ancorado só no slot ele cortava o
   nome, o preço e a borda do botão). Toque longo fixa o tooltip: sem o balão de "copiar/abrir" do iOS e sem selecionar o
   nome. O aro de foco é o `:focus-visible` global (base.css). */
#merchant-window .merchant-item { align-self: stretch; display: flex; flex-direction: column; align-items: center; gap: calc(2 * var(--px)); -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }

/* --- auto-avanco --- (docs/specs/auto-advance.md) cartão da contagem, linha do painel e véu da troca. */
.hud-auto-advance {
  position: absolute;
  top: calc(58 * var(--px));
  left: 50%;
  /* --- auto-avanco --- (B50) 208 px lógicos deixavam 137 px CSS para uma frase que pede 202: TODA frase do cartão saía
     "Indo para o N… 4" e o cartão deixava de dizer para onde vai. 244 cabe na faixa livre do topo (x 144 a 536) e, com a
     frase podendo quebrar em duas linhas, a mais longa ("Indo para o Nv. 13 ao fim do combate…") entra inteira. */
  width: calc(244 * var(--px));
  margin-left: calc(-122 * var(--px));
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(4 * var(--px));
  padding: calc(2 * var(--px)) calc(4 * var(--px));
  pointer-events: auto;
  z-index: 40;
  text-shadow: var(--px) var(--px) 0 #000;
}
.hud-auto-advance-text { color: var(--c-gold); white-space: normal; overflow-wrap: break-word; line-height: 1.15; flex: 1 1 auto; min-width: 0; }
.hud-auto-advance-num { color: var(--c-gold); font-size: var(--text-2); line-height: 1; min-width: calc(10 * var(--px)); text-align: center; flex: 0 0 auto; }
#btn-auto-advance-stay { flex: 0 0 auto; }
/* Com a vitrine do mercador aberta (y 64…243, z 45) o cartão — que é justamente o "Nv. N depois do mercador" — ficaria embaixo dela:
   desce para depois dos avisos de loot (loot.css: 247 e 261), no molde deles. */
#ui-root:has(#merchant-window:not(.hidden)) .hud-auto-advance { top: calc(277 * var(--px)); }
.hud-auto-advance-line { display: flex; flex-direction: column; align-items: flex-end; gap: var(--px); margin-top: calc(2 * var(--px)); }
/* O SELO de estado da subida (G2; `.hud-seal` de screens.css dá a moldura de 10 px e a cor `is-lock`/`text-dim`). Pedido do
   dono (2026-10-01): a linha não tem mais o botão "Retomar subida" — o que segura a subida é trava do servidor, e ela aparece
   aqui com o motivo no gesto. A pista (`.has-more`) não pode ser o `border-bottom` cinza de base.css: cairia em cima da
   moldura (a regra de `.create-seal`, screens.css) — a moldura é que vira pontilhada embaixo, na cor do selo. */
.hud-auto-advance-seal { white-space: nowrap; position: relative; }
#ui-root .hud-auto-advance-seal[data-hint].has-more { border-bottom: var(--px) dotted currentColor; }
/* O cadeado da série (`ico_lock`, 8×8 a 1×, o do `[cadeado] Nv 10` de reqSeal.js): "ainda trancado" na fronteira (apagado) e
   "a subida parou" na faixa Mortal (perigo). O `▲` fica só para quando a subida VEM (ux-casos §30). */
.hud-auto-advance-lock { flex: none; width: calc(8 * var(--px)); height: calc(8 * var(--px)); background: var(--ui-ico_lock, none) center / 100% 100% no-repeat; image-rendering: pixelated; }
.hud-auto-advance-lock.hidden { display: none; }
/* O ALVO DE TOQUE do selo (revisão de 2026-10-01): ele tem 10 px de arte, e no celular deitado (844×390 a DPR 3: k 3, 1 px de
   CSS por px de arte) eram 10 px de dedo para chegar ao motivo e ao conselho, que só moram no gesto. A área invisível estende o
   alvo para a esquerda (o vão vazio da última fila do painel) e para baixo — nunca para cima, onde mora o interruptor. */
.hud-auto-advance-seal::after { content: ''; position: absolute; top: 0; right: calc(-4 * var(--px)); bottom: calc(-6 * var(--px)); left: calc(-48 * var(--px)); }
/* O INTERRUPTOR "Subir sozinho" (seletor e HUD; widgets/autoAdvanceHud.js › autoSwitchButton): a peça `toggle` da série
   (ui/toggles/toggle.<off|on>.png, 16×10 — a do AUTO das habilidades, do "Usar automaticamente" e do Filtro de loot) à direita
   do rótulo; `aria-checked` decide a figura. Pedido do dono (2026-10-01): ligado e desligado eram o MESMO botão cinza, e só a
   última palavra ("sim"/"não") mudava. */
.aa-switch {
  flex: none;
  width: calc(16 * var(--px));
  height: calc(10 * var(--px));
  margin-left: calc(2 * var(--px));
  background: var(--ui-toggle-off, linear-gradient(90deg, #d8c8a0 0 40%, #2a2118 40% 100%)) no-repeat;
  background-size: 100% 100%;
  image-rendering: pixelated;
}
.aa-switch-btn[aria-checked="true"] > .aa-switch { background-image: var(--ui-toggle-on, linear-gradient(90deg, #2a2118 0 60%, #e0b040 60% 100%)); }
/* O recibo do "Ficar neste nível" (N6): o interruptor que acabou de desligar ganha um contorno de ouro por STAY_FLASH_MS —
   o cartão some do meio da tela e o olho é levado ao lugar onde a opção mudou. Estático: nada pisca (prefers-reduced-motion). */
#btn-auto-advance-toggle.is-flash { outline: var(--px) solid var(--c-gold); outline-offset: var(--px); }
/* --- vip --- O INTERRUPTOR 2× (widgets/vipSpeedHud.js; docs/specs/shop.md §11.10), a primeira peça da linha de baixo do canto:
   [2× ⊂●⊃][Auto ⊂●⊃][Sair]. A peça é a do "Subir sozinho" (`.aa-switch` acima); aqui só o que o 2× tem de seu.
   (1) O [cadeado] (`ico_lock`, 8×8 a 1×, o mesmo do selo da subida) na FRENTE do rótulo quando o 2× não vale: nunca foi VIP (com a
       vitrine), venceu, ou o modo não está na lista. O motivo mora no gesto (`setButtonReason`).
   (2) `.is-paused`: LIGADO, mas a corrida está a 1× enquanto o mercador ou a contagem da subida está na tela. A figura continua a
       "ligada" (a escolha não mudou) e fica apagada pela metade — estático, nada pisca (prefers-reduced-motion). */
.vip-speed-lock { flex: none; width: calc(8 * var(--px)); height: calc(8 * var(--px)); background: var(--ui-ico_lock, none) center / 100% 100% no-repeat; image-rendering: pixelated; }
#btn-vip-speed.is-paused > .aa-switch { opacity: 0.45; }
/* --- /vip --- */
.hud-level-veil {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(10, 8, 14, 0.55);
  pointer-events: none;
  z-index: 60;
  /* a DURAÇÃO vem do dado (autoAdvance.transitionVeilMs), aplicada inline pelo widget; aqui só o resto */
  animation-name: level-veil;
  animation-timing-function: ease-out;
  animation-fill-mode: both;
}
.hud-level-veil-text { color: var(--c-gold); font-size: calc(16 * var(--px)); text-shadow: var(--px) var(--px) 0 #000; }
@keyframes level-veil { from { opacity: 1; } to { opacity: 0; } }
.hud-auto-advance.hidden, .hud-auto-advance-line.hidden, .hud-level-veil.hidden, .hud-auto-advance-seal.hidden, .hud-auto-advance-num.hidden { display: none; }
/* --- F3 queda --- (docs/specs/auto-advance.md §4.1; widgets/fallCard.js) O CARTÃO DA QUEDA: "Levanta no Nv 29 em" + o dígito
   grande, na MESMA faixa do topo do cartão da contagem (y 58, no meio; os avisos de loot descem para y 106 enquanto ele está no ar,
   `reservesAutoAdvanceBand`). Os dois nunca dividem a tela: na espera a subida está travada (`blocked/fell` ou `band`). Sem botão,
   então mais estreito (168 cabe "Levanta no Nv 100 em" + "10") e sem alvo de toque: o toque passa para a cena (`pointer-events`).
   A frase e o dígito são os do cartão irmão (ouro, sombra de 1 px, `--text-2` no dígito): uma figura, uma ideia. */
.hud-fall-card {
  position: absolute;
  top: calc(58 * var(--px));
  left: 50%;
  width: calc(168 * var(--px));
  margin-left: calc(-84 * var(--px));
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(4 * var(--px));
  padding: calc(2 * var(--px)) calc(4 * var(--px));
  pointer-events: none;
  z-index: 40;
  text-shadow: var(--px) var(--px) 0 #000;
}
.hud-fall-text { color: var(--c-gold); white-space: nowrap; line-height: 1.15; }
.hud-fall-num { color: var(--c-gold); font-size: var(--text-2); line-height: 1; min-width: calc(10 * var(--px)); text-align: center; flex: 0 0 auto; }
/* --- F3 queda --- (revisão F3-ux-n2, medida no servidor real: a Mochila aberta na corrida e o cartão da queda por cima das luvas e
   da 1.ª fileira) Janela aberta na corrida = os DOIS cartões da faixa do topo saem de vista, no molde do selo da corrida
   (`.hud-run-seal`, acima): por cima da janela (z 40 > 10) eles escondiam controles, e o da queda, sem alvo de toque, deixava o
   toque cair na célula escondida embaixo (a poção de mana gasta com a mana cheia). `visibility`, não `display`: a faixa dos avisos
   de loot (`reservesAutoAdvanceBand`) não muda. As janelas da corrida são filhas diretas de `#hud`; a vitrine do mercador não é
   `.window` (o cartão da subida segue à vista abaixo dela). Preso por client/tests/ui/fallView.test.js. */
#hud:has(> .window) .hud-fall-card, #hud:has(> .window) .hud-auto-advance { visibility: hidden; }

/* --- masmorra-continuar --- (docs/specs/dungeons.md §12.10) O "Continuar sozinho" no HUD da incursão (widgets/autoContinueHud.js).
   A linha, o selo, o cadeado e o alvo de toque são os do "Subir sozinho" acima (`.hud-auto-advance-line`, `-seal`, `-lock`,
   `.aa-switch`); aqui só o que a masmorra tem de seu.
   (1) O RÓTULO EM DUAS LINHAS — "Continuar" / "sozinho", o mesmo texto e o mesmo nome acessível. Em uma linha o botão teria
   117,6 px (17 caracteres de 4,8 + 16 de moldura e respiro + 2 + 2 + a peça de 16) e o painel 129,6, com a borda esquerda em
   x 506: dentro da faixa que as janelas da corrida usam até x 514 (ui/windows/windowLayout.js), e o painel fica ACIMA delas
   (z 12) — cobriria a borda e o × da Mochila. Com o rótulo em 44 ("Continuar" tem 43,2) o botão fica com 80 e cabe na
   largura mínima do painel (96, borda em x 540); o que ainda poderia alargá-lo é uma linha de números mais longa, e a mais
   larga que o painel escreve na masmorra deixa a borda acima de x 518. Encostado à direita: as duas linhas terminam juntas,
   coladas à peça. */
#btn-auto-continue-toggle > span:first-child { white-space: normal; max-width: calc(44 * var(--px)); text-align: right; }
/* (1-bis) O ALVO DE TOQUE DO SELO não sai do painel. O do "Subir sozinho" estende 48 px para a esquerda do PRÓPRIO selo, e um
   selo largo ("Grau 10 Mortal", 83 px) levaria a área invisível 41 px para fora do painel — por cima do × das janelas da
   corrida, que vão até x 514 e ficam ABAIXO do painel. Aqui o alvo é a fila do selo dentro da linha (da borda esquerda da linha
   até 4 px depois dele) e os mesmos 6 px para baixo; nunca para cima, onde mora o interruptor. */
#hud-auto-continue-line { position: relative; }
#hud-auto-continue-seal { position: static; }
#hud-auto-continue-seal::after { top: auto; left: 0; height: calc(16 * var(--px)); }
/* (2) O CARTÃO DA TROCA — "Grau 3 vencido" (pequeno) sobre "Grau 4" (grande): o véu do "Subir sozinho" com duas linhas. Nasce
   CHEIO (cobre o corte da arena, que troca no mesmo quadro), fica e some no fim. A DURAÇÃO vem do dado
   (dungeonConfig.autoContinue.veilMs), aplicada inline pelo widget. z 48: acima das janelas e ABAIXO do banner de loot (z 49) —
   o loot do chefe que acabou de cair é notícia maior que a troca. */
.hud-auto-continue-veil {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(3 * var(--px));
  background: rgba(10, 8, 14, 0.55);
  pointer-events: none;
  z-index: 48;
  text-shadow: var(--px) var(--px) 0 #000;
  animation-name: continue-veil;
  animation-timing-function: ease-out;
  animation-fill-mode: both;
}
.hud-auto-continue-veil-done { color: var(--c-text); line-height: 1; }
.hud-auto-continue-veil-next { color: var(--c-gold); font-size: calc(16 * var(--px)); line-height: 1; }
@keyframes continue-veil { 0%, 65% { opacity: 1; } 100% { opacity: 0; } }
/* `prefers-reduced-motion`: sem cartão — o toast do trecho ("Grau 3 vencido: +EXP · +G · abates") é o recibo. O widget já não o
   mostra; isto é a rede para a preferência que muda com o cartão no ar. */
@media (prefers-reduced-motion: reduce) {
  .hud-auto-continue-veil { display: none; }
}

/* --- auto-avanco --- (C2) FAIXA RESERVADA AO CARTÃO. O cartão ocupa y 58…102 (painel 8 + respiro 2 + o botão
   [Ficar neste nível] de 24 + 2 + 8) no meio do topo, e é a única coisa que diz por que a subida parou e como ficar
   neste nível. O banner de loot nasce em y 72 com z 49 — acima do cartão (z 40) — e a pilha de cartões divide a mesma
   faixa: com a mochila cheia (que é quando os dois aparecem) o jogador via "Perdido: sem espaço" por cima do motivo.
   Enquanto o cartão está no ar os dois descem para y 106; a classe vem de widgets/lootToast.js
   (`reservesAutoAdvanceBand`), porque o CSS não sabe se o cartão está `hidden` — e o número é o mesmo do JS
   (AUTO_ADVANCE_BAND_TOP_PX), provado em client/tests/ui/hudAutoAdvanceBand.test.js. */
.loot-layer.is-auto-advance .loot-toasts,
.loot-layer.is-auto-advance .loot-banner { top: calc(106 * var(--px)); }

/* (C9) VÉU "Entrando…". Entre o `explore.enter.ok`/`arena.joined` e o primeiro `arena.tick` o slice `run` ainda não
   tem vida nem mana: o HUD nascia "Nv. 0 · Exploração 1", "0 / 0" e "EXP 0 / 0" sobre a praça do lobby escurecida.
   Enquanto isso os dois painéis de leitura ficam escondidos e o véu cobre o palco — por no máximo ENTER_VEIL_MS
   (500 ms, screens/explorationHud.js): se o primeiro tique não vier, o HUD aparece mesmo assim (e já nasce com o
   nível e a EXP do personagem, herdados no `applyArenaJoin`). Acima do véu da troca de nível (z 60): a entrada vem
   antes dele. */
.hud.is-entering .hud-top-left,
.hud.is-entering .hud-top-right { visibility: hidden; }
.hud-enter-veil {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #0a080e;
  pointer-events: none;
  z-index: 70;
}
.hud-enter-veil-text { color: var(--c-gold); font-size: var(--text-2); text-shadow: var(--px) var(--px) 0 #000; }
.hud-enter-veil.hidden { display: none; }
