/* ============================================================================
   app.css - ชุดรูปแบบหน้าตากลางของทั้งเว็บแอป (Design System)
   ทุกหน้าต้องเรียกใช้ไฟล์นี้ เพื่อให้ฟอนต์ สี ตาราง ปุ่ม และป้ายสถานะ
   หน้าตาเหมือนกันหมดทุกหน้า ไม่ต้องกำหนดสีซ้ำในแต่ละหน้าอีก
   ============================================================================ */

/* ---------------------------------------------------------------------------
   1. ชุดสีกลาง (Color Palette)
   กำหนดไว้ที่เดียว ทุกหน้าดึงไปใช้ผ่านชื่อตัวแปร ไม่ต้องจำรหัสสี
   --------------------------------------------------------------------------- */
:root {
    /* ฟอนต์เดียวทั้งเว็บ - Noto Sans Thai อ่านภาษาไทยและตัวเลขได้ชัดเจน */
    --font-sans: 'Noto Sans Thai', system-ui, -apple-system, 'Segoe UI', sans-serif;

    /* สีหลัก - ใช้กับปุ่มหลัก ลิงก์ และองค์ประกอบที่ต้องการเน้น */
    --color-primary: #2563eb;
    --color-primary-hover: #1d4ed8;
    --color-primary-soft: #eff6ff;

    /* สีพื้นหลังและพื้นผิว */
    --color-page: #f1f5f9;      /* พื้นหลังทั้งหน้า */
    --color-surface: #ffffff;    /* พื้นการ์ด/ตาราง */
    --color-surface-alt: #f8fafc; /* แถวสลับสีในตาราง (zebra stripe) */
    --color-header: #f1f5f9;     /* พื้นหัวตาราง */

    /* เส้นขอบ */
    --color-border: #e2e8f0;
    --color-border-strong: #cbd5e1;

    /* ตัวอักษร */
    --color-text: #0f172a;        /* ข้อความหลัก */
    --color-text-soft: #475569;   /* ข้อความรอง */
    /* ข้อความจาง เช่น คำอธิบายเพิ่มเติม / จำนวนแถว / ป้ายกำกับตัวเลข
       ค่าเดิม #94a3b8 ตัดกับพื้นขาวได้แค่ 2.56:1 — ไม่ถึงเกณฑ์ 4.5:1 ของ WCAG AA
       (ตัวอักษร 11-13px สีนี้บนพื้นขาวคือจุดที่คนสายตาไม่ดีอ่านไม่ออกจริงๆ ในระบบนี้)
       ค่าใหม่ตัดกันได้ >= 5.0:1 บนพื้นทุกแบบที่ระบบใช้ (ขาว/สลับแถว/หัวตาราง/พื้นหน้า/พื้นป้าย)
       แต่ยังจางกว่า --color-text-soft (7.58:1) ชัดเจน ลำดับความสำคัญจึงไม่เปลี่ยน */
    --color-text-muted: #5a6a7f;

    /* สีสื่อความหมาย - ใช้กับป้ายสถานะและข้อความแจ้งเตือน */
    --color-success: #15803d;
    --color-success-bg: #dcfce7;
    --color-success-hover: #166534;   /* พื้นปุ่มเขียวตอน hover (ค่าเดิมที่เคยฝังใน .btn-success) */
    --color-warning: #b45309;     /* เหลือง - ค้างเกิน 30 วัน */
    --color-warning-bg: #fef3c7;
    --color-alert: #c2410c;       /* ส้ม - ค้างเกิน 60 วัน */
    --color-alert-bg: #ffedd5;
    --color-danger: #b91c1c;      /* แดง - ค้างเกิน 90 วัน / ปุ่มลบ */
    --color-danger-bg: #fee2e2;
    --color-danger-soft: #fca5a5; /* ขอบปุ่มอันตรายแบบขอบ (ค่าเดิมที่เคยฝังใน .btn-danger-outline) */
    --color-info: #1d4ed8;
    --color-info-bg: #dbeafe;
    --color-accent: #0f766e;      /* เขียวอมฟ้า - การเคลียร์บางส่วน */
    --color-accent-bg: #ccfbf1;
    --color-neutral: #475569;
    --color-neutral-bg: #e2e8f0;
    --color-text-invert: #ffffff; /* ตัวอักษรบนปุ่มพื้นทึบ (ค่าเดิม #fff ที่เคยฝังในปุ่ม) */

    /* สเกลตัวอักษรกลาง — ค่าตรงกับที่ใช้จริงในหน้าต่างๆ ตอนนี้ (เตรียมไว้ให้งานชุด D
       ไล่แทน font-size ที่เขียน inline อยู่ ~30 จุด มาเกาะสเกลนี้ — ยังไม่มีใครใช้ ไม่กระทบผลตา) */
    --font-xs: 10.5px;   /* ป้ายเล็กใน detail-table */
    --font-sm: 12px;     /* ข้อความรอง/วันที่จาง */
    --font-md: 12.5px;   /* ตารางย่อย/ช่องกรองโต๊ะจับคู่ */
    --font-lg: 13.5px;   /* ตัวอักษรฐานของตาราง */
    --font-xl: 15px;     /* ตัวเลขเด่นในแถบสรุป */

    --radius: 8px;
    --radius-pill: 999px;
    --shadow-card: 0 1px 2px rgba(15, 23, 42, .06), 0 1px 3px rgba(15, 23, 42, .04);
    --shadow-pop: 0 6px 16px rgba(15, 23, 42, .12);      /* กล่องลอย: รายการของ combobox / กล่องยืนยัน / toast */
    --shadow-sticky: 0 -4px 16px rgba(15, 23, 42, .10);  /* แถบสรุปที่ตรึงก้นจอ */
    --shadow-auth: 0 4px 20px rgba(15, 23, 42, .08);     /* การ์ดหน้าเข้าสู่ระบบ */

    /* สีอ่อน/พื้นจางที่เดิมฝังเป็นรหัสสีไว้ในกฎเฉพาะจุด — ยกมาเป็นตัวแปรเพื่อให้โหมดมืดสลับตามได้
       (ค่าเท่าของเดิมทุกตัว โหมดสว่างจึงไม่เปลี่ยนแม้แต่พิกเซลเดียว) */
    --color-success-soft: #86efac;   /* ขอบกล่องสรุป "สำเร็จ" / เส้นไทม์ไลน์ */
    --color-success-tint: #f0fdf4;   /* พื้นกล่องสรุป "สำเร็จ" */
    --color-warning-soft: #fcd34d;   /* ขอบแถบงวดปิด / กล่องสรุป "ต้องดู" */
    --color-warning-tint: #fffbeb;   /* พื้นกล่องสรุป "ต้องดู" */
    --color-danger-tint: #fef2f2;    /* พื้นแถบล็อกถาวร */
    --tint-credit: rgba(234, 88, 12, .045);          /* พื้นแถวฝั่งเครดิตในตาราง Open */
    --overlay-on-primary: rgba(255, 255, 255, .22);  /* ป้ายบนพื้นสีหลัก (แถบหัวหน้ารายละเอียด) */

    /* วงแหวนโฟกัสคีย์บอร์ด — ต้องมองเห็นชัดทั้งสองโหมด (WCAG 2.4.7 Focus Visible) */
    --color-focus: #1d4ed8;
    --shadow-focus: 0 0 0 3px rgba(37, 99, 235, .28);

    /* บอกเบราว์เซอร์ว่าหน้านี้โหมดไหน — scrollbar, ปฏิทินของ input[type=date] และรายการของ
       <select> จะเปลี่ยนตามให้เอง ไม่ต้องเขียน CSS ครอบเอง */
    color-scheme: light;
}

/* ---------------------------------------------------------------------------
   1b. โหมดมืด (Dark Mode)
   เขียนไว้ "บล็อกเดียว" ผูกกับ <html data-theme="dark"> — ไม่ได้ผูกกับ
   @media (prefers-color-scheme: dark) โดยตรง เพราะ theme.js เป็นคนแปลง
   "ตามระบบ" ให้เป็นค่าจริง (light/dark) แล้วเขียนลง data-theme ให้ตั้งแต่ก่อนวาดหน้า
   -> ค่าทุกตัวมีที่เดียว แก้ที่เดียว และปุ่มสลับธีมเอาชนะค่าของระบบได้ทันทีทั้งสองทาง

   หลักการเลือกสี: โหมดมืดกลับบทบาทของสีเน้น — พื้นเป็นสีสว่างขึ้น ตัวอักษรบนพื้นทึบเป็นสีเข้ม
   (ขาวบนฟ้าเข้มได้อัตราตัดกันไม่ถึง 4.5:1 ในโหมดมืด) ทุกคู่สีป้าย/ข้อความตรวจแล้วเกิน 4.5:1
   --------------------------------------------------------------------------- */
:root[data-theme="dark"] {
    color-scheme: dark;

    --color-primary: #60a5fa;
    --color-primary-hover: #7db6fb;
    --color-primary-soft: #1b2c4d;

    --color-page: #0b1120;
    --color-surface: #131c2e;
    --color-surface-alt: #1a2436;
    --color-header: #1e293b;

    --color-border: #2c3a52;
    --color-border-strong: #3d4c66;

    --color-text: #e8edf6;
    --color-text-soft: #b6c2d6;
    --color-text-muted: #8a99b1;
    --color-text-invert: #0b1120;   /* ตัวอักษรบนปุ่มพื้นทึบ — โหมดมืดต้องเป็นสีเข้ม */

    --color-success: #4ade80;
    --color-success-bg: #123020;
    --color-success-hover: #22c55e;
    --color-success-soft: #1f6b41;
    --color-success-tint: #10251a;
    --color-warning: #fbbf24;
    --color-warning-bg: #3a2a08;
    --color-warning-soft: #8a6410;
    --color-warning-tint: #2b2008;
    --color-alert: #fb923c;
    --color-alert-bg: #3a2410;
    --color-danger: #f87171;
    --color-danger-bg: #3a1618;
    --color-danger-soft: #7f2b2b;
    --color-danger-tint: #2c1315;
    --color-info: #7cb8fc;
    --color-info-bg: #17263f;
    --color-accent: #2dd4bf;
    --color-accent-bg: #0f2e2b;
    --color-neutral: #cbd5e1;
    --color-neutral-bg: #2f3b4f;

    /* เงาบนพื้นมืดต้องเข้มขึ้นถึงจะเห็น (เงาอ่อนบนพื้นเข้ม = มองไม่เห็นเลย) */
    --shadow-card: 0 1px 2px rgba(0, 0, 0, .45), 0 1px 3px rgba(0, 0, 0, .30);
    --shadow-pop: 0 8px 24px rgba(0, 0, 0, .55);
    --shadow-sticky: 0 -4px 18px rgba(0, 0, 0, .50);
    --shadow-auth: 0 6px 26px rgba(0, 0, 0, .50);

    --tint-credit: rgba(251, 146, 60, .07);
    --overlay-on-primary: rgba(11, 17, 32, .20);

    --color-focus: #93c5fd;
    --shadow-focus: 0 0 0 3px rgba(147, 197, 253, .35);
}

