:root {
  /* AHOKU brand tokens — docs/AHOKU Design System/tokens */
  --ah-blue: #0019FF;
  --ah-orange: #FF8000;
  --navy-600: #223351;

  --font-display: "Titillium Web", system-ui, sans-serif;
  --font-body: "IBM Plex Sans", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;

  --radius-md: 6px;
  --radius-lg: 10px;
  --shadow-sm: 0 1px 3px rgba(10,18,32,.08), 0 1px 2px rgba(10,18,32,.04);
  --shadow-brand: 0 8px 24px rgba(0,25,255,.22);
  --focus-ring: rgba(0,25,255,.35);
  --summary-focus: #0019ff;
  --dur-fast: 120ms;
  --ease-standard: cubic-bezier(.4,0,.2,1);
  --tabbar-height: 60px;

  --primary: var(--ah-blue);
  --ok: #12a150;
  --err: #d12d2d;
  --bg: #f6f8fb;
  --card: #ffffff;
  --text: #1f2328;
  --muted: #6b7688;
  /* neutral 標籤專用:--muted 疊在 --surface-subtle 上只有 4.05:1,不到 AA 的 4.5:1。
     出勤時數改用 neutral 後這個標籤天天出現,對比必須補足。 */
  --tag-neutral-text: #47536b;
  --border: #e0e5ee;
  --surface-subtle: #eef1f6;
  --success-bg: #e5f6ec;
  --warning: #b86d00;
  --warning-bg: #fff2dc;
  --danger-bg: #fce8e8;
  --primary-bg: #e6e9ff;
  color-scheme: light;
}
* { box-sizing: border-box; }
/* hidden 屬性必須永遠勝過任何 display 規則。
   瀏覽器內建的 [hidden]{display:none} 只是屬性選擇器,會被
   .modal-overlay / header#topbar / nav#tabbar 這類含 display 的
   作者樣式蓋掉 —— 曾導致裝置綁定 modal 從頁面載入起就無法隱藏,
   使用者在未登入狀態也看得到、點得到「開始註冊」。 */
[hidden] { display: none !important; }
body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  padding-bottom: calc(var(--tabbar-height) + env(safe-area-inset-bottom));
}
main { max-width: 480px; margin: 0 auto; padding: 16px; transition: max-width 200ms ease; }
body.admin-mode main { max-width: 1200px; }
h1, h2 { font-family: var(--font-display); font-weight: 700; }
h1 { text-align: center; }
h2 { font-size: 1.1rem; }

header#topbar {
  display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 4px 12px;
  padding: calc(10px + env(safe-area-inset-top)) 16px 10px; background: var(--card); border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 50;
}
.user-toggle {
  flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 6px;
  min-height: 44px; padding: 4px 0; background: none; border: none; color: inherit;
  font: inherit; text-align: left; cursor: pointer;
}
.user-toggle:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--focus-ring); border-radius: var(--radius-md); }
.user-identity {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  display: flex; align-items: baseline; gap: 6px;
}
.user-chevron {
  flex: 0 0 auto; transition: transform var(--dur-fast) var(--ease-standard);
}
.user-toggle[aria-expanded="true"] .user-chevron { transform: rotate(180deg); }
.user-details { flex-basis: 100%; font-size: .85rem; }
.link-btn {
  flex: 0 0 auto; min-height: 44px; padding: 0 4px;
  background: none; border: none; color: var(--primary); font-size: 1rem; cursor: pointer;
}

form { display: flex; flex-direction: column; gap: 12px; }
label { display: flex; flex-direction: column; gap: 4px; font-size: 0.9rem; }
label.checkbox { flex-direction: row; align-items: center; }
input, select {
  padding: 12px; font-size: 1rem; line-height: 1.25; border: 1px solid var(--border);
  border-radius: var(--radius-md); background: var(--card); color: var(--text);
  transition: box-shadow var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard);
}
/* iOS Safari 的 date/time 欄位靠 shadow DOM 畫值,::-webkit-date-and-time-value
   有自己的固有寬度且預設置中,外層 width/min-width 完全管不到它,
   欄位仍會被撐到瀏覽器內建的最小寬度,導致比同排的 input/select 還寬而破版、文字被邊框裁掉。
   必須用 appearance: none 卸掉原生控制項尺寸,再直接改寫該偽元素。 */
