*, *::before, *::after { box-sizing: border-box; }
html { font-size: var(--font-size); -webkit-text-size-adjust: 100%; }
body { margin: 0; font-family: var(--font); color: var(--text); background: var(--bg); line-height: 1.5; }
a { color: var(--blue); text-decoration: none; }
a:hover { text-decoration: underline; }
h1, h2, h3 { margin: 0 0 var(--space-3); line-height: 1.25; }
h1 { font-size: 1.5rem; } h2 { font-size: 1.2rem; } h3 { font-size: 1.05rem; }
p { margin: 0 0 var(--space-3); }
img { max-width: 100%; }
:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }
/* An element with the hidden attribute is hidden, whatever display it was given elsewhere.
   Without this, `el.hidden = true` quietly does nothing to anything we styled as a flex or a pill. */
[hidden] { display: none !important; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.muted { color: var(--muted); }
.money { font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.money.negative { color: var(--red); }
.text-right { text-align: right; }
.text-center { text-align: center; }
.mt-2 { margin-top: var(--space-2); } .mt-4 { margin-top: var(--space-4); } .mb-4 { margin-bottom: var(--space-4); }
.flex { display: flex; gap: var(--space-3); align-items: center; }
.flex-between { display: flex; justify-content: space-between; align-items: center; gap: var(--space-3); }
.stack > * + * { margin-top: var(--space-3); }
.grid { display: grid; gap: var(--space-4); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1024px) { .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; } }

/* Cards */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); }
.card-body { padding: var(--space-4); }
.card-header { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border); font-weight: 600; display: flex; justify-content: space-between; align-items: center; gap: var(--space-3); }
/* หัวการ์ดเป็น flex แบบ space-between — ไอคอนกับชื่อต้องอยู่ในกล่องเดียวกัน ไม่งั้นไอคอนไปชิดซ้าย ชื่อไปชิดขวา */
.card-title { display: inline-flex; align-items: center; gap: 6px; }
.card-title .ic { color: var(--muted); }
.card-footer { padding: var(--space-3) var(--space-4); border-top: 1px solid var(--border); background: var(--gray-50); border-radius: 0 0 var(--radius) var(--radius); }
.kpi { display: flex; flex-direction: column; gap: var(--space-1); }
.kpi .kpi-label { color: var(--muted); font-size: .9rem; }
.kpi .kpi-value { font-size: 2rem; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--navy); }
.kpi .kpi-sub { font-size: .85rem; color: var(--muted); }

/* Buttons */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2); min-height: var(--touch); padding: 0 var(--space-4); border-radius: var(--radius-sm); border: 1px solid transparent; font: inherit; font-weight: 600; cursor: pointer; background: var(--gray-100); color: var(--text); text-decoration: none; }
.btn:hover { text-decoration: none; filter: brightness(.97); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .55; cursor: not-allowed; }
.btn-primary { background: var(--blue); color: var(--white); }
.btn-success { background: var(--teal); color: var(--white); }
.btn-danger { background: var(--red); color: var(--white); }
.btn-outline { background: transparent; border-color: var(--gray-300); color: var(--text); }   /* also wins back the text colour if a filled variant is still on the element */
.btn-sm { min-height: 34px; padding: 0 var(--space-3); font-size: .9rem; }
.btn-block { width: 100%; }
.btn-google { background: var(--white); border-color: var(--gray-300); }
.btn-line { background: #06C755; border-color: #06C755; color: var(--white); }
.btn-block + .btn-block { margin-top: var(--space-2); }   /* ปุ่มเข้าสู่ระบบด้วย Google/LINE ไม่ให้ติดกัน */

/* Forms */
.form-field { margin-bottom: var(--space-4); }
.form-field label { display: block; font-weight: 600; margin-bottom: var(--space-1); }
.form-field .label-ico { display: inline-flex; vertical-align: -3px; margin-right: 6px; color: var(--muted); }
.form-field .label-ico .ic { vertical-align: 0; }
.form-field .hint { color: var(--muted); font-size: .85rem; margin-top: var(--space-1); }
.form-field .error { color: var(--red); font-size: .9rem; margin-top: var(--space-1); }
.input, select, textarea { width: 100%; min-height: var(--touch); padding: var(--space-2) var(--space-3); border: 1px solid var(--gray-300); border-radius: var(--radius-sm); font: inherit; background: var(--white); color: var(--text); }
textarea { min-height: 96px; resize: vertical; }
.input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] { border-color: var(--red); }
.checkbox { display: flex; align-items: center; gap: var(--space-2); min-height: var(--touch); }

