/* --- temper --- A Refinaria: a FORJA VIVA (docs/specs/temper.md §11.1; js/ui/windows/temper.js, ui/temperDirector.js).
   Medidas em px de arte: calc(N * var(--px)); animação sempre em steps(); prefers-reduced-motion no fim.
   O corpo (580 × 246) é uma grade ficha 168 · 6 · palco 232 · 6 · ritos 168. Na PORTA (sem peça) só o palco, na largura toda — e a
   composição fica no MESMO x (290): o `.temper-rig` de 232 mora centrado no palco, com peça ou sem.
   NENHUM `overflow` de rolagem aqui: quem rola é a classe `scroll-fade` (base.css) posta pelo JS (só a ficha e o detalhe da aba), e o
   degradê é de scroll-fade.css (B74 — client/tests/ui/scrollFade.test.js). Cor só por token de base.css; as cores de qualidade
   (.q0….q5 / --q0…--q5) são geradas pelo main.js.
   EMPILHAMENTO: o corpo é o contexto (`isolation: isolate`); o palco NÃO cria contexto (sem z-index nem transform), para a placa
   (z 7) ficar por cima da camada de FX do corpo (z 5) e do clarão (z 6): fundo · braseiros · forja · FX de trás · coroa · vaga ·
   #temper-fx · clarão · placa. Tremor e escala só em filhos da janela, nunca nela (ui-gameplay.md §0.1). */
.temper-body {
  position: relative;
  display: grid;
  grid-template-columns: calc(168 * var(--px)) calc(232 * var(--px)) calc(168 * var(--px));
  gap: calc(6 * var(--px));
  height: 100%;
  min-height: 0;
  line-height: calc(10 * var(--px));
  overflow: hidden;
  isolation: isolate;
}
.temper-body.is-door { grid-template-columns: 1fr; }
.temper-body.is-door > .temper-ficha, .temper-body.is-door > .temper-side { display: none; }
.temper-ficha, .temper-side { display: flex; flex-direction: column; gap: calc(4 * var(--px)); min-height: 0; min-width: 0; }

/* ---- O PALCO ---------------------------------------------------------------------------------------------------------- */
.temper-stage { position: relative; min-width: 0; min-height: 0; overflow: hidden; }
.temper-body.is-door > .temper-stage { cursor: pointer; }
/* o nicho: a peça 9-slice `ui/temper_stage` (slice 16); sem ela no manifesto, a pedra lisa com o fio de brasa */
.temper-stage-bg { position: absolute; inset: 0; background: var(--c-forge-bg); border: var(--px) solid var(--c-forge-rim); pointer-events: none; }
.temper-stage-bg.has-art {
  background: none;
  border: calc(16 * var(--px)) solid transparent;
  border-image: var(--ui-temper_stage) 16 fill / calc(16 * var(--px)) stretch;
  image-rendering: pixelated;
}
.temper-rig { position: absolute; left: 50%; top: 0; width: calc(232 * var(--px)); height: calc(248 * var(--px)); margin-left: calc(-116 * var(--px)); }
/* a FORJA e os braseiros: props do pipeline, tira de `--n` quadros, ancorados pela base em F (o chão, y 200). O JS escreve a
   largura, a altura e o centro (`margin-left`); a tira anda em steps() — a bigorna nunca se move, só o miolo do poço. */
.temper-forge, .temper-brazier { position: absolute; left: 50%; bottom: calc(48 * var(--px)); background-repeat: no-repeat; background-size: calc(var(--n, 1) * 100%) 100%; image-rendering: pixelated; pointer-events: none; }
.temper-forge.is-anim, .temper-brazier.is-anim { animation: temper-strip var(--dur, 1333ms) steps(var(--n, 1)) infinite; }
@keyframes temper-strip { from { background-position-x: 0; } to { background-position-x: calc(var(--n, 1) * -1 * var(--fw, 0px)); } }
.temper-brazier { display: none; }
.temper-brazier.is-left { left: calc(-80 * var(--px)); }
.temper-brazier.is-right { left: calc(312 * var(--px)); transform: scaleX(-1); }
.temper-body.is-door .temper-brazier.has-art { display: block; }
/* o poço muda de humor com a cena: clareia quando a moeda cai, "inspira" no laço de espera e fica violeta na corrupção */
.temper-forge.is-flare { filter: brightness(1.5); }
/* (sem `hue-rotate`: a pedra cinza-azulada virava verde; quem pinta o poço de violeta é a chama `fx/temper_void#seep`, por cima) */
.temper-forge.is-void { filter: saturate(0.35) brightness(0.8); }
.temper-forge.is-breathe.is-anim { animation: temper-strip var(--dur, 1333ms) steps(var(--n, 1)) infinite, temper-breathe 0.25s steps(2) infinite; }
@keyframes temper-breathe { 50% { filter: brightness(1.35); } }
/* as BRASAS do repouso: cinco, em sequência fixa, todas nascendo DENTRO da boca do poço (o JS dá o x, o intervalo e a fase). Com a folha
   `fx/temper_ember` (6 quadros 32×32 na grade de 8 colunas do pipeline: a folha tem 256 × 32, 512 × 64 a 2×) a brasa salta em arco nos
   primeiros 15 % do ciclo; sem ela, uma faísca de 2 px sobe do poço. */
.temper-embers { position: absolute; inset: 0; pointer-events: none; }
.temper-ember { position: absolute; top: calc(126 * var(--px)); width: calc(64 * var(--px)); height: calc(64 * var(--px)); opacity: 0; animation: temper-spark var(--dur, 2s) infinite; }
.temper-embers.has-art > .temper-ember { background: var(--ember) 0 0 / calc(512 * var(--px)) calc(64 * var(--px)) no-repeat; image-rendering: pixelated; animation-name: temper-ember; }
.temper-embers:not(.has-art) > .temper-ember::after { content: ''; position: absolute; left: calc(31 * var(--px)); bottom: calc(8 * var(--px)); width: calc(2 * var(--px)); height: calc(2 * var(--px)); background: var(--c-forge-rim); }
@keyframes temper-ember {
  0% { opacity: 1; background-position-x: 0; animation-timing-function: steps(6, end); }
  15% { opacity: 1; background-position-x: calc(-384 * var(--px)); }
  15.01%, 100% { opacity: 0; }
}
@keyframes temper-spark {
  0% { opacity: 1; transform: translateY(0); animation-timing-function: steps(6, end); }
  15% { opacity: 1; transform: translateY(calc(-24 * var(--px))); }
  15.01%, 100% { opacity: 0; transform: translateY(0); }
}
.temper-fx-back { position: absolute; inset: 0; pointer-events: none; }

/* ---- A COROA: o +N desenhado em 20 runas 8×8 num arco sobre a vaga (o JS dá a caixa de cada uma; `--i` = o índice) ---- */
.temper-crown { position: absolute; inset: 0; pointer-events: none; }
.temper-rune { position: absolute; width: calc(8 * var(--px)); height: calc(8 * var(--px)); background-repeat: no-repeat; background-size: 100% 100%; image-rendering: pixelated; color: var(--c-field-edge); }
/* a luz que passa por cima da runa (o cometa do repouso, o clarão do acerto, o branco do Radiante): um véu, nunca `filter` */
.temper-rune::before { content: ''; position: absolute; inset: 0; background: var(--c-gold); opacity: 0; animation: temper-comet 4s steps(1) infinite; animation-delay: calc(var(--i, 0) * 200ms); }
@keyframes temper-comet { 0% { opacity: 0.5; } 5%, 100% { opacity: 0; } }
/* o cometa é a vida do REPOUSO (e da porta): durante o rito ele apaga — a luz da coroa passa a ser da cena (a corrupção a suga, o Radiante a
   pinta de branco) e uma runa apagada acendendo em ouro no meio da corrupção desmentia a sucção. O branco e os clarões têm regra própria. */