input[type="date"], input[type="time"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; max-width: 100%; min-height: 46px;
  min-width: 0; -webkit-min-logical-width: 0;
  overflow: hidden; font-family: inherit;
}
input[type="date"]::-webkit-date-and-time-value,
input[type="time"]::-webkit-date-and-time-value {
  display: block; width: 100%; min-width: 0; margin: 0;
  text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
input[type="date"]::-webkit-datetime-edit,
input[type="time"]::-webkit-datetime-edit { padding: 0; min-width: 0; }
input:focus, select:focus {
  outline: none; border-color: var(--ah-blue);
  box-shadow: 0 0 0 3px var(--focus-ring);
}
button.primary, button.secondary {
  padding: 14px; font-size: 1rem; border-radius: var(--radius-md); border: none;
  transition: transform var(--dur-fast) var(--ease-standard), box-shadow var(--dur-fast) var(--ease-standard);
}
button.primary { background: var(--primary); color: #fff; box-shadow: var(--shadow-brand); }
button.secondary { background: var(--card); color: var(--primary); border: 1px solid var(--primary); }
button { font-family: inherit; cursor: pointer; }
button:disabled { cursor: not-allowed; opacity: .55; }
button.compact { width: auto; min-height: 40px; padding: 9px 14px; font-size: .9rem; box-shadow: none; }
button.danger-link {
  min-height: 40px; padding: 9px 12px; border: 1px solid var(--err); border-radius: var(--radius-md);
  background: var(--card); color: var(--err); font-size: .9rem; font-weight: 600;
}
button.danger-link:hover { background: var(--danger-bg); }
.danger-button {
  padding: 14px; border: 0; border-radius: var(--radius-md); background: var(--err); color: #fff; font-size: 1rem;
}
button.primary:active, button.secondary:active, .punch-btn:active { transform: translateY(1px); }

.clock { text-align: center; font-size: 2.2rem; font-family: var(--font-mono); font-variant-numeric: tabular-nums; margin: 24px 0; }
.work-hours, .punch-next { text-align: center; margin: 8px 0; }
.work-hours { color: var(--muted); font-variant-numeric: tabular-nums; }
.punch-next { font-weight: 600; }
/* 只在載入中或取狀態失敗時才有內容；平時清空，別留一條空行撐出間距。 */
.punch-next:empty { display: none; }
.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;
}
.punch-type-control {
  position: relative; display: flex; margin: 16px 0 10px; padding: 4px;
  border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface-subtle);
}
.punch-type-control::before {
  content: ''; position: absolute; top: 4px; bottom: 4px; left: 4px; width: calc(50% - 4px);
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm); transition: transform 200ms var(--ease-standard); z-index: 0;
}
.punch-type-control:has(#punch-type-out:checked)::before { transform: translateX(100%); }
.punch-type-control label { position: relative; z-index: 1; flex: 1; display: block; cursor: pointer; }
.punch-type-control input { position: absolute; opacity: 0; pointer-events: none; }
.punch-type-control span {
  display: flex; align-items: center; justify-content: center; min-height: 44px; padding: 10px 12px;
  border-radius: var(--radius-md); color: var(--muted); font-weight: 600; font-size: .95rem;
  transition: color 200ms var(--ease-standard);
}
.punch-type-control input:checked + span { color: var(--primary); font-weight: 700; }
.punch-type-control input:focus-visible + span { box-shadow: 0 0 0 3px var(--focus-ring); border-radius: var(--radius-md); }
.punch-type-control:disabled { opacity: .65; }
.punch-type-control:disabled label { cursor: not-allowed; }
.punch-btn {
  display: block; width: 100%; min-height: 72px; margin: 12px 0;
  font-family: var(--font-display); font-size: 1.4rem; font-weight: 700; color: #fff; border: none; border-radius: 16px;
  transition: transform var(--dur-fast) var(--ease-standard);
}
.punch-btn { background: var(--primary); }
.punch-btn:disabled { opacity: 0.6; }
.hint { text-align: center; color: var(--muted); font-size: 0.85rem; }

/* ---- 打卡頁：補打卡提示卡片（原本入口只藏在紀錄頁的小按鈕裡，這裡隨時看得到） ---- */
.correction-banner {
  display: flex; align-items: center; gap: 14px; margin: 16px 0; padding: 14px 16px;
  border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--card); box-shadow: var(--shadow-sm);
}
.correction-banner-icon {
  display: flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 40px; height: 40px; border-radius: 50%; background: var(--surface-subtle); color: var(--muted);
}
.correction-banner-body { flex: 1 1 auto; min-width: 0; display: grid; gap: 2px; }
.correction-banner-body strong { font-size: .95rem; }
.correction-banner-body p { margin: 0; color: var(--muted); font-size: .82rem; }
.correction-banner button { flex: 0 0 auto; }
.correction-banner.attention { border-color: var(--warning); background: var(--warning-bg); }
.correction-banner.attention .correction-banner-icon { background: var(--card); color: var(--warning); }
.correction-banner.attention .correction-banner-body p { color: var(--text); }
@media (max-width: 480px) {
  .correction-banner { flex-wrap: wrap; }
  .correction-banner button { width: 100%; }
}

.status-card {
  padding: 14px; border-radius: var(--radius-lg); margin-bottom: 8px;
  background: var(--card); border: 1px solid var(--border); box-shadow: var(--shadow-sm); text-align: center;
}
.status-card.ok { border-color: var(--ok); color: var(--ok); }
.status-card.err { border-color: var(--err); color: var(--err); }
.error-text { color: var(--err); min-height: 1em; }

/* ---- 打卡成功全螢幕回饋 ----
   刻意「不」共用 .modal-overlay：檔案下方 @media (max-width: 480px) 會把
   .modal-overlay 改成 align-items: flex-end 的 bottom sheet(給既有 modal 用)，
   成功卡片在手機上必須維持置中，所以獨立一組類別。 */
.punch-success-overlay {
  position: fixed; inset: 0; z-index: 1100;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: rgba(15, 23, 42, .55);
  backdrop-filter: blur(4px);
  opacity: 0;
  /* 基準態同時是「離場態」：120ms 約為進場 180ms 的 67%，形成進慢出快。 */
  transition: opacity var(--dur-fast) var(--ease-standard);
}
/* [hidden]{display:none!important} 讓離場動畫沒有機會播，所以 JS 是兩段式：
   先移除 .is-open 播離場、再於 PUNCH_SUCCESS_EXIT_MS 之後補上 hidden。
   這段空窗期把 overlay 變成穿透的，避免蓋住底下的點擊。 */
.punch-success-overlay:not(.is-open) { pointer-events: none; }
.punch-success-overlay.is-open { opacity: 1; transition-duration: 180ms; }

.punch-success-card {
  width: 100%; max-width: 340px;
  padding: 28px 24px 18px;
  background: var(--card);
  border-radius: 20px;
  box-shadow: 0 12px 40px rgba(10, 18, 32, .28);
  text-align: center;
  transform: scale(.92) translateY(10px);
  transition: transform 130ms var(--ease-standard);
}
.punch-success-overlay.is-open .punch-success-card {
  transform: none;
  transition-duration: 200ms;
}
/* 卡片只是為了播報與焦點落點才 focusable，滑鼠點擊不該畫出焦點框 */
.punch-success-card:focus { outline: none; }
.punch-success-card:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }

/* 實心綠圓 + 白勾：白色疊在 --ok(#12a150) 上約 3.37:1，過 1.4.11 的 3:1；
   --ok 疊在 --success-bg 上只有 3.0:1，剛好卡在邊界，所以不用淡底深勾。 */
.punch-success-icon {
  display: flex; align-items: center; justify-content: center;
  width: 68px; height: 68px; margin: 0 auto 16px;
  border-radius: 50%;
  background: var(--ok); color: #fff;
}
.punch-success-title {
  margin: 0 0 6px;
  font-family: var(--font-display); font-size: 1.35rem; font-weight: 700; color: var(--text);
}
.punch-success-time {
  margin: 0 0 14px;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 2.4rem; line-height: 1.1; color: var(--text);
}
.punch-success-method {
  display: inline-block; margin: 0;
  padding: 5px 12px; border-radius: 999px;
  background: var(--surface-subtle); color: var(--tag-neutral-text);
  font-size: .82rem; font-weight: 600;
}

.punch-success-progress {
  height: 4px; margin-top: 14px;
  border-radius: 999px; background: var(--surface-subtle); overflow: hidden;
}
.punch-success-progress-bar {
  display: block; height: 100%; width: 100%;
  transform-origin: left center; transform: scaleX(1);
  border-radius: 999px; background: var(--ok);
  /* 基準態不給 transition：提前關閉時進度條要瞬間復位，
     不能讓它一邊淡出一邊反向長回去 3 秒。 */
  transition: none;
}
.punch-success-overlay.is-open .punch-success-progress-bar {
  transform: scaleX(0);
  transition: transform 3000ms linear;
}
@media (prefers-reduced-motion: reduce) {
  /* 檔案結尾的全域 reduced-motion 規則把所有 transition-duration 壓成 .01ms，
     進度條會在開場瞬間歸零、看起來像壞掉的空白軌道。這裡改成靜態滿格：
     不動，但仍保留「稍後會自動關閉」的視覺提示。overlay 本身照樣 3 秒關。
     用 !important 是為了蓋掉上面 .is-open 的 transform: scaleX(0)。 */
  .punch-success-overlay.is-open .punch-success-progress-bar { transform: none !important; }
}

