/* The client's own bitmap fonts (Client/font/*.fnt, TCVN3), see tools/export_font.py.
   Crisp at their cell size: PT Font 14 at 14px, 16 at 16px, 18 at 18px. */
@font-face {
  font-family: "PT Font 14";
  src: url("assets/fonts/pt-14.woff") format("woff");
  font-display: swap;
}

@font-face {
  font-family: "PT Font 16";
  src: url("assets/fonts/pt-16.woff") format("woff");
  font-display: swap;
}

/* Character and map names (Google Fonts, SIL OFL: assets/fonts/OFL-*.txt). Pick one
   with map.titleFont in src/config.js; it sets --font-title. */
@font-face {
  font-family: "Alegreya";
  font-weight: 700;
  src: url("assets/fonts/alegreya-700.ttf") format("truetype");
  font-display: swap;
}

@font-face {
  font-family: "Grenze";
  font-weight: 700;
  src: url("assets/fonts/grenze-700.ttf") format("truetype");
  font-display: swap;
}

@font-face {
  font-family: "Charm";
  font-weight: 700;
  src: url("assets/fonts/charm-700.ttf") format("truetype");
  font-display: swap;
}

@font-face {
  font-family: "Playfair Display";
  font-weight: 700;
  src: url("assets/fonts/playfair-display-700.ttf") format("truetype");
  font-display: swap;
}

/* Smooth faces for chat / system text (map.chatFont / map.systemFont). */
@font-face {
  font-family: "IBM Plex Mono";
  font-weight: 500;
  src: url("assets/fonts/ibm-plex-mono-500.ttf") format("truetype");
  font-display: swap;
}

@font-face {
  font-family: "Noto Serif";
  font-weight: 500;
  src: url("assets/fonts/noto-serif-500.ttf") format("truetype");
  font-display: swap;
}

@font-face {
  font-family: "Roboto Slab";
  font-weight: 500;
  src: url("assets/fonts/roboto-slab-500.ttf") format("truetype");
  font-display: swap;
}

@font-face {
  font-family: "Merriweather";
  font-weight: 400;
  src: url("assets/fonts/merriweather-400.ttf") format("truetype");
  font-display: swap;
}

@font-face {
  font-family: "PT Font 18";
  src: url("assets/fonts/pt-18.woff") format("woff");
  font-display: swap;
}

:root {
  color-scheme: dark;
  /* KFontRes draws a 1px dark border round every letter. */
  --font-title: "Alegreya", "Palatino Linotype", Georgia, serif;
  --pt-text-border: 1px 0 0 #000, -1px 0 0 #000, 0 1px 0 #000, 0 -1px 0 #000;
  --ink: #171512;
  --ink-soft: #211e18;
  --panel: #29251d;
  --panel-raised: #332d22;
  --paper: #d7c68d;
  --paper-muted: #9f936e;
  --gold: #d1a84c;
  --gold-bright: #f0d47b;
  --jade: #5fc18c;
  --jade-dark: #2c7453;
  --red: #aa4f3d;
  --blue: #5a91ad;
  --line: rgba(230, 203, 125, 0.22);
  --shadow: rgba(0, 0, 0, 0.45);
  --topbar-height: 72px;
  --dock-height: 72px;
  font-family: Inter, "Segoe UI", Arial, sans-serif;
}

* {
  box-sizing: border-box;
}

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  overflow: hidden;
  background: var(--ink);
}

body {
  color: var(--paper);
  letter-spacing: 0;
}

button,
input {
  font: inherit;
}

button {
  color: inherit;
}

.app-shell {
  display: grid;
  grid-template-rows: minmax(0, 1fr);
  width: 100%;
  height: 100%;
  background: var(--ink);
}

.topbar {
  position: relative;
  z-index: 30;
  display: grid;
  grid-template-columns: minmax(240px, 1fr) auto minmax(280px, 1fr);
  align-items: center;
  gap: 20px;
  padding: 0 22px;
  border-bottom: 1px solid var(--line);
  background: #1d1a15;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.24);
}

.brand,
.resource-strip,
.resource,
.world-status {
  display: flex;
  align-items: center;
}

.brand {
  gap: 12px;
  min-width: 0;
}

.brand-seal,
.loading-seal {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: 0 0 auto;
  border: 1px solid var(--gold);
  background: var(--red);
  color: #fff2c4;
  font-family: Georgia, serif;
  font-size: 23px;
  box-shadow: inset 0 0 0 3px rgba(20, 15, 10, 0.28);
}

.brand-kicker {
  margin: 0 0 2px;
  color: var(--gold);
  font-size: 10px;
  font-weight: 800;
}

.brand h1 {
  margin: 0;
  overflow: hidden;
  color: #f1e6bd;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 22px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.world-status {
  gap: 9px;
  min-width: 260px;
  justify-content: center;
  color: var(--paper-muted);
  font-size: 12px;
}

.world-status strong {
  color: var(--paper);
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--jade);
  box-shadow: 0 0 12px rgba(95, 193, 140, 0.8);
}

.latency {
  padding-left: 10px;
  border-left: 1px solid var(--line);
}

.resource-strip {
  justify-content: flex-end;
  gap: 10px;
}

.resource {
  min-width: 116px;
  gap: 9px;
  padding: 7px 10px;
  border: 1px solid var(--line);
  background: #242019;
}

.resource-icon {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 50%;
  color: white;
  font-family: Georgia, serif;
  font-size: 13px;
}

.resource-icon.copper {
  background: #a76a35;
}

.resource-icon.jade {
  background: var(--jade-dark);
}

.resource span:last-child {
  display: grid;
}

.resource small {
  color: var(--paper-muted);
  font-size: 9px;
}

.resource strong {
  color: #f3e7bd;
  font-size: 13px;
}

.icon-button,
.icon-button:hover,
.panel-toggle {
  display: none;
  width: 42px;
  height: 42px;
  font-size: 18px;
}

.game-layout {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--panel-width, 310px);
  min-height: 0;
}

.map-stage {
  position: relative;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  background: #171b14;
  cursor: crosshair;
}

#gameCanvas {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;
}

.map-vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow:
    inset 0 0 110px rgba(18, 23, 15, 0.62),
    inset 0 0 18px rgba(0, 0, 0, 0.42);
}

.loading-screen {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 10px;
  background: #1c2018;
  transition: opacity 350ms ease, visibility 350ms ease;
}

.loading-screen.hidden {
  display: none;
}

.loading-seal {
  width: 58px;
  height: 58px;
  margin-bottom: 4px;
  font-size: 28px;
}

.loading-screen strong {
  color: var(--gold-bright);
  font-family: Georgia, serif;
  font-size: 18px;
}

.loading-screen span {
  color: var(--paper-muted);
  font-size: 11px;
}

.side-panel {
  position: relative;
  z-index: 15;
  min-width: 0;
  overflow: hidden;
}

.bottom-dock {
  position: relative;
  z-index: 25;
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: 4px;
  padding: 7px 14px;
  border-top: 1px solid var(--line);
  background: #1b1813;
  box-shadow: 0 -10px 28px rgba(0, 0, 0, 0.22);
}

.dock-button {
  display: grid;
  grid-template-rows: 29px 15px;
  place-items: center;
  width: 92px;
  min-width: 72px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--paper-muted);
  cursor: pointer;
}

.dock-button span {
  display: grid;
  place-items: center;
  width: 31px;
  height: 31px;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--paper);
  font-family: Georgia, serif;
  font-size: 15px;
}

.dock-button small {
  font-size: 8px;
  white-space: nowrap;
}

.dock-button:hover,
.dock-button.active {
  color: var(--gold-bright);
}

.dock-button.active span,
.dock-button.primary span {
  border-color: var(--gold);
  background: var(--red);
  color: #fff0bd;
}

.dock-button.primary {
  color: var(--gold-bright);
}

@media (max-width: 1050px) {
  .topbar {
    grid-template-columns: minmax(190px, 1fr) auto;
  }

  .world-status {
    display: none;
  }

}

@media (max-width: 820px) {
  :root {
    --topbar-height: 62px;
    --dock-height: 66px;
  }

  .topbar {
    gap: 10px;
    padding: 0 12px;
  }

  .brand-seal {
    width: 38px;
    height: 38px;
    font-size: 19px;
  }

  .brand h1 {
    font-size: 18px;
  }

  .brand-kicker {
    font-size: 8px;
  }

  .resource {
    display: none;
  }

  .panel-toggle {
    display: grid;
  }

  .game-layout {
    display: block;
  }

  .map-stage {
    width: 100%;
    height: 100%;
  }

  .side-panel {
    position: absolute;
    top: 0;
    right: 0;
    /* Leave the bottom tool bar (and its friend / chat button) clickable. */
    bottom: calc(58px * var(--hud-scale, 1));
    width: min(310px, calc(100% - 38px));
    box-shadow: -20px 0 50px rgba(0, 0, 0, 0.48);
    transform: translateX(105%);
    transition: transform 200ms ease;
  }

  .side-panel.open {
    transform: translateX(0);
  }

  .bottom-dock {
    justify-content: flex-start;
    overflow-x: auto;
    padding-inline: 8px;
    scrollbar-width: none;
  }

  .bottom-dock::-webkit-scrollbar {
    display: none;
  }

  .dock-button {
    flex: 0 0 72px;
    width: 72px;
  }
}

/* Skill bar: two hand slots like the client's ImediaLeftSkill / ImediaRightSkill */
/* ui4 "00" skin HUD exported by tools/export_ui.py; coordinates from the client inis. */
.pt-status,
.pt-toolbar-body {
  image-rendering: auto;
  user-select: none;
}

.pt-status {
  position: absolute;
  top: 6px;
  left: 6px;
  width: 251px;
  height: 93px;
  transform: scale(var(--status-scale, 1));
  transform-origin: top left;
  pointer-events: none;
  z-index: 6;
  color: #fff;
  font: 12px/14px Tahoma, Verdana, "Segoe UI", sans-serif;
  text-shadow:
    0.8px 0 #000, -0.8px 0 #000, 0 0.8px #000, 0 -0.8px #000,
    0.8px 0.8px #000, -0.8px -0.8px #000;
}

.pt-status > *,
.pt-toolbar-body > * {
  position: absolute;
}

.pt-status-frame,
.pt-toolbar-frame {
  left: 0;
  top: 0;
}

.pt-portrait {
  left: 10px;
  top: 22px;
  width: 64px;
  height: 64px;
}

/* Text sits on the frame's rows: name band 20-34, bar slots 38-46 / 48-56 / 58-66 /
   68-76, title band 79-88 (pixels of status-frame.png). The panel is scaled up via
   --status-scale, so the small native font renders around 13px. */
.pt-name {
  left: 90px;
  top: 21px;
  width: 136px;
  color: rgb(255, 251, 254);
  font: 700 13px/12px var(--font-title);
  letter-spacing: 0.3px;
  text-align: center;
  white-space: nowrap;
}

.pt-bar {
  width: 142px;
  height: 7px;
  overflow: visible;
}

.pt-bar i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 100%;
  background-repeat: no-repeat;
  background-size: 142px 7px;
}

.pt-bar span {
  position: absolute;
  left: 0;
  right: 0;
  top: -1.5px;
  font-size: 9.5px;
  line-height: 10px;
  letter-spacing: 0.3px;
  text-align: center;
  white-space: nowrap;
}

.pt-life { left: 87px; top: 39px; }
.pt-mana { left: 86px; top: 49px; }
.pt-exp { left: 82px; top: 59px; }
.pt-exp2 { left: 77px; top: 69px; }
.pt-life i { background-image: url("assets/ui/hud/bar-life.png"); }
.pt-mana i { background-image: url("assets/ui/hud/bar-mana.png"); }
.pt-exp i,
.pt-exp2 i { background-image: url("assets/ui/hud/bar-exp.png"); }
.pt-life span { color: rgb(255, 226, 220); }
.pt-mana span { color: rgb(200, 236, 255); }

.pt-level {
  left: 45px;
  top: 66px;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  background: url("assets/ui/hud/level.png") no-repeat;
  color: rgb(241, 220, 227);
  font: 700 12px/12px var(--font-level, Tahoma, sans-serif);
}

.pt-title {
  left: 72px;
  top: 78px;
  width: 126px;
  color: #d8cfae;
  font: 700 11px/11px var(--font-title);
  letter-spacing: 0.6px;
  text-align: center;
  white-space: nowrap;
}

/* Target panel (ui4 人物点选界面00 scheme, ini 0x9eaabe41): shown top centre while a
   monster is selected. Layout in client pixels: kill icon (5,4), level box (44,6),
   name (71,5) 180 wide, life bar (45,22); the grey row under it carries the life
   percentage in the ini's LifePercentFontColor. */
.pt-target {
  position: absolute;
  left: 50%;
  top: 4px;
  width: 294px;
  height: 48px;
  z-index: 6;
  transform: translateX(-50%) scale(var(--status-scale, 1));
  transform-origin: top center;
  pointer-events: none;
  animation: pt-target-in 160ms ease-out;
}

