/* work.css — telas de nódulos e trabalhadores: janelas `hire` (js/ui/windows/hire.js), `workers` (workers.js) e
   `node` (node.js), o mapa de nódulos (js/ui/widgets/nodeMap.js) e as peças comuns (windows/workWindowBase.js,
   widgets/progressBar.js). Design: docs/specs/workers-nodes.md Dona: trilha de UI de nódulos.
   Medidas em px de arte — sempre calc(N * var(--px)); nada de transform em texto; ampliação de arte só por fator
   inteiro. Geometria das janelas: hire 420×222 (corpo 404×~180), workers 436×258 (corpo 420×~214, lista 168 |
   ficha 248), node 272 × 96…272 (o cartão da ilha da carta do mar v2: miolo 260, a altura do conteúdo, rola só no teto). */

/* ---- peças comuns --------------------------------------------------------------------------------------------- */
.text-ok { color: var(--c-ok); }

.work-body {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 0 calc(2 * var(--px));
  line-height: calc(10 * var(--px));
}
/* Rolagem própria: o `::before` do `.panel-inset` (inset −4) viraria área rolável se a rolagem ficasse no painel. */
.work-panes,
.workers-sheet,
.workers-list {
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
  scrollbar-color: #575273 #12101c;
}
@supports selector(::-webkit-scrollbar) {
  .work-panes, .workers-sheet, .workers-list { scrollbar-width: auto; scrollbar-color: auto; }
  .work-panes::-webkit-scrollbar, .workers-sheet::-webkit-scrollbar, .workers-list::-webkit-scrollbar { width: calc(6 * var(--px)); }
  .work-panes::-webkit-scrollbar-track, .workers-sheet::-webkit-scrollbar-track, .workers-list::-webkit-scrollbar-track { background: #12101c; }
  .work-panes::-webkit-scrollbar-thumb, .workers-sheet::-webkit-scrollbar-thumb, .workers-list::-webkit-scrollbar-thumb { background: #575273; border: var(--px) solid #12101c; }
}
/* C6 — a última linha visível saía FATIADA ao meio, colada no rodapé ("Nível 2: 1 vaga(s)…" por cima de "Nível 1/5"),
   e lia-se como defeito de render, não como "tem mais coisa abaixo". Mesmo molde do livro de receitas
   (`professions.css › .rb-list`): respiro no fim da rolagem, e a fatia nunca encosta no rodapé. */
.work-panes { flex: 1; min-height: 0; padding-right: calc(2 * var(--px)); padding-bottom: calc(6 * var(--px)); }

.work-head {
  display: flex;
  align-items: center;
  gap: calc(3 * var(--px));
  min-height: calc(12 * var(--px));
}
.work-head-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.work-section {
  margin-top: calc(3 * var(--px));
  border-bottom: var(--px) solid rgba(255, 255, 255, 0.14);
}
.work-note { line-height: calc(9 * var(--px)); }
.work-row {
  display: flex;
  align-items: center;
  gap: calc(4 * var(--px));
  margin-top: calc(2 * var(--px));
}
.work-row-end { justify-content: flex-end; }
.work-row > .bar { flex: 1; min-width: calc(40 * var(--px)); }
.work-label { display: inline-flex; align-items: center; gap: calc(2 * var(--px)); white-space: nowrap; }
.work-stats { margin: calc(1 * var(--px)) 0 0; }
.work-actions {
  display: flex;
  flex-wrap: wrap;
  gap: calc(2 * var(--px));
  margin-top: calc(3 * var(--px));
}
.work-actions > .btn { min-height: calc(14 * var(--px)); }

/* Retrato do tipo de trabalhador na moldura do grau: o mesmo `.slot` do inventário, sem nada de interativo. O `.slot` nasce
   com `touch-action: none` (é o arrasto da Mochila) e o polegar que pousava no retrato não rolava a caixa: a fileira de
   Trabalhadores (20 camas, workers-nodes.md §6.4), o cartão do Capataz (o `.window-body` rola quando o cartão passa da janela)
   e as vagas do cartão da ilha (`.work-panes`). Ninguém arrasta retrato: a regra fica NO retrato (`.slot.work-portrait`
   vence o `.slot` de nine-slice.css em qualquer ordem de folha), e lista nova com retrato já nasce rolando. */
.work-portrait { cursor: default; }
.slot.work-portrait { touch-action: auto; }
.work-portrait-icon.is-blank { box-shadow: inset 0 0 0 var(--px) rgba(0, 0, 0, 0.6); }

.work-item-icon {
  display: inline-block;
  flex: none;
  width: calc(16 * var(--px));
  height: calc(16 * var(--px));
  background-repeat: no-repeat;
  background-size: 100% 100%;
  image-rendering: pixelated;
}
.work-item-icon.is-missing {
  background-image: linear-gradient(45deg, #ff00ff 25%, #200020 25%, #200020 50%, #ff00ff 50%, #ff00ff 75%, #200020 75%);
  background-size: calc(8 * var(--px)) calc(8 * var(--px));
}
.work-kind-ico { width: calc(16 * var(--px)); height: calc(16 * var(--px)); }
.ico-worker { width: calc(9 * var(--px)); height: calc(9 * var(--px)); background-image: var(--ui-ico_worker, none); }
.ico-node { width: calc(9 * var(--px)); height: calc(9 * var(--px)); background-image: var(--ui-ico_node, none); }
.ico-meter { width: calc(9 * var(--px)); height: calc(9 * var(--px)); background-image: var(--ui-ico_meter, none); }

/* A TIRA DO SALÁRIO (janela `workers`): interruptor + custo/ciclo + bolsa + autonomia, todos ÍCONE + número, com a
   frase inteira na dica. Herdeira de [Alimentar] / [Alimentar todos], que saíram com o vigor em 2026-09-26. */
.work-wage {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: calc(3 * var(--px));
  margin-top: calc(3 * var(--px));
  padding: calc(1 * var(--px)) calc(2 * var(--px));
  background: rgba(255, 255, 255, 0.05);
}
.work-wage-chip { display: inline-flex; align-items: center; gap: calc(2 * var(--px)); white-space: nowrap; color: var(--c-gold); }
/* Vermelho é o único "grito" da tira: a bolsa no zero e a autonomia abaixo de uma hora. */
.work-wage-chip.is-dry { color: var(--c-danger); }
/* Interruptor: selo aceso quando o ouro está saindo, apagado quando não. Nada interativo dentro do <button>. */
.work-wage-switch {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: calc(16 * var(--px));
  height: calc(16 * var(--px));
  padding: 0;
  border: 0;
  background: rgba(0, 0, 0, 0.35);
  box-shadow: inset 0 0 0 var(--px) rgba(255, 255, 255, 0.18);
  cursor: pointer;
}
/* ALVO DE 24 sem mudar o selo (o lint W9.1 media 16×16): uma área invisível de 24×24 em volta dele. Ela cabe nos vãos que já
   existem — 4 acima (padding 1 + margin 3 da tira) e 4 abaixo (padding 1 + o margin 3 de `.work-actions`, ou o `row-gap` 4
   quando a tira quebra linha) —; à esquerda só há os 2 do padding (a ficha corta o resto, `overflow`), então o selo empurra
   a ficha de custo 3 px e a área cresce para a DIREITA, sem cobrir a ficha vizinha. */
#workers-wage-strip { row-gap: calc(4 * var(--px)); }
.work-wage-switch { position: relative; margin-right: calc(3 * var(--px)); }
.work-wage-switch::after { content: ''; position: absolute; top: calc(-4 * var(--px)); bottom: calc(-4 * var(--px)); left: calc(-2 * var(--px)); right: calc(-6 * var(--px)); }
.work-wage-switch.is-on { box-shadow: inset 0 0 0 var(--px) var(--c-gold); }
.work-wage-switch.is-off > .btn-icon { opacity: 0.35; filter: grayscale(1); }

/* Barras: o preenchimento de `nine-slice.css` por tipo. */
.bar-work .bar-fill { background-image: url(../assets/ui/bars/bar_fill_cast.png); }
.bar-stock .bar-fill { background-image: url(../assets/ui/bars/bar_fill_exp.png); }

/* Lista de escolha (Atribuir): botões de linha inteira dentro do modal. */
.work-picker {
  display: flex;
  flex-direction: column;
  gap: calc(2 * var(--px));
  min-width: calc(200 * var(--px));
  max-height: calc(160 * var(--px));
  overflow-y: auto;
}

/* ---- janela `node` -------------------------------------------------------------------------------------------- */
/* MATERIAL = o slot da mochila (js/ui/widgets/materialSlot.js), pedido do dono de 2026-09-30 ("exibindo no ícone do
   material o tier dele"; docs/specs/workers-nodes.md §7): ícone 32 em 1:1, selo de tier ↖ e número ↘ da MESMA peça
   (nine-slice.css `.slot-tier` / `.slot-qty` — nada de selo novo), nome ao lado em até duas linhas. Antes era um ícone
   de 16 (o PNG de 32 pela metade) numa linha de 16 px; o selo de 6 px de arte cobriria metade dele.
   Duas colunas no miolo de 260 do cartão da ilha: cada célula tem 36 + 3 + ~86 de nome (≈ 18 caracteres por linha). O RARO
   mora na mesma grade, depois dos comuns, com "Raro" dourado na 2.ª linha (`.is-rare`): uma seção própria custava cabeçalho
   + uma fileira de 36 e empurrava as Vagas para baixo. Assim o pior nódulo do dado (`herb_glade`,
   5 comuns + 1 raro) ocupa três fileiras. `touch-action` volta a `auto` porque o `.slot` da grade o desliga
   para o arrasto (dragdrop.js) — aqui não há arrasto, e o dedo que começa num slot tem de rolar a janela. */
.work-mats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: calc(2 * var(--px)) calc(4 * var(--px));
  margin-top: calc(2 * var(--px));
}
.work-mat { display: flex; align-items: center; gap: calc(3 * var(--px)); min-width: 0; }
.work-mat > .slot { cursor: default; touch-action: auto; }
.work-mat:focus-visible { outline: var(--px) solid #fff5a8; outline-offset: 0; }
.work-mat-text { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: calc(9 * var(--px)); }
/* o nome nunca vira reticências no meio de uma palavra que distingue dois materiais: quebra em até duas linhas */
.work-mat-name { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; }
.work-mat-sub { white-space: nowrap; color: var(--c-text-dim); }
.work-mat.is-missing .work-mat-sub { color: var(--c-danger); }
.work-mat.is-rare .work-mat-sub { color: var(--c-gold); }
.work-stock-bar { margin-top: calc(1 * var(--px)); }

.work-slot {
  display: flex;
  align-items: center;
  gap: calc(3 * var(--px));
  margin-top: calc(2 * var(--px));
  padding: calc(1 * var(--px));
  background: rgba(255, 255, 255, 0.05);
}
.work-slot.is-free, .work-slot.is-locked { justify-content: space-between; min-height: calc(16 * var(--px)); }
.work-slot-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--px); }
.work-slot-line { display: flex; align-items: center; justify-content: space-between; gap: calc(3 * var(--px)); }
.work-slot-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.work-slot-bar { height: calc(8 * var(--px)); }

/* --- carta --- O CARTÃO DA ILHA tem a ALTURA DO CONTEÚDO nos dois estados (docs/specs/workers-nodes.md §7.8: a linha `node` da
   tabela declara `fitMinH` 96…272 — `windowLayout.js` — e o gerenciador escreve `height: auto` entre o piso e o teto). Acima do
   teto quem rola é a `.work-panes`, com o degradê de `scroll-fade.css`; abaixo dele a caixa não tem o que desbotar e o degradê
   sai (`is-scrollable`, MEDIDO por `node.js › afterLayout`, o molde de `sources.css › .src-list`): os 12 px dele comiam o pé do
   [Descobrir]. Saíram com o `fitState` a regra `#win-node:has(> .node-body.is-locked)` e o rodapé (`.node-footer`). */
.node-body > .work-panes:not(.is-scrollable) { --scroll-fade: 0px; --scroll-fade-pad: calc(2 * var(--px)); }
/* o que a ilha dá: a MESMA grade de duas colunas da ficha aberta (`.work-mats`, nome escrito ao lado da figura: o Ferro e
   a Magnetita têm a mesma pedra, só o selo de tier muda — ux-casos §13.3) */
/* a ação: UM botão grande (alvo de dedo no celular deitado) com o preço exato dentro, na cor do rótulo do botão (ouro
   sobre o botão de ouro sumia, visto na captura). Sem ouro o preço NÃO se pinta: vermelho no miolo do botão travado não
   passava de 2,8:1 — quem diz "falta ouro" é o motivo do botão, como no [Promover] (ux-casos §8). A MESMA regra vale
   para o [Melhorar] do botão principal (`.node-btn-cost`). */
.node-unlock-row { margin-top: calc(4 * var(--px)); }
.btn.node-unlock { min-height: calc(24 * var(--px)); gap: calc(6 * var(--px)); }
.node-unlock-cost, .node-btn-cost { color: inherit; }
/* fora de alcance: "Descubra antes:" e as vizinhas que abrem o caminho como PORTAS (o toque voa até ela) — o nome inteiro no
   botão (nome próprio não se trunca), e a fila quebra linha quando duas não cabem */
.node-gate-label { white-space: nowrap; }
.btn.node-gate { min-height: calc(16 * var(--px)); }

/* ---- enxugamento da janela `node` (docs/UX-GRAMATICA.md) -------------------------------------------------------
   FICHA CURTA: na tela o numero com o seu icone; a frase inteira no gesto (`widgets/hint.js`) e no `aria-label`.
   Uma linha de fichas no lugar de tres linhas de largura cheia foi o que fez a ficha do Catalogo caber numa tela
   (ux-casos §11) e e o mesmo problema aqui: 300 px de janela, `dl` de `dt`/`dd` gastando uma linha por rotulo. */
.node-chips { display: flex; flex-wrap: wrap; align-items: center; gap: calc(4 * var(--px)); margin-top: calc(2 * var(--px)); }
.node-chip, .node-group { display: inline-flex; align-items: center; gap: calc(2 * var(--px)); white-space: nowrap; }
.node-group { gap: calc(3 * var(--px)); }
.node-sep { opacity: 0.6; }
.node-chip.is-ok, .node-group.is-ok { color: var(--c-ok); }
.node-chip.is-bad, .node-group.is-bad { color: var(--c-danger); }
.node-ico { flex: none; }
/* O nome dos vizinhos por onde a estrada AINDA nao chega e a acao ("ligue estes antes"), entao ele quebra linha em
   vez de virar reticencias — foi a licao da ficha de `workers.js`, onde o nome do nodulo saia truncado. */
.node-reach-from { white-space: normal; min-width: 0; }
/* O bonus de rendimento sobe para o cabecalho da secao: e o `+20%` que responde "vale a pena melhorar?". */
.work-section { display: flex; align-items: baseline; justify-content: space-between; gap: calc(4 * var(--px)); }

/* --- carta --- O CARTÃO DA ILHA da carta do mar v2 (js/ui/windows/node.js; docs/specs/workers-nodes.md §7.8 e §7.9).
   O selo `Nv N` na barra de título (à esquerda do ×): a moldura de selo na cor do título (ouro com a janela em foco). */
.node-seal.node-title-level { color: inherit; align-self: center; }
.node-seal.is-gold { color: var(--c-gold); }
/* (1) a linha de estado: o selo do marcador, o placar do tipo e o arquipélago apagado — logo abaixo do título */
.node-chips.node-state { margin-top: 0; }
.node-arch { white-space: nowrap; }
/* (2) o BOTÃO PRINCIPAL: largura cheia e 24 de altura (o alvo do dedo no celular deitado); o preço exato dentro quando custa */
.node-primary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(2 * var(--px));
  margin-top: calc(3 * var(--px));
}
.node-primary > .btn { min-height: calc(24 * var(--px)); }
.btn.node-primary-btn { flex: 1 1 auto; gap: calc(6 * var(--px)); }
.node-primary.is-connect > .node-see-kind { flex: none; }
/* o Atribuir: a palavra e as FICHAS de rosto — `[rosto 16] Nome` em 24 de altura (o rosto sozinho era alvo de 2,8 mm) — e o
   [+N] com a lista inteira. O rosto é o do aviso de entrega (`workWindowBase.js › portraitMini`), sem o vão de lá. */
