/* ═══════════════════════════════════════════════════════════════════════
   world-forge.css — THE FORGE WINDOW (#3057), one centred window.

   Wray's FORGE 1B (2026-09-26): the lines as tabs across the top, the
   staples down the left, the anvil in the middle with the chosen card on it,
   the costs, the line's level and the STRIKE on the right. The window's own
   size (.43 x .71, the centred shape #2751 measured) is world-skin.css's
   per-door ask, like every door's; a phone's window is full screen (S12).
   The drawing is public/js/world-forge.js.

   Kit B throughout, at the chrome pixel --hv-k (world-hud-v2.css): the red
   and gold tabs are the shell's own `.ws-paneltab` (world-windows-v2.css),
   the slots `.hv-slot`, the bars `.hv-bar.hv-xp`; this file adds the gold
   STRIKE (btngold.png), the slate buttons (btn.png), the level shield
   (shield.png), the socket (g-sock1.png) and the stage.

   Every selector starts at `body.hud-v2`, so ?hud=0 never meets it (the
   anvil opens the Inventory's framed Forge tab there, as it always has).

   ── THE LAYER ────────────────────────────────────────────────────────────
   `corners`, like world-windows-v2.css and world-inventory-v2.css: this is
   window content inside the slate window, and it answers that file and the
   skin by layer, never by specificity (__tests__/worldCssLayers.test.js).
   ═══════════════════════════════════════════════════════════════════════ */
@layer base, module, skin, nerm, corners;

@layer corners {

/* ── 1. THE BODY: a column, the tabs over a three-part main ─────────────── */
body.hud-v2 .wf {
  position: relative;
  flex: 1 1 auto;
  width: 100%;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: calc(4px + 2 * var(--hv-k) * 1px);
  color: var(--hv-ink-slate);
  font: 400 calc(16px + 2 * var(--hv-k) * 1px) / 1.05 var(--hv-f-vt);
  container: wf / inline-size;
  --wf-line: #e3c79a;
}
body.hud-v2 .wf-note {
  margin: auto;
  padding: 24px;
  text-align: center;
  color: var(--hv-dim);
}

/* the lines, as the shell's own tab row: crest, name, and your house marked */
body.hud-v2 .wf .wf-lines {
  display: flex;
  flex: none;
  gap: calc(2 * var(--hv-k) * 1px);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  padding-bottom: calc(2 * var(--hv-k) * 1px);
}
body.hud-v2 .wf .wf-lines::-webkit-scrollbar { display: none; }
/* ONE ROW: the crest on every tab, the name only on the chosen one (the
   mock's B draws crests with names in tooltips; the chosen line is named on
   its tab and again over its level on the right) */
body.hud-v2 .wf .wf-line {
  position: relative;
  flex: 1 1 0;
  min-width: 44px;
  min-height: max(44px, calc(36px + 6 * var(--hv-k) * 1px));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  cursor: pointer;
  font: 400 calc(4px + 2 * var(--hv-k) * 1px) / 1 var(--hv-f-px);
  letter-spacing: .02em;
  text-transform: uppercase;
}
body.hud-v2 .wf .wf-crest {
  display: block;
  width: calc(12px + 8 * var(--hv-k) * 1px);
  height: calc(12px + 8 * var(--hv-k) * 1px);
  background: center / contain no-repeat;
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, .6));
}
body.hud-v2 .wf .wf-crest.is-anvil svg { width: 100%; height: 100%; margin-top: 20%; }
body.hud-v2 .wf .wf-line-name { display: none; white-space: nowrap; }
body.hud-v2 .wf .wf-line[aria-current] { flex: 2.4 0 auto; }
body.hud-v2 .wf .wf-line[aria-current] .wf-line-name { display: block; }
/* your house: a gold pip on the tab, and its name on the tab's title */
body.hud-v2 .wf .wf-house-pip {
  position: absolute;
  top: 1px;
  right: 1px;
  width: calc(4 * var(--hv-k) * 1px + 2px);
  height: calc(4 * var(--hv-k) * 1px + 2px);
  overflow: hidden;
  text-indent: 200%;
  white-space: nowrap;
  background: var(--hv-xp); transform: rotate(45deg);
  box-shadow: 0 0 0 1px #2a1c0c, 0 0 6px var(--hv-gold-hi);
}

body.hud-v2 .wf .wf-main {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(160px, 26%) minmax(0, 1fr) minmax(170px, 24%);
  gap: calc(4px + 3 * var(--hv-k) * 1px);
}