/* ---- 全站操作回饋 toast ----
   z-index 1050:必須高於 .modal-overlay(1000),modal 裡送出的結果才看得到;
   必須低於 .punch-success-overlay(1100),打卡成功那層仍是最上層。
   底部錨點對齊 body 的 padding-bottom(--tabbar-height),讓 toast 浮在 nav#tabbar 之上。 */
.toast-host {
  position: fixed; z-index: 1050;
  left: 50%; transform: translateX(-50%);
  bottom: calc(var(--tabbar-height) + env(safe-area-inset-bottom, 0px));
  display: flex; flex-direction: column; gap: 8px;
  width: min(420px, calc(100vw - 24px));
  /* 容器本身不吃點擊,只有 toast 本體吃(關閉鈕要能按) */
  pointer-events: none;
}
.toast {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 11px 12px;
  border: 1px solid var(--border); border-left: 4px solid var(--muted);
  border-radius: var(--radius-md);
  background: var(--card); color: var(--text);
  box-shadow: 0 8px 24px rgba(10, 18, 32, .18);
  font-size: .9rem; font-weight: 600;
  pointer-events: auto;
  /* 基準態同時是離場態,同 .punch-success-overlay 的兩段式作法 */
  opacity: 0; transform: translateY(8px);
  transition: opacity var(--dur-fast) var(--ease-standard),
              transform var(--dur-fast) var(--ease-standard);
}
.toast.is-open { opacity: 1; transform: none; transition-duration: 180ms; }
.toast-success { border-left-color: var(--ok); background: var(--success-bg); }
/* --err 疊在 --danger-bg 上對比不足 4.5:1,本文改用 --text、只在左邊框
   保留 --err(見上面 .punch-success-icon 對同一組色的推理)。 */
.toast-error { border-left-color: var(--err); background: var(--danger-bg); color: var(--text); }
.toast-info { border-left-color: var(--primary); background: var(--primary-bg); }
.toast-text { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.toast-close {
  flex: none; width: 24px; height: 24px; min-height: 24px; padding: 0;
  border: 0; border-radius: 50%; background: transparent; color: inherit;
  font-size: 1.1rem; line-height: 1;
}
.toast-close:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }

/* ---- 送出中的按鈕 ----
   這是本檔第一組 @keyframes;檔案結尾的全域 reduced-motion 規則只壓
   transition-duration,壓不到 animation-duration,所以下面要自己補一條覆寫。 */
@keyframes ui-spin { to { transform: rotate(360deg); } }
button[aria-busy="true"]::after {
  content: ''; display: inline-block;
  width: 14px; height: 14px; margin-left: 8px; vertical-align: -2px;
  border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%;
  animation: ui-spin 700ms linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  /* 不整個拿掉:轉圈是「還在跑」的唯一線索(按鈕已 disabled、文字也換掉了)。
     放慢到近乎靜止的一圈,保留語意但不造成前庭不適。 */
  button[aria-busy="true"]::after { animation-duration: 3s; }
}

.records { list-style: none; padding: 0; margin: 8px 0; }
.records li {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 10px 12px; margin-bottom: 8px; font-size: 0.9rem;
  display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap;
}
.badge { padding: 2px 8px; border-radius: 999px; font-size: 0.75rem; color: #fff; }
.badge.identity { background: var(--navy-600); }
.badge.in { background: var(--ok); }
.badge.out { background: var(--primary); }
.badge.wifi { background: var(--navy-600); }
.badge.gps { background: var(--ah-orange); }
.badge.correction { background: var(--warning); }
.badge.late { background: var(--err); }
.muted { color: var(--muted); }
.today-records { margin-top: 40px; }
.today-records h2 { margin-bottom: 8px; }

details {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 10px 12px; margin-bottom: 12px;
}
details summary { font-weight: 600; cursor: pointer; }
details form { margin-top: 10px; }

/* 底部 tabbar 固定 5 欄(打卡/紀錄/管理/日誌/設定,bottom-nav-limit)。
   「今日出勤」「代辦」已收進管理分頁的 sub-panel,不再佔用底部欄位,
   圖示與字級因此可以放寬回 Heroicons 原生尺寸,不需要再靠縮小字級撐版。 */
nav#tabbar {
  position: fixed; bottom: 0; left: 0; right: 0; height: var(--tabbar-height);
  display: flex; justify-content: space-between; background: var(--card); border-top: 1px solid var(--border);
  padding-bottom: env(safe-area-inset-bottom);
}
nav#tabbar button {
  position: relative; flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  padding: 8px 2px; min-height: 44px; background: none; border: none;
  font-size: .78rem; line-height: 1; color: var(--muted);
  transition: color var(--dur-fast) var(--ease-standard);
}
nav#tabbar button.active { color: var(--primary); font-weight: 700; }
.tab-icon { width: 24px; height: 24px; flex: 0 0 auto; }
.tab-label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tab-badge {
  position: absolute; top: 2px; right: calc(50% - 24px);
  min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px;
  background: var(--err); color: #fff; font-size: .62rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}

/* ---- WebAuthn Credential Modal ---- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  backdrop-filter: blur(4px);
}
.modal-box {
  background: var(--bg, #fff);
  border-radius: 1rem;
  padding: 2rem;
  max-width: 400px;
  width: 90%;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
}
.modal-box h2 { margin-top: 0; }
.modal-box label { display: block; margin-bottom: 1rem; }
.modal-box input[type="text"] { width: 100%; box-sizing: border-box; }
.modal-box .primary { width: 100%; margin-bottom: 0.5rem; }
.modal-box .link-btn { width: 100%; text-align: center; }
.punch-confirm-message { font-size: 1.15rem; font-weight: 600; text-align: center; margin: 1.25rem 0 0.5rem; }
.punch-confirm-warning { min-height: 0; margin: 8px 0 0; text-align: center; }
.modal-actions { display: flex; gap: 0.75rem; margin-top: 1.25rem; }
.modal-actions button { flex: 1; margin: 0; }
.modal-actions .primary, .modal-actions .secondary { width: auto; margin-bottom: 0; }

/* ---- Admin Console ---- */
.admin-page-header { padding: 24px 4px 18px; }
/* 帶右側動作鈕的頁首（批次補正入口、返回紀錄） */
.admin-page-header.with-action {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap;
}
.admin-page-header h1 { margin: 0; text-align: left; font-size: clamp(1.9rem, 4vw, 2.45rem); line-height: 1.1; }
.admin-page-subtitle { margin: 6px 0 0; color: var(--muted); }
.eyebrow {
  margin: 0 0 5px; color: var(--primary); font-family: var(--font-mono); font-size: .72rem;
  font-weight: 600; letter-spacing: .12em;
}
.danger-text { color: var(--err); }
.admin-tabs {
  position: sticky; top: 45px; z-index: 30; display: flex; gap: 4px; padding: 5px;
  margin-bottom: 16px; overflow-x: auto; background: var(--surface-subtle); border: 1px solid var(--border);
  border-radius: var(--radius-lg); scrollbar-width: none;
  scroll-snap-type: x proximity;
}
.admin-tabs::-webkit-scrollbar { display: none; }
.admin-tabs button {
  position: relative; flex: 0 0 auto; min-height: 42px; padding: 9px 16px; border: 0; border-radius: var(--radius-md);
  background: transparent; color: var(--muted); font-weight: 600; white-space: nowrap;
  scroll-snap-align: start;
}
.admin-tabs button.active { background: var(--card); color: var(--primary); box-shadow: var(--shadow-sm); }
/* admin 使用者最多同時看到 8 顆 sub-tab(主管事務 today/todo + 6 個系統管理面板),
   會橫向捲動;第一顆可見的管理面板按鈕(由 app.js 的 syncAdminTabVisibility()
   在有主管事務與系統管理面板都可見時加上 .group-start)用左邊框做視覺分隔,
   純裝飾、無邏輯依賴。 */
.admin-tabs button.group-start {
  margin-left: 6px; padding-left: 16px; border-left: 1px solid var(--border);
}
.admin-tab-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; margin-left: 6px; padding: 0 5px;
  border-radius: 999px; background: var(--err); color: #fff;
  font-size: .68rem; font-weight: 700; vertical-align: 1px;
}
.admin-panel {
  padding: clamp(16px, 3vw, 28px); background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
}
.panel-heading { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; margin-bottom: 20px; }
.panel-heading h2 { margin: 0; font-size: 1.35rem; }
.panel-heading p { margin: 5px 0 0; color: var(--muted); }
.panel-heading-actions { align-items: center; }
.filter-bar {
  display: flex; flex-direction: row; flex-wrap: wrap;
  align-items: end; gap: 12px 16px; padding: 16px; background: var(--surface-subtle); border-radius: var(--radius-lg);
}
.filter-bar label { flex: 1 1 170px; min-width: 0; }
/* 個人出勤的員工欄是 div 包 label，補上與 label 相同的伸縮規則。 */
.filter-bar .filter-employee { flex: 1 1 170px; min-width: 0; }
/* 開始/結束日期用 grid 綁成一組，換行時整組一起換，兩個日期永遠同一列。 */
.filter-bar .date-range {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px 16px;
  flex: 1 1 380px; min-width: 0;
}
.filter-bar input, .filter-bar select { width: 100%; }
.filter-bar button { flex: 0 0 auto; }
/* .search-field 預設有 margin-bottom(給員工管理頁的搜尋框用),
   放進 filter-bar 裡會被 align-items:end 往上推,跟其他欄位底邊對不齊。 */
