/* island.css — a frente "ilha" da v2 (docs/specs/ui-v2.md §6.5 e §6.6): a parte 1, a OFICINA, e a parte 2, a GESTÃO (Construir,
   Trabalhadores, Capataz, Mascote). A oficina: o Armazém, a Oficina, o Refino, a Refinaria,
   a Bancada de Reparo, as Profissões e o Livro de receitas — as janelas clássicas HOSPEDADAS no modo fluido (`windowSheet › fluid`:
   o `--px` é o pixel de arte da v2 e a janela ocupa a folha). Inerte sem `html.ui-v2`. O que muda de lugar na instância é de
   `ui/v2/hostedIsland.js`; aqui, só o arranjo, o alvo do dedo (46, `--v2-target`) e a letra (16 no corpo, 13 na secundária). A conta
   é a do iPhone deitado no app (folha de 763 × 288 sem entalhe, 675 × 288 com ele) e a do SE (651 × 287). */

/* ---- o que as sete dividem: os botões, as abas e os campos na régua da v2 ---- */
html.ui-v2 :is(.v2-hosted-storage, .v2-hosted-craft, .v2-hosted-refine, .v2-hosted-temper, .v2-hosted-repair, .v2-hosted-professions, .v2-hosted-recipeBook, .v2-hosted-islandBuild, .v2-hosted-workers, .v2-hosted-hire, .v2-hosted-pet, .v2-hosted-node) .btn {
  --px: var(--ap);
  min-height: var(--v2-target);
  min-width: var(--v2-target);
  height: auto;
  padding: 0 calc(12 * var(--u));
  font-size: var(--v2-text);
}
html.ui-v2 :is(.v2-hosted-storage, .v2-hosted-recipeBook, .v2-hosted-islandBuild, .v2-hosted-pet) :is(.window-tabs, .filterbar-tabs) > :is(.tab, .btn) {
  --px: var(--ap);
  height: auto;
  min-height: var(--v2-target);
  min-width: var(--v2-target);
  padding: 0 calc(12 * var(--u));
  font-size: var(--v2-text);
}
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine, .v2-hosted-storage, .v2-hosted-recipeBook) :is(input.input, select) {
  --px: var(--ap);
  min-height: var(--v2-target);
  height: auto;
  font-size: max(16px, var(--v2-text));
}
/* o selo do nível do PRÉDIO (`widgets/plotUpgrade.js`) que sobe para o cabeçalho da folha: o alvo de 46, o desenho no pixel da v2 */
#ui2 .v2-sheet-head-tools .plot-chip {
  --px: var(--ap);
  min-height: var(--v2-target);
  min-width: var(--v2-target);
  justify-content: center;
  padding: 0 calc(10 * var(--u));
}

/* ================================================================================================================================
   OFICINA e REFINO — as receitas e o detalhe lado a lado; a fila de vagas (e o "Pronto") numa coluna à DIREITA, a do polegar. Em
   pé (a clássica), a fila é uma faixa embaixo: deitada, as colunas e a faixa somavam 315 px numa folha de 288, e o "Pronto" e as
   vagas caíam para fora
   ================================================================================================================================ */
html.ui-v2 .v2-hosted-craft > .craft-win,
html.ui-v2 .v2-hosted-refine > .refine-win {
  display: grid;
  /* a fila cede no estreito (24 % da folha: 158 com o entalhe), devolvendo largura à ficha */
  grid-template-columns: minmax(0, 1fr) clamp(150px, 24%, calc(184 * var(--u)));
  grid-template-rows: minmax(0, 1fr) auto;
  gap: var(--v2-gap);
  height: 100%;
  overflow: hidden;
}
html.ui-v2 :is(.v2-hosted-craft > .craft-win, .v2-hosted-refine > .refine-win) > .craft-columns { grid-column: 1; grid-row: 1 / -1; height: auto; min-height: 0; gap: var(--v2-gap); }
html.ui-v2 :is(.v2-hosted-craft > .craft-win, .v2-hosted-refine > .refine-win) > :is(.craft-locked, .refine-locked) { grid-column: 1; grid-row: 1 / -1; }
/* a Oficina: a fila é um bloco só (`craftQueueStrip.js`) — as vagas rolam, o "Pronto" fica no pé */
html.ui-v2 .v2-hosted-craft > .craft-win > .craft-queue { grid-column: 2; grid-row: 1 / -1; display: flex; flex-direction: column; gap: var(--v2-gap); min-height: 0; }
html.ui-v2 .v2-hosted-craft .craft-queue > .refine-slots { flex: 1 1 auto; }
html.ui-v2 .v2-hosted-craft .craft-queue > .refine-ready { flex: none; }
/* o Refino: as vagas e o "Pronto" são filhos do corpo */
html.ui-v2 .v2-hosted-refine > .refine-win > .refine-slots { grid-column: 2; grid-row: 1; }
html.ui-v2 .v2-hosted-refine > .refine-win > .refine-ready { grid-column: 2; grid-row: 2; }
/* as vagas: uma por linha, a coluna rola (as travadas embaixo) */
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .refine-slots {
  grid-template-columns: minmax(0, 1fr);
  grid-auto-rows: min-content;
  align-content: start;
  height: auto;
  min-height: 0;
  gap: calc(6 * var(--u));
  overflow-y: auto;
  overscroll-behavior: contain;
}
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .refine-card { height: auto; min-height: calc(56 * var(--u)); padding: calc(4 * var(--u)); gap: var(--v2-gap); }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .refine-card-text { line-height: 1.25; gap: calc(4 * var(--u)); }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) :is(.refine-seal, .refine-card-need) { font-size: var(--v2-text-small); line-height: 1.25; }
/* o "Pronto": o rótulo e o estoque numa linha, o "Coletar" inteiro embaixo */
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .refine-ready { flex-wrap: wrap; height: auto; gap: calc(4 * var(--u)) var(--v2-gap); font-size: var(--v2-text-small); }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .refine-ready > .refine-stock { flex: 1 1 auto; }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .refine-ready > .btn { flex: 1 1 100%; margin-left: 0; }

/* as colunas: a lista e o detalhe dividem a largura (o detalhe um pouco maior: ele tem o rodapé do Criar) */
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-left { width: auto; flex: 1 1 0; min-width: 0; gap: calc(4 * var(--u)); }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-detail { width: auto; flex: 1.15 1 0; min-width: 0; }
/* a letra de 16 pede a linha dela (a clássica trava a linha em 10 px de arte: as linhas se encavalavam) */
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) :is(.craft-detail-inner, .craft-row-text, .craft-head-text, .craft-mat-text, .refine-group-head) { line-height: 1.25; }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-row { height: auto; min-height: calc(52 * var(--u)); }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-row-sub { font-size: var(--v2-text-small); }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) :is(.craft-head-sub, .craft-head-exp) { font-size: var(--v2-text-small); }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-detail-inner { gap: calc(6 * var(--u)); }
/* os atributos da peça numa coluna (duas não cabem na largura do detalhe) */
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-stats { grid-template-columns: minmax(0, 1fr); row-gap: calc(2 * var(--u)); font-size: calc(15 * var(--u)); }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-mats { gap: calc(6 * var(--u)); }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-mat-name { font-size: calc(15 * var(--u)); }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-mats-head { font-size: var(--v2-text-small); }
/* o rodapé do Criar numa linha só — a quantidade, o "Máx", o tempo (letra secundária) e o Criar à direita (o polegar): em duas linhas
   ele tomava 130 dos 226 px do detalhe e os materiais rolavam por baixo dele. O "×" sai (o campo já diz quantos) */
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-foot { flex-wrap: nowrap; align-items: center; gap: calc(6 * var(--u)); padding-top: calc(6 * var(--u)); }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) :is(.craft-qty, .refine-foot-batches) { flex: none; gap: calc(6 * var(--u)); }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-qty-mark { display: none; }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) :is(.craft-units, .refine-batches) { width: calc(52 * var(--u)); padding: 0 calc(4 * var(--u)); text-align: center; }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-foot > .craft-time { flex: 1 1 auto; min-width: 0; margin-left: 0; text-align: right; font-size: var(--v2-text-small); }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-foot > :is(.btn, .craft-make-wrap) { flex: none; }
/* os filtros no CABEÇALHO (`hostedIsland.js › craftLayout`): "Só minha classe" (o interruptor em 2×, o alvo de 46), o espaço do
   equipamento e o tier, presos à direita antes do selo do prédio; o título cede */