/* ── 2. THE STAPLES, down the left ──────────────────────────────────────── */
body.hud-v2 .wf .wf-list {
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: calc(2 * var(--hv-k) * 1px);
  padding-right: 2px;
  scrollbar-width: thin;
}
body.hud-v2 .wf .wf-staple {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 4px 6px 4px 4px;
  border: 0;
  background: #1b2330;
  box-shadow: inset 0 0 0 2px #0b0f15, inset 0 0 0 3px #3a4760;
  color: var(--hv-ink-slate);
  text-align: left;
  cursor: pointer;
  font: inherit;
}
body.hud-v2 .wf .wf-staple:hover { background: #222c3a; }
body.hud-v2 .wf .wf-staple.is-on {
  background: #2b2418;
  box-shadow: inset 0 0 0 2px #0b0f15, inset 0 0 0 4px var(--hv-gold), 0 0 10px rgba(227, 199, 154, .25);
}
body.hud-v2 .wf .wf-staple.is-locked { color: var(--hv-hint); }
body.hud-v2 .wf .wf-staple.is-locked .wf-art { filter: grayscale(1) brightness(.55); }
body.hud-v2 .wf .wf-staple.is-opened { animation: wf-open .7s steps(7); }
@keyframes wf-open { 0%, 60% { box-shadow: inset 0 0 0 2px #0b0f15, inset 0 0 0 4px #fff3c4, 0 0 18px var(--wf-line); } }
body.hud-v2 .wf .wf-face {
  position: relative;
  display: block;
  width: calc(40px + 10 * var(--hv-k) * 1px);
  height: calc(40px + 10 * var(--hv-k) * 1px);
}
body.hud-v2 .wf .wf-art {
  position: absolute;
  inset: calc(5 * var(--hv-k) * 1px);
  background-repeat: no-repeat;
  image-rendering: pixelated;
}
/* the crop is in percentages of this box (world-forge.js cropStyle), so any
   slot size shows the same square of the art */
body.hud-v2 .wf .wf-lock {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 14px;
  height: 12px;
  margin: -4px 0 0 -7px;
  background: #b8c0cc;
  box-shadow: 0 0 0 2px #0b0f15;
}
body.hud-v2 .wf .wf-lock::before {
  content: '';
  position: absolute;
  left: 3px;
  top: -8px;
  width: 4px;
  height: 6px;
  border: 2px solid #b8c0cc;
  border-bottom: 0;
}
body.hud-v2 .wf .wf-lock.is-shatter { animation: wf-shatter .52s steps(6) forwards; }
@keyframes wf-shatter {
  30% { transform: scale(1.4) rotate(-12deg); background: #fff; }
  100% { transform: scale(2.2) rotate(30deg); opacity: 0; }
}
body.hud-v2 .wf .wf-staple-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
body.hud-v2 .wf .wf-staple-name {
  font-weight: 400;
  color: var(--hv-gold-hi);
  overflow-wrap: break-word;
}
body.hud-v2 .wf .wf-staple.is-locked .wf-staple-name { color: var(--hv-dim); }
body.hud-v2 .wf .wf-staple-sub {
  font-size: .8em;
  line-height: 1;
  color: var(--hv-mute);
}
body.hud-v2 .wf .wf-fits { display: flex; align-items: center; gap: 3px; }
body.hud-v2 .wf .wf-sock {
  display: inline-block;
  width: 12px;
  height: 13px;
  background: url('/assets/ui/kitb/g-sock1.png?v=2026-09-24a') center / 100% 100% no-repeat;
  image-rendering: pixelated;
}
/* the gate: the level shield, with the level that opens the staple */
body.hud-v2 .wf .wf-gate,
body.hud-v2 .wf .wf-shield {
  display: grid;
  place-items: center;
  width: calc(24 * var(--hv-k) * 1px);
  height: calc(29 * var(--hv-k) * 1px);
  padding-bottom: calc(3 * var(--hv-k) * 1px);
  box-sizing: border-box;
  background: url('/assets/ui/kitb/shield.png?v=2026-09-24a') center / 100% 100% no-repeat;
  image-rendering: pixelated;
  font: 400 calc(4px + 3 * var(--hv-k) * 1px) / 1 var(--hv-f-px);
  color: #fff3d6;
  text-shadow: 0 2px 0 #3a1406;
}
/* the gate rides the slot's corner, so the name keeps the row's width */
body.hud-v2 .wf .wf-gate {
  position: absolute;
  right: calc(-4 * var(--hv-k) * 1px);
  bottom: calc(-4 * var(--hv-k) * 1px);
  width: calc(12 * var(--hv-k) * 1px + 4px);
  height: calc(14 * var(--hv-k) * 1px + 5px);
  padding-bottom: calc(2 * var(--hv-k) * 1px);
  font-size: calc(4px + 2 * var(--hv-k) * 1px);
}
body.hud-v2 .wf .wf-staple:not(.is-locked) .wf-gate { filter: saturate(.6) brightness(.9); }

/* ── 3. THE STAGE: the anvil scene, the card on it, the tray ────────────── */
body.hud-v2 .wf .wf-stage {
  min-height: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: calc(2 * var(--hv-k) * 1px + 2px);
}
/* the chosen staple in words: its name, role, socket and gate. The wide
   window's list already says all of it, so this shows only in the laptop
   and phone shapes (section 6), where the slots carry a name alone */
body.hud-v2 .wf .wf-chosen {
  display: none;
  flex: none;
  min-width: 0;
  font-size: .85em;
  color: var(--hv-gold-hi);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
body.hud-v2 .wf .wf-scene {
  position: relative;
  flex: 1 1 auto;
  min-height: 180px;
  overflow: hidden;
  cursor: pointer;
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  /* height-fitted and centred, so the anvil's face sits 69.7% down
     (public/assets/ui/forge/README.md) */
  background: #0b0f15 url('/assets/ui/forge/anvil.webp?v=2026-09-26a') 50% 70% / cover no-repeat;
  image-rendering: pixelated;
  box-shadow: inset 0 0 0 2px #0b0f15, inset 0 0 0 4px #7e6440, inset 0 0 40px rgba(0, 0, 0, .6);
}
body.hud-v2 .wf .wf-scene::after {
  /* the hearth's breath: brighter while a strike is out */
  content: '';
  position: absolute;
  left: 30%;
  right: 30%;
  top: 40%;
  height: 34%;
  background: radial-gradient(closest-side, rgba(255, 140, 40, .35), rgba(255, 90, 20, 0));
  pointer-events: none;
  opacity: .5;
  transition: opacity .25s;
}
body.hud-v2 .wf .wf-scene.is-hot::after { opacity: 1; }
body.hud-v2 .wf .wf-scene.is-cold { filter: grayscale(.8) brightness(.8); transition: filter .2s; }
body.hud-v2 .wf .wf-ghost {
  position: absolute;
  left: 50%;
  bottom: 30.3%;
  height: 50%;
  aspect-ratio: 240 / 380;
  transform: translateX(-50%);
  pointer-events: none;
}
body.hud-v2 .wf .wf-ghost-img {
  display: block;
  width: 100%;
  height: 100%;
  image-rendering: pixelated;
  /* the cold ghost: the card waits on the anvil, not yet made */
  filter: grayscale(.55) brightness(.78) drop-shadow(0 6px 0 rgba(0, 0, 0, .45));
  opacity: .9;
  transition: filter .12s;
}
/* ⭐THE CARD ON THE ANVIL IS ITS ICON (#3560, Wray 2026-10-02: a card is the
   size it was painted at or its icon, never a shrunken face). The square
   stands where the face's art stood; the card at full size opens from its
   staple's slot (world-card-tip.js). */
body.hud-v2 .wf .wf-ghost.is-icon {
  height: 34%;
  bottom: 36%;
  aspect-ratio: 1 / 1;
}
body.hud-v2 .wf .wf-ghost.is-icon .wf-ghost-img {
  box-shadow: 0 0 0 2px #0b0f15, 0 0 0 4px #3a4760;
}
body.hud-v2 .wf .wf-scene.is-hot .wf-ghost-img {
  filter: grayscale(0) sepia(.35) saturate(1.8) brightness(1.15) drop-shadow(0 0 10px #ff8a2a);
}
/* every tap is a hit: the card squashes on the anvil; the third, the blow,
   squashes it harder and jolts the stage; a big moment shakes the stage */
body.hud-v2 .wf .wf-scene.is-hit .wf-ghost { animation: wf-hit .16s steps(3); }
body.hud-v2 .wf .wf-scene.is-blow .wf-ghost { animation: wf-blow .2s steps(4); }
body.hud-v2 .wf .wf-scene.is-blow { animation: wf-jolt .18s steps(3); }
body.hud-v2 .wf .wf-scene.is-hit-big { animation: wf-shake .32s steps(6); }
@keyframes wf-hit {
  0% { transform: translateX(-50%) translateY(3px) scale(1.03, .97); }
  60% { transform: translateX(-50%) translateY(-2px); }
}
@keyframes wf-blow {
  0% { transform: translateX(-50%) translateY(6px) scale(1.07, .92); }
  50% { transform: translateX(-50%) translateY(-4px) scale(.98, 1.03); }
}
@keyframes wf-jolt {
  30% { transform: translate(-3px, 2px); }
  60% { transform: translate(3px, -1px); }
}
@keyframes wf-shake {
  20% { transform: translate(-5px, 3px); }
  40% { transform: translate(5px, -3px); }
  60% { transform: translate(-3px, 2px); }
  80% { transform: translate(2px, -1px); }
}
body.hud-v2 .wf .wf-fx {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
/* three pips: the taps toward the next card */
body.hud-v2 .wf .wf-pips {
  position: absolute;
  left: 50%;
  bottom: 8%;
  display: flex;
  gap: calc(4 * var(--hv-k) * 1px);
  transform: translateX(-50%);
  pointer-events: none;
}
body.hud-v2 .wf .wf-pip {
  width: calc(4 * var(--hv-k) * 1px + 6px);
  height: calc(4 * var(--hv-k) * 1px + 6px);
  transform: rotate(45deg);
  background: #2a2016;
  box-shadow: 0 0 0 2px #0b0f15, inset 0 0 0 1px #7e6440;
}
body.hud-v2 .wf .wf-pip.is-lit {
  background: #ffb347;
  box-shadow: 0 0 0 2px #0b0f15, 0 0 10px #ff8a2a;
}
body.hud-v2 .wf .wf-pips.is-waiting .wf-pip.is-lit { animation: wf-wait .5s steps(2) infinite; }
@keyframes wf-wait { 50% { background: #fff3c4; } }
body.hud-v2 .wf .wf-prog {
  position: absolute;
  right: 8px;
  top: 8px;
  font: 400 calc(4px + 3 * var(--hv-k) * 1px) / 1 var(--hv-f-px);
  color: #fff3d6;
  text-shadow: 0 2px 0 #000;
  pointer-events: none;
}
/* the full moment's banner (3A): the title ribbon, dropped over the anvil */
body.hud-v2 .wf .wf-banner {
  position: absolute;
  left: 50%;
  top: 10%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  transform: translate(-50%, -20px) scale(.6);
  opacity: 0;
  pointer-events: none;
  text-align: center;
}
body.hud-v2 .wf .wf-banner b {
  display: block;
  padding: calc(3 * var(--hv-k) * 1px) calc(26 * var(--hv-k) * 1px) calc(10 * var(--hv-k) * 1px);
  border-style: solid;
  border-width: 0;
  border-image: url('/assets/ui/kitb/title.png?v=2026-09-24a') 2 24 9 24 fill / calc(2 * var(--hv-k) * 1px) calc(24 * var(--hv-k) * 1px) calc(9 * var(--hv-k) * 1px) calc(24 * var(--hv-k) * 1px) stretch;
  image-rendering: pixelated;
  font: 400 calc(8px + 5 * var(--hv-k) * 1px) / 1 var(--hv-f-px);
  color: #f7e6c4;
  text-shadow: 0 2px 0 #5e1414;
  white-space: nowrap;
  font-weight: 400;
}
body.hud-v2 .wf .wf-banner span {
  padding: 3px 8px;
  background: rgba(8, 10, 14, .85);
  box-shadow: 0 0 0 1px #7e6440;
  color: var(--hv-gold-hi);
}
body.hud-v2 .wf .wf-banner.is-up { animation: wf-banner 2.6s steps(26) forwards; }
@keyframes wf-banner {
  0% { opacity: 0; transform: translate(-50%, -20px) scale(.6); }
  10% { opacity: 1; transform: translate(-50%, 0) scale(1.08); }
  16%, 82% { opacity: 1; transform: translate(-50%, 0) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -10px) scale(1); }
}

/* the tray: this visit's cards, each one picked up to look at */
body.hud-v2 .wf .wf-tray {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px 8px 8px;
  background: #121821;
  box-shadow: inset 0 0 0 2px #0b0f15, inset 0 0 0 3px #3a4760;
}
body.hud-v2 .wf .wf-tray-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font: 400 calc(4px + 2 * var(--hv-k) * 1px) / 1 var(--hv-f-px);
  color: var(--hv-gold-hi);
  text-transform: uppercase;
}
body.hud-v2 .wf .wf-tray-head b { font-weight: 400; }
body.hud-v2 .wf .wf-tray-n { color: #fff3d6; }
body.hud-v2 .wf .wf-tray-row {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  min-height: calc(40px + 22 * var(--hv-k) * 1px);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  overscroll-behavior-x: contain;
}
body.hud-v2 .wf .wf-tray-empty { align-self: center; color: var(--hv-hint); font-size: .9em; }
/* ⛔ THE CARD'S BOX IS THE RENDER'S SHAPE, 292:391, not the flat face's
   240:380. CardPaint draws a model to its own bounds (the title ribbon's
   swallowtails reach past the frame), so a 240:380 box squashed every
   painted card about 16% across and let the flat png peek out at its edge
   (the UX review's blocker, 2026-09-27; Wray called the same thing
   "squashed" on the pack reveal, pack-reveal.js CARD_BOX). Both layers are
   `contain` besides, so a model that bounds a little differently letterboxes
   rather than stretches. At least 44 px across on a phone (a thumb). */
body.hud-v2 .wf .wf-tray-card {
  position: relative;
  flex: none;
  width: max(44px, calc(26px + 14 * var(--hv-k) * 1px));
  aspect-ratio: 292 / 391;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
/* ⭐A COPY IN THE TRAY IS ITS ICON (#3560): a square kit B slot holding the
   card's cell of spell_icons.png, never the painted face at 44 px. Pointing
   at it opens the copy at full size; a tap still picks it up. */
body.hud-v2 .wf .wf-tray-card.is-icon { aspect-ratio: 1 / 1; }
body.hud-v2 .wf .wf-tray-card:hover,
body.hud-v2 .wf .wf-tray-card:focus-visible { transform: translateY(-3px); outline: 2px solid var(--hv-gold-hi); outline-offset: 1px; }
body.hud-v2 .wf .wf-tray-img,
body.hud-v2 .wf .wf-tray-cv {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  image-rendering: pixelated;
}
body.hud-v2 .wf .wf-tray-cv { opacity: 0; }
body.hud-v2 .wf .wf-tray-cv.is-painted { opacity: 1; }
body.hud-v2 .wf .wf-tray-card.is-painted .wf-tray-img { visibility: hidden; }
body.hud-v2 .wf .wf-tray-card.is-new { visibility: hidden; }
body.hud-v2 .wf .wf-tray-card.is-landed { animation: wf-land .3s steps(4); }
@keyframes wf-land { 0% { transform: translateY(-6px) scale(1.12); filter: brightness(1.8); } }
/* the slot: the card over its roll. A forged copy rolls its FOIL and nothing
   else (Wray's ruling A, 2026-09-27 on #3057), so the foil is named under the
   card, "Starlight foil", in the foil's own light. The slot is as wide as the
   card, so the name wraps rather than crowding the next card. */
body.hud-v2 .wf .wf-tray-slot {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  width: max(44px, calc(26px + 14 * var(--hv-k) * 1px));
}
body.hud-v2 .wf .wf-tray-foil {
  max-width: 100%;
  font-size: .7em;
  line-height: 1.05;
  text-align: center;
  color: var(--wf-foil);
}
body.hud-v2 .wf [data-finish] { --wf-foil: #d9d4c7; }
body.hud-v2 .wf [data-finish="starlight"] { --wf-foil: #cfe3ff; }
body.hud-v2 .wf [data-finish="cosmos"] { --wf-foil: #cdb0ff; }
body.hud-v2 .wf [data-finish="twinkle"] { --wf-foil: #ffe7a3; }
body.hud-v2 .wf [data-finish="starburst"] { --wf-foil: #ffbd85; }
body.hud-v2 .wf .wf-tray-slot.is-new .wf-tray-foil { visibility: hidden; }
body.hud-v2 .wf .wf-tray-slot.is-landed .wf-tray-foil { animation: wf-foil-up .4s steps(4); }
@keyframes wf-foil-up { 0% { opacity: 0; transform: translateY(4px); } }
body.hud-v2 .wf .wf-fly {
  position: absolute;
  z-index: 5;
  image-rendering: pixelated;
  pointer-events: none;
  filter: drop-shadow(0 0 10px #ffb347);
}

/* ── 4. THE SIDE: the level, the costs, the run ─────────────────────────── */
/* the level and the costs scroll if they must (.wf-info); the run, its
   lines and STRIKE (.wf-act) are pinned at the foot, so a stop's line and
   the button are never below the fold (the UX review at 1366x768) */
body.hud-v2 .wf .wf-side {
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: calc(2 * var(--hv-k) * 1px + 2px);
  font-size: .92em;
}
body.hud-v2 .wf .wf-info {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: calc(2 * var(--hv-k) * 1px + 2px);
  scrollbar-width: thin;
}
body.hud-v2 .wf .wf-level {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}
body.hud-v2 .wf .wf-shield { flex: none; }
body.hud-v2 .wf .wf-level-txt { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
body.hud-v2 .wf .wf-level-txt > b { font-weight: 400; color: var(--hv-gold-hi); }
body.hud-v2 .wf .wf-xp-txt,
body.hud-v2 .wf .wf-pool-t { font-size: .85em; color: var(--hv-mute); }
body.hud-v2 .wf .wf-house-tag { font-size: .8em; color: var(--hv-gold); }
body.hud-v2 .wf .wf-xp.is-filling > i { transition: width .7s steps(14); }
body.hud-v2 .wf .wf-xp > i { transition: width .25s steps(5); }
body.hud-v2 .wf .wf-h {
  font: 400 calc(4px + 2 * var(--hv-k) * 1px) / 1.2 var(--hv-f-px);
  color: var(--hv-dim);
  text-transform: uppercase;
}
body.hud-v2 .wf .wf-costs { display: flex; flex-direction: column; gap: 5px; }
body.hud-v2 .wf .wf-cost { display: flex; align-items: center; gap: 8px; }
/* ⛔ THE SLOT HOLDS THE ICON: a MatIcons icon is 32 px (mat-icons.js SIZE)
   and the kit B slot's rim is 5k each side (.hv-slot's padding), so the
   slot is 32 + 10k across. It was 26 + 5k, a 16 px well at 1920 (the rim
   eating 20 of 36), and the icon spilled out of its lower right corner at
   every size (the UX review's should-fix 7, measured on the served page:
   slot 36x36, icon 32x32 at its padding edge) */
body.hud-v2 .wf .wf-cost-slot {
  flex: none;
  display: grid;
  place-items: center;
  width: calc(32px + 10 * var(--hv-k) * 1px);
  height: calc(32px + 10 * var(--hv-k) * 1px);
}
body.hud-v2 .wf .wf-mat { display: grid; place-items: center; line-height: 0; }
body.hud-v2 .wf .wf-coin::before {
  content: '';
  width: 32px;
  height: 32px;
  /* the Obol (Wray's pick A, 2026-10-04), at its own 32 art pixels */
  background: url('/assets/ui/kitb/obol.png?v=2026-10-04a') center / contain no-repeat;
  image-rendering: pixelated;
}
body.hud-v2 .wf .wf-cost-txt { display: flex; flex-direction: column; min-width: 0; }
body.hud-v2 .wf .wf-cost-txt b { font-weight: 400; color: #fff3d6; }
body.hud-v2 .wf .wf-cost-txt span { font-size: .85em; color: var(--hv-mute); }
body.hud-v2 .wf .wf-cost.is-short .wf-cost-txt span,
body.hud-v2 .wf .wf-cost.is-short .wf-cost-txt b { color: var(--hv-foe); }
body.hud-v2 .wf .wf-pool { display: flex; flex-direction: column; gap: 3px; margin-top: 2px; }
body.hud-v2 .wf .wf-sub { font-size: .8em; color: var(--hv-hint); }

body.hud-v2 .wf .wf-act { flex: none; display: flex; flex-direction: column; gap: 6px; }
body.hud-v2 .wf .wf-counts { display: flex; gap: 4px; }
body.hud-v2 .wf .wf-count,
body.hud-v2 .wf .wf-mute,
body.hud-v2 .wf .wf-insp-close {
  flex: 1;
  min-height: 44px;
  border-style: solid;
  border-image: url('/assets/ui/kitb/btn.png?v=2026-09-24a') 3 3 5 3 fill / calc(3 * var(--hv-k) * 1px) calc(3 * var(--hv-k) * 1px) calc(5 * var(--hv-k) * 1px) calc(3 * var(--hv-k) * 1px) stretch;
  border-width: calc(3 * var(--hv-k) * 1px) calc(3 * var(--hv-k) * 1px) calc(5 * var(--hv-k) * 1px) calc(3 * var(--hv-k) * 1px);
  background: none;
  image-rendering: pixelated;
  color: var(--hv-ink);
  font: 400 calc(4px + 3 * var(--hv-k) * 1px) / 1 var(--hv-f-px);
  text-shadow: 0 2px 0 rgba(0, 0, 0, .5);
  cursor: pointer;
}
body.hud-v2 .wf .wf-count:hover,
body.hud-v2 .wf .wf-mute:hover,
body.hud-v2 .wf .wf-insp-close:hover { filter: brightness(1.18); }
body.hud-v2 .wf .wf-count[aria-pressed='true'] {
  border-image-source: url('/assets/ui/kitb/tab-on-red.png?v=2026-09-24a');
  border-image-slice: 6 fill;
  border-image-width: calc(6 * var(--hv-k) * 1px);
  color: #f7e6c4;
  text-shadow: 0 2px 0 #5e1414;
}
/* the sound switch: the bus's own mute (ALL game sound, as its label says),
   an icon in the stage's top-left corner, so it can never scroll below the
   side column (the UX review: at 1366x768 it sat under the window's edge and
   a click hit nothing) */
body.hud-v2 .wf .wf-mute {
  position: absolute;
  left: 8px;
  top: 8px;
  z-index: 3;
  flex: none;
  width: calc(28px + 4 * var(--hv-k) * 1px);
  height: calc(28px + 4 * var(--hv-k) * 1px);
  min-height: 0;
  padding: 0;
  display: grid;
  place-items: center;
}
body.hud-v2 .wf .wf-mute svg { width: 72%; height: auto; display: block; }
body.hud-v2 .wf .wf-mute .wf-mute-x { display: none; }
body.hud-v2 .wf .wf-mute.is-off .wf-mute-x { display: inline; }
body.hud-v2 .wf .wf-mute.is-off svg rect { opacity: .45; }
body.hud-v2 .wf .wf-strike {
  min-height: calc(40px + 6 * var(--hv-k) * 1px);
  border-style: solid;
  border-image: url('/assets/ui/kitb/btngold.png?v=2026-09-24a') 3 3 5 3 fill / calc(3 * var(--hv-k) * 1px) calc(3 * var(--hv-k) * 1px) calc(5 * var(--hv-k) * 1px) calc(3 * var(--hv-k) * 1px) stretch;
  border-width: calc(3 * var(--hv-k) * 1px) calc(3 * var(--hv-k) * 1px) calc(5 * var(--hv-k) * 1px) calc(3 * var(--hv-k) * 1px);
  background: none;
  image-rendering: pixelated;
  color: #2a1c0c;
  font: 400 calc(6px + 5 * var(--hv-k) * 1px) / 1 var(--hv-f-px);
  letter-spacing: .06em;
  cursor: pointer;
  touch-action: manipulation;
}
body.hud-v2 .wf .wf-strike:hover { filter: brightness(1.1); }
body.hud-v2 .wf .wf-strike:active { transform: translateY(2px); }
body.hud-v2 .wf .wf-strike:disabled {
  border-image-source: url('/assets/ui/kitb/btn.png?v=2026-09-24a');
  color: var(--hv-dim);
  cursor: default;
  filter: none;
}
body.hud-v2 .wf .wf-hint { font-size: .8em; color: var(--hv-hint); }
/* once the window has something to say, the how-to has been learned */
body.hud-v2 .wf .wf-act:has(.wf-status:not(:empty)) .wf-hint,
body.hud-v2 .wf .wf-act:has(.wf-need:not(:empty)) .wf-hint { display: none; }
/* the SHORT state (the mock's research §8): what a craft needs that the bag
   does not hold, over a greyed STRIKE */
body.hud-v2 .wf .wf-need { font-size: .9em; color: var(--hv-foe); }
body.hud-v2 .wf .wf-need:empty { display: none; }
/* a tap that did nothing points at the line that says why */
body.hud-v2 .wf .is-flash { animation: wf-flash .5s steps(4); }
@keyframes wf-flash { 25%, 75% { filter: brightness(1.8); } }
body.hud-v2 .wf .wf-away {
  padding: 8px;
  background: #121821;
  box-shadow: inset 0 0 0 2px #0b0f15, inset 0 0 0 3px #3a4760;
  color: var(--hv-gold-hi);
}
body.hud-v2 .wf .wf-status { min-height: 1.1em; font-size: .9em; color: var(--hv-ok); }
body.hud-v2 .wf .wf-status[data-kind='stop'],
body.hud-v2 .wf .wf-status[data-kind='away'] { color: var(--hv-foe); }
body.hud-v2 .wf .wf-status:empty { display: none; }

/* ── 5. INSPECT: a card held up until it is put down ────────────────────── */
body.hud-v2 .wf .wf-inspect {
  position: absolute;
  inset: 0;
  z-index: 8;
  display: grid;
  place-items: center;
  background: rgba(6, 8, 12, .95);
  /* its own size container, so the held card can be sized off the room
     there is in BOTH directions (a landscape phone's window is 310 tall) */
  container: wfi / size;
}
body.hud-v2 .wf .wf-inspect[hidden] { display: none; }
body.hud-v2 .wf .wf-insp-panel {
  display: flex;
  align-items: center;
  gap: calc(8px + 6 * var(--hv-k) * 1px);
  max-width: 100%;
  max-height: 100%;
  padding: 12px;
  box-sizing: border-box;
}
/* the render's shape, 292:391, as the tray's (section 3 says why) */
body.hud-v2 .wf .wf-insp-card {
  position: relative;
  flex: none;
  /* the size the card was painted at wherever the window holds it (#3560):
     292 across its whole bounds, and the Forge paints those with 4% of
     margin each side, so 316. It was 240, the face under its drawn size. */
  width: min(316px, 44cqw, calc((100cqh - 24px) * 292 / 391));
  aspect-ratio: 292 / 391;
}
body.hud-v2 .wf .wf-insp-img,
body.hud-v2 .wf .wf-insp-cv {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  image-rendering: pixelated;
}
body.hud-v2 .wf .wf-insp-cv { opacity: 0; }
body.hud-v2 .wf .wf-insp-cv.is-painted { opacity: 1; }
body.hud-v2 .wf .wf-insp-card.is-painted .wf-insp-img { visibility: hidden; }
body.hud-v2 .wf .wf-insp-info {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: calc(180px + 50 * var(--hv-k) * 1px);
  min-width: 0;
}
body.hud-v2 .wf .wf-insp-name {
  font: 400 calc(6px + 4 * var(--hv-k) * 1px) / 1.1 var(--hv-f-px);
  color: var(--hv-gold-hi);
  font-weight: 400;
}
/* the craft's roll, under the name: the foil, named, in its own light */
body.hud-v2 .wf .wf-insp-roll {
  align-self: flex-start;
  padding: 3px 8px;
  font: 400 calc(4px + 2 * var(--hv-k) * 1px) / 1.2 var(--hv-f-px);
  text-transform: uppercase;
  color: var(--wf-foil);
  background: #0b0f15;
  box-shadow: inset 0 0 0 1px var(--wf-foil);
}
body.hud-v2 .wf .wf-insp-roll-note { font-size: .85em; color: var(--hv-mute); }
body.hud-v2 .wf .wf-insp-rules { margin: 0; color: #fff3d6; }
body.hud-v2 .wf .wf-facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 3px 10px;
  margin: 0;
}
body.hud-v2 .wf .wf-facts dt { color: var(--hv-dim); }
body.hud-v2 .wf .wf-facts dd { margin: 0; color: var(--hv-ink); }
body.hud-v2 .wf .wf-insp-maker { color: #d9d4c7; }
body.hud-v2 .wf .wf-insp-note { font-size: .85em; color: var(--hv-mute); }
body.hud-v2 .wf .wf-insp-close { flex: none; align-self: flex-start; padding: 0 16px; }

/* ── 6. A SMALLER WINDOW: a laptop's centred window, then a phone ──────────
   Measured on the served page: at 1366x768 the centred window is 587 across
   and its body about 500, where three columns crush the anvil. So there are
   three shapes, by the WINDOW's width (a container query, not the screen's):
     wide    (over 640)   staples | anvil | side, the mock's B
     laptop  (420 to 640) the staples as a row of slots over the anvil, the
                          side column kept beside it, nothing scrolls
     phone   (under 420)  one column that scrolls, the STRIKE held at the
                          foot where a thumb is */
@container wf (max-width: 640px) {
  body.hud-v2 .wf .wf-main {
    grid-template-columns: minmax(0, 1fr) minmax(150px, 34%);
    grid-template-rows: auto minmax(0, 1fr);
    grid-template-areas: 'list side' 'stage side';
    gap: 6px;
  }
  body.hud-v2 .wf .wf-list { grid-area: list; }
  body.hud-v2 .wf .wf-stage { grid-area: stage; }
  body.hud-v2 .wf .wf-side { grid-area: side; }
  body.hud-v2 .wf .wf-list {
    flex: none;
    flex-direction: row;
    overflow-x: auto;
    overflow-y: hidden;
    gap: 4px;
    padding: 0 0 2px;
  }
  body.hud-v2 .wf .wf-staple {
    flex: none;
    grid-template-columns: auto;
    justify-items: center;
    align-content: start;
    gap: 3px;
    width: 72px;
    min-height: 60px;
    padding: 4px;
  }
  /* each slot keeps its NAME under the art (the mock's phone B names every
     tile; the UX review found the names gone); the role, the socket and the
     gate of the chosen one are spelled out over the anvil (.wf-chosen) */
  body.hud-v2 .wf .wf-staple-txt { width: 100%; align-items: center; }
  body.hud-v2 .wf .wf-staple-sub { display: none; }
  body.hud-v2 .wf .wf-staple-name {
    width: 100%;
    font-size: .72em;
    line-height: 1;
    text-align: center;
    overflow-wrap: normal;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  body.hud-v2 .wf .wf-chosen { display: block; }
  body.hud-v2 .wf .wf-gate { right: -2px; bottom: -2px; }
  body.hud-v2 .wf .wf-lines .wf-line { flex: 1 1 0; min-width: 40px; }
  body.hud-v2 .wf .wf-lines .wf-line[aria-current] { flex: 2.4 0 auto; padding-left: 6px; padding-right: 6px; }
  body.hud-v2 .wf .wf-tray-row { min-height: 60px; }
  body.hud-v2 .wf .wf-scene { min-height: 150px; }
}
@container wf (max-width: 420px) {
  body.hud-v2 .wf .wf-main {
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    gap: 6px;
  }
  body.hud-v2 .wf .wf-lines .wf-line { flex: 0 0 48px; }
  body.hud-v2 .wf .wf-lines .wf-line[aria-current] { flex: 0 0 auto; padding-left: 8px; padding-right: 8px; }
  body.hud-v2 .wf .wf-staple { width: 72px; min-height: 64px; }
  body.hud-v2 .wf .wf-stage { flex: 0 0 auto; }
  /* sized so the whole bench fits a 390x844 phone without scrolling: the
     row of staples with their names, the anvil, the tray, the costs and
     STRIKE, with a line of status over it (measured on the served page at
     25vh: a status line pushed STRIKE half under the edge; a sticky bar
     covered the costs, which is worse) */
  body.hud-v2 .wf .wf-scene { flex: none; height: clamp(140px, 21vh, 240px); }
  body.hud-v2 .wf .wf-tray-row { min-height: 64px; }
  body.hud-v2 .wf .wf-mute { width: 44px; height: 44px; }
  body.hud-v2 .wf .wf-side { flex: none; overflow: visible; }
  body.hud-v2 .wf .wf-info { flex: none; overflow: visible; }
  body.hud-v2 .wf .wf-costs { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 8px; }
  body.hud-v2 .wf .wf-costs > .wf-h,
  body.hud-v2 .wf .wf-costs > .wf-pool { grid-column: 1 / -1; }
  body.hud-v2 .wf .wf-act { margin-top: 2px; }
  body.hud-v2 .wf .wf-insp-panel { flex-direction: column; overflow-y: auto; gap: 10px; }
  body.hud-v2 .wf .wf-insp-card { width: min(180px, 50cqw); }
}

@media (prefers-reduced-motion: reduce) {
  body.hud-v2 .wf .wf-scene.is-hit .wf-ghost,
  body.hud-v2 .wf .wf-scene.is-blow .wf-ghost,
  body.hud-v2 .wf .wf-scene.is-blow,
  body.hud-v2 .wf .wf-scene.is-hit-big,
  body.hud-v2 .wf .wf-banner.is-up,
  body.hud-v2 .wf .wf-tray-card.is-landed,
  body.hud-v2 .wf .wf-tray-slot.is-landed .wf-tray-foil,
  body.hud-v2 .wf .wf-staple.is-opened,
  body.hud-v2 .wf .wf-pips.is-waiting .wf-pip.is-lit,
  body.hud-v2 .wf .is-flash { animation: none; }
  body.hud-v2 .wf .wf-banner.is-up { opacity: 1; transform: translate(-50%, 0); }
}

}
/* end of @layer corners */
