/* ═══ UI สไตล์ Ragnarok Online ═══
   อ้างอิงภาพจริงที่ Stamp ส่งมา (Skill Tree window):
   หน้าต่าง = พื้นสว่าง เส้นขอบบาง 1px สะอาด ไม่มีกรอบหนา ไม่มีมุมโค้งใหญ่
   HUD = ยังเป็นแผงเข้มโปร่ง เพราะทับอยู่บนโลก 3D สีสด
   ไอคอนทั้งหมดเป็น SVG (js/rpg/icons.js) — ห้ามอีโมจิ */

:root {
  /* หน้าต่าง (สว่าง) */
  --w-bg:      #ececec;
  --w-body:    #f4f4f4;
  --w-line:    #6f6f6f;
  --w-line-2:  #a8a8a8;
  --w-cell:    #ffffff;
  --w-ink:     #262626;
  --w-ink-2:   #5a5a5a;
  --w-ink-3:   #8a8a8a;
  --w-head-a:  #fcfcfc;
  --w-head-b:  #d9d9d9;
  --w-accent:  #2f5f96;   /* น้ำเงิน RO — ลิงก์/ค่าที่เลือก */
  --w-red:     #b02a2a;   /* เลขที่ยังไม่เต็ม */
  --w-green:   #2c7a4b;

  /* สีของ HUD ไม่ได้อยู่ตรงนี้แล้ว — ย้ายไปบล็อกธีมท้ายไฟล์ (ค้นหา "C3 · ธีมของ HUD")
     เดิมประกาศไว้ตรงนี้ชุดหนึ่ง แล้วบล็อกท้ายไฟล์ทับอีกชุด = ชุดบนเป็นค่าตาย อ่านโค้ดแล้วหลงว่าใช้อยู่ */

  /* ── ระเบียบขอบล่างของ HUD: แชท | ฮอตบาร์ | ปุ่มเมนู อยู่ใน "กริดแถวเดียว" ──
     ผังใหม่ 31 ก.ค. (คำสั่ง Stamp): ทั้งสามส่วนต้องชิดขอบล่าง ไม่ลอยกลางอากาศ
     และปุ่มเมนูกดแล้วตัวเลือกกางเป็น "กระจุก" อยู่ด้านขวา ไม่ใช่แถวยาวพาดขวางจอ

     ผังเดิมแยกกัน "แนวตั้ง" (เมนูแถวล่างสุด · ฮอตบาร์แถวถัดขึ้นไป) เพราะทั้งสามเป็น
     position:absolute ที่ต่างคนต่างเดา bottom ของตัวเอง — พลาดตัวเลขเมื่อไหร่ก็นอนทับกัน
     แล้วกดไม่ได้ (วัดด้วย elementFromPoint 31 ก.ค.: 561px กดไม่ได้ทั้ง 10 ปุ่ม · 1024px 5 ปุ่ม)
     ผังใหม่แยกกัน "แนวนอน" ด้วย .ro-bottom ที่เป็น grid — ทั้งสามเป็นลูกในกริดเดียว
     คนละ grid-area กัน จึง "ทับกันไม่ได้เชิงโครงสร้าง" ไม่ใช่เพราะเราคำนวณตัวเลขถูก
     ที่แคบก็บีบแทร็ก / ให้ฮอตบาร์ห่อบรรทัด / สลับเป็นสองแถวในกริดเดิม — ไม่มีทางซ้อนกัน
     ทุกที่ที่วางของขอบล่างต้องอ้างตัวแปรพวกนี้ ห้ามเขียน 7px/46px ทับเอง */
  --hud-edge:   7px;    /* ระยะห่างจากขอบจอของแถวล่าง */
  --hud-menu-h: 46px;   /* ความสูงปุ่ม "เมนู" ที่มุมขวาล่าง (ตัวเปิด/ปิด) */
  --hud-menu-w: 46px;   /* ความกว้างปุ่มเดียวกัน */
  --hud-menu-cols: 6;   /* แผงกลางจอเป็นกริดกี่คอลัมน์ — 12 ปุ่ม ÷ 6 = 2 แถว (คำสั่ง Stamp 1 ส.ค. 2026) */
  /* ขนาดปุ่ม "ในแผงกลางจอ" แยกจากปุ่มมุมจอ เพราะคนละหน้าที่กันคนละขนาด
     กว้าง: เพดาน 104px แต่หดตามจอเสมอ — 6 คอลัมน์ต้องไม่ล้นจอแม้ที่ 320px
     82 = ทุกอย่างที่ไม่ใช่ตัวปุ่ม: ช่องไฟ 8×5 + ขอบใน 12×2 + เส้นขอบ 1×2 = 66 แล้วเผื่อขอบจอข้างละ 8
     ตัวเลขชุดนี้ต้องขยับตามถ้าแก้ gap/padding ของ .ro-menu-items — test/rpg-hud.js
     คำนวณกล่องแผงจากค่าจริงทั้งสามแล้วเทียบกับที่วัดจากเบราว์เซอร์ จึงแดงเองถ้าลืม
     สูตรนี้ต้องอ้าง 100vw เสมอ ไม่งั้นแผงล้นจอที่ความกว้างเล็ก (มีข้อตรวจแยกบังคับไว้) */
  --hud-menu-pw: min(104px, calc((100vw - 82px) / 6));
  --hud-menu-ph: 84px;  /* สูงพอให้ไอคอน 28px + ตัวหนังสือ 12px อยู่คนละบรรทัดได้สบาย */
  --hud-gap:    5px;    /* ช่องไฟระหว่างส่วนในแถวล่าง และระหว่างแผงเมนูกับปุ่มเมนู */
  --hud-chat-w: 268px;  /* ความกว้างสูงสุดของเลนแชท (เลนซ้าย) */
  --hud-row-h:  110px;  /* ความสูงจริงของแถวล่าง (เดสก์ท็อป = แถวเดียว: แชท 108 + เศษขอบ) */
  --hud-quest-h: 284px; /* เพดานความสูงแผงเควส — ประกาศไว้เพื่อให้ "ของขวาบนสูงแค่ไหน" เป็นตัวเลขที่อ่านได้
                           (.ro-quest บังคับด้วย max-height จริง ข้อความเควสยาวผิดคาดจึงยืดลงมาชนแถวล่างไม่ได้)
                           200 → 284 (1 ส.ค. 2026): แผงเป็นสองชั้นแล้ว (เส้นทางหลัก + ภารกิจที่รับไว้)
                           คิดจากกรณีแน่นสุดที่เกิดได้จริง วัดบนเกมจริง 1280×800:
                           ชั้นหลัก 125 (ชื่อยาวสองบรรทัด + บรรทัดสอน) + หัวข้อรอง 26 + แถวรองสามใบ 51
                           + บรรทัด "อีก N ใบ" 12 + ปุ่มสมุด 26 + ชิปแต้ม 14 + ขอบแผง/หัวแผง 28 = 282
                           แผงอยู่ที่ top 256 บนจอสูง 800 ⇒ ก้นแผง 540 ยังห่างแถวล่างมาก
                           (test/rpg-hud.js คำนวณการทับจากตัวแปรตัวนี้ — รันยืนยันแล้วไม่ทับใคร) */
  /* ปุ่มสัมผัสมือถือกินขอบล่างไปทั้งแถบ แถวล่างจึงต้องยกขึ้นเหนือมันทั้งแถว
     สองค่านี้ทำให้คำนวณได้จริงว่า "เหนือ" คือเท่าไร แทนที่จะฝังตัวเลขเดา ๆ */
  --hud-touch-b: 74px;      /* bottom ของกลุ่มปุ่มสัมผัสฝั่งขวา (.touchacts) */
  --hud-touch-stack: 200px; /* ความสูงกลุ่มนั้น = ปุ่มใหญ่ 72 + 56 + 56 + ช่องไฟ 8×2 */

  /* ── ก้นแถวล่างอยู่สูงจากขอบจอเท่าไร — "แหล่งเดียว" ของทั้งตำแหน่งแถวและของที่ลอยเหนือแถว ──
     .ro-bottom วางตัวเองจากค่านี้ และ --hud-above ก็คิดต่อจากค่าเดียวกัน
     แถวขยับด้วยเหตุผลใด (ปุ่มสัมผัส / จอบาก) --hud-above จึงขยับตามเองเสมอ
     บั๊ก 31 ก.ค.: แถวถูกยกหนีปุ่มสัมผัส 265/279px แต่ --hud-above ยังเป็นเลขคงที่ 220/264/122
     บทสนทนา NPC (.npc-dlg z-index 12) จึงค้างอยู่ล่างแล้วโดนแถว (z-index 16) นั่งทับจนกดปุ่ม "ลาก่อน" ไม่ได้ */
  --hud-bottom-b: var(--hud-edge);
  --hud-above: calc(var(--hud-bottom-b) + var(--hud-row-h) + var(--hud-gap));

  /* ── เพดานของ "ของที่ลอยเหนือแถวล่าง" ────────────────────────────────────
     --hud-above เป็นแค่ "พื้น" (ยอดแถวล่าง) มันไม่มีเพดาน — จอเตี้ยจึงยกของหลุดขอบบนไปทั้งใบ
     บั๊ก 31 ก.ค. รอบสาม วัดจริง 812x375 โหมดสัมผัส (iPhone แนวนอน):
       --hud-above = 279 (ยกหนีปุ่มสัมผัส) + 252 (แถวสองบรรทัด) + 5 = 536 > ความสูงจอ 375
       กล่องคุย NPC ("ประตูเดียวเข้าระบบเศรษฐกิจ") ไปอยู่ที่ [-281,-161] = นอกจอทั้งใบ กดไม่ได้สักปุ่ม
       (แย่กว่าเดิม: ก่อนหน้านั้นเสียแค่ปุ่ม "ลาก่อน" ที่โดนแถวทับ)
     ทุกตัวที่ยึด --hud-above จึงต้องเขียน bottom เป็น
       min(var(--hud-above), calc(100% - var(--hud-edge) - <ที่ที่กันไว้ให้กล่องนั้น>))
     = ยกได้เท่าที่จอมีที่ให้ ยกไม่ไหวก็ไปแปะขอบบนแทน แต่ไม่หลุดจอ
     CSS อ้าง "ความสูงของตัวเอง" ในสูตร bottom ไม่ได้ ที่กันไว้จึงต้องเป็นตัวเลขประกาศตรงนี้
     (กล่องจริงสูงเกินที่กันไว้ก็ยังไม่ทะลุขอบบน เพราะ .npc-dlg ยึด top ไว้ด้วยแล้วเลื่อนในตัว) */
  --hud-npc-dlg-h: 132px;   /* กล่องคุย NPC — วัดจริง 118px (จอแคบ 113px) เผื่อชื่อ/ข้อความยาวขึ้นบรรทัด */
  --hud-hint-h: 30px;       /* คำใบ้บรรทัดเดียว — วัดจริง 21px */
}
/* ยกแถวหนีปุ่มสัมผัส — ประกาศที่ :root ไม่ใช่ .rpg เพราะ --hud-above ถูกคลี่ค่าตั้งแต่ :root แล้ว
   ทับ --hud-bottom-b ที่ .rpg เมื่อไหร่ ลูกจะได้ --hud-above ที่คลี่ไปแล้วจาก :root = ไม่ตามการยก
   (:root:has(…) จำเพาะกว่า :root เปล่า ๆ จึงชนะทุกเบรกพอยต์โดยไม่ต้องพึ่งลำดับไฟล์) */
:root:has(.touchpad) {
  --hud-bottom-b: calc(var(--hud-touch-b) + var(--hud-touch-stack) + var(--hud-gap));
}
/* ขยายแผงแชทแล้วแถวล่างสูงขึ้นจริง — ต้องประกาศที่ :root ด้วยเหตุผลเดียวกับบล็อกข้างบน
   (--hud-above ถูกคลี่ค่าตั้งแต่ :root แล้ว ทับที่ .rpg ทีหลังของลอยเหนือแถวจะไม่ตามขึ้น)
   ไม่งั้นกล่องคุย NPC / คำใบ้ ที่ยึด --hud-above จะไปนอนทับแชทที่เพิ่งขยาย */
:root:has(.ro-chat.chat-s2) { --hud-row-h: 212px; }

/* ── ไอคอน ── */
.ro-ic { width: 22px; height: 22px; display: block; flex: 0 0 auto; }
.ro-ic.sm { width: 14px; height: 14px; }
.ro-ic.xs { width: 11px; height: 11px; }
.ro-ic.lg { width: 28px; height: 28px; }