/* ---------------------------------------------------------------------------
   2. ฟอนต์และพื้นฐาน
   บังคับใช้ฟอนต์เดียวกับทุกองค์ประกอบ รวมถึงปุ่มและช่องกรอกข้อมูล
   ที่ปกติเบราว์เซอร์จะใช้ฟอนต์ของตัวเองแยกต่างหาก
   --------------------------------------------------------------------------- */

/* นับ padding และเส้นขอบรวมอยู่ใน width ที่กำหนด
   ถ้าไม่ตั้งค่านี้ ช่องกรอกที่กำหนด width:100% จะกว้างจริงเกินกรอบไปเท่ากับ padding+border
   (ประมาณ 24px) แล้วล้นไปทับปุ่มหรือช่องข้างๆ - เป็นต้นเหตุของอาการช่องซ้อนทับกัน */
*, *::before, *::after {
    box-sizing: border-box;
}

html, body, button, input, select, textarea, table, th, td {
    font-family: var(--font-sans);
}

body {
    background-color: var(--color-page);
    color: var(--color-text);
    font-size: 14px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

/* ตัวเลขทั้งหมดใช้ความกว้างเท่ากันทุกหลัก (tabular-nums)
   ทำให้ตัวเลขในแต่ละแถวเรียงตรงกันเป็นคอลัมน์ อ่านเปรียบเทียบง่าย
   โดยไม่ต้องเปลี่ยนไปใช้ฟอนต์ monospace คนละแบบ */
table, .num, input, .tabular {
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum';
}

/* ---------------------------------------------------------------------------
   3. โครงหน้า (Layout)
   --------------------------------------------------------------------------- */
.page {
    max-width: 1180px;
    margin: 0 auto;
    padding: 28px 20px 64px;
}
.page-narrow { max-width: 860px; }

.page-title {
    font-size: 22px;
    font-weight: 700;
    color: var(--color-text);
    line-height: 1.35;
}
.page-subtitle {
    font-size: 13px;
    color: var(--color-text-muted);
    margin-top: 2px;
}

.card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
    padding: 20px;
    margin-bottom: 20px;
}
.card-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--color-text);
}
.card-desc {
    font-size: 12.5px;
    color: var(--color-text-muted);
    margin-top: 2px;
}
.card-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

/* ---------------------------------------------------------------------------
   4. เมนูหลัก (Navigation) - เหมือนกันทุกหน้า
   --------------------------------------------------------------------------- */
.nav {
    display: flex;
    gap: 4px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 5px;
    margin-bottom: 22px;
    box-shadow: var(--shadow-card);
    flex-wrap: wrap;
}
.nav a {
    padding: 7px 14px;
    border-radius: 6px;
    font-size: 13.5px;
    font-weight: 500;
    color: var(--color-text-soft);
    text-decoration: none;
    transition: background-color .12s, color .12s;
}
.nav a:hover { background: var(--color-surface-alt); color: var(--color-text); }
.nav a.active { background: var(--color-primary); color: var(--color-text-invert); }

/* ---------------------------------------------------------------------------
   แถบผู้ใช้บนแถบเมนู (ชื่อ + สิทธิ์ + ออกจากระบบ) — auth-guard.js แทรกให้ทุกหน้า
   --------------------------------------------------------------------------- */
.user-bar {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    font-size: 13px;
    margin-bottom: 8px;
    flex-wrap: wrap;
}
.user-bar-name { font-weight: 600; color: var(--color-text); }
.user-bar-roles { color: var(--color-text-muted); font-size: 12px; }
.user-bar-link { font-size: 12.5px; }
/* ปุ่มที่ผู้ใช้ไม่มีสิทธิ์กด — เทาแต่ยังชี้เมาส์อ่าน tooltip ได้ (ด่านจริงอยู่ฝั่งเซิร์ฟเวอร์) */
.is-no-permission { opacity: .45; cursor: not-allowed; }
/* ป้ายสภาพแวดล้อมสนามซ้อม — โผล่เฉพาะเมื่อเซิร์ฟเวอร์ตั้ง GL_ENV_LABEL (env-banner.js)
   ระบบจริงไม่ตั้งค่า -> ไม่มี element/คลาสพวกนี้เกิดขึ้นเลย หน้าตาเหมือนเดิมทุกพิกเซล */
.env-banner {
    background: var(--color-warning);
    color: var(--color-surface);
    text-align: center;
    font-weight: 700;
    font-size: 13px;
    padding: 6px 12px;
}
.env-flagged .nav {
    background: var(--color-warning-bg);
    border-color: var(--color-warning);
}

/* แถวค้นหา + ตัวกรองเหนือตาราง — จอแคบยุบบรรทัดเองด้วย flex-wrap ไม่ล้นกรอบ */
.filter-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 14px;
}

/* ช่องติ๊กเลือกสิทธิ์ในฟอร์มผู้ใช้ */
.role-checks { display: flex; flex-wrap: wrap; gap: 8px 20px; margin-top: 4px; }
.role-checks label { display: inline-flex; align-items: center; gap: 6px; font-size: 13.5px; }
/* ฟอร์มผู้ใช้แบ่งเป็นชั้น: ข้อมูลคน / สิทธิ์+สถานะ / ปุ่ม — คั่นด้วยเส้นบาง */
.form-section {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 12px 28px;
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--color-border);
}

/* ⭐ ป้ายสิทธิ์ในตาราง: 4 ช่องตำแหน่งคงที่ กว้างเท่ากันต่อชนิด -> อ่านเทียบข้ามแถวได้
   มีสิทธิ์ = ป้ายสี · ไม่มี = ป้ายจาง (ยังเห็นโครงว่าช่องนี้คือสิทธิ์อะไร) */
.role-badges { display: flex; gap: 6px; flex-wrap: nowrap; }
.role-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 82px;
    height: 22px;
    border-radius: 999px;
    font-size: 11.5px;
    font-weight: 600;
    white-space: nowrap;
    background: var(--color-surface-alt);
    color: var(--color-text-muted);
    border: 1px solid var(--color-border);
}
.role-badge.is-on {
    background: var(--color-accent-bg);
    color: var(--color-accent);
    border-color: var(--color-accent-bg);
}

/* ป้ายสิทธิ์ระดับแพลตฟอร์ม — คนละชนิดกับ 4 ป้ายด้านซ้าย
   4 ป้ายแรกคือ "สิทธิ์ในระบบกระทบยอด" ตำแหน่งคงที่เพื่อกวาดตาเทียบข้ามแถวได้
   ส่วนป้ายนี้คือ "สิทธิ์ระดับองค์กร" ใช้ได้ทุกระบบ จึงแยกด้วยเส้นคั่นและรูปทรงที่ต่างออกไป
   (ไม่ใส่รวมในกริดเดิม เพราะจะทำให้สิทธิ์คนละระดับดูเป็นชนิดเดียวกัน)
   ไม่มีป้ายจางคู่ = แถวที่ไม่ใช่ผู้ดูแลแพลตฟอร์มไม่ต้องจองที่ (มีไม่กี่คนในองค์กร) */
.role-badge-platform {
    display: inline-flex;
    align-items: center;
    height: 22px;
    padding: 0 10px;
    margin-left: 10px;
    border-left: 1px solid var(--color-border);
    padding-left: 12px;
    border-radius: 0;
    font-size: 11.5px;
    font-weight: 700;
    white-space: nowrap;
    color: var(--color-accent);
}

/* ชื่อ + อีเมล ในเซลล์เดียว (อีเมลบรรทัดล่าง ตัวเล็กสีจาง) */
.people-name { font-weight: 600; white-space: nowrap; }
.people-sub { font-size: 12px; color: var(--color-text-muted); }

/* สถานะ "ยังไม่เปลี่ยนรหัสชั่วคราว" — ใช้สามเหลี่ยมเตือนแทนจุดสี
   เหตุผล: จุดสีส้มอยู่ติดกับจุดสีแดงในตารางเดียวกันแล้วแยกยาก · เปลี่ยนเป็นคนละรูปทรง
   ทำให้กวาดตาแยกออกทันทีโดยไม่ต้องพึ่งสี (ยังมี title กำกับเหมือนเดิม) */
.status-warn-wrap { display: inline-flex; align-items: center; justify-content: center; vertical-align: middle; }
.status-warn {
    width: 15px;
    height: 15px;
    display: block;
    color: var(--color-warning);
}

/* ---------------------------------------------------------------------------
   หน้าเข้าสู่ระบบ / เปลี่ยนรหัสผ่าน
   --------------------------------------------------------------------------- */
.auth-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: var(--color-page);
}
.auth-card {
    width: 100%;
    max-width: 420px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 12px;
    box-shadow: var(--shadow-auth);
    overflow: hidden;
}
.auth-head {
    background: var(--color-primary);
    color: var(--color-text-invert);
    padding: 20px 24px;
}
.auth-title { font-size: 20px; font-weight: 700; margin: 0; }
.auth-subtitle { font-size: 13px; opacity: .9; margin: 4px 0 0; line-height: 1.6; }
.auth-form { padding: 22px 24px 8px; display: flex; flex-direction: column; gap: 14px; }
.auth-rule { font-size: 12.5px; color: var(--color-text-muted); margin: 0; }
.auth-submit { width: 100%; justify-content: center; }
.auth-note {
    padding: 14px 24px 20px;
    font-size: 12.5px;
    color: var(--color-text-soft);
    line-height: 1.7;
    margin: 0;
}

/* ---------------------------------------------------------------------------
   5. ตารางข้อมูล (Data Table)
   หัวใจของหน้าจอนี้ - เน้นให้อ่านง่าย ไล่สายตาตามแถวได้สะดวก
   --------------------------------------------------------------------------- */
.table-wrap {
    overflow-x: auto;            /* ตารางคอลัมน์เยอะ เลื่อนแนวนอนได้ ไม่ดันจนหน้าเว็บล้น */
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
}
.card .table-wrap { box-shadow: none; }

.table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13.5px;
}

