﻿/* style.css — เฟส 2 (shell) · design pass เต็มอยู่ในเฟส 6 */

:root{
  /* ⚠ ค่าพวกนี้เป็นแค่ **ค่าสำรองก่อน JS ทำงาน** — แหล่งจริงคือ `data/names.js`
     `ui.js init()` เขียนทับตอนเริ่ม (ดูคอมเมนต์ที่นั่น) · แก้สีฝ่ายให้แก้ที่ names.js ที่เดียว */
  --han:#3E7F58; --wei:#3C5F8C; --wu:#A8544A;
  --bg:#0e1015; --panel:#161922; --panel2:#1d212c; --line:#2a2f3d;
  --text:#e8eaf0; --dim:#8b93a7; --gold:#d9b169;
  --pad:18px;
}
*{box-sizing:border-box; margin:0; padding:0}
html,body{height:100%; overflow:hidden}
body{
  background:var(--bg); color:var(--text);
  font-family:"Leelawadee UI","Segoe UI",Tahoma,system-ui,sans-serif;
  display:grid;
  /* ⚠ ต้องเป็น minmax(0,1fr) ไม่ใช่ 1fr เฉย ๆ
     `1fr` ย่อมาจาก minmax(auto,1fr) ซึ่ง auto = ขนาดต่ำสุดของเนื้อหาข้างใน
     <svg viewBox="0 0 1650 1950"> มีสัดส่วนในตัว เบราว์เซอร์จึงคิดขนาดขั้นต่ำให้
     แล้วคอลัมน์แผนที่บานเกินพื้นที่จริง ดันพาเนลนิยายออกนอกจอ
     (ใส่ min-width:0 ที่ตัว element อย่างเดียวไม่พอ ต้องแก้ที่ track ของ grid ด้วย) */
  grid-template-columns:minmax(0,1fr) 400px;
  grid-template-rows:minmax(0,1fr) auto;
  grid-template-areas:"map side" "time side";
}

/* ══ แผนที่ ══
   ⚠ min-height/min-width:0 ห้ามตัดออก
   grid item มีค่าปริยาย min-height:auto = หดต่ำกว่าเนื้อหาข้างในไม่ได้
   และ <svg viewBox="0 0 1650 1950"> ที่ width:100% มีสัดส่วนในตัว
   เบราว์เซอร์จึงคิดความสูงให้เป็น กว้าง×(1950/1650) — จอกว้าง 1900px = สูง 2245px
   แถวแผนที่จะบานตามนั้นแล้วดันพาเนลนิยายกับแถบเวลาตกขอบจอไปทั้งหมด */
#stage{grid-area:map; position:relative; overflow:hidden; background:#0b0d12; cursor:grab;
  min-height:0; min-width:0}
#stage.grabbing{cursor:grabbing}
/* ══ ★★★ สองบรรทัดนี้คือตัวแก้จริงของอาการ "ลากแล้วติดคลุมดำ แล้วเลื่อนไม่ได้อีก" ══
   (เจ้าของทัก 2026-09-08 · หลักฐานการวัดอยู่ที่ `bindPanZoom` ใน strategic.js)
   `user-select` — ถ้าไม่ปิด ทุกครั้งที่ลาก เบราว์เซอร์จะ **เลือกข้อความบนแผ่น** ไปด้วย
     แถบไฮไลต์บนธีมมืด = "คลุมดำ" ที่เจ้าของเห็น · และพอมี selection ค้างใต้เมาส์
     การกดลากครั้งถัดไปกลายเป็น drag-and-drop ของข้อความนั้น ซึ่งกลืน pointermove ทั้งชุด
   `user-drag` — `<image>` ใน SVG ลากได้เองเหมือน <img> ต้องปิดคู่กัน
   ★ ต้นแบบของ Codex ปิด `user-select` ไว้ที่ป้ายของเขาตั้งแต่แรก — นี่คือเหตุผลที่มัน "ลื่น"
   ⚠ ปิดที่ `#tkmap` เท่านั้น **ห้ามปิดที่ `#stage`** — `#placecard` อยู่ในนั้นและมีพิกัด
     ที่คนสอบเทียบต้องก๊อปไปใช้ */
#tkmap{width:100%; height:100%; display:block; touch-action:none;
  user-select:none; -webkit-user-select:none;
  min-height:0; min-width:0}
#tkmap image{-webkit-user-drag:none}
#stage.art-on.map-surface-ready #L-plate,
#stage.art-on.map-surface-ready #L-relief,
#stage.art-on.map-surface-ready [data-art-layer="environment"]{display:none}
#stage.art-on.map-surface-ready #L-regions{opacity:0}
#stage.art-on.map-surface-ready .region{animation:none;transition:none}
#stage:not(.art-on) #L-map-surface{display:none}
/* ══ ★★ ลำดับการวาดของสองชั้นนี้ (2026-09-10 — ตอนย้าย canvas ออกจาก SVG) ══════
   `#L-map-surface` เป็น `position:absolute` ส่วน `#tkmap` เดิมเป็น static
   → ตามกฎการวาดของ CSS **ของที่ positioned วาดทับของที่ static เสมอ ไม่สนลำดับใน DOM**
   ผลคือ canvas ขึ้นไปคลุมทั้งหมุดและตัวหนังสือ (เจอจริงทันทีที่ย้าย: แผนที่มีแต่พื้น)
   → ต้องยก `#tkmap` ขึ้นมาเป็น positioned ด้วย แล้วเรียง z-index ให้ชัด */
#stage > #L-map-surface{z-index:0}
/* ★ ยกเป็นชั้น GPU **เฉพาะตอนกล้องเคลื่อน** — ตั้งค้างไว้ = เบราว์เซอร์กัน texture ไว้ตลอด
   ซึ่งเป็นตัวการเดียวกับที่ทำให้ตัวหนังสือใน SVG เบลอ (ดู cameraSettled ใน strategic.js) */
#stage.camera-moving > #L-map-surface{will-change:transform}
#stage > #tkmap{position:relative; z-index:1}
/* กล้องเลื่อนชั้นภาพที่วาดไว้แล้ว; #stage เป็นผู้ตัดขอบภาพ */
#tkmap{transform-origin:0 0;will-change:transform;overflow:visible}
#stage.camera-moving .mk-halo,
#stage.camera-moving .mk-clash-ring,
#stage.camera-moving .region.flip{animation-play-state:paused}
/* ความเข้มของแผนที่พื้น — เดิมฟอกจนซีดเพื่อให้ชื่อไทยชนะชื่ออังกฤษที่พิมพ์ติดมากับภาพ
   ซึ่งเป็นการแก้ผิดจุด (ทำลายแผนที่เพื่อช่วยตัวหนังสือ)
   ที่ถูกคือให้ป้ายมีฮาโลของตัวเองแล้วคืนสีภูมิประเทศให้เห็นแม่น้ำกับภูเขา
   กดปุ่มมุมขวาบนสลับได้สามระดับ */
#basemap{filter:saturate(.45) brightness(1.04) contrast(.9); transition:filter .3s ease}

/* ══ ★★ แผ่นพื้นที่เราวาดเอง — สไตล์ "กลางคืน" ═══════════════════════════
   เจ้าของเคาะ 2026-09-05 · จานสีเต็มอยู่ที่ DECISIONS §14 เฟส 2
   ข้อมูล data/plate_water.js ลอกจากหมึกของ map.jpg เอง (ไม่ใช่ Natural Earth)

   ⚠ ความหนาทุกค่าที่นี่เป็น **หน่วยแผ่น ไม่ใช่หน่วยจอ** — มันคือแผ่นดิน ต้องโตตามแผ่น
     (ต่างจาก .road / .mk-route ที่ relayout คอยคูณ mu ให้คงที่บนจอ)                */
#L-plate .pl-ground{fill:#1C2129}
/* ⚠ ทะเล/ทะเลสาบ/เกาะ ย้ายไปชั้น #L-water แล้ว (2026-09-05) — ต้องอยู่ *บน* สีเขต
     ไม่งั้นสีเขต .45 กลบพื้นน้ำจนเหลือแต่เส้นขอบ แล้วตาอ่านว่า "วงกลวง" (เจ้าของทัก)
     ตัวเลือกที่นี่จึงต้องอ้าง #L-water ให้ตรงกับที่ strategic.js วางจริง */
/* ★★ ทะเลสาบต้องเป็น **สีเดียวกับหมึกสายน้ำ** — มันคือน้ำสายเดียวกันที่กว้างขึ้น
     ของเดิมทะเลสาบ #26323D ห่างจากพื้นดิน #1C2129 แค่นิดเดียว บนแผ่นมืดจึงอ่านเป็น "หลุม"
     เหลือแต่เส้นขอบให้เห็น — เจ้าของทักสองรอบ
     ⚠ รอบแรกผมแก้แต่ *ชั้น* (ย้ายขึ้นเหนือสีเขต) ซึ่งจำเป็นแต่ไม่พอ · ที่เหลือคือ *สี*
     ทะเลไม่ใช้สีเดียวกับสายน้ำเพราะเป็นผืนใหญ่ ถ้าสว่างเท่ากันจะกลบทุกอย่าง
     แต่ต้องสว่างพอให้อ่านว่า "น้ำ" ไม่ใช่ "ขอบแผ่น" */
#L-water .pl-sea{fill:#33495B; stroke:#6E8DA3; stroke-width:2}
#L-water .pl-shelf{fill:none; stroke:#3E5A70; stroke-width:22; stroke-opacity:.55}
#L-water .pl-isl{fill:#1C2129; stroke:#4A5C6A; stroke-width:2}
#L-water .pl-lake{fill:#5F8299; stroke:none}
/* หมึกน้ำอยู่คนละชั้น (#L-water) เพราะมันต้องอยู่ *บน* สีเขต ไม่ใช่ใต้ — §14 เฟส 2
   ★ สายน้ำเป็น **ลายฉลุของหมึกแผ่นเอง** (assets/water_stencil.png ผ่าน SVG mask)
     ไม่ใช่เส้นที่เราวาดใหม่ — ความเพี้ยนจากแผ่นเดิมจึงเป็นศูนย์ (§14 เฟส 4.3) */
#L-water .pl-river-ink{fill:#5F8299}
/* ★ กำแพงเมืองจีน — อยู่เหนือชั้นเขตเหมือนหมึกน้ำ เพราะเรื่องอ้างถึงมันตลอด
   สีหินอุ่น ตัดกับหมึกน้ำที่เย็น → อ่านออกทันทีว่าอันไหนธรรมชาติ อันไหนคนสร้าง
   ⚠ ฟันเสมาห้อยลงใต้เสมอ (ทำใน strategic.js) — กำแพงกันของที่มาจากทางเหนือ */
#L-wall .pl-wall{stroke:#8C8375; stroke-width:2.6; fill:none; stroke-linejoin:round; stroke-linecap:round}
#L-wall .pl-tooth{stroke:#8C8375; stroke-width:1.5; stroke-linecap:round}
#stage.map-rich #L-wall .pl-wall,
#stage.map-rich #L-wall .pl-tooth{stroke:#A2988A}
#stage:not(.plate-new) #L-wall{display:none}

/* สลับแผ่น: คลาสเดียวคุมทั้งสี่อย่าง */
#stage.plate-new #basemap{display:none}
/* กรอบปิดตัวอักษร WEI/SHU/WU ไม่ต้องมีอีก — แผ่นใหม่ไม่ได้พิมพ์ชื่อฝ่ายไว้ */
#stage.plate-new #L-mask{display:none}
/* ★ .38 ตั้งไว้สำหรับแผ่นสว่าง · บนพื้นมืดสีโปร่งจะทั้งมืดลงและซีดลงพร้อมกัน
   วัดด้วยตาแล้ว: ที่ .38 เขียว/น้ำเงิน/แดงเริ่มแยกกันยาก · ที่ .55 สีเขตเริ่มกลบ
   **ลูกศรสีเดียวกันของตัวเอง** (ลูกศรวุ่ยในแผ่นดินวุ่ย) · .45 อยู่กลางพอดี */
#stage.plate-new #L-regions{opacity:.45}
/* ★ ปุ่ม "ความเข้มของแผนที่พื้น" ต้องมีความหมายกับแผ่นใหม่ด้วย ห้ามซ่อนทิ้ง
   ⚠ เคยเขียนเป็น `#stage.plate-new #mapmode{display:none}` แล้ว **check_click จับได้ทันที**
     ว่ามีปุ่มที่เมาส์จริงกดไม่โดน — การซ่อนปุ่มไม่ใช่การแก้ปัญหา มันคือการซ่อนปัญหา
   ค่าที่เจ้าของเคาะคือชุด "เข้ม" ซึ่งเป็นค่าเริ่มต้นอยู่แล้ว · ชุด "ปกติ" คือแบบที่อ่อนลงหนึ่งขั้น */