.filter-bar .search-field { margin-bottom: 0; }
/* 桌面瀏覽器：出勤篩選器改用固定 12 欄格線，換行位置不再隨視窗寬度浮動。
   上列放員工相關欄位（員工欄佔 6 欄，員編 · 代號 · 姓名才不會被截斷），
   下列固定放開始日期、結束日期、異常篩選與查詢。 */
@media (min-width: 801px) {
  #attendance-filter.filter-bar,
  #records-attendance-filter.filter-bar {
    display: grid; grid-template-columns: repeat(12, 1fr);
  }
  #attendance-filter.filter-bar > *,
  #records-attendance-filter.filter-bar > * { grid-column: span 3; min-width: 0; }
  #attendance-filter.filter-bar > .filter-employee,
  #records-attendance-filter.filter-bar > .filter-employee { grid-column: span 6; }
  /* 明確從第 1 欄起算，強迫日期整組換到新的一列，日期與異常篩選才會固定同列。 */
  #attendance-filter.filter-bar > .date-range,
  #records-attendance-filter.filter-bar > .date-range { grid-column: 1 / span 6; }
  #attendance-filter.filter-bar > button,
  #records-attendance-filter.filter-bar > button { justify-self: start; }
}
.summary-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; margin: 20px 0; }
.summary-card {
  --summary-accent: var(--primary);
  --summary-accent-bg: var(--primary-bg);
  min-width: 0; padding: 16px; background: var(--card); border: 1px solid var(--border); border-top: 3px solid var(--primary);
  border-radius: var(--radius-md); box-shadow: var(--shadow-sm); color: var(--text); font: inherit; text-align: left;
  appearance: none; transition: border-color var(--dur-fast) var(--ease-standard), background-color var(--dur-fast) var(--ease-standard), box-shadow var(--dur-fast) var(--ease-standard), transform var(--dur-fast) var(--ease-standard);
}
.summary-card.warning { --summary-accent: var(--warning); --summary-accent-bg: var(--warning-bg); border-top-color: var(--warning); }
.summary-card.danger { --summary-accent: var(--err); --summary-accent-bg: var(--danger-bg); border-top-color: var(--err); }
.summary-card:hover { border-color: var(--summary-accent); transform: translateY(-1px); }
.summary-card:focus-visible { outline: 3px solid var(--summary-focus); outline-offset: 2px; }
.summary-card[aria-pressed="true"] {
  border-color: var(--summary-accent);
  background: var(--summary-accent-bg);
  box-shadow: inset 0 0 0 2px var(--summary-accent), var(--shadow-sm);
}
.summary-card[aria-pressed="true"] span { color: var(--summary-accent); font-weight: 700; }
.summary-card span, .summary-card small { display: block; color: var(--muted); }
.summary-card strong { display: block; margin: 5px 0 1px; font: 700 2rem/1 var(--font-mono); }
.summary-card small { font-size: .75rem; }
/* 今日出勤統計卡:三欄、不可點擊(純顯示,不是篩選按鈕),取消 .summary-card
   原本給互動用的 hover 位移與 cursor。 */
.summary-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.summary-card.is-static { cursor: default; }
.summary-card.is-static:hover { border-color: var(--border); transform: none; }

/* 今日出勤:狀態/關鍵字/部門篩選,樣式沿用 .filter-bar,這裡只補與統計卡、
   分組清單之間的垂直節奏。 */
#today-filter { margin-top: 20px; }
#today-filter-count { margin: 8px 0 0; }