/*
 * สวิตช์เปิด/ปิด — checkbox ตัวเดิมที่ซ่อนไว้ แล้ววาดรางกับปุ่มแทน
 *
 * ซ่อนด้วย opacity:0 ไม่ใช่ display:none เพราะช่องที่ถูก display:none จะหลุดจากลำดับ Tab และ
 * โฟกัสด้วยคีย์บอร์ดไม่ได้อีกเลย ตัวจริงจึงยังอยู่ทับรางไว้ แค่มองไม่เห็น
 */
/* `label.switch` ไม่ใช่ `.switch` เฉย ๆ เพราะ `.form-field label` ตั้ง display:block ไว้ด้วย
   ความจำเพาะเท่ากัน ราง 44px จึงถูกยุบเหลือศูนย์เมื่อสวิตช์อยู่ในฟอร์ม */
label.switch { display: inline-flex; align-items: center; gap: var(--space-2); min-height: var(--touch); margin-bottom: 0; font-weight: 400; cursor: pointer; position: relative; }
.switch input { position: absolute; width: 44px; height: 26px; margin: 0; opacity: 0; cursor: pointer; }
.switch .track { flex: 0 0 44px; width: 44px; height: 26px; border-radius: 999px; background: var(--gray-300); transition: background .15s ease; position: relative; }
.switch .track::after { content: ''; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: var(--white); box-shadow: 0 1px 2px rgba(16, 24, 40, .25); transition: transform .15s ease; }
.switch input:checked ~ .track { background: var(--teal); }
.switch input:checked ~ .track::after { transform: translateX(18px); }
.switch input:focus-visible ~ .track { outline: 2px solid var(--blue); outline-offset: 2px; }
.switch input:disabled ~ .track { opacity: .5; cursor: not-allowed; }
.switch .switch-label { flex: 1; }
/* ในช่องตาราง สวิตช์ไม่มีข้อความกำกับ หัวคอลัมน์บอกแทนแล้ว */
.switch-sm { min-height: 0; }
.switch-sm input { width: 34px; height: 20px; }
.switch-sm .track { flex-basis: 34px; width: 34px; height: 20px; }
.switch-sm .track::after { width: 14px; height: 14px; }
.switch-sm input:checked ~ .track::after { transform: translateX(14px); }
.form-actions { display: flex; gap: var(--space-3); justify-content: flex-end; margin-top: var(--space-4); }