#stage.map-rich #L-plate .pl-ground{fill:#171A20}
#stage.map-rich #L-water .pl-isl   {fill:#171A20}
#stage.map-rich #L-water .pl-sea   {fill:#2C4054}
#stage.map-rich #L-water .pl-lake  {fill:#6E93AA}
#stage.map-rich #L-water .pl-river-ink{fill:#6E93AA}
#stage:not(.plate-new) #L-plate,
#stage:not(.plate-new) #L-water{display:none}

/* ══ ★★★ ชั้นภาพรุ่น 03 จากฝั่ง Codex (เสียบ 2026-09-08) ═══════════════════════
   ภาพมาเป็น `<g data-art-layer="terrain|water">` ที่ strategic.js ย้ายเข้าสองชั้นนี้
   ★ ของเราเองที่เคยวาดไว้ในชั้นเดียวกัน (`.pl-*` จาก plate_water) ต้อง **ซ่อน ไม่ใช่ลบ**
     — HANDOFF สั่งไว้ว่า *"เลือกแทนชั้นน้ำเดิมหนึ่งชุด ไม่วาดสองชุดซ้อนกัน"*
     และ `data/plate_water.js` ยังเป็นข้อมูลที่ `check_water.js` ใช้อยู่ ห้ามทิ้ง */
#stage.art-on #L-plate > :not([data-art-layer]),
#stage.art-on #L-water > :not([data-art-layer]){display:none}
/* ══ ★★★ ระบบสีของโหมดแผ่นวาดใหม่ — **แผ่นเป็นพระเอก สีของเราเป็นตัวประกอบ**
   เจ้าของสั่ง 2026-09-08: *"สีที่ใช้ระบายมันกลบความสวยของแผนที่ที่ GPT ทำมาหมดเลย
    โดยเฉพาะภูเขามันโดนกลบหมด และแม่น้ำกลืนกับสีเขียวไปเลย"*

   ★ ต้นเหตุ: เราเอาวิธีคิดของ "แผ่นมืด" มาใช้กับ "แผ่นกระดาษสว่าง"
     บนแผ่นมืด สีเขตต้องทึบถึงจะเห็น · บนกระดาษ ความทึบเท่านั้นกลายเป็นสีทาทับ

   ⛔⛔ **ทางที่เคยเดินแล้วถอยกลับมา — ห้ามเดินซ้ำ** (เจ้าของสั่งถอย 2026-09-08 ตอนเย็น)
     รอบแรกผมแก้ด้วยการ *ปลด opacity ของชั้นออก* แล้วตั้ง `fill-opacity:.28`
     คู่กับ `stroke-opacity:.95; stroke-width:2.6` — คือให้อ่านเจ้าของพื้นที่จาก **เส้นขอบ**
     เจ้าของทักทันทีว่า *"เหมือนการซอยเขตให้มันชัดโดยใช้ขอบเข้มเข้ามาตี ...
     แผนที่เก่าไม่มีปัญหา ทำไมอันนี้มีล่ะ"* — และคำถามนั้นชี้ตรงเข้าต้นเหตุ

   ★★★ **คำตอบ: ปัญหาที่เส้นขอบเกิดมาแก้ ถูกแก้ไปแล้วด้วยวิธีอื่นตั้งแต่วันเดียวกัน**
     • แผ่นเดิมไม่มีปัญหาเพราะ **ใต้สีไม่มีอะไรให้กลบ** — หมึกภูเขาบน map.jpg มีแค่
       17,963 px = 0.56% ของแผ่น (วัดไว้ที่ LOG §5.12) ทาทับ .45 ก็ไม่ได้เสียอะไร
     • แผ่นใหม่มีภาพนูนเต็มแผ่น รอบแรกจึงโดนกลบจริง
     • แต่ `strategic.js` `loadArt()` **ยกภาพนูนออกไปไว้ *เหนือ* สีเขตแล้ว** (`#L-relief`
       + `mix-blend-mode:multiply` ข้างล่างนี้) ภูเขาจึงไม่ได้อยู่ใต้สีอีกต่อไป
       มันทำหน้าที่ *ทำให้มืดลง* จากข้างบน → **ความทึบของสีเขตไม่เกี่ยวกับภูเขาอีกแล้ว**
     ตารางใน HANDOFF §1① ที่บอกว่า `.45` แล้วภูเขาหาย เป็นตัวเลขที่วัด **ก่อน** มี multiply
     พิสูจน์ด้วยภาพคู่เทียบที่ c9-05 แล้ว: เอาขอบออก + ดันเนื้อสีกลับ → ภูเขาคมกว่าเดิม

   ⚠⚠ **ห้าม "เอาขอบออก" ด้วย `stroke-opacity:0`** (HANDOFF เคยเสนอทางนี้ไว้)
     `stroke-width:1.5` ของ `.region` **ไม่ใช่เส้นขอบ** มันคือตัวปิดรอย anti-aliasing
     ตรงรอยต่อ path สองอัน (อ่านบันทึกประวัติของเลขนี้ที่ `.region` ข้างล่าง)
     ถอดมันออกเมื่อไหร่ = ได้เส้นขาวบาง ๆ คั่นทุกเขต

   ★ วิธีที่ถูก คือ **กลไกเดิมของแผ่นเก่าเป๊ะ ๆ — คุมความเข้มที่ `opacity` ของ *ชั้น***
     ไม่ใช่ที่ `fill/stroke` ของแต่ละรูป · ทำแบบนี้แล้ว stroke จางเท่า fill โดยอัตโนมัติ
     (เส้นหายไปเอง แต่ยังปิดรอยต่ออยู่) และไม่มีการทับซ้อนของ stroke บน fill
     ที่ทำให้ขอบเข้มขึ้นมาเองแม้ตั้งค่าเท่ากัน — เพราะ alpha ถูกรวมในชั้นก่อน แล้วค่อยจาง
   ★ ตัวเลขสองตัวข้างล่าง **ไม่ได้ตั้งใหม่ด้วยตา** — เป็นค่าที่มีอยู่แล้วทั้งคู่:
     `.38` = `#L-regions` ฐานเดิม · `.45` = `#stage.plate-new #L-regions` เดิม */
#stage.art-on #L-regions{opacity:.45}
/* ⛔ เคยมีคู่ `:not(.map-rich)` ที่ .38 สำหรับโหมด "ปกติ" — ถอดพร้อมปุ่ม 2026-09-08
   ตอนนี้ `map-rich` ติดกับ #stage ตลอด จึงเหลือความเข้มเดียว */

/* ══ ★★★ บรรทัดเดียวที่คืน "เข้ม" ให้ **แผ่นต้นฉบับ** ด้วย (แก้ 2026-09-08 ดึก) ══════
   เจ้าของทัก: *"ทำไมแผนที่มันเป็นสีปกติ แทนที่จะเป็นเข้ม ไม่ใช่ session ก่อนหน้าทำไปแล้วเหรอ"*
   — และเขาถูก · **วัดของจริงแล้ว**: กด "แผ่น: ต้นฉบับ" ปุ๊บ `#stage` เหลือคลาสเดียวคือ
   `map-rich` (ไม่มี `art-on` ไม่มี `plate-new`) → **ไม่มีกฎ .45 ข้อไหนติดเลย**
   → ตกไปใช้ค่าฐาน `#L-regions{opacity:.38}` ซึ่งคือ *"ปกติ"* พอดี

   ★★ ต้นเหตุคือรอบที่แล้วเขียนกฎ "เข้ม" ผูกไว้กับ `art-on` (= แผ่นวาดใหม่) ทั้งที่คลาสที่
   **แปลว่า "เข้ม" จริง ๆ คือ `map-rich`** · พอปุ่มสลับความเข้มถูกถอดและ `map-rich`
   กลายเป็นค่าถาวร ไม่มีใครสังเกตว่าฝั่งแผ่นต้นฉบับหลุดออกจากกฎไปเงียบ ๆ
   ★ บทเรียนเดิมของ §5.14 ซ้ำอีกที: **เปลี่ยนสถาปัตยกรรมของชั้นเมื่อไหร่ ต้องไล่ดูทุกโหมด
     ที่ยังเปิดอยู่ ไม่ใช่เฉพาะโหมดที่กำลังทำ** (คราวนั้นคือ multiply · คราวนี้คือปุ่มที่ถูกถอด) */
#stage.map-rich #L-regions{opacity:.45}

/* ★ เงาเขา — คูณทับสีพื้น · ต้องถอดสีก่อน ไม่งั้นภาพสีน้ำตาลจะย้อมสีฝ่ายให้เพี้ยน
   ยกความเข้มขึ้นได้แล้วเพราะเนื้อสีเขตบางลงมาก (เดิม .55 ตอนเขตทึบ .62) */
#L-relief{mix-blend-mode:multiply}
#L-relief image{opacity:.72; filter:grayscale(1) brightness(1.06) contrast(1.22)}
#stage:not(.art-on) #L-relief{display:none}

/* ★ ชั้น Environment (ป่า/ดิน จากฝั่ง Codex) — โผล่เฉพาะโหมดแผ่นวาดใหม่
   แผ่นต้นฉบับมีสีพื้นของมันเองอยู่แล้ว เอาป่าไปทับจะได้สองระบบซ้อนกัน
   ⚠ ความเข้มคุมที่ `opacity` ของ group ผ่าน `TKEnvironment.setOpacity()` ใน JS
     **ห้ามมาตั้ง opacity ทับที่นี่** ไม่งั้นสองที่จะแย่งกันคุมแล้วงงว่าค่าจริงคือเท่าไร */
#stage:not(.art-on) [data-art-layer="environment"]{display:none}

/* ★★ น้ำ — ไฟล์ส่งมาเป็น **เทาอมเขียว** (`#9bbdbc` / `#688f87`) ซึ่งสวยบนกระดาษเปล่า
   แต่พอมีแผ่นดินของฮั่นสีเขียวอยู่ข้างใต้ มันกลืนกันทันที (เจ้าของจับได้)
   → ดันไปทางน้ำเงินให้พ้นย่านสีเขียว แต่คงความหม่นของแผ่นไว้ ไม่ใช่ฟ้าสด

   ══ รุ่น 04 (8 ก.ย. 2026) — เล็งด้วย **class** แล้ว ไม่ใช่ตำแหน่ง ══════════════
   เราขอไปเองใน `NOTES_FROM_CLAUDE_TH.md` §2.1 ว่า `nth-of-type` คือระเบิดเวลา
   (วันที่เขาสลับลำดับกลุ่ม สีน้ำจะเพี้ยนทั้งแผ่นโดยไม่มีอะไรฟ้อง) — **เขาให้ class มาแล้ว**

   โครงของไฟล์รุ่น 04 มี **สี่ชนิด** และลำดับวาดสำคัญ (บนลงล่าง = หลังทับหน้า):
     ① `.open-water-shore` 13 รูป  — ขอบทะเล/ทะเลสาบ (รูปปิด มี fill + stroke)
     ② `.rivers-casing`   95 เส้น  — ขอบเข้มของแม่น้ำ
     ③ `.rivers-core`     95 เส้น  — แกนอ่อนของแม่น้ำ
     ④ `.open-water-fill` 13 รูป  — **ผิวน้ำนิ่งทับปิดท้าย** กันไม่ให้ขอบแม่น้ำ ② โผล่ในทะเลสาบ

   ⚠⚠ **`.open-water-fill` ห้ามมี `stroke` เด็ดขาด** (Codex เตือนมาเอง) — มันถูกวาด
     ทับท้ายสุด ถ้าใส่เส้นขอบให้มัน จะได้ **ขอบตัดขวางปากแม่น้ำ** ทุกจุดที่แม่น้ำไหลลงทะเลสาบ
   ⚠⚠ **`.open-water-fill` กับ `.rivers-core` ต้องเป็นสีเดียวกัน** ไม่งั้นเห็นรอยต่อ
     ตรงปากน้ำ เพราะแม่น้ำวิ่งเข้าไปจบใต้ผิวน้ำนิ่งพอดี
   ⚠ **ห้ามเขียนกฎรวบว่า `... path{fill:X; stroke:Y}` แบบเดิมอีก** — ของเดิมเล็ง
     "ลูกตรงที่เป็น path" ซึ่งรุ่น 04 มี **26 อัน** (shore 13 + fill 13) ไม่ใช่ 13
     กฎเดิมจะไปใส่ stroke ให้ ④ ด้วย = ตำหนิที่ย่อหน้าบนเตือนไว้เป๊ะ ๆ
   ⚠ **ห้ามยัด `fill` ให้ ② หรือ ③** — มันเป็นเส้นเปิด ยัด fill แล้วถูกปิดเป็นรูป
     → ได้ลิ่มสีฟ้าพาดทั้งแผ่น (ผมพลาดข้อนี้มาแล้ว 2026-09-08 เช้า) */
