/* ================================================================
   平台介面（企劃書 §8；使用者 2026-09-30：「外觀做成與VSMS一樣」）
   顏色、圓角、字型一律用 workspace-tokens.css 的 --vw-* token，那個檔在這個檔之前載入。
   這裡只定義 LRMS 自己的識別色（§8.7 莓紫）——整個檔案裡只有這三個色碼。
   ================================================================ */
:root {
  --vw-accent: #8A2F7A;            /* 內容區的連結、焦點框、選取；對白底 7.6 */
  --vw-accent-subtle: #F8EAF5;     /* 選取列的底色；識別色在其上 6.5 */
  --vw-accent-on-chrome: #E59AD6;  /* 頂欄與側欄上的目前項目色條；對墨色頂欄 7.7 */
  /* 框架外的原值留一份。.vw-chrome 會把一般 token 換成框架色；框架裡彈出的白底選單
     （.vw-chrome-reset）要換回來時用這幾個。自訂屬性在 :root 就算好值，往下繼承的是值，
     不會跟著框架裡的換色一起變。 */
  --lrms-surface: var(--vw-surface);
  --lrms-surface-subtle: var(--vw-surface-subtle);
  --lrms-border: var(--vw-border);
  --lrms-ink: var(--vw-ink);
  --lrms-text-secondary: var(--vw-text-secondary);
  --lrms-text-muted: var(--vw-text-muted);
  --lrms-accent: var(--vw-accent);
  --lrms-accent-subtle: var(--vw-accent-subtle);
}
.vw-chrome-reset {
  --vw-surface: var(--lrms-surface);
  --vw-surface-subtle: var(--lrms-surface-subtle);
  --vw-border: var(--lrms-border);
  --vw-ink: var(--lrms-ink);
  --vw-text-secondary: var(--lrms-text-secondary);
  --vw-text-muted: var(--lrms-text-muted);
  --vw-accent: var(--lrms-accent);
  --vw-accent-subtle: var(--lrms-accent-subtle);
  color: var(--vw-ink);
}

body { font-family: var(--vw-font-sans); margin: 0; background: var(--vw-bg); color: var(--vw-ink); }
a { color: var(--vw-accent); }

/* ---------- 頂欄（§8.3）：高 48px、墨色底、左右內距 16px、元素間距 16px ---------- */
.vw-topbar {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; gap: 16px;
  height: 48px; padding: 0 16px; box-sizing: border-box;
  background: var(--vw-chrome-top); border-bottom: 1px solid var(--vw-border);
  color: var(--vw-text-secondary); white-space: nowrap;
}
.vw-topbar svg { flex: 0 0 auto; }
.vw-iconbtn {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0; border: 0; border-radius: var(--vw-radius-control);
  background: none; color: var(--vw-text-secondary); cursor: pointer; text-decoration: none;
}
.vw-iconbtn:hover { background: var(--vw-surface-subtle); color: var(--vw-ink); }
.vw-menu-btn { display: none; }
.vw-switcher, .vw-brand {
  display: inline-flex; align-items: center; gap: 8px; height: 32px; padding: 0 6px;
  border: 0; border-radius: var(--vw-radius-control); background: none; cursor: pointer;
  color: var(--vw-ink); font: 700 14px var(--vw-font-sans); text-decoration: none;
}
.vw-switcher:hover, .vw-brand:hover { background: var(--vw-surface-subtle); }
/* 標誌方塊：識別色底、白勾。用 :root 的識別色，框架裡的 --vw-accent 已經換成淺色版。 */
.vw-logo {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: var(--vw-radius-control);
  background: var(--lrms-accent); color: var(--vw-primary-text);
}
.vw-chevron { color: var(--vw-text-muted); }
.vw-apps { display: flex; align-items: center; gap: 4px; min-width: 0; overflow: hidden; }
.vw-apps a {
  display: flex; align-items: center; flex-shrink: 0; height: 32px; padding: 0 12px;
  border-radius: var(--vw-radius-control); font-size: 13px; font-weight: 500;
  color: var(--vw-text-secondary); text-decoration: none;
}
.vw-apps a:hover { background: var(--vw-surface-subtle); color: var(--vw-ink); }
.vw-apps a[aria-current="page"] { background: var(--vw-accent-subtle); color: var(--vw-ink); }
.vw-topbar__end { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.vw-bell__badge {
  position: absolute; top: 2px; right: 0; min-width: 16px; height: 16px; padding: 0 4px;
  box-sizing: border-box; border-radius: 999px; background: var(--vw-chrome-badge);
  color: var(--vw-primary-text); font-size: 10px; font-weight: 700; line-height: 16px; text-align: center;
}
.vw-bell__badge[hidden] { display: none; }
.vw-user {
  display: inline-flex; align-items: center; gap: 8px; height: 32px; padding: 0 6px 0 4px;
  border: 0; border-radius: var(--vw-radius-control); background: none; cursor: pointer;
  color: var(--vw-text-secondary); font: 500 13px var(--vw-font-sans);
}
.vw-user:hover { background: var(--vw-surface-subtle); color: var(--vw-ink); }
/* 頭像：帳號前兩字大寫；框架裡的 --vw-accent 是淺色版識別色，字用墨色。 */
.vw-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 999px;
  background: var(--vw-accent); color: var(--vw-chrome-top); font-size: 11px; font-weight: 700;
}
.vw-login { padding: 0 8px; color: var(--vw-ink); font-size: 13px; text-decoration: none; }
.vw-login:hover { text-decoration: underline; }

/* 下拉清單（系統切換、使用者選單）：從框架裡彈出來，但維持白底（§8.3、§8.5）。 */
.vw-dropdown { position: relative; }
.vw-menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 60;
  min-width: 220px; padding: 4px; box-sizing: border-box;
  background: var(--vw-surface); border: 1px solid var(--vw-border);
  border-radius: var(--vw-radius-card);
  box-shadow: 0 8px 24px color-mix(in srgb, var(--lrms-ink) 16%, transparent);
  white-space: normal;
}
.vw-dropdown--end .vw-menu { left: auto; right: 0; }
.vw-menu[hidden] { display: none; }
.vw-menu [role="menuitem"] {
  display: flex; align-items: center; gap: 8px; width: 100%; box-sizing: border-box;
  padding: 8px 10px; border: 0; border-radius: var(--vw-radius-control); background: none;
  color: var(--vw-ink); font: 13px var(--vw-font-sans); text-align: left; text-decoration: none; cursor: pointer;
}
.vw-menu [role="menuitem"]:hover, .vw-menu [role="menuitem"]:focus-visible {
  background: var(--vw-surface-subtle); outline: none;
}
.vw-menu form { margin: 0; }
.vw-menu__sep { margin: 4px 0; border: 0; border-top: 1px solid var(--vw-border); }
.vw-menu__head { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px 6px; }
.vw-menu__name { font-size: 13px; font-weight: 700; color: var(--vw-ink); }
.vw-menu__level { font-size: 12px; color: var(--vw-text-muted); }
.vw-menu .vw-menu__app {
  position: relative; flex-direction: column; align-items: flex-start; gap: 1px; padding-right: 30px;
}
.vw-menu__app-name { font-weight: 600; }
.vw-menu__app-desc { font-size: 12px; color: var(--vw-text-muted); }
/* 目前的系統打勾。 */
.vw-menu .vw-menu__app[aria-current="page"] { background: var(--vw-accent-subtle); }
.vw-menu .vw-menu__app[aria-current="page"]::after {
  content: "\2713"; position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  color: var(--vw-accent); font-weight: 700;
}

/* ---------- 版面：側欄＋內容區 ---------- */
.vw-shell { display: flex; align-items: flex-start; min-height: calc(100vh - 48px); }
.vw-main { flex: 1 1 auto; min-width: 0; }

/* ---------- 側欄（§8.4）：展開 232px、收合 56px；項目高 36px、圖示 18px、字 13px ---------- */
.vw-sidebar {
  position: sticky; top: 48px; flex: 0 0 232px; width: 232px; height: calc(100vh - 48px);
  display: flex; flex-direction: column; box-sizing: border-box;
  background: var(--vw-surface); border-right: 1px solid var(--vw-border);
  overflow: hidden; transition: width 150ms ease, flex-basis 150ms ease;
}
.vw-nav {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  display: flex; flex-direction: column; gap: 16px; padding: 12px 8px;
}
.vw-nav__title {
  padding: 0 12px 6px; font-size: 11px; font-weight: 600; letter-spacing: .04em;
  color: var(--vw-text-muted); white-space: nowrap;
}
.vw-nav__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.vw-nav__item {
  display: flex; align-items: center; gap: 10px; width: 100%; height: 36px; padding: 0 12px;
  box-sizing: border-box; border: 0; border-radius: var(--vw-radius-control); background: none;
  color: var(--vw-text-secondary); font: 500 13px var(--vw-font-sans);
  text-decoration: none; white-space: nowrap; cursor: pointer;
}
.vw-nav__item svg {
  width: 18px; height: 18px; flex: 0 0 18px;
  fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}
.vw-nav__item:hover { background: var(--vw-surface-subtle); color: var(--vw-ink); }
/* 目前項目：底色加左側 3px 識別色條。 */
.vw-nav__item.active {
  background: var(--vw-accent-subtle); color: var(--vw-ink);
  box-shadow: inset 3px 0 0 var(--vw-accent-on-chrome);
}
.vw-nav__label { overflow: hidden; text-overflow: ellipsis; }
.vw-collapse { flex: 0 0 auto; margin: 8px; width: auto; color: var(--vw-text-muted); }
/* 收合：只留圖示，分組標題收起來；狀態存在 localStorage 的 lrms-nav-collapsed。 */
.nav-collapsed .vw-sidebar { flex-basis: 56px; width: 56px; }
.nav-collapsed .vw-nav__label, .nav-collapsed .vw-nav__title { display: none; }
.nav-collapsed .vw-nav__item { justify-content: center; padding: 0; }
.nav-collapsed .vw-collapse svg { transform: scaleX(-1); }
@media (prefers-reduced-motion: reduce) { .vw-sidebar { transition: none; } }