/* 今日出勤:依狀態分組的卡片列表,一列一員工,不用 <table>(同出勤總表的作法)。
   欄位:員工(姓名+部門/英文代號/職級) / 打卡時間(或排定上班時間) / 狀態標籤(可能多個)。 */
.today-group { margin: 20px 0; }
.today-group-heading { display: flex; align-items: baseline; gap: 8px; margin-bottom: 10px; }
.today-group-heading h3 { margin: 0; font-size: 1rem; }
.today-group-count {
  min-width: 22px; padding: 1px 7px; border-radius: 999px; background: var(--surface-subtle);
  color: var(--tag-neutral-text); font: 700 .8rem/1.4 var(--font-mono); text-align: center;
}
.today-group-empty { padding: 10px 16px; }
.today-row {
  display: grid; grid-template-columns: minmax(200px, 1.3fr) minmax(180px, 1fr) minmax(160px, 1.1fr);
  align-items: center; gap: 12px; padding: 12px 16px; margin-bottom: 8px;
  border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--card);
}
.today-row .who { display: grid; min-width: 0; gap: 2px; }
.today-row .who small { color: var(--muted); font-size: .78rem; }
.today-row .time { color: var(--muted); font-size: .85rem; font-variant-numeric: tabular-nums; }
.today-row .tags { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; }

.empty-state {
  padding: 32px 16px; border: 1px dashed var(--border); border-radius: var(--radius-lg);
  color: var(--muted); text-align: center;
}
.attendance-days { display: grid; gap: 10px; }

/* 出勤總表:一列一員工的可展開卡片,與 .employee-row 同一套 grid 卡片列風格,
   不用 <table>。欄位:展開箭頭 / 員工 / 次數 / 分鐘,與 .summary-table-head
   的表頭欄位對齊。 */
.summary-table-head {
  display: grid; grid-template-columns: 20px minmax(200px, 1.6fr) 110px minmax(90px, max-content);
  gap: 12px; padding: 0 16px; margin-bottom: 6px;
  color: var(--muted); font-size: .78rem; font-weight: 600;
}
.attendance-summary-row {
  display: grid; grid-template-columns: 20px minmax(200px, 1.6fr) 110px minmax(90px, max-content);
  align-items: center; gap: 12px; width: 100%;
  padding: 14px 16px; border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--card); color: var(--text); font: inherit; text-align: left; cursor: pointer;
}
.attendance-summary-row:hover { border-color: var(--primary); }
.attendance-summary-row:focus-visible { outline: 3px solid var(--summary-focus); outline-offset: 2px; }
.attendance-summary-row .chev { transition: transform 150ms var(--ease-standard); color: var(--muted); }
.attendance-summary-row[aria-expanded="true"] .chev { transform: rotate(90deg); }
.attendance-summary-row .who { display: grid; min-width: 0; gap: 2px; }
.attendance-summary-row .who small { color: var(--muted); font-size: .8rem; }
.attendance-summary-row .count, .attendance-summary-row .mins {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap;
}
.summary-row-group { margin-bottom: 10px; }
.summary-row-detail {
  display: grid; gap: 6px; margin-top: 6px; padding: 12px 16px 12px 48px;
  border: 1px dashed var(--border); border-radius: var(--radius-md); background: var(--surface-subtle);
}
/* 一列一「異常」(不是一列一天):日期 / 遲到早退標籤 / 分鐘數 / 實際打卡時間
   對排定時間,四欄。日期用 max-content 而非固定寬度,避免「9月1日 週二」這種
   7 個中日文字被壓成兩行;最後一欄吸收所有剩餘寬度,不再留一大片空白。
   標籤(.status-tag)靠文字+顏色+圖示三重區分遲到/早退,不再只靠圖示方向。 */