/* หัวตาราง: พื้นเข้มกว่าเนื้อหา ตัวหนา และมีเส้นหนาคั่นด้านล่างให้แยกจากข้อมูลชัดเจน */
.table thead th {
    background: var(--color-header);
    color: var(--color-text-soft);
    font-weight: 600;
    font-size: 12px;
    letter-spacing: .02em;
    text-align: left;
    padding: 11px 14px;
    border-bottom: 2px solid var(--color-border-strong);
    white-space: nowrap;
}

/* ช่องข้อมูล: เพิ่มระยะห่างให้ข้อความมีที่หายใจ ไม่อึดอัด */
.table tbody td {
    padding: 11px 14px;
    border-bottom: 1px solid var(--color-border);
    vertical-align: middle;
    color: var(--color-text);
}

/* สลับสีพื้นหลังแถวคู่-คี่ ช่วยให้ตาไล่ตามแถวยาวๆ ได้ไม่หลง */
.table tbody tr:nth-child(even) { background: var(--color-surface-alt); }
.table tbody tr:hover { background: var(--color-primary-soft); }
.table tbody tr:last-child td { border-bottom: none; }

/* ตารางที่จับกลุ่มสีพื้น "รายชุด" เอง (ประวัติการจับคู่ / ตารางเปรียบเทียบข้อเสนอ)
   ปิด zebra รายแถวของฐาน แล้วให้แต่ละตารางคุมสีพื้นของชุดด้วยคลาสของตัวเอง
   (เดิมกติกานี้ถูกนิยามซ้ำรายตาราง 2 ที่ — ตั้งใจใช้ตัวเลือกชั้นเดียว (ไม่ผูก .table)
    เพื่อคง specificity เดิมเป๊ะ: hover ของฐานยังชนะแถวคี่เหมือนพฤติกรรมเดิม) */
.table-grouped tbody tr { background: transparent; }
.table-grouped tbody tr:nth-child(even) { background: transparent; }

/* แถวสรุปยอดรวมท้ายตาราง - เน้นด้วยเส้นหนาและตัวหนา */
.table tr.row-total td {
    background: var(--color-header);
    font-weight: 700;
    border-top: 2px solid var(--color-border-strong);
    border-bottom: none;
}
.table tbody tr.row-total:hover { background: var(--color-header); }

/* คอลัมน์ตัวเลข (จำนวนเงิน/จำนวนวัน) ชิดขวาเสมอ เพื่อให้หลักหน่วย-สิบ-ร้อย ตรงกันทุกแถว */
.table .num { text-align: right; white-space: nowrap; }
.table .col-doc { white-space: nowrap; font-weight: 500; }
.table .col-date { white-space: nowrap; color: var(--color-text-soft); }
.table .col-check { width: 40px; text-align: center; }
.table .col-action { text-align: right; white-space: nowrap; }

/* คอลัมน์สถานะแบบไอคอน: จุดสีเขียว (ใช้งานอยู่) / แดง (ไม่ได้ใช้งาน)
   ⚠️ ต้องมี title กำกับเสมอ — ห้ามให้ผู้ใช้เดาความหมายจากสีอย่างเดียว */
.table .col-status { text-align: center; width: 70px; }
.status-dot { display: inline-block; width: 11px; height: 11px; border-radius: 50%; vertical-align: middle; }
.status-dot.is-on  { background: var(--color-success); }
.status-dot.is-off { background: var(--color-danger); }

/* ข้อความรายละเอียดยาวๆ ตัดท้ายด้วย ... กันไม่ให้ดันตารางกว้างจนล้นจอ
   (ผู้ใช้ยังเอาเมาส์ชี้เพื่อดูข้อความเต็มได้จาก tooltip) */
.table .col-desc {
    min-width: 200px;
    max-width: 380px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* โหมด "รายละเอียดเต็มไม่ตัด" — หน้างานที่ต้องอ่านคำอธิบายครบทุกตัวอักษร (กันจับคู่ผิด)
   เปิดใช้ด้วยคลาสนี้ที่ <body> ของหน้านั้น (เดิมกติกานี้ถูกนิยามซ้ำเฉพาะหน้า 2 ไฟล์)
   ความกว้าง (min-width) แต่ละหน้า/ตารางยังจูนของตัวเองได้ตามเดิม */
body.tables-full-desc .table .col-desc {
    white-space: normal;
    max-width: none;
    overflow: visible;
    text-overflow: clip;
    word-break: break-word;
}
.table .cell-muted { color: var(--color-text-muted); }
.table .cell-strong { font-weight: 600; }
.table .cell-empty { color: var(--color-text-muted); }

/* แถบค้นหา/กรองเหนือตาราง (ย้ายจาก style เฉพาะหน้ามาไว้กลาง ให้ทุกหน้าใช้แบบเดียวกัน) */
.table-search { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; flex-wrap: wrap; }
.table-search .input { max-width: 320px; }
/* จูนระยะเฉพาะจุด (ย้ายจาก inline style เดิม — ค่าเท่าเดิมเป๊ะ) */
.table-search.is-roomy { margin-bottom: 14px; }
.table-search.is-wide-gap { gap: 14px; }

.table-note {
    font-size: 12px;
    color: var(--color-text-muted);
    margin-top: 8px;
}

/* ---------------------------------------------------------------------------
   6. ป้ายสถานะ (Badge)
   ทุกป้ายสูงเท่ากันหมด (22px) มุมโค้งเท่ากัน แถวจึงไม่สูงเตี้ยไม่เท่ากัน
   --------------------------------------------------------------------------- */
.badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 22px;
    padding: 0 9px;
    border-radius: var(--radius-pill);
    font-size: 11.5px;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    vertical-align: middle;
}
.badge-neutral { background: var(--color-neutral-bg); color: var(--color-neutral); }
.badge-success { background: var(--color-success-bg); color: var(--color-success); }
.badge-warning { background: var(--color-warning-bg); color: var(--color-warning); }
.badge-alert   { background: var(--color-alert-bg);   color: var(--color-alert); }
.badge-danger  { background: var(--color-danger-bg);  color: var(--color-danger); }
.badge-info    { background: var(--color-info-bg);    color: var(--color-info); }
.badge-accent  { background: var(--color-accent-bg);  color: var(--color-accent); }
/* ระยะ A: ทิศทางรายการ Open — เดบิต (เขียว) / เครดิต (ส้ม) แยกด้วยสี ไม่ใช่แค่เครื่องหมายลบ */
.badge-debit   { background: var(--color-success-bg); color: var(--color-success); }
.badge-credit  { background: var(--color-warning-bg); color: var(--color-warning); }
.row-credit td { background: var(--tint-credit); }
.num.is-credit { color: var(--color-warning); }
.oi-filter-btn { background: var(--color-surface-alt); color: var(--color-text-soft); border: 1px solid var(--color-border); }
.oi-filter-btn.is-active { background: var(--color-info-bg); color: var(--color-info); border-color: var(--color-info); font-weight: 600; }

/* ป้ายอายุรายการในตาราง - ชิดขวาให้ตรงกับคอลัมน์ตัวเลขอื่น */
.badge-age { min-width: 62px; }

/* ---------------------------------------------------------------------------
   โต๊ะจับคู่เอง (Manual Matching) - หน้า manual-match.html
   ใช้ชุดสี ฟอนต์ และรูปแบบตารางเดียวกับหน้าอื่นทั้งหมด
   --------------------------------------------------------------------------- */

/* วางสองฝั่งเคียงกัน จอแคบให้ซ้อนกันลงมาแทน */
.match-desk {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
    align-items: start;
}
@media (max-width: 1100px) {
    .match-desk { grid-template-columns: minmax(0, 1fr); }
}

.match-side .card-title { display: flex; align-items: center; gap: 8px; }

/* แถบตัวกรองของแต่ละฝั่ง */
.match-filters {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 110px 110px;
    gap: 8px;
    margin-bottom: 10px;
}
.match-filters-dates { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-bottom: 10px; }
.match-filters .input, .match-filters-dates .input { font-size: 12.5px; padding: 6px 9px; }

/* กล่องรายการที่เลื่อนได้ - จำกัดความสูงไว้เพื่อให้แถบสรุปยอดอยู่ในสายตาเสมอ */
.match-list {
    max-height: 460px;
    overflow-y: auto;
    border: 1px solid var(--color-border);
    border-radius: 8px;
    background: var(--color-surface);
}
.match-list .table { margin: 0; }
.match-list .table thead th { position: sticky; top: 0; z-index: 1; }

.match-row-selected { background: var(--color-primary-soft) !important; }

/* แถบเครื่องมือปฏิเสธข้อเสนอที่รอตรวจสอบทีละหลายรายการ */
.match-bulk-bar {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}
.checkbox-inline {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--color-text-muted);
    white-space: nowrap;
    cursor: pointer;
}
/* ป้ายเตือนในแถว NAV ว่ามีข้อเสนอ pending ผูกอยู่ */
.pending-hint { color: var(--color-accent); font-weight: 500; }

.match-count-note {
    font-size: 12px;
    color: var(--color-text-muted);
    margin-top: 8px;
    display: flex;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
}

/* ---------------------------------------------------------------------------
   แถบสรุปยอดแบบทันที - ตัวเลขต้องเด่นและอ่านง่ายที่สุดในหน้า
   --------------------------------------------------------------------------- */
.match-summary {
    position: sticky;
    bottom: 0;
    z-index: 5;
    margin-top: 16px;
    padding: 16px 18px;
    border-radius: 10px;
    border: 2px solid var(--color-border);
    background: var(--color-surface);
    box-shadow: var(--shadow-sticky);
}
.match-summary.is-balanced { border-color: var(--color-success); background: var(--color-success-bg); }
.match-summary.is-unbalanced { border-color: var(--color-alert); background: var(--color-alert-bg); }

.match-figures {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px;
}
@media (max-width: 720px) {
    .match-figures { grid-template-columns: minmax(0, 1fr); }
}
.match-figure { text-align: center; }
.match-figure-label {
    font-size: 12.5px;
    color: var(--color-text-soft);
    margin-bottom: 4px;
}
.match-figure-value {
    font-size: 26px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--color-text);
    line-height: 1.25;
}
.match-figure-sub { font-size: 12px; color: var(--color-text-muted); margin-top: 2px; }
.match-summary.is-balanced .match-figure-diff { color: var(--color-success); }
.match-summary.is-unbalanced .match-figure-diff { color: var(--color-alert); }

.match-verdict {
    margin-top: 12px;
    font-size: 13.5px;
    font-weight: 600;
    text-align: center;
}
.match-summary.is-balanced .match-verdict { color: var(--color-success); }
.match-summary.is-unbalanced .match-verdict { color: var(--color-alert); }