.node-primary-label { color: var(--c-text-dim); margin-right: calc(1 * var(--px)); white-space: nowrap; }
.btn.node-face { padding: 0 calc(3 * var(--px)) 0 calc(2 * var(--px)); gap: calc(3 * var(--px)); }
.node-face > .work-yield-face { margin-right: 0; }
.btn.node-face-more { padding: 0 calc(3 * var(--px)); }
/* (5) a DISPUTA (a costura da guerra, js/ui/widgets/nodeWarSlot.js): quem detém a ilha e o bônus, a porta da aba Guerra do
   clã e, com guerra aberta, o selo da fase e a data. Sem rolagem própria: a altura é a do conteúdo. */
.node-war-row { display: flex; flex-wrap: wrap; align-items: center; gap: calc(3 * var(--px)); margin-top: calc(2 * var(--px)); }
.node-war-owner { display: inline-flex; align-items: center; gap: calc(2 * var(--px)); white-space: nowrap; }
.node-war-owner.is-mine { color: var(--c-ok); }
.node-war-ico { flex: none; width: calc(16 * var(--px)); height: calc(16 * var(--px)); }
.btn.node-war-go { margin-left: auto; }
/* (7) a Rota no fim: o selo à esquerda e o [Desconectar] (perigo, a ação rara) à direita */
.node-chips.node-route { justify-content: space-between; }
/* Trazer alguém: a lista do modal — [rosto] Nome … a ilha de onde ele vem. A ilha na cor do RÓTULO do botão (o apagado sobre
   o cinza-claro do botão secundário não se lia — olhado na captura do celular, 2026-10-02); quem a separa do nome é o lugar. */
.btn.node-bring-row { justify-content: flex-start; gap: calc(3 * var(--px)); min-height: calc(24 * var(--px)); }
.node-bring-row > .work-yield-face { margin-right: 0; }
.node-bring-from { margin-left: auto; color: inherit; }
/* o selo "Armazém cheio" do descansado (F6, revisão de 2026-10-05): o apagado do `.workers-seal` some no cinza-claro do botão —
   olhado na captura do celular —, então a moldura e a palavra vão na cor do rótulo, como a ilha ao lado */
.node-bring-row > .node-bring-st { color: inherit; }
/* --- /carta --- */

/* ---- janela `workers` ----------------------------------------------------------------------------------------- */
.workers-cols { flex: 1; min-height: 0; display: flex; gap: calc(4 * var(--px)); }
.workers-col-list { flex: none; width: calc(168 * var(--px)); position: relative; }
.workers-list { position: absolute; inset: calc(-4 * var(--px)); padding: calc(1 * var(--px)) calc(2 * var(--px)); }
.workers-sheet { flex: 1; min-width: 0; padding-right: calc(2 * var(--px)); }