.summary-detail-item {
  display: grid;
  grid-template-columns: minmax(120px, max-content) auto minmax(84px, max-content) minmax(0, 1fr);
  align-items: center; gap: 12px; padding: 6px 8px; border-left: 3px solid transparent;
  border-radius: var(--radius-md); font-size: .85rem;
}
.summary-detail-item:hover { background: var(--card); }
.summary-detail-item.is-late { border-left-color: var(--warning); }
.summary-detail-item.is-early { border-left-color: var(--err); }
.summary-detail-item .d { white-space: nowrap; }
.summary-detail-item .status-tag { gap: 5px; }
.summary-detail-item .icon { display: inline-flex; width: 14px; height: 14px; flex: none; }
.summary-detail-item .icon svg { width: 100%; height: 100%; }
.summary-detail-item .m { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.summary-detail-item .t { color: var(--muted); font-variant-numeric: tabular-nums; }
.summary-detail-empty { margin: 0; color: var(--muted); font-size: .85rem; }
.attendance-day {
  display: grid; grid-template-columns: minmax(190px, .8fr) minmax(300px, 1.2fr); align-items: center; gap: 18px;
  padding: 15px 16px; border: 1px solid var(--border); border-radius: var(--radius-lg);
}
.correction-actions { grid-column: 1 / -1; display: flex; justify-content: center; flex-wrap: wrap; gap: 10px; }
/* 一次 appendCorrectionStatus 的產物(標籤+細節行)綁成一組:缺勤日整卡當
   host 時 .correction-actions 是橫排置中,不分組的話上班/下班的細節行會
   交錯在同一條橫列裡,看不出哪幾行屬於哪個班別。 */
.correction-status-group { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.correction-request-detail { display: block; color: var(--muted); }
/* 貼在打卡卡片內時改為靠左直排:欄寬只有 130px,狀態與簽核人並排會被擠爆。 */
.punch-detail .correction-actions {
  grid-column: auto; flex-direction: column; align-items: flex-start; gap: 4px; margin-top: 8px;
}
.punch-detail .correction-status-group { width: 100%; }
/* 自由輸入的申請理由/駁回原因沒有長度上限,貼一串無空白的英數字(如網址)
   會橫向撐破這個只有 130px 的欄位,需要 overflow-wrap 讓它改成斷行。 */
.punch-detail .correction-request-detail,
.punch-detail .correction-decision-note { margin-top: 0; overflow-wrap: anywhere; }
/* 待補正日在卡片底部的單一入口——所有互動都導向補正畫面逐筆決定,
   紀錄頁本身不再提供就地展開的表單。 */
.correction-day-actions { grid-column: 1 / -1; display: flex; justify-content: center; margin-top: 4px; }
.correction-request-toolbar { display: flex; gap: 8px; margin-bottom: 12px; }
.correction-request-list { display: grid; gap: 12px; margin-bottom: 20px; }
.correction-control-label { gap: 4px; font-size: .78rem; color: var(--muted); font-weight: 600; }
/* 理由欄位橫跨整列：一行文字框比擠在半欄裡好讀，也強調這是必填項目。 */
.correction-reason-field { grid-column: 1 / -1; }
.correction-reason-input {
  width: 100%; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--card); color: var(--text); font: inherit; resize: vertical;
}
.reason-option-select { width: 100%; }
.reason-other-input { margin-top: 6px; }

/* ---- 補正日群組：<details> 可折疊，summary 只放事實(日期/狀態/筆數/即時計數) ---- */
.correction-day-group { padding: 0; overflow: hidden; }
.correction-day-summary {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
  padding: 14px 16px; min-height: 44px; list-style: none;
}
.correction-day-summary::-webkit-details-marker { display: none; }
.correction-day-summary::before {
  content: '▸'; color: var(--muted); font-size: .85rem; transition: transform var(--dur-fast) var(--ease-standard);
}
.correction-day-group[open] > .correction-day-summary::before { transform: rotate(90deg); }
.correction-day-summary > strong { font-size: 1rem; }
.correction-day-punch-count { font-size: .82rem; }
.correction-day-live { margin-left: auto; font-size: .82rem; }
.correction-day-body {
  display: grid; gap: 12px; padding: 4px 16px 16px; border-top: 1px solid var(--border);
}
/* 只有手動加入的日群組才有這個移除控制,放在 body 第一個子元素而不是
   summary——summary 裡的 button 會連帶 toggle <details>，且其可及名稱是由
   文字內容組成，塞進「移除這天」會讓整顆折疊鈕唸起來很奇怪。 */
.correction-day-remove { justify-self: end; }
.correction-day-remove-confirm { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* ---- 逐筆打卡列：事實區(唯讀) + 三選一 radio + 選了才展開的表單 ---- */
.correction-punch-row {
  display: grid; gap: 10px; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface-subtle);
}
.correction-punch-fact { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; }
.correction-punch-index { font-size: .78rem; }
.correction-punch-time { font: 600 1.05rem/1.25 var(--font-mono); font-variant-numeric: tabular-nums; }
.correction-punch-anomaly { font-weight: 600; }
.correction-decision-note { display: block; width: 100%; }

/* 這一列會不會被送出的勾選提示：純視覺,不是另一個可互動控制項(見 JS 端
   aria-hidden 註解)。用外框圓圈 + 打勾圖示,不是只變色——色弱使用者也分得出
   已勾選/未勾選,而不是只能靠底色深淺猜。 */
.correction-item-check {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 20px; height: 20px; border-radius: 50%;
  border: 1.5px solid var(--border); background: var(--card); color: transparent;
  transition: border-color var(--dur-fast) var(--ease-standard), background-color var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.correction-item-check svg { width: 11px; height: 11px; }
.correction-item-check.is-checked { border-color: var(--primary); background: var(--primary); color: #fff; }
.correction-item-check.is-checked.is-danger { border-color: var(--err); background: var(--err); }

.correction-punch-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin: 0; padding: 0; border: 0;
}
/* 三選一用 radio 而非自訂按鈕：免費拿到鍵盤操作、radiogroup 語意與 checked 狀態。
   pill 高度 ≥44px、間距 ≥8px 符合觸控目標大小；選中狀態不只變色,加粗字重＋外框,
   不單靠顏色分辨。 */
.correction-radio-pill {
  display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 8px 14px;
  border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--card);
  font-size: .85rem; font-weight: 500; cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-standard), background-color var(--dur-fast) var(--ease-standard);
}
.correction-radio-pill:has(input:checked) {
  border-color: var(--primary); background: var(--primary-bg); font-weight: 700;
}
.correction-radio-pill:has(input:disabled) { opacity: .5; cursor: not-allowed; }
.correction-radio-pill-danger:has(input:checked) { border-color: var(--err); background: var(--danger-bg); color: var(--err); }
.correction-radio-pill input[type="radio"] { width: 18px; height: 18px; margin: 0; accent-color: currentColor; }

.correction-punch-form {
  display: grid; gap: 10px; padding: 12px; border: 1px dashed var(--border); border-radius: var(--radius-md);
  background: var(--card);
}
.correction-edit-fields { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; }
.correction-edit-fields select, .correction-edit-fields input { width: 100%; }

.correction-add-punch-row { border-style: dashed; background: var(--card); }
.correction-add-punch-btn { justify-self: start; }

/* 整列跟著打勾圖示一起變色,掃過一長串打卡列表時不用逐一看小圖示——
   兩種卡片(既有打卡列、新增打卡列)共用同一套「已勾選」樣式,才會一致。 */
.correction-punch-row.is-selected { border-color: var(--primary); background: var(--primary-bg); }
.correction-punch-row.is-selected.is-danger { border-color: var(--err); background: var(--danger-bg); }

/* 送出時擋下來的那幾列:用外框環而不是改 border-color/background,才不會跟
   .is-selected / .is-danger 已經佔用的那兩個屬性打特異度戰爭。 */
.correction-punch-row.is-invalid { box-shadow: 0 0 0 2px var(--err); }
.correction-row-error { margin: 0; color: var(--err); font-size: .82rem; font-weight: 600; }
.correction-submit-error { margin: 12px 0 0; font-weight: 600; }
.correction-existing-add-list { display: grid; gap: 2px; }
.correction-existing-add-line { margin: 0; }

/* ---- 補打卡頁：步驟指引與「其他忘記打卡的日期」新增卡 ---- */
.flow-steps {
  display: flex; flex-wrap: wrap; gap: 8px 20px; margin: 0 0 20px; padding: 0; list-style: none;
  color: var(--muted); font-size: .85rem; font-weight: 600;
}
.flow-steps li { display: flex; align-items: center; gap: 8px; }
.flow-step-index {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--surface-subtle); color: var(--muted); font-size: .78rem; font-weight: 700;
}
.step-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; margin-right: 8px; border-radius: 50%;
  background: var(--primary-bg); color: var(--primary); font-size: .8rem; font-weight: 700;
  vertical-align: middle;
}
.step-heading { display: flex; align-items: center; margin: 4px 0 2px; font-size: 1.05rem; }
.correction-add-row {
  display: flex; flex-wrap: wrap; align-items: end; gap: 12px 16px;
  padding: 14px 16px; margin-bottom: 8px;
  border: 1px dashed var(--border); border-radius: var(--radius-lg); background: var(--surface-subtle);
  cursor: pointer; transition: border-color .15s ease, background-color .15s ease;
}
.correction-add-row:hover { border-color: var(--primary); }
.correction-add-row:focus-within { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-bg); }
.correction-add-row-icon {
  display: flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--primary-bg); color: var(--primary); font-size: 1.3rem; font-weight: 700; flex: 0 0 auto;
}
.correction-add-row label { flex: 1 1 200px; min-width: 0; cursor: pointer; }
.correction-add-row button { flex: 0 0 auto; }
.correction-add-note { margin-bottom: 20px; }
.badge-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; margin-left: 6px; padding: 0 6px;
  border-radius: 999px; background: var(--err); color: #fff; font-size: .72rem; font-weight: 700;
  vertical-align: middle;
}
.correction-inbox { margin-bottom: 16px; }
.correction-list { display: grid; gap: 10px; }
.correction-notification {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 16px; border: 1px solid var(--warning); border-radius: var(--radius-lg);
  background: var(--warning-bg);
}
.correction-notification > div { display: grid; gap: 4px; }
.correction-notification-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.correction-applicant-dept { color: var(--muted); font-weight: 400; }
.correction-submitted-at { opacity: .8; }
.correction-notification-actions { display: flex; gap: 8px; }
.correction-reject-form { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.correction-reject-note {
  width: 100%; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--card); color: var(--text); font: inherit; resize: vertical;
}
/* 申請刪除此筆:貼在異常卡下方的行內表單,理由必填、送出前用確認文字
   覆誦目標卡的日期時間,破壞性操作先讓使用者確認一次再送出。 */