.pt-target[hidden] {
  display: none;
}

@keyframes pt-target-in {
  from {
    opacity: 0;
    translate: 0 -6px;
  }
}

.pt-target > * {
  position: absolute;
}

.pt-target-frame {
  left: 0;
  top: 0;
}

.pt-target-icon {
  left: 5px;
  top: 4px;
}

.pt-target-level,
.pt-target-name,
.pt-target-hp {
  color: #fff;
  text-align: center;
  white-space: nowrap;
  text-shadow: var(--pt-text-border);
}

.pt-target-level {
  left: 44px;
  top: 5px;
  width: 28px;
  font: 700 11px/14px var(--font-level, Tahoma, sans-serif);
}

.pt-target-name {
  left: 71px;
  top: 4px;
  width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
  font: 700 13px/15px var(--font-title);
  letter-spacing: 0.3px;
}

.pt-target-life {
  left: 45px;
  top: 22px;
  width: 228px;
  height: 7px;
  overflow: hidden;
}

.pt-target-life i {
  display: block;
  width: 100%;
  height: 100%;
  background: url("assets/ui/target/life-green.png") no-repeat 0 0;
  transition: width 180ms ease-out;
}

.pt-target-life i[data-life="half"] {
  background-image: url("assets/ui/target/life-yellow.png");
}

.pt-target-life i[data-life="low"] {
  background-image: url("assets/ui/target/life.png");
}

/* What the target is under, below its bar: the curses' 16 px icons, the effects as badges. */
.pt-target-states {
  left: 45px;
  top: 50px;
  display: flex;
  gap: 2px;
}

.pt-target-states img,
.pt-target-states span {
  display: block;
  height: 16px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.75);
}

.pt-target-states img {
  width: 16px;
}

.pt-target-states span {
  padding: 0 3px;
  border-radius: 3px;
  background: rgba(20, 14, 8, 0.85);
  color: var(--state-color, #fff);
  font: 700 10px/16px sans-serif;
  text-shadow: 1px 1px 0 #000;
  white-space: nowrap;
}

/* Recent damage flashes white on the bar end. */
.pt-target.hit .pt-target-life i {
  filter: brightness(1.6);
}

.pt-target-hp {
  left: 45px;
  top: 29px;
  width: 228px;
  color: rgb(248, 252, 0);
  font: 500 10px/9px "IBM Plex Mono", Consolas, monospace;
  letter-spacing: 0.4px;
}

.pt-toolbar {
  position: absolute;
  left: 50%;
  bottom: 0;
  translate: -50% 0;
  width: calc(756px * var(--hud-scale, 1));
  height: calc(58px * var(--hud-scale, 1));
  z-index: 6;
}

.pt-toolbar-body {
  width: 756px;
  height: 58px;
  transform: scale(var(--hud-scale, 1));
  transform-origin: bottom center;
  position: absolute;
  left: 50%;
  bottom: 0;
  margin-left: -378px;
}

.pt-quickbar {
  left: 240px;
  top: 18px;
}

.pt-tool {
  left: var(--x);
  top: 14px;
  width: 32px;
  height: 40px;
  padding: 0;
  border: 0;
  background: transparent no-repeat 0 0;
  cursor: inherit;
}

.pt-tool:hover {
  background-position: -64px 0;
}

.pt-tool:active,
.pt-tool.active {
  background-position: -32px 0;
}

.pt-ibshop {
  left: 389px;
  top: -1px;
  width: 54px;
  height: 58px;
  background-image: url("assets/ui/hud/btn-ibshop.png");
}

.pt-ibshop:hover {
  background-position: -108px 0;
}

.pt-ibshop:active {
  background-position: -54px 0;
}

.skill-slot {
  position: absolute;
  left: var(--x);
  top: 20px;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: inherit;
  overflow: hidden;
}

.skill-slot:hover,
.skill-slot.open {
  outline: 1px solid rgba(255, 228, 140, 0.85);
  box-shadow: 0 0 8px rgba(240, 212, 123, 0.55);
}

.skill-slot b {
  position: absolute;
  left: 1px;
  bottom: 0;
  color: #fff;
  font: 700 10px/11px Tahoma, Verdana, sans-serif;
  text-shadow: 1px 0 #000, -1px 0 #000, 0 1px #000, 0 -1px #000;
  pointer-events: none;
}

.skill-slot img[src=""] {
  visibility: hidden;
}

.skill-slot img,
.skill-option img {
  display: block;
  width: 100%;
  height: 100%;
  image-rendering: auto;
}

/* Cooldown clock (tham_khao/ui_coldown_skill.png): the slot is dimmed and opens clockwise
   from 12 o'clock as the wait runs out (--cd: share of the wait left, 1 -> 0). */
.skill-cooldown {
  position: absolute;
  inset: 0;
  background: conic-gradient(transparent calc((1 - var(--cd, 0)) * 360deg), rgba(8, 14, 22, 0.68) 0);
  pointer-events: none;
}

.skill-slot.no-mana img {
  filter: grayscale(0.8) brightness(0.6);
}

.skill-picker {
  position: absolute;
  right: 8px;
  bottom: calc(100% + 6px);
  width: 286px;
  padding: 10px;
  border: 1px solid rgba(209, 168, 76, 0.55);
  background: rgba(30, 26, 19, 0.97);
  box-shadow: 0 10px 28px var(--shadow);
}

.skill-picker[hidden] {
  display: none;
}

.skill-picker-head {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: 8px;
}

.skill-picker-head strong {
  color: var(--gold-bright);
  font-size: 12px;
}

.skill-picker-head small,
.skill-info {
  color: var(--paper-muted);
  font-size: 10px;
}

.skill-grid {
  display: grid;
  grid-template-columns: repeat(6, 38px);
  gap: 7px;
}

.skill-option {
  position: relative;
  width: 38px;
  height: 38px;
  padding: 0;
  border: 1px solid rgba(209, 168, 76, 0.3);
  background: #15130f;
  cursor: pointer;
}

.skill-option:hover,
.skill-option.selected {
  border-color: var(--gold-bright);
}

.skill-option.selected::after {
  content: "";
  position: absolute;
  inset: -3px;
  border: 1px solid var(--gold);
  pointer-events: none;
}

.skill-key {
  position: absolute;
  right: 1px;
  bottom: 0;
  padding: 0 2px;
  background: rgba(0, 0, 0, 0.7);
  color: #ffe58a;
  font-size: 18px;
  font-weight: 700;
  line-height: 22px;
}

.skill-info {
  min-height: 26px;
  margin: 8px 0 0;
  line-height: 1.35;
}

.skill-info strong {
  color: var(--paper);
}

@media (max-width: 560px) {
  .skill-picker {
    width: min(286px, calc(100vw - 24px));
  }

}

/* Client mouse cursors ([CursorList] in UiPubLicSetting.ini, PhongThanCursorResources.h),
   hotspot at the tip. The client shows only its own cursors: slot 0 everywhere, buttons and
   windows too (no hand / move / help system cursor), so it wins over every other rule. */
body,
body *,
body *::before,
body *::after {
  cursor: url("assets/ui/cursors/normal.png") 0 0, auto !important;
}

/* Slot 1 on a monster, slot 2 on an NPC or a place, slot 3 on an item on the ground. */
#gameCanvas.cursor-attack {
  cursor: url("assets/ui/cursors/attack.png") 0 0, crosshair !important;
}

#gameCanvas.cursor-dialog {
  cursor: url("assets/ui/cursors/dialog.png") 0 0, pointer !important;
}

#gameCanvas.cursor-pick {
  cursor: url("assets/ui/cursors/pick.png") 0 0, pointer !important;
}

/* KUiBase::SetCurrentCursor: the shop's repair state (slot 7) on every element. */
body.cursor-repair,
body.cursor-repair * {
  cursor: url("assets/ui/cursors/repair.png") 0 0, auto !important;
}

/* Client mini map (ui4 小地图 inis), top right of the stage. Layout in client pixels. */
.pt-minimap {
  position: absolute;
  top: 0;
  right: 0;
  width: 208px;
  height: 163px;
  transform: scale(var(--minimap-scale, 1));
  transform-origin: top right;
  z-index: 6;
  user-select: none;
  font: 12px/14px Tahoma, Verdana, "Segoe UI", sans-serif;
}

.pt-minimap > * {
  position: absolute;
}

.mm-map {
  left: 37px;
  top: 16px;
  width: 152px;
  height: 126px;
  border: 1px solid #0d0904;
  outline: 1px solid rgba(181, 141, 62, 0.75);
  background: #2a2216;
  overflow: hidden;
}

#minimapCanvas {
  display: block;
  width: 150px;
  height: 124px;
  cursor: inherit;
}

.mm-title {
  left: 15px;
  top: 0;
  pointer-events: none;
}

.mm-name,
.mm-pos {
  color: #00ff00;
  font-weight: 400;
  letter-spacing: 1px;
  text-align: center;
  white-space: nowrap;
  pointer-events: none;
  text-shadow: 1px 1px 0 #000, -1px 0 0 #000, 0 -1px 0 #000;
}

.mm-name {
  left: 50px;
  top: 3px;
  width: 129px;
  font: 700 14px/16px var(--font-title);
  letter-spacing: 0.5px;
}

.mm-pos {
  left: 37px;
  top: 19px;
  width: 130px;
}

.mm-btn {
  left: var(--x);
  top: var(--y);
  width: 18px;
  height: 18px;
  padding: 0;
  border: 0;
  background: transparent no-repeat calc(var(--up) * -18px) 0;
  cursor: inherit;
}

.mm-btn:hover {
  background-position: calc(min(2, var(--frames) - 1) * -18px) 0;
}

.mm-btn:active,
.mm-btn.on {
  background-position: -18px 0;
}

.mm-coord {
  left: 37px;
  top: 142px;
  width: 151px;
  height: 20px;
  margin: 0;
}

.mm-coord > * {
  position: absolute;
}

.mm-coord img {
  left: 0;
  top: 0;
  pointer-events: none;
}

.mm-coord input {
  top: 3px;
  width: 28px;
  height: 15px;
  padding: 0 1px;
  border: 0;
  outline: 0;
  background: transparent;
  color: rgb(218, 255, 165);
  font: 12px/15px Tahoma, Verdana, sans-serif;
}

#miniMapX { left: 16px; }
#miniMapY { left: 58px; }

.mm-coord-btn {
  left: var(--x);
  top: 3px;
  width: 14px;
  height: 14px;
  padding: 0;
  border: 0;
  background: transparent no-repeat 0 0;
  cursor: inherit;
}

.mm-coord-btn:hover,
.mm-coord-btn:active {
  background-position: -14px 0;
}

/* Collapsed (▼): only the title bar stays. */
.pt-minimap.collapsed > :not(.mm-title, .mm-name, .mm-close) {
  display: none;
}


/* System message pad (KSysMsgCentrePad, tham_khao/ui_tin_he_thong2.png): 4 tabs over a
   see-through 10-line body with Up/Down buttons, bottom-left of the game view. Laid out
   in client pixels and scaled; raised over the tool bar when the stage is too narrow. */
.pt-sysmsg {
  position: absolute;
  left: 0;
  bottom: calc(var(--sys-lift, 0) * 58px * var(--hud-scale, 1));
  width: 227px;
  /* 19px tabs + 1px gap + 140px body (10 lines; the client shows 5 in 70px). */
  height: 160px;
  z-index: 5;
  transform: scale(var(--sys-scale, 1));
  transform-origin: bottom left;
  /* Face from map.systemFont (src/fonts.js); line height follows the size. */
  font-family: var(--font-system, "PT Font 14", Tahoma, sans-serif);
  font-size: var(--font-system-size, 14px);
  font-weight: var(--font-system-weight, 400);
  line-height: var(--font-system-line, 14px);
  user-select: text;
}

.sys-tabs {
  position: absolute;
  inset: 0 0 auto 0;
  height: 19px;
}

.sys-tab {
  position: absolute;
  left: var(--x);
  top: 0;
  width: var(--w);
  height: 19px;
  padding: 0;
  border: 0;
  background: no-repeat 0 0;
  font-size: 0;
  color: transparent;
  cursor: inherit;
}

.sys-tab.on {
  background-position: calc(-1 * var(--w)) 0;
}

.sys-tab:hover:not(.on) {
  filter: brightness(1.2);
}

/* New lines in a tab you are not looking at. */
.sys-tab.unread:not(.on) {
  animation: sys-unread 0.9s steps(2, jump-none) infinite;
}

@keyframes sys-unread {
  to {
    filter: brightness(1.45);
  }
}

.sys-body {
  position: absolute;
  left: 0;
  right: 0;
  top: 20px;
  bottom: 0;
  background: rgba(0, 0, 0, 0.6);
}