#stage.art-on #L-water [data-art-layer="water"] .open-water-shore{fill:#93BEDA; stroke:#5E8CAB}
#stage.art-on #L-water [data-art-layer="water"] .rivers-casing{stroke:#4E7A9B}
#stage.art-on #L-water [data-art-layer="water"] .rivers-core{stroke:#93BEDA}
#stage.art-on #L-water [data-art-layer="water"] .open-water-fill{fill:#93BEDA; stroke:none}
/* กำแพงบนกระดาษสว่างต้องเข้มขึ้น ไม่งั้นหายไปกับพื้น (ของเดิมตั้งไว้สำหรับพื้นมืด) */
#stage.art-on #L-wall .pl-wall,
#stage.art-on #L-wall .pl-tooth{stroke:#6B6255}
#stage.art-on.map-rich #L-wall .pl-wall,
#stage.art-on.map-rich #L-wall .pl-tooth{stroke:#A2988A}

#stage.map-faint #basemap{filter:saturate(.18) brightness(1.30) contrast(.72)}
#stage.map-rich  #basemap{filter:saturate(.85) brightness(.96) contrast(1)}

/* ปุ่มมุมขวาบนของแผนที่ — เรียงเป็นแถวเดียว จะได้ไม่ไปแย่งที่กับป้ายของฉาก
   ⚠ z-index ต้องสูงกว่า #spine (8) — ไม่งั้นพอเปิดกระดูกสันหลังแล้วโอเวอร์เลย์จะคลุมปุ่ม
     ทั้งแถว รวมถึงปุ่มที่ใช้ปิดมันเอง คนอ่านติดอยู่ในนั้นจนกว่าจะรู้ว่ากด Esc ได้
     (tools\check_click.js จับได้ทันทีที่รันครั้งแรก) */
#maptools{position:absolute; right:var(--pad); top:var(--pad); z-index:9;
  display:flex; gap:7px; align-items:flex-start}
#maptools button{background:rgba(14,16,21,.84); backdrop-filter:blur(9px);
  border:1px solid var(--line); border-radius:8px; padding:7px 12px;
  font-size:11.5px; color:var(--dim); cursor:pointer; font-family:inherit;
  white-space:nowrap; transition:color .18s, border-color .18s, background .18s}
#maptools button:hover{color:var(--text); border-color:var(--gold)}
#maptools button.on{color:var(--gold); border-color:var(--gold); background:rgba(58,51,32,.8)}
#maptools button:disabled{opacity:.35; cursor:default}
#maptools button:disabled:hover{color:var(--dim); border-color:var(--line)}

/* ── echo: marker ของฉากอื่นในฤดูเดียวกัน ──
   ต้องอ่านออกว่า "มีอะไรเกิดที่อื่นด้วย" แต่ต้องไม่แย่งสายตาจากฉากที่กำลังอ่าน
   จางอย่างเดียวไม่พอ เพราะลูกศรเต็มสีบาง ๆ ยังดึงตาอยู่ — ตัดหัวลูกศรทิ้งด้วย
   แล้วมันจะอ่านเป็น "ร่องรอย" แทนที่จะเป็น "การเดินทัพอีกกอง" */
/* ⚠ วัดจริงแล้ว .26 มองไม่เห็นเลยสักเส้น — ลูกศรฮั่นเป็นสีเขียวบนแผ่นดินฮั่นที่เขียวอยู่แล้ว
   และพอเปิดโหมดฤดู กล้องถอยออกไปกินทั้งภูมิภาค เส้นหนา 4 พิกเซลจึงเล็กลงเทียบกับทุกอย่างรอบตัว
   .5 คือจุดที่ "เห็นว่ามีอะไรอยู่ตรงนั้น" แต่ยังไม่แย่งสายตาไปจากฉากที่กำลังอ่าน */
.mk-echo{opacity:.5}
path.mk-echo{marker-end:none !important; marker-start:none !important; filter:none}
.mk-pin.mk-echo .mk-dot{opacity:.85}

/* คำบอกว่ากำลังดูทั้งฤดูอยู่ ไม่ใช่ฉากเดียว
   ⚠ ห้ามวางที่ left/top เดียวกับ #where — สองอันทับกันพอดีจนอ่านไม่ออกทั้งคู่
   (เจอตอนถ่ายภาพ c5-02c โหมดฤดูครั้งแรก) กลางบนว่างเสมอ เพราะ #maptools ชิดขวา */
#seasonnote{position:absolute; left:50%; transform:translateX(-50%); top:var(--pad); z-index:5;
  background:rgba(58,51,32,.86); backdrop-filter:blur(9px);
  border:1px solid var(--gold); border-radius:8px; padding:6px 11px;
  font-size:11.5px; color:var(--gold); pointer-events:none; display:none}
#seasonnote.on{display:block}
#seasonnote b{font-weight:700}
#seasonnote i{font-style:normal; color:var(--text); opacity:.75}

/* ══ กระดูกสันหลัง — สงคราม 48 ปีในหน้าจอเดียว ══
   คลุมเฉพาะ #stage ไม่คลุมคอลัมน์นิยาย เจตนาคือดูรูปทรงไปพลางอ่านไปพลางได้
   ไม่ใช่โหมดเต็มจอที่ตัดคนอ่านออกจากหนังสือ */
#spine{position:absolute; inset:0; z-index:8; display:none;
  background:rgba(10,12,17,.985); backdrop-filter:blur(5px); padding:10px 14px 6px}
#spine.on{display:block}
.spine-svg{width:100%; height:100%; display:block; overflow:visible}

.sp-chap{fill:#20242f}
.sp-chap.alt{fill:#272c39}
.sp-chaptxt{fill:var(--dim); font-size:10px; text-anchor:middle;
  font-family:"Leelawadee UI","Segoe UI",sans-serif}
.sp-grid{stroke:#252a37; stroke-width:1}
.sp-axis{fill:var(--dim); font-size:10px;
  font-family:"Leelawadee UI","Segoe UI",sans-serif}
.sp-head{fill:var(--dim); font-size:10.5px; letter-spacing:.3px;
  font-family:"Leelawadee UI","Segoe UI",sans-serif}
.sp-key{font-size:10.5px; font-weight:700;
  font-family:"Leelawadee UI","Segoe UI",sans-serif}
text.sp-key.sp-han{fill:var(--han)} text.sp-key.sp-wei{fill:var(--wei)} text.sp-key.sp-wu{fill:var(--wu)}
rect.sp-sw2.sp-han{fill:var(--han)} rect.sp-sw2.sp-wei{fill:var(--wei)} rect.sp-sw2.sp-wu{fill:var(--wu)}

.sp-line{fill:none; stroke-width:2.2; stroke-linejoin:round; stroke-linecap:round}
.sp-line.sp-han{stroke:var(--han)}
.sp-line.sp-wei{stroke:var(--wei)}
.sp-line.sp-wu {stroke:var(--wu)}

/* ราคาของแต่ละศึก — โปร่งพอที่วงซ้อนกันแล้วยังนับออกว่ามีกี่ครั้ง */
.sp-loss{opacity:.5; cursor:pointer}
.sp-loss:hover{opacity:.95}
circle.sp-han{fill:var(--han)} circle.sp-wei{fill:var(--wei)} circle.sp-wu{fill:var(--wu)}
rect.sp-han{fill:var(--han)}   rect.sp-wei{fill:var(--wei)}   rect.sp-wu{fill:var(--wu)}
rect.sp-none{fill:#6b7285}
.sp-terr{opacity:.8; cursor:pointer}
.sp-terr:hover{opacity:1}

.sp-dot{fill:#39415a; cursor:pointer; transition:fill .15s, r .15s}
.sp-dot:hover{fill:var(--text)}
.sp-dot.now{fill:var(--gold); r:5}
#sp-now{stroke:var(--gold); stroke-width:1; opacity:.55; stroke-dasharray:3 3}

.sp-tip{position:absolute; z-index:9; pointer-events:none; display:none;
  max-width:240px; background:rgba(14,16,21,.96); border:1px solid var(--line);
  border-radius:7px; padding:7px 10px; font-size:11.5px; color:var(--text);
  line-height:1.5; box-shadow:0 6px 22px rgba(0,0,0,.55)}
.sp-tip.on{display:block}
.sp-tip b{color:var(--gold); font-weight:700}
.sp-sw{display:inline-block; width:8px; height:8px; border-radius:2px; margin-right:5px}
.sp-sw.sp-han{background:var(--han)} .sp-sw.sp-wei{background:var(--wei)}
.sp-sw.sp-wu{background:var(--wu)}

/* กันเส้นที่ลืมสั่ง fill ไม่ให้กลายเป็นก้อนทึบ — ยกเว้นชั้นพื้นที่ยึดครองที่ต้องระบายจริง
   ⚠⚠⚠ **กฎนี้อันตรายกว่าที่หน้าตาบอก** — CSS ชนะ presentation attribute เสมอ
     `fill="white"` ที่เขียนมาในไฟล์ SVG ภายนอกจึงถูกกฎนี้ลบทิ้งเงียบ ๆ
     เจอครั้งที่สอง 2026-09-08: หน้ากากภูเขาของชั้นภาพรุ่น 03 เป็น `<path fill="white">`
     อยู่ใน `<mask>` → ถูกทำเป็น `fill:none` → หน้ากากดำสนิท → **ภูเขาหายทั้งแผ่น**
     โดยไม่มี error ใด ๆ (ครั้งแรกคือ `.pin-sym` 2026-09-02 — ดูคอมเมนต์ข้างล่าง)
   ★ ทางแก้: กันทั้งซับทรีของชั้นภาพภายนอกออกจากกฎนี้ ของข้างในมี fill ของตัวเองครบแล้ว */
#tkmap path:not(.region):not([data-art-layer] *){fill:none}

#L-regions{opacity:.38}
/* ประวัติของเลขนี้: 34 → 10 → 1.5
   34 มีไว้พองรูปที่ลากมือให้ชนกัน (มุมมนหมด สีล้นทะเล) · 10 มีไว้กลบเสี้ยวขาวที่
   การลดจุด "เขตใครเขตมัน" กินขอบเข้ามา — ตั้งแต่ 2026-08-25 build_geo ใช้เส้นขอบร่วม
   (shared arcs) พรมแดนสองฝั่งเป็นพิกัดชุดเดียวกันเป๊ะ จึงไม่มีรอยรั่วให้กลบอีก
   1.5 ที่เหลือมีหน้าที่เดียว: ปิดเส้นบางจาก anti-aliasing ตรงรอยต่อ path สองอัน
   ⚠ ห้ามกลับไปเพิ่มเพื่อแก้รอยขาว — ถ้าเห็นรอยขาวแปลว่า build_geo พัง ไปแก้ที่นั่น */
.region{stroke-width:1.5; stroke-linejoin:round;
  transition:fill .9s ease, stroke .9s ease}
.region.flip{animation:flip 1.1s ease}
@keyframes flip{0%{filter:brightness(2.4)} 100%{filter:none}}

/* ป้ายบอกว่าตอนนี้กล้องกำลังเล็งอะไรอยู่ */
/* ★ ย้ายมาอยู่ใน `#topleft` (flex row) 2026-09-08 — จึงเลิกเป็น absolute
   ความกว้างของมันเปลี่ยนตามชื่อที่กล้องเล็ง flex จึงเป็นวิธีเดียวที่ HUD ตามได้ถูก */
#where{position:relative; z-index:5; flex:none;
  background:rgba(14,16,21,.84); backdrop-filter:blur(9px);
  border:1px solid var(--line); border-left:3px solid var(--gold);
  border-radius:8px; padding:8px 13px; pointer-events:none;
  opacity:0; transform:translateY(-5px); transition:opacity .3s ease, transform .3s ease}
#where.on{opacity:1; transform:none}
#where b{display:block; font-size:14px; color:var(--gold); letter-spacing:.2px}
#where span{display:block; font-size:11.5px; color:var(--dim); margin-top:2px}

/* กรอบเน้นเขตที่กำลังดู (DECISIONS §17) — เส้นประทองบนขอบมืด (casing)
   ความหนากับลายประจริงเป็น "พิกเซลจอ" ตั้งจาก strategic.js (FOCUS_PX / styleFocusPaths)
   ค่าในไฟล์นี้เป็นแค่สำรองตอนสคริปต์ยังไม่ทัน · casing มีไว้แยกวงของเราออกจาก
   เส้นประเขตแดนสีเหลืองที่พิมพ์มากับแผ่นแผนที่ — ไม่มีมันสองลายนี้กลืนกันจนอ่านว่ารก
   การเฟดเข้า-ออกทำที่ชั้น #L-focus (บรรทัดถัดลงไป) ไม่ใช่ที่ตัวเส้น */
.region-focus{fill:none; stroke:var(--gold); stroke-width:3; stroke-opacity:.85;
  stroke-dasharray:14 9; stroke-linejoin:round; stroke-linecap:round; pointer-events:none}
.region-focus-under{fill:none; stroke:#0b0d12; stroke-width:6; stroke-opacity:.5;
  stroke-dasharray:14 9; stroke-linejoin:round; stroke-linecap:round; pointer-events:none}
/* ชายฝั่งของเขตที่เน้น — เส้นบางจางกว่าแนวการเมือง (§17) */
.region-focus-coast{stroke-opacity:.45}
/* แสงทองจางบนพื้นที่ที่เน้น — ให้กลุ่มเขตอ่านเป็นก้อนเดียว มีมิติ (§17) */
.region-glow{stroke:none; pointer-events:none}

/* ══ ★★ การ์ดข้อมูลจุด — คลิกหมุดแล้วอ่านได้ (2026-09-08) ═══════════════════════
   อยู่มุมซ้ายล่างของแผนที่ ไม่ชนกับ `#where` (ซ้ายบน) และแถบปุ่ม (ขวาบน)
   ⚠ ต้อง `pointer-events:auto` เพราะปุ่มข้างในต้องกดได้จริง (check_click จะจับถ้าไม่ได้) */
#placecard{position:absolute; left:var(--pad); bottom:calc(var(--pad) + 4px); z-index:6;
  width:264px; max-height:62%; overflow:auto;
  background:rgba(14,16,21,.93); backdrop-filter:blur(9px);
  border:1px solid var(--line); border-left:3px solid var(--gold);
  border-radius:9px; padding:11px 13px 10px; color:var(--text); font-size:12px}
#placecard .pc-x{position:absolute; top:6px; right:7px; background:none; border:0;
  color:var(--dim); font-size:13px; cursor:pointer; padding:2px 5px; border-radius:5px}
#placecard .pc-x:hover{color:var(--text); background:rgba(255,255,255,.08)}
#placecard .pc-kind{color:var(--dim); font-size:10.5px; letter-spacing:.4px;
  text-transform:uppercase; margin:0 0 2px}
#placecard h3{margin:0 0 1px; font-size:16px; color:var(--gold)}
#placecard .pc-py{margin:0 0 8px; color:var(--dim); font-size:11px}
#placecard .pc-py span{opacity:.75}
#placecard .pc-row{display:flex; justify-content:space-between; gap:10px;
  padding:3px 0; border-top:1px solid rgba(255,255,255,.06)}