.correction-void-form { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; width: 100%; }
.correction-void-confirm-text { margin: 0; font-size: .82rem; }
.correction-decision-note { display: block; color: var(--muted); margin-top: 4px; }
.correction-notification span, .correction-notification small { color: var(--muted); }
.attendance-day-heading { display: grid; gap: 8px; }
.attendance-day-heading > strong { font-size: 1rem; }
.attendance-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.status-tag {
  display: inline-flex; align-items: center; width: max-content; padding: 3px 8px; border-radius: 999px;
  background: var(--surface-subtle); color: var(--muted); font-size: .73rem; font-weight: 600;
}
.status-tag.admin { background: #eef0ff; color: #0019ff; }
.status-tag.success { background: var(--success-bg); color: var(--ok); }
.status-tag.warning { background: var(--warning-bg); color: var(--warning); }
.status-tag.danger { background: var(--danger-bg); color: var(--err); }
.status-tag.neutral { background: var(--surface-subtle); color: var(--tag-neutral-text); }
.audit-entry {
  display: flex; flex-direction: column; gap: 6px;
  padding: 14px 16px; border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--card);
}
.audit-entry-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.audit-entry-head > strong { flex: 1 1 auto; }
.audit-entry-head > small { color: var(--muted); }
.audit-entry-parties { color: var(--muted); font-size: .85rem; }
.audit-entry-note { font-size: .85rem; }
.audit-entry-group { gap: 10px; }
.audit-entry-group > summary { cursor: pointer; font-weight: 600; list-style: none; }
.audit-entry-group > summary::-webkit-details-marker { display: none; }
.audit-entry-group > .audit-entry { margin-left: 8px; }
.audit-pager { display: flex; justify-content: center; margin-top: 14px; }
.attendance-punches { display: grid; grid-template-columns: repeat(2, minmax(130px, 1fr)); gap: 10px; }
.punch-detail { min-width: 0; padding: 10px 12px; background: var(--surface-subtle); border-radius: var(--radius-md); }
.punch-detail span, .punch-detail small { display: block; color: var(--muted); font-size: .75rem; }
.punch-detail strong { display: block; margin: 2px 0; font: 600 1.05rem/1.25 var(--font-mono); }
/* 上一條的 muted 特異性高於 .danger-text，補正提示的紅字要在此重新宣告才生效。 */
.punch-detail span.danger-text, .punch-detail small.danger-text { color: var(--err); }
/* 缺卡的空位:用虛線框與淡色時間表示「這格還沒有打卡紀錄」,補打卡按鈕與
   補正狀態就掛在這裡（見 public/punch-corrections.js）。 */
.punch-detail-missing { background: transparent; border: 1px dashed var(--border); }
.punch-detail-missing strong { color: var(--muted); font-size: .95rem; }
/* 缺勤日沒有任何打卡可畫時間軸,改顯示一段說明文字,取代整塊空白。 */
.attendance-absent-notice { grid-column: 1 / -1; margin: 0; padding: 10px 12px; color: var(--err); background: var(--danger-bg); border-radius: var(--radius-md); }
.search-field { max-width: 420px; margin-bottom: 16px; }
.employee-list { display: grid; gap: 8px; }
.reason-option-list { display: grid; gap: 8px; }
.reason-option-row {
  display: grid; grid-template-columns: minmax(220px, 1fr) auto auto;
  align-items: center; gap: 12px;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius-lg);
}
.reason-option-info { display: grid; gap: 4px; min-width: 0; }
.reason-option-actions { display: flex; gap: 8px; }
/* 打卡地點清單副標(座標/半徑、CIDR 範圍)用等寬字呈現數字,對齊比較整齊。 */
.location-meta { font-family: var(--font-mono); font-size: .8rem; }
/* 保留兩行高度,CIDR 輸入時預覽文字出現/消失不會推擠下方按鈕(layout shift)。 */
.cidr-preview { min-height: 2.6em; font-family: var(--font-mono); font-size: .85rem; color: var(--muted); margin: 4px 0 0; }
.employee-row {
  display: grid; grid-template-columns: minmax(220px, 1.4fr) minmax(150px, .7fr) 220px;
  align-items: center; gap: 16px; padding: 14px 16px; border: 1px solid var(--border); border-radius: var(--radius-lg);
}
.employee-identity { display: grid; min-width: 0; gap: 2px; }
.employee-code { color: var(--primary); font: 600 .75rem/1.2 var(--font-mono); }
.employee-email { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .82rem; }
.employee-status { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.employee-actions {
  display: grid; grid-template-columns: 60px 90px 58px;
  align-items: center; justify-content: end; gap: 6px;
}
.employee-actions button { width: 100%; }
.employee-devices { grid-column: 1 / -1; min-width: 0; padding-top: 10px; border-top: 1px solid var(--border); }
.employee-devices summary { width: max-content; color: var(--primary); cursor: pointer; font-size: .84rem; font-weight: 600; }
.employee-device-list { display: grid; gap: 8px; margin-top: 10px; }
.employee-device-empty { margin: 0; padding: 10px 12px; background: var(--surface-subtle); border-radius: var(--radius-md); }
.import-card, .settings-card {
  padding: 18px; border: 1px solid var(--border); background: var(--bg); border-radius: var(--radius-lg);
}
.import-card { display: grid; grid-template-columns: minmax(0, 1fr); max-width: 680px; gap: 12px; }
.import-card p { margin: 0; }
.import-card label { min-width: 0; }
.import-card input[type="file"] { width: 100%; max-width: 100%; }
.download-link { width: max-content; color: var(--primary); font-weight: 600; }
.system-grid { display: grid; grid-template-columns: minmax(0, 760px); gap: 16px; }
.system-heading { grid-column: 1 / -1; margin-bottom: 0; }
.settings-card h3 { margin: 0 0 16px; font: 700 1.05rem/1.2 var(--font-display); }
.field-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; }
.field-grid label { justify-content: flex-start; }
.field-grid .field-label-text { display: block; min-height: 2.4em; line-height: 1.2; }
.device-list { display: grid; gap: 8px; }
.device-row {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: 11px 12px; background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-md);
}
.device-row > div { display: grid; min-width: 0; gap: 2px; }
.device-row span { overflow-wrap: anywhere; font-size: .8rem; }
.admin-modal { max-width: 560px; padding: 24px; }
.modal-box.admin-modal label { display: flex; margin-bottom: 0; }
.modal-box.admin-modal input:not([type="checkbox"]), .modal-box.admin-modal select { width: 100%; }
.time-select-pair { display: flex; gap: 6px; }
.time-select-pair select { width: 100%; min-width: 0; }
.compact-modal { max-width: 480px; }
.modal-heading { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; margin-bottom: 18px; }
.modal-heading h2 { margin: 0; font-size: 1.4rem; }
.icon-close { padding: 6px; border: 0; background: transparent; color: var(--muted); font-size: .85rem; }
.icon-close:hover { color: var(--text); }
.switch-row { padding: 10px 12px; background: var(--surface-subtle); border-radius: var(--radius-md); }
.modal-description { margin: 0 0 16px; }
.form-note { margin: -3px 0 0; font-size: .8rem; }
.danger-callout {
  padding: 12px; color: var(--err); background: var(--danger-bg); border-radius: var(--radius-md); font-size: .9rem;
}

