/* tower.css — modo Torre (docs/specs/tower.md): a janela da Torre (`ui/windows/tower.js`).
   O HUD da incursão reusa `.hud-boss` de dungeon.css; o que é só da Torre no HUD mora em hud.css sob `.scene-tower` (o
   combo) e no fim deste arquivo (o corpo do chefe no alto do bloco, a conjuração e a fase).
   Medidas em px de arte, sempre calc(N * var(--px)); posição sempre left/top, nunca transform (ui-gameplay.md §0.1). */

/* ---- a janela: painel 420 × 258 em (110, 46) — a mesma caixa do seletor de masmorra -------------------------------
   Área útil x 116…524, y 62…298 (o título entra 4 px na borda de cima e as colunas 2 px nas laterais). */
.tw-panel {
  position: absolute;
  left: calc(110 * var(--px));
  top: calc(46 * var(--px));
  width: calc(420 * var(--px));
  height: calc(258 * var(--px));
  /* camada dos seletores de modo (screens.css): acima das placas de NPC, ABAIXO das janelas (z 10+) — em 20 a Torre
     escondia a janela de Habilidades que o próprio "Ajustar a barra" abre */
  z-index: 9;
  pointer-events: auto;
}
.tw-panel > .window-title {
  height: calc(12 * var(--px));
  margin: calc(-4 * var(--px)) calc(-2 * var(--px)) 0;
  padding: 0 calc(2 * var(--px));
  cursor: default;
}
.tw-cols {
  position: relative;
  display: flex;
  gap: calc(10 * var(--px));
  height: calc(236 * var(--px));
  margin: 0 calc(-2 * var(--px));
}
/* Divisória vertical de 1 px em x 266, de y 62 a y 282. */
.tw-cols::after {
  content: '';
  position: absolute;
  left: calc(150 * var(--px));
  top: 0;
  width: var(--px);
  height: calc(220 * var(--px));
  background: rgba(244, 240, 230, 0.16);
  pointer-events: none;
}

/* ---- coluna esquerda: a escada, x 116…262, dez linhas de 22 px (andar 10 em cima) --------------------------------- */
.tw-list {
  width: calc(146 * var(--px));
  flex: none;
  display: flex;
  flex-direction: column;
}
.tw-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: calc(4 * var(--px));
  height: calc(22 * var(--px));
  padding: 0 calc(2 * var(--px));
  background: none;
  border: var(--px) solid transparent;
  text-align: left;
  color: var(--c-text);
  cursor: pointer;
}
/* B143: o degrau trancado deixou de ser `:disabled` (para continuar alcançável pelo teclado), então quem tira o
   realce de "clicável" agora é o `[aria-disabled]`. O `:focus` FICA: é o foco que dispara a dica com o motivo. */