/* Alerts & badges */
.alert { padding: var(--space-3) var(--space-4); border-radius: var(--radius-sm); border: 1px solid; margin-bottom: var(--space-4); }
.alert-success { background: var(--teal-100); border-color: var(--teal); color: #085f53; }
.alert-warning { background: var(--amber-100); border-color: var(--amber); color: #7a4f00; }
.alert-danger { background: var(--red-100); border-color: var(--red); color: #7a2600; }
.alert-info { background: var(--blue-100); border-color: var(--blue); color: var(--navy); }
.badge { display: inline-flex; align-items: center; gap: 6px; padding: 2px 10px; border-radius: 999px; font-size: .85rem; font-weight: 600; white-space: nowrap; }
.badge::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.badge-success { background: var(--teal-100); color: #085f53; }
.badge-warning { background: var(--amber-100); color: #7a4f00; }
.badge-danger { background: var(--red-100); color: #7a2600; }
.badge-info { background: var(--blue-100); color: var(--navy); }
.badge-neutral { background: var(--gray-100); color: var(--gray-700); }

/* Tables */
.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
table.table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: .95rem; }
.table th, .table td { padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--border); text-align: left; vertical-align: middle; white-space: nowrap; }
.table thead th { position: sticky; top: 0; background: var(--gray-50); font-weight: 600; color: var(--gray-700); z-index: 2; }
.table th.sortable a { color: inherit; display: inline-flex; gap: 4px; align-items: center; }
.table tbody tr:hover { background: var(--blue-100); }
.table .sticky-col { position: sticky; left: 0; background: var(--surface); z-index: 1; box-shadow: 1px 0 0 var(--border); }
.table thead .sticky-col { z-index: 3; background: var(--gray-50); }
.table tfoot td { font-weight: 700; background: var(--gray-50); }
.table-toolbar { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; margin-bottom: var(--space-3); }
.table-toolbar .input { max-width: 320px; }
.pagination { display: flex; justify-content: space-between; align-items: center; gap: var(--space-3); padding: var(--space-3) 0; flex-wrap: wrap; }
.pagination nav { display: flex; gap: var(--space-2); }

/* Empty state */
.empty-state { text-align: center; padding: var(--space-6) var(--space-4); color: var(--muted); }
.empty-state .icon { font-size: 2rem; margin-bottom: var(--space-2); }

/* Toast & dialog */
/* แถบบอกว่ามีข้อมูลใหม่ — ไม่ทับของเดิม รอให้คนกดเอง */
.live-stale { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-2) var(--space-3); margin-bottom: var(--space-2); border-radius: var(--radius-sm);
  background: var(--blue-100); border: 1px solid var(--blue); color: var(--navy); font-size: .85rem; }
.live-stale button { border: 0; background: var(--blue); color: var(--white); font: inherit; font-weight: 600;
  padding: 4px 12px; border-radius: 999px; cursor: pointer; }
.live-stale button:hover { filter: brightness(1.08); }

/* แถบบางบนสุดตอนกำลังไปหน้าถัดไป — เปลี่ยนหน้าโดยไม่โหลดใหม่ ต้องมีอะไรบอกว่าระบบรับคำสั่งแล้ว */
.nav-progress { position: fixed; top: 0; left: 0; height: 2px; width: 0; z-index: 2000; background: var(--blue);
  opacity: 0; transition: width .25s ease, opacity .2s ease; pointer-events: none; }
.nav-progress.on { width: 85%; opacity: 1; transition: width 8s cubic-bezier(0,.8,.2,1), opacity .2s ease; }
.toast-region { position: fixed; right: var(--space-4); bottom: var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); z-index: 1000; max-width: 360px; }
.toast { padding: var(--space-3) var(--space-4); border-radius: var(--radius-sm); background: var(--navy); color: var(--white); box-shadow: var(--shadow-lg); }
.toast-success { background: var(--teal); } .toast-error { background: var(--red); } .toast-warning { background: var(--amber); }
.toast { display: flex; align-items: center; gap: var(--space-3); }
.toast .toast-action { background: var(--white); color: var(--gray-900); border: 0; border-radius: var(--radius-sm); padding: 4px 10px; font: inherit; font-size: .85rem; cursor: pointer; }
/*
 | toast แจ้งเตือนที่มาเอง — ต่างจาก toast ยืนยันการกดปุ่ม ตรงที่กดได้และมีปุ่มปิด
 |
 | ปุ่มปิดวางนอกลิงก์ (ไม่ใช่ซ้อนใน <a>) เพราะ interactive ซ้อน interactive คือ markup ที่เบราว์เซอร์
 | ตีความไม่ตรงกัน และแถวทั้งแถวจะกดไม่ได้ตามที่คิด
 */
.toast-notify { display: flex; align-items: flex-start; gap: var(--space-2); padding: 0; overflow: hidden; }
.toast-notify .tn-body { display: flex; align-items: flex-start; gap: var(--space-3); flex: 1; min-width: 0; padding: var(--space-3) 0 var(--space-3) var(--space-3); color: inherit; }
.toast-notify .tn-text { min-width: 0; flex: 1; }
.toast-notify .ava { margin-top: 1px; }
.toast-notify .tn-kind { display: inline-block; font-size: .7rem; font-weight: 600; padding: 1px 7px; border-radius: 999px; background: rgba(255,255,255,.22); margin-bottom: 3px; }
.toast-notify .tn-who { display: block; font-weight: 600; font-size: .9rem; }
.toast-notify .tn-what { display: block; font-size: .82rem; opacity: .85; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.toast-notify .tn-more { display: block; font-size: .75rem; opacity: .7; margin-top: 2px; }
.toast-notify .tn-x { flex: 0 0 auto; background: none; border: 0; color: inherit; opacity: .6; cursor: pointer; font-size: .9rem; line-height: 1; padding: var(--space-3); }
.toast-notify .tn-x:hover { opacity: 1; }
/* ปิดทีเดียวทั้งกอง — โผล่เมื่อมีมากกว่าหนึ่งใบเท่านั้น ใบเดียวก็กด ✕ ของมันเองจบแล้ว */
.tn-clear { border: 0; cursor: pointer; font: inherit; font-size: .78rem; text-align: center; opacity: .85;
  background: var(--gray-700, #3f4a56); color: var(--white); padding: var(--space-2) var(--space-3); }
.tn-clear:hover { opacity: 1; }
dialog.dialog { border: none; border-radius: var(--radius); padding: 0; max-width: 480px; width: calc(100% - 32px); box-shadow: var(--shadow-lg); }
dialog.dialog::backdrop { background: rgba(11, 42, 74, .5); }
.dialog-body { padding: var(--space-5); }
.dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-3); padding: var(--space-3) var(--space-5); border-top: 1px solid var(--border); background: var(--gray-50); }

/* Drawer */
.drawer { position: fixed; top: 0; right: 0; height: 100vh; width: min(520px, 100%); background: var(--surface); box-shadow: var(--shadow-lg); transform: translateX(100%); transition: transform .2s ease; z-index: 900; overflow-y: auto; }
.drawer.open { transform: none; }
.drawer-wide { width: min(860px, 100%); }
/* Sixty checkboxes read as a wall unless they stay in their groups; the panel is narrow, so the
   groups flow into as many columns as fit rather than a fixed three. */
.perm-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--space-3); }
.drawer-header { position: sticky; top: 0; background: var(--surface); padding: var(--space-4); border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; }
.drawer-body { padding: var(--space-4); }
.drawer-foot { position: sticky; bottom: 0; display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); padding: var(--space-3) var(--space-4); border-top: 1px solid var(--border); background: var(--gray-50); }
.drawer-foot .drawer-flag { margin-right: auto; font-size: .82rem; color: var(--muted); }
.drawer-foot .drawer-flag.is-error { color: var(--red); }
.drawer-foot .drawer-flag.is-saved { color: var(--teal); }
.drawer-x { padding: 0 8px; font-size: 1.1rem; line-height: 1.6; color: var(--muted); text-decoration: none; border: 1px solid var(--border); border-radius: var(--radius-sm, 6px); }
.drawer-x:hover { color: var(--navy); background: var(--gray-50); }
/* Without JavaScript the trigger is an ordinary link to the panel's id, and this opens it; the
   second rule stops a hash left in the URL from opening one once drawer.js is running. */