.sys-list {
  position: absolute;
  left: 1px;
  right: 17px;
  top: 1px;
  bottom: 1px;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  scrollbar-width: none;
  overscroll-behavior: contain;
}

/* Newest line on the bottom edge, like the client's message list. */
.sys-list > :first-child {
  margin-top: auto;
}

.sys-list::-webkit-scrollbar {
  display: none;
}

.sys-list .chat-line {
  line-height: var(--font-system-line, 14px);
}

.sys-title {
  color: #fff;
}

.sys-arrow {
  position: absolute;
  right: 0;
  width: 15px;
  height: 14px;
  padding: 0;
  border: 0;
  background: no-repeat 0 0;
  cursor: inherit;
}

.sys-arrow:hover {
  filter: brightness(1.25);
}

.sys-arrow:active {
  translate: 0 1px;
}

/* Chat (ui4 UiChatCentre: 聊天框背景00 skin), the right column. */
.pt-chat {
  /* 260x768 swirl skin, stretched to the column so no tile seam shows. */
  background: #2a2410 url("assets/ui/chat/bg.png") no-repeat 0 0 / 100% max(768px, 100%);
  /* Face from map.chatFont (src/fonts.js). */
  font-family: var(--font-chat, "PT Font 14", Tahoma, sans-serif);
  font-size: var(--font-chat-size, 14px);
  font-weight: var(--font-chat-weight, 400);
  line-height: calc(var(--font-chat-line, 14px) + 2px);
  user-select: text;
}

.pt-chat > * {
  position: absolute;
}

/* ChatRoom_Scroll: the 滑动条 rail between the game view and the messages, with the
   通用拖动条 knob (drag it, click the rail or use the wheel). */
.chat-track {
  left: 0;
  top: 0;
  bottom: 38px;
  width: 20px;
  border-left: 1px solid #000;
  background:
    url("assets/ui/chat/track.png") repeat-y 3px 0,
    linear-gradient(90deg, rgba(0, 0, 0, 0.35), rgba(0, 0, 0, 0.1));
  cursor: inherit;
  touch-action: none;
}

.chat-thumb {
  position: absolute;
  left: 2px;
  top: 3px;
  width: 15px;
  height: 20px;
  background: url("assets/ui/chat/thumb.png") no-repeat;
}

.chat-thumb:hover,
.chat-track.dragging .chat-thumb {
  filter: brightness(1.25);
}

.chat-list {
  left: 23px;
  right: 2px;
  top: 3px;
  bottom: 42px;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  scrollbar-width: none;
  overscroll-behavior: contain;
}

/* TextBottom=1 in the client: newest line sits on the bottom edge. */
.chat-list > :first-child {
  margin-top: auto;
}

.chat-list::-webkit-scrollbar {
  display: none;
}

.chat-line {
  margin: 0;
  color: rgb(255, 249, 148);
  overflow-wrap: anywhere;
  text-shadow: var(--pt-text-border);
}

.chat-line img {
  width: 19px;
  height: 13px;
  margin-right: 2px;
  vertical-align: -2px;
}

.chat-sender {
  color: rgb(220, 220, 220);
}

.chat-channels {
  left: 0;
  right: 0;
  bottom: 19px;
  height: 19px;
  background: rgba(10, 7, 2, 0.55);
}

.chat-channels {
  display: flex;
  justify-content: space-between;
  padding: 0 1px;
}

.chat-chk {
  position: relative;
  flex: none;
  width: var(--w);
  height: 19px;
  padding: 0 0 0 16px;
  border: 0;
  background: transparent no-repeat calc(var(--w) * -1) 0;
  color: #f2c94c;
  font: 700 11px/19px Tahoma, Verdana, sans-serif;
  text-align: left;
  text-shadow: 1px 1px 0 #000;
  white-space: nowrap;
  cursor: inherit;
}

.chat-chk.off {
  background-position: 0 0;
  color: #b58f3a;
}

.chat-bar {
  left: 0;
  right: 0;
  bottom: 0;
  height: 19px;
  margin: 0;
}

.chat-bar > * {
  position: absolute;
}

/* 聊天框00 as a 3-slice so the input bar stretches with the column. */
.chat-bar-bg {
  inset: 0;
  width: 100%;
  height: 19px;
  box-sizing: border-box;
  border-style: solid;
  border-width: 0 40px 0 46px;
  border-image: url("assets/ui/chat/bar.png") 0 40 0 46 fill stretch;
  pointer-events: none;
}

.chat-icon {
  left: var(--x);
  top: 0;
  width: var(--w);
  height: 19px;
  padding: 0;
  border: 0;
  background: transparent no-repeat 0 0;
  cursor: inherit;
}

.chat-hide {
  top: 2px;
  height: 15px;
}

#chatFace { left: auto; right: 20px; }
#chatHide { left: auto; right: 2px; }

.chat-icon:hover {
  background-position: calc(var(--w) * -2) 0;
}

.chat-icon:active,
.chat-icon.on {
  background-position: calc(var(--w) * -1) 0;
}

.chat-channel {
  left: 22px;
  top: 1px;
  width: 22px;
  height: 17px;
  padding: 0;
  border: 1px solid #8a6a2c;
  background: #1a1206;
  font: 700 10px/15px Tahoma, Verdana, sans-serif;
  text-shadow: 1px 1px 0 #000;
  cursor: inherit;
}

#chatInput {
  left: 46px;
  right: 41px;
  top: 3px;
  height: 13px;
  padding: 0 2px;
  border: 0;
  outline: 0;
  background: transparent;
  color: rgb(254, 255, 160);
  font: 12px/13px Tahoma, Verdana, sans-serif;
}

#chatInput:focus {
  background: rgba(25, 31, 11, 0.94);
}

/* Hide button: keep only the input bar. */
.pt-chat.chat-collapsed .chat-list,
.pt-chat.chat-collapsed .chat-track,
.pt-chat.chat-collapsed .chat-channels {
  visibility: hidden;
}

/* ---- Status window (F3): KUiStatus 状态.spr frame + attribute detail window ---- */
.pt-statwin {
  position: absolute;
  /* zoom (not transform: scale) keeps the text on whole pixels; a scaled layer at a
     fractional offset made the attribute list shimmer when the panel repainted.
     zoom also scales left/top, hence the division. */
  left: calc(8px / var(--statwin-scale, 1));
  top: calc(var(--window-top, 116px) / var(--statwin-scale, 1));
  z-index: 12;
  display: flex;
  gap: 6px;
  align-items: flex-start;
  zoom: var(--statwin-scale, 1);
  color: rgb(232, 226, 200);
  font: var(--font-status-weight, 500) 12px/15px var(--font-status, Georgia, serif);
  text-shadow: var(--pt-text-border);
  animation: sw-in 140ms ease-out;
}

.pt-statwin[hidden],
.sw-panel[hidden] {
  display: none;
}

@keyframes sw-in {
  from {
    opacity: 0;
    translate: -10px 0;
  }
}

.sw-panel {
  position: relative;
  width: 277px;
  height: 459px;
  flex: none;
}

.sw-frame {
  position: absolute;
  inset: 0;
  pointer-events: none;
  user-select: none;
}

.sw-drag {
  position: absolute;
  left: 24px;
  right: 34px;
  top: 0;
  height: 28px;
  cursor: move;
  touch-action: none;
}

.sw-close {
  position: absolute;
  left: 255px;
  top: 7px;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  background: url("assets/ui/status/close.png") 0 0 no-repeat;
  cursor: pointer;
}

.sw-close:hover {
  background-position: -40px 0;
}

.sw-close:active {
  background-position: -20px 0;
}

.sw-pagetab {
  position: absolute;
  left: 40px;
  top: 30px;
  width: 32px;
  height: 25px;
  padding: 0;
  border: 0;
  background: url("assets/ui/status/tab-status.png") 0 0 no-repeat;
}

.sw-pagetab.on {
  background-position: -32px 0;
}

.sw-title {
  position: absolute;
  left: 82px;
  width: 114px;
  top: 4px;
  height: 18px;
  overflow: hidden;
  color: #fff;
  font: 700 12px/18px var(--font-window-title, var(--font-title));
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  text-shadow: var(--pt-text-border);
  pointer-events: none;
}
/* Chi tiết thuộc tính keeps its written case. */
.sw-title-plain {
  text-transform: none;
}


/* 状态内.spr: a 1px gold border on a dark translucent fill. */
.sw-inner {
  position: absolute;
  left: 26px;
  top: 56px;
  width: 231px;
  height: 387px;
  box-sizing: border-box;
  padding: 7px 8px;
  border: 1px solid rgb(167, 151, 84);
  border-radius: 5px;
  background: rgba(7, 9, 7, 0.66);
}

.sw-inner dl {
  margin: 0;
}

.sw-inner dt,
.sw-inner dd {
  margin: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.sw-inner dt[title] {
  cursor: help;
}

.sw-inner dd {
  color: rgb(255, 217, 78);
}

.sw-inner h4 {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 6px 0 2px;
  color: rgb(214, 189, 120);
  font: inherit;
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}

.sw-inner h4::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, rgba(167, 151, 84, 0.8), transparent);
}

.sw-card {
  display: grid;
  grid-template-columns: 67px 1fr;
  align-items: center;
  gap: 7px;
}

.sw-face {
  width: 65px;
  height: 65px;
  border: 1px solid rgb(167, 151, 84);
  background: #000;
  box-shadow: 0 0 0 1px #000, inset 0 0 6px #000;
}

.sw-face img {
  display: block;
  width: 65px;
  height: 65px;
}

.sw-info {
  display: grid;
  grid-template-columns: 66px minmax(0, 1fr);
  align-content: center;
  line-height: 17px;
}

/* Character card values are green like StatusPage_Name / _Level (Color=0,255,0). */
.sw-info dd,
.sw-pair dd {
  color: rgb(90, 255, 110);
}

.sw-info dd.max {
  font-weight: 700;
}

/* Cấp / Hạng / Danh vọng on one row. */
.sw-pair div {
  display: flex;
  gap: 5px;
  white-space: nowrap;
}

.sw-pair {
  display: flex;
  justify-content: space-between;
  column-gap: 6px;
  margin-top: 5px;
}

.sw-exp {
  margin-top: 3px;
}

.sw-exp > span {
  margin-right: 6px;
}

.sw-exp b {
  float: right;
  color: rgb(90, 255, 110);
  font-weight: inherit;
}

.sw-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto;
  column-gap: 6px;
}

.sw-grid dd {
  text-align: right;
}

.sw-grid dd.wide {
  grid-column: span 3;
}

/* Sát thương uses the Phòng thủ columns (label, its value beside it, two pairs a row);
   Sát thương cơ bản, too long for half a row, has a row of its own with the value under
   the right-hand values. */

/* Empty right half after a row of its own (Phòng ngự). */
.sw-grid .sw-gap {
  grid-column: span 2;
}

/* Long label over the first three columns, value in the last (Xuất chiêu rows). */
.sw-grid dt.wide {
  grid-column: span 3;
}

.sw-cur {
  display: inline-block;
  text-align: right;
}

.sw-grid dd small {
  display: inline-block;
  min-width: 42px;
  margin-left: 6px;
  color: rgb(150, 220, 140);
  font-size: 11px;
  cursor: help;
}

.sw-potential dd {
  min-width: 30px;
  color: rgb(255, 236, 140);
  font-weight: 700;
}