@media (max-width: 800px) {
  .admin-page-header { padding-top: 12px; }
  .admin-tabs { margin-left: -8px; margin-right: -8px; border-radius: 0; border-left: 0; border-right: 0; }
  .filter-bar label,
  .filter-bar .filter-employee { flex-basis: 100%; }
  .filter-bar .date-range { flex-basis: 100%; }
  .filter-bar button { flex-basis: 100%; width: 100%; }
  .attendance-day { grid-template-columns: 1fr; }
  .correction-notification { align-items: stretch; flex-direction: column; }
  .correction-edit-fields { grid-template-columns: 1fr; }
  .correction-day-live { margin-left: 0; flex-basis: 100%; }
  .employee-row { grid-template-columns: 1fr auto; }
  .employee-identity { grid-column: 1; }
  .employee-status { grid-column: 2; grid-row: 1; justify-content: flex-end; }
  .employee-actions {
    grid-column: 1 / -1; display: flex; justify-content: flex-start;
    padding-top: 10px; border-top: 1px solid var(--border);
  }
  .system-grid { grid-template-columns: 1fr; }
  .system-heading { grid-column: auto; }
  .summary-table-head { display: none; }
  .attendance-summary-row { grid-template-columns: 20px 1fr; row-gap: 4px; }
  .attendance-summary-row .count, .attendance-summary-row .mins { grid-column: 2; text-align: left; }
  .summary-row-detail { padding-left: 16px; }
  /* 窄螢幕下四欄擠不下,退成三行堆疊:日期+標籤一行、分鐘數一行、打卡時間
     一行,避免橫向捲動(出勤總表在手機上仍要能看)。 */
  .summary-detail-item {
    grid-template-columns: 1fr auto; grid-template-rows: auto auto auto; row-gap: 4px;
  }
  .summary-detail-item .d { grid-column: 1; grid-row: 1; }
  .summary-detail-item .status-tag { grid-column: 2; grid-row: 1; }
  .summary-detail-item .m { grid-column: 1 / -1; grid-row: 2; }
  .summary-detail-item .t { grid-column: 1 / -1; grid-row: 3; }
}

@media (max-width: 520px) {
  body.admin-mode main { padding: 10px; }
  .admin-panel { padding: 14px; }
  .panel-heading, .panel-heading-actions { align-items: stretch; flex-direction: column; }
  .panel-heading-actions button { width: 100%; }
  .filter-bar { padding: 12px; }
  .correction-add-row { padding: 12px; }
  .correction-add-row label, .correction-add-row button { flex-basis: 100%; }
  .summary-grid { grid-template-columns: 1fr; gap: 8px; }
  .summary-card { display: grid; grid-template-columns: 1fr auto; align-items: center; column-gap: 12px; padding: 12px 14px; }
  .summary-card strong { grid-column: 2; grid-row: 1 / 3; margin: 0; }
  .attendance-punches, .field-grid { grid-template-columns: minmax(0, 1fr); }
  /* 窄螢幕下原生日期輸入框(YYYY/MM/DD 或在地化長格式)在雙欄並排時會被日曆圖示截斷，改為單欄堆疊。 */
  .filter-bar .date-range { grid-template-columns: minmax(0, 1fr); }
  .employee-row { grid-template-columns: 1fr; padding: 13px; }
  .employee-identity, .employee-status, .employee-actions { grid-column: 1; grid-row: auto; justify-content: flex-start; }
  .employee-actions button { flex: 1; }
  .modal-overlay { align-items: flex-end; }
  .modal-box.admin-modal { width: 100%; max-width: none; max-height: 92vh; overflow-y: auto; border-radius: 14px 14px 0 0; padding: 20px 16px calc(20px + env(safe-area-inset-bottom)); }
  .device-row { align-items: flex-start; }
  .today-row { grid-template-columns: 1fr; gap: 8px; }
  .today-row .tags { justify-content: flex-start; }
}

/* 版號顯示(登入頁小字 + 設定頁「關於」)。
   --muted 疊在 --bg 上實測只有 4.32:1,未達 AA 的 4.5:1;沿用專案已為同樣
   問題準備的 --tag-neutral-text(7.16:1)。 */
.app-version {
  margin-top: 24px; text-align: center;
  font-size: 0.8rem; color: var(--tag-neutral-text);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
}
.build-info {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: 6px 12px; margin: 10px 0 12px; font-size: 0.8rem;
}
.build-info dt { color: var(--tag-neutral-text); }
.build-info dd {
  margin: 0; min-width: 0;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
  background: var(--surface-subtle); border-radius: var(--radius-md); padding: 1px 6px;
}
.build-info-actions button { width: auto; min-height: 44px; padding: 11px 16px; font-size: .9rem; }
.build-info-msg { min-height: 1.2em; margin: 6px 0 0; font-size: .8rem; color: var(--tag-neutral-text); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; transition-duration: .01ms !important; }
}