.drawer:target { transform: none; }
.drawer-live .drawer:target:not(.open) { transform: translateX(100%); }
/* A panel is a page of its own while it is open — the page behind it should stay put. */
/* ล็อกการเลื่อนเฉพาะลิ้นชักที่เป็นกล่องคำถามจริง ๆ · แผงที่ติด data-drawer-inline (ลิ้นชักวันของกริดเวลาเข้าออก)
   ไม่ได้คลาสนี้จาก drawer.js เลย เพราะหน้าข้างใต้ยังต้องเลื่อนและกดต่อได้ — อย่าย้ายสไตล์ระดับหน้าอื่นมาไว้ที่นี่ */
.drawer-open, .drawer-open body { overflow: hidden; }
.backdrop { position: fixed; inset: 0; background: rgba(11, 42, 74, .35); z-index: 850; }

/* Definition lists */
dl.dl { display: grid; grid-template-columns: max-content 1fr; gap: var(--space-2) var(--space-4); margin: 0; }
dl.dl dt { color: var(--muted); }
dl.dl dd { margin: 0; }
code.mono { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: .85rem; background: var(--gray-100); padding: 1px 6px; border-radius: 4px; }

/* Image preview: hover popover + click-to-zoom for private images (see js/image-preview.js). */
/* อยู่เหนือลิ้นชักข้าง (900) และฉากหลังของมัน · เบราว์เซอร์ที่มี popover วางไว้ใน top layer เหนือกล่อง modal ด้วย */
.img-pop {
  position: fixed;
  z-index: 2100;
  padding: var(--space-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  pointer-events: none;
}
/* Big enough to read an ID card without opening it. The height is trimmed to the room actually
   available above or below the row by place() in image-preview.js. */
.img-pop img { display: block; max-width: min(52vw, 560px); max-height: min(64vh, 620px); border-radius: var(--radius-sm); }
.img-pop-cap { display: block; margin-top: var(--space-1); font-size: .78rem; color: var(--muted); text-align: center; }

/* popover มีสไตล์ตั้งต้นของเบราว์เซอร์ (inset:0 + margin:auto = จัดกลางจอ, ขอบ, overflow) — ล้างให้เป็นของเราเอง */
.img-pop[popover] { inset: auto; margin: 0; overflow: visible; color: inherit; }
.img-zoom[popover] { width: auto; height: auto; max-width: none; max-height: none; margin: 0; border: 0; overflow: auto; color: inherit; }
.img-zoom {
  position: fixed;
  inset: 0;
  z-index: 2100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
  background: rgba(11, 42, 74, .72);
}
.img-zoom figure { margin: 0; max-width: 100%; max-height: 100%; text-align: center; }
.img-zoom img {
  display: block;
  max-width: min(94vw, 1100px);
  max-height: 86vh;
  margin: 0 auto;
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  background: var(--surface);
}
.img-zoom figcaption { margin-top: var(--space-3); color: var(--white); font-size: .9rem; }
.img-zoom-close {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  width: 36px;
  height: 36px;
  font-size: 1rem;
  line-height: 1;
  color: var(--white);
  background: rgba(255, 255, 255, .14);
  border: 1px solid rgba(255, 255, 255, .3);
  border-radius: 50%;
  cursor: pointer;
}
.img-zoom-close:hover { background: rgba(255, 255, 255, .26); }
body.img-zoom-open { overflow: hidden; }

/* A pointer that cannot hover gets no popover; the click overlay is the whole interaction. */
@media (hover: none) { .img-pop { display: none; } }

/* An uploaded file in a list (components/file-link.php): a picture shows itself, anything else
   says what it is and offers itself for download. Both shapes keep the same footprint so a
   column of mixed attachments stays a column. */
.file-link { display: inline-flex; align-items: center; gap: var(--space-2); min-width: 0; }
.file-open { display: inline-flex; align-items: center; gap: var(--space-2); min-width: 0; text-decoration: none; }
.file-open:hover .file-name { text-decoration: underline; }
.file-thumb {
  flex: 0 0 auto;
  width: 36px;
  height: 46px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--gray-100);
  box-shadow: inset 0 0 0 1px rgba(11, 42, 74, .12);
}
img.file-thumb { object-fit: cover; object-position: center top; }
.file-ext { font-size: 10px; font-weight: 700; letter-spacing: .02em; color: var(--muted); }
.file-meta { display: inline-flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 22ch; }
.file-size { white-space: nowrap; font-size: .78rem; }
.file-dl {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 4px;
  border-radius: var(--radius-sm);
  color: var(--muted);
}
a.file-dl:hover { color: var(--blue); background: var(--gray-100); }
@media (max-width: 640px) { .file-name { max-width: 14ch; } }