/* Sits at the end of the Điểm tiềm năng heading, after its rule line. */
.sw-more {
  order: 1;
  flex: none;
  height: 17px;
  padding: 0 5px;
  white-space: nowrap;
  letter-spacing: normal;
  text-transform: none;
  border: 1px solid rgb(167, 151, 84);
  border-radius: 2px;
  background: linear-gradient(180deg, #3b2a12, #120c05);
  color: rgb(240, 222, 160);
  font: inherit;
  font-size: 10px;
  font-weight: 400;
  text-shadow: var(--pt-text-border);
  cursor: pointer;
}

.sw-more:hover,
.sw-more.on {
  background: linear-gradient(180deg, #6a3a12, #3a1d07);
  color: #fff3c0;
}

/* Detail window pages: the npc dialog 6-character button stretched into tabs. */
.sw-tabs {
  position: absolute;
  left: 28px;
  top: 32px;
  display: flex;
  gap: 3px;
}

.sw-tabs button {
  width: 73px;
  height: 19px;
  padding: 0;
  border: 0;
  background: url("assets/ui/status/tab.png") 0 0 / 219px 19px no-repeat;
  color: rgb(200, 190, 150);
  font: inherit;
  font-size: 11px;
  line-height: 19px;
  text-shadow: var(--pt-text-border);
  cursor: pointer;
}

.sw-tabs button:hover {
  background-position: -73px 0;
  color: #fff;
}

.sw-tabs button.on {
  background-position: -146px 0;
  color: #ffe9a0;
  font-weight: 700;
}

/* The frame is as tall as the item window; the status rows share the spare height. */
.sw-status .sw-inner {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

/* Trạng thái and Chi tiết thuộc tính are 64px wider than 状态.spr (frame-wide.png: the frame with 32px of straight
   bar added on each side of the title plate), so the "min-max" ranges have room. */
.sw-panel.sw-status,
.sw-panel.sw-detail {
  width: 341px;
  /* 36px taller than 状态.spr (Lực tay trái / phải rows): frame-wide.png is drawn with
     border-image (::before) so the bar, plaque and corners keep their pixels. */
  height: 495px;
}

.sw-status .sw-frame,
.sw-detail .sw-frame {
  display: none;
}

.sw-panel.sw-status::before,
.sw-panel.sw-detail::before {
  content: "";
  position: absolute;
  inset: 0;
  border: solid transparent;
  border-width: 30px 16px 18px;
  border-image: url("assets/ui/status/frame-wide.png") 30 16 18 fill / 30px 16px 18px stretch;
  pointer-events: none;
}

.sw-status .sw-inner,
.sw-detail .sw-inner {
  width: 295px;
  height: 423px;
}

.sw-status .sw-close,
.sw-detail .sw-close {
  left: 319px;
}

.sw-status .sw-title,
.sw-detail .sw-title {
  left: 114px;
}

/* The three page tabs centred over the wider list. */
.sw-detail .sw-tabs {
  left: 58px;
}

/* Chỉ số tấn công: Xuất chiêu and Bạo kích side by side, Chính xác / Né tránh under them. */
/* Chỉ số tấn công: the two halves as wide as each other (XC vật lý / Bạo kích PT...). */
.sw-grid.sw-attack {
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto;
}

.sw-detail-body {
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgb(167, 151, 84) rgba(0, 0, 0, 0.4);
}

.sw-list {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 8px;
  margin-bottom: 5px !important;
  padding: 2px 6px;
  border: 1px solid rgba(167, 151, 84, 0.35);
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.28);
}

.sw-list dd {
  text-align: right;
}

/* ---- Item window (F4, KUiItem / UiItem.ini): 538x459 道具栏 frame, window px. ---- */
/* Mirror of the status window: right edge, below the mini map, slides in from the right. */
.pt-itemwin {
  position: absolute;
  right: calc(8px / var(--itemwin-scale, 1));
  top: calc(var(--window-top, 116px) / var(--itemwin-scale, 1));
  z-index: 12;
  width: 538px;
  height: 459px;
  zoom: var(--itemwin-scale, 1);
  color: rgb(255, 217, 78);
  font: var(--font-status-weight, 500) 12px/15px var(--font-status, Georgia, serif);
  text-shadow: var(--pt-text-border);
  animation: iw-in 140ms ease-out;
}

.pt-itemwin[hidden] {
  display: none;
}

@keyframes iw-in {
  from {
    opacity: 0;
    translate: 10px 0;
  }
}

.iw-frame {
  position: absolute;
  inset: 0;
  pointer-events: none;
  user-select: none;
}

/* Title on the frame's plaque (its baked caption is cleared by export_ui.py). */
.iw-title {
  position: absolute;
  left: 170px;
  width: 200px;
  top: 6px;
  height: 18px;
  overflow: hidden;
  color: #fff;
  font: 700 12px/18px var(--font-window-title, var(--font-title));
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  text-shadow: var(--pt-text-border);
  pointer-events: none;
}

.iw-drag {
  position: absolute;
  left: 34px;
  right: 40px;
  top: 0;
  height: 28px;
  cursor: move;
  touch-action: none;
}

.pt-itemwin button {
  position: absolute;
  padding: 0;
  border: 0;
  background-color: transparent;
  background-repeat: no-repeat;
  cursor: pointer;
}

.iw-close {
  left: 505px;
  top: 9px;
  width: 20px;
  height: 20px;
  background-image: url("assets/ui/items/close.png");
}

.iw-close:hover {
  background-position: -40px 0;
}

.iw-close:active {
  background-position: -20px 0;
}

/* 人物图画: the class figure behind the equipment boxes ([Equip] 37, 35). */
.iw-figure {
  position: absolute;
  left: 37px;
  top: 35px;
  width: 230px;
  height: 355px;
  background: url("assets/ui/items/figure.png") 0 0 no-repeat;
  opacity: 0.55;
  pointer-events: none;
}

/* Nhân giới / Tiên Ma giới tabs: frame 0 selected, frame 1 not. */
.iw-world {
  top: 35px;
  width: 76px;
  height: 19px;
  background-position: -76px 0;
}

/* The two 76px tabs sit 64px apart (ini), so the selected one goes on top. */
.iw-world.on {
  z-index: 1;
  background-position: 0 0;
}

.iw-slot {
  position: absolute;
  background-repeat: no-repeat;
}

.iw-slot:hover,
.iw-cell:hover {
  outline: 1px solid rgba(255, 217, 78, 0.7);
  outline-offset: -1px;
}

/* Thần ấn: its box is the Pháp bảo one without the caption. */
.iw-slot span {
  display: grid;
  height: 100%;
  place-items: center;
  color: rgb(151, 151, 151);
  font-size: 11px;
  line-height: 12px;
  text-align: center;
  text-shadow: none;
  white-space: pre-line;
}

.iw-amulet {
  width: 15px;
  height: 15px;
  background-image: url("assets/ui/items/btn-amulet.png");
}

/* Hidden for now: there are no talisman skills yet. */
.iw-amulet[hidden] {
  display: none;
}

.iw-amulet:hover {
  background-position: -30px 0;
}

.iw-amulet:active {
  background-position: -15px 0;
}

/* Bag pages 1-4: frame 1 selected. */
.iw-page {
  width: 34px;
  height: 19px;
  background-image: url("assets/ui/items/tab-page.png");
}

.iw-page.on {
  background-position: -34px 0;
}

.iw-lock {
  left: 438px;
  top: 36px;
  width: 68px;
  height: 17px;
  background-image: url("assets/ui/items/chk-lock.png");
}

.iw-lock.on {
  background-position: -68px 0;
}

.iw-cell {
  position: absolute;
}

.iw-value {
  position: absolute;
  height: 13px;
  overflow: hidden;
  font-size: 12px;
  font-weight: 500;
  line-height: 13px;
  text-align: center;
  white-space: nowrap;
  cursor: help;
}

/* Bottom buttons: normal / pressed / highlighted. */
.iw-btn {
  top: 410px;
  width: 53px;
  height: 24px;
}

.iw-btn:hover {
  background-position: -106px 0;
}

.iw-btn:active {
  background-position: -53px 0;
}

/* 一键换装 icon above Pháp khí ([ChangeEquipSet] Equip + 171, 30): colour / grey. */
.iw-sets-toggle {
  left: 208px;
  top: 65px;
  width: 31px;
  height: 27px;
  background-image: url("assets/ui/items/btn-equipset.png");
}

.iw-sets-toggle:hover {
  filter: brightness(1.25);
}

.iw-sets-toggle:active {
  background-position: -31px 0;
}

/* Thay đổi trang bị: a blank status frame on the left of the item window. */
.iw-sets {
  position: absolute;
  left: -283px;
  top: 0;
  width: 277px;
  height: 459px;
  animation: iw-in 140ms ease-out;
}

.iw-sets[hidden] {
  display: none;
}

.iw-sets-frame {
  position: absolute;
  inset: 0;
  pointer-events: none;
  user-select: none;
}

.iw-sets-title {
  position: absolute;
  left: 72px;
  width: 134px;
  top: 4px;
  height: 18px;
  overflow: hidden;
  color: #fff;
  font: 700 12px/18px var(--font-window-title, var(--font-title));
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
}

.iw-sets-close {
  left: 255px;
  top: 7px;
  width: 20px;
  height: 20px;
  background-image: url("assets/ui/status/close.png");
}

.iw-sets-close:hover {
  background-position: -40px 0;
}

.iw-sets-close:active {
  background-position: -20px 0;
}

.iw-sets-box {
  position: absolute;
  left: 26px;
  width: 225px;
  box-sizing: border-box;
  border: 1px solid rgb(167, 151, 84);
  border-radius: 5px;
  background: rgba(7, 9, 7, 0.66);
}

/* Preview of the chosen set: one bag cell per equipment box. */
.iw-set-cell {
  position: absolute;
  width: 41px;
  height: 41px;
  background: url("assets/ui/items/cell.png") no-repeat;
}

.iw-set-cell span {
  display: grid;
  height: 100%;
  place-items: center;
  color: rgb(151, 151, 151);
  font-size: 10px;
  line-height: 11px;
  text-align: center;
  white-space: pre-line;
}

.iw-set-cell.filled {
  outline: 1px solid rgba(255, 217, 78, 0.7);
  outline-offset: -1px;
}

.iw-set-cell.filled span {
  color: rgb(255, 217, 78);
}

.iw-sets-controls {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-evenly;
  padding: 4px 8px;
}

.iw-sets-controls p {
  margin: 0;
  text-align: center;
}

.iw-sets-controls em {
  color: rgb(255, 64, 48);
  font-style: normal;
}

.iw-sets-controls select {
  width: 110px;
  height: 18px;
  padding: 0 4px;
  border: 1px solid rgb(167, 151, 84);
  border-radius: 2px;
  background: rgb(52, 50, 44);
  color: rgb(255, 217, 78);
  font: inherit;
  cursor: pointer;
}

.pt-itemwin .iw-set-btn {
  position: static;
  flex: none;
  height: 19px;
}

.iw-set-btn:hover {
  background-position: 100% 0;
}

.iw-set-btn:active {
  background-position: 50% 0;
}

.iw-sets-message {
  color: rgb(230, 230, 230);
  font-size: 11px;
  line-height: 14px;
}

/* ---- Items in the item window (src/item-window.js) ----
   Art is drawn at its own pixels, centred in the box and clipped to it, like
   PhongThanDrawSlotImage; the box art (with its caption) stays underneath. */
.iw-slot,
.iw-cell,
.iw-set-cell {
  display: grid;
  place-items: center;
  overflow: hidden;
}

.iw-set-cell.filled span,
.iw-slot.filled span {
  display: none;
}

.iw-item {
  max-width: none;
  cursor: pointer;
  user-select: none;
  image-rendering: pixelated;
}

.iw-item.dragging {
  opacity: 0.4;
}

/* Gear that cannot be worn now: red tint over the icon, as the client paints such items. */
.iw-cell.blocked::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(255, 0, 0, 0.3);
  pointer-events: none;
}

.iw-cell.drop,
.iw-slot.drop {
  outline: 1px solid rgb(255, 217, 78);
  outline-offset: -1px;
}

.iw-set-cell .iw-item {
  cursor: default;
}

/* Item tip, spaced like tham_khao/ui_trangbi.png (KMouseOver, UiMouseHover.ini): font
   14 on 14px lines, a dark see-through card in the RectColor 130,100,32 frame. The text
   column starts 95px in; the name, attributes and weight are centred in it, the intro,
   Ctrl+D line and chat hint are left / centred like the client, with blank lines (14px)
   between the blocks. The preview sits bottom-left. Every card is 410px wide so the tip
   is one clean rectangle; Ctrl+D puts the worn item's card beside it. */
.pt-itemtip {
  position: fixed;
  z-index: 60;
  display: flex;
  align-items: stretch;
  gap: 4px;
  color: #fff;
  font: 400 14px/14px "PT Font 14", Tahoma, sans-serif;
  pointer-events: none;
}

.pt-itemtip[hidden] {
  display: none;
}

/* Lines keep their spacing but wrap inside the text column: some attributes run past it
   ("Tỷ lệ sát thương tấn công chính xác toàn bộ pháp thuật: +15%" is ~400px). */
.pt-itemtip p {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  text-wrap: balance;
}

.pt-itemtip em {
  color: rgb(0, 255, 0);
  font-style: normal;
}

.tip-card {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  width: 410px;
  border: 1px solid rgb(130, 100, 32);
  background: rgba(37, 40, 37, 0.88);
}

.tip-heading {
  padding: 4px 0;
  color: rgb(255, 217, 78);
  text-align: center;
}

.tip-inner {
  position: relative;
  min-height: 130px;
  padding: 15px 8px 15px 95px;
}

.tip-name {
  margin-bottom: 14px !important;
  text-align: center;
}

/* The intro wraps to the text column, with its lines balanced in length (the client
   cut it every 32 characters, which split words and left a short last line). */
.pt-itemtip .tip-intro {
  margin-bottom: 14px;
  white-space: normal;
  text-align: center;
  text-wrap: balance;
}

.tip-props {
  margin-bottom: 28px;
  text-align: center;
}

.tip-props .bad {
  color: rgb(255, 0, 0);
}

/* Chat hint under the text column, below the preview (its own box in the sample). */
.tip-hint {
  margin-top: auto;
  padding: 8px 8px 10px 95px;
  line-height: 16px;
  text-align: center;
}

/* Big art on the green 装备大背景 (66x98), small art on the brown 装备小背景 (33x49)
   overlapping its lower right corner (PhongThanGenderPreview). */
.tip-preview {
  position: absolute;
  left: 6px;
  bottom: 1px;
  width: 82px;
  height: 122px;
}

.tip-preview.single {
  width: 66px;
  height: 98px;
}

.tip-big,
.tip-small {
  position: absolute;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: no-repeat center;
}

.tip-big {
  left: 0;
  top: 0;
  width: 66px;
  height: 98px;
  background-image: url("assets/items/preview-big.png");
}

.tip-small {
  left: 49px;
  top: 73px;
  width: 33px;
  height: 49px;
  background-image: url("assets/items/preview-small.png");
}

.tip-big img,
.tip-small img {
  max-width: none;
  image-rendering: pixelated;
}

/* Item held on the cursor (src/item-window.js), centred on the pointer. */
.pt-hand {
  position: fixed;
  z-index: 70;
  translate: -50% -50%;
  image-rendering: pixelated;
  pointer-events: none;
}

.pt-hand[hidden] {
  display: none;
}

/* Over the ground item the client shows its pick-up hand. */
#gameCanvas.cursor-pick {
  cursor: url("assets/ui/cursors/pick.png") 0 0, pointer;
}