.match-confirm-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 10px;
    align-items: end;
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--color-border);
}
@media (max-width: 720px) {
    .match-confirm-row { grid-template-columns: minmax(0, 1fr); }
}

/* บรรทัดเล็กใต้ป้ายอายุ บอกว่านับอายุจากวันไหน
   จำเป็นเพราะบางรายการไม่มีวันที่เอกสารในไฟล์ ระบบต้องประมาณจากวันสิ้นงวดที่พบครั้งแรก
   ผู้ใช้จึงควรเห็นได้ทันทีว่าตัวเลขอายุนั้นมาจากวันที่จริงหรือค่าประมาณ */
.aging-origin {
    font-size: 11px;
    color: var(--color-text-muted);
    margin-top: 2px;
    white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   7. ปุ่ม (Button)
   --------------------------------------------------------------------------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 36px;
    padding: 0 16px;
    border-radius: 6px;
    border: 1px solid transparent;
    font-size: 13.5px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color .12s, border-color .12s, color .12s;
}
.btn:disabled { opacity: .55; cursor: not-allowed; }

.btn-primary { background: var(--color-primary); color: var(--color-text-invert); }
.btn-primary:hover:not(:disabled) { background: var(--color-primary-hover); }

.btn-secondary { background: var(--color-surface); color: var(--color-text-soft); border-color: var(--color-border-strong); }
.btn-secondary:hover:not(:disabled) { background: var(--color-surface-alt); color: var(--color-text); }

.btn-success { background: var(--color-success); color: var(--color-text-invert); }
.btn-success:hover:not(:disabled) { background: var(--color-success-hover); }

.btn-danger-outline { background: var(--color-surface); color: var(--color-danger); border-color: var(--color-danger-soft); }
.btn-danger-outline:hover:not(:disabled) { background: var(--color-danger-bg); }

.btn-sm { height: 30px; padding: 0 12px; font-size: 12.5px; }

/* ปุ่มไอคอนในตาราง (แก้ไข = ดินสอ / ลบ = ถังขยะ) — ต้องมี title ทุกปุ่ม
   ขนาด 32px กดง่าย · ไอคอนวาดด้วย currentColor จึงได้สีตามชนิดปุ่มเดิม (ลบ = แดง) */
.btn-icon { width: 32px; height: 32px; padding: 0; display: inline-flex; align-items: center; justify-content: center; }
/* ไอคอนไม่รับคลิกเอง — ให้คลิกตกที่ปุ่มเสมอ (event delegation เดิมหา data-action ที่ปุ่ม) */
.btn-icon .icon { width: 16px; height: 16px; display: block; pointer-events: none; }

/* ปุ่มแบบลิงก์ในตาราง (แก้ไข / ลบ) */
.btn-link {
    background: none;
    border: none;
    padding: 0;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    color: var(--color-primary);
}
.btn-link:hover { text-decoration: underline; }
.btn-link.danger { color: var(--color-danger); }

/* ---------------------------------------------------------------------------
   8. ฟอร์ม (Form)
   --------------------------------------------------------------------------- */
.field { display: flex; flex-direction: column; gap: 5px; }
.label {
    font-size: 12px;
    font-weight: 600;
    color: var(--color-text-soft);
}
.input, .select {
    height: 36px;
    padding: 0 11px;
    border: 1px solid var(--color-border-strong);
    border-radius: 6px;
    font-size: 13.5px;
    background: var(--color-surface);
    color: var(--color-text);
    width: 100%;
}
.input:focus, .select:focus {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: var(--shadow-focus);
}
.input-file { font-size: 13px; color: var(--color-text-soft); }

input[type="checkbox"] {
    width: 15px;
    height: 15px;
    accent-color: var(--color-primary);
    cursor: pointer;
    vertical-align: middle;
}

/* ---------------------------------------------------------------------------
   ช่องค้นหาแบบพิมพ์กรอง (Combobox)
   ใช้แทน dropdown ธรรมดาเมื่อมีตัวเลือกจำนวนมาก เช่น รายชื่อบัญชี GL เกือบ 200 รายการ
   --------------------------------------------------------------------------- */
.combo { position: relative; }

.combo-list {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 30;
    max-height: 300px;
    overflow-y: auto;
    background: var(--color-surface);
    border: 1px solid var(--color-border-strong);
    border-radius: 6px;
    box-shadow: var(--shadow-pop);
}

.combo-option {
    padding: 8px 12px;
    font-size: 13.5px;
    cursor: pointer;
    border-bottom: 1px solid var(--color-border);
    line-height: 1.5;
}
.combo-option:last-child { border-bottom: none; }
.combo-option:hover,
.combo-option.is-active { background: var(--color-primary-soft); }

.combo-option .combo-code { font-weight: 600; font-variant-numeric: tabular-nums; }
.combo-option .combo-name { color: var(--color-text-soft); }
.combo-option .combo-sub { display: block; font-size: 11.5px; color: var(--color-text-muted); }

.combo-empty {
    padding: 12px;
    font-size: 13px;
    color: var(--color-text-muted);
    text-align: center;
}
.combo-more {
    padding: 7px 12px;
    font-size: 11.5px;
    color: var(--color-text-muted);
    background: var(--color-surface-alt);
    text-align: center;
}

/* ช่องที่เลือกค่าแล้ว - ทำให้เห็นชัดว่ามีค่าที่ถูกต้องอยู่ */
.combo input.is-selected {
    border-color: var(--color-primary);
    font-weight: 500;
}

/* เครื่องหมายถูกสีเขียว แทน checkbox ของรายการที่ยกยอดไปแล้ว */
.check-done {
    color: var(--color-success);
    font-size: 15px;
    font-weight: 700;
    line-height: 1;
}

.form-row {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: flex-end;
}
/* กันไม่ให้ช่องกรอกที่ยืดหยุ่น (flex) ดันจนล้นออกนอกแถว แล้วไปทับปุ่มข้างๆ */
.form-row > .field { min-width: 0; }

/* ฟอร์มแถวเดียวที่มีปุ่มอยู่ท้ายแถว
   ใช้ grid แทน flex เพื่อกำหนดพื้นที่ของแต่ละช่องให้ชัดเจน ปุ่มจึงไม่มีทางถูกช่องกรอกทับ
   คอลัมน์สุดท้าย (auto) = ปุ่ม กว้างพอดีข้อความ, คอลัมน์ 1fr = ช่องที่ยืดได้ */
.inline-form {
    display: grid;
    gap: 12px;
    align-items: end;
}
.inline-form > .field { min-width: 0; }
.inline-form .btn { align-self: end; }

/* จอแคบ: เรียงลงมาเป็นแนวตั้งทั้งหมด ปุ่มกว้างเต็มแถว */
@media (max-width: 640px) {
    .inline-form { grid-template-columns: 1fr !important; }
    .inline-form .btn { width: 100%; }
}
.form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 14px;
}

/* ---------------------------------------------------------------------------
   9. ข้อความแจ้งผล / กล่องสรุป
   --------------------------------------------------------------------------- */
.msg { font-size: 13px; margin-top: 8px; }
.msg-error { color: var(--color-danger); }
.msg-success { color: var(--color-success); }
.msg-muted { color: var(--color-text-muted); }
/* กล่องเตือนแบบเด่น (พื้นเหลือง) - ใช้กับแถบเตือนที่ต้องให้ผู้ใช้สังเกตและทำตาม */
.msg-warning {
    color: var(--color-warning);
    background: var(--color-warning-bg);
    border: 1px solid var(--color-warning);
    border-radius: var(--radius);
    padding: 12px 14px;
    font-size: 14px;
    font-weight: 500;
}

.summary-box {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 14px 16px;
    margin-top: 14px;
    background: var(--color-surface-alt);
}
.summary-box.is-success { border-color: var(--color-success-soft); background: var(--color-success-tint); }
.summary-box.is-warning { border-color: var(--color-warning-soft); background: var(--color-warning-tint); }
.summary-title { font-size: 13px; font-weight: 600; margin-bottom: 10px; }
.summary-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 12px;
}
.summary-label { font-size: 11.5px; color: var(--color-text-muted); }
.summary-value { font-size: 17px; font-weight: 700; margin-top: 1px; }
.summary-value.is-success { color: var(--color-success); }
.summary-value.is-warning { color: var(--color-warning); }