.workers-row {
  display: flex;
  width: 100%;
  align-items: center;
  gap: calc(3 * var(--px));
  margin-bottom: calc(2 * var(--px));
  padding: calc(1 * var(--px));
  border: 0;
  background: rgba(255, 255, 255, 0.05);
  color: var(--c-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.workers-row:hover { background: rgba(255, 255, 255, 0.12); }
.workers-row.is-selected { background: rgba(224, 176, 64, 0.18); outline: var(--px) solid var(--c-gold); outline-offset: calc(-1 * var(--px)); }
.workers-row:focus-visible { outline: calc(2 * var(--px)) solid #fff5a8; outline-offset: calc(-1 * var(--px)); }
/* Cama LIVRE do alojamento (Onda 3a): a coluna da lista terminava num retângulo vazio e o alojamento só existia como
   número no rodapé. A cama é uma fileira de verdade — aro tracejado para não se confundir com gente — e é a porta do
   Capataz dentro da própria janela (B68). Alvo de toque de 24 px de arte: com o teto de 20 camas (workers-nodes.md §6.4) a
   lista de quem acaba de ampliar é quase só cama livre, e a fileira de 18 px (ícone 16 + aro) era pequena para o dedo. */
.workers-row.is-bed { min-height: calc(24 * var(--px)); background: rgba(255, 255, 255, 0.03); outline: var(--px) dashed rgba(255, 255, 255, 0.2); outline-offset: calc(-1 * var(--px)); }
.workers-row.is-bed:hover { background: rgba(255, 255, 255, 0.1); }
.workers-bed-ico {
  flex: none;
  width: calc(16 * var(--px));
  height: calc(16 * var(--px));
  background-image: var(--ui-ico_hire);
  background-size: 100% 100%;
  image-rendering: pixelated;
  opacity: 0.75;
}
.workers-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--px); }
.workers-row-line { display: flex; align-items: baseline; justify-content: space-between; gap: calc(3 * var(--px)); }
.workers-row-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A fila tinha TRÊS linhas de altura (nome+nível · estado · salário) para quatro coisas curtas. O selo e o ouro
   dividem a segunda linha: a lista passa a ser lida em coluna (nome → selo → moeda) e cabe mais gente sem rolagem. */
.workers-row-sub { align-items: center; }

/* ---- G2: o estado do trabalhador é SELO, nunca frase (`docs/UX-GRAMATICA.md`) ---------------------------------
   Mesma peça da aba Guerra (`clan.css › .clan-war-phase`): moldura de 1 px + palavra curta + cor. A COR NUNCA VEM
   SOZINHA (ui-gameplay.md §8.7) — quem informa é a palavra dentro do selo; a cor só faz o olho achar, na lista, quem
   parou de trabalhar.
   A ESCALA DE COR foi corrigida na 2.ª rodada, olhando a captura: `Trabalhando` em ouro acendia TRÊS das quatro
   filas e o olho caía justamente em quem não precisava de nada. Quem pinta é quem precisa do jogador — o ocioso
   (ouro: atribua-o a um nódulo, ele está sem render) e o parado por falta de pagamento (perigo: a produção morreu).
   Trabalhando é a cor normal do texto (vivo, não me chame) e em promoção é apagado (só esperar). */
.workers-seal, .node-seal {
  flex: none;
  padding: 0 calc(2 * var(--px));
  border: var(--px) solid currentColor;
  color: var(--c-text-dim);
  line-height: calc(9 * var(--px));
}
.workers-seal.is-s0 { color: var(--c-gold); }
.node-seal.is-ok { color: var(--c-ok); }
.node-seal.is-bad { color: var(--c-danger); }
.node-seal.is-off { color: var(--c-text-dim); }
.workers-seal.is-s1 { color: var(--c-text); }
.workers-seal.is-s5 { color: var(--c-danger); }
/* `flex-wrap`: o nome do nódulo é o VALOR da linha e não pode virar "Pedreira do…" — na 1.ª captura ele saía
   truncado, porque selo + ícone + nome não cabem nos 284 px da ficha. Faltando espaço, o nome desce de linha. */
.workers-state { display: flex; align-items: center; flex-wrap: wrap; gap: calc(3 * var(--px)); margin-top: calc(2 * var(--px)); }
/* G3 — "Trabalhando em" saiu: o ícone do tipo de nódulo (a MESMA peça do marcador do mapa) diz o "em". */
.workers-state-node { display: inline-flex; align-items: center; gap: calc(2 * var(--px)); min-width: 0; }
/* --- carta --- o par ícone + nome é a PORTA da ilha para a carta (um `.btn`, workers-nodes.md §7.11). O `.btn` não quebra
   linha, e o nome mais longo do dado ("Cova dos Pinheiros Gelados", 26 letras) com o ícone e a moldura passa da ficha: aqui
   o rótulo quebra DENTRO do botão, nunca corta nem rola a ficha de lado. */
.btn.workers-state-node { white-space: normal; text-align: left; justify-content: flex-start; max-width: 100%; }
#workers-lodging { display: inline-flex; align-items: center; gap: calc(2 * var(--px)); }
.workers-cycle { margin-top: var(--px); }
/* --- focus --- A fila `[barra][Concluir ◈ N]` da ficha (docs/specs/focus.md §8): a barra cede o que o botão pede e não fica abaixo de 45
   (o `Concluir ◈ 4.800` da promoção mais longa cabe ao lado dela); o botão não quebra nem encolhe. ACEITO (polimento, 2026-10-07): a
   fila tem a altura do botão (16, a barra sozinha 8) e empurra o Demitir — que já quebrava para a 2.ª linha das ações e passava da dobra
   antes do Foco (cel 1–7 px, pc 2–14) — mais 8 px para baixo; a ficha rola e o `.scroll-fade` diz que há mais. Apertar 8 px não o traria
   à vista nos dois perfis, e o botão de 16 é o alvo de toque. */
.workers-cycle-row { display: flex; align-items: center; gap: calc(3 * var(--px)); margin-top: var(--px); }
.workers-cycle-row > .workers-cycle { flex: 1 1 auto; min-width: calc(45 * var(--px)); margin-top: 0; }
.workers-cycle-row > .focus-btn { flex: none; }
/* --- focus --- O cartão da ilha: `Concluir ◈ N` antes do Retirar, os dois à direita da linha do salário (a margem automática leva a sobra). */
.work-slot-line > .focus-btn { flex: none; margin-left: auto; }
/* A fila da habilidade: o ícone 16×16 da série (`ico_wskill_*`/`ico_stat_*`, workers-nodes.md §8) na frente do nome e da
   descrição, que continuam escritos (a descrição é a mecânica, N1). Centrado na altura das duas linhas de texto. */
.work-skill { display: flex; align-items: center; gap: calc(3 * var(--px)); line-height: calc(9 * var(--px)); margin-top: calc(1 * var(--px)); }
.work-skill-text { display: flex; flex-direction: column; min-width: 0; }
.work-skill-ico { width: calc(16 * var(--px)); height: calc(16 * var(--px)); }
/* O "—" de quem ainda não tem habilidade é a PISTA da regra ("aprende uma a cada N níveis", no gesto) e media 10 de altura
   (o lint W9.1 marcava 142×10). A área de toque cresce 14 para CIMA, sobre o cabeçalho "Habilidades" (texto, não controle;
   a dica é a da seção), até o fim da linha da exp: para baixo não há vão — a área do interruptor do salário ocupa os 4 px. */
#workers-no-skills { position: relative; }
#workers-no-skills::after { content: ''; position: absolute; left: 0; right: 0; top: calc(-14 * var(--px)); bottom: 0; }
.workers-footer { gap: calc(4 * var(--px)); }
.workers-footer > .gold-label { margin-left: auto; }
/* O PREÇO DENTRO DO BOTÃO (`Ampliar +1 [moeda] 38.071` no rodapé, `Promover [moeda] 19.879` na ficha): a ficha de moeda nasce
   `.text-gold` (224,176,64) e, sobre o cinza-claro do botão secundário, o número quase não se lia — no PC e no celular
   (verificação integrada de 2026-10-02). Dentro do botão o preço toma a cor do RÓTULO (a do estado dele: livre, sob o mouse,
   travado); a moeda de 9 px ao lado já diz que é ouro. O molde é o `Receber` do Bestiário (`.bestiary-claim-gold`). */
#workers-expand > .gold-label, #workers-promote > .gold-label { color: inherit; }

/* ---- janela `hire` -------------------------------------------------------------------------------------------- */
.hire-cards { flex: 1; min-height: 0; display: flex; gap: calc(4 * var(--px)); align-items: stretch; }
.hire-card {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--px);
  padding: calc(1 * var(--px));
  text-align: center;
}
.hire-card.is-empty { justify-content: center; line-height: calc(9 * var(--px)); }
.hire-name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hire-sub, .hire-skill, .hire-skill-desc { max-width: 100%; line-height: calc(9 * var(--px)); }
.hire-skill-desc { overflow: hidden; }
/* habilidade inicial: [ícone 16×16] nome, centrados no cartão — a mesma figura da ficha do trabalhador */
.hire-skill.has-ico { display: flex; align-items: center; justify-content: center; gap: calc(2 * var(--px)); flex: 0 0 auto; }
.hire-stats { width: 100%; padding: 0 calc(2 * var(--px)); column-gap: calc(2 * var(--px)); }
.hire-cost { margin-top: auto; }
.hire-card > .btn { width: 100%; min-height: calc(14 * var(--px)); }
.hire-footer { gap: calc(4 * var(--px)); }
.hire-warn { flex-basis: 100%; }

/* ---- carta do mar (visto de cima) — a carta v2 (docs/specs/workers-nodes.md §7.1–§7.14) ------------------------ */
/* Quatro camadas: `.node-map-cam` (terreno + teia + barcos do Ilhas/Perto) ANDA com a câmera; `.node-map-chart` é a CARTA
   (a imagem ÷3, a teia a ÷3, os rótulos e o "você estava aqui"), parada e só no degrau `is-chart`; `.node-map-marks` fica
   parada em espaço de tela, com os medalhões, os pips e os nomes em tamanho CONSTANTE — quem amplia é o terreno, não o
   rótulo. Tudo o que escala usa `image-rendering: pixelated`: zoom em degrau inteiro, nunca interpolado. A raiz leva o
   degrau (`is-chart` | `is-isles` | `is-near`) e a troca de degrau é um CORTE de opacidade em dois passos (`is-cut`, 120 ms):
   a arte nunca escala em transição. */