/* 窄螢幕（小於 768px）：頂欄的系統頁籤收起來（系統切換選單裡都有），側欄改成抽屜。 */
.vw-backdrop {
  position: fixed; inset: 48px 0 0 0; z-index: 65;
  background: color-mix(in srgb, var(--lrms-ink) 40%, transparent);
}
.vw-backdrop[hidden] { display: none; }
@media (max-width: 767.98px) {
  .vw-topbar { gap: 8px; padding: 0 8px; }
  .vw-menu-btn { display: inline-flex; }
  .vw-apps, .vw-user__name, .vw-switcher__name { display: none; }
  .vw-sidebar {
    position: fixed; top: 48px; left: 0; bottom: 0; z-index: 70; height: auto;
    transform: translateX(-100%); transition: transform 150ms ease;
  }
  .drawer-open .vw-sidebar { transform: none; }
  .nav-collapsed .vw-sidebar { flex-basis: 232px; width: 232px; }
  .nav-collapsed .vw-nav__label { display: inline; }
  .nav-collapsed .vw-nav__title { display: block; }
  .nav-collapsed .vw-nav__item { justify-content: flex-start; padding: 0 12px; }
  .vw-collapse { display: none; }
}
@media (max-width: 767.98px) and (prefers-reduced-motion: reduce) { .vw-sidebar { transition: none; } }

/* ---------- 內容區 ---------- */
/* 頁首只留標題：拿掉綠色英文小標（§8.6），標題維持 20px 粗體。 */
/* 標題在左、頁面動作在右（page_actions block）；寬度跟下面的 .content 一樣，寬螢幕時按鈕不會飄到最右邊。 */
.page-hero {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 16px;
  max-width: 1100px; padding: 20px 24px 12px;
}
.page-hero__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.page-hero__actions:empty { display: none; }
.page-hero h1 { font-size: 20px; font-weight: 700; margin: 0; color: var(--vw-ink); }

.content { padding: 1.25rem 1.5rem; max-width: 1100px; }
.msg { font-size: 13px; line-height: 1.7; }
.msg--error { color: var(--vw-danger); }
.msg--warning { color: var(--vw-warning); }
.msg--ok { color: var(--vw-success); }

table { width: 100%; border-collapse: collapse; font-size: 13px; background: var(--vw-surface); border-radius: var(--vw-radius-card); overflow: hidden; }
th, td { padding: 9px 10px; text-align: left; border-bottom: 1px solid var(--vw-border); }
th { color: var(--vw-text-muted); font-weight: 500; background: var(--vw-surface-subtle); }
tr:hover td { background: var(--vw-bg); }

.btn { display: inline-block; background: var(--vw-primary-bg); color: var(--vw-primary-text); padding: 7px 16px;
       border-radius: var(--vw-radius-control); text-decoration: none; font-size: 13px; border: none; cursor: pointer; }
.btn:hover { background: var(--vw-primary-bg-hover); }
/* 次要按鈕：白底、深框、墨色字。 */
.btn-outline { background: var(--vw-surface); border: 1px solid var(--vw-border-strong); color: var(--vw-ink); }
.btn-outline:hover { background: var(--vw-surface-subtle); }

/* Saturated fills with dark text and a defining edge. The old versions
   were 12%-opacity tints that sat at 2.9-4.9:1 against their own text and
   had almost no edge, so on a page that is already green throughout the
   status was the hardest thing on the row to read. These run 6.1-6.9:1,
   and are told apart by hue rather than by lightness. 未採用 is slate on
   purpose — it is the one state that is not a status, so it must not read
   as another shade of the page. */
.badge { display: inline-block; white-space: nowrap; padding: 2px 9px;
         border-radius: var(--vw-radius-control); font-size: 12px; font-weight: 600;
         border: 1px solid transparent; }
.badge-green { background: var(--vw-success-bg); color: var(--vw-success); border-color: var(--vw-success); }
.badge-yellow { background: var(--vw-warning-bg); color: var(--vw-warning); border-color: var(--vw-warning); }
.badge-red { background: var(--vw-danger-bg); color: var(--vw-danger); border-color: var(--vw-danger); }
.badge-muted { background: var(--vw-surface-subtle); color: var(--vw-text-secondary); border-color: var(--vw-border-strong); }

form p { margin-bottom: 14px; }
form label { display: block; font-size: 13px; color: var(--vw-text-secondary); margin-bottom: 4px; }
form input:not([type="checkbox"]):not([type="radio"]), form select, form textarea {
  width: 100%; padding: 7px 10px; border: 1px solid var(--vw-border-strong); border-radius: var(--vw-radius-control);
  font-size: 13px; box-sizing: border-box; background: var(--vw-surface);
}
/* Filter bars sit on one row, so their controls must not inherit the
   width:100% written above for the stacked model forms — a bare <select>
   there was computing to the full width of the page and pushing every
   other control onto a line of its own. */
.filter-bar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 14px; }
.filter-bar input:not([type="checkbox"]):not([type="radio"]),
.filter-bar select { width: auto; }
.filter-bar input[type="text"] { min-width: 200px; flex: 1 1 200px; max-width: 320px; }
.filter-bar select { max-width: 220px; }
/* Pushes 新增 to the far end without needing an inline margin-left:auto. */
.filter-bar .filter-bar__end { margin-left: auto; }

form input[type="checkbox"], form input[type="radio"] {
  width: auto; padding: 0; border: none; margin-right: 6px; vertical-align: middle;
}
form .helptext { display: block; font-size: 13px; color: var(--vw-text-muted); margin-top: 3px; }

/* Validation feedback. Django re-renders the form on failure without
   marking the offending input, which on a long form leaves the user
   hunting; forms add .has-error so the field itself stands out. */
form input.has-error, form select.has-error, form textarea.has-error {
  border-color: var(--vw-danger);
  background: var(--vw-danger-bg);
}
form input.has-error:focus, form select.has-error:focus, form textarea.has-error:focus {
  outline: 2px solid color-mix(in srgb, var(--vw-danger) 35%, transparent); outline-offset: 1px;
}
form ul.errorlist {
  list-style: none; margin: 4px 0 0; padding: 0;
}
form ul.errorlist li {
  font-size: 12.5px; color: var(--vw-danger); line-height: 1.6;
}
.form-error-summary {
  background: var(--vw-danger-bg); border-radius: var(--vw-radius-card); padding: 12px 14px; margin-bottom: 16px;
}
.form-error-summary p { margin: 0 0 6px; font-size: 13px; color: var(--vw-danger); font-weight: 600; }
.form-error-summary ul { margin: 0; padding-left: 20px; }
.form-error-summary li { font-size: 12.5px; color: var(--vw-danger); line-height: 1.7; }
form label:has(input[type="checkbox"]), form label:has(input[type="radio"]) {
  display: inline-flex; align-items: center; font-weight: normal;
}
/* Dashboard quick-search results. The three search cards share one grid
   row, so a 4-column result table gets crushed at that width — the card
   spans the full row once it has results (see .search-card--wide), and
   columns stop wrapping so values like "FT-5115A" stay on one line. */
.search-results { overflow-x: auto; margin-top: 10px; }
.search-results table { margin-top: 0; }
.search-results th, .search-results td { white-space: nowrap; }
.search-results td.cell-long {
  white-space: nowrap; max-width: 340px; overflow: hidden;
  text-overflow: ellipsis;
}

.kpi-grid { display: grid; grid-template-columns: repeat(auto-fit,minmax(200px,1fr)); gap: 14px; margin-bottom: 20px; }
.kpi-card { background: var(--vw-surface); border-radius: var(--vw-radius-card); padding: 16px;
            border-top: 3px solid var(--vw-border-strong); box-shadow: var(--vw-shadow); }
.kpi-card p.label { font-size: 12px; color: var(--vw-text-muted); margin: 0 0 6px; }
.kpi-card p.value { font-size: 22px; font-weight: 600; margin: 0; }
.kpi-card a { text-decoration: none; color: inherit; }
/* 系統概況：有事要處理的格子換色，一眼看得出該點哪一格（2026-09-23）。 */
.kpi-card--alert { border-top-color: var(--vw-danger); }
.kpi-card--alert p.value { color: var(--vw-danger); }
.kpi-card--warn { border-top-color: var(--vw-warning); }
.kpi-card--warn p.value { color: var(--vw-warning); }
.kpi-card p.note { font-size: 11.5px; color: var(--vw-text-muted); margin: 6px 0 0; }

/* ---------- 可靠度應用工具 ---------- */
/* One grid for every tool, not a grid per category: with one tool in each
   of three categories, per-category grids left each card alone in a third
   of the page. The category rides on the card as a chip instead. */