/* กล่องรายการรอตรวจสอบ / ประวัติการเคลียร์ */
.item-box {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 13px 15px;
    background: var(--color-surface);
}
.item-box + .item-box { margin-top: 10px; }
.item-box-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; flex-wrap: wrap; }
.item-tags { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.item-text { font-size: 13.5px; color: var(--color-text); margin-top: 6px; }
.item-sub { font-size: 12.5px; color: var(--color-text-soft); }
.evidence-list { margin-top: 5px; padding-left: 0; list-style: none; }
.evidence-list li { font-size: 12px; color: var(--color-text-muted); padding: 1px 0; }

/* รายการเหตุผลที่ระบบใช้ประกอบการเสนอ (แสดงให้ผู้ใช้อ่านก่อนตัดสินใจ) */
.reason-list { margin-top: 5px; padding-left: 0; list-style: none; }
.reason-list li { font-size: 11.5px; color: var(--color-text-soft); padding: 1px 0; }

/* ---------------------------------------------------------------------------
   ฟอร์มส่วนหัวของรอบกระทบยอด
   ใช้ grid ที่แต่ละช่องมีความกว้างขั้นต่ำแน่นอน ป้ายกำกับกับช่องกรอกจึงอยู่ตรงกันเสมอ
   และไม่ล้นออกนอกกรอบการ์ดเมื่อย่อ/ขยายหน้าต่าง
   --------------------------------------------------------------------------- */
.recon-form {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 16px;
    margin-top: 18px;
    align-items: start;
}
/* (.recon-form-actions ถูกถอด — ปุ่มบันทึกย้ายไปใต้ช่องสถานะ ปุ่มลบรอบไปมุมขวาบนหัวการ์ด) */
/* กันไม่ให้ input ที่มี width:100% ดันกรอบ grid จนล้น */
.recon-form .field { min-width: 0; }
.recon-form .input, .recon-form .select { max-width: 100%; box-sizing: border-box; }

/* ---------------------------------------------------------------------------
   แถบแจ้งเตือนงวดที่ถูกล็อก
   --------------------------------------------------------------------------- */
/* แถบแดง "ล็อกถาวร" (ระดับ 4) — เกณฑ์ใหม่: ไม่มีปุ่มใดๆ บนแถบนี้ */
.lock-banner {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    border: 1px solid var(--color-danger-soft);
    background: var(--color-danger-tint);
    border-radius: var(--radius);
    padding: 14px 16px;
    margin-bottom: 20px;
}
.lock-banner .lock-icon { font-size: 20px; line-height: 1.2; }
.lock-banner .lock-title { font-size: 14px; font-weight: 700; color: var(--color-danger); }
.lock-banner .lock-detail { font-size: 12.5px; color: var(--color-text-soft); margin-top: 3px; line-height: 1.6; }
.lock-banner .lock-actions { margin-left: auto; }

/* ทำให้ทั้งการ์ดเป็นแบบอ่านอย่างเดียวเมื่องวดถูกล็อก */
/* แถบงวดปิดแล้ว (ล็อกระดับ 2 — ยังไม่ถูกยกยอด เปิดงวดกลับมาแก้ได้) — โครงเดียวกับ lock-banner */
.closed-banner {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 12px 16px;
    margin-bottom: 14px;
    border: 1px solid var(--color-warning-soft);
    border-radius: 8px;
    background: var(--color-warning-bg);
}
.closed-banner .lock-icon { font-size: 20px; line-height: 1.2; }
.closed-banner .lock-title { font-size: 14px; font-weight: 700; color: var(--color-warning); }
.closed-banner .lock-detail { font-size: 12.5px; color: var(--color-text-soft); margin-top: 3px; line-height: 1.6; }
.closed-banner .lock-actions { margin-left: auto; }
.closed-banner .reopen-form { flex-basis: 100%; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.closed-banner .reopen-form .input { flex: 1; min-width: 220px; }

/* โหมดอ่านอย่างเดียว 2 ระดับ: readonly-locked (ล็อกถาวร) / readonly-closed (ปิดงวด รอเปิด)
   ปิดปุ่ม/ช่องกรอกที่ "แก้ข้อมูล" — แต่ของที่เป็น "การดู/ตรวจ" ล้วนต้องยังใช้ได้เสมอ:
   ค้นหา · ตัวกรอง · ปุ่มเหตุผล/โหลดเพิ่ม · Export · แท็บ (ไม่ใช่ .btn อยู่แล้ว) */
.readonly-locked input:not([type="checkbox"]):not([type="search"]),
.readonly-locked select,
.readonly-locked textarea,
.readonly-closed input:not([type="checkbox"]):not([type="search"]),
.readonly-closed select,
.readonly-closed textarea {
    background: var(--color-surface-alt);
    color: var(--color-text-muted);
    cursor: not-allowed;
}
.readonly-locked .btn { opacity: .5; pointer-events: none; }
.readonly-closed .btn:not(.btn-reopen) { opacity: .5; pointer-events: none; }
.readonly-locked input[type="checkbox"],
.readonly-closed input[type="checkbox"] { pointer-events: none; opacity: .5; }
/* ปุ่มยืนยัน/ยกเลิกการตรวจ (maker-checker) — เป็น metadata ต้องกดได้ทุกระดับงวด
   รวมงวดปิด (readonly-closed) และงวดล็อกถาวร (readonly-locked) */
.readonly-locked .btn-review,
.readonly-closed .btn-review { opacity: 1; pointer-events: auto; }
/* ช่องผู้ตรวจในฟอร์มข้อมูลงวด (อ่านอย่างเดียว — กรอบเดียวกับ input) + ปุ่ม/สถานะใต้ช่อง */
.review-display {
    display: flex;
    align-items: center;
    background: var(--color-surface-alt);
    cursor: default;
}
.review-display.is-empty { color: var(--color-text-muted); }
/* ปุ่ม (บันทึก / ยืนยันการตรวจ) + คำอธิบายสถานะ อยู่แถวเดียวกัน — ล้นแล้วตัดบรรทัดเอง */
.review-actions { display: flex; gap: 8px 10px; align-items: center; flex-wrap: wrap; margin-top: 8px; }
.review-status-line {
    flex: 1 1 auto; min-width: 0;
    font-size: 12.5px; color: var(--color-text-soft); line-height: 1.5;
}
.review-status-line.is-reviewed { color: var(--color-success); font-weight: 600; }
/* ข้อยกเว้น "การดู" — เปิดใช้กลับทั้งสองโหมด */
.readonly-locked a[data-export], .readonly-closed a[data-export],
.readonly-locked .mh-filter-btn, .readonly-closed .mh-filter-btn,
.readonly-locked .mh-who-btn, .readonly-closed .mh-who-btn,
.readonly-locked .oi-filter-btn, .readonly-closed .oi-filter-btn,
.readonly-locked [data-action="toggle-why"], .readonly-closed [data-action="toggle-why"],
.readonly-locked [data-acc-more], .readonly-closed [data-acc-more] {
    opacity: 1;
    pointer-events: auto;
}
/* ช่องเลือกคน/เหตุผลในฟอร์มเปิดงวด ต้องกรอกได้แม้อยู่โหมดอ่านอย่างเดียว
   (ฟอร์มปลดล็อกใน lock-banner ถูกถอดออกแล้ว — แถบล็อกถาวรไม่มีช่องกรอกใดๆ) */
.readonly-closed .closed-banner input,
.readonly-closed .closed-banner select {
    background: var(--color-surface);
    color: var(--color-text);
    cursor: auto;
}

/* ---------------------------------------------------------------------------
   ปรับปรุงยอดยกมาในงวดปัจจุบัน (ฟอร์มแก้/เพิ่ม/ลบ + ประวัติ)
   --------------------------------------------------------------------------- */
.carry-adjust-form {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface-alt);
    padding: 12px 14px;
    margin-bottom: 12px;
}
.carry-adjust-form .ca-form-title { font-size: 13.5px; font-weight: 700; margin-bottom: 8px; }
.carry-adjust-form .ca-form-item { font-size: 13px; color: var(--color-danger); font-weight: 600; margin-bottom: 8px; }
.carry-adjust-form .ca-form-fields {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 10px;
    margin-bottom: 8px;
}
.carry-adjust-form .ca-form-reason { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.carry-adjust-form .ca-form-reason .input { flex: 1; min-width: 260px; }
.carry-adjust-form .ca-adjuster { font-size: 12.5px; color: var(--color-text-soft); }
.carry-adjust-form .ca-form-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 10px; }
/* แถวใบยกที่ถูกลบผ่านการปรับปรุง — เห็นร่องรอยแต่จางลง ไม่มีปุ่ม */
.row-carry-deleted td { opacity: .55; }
.carry-log-section { margin-top: 10px; font-size: 13px; }
.carry-log-section summary { cursor: pointer; font-weight: 600; color: var(--color-text-soft); }

/* ---------------------------------------------------------------------------
   ผลการตรวจสอบก่อนปิดงวด
   --------------------------------------------------------------------------- */
.check-item {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    padding: 9px 0;
    border-bottom: 1px solid var(--color-border);
    font-size: 13.5px;
}
.check-item:last-child { border-bottom: none; }
.check-mark { font-weight: 700; line-height: 1.5; }
.check-item.is-pass .check-mark { color: var(--color-success); }
.check-item.is-fail .check-mark { color: var(--color-danger); }
.check-diff {
    margin-top: 6px;
    padding: 9px 12px;
    background: var(--color-danger-bg);
    border-radius: 6px;
    font-size: 12.5px;
    color: var(--color-danger);
    line-height: 1.6;
}
.check-diff ul { margin: 4px 0 0; padding-left: 18px; }
.check-diff li { font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
   คำอธิบายผลต่าง (GL เทียบรายการ Open) — อยู่ในการ์ด "การตรวจสอบ" (โซน 3)
   ตัวเลขทั้งสามย้ายขึ้นแถบหัวหน้า (โซน 1) แล้ว กล่องสรุปเดิมจึงถูกถอดทิ้งทั้งชุด
   (.recon-result / .recon-result-figures / .recon-figure*)
   --------------------------------------------------------------------------- */
.recon-result-msg {
    font-size: 13px;
    color: var(--color-text-soft);
    margin-top: 10px;
    line-height: 1.6;
}

/* ---------------------------------------------------------------------------
   แถบตรวจสอบความสมดุลทางบัญชี
   --------------------------------------------------------------------------- */
.balance-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 14px;
}
.balance-cell { text-align: right; }
.balance-cell .summary-label { text-align: right; }
.balance-cell .balance-value {
    font-size: 17px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    margin-top: 2px;
}
.balance-cell.is-result .balance-value { color: var(--color-primary); }
.balance-cell.is-ok .balance-value { color: var(--color-success); }
.balance-cell.is-diff .balance-value { color: var(--color-alert); }

/* ---------------------------------------------------------------------------
   การ์ดตัวเลือกจับคู่ที่ระบบเสนอ
   แบ่ง 2 คอลัมน์: ซ้าย = เอกสาร/เหตุผล (กว้างกว่า), ขวา = คะแนน/ตัวเลข/ปุ่ม
   --------------------------------------------------------------------------- */
.candidate-list { margin-top: 12px; }
.candidate {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface-alt);
    overflow: hidden;
}
.candidate + .candidate { margin-top: 10px; }
.candidate.is-top { border-color: var(--color-primary); background: var(--color-primary-soft); }

.candidate-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 260px;  /* ซ้ายยืดหยุ่น ขวากว้างคงที่ */
    gap: 18px;
    padding: 14px 16px;
}
@media (max-width: 780px) {
    .candidate-body { grid-template-columns: 1fr; }
}

/* คอลัมน์ซ้าย: รายการเอกสาร NAV */
.candidate-docs { list-style: none; padding: 0; margin: 0; }
.candidate-docs li {
    font-size: 13.5px;
    line-height: 1.65;
    color: var(--color-text);
    padding: 3px 0;
}
.candidate-docs .doc-no { font-weight: 600; }
.candidate-docs .doc-amt { font-variant-numeric: tabular-nums; color: var(--color-text-soft); }

/* ป้ายเหตุผล (chip) เรียงแนวนอน ประหยัดพื้นที่กว่าบูลเล็ตแนวตั้ง */
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.chip {
    display: inline-flex;
    align-items: center;
    height: 24px;
    padding: 0 10px;
    border-radius: var(--radius-pill);
    font-size: 12px;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
}
.chip-support { background: var(--color-success-bg); color: var(--color-success); }
.chip-caution { background: var(--color-warning-bg); color: var(--color-warning); }