.temper-stage:not([data-stage="idle"]):not([data-stage="door"]) .temper-rune:not(.is-white):not([class*="is-fx-"])::before { animation: none; opacity: 0; }
/* a runa ALVO do golpe (a próxima) fica acima da camada de FX do corpo (z 5) durante o rito: o martelo erguido para sobre o arco direito da
   coroa e cobria justo ela (no +12 a +15). O clarão (z 6, depois no DOM) e a placa (z 7) continuam por cima. */
.temper-rune.is-target { z-index: 6; }
/* com a arte, o véu acende só o DESENHO da runa (a pedra oitavada, o losango, a estrela): a máscara é a própria folha do estado (`--rune`, o
   JS a escreve junto com o fundo) — o quadrado 8×8 acendia os cantos vazios e a runa virava um bloco no meio do arco */
.temper-crown.has-art .temper-rune::before { -webkit-mask: var(--rune) 0 0 / 100% 100% no-repeat; mask: var(--rune) 0 0 / 100% 100% no-repeat; }
/* sem a peça `ico_temper_rune` no manifesto: um quadrado (runa) ou um losango (marco) de 4 px, na cor do estado — a FORMA diz o marco */
.temper-crown:not(.has-art) .temper-rune::after { content: ''; position: absolute; inset: calc(2 * var(--px)); background: currentColor; }
.temper-crown:not(.has-art) .temper-rune[data-state^="mark"]::after, .temper-crown:not(.has-art) .temper-rune[data-state="sealed_mark"]::after { transform: rotate(45deg); }
.temper-crown:not(.has-art) .temper-rune[data-state="off"], .temper-crown:not(.has-art) .temper-rune[data-state="mark"] { color: var(--c-text-dim); opacity: 0.45; }
.temper-crown:not(.has-art) .temper-rune[data-state="next"], .temper-crown:not(.has-art) .temper-rune[data-state="mark_next"] { color: var(--c-text-dim); outline: var(--px) solid var(--c-gold); }
.temper-crown:not(.has-art) .temper-rune[data-state="lit"], .temper-crown:not(.has-art) .temper-rune[data-state="mark_lit"] { color: var(--c-gold); }
.temper-crown:not(.has-art) .temper-rune[data-state="lost"] { color: var(--c-danger); }
.temper-crown:not(.has-art) .temper-rune[data-state="sealed"], .temper-crown:not(.has-art) .temper-rune[data-state="sealed_mark"] { color: var(--c-void); }
.temper-crown:not(.has-art) .temper-rune[data-state="over"] { color: var(--c-radiant); }
/* a PRÓXIMA runa chama: pulsa em 2 passos; a Brasa acelera (data-ember 1/2/3) e o laço de espera de um refino arriscado mais ainda */
.temper-rune[data-state="next"], .temper-rune[data-state="mark_next"] { animation: temper-next 1.2s steps(2) infinite; }
.temper-rune[data-ember="1"] { animation-duration: 0.9s; }
.temper-rune[data-ember="2"] { animation-duration: 0.6s; }
.temper-rune[data-ember="3"] { animation-duration: 0.4s; }
.temper-crown[data-pulse="fast"] .temper-rune[data-state="next"], .temper-crown[data-pulse="fast"] .temper-rune[data-state="mark_next"] { animation-duration: 0.25s; }
@keyframes temper-next { 50% { opacity: 0.4; } }
/* Proteger: na carga, as runas acesas ganham aro de ouro */
.temper-crown.is-warded .temper-rune[data-state="lit"], .temper-crown.is-warded .temper-rune[data-state="mark_lit"] { outline: var(--px) solid var(--c-gold); }
/* os instantes do rito (o diretor põe a classe; a coroa volta ao estado da peça na revelação) */
.temper-rune.is-white::before { background: var(--c-radiant); opacity: 0.9; animation: none; }
.temper-rune.is-fx-flash::before { background: var(--c-radiant); animation: temper-rune-flash 0.18s steps(3) 1 both; }
.temper-rune.is-fx-blink { animation: temper-next 0.12s steps(2) 2; }
.temper-rune.is-fx-held::before, .temper-rune.is-fx-ember::before { animation: temper-rune-flash 0.36s steps(3) 1 both; }
@keyframes temper-rune-flash { from { opacity: 0.9; } to { opacity: 0; } }

/* ---- A VAGA 2× (72×72 em P): o centro das atenções ---- */
.temper-slot { position: absolute; left: calc(80 * var(--px)); top: calc(40 * var(--px)); width: calc(72 * var(--px)); height: calc(72 * var(--px)); transition: top 0.12s steps(2); }
/* a peça ASSENTA na bigorna (S = P + 12) enquanto o martelo sobe, e volta depois do golpe */
.temper-slot.is-seat { top: calc(52 * var(--px)); }
.temper-slot:focus-visible { outline: none; }
.temper-slot:focus-visible > .slot { outline: var(--px) solid var(--c-gold); outline-offset: var(--px); }
/* a peça da bancada é alvo do menu de item (ui-gameplay.md §0.4): o slot solta o `touch-action: none` do arrasto da Mochila */
.temper-slot > .slot { touch-action: auto; animation: temper-breath 1.6s steps(2) infinite; }
@keyframes temper-breath { 50% { transform: translateY(calc(-2 * var(--px))); } }
/* o `+N` dobra junto com a vaga 2×: o `.slot-refine` só dobra a posição e a sombra (`--spx`), e a 8 px de arte a sombra de 2 px
   não encosta no traço — vira uma gaiola de cópias em volta do número (medido no palco a 3× em 2026-10-02) */
.temper-slot .slot-refine { font-size: calc(2 * var(--text-1)); }
/* VAZIA, a vaga é a porta do seletor: a moldura `slot_hover` pulsa e as silhuetas `ghost_*` passam, a 2× e 70 % */
.temper-slot.is-empty { cursor: pointer; }
.temper-slot.is-empty > .slot { animation: none; }
.temper-slot.is-empty::after { content: ''; position: absolute; inset: 0; border: calc(8 * var(--px)) solid transparent; border-image: url(../assets/ui/slots/slot_hover.png) 4 / calc(8 * var(--px)) stretch; image-rendering: pixelated; pointer-events: none; animation: temper-vaga 1.2s steps(2) infinite; }
@keyframes temper-vaga { 50% { opacity: 0.25; } }
/* …e é o ponto MAIS ACESO da porta (o centro das atenções, no pedido do dono): uma luz quente, mais alta embaixo (sobe do poço), soma luz à
   vaga, à moldura e à silhueta, no ritmo da moldura — sem ela a vaga era o miolo mais escuro do centro e o olho ia para os braseiros */
