* { box-sizing: border-box; }
body {
  margin: 0; font-family: "PingFang TC", "Microsoft JhengHei", "Noto Sans TC", sans-serif;
  background: #eef1f5; color: #1f2937; font-size: 14px;
}
[hidden] { display: none !important; }
.muted { color: #6b7280; }
.small { font-size: 12px; }
.center { text-align: center; }
.err { color: #dc2626; }
.num { text-align: right; }

/* ---------- buttons & inputs ---------- */
.btn {
  border: 1px solid #cbd5e1; background: #fff; color: #1f2937;
  padding: 7px 14px; border-radius: 8px; cursor: pointer; font-size: 14px;
}
.btn:hover { background: #f1f5f9; }
.btn.primary { background: #1d4ed8; border-color: #1d4ed8; color: #fff; }
.btn.primary:hover { background: #1e40af; }
.btn.danger { background: #fff; border-color: #fca5a5; color: #dc2626; }
.btn.ghost { border-color: transparent; background: transparent; }
.btn.ghost:hover { background: #e2e8f0; }
.btn.block { width: 100%; }
.btn.small { padding: 4px 10px; font-size: 13px; }
.btn.tiny { padding: 1px 8px; font-size: 11px; margin-left: 6px; }
input, select, textarea {
  width: 100%; padding: 7px 9px; border: 1px solid #cbd5e1; border-radius: 7px;
  font-size: 14px; font-family: inherit; background: #fff;
}
textarea { resize: vertical; line-height: 1.55; }
label { display: block; font-size: 13px; color: #374151; margin-bottom: 8px; }
label > input, label > select, label > textarea { margin-top: 3px; }
label.chk { display: flex; align-items: center; gap: 6px; }
label.chk input { width: auto; margin: 0; }
label.inline { display: flex; align-items: center; gap: 6px; }
label.inline input { margin: 0; }

/* ---------- login ---------- */
.login-wrap { min-height: 100vh; display: flex; align-items: center; justify-content: center; }
.login-card {
  background: #fff; padding: 40px; border-radius: 16px; width: 340px;
  box-shadow: 0 10px 40px rgba(0,0,0,.08); text-align: center;
}
.login-card h1 { margin: 0 0 4px; font-size: 22px; }
.login-card input { margin: 18px 0 12px; }

/* ---------- layout ---------- */
.topbar {
  display: flex; justify-content: space-between; align-items: center;
  background: #fff; padding: 10px 22px; border-bottom: 1px solid #e2e8f0;
  position: sticky; top: 0; z-index: 20;
}
.brand { font-weight: 700; font-size: 16px; cursor: pointer; }
.topbar nav { display: flex; gap: 8px; align-items: center; }
.who { margin: 0 4px; white-space: nowrap; }
.user-add { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.user-add input, .user-add select { width: auto; }
.container { max-width: 1100px; margin: 24px auto; padding: 0 20px; }
.toolbar { display: flex; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; align-items: center; }
.toolbar input[type=search] { max-width: 320px; }
/* 搜尋命中標記：底色夠淡才不會讓整列變花，但要看得出是哪個欄位對上的 */
mark { background: #fef08a; color: inherit; padding: 0 1px; border-radius: 2px; }

/* ---------- 可搜尋下拉（combobox） ----------
   取代原本的 <select>：客戶累積到 60 幾筆後整份列出來很難找。
   清單絕對定位浮在上層，所以外層 .combo 要 position: relative；z-index 要高過相鄰欄位。 */
.combo { position: relative; }
.combo > input { width: 100%; padding-right: 26px; }
.combo-clear {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  border: 0; background: none; cursor: pointer; color: #94a3b8; font-size: 13px;
  line-height: 1; padding: 4px;
}
.combo-clear:hover { color: #334155; }
.combo-list {
  /* 「帶入既有客戶」在窄版會被壓到 100px 左右，清單若只跟著它的寬度，公司名會擠成好幾行。
     給一個 min-width（但不超過視窗）讓清單自己撐開，right:auto 才不會被 left/right 同時釘住。 */
  position: absolute; left: 0; right: auto; top: calc(100% + 2px); z-index: 40;
  min-width: min(340px, calc(100vw - 32px)); max-width: calc(100vw - 32px);
  max-height: 320px; overflow-y: auto; background: #fff;
  border: 1px solid #cbd5e1; border-radius: 8px; box-shadow: 0 8px 24px rgba(15,23,42,.14);
}
.combo-item { padding: 6px 10px; cursor: pointer; font-size: 13px; display: flex; gap: 8px; flex-wrap: wrap; align-items: baseline; }
.combo-item.on, .combo-item:hover { background: #eff6ff; }
.combo-main { font-weight: 600; color: #0f172a; }
.combo-sub { font-size: 12px; color: #475569; }
.combo-more { padding: 6px 10px; font-size: 12px; color: #64748b; }
.toolbar select { width: auto; }
.toolbar label.inline, .toolbar label.chk.inline { font-size: 13px; color: #475569; }
.toolbar label input[type=date] { width: auto; }
#more-filter { background: #f1f5f9; border-radius: 10px; padding: 10px 12px; margin-top: -6px; }
.btn.on { background: #dbeafe; border-color: #93c5fd; color: #1e40af; }

/* ---------- list table ---------- */
.list-table { width: 100%; border-collapse: collapse; background: #fff; border-radius: 10px; overflow: hidden; }
.list-table th, .list-table td { padding: 10px 12px; text-align: left; border-bottom: 1px solid #eef1f5; }
.list-table th { background: #f8fafc; font-size: 12px; color: #64748b; }
.list-table td.num, .list-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.list-table tr:hover td { background: #f8fafc; }
.list-table th.sortable { cursor: pointer; user-select: none; }
.list-table th.sortable:hover { background: #eef2f7; color: #1d4ed8; }
.sort-ind { color: #1d4ed8; font-size: 10px; }
.link { color: #1d4ed8; cursor: pointer; text-decoration: none; font-weight: 600; }
.link:hover { text-decoration: underline; }
.tag { display: inline-block; padding: 2px 9px; border-radius: 99px; font-size: 12px; white-space: nowrap; }
.list-table td:has(> .tag) { white-space: nowrap; }

/* 報價單列表欄寬：把可預期寬度的欄位收到內容寬（width:1% + nowrap），
   剩餘空間留給單號與客戶；客戶名稱常是長公司全名，給它比單號更多的下限。
   只在表格模式（>1200px）生效——窄螢幕轉卡片後這些欄寬會把 td 壓成幾 px。 */
@media (min-width: 1201px) {
  #quote-list-table { table-layout: auto; }
  #quote-list-table .c-no { min-width: 190px; }
  #quote-list-table .c-cust { min-width: 260px; }
  #quote-list-table .c-type,
  #quote-list-table .c-date,
  #quote-list-table .c-money,
  #quote-list-table .c-status,
  #quote-list-table .c-owner,
  #quote-list-table .c-act { width: 1%; white-space: nowrap; }
}
/* 版本備註另起一行放在單號下方，不再接在單號後面把欄位撐寬 */
.row-note { margin-top: 2px; font-size: 12px; color: #64748b; }
.tag.MA { background: #dbeafe; color: #1e40af; }
.tag.CR { background: #fef3c7; color: #92400e; }
.tag.QT { background: #dcfce7; color: #166534; }
.tag.NB { background: #fce7f3; color: #9d174d; }
.tag.RN { background: #cffafe; color: #155e75; }
.tag.priv { background: #fee2e2; color: #991b1b; }
label.chk.is-private { color: #991b1b; font-weight: 700; }
.tag.vfinal { background: #16a34a; color: #fff; }
.tag.vplain { background: #e2e8f0; color: #475569; }
.tag.dl-expired { background: #7f1d1d; color: #fff; }
.tag.dl-30 { background: #dc2626; color: #fff; }
.tag.dl-60 { background: #f97316; color: #fff; }
.tag.dl-90 { background: #facc15; color: #713f12; }

/* 到期提醒卡 */
.reminder-card {
  background: #fff; border: 1px solid #fcd34d; border-radius: 10px;
  overflow: hidden; margin-bottom: 16px;
}
.reminder-head {
  background: #fffbeb; padding: 9px 14px; font-weight: 700; font-size: 14px;
  color: #92400e; border-bottom: 1px solid #fde68a;
}

/* 版本鏈（列表） */
.fam-toggle { cursor: pointer; color: #1d4ed8; font-size: 12px; margin-right: 6px; user-select: none; }
.fam-toggle:hover { text-decoration: underline; }
.fam-child { display: none; }
.fam-child.show { display: table-row; }
.fam-child td { background: #fafbfc; color: #6b7280; }
.fam-indent { color: #94a3b8; margin-right: 4px; }

/* 版本鏈（編輯器） */
#version-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 8px 0 4px; }
.ver-label { font-size: 12px; color: #64748b; }
#version-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.ver-chip {
  padding: 3px 10px; border-radius: 99px; border: 1px solid #cbd5e1; font-size: 12px;
  cursor: pointer; background: #fff; white-space: nowrap;
}
.ver-chip small { color: #94a3b8; }
.ver-chip:hover { background: #f1f5f9; }
.ver-chip.cur { border-color: #1d4ed8; background: #eff6ff; font-weight: 700; cursor: default; }
.ver-chip.fin { border-color: #16a34a; }
.ver-chip.fin small { color: #16a34a; }
.ver-actions { display: flex; gap: 6px; align-items: center; }
.warn-banner {
  background: #fef3c7; border: 1px solid #fbbf24; color: #92400e;
  padding: 7px 12px; border-radius: 8px; font-size: 13px; margin: 6px 0;
}
.tag.draft { background: #e2e8f0; color: #475569; }
.tag.sent { background: #ffedd5; color: #9a3412; }
.tag.signed { background: #dcfce7; color: #166534; }
.tag.lost { background: #fee2e2; color: #991b1b; }
.tag.void { background: #f1f5f9; color: #94a3b8; text-decoration: line-through; }
/* 預算評估中：客戶有回應但要等編預算。刻意用靛藍，和橘色的「已送出」、紅色的
   「未成交」都拉開——它既不是待催，也不是壞消息。 */
.tag.budgeting { background: #e0e7ff; color: #3730a3; }
.tag.budget-unset { background: #f1f5f9; color: #64748b; }
/* 列表／追蹤卡上的一鍵改狀態下拉：外觀沿用 .tag 的色票，看起來仍像狀態標籤 */
/* select 寬度取決於最長的那個選項（「預算評估中」），短標籤在膠囊裡會偏左，
   所以把收合後顯示的值置中；展開的選項清單維持靠左才好讀。 */
.status-pick {
  width: auto; border: 1px solid rgba(0,0,0,.12); padding: 1px 4px; font-size: 12px;
  font-family: inherit; cursor: pointer; appearance: none; -webkit-appearance: none;
  background-image: none; color: inherit;
  text-align: center; text-align-last: center;
}
.status-pick option { text-align: left; text-align-last: left; color: #0f172a; }
.status-pick:hover { border-color: rgba(0,0,0,.35); }
.followup-days { float: right; font-weight: 400; font-size: 12px; }
.followup-days input { width: 52px; padding: 1px 4px; font-size: 12px; }
/* 預算追蹤卡：藍色系，與黃色的到期／跟催卡區隔 */
#budgets-card { border-color: #c7d2fe; }
#budgets-card .reminder-head {
  background: #eef2ff; color: #3730a3; border-bottom-color: #c7d2fe;
}
#budgets-card .reminder-head .muted { float: right; font-weight: 400; }
/* 月份輸入框原生寬度很寬，會把卡片欄位撐開，收窄並固定不換行 */
.budget-set { white-space: nowrap; }
.budget-set input { width: 130px; padding: 1px 4px; font-size: 12px; }

/* ---------- 項次明細欄寬（可拖曳調整，編輯器與報價單版面共用同一組寬度） ---------- */
:root {
  --col-no-mm: 11mm;
  --col-name-mm: 30mm;
  --col-unit-mm: 16mm;
  --col-price-mm: 24mm;
  --col-disc-mm: 24mm;
  /* 其他增購／其他選購表獨立一組欄寬，不與上方報價項目主表共用 */
  --excol-no-mm: 11mm;
  --excol-unit-mm: 16mm;
  --excol-price-mm: 24mm;
  --excol-disc-mm: 24mm;
  /* 服務計費標準附表，同樣是編輯器與報價單版面共用 */
  --fee-no-mm: 10mm;
  --fee-time-mm: 28mm;
  --fee-scope-mm: 20mm;
  --fee-unit-mm: 20mm;
  --fee-fee-mm: 26mm;
}
/* 服務計費標準附表：編輯器與報價單版面共用同一組欄寬（「項目」欄不設寬，吃剩餘空間）。
   編輯器裡是輸入框，拖太窄會打不了字，故取「設定值」與「可操作下限」的較大者——
   拖寬時兩邊同步，拖窄時編輯器守住下限、報價單那側仍照設定值縮。 */
/* 「項目」是彈性欄、不設寬，但仍要 position:relative 才能放把手（把手是絕對定位） */
.fcol-item { position: relative; }
.fcol-no { width: var(--fee-no-mm); }
.fcol-time { width: var(--fee-time-mm); }
.fcol-scope { width: var(--fee-scope-mm); }
.fcol-unit { width: var(--fee-unit-mm); }
.fcol-fee { width: var(--fee-fee-mm); }
#feetable-editor .fcol-no { width: max(var(--fee-no-mm), 26px); }
#feetable-editor .fcol-time { width: max(var(--fee-time-mm), 70px); }
#feetable-editor .fcol-scope { width: max(var(--fee-scope-mm), 64px); }
#feetable-editor .fcol-unit { width: max(var(--fee-unit-mm), 58px); }
#feetable-editor .fcol-fee { width: max(var(--fee-fee-mm), 74px); }

.col-no { width: var(--col-no-mm); }
/* 編輯器的第一欄放的是分組下拉（NB/NC）或項次數字，比報價單的項次欄需要更多空間，
   所以取「設定寬度」與「可用最小寬度」的較大者——拖寬時兩邊仍同步，拖窄時編輯器守住可操作下限 */
.items-table td.col-no, .items-table th.col-no { width: max(var(--col-no-mm), 34px); }
.items-table.has-group-col td.col-no, .items-table.has-group-col th.col-no { width: max(var(--col-no-mm), 62px); }
.items-table td.col-no select { width: 100%; min-width: 0; }
.col-name { width: var(--col-name-mm); }
.col-unit { width: var(--col-unit-mm); }
/* 編輯器的單位欄放的是輸入框（CR 還多一個模式切換 icon），拖太窄會打不了字，
   故取「設定寬度」與「可操作下限」的較大者——比照上方 col-no 的做法 */
.items-table td.col-unit, .items-table th.col-unit { width: max(var(--col-unit-mm), 64px); }
.col-price { width: var(--col-price-mm); }
.col-disc { width: var(--col-disc-mm); }
.excol-no { width: max(var(--excol-no-mm), 34px); }
.excol-unit { width: var(--excol-unit-mm); }
.excol-price { width: var(--excol-price-mm); }
.excol-disc { width: var(--excol-disc-mm); }
.col-tfnum { width: 20mm; }  /* 流量對帳單專用：實際流量／超出流量欄，固定寬不參與拖曳系統 */
.items-table th { position: relative; }
.col-resize-handle {
  position: absolute; top: 2px; right: -7px; bottom: 2px; width: 14px; cursor: col-resize; z-index: 3;
}
.col-resize-handle::after {
  content: ''; position: absolute; top: 0; bottom: 0; left: 50%; width: 2px; margin-left: -1px;
  background: #94a3b8; border-radius: 1px;
}
.col-resize-handle:hover, .col-resize-handle.active { background: rgba(29, 78, 216, .12); }
.col-resize-handle:hover::after, .col-resize-handle.active::after { background: #1d4ed8; width: 3px; margin-left: -1.5px; }

/* ---------- editor ---------- */
.edit-layout { display: flex; gap: 0; align-items: flex-start; }
/* 左右比例可拖曳：--form-w 由分隔線即時寫入，存 localStorage 記住偏好 */
.edit-form {
  flex: 0 0 var(--form-w, 46%); min-width: 0; background: #fff; min-height: calc(100vh - 53px);
  padding: 18px 22px 60px;
}
.split-handle {
  flex: 0 0 7px; align-self: stretch; cursor: col-resize; background: #e2e8f0;
  position: sticky; top: 53px; height: calc(100vh - 53px);
  display: flex; align-items: center; justify-content: center;
}
.split-handle::after {
  content: ''; width: 3px; height: 42px; border-radius: 2px; background: #94a3b8;
}
.split-handle:hover, .split-handle.active { background: #bfdbfe; }
.split-handle:hover::after, .split-handle.active::after { background: #1d4ed8; }
.form-head { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px; }
.form-head h2 { margin: 0; font-size: 18px; }
.form-head-actions { display: flex; gap: 6px; }
fieldset {
  border: 1px solid #e2e8f0; border-radius: 10px; margin: 16px 0; padding: 12px 14px 6px;
}
legend { font-weight: 700; font-size: 13px; color: #1d4ed8; padding: 0 6px; }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
.grid3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0 14px; }
.grid4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0 10px; }
.calc-result span { margin-right: 8px; }
.calc-box {
  background: #f0f6ff; border: 1px dashed #93c5fd; border-radius: 8px;
  padding: 10px 12px; margin-bottom: 12px; font-size: 13px;
}
.calc-box strong { display: block; margin-bottom: 6px; }
.calc-result { display: flex; align-items: center; gap: 10px; }
.calc-result strong { display: inline; color: #1d4ed8; font-size: 15px; }
.items-table { width: 100%; border-collapse: collapse; margin-bottom: 8px; }
.items-table th { background: #f8fafc; font-size: 12px; color: #64748b; padding: 6px; text-align: left; }
.items-table td { padding: 4px 3px; vertical-align: top; }
.items-table textarea { font-size: 13px; padding: 5px 7px; }
.items-table input { font-size: 13px; padding: 5px 7px; }
.del-item { color: #dc2626; cursor: pointer; font-size: 16px; padding: 6px 4px; }
.items-table td.item-ops { width: 62px; white-space: nowrap; padding-top: 6px; }
.items-table td.extra-ops { width: 42px; white-space: nowrap; padding-top: 6px; }
/* 列拖曳排序：把手＋落點指示線（藍線畫在目標列上緣或下緣） */
.drag-item { cursor: grab; color: #94a3b8; font-size: 15px; padding: 6px 3px; user-select: none; }
.drag-item:hover { color: #2563eb; }
.items-table tr.row-dragging td { opacity: .45; }
.items-table tr.drop-before td { box-shadow: inset 0 3px 0 #2563eb; }
.items-table tr.drop-after td { box-shadow: inset 0 -3px 0 #2563eb; }
.tpl-item { cursor: pointer; font-size: 14px; padding: 6px 2px; opacity: .45; }
.tpl-item:hover { opacity: 1; }
/* CR 單位欄：人天自動計價 ⇄ 自訂單位（如「1 Set」）切換 icon，貼齊輸入框右緣 */
.unit-mode-wrap { position: relative; }
.unit-mode-wrap input { padding-right: 20px; }
/* 關掉 type=number 的原生上下鍵：這欄只有 16mm（約 60px），原生 spinner 約佔 17px 又正好
   畫在切換 icon 的位置上，兩者疊在一起會把整格擋滿，能打字的區域剩不到 20px。
   人天是直接鍵入的數字，上下鍵在這個寬度下沒有實用價值。其他較寬的數字欄不受影響。 */
.unit-mode-wrap input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.unit-mode-wrap input[type="number"]::-webkit-outer-spin-button,
.unit-mode-wrap input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.unit-mode-toggle {
  position: absolute; right: 3px; top: 50%; transform: translateY(-50%);
  cursor: pointer; font-size: 12px; opacity: .4; user-select: none; line-height: 1;
}
.unit-mode-toggle:hover { opacity: 1; }
.tpl-pick { width: auto; margin-left: 8px; font-size: 13px; padding: 4px 8px; }
.list-table td.tpl-desc { max-width: 320px; font-size: 12px; color: #475569; }
.totals-preview { text-align: right; font-size: 14px; padding: 6px 4px; }
.totals-preview b { font-variant-numeric: tabular-nums; }
.form-foot { display: flex; gap: 8px; margin-top: 18px; }

/* ---------- preview sheet (screen) ---------- */
.preview-pane { flex: 1; padding: 18px; position: sticky; top: 53px; max-height: calc(100vh - 53px); overflow: auto; }
.preview-label { font-size: 12px; color: #64748b; margin-bottom: 8px; }
/* 預覽縮放用 transform: scale() 而非 zoom：zoom 會觸發整份版面重新排版（實測 70 項次的
   單一次切換就要 32.8ms，逐字輸入時每個按鍵都付這個成本），transform 只影響合成不動排版
   （同樣情境 4.7ms）。附帶好處是預覽的排版就是列印的排版：zoom 會依縮放比重新排版，量到的
   高度會有些微偏移（實測 zoom 0.9 時 473.4mm→474.2mm），transform 完全不動排版。
   transform 不佔版面空間，所以外面包一層 .sheet-wrap，由 fitSheet() 設成縮放後的尺寸，
   捲動區域才會正確。 */
.sheet-wrap { position: relative; margin: 0 auto; }
.sheet {
  background: #fff; width: 210mm; min-height: 290mm; position: absolute; top: 0; left: 0;
  padding: 14mm 14mm 10mm; box-shadow: 0 4px 24px rgba(0,0,0,.12);
  /* 內嵌 Noto Sans TC（思源黑體繁體，見 fonts/noto-sans-tc.css），不吃本機安裝的 PMingLiU
     (新細明體，僅 Windows 有)／PingFang TC(Mac 內建) ——不同電腦 fallback 到的字型字寬不同，
     會讓換行位置跟著變，曾導致同一張單有的電腦印一頁、有的多跳到第二頁。
     第二順位 TW-Sung（全字庫正宋體，見 fonts/tw-sung.css）只收主字型沒有的 CNS 罕用字與
     異體字——客戶名稱／聯絡人姓名出現這類字時，落到的仍是自行 host 的同一份檔案，不會回到
     「各電腦各自為政」的本機字型。它靠 unicode-range 生效，一般報價單不會多下載任何檔案。
     sans-serif 純屬兩份都載入失敗時的最終備援。 */
  font-family: "Noto Sans TC", "TW-Sung", sans-serif;
  color: #000; font-size: 11.5pt; line-height: 1.45;
  transform-origin: top left;
}

/* 預覽的分頁線：標出列印時實際會斷頁的位置（由 fitSheet() 模擬後插入，不列印）。
   定位基準是 .sheet 本身（它已是 position: absolute，即為子孫的含塊）。 */
.page-break-mark {
  position: absolute; left: 0; right: 0; height: 0;
  border-top: 0.4mm dashed #dc2626; pointer-events: none;
}
.page-break-mark::after {
  content: attr(data-label);
  position: absolute; right: 2mm; top: 0.5mm;
  font-family: system-ui, sans-serif; font-size: 8pt; color: #dc2626;
  background: #fff; padding: 0 4px;
}

/* ---------- quote document ---------- */
.q-head { position: relative; }
.q-logo { position: absolute; left: 0; top: 50%; transform: translateY(-50%); height: 9mm; width: auto; }
.q-company { text-align: center; font-size: 17pt; font-weight: 700; letter-spacing: 6px; }
.q-title { text-align: center; font-size: 14pt; font-weight: 700; letter-spacing: 10px; margin: 8px 0 10px; }
.q-info { width: 100%; border-collapse: collapse; font-size: 10.5pt; margin-bottom: 2px; }
.q-info td { padding: 1.5px 0; vertical-align: top; }
.q-info td.r { width: 38%; }
.q-ntd { text-align: right; font-size: 9.5pt; font-style: italic; padding: 2px 0; }
.q-items { width: 100%; border-collapse: collapse; font-size: 10.5pt; }
.q-items th, .q-items td { border: 1.2px solid #000; padding: 5px 7px; vertical-align: top; }
.q-items th { text-align: center; font-weight: 700; background: #fff; }
.q-items td.c { text-align: center; }
.q-items td.n { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.q-items .desc { white-space: pre-wrap; }
.q-items .total-row td { font-weight: 700; }
.q-items .group-row td { font-weight: 700; background: #efefef; padding: 3px 7px; }
.q-items .subtotal-row td { background: #f7f7f7; }
.q-items .grand-row td { background: #fdf3e7; }
.q-section-label { float: left; font-weight: 700; font-style: normal; color: #c2410c; }
.q-special { margin-top: 8px; font-size: 10.5pt; font-weight: 700; white-space: pre-wrap; }
.q-ncnote { margin-top: 8px; font-size: 9.5pt; white-space: pre-wrap; line-height: 1.5; }
.tag.NC { background: #ede9fe; color: #5b21b6; }
.tag.BD { background: #ffe4e6; color: #9f1239; }
.tag.TF { background: #e0f2fe; color: #075985; }
.q-title-tf { font-size: 12pt; font-weight: 700; margin: 6px 0 8px; }
.q-fee { margin-top: 6px; }
.q-fee td, .q-fee th { vertical-align: middle; }
.q-fee td.fee-item { text-align: left; vertical-align: middle; }
.q-fee td.desc { vertical-align: middle; }
.q-extras-title { font-weight: 700; font-size: 10.5pt; margin-top: 10px; }
.q-extras-note { font-size: 8.5pt; text-align: right; margin-top: 2px; }
.q-block { border: 1.2px solid #000; border-top: none; padding: 6px 8px; font-size: 9.5pt; white-space: pre-wrap; line-height: 1.5; }
.q-remark { margin-top: 5px; font-size: 9.5pt; white-space: pre-wrap; line-height: 1.5; }
.q-remark .h { font-weight: 700; }
.q-secret { margin-top: 5px; font-size: 9.5pt; font-weight: 700; }
.q-sign { margin-top: 8px; font-size: 11pt; display: flex; justify-content: space-between; align-items: flex-end; }
.q-sign-left { padding-bottom: 4mm; }
.q-sign .line { display: inline-block; width: 60mm; border-bottom: 1.2px solid #000; height: 14mm; vertical-align: bottom; }
.q-stamp { height: 30mm; width: auto; margin-right: 8mm; }

/* ---------- 客戶報價單彈窗 ---------- */
.modal-backdrop {
  position: fixed; inset: 0; background: rgba(15, 23, 42, .45);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 6vh 20px; z-index: 100; overflow-y: auto;
}
.modal-box {
  background: #fff; border-radius: 12px; width: 100%; max-width: 960px;
  padding: 20px 22px; box-shadow: 0 20px 60px rgba(0,0,0,.25);
}
.modal-box.narrow { max-width: 520px; }
.modal-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
.modal-head h3 { margin: 0; font-size: 17px; }
.modal-foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
.dup-preview { min-height: 18px; margin: -6px 0 8px; }
.list-table td.row-actions { white-space: nowrap; text-align: right; }

/* ---------- RWD ---------- */
/* 報價單列表欄位多，寬螢幕時放寬容器上限（其他頁維持 1100px 的閱讀寬度） */
#view-list.container { max-width: 1400px; }

@media (max-width: 1200px) {
  .container { padding: 0 12px; margin: 16px auto; }
  .topbar { flex-wrap: wrap; gap: 8px; padding: 10px 12px; }
  .topbar nav { flex-wrap: wrap; gap: 6px; }
  .toolbar input[type=search] { max-width: none; flex: 1 1 100%; }

  /* 報價單列表：表格轉卡片，每列一張卡、欄位標題用 data-l 補在值前面 */
  #quote-list-table { display: block; background: none; }
  #quote-list-table thead { display: none; }
  #quote-list-table tbody { display: block; }
  #quote-list-table tr {
    display: block; background: #fff; border: 1px solid #e2e8f0; border-radius: 10px;
    padding: 10px 12px; margin-bottom: 10px;
  }
  #quote-list-table tr:hover td { background: transparent; }
  /* 桌機的 width:1%／min-width 欄寬在卡片模式下要全部歸零，否則 td 會被壓成幾 px */
  #quote-list-table td {
    display: flex; gap: 8px; align-items: baseline;
    border: none; padding: 3px 0; text-align: left;
    width: auto; min-width: 0; white-space: normal;
  }
  #quote-list-table td::before {
    content: attr(data-l); flex: 0 0 66px;
    font-size: 12px; color: #94a3b8;
  }
  #quote-list-table td.c-no { display: block; font-size: 15px; margin-bottom: 6px; }
  #quote-list-table td.c-no::before { content: none; }
  #quote-list-table td.c-money { justify-content: flex-start; }
  #quote-list-table td.c-act {
    display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 6px;
    margin-top: 8px; padding-top: 8px; border-top: 1px solid #f1f5f9;
  }
  #quote-list-table td.c-act .btn { flex: 0 0 auto; }
  #quote-list-table td.c-act::before { content: none; }
  /* 版本子列在卡片模式下改用 display:block（原本是 table-row） */
  #quote-list-table tr.fam-child.show { display: block; }
  #quote-list-table tr.fam-child td { background: transparent; }
  #quote-list-table tr.fam-child { background: #fafbfc; margin-left: 14px; }

  /* 其他頁的表格（客戶／範本／帳號／稽核／到期提醒）改成可橫向捲動，不擠壓內容 */
  .list-table:not(#quote-list-table) { display: block; overflow-x: auto; }
  .list-table:not(#quote-list-table) th,
  .list-table:not(#quote-list-table) td { white-space: nowrap; }
}

/* ---------- print ---------- */
@media print {
  body { background: #fff; }
  .no-print, .topbar, .preview-label { display: none !important; }
  .edit-layout { display: block; }
  .split-handle { display: none !important; }
  .preview-pane { padding: 0; position: static; max-height: none; overflow: visible; }
  /* 內距移回 sheet，@page margin 設 0 → 瀏覽器無空間放頁首頁尾（日期/標題/網址），自動消失 */
  .sheet-wrap { position: static; width: auto !important; height: auto !important; }
  .sheet { box-shadow: none; width: auto; min-height: 0; margin: 0; padding: 14mm 14mm 10mm;
           position: static; transform: none !important; }
  @page { size: A4 portrait; margin: 0; }

  /* ⚠️ Safari／WebKit：跨頁被切開的表格列不會像 Chrome 那樣接續印出，而是「直接把超出
     的文字裁掉」——說明欄較長的項次在分頁處會整段消失。故明確要求整列不可被切開，
     放不下就整列移到下一頁。Chrome 本來就正常，加了也不會變差。
     兩種寫法都寫：break-inside 是標準屬性，page-break-inside 給舊版 Safari。 */
  .q-items tr, .q-items td, .q-items th {
    break-inside: avoid; page-break-inside: avoid;
  }
  /* 註：報價單表頭是純 <tr> 沒有 <thead>，故沒有加 table-header-group（加了也無效）。
     若日後要讓表頭在第二頁重複，需先把表頭那列包進 <thead>。 */

  /* 這幾區塊都不長，被切開只會更難讀，一律整塊移到下一頁 */
  .q-head, .q-info, .q-sign, .q-secret, .q-ntd,
  .q-section-label, .q-extras-title, .q-extras-note, .q-special {
    break-inside: avoid; page-break-inside: avoid;
  }
  /* 備註／說明／特別說明可能長到超過一頁，不能設 avoid（設了也滿足不了，反而可能
     被推到下一頁又爆版）。改為避免只留孤行，讓它自然斷在段落之間。 */
  .q-block, .q-remark, .q-ncnote { orphans: 3; widows: 3; }
}


/* 帳號管理：角色變更下拉（緊湊，與同列的小按鈕對齊） */
.role-pick { width: auto; display: inline-block; padding: 2px 6px; font-size: 12px; margin-right: 6px; }

/* ---------- 牌價表 ---------- */
.form-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
@media (max-width: 640px) { .form-grid-2 { grid-template-columns: 1fr; } }
#price-table td.pnum, #price-table th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* 欄寬可拖曳：table-layout:fixed 讓寬度真正照設定值走（auto 會被內容撐開，拖了沒反應）。
   寬度由 --pc-* CSS 變數控制，表頭把手拖曳時即時更新、放開存 localStorage。
   ⚠️ 用 class 而非 nth-child：內部成本欄對非管理員不會渲染 td，nth-child 會整排錯位。 */
/* ⚠️ 不能用 width:100%：table-layout:fixed 時若各欄寬度總和與表格寬度不符，瀏覽器會
   「按比例」縮放所有欄位——拖寬一欄會連帶壓縮其他欄，視覺上等於沒反應。
   改成表格寬度＝各欄總和（max-content），不足一個容器寬時撐滿（min-width:100%），
   超出時由外層 .table-scroll 橫向捲動。 */
/* 表格固定塞滿容器（width:100%），各欄寬度由 JS 維持「總和＝容器寬－操作欄」，
   拖曳時本欄與右鄰欄互相借空間、總寬不變，所以正常情況不會出現橫向捲軸。
   .table-scroll 的 overflow 只是視窗窄到各欄都到最小寬時的安全閥。 */
#price-table { table-layout: fixed; width: 100%; }
#price-table th:last-child, #price-table td:last-child { width: var(--pc-act, 120px); }
.table-scroll { overflow-x: auto; border-radius: 10px; }
#price-table th { position: relative; }
#price-table .pc-mode { width: var(--pc-mode, 92px); }
#price-table .pc-cat { width: var(--pc-cat, 92px); }
#price-table .pc-product { width: var(--pc-product, 240px); }
#price-table .pc-spec { width: var(--pc-spec, 170px); }
#price-table .pc-avail { width: var(--pc-avail, 100px); }
#price-table .pc-unit { width: var(--pc-unit, 64px); }
#price-table .pc-list { width: var(--pc-list, 100px); }
#price-table .pc-floor { width: var(--pc-floor, 100px); }
#price-table .pc-cost { width: var(--pc-cost, 100px); }
#price-table .pc-eff { width: var(--pc-eff, 100px); }
/* 拖窄時內容要能收進去，不要溢出破版；產品與備註允許換行 */
#price-table td { overflow-wrap: anywhere; }
#price-table td.pc-mode, #price-table td.pc-unit, #price-table td.pc-eff { white-space: nowrap; }
/* 備註可能很長，限制寬度不讓它把整表撐爆 */
#price-table .row-note { white-space: normal; max-width: 420px; }
#pp-table th:nth-child(2), #pp-table td:nth-child(2) { min-width: 200px; }
#pp-table th:nth-child(3), #pp-table td:nth-child(3) { min-width: 140px; }
.tag.mode-perpetual { background: #e0e7ff; color: #3730a3; }
.tag.mode-cloud { background: #cffafe; color: #155e75; }
.price-inactive td { opacity: .55; }
.cost-col { color: #b45309; }
#pp-table tbody tr { cursor: pointer; }
#pp-table tbody tr:hover td { background: #eff6ff; }
/* 牌價表排序指示器（沿用列表的 .sortable hover 樣式；把手要在指示器之上不被蓋住） */
#price-table .psort-ind { color: #1d4ed8; font-size: 10px; }
#price-table th.sortable { user-select: none; }

/* 級距試算結果 */
.tc-result { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 10px 12px; margin: 6px 0 4px; }
.tc-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.tc-table td { padding: 3px 0; }
.tc-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.tc-table tr.tc-total td { border-top: 1px solid #cbd5e1; padding-top: 6px; font-weight: 700; font-size: 15px; }

/* 牌價「規則列」：描述計價規則而非可獨立報價的品項，需明顯區隔 */
.tag.rule-row { background: #fef3c7; color: #92400e; font-weight: 700; }
.rule-note { color: #92400e !important; }
#pp-table tbody tr.pp-rule-row td { background: #fffbeb; }

/* ---------- 自動檢核 ---------- */
.nav-badge {
  display: inline-block; min-width: 18px; padding: 0 5px; border-radius: 9px;
  background: #dc2626; color: #fff; font-size: 11px; line-height: 18px; text-align: center; margin-left: 2px;
}
.sev { font-weight: 700; white-space: nowrap; }
.sev.high { color: #dc2626; }
.sev.medium { color: #c2410c; }
.sev.low { color: #64748b; }
.checks-table { table-layout: fixed; }
#view-checks .checks-table td { vertical-align: top; overflow-wrap: anywhere; white-space: normal; }
/* 窄螢幕時其他表格改橫向捲動（見上方 @media），這頁的說明很長，維持換行比較好讀 */
#view-checks .checks-table { display: table; }
.checks-table td:nth-child(4) a { word-break: break-all; }
.checks-table tr.resolved td { color: #94a3b8; }
.checks-table tr.resolved .sev { color: #cbd5e1; }
.checks-table .rule-name { font-size: 11px; color: #64748b; background: #f1f5f9; border-radius: 4px; padding: 0 5px; margin-right: 4px; white-space: nowrap; }
.checks-table .resolved-note { font-size: 12px; color: #16a34a; margin-top: 2px; }
.check-panel {
  border: 1px solid #fecaca; background: #fef2f2; border-radius: 8px; padding: 7px 12px; margin: 6px 0; font-size: 13px;
}
.check-panel.only-low { border-color: #e2e8f0; background: #f8fafc; }
.check-panel summary { cursor: pointer; font-weight: 700; color: #991b1b; }
.check-panel.only-low summary { color: #475569; }
.check-panel ul { margin: 6px 0 2px; padding-left: 4px; list-style: none; }
.check-panel li { display: flex; gap: 8px; align-items: baseline; padding: 3px 0; border-top: 1px dashed #fecaca; }
.check-panel li:first-child { border-top: 0; }
.check-panel li.resolved { color: #94a3b8; }
.check-panel li .grow { flex: 1; }

/* 多套系統期間提示（編輯器合約起訖下方） */
.period-hint { font-size: 12px; color: #1e40af; background: #eff6ff; border: 1px solid #bfdbfe;
  border-radius: 6px; padding: 5px 9px; margin: 2px 0 8px; line-height: 1.6; }
.rem-sys { color: #334155; font-weight: 600; }

/* ---------- 客戶合約總覽 ---------- */
.kpi-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin: 12px 0 16px; }
@media (max-width: 760px) { .kpi-row { grid-template-columns: repeat(2, 1fr); } }
.kpi { background: #fff; border: 1px solid #e2e8f0; border-radius: 10px; padding: 12px 16px; }
.kpi.link { cursor: pointer; }
.kpi.link:hover { border-color: #93c5fd; }
.kpi-label { font-size: 12px; color: #64748b; }
.kpi-num { font-size: 26px; font-weight: 700; color: #0f172a; line-height: 1.3; font-variant-numeric: tabular-nums; }
.kpi-sub { font-size: 12px; color: #94a3b8; }
.contracts-table { table-layout: fixed; }
#view-contracts .contracts-table { display: table; }
#view-contracts .contracts-table td { vertical-align: top; white-space: normal; overflow-wrap: anywhere; }
.contracts-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.contracts-table .days { font-size: 18px; font-weight: 700; white-space: nowrap; }
.contracts-table .days small { font-size: 12px; font-weight: 400; color: #94a3b8; margin-left: 2px; }
.contracts-table .days.overdue { color: #b91c1c; }
.contracts-table .days.soon { color: #c2410c; }
.contracts-table .sub { font-size: 12px; color: #64748b; margin-top: 2px; }
.tag.est { background: #f1f5f9; color: #64748b; }
.tag.c-ok { background: #dcfce7; color: #166534; }
.tag.c-soon { background: #ffedd5; color: #9a3412; }
.tag.c-over { background: #fee2e2; color: #991b1b; }