#placecard .pc-row span{color:var(--dim)}
#placecard .pc-row b{font-weight:600; text-align:right}
#placecard .pc-warn{margin:7px 0 0; color:#E0B457; font-size:11px}
#placecard .pc-note{margin:8px 0 0; color:#c8cddb; font-size:11px; line-height:1.5;
  padding-top:7px; border-top:1px solid rgba(255,255,255,.06)}
#placecard .pc-scenes{margin-top:9px; padding-top:7px;
  border-top:1px solid rgba(255,255,255,.06); display:flex; flex-wrap:wrap; gap:4px}
#placecard .pc-scenes > span{width:100%; color:var(--dim); font-size:10.5px; margin-bottom:2px}
#placecard .pc-scenes i{color:var(--dim)}
#placecard .pc-scenes button{background:rgba(255,255,255,.07); border:1px solid var(--line);
  color:var(--text); border-radius:5px; padding:2px 7px; font-size:11px; cursor:pointer}
#placecard .pc-scenes button:hover{border-color:var(--gold); color:var(--gold)}
#placecard .pc-foot{margin:8px 0 0; color:var(--dim); font-size:10px; line-height:1.45}

.pin circle{fill:#f3f6ff; stroke:#0b0d12; stroke-width:1.4; opacity:.9}
.pin.t-capital circle{fill:var(--gold); stroke-width:2}

/* ★★ สัญลักษณ์สถานที่ (DECISIONS §3 · ล็อก 2026-09-02)
   หมึกดำล้วน **ไม่มีสีฝ่าย** — สีฝ่ายเป็นภาษาของกองทัพเท่านั้น
   ขอบขาวบาง ๆ ด้วย paint-order เพื่อให้อ่านออกบนพื้นเขียวของแผ่นเดิม
   ⚠ ความหนาเส้นอยู่ในหน่วยกล่อง 24 แล้ว ห้ามใส่ stroke-width เป็น px ที่นี่ */
/* ★★ โซ่ป้อม / แนวรั้ว — หน่วยแผนที่ ไม่ใช่หน่วยจอ (มันตั้งอยู่บนแผ่นดิน)
   สีจางกว่าลูกศรของฉากเสมอ: มันคือฉากหลังของสงคราม ไม่ใช่เหตุการณ์ */
#tkmap .works-spine{fill:none; stroke:#2e2a20; stroke-opacity:.45; stroke-width:1.4}
#tkmap .works-fort{stroke:#20242c; stroke-width:1.1; stroke-opacity:.85}
#tkmap .works-stake{fill:none; stroke:#2e2a20; stroke-opacity:.6; stroke-width:1.5;
                    stroke-linecap:round}
#tkmap .works.s-han .works-fort{fill:#2E9E5B; fill-opacity:.75}
#tkmap .works.s-wei .works-fort{fill:#2563A8; fill-opacity:.75}
#tkmap .works.s-wei .works-stake{stroke:#1f4a7a; stroke-opacity:.7}
/* ══ ★★ สัญลักษณ์ = **ขาวขอบดำ** บนแผ่นกระดาษสีอ่อน (เจ้าของสั่ง 2026-09-06) ══
   ของเดิมเป็นรูปทึบสีเข้ม (#12161d) ซึ่งบนแผ่นขาวมันไปกลืนกับ **ชื่อเมืองที่แผ่นพิมพ์ไว้**
   (ตัวหนังสือดำเหมือนกัน) → อ่านชื่อเมืองไม่ออกตรงที่มีสัญลักษณ์ทับ
   ★ ขาวทึบ + ขอบเข้ม แก้สองอย่างพร้อมกัน: ตัวรูปเองอ่านออก **และ** มันบังตัวหนังสือ
     ด้วยพื้นขาวแทนที่จะทับด้วยดำบนดำ · ออร่าขาวรอบนอกดันตัวหนังสือให้ห่างอีกชั้น
   ⚠⚠ ต้องขึ้นต้นด้วย #tkmap — กฎ "#tkmap path:not(.region){fill:none}" ข้างบน
      มี specificity สูงกว่า ".pin-sym path" และจะลบสีทิ้งเงียบ ๆ (เจอ 2026-09-02:
      สัญลักษณ์วาดครบ 69 ตัว transform ถูกหมด แต่ fill กลายเป็น none = มองไม่เห็นเลย) */
#tkmap .pin-sym, #tkmap .pin-role{
  filter:drop-shadow(0 0 1.6px rgba(255,255,255,.95)) drop-shadow(0 0 3px rgba(255,255,255,.7));
}
#tkmap .pin-sym path, #tkmap .pin-role path{fill:#fff; fill-opacity:1; stroke:#151a22; stroke-width:1.15;
              paint-order:normal; stroke-linejoin:round}
#tkmap .pin-sym path.gs, #tkmap .pin-role path.gs{fill:none; stroke:#151a22; stroke-opacity:.95;
                 stroke-width:1.35; stroke-linecap:round; paint-order:normal}
/* เมืองหลวงยังต้องเด่นกว่าเมืองอื่น — ใช้พื้นทองอ่อนแทนขาว ขอบเข้มชุดเดียวกัน */
#tkmap .pin.t-capital .pin-sym path:not(.gs){fill:#F3D590; stroke:#2a1d05; stroke-width:1.25}

/* ══ ★★ สีของสัญลักษณ์ = **ประเภทของสิ่งนั้น** ไม่ใช่การตกแต่ง (เจ้าของสั่ง 2026-09-06) ══
   ขาวล้วนอ่านง่ายก็จริง แต่มันทำให้ทุกอย่างดูเป็นของชนิดเดียวกันหมด
   ★ กติกา: **พื้นอ่อน + ขอบเข้มชุดเดิม** — สีบอกชนิด ส่วนความอ่านง่ายยังมาจากขอบกับออร่า
     ห้ามใช้สีฝ่าย (เขียว/น้ำเงิน/แดง) กับสัญลักษณ์เด็ดขาด — สามสีนั้นจองไว้ให้ *เจ้าของพื้นที่*
     ถ้าเอามาใช้กับรูปด้วย คนอ่านจะอ่านว่า "ป้อมนี้เป็นของวุ่ย" ทั้งที่รูปไม่ได้บอกข้างเลย */
#tkmap .pin.t-city    .pin-sym path:not(.gs){fill:#F2EDE2}   /* เมือง — งาช้าง */
#tkmap .pin.t-town    .pin-sym path:not(.gs){fill:#F6F2E8}   /* เมืองเล็ก — อ่อนกว่าหนึ่งขั้น */
#tkmap .pin.t-pass    .pin-sym path:not(.gs){fill:#D9C9A8}   /* ด่าน — หินทราย */
#tkmap .pin.t-fort    .pin-sym path:not(.gs){fill:#C9CFD6}   /* ป้อม — หินเทา */
#tkmap .pin.t-camp    .pin-sym path:not(.gs){fill:#E4D6A7}   /* ค่าย — ผ้าใบกระโจม */
#tkmap .pin.t-farm    .pin-sym path:not(.gs){fill:#CFE0A8}   /* ที่นา — ข้าวอ่อน */
#tkmap .pin.t-farm    .pin-sym path.gs{stroke:#4E6A2A}  /* ร่องนาเป็นสีเขียวเข้ม ไม่ใช่ดำ */
/* ★★ ภูเขา/ปากหุบ — **หินเทาอมฟ้า ไม่ใช่เขียว** (เจ้าของทัก 2026-09-06:
   *"สีภูเขาควรเป็นสีอื่นไหม เพราะมันค่อนข้างกลืนกับฉาก"* — ถูก)
   เขียวหม่น `#BFD3B4` เดิมนั่งอยู่บนพื้นกระดาษสีเขียวอ่อนกับหมึกภูเขาสีเขียวของแผ่นเอง
   → ค่าความสว่างต่างกันไม่ถึงขั้น ตาจึงอ่านมันเป็น "ส่วนหนึ่งของฉากหลัง" ไม่ใช่สัญลักษณ์
   ★ หินเทาอมฟ้าเป็นสีเย็นสีเดียวที่เหลือในจานนี้ (ยังไม่ชนกับสีฝ่ายและไม่ชนกับทองเมืองหลวง)
     และตรงความหมายด้วย — ภูเขาคือหิน · ป้อม `#C9CFD6` ใช้เทาเหมือนกันแต่เย็นกว่าหนึ่งขั้น */
#tkmap .pin.t-mountain .pin-sym path:not(.gs){fill:#B9C2CE}   /* ภูเขา — หินเทาอมฟ้า */
#tkmap .pin.t-mountain .pin-sym path{stroke:#2B3440}          /* ขอบเข้มอมน้ำเงิน ไม่ใช่ดำล้วน */
#tkmap .pin.t-valley_mouth .pin-sym path:not(.gs){fill:#C7CEDA}
#tkmap .pin.t-ford    .pin-sym path.gs{stroke:#2F6E8F}  /* ท่าข้าม — เส้นน้ำต้องเป็นสีน้ำ */
#tkmap .pin-role path{fill:#EBC77A}                 /* ยุ้งข้าว — สีเมล็ดข้าว */