/* คอลัมน์ขวา: คะแนน + ตัวเลข + ปุ่ม */
.candidate-side {
    display: flex;
    flex-direction: column;
    gap: 12px;
    border-left: 1px solid var(--color-border);
    padding-left: 16px;
}
@media (max-width: 780px) {
    .candidate-side { border-left: none; border-top: 1px solid var(--color-border); padding-left: 0; padding-top: 12px; }
}

/* แถบแสดงระดับความมั่นใจ */
.score-head { display: flex; justify-content: space-between; align-items: baseline; }
.score-num { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1; }
.score-max { font-size: 12px; color: var(--color-text-muted); }
.score-bar {
    height: 7px;
    border-radius: 999px;
    background: var(--color-border);
    overflow: hidden;
    margin-top: 6px;
}
.score-fill { height: 100%; border-radius: 999px; }
.score-high .score-num { color: var(--color-success); }
.score-high .score-fill { background: var(--color-success); }
.score-mid .score-num { color: var(--color-warning); }
.score-mid .score-fill { background: var(--color-warning); }
.score-low .score-num { color: var(--color-alert); }
.score-low .score-fill { background: var(--color-alert); }

/* แถวตัวเลขสรุป 3 ตัว - ตัวเลขเด่น ชิดขวา ป้ายกำกับเล็กอยู่ด้านบน */
.num-row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
}
.num-cell { text-align: right; }
.num-cell .num-label {
    font-size: 11px;
    color: var(--color-text-muted);
    line-height: 1.3;
}
.num-cell .num-value {
    font-size: 15px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1.35;
    margin-top: 1px;
}
.num-cell.is-warn .num-value { color: var(--color-alert); }
.num-cell.is-ok .num-value { color: var(--color-success); }

.candidate-actions { display: flex; gap: 8px; }
.candidate-actions .btn { flex: 1; }

/* แถวย่อของตัวเลือกอันดับรองๆ - แสดงข้อมูลสำคัญบรรทัดเดียว คลิกเพื่อขยาย */
.candidate-collapsed {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px;
    cursor: pointer;
    font-size: 13px;
}
.candidate-collapsed:hover { background: var(--color-primary-soft); }
.candidate-collapsed .cc-rank { font-weight: 600; color: var(--color-text-soft); white-space: nowrap; }
.candidate-collapsed .cc-score { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.candidate-collapsed .cc-doc {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--color-text-soft);
}
.candidate-collapsed .cc-num { font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.candidate-collapsed .cc-toggle { color: var(--color-primary); font-weight: 600; white-space: nowrap; }
.timeline-entry {
    border-left: 2px solid var(--color-success-soft);
    padding-left: 11px;
    margin-top: 9px;
}

.empty-state {
    font-size: 13px;
    color: var(--color-text-muted);
    padding: 10px 0;
}

.stack { display: flex; flex-direction: column; gap: 10px; }
.hidden { display: none !important; }

/* ---------------------------------------------------------------------------
   10. โฟกัสคีย์บอร์ด (Focus Visible)
   เดิมมีวงแหวนโฟกัสอยู่แค่ .input/.select — ปุ่ม ลิงก์ เมนู แท็บ และ checkbox
   ไม่มีอะไรบอกเลยว่าโฟกัสอยู่ที่ไหน คนที่ใช้ Tab ไล่หน้าจอจึงหลงทาง
   ใช้ :focus-visible (ไม่ใช่ :focus) เพื่อให้วงแหวนขึ้นเฉพาะตอนใช้คีย์บอร์ด
   ไม่ขึ้นตอนคลิกเมาส์ — หน้าตาเวลาใช้เมาส์จึงเหมือนเดิมทุกจุด
   --------------------------------------------------------------------------- */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
details:focus-visible,
[tabindex]:focus-visible,
[role="button"]:focus-visible,
input[type="checkbox"]:focus-visible,
input[type="file"]:focus-visible {
    outline: 2px solid var(--color-focus);
    outline-offset: 2px;
}
/* แถวตารางที่กดได้ (แถวสรุปกลุ่มบัญชีย่อย) — วงแหวนวาดเข้าด้านในกันเส้นตารางบัง
   และย้ำด้วยพื้นหลัง เพราะเส้นบางบนพื้นสลับสีอ่านยากในบางแถว */
tr:focus-visible {
    outline: 2px solid var(--color-focus);
    outline-offset: -2px;
}
tr:focus-visible > td { background: var(--color-primary-soft); }
/* กล่องยุบ/กางที่เป็น div (accordion, การ์ดตัวเลือกอันดับรอง) — ui-kit.js เติม tabindex ให้ */
.acc-head:focus-visible,
.candidate-collapsed:focus-visible { outline-offset: -2px; }

/* เลื่อนหน้าไปหา anchor แล้วต้องไม่ถูกหัวตาราง/แถบที่ตรึงไว้ทับ (WCAG 2.2 Focus Not Obscured) */
html { scroll-padding-top: 72px; }

/* ข้อความสำหรับโปรแกรมอ่านหน้าจอเท่านั้น — ตาไม่เห็น แต่ยังอยู่ในลำดับการอ่าน
   (ห้ามใช้ display:none หรือ visibility:hidden เพราะโปรแกรมอ่านหน้าจอจะข้ามไปด้วย) */
.sr-only {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ---------------------------------------------------------------------------
   11. หัวตารางตรึง (Sticky Table Head)
   ตารางยาวเป็นร้อยแถว เลื่อนลงไปแล้วลืมว่าคอลัมน์ไหนคืออะไร ต้องเลื่อนกลับขึ้นมาดู
   เปิดใช้ด้วยการเติมคลาส is-sticky-head ที่ .table-wrap ของตารางนั้น

   เงื่อนไขสำคัญ: .table-wrap ปกติเป็น overflow-x:auto ซึ่งทำให้มันกลายเป็น "กล่องเลื่อน"
   -> thead จะไปตรึงกับขอบของกล่อง (ที่ไม่เคยเลื่อนแนวตั้ง) แทนขอบจอ = ไม่เกิดอะไรขึ้นเลย
   จึงต้องปลด overflow ทิ้งบนจอกว้าง แล้วคืนให้เฉพาะจอแคบ
   (จอแคบ การเลื่อนแนวนอนสำคัญกว่าหัวตารางตรึง)
   --------------------------------------------------------------------------- */
.table-wrap.is-sticky-head { overflow: visible; }
@media (max-width: 900px) {
    .table-wrap.is-sticky-head { overflow-x: auto; }
}
.table-wrap.is-sticky-head .table thead th {
    position: sticky;
    top: var(--sticky-top, 0);
    z-index: 3;
    /* ใช้เงาด้านในแทน border-bottom เพราะเส้นขอบไม่ติดไปกับหัวตารางตอนมันตรึงอยู่ */
    box-shadow: inset 0 -2px 0 var(--color-border-strong);
}

/* ---------------------------------------------------------------------------
   12. โครงร่างระหว่างโหลด (Skeleton)
   แทนข้อความ "กำลังโหลดข้อมูล..." บรรทัดเดียว — โครงร่างสูงเท่าแถวจริง
   ตารางจึงไม่กระตุกตอนข้อมูลมาถึง (CLS) และผู้ใช้เห็นล่วงหน้าว่ากำลังจะมีอะไรมา
   --------------------------------------------------------------------------- */
.skeleton {
    display: block;
    height: 12px;
    border-radius: var(--radius-pill);
    background: linear-gradient(90deg,
        var(--color-surface-alt) 25%, var(--color-header) 37%, var(--color-surface-alt) 63%);
    background-size: 400% 100%;
    animation: skeleton-shimmer 1.4s ease-in-out infinite;
}
@keyframes skeleton-shimmer {
    from { background-position: 100% 0; }
    to   { background-position: 0 0; }
}
.skeleton-row td { vertical-align: middle; }
/* แถวโครงร่างไม่ต้องไฮไลต์ตอนเอาเมาส์ชี้ — ยังไม่มีอะไรให้กด */
.table tbody tr.skeleton-row:hover { background: inherit; }

/* ตัวหมุนสำหรับหน้าที่โหลดทั้งหน้า (ไม่ใช่ตาราง) */
.spinner {
    display: inline-block;
    width: 15px; height: 15px;
    border: 2px solid var(--color-border-strong);
    border-top-color: var(--color-primary);
    border-radius: 50%;
    animation: spinner-turn .7s linear infinite;
    vertical-align: -2px;
    margin-right: 7px;
}
@keyframes spinner-turn { to { transform: rotate(360deg); } }

/* ---------------------------------------------------------------------------
   13. ข้อความแจ้งผลลอย (Toast) — ui-kit.js
   แทน alert() ของเบราว์เซอร์: ไม่บล็อกหน้าจอ ขึ้นซ้อนกันได้หลายข้อความ
   ขึ้นบรรทัดใหม่ตามข้อความจริงที่ API ส่งมา และปิดเองตามระดับความสำคัญ
   --------------------------------------------------------------------------- */
.toast-region {
    position: fixed;
    right: 16px; bottom: 16px;
    z-index: 1000;
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: flex-end;
    pointer-events: none;   /* คลิกทะลุพื้นที่ว่างไปโดนหน้าเว็บได้ตามปกติ */
    max-width: min(420px, calc(100vw - 32px));
}
@media (max-width: 640px) {
    .toast-region { left: 12px; right: 12px; bottom: 12px; max-width: none; align-items: stretch; }
}
/* สองช่องซ้อนกัน (assertive สำหรับข้อผิดพลาด / polite สำหรับที่เหลือ) — ดูเป็นกองเดียวกัน */
.toast-slot {
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 100%;
}
.toast-slot:empty { display: none; }   /* ช่องว่างไม่ต้องกิน gap ของ region */
.toast {
    pointer-events: auto;
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    width: 100%;
    padding: 11px 12px;
    border: 1px solid var(--color-border-strong);
    border-left-width: 4px;
    border-radius: var(--radius);
    background: var(--color-surface);
    box-shadow: var(--shadow-pop);
    font-size: 13px;
    line-height: 1.55;
    color: var(--color-text);
    /* เข้า: ลอยขึ้นมาจากทิศที่มันอยู่ · ออก: เร็วกว่าเข้า เพื่อไม่ขัดจังหวะงานถัดไป */
    animation: toast-in .18s cubic-bezier(.16, 1, .3, 1);
}
.toast.is-out { animation: toast-out .12s ease-in forwards; }
@keyframes toast-in  { from { opacity: 0; transform: translateY(10px); } }
@keyframes toast-out { to   { opacity: 0; transform: translateY(6px); } }

.toast-icon { flex: 0 0 auto; width: 17px; height: 17px; margin-top: 1px; }
.toast-msg  { flex: 1 1 auto; min-width: 0; white-space: pre-line; word-break: break-word; }
.toast-close {
    flex: 0 0 auto;
    position: relative;
    width: 26px; height: 26px;
    margin: -3px -4px 0 0;
    display: inline-flex; align-items: center; justify-content: center;
    border: none; border-radius: 6px;
    background: none;
    color: var(--color-text-muted);
    cursor: pointer;
}
.toast-close:hover { background: var(--color-surface-alt); color: var(--color-text); }
.toast-close .icon { width: 13px; height: 13px; pointer-events: none; }
/* ขยายพื้นที่กดจริงเป็น 44x44 (นิ้วกดโดน) โดยปุ่มยังดูเล็กพอดีกล่อง */
.toast-close::before {
    content: "";
    position: absolute;
    top: 50%; left: 50%;
    width: 44px; height: 44px;
    transform: translate(-50%, -50%);
}

.toast-success { border-left-color: var(--color-success); }
.toast-success .toast-icon { color: var(--color-success); }
.toast-error   { border-left-color: var(--color-danger); }
.toast-error .toast-icon { color: var(--color-danger); }
.toast-warning { border-left-color: var(--color-warning); }
.toast-warning .toast-icon { color: var(--color-warning); }
.toast-info    { border-left-color: var(--color-primary); }
.toast-info .toast-icon { color: var(--color-primary); }

/* ---------------------------------------------------------------------------
   14. กล่องยืนยัน / กล่องกรอก (Dialog) — ui-kit.js
   แทน confirm() และ prompt() ของเบราว์เซอร์
   ใช้ <dialog> ของ HTML จริง จึงได้สิ่งเหล่านี้มาฟรีและถูกต้องตามมาตรฐาน:
   กักโฟกัสไว้ในกล่อง · Esc ปิด · คืนโฟกัสกลับปุ่มที่กดเปิด · วาดทับทุกอย่างเสมอ
   --------------------------------------------------------------------------- */
.ui-dialog {
    width: min(460px, calc(100vw - 32px));
    padding: 0;
    border: 1px solid var(--color-border-strong);
    border-radius: 10px;
    background: var(--color-surface);
    color: var(--color-text);
    box-shadow: var(--shadow-pop);
}
.ui-dialog::backdrop { background: rgba(15, 23, 42, .45); }
.ui-dialog[open] { animation: dialog-in .16s cubic-bezier(.16, 1, .3, 1); }
@keyframes dialog-in { from { opacity: 0; transform: scale(.97); } }

.ui-dialog-form { padding: 18px 20px 16px; margin: 0; }
.ui-dialog-title { font-size: 15.5px; font-weight: 700; line-height: 1.4; }
.ui-dialog-msg {
    margin-top: 8px;
    font-size: 13.5px;
    line-height: 1.65;
    color: var(--color-text-soft);
    white-space: pre-line;      /* ข้อความจาก API ที่คั่นบรรทัดไว้ต้องยังอ่านเป็นย่อหน้าได้ */
    word-break: break-word;
    max-height: 46vh;
    overflow-y: auto;
}
.ui-dialog-field { margin-top: 14px; }
.ui-dialog-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 18px;
    flex-wrap: wrap;
}
.ui-dialog-actions .btn { min-width: 92px; }
/* ปุ่มยืนยันของสิ่งที่กู้คืนไม่ได้ — สีอันตราย และโฟกัสเริ่มต้นไปอยู่ที่ "ยกเลิก" */
.btn-danger { background: var(--color-danger); color: var(--color-text-invert); }
.btn-danger:hover:not(:disabled) { filter: brightness(.93); }

/* ---------------------------------------------------------------------------
   กล่องนำเข้าบัญชี GL จาก Excel (index.html)
   กว้างกว่ากล่องยืนยันทั่วไป เพราะมีตารางจับคู่คอลัมน์ + ตารางพรีวิวข้อมูล
   (เดิมกล่องกว้าง 460px แต่ฟอร์มถูกบังคับ 560px จึงล้นออกนอกกล่อง — กำหนดความกว้าง
   ให้กล่องนี้เองและปล่อยให้เนื้อหาพอดีขอบ ไม่ต้องมี min-width ที่ฟอร์มอีก)
   --------------------------------------------------------------------------- */
#import-dialog { width: min(760px, calc(100vw - 32px)); max-height: calc(100vh - 24px); max-height: calc(100dvh - 24px); }

/* ---------------------------------------------------------------------------
   กล่องย่อยของ "นำเข้าข้อมูลและจับคู่รายการ" (reconciliation.html)
   แต่ละกล่องย่อย = หนึ่งการกระทำ พร้อมหัวข้อและคำอธิบายของตัวเอง
   กล่องที่ลบข้อเสนอทิ้งใช้พื้นสีเตือน เพื่อให้แยกออกจากการนำเข้าไฟล์ตามปกติได้ทันที
   --------------------------------------------------------------------------- */
.nav-action { border: 1px solid var(--color-border); border-radius: 8px; padding: 14px 16px; }
.nav-action + .nav-action { margin-top: 12px; }
.nav-action-title { font-size: 13.5px; font-weight: 600; color: var(--color-text); margin: 0; }
.nav-action-warn { border-color: var(--color-warning-soft); background: var(--color-warning-tint); }
/* ปุ่มทึบสีเตือน — ใช้กับการกระทำที่ "ล้างของเดิมทิ้ง" แต่ยังไม่ถึงขั้นกู้คืนไม่ได้ */
.btn-warning { background: var(--color-warning); color: var(--color-text-invert); }
.btn-warning:hover:not(:disabled) { filter: brightness(.93); }

/* โซนปุ่มคำนวณใหม่ทั้งงวดแบบเดิม (ไม่ได้ใช้แล้วหลังจัดกล่องใหม่ 9 ก.ย. 2026 — เก็บไว้เผื่อย้อนกลับ) */
.reanalyze-zone { margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--color-border); }
#reanalyze-dialog { width: min(560px, calc(100vw - 32px)); }
#reanalyze-dialog .ui-dialog-form { display: flex; flex-direction: column; gap: 10px; }
.reanalyze-facts { margin: 0; padding-left: 18px; font-size: 13px; line-height: 1.7; }
.reanalyze-options { border: 1px solid var(--color-border); border-radius: 8px; padding: 8px 12px 10px; display: flex; flex-direction: column; gap: 6px; }
.reanalyze-options legend { padding: 0 4px; }
/* ฟอร์มเลื่อนในตัวเองได้ถ้ากล่องสูงเกินจอ (จอเตี้ย/มือถือ) — หัวเรื่องกับปุ่มจะไม่ถูกตัดหาย */
#import-dialog .ui-dialog-form {
    display: flex;
    flex-direction: column;
    gap: 13px;
    max-height: calc(100vh - 24px);
    max-height: calc(100dvh - 24px);
    overflow-y: auto;
    box-sizing: border-box;
}