.tool-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
  gap: 14px;
}
.tool-card {
  display: flex;
  flex-direction: column;
  background: var(--vw-surface);
  border: 1px solid var(--vw-border);
  border-radius: var(--vw-radius-card);
  padding: 16px 18px;
  text-decoration: none;
  color: inherit;
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.tool-card:hover {
  border-color: var(--vw-accent);
  box-shadow: 0 4px 14px color-mix(in srgb, var(--lrms-ink) 8%, transparent);
  transform: translateY(-1px);
}
.tool-card:focus-visible { outline: 2px solid var(--vw-accent); outline-offset: 2px; }
.tool-card.is-planned { opacity: .6; }
.tool-card.is-planned:hover {
  border-color: var(--vw-border); box-shadow: none; transform: none;
}
.tool-chip {
  align-self: flex-start;
  font-size: 11px;
  letter-spacing: .04em;
  padding: 2px 9px;
  border-radius: 999px;
  margin-bottom: 10px;
}
.tool-chip--convert { background: var(--vw-success-bg); color: var(--vw-success); }
.tool-chip--form    { background: var(--vw-warning-bg); color: var(--vw-warning); }
.tool-chip--calc    { background: var(--vw-info-bg); color: var(--vw-info); }
.tool-chip--lookup  { background: var(--vw-accent-subtle); color: var(--vw-accent); }
.tool-chip--chart   { background: var(--vw-info-bg); color: var(--vw-info); }
.tool-chip--other   { background: var(--vw-surface-subtle); color: var(--vw-text-muted); }
.tool-name { font-size: 15px; font-weight: 600; color: var(--vw-ink); margin: 0 0 6px; }
/* 工具版本號（2026-09-30 BOM 轉檔工具 v0.2 起）：卡片與工具頁標題旁。 */
.tool-version {
  margin-left: 8px; padding: 1px 8px; border-radius: 999px; vertical-align: middle;
  font-size: 11.5px; font-weight: 600; background: var(--vw-surface-subtle); color: var(--vw-text-muted);
}
.tool-desc {
  font-size: 12.5px; color: var(--vw-text-muted); line-height: 1.65;
  margin: 0 0 14px; flex: 1;
}
/* 輸入 → 輸出 on one line: the pair is the tool's contract, and reading it
   as a flow says more than two stacked labels. */
.tool-io {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
  border-top: 1px solid var(--vw-border); padding-top: 11px;
  font-size: 11.5px; color: var(--vw-text-secondary); line-height: 1.6;
}
.tool-io .arrow { color: var(--vw-accent); font-weight: 600; }
.tool-planned-note { font-size: 11.5px; color: var(--vw-warning); margin: 11px 0 0; }

@media (prefers-reduced-motion: reduce) {
  .tool-card { transition: none; }
  .tool-card:hover { transform: none; }
}

/* Result tables read as data, not prose: centring the columns lines the
   digits up the way the exported workbook does. Scoped to a class so the
   record tables elsewhere keep their left-aligned text. */
.table-centered th, .table-centered td { text-align: center; }

/* ---------- 檔案上傳欄位 ---------- */
.file-widget__current { margin: 0 0 7px; font-size: 13px; color: var(--vw-ink); word-break: break-all; }
/* inline-flex keeps the box and its words on one line whatever the width */
.file-widget__clear {
  display: inline-flex; align-items: center; gap: 7px;
  margin: 0 0 10px; padding: 4px 9px 4px 7px;
  border: 1px solid var(--vw-danger-border); border-radius: var(--vw-radius-control); background: var(--vw-danger-bg);
  font-size: 12.5px; color: var(--vw-danger); cursor: pointer;
}
.file-widget__clear input { margin: 0; cursor: pointer; }
.file-widget__change { margin: 0 0 5px; font-size: 13px; color: var(--vw-text-secondary); }

/* ---------- 測試排程表格 ---------- */
/* Ten columns of mostly short values plus one long name. Left to itself
   the browser hands the width to whatever is widest, so dates broke as
   "2026-10-" / "01" and every two-character header stacked vertically.
   Fixed layout with explicit widths gives the short columns exactly what
   they need and the sub-item name the rest. */
/* 這張表的容器（.table-scroll）在頁面最寬時也只有 1068px。固定欄加總要留 170px
   以上給沒設寬度的「子測試項目」，不然它一個字一個字往下折；min-width 不能超過
   容器，超過就整張往右溢出、最右邊的編輯／刪除被切掉（2026-09-16 兩次回報）。 */
.schedule-table { table-layout: fixed; min-width: 1012px; }
.equip-table { table-layout: fixed; min-width: 940px; }
.schedule-table th, .schedule-table td,
.equip-table th, .equip-table td { vertical-align: top; }
/* Short columns: never wrap, and line the digits up. Shared, because the
   equipment list broke exactly the same way — 設備編號 split as "EQ-" /
   "161600000603" and the overdue note as "（已逾" / "期）". */
.col-fit { white-space: nowrap; }
.col-num { white-space: nowrap; text-align: center; font-variant-numeric: tabular-nums; }
.col-date { font-variant-numeric: tabular-nums; }
/* 金額靠右。置中的話 8,000 跟 1,250,000 的個位數不在同一條線上，
   一欄數字要比大小就得一個一個讀。 */
.col-money { white-space: nowrap; text-align: right; font-variant-numeric: tabular-nums; }
/* 年度矩陣：欄位每年多一欄，總有一天要橫向捲。捲出去之後左邊那一欄如果跟著
   走，剩下的就只是一排數字，看不出是哪個科目——所以第一欄釘住。 */
/* 基礎的 table 規則掛著 overflow:hidden（為了圓角）。那會讓表格自己變成一個
   捲動容器，於是 sticky 是相對「表格」定位而不是相對外面的 .table-scroll——
   看起來就完全沒有釘住。這一欄要釘住就得放掉那個圓角。 */
.matrix { overflow: visible; }
.matrix th:first-child, .matrix td:first-child {
  position: sticky; left: 0; z-index: 1;
  /* 底色一定要填實。透明的話，捲過去的數字會直接印在這一欄的字上面。 */
  background: var(--vw-surface);
}
.matrix th:first-child { background: var(--vw-surface-subtle); }          /* 跟其他表頭同色 */
.matrix tr:hover td:first-child { background: var(--vw-bg); } /* 整列 hover 要連著 */
/* 「該年度合計」那一列自己有底色，釘住的第一格要跟上。 */
.matrix tr.matrix__total td:first-child { background: var(--vw-bg); }
.matrix tr.matrix__total:hover td:first-child { background: var(--vw-bg); }
/* 日期本身不斷行，但整格可以換行讓徽章落到第二行 */
.col-date > time, .equip-table .col-date { white-space: normal; }
/* The columns allowed to wrap do so between words. */
.col-wrap { overflow-wrap: break-word; }
/* Lab names are CJK either side of a bracketed abbreviation, and CJK has
   no spaces to break at — so the default split "可靠度" / "實驗室" cut the
   phrase in half. keep-all treats each CJK run as one word so the break
   lands on the real space; overflow-wrap still rescues a name that has no
   space at all, which would otherwise run past the column. */
.col-lab { word-break: keep-all; overflow-wrap: anywhere; }
/* 客戶名稱以前掛 col-fit（nowrap）。欄寬固定，nowrap 的字超出去不會被裁掉
   也不會換行，而是直接壓到隔壁的子測試項目上——「Lanner_P Series」正是這樣
   蓋住「5.1_Vibration Response」的（Michael 回報）。
   改成允許換行：有空白就在空白處斷，沒有空白的長名字才硬斷，寧可佔兩行也
   不要疊到別欄。欄寬同時放寬到放得下 Lanner_P Series 這種最長的名字，常見
   的名字仍然是一行。 */
.col-customer { overflow-wrap: break-word; word-break: keep-all; }
/* Below the table's own width, scroll it rather than squashing the
   columns back into the state above. */
.table-scroll { overflow-x: auto; }

/* Pass/Fail carries more than its text — shape and colour make the
   exceptions findable without reading every row. */
.result-pill {
  display: inline-block; padding: 1px 9px; border-radius: 999px;
  font-size: 12px; font-weight: 500; white-space: nowrap;
}
.result-pass { background: var(--vw-success-bg); color: var(--vw-success); }
.result-fail { background: var(--vw-danger-bg); color: var(--vw-danger); }
/* 結案表單（第三方實驗室，2026-10-10）：結案時一起確認測試結果，沒勾 Fail 的記 Pass。 */
.close-form { flex-basis: 100%; max-width: 720px; }
.close-form__hint { font-size: 13px; color: var(--vw-text-secondary); margin: 0 0 6px; }
.close-form__results { margin: 0 0 10px; }
.close-form__results label { cursor: pointer; }
/* 權限管理依部門分段（2026-10-10）。 */
.perm-section { margin: 22px 0 8px; }
.perm-section__count { font-size: 13px; font-weight: 400; color: var(--vw-text-secondary); }

/* ---------- 表單說明區塊 ---------- */
/* Was one dense paragraph of run-on clauses. The three guarantees about a
   typed-in name are a list, so they are set as one — they get scanned,
   not read. */
.form-note {
  background: var(--vw-surface-subtle); border-radius: var(--vw-radius-card); padding: 12px 14px;
  margin: 4px 0 16px; max-width: 620px;
  font-size: 12px; color: var(--vw-ink); line-height: 1.65;
}
.form-note__lead { margin: 0; }
.form-note__list { margin: 6px 0 8px; padding-left: 18px; }
.form-note__list li { margin: 1px 0; }
.form-note__p { margin: 0 0 6px; }
.form-note__p:last-child { margin-bottom: 0; }

/* ---------- 搜尋說明「?」 ---------- */
.search-title { display: flex; align-items: center; gap: 6px; }
.help-dot {
  width: 16px; height: 16px; flex: 0 0 16px; padding: 0;
  border: 1px solid var(--vw-border-strong); border-radius: 50%;
  background: var(--vw-surface); color: var(--vw-text-secondary);
  font-size: 11px; line-height: 1; font-weight: 700; cursor: pointer;
}
/* 放在 <h1> 裡的那顆。標題是 20px，16px 的圓點跟著基線走會偏低，而且
   緊貼著字；往上抬一點並留白，看起來才像標題的一部分而不是掉在後面。 */
.help-dot--title {
  margin-left: 9px; vertical-align: 4px;
  width: 18px; height: 18px; flex-basis: 18px; font-size: 12px;
}
/* 圓點跟前面的字之間要有距離，而且不要單獨被折到下一行——折下去看起來像掉
   在標題底下的一個誤點，不像那一行的一部分。 */
.help-dot { margin-left: 5px; vertical-align: 1px; }
.help-dot:hover, .help-dot:focus-visible {
  background: var(--vw-accent); border-color: var(--vw-accent); color: var(--vw-primary-text);
}
.help-dialog {
  /* border-box, or the 40px of padding lands outside the width and the
     box grows wider than the phone it is sitting on. */
  box-sizing: border-box;
  width: min(440px, calc(100dvw - 32px));
  max-height: calc(100dvh - 32px); overflow-y: auto;
  padding: 18px 20px; border: none; border-radius: var(--vw-radius-dialog);
  background: var(--vw-surface); color: var(--vw-ink);
  box-shadow: 0 18px 44px color-mix(in srgb, var(--lrms-ink) 22%, transparent);
}
.help-dialog::backdrop { background: color-mix(in srgb, var(--lrms-ink) 38%, transparent); }
/* 這一則說明有四段，440px 會拉得很長。 */
.help-dialog--wide { width: min(560px, calc(100dvw - 32px)); }
.help-foot-note {
  margin: 12px 0 0; padding-top: 10px; border-top: 1px solid var(--vw-border);
  font-size: 12px; color: var(--vw-text-muted);
}
.help-dialog__title { margin: 0 0 12px; font-size: 14px; }
.help-fields { margin: 0 0 12px; }
/* Label above value rather than beside it: the values are long enough
   that a side-by-side pair wrapped into a ragged second column. */
.help-row { margin-bottom: 8px; }
.help-row dt { font-size: 11px; color: var(--vw-text-muted); letter-spacing: .04em; }
.help-row dd { margin: 1px 0 0; font-size: 13px; }
.help-tips { margin: 0; padding-left: 18px; font-size: 12.5px;
             color: var(--vw-text-secondary); line-height: 1.75; }
.help-tips li { margin: 3px 0; }
/* 說明以段落呈現時用 gap 排版，不靠 <p> 各自的 margin——相鄰的上下 margin
   會摺疊，段距會比看起來的設定值小。 */
.help-body { display: flex; flex-direction: column; gap: 9px;
             font-size: 12.5px; color: var(--vw-text-secondary); line-height: 1.75; }
.help-body p { margin: 0; }
/* 一個對話框裡放兩節時的小標。用邊框而不是加大字級——說明框本來就窄，
   字級一拉開整段會被推得很長。 */
.help-section {
  margin: 4px 0 0; padding-bottom: 4px; border-bottom: 1px solid var(--vw-border);
  font-size: 12px; font-weight: 700; color: var(--vw-ink); letter-spacing: 0.5px;
}
.help-body .help-section:first-child { margin-top: 0; }
/* 操作步驟：說明「怎麼做」時列點比一整段好讀，但縮排要收窄，
   說明框本來就窄，預設的 40px 會把文字擠成一條。 */
.help-body .help-steps { margin: 0; padding-left: 18px; }
.help-body .help-steps li { margin: 0 0 3px; }
.help-body .help-steps li:last-child { margin-bottom: 0; }
.help-body code { background: var(--vw-surface-subtle); border-radius: 3px; padding: 0 3px;
                  font-size: 11.5px; }
.help-dialog__foot { margin: 14px 0 0; text-align: right; }

/* ---------- 規範查詢結果 ---------- */
/* Cards, not a table of editions. Whoever reads this box needs to know
   what a standard tests before the version numbers mean anything. */
.reg-cards { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.reg-card { border: 1px solid var(--vw-border); border-radius: var(--vw-radius-card); padding: 13px 15px; }
.reg-card__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.reg-card__id { font-size: 14px; font-weight: 700; color: var(--vw-ink);
                font-variant-numeric: tabular-nums; }
.reg-card__name { font-size: 12.5px; color: var(--vw-text-muted); }
/* Pushed to the far end so the eye lands on the id, not the link. */
.reg-card__more { margin-left: auto; font-size: 12px; white-space: nowrap; }
.reg-card__summary {
  margin: 8px 0 0; font-size: 13px; line-height: 1.85; color: var(--vw-ink);
  white-space: pre-line;   /* summaries are written with real line breaks */
}
.reg-card__summary--empty { color: var(--vw-text-muted); }
.reg-card__apply { margin: 9px 0 0; font-size: 12px; color: var(--vw-text-secondary); }
.reg-card__applylabel {
  display: inline-block; margin-right: 7px; padding: 1px 7px;
  border-radius: var(--vw-radius-control); background: var(--vw-surface-subtle); color: var(--vw-text-secondary);
  font-size: 11px; font-weight: 600;
}
.reg-cards__none { font-size: 13px; color: var(--vw-text-muted); margin: 12px 0 0; }
/* Esc closes a native <dialog> on its own, but a visible affordance means
   the way out never depends on that. */
.help-dialog__x { position: absolute; top: 8px; right: 10px; margin: 0; }
.help-dialog__x button {
  border: none; background: none; cursor: pointer;
  font-size: 20px; line-height: 1; color: var(--vw-text-muted); padding: 2px 4px;
}
.help-dialog__x button:hover, .help-dialog__x button:focus-visible { color: var(--vw-ink); }
/* No position on the dialog itself: the UA already positions a modal one
   and that makes it the containing block for the button above. Setting
   position:fixed here knocked it off centre. */
.help-dialog__title { padding-right: 24px; }

/* ---------- 校驗/保養紀錄表單 ---------- */
/* Fourteen fields in one flat list, with no indication of which answers
   changed what the others meant. Grouped into the questions someone
   actually asks while filling it in. */
.log-scope {
  background: var(--vw-surface-subtle); border-radius: var(--vw-radius-card); padding: 10px 13px;
  margin: 0 0 16px; max-width: 620px; font-size: 13px; color: var(--vw-ink);
}
.log-form { max-width: 620px; }
.log-section {
  border: 1px solid var(--vw-border); border-radius: var(--vw-radius-card);
  padding: 14px 16px 4px; margin: 0 0 14px;
}
.log-section__legend {
  padding: 0 6px; font-size: 13px; font-weight: 600; color: var(--vw-ink);
}
.log-section__hint { margin: 0 0 12px; font-size: 12px; color: var(--vw-text-muted); line-height: 1.6; }
.log-field { margin-bottom: 14px; }
.log-field label { display: block; font-size: 13px; color: var(--vw-text-secondary); margin-bottom: 4px; }
/* The checkbox and its words are one label, so they cannot wrap apart. */
.log-field--check label { display: inline-flex; align-items: center; gap: 7px; }
.log-req {
  margin-left: 4px; padding: 0 5px; border-radius: var(--vw-radius-control);
  background: var(--vw-warning-bg); color: var(--vw-warning); font-size: 11px; font-weight: 600;
}
.log-help { margin: 4px 0 0; font-size: 11.5px; color: var(--vw-text-muted); line-height: 1.6; }
.log-error { margin: 4px 0 0; font-size: 12px; color: var(--vw-danger); font-weight: 500; }
/* Radios read as a row of choices, not a stack of stray inputs.
   Django renders RadioSelect as a wrapper <div> of one <div> per option —
   not the <ul> this first targeted, which is why the rule did nothing and
   the options stayed stacked. The wrapper is the log-field's only child
   div, so select it that way rather than by an id that changes per field. */
.log-field--radio > div { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.log-field--radio > div > div { margin: 0; }
.log-field--radio label {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 0; color: var(--vw-ink); font-size: 13px;
}
.log-actions { display: flex; gap: 8px; margin-top: 4px; }
.form-errors {
  background: var(--vw-danger-bg); border: 1px solid var(--vw-danger); border-radius: var(--vw-radius-card);
  padding: 11px 14px; margin: 0 0 16px; max-width: 620px;
  font-size: 13px; color: var(--vw-danger);
}
.form-errors p { margin: 0 0 6px; }
.form-errors ul { margin: 0; padding-left: 18px; line-height: 1.7; }
/* Every page below a module list opens with a way back to it, so getting
   out never depends on the browser's own button. Shared, so the row sits
   at the same height on every page. */
.page-back { margin: 0 0 14px; display: flex; gap: 8px; flex-wrap: wrap; }
/* 同一列靠右的動作（設備部門頁的匯出／匯入 Excel，2026-10-01）。 */
.page-back__end { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }
/* 設備匯入頁（2026-10-01）。 */
.import-steps { font-size: 13px; color: var(--vw-text-secondary); line-height: 1.8; margin: 0 0 8px; padding-left: 20px; }
.import-summary { font-size: 14px; margin: 0 0 10px; }
.import-summary__error { color: var(--vw-danger); }
.import-apply { margin: 0 0 14px; }

/* ---------- 設備校驗紀錄（稽核查閱） ---------- */
.cal-intro { font-size: 13px; color: var(--vw-text-secondary); line-height: 1.8; margin: 0 0 16px; max-width: 760px; }
/* 說明分成數段時用 gap 排版，不靠 <p> 各自的 margin——相鄰的上下 margin
   會摺疊，段距會比看起來的設定值小。 */
div.cal-intro { display: flex; flex-direction: column; gap: 9px; }
div.cal-intro p { margin: 0; }
.cal-filter { margin: 16px 0 14px; display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.cal-filter input, .cal-filter select {
  padding: 7px 10px; border: 1px solid var(--vw-border-strong); border-radius: var(--vw-radius-control); font-size: 13px;
}
.cal-filter input { width: 220px; }
.cal-table { table-layout: fixed; min-width: 940px; }
.cal-table th, .cal-table td { vertical-align: top; }
/* An instrument with no certificate is the thing an auditor is looking
   for, so it is stated rather than left as a blank cell. */
.cal-missing { color: var(--vw-danger); font-weight: 500; }
.cal-more { font-size: 11px; color: var(--vw-text-muted); }
.cal-note { font-size: 12px; color: var(--vw-text-muted); line-height: 1.8; margin-top: 14px; }

/* ---------- 校驗歷程 ---------- */
.cal-machine { margin: 4px 0 2px; }
/* A due date worked out from the cycle is not what the certificate says.
   It is useful, but it is not audit evidence, so it never looks the same
   as a date that was copied off a certificate. */
.cal-derived {
  display: inline-block; padding: 1px 6px; border-radius: 999px;
  background: var(--vw-surface-subtle); color: var(--vw-text-muted); font-size: 10.5px; font-weight: 600;
}
/* The stretch between one certificate expiring and the next calibration
   is what an auditor works out for themselves. Better to have worked it
   out first. */
.cal-gaps {
  border: 1px solid var(--vw-danger-border); border-left: 3px solid var(--vw-danger); border-radius: var(--vw-radius-card);
  background: var(--vw-danger-bg); padding: 14px 16px; margin: 0 0 20px; max-width: 720px;
}
.cal-gaps__title { margin: 0 0 8px; font-size: 13.5px; font-weight: 600; color: var(--vw-danger); }
.cal-gaps ul { margin: 0; padding-left: 20px; }
.cal-gaps li { font-size: 13px; color: var(--vw-text-secondary); line-height: 1.9; }
.cal-gaps__note { margin: 9px 0 0; font-size: 12px; color: var(--vw-text-muted); line-height: 1.7; }

/* ---------- 分頁 ---------- */
.pager { display: flex; gap: 8px; align-items: center; margin-top: 14px; flex-wrap: wrap; }
.pager__count { font-size: 13px; color: var(--vw-text-muted); }

/* ---------- 開發中區塊 ---------- */
/* Says the feature is not built rather than showing an empty table that
   reads as broken or as lost data. */
.wip {
  border: 1px dashed var(--vw-border-strong); border-radius: var(--vw-radius-card);
  background: var(--vw-bg); padding: 16px 18px; margin: 0 0 22px; max-width: 720px;
}
.wip__tag {
  display: inline-block; margin: 0 0 8px; padding: 2px 9px; border-radius: 999px;
  background: var(--vw-warning-bg); color: var(--vw-warning); font-size: 11px; font-weight: 700;
}
.wip__title { margin: 0 0 8px; font-size: 15px; color: var(--vw-ink); }
.wip__body { margin: 0 0 6px; font-size: 13px; color: var(--vw-text-secondary); line-height: 1.8; }
.wip__body:last-child { margin-bottom: 0; }
.wip-links { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 22px; }
.wip-card {
  display: block; text-decoration: none; border: 1px solid var(--vw-border);
  border-radius: var(--vw-radius-card); padding: 13px 15px; background: var(--vw-surface); max-width: 360px;
  transition: border-color .13s ease;
}
.wip-card:hover { border-color: var(--vw-accent); }
.wip-card__title { display: block; font-size: 13.5px; font-weight: 600; color: var(--vw-ink); }
.wip-card__desc { display: block; margin-top: 4px; font-size: 12px; color: var(--vw-text-muted); line-height: 1.7; }
/* Capability under the name on the audit view — what the instrument can
   actually do is the question that follows "which instrument is this". */
.cal-capability { display: block; margin-top: 3px; font-size: 11.5px; color: var(--vw-text-muted); line-height: 1.6; }

/* ---------- 校驗到期提醒列 ---------- */
.due-strip { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 12px; }
.due-strip__label { font-size: 12px; color: var(--vw-text-muted); }
.due-chip {
  display: inline-block; padding: 3px 11px; border-radius: 999px;
  border: 1px solid var(--vw-border-strong); background: var(--vw-surface); color: var(--vw-text-secondary);
  font-size: 12.5px; text-decoration: none; white-space: nowrap;
}
.due-chip:hover { border-color: var(--vw-accent); color: var(--vw-ink); }
/* Only coloured when the count is non-zero — a red chip reading "0 台"
   would train people to ignore the colour. */
.due-chip--warn { background: var(--vw-warning-bg); border-color: var(--vw-warning); color: var(--vw-warning); font-weight: 600; }
.due-chip--alert { background: var(--vw-danger-bg); border-color: var(--vw-danger); color: var(--vw-danger); font-weight: 600; }
/* 校驗到期是排送校的第一個問題，所以做成一眼看得到的卡片，而不是一排
   小標籤。四張都是連結，點了就篩；目前篩到哪一張會標示出來。 */
/* 這排卡片是一組篩選器，要看起來像一條控制列。160px 的下限在 1100px 的
   版面裡一排只放得下六張，第七張（免保養）就自己掉到第二行，右邊留一大
   片空白，像是壞掉而不是排版。118px 讓七到八張都排得進同一行；auto-fit
   會把用不到的軌道收掉，所以七張時每張仍有 138px，不會變得又小又空。 */
.due-cards { grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); margin-bottom: 16px; }
.due-card {
  display: block; text-decoration: none; color: inherit;
  border-top-color: var(--vw-border-strong); transition: box-shadow .13s ease, border-color .13s ease;
}
.due-card:hover { box-shadow: 0 3px 12px color-mix(in srgb, var(--lrms-ink) 10%, transparent); }
.due-card .value { font-size: 26px; }
.due-card__unit { font-size: 13px; font-weight: 400; color: var(--vw-text-muted); }
/* 有東西要處理才上色——寫著「0 台」的紅卡片會讓人學會忽略顏色。 */
.due-card--warn { border-top-color: var(--vw-warning); background: var(--vw-warning-bg); }
.due-card--warn .value { color: var(--vw-warning); }
.due-card--alert { border-top-color: var(--vw-danger); background: var(--vw-danger-bg); }
.due-card--alert .value { color: var(--vw-danger); }
/* 目前正在看哪一批。 */
.due-card--on { outline: 2px solid var(--vw-accent); outline-offset: -2px; }
/* 設備管理先選部門（2026-09-30）：三個部門各一個顏色與圖示（使用者：「能不能多一點美感，三個白框框很難看」）。
   部門色在下面的 .dept--ra／--sit／--si。 */
.dept-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); gap: 18px; }
.dept-card {
  --dept: var(--vw-text-muted); --dept-bg: var(--vw-surface-subtle);
  position: relative; display: flex; flex-direction: column; gap: 24px; overflow: hidden;
  padding: 24px 22px 18px; border-radius: 14px; border: 1px solid var(--vw-border);
  background: linear-gradient(155deg, var(--dept-bg) 0%, var(--vw-surface) 60%);
  box-shadow: var(--vw-shadow); color: inherit; text-decoration: none;
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.dept-card::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 4px; background: var(--dept); }
.dept-card:hover {
  transform: translateY(-2px); border-color: var(--dept);
  box-shadow: 0 12px 26px color-mix(in srgb, var(--dept) 18%, transparent);
}
.dept-card:focus-visible { outline: 2px solid var(--dept); outline-offset: 2px; }
.dept-card__head { display: flex; align-items: center; gap: 14px; }
.dept-card__icon {
  flex: none; display: grid; place-items: center; width: 50px; height: 50px; border-radius: 13px;
  background: var(--vw-surface); color: var(--dept);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--dept) 28%, transparent);
}
.dept-card__icon svg { width: 26px; height: 26px; }
.dept-card__title { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.dept-card__code { font-size: 24px; font-weight: 700; line-height: 1.15; letter-spacing: .02em; color: var(--vw-ink); }
.dept-card__name { font-size: 13.5px; color: var(--vw-text-muted); }
.dept-card__go { font-size: 20px; color: var(--dept); transition: transform .15s ease; }
.dept-card:hover .dept-card__go { transform: translateX(4px); }
.dept-card__stats { display: grid; grid-template-columns: repeat(3, 1fr); padding-top: 14px; border-top: 1px solid var(--vw-border); }
.dept-stat { display: flex; flex-direction: column; gap: 2px; }
.dept-stat + .dept-stat { padding-left: 14px; border-left: 1px solid var(--vw-border); }
.dept-stat__num { font-size: 22px; font-weight: 700; line-height: 1.2; color: var(--vw-ink); font-variant-numeric: tabular-nums; }
.dept-stat__label { font-size: 12px; color: var(--vw-text-muted); }
.dept-stat--alert .dept-stat__num, .dept-stat--alert .dept-stat__label { color: var(--vw-danger); }
/* 部門頁的標題旁寫著現在在哪個部門。 */
.page-hero__dept {
  margin-left: 10px; padding: 3px 10px; border-radius: 999px; vertical-align: middle;
  font-size: 14px; font-weight: 600; background: var(--dept-bg); color: var(--dept);
}
/* 部門色：部門按鈕與部門頁標題旁的標籤用同一組（使用者 2026-09-30：「SIT 應該是顯示藍色」「SI 訊號量測部
   顯示綠色，保持一致性」「RA 不要這個顏色，改黃色」）。黃用 --vw-warning 那一組——設計系統裡的黃就是它
   （.badge-yellow 也是）；style.css 只准三個識別色寫色碼（core/tests_workspace_frame.py）。 */
.dept--ra { --dept: var(--vw-warning); --dept-bg: var(--vw-warning-bg); }
.dept--sit { --dept: var(--vw-info); --dept-bg: var(--vw-info-bg); }
.dept--si { --dept: var(--vw-success); --dept-bg: var(--vw-success-bg); }
/* 放在日期下一行，不放旁邊：「2026-08-13 逾期 79 天」要 164px，而這一欄
   只有 100px，並排就會溢位到隔壁的保養到期欄，兩欄的字疊在一起。 */
.due-flag {
  display: inline-block; margin-top: 3px; padding: 1px 7px; border-radius: var(--vw-radius-control);
  font-size: 11px; font-weight: 700; white-space: nowrap;
}
.due-flag--warn { background: var(--vw-warning-bg); color: var(--vw-warning); }
.due-flag--alert { background: var(--vw-danger-bg); color: var(--vw-danger); }
/* 還早的倒數。用灰的不是綠的——綠色在這個站上代表「好了」，而「剩 40 天」
   只是還沒到，不是已經完成。 */
.due-flag--calm { background: var(--vw-surface-subtle); color: var(--vw-text-secondary); font-weight: 600; }
/* Delete sits inline beside 編輯 and looks like the link it behaves as. */
.log-del { display: inline; margin-left: 6px; }
.log-del button {
  background: none; border: none; padding: 0; cursor: pointer;
  color: var(--vw-danger); font-size: 13px; text-decoration: underline;
}

/* ---------- 刪除確認 ---------- */
.confirm {
  box-sizing: border-box; width: min(440px, calc(100dvw - 32px));
  padding: 20px 22px; border: none; border-radius: var(--vw-radius-dialog);
  background: var(--vw-surface); color: var(--vw-ink);
  box-shadow: 0 18px 44px color-mix(in srgb, var(--lrms-ink) 24%, transparent);
}
.confirm::backdrop { background: color-mix(in srgb, var(--lrms-ink) 42%, transparent); }
.confirm__tag {
  display: inline-block; margin: 0 0 10px; padding: 2px 9px; border-radius: 999px;
  background: var(--vw-danger-bg); color: var(--vw-danger); font-size: 11px; font-weight: 700;
}
.confirm__title { margin: 0 0 10px; font-size: 15px; line-height: 1.6; }
.confirm__what {
  margin: 0 0 10px; padding: 9px 12px; border-radius: var(--vw-radius-card); background: var(--vw-surface-subtle);
  font-size: 13px; line-height: 1.7; white-space: pre-line; word-break: break-word;
}
.confirm__warn { margin: 0 0 10px; font-size: 13px; line-height: 1.7; color: var(--vw-warning); }
/* 打字確認。反射性地按「確定」是刪錯東西最常見的一條路——要求把名字抄一次，
   手就會停下來，眼睛也會真的去看刪的是哪一筆。 */
.confirm__type { display: block; margin: 0 0 12px; }
.confirm__type span {
  display: block; margin-bottom: 5px; font-size: 12px; color: var(--vw-text-muted); line-height: 1.6;
}
.confirm__type code {
  padding: 1px 5px; border-radius: var(--vw-radius-control); background: var(--vw-surface-subtle);
  font-size: 12.5px; color: var(--vw-ink); user-select: all;
}
.confirm__type input {
  box-sizing: border-box; width: 100%; padding: 7px 10px;
  border: 1px solid var(--vw-border-strong); border-radius: var(--vw-radius-control); font-size: 13px; font-family: inherit;
}
.confirm__type input:focus { outline: 2px solid var(--vw-accent); outline-offset: -1px; }
.confirm__final { margin: 0; font-size: 13px; font-weight: 600; color: var(--vw-danger); }
.confirm .btn[disabled] { opacity: .45; cursor: not-allowed; }
.confirm__actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }
.btn-danger { background: var(--vw-danger-solid); color: var(--vw-primary-text); }
.btn-danger:hover { background: color-mix(in srgb, var(--vw-danger-solid) 85%, black); }
/* 日期本身不折 */
.due-date { display: inline-block; white-space: nowrap; }

