/* ============================================================
   app.css — Bootstrap-first
   ทุกอย่างสร้างด้วย Bootstrap class ก่อนเสมอ ไฟล์นี้มีแค่ 7 บล็อค
   ที่ Bootstrap ทดแทนไม่ได้จริงๆ (เหตุผลกำกับรายบล็อค)
   ============================================================ */

/* [1] font — @font-face ไม่มี utility ทดแทน
   self-host ทั้งหมด (MOTION.md 1.2) — เดิม Noto Sans Thai กับ Material Symbols โหลดจาก
   Google Fonts ตัวหนังสือ/ไอคอนจึงกระพริบตอน font-display: swap สลับเข้ามา
   (2569-10-02 ลอง Sarabun ไปรอบหนึ่งแล้วกลับมา Google Sans + Noto Sans Thai ตามเดิม)
   เก็บแค่ 2 subset ที่ระบบใช้จริง (thai · latin) ตัด latin-ext ที่ไม่มีอักษรพิเศษยุโรปทิ้ง */
@font-face {
  font-family: "Google Sans";
  src: url("fonts/GoogleSans-Variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Noto Sans Thai";
  src: url("fonts/NotoSansThai-thai.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC;
}
@font-face {
  font-family: "Noto Sans Thai";
  src: url("fonts/NotoSansThai-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ฟอนต์ไอคอน (Material Symbols) — @font-face อยู่ใน <style> ของ _base.html ไม่ใช่ที่นี่
   เพราะต้องใช้ url_for ติด ?v= ให้ตรงกับ preload (ไฟล์ถูก subset ใหม่บ่อย · ดู _ICON_FONT ใน app.py) */

/* [2] ฐาน 18px — scale ทุก rem ของ Bootstrap พร้อมกัน */
html {
  font-size: 112.5%;
}

/* [3] token — override ตัวแปร Bootstrap ให้ตรงสีที่ล็อคไว้ */
:root {
  --bs-primary: #327BFA;
  --bs-primary-rgb: 50, 123, 250;
  --bs-success: #15803D;
  --bs-success-rgb: 21, 128, 61;

  /* เขียวของแถบขั้นบนการ์ดทริป (2569-09-20) — คนละตัวกับ --bs-success ซึ่งเป็นเขียวเข้ม
     ที่ใช้กับป้ายสถานะและตัวหนังสือ · ตัวนี้สด contrast 2.29:1 จึงใช้ได้กับ **รูปร่าง**
     (ไอคอน เส้น วงแหวน) เท่านั้น ห้ามเอาไปทำสีตัวหนังสือ — ตัวหนังสือใช้ --green-ink */
  --green:      #2EC459;   /* oklch(0.720 0.192 148) */
  --green-soft: #D5F8D9;   /* oklch(0.945 0.055 148) */
  --green-ink:  #087736;   /* oklch(0.500 0.135 150) */

  /* คู่สีของกล่องไอคอนในรายการ — พื้นอ่อน (soft) + ตัวไอคอน (ink)
     ใช้ผ่านคลาส .tone-* ซึ่งตั้ง --tint กับ --fg ให้ .ico-tint */
  --blue-soft:  #D9EDFF;   /* oklch(0.940 0.045 258) */
  --blue-ink:   #006BED;   /* oklch(0.558 0.214 258) */
  --amber-soft: #FFEACB;   /* oklch(0.950 0.050 72) */
  --amber-ink:  #935800;   /* oklch(0.515 0.115 66) */
  /* แดงยืมคู่สีที่ระบบใช้อยู่แล้ว (CALENDAR_STATUS_COLOR · .state-bad) ไม่ตั้งค่าใหม่ */
  --red-soft:   #FBE9E9;
  --red-ink:    #A32D2D;

  /* สีสถานะมาตรฐาน 5 ขั้น ทั้งระบบ (2569-10-15) — ขั้นของงานแต่ละชนิดอยู่ mock.STAGE
     info แจ้งให้ทราบ/ยกเลิก · wait รอ… · ok อนุมัติแล้ว/กำลังทำ · done จบแล้ว · bad ไม่ผ่าน
     --st-X = จุด/ไอคอน/ตัวหนังสือบนพื้นขาว (≥4.5:1) · -soft = พื้นอ่อน · -ink = ตัวหนังสือบน -soft
     ห้ามตั้งค่าสีสถานะที่อื่นอีก — คลาส .tone-* .rgt-lbl-* .dt-tone-* .ev-* อ่านจากชุดนี้ */
  --st-info: #5F6368;  --st-info-soft: #F1F3F4;  --st-info-ink: #3C4043;
  --st-wait: #B06000;  --st-wait-soft: #FEEFE3;  --st-wait-ink: #7A4100;
  --st-ok:   #1A73E8;  --st-ok-soft:   #E8F0FE;  --st-ok-ink:   #174EA6;
  --st-done: #137333;  --st-done-soft: #E6F4EA;  --st-done-ink: #0D652D;
  --st-bad:  #C5221F;  --st-bad-soft:  #FCE8E6;  --st-bad-ink:  #A50E0E;
  --bs-border-color: #E5E7EB;
  --bs-body-bg: #FFFFFF;
  --bs-body-color: #000000;
  --bs-secondary-color: #6E6E6E;
  --bs-secondary-bg: #F2F3F5;        /* พื้นเมนู active (bg-body-secondary) */
  --bs-font-sans-serif: "Google Sans", "Noto Sans Thai", system-ui, sans-serif;
  --bs-body-font-weight: 300;
  --app-header-h: 64px;          /* ความสูง header — sidebar อ้างอิงค่านี้ */

  /* ขนาดตัวอักษร — ฐาน 18px (html 112.5%)
     ก่อนหน้านี้เขียน inline กระจาย 37 ค่า ต่างกันไม่ถึง 1px หลายคู่ จึงรวบเป็นชั้น
     ใช้ผ่าน .fs-2xs … .fs-2xl ห้ามเขียน font-size inline ใหม่

     ชั้น xl/2xl เพิ่งเพิ่ม: เดิมตารางไล่จาก body ลงล่างอย่างเดียว ไม่มี token ไหน
     ใหญ่กว่า body เลย ทุกหน้าที่ต้องการตัวเลขเด่น (เวลา · ยอดเงิน · วันที่) จึงเขียน
     inline กันหมด — สองชั้นนี้ปิดช่องนั้น (.fs-1..6 ของ Bootstrap ใหญ่เกิน เป็นหัวเรื่อง) */
  --fs-2xs: 0.68rem;   /* 12px — badge จิ๋ว */
  --fs-xs:  0.72rem;   /* 13px — kicker, caption, ข้อความกำกับ */
  --fs-sm:  0.78rem;   /* 14px — หัวตาราง, ข้อความรอง */
  --fs-md:  0.85rem;   /* 15px — subtitle ของหน้า, เนื้อความรอง */
  --fs-lg:  0.9rem;    /* 16px — ข้อความ empty state */
  --fs-xl:  1.05rem;   /* 19px — ตัวเลขในแถบสัปดาห์, ชื่อในหัวการ์ด */
  --fs-2xl: 1.25rem;   /* 22px — ตัวเลขเด่นของการ์ด (เวลาเดินทาง, หัว modal) */
  --fs-3xl: 1.6rem;    /* 29px — ยอดรวมบนการ์ดสรุป (งบ · OT · น้ำมัน · ยืนยันเดินทาง) */

  /* ขนาดไอคอน material-symbols — เดิมมี 9 ค่าปนกัน (15-26px) รวบเหลือ 3 */
  --ico-sm: 18px;      /* ไอคอนในบรรทัดข้อความ */
  --ico-md: 20px;      /* ไอคอนในปุ่ม */
  --ico-lg: 24px;      /* ไอคอนหัวเรื่อง */

  /* motion — MOTION.md ระยะ 0 · ห้ามเขียน transition/animation ด้วยตัวเลขดิบใหม่
     ค่าที่ต่างกันไม่ถึง 40ms ปัดเข้าชั้นที่ใกล้ที่สุด */
  --mo-fast: 120ms;     /* กดปุ่ม · hover · dropdown */
  --mo-base: 180ms;     /* modal · toast · แทนก้อนเนื้อหา */
  --mo-slow: 260ms;     /* เปลี่ยนหน้า · แถบสัปดาห์เลื่อน · ปฏิทินเปลี่ยนเดือน */
  --mo-count: 500ms;    /* ตัวเลขนับขึ้น — ตัวเดียวที่ยาวได้ */
  --mo-pulse: 2s;       /* จังหวะที่วนไม่จบ (แถบวิ่งของเส้นขั้นที่กำลังเดินทาง) — ชั้นใหม่
                           เพราะไม่มีชั้นไหนใกล้เลย · ช้าพอที่ตาไม่ถูกดึงซ้ำๆ */
  --ease-out: cubic-bezier(.2,.8,.2,1);     /* ของที่เข้ามา */
  --ease-in-out: cubic-bezier(.4,0,.2,1);   /* ของที่ย้ายตำแหน่ง */
  --ease-in: cubic-bezier(.4,0,1,1);        /* ของที่ออกไป (สลับ shell home ↔ sidebar) */
}

/* [4] weight 300 เป็นมาตรฐาน — Bootstrap ไม่มี utility สำหรับ body weight */
body {
  font-weight: 300;
}

/* [5] ปุ่ม primary — .btn-* ของ Bootstrap ไม่ผูกกับ --bs-primary ต้อง override เอง */
.btn-primary {
  --bs-btn-bg: #327BFA;
  --bs-btn-border-color: #327BFA;
  --bs-btn-hover-bg: #2a68d1;
  --bs-btn-hover-border-color: #2a68d1;
  --bs-btn-active-bg: #2560bd;
  --bs-btn-active-border-color: #2560bd;
  --bs-btn-focus-shadow-rgb: 50, 123, 250;
}

.btn-outline-primary {
  --bs-btn-color: #327BFA;
  --bs-btn-border-color: #327BFA;
  --bs-btn-hover-bg: #327BFA;
  --bs-btn-hover-border-color: #327BFA;
  --bs-btn-active-bg: #327BFA;
  --bs-btn-active-border-color: #327BFA;
}

/* [5.1] .btn-link ของ Bootstrap ขีดเส้นใต้เสมอ — ปุ่มที่มีแต่ไอคอน (เช่น ‹ › ของแถบสัปดาห์)
   เลยมีเส้นใต้โผล่ใต้ไอคอนไปด้วย ปิดที่นี่ที่เดียวแทนไล่ใส่ text-decoration-none ทีละปุ่ม */
.btn-link {
  text-decoration: none;
}

/* [6] icon font — font-variation-settings ไม่มี utility ทดแทน */
.material-symbols-rounded {
  font-family: "Material Symbols Rounded";
  font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
  font-size: 25px;
  line-height: 1;
  flex-shrink: 0;
}

/* [7] แถบ active ยื่นชิดขอบ sidebar — Bootstrap ไม่มี pseudo-element utility */
.nav-item-active {
  position: relative;
}

.nav-item-active::before {
  content: "";
  position: absolute;
  left: -12px;              /* ชดเชย margin ให้ไปชิดขอบ sidebar พอดี */
  top: 2px;
  bottom: 2px;
  width: 5px;
  border-radius: 0 3px 3px 0;
  background: var(--bs-primary);
}

/* [8] sidebar เต็มความสูงจอ + ซ่อน scrollbar
   Bootstrap ไม่มี utility สำหรับ height:calc() และซ่อน scrollbar
   1200px = breakpoint xl ต้องตรงกับ .offcanvas-xl ใน _sidebar.html */
@media (min-width: 1200px) {
  #sidebar {
    position: sticky;
    top: 0;
    height: 100vh;
    display: flex;
    flex-direction: column;
  }
  /* min-height:0 จำเป็น ไม่งั้น flex child ไม่ยอมหดแล้ว overflow ไม่ทำงาน */
  #sidebar .offcanvas-body {
    min-height: 0;
    flex: 1 1 auto;
  }
}

/* offcanvas จอ <1200 กว้างกว่า sidebar ถาวร — "จัดการงบประมาณ" (ชั้น 2 มีลูกศร) ไม่ตัดบรรทัด
   inline width:300px ใน _sidebar.html จึงต้อง !important */
@media (max-width: 1199.98px) {
  #sidebar { width: min(320px, 88vw) !important; }
}

#sidebar .offcanvas-body {
  overflow-y: auto;
  scrollbar-width: none;         /* Firefox */
  -ms-overflow-style: none;      /* Edge เก่า */
}

#sidebar .offcanvas-body::-webkit-scrollbar {
  display: none;                 /* Chrome / Safari */
}

/* [9] ซ่อน scrollbar ของหน้าหลัก (ยังเลื่อนได้ปกติ)
   Bootstrap ไม่มี utility — และเมื่อไม่มี scrollbar ให้ชดเชย
   Bootstrap จะไม่ใส่ padding-right ตอนเปิด modal เอง = ไม่กระตุก */
html {
  scrollbar-width: none;         /* Firefox */
  -ms-overflow-style: none;      /* Edge เก่า */
}

html::-webkit-scrollbar {
  display: none;                 /* Chrome / Safari */
}

/* [9.1] modal ที่ห่อ .modal-body ด้วย <form> (ทุกใบที่บันทึกข้อมูลจริง)
   Bootstrap คุมความสูงจาก .modal-content ลงไปที่ .modal-body ตรงๆ — ฟอร์มที่คั่นกลาง
   ไม่มีขอบเขต .modal-body เลยสูงเท่าเนื้อหาทั้งก้อน แล้วโดน overflow:hidden ของ
   .modal-content ตัดท้ายทิ้ง แทนที่จะได้แถบเลื่อน (เจอที่ modal แจ้ง Telegram 3 การ์ด:
   เนื้อหา 1110px ในกล่อง 655px หายไป 455px โดยเลื่อนลงไปดูไม่ได้) */
