/*
 * Design token จาก UI mockups สำหรับระบบอนุมัติ/design_handoff_attendance/README.md
 * ค่าสี ระยะ และขนาดตัวอักษรเป็นค่าตั้งใจทั้งหมด ห้ามเปลี่ยนโดยไม่ดู mockup ก่อน
 *
 * โครงหน้า (4 ก.ย. 2569 — ออกแบบใหม่ตามคำสั่งเจ้าของโครงการ "เมนูใช้ง่าย มือถือก็ได้ คอมก็ได้"):
 *   PC ≥ 900px : แถบเมนูซ้ายถาวร (.side) + หัวหน้า (.app-head) + เนื้อหา (.page)
 *   มือถือ      : หัวหน้าแบบย่อ + เนื้อหา + แถบเมนูล่าง (.bottom-nav)
 *   แท็บภายในหน้า (.page-tabs) ทำงานเหมือนกันทั้งสองจอ
 */
:root {
  --primary: #0e6b57;
  --primary-dark: #0a4f41;
  --primary-darker: #093f34;
  --bg-page: #f6f5f1;
  --bg-muted: #f1efe9;
  --surface: #ffffff;
  --border: rgba(0, 0, 0, 0.07);
  /* ขอบของช่องที่ "กดได้" — เส้น 0.07 จางเกินไป ดรอปดาวน์เลยดูเหมือนข้อความธรรมดา (พบ 8 ก.ย. 2569) */
  --border-input: rgba(0, 0, 0, 0.24);
  --text: #1c2a26;
  /* คอนทราสต์ต้องผ่านเกณฑ์อ่านออกกลางแดด (WCAG AA 4.5:1) — ค่าเดิม .5/.4 ได้แค่ 4.1:1 และ 2.9:1 */
  --text-muted: rgba(0, 0, 0, 0.62);
  --text-faint: rgba(0, 0, 0, 0.55);

  --success-bg: #dff0e9;
  --success-bg-soft: #e9f3ef;
  --success-text: #0a4f41;
  /* เหลือง = "อนุมาน" และ "รอตรวจ" — ความหมายนี้คงที่ทั้งระบบ ห้ามใช้สื่อความอื่น */
  --warn-bg: #fdf3dd;
  --warn-text: #8a5a08;
  --warn2-bg: #fce8d8;
  --warn2-text: #a05412;
  --info-bg: #e3ecf7;
  --info-text: #2b5c96;
  --danger-bg: #fdeaea;
  --danger-text: #a83232;
  --accent-dashed: #d9a53f;

  /**
   * สีเฉพาะปฏิทินหน้า "ข้อมูลของฉัน" (ออกแบบใหม่ 9 ก.ย. 2569)
   *
   * ของเดิมใช้โทเคนรวม (--warn-bg #fdf3dd · --warn2-bg #fce8d8 · --danger-bg #fdeaea)
   * ซึ่งสามตัวนี้เป็นโทนอุ่นจางเกือบเท่ากัน พอวางติดกัน 30 ช่องในปฏิทินแล้ว
   * เจ้าของโครงการอ่านไม่ออกว่าช่องไหนคืออะไร ("แทบไม่ต่างเลยบอกยากมาก")
   * จึงแยกชุดสีของปฏิทินออกมาต่างหาก **ไม่แตะโทเคนรวม** เพราะป้าย/ชิป/กล่องข้อความ
   * ทั้งระบบผูกความหมายกับโทเคนพวกนั้นอยู่ (เหลือง = อนุมาน/รอตรวจ ห้ามเปลี่ยนความหมาย)
   *
   * หลักที่ใช้แยก 3 แกน ไม่ใช่แค่สี — จะได้ยังอ่านออกตอนตาบอดสีและตอนพิมพ์ขาวดำ:
   *   1. เนื้อสี  เขียว / แดง / ส้ม / เหลือง / ฟ้า / เทา
   *   2. ความเข้ม  "มีเรื่องเกิดขึ้นจริง" = พื้นเข้ม · "รอ/ไม่รู้" = พื้นจาง · "ไม่ต้องสนใจ" = เทา
   *   3. เส้นขอบ  ทึบ = ตัดสินแล้ว · ประ = ยังไม่จบ · ไม่มีขอบ = จบแล้วไม่ต้องทำอะไร
   *
   * คู่ที่เคยสับสนที่สุดคือ "สาย" กับ "รอตรวจ" — คราวนี้ต่างกันทั้งความเข้ม (ส้มเข้ม vs เหลืองจาง)
   * และเส้นขอบ (ไม่มีขอบ vs ประหนา) ไม่ได้พึ่งเนื้อสีอย่างเดียวเหมือนเดิม
   * ทุกคู่สีตัวอักษร/พื้นผ่าน WCAG AA (≥ 4.5:1)
   */
  --cal-ontime-bg: #b9e3d0;      --cal-ontime-fg: #08483b;
  --cal-late-bg: #fbd08a;        --cal-late-fg: #7a4206;
  --cal-official-bg: #f5b8b8;    --cal-official-fg: #7d1d1d;   --cal-official-line: #a12b2b;
  --cal-pending-bg: #fdf3dd;     --cal-pending-fg: #8a5a08;    --cal-pending-line: #d9a53f;
  --cal-leave-bg: #bcd6f0;       --cal-leave-fg: #1c4a7a;
  --cal-holiday-bg: #eceae6;     --cal-holiday-fg: rgba(0, 0, 0, 0.42);
  --cal-unknown-line: rgba(0, 0, 0, 0.22);

  --radius-card: 13px;
  --radius-ctl: 9px;
  --radius-badge: 5px;
  --shadow-card: 0 2px 8px rgba(0, 0, 0, 0.06);
  --shadow-btn: 0 3px 8px rgba(14, 107, 87, 0.3);

  --font-head: 'Anuphan', 'Sarabun', system-ui, sans-serif;
  --font-body: 'Sarabun', system-ui, sans-serif;

  --side-w: 232px;
}

* { box-sizing: border-box; }

/* ให้ hidden ชนะ display ของ class เสมอ — ไม่งั้น .card-exception{display:flex} จะโผล่ทั้งที่ซ่อนไว้ */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--bg-page);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 12.5px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, .num { font-family: var(--font-head); margin: 0; }

/* ══ โครงหน้าร่วม (app shell) ═══════════════════════════════════════════ */
.app { display: flex; min-height: 100dvh; }

.brand-mark {
  width: 30px; height: 30px; border-radius: 9px; background: var(--primary);
  display: grid; place-items: center; color: #fff; flex: none;
}
.brand-mark svg { width: 62%; height: 62%; }