.temper-slot.is-empty::before { content: ''; position: absolute; z-index: 1; left: calc(-26 * var(--px)); right: calc(-26 * var(--px)); top: calc(-18 * var(--px)); bottom: calc(-46 * var(--px)); background: radial-gradient(closest-side at 50% 58%, var(--c-gold), transparent); opacity: 0.34; mix-blend-mode: screen; pointer-events: none; animation: temper-vaga-glow 1.2s steps(2) infinite; }
@supports (mix-blend-mode: plus-lighter) { .temper-slot.is-empty::before { mix-blend-mode: plus-lighter; } }
@keyframes temper-vaga-glow { 50% { opacity: 0.22; } }
.temper-slot.is-empty[aria-disabled="true"] { cursor: progress; }
.temper-slot.is-empty[aria-disabled="true"]::after { border-image-source: url(../assets/ui/slots/slot_pending.png); animation: none; }
.temper-slot.is-empty[aria-disabled="true"]::before { animation: none; opacity: 0.14; }
.temper-ghost { position: absolute; inset: calc(4 * var(--px)); background-repeat: no-repeat; background-size: 100% 100%; image-rendering: pixelated; opacity: 0.7; pointer-events: none; background-image: var(--ui-ghost_weapon, none); animation: temper-ghosts 12s steps(1) infinite; }
@keyframes temper-ghosts {
  0% { background-image: var(--ui-ghost_weapon, none); }
  10% { background-image: var(--ui-ghost_helmet, none); }
  20% { background-image: var(--ui-ghost_armor, none); }
  30% { background-image: var(--ui-ghost_gloves, none); }
  40% { background-image: var(--ui-ghost_pants, none); }
  50% { background-image: var(--ui-ghost_boots, none); }
  60% { background-image: var(--ui-ghost_cape, none); }
  70% { background-image: var(--ui-ghost_necklace, none); }
  80% { background-image: var(--ui-ghost_ring, none); }
  90%, 100% { background-image: var(--ui-ghost_earring, none); }
}
/* a porta do resumo: a marca do efeito recém-desbloqueado paira na vaga (a arte útil da wmark é o canto 12×12 do PNG 32×32) */
.temper-door-mark { position: absolute; left: calc(12 * var(--px)); top: calc(12 * var(--px)); width: calc(48 * var(--px)); height: calc(48 * var(--px)); background-repeat: no-repeat; background-position: 0 0; background-size: calc(128 * var(--px)) calc(128 * var(--px)); image-rendering: pixelated; pointer-events: none; animation: temper-hover 1.2s steps(2) infinite; }
@keyframes temper-hover { 50% { transform: translateY(calc(-2 * var(--px))); opacity: 0.7; } }
/* a cena mexe na vaga: a peça clareia antes das runas, treme enquanto a luz se junta (suave) ou a sombra sobe (irregular), e some
   em 4 passos quando o Radiante a destrói */
.temper-slot.is-glow > .slot { animation: temper-glow 0.24s steps(3) 1; }
@keyframes temper-glow { from { filter: brightness(2.2); } to { filter: none; } }
.temper-slot.is-tremble > .slot { animation: temper-tremble 0.08s steps(2) infinite; }
@keyframes temper-tremble { 50% { transform: translateX(var(--px)); } }
.temper-slot.is-quake > .slot { animation: temper-quake 0.48s steps(1) infinite; }
@keyframes temper-quake {
  0%, 33.3%, 83.3%, 100% { transform: none; }
  16.6%, 66.6% { transform: translateX(var(--px)); }
  50% { transform: translateX(calc(-1 * var(--px))); }
}
/* a marca do efeito escolhido paira sobre a peça enquanto o ouro derrete (Imbuir) e desce em 4×, 3×, 2× até o canto ↖ da vaga */
.temper-wmark { position: absolute; left: calc(92 * var(--px)); top: calc(52 * var(--px)); display: none; background-repeat: no-repeat; background-position: 0 0; image-rendering: pixelated; pointer-events: none; }
.temper-wmark[data-scale] { display: block; }
.temper-wmark[data-scale="4"] { width: calc(48 * var(--px)); height: calc(48 * var(--px)); background-size: calc(128 * var(--px)) calc(128 * var(--px)); }
.temper-wmark[data-scale="3"] { width: calc(36 * var(--px)); height: calc(36 * var(--px)); background-size: calc(96 * var(--px)) calc(96 * var(--px)); }
.temper-wmark[data-scale="2"], .temper-wmark[data-scale="1"] { width: calc(24 * var(--px)); height: calc(24 * var(--px)); background-size: calc(64 * var(--px)) calc(64 * var(--px)); }
.temper-wmark.is-hover { animation: temper-wmark 0.8s steps(2) infinite; }
@keyframes temper-wmark { from { opacity: 0.3; } to { opacity: 0.6; } }

/* ---- luz: o clarão (do palco e do corpo), as faixas Radiantes só no palco, e a camada de FX do corpo inteiro ---- */
.temper-flash { position: absolute; inset: 0; opacity: 0; pointer-events: none; z-index: 6; background: var(--c-gold); }
.temper-flash[data-step="1"] { opacity: 0.42; }
.temper-flash[data-step="2"] { opacity: 0.22; }
.temper-flash[data-step="3"] { opacity: 0.1; }
.temper-flash[data-tone="danger"] { background: var(--c-danger); }
.temper-flash[data-tone="void"] { background: var(--c-void); }
/* os clarões de LUZ (ouro, branco, a cor da qualidade) são uma luz que NASCE NA PEÇA — P: o meio do palco, 76 px do topo (no corpo, o mesmo
   meio: 290 = 50 %) —, branca no miolo, na cor do clarão em volta e transparente nas bordas, SOMADA à cena (`plus-lighter`; `screen` de
   reserva). O véu chapado de ouro, mesmo somado, deixava o palco inteiro pardo no golpe (o fundo media rgb(124,104,69) contra
   rgb(30,30,42) em repouso, 2026-10-02): a cena tem de acender na peça, não sujar. Perigo e vazio continuam tingindo o quadro inteiro. */