/* Message box (src/message-box.js, UiInformation2.ini), centred over the game view:
   the "TIN TỨC" frame cut to 344x170 (export_ui.py), its dark panel from (18, 35) to
   (326, 130). */
.pt-msgbox {
  position: absolute;
  left: 50%;
  top: 40%;
  z-index: 40;
  width: 344px;
  height: 170px;
  translate: -50% -50%;
  color: rgb(232, 226, 200);
  font: 400 14px/18px "PT Font 14", Tahoma, sans-serif;
  text-shadow: none;
}

.pt-msgbox[hidden] {
  display: none;
}

/* The frame's panel is see-through; a dark fill under it keeps the map out of the text. */
.pt-msgbox::before {
  content: "";
  position: absolute;
  left: 8px;
  top: 26px;
  right: 8px;
  bottom: 14px;
  background: rgba(10, 12, 10, 0.8);
}

.mb-frame {
  position: absolute;
  inset: 0;
  pointer-events: none;
  user-select: none;
}

/* Close button in the frame's round slot (top right). */
.mb-close {
  position: absolute;
  left: 318px;
  top: 5px;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  background: url("assets/ui/dialog/close.png") no-repeat 0 0;
  cursor: pointer;
}

.mb-close:hover {
  background-position: -40px 0;
}

.mb-close:active {
  background-position: -20px 0;
}

/* Message: top of the dark panel, 14px in from its edges (UiInformation2 [Info]). */
.mb-text {
  position: absolute;
  left: 32px;
  top: 50px;
  width: 280px;
  height: 36px;
  margin: 0;
  overflow: hidden;
}

/* Item names in the message, yellow (UiInformation2 [Info] Color 255,253,122). */
.mb-text b {
  color: rgb(255, 253, 122);
  font-weight: 400;
}

.mb-btn {
  position: absolute;
  top: 96px;
  width: 50px;
  height: 23px;
  padding: 0;
  border: 0;
  background: transparent no-repeat 0 0;
  cursor: pointer;
}

.mb-btn:hover {
  background-position: -100px 0;
}

.mb-btn:active {
  background-position: -50px 0;
}

/* Options window "Cấu hình" (src/options-window.js, UiOptions.ini): the frame rebuilt
   blank at 420x150 (export_ui.py), its panel from (20, 28) to (398, 112); one row per
   slider (label, then −, the 180px track and +), "xác định" on the panel's foot. */
.pt-options {
  position: absolute;
  left: 50%;
  top: 40%;
  z-index: 41;
  width: 420px;
  height: 150px;
  translate: -50% -50%;
  color: rgb(248, 251, 159);
  font: 400 14px/16px "PT Font 14", Tahoma, sans-serif;
  user-select: none;
}

.pt-options[hidden] {
  display: none;
}

/* The frame's panel is see-through; a dark fill under it keeps the map out of the rows. */
.pt-options::before {
  content: "";
  position: absolute;
  left: 8px;
  top: 26px;
  right: 8px;
  bottom: 12px;
  background: rgba(10, 12, 10, 0.9);
}

.op-frame {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.op-title {
  position: absolute;
  left: 110px;
  width: 200px;
  top: 4px;
  height: 18px;
  color: #fff;
  font: 700 12px/18px var(--font-window-title, var(--font-title));
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  text-shadow: var(--pt-text-border);
  pointer-events: none;
}

/* Label on the left, [−][track][+] against the panel's right side (ui_cau_hinh.png). */
.op-row {
  position: absolute;
  left: 32px;
  right: 32px;
  display: flex;
  align-items: center;
  height: 15px;
}

.op-label {
  flex: 1;
  text-align: left;
  white-space: nowrap;
}

.op-step {
  width: 13px;
  height: 14px;
  padding: 0;
  border: 0;
  background: transparent no-repeat 0 0;
  cursor: pointer;
}

.op-step:hover {
  filter: brightness(1.6);
}

.op-step:active {
  filter: brightness(0.7);
}

.op-slider {
  position: relative;
  width: 180px;
  height: 15px;
  background: url("assets/ui/options/track.png") no-repeat;
  cursor: pointer;
  outline: none;
  touch-action: none;
}

.op-knob {
  position: absolute;
  top: 1px;
  width: 15px;
  height: 13px;
  background: url("assets/ui/options/knob.png") no-repeat;
  cursor: grab;
}

.op-slider:focus-visible .op-knob {
  filter: brightness(1.3);
}

.op-ok {
  position: absolute;
  left: 185px;
  top: 116px;
  width: 50px;
  height: 23px;
  padding: 0;
  border: 0;
  background: url("assets/ui/dialog/btn-ok.png") no-repeat 0 0;
  cursor: pointer;
}

/* 确定.spr: Up 0, Down 1, Over 2. */
.op-ok:hover {
  background-position: -100px 0;
}

.op-ok:active {
  background-position: -50px 0;
}

/* Centre notice (CenterNotice in src/message-box.js), as in tham_khao/ui_nhat_vat_pham.png. */
/* Bottom centre of the game view, just above the tool bar; newest line at the bottom. */
.pt-notice {
  position: absolute;
  left: 50%;
  bottom: calc(80px * var(--hud-scale, 1));
  z-index: 30;
  display: flex;
  flex-direction: column;
  align-items: center;
  translate: -50% 0;
  gap: 2px;
  pointer-events: none;
}

.pt-notice p {
  min-width: 300px;
  margin: 0;
  padding: 4px 48px;
  background: linear-gradient(90deg, transparent, rgba(0, 0, 0, 0.62) 18%, rgba(0, 0, 0, 0.62) 82%, transparent);
  color: #fff;
  font: 400 14px/15px "PT Font 14", Tahoma, sans-serif;
  text-align: center;
  white-space: nowrap;
  transition: opacity 400ms ease-out;
}

.pt-notice p.out {
  opacity: 0;
}

/* Thẻ Tân Thủ dialog (src/card-dialog.js), like tham_khao/ui_the_admin_khi_sudung.png:
   a dark see-through window in a thin gold frame, the brown title bar with the red gem,
   the round red close button, the message box and the option list (with its gold scroll
   bar) in their own gold-edged panels, "Kết thúc đối thoại" at the foot. */
.pt-carddlg,
.pt-trash {
  position: absolute;
  z-index: 38;
  box-sizing: border-box;
  border: 1px solid rgb(150, 118, 48);
  border-radius: 3px;
  background: rgba(14, 11, 8, 0.86);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.8), 0 6px 18px rgba(0, 0, 0, 0.55);
  color: rgb(232, 226, 210);
  font: 400 14px/16px "PT Font 14", Tahoma, sans-serif;
  text-shadow: 1px 1px 0 #000;
}

.pt-carddlg {
  left: 50%;
  top: 44%;
  width: 360px;
  height: 300px;
  translate: -50% -50%;
}

.pt-carddlg[hidden],
.pt-trash[hidden] {
  display: none;
}

.cd-head {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  height: 22px;
  border-bottom: 1px solid rgb(150, 118, 48);
  background: linear-gradient(rgb(92, 40, 30), rgb(52, 20, 16) 60%, rgb(36, 14, 12));
  text-align: center;
}

.cd-head strong {
  color: rgb(236, 214, 170);
  font-weight: 400;
  line-height: 22px;
}

/* The red gem in its gold setting on the title bar's left end. */
.cd-gem {
  position: absolute;
  left: -6px;
  top: -4px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 40% 35%, rgb(255, 150, 140) 0 2px, rgb(220, 20, 20) 3px 5px, rgb(110, 0, 0) 6px 7px, transparent 7.5px),
    radial-gradient(circle, rgb(240, 200, 90) 0 9px, rgb(120, 84, 20) 10px, transparent 11px);
}

.cd-close {
  position: absolute;
  right: -8px;
  top: -8px;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 2px solid rgb(225, 225, 225);
  border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, rgb(240, 90, 80), rgb(170, 20, 20) 60%, rgb(110, 0, 0));
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.7);
  cursor: pointer;
}

.cd-close::before,
.cd-close::after {
  content: "";
  position: absolute;
  left: 4px;
  top: 8px;
  width: 12px;
  height: 3px;
  border-radius: 1px;
  background: #fff;
  rotate: 45deg;
}

.cd-close::after {
  rotate: -45deg;
}

.cd-close:hover {
  filter: brightness(1.2);
}

.cd-text {
  position: absolute;
  left: 8px;
  top: 30px;
  right: 8px;
  height: 66px;
  box-sizing: border-box;
  padding: 5px 7px;
  /* Long texts (Gọi Quái: AI and skills of a monster) scroll inside the box. */
  overflow-x: hidden;
  overflow-y: auto;
  scrollbar-width: thin;
  border: 1px solid rgba(180, 145, 70, 0.75);
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.35);
}

.cd-text b {
  color: rgb(255, 253, 122);
  font-weight: 400;
}

.cd-search {
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}

.cd-search input {
  flex: 1;
  min-width: 0;
  height: 20px;
  box-sizing: border-box;
  padding: 0 5px;
  border: 1px solid rgb(150, 118, 48);
  background: rgba(0, 0, 0, 0.6);
  color: rgb(255, 246, 108);
  font: inherit;
  outline: 0;
}

.cd-status {
  display: block;
  margin-top: 6px;
  color: rgb(190, 184, 160);
}

.cd-select {
  position: absolute;
  left: 8px;
  top: 102px;
  right: 8px;
  bottom: 40px;
  border: 1px solid rgba(180, 145, 70, 0.75);
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.35);
}

.cd-list {
  position: absolute;
  left: 4px;
  top: 4px;
  right: 22px;
  bottom: 4px;
  margin: 0;
  padding: 0;
  overflow: hidden auto;
  list-style: none;
  scrollbar-width: none;
}

.cd-list::-webkit-scrollbar {
  display: none;
}

.cd-list li {
  padding: 0 3px;
  overflow: hidden;
  color: rgb(240, 240, 240);
  line-height: 18px;
  white-space: nowrap;
  text-overflow: ellipsis;
  cursor: pointer;
}

.cd-list li:hover {
  background: rgba(150, 150, 150, 0.45);
}

.cd-list li.on {
  color: rgb(255, 70, 50) !important;
}

.cd-list li.back {
  color: rgb(255, 253, 122);
}

/* Select_Scroll: gold arrow buttons, a gold thumb on a dark track. */
.cd-scroll {
  position: absolute;
  top: 3px;
  right: 3px;
  bottom: 3px;
  width: 15px;
}

.cd-scroll.idle {
  opacity: 0.45;
}

.cd-arrow {
  position: absolute;
  left: 0;
  width: 15px;
  height: 15px;
  padding: 0;
  border: 1px solid rgb(120, 92, 30);
  border-radius: 2px;
  background: linear-gradient(rgb(70, 52, 20), rgb(30, 22, 8));
  cursor: pointer;
}

.cd-arrow::before {
  content: "";
  position: absolute;
  left: 3px;
  width: 0;
  height: 0;
  border: 4px solid transparent;
}

.cd-arrow.up {
  top: 0;
}

.cd-arrow.up::before {
  top: 1px;
  border-bottom: 6px solid rgb(240, 200, 80);
}

.cd-arrow.down {
  bottom: 0;
}

.cd-arrow.down::before {
  top: 4px;
  border-top: 6px solid rgb(240, 200, 80);
}

.cd-track {
  position: absolute;
  left: 2px;
  top: 17px;
  bottom: 17px;
  width: 11px;
  background: rgba(0, 0, 0, 0.6);
}

.cd-thumb {
  position: absolute;
  left: -1px;
  width: 13px;
  height: 26px;
  box-sizing: border-box;
  border: 1px solid rgb(90, 68, 20);
  border-radius: 2px;
  background: linear-gradient(90deg, rgb(150, 120, 50), rgb(230, 200, 110) 45%, rgb(140, 110, 40));
  cursor: grab;
}