/* Optional block on long forms: folded by default, opened when it holds anything worth seeing. */
.optional-block {
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  background: var(--gray-50);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.optional-block > summary { cursor: pointer; font-weight: 600; }
.optional-block > summary::marker { color: var(--muted); }
.optional-block[open] > summary { margin-bottom: var(--space-2); }

/* Inline SVG icons sit on the text baseline and take the colour of whatever holds them. */
.ic { flex: 0 0 auto; vertical-align: -0.18em; }
.btn .ic, .dt-btn .ic { margin-right: 2px; }
.btn > .ic:only-child, .dt-btn > .ic:only-child { margin-right: 0; }

/* Drop area around every file input (js/file-drop.js). The chosen files use the same row shape as
   file-link.php, so what you are about to upload looks like what is already uploaded. */
.file-drop { display: block; }
.file-drop-input { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.file-drop-zone {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-4);
  border: 1.5px dashed var(--border);
  border-radius: var(--radius);
  background: var(--gray-50, var(--surface));
  color: var(--muted);
  font-size: .9rem;
  text-align: center;
  cursor: pointer;
  transition: border-color .12s, background .12s;
}
.file-drop-zone:hover { border-color: var(--blue); }
.file-drop-zone.over { border-color: var(--blue); border-style: solid; background: var(--blue-100); color: var(--navy); }
.file-drop-input:focus-visible + .file-drop-zone, .file-drop-zone:focus-within { outline: 2px solid var(--blue); outline-offset: 2px; }
.file-drop.busy .file-drop-zone { opacity: .6; }
.file-drop-note:empty { display: none; }
.file-drop-note { margin: var(--space-2) 0 0; font-size: .82rem; color: var(--amber-700, var(--muted)); }
.file-drop-list { list-style: none; margin: var(--space-2) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.file-drop-item { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.file-drop-item .file-meta { flex: 1; }
.file-drop-item.too-big .file-size { color: var(--red, #C0392B); font-weight: 600; }
.file-drop-remove {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  line-height: 1;
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 50%;
  cursor: pointer;
}
.file-drop-remove:hover { color: var(--red, #C0392B); border-color: currentColor; }

/* ส่วนของหน้าที่วาดตัวเองใหม่ ต้องบอกว่าเพิ่งเปลี่ยน ไม่งั้นตัวเลขขยับตอนคนกำลังมองทางอื่นอยู่ */
@keyframes live-flash { from { background: var(--amber-100); } to { background: transparent; } }
.live-changed { animation: live-flash 1.2s ease-out; }
@media (prefers-reduced-motion: reduce) { .live-changed { animation: none; } }

/*
 * รูปเล็กหน้าชื่อพนักงานในตาราง
 *
 * ขนาดมาจาก --ava-size ที่ component ตั้งให้ ไม่ใช่คลาสละขนาด ตารางแน่น ๆ กับหน้ารายละเอียดจึงใช้
 * ตัวเดียวกันได้ · flex-shrink:0 เพราะในเซลล์ที่ชื่อยาว วงกลมจะโดนบีบจนเป็นวงรีถ้าไม่กัน
 */
.ava { width: var(--ava-size, 22px); height: var(--ava-size, 22px); flex: 0 0 var(--ava-size, 22px); border-radius: 50%; object-fit: cover; vertical-align: middle; background: var(--gray-100); }
.ava-selfie { box-shadow: 0 0 0 2px var(--teal-100), 0 0 0 3px var(--teal); }   /* รูปตอนลงเวลา ไม่ใช่รูปประจำตัว */
.ava-link { display: inline-flex; flex: 0 0 auto; line-height: 0; border-radius: 50%; vertical-align: middle; }
.ava-link:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.ava-none { display: inline-flex; align-items: center; justify-content: center; font-weight: 700; color: var(--white); font-size: calc(var(--ava-size, 22px) * .46); line-height: 1; vertical-align: middle; }
.ava-t0 { background: #5B7C99; } .ava-t1 { background: #7E8F5B; } .ava-t2 { background: #9A6A8C; }
.ava-t3 { background: #4F8A83; } .ava-t4 { background: #A0764F; } .ava-t5 { background: #6E6AA8; }
/*
 * ชื่อกับรูปเป็นหน่วยเดียวกัน ไม่ใช่สองสิ่งที่บังเอิญอยู่ติดกัน
 *
 * vertical-align:middle สำคัญกว่าที่เห็น: กล่อง inline-flex จะถูกวางตามเส้นฐานของตัวอักษร รูปจึงห้อย
 * ต่ำกว่าเส้นฐานแล้วดันแถวให้สูงขึ้นเก้าพิกเซล — แถวที่มีรูปสูงกว่าแถวที่ไม่มีรูปอย่างเห็นได้ชัด
 * และขนาดรูปตั้งไว้ 22px ไม่เกิน line-height ของช่อง ความสูงแถวจึงเท่าเดิมทุกแถว
 */
.who { display: inline-flex; align-items: center; gap: var(--space-2); min-width: 0; vertical-align: middle; }
.who .who-text { min-width: 0; }
.who .who-text .muted { display: block; font-size: .8rem; }

/*
 * ปุ่มไอคอนในแถวตาราง — สูงเท่าบรรทัดตัวอักษร ความแน่นของแถวจึงเป็นของตาราง ไม่ใช่ของปุ่ม
 * พื้นที่กดยังพอสำหรับเมาส์ · บนจอสัมผัสขยายเป็นเป้าขนาดนิ้วโดยไม่ดันความสูงแถว (padding ติดลบด้วย margin)
 */
.icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 22px; padding: 0; border: 1px solid transparent; border-radius: var(--radius-sm); background: none; color: var(--gray-700); cursor: pointer; vertical-align: middle; text-decoration: none; }
.icon-btn:hover, .icon-btn:focus-visible { background: var(--gray-100); border-color: var(--border); color: var(--navy); }
.icon-btn.is-danger:hover, .icon-btn.is-danger:focus-visible { background: var(--red-100); border-color: transparent; color: var(--red); }
.row-actions form { display: inline; }
@media (pointer: coarse) { .icon-btn { width: 34px; height: 30px; margin: -4px 0; } }

/* ตัวเลขในสูตรของรายการเงินเดือน — แยกกรอบจากช่องของรายการ เพราะบันทึกไปคนละที่ (นโยบาย OT) */
fieldset.formula { margin: var(--space-3) 0; padding: var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--gray-50); }
fieldset.formula legend { padding: 0 6px; font-weight: 600; font-size: .9rem; }
.formula-hint { font-size: .8rem; line-height: 1.5; margin: 4px 0 var(--space-2); }

/* ปุ่มเลือกเดือน/ปี (components/month-jump.php) */
.month-jump { position: relative; display: inline-block; vertical-align: middle; }
/* ปุ่มข้าง ๆ เป็นลิงก์ inline-flex ที่วางตามเส้นฐานตัวอักษร — จัดกึ่งกลางทั้งแถวให้ปุ่มเลือกเดือนสูงเท่ากัน */
.page-actions:has(> .month-jump) > .btn { vertical-align: middle; }
.month-jump > summary { list-style: none; white-space: nowrap; }
.month-jump > summary::-webkit-details-marker { display: none; }
.month-jump[open] > summary { border-color: var(--blue); color: var(--blue); }
.month-jump-pop { position: absolute; right: 0; top: calc(100% + 6px); z-index: 60; width: 244px; max-width: calc(100vw - 32px); padding: var(--space-3); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-lg); }
.month-jump-year { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-2); }
.month-jump-year .icon-btn { font-size: 1.1rem; }
.month-jump-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.month-jump-grid a { display: block; padding: 6px 0; text-align: center; border-radius: var(--radius-sm); color: var(--text); font-size: .9rem; }
.month-jump-grid a:hover { background: var(--gray-100); text-decoration: none; }
.month-jump-grid a.is-now { box-shadow: inset 0 0 0 1px var(--blue); }
.month-jump-grid a.is-current { background: var(--blue); color: #fff; font-weight: 600; }
.month-jump-today { display: block; margin-top: var(--space-2); text-align: center; font-size: .85rem; }