.temper-flash[data-tone="gold"] { --flash: var(--c-gold); }
.temper-flash[data-tone="white"] { --flash: var(--c-radiant); }
.temper-flash[data-tone="q0"] { --flash: var(--q0, var(--c-text)); }
.temper-flash[data-tone="q1"] { --flash: var(--q1, var(--c-ok)); }
.temper-flash[data-tone="q2"] { --flash: var(--q2, var(--c-gold)); }
.temper-flash[data-tone="q3"] { --flash: var(--q3, var(--c-void)); }
.temper-flash[data-tone="q4"] { --flash: var(--q4, var(--c-gold)); }
.temper-flash[data-tone="q5"] { --flash: var(--q5, var(--c-radiant)); }
.temper-flash[data-tone="gold"], .temper-flash[data-tone="white"], .temper-flash[data-tone^="q"] {
  background: radial-gradient(circle calc(112 * var(--px)) at 50% calc(76 * var(--px)), var(--c-radiant) 0, var(--flash, var(--c-gold)) calc(30 * var(--px)), transparent calc(112 * var(--px)));
  mix-blend-mode: screen;
}
@supports (mix-blend-mode: plus-lighter) { .temper-flash[data-tone="gold"], .temper-flash[data-tone="white"], .temper-flash[data-tone^="q"] { mix-blend-mode: plus-lighter; } }
.temper-bands { position: absolute; inset: 0; opacity: 0; pointer-events: none; z-index: 2; background-repeat: repeat; background-size: auto 100%; image-rendering: pixelated; mix-blend-mode: screen; }
.temper-bands[data-step="1"] { opacity: 0.3; }
.temper-bands[data-step="2"] { opacity: 0.22; }
.temper-bands[data-step="3"] { opacity: 0.14; }
.temper-bands[data-step="4"] { opacity: 0.06; }
.temper-fx { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 5; }
.temper-fx-sprite { position: absolute; background-repeat: no-repeat; image-rendering: pixelated; pointer-events: none; }
.temper-fx-sprite.is-add { mix-blend-mode: screen; }
@supports (mix-blend-mode: plus-lighter) { .temper-fx-sprite.is-add { mix-blend-mode: plus-lighter; } }
.temper-fx-sprite[data-fade="1"] { opacity: 0.66; }
.temper-fx-sprite[data-fade="2"] { opacity: 0.33; }
.temper-fx-sprite[data-fade="3"] { opacity: 0; }
/* o OURO vira forja: a moeda `ico_gold` (9×9) a 2×, do botão de preço ao poço; e a brasa da falha, do poço à próxima runa */
.temper-coin { position: absolute; width: calc(18 * var(--px)); height: calc(18 * var(--px)); background: var(--ui-ico_gold, none) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; }
.temper-coin.is-dark { filter: brightness(0.55) hue-rotate(230deg) saturate(1.5); }
/* a brasa da falha: núcleo claro, aro de ouro e borda de fogo (6 px de arte) — o quadrado liso de 4 px se lia como cisco na bigorna */
.temper-pity { position: absolute; width: calc(2 * var(--px)); height: calc(2 * var(--px)); background: var(--c-radiant); box-shadow: 0 0 0 var(--px) var(--c-gold), 0 0 0 calc(2 * var(--px)) var(--c-forge-rim); }
/* o escurecer das duas cenas (Radiante e Corrupção): a ficha e os ritos apagam em 3 passos; o palco fica aceso — e, na corrupção, a BARRA
   DAS CHANCES e a agulha também (é nelas que o olho tem de estar). Por isso o filtro vai nos filhos, não na coluna dos ritos inteira. */
.temper-body[class*="is-dim-"] > .temper-ficha,
.temper-body[class*="is-dim-"] > .temper-side > :not(.temper-detail),
.temper-body[class*="is-dim-"] .temper-detail > :not(.temper-bar-box),
.temper-body[class*="is-dim-"] .temper-bar-box > :not(.temper-bar):not(.temper-needle) { filter: brightness(var(--dim, 1)); }
.temper-body.is-dim-1 { --dim: 0.7; }
.temper-body.is-dim-2 { --dim: 0.55; }
.temper-body.is-dim-3 { --dim: 0.45; }
/* o silêncio (o Radiante prende o fôlego) e o sono (aba oculta; modal aberto ou janela tapada: o `inert` do gerenciador): os laços param */
.temper-body.is-hush .temper-ember, .temper-body.is-hush .temper-rune::before, .temper-body.is-hush .temper-forge { animation-play-state: paused; }
.temper-body.is-asleep *, .temper-body.is-asleep *::before, .temper-body.is-asleep *::after,
[inert] .temper-body *, [inert] .temper-body *::before, [inert] .temper-body *::after { animation-play-state: paused; }
/* a INVOCAÇÃO (a peça escolhida): a vaga cai em 3 passos, as runas acendem de +1 a +N (25 ms cada) e as colunas aparecem */
.temper-body.is-invoke .temper-slot > .slot { animation: temper-drop 0.12s steps(3) 1; }
@keyframes temper-drop { from { transform: translateY(calc(-18 * var(--px))); opacity: 0.4; } to { transform: none; opacity: 1; } }
.temper-body.is-invoke .temper-rune[data-state="lit"], .temper-body.is-invoke .temper-rune[data-state="mark_lit"],
.temper-body.is-invoke .temper-rune[data-state="sealed"], .temper-body.is-invoke .temper-rune[data-state="sealed_mark"] { animation: temper-rune-in 0.05s steps(2) 1 both; animation-delay: calc(120ms + var(--i, 0) * 25ms); }
@keyframes temper-rune-in { from { opacity: 0.2; } to { opacity: 1; } }
.temper-body.is-invoke > .temper-ficha, .temper-body.is-invoke > .temper-side { animation: temper-cols-in 0.16s steps(2) 1 both; }
@keyframes temper-cols-in { from { opacity: 0; } to { opacity: 1; } }

/* ---- A PLACA (os 48 px de baixo do palco; cresce para cima até 72): a prévia da opção, e depois de cada rito a revelação (N6).
   6 px de folga embaixo: a moldura do palco passa por cima dela e a última linha de um recibo de 3 linhas encostava no fio ---- */
.temper-plaque { position: absolute; left: 0; right: 0; bottom: 0; z-index: 7; display: flex; flex-direction: column; justify-content: center; gap: var(--px); min-height: calc(48 * var(--px)); max-height: calc(72 * var(--px)); padding: calc(2 * var(--px)) calc(5 * var(--px)) calc(6 * var(--px)); text-align: center; overflow: hidden; }
.temper-plaque::before { content: ''; position: absolute; inset: 0; background: var(--c-forge-bg); opacity: 0.84; z-index: -1; }
.temper-plaque:empty { display: none; }
.temper-invite { color: var(--c-gold); font-size: var(--text-2); line-height: 1; }
.temper-body.is-door:hover .temper-invite, .temper-slot.is-empty:focus-visible ~ .temper-invite { text-decoration: underline; }
.temper-wait, .temper-corrupted-line { color: var(--c-text-dim); }
.temper-corrupted-line { color: var(--c-danger); }
.temper-oracle, .temper-reveal { display: flex; flex-direction: column; align-items: center; gap: var(--px); }
.temper-oracle-line { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center; gap: calc(3 * var(--px)); }
.temper-oracle-line.is-dim, .temper-reveal-sub { color: var(--c-text-dim); }
.temper-oracle-line.is-danger, .temper-reveal-sub.is-danger, .temper-reveal-line.is-danger { color: var(--c-danger); }
.temper-reveal-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: calc(4 * var(--px)); }
/* --text-2 só para a forma curta (até 22 caracteres: o JS decide); nunca reticências */
.temper-reveal-line.is-big { font-size: var(--text-2); line-height: 1; }
/* o RECIBO do laço (N6): "12 tentativas · [moeda] 22.500 · [refinado] 24" numa fila — o ponto médio entre famílias (G1), o vão entre
   fichas maior que o de dentro; cada material é a peça mini (20) com o número, e o toque é "Onde conseguir" */
.temper-receipt-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--px) calc(4 * var(--px)); color: var(--c-text); }
.temper-receipt-row > .ico-gold { margin-right: calc(-2 * var(--px)); }
.temper-receipt-mat { display: inline-flex; align-items: center; gap: calc(2 * var(--px)); cursor: pointer; }
.temper-receipt-mat:focus-visible { outline: var(--px) solid var(--c-gold); outline-offset: var(--px); }
.temper-sep { color: var(--c-text-dim); }
/* o RECIBO do set (N6; docs/specs/temper.md §5.1): até 3 peças "[peça] [atributo] +5" numa fila, o ponto médio entre elas e "e mais N" (a lista
   inteira no gesto dele); a peça é a mini (20), alvo do menu de consulta. Cada entrada e o "e mais N" têm 24 de altura (o toque mínimo
   do celular deitado, o lint W9.1): o "e mais N" quebra para a 2.ª fila e, com 11, era o alvo mais difícil da placa — as duas filas
   cabem nos 72 da placa */