.node-map {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  pointer-events: auto;
}
.node-map-view {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: #0c0a14;
  cursor: grab;
  touch-action: none;
}
.node-map-view.is-grabbing { cursor: grabbing; }
.node-map.is-chart .node-map-view { cursor: default; }
.node-map-view.is-cut { animation: node-map-cut 0.12s steps(2, jump-none) both; }
@keyframes node-map-cut { from { opacity: 0.35; } to { opacity: 1; } }
.node-map.is-chart .node-map-cam { display: none; }
/* A CARTA: a imagem própria do pipeline (`bg/<região>/overview.png`, 640×360) 1:1 no palco, com a câmera parada. */
.node-map-chart { position: absolute; left: 0; top: 0; width: calc(640 * var(--px)); height: calc(360 * var(--px)); display: none; }
.node-map.is-chart .node-map-chart { display: block; }
.node-map-chart-bg { position: absolute; left: 0; top: 0; background-repeat: no-repeat; background-size: 100% 100%; image-rendering: pixelated; }
.node-map-chart-bg.is-missing { background: linear-gradient(#1b2740 0%, #20304a 100%); }
.node-map-chart-links { position: absolute; left: 0; top: 0; image-rendering: pixelated; pointer-events: none; }
/* "você estava aqui": o retângulo do último Ilhas, tracejado de 1 px (desenho; o degrau e o lugar vão nos três pontos e na placa) */
.node-map-was-here { position: absolute; box-sizing: border-box; border: var(--px) dashed rgba(255, 245, 168, 0.75); pointer-events: none; }
/* Os RÓTULOS dos arquipélagos: a placa centrada no `label ÷ 3` (o pino tem largura zero e centra o conteúdo nos dois lados —
   sem `transform`, a posição fica em px inteiros), 12 de altura; o selo `Expl. N` em vermelho enquanto a Exploração não chega
   e `achadas/total` apagado com ≥ 1. Tocar filtra o arquipélago. */
.node-map-arch-pin { position: absolute; width: 0; height: 0; display: flex; align-items: center; justify-content: center; }
.node-map-arch {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: calc(2 * var(--px));
  height: calc(12 * var(--px));
  padding: 0 calc(2 * var(--px));
  border: 0;
  /* quase opaca: a teia e o tracejado do "você estava aqui" passam POR TRÁS do nome sem riscar as letras (a 0,72 o tracejado
     cortava o "Expl. 52" da Garganta na captura de 844×390) */
  background: rgba(12, 10, 20, 0.9);
  box-shadow: 0 0 0 var(--px) rgba(12, 10, 20, 0.9);
  color: var(--c-text);
  font: inherit;
  line-height: calc(10 * var(--px));
  white-space: nowrap;
  cursor: pointer;
  pointer-events: auto;
}
.node-map-arch.is-on { box-shadow: 0 0 0 var(--px) var(--c-gold); }
.node-map-arch-seal { color: var(--c-danger); }
.node-map-arch-ratio { color: var(--c-text-dim); }
.node-map-arch-seal.hidden, .node-map-arch-ratio.hidden { display: none; }
@media (prefers-reduced-motion: reduce) { .node-map-view.is-cut { animation: none; } }
.node-map-cam { position: absolute; left: 0; top: 0; }
.node-map-bg { position: absolute; inset: 0; }
.node-map-bg.is-missing { background: linear-gradient(#1b2740 0%, #2c3c26 62%, #3a3324 100%); }
.node-map-layer {
  position: absolute;
  left: 0;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  image-rendering: pixelated;
}
/* A teia é rasterizada em px de ARTE (o canvas do tamanho do mapa, 1920×1080) e esticada por CSS: o traço amplia em
   blocos, como o terreno. */
.node-map-links {
  position: absolute;
  left: 0;
  top: 0;
  image-rendering: pixelated;
  pointer-events: none;
}
/* nodes-mar: os barcos vivem em `.node-map-cam` (andam com a câmera); sprite 12×12 × zoom, `image-rendering: pixelated`.
   Sem a arte (pacote 11) o barco é um losango de CSS na cor da madeira — a tela funciona antes do PNG. */
.sea-boats { position: absolute; left: 0; top: 0; pointer-events: none; }
.sea-boat {
  position: absolute;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  image-rendering: pixelated;
  pointer-events: auto;
}
.sea-boat[style*="background-image: none"] { background: #8a5a2b; clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); box-shadow: 0 0 0 var(--px) #17141f; }
.sea-boat.is-docked { opacity: 0.9; }

/* As caixas de UI da carta (barra, filtro, zoom, o lugar e a dica) ficam ACIMA dos medalhões: o medalhão tem `z-index: 2`
   e, sem isto, um nódulo do alto era pintado por cima da barra e ROUBAVA O CLIQUE do botão dela. Medalhão que fica atrás
   de uma caixa volta com um arrasto; botão que não responde não tem volta. */
.node-map-bar,
.node-map-zoombox,
.node-map-filters,
.node-map-where,
.node-map-coach { z-index: 3; }

/* A BARRA (4,4)–(636,28): a placa `hud_plate` (9-slice 4, a da Faixa A) com o conteúdo de 16 — tripulação, o próximo passo,
   saldo, [Trabalhadores (T)], [Contratar] e [×]. Ninguém quebra linha (a linha do passo é UMA linha). */
.node-map-bar {
  position: absolute;
  left: calc(4 * var(--px));
  right: calc(4 * var(--px));
  top: calc(4 * var(--px));
  height: calc(24 * var(--px));
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: calc(4 * var(--px));
  padding: 0 calc(1 * var(--px));
  border: calc(4 * var(--px)) solid transparent;
  border-image: var(--ui-hud_plate, url(../assets/ui/hud/hud_plate.png)) 4 fill / calc(4 * var(--px)) stretch;
  image-rendering: pixelated;
  white-space: nowrap;
}
.node-map-spacer { flex: 1 1 auto; }
.node-map-actions { flex: none; display: flex; gap: calc(2 * var(--px)); }
.node-map-bar .btn { min-height: calc(14 * var(--px)); white-space: nowrap; }
.node-map-close { min-width: calc(16 * var(--px)); }
.node-map-wallet { flex: none; }
/* a TRIPULAÇÃO: `[ico_worker16] em campo/total` — toque = as ilhas da tripulação, contornadas na Carta */
.node-map-crew {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: calc(2 * var(--px));
  height: calc(16 * var(--px));
  padding: 0 calc(1 * var(--px));
  border: 0;
  background: none;
  color: var(--c-text);
  font: inherit;
  cursor: pointer;
}
.node-map-crew-ico { width: calc(16 * var(--px)); height: calc(16 * var(--px)); background: var(--ui-ico_worker16) center / 100% 100% no-repeat; image-rendering: pixelated; }
/* o PRÓXIMO PASSO: UMA linha com UM botão (§7.5) — o rosto 16, o alvo, o verbo; o porquê vai no gesto */
.node-map-next { flex: 0 1 auto; min-width: 0; display: inline-flex; align-items: center; gap: calc(3 * var(--px)); overflow: hidden; }
.node-map-next .work-yield-face { margin-right: 0; }
.node-map-next-text { flex: none; }
.node-map-next-node {
  flex: none;
  padding: 0;
  border: 0;
  background: none;
  color: var(--c-gold);
  font: inherit;
  text-decoration: underline dotted;
  text-underline-offset: calc(2 * var(--px));
  cursor: pointer;
}
/* o selo-botão do passo: moldura + palavra curta + cor (G2) — perigo no sem pagamento, ouro no ocioso, apagado no sem vaga */
.node-map-next-seal {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: calc(2 * var(--px));
  height: calc(16 * var(--px));
  padding: 0 calc(3 * var(--px)) 0 0;
  border: 0;
  background: rgba(12, 10, 20, 0.55);
  color: var(--c-text);
  font: inherit;
  box-shadow: inset 0 0 0 var(--px) rgba(255, 255, 255, 0.18);
}
button.node-map-next-seal { cursor: pointer; }
.node-map-next-seal.is-danger { color: var(--c-danger); box-shadow: inset 0 0 0 var(--px) var(--c-danger); }
.node-map-next-seal.is-gold { color: var(--c-gold); box-shadow: inset 0 0 0 var(--px) var(--c-gold); }
.node-map-next-seal.is-dim { padding: 0 calc(3 * var(--px)); color: var(--c-text-dim); }
/* F6 — o `pay` (§7.5, caso 8): o selo de ouro começa pelo `ico_meter` de 9, não pelo rosto de 16 — respiro dos dois lados.
   O `rest` usa a linha do `send` (rosto → [ilha] [Mover]) e não tem regra própria. */
.node-map-next-seal.is-pay { padding: 0 calc(3 * var(--px)); }
/* o [Contratar] do passo pulsa: é o ÚNICO pulso da tela enquanto não há trabalhador (G2) */
.node-map-next .btn.is-pulse { animation: node-pulse 1.6s steps(2) infinite; }

/* O LUGAR (Ilhas e Perto): a placa apagada em (8,32) com o arquipélago sob o centro da câmera. */
.node-map-where {
  position: absolute;
  left: calc(8 * var(--px));
  top: calc(32 * var(--px));
  height: calc(12 * var(--px));
  box-sizing: border-box;
  padding: var(--px) calc(3 * var(--px));
  background: rgba(12, 10, 20, 0.62);
  color: var(--c-text-dim);
  line-height: calc(10 * var(--px));
  white-space: nowrap;
  pointer-events: none;
}
.node-map.is-chart .node-map-where { display: none; }

/* O FILTRO — a legenda viva (4,306)–(190,356): duas linhas de 20 na placa `hud_plate` (o aro de 4 pinta por cima dos 2 px
   de borda: as linhas caem em y 308 e 332, a geometria do §7.13). Linha 1: os chips de estado (pip + número; zero não
   aparece, G5); linha 2: os tipos com o placar de rotas e o funil. Aceso = `is-on` (o `aria-pressed` diz o mesmo). */
.node-map-filters {
  position: absolute;
  left: calc(4 * var(--px));
  bottom: calc(4 * var(--px));
  width: calc(186 * var(--px));
  height: calc(50 * var(--px));
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: calc(4 * var(--px));
  border: calc(2 * var(--px)) solid transparent;
  border-image: var(--ui-hud_plate, url(../assets/ui/hud/hud_plate.png)) 4 fill / calc(4 * var(--px)) stretch;
  image-rendering: pixelated;
}
.node-map-filter-row { display: flex; align-items: center; gap: calc(1 * var(--px)); height: calc(20 * var(--px)); padding: 0 calc(1 * var(--px)); }
.node-map-chip,
.node-map-route,
.node-map-mat-btn {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: calc(1 * var(--px));
  height: calc(20 * var(--px));
  padding: 0 calc(2 * var(--px));
  border: 0;
  background: none;
  color: var(--c-text);
  font: inherit;
  line-height: calc(10 * var(--px));
  cursor: pointer;
}
.node-map-chip.is-on,
.node-map-route.is-on,
.node-map-mat-btn.is-on { box-shadow: inset 0 0 0 var(--px) var(--c-gold); background: rgba(224, 176, 64, 0.12); }
.node-map-chip-pip { width: calc(12 * var(--px)); height: calc(12 * var(--px)); background-repeat: no-repeat; background-size: 100% 100%; image-rendering: pixelated; }
.node-map-chip-pip.is-war { width: calc(16 * var(--px)); height: calc(16 * var(--px)); }
.node-map-chip-pip.is-missing { border-radius: 50%; background: var(--c-text-dim); }
/* F6: o chip do armazém cheio sem `node_pip_resting`: o disco apagado do marcador (`.node-mark.is-pip-css.is-resting`) */
.node-map-chip-pip.is-resting.is-missing { background: #6e675c; }
.node-map-route-ico { width: calc(16 * var(--px)); height: calc(16 * var(--px)); background-repeat: no-repeat; background-size: 100% 100%; image-rendering: pixelated; }
.node-map-route-ico.is-missing { width: auto; color: var(--c-gold); }
.node-map-route-count { color: var(--c-text); }
.node-map-route.is-full .node-map-route-count { color: var(--c-danger); }
.node-map-mat-btn { width: calc(20 * var(--px)); justify-content: center; padding: 0; }
.node-map-mat-ico { width: calc(16 * var(--px)); height: calc(16 * var(--px)); background: var(--ui-ico_filter) center / 100% 100% no-repeat; image-rendering: pixelated; }
.node-map-mat-ico.is-missing { background: none; color: var(--c-gold); text-align: center; }
/* O PAINEL DE MATERIAL (32, 302 − h)–(332, 302), h ≤ 160: acima do filtro e à direita do botão do chat (x 4…28, y 250…274,
   que segue à vista). Quem rola é a lista de dentro (`scroll-fade.css`); a moldura é o painel. A linha "Falta" vem primeiro,
   só quando há; depois os materiais das ilhas por tipo e tier, no mini-slot de 16 com o selo de tier. */
.node-map-mat-picker {
  position: absolute;
  left: calc(32 * var(--px));
  bottom: calc(58 * var(--px));
  width: calc(300 * var(--px));
  box-sizing: border-box;
  z-index: 4;
}
.node-map-mat-list {
  display: flex;
  flex-direction: column;
  gap: calc(3 * var(--px));
  max-height: calc(144 * var(--px));
  overflow-y: auto;
}
.node-map-needs,
.node-map-mat-group { display: flex; flex-wrap: wrap; align-items: center; gap: calc(2 * var(--px)); }
.node-map-needs.hidden { display: none; }
.node-map-needs-title { color: var(--c-danger); margin-right: calc(2 * var(--px)); }
.node-map-mat-title { line-height: calc(10 * var(--px)); }
.node-map-mat-kind { width: calc(16 * var(--px)); height: calc(16 * var(--px)); background-repeat: no-repeat; background-size: 100% 100%; image-rendering: pixelated; opacity: 0.8; }
button.node-map-mat { padding: 0; border: 0; cursor: pointer; touch-action: auto; }
.node-map-mat.is-on { box-shadow: inset 0 0 0 var(--px) var(--c-gold); }

/* O ZOOM (542,306)–(636,356): [−][● ● ●][+] em y 308–330 e, embaixo, [⌂] com o nome do degrau apagado. */
.node-map-zoombox {
  position: absolute;
  right: calc(4 * var(--px));
  bottom: calc(4 * var(--px));
  width: calc(94 * var(--px));
  height: calc(50 * var(--px));
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: calc(2 * var(--px));
  border: calc(2 * var(--px)) solid transparent;
  border-image: var(--ui-hud_plate, url(../assets/ui/hud/hud_plate.png)) 4 fill / calc(4 * var(--px)) stretch;
  image-rendering: pixelated;
}
.node-map-zoom-row { display: flex; align-items: center; gap: calc(2 * var(--px)); height: calc(22 * var(--px)); }
.node-map-zoombox .btn { width: calc(22 * var(--px)); height: calc(22 * var(--px)); min-height: calc(22 * var(--px)); padding: 0; flex: none; }
.node-map-level-dots { display: flex; flex: none; }
.node-map-level { width: calc(14 * var(--px)); height: calc(22 * var(--px)); display: flex; align-items: center; justify-content: center; padding: 0; border: 0; background: none; cursor: pointer; }
.node-map-level::before { content: ''; width: calc(6 * var(--px)); height: calc(6 * var(--px)); border-radius: 50%; background: rgba(255, 255, 255, 0.28); box-shadow: 0 0 0 var(--px) rgba(12, 10, 20, 0.85); }
.node-map-level.is-on::before { background: var(--c-gold); }
.node-map-home > span:last-child:empty { display: none; }
.node-map-level-name { white-space: nowrap; line-height: calc(10 * var(--px)); }

/* A DICA DO APARELHO (§7.12): y 286–302, centrada entre o filtro e o zoom (ou entre o filtro e o cartão); some no 1.º
   arrasto, pinça ou roda da sessão. A faixa tem a largura do vão e centra a placa sem `transform`. */
.node-map-coach {
  position: absolute;
  left: calc(190 * var(--px));
  right: calc(98 * var(--px));
  bottom: calc(58 * var(--px));
  height: calc(16 * var(--px));
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
/* com o cartão aberto, entre o botão do chat e o cartão (x 32…360): a dica (~238 px) não cabe nos 174 entre o filtro e o cartão */
.node-map.has-card .node-map-coach { left: calc(32 * var(--px)); right: calc(280 * var(--px)); }
.node-map-coach > span { flex: none; padding: var(--px) calc(4 * var(--px)); background: rgba(12, 10, 20, 0.9); color: var(--c-text-dim); line-height: calc(10 * var(--px)); white-space: nowrap; }
.node-map-coach.hidden { display: none; }

/* Cada marcador é um PIN: uma caixa do tamanho da janela cujos filhos se posicionam sozinhos (medalhão centrado no
   ponto do mapa, nome ao lado, medidores abaixo). Assim um `hidden` no pin apaga o conjunto quando ele sai de vista. */
.node-map-marks { position: absolute; inset: 0; pointer-events: none; }
.node-mark-pin { position: absolute; inset: 0; }
.node-mark-pin > * { position: absolute; }
/* medalhão SEMPRE acima das placas: com o mapa afastado dois nódulos chegam perto e a placa de um cobria o outro */
.node-mark, .node-city { z-index: 2; pointer-events: auto; }
.node-map-plate, .node-mark-gauge { z-index: 1; }

.node-map-plate {
  max-width: calc(132 * var(--px));
  padding: 0 calc(2 * var(--px));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: calc(10 * var(--px));
}
.node-map-plate.is-locked { color: #8d8698; }
.node-map-plate.is-available { color: var(--c-gold); }
.node-map-plate.is-city { color: var(--c-gold); }
/* a ilha FORA DE ALCANCE no Ilhas/Perto: a névoa — pip de 12 e a placa apagada */
.node-map-plate.is-far { color: #6f6a7a; opacity: 0.8; }
/* no voo só a câmera e os pins andam: as placas se refazem no fim */
.node-map.is-flying .node-map-plate { visibility: hidden; }
/* fora da janela o pin continua no Tab (B404): invisível e sem ponteiro, e o foco leva a câmera até ele */
.node-mark-pin.is-offview > * { opacity: 0; }
.node-mark-pin.is-offview > .node-mark,
.node-mark-pin.is-offview > .node-mark-mats,
.node-mark-pin.is-offview > .node-city { pointer-events: none; }
/* filtro ligado: o resto a 35 % (os achados ganham contorno e placa) */
.node-mark-pin.is-dim > * { opacity: 0.35; }

/* Marcador: medalhão 28×28 de `manifest.ui.node_marker_<estado>`; sem a arte, um círculo de CSS com a cor do estado
   (a forma do aro é a informação; o estado também sai escrito no `aria-label` e na placa). O anel escuro por fora é
   o que separa o medalhão do terreno — sobre a mata escura o aro de pedra sumia. */
.node-mark {
  width: calc(28 * var(--px));
  height: calc(28 * var(--px));
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  overflow: visible;
  background: rgba(12, 10, 20, 0.62);
  image-rendering: pixelated;
  cursor: pointer;
}
/* --- carta (revisão, 2026-10-03) --- A PEÇA do medalhão (`node_marker_<estado>`) mora numa camada PRÓPRIA, sem o recorte
   redondo: o `border-radius` do botão recortava o PNG em círculo de raio 14 e o anel de estado (`inset` de 1 px) era pintado POR
   CIMA dela — o selo do canto ↙ pende para fora do aro, e o ponto de 1 px do "!" do sem pagamento (pixel (5,24), a 13,5 px do
   centro) saía na cor do anel; o "+" do pode descobrir perdia duas pontas e a âncora, 7 pixels. Por baixo dela ficam o disco
   escuro e o anel de estado do botão — o medalhão de CSS de quando a arte falta (a peça é opaca em todo o círculo de raio 14). */
.node-mark:not(.is-pip)::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--node-mark, none) center / 100% 100% no-repeat;
  image-rendering: pixelated;
  pointer-events: none;
}
.node-mark.is-locked { --node-mark: var(--ui-node_marker_locked); box-shadow: inset 0 0 0 var(--px) #6d6878, 0 0 0 var(--px) rgba(12, 10, 20, 0.85); }
/* "Pode descobrir": o aro dourado PARADO (carta v2, G2 — um pulso por tela: só a ilha do próximo passo pulsa, `.is-next`) */
.node-mark.is-available { --node-mark: var(--ui-node_marker_available); box-shadow: inset 0 0 0 var(--px) var(--c-gold), 0 0 0 var(--px) rgba(12, 10, 20, 0.85); }
.node-mark.is-free { --node-mark: var(--ui-node_marker_free); box-shadow: inset 0 0 0 var(--px) #b0a898, 0 0 0 var(--px) rgba(12, 10, 20, 0.85); }
.node-mark.is-working { --node-mark: var(--ui-node_marker_working); box-shadow: inset 0 0 0 var(--px) var(--c-ok), 0 0 0 var(--px) rgba(12, 10, 20, 0.85); }
/* carta v2: parada SEM PAGAMENTO — o aro `fire` com o "!" (parecia "parada por escolha" quando vestia o livre) */
.node-mark.is-stalled { --node-mark: var(--ui-node_marker_stalled); box-shadow: inset 0 0 0 var(--px) var(--c-danger), 0 0 0 var(--px) rgba(12, 10, 20, 0.85); }
/* nodes-mar: descoberta SEM rota — aro azul-acinzentado, sem animação (não é alerta, é escolha do jogador). */
.node-mark.is-moored { --node-mark: var(--ui-node_marker_moored); box-shadow: inset 0 0 0 var(--px) #6f8fb0, 0 0 0 var(--px) rgba(12, 10, 20, 0.85); }
.node-mark.is-moored > .node-mark-ico { opacity: 0.7; }
.node-map-plate.is-moored { color: #9fb4c8; }
/* F6 (workers-nodes.md §6.6): ARMAZÉM CHEIO — a tripulação descansa (st 6). A peça `node_marker_resting` (aro de osso fosco e o
   selo "Z" no ↙, G2: apagado = parado sem pedir ação) vai na camada do `::before`; por baixo dela, o medalhão de CSS APAGADO de
   quando a arte falta (o disco cheio cinza e o aro apagado, a cor do pip e do chip). O ícone do tipo sem cor, sem animação. Fica
   ANTES do `.is-pip`, que o substitui pelo pip na Carta. */
.node-mark.is-resting { --node-mark: var(--ui-node_marker_resting); background: #6e675c; box-shadow: inset 0 0 0 var(--px) #8a8276, 0 0 0 var(--px) rgba(12, 10, 20, 0.85); }
.node-mark.is-resting > .node-mark-ico { opacity: 0.6; filter: grayscale(1); }
.node-mark:hover, .node-city:hover { filter: brightness(1.25); }
.node-mark:focus-visible, .node-city:focus-visible { outline: calc(2 * var(--px)) solid #fff5a8; outline-offset: 0; }
.node-mark.is-selected { outline: calc(2 * var(--px)) solid var(--c-gold); outline-offset: 0; }
/* o achado de um filtro: contorno claro de 1 px (a placa também aparece) */
.node-mark.is-match:not(.is-selected) { outline: var(--px) solid #fff5a8; outline-offset: var(--px); }
/* UM PULSO SÓ: a ilha que o próximo passo nomeia (movimento reduzido: o contorno parado) */
.node-mark.is-next { animation: node-pulse 1.6s steps(2) infinite; }
/* chegou de um voo: o medalhão pulsa duas vezes; no salto pela Carta, o alvo pulsa nela */
.node-mark.is-arrived { animation: node-pulse 0.3s steps(2, jump-none) 2; }
.node-mark.is-hop { animation: node-pulse 0.35s steps(2) infinite; }
/* O PIP (12×12, `node_pip_<estado>`): a Carta inteira e, no Ilhas/Perto, a ilha FORA DE ALCANCE. O botão mantém o alvo de
   toque de 28 (invisível) e a peça mora no meio dele; sem a peça no manifesto, o medalhão de CSS (`is-pip-css`). */
.node-mark.is-pip { border-radius: 0; box-shadow: none; background: var(--node-mark, none) center / calc(12 * var(--px)) calc(12 * var(--px)) no-repeat; }
.node-mark.is-pip > .node-mark-ico,
.node-mark.is-pip > .node-mark-lock,
.node-mark.is-pip.is-locked > .node-mark-lock { display: none; }
.node-mark.is-pip.is-working { --node-mark: var(--ui-node_pip_working); }
.node-mark.is-pip.is-free { --node-mark: var(--ui-node_pip_free); }
.node-mark.is-pip.is-stalled { --node-mark: var(--ui-node_pip_stalled); }
.node-mark.is-pip.is-moored { --node-mark: var(--ui-node_pip_moored); }
.node-mark.is-pip.is-available { --node-mark: var(--ui-node_pip_available); }
.node-mark.is-pip.is-locked { --node-mark: var(--ui-node_pip_locked); }
.node-mark.is-pip.is-far { --node-mark: var(--ui-node_pip_far); }
.node-mark.is-pip.is-resting { --node-mark: var(--ui-node_pip_resting); }
/* na Carta a ilha fora de alcance NÃO tem pip (o terreno a mostra; o alvo de toque fica, focável) — menos a achada por um filtro */
.node-map.is-chart .node-mark.is-pip.is-far:not(.is-found) { --node-mark: none; }
.node-mark.is-pip.is-selected,
.node-mark.is-pip.is-match:not(.is-selected) { outline: none; }
.node-mark.is-pip.is-selected::after,
.node-mark.is-pip.is-match:not(.is-selected)::after {
  content: '';
  position: absolute;
  left: calc(6 * var(--px));
  top: calc(6 * var(--px));
  width: calc(16 * var(--px));
  height: calc(16 * var(--px));
  box-sizing: border-box;
  border: calc(2 * var(--px)) solid var(--c-gold);
  pointer-events: none;
}
.node-mark.is-pip.is-match:not(.is-selected)::after { border-width: var(--px); border-color: #fff5a8; left: calc(7 * var(--px)); top: calc(7 * var(--px)); width: calc(14 * var(--px)); height: calc(14 * var(--px)); }
.node-mark.is-pip-css::before {
  content: '';
  position: absolute;
  left: calc(9 * var(--px));
  top: calc(9 * var(--px));
  width: calc(10 * var(--px));
  height: calc(10 * var(--px));
  border-radius: 50%;
  box-shadow: 0 0 0 var(--px) rgba(12, 10, 20, 0.9);
  background: #b0a898;
}
.node-mark.is-pip-css.is-working::before { background: var(--c-ok); }
.node-mark.is-pip-css.is-stalled::before { background: var(--c-danger); }
.node-mark.is-pip-css.is-available::before { background: var(--c-gold); }
.node-mark.is-pip-css.is-moored::before { background: #6f8fb0; }
.node-mark.is-pip-css.is-locked::before { background: #4a4552; }
/* F6: armazém cheio — o disco APAGADO cheio (sem `node_pip_resting`; é a mesma cor do medalhão de 28 e do chip do filtro) */
.node-mark.is-pip-css.is-resting::before { background: #6e675c; }
.node-mark.is-pip-css.is-far::before { background: rgba(255, 255, 255, 0.18); }
.node-map.is-chart .node-mark.is-pip-css.is-far:not(.is-found)::before { content: none; }
/* na Carta não há anel, ponto de vaga, bandeja, brasão nem selo `Expl. N` (§7.1): só o pip e, na guerra aberta, `ico_war9` */
.node-map.is-chart .node-mark-ring,
.node-map.is-chart .node-mark-gauge,
.node-map.is-chart .node-mark-mats,
.node-map.is-chart .node-mark-flag,
.node-map.is-chart .node-mark-expl { display: none; }
@media (prefers-reduced-motion: reduce) {
  .node-mark.is-next,
  .node-mark.is-arrived,
  .node-mark.is-hop,
  .node-map-next .btn.is-pulse { animation: none; }
  .node-mark.is-next:not(.is-selected) { outline: calc(2 * var(--px)) solid var(--c-gold); outline-offset: var(--px); }
}
.node-mark-ico {
  width: calc(16 * var(--px));
  height: calc(16 * var(--px));
  background-repeat: no-repeat;
  background-size: 100% 100%;
  image-rendering: pixelated;
}
.node-mark.is-locked > .node-mark-ico { opacity: 0.55; }
/* Cadeado do marcador bloqueado (8×8 no canto inferior direito do medalhão). O ícone é escuro e o medalhão também:
   sem o disco claro atrás ele some no mapa — é a mesma solução da bigorna da artesã em screens.css. */
.node-mark-lock {
  position: absolute;
  right: calc(-1 * var(--px));
  bottom: calc(-1 * var(--px));
  display: none;
  width: calc(8 * var(--px));
  height: calc(8 * var(--px));
  background: var(--ui-ico_lock, none) center / 100% 100% no-repeat, #e8e2d0;
  border-radius: 50%;
  box-shadow: 0 0 0 var(--px) #17141f;
  image-rendering: pixelated;
}
.node-mark.is-locked > .node-mark-lock { display: block; }
@keyframes node-pulse { from { filter: brightness(1); } to { filter: brightness(1.6); } }

/* A CIDADE: quadrado, não medalhão — a forma já diz que ela não é um nódulo (§8.7). É a raiz da teia e está sempre
   ligada, então não tem estado: só o aro de ouro e o brasão. */
.node-city {
  width: calc(36 * var(--px));
  height: calc(36 * var(--px));
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  background: rgba(12, 10, 20, 0.5);
  box-shadow: inset 0 0 0 calc(2 * var(--px)) var(--c-gold), 0 0 0 var(--px) #17141f;
  cursor: pointer;
}
.node-city-ico {
  position: relative;
  width: calc(20 * var(--px));
  height: calc(14 * var(--px));
  margin-top: calc(4 * var(--px));
  background: #efe6cc;
  box-shadow: inset 0 0 0 var(--px) #17141f;
}
/* ameias: tres blocos no topo da muralha */
.node-city-ico::before {
  content: '';
  position: absolute;
  left: 0;
  top: calc(-4 * var(--px));
  width: calc(4 * var(--px));
  height: calc(5 * var(--px));
  background: #efe6cc;
  box-shadow: calc(8 * var(--px)) 0 0 0 #efe6cc, calc(16 * var(--px)) 0 0 0 #efe6cc;
}
/* portao */
.node-city-ico::after {
  content: '';
  position: absolute;
  left: calc(7 * var(--px));
  bottom: 0;
  width: calc(6 * var(--px));
  height: calc(9 * var(--px));
  background: #3a2a1e;
  box-shadow: inset 0 0 0 var(--px) #17141f;
}
/* na Carta a sua ilha é `ico_island` 16 (com o alvo de toque de 28) e a placa "Sua Ilha" — a angra a ÷3 já a desenha */
.node-map.is-chart .node-city {
  width: calc(28 * var(--px));
  height: calc(28 * var(--px));
  background: var(--ui-ico_island, none) center / calc(16 * var(--px)) calc(16 * var(--px)) no-repeat;
  box-shadow: none;
  image-rendering: pixelated;
}
.node-map.is-chart .node-city-ico { display: none; }

/* O selo `Expl. N` da ilha TRANCADA (alcançável, Exploração baixa — §7.3), sob o medalhão, na faixa dos pontos de vaga (a
   trancada não tem vaga): o porquê na tela (N3), em vermelho com moldura. */
.node-mark-expl { width: calc(48 * var(--px)); display: flex; justify-content: center; z-index: 1; pointer-events: none; }
.node-mark-expl-seal {
  padding: 0 calc(2 * var(--px));
  background: rgba(12, 10, 20, 0.85);
  color: var(--c-danger);
  box-shadow: inset 0 0 0 var(--px) var(--c-danger);
  line-height: calc(9 * var(--px));
  white-space: nowrap;
}
/* A MARCA DE GUERRA (fases 1–3, `ui/nodeWarMark.js`): `ico_war` 16 no canto livre ↖ do anel no Ilhas/Perto; na Carta,
   `ico_war9` colado ao ↗ do pip. Não pulsa (G2): no Ilhas/Perto a fase 1 leva a casca em ouro, a 3 em perigo (na Carta, só a
   escura — abaixo); a fase vai no rótulo do marcador. A casca escura de 1 px é a de toda marca da carta. */
.node-mark-war {
  width: calc(16 * var(--px));
  height: calc(16 * var(--px));
  background: var(--ui-ico_war, none) center / 100% 100% no-repeat;
  image-rendering: pixelated;
  z-index: 2;
  pointer-events: none;
  filter: drop-shadow(var(--px) 0 0 rgb(12, 10, 20)) drop-shadow(calc(-1 * var(--px)) 0 0 rgb(12, 10, 20)) drop-shadow(0 var(--px) 0 rgb(12, 10, 20)) drop-shadow(0 calc(-1 * var(--px)) 0 rgb(12, 10, 20));
}
.node-mark-war.is-bid { filter: drop-shadow(var(--px) 0 0 var(--c-gold)) drop-shadow(calc(-1 * var(--px)) 0 0 var(--c-gold)) drop-shadow(0 var(--px) 0 var(--c-gold)) drop-shadow(0 calc(-1 * var(--px)) 0 var(--c-gold)); }
.node-mark-war.is-battle { filter: drop-shadow(var(--px) 0 0 var(--c-danger)) drop-shadow(calc(-1 * var(--px)) 0 0 var(--c-danger)) drop-shadow(0 var(--px) 0 var(--c-danger)) drop-shadow(0 calc(-1 * var(--px)) 0 var(--c-danger)); }
.node-map.is-chart .node-mark-war { width: calc(9 * var(--px)); height: calc(9 * var(--px)); background-image: var(--ui-ico_war9, var(--ui-ico_war, none)); }
/* --- carta (revisão, 2026-10-03) --- na Carta a casca de FASE engrossava a peça de 9: em ouro, as flâmulas de 2×2 viravam pontos
   e a silhueta lia "taça dourada" (ao lado do losango de ouro do "Pode descobrir", um bolo só). Ali a casca é a escura de toda
   marca, em todas as fases; a fase fica no gesto e no rótulo do marcador (`ui.work.map.warBadge`) e no Ilhas/Perto. */
.node-map.is-chart .node-mark-war.is-bid,
.node-map.is-chart .node-mark-war.is-battle { filter: drop-shadow(var(--px) 0 0 rgb(12, 10, 20)) drop-shadow(calc(-1 * var(--px)) 0 0 rgb(12, 10, 20)) drop-shadow(0 var(--px) 0 rgb(12, 10, 20)) drop-shadow(0 calc(-1 * var(--px)) 0 rgb(12, 10, 20)); }

/* Medidores abaixo do medalhão (48 de largura, centrados no ponto do mapa). */
.node-mark-gauge {
  width: calc(48 * var(--px));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--px);
}
/* A barra de estoque do marcador saiu em 2026-09-25 com o estoque do nódulo: sobraram os pontos de vaga. */
.node-mark-slots { display: flex; gap: var(--px); }
/* O ponto leva a casca escura de 1 px do medalhão e do anel (revisão de 2026-10-01): verde sobre a mata, sem ela, o
   ponto do Bosque mal se separava do chão — e com 2+ trabalhadores é a única pista de quantos estão lá. */
.node-mark-dot {
  width: calc(4 * var(--px));
  height: calc(4 * var(--px));
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.65);
  box-shadow: inset 0 0 0 var(--px) rgba(255, 255, 255, 0.35), 0 0 0 var(--px) rgba(12, 10, 20, 0.85);
}
.node-mark-dot.is-used { background: var(--c-ok); }
/* O ANEL DE TRABALHO (js/ui/widgets/nodeRings.js; pedido do dono de 2026-10-01, docs/specs/workers-nodes.md §7): tela
   de `nodeRing.js › RING_SIZE` px de arte (o medalhão + `RING_PAD` de cada lado; a medida vai no `style`, de lá) centrada
   no medalhão e ABAIXO dele: o miolo é transparente e o medalhão, a sombra e o contorno de seleção ficam por cima — a
   faixa começa depois do raio que o contorno de 2 px cobre. Os pixels são inteiros e a tela estica em blocos, como a
   teia; o arco é desenho (`aria-hidden`) — o estado continua escrito no `aria-label` do marcador. */
.node-mark-ring {
  z-index: 1;
  image-rendering: pixelated;
  pointer-events: none;
}
/* A BANDEJA DE MATERIAIS da ilha que TRABALHA (js/ui/widgets/nodeMap.js; pedido do dono de 2026-10-01, docs/specs/
   workers-nodes.md §7): o mini-slot de 16 da série (`.bankmat-ico` de windows.css — o do banco de materiais, dos chips do
   Pronto e da pílula de entrega) com o selo de tier ↖, lado a lado sobre o fundo OPACO da pílula de entrega, logo abaixo
   dos pontos de vaga. Vão e respiro vão no `style` (de `nodeMap.js`, que mede a caixa pelas mesmas constantes). Recebe o
   ponteiro: o `title` do mouse e o balão do toque (`setHint`) e o menu de item (botão direito, toque longo); o clique não
   faz nada aqui — quem abre a ficha da ilha é o medalhão. */
.node-mark-mats {
  z-index: 1;
  display: flex;
  background: #0e0c14;
  pointer-events: auto;
}
/* o RARO vem por último, depois de um FIO APAGADO de 1 px num vão de 3 (`nodeMap.js › MAT_FENCE`; o `gap` da bandeja dá o
   ar de cada lado): o LUGAR separa (UX-GRAMATICA G1, "lugar e forma"), e a palavra "Raro" vai no gesto e no rótulo do
   medalhão. Nunca o ouro: na carta o aro dourado já é "Pode descobrir" (o medalhão que pulsa) e o contorno dourado é
   "selecionado" — o mesmo desenho com duas ideias (G2, §12.3 nº 2; revisão de 2026-10-01). */
.node-mark-mats-fence {
  flex: none;
  width: var(--px);
  margin: calc(3 * var(--px)) 0;
  background: var(--c-text-dim);
  opacity: 0.5;
}

/* ---- a praça enquanto o mapa está aberto ----------------------------------------------------------------------- */
/* O mapa é uma TELA (design §8.2): a barra do personagem, a fila de botões e os NPCs da praça saem de cena — senão
   ficariam boiando sobre um cenário que não é o deles. As janelas continuam (z 10+).
   --- lobby-v2 --- (04 §5) a caixinha de "Jogadores online" do canto inferior direito não existe mais: o contador
   subiu para a Faixa A, que já sai daqui junto com a `.lobby-topbar`. O seletor dela saiu com ela.
   --- lobby-v2 --- (02 §1) a fila de botões passou a se chamar `.lobby-bar` (antes `.lobby-actions`): o seletor velho
   não casava com nada e a barra ficava boiando SOBRE o mapa de nódulos, com o trilho junto — medido no navegador em
   2026-09-23, `07` §3 linha 11 → PERGUNTAS 26. */
.screen-lobby.is-node-map > .lobby-topbar,
.screen-lobby.is-node-map > .lobby-bar,
.screen-lobby.is-node-map > .npc-hotspots { display: none; }

/* ícone do botão "Nódulos" do lobby (mesma família de `.lobby-btn-icon`, screens.css) */
.lobby-btn-icon.is-node { background-image: var(--ui-ico_node); }

/* Ícone da placa do Capataz na praça (`ROLE_UI.work` de widgets/npcHotspots.js): a regra vive em screens.css, com a
   família das outras três placas de NPC. A linha que existia AQUI citava `ico_foreman` (12 px) e, com a MESMA
   especificidade da de screens.css e carregando depois (index.php:28 > :22), vencia: a praça desenhava o ícone de
   12 px boiando na caixa de 16, e não o `ico_foreman16` que `lobbyCity.js:47` declara. Medido na folha de contato
   (UX-GRAMATICA §12.3) e resolvido tirando a duplicata — o fundo de papel saiu com ela: a figura nova é o chapéu de
   palha do Bento, claro, e sobre papel ele sumia (a razão do fundo era a prancheta escura, que não existe mais). */

/* As tentativas de promoção guardadas. Era "Tentativas de promoção: 3" em linha própria (no meio da fileira de
   botões, uma frase parecia mais um botão); com G1/G5 virou o chip `×3`, que cabe ao lado do [Promover] e só existe
   quando há tentativa. Alinhado ao centro para não flutuar acima da base dos botões. */
.work-actions > .work-note { align-self: center; }

/* --- nodewar --- selo do clã que detém o nódulo disputável (seven-systems 08 §6). Fica no canto superior direito do
   medalhão, FORA do anel de trabalho — no canto livre do anel (`nodeRing.js › RING_CORNER`), posto pelo `nodeMap.js`
   (left/top; o `right` daqui é anulado lá): dentro do anel o brasão cobria o arco no 1.º quarto do ciclo. Fora dele o
   brasão pousa no chão da carta (o azul do clã sumia no mar — olhado na captura de 2026-10-01), então leva a CASCA escura de
   1 px de toda marca da carta: quatro sombras sem desfoque, em px inteiros, que contornam só os pixels do brasão. Nunca
   carrega informação sozinho: o nome do dono também vai no `aria-label` e no `title` do marcador. */
.node-mark-flag {
  position: absolute;
  top: calc(-3 * var(--px));
  right: calc(-3 * var(--px));
  z-index: 2;
  pointer-events: none;
  line-height: 0;
  filter: drop-shadow(var(--px) 0 0 rgb(12, 10, 20)) drop-shadow(calc(-1 * var(--px)) 0 0 rgb(12, 10, 20)) drop-shadow(0 var(--px) 0 rgb(12, 10, 20)) drop-shadow(0 calc(-1 * var(--px)) 0 rgb(12, 10, 20));
}

/* ---- aviso de ENTREGA do trabalhador (js/ui/widgets/workYieldCards.js) ------------------------------------------
   Pedidos do dono: 2026-09-25 ("imagem do trabalhador, imagem do item que coletou e quantidade"), 2026-09-30 ("em
   qualquer momento, seja em dg, exploração etc." + "somente a imagem do trabalhador, imagem do item (com tier) e
   quantidade ... menor e mais simples, ocupando menos espaço e mais discreto") e 2026-10-01 ("os ícones estão muito
   grandes, tanto a imagem do trabalhador quanto os ícones dos materiais [...] você está ali fazendo alguma coisa e vem a
   notificação"). Uma PÍLULA por trabalhador, sem frase: o ROSTO 16×16 (o retrato de 32 na redução 2:1, aro de 1 px na
   cor do grau) e, por material, o MINI-SLOT 16×16 do banco (`.bankmat-ico` de windows.css, selo de tier ↖) com a
   quantidade AO LADO. 18 de altura (era 38 com os slots de 36). Fundo OPACO, o mesmo `#0e0c14` do toast, sem moldura
   9-slice. Discreta pelo TAMANHO e pela falta de texto, não pela transparência — com o fundo a 72 % e a pílula a 0,92 o
   rótulo "Portal das Masmorras" da ilha se lia por dentro dela (revisão de 2026-09-30).
   A camada vive no `#ui-overlay` (ui.js), fora das telas. A POSIÇÃO e o TETO (`--work-yield-cap`, que o widget lê a
   cada lote: 3 no lobby, 2 na corrida, na carta do mar e com o resumo aberto; o widget nunca desce de 2 = uma pílula +
   o `+N`) mudam por tela — medidas em px de arte do palco 640×360:
   - lobby (padrão): uma FAIXA no rodapé ESQUERDO, em FILA (a mais nova à direita), com o pé em y 326 — acima dos selos
     da barra de modos (`.lobby-bar` em y 336, o selo "60/60" da Mochila 5 px acima) e a partir do pé das janelas de 258
     (de y 50 a 308, medido em 2026-10-01 com Trabalhadores aberta): y 308…326. Até 2026-10-01 ela morava no canto
     SUPERIOR esquerdo, em y 52…170, que é onde as janelas da esquerda põem o TÍTULO e a primeira fila (a pílula tapava a
     lista de Trabalhadores — medido no print); lá embaixo ela não cruza o painel do chat (y 134…262) nem o botão dele
     (y 266…290). Com uma janela aberta ela fica POR BAIXO das janelas, e as de 276–280 a escondem onde passam (regra
     abaixo); com a carta do mar e com o resumo da corrida, posição própria (abaixo);
   - corrida (`#hud` montado: Exploração, Masmorra e Torre): coluna ESQUERDA à DIREITA do botão do chat (chat.css
     `.chat`: 24×24 em x 4…28, y 266…290) e com o PÉ na base dele (y 290), acima do log de abates (5 linhas a partir de
     y 356 → topo em y ≈ 293). Cresce para cima com TETO 2: y 252…290 (era 212…290 com os slots de 36), em x 32…~142 — longe da
     barra de habilidades e das poções (x ≥ 190), do herói (x ≥ 192 com o arco do golpe), do painel do canto direito e
     dos cartões de loot. A FAIXA de cima é da pilha de toasts da corrida (hud.css `.toast-stack.is-explore`: x 4…164,
     desce de y 74): y 74…210 = 136, onde cabem 4 avisos de 3 linhas (4 × 32 + 3 × 2 = 134, medido no navegador com um
     texto de 84 letras) ou 2 dos erros mais longos do i18n (132 letras, 5 linhas). Com 3 pílulas a pilha subia a y 172
     e os 4 avisos de 3 linhas desciam a y 208 — medido, cobriam a de cima. Efeitos (status chips) empurram os toasts
     para y 105/134 e o aviso de rede mais 24: ainda cabem 3 avisos de 3 linhas sobre uma fileira de efeitos; além
     disso (duas fileiras + rede + avisos longos empilhados) o toast (z 110) passa por cima — o texto a ler ganha;
   - corrida com o painel do chat ABERTO (x 4…188, y 134…262): nem acima do painel (y 74…134 é a faixa dos toasts, dos
     efeitos e do aviso de rede) nem ao lado da base (o painel desce até y 262): a pilha vai para o CÉU à direita dele,
     x 192, em FILA (lado a lado, a mais nova à direita) a partir de y 80 — abaixo do combo (Exploração y 40…60, Torre
     64…74), da faixa da sala da Masmorra (y ≤ 47) e da barra de chefe (y ≤ 21) —, com teto 2: y 80…98, x 192…≤ 420
     (antes dos cartões de loot, x ≥ 487). Em coluna (y 80…158, com os slots de 36) o número de dano do chefe da Torre,
     que sobe até ~27 px (numberStyles.js: riseVy −80, gravity 120), passava a menos de 10 px do pé da 2.ª pílula. */
.work-yield-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 45;
}
.work-yields {
  --work-yield-cap: 3;
  position: absolute;
  left: calc(4 * var(--px));
  bottom: calc(34 * var(--px));
  display: flex;
  flex-direction: row;
  gap: calc(4 * var(--px)); /* em fila, 4: com 2 as pílulas vizinhas se liam como uma barra só */
  align-items: flex-end;
}
#ui-root:has(#hud) .work-yields {
  --work-yield-cap: 2;
  left: calc(32 * var(--px));
  bottom: calc(70 * var(--px));
  flex-direction: column;
  gap: calc(2 * var(--px));
  align-items: flex-start;
}
#ui-root:has(#hud):has(#chat:not(.hidden) > #chat-panel:not(.hidden)) .work-yields {
  left: calc(192 * var(--px));
  top: calc(80 * var(--px));
  bottom: auto;
  flex-direction: row;
  gap: calc(4 * var(--px)); /* com 2 as duas pílulas se liam como uma barra só */
}
/* O teto cai com pílulas no ar (entrou na corrida depois do lote): o widget só relê o teto no lote seguinte, então
   aqui a folha esconde na hora as mais ANTIGAS além de 2 (a mais nova é a última da pilha). */
#ui-root:has(#hud) .work-yields > .work-yield-pill:nth-last-child(n + 3) { display: none; }
/* LOBBY com janela aberta (revisão de 2026-10-01): a camada desce para BAIXO das janelas (z 10 + i, windowManager.js),
   acima da ilha e do botão do chat (z 8). As janelas do lobby nascem em y 50 (`fitLobbyTop`): as de 258 terminam em
   y 308, onde a faixa começa, e as de 276–280 (Armazém, Correio, Refino, Mascote e a família 592×276 em x 24 —
   Catálogo, Missões, Leilão, Talentos, Livro de receitas, Ranking, Refinaria) terminam em y 326–330 e ESCONDEM a faixa
   onde passam, inteira (o pé dela é y 326): o rodapé delas (Guardar, paginação…) não fica mais tapado por 4 s a cada
   entrega — o "você está ali fazendo alguma coisa e vem a notificação" do pedido do dono. O que a janela não cobre (o
   rosto da 1.ª pílula à esquerda de uma janela em x 24; a faixa inteira sob uma janela de 258) continua à vista. Com o
   resumo da corrida aberto a regra não vale: o véu dele (z 42) apagaria a entrega da volta (abaixo). */
#ui-root:has(#screen-lobby > section.window):not(:has(.summary-backdrop)) .work-yield-layer { z-index: 9; }
/* CARTA DO MAR aberta (`.is-node-map`, a barra de modos sai de cena): o FILTRO ocupa o canto esquerdo (`.node-map-filters`,
   x 4…190, y 306…356) e o ZOOM o direito (`.node-map-zoombox`, x 542…636 — carta v2, docs/specs/workers-nodes.md §7.13; até
   2026-10-02 era a legenda de 210×77), e a faixa ficaria POR CIMA deles — justo onde a entrega mais aparece (com a carta
   aberta o client sincroniza a cada fim de ciclo). A faixa vai para o MAR, entre os dois, com teto 2: x 218…≤ 530 (duas
   pílulas das largas). Ela não recebe ponteiro: passar sobre os pips da Garganta Cindida na Carta não tira nada do dedo. */
#ui-root:has(.screen-lobby.is-node-map) .work-yields { --work-yield-cap: 2; left: calc(218 * var(--px)); }
/* --- carta --- os TOASTS com a carta aberta: o pé em y 302, acima do filtro e do zoom. `#screen-lobby` (um id) é o que vence
   a regra do lobby de windows.css (`#ui-root:has(#screen-lobby) .toast-stack…`, especificidade 2,2,0); `--toast-floor` é o
   piso que `toast.js › place` lê — a coluna nunca desce abaixo dele, nem quando cobre o cartão (§7.13). */
#ui-root:has(#screen-lobby.is-node-map) .toast-stack:not(.is-explore) { bottom: calc(58 * var(--px)); --toast-floor: 58; }
/* RESUMO DA CORRIDA aberto (o painel em x 140…500, até y 324 no resumo cheio): a volta da corrida é a hora em que TODOS
   os trabalhadores entregam juntos, e em fila a 2.ª e a 3.ª pílula cruzavam a quina e a moldura de baixo do painel
   (x 140…246). Aqui a pilha vira COLUNA à esquerda dele, teto 2: x 4…≤ 140, y 292…330 — abaixo do botão do chat
   (y 266…290) e acima dos selos da barra —, por cima do véu (z 45 > 42): a entrega da volta não fica apagada. A pílula
   mais larga de todas (dois `×999`, `+N` e a moeda `−1.234`) mede 155 e passaria 19 px sobre a moldura do painel. */
#ui-root:has(.modal-backdrop.summary-backdrop) .work-yields {
  --work-yield-cap: 2;
  bottom: calc(30 * var(--px));
  flex-direction: column;
  gap: calc(2 * var(--px));
  align-items: flex-start;
}
#ui-root:has(.screen-lobby.is-node-map) .work-yields > .work-yield-pill:nth-last-child(n + 3),
#ui-root:has(.modal-backdrop.summary-backdrop) .work-yields > .work-yield-pill:nth-last-child(n + 3) { display: none; }
/* 18 de altura: 16 da figura + 1 de respiro em cima e embaixo */
.work-yield-pill {
  display: flex;
  align-items: center;
  min-height: calc(16 * var(--px));
  padding: calc(1 * var(--px)) calc(2 * var(--px)) calc(1 * var(--px)) calc(1 * var(--px));
  background: #0e0c14;
}
/* O ROSTO (workWindowBase.js › portraitMini): o retrato de 32 em 16, aro de 1 px na cor do GRAU (`.q<id>` dá a cor). */
.work-yield-face {
  flex: none;
  width: calc(16 * var(--px));
  height: calc(16 * var(--px));
  margin-right: calc(3 * var(--px)); /* o vão entre QUEM entregou e O QUE entregou */
  background-position: center;
  background-size: 100% 100%;
  background-repeat: no-repeat;
  image-rendering: pixelated;
  box-shadow: inset 0 0 0 var(--px) currentColor;
}
/* trabalhador demitido entre a liquidação e o aviso: a casinha vazia (a pílula não muda de forma) */
.work-yield-face.is-gone { background-color: rgba(0, 0, 0, 0.35); color: rgba(255, 255, 255, 0.08); }
/* um material: o mini-slot do banco (windows.css `.bankmat-ico`, selo de tier ↖) e a quantidade AO LADO (G1) */
.work-yield-mat { display: inline-flex; align-items: center; gap: calc(1 * var(--px)); }
.work-yield-mat + .work-yield-mat { margin-left: calc(3 * var(--px)); }
.work-yield-qty {
  font-size: var(--text-1);
  line-height: 1;
  color: var(--c-text);
  text-shadow: var(--px) var(--px) 0 #000;
  white-space: nowrap;
}
/* `+N`: materiais além de MAX_MATS (dentro da pílula) ou trabalhadores além do teto (pílula só de texto). Apagado:
   é resumo, não entrega — o que ele esconde está no `aria-label`. */
.work-yield-extra,
.work-yield-more {
  line-height: calc(10 * var(--px));
  color: var(--c-text-dim);
  text-shadow: var(--px) var(--px) 0 #000;
  white-space: nowrap;
}
.work-yield-extra { padding-left: calc(3 * var(--px)); }
.work-yield-more { padding: calc(1 * var(--px)) calc(3 * var(--px)); }
/* O SALÁRIO que o lote pagou sozinho (workers-nodes §6.4.1; era um toast à parte até 2026-10-01): a moeda de 9 e o `−N`
   no fim da última peça do lote, apagados — custo de rotina, não alarme. Um fio de 1 px separa o que SAIU do que
   ENTROU; na moeda sozinha (`.work-yield-paid`, lote só de salário) não há o que separar. */
.work-yield-wage {
  display: inline-flex;
  align-items: center;
  gap: calc(1 * var(--px));
  margin-left: calc(3 * var(--px));
  padding-left: calc(3 * var(--px));
  box-shadow: inset var(--px) 0 0 rgba(255, 255, 255, 0.16);
}
.work-yield-wage > .work-yield-qty { color: var(--c-text-dim); }
.work-yield-paid > .work-yield-wage { margin-left: calc(1 * var(--px)); padding-left: 0; box-shadow: none; }

/* entra SUBINDO em 3 degraus (150 ms); sai descendo em 4 (200 ms). Em fila, deslizar de lado passava a nova por cima
   da vizinha; subir do pé serve à fila do lobby e às colunas da corrida. */
.work-yield-pill.is-in { animation: work-yield-in 0.15s steps(3, jump-none) both; }
.work-yield-pill.is-out { animation: work-yield-out 0.2s steps(4, jump-none) both; }
@keyframes work-yield-in {
  from { transform: translateY(calc(6 * var(--px))); opacity: 0; }
  to   { transform: none; opacity: 1; }
}
@keyframes work-yield-out {
  from { transform: none; opacity: 1; }
  to   { transform: translateY(calc(4 * var(--px))); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .work-yield-pill.is-in, .work-yield-pill.is-out { animation: none; }
}