#ui2 .v2-sheet-craft .v2-sheet-title { flex: 0 1 auto; min-width: calc(110 * var(--u)); }
#ui2 .v2-sheet-craft .v2-sheet-actions,
#ui2 .v2-sheet-craft .v2-sheet-head-tools { flex: 1 1 auto; min-width: 0; justify-content: flex-end; }
/* o rótulo é parte do alvo (o toque nele liga o interruptor): letra de AÇÃO, 16 (revisão P3-04) */
#ui2 .v2-sheet-craft .craft-myclass { --px: var(--ap); flex: 0 1 auto; min-width: 0; height: auto; min-height: var(--v2-target); gap: calc(6 * var(--u)); font-size: var(--v2-text); line-height: 1.1; }
#ui2 .v2-sheet-craft .craft-myclass > .toggle {
  flex: none;
  box-sizing: content-box;
  width: calc(32 * var(--ap));
  height: calc(20 * var(--ap));
  padding: calc((var(--v2-target) - 20 * var(--ap)) / 2) 0;
  background-origin: content-box;
  background-clip: content-box;
}
#ui2 .v2-sheet-craft #craft-myclass-label { flex: 0 100 auto; min-width: 0; max-width: calc(96 * var(--u)); white-space: normal; overflow: hidden; }
/* a largura em que "Todo espaço" e "Tier: todos" cabem inteiros na letra de 16 (a do conteúdo seguiria a opção mais longa) */
#ui2 .v2-sheet-craft :is(.craft-slot, .craft-tier) { --px: var(--ap); flex: 0 1 calc(136 * var(--u)); width: calc(136 * var(--u)); min-width: 0; min-height: var(--v2-target); height: auto; margin-left: 0; padding: 0 calc(6 * var(--u)); font-size: max(16px, var(--v2-text)); }

/* ================================================================================================================================
   ARMAZÉM — as duas grades (o cofre e a Mochila) rolam cada uma no seu lugar; as abas, as páginas e os baús no alvo de 46
   ================================================================================================================================ */
/* o corpo NÃO rola (a regra das fluidas, `v2.css › .v2-hosted.is-fluid > .window-body`, é mais específica: daí o `.is-fluid`) — quem
   rola é cada grade, e a fila de cima (as abas, os baús) e as páginas ficam paradas (revisão P3-06) */
html.ui-v2 .v2-hosted.is-fluid.v2-hosted-storage > .storage-body { overflow: hidden; gap: calc(4 * var(--u)); }
html.ui-v2 .v2-hosted-storage .storage-topbar { height: auto; min-height: var(--v2-target); gap: calc(6 * var(--u)); }
html.ui-v2 .v2-hosted-storage .storage-topbar > .tab { min-height: var(--v2-target); height: auto; padding: 0 calc(12 * var(--u)); font-size: var(--v2-text); }
html.ui-v2 .v2-hosted-storage :is(.bank-tab, #storage-buy-tab, #storage-tab-icon) { width: var(--v2-target); height: var(--v2-target); }
html.ui-v2 .v2-hosted-storage .storage-topbar .bank-tabs { gap: calc(6 * var(--u)); }
html.ui-v2 .v2-hosted-storage .storage-body > div:not(.storage-topbar) { flex: 1 1 auto; min-height: 0; align-items: stretch; }
/* a coluna estica até o pé da fileira (o `align-items: flex-start` vem no estilo do elemento, `storage.js`: o `align-self` do filho o
   vence), e a grade dentro dela rola */
html.ui-v2 .v2-hosted-storage .storage-col { min-height: 0; align-self: stretch; gap: calc(2 * var(--u)); }
html.ui-v2 .v2-hosted-storage .storage-label { min-height: var(--v2-target); line-height: 1.25; font-size: var(--v2-text-small); gap: var(--v2-gap); }
html.ui-v2 .v2-hosted-storage .storage-label > .grid-pager { gap: calc(6 * var(--u)); }
html.ui-v2 .v2-hosted-storage .storage-label > .grid-pager > .grid-tab { height: var(--v2-target); min-width: var(--v2-target); font-size: var(--v2-text); }
html.ui-v2 .v2-hosted-storage :is(.storage-grid-host, .storage-col > .item-grid-wrap) { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
html.ui-v2 .v2-hosted-storage .window-footer { gap: var(--v2-gap); }

/* ================================================================================================================================
   LIVRO DE RECEITAS — a busca e o tier no cabeçalho (`hostedIsland.js`); no corpo, a fila das profissões com o "Só o que posso
   criar", a lista numa coluna de linhas de 48 (o ícone em 2×, o nome inteiro) e a ficha ao lado
   ================================================================================================================================ */
#ui2 .v2-sheet-recipeBook .v2-sheet-title { flex: 0 1 auto; min-width: 0; }
#ui2 .v2-sheet-recipeBook .v2-sheet-actions,
#ui2 .v2-sheet-recipeBook .v2-sheet-head-tools { flex: 1 1 auto; min-width: 0; justify-content: flex-end; }
#ui2 .v2-sheet-head-tools #rb-tier {
  --px: var(--ap);
  flex: none;
  min-height: var(--v2-target);
  height: auto;
  max-width: calc(150 * var(--u));
  padding: 0 calc(10 * var(--u));
  font-size: var(--v2-text);
}
html.ui-v2 .v2-hosted-recipeBook .rb-body { gap: var(--v2-gap); font-size: var(--v2-text); }
html.ui-v2 .v2-hosted-recipeBook .filterbar { height: auto; min-height: var(--v2-target); flex-wrap: wrap; gap: var(--v2-gap); margin: 0; }
html.ui-v2 .v2-hosted-recipeBook .filterbar-tabs { gap: calc(6 * var(--u)); flex-wrap: wrap; }
html.ui-v2 .v2-hosted-recipeBook .rb-toggle { min-height: var(--v2-target); gap: calc(6 * var(--u)); font-size: var(--v2-text); line-height: 1.15; margin-left: auto; }
/* no SE a fila das abas e o "Só o que posso fazer" cabem numa linha (o rótulo em duas): numa linha própria, a lista ficava com 3
   receitas à vista (revisão P3-13) */
html.ui-v2 .v2-hosted-recipeBook .rb-toggle > :last-child { max-width: calc(130 * var(--u)); white-space: normal; }
html.ui-v2 .v2-hosted-recipeBook .filterbar-tabs > :is(.tab, .btn) { padding: 0 calc(10 * var(--u)); }
html.ui-v2 .v2-hosted-recipeBook .rb-toggle > .toggle {
  flex: none;
  box-sizing: content-box;
  width: calc(32 * var(--ap));
  height: calc(20 * var(--ap));
  padding: calc((var(--v2-target) - 20 * var(--ap)) / 2) 0;
  background-origin: content-box;
  background-clip: content-box;
}
html.ui-v2 .v2-hosted-recipeBook .rb-content { gap: calc(12 * var(--u)); min-width: 0; }
/* a coluna da lista e a ficha SEMPRE lado a lado: sem receita escolhida, a clássica abre a lista em duas colunas e encolhe a ficha
   (`recipeBook.js › setWide`, estilo no elemento — daí o `!important`); no celular os nomes quebravam em três linhas */
html.ui-v2 .v2-hosted-recipeBook .rb-listcol { width: auto !important; flex: 1.1 1 0 !important; min-width: 0; }
html.ui-v2 .v2-hosted-recipeBook .rb-list { display: grid !important; grid-template-columns: minmax(0, 1fr) !important; align-content: start; gap: calc(4 * var(--u)); }
/* a linha em 48: o ícone em 2× (o `--px` da linha), o nome por inteiro em até duas linhas, o nível na letra secundária */
html.ui-v2 .v2-hosted-recipeBook .rb-row { --px: calc(var(--ap) * 1.5); height: auto; min-height: calc(48 * var(--u)); gap: var(--v2-gap); padding: calc(4 * var(--u)); }
html.ui-v2 .v2-hosted-recipeBook .rb-row-name { white-space: normal; line-height: 1.2; font-size: var(--v2-text); }
html.ui-v2 .v2-hosted-recipeBook .rb-row-level { font-size: var(--v2-text-small); }
html.ui-v2 .v2-hosted-recipeBook .rb-sheet { flex: 1 1 0 !important; min-width: 0; gap: calc(6 * var(--u)); font-size: calc(15 * var(--u)); line-height: 1.3; }
/* o material da receita é um BOTÃO (abre o "Onde conseguir" dele): a linha no alvo de 46, o ícone em 1,5×, o nome inteiro */
html.ui-v2 .v2-hosted-recipeBook .rb-mat { --px: calc(var(--ap) * 1.5); min-height: var(--v2-target); gap: var(--v2-gap); }
html.ui-v2 .v2-hosted-recipeBook .rb-mat-name { white-space: normal; line-height: 1.2; }
html.ui-v2 .v2-hosted-recipeBook .rb-mat-have { font-size: var(--v2-text-small); }
/* o "Abrir na oficina", a ÚNICA ação da ficha, preso no pé dela, à direita (o polegar): ele morava 190 px abaixo da tela, no fim
   da ficha que rola (revisão P3-05) */
html.ui-v2 .v2-hosted-recipeBook .rb-sheet { padding-bottom: 0 !important; --scroll-fade-pad: 0px; --scroll-fade: 0px; }
html.ui-v2 .v2-hosted-recipeBook .rb-actions { position: sticky; bottom: 0; z-index: 1; display: flex; justify-content: flex-end; flex: none; margin-top: auto; padding-top: calc(6 * var(--u)); background: var(--v2-bg); }
html.ui-v2 .v2-hosted-recipeBook .window-footer { font-size: var(--v2-text-small); }
/* buscando com o teclado aberto (§3.2): a fila das abas e o rodapé saem, o resultado fica */
html.ui-v2.v2-kb #ui2 .v2-sheet-recipeBook:has(.v2-sheet-head :focus) :is(.rb-body > .filterbar, .window-footer) { display: none; }

/* ================================================================================================================================
   PROFISSÕES — um cartão por profissão; o "Livro" no alvo comum
   ================================================================================================================================ */
html.ui-v2 .v2-hosted-professions :is(.prof-row, .prof-card) { line-height: 1.25; }

/* ================================================================================================================================
   REFINARIA — a ficha da peça, o palco (a bigorna) e os ritos. Os ritos ganham a coluna mais larga (a do polegar): as cinco abas de
   ícone dividem a largura (a 5.ª, "Corromper", saía pela borda com 3 mm), as opções em linhas de 46 e o "lançar" (a chance e o
   preço) preso no pé da coluna, que rola por baixo dele
   ================================================================================================================================ */
html.ui-v2 .v2-hosted-temper > .temper-body:not(.is-door) {
  /* a coluna dos ritos com piso de 5 abas de 46 + 4 vãos de 8 (262): com o entalhe as abas se encavalavam (revisão P3-10); o palco cede */
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr) clamp(262px, 34%, calc(300 * var(--u)));
  gap: var(--v2-gap);
  line-height: 1.25;
}
html.ui-v2 .v2-hosted-temper .temper-side { overflow-y: auto; overscroll-behavior: contain; gap: calc(6 * var(--u)); }
/* as abas presas no alto da coluna que rola: o rito em que se está fica à vista (revisão P3-11) */
html.ui-v2 .v2-hosted-temper .temper-tabs { position: sticky; top: 0; z-index: 1; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: var(--v2-gap); padding-bottom: calc(4 * var(--u)); background: var(--v2-bg); }
html.ui-v2 .v2-hosted-temper .temper-tabs > .tab.tab { width: auto; min-width: 0; height: var(--v2-target); padding: 0; justify-content: center; }
html.ui-v2 .v2-hosted-temper .temper-opts { gap: var(--v2-gap); }
html.ui-v2 .v2-hosted-temper .temper-opt { height: auto; min-height: var(--v2-target); padding: 0 calc(8 * var(--u)); gap: var(--v2-gap); }
html.ui-v2 .v2-hosted-temper .temper-opt-label { line-height: 1.2; }
html.ui-v2 .v2-hosted-temper .temper-detail { flex: none; font-size: calc(15 * var(--u)); }
html.ui-v2 .v2-hosted-temper .temper-cast { order: 9; position: sticky; bottom: 0; z-index: 1; display: flex; align-items: center; gap: var(--v2-gap); padding-top: calc(4 * var(--u)); background: var(--v2-bg); }
/* o nome do rito escolhido ao lado do preço (`hostedIsland.js › temperLayout`): o botão diz só "◎ 181" */
html.ui-v2 .v2-hosted-temper .v2-temper-rite { flex: 1 1 auto; min-width: 0; color: var(--c-gold); font-size: var(--v2-text-small); line-height: 1.2; }
html.ui-v2 .v2-hosted-temper .temper-cast > :is(.temper-cast-chance, .btn) { flex: none; }
html.ui-v2 .v2-hosted-temper .temper-ficha { gap: calc(6 * var(--u)); }
html.ui-v2 .v2-hosted-temper .temper-bench-foot { gap: calc(6 * var(--u)); }
html.ui-v2 .v2-hosted-temper .temper-badge { line-height: 1.25; }