/* ป้ายกับหมุดเฟดหายระหว่างกล้องเคลื่อน แล้วโผล่กลับมาตอนนิ่ง
   ทั้งเร็วกว่าและดูดีกว่าปล่อยให้วิ่งสะบัดตามกล้อง */
#L-labels, #L-pins, #L-focus{transition:opacity .28s ease}

.plabel{
  fill:#fff; font-weight:600; paint-order:stroke;
  stroke:#0b0d12; stroke-linejoin:round; pointer-events:none;
  dominant-baseline:alphabetic;
}
.plabel.hot{fill:var(--gold)}

/* ★★ ชื่อมณฑล (州) — ชั้น "ภาพรวม" ของแผ่นวาดใหม่ (เจ้าของสั่ง 2026-09-08)
   ต้องอ่านออกว่าเป็นคนละชนิดกับชื่อเมืองตั้งแต่แวบแรก จึงใช้ภาษาคนละแบบ

   ⚠⚠ **รอบแรกใช้ "จาง" เป็นตัวแยกชนิด แล้วเจ้าของทักว่า "มันกลืนกับฉาก"** (2026-09-08)
   — และเขาถูก · ตัวเลขเดิมคือ fill `rgba(255,255,255,.62)` บนฮาโล `rgba(11,13,18,.78)`
   คือ **จางทั้งตัวอักษรและฮาโล** พร้อมกัน ตัวหนังสือจึงไม่มีอะไรกันตัวเองจากภูมิประเทศเลย
   ★ ที่ถูกคือแยกชนิดด้วย **รูปแบบ** ไม่ใช่ด้วยความจาง:
     ตัวห่าง (letter-spacing) · ตัวใหญ่กว่า · สีเย็นอมฟ้าแทนขาวจัด · ฮาโลหนากว่าและทึบ
     → ยังอ่านออกทันทีว่าเป็นชั้นภูมิภาค แต่ไม่ต้องเพ่ง
   ⚠ ห้ามใช้สีฝ่ายกับชื่อนี้ — มณฑลไม่ใช่ของฝ่ายไหน */
.zlabel{
  fill:#D6E0F0; font-weight:700; paint-order:stroke;
  stroke:#0b0d12; stroke-linejoin:round; pointer-events:none;
  dominant-baseline:alphabetic;
}

/* ══ ★★★ เส้นแบ่งมณฑล (州界) — กลับมาแล้ว 2026-09-08 รอบสอง ═══════════════
   ข้อมูล `data/zhou_lines.js` · ตัวตรวจ `tools/check_zhou.js` · ที่มาเต็มอยู่หัวไฟล์นั้น

   ⚠ **ต้องอ่านว่าเป็นคนละภาษากับทุกเส้นที่มีอยู่แล้วบนแผ่น** — บนจอเดียวกันมี
     · เส้นประ **แดง** ที่แผ่นพิมพ์มาเอง = พรมแดนสามรัฐปี 221
     · เส้นประ **ทอง** 9/7 = วงเน้นพื้นที่ของฉาก (§17)
     · เส้น **ถนน** ทึบ/ประถี่
   → ของเราจึงเป็น **เทาอมฟ้าเย็น จังหวะยาว-ห่าง (10/8) และบางที่สุดในสามอัน**
     ไม่มีสีฝ่ายเด็ดขาด เพราะมณฑลไม่เปลี่ยนมือ ต่างจากสีเขต

   ★ `non-scaling-stroke` = ความหนากับจังหวะประคงที่บนจอเองทุกระดับซูม
     จึงไม่ต้องให้ `relayout` มาคูณ mu ให้เหมือน .road/.mk-route (เส้นเดียวในโปรเจกต์
     ที่ทำแบบนี้ได้ เพราะมันไม่มีหัวลูกศรหรือป้ายที่ต้องคำนวณตามไปด้วย) */
#L-zhou{pointer-events:none}
/* ปลอกสว่าง — ทำให้แกนหมึกเข้มอ่านออกทั้งบนพื้นสว่าง (ที่ราบ) และพื้นเข้ม (ป่า/ภูเขา)
   ⚠ ต้องไม่ประ ไม่งั้นจะเห็นเป็นเส้นประสองชั้นเหลื่อมกัน */
/* ⚠ ตัวเลขชุดนี้ **ลดลงหนึ่งขั้นเมื่อ 2026-09-10** (เจ้าของ: *"ดูแล้วรกแผนที่"*)
   จาก ปลอก .42/3.2px + แกน .62/1.25px → .28/2.8px + .46/1.15px
   ★ แต่ตัวแก้หลักของความรก **ไม่ได้อยู่ที่นี่** — อยู่ที่ `zhouMinVB()` ใน strategic.js
     (เดิมเส้นวาดต่อไปแม้ชื่อมณฑลหายหมดแล้ว = เส้นประไม่มีป้ายพาดจอทุกฉาก)
     ตรงนี้แค่ผ่อนให้ *ภาพรวม* ไม่หนาแน่นเกิน · ถ้าจะจูนต่อ ขยับสองค่านี้พอ */
.zline-case{
  stroke:#F4F1E6; stroke-opacity:.28; stroke-width:2.8px; stroke-linecap:round;
  vector-effect:non-scaling-stroke;
}
.zline{
  stroke:#2E3A4B; stroke-opacity:.46; stroke-width:1.15px;
  stroke-dasharray:9 7; stroke-linecap:butt;
  vector-effect:non-scaling-stroke;
}
/* ★ ท่อนที่ข้อมูลเองบอกว่า *หยาบ* (แผ่นไม่มีจุดอ้างอิงแถบนั้น) ต้องดูไม่มั่นใจกว่าท่อนอื่น
   — จางลงและประสั้นกว่า · ความไม่แน่นอนของข้อมูลควรมองเห็นได้ ไม่ใช่ซ่อนไว้ในคอมเมนต์ */
.zline.coarse{stroke-opacity:.4; stroke-dasharray:4 7}
.zline-case.coarse{stroke-opacity:.28}

/* หมุด/ลูกศร/ปะทะ ของฉากปัจจุบัน */
/* ★★ ออร่าต้อง **หาเจอโดยไม่ต้องหา** (เจ้าของ 2026-09-10: *"อ่านแล้วยังต้องหาเลยว่า
   อยู่ตรงไหน"*) — ดันความทึบขึ้นจาก .22 เป็น .34 และให้วงพองกว้างขึ้น (ดู r1 ใน strategic.js)
   ⚠ **ไม่**ดันด้วยการทำสีให้จัดขึ้น — นั่นคือสิ่งที่ทำให้รอบก่อนดู "ฉูดฉาดไม่เข้าโทนแผนที่" */