/* หัวข้อย่อยคั่นส่วน "จับคู่คอลัมน์" กับ "ตัวอย่างข้อมูล" */
.import-section-title {
    margin: 2px 0 0;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .02em;
    color: var(--color-text-soft);
}

/* บรรทัดชื่อชีต + ป้ายความมั่นใจ */
.import-sheet-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.import-sheet-row .table-note { margin: 0; }

/* ตารางจับคู่: ชิดกระชับ · select ไม่ดันความกว้างกล่อง */
.import-map-table td { padding: 8px 12px; }
.import-map-table .import-map-field { white-space: nowrap; font-weight: 500; }
.import-map-table .select { max-width: 100%; box-sizing: border-box; }

/* ป้ายความมั่นใจในการเดา (สูง/ปานกลาง/ต่ำ) — จุดสีนำหน้าจากสีตัวอักษร */
.import-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
}
.import-badge::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.import-badge-high { color: var(--color-success); background: var(--color-success-bg); }
.import-badge-medium { color: var(--color-warning); background: var(--color-warning-bg); }
.import-badge-low { color: var(--color-danger); background: var(--color-danger-bg); }

/* ชิปสรุปจำนวน เพิ่มใหม่ / อัปเดต / ข้าม / รวม */
.import-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.import-chip {
    display: inline-flex;
    align-items: center;
    padding: 4px 11px;
    border-radius: 999px;
    border: 1px solid transparent;
    font-size: 12.5px;
    font-weight: 600;
}
.import-chip-new { color: var(--color-success); background: var(--color-success-bg); border-color: var(--color-success-soft); }
.import-chip-update { color: var(--color-primary); background: var(--color-primary-soft); border-color: var(--color-primary); }
.import-chip-muted { color: var(--color-text-soft); background: var(--color-surface-alt); border-color: var(--color-border); }

/* ตารางพรีวิว: จำกัดความสูงให้เห็นไม่กี่แถวแล้วเลื่อนในกล่องเอง (หัวตารางติดขอบบน) */
.import-preview-wrap { max-height: 232px; overflow: auto; }

/* ---------------------------------------------------------------------------
   15. ปุ่มสลับธีม (ตามระบบ / สว่าง / มืด) — theme.js
   อยู่ท้ายแถบเมนูชิดขวา · หน้า login ที่ไม่มีแถบเมนูจะไปอยู่มุมขวาบนของการ์ด
   --------------------------------------------------------------------------- */
.nav .theme-toggle { margin-left: auto; }
.theme-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    padding: 0 10px;
    border: 1px solid transparent;
    border-radius: 6px;
    background: none;
    color: var(--color-text-soft);
    font-size: 12.5px;
    font-weight: 500;
    cursor: pointer;
    transition: background-color .12s, color .12s;
}
.theme-toggle:hover { background: var(--color-surface-alt); color: var(--color-text); }
.theme-toggle .icon { width: 16px; height: 16px; pointer-events: none; }
.auth-card { position: relative; }
/* การ์ดนี้มีหัวพื้นสีหลัก (ฟ้า) ปุ่มจึงต้องใช้สีตัวอักษรบนพื้นทึบ
   ไม่ใช่ --color-text-soft ตามค่าตั้งต้น (เทาบนฟ้า = อ่านไม่ออก) */
.auth-card .theme-toggle {
    position: absolute;
    top: 10px; right: 10px;
    color: var(--color-text-invert);
}
.auth-card .theme-toggle:hover {
    background: var(--overlay-on-primary);
    color: var(--color-text-invert);
}