/* ---- as telas ESTREITAS (o SE, o iPhone com entalhe): o arranjo segue a largura que a coluna tem de verdade (`@container`) ---- */
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) :is(.craft-left, .craft-detail) { container-type: inline-size; }
/* o detalhe estreito: o Criar desce para uma linha inteira (o polegar), os materiais numa coluna (nunca o nome partido no meio) */
/* o detalhe estreito (o entalhe, o SE): o TEMPO sai do rodapé (ele está no `aria-label` do Criar) e o rodapé fica numa linha —
   descendo, o Criar cobria os materiais (revisão P3-09); os materiais numa coluna e a legenda "tenho / preciso" sai */
@container (max-width: 279px) {
  html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-foot > .craft-time { display: none; }
  html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-foot > .btn { flex: 1 1 auto; }
  html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-mats { grid-template-columns: minmax(0, 1fr); }
  html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-mats-head > .text-dim { display: none; }
}
/* mais estreito ainda: o Criar desce para uma linha inteira (o último recurso) */
@container (max-width: 239px) {
  html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-foot { flex-wrap: wrap; }
  html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-foot > .btn { flex: 1 1 100%; }
}
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine) .craft-mat-name { overflow-wrap: break-word; }
/* o Armazém estreito: as duas grades de seis encolhem o pixel delas só o que falta para caber lado a lado (o `cqw` é a largura da
   fileira das grades); no iPhone sem entalhe fica o pixel da v2 */
html.ui-v2 .v2-hosted-storage .storage-body > div:not(.storage-topbar) { container-type: inline-size; }
/* SEM arredondar ao pixel do aparelho: no SE (passo de 0,5 px CSS) o múltiplo abaixo de 1,33 é 1,0 — casas de 36 px, 5,6 mm, abaixo
   do alvo. O alvo do dedo vence o pixel inteiro (§2, a exceção do Armazém estreito; revisão P3-13 medida e recusada) */
html.ui-v2 .v2-hosted-storage .item-grid-wrap { --px: min(var(--ap), calc((100cqw - 44px) / 456)); }

/* ---- o PAINEL DE MELHORIA do prédio (`widgets/plotUpgrade.js`, aberto pelo selo do cabeçalho) na Oficina, no Refino e na
   Refinaria: os materiais do custo são AÇÕES (o toque abre o "Onde conseguir" — o que falta é o que o jogador vai tocar), em linhas
   de 46 com o ícone em 1,5×; o "▲ Melhorar", que gasta, a 16 deles (revisão P3-03: eram agulhas de 3,8 mm a 0,7 mm do botão) ---- */
/* mais alto que a folha deitada: o painel rola e o "▲ Melhorar" fica preso no pé dele */
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine, .v2-hosted-temper) .plot-up { gap: var(--v2-gap); line-height: 1.25; max-height: 100%; overflow-y: auto; overscroll-behavior: contain; }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine, .v2-hosted-temper) .plot-up .ib-cost { gap: calc(6 * var(--u)); }
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine, .v2-hosted-temper) .plot-up .ib-mat {
  --px: calc(var(--ap) * 1.5);
  min-height: var(--v2-target);
  min-width: var(--v2-target);
  height: auto;
  align-items: center;
  font-size: var(--v2-text-small);
}
html.ui-v2 :is(.v2-hosted-craft, .v2-hosted-refine, .v2-hosted-temper) #plot-up-do { margin-top: calc(16 * var(--u)); position: sticky; bottom: 0; flex: none; }

/* a aba MATERIAIS do Armazém (o banco de materiais, `bankMaterials.js`): as linhas são AÇÕES (o toque abre o "Retirar"), em 46 com
   o ícone em 1,5× e 8 de vão; as abas de grupo no alvo de 46; a caixa toma a fileira inteira (a clássica a trava em 226 × 188 de
   arte) e a lista rola nela (revisão P3-07: linhas de 3,8 mm coladas) */
/* a caixa estica até o pé da fileira (o mesmo `align-items` no estilo do elemento do P3-06) e ROLA INTEIRA: deitado, a fileira tem
   184 px, e os grupos, a busca e o aviso parados deixavam 20 px para a lista — só o 1.º material à vista, o resto embaixo do rodapé
   (revisão P3-15). Rolando, os grupos e a busca sobem junto, como toda lista com busca no topo */