.tw-row:hover:not(:disabled):not([aria-disabled='true']), .tw-row:focus { background: rgba(255, 255, 255, 0.12); outline: none; }
.tw-row.is-selected { background: rgba(224, 176, 64, 0.22); }
/* vencido: moldura dourada + marca de conferido 6 × 6 */
.tw-row.is-cleared { border-color: var(--c-gold); color: var(--c-gold); }
/* aberto: moldura normal */
.tw-row.is-open { border-color: var(--c-text-dim); }
/* bloqueado: cinza, cadeado 8 × 8, não clicável — e o nome vira "???" (quem escreve é tower.js) */
.tw-row.is-locked, .tw-row:disabled, .tw-row[aria-disabled='true'] { border-color: #4a4640; color: #7c766e; cursor: default; }
/* número do andar em x 118 (20 px), nome em x 142, selo em x 240 (20 px) */
.tw-row-n { width: calc(20 * var(--px)); flex: none; text-align: center; }
.tw-row-name {
  width: calc(94 * var(--px));
  flex: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tw-row-seal { width: calc(20 * var(--px)); height: calc(8 * var(--px)); margin-left: auto; flex: none; }
.tw-row-check {
  width: calc(6 * var(--px));
  height: calc(6 * var(--px));
  margin: 0 calc(7 * var(--px)) 0 auto;
  flex: none;
  background: var(--c-gold);
  clip-path: polygon(0 55%, 22% 33%, 40% 55%, 78% 0, 100% 22%, 40% 100%);
}
/* Cadeado 8 × 8 desenhado em CSS (o mesmo da masmorra): corpo cheio com o arco por cima. */
.tw-row-lock {
  position: relative;
  width: calc(8 * var(--px));
  height: calc(8 * var(--px));
  margin: 0 calc(6 * var(--px)) 0 auto;
  flex: none;
  background: #7c766e;
  box-shadow: 0 calc(-3 * var(--px)) 0 calc(-1 * var(--px)) #7c766e, inset 0 0 0 var(--px) rgba(0, 0, 0, 0.55);
}

/* ---- coluna direita: o andar selecionado, x 272…524 (252 de largura), faixas medidas no §2 ------------------------- */
.tw-side {
  position: relative;
  width: calc(252 * var(--px));
  flex: none;
}
.tw-side > * { position: absolute; left: 0; right: 0; }
/* --- chefe-na-tela --- A coluna direita virou RETRATO + ficha curta. Faixas medidas (a coluna tem 236 px, os
   mesmos de `.tw-cols`):
     0…12    nome do chefe (a descrição virou dica — `.has-more`)
     14…142  o chefe, 128 × 128, à esquerda, com a etiqueta do tipo de dano por cima; a ficha de 120 px à direita
     146…176 o kit (até três ativas) · 178 a régua · 181…209 o conselho · 212…232 as marcas e os botões
   A caixa do chefe é 128 porque as grades da Torre são 96 (andares 1–9) e 128 (O Selo): é a única em que as duas
   aparecem em 1:1. Tudo o que descia daqui para baixo subiu junto — nada passa de 236. */
.tw-name   { top: 0;                     height: calc(12 * var(--px)); font-size: var(--text-2); line-height: calc(12 * var(--px)); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.tw-boss   { top: calc(14 * var(--px));  left: 0; right: auto; width: calc(128 * var(--px)); height: calc(128 * var(--px)); display: flex; align-items: center; justify-content: center; overflow: hidden; background: rgba(0, 0, 0, 0.45); box-shadow: inset 0 0 0 var(--px) rgba(244, 240, 230, 0.16); }
.tw-boss-art { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; }
/* O tipo de dano é a decisão de EQUIPAMENTO do andar (D9): continua em destaque, agora como etiqueta sobre o
   retrato — uma palavra tingida no lugar de "Dano do chefe: mágico". A frase inteira está na dica. */
.tw-damage { position: absolute; left: 0; right: auto; top: 0; height: calc(10 * var(--px)); line-height: calc(10 * var(--px)); padding: 0 calc(2 * var(--px)); background: rgba(0, 0, 0, 0.72); overflow: hidden; white-space: nowrap; color: var(--c-gold); }
.tw-damage.is-magical { color: #8fb8ff; }
.tw-damage:empty { display: none; }

/* A ficha: 120 px à direita do retrato. */
.tw-facts  { top: calc(14 * var(--px));  left: calc(132 * var(--px)); right: 0; height: calc(128 * var(--px)); display: flex; flex-direction: column; gap: calc(4 * var(--px)); }
.tw-facts > * { position: static; }
.tw-meta   { height: calc(10 * var(--px)); line-height: calc(10 * var(--px)); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
/* Sincronia ligada (o chefe sobe para o nível do jogador): a meta curta não caberia dizendo isso, então o que
   avisa é a COR — e a frase inteira continua na dica. */
.tw-meta.is-synced { color: var(--c-gold); }
/* A faixa e o Potencial recomendado do andar (§2.1) — as duas linhas que `renderBand` de fato escreve. */
.tw-sheet  { height: calc(22 * var(--px)); line-height: calc(11 * var(--px)); overflow: hidden; }
.tw-power { display: flex; align-items: center; gap: calc(2 * var(--px)); white-space: nowrap; overflow: hidden; }
.tw-power-ico { width: calc(8 * var(--px)); height: calc(8 * var(--px)); flex: none; background: var(--ui-ico_power, none) center / contain no-repeat; image-rendering: pixelated; }
.tw-power-v { overflow: hidden; text-overflow: ellipsis; }
/* Marcas de fase numa barra de vida: "35 % e 25 %" viram duas posições. A barra é a vida CHEIA do chefe. */
.tw-phases { height: calc(8 * var(--px)); display: flex; align-items: center; }
.tw-phases:empty { display: none; }
/* A trilha é PREENCHIDA com o vermelho de vida, e não um contorno vazio: logo acima dela está o par de Potencial
   ("353K / 1,73M") e uma barra vazia ali embaixo era lida como o MEDIDOR daquele par — um "você está em 20 % do
   Potencial pedido" que ninguém escreveu. Cheia e vermelha, ela diz "vida do chefe" antes de qualquer palavra, e as
   marcas douradas passam a ser posições nessa vida. */
.tw-phases-track { position: relative; flex: 1; height: calc(4 * var(--px)); background: var(--c-danger); box-shadow: inset 0 0 0 var(--px) rgba(0, 0, 0, 0.55); }
.tw-phase-mark { position: absolute; top: calc(-2 * var(--px)); width: var(--px); height: calc(8 * var(--px)); background: var(--c-gold); }

.tw-rule   { top: calc(178 * var(--px)); height: var(--px); background: rgba(244, 240, 230, 0.16); }
/* O aviso da barra (§2.2) e a linha de resposta. */
.tw-advice { top: calc(181 * var(--px)); height: calc(28 * var(--px)); }
/* B87: com `overflow: hidden` a frase da mecânica nova parava no meio ("Ponha" e acabou) em 4 dos 10 andares.
   Quem rola e avisa é `.scroll-fade` (base.css); aqui fica só a faixa. */
.tw-advice-text { height: calc(28 * var(--px)); line-height: calc(9 * var(--px)); --scroll-fade-pad: 0px; }
.tw-advice-text.is-ready { color: var(--c-ok); }
/* O VEREDITO da barra (`Barra pronta` · `Corte Amplo não dispara`): estado curto na tela, frase inteira no gesto.
   Era `textContent` direto no painel, sem elemento próprio — e por isso sem dica, sem pista e sem `aria-label`. */
.tw-verdict { display: flex; align-items: flex-start; }
.tw-verdict-text { min-width: 0; }
.tw-advice > .tw-fix {
  position: absolute;
  right: 0;
  top: calc(4 * var(--px));
  width: calc(100 * var(--px));
  height: calc(16 * var(--px));
  justify-content: center;
}
/* A linha de RESPOSTA — a única que não virou ícone, porque um escudo não ensina "= 40 tiques". Verde quando a
   barra já responde; vermelha, com marca, quando não responde (era um aviso separado de 96 caracteres). */
/* `white-space: normal` e `align-items: flex-start`: a frase tem 52 caracteres contra os 52 que a coluna cabe, e
   com um número de três dígitos ela passa. Cortada, o que se perde é o FIM — o número. Quebrando, ela ocupa duas
   linhas e o `.scroll-fade` do `.tw-advice-text` avisa quando precisa rolar (foi o conserto do B87). */
.tw-answer { display: flex; align-items: flex-start; gap: calc(3 * var(--px)); color: var(--c-ok); white-space: normal; }
.tw-answer.is-danger { color: var(--c-danger); }
.tw-answer-text { min-width: 0; }
.tw-answer-mark { width: calc(8 * var(--px)); height: calc(8 * var(--px)); flex: none; margin-top: var(--px); background: var(--c-danger); clip-path: polygon(50% 0, 100% 100%, 0 100%); }

.tw-actions{ top: calc(212 * var(--px)); height: calc(20 * var(--px)); display: flex; align-items: center; justify-content: flex-end; gap: calc(4 * var(--px)); }
/* O motivo visível da Torre fechada ("Abre na Exploração 10"): uma linha só. Quebrado em duas ele subia por cima
   da faixa das marcas e encostava no "Entrar" — e a faixa tem 20 px de altura. */
.tw-lock-note { flex: none; white-space: nowrap; }
/* --- enxugamento --- Os dois botões tinham 120 px FIXOS cada: 240 + gap num trilho de 252, e o que sobrava para
   `.tw-best` eram 4 px. Medido no navegador: `.tw-best` com 8 px de largura CSS para 95 px de conteúdo — a marca de
   conferido, o `×8` e o `01:43` estavam escritos e recortados, justo nos andares em que o jogador volta para bater o
   próprio tempo (§3 N6: prova de que a ação aconteceu). Agora o botão tem a largura do seu rótulo, com um piso para
   não virar alvo pequeno demais, e o recorde aparece. */
.tw-actions > .btn { width: auto; min-width: calc(56 * var(--px)); flex: none; padding: 0 calc(6 * var(--px)); justify-content: center; }
/* As marcas de "vencido" e o melhor tempo, à esquerda dos botões. */
.tw-best   { position: static; flex: 1; min-width: 0; display: flex; align-items: center; gap: calc(3 * var(--px)); height: calc(10 * var(--px)); line-height: calc(10 * var(--px)); overflow: hidden; white-space: nowrap; }
.tw-mark   { width: calc(8 * var(--px)); height: calc(8 * var(--px)); flex: none; background: var(--c-gold); clip-path: polygon(0 55%, 22% 33%, 40% 55%, 78% 0, 100% 22%, 40% 100%); }
.tw-mark-n { color: var(--c-gold); }
.tw-mark-time { color: var(--c-text-dim); }

/* Ícone do botão `Torre` da barra do lobby (`ico_tower`, art/src/ui/icons_tower.py); sem arte o botão fica sem ícone. */
.lobby-btn-icon.is-tower { background-image: var(--ui-ico_tower); }
/* --- torre-chefes / chefe-na-tela --- O KIT do chefe (y 146…179), agora LARGURA INTEIRA e abaixo do retrato: com
   o retrato ocupando 128 px à esquerda, uma coluna de 120 cortava o nome da habilidade em três letras. Cada linha
   é ÍCONE + nome + tempo + cadeado; a frase "não dá para interromper" virou o cadeado. Rola quando o chefe tem
   três ativas (3 × 11 = 33, que é exatamente a altura da caixa). */
.tw-kit {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(146 * var(--px));
  height: calc(30 * var(--px));
  overflow-y: auto;
  line-height: calc(10 * var(--px));
  /* a barra PADRÃO do navegador come 15 px CSS = 7,5 px de arte da largura útil; `thin` é o que o resto da UI já
     usa (`abilities.css`, `auction.css`) e o gutter de 1 px impede que o cadeado encoste nela */
  scrollbar-width: thin;
  scrollbar-color: #575273 transparent;
  padding-right: calc(1 * var(--px));
}
.tw-kit-row { display: flex; align-items: center; gap: calc(3 * var(--px)); white-space: nowrap; overflow: hidden; height: calc(10 * var(--px)); }
/* O ícone é o MESMO que a barra de conjuração do chefe mostra durante a luta: o que se estuda aqui é o que se vê lá. */
.tw-kit-ico { width: calc(10 * var(--px)); height: calc(10 * var(--px)); flex: none; background: center / contain no-repeat; image-rendering: pixelated; }
.tw-kit-ico.is-empty { background: rgba(255, 255, 255, 0.08); }
.tw-kit-name { color: var(--c-gold); flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.tw-kit-tell { color: var(--c-dim); flex: none; }
/* O cadeado: INTEIRO = não dá para interromper (vermelho), PARTIDO = dá (verde). A diferença é de FORMA antes de
   ser de cor — o arco cortado no meio —, para quem não separa vermelho de verde continuar lendo a linha. */
.tw-kit-lock {
  position: relative;
  width: calc(8 * var(--px));
  height: calc(8 * var(--px));
  flex: none;
  margin-left: auto;
}
.tw-kit-lock::before {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: calc(8 * var(--px));
  height: calc(4 * var(--px));
  background: currentColor;
}
/* A ARGOLA, 4 px acima do corpo. Na rodada 1 o corpo tinha 5 px e a argola encostava nele: os dois viravam uma
   mancha só e a diferença entre inteiro e partido sumia no 1×. Com corpo de 4 e argola de 4 SEM aresta de baixo,
   o que se lê é "∩ sobre a caixa" — e o partido perde metade do ∩, que é uma diferença de FORMA, não de cor
   (quem não separa vermelho de verde continua lendo a linha). */
.tw-kit-lock::after {
  content: '';
  position: absolute;
  left: calc(2 * var(--px));
  top: 0;
  width: calc(4 * var(--px));
  height: calc(4 * var(--px));
  box-shadow: inset var(--px) 0 0 currentColor, inset calc(-1 * var(--px)) 0 0 currentColor, inset 0 var(--px) 0 currentColor;
}
.tw-kit-row.is-unbreakable .tw-kit-lock { color: #ff8a7a; }
.tw-kit-row.is-breakable   .tw-kit-lock { color: var(--c-ok); }
/* partido: sobra só a haste esquerda — a argola arrebentou e o cadeado não fecha mais */
.tw-kit-row.is-breakable .tw-kit-lock::after { box-shadow: inset var(--px) 0 0 currentColor; }

/* --- torre-chefes --- A barra de conjuração do chefe e a linha de fase (na Masmorra a faixa de baixo do bloco do chefe é
   da barra de objetivo, e é por isso que isto mora aqui e não em css/dungeon.css nem em css/hud.css: os dois são
   compartilhados). A barra esvazia por ANIMAÇÃO, com a duração que veio do servidor (`--dur` = durTicks ÷ tickRate): o
   client não conta tique nenhum. Âmbar = você pode quebrar; vermelho com contorno = `uninterruptible`, atordoar não
   adianta — é a única informação nova que a Torre precisa ensinar.
   ONDE (verificação integrada de 2026-10-02): o `.hud-boss` de dungeon.css centra o CORPO (nome + vida, 18 px) no rosto de
   32, e a barra de vida caía em y 22…30 — o texto do telegrafo, em y 24…34, era desenhado POR CIMA dela (1.308 px² medidos
   no navegador), e a vida e o "dá para quebrar" ficavam ilegíveis justo no instante em que o jogador precisa ler os dois.
   Na Torre o corpo sobe para o ALTO do bloco (nome y 4…14, vida y 14…22) e a conjuração mora na faixa y 24…39 LOGO ABAIXO
   dele, na coluna do corpo (x 222…454, à direita do rosto em x 186…218): o bloco lê nome · vida · o golpe que vem. O texto
   mais longo do dado ("Derrame de Escória — Não dá para interromper", 44 caracteres = 211 px) cabe nos 232. Preso por
   client/tests/ui/towerHudTop.test.js, que faz a conta com as regras deste arquivo, de dungeon.css e de nine-slice.css. */
.scene-tower .hud-boss { align-items: flex-start; }
.scene-tower .hud-bosscast {
  position: absolute;
  top: calc(24 * var(--px));
  left: 50%;
  width: calc(232 * var(--px));
  margin-left: calc(-98 * var(--px));
  height: calc(16 * var(--px));
  pointer-events: none;
  text-shadow: var(--px) var(--px) 0 #000;
}
.hud-bosscast.hidden { display: none; }
.hud-bosscast-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-bosscast-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-bosscast-fill { height: 100%; width: 100%; background: var(--c-gold); }
.hud-bosscast-fill.is-draining { animation: bosscast-drain var(--dur, 1s) linear forwards; }
@keyframes bosscast-drain {
  from { width: 100%; }
  to   { width: 0%; }
}
/* inquebrável: vermelho, com contorno grosso — legível em 1× e distinguível do âmbar sem depender de cor só */
.hud-bosscast.is-unbreakable .hud-bosscast-text { color: #ff8a7a; }
.hud-bosscast.is-unbreakable .hud-bosscast-fill { background: #d8412c; }
.hud-bosscast.is-unbreakable .hud-bosscast-bar { box-shadow: inset 0 0 0 var(--px) #ff8a7a; }
/* a fase, À ESQUERDA DO ROSTO do chefe, sem empurrar nada: x 144…184 (2 px antes do rosto, que começa em x 186; o painel do
   herói acaba em x 140) e y 24…34. Em x 148…196 ela entrava 10 × 10 px no retrato. "Fase 3" tem 6 caracteres = 29 px. */
.scene-tower .hud-phase {
  position: absolute;
  top: calc(24 * var(--px));
  left: calc(144 * var(--px));
  width: calc(40 * var(--px));
  height: calc(10 * var(--px));
  line-height: calc(10 * var(--px));
  text-align: right;
  white-space: nowrap;
  color: var(--c-dim);
  text-shadow: var(--px) var(--px) 0 #000;
  pointer-events: none;
}
.hud-phase.hidden { display: none; }