/* แถบเมนูซ้าย (PC) */
.side {
  width: var(--side-w); flex: none; background: var(--surface); border-right: 1px solid var(--border);
  position: sticky; top: 0; height: 100dvh; display: flex; flex-direction: column; gap: 12px; padding: 18px 14px 16px;
}
.side-brand { display: flex; align-items: center; gap: 10px; padding: 2px 6px 8px; font-family: var(--font-head); font-weight: 700; font-size: 14px; line-height: 1.2; }
.side-brand small { display: block; font-weight: 500; color: var(--text-muted); font-size: 11px; margin-top: 2px; }
.side-user { display: flex; gap: 10px; align-items: center; padding: 10px; border-radius: 12px; background: var(--bg-muted); text-decoration: none; color: inherit; }
.side-user:hover { background: #e8e5dd; }
.side-user .avatar { width: 38px; height: 38px; }
.side-user-text { min-width: 0; }
.side-user-name { display: block; font-family: var(--font-head); font-weight: 700; font-size: 13px; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-user-role { display: block; font-size: 11px; color: var(--text-muted); margin-top: 2px; }
.side-nav { display: flex; flex-direction: column; gap: 3px; }
.nav-item {
  display: flex; align-items: center; gap: 11px; width: 100%; padding: 10px 12px; border-radius: 10px;
  text-decoration: none; color: var(--text); font-family: var(--font-head); font-weight: 600; font-size: 13px;
  border: 0; background: none; cursor: pointer; text-align: left;
}
.nav-item:hover { background: var(--bg-muted); }
.nav-item.is-active { background: var(--success-bg-soft); color: var(--primary-dark); }
.nav-ico { width: 18px; height: 18px; flex: none; color: var(--text-muted); display: inline-grid; place-items: center; }
.nav-ico svg { width: 18px; height: 18px; }
.nav-item.is-active .nav-ico { color: var(--primary); }
.side-foot { margin-top: auto; display: flex; flex-direction: column; gap: 6px; }
.side-foot .nav-item { color: var(--text-muted); }
.side-ver { font-size: 10.5px; color: var(--text-faint); padding: 0 6px; }

/* พื้นที่หลัก + หัวหน้า */
.app-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.app-head {
  position: sticky; top: 0; z-index: 10;
  background: rgba(246, 245, 241, 0.94); backdrop-filter: blur(8px); border-bottom: 1px solid var(--border);
  padding: 14px 28px; display: flex; align-items: center; gap: 14px;
}
.app-head .brand-mini { display: none; }
.app-head-title { flex: 1; min-width: 0; }
.app-head h1 { font-size: 19px; font-weight: 700; line-height: 1.25; }
.app-head-sub { font-size: 12px; color: var(--text-muted); margin-top: 1px; }
.app-head-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.app-head .back-link { margin-bottom: 0; }
.avatar {
  width: 34px; height: 34px; border-radius: 50%; background: var(--success-bg-soft);
  color: var(--primary-dark); display: grid; place-items: center;
  font-family: var(--font-head); font-weight: 700; font-size: 12px; flex: none; text-decoration: none;
}

.page { max-width: 1180px; width: 100%; margin: 0 auto; padding: 20px 28px 60px; }
.bottom-nav { display: none; }

/* แถบสถานะความสดของข้อมูล — ใต้หัวหน้าทุกหน้า (shell.js renderDataStatus)
   บรรทัดเดียว (~30px) กดแล้วคลี่รายละเอียด — เจ้าของโครงการเลือกแบบนี้ 6 ก.ย. 2569 เพราะแบบ 4 บรรทัดกินที่บนมือถือ */
.data-status {
  font-size: 12px; color: var(--text-muted); border-radius: 10px;
  background: var(--success-bg-soft); margin-bottom: 12px;
}
.data-status b { color: var(--primary-dark); font-family: var(--font-head); }
.data-status.is-warn { background: var(--warn-bg); color: var(--warn-text); }
.data-status.is-warn b { color: inherit; }
/* แถวบน = ปุ่มทั้งแถว (มือถือแตะง่าย) · แบบ is-static = ไม่มีอะไรให้คลี่ (กำลังโหลด / ยังไม่มีข้อมูล) */
.ds-row {
  display: flex; align-items: center; gap: 8px; width: 100%; min-height: 30px;
  padding: 5px 10px 5px 12px; background: none; border: 0; border-radius: 10px;
  color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.ds-row.is-static { cursor: default; }
.ds-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.ds-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ds-stale { font-weight: 600; }
.ds-ico { width: 16px; height: 16px; display: inline-grid; place-items: center; color: var(--primary); flex: none; }
.ds-ico svg { width: 16px; height: 16px; }
.data-status.is-warn .ds-ico { color: var(--warn-text); }
.ds-caret { width: 16px; height: 16px; flex: none; display: inline-grid; place-items: center; opacity: 0.7; transition: transform 0.15s; }
.ds-caret svg { width: 16px; height: 16px; }
.data-status.is-open .ds-caret { transform: rotate(180deg); }
/* รายละเอียดที่คลี่ — จัดชิดข้อความของแถวบน (เว้นไอคอน) */
.ds-detail { display: none; flex-direction: column; gap: 3px; padding: 0 12px 9px 36px; line-height: 1.5; }
.data-status.is-open .ds-detail { display: flex; }
.ds-detail [data-help] { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.ds-link { font-family: var(--font-head); font-weight: 600; color: var(--primary); text-decoration: none; white-space: nowrap; }
.ds-row .ds-link { margin-left: auto; }
.ds-detail .ds-link { align-self: flex-start; margin-top: 3px; }
.data-status.is-warn .ds-link { color: var(--warn-text); text-decoration: underline; }

/* แท็บภายในหน้า — segmented control ทำงานเหมือนกันทั้งมือถือและ PC */
.page-tabs {
  display: flex; gap: 4px; background: var(--bg-muted); padding: 4px; border-radius: 12px;
  width: max-content; max-width: 100%; overflow-x: auto; scrollbar-width: none; margin-bottom: 14px;
}
.page-tabs::-webkit-scrollbar { display: none; }
.page-tab {
  border: 0; background: none; font-family: var(--font-head); font-weight: 600; font-size: 12.5px;
  padding: 8px 14px; border-radius: 9px; color: var(--text-muted); cursor: pointer; white-space: nowrap; text-decoration: none;
  display: inline-flex; align-items: center; gap: 6px;
}
.page-tab[aria-selected='true'] { background: var(--surface); color: var(--primary-dark); box-shadow: var(--shadow-card); }
.page-tab:hover:not([aria-selected='true']) { color: var(--text); }

/* มือถือ */
@media (max-width: 899px) {
  .side { display: none; }
  .app-head { padding: 10px 14px; gap: 10px; }
  .app-head .brand-mini { display: grid; width: 32px; height: 32px; }
  .app-head h1 { font-size: 15px; }
  .app-head-sub { font-size: 11px; }
  /* มือถือมีเมนูล่างแล้ว ปุ่มย้อนกลับในหัวหน้าเปลืองที่จนชื่อหน้าตกบรรทัด */
  .app-head .back-link { display: none !important; }
  .mob-hide { display: none !important; }
  .app-head .badge-round { padding: 3px 8px; font-size: 11px; }
  .app-head-actions { gap: 6px; }
  .page { padding: 14px 12px calc(84px + env(safe-area-inset-bottom)); }
  .bottom-nav {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
    background: var(--surface); border-top: 1px solid var(--border);
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom)); justify-content: space-around;
  }
  .bottom-nav a {
    flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 0;
    text-decoration: none; color: var(--text-muted); font-family: var(--font-head); font-weight: 600; font-size: 10.5px;
    padding: 4px 2px; border-radius: 10px;
    /* ผู้ดูแลระบบที่เป็นผู้บริหารด้วยมีเมนูถึง 7 ช่อง — ป้ายยาวต้องตัดท้าย ไม่ใช่ดันแถบเสียรูป */
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .bottom-nav .nav-ico, .bottom-nav .nav-ico svg { width: 22px; height: 22px; }
  /* บัญชีที่เป็นทั้งผู้บริหารและผู้ดูแลระบบมีเมนูถึง 9 ช่อง — ที่ 375px เหลือช่องละ 41px
     ป้าย 6 ตัวอักษร ("ภาพรวม" "ทะเบียน") ที่ 10.5px กว้างเกินจนชนช่องข้าง ๆ จึงย่อลงเมื่อเมนูแน่น
     (นับพี่น้องด้วย :nth-last-child — ไม่ต้องพึ่ง JS และไม่กระทบเมนูสั้นของเจ้าหน้าที่ทั่วไป) */
  .bottom-nav a:first-child:nth-last-child(n+8),
  .bottom-nav a:first-child:nth-last-child(n+8) ~ a { font-size: 9px; gap: 2px; padding: 4px 0; }
  .bottom-nav a:first-child:nth-last-child(n+8) .nav-ico,
  .bottom-nav a:first-child:nth-last-child(n+8) ~ a .nav-ico,
  .bottom-nav a:first-child:nth-last-child(n+8) .nav-ico svg,
  .bottom-nav a:first-child:nth-last-child(n+8) ~ a .nav-ico svg { width: 20px; height: 20px; }
  .bottom-nav a.is-active { color: var(--primary); }
  .bottom-nav a.is-active .nav-ico { color: var(--primary); }
  .card { padding: 13px; }
}

/* ══ โครงหน้าย่อย ════════════════════════════════════════════════════════ */
.split { display: grid; grid-template-columns: 340px 1fr; gap: 16px; align-items: start; }
@media (max-width: 899px) { .split { grid-template-columns: 1fr; } }
/* grid item มี min-width:auto โดยปริยาย — ตารางกว้างจะดันทั้งหน้าให้เกิน viewport บนมือถือ */
.split > *, .two-col > * { min-width: 0; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 16px;
}
.card + .card { margin-top: 14px; }
.card-title { font-size: 14.5px; font-weight: 600; font-family: var(--font-head); }
.card-sub { font-size: 11.5px; color: var(--text-muted); margin-top: 2px; }
.stack { display: flex; flex-direction: column; gap: 12px; }
.stack > .card { margin: 0; }

/* ── ปุ่ม ─────────────────────────────────────────────────────────────── */
.btn {
  font-family: var(--font-head); font-size: 12.5px; font-weight: 600;
  border-radius: var(--radius-ctl); border: 1px solid transparent;
  padding: 8px 14px; cursor: pointer; background: var(--bg-muted); color: var(--text);
  transition: background 0.12s, color 0.12s; text-decoration: none; display: inline-block;
}
.btn:hover:not(:disabled) { background: #e8e5dd; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-primary { background: var(--primary); color: #fff; box-shadow: var(--shadow-btn); }
.btn-primary:hover:not(:disabled) { background: var(--primary-dark); }
.btn-sm { padding: 6px 10px; font-size: 11.5px; }

/* ── ป้ายสถานะ ───────────────────────────────────────────────────────── */
.badge {
  display: inline-block; padding: 2.5px 8px; border-radius: var(--radius-badge);
  font-size: 10.5px; font-weight: 700; font-family: var(--font-head); white-space: nowrap;
}
/* ป้ายที่ข้อความยาว (เช่น ชื่อกลุ่มเวลา + ช่วงเวลา) ให้ตัดบรรทัดในกรอบ ไม่ล้นการ์ด */
.badge-wrap { white-space: normal; line-height: 1.35; max-width: 100%; }
.badge-ok { background: var(--success-bg); color: var(--success-text); }
/* "อนุมาน" และ "รอตรวจ" ใช้สีเดียวกันโดยตั้งใจ — สื่อว่ายังไม่ใช่ข้อสรุป */
.badge-warn { background: var(--warn-bg); color: var(--warn-text); }
.badge-warn2 { background: var(--warn2-bg); color: var(--warn2-text); }
.badge-info { background: var(--info-bg); color: var(--info-text); }
.badge-danger { background: var(--danger-bg); color: var(--danger-text); }
/* ป้ายที่กดอ่านคำอธิบายได้ — help.js ผูกให้เองเมื่อ .badge เขียน data-help ไว้ (v1.5.5)
   เส้นประใต้ข้อความเป็นสัญญาณเดียวที่บอกว่ากดได้ ไม่เพิ่มปุ่มเพราะป้ายมีหลายสิบใบต่อหน้า */
.badge-help { cursor: help; text-decoration: underline dotted currentColor; text-underline-offset: 2px; }
.badge-help:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.badge-role {
  background: var(--bg-muted); color: var(--text-muted);
  padding: 2px 8px; border-radius: var(--radius-badge); font-size: 10.5px; font-weight: 600;
}

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  border: 0; cursor: pointer; font-family: var(--font-head); font-weight: 600;
  font-size: 11.5px; padding: 5px 12px; border-radius: 20px;
  background: var(--bg-muted); color: var(--text-muted);
}
.chip[aria-pressed='true'] { outline: 2px solid currentColor; outline-offset: -2px; }
.chip-warn { background: var(--warn-bg); color: var(--warn-text); }
.chip-warn2 { background: var(--warn2-bg); color: var(--warn2-text); }
.chip-info { background: var(--info-bg); color: var(--info-text); }
.chip-danger { background: var(--danger-bg); color: var(--danger-text); }

/* ── dropzone ────────────────────────────────────────────────────────── */
.dropzone {
  border: 2px dashed rgba(14, 107, 87, 0.4);
  border-radius: var(--radius-card);
  background: var(--surface);
  padding: 30px 18px; text-align: center; transition: background 0.15s, border-color 0.15s;
}
.dropzone.is-over { background: var(--success-bg-soft); border-color: var(--primary); }
.dropzone-icon {
  width: 52px; height: 52px; margin: 0 auto 12px; border-radius: 14px;
  background: var(--success-bg-soft); color: var(--primary);
  display: grid; place-items: center;
}
.dropzone h2 { font-size: 15px; font-weight: 700; }
.dropzone p { color: var(--text-muted); font-size: 11.5px; margin: 6px 0 14px; }

/* ── แถวสรุป ─────────────────────────────────────────────────────────── */
.stat { display: flex; justify-content: space-between; align-items: baseline; padding: 5px 0; }
.stat-label { color: var(--text-muted); font-size: 12px; }
.stat-value { font-family: var(--font-head); font-weight: 700; font-size: 15px; }
.stat-value.ok { color: var(--primary); }
.stat-value.warn { color: var(--warn2-text); }
.stat-value.muted { color: var(--text-muted); }

.stackbar { display: flex; height: 8px; border-radius: 4px; overflow: hidden; background: var(--bg-muted); margin-top: 10px; }
.stackbar > span { display: block; height: 100%; }

/* ── ตาราง ───────────────────────────────────────────────────────────── */
.table { width: 100%; border-collapse: collapse; }
.table th {
  text-align: left; font-family: var(--font-head); font-weight: 600; font-size: 11.5px;
  color: var(--text-muted); padding: 10px 12px; border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.table td { padding: 12px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.table tbody tr:hover { background: #faf9f6; }
.table tbody tr:last-child td { border-bottom: 0; }
.table-wrap { overflow-x: auto; }
.cell-name { font-weight: 600; }
.cell-muted { color: var(--text-muted); font-size: 11.5px; }
.row-actions { display: flex; gap: 6px; justify-content: flex-end; flex-wrap: wrap; }

/* รายการสรุปข้อความยาว ๆ (หน้าประกาศ) — หัวข้อหนา ตามด้วยคำอธิบาย อ่านง่ายบนมือถือ */
.plain-list { list-style: none; display: flex; flex-direction: column; gap: 7px; margin-top: 8px; font-size: 12.5px; line-height: 1.65; }
.plain-list li { padding-left: 13px; position: relative; color: var(--text-muted); }
.plain-list li::before { content: ''; position: absolute; left: 0; top: 8px; width: 5px; height: 5px; border-radius: 50%; background: var(--primary); }
.plain-list b { color: var(--text); }

/* ตารางบนมือถือกลายเป็นการ์ดรายแถว — แต่ละช่องมีป้ายชื่อคอลัมน์ (data-label) */
@media (max-width: 899px) {
  .table-cards thead { display: none; }
  .table-cards, .table-cards tbody, .table-cards td { display: block; width: 100%; }
  /* แถวไม่ใส่ width:100% — แถวมี margin ซ้ายขวา 12px ถ้ากว้าง 100% ด้วยจะล้นขวา 24px
     (ขอบขวาของการ์ดถูกตัดทุกหน้า: ประกาศ · ภาพรวม · นำเข้า · การมาสาย — พบ 12 ก.ย. 2569) */
  .table-cards tr { display: block; border: 1px solid var(--border); border-radius: 12px; margin: 10px 12px; padding: 10px 12px; background: var(--surface); }
  .table-cards tr:hover { background: var(--surface); }
  .table-cards td { border: 0; padding: 5px 0; }
  .table-cards td[data-label]::before { content: attr(data-label); display: block; font-family: var(--font-head); font-size: 10.5px; color: var(--text-muted); font-weight: 600; margin-bottom: 2px; }
  .table-cards td.empty { text-align: center; }
  .table-cards .row-actions { justify-content: flex-start; }
}

/* ── สถานะพิเศษ ──────────────────────────────────────────────────────── */
.empty { text-align: center; padding: 40px 16px; color: var(--text-muted); }
.notice {
  border-radius: var(--radius-ctl); padding: 10px 13px; font-size: 12px; margin-bottom: 12px;
}
.notice-error { background: var(--danger-bg); color: var(--danger-text); }
.notice-ok { background: var(--success-bg); color: var(--success-text); }
.notice-warn { background: var(--warn-bg); color: var(--warn-text); }

.spinner {
  width: 15px; height: 15px; border: 2px solid rgba(255, 255, 255, 0.4);
  border-top-color: #fff; border-radius: 50%; display: inline-block;
  animation: spin 0.7s linear infinite; vertical-align: -2px;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ══ หน้าเจ้าหน้าที่ (/me) ═══════════════════════════════════════════════ */
.me-grid { display: flex; flex-direction: column; gap: 12px; }
.me-grid > .card { margin: 0; }
.area-score > * { min-width: 0; }
/* 900–1279px: สองคอลัมน์ · ประวัติเต็มความกว้างข้างล่าง
   เดิมยัดสามคอลัมน์ตั้งแต่ 900px ทำให้คอลัมน์ประวัติเหลือ ~200px แล้วบรรทัด
   "เข้า 07:43 → ออก 16:02" หักบรรทัดทีละคำ อ่านไม่ออก (พบบนจอ ~1080px 7 ก.ย. 2569) */
@media (min-width: 900px) {
  .me-grid {
    display: grid; gap: 16px; align-items: start;
    grid-template-columns: 340px minmax(0, 1fr);
    grid-template-rows: auto auto auto auto auto auto auto;
    /* แถว punch ว่างสำหรับเกือบทุกคน (การ์ดซ่อนอยู่) — auto จึงยุบเหลือ 0 ไม่เกิดช่องว่าง */
    grid-template-areas:
      "status status"
      "notice notice"
      "score  cal"
      "punch  cal"
      "kpi    cal"
      "exc    cal"
      "hist   hist";
  }
  .me-grid > .data-status { grid-area: status; margin-bottom: 0; }
  .me-grid > #pageNotice { grid-area: notice; }
  .me-grid > .area-score { grid-area: score; }
  .me-grid > .area-kpi { grid-area: kpi; }
  .me-grid > .area-cal { grid-area: cal; }
  .me-grid > .area-hist { grid-area: hist; }
  .me-grid > .area-exc { grid-area: exc; }
  .me-grid > .area-punch { grid-area: punch; }
  .me-grid .card { padding: 18px; }
}

/* ≥1280px: กว้างพอให้ประวัติอยู่คอลัมน์ขวาได้จริง (ต้องเหลือให้คอลัมน์นี้ ≥ 300px)
   แถวสุดท้าย (pad) เปล่าในคอลัมน์ซ้าย ไว้ซับความสูงส่วนเกินจากปฏิทิน/ประวัติที่ยาวกว่า
   ไม่งั้น grid จะยืดแถว score/kpi/exc ให้สูงตาม แล้วการ์ดหล่นเกาะหัวแถว เกิดช่องว่างใหญ่ */
@media (min-width: 1280px) {
  .me-grid {
    grid-template-columns: 340px minmax(380px, 460px) minmax(300px, 1fr);
    grid-template-rows: auto auto auto auto auto auto 1fr;
    grid-template-areas:
      "status status status"
      "notice notice notice"
      "score  cal    hist"
      "punch  cal    hist"
      "kpi    cal    hist"
      "exc    cal    hist"
      "pad    cal    hist";
  }
}

/* วงแหวนคะแนน conic-gradient 76px */
.ring {
  width: 76px; height: 76px; border-radius: 50%; flex: none; display: grid; place-items: center;
  background: conic-gradient(var(--primary) calc(var(--pct, 0) * 1%), var(--bg-muted) 0);
}
.ring > span {
  width: 60px; height: 60px; border-radius: 50%; background: var(--surface);
  display: grid; place-items: center; font-family: var(--font-head); font-weight: 700;
  font-size: 26px; color: var(--primary);
}
/*
 * ยังมีวันทำการที่ไม่มีสแกนและยังไม่ชี้แจง — คะแนนยังไม่สมบูรณ์
 * จึงใช้เขียวจางแทนเขียวเข้ม ไม่ใช้ opacity กับทั้งวง (ตัวเลขข้างในจะจางไปด้วยจนอ่านยาก)
 */
.ring.is-provisional { background: conic-gradient(var(--success-bg) calc(var(--pct, 0) * 1%), var(--bg-muted) 0); }
.ring.is-provisional > span { color: var(--text-muted); }

.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.pair > .card { margin: 0; }
.kpi-label { font-size: 12px; color: var(--text-muted); font-weight: 600; }
.kpi-num { font-family: var(--font-head); font-weight: 700; font-size: 28px; line-height: 1.15; margin-top: 2px; }
.kpi-num small { font-size: 14px; font-weight: 600; margin-left: 2px; }
.kpi-note { font-size: 11px; color: var(--text-muted); margin-top: 3px; }
.card-soft { background: var(--success-bg-soft); border-color: transparent; }
.card-soft .kpi-num { color: var(--primary-dark); }

/* ปฏิทินเดือน — สีแต่ละสถานะตรง mockup 1b */
.cal { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; }
.cal-dow { text-align: center; font-size: 10.5px; color: var(--text-muted); padding-bottom: 2px; }
.cal-cell {
  aspect-ratio: 1; border-radius: 8px; display: grid; place-items: center;
  font-family: var(--font-head); font-weight: 600; font-size: 12.5px;
  border: 1.5px solid transparent; background: var(--bg-muted); color: var(--text-faint);
}
/* มาตรงเวลา — จบแล้ว ไม่ต้องทำอะไร จึงไม่มีขอบ */
.cal-cell.on_time { background: var(--cal-ontime-bg); color: var(--cal-ontime-fg); }
/**
 * สายมีสองระดับ ห้ามยุบเป็นสีเดียว (เจ้าของโครงการขอสีแดง 9 ก.ย. 2569)
 *
 *  late_official = นับเข้ามาตรการได้จริง → แดง + ขอบทึบ + ตัวหนา
 *  late          = สายแต่ "ยังไม่นับ" (เวรผลัดก่อนวันเริ่มนับ · คนที่ยังไม่ระบุกลุ่มเวลา)
 *                  หรือกลับก่อนเวลา → คงสีอำพันไว้ **ห้ามทำเป็นแดง**
 *
 * เหตุผล: CLAUDE.md ข้อ 4 บังคับให้แยกให้ชัดว่าตัวเลขไหนเป็นทางการ ตัวไหนยังไม่นับ
 * ในเดือนตัวอย่างที่เจ้าของโครงการส่งมา 12 วันเป็นตัวเลขอนุมานที่ยังไม่นับเป็นสายทางการ
 * ถ้าทาแดงทั้งหมดจะกลายเป็นการกล่าวหาด้วยตัวเลขที่ระบบเองยังไม่ยืนยัน
 *
 * ขอบทึบ + ตัวหนาเป็นสัญญาณที่ไม่ใช่สี — คนตาบอดสีแดง-เขียว (พบบ่อยที่สุด) ยังแยกออก
 * และยังแยกออกเมื่อพิมพ์ขาวดำ ซึ่งเป็นวิธีที่หัวหน้ากลุ่มงานเอาไปแนบวาระประชุม
 */
.cal-cell.late_official {
  background: var(--cal-official-bg);
  color: var(--cal-official-fg);
  border-color: var(--cal-official-line);
  border-width: 2px;
  font-weight: 700;
}
/* สายที่ยังไม่นับ — ส้มเข้ม ไม่มีขอบ · ต่างจาก "รอตรวจ" ทั้งความเข้มและเส้นขอบ ไม่ใช่แค่เนื้อสี */
.cal-cell.late { background: var(--cal-late-bg); color: var(--cal-late-fg); }
/* รอตรวจ — เหลืองจาง + ประหนา (ยังไม่จบ ต้องมีคนมากด) */
.cal-cell.pending {
  background: var(--cal-pending-bg); color: var(--cal-pending-fg);
  border: 2px dashed var(--cal-pending-line);
}
.cal-cell.leave { background: var(--cal-leave-bg); color: var(--cal-leave-fg); }
.cal-cell.today { background: var(--primary); color: #fff; }
.cal-cell.future { background: transparent; border-color: var(--border); }
/* วันที่ผ่านมาแล้วแต่ยังไม่นำเข้าข้อมูล — ต้องไม่ดูเหมือน "ไม่มา" */
.cal-cell.nodata { background: transparent; border: 1.5px dashed var(--cal-unknown-line); color: var(--text-faint); }
/* ข้อมูลมาถึงแล้วแต่ยังไม่ครบทั้งวัน ("ยังไม่ปิดวัน") — จางเหมือน .nodata เพราะยังไม่มีอะไรให้ทำเหมือนกัน
   แยกคลาสไว้เพื่อให้เปลี่ยนทีหลังได้โดยไม่กระทบ "ยังไม่นำเข้าข้อมูล" ซึ่งคนละเรื่องกัน */
.cal-cell.notclosed { background: transparent; border: 1.5px dashed var(--cal-unknown-line); color: var(--text-faint); }

/* บรรทัดบอกสถานะที่ไม่ต้องทำอะไร (เช่น "ยังไม่ปิดวัน") — จางกว่า card-sub ปกติ ไม่แย่งสายตากับงานที่ต้องกด */
.is-muted-note { color: var(--text-faint); font-style: italic; }
/* วันทำการที่ไม่มีสแกนเลย และยังไม่มีใครตรวจ — ว่างเปล่าแต่มีเรื่องต้องทำ จึงเป็นกรอบประสีเหลือง ไม่ใช่พื้นทึบ
   ต่างจาก .nodata (ประจาง = ยังไม่นำเข้า) และ .pending (พื้นเหลือง = มีช่วงงานแต่ติดธง) */
.cal-cell.noscan { background: transparent; border: 2px dashed var(--cal-pending-line); color: var(--cal-pending-fg); }
/* วันหยุดของคนเวลาตายตัว (เสาร์ อาทิตย์ วันหยุดราชการ) — เงียบ ไม่เตือน ไม่ประ */
.cal-cell.holiday { background: var(--cal-holiday-bg); border-color: transparent; color: var(--cal-holiday-fg); }
.cal-cell.blank { background: transparent; }
.cal-cell.has-data { cursor: pointer; }
.cal-cell.has-data:active { transform: scale(0.94); }
/* วันที่กำลังเลือกดูอยู่ — ใช้กรอบหนาแทนการเปลี่ยนสีพื้น เพื่อไม่ให้ทับสีสถานะ (ตรงเวลา/สาย/รอตรวจ) ที่ช่องนั้นสื่ออยู่ */
.cal-cell.is-picked { box-shadow: 0 0 0 2px var(--primary); font-weight: 700; }

/* แถบ "กำลังดูเฉพาะวันที่ …" เหนือรายการประวัติ พร้อมปุ่มกลับไปดูทั้งเดือน */
.hist-filter {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 8px; padding: 7px 10px; border-radius: 8px;
  background: var(--info-bg); color: var(--info-text); font-size: 12px; font-weight: 600;
}
.legend { display: flex; flex-wrap: wrap; gap: 10px; font-size: 10.5px; color: var(--text-muted); margin-top: 10px; }
.legend i { display: inline-block; width: 11px; height: 11px; border-radius: 3px; margin-right: 4px; vertical-align: -1px; border: 1.5px solid transparent; }

/* แถว "ชื่อที่จับคู่ไม่ได้" ในหน้านำเข้าไฟล์ — ปุ่มข้อเสนอตกบรรทัดเองเมื่อชื่อยาว */
.unmatched-row { display: flex; gap: 10px; padding: 10px 2px; border-bottom: 1px solid var(--border); }
.unmatched-row:last-child { border-bottom: 0; }
.unmatched-row .row-actions { justify-content: flex-start; }

/* รายการประวัติการสแกนรายวัน */
/* flex + wrap (ไม่ใช่ grid 3 คอลัมน์ตายตัว) — คอลัมน์แคบลงเมื่อไร ป้ายสถานะจะตกลงบรรทัดใหม่
   แทนที่จะบีบข้อความเวลาให้หักทีละคำ (พบบนจอ ~1080px 7 ก.ย. 2569) */
.hist-row {
  display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center;
  padding: 10px 4px; border-bottom: 1px solid var(--border); transition: background 0.3s;
}
.hist-row > .hist-date { flex: none; width: 44px; }
.hist-row > .hist-body { flex: 1 1 190px; }
/* ทุกอย่างที่เหลือ (ป้ายสถานะ · ปุ่มชี้แจง) ชิดขวาเสมอ แล้วตกบรรทัดใหม่เองเมื่อที่ไม่พอ */
.hist-row > :not(.hist-date):not(.hist-body) { margin-left: auto; flex: none; }
/* "เข้า 07:43" กับ "ออก 16:02" ต้องไม่ถูกหักกลางวลี — หักได้เฉพาะตรงลูกศร */
.hist-times > .nw { white-space: nowrap; }
.hist-row:last-child { border-bottom: 0; }
.hist-row.is-flash { background: var(--warn-bg); }
.hist-date { text-align: center; line-height: 1.1; }
.hist-date b { display: block; font-family: var(--font-head); font-size: 17px; }
.hist-date span { font-size: 10px; color: var(--text-muted); }
.hist-body { min-width: 0; }
.hist-times { font-family: var(--font-head); font-weight: 600; font-size: 13px; }
.hist-meta { font-size: 11px; color: var(--text-muted); margin-top: 2px; }

/* การ์ดชี้แจง exception */
.card-exception { background: #fffbf0; border-color: rgba(217, 165, 63, 0.4); display: flex; gap: 12px; align-items: center; }
/* การ์ดแนะนำของใหม่ช่วงเริ่มใช้ — ขึ้นเฉพาะตอนมีรายการค้างจริง แล้วหายเองเมื่อเคลียร์หมด (ไม่ใช่ประกาศถาวร) */
.card-intro { background: var(--success-bg-soft); border-color: rgba(14, 107, 87, 0.3); margin-bottom: 12px; }
.card-intro .intro-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; flex-wrap: wrap; }
.card-intro ul { margin: 8px 0 0; padding-left: 18px; font-size: 12.5px; line-height: 1.55; }
.card-intro li { margin-bottom: 2px; }
.exc-icon { width: 40px; height: 40px; border-radius: 11px; background: var(--warn-bg); color: var(--warn-text); display: grid; place-items: center; flex: none; }

/* ══ หน้าทีม (/team) ═══════════════════════════════════════════════════ */
.team-grid { display: flex; flex-direction: column; gap: 12px; }
/* ค้นหา/กรองลูกทีม */
.team-filters { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.search-input {
  flex: 1; min-width: 160px; padding: 9px 12px; font: inherit; font-size: 13px;
  border: 1px solid var(--border); border-radius: var(--radius-ctl); background: var(--surface); color: var(--text);
}
.search-input:focus { outline: none; border-color: rgba(14, 107, 87, 0.35); box-shadow: 0 0 0 1.5px rgba(14, 107, 87, 0.35); }
/**
 * ดรอปดาวน์ในหน้า (กลุ่มงาน · งาน · เดือน) — ต้องดูออกทันทีว่ากดเลือกได้
 * (เจ้าของโครงการ 8 ก.ย. 2569: "บางทีมองไม่ออกเลยว่าเลือกได้")
 * วาดลูกศรเองด้วย background-image เพราะลูกศรของระบบบางเครื่อง (iOS/Android) แทบมองไม่เห็น
 * ห้ามใช้ `background:` แบบย่อทับ ไม่งั้นลูกศรหาย
 */
.sel-inline {
  appearance: none; -webkit-appearance: none;
  padding: 9px 32px 9px 11px; min-height: 38px;
  font: inherit; font-size: 12.5px; font-weight: 600;
  border: 1px solid var(--border-input); border-radius: var(--radius-ctl);
  background-color: var(--surface); color: var(--text); max-width: 100%; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230a4f41' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; background-size: 14px;
}
.sel-inline:hover { border-color: var(--primary); }
.sel-inline:focus-visible { outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px rgba(14, 107, 87, 0.28); }
/** ป้ายหน้าดรอปดาวน์ — บอกว่าแถวนี้คือตัวเลือก ไม่ใช่หัวข้อ */
.sel-label { font-size: 11.5px; font-weight: 600; color: var(--text-muted); align-self: center; }
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
/**
 * "ยังไม่ปิดวัน" เหนือรายการลูกทีม — เป็นคำอธิบายว่าทำไมบางวันยังว่าง ไม่ใช่งานที่ต้องกด
 * ใช้สีข้อมูล (ฟ้า) เท่านั้น · ห้ามใช้เหลือง เพราะทั้งระบบเหลือง = "รอตรวจ/ยังไม่นับ"
 * (v1.6.7 — ของเดิมเป็นตัวเอียงสีจาง เจ้าของโครงการอ่านผ่านตลอด)
 */
.day-open-note {
  display: flex; align-items: center; gap: 8px; padding: 9px 12px; border-radius: 10px;
  background: var(--info-bg); color: var(--info-text);
  font-size: 12.5px; font-weight: 600; line-height: 1.5;
}
.day-open-note .don-ico { flex: none; display: inline-grid; place-items: center; }
.day-open-note .don-ico svg { width: 17px; height: 17px; }
.day-open-note .help-dot { border-color: currentColor; color: inherit; }
.team-col { min-width: 0; display: flex; flex-direction: column; gap: 12px; }
#memberList { display: grid; gap: 10px; }
#memberList > .card { margin: 0; }
#certifySection { display: flex; flex-direction: column; gap: 12px; }
#certifySection > .card { margin: 0; }
.team-aside > .card { margin: 0; }
@media (min-width: 900px) {
  .team-grid { display: grid; grid-template-columns: 1fr 340px; gap: 16px; align-items: start; }
  #memberList { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  #memberList > .card-sub, #memberList > .day-open-note { grid-column: 1 / -1; }
  /* PC: แผนภาพเวลาอยู่คอลัมน์ขวาเสมอ แท็บ "ภาพรวมเวลา" จึงไม่ต้องมี */
  .team-aside { position: sticky; top: 76px; }
  .team-aside[hidden] { display: block !important; }
  .page-tab.pc-hide { display: none; }
}
.badge-round { background: var(--warn2-bg); color: var(--warn2-text); border-radius: 20px; padding: 4px 11px; font-family: var(--font-head); font-weight: 700; font-size: 12px; white-space: nowrap; }
.member { display: flex; gap: 11px; align-items: center; flex-wrap: wrap; }
.member.is-pending { border-color: rgba(217, 165, 63, 0.5); }
.member .scan-wrap { width: 100%; margin-top: -2px; }
.member-body { flex: 1; min-width: 0; }
.member-name { font-family: var(--font-head); font-weight: 700; font-size: 14px; }
.member-status { font-size: 11.5px; color: var(--text-muted); margin-top: 1px; }
.member-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; width: 100%; }
.member-actions .btn { padding: 10px 8px; }

/* รอบรับรองรายสัปดาห์ — สถิติ 5 ช่อง · รายการที่ขวางการรับรอง · คำชี้แจง */
.cert-stats { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; margin-top: 12px; }
/* จอ 360px หาร 5 ช่องได้ช่องละ ~57px แต่ป้าย "สายทางการ" ยาวเกิน ล้นทับช่องข้าง ๆ */
@media (max-width: 480px) { .cert-stats { grid-template-columns: repeat(3, 1fr); } }
.cert-stat { background: var(--bg-muted); border-radius: 10px; padding: 8px 4px; text-align: center; min-width: 0; overflow-wrap: anywhere; }
.cert-stat b { display: block; font-family: var(--font-head); font-size: 17px; font-weight: 700; }
.cert-stat span { font-size: 10.5px; color: var(--text-muted); }
.cert-stat.is-warn { background: var(--warn-bg); color: var(--warn-text); }
.cert-stat.is-warn2 { background: var(--warn2-bg); color: var(--warn2-text); }
.cert-stat.is-ok { background: var(--success-bg); color: var(--success-text); }
.cert-stat.is-warn span, .cert-stat.is-warn2 span, .cert-stat.is-ok span { color: inherit; opacity: 0.8; }
.cert-blocker { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 8px 0; border-top: 1px solid var(--border); font-size: 13px; }
.cert-done { display: flex; gap: 10px; align-items: flex-start; margin-top: 12px; font-size: 13px; }
.cert-note { font-size: 12.5px; color: var(--text-muted); margin-top: 10px; padding: 8px 10px; background: var(--bg-muted); border-radius: 8px; }
.cert-list { display: flex; flex-direction: column; margin-top: 8px; }
.cert-dept { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; background: none; border: 0; border-top: 1px solid var(--border); padding: 10px 2px; font: inherit; cursor: pointer; color: inherit; }
.cert-dept:hover { background: var(--bg-muted); }
.exc-row { border-top: 1px solid var(--border); padding: 10px 0 4px; margin-top: 8px; }
.exc-reason { font-size: 12.5px; margin-top: 6px; line-height: 1.5; }
.dlg-msg { white-space: pre-line; }

/* สแกนดิบทุกครั้ง — ปุ่มขยายในประวัติและการ์ดลูกทีม */
.scan-toggle { background: none; border: 0; padding: 2px 0; margin-top: 3px; color: var(--primary); font: inherit; font-size: 11.5px; font-weight: 600; cursor: pointer; }
.scan-list { margin-top: 4px; padding: 6px 10px; border-left: 2px solid var(--border); font-size: 12px; color: var(--text-muted); display: flex; flex-direction: column; gap: 3px; }
.scan-list .scan-item.is-used { color: var(--text); }
.scan-list .scan-date { font-weight: 600; color: var(--text); margin-top: 4px; }
.scan-list .scan-date:first-child { margin-top: 0; }
/* สรุปรายวันของแผง "ดูสแกนทั้งเดือน" (v1.6.5) — ทั้งเดือนแบบไล่ทุกการแตะยาว 60–120 บรรทัด
   ย่อเหลือวันละบรรทัด แตะวันไหนจึงคลี่การแตะดิบของวันนั้น */
.scan-day {
  /* wrap: วันที่มีทั้งป้ายเวรดึกและป้ายเตือน ยาวเกินจอมือถือ — ให้ขึ้นบรรทัดใหม่ทั้งชิ้น ไม่ใช่หักกลางคำ */
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 8px; width: 100%; padding: 3px 0;
  background: none; border: 0; color: var(--text); font: inherit; font-size: 12px; text-align: left; cursor: pointer;
}
.scan-day:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 6px; }
.scan-day > b { flex: none; min-width: 56px; font-weight: 600; }
.scan-day .sd-time { font-variant-numeric: tabular-nums; }
.scan-day .sd-note { color: var(--text-muted); font-size: 11px; }
.scan-day .sd-warn { color: var(--warn-text); font-size: 11px; }
.scan-day .sd-caret { margin-left: auto; flex: none; color: var(--text-faint); font-size: 10px; }
.scan-day-detail { display: flex; flex-direction: column; gap: 3px; padding: 2px 0 6px 12px; }

/* heatmap วัน × ช่วงเวลา — สเกลเขียว 5 ระดับ */
.heat { display: grid; grid-template-columns: 26px repeat(6, 1fr); gap: 3px; align-items: center; margin-top: 10px; }
.heat-h { font-size: 10px; color: var(--text-muted); text-align: center; }
.heat-d { font-size: 11px; color: var(--text-muted); }
.heat-c {
  height: 26px; border-radius: 5px; background: #eaf2ee; border: 0; padding: 0; cursor: pointer;
  font-family: var(--font-head); font-size: 10.5px; font-weight: 700; color: #16261f;
}
.heat-c:hover, .heat-c:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.heat-c[data-l='1'] { background: #cde4da; }
.heat-c[data-l='2'] { background: #9ecbb9; }
.heat-c[data-l='2'] { color: #10201a; }
.heat-c[data-l='3'] { background: #5aa48b; color: #fff; }
.heat-c[data-l='4'] { background: #0e6b57; color: #fff; }

/* ══ ตารางเวรจริงจากการสแกน (/team แท็บ "ตารางเวรจริง" · การ์ดกำลังคนใน /director) ═══
   เป็นตารางจริง ๆ ห้ามพับเป็นการ์ดบนมือถือ (คน × วัน ต้องเห็นเป็นกริด) — ให้เลื่อนซ้ายขวาแทน
   คอลัมน์ชื่อตรึงซ้ายไว้ เลื่อนดูวันแล้วยังรู้ว่าแถวไหนเป็นใคร                                    */
.roster-ward { margin-top: 12px; }
.roster-ward-title { font-family: var(--font-head); font-weight: 700; font-size: 12.5px; color: var(--primary-dark); margin: 0 0 4px; }
.roster { border-collapse: separate; border-spacing: 0; width: 100%; font-size: 11px; }
.roster th, .roster td { padding: 5px 6px; border-bottom: 1px solid var(--border); vertical-align: top; white-space: nowrap; }
.roster th { font-family: var(--font-head); font-weight: 600; font-size: 10.5px; color: var(--text-muted); text-align: center; background: var(--surface); }
.roster th:first-child, .roster td:first-child {
  position: sticky; left: 0; z-index: 1; background: var(--surface); text-align: left;
  font-weight: 600; max-width: 150px; overflow: hidden; text-overflow: ellipsis; box-shadow: 1px 0 0 var(--border);
}
.roster th.is-weekend { color: var(--warn-text); }
.roster td { text-align: center; min-width: 64px; }
/* เป็นบล็อก (flex) ไม่ใช่ inline — คนที่ขึ้นสองเวรในวันเดียวต้องเห็นซ้อนกันเป็นสองบรรทัด ไม่ใช่ต่อกันในบรรทัดเดียว */
.roster-cell { display: flex; flex-direction: column; align-items: center; gap: 1px; width: max-content; margin: 0 auto; padding: 2px 5px; border-radius: 6px; background: var(--success-bg-soft); }
.roster-cell + .roster-cell { margin-top: 3px; }
.roster-cell b { font-family: var(--font-head); font-size: 12px; color: var(--primary-dark); }
.roster-cell small { font-size: 9.5px; color: var(--text-muted); }
.roster-cell.is-unknown { background: var(--warn-bg); }
.roster-cell.is-unknown b { color: var(--warn-text); }
.roster-cell.is-open { border: 1px dashed var(--accent-dashed); }
.roster-cell.is-late b { color: var(--warn2-text); }
/* ตารางเวรรายงาน: คนเวลาตายตัว — ท (วันทำการ) พื้นเรียบ · OT (สแกนแยกนอกเวลา/วันหยุด) พื้นม่วงอ่อน · ✓ ชี้แจงแล้ว */
.roster-cell.is-work { background: var(--surface); border: 1px solid var(--border); }
.roster-cell.is-ot { background: #eeedfe; }
.roster-cell.is-ot b { color: #3c3489; }
.roster-cell.is-explained b { color: var(--primary-dark); }
.roster tr.roster-block td { text-align: left; font-family: var(--font-head); font-weight: 600; font-size: 10.5px; color: var(--text-muted); background: var(--surface); }
.roster td.roster-total { text-align: left; font-size: 10.5px; color: var(--text-muted); }
.roster-filters .sel-inline { max-width: 260px; }
.roster-cov th, .roster-cov td { text-align: center; white-space: nowrap; }
.roster-cov th:first-child, .roster-cov td:first-child { text-align: left; }
.roster-cov td.is-thin { color: var(--warn-text); font-weight: 700; }
/* วันทำการที่ไม่มีสแกนและยังไม่มีใครตรวจ — เครื่องหมายเบา ๆ ในช่องว่าง ไม่ใช่การตัดสินว่าขาดงาน */
.roster-noscan { display: block; font-size: 9.5px; color: var(--warn-text); opacity: 0.85; }
/* วันที่ยังไม่ปิดวัน — "–" จาง ๆ บอกว่ายังไม่รู้ ไม่ใช่ 0 ชั่วโมง (ดู help.js คีย์ dayNotClosed) */
.roster-pending { display: block; font-size: 12px; color: var(--text-faint); }
.roster-foot { margin: 6px 2px 0; font-size: 11px; }

/* ══ หน้า ผอ. (/director) ═══════════════════════════════════════════════ */
.kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 16px; }
.kpi-grid > .card { margin: 0; }
/* หน้าภาพรวมของ ผอ. มีการ์ด 5 ใบ — ให้อยู่แถวเดียวบนจอกว้าง ไม่ให้เหลือใบเดียวลอยแถวที่สอง */
.kpi-grid.kpi-5 { grid-template-columns: repeat(5, 1fr); }
@media (max-width: 899px) { .kpi-grid, .kpi-grid.kpi-5 { grid-template-columns: repeat(2, 1fr); gap: 10px; } }
.kpi-card .kpi-num { font-size: 30px; }
/* การ์ด KPI กดได้ → แผงรายละเอียดแยกกลุ่มงาน (มุมขวามีลูกศรบอกว่ากดได้) */
.kpi-card[data-kpi] { cursor: pointer; position: relative; transition: box-shadow 0.12s, transform 0.12s; user-select: none; }
.kpi-card[data-kpi]::after { content: '›'; position: absolute; right: 13px; top: 8px; font-size: 18px; color: var(--text-faint); font-family: var(--font-head); }
.kpi-card[data-kpi]:hover { box-shadow: 0 4px 14px rgba(0, 0, 0, 0.09); }
.kpi-card[data-kpi]:active { transform: scale(0.985); }
.kpi-card[aria-pressed='true'] { outline: 2px solid var(--primary); outline-offset: 1px; }
.kpi-card[aria-pressed='true']::after { content: '▾'; color: var(--primary); }
#drill { margin: 0 0 16px; }
.drill-row { display: flex; align-items: center; gap: 12px; padding: 9px 0; border-top: 1px solid var(--border); font-size: 12.5px; }
.drill-row:first-child { border-top: 0; }
.drill-name { flex: 1; min-width: 0; }
.drill-track { height: 6px; background: var(--bg-muted); border-radius: 3px; margin-top: 5px; overflow: hidden; max-width: 320px; }
.drill-fill { height: 100%; background: var(--primary); border-radius: 3px; }
.drill-val { font-family: var(--font-head); font-weight: 700; font-size: 13.5px; min-width: 64px; text-align: right; white-space: nowrap; }
.drill-val.is-warn { color: var(--warn2-text); }
.kpi-up { color: var(--primary); font-weight: 600; }
.kpi-down { color: var(--warn2-text); font-weight: 600; }
/* ใบ "รอตรวจ" แยกสีจากใบอื่น — สื่อว่ายังไม่ใช่ข้อสรุป (mockup 1d) */
.kpi-pending { background: #fffbf0; border-color: rgba(217, 165, 63, 0.45); }
.kpi-pending .kpi-num { color: var(--warn-text); }

.two-col { display: grid; grid-template-columns: 1fr 340px; gap: 16px; align-items: start; }
/* แท็บ "เทียบกลุ่มงาน" — กราฟเต็มความกว้าง คอลัมน์ขวาซ่อน */
.two-col.is-focus { grid-template-columns: 1fr; }
.two-col.is-focus .bars { grid-template-columns: minmax(140px, 260px) 1fr 52px; }
@media (max-width: 899px) { .two-col { grid-template-columns: 1fr; } .two-col.is-focus .bars { grid-template-columns: minmax(96px, 150px) 1fr 44px; } }

/* bar chart อัตราตรงเวลารายกลุ่มงาน */
.bars { display: grid; grid-template-columns: minmax(96px, 150px) 1fr 44px; gap: 8px 12px; align-items: center; margin-top: 12px; }
.bar-label { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bar-label a { color: inherit; text-decoration: none; }
.bar-label a:hover { color: var(--primary); text-decoration: underline; }
.bar-track { height: 18px; background: var(--bg-muted); border-radius: 5px; overflow: hidden; }
.bar-fill { height: 100%; border-radius: 5px; background: var(--primary); }
/* ลาย stripe = อนุมาน (รอตารางเวร) — ห้ามใช้ทึบกับกลุ่มที่ยังไม่มีตัวเลขทางการ */
.bar-fill.inferred { background: repeating-linear-gradient(45deg, #d9a53f 0 4px, #f3dfae 4px 8px); }
.bar-pct { font-family: var(--font-head); font-weight: 700; font-size: 12.5px; text-align: right; color: var(--primary); }
.bar-pct.inferred { color: var(--warn-text); }
.bar-legend { display: flex; gap: 14px; font-size: 11px; color: var(--text-muted); margin-top: 12px; }
.bar-legend i { display: inline-block; width: 22px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; background: var(--primary); }
.bar-legend i.inferred { background: repeating-linear-gradient(45deg, #d9a53f 0 4px, #f3dfae 4px 8px); }

/* sparkline */
.spark { width: 100%; height: 64px; display: block; margin-top: 8px; }
.spark-axis { display: flex; justify-content: space-between; font-size: 10px; color: var(--text-muted); margin-top: 4px; }
.spark-week { background: none; border: 0; padding: 4px 6px; font: inherit; color: inherit; cursor: pointer; border-radius: 6px; }
.spark-week:hover, .spark-week:focus-visible { background: var(--bg-muted); color: var(--text); outline: none; }

/* แจ้งเตือน */
.alert-list { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }
.alert { display: flex; gap: 10px; align-items: flex-start; font-size: 12px; }
.alert i { width: 8px; height: 8px; border-radius: 50%; margin-top: 6px; flex: none; background: var(--accent-dashed); }
.alert i.high { background: var(--warn2-text); }
.alert .cell-muted { display: block; }

.month-nav { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted); }
.month-nav button { border: 0; background: none; cursor: pointer; font-size: 16px; color: var(--text-muted); padding: 2px 6px; }

/* ปุ่มย้อนกลับ — หัวหน้าทุกหน้าที่ไม่ใช่หน้าหลักของบทบาท */
.back-link {
  display: inline-flex; align-items: center; gap: 4px; text-decoration: none;
  font-family: var(--font-head); font-weight: 600; font-size: 12.5px;
  padding: 6px 12px 6px 9px; border-radius: 20px;
  background: var(--bg-muted); color: var(--text-muted); white-space: nowrap;
}
.back-link:hover { background: #e8e5dd; color: var(--text); }

/* กรอบไฮไลต์ชั่วคราวเมื่อแท็บเลื่อนไปยังการ์ด (เช่น "เทียบกลุ่มงาน") */
/* ข้อความลอยเหนือเมนูล่าง — ผลของปุ่มต้องเห็นตรงที่ผู้ใช้อยู่ ไม่ใช่เฉพาะยอดหน้า */
.toast-box {
  position: fixed; left: 12px; right: 12px; z-index: 60; display: flex; flex-direction: column; gap: 8px;
  bottom: calc(84px + env(safe-area-inset-bottom)); pointer-events: none; align-items: center;
}
@media (min-width: 900px) { .toast-box { left: auto; right: 20px; bottom: 20px; align-items: flex-end; } }
.toast {
  max-width: min(520px, 100%); padding: 11px 15px; border-radius: 12px; font-size: 13px; line-height: 1.45;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.16); opacity: 1; transition: opacity 0.35s, transform 0.35s;
  background: var(--text); color: #fff;
}
.toast-ok { background: var(--primary-dark); }
.toast-error { background: #8c2f2f; }
.toast-warn { background: #8a5a08; }
.toast.is-out { opacity: 0; transform: translateY(6px); }
#inferredNote.is-flash { background: var(--warn-bg); color: var(--warn-text); border-radius: 8px; padding: 6px 8px; }

/* แท็บ/ปุ่มของฟีเจอร์ที่ยังไม่เปิดใช้ — กดได้ ขึ้นคำอธิบาย มีป้ายบอกเฟส */
.tab-soon { color: var(--text-faint); }
.tab-soon::after {
  content: attr(data-phase); display: inline-block; margin-left: 5px; padding: 1px 6px;
  border-radius: 4px; background: rgba(0, 0, 0, 0.06); color: var(--text-muted);
  font-size: 9.5px; font-weight: 700; vertical-align: 1px;
}

/* ══ กล่องโต้ตอบ (dialog.js) แทน prompt/confirm ═══════════════════════════ */
.dlg {
  border: 0; border-radius: var(--radius-card); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.18);
  padding: 0; width: min(92vw, 420px); background: var(--surface); color: var(--text);
  font-family: var(--font-body);
}
.dlg::backdrop { background: rgba(28, 42, 38, 0.45); }
.dlg-form { padding: 18px 18px 16px; display: flex; flex-direction: column; gap: 12px; }
.dlg-title { font-size: 15px; font-weight: 700; font-family: var(--font-head); }
.dlg-msg { margin: -4px 0 0; font-size: 12.5px; color: var(--text-muted); line-height: 1.6; }
.dlg-field { display: flex; flex-direction: column; gap: 5px; }
.dlg-check { flex-direction: row; align-items: center; gap: 8px; }
.dlg-label { font-size: 12px; font-weight: 600; }
.dlg-hint { font-size: 11px; color: var(--text-muted); }
/* ช่องกรอก — ใช้ทั้งในกล่องโต้ตอบ (.dlg-input) และในฟอร์มบนหน้า (.form-input) หน้าตาเดียวกันที่เดียว */
.dlg-input, .form-input {
  width: 100%; padding: 10px 12px; font-family: var(--font-body); font-size: 14px;
  border: 1px solid var(--border-input); border-radius: var(--radius-ctl); background: var(--bg-page); color: var(--text);
}
.dlg-input:focus, .form-input:focus { outline: none; border-color: rgba(14, 107, 87, 0.35); box-shadow: 0 0 0 1.5px rgba(14, 107, 87, 0.35); background: var(--surface); }
textarea.form-input { resize: vertical; min-height: 96px; line-height: 1.55; }
.dlg-error { background: var(--danger-bg); color: var(--danger-text); padding: 8px 11px; border-radius: var(--radius-ctl); font-size: 12px; }
.dlg-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 4px; }
.dlg-actions .btn { padding: 10px 16px; }

/* ══ คำอธิบายศัพท์ (help.js) ══════════════════════════════════════════════
   ทำเป็นปุ่มกดแทน tooltip แบบชี้เมาส์ เพราะผู้ใช้ส่วนใหญ่เปิดจากมือถือ
   ขนาดปุ่มขั้นต่ำ 22px เพื่อให้แตะติดโดยไม่ดันความสูงของหัวตาราง          */
.help-dot {
  display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; min-width: 15px; margin-left: 5px; padding: 0;
  border: 1px solid var(--border); border-radius: 50%; background: transparent;
  color: var(--text-muted); font-family: var(--font-head); font-size: 10px; font-weight: 700;
  line-height: 1; cursor: pointer; vertical-align: middle; position: relative;
}
/* พื้นที่แตะจริงกว้างกว่าที่เห็น — นิ้วโดนง่ายขึ้นโดยหน้าตาไม่เปลี่ยน */
.help-dot::after { content: ''; position: absolute; inset: -6px; }
.help-dot:hover, .help-dot:focus-visible { border-color: var(--primary); color: var(--primary); background: var(--success-bg); }
.help-dot:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }

.help-link {
  border: 0; background: transparent; padding: 0; margin-left: 8px;
  color: var(--primary); font-family: var(--font-body); font-size: 11.5px; font-weight: 600;
  text-decoration: underline; text-underline-offset: 2px; cursor: pointer; white-space: nowrap;
}
.help-link:hover, .help-link:focus-visible { color: var(--text); }

.help-sheet { display: flex; flex-direction: column; gap: 6px; max-height: 62vh; overflow-y: auto; margin: -4px -2px 0; padding: 0 2px; }
.help-sheet details { border: 1px solid var(--border); border-radius: var(--radius-ctl); background: var(--bg-page); }
.help-sheet summary {
  padding: 9px 11px; font-family: var(--font-head); font-size: 12.5px; font-weight: 600;
  cursor: pointer; list-style: none;
}
.help-sheet summary::-webkit-details-marker { display: none; }
.help-sheet summary::after { content: '+'; float: right; color: var(--text-muted); font-weight: 400; font-size: 15px; line-height: 1; }
.help-sheet details[open] summary::after { content: '2'; }
.help-sheet details[open] summary { border-bottom: 1px solid var(--border); }
.help-sheet p { margin: 0; padding: 9px 11px 11px; font-size: 12px; color: var(--text-muted); line-height: 1.65; }
.btn-danger { background: var(--danger-text); box-shadow: none; color: #fff; }
.btn-danger:hover:not(:disabled) { background: #8a2626; }

/* ปุ่มโหลดเพิ่มท้ายตาราง */
.load-more { display: block; width: 100%; padding: 12px; border: 0; border-top: 1px solid var(--border); background: var(--bg-page); cursor: pointer; font-family: var(--font-head); font-weight: 600; font-size: 12.5px; color: var(--primary); }
.load-more:hover { background: var(--bg-muted); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ══ แจ้งปัญหา (/issue) — รับมาจากตาพระยา v1.7.0 ═════════════════════════ */
/* บริบทที่ระบบแนบให้เอง — บอกให้ผู้ใช้รู้ว่าอะไรถูกส่งไปด้วย ไม่ใช่เก็บเงียบ ๆ */
.issue-ctx { margin-top: 14px; font-size: 11.5px; color: var(--text-muted); background: var(--bg-muted); border-radius: 8px; padding: 8px 10px; line-height: 1.6; }
.issue-row { padding: 10px 0; border-top: 1px solid var(--border); }
.issue-row:first-child { border-top: 0; }
.card.issue-row { border-top: 0; padding: 13px 15px; margin-bottom: 10px; }
.issue-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.issue-kind { font-family: var(--font-head); font-weight: 700; font-size: 13.5px; }
.issue-who { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
/* คำพูดของผู้แจ้ง — คงการขึ้นบรรทัดที่เขาพิมพ์มา และตัดคำยาวไม่ให้ดันการ์ด */
.issue-body { margin: 6px 0; font-size: 13.5px; line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere; }
.issue-ua { font-size: 10.5px; white-space: pre-wrap; overflow-wrap: anywhere; }
/* คำตอบของผู้พัฒนา — ท่อนที่คนแจ้งรอดู ต้องเด่นกว่าข้อความของตัวเอง */
.issue-reply { margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: var(--success-bg-soft); font-size: 12.5px; line-height: 1.6; white-space: pre-wrap; }
.issue-reply b { font-family: var(--font-head); color: var(--primary-dark); display: block; margin-bottom: 2px; }
/* ปุ่มตัดสินในการ์ดเรื่องแจ้ง — 3 ปุ่มยาวไม่เท่ากัน ใช้แถวเรียงชิดซ้าย ไม่ใช่ตาราง 2 ช่องแบบการ์ดลูกทีม */
.issue-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
/* ตัวเลขเรื่องใหม่บนเมนู */
.nav-count { margin-left: auto; }
.bottom-nav .nav-count { margin: 0; position: absolute; top: 0; left: 50%; transform: translateX(4px); padding: 1px 5px; font-size: 9.5px; }
.bottom-nav a { position: relative; }