.temper-set-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0 calc(4 * var(--px)); color: var(--c-text); }
.temper-set-entry { display: inline-flex; align-items: center; gap: calc(2 * var(--px)); min-height: calc(24 * var(--px)); white-space: nowrap; }
.temper-set-entry:focus-visible { outline: var(--px) solid var(--c-gold); outline-offset: var(--px); }
/* o pontilhado da pista (`.has-more` — base.css) vai para o RÓTULO, colado no texto, e não para o pé da caixa de 24 (o molde do `.btn` com
   pista: a margem −1 devolve o pixel do pontilhado) */
.temper-set-more { display: inline-flex; align-items: center; min-height: calc(24 * var(--px)); white-space: nowrap; }
#ui-root .temper-plaque .temper-set-more[data-hint].has-more { border-bottom: 0; }
#ui-root .temper-plaque .temper-set-more[data-hint].has-more > span { border-bottom: var(--px) dotted rgba(244, 240, 230, 0.4); margin-bottom: calc(-1 * var(--px)); }
/* o recibo da porta ("… voltou ao corpo." do Vestir de novo, N6): apagado acima do convite */
.temper-reveal.is-dim { color: var(--c-text-dim); }
.temper-plaque[data-tone="up"] .temper-reveal-line, .temper-plaque[data-tone="boon"] .temper-reveal-line, .temper-plaque[data-tone="abyss"] .temper-reveal-line { color: var(--c-gold); }
.temper-plaque[data-tone="down"] .temper-reveal-line, .temper-plaque[data-tone="bane"] .temper-reveal-line { color: var(--c-danger); }
.temper-reveal-line .q0, .temper-reveal-line .q1, .temper-reveal-line .q2, .temper-reveal-line .q3, .temper-reveal-line .q4, .temper-reveal-line .q5 { font: inherit; }
/* a revelação CAI no lugar, acesa (3 passos): sem escala — a manchete escalada cobria o selo ao lado e, nas longas, era cortada pela
   borda do palco. A queda é de 2 px, a folga de cima da placa: de mais alto, o selo nascia cortado. O nó nasce UMA vez por recibo
   (`renderPlaque` não o refaz), então o salto não se repete. */
.temper-reveal:not(.is-dim) > .temper-reveal-head { animation: temper-reveal 0.18s steps(3) 1; }
@keyframes temper-reveal { from { transform: translateY(calc(-2 * var(--px))); filter: brightness(1.8); } to { transform: none; filter: none; } }

/* ---- A FICHA (168): o ESTADO da peça — nome inteiro, selos, atributos base, adicionais, efeito ---- */
.temper-ficha-body { display: flex; flex-direction: column; gap: calc(2 * var(--px)); flex: 1 1 auto; min-height: 0; min-width: 0; }
.temper-piece-name { overflow-wrap: anywhere; flex-shrink: 0; }
.temper-refine { color: var(--c-gold); margin-left: calc(3 * var(--px)); display: inline-block; }
.temper-seals { display: flex; flex-wrap: wrap; gap: calc(2 * var(--px)); flex-shrink: 0; }
.temper-badge { display: inline-block; padding: 0 calc(2 * var(--px)); line-height: calc(9 * var(--px)); color: var(--c-text-dim); border: var(--px) solid currentColor; white-space: nowrap; font-size: var(--text-1); }
.temper-badge.is-gold { color: var(--c-gold); }
.temper-badge.is-danger { color: var(--c-danger); }
.temper-ico { flex: none; width: calc(16 * var(--px)); height: calc(16 * var(--px)); image-rendering: pixelated; background-repeat: no-repeat; background-size: 100% 100%; }
.temper-base { display: flex; flex-wrap: wrap; gap: var(--px) calc(6 * var(--px)); flex-shrink: 0; }
.temper-stat { display: inline-flex; align-items: center; gap: calc(2 * var(--px)); white-space: nowrap; }
.temper-delta { white-space: nowrap; }
.temper-delta.is-up { color: var(--c-ok); }
.temper-delta.is-down { color: var(--c-danger); }
.temper-delta.is-new { color: var(--c-gold); }
.temper-affix-row { display: flex; align-items: baseline; gap: calc(3 * var(--px)); color: var(--c-ok); flex-shrink: 0; }
.temper-affix-row > .temper-affix-label { flex: 1 1 auto; min-width: 0; }
.temper-affix-row > .temper-badge { flex-shrink: 0; }
/* a Maldição: a linha do adicional em vermelho, com o selo Maldição (a cor nunca sozinha) */
.temper-affix-row.is-cursed { color: var(--c-danger); }
/* na prévia do que tira adicional (Anular, Limpar, Caos, o escolhido do Transmutar), as linhas que podem sair ficam tracejadas */
.temper-affix-row.is-atrisk { border-bottom: var(--px) dashed var(--c-text-dim); }
/* as linhas que ENTRARAM (Encantar, Transmutar, Caos, a corrupção) chegam uma a uma, 120 ms cada, desde o impacto: `--n` = a ordem,
   `--since` = quanto já passou quando a ficha foi redesenhada (a revelação redesenha 150 ms depois e a entrada não recomeça) */
.temper-affix-row.is-entering { animation: temper-enter 0.12s steps(2) 1 backwards; animation-delay: calc(var(--n, 0) * 120ms - var(--since, 0ms)); }
@keyframes temper-enter { from { opacity: 0; } }
/* as marcas da revelação: o novo queima de ouro para a cor normal; o que saiu fica riscado em vermelho e some em 3 passos. As MARCAS ficam
   até a próxima ação; a animação delas toca UMA vez — só no redesenho da revelação, que traz `.is-fresh` (senão cada redesenho da ficha as
   repetia: o +N saltava de novo no fim do rito) */
.temper-ficha-body.is-fresh .temper-affix-row[data-mark="new"] > .temper-affix-label, .temper-ficha-body.is-fresh .temper-effect.is-new > span:last-child { animation: temper-new 0.36s steps(3) 1; }
@keyframes temper-new { from { color: var(--c-gold); } }
.temper-ficha-body.is-fresh .temper-affix-row[data-mark="cursed"] > .temper-affix-label { animation: temper-cursed 0.36s steps(3) 1; }
@keyframes temper-cursed { from { color: var(--c-radiant); } }
.temper-affix-row.is-gone { color: var(--c-danger); text-decoration: line-through; }
.temper-ficha-body.is-fresh .temper-affix-row.is-gone.is-fading { animation: temper-gone 0.36s steps(3) 1 forwards; }
@keyframes temper-gone { to { opacity: 0; } }
/* a cena mexe nas linhas: as do alvo pulsam, a que sai queima, a roleta do Anular salta de uma a outra */
.temper-affix-row.is-pulse { animation: temper-next 0.4s steps(2) infinite; }
.temper-affix-row.is-burn { color: var(--c-danger); animation: temper-gone 0.36s steps(3) 1 forwards; }
/* a linha da roleta fica ACESA inteira (não pulsa com as outras: o realce apagado pela metade do pulso se lia como linha travada) */
.temper-affix-row.is-roulette { background: var(--c-gold); color: var(--c-text-dark); animation: none; }
.temper-effect { display: flex; align-items: baseline; gap: calc(3 * var(--px)); color: var(--c-gold); flex-shrink: 0; }
/* +N, qualidade e selo saltam (2 passos) na cor do sentido — crescem para a DIREITA (a origem na esquerda): do centro, o selo encostado na
   borda da ficha saía cortado pela coluna e o +N tapava o fim do nome */