/* ---------- 設備稼動率 ---------- */
.util-table { table-layout: fixed; min-width: 820px; }
.util-table th, .util-table td { vertical-align: middle; }
.util-bar {
  display: inline-block; width: 90px; height: 8px; border-radius: 999px;
  background: var(--vw-border); overflow: hidden; vertical-align: middle; margin-right: 8px;
}
.util-bar__fill { display: block; height: 100%; background: var(--vw-info); }
/* 稼動率超過 100%（分子含假日運轉、分母只有工作日）。長條本來就被
   overflow:hidden 裁在滿格，換色才分得出 100% 與 130%。 */
.util-bar__fill--over { background: var(--vw-warning); }
.util-rate--over { color: var(--vw-warning); }
.util-rate { font-variant-numeric: tabular-nums; font-weight: 600; font-size: 13px; }
/* 把「實際搜了哪些詞」講出來。使用者反映搜不到東西時，第一個疑問是「它到
   底有沒有拿我打的字去找」——列出展開後的詞就直接回答了這件事，也讓人知道
   下次可以怎麼打。 */
.reg-expand { margin: 0 0 10px; font-size: 12px; color: var(--vw-text-muted); }
.reg-expand__term {
  display: inline-block; margin: 0 4px 4px 0; padding: 2px 8px;
  border: 1px solid var(--vw-border-strong); border-radius: 999px;
  background: var(--vw-bg); color: var(--vw-text-secondary); text-decoration: none;
}
a.reg-expand__term:hover { background: var(--vw-accent); border-color: var(--vw-accent); color: var(--vw-primary-text); }