.cd-end {
  position: absolute;
  left: 50%;
  bottom: 9px;
  min-width: 128px;
  height: 24px;
  padding: 0 10px;
  translate: -50% 0;
  border: 1px solid rgb(170, 132, 54);
  border-radius: 2px;
  background: linear-gradient(rgb(110, 40, 24), rgb(64, 18, 10));
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.6);
  color: rgb(255, 222, 120);
  font: inherit;
  text-shadow: 1px 1px 0 #000;
  cursor: pointer;
}

.cd-end:hover {
  filter: brightness(1.2);
}

.cd-end:active {
  translate: -50% 1px;
}

/* Destroy box (src/destroy-box.js): 6 x 6 bag cells, left of the item window. */
.pt-trash {
  right: calc(18px + 538px * var(--itemwin-scale, 1));
  top: var(--window-top, 116px);
  width: 286px;
  height: 392px;
}

.tr-text {
  position: absolute;
  left: 10px;
  top: 26px;
  right: 10px;
  margin: 0;
  color: rgb(220, 214, 196);
  font-size: 13px;
  line-height: 16px;
}

.tr-text em {
  color: rgb(255, 80, 60);
  font-style: normal;
}

.tr-grid {
  position: absolute;
  left: 11px;
  top: 76px;
  width: 262px;
  height: 262px;
}

.tr-cell {
  left: calc(var(--col) * 44px);
  top: calc(var(--row) * 44px);
  width: 41px;
  height: 41px;
  background: url("assets/ui/items/cell.png") no-repeat;
  cursor: pointer;
}

.tr-buttons .cd-end {
  min-width: 96px;
}

.tr-buttons .cd-end:first-child {
  left: 30%;
}

.tr-buttons .cd-end:last-child {
  left: 70%;
}

/* Item ring (PhongThanPaintUpgradeAura, src/item-window.js hasAura): the client's 20-frame
   strip at 200 ms a frame, centred under the item art in its box / bag cell. */
.iw-aura {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--aura-w);
  height: var(--aura-h);
  translate: -50% -50%;
  background: var(--aura-image) no-repeat 0 0;
  animation: iw-aura 4s steps(20) infinite;
  pointer-events: none;
}

.iw-aura + .iw-item {
  position: relative;
}

@keyframes iw-aura {
  to {
    background-position-x: calc(var(--aura-w) * -20);
  }
}

.aura-shen {
  --aura-w: 66px;
  --aura-h: 98px;
  --aura-image: url("assets/items/all/aura/shen.webp");
}

.aura-tou {
  --aura-w: 68px;
  --aura-h: 68px;
  --aura-image: url("assets/items/all/aura/tou.webp");
}

.aura-yao {
  --aura-w: 66px;
  --aura-h: 45px;
  --aura-image: url("assets/items/all/aura/yao.webp");
}

.aura-fabao {
  --aura-w: 34px;
  --aura-h: 34px;
  --aura-image: url("assets/items/all/aura/fabao.webp");
}

/* Bag cell frame (WndBorder.cpp DrawBorder): two 1px rects in the frame colour and, on the
   outer one, a light half the perimeter long running clockwise, fading bright -> dark
   twice along its length (_DrawBorder). Colours come from the item's name colour
   (src/item-window.js gradeElement). */
@property --grade-spin {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

.iw-grade {
  position: absolute;
  inset: 0;
  border: 2px solid var(--grade-frame);
  pointer-events: none;
}

.iw-grade::after {
  content: "";
  position: absolute;
  inset: -2px;
  padding: 1px;
  background: conic-gradient(from var(--grade-spin), var(--grade-dark) 0%, var(--grade-light) 25%,
    var(--grade-dark) 25%, var(--grade-light) 50%, transparent 50%);
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  animation: iw-grade-spin 6s linear infinite;
}

@keyframes iw-grade-spin {
  to {
    --grade-spin: 360deg;
  }
}

/* ---- Ngự Các (F2, src/ibshop.js, Ui/ui4/ibshopcfg.ini): the 640x503 八宝如意阁 panel. ---- */
.pt-ibshop-win {
  position: absolute;
  left: 50%;
  top: calc(var(--window-top, 116px) / var(--itemwin-scale, 1));
  z-index: 13;
  translate: -50% 0;
  zoom: var(--itemwin-scale, 1);
  color: rgb(240, 240, 158);
  font: 400 14px/15px "PT Font 14", Tahoma, sans-serif;
  text-shadow: none;
}

.pt-ibshop-win[hidden] {
  display: none;
}

/* The panel's inner area is see-through; a dark fill under it keeps the map out. */
.pt-ibshop-win::before {
  content: "";
  position: absolute;
  left: 10px;
  top: 26px;
  right: 10px;
  bottom: 10px;
  background: rgba(14, 14, 14, 0.88);
}

.pt-ibshop-win button {
  position: absolute;
  padding: 0;
  border: 0;
  background: transparent no-repeat 0 0;
  cursor: pointer;
}

.ib-frame,
.ib-pagebg,
.ib-buybox-bg {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;
  user-select: none;
}

/* The panel's title plaque (its "BÁT BẢO CÁC" cleared by export_ibshop.py). */
.ib-title {
  position: absolute;
  left: 220px;
  top: 6px;
  width: 200px;
  height: 18px;
  color: #fff;
  font: 700 13px/18px var(--font-window-title, var(--font-title));
  text-align: center;
  text-transform: uppercase;
  text-shadow: var(--pt-text-border);
  pointer-events: none;
}

.ib-drag {
  position: absolute;
  left: 190px;
  top: 0;
  width: 260px;
  height: 28px;
  cursor: move;
}

/* Sprite frames: 0 normal, 1 pressed, 2 hover (关闭键 / 购买按钮 / 加减 / 确定取消). */
.pt-ibshop-win [data-sprite] {
  background-repeat: no-repeat;
  background-position: 0 0;
}

.ib-btn:hover {
  background-position-x: calc(var(--fw) * -2);
}

.ib-btn:active {
  background-position-x: calc(var(--fw) * -1);
}

/* PageBtn: Up=1 (frame 1) normal, frame 0 the open tab. */
.ib-tab {
  background-position-x: calc(var(--fw) * -1);
}

.ib-tab.on {
  background-position-x: 0;
}

/* The "Tất cả" tab: a text label (0xfff09e) on a plain tab. */
.pt-ibshop-win .ib-tab-text {
  border: 1px solid rgb(150, 118, 48);
  border-radius: 2px;
  background: linear-gradient(rgb(120, 100, 50), rgb(70, 56, 24));
  color: rgb(255, 240, 158);
  font: inherit;
  font-size: 12px;
  line-height: 17px;
}

.pt-ibshop-win .ib-tab-text.on {
  background: linear-gradient(rgb(240, 228, 190), rgb(200, 186, 140));
  color: rgb(60, 40, 10);
}

.ib-coin {
  position: absolute;
  overflow: hidden;
  color: rgb(240, 240, 10);
  font-weight: 400;
  line-height: 18px;
  text-align: right;
  white-space: nowrap;
}

.ib-page,
.ib-limits {
  position: absolute;
}

.ib-limits {
  inset: 0;
  pointer-events: none;
}

.ib-limits .ib-cell {
  pointer-events: auto;
}

.ib-cell {
  position: absolute;
}

.ib-cell > span {
  position: absolute;
  display: block;
  overflow: hidden;
  white-space: nowrap;
}

.ib-obj {
  display: grid !important;
  place-items: center;
  overflow: visible !important;
  cursor: help;
}

.ib-obj img {
  max-width: none;
  image-rendering: pixelated;
}

.ib-name {
  text-align: center;
  text-overflow: ellipsis;
}

.ib-price {
  text-align: center;
  line-height: 15px;
}

.ib-show {
  color: rgb(210, 240, 210);
}

.ib-actual {
  color: rgb(78, 245, 245);
}

/* PriceNotUsedImg (红叉) over a show price above the selling one. */
.ib-cross {
  position: absolute;
  inset: 0;
  background: no-repeat center / 100% 100%;
}

/* Status icons (商业图标): animated frame strips. */
.ib-status {
  position: absolute;
  animation: ib-status 1s steps(var(--frames, 1)) infinite;
  pointer-events: auto;
}

@keyframes ib-status {
  to {
    background-position-x: calc(var(--fw) * var(--frames, 1) * -1);
  }
}

/* Paging buttons: 0 normal, 1 pressed, 2 disabled, 3 hover. */
.ib-pager:hover {
  background-position-x: calc(var(--fw) * -3);
}

.ib-pager:disabled {
  background-position-x: calc(var(--fw) * -2);
  cursor: default;
}

.ib-pageindex {
  position: absolute;
  color: rgb(240, 240, 10);
  font-weight: 400;
  line-height: 18px;
  text-align: center;
}

.ib-empty {
  position: absolute;
  left: 0;
  right: 0;
  top: 140px;
  margin: 0;
  color: rgb(240, 240, 158);
  text-align: center;
}

.ib-search,
.ib-bb-count {
  position: absolute;
  box-sizing: border-box;
  padding: 0 3px;
  border: 0;
  background: transparent;
  color: rgb(255, 246, 108);
  font: inherit;
  outline: 0;
}

.ib-search::placeholder {
  color: rgba(240, 240, 158, 0.45);
}

/* Buy box (买进.spr) over the left of the panel. */
.ib-buybox {
  position: absolute;
  left: 10px;
  top: 100px;
  z-index: 2;
  width: 168px;
  height: 150px;
}

.ib-buybox[hidden] {
  display: none;
}

.ib-bb-info {
  position: absolute;
  overflow: hidden;
  color: rgb(115, 209, 206);
  white-space: nowrap;
  text-overflow: ellipsis;
}

.ib-bb-cost {
  position: absolute;
  color: rgb(240, 240, 10);
  text-align: right;
}

.ib-bb-count {
  text-align: center;
}

/* Buy box currency rows ("chi trả … Thông Bảo" = Xu, "… Linh Bảo" = Xu khóa): the row is
   the choice, the chosen one framed in gold with its cost in the gap. */
.pt-ibshop-win .ib-bb-row {
  left: 16px;
  width: 137px;
  height: 18px;
}

.pt-ibshop-win .ib-bb-row.on {
  box-shadow: inset 0 0 0 1px rgb(240, 200, 80);
}

.ib-bb-row span {
  position: absolute;
  top: 0;
  left: 32px;
  width: 52px;
  color: rgb(240, 240, 10);
  line-height: 18px;
  text-align: center;
}

/* Big map (Tab / "Bản đồ thế giới", src/world-map.js), laid out like tham_khao/ui_minimap.png:
   the map name in green in the middle of the title bar, the coordinates on its right,
   the whole map below, the green hint, the X / Y boxes and buttons along the foot. */
.pt-bigmap {
  position: absolute;
  z-index: 45;
  left: 50%;
  top: 50%;
  width: min(660px, calc(100% - 24px));
  height: min(440px, calc(100% - 24px));
  translate: -50% -50%;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  border: 2px solid rgb(130, 100, 32);
  outline: 1px solid rgba(0, 0, 0, 0.85);
  background: rgb(26, 21, 14);
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.6);
  color: #fff;
  font: 400 14px/14px "PT Font 14", Tahoma, sans-serif;
}

.pt-bigmap[hidden] {
  display: none;
}

.bm-head {
  position: relative;
  flex: 0 0 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 1px solid rgb(130, 100, 32);
  background: linear-gradient(rgb(58, 40, 22), rgb(30, 21, 12));
}

.bm-name {
  color: rgb(0, 255, 0);
  font-weight: 400;
  text-shadow: 1px 1px 0 #000;
}

.bm-pos {
  position: absolute;
  right: 34px;
  color: rgb(0, 255, 0);
  text-shadow: 1px 1px 0 #000;
}

.bm-close {
  position: absolute;
  right: 4px;
  top: 2px;
  width: 22px;
  height: 14px;
  padding: 0;
  border: 0;
  background: transparent url(assets/ui/minimap/btn-close.png) no-repeat 0 0;
  cursor: inherit;
}

.bm-close:hover {
  background-position: -22px 0;
}

.bm-map {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  margin: 4px;
  border: 1px solid rgba(130, 100, 32, 0.8);
}

.bm-map canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: pointer;
}

.bm-map canvas.dragging {
  cursor: grabbing;
}

.bm-foot {
  position: relative;
  flex: 0 0 26px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 6px 2px;
}

.bm-hint {
  flex: 1 1 auto;
  overflow: hidden;
  color: rgb(0, 255, 0);
  white-space: nowrap;
  text-overflow: ellipsis;
}

.bm-coord {
  position: relative;
  flex: 0 0 151px;
  height: 20px;
  margin: 0;
}