.temper-ficha-body.is-fresh .temper-refine.is-pop-up, .temper-ficha-body.is-fresh .temper-badge.is-pop-up { animation: temper-pop 0.24s steps(2) 1; transform-origin: left center; }
.temper-ficha-body.is-fresh .temper-refine.is-pop-down, .temper-ficha-body.is-fresh .temper-badge.is-pop-down { animation: temper-pop-down 0.24s steps(2) 1; transform-origin: left center; }
@keyframes temper-pop { from { transform: scale(1.6); color: var(--c-radiant); } }
@keyframes temper-pop-down { from { transform: scale(1.6); color: var(--c-danger); } }
/* o selo que salta tem vizinho na linha (Nv, Corrompida): ele passa POR CIMA, com o fundo do painel (o miolo de `panel.png`, o token
   `--c-panel-fill`) — sem o fundo as duas legendas se misturavam no quadro do salto (medido na revelação do Lapidar em 2026-10-02) */
.temper-ficha-body.is-fresh .temper-badge.is-pop-up, .temper-ficha-body.is-fresh .temper-badge.is-pop-down { position: relative; z-index: 1; background: var(--c-panel-fill); }
/* o Fixado mora no FIM da linha do adicional, encostado na borda da ficha: cresce para a ESQUERDA, por cima do vão da linha — da esquerda
   ele saía cortado pela coluna ("Fixa", filmado no servidor real em 2026-10-02, 1280×720 e 844×390) */
.temper-ficha-body.is-fresh .temper-affix-row > .temper-badge.is-pop-up, .temper-ficha-body.is-fresh .temper-affix-row > .temper-badge.is-pop-down { transform-origin: right center; }
.temper-bench-foot { display: flex; flex-direction: column; gap: calc(2 * var(--px)); flex-shrink: 0; }

/* ---- OS RITOS (168): abas só de ícone · opções (escolher não gasta) · a linha de lançar · o detalhe da aba ---- */
.temper-tabs { flex-shrink: 0; }
.temper-opts { display: flex; flex-direction: column; gap: calc(2 * var(--px)); flex-shrink: 0; }
/* a aba Adicionais: 7 fichas de 81×20 em 2 colunas e o "Encantar o set" (docs/specs/temper.md §5.1) na fila inteira — em 81 ele saía
   cortado ("Encantar o s", filmado no mock em 2026-10-05, 844×390); nunca reticências */
.temper-opts.is-chips { display: grid; grid-template-columns: 1fr 1fr; }
.temper-opts.is-chips > .temper-opt[data-key="addSet"] { grid-column: 1 / -1; }
.temper-opt {
  display: flex;
  align-items: center;
  gap: calc(2 * var(--px));
  min-width: 0;
  height: calc(20 * var(--px));
  padding: 0 calc(2 * var(--px));
  font: inherit;
  text-align: left;
  color: var(--c-text);
  background: var(--c-field-bg);
  border: var(--px) solid var(--c-field-edge);
  cursor: pointer;
}
.temper-opt:hover, .temper-opt:focus-visible { border-color: var(--c-gold); outline: none; }
.temper-opt.is-selected { background: var(--c-field-pop); border-color: var(--c-gold); color: var(--c-gold); }
/* a opção travada por regra continua escolhível (é assim que se lê o porquê): só apaga */
.temper-opt.is-locked { color: var(--c-text-dim); }
.temper-opt.is-locked > .temper-ico { opacity: 0.45; filter: grayscale(1); }
.temper-opt.is-locked.is-selected { border-color: var(--c-text-dim); }
.temper-opt.is-disabled { cursor: progress; }
.temper-opt-label { min-width: 0; white-space: nowrap; overflow: hidden; }
/* o LAÇO «Até o alvo» (docs/specs/temper.md §2.4; docs/ux-casos.md §33): sob as opções, o [−][+] do alvo (24×24: o alvo de toque mínimo
   do celular deitado, o do lint W9.1) e, no refino, o interruptor "Proteger as quedas (×3)" na largura da coluna — a peça `toggle` da série
   à direita do rótulo */
.temper-loop { display: flex; flex-direction: column; gap: calc(2 * var(--px)); flex-shrink: 0; }
.temper-target { display: flex; gap: calc(4 * var(--px)); }
.temper-target-btn { min-width: calc(24 * var(--px)); min-height: calc(24 * var(--px)); padding: 0; }
.temper-falls { justify-content: space-between; width: 100%; min-height: calc(24 * var(--px)); }
/* a PREVISÃO no lugar da chance ("~12 tentativas"): letra de corpo — o número grande é da chance de UMA tentativa; quebra linha antes de
   empurrar o botão (o preço do botão do laço é o teto de ouro, "até [moeda] N") */
.temper-cast-chance.is-forecast { display: flex; align-items: center; min-height: calc(24 * var(--px)); font-size: var(--text-1); line-height: 1.25; white-space: normal; justify-self: start; }
/* a pista (o pontilhado de 1 px, base.css) colada no TEXTO: o alvo de toque tem 24 de altura (o lint W9.1) e a borda de baixo dele ficava
   6 px abaixo das letras, solta */
#ui-root .temper-cast-chance.is-forecast[data-hint].has-more { border-bottom: 0; text-decoration: underline dotted rgba(244, 240, 230, 0.4); text-decoration-thickness: var(--px); text-underline-offset: calc(2 * var(--px)); }
.temper-cast-upto { white-space: nowrap; }
/* a LINHA DE LANÇAR (24): a chance à esquerda, o botão de preço à direita; o motivo da trava por regra, à vista, logo abaixo */
.temper-cast { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: calc(2 * var(--px)) calc(4 * var(--px)); min-height: calc(24 * var(--px)); flex-shrink: 0; }
.temper-cast-chance { font-size: var(--text-2); line-height: 1; color: var(--c-gold); white-space: nowrap; }
.temper-cast-chance.is-danger { color: var(--c-danger); }
.temper-cast-btn { min-height: calc(24 * var(--px)); min-width: calc(48 * var(--px)); gap: calc(3 * var(--px)); }
.temper-cast-btn.is-disabled { cursor: not-allowed; }
.temper-cast-btn > .gold-label { color: inherit; }
.temper-ico-lock { width: calc(8 * var(--px)); height: calc(8 * var(--px)); background: var(--ui-ico_lock, none) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; }
.temper-cast-reason { grid-column: 1 / -1; color: var(--c-danger); }
/* o motivo que é GUIA (o passo que falta — "Escolha … na lista." — ou o topo já alcançado) vai em ouro: o vermelho é da recusa */
.temper-cast-reason.is-guide { color: var(--c-gold); }
/* o CADEADO do teto (G5: só onde bloqueia) — "[cadeado] Personagem Nv 15", "[cadeado][Refinaria] Nv 3" — no lugar do preço, em perigo como o
   selo de requisito do jogo (`craft.css › .req-seal`); o motivo inteiro fica à vista logo abaixo */
.temper-cast-btn.is-lock > .temper-cast-nv { color: var(--c-danger); white-space: nowrap; }
/* a FICHA DO CATALISADOR (docs/specs/temper.md §2.2): uma ficha por tipo — o refinado, o troféu — com o material (o slot da bancada, 36) e o N
   por tentativa; faltando, "Faltam [material] N" em perigo. Cada ficha na SUA moldura de campo (o "Faltam" da 2.ª, sem ela, se lia como o fim
   da 1.ª: "2 Faltam") — e a moldura diz que ela se toca: é o alvo da consulta ("Onde conseguir"), com o foco nela inteira */
