/* craft.css — janela da Artesã (js/ui/windows/craft.js; ui-gameplay.md §4). Dona: trilha K2b (§12).
   Geometria: faixa da estação | lista 170 (rolagem, linha = slot 36 + nome + 2ª linha + marca) | detalhe 244 (slot, stats base,
   nota, materiais tenho/preciso em 2 colunas, resultado, custo + Criar) | revelação do equipamento por cima do corpo
   (slot 2×, clarão, rótulo com pop, adicionais um a um, raios/tremor por nível de anúncio).
   Medidas em px de arte: calc(N * var(--px)); animação sempre em steps(); prefers-reduced-motion no fim. */

.craft-body {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: calc(2 * var(--px));
  height: 100%;
  overflow: hidden;
}

/* ---- faixa da estação (onde moravam as abas: UMA estação por janela, decisão do dono 2026-09-30) ----------------
   ícone 16 da estação + o NPC, apagado · à direita o nível da profissão e a barra de exp (a frase inteira na dica). */
.craft-station {
  display: flex;
  align-items: center;
  gap: calc(4 * var(--px));
  height: calc(16 * var(--px));
  margin-bottom: calc(2 * var(--px));
  flex-shrink: 0;
  min-width: 0;
}
.craft-station-ico { width: calc(16 * var(--px)); height: calc(16 * var(--px)); flex-shrink: 0; background-repeat: no-repeat; background-size: 100%; image-rendering: pixelated; }
.craft-station-npc { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.craft-station-prof { display: inline-flex; align-items: center; gap: calc(3 * var(--px)); margin-left: auto; flex-shrink: 0; }
.craft-station-prof:focus-visible { outline: var(--px) solid var(--c-gold); outline-offset: var(--px); }
.craft-station-level { color: var(--c-gold); white-space: nowrap; }
.craft-station-prof .bar { width: calc(60 * var(--px)); height: calc(8 * var(--px)); }

/* ---- estação trancada: o aviso no lugar das colunas (o prédio não existe na ilha) --------------------------------- */
.craft-locked {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(6 * var(--px));
  padding: 0 calc(24 * var(--px));
  text-align: center;
}
.craft-locked-ico { width: calc(16 * var(--px)); height: calc(16 * var(--px)); background: var(--ui-ico_lock, none) center / 100% no-repeat; image-rendering: pixelated; }

/* ---- colunas ----------------------------------------------------------------------------------------------- */
.craft-columns {
  display: flex;
  gap: calc(4 * var(--px));
  flex: 1;
  min-height: 0;
}
.craft-left {
  display: flex;
  flex-direction: column;
  gap: calc(2 * var(--px));
  width: calc(170 * var(--px));
  flex-shrink: 0;
  min-height: 0;
}

/* ---- lista de receitas -------------------------------------------------------------------------------------- */
.craft-list {
  flex: 1;
  min-height: 0;
  /* sem `overflow: hidden` aqui: ele recortaria no padding box e comeria os 4 px que a rolagem usa da faixa da borda */
}
/* a moldura do painel rebaixado tem 3 px; o miolo usa 4 dos 8 px da faixa da borda (como o `::before`) */
.craft-list-scroll {
  position: absolute;
  inset: calc(-4 * var(--px));
  overflow-y: scroll;
  overflow-x: hidden;
  scrollbar-width: thin;
  scrollbar-color: #575273 #12101c;
}
.craft-list-scroll:focus { outline: none; }
.craft-list-scroll:focus-visible .craft-row.is-selected { outline: var(--px) solid var(--c-gold); outline-offset: calc(-1 * var(--px)); }
/* barra de rolagem em pixel (Chromium/WebKit); Firefox fica no `scrollbar-width: thin` */
@supports selector(::-webkit-scrollbar) {
  .craft-list-scroll { scrollbar-width: auto; scrollbar-color: auto; }
  .craft-list-scroll::-webkit-scrollbar { width: calc(7 * var(--px)); }
  .craft-list-scroll::-webkit-scrollbar-track { background: #221f33; border-left: var(--px) solid #0d0a14; }
  .craft-list-scroll::-webkit-scrollbar-thumb {
    background: #8391a8;
    border: var(--px) solid #221f33;
    border-left: calc(2 * var(--px)) solid #221f33;
    box-shadow: inset var(--px) var(--px) 0 #bcc8d6;
  }
  .craft-list-scroll::-webkit-scrollbar-thumb:hover { background: #bcc8d6; }
  .craft-list-scroll::-webkit-scrollbar-thumb:active { background: var(--c-gold); }
}

.craft-row {
  display: flex;
  align-items: center;
  gap: calc(3 * var(--px));
  height: calc(38 * var(--px));
  padding: calc(1 * var(--px)) calc(2 * var(--px)) calc(1 * var(--px)) calc(4 * var(--px));
  cursor: pointer;
}
.craft-row > .slot { flex-shrink: 0; }
.craft-row:hover { background: rgba(255, 255, 255, 0.06); }
.craft-row.is-selected { background: rgba(224, 176, 64, 0.16); box-shadow: inset calc(2 * var(--px)) 0 0 var(--c-gold); }
.craft-row-text {
  display: flex;
  flex-direction: column;
  justify-content: center;
  flex: 1;
  min-width: 0;
  line-height: calc(10 * var(--px));
}
.craft-row-name {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
/* a 2.ª linha leva TEXTO ("Nv. do item 12", "Tenho: 40") ou o SELO do requisito que falta (`.req-seal`, abaixo) — o selo
   cabe inteiro nos ~99 px dela (o pior caso do bundle mede 96; `client/tests/ui/reqSeal.test.js`) */
.craft-row-sub { color: var(--c-text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.craft-row.is-level-locked .craft-row-name { color: var(--c-text-dim); }
.craft-row.is-level-locked .item-icon { filter: grayscale(1) brightness(0.6); }
.craft-row.is-selected .craft-row-name { color: var(--c-text); }

/* marca à direita: ponto verde (dá para criar agora) ou ✖ (falta material) — forma + cor. Falta NÍVEL (do personagem ou do
   ofício): a marca fica vazia, e o cadeado é o do selo da 2.ª linha (`.req-seal`, abaixo) — dois cadeados na mesma linha seriam
   a duplicata da G6 */
.craft-row-mark {
  flex-shrink: 0;
  width: calc(8 * var(--px));
  height: calc(8 * var(--px));
}
.craft-row-mark.is-craftable {
  background:
    linear-gradient(#a8e08c, #a8e08c) calc(3 * var(--px)) calc(2 * var(--px)) / calc(1 * var(--px)) calc(1 * var(--px)) no-repeat,
    linear-gradient(var(--c-ok), var(--c-ok)) calc(2 * var(--px)) calc(1 * var(--px)) / calc(4 * var(--px)) calc(6 * var(--px)) no-repeat,
    linear-gradient(var(--c-ok), var(--c-ok)) calc(1 * var(--px)) calc(2 * var(--px)) / calc(6 * var(--px)) calc(4 * var(--px)) no-repeat,
    linear-gradient(#1a1423, #1a1423) calc(1 * var(--px)) 0 / calc(6 * var(--px)) calc(8 * var(--px)) no-repeat,
    linear-gradient(#1a1423, #1a1423) 0 calc(1 * var(--px)) / calc(8 * var(--px)) calc(6 * var(--px)) no-repeat;
}
.craft-empty { padding: calc(6 * var(--px)) calc(4 * var(--px)); text-align: center; }

.craft-myclass {
  display: flex;
  align-items: center;
  gap: calc(3 * var(--px));
  flex-shrink: 0;
  height: calc(12 * var(--px));
  padding-left: calc(1 * var(--px));
  color: var(--c-text-dim);
  cursor: pointer;
}
.craft-myclass:hover { color: var(--c-text); }

/* ---- detalhe ------------------------------------------------------------------------------------------------- */
.craft-detail {
  width: calc(244 * var(--px));
  flex-shrink: 0;
  min-height: 0;
}
.craft-detail-inner {
  position: absolute;
  inset: calc(-4 * var(--px)) calc(-3 * var(--px));
  display: flex;
  flex-direction: column;
  gap: calc(3 * var(--px));
  overflow: hidden;
  line-height: calc(10 * var(--px));
}
.craft-detail-empty {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  text-align: center;
}

.craft-head {
  display: flex;
  align-items: center;
  gap: calc(4 * var(--px));
  flex-shrink: 0;
}
.craft-head > .slot { flex-shrink: 0; }
.craft-head-text { min-width: 0; flex: 1; }
.craft-head-name { color: var(--c-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.craft-head-owned { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 2.ª linha da cabeça: o nível do item e os selos dos requisitos que faltam. QUEBRA em vez de cortar (pedido do dono,
   2026-10-01): com `nowrap` + reticências, "Nv. do item 12 · Requer nível 10 · Requer Alfaiate 2" (~250 px num miolo de ~200)
   mostrava só "Requer…" em vermelho — o requisito que faltava era justamente o pedaço cortado. */
.craft-head-sub { display: flex; flex-wrap: wrap; align-items: center; gap: calc(2 * var(--px)) calc(4 * var(--px)); }

/* ---- selo do requisito que FALTA (`widgets/reqSeal.js`; Oficina, Refino, Livro de receitas, "Onde conseguir") ----------
   docs/UX-GRAMATICA.md G2/G5: moldura + cadeado + palavra curta, na cor de perigo, só quando bloqueia — o mesmo desenho do
   `[cadeado] Ilha Nv N` da janela Construir (island.css › .ib-seal.is-locked), na altura da linha de texto (8 + moldura = 10),
   e NUNCA cortado (sem `overflow`): a frase inteira mora no gesto e no `aria-label`.
   FUNDO PRÓPRIO, o mais escuro da UI (revisão de 2026-10-01): sem ele o vermelho dependia da linha embaixo — 3,57:1 sobre a
   receita escolhida (o realce de ouro da lista), 3,77:1 no Livro; sobre `--c-field-bg` ele fica em 4,6:1 em qualquer linha. */
.req-seal {
  display: inline-flex;
  align-items: center;
  gap: calc(2 * var(--px));
  flex: none;
  padding: 0 calc(2 * var(--px));
  border: var(--px) solid var(--c-danger);
  background: var(--c-field-bg);
  color: var(--c-danger);
  line-height: calc(8 * var(--px));
  white-space: nowrap;
  vertical-align: middle;
}
.req-seal-lock { flex: none; width: calc(8 * var(--px)); height: calc(8 * var(--px)); background: var(--ui-ico_lock, none) center / 100% 100% no-repeat; image-rendering: pixelated; }

/* forja: tremor de 2 px em degraus enquanto o pedido está em voo (equipamento) */
.craft-out-slot.is-forging { animation: craft-forge 0.2s steps(1) infinite; }
.craft-out-slot.is-forging .item-icon { filter: brightness(1.35); }
@keyframes craft-forge {
  0%   { transform: translate(0, 0); }
  25%  { transform: translate(calc(-2 * var(--px)), 0); }
  50%  { transform: translate(calc(2 * var(--px)), calc(-1 * var(--px))); }
  75%  { transform: translate(0, calc(1 * var(--px))); }
  100% { transform: translate(0, 0); }
}

.craft-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: calc(8 * var(--px));
  margin: 0;
  flex-shrink: 0;
}
.craft-stat { display: flex; justify-content: space-between; gap: calc(3 * var(--px)); min-width: 0; }
.craft-stat dt { color: var(--c-text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.craft-stat dd { margin: 0; white-space: nowrap; }

.craft-note {
  flex-shrink: 0;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
.craft-note.is-hint { color: var(--c-gold); }

.craft-mats-head {
  display: flex;
  justify-content: space-between;
  flex-shrink: 0;
  padding-bottom: calc(1 * var(--px));
  border-bottom: var(--px) solid rgba(255, 255, 255, 0.15);
}
.craft-mats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: calc(2 * var(--px)) calc(4 * var(--px));
  flex-shrink: 0;
}
/* até 2 materiais: uma coluna só, com o nome inteiro na linha */
.craft-mats.is-single { grid-template-columns: 1fr; }
.craft-mat {
  display: flex;
  align-items: center;
  gap: calc(3 * var(--px));
  min-width: 0;
}
.craft-mat > .slot { flex-shrink: 0; }
.craft-mat-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.craft-mats.is-single .craft-mat-text { flex-direction: row; justify-content: space-between; align-items: center; gap: calc(4 * var(--px)); }
/* o nome do material INTEIRO, em quantas linhas precisar (até 3 com o acervo de hoje — `client/tests/ui/matNameWrap.test.js`):
   cortado em 2 linhas com reticências, "Essência Sussurrante Bruta" e "… Pura" eram o mesmo "Essência / Sussurrante…" — os três
   pontinhos que o dono pediu para tirar (revisão de 2026-10-01; UX-GRAMATICA §3, nome próprio inteiro). O detalhe rola. */
.craft-mat-name { overflow-wrap: anywhere; }
.craft-mat-have { white-space: nowrap; flex-shrink: 0; }
.craft-mat-mark { display: inline-block; width: calc(8 * var(--px)); margin-left: calc(2 * var(--px)); text-align: center; }
.craft-mat.is-ok .craft-mat-have { color: var(--c-ok); }
.craft-mat.is-missing .craft-mat-have { color: var(--c-danger); }
.craft-mat.is-missing .item-icon { opacity: 0.45; }
/* O material da Oficina e do Refino é um BOTÃO (docs/specs/professions.md §7): clique = "Onde conseguir", botão direito = o
   menu de item (ui-gameplay.md §0.4). O realce é o do insumo da janela "Onde conseguir" (`sources.css › .src-mat`): o slot
   acende como no hover da Mochila e o nome fica dourado; o foco de teclado é o contorno dourado, 1 px para DENTRO (o miolo
   do detalhe recorta o que passa da borda). */
.craft-mat[role='button'] { cursor: pointer; }
.craft-mat[role='button']:hover > .slot,
.craft-mat[role='button']:focus-visible > .slot { border-image-source: url(../assets/ui/slots/slot_hover.png); }
.craft-mat[role='button']:hover .craft-mat-name { color: var(--c-gold); }
.craft-mat[role='button']:focus-visible { outline: var(--px) solid var(--c-gold); outline-offset: calc(-1 * var(--px)); }
/* o `.slot` nasce com `touch-action: none` (é o arrasto da Mochila): no detalhe e na lista que rola o dedo tem de rolar, e o
   toque longo abre o menu (§8.7) */
.craft-mat > .slot,
.craft-row > .slot { touch-action: auto; }

.craft-result {
  flex-shrink: 0;
  color: var(--c-ok);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transform-origin: left center;
}
.craft-result.is-pop { animation: craft-pop 0.12s steps(3) both; }
@keyframes craft-pop {
  from { transform: scale(1.25); filter: brightness(1.8); }
  to   { transform: none; filter: none; }
}

.craft-foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: calc(4 * var(--px));
  margin-top: auto;
  flex-shrink: 0;
}
.craft-foot-gold { min-width: 0; }
.craft-cost { display: flex; align-items: center; gap: calc(2 * var(--px)); white-space: nowrap; }
.craft-ico-gold {
  flex-shrink: 0;
  width: calc(9 * var(--px));
  height: calc(9 * var(--px));
  background: var(--ui-ico_gold, none) center / 100% 100% no-repeat;
  image-rendering: pixelated;
}
.craft-gold { display: block; padding-left: calc(11 * var(--px)); white-space: nowrap; }
.craft-make-wrap { display: inline-flex; flex-shrink: 0; }
.craft-make-wrap.is-blocked { cursor: help; }
#craft-make { min-width: calc(56 * var(--px)); }

/* ---- revelação do equipamento (momento de recompensa) -------------------------------------------------------- */
.craft-reveal {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(3 * var(--px));
  padding: calc(4 * var(--px)) calc(8 * var(--px)) calc(6 * var(--px));
  background: #0d0a14;
  overflow: hidden;
  line-height: calc(10 * var(--px));
  text-align: center;
  cursor: pointer;
}
.craft-reveal:focus { outline: none; }
.craft-reveal.is-done { cursor: default; }
.craft-reveal-title { flex-shrink: 0; }

.craft-reveal-stage {
  position: relative;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: calc(112 * var(--px));
  height: calc(84 * var(--px));
  /* 2× inteiro: o slot filho troca o próprio --px por este valor (72 px de arte na tela) */
  --px2: calc(2 * var(--px));
}
.craft-reveal-slot { position: relative; z-index: 1; }
.craft-reveal-slot > .slot { --px: var(--px2); }
.craft-reveal.is-silhouette .craft-reveal-slot > .slot { animation: craft-forge 0.2s steps(1) infinite; }

/* passo 1: silhueta preta + moldura normal, sem Shining/brilho */
.craft-reveal.is-silhouette .item-icon { filter: brightness(0); }
.craft-reveal.is-silhouette .item-icon::before,
.craft-reveal.is-silhouette .item-icon::after { display: none; }
.craft-reveal.is-silhouette .slot-frame {
  border-image-source: var(--ui-slot_q_normal, url(../assets/ui/slots/slot_q_normal.png));
  animation: none;
}

/* passo 2: clarão branco de 120 ms em 2 degraus — filho direto de `.craft-reveal`, cobre a revelação INTEIRA */
.craft-flash {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: #fff;
  opacity: 0;
  pointer-events: none;
}
.craft-reveal.is-flash .craft-flash { animation: craft-flash 0.12s steps(2) both; }
@keyframes craft-flash {
  from { opacity: 1; }
  to   { opacity: 0.4; }
}
/* logo depois da revelação o ícone ainda "esfria" do branco */
.craft-reveal.is-revealed .craft-reveal-slot > .slot { animation: craft-cool 0.24s steps(3) both; }
@keyframes craft-cool {
  from { filter: brightness(3); }
  to   { filter: none; }
}

/* passo 4: raios girando atrás do slot (anúncio toast/banner), em 12 degraus */
.craft-rays {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(128 * var(--px));
  height: calc(128 * var(--px));
  margin: calc(-64 * var(--px)) 0 0 calc(-64 * var(--px));
  border-radius: 50%;
  background: repeating-conic-gradient(var(--craft-ray, #f7cf4a) 0deg 15deg, transparent 15deg 30deg);
  -webkit-mask-image: radial-gradient(circle, #000 0 30%, rgba(0, 0, 0, 0.5) 45%, transparent 68%);
  mask-image: radial-gradient(circle, #000 0 30%, rgba(0, 0, 0, 0.5) 45%, transparent 68%);
  opacity: 0;
  pointer-events: none;
}
.craft-reveal.is-revealed.is-announce-toast .craft-rays { opacity: 0.3; animation: craft-rays 2.4s steps(12) infinite; }
.craft-reveal.is-revealed.is-announce-banner .craft-rays { opacity: 0.5; animation: craft-rays 1.2s steps(12) infinite; }
@keyframes craft-rays {
  from { transform: rotate(0deg); }
  to   { transform: rotate(30deg); }
}

.craft-reveal-info {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(1 * var(--px));
  width: 100%;
  visibility: hidden;
}
.craft-reveal.is-revealed .craft-reveal-info { visibility: visible; }
.craft-reveal-name { font-size: var(--text-2); line-height: calc(18 * var(--px)); white-space: nowrap; }
.craft-reveal-quality { display: inline-block; }
.craft-reveal.is-revealed .craft-reveal-quality { animation: craft-pop-center 0.12s steps(3) both; }
.craft-reveal.is-revealed .craft-reveal-name { animation: craft-pop-center 0.12s steps(3) both; }
/* Shining: o `.q<id>` gerado no boot vem depois de windows.css e venceria o `color: transparent` do gradiente; e o pop
   não pode derrubar a varredura do `.is-shining-text` (as duas animações juntas) */
.craft-reveal-name.is-shining-text {
  color: transparent;
  /* véu claro sobre o arco-íris: o trecho azul/roxo puro some no fundo escuro em 1× */
  background-image: linear-gradient(rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.4)), var(--shining-gradient, linear-gradient(90deg, #fff, #fff));
}
.craft-reveal.is-revealed .craft-reveal-name.is-shining-text { animation: craft-pop-center 0.12s steps(3) both, shining-text 1.333s steps(16) infinite; }
@keyframes craft-pop-center {
  from { transform: scale(1.25); }
  to   { transform: none; }
}
.craft-reveal-base { white-space: nowrap; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.craft-reveal-pct { color: var(--c-ok); }
.craft-reveal-affixes {
  list-style: none;
  margin: calc(2 * var(--px)) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.craft-reveal-affix { visibility: hidden; white-space: nowrap; text-align: left; }
.craft-reveal-affix.is-in { visibility: visible; animation: craft-affix-in 0.12s steps(3) both; }
@keyframes craft-affix-in {
  from { transform: translateX(calc(-6 * var(--px))); filter: brightness(2); }
  to   { transform: none; filter: none; }
}

.craft-reveal-actions {
  display: flex;
  justify-content: center;
  gap: calc(6 * var(--px));
  flex-shrink: 0;
  visibility: hidden;
}
.craft-reveal.is-done .craft-reveal-actions { visibility: visible; }
.craft-reveal-actions .btn { min-width: calc(56 * var(--px)); }

/* anúncio `banner` (Obra-prima, Shining): a janela inteira treme 300 ms em degraus */
.window.is-craft-shake { animation: craft-shake 0.3s steps(1) both; }
@keyframes craft-shake {
  0%   { transform: translate(calc(-2 * var(--px)), calc(1 * var(--px))); }
  20%  { transform: translate(calc(2 * var(--px)), calc(-1 * var(--px))); }
  40%  { transform: translate(calc(-1 * var(--px)), calc(-1 * var(--px))); }
  60%  { transform: translate(calc(1 * var(--px)), calc(1 * var(--px))); }
  80%  { transform: translate(calc(-1 * var(--px)), 0); }
  100% { transform: none; }
}

/* ---- acessibilidade: sem tremor, raios, clarão nem pop — a revelação vira troca direta (§8.7) ---------------- */
@media (prefers-reduced-motion: reduce) {
  .craft-out-slot.is-forging,
  .craft-reveal.is-silhouette .craft-reveal-slot > .slot,
  .craft-reveal.is-revealed .craft-reveal-slot > .slot,
  .craft-reveal.is-flash .craft-flash,
  .craft-reveal.is-revealed .craft-reveal-quality,
  .craft-reveal.is-revealed .craft-reveal-name,
  .craft-reveal.is-revealed .craft-reveal-name.is-shining-text,
  .craft-reveal-affix.is-in,
  .craft-result.is-pop,
  .window.is-craft-shake { animation: none; }
  .craft-reveal .craft-rays { display: none; }
}

/* ---- avaliação de UX, rodada 2 --------------------------------------------------------------------------------
   Receita com 3 materiais faltando: o detalhe media 420 num espaço de 412 e o excedente empurrava "Seu ouro" e o
   botão Criar para FORA da moldura da janela — o jogador via o custo e não via com que botão pagar. Agora o miolo
   rola (professions.css já pôs `overflow-y: auto` no `.craft-detail-inner`) e o rodapé fica grudado no pé da área
   rolável, sempre visível. Fundo opaco na cor do miolo do painel rebaixado (panel.png #221f33 sob o véu de 35 %
   do `.panel-inset::before`): sem ele o texto que rola apareceria por trás do rodapé. */
.craft-detail-inner { overflow-x: hidden; }
.craft-foot {
  position: sticky;
  bottom: 0;
  z-index: 1;
  padding-top: calc(2 * var(--px));
  background: #161421;
}

.craft-slot { margin-left: auto; height: calc(12 * var(--px)); font: inherit; }
/* --- tier --- o seletor "Tier: todos / Tier N" da Oficina e do Refino (js/ui/widgets/tierSelect.js; professions.md §7): o par do
   seletor de espaço, encostado à direita; na largura NATURAL (o `width: 100%` do `.input` o esticaria a uma linha inteira) — a da
   opção mais longa, "Tier: todos", inteira */
.craft-tier { flex: none; width: auto; margin-left: auto; height: calc(12 * var(--px)); font: inherit; }

/* --- craft-queue --- a FAIXA DA OFICINA (js/ui/widgets/craftQueueStrip.js; docs/specs/professions.md §11.7): as 4 vagas e a fileira
   Pronto de UMA oficina com as peças do Refino (`professions.css › .refine-slots/.refine-card/.refine-ready/.refine-stock-*`, reusadas
   sem mudar nenhuma regra delas — duas filas, uma língua). Aqui só o que é da Oficina, sob `.craft-win`: craft.css é compartilhado com
   o Refino, a "Onde conseguir", a ilha, o painel do prédio e o selo de requisito, e nenhum seletor craft-* existente muda. A geometria é
   a do Refino: corpo 428 × 246 = colunas 176 · 4 · a faixa 42 · 2 · o Pronto 16. */
.craft-win .craft-queue { flex: none; display: flex; flex-direction: column; margin-top: calc(4 * var(--px)); }
.craft-win .craft-queue > .refine-ready { margin-top: calc(2 * var(--px)); }
/* "3/10 01:15" — a contagem e o mm:ss da unidade em curso, sem ícone de relógio (G1). A linha não passa do cartão: o relógio que não
   couber ("49/50 1:24:35" num cartão estreito) sai da tela pelo JS (fica no gesto e no `aria-label`), nunca um número cortado ao meio */
.craft-win .craft-queue .refine-card-top { max-width: 100%; overflow: hidden; }
.craft-win .craft-card-clock { flex: none; color: var(--c-text-dim); }
/* --- /craft-queue --- */

/* --- craft-win --- a JANELA DA OFICINA com a fila (js/ui/windows/craft.js; docs/specs/professions.md §11.7): a GEOMETRIA DO REFINO
   (`professions.css › .refine-win`) — corpo 428 × 246 = colunas de 176 (lista 180 + detalhe 244) · 4 · a faixa das vagas 42 · 2 · o
   Pronto 16 (o bloco `--- craft-queue ---` acima). Tudo aqui mora sob `.craft-win`: craft.css é compartilhado com o Refino, a "Onde
   conseguir", a ilha, o painel do prédio e o selo de requisito, e NENHUM seletor craft-* de cima muda (os da janela antiga — faixa da
   estação, custo, revelação — ficaram sem dono e saem na limpeza da frente). */
.window-body.craft-win { position: relative; display: flex; flex-direction: column; height: 100%; overflow: hidden; }
.craft-win > .craft-columns { flex: none; height: calc(176 * var(--px)); }
.craft-win > .craft-locked { flex: 1; min-height: 0; }
.craft-win .craft-left { flex: 1 1 auto; width: auto; min-width: 0; }
/* --- tier --- a FILEIRA DOS FILTROS numa linha só (professions.md §7 › Filtro de tier): [interruptor][brasão] [Todo espaço ▾]
   [Tier: todos ▾] = 16 · 2 · 12 · 2 · 72 · 2 · 72 = 178 dos 179 da lista (180 − o recuo de 1), medido no navegador em 2026-10-06. A
   palavra "Só minha classe" (72) não cabia: o tier descia para uma 2.ª linha e a lista perdia 16 px (3,5 → 3,1 receitas); agora o rótulo
   à vista é o brasão da classe (`craft.js › paintCrest`) e a palavra fica no leitor de tela e no `title`. Nenhum seletor encolhe: texto
   de `<select>` cortado não se lê (client/CLAUDE.md, o texto MAIS LONGO no print). Só a fileira na COLUNA DA LISTA (`.craft-left`) troca
   a palavra pelo brasão: a v2 leva a fileira ao cabeçalho da folha e segue com a palavra. A quebra fica de rede (fonte ainda chegando,
   brasão fora do manifesto — a palavra volta, G1): o tier desce ao INÍCIO da 2.ª linha, a 6 px dela, e não fica empilhado sob o espaço.
   O vazio da fileira não é alvo: o gesto é do interruptor e do rótulo (`craft.js › flipMyClass`). */
.craft-win .craft-myclass { flex-wrap: wrap; height: auto; min-height: calc(12 * var(--px)); column-gap: calc(2 * var(--px)); row-gap: calc(6 * var(--px)); cursor: default; }
.craft-win .craft-myclass:hover { color: var(--c-text-dim); }
.craft-win #craft-myclass-label { cursor: pointer; }
.craft-win #craft-myclass-label:hover { color: var(--c-text); }
/* o espaço também na largura natural: esticado (o `width: 100%` do `.input`), ele tomava a linha inteira ao quebrar */
.craft-win .craft-myclass > .craft-slot { flex: none; width: auto; }
/* com o espaço à vista o tier encosta nele (o par vai junto à direita, empurrado pela margem do espaço); sozinho — o Laboratório —,
   a margem automática da regra de cima o leva à direita */
.craft-win .craft-myclass > .craft-slot:not(.hidden) ~ .craft-tier { margin-left: 0; }
/* o brasão: escondido fora da coluna da lista (a v2 mostra a palavra) */
.craft-myclass-crest { display: none; }
.craft-win .craft-left > .craft-myclass > .has-crest { position: relative; }
.craft-win .craft-left > .craft-myclass > .has-crest > .craft-myclass-crest {
  display: block;
  width: calc(12 * var(--px));
  height: calc(12 * var(--px));
  background-repeat: no-repeat;
  background-size: 100% 100%;
  image-rendering: pixelated;
}
/* a palavra sai da tela e fica no leitor de tela (o `#ui-root .sr-only` de base.css, por seletor: a classe só vale com o brasão) */
.craft-win .craft-left > .craft-myclass > .has-crest > .craft-myclass-text {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
/* CABEÇALHO DA LISTA (a faixa da estação de antes): o desenho do cabeçalho de grupo do Refino (`.refine-group-head`), FIXO no alto do
   painel — a lista rola embaixo dele, o NPC e o nível ficam à vista. A barra encolhe de 32 até 16 e o JS a esconde se nem assim couber:
   o nome do NPC nunca se corta (nome próprio, UX-GRAMATICA §3). Pior caso medido: "Sabina, a Alquimista" + "Nv 50". */
.craft-win .craft-list-head {
  position: absolute;
  top: calc(-4 * var(--px));
  left: calc(-4 * var(--px));
  right: calc(-4 * var(--px));
  overflow: hidden;
}
.craft-win .craft-list-head:focus-visible { outline: var(--px) solid var(--c-gold); outline-offset: calc(-1 * var(--px)); }
.craft-win .craft-list > .craft-list-scroll { top: calc(14 * var(--px)); }
.craft-win .craft-list-npc { flex: none; white-space: nowrap; }
.craft-win .craft-list-head > .refine-group-level { margin-left: auto; }
.craft-win .craft-list-head > .bar { flex: 0 1 calc(32 * var(--px)); width: auto; min-width: calc(16 * var(--px)); }
/* DETALHE (244 × 168): as medidas do Refino — vão de 2 e sem o respiro/degradê do pé (o rodapé com o Criar é opaco e grudado embaixo).
   Pior caso de equipamento (4 atributos, 4 insumos): 36 + 20 + 12 + 74 + 18 + 4 vãos de 2 = 168, sem rolar; a rolagem fica de rede. */
.craft-win .craft-detail-inner { gap: calc(2 * var(--px)); --scroll-fade-pad: 0px; --scroll-fade: 0px; }
.craft-win .craft-head-sub { white-space: normal; }
.craft-win .craft-head-exp { display: flex; flex-wrap: wrap; align-items: center; gap: 0 calc(4 * var(--px)); }
.craft-win .craft-mats-title { display: inline-flex; align-items: center; gap: calc(4 * var(--px)); }
/* a grade do ELIXIR leva a pista (a descrição está no gesto dela — content-plan.md §2.1 › Tela): a pista tem a largura do que
   marca (UX-GRAMATICA G4), então a grade encolhe ao conteúdo em vez de riscar o detalhe de ponta a ponta. Elixir: 36 + 11 + 12 +
   74 (3 insumos em 2 filas) + 18 + 4 vãos de 2 = 159 de 168. */
.craft-win .craft-stats.has-more { align-self: flex-start; }
/* o rodapé "× [N] [Máx]  mm:ss  [Criar ◉ preço]": a quantidade à esquerda, o tempo encostado no Criar */
.craft-win .craft-foot { align-items: center; justify-content: flex-start; }
.craft-win .craft-qty { display: flex; align-items: center; gap: calc(3 * var(--px)); flex: none; }
.craft-win .craft-time { flex: none; margin-left: auto; white-space: nowrap; }
/* o preço DENTRO do Criar: a cor do rótulo; a moeda tem 9 e o miolo do botão 8 (o molde do `Redistribuir`, abilities.css) */
.craft-win #craft-make > .gold-label { color: inherit; }
.craft-win #craft-make > .gold-label > .ico-gold { margin: calc(-1 * var(--px)) 0; }
/* --- prog --- A FORJA COM A PEÇA ANTERIOR (js/ui/windows/craft.js; docs/specs/professions.md §11.10): a vaga da peça ANTES do produto —
   `[velha] → [nova] Nome`, a cabeça na MESMA altura (36). Escolher = o fantasma da posição na moldura de destaque, pulsando (a vaga que
   espera); faltar = o ícone do modelo apagado e o ✖ no canto ↘ (a gramática do insumo que falta); o nome da receita vai a até 2 linhas
   (com a vaga, o texto da cabeça tem 144 px: 35 dos 406 nomes do T2+ pedem a 2.ª). */
.craft-win .craft-prev { display: flex; align-items: center; gap: calc(2 * var(--px)); flex: none; cursor: pointer; }
.craft-win .craft-prev[aria-disabled='true'] { cursor: default; }
.craft-win .craft-prev:focus-visible { outline: var(--px) solid var(--c-gold); outline-offset: var(--px); }
.craft-win .craft-prev > .slot { flex: none; touch-action: auto; }
.craft-win .craft-prev.is-empty > .slot { border-image-source: url(../assets/ui/slots/slot_hover.png); animation: craft-prev-pulse 1.6s ease-in-out infinite; }
.craft-win .craft-prev.is-missing > .slot .item-icon { opacity: 0.45; }
.craft-win .craft-prev-mark { display: none; position: absolute; right: calc(1 * var(--px)); bottom: calc(-1 * var(--px)); color: var(--c-danger); line-height: 1; }
.craft-win .craft-prev.is-missing .craft-prev-mark { display: block; }
.craft-win .craft-prev-arrow { flex: none; width: calc(8 * var(--px)); text-align: center; color: var(--c-gold); }
.craft-win .craft-prev:not(.hidden) ~ .craft-head-text > .craft-head-name {
  white-space: normal;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
@keyframes craft-prev-pulse { 50% { filter: brightness(1.35); } }
@media (prefers-reduced-motion: reduce) { .craft-win .craft-prev.is-empty > .slot { animation: none; } }
/* os selos do que NÃO passa (G2/G5): `Teto do nível` no desenho do selo de requisito, sem o cadeado (perigo); `Sem corrupção` e `No
   corpo` no selo da série, em ouro (pede atenção) */
.craft-win .craft-keep-info { color: var(--c-gold); }
.craft-win .craft-keep-loss { padding: 0 calc(2 * var(--px)); }
/* as células da TAXA de manter, PRIMEIRO na grade, com o fio de ouro à esquerda (a mesma linha de material) */
.craft-win .craft-mat.is-keep { box-shadow: inset calc(2 * var(--px)) 0 var(--c-gold); padding-left: calc(3 * var(--px)); }
/* MANTER no lugar da quantidade: o interruptor da série com o ícone da Refinaria */
.craft-win .craft-foot > #craft-keep { flex: none; }
/* os DIÁLOGOS da forja (fora do `.craft-win`: o diálogo é anexado ao corpo da página) — a transformação da confirmação e do Cancelar
   da faixa, e o seletor vazio que é a porta de "Onde conseguir" (`widgets/piecePicker.js`) */
.forge-confirm-pair { display: flex; align-items: center; gap: calc(4 * var(--px)); margin-bottom: calc(4 * var(--px)); }
.forge-confirm-pair > .slot { flex: none; }
.forge-confirm-pair:focus-visible { outline: var(--px) solid var(--c-gold); outline-offset: var(--px); }
.forge-confirm-arrow { color: var(--c-gold); }
.piece-picker-empty { display: flex; flex-direction: column; gap: calc(4 * var(--px)); }
.piece-picker-model { display: flex; align-items: center; gap: calc(4 * var(--px)); }
.piece-picker-model > .temper-picker-name { flex: 1; min-width: 0; }
/* --- /craft-win --- */