.mk-halo{fill:var(--ev,var(--gold)); opacity:.34; animation:pulse 2.2s ease-in-out infinite}
.mk-dot{fill:var(--gold); stroke:#0b0d12; stroke-width:1.5}
/* อยู่ในชั้นที่ถูก scale(mu) แล้ว ขนาดจึงเป็นพิกเซลจอตรง ๆ ไม่ต้องให้ JS คำนวณ */
.mk-label{fill:var(--gold); font-weight:700; font-size:16px;
  paint-order:stroke; stroke:#0b0d12; stroke-width:4.5px; stroke-linejoin:round}
.mk-cap{pointer-events:none}
/* ★★ วงกระเพื่อมต้องพองรอบ **รูปสัญลักษณ์** ไม่ใช่รอบจุดขนาดตายตัว (เจ้าของสั่ง 2026-09-06)
   รัศมีจึงมาจากตัวแปรที่ JS ตั้งตามขนาดรูปจริง · ค่าเริ่มต้นคือของเดิม (13→19)
   สำหรับสถานที่ที่ไม่มีรูปให้เกาะ */
@keyframes pulse{0%,100%{r:var(--r0,13px); opacity:var(--o0,.34)}
                 50%    {r:var(--r1,24px); opacity:var(--o1,.10)}}

/* ══ ★★★ จังหวะการเต้นบอกชนิดของเหตุการณ์ ไม่ใช่แค่สี (เจ้าของสั่ง 2026-09-06) ══
   สีอย่างเดียวไม่พอบนกระดาษที่มีทั้งเขียว น้ำเงิน และหมึกดำอยู่แล้ว — **จังหวะ**
   เป็นช่องสัญญาณที่ว่างอยู่ และตาคนจับความต่างของจังหวะได้ก่อนจับความต่างของเฉดสี
     รบ    เร็วและแรง — เหมือนชีพจรตอนตกใจ
     ธงพลิก ช้าและกว้าง — การเปลี่ยนมือของแผ่นดินไม่ใช่เรื่องเร่งรีบ
     เสบียง ช้าที่สุด สม่ำเสมอ — มันคือสายที่ไหลอยู่ตลอด ไม่ใช่เหตุการณ์ครั้งเดียว
   ⚠ ค่าที่ไม่ประกาศ = 2.2s ของเดิมทุกประการ (force / focus ไม่เปลี่ยนเลย)  */
.mk-pin.ev-battle .mk-halo{animation-duration:1.25s}
.mk-pin.ev-flip   .mk-halo{animation-duration:3.2s}
.mk-pin.ev-supply .mk-halo{animation-duration:3.8s}
/* วงของการรบต้องทึบกว่าเพื่อน — มันแข่งกับวงปะทะสีเหลืองที่ซ้อนอยู่จุดเดียวกัน
   ⚠ ตั้ง `opacity` ตรง ๆ ไม่ได้ — keyframes ทับเสมอ · ต้องผ่านตัวแปรที่ keyframes อ่าน */
/* วงของการรบทึบสุด — มันคือเหตุการณ์ที่ฉากอยากให้เห็นก่อนอย่างอื่นเสมอ */
.mk-pin.ev-battle .mk-halo{--o0:.46; --o1:.14}
.mk-pin.ev-flip   .mk-halo{--o0:.38; --o1:.11}
.mk-pin.ev-supply .mk-halo{--o0:.30; --o1:.09}

/* ป้ายธง — ใครเดินเส้นนี้ และมากับกี่คน · ราคาของวงปะทะ
   พื้นหลังต้องทึบพอ เพราะมันลอยอยู่บนแผนที่พื้นที่มีทั้งตัวหนังสือ ภูเขา และแม่น้ำ
   ทุกค่าเป็นหน่วยพิกเซลจอ ชั้น .mk-chip-s สเกลกลับให้เอง (strategic.js relayout) */
.mk-chip{transition:opacity .45s ease; pointer-events:none}
.mk-chip-pill{fill:rgba(10,12,17,.86); stroke:rgba(255,255,255,.16); stroke-width:1}
/* ป้ายธงพิมพ์ชื่อไทยแล้ว (DECISIONS §11) — ต้องมีฟอนต์ไทยนำ stack ไม่งั้นสระบน-ล่างเพี้ยน */
.mk-chip-txt{fill:#f0f2f8; font-size:12px; font-weight:600; dominant-baseline:alphabetic;
  font-family:"Leelawadee UI","Segoe UI",Tahoma,sans-serif; letter-spacing:.2px}

/* เส้นโยงป้าย→จุดยึด (รีวิวรอบสอง 2026-08-26 — "อีลุงตุงนังไม่รู้อันไหนของใคร")
   โผล่เฉพาะป้ายที่ถูกดันไกลจากของที่มันอธิบาย · เส้นสว่างบนขอบมืดแบบเดียวกับลูกศร
   ความหนาคุมโดย layoutAnnotations (คงที่บนจอ) · เฟดพร้อมป้ายของมัน */
.mk-leader-under{stroke:#0b0d12; stroke-opacity:.85; stroke-linecap:round;
  pointer-events:none; transition:opacity .45s ease}
.mk-leader{stroke:#e6ddc2; stroke-opacity:.8; stroke-linecap:round;
  pointer-events:none; transition:opacity .45s ease}

/* โหมดสองเอกภพ (§15 · c7-09 — เจ้าของเคาะ "Visual เลย")
   ผี = วงประซีดกับตัวหนังสือเทา — ของอีกเอกภพต้องดูเหมือนความทรงจำ ไม่ใช่ของจริง
   สีแผ่นดินพลิกด้วยกลไก setOwners เดิม (ได้แอนิเมชัน flip ฟรี) */
.mk-mirror{pointer-events:none; animation:mirrorIn .9s ease}
@keyframes mirrorIn{from{opacity:0} to{opacity:1}}
.mk-ghost-dot{fill:none; stroke:#c9cdd6; stroke-width:2; stroke-dasharray:3 3; opacity:.85}
.mk-ghost-txt{fill:#c9cdd6; font-size:12.5px; font-weight:600; paint-order:stroke;
  stroke:#0b0d12; stroke-width:3.5px; stroke-linejoin:round;
  font-family:"Leelawadee UI","Segoe UI",Tahoma,sans-serif}
.mk-mirror-txt{fill:#e6ddc2; font-size:15px; font-weight:700; letter-spacing:.4px;
  paint-order:stroke; stroke:#0b0d12; stroke-width:4.5px; stroke-linejoin:round;
  font-family:"Leelawadee UI","Segoe UI",Tahoma,sans-serif}

/* ══ โหมดถนน (ปุ่ม "ถนน" · DECISIONS §15) ══
   ฉากหลังจาง ๆ ที่บอกว่ากองทัพ *เลือกทางได้เท่านี้* — ต้องไม่แย่งสายตาไปจากลูกศรของฉาก
   จึงเป็นสีเดียวทั้งกราฟ ไม่ผูกกับฝ่ายไหน · ความหนา/ระยะประคุมโดย relayout() (คงที่บนจอ) */
.road{stroke:#c9b071; stroke-opacity:.55; stroke-linecap:round; stroke-linejoin:round;
  filter:drop-shadow(0 0 2px rgba(0,0,0,.55))}
.road-horse{stroke-opacity:.42}          /* wagons:false — ทางม้า ไม่ใช่ถนนเกวียน */
.road-node{fill:#12151a; stroke:#c9b071; stroke-opacity:.7}
.mk-route{fill:none; stroke-width:4; stroke-linecap:round; opacity:.95;
  filter:drop-shadow(0 0 4px rgba(0,0,0,.6))}
/* ขอบมืดใต้เส้นทาง (ลูกศรแบบ ข — เจ้าของเคาะ 2026-08-25) — สี inline จาก strategic.js
   ห้ามมีเงาซ้อน ไม่งั้นเส้นบวมเป็นแถบดำ */
.mk-route-under{opacity:.5; filter:none}
/* ขบวนเสบียง: เส้นบางกว่า จางกว่า และเป็นเส้นประหลังวิ่งถึง (ลายประตั้งจาก strategic.js
   เพราะมันต้องคงที่บนจอ) — มันคือสายที่ไหลอยู่ตลอด ไม่ใช่การเดินทัพครั้งเดียว */
.mk-route.supply{opacity:.88}
/* กองเรือ — เส้นสีทึบเหมือนทัพบก (มันคือกองทัพ ไม่ใช่สายที่ไหลอยู่ตลอดแบบเสบียง)
   ส่วนเงาใต้เส้นเป็นลายคลื่น ทำใน strategic.js เพราะระยะประต้องคงที่บนจอ
   ที่นี่คุมแค่ความเข้ม */
.mk-route.fleet{opacity:.95}
.mk-route-under.fleet{opacity:.55}
.mk-route-under.supply{opacity:.4}
/* ถอยทัพ: เส้นจางกว่าและหน่วยเป็นโครงกลวง ให้อ่านออกทันทีว่าไม่ใช่การบุก */
.mk-route.retreat{opacity:.6}
.mk-route-under.retreat{opacity:.3}
.mk-unit.retreat{opacity:.85}
.mk-unit{filter:drop-shadow(0 1px 3px rgba(0,0,0,.8))}
/* หัวลูกศรของเรา (โผล่ตอนเดินถึง) กับจุดแวะตาม node ระหว่างทาง */
.mk-head{filter:drop-shadow(0 1px 2px rgba(0,0,0,.7)); transition:opacity .3s ease}
.mk-head.retreat{opacity:.85}
.mk-ticks{transition:opacity .3s ease}
.mk-tick{stroke:#0b0d12; stroke-width:1.2}
/* บั๊กเดียวกับวงไฟในสมรภูมิ — ต้องมี transform-box ไม่งั้นวงแหวนเหวี่ยงหลุดตำแหน่ง */
/* ★★★ วงปะทะเป็น **สีของเหตุการณ์** ไม่ใช่สีเหลืองตายตัวอีกต่อไป (2026-09-10)
   เจ้าของเสนอเอง: *"ตรงที่มีการปะทะเราใช้สีโดนแดงดีไหมและมีกระเพื่อมๆ"*
   ⚠ เดิม stroke ตรึง #ffcf5c ไว้ตรงนี้ — แปลว่าถึง strategic.js จะส่งสีมา วงก็ยังเหลือง
     (นั่นคือเหตุผลที่ "สีของเหตุการณ์" มองไม่เห็นผลที่จุดปะทะเลยสักฉาก)
   ★ ขอบมืดใต้วง = สิ่งที่ทำให้สีเข้มอ่านออกบนกระดาษสว่าง โดยไม่ต้องเพิ่มความจัดของสี */
.mk-clash-ring{fill:none; stroke:var(--ev,#8F2A1B); stroke-width:3.2; opacity:1;
  filter:drop-shadow(0 0 1.5px rgba(0,0,0,.55));
  animation:ring 1.6s ease-out infinite;
  transform-box:fill-box; transform-origin:center}
.mk-clash-ring.r2{animation-delay:.55s}
.mk-clash-x{fill:none; stroke:var(--ev,#8F2A1B); stroke-width:4; stroke-linecap:round;
  filter:drop-shadow(0 0 1.5px rgba(0,0,0,.6))}
@keyframes ring{0%{transform:scale(.5); opacity:1} 100%{transform:scale(1.5); opacity:0}}

/* ══ แถบเวลา ══ */
#time{grid-area:time; background:var(--panel); border-top:1px solid var(--line);
  padding:8px var(--pad) 11px; display:flex; align-items:flex-end; gap:14px}
#tstack{flex:1; display:flex; flex-direction:column; gap:4px; min-width:0}

/* แถวภาค — กดกระโดดไปต้นภาคได้ */
#chapstrip{display:flex; gap:5px}
.chapbtn{flex:1 1 0; min-width:0; padding:3px 2px 4px; border:0; border-radius:4px;
  background:#21263280; color:var(--dim); cursor:pointer; line-height:1.15;
  display:flex; flex-direction:column; align-items:center; gap:1px;
  transition:background .18s, color .18s}
.chapbtn b{font-size:12px; font-weight:700}
.chapbtn i{font-size:9px; font-style:normal; opacity:.7; white-space:nowrap;
  overflow:hidden; text-overflow:clip}
.chapbtn:hover{background:#2e3546; color:var(--text)}
.chapbtn.now{background:#3a3320; color:var(--gold)}

#track{display:flex; gap:5px; height:20px; cursor:ew-resize; touch-action:none}
#chapstrip{touch-action:none}
#track.scrubbing .tcell{transition:none}
.hint b{color:var(--gold); font-weight:600}
.tgrp{display:flex; gap:2px; flex:1 1 0; min-width:0; padding:0 3px;
  border-bottom:2px solid var(--line); border-radius:2px}
.tgrp:nth-child(even){border-bottom-color:#39415a}
/* ⚠ padding:0 ต้องอยู่ตรงนี้ ไม่ใช่เฉพาะในบล็อกมือถือ — วัดจริงในเบราว์เซอร์ 2026-08-22
   .tcell เป็น <button> เบราว์เซอร์ใส่ padding ปริยายมาให้ราว 6px สองข้าง = 12px ต่อช่อง
   ที่ 95 ฉาก นั่นแปลว่าแถวช่องกว้างจริงเกิน 1300px ในกล่องที่กว้างราว 1400px
   ช่องจึงเบียดกันจนขอบหาย กลายเป็นแท่งยาวติดกันเป็นพรืด (อาการที่ผู้ใช้เห็น) และช่องท้าย ๆ
   ถูกดันออกไปทับ #counter หรือหลุดนอกจอ — คือคลิกทีละฉากไม่ได้เลยในครึ่งหลังของเล่ม
   โปรเจกต์พี่น้อง (เรื่องกวนอู) เจอบั๊กเดียวกันที่ 61 ฉาก และแก้ด้วยบรรทัดนี้เมื่อ 2026-08-20
   คิดใหม่หลังแก้: 95 ฉาก = ราว 760px ในกล่อง 1400px ยังเหลือที่ให้เล่มยาวขึ้นอีกมาก
   (กฎในบล็อก @media มือถือยังต้องอยู่ ตรงนั้นต้องปล่อย min-width ลงเป็น 0 ด้วย) */
.tcell{flex:1; min-width:5px; padding:0; border:0; border-radius:2px; cursor:pointer;
  background:#2b3141; transition:background .2s, transform .15s}
.tcell:hover{background:#48516b; transform:scaleY(1.25)}
.tcell.done{background:#4a5570}
.tcell.now{background:var(--gold); transform:scaleY(1.5)}
#counter{color:var(--dim); font-size:12px; font-variant-numeric:tabular-nums; min-width:56px;
  text-align:right}

/* ★★ แถบบนซ้าย — `#where` + `#hud` เรียงแถวเดียวกับปุ่มขวาบน (เจ้าของสั่ง 2026-09-08)
   ⚠ `right` ต้องเว้นที่ให้ `#maptools` ไม่งั้น HUD จะไหลไปทับปุ่ม
     ค่านี้กว้างกว่าปุ่มจริง (495px) นิดหน่อยเผื่อฟอนต์ต่างเครื่อง */
#topleft{position:absolute; left:var(--pad); top:var(--pad); right:calc(var(--pad) + 520px);
  z-index:5; display:flex; align-items:center; gap:10px; flex-wrap:wrap; pointer-events:none}
#topleft > *{pointer-events:auto}

/* ══ HUD ══
   ★★ ย้ายจาก **มุมล่างซ้ายแนวตั้ง** มาเป็น **แถบแนวนอนใต้ `#where`** (เจ้าของสั่ง 2026-09-08)
   > *"หลอดกำลังพลมันบังแผนที่ กำลังคิดว่าจะย้ายไปเป็นแนวนอนมุมบนซ้ายจะดีไหม
   >  เพราะบางฉากมันก็บังแผนที่จริง ๆ"*

   ★ ทำไมแนวนอนถึงบังน้อยกว่า: ของเดิมเป็นกล่อง 250 × ~150 px นั่งทับมุมล่างซ้าย
     ซึ่งบนแผ่นนี้คือ **อี้โจว/เสฉวน** — เวทีของจ๊กทั้งเรื่อง · แนวนอนสูงแค่ ~34 px
     และไปอยู่ในแถบบนซึ่งเป็นพื้นที่ของเครื่องมืออยู่แล้ว

   ⚠ `top` คิดจากความสูงของ `#where` (หัวหนา 1 บรรทัด + บรรทัดรอง = ~46px + เว้น)
     `#where` มีสองบรรทัดคงที่เสมอ ค่านี้จึงนิ่ง — ถ้าวันหนึ่งมันยาวขึ้นเป็นสามบรรทัด
     ต้องขยับเลขนี้ตาม (ไม่มีทางคำนวณอัตโนมัติเพราะทั้งคู่เป็น absolute คนละตัว)
   ⚠ **ห้ามใช้ `bottom`** อีก — แถบเวลาด้านล่างกับกล่องนี้เคยเบียดกันบนจอเตี้ย */
#hud{position:relative; z-index:4; flex:0 1 auto; min-width:0;
  background:rgba(14,16,21,.82); backdrop-filter:blur(9px);
  border:1px solid var(--line); border-radius:10px; padding:7px 12px;
  display:flex; flex-direction:row; align-items:center; flex-wrap:wrap; gap:6px 14px}
/* หัวข้อบอกว่าหลอดวัดอะไร — ถ้าไม่บอก คนอ่านเดาไม่ออกว่าเทียบกับอะไร
   แนวนอนแล้วเส้นคั่นย้ายจากใต้หัวข้อ ไปอยู่ *ขวา* ของมันแทน */
.hhead{font-size:10px; color:var(--dim); letter-spacing:.4px;
  padding-right:12px; border-right:1px solid var(--line); flex:none}
.hrow{display:flex; flex-direction:row; align-items:center; gap:7px; font-size:11.5px; flex:none}
.htop{display:flex; align-items:baseline; gap:6px}
.hname{font-weight:700; color:var(--text); display:flex; align-items:center; gap:5px}
.hdot{width:9px; height:9px; border-radius:2px; flex:none; display:inline-block}
.hbar{height:6px; width:54px; flex:none; background:#232836; border-radius:3px; overflow:hidden}
.hbar i{display:block; height:100%; width:0; border-radius:3px; transition:width .9s ease}
.hnum{color:var(--dim); font-size:10.5px; font-variant-numeric:tabular-nums; white-space:nowrap}
/* ★ บรรทัดแนวตะวันตก — ชั้นกลางระหว่าง "ทั้งรัฐ" กับ "กองที่อยู่ในฉาก" (2026-08-27)
   เส้นคั่นบอกว่ามันไม่ใช่หลอดที่สี่ แต่เป็นการซูมเข้าไปในสามหลอดข้างบน
   แนวนอนแล้วเส้นคั่นย้ายจากด้านบน มาอยู่ *ซ้าย* แทน */
.hfront{display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  padding-left:12px; border-left:1px solid var(--line); font-size:10.5px; flex:none}
.hfl{color:var(--dim); letter-spacing:.3px}
.hfv{color:var(--text); display:inline-flex; align-items:center; gap:4px;
  font-variant-numeric:tabular-nums; white-space:nowrap}
.hfv .hdot{width:7px; height:7px}

/* ══ แผงเนื้อเรื่อง ══ */
aside{grid-area:side; background:var(--panel); border-left:1px solid var(--line);
  display:flex; flex-direction:column; overflow:hidden; min-height:0; min-width:0}
/* แถบบนบอกว่าอ่านถึงภาคไหนปีไหน ค้างอยู่กับที่ตลอด */
.head{padding:13px var(--pad) 11px; border-bottom:1px solid var(--line);
  display:flex; justify-content:space-between; align-items:baseline; gap:10px}
#nowchap{color:var(--gold); font-size:12.5px; font-weight:700; letter-spacing:.3px}
#nowyear{color:var(--dim); font-size:11.5px; white-space:nowrap}

/* เครดิตแผนที่ — DECISIONS §2 บังคับให้แสดงท้ายหน้าเสมอ ห้ามซ่อนแม้บนจอแคบ
   flex:none กันไม่ให้โดนบีบหายตอนคอลัมน์นิยายยาว */
.credit{flex:none; padding:7px var(--pad) 9px; border-top:1px solid var(--line);
  font-size:10.5px; line-height:1.55; color:var(--dim)}
.credit a{color:var(--dim); text-decoration:underline; text-underline-offset:2px}
.credit a:hover{color:var(--gold)}

/* ══ นิยาย ══ */
.body{flex:1 1 0; min-height:0; overflow-y:auto; padding:8px var(--pad) 0;
  scroll-behavior:smooth}

.chapmark{margin:26px 0 18px; padding-bottom:9px; border-bottom:1px solid var(--line)}
.chapmark:first-child{margin-top:6px}
.chapmark b{display:block; color:var(--gold); font-size:15px; letter-spacing:.3px}
.chapmark i{display:block; color:var(--dim); font-size:11px; font-style:normal; margin-top:2px}

.beat{padding:14px 0 20px; opacity:.42; transition:opacity .35s ease;
  border-left:2px solid transparent; padding-left:13px; margin-left:-15px;
  transition:opacity .35s ease, border-color .35s ease}
.beat.now{opacity:1; border-left-color:var(--gold)}
.beat:hover{opacity:.75}
.beat.now:hover{opacity:1}
.bmeta{color:var(--dim); font-size:11px; letter-spacing:.3px}
.btitle{font-size:17.5px; font-weight:700; line-height:1.4; margin:4px 0 9px;
  font-family:"Palatino Linotype",Cambria,Georgia,serif; letter-spacing:.01em}

.text{font-size:15px; line-height:1.72; text-indent:1.6em; text-align:justify;
  font-family:"Palatino Linotype",Cambria,Georgia,serif}
.text.watcher{
  font-style:italic; color:#cdd4e6; text-indent:0;
  border-left:2px solid rgba(217,177,105,.45); padding-left:14px;
}
/* ประกาศพื้นที่เปลี่ยนมือ — อยู่ในตอนนั้นเลย คนอ่านเห็นพร้อมข้อความ */
.chg:not(:empty){margin-top:15px}
.chead{font-size:10.5px; color:var(--dim); text-transform:uppercase;
  letter-spacing:.8px; font-weight:600; margin-bottom:7px}
.crow{display:flex; align-items:center; gap:8px; font-size:12.5px;
  padding:7px 11px; margin-bottom:5px; border-radius:7px;
  background:#20242f; border-left:3px solid var(--gold)}
.cname{flex:1; font-weight:700}
.carrow{color:var(--dim)}
.cfrom, .cto{font-weight:600}
/* ราคาที่จ่าย — แถวเดียวกับพื้นที่เปลี่ยนมือ แต่ขอบซ้ายจาง เพราะเป็นการ "เสีย" ไม่ใช่การ "ได้"
   .chead ตัวที่สองต้องมีที่หายใจเหนือมัน ไม่งั้นสองบล็อกอ่านเป็นตารางเดียวกัน */
.crow.loss{border-left-color:#7a4a4a}
.cnum{font-variant-numeric:tabular-nums; color:var(--dim); font-weight:600}
.chead + .crow ~ .chead{margin-top:13px}

.fact{display:inline-block; margin-top:15px; padding:5px 12px; border-radius:20px;
  font-size:11.5px; font-weight:700; cursor:pointer; user-select:none; border:1px solid}
.f-real{color:#6fd39a; border-color:#2f6d4b; background:#152a1f}
.f-fic {color:#e78ba3; border-color:#7a3547; background:#2b1620}
.f-mix {color:#e8c274; border-color:#7a6231; background:#2a2416}
.fnote{max-height:0; overflow:hidden; transition:max-height .3s ease, margin .3s;
  font-size:12.5px; line-height:1.8; color:var(--dim)}
.fnote.open{max-height:340px; margin-top:10px}

.foot{padding:13px var(--pad) 16px; border-top:1px solid var(--line);
  display:flex; gap:9px; align-items:center}
button{font-family:inherit; font-size:13.5px; cursor:pointer; border-radius:7px;
  border:1px solid var(--line); background:var(--panel2); color:var(--text);
  padding:10px 15px; transition:background .15s, border-color .15s}
button:hover:not(:disabled){background:#282e3d; border-color:#454e66}
button:disabled{opacity:.32; cursor:default}
#btnNext{flex:1; background:var(--gold); color:#1b1405; border-color:var(--gold);
  font-weight:700}
#btnNext:hover:not(:disabled){background:#e8c27f}
#btnReset{padding:10px 12px}

.hint{padding:0 var(--pad) 13px; color:#5f6779; font-size:10.5px; line-height:1.6}

::-webkit-scrollbar{width:9px}
::-webkit-scrollbar-thumb{background:#333a4c; border-radius:5px}
::-webkit-scrollbar-track{background:transparent}

/* จอแคบ: วางแผนที่บน นิยายล่าง — ล็อกความสูงทั้งสองส่วนไว้ชัดเจน
   ห้ามใช้ 1fr กับแถวแผนที่ตรงนี้ เพราะสัดส่วนในตัวของ SVG จะดันให้บานอีก */
@media (max-width:1100px){
  body{grid-template-columns:minmax(0,1fr); grid-template-rows:46vh minmax(0,1fr) auto;
       grid-template-areas:"map" "side" "time"}
  aside{border-left:0; border-top:1px solid var(--line)}
  #hud{transform:scale(.92); transform-origin:left top}   /* แนวนอนแล้ว origin ต้องเป็น top */
}

/* ══ มือถือ ══
   วัดที่ 500px แล้วเจอสองเรื่อง ไม่ใช่เรื่องที่เดาไว้จากการดูภาพ:
   1. #track ล้น 279px — ช่องละ min-width:5px + ช่องไฟ ยัดไม่ลงในราว 400px
      (ตอนวัดมี 71 ฉาก ตอนนี้ 95 — ยิ่งแน่นกว่าเดิม กฎด้านล่างยังจำเป็นอยู่)
   2. ช่องอ่านเหลือสูง 105px ประมาณสี่บรรทัด เพราะแผนที่กิน 46vh แล้วยังมี
      หัว + คำใบ้ + ปุ่ม + เครดิต มาแบ่งที่อีก
   ส่วนตัวหนังสือไม่ได้ล้นขอบอย่างที่เห็นในภาพ — วัดแล้วพอดีกรอบ */
@media (max-width:700px){
  /* คืนที่ให้คนอ่าน แผนที่ยังใหญ่พอเห็นลูกศรเดินทัพ */
  body{grid-template-rows:38vh minmax(0,1fr) auto}

  /* คำใบ้เป็นปุ่มลูกศรกับล้อเมาส์ ซึ่งบนมือถือไม่มีทั้งคู่ — เอาที่คืนให้เนื้อเรื่อง */
  .hint{display:none}

  /* ปล่อยให้ช่องเล็กลงได้ตามจริง ไม่งั้นแถบเวลาดันตัวเองล้นจอ
     ต้องล้าง padding ด้วย — .tcell เป็น <button> ที่เบราว์เซอร์ใส่ padding มาให้เอง
     ลด min-width อย่างเดียวจึงยังล้นอยู่ 248px เพราะจำนวนปุ่มคูณ padding ปริยาย */
  .tcell{min-width:0; padding:0}
  #track{gap:2px}
  .tgrp{gap:1px; padding:0 1px}
  #chapstrip{gap:2px}
  .chapbtn i{display:none}          /* ช่วงปีอ่านไม่ทันอยู่แล้วตอนกว้าง 40px */
  #time{gap:8px; padding:6px 10px 8px}
  #counter{min-width:44px; font-size:11px}

  :root{--pad:12px}
  .btitle{font-size:16px}
  .text{font-size:15.5px; line-height:1.65}   /* phone reading needs a size up from desktop */
  /* -15/+13 บนเดสก์ท็อปมีไว้ให้เส้นทองของตอนที่กำลังอ่านออกไปอยู่นอกแนวข้อความ
     พอ --pad เหลือ 12 มันดันข้อความไปชิดขอบจอจนอึดอัด ย่อระยะลงให้ได้ที่หายใจ */
  .beat{padding:11px 0 16px 8px; margin-left:-8px}
  /* .hnum เป็น nowrap บนเดสก์ท็อปเพื่อไม่ให้ "130k troops" ตกบรรทัด
     พอย่อลงมาขนาดนี้ nowrap กลายเป็นตัวตัดข้อความทิ้ง — วัดที่ 680px แล้วเหลือแค่
     "4 regions · 1.1M peop" ปล่อยให้ตกบรรทัดได้ และคืนความกว้างให้หน่อย */
  /* จอแคบ: ปล่อยให้แถบตกบรรทัดเองแทนการย่อ — ย่อแล้วตัวเลขอ่านไม่ออก */
  #hud{transform:scale(.82); transform-origin:left top; gap:4px 10px}
  .hnum{white-space:normal; line-height:1.35}
}

/* ══ ★ หน้าเปิด (เพิ่ม 2026-09-01) ═════════════════════════════════════════
   จอเดียวก่อนเข้าเรื่อง · ปิดแล้วถูก remove() ออกจาก DOM ไปเลย ไม่ใช่แค่ซ่อน
   (ถ้าแค่ซ่อน มันยังกิน pointer-events ในบางเบราว์เซอร์แล้วแผนที่ลากไม่ได้)
   ⚠ ห้ามใช้ position:fixed อย่างเดียว — body เป็น grid + overflow:hidden
     ต้อง inset:0 กับ z-index สูงกว่า #time (ซึ่งไม่ได้ตั้ง z-index ไว้) */
#intro{
  position:fixed; inset:0; z-index:9000;
  background:rgba(9,11,15,.93); backdrop-filter:blur(3px);
  display:flex; align-items:center; justify-content:center;
  padding:24px; overflow:auto;
  animation:introIn .35s ease;
}
@keyframes introIn{from{opacity:0}to{opacity:1}}
#intro .sheet{
  max-width:680px; width:100%;
  background:var(--panel); border:1px solid var(--line); border-radius:14px;
  padding:34px 38px 26px;
  box-shadow:0 24px 70px rgba(0,0,0,.6);
}
#intro .kicker{color:var(--gold); font-size:13px; letter-spacing:.04em; margin-bottom:8px}
#intro h1{font-size:27px; line-height:1.35; font-weight:700; margin-bottom:16px}
#intro .lede{font-size:15px; line-height:1.85; color:var(--text); margin-bottom:12px}
#intro .lede b{color:var(--gold); font-weight:600}
#intro .dimline{color:var(--dim)}
#intro .dimline b{color:var(--text)}
#intro .scale{
  font-size:13px; color:var(--dim); border-top:1px solid var(--line);
  padding-top:14px; margin-top:16px;
}
#intro .scale b{color:var(--text)}
#intro .acts{display:flex; gap:10px; margin:18px 0 4px; flex-wrap:wrap}
#intro .acts button{
  font:inherit; font-size:15px; cursor:pointer;
  padding:11px 22px; border-radius:9px;
  background:var(--panel2); color:var(--text); border:1px solid var(--line);
}
#intro .acts button:hover{border-color:var(--gold)}
#intro .acts .primary{background:var(--gold); color:#1a1408; border-color:var(--gold); font-weight:700}
#intro .acts .primary:hover{filter:brightness(1.08)}

/* ③ สามฉาก — ซ่อนไว้จนกดปุ่ม "ดูสามฉากก่อน" */
#intro .peeks{display:none; flex-direction:column; gap:8px; margin-top:14px}
#intro.peek .peeks{display:flex; animation:introIn .3s ease}
#intro .peeks button{
  font:inherit; text-align:left; cursor:pointer;
  background:var(--panel2); color:var(--text);
  border:1px solid var(--line); border-radius:9px; padding:12px 14px;
  display:flex; flex-direction:column; gap:3px;
}
#intro .peeks button:hover{border-color:var(--gold); background:#232838}
#intro .peeks b{font-size:14.5px; font-weight:600}
#intro .peeks span{font-size:12.5px; color:var(--dim); line-height:1.6}
#intro .fine{font-size:11.5px; color:var(--dim); line-height:1.8; margin-top:18px}
#intro .fine a{color:var(--dim)}

@media (max-width:700px){
  #intro{padding:12px}
  #intro .sheet{padding:24px 20px 20px}
  #intro h1{font-size:22px}
  #intro .lede{font-size:14px}
  #intro .acts button{flex:1 1 auto}
}

/* ══ ★ แถบอ่านต่อ + ลิงก์กลับหน้าเปิด (เพิ่ม 2026-09-02) ════════════════════
   เสนอ ไม่ใช่ยึด — เปิดมายังเริ่มที่ฉากแรกเหมือนเดิม แถบนี้แค่ให้ทางลัดหนึ่งคลิก */
#resume{
  display:flex; align-items:center; gap:8px;
  margin:0 var(--pad) 8px; padding:9px 11px;
  background:var(--panel2); border:1px solid var(--line);
  border-left:3px solid var(--gold); border-radius:8px;
  font-size:12.5px; color:var(--dim);
}
#resume[hidden]{display:none}
#resume .rtext{flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
#resume b{color:var(--text); font-weight:600}
#resume button{
  font:inherit; font-size:12.5px; cursor:pointer; white-space:nowrap;
  background:transparent; color:var(--gold);
  border:1px solid var(--line); border-radius:6px; padding:4px 10px;
}
#resume button:hover{border-color:var(--gold)}
#resume #resumeNo{color:var(--dim); padding:4px 8px}

/* ปุ่มที่หน้าตาเหมือนลิงก์ — ใช้ในบรรทัดคำใบ้ท้ายคอลัมน์ */
.linkish{
  font:inherit; background:none; border:0; padding:0; cursor:pointer;
  color:var(--gold); text-decoration:underline; text-underline-offset:2px;
}

/* กันหน้าเปิด "แว้บ" ตอนโหลด — คลาสนี้ถูกติดโดยสคริปต์จิ๋วใน <head> ก่อน paint
   (ดูคอมเมนต์ยาวที่ index.html) · ui.js ถอดออกเองถ้าตัดสินใจว่าจะโชว์จริง */
html.no-intro #intro{display:none}

/* ══ ★★ ตารางสัญลักษณ์ (ปุ่ม "สัญลักษณ์" · 2026-09-05) ══
   วางใต้แถบปุ่มมุมขวาบน · z-index ต่ำกว่าปุ่มเอง จะได้ไม่บังปุ่มที่ใช้ปิดมัน
   (บทเรียนเดียวกับ #spine ที่เคยคลุมปุ่มตัวเองจนคนอ่านติดอยู่ข้างใน) */
#legend{position:absolute; right:var(--pad); top:calc(var(--pad) + 40px); z-index:7;
  width:298px; max-height:calc(100% - 110px); overflow-y:auto;
  background:rgba(14,16,21,.94); backdrop-filter:blur(10px);
  border:1px solid var(--line); border-radius:10px; padding:11px 13px 13px;
  box-shadow:0 10px 30px rgba(0,0,0,.5); font-size:11.5px; line-height:1.45}
#legend .lg-head{color:var(--gold); font-size:10.5px; font-weight:700; letter-spacing:.3px;
  margin:11px 0 5px; padding-bottom:4px; border-bottom:1px solid var(--line)}
#legend .lg-head:first-child{margin-top:0}
.lg-row{display:flex; gap:9px; align-items:flex-start; padding:3px 0}
.lg-ico{flex:0 0 26px; height:26px; display:flex; align-items:center; justify-content:center}
.lg-row b{display:block; color:var(--text); font-weight:600}
.lg-row span{display:block; color:var(--dim); font-size:10.5px; line-height:1.35}
/* ⚠ ต้องเป็นสีอ่อนที่นี่ — พาเนลพื้นมืด ต่างจากบนแผนที่ที่พื้นเป็นกระดาษ */
#legend svg path{fill:#dfe3ec; fill-opacity:.95; stroke:none}
#legend svg path.gs{fill:none; stroke:#dfe3ec; stroke-linecap:round}
#legend .lg-unit{fill:var(--gold)}
#legend .lg-wall{stroke:#c9c1ad; stroke-width:2.4}
#legend .lg-wall-t{stroke:#c9c1ad; stroke-width:1.6; fill:none}
#legend .lg-spine{stroke:#9a927f; stroke-width:1.4}
#legend .lg-fort{fill:var(--han); stroke:#0b0d12; stroke-width:1}
#legend .lg-stake{stroke:#9a927f; stroke-width:1.5; fill:none; stroke-linecap:round}
.lg-sides{display:flex; gap:10px; flex-wrap:wrap; align-items:center;
  color:var(--dim); font-size:10.5px; margin-top:7px}
.lg-sides i{display:inline-block; width:9px; height:9px; border-radius:2px; margin-right:4px}
.lg-foot{color:var(--dim); font-size:10.5px; line-height:1.4; margin-top:9px;
  padding-top:8px; border-top:1px solid var(--line)}

/* ══ ★★ สถานที่ที่ฉากชี้ให้ดู = **รูปของมันเองสว่างขึ้น** ไม่ใช่หมุดกลมทับมัน ══
   เจ้าของสั่ง 2026-09-06: *"เราสามารถเอาพวกหมุดกลมๆ ใหญ่ๆ ของเราออกได้
    และใช้สัญลักษณ์นั้นแทนไปเลย เวลาทำ Animation กระเพื่อมก็ทำโดยใช้สัญลักษณ์นั้นไปเลย"*

   ทำไมถึงถูก: หมุดกลมทับรูป = เอาของที่ไม่มีความหมายไปบังของที่มีความหมาย
   และมันบังคับให้เราเลื่อนรูปหนี ซึ่งทำให้ตำแหน่งเมืองเพี้ยน (ลองแล้วในคอมมิตก่อน — ถอยกลับ)
   ★ รูปอยู่ที่พิกัดจริงเสมอ · ฉากชี้ตรงไหน รูปตรงนั้นติดไฟแล้วมีวงพองรอบตัว

   ══ ★★★ แก้ 2026-09-06 รอบสอง — **ไฟไม่ใช่สีทองอีกต่อไป** ═══════════════════════
   เจ้าของทัก: *"การ Highlight เมืองที่มีเหตุการณ์เป็นติดไฟสีทอง ... ไม่งั้นทุกอย่าง
    จะเหมือนเมืองหลวงไปหมด เราต้องแยกมันตามเหตุการณ์ · การสู้รบเป็นสีนึง
    การเล่าเรื่องเน้นตรงนั้นเป็นสีนึง"* — ถูกทั้งสองข้อ:
     (1) `#F3D590` ที่ใช้เป็นสีไฟ **คือสีเดียวกับพื้นรูปเมืองหลวงเป๊ะ ๆ** (ดูกฎ t-capital
         ข้างบน) → เมืองเล็กที่ฉากชี้ อ่านออกมาเป็น "เมืองหลวง" ทุกครั้ง
     (2) ไฟสีเดียวแปลว่า "ตรงนี้มีอะไร" แต่ไม่ได้บอกว่า **อะไร**

   ★ กติกาใหม่ — สามช่องสัญญาณ แยกหน้าที่กันเด็ดขาด:
       **พื้นรูป**  = ชนิดของสถานที่ (เมือง/ด่าน/ค่าย/ที่นา) — ไฟ**ไม่แตะ**พื้นรูปเลย
                     จึงไม่มีทางกลายเป็นเมืองหลวง และไม่มีทางกลายเป็นสีฝ่าย
       **ขอบ+ออร่า** = ชนิดของเหตุการณ์ (`--ev` ที่ strategic.js ตั้งให้ต่อหมุด)
       **ป้าย**     = ฝ่าย (สีชิปเหมือนเดิม)
   ⚠ ออร่าขาวของกฎฐาน (#tkmap .pin-sym) ถูกกฎนี้ทับ — จึงต้องเขียนชั้นขาวกลับเข้ามา
     เองในนี้ ไม่งั้นรูปที่ติดไฟจะอ่านไม่ออกบนชื่อเมืองสีดำที่แผ่นพิมพ์ไว้ */
#tkmap .pin.hot .pin-sym path{stroke:var(--ev,#5A420C); stroke-width:2.1}
/* ★ ไอคอนชุดใหม่ทาสีด้วย inline style (เพื่อรักษาเงาสองระดับ) ซึ่งชนะ selector ทุกตัว
   → สถานะ "ฉากชี้มาที่นี่" ต้องใช้ `!important` เพื่อทวงเส้นขอบคืนมาให้สีเหตุการณ์
   ⚠ นี่คือที่เดียวในไฟล์ที่ใช้ !important และมีเหตุผลเฉพาะข้อนี้ ห้ามลอกไปใช้ที่อื่น */
#tkmap .pin.hot .pin-sym path.art{stroke:var(--ev,#5A420C) !important; stroke-width:1.2}
#tkmap .pin.hot .pin-sym path.gs{fill:none; stroke:var(--ev,#5A420C)}
#tkmap .pin.hot .pin-role path{stroke:var(--ev,#5A420C); stroke-width:1.4}
/* ⚠ ออร่าสีชั้นเดียวเท่านั้น — ลองซ้อนสองชั้น (3.5px + 7px) แล้วสีทับสีจนกลายเป็น
   ก้อนดำขุ่นรอบรูป (ตรวจด้วยภาพจริง c7-04 2026-09-06) · ชั้นขาวต้องมาก่อนเสมอ
   มันคือชั้นที่ดันชื่อเมืองสีดำของแผ่นให้ห่างตัวรูป */
/* ★ ออร่ารอบรูปแรงขึ้นหนึ่งขั้น (4px → 7px) พร้อมชั้นขาวที่หนาขึ้น
   ชั้นขาวคือสิ่งที่ดันชื่อเมืองสีดำของแผ่นให้ห่างตัวรูป — ถ้าไม่หนาพอ สีเข้มจะจมหมึก */
#tkmap .pin.hot .pin-sym, #tkmap .pin.hot .pin-role{
  filter:drop-shadow(0 0 2.2px rgba(255,255,255,.98))
         drop-shadow(0 0 7px   var(--ev,#d9b169));
}

/* ⛔ หมุด `chk:true` แบบ "จาง + ขอบประ" ถูกถอด 2026-09-11 (LOG §5.28 ①) — เจ้าของ:
   *"ไม่เอาไอคอนเส้นประ ไม่สวย เอาแบบปกตินั่นแหละ"* · หมุดพวกนี้หน้าตาเหมือนหมุดทั่วไปแล้ว
   ธง `chk` ยังบอกได้สองที่ที่ไม่รกแผนที่: การ์ดตอนคลิก (ui.js) · รายการค้นหา (ui-studio.js)
   ⚠ ห้ามเอากลับมาโดยไม่ถามเจ้าของ */