html.ui-v2 .v2-hosted-storage .bankmat { width: auto; height: auto; flex: 1 1 auto; align-self: stretch; display: flex; flex-direction: column; min-height: 0; gap: calc(6 * var(--u)); overflow-y: auto; overscroll-behavior: contain; }
html.ui-v2 .v2-hosted-storage .bankmat > * { flex: none; }
html.ui-v2 .v2-hosted-storage .bankmat-notice { font-size: var(--v2-text-small); line-height: 1.25; }
html.ui-v2 .v2-hosted-storage .bankmat-cats { flex-wrap: wrap; gap: calc(6 * var(--u)); }
html.ui-v2 .v2-hosted-storage .bankmat-cat { --px: var(--ap); min-width: var(--v2-target); height: var(--v2-target); }
/* a lista na altura natural (o `#bankmat-list { flex: 1 }` da clássica a espremia em 54 px) e sem o degradê de rolagem dela (quem rola é a
   caixa: a máscara apagava as linhas além da caixa da lista) */
html.ui-v2 .v2-hosted-storage #bankmat-list { flex: none; display: grid; align-content: start; gap: calc(8 * var(--u)); height: auto; min-height: auto; max-height: none; overflow: visible; padding-bottom: 0; -webkit-mask-image: none; mask-image: none; }
html.ui-v2 .v2-hosted-storage .bankmat-row { --px: calc(var(--ap) * 1.5); min-height: var(--v2-target); gap: var(--v2-gap); line-height: 1.25; }

/* ---- os vãos de 8 entre vizinhos (§2) nos cabeçalhos com campos: a busca e o tier do Livro estavam a 2 px (revisão P3-10) ---- */
#ui2 :is(.v2-sheet-recipeBook, .v2-sheet-craft) .v2-sheet-head-tools { gap: var(--v2-gap); }

/* ---- BANCADA DE REPARO: o nome da peça inteiro (a linha da clássica, 10 px de arte, encavalava as duas linhas da letra de 16) ----
   (revisão P3-08) */
html.ui-v2 .v2-hosted-repair .rp-row-name { line-height: 1.2; -webkit-line-clamp: 3; }
/* PROFISSÕES: o número da exp dentro da barra (a letra transbordava a barra de 13 px) */
html.ui-v2 .v2-hosted-professions .prof-bar .bar { height: calc(18 * var(--u)); }
html.ui-v2 .v2-hosted-professions .prof-bar .bar-label { line-height: 1; font-size: var(--v2-text-small); }

/* ================================================================================================================================
   A GESTÃO (§6.6) — o Construir, os Trabalhadores, o Capataz e o Mascote: a régua comum dos botões e das abas (acima) e
   o que cada uma tem de próprio
   ================================================================================================================================ */
/* TRABALHADORES: cada cama (uma ação: a livre abre o Capataz, a ocupada mostra o trabalhador) numa linha de 46 com 8 de vão */
html.ui-v2 .v2-hosted-workers .workers-row { min-height: var(--v2-target); height: auto; margin-bottom: var(--v2-gap); line-height: 1.25; }
/* a 2.ª linha da ficha da lista: o selo ("Armazém cheio", "Sem pagamento", "Em promoção") abrevia e o salário nunca encolhe — com
   o selo inteiro o "◎ 12" saía pela direita e virava "◎ 1" (revisão P4-19) */