/* ---------- 工具頁的表單 ---------- */
.tool-form {
  background: var(--vw-surface); border: 1px solid var(--vw-border-strong); border-radius: var(--vw-radius-card);
  padding: 18px 20px; margin: 0 0 18px; max-width: 860px;
  display: flex; flex-direction: column; gap: 16px;
}
.tool-row { display: flex; gap: 20px; flex-wrap: wrap; }
.tool-row > .tool-field { flex: 1 1 300px; }
.tool-field { display: flex; flex-direction: column; gap: 6px; }
.tool-field > label { font-size: 13px; font-weight: 600; color: var(--vw-ink); }
.tool-field input[type="text"], .tool-field select, .tool-field input[type="file"] {
  padding: 7px 10px; border: 1px solid var(--vw-border-strong); border-radius: var(--vw-radius-control);
  font-size: 13px; background: var(--vw-surface); color: var(--vw-ink);
}
.tool-hint { margin: 0; font-size: 12px; color: var(--vw-text-muted); line-height: 1.7; }
.tool-checks { display: flex; gap: 8px 18px; flex-wrap: wrap; }
/* 勾選框跟它的文字要一起可點，而且不要被 flex 拉開 */
.tool-check {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--vw-ink); cursor: pointer;
}
.tool-actions { display: flex; gap: 10px; }

