/* CSS ของฟอร์ม Draft B/L — ที่เดียวที่มีกฎของกริด ช่อง และสถานะของช่อง · ทั้ง / (index.html) และ /entry (entry.html) ใช้ร่วมกัน
   ทำไมต้องรวม: เคยคัดลอกไว้ในสองหน้า แล้วเหลื่อมกันเงียบ ๆ (หน้าละกฎ .cell สถานะที่อีกหน้าไม่มี) · แก้ที่นี่ที่เดียวแล้วสองหน้าต้องเปลี่ยนตาม
   หน้าต้อง <link> ไฟล์นี้ "ก่อน" <style> ของตัวเอง เพื่อให้กฎเฉพาะหน้า (เช่น .panes) ชนะได้เหมือนเดิมเมื่อความจำเพาะเท่ากัน */
.paper{width:980px;background:#fff;color:#111;box-shadow:0 1px 5px rgba(0,0,0,.2);padding:14px;font-family:Arial,"IBM Plex Sans Thai",Tahoma,sans-serif}
/* ความสูงแถวและจำนวนแถวของกริดถูกกำหนดที่ form.js ที่เดียว (ใส่เป็น inline style ตอนวาด และคำนวณแถวตู้เพิ่มเองตามจำนวนตู้)
   ห้ามใส่ grid-template-rows กลับมาที่นี่: inline style ชนะ stylesheet เสมอ ค่าตรงนี้จึงไม่เคยมีผล แต่ดูเหมือนเป็นตัวกำหนดความสูง
   คนที่มาแก้เลขตรงนี้จะเห็นว่าหน้าจอไม่เปลี่ยน แล้วไปไล่หาผิดที่ — มีสำเนาแบบนี้อยู่ในหน้าละที่มาก่อนหน้านี้ */
.grid{display:grid;border:1.6px solid #11161d;position:relative}
/* เส้นในกรอบจาง (#c9d2da) ให้เส้นคั่นกลุ่มกับกรอบนอก (#11161d หนา 1.6px) เป็นสิ่งเดียวที่ดำ · ลูกค้าบอกว่าเดิมเส้น 33 กล่องหนักเท่ากันหมดจนสายตาไม่มีจุดเกาะ
   ห้ามทำจางด้วย opacity: จะจางทั้งตัวอักษรในช่องด้วย */
.cell{border:1px solid #c9d2da;margin:-1px 0 0 -1px;padding:2px 5px;display:flex;flex-direction:column;min-width:0;min-height:0;position:relative;background:#fff}
.cell.title{justify-content:center;font-weight:700;font-size:15px;letter-spacing:.02em}
.cell.static{justify-content:center;font-size:9.5px;font-weight:700;text-transform:uppercase;color:#414b59;background:#eef1f5}
/* เส้นคั่นกลุ่ม (ผู้เกี่ยวข้อง | เส้นทางเรือ | สินค้า | ตู้): form.js ใส่ sep ให้ทุกช่องที่เริ่มแถว 22, 28, 48 (ดู SEP_ROWS)
   margin-top:-2px (ไม่ใช่ -1px เหมือน .cell) คู่กับ border 2px: เส้นหนาวางทับเส้นล่างของช่องเหนือพอดี และความสูงที่เหลือให้ตัวควบคุมเท่าเดิม
   (ช่องสูงขึ้น 1px เท่ากับเส้นหนาขึ้น 1px) · ถ้าใช้ -1px เฉย ๆ ช่อง carriers_receipt ที่คับอยู่แล้ว (กล่อง 18px ในเซลล์ 20px) จะถูกบีบจนหมึกไทยโดนตัด
   ผูกกับแถวสัมบูรณ์เพราะแถวตู้งอกใต้แถว 48 ตามจำนวนตู้ — เส้นจึงต้องไม่นับจากท้ายกริด */
.cell.sep{border-top:2px solid #11161d;margin-top:-2px}
.cell.blank{background:#fafafa}
/* padding แนวตั้งของตัวควบคุมเป็น 0 (เดิม 1px): ที่ 13px/1.42 บรรทัดเดียวสูง 18.46px + 2px = 20 แต่ช่อง 2 แถวเหลือที่ให้ตัวควบคุมแค่ 19px
   → ช่องบรรทัดเดียว 7 ช่อง (booking_no ฯลฯ) ล้น 1px · เลือกตัดที่ padding เพราะ "ห้ามเพิ่มความสูงแถว" (ฟอร์มสูงขึ้น = ถูกย่อหนักขึ้นบนจอ)
   และไม่ลด line-height ต่ำกว่า 1.42 เพราะ Thai มีสระ/วรรณยุกต์ซ้อนบน-ล่าง · ข้อยกเว้นมีช่องเดียว: carriers_receipt (1.5 · ดูเหตุผลด้านล่าง) */
/* ป้ายช่องเล็กกว่าและจางกว่าค่า (10.5px สีเทา #727d8c) เพื่อให้ "ข้อมูล" เด่นกว่า "ชื่อช่อง" · ลูกค้าบอกว่าฟอร์มมองยาก */
.cell label{font-size:10.5px;font-weight:600;text-transform:uppercase;color:#727d8c;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.3;flex:none}
.cell.inline{flex-direction:row;align-items:center;gap:6px}
.cell textarea,.cell select,.cell input{flex:1;width:100%;border:0;background:transparent;resize:none;font-size:13px;line-height:1.42;padding:0;color:#111;font-family:Arial,"IBM Plex Sans Thai",Tahoma,sans-serif;min-height:0;outline:none}
/* แยกฟอนต์ตามชนิดข้อมูล: ค่าเริ่มต้นเป็น sans (ชื่อบริษัท ที่อยู่ รายละเอียดสินค้า อ่านยากใน mono) · ช่องรหัส/เลขที่/วันที่/ตัวเลข/ตารางตู้
   ได้คลาส fmono จาก BOXES[].font ใน form.js (แหล่งเดียว — อย่าเขียนรายชื่อ key ซ้ำที่นี่) เพื่อให้ตัวเลขและตัวอักษรเรียงตรงกันเทียบเอกสารง่าย
   ทำไมชื่อ fmono ไม่ใช่ .mono: index.html มี .mono{font-family:…} อยู่แล้ว ถ้าใช้ชื่อเดียวกันมันจะลามไปที่ป้าย (label) ซึ่งสืบ font จาก .cell แล้วป้ายกลายเป็น mono
   ทำไมต้องมี "IBM Plex Sans Thai" คั่นก่อน Consolas: IBM Plex Mono ไม่มีกลีฟไทย ช่อง marks_and_numbers พิมพ์ไทยได้ · ถ้าไม่ระบุ เบราว์เซอร์เลือกฟอนต์ไทยของระบบเอง
   (Leelawadee/Tahoma ฯลฯ) ซึ่งสูง/ต่ำกว่า จึงทำให้บรรทัดสูงไม่เท่ากันและสระ-วรรณยุกต์ชนบรรทัดข้างเคียงจนล้นกรอบ · ใช้ฟอนต์ไทยตัวเดียวกับที่ .paper ใช้เพื่อให้ metric เท่ากันทั้งใบ */
.cell.fmono textarea,.cell.fmono input{font-family:"IBM Plex Mono","IBM Plex Sans Thai",Consolas,monospace}
.cell select{font-family:Arial,sans-serif;font-size:13px;padding:0;cursor:pointer}
.cell:has([data-key="carriers_receipt"]) input{font-size:12px;line-height:1.5}
/* ทำไมช่อง CARRIER'S RECEIPT เล็กกว่าช่องอื่น (12px) และทำไมไม่แก้ด้วยการเพิ่มแถว/ขยายความสูง:
   ช่องนี้สูงแค่ 1 แถว (19px) และมีป้ายอยู่ข้างในแถวเดียวกัน ที่ 13px จะคับ (spec §4.1) · ทางที่ดูชัดกว่าคือเพิ่มความสูงแถว
   แต่ BOXES ใช้เลขแถวสัมบูรณ์ — เพิ่มแถวที่ 28 ต้องไล่เลื่อนแถว 29–50 ทุกกล่อง และตำแหน่งจะไม่ตรงไฟล์ xls ต้นแบบอีก
   อีกเหตุผล: ฟอร์มสูงขึ้น = ถูกย่อให้พอดีจอหนักขึ้น (ที่ 1440 ย่อเหลือ ~0.64) ตัวที่ใหญ่ขึ้นในโค้ดจะเล็กลงบนจอ
   line-height ของช่องนี้ต่างจากช่องอื่น (1.5 แทน 1.42) เพราะเป็นช่องเดียวที่เป็นแถวเดียวสูง 1 แถว (เซลล์ 20px เหลือที่ในกรอบ 14px หลังหัก border 2 + padding 4)
   และเป็น <input> ที่ตัดหมึกเกินกล่อง · ค่าที่เลือกและเหตุผลอยู่ในย่อหน้าถัดไป
   ทำไมไม่ใช่ 1.15 (ค่าเดิม) และไม่ใช่ 1.3 (ค่าที่เคยแก้รอบแรก): ช่องนี้เป็น <input> ที่คนหรือ OCR ใส่ภาษาไทยได้ และ input ตัดหมึกที่เกินกล่องของตัวเอง
   วัดด้วยพิกเซลจริง (ภาพ 6 เท่า เทียบกับ input เดียวกันสูง 44px ที่ไม่มีอะไรตัด) ด้วยข้อความที่มีวรรณยุกต์ซ้อนสระ: หมึกที่เสียไป
   1.15 → 3px · 1.3 → 2px (รอบแรกดูภาพด้วยตาแล้วสรุปว่าครบ — ผิด) · 1.4 → 1.2px · 1.45 → 1px · **1.5 → 0px** (กล่อง 18px, หมึกเต็ม 13.2px)
   ขนาด 11–11.5px ที่ 1.6 ก็ไม่เสียหมึก แต่ไม่จำเป็น: 12px/1.5 ได้ครบและไม่ต้องลดขนาดตัวอักษร · กล่อง 18px สูงเต็มที่ว่างในเซลล์ (เซลล์ 20px − border 2px = 18px) จึงชนเส้นขอบในพอดี ห่าง 0 · หมึกจริงอยู่ในกล่อง ไม่ล้ำเส้น แต่ไม่เหลือที่ว่างให้เพิ่ม
   ห้ามลดกลับไปต่ำกว่า 1.5 (เทสต์ --assert fonts เฝ้าไว้ด้วยการวัดหมึกจริงบนหน้า /entry)
   ใช้ :has() แทนแอตทริบิวต์บน .cell เพราะ data-key อยู่ที่ตัวควบคุม ไม่ได้อยู่ที่ .cell และไม่อยากแตะ form.js
   (ระวัง: ห้ามใส่ตัวปิดคอมเมนต์กลางย่อหน้านี้ — เคยปิดก่อนเวลา ข้อความที่เหลือกลายเป็นตัวเลือก CSS เสีย แล้วกฎ .combo ข้างล่างถูกทิ้งเงียบ ๆ) */
.combo{display:flex;align-items:center;flex:1;min-width:0}
.combo input{flex:1;min-width:0}
.combo .pick{flex:none;border:0;background:none;color:#555;font-size:11px;padding:0 3px;cursor:pointer;line-height:1}
.combo .pick:hover{color:#0b5c73}
#optmenu{position:fixed;z-index:60;min-width:180px;background:var(--panel,#fff);border:1px solid var(--line,#ccc);border-radius:7px;box-shadow:0 6px 20px rgba(0,0,0,.18);padding:4px;font-size:12.5px}
#optmenu button{display:block;width:100%;text-align:left;border:0;background:none;padding:6px 10px;border-radius:5px;cursor:pointer;font-family:Arial,sans-serif}
#optmenu button:hover,#optmenu button.cur{background:#e6f0f3}
#optmenu .hint{padding:5px 10px 3px;color:var(--ink-3,#777);font-size:11px;border-top:1px solid var(--line,#ddd);margin-top:3px}
/* สถานะของช่องที่เคยมีหน้าเดียว ย้ายมารวมกันที่นี่เพื่อให้ "ช่องหนึ่งหน้าตาเป็นอย่างไรในแต่ละสถานะ" อยู่ที่เดียว
   (class ที่หน้าไหนไม่เคยใส่ให้ช่อง กฎก็ไม่มีผลกับหน้านั้น จึงไม่เปลี่ยนหน้าตาของหน้าใดเลย)
   ต้องอยู่ก่อน .cell:focus-within: ความจำเพาะเท่ากัน ลำดับเป็นตัวชนะ — ขณะพิมพ์ในช่องต้องเห็นกรอบโฟกัสสีเขียวน้ำเงิน ไม่ใช่กรอบแดง/ม่วง */
/* .invalid: หน้า /entry ใส่ให้ช่องที่ตัวตรวจค่าไม่ผ่าน · สีแดงต้องต่างจากช่องว่าง (ส้ม) ให้เห็นว่าอันนี้ "ต้องแก้" ไม่ใช่ "ยังไม่กรอก" */
.cell.invalid{box-shadow:inset 0 0 0 2px var(--bad,#b3372c);background:#fdeeec}
.cell.invalid:focus-within{box-shadow:inset 0 0 0 2px #0b5c73}
/* .target: หน้า / ใส่ให้ช่องที่ถูกชี้จากรายการ "แก้ N จุด" */
.cell.target{box-shadow:inset 0 0 0 2px #6b3fb3}
.cell:focus-within{box-shadow:inset 0 0 0 2px #0b5c73;z-index:2}
.cell.edited{background:#eef4fd}
.cell.edited::after,.cell.added::after{content:"";position:absolute;right:3px;top:3px;width:7px;height:7px;border-radius:50%;background:#2a5fa8}
.cell.added{background:#f5effd}
.cell.added::after{background:#6b3fb3}
/* ช่องที่ยังว่าง: ขอบประส้ม + ป้าย "ว่าง" · กรอกแล้วหายทันที */
.hl-empty .cell.empty{background:repeating-linear-gradient(-45deg,#fff8ec 0 6px,#fff2dc 6px 12px);box-shadow:inset 0 0 0 1.5px #e0a030}
.hl-empty .cell.empty::before{content:"ว่าง";position:absolute;right:3px;bottom:2px;font:600 9px/1 "IBM Plex Sans Thai",Tahoma,sans-serif;color:#a8660f;background:#ffe7bf;border-radius:3px;padding:2px 4px;pointer-events:none}
.hl-empty .cell.empty:focus-within{box-shadow:inset 0 0 0 2px #0b5c73}
.cell.flash{animation:flash 1.1s ease-out 1}
@keyframes flash{0%{box-shadow:inset 0 0 0 3px #e0a030,0 0 0 4px rgba(224,160,48,.45)}100%{box-shadow:inset 0 0 0 1.5px #e0a030}}
.emptybox{display:flex;align-items:center;gap:0;border-radius:999px;overflow:hidden;border:1px solid #e0b060;background:#fff4e0;font-size:13px}
.emptybox.none{border-color:var(--line);background:var(--ok-bg)}
.emptybox button{border:0;background:none;padding:5px 10px;cursor:pointer;color:#8a5208;font-weight:600;white-space:nowrap}
.emptybox.none button{color:var(--ok)}
.emptybox button+button{border-left:1px solid #e8c78a;font-weight:400}
.emptybox button:hover{background:rgba(224,160,48,.18)}
.emptybox button[aria-pressed="false"]{opacity:.6}
.cell.pending textarea::placeholder,.cell.pending input::placeholder{color:#a8660f;font-family:Arial,sans-serif;font-size:10.5px}
.cell .src{position:absolute;right:14px;top:1px;font-size:9px;color:#0b5c73;background:none;border:0;padding:0 2px;opacity:0;cursor:pointer;font-family:Arial,sans-serif}
.cell:hover .src,.cell:focus-within .src{opacity:1}
.ctable td{padding:0}
.formfoot{display:flex;gap:8px;align-items:center;margin-top:10px;font-family:"IBM Plex Sans Thai",Tahoma,sans-serif;font-size:12px;color:#444}
/* แผง "ข้อมูลสำหรับยื่นเว็บสายเรือ" (spec §4.6) — อยู่ใน .paper ใต้ใบ B/L แต่นอก .grid
   ช่องในแผงเป็น .cell เหมือนช่องในใบ เพื่อให้สถานะ edited / added / empty ใช้กฎชุดเดียวกัน (ไม่เขียนสีสถานะซ้ำที่นี่) และ ฟอนต์/ขนาด/สีป้ายตามกฎ .cell ข้างบน
   ต่างจากช่องในกริดตรงที่ไม่ต้องซ้อนเส้นกับช่องข้าง ๆ จึงยกเลิก margin ลบของ .cell (ใช้ซ้อนเส้นในกริดเท่านั้น) และเรียงเป็นคอลัมน์เดียวเต็มความกว้าง
   ความสูงของช่อง multiline ตายตัว 4 บรรทัด (13px × 1.42 = 18.46px/บรรทัด + ป้าย + padding + เส้น) เพราะ textarea ใน flex ไม่มีความสูงในตัวเอง
   ถ้าเหลือบรรทัดเกินให้เลื่อนในช่อง ไม่ขยายแผง — ฟอร์มสูงขึ้น = ถูกย่อหนักขึ้นบนจอ (ดูเหตุผลที่ carriers_receipt) */
.extras{margin-top:16px;padding-top:10px;border-top:1.6px solid #11161d;font-family:"IBM Plex Sans Thai",Tahoma,sans-serif}
.extras h3{margin:0;font-size:14px;font-weight:700;color:#111}
.extras-note{margin:2px 0 8px;font-size:12px;color:#414b59}
.extras-list{display:grid;gap:8px}
.extras .cell{margin:0;height:46px}
.extras .cell.multi{height:98px}
.extra-hint{margin-top:2px;font-size:11.5px;color:#414b59;line-height:1.4}

/* ── ตารางตู้ 8 คอลัมน์ (2026-10-31) — กริดซ้อนในกริดหลัก ──
   ทำไมซ้อน: กริดหลักมี 8 คอลัมน์ที่คุมตำแหน่งทุกกล่องบนใบ (COLS ใน form.js)
   แก้ COLS เพื่อให้ตารางตู้มี 8 ช่อง = ทุกกล่องบนใบขยับ ซึ่งทำลายงานจัดผังทั้งหมด
   แถวตู้จึงเป็นกล่องเดียวของกริดหลัก แล้วแบ่งช่องเองข้างใน (spec 2026-10-31 §4.2) */
.ctnr-row{display:grid;min-width:0}
.cell.ctnr-c{margin:-1px 0 0 -1px}
.cell.ctnr-head{justify-content:center;font-size:8.5px;font-weight:700;text-transform:uppercase;
  color:#414b59;background:#eef1f5;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* หน่วยในแถวไม่ตรงหัวตาราง — เตือนด้วยสี ไม่แปลงค่าให้เอง (แปลงเอง = เดาแทนคน) */
.cell.unit-odd{background:#fff7e6}
.cell.unit-odd::after{content:"";position:absolute;top:1px;right:1px;width:5px;height:5px;border-radius:50%;background:#e08b00}

/* ── คำเตือนน้ำหนักรวมไม่ตรง (2026-11-01) — เตือน ไม่บล็อกการบันทึก ── */
.wcheck{margin:6px 0 0;padding:6px 10px;border:1px solid #e0b000;border-left-width:4px;border-radius:3px;
  background:#fff8e3;color:#5d4600;font-size:12px;line-height:1.5}
.cell.warn{background:#fff8e3}
.cell.warn::after{content:"";position:absolute;top:2px;right:2px;width:6px;height:6px;border-radius:50%;background:#e0b000}