/* ---------------------------------------------------------------------------
   16. เคารพการตั้งค่า "ลดการเคลื่อนไหว" ของเครื่องผู้ใช้
   บางคนเวียนหัว/คลื่นไส้กับภาพเคลื่อนไหว (vestibular disorder) และตั้งค่าไว้ที่ OS แล้ว
   หน้าเว็บต้องหยุดให้ — แต่ยังต้องเห็นผลลัพธ์ปลายทาง จึงไม่ปิดทิ้ง แค่ย่อเวลาให้เกือบศูนย์
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
    /* โครงร่างระหว่างโหลดไม่ต้องมีแสงวิ่ง — พื้นเทานิ่งๆ ก็บอกได้ว่ากำลังโหลด */
    .skeleton { background: var(--color-surface-alt); }
}

/* ---------------------------------------------------------------------------
   17. หลายขนาดหน้าจอ (Responsive) + โหมดติดตั้งเป็นแอป (PWA)

   จุดตัด (breakpoint) ที่ระบบนี้ใช้ — ค่าเดิมถูกจูนมาเป็นรายส่วนประกอบ ไม่ได้เป็นสเกลเดียวกัน
   จึงคงไว้ตามเดิมทั้งหมด (เปลี่ยนแล้วเลย์เอาต์จะสลับที่ความกว้างใหม่ = เสี่ยงเปล่าๆ):
     640px  ฟอร์มแถวเดียว -> เรียงลง · toast กินเต็มความกว้าง
     700px  ช่องตัวเลขบนแถบหัวหน้ารายละเอียด (reconciliation.html)
     720px  ตัวเลขสรุปโต๊ะจับคู่ -> เรียงลง
     780px  การ์ดตัวเลือกจับคู่ -> คอลัมน์เดียว
     900px  หัวตารางตรึง <-> เลื่อนแนวนอน (และคอลัมน์แรกตรึงเริ่มทำงาน)
     1100px โต๊ะจับคู่สองฝั่ง -> ซ้อนกันลงมา
   ของใหม่ในไฟล์นี้เพิ่มเฉพาะสองปลาย: จอใหญ่ (>=1500px) และจอสัมผัส (pointer: coarse)
   --------------------------------------------------------------------------- */

/* ---- จอใหญ่: เลิกทิ้งพื้นที่ว่างสองข้าง ----
   ค่าเดิม .page ตัน 1180px ทุกจอ — บนจอ 1920 คือปล่อยว่างข้างละ ~370px
   ขณะที่ตารางข้างในต้องเลื่อนแนวนอน/ตัดข้อความทิ้ง เป็นการเสียของ
   (.page-narrow เช่นหน้าเปลี่ยนรหัส ต้องแคบเท่าเดิม — ความกว้างสั้นๆ อ่านง่ายกว่า) */
@media (min-width: 1500px) {
    .page:not(.page-narrow) { max-width: 1360px; }
}
@media (min-width: 1800px) {
    .page:not(.page-narrow) { max-width: 1560px; }
}

/* ---- ขอบปลอดภัยของจอ (safe area) ----
   จำเป็นเมื่อติดตั้งเป็นแอปแล้วเปิดเต็มจอ (display: standalone + viewport-fit=cover):
   มือถือมีติ่ง/มุมโค้ง/แถบ home indicator จะกินพื้นที่ขอบจอ ถ้าไม่เว้นระยะเอง
   ปุ่มมุมล่างกับข้อความริมขอบจะถูกทับจนกดไม่ได้
   บนจอคอมค่าพวกนี้เป็น 0px ทั้งหมด -> ไม่มีอะไรเปลี่ยน */
:root {
    --safe-top: env(safe-area-inset-top, 0px);
    --safe-right: env(safe-area-inset-right, 0px);
    --safe-bottom: env(safe-area-inset-bottom, 0px);
    --safe-left: env(safe-area-inset-left, 0px);
}
.page {
    padding-top: calc(28px + var(--safe-top));
    padding-left: calc(20px + var(--safe-left));
    padding-right: calc(20px + var(--safe-right));
    padding-bottom: calc(64px + var(--safe-bottom));
}
.auth-page {
    padding-top: calc(24px + var(--safe-top));
    padding-left: calc(24px + var(--safe-left));
    padding-right: calc(24px + var(--safe-right));
    padding-bottom: calc(24px + var(--safe-bottom));
}
/* แถบเตือน "เซิร์ฟเวอร์รันโค้ดเก่า" เขียนสไตล์ไว้ในตัวเอง (version-check.js ไม่พึ่ง app.css
   เผื่อ CSS โหลดไม่ทัน) จึงต้องใช้ !important เพื่อเว้นขอบติ่งจอให้ — ไม่งั้นข้อความเตือน
   ที่สำคัญที่สุดในระบบจะถูกแถบสถานะของมือถือทับตอนติดตั้งเป็นแอป */
#stale-server-banner { padding-top: calc(14px + var(--safe-top)) !important; }
.toast-region {
    right: calc(16px + var(--safe-right));
    bottom: calc(16px + var(--safe-bottom));
}
@media (max-width: 640px) {
    .toast-region {
        left: calc(12px + var(--safe-left));
        right: calc(12px + var(--safe-right));
        bottom: calc(12px + var(--safe-bottom));
    }
}
/* แถบสรุปยอดที่ตรึงก้นจอ (โต๊ะจับคู่) — ต้องไม่ให้ home indicator ทับปุ่มยืนยัน */
.match-summary { padding-bottom: calc(16px + var(--safe-bottom)); }

/* ---- จอสัมผัส: ขนาดที่กดโดน ----
   pointer: coarse = นิ้ว (ไม่ใช่เมาส์) · เกณฑ์ 44x44px ของทั้ง iOS และ Android
   ปุ่มในตารางของเดิมสูง 30-32px ซึ่งกดพลาดง่ายมากบนแท็บเล็ต
   แถวตารางจะสูงขึ้นเฉพาะบนเครื่องสัมผัส — บนคอมความหนาแน่นเท่าเดิมทุกพิกเซล */
@media (pointer: coarse) {
    .btn { height: 44px; padding: 0 18px; }
    .btn-sm { height: 44px; padding: 0 14px; }
    .btn-icon { width: 44px; height: 44px; }
    .btn-icon .icon { width: 18px; height: 18px; }
    /* ปุ่มแบบข้อความในตาราง (แก้ไข/ลบ) — ไม่มีความสูงของตัวเอง ต้องบังคับพื้นที่กด */
    .btn-link { display: inline-flex; align-items: center; min-height: 44px; padding: 0 4px; }
    .nav a { padding: 12px 16px; }
    .theme-toggle { height: 44px; }
    .input, .select { height: 44px; }
    input[type="checkbox"] { width: 20px; height: 20px; }
    /* ช่องติ๊กในตารางต้องมีที่ว่างรอบตัวพอให้นิ้วลงได้ตรงช่อง ไม่ไปโดนแถวข้างๆ */
    .table .col-check { width: 48px; }
    .table tbody td { padding-top: 13px; padding-bottom: 13px; }
    .combo-option { padding: 12px; }
    .checkbox-inline { min-height: 44px; }
    .toast-close { width: 36px; height: 36px; }
    /* ปุ่มปิด/ปุ่มในกล่องยืนยันต้องกดง่ายที่สุด — เป็นจุดตัดสินใจ */
    .ui-dialog-actions .btn { min-width: 112px; }
}

/* ---- จอเล็ก: คอลัมน์แรกของตารางกว้างตรึงไว้ ----
   ตารางกว้างบนจอมือถือต้องเลื่อนแนวนอน แล้วพอเลื่อนไปดูคอลัมน์ขวา
   "ไม่รู้แล้วว่าแถวนี้คือบัญชีอะไร" — ตรึงคอลัมน์แรก (เลขบัญชี/ชื่อ) ไว้ให้เห็นตลอด
   เปิดใช้ด้วยคลาส is-sticky-col ที่ .table-wrap

   ทำเฉพาะ <= 900px โดยเจตนา: เหนือจากนั้น is-sticky-head ปลด overflow ของกล่องไปแล้ว
   ไม่มีการเลื่อนแนวนอน -> ตรึงคอลัมน์ไม่มีความหมาย และไม่ต้องเสี่ยงเปลี่ยนอะไรบนจอคอม */
@media (max-width: 900px) {
    /* ทุกแถวต้องมีพื้นทึบของตัวเอง ไม่งั้นเซลล์ที่ตรึงอยู่จะโปร่งใส
       แล้วเห็นเนื้อหาคอลัมน์อื่นวิ่งทะลุผ่านตอนเลื่อน (แถวคู่มีพื้นอยู่แล้ว แถวคี่ไม่มี) */
    .table-wrap.is-sticky-col .table tbody tr { background: var(--color-surface); }
    .table-wrap.is-sticky-col .table th:first-child,
    .table-wrap.is-sticky-col .table td:first-child {
        position: sticky;
        left: 0;
        z-index: 2;
        background: inherit;                              /* ตามสีแถว: สลับสี/ชี้เมาส์/แถวรวม */
        box-shadow: 1px 0 0 var(--color-border);          /* เส้นบางบอกว่ามีของซ่อนอยู่ทางขวา */
    }
    /* มุมซ้ายบน (หัวตาราง + คอลัมน์แรก) ต้องอยู่บนสุด ไม่ให้เซลล์อื่นเลื่อนมาทับ */
    .table-wrap.is-sticky-col .table thead th:first-child {
        z-index: 4;
        background: var(--color-header);
    }
    .table-wrap.is-sticky-col .table tr.row-total td:first-child { background: var(--color-header); }
}

/* ---- แถบเตือนตอนออฟไลน์ (pwa.js) ----
   ติดก้นจอ ไม่ใช่หัวจอ — ไม่ไปแย่งที่กับแถบ "เซิร์ฟเวอร์รันโค้ดเก่า" (version-check.js)
   ที่ยึดหัวจอไว้แล้ว และไม่ดันเนื้อหาทั้งหน้าลงตอนโผล่ */
.offline-bar {
    position: fixed;
    left: var(--safe-left);
    right: var(--safe-right);
    bottom: 0;
    z-index: 1001;                 /* สูงกว่า toast — เป็นสถานะของทั้งระบบ */
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: 10px 14px calc(10px + var(--safe-bottom));
    background: var(--color-warning-bg);
    color: var(--color-warning);
    border-top: 2px solid var(--color-warning);
    font-size: 13px;
    font-weight: 600;
    line-height: 1.5;
    text-align: center;
}
.offline-bar .icon { flex: 0 0 auto; width: 18px; height: 18px; }
/* toast ต้องขึ้นเหนือแถบออฟไลน์ ไม่ให้ทับกัน */
body:has(.offline-bar) .toast-region { bottom: calc(60px + var(--safe-bottom)); }