.bm-coord > * {
  position: absolute;
}

.bm-coord img {
  left: 0;
  top: 0;
  pointer-events: none;
}

.bm-coord input {
  top: 3px;
  width: 28px;
  height: 15px;
  padding: 0 1px;
  border: 0;
  outline: 0;
  background: transparent;
  color: rgb(218, 255, 165);
  font: 12px/15px Tahoma, Verdana, sans-serif;
}

.bm-coord [data-bm-x] { left: 16px; }
.bm-coord [data-bm-y] { left: 58px; }

.bm-buttons {
  display: flex;
  gap: 3px;
}

.bm-buttons .mm-btn {
  position: relative;
  left: auto;
  top: auto;
}

/* FPS / ping counter (F10): top right, just left of the mini map. */
.fps-meter {
  position: absolute;
  top: 4px;
  right: calc(208px * var(--minimap-scale, 1) + 6px);
  z-index: 40;
  padding: 2px 8px;
  border: 1px solid rgba(214, 180, 96, 0.55);
  border-radius: 3px;
  background: rgba(10, 8, 4, 0.72);
  color: #7dff7d;
  font: 12px/16px Consolas, "Courier New", monospace;
  pointer-events: none;
  white-space: nowrap;
}

.fps-meter[data-level="ok"] {
  color: #ffe466;
}

.fps-meter[data-level="bad"] {
  color: #ff6a5a;
}

/* Preload screen (src/preloader.js): the world map over the whole window, loading bar below. */
.preloader {
  position: fixed;
  inset: 0;
  z-index: 1000;
  overflow: hidden;
  background: #0b0906;
  transition: opacity 420ms ease;
}

.preloader.done {
  opacity: 0;
  pointer-events: none;
}

/* The login screen art (logo.spr) over the whole window, so the sides are not empty; dimmed
   towards the middle so the map stands out. */
.pl-backdrop {
  position: absolute;
  inset: 0;
  background: url("assets/ui/loading/login-bg.webp") center / cover no-repeat #0b0906;
  filter: brightness(0.62) saturate(0.9);
}

.pl-backdrop::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 60% 70% at 50% 50%, rgba(8, 6, 4, 0.82) 0%, rgba(8, 6, 4, 0.55) 55%, rgba(8, 6, 4, 0) 100%),
    linear-gradient(to bottom, rgba(8, 6, 4, 0.35), rgba(8, 6, 4, 0) 25%, rgba(8, 6, 4, 0) 75%, rgba(8, 6, 4, 0.6));
}

/* The map at its own 1024 x 738 (never enlarged, only shrunk on a small window), the bar
   under it, both in the middle of the screen. */
.pl-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 16px;
}

.pl-map {
  display: block;
  width: auto;
  height: auto;
  max-width: calc(100vw - 120px);
  max-height: calc(100vh - 260px);
  min-height: 0;
  object-fit: contain;
  border: 1px solid rgba(214, 170, 92, 0.55);
  box-shadow: 0 0 0 3px rgba(20, 14, 8, 0.85), 0 0 32px rgba(0, 0, 0, 0.85);
  user-select: none;
}

.pl-foot {
  width: min(560px, 100%);
}

/* The map hung as an unrolled scroll: a rolled-paper rod each side, jade knob and wood cap at
   both ends (scroll-knob.svg). The client has no scroll art, so the rods are drawn here. */
.pl-scroll {
  position: relative;
  margin: 52px 0 6px;
}

.pl-rod {
  position: absolute;
  top: -18px;
  bottom: -18px;
  width: 38px;
  /* Aged paper: grime noise, water stains, uneven roll lines over a sepia roll. */
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='96' height='96'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.22 0 0 0 0 0.14 0 0 0 0 0.06 0 0 0 0.55 0'/%3E%3C/filter%3E%3Crect width='96' height='96' filter='url(%23n)'/%3E%3C/svg%3E"),
    radial-gradient(ellipse 18px 40px at 40% 18%, rgba(92, 58, 24, 0.38), rgba(92, 58, 24, 0) 70%),
    radial-gradient(ellipse 14px 60px at 62% 47%, rgba(80, 50, 20, 0.32), rgba(80, 50, 20, 0) 70%),
    radial-gradient(ellipse 20px 34px at 35% 76%, rgba(70, 40, 14, 0.4), rgba(70, 40, 14, 0) 70%),
    radial-gradient(ellipse 10px 22px at 55% 90%, rgba(40, 24, 8, 0.35), rgba(40, 24, 8, 0) 70%),
    repeating-linear-gradient(to bottom, rgba(60, 38, 14, 0) 0 37px, rgba(60, 38, 14, 0.22) 37px 38px, rgba(60, 38, 14, 0) 38px 61px, rgba(60, 38, 14, 0.14) 61px 63px),
    linear-gradient(to right, #2e1f0e, #7a5c34 14%, #b8996a 38%, #cdb489 50%, #a88a5c 66%, #634626 86%, #24180a);
  box-shadow: 0 0 0 1px rgba(26, 16, 6, 0.9), inset 0 0 6px rgba(40, 24, 8, 0.55), 4px 0 10px rgba(0, 0, 0, 0.6), -4px 0 10px rgba(0, 0, 0, 0.6);
  border-radius: 3px;
}

.pl-rod.left {
  left: -30px;
}

.pl-rod.right {
  right: -30px;
}

.pl-rod::before,
.pl-rod::after {
  content: "";
  position: absolute;
  left: -7px;
  width: 52px;
  height: 64px;
  background: url("assets/ui/loading/scroll-knob.svg") no-repeat;
  /* Worn: dull jade, tarnished bronze instead of bright gold. */
  filter: sepia(0.45) saturate(0.7) brightness(0.82) contrast(1.05) drop-shadow(0 2px 3px rgba(0, 0, 0, 0.6));
}

.pl-rod::before {
  top: -60px;
}

.pl-rod::after {
  bottom: -60px;
  transform: scaleY(-1);
}

.pl-text {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin: 0 4px 6px;
  color: #fff6c8;
  font: 12px/15px Tahoma, Verdana, "Segoe UI", sans-serif;
  text-shadow: 1px 1px 0 #000, -1px 1px 0 #000, 1px -1px 0 #000, -1px -1px 0 #000;
}

.pl-text b {
  color: #fffd7a;
  font-variant-numeric: tabular-nums;
}

/* Round-ended bar (tools/export_world_map.py): the VNG gold-rimmed track with round ends
   (barback.spr -> track-round.png, 163 x 15) and the HUD's glossy pill-shaped experience bar
   (经验条.spr -> fill-round.png, 143 x 11) as the fill, both at exactly 2x kept sharp
   (pixelated, on whole pixels: Preloader.snap); only the middle stretches, the round caps
   keep their shape. */
.pl-bar {
  position: relative;
  height: 30px;
  box-sizing: border-box;
  border-style: solid;
  border-width: 0 14px;
  border-image: url("assets/ui/loading/track-round.png") 0 7 fill / 0 14px stretch;
  image-rendering: pixelated;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.7));
}

/* The fill lies in the track's dark inside: 4 px in from each end, 4 px from top / bottom
   (the track rim at 2x). Its width is set as a share of that inside (src/preloader.js). */
.pl-bar i {
  position: absolute;
  top: 4px;
  left: -10px;
  display: block;
  width: 0;
  min-width: 24px;
  max-width: calc(100% + 20px);
  height: 22px;
  box-sizing: border-box;
  border-style: solid;
  border-width: 0 12px;
  border-image: url("assets/ui/loading/fill-round.png") 0 6 fill / 0 12px stretch;
  image-rendering: pixelated;
  /* Aged gold: the HUD's lemon yellow warmed to old bronze-gold. */
  filter: sepia(0.55) saturate(1.25) hue-rotate(-12deg) brightness(0.92) drop-shadow(0 0 4px rgba(230, 170, 70, 0.45));
}

.preloader.failed .pl-text span {
  color: #ff8a6a;
}

/* ---- NPC shop (Sale(n), src/shop.js, \ui\ui3\npc买卖界面.ini): the 282x409 买卖面板. ---- */
.pt-shop-win {
  position: absolute;
  left: 0;
  top: calc(var(--window-top, 116px) / var(--itemwin-scale, 1));
  z-index: 13;
  zoom: var(--itemwin-scale, 1);
  font: 400 14px/15px "PT Font 14", Tahoma, sans-serif;
  text-shadow: none;
  user-select: none;
}

.pt-shop-win[hidden],
.sh-confirm[hidden] {
  display: none;
}

/* The panel's inner area is see-through; a dark fill under it keeps the map out. */
.pt-shop-win::before {
  content: "";
  position: absolute;
  left: 12px;
  top: 28px;
  right: 12px;
  bottom: 12px;
  background: rgba(14, 14, 14, 0.85);
}

.sh-frame {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;
}

.sh-drag {
  position: absolute;
  left: 40px;
  top: 0;
  width: 200px;
  height: 24px;
  cursor: move;
}

.pt-shop-win button {
  position: absolute;
  padding: 0;
  border: 0;
  background: transparent no-repeat 0 0;
  cursor: pointer;
}

/* Frames: 0 normal, 1 pressed, 2 hover (关闭键 / 确定 / 取消 / 加减). */
.sh-btn:hover:not(:disabled) {
  background-position-x: calc(var(--fw) * -2);
}

.sh-btn:active:not(:disabled),
.sh-check:hover:not(:disabled),
.sh-check.on {
  background-position-x: calc(var(--fw) * -1);
}

/* Two-frame buttons (修理键, 上一页 / 下一页) have no hover frame. */
.sh-btn[data-sprite="leftbtn"]:hover:not(:disabled),
.sh-btn[data-sprite="rightbtn"]:hover:not(:disabled),
.sh-btn[data-sprite="repairbtn"]:hover:not(:disabled) {
  background-position-x: 0;
}

/* The repair check button stays pressed while the repair state is on. */
.sh-btn[data-sprite="repairbtn"].on {
  background-position-x: calc(var(--fw) * -1);
}

.sh-btn:disabled {
  cursor: default;
  filter: grayscale(1) brightness(0.6);
}

/* ShopBtn Up=1: frame 1 normal, frame 0 the open tab. */
.sh-tab {
  background-position-x: calc(var(--fw) * -1);
}

.sh-tab.on {
  background-position-x: 0;
}

.sh-card {
  position: absolute;
  cursor: pointer;
}

.sh-card.empty {
  cursor: default;
}

.sh-card:not(.empty):hover {
  outline: 1px solid rgba(255, 246, 108, 0.45);
}

.sh-icon {
  position: absolute;
  display: grid;
  place-items: center;
  overflow: hidden;
}

.sh-icon img {
  max-width: 100%;
  max-height: 100%;
  image-rendering: pixelated;
}

.sh-name,
.sh-price {
  position: absolute;
  height: 15px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: #fff;
  text-shadow: var(--pt-text-border);
}

.sh-price {
  color: rgb(255, 255, 0);
}

.sh-page {
  position: absolute;
  left: 156px;
  top: 362px;
  width: 30px;
  color: rgb(255, 246, 108);
  font-weight: 400;
  text-align: center;
}

/* KUiTradeConfirm (买卖确认.ini Main 30,30, Moveable): above the cards. */
.sh-confirm {
  position: absolute;
  left: 24px;
  top: 130px;
  z-index: 2;
}

.sh-count {
  position: absolute;
  padding: 0;
  border: 0;
  background: transparent;
  font: inherit;
  outline: none;
}

.sh-cost,
.sh-item {
  position: absolute;
  overflow: hidden;
  white-space: nowrap;
  font-weight: 400;
  text-shadow: var(--pt-text-border);
}

.sh-cost {
  text-align: center;
}

/* ---- F5 skill window (src/skill-window.js), in the Hành trang (F4) style and 1.25x the
   client's size: the 状态 frame narrowed to 298 px (frame-skills.png, tools/make_dialog_frame.py)
   stretched to the window's height, the white uppercase title on its plaque, the round gold
   close button; the gold Hệ phái / Chuyển / Ngưng buttons, the Đoản binh / Trường binh tabs
   and the dark gold-edged page with the cells (技能框 box, icon, name, level) of the class
   page ini at 1.25x. PT Font 16 / 18 for crisp text at those sizes. ---- */
.pt-skillwin {
  position: absolute;
  left: 0;
  top: calc(var(--window-top, 116px) / var(--itemwin-scale, 1));
  z-index: 14;
  zoom: var(--itemwin-scale, 1);
  width: 298px;
  height: 462px;
  box-sizing: border-box;
  border: solid transparent;
  border-width: 30px 16px 18px;
  border-image: url("assets/ui/status/frame-skills.png") 30 16 18 fill / 30px 16px 18px stretch;
  color: #fff;
  font: 400 16px/18px "PT Font 16", "PT Font 14", Tahoma, sans-serif;
  text-shadow: 1px 1px 0 #000;
  user-select: none;
}