.temper-mats { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: calc(2 * var(--px)) calc(4 * var(--px)); }
.temper-mat { display: inline-flex; align-items: center; gap: calc(2 * var(--px)); padding: var(--px) calc(3 * var(--px)); cursor: pointer; color: var(--c-text); white-space: nowrap; background: var(--c-field-bg); border: var(--px) solid var(--c-field-edge); }
.temper-mat:hover { border-color: var(--c-gold); }
.temper-mat.is-missing { color: var(--c-danger); border-color: var(--c-danger); }
.temper-mat:focus-visible { outline: var(--px) solid var(--c-gold); outline-offset: var(--px); }
.temper-detail { display: flex; flex-direction: column; gap: calc(3 * var(--px)); flex: 1 1 auto; min-height: 0; min-width: 0; }
.temper-detail-title { color: var(--c-gold); flex-shrink: 0; }
/* a régua da Brasa/Calor: o rótulo e os pips `ico_temper_pip` (6×6) */
.temper-gauge { display: flex; flex-direction: column; gap: calc(2 * var(--px)); flex-shrink: 0; color: var(--c-gold); }
.temper-pips { display: flex; flex-wrap: wrap; gap: var(--px); }
.temper-pip { display: block; width: calc(6 * var(--px)); height: calc(6 * var(--px)); background-repeat: no-repeat; background-size: 100% 100%; image-rendering: pixelated; }
.temper-gauge.is-gain .temper-pip[data-state="ember"] { animation: temper-pop 0.24s steps(2) 1; }
/* a ESCADA da qualidade: as seis molduras `slot_q_*` (12×12) — alcançadas cheias, a de agora com aro de ouro, o Radiante com aro de perigo */
.temper-qladder { display: flex; align-items: center; gap: calc(4 * var(--px)); flex-shrink: 0; padding: var(--px); }
.temper-qstep { width: calc(12 * var(--px)); height: calc(12 * var(--px)); background-repeat: no-repeat; background-size: 100% 100%; image-rendering: pixelated; }
.temper-qstep[data-state="reached"] { background-color: currentColor; }
.temper-qstep[data-state="current"] { background-color: currentColor; outline: var(--px) solid var(--c-gold); outline-offset: var(--px); }
.temper-qstep[data-state="beyond"] { opacity: 0.45; }
.temper-qstep.is-danger { outline: var(--px) solid var(--c-danger); outline-offset: var(--px); }
.temper-qladder.is-gain .temper-qstep[data-state="current"] { animation: temper-pop 0.24s steps(2) 1; }
/* os candidatos (Encantar, Transmutar, Caos), a faixa do Reforjar e a ESCOLHA do adicional (Transmutar, Fixar) */
.temper-cands, .temper-affix-pick { display: flex; flex-direction: column; gap: var(--px); flex-shrink: 0; }
.temper-cand { display: flex; align-items: center; gap: calc(3 * var(--px)); color: var(--c-text-dim); }
.temper-pick { display: flex; align-items: center; gap: calc(3 * var(--px)); min-height: calc(18 * var(--px)); padding: 0 calc(2 * var(--px)); font: inherit; text-align: left; color: var(--c-text); background: var(--c-field-bg); border: var(--px) solid var(--c-field-edge); cursor: pointer; }
.temper-pick:hover, .temper-pick:focus-visible { border-color: var(--c-gold); outline: none; }
.temper-pick.is-selected { background: var(--c-field-pop); border-color: var(--c-gold); color: var(--c-gold); }
/* a GRADE do Encantar o set (docs/specs/temper.md §5.1; ux-casos §33): células de 24×24 (o toque mínimo do lint W9.1), 6 por linha na coluna de
   168 (6 × 24 + 5 × 4 = 164) — 12 peças são 2 linhas; marcada, o aro e o fundo de ouro da opção escolhida; desmarcada, a peça apagada e cinza
   (a cor nunca vem sozinha: o brilho e a figura também mudam); a nota de quando não há outra peça do tier, apagada */
.temper-set-box { display: flex; flex-direction: column; gap: calc(3 * var(--px)); flex-shrink: 0; }
.temper-set { display: grid; grid-template-columns: repeat(6, calc(24 * var(--px))); gap: calc(4 * var(--px)); }
.temper-set-cell { display: flex; align-items: center; justify-content: center; box-sizing: border-box; width: calc(24 * var(--px)); height: calc(24 * var(--px)); padding: 0; font: inherit; background: var(--c-field-bg); border: var(--px) solid var(--c-field-edge); cursor: pointer; }
.temper-set-cell:hover, .temper-set-cell:focus-visible { border-color: var(--c-gold); outline: none; }
.temper-set-cell.is-on { background: var(--c-field-pop); border-color: var(--c-gold); }
.temper-set-cell:not(.is-on) > .item-art { opacity: 0.4; filter: grayscale(1); }
.temper-set-cell.is-disabled { cursor: not-allowed; }
.temper-set-note { color: var(--c-text-dim); }
/* a BARRA DAS CHANCES da corrupção (160×10): uma fatia por resultado com peso (o JS dá x e largura); cor por grupo — ouro · apagado ·
   escuro · perigo — e a palavra de cada fatia no `aria-label`; a agulha (`ico_temper_needle`, 8×8) corre por cima e pousa no sorteado */
.temper-bar-box { position: relative; display: flex; flex-direction: column; gap: calc(3 * var(--px)); padding-top: calc(9 * var(--px)); flex-shrink: 0; }
/* a barra tem 160 (STAGE.bar) com 4 px de cada lado (STAGE.barInset): a agulha que pousa na fatia da ponta fica inteira na coluna */
.temper-bar { position: relative; height: calc(10 * var(--px)); margin: 0 calc(4 * var(--px)); }
.temper-slice { position: absolute; top: 0; bottom: 0; }
.temper-slice.is-up { background: var(--c-gold); }
.temper-slice.is-mixed { background: var(--c-text-dim); }
.temper-slice.is-none { background: var(--c-field-edge); outline: var(--px) solid var(--c-text-dim); outline-offset: calc(-1 * var(--px)); }
.temper-slice.is-down { background: var(--c-danger); }
.temper-needle { position: absolute; top: 0; width: calc(8 * var(--px)); height: calc(8 * var(--px)); background: var(--ui-ico_temper_needle, none) 0 0 / 100% 100% no-repeat; image-rendering: pixelated; }
/* sem a peça `ico_temper_needle`: um triângulo de ouro com a ponta para baixo */
.temper-needle::after { content: ''; position: absolute; left: var(--px); top: var(--px); border: calc(3 * var(--px)) solid transparent; border-top-color: var(--c-gold); border-bottom-width: 0; }
.has-needle-art .temper-needle::after { content: none; }
.temper-bar-box.is-lit .temper-bar { outline: var(--px) solid var(--c-void); outline-offset: var(--px); }
/* os selos Melhora · Troca · Nada com a soma e a caixa da PIORA por extenso (N2: aviso de perda não se corta) — na aba e na confirmação */
#temper-corrupt { display: flex; flex-direction: column; gap: calc(4 * var(--px)); max-width: calc(260 * var(--px)); }
#temper-corrupt > p { margin: 0; }
.temper-corrupt-groups { display: flex; flex-wrap: wrap; gap: calc(3 * var(--px)) calc(8 * var(--px)); }
.temper-corrupt-group, .temper-corrupt-loss-head { display: inline-flex; align-items: baseline; gap: calc(3 * var(--px)); }
.temper-corrupt-group.is-up > .temper-corrupt-pct { color: var(--c-gold); }
.temper-corrupt-group.is-none > .temper-corrupt-pct, .temper-corrupt-group.is-mixed > .temper-corrupt-pct { color: var(--c-text-dim); }
.temper-corrupt-loss { display: flex; flex-direction: column; gap: var(--px); padding: calc(3 * var(--px)); border: var(--px) solid var(--c-danger); }
.temper-corrupt-loss .temper-corrupt-pct { color: var(--c-danger); white-space: nowrap; }
.temper-corrupt-loss-row { display: flex; justify-content: space-between; align-items: baseline; gap: calc(6 * var(--px)); }
/* uma piora só (a peça crua): selo, frase e chance numa linha — a frase empurra a chance para a direita, como nas linhas de várias pioras */
.temper-corrupt-loss-head.is-single { display: flex; flex-wrap: wrap; }
.temper-corrupt-loss-head.is-single > .temper-corrupt-loss-text { flex: 1 1 auto; }
.temper-corrupt-curse { color: var(--c-text-dim); padding-left: calc(6 * var(--px)); }
/* O CATÁLOGO dos efeitos de arma (temper.md §6): só na aba Lendário, com peça. O topo "Efeitos N/10" e a lista — o seletor do Imbuir;
   quem rola é o detalhe (`scroll-fade`). Linha: marca 12 (a arte útil da wmark_* é o canto 12×12 do PNG 32×32, mostrada 1:1) · nome /
   selo Desbloqueado ou a origem (o anzol), que quebra em duas linhas em vez de cortar o nome da masmorra. O que o efeito escolhido faz
   vai para a PLACA. Prefixo `temper-cat-`: `.temper-effect` é a linha do efeito GRAVADO na ficha. */