/* ---------- 曲線圖結果 ---------- */
.chart-result { margin: 0 0 18px; }
.chart-result__bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin: 0 0 8px;
}
.chart-result__files { font-size: 12px; color: var(--vw-text-muted); }
.chart-result__files code { margin-right: 6px; }
/* 兩顆下載按鈕是一組。不包起來的話，space-between 會把它們拆到左右兩端 */
.chart-result__actions { display: flex; gap: 8px; margin-left: auto; }
/* 四個面板疊起來很高，寬度給滿；窄螢幕橫向捲動而不是把線壓成一團 */
.chart-box--wide { padding: 8px; }
.chart-box--wide svg { min-width: 900px; }
.chart-notes {
  margin: 10px 0 0; padding-left: 18px; max-width: 900px;
  font-size: 12px; color: var(--vw-text-muted); line-height: 1.8;
}
.chart-notes--plain { list-style: none; padding-left: 0; }
.chart-notes code { margin-right: 6px; }

/* 機台勾選收在 details 裡：八台展開就是一整排，平常不需要佔著版面，但只要
   有機台被取消勾選就自動展開，免得使用者忘了自己篩過還以為圖是全部。 */
.pick-machines { font-size: 13px; position: relative; }
.pick-machines > summary {
  cursor: pointer; list-style: none; padding: 7px 12px;
  border: 1px solid var(--vw-border-strong); border-radius: var(--vw-radius-control); background: var(--vw-surface);
  color: var(--vw-ink); user-select: none; white-space: nowrap;
}
.pick-machines > summary::-webkit-details-marker { display: none; }
.pick-machines > summary::after { content: ' \25BE'; color: var(--vw-text-muted); }
.pick-machines[open] > summary::after { content: ' \25B4'; }
.pick-machines > summary:hover { border-color: var(--vw-accent); }
.pick-machines__count {
  display: inline-block; margin-left: 6px; padding: 0 7px;
  border-radius: 999px; background: var(--vw-success-bg); color: var(--vw-success);
  font-size: 11.5px; font-variant-numeric: tabular-nums;
}
/* 絕對定位，展開時不要把查詢列往下推 */
.pick-machines__body {
  position: absolute; z-index: 20; top: 100%; left: 0; margin-top: 6px;
  padding: 12px 14px; min-width: 300px; max-width: 460px;
  background: var(--vw-surface); border: 1px solid var(--vw-border-strong); border-radius: var(--vw-radius-card);
  box-shadow: 0 6px 18px color-mix(in srgb, var(--lrms-ink) 12%, transparent);
}
.pick-machines__hint { margin: 0 0 9px; font-size: 12px; color: var(--vw-text-muted); line-height: 1.7; }
.pick-machines__list { display: flex; flex-direction: column; gap: 6px; }
.pick-machines__item {
  display: flex; align-items: center; gap: 7px; cursor: pointer; color: var(--vw-ink);
}
.pick-machines__item span {
  color: var(--vw-text-muted); font-size: 12px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chart-filtered { margin: -8px 0 16px; font-size: 12px; color: var(--vw-text-muted); }

/* ---------- 稼動率圖表 ---------- */
.chart-box {
  background: var(--vw-surface); border: 1px solid var(--vw-border-strong); border-radius: var(--vw-radius-card);
  padding: 10px 12px; margin: 0 0 16px; overflow-x: auto;
}
/* SVG 自己有 viewBox，寬度交給容器；min-width 讓窄螢幕橫向捲動而不是把
   八個通道的標籤擠成一團。 */
.util-chart { display: block; width: 100%; min-width: 620px; height: auto; }
.util-channel { font-variant-numeric: tabular-nums; }
.util-power {
  display: inline-block; margin-left: 6px; padding: 1px 6px;
  white-space: nowrap;
  border: 1px solid var(--vw-border-strong); border-radius: 999px;
  font-size: 11.5px; color: var(--vw-text-secondary); background: var(--vw-bg);
}
/* 假日運轉不算進稼動率，是旁證不是主角——顏色壓下來，免得跟稼動率搶眼。 */
.util-holiday { color: var(--vw-text-muted); font-variant-numeric: tabular-nums; }
.util-table th { line-height: 1.35; }
/* A channel with no equipment record is a finding, not noise to hide. */
.util-unmapped { color: var(--vw-danger); font-size: 12.5px; }
.util-partial {
  background: var(--vw-warning-bg); border: 1px solid var(--vw-warning); border-radius: var(--vw-radius-card);
  padding: 11px 14px; margin: 0 0 16px; max-width: 760px;
  font-size: 13px; line-height: 1.8; color: var(--vw-warning);
}
.util-imported {
  background: var(--vw-success-bg); border: 1px solid var(--vw-success); border-radius: var(--vw-radius-card);
  padding: 10px 13px; margin: 0 0 14px; max-width: 760px;
  font-size: 13px; line-height: 1.7; color: var(--vw-success);
}
/* 狀態標籤永遠一行——折成兩行的「無校驗／紀錄」比沒有標籤還難讀。 */
.col-state .badge { white-space: nowrap; }

/* ---------- ISO 17025 條文與文件對應 ---------- */
/* 一條條文一列。章節列只是標題，用表頭的底色但字體加粗，跟資料列分開；
   狀態用左側細邊示意，掃一眼就看得到哪幾列是缺口，不用逐列讀徽章。 */
.clause-table { table-layout: fixed; min-width: 900px; }
.clause-table th, .clause-table td { vertical-align: top; }
.clause-chapter td { background: var(--vw-surface-subtle); font-weight: 700; color: var(--vw-ink); font-size: 13.5px; }
.clause-row--gap td:first-child { box-shadow: inset 3px 0 0 var(--vw-danger); }
.clause-row--partial td:first-child { box-shadow: inset 3px 0 0 var(--vw-warning); }
.clause-row--na td { color: var(--vw-text-muted); }
.clause-en { display: block; font-size: 11px; color: var(--vw-text-muted); margin-top: 1px; }
.clause-req { margin: 5px 0 0; font-size: 12px; color: var(--vw-text-muted); line-height: 1.65; }
.clause-muted { color: var(--vw-text-muted); }
/* 文件籤：規範是實心綠、表單是淡灰、參考是虛線框——三種角色一眼分得開。 */
.doc-chip {
  display: inline-block; margin: 2px 6px 2px 0; padding: 3px 9px; border-radius: var(--vw-radius-control);
  background: var(--vw-surface-subtle); color: var(--vw-ink); font-size: 12.5px; line-height: 1.5;
  text-decoration: none; border: 1px solid var(--vw-border); max-width: 100%;
}
.doc-chip:hover { border-color: var(--vw-accent); background: var(--vw-accent-subtle); }
.doc-chip--form { background: var(--vw-bg); color: var(--vw-text-secondary); border-color: var(--vw-border); font-size: 12px; }
.doc-chip--ref { background: transparent; border-style: dashed; color: var(--vw-text-muted); font-size: 12px; }
.doc-chip__ver { margin-left: 5px; font-size: 11px; color: var(--vw-text-muted); }
.doc-chip__name { color: var(--vw-text-muted); }
.doc-note { display: block; margin: -1px 0 5px; font-size: 11.5px; color: var(--vw-text-muted); }
.clause-chip {
  display: inline-block; margin: 1px 4px 1px 0; padding: 1px 7px; border-radius: var(--vw-radius-control);
  background: var(--vw-surface-subtle); color: var(--vw-ink); font-size: 11.5px; font-weight: 600;
}
.doc-form-row td { background: var(--vw-bg); font-size: 12.5px; }
.doc-form-row td:first-child { padding-left: 24px; white-space: nowrap; }
.doc-path { background: var(--vw-surface); border-radius: var(--vw-radius-card); padding: 10px 14px; font-size: 13px; color: var(--vw-text-secondary); }
.doc-path__row { margin: 4px 0; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.doc-path__label { flex: 0 0 84px; font-size: 12px; color: var(--vw-text-muted); }
/* 外連到 DCC 的小籤：跟內部的文件籤長得不一樣（有箭頭、灰底），一眼知道會離開系統。 */
.dcc-link {
  display: inline-block; margin-left: 4px; padding: 0 6px; border-radius: var(--vw-radius-control);
  font-size: 10.5px; font-weight: 700; color: var(--vw-text-secondary); background: var(--vw-surface-subtle);
  text-decoration: none; vertical-align: 1px; white-space: nowrap;
}
.dcc-link:hover { background: var(--vw-accent-subtle); color: var(--vw-ink); }
.doc-path__unc {
  font-size: 12px; background: var(--vw-surface-subtle); padding: 3px 8px; border-radius: var(--vw-radius-control);
  color: var(--vw-ink); word-break: break-all; user-select: all;
}
.doc-copy { padding: 4px 10px; font-size: 12px; }

/* ---------------------------------------------------------- 我的簽名檔 */
/* 左右兩欄：左邊「現在會蓋出什麼」，右邊改它。原本上下堆疊，右半邊整片空
   著，而最重要的那件事——實際蓋上去長什麼樣——根本看不到。 */
.sig-grid {
  display: grid; gap: 16px; align-items: start;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}
@media (max-width: 900px) { .sig-grid { grid-template-columns: 1fr; } }
.sig-card {
  background: var(--vw-surface); border: 1px solid var(--vw-border-strong); border-radius: var(--vw-radius-card);
  padding: 18px 20px;
}
.sig-card__title {
  margin: 0 0 14px; font-size: 15px; color: var(--vw-ink);
}
/* 預覽底下墊一條線，看起來就是「簽在線上」——跟實際蓋進 PDF 的樣子一致 */
.sig-preview {
  min-height: 96px; display: flex; align-items: flex-end; justify-content: center;
  padding: 10px 16px 8px; border-bottom: 1px solid var(--vw-border-strong); margin-bottom: 14px;
}
.sig-preview img { max-height: 76px; max-width: 100%; }
.sig-preview--empty {
  flex-direction: column; align-items: center; justify-content: center;
  border-bottom: 1px dashed var(--vw-border-strong); color: var(--vw-text-muted); text-align: center;
}
.sig-preview--empty p { margin: 0; font-size: 13px; }
.sig-preview--empty .sig-hint { margin-top: 6px; font-size: 12px; }
.sig-facts { margin: 0 0 16px; font-size: 13px; }
.sig-facts > div { display: flex; gap: 10px; padding: 4px 0; }
.sig-facts dt { flex: 0 0 76px; color: var(--vw-text-muted); }
.sig-facts dd { margin: 0; color: var(--vw-ink); }
.sig-actions { display: flex; gap: 8px; }
.sig-actions form { display: inline; }
/* 兩個欄位之間要有喘息。擠在一起時，上一欄的說明看起來像下一欄的標題。 */
.sig-card .tool-field { margin-bottom: 18px; }

/* ---------- 測試報告 V3（report_gen_v3）---------- */
/* 回填畫面的共同骨架（設計 §4a.2）：頁首列、地點、測試紀錄、本頁帶入、結果、照片、附件、頁尾。 */
.v3-tabs { display: flex; gap: 8px; margin-bottom: 14px; }
.v3-form { max-width: 980px; }
.v3-section { border: 1px solid var(--vw-border); border-radius: var(--vw-radius-card); background: var(--vw-surface); padding: 12px 16px; margin: 0 0 14px; }
.v3-section legend, .v3-section > summary { font-weight: 600; color: var(--vw-ink); padding: 0 4px; cursor: default; }
.v3-section > summary { cursor: pointer; }
.v3-section h3 { margin: 0 0 10px; font-size: 15px; }
.v3-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px 16px; }
/* hidden 屬性要贏過上面的 display: grid（不然選「本廠」時第三方欄位還在）。 */
.v3-grid[hidden] { display: none; }
.v3-field { margin: 8px 0; }
.v3-field label, .v3-label { display: block; font-size: 12.5px; color: var(--vw-text-secondary); margin-bottom: 4px; }
.v3-field input[type=text], .v3-field input[type=datetime-local], .v3-field select, .v3-field textarea {
  width: 100%; box-sizing: border-box; padding: 6px 8px; border: 1px solid var(--vw-border-strong); border-radius: var(--vw-radius-control); font-size: 13.5px; }
.v3-field--missing input { border-color: var(--vw-warning); background: var(--vw-warning-bg); }
.v3-inline { display: flex; gap: 6px; align-items: center; }
.v3-inline input[type=text] { flex: 1 1 auto; }
.v3-check { display: inline-flex; gap: 6px; align-items: center; margin: 4px 14px 4px 0; font-size: 13.5px; }
.v3-hint { font-size: 12px; color: var(--vw-text-muted); margin: 4px 0; }
.v3-muted { color: var(--vw-text-muted); }
.v3-error { font-size: 12.5px; color: var(--vw-danger); margin: 4px 0; }
.v3-overdue { color: var(--vw-danger); font-weight: 600; }
.v3-yellow { background: var(--vw-warning-bg); border-left: 4px solid var(--vw-warning); padding: 8px 12px; border-radius: var(--vw-radius-control); font-size: 13px; }
.v3-banner { background: var(--vw-surface-subtle); border-radius: var(--vw-radius-card); padding: 12px 16px; margin: 0 0 14px; }
.v3-banner--error { background: var(--vw-danger-bg); }
.v3-pre { white-space: pre-wrap; font-size: 12px; max-height: 220px; overflow: auto; }
.v3-stagebar, .v3-pagebar { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; margin-bottom: 14px; }
.v3-pagebar__facts { font-size: 13px; color: var(--vw-text-secondary); }
/* 階段清單的批次：勾選的頁一起〔照預設填〕或指派；章節列可以整章勾選。 */
.v3-batchbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 10px; font-size: 13px; }
.v3-batchbar select { padding: 5px 8px; border: 1px solid var(--vw-border-strong); border-radius: var(--vw-radius-control); font-size: 13px; }
.v3-chapter-row td { background: var(--vw-surface-subtle); font-weight: 600; color: var(--vw-ink); font-size: 12.5px; }
/* 數據表（W6）：輸入格、母版固定字（灰）、系統算的（綠）；貼上或存檔有問題的格標紅。 */
.v3-table { margin: 0 0 14px; }
.v3-grid-table { border-collapse: collapse; font-size: 12.5px; }
.v3-grid-table th, .v3-grid-table td { border: 1px solid var(--vw-border); padding: 3px 5px; vertical-align: middle; text-align: left; }
.v3-grid-table thead th { background: var(--vw-surface-subtle); font-weight: 600; }
.v3-grid-table__label { white-space: nowrap; font-weight: 500; }
.v3-grid-table input { width: 6.5em; padding: 3px 5px; border: 1px solid var(--vw-border-strong); border-radius: var(--vw-radius-control); font-size: 12.5px; }
.v3-cell--fixed { color: var(--vw-text-muted); }
.v3-cell--derived { color: var(--vw-success); font-weight: 500; }
.v3-cell--flag { background: var(--vw-danger-bg); }
.v3-cell--flag input { border-color: var(--vw-danger); }
.v3-paste textarea { width: 100%; box-sizing: border-box; font-family: var(--vw-font-mono); font-size: 12px; }
/* 框選：報告頁面圖上拖一個範圍（向量頁抽不到照片時的備援）。 */
.v3-crop { margin: 8px 0; }
.v3-crop__stage { position: relative; display: inline-block; max-width: 100%; margin: 8px 0; cursor: crosshair; }
.v3-crop__stage img { display: block; max-width: 100%; border: 1px solid var(--vw-border); user-select: none; }
.v3-crop__box { position: absolute; border: 2px solid var(--vw-accent); background: color-mix(in srgb, var(--vw-accent) 12%, transparent); pointer-events: none; }
/* 範圍頁：每一頁一列，右邊是地點預設。 */
.v3-scope-row { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: center; justify-content: space-between; }
.v3-scope-row select { padding: 3px 6px; border: 1px solid var(--vw-border-strong); border-radius: var(--vw-radius-control); font-size: 12.5px; }
.v3-pagebar__nav { margin-left: auto; display: flex; gap: 12px; }
.v3-conflict { background: var(--vw-danger-bg); border-radius: var(--vw-radius-card); padding: 10px 14px; margin: 0 0 14px; }
.v3-conflict__title { font-weight: 600; color: var(--vw-danger); margin: 0 0 8px; }
/* 〔帶入 BOM〕：每一行 BOM 放進 Test Config. 的哪一列，系統先選好、人可以改。 */
.v3-bom table { width: 100%; border-collapse: collapse; font-size: 13px; margin: 8px 0; background: var(--vw-surface); }
.v3-bom th, .v3-bom td { border-bottom: 1px solid var(--vw-border); padding: 5px 6px; text-align: left; vertical-align: top; }
.v3-bom select { min-width: 140px; }
.v3-carried table td { font-size: 12.5px; }
/* R2 頁照列分組：標題是那一列的條件（Voltage 90 V｜Frequency 63 Hz｜Temperature -5 ℃）。 */
.v3-group { margin: 16px 0 2px; padding-top: 10px; border-top: 1px solid var(--vw-border); font-size: 13.5px; color: var(--vw-ink); }
.v3-group:first-of-type { border-top: 0; padding-top: 0; }
.v3-group-end { border: 0; border-top: 1px solid var(--vw-border); margin: 16px 0 8px; }
/* 判定用大按鈕（Pass／Fail／Block），選到的那一顆填色；鍵盤 p／f／b 也能選。 */
.v3-verdicts { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.v3-verdict input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.v3-verdict span { display: inline-block; min-width: 64px; text-align: center; padding: 7px 14px; border-radius: var(--vw-radius-card);
  border: 1px solid var(--vw-border-strong); background: var(--vw-surface); font-weight: 600; cursor: pointer; }
.v3-verdict input:focus-visible + span { outline: 2px solid var(--vw-accent); outline-offset: 2px; }
.v3-verdict--pass input:checked + span { background: var(--vw-success); border-color: var(--vw-success); color: var(--vw-primary-text); }
.v3-verdict--fail input:checked + span { background: var(--vw-danger-solid); border-color: var(--vw-danger-solid); color: var(--vw-primary-text); }
.v3-verdict--block input:checked + span { background: var(--vw-warning); border-color: var(--vw-warning); color: var(--vw-primary-text); }
.v3-verdict--clear span { font-weight: 400; color: var(--vw-text-muted); min-width: 0; }
.v3-verdict--clear input:checked + span { background: var(--vw-surface-subtle); }
.v3-block { background: var(--vw-warning-bg); color: var(--vw-warning); }
/* 照片框：框內直接看到縮圖，放錯用〔換位置〕。 */
.v3-drop { border: 2px dashed var(--vw-border-strong); border-radius: var(--vw-radius-card); padding: 12px 16px; margin-bottom: 12px; background: var(--vw-bg); }
.v3-drop--over { background: var(--vw-accent-subtle); border-color: var(--vw-accent); }
.v3-frames { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; }
.v3-frame { border: 1px solid var(--vw-border); border-radius: var(--vw-radius-card); padding: 8px; background: var(--vw-surface); }
.v3-frame--empty { border-style: dashed; border-color: var(--vw-warning); }
.v3-frame__label { font-size: 13px; font-weight: 600; margin: 0 0 6px; }
.v3-frame img { width: 100%; height: 150px; object-fit: contain; background: var(--vw-bg); border-radius: var(--vw-radius-control); }
/* 框裡的縮圖照框的比例顯示，跟報告一樣：照片置中裁切填滿（cover），截圖補白（contain）。--ratio 由頁面帶入。 */
.v3-frame img.v3-frame__img { height: auto; aspect-ratio: var(--ratio); }
.v3-frame img.v3-frame__img--photo { object-fit: cover; }
/* 建專案從 V1 帶入的範圍預覽：和 VTMS 預設不同的列 */
.v3-row--changed td { background: var(--vw-warning-bg); }
.v3-frame__actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.v3-frame__actions form { display: inline-flex; gap: 4px; }
.v3-frame__actions select, .v3-frame__actions input[type=text] { font-size: 12px; padding: 3px 6px; max-width: 150px; }
.v3-na { color: var(--vw-warning); font-size: 13px; }
.v3-uploads { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.v3-footer { background: var(--vw-surface); border-top: 2px solid var(--vw-border); padding: 10px 16px; margin-top: 14px; }
/* 螢幕夠高才把頁尾（還缺、儲存）固定在底部；筆電小視窗、手機上固定的頁尾會蓋掉照片。 */
@media (min-height: 820px) { .v3-footer { position: sticky; bottom: 0; } }
.v3-footer__buttons { display: flex; gap: 8px; flex-wrap: wrap; }
.v3-missing { color: var(--vw-warning); font-size: 13px; }
.v3-missing a { color: var(--vw-warning); }
.v3-done { color: var(--vw-success); font-size: 13px; }

/* ---------- 權限管理（sso/templates/sso/permissions.html）---------- */
/* 群組表頭可以換行、欄窄而置中：九個群組名稱不換行的話，整張表比內容區還寬，
   最後登入與〔儲存〕被推到畫面外（2026-09-30 使用者回報）。 */
.perm-table th.perm-col {
  min-width: 36px; white-space: nowrap; text-align: center;
  font-size: 11.5px; line-height: 1.35; vertical-align: bottom;
}
/* 名稱固定斷在「管理員」「瀏覽者」前面，每一行本身不再斷。 */
.perm-table .perm-col__line { display: block; }
.perm-table td.perm-col { text-align: center; }
/* 勾選欄左右留白收窄：設備管理員分成三組（2026-09-30）之後多了兩欄，〔儲存〕又被推到畫面外。 */
.perm-table th.perm-col, .perm-table td.perm-col { padding-left: 3px; padding-right: 3px; }
.perm-table td.perm-col input { margin: 0; }
/* 部門選單與最後登入收窄（2026-10-10）：多了部門一欄之後〔儲存〕又被推到畫面外。 */
.perm-table .perm-dept { font-size: 12px; padding: 2px 4px; width: 64px; }
.perm-table td.perm-login { font-size: 12px; line-height: 1.35; color: var(--vw-text-secondary); }
.perm-table .perm-save { padding: 4px 10px; font-size: 12px; }
/* 依部門分段之後每段是一張表：帳號、部門兩欄固定寬，各段的勾選欄才會上下對齊。 */
.perm-table th:first-child { width: 160px; }
.perm-table th:nth-child(2) { width: 72px; }

/* ---------- 設備照片（2026-09-30，SI 設備整合）---------- */
/* 照片放在欄位表右邊；窄螢幕排到下面。點了開原圖。 */
.eq-overview--photo { display: grid; grid-template-columns: minmax(0, 1fr) 240px; gap: 16px; align-items: start; }
.eq-photo { margin: 0 0 20px; }
.eq-photo img {
  display: block; width: 100%; max-height: 220px; object-fit: contain;
  background: var(--vw-surface); border: 1px solid var(--vw-border); border-radius: var(--vw-radius-card);
}
@media (max-width: 767.98px) { .eq-overview--photo { grid-template-columns: 1fr; } }

/* ---------- 委外送測窗口與週報（2026-10-06）：一家實驗室一張卡片 ---------- */
.vendor-card {
  background: var(--vw-surface); border-radius: var(--vw-radius-card); box-shadow: var(--vw-shadow);
  border-top: 3px solid var(--vw-border-strong); padding: 14px 16px; margin: 0 0 14px;
}
.vendor-card--muted { opacity: 0.72; }
.vendor-card__head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin: 0 0 10px; }
.vendor-card__id { font-size: 12px; color: var(--vw-text-muted); font-variant-numeric: tabular-nums; }
.vendor-card__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px 16px; }
.vendor-card__field { margin: 0 0 6px; }
.vendor-card__field--wide { grid-column: 1 / -1; }
/* 週報那一列跟聯絡資訊分開：勾不勾、寄給誰是一件事，放在一起看 */
.vendor-card__weekly {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 16px; align-items: end;
  border-top: 1px dashed var(--vw-border); margin-top: 6px; padding-top: 10px;
}
.vendor-card__weekly > label { padding-bottom: 12px; white-space: nowrap; }
.vendor-contacts__save {
  position: sticky; bottom: 0; background: var(--vw-bg, transparent); padding: 10px 0; text-align: right;
}
@media (max-width: 767.98px) {
  .vendor-card__grid, .vendor-card__weekly { grid-template-columns: 1fr; }
}
/* 聯絡信箱旁的信封：點了開 Outlook 新郵件（mailto） */
/* 信封跟著輸入框的高度（stretch）：固定 34px 會把這一列撐高，信箱欄就比左邊那一格低一截 */
.vendor-card__with-icon { display: flex; align-items: stretch; gap: 6px; }
.vendor-card__with-icon input { flex: 1 1 auto; min-width: 0; }
.vendor-card__mail {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 34px; border: 1px solid var(--vw-border-strong); border-radius: var(--vw-radius-control);
  background: var(--vw-surface); color: var(--vw-text-muted);
}
.vendor-card__mail:hover { color: var(--vw-ink); border-color: var(--vw-ink); }
/* 主要窗口／其他聯絡人的小標（2026-10-06） */
.vendor-card__sub { font-size: 12.5px; font-weight: 600; color: var(--vw-text-secondary); margin: 0 0 6px; }
.vendor-card__sub span { font-weight: 400; color: var(--vw-text-muted); margin-left: 8px; }
.vendor-card__contacts { border-top: 1px dashed var(--vw-border); margin-top: 6px; padding-top: 10px; }
/* 一列五格＋刪除；欄名只在有人的時候出現 */
.contact-row {
  display: grid; grid-template-columns: 1.1fr 1fr 1.1fr 1.1fr 1.8fr 64px; gap: 6px 10px;
  align-items: center; margin: 0 0 6px;
}
.contact-row--head span { font-size: 12px; color: var(--vw-text-muted); }
.contact-rows:not(:has(.contact-row:not(.contact-row--head))) .contact-row--head { display: none; }
.contact-row__delete label { margin: 0; font-size: 12.5px; color: var(--vw-text-muted); white-space: nowrap; }
.contact-row__errors { grid-column: 1 / -1; }
.vendor-card__contacts [data-add-contact] { margin: 2px 0 6px; }
@media (max-width: 767.98px) {
  .contact-row { grid-template-columns: 1fr 1fr; }
  .contact-row--head { display: none; }
}

/* 測試報告 V3 清單：整章收合的小按鈕（2026-10-08，照 VTMS 任務清單依 Suite 分群） */
.v3-chapter-toggle { border: 0; background: none; cursor: pointer; font-size: 13px; padding: 0 4px; color: inherit; }