html.ui-v2 .v2-hosted-workers .workers-row-sub { min-width: 0; }
html.ui-v2 .v2-hosted-workers .workers-row-sub > .workers-seal { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html.ui-v2 .v2-hosted-workers .workers-row-sub > .gold-label { flex: none; }
/* o "Pagamento automático" (o selo que acende quando o ouro está saindo) no alvo de 46, o selo no centro (a clássica estende a
   área com um ::after de 24; aqui a caixa é o alvo) */
html.ui-v2 .v2-hosted-workers .work-wage-switch { width: var(--v2-target); height: var(--v2-target); margin-right: 0; }
html.ui-v2 .v2-hosted-workers .work-wage-switch::after { content: none; }
html.ui-v2 .v2-hosted-workers #workers-wage-strip { gap: var(--v2-gap); }
/* a FICHA do trabalhador em duas regiões (`hostedIsland.js › workersLayout`): o conteúdo rola em cima e as AÇÕES moram num pé fixo
   embaixo, FORA do rolador — presas no pé dentro dele, cobriam a tira do salário e o "Pagamento automático" (revisão P4-17); numa
   linha só (o "×N" das tentativas é o contador no canto do "Promover": revisão P4-20). O "Demitir" à esquerda, a 16 das outras, e
   o "Atribuir…"/o "Promover" à direita, no polegar (revisão P4-05) */
html.ui-v2 .v2-hosted-workers .v2-workers-side { flex: 1 1 0; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
html.ui-v2 .v2-hosted-workers #workers-sheet { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
html.ui-v2 .v2-hosted-workers .v2-workers-foot { flex: none; }
html.ui-v2 .v2-hosted-workers .v2-workers-foot:empty { display: none; }
/* 16 entre a borda da área que rola e o pé: o que a rolagem corta ali (o interruptor do salário) ficava a 6 do "Demitir" */
html.ui-v2 .v2-hosted-workers #workers-actions { flex-wrap: nowrap; justify-content: flex-end; gap: var(--v2-gap); margin-top: 0; padding-top: calc(16 * var(--u)); }
html.ui-v2 .v2-hosted-workers #workers-actions > .btn { flex: 0 1 auto; min-width: 0; }
html.ui-v2 .v2-hosted-workers #workers-promote { position: relative; overflow: visible; }
html.ui-v2 .v2-hosted-workers #workers-promote > #workers-attempts { position: absolute; top: calc(-6 * var(--u)); right: calc(-4 * var(--u)); padding: 0 calc(4 * var(--u)); border-radius: calc(6 * var(--u)); background: var(--v2-bg); font-size: var(--v2-text-small); line-height: 1.3; pointer-events: none; }
/* o 16 do "Demitir" é DELE (a margem) e a sobra vai num espaçador elástico depois dele: com `margin-right: auto` e o `+ *` (o irmão do
   DOM, que não existe — o Demitir é o último) o vão caía para 8 no SE (revisão P4-29) */
html.ui-v2 .v2-hosted-workers #workers-dismiss { order: -1; margin-right: calc(16 * var(--u)); }
html.ui-v2 .v2-hosted-workers #workers-actions::after { content: ""; order: -1; flex: 1 1 0; }
html.ui-v2 .v2-hosted-workers #workers-actions > .btn { padding-left: calc(10 * var(--u)); padding-right: calc(10 * var(--u)); }
/* o "Atribuir…": a lista das ilhas num modal, fora da folha — cada linha manda o trabalhador, no
   alvo de 46 com 8 de vão (eram 26 px a 2,7 px: o vizinho da borda mandava para a ilha errada — revisão P4-06) */
html.ui-v2 .modal-backdrop .work-picker { --px: var(--ap); gap: var(--v2-gap); max-height: min(60vh, calc(240 * var(--v2-u))); }
html.ui-v2 .modal-backdrop .work-picker > .btn { min-height: var(--v2-target); height: auto; font-size: var(--v2-text); }
/* CAPATAZ: o cartão do candidato COMPACTO — o retrato ao lado do nome e do tipo, os números embaixo, o preço e o "Contratar" (no
   alvo de 46) numa linha no pé. Em coluna, o cartão pedia 301 px num espaço de 234 e o "Contratar" nascia embaixo do rodapé, sem
   sinal de que o corpo rolava (revisão P4-03) */
html.ui-v2 .v2-hosted-hire .hire-card { display: grid; grid-template-columns: auto minmax(0, 1fr); align-content: start; align-items: center; column-gap: var(--v2-gap); row-gap: calc(4 * var(--u)); padding: calc(6 * var(--u)); line-height: 1.2; text-align: left; }
html.ui-v2 .v2-hosted-hire .hire-card > :first-child { grid-column: 1; grid-row: 1 / 3; }
html.ui-v2 .v2-hosted-hire .hire-card > :is(.hire-name, .hire-sub) { grid-column: 2; }
html.ui-v2 .v2-hosted-hire .hire-sub { font-size: var(--v2-text-small); }
html.ui-v2 .v2-hosted-hire .hire-card > :is(.hire-stats, .hire-skill, .hire-skill-desc) { grid-column: 1 / -1; }
html.ui-v2 .v2-hosted-hire .hire-stats { font-size: calc(15 * var(--u)); padding: 0; row-gap: 0; }
html.ui-v2 .v2-hosted-hire :is(.hire-skill, .hire-skill-desc) { font-size: var(--v2-text-small); }
html.ui-v2 .v2-hosted-hire .hire-card > .hire-cost { grid-column: 1; margin-top: 0; }
html.ui-v2 .v2-hosted-hire .hire-card > .btn { grid-column: 2; width: 100%; min-height: var(--v2-target); }
/* o rodapé: os atalhos sem a tecla no aparelho de toque (`hostedIsland.js › hireLayout`) e o texto que cabe no botão */
html.ui-v2 .v2-hosted-hire .hire-footer > .btn { flex: none; }
html.ui-v2 .v2-hosted-hire .hire-footer > .hire-reroll { flex: 0 1 auto; min-width: 0; }
html.ui-v2 .v2-hosted-hire .hire-footer > .hire-reroll > .btn { max-width: 100%; white-space: normal; line-height: 1.15; }
html.ui-v2 .v2-hosted-hire .window-footer { gap: var(--v2-gap); }

/* ================================================================================================================================
   MASCOTE (a v4: Equipe · Canil · Troca · Alfa). As duas colunas de cada aba ficam SEMPRE lado a lado e CADA UMA rola sozinha —
   a lista à esquerda, o painel à direita com as ações presas no pé dele. As larguras são da v2 (`--u`), não as de arte da clássica
   (que somavam a folha inteira do iPhone sem entalhe e cortavam a da direita com o entalhe). Rolar a ÁREA inteira com as colunas
   quebrando (a 1.ª tentativa) tirava o rolador do alforje, cortava o pé do canil e jogava a ficha para fora da tela (revisão P4-18,
   P4-22, P4-23, P4-24, P4-25)
   ================================================================================================================================ */
html.ui-v2 .v2-hosted-pet .pet-pane { min-width: 0; min-height: 0; overflow: hidden; }
html.ui-v2 .v2-hosted-pet .pet-split { width: 100%; min-width: 0; height: 100%; flex-wrap: nowrap; gap: var(--v2-gap); }
html.ui-v2 .v2-hosted-pet .pet-divider { display: none; }
/* a lista (Canil, Troca, Alfa) estreita; a ficha com o resto */
html.ui-v2 .v2-hosted-pet #pet-left { flex: 0 1 calc(210 * var(--u)); width: auto; min-width: 0; min-height: 0; }
html.ui-v2 .v2-hosted-pet #pet-right { flex: 1 1 0; width: auto; min-width: 0; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
/* a Equipe ao contrário: os cartões com o resto, o alforje numa coluna de 220 */
html.ui-v2 .v2-hosted-pet .pet-team-left#pet-left { flex: 1 1 0; overflow-y: auto; overscroll-behavior: contain; }
/* o alforje: a coluna pede as 5 casas (5 × 36 de arte) e cede até 4 — as casas em grade (as fileiras de 5 da clássica viram
   `display: contents`), nunca uma casa cortada ao meio pela borda da coluna (revisão P4-26: a 5.ª coluna com 28 de 48 px à vista) */
html.ui-v2 .v2-hosted-pet .pet-team-right#pet-right { flex: 0 1 calc(5 * 36 * var(--px) + 12 * var(--u)); min-width: calc(4 * 36 * var(--px) + 12 * var(--u)); display: flex; flex-direction: column; }
html.ui-v2 .v2-hosted-pet .pet-pouch { width: auto; margin: 0; display: grid; grid-template-columns: repeat(auto-fill, calc(36 * var(--px))); justify-content: center; align-content: start; }
html.ui-v2 .v2-hosted-pet .pet-pouch-row { display: contents; }
html.ui-v2 .v2-hosted-pet .pet-team-row { gap: var(--v2-gap); }
html.ui-v2 .v2-hosted-pet .pet-team-card { flex: 1 1 0; min-width: 0; width: auto; }
/* no estreito (o SE) o cartão fica menor que o palco de arte (110 × 70): o palco, a barra de EXP e a linha do grau acompanham a largura do
   cartão — com o palco fixo os cartões se sobrepunham e o "Nv 20" ia para trás do selo do vizinho (revisão P4-26) */
html.ui-v2 .v2-hosted-pet .pet-team-card > .pet-team-stage { width: 100%; max-width: calc(110 * var(--px)); }
html.ui-v2 .v2-hosted-pet .pet-team-card .pet-team-exp { width: 100%; max-width: calc(108 * var(--px)); }
html.ui-v2 .v2-hosted-pet .pet-team-id { flex-wrap: wrap; justify-content: center; row-gap: calc(2 * var(--u)); max-width: 100%; }
/* a trilha das habilidades da equipe (260 de arte) encolhe até caber na coluna: no SE ela passava das duas bordas e o 1.º e o 5.º nós
   saíam cortados ao meio (o pixel fracionado é a exceção do `cqw`, a mesma do Armazém, docs/specs/ui-v2.md §6.5) */
html.ui-v2 .v2-hosted-pet .pet-team-detail { container-type: inline-size; }
html.ui-v2 .v2-hosted-pet .pet-team-detail > .pet-track { --px: min(var(--ap), calc(100cqw / 262)); }
/* o nome da raça quebra no hífen ("Raposa-de-" / "alforje") em vez de passar da borda do cartão (revisão P4-22) */
html.ui-v2 .v2-hosted-pet .pet-team-name { max-width: 100%; white-space: normal; overflow-wrap: anywhere; text-align: center; line-height: 1.15; }
/* o retrato do mascote em 2/3 no deitado (o cartão da equipe e a cabeça da ficha): os 32 px que sobram são a soma da equipe e o
   "Treinar" à vista */
html.ui-v2 .v2-hosted-pet :is(.pet-team-card, .pet-card-head) .pet-frame { --px: calc(var(--ap) * 0.67); }
html.ui-v2 .v2-hosted-pet .pet-pouch { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
/* as listas: linhas de 46 com 8 de vão, cada uma rola */
html.ui-v2 .v2-hosted-pet .pet-list { min-height: 0; overflow-y: auto; overscroll-behavior: contain; gap: var(--v2-gap); }
html.ui-v2 .v2-hosted-pet .pet-row { min-height: var(--v2-target); height: auto; line-height: 1.2; }
/* o painel da direita (a ficha do Canil, a Troca, o Alfa) rola sozinho; as AÇÕES moram no pé, fora dele (abaixo) */
html.ui-v2 .v2-hosted-pet :is(.pet-ex, .pet-alpha) { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; gap: calc(6 * var(--u)); }
html.ui-v2 .v2-hosted-pet .pet-ex-skills { flex: none; }
/* o pé das ações FORA do rolador do painel (`hostedIsland.js › petLayout`), a 16 da borda dele (o "Trocar N por 1" é perigo) */
html.ui-v2 .v2-hosted-pet .pet-ex-actions { flex: none; justify-content: flex-end; gap: var(--v2-gap); margin-top: 0; padding-top: calc(16 * var(--u)); }
/* o Canil: a ficha (ou a ninhada) rola, o pé ("Catálogo", "Chamar ninhada") fixo embaixo da coluna */
html.ui-v2 .v2-hosted-pet .pet-kennel-main { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; align-items: flex-start; }
html.ui-v2 .v2-hosted-pet .pet-foot { flex: none; gap: var(--v2-gap); padding-top: var(--v2-gap); }
/* o "Dispensar" (perigo) à esquerda, a 16 do "Pôr na equipe" (o lado do polegar) */
html.ui-v2 .v2-hosted-pet #pet-release { order: -1; margin-right: calc(16 * var(--u)); }
/* a Troca: a aparência que fica (peças de 46) e as habilidades a marcar (linhas de 46), 8 de vão */
html.ui-v2 .v2-hosted-pet .pet-ex-keep { gap: var(--v2-gap); flex-wrap: wrap; }
html.ui-v2 .v2-hosted-pet .pet-ex-face { min-width: var(--v2-target); min-height: var(--v2-target); }
html.ui-v2 .v2-hosted-pet .pet-ex-skills { gap: var(--v2-gap); overflow: visible; }
html.ui-v2 .v2-hosted-pet .pet-skill-chip { min-height: var(--v2-target); }
/* o Alfa: os materiais do treino (cada um abre o "Onde conseguir") em linhas de 46, o ícone em 1,5× */
html.ui-v2 .v2-hosted-pet .pet-alpha-cost { gap: calc(4 * var(--u)) var(--v2-gap); }
html.ui-v2 .v2-hosted-pet .pet-alpha-mat { --px: calc(var(--ap) * 1.5); min-height: var(--v2-target); font-size: var(--v2-text-small); }
html.ui-v2 .v2-hosted-pet :is(.pet-alpha-perk, .pet-alpha-need) { line-height: 1.25; }
/* o catálogo das raças em linhas (o ícone à esquerda, o nome numa linha ao lado): na grade de 2, os nomes partidos em três
   linhas caíam sobre o ícone de baixo (revisão P4-16) */
html.ui-v2 .v2-hosted-pet .pet-catalog { grid-template-columns: minmax(0, 1fr); gap: var(--v2-gap); overflow-y: auto; }
html.ui-v2 .v2-hosted-pet .pet-cat { width: auto; height: auto; min-height: var(--v2-target); flex-direction: row; justify-content: flex-start; gap: var(--v2-gap); }
html.ui-v2 .v2-hosted-pet .pet-cat-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* o modal "no lugar de quem?" (a equipe cheia): cada mascote numa linha de 46 com 8 de vão (o toque troca direto) */
html.ui-v2 .modal-backdrop .pet-swap { gap: var(--v2-gap); }
html.ui-v2 .modal-backdrop .pet-swap-btn { --px: var(--ap); min-height: var(--v2-target); font-size: var(--v2-text); }

/* a NINHADA: cada filhote inteiro (o retrato menor à esquerda, o nome em até duas linhas, o grau e os números à direita, o
   "Escolher" embaixo) — o "Escolher" é definitivo (os outros dois se perdem) e, rolado até ele, o filhote saía da vista (revisão
   P4-12); o "Dispensar ninhada" (perigo) à esquerda, a 16 dos cartões, longe do polegar */
html.ui-v2 .v2-hosted-pet :is(.pet-litter-box, .pet-litter) { flex: none; min-height: auto; }
html.ui-v2 .v2-hosted-pet .pet-litter-box { width: 100%; padding-bottom: calc(4 * var(--u)); }
html.ui-v2 .v2-hosted-pet .pet-litter { gap: var(--v2-gap); }
html.ui-v2 .v2-hosted-pet .pet-pup { width: auto; flex: 1 1 0; min-width: 0; display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; align-content: start; column-gap: calc(6 * var(--u)); row-gap: calc(2 * var(--u)); text-align: left; line-height: 1.2; }
html.ui-v2 .v2-hosted-pet .pet-pup > .pet-frame { --px: calc(var(--ap) * 0.6); grid-column: 1; grid-row: 1 / 5; }
html.ui-v2 .v2-hosted-pet .pet-pup > :not(.pet-frame, .btn) { grid-column: 2; justify-self: start; min-width: 0; max-width: 100%; }
html.ui-v2 .v2-hosted-pet .pet-pup-race { min-height: 0; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; font-size: calc(15 * var(--u)); line-height: 1.15; }
html.ui-v2 .v2-hosted-pet .pet-pup > :is(.pet-grade, .pet-pup-sig, .pet-pup-cells) { font-size: var(--v2-text-small); }
/* o selo do grau não passa do cartão ("Grau Obra-prima" saía da tela no 3.º filhote) */
html.ui-v2 .v2-hosted-pet .pet-pup > .pet-grade { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html.ui-v2 .v2-hosted-pet .pet-pup > .btn { grid-column: 1 / -1; grid-row: 5; width: 100%; margin-top: calc(4 * var(--u)); }
html.ui-v2 .v2-hosted-pet .pet-litter-actions:empty { display: none; }
/* o "Dispensar ninhada" (perigo) mora no pé do Canil, à esquerda (`hostedIsland.js › petLayout`), no lugar do "Chamar ninhada" — que fica
   travado enquanto há ninhada: na área que rola ele nascia como um fio de 9 px colado no pé (revisão P4-30) */
html.ui-v2 .v2-hosted-pet #pet-foot > #pet-dismiss-litter { margin-right: calc(16 * var(--u)); }
html.ui-v2 .v2-hosted-pet #pet-foot:has(> #pet-dismiss-litter) > #pet-litter-btn { display: none; }

/* CONSTRUIR: os prédios em CARTÕES DE LINHA numa grade (o desenho à esquerda, o nome, o que abre e o custo ao lado, o "Construir"
   do tamanho do cartão embaixo) — na fileira da clássica (cartões de 104 px, o botão de 120 da régua) os botões nasciam fora da
   vista e, rolados, se encavalavam: a borda de um construía o prédio vizinho, sem pergunta (revisão P4-13) */
html.ui-v2 .v2-hosted-islandBuild .ib-tabs { gap: var(--v2-gap); }
html.ui-v2 .v2-hosted-islandBuild .ib-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(calc(220 * var(--u)), 1fr)); align-content: start; gap: var(--v2-gap); overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; }
html.ui-v2 .v2-hosted-islandBuild .ib-card { width: auto; height: auto; min-width: 0; max-width: none; display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto auto auto 1fr; align-items: center; column-gap: var(--v2-gap); row-gap: calc(2 * var(--u)); padding: calc(6 * var(--u)); text-align: left; }
html.ui-v2 .v2-hosted-islandBuild .ib-card > .ib-sprite { --px: calc(var(--ap) * 0.66); grid-column: 1; grid-row: 1 / 4; }
html.ui-v2 .v2-hosted-islandBuild .ib-card > :is(.ib-name, .ib-opens, .ib-cost) { grid-column: 2; min-width: 0; justify-self: start; max-width: 100%; text-align: left; }
html.ui-v2 .v2-hosted-islandBuild .ib-card > .ib-opens { min-height: 0; }
html.ui-v2 .v2-hosted-islandBuild .ib-name { line-height: 1.2; }
html.ui-v2 .v2-hosted-islandBuild .ib-opens { font-size: var(--v2-text-small); line-height: 1.25; }
html.ui-v2 .v2-hosted-islandBuild .ib-card > :is(.btn, .island-bar-seal, .ib-seal) { grid-column: 1 / -1; justify-self: stretch; width: auto; min-width: 0; max-width: 100%; margin-top: calc(4 * var(--u)); align-self: end; }

/* ================================================================================================================================
   A ILHA E A CARTA (docs/specs/ui-v2.md §6.7): as peças da clássica que seguem na camada de compatibilidade — a barra do lote, o
   painel do próximo nível e a carta do mar — com o que se toca na régua (46, 8 de vão, 16 do perigo) e a letra da v2
   ================================================================================================================================ */
/* a BARRA DO LOTE (a Casa e os lugares de duas portas): as portas e o "×" no alvo de 46, o "×" a 16 delas. A largura máxima que a
   clássica escreve na barra conta com o chat no canto ESQUERDO (`islandMap.js › barMaxW`/`chatGuard`): na v2 ele mora na coluna
   da direita, e a conta dava 28 px — a barra só aparecia porque o conteúdo vazava da caixa. Sem o teto, ela tem a largura do que
   leva; a linha da ILHA da Casa vira a porta "▲ Expandir ilha" da v2 (`islandChart.js › houseBarDoor`), e a barra fica numa linha */
/* o pixel de arte da v2 vale nos FILHOS: a posição da barra (e a do painel) a clássica escreve em `--px` (o da ilha) */
html.ui-v2 #island-bar > *, html.ui-v2 .v2-island-next > * { --px: var(--ap); }
html.ui-v2 #island-bar { height: auto; max-width: none !important; padding: calc(4 * var(--u)) calc(6 * var(--u)); font-size: var(--v2-text-small); }
html.ui-v2 #island-bar > .island-bar-row { gap: var(--v2-gap); align-items: center; flex-wrap: wrap; justify-content: center; }
/* a barra mora EMBAIXO, no meio da ilha, como a barra de ação do celular: ao lado do lote (a posição da clássica) ela não tinha como
   ficar entre as docas, e no SE — as docas por cima do palco — o "×" dela caía embaixo do "Nível" (revisão P5-15). Com as docas
   por cima (`data-docks=in`) ela cabe entre elas e quebra em duas linhas quando precisa */
html.ui-v2 #island-bar { left: 50% !important; top: auto !important; bottom: calc(6 * var(--u)); translate: -50% 0; width: max-content; }
html.ui-v2:has(#ui2[data-docks="in"]) #island-bar { max-width: calc(100vw - var(--v2-safe-l) - var(--v2-safe-r) - 2 * (var(--v2-target) + 16 * var(--u)) - 2 * var(--v2-gap)) !important; }
/* com as docas por cima as portas vão SÓ COM O ÍCONE (o nome na dica e no leitor de tela, como os atalhos da barra da carta) e o nome do
   lugar sai (o lote tocado já se acende): em três linhas a barra cobria a própria Casa (revisão P5-16) */
html.ui-v2:has(#ui2[data-docks="in"]) #island-bar .island-bar-head { display: none; }
html.ui-v2:has(#ui2[data-docks="in"]) #island-bar :is(#island-bar-open, #island-bar-open2):has(> .btn-icon) { min-width: var(--v2-target); padding: 0; justify-content: center; }
html.ui-v2:has(#ui2[data-docks="in"]) #island-bar :is(#island-bar-open, #island-bar-open2):has(> .btn-icon) > :not(.btn-icon) { display: none; }
html.ui-v2 #island-bar .island-bar-head { gap: calc(6 * var(--u)); }
html.ui-v2 #island-bar .island-bar-name { font-size: var(--v2-text); }
html.ui-v2 #island-bar .island-bar-row > .btn { min-height: var(--v2-target); padding: 0 calc(12 * var(--u)); font-size: var(--v2-text); }
html.ui-v2 #island-bar .island-bar-row > .island-bar-close { min-width: var(--v2-target); padding: 0; margin-left: calc(8 * var(--u)); }
html.ui-v2 #island-bar > #island-expand { display: none; }
/* o PRÓXIMO NÍVEL (o selo da ilha na barra de cima): a letra da v2, cada material numa linha de 46 com o nome escrito ao lado do
   ícone (`islandChart.js › nameMaterials`), em duas colunas; o "▲ Expandir ilha" e o "×" no alvo de 46; o corpo rola */
/* o painel sobe ao alto da tela (cobre o ouro e o selo enquanto aberto, como uma folha: o "×" e o toque fora fecham) e o que o nível
   DÁ divide a linha com o nível de personagem que ele pede: os 5 materiais do custo à vista no iPhone (no Nv 3 → 4 o 5.º morava
   embaixo da dobra, sem sinal — revisão P5-01); quando não cabem (o SE), o degradê de "a lista continua" (`.scroll-fade`, o da
   clássica, posto pela v2 em `topBar.js`) */
html.ui-v2 .v2-island-next { top: calc(8 * var(--u)); width: min(calc(460 * var(--u)), calc(100vw - 16 * var(--u))); max-height: calc(100dvh - 16 * var(--u)); overflow: hidden; gap: calc(6 * var(--u)); padding: calc(6 * var(--u)) calc(8 * var(--u)) calc(8 * var(--u)); font-size: var(--v2-text-small); line-height: 1.25; white-space: normal; }
html.ui-v2 .v2-island-next .island-next-head { font-size: var(--v2-text); line-height: 1.2; }
html.ui-v2 .v2-island-next #island-next-close { min-width: var(--v2-target); min-height: var(--v2-target); padding: 0; }
html.ui-v2 .v2-island-next .island-next-gives { row-gap: 0; }
html.ui-v2 .v2-island-next .island-next-gives > .island-next-blds { flex-basis: auto; flex: 1 1 auto; grid-template-columns: repeat(auto-fill, minmax(calc(170 * var(--u)), 1fr)); }
/* o selo de tier dos materiais na letra pequena da v2 (era 8 px: a regra das folhas, `.v2-hosted .slot-tier`, não alcança o painel —
   revisão P5-02) */
html.ui-v2 .v2-island-next .slot-tier { font-size: var(--v2-text-small); line-height: 1; }
html.ui-v2 .v2-island-next .ib-mat-ico { --px: calc(var(--ap) * 1.5); }
/* o que rola é o CUSTO; a cabeça e o "▲ Expandir ilha" ficam (a ação fora do rolador, §6.6) */
html.ui-v2 .v2-island-next > * { flex: none; }
html.ui-v2 .v2-island-next .island-next-cost { flex: 0 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-content: start; gap: calc(4 * var(--u)) var(--v2-gap); width: 100%; }
html.ui-v2 .v2-island-next .island-next-cost > .island-req { display: flex; grid-column: auto; align-items: center; gap: calc(6 * var(--u)); min-width: 0; }
html.ui-v2 .v2-island-next .island-next-cost > .island-req.is-mat { min-height: var(--v2-target); }
html.ui-v2 .v2-island-next .island-req > .v2-req-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html.ui-v2 .v2-island-next .island-req-val { flex: none; }
html.ui-v2 .v2-island-next #island-next-do { align-self: flex-end; margin-top: calc(8 * var(--u)); min-height: var(--v2-target); padding: 0 calc(14 * var(--u)); font-size: var(--v2-text); }
/* a folha NÍVEL: o "Subir sozinho" no alvo de 46 */
html.ui-v2 #ui2 #btn-explore-auto-advance { min-height: var(--v2-target); }
/* no rodapé da folha, à esquerda das ações (`panelSheet › footerLead`): no corpo, no alvo de 46, ele passava da dobra (P5-18); a fileira dele
   no corpo fica vazia e sai */
html.ui-v2 #ui2 .v2-host-level .option-row:empty { display: none; }
/* a CARTA DO MAR: a vista de arte é a da clássica (640 × 360, `mapView.js`); o que se toca por cima dela vai para a régua. A BARRA
   de cima com 46 de alvo: o "0/3" da tripulação, a sugestão ("Léo → Veio de Ferro" · "Mandar"), os atalhos e o "×" a 16 deles; o
   saldo sai (o custo de cada melhoria mora no Nódulo, com ✔/✖); o "Contratar" só com o ícone (o nome na dica e no leitor de tela) */
html.ui-v2 #node-map-bar { height: auto; min-height: calc(54 * var(--u)); gap: var(--v2-gap); padding: 0 calc(2 * var(--u)); font-size: var(--v2-text-small); }
html.ui-v2 #node-map-bar > * { --px: var(--ap); }
html.ui-v2 #node-map-bar :is(button, .btn) { min-height: var(--v2-target); font-size: var(--v2-text); }
html.ui-v2 #node-map-bar #node-map-crew { min-width: var(--v2-target); height: var(--v2-target); padding: 0 calc(8 * var(--u)); gap: calc(4 * var(--u)); }
/* o nome da ilha (voa e abre o Nódulo) e o "Mandar" (grava, sem pergunta) a 16 um do outro (revisão P5-03) */
html.ui-v2 #node-map-bar #node-map-next { gap: var(--v2-gap); min-width: 0; }
html.ui-v2 #node-map-bar #node-map-next-do { margin-left: calc(8 * var(--u)); }
html.ui-v2 #node-map-bar #node-map-next-node { min-width: var(--v2-target); padding: 0 calc(4 * var(--u)); }
html.ui-v2 #node-map-bar #node-map-next-do { padding: 0 calc(12 * var(--u)); }
html.ui-v2 #node-map-bar .node-map-wallet { display: none; }
html.ui-v2 #node-map-bar .node-map-actions { gap: var(--v2-gap); }
html.ui-v2 #node-map-bar .node-map-actions > .btn { padding: 0 calc(10 * var(--u)); }
html.ui-v2 #node-map-bar :is(#node-map-hire-btn, #node-map-workers-btn) { min-width: var(--v2-target); padding: 0; justify-content: center; }
/* o "Trabalhadores" não tem ícone na clássica: a peça `ico_worker` no lugar do texto (o nome fica no leitor de tela e na dica) */
html.ui-v2 #node-map-bar #node-map-workers-btn { font-size: 0; }
html.ui-v2 #node-map-bar #node-map-workers-btn::before { content: ""; width: calc(16 * var(--ap)); height: calc(16 * var(--ap)); background: var(--ui-ico_worker, none) center / 100% 100% no-repeat; image-rendering: pixelated; }
html.ui-v2 #node-map-bar #node-map-hire-btn > :not(.btn-icon) { display: none; }
html.ui-v2 #node-map-bar #node-map-close { min-width: var(--v2-target); padding: 0; margin-left: calc(8 * var(--u)); }
/* os FILTROS (canto de baixo à esquerda) e o ZOOM (à direita): cada ficha, o "−", o "+" e o "⌂" no alvo de 46 com 8 de vão; os três
   pontos do degrau saem (o "−"/"+" e a pinça chegam aos três) e o nome do degrau fica ao lado do "⌂" */
/* cada caixa numa FILEIRA só (as duas linhas da clássica lado a lado): a faixa de baixo fica com 54 de altura, não 108 */
html.ui-v2 #node-map-filters, html.ui-v2 .node-map-zoombox { width: auto; height: auto; flex-direction: row; align-items: center; gap: var(--v2-gap); padding: calc(2 * var(--u)); }
html.ui-v2 #node-map-filters > *, html.ui-v2 .node-map-zoombox > * { --px: var(--ap); }
html.ui-v2 #node-map-filters .node-map-filter-row, html.ui-v2 .node-map-zoombox .node-map-zoom-row { height: auto; gap: var(--v2-gap); }
html.ui-v2 #node-map-filters :is(button, .btn) { min-width: var(--v2-target); min-height: var(--v2-target); justify-content: center; font-size: var(--v2-text-small); }
html.ui-v2 .node-map-zoombox .btn { width: var(--v2-target); height: var(--v2-target); min-height: var(--v2-target); font-size: var(--v2-text-title); }
html.ui-v2 .node-map-zoombox .node-map-level-dots { display: none; }
html.ui-v2 .node-map-zoombox .node-map-level-name { font-size: var(--v2-text-small); line-height: 1.2; }
/* a dica de uma vez ("Toque numa ilha · pinça…") logo acima da faixa de baixo (no alto ela caía sobre as placas dos arquipélagos: P5-17) */
html.ui-v2 #node-map-coach { font-size: var(--v2-text-small); bottom: calc(4 * var(--px) + 62 * var(--u)); }
/* as ILHAS: o alvo de 46 em volta do medalhão (28) e do pip da Carta, sem mudar o desenho (o `::after` absoluto estica o toque —
   a régua do kit o conta; o do pip escolhido/achado é o contorno da clássica, e fica). As PLACAS (o nome da ilha) e as dos
   ARQUIPÉLAGOS na letra pequena da v2; a do arquipélago, que se toca, com 46 de alvo na vertical */
html.ui-v2 .node-mark:not(.is-pip.is-selected, .is-pip.is-match)::after { content: ""; position: absolute; inset: calc(-9 * var(--u)); }
/* "Sua ilha" (o medalhão da cidade: 28 na Carta, 36 de perto) idem */
html.ui-v2 .node-city { position: absolute; }
html.ui-v2 .node-city::after { content: ""; position: absolute; inset: calc(-9 * var(--u)); }
html.ui-v2 .node-map-plate { font-size: var(--v2-text-small); line-height: 1.25; max-width: calc(170 * var(--u)); }
html.ui-v2 .node-map-arch { position: relative; height: auto; padding: calc(1 * var(--u)) calc(4 * var(--u)); font-size: var(--v2-text-small); line-height: 1.25; }
html.ui-v2 .node-map-arch::after { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: var(--v2-target); transform: translateY(-50%); }
/* o NÓDULO, a folha AO LADO da carta (`sheets.js › beside`, §6.7): à direita, embaixo da barra da carta (`--v2-beside-top`, medida),
   sem véu — a carta fica à vista e no toque à esquerda (tocar outra ilha troca o Nódulo); a largura, 46 % da tela entre 300 e 400, é a
   do cartão da clássica (272 de 640): o "⌂" e a sua ilha cabem à esquerda dele (revisão P5-10). Enquanto ele está aberto o zoom muda para
   o canto de baixo à ESQUERDA e os filtros saem (não cabem os dois ao lado do painel; filtrar é procurar ilha, não olhar uma) */
#ui2 .v2-sheet.is-beside { left: auto; top: var(--v2-beside-top, 0px); width: clamp(calc(300 * var(--u)), 46vw, calc(400 * var(--u))); padding-top: 0; padding-left: 0; border-left: calc(2 * var(--u)) solid var(--v2-line); box-shadow: calc(-4 * var(--u)) 0 calc(12 * var(--u)) rgba(0, 0, 0, 0.45); }
html.ui-v2 #screen-lobby.has-beside #node-map-filters { display: none; }
html.ui-v2 #screen-lobby.has-beside .node-map-zoombox { right: auto; left: calc(4 * var(--px)); }
html.ui-v2 #screen-lobby.has-beside #node-map-coach { display: none; }
/* o chat fechado (o 💬 da coluna da direita) sai enquanto o painel está aberto: sem as faixas pretas (o SE) ele aparecia 4 px entre a
   barra da carta e o painel; toda outra folha o cobre inteiro */
html.ui-v2:has(#screen-lobby.has-beside) #ui-overlay > #chat { visibility: hidden; }
/* o corpo do Nódulo na régua: as caras do "Atribuir" com 8 de vão (eram 32 px a 3), o "Desconectar" (perigo) a 16 do que vier antes;
   o "onde você está" da carta desce para baixo da barra de 54 (ficava por cima do "0/3") */
html.ui-v2 .v2-hosted-node .node-primary { gap: var(--v2-gap); flex-wrap: wrap; }
html.ui-v2 .v2-hosted-node .btn.node-face { gap: calc(6 * var(--u)); padding: 0 calc(10 * var(--u)) 0 calc(6 * var(--u)); }
html.ui-v2 .v2-hosted-node #node-disconnect { margin-left: calc(16 * var(--u)); }
html.ui-v2 .node-map-where { top: calc(4 * var(--px) + 58 * var(--u)); font-size: var(--v2-text-small); height: auto; line-height: 1.25; }
/* a ORDEM do corpo do Nódulo na v2: o estado e o "Atribuir" no alto, o MELHORAR (custo e botão) logo depois, as vagas, a rota, o que
   produz, a disputa e o "Sobre" — na ordem da clássica o "Melhorar" morava a 2,2 alturas do painel, depois da Disputa (revisão P5-06,
   P4-10). As seções são irmãs sem invólucro: cada uma pelo título dela (`:has`) e pelo que vem junto */
html.ui-v2 .v2-hosted-node .work-panes { display: flex; flex-direction: column; }
html.ui-v2 .v2-hosted-node .work-panes > :is(.work-section:has(#node-next-level), #node-next, #node-mats, .work-row-end:has(#node-upgrade)) { order: 1; }
html.ui-v2 .v2-hosted-node .work-panes > :is(.work-section:has(+ .work-slot), .work-slot) { order: 2; }
html.ui-v2 .v2-hosted-node .work-panes > :is(.work-section:has(+ #node-route), #node-route) { order: 3; }
html.ui-v2 .v2-hosted-node .work-panes > :is(.work-section:has(+ #node-produce), #node-produce) { order: 4; }
html.ui-v2 .v2-hosted-node .work-panes > #node-war { order: 5; }
html.ui-v2 .v2-hosted-node .work-panes > :is(.work-section:has(+ #node-about), #node-about) { order: 6; }
/* o selo "Nv N" do cabeçalho do Nódulo inteiro dentro da moldura (a altura de linha da clássica, 9 px, cortava a letra de 16: P5-07) */
#ui2 #v2-sheet-node .node-title-level { line-height: 1.2; padding: calc(2 * var(--u)) calc(6 * var(--u)); }
/* o BALÃO da camada de compatibilidade (a dica do toque na carta, na ilha) na letra pequena da v2 — era a de 8 px (revisão P5-05) */
html.ui-v2 #ui-root .hint-bubble { font-size: var(--v2-text-small); line-height: 1.3; max-width: min(60vw, calc(360 * var(--u))); padding: calc(4 * var(--u)) calc(8 * var(--u)); }
/* uma janela CLÁSSICA por cima da carta (a Guerra, aberta da Disputa do Nódulo: é da frente "social") nasce onde a barra de 22 da
   clássica deixava, e a barra de 54 da v2 ficava metade por baixo dela — dois "×" colados, um fechando a Guerra e o outro a carta
   (revisão P5-11). Enquanto ela está aberta a barra da carta sai, como as docas saem embaixo das folhas; o "◀" da v2 volta */
html.ui-v2 #screen-lobby.is-node-map:has(> .window) #node-map-bar { visibility: hidden; }
/* os FILTROS numa fileira só que ROLA de lado quando não cabe ao lado do zoom, com o funil ("Procurar por material") preso na ponta:
   com 9 fichas — a conta adiantada — a fileira passava por baixo do zoom e o funil sumia (revisão P5-13); em duas linhas (a 1.ª
   tentativa) ela engolia a placa da Garganta e as ilhas de baixo (P5-17) */
html.ui-v2 #node-map-filters { flex-wrap: nowrap; max-width: calc(100% - 8 * var(--px) - 228 * var(--u)); overflow-x: auto; overflow-y: hidden; overscroll-behavior: contain; touch-action: pan-x; scrollbar-width: none; }
html.ui-v2 #node-map-filters .node-map-filter-row { flex: none; }
/* o funil preso na ponta da fileira que rola (a ação fora do rolador, §6.6) */
html.ui-v2 #node-map-filters #node-map-mat-btn { position: sticky; right: 0; z-index: 1; box-shadow: calc(-6 * var(--u)) 0 calc(6 * var(--u)) rgba(12, 10, 20, 0.85); }
/* o SELETOR do funil ("Procurar por material"): cada material (e cada um da linha "Falta") numa casa de 46 com 8 de vão, o ícone em
   1,5×, o tier na letra pequena; a largura da carta, acima dos filtros, e a lista rola dentro dele (eram 77 casas de 16 a 2 px: P5-14) */
html.ui-v2 #node-map-mat-picker { left: calc(4 * var(--px)); right: calc(4 * var(--px)); width: auto; bottom: calc(4 * var(--px) + 116 * var(--u)); padding: calc(4 * var(--u)); }
html.ui-v2 #node-map-mat-picker .node-map-mat-list { gap: var(--v2-gap); max-height: calc(100dvh - 200 * var(--u)); font-size: var(--v2-text-small); }
html.ui-v2 #node-map-mat-picker :is(.node-map-needs, .node-map-mat-group) { gap: var(--v2-gap); }
html.ui-v2 #node-map-mat-picker button.node-map-mat { --px: calc(var(--ap) * 1.5); min-width: var(--v2-target); min-height: var(--v2-target); display: inline-flex; align-items: center; justify-content: center; }
html.ui-v2 #node-map-mat-picker .node-map-mat-kind { --px: calc(var(--ap) * 1.5); }
html.ui-v2 #node-map-mat-picker .slot-tier { font-size: var(--v2-text-small); line-height: 1; }