.temper-catalog-box { display: flex; flex-direction: column; gap: calc(3 * var(--px)); flex-shrink: 0; }
.temper-catalog { display: flex; flex-direction: column; gap: calc(2 * var(--px)); }
.temper-cat-row {
  display: grid;
  grid-template-columns: calc(12 * var(--px)) 1fr;
  align-items: start;
  gap: calc(4 * var(--px));
  padding: calc(2 * var(--px));
  background: var(--c-field-bg);
  border: var(--px) solid var(--c-field-edge);
  cursor: pointer;
  flex-shrink: 0;
}
.temper-cat-row:hover, .temper-cat-row:focus-visible { border-color: var(--c-gold); outline: none; }
.temper-cat-row.is-selected { background: var(--c-field-pop); border-color: var(--c-gold); }
.temper-cat-mark { width: calc(12 * var(--px)); height: calc(12 * var(--px)); image-rendering: pixelated; background-repeat: no-repeat; background-position: 0 0; background-size: calc(32 * var(--px)) calc(32 * var(--px)); }
/* bloqueado: a marca em silhueta (a regra de `.is-unknown` do Bestiário — zero arte nova); o estado também está no `aria-label` */
.temper-cat-mark.is-locked { filter: grayscale(1) brightness(0.35); }
.temper-cat-text { display: flex; flex-direction: column; align-items: flex-start; gap: var(--px); min-width: 0; }
.temper-cat-name { max-width: 100%; overflow-wrap: anywhere; color: var(--c-text); }
.temper-cat-row.is-locked .temper-cat-name { color: var(--c-text-dim); }
.temper-cat-from { color: var(--c-text-dim); }
/* as confirmações do Imbuir e do Radiante: o texto À VISTA (o que a falha faz, o catalisador, o preço e o saldo), na largura de leitura dos
   outros avisos da bancada */
#temper-imbue > p, #temper-shine > p { margin: 0 0 calc(4 * var(--px)); max-width: calc(260 * var(--px)); }
/* seletor de peças (modal): EQUIPADAS primeiro, depois NA MOCHILA — cada grupo com o cabeçalho e duas colunas de botões-slot; quem
   rola é a lista inteira (`scroll-fade`, posta pelo JS) */
.temper-picker { display: flex; flex-direction: column; gap: calc(6 * var(--px)); max-height: calc(200 * var(--px)); }
.temper-picker-group { display: grid; grid-template-columns: repeat(2, 1fr); gap: calc(4 * var(--px)); }
.temper-picker-head { grid-column: 1 / -1; color: var(--c-text-dim); }
.temper-picker-note { grid-column: 1 / -1; color: var(--c-danger); }
.temper-picker-item {
  display: grid;
  grid-template-columns: calc(36 * var(--px)) 1fr;
  align-items: center;
  gap: calc(4 * var(--px));
  padding: calc(2 * var(--px));
  font: inherit;
  text-align: left;
  color: var(--c-text);
  background: var(--c-field-bg);
  border: var(--px) solid var(--c-field-edge);
  cursor: pointer;
}
.temper-picker-item:hover, .temper-picker-item:focus-visible { background: var(--c-field-pop); border-color: var(--c-gold); outline: none; }
.temper-picker-item.is-current { border-color: var(--c-gold); }
/* a equipada travada (mochila cheia) continua recebendo ponteiro e foco: é por eles que o motivo aparece (setButtonReason) */
.temper-picker-item.is-disabled { color: var(--c-text-dim); }
.temper-picker-item.is-disabled > .slot { opacity: 0.45; filter: grayscale(1); }
.temper-picker-item.is-disabled > .temper-picker-text { opacity: 0.6; }
.temper-picker-item.is-disabled:hover, .temper-picker-item.is-disabled:focus-visible { background: var(--c-field-bg); border-color: var(--c-danger); }
.temper-picker-text { display: flex; flex-direction: column; min-width: 0; }
.temper-picker-name { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.temper-picker-where { color: var(--c-text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.temper-picker-empty { color: var(--c-text-dim); }
/* o aviso de levar a peça do corpo: o mesmo ícone e o mesmo nome do seletor, e as três frases */
.temper-from-body-piece { display: flex; align-items: center; gap: calc(4 * var(--px)); margin-bottom: calc(4 * var(--px)); }
#temper-from-body > p { margin: 0 0 calc(4 * var(--px)); max-width: calc(260 * var(--px)); }
.temper-from-body-loss { color: var(--c-gold); }
/* botão segurado (`widgets/holdButton.js`; hoje só a troca de classe — o Radiante saiu dele, docs/specs/temper.md §4): o .btn pinta o miolo
   com border-image `fill`, então a barra que enche é um ::after POR CIMA do miolo */
.btn-hold { position: relative; }
.btn-hold::after { content: ''; position: absolute; inset: 0; background: var(--c-gold); opacity: 0.35; transform: scaleX(0); transform-origin: left center; pointer-events: none; }
.btn-hold.is-holding::after { animation: temper-hold 1.5s steps(12, end) forwards; }
@keyframes temper-hold { to { transform: scaleX(1); } }
/* MOVIMENTO REDUZIDO: nada se mexe — a forja fica acesa e parada, a vaga segura a foto e o resultado aparece direto quando chega */
@media (prefers-reduced-motion: reduce) {
  .btn-hold.is-holding::after { animation: none; transform: scaleX(1); }
  .temper-body *, .temper-body *::before, .temper-body *::after { animation: none !important; transition: none !important; }
  .temper-ember { opacity: 0; }
}
.temper-body.is-reduced *, .temper-body.is-reduced *::before, .temper-body.is-reduced *::after { animation: none !important; transition: none !important; }
/* --- /temper --- */