.modal-dialog-scrollable .modal-content > form {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.modal-dialog-scrollable .modal-content > form > .modal-body {
  min-height: 0;                 /* min-height:auto ของ flex item กันไม่ให้หดลงมาเลื่อน */
}

/* [9.2] ระยะขอบบน-ล่างของ modal — คุมที่เดียว มีผลทุกใบทั้งโปรเจค
   .modal-dialog-scrollable คิด max-height จาก calc(100% - margin*2) ค่า default ของ
   Bootstrap คือ 0.5rem บนมือถือ · modal ที่เนื้อหายาวจึงกินจนเกือบเต็มจอ ไม่เหลือพื้น
   ให้เห็นว่าเป็นชั้นที่ลอยอยู่ — ห้ามไปใส่ my-3 รายใบ ค่าจะกระจายจนแก้ทีหลังไม่ไหว */
.modal {
  --bs-modal-margin: 0.7rem;
}

@media (min-width: 576px) {
  .modal { --bs-modal-margin: 2rem; }
}

/* [10] ปฏิทินจองรถ — Bootstrap ไม่มี utility สำหรับ min-height, truncate 1 บรรทัด,
   วงกลมวันนี้, และ marker ฝั่งมือถือ */
.cal-cell { min-height: 132px; }

/* ช่องวันกดได้ (role="button" → เปิดฟอร์มจอง) — เดิมไม่มีทั้ง cursor, hover, active
   ทั้งที่ "กดช่องวันแล้วจอง" คือ interaction หลักของหน้านี้ (2569-09-20)
   ⚠️ ไม่ใช้ transform — ช่องในกริดใช้เส้นขอบร่วมกับช่องข้างๆ ย่อแล้วเส้นแหว่งเห็นชัด
   ชี้กับกดใช้พื้นเดียวกัน: เดสก์ท็อปมี hover บอกอยู่แล้ว · จอสัมผัสไม่มี hover
   พื้นตอนกดจึงเป็น feedback ตัวเดียวที่มี ไม่ต้องตั้งเฉดที่สองขึ้นมาเป็นค่าใหม่ */
.cal-cell[role="button"],
.mcal-day[role="button"],
.cal-ev { cursor: pointer; }

.cal-cell[role="button"] {
  transition: background var(--mo-fast) linear;
}

@media (hover: hover) and (pointer: fine) {
  .cal-cell[role="button"]:hover { background: var(--bs-secondary-bg); }
}

.cal-cell[role="button"]:active { background: var(--bs-secondary-bg); }

.cal-ev {
  font-size: 0.68rem;
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* วันที่มีคำขอแน่นเกิน CALENDAR_BUSY — ring ด้านในแทน border จริง
   (border จริงดัน grid ของปฏิทินเคลื่อน 1.5px ทั้งแถว) */
.cal-cell.is-busy { box-shadow: inset 0 0 0 1.5px var(--bs-danger); }

/* ปฏิทินบน shell แผ่นขาว (2569-10-01) — event/ดูทั้งหมด = .fs-md (0.85rem · เดิม 0.68rem) · วันนี้ = วง primary
   นอกเดือน = พื้นสี sidebar · ชี้ช่องจองได้ = พื้นสีเมนูที่ยืนอยู่ + "+ จอง"
   ชี้วันที่ผ่านแล้ว = พื้นจางลง + "ไม่สามารถจองได้" · ใช้ทั้งจองรถและจองห้องประชุม */
.app-panel-shell .cal-ev,
.app-panel-shell .cal-more { font-size: 0.85rem; }   /* = .fs-md */
.app-panel-shell .cal-out { background: var(--app-panel-bg); }
.cal-hint { visibility: hidden; font-size: 0.9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (hover: hover) and (pointer: fine) {
  .app-panel-shell .cal-cell[role="button"]:hover { background: var(--app-active-bg); }
  .app-panel-shell .cal-cell[role="button"]:hover .cal-hint { visibility: visible; color: var(--app-active-ink); }
  .app-panel-shell .cal-cell.is-past:hover { background: color-mix(in srgb, var(--app-active-bg) 35%, transparent); }
  .app-panel-shell .cal-cell.is-past:hover .cal-hint { visibility: visible; color: var(--bs-secondary-color); }
}

/* แถบเลือกเดือน (2569-10-01) — "วันนี้" พื้นเทาไม่มีขอบ · ‹ › ลูกศรเปล่า กดได้ทั้งวง 38px */
.cal-nav-today { height: 38px; display: inline-flex; align-items: center; background: var(--bs-tertiary-bg); }
.cal-nav-arrow { width: 38px; height: 38px; border: 0; }
.cal-nav-arrow:hover { background: var(--bs-tertiary-bg); }

/* [10.6] ปฏิทินจองรถเต็มแผ่น (2569-10-01 · แบบ Google Calendar · จอ ≥768 เท่านั้น มือถือคงเดิม)
   วันนี้ ‹ › เดือน อยู่ช่องเครื่องมือของแถบบน (head_tools · _topbar.html)
   แผ่นสูงเท่าจอพอดี กริดกินที่เหลือ แถวสัปดาห์หารเท่ากัน — ช่องไม่ยืดตาม event
   (event ที่ไม่พอ JS fitCells() ซ่อนแล้วขึ้น "อีก N รายการ") · จองรถ + จองห้องประชุม */
@media (min-width: 768px) {
  .app-panel:has(.cal-fit) { height: 100vh; height: 100dvh; min-height: 0; display: flex; flex-direction: column; }
  .app-panel:has(.cal-fit) > .tb { flex: none; }
  .app-panel:has(.cal-fit) > main { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; padding-top: .75rem !important; }
  .cal-fit, .cal-fit #calBody { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .cal-fit .cal-toolbar { flex-shrink: 0; margin-bottom: .75rem !important; }
  .cal-desk { flex: 1 1 auto; min-height: 0; flex-direction: column; }
  .cal-desk .cal-card { flex: 1 1 auto; min-height: 0; display: flex; }
  .cal-desk .cal-grid { flex: 1 1 auto; min-height: 0; grid-template-columns: repeat(7, minmax(0, 1fr)); }
  .cal-desk .cal-cell { min-height: 0; overflow: hidden; padding: 4px 6px 4px; }
  .cal-desk .cal-day { flex-shrink: 0; margin-bottom: 4px; line-height: 1.2; }
  .cal-desk .cal-dow { margin: 2px 0 2px; }
  .cal-desk .cal-num { display: inline-flex; align-items: center; justify-content: center;
                       min-width: 26px; height: 26px; padding: 0 6px; border-radius: 50rem; font-size: .85rem; white-space: nowrap; }
  .cal-desk .cal-num.is-today { background: var(--bs-primary); color: #fff; font-weight: 600; }
  .cal-desk .cal-evs { flex: 1 1 auto; min-height: 0; overflow: hidden; gap: 2px; }
  .cal-desk .cal-ev { flex-shrink: 0; padding-top: .5rem !important; padding-bottom: .5rem !important; }   /* ไม่งั้นแถบหดเบียดกันแทนที่จะล้น — fitCells() วัดไม่เจอ */
  .cal-desk .cal-more { flex-shrink: 0; padding: .5rem 8px; line-height: 1.3; border-radius: 4px; }
  .cal-desk .cal-more:hover { background: var(--bs-tertiary-bg); }
  /* ชี้ช่อง = พื้นสี sidebar (จางกว่าสีเมนูที่ยืนอยู่) */
  .app-panel-shell .cal-desk .cal-cell[role="button"]:hover,
  .app-panel-shell .cal-desk .cal-cell.is-past:hover { background: var(--app-panel-bg); }
  /* "+ จอง" / "ไม่สามารถจองได้" มุมขวาล่าง — ทับแถบ event ได้ จึงมีพื้นสีเดียวกับช่องตอนชี้ */
  .cal-desk .cal-hint { position: absolute; right: 8px; bottom: 6px; max-width: calc(100% - 16px); font-size: .78rem;
                        padding: 0 4px; border-radius: 4px; background: var(--app-panel-bg); }
}
/* แถวเครื่องมือของปฏิทินไม่มีท่าเข้าของตัวเอง (cal-head-in ถอด 2569-10-03) — เบลอ + ทยอยเข้า 4 ก้อนทุกครั้ง
   ที่เข้าหน้า อ่านเป็นกระตุก · หน้าที่เปิดถี่ให้สลับทันทีเหมือนหน้าอื่น (ท่าสลับ shell อยู่ใน _base.html) */
@media (min-width: 992px) {
  .app-panel:has(.cal-fit) > main { padding-bottom: 1rem !important; }
}
@media (min-width: 1200px) {
  .app-panel:has(.cal-fit) { height: calc(100vh - 24px); height: calc(100dvh - 24px); }
}

.cal-more {
  font-size: 0.68rem;
  background: none;
  border: 0;
  padding: 2px 4px;
  text-align: left;
}


/* ปฏิทินฝั่งมือถือ */
.mcal-day { aspect-ratio: 1; }
.mcal-num { width: 40px; height: 44px; }
.mcal-dot { width: 5px; height: 5px; border-radius: 50%; }
.mcal-bar { width: 16px; height: 3px; border-radius: 2px; }

.mcal-day.is-today .mcal-num {
  background: #000;
  color: #fff;
  border-radius: 10px;
}

.mcal-day.is-sel .mcal-num {
  border: 1.5px solid #6E6E6E;
  border-radius: 10px;
}

.mcal-day.is-busy .mcal-num {
  border: 1.5px solid var(--bs-danger);
  border-radius: 10px;
}

.mcal-day.is-today .mcal-bar,
.mcal-day.is-today .mcal-dot { background: #fff !important; }

/* [10.1] ปฏิทิน — ปรับตามรีวิว */
.popover.cal-popover { max-width: 420px; }

/* มือถือ: เส้นคร่อมหัวสัปดาห์ (บางกว่า border ปกติ) */
.mcal-head {
  border-top: 0.5px solid var(--bs-border-color);
  border-bottom: 0.5px solid var(--bs-border-color);
}

/* จองพื้นที่ marker ไว้เสมอ ตัวเลขทุกช่องจึงอยู่ระดับเดียวกัน */
.mcal-mark {
  height: 9px;
  margin-top: 2px;
}

/* [10.2] ฟอร์มจองบนจอเล็ก — ฐาน 18px ทำให้ข้อความยาวล้นช่อง จึงย่อลง
   **16px คือเพดานล่าง ห้ามลดกว่านี้** — WebKit (Safari iOS) zoom หน้าเข้าเองเมื่อ focus
   ช่องที่เล็กกว่า 16px แล้ว **ไม่ย่อกลับ** ปิด modal มาหน้าก็ค้างอยู่ที่ zoom นั้น
   (เคยเป็น 0.82rem = 14.76px จึง zoom ทุกครั้งที่กรอกฟอร์มจอง)
   นี่เป็นเหตุผลเดียวในโปรเจคที่ขนาดตัวอักษรเขียนเป็น px ไม่ใช่ token — เพดานของเบราว์เซอร์
   ไม่ใช่ค่าที่ดีไซน์เลือก · ช่องกรอกของหน้าอื่นเป็น 18px อยู่แล้วจึงไม่มีปัญหานี้ */
@media (max-width: 575.98px) {
  #bookModal .form-control,
  #bookModal .form-select {
    font-size: 16px;
  }
  #bookModal .input-group-text {
    padding-left: 0.5rem;
    padding-right: 0.5rem;
  }
}

/* [10.3] สีแถบ event ตามสถานะ — ใช้ class แทน inline style
   เพราะ Bootstrap sanitizer ตัด style ออกจากเนื้อหา popover (class ผ่านได้) */
/* ขั้นมาตรฐาน --st-* (2569-10-15) — ตรงกับ mock.STAGE["booking"] */
.ev-approved, .ev-merged { background: var(--st-ok-soft);   color: var(--st-ok-ink); }
.ev-completed            { background: var(--st-done-soft); color: var(--st-done-ink); }
.ev-awaiting_approval    { background: var(--st-wait-soft); color: var(--st-wait-ink); }
.ev-rejected             { background: var(--st-bad-soft);  color: var(--st-bad-ink); }
.ev-cancelled            { background: var(--st-info-soft); color: var(--st-info-ink); }

/* ห้องประชุม — สีแยกห้องแทนสีสถานะ · ชื่อสีตรงกับ rooms.PALETTE (ผู้ดูแลเลือกสีที่หน้าจัดการห้อง) */
.ev-room-orange { background: #FCEFDD; color: #854F0B; }
.ev-room-blue   { background: #E3EEFD; color: #0A44A1; }
.ev-room-green  { background: #E4F5E9; color: #1E6B34; }
.ev-room-purple { background: #EEEAFB; color: #4B3A9E; }
.ev-room-pink   { background: #FBE8F0; color: #8E2752; }
.ev-room-teal   { background: #E0F4F2; color: #0F5F58; }

/* [10.3.1] แถบ event ของปฏิทินเต็มแผ่น (จองรถ + ห้องประชุม · 2569-10-01 · แบบ Google)
   พื้นเข้มตัวขาว ไม่มีเส้น · รถ: สีขั้นมาตรฐาน · รออนุมัติ = พื้นขาวขอบส้ม (ทรงเดียวกับห้องรออนุมัติ) · ห้อง: สีเข้มของห้อง
   popover "อีก N รายการ" (.cal-pop-fit) ขนาด/สีเท่าในช่อง — อยู่นอก .app-panel-shell สี sidebar จึงใส่ค่าสำรองเอง */
:is(.cal-desk, .cal-pop-fit) .cal-ev { color: #fff; box-shadow: none; border: 0; font-size: .85rem; }
.cal-pop-fit .cal-ev { padding-top: .5rem !important; padding-bottom: .5rem !important; }
:is(.cal-desk, .cal-pop-fit) .cal-ev:is(.ev-approved, .ev-merged) { background: var(--st-ok); }
:is(.cal-desk, .cal-pop-fit) .cal-ev.ev-completed { background: var(--st-done); }
:is(.cal-desk, .cal-pop-fit) .cal-ev.ev-awaiting_approval { background: var(--st-wait); }
:is(.cal-desk, .cal-pop-fit) .cal-ev.ev-rejected { background: var(--st-bad); }
/* ไม่อนุมัติบนปฏิทินจองรถ (ev_tone → cancelled) = ทรงเดียวกับรออนุมัติแต่เทา — ไม่แดง ตามที่ตกลง 2569-10-09 */
:is(.cal-desk, .cal-pop-fit) .cal-ev.ev-cancelled { background: #fff; color: var(--st-info-ink); box-shadow: inset 0 0 0 1.5px var(--bs-border-color); }
:is(.cal-desk, .cal-pop-fit) .cal-ev.ev-room-orange { background: #854F0B; }
:is(.cal-desk, .cal-pop-fit) .cal-ev.ev-room-blue   { background: #0A44A1; }
:is(.cal-desk, .cal-pop-fit) .cal-ev.ev-room-green  { background: #1E6B34; }
:is(.cal-desk, .cal-pop-fit) .cal-ev.ev-room-purple { background: #4B3A9E; }
:is(.cal-desk, .cal-pop-fit) .cal-ev.ev-room-pink   { background: #8E2752; }
:is(.cal-desk, .cal-pop-fit) .cal-ev.ev-room-teal   { background: #0F5F58; }
/* รออนุมัติ (ห้อง 2569-10-08 · รถ 2569-10-15) — พื้นขาว ขอบส้ม · อ่านออกว่ายังไม่ยืนยัน */
:is(.cal-desk, .cal-pop-fit) .cal-ev:is(.is-pending, .ev-pending) { background: #fff; color: var(--st-wait-ink); box-shadow: inset 0 0 0 1.5px var(--st-wait); }
.popover.cal-pop-fit { width: 340px; max-width: calc(100vw - 32px); }
.popover.cal-pop-fit .popover-body { padding: .75rem; }

/* .ev-pending = รออนุมัติ ไม่ใส่สีพื้น ตามที่ตกลงไว้ (2569-10-01) — เส้นบางสีรอ… แทน (2569-10-15)
   ใช้ inset shadow ไม่ใช่ border จะได้สูงเท่าแถบสถานะอื่น */
.ev-pending { box-shadow: inset 0 0 0 1px var(--st-wait); color: var(--st-wait-ink); }

/* [10.5] ปฏิทินเป็นการ์ดขาว + shadow-sm (2569-09-20)
   พื้นขาวมาจากกฎกลาง [23] (.border.rounded-3 ใน main) — ที่นี่แก้แค่เส้นซ้ำ:
   ช่องริมขวาและแถวล่างมี border ของตัวเองอยู่แล้ว ทับกรอบการ์ดเป็นเส้นคู่ */
.cal-card > div > :nth-child(7n) { border-right: 0; }
.cal-card > div:last-child > :nth-last-child(-n+7) { border-bottom: 0; }

/* หัววันในการ์ดมือถือ — ขอบบนของการ์ดทำหน้าที่แทนเส้นบนแล้ว */
.cal-card .mcal-head { border-top: 0; }

/* [10.4] ขอบรอบ toast (แจ้งเตือนสั้นมุมขวาบน) ย้อมตามชนิด — เดิมมีแค่ไอคอนสีเล็กๆ
   ตัวการ์ด (bg-light-subtle + border เทาเฉยๆ) กลืนกับพื้นขาว สีตรงกับ text-success/warning/danger
   ที่ไอคอนใช้อยู่แล้ว (toast() ใน _base.html เติม class ให้ตาม kind) */
.toast-ok   { border-color: var(--bs-success) !important; }
.toast-warn { border-color: var(--bs-warning) !important; }
.toast-bad  { border-color: var(--bs-danger) !important; }

/* [11] min-width:0 — Bootstrap 5 ไม่มี utility ตัวนี้ (มีแต่ min-vw-*)
   จำเป็นกับ flex item ที่ต้องยอมหดให้ text-truncate ทำงาน ไม่งั้นเนื้อหาดันของข้างๆ ทะลุออกนอกกรอบ */
.min-w-0 { min-width: 0; }

/* [12] หน้า admin — Bootstrap ไม่มี utility สำหรับขนาดคงที่/สีแบรนด์/เส้นประ */

/* แถบสัปดาห์ — ชื่อวันกับตัวเลขอยู่ในกล่องเดียวกัน */
.wk-num {
  width: 100%;
  max-width: 52px;
  padding: 6px 0;
  border-radius: 12px;
}
.wk-dow { line-height: 1; }
.wk-mark { height: 9px; margin-top: 3px; }
/* จุด = มีงาน 1 รายการ · ขีด = มีหลายรายการ
   สีเคยเขียน inline เป็น #9CA3AF ซึ่งได้คอนทราสต์แค่ 2.6:1 — ไม่ผ่าน WCAG 1.4.11
   (3:1 สำหรับองค์ประกอบที่สื่อความหมาย ไม่ใช่ของประดับ) จึงย้ายมาคุมที่นี่ */
.wk-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--bs-secondary-color); }
.wk-bar { width: 16px; height: 3px; border-radius: 2px; background: var(--bs-body-color); }

.wk-day.is-selected .wk-num { background: #000; color: #fff; }
.wk-day.is-selected .wk-dot,
.wk-day.is-selected .wk-bar { background: #fff !important; }
/* week_strip (2569-10-03) — ไม่มีกรอบ พื้นสีเดียวกับ sidebar แผ่นขาว
   .wk-bleed = ยื่นชนขอบจอ กิน p-3 ของ <main> ทั้งซ้าย/ขวา/บน → ต่อกับแถบหัวเป็นผืนเดียว */
.wk-strip { padding: 4px 8px 10px; background: var(--app-panel-bg, var(--bs-tertiary-bg)); }
.wk-bleed { margin: -1rem -1rem 1rem; }

/* ไฮไลต์ hover เฉพาะเครื่องที่ชี้ได้จริง (2569-09-20) — จอสัมผัสแตะแล้ว :hover ค้าง
   พื้นเทาจึงค้างหลังกด อ่านว่า "แถวนี้ถูกเลือก" ซึ่งชนกับ .is-checked ที่แปลว่าเลือกจริง */
@media (hover: hover) and (pointer: fine) {
  .job-row:hover { background: var(--bs-secondary-bg); }
}

/* [12.1] หน้ารถและคนขับ */

/* แถบวงเงินบัตรน้ำมัน */
.fleet-bar {
  height: 5px;
  border-radius: 3px;
  background: var(--bs-secondary-bg);
  overflow: hidden;
}
.fleet-bar > span {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: #15803D;
}
.fleet-bar > span.is-warn { background: #C2410C; }
.fleet-bar > span.is-full { background: #A32D2D; }

/* ช่องวันในแถบ "งานในสัปดาห์"
   4 สถานะแยกกันด้วยสี + รูปร่าง — เทากับเทาเข้มต่างกันน้อยเกินกว่าจะพึ่งสีอย่างเดียว
   is-idle = ขีดฆ่า (มีงานแต่ไม่ได้ไป) · is-ot = จุดทึบมุมขวาบน (ได้ OT) */
.dw-cell {
  position: relative;
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  border: 0;
  border-radius: 8px;
  font-size: 0.74rem;
  line-height: 30px;
  padding: 0;
  text-align: center;
  background: var(--bs-secondary-bg);
  color: var(--bs-secondary-color);
}
.dw-cell.is-idle {
  background: #D3D5D9;
  color: #3A3A3A;
  text-decoration: line-through;
}
.dw-cell.is-drive {
  background: #DCF5E6;
  color: #0F6E56;
}
.dw-cell.is-ot {
  background: #FCEFDD;
  color: #C2410C;
}
.dw-cell.is-ot::after {
  content: "";
  position: absolute;
  top: 4px;
  right: 4px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: #C2410C;
}
.dw-cell:focus-visible { outline: 2px solid var(--bs-primary); outline-offset: 1px; }

/* ตัวอย่างสีใน popover คำอธิบาย — ไม่มีตัวอักษรข้างใน เลยย่อลงได้ */
.dw-swatch {
  width: 22px;
  height: 22px;
  flex: 0 0 22px;
  border-radius: 6px;
}

/* ช่องว่างไม่มีตัวอักษรให้ขีดฆ่า — วาดเส้นเองเพื่อให้ตัวอย่างสื่อเท่าช่องจริง */
.dw-swatch.is-idle::before {
  content: "";
  position: absolute;
  left: 4px;
  right: 4px;
  top: 50%;
  height: 1px;
  background: #3A3A3A;
}

/* แท็บ — เส้นใต้จางยาวเต็มความกว้าง เส้นเข้มเฉพาะแท็บที่เลือก */
.nav-underline-full {
  border-bottom: 1px solid var(--bs-border-color);
  --bs-nav-underline-border-width: 2px;
}
.nav-underline-full .nav-link { margin-bottom: -1px; }

/* เส้นคั่นแบบประ */
.border-dashed-top { border-top: 1px dashed var(--bs-border-color); }

/* ปุ่มสีแบรนด์ */
.btn-line {
  --bs-btn-bg: #04A94A;
  --bs-btn-border-color: #04A94A;
  --bs-btn-color: #fff;
  --bs-btn-hover-bg: #038A3C;
  --bs-btn-hover-border-color: #038A3C;
  --bs-btn-hover-color: #fff;
  --bs-btn-disabled-bg: #04A94A;
  --bs-btn-disabled-border-color: #04A94A;
  --bs-btn-disabled-color: #fff;
}

@media (max-width: 575.98px) {
  .wk-num { max-width: 44px; }
}

/* [12.1] แถว/การ์ดงานกดเลือกได้ทั้งก้อน */
.job-row,
.job-card { cursor: pointer; }
@media (hover: hover) and (pointer: fine) {
  .job-card:hover { background: var(--bs-secondary-bg); }
}
.job-row.is-checked,
.job-card.is-checked { background: rgba(50, 123, 250, 0.06); }
/* จบงานแล้ว = การ์ดปิด กดไม่ได้ (หน้างานขับรถ · 2569-10-08) */
.job-card.is-done { cursor: default; background: var(--bs-tertiary-bg) !important; }
/* หน้าอนุมัติรถเป็นตาราง rgt แล้ว — td ทาพื้นขาวทึบเอง (คอลัมน์ปักหมุด) พื้นของแถวที่เลือกจึงต้องลงที่ td */
.rgt-t tr.job-row.is-checked td { background: #e8f0fe; }

/* ปุ่ม/ลิงก์ในแถว ต้องไม่ไปโดน toggle checkbox */
.job-row .btn,
.job-card .btn,
.job-row [data-bs-toggle],
.job-card [data-bs-toggle] { cursor: pointer; }

/* [12.2] แถบที่เลื่อนแนวนอน ต้องไม่ดักการเลื่อนหน้าแนวตั้ง
   CSS spec: ถ้าแกนหนึ่งเป็น auto อีกแกนที่ visible จะกลายเป็น auto เอง — ต้องปิดชัดเจน
   ไม่งั้นก้อนที่ล้นแนวตั้งไม่กี่ px (focus ring · ขอบล่างของการ์ดใบท้าย) กินการปัดนิ้ว
   ของหน้าไปเอง — บนมือถือคือปัดแล้วหน้าไม่ขยับ ต้องเลื่อนนิ้วออกนอกแถบก่อน

   ครอบทุกก้อนที่ตั้งใจให้เลื่อนเฉพาะแกน x: แท็บระดับหน้า · แท็บใน modal ·
   แถบเครื่องมือ · ตาราง · ก้อนที่ห่อด้วย utility ตรงๆ (ตารางงบ/อัตรา OT)
   ปลอดภัยเพราะ dropdown/popover ในก้อนพวกนี้ลอยพ้น overflow อยู่แล้ว —
   pick() กับ kebab() ใช้ popper strategy:fixed · popover หน้ารถและคนขับใช้ container:body */
.nav-underline,
.nav-underline-full,
.table-responsive,
.overflow-x-auto {
  overflow-y: hidden;
}

/* [12.3] ทริปย่อยของงานรวม — เยื้องให้ชิดตรงกับชื่อหัวรายการ
   (ข้ามคอลัมน์ checkbox + ไอคอน ซึ่งกว้างคงที่) */
.trips-indent { padding-left: calc(4rem + 5px); }

/* @media (max-width: 767.98px) {
  .trips-indent { padding-left: -6.75rem; }
} */

/* [12.4] segmented เลือกประเภทงบ — Bootstrap btn-check ทำให้ปุ่มที่เลือก "เข้มขึ้น"
   แต่แบบที่ต้องการคือรางเทา + อันที่เลือกเป็นพื้นขาวยกนูน (ไม่มี component ใน Bootstrap) */
.seg-btn {
  --bs-btn-bg: transparent;
  --bs-btn-border-color: transparent;
  --bs-btn-color: var(--bs-secondary-color);
  --bs-btn-hover-bg: transparent;
  --bs-btn-hover-border-color: transparent;
  --bs-btn-hover-color: var(--bs-body-color);
  --bs-btn-active-bg: #fff;
  --bs-btn-active-border-color: transparent;
  --bs-btn-active-color: var(--bs-body-color);
  --bs-btn-focus-shadow-rgb: 0, 0, 0;
  font-size: 0.82rem;
  padding-left: 0.35rem;
  padding-right: 0.35rem;
}

.btn-check:checked + .seg-btn {
  background: #fff;
  color: var(--bs-body-color);
  font-weight: 500;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
}

/* [12.5] caret ของ .dropdown-toggle เป็นสามเหลี่ยมทึบ และ Bootstrap ไม่มี utility ปิด
   แบบที่ต้องการใช้ไอคอน expand_more แทน */
.no-caret::after { display: none; }

/* [13] chevron เมนูย่อย sidebar (เช่น "จัดการรถ") หมุนตาม aria-expanded ของปุ่ม
   Bootstrap ไม่มี utility ผูก transform กับสถานะ collapse */
.sidebar-chevron {
  transition: transform var(--mo-base) var(--ease-in-out);
}
[aria-expanded="true"] > .sidebar-chevron {
  transform: rotate(180deg);
}

/* [12.6] กรอบประแบบ dropzone แนบภาพเลขไมล์ — Bootstrap มีแต่ border ทึบ ไม่มี utility เส้นประ */
.border-dashed {
  border: 1px dashed var(--bs-border-color);
}

/* [12.7] ลูกศรของหัวการ์ดงานคนขับ กางแล้วให้ชี้ขึ้น — Bootstrap collapse ไม่หมุนไอคอนให้ */
.chev {
  transition: transform var(--mo-base) var(--ease-in-out);
}
[aria-expanded="true"] .chev {
  transform: rotate(180deg);
}

/* [14] คุมความกว้างเนื้อหาไม่ให้ยืดเกิน 1400 บนจอกว้าง
   Bootstrap มีแต่ .container-xxl ที่ได้ max 1400 ไม่ได้ (ได้ 1320) และค่านี้ hardcode
   ใน media query แก้ได้ทาง Sass เท่านั้น — เราใช้ CDN จึงต้องคุมเอง
   margin auto ทำงานคู่กับ flex-grow-1: โตจนชน max-width แล้วที่เหลือถูกแบ่งซ้าย-ขวาเท่ากัน */
.app-main {
  max-width: 1400px;
}

/* [15] หน้าบันทึกเลขไมล์ — Bootstrap ไม่มี utility สำหรับสีเตือน 2 ระดับนี้
   (text-warning ของ Bootstrap เป็นเหลืองสด อ่านบนพื้นขาวไม่ออก) และไม่มี tabular-nums */
.odo-warn { color: #854F0B; }
.odo-bad { color: #A32D2D; }

/* เลขไมล์ต้องเรียงหลักตรงกันทุกแถว */
.odo-num { font-variant-numeric: tabular-nums; }

/* แถวผิดปกติ — แถบซ้ายแดง ไม่ย้อมพื้นทั้งแถว (ตารางแน่นอยู่แล้ว พื้นสีจะกลบลำดับสายตา) */
.odo-row.is-bad > td:first-child { box-shadow: inset 3px 0 0 #A32D2D; }

/* [15] ตรึงคอลัมน์ชื่องบไว้ซ้ายตอนเลื่อนตารางภาพรวม 16 คอลัมน์แนวนอน
   Bootstrap ไม่มี utility สำหรับ position:sticky แนวนอนใน <td> */
.budget-stick {
  position: sticky;
  left: 0;
  z-index: 1;
}

/* [16] ความสูงแถวของตารางตระกูลนี้ — อิงแถวที่มีปุ่มวงกลม 32px (32 + padding 8+8 + เส้น 1 = 49 → 51 กันเผื่อ)
   ใส่ที่ td เพราะ height บน tr ไม่มีผลเมื่อ table-layout เป็น auto */
.budget-table td {
  height: 51px;
}

/* [16.1] .budget-grid — ชั้นบนของ .budget-table · ตอนนี้เหลือที่ตารางสรุปสิทธิ์ (manage/report.html)
   ช่องโปร่ง เส้นคั่นคอลัมน์ แถบสลับสีขาว/เทา (2569-09-15)

   ห้ามเลื่อนไปผูกกับ .budget-table ตรงๆ — ตารางภาพรวมของหน้าค่าน้ำมันมีแถว
   .table-secondary ที่คิดสีผ่านตัวแปรของ Bootstrap พื้นทึบข้างล่างนี้จะย้อมทับหมด

   ทุกช่องต้องมี**พื้นทึบ** ไม่งั้นคอลัมน์ที่ตรึงซ้าย (.budget-stick) โปร่ง
   แล้วตัวเลขของคอลัมน์อื่นวิ่งทะลุออกมาตอนเลื่อนแนวนอน
   min-width ที่ช่องเป็นตัวกันตารางถูกบีบ — 13-16 คอลัมน์เดือนจะดันความกว้างเอง
   แล้วกล่องครอบ (overflow-x-auto) เลื่อนแทน ไม่ใช่หดตัวเลขให้ชนเส้น */
.budget-grid > :not(caption) > * > * {
  padding: 0.7rem 0.85rem;
  background: var(--bs-body-bg);
  min-width: 4.2rem;
}

/* คอลัมน์ชื่องบยาวกว่าช่องอื่น — ตั้งพื้นไว้ให้พออ่านชื่อกองเต็มโดยไม่ตัดบรรทัด */
.budget-grid .budget-stick {
  min-width: 11rem;
}

/* หัวตารางห้ามตัดบรรทัด — "ประเภทงบ" / "จำนวนเงิน" ตกบรรทัดแล้วแถวหัวสูงกว่าที่ออกแบบ
   และคอลัมน์ข้างล่างดูเบียดทั้งที่ตัวเลขสั้น · ยาวเกินจอให้กล่องเลื่อนแนวนอนแทน */
.budget-grid th {
  white-space: nowrap;
}

/* ช่องโปร่งขึ้นแล้ว แถวจึงสูงกว่า .budget-table ปกติ */
.budget-grid td {
  height: 58px;
}

/* เส้นคั่นคอลัมน์ — ใส่ทางซ้ายของทุกช่องยกเว้นช่องแรกของแถว */
.budget-grid > :not(caption) > * > * + * {
  border-left: 1px solid var(--bs-border-color);
}

/* แถบสลับสี — แถวคู่เป็นเทา */
.budget-grid > tbody > tr:nth-of-type(even) > * {
  background: var(--bs-secondary-bg);
}

/* แถวกดเลือกได้ทั้งแถว (เหมือน .job-row ของหน้าอนุมัติรถ) */
.odo-row { cursor: pointer; }

/* เฉพาะเครื่องที่ชี้ได้จริง (2569-09-20) — เหมือน .job-row/.job-card
   จอสัมผัสแตะแล้วพื้นเทาค้าง ชนกับ .is-checked ข้างล่างที่แปลว่าติ๊กเลือกจริง */
@media (hover: hover) and (pointer: fine) {
  .odo-row:hover > td { background: var(--bs-secondary-bg); }
}

.odo-row.is-checked > td { background: #f0f6ff; }   /* ทึบ — คอลัมน์ปักหมุด sticky ต้องบังของที่เลื่อนผ่าน */

/* [17] หน้าค่าล่วงเวลา (OT) — Bootstrap ไม่มี utility สำหรับแถบเส้นทางใน popup
   และไม่มีอะไรทดแทน "กระดาษใบเสร็จ" ที่ต้องคุมขนาด/เส้นตารางเองทั้งหมด */

/* ใบจ่ายจริงบนจอเป็นฟอร์ม (2569-10-01) — กระดาษขึ้นเฉพาะตอนพิมพ์ */
.ot-print { display: none; }

/* กระดาษใบเสร็จ — สัดส่วน A4 ย่อ ตัวหนังสือเล็กกว่าหน้าจอปกติทั้งใบ */
.ot-paper {
  background: #fff;
  border: 1px solid var(--bs-border-color);
  border-radius: 10px;
  padding: 20px 18px;
  font-size: 0.7rem;
  line-height: 1.7;
}

.ot-paper-title {
  text-align: center;
  font-weight: 600;
  font-size: 0.9rem;
  margin-bottom: 12px;
}

/* หัวใบเสร็จ — 3 คอลัมน์ตามฟอร์มกระดาษที่ใช้จริง ไม่มีเส้นใต้ค่า
   คอลัมน์แรกกันที่ให้ป้ายกว้างเท่ากันทุกแถว ค่าจึงเรียงตรงกัน
   ป้ายที่ยาวเกิน (บัตรประจำตัวประชาชนเลข) ดันค่าของตัวเองไปเอง */
.ot-paper-head {
  display: grid;
  grid-template-columns: 42% 1fr auto;
  column-gap: 10px;
  row-gap: 6px;
  margin-bottom: 10px;
}
.ot-paper-head .pf {
  display: flex;
  gap: 6px;
  min-width: 0;
}
.ot-paper-head .pf > b {
  font-weight: 600;
  white-space: nowrap;
}
.ot-paper-head .pf > span {
  min-width: 0;
  overflow-wrap: anywhere;
}
.ot-paper-head .pf-key > b { min-width: 108px; }
.ot-paper-head .pf-full { grid-column: 1 / -1; }
.ot-paper-head .pf-2 { grid-column: 2 / -1; }
.ot-paper-head .pf-end { justify-self: end; }

/* บรรทัดหัวใบงาน: ป้ายตัวหนา + ค่าที่ขีดเส้นใต้แบบฟอร์มกระดาษ */
.ot-paper-field {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
}
.ot-paper-field > b { font-weight: 600; }
.ot-paper-field > span {
  flex: 1 1 60px;
  min-width: 0;
  border-bottom: 1px dotted var(--bs-border-color);
  overflow-wrap: anywhere;
}

.ot-paper-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}
.ot-paper-table th,
.ot-paper-table td {
  border: 1px solid #000;
  padding: 3px 6px;
  vertical-align: top;
  overflow-wrap: anywhere;
}
.ot-paper-table th {
  text-align: center;
  font-weight: 600;
}
/* ทุกแถวบรรทัดเดียว (2569-10-24) — ไม่พอ JS ย่อตัวหนังสือเฉพาะช่องนั้นตอนพิมพ์ (fitPaper ใน vehicle_ot/index.html)
   .is-auto = กว้างตามของในช่อง (ใบงาน) · .is-measure = กางกระดาษนอกจอกว้างเท่า A4 ขอบ 10 มม. ไว้วัด */
.ot-paper-table.is-auto { table-layout: auto; }
.ot-paper-table.is-1line tbody td { white-space: nowrap; overflow-wrap: normal; overflow: hidden; }
.ot-print.is-measure {
  display: block !important;
  position: absolute;
  left: -10000px;
  top: 0;
  width: 190mm;
  visibility: hidden;
}
.ot-print.is-measure .ot-paper,
.ot-print.is-measure .ot-paper[hidden] { display: block !important; border: 0; padding: 0; }
@page otpaper { size: A4; margin: 10mm; }

/* สำเนาบัตรตัวจริงบนใบเสร็จ — กว้างเต็มใบ สูงตามสัดส่วนรูป
   เส้นขอบบางไว้ให้เห็นกรอบบัตรตอนรูปพื้นขาว */
.ot-paper-idcard-img {
  display: block;
  width: 46%;
  max-width: 240px;
  border: 1px solid var(--bs-border-color);
  border-radius: 6px;
}

/* พิมพ์ = เหลือเฉพาะกระดาษ ไม่ต้องทำหน้าพิมพ์แยก */
@media print {
  #sidebar,
  header,
  .app-main > *:not(.row):not(#otBody),
  #otBody > *:not(.row):not(.ot-print) { display: none !important; }   /* หน้า OT แบบ rgt ห่อทุกอย่างใน #otBody (2569-10-01) */
  .ot-paper { border: 0; border-radius: 0; padding: 0; }
  /* พิมพ์ทั้งชุด = กางทุกใบพร้อมกัน ต้องขึ้นหน้าใหม่ทุกใบ ไม่งั้นต่อกันเป็นพรืด
     ใบสุดท้ายไม่ต้องขึ้นหน้า ไม่งั้นได้กระดาษเปล่าท้ายชุด */
  .ot-paper + .ot-paper { break-before: page; page-break-before: always; }
  .ot-print { display: block !important; page: otpaper; }
}

/* [17] utility ขนาดตัวอักษรรอง — Bootstrap มีแต่ .fs-1..6 ซึ่งเป็นขนาดหัวเรื่อง
   ไม่มีชั้นเล็กกว่า body ให้ใช้ ทั้งระบบเรียกผ่าน class เหล่านี้แทน style="font-size:" */
.fs-2xs { font-size: var(--fs-2xs); }
.fs-xs  { font-size: var(--fs-xs); }
.fs-sm  { font-size: var(--fs-sm); }
.fs-md  { font-size: var(--fs-md); }
.fs-lg  { font-size: var(--fs-lg); }
.fs-xl  { font-size: var(--fs-xl); }
.fs-2xl { font-size: var(--fs-2xl); }
.fs-3xl { font-size: var(--fs-3xl); }

/* [18] ขนาดไอคอน — material-symbols คุมด้วย font-size จึงต้องมี utility คู่กัน */
.ico-sm { font-size: var(--ico-sm); }
.ico-md { font-size: var(--ico-md); }
.ico-lg { font-size: var(--ico-lg); }

/* [19] หัวตาราง — เดิม 17 ตารางเขียน inline ปนกัน 0.78 กับ 0.8 rem
   รวบเป็นค่าเดียวที่นี่ ใช้ที่ <tr> ใน <thead> */
.table-head {
  color: var(--bs-secondary-color);
  font-size: var(--fs-sm);
}

/* [20] หน้า login แบบหน้าลงชื่อเข้าใช้ของ Google (2569-10-03) — เต็มจอ ไม่มี header/sidebar
   สีชุดเดียวกับหน้าแรก [41] · ช่องกรอกชื่อลอยบนกรอบ (Bootstrap form-floating ลอยในช่อง ไม่ใช่บนเส้น)
   จอ ≥768 การ์ดสองเสา หัว | ฟอร์ม · มือถือแผ่นขาวเต็มจอ ไม่มีการ์ดลอย */
.lg-wrap {
  --lg-ink: #202124; --lg-mut: #5F6368; --lg-line: #DADCE0; --lg-blue: #1A73E8;
  min-height: 100vh; min-height: 100dvh;   /* dvh = จอที่เห็นจริง (มือถือ vh รวมแถบที่อยู่ = สูงเกินจอ ต้องเลื่อน) */
  display: flex; align-items: center; justify-content: center;
  padding: 24px 16px; background: rgb(247, 249, 252); color: var(--lg-ink); font-weight: 400;
}
.lg-box { width: 100%; max-width: 1000px; }
.lg-card { background: #fff; border-radius: 28px; padding: 36px 40px 40px;
           display: grid; grid-template-columns: 1fr 1fr; gap: 24px 48px; }
.lg-logo { font-size: 1.25rem; font-weight: 500; color: var(--lg-ink); text-decoration: none; }
.lg-logo span { color: var(--lg-blue); }
.lg-title { font-size: 2rem; font-weight: 400; margin: 24px 0 12px; }
.lg-sub { font-size: .9rem; color: var(--lg-mut); margin: 0; }
.lg-body { padding-top: 56px; }

.lg-field { position: relative; margin-bottom: 20px; }
.lg-field input { width: 100%; height: 56px; padding: 0 15px; font-size: 1rem; color: var(--lg-ink);
  border: 1px solid var(--lg-line); border-radius: 6px; background: #fff; outline: 0; }
.lg-field input:focus { border: 2px solid var(--lg-blue); padding: 0 14px; }
.lg-field label { position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  padding: 0 4px; background: #fff; color: var(--lg-mut); font-size: 1rem; pointer-events: none;
  transition: top var(--mo-fast) var(--ease-out), font-size var(--mo-fast) var(--ease-out); }
.lg-field input:focus + label,
.lg-field input:not(:placeholder-shown) + label { top: 0; font-size: .72rem; }
.lg-field input:focus + label { color: var(--lg-blue); }

.lg-check { display: inline-flex; align-items: center; gap: 10px; font-size: .85rem; cursor: pointer; }
.lg-check input { width: 18px; height: 18px; accent-color: var(--lg-blue); }
.lg-act { display: flex; align-items: center; gap: 16px; margin-top: 36px; }
.lg-link { color: var(--lg-blue); font-size: .85rem; font-weight: 500; text-decoration: none; }
.lg-link:hover { text-decoration: underline; }
.lg-btn { margin-left: auto; border: 0; border-radius: 999px; padding: 0 24px; height: 44px;
  background: var(--lg-blue); color: #fff; font-size: .9rem; font-weight: 500; }
.lg-btn:hover { background: #1765CC; box-shadow: 0 1px 3px rgba(60, 64, 67, .3); }
.lg-btn:focus-visible { outline: 2px solid var(--lg-blue); outline-offset: 2px; }

.lg-alert { display: flex; gap: 8px; align-items: flex-start; font-size: .85rem; margin-bottom: 20px;
  padding: 10px 14px; border-radius: 8px; background: #E8F0FE; color: #174EA6; }
.lg-alert.is-err { background: #FCE8E6; color: #C5221F; }

.lg-dev { margin-top: 16px; padding: 0 8px; }
.lg-dev-t { font-size: .72rem; color: var(--lg-mut); margin-bottom: 8px; }
.lg-chip { font-size: .72rem; color: var(--lg-ink); text-decoration: none; background: #fff;
  border: 1px solid var(--lg-line); border-radius: 999px; padding: 4px 12px; }
.lg-chip span { color: var(--lg-mut); }
.lg-chip:hover { background: #F1F3F4; }

@media (max-width: 767.98px) {
  .lg-wrap { align-items: stretch; padding: 0; background: #fff; }
  .lg-card { grid-template-columns: 1fr; border-radius: 0; padding: 32px 24px 24px; gap: 0; }
  .lg-title { font-size: 1.6rem; margin-top: 20px; }
  .lg-body { padding-top: 32px; }
  .lg-dev { padding: 0 24px 24px; }
}
/* หน้ายืนยันการใช้งบจากลิงก์ LINE (approver/link.html) — การ์ดเดียวคอลัมน์เดียว */
.lg-box.is-one { max-width: 480px; }
.lg-box.is-one .lg-card { grid-template-columns: 1fr; gap: 0; }
.lg-box.is-one .lg-body { padding-top: 24px; }
.lg-rows { font-size: .9rem; }
.lg-rows div { display: flex; justify-content: space-between; gap: 16px; padding: 4px 0; }
.lg-rows span { color: var(--lg-mut); }
.lg-rows b { font-weight: 500; text-align: right; }
.lg-alert.is-ok { background: #E6F4EA; color: #137333; }
/* หน้า login: ลายเส้นอาคารจาง static/img/home-building-l.svg (= ภาพหน้าแรกกลับด้าน · 2569-10-07)
   พื้นเทาฟ้าสีเดียวทั้งจอ = พื้นหน้าแรก (--hm-page · ไม่ไล่สีแล้ว 2569-10-07) · ≥768 ตึกอยู่ซ้าย (::before · ไฟล์กลับด้านแล้ว ไม่ใช้ scaleX) · ≥992 การ์ดชิดขวา
   มือถือ ฟอร์มค่อนบน ลายเส้นชิดล่าง (::after) */
.lg-wrap.is-art { position: relative; overflow: hidden;
  background: rgb(247, 249, 252); }
.lg-wrap.is-art .lg-box { position: relative; z-index: 1; }
.lg-wrap.is-art .lg-card { border-radius: var(--bs-border-radius-xl); box-shadow: var(--bs-box-shadow-sm); }   /* = rounded-4 + shadow-sm ของ Bootstrap (คลาสมี !important ทับกฎมือถือ จึงใช้ตัวแปร) */
.lg-copy { position: absolute; left: 0; right: 0; bottom: 16px; z-index: 1; margin: 0; text-align: center;
  font-size: .72rem; color: var(--lg-mut); }
@media (min-width: 768px) {
  .lg-wrap.is-art::before { content: ""; position: absolute; inset: 0;
    background: url("/static/img/home-building-l.svg?v=2") left bottom / cover no-repeat; pointer-events: none; }
}
@media (min-width: 992px) {
  .lg-wrap.is-art { justify-content: flex-end; padding-right: 8vw; }
}
@media (max-width: 767.98px) {
  .lg-wrap.is-art { align-items: flex-start; padding-top: 14vh; padding-top: 14dvh; }   /* ฟอร์มค่อนบน (ผู้ใช้กำหนดแนว) */
  .lg-wrap.is-art::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 34vh; height: 34dvh;
    background: url("/static/img/home-building.svg?v=2") right bottom / cover no-repeat;
    -webkit-mask-image: linear-gradient(180deg, transparent, #000 45%); mask-image: linear-gradient(180deg, transparent, #000 45%);
    pointer-events: none; }
  .lg-wrap.is-art .lg-card { box-shadow: none; background: transparent; }
  /* กล่องใสบนพื้นเทาฟ้า — ป้ายที่ลอยขึ้นคร่อมเส้นกรอบ ครึ่งบนต้องเป็นสีพื้น ไม่งั้นเป็นแถบขาวโผล่นอกช่อง */
  .lg-wrap.is-art .lg-field input:focus + label,
  .lg-wrap.is-art .lg-field input:not(:placeholder-shown) + label { background: linear-gradient(rgb(247, 249, 252) 50%, #fff 50%); }
}

/* [20.1] login → หน้าแรก (2569-10-07)
   ปุ่มเข้าสู่ระบบ: ยุบตอนกด · ระหว่างรอ AD = disabled + spinner (ตัวกลางใน _base.html ใส่ให้)
   เปลี่ยนหน้า: View Transition (เปิดเฉพาะ 2 หน้านี้ใน _base.html <head>) · Firefox/Safari เก่า = เปลี่ยนหน้าตรงๆ
   เรียงจังหวะ (เกิดวันละครั้ง จึงยาวกว่าเพดาน 300ms ได้ · กดได้ตั้งแต่ก้อนขึ้น):
     หน้า login  ลายเส้นถูกลบทีละเส้น ปลาย → หัว (~1.3s) · กล่องขาวจาง+เบลอตั้งแต่ 450 → ลบหมดค่อย submit (login.html)
     VT 0–300    พื้น login (เหลือแต่สีพื้น = สีหน้าแรก) จาง + เบลอ
     หน้าแรก     ลายเส้นวาดทีละเส้น หัว → ปลาย (~1.3s · home.html) · แถบบนลง +200 · เนื้อหา +500 ห่างกัน 70
   --arrive-wait = 300ms เฉพาะเมื่อ VT เล่นจริง (pagereveal ใน <head> ใส่ .vt-in) — ไม่งั้น 0
   ตัวแตกเส้น lineArt() อยู่ _base.html ใช้ร่วมสองหน้า
   ภาพตึก: login ตึกซ้าย (home-building-l.svg) · หน้าแรกตึกขวา (home-building.svg) จางกว่า (ชั้นสีทับ [41]) */
.lg-btn { display: inline-flex; align-items: center; transition: transform var(--mo-fast) var(--ease-out); }
.lg-btn:active:not(:disabled) { transform: scale(.97); }
.lg-btn:disabled { opacity: .85; cursor: progress; }
::view-transition-old(root),
::view-transition-new(root) { animation-duration: var(--mo-slow); animation-timing-function: var(--ease-in-out); }
.lg-wrap .lg-card { view-transition-name: lg-card; }
/* ลายเส้นที่ JS แตกเป็นเส้นละ path ไว้ลบตอนกดเข้าสู่ระบบ (login.html) — วางแทน ::before ตำแหน่งเดียวกัน */
.lg-erase { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.lg-wrap.is-erase::before { visibility: hidden; }
/* แสงเส้นเดียวบนลายเส้น (login.html) — วิ่งทับเส้นเดิม (.13) ไม่ต้องซ่อน ::before */
.lg-trace { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.lg-trace path.is-run { stroke-opacity: .55; }   /* แสงเส้นเดียว */
/* ท่าอยู่ฝั่งเอกสารใหม่ · VT บนหน้าแรกเกิดได้ทางเดียวคือมาจาก login
   new(root) ไม่ขยับ — หน้าแรกยังเป็นพื้นเปล่าอยู่ (ท่าเข้ารอ --arrive-wait) จึงเห็นเป็น "พื้นหลังหายไป" */
:root:has(.app-home-shell)::view-transition-old(root) { animation: vt-blur-out 300ms var(--ease-in-out) both; }
:root:has(.app-home-shell)::view-transition-new(root) { animation: none; }
:root:has(.app-home-shell)::view-transition-old(lg-card) { animation: vt-blur-out 300ms var(--ease-in-out) both; }   /* จางไปแล้วบนหน้า login — เหลือไว้ให้มือถือ/ปิด motion */
@keyframes vt-blur-out { to { opacity: 0; filter: blur(6px); } }
@keyframes vt-fade-out { to { opacity: 0; } }
:root { --arrive-wait: 0ms; }
:root.vt-in { --arrive-wait: 300ms; }
/* ลายเส้นหน้าแรกวาดขึ้นทีละเส้น (home.html · lineArt) — ระหว่างวาด พื้นเดิมของ shell ปิด
   svg ลอย fixed z-index -1 = อยู่ใต้ shell ที่ใสชั่วคราว โดยไม่สร้าง stacking context บน shell (modal ไม่จม)
   html ทาสีพื้นแทน · body ต้องใสด้วย ไม่งั้นพื้น body ทับ svg · opacity .45 = เท่าชั้นสีทับ 55% ของพื้นจริง */
:root.bg-draw { background: rgb(247, 249, 252); }
:root.bg-draw body,
:root.bg-draw .app-home-shell.is-arrive { background: transparent; }
.hm-bg-draw { position: fixed; inset: 0; width: 100%; height: 100%; z-index: -1; pointer-events: none; opacity: .45; }
/* แถบบนเลื่อนลงก่อนเนื้อหา — fill backwards ห้ามค้าง transform บน .tb (sticky เพี้ยน · ท่าเดียวกับ shellIn) */
@keyframes top-drop { from { transform: translateY(-100%); } }
.app-home-shell.is-arrive .tb { animation: top-drop 360ms var(--ease-out) calc(var(--arrive-wait) + 200ms) backwards; }
.app-home-shell.is-arrive :is(.hm-hello, .hm-cats, .hm-board, .hm-rail) { animation: stagger-in 300ms var(--ease-out) calc(var(--arrive-wait) + 500ms) backwards; }
.app-home-shell.is-arrive .hm-cats { animation-delay: calc(var(--arrive-wait) + 535ms); }
.app-home-shell.is-arrive .hm-board { animation-delay: calc(var(--arrive-wait) + 570ms); }
.app-home-shell.is-arrive .hm-rail { animation-delay: calc(var(--arrive-wait) + 640ms); }
@media (prefers-reduced-motion: reduce) {
  .lg-btn:active:not(:disabled) { transform: none; }
  .app-home-shell.is-arrive :is(.hm-hello, .hm-cats, .hm-board, .hm-rail) { animation-name: swap-fade-in; }
  .app-home-shell.is-arrive .tb { animation-name: swap-fade-in; }
  :root:has(.app-home-shell)::view-transition-old(root),
  :root:has(.app-home-shell)::view-transition-old(lg-card) { animation-name: vt-fade-out; }
}

/* [21] แจ้งเตือนสั้น (toast) — ขึ้นมุมขวาบน 5 วิ แล้วหายเอง ทั้งมือถือและเดสก์ท็อป
   Bootstrap มี .toast ให้แล้ว ที่นี่คุมแค่ 3 อย่างที่ utility ทำไม่ได้:
   ระยะจากขอบบน · ความกว้าง · จังหวะเลื่อนลงตอนโผล่ */
.toast-stack {
  top: var(--app-header-h);      /* ใต้ header พอดี ไม่บังกระดิ่งกับปุ่มออกจากระบบ */
  z-index: 1090;                 /* สูงกว่า modal (1055) — กดยืนยันใน modal แล้วต้องเห็น */
  max-width: 100%;
}

.toast-stack .toast {
  --bs-toast-max-width: 380px;
  width: 380px;
  max-width: 100%;
  animation: toast-in var(--mo-base) var(--ease-out);
}

/* เลื่อนเข้าจากขวา ไม่ใช่ลงมาจากบน — toast-stack ปักอยู่มุมขวาบน (MOTION.md ระยะ 3 ชั้น 0)
   ทิศเข้าตรงกับตำแหน่งที่มันอยู่จริง ไม่ใช่ทิศที่ขัดกับมุมจอ */
@keyframes toast-in {
  from { opacity: 0; transform: translateX(24px); }
  to   { opacity: 1; transform: none; }
}

/* มือถือ: กว้างเต็มจอลบขอบ — .toast-container ของ Bootstrap เป็น width:max-content
   ปล่อยไว้ใบสั้นจะหดตามข้อความ ขอบขวาไม่ตรงกัน จึงบังคับ width กลับ */
@media (max-width: 575.98px) {
  .toast-stack { left: 0; right: 0; width: auto; }
  .toast-stack .toast { width: 100%; }
}

/* บรรทัดข้อความเตือนใต้ช่องกรอก — จองที่ไว้ ฟอร์มจะได้ไม่ขยับตอนข้อความโผล่ */
.odo-msg { min-height: 1rem; }

/* [22] ของกลางที่เกิดจากหน้าแรกรุ่นก่อน — กล่องไอคอนตามโทน · แถวที่กดได้ทั้งแถว
   (การ์ดทริป [22.2] ถอดแล้ว 2569-10-02 — หน้าแรกใหม่อยู่ [41]) */

/* [22.25] กล่องไอคอนที่รับคู่สีจากคลาส .tone-* — ใช้ทั้งแถวงานล่าสุดและใบแจ้งเตือน
   สีตัวไอคอนสืบทอดจากกล่อง (span ไม่ใส่ text-* เอง) เปลี่ยนคู่สีจุดเดียวจบทั้งก้อน */
.ico-tint {
  background: var(--tint);
  color: var(--fg);
}

/* ขั้นมาตรฐาน (--st-* · mock.STAGE) — --tint/--fg ของ .ico-tint · --c/--bg ของแถว .pk หน้าแรก */
.tone-info { --tint: var(--st-info-soft); --fg: var(--st-info); }
.tone-wait { --tint: var(--st-wait-soft); --fg: var(--st-wait); }
.tone-ok   { --tint: var(--st-ok-soft);   --fg: var(--st-ok); }
.tone-done { --tint: var(--st-done-soft); --fg: var(--st-done); }
.tone-bad, .tone-late { --tint: var(--st-bad-soft); --fg: var(--st-bad); }

/* [22.3] แถวรายการที่กดได้ทั้งแถว — ต้องต่างจากแถวที่กดไม่ได้ด้วยตา ไม่ใช่ด้วยการลองกด
   (.job-row ของหน้า admin ใช้ไม่ได้ เพราะมันผูกกับสถานะ "ถูกเลือก" ของ checkbox)

   เฉพาะเครื่องที่ชี้ได้จริง (2569-09-20) — จอสัมผัสแตะแล้ว :hover ค้างจนกว่าจะแตะที่อื่น
   พื้นเทาจึงค้างอยู่หลังกดและหลังกด back กลับมา อ่านว่า "อยู่แถวนี้" ทั้งที่ไม่ใช่
   บนจอสัมผัส feedback ตอนกดมาจาก .link-row:active ใน [28] แทน ไม่ได้หายไปเฉยๆ */
@media (hover: hover) and (pointer: fine) {
  .link-row:hover { background: var(--bs-secondary-bg); }
}


/* แถวที่กดได้ทั้งแถว (ไม่ใช่ .btn) — มือถือไม่มี hover กดแล้วต้องขยับให้รู้ว่าโดน
   ยุบน้อยกว่าไอคอน — ของยิ่งกว้าง scale เท่ากันยิ่งขยับเป็นพิกเซลเยอะ
   .link-row ประกาศ transition ไว้แล้วข้างบน (--mo-fast) ไม่ต้องประกาศซ้ำ */
.link-row:active {
  transform: scale(0.985);
}

/* [28.0] ของที่กดได้ทั่วระบบซึ่งไม่ใช่ `.btn` — ไล่จาก `:hover`/`role="button"` ทั้งไฟล์
   ไม่ใช่จากชื่อคลาสที่นึกออก (2569-09-20) ทุกตัวเป็นปุ่ม/ลิงก์จริงที่เดิมกดแล้วเงียบสนิท

   ตัวที่ย่อคือ **ก้อนที่ตาเล็งไว้** ไม่ใช่กล่องที่ครอบมัน — วงเลขในแถบสัปดาห์กับปฏิทินมือถือ
   จึงย่อที่ .wk-num / .mcal-num ไม่ใช่ทั้งช่อง (ย่อทั้งช่องแล้วช่องว่างรอบๆ ขยับตามไปด้วย
   เห็นเป็นทั้งแถวกระตุก)

   80ms + --ease-out ตัวเดียวกับ .btn ทั้งหมด ไม่มีเลขใหม่ */
.wk-num,
.mcal-num,
.cal-ev,
.dp-day,
.tp-seg {
  transition: transform 80ms var(--ease-out);
}

/* เป้าขนาดไอคอน/วงกลม — ย่อ .94 เท่า .tab:active ของแถบล่าง */
.wk-day:active .wk-num,
.mcal-day:active .mcal-num,
.dp-day:active:not(:disabled),
.tp-seg:active { transform: scale(0.94); }

/* ชิปงานในช่องปฏิทิน — กว้างกว่าวงเลข ย่อเท่ากันจะขยับเยอะเกิน */
.cal-ev:active { transform: scale(0.96); }

@media (prefers-reduced-motion: reduce) {
  .link-row:active,
  .wk-day:active .wk-num,
  .mcal-day:active .mcal-num,
  .cal-ev:active,
  .dp-day:active:not(:disabled),
  .tp-seg:active { transform: none; }
}

/* [28.1] ขีดเส้นใต้แท็บสไลด์ตามตอนสลับ — ครอบทั้งแท็บระดับหน้า (.nav-underline จาก tabbar())
   และแท็บใน modal (.nav-underline-full จาก mtab()) แถบ <span> เดียวถูก JS เติมเข้าไปท้าย
   <ul> ใน _base.html แล้ววางตำแหน่งจาก offsetLeft/offsetWidth ของ .nav-link.active —
   ต้องปิด border-bottom เดิมของ Bootstrap บนแท็บที่ active ไม่งั้นเห็นเส้นสองเส้นซ้อนกัน
   (เส้นเดิมโผล่ทันที ไม่เลื่อน + แถบใหม่ที่กำลังสไลด์ตามมา) */
.nav-underline,
.nav-underline-full {
  position: relative;
}
.nav-underline .nav-link.active,
.nav-underline-full .nav-link.active {
  border-bottom-color: transparent;
}
.tab-underline-bar {
  position: absolute;
  left: 0;
  bottom: -1px;
  height: var(--bs-nav-underline-border-width, 2px);
  background: var(--bs-emphasis-color);
  border-radius: 2px 2px 0 0;
  opacity: 0;
  transition: transform var(--mo-fast) var(--ease-out), width var(--mo-fast) var(--ease-out);
  pointer-events: none;
}

/* [29] ระยะ 3 ชั้น 1 — motion ระดับข้อมูล (MOTION.md) */

/* แถบสัปดาห์/ปฏิทินเปลี่ยนเดือน: เข้าจากทิศที่กด — data-swap-dir ใส่ให้เองใน _base.html
   ตอนก้อนใหม่ (fresh) เข้ามาแทน ผู้ใช้ไม่หลงว่าอยู่สัปดาห์ไหนเพราะทิศตรงกับปุ่มที่กด */
@keyframes swap-from-right {
  from { opacity: 0; transform: translateX(16px); }
}
@keyframes swap-from-left {
  from { opacity: 0; transform: translateX(-16px); }
}
[data-swap-dir="next"] { animation: swap-from-right var(--mo-slow) var(--ease-out); }
[data-swap-dir="prev"] { animation: swap-from-left var(--mo-slow) var(--ease-out); }

/* สลับแท็บ/ตัวกรอง/เลขหน้า/บันทึกฟอร์ม — ไม่มีทิศให้สื่อ ก้อนใหม่จึงแค่จางเข้ามา
   บอกว่า "ตรงนี้เพิ่งเปลี่ยน" โดยไม่ลากสายตาไปทางไหน (swap วัดจริง ~47ms ถ้าไม่มีอะไร
   ขยับเลยจะอ่านเป็นภาพกระตุกมากกว่าการเปลี่ยนหน้า)
   ⚠️ opacity ล้วน ห้ามใส่ transform — ก้อนที่ swap รวมตารางภาพรวมงบซึ่งตรึงคอลัมน์ซ้าย
   ด้วย position:sticky ที่ตายทันทีเมื่อบรรพบุรุษมี transform (ดู MOTION.md กับดักข้อ 1) */
@keyframes swap-fade-in {
  from { opacity: 0; }
}
[data-swap-in] { animation: swap-fade-in var(--mo-fast) var(--ease-out); }

/* แถวในรายการทยอยขึ้น — data-stagger ใส่ไว้ที่ container, JS ใน _base.html ตั้ง
   animation-delay ทีละ 25ms ให้ 8 ตัวแรกของ direct children เท่านั้น เกินกว่านั้นไม่หน่วง */
@keyframes stagger-in {
  from { opacity: 0; transform: translateY(6px); }
}
.js-stagger-item {
  animation: stagger-in var(--mo-base) var(--ease-out) backwards;
}

/* [30.1] ระยะ 3 ชั้น 2 ข้อ 1 — บันทึกสำเร็จ → ปุ่มวาดเครื่องหมายถูกก่อน modal ปิด
   ปิด modal เฉยๆ แล้วให้ toast บอกทีหลัง = ผู้ใช้ไม่แน่ใจว่าบันทึกสำเร็จจริงไหม
   ไอคอน check ขยายจากเล็กเข้าที่ (เดิมเส้น SVG วาดเอง · 2569-10-04) — ตาจับได้ว่า "เพิ่งเกิดขึ้น"
   ปิด motion แล้วเหลือเครื่องหมายถูกที่วาดเสร็จแล้ว (dashoffset ฐานเป็น 0) ข้อมูลไม่หาย */
@keyframes check-draw {
  from { transform: scale(.3); opacity: 0; }
}
.mo-check {
  display: inline-block;
  font-size: 18px;
  vertical-align: -3px;
  animation: check-draw var(--mo-slow) var(--ease-out);
}

/* [30.2] ข้อ 2 — แถวที่เพิ่งอนุมัติ/ปิดงาน เลื่อนออกก่อนก้อนใหม่เข้ามาแทน
   ตาเห็นว่างานหายไปจากคิว ไม่ใช่รายการเปลี่ยนแล้วเดาเอาว่าอันไหนหาย
   ที่ว่างของแถวปิดเองตอนก้อนใหม่เข้ามา — ไม่ยุบความสูงเอง เพราะ height/max-height
   ไม่อยู่ในรายการที่ขยับได้ (หลักการข้อ 4) */
@keyframes row-exit {
  to { opacity: 0; transform: translateX(24px); }
}
.mo-row-exit {
  animation: row-exit var(--mo-base) var(--ease-out) forwards;
}

/* ⚠️ แถวตาราง (<tr>) ห้าม transform — ภาพซ้อนทับแถวข้างเคียง (กับดักเดียวกับ .odo-row
   ในหัวข้อ [28]) จางอย่างเดียวพอ ผลที่ตาเห็นคือ "แถวนี้กำลังจะไป" เหมือนกัน */
@keyframes row-fade {
  to { opacity: 0; }
}
tr.mo-row-exit {
  animation: row-fade var(--mo-base) var(--ease-out) forwards;
}

/* ตัวเลขบนหัวแท็บที่เพิ่งเปลี่ยนค่า (12) → (11) — เด้งเข้ามาแทนการนับไล่เลข
   เพราะต่างกันทีละ 1 การนับ 12→11 กินเวลาเท่าไหร่ก็มองไม่ทัน สิ่งที่ต้องบอกคือ "เปลี่ยนแล้ว" */
@keyframes count-bump {
  from { opacity: 0; transform: scale(0.8); }
}
.mo-count-bump {
  display: inline-block;
  animation: count-bump var(--mo-base) var(--ease-out);
}

/* กระดิ่งมีของใหม่ — สั่นครั้งเดียว + จุดแดงเด้งเข้ามา (คลาสใส่ให้เองใน _base.html
   เฉพาะตอนจำนวนแจ้งเตือนมากกว่าครั้งก่อนที่เคยเห็น ไม่ใช่ทุกครั้งที่เปิดหน้า) */
@keyframes bell-shake {
  0%, 100% { transform: rotate(0); }
  20% { transform: rotate(-12deg); }
  40% { transform: rotate(10deg); }
  60% { transform: rotate(-6deg); }
  80% { transform: rotate(3deg); }
}
.mo-bell-shake .material-symbols-rounded {
  animation: bell-shake 500ms var(--ease-out);
}
@keyframes badge-in {
  from { opacity: 0; transform: scale(0.4); }
}
.mo-badge-in {
  animation: badge-in var(--mo-base) var(--ease-out);
}



/* [23] พื้นหลังเทาอ่อนทั้งแอป (redesign 2569-09-19)
   ไม่แตะ --bs-body-bg — ตัวนั้นเป็น "สีพื้นผิว" ที่ modal/การ์ด/ตารางใช้ ต้องขาวต่อไป
   ก้อนที่มีกรอบใน <main> จึงทาขาวให้ที่นี่ ไม่งั้นโปร่งจนเห็นพื้นเทาทะลุทั้งหน้า
   (.bg-body-secondary ของ Bootstrap เป็น !important ชนะกฎนี้ — ของที่ตั้งใจให้เทายังเทาเหมือนเดิม) */
:root {
  --app-bg: rgb(248, 249, 250);
}

body {
  background-color: var(--app-bg);
}

main.app-main .border.rounded-3,
main.app-main .border.rounded-2,
main.app-main .table {
  background-color: var(--bs-body-bg);
}

/* [23] ตัวเลือกวันที่ + เวลาในฟอร์มจองรถ — Bootstrap ไม่มี date/time picker ของตัวเอง
   และ <input type="date|time"> ของเบราว์เซอร์คุมหน้าตาไม่ได้ (คนละทรงกันทุกเครื่อง)
   กลไกเปิด/ปิด/วางตำแหน่งใช้ dropdown ของ Bootstrap ทั้งคู่ ที่นี่มีแค่กริดวันกับปุ่ม ชม./นาที */
.dp-menu { width: 17rem; }

.dp-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}

.dp-day {
  height: 2rem;
  border: 0;
  border-radius: 0.5rem;
  background: transparent;
  color: inherit;
  line-height: 1;
}

@media (hover: hover) and (pointer: fine) {
  .dp-day:hover:not(:disabled) { background: var(--bs-secondary-bg); }
}

/* วันย้อนหลัง — จางแต่ยังอ่านออก ต้องเห็นว่ามีวันนั้นอยู่ ไม่ใช่หายไปเฉยๆ */
.dp-day:disabled {
  color: var(--bs-secondary-color);
  opacity: 0.45;
}

/* วันนี้ = วงบาง · วันที่เลือกอยู่ = ทึบ (ทับวงของวันนี้เมื่อเป็นวันเดียวกัน) */
.dp-day.is-today { box-shadow: inset 0 0 0 1px var(--bs-primary); }

.dp-day.is-on {
  background: var(--bs-primary);
  color: #fff;
}

/* ชั่วโมง : นาที อยู่ในกล่อง .form-control ใบเดียว แต่กดแยกกันคนละ dropdown
   padding ตั้งให้ความสูงรวมเท่า .form-control ปกติ (0.375rem + line-height + ขอบ) */
.tp-box {
  display: flex;
  align-items: center;
  gap: 2px;
  padding-top: 0;
  padding-bottom: 0;
}

.tp-seg {
  border: 0;
  border-radius: 0.25rem;
  background: transparent;
  color: inherit;
  padding: 0.375rem 0.45rem;
}

@media (hover: hover) and (pointer: fine) {
  .tp-seg:hover { background: var(--bs-secondary-bg); }
}

/* .show = dropdown ของช่องนี้กางอยู่ (Bootstrap ใส่ให้เอง) */
.tp-seg.show {
  background: rgba(var(--bs-primary-rgb), 0.16);
  color: var(--bs-primary);
}

.tp-menu {
  --bs-dropdown-min-width: 4.5rem;
  max-height: 11rem;
  overflow-y: auto;
}

/* [25] แถบล่างของมือถือ — ถอดแล้ว 2569-10-09 (sidebar เปิดจากปุ่มเมนูบนแถบบนทุกจอ <1200) */

/* [31] หน้ารายการแบบ rgt (getFilterBar + toolsBar + getTableV2 · 2569-09-30)
   component กลาง (macro _rgt.html · JS rgt-list.js · skill bb-rgt-list) — หน้าที่ใช้ชุดนี้ไม่ใช้กฎ
   ตาราง/เลขหน้า/ทรงปุ่มของหน้าอื่น (ดู CLAUDE.md "Component กลาง: หน้ารายการแบบ rgt") · ค่าลอกจาก rgt_php74 public_html/global/css/global.css
   ขนาดใน rgt เป็น px บนฐาน 16 — ที่นี่ฐาน 18 จึงแปลงเป็น rem ให้ได้ px เท่าเดิม */

/* ---- แถบค้นหา + แผงตัวกรอง ---- */
.rgt-filter { border: 1px solid rgba(0, 0, 0, .1); border-radius: 5px; background: var(--bs-body-bg); }
.rgt-searchbar { background: #f5f5f5; padding: 16px; border-radius: 5px 5px 0 0; }
.rgt-searchbar:has(.rgt-aside) { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.rgt-searchbar:has(.rgt-aside) > .col-12 { flex: 1 1 280px; max-width: 480px; }
.rgt-aside { margin-left: auto; }
.rgt-aside .form-select { min-width: 180px; }
/* มือถือ: ตัวเลือกปี/รุ่นขึ้นบนเต็มแถว ช่องค้นหาเต็มแถวข้างล่าง (แบบ rgt) */
@media (max-width: 575.98px) {
  .rgt-aside { order: -1; flex: 0 0 100%; margin-left: 0; }
  .rgt-searchbar:has(.rgt-aside) > .col-12 { flex-basis: 100%; max-width: none; }
}
.rgt-filter-toggle { background: #fff; border-color: rgba(0, 0, 0, .15); color: #6c757d; }
.rgt-filter-toggle:hover,
.rgt-filter-toggle:focus { background: #f7f7f7; border-color: rgba(0, 0, 0, .18); color: #6c757d; }
.rgt-filter-toggle .rgt-chev { transition: transform .3s ease; }
.rgt-filter-toggle.active .rgt-chev { transform: rotate(180deg); }
.rgt-filter-panel { display: flex; border-top: 1px solid rgba(0, 0, 0, .1); border-radius: 0 0 5px 5px; }
.rgt-filter-panel.rgt-hidden { display: none; }
.rgt-filter-items { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; padding: 0 0 16px 16px; }
.rgt-filter-items > * { margin: 16px 8px 0 0; }
.rgt-filter-go { height: auto; border-radius: 0 0 5px 0; padding: 0 16px; }
.rgt-filter .input-group-text { white-space: nowrap; }
/* multiselect — ตาม bootstrap-multiselect ของ rgt: ปุ่ม btn-light มีเส้นขอบจาง (global.css ของ rgt)
   เมนูเป็น checkbox ธรรมดา · ช่องค้นหาติดบนสุดของเมนู */
/* ชิปตัวกรองแบบ Drive (2569-09-30) — กรอบเทาเข้ม มุม 8px พื้นโปร่ง · มีค่าเลือกอยู่ (.is-on) = พื้นฟ้า
   ไม่มีกรอบ + ปุ่ม ✕ คั่นเส้นขาว · ช่วงวันที่ใช้ทรงเดียวกัน · ชิปในฟอร์มแก้ไข (.rgt-form) ไม่เกี่ยว */
.rgt-filter-items { --chip-line: #747775; --chip-ink: #444746; --chip-on: #c2e7ff; --chip-on-ink: #001d35; }
.rgt-ms > .btn-light { border: 1px solid rgba(0, 0, 0, .1); white-space: nowrap; }
.rgt-ms > .btn-light:hover { border-color: rgba(0, 0, 0, .2); }
.rgt-filter-items .rgt-ms > .btn {
  background: transparent; border: 1px solid var(--chip-line); color: var(--chip-ink);
  font-weight: 500; border-radius: 8px; padding: .3rem .75rem;
}
.rgt-filter-items .rgt-ms > .btn:hover,
.rgt-filter-items .rgt-ms > .btn.show { background: rgba(68, 71, 70, .08); border-color: var(--chip-line); }
.rgt-filter-items .rgt-ms.is-on > .btn { background: var(--chip-on); border-color: var(--chip-on); color: var(--chip-on-ink); }
.rgt-filter-items .rgt-ms.is-on > .btn:hover,
.rgt-filter-items .rgt-ms.is-on > .btn.show { background: #b3dcf5; border-color: #b3dcf5; }
.rgt-filter-items .rgt-ms.is-on > .dropdown-toggle { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.rgt-ms-x { display: inline-flex; align-items: center; padding: 0 .55rem !important;
            border-top-left-radius: 0 !important; border-bottom-left-radius: 0 !important;
            border-left: 1px solid #fff !important; margin-left: 0 !important; }
.rgt-ms-x[hidden] { display: none; }
/* ช่วงวันที่เป็นชิปเดียวกัน — ป้าย + ช่อง + ขีด อยู่ในกรอบมน 8px ใบเดียว */
.rgt-filter-items .rgt-dt > * { border-color: var(--chip-line); background: transparent; }
.rgt-filter-items .rgt-dt > :first-child { border-radius: 8px 0 0 8px; color: var(--chip-ink); font-weight: 500; }
.rgt-filter-items .rgt-dt > :last-child { border-radius: 0 8px 8px 0; }
.rgt-filter-items .rgt-dt.is-on > * { background: var(--chip-on); border-color: var(--chip-on); color: var(--chip-on-ink); }
.rgt-filter-items .rgt-dt.is-on > :not(:first-child) { border-left-color: #fff; }
/* ล้างตัวกรอง — ปุ่มตัวหนังสือเปล่าแบบ "Clear filters" */
.rgt-clear { color: #1f1f1f; font-weight: 500; border: 0; border-radius: 8px; }
.rgt-clear:hover { background: rgba(68, 71, 70, .08); color: #1f1f1f; }
.rgt-ms-menu { max-height: 80vh; overflow-y: auto; padding-top: 0; }
.rgt-ms-menu .dropdown-item { display: flex; align-items: center; gap: 6px; padding: 3px 20px; margin: 0; cursor: pointer; }
.rgt-ms-menu li.active > .dropdown-item { background: var(--bs-primary-bg-subtle); color: inherit; }
.rgt-ms-menu input[type="checkbox"] { margin: 0; flex-shrink: 0; }
.rgt-ms-search { position: sticky; top: 0; z-index: 1; background: var(--bs-body-bg);
                 border-bottom: 1px solid var(--bs-border-color); padding: 6px 10px; margin-bottom: 4px; }
.rgt-ms-search .form-control { font-size: 16px; }   /* มือถือห้ามต่ำกว่า 16px — Safari zoom ค้าง */

/* select พิมพ์ค้นได้ (rgt.select search=True · ห่อโดย rgt-list.js) — ช่องเป็น form-select ได้ลูกศรเดิม */
.rgt-ss { position: relative; }
.rgt-ss-menu { position: absolute; top: calc(100% + 2px); left: 0; right: 0; z-index: 1000; max-height: 18rem;
               overflow-y: auto; margin: 0; padding: 4px 0; list-style: none; background: var(--bs-body-bg);
               border: 1px solid var(--bs-border-color); border-radius: var(--bs-border-radius); box-shadow: var(--bs-box-shadow); }
.rgt-ss-menu li { padding: 6px 12px; cursor: pointer; }
.rgt-ss-menu li.active { background: var(--bs-primary-bg-subtle); }
.rgt-ss-menu li.is-sel { font-weight: 500; }
.rgt-ss-menu li.is-none { color: var(--bs-secondary-color); cursor: default; }

/* ช่วงวันที่ (.filter-datetime ของ rgt) */
.rgt-dt { flex-wrap: nowrap; width: auto; }
.rgt-dt .rgt-dt-sep { padding: .25rem .3rem; color: #6c757d; }
.rgt-dt .js-dt { flex: 0 0 9.5rem; width: 9.5rem; }
/* มือถือ: ช่วงวันที่เต็มแถว ป้ายหดได้ (แบบ rgt @576) */
@media (max-width: 575.98px) {
  .rgt-filter-items > .rgt-dt { width: calc(100% - 8px); min-width: 0; }
  .rgt-dt .js-dt { flex: 1 1 0; min-width: 0; width: auto; }
  .rgt-dt > .input-group-text:first-child { max-width: 90px; overflow: hidden; text-overflow: ellipsis; }
}

/* ---- แถบเครื่องมือ ---- */
.rgt-tools { display: flex; flex-wrap: wrap; gap: 8px; padding: 8px 0 16px; margin: 4px 0 16px;
             border-bottom: 1px solid var(--bs-border-color); }
/* มือถือ: แถวเดียว เลื่อนแนวนอนอย่างเดียว ซ่อนแถบเลื่อน */
@media (max-width: 991.98px) {
  .rgt-tools { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
               overscroll-behavior-x: contain; }
  .rgt-tools::-webkit-scrollbar { display: none; }
  .rgt-tools > * { flex-shrink: 0; }
  .rgt-tools .btn { white-space: nowrap; }
}

/* ---- ตาราง (getTableV2) ---- */
.rgt-table { position: relative; }                                 /* ขนาดมาตรฐาน (1rem) — ผู้ใช้ขอ 2569-09-30 */
.rgt-table-bar { display: flex; justify-content: space-between; align-items: center;
                 padding: 6px 0; gap: 8px; flex-wrap: wrap; }
.rgt-table-bar-r { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.rgt-info,
.rgt-cfg-btn {
  font-size: 0.778rem;                                             /* 14px */
  color: #545b64; border: 1px solid #d5dbdb; padding: 4px 10px; border-radius: 4px;
  background: #fff; white-space: nowrap;
}
/* ยอด + ⚙ สูงเท่ากัน (30px) · ⚙ เป็นสี่เหลี่ยมจัตุรัส */
.rgt-info, .rgt-cfg-btn { display: inline-flex; align-items: center; height: 30px; }
.rgt-cfg-btn { width: 30px; padding: 0; justify-content: center; }
.rgt-cfg-btn .rgt-i { font-size: 18px; }
.rgt-cfg-btn:hover { background: #f2f3f3; }
/* ทรงตาราง: แบบรายการไฟล์ของ Google Drive (2569-09-30) — ไม่มีกรอบนอก ไม่มีเส้นตั้ง ไม่สลับสีแถว
   เส้นนอนเส้นเดียวใต้ทุกแถว · แถวสูง 48px · ชี้แล้วพื้นเทาทั้งแถว · หัวคอลัมน์ตัวเข้มไม่ใช่ลิงก์ฟ้า
   คอลัมน์ที่เรียงอยู่มีลูกศรในวงฟ้าอ่อน · พื้นทึบทุกเซลล์ (คอลัมน์ปักหมุด sticky ต้องบังของที่เลื่อนผ่าน) */
.rgt-scroll { overflow-x: auto; overflow-y: clip; background: var(--bs-body-bg); }
.rgt-t { width: 100%; margin: 0; border-collapse: separate; border-spacing: 0; color: #1f1f1f; }
.rgt-t th {
  position: relative; z-index: 3; background: #fff; font-weight: 500; color: #1f1f1f;
  border-bottom: 1px solid #c4c7c5;
  height: 48px; padding: 4px 12px; white-space: nowrap; vertical-align: middle;
}
.rgt-t td { height: 48px; padding: 6px 12px; background: #fff; vertical-align: middle;
            border-bottom: 1px solid #e3e3e3; }
.rgt-t tbody tr:hover td { background: #f1f3f4; }
.rgt-t.rgt-stuck th { box-shadow: 0 2px 4px rgba(0, 0, 0, .08); }
.rgt-t .rgt-pin { position: sticky; z-index: 2; }
.rgt-t th.rgt-pin { z-index: 4; }
.rgt-t .rgt-pin-last { box-shadow: 4px 0 6px -2px rgba(0, 0, 0, .1); }
.rgt-t td.rgt-empty { text-align: center; color: var(--bs-secondary-color); padding: 8px; }
/* ลิงก์ในแถว (ชื่อ · จำนวน) ตัวเข้มแบบชื่อไฟล์ของ Drive — ขีดเส้นใต้ตอนชี้เพื่อบอกว่ากดได้ */
.rgt-t td a:not(.btn):not(.dropdown-item) { color: inherit; text-decoration: none; font-weight: 500; }
.rgt-t td a:not(.btn):not(.dropdown-item):hover { text-decoration: underline; }
.rgt-sort { display: inline-flex; align-items: center; gap: 6px; color: inherit; text-decoration: none; }
.rgt-sort:hover { color: inherit; text-decoration: underline; }
.rgt-sort .rgt-i { width: 24px; height: 24px; padding: 4px; border-radius: 50%;
                   background: #c2e7ff; color: #0b57d0; font-size: 16px; overflow: visible; }
.rgt-resize { position: absolute; right: -3px; top: 0; bottom: 0; width: 6px; cursor: col-resize; z-index: 5; }
.rgt-resize:hover { background: rgba(13, 110, 253, .3); }
.rgt-t th:last-child .rgt-resize { right: 0; }     /* ยื่นเกินขอบ = กล่องเลื่อนแนวนอนโผล่ทั้งที่ตารางพอดี */
/* ป้ายสถานะ — pill พื้นอ่อน ตัวเข้ม (จานสีชิปของ Google · 2569-09-30) · primary ตรงกับชิปตัวกรองที่เลือกอยู่ */
.rgt-lbl { display: inline-block; padding: 2px 10px; border-radius: 50rem; font-size: var(--fs-xs);
           font-weight: 500; line-height: 1.4; white-space: nowrap; }
/* สีจากขั้นมาตรฐาน --st-* (2569-10-15) · ชื่อโทนแบบ Bootstrap ↔ ขั้น = mock.LBL_OF */
.rgt-lbl-success   { background: var(--st-done-soft); color: var(--st-done-ink); }
.rgt-lbl-danger    { background: var(--st-bad-soft);  color: var(--st-bad-ink); }
.rgt-lbl-primary   { background: var(--st-ok-soft);   color: var(--st-ok-ink); }
.rgt-lbl-warning   { background: var(--st-wait-soft); color: var(--st-wait-ink); }
.rgt-lbl-secondary { background: var(--st-info-soft); color: var(--st-info-ink); }
/* ⋮ ในแถว — ไอคอนเปล่าแบบ Drive พื้นเทาเฉพาะตอนชี้/กางเมนู */
.rgt-row-btn { width: 32px; height: 32px; background: transparent; border-color: transparent; }
.rgt-row-btn:hover, .rgt-row-btn.show { background: rgba(31, 31, 31, .08); border-color: transparent; }

/* เลขหน้า — .pagination-sm ของ Bootstrap ตามแบบ rgt (หน้าอื่นยังใช้ pager() ของ jame) */
.rgt-pgn .pagination { flex-wrap: wrap; margin: 0; }
.rgt-pgn .page-link { font-size: 0.778rem; padding: 3px 8px; }

/* ตั้งค่าคอลัมน์ */
.rgt-cs { min-width: 240px; max-height: 400px; overflow-y: auto; padding: 8px; }
.rgt-cs-item { display: flex; align-items: center; gap: 8px; padding: 4px 8px; border-radius: 4px;
               font-size: 0.667rem; }
.rgt-cs-item.drag-over { background: var(--bs-primary-bg-subtle); }
.rgt-cs-item .grip { cursor: grab; opacity: .4; }
.rgt-cs-item label { flex: 1; display: flex; gap: 6px; align-items: center; cursor: pointer; margin: 0; }
.rgt-cs-pin { cursor: pointer; opacity: .35; border: 0; background: none; padding: 0; line-height: 1; }
.rgt-cs-pin.on { opacity: 1; color: var(--bs-primary); }

/* แถบบอกโปรแกรมที่กำลังดู (ของ jame — rgt ไม่มี เพราะ rgt แยกหน้าตามโปรแกรม) */
.rgt-scope { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px;
             padding: 8px 12px; border-radius: 6px; font-size: 0.778rem;
             background: var(--bs-primary-bg-subtle); color: var(--bs-primary-text-emphasis); }

/* หน้าแบบ rgt ไม่มีกรอบเนื้อหา — พื้นขาวเต็มความกว้างที่เหลือจาก sidebar (block main_class ใน _base) */
main.app-main.app-main-full { max-width: none; margin: 0 !important; background: var(--bs-body-bg); }

/* [32.0] แถบบนอันเดียวทั้งระบบ (_topbar.html · 2569-10-15 · แทน .gn หน้าแรก + header แผ่นขาว)
   ซ้าย ปุ่มเมนู + โลโก้/ชื่อหน้า · กลาง เครื่องมือของหน้า · ขวา กระดิ่ง + เมนูบัญชี
   พื้นเป็นของ shell: แผ่นขาว = ขาวหัวแผ่น (จอ <992 สีพื้น sidebar) · หน้าแรก = โปร่งเบลอเต็มกว้าง */
.tb { height: var(--app-header-h); background: var(--bs-body-bg); }
.tb-row { display: flex; align-items: center; gap: 12px; height: 100%; padding: 0 12px; }
.tb-btn { width: 40px; height: 40px; flex: none; display: flex; align-items: center; justify-content: center;
  border: 0; padding: 0; border-radius: 50%; background: none; color: var(--bs-body-color); }
.tb-logo { display: flex; align-items: center; flex: none; font-size: 1.05rem; font-weight: 700; letter-spacing: -.01em;
  color: var(--bs-body-color); text-decoration: none; white-space: nowrap; }
.tb-logo > span { color: var(--bs-primary); }
.tb-title { align-self: stretch; display: flex; align-items: center; }
.tb-h1 { font-size: 1.25rem; font-weight: 600; margin: 0; }
.tb-tools { display: flex; align-items: center; margin-left: 12px; }
.tb .cal-nav-month { font-size: 1.25rem; }
.tb-end { display: flex; align-items: center; gap: 4px; margin-left: auto; flex: none; }
@media (hover: hover) and (pointer: fine) {
  .tb-btn:hover { background: rgb(0 0 0 / .05); }
  .tb-logo:hover { color: var(--bs-body-color); }
}
@media (min-width: 768px) { .tb-row { padding: 0 16px; } }
/* โลโก้ + ชื่อหน้าคู่กัน (แผ่นขาว 992–1199) = เส้นคั่นสูงเต็มแถบ */
@media (min-width: 992px) and (max-width: 1199.98px) {
  .tb-logo + .tb-title { border-left: 1px solid var(--bs-border-color); padding-left: 16px; }
}
/* หน้าแรก: โปร่งเบลอ · แถวกว้างเท่าเนื้อหา (1188) */
.app-home-shell .tb { background: rgb(250 251 253 / .8);
  backdrop-filter: saturate(180%) blur(20px); -webkit-backdrop-filter: saturate(180%) blur(20px); }
.app-home-shell .tb-row { max-width: 1188px; margin: 0 auto; }

/* [32] shell แผ่นขาว (route ส่ง shell='panel' · ส่วนหนึ่งของ component หน้ารายการแบบ rgt · 2569-09-30)
   sidebar ไม่มีเส้นขอบ วางบนพื้นฟ้าเทาอ่อน (ผู้ใช้เลือกค่า 2569-09-30) สูงเต็มจอ ·
   เนื้อหาเป็นกล่องขาวลอย ไม่มีขอบ มนครบ 4 มุม เว้นพื้นฟ้ารอบกล่อง
   header อยู่หัวแผ่น (sticky ในแผ่น) · จอ <1200 ไม่มี sidebar ถาวร แผ่นจึงเต็มจอไม่มีขอบ */
.app-panel-shell { --app-panel-bg: rgb(247, 249, 252); --app-active-bg: #d2e2fc; --app-active-ink: #0a44a1; min-height: 100vh; background: var(--app-panel-bg); }
.app-home-shell { --app-active-bg: #d2e2fc; --app-active-ink: #0a44a1; }   /* sidebar หน้าแรก = แบบแผ่นขาว (2569-10-09) */
.app-panel-shell .rgt-searchbar { background: var(--app-panel-bg); }   /* แถบค้นหาสีเดียวกับพื้น sidebar */
.app-panel { background: var(--bs-body-bg); min-height: 100vh; }   /* จอแคบไม่เหลือพื้นเทาใต้เนื้อหา */
.app-panel > .tb { border-bottom: 1px solid var(--bs-border-color); }
#sidebar .app-panel-logo { display: none; }
/* มือถือ (<992 ช่วงที่มีแถบล่าง): แถบบนพื้นสีเดียวกับ sidebar · ไม่มีโลโก้ ชื่อหน้าขึ้นต้นแถบ
   (2569-10-02 · เดิมพื้น primary ไอคอนขาว — เปลี่ยนตามหน้าแรก) */
@media (max-width: 991.98px) {
  .app-panel > .tb { background: var(--app-panel-bg); border-bottom: 0; }
}
@media (min-width: 1200px) {
  .app-panel-shell #sidebar { background: transparent !important; border: 0 !important; }
  #sidebar .app-panel-logo { display: flex; align-items: center; flex-shrink: 0; height: var(--app-header-h); margin: -6px 0 4px; }   /* pt-3 ของ offcanvas-body = 18px → ขอบบน 12px เท่าแผ่น */
  .app-panel { margin: 12px 12px 12px 0; min-height: calc(100vh - 24px); border-radius: 16px; }
  .app-panel > .tb { border-radius: 16px 16px 0 0; }
  .app-panel > main { border-radius: 0 0 16px 16px; }
  /* โลโก้หายจากแถบหัว ชื่อหน้าขึ้นต้นแถบ — ไม่ต้องมีเส้นคั่น · ชิดแนวเดียวกับเนื้อหา (16 + 8 = 1.5rem) */
  .app-panel .tb-title { padding-left: 8px; }
}

/* เมนูที่ยืนอยู่ในโหมดแผ่นขาว — แคปซูลฟ้าอ่อนแบบปุ่ม Ask Gemini (สีผู้ใช้กำหนด 2569-09-30)
   ไม่มีเงา ไม่มีแถบซ้าย (ทุกจอ รวม offcanvas) · utility bg-body-secondary เป็น !important จึงต้องสู้ด้วย !important */
:is(.app-panel-shell, .app-home-shell) #sidebar .nav-item-active,
:is(.app-panel-shell, .app-home-shell) #sidebar .nav-sub-active {        /* เมนูลูกที่ยืนอยู่ (ชั้น 2–3) ใช้แคปซูลเดียวกับเมนูหลัก */
  background: var(--app-active-bg) !important;
  color: var(--app-active-ink) !important;
  border-radius: 50rem !important;
}
:is(.app-panel-shell, .app-home-shell) #sidebar .nav-item-active::before { display: none; }
/* ชี้เมนูอื่น — พื้นเทาอ่อนทรงแคปซูลแบบ Drive (เฉพาะเครื่องที่ชี้ได้จริง ดู [22.3]) */
@media (hover: hover) and (pointer: fine) {
  :is(.app-panel-shell, .app-home-shell) #sidebar ul a:not(.nav-item-active):not(.nav-sub-active):hover,
  :is(.app-panel-shell, .app-home-shell) #sidebar ul button[data-bs-toggle="collapse"]:not(.sidebar-sub-toggle):hover {   /* หัวหมวด "จัดการรถ" ด้วย */
    background: rgba(31, 31, 31, .08) !important; border-radius: 50rem !important; }   /* สู้ rounded-2 / bg-transparent */
  :is(.app-panel-shell, .app-home-shell) #sidebar .sidebar-sub-toggle:hover { background: rgba(31, 31, 31, .08); border-radius: 50%; }
}
/* ไอคอนเมนูแบบ Drive — ไม่ใหญ่กว่าตัวหนังสือ (20px = ตัวไอคอนจริง ~16px เท่าข้อความ 1rem) เส้นบาง wght 300
   (แกน wght 300..400 อยู่ในฟอนต์ subset แล้ว — tools/subset_icons.py) · ลูกศรพับเมนู (.ico-sm) คงเดิม */
:is(.app-panel-shell, .app-home-shell) #sidebar .material-symbols-rounded:not(.ico-sm) {
  font-size: 20px;
  font-variation-settings: 'FILL' 0, 'wght' 300, 'GRAD' 0, 'opsz' 24;
}

/* [33] หน้าแบบ rgt — ฟอนต์ Google Sans ตัวเดียวกับทั้งระบบ · ฐาน 18px เท่าทั้งแอป (2569-10-02 ·
   เดิมฟอนต์ระบบ 16px เท่า rgt ลดที่รากด้วย :root:has — ถอดแล้ว) — 2569-09-30
   ฟอนต์ไอคอนของ sidebar/header ยังอยู่ (ของกลางทุกหน้า) — ในเนื้อหาใช้ _rgt.html icon() = Material Symbols เหมือนกัน (2569-10-04) */
.app-panel-shell { font-family: var(--bs-font-sans-serif); font-weight: 400; }
.rgt-i { font-size: 1.15em; width: 1em; height: 1em; overflow: hidden; vertical-align: -0.2em; }
.rgt-filter-toggle, .rgt-tools .btn, .rgt-searchbar .btn { display: inline-flex; align-items: center; gap: 6px; }
.rgt-scope .rgt-i { font-size: 1.1em; }

/* [34] หน้าแก้ไขแบบ rgt (user/edit · getButtonBar + legend + getProfileCard + getForm) — 2569-09-30
   ต้นแบบ: manage/edit.html · ค่าตาม global.css ของ rgt (.legend · .profile-card · form max 1280) */
.rgt-dd-i { display: flex; align-items: center; gap: 8px; }      /* ไอคอนหน้าข้อความใน ⋮ (bi … pe-1) */
.rgt-legend { font-size: 1.25rem; border-bottom: 1px solid rgba(0, 0, 0, .1);
              padding-bottom: 10px; margin: 15px 0; }
.rgt-legend.is-band { font-size: 1rem; font-weight: 500; color: #3d5a7a; background: #dbeaf6;
                      border: 0; border-radius: 2px; padding: 10px 16px; }
.rgt-profile-pic { width: 160px; padding-right: 20px; flex-shrink: 0; }
.rgt-profile-none { display: inline-flex; align-items: center; justify-content: center; width: 100px; height: 100px;
                     border-radius: 6px; background: #e9ecef; color: #adb5bd; }
.rgt-profile-none .material-symbols-rounded { font-size: 72px; font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24; }
.rgt-form { max-width: 1280px; }
.rgt-form .rgt-ms > .btn { text-align: left; }
.rgt-btnbar { display: flex; flex-wrap: wrap; margin-bottom: 4px; }
.rgt-btnbar .page-link { display: inline-flex; align-items: center; gap: 4px; }

/* [35] แจ้งเตือน · ป๊อปอัป · loading แบบ rgt (notify · getPopupForm · getPopupCard · getAlertCard · rgtLoading)
   ค่าตาม global.css ของ rgt · JS อยู่ท้าย rgt-list.js · ป๊อปอัปต่อท้าย <body> (นอก #appShell) */
.rgt-notify { position: fixed; z-index: 1070; top: 50px; left: 50%; transform: translate(-50%, -50%);
              text-align: center; transition: opacity 2s; pointer-events: none; }
.rgt-notify.out { opacity: 0; }
.rgt-notify-c { display: inline-block; padding: 10px 15px; border-radius: 10px;
                box-shadow: 0 4px 8px rgba(0, 0, 0, .3); font-size: 1rem; pointer-events: auto; }
.rgt-notify-success { background: #d1e7dd; color: #0f5132; border: 1px solid #badbcc; }
.rgt-notify-error   { background: #f8d7da; color: #842029; border: 1px solid #f5c2c7; }
.rgt-notify-warning { background: #fff3cd; color: #664d03; border: 1px solid #ffecb5; }
.rgt-notify-info    { background: #cff4fc; color: #055160; border: 1px solid #b6effb; }

.rgt-overlay { position: fixed; inset: 0; z-index: 1062; display: flex; align-items: center; justify-content: center;
               background: rgba(0, 0, 0, .5); font-family: var(--bs-font-sans-serif); }
body.rgt-noscroll { overflow: hidden; }
.rgt-modal { display: flex; flex-direction: column; background: var(--bs-body-bg);
             min-width: 300px; width: 90vw; max-width: 650px; max-height: 90%; }
.rgt-modal-h { position: relative; font-size: 1.25rem; font-weight: 600; padding: 1rem 3rem 1rem 1rem; }
.rgt-modal-x { position: absolute; top: 12px; right: 12px; border: 0; background: none; padding: 4px;
               line-height: 1; color: inherit; font-size: 1.1rem; cursor: pointer; }
.rgt-modal-body { overflow: auto; position: relative; }
@media (max-width: 649px) {
  .rgt-modal { width: 100vw; max-width: 100vw; max-height: 100%; border-radius: 0; }
}

.rgt-loader { width: 25px; height: 25px; margin: auto; border-radius: 50%;
              border: 4px solid #728bf1; border-top-color: transparent; animation: rgt-spin 1s linear infinite; }
.rgt-loader-w { border-color: #fff; border-top-color: rgba(255, 255, 255, .05); }
.rgt-loading-box { border-radius: 10px; background: rgba(0, 0, 0, .5); padding: 20px; }
.rgt-masked { position: relative; }
.rgt-mask { position: absolute; inset: 0; z-index: 1060; display: flex; align-items: center;
            background: rgba(255, 255, 255, .8); }
@keyframes rgt-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .rgt-loader { animation-duration: 3s; } .rgt-notify { transition: none; } }

/* [36] หน้าค่าน้ำมันแบบ rgt (2569-09-30) — แถบเงินสำรอง · สรุปข้อมูล · แถวที่เลือก · บิลในใบเบิก */
.fuel-cash { margin: 0 0 20px; }
.fuel-cash-num { color: var(--bs-secondary-color); font-size: .875rem; margin-bottom: 8px; }
.fuel-cash-num span { color: var(--bs-body-color); font-size: 2rem; line-height: 1.1; margin-right: 2px; }
.fuel-cash-bar { display: flex; gap: 2px; height: 8px; border-radius: 50rem; background: #f1f3f4; }
.fuel-seg { position: relative; display: block; height: 100%; border-radius: 50rem; outline: 0; cursor: default; }
.fuel-orange { background: var(--bs-orange) !important; }
/* tooltip แบบการ์ดของ Drive — ใต้ท่อน ชิดซ้าย · ชี้/โฟกัสแล้วขึ้น */
.fuel-tip { position: absolute; top: calc(100% + 10px); left: 0; z-index: 1025; width: 240px; padding: 14px 16px;
            border-radius: 12px; background: #e9eef6; color: var(--bs-body-color); text-align: center;
            box-shadow: 0 4px 12px rgba(0, 0, 0, .15); opacity: 0; visibility: hidden; pointer-events: none;
            transition: opacity .12s; }
.fuel-seg:hover .fuel-tip, .fuel-seg:focus-visible .fuel-tip { opacity: 1; visibility: visible; }
.fuel-seg:last-child:not(:first-child) .fuel-tip { left: auto; right: 0; }   /* ท่อนท้ายชิดขอบขวา — ไม่ล้นจอ */
.fuel-tip-k { display: block; font-size: .75rem; letter-spacing: .06em; color: var(--bs-secondary-color); }
.fuel-tip-v { display: block; font-size: 1.75rem; line-height: 1.3; margin: 2px 0 4px; }
.fuel-tip-d { display: block; font-size: .8125rem; color: var(--bs-secondary-color); }
@media (prefers-reduced-motion: reduce) { .fuel-tip { transition: none; } }
.fuel-cash-legend { display: flex; flex-wrap: wrap; gap: 4px 24px; margin-top: 10px; font-size: .8125rem; }
.fuel-cash-legend a, .fuel-cash-legend > span { display: inline-flex; align-items: center; gap: 8px; color: inherit; text-decoration: none; }
.fuel-cash-legend a:hover { text-decoration: underline; }
/* การ์ดงบรายกองบนหน้ารายการรออนุมัติ — พื้นสีเดียวกับ sidebar · รางแถบเป็นขาว (เทาจมหายบนพื้นนี้) */
.appr-budget { background: var(--app-panel-bg, var(--bs-tertiary-bg)); }
.appr-budget .fuel-cash { margin: 0; }
.appr-budget .fuel-cash-bar { background: #fff; }
/* มือถือ: หัวการ์ดงบเป็นปุ่มพับ เหลือแค่ชื่อกอง (2569-10-03) */
.appr-budget-tg { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%;
  padding: 12px 16px; border: 0; background: none; color: inherit; text-align: start; }
.appr-budget-tg .material-symbols-rounded { color: var(--bs-secondary-color); transition: transform var(--mo-base, .18s); }
.appr-budget-tg:not(.collapsed) .material-symbols-rounded { transform: rotate(180deg); }
.pk-list .pk-trip > .material-symbols-rounded { justify-self: center; }
.appr-note { min-width: 13rem; }   /* เหตุผลไม่อนุมัติ — ตารางบีบแล้วหักทีละคำ */
.fuel-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.fuel-sum { min-width: 280px; padding: 12px 16px; }   /* สรุปข้อมูลของหน้า OT ใช้ด้วย */
/* ใบเบิก (แบบใบเบิกพัสดุ rgt · 2569-10-03) — หัวใบ: เลขที่ + ป้าย ซ้าย · ปุ่มขั้นถัดไป ขวา · ฟอร์มติ๊กบิล */
.fc-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px;
           padding: 12px 0; margin-bottom: 12px; border-bottom: 1px solid rgba(0, 0, 0, .1); }
.fc-head > div:first-child { display: flex; align-items: center; gap: 10px; }
.fc-title { font-size: 1.25rem; font-weight: 600; margin: 0; }
.fc-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.rgt-t tr.cf-row { cursor: pointer; }
.rgt-t tr.cf-row.is-checked td { background: var(--bs-primary-bg-subtle); }

/* [37] กล่องรูปแบบ rgt (upload_picture ≈ getUploadFile + getShowFile · 2569-10-01)
   จัตุรัสมุมมน กว้างเต็มคอลัมน์ · รูปตัดพอดีกล่อง (cover) · ปุ่มเปลี่ยน/ลบลอยมุมล่างขวา */
.rgt-pic { position: relative; width: 100%; aspect-ratio: 1 / 1; border-radius: 12px; overflow: hidden;
           background: #f1f3f4; }
.rgt-pic-img, .rgt-pic-img img { display: block; width: 100%; height: 100%; object-fit: cover; }
.rgt-pic-drop { height: 100%; margin: 0; }
.rgt-pic-box { height: 100%; margin: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
               gap: 4px; padding: 8px; text-align: center; border: 2px dashed #c4c7c5; border-radius: 12px;
               color: #444746; cursor: pointer; transition: background .15s, border-color .15s; }
.rgt-pic-box .rgt-i { font-size: 2.2rem; margin-bottom: 4px; }
.rgt-pic-box:hover, .rgt-pic-box.is-over { background: #e8f0fe; border-color: var(--bs-primary); color: var(--bs-primary); }
.rgt-pic-none, .rgt-pic-none:hover { cursor: default; background: transparent; border-color: #c4c7c5; color: var(--bs-secondary-color); }
.rgt-pic-tools { position: absolute; right: 8px; bottom: 8px; display: flex; gap: 6px; }
.rgt-pic-tools form { margin: 0; }
.rgt-pic-tools .btn { box-shadow: 0 1px 3px rgba(0, 0, 0, .2); }
/* รูปย่อในแถวตาราง (ภาพหน้าปัดของหน้าเลขไมล์) — จัตุรัสมุมมนเท่าความสูงแถว กดแล้วเปิดขนาดเต็ม */
.rgt-thumb { display: inline-block; width: 40px; height: 40px; border-radius: 8px; overflow: hidden;
             background: #f1f3f4; vertical-align: middle; }
.rgt-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* ภาพวัสดุอุปกรณ์ — ช่องในตาราง (ไม่มีภาพ = ไอคอน กดเพิ่ม · มีภาพ = ดินสอมุม กดเปลี่ยน) + ช่องเลือกภาพบนหน้าแก้ไข */
.mat-pic { position: relative; display: inline-block; vertical-align: middle; }
.mat-pic form { margin: 0; }
.mat-pic-none { display: inline-flex; align-items: center; justify-content: center; color: #9aa0a6; margin: 0; }
.mat-pic-add { cursor: pointer; border: 1px dashed #c4c7c5; }
.mat-pic-add:hover { color: var(--bs-primary); border-color: var(--bs-primary); background: #e8f0fe; }
.mat-pic-edit { position: absolute; right: -6px; bottom: -6px; width: 20px; height: 20px; margin: 0; border-radius: 50%;
                display: flex; align-items: center; justify-content: center; cursor: pointer;
                background: #fff; color: #5f6368; box-shadow: 0 1px 3px rgba(0, 0, 0, .3); }
.mat-pic-edit .rgt-i { font-size: 13px; }
.mat-pic-edit:hover { color: var(--bs-primary); }
.mat-pic-pick { width: 120px; height: 120px; margin: 0; border-radius: 12px; overflow: hidden; cursor: pointer;
                display: flex; align-items: center; justify-content: center;
                background: #f1f3f4; border: 2px dashed #c4c7c5; color: #9aa0a6; }
.mat-pic-pick.has-pic { border-style: solid; border-color: transparent; }
.mat-pic-pick:hover { border-color: var(--bs-primary); color: var(--bs-primary); }
.mat-pic-pick img { width: 100%; height: 100%; object-fit: cover; }
.mat-pic-pick .rgt-i { font-size: 2.2rem; }

/* [38] แจ้งซ่อมแบบ rgt (หน้าผู้ใช้ + โต๊ะงานซ่อม · 2569-10-01)
   ภาพหน้าแถว — ทรงเดียวกับ .rgt-thumb · มีภาพหลังซ่อม = แบ่งครึ่ง ขวาเขียว */
.repair-thumb { display: inline-flex; width: 40px; height: 40px; padding: 0; border: 0; border-radius: 8px;
                overflow: hidden; background: #f1f3f4; color: #5f6368; vertical-align: middle; position: relative; }
.repair-thumb > span { flex: 1; display: flex; align-items: center; justify-content: center; }
.repair-thumb .is-none { color: #bdc1c6; }
.repair-thumb > img { width: 100%; height: 100%; object-fit: cover; }
/* มีภาพหลังซ่อม = ป้ายเขียวมุมขวาล่างทับรูป */
.repair-thumb > img ~ .is-after { position: absolute; right: 0; bottom: 0; width: 16px; height: 16px; flex: none; border-radius: 6px 0 0 0; }
.repair-thumb > img ~ .is-after .rgt-i { font-size: 13px; vertical-align: 0; }
.repair-thumb .is-after { background: var(--green-soft); color: var(--green-ink); }
.repair-thumb:hover { filter: brightness(.95); }
/* มือถือ (< md · 2569-10-03): ตาราง → แถว .pk ทรงเดียวกับ "งานซ่อม" หน้าแรก (คลาสอยู่ [41])
   แตะแถว = เปิด #repairPhotoModal (_js.html) · ⋮ ขวาเป็นเมนูเดิม */
.repair-m-bar { padding: 4px 0 10px; margin-bottom: 14px; border-bottom: 1px solid #eef0f3; }
.pk-list .repair-card { cursor: pointer; }
/* ⋮ ขวา — ชนะ .pk-list .st-side .pk-top ของปฏิทิน */
.pk-list .st-side .repair-card .pk-top { grid-template-columns: 56px minmax(0, 1fr) auto; }
.pk-list .repair-card .pk-t { overflow-wrap: anywhere; }
.pk-list + .rgt-pgn { margin-top: 12px; }
.pk-list .pk-unsafe { color: var(--hm-red); }   /* เรื่องที่ฉันแจ้ง (งานขับรถของฉัน): รถไม่ควรใช้ แดงแม้แถวโทนอื่น */
.pk-list .st-side > :is(.collapse, .collapsing) > .pk:first-child { border-top: 1px solid var(--hm-line); }   /* แถวที่พับไว้ต่อเส้นกั้นกับแถวบน */
.pk-list .pk-more[aria-expanded="true"] .pm-off, .pk-list .pk-more[aria-expanded="false"] .pm-on { display: none; }
/* อนุมัติรถบนมือถือ (2569-10-03): แถว .pk ของปฏิทินจองรถ + งบ + ปุ่มอนุมัติ · checkbox ขวาบน
   ยื่นซ้าย-ขวา 8px ให้พื้นตอนเลือก (.is-checked [12.1]) ไม่ชิดขอบตัวหนังสือ */
.pk-list .job-card { padding-inline: 12px; border-radius: 12px; }
.pk-list .st-side .job-card .pk-top { grid-template-columns: 56px minmax(0, 1fr) auto; row-gap: 10px; }
.pk-list .job-card .job-check { margin: 2px 0 0; }
.pk-list .pk-budget { display: flex; align-items: center; gap: 6px; margin-top: 6px; font-size: .75rem; color: #3c4043; }
.pk-list .pk-bt { flex: none; padding: 0 8px; border: 1px solid #dadce0; border-radius: 999px; line-height: 1.6; }
.pk-list .job-card .js-detail { cursor: pointer; }
/* คำขอย่อยของงานร่วม (มือถือ) — กริดเดียวกับ .pk-top · ✕ ฟ้าในเสาวงแหวน · ระยะระหว่างใบแคบกว่า detailModal */
.pk-list .pk-trip { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: 14px; padding-top: 10px; margin-top: 10px;
  border-top: 1px dashed var(--hm-line); }
.pk-list .pk-trip-x { justify-self: center; align-self: start; margin-top: 4px; color: var(--hm-blue); line-height: 1; }
.pk-list .pk-trip-x:hover { color: var(--hm-blue); opacity: .75; }   /* กดชื่อ = detailModal · ที่เหลือของแถว = เลือก */
/* ตาราง (จอ md ขึ้นไป) ใช้คำขอย่อยชุดเดียวกัน — ไม่มีวงแหวน เสา ✕ เหลือเท่าไอคอน */
.pk-sub .pk-trip { grid-template-columns: 20px minmax(0, 1fr); gap: 8px; }
.pk-sub .pk-trip-x { justify-self: start; }
.pk-list .pk-act { grid-column: 2 / -1; display: flex; align-items: center; gap: 8px; }
.pk-list .pk-more { display: inline-flex; align-items: center; gap: 2px; font-size: .8125rem; color: var(--hm-blue); text-decoration: none; }
.pk-list .pk-more[aria-expanded="true"] .hm-i { transform: rotate(180deg); }
/* เสร็จแล้ว: ช่างแก้อะไร — กล่องเขียวอ่อนใต้แถว (มือถือ · ตารางแยกคอลัมน์ .repair-fix-cell) ตัด 2 บรรทัด เต็มอยู่ใน modal ภาพ */
.repair-fix { display: flex; gap: 6px; align-items: flex-start; margin-top: 6px; padding: 4px 8px; border-radius: 6px;
  background: var(--green-soft); color: var(--green-ink); font-size: .75rem; line-height: 1.45; }
.repair-fix > .rgt-i { flex: none; font-size: 14px; margin-top: 2px; }
.repair-fix > span { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* เสร็จแล้ว = ทั้งแถวพื้นสีเดียวกับ sidebar แผ่นขาว (ทาที่ td เพราะคอลัมน์ปักหมุดมีพื้นของตัวเอง) */
.rgt-t tr.repair-row.is-done td,
.rgt-t tr.job-row.is-done td { background: var(--app-panel-bg, rgb(247, 249, 252)); }
.repair-fix-cell { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
/* แถบผู้ติดต่อฉุกเฉินบนหน้าแจ้งซ่อมของผู้ใช้ — ทรงเดียวกับ .rgt-scope โทนแดง */
.repair-sos { background: #fce8e6; color: #a50e0e; }
.repair-sos a { color: inherit; font-weight: 600; }
.repair-sos-p { display: inline-block; margin-left: 12px; white-space: nowrap; }

/* [40] detailModal ของปฏิทินจองรถ — หัวแบบการ์ด + แถบล่างพื้นฟ้า (2569-10-01 · ไม่ใช้ head())
   แถบล่างใช้ primary 8% บนพื้นขาว (≈ #EEF4FF) จึงตามสีหลักเสมอ ไม่ต้องตั้ง token ใหม่ */
.dt-ico { width: 44px; height: 44px; background: var(--blue-soft); color: var(--blue-ink); }
.dt-ico .material-symbols-rounded, .dt-fill { font-variation-settings: "FILL" 1; }
.dt-ico-sm { width: 44px; height: 44px; }
.dt-pill {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  border-radius: 999px; padding: 4px 12px; font-size: var(--fs-xs); font-weight: 600;
}
.dt-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
/* สีของป้ายเมื่อหน้าไม่ได้ส่งสีเอง (modal ภาพงานซ่อม · 2569-10-03) — จุดตามสีตัวหนังสือ */
.dt-tone-secondary { background: var(--st-info-soft); color: var(--st-info-ink); }
.dt-tone-warning   { background: var(--st-wait-soft); color: var(--st-wait-ink); }
.dt-tone-primary   { background: var(--st-ok-soft);   color: var(--st-ok-ink); }
.dt-tone-success   { background: var(--st-done-soft); color: var(--st-done-ink); }
[class*="dt-tone-"] .dt-dot { background: currentColor; }
.dt-title { line-height: 1.35; margin-top: 2px; text-wrap: balance; }
.dt-spec { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.dt-spec > div { min-width: 0; padding: 0 10px; }
.dt-spec > div:first-child { padding-left: 0; }
.dt-spec > div + div { border-left: 1px solid var(--bs-border-color); }
/* จอแคบให้ขึ้นบรรทัดใหม่ (ตัดที่ – ได้) ไม่ตัดเป็น … — เวลาที่หายครึ่งอ่านผิดได้ */
.dt-spec .fw-medium { font-variant-numeric: tabular-nums; }
.dt-band { background: rgba(var(--bs-primary-rgb), .08); }
.dt-chip {
  display: inline-flex; align-items: center; gap: 4px; border-radius: 6px; padding: 2px 8px;
  background: var(--bs-secondary-bg); font-size: var(--fs-xs); font-variant-numeric: tabular-nums;
}
.dt-chip .material-symbols-rounded { font-size: 1.2em; }   /* ไอคอนเท่าความสูงตัวหนังสือในชิป */
.dt-chip-me { background: var(--blue-soft); color: var(--blue-ink); font-weight: 600; }
/* detailModal ของจองรถ ทรงใหม่ (2569-10-15) — เส้นเวลา + ป้ายทะเบียน · แถบล่างพื้นฟ้าเหลือแค่ห้องประชุม/ภาพงานซ่อม */
.dt-time { font-variant-numeric: tabular-nums; flex-shrink: 0; }
/* แถบฟ้าเข้มรอผู้ประสานงาน · ไม่เลื่อนตาม modal-body · ตัวขาวบน blue-ink = 4.85:1 (บน primary แค่ 3.9 ไม่ผ่าน) */
.dt-banner { background: var(--blue-ink); color: #fff; flex-shrink: 0; }
.dt-banner-x { color: #fff; }
.dt-acts:not(:has(> :not(.d-none))) { display: none !important; }   /* ไม่มีปุ่มของหน้าที่เห็น = ไม่เว้นแถวว่าง */
.dt-banner-x:hover, .dt-banner-x:focus-visible { color: #fff; background: rgba(255, 255, 255, .18); }
.dt-plate { min-width: 7.5rem; }
/* modal อนุมัติรถ (ทรง detailModal + ฟอร์มจองรถ · 2569-10-16) — ช่องที่เลือกแล้ว/ป้ายทะเบียน กดเพื่อล้าง · ล็อก = งานนอกระบบ */
#assignModal :is(.as-chip, .as-plate) { cursor: pointer; }
#assignModal .as-chip .form-control { background: var(--bs-secondary-bg); }
#assignModal :is(.as-chip, .as-plate).is-locked { cursor: default; opacity: .75; }
/* modal เพิ่มงาน (ทรงเดียวกับ assignModal · 2569-10-16) — กลุ่มห่างเท่าฟอร์มจองรถ (mb-4) แต่ใช้ gap: กลุ่มที่ซ่อนตามชนิดงานไม่กินที่
   หัวสีตามสถานะที่ใบจะได้: ขับรถ = อนุมัติแล้ว (ok) · ล้างรถ = รอล้าง (wait) */
#dispatchModal .dp-groups { display: flex; flex-direction: column; gap: 1.5rem; }
#dispatchModal .dp-kicker { color: var(--st-ok-ink); }
#dispatchModal .dp-kicker.is-wash { color: var(--st-wait-ink); }
#dispatchModal .dp-step { width: 34px; height: 34px; }
/* ช่องเวลามีไอคอนนาฬิกาของเราแล้ว — ซ่อนนาฬิกาของเบราว์เซอร์ (สองอันซ้อน + มือถือกินที่จนตัวเลขขาด) · กดช่อง = เปิดตัวเลือก (JS showPicker) */
#dispatchModal input[type="time"] { cursor: pointer; }
#dispatchModal input[type="time"]::-webkit-calendar-picker-indicator { display: none; }
#dispatchModal .dp-hit { background: var(--st-bad-soft); color: var(--st-bad-ink); }
#dispatchModal .dp-people { max-height: 190px; }   /* ผลค้นหาผู้จอง — เลื่อนในกล่อง ไม่ดัน modal ยาว */
/* ฉากรอ (.is-wait · ยังไม่มีรถ: รออนุมัติ · ไม่ได้รับอนุมัติ) — Commuter จอดรอหน้าไม้กั้น ฉากเทา ไฟเหลืองกะพริบ แขนขยับทีละนิด
   ไฟ + แขนไม้กั้นเป็นสีเดียวในฉาก = ตาไปที่ "รออยู่ตรงนี้" · ตัวรถเด้งเบาแบบติดเครื่อง ล้อไม่หมุน */
.dt-sheet .ln-wait { display: none; }
.dt-sheet .is-wait .ln-wait { display: block; }
.dt-sheet .is-wait :is(.ln-bush, .ln-wait .hm-art) { filter: grayscale(1); opacity: .8; }
.dt-sheet .is-wait .ln-sign { background: #8A94A3; max-width: 38%; }   /* ป้ายยาวไม่ทับไฟของไม้กั้นบนจอแคบ */
.dt-sheet .is-wait .ln-wait .hm-art { left: 12%; animation: none; }
.dt-sheet .ln-wait .hm-art .wheel { animation: none; }
.dt-sheet .ln-gate { position: absolute; z-index: 2; bottom: 56px; left: calc(12% + 84px); line-height: 0; }
.dt-sheet .gt-lamp { animation: dt-blink 1.2s ease-in-out infinite; }
.dt-sheet .gt-arm { transform-origin: 52px 16px; animation: dt-arm 2.6s var(--ease-in-out) infinite; }
@keyframes dt-blink { 50% { opacity: .25; } }
@keyframes dt-arm { 0%, 70%, 100% { transform: rotate(0); } 80% { transform: rotate(-9deg); } 90% { transform: rotate(0); } }
@media (prefers-reduced-motion: reduce) { .dt-sheet :is(.gt-lamp, .gt-arm) { animation: none; } }
/* ลำดับ 4 ชั้น: ปลายทาง (3xl) > เวลา (2xl) > เนื้อความ (ฐาน) > ข้อความรอง (sm เทา) · ตัวหนาเหลือ ชื่อ · เวลา · ทะเบียน · ชื่อผู้ขอ
   ระยะระหว่างก้อน (หัว · เวลา · รถ+ฉาก · ผู้ขอ · ปุ่ม) = --dt-gap ค่าเดียว — ในก้อนชิดกัน (mt-1/mt-2) */
.dt-sheet { --dt-gap: 1.25rem; }
.dt-sheet .dt-sec { margin-top: var(--dt-gap); }
.dt-sheet .dt-foot { padding-top: var(--dt-gap); }
/* มือถือ: ฐาน 18px ใหญ่ไปสำหรับใบนี้ — ลดทั้งชุดหนึ่งขั้น (เนื้อความ 15 · รอง 13) ระยะก้อนแคบลง */
@media (max-width: 575.98px) {
  .dt-sheet { --dt-gap: .875rem; font-size: var(--fs-md); }
  .dt-sheet .dt-title { font-size: var(--fs-2xl); }
  .dt-sheet .dt-time { font-size: var(--fs-xl); }
  .dt-sheet .fs-sm { font-size: var(--fs-xs); }
}
/* ฉากรถวิ่งบนทางยกระดับ (ภาพเดียวกับหน้าแรก · ผู้ใช้สั่ง 2569-10-15) — ชนขอบ modal เท่าระยะขอบของ modal-body */
.dt-sheet .tc-lane { margin: 0 -1rem; }
@media (min-width: 576px) { .dt-sheet .tc-lane { margin: 0 -1.5rem; } }
/* detailModal ขอใช้ห้อง (_room_detail.html · 2569-10-16) — แถบเวลาของห้องทั้งวันแทนฉากรถ
   ภาษาเดียวกับแถบห้องว่างบนหน้าแรก: เขียวอ่อน = ว่าง · เทา = จองแล้ว · ส้มอ่อน = รออนุมัติ · เส้นแดง = ตอนนี้
   ใบที่เปิดอยู่ = สีทึบตามขั้นสถานะ (--st-*) ยกสูงกว่าใบอื่นนิดเดียวให้ตาจับได้ */
.dt-bar { position: relative; height: 24px; border-radius: 6px; background: var(--st-done-soft); }
.dt-bar span { position: absolute; top: 3px; bottom: 3px; background: #DADCE0; border-radius: 3px; }
.dt-bar .is-wait { background: var(--st-wait-soft); box-shadow: inset 0 0 0 1px var(--st-wait); }
.dt-bar .is-this { top: 0; bottom: 0; z-index: 1; }
.dt-bar .st-wait { background: var(--st-wait); }
.dt-bar .st-ok   { background: var(--st-ok); }
.dt-bar .st-done { background: var(--st-done); }
.dt-bar .now { top: -3px; bottom: -3px; width: 2px; margin-left: -1px; border-radius: 0; background: #D93025; z-index: 2; }
.dt-ticks { position: relative; height: 1.4em; margin-top: 2px; font-variant-numeric: tabular-nums; }
.dt-ticks span { position: absolute; transform: translateX(-50%); }
.dt-ticks .is-start { transform: none; }          /* ขีดชนขอบแถบไม่ล้นออกนอก modal */
.dt-ticks .is-end { transform: translateX(-100%); }
/* detailModal งานซ่อม (#repairPhotoModal · 2569-10-16) — ป้ายประเภทแทนป้ายทะเบียน · ภาพก่อน | หลัง ชนขอบแทนฉากรถ
   ค้างเกินกำหนด = แถบแดง (ตัวขาวบน --st-bad = 5.6:1) · ยังไม่มีภาพ = ช่องเทา บอกว่ารออะไร */
.dt-banner-bad { background: var(--st-bad); }
.rp-cat { min-width: 4.5rem; }
.rp-photos { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; margin: 0 -1rem; }
@media (min-width: 576px) { .rp-photos { margin: 0 -1.5rem; } }
.rp-ph { position: relative; display: flex; align-items: center; justify-content: center; height: 200px;
         overflow: hidden; background: var(--bs-secondary-bg); color: var(--bs-secondary-color); text-decoration: none; }
.rp-ph > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.rp-ph-tag { position: absolute; z-index: 1; left: 8px; top: 8px; padding: 2px 10px; border-radius: 999px;
             background: rgba(255, 255, 255, .92); color: var(--bs-body-color); font-size: var(--fs-xs); font-weight: 600; }
a.rp-ph:hover > img { filter: brightness(.94); }
a.rp-ph:focus-visible { outline: 2px solid var(--bs-primary); outline-offset: -2px; }
@media (max-width: 575.98px) { .rp-ph { height: 150px; } }
.rp-urgent { background: var(--st-bad-soft); color: var(--st-bad-ink); font-weight: 600; }

/* [41] หน้าแรกแบบ Google News (shell='home' · 2569-10-02) — ไม่มี sidebar · ฐาน 18px · Google Sans
   แถบบน (.tb · [32.0]) · หัวทักทาย + ชิปเดินทาง (.tc · ≈ ช่องอากาศ) · บอร์ด (.st · ≈ Top stories)
   ติดตามงาน (.pk · ≈ Picks for you) · สีตัวหนังสือบนชิปตามช่องอากาศของ Google (ผู้ใช้กำหนด)
   ไอคอนเป็น Material Symbols ของกลาง (.hm-i คุมขนาดด้วย font-size) · พื้นสีเดียวกับ sidebar แผ่นขาว */
.app-home-shell, .pk-list, .notif-panel, .hm-menu {
  --hm-ink: #202124; --hm-mut: #5F6368; --hm-faint: #9AA0A6; --hm-line: #E3E6EB; --hm-soft: #F1F3F4;
  --hm-blue: #1A73E8; --hm-blue-soft: #E8F0FE; --hm-green: #137333; --hm-green-soft: #E6F4EA;
  --hm-amber: #B06000; --hm-amber-soft: #FEF7E0; --hm-red: #C5221F; --hm-red-soft: #FCE8E6;
  --hm-violet: #8430CE; --hm-violet-soft: #F3E8FD;
  --hm-page: rgb(247, 249, 252);     /* = --app-panel-bg ของ sidebar แผ่นขาว */
}
/* .pk-list = แถวแบบ "ติดตามงาน" นอกหน้าแรก (รายการวันที่เลือกของปฏิทินจองรถบนมือถือ · 2569-10-03) */
.app-home-shell {
  font-weight: 400; color: var(--hm-ink); min-height: 100vh; background: var(--hm-page);
}
/* พื้นอาคารลายเส้นจางชิดขวาล่าง (2569-10-07) — เป็นพื้นของ shell ไม่ใช่ element ซ้อน
   (ซ้อนต้องสร้าง stacking context = modal ในหน้าจมใต้ backdrop) · ความจาง/การไล่อยู่ในไฟล์ svg */
@media (min-width: 768px) {
  /* ลายเส้นจางกว่าหน้า login — ทาสีพื้นโปร่ง 55% ทับภาพอีกชั้น · ตึกขวา (login ตึกซ้าย) */
  .app-home-shell { background: linear-gradient(rgb(247 249 252 / .55), rgb(247 249 252 / .55)) fixed,
    url("/static/img/home-building.svg?v=2") right bottom / cover no-repeat fixed, var(--hm-page); }
}
:is(.app-home-shell, .pk-list) .hm-i { font-size: 1.25em; line-height: 1; flex: none; }
.hm-small { font-size: .8125rem; }

/* เมนูบัญชี — dropdown ของ Bootstrap */
.hm-menu { --bs-dropdown-font-size: .9375rem; min-width: 240px; }
.hm-menu .dropdown-item { display: flex; align-items: center; gap: 10px; padding: 8px 16px; }
.hm-menu .material-symbols-rounded { color: var(--hm-mut); }
.hm-menu .text-danger .material-symbols-rounded { color: inherit; }
.hm-menu .dropdown-header { padding: 8px 16px 4px; font-size: .75rem; font-weight: 500; color: var(--hm-mut); }
.hm-menu-me { padding: 6px 16px 4px; }
/* กระดิ่งจอกว้าง ทรงเดียวกับเมนูบัญชี (_notif_bell.html · 2569-10-08) — แถวแบบ dropdown-item ไม่มีเส้นคั่น */
.notif-menu { width: 380px; }
.notif-menu .notif-head { padding: 8px 16px 4px !important; font-size: .75rem; font-weight: 500; color: var(--hm-mut) !important; }
.notif-menu .notif-row { border-top: 0 !important; padding: 8px 16px !important; }
.notif-menu .notif-row:hover { background: var(--bs-dropdown-link-hover-bg); }
.notif-menu .ico-tint .material-symbols-rounded { color: inherit; }
/* เนื้อหา — กว้างสุด 1140 วางกลาง · sidebar เป็น offcanvas ทุกจอ (กัน [8] ที่ทำให้ sticky) */
main.app-main.app-home-main { max-width: 1188px; margin: 0 auto; padding-top: 32px !important; }
@media (min-width: 1200px) {
  .app-home-shell #sidebar { position: fixed; top: 0; height: 100vh; }
}
/* แถบบริการ = chapternav ของ Apple (หน้าอุปกรณ์เสริม · 2569-10-07): ไอคอนทึบ 40 ดำ · ชื่อ 14px หนา 600 ห่างใต้ไอคอน 12
   ช่องกว้างตามชื่อ (ไม่ fix) ห่างกัน 40 · ช่องแรกชิดซ้ายตรงขอบชื่อ · ห่างหัวทักทาย 72 (56 + 16) · ล่าง 24 + 52 ก่อนการ์ด
   เลื่อนแนวนอนไม่มีแถบเลื่อน */
.hm-cats { display: flex; gap: 40px; overflow-x: auto; scrollbar-width: none; padding: 8px 0 12px; margin-bottom: 32px; }   /* แน่นขึ้น 2569-10-15 (เดิม 16/24 + 52) */
.hm-cats::-webkit-scrollbar { display: none; }
.hm-cats > a { flex: none; display: flex; flex-direction: column; align-items: center; text-align: center; white-space: nowrap;
  font-size: 14px; font-weight: 600; line-height: 1.3; color: #1d1d1f; text-decoration: none; }
.hm-cats .material-symbols-rounded { display: flex; align-items: center; justify-content: center; height: 44px;
  margin-bottom: 12px; font-size: 40px; color: #1d1d1f;
  font-family: "Material Symbols Rounded Svc"; font-variation-settings: normal; }   /* ฟอนต์ตรึง wght 200 · GRAD 200 (tools/subset_icons.py) */
@media (max-width: 767.98px) { .hm-cats { gap: 32px; margin-inline: -1rem; padding-inline: 1rem; } }   /* เลื่อนชนขอบจอ (main p-3) แบบ Apple */
/* มือถือ ≤ 4 บริการ = กระจายเต็มความกว้าง · 5 ขึ้นไป = เรียงชิดซ้ายเลื่อนได้แบบเดิม (gap เล็กลงไว้กันจอแคบล้น — ล้นก็ยังเลื่อนได้) */
@media (max-width: 767.98px) { .hm-cats:not(:has(> a:nth-child(5))) { justify-content: space-between; gap: 12px; } }
@media (hover: hover) and (pointer: fine) { .hm-cats > a:hover { color: #06c; } }
/* หัวทักทาย = hero ของ Apple Store (2569-10-07): ชื่อ clamp 48–80 หนา 600 · บน 72 (32 ของ main + 40) ล่าง 56 · gap 32
   line-height 1.15 ไม่ใช่ 1.05 ของ Apple — สระบน/วรรณยุกต์ไทยซ้อนกันถูกตัด */
/* ลดลง 2569-10-15: ชื่อคนไม่ใช่ของที่มาดู — 40 สูงสุด (เดิม 48 ใหญ่กว่าหัวการ์ด 28 เกือบเท่าตัว) · บน 24 ล่าง 36 (เดิม 40/56) */
.hm-hello { display: flex; justify-content: space-between; align-items: flex-end; gap: 32px; padding-top: 24px; margin-bottom: 36px; }
.hm-h1 { font-size: clamp(28px, 3.2vw, 40px); font-weight: 600; letter-spacing: -.015em; line-height: 1.15; margin: 0; }
.hm-date { margin: 6px 0 0; color: var(--hm-mut); font-size: .875rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* ↑ ห้ามห่อ — ตั๋วกางแล้วบรรทัดนี้แคบลงทีละเฟรม ถ้าห่อได้หัวทักทายจะสูงขึ้นกลางทาง ทั้งหน้ากระตุก */
/* การ์ด = การ์ดของ Apple Store (2569-10-07): มุม 18 · เงา 2/4/12 · ใน 28/30 · หัว 28px หนา 600 ดำ (ไม่มีเส้นใต้)
   บรรทัดสรุปเป็นลิงก์ 17px สีลิงก์ Apple · ห่างกัน 20 (= gap ของชั้นวาง) · ไม่ขยายตอนชี้ (ในการ์ดมีลิงก์/ปุ่มหลายตัว) แค่เงาเข้ม */
.hm-grid { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 20px; align-items: start; }
.hm-card { background: #fff; border-radius: 18px; padding: 28px 30px; box-shadow: 2px 4px 12px rgb(0 0 0 / .08);
  transition: box-shadow 300ms var(--ease-out); }
@media (hover: hover) and (pointer: fine) { .hm-card:hover { box-shadow: 2px 4px 16px rgb(0 0 0 / .16); } }
.hm-card-h { font-size: 28px; font-weight: 600; line-height: 1.14; letter-spacing: -.01em; color: #1d1d1f; margin: 0 0 8px; }
.hm-board { display: grid; gap: 20px; }
.hm-rail { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; }   /* ไม่ให้ของข้างในดันรางกว้างเกินจอ (มือถือเคยล้นขวา 10px) */
/* ทางลัดจองรถ = .val ของ Apple Store: ไอคอนเส้นบนซ้าย · หัว 24/600 · คำอธิบาย 15 · ปุ่ม + ดำ 36 มุมขวาล่าง
   ทั้งใบกดได้ → ชี้ = ขยาย 1.01 + เงาเข้ม · กด = ยุบ .985 (การ์ดนี้ไม่มีลิงก์ข้างใน ขยายได้ไม่เบลอ) */
.hm-card.hm-val { position: relative; display: block; padding: 30px 30px 64px; color: #1d1d1f; text-decoration: none;
  background: #ebebf0; box-shadow: none;   /* พื้นเทาแบบการ์ดของ Apple · #f5f5f7 ของ Apple กลืนกับพื้นหน้า (--hm-page) จึงเข้มขึ้นหนึ่งขั้น */
  transition: transform 300ms var(--ease-out), box-shadow 300ms var(--ease-out); }
.hm-val:active { transform: scale(.985); }
.hm-val-ic { display: block; font-size: 40px; font-weight: 300; margin-bottom: 28px; }
/* ไม่มีทริป (2569-10-09) = ภาพคนลากกระเป๋าซ้าย (สูงเกือบเต็มการ์ด) + คำถามกลางแนวตั้ง · สีมาจาก mask จึงตาม --bs-primary */
.hm-val:has(.hm-val-art) { display: grid; grid-template-columns: 124px 1fr; column-gap: 16px; align-items: center;
  padding: 16px 20px 16px 16px; min-height: 180px; }
.hm-val-art { width: 124px; height: 156px; background: var(--bs-primary);
  -webkit-mask: url(img/carrying-luggage.svg) center / contain no-repeat; mask: url(img/carrying-luggage.svg) center / contain no-repeat; }
.hm-val:has(.hm-val-art) h2 { font-size: 17px; line-height: 1.35; margin: 0 0 24px; }   /* +ปุ่มมุมล่าง = ดันขึ้นเล็กน้อยให้กลางตา · ห่อได้เฉพาะรอยต่อก้อนคำ (inline-block ใน home.html) */
.hm-val-big { display: block; font-size: 32px; line-height: 1.15; margin-bottom: 4px; }
.hm-val h2 { font-size: 24px; font-weight: 600; line-height: 1.2; letter-spacing: -.01em; margin: 0 0 12px; }
.hm-val p { font-size: 15px; line-height: 1.4; margin: 0; }
.hm-val-add { position: absolute; right: 20px; bottom: 20px; width: 36px; height: 36px; border-radius: 50%;
  display: grid; place-items: center; background: #1d1d1f; color: #fff; transition: background-color 150ms ease; }
.hm-val-add .material-symbols-rounded { font-size: 24px; }
@media (hover: hover) and (pointer: fine) {
  .hm-val:hover { color: #1d1d1f; transform: scale(1.01); }
  .hm-val:hover .hm-val-add { background: #000; }
}
/* ปุ่ม "ดู…" = ลิงก์ด่วนของ Apple: แคปซูลเส้นเทา 14px ชิดขวาของการ์ด · ชี้ = ทึบดำ */
.hm-more { display: flex; width: fit-content; margin-left: auto; align-items: center; margin-top: 24px; padding: 10px 20px; border: 1px solid #86868b;
  border-radius: 980px; color: #1d1d1f; font-size: 14px; text-decoration: none;
  transition: background-color 150ms ease, color 150ms ease, transform 160ms var(--ease-out); }
.hm-more:active { transform: scale(.97); }
@media (hover: hover) and (pointer: fine) { .hm-more:hover { background: #1d1d1f; border-color: #1d1d1f; color: #fff; } }

/* ชิปเดินทาง — [หลัก] [ตั๋ว width 0 → วัดจริง] [chevron] */
.hm-trip:empty { display: none; }
.hm-trip { display: grid; gap: 8px; justify-items: end; }
.app-home-shell .tc { background: #fff; border-radius: 16px; padding: 8px 6px 8px 16px; display: flex; align-items: center; }
.app-home-shell .tc-main { display: flex; align-items: center; gap: 12px; padding-right: 20px; flex: none; white-space: nowrap;
  overflow: hidden; transition: max-width .4s cubic-bezier(.2, 0, 0, 1), padding .4s cubic-bezier(.2, 0, 0, 1), opacity .2s; }
.hm-hello > div:first-child { min-width: 0; }   /* ตั๋วกางแล้วบรรทัดวันที่ห่อได้ · ชื่อไม่ห่อ (JS หักความกว้างชื่อออก) */
.hm-hello .hm-h1 { width: max-content; max-width: 100%; }
.app-home-shell .tc-txt { overflow: hidden; transition: max-width .4s cubic-bezier(.2, 0, 0, 1), opacity .2s; }
.app-home-shell .tc.open .tc-txt { max-width: 0 !important; opacity: 0; }   /* กางตั๋วแล้วเหลือแค่รูปรถ */
.app-home-shell .tc.open .tc-main { gap: 0; padding-right: 8px; }   /* รูปรถกลางช่อง: ซ้าย 16 = ขวา 8 + ขอบตั๋ว 8 */
.app-home-shell .tc.open.tight .tc-main { max-width: 0 !important; padding-right: 0; opacity: 0; }   /* ที่ไม่พอวางตั๋ว (JS วัด) — ฝั่งเวลาหุบลงพร้อมตั๋วกาง ไม่หายวับ */
.app-home-shell .tc-l1 { font-size: 14px; color: #5F6368; line-height: 1.3; margin-bottom: 2px; }
.app-home-shell .tc-l2 { font-size: 1.5rem; color: #202124; line-height: 1.1; }
.app-home-shell .tc-l2 small { font-size: .875rem; }
.app-home-shell .tc-l2.is-late { color: var(--hm-red); }
.app-home-shell .tc-lead { display: none; margin: 0 0 12px; font-size: .875rem; font-weight: 600; color: #1d1d1f; }   /* ป้ายวันเหนือตั๋ว — มือถือเท่านั้น */
.app-home-shell .tc-lead.is-late { color: var(--hm-red); }
.app-home-shell .tc-l3 { display: block; font-size: .8125rem; color: #1A73E8; line-height: 1.3; text-decoration: none; transition: opacity .2s; }
.app-home-shell .tc-l3:hover { text-decoration: underline; }
.app-home-shell .tc.open .tc-l3 { opacity: 0; pointer-events: none; }
.app-home-shell .tc-exp { width: 0; max-height: 0; overflow: hidden; transition: width .4s cubic-bezier(.2, 0, 0, 1), max-height .4s cubic-bezier(.2, 0, 0, 1); }
.app-home-shell .tc.open .tc-exp { max-height: 240px; }   /* หุบแล้วตั๋วไม่ดันความสูงชิป */
.app-home-shell .tc-in { display: flex; align-items: stretch; width: max-content; padding: 0 4px 0 8px; opacity: 0;
  transform: translateX(-16px); transition: opacity .2s ease, transform .4s cubic-bezier(.2, 0, 0, 1); }
.app-home-shell .tc.open .tc-in { opacity: 1; transform: none; transition-delay: .12s, 0s; }
.app-home-shell .tc-sep { width: 1px; background: var(--hm-line); margin: 4px 14px 4px 0; }
.app-home-shell .tc-chev { width: 40px; height: 40px; border: 0; border-radius: 50%; background: none; color: #5F6368;
  display: grid; place-items: center; flex: none; }
.app-home-shell .tc-chev:hover { background: var(--hm-soft); }
.app-home-shell .tc-chev .hm-i { font-size: 24px; transition: transform .4s cubic-bezier(.2, 0, 0, 1); }
.app-home-shell .tc.open .tc-chev .hm-i { transform: rotate(180deg); }
.app-home-shell .tk { display: grid; gap: 3px; min-width: 320px; padding: 0 4px 0 0; }
.app-home-shell .tk-top { display: grid; grid-template-columns: auto minmax(110px, 1fr) auto; align-items: start; gap: 14px; }
.app-home-shell .tk-t { font-size: 1.125rem; font-weight: 700; color: #202124; line-height: 1.05; }
.app-home-shell .tk-p { font-size: 14px; color: #5F6368; margin-top: 1px; }
.app-home-shell .tk-end { text-align: right; }
.app-home-shell .tk-mid { display: grid; justify-items: center; gap: 2px; min-width: 0; padding-top: 6px; }
.app-home-shell .tk-dur { font-weight: 400; color: #5F6368; white-space: nowrap; }
.app-home-shell .tk-line { position: relative; width: 100%; height: 10px; }
.app-home-shell .tk-line::before { content: ""; position: absolute; left: 0; right: 6px; top: 4px; border-top: 1.6px dashed #5F6368; }
.app-home-shell .tk-line::after { content: ""; position: absolute; right: 0; top: 0; border: 5px solid transparent;
  border-left: 7px solid #5F6368; border-right: 0; }
.app-home-shell .tk-pin { position: absolute; left: 50%; top: 0; width: 10px; height: 10px; margin-left: -5px; border-radius: 50%;
  background: #fff; border: 2px solid #1A73E8; }
.app-home-shell .tk-dest { max-width: 100%; font-size: 14px; font-weight: 500; color: #202124; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.app-home-shell .tk-bot { display: flex; align-items: center; gap: 10px; font-size: 14px; color: #202124; }
.app-home-shell .tk-item { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.app-home-shell .tk-item .hm-i { font-size: 16px; color: #5F6368; }
.app-home-shell .tk-div { width: 1px; height: 16px; background: #DADCE0; }
.app-home-shell .tk-call { display: none; margin-left: auto;   /* ปุ่มโทรเฉพาะมือถือ (ผู้ใช้สั่ง 2569-10-03) */
   align-items: center; gap: 4px; padding: 2px 10px 2px 8px;
  border-radius: 999px; background: #1A73E8; color: #fff; font-size: .75rem; font-weight: 500; text-decoration: none; }
.app-home-shell .tk-call:hover { background: #1765CC; color: #fff; }
.app-home-shell .tk-call .hm-i { font-size: 14px; }
.hm-art { transform: scaleX(-1); flex: none; }   /* รถหันหน้าไปซ้าย (ผู้ใช้ขอ) — กลับทั้งภาพ ล้อ/ถนนวิ่งถูกทิศเอง */
/* ฉากใต้การ์ดตั๋ว แบบภาพประกอบรถไฟฟ้า (ผู้ใช้ให้ภาพอ้างอิง) · ติดตามงานชิดพื้น
   ป้ายปลายทาง (ป้ายสถานี · ขวา — รถวิ่งเข้าหาป้าย) · ทางยกระดับ + เสาตอม่อซ้ำทุก 72px · พุ่มไม้สีทึบ · เส้นพื้น
   รถหันขวา วิ่งซ้าย → ขวาบนทางยกระดับ (2569-10-03 · เดิมขวา → ซ้าย): เข้าชะลอ · คลานช้า ~2 วิ · เร่งออก (ทางนิ่ง รถเป็นฝ่ายวิ่ง)
   ล้อแตะผิวทาง (ล่างล้อ = 85% ของความสูงภาพรถ) · ผิวทางอยู่ที่ 52px จากบน
   ใช้สองที่: ใต้ชิปบนมือถือ (เต็มจอ) · ท้ายการ์ดเดินทางวันนี้ในรางจอกว้าง (.hm-ride · เต็มการ์ด) */
:is(.app-home-shell, .dt-sheet) .tc-lane { position: relative; height: 108px; overflow: hidden; }
:is(.app-home-shell, .dt-sheet) .ln-sign { position: absolute; right: 6%; top: 4px; max-width: 46%; padding: 4px 10px; border-radius: 3px;
  background: #1B2A6B; color: #fff; font-size: .6875rem; font-weight: 500; line-height: 1.3; }
:is(.app-home-shell, .dt-sheet) .ln-sign > span { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
:is(.app-home-shell, .dt-sheet) .ln-sign::before, :is(.app-home-shell, .dt-sheet) .ln-sign::after { content: ""; position: absolute; top: 100%; width: 2px;
  height: calc(52px - 4px - 100%); background: #D0D5DB; }   /* เสาป้าย 2 ต้น ใต้ป้ายลงถึงผิวทาง */
:is(.app-home-shell, .dt-sheet) .ln-sign::before { left: 8px; } :is(.app-home-shell, .dt-sheet) .ln-sign::after { right: 8px; }
:is(.app-home-shell, .dt-sheet) .ln-deck { position: absolute; left: 0; right: 0; top: 52px; height: 18px; background: #B8C2CC;
  border-top: 4px solid #C9D6E3; }
:is(.app-home-shell, .dt-sheet) .ln-cap { position: absolute; left: 0; right: 0; top: 70px; height: 6px;
  background: repeating-linear-gradient(90deg, transparent 0 18px, #9AA6B4 18px 48px, transparent 48px 72px); }
:is(.app-home-shell, .dt-sheet) .ln-col { position: absolute; left: 0; right: 0; top: 76px; bottom: 2px;
  background: repeating-linear-gradient(90deg, transparent 0 28px, #A9B4C2 28px 38px, transparent 38px 72px); }
:is(.app-home-shell, .dt-sheet) .ln-ground { position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: #E3E6EB; }
:is(.app-home-shell, .dt-sheet) .ln-bush { position: absolute; bottom: 2px; line-height: 0; }
:is(.app-home-shell, .dt-sheet) .ln-b1 { left: 4%; } :is(.app-home-shell, .dt-sheet) .ln-b2 { left: 62%; }
:is(.app-home-shell, .dt-sheet) .tc-lane .hm-art { position: absolute; z-index: 1; left: 38%; bottom: 56px; transform: translateY(15%);
  animation: hm-drive 8s infinite; }
:is(.app-home-shell, .dt-sheet) .tc-lane .road { display: none; }
/* รถในฉากแบนเหมือนฉาก (แบบ C · 2569-10-07) — ถอดขอบกรมท่าของภาพ bb-vehicle-art ในฉาก + รูปรถในแถวบนบอร์ด (2569-10-07)
   เส้นที่ไม่มี fill (เสากระจก · ร่องประตู) เหลือเป็นสีตัวถังเข้ม · ขอบยางนอกเป็นยางเข้ม */
:is(:is(.app-home-shell, .dt-sheet) .tc-lane .hm-art, :is(.app-home-shell, .pk-list) .pk-thumb.is-car svg, .pk-scene svg) [stroke="#0B0B6E"] { stroke: none; }
:is(:is(.app-home-shell, .dt-sheet) .tc-lane .hm-art, :is(.app-home-shell, .pk-list) .pk-thumb.is-car svg, .pk-scene svg) [stroke="#0B0B6E"]:not([fill]),
:is(:is(.app-home-shell, .dt-sheet) .tc-lane .hm-art, :is(.app-home-shell, .pk-list) .pk-thumb.is-car svg, .pk-scene svg) [stroke="#0B0B6E"][fill="none"][stroke-width="4"] { stroke: #AAB3BD; }
:is(:is(.app-home-shell, .dt-sheet) .tc-lane .hm-art, :is(.app-home-shell, .pk-list) .pk-thumb.is-car svg, .pk-scene svg) circle[r="54"] { fill: #2B2B2B; }
.hm-hello .tc-lane { display: none; }
.hm-trip.is-today { display: none; }   /* จอกว้าง: เดินทางวันนี้ขึ้นเป็นการ์ดในราง */
/* การ์ดเดินทางวันนี้ในราง — ตั๋วทรงเดียวกับมือถือ (ค่าชุดเดียวกับ ≤720 ข้างล่าง) + ฉากรถวิ่งชนขอบการ์ด */
.hm-card.hm-ride { overflow: hidden; padding-bottom: 0; }
.hm-ride h2 { font-size: 15px; font-weight: 400; color: #6e6e73; margin: 0 0 12px; }
.app-home-shell .hm-ride .tk { gap: 8px; min-width: 0; padding: 0; }
.app-home-shell .hm-ride .tk-top { grid-template-columns: auto minmax(0, 1fr) auto; gap: 8px; }
.app-home-shell .hm-ride .tk-t { font-size: 1.375rem; }
.app-home-shell .hm-ride .tk-p { font-size: 14px; }
.app-home-shell .hm-ride :is(.tk-dest, .tk-bot) { font-size: .8125rem; }
.app-home-shell .hm-ride .tk-bot { gap: 8px; }
.app-home-shell .hm-ride .tk-bot > .tk-item:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; display: block; }
.app-home-shell .hm-ride .tk-merge { display: none; }
.app-home-shell .hm-ride :is(.tk-call, .tk-dn) { display: none; }   /* ไม่มีปุ่มโทร · ชื่อปลายทางอยู่บนป้ายในฉากแล้ว (ผู้ใช้สั่ง 2569-10-07) */
.hm-ride .tc-lane { margin: 16px -30px 0; }
@media (max-width: 720px) {
  .hm-hello { margin-bottom: 6px; }
  .hm-hello .tc-lane { display: block; margin: 0 -1rem; }
  .hm-trip.is-today { display: grid; }
  .hm-card.hm-ride { display: none; }   /* มือถือใช้ชิปข้างหัวทักทาย */
}
@keyframes hm-drive {
  0%   { left: -25%; animation-timing-function: cubic-bezier(0, 0, .3, 1); }   /* เข้าจากซ้าย ชะลอ */
  35%  { left: 30%;  animation-timing-function: linear; }                       /* คลานช้า 2 วิ เข้าหาป้าย */
  60%  { left: 38%;  animation-timing-function: cubic-bezier(.6, 0, 1, 1); }    /* เร่งผ่านป้ายออกขวา */
  85%, 100% { left: 105%; }
}
.hm-art .wheel { transform-box: fill-box; transform-origin: center; animation: hm-spin 1.2s linear infinite; }
.hm-art .body { animation: hm-bob .6s ease-in-out infinite alternate; }
.hm-art .road { stroke-dasharray: 4 5; animation: hm-road .6s linear infinite; }
@keyframes hm-spin { to { transform: rotate(360deg); } }
@keyframes hm-bob { to { transform: translateY(-1px); } }
@keyframes hm-road { to { stroke-dashoffset: -9; } }

/* บอร์ด — หัวกลุ่ม › / การ์ดใหญ่ซ้าย / รายการรองขวา / ปุ่มแคปซูล "ดู…ทั้งหมด" */
.app-home-shell .st-h { display: flex; align-items: center; gap: 6px; margin-bottom: 20px; font-size: 17px; line-height: 1.3;
  color: #06c; text-decoration: none; }
.app-home-shell .st-h .st-t { color: inherit; text-decoration: none; }
.app-home-shell .st-h:hover .st-t, .app-home-shell .st-h .st-t:hover { text-decoration: underline; }
.app-home-shell .st-h > .hm-i { font-size: 20px; }
.app-home-shell .st-tag { margin-left: auto; border-radius: 999px; padding: 2px 10px; background: #f5f5f7; color: #6e6e73;
  font-size: 12px; font-weight: 600; }
.app-home-shell .st-empty { margin: 0; padding: 8px 0; font-size: 14px; color: #6e6e73; }
/* ติดตามงานว่าง (2569-10-09) — ช่างถามหางาน · ภาพเทา (สถานะว่างไม่แย่งตากับการ์ดจองรถข้างบน) · สีมาจาก mask */
.pk-idle { text-align: center; padding: 8px 8px 12px; }
.pk-idle-art { display: block; width: 132px; height: 141px; margin: 0 auto 16px; background: #6e6e73;
  -webkit-mask: url(img/mechanic.svg) center / contain no-repeat; mask: url(img/mechanic.svg) center / contain no-repeat; }
.pk-idle h3 { font-size: 20px; font-weight: 600; color: #1d1d1f; margin: 0 0 6px; }
.pk-idle p { font-size: 14px; color: #6e6e73; margin: 0 0 20px; }
.pk-idle .btn { display: inline-flex; align-items: center; gap: 4px; }
/* รถที่อนุมัติว่าง (2569-10-09) — แนวนอน (บอร์ดกว้าง ไม่ดันการ์ดห้องลงใต้จอ) · ภาพสถานะว่าง = เทาเสมอ */
.st-idle { display: flex; align-items: center; justify-content: center; gap: 24px; padding: 12px 0 8px; }
.st-idle-art { flex: none; width: 115px; height: 120px; background: #6e6e73;
  -webkit-mask: url(img/person-waiting-list.svg) center / contain no-repeat; mask: url(img/person-waiting-list.svg) center / contain no-repeat; }
.st-idle h3 { font-size: 20px; font-weight: 600; color: #1d1d1f; margin: 0 0 6px; }
.st-idle p { font-size: 14px; color: #6e6e73; margin: 0; }
/* section ย่อยในการ์ด (งานซ่อม: โต๊ะละ section · 2569-10-07) — หัว 17/600 ดำ + ยอดเทา 14 · คั่นด้วยเส้นเต็ม */
/* หัวโต๊ะซ่อม = หัวกลุ่ม เล็กกว่าชื่องานในแถว (15 < 17) แบบหัวกลุ่มรายการของ iOS · ชื่อการ์ด → โต๊ะแรก 20 (2569-10-15) */
.app-home-shell .hm-card-h + .st-sec { margin-top: 20px; }
.app-home-shell .st-sec + .st-sec { margin-top: 20px; padding-top: 20px; border-top: 1px solid #d2d2d7; }
.app-home-shell .st-sec-h { display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px; color: #1d1d1f; text-decoration: none; }
.app-home-shell .st-sec-h > span { font-size: 15px; font-weight: 600; }
.app-home-shell .st-sec-h > small { font-size: 14px; color: #6e6e73; }
.app-home-shell .st-side .pk-top.no-thumb { grid-template-columns: minmax(0, 1fr) auto; }   /* แถวซ่อม: ไม่มีไอคอนหน้าแถว */
.app-home-shell .st-sec .st-side > .pk:last-child { padding-bottom: 0; }   /* เส้นกั้นโต๊ะคุมระยะเอง ไม่บวกขอบล่างของแถวซ้ำ */
.app-home-shell .st-sec-h > .hm-i { align-self: center; margin-left: auto; font-size: 20px; color: #6e6e73; }
@media (hover: hover) and (pointer: fine) { .app-home-shell .st-sec-h:hover > span { color: #06c; } }
:is(.app-home-shell, .pk-list) .pk-t { display: block; font-size: .9375rem; line-height: 1.4; color: #202124; text-decoration: none; }
:is(.app-home-shell, .pk-list) .pk-t:hover { text-decoration: underline; color: #202124; }
:is(.app-home-shell, .pk-list) .pk-bot { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 6px; font-size: .75rem;
  color: var(--hm-mut); }
:is(.app-home-shell, .pk-list) .pk-bot > i { width: 3px; height: 3px; border-radius: 50%; background: var(--hm-faint); }
:is(.app-home-shell, .pk-list) .pk-route { margin-top: 2px; font-size: .875rem; font-weight: 500; line-height: 1.35; color: #3c4043; }   /* รับที่ → ปลายทาง (เด่นรองจากชื่อผู้ขอ) */
:is(.app-home-shell, .pk-list) .pk-leg + .pk-leg { margin-top: 6px; padding-top: 6px; border-top: 1px dashed #dadce0; }   /* งานรวม: ผู้ขอทีละคน · เส้นประกั้น (เฉพาะเสาข้อความ ไม่ลามถึงไอคอน) */
:is(.app-home-shell, .pk-list) .pk-share { display: inline-block; margin-right: 8px; padding: 2px 10px; border: 1px solid var(--hm-blue);
  border-radius: 999px; color: var(--hm-blue); font-size: 11px; font-weight: 500; line-height: 18px; vertical-align: 1px; }
.app-home-shell .pk-pay { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px; font-size: 14px; color: var(--hm-mut); }
:is(.app-home-shell, .pk-list) .st-side { display: grid; align-content: start; }

/* ห้องประชุม — แถบเวลา 08–18 */
.hm-seg { display: inline-flex; margin-left: auto; padding: 3px; border-radius: 999px; background: var(--hm-soft); }
.hm-seg button { border: 0; border-radius: 999px; background: none; padding: 4px 12px; color: var(--hm-mut);
  font-size: .75rem; font-weight: 500; }
.hm-seg button.on { background: #fff; color: #202124; box-shadow: 0 1px 2px rgba(0, 0, 0, .12); }
/* หัวการ์ดห้อง (2569-10-15): ชื่อ + ปุ่ม + ทรงเดียวกับการ์ดจองรถในราง · แถวสอง สลับวัน ทรงเหลี่ยม (ผู้ใช้สั่ง) */
.rm-h { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.rm-h .hm-card-h { margin: 0; }
.rm-add { flex: none; width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center;
  background: #1d1d1f; color: #fff; text-decoration: none; transition: background-color var(--mo-fast) var(--ease-out), transform var(--mo-fast) var(--ease-out); }
.rm-add .material-symbols-rounded { font-size: 24px; }
.rm-add:hover { background: #000; color: #fff; }
.rm-add:active { transform: scale(.94); }
.rm-add:focus-visible { outline: 2px solid var(--hm-blue); outline-offset: 2px; }
.app-home-shell .rm-sub .hm-seg { margin-left: 0; border-radius: 8px; }
.app-home-shell .rm-sub .hm-seg button { padding: 6px 16px; border-radius: 6px; font-size: .8125rem; }
@media (prefers-reduced-motion: reduce) { .rm-add { transition: none; } .rm-add:active { transform: none; } }
.app-home-shell .rooms { display: grid; gap: 14px; }
.app-home-shell .room, .app-home-shell .hours { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 16px; align-items: center; }
.app-home-shell .room-n { font-size: .9375rem; }
.app-home-shell .room-n small { display: block; font-size: 14px; color: var(--hm-mut); }
.app-home-shell .bar { position: relative; height: 22px; border-radius: 6px; background: var(--hm-green-soft); overflow: hidden; }
.app-home-shell .bar span { position: absolute; top: 0; bottom: 0; background: #DADCE0; border-left: 2px solid #fff; }
.app-home-shell .bar .now { width: 2px; border: 0; background: #D93025; z-index: 1; }
.app-home-shell .bar .wait { background: #FBD5B5; }          /* ขอใช้ห้องรออนุมัติ (สีรอ… ของ _pick_tone) */
/* ข้อความสถานะห้อง (ว่างถึงเย็น/เต็มถึงเย็น) ถอดแล้ว 2569-10-07 — แถบเวลาบอกพอ */
.app-home-shell .hours { font-size: 14px; color: var(--hm-mut); }   /* เดิม 12.4px สี faint = คอนทราสต์ 2.6:1 ไม่ผ่าน AA */
.app-home-shell .hours div { display: flex; justify-content: space-between; }

/* ติดตามงาน — รูป 64 ขวาเป็นวงแหวนความคืบหน้า */
.app-home-shell .pk-h { display: flex; align-items: center; gap: 8px; margin-bottom: 20px; }
.app-home-shell .pk-h h2 { margin: 0; font-size: 28px; font-weight: 600; line-height: 1.14; letter-spacing: -.01em; color: #1d1d1f; }
/* ติดตามงานแบบกลุ่ม (2569-10-15 · home_picks) — หัวกลุ่ม (วันนี้ · พรุ่งนี้ · งานซ่อม) เทาเล็ก แทนวันที่ซ้ำทุกแถว
   แถว: จุดสี 8 · ชื่อ 17/600 + บรรทัดรอง 14 เทา · สถานะชิดขวา 13/600 (สีเดียวต่อแถว — เดิมสีซ้ำทั้งกล่องไอคอนและคำ)
   ส้ม --st-wait (4.9:1) ใช้ได้ทั้งจุดและตัวหนังสือ */
.app-home-shell .pk-card .pk-grp + .pk-grp { margin-top: 20px; }
.app-home-shell .pk-card .pk-gh { margin: 0; font-size: 14px; font-weight: 600; line-height: 1.3; color: var(--hm-mut); }
.app-home-shell .pk-card .pk-row { display: grid; grid-template-columns: 8px minmax(0, 1fr) auto; column-gap: 12px; align-items: start; padding: 12px 0; }
.app-home-shell .pk-card .pk-gh + .pk-row { padding-top: 8px; }
.app-home-shell .pk-card .pk-mark { width: 8px; height: 8px; margin-top: 7px; border-radius: 50%; background: var(--c); }
.app-home-shell .pk-card .pk-sub { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 2px; font-size: 14px; line-height: 1.35; color: var(--hm-mut); }
.app-home-shell .pk-card .pk-sub > i { width: 3px; height: 3px; border-radius: 50%; background: var(--hm-faint); }
.app-home-shell .pk-card .pk-age.is-old { color: var(--hm-amber); font-weight: 500; }   /* ค้างเกิน PICK_OLD_DAYS */
.app-home-shell .pk-card .pk-st { margin-top: 3px; font-size: 14px; font-weight: 600; line-height: 1.3; white-space: nowrap; text-align: right; color: var(--c); }
:is(.app-home-shell, .pk-list) .pk { padding: 14px 0; }
:is(.app-home-shell, .pk-list) .pk + .pk { border-top: 1px solid var(--hm-line); }
:is(.app-home-shell, .pk-list) .pk-top { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: 14px; align-items: start; }
:is(.app-home-shell, .pk-list) .pk-t { margin-top: 0; }
:is(.app-home-shell, .pk-list) .pk-stage { margin-bottom: 2px; font-size: .75rem; font-weight: 500; color: var(--c); }
:is(.app-home-shell, .pk-list) .pk-keep { font-weight: 400; color: var(--hm-mut); }
:is(.app-home-shell, .pk-list) .pk-thumb { position: relative; width: 56px; height: 56px; text-decoration: none; border-radius: 12px; display: grid; place-items: center;
  background: var(--bg); color: var(--c); }
:is(.app-home-shell, .pk-list) .pk-thumb > .hm-i { font-size: 24px; }
:is(.app-home-shell, .pk-list) .pk-thumb > .pk-svc { font-size: 36px; line-height: 1;
  font-family: "Material Symbols Rounded Svc"; font-variation-settings: normal; }   /* แบบเดียวกับ .hm-cats · ไม่มีวงแหวน (2569-10-09) */
:is(.app-home-shell, .pk-list) .pk-thumb.is-car { background: none; }   /* ภาพรถแทนวงแหวน — ไม่มีกล่อง · รถ 112px โผล่แค่ครึ่งหน้า (2569-10-07) */
:is(.app-home-shell, .pk-list) .pk-crop { position: absolute; inset: -4px 0 -14px; overflow: hidden; display: flex; justify-content: flex-end; align-items: flex-end; }   /* สูงกว่าช่อง ให้ล้อโผล่ครบ */
:is(.app-home-shell, .pk-list) .pk-crop .hm-car { flex: none; }
:is(.app-home-shell, .pk-list) .pk-full { display: none; }
/* จอกว้าง: รถเต็มคัน 120px + เงาใต้ล้อ · มือถือคงครึ่งคัน */
@media (min-width: 721px) {
  :is(.app-home-shell, .pk-list) .st-side .pk-top.is-car { grid-template-columns: 120px minmax(0, 1fr) auto; gap: 20px; }
  :is(.app-home-shell, .pk-list) .pk-top.is-car .pk-thumb { width: 120px; height: auto; border-radius: 0; }
  :is(.app-home-shell, .pk-list) .pk-top.is-car .pk-crop { display: none; }
  :is(.app-home-shell, .pk-list) .pk-full { display: block; position: relative; }
  :is(.app-home-shell, .pk-list) .pk-full .hm-car { position: relative; display: block; }
  :is(.app-home-shell, .pk-list) .pk-full::before { content: ""; position: absolute; left: 4%; right: 2%; bottom: -6px; height: 12px;
    background: radial-gradient(closest-side, rgb(0 0 0 / .22), transparent); }
}
/* วันนี้ฉันขับรถ — คนยืนหน้ารถคันที่ขับ (2569-10-07 · home_drives) · หน้ารถขวา คนยืนค่อนไปทางหน้ารถ · คนสูงกว่ารถ ~1.4 เท่า */
.pk-scene { position: relative; display: block; width: 210px; height: 156px; margin: 0 auto 12px; }
.pk-scene::before { content: ""; position: absolute; left: 0; right: 0; bottom: -6px; height: 14px;
  background: radial-gradient(closest-side, rgb(0 0 0 / .18), transparent); }
.pk-scene .hm-car { position: absolute; left: 0; bottom: 0; display: block; }
.pk-man { position: absolute; left: 54%; bottom: -2px; height: 152px; width: auto; }
.pk-drive .dv-h { display: block; font-size: 19px; font-weight: 600; line-height: 1.3; color: #1d1d1f; text-decoration: none; }
.pk-drive .dv-sub { margin-top: 2px; font-size: 15px; color: #6e6e73; }
.pk-drive .dv-step { margin-top: 12px; font-size: 14px; font-weight: 600; color: #1d1d1f; }
.pk-drive .dv-list { margin: 6px 0 0; padding-left: 1.2em; font-size: 14px; line-height: 1.6; color: #1d1d1f; }
.pk-drive .dv-step + .dv-list { margin-top: 2px; }
.pk-drive .dv-ex { margin-top: 6px; padding: 6px 10px; border-radius: 8px; background: #f5f5f7; font-size: 14px; color: #1d1d1f; }
:is(.app-home-shell, .pk-list) .pk-n { position: absolute; right: -4px; bottom: -4px; padding: 0 6px; border: 2px solid #fff; border-radius: 999px;
  background: var(--c); color: #fff; font-size: .6875rem; font-weight: 600; line-height: 16px; }
/* สีสถานะ = ขั้นมาตรฐาน --st-* (2569-10-15) — รอ… ส้ม · อนุมัติแล้ว/กำลังทำ ฟ้า · เสร็จ เขียว · late แดง (รถเลยเวลา) */
:is(.app-home-shell, .pk-list) :is(.tone-info, .tone-wait, .tone-ok, .tone-done, .tone-bad, .tone-late) { --c: var(--fg); --bg: var(--tint); }
:is(.app-home-shell, .pk-list) .pk-dot { display: inline-block; width: 3px; height: 3px; margin: 0 6px; border-radius: 50%; background: currentColor;
  vertical-align: middle; opacity: .6; }
:is(.app-home-shell, .pk-list) .pk-st { font-weight: 500; color: var(--c); }
:is(.app-home-shell, .pk-list) .st-side > .pk:first-child { padding-top: 0; }
:is(.app-home-shell, .pk-list) .st-side .pk-top { grid-template-columns: 56px minmax(0, 1fr) auto; }   /* แถวรถ: + ปุ่ม ↗ ขวาล่าง */
:is(.app-home-shell, .pk-list) .pk-go { align-self: end; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
  color: var(--hm-blue); text-decoration: none; }
:is(.app-home-shell, .pk-list) .pk-go:hover { background: var(--hm-blue-soft); }
:is(.app-home-shell, .pk-list) .pk-go .hm-i { font-size: 20px; }
:is(.app-home-shell, .pk-list) .st-side .pk + .pk { border-top-style: dashed; }                       /* บอร์ด: เส้นคั่นแถวเป็นเส้นประ */
.pk-list .st-side .pk-top { grid-template-columns: 56px minmax(0, 1fr); }   /* ปฏิทินจองรถ: ไม่มีปุ่ม ↗ */
.pk-list .pk-pax { display: inline-flex; align-items: center; gap: 2px; }                /* ผู้โดยสาร: hail + จำนวน */
/* งานรวม: วงกลมผู้ขอซ้อนกัน 1 วงต่อคำขอ · ชี้/โฟกัสวงไหนขึ้นชื่อคนนั้น */
@media (max-width: 720px) { :is(.app-home-shell, .pk-list) .pk-wide { display: none; } }   /* จอแคบ: ไม่มีต้นทาง */
/* แถวบนหน้าแรกตัวหนังสือแบบ tile ของ Apple: สถานะ = eyebrow 12/600 · ชื่อ 17/600 · บรรทัดล่าง 14 เทา (ปฏิทินจองรถ .pk-list คงเดิม) */
.app-home-shell .pk-stage { font-size: 14px; font-weight: 500; margin-bottom: 4px; }
.app-home-shell .pk-share { font-size: 14px; line-height: 20px; }   /* ไทยเล็กกว่า 14 สระ/วรรณยุกต์เบียด (2569-10-15 · ฐานของ .pk-list 11px) */
.app-home-shell .ln-sign { font-size: 14px; }
.app-home-shell .pk-t { font-size: 17px; font-weight: 600; line-height: 1.25; color: #1d1d1f; }
.app-home-shell .pk-t:hover { color: #1d1d1f; }
.app-home-shell .pk-bot { font-size: 14px; color: #6e6e73; }
.app-home-shell .pk { padding: 18px 0; }
/* แถวรถบนบอร์ด: ระยะไล่ตามความผูกกัน — ชื่อ↔เส้นทาง↔ธุระ ชิด (2–4) · รถ/เวลา ห่างกว่า (6–10) · ผู้ขอคนถัดไป 12 */
.app-home-shell .st-side .pk-stage { margin-bottom: 6px; }
.app-home-shell .pk-route { margin-top: 4px; }
.app-home-shell .pk-why { display: block; margin-top: 2px; font-weight: 400; color: #6e6e73; }   /* ธุระ — บรรทัดรอง เทา */
.app-home-shell .pk-leg + .pk-leg { margin-top: 12px; padding-top: 12px; }
.app-home-shell .st-side .pk-bot { margin-top: 10px; }

@media (max-width: 991.98px) {
  .hm-grid { grid-template-columns: minmax(0, 1fr); }
  .hm-rail { order: -1; }                          /* งานค้างของฉันขึ้นก่อนบอร์ดบนจอแคบ */
}
@media (max-width: 720px) {
  .hm-bar { padding: 0 16px; }
  .hm-nav { padding: 0 8px; gap: 4px; }
  main.app-main.app-home-main { padding-top: 20px !important; }
  .hm-hello { flex-direction: column; align-items: stretch; padding-top: 12px; gap: 20px; }   /* เดิมบน 56 = ที่ว่าง ~150px เหนือชื่อ (2569-10-15) */
  .hm-cats { margin-bottom: 16px; padding-bottom: 12px; }
  .hm-date { white-space: normal; }               /* ชิปอยู่คนละแถวแล้ว ห่อได้ไม่กระตุก */
  main.app-main.app-home-main { padding-bottom: 2rem !important; }   /* หน้าแรกไม่มีแถบล่าง */
  /* ชิปเดินทาง: ตั๋วกางถาวรเต็มความกว้างจอ ไม่มีฝั่งเวลา/chevron (JS ปลด inert ให้) */
  .hm-trip { justify-items: stretch; }
  .app-home-shell .tc { padding: 24px 18px 20px; border-radius: 20px; }   /* บนมากกว่าล่าง */
  .app-home-shell .tc-main, .app-home-shell .tc-chev, .app-home-shell .tc-sep { display: none; }
  .app-home-shell .tc-lead { display: block; }
  .app-home-shell .tc { padding-top: 18px; }
  .app-home-shell .tc-exp { flex: 1; width: auto !important; max-height: none; overflow: visible; }
  .app-home-shell .tc-in { width: auto !important; padding: 0; opacity: 1; transform: none; flex-direction: column; }   /* ป้ายวันบน ตั๋วล่าง */
  .app-home-shell .tk { gap: 8px; flex: 1; }
  .hm-card { padding: 24px 20px; }
  .hm-card.pk-card { background: none; box-shadow: none; border-radius: 0; padding: 8px 0 0; }   /* ติดตามงาน: ไม่มีการ์ด เต็มความกว้าง (2569-10-09) */
  /* ห้อง: ชื่อบรรทัดเดียวเหนือแถบเต็มกว้าง (เดิมเสาชื่อ 96px ทำชื่อห้องตกบรรทัด · 2569-10-15) · "ต้องอนุมัติ" ต่อท้ายชื่อ */
  .app-home-shell .rooms { gap: 16px; }
  .app-home-shell .room { grid-template-columns: minmax(0, 1fr); gap: 6px; }
  .app-home-shell .room-n { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .app-home-shell .room-n small { display: inline; margin-left: 8px; }
  .app-home-shell .hours { grid-template-columns: minmax(0, 1fr); margin-top: -8px; }
  .app-home-shell .hours > span:first-child { display: none; }
  .app-home-shell .st-h { flex-wrap: wrap; font-size: 1.0625rem; }
  .app-home-shell .tk { min-width: 0; }
  .app-home-shell .tk-merge { display: none; }   /* แถวล่างแถวเดียว (คนขับ · ทะเบียน · โทร) */
  .app-home-shell .tk-dn { display: none; }   /* ชื่อปลายทางอยู่บนป้ายในฉากแล้ว เหลือแค่ระยะเวลา */
  .app-home-shell .tk-t { font-size: 1.375rem; }
  .app-home-shell .tk-p { font-size: 14px; }
  .app-home-shell .tk-dest, .app-home-shell .tk-bot { font-size: .8125rem; }
  .app-home-shell .tk-call { display: inline-flex; align-items: center; padding: 8px 18px 8px 14px; gap: 6px; font-size: .9375rem; }
  .app-home-shell .tk-call .hm-i { font-size: 20px; }
  .app-home-shell .tk-top { grid-template-columns: auto minmax(0, 1fr) auto; gap: 8px; }
  .app-home-shell .tk-bot { gap: 8px; }
  .app-home-shell .tk-bot > .tk-item:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; display: block; }
}
@media (prefers-reduced-motion: reduce) {
  .hm-art *, :is(.app-home-shell, .dt-sheet) .tc-lane .hm-art { animation: none !important; }
  .app-home-shell .tc-exp, .app-home-shell .tc-in, .app-home-shell .tc-main, .app-home-shell .tc-txt, .app-home-shell .tc-chev .hm-i, .app-home-shell .tc-l3 { transition: none !important; }
}

/* [42] แผงแจ้งเตือน (กระดิ่ง dropdown + offcanvas · 2569-10-03) — สีชุด Google ของหน้าแรก [41] ทุก shell
   ตัวแปร --hm-* ประกาศให้ .notif-panel ใน [41] แล้ว · โครงแถวอยู่ _notif_list.html */
.notif-panel { color: var(--hm-ink); }
.notif-panel .notif-row { color: var(--hm-ink) !important; border-color: var(--hm-line) !important; }
/* แถว 2 บรรทัด (2569-10-15): สถานะสีขั้น · ชื่องาน ... เวลา • / รายละเอียด · ยังไม่อ่าน = จุด ไม่ทาพื้น (ฟ้า = ขั้น ok แล้ว) */
.notif-panel .notif-row .text-secondary { color: var(--hm-mut) !important; }
.notif-panel .notif-ico { width: 32px; height: 32px; }
.notif-panel .notif-st { color: var(--fg); font-weight: 500; }
.notif-panel .notif-when { color: var(--hm-mut); }
.notif-panel .notif-dot { width: 7px; height: 7px; align-self: center; background: var(--hm-blue); }
.notif-panel .notif-row.is-unread .notif-when { color: var(--hm-blue); font-weight: 500; }
.notif-panel .js-notif-read { color: var(--hm-blue) !important; }

/* [43] ดูรูปเต็มจอแบบ rgt (.modal-picture ของ global.css · 2569-10-06) — JS ใน rgt-list.js (show-picture-button)
   z-index 1062 เหนือ modal (1055) · พื้นดำ 70% · รูปพอดีจอ กรอบขาว 5px · ขยาย = ขนาดจริงแล้วเลื่อนดู */
.rgt-picview { position: fixed; inset: 0; z-index: 1062; padding: 60px 0; overflow: auto; color: #fff;
               background: rgba(0, 0, 0, .7); display: flex; flex-direction: column; align-items: center;
               justify-content: center; justify-content: safe center; }
.rgt-picview > * { flex-shrink: 0; }
.rgt-picview-img { display: block; max-width: 80%; max-height: 80%; border: 5px solid #fff; }
.rgt-picview.is-zoom .rgt-picview-img { max-height: none; }
.rgt-picview-spin { display: none; }
.rgt-picview.is-loading .rgt-picview-spin { display: block; }
.rgt-picview.is-loading .rgt-picview-img { display: none; }
.rgt-picview-name { padding: 0 16px 12px; text-align: center; }
.rgt-picview-info { padding: 12px 16px 0; text-align: center; opacity: .85; }
.rgt-picview-name:empty, .rgt-picview-info:empty { display: none; }
.rgt-picview-tools { position: fixed; top: 12px; right: 16px; display: flex; gap: 8px; }
.rgt-picview-btn { width: 44px; height: 44px; border: 0; border-radius: 50%; background: transparent; color: #fff;
                   display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }
.rgt-picview-btn:hover, .rgt-picview-btn:focus-visible { background: rgba(255, 255, 255, .15); color: #fff; }
.rgt-picview-btn .material-symbols-rounded { font-size: 28px; }
.rgt-picview-prev, .rgt-picview-next { position: fixed; top: 50%; transform: translateY(-50%); }
.rgt-picview-prev { left: 12px; }
.rgt-picview-next { right: 12px; }
.rgt-picview-prev .material-symbols-rounded, .rgt-picview-next .material-symbols-rounded { font-size: 40px; }
@media (max-width: 575.98px) { .rgt-picview-img { max-width: 94%; } }

/* [44] การ์ดงานนอกระบบ หน้างานขับรถของฉัน (2569-10-08) — ข้อความซ้าย · ฉาก adhoc_scene (_art_vehicle.html) ขวา
   กระบะวิ่งขวา→ซ้าย ออกจากหลังต้นไม้ จางก่อนถึงข้อความ · เมฆลอยช้า */
.ad-card { display: flex; overflow: hidden; min-height: 128px; background: var(--bs-body-bg); }
.ad-card .ad-text { flex: 0 0 auto; align-self: center; }
.ad-scene { order: 2; flex: 1 1 0; min-width: 0; align-self: stretch; height: auto; }   /* กินที่ที่เหลือ ไม่ทับข้อความ */
.ad-car { animation: ad-drive 9s infinite; }
.ad-spin { transform-box: fill-box; transform-origin: center; animation: ad-spin .9s linear infinite; }
.ad-bob { animation: hm-bob .5s ease-in-out infinite alternate; }
.ad-cloud { animation: ad-cloud 24s ease-in-out infinite alternate; }
.ad-cloud-2 { animation-duration: 18s; animation-direction: alternate-reverse; }
/* ความเร็วคงที่ตลอดทาง (เดิมเร่ง-ชะลอ ดูกระตุก · 2569-10-08) · พักนอกจอ 15% ก่อนวนรอบใหม่ */
/* รถในฉากไม่มีขอบ ให้แบนเท่าฉาก (แบบ lane_scene) · เส้นประตู = สีตัวถังเข้ม · ขอบยาง = ยางเข้ม */
.ad-car [stroke="#0B0B6E"] { stroke: none; }
.ad-car [stroke="#0B0B6E"]:not([fill]), .ad-car [stroke="#0B0B6E"][fill="none"][stroke-width="4"] { stroke: #4E7099; }
.ad-car circle[r="54"] { fill: #2B2B2B; }
@keyframes ad-drive {
  0%   { transform: translateX(240px); animation-timing-function: linear; }
  85%, 100% { transform: translateX(-240px); }
}
/* มือถือ: ฉากแคบ viewBox ถูกครอปจนขอบฟ้าโค้งในภาพหลุด เหลือขอบตรง → โค้งที่ตัวกล่องแทน
   (รัศมีวงรีบนซ้าย = โค้งจากบนลงล่างซ้ายแบบขอบฟ้าเดิม) + เงาทึบ = ขอบมิ้นต์ ตามโค้งเดียวกัน */
@media (max-width: 575.98px) {
  .ad-scene { border-top-left-radius: 64px 100%; box-shadow: -6px 0 0 #BFEFDF; margin-left: 6px; }
}
@keyframes ad-spin { to { transform: rotate(-360deg); } }
@keyframes ad-cloud { to { transform: translateX(-14px); } }
@media (prefers-reduced-motion: reduce) {
  .ad-car, .ad-spin, .ad-bob, .ad-cloud { animation: none; }
}

/* [45] กล่องสภาพรถตอนรับ + ทำความสะอาดก่อนส่งมอบ (หน้างานขับรถของฉัน · 2569-10-08) — พื้นสีเดียวกับ sidebar แผ่นขาว
   (ภาพคนขับจับพวงมาลัย .job-face ถอดแล้ว 2569-10-08) */
.recv-box { background: var(--app-panel-bg, rgb(247, 249, 252)) !important; }

/* [46] ภาพพนักงานล้างรถ — การ์ดล้างรถ (vehicle_wash) + กล่องทำความสะอาดก่อนส่งมอบ (หน้างานขับรถของฉัน · 2569-10-08) — static/img/car-wash.svg
   กระบะ ref/pickup-4door-canopy.svg ถอดขอบ + ย่อเล็กกว่าคน · คน/ฟองจาก Freepik (ต้องใส่เครดิต) · ข้อความซ้าย ภาพขวา */
.wash-art { flex: 0 0 auto; width: 42%; max-width: 220px; height: auto; margin-bottom: -.25rem; }
/* การ์ดล้างรถ: ภาพกลางบนสุด ใหญ่กว่าในกล่องส่งมอบ */
.wash-art-top { width: 80%; max-width: 340px; height: auto; }
/* กล่องทำความสะอาดก่อนส่งมอบ: ข้อความยาว — มือถือภาพขึ้นบน ข้อความเต็มกว้าง (ข้างภาพเหลือ 5 บรรทัดสั้นๆ) */
@media (max-width: 575.98px) {
  .wash-head { flex-direction: column-reverse; align-items: stretch !important; }
  .wash-head .wash-art { align-self: center; width: 70%; margin: .75rem 0 .25rem; }
}

/* แถวงานล้างรถในคิวอนุมัติรถบนมือถือ (wash_person · 2569-10-09) — สีจาก .tone-wait (ส้ม รอล้าง) / .tone-done (เขียว ล้างแล้ว) */
.pk-list .wash-card .pk-thumb { background: none; border-radius: 0; }   /* มือถือ: ไม่มีกรอบ เหลือแต่ภาพ */
.pk-thumb .wash-person { width: 56px; height: auto; }

/* [47] ช่องรูปจัตุรัส photo_tile (_macros.html · 2569-10-08) — พื้นเทา + ปุ่ม + · เลือกแล้วรูปย่อเต็มช่อง */
.photo-tile { cursor: pointer; }
.photo-tile-box { background: var(--bs-secondary-bg); color: var(--bs-secondary-color); overflow: hidden; }
.photo-tile:hover .photo-tile-box { filter: brightness(.95); color: var(--bs-body-color); }
.photo-tile-box.is-set { color: var(--bs-success); }
.photo-tile-img { object-fit: cover; }
.photo-tile input:focus-visible ~ .photo-tile-add { outline: 2px solid var(--bs-primary); outline-offset: -2px; border-radius: inherit; }

/* [48] พรีวิวการ์ด LINE flex (flex_html.py · modal แจ้ง LINE ของอนุมัติรถ · 2569-10-09)
   ขนาด px ตามสเกลของ LINE (ไม่ใช่ token ของหน้าเว็บ) — ให้พรีวิวหน้าตาเท่าการ์ดจริง · พื้นหลังสีแชท LINE */
.lf-chat { background: #8ba6c9; border-radius: 1rem; padding: 1rem; min-width: 0; overflow: hidden; }
/* min-width 0: #ntList เป็น d-grid — ไม่ใส่ track ขยายตามข้อความ nowrap แล้วล้น modal */
@media (max-width: 575.98px) { .lf-chat { padding: .5rem; } }
.lf-bubble { background: #fff; border-radius: 16px; margin: 0 auto; overflow: hidden; color: #111;
  font-family: -apple-system, 'Sukhumvit Set', 'Thonburi', sans-serif; line-height: 1.4; }
.lf-kilo { max-width: 260px; } .lf-mega { max-width: 300px; } .lf-giga { max-width: 500px; }
/* carousel (การ์ดรวมงานอนุมัติเข้ากลุ่ม · 2569-10-17) — วันละใบ เลื่อนแนวนอน ใบถัดไปโผล่ขอบ */
.lf-carousel { display: flex; gap: 8px; overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior-x: contain;
  margin: 0 -1rem; padding: 0 1rem; scroll-padding: 0 1rem; padding-bottom: 6px; scrollbar-width: thin; }
.lf-carousel > .lf-bubble { flex: 0 0 min(300px, 85%); margin: 0; scroll-snap-align: start; }
@media (max-width: 575.98px) { .lf-carousel { margin: 0 -.5rem; padding: 0 .5rem; scroll-padding: 0 .5rem; } }
.lf-box { display: flex; min-width: 0; } .lf-vertical { flex-direction: column; } .lf-horizontal { flex-direction: row; }
.lf-center { justify-content: center; }
.lf-text { min-width: 0; } .lf-wrap { white-space: normal; word-break: break-word; }
.lf-clip { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lf-b { font-weight: 700; } .lf-a-end { text-align: right; } .lf-a-center { text-align: center; }
.lf-separator { border-top: 1px solid; }
.lf-btn-primary, .lf-btn-link { height: 40px; display: flex; align-items: center; justify-content: center;
  font-size: 16px; border-radius: 8px; }
.lf-btn-primary { color: #fff; }
.lf-s-xxs { font-size: 11px; } .lf-s-xs { font-size: 13px; } .lf-s-sm { font-size: 14px; } .lf-s-md { font-size: 16px; }
.lf-s-lg { font-size: 19px; } .lf-s-xl { font-size: 22px; } .lf-s-xxl { font-size: 29px; } .lf-s-3xl { font-size: 35px; }
.lf-mt-xs { margin-top: 2px; } .lf-mt-sm { margin-top: 4px; } .lf-mt-md { margin-top: 8px; }
.lf-mt-lg { margin-top: 12px; } .lf-mt-xl { margin-top: 16px; } .lf-mt-xxl { margin-top: 20px; }
.lf-ml-xs { margin-left: 2px; } .lf-ml-sm { margin-left: 4px; } .lf-ml-md { margin-left: 8px; }
.lf-ml-lg { margin-left: 12px; } .lf-ml-xl { margin-left: 16px; } .lf-ml-xxl { margin-left: 20px; }

/* [49] สิทธิ์ของบทบาท (manage/report.html · 2569-10-13) — ช่องระดับในตาราง หน้า × บทบาท
   select กว้างพอให้คำว่า "อนุมัติ" ไม่ถูกตัด · ● = ระดับต่างจากค่าตั้งต้นในโค้ด */
.pm-grid .form-select { min-width: 7.5rem; }
.pm-diff { color: var(--bs-warning); cursor: help; }

/* [50] ชวนเพิ่มเพื่อน LINE OA (#lineInvite · _line_invite.html · 2569-10-12) — ทรงเดียวกับ #rulesModal (.pk-drive) */
.li-scene { position: relative; width: 210px; height: 170px; margin: 0 auto 12px; }
.li-scene::before { content: ""; position: absolute; left: 10%; right: 10%; bottom: -6px; height: 14px;
  background: radial-gradient(closest-side, rgb(0 0 0 / .14), transparent); }
.li-man { position: absolute; left: 20px; bottom: 0; height: 170px; width: auto; }
.li-logo { position: absolute; right: 6px; top: 4px; width: 54px; height: 54px; transform: rotate(8deg);
  filter: drop-shadow(0 4px 8px rgb(6 199 85 / .25)); }
.li-btn { --bs-btn-bg: #06C755; --bs-btn-color: #fff; --bs-btn-hover-bg: #05B04B; --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: #049C42; --bs-btn-active-color: #fff; display: inline-flex; align-items: center; justify-content: center;
  gap: 8px; font-weight: 600; }
.li-btn svg { width: 22px; height: 22px; flex: none; }

/* [51] ยืนยันออกจากระบบ (#logoutModal · _logout.html · 2569-10-13) — ภาพ static/img/logout-exit.svg + หัวบรรทัดเดียว + ปุ่มคู่ */
.lo-body { padding: 2rem 1.5rem 1.5rem; }
.lo-art { display: block; width: 130px; height: auto; margin: 0 auto 1rem; }
.lo-h { font-size: 1.15rem; font-weight: 600; }
.lo-btns { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; margin-top: 1.5rem; }
@media (min-width: 576px) {
  .lo-body { padding: 2.75rem 2.5rem 2.5rem; }
  .lo-art { width: 160px; margin-bottom: 1.25rem; }
  .lo-btns { gap: .75rem; margin-top: 1.75rem; }
}

/* [52] ตัวอย่างข้อความ LINE (line/_messages.html · /line/admin?tab=messages · 2569-10-17)
   ห้องแชทจำลองบนพื้น .lf-chat ([48]) — ป้ายเหตุการณ์ทรงป้ายวันที่ของ LINE · การ์ดชิดซ้ายแบบข้อความจากบอท
   ขนาด px ในห้องแชทตามสเกลของ LINE (เหมือน [48]) · รางขวาใช้ token ของหน้าเว็บ */
.lm-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .75rem 1.5rem;
  margin-bottom: 1.5rem; border-bottom: 1px solid var(--bs-border-color); }
.lm-tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-bottom: -1px; }
.lm-tabs::-webkit-scrollbar { display: none; }
.lm-tabs .nav-link { white-space: nowrap; }
.lm-pick { display: flex; flex-direction: column; gap: .25rem; margin-bottom: 1.25rem; }
.lm-chat { padding: 4px 20px 28px; }
.lm-msg { padding-top: 24px; scroll-margin-top: 1rem; }
.lm-pill { display: table; margin: 0 auto 12px; padding: 3px 14px; border-radius: 999px; max-width: 100%;
  background: rgb(22 35 52 / .55); color: #fff; font-size: 13px; text-align: center; }
.lm-row { display: flex; gap: 8px; align-items: flex-start; }
.lm-avatar { flex: none; width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center;
  background: #fff; color: #1f2a6b; font-size: 12px; font-weight: 700; }
.lm-col { min-width: 0; flex: 1; }
.lm-name { display: block; margin: 0 0 4px 2px; font-size: 12px; color: #1d2b44; }
.lm-col .lf-bubble { margin: 0; }
.lm-err { background: #fff; border-radius: 16px; padding: 14px 18px; max-width: 300px; font-size: 14px;
  color: var(--bs-danger); }
@media (max-width: 575.98px) { .lm-chat { padding: 0 10px 20px; } .lm-avatar { display: none; } }
.lm-rail { position: sticky; top: 1rem; }
.lm-rail-h { font-size: 1rem; font-weight: 600; margin-bottom: .5rem; }
.lm-idx { list-style: none; padding: 0; margin: 0 0 1rem; border-top: 1px solid var(--bs-border-color); }
.lm-idx li { border-bottom: 1px solid var(--bs-border-color); }
.lm-idx a { display: flex; flex-direction: column; gap: 2px; padding: .6rem .25rem; color: inherit; text-decoration: none; }
.lm-idx a:hover .lm-idx-t { text-decoration: underline; }
.lm-idx-t { font-weight: 500; }
.lm-idx-s { font-size: .78rem; color: var(--bs-secondary-color); }
.lm-idx-alt { font-size: .78rem; color: var(--bs-secondary-color); overflow: hidden; display: -webkit-box;
  -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
.lm-note { font-size: .78rem; color: var(--bs-secondary-color); }
@media (max-width: 991.98px) { .lm-rail { position: static; } }

/* [53] ภาพรวม LINE แจ้งเตือน (line/_overview.html · /line/admin ค่าปริยาย · 2569-10-17)
   สถานะเดียวบนสุด (สีพื้นตามสถานะ = ก้อนเดียวในหน้าที่ไม่ขาว) · ต้องทำต่อ · รางขวา = การ์ดราย OA (กดทั้งใบ = หน้า OA) */
.lv-status { display: flex; gap: 1rem; align-items: flex-start; padding: 1.25rem 1.5rem; border-radius: 12px;
  background: var(--st-done-soft); color: var(--st-done-ink); }
.lv-status.is-warn { background: var(--st-wait-soft); color: var(--st-wait-ink); }
.lv-status.is-down { background: var(--st-bad-soft); color: var(--st-bad-ink); }
.lv-dot { flex: none; width: 14px; height: 14px; margin-top: .45rem; border-radius: 50%; background: var(--st-done);
  box-shadow: 0 0 0 5px rgb(255 255 255 / .6); }
.is-warn .lv-dot { background: var(--st-wait); } .is-down .lv-dot { background: var(--st-bad); }
.lv-title { font-size: 1.25rem; font-weight: 600; margin: 0 0 .25rem; text-wrap: balance; }
.lv-sub { margin: 0; font-size: .85rem; }
.lv-h { font-size: 1rem; font-weight: 600; margin: 0 0 .75rem; }
.lv-todo { margin-top: 2rem; }
.lv-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--bs-border-color); }
.lv-item { display: flex; align-items: center; gap: .75rem; padding: .75rem 0; border-bottom: 1px solid var(--bs-border-color); }
.lv-ico { flex: none; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
  background: var(--tint); color: var(--fg); }
.lv-text { flex: 1; min-width: 0; }
.lv-clear { margin-top: 1.5rem; color: var(--bs-secondary-color); }
.lv-foot { margin-top: 1.5rem; font-size: .78rem; color: var(--bs-secondary-color); }
.lv-oa { display: flex; flex-direction: column; gap: .35rem; padding: 1rem 1.1rem; margin-bottom: .75rem;
  border: 1px solid var(--bs-border-color); border-radius: 12px; color: inherit; text-decoration: none;
  transition: border-color .15s ease-out; }
.lv-oa:hover { border-color: var(--bs-secondary-color); }
.lv-oa-head { display: flex; justify-content: space-between; align-items: center; gap: .5rem; }
.lv-oa-name { font-weight: 600; }
.lv-oa-kind, .lv-oa-row { font-size: .78rem; color: var(--bs-secondary-color); }
.lv-oa-row { display: flex; justify-content: space-between; gap: .5rem; }
.lv-oa-row b { font-weight: 500; color: var(--bs-body-color); }
.lv-oa-warn { font-size: .78rem; color: var(--st-bad); }
.lv-meter { display: block; height: 6px; margin-top: .35rem; border-radius: 3px; background: var(--bs-secondary-bg); overflow: hidden; }
.lv-meter-bar { display: block; height: 100%; border-radius: 3px; background: var(--st-ok); }
.lv-meter-bar.is-high { background: var(--st-bad); }
@media (max-width: 575.98px) { .lv-item { flex-wrap: wrap; } .lv-item .btn { margin-left: calc(32px + .75rem); } }
@media (prefers-reduced-motion: reduce) { .lv-oa { transition: none; } }
/* [52] ต่อ — แถวใต้การ์ด: ส่งผ่าน OA ไหน + ส่งให้ฉันดู (สีตัวหนังสือเข้มบนพื้นแชท 6:1) */
.lm-sw { display: flex; align-items: center; gap: 8px; justify-content: center; margin: 0 0 8px; padding: 0;
  font-size: 13px; color: #1d2b44; }
.lm-sw .form-check-input { margin: 0; float: none; }
.lm-off .lm-row { opacity: .45; }   /* การ์ดที่ปิดส่ง — ยังดูหน้าตาได้ */
.lm-act { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; margin-top: 8px; max-width: 500px; }
.lm-via { font-size: 12px; color: #1d2b44; }
.lm-act .btn { font-size: 13px; }

/* [54] search dropdown ผู้อนุมัติงบย่อย (vehicle_budget/sub.html · 2569-10-17) */
.sm-pick-list { max-height: 16rem; }