.pt-skillwin[hidden],
.pt-skilltip[hidden] {
  display: none;
}

/* The gold bar: drag handle, title on the plaque. */
.skw-head {
  position: absolute;
  left: -16px;
  right: 14px;
  top: -30px;
  height: 26px;
  text-align: center;
  cursor: move;
}

.skw-head strong {
  display: inline-block;
  margin-top: 4px;
  color: #fff;
  font: 700 12px/18px var(--font-window-title, var(--font-title));
  text-transform: uppercase;
  text-shadow: var(--pt-text-border);
}

.skw-close {
  position: absolute;
  right: -9px;
  top: -24px;
  z-index: 2;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  background: url("assets/ui/status/close.png") 0 0 no-repeat;
  cursor: pointer;
}

.skw-close:hover {
  background-position: -40px 0;
}

.skw-close:active {
  background-position: -20px 0;
}

/* Hệ phái / Chuyển / Ngưng: gold-edged buttons, light text. */
.skw-pages {
  position: absolute;
  left: 0;
  right: 0;
  top: 6px;
  display: flex;
  justify-content: center;
  gap: 14px;
  padding-bottom: 7px;
  border-bottom: 1px solid rgba(167, 151, 84, 0.6);
}

.skw-pages button {
  min-width: 62px;
  height: 30px;
  padding: 0 6px;
  border: 2px solid rgb(214, 172, 74);
  border-radius: 4px;
  background: linear-gradient(rgb(150, 112, 40), rgb(74, 50, 14) 50%, rgb(40, 26, 6) 51%, rgb(96, 68, 20));
  box-shadow: inset 0 0 0 1px rgba(40, 24, 0, 0.9), 0 0 0 1px rgba(0, 0, 0, 0.8);
  color: rgb(252, 240, 200);
  font: 400 16px/18px "PT Font 16", "PT Font 14", Tahoma, sans-serif;
  text-shadow: 1px 1px 0 #000, -1px 0 #000;
  cursor: pointer;
}

.skw-pages button:hover,
.skw-pages button.on {
  color: #fff;
  border-color: rgb(246, 210, 110);
  background: linear-gradient(rgb(188, 146, 56), rgb(98, 68, 20) 50%, rgb(56, 36, 8) 51%, rgb(126, 90, 28));
}

/* Đoản binh / Trường binh: brown tabs over the page. */
.skw-subs {
  position: absolute;
  left: 8px;
  top: 53px;
  z-index: 2;
  display: flex;
  gap: 3px;
}

.skw-subs[hidden] {
  display: none;
}

.skw-subs button {
  height: 24px;
  padding: 0 7px;
  white-space: nowrap;
  border: 1px solid rgb(167, 151, 84);
  border-bottom: 0;
  border-radius: 4px 4px 0 0;
  background: linear-gradient(rgb(70, 46, 26), rgb(36, 22, 12));
  color: rgb(214, 198, 160);
  font: inherit;
  line-height: 23px;
  text-shadow: 1px 1px 0 #000;
  cursor: pointer;
}

/* Three tabs and more (Dị Nhân's Chuyển page): tighter, so the labels stay on one line. */
.skw-subs button:first-child:nth-last-child(n + 3),
.skw-subs button:first-child:nth-last-child(n + 3) ~ button {
  padding: 0 5px;
}

.skw-subs button.on {
  background: linear-gradient(rgb(150, 82, 46), rgb(90, 44, 22));
  color: rgb(255, 238, 200);
}

/* The page: dark, gold-edged like the F3 / F4 inner panels. */
.skw-body {
  position: absolute;
  left: 4px;
  right: 4px;
  top: 77px;
  bottom: 4px;
  border: 1px solid rgb(167, 151, 84);
  border-radius: 5px;
  background: rgba(7, 9, 7, 0.82);
}

.skw-cell {
  position: absolute;
  cursor: pointer;
}

.skw-box,
.skw-icon {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;
}

.skw-cell.off .skw-icon {
  filter: grayscale(0.15) brightness(0.85);
}

/* Skill names and levels: map.skillFont / skillLevelFont in src/config.js (src/fonts.js sets
   the --font-skill* variables); the fallbacks are the client's PT 18 / PT 16. */
.skw-name {
  position: absolute;
  overflow: hidden;
  white-space: nowrap;
  color: rgb(218, 255, 165);
  font-family: var(--font-skill, "PT Font 18", "PT Font 16", Tahoma, sans-serif);
  font-size: var(--font-skill-size, 18px);
  font-weight: var(--font-skill-weight, 400);
  line-height: var(--font-skill-line, 20px);
  text-shadow: -1px 0 rgb(23, 68, 0), 1px 0 rgb(23, 68, 0), 0 -1px rgb(23, 68, 0), 0 1px rgb(23, 68, 0);
  pointer-events: none;
}

.skw-cell.off .skw-name {
  color: rgb(128, 128, 128);
  text-shadow: 1px 1px 0 #000;
}

.skw-level {
  position: absolute;
  display: grid;
  place-items: center;
  color: rgb(218, 255, 165);
  font-family: var(--font-skill-level, "PT Font 16", "PT Font 14", Tahoma, sans-serif);
  font-size: var(--font-skill-level-size, 16px);
  font-weight: var(--font-skill-level-weight, 400);
  line-height: var(--font-skill-level-line, 18px);
  text-shadow: -1px 0 rgb(23, 68, 0), 1px 0 rgb(23, 68, 0), 0 -1px rgb(23, 68, 0), 0 1px rgb(23, 68, 0);
  pointer-events: none;
}

.skw-empty {
  position: absolute;
  left: 0;
  right: 0;
  top: 150px;
  margin: 0;
  color: rgb(160, 150, 130);
  text-align: center;
}

/* Skill tooltip (KSkill::GetDesc in the mouse-hover box, tham_khao/ui_chi_tietskill_trong f5.png):
   centred lines on a grey see-through box; name yellow (grey before it is learned),
   Thuộc tính cyan, Hạn chế vũ khí green, the next level in the source's 25,141,250 blue. */
/* 1.25x the client's box: PT Font 18 (14 x 1.25), wider, more padding. */
.pt-skilltip {
  position: absolute;
  z-index: 60;
  zoom: var(--itemwin-scale, 1);
  max-width: 375px;
  padding: 12px 18px 15px;
  border: 1px solid rgba(190, 190, 190, 0.6);
  background: rgba(46, 48, 46, 0.86);
  color: #fff;
  font: 400 18px/21px "PT Font 18", "PT Font 16", Tahoma, sans-serif;
  text-align: center;
  text-shadow: 1px 1px 0 #000;
  pointer-events: none;
  white-space: normal;
}

.st-gap {
  height: 19px;
}

.st-name {
  color: rgb(255, 255, 0);
}

.st-name.off {
  color: rgb(128, 128, 128);
}

.st-cyan {
  color: rgb(0, 255, 255);
}

.st-green {
  color: rgb(0, 255, 0);
}

.st-blue {
  color: rgb(25, 141, 250);
}

.st-red {
  color: rgb(255, 0, 0);
}

/* Hand picker with a skill book (KUiSkillTree, tham_khao/ui_danh_sach_skill.png): rows of
   8 icons right-aligned to the hand slot, no frame, 34 px cells with a thin light edge. */
/* Its foot sits on the bar's top edge (the toolbar is 58 px; Ngự Các rises above it) and it
   draws over the bar, so no icon hides under Ngự Các or the bar frame. */
.skill-picker.book {
  z-index: 3;
  left: calc(var(--slot-right, 516px) * var(--hud-scale, 1));
  right: auto;
  bottom: calc(60px * var(--hud-scale, 1));
  width: auto;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  translate: -100% 0;
}

.skill-picker.book .skill-picker-head,
.skill-picker.book .skill-info {
  display: none;
}

.skill-picker.book .skill-grid {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0;
}

.skill-row {
  display: flex;
}

.skill-picker.book .skill-option {
  width: 34px;
  height: 34px;
  border: 1px solid rgba(201, 223, 176, 0.85);
  background: rgba(8, 8, 8, 0.75);
}

.skill-picker.book .skill-option.selected::after {
  inset: 0;
  border: 1px solid rgb(255, 228, 120);
}

.skill-picker.book .skill-key {
  right: 1px;
  bottom: 0;
  padding: 0;
  background: none;
  color: rgb(255, 0, 0);
  /* PT Font 14 at exactly 2x (28 px, no synthetic bold): its pixels land on whole 2x2
     blocks, so the letter stays sharp; a 2 px black outline keeps it readable. */
  font: 400 28px/24px "PT Font 14", Tahoma, sans-serif;
  text-shadow: 2px 0 0 #000, -2px 0 0 #000, 0 2px 0 #000, 0 -2px 0 #000, 2px 2px 0 #000;
}

/* NPC dialog (CardDialog.say) in the F3 / F4 window style: the 状态 frame (frame-wide.png,
   gold scroll bar with the title plaque, gold edges, see-through patterned body) stretched
   to the dialog's height, the white uppercase title on the plaque, the round gold close
   button of those windows, text and options in dark gold-edged boxes like F3's. */
/* frame-dialog.png: frame-wide widened to 420 px (tools/make_dialog_frame.py). Even sizes
   and whole-pixel left / top (CardDialog.place) keep the PT bitmap font sharp. */
.pt-carddlg.npc {
  width: 420px;
  height: 360px;
  translate: none;
  border: solid transparent;
  border-width: 30px 16px 18px;
  border-image: url("assets/ui/status/frame-dialog.png") 30 16 18 fill / 30px 16px 18px stretch;
  border-radius: 0;
  background: none;
  box-shadow: none;
  color: #fff;
}

.pt-carddlg.npc .cd-head {
  left: 50%;
  right: auto;
  top: -26px;
  width: 114px;
  height: 18px;
  translate: -50% 0;
  border: 0;
  background: none;
}

.pt-carddlg.npc .cd-head strong {
  color: #fff;
  font: 700 12px/18px var(--font-window-title, var(--font-title));
  text-transform: uppercase;
  text-shadow: var(--pt-text-border);
}

.pt-carddlg.npc .cd-gem {
  display: none;
}

.pt-carddlg.npc .cd-close {
  right: -9px;
  top: -24px;
  width: 20px;
  height: 20px;
  border: 0;
  border-radius: 0;
  background: url("assets/ui/status/close.png") 0 0 no-repeat;
  box-shadow: none;
}

.pt-carddlg.npc .cd-close::before,
.pt-carddlg.npc .cd-close::after {
  display: none;
}

.pt-carddlg.npc .cd-close:hover {
  filter: none;
  background-position: -40px 0;
}

.pt-carddlg.npc .cd-close:active {
  background-position: -20px 0;
}

.pt-carddlg.npc .cd-text {
  left: 4px;
  right: 4px;
  top: 4px;
  height: 116px;
  padding: 7px 9px;
  border: 1px solid rgb(167, 151, 84);
  border-radius: 5px;
  background: rgba(7, 9, 7, 0.86);
  color: #fff;
}

.pt-carddlg.npc .cd-select {
  left: 4px;
  right: 4px;
  top: 126px;
  bottom: 36px;
  border: 1px solid rgb(167, 151, 84);
  border-radius: 5px;
  background: rgba(7, 9, 7, 0.86);
}

.pt-carddlg.npc .cd-list li {
  color: rgb(255, 217, 78);
}

.pt-carddlg.npc .cd-end {
  bottom: 4px;
  border-color: rgb(167, 151, 84);
  background: linear-gradient(rgb(70, 60, 30), rgb(30, 26, 12));
  color: rgb(255, 217, 78);
}

/* Drag handle: the NPC dialog's gold bar (not the close button), none on the Thẻ Tân Thủ. */
.cd-drag {
  display: none;
}

.pt-carddlg.npc .cd-drag {
  position: absolute;
  display: block;
  left: -16px;
  right: 14px;
  top: -30px;
  height: 26px;
  cursor: move;
  z-index: 1;
}

/* Buff icons under the status frame (KUiPlayerControlBar: 16 px icons of the header buff
   table, 18 px apart, 10 a row from BuffWndLeft 38; under the life / exp frame here, the
   web HUD being laid out differently from 个人状态.spr). Hover for the buff's title. */
.pt-buffs {
  position: absolute;
  left: 38px;
  top: 95px;
  display: grid;
  grid-template-columns: repeat(10, 16px);
  gap: 2px;
  pointer-events: auto;
}

.pt-buffs span {
  position: relative;
  display: block;
  width: 16px;
  height: 16px;
}

.pt-buffs img {
  display: block;
  width: 16px;
  height: 16px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.75);
}

/* Stacks of a layered buff (Phá Đao Thức), on the icon's lower right. */
.pt-buffs b {
  position: absolute;
  right: -3px;
  bottom: -4px;
  color: #ffe070;
  font: 700 10px/1 sans-serif;
  text-shadow: 1px 1px 0 #000, -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000;
  pointer-events: none;
}