/* ═══════════ หน้าต่างสไตล์ RO ═══════════ */
.winbox {
  background: var(--w-bg);
  border: 1px solid var(--w-line);
  border-radius: 3px;
  box-shadow: 0 10px 30px #000a;
  color: var(--w-ink);
  font-size: 13px;
}
.win-h {
  display: flex; align-items: center; gap: 6px;
  padding: 4px 5px 4px 9px;
  background: linear-gradient(var(--w-head-a), var(--w-head-b));
  border-bottom: 1px solid var(--w-line-2);
  cursor: grab;
  user-select: none;
}
.win-h:active { cursor: grabbing; }
.win-h b { font-size: 12.5px; font-weight: 700; color: var(--w-ink); flex: 1; letter-spacing: .01em; }
.win-h .ro-ic { color: var(--w-ink-2); }
.win-btn {
  width: 15px; height: 15px; border-radius: 50%; padding: 0;
  background: radial-gradient(circle at 40% 35%, #fdfdfd, #cfcfcf);
  border: 1px solid #8f8f8f; display: grid; place-items: center; cursor: pointer;
}
.win-btn:hover { background: radial-gradient(circle at 40% 35%, #fff, #e6eef7); border-color: #6d8fb5; }
.win-btn:active { background: #d2d2d2; }
.win-btn .ro-ic { width: 9px; height: 9px; color: #4a4a4a; }
.win-body {
  background: var(--w-body);
  overflow-y: auto; padding: 9px;
  display: flex; flex-direction: column; gap: 8px;
}

/* การ์ดในหน้าต่าง — เรียบ ไม่มีมุมโค้งใหญ่ */
.winbox .card {
  background: var(--w-cell); border: 1px solid var(--w-line-2);
  border-radius: 2px; padding: 9px 10px;
}
.winbox .card .h {
  font-weight: 700; font-size: 12.5px; color: var(--w-ink);
  margin-bottom: 7px; padding-bottom: 5px; border-bottom: 1px solid #e0e0e0;
  display: flex; align-items: center; gap: 6px;
}
.winbox .card.goal { background: #fffbe8; border-color: #d8c78a; }
.winbox .dim { color: var(--w-ink-3); }
.winbox .small { font-size: 11.5px; line-height: 1.5; }
.winbox .big { font-size: 17px; }
.winbox .row { border-top: 1px solid #e6e6e6; padding: 7px 0; gap: 7px; }
.winbox .row:first-of-type { border-top: 0; }
.winbox b, .winbox .gold-t { color: var(--w-ink); }
.winbox .gold-t { color: #9a6f10; }
.winbox .cry-t { color: #1f6d96; }
.winbox .bad-t { color: var(--w-red); }
.winbox .ok-t  { color: var(--w-green); }
.winbox .price { color: #9a6f10; font-weight: 700; }

/* ปุ่มในหน้าต่าง — สไตล์ Win95 เรียบๆ */
.winbox button {
  font: inherit; font-size: 12px; padding: 4px 12px; border-radius: 2px;
  color: #202020; background: linear-gradient(#fbfbfb, #dedede);
  border: 1px solid #8f8f8f; cursor: pointer;
}
.winbox button:hover:not(:disabled) { background: linear-gradient(#fff, #eaf1f8); border-color: #6d8fb5; }
.winbox button:active:not(:disabled) { background: linear-gradient(#d6d6d6, #ececec); }
.winbox button:disabled { opacity: .45; cursor: default; }
.winbox button.ghost { background: #f4f4f4; }
.winbox button.cry-btn { border-color: #6d8fb5; color: #1f6d96; }
.winbox input[type=number] {
  background: #fff; color: var(--w-ink); border: 1px solid #9a9a9a;
  border-radius: 2px; padding: 4px 6px; font-size: 12.5px; width: 68px;
}
.winbox input[type=number]:focus { outline: 2px solid var(--w-accent); outline-offset: -1px; }

/* ตาราง/แถบในหน้าต่าง */
.winbox .tb th, .winbox .tb td { border-bottom: 1px solid #e0e0e0; }
.winbox .tb th { color: var(--w-ink-3); }
.winbox .tb tr.cur td { background: #fff6dc; }
.winbox .bar, .winbox .qbar, .winbox .sfbar { background: #dcdcdc; border: 1px solid #b4b4b4; }
.winbox .derived { border-top: 1px solid #e0e0e0; }
.winbox .derived span { color: var(--w-ink-3); }
.winbox .log { color: var(--w-ink-2); }
.winbox .q { background: #eee; border: 1px solid #d0d0d0; }

/* ── ช่องไอเทม/สกิลแบบ RO: ไทล์ขาว เส้นบาง ไอคอนสีสด ── */
.tile-cell {
  width: 34px; height: 34px; border: 1px solid #9d9d9d; border-radius: 2px;
  background: var(--w-cell); display: grid; place-items: center; position: relative;
}
.tile-cell.empty { background: #fafafa; }
.tile-cell .ro-ic { width: 22px; height: 22px; color: #fff; filter: drop-shadow(0 1px 1px #0006); }
.tile-cell[data-plus]::after {
  content: "+" attr(data-plus); position: absolute; right: 1px; bottom: 0;
  font-size: 9px; font-weight: 700; color: #b02a2a; text-shadow: 0 0 2px #fff;
}
/* สีไทล์ตามเทียร์ (แทนอีโมจิเดิม)
   !! ต้องมีครบทุกเทียร์ที่ items.js มีจริง — เทียร์ 5 (ของบอส 5 ชิ้น) เคยไม่ถูกประกาศ
   ช่องเลยตกไปใช้พื้นขาว var(--w-cell) แล้วไอคอนขาวหายไปกับพื้น มองไม่เห็นเลยว่าถืออะไรอยู่ */
/* ประกาศคู่กับ .islot (ช่องไอเทมกลางตัวใหม่) — สีเทียร์มีที่เดียวในไฟล์ ห้ามก็อปไปไว้ที่อื่น */
.tile-cell.tier1, .islot.tier1 { background: linear-gradient(150deg, #a98a5e, #8a6f48); }
.tile-cell.tier2, .islot.tier2 { background: linear-gradient(150deg, #5c87b8, #3f6a9a); }
.tile-cell.tier3, .islot.tier3 { background: linear-gradient(150deg, #7b5cb8, #5c3f9a); }
.tile-cell.tier4, .islot.tier4 { background: linear-gradient(150deg, #c9922e, #a8741a); }
.tile-cell.tier5, .islot.tier5 { background: linear-gradient(150deg, #d1543f, #96261c); }   /* อสูรกาย — แดงเลือดหมู */
/* เทียร์ 6-14 = ชั้นที่ 2-10 · ไล่โทนตามธีมชั้น (เถ้า → เกลือ → ราก → แร่ → น้ำ → เงา → กรด → แก้วดำ → ทั่ง)
   ต้องประกาศครบทุกเทียร์ที่ TIER_TH มีจริง ไม่งั้นช่องตกไปใช้พื้นขาวแล้วไอคอนหายไปกับพื้น */
.tile-cell.tier6,  .islot.tier6  { background: linear-gradient(150deg, #9a6a4a, #6e4630); }
.tile-cell.tier7,  .islot.tier7  { background: linear-gradient(150deg, #5f9aae, #3d7286); }
.tile-cell.tier8,  .islot.tier8  { background: linear-gradient(150deg, #5f9a5c, #3d7240); }
.tile-cell.tier9,  .islot.tier9  { background: linear-gradient(150deg, #8a7fb0, #5f5688); }
.tile-cell.tier10, .islot.tier10 { background: linear-gradient(150deg, #4f92a8, #2f6a80); }
.tile-cell.tier11, .islot.tier11 { background: linear-gradient(150deg, #8f8a7c, #63604f); }
.tile-cell.tier12, .islot.tier12 { background: linear-gradient(150deg, #94a84e, #6d7a3c); }
.tile-cell.tier13, .islot.tier13 { background: linear-gradient(150deg, #4a4550, #26232e); }
.tile-cell.tier14, .islot.tier14 { background: linear-gradient(150deg, #c98f3a, #8a5a18); }
/* สีความหายากในหน้าต่างพื้นสว่าง — fine/legend = ชื่อเดิมที่ยังค้างในเซฟเก่า */
.rar-common { color: var(--w-ink); }
.rar-uncommon, .rar-fine { color: #2c7a4b; }
.rar-rare   { color: #2f5f96; }
.rar-epic, .rar-legend { color: #9a6f10; font-weight: 700; }
.rar-legendary { color: #b04a10; font-weight: 700; }
.rar-mythic { color: #96218a; font-weight: 800; }
.winbox .warn-t { color: #8a5f0a; }
.winbox .dia-t { color: #96218a; }
.winbox .dur-wrap { background: #dcd6c8; border: 1px solid #b8b0a0; }
.winbox .gac-pill { background: #f0ece0; border: 1px solid #c8c0ae; }
.winbox .gac-cell { background: #f4f1e6; border: 1px solid #c8c0ae; }

/* ═══════════ HUD (เข้มโปร่ง ทับโลก 3D) ═══════════ */
/* ปุ่ม "เมนู" มุมจอ กับปุ่มในแผงกลางจอ ใช้หน้าตาชุดเดียวกัน ต่างกันแค่ขนาด (ดู rpg.css)
   ขนาดปุ่มมุมจอมาจาก --hud-menu-h/w · ขนาดปุ่มในแผงมาจาก --hud-menu-pw/ph — ห้ามปนกัน */
.ro-menu button, .ro-menu-items button {
  background: linear-gradient(#2b3140, #171b25);
  border: 1px solid var(--h-line); border-radius: 3px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
}
.ro-menu button .ro-ic, .ro-menu-items button .ro-ic { color: var(--h-ink2); }
.ro-menu button:hover, .ro-menu-items button:hover { background: var(--h-hover); border-color: var(--h-edge); }
.ro-menu button:hover .ro-ic, .ro-menu-items button:hover .ro-ic { color: var(--h-strong); }
.ro-menu button:active, .ro-menu-items button:active { transform: translateY(1px); }
.ro-menu button span { font-size: 7.5px; color: var(--h-ink2); }

.ro-slot .ic-wrap { display: grid; place-items: center; }
.ro-slot .ro-ic { color: var(--h-ink2); }
.ro-slot.off .ro-ic { color: #6d7686; }
.ro-slot.aim .ro-ic { color: #bff0ff; }

/* ป้ายบอส/มินิบอส — ตัวอักษรแบบ RO ไม่ใช่อีโมจิ */
.tag-boss, .tag-mini {
  font-size: 8.5px; font-weight: 800; letter-spacing: .08em;
  padding: 0 4px; border-radius: 2px; margin-left: 4px; vertical-align: 1px;
}
.tag-boss { background: #7a1f1f; color: #ffd9d0; }
.tag-mini { background: #6a521a; color: #ffe9b5; }

/* จุดสีวัตถุดิบ (แทนอีโมจิ 7 ตัว) */
.mat-dot {
  width: 15px; height: 15px; border-radius: 3px; display: inline-block;
  border: 1px solid #00000040; box-shadow: inset 0 1px 0 #ffffff50;
}
.m-jelly { background: #7cc94a; } .m-fang { background: #e8e0d0; }
.m-hide  { background: #a9784f; } .m-silk { background: #cfd8e6; }
.m-bone  { background: #f2efe4; } .m-ember { background: #ff8a3d; }
.m-core  { background: #8ad8f0; }
.mat-dot.lg { width: 26px; height: 26px; border-radius: 4px; }

/* แถบทรัพยากรใน HUD */
.econ-row { display: flex; flex-wrap: wrap; gap: 3px 10px; font-size: 10.5px; align-items: center; }
.econ-row > span { display: inline-flex; align-items: center; gap: 3px; }
.econ-row .ro-ic { width: 12px; height: 12px; }
.e-gold .ro-ic { color: var(--h-coin); }
.e-cry .ro-ic  { color: var(--ac-info); }
.e-dia .ro-ic  { color: var(--ac-pink); }
.e-stam .ro-ic { color: var(--ac-mint); }
.e-day .ro-ic  { color: var(--h-ink2); }


/* ปุ่มเฉพาะทางในหน้าต่าง — สืบสไตล์ Win95 เดียวกัน (ทับ .winbox button ที่กว้างกว่า) */
.winbox .up, .winbox .hb, .winbox .tab, .winbox .skin {
  background: linear-gradient(#fbfbfb, #dedede); border: 1px solid #8f8f8f;
  color: #202020; border-radius: 2px;
}
.winbox .up { min-width: 40px; padding: 5px 6px; font-size: 14px; font-weight: 700; line-height: 1.1; }
.winbox .up small { display: block; font-size: 9px; font-weight: 400; color: var(--w-ink-3); }
.winbox .up.off { opacity: .35; }
.winbox .hb { min-width: 46px; padding: 3px 6px; font-size: 10px; }
.winbox .hb.on { background: linear-gradient(#dcecff, #b9d4f0); border-color: #4a7fc1; color: #17456f; }
.winbox .tab.on { background: linear-gradient(#dcecff, #b9d4f0); border-color: #4a7fc1; color: #17456f; font-weight: 700; }
.winbox .skin { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; padding: 6px 8px; font-size: 11.5px; }
.winbox .skin.on { background: linear-gradient(#fff3d4, #ffe6a8); border-color: #c9a24a; }
.winbox .skin i { font-style: normal; font-size: 10px; color: var(--w-ink-3); }
.winbox .skin.on i { color: #9a6f10; }

/* ── ตัวเลือกธีมสีในหน้าตัวเลือก ──
   การ์ดละธีม โชว์แถบสีจริงสามช่อง (พื้น · สีเน้น · ตัวอักษร) ให้เห็นก่อนกด
   ไม่ใช่แค่ชื่อธีม เพราะชื่ออย่าง "อะซัวร์" ไม่ได้บอกอะไรถ้าไม่เคยเห็น */
.winbox .themepick { display: grid; grid-template-columns: repeat(auto-fit, minmax(146px, 1fr)); gap: 7px; }
.winbox .themecard {
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  padding: 7px 8px; text-align: left; cursor: pointer;
  background: var(--w-cell); border: 1px solid var(--w-line-2); border-radius: 3px;
  color: var(--w-ink); font: inherit;
}
.winbox .themecard:hover { border-color: var(--w-accent); }
.winbox .themecard.on { border-color: var(--w-accent); background: #eef4fb;
  box-shadow: inset 0 0 0 1px var(--w-accent); }
.winbox .themecard b { font-size: 11.5px; }
.winbox .themecard em { font-style: normal; font-size: 10px; color: var(--w-ink-3); line-height: 1.3; }
.winbox .themesw { display: flex; width: 100%; height: 15px; border-radius: 2px; overflow: hidden;
  border: 1px solid var(--w-line-2); }
.winbox .themesw i { flex: 1; display: block; }
/* ปุ่มกลมบนแถบหัว ต้องชนะกฎปุ่มทั่วไปในหน้าต่าง */
.winbox .win-h .win-btn {
  background: radial-gradient(circle at 40% 35%, #fdfdfd, #cfcfcf);
  border: 1px solid #8f8f8f; border-radius: 50%; padding: 0; width: 15px; height: 15px;
}
.winbox .win-h .win-btn:hover { background: radial-gradient(circle at 40% 35%, #fff, #e6eef7); }

/* การ์ด/แถวอื่นๆ ในหน้าต่างให้เข้าโทนสว่าง */
.winbox .sk { background: var(--w-cell); border: 1px solid var(--w-line-2); }
.winbox .sk.lock { opacity: .5; }
.winbox .sk.has { border-color: #c9a24a; background: #fffdf5; }
.winbox .sk.ult { border-color: #b58a3a; background: #fff8e6; }
.winbox .sk-ic .ro-ic { color: #4a5568; }
.winbox .sk.has .sk-ic .ro-ic, .winbox .sk.ult .sk-ic .ro-ic { color: #9a6f10; }
.winbox .tag { background: #e8e8e8; color: var(--w-ink-2); }
.winbox .tag.passive { background: #e0efe4; color: #2c7a4b; }
.winbox .tag.buff { background: #e2eaf7; color: #2f5f96; }
.winbox .tag.ultt { background: #fdefc9; color: #9a6f10; }
.winbox .bagit, .winbox .slotbox, .winbox .craftrow, .winbox .wm-node, .winbox .acard, .winbox .tile {
  background: var(--w-cell); border: 1px solid var(--w-line-2);
}
.winbox .craftrow { border: 0; border-top: 1px solid #e6e6e6; background: transparent; }
.winbox .craftrow:first-of-type { border-top: 0; }
.winbox .wm-node.here { background: #fff8e6; border-color: #c9a24a; }
.winbox .skillcol-h { border-bottom: 1px solid var(--w-line-2); color: var(--w-ink); }
.winbox .skillcol-h .ro-ic { color: #4a5568; }
.winbox .charbig { background: linear-gradient(160deg, #e9edf2, #d5dbe3); border: 1px solid var(--w-line-2); }
.winbox .charcard { background: var(--w-cell); }
.winbox .qbar i, .winbox .bar i { background: #4a90d9; }
.winbox .sfbar i.good { background: linear-gradient(90deg, #2c7a4b, #56b487); }
.winbox .sfbar i.warn { background: linear-gradient(90deg, #b06a2a, #d99a4a); }
.winbox .sfbar .mark { background: #00000030; }
.winbox .rarrow span { font-size: 11.5px; }
.winbox .killrow { border-top: 1px solid #e0e0e0; color: var(--w-ink-3); }
.winbox .toolshow { align-items: center; }
.winbox .selpanel { border-color: #c9a24a; background: #fffdf5; }

/* คลาสที่ประกอบชื่อจาก template — ประกาศไว้ให้ audit ตรวจเจอ */
.m- {} .tier {}

/* สีสกิลตามอาชีพในฮอตบาร์ */
.job-swordsman .ro-ic { color: #c9d4e6; }
.job-archer    .ro-ic { color: #86d95e; }
.job-acolyte   .ro-ic { color: #ffdf94; }
.job-mage      .ro-ic { color: #7fc7f0; }
.job-thief     .ro-ic { color: #b294f5; }
.job-merchant  .ro-ic { color: #f0954e; }
.job-novice    .ro-ic { color: #cfc6b6; }

/* ═══════════ หน้าสร้างตัวละคร (อ้างอิง Make Your Character ของ RO) ═══════════ */
.cc-screen { position: fixed; inset: 0; display: grid; place-items: center; overflow: auto;
  background: linear-gradient(160deg, #cfe0f2 0%, #eef4fa 45%, #dfe8f2 100%); padding: 18px; }
.cc-win { width: min(94vw, 780px); background: #f4f4f4; border: 1px solid #6f6f6f;
  border-radius: 3px; box-shadow: 0 12px 36px #0004; overflow: hidden; }
.cc-head { display: flex; align-items: baseline; gap: 8px; padding: 5px 10px;
  background: linear-gradient(#fcfcfc, #d9d9d9); border-bottom: 1px solid #a8a8a8; }
.cc-title { font-size: 13px; font-weight: 700; color: #262626; }
.cc-sub { font-size: 10.5px; color: #8a8a8a; letter-spacing: .06em; }
.cc-body { padding: 14px; display: grid; gap: 14px;
  grid-template-columns: 200px 1fr 152px; grid-template-areas:
    "preview hex table" "opts opts opts" "note note note"; align-items: center; }
.cc-preview { grid-area: preview; display: flex; align-items: center; justify-content: center; gap: 4px; }
.cc-arrow { width: 22px; height: 34px; font-size: 11px; color: #3a5f8a; cursor: pointer;
  background: linear-gradient(#fbfbfb, #dedede); border: 1px solid #8f8f8f; border-radius: 2px; }
.cc-arrow:hover { background: linear-gradient(#fff, #eaf1f8); border-color: #6d8fb5; }
.cc-doll { width: 132px; height: 190px; display: grid; place-items: center; position: relative;
  background: linear-gradient(#ffffff, #e8eef5); border: 1px solid #b8c4d0; border-radius: 2px; }
.cc-doll canvas { width: 132px; height: 190px; display: block; position: relative; z-index: 1; }
.cc-doll img { width: 108px; height: 150px; object-fit: contain; object-position: bottom center; }
.cc-doll-base { position: absolute; bottom: 6px; width: 62px; height: 9px; border-radius: 50%;
  background: radial-gradient(#00000022, #00000000 70%); }
.cc-hex { grid-area: hex; display: grid; justify-items: center; gap: 4px; }
.hexchart { --hex-grid: #b9c6d4; display: block; }
.hexchart .hex-fill { fill: #5b8fd0aa; stroke: #2f5f96; stroke-width: 1.6; }
.hexchart .hex-dot { fill: #2f5f96; }
.hexchart .hex-lb { font: 700 10px ui-monospace, Menlo, monospace; fill: #46566b; text-anchor: middle; letter-spacing: .04em; }
.cc-hexnote { font-size: 10.5px; color: #7b8794; text-align: center; }
.hexchart .hex-hit { fill: transparent; cursor: pointer; }
.hexchart .hex-hit:hover { fill: #2f5f9622; }
.cc-statbox { grid-area: table; display: grid; gap: 5px; justify-items: stretch; }
.cc-table { border-collapse: collapse; width: 100%; }
.cc-table th, .cc-table td { border: 1px solid #c4ccd4; padding: 2px 6px; font-size: 11.5px; }
.cc-table th { background: #e4eaf0; color: #46566b; text-align: left; font-family: ui-monospace, Menlo, monospace; }
.cc-table td { background: #fff; text-align: right; font-family: ui-monospace, Menlo, monospace;
  font-variant-numeric: tabular-nums; color: #262626; }
.cc-table td.cc-adj { padding: 1px 3px; white-space: nowrap; }
.cc-mini { width: 19px; height: 19px; line-height: 1; font: inherit; font-size: 12px; color: #26466b;
  background: linear-gradient(#fbfbfb, #dedede); border: 1px solid #8f8f8f; border-radius: 2px;
  cursor: pointer; padding: 0; margin: 0 1px; }
.cc-mini:hover:not(:disabled) { background: linear-gradient(#fff, #eaf1f8); border-color: #6d8fb5; }
.cc-mini:disabled { color: #b0b0b0; cursor: default; opacity: .55; }
.cc-link { font: inherit; font-size: 10.5px; color: #2f5f96; background: none; border: 0;
  padding: 0; cursor: pointer; text-decoration: underline; }
.cc-link:hover { color: #17436f; }
.cc-opts { grid-area: opts; display: grid; gap: 7px; border-top: 1px solid #ddd; padding-top: 10px; }
.cc-row { display: flex; align-items: center; gap: 10px; font-size: 12px; color: #3a3a3a; }
.cc-row > span:first-child { width: 78px; color: #5a5a5a; flex: 0 0 auto; }
.cc-swatch { display: flex; gap: 4px; flex-wrap: wrap; }
.cc-dot { width: 20px; height: 20px; border-radius: 3px; background: var(--c);
  border: 1px solid #8f8f8f; cursor: pointer; padding: 0; }
.cc-dot.on { outline: 2px solid #2f5f96; outline-offset: 1px; }
.cc-segs { display: flex; }
.cc-seg { font: inherit; font-size: 11.5px; padding: 3px 16px; color: #262626; cursor: pointer;
  background: linear-gradient(#fbfbfb, #dedede); border: 1px solid #8f8f8f; }
.cc-seg:first-child { border-radius: 2px 0 0 2px; }
.cc-seg:last-child { border-radius: 0 2px 2px 0; border-left: 0; }
.cc-seg.on { background: linear-gradient(#dceaf8, #b9d3ec); border-color: #4a7fc1; font-weight: 700; color: #17436f; }
.cc-chips { display: flex; gap: 4px; flex-wrap: wrap; }
.cc-chip { font: inherit; font-size: 11px; padding: 3px 9px; color: #3a3a3a; cursor: pointer;
  background: linear-gradient(#fbfbfb, #ededed); border: 1px solid #a8a8a8; border-radius: 2px; }
.cc-chip:hover { background: linear-gradient(#fff, #eaf1f8); border-color: #6d8fb5; }
.cc-chip.on { background: linear-gradient(#dceaf8, #b9d3ec); border-color: #4a7fc1; color: #17436f; font-weight: 700; }
#cc-name { flex: 1; max-width: 240px; font: inherit; font-size: 12.5px; padding: 4px 8px;
  border: 1px solid #9a9a9a; border-radius: 2px; background: #fff; color: #262626; }
#cc-name:focus { outline: 2px solid #2f5f96; outline-offset: -1px; }
.cc-note { grid-area: note; font-size: 11.5px; color: #4a4a4a; background: #fffbe8;
  border: 1px solid #d8c78a; border-radius: 2px; padding: 7px 9px; }
.cc-note .dim { display: block; color: #8a8a8a; margin-top: 2px; }
.cc-foot { display: flex; justify-content: flex-end; gap: 6px; padding: 8px 12px;
  background: linear-gradient(#f0f0f0, #e2e2e2); border-top: 1px solid #b4b4b4; }
.w95 { font: inherit; font-size: 11.5px; padding: 4px 16px; color: #202020;
  background: linear-gradient(#fbfbfb, #dedede); border: 1px solid #8f8f8f; border-radius: 2px; cursor: pointer; }
.w95:hover { background: linear-gradient(#fff, #eaf1f8); border-color: #6d8fb5; }
.w95.primary { font-weight: 700; border-color: #4a7fc1; }

/* จอแคบ — ต้องอยู่ "ท้ายสุด" ของบล็อกนี้ media query ไม่เพิ่ม specificity
   ถ้าวางก่อนกฎฐาน (.cc-doll ฯลฯ) กฎที่มาทีหลังจะชนะ แล้ว override มือถือกลายเป็นโค้ดตาย */
@media (max-width: 640px) {
  /* minmax(0,1fr) = ยอมให้คอลัมน์หดเล็กกว่าเนื้อหา ไม่งั้นกราฟ 200px ดันจนปุ่มสเตตัสหลุดกรอบ */
  .cc-body { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas: "preview hex" "table table" "opts opts" "note note"; }
  .cc-preview, .cc-hex, .cc-statbox, .cc-opts, .cc-row { min-width: 0; }
  .cc-preview { gap: 2px; }
  .cc-doll, .cc-doll canvas { width: 108px; height: 156px; }
  .hexchart { width: 100%; height: auto; }
  .cc-row { flex-wrap: wrap; }
}

/* ═══════════ หน้าต่างสวมใส่ + สเตตัส (อ้างอิงหน้าต่าง Equip ของ RO) ═══════════ */
.eq-card { padding: 10px !important; }
.eq-grid { display: grid; grid-template-columns: 1fr auto 1fr; gap: 10px; align-items: start; }
.eq-grid.cos { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 560px) { .eq-grid { grid-template-columns: 1fr 1fr; } .eq-doll { grid-column: 1 / -1; order: -1; } }
/* ช่องสวมใส่: รูปอยู่บน ชื่อเป็นคำบรรยายอยู่ล่าง — วางชื่อ "ข้าง" รูปเมื่อไหร่
   สองคอลัมน์ที่ขนาบตุ๊กตาจะอ่านเป็นลิสต์ตัวหนังสือสองลิสต์ทันที ไม่ใช่ช่องสวมใส่แบบ RO
   (ผลตรวจ 31 ก.ค.) · ค่าสถานะย้ายไปอยู่ในกล่องรายละเอียดที่ชี้แล้วขึ้นแทน */
.eq-col { display: grid; gap: 8px; justify-items: center; align-content: start; }
.eq-slot { display: flex; flex-direction: column; gap: 3px; align-items: center; padding: 4px 2px;
  width: 100%; max-width: 92px; border: 1px solid transparent; border-radius: 2px; }
.eq-slot.filled { cursor: pointer; }
.eq-slot.filled:hover { background: #eef3f9; border-color: #b9cde0; }
/* ช่องว่างในหน้าต่างสวมใส่ใช้ .islot.empty ของชุดกลางแล้ว — กฎ .tile-cell.empty เดิมตายไปพร้อมกัน */
.eq-cell { flex: 0 0 auto; }
.eq-lb { min-width: 0; width: 100%; display: grid; gap: 2px; justify-items: center;
  text-align: center; font-size: 10.5px; line-height: 1.3; }
.eq-lb b { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.eq-lb .dur-wrap { width: 100%; }
.eq-doll { width: 116px; display: grid; justify-items: center; gap: 2px; padding: 8px 6px;
  background: linear-gradient(#ffffff, #e9eef4); border: 1px solid #b8c4d0; border-radius: 2px; }
.eq-doll img { width: 78px; height: 104px; object-fit: contain; object-position: bottom center; }
.eq-doll-name { font-size: 12px; font-weight: 700; color: var(--w-ink); }
.eq-doll-job { font-size: 10.5px; color: var(--w-ink-3); }
.eq-warn { font-size: 10px; color: #fff; background: #b02a2a; border-radius: 2px; padding: 1px 6px; margin-top: 2px; }

.st-grid { display: grid; grid-template-columns: 1fr 1.15fr; gap: 12px; }
@media (max-width: 520px) { .st-grid { grid-template-columns: 1fr; } }
.st-left { display: grid; gap: 3px; }
.st-row { display: grid; grid-template-columns: 42px 1fr auto; align-items: center; gap: 6px;
  padding: 2px 0; border-bottom: 1px solid #eee; }
.st-name { font-family: var(--f-data, ui-monospace), Menlo, monospace; font-size: 11px;
  font-weight: 700; color: #46566b; letter-spacing: .04em; }
.st-val { font-family: ui-monospace, Menlo, monospace; font-variant-numeric: tabular-nums;
  font-size: 13px; color: var(--w-ink); }
.st-val i { font-style: normal; color: #2c7a4b; font-size: 11px; margin-left: 2px; }
.st-up { min-width: 34px; padding: 2px 6px !important; font-size: 12px !important; font-weight: 700; line-height: 1.1; }
.st-up small { display: block; font-size: 8.5px; font-weight: 400; color: #8a8a8a; }
.st-up.off { opacity: .3; pointer-events: none; }
/* ── บรรทัด "อีกกี่แต้มถึงก้อนโบนัสถัดไป" ──────────────────────────────────
   ต้องเป็น "แถวที่ 2 ของกริดเดิม" ไม่ใช่คอลัมน์ที่ 4 — คอลัมน์ที่ 4 เป็น auto มันจะกว้าง
   ตามความยาวข้อความ แล้วปุ่ม + ของแต่ละแถวกว้างไม่เท่ากันทันที
   เขียน grid-row: 2 ตรง ๆ ไม่พึ่ง auto-placement → แถวที่ไม่มีบรรทัดนี้ (ธนู/ตัน/เต็ม 99)
   สูงเท่าเดิมเป๊ะ ไม่เหลือที่ว่างค้าง · เยื้องเริ่มที่คอลัมน์ 2 = อ่านเป็นคำอธิบายของตัวเลข
   ปล่อยให้ตกบรรทัดได้ ไม่ ellipsis — บนจอ 320px ยาวสองบรรทัดยังดีกว่าถูกตัดหาย */
.st-next { grid-column: 2 / -1; grid-row: 2; display: flex; align-items: center; gap: 5px;
  min-width: 0; font-size: 10px; line-height: 1.4; color: var(--w-ink-3);
  font-variant-numeric: tabular-nums; }
/* เหลือ ≤2 แต้ม = จังหวะที่ควรสะดุดตา — ทองของหน้าต่าง (#9a6f10 ตัวเดียวกับ .winbox .gold-t) */
.st-next.near { color: #9a6f10; font-weight: 700; }
/* รางเดียวกับหลอดความทนทานที่อยู่ในหน้าเดียวกันอยู่แล้ว (.winbox .dur-wrap) */
.st-bar { flex: 0 0 26px; height: 3px; border-radius: 2px;
  background: #dcd6c8; border: 1px solid #b8b0a0; overflow: hidden; }
.st-bar i { display: block; height: 100%; background: var(--w-accent); }
.st-next.near .st-bar i { background: #9a6f10; }
.st-right { display: grid; gap: 3px; align-content: start; }
.dv-row { display: grid; grid-template-columns: 1fr auto 1fr auto; gap: 6px; align-items: baseline;
  padding: 3px 0; border-bottom: 1px solid #eee; font-size: 11.5px; }
.dv-row span { color: var(--w-ink-3); font-family: ui-monospace, Menlo, monospace; font-size: 10.5px; }
.dv-row b { font-family: ui-monospace, Menlo, monospace; font-variant-numeric: tabular-nums;
  font-size: 12.5px; color: var(--w-ink); text-align: right; }

/* ═══════════ เคอร์เซอร์ตามสิ่งที่ชี้ ═══════════
   ปกติ = ลูกศรเมาส์ · ชี้มอน = ดาบ · ชี้ NPC = บอลลูนคุย · ชี้ซุ้มวาร์ป = ประตู */
#rpg-canvas { cursor: default; }
.rpg.aiming #rpg-canvas { cursor: crosshair; }

/* แผนที่ขยายเมื่อคลิกมินิแมป */
.ro-map #minimap { cursor: zoom-in; transition: width .18s, height .18s; }
.ro-map.big { z-index: 30; }
.ro-map.big #minimap { width: 420px; height: 420px; cursor: zoom-out; }
@media (max-width: 560px) { .ro-map.big #minimap { width: min(78vw, 320px); height: min(78vw, 320px); } }

/* แถบ Job EXP — แยกสีจาก Base EXP ให้อ่านออกทันที */
#rpg-mount .ro-bar.jxp i { background: linear-gradient(180deg,#8fd4ff,#3d8fd6); }
#rpg-mount .ro-lv b.jlv { color:#5aa9e6; font-size:11px; }

/* ═══ แผนที่โลกแบบกริด (RO) ═══ */
#win .wm-grid { display:grid; gap:6px; margin:8px 0; }
#win .wm-cell { display:flex; flex-direction:column; gap:4px; }
#win .wm-cell.empty { min-height:8px; }
#win .wm-tile { position:relative; background:#f6f4ef; border:1px solid #8a8a8a; border-radius:2px;
  padding:9px 7px 8px; text-align:center; min-height:52px; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:2px; }
#win .wm-tile.city { background:#fdf6e0; border-color:#b08a3c; box-shadow:inset 0 0 0 1px #f0e2b8; }
#win .wm-tile.here, #win .wm-dun.here { outline:2px solid #d24a3a; outline-offset:-1px; }
#win .wm-tile b, #win .wm-dun b { font-size:11px; line-height:1.25; color:#2a2a2a; }
#win .wm-lv { display:block; font-size:9px; color:#6a6a6a; letter-spacing:.02em; }
#win .wm-you, #win .wm-home { position:absolute; top:2px; }
#win .wm-you { right:3px; } #win .wm-home { left:3px; }
/* ขีดบอกทิศที่มีวาร์ป — ยื่นออกไปชนแมปข้างๆ */
#win .wm-w { position:absolute; background:#5a8fc4; }
#win .wm-w.n, #win .wm-w.s { left:50%; width:3px; height:7px; margin-left:-1.5px; }
#win .wm-w.w, #win .wm-w.e { top:50%; height:3px; width:7px; margin-top:-1.5px; }
#win .wm-w.n { top:-7px; } #win .wm-w.s { bottom:-7px; }
#win .wm-w.w { left:-7px; } #win .wm-w.e { right:-7px; }
#win .wm-dun { position:relative; background:#efe8f6; border:1px dashed #8a6fb0; border-radius:2px;
  padding:5px 6px; text-align:center; }
#win .wm-down { display:block; font-size:9px; color:#7a5fa0; }
#win .wm-legend { display:flex; flex-wrap:wrap; gap:10px; font-size:10px; color:#5a5a5a; margin-top:6px; }
#win .wm-legend .lg { display:inline-block; width:10px; height:10px; vertical-align:-1px; margin-right:3px;
  border:1px solid #8a8a8a; border-radius:2px; }
#win .lg.city { background:#fdf6e0; border-color:#b08a3c; }
#win .lg.field { background:#f6f4ef; }
#win .lg.dun { background:#efe8f6; border:1px dashed #8a6fb0; }
#win .lg.warp { background:#5a8fc4; border-color:#5a8fc4; }
#win .wm-exits { display:flex; flex-direction:column; gap:3px; margin:6px 0; }
#win .wm-exit { display:flex; align-items:baseline; gap:6px; padding:3px 5px; background:#f2f0eb;
  border:1px solid #cfcac0; border-radius:2px; font-size:11px; }
#win .wm-dir { min-width:70px; font-size:10px; font-weight:700; color:#fff; background:#7a8a9a;
  border-radius:2px; padding:1px 5px; text-align:center; }
#win .wm-dir.n { background:#4a7ab0; } #win .wm-dir.s { background:#b0764a; }
#win .wm-dir.w { background:#6a9a5a; } #win .wm-dir.e { background:#a0679a; }
#win .wm-dir.down { background:#7a5fa0; } #win .wm-dir.up { background:#4a9a8a; }

/* ═══ อาร์ตเวิร์กที่เจนด้วย Gemini (assets/art/) ═══
   กฎ: ไม่มีไฟล์รูป → art.js ลบ .artbox ทิ้ง หน้าตาเดิมกลับมาเป๊ะ

   !! บล็อกนี้เคย "ประกาศซ้ำสองรอบ" ในไฟล์เดียว (ราวบรรทัด 444 กับ 477 ของเวอร์ชันก่อน)
   ชุดล่างทับชุดบนเงียบๆ ทำให้แก้ชุดบนแล้วในเกมไม่เปลี่ยน หาสาเหตุไม่เจอ
   รวมเหลือชุดเดียวแล้ว โดยเก็บ "ค่าที่ชนะของเดิม" ไว้ทุกตัว หน้าตาจึงไม่ขยับสักพิกเซล:
     · border ใช้เลขตรง #b8b2a6 (ชุดล่างชนะ var(--w-line) ของชุดบน)
     · .job-art.sm ที่ float:right ของชุดบนตายอยู่แล้ว เพราะชุดล่างสั่ง position:absolute ทับ */
#win .artbox { margin: 8px 0; border: 1px solid #b8b2a6; border-radius: 3px;
  overflow: hidden; background: #e4e0d6; line-height: 0; }
#win .artbox .art { width: 100%; height: auto; display: block; }
#win .artbox.map-art { aspect-ratio: 16/9; }
#win .artbox.map-art .art { height: 100%; object-fit: cover; }
#win .artbox.job-art { aspect-ratio: 3/4; max-width: 260px; margin-inline: auto; }
#win .artbox.job-art .art { height: 100%; object-fit: cover; }
/* การ์ดอาชีพ: รูปลอยชิดขวา เนื้อหาไหลปกติในความกว้างที่เหลือ
   (ไม่ใช้ float — ไม่ดันการ์ดให้สูงตาม · ไม่ใช้ grid-row 1/-1 — ไม่มี explicit row เลยยุบเหลือแถวเดียว) */
#win .jobcard { position: relative; overflow: hidden; padding-right: 126px; min-height: 159px; }
#win .jobcard > .artbox.job-art.sm { position: absolute; top: 10px; right: 10px;
  width: 104px; height: 139px; max-width: none; aspect-ratio: auto; margin: 0; }
/* ช่องแผนที่โลกที่มีภาพประจำแมปเป็นพื้น (ui.js ใส่ทั้ง .wm-tile และ .wm-tile-art คู่กันเสมอ) */
#win .wm-tile, #win .wm-tile-art, #win .wm-dun { background-size: cover; background-position: center; }
/* หน้าจอเริ่มเกม — คีย์อาร์ตเต็มจอ */
.start-screen.has-art { background-size: cover; background-position: center;
  background-repeat: no-repeat; }
.start-screen.has-art .start-box { background: rgba(12,14,20,.62); backdrop-filter: blur(3px);
  padding: 30px 42px; border-radius: 8px; border: 1px solid rgba(255,230,163,.28);
  box-shadow: 0 18px 50px rgba(0,0,0,.5); }

/* แถบเป้าหมาย — รูปมอน + ธาตุ (เคยประกาศซ้ำสองรอบเหมือนกัน · รวมแล้ว) */
#rpg-mount #target-bar.on { display: flex; align-items: center; gap: 9px; }
#rpg-mount #target-bar .tface { width: 46px; height: 46px; border-radius: 3px; object-fit: cover;
  border: 1px solid #6f6f6f; background: #2a2a2a; flex: 0 0 auto; }
#rpg-mount #target-bar .tinfo { flex: 1 1 auto; min-width: 0; }
#rpg-mount .tel { font-size: 10px; padding: 1px 6px; border-radius: 8px; margin-left: 5px;
  color: #fff; vertical-align: 1px; }
#rpg-mount .el-neutral { background: #8a8378; } #rpg-mount .el-fire { background: #d2542e; }
#rpg-mount .el-water { background: #3f8fc4; }   #rpg-mount .el-earth { background: #7a9a48; }
#rpg-mount .el-wind { background: #4faa9a; }    #rpg-mount .el-poison { background: #8a5aa8; }
#rpg-mount .el-undead { background: #6a6a7a; }

/* หน้าจอโหลดตอนข้ามแมป */
#rpg-mount #maploader { position: absolute; inset: 0; z-index: 60; opacity: 0; pointer-events: none;
  transition: opacity .28s ease; background: #0d0f14; overflow: hidden; }
#rpg-mount #maploader.on { opacity: 1; }
#rpg-mount #maploader img { width: 100%; height: 100%; object-fit: cover; }
#rpg-mount #maploader .ml-txt { position: absolute; left: 0; right: 0; bottom: 0; padding: 26px 30px 24px;
  background: linear-gradient(transparent, rgba(8,10,14,.9)); color: #fff; text-align: center; }
#rpg-mount #maploader .ml-txt b { display: block; font-size: 26px; letter-spacing: 1px;
  text-shadow: 0 2px 10px #000a; }
#rpg-mount #maploader .ml-txt span { display: block; font-size: 13px; color: var(--h-gold); margin-top: 3px; }
#rpg-mount #maploader .ml-txt i { display: block; font-size: 12px; color: #c8d0dc; margin-top: 5px;
  font-style: normal; opacity: .85; }

/* ── เพื่อนร่วมแมป (MMO ghost presence) ── */
#chat-in { width: 100%; margin-top: 3px; padding: 3px 7px; border-radius: 3px; box-sizing: border-box;
  border: 1px solid var(--h-line); background: var(--h-deep); color: var(--h-ink);
  font: inherit; font-size: 11px; }
#chat-in::placeholder { color: var(--h-ink3); }
#chat-in:focus { outline: none; border-color: var(--h-edge); }
.ntag.peer { color: #9fe0ff; }               /* ป้ายชื่อผู้เล่นอื่น — ฟ้าอ่อน แยกจาก NPC/ซุ้มวาร์ป */
.c-talk { color: var(--h-gold); }                  /* บรรทัดแชทของผู้เล่น */

/* คู่มือ — รูปมอนทับไอคอน (รูปโหลดไม่ขึ้น → เห็นไอคอนเดิม) */
#win .tile-cell.mobface { position: relative; width: 52px; height: 52px; padding: 0;
  overflow: hidden; border-radius: 4px; }
#win .tile-cell.mobface img { position: absolute; inset: 0; z-index: 2; width: 100%; height: 100%;
  object-fit: cover; display: block; }
#win .tile-cell.mobface svg { position: relative; z-index: 1; }

/* ═══════════════════════════════════════════════════════════════════
   POLISH PASS — ทำให้ HUD ดู "เกมสำเร็จรูป" ไม่ใช่ WebGL demo
   บล็อกนี้ต้องอยู่ท้ายไฟล์เสมอ: rpg.css ฮาร์ดโค้ดสีน้ำเงินเข้มไว้ทั้งไฟล์
   ทับได้ด้วยลำดับโหลดอย่างเดียว (specificity เท่ากัน) — แทรกกลางแล้วแพ้
   ═══════════════════════════════════════════════════════════════════ */

/* ── C3 · ธีมของ HUD ────────────────────────────────────────────────
   Stamp แจ้ง 1 ส.ค. 2026: "ธีมแท็บต่าง ๆ เป็นสีน้ำตาล ให้ออกโทนขาว ๆ ฟ้า ๆ · ทำมาให้เลือกดูก็ได้"
   → เลิกฝังพาเลตเดียวตายตัว เปลี่ยนเป็น "ชุดตัวแปร" แล้วสลับด้วย data-theme บน <html>

   กติกาของไฟล์นี้: ทุกสีของ "โครงแผง HUD" (พื้น/ขอบ/ตัวอักษร/แท็บ/ปุ่ม) ต้องมาจากตัวแปรข้างล่าง
   สีที่ "มีความหมายในตัวเอง" ห้ามผูกกับธีม — เลือดต้องแดง · SP ต้องฟ้า · ธาตุไฟต้องส้ม
   ระดับของ ไอคอนอาชีพ ตัวเลขดาเมจ ก็เช่นกัน ไม่งั้นเปลี่ยนธีมแล้วอ่านเกมไม่ออก

   :root = ธีมตั้งต้น (frost · ขาว-ฟ้า ตามที่สั่ง) · :root[data-theme=…] จำเพาะกว่าจึงทับได้เสมอ
   ธีมที่มี: frost (ขาว-ฟ้าสว่าง) · azure (ฟ้าเข้ม) · amber (น้ำตาลทองของเดิม) · slate (เทากลาง) */
:root {
  /* ── frost · ขาว-ฟ้า (ตั้งต้น) ── แผงสว่างตัวอักษรเข้ม อ่านง่ายบนฉากกลางวัน */
  --h-bg:    #eef4fbf2;   /* พื้นแผง — ทึบพอให้ตัวอักษรอ่านออกบนฉากสว่าง */
  --h-bg-2:  #fffffff2;
  --h-line:  #7ea6cd;     /* ขอบต้องหนักพอจะตัดกับฉากกลางวันสว่าง ๆ ไม่งั้นแผงขาวละลายหายไปกับพื้นทราย */
  --h-edge:  #2f7fd0;     /* ขอบเน้น (เป้าหมาย/ปุ่มที่เลือก) */
  --h-ink:   #17293d;
  --h-ink2:  #4a6480;
  --h-ink3:  #667f9e;     /* จาง — ป้ายปุ่มลัด/ตัวหนังสือรอง */
  --h-gold:  #1466b8;     /* ค่าที่ต้องเด้ง (เลเวล/อาชีพ) — ในธีมสว่างต้องเป็นสีเข้ม ไม่ใช่ทอง */
  --h-strong:#0b1826;     /* ตัวอักษรเน้นสุด (ชื่อตัวละคร) */
  --h-body:  #2b3d52;     /* เนื้อความในแชท */
  --h-deep:  #cfdeee;     /* รางแถบ/ช่องพิมพ์/พื้นคำใบ้ — "ลึกที่สุด" ของธีม */
  --h-chip:  #dce8f5;     /* แท็บ/ชิปที่ไม่ได้เลือก */
  --h-chip-on: #2f7fd0;   /* แท็บที่เลือกอยู่ */
  --h-chip-on-ink: #ffffff;
  --h-hover: #dbebfc;     /* ปุ่มตอนเอาเมาส์ชี้ */
  --h-glow:  #2f7fd045;   /* เรืองรอบของที่ถูกเลือก */
  --h-inset: inset 0 1px 0 #ffffffcc, inset 0 0 0 1px #0a1c3026;
  --h-drop:  0 3px 12px #0e1e3352, 0 0 0 1px #0e1e331f;
  /* สีที่ "มีความหมาย" แต่ยังต้องอ่านออก — ธีมสว่างใช้เฉดเข้ม ธีมมืดใช้เฉดสด
     (Stamp 1 ส.ค.: "ตัวหนังสือบางตัวกลืนกับขาว · ใน RO ตัวหนังสือ/ไอคอนเป็นสีดำเพราะตัดกับขาว")
     ความหมายยังคงเดิมทุกธีม — เขียว=ได้ของ · ฟ้า=สกิล/คริสตัล · แดง=ตาย · เหลือง=เลเวล */
  --ac-good: #1f6d16;    /* เขียว — ได้ของ/EXP/ออนไลน์ */
  --ac-mint: #0b6b57;    /* เขียวมิ้นต์ — ข้อความระบบ/สแตมินา/ฮีล */
  --ac-info: #14599f;    /* ฟ้า — สกิล/อาชีพ/คริสตัล/บัฟ */
  --ac-warn: #8a5300;    /* เหลือง — เลเวล/แต้มที่รอลง */
  --ac-bad:  #a52222;    /* แดง — ตาย/ผิดพลาด */
  --ac-pink: #a3277a;    /* ชมพู — เพชร */
  --h-coin:  #8a5c00;     /* ตัวเลขเงิน/ทอง — ธีมสว่างต้องเข้ม ไม่งั้นเลขทองบนแผงขาวหายไปเลย */
  --h-track: #34506e;     /* รางแถบ HP/SP/EXP — เข้มทุกธีม เพราะตัวเลขบนแถบเป็นสีขาวเสมอ */
  --h-tsh:   none;        /* พื้นสว่าง = ไม่ต้องมีเงาตัวอักษร ใส่แล้วดูเลอะ */

  /* แถบสามเส้นหลัก — ต้องแยกออกจากกันได้ด้วยสีล้วน ไม่ต้องอ่านตัวหนังสือ (ไม่ผูกกับธีม) */
  --bar-hp-a: #ff6f5e; --bar-hp-b: #a81c1c;
  --bar-sp-a: #7ac6ff; --bar-sp-b: #1f56b8;
  --bar-xp-a: #ffe485; --bar-xp-b: #c08a12;
  --bar-jx-a: #9ee0ff; --bar-jx-b: #2f7fc4;
}

/* ── azure · ฟ้าเข้ม — สำหรับคนที่ชอบแผงเข้มแต่ไม่เอาสีน้ำตาล ── */
:root[data-theme="azure"] {
  --h-bg:    #0f1c2ceb;  --h-bg-2:  #1b2d45eb;
  --h-line:  #47658d;    --h-edge:  #63b4ff;
  --h-ink:   #e9f2ff;    --h-ink2:  #a9c3df;   --h-ink3: #7b93ad;
  --h-gold:  #8fd0ff;    --h-strong:#ffffff;   --h-body: #cfe0f2;   --h-coin: #ffcf6b;
  --ac-good: #9ee86a; --ac-mint: #7fd1b9; --ac-info: #9cc7f0;
  --ac-warn: #ffdb6e; --ac-bad:  #e87f7f; --ac-pink: #ff9ad5;
  --h-deep:  #07111c;    --h-track: #07111c;   --h-chip:  #16273ae0; --h-chip-on: #2c5686e8;
  --h-chip-on-ink: #eaf5ff;
  --h-hover: #233a58;    --h-glow:  #63b4ff55;
  --h-inset: inset 0 1px 0 #ffffff22, inset 0 0 0 1px #00000055;
  --h-drop:  0 4px 14px #000000a0;
  --h-tsh:   0 1px 2px #000000cc;
}

/* ── amber · น้ำตาลทอง (พาเลตเดิมก่อน 1 ส.ค. เก็บไว้ให้เลือกกลับได้) ──
   เหตุผลเดิมที่เลือกโทนนี้: HUD น้ำเงินอมเทา (#10131a) ชนกับท้องฟ้า/น้ำในฉาก 3D จนแผงจม */
:root[data-theme="amber"] {
  --h-bg:    #241c12ec;  --h-bg-2:  #34291aec;
  --h-line:  #8a7346;    --h-edge:  #c9a24a;
  --h-ink:   #f4ead6;    --h-ink2:  #cbb891;   --h-ink3: #a2947a;
  --h-gold:  #ffd77a;    --h-strong:#fff4dd;   --h-body: #ddd0b6;   --h-coin: #f0c25a;
  --ac-good: #9ee86a; --ac-mint: #7fd1b9; --ac-info: #9cc7f0;
  --ac-warn: #ffdb6e; --ac-bad:  #e87f7f; --ac-pink: #ff9ad5;
  --h-deep:  #120d07;    --h-track: #120d07;   --h-chip:  #1c150ce0; --h-chip-on: #46381fe8;
  --h-chip-on-ink: #ffeccd;
  --h-hover: #4a3a22;    --h-glow:  #c9a24a55;
  --h-inset: inset 0 1px 0 #ffffff22, inset 0 0 0 1px #00000055;
  --h-drop:  0 4px 14px #000000a0;
  --h-tsh:   0 1px 2px #000000cc;
}

/* ── slate · เทากลาง — เป็นกลางที่สุด ไม่แย่งสายตากับฉาก ── */
:root[data-theme="slate"] {
  --h-bg:    #1a1d22ee;  --h-bg-2:  #262a31ee;
  --h-line:  #5c626c;    --h-edge:  #b9c2cf;
  --h-ink:   #eceef1;    --h-ink2:  #b2b8c2;   --h-ink3: #868d98;
  --h-gold:  #dfe5ee;    --h-strong:#ffffff;   --h-body: #cfd4db;   --h-coin: #e3c483;
  --ac-good: #9ee86a; --ac-mint: #7fd1b9; --ac-info: #9cc7f0;
  --ac-warn: #ffdb6e; --ac-bad:  #e87f7f; --ac-pink: #ff9ad5;
  --h-deep:  #0d0f12;    --h-track: #0d0f12;   --h-chip:  #22262cE0; --h-chip-on: #414852e8;
  --h-chip-on-ink: #f2f4f7;
  --h-hover: #323841;    --h-glow:  #b9c2cf40;
  --h-inset: inset 0 1px 0 #ffffff1c, inset 0 0 0 1px #00000055;
  --h-drop:  0 4px 14px #000000a0;
  --h-tsh:   0 1px 2px #000000cc;
}

.ro-char, .ro-map, .ro-quest, .ro-chat, .target-bar, .castbar, .npc-dlg,
.ro-slot, .ro-menu button, .ro-menu-items button, .rpg-hint, .travelbar, .alertline, .combo {
  color: var(--h-ink);
  text-shadow: var(--h-tsh);
}
.ro-char, .ro-map, .ro-quest, .ro-chat {
  background: linear-gradient(var(--h-bg-2), var(--h-bg));
  border: 1px solid var(--h-line); border-radius: 4px;
  box-shadow: var(--h-inset), var(--h-drop);
}
.ro-char-top b { color: var(--h-strong); letter-spacing: .01em; }
.ro-job { color: var(--h-gold); }
.ro-chat-body div { color: var(--h-body); }
.ro-chat-tabs span { background: var(--h-chip); color: var(--h-ink3); }
.ro-chat-tabs b { background: var(--h-chip-on); color: var(--h-chip-on-ink); }
.ro-map-top .dim, .ro-quest .dim { color: var(--h-ink2); }
#minimap { border-radius: 3px; box-shadow: inset 0 0 0 1px #00000070; }

/* แถบสถานะ — ขอบคม 1px + เงาใน ให้แถบดู "จม" ในราง ไม่ใช่แปะทับ */
.ro-bar {
  background: var(--h-track); border: 1px solid #00000090; border-radius: 2px;
  box-shadow: inset 0 1px 2px #000000b0, 0 1px 0 #ffffff14;
}
.ro-bar i { border-radius: 1px; box-shadow: inset 0 1px 0 #ffffff55, inset 0 -3px 4px #00000040; }
.ro-bar.hp i  { background: linear-gradient(var(--bar-hp-a), var(--bar-hp-b)); }
.ro-bar.sp i  { background: linear-gradient(var(--bar-sp-a), var(--bar-sp-b)); }
.ro-bar.xp i  { background: linear-gradient(var(--bar-xp-a), var(--bar-xp-b)); }
.ro-bar.mob i { background: linear-gradient(var(--bar-hp-a), #7a1414); }
#rpg-mount .ro-bar.jxp i { background: linear-gradient(var(--bar-jx-a), var(--bar-jx-b)); }
.ro-bar span, .ro-bar em { color: #fff; text-shadow: 0 1px 2px #000, 0 0 3px #000c; }
.ro-lv b { color: var(--h-gold); text-shadow: var(--h-tsh); }
#rpg-mount .ro-lv b.jlv { color: var(--ac-info); }

/* ── C4b · แถบหลอน — เลือดลดฮวบแล้วมีเงาไล่ตามลงมา ตาจับได้ว่า "เพิ่งเสียไปเท่านี้"
   ต้องซ้อนหลังแถบจริง: .ro-bar i เดิมเป็น block ไหลตามกัน ถ้าไม่ absolute จะดันบรรทัด */
.ro-bar > i.ghost {
  position: absolute; left: 0; top: 0; height: 100%; z-index: 0;
  background: #ffffff5c; box-shadow: none;
  transition: width .45s ease-out .12s;   /* หน่วง .12s ให้แถบจริงลงไปก่อน แล้วเงาค่อยตาม */
}
.ro-bar > i { position: relative; z-index: 1; }
/* ตัวเลขในแถบต้องขึ้นก่อนแถบสี: พอ .ro-bar>i ได้ z-index:1 มันจะแซง span/em ที่เป็น auto
   (positioned เหมือนกัน) แล้วเลือดบังตัวเลขทันที — ต้องยกกลับขึ้นมาเอง */
.ro-bar span, .ro-bar em { z-index: 2; }
.ro-bar.hp > i.ghost { background: #ff9a8a70; }
.ro-bar.sp > i.ghost { background: #9ed0ff60; }

/* บัฟ/เควส/คำใบ้ */
.buffchip { background: var(--h-chip); border: 1px solid var(--h-line); border-radius: 3px; }
.buffchip i, .buffchip .ro-ic { color: var(--h-gold); }
.qh { color: var(--h-gold); }
.qrow b, .qticker b, .qpt { color: var(--h-gold); }
.qbar { background: var(--h-track); box-shadow: inset 0 1px 2px #000000b0; }
.qbar i { background: linear-gradient(#b8e87a, #5f9a2c); }
.qzone { color: var(--h-ink2); }
.rpg-hint { background: var(--h-chip); border: 1px solid var(--h-line); color: var(--h-ink2); padding: 3px 12px; }

/* แถบเป้าหมาย — ขอบแดงเข้มบอก "นี่คือศัตรู" ไม่ต้องอ่านชื่อ */
.target-bar {
  background: linear-gradient(var(--h-bg-2), var(--h-bg));
  border: 1px solid #a05a3a; border-radius: 4px;
  box-shadow: var(--h-inset), var(--h-drop);
}

/* ทูลทิปมอน — ชี้เมาส์ที่มอนแล้วรู้ชื่อ/ธาตุ/เลือด ก่อนตัดสินใจเข้าตี
   หน้าตาเดียวกับแถบเป้าหมายโดยตั้งใจ (ใช้ .tname/.tel/.ro-bar.mob ร่วมกัน) = เป็นภาษาภาพชุดเดียว
   pointer-events:none บังคับ — กล่องลอยอยู่ใต้เคอร์เซอร์ ถ้ามันรับเมาส์จะกิน mousemove ของฉากแล้วกะพริบ
   ตำแหน่ง left/top เขียนจาก JS (showMobTip) เพราะต้องพลิกด้านเองเมื่อชนขอบจอ */
.mob-tip {
  position: absolute; z-index: 22; display: none; width: 166px; padding: 5px 8px 6px;
  pointer-events: none; font-size: 11px;
  color: var(--h-ink); text-shadow: var(--h-tsh);
  background: linear-gradient(var(--h-bg-2), var(--h-bg));
  border: 1px solid #a05a3a; border-radius: 4px;
  box-shadow: var(--h-inset), var(--h-drop);
}
.mob-tip.on { display: block; }
.mob-tip .tname { margin-bottom: 4px; }
.mob-tip .dim { color: var(--h-ink2); }
.mob-tip .ro-bar { margin-bottom: 0; }
.castbar {
  background: var(--h-track); border: 1px solid var(--h-line); border-radius: 3px;
  box-shadow: inset 0 1px 3px #000000b0, var(--h-drop);
}
.castbar i { background: linear-gradient(#e6c0ff, #8a5fc9); }

/* ปุ่มฮอตบาร์/เมนู — กรอบทองบาง ๆ ตอน hover ให้รู้ว่ากดได้ */
.ro-slot {
  background: linear-gradient(var(--h-bg-2), var(--h-bg));
  border: 1px solid var(--h-line); border-radius: 4px;
  box-shadow: var(--h-inset), 0 2px 8px #00000090;
  transition: border-color .12s, box-shadow .12s, transform .08s;
}
.ro-slot:hover:not(.empty) { border-color: var(--h-edge); box-shadow: var(--h-inset), 0 0 10px var(--h-glow); }
.ro-slot:active:not(.empty) { transform: translateY(1px); }
.ro-slot .fk { color: var(--h-ink2); }
.ro-slot .nm { color: var(--h-ink2); }
.ro-slot .lv { color: var(--h-gold); }
.ro-slot.ration { border-color: #b0863c; }
.ro-slot.pot-hp { border-color: #b04a4a; }
.ro-slot.pot-sp { border-color: #4a6ab0; }
.ro-menu button, .ro-menu-items button {
  background: linear-gradient(var(--h-bg-2), var(--h-bg));
  border: 1px solid var(--h-line); border-radius: 4px;
  box-shadow: var(--h-inset), 0 2px 8px #00000090;
}
.ro-menu button:hover, .ro-menu-items button:hover { background: var(--h-hover); border-color: var(--h-edge); }
.ro-menu button span, .ro-menu-items button span { color: var(--h-ink2); }
/* ปุ่มเปิด/ปิดต้องเด่นกว่าปุ่มหน้าต่าง — ตอนปิดอยู่มันคือปุ่มเดียวที่เหลือบนจอ */
.ro-menu-tog { border-color: var(--h-edge) !important; }
.ro-menu-tog .ro-ic { color: var(--h-gold); }
.mnu-caret { border-right-color: var(--h-gold); }

/* ป้ายชื่อ NPC / ซุ้มวาร์ป */
.ntag { background: var(--h-chip); border-color: var(--h-line); color: var(--h-ink); }
.ntag.near { background: var(--h-chip-on); border-color: var(--h-edge); color: var(--h-chip-on-ink); }
.ptag { background: #14251fc0; border-color: #4a9a8a; color: #b8f0e0; }

/* ── C2 · บั๊กโลโก้หน้าไตเติล ─────────────────────────────────────────
   ต้นเหตุ: main.js ใส่ ic('anvil') ลง .start-logo แต่ ic() คืน <svg class="ro-ic">
   ซึ่งถูกล็อก 22×22px ไว้ที่หัวไฟล์นี้ — .start-logo{font-size:56px} จึงไม่มีผลเลย
   (font-size ไม่ขยาย svg ที่มี width/height ของตัวเอง) → เห็นเป็นไอคอนจิ๋วกลางจอ
   แก้ที่ CSS ล้วน เพราะ main.js เป็นไฟล์ของ agent อื่น */
.start-logo {
  width: 132px; height: 132px; display: grid; place-items: center;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 38%, #6a4f1e, #2a1d0a 72%);
  border: 2px solid #c9a24a;
  box-shadow: 0 0 0 1px #00000090, 0 0 34px #e8b94c40, inset 0 2px 0 #ffffff30, 0 12px 30px #000a;
  filter: drop-shadow(0 6px 16px #000a);
}
.start-logo .ro-ic {
  width: 78px; height: 78px;                 /* ต้องระบุตรง ๆ — .ro-ic ล็อก 22px ไว้ */
  color: #ffdf9a;
  filter: drop-shadow(0 2px 0 #8a5a2a) drop-shadow(0 0 12px #e8b94c66);
}
.start-title { font-size: clamp(30px, 9vw, 46px); }
.start-screen { background: radial-gradient(1200px 620px at 50% 18%, #3a5470, #17222f 72%); }
.start-box { gap: 12px; }
.start-continue, .start-new {
  box-shadow: 0 3px 0 #8a5a2a, 0 8px 20px #0008;
  transition: transform .08s, box-shadow .08s;
}
.start-continue:active, .start-new:active { transform: translateY(2px); box-shadow: 0 1px 0 #8a5a2a, 0 4px 10px #0008; }
.start-new.ghost2 { box-shadow: 0 2px 0 #16283a, 0 6px 16px #0007; }

/* ── B5 · ตัวเลขดาเมจให้มีน้ำหนัก ───────────────────────────────────
   ขอบดำทำด้วย text-shadow 8 ทิศ ไม่ใช้ -webkit-text-stroke:
   stroke วาดคร่อมเส้นอักษร (เข้าไปกินด้านในครึ่งหนึ่ง) เลข 3-4 หลักเลยตัน อ่านไม่ออก
   --t: COMBAT ยิง style="--t:${f.t}" มาได้ → ตัวเลขเด้งตอนเกิดแล้วยุบเข้าที่
   ค่าตั้งต้น 1 = ไม่เด้ง เพราะ #floaters ถูกสร้างใหม่ทุกเฟรม @keyframes จึงใช้ไม่ได้ */
.floaters .fl {
  --t: 1;
  --pop: max(0, 1 - var(--t) * 7);
  transform: translate(-50%, -50%) scale(calc(1 + .45 * var(--pop)));
  font-weight: 900; letter-spacing: .02em;
  font-variant-numeric: tabular-nums;
  text-shadow:
    1.5px 0 0 #140e06, -1.5px 0 0 #140e06, 0 1.5px 0 #140e06, 0 -1.5px 0 #140e06,
    1.1px 1.1px 0 #140e06, -1.1px 1.1px 0 #140e06, 1.1px -1.1px 0 #140e06, -1.1px -1.1px 0 #140e06,
    0 3px 6px #000000b0;
}
.floaters .fl.dmg   { color: #fff3cf; font-size: 17px; }
.floaters .fl.magic { color: #a8e0ff; font-size: 17px; }
.floaters .fl.hurt  { color: #ff7a6a; font-size: 18px; }
.floaters .fl.exp   { color: #b6f07a; font-size: 13px; font-weight: 800; }
/* EXP สองสาย = สองสี (คำสั่ง Stamp 1 ส.ค. 2026) — เขียว Base · ฟ้า Job · ทองบอกว่าแบ่งกันในปาร์ตี้
   อยู่ในก้อนลอยเดียวกันเพื่อไม่ให้ตัวเลขสองก้อนซ้อนกันตอนล้มมอนรัว ๆ */
.floaters .fl.exp .e-b,
.floaters .fl.exp .e-j,
.floaters .fl.exp .e-p { display: inline-block; margin: 0 3px; }
.floaters .fl.exp .e-b { color: #b6f07a; }
.floaters .fl.exp .e-j { color: #7fd7ff; }
.floaters .fl.exp .e-p { color: #ffd76a; font-size: 11px; }
.floaters .fl.burst { color: #ffe8a0; font-size: 12px; font-weight: 800; }
.floaters .fl.buff  { color: #e0b0ff; font-size: 15px; }
/* คริต — ใหญ่กว่า สีทอง มีรัศมี เด้งแรงกว่าเลขปกติ (--pop คูณ .8 แทน .45) */
.floaters .fl.crit {
  color: #ffd451; font-size: 27px;
  transform: translate(-50%, -50%) scale(calc(1 + .8 * var(--pop)));
  text-shadow:
    2px 0 0 #140e06, -2px 0 0 #140e06, 0 2px 0 #140e06, 0 -2px 0 #140e06,
    1.5px 1.5px 0 #140e06, -1.5px 1.5px 0 #140e06, 1.5px -1.5px 0 #140e06, -1.5px -1.5px 0 #140e06,
    0 0 16px #ffb43cb0, 0 4px 8px #000000b0;
}
.floaters .fl.warn { color: #ffab4a; font-size: 19px; }
/* ฮีลเขียว ลอยขึ้นเร็วกว่าเลขอื่นเล็กน้อยด้วยการยกฐานขึ้น 6px */
.floaters .fl.heal {
  color: #7ff0bd; font-size: 17px;
  transform: translate(-50%, calc(-50% - 6px)) scale(calc(1 + .35 * var(--pop)));
}
/* miss เทาจาง ไม่แย่งสายตาจากเลขจริง */
.floaters .fl.miss {
  color: #cfd6de; font-size: 13px; font-weight: 700; opacity: .8;
  text-shadow: 0 1px 0 #140e06, 0 -1px 0 #140e06, 1px 0 0 #140e06, -1px 0 0 #140e06, 0 2px 5px #000a;
}
/* ข้อความใหญ่กลางจอ (LEVEL UP / ชนะบอส) — สร้างครั้งเดียวแล้วลบ keyframes ใช้ได้จริง */
.bigtext {
  color: #ffd451;
  text-shadow: 0 2px 0 #7a4a10, 0 4px 0 #3a2408, 0 6px 22px #000c, 0 0 40px #e8b94c66;
}

/* ── C4a · คูลดาวน์แบบเข็มกวาด ──────────────────────────────────────
   --p = สัดส่วนที่ "ยังคูลดาวน์อยู่" (1 = เพิ่งกด, 0 = พร้อมใช้)
   เริ่มที่ยอด (from 0deg) แล้วเงาหดตามเข็มนาฬิกา — อ่านออกด้วยหางตา ไม่ต้องอ่านตัวเลข
   renderHotbar() วาดใหม่ทุก 0.25s อยู่แล้ว conic-gradient จึงอัปเดตตามเองไม่ต้องใช้ animation */
.ro-slot .cdsweep {
  position: absolute; inset: 0; border-radius: 3px; pointer-events: none; z-index: 2;
  background: conic-gradient(from 0deg at 50% 50%,
    #0000 0turn calc((1 - var(--p, 0)) * 1turn), #0b0906d9 0);
}
.ro-slot .cdsweep::after {
  content: ''; position: absolute; inset: 0; border-radius: 3px;
  box-shadow: inset 0 0 0 1px #ffffff1c;
}
/* มีเข็มกวาดแล้วไม่ต้องมีฉากดำทับอีกชั้น — เหลือแค่ตัวเลขวินาที */
.ro-slot:has(.cdsweep) .cd { background: transparent; }
.ro-slot .cd { color: #fff; text-shadow: 0 1px 3px #000, 0 0 6px #000; z-index: 3; }

/* ── คอมโบ ──────────────────────────────────────────────────────────
   .combo > b เลข · > span คำว่าคอมโบ · > i แถบเวลาที่เหลือ (--p 0–1)
   เด้ง: HUD เติมคลาส .hit ตอนเลขเพิ่ม แล้วถอดในเฟรมถัดไป — เติมซ้ำ = animation รันใหม่ */
/* วางชิดขวากลางจอ ไม่ใช่กลางบน — กลางบนชนป้ายชื่อแมปตอนเพิ่งวาร์ปเข้ามา
   และชนตัวเลขดาเมจที่พุ่งขึ้นจากตัวมอนกลางจอพอดี */
.combo {
  position: absolute; right: 14px; top: 48%; transform: translateY(-50%) scale(.8);
  display: grid; justify-items: center; gap: 2px; pointer-events: none; z-index: 14;
  opacity: 0; transition: opacity .18s ease-out, transform .18s ease-out;
}
.combo.on { opacity: 1; transform: translateY(-50%) scale(1); }
.combo > b {
  font-size: 44px; font-weight: 900; line-height: .9; color: #ffd451;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 2px 0 #7a4a10, 0 4px 0 #3a2408, 0 6px 18px #000c, 0 0 26px #ffb43c70;
  transform-origin: 50% 60%;
}
.combo > span { font-size: 11px; font-weight: 800; letter-spacing: .16em; color: #ffe2a0; }
.combo > i {
  display: block; width: 74px; height: 4px; border-radius: 2px; margin-top: 3px;
  background: #00000080; box-shadow: inset 0 0 0 1px #00000090;
  background-image: linear-gradient(#ffd451, #c9891a);
  background-size: calc(var(--p, 0) * 100%) 100%; background-repeat: no-repeat;
}
.combo.hit > b { animation: combo-bump .22s cubic-bezier(.2, 1.5, .4, 1); }
@keyframes combo-bump { 0% { transform: scale(1.55); } 100% { transform: scale(1); } }

/* ── แถบประกาศกลางจอบน ──────────────────────────────────────────────
   .champ = มอนตัวเด่นโผล่ (ทอง) · .flee = มอนขี้ตื่นกำลังหนี (ฟ้าเทา) */
.alertline {
  position: absolute; left: 50%; top: 0; transform: translate(-50%, -140%);
  z-index: 22; pointer-events: none; white-space: nowrap; max-width: 94vw; overflow: hidden;
  display: flex; align-items: center; gap: 7px;
  padding: 6px 18px; border-radius: 0 0 5px 5px;
  font-size: 12.5px; font-weight: 700;
  background: linear-gradient(var(--h-bg-2), var(--h-bg));
  border: 1px solid var(--h-line); border-top: 0;
  box-shadow: var(--h-inset), var(--h-drop);
  opacity: 0; transition: transform .32s cubic-bezier(.2, 1.1, .4, 1), opacity .32s ease-out;
}
.alertline.on { transform: translate(-50%, 0); opacity: 1; }
.alertline .ro-ic { width: 16px; height: 16px; }
.alertline.champ { border-color: var(--h-edge); color: var(--h-gold); box-shadow: var(--h-inset), 0 0 20px var(--h-glow), var(--h-drop); }
.alertline.champ .ro-ic { color: var(--h-gold); }
.alertline.flee { border-color: #5f8aa8; color: #d6ecf8; }
.alertline.flee .ro-ic { color: #9ed0ff; }

/* ── ปุ่มสัมผัสมือถือ ────────────────────────────────────────────────
   ขนาดนิ้วจริง ≥52px (เกณฑ์ Apple HIG 44pt + เผื่อถุงมือ/นิ้วโป้ง)
   วางมุมล่างซ้าย/ขวาให้ฝ่ามือไม่บังกลางจอ และไม่ทับ .ro-chat ที่อยู่ซ้ายล่างเหมือนกัน */
.touchpad {
  position: absolute; left: 14px; bottom: 14px; z-index: 18;
  width: 132px; height: 132px; border-radius: 50%; touch-action: none;
  background: radial-gradient(circle at 50% 50%, #2c221490, #1408 72%, #0000);
  border: 1px solid #8a734680; box-shadow: inset 0 0 20px #00000060;
}
.touchpad > i {
  position: absolute; left: 50%; top: 50%; width: 56px; height: 56px; margin: -28px 0 0 -28px;
  border-radius: 50%; display: block;
  background: radial-gradient(circle at 42% 34%, #6a5228, #2a1d0a);
  border: 1px solid var(--h-edge);
  box-shadow: inset 0 2px 0 #ffffff30, 0 3px 10px #000a;
  transition: transform .09s ease-out;   /* JS ยิง translate ตอนลาก — ปล่อยแล้วดีดกลับเอง */
}
.touchpad.on > i { box-shadow: inset 0 2px 0 #ffffff40, 0 0 14px #c9a24a70, 0 3px 10px #000a; }
/* min-height ประกาศความสูงจริงของกลุ่มปุ่มไว้เป็นตัวเลขที่อ่านได้ (--hud-touch-stack)
   แถวล่างใช้ค่านี้คำนวณว่าต้องยกขึ้นแค่ไหนถึงจะพ้น — เพิ่ม/ลดปุ่มเมื่อไหร่ต้องแก้ตัวแปรตาม
   align-content: flex-start กันไม่ให้บรรทัดถูกยืดกระจายเมื่อความสูงถูกกำหนด */
.touchacts {
  position: absolute; right: 12px; bottom: var(--hud-touch-b); z-index: 18;
  display: flex; flex-wrap: wrap-reverse; justify-content: flex-end; align-content: flex-start; gap: 8px;
  width: 132px; min-height: var(--hud-touch-stack); pointer-events: none;
}
.touchacts > button {
  pointer-events: auto;
  width: 56px; height: 56px; min-width: 56px; padding: 0; border-radius: 50%;
  display: grid; place-items: center;
  background: linear-gradient(var(--h-bg-2), var(--h-bg));
  border: 1px solid var(--h-edge); color: var(--h-gold);
  box-shadow: var(--h-inset), 0 3px 10px #000a;
}
.touchacts > button .ro-ic { width: 26px; height: 26px; }
.touchacts > button:active { transform: scale(.93); background: linear-gradient(#5a4318, #362510); }
.touchacts > button:disabled { opacity: .35; }
.touchacts > button.big { width: 72px; height: 72px; }
.touchacts > button.big .ro-ic { width: 32px; height: 32px; }

/* ── แถวล่างสุดของ HUD: กริดเดียว 3 เลน ────────────────────────────
   แชท (ซ้าย) · ฮอตบาร์ (กลาง) · ปุ่มเมนู (ขวา) — ทั้งหมดชิดขอบล่างจริง
   นี่คือกล่องเดียวที่ "วางพิกัด" ให้สามส่วนนี้ · ลูกทั้งสามห้ามเป็น absolute เด็ดขาด
   เลนกลางเป็น minmax(0,1fr): ฮอตบาร์ยาวแค่ไหนก็ดันเลนข้าง ๆ ไม่ได้ ต้องห่อบรรทัดแทน
   pointer-events แพทเทิร์นเดิม — ช่องว่างในกริดต้องไม่กินคลิกให้โลก 3D ที่อยู่ข้างใต้ */
.ro-bottom {
  position: absolute; z-index: 16;
  left: var(--hud-edge); right: var(--hud-edge); bottom: var(--hud-bottom-b);
  display: grid; align-items: end; gap: var(--hud-gap);
  grid-template-columns: minmax(0, var(--hud-chat-w)) minmax(0, 1fr) max-content;
  grid-template-areas: "chat hot menu";
  pointer-events: none;
}
.ro-bottom > * { pointer-events: auto; }
.ro-chat    { grid-area: chat; }
.ro-hotwrap { grid-area: hot; }
/* เมนูสูงเท่า "ปุ่มเมนู" (end) ไม่ใช่ทั้งแถว — bottom:100% ของแผงที่กางจึงเท่ากับ
   "ยอดปุ่มเมนู" แผงโผล่ติดนิ้วที่เพิ่งกด ไม่ลอยไปกลางจอเหมือนตอนยึดยอดแถว
   ไม่ทับฮอตบาร์/แชทเพราะทั้งคู่อยู่คนละคอลัมน์ของกริดและจบก่อนเลนเมนูเสมอ
   pointer-events: none ยังต้องมี — แผงกว้างกว่าปุ่ม ส่วนที่ล้นออกมาต้องไม่กินคลิกตอนพับ */
.ro-menu { grid-area: menu; align-self: end; pointer-events: none; }
.ro-menu > * { pointer-events: auto; }

/* ── ฮอตบาร์แบ่งหน้า ────────────────────────────────────────────────
   จอแคบใส่ 9 ช่องไม่พอ → แบ่งเป็นหน้าละไม่กี่ช่อง แล้วมีจุดบอกว่าอยู่หน้าไหน
   pointer-events: none ที่กล่องนอก — กล่องนี้กว้างเท่าฮอตบาร์ (ทั้งที่แถวจุดหน้าแคบนิดเดียว)
   ช่องว่างข้าง ๆ จึงเคยกินคลิกให้ของที่อยู่ข้างใต้แบบมองไม่เห็น (แพทเทิร์นเดียวกับ .combo)
   width: max-content + max-width: 100% = กว้างเท่าเนื้อหาแต่ไม่เกินเลนกลาง
   เลนกลางเป็น 1fr (ความกว้างชี้ชัด) จึงใช้ % ตรงนี้ได้ ไม่อ้างวนเหมือนตอนใส่ที่ .ro-hotbar */
.ro-hotwrap {
  position: static; justify-self: center;
  width: max-content; max-width: 100%; min-width: 0;
  display: grid; justify-items: center; gap: 4px; pointer-events: none;
}
.ro-hotwrap > * { pointer-events: auto; }

/* ── จอที่ใส่สามเลนในแถวเดียวไม่พอ → "ซ้อนอย่างมีระเบียบ" ในกริดเดิม ──────
   ต้องการอย่างน้อย 14 + แชท 268 + 5 + ฮอตบาร์ 11 ช่อง 624 + 5 + ปุ่มเมนู 46 = 962px
   ต่ำกว่านั้นเลนกลางจะแคบจนฮอตบาร์ห่อเป็นเสา — แยกแชทขึ้นแถวบนแทน
   ปุ่มเมนูคร่อมสองแถว (grid-area menu อยู่ทั้งสองบรรทัด) จึงยังชิดขวาล่าง
   และแผงที่กางยังลอยพ้นทั้งแชทและฮอตบาร์เหมือนเดิม
   ย้ำ: ยังเป็นกริดเดียว = สามส่วนคนละ area ทับกันไม่ได้อยู่ดี */
@media (max-width: 960px) {
  .ro-bottom {
    grid-template-columns: minmax(0, 1fr) max-content;
    grid-template-areas: "chat menu" "hot menu";
  }
  /* แถวล่างสูงขึ้นเพราะซ้อนสองบรรทัด — ประกาศที่ "ความสูงแถว" อย่างเดียว
     แล้ว --hud-above คิดตามเอง (วัดจริงที่ 561px: แชท 108 + ช่องไฟ 5 + ฮอตบาร์ห่อ 2 บรรทัด 134 = 247) */
  :root { --hud-row-h: 252px; }
}

/* ป้ายบอกทาง: กฎยกแถวหนีปุ่มสัมผัสเคยอยู่ตรงนี้ (.rpg:has(.touchpad) .ro-bottom)
   ย้ายไปเป็น --hud-bottom-b บน :root:has(.touchpad) ด้านบนไฟล์นี้แล้ว
   เขียนกลับมาที่นี่เมื่อไหร่ = แถวขยับแต่ --hud-above ไม่รู้เรื่อง ซึ่งคือบั๊กบทสนทนา NPC โดนแถวทับ 31 ก.ค. เป๊ะ ๆ
   (test/rpg-hud.js บังคับไว้: ห้ามกฎไหนตั้ง bottom ให้ .ro-bottom นอกจาก var(--hud-bottom-b)) */

.hb-page { display: flex; gap: 3px; }
.hb-page[hidden] { display: none; }
.hb-dots { display: flex; gap: 5px; }
.hb-dots > i {
  display: block; width: 7px; height: 7px; border-radius: 50%;
  background: #00000090; border: 1px solid var(--h-line);
  transition: background .14s, border-color .14s, transform .14s;
}
.hb-dots > i.on { background: var(--h-gold); border-color: var(--h-edge); transform: scale(1.25); }

/* ── แถบเดินทางอัตโนมัติ ───────────────────────────────────────────── */
.travelbar {
  position: absolute; left: 50%; top: 46px; transform: translate(-50%, -10px);
  z-index: 20; display: flex; align-items: center; gap: 8px;
  white-space: nowrap; max-width: calc(100vw - 20px);   /* ไม่ให้ชื่อแมปยาว ๆ ตัดบรรทัดจนแถบสูงเป็นบล็อก */
  padding: 5px 12px; border-radius: 4px; font-size: 11.5px;
  background: linear-gradient(var(--h-bg-2), var(--h-bg));
  border: 1px solid var(--h-line); box-shadow: var(--h-inset), var(--h-drop);
  opacity: 0; pointer-events: none;
  transition: opacity .22s ease-out, transform .22s ease-out;
}
.travelbar.on { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.travelbar b { color: var(--h-gold); }
.travelbar .ro-ic { color: #9ed0ff; width: 15px; height: 15px; }
.travelbar button {
  min-height: 28px; padding: 3px 10px; font-size: 11px; border-radius: 3px;
  color: var(--h-ink2); background: #1c150cd0; border: 1px solid var(--h-line); cursor: pointer;
}
.travelbar button:hover { border-color: var(--h-edge); color: #fff0c0; }

/* ── วงเลือกท่าทาง (emotes) ─────────────────────────────────────────
   emoteWheelHTML() ยัดตำแหน่งมาใน style= อยู่แล้ว (inline ชนะ CSS เสมอ) — กฎด้านล่าง
   จึงทำสองอย่าง: (1) เติมเงา/hover/แอนิเมชันเปิดที่ inline ไม่มี
   (2) กางวงให้เองด้วย nth-child เผื่อ HUD เขียน markup เป็นคลาสล้วนไม่พึ่ง emotes.js */
.em-wheel {
  position: absolute; left: 50%; bottom: 92px; transform: translateX(-50%);
  width: 276px; height: 276px; z-index: 26;
  animation: em-open .18s cubic-bezier(.2, 1.2, .4, 1);
}
@keyframes em-open { from { opacity: 0; transform: translateX(-50%) scale(.82); } }
.em-wheel > .em-btn {
  --a: 0deg;
  position: absolute; left: 50%; top: 50%;
  width: 52px; height: 52px; padding: 0; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  font: 700 9px/1.25 inherit; color: var(--h-gold); cursor: pointer;
  background: linear-gradient(var(--h-bg-2), var(--h-bg));
  border: 1px solid var(--h-line);
  box-shadow: var(--h-inset), 0 3px 10px #000a;
  transform: translate(-50%, -50%) rotate(var(--a)) translateY(-108px) rotate(calc(-1 * var(--a)));
  transition: border-color .12s, box-shadow .12s;
}
.em-wheel > .em-btn:nth-child(1)  { --a: 0deg; }
.em-wheel > .em-btn:nth-child(2)  { --a: 30deg; }
.em-wheel > .em-btn:nth-child(3)  { --a: 60deg; }
.em-wheel > .em-btn:nth-child(4)  { --a: 90deg; }
.em-wheel > .em-btn:nth-child(5)  { --a: 120deg; }
.em-wheel > .em-btn:nth-child(6)  { --a: 150deg; }
.em-wheel > .em-btn:nth-child(7)  { --a: 180deg; }
.em-wheel > .em-btn:nth-child(8)  { --a: 210deg; }
.em-wheel > .em-btn:nth-child(9)  { --a: 240deg; }
.em-wheel > .em-btn:nth-child(10) { --a: 270deg; }
.em-wheel > .em-btn:nth-child(11) { --a: 300deg; }
.em-wheel > .em-btn:nth-child(12) { --a: 330deg; }
.em-wheel > .em-btn.em-close {
  transform: translate(-50%, -50%); width: 48px; height: 48px; color: var(--h-ink2);
}
/* ปุ่มจาก emotes.js ไม่มีคลาส — จับด้วย data-act แทน เพื่อให้ hover/เงาเข้าชุดกัน */
.em-wheel > .em-btn:hover,
[data-act="emote"]:hover, [data-act="emote-close"]:hover {
  border-color: var(--h-edge); box-shadow: 0 0 12px #c9a24a66, 0 3px 10px #000a;
}
.em-wheel > .em-btn span { color: var(--h-ink2); letter-spacing: .02em; }
[data-act="emote"] .ro-ic, .em-wheel > .em-btn .ro-ic { width: 20px; height: 20px; }

/* ── โคเด็กซ์ (สารานุกรม) ในหน้าต่าง ────────────────────────────────
   codex.js ปัจจุบันออก .tabbar/.tab/.craftrow — จับทั้งชื่อเดิมและชื่อตาม CONTRACT
   ให้เหมือนกันเป๊ะ ใครออก markup แบบไหนก็หน้าตาเดียวกัน */
.winbox .codex-tabs, .winbox .tabbar {
  display: flex; gap: 3px; flex-wrap: wrap; margin-bottom: 7px;
  border-bottom: 1px solid var(--w-line-2); padding-bottom: 6px;
}
.winbox .codex-tabs button, .winbox .tabbar .tab {
  font-size: 12px; padding: 5px 13px; min-height: 30px; border-radius: 2px;
  background: linear-gradient(#fbfbfb, #dedede); border: 1px solid #8f8f8f; color: #202020;
}
.winbox .codex-tabs button.on, .winbox .tabbar .tab.on {
  background: linear-gradient(#dcecff, #b9d4f0); border-color: #4a7fc1; color: #17456f; font-weight: 700;
}
.winbox .codexrow, .winbox .craftrow {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 8px 0; border-top: 1px solid #e6e6e6; background: transparent;
}
.winbox .codexrow:first-of-type, .winbox .craftrow:first-of-type { border-top: 0; }
.winbox .codexrow:hover, .winbox .craftrow:hover { background: #f3f7fb; }
.winbox .codexrow .grow, .winbox .craftrow .grow { min-width: 0; }
.winbox .codexrow b, .winbox .craftrow b { color: var(--w-ink); }
.winbox input[type=text], .winbox input[type=search] {
  width: 100%; font: inherit; font-size: 12.5px; padding: 5px 8px; min-height: 32px;
  background: #fff; color: var(--w-ink); border: 1px solid #9a9a9a; border-radius: 2px;
}
.winbox input[type=text]:focus, .winbox input[type=search]:focus { outline: 2px solid var(--w-accent); outline-offset: -1px; }

/* ── หน้าต่างตัวเลือก ───────────────────────────────────────────────
   optrow = ป้ายซ้าย + ตัวคุมขวา · ป้ายกว้างคงที่ให้ตัวคุมเรียงตรงกันทั้งคอลัมน์ */
.winbox .optrow {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 7px 0; border-top: 1px solid #e6e6e6; font-size: 12px;
}
.winbox .optrow:first-of-type { border-top: 0; }
.winbox .optrow > span:first-child { flex: 0 0 auto; width: 112px; color: var(--w-ink-2); }
.winbox .optrow .grow { flex: 1 1 120px; min-width: 0; display: flex; align-items: center; gap: 8px; }
.winbox .optrow output, .winbox .optrow .optval {
  min-width: 44px; text-align: right; font-family: ui-monospace, Menlo, monospace;
  font-variant-numeric: tabular-nums; font-size: 12px; color: var(--w-ink);
}
.winbox .optrow .dim { flex: 1 1 100%; font-size: 11px; }
/* สไลเดอร์ — เขียนเอง 100% เพราะ appearance เริ่มต้นของแต่ละเบราว์เซอร์ไม่เหมือนกันเลย */
.optslider {
  -webkit-appearance: none; appearance: none; flex: 1 1 90px; min-width: 90px;
  height: 22px; background: transparent; cursor: pointer; margin: 0;
}
.optslider::-webkit-slider-runnable-track {
  height: 6px; border-radius: 3px; background: #dcdcdc;
  box-shadow: inset 0 1px 2px #00000030; border: 1px solid #b4b4b4;
}
.optslider::-moz-range-track {
  height: 6px; border-radius: 3px; background: #dcdcdc;
  box-shadow: inset 0 1px 2px #00000030; border: 1px solid #b4b4b4;
}
/* หัวจับ 20px — เล็กกว่านี้นิ้วโป้งบนมือถือจับไม่ติด */
.optslider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 20px; height: 20px; margin-top: -8px; border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, #fdfdfd, #cfcfcf);
  border: 1px solid #6d8fb5; box-shadow: 0 1px 3px #0004;
}
.optslider::-moz-range-thumb {
  width: 20px; height: 20px; border-radius: 50%; border: 1px solid #6d8fb5;
  background: radial-gradient(circle at 40% 35%, #fdfdfd, #cfcfcf); box-shadow: 0 1px 3px #0004;
}
.optslider:focus-visible::-webkit-slider-thumb { outline: 2px solid var(--w-accent); outline-offset: 1px; }
.winbox .optrow input[type=checkbox] { width: 17px; height: 17px; accent-color: var(--w-accent); cursor: pointer; }

/* ── ทรานซิชันเปิดหน้าต่าง ──────────────────────────────────────────
   ui.js เปิดด้วย innerHTML = โหนดเกิดใหม่ → animation รันครบรอบพอดี
   ปิดไม่มีทรานซิชันเพราะ innerHTML='' ลบโหนดทันที (ต้องแก้ที่ JS ซึ่งเป็นไฟล์ของ agent อื่น) */
#win .winbg { animation: win-fade .16s ease-out; }
#win .winbox { animation: win-pop .2s cubic-bezier(.2, 1.1, .4, 1); transform-origin: 50% 42%; }
@keyframes win-fade { from { opacity: 0; } }
@keyframes win-pop { from { opacity: 0; transform: translate(-50%, -50%) scale(.94); } }
.winbox { box-shadow: 0 14px 40px #000b, 0 0 0 1px #00000060; }

/* ── ป้ายชื่อแมปตอนเข้า ─────────────────────────────────────────────
   rpgui.js สลับคลาส .on อย่างเดียว → ใช้ transition ไม่ใช่ keyframes ถึงจะจางหายตอนถอดคลาส
   ตัวอักษรซ้อนขอบทองด้วย -webkit-text-stroke ได้ (ตัวใหญ่มาก ขอบไม่กินเนื้ออักษร) */
.rpg .mapbanner {
  top: 15%; font-size: clamp(26px, 6vw, 44px); letter-spacing: .06em;
  color: #fff6e2;
  -webkit-text-stroke: 1.5px #7a5410;
  text-shadow: 0 3px 0 #4a3208, 0 6px 22px #000c, 0 0 44px #e8b94c55;
  transform: translateX(-50%) scale(1.06);
  transition: opacity .55s ease-out, transform .55s cubic-bezier(.2, 1, .4, 1);
}
.rpg .mapbanner.on { transform: translateX(-50%) scale(1); }
/* ขีดทองบน-ล่างชื่อแมป — ทำให้ป้ายดูเป็น "การ์ดชื่อด่าน" ไม่ใช่ตัวหนังสือลอย */
.rpg .mapbanner::before, .rpg .mapbanner::after {
  content: ''; position: absolute; left: 50%; transform: translateX(-50%);
  width: 118%; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, #e8b94c00, #e8b94ce0 22%, #fff6c8 50%, #e8b94ce0 78%, #e8b94c00);
}
.rpg .mapbanner::before { top: -8px; }
.rpg .mapbanner::after { bottom: -8px; }

/* ── ฟองข้อความ NPC ─────────────────────────────────────────────────
   กล่องคุยเดิมเป็นน้ำเงินเข้ม — เปลี่ยนเป็นกระดาษครีมแบบหน้าต่างเกม อ่านง่ายกว่าบนฉากสว่าง
   หางฟองชี้ลงหา NPC ด้วย ::after หมุน 45° (ไม่ต้องมีรูป ไม่ต้องมี SVG)

   ── รอบขัดใหม่ 31 ก.ค. (คำสั่ง Stamp: "ตรงนี้ดูไม่สวย ออกแบบดีๆหน่อย") ──────────
   ของเดิมเป็นกระดาษครีมแบนสี่เหลี่ยม ทุกชิ้นน้ำหนักเท่ากันหมด ตาไม่รู้ว่าจะอ่านอะไรก่อน:
     รูปตัวละครลอยอยู่บนพื้นครีมโดยไม่มีอะไรรอง (วอกเซลสีเข้มจมหายไปกับกรอบ)
     ชื่อคนกับชื่อร้านต่อกันเป็นบรรทัดเดียว "Recruiter Phian · ที่ว่าการจ้างงาน"
     ปุ่มรองเป็นสีเทา-ขาวแบบปุ่มระบบปฏิบัติการ หลุดจากพาเลตอุ่นของทั้งเกม
   ที่แก้ — ทั้งหมดเป็นเรื่อง "ลำดับการมอง" ไม่ใช่แค่เปลี่ยนสี:
     1. กรอบสองชั้น (::before) = ภาษาเดียวกับหน้าต่างเกมแนว RO ไม่ใช่กล่องแจ้งเตือนเปล่า ๆ
     2. ช่องรูปเป็น "ซุ้มมืด" มีแสงสาดจากล่าง = ตัวละครวอกเซลเด้งออกจากพื้นครีม
     3. ชื่อคนตัวหนาเข้ม + ที่ทำงานเป็นชิปเล็ก + เส้นคั่นใต้หัวเรื่อง = แยกชั้นข้อมูลชัด
     4. ปุ่มรองเป็นกระดาษ (ไม่ใช่เทา) ปุ่มหลักเป็นทองมีความหนา = รู้ทันทีว่าอันไหนคือทางไปต่อ */
.npc-dlg {
  background: linear-gradient(#fdf8ec, #eee2c8);
  border: 1px solid #a98c52; border-radius: 10px;
  color: #2a2114;
  box-shadow: 0 2px 0 #00000026, 0 16px 44px #000c, inset 0 1px 0 #fffdf6;
  animation: npc-in .2s cubic-bezier(.2, 1.1, .4, 1);
}
@keyframes npc-in { from { opacity: 0; transform: translate(-50%, 10px); } }
/* กรอบในอีกชั้น — วางทับด้วย inset ไม่กินที่ในผัง จึงไม่ขยับความสูงกล่อง (--hud-npc-dlg-h) */
.npc-dlg::before {
  content: ''; position: absolute; inset: 3px; border-radius: 7px;
  border: 1px solid #c9ad7099; pointer-events: none;
}
.npc-dlg::after {
  content: ''; position: absolute; left: 43px; bottom: -7px; width: 13px; height: 13px;
  transform: rotate(45deg); background: #eee2c8;
  border-right: 1px solid #a98c52; border-bottom: 1px solid #a98c52;
}
/* ซุ้มรูป — เข้มและมีแสงสาดจากพื้น ตัวละครวอกเซลจึงมีขอบตัดกับกล่อง ไม่จมกลืนไปกับครีม */
.npc-port {
  background:
    radial-gradient(120% 78% at 50% 100%, #7a5f2b 0%, #3a2d1800 68%),
    linear-gradient(#2f2515, #191207);
  border: 1px solid #8a7346;
  box-shadow: inset 0 2px 9px #000000a8, 0 1px 0 #fffdf6;
}
.npc-face { filter: drop-shadow(0 3px 6px #00000070); }
.npc-who {
  padding-bottom: 5px; margin-bottom: 1px;
  border-bottom: 1px solid #c9ad7066;
}
.npc-who b { color: #5a3007; font-weight: 800; text-shadow: 0 1px 0 #fffdf6cc; }
.npc-who i {
  color: #6d5a30; background: #d8c69a55; border: 1px solid #b9a06b;
}
.npc-txt p { color: #3b2f1c; }
.npc-dlg .dim { color: #8a7a5c; }
.npc-acts button {
  min-height: 36px; border-radius: 6px; font-weight: 700;
  background: linear-gradient(#fffaee, #e6d9bb); border: 1px solid #a98c52; color: #4a3a1c;
  box-shadow: 0 2px 0 #0000001c;
}
.npc-acts button:hover { background: linear-gradient(#fffdf6, #f0e4c8); border-color: #8a6a2a; }
.npc-acts button.npc-go {
  background: linear-gradient(#ffdc8c, #dfa32a); border-color: #8a5a10; color: #3a2408;
  box-shadow: 0 2px 0 #8a5a10, inset 0 1px 0 #fff3c9;
}
.npc-acts button.npc-go:hover { background: linear-gradient(#ffe5a4, #e8ae38); }
.npc-acts button:active { transform: translateY(2px); box-shadow: none; }
.npc-acts button.ghost { background: #00000008; color: #6a5636; box-shadow: none; }

/* ── เคอร์เซอร์ ─────────────────────────────────────────────────────
   32px + ขอบดำหนา 5px รอบเส้นสี — เคอร์เซอร์เดิม 30px/ขอบ 4.2px จมหายบนพื้นหญ้าสว่าง
   (ทับกฎเดิมด้านบนไฟล์นี้ ซึ่งประกาศไว้ก่อนจึงแพ้ลำดับ)

   ศิลปะดาบเก็บเป็นตัวแปร --cur-sword ตัวเดียว เพราะถูกใช้สองที่:
     1) เคอร์เซอร์ระบบ (.cur-mob) — ทางถอย เผื่อดาบที่วาดเองยังไม่ติด
     2) sprite .swordcur ที่ JS วาดเองตอนมีแรงดูด
   ถ้าแยกกันเขียน วันไหนแก้สีดาบแล้วลืมอีกที่ จะเห็นดาบสองแบบสลับกันตอนเข้า/ออกรัศมีดูด */
.rpg {
  --cur-sword: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><g transform="rotate(45 16 16)"><g fill="%23120d06" stroke="%23120d06" stroke-width="3.8" stroke-linejoin="round"><path d="M16 2.2 L18.6 7 V19.2 H13.4 V7 Z"/><rect x="8.2" y="19.2" width="15.6" height="3.2" rx="1.6"/><rect x="13.9" y="22.4" width="4.2" height="4.6" rx="1.1"/><circle cx="16" cy="28.3" r="2.45"/></g><path d="M16 2.2 L18.6 7 V19.2 H13.4 V7 Z" fill="%23f2f7fc"/><path d="M16 4 L17.7 7.3 V19.2 H16 Z" fill="%23a9b9c9"/><rect x="8.2" y="19.2" width="15.6" height="3.2" rx="1.6" fill="%23ffd77a"/><rect x="13.9" y="22.4" width="4.2" height="4.6" rx="1.1" fill="%237d4c24"/><circle cx="16" cy="28.3" r="2.45" fill="%23ffd77a"/></g></svg>');
}
.rpg.cur-mob #rpg-canvas {
  cursor: var(--cur-sword) 6 26, crosshair;
}
/* มีแรงดูดอยู่ = ดาบถูกวาดเองแล้ว ต้องซ่อนเคอร์เซอร์ระบบ ไม่งั้นเห็นดาบสองเล่ม
   ประกาศหลัง .cur-mob/.cur-npc/.cur-warp จึงชนะทุกตัวโดยไม่ต้องพึ่ง !important */
.rpg.cur-sword #rpg-canvas { cursor: none; }
/* sprite ดาบที่ JS ขยับเองทุกเฟรม — hotspot (6,26) ตรงกับที่ .cur-mob ประกาศไว้เป๊ะ
   ห้ามใส่ transition ให้ transform: ตำแหน่งถูกเขียนทุกเฟรมอยู่แล้ว หน่วงเมื่อไหร่ = ดาบตามเมาส์ไม่ทัน
   และห้ามใส่ transition ให้ opacity ด้วย (เคยมี .09s — ถอดออก 1 ส.ค. 2026):
   วินาทีที่สไปรต์ติด .on คือวินาทีเดียวกับที่ #rpg-canvas ถูกสั่ง cursor:none
   เคอร์เซอร์ระบบดับ "ทันที" แต่สไปรต์ยังจางอยู่ 90 มิลลิวิ = จอไม่มีดาบเลยชั่วขณะ
   อาการที่เห็นคือ "เลื่อนเมาส์ไปที่มอนแล้วดาบหายแวบแล้วกลับมา" — การสลับสองตัวนี้ต้องเป็นเฟรมเดียวจบ */
.swordcur {
  position: absolute; left: 0; top: 0; width: 32px; height: 32px; z-index: 25;
  background: var(--cur-sword) 0 0 / 32px 32px no-repeat;
  pointer-events: none; opacity: 0; will-change: transform;
}
.swordcur.on { opacity: 1; }
/* ฟาดแล้วดาบหายแวบ — ต้องอยู่หลัง .on (ความจำเพาะเท่ากัน ลำดับหลังชนะ) */
.swordcur.gone { opacity: 0; }

.rpg.cur-npc #rpg-canvas {
  cursor: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><g stroke="%23120d06" stroke-width="5.4" stroke-linejoin="round" fill="%23120d06"><path d="M5.5 6.5h21v14H15l-6.5 5.5v-5.5H5.5z"/></g><g stroke="%23bff0ff" stroke-width="2.2" stroke-linejoin="round" fill="%231d4a63"><path d="M5.5 6.5h21v14H15l-6.5 5.5v-5.5H5.5z"/></g><g fill="%23eaffff"><circle cx="11.5" cy="13.4" r="1.8"/><circle cx="16" cy="13.4" r="1.8"/><circle cx="20.5" cy="13.4" r="1.8"/></g></svg>') 6 6, pointer;
}
.rpg.cur-warp #rpg-canvas {
  cursor: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><g fill="none" stroke="%23120d06" stroke-width="5.4" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="16" cy="16" rx="6.4" ry="10.6"/><path d="M4.5 16h23"/><path d="M22.5 10.6l5.4 5.4-5.4 5.4"/></g><g fill="none" stroke="%237fe0ff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="16" cy="16" rx="6.4" ry="10.6"/><path d="M4.5 16h23"/><path d="M22.5 10.6l5.4 5.4-5.4 5.4"/></g></svg>') 16 16, pointer;
}

/* ── มือถือ: ปุ่มสัมผัสกับแผงเดิมอยู่มุมเดียวกัน ต้องหลบกัน ──────────
   ใช้ :has(.touchpad) เพื่อขยับเฉพาะตอนเปิดปุ่มสัมผัสจริง —
   เครื่องที่เล่นด้วยเมาส์จะได้ไม่โดนดันเลย์เอาต์ไปฟรี ๆ */
@media (max-width: 560px) {
  /* ปุ่มเมนูเตี้ย/แคบลงในจอแคบ — ประกาศที่ตัวแปรที่เดียว แผงกริดกับปุ่มจึงขยับพร้อมกัน
     --hud-row-h ต้องโตตาม เพราะแถวล่างจอแคบซ้อนสองบรรทัด (แชท + ฮอตบาร์ที่ห่อได้ 2 แถว)
     แล้ว --hud-above คิดตามเอง — ห้ามประกาศ --hud-above ทับที่นี่ */
  :root { --hud-menu-h: 40px; --hud-menu-w: 32px; --hud-chat-w: 210px;
          --hud-row-h: 208px; --hud-touch-b: 60px;
          /* แผงกลางจอเตี้ยลงนิดเดียวพอ — ห้ามหดจนตัวหนังสือหาย นั่นคือบั๊กที่รอบนี้แก้อยู่
             ความกว้างไม่ต้องประกาศทับ: --hud-menu-pw หดตาม 100vw เองอยู่แล้ว */
          --hud-menu-ph: 70px; }
  /* จอแคบ แผงตัวละคร+มินิแมปกินพื้นที่บนเกือบหมด — ป้ายชื่อแมปต้องหลบลงมา */
  .rpg .mapbanner { font-size: clamp(20px, 6.4vw, 30px); top: 30%; }
  /* แถบเดินทางที่ท็อปจะทับแผงตัวละคร → ย้ายลงมาอยู่เหนือแชท */
  .travelbar { top: auto; bottom: 196px; transform: translate(-50%, 10px); }
  .travelbar.on { transform: translate(-50%, 0); }
  .rpg:has(.touchpad) .travelbar { bottom: 226px; }
  .touchpad { width: 116px; height: 116px; }
  .touchpad > i { width: 50px; height: 50px; margin: -25px 0 0 -25px; }
  .touchacts { width: 120px; gap: 7px; }
  /* ตำแหน่งของแถวล่างมาจาก .ro-bottom ที่เดียวแล้ว — ที่นี่เหลือแค่ย่อความสูงแชทให้จอเตี้ย */
  /* ตั้งตัวแปรแทนการตั้ง height ตรง ๆ — ไม่งั้นทับสถานะย่อ/ขยายที่ผู้เล่นเลือกไว้ (.chat-s0/1/2) */
  .rpg:has(.touchpad) .ro-chat { --chat-h: 70px; }
  .rpg:has(.touchpad) .castbar { bottom: 208px; }
}

/* ── จอ ≤430px: ทุกหน้าต่างต้องอ่านออก ปุ่มกดถูก ไม่ล้นแนวนอน ──────── */
@media (max-width: 430px) {
  .winbox { width: 96vw; max-height: 90vh; }
  .win-body { padding: 7px; gap: 7px; }
  .winbox .card { padding: 8px; }
  .winbox .card .h { font-size: 12px; }
  .winbox button { min-height: 34px; padding: 6px 12px; }   /* เป้ากดนิ้วโป้ง */
  /* ปุ่มกลมบนแถบหัวต้องไม่โดน min-height ข้างบนยืดจนเบี้ยว */
  .winbox .win-h .win-btn { width: 22px; height: 22px; min-height: 0; padding: 0; }
  .winbox .win-h .win-btn .ro-ic { width: 11px; height: 11px; }
  .winbox .row { gap: 6px; }
  .winbox .skillcols { grid-template-columns: 1fr; }
  .winbox .equip-grid { grid-template-columns: 1fr; }
  .winbox .bag { grid-template-columns: repeat(auto-fill, minmax(66px, 1fr)); }
  .winbox .tb { font-size: 11.5px; }
  .winbox .tb th, .winbox .tb td { padding: 5px 4px; }
  .winbox .optrow > span:first-child { width: 100%; }       /* ป้ายขึ้นบรรทัดเอง ตัวคุมได้ความกว้างเต็ม */
  .winbox .codexrow, .winbox .craftrow { gap: 7px; }
  .winbox .rarrow { gap: 4px 10px; }
  .cc-mini { width: 26px; height: 26px; }
  .combo > b { font-size: 34px; }
  .combo > span { font-size: 10px; }
  .alertline { font-size: 11.5px; padding: 5px 12px; }
  .em-wheel { transform: translateX(-50%) scale(.86); }
  .travelbar { font-size: 11px; padding: 4px 10px; }
  .start-logo { width: 104px; height: 104px; }
  .start-logo .ro-ic { width: 60px; height: 60px; }
}

/* ── จอบาก (safe area) ──────────────────────────────────────────────
   index.html ประกาศ viewport-fit=cover ไว้แล้ว = โลก 3D กินเต็มขอบจอ
   แต่ HUD ที่ยึด 7px ตายตัวจะไปนอนใต้บาก/แถบโฮมของ iPhone — ขยับตามขอบปลอดภัย
   (คำนวณเป็น calc ไม่ใช่ padding เพราะทุกแผงวางด้วย position:absolute) */
@supports (top: env(safe-area-inset-top)) {
  /* ขอบปลอดภัยด้านล่างเข้าที่ตัวแปรเดียว — แถวล่างขยับตาม และ --hud-above ก็ขยับตามอัตโนมัติ
     (ของเดิมเขียน bottom ของ .ro-bottom ซ้ำสองกฎที่นี่ แล้ว --hud-above ไม่รู้เรื่องทั้งคู่) */
  :root { --hud-bottom-b: calc(var(--hud-edge) + env(safe-area-inset-bottom)); }
  :root:has(.touchpad) {
    --hud-bottom-b: calc(var(--hud-touch-b) + var(--hud-touch-stack) + var(--hud-gap) + env(safe-area-inset-bottom)); }
  .ro-char    { top: calc(7px + env(safe-area-inset-top)); left: calc(7px + env(safe-area-inset-left)); }
  .ro-map     { top: calc(7px + env(safe-area-inset-top)); right: calc(7px + env(safe-area-inset-right)); }
  .ro-quest   { top: calc(200px + env(safe-area-inset-top)); right: calc(7px + env(safe-area-inset-right)); }
  /* แถวล่างขยับกล่องเดียวจบ — แชท/ฮอตบาร์/ปุ่มเมนูอยู่ในกริดนี้ ไม่ต้องขยับทีละอัน
     (ของเดิมสามอันต่างคนต่างบวก env() เอง พลาดตัวใดตัวหนึ่งเมื่อไหร่ก็กลับมาทับกัน) */
  .ro-bottom  { left: calc(var(--hud-edge) + env(safe-area-inset-left));
                right: calc(var(--hud-edge) + env(safe-area-inset-right)); }
  .touchpad   { left: calc(14px + env(safe-area-inset-left)); bottom: calc(14px + env(safe-area-inset-bottom)); }
  .touchacts  { right: calc(12px + env(safe-area-inset-right)); bottom: calc(var(--hud-touch-b) + env(safe-area-inset-bottom)); }
  .alertline  { top: env(safe-area-inset-top); }
  .em-wheel   { bottom: calc(92px + env(safe-area-inset-bottom)); }
}

/* เก็บรายละเอียดเล็ก ๆ */
.em-wheel > .em-btn span { max-width: 48px; }          /* ป้ายยาว ("ไปกันเลย") ไม่ล้นออกนอกวงกลม */
.combo > b { will-change: transform; }                  /* เด้งทุกครั้งที่ต่อคอมโบ — กันเฟรมกระตุกตอนสู้ */
.ro-slot, .ro-menu button, .ro-menu-items button, .touchacts > button { -webkit-tap-highlight-color: transparent; }

/* ═══════════════════════════════════════════════════════════════════
   RO WINDOW KIT — ระบบกลางของหน้าต่างทุกบาน (เพิ่ม 31 ก.ค.)
   วางไว้ "หลัง" บล็อก POLISH PASS ได้ เพราะเป็นชื่อคลาสใหม่ทั้งชุด
   ไม่ไปทับกฎ HUD ของ POLISH PASS · ส่วนที่ตั้งใจทับคือกรอบหน้าต่างเท่านั้น
   คู่กับ itemSlot() / tipBox() ใน js/rpg/icons.js — แก้หน้าตาช่องไอเทมทั้งเกมที่นี่ที่เดียว
   ═══════════════════════════════════════════════════════════════════ */

/* ── กรอบหน้าต่างแบบ RO: ขอบหนามีมิติ + หัวมีแถบสี + พื้นมีเนื้อ ────
   ของเดิมเป็นการ์ดขาวเรียบเหมือนฟอร์มเว็บ · ยังคุมให้สว่างสดใสตามกฎบริษัท
   (ห้ามอึมครึม) แค่เพิ่ม "น้ำหนัก" ให้ดูเป็นเกม ไม่ใช่หน้าเว็บ */
.winbox {
  border: 1px solid #6d6252;
  border-radius: 5px;
  box-shadow: inset 0 0 0 1px #fffdf6, inset 0 0 0 2px #cfc4ac,
              0 18px 46px #000b, 0 0 0 1px #00000060;
  /* พื้นมีเนื้อกระดาษบาง ๆ — ไล่สีทแยงสองชั้น ไม่ใช้ไฟล์ภาพ (ไม่มี request เพิ่ม) */
  background:
    repeating-linear-gradient(135deg, #ffffff00 0 3px, #00000006 3px 6px),
    linear-gradient(#f7f4ec, #eae5d8);
}
.winbox .win-h {
  padding: 5px 6px 5px 10px;
  background: linear-gradient(#fdf6e2 0%, #f0dfb4 48%, #dfc98c 52%, #cbb072 100%);
  border-bottom: 1px solid #9a8759;
  box-shadow: inset 0 1px 0 #fffdf2, inset 0 -1px 0 #ffffff5c;
}
.winbox .win-h b { color: #4a3a18; text-shadow: 0 1px 0 #fffdf299; }
.winbox .win-h .ro-ic { color: #7a6428; }
.winbox .win-body {
  background: transparent;
  padding: 9px;
  scrollbar-width: thin;
}
/* แถบเลื่อนให้เข้าชุดไม้/ทอง — WebKit เท่านั้น เบราว์เซอร์อื่นใช้ scrollbar-width ข้างบน */
.winbox .win-body::-webkit-scrollbar { width: 9px; }
.winbox .win-body::-webkit-scrollbar-track { background: #e2dccb; border-radius: 4px; }
.winbox .win-body::-webkit-scrollbar-thumb {
  background: linear-gradient(#c9b688, #a8946a); border-radius: 4px; border: 1px solid #8d7a4f;
}
/* การ์ดในหน้าต่าง — ขอบนูนบางๆ ให้แยกชั้นจากพื้นหน้าต่างได้ด้วยตา ไม่ต้องอ่าน */
.winbox .card {
  background: linear-gradient(#ffffff, #fbf9f3);
  border: 1px solid #c3b89f;
  border-radius: 3px;
  box-shadow: 0 1px 0 #ffffffcc inset, 0 1px 2px #00000012;
}
.winbox .card .h { border-bottom: 1px solid #e3dcc9; }
/* ปุ่มมีขอบนูน — กดแล้วยุบลงจริง ให้รู้สึกว่าเป็นปุ่มเกม ไม่ใช่ปุ่มฟอร์ม */
.winbox button {
  border-radius: 3px; border-color: #8d7f63;
  background: linear-gradient(#fffdf6 0%, #f2ebd9 52%, #e3d9be 100%);
  box-shadow: inset 0 1px 0 #ffffff, inset 0 -1px 0 #00000014, 0 1px 1px #00000018;
}
.winbox button:hover:not(:disabled) {
  background: linear-gradient(#ffffff 0%, #fbf3dd 52%, #efe4c4 100%); border-color: #b08f45;
}
.winbox button:active:not(:disabled) {
  background: linear-gradient(#ddd3b8, #f0e9d6); box-shadow: inset 0 2px 3px #00000030;
  transform: translateY(1px);
}
/* หัวหน้าต่างลากได้จริงแล้ว (ui.js) — บอกด้วยเคอร์เซอร์ให้ตรงกับพฤติกรรม */
.winbox.dragged { animation: none; }

/* ── ช่องไอเทมกลาง .islot — กริดสี่เหลี่ยม กรอบสีตามความหายาก ──────
   พื้นช่อง = เทียร์ (สำริด/เหล็ก/เหล็กกล้า/คริสตัล/อสูรกาย)
   กรอบช่อง = ความหายาก (ธรรมดา→อมตะ) · สองแกนนี้อ่านพร้อมกันได้ในแวบเดียวแบบ RO */
.islot {
  position: relative; box-sizing: border-box;
  width: 38px; height: 38px; flex: 0 0 auto;
  display: grid; place-items: center;
  border: 2px solid #9a9284; border-radius: 3px;
  background: linear-gradient(150deg, #fdfbf4, #e6e0d0);
  box-shadow: inset 0 1px 0 #ffffff9e, 0 1px 2px #00000024;
}
.islot .islot-ic { width: 24px; height: 24px; color: #fff; filter: drop-shadow(0 1px 1px #0007); }
.islot.plain .islot-ic { color: #5f5748; filter: none; }
.islot .ico { display: block; }                                  /* รูปสินค้าจากแผ่นไอคอน */
.islot.empty { border-style: dashed; border-color: #bdb6a6; background: #f4f2ea; box-shadow: none; }
.islot.empty .islot-ic { color: #b9b2a2; filter: none; }
.islot.lg { width: 52px; height: 52px; }
.islot.lg .islot-ic { width: 32px; height: 32px; }
/* ป้ายตีบวก (ซ้ายบน) กับจำนวน (ขวาล่าง) — ตำแหน่งเดียวกับ RO ตาไปหาถูกที่ทันที */
.islot-plus {
  position: absolute; left: -3px; top: -3px; font-style: normal;
  font-size: 8.5px; font-weight: 700; line-height: 1.15; padding: 1px 2px;
  color: #fff3c9; background: #96261c; border: 1px solid #ffd77a; border-radius: 2px;
}
.islot-qty {
  position: absolute; right: -3px; bottom: -3px;
  font-size: 9px; font-weight: 700; line-height: 1.15; padding: 1px 2px;
  color: #fffdf2; background: #2f2a20e0; border: 1px solid #d8c78a; border-radius: 2px;
  font-variant-numeric: tabular-nums;
}
/* กรอบตามความหายาก 6 ระดับ — ต้องครบทุกระดับที่ RARITY ใน items.js มีจริง */
.islot.rar-b-common    { border-color: #a49b8a; }
.islot.rar-b-uncommon  { border-color: #3f9a63; box-shadow: inset 0 1px 0 #ffffff9e, 0 0 0 1px #b6e7c9, 0 1px 2px #00000024; }
.islot.rar-b-rare      { border-color: #3a72b8; box-shadow: inset 0 1px 0 #ffffff9e, 0 0 0 1px #bcd9f7, 0 1px 2px #00000024; }
.islot.rar-b-epic      { border-color: #c08a1a; box-shadow: inset 0 1px 0 #ffffff9e, 0 0 0 1px #ffe6a8, 0 1px 3px #a8741a55; }
.islot.rar-b-legendary { border-color: #d1601c; box-shadow: inset 0 1px 0 #ffffff9e, 0 0 0 1px #ffd2a3, 0 0 8px #ff8a3c66; }
.islot.rar-b-mythic    { border-color: #a4239a; box-shadow: inset 0 1px 0 #ffffff9e, 0 0 0 1px #f3bdef, 0 0 9px #d84fce77; }
/* ช่องที่มีรายละเอียดให้ดู — เคอร์เซอร์ต้องบอกว่า "ชี้แล้วมีอะไร"
   (ช่องที่อยู่ในการ์ดกระเป๋าไม่ได้ถือ data-tip เอง — ตัวการ์ด .bagit ถืออยู่แล้ว) */
.islot[data-tip] { cursor: help; }
.islot[data-tip]:hover, .bagit[data-tip]:hover .islot { filter: brightness(1.08); }
/* ช่องในกระเป๋าเว้นที่ให้ป้ายจำนวนที่ล้นมุมช่อง ไม่งั้นโดนขอบการ์ดตัด */
.winbox .bagit .islot { margin: 2px 3px 3px 2px; }

/* ── กล่องรายละเอียด (tooltip) — ลอยระดับ body ──────────────────────
   สำคัญ: ต้องอยู่ "นอก" #win เพราะ drawWin() เขียนเนื้อหน้าต่างใหม่ทั้งก้อนทุกครั้งที่กดอะไร
   ถ้าเกิดอยู่ในหน้าต่าง มันจะโดนลบทิ้งกลางทางทุกครั้ง (บั๊กที่ทำให้ทูลทิปใช้ไม่ได้จริง) */
.ro-tip {
  position: fixed; left: 0; top: 0; z-index: 90; max-width: min(78vw, 268px);
  padding: 7px 9px 8px; border-radius: 3px; pointer-events: none;
  opacity: 0; visibility: hidden; transform: translateY(2px);
  transition: opacity .1s ease-out, transform .1s ease-out;
  border: 1px solid #6d6252; color: #2a2418; font-size: 11.5px; line-height: 1.5;
  background: linear-gradient(#fffdf5, #f0ead9);
  box-shadow: inset 0 0 0 1px #fffdf6, 0 10px 26px #0009;
}
.ro-tip.on { opacity: 1; visibility: visible; transform: translateY(0); }
.ro-tip .tip-head { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.ro-tip .tip-name { font-size: 13px; font-weight: 700; }
.ro-tip .tip-rar { font-style: normal; font-size: 10.5px; }
.ro-tip .tip-sub { color: #6d6455; font-size: 10.5px; margin-top: 1px; }
.ro-tip .tip-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }
.ro-tip .tip-tag {
  font-size: 10px; padding: 1px 6px; border-radius: 2px;
  background: #e7e0cd; border: 1px solid #cbc0a4; color: #5c5340;
}
.ro-tip .tip-tag.good { background: #dcefe2; border-color: #a6cdb4; color: #2c7a4b; }
.ro-tip .tip-tag.bad  { background: #f7dfdc; border-color: #dcaea8; color: #a3291f; }
.ro-tip .tip-tag.warn { background: #fbeecd; border-color: #ddc484; color: #8a5f0a; }
.ro-tip .tip-rows {
  display: grid; grid-template-columns: auto 1fr; gap: 1px 10px;
  margin-top: 6px; padding-top: 5px; border-top: 1px solid #ddd4bd;
}
.ro-tip .tip-k { color: #6d6455; font-size: 10.5px; }
.ro-tip .tip-v { font-weight: 700; font-variant-numeric: tabular-nums; text-align: right; }
.ro-tip .tip-desc {
  margin-top: 6px; padding-top: 5px; border-top: 1px solid #ddd4bd;
  color: #5b5240; font-style: italic;
}
.ro-tip .tip-foot { margin-top: 5px; font-size: 10.5px; color: #6d6455; }

/* ── ร้าน/ตลาดแบบ RO — แถวสินค้ามีรูปของจริงให้เห็นว่ากำลังซื้ออะไร ──
   เดิมเป็นแถวตัวหนังสือล้วน ผู้เล่นต้องอ่านชื่อถึงจะรู้ว่าซื้ออะไรอยู่ */
/* เส้นคั่นใส่ที่ "แถวที่ตามหลังแถวสินค้าด้วยกัน" ไม่ใช่ :first-of-type
   :first-of-type นับตาม tag ไม่ใช่ตาม class — พี่น้อง <div> ตัวแรกในการ์ดคือหัวข้อ .h เสมอ
   กฎเดิมจึงไม่เคยแมตช์แถวไหนเลย และแถวสินค้าแถวแรกก็มีเส้นคั่นเกินมาตลอด */
.winbox .shoprow {
  display: grid; grid-template-columns: auto 1fr auto; gap: 9px; align-items: center;
  padding: 7px 0;
}
.winbox .shoprow + .shoprow { border-top: 1px solid #e6ddc8; }
.winbox .shoprow:hover { background: #fffaea; }
.winbox .shop-name { min-width: 0; }
/* ลูกตรง ๆ เท่านั้น — ไม่งั้น <b> ราคาที่อยู่ในบรรทัดย่อยกลายเป็นบล็อก แล้วราคาตกบรรทัดแยกจากคำว่า "ซื้อ" */
.winbox .shop-name > b { display: block; font-size: 12.5px; }
/* ประกาศครั้งเดียวที่นี่เท่านั้น — เดิมมีอีกก้อนอยู่ "หลัง" กฎจอแคบ ทำให้กฎจอแคบถูกทับเงียบ ๆ */
.winbox .shop-buy { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 5px; }
.winbox .shop-buy input[type=number] { width: 62px; }
.winbox .shop-price {
  font-variant-numeric: tabular-nums; font-weight: 700; color: #9a6f10;
  font-size: 13px; white-space: nowrap;
}
.winbox .shop-trend { display: inline-flex; align-items: center; gap: 1px;
  font-size: 10px; font-style: normal; font-weight: 400; margin-left: 4px; vertical-align: 1px; }
.winbox .shop-trend .ro-ic { width: 9px; height: 9px; }
/* ชื่อคลาสห้ามใช้ .up/.down — ชนกับ .winbox .up (ปุ่มบวกสเตตัส) แล้วเด้งกรอบปุ่มขึ้นรอบลูกศร */
.winbox .shop-trend.rise { color: #a3291f; }      /* ราคาขึ้น = ขายดี (แดงแบบกราฟหุ้นไทย) */
.winbox .shop-trend.fall { color: #2c7a4b; }
.winbox .shop-meter { display: block; height: 5px; margin-top: 3px; border-radius: 3px;
  background: linear-gradient(90deg, #7fb4e0, #ffd77a, #e08a6a); position: relative; }
.winbox .shop-meter i { position: absolute; top: -2px; width: 3px; height: 9px; margin-left: -1.5px;
  background: #2a2418; border-radius: 1px; box-shadow: 0 0 0 1px #fffdf2; }
@media (max-width: 430px) {
  .winbox .shoprow { grid-template-columns: auto 1fr; }
  .winbox .shop-buy { grid-column: 1 / -1; justify-content: flex-end; }
  .ro-tip { max-width: 86vw; font-size: 12px; }
}
/* ช่องในกระเป๋าก็ชี้ดูรายละเอียดได้ (data-tip เดียวกับ .islot) */
.winbox .bagit[data-tip] { cursor: help; }
.winbox .bagit[data-tip]:hover { border-color: #b08f45; background: #fffaea; }

/* ── บรรทัด "ราคา/ได้อะไร" ในแถวสินค้า ──
   วางไว้ในคอลัมน์ชื่อ ไม่ใช่ฝั่งปุ่ม เพราะฝั่งปุ่มต้องกว้างคงที่ ไม่งั้นปุ่มซื้อ-ขายเต้นไปมาตามความยาวราคา */
.winbox .shop-px { display: block; font-size: 11.5px; line-height: 1.55; }
.winbox .shop-px i { font-style: normal; }
/* รายละเอียดค่าใช้จ่ายย่อยลงบรรทัดของตัวเอง — ต่อท้ายราคาแล้วบรรทัดยาวจนราคาหลักหาไม่เจอ
   (ต้องเจาะจงคลาสนี้ ห้ามใช้ .shop-px i ทั้งหมด — ลูกศรราคาขึ้น/ลงก็เป็น <i> แล้วจะโดนดันลงบรรทัดใหม่ด้วย) */
.winbox .shop-sub { display: block; font-size: 10.5px; color: #6d6455; }
.winbox .shop-sep { color: #b0a894; margin: 0 3px; }
/* ชื่อของในแถวสินค้าเวลาชื่อมาเป็น HTML สำเร็จรูป (itemName คืน <b class="rar-…"> มาแล้ว)
   ห้ามเอาไปห่อ <b> ซ้อนอีกชั้น — เลยต้องมีคลาสของตัวเองแทนกฎ .shop-name > b */
.winbox .shop-nm { display: block; font-size: 12.5px; }
/* ป้ายอัตราสำเร็จ — กฎบริษัท "อัตราต้องเปิดเผย" แปลว่าต้องเห็นก่อนกด ไม่ใช่ซุกในบรรทัดเทาเล็ก
   สีบอกความเสี่ยงก่อนสมองอ่านตัวเลขทัน */
.winbox .rate-pill {
  display: inline-block; font-size: 11px; font-weight: 700; line-height: 1.5;
  padding: 1px 8px; border-radius: 2px; white-space: nowrap;
  font-variant-numeric: tabular-nums;
  background: #e7e0cd; border: 1px solid #cbc0a4; color: #5c5340;
}
.winbox .rate-pill.good { background: #dcefe2; border-color: #a6cdb4; color: #1f6b3e; }
.winbox .rate-pill.warn { background: #fbeecd; border-color: #ddc484; color: #8a5f0a; }
.winbox .rate-pill.bad  { background: #f7dfdc; border-color: #dcaea8; color: #a3291f; }
/* ของที่ใส่อยู่ในกริดกระเป๋า — ต้องแยกออกจากของในกองด้วยตา ไม่ใช่ด้วยการอ่าน */
.winbox .bagit.on { border-color: #a6cdb4; background: #f2faf4; }
/* ยอดรวมสดตอนพิมพ์จำนวน — กินเต็มความกว้าง "ของทั้งแถว" ไม่ใช่ของคอลัมน์ปุ่ม
   ถ้าอยู่ในคอลัมน์ปุ่ม ความยาวข้อความจะไปดันคอลัมน์นั้นให้กว้าง แล้วบีบชื่อ/ราคาจนตกบรรทัด */
.winbox .shop-live {
  grid-column: 1 / -1; text-align: right; font-size: 10.5px; color: #6d6455;
  font-variant-numeric: tabular-nums; min-height: 13px; margin-top: -2px;
}
/* หลอด "คุ้มแค่ไหน" ของครัว — ยาวกว่า = คุ้มกว่า (คนละความหมายกับหลอดราคาที่เป็นหมุดชี้ตำแหน่ง) */
.winbox .shop-meter.eff { background: #e7e0cd; overflow: hidden; }
.winbox .shop-meter.eff i {
  top: 0; left: 0; height: 5px; margin-left: 0; border-radius: 3px;
  background: linear-gradient(90deg, #bcd9a4, #5f9f46); box-shadow: none;
}

/* ── รายชื่อของในตู้สุ่ม — เดิมเป็นตัวหนังสือล้วน ตอนนี้เป็นช่องมีรูปชี้ดูได้ ── */
.winbox .gac-pool {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(74px, 1fr)); gap: 8px 6px;
}
.winbox .poolit {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  text-align: center; line-height: 1.3;
}
.winbox .poolit b { font-weight: 600; word-break: break-word; }
.winbox .poolit i { font-style: normal; }

/* มุมหน้าต่างบนจอแคบ — ต้องอยู่ "หลัง" บล็อก RO WINDOW KIT ที่ตั้ง border-radius: 5px ไว้
   ไม่งั้นกฎจอแคบถูกกินเงียบ ๆ เพราะความจำเพาะเท่ากันแล้วลำดับหลังชนะ (test/audit.js เฝ้าข้อนี้อยู่)
   จอ ≤430px หน้าต่างกว้าง 96vw เกือบเต็มจอ — มุมมนเยอะทำให้ดูเหมือนการ์ดลอย ไม่ใช่หน้าต่างเต็มจอ */
@media (max-width: 430px) { .winbox { border-radius: 2px; } }

/* ── แถบบอกสถานะบอทฟาร์ม ─────────────────────────────────────────────
   วางใต้แถบเดินทางอัตโนมัติ (top 46 + สูงแถบ ≈ 30) — สองแถบขึ้นพร้อมกันได้ ห้ามทับกัน
   เป็น selector ใหม่ล้วน ไม่ทับกฎไหนที่ @media ตั้งไว้ (กฎ audit ข้อ 3.6) */
.botbar {
  position: absolute; left: 50%; top: 82px; transform: translate(-50%, -10px);
  z-index: 20; display: flex; align-items: center; gap: 8px;
  white-space: nowrap; max-width: calc(100vw - 20px);
  padding: 5px 12px; border-radius: 4px; font-size: 11.5px;
  background: linear-gradient(var(--h-bg-2), var(--h-bg));
  border: 1px solid var(--h-line); box-shadow: var(--h-inset), var(--h-drop);
  opacity: 0; pointer-events: none;
  transition: opacity .22s ease-out, transform .22s ease-out;
}
.botbar.on { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.botbar b { color: #8ad86a; }
.botbar .ro-ic { color: #8ad86a; width: 15px; height: 15px; }
.botbar button {
  min-height: 28px; padding: 3px 10px; font-size: 11px; border-radius: 3px;
  color: var(--h-ink2); background: #1c150cd0; border: 1px solid var(--h-line); cursor: pointer;
}
.botbar button:hover { border-color: var(--h-edge); color: #fff0c0; }

/* ── ปุ่มในแผงภารกิจมุมขวา ── */
.qgo {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px; border-radius: 4px; font: 700 10.5px/1.3 inherit; cursor: pointer;
  color: var(--h-gold); background: #1c150cd0; border: 1px solid var(--h-line);
}
.qgo.ghost { color: var(--h-ink2); }
.qgo:hover { border-color: var(--h-edge); color: #fff0c0; }
.qgo .ro-ic { width: 12px; height: 12px; }

/* ── สมุดภารกิจ (หน้าต่างใน ui.js) ── */
.winbox .qlist { display: flex; flex-direction: column; gap: 7px; }
.winbox .qitem {
  display: flex; align-items: flex-start; gap: 8px; padding: 7px 9px;
  border-radius: 4px; background: #00000030; border: 1px solid var(--h-line);
}
.winbox .qitem.ready { border-color: #6fae4e; background: #14200e60; }
.winbox .qitem.done { opacity: .55; }
.winbox .qitem .qmain { flex: 1 1 auto; min-width: 0; }
.winbox .qitem .qname { font-weight: 700; }
.winbox .qitem .qmeta { display: block; font-size: 10.5px; line-height: 1.55; }
.winbox .qitem .qacts { display: flex; flex-direction: column; gap: 4px; flex: 0 0 auto; }
.winbox .qbadge {
  display: inline-block; padding: 1px 6px; border-radius: 3px; font-size: 10px; font-weight: 700;
  background: #00000050; border: 1px solid var(--h-line); color: var(--h-ink2);
}
.winbox .qbadge.ready { color: #b8f08a; border-color: #6fae4e; }
.winbox .qbadge.active { color: #9ed0ff; }
.winbox .qbadge.locked { color: #b08a8a; }

/* จอแคบ: แถบบอทต้องหลบแผงตัวละคร/มินิแมปเหมือนแถบเดินทาง แล้วซ้อนกันเป็นสองแถวเหนือแชท
   วางไว้ท้ายไฟล์สุด — กฎ audit ข้อ 3.6 ห้ามมีการประกาศทับ "หลัง" @media ของตัวเอง */
@media (max-width: 560px) {
  .botbar { top: auto; bottom: 160px; transform: translate(-50%, 10px); }
  .botbar.on { transform: translate(-50%, 0); }
  .rpg:has(.touchpad) .botbar { bottom: 190px; }
}

/* ═══════════ หน้าเลือกตัวละคร (Character Select) ═══════════
   ใช้ฉาก .start-screen เดิมเป็นพื้น (ภาพคีย์อาร์ต + โลโก้) แล้ววางการ์ดช่องตัวละครทับ
   วางท้ายไฟล์ตามกฎ audit 3.6 — ห้ามประกาศทับ @media ที่อยู่ก่อนหน้า */
.cs-screen { align-items: flex-start; overflow: auto; padding: 3vh 12px 24px; }
.cs-box { width: min(96vw, 760px); padding: 18px 8px; }
.cs-slots { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; width: 100%; margin-top: 14px; }
.cs-card { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 12px 10px;
  border-radius: 12px; text-align: center; cursor: pointer;
  background: linear-gradient(#1d2c3c, #16212e); border: 1px solid #3a5a74;
  box-shadow: 0 2px 0 #0d1620, 0 8px 18px #0007; transition: transform .12s, border-color .12s; }
.cs-card:hover { border-color: #d9a441; transform: translateY(-2px); }
.cs-blank { background: #16202bcc; border-style: dashed; }
.cs-pic { width: 92px; height: 116px; display: grid; place-items: center; flex: 0 0 auto;
  border-radius: 8px; border: 1px solid #2c4459;
  background: radial-gradient(70% 70% at 50% 28%, #2b425a, #16212e 78%); }
.cs-pic .ro-ic { width: 42px; height: 42px; color: #4d6c88; }
.cs-ghost { opacity: .9; }
.cs-face { width: 84px; height: 112px; object-fit: contain; object-position: bottom center; }
.cs-info { display: flex; flex-direction: column; gap: 2px; width: 100%; min-width: 0; }
.cs-name { font-size: 15px; color: #ffe6a3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cs-line { font-size: 11.5px; color: #b8cfe0; }
.cs-when { font-size: 10.5px; color: #7a93a8; }
.cs-btns { display: flex; flex-direction: column; gap: 5px; width: 100%; margin-top: 2px; }
.cs-go { padding: 8px 10px; font: inherit; font-size: 13.5px; font-weight: 700; border: 0; border-radius: 9px;
  background: linear-gradient(#f0c25a, #d09b2c); color: #241a03; cursor: pointer; }
.cs-go:active { transform: translateY(1px); }
.cs-del { padding: 5px 8px; font: inherit; font-size: 11px; border-radius: 8px; cursor: pointer;
  background: #22303f; color: #9db4c6; border: 1px solid #3a5a74; }
.cs-del:hover { color: #ffb4a8; border-color: #8a4740; }
.cs-acts { margin-top: 12px; }
.cs-acct { margin-top: 8px; font-size: 11.5px; color: #9db4c6; text-decoration: underline; }
.cs-acct:hover { color: #ffe6a3; }

/* จอแคบ: การ์ดเรียงลงมาใบละแถว — รูปซ้าย/ข้อมูลขวา ส่วนปุ่มลงไปกินเต็มความกว้างข้างล่าง
   (เคยวางปุ่มไว้ข้างขวาแบบเดสก์ท็อป แล้วช่องข้อความเหลือแคบจนชื่อเมืองตัดเป็น 4 บรรทัด) */
@media (max-width: 560px) {
  .cs-slots { grid-template-columns: 1fr; }
  .cs-card { display: grid; grid-template-columns: 62px minmax(0, 1fr);
    grid-template-areas: "pic info" "btns btns"; align-items: center; text-align: left; gap: 8px 10px; }
  .cs-pic { grid-area: pic; width: 62px; height: 78px; }
  .cs-pic .ro-ic { width: 30px; height: 30px; }
  .cs-face { width: 56px; height: 74px; }
  .cs-info { grid-area: info; width: auto; }
  .cs-name { font-size: 14px; }
  .cs-line { font-size: 11px; }
  .cs-btns { grid-area: btns; flex-direction: row; width: 100%; margin-top: 0; }
  .cs-go { flex: 1 1 auto; font-size: 12.5px; padding: 8px 10px; }
  .cs-del { flex: 0 0 auto; padding: 6px 12px; }
}

/* ═══════════ โหมดผูกคีย์ — ลากสกิลจากผังสกิลมาวางช่องคีย์ลัด ═══════════
   เปิดตอนหน้าต่าง "ผังสกิล" เปิดอยู่เท่านั้น (rpgui.js แปะ .hb-bind ให้ที่ .rpg)
   สามข้อที่กฎชุดนี้แก้:
   1) ฮอตบาร์ z-index 16 นอนอยู่ใต้ฉากหลังหน้าต่าง (.winbg 60) — ต้องยกขึ้นเหนือกล่องหน้าต่าง (61)
   2) จอแคบซ่อนช่องว่างไว้ (.ro-slot.empty display:none) — ช่องว่างคือเป้าหลักของการลาก ต้องโผล่ครบ
   3) นิ้วลากบนปุ่มต้องไม่กลายเป็นการเลื่อนจอ — touch-action:none เฉพาะตอนอยู่ในโหมดนี้
   ห้ามใส่ position/bottom/width/max-width ในกฎที่ลงท้ายด้วย .ro-hotwrap/.ro-hotbar
   (test/rpg-hud.js คุมแถวล่างอยู่ — ฮอตบาร์ต้องอยู่ในกริด .ro-bottom เสมอ)
   ยกทั้ง .ro-bottom ไม่ใช่ยกเฉพาะฮอตบาร์: ฮอตบาร์เป็นลูกในกริดแล้ว z-index ของมันเอง
   ถูกขังอยู่ในบริบทซ้อนของ .ro-bottom (z-index 16) ยังไงก็ไม่พ้นฉากหลังหน้าต่าง (60) */
.rpg.hb-bind .ro-bottom { z-index: 62; }
.rpg.hb-bind .ro-slot { touch-action: none; }
.rpg.hb-bind .ro-slot.hb-t { cursor: grab; }
.rpg.hb-bind .ro-slot.empty { display: flex; opacity: .8; border-style: dashed; }
.rpg.hb-bind .ro-slot.drop { border-color: #7fe0ff; border-style: solid; opacity: 1;
  box-shadow: 0 0 0 2px #7fe0ff55, 0 0 14px #7fe0ff66; }

/* ตอนลากจริง: หรี่กล่องหน้าต่างแล้วปล่อยให้คลิกทะลุ — จอแคบหน้าต่างสูง 90vh ทับฮอตบาร์อยู่
   ถ้าไม่ปิด pointer-events ตรงนี้ elementFromPoint จะเจอแต่หน้าต่าง วางบนมือถือไม่ได้เลย */
body.hb-dragging .winbox { opacity: .28; pointer-events: none; }
body.hb-dragging { cursor: grabbing; }

/* จุดจับ = ไอคอนสกิลอย่างเดียว (ที่เหลือของแถวยังใช้นิ้วเลื่อนรายการได้ตามปกติ) */
.sk-ic.grab { cursor: grab; touch-action: none; -webkit-user-drag: none; user-select: none; }
.sk-ic.grab:active { cursor: grabbing; }
.winbox .bindhint { align-items: flex-start; gap: 7px; }
.winbox .bindhint .ro-ic { color: #9a6f10; flex: 0 0 auto; margin-top: 1px; }

/* เงาสกิลที่ลอยตามนิ้ว — ต้องไม่กินคลิก ไม่งั้น elementFromPoint เจอแต่ตัวมันเอง */
.sk-ghost {
  position: fixed; z-index: 90; pointer-events: none; transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: 6px; padding: 5px 9px;
  background: #10131af2; border: 1px solid #7fe0ff; border-radius: 6px;
  color: var(--h-ink); font-size: 11.5px; box-shadow: 0 6px 18px #000a;
}
.sk-ghost .ro-ic { color: #7fe0ff; }

/* ── ตั้งคีย์ลัดเอง (หน้าตัวเลือก) ── */
/* ปุ่มแสดงคีย์ปัจจุบัน กดแล้วเข้าโหมดรอรับปุ่ม — ต้องกว้างคงที่ ไม่งั้นพอข้อความเปลี่ยนเป็น
   "กดปุ่มที่ต้องการ…" ทั้งแถวจะกระตุกกว้างขึ้นแล้วเลย์เอาต์ทั้งการ์ดขยับตาม */
.keyrow .grow { display: flex; align-items: center; gap: 8px; }
.keybtn { min-width: 118px; font-weight: 700; font-variant-numeric: tabular-nums; }
.keybtn.wait { border-color: var(--h-edge); color: var(--h-strong);
  background: var(--h-hover); animation: keywait 1s ease-in-out infinite; }
@keyframes keywait { 50% { opacity: .55; } }
.keyrow .ghost.small { font-size: 11px; padding: 3px 8px; }

/* ══════════════════════════════════════════════════════════════════════════
   โฉมใหม่: สเตตัส · ผังสกิล · สวมใส่ (คำสั่ง Stamp 1 ส.ค. 2026
   "ออกแบบใหม่ให้หมด ให้ดูดีกว่านี้ แล้วอย่าลืม keep theme ขาวฟ้า")

   จำกัดขอบเขตด้วย [data-win] ทั้งบล็อก — กระเป๋าเพิ่งถูกออกแบบใหม่ไปแล้ว
   แตะพาเลตกลาง (--w-*) เมื่อไหร่ก็ลากบานนั้นเปลี่ยนตามไปด้วย ซึ่งไม่ใช่สิ่งที่สั่ง

   ปัญหาที่แก้ (ดูจากภาพที่ยิงไปให้ Stamp):
   1) ทั้งสามบานเป็น "เทา-ขาว" ส่วนสกิลที่เรียนแล้วเป็น "ทองอำพัน" — หลุดธีมขาวฟ้าทั้งคู่
   2) ผังสกิล: ข้อความช่วยเหลือกินพื้นที่เกือบครึ่งบาน · ไอคอนเล็กกว่าปุ่ม + · ลำดับสายตาไม่มี
   3) สเตตัส: สองคอลัมน์ลอย ๆ ไม่มีอะไรบอกว่าฝั่งขวาคือ "ผลลัพธ์" ของฝั่งซ้าย
   4) สวมใส่: ช่องว่างกับช่องมีของหน้าตาใกล้กันเกินไป
   ══════════════════════════════════════════════════════════════════════════ */
#win .winbox[data-win="stats"],
#win .winbox[data-win="skills"],
#win .winbox[data-win="equip"] {
  --w-body:   #eff5fc;          /* พื้นบานอมฟ้าอ่อน แทนเทากลาง */
  --w-cell:   #ffffff;
  --w-line-2: #c3d7ea;
  --w-accent: #2f7fd0;
}
#win .winbox[data-win="stats"] .win-body,
#win .winbox[data-win="skills"] .win-body,
#win .winbox[data-win="equip"] .win-body { background: var(--w-body); }
/* หัวการ์ด: แถบฟ้าอ่อนเต็มความกว้าง แทนเส้นใต้บาง ๆ — อ่านออกทันทีว่าแบ่งเป็นกี่ส่วน */
#win .winbox[data-win="stats"] .card > .h,
#win .winbox[data-win="skills"] .card > .h,
#win .winbox[data-win="equip"] .card > .h {
  background: linear-gradient(#f4f9ff, #e4eefb);
  border-bottom: 1px solid #cfe0f2;
  margin: -9px -10px 8px; padding: 7px 10px; border-radius: 2px 2px 0 0;
  color: #17293d;
}
#win .winbox[data-win="stats"] .card,
#win .winbox[data-win="skills"] .card,
#win .winbox[data-win="equip"] .card { border-color: #c3d7ea; }

/* ── ผังสกิล ─────────────────────────────────────────────────────────────
   แถวสกิลเดิม: ไอคอน 24px ลอยซ้าย · ชื่อ/คำอธิบาย/ปุ่ม เรียงกันแบบไม่มีคอลัมน์
   ใหม่: กริด 3 คอลัมน์ตายตัว (ไอคอน 44 | เนื้อ | ปุ่ม) — ทุกแถวปุ่มตรงกันหมด อ่านเป็นตาราง */
#win .winbox[data-win="skills"] .sk {
  display: grid; grid-template-columns: 44px 1fr auto; gap: 10px;
  align-items: center; padding: 8px 9px; border-radius: 6px; margin-bottom: 6px;
  border: 1px solid #c9dcee; background: #fff;
}
#win .winbox[data-win="skills"] .sk:hover { border-color: #8fbde8; background: #f7fbff; }
/* ไอคอนอยู่ในกรอบสี่เหลี่ยมมนแบบเดียวกับช่องของในกระเป๋า = ภาษาเดียวกันทั้งเกม */
#win .winbox[data-win="skills"] .sk-ic {
  width: 44px; height: 44px; display: grid; place-items: center; border-radius: 7px;
  background: linear-gradient(#f6faff, #e6eff9); border: 1px solid #c3d7ea;
}
#win .winbox[data-win="skills"] .sk-ic .ro-ic { width: 24px; height: 24px; color: #46648a; }
/* เรียนแล้ว = ฟ้าเข้ม (ของเดิมเป็นทองอำพัน ซึ่งหลุดธีม) · ไม้ตาย = คราม */
#win .winbox[data-win="skills"] .sk.has { border-color: #2f7fd0; background: #f3f9ff; }
#win .winbox[data-win="skills"] .sk.has .sk-ic {
  background: linear-gradient(#e3f0fd, #cbe2f8); border-color: #2f7fd0; }
#win .winbox[data-win="skills"] .sk.has .sk-ic .ro-ic { color: #1466b8; }
#win .winbox[data-win="skills"] .sk.ult { border-color: #4a44b8; background: #f5f4ff; }
#win .winbox[data-win="skills"] .sk.ult .sk-ic {
  background: linear-gradient(#eceafd, #d9d5f7); border-color: #4a44b8; }
#win .winbox[data-win="skills"] .sk.ult .sk-ic .ro-ic { color: #3b35a8; }
#win .winbox[data-win="skills"] .sk.lock { opacity: 1; background: #f4f6f8; border-color: #d8dfe6; }
#win .winbox[data-win="skills"] .sk.lock .sk-ic { filter: grayscale(1); opacity: .55; }
#win .winbox[data-win="skills"] .sk.lock b { color: #7d8896; }
/* ระดับสกิลเป็นชิป ไม่ใช่ตัวเลขลอยข้างชื่อ — หาว่าเรียนไปกี่ขั้นได้โดยไม่ต้องอ่านทีละตัว */
#win .winbox[data-win="skills"] .lvl {
  display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px;
  background: #e4eefb; color: #1466b8; font-weight: 700; font-size: 11px;
  font-variant-numeric: tabular-nums; }
#win .winbox[data-win="skills"] .sk.has .lvl { background: #2f7fd0; color: #fff; }
#win .winbox[data-win="skills"] .sk .dim.small { line-height: 1.45; }
#win .winbox[data-win="skills"] .sk-btns { display: flex; gap: 6px; align-items: center; }
#win .winbox[data-win="skills"] .skillcol-h {
  font-weight: 800; font-size: 12.5px; color: #17293d; margin: 10px 0 6px;
  padding-left: 8px; border-left: 3px solid #2f7fd0; }
/* คำใบ้เรื่องลากสกิล — เดิมเป็นย่อหน้ายาวกินครึ่งบาน ย่อเป็นแถบเดียวสีอ่อน */
#win .winbox[data-win="skills"] .bindhint {
  background: #e8f2fd; border: 1px solid #cfe0f2; border-radius: 6px;
  padding: 6px 9px; font-size: 11px; line-height: 1.5; }

/* ── สวมใส่ ──────────────────────────────────────────────────────────────
   ช่องว่างกับช่องมีของต้องต่างกันตั้งแต่แวบแรก: ช่องว่าง = เส้นประจาง · มีของ = กรอบฟ้าทึบ */
#win .winbox[data-win="equip"] .eq-slot {
  border: 1px dashed #c3d7ea; border-radius: 8px; background: #f7fbff; }
#win .winbox[data-win="equip"] .eq-slot.filled {
  border-style: solid; border-color: #9cc4e8; background: #fff;
  box-shadow: 0 1px 3px #1b3c5e14; }
#win .winbox[data-win="equip"] .eq-slot.filled:hover {
  border-color: #2f7fd0; background: #f3f9ff; box-shadow: 0 2px 8px #2f7fd033; }
/* ตุ๊กตากลาง — วางบนพื้นไล่เฉดฟ้า ให้เป็น "จุดสนใจ" ของบาน ไม่ใช่ช่องหนึ่งเท่ากับช่องอื่น */
#win .winbox[data-win="equip"] .eq-doll {
  background: linear-gradient(#f2f8ff, #dfeaf7); border: 1px solid #b9d1e9;
  border-radius: 10px; box-shadow: inset 0 1px 0 #fff; }
#win .winbox[data-win="equip"] .eq-doll-name { font-weight: 800; color: #17293d; }
#win .winbox[data-win="equip"] .eq-doll-job { color: #46648a; }

/* ── สเตตัส ──────────────────────────────────────────────────────────────
   ฝั่งขวาคือ "ผลลัพธ์" ของฝั่งซ้าย — ให้มันมีพื้นของตัวเองแทนที่จะลอยอยู่ข้าง ๆ เฉย ๆ */
#win .winbox[data-win="stats"] .st-right {
  background: #f7fbff; border: 1px solid #cfe0f2; border-radius: 7px; padding: 6px 8px; }
#win .winbox[data-win="stats"] .dv-row {
  display: grid; grid-template-columns: 1fr auto 1fr auto; gap: 4px; align-items: baseline;
  border-bottom: 1px dashed #dde9f5; }
#win .winbox[data-win="stats"] .dv-row:last-child { border-bottom: 0; }
#win .winbox[data-win="stats"] .dv-row span { color: #46648a; font-size: 10.5px; }
#win .winbox[data-win="stats"] .dv-row b {
  color: #17293d; font-variant-numeric: tabular-nums; font-weight: 700; }
/* แถวสเตตัสสลับพื้น — ไล่สายตาลงมาแล้วไม่หลุดแถว */
#win .winbox[data-win="stats"] .st-row:nth-child(odd) { background: #f7fbff; }
#win .winbox[data-win="stats"] .st-row { border-bottom: 1px solid #e6eef7; border-radius: 4px; }
#win .winbox[data-win="stats"] .st-name { color: #2f5f96; }
#win .winbox[data-win="stats"] .st-up {
  background: linear-gradient(#f8fbff, #e4eefb); border: 1px solid #a9c9e6; color: #1466b8; }
#win .winbox[data-win="stats"] .st-up:not(.off):hover { background: #dbebfc; border-color: #2f7fd0; }
/* การ์ด .goal (กล่องเป้าหมาย/คำแนะนำ) เป็นครีม-ทองมาแต่เดิม — ในสามบานนี้ปรับเป็นฟ้าอ่อนให้เข้าธีม
   ไม่แตะ .card.goal ตัวกลาง เพราะบานอื่น (เควส/ร้านค้า) ยังใช้โทนเดิมอยู่ */
#win .winbox[data-win="stats"] .card.goal,
#win .winbox[data-win="skills"] .card.goal,
#win .winbox[data-win="equip"] .card.goal {
  background: #f2f8ff; border-color: #a9c9e6;
}
#win .winbox[data-win="skills"] .card.goal > .h {
  background: linear-gradient(#e9f3ff, #d8e8fa); border-bottom-color: #b9d1e9; }
/* ช่องสวมใส่ที่ "ยังว่าง" ให้เป็นฟ้าอ่อนเข้าธีม — ส่วนช่องที่มีของจริงคงโทนอุ่นเดิมไว้
   จงใจไม่แตะ .islot ตัวกลาง: มันคือภาษาของ "ช่องไอเทม" ที่กระเป๋าใช้อยู่และเพิ่งออกแบบใหม่ไป
   ผลพลอยได้คือของจริงเด้งออกจากช่องว่างชัดขึ้นมาก เพราะอุ่นตัดกับฟ้ารอบ ๆ */
#win .winbox[data-win="equip"] .islot.empty {
  border-color: #b6cde3; background: #f4f9ff; }
#win .winbox[data-win="equip"] .islot.empty .islot-ic { color: #9fbdd8; }
#win .winbox[data-win="equip"] .eq-slot .dim { color: #5b7997; }
/* แผง "ค่าที่ได้จริง" ต้องสูงเท่าเนื้อหา ไม่ยืดตามคอลัมน์ซ้ายที่ยาวกว่า
   (กริดยืดลูกทุกตัวเต็มแถวเป็นค่าตั้งต้น — ปล่อยไว้จะเหลือพื้นฟ้าว่างใต้ HP/SP ครึ่งแผง) */
#win .winbox[data-win="stats"] .st-grid { align-items: start; }
