  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

  :root {
    --bg: #f5f4f0;
    --surface: #ffffff;
    --surface2: #f0efe9;
    --border: #dddbd3;
    --border2: #c9c7be;
    --text: #1a1a18;
    --text2: #6b6960;
    /* --text3 為次要標籤/序號用色。原 #9c9a91 對白底僅 2.8:1、對 --bg 2.5:1，不達 WCAG AA；
       客戶版標籤也用它 → 調到 #6a6860（白底 5.6:1、--bg 5.0:1）確保可讀。 */
    --text3: #6a6860;
    /* placeholder 專用：原用 --border2(1.7:1) 幾近不可見。#8d8b82 對白底 3.4:1、--bg 3.1:1，提示可辨又不搶戲。 */
    --placeholder: #8d8b82;
    --accent: #1a6b4a;
    --accent-light: #e4f2eb;
    --accent-text: #0f4a33;
    --danger: #8b2020;
    --danger-light: #fceaea;
    --radius: 10px;
    --radius-sm: 6px;
  }

  body {
    font-family: 'Noto Sans TC', sans-serif;
    background: var(--bg);
    color: var(--text);
    min-height: 100vh;
    padding: 40px 24px 80px;
    /* 關掉水平 overscroll 的「上一頁/下一頁」導覽（Android Chrome）——客戶在手機簽名時
       左右滑動很容易誤觸。iOS 邊緣返回是系統手勢、CSS 擋不掉，另以 popstate 防護處理。 */
    overscroll-behavior-x: none;
  }

  .page {
    max-width: 900px;
    margin: 0 auto;
  }
  /* 編輯畫面整體放大一點（含字）。px-based 設計用 zoom 一次等比放大字與間距；
     只作用在編輯視圖，客戶版/列印(.readonly/.exporting)維持既有精算尺寸。 */
  body:not(.readonly):not(.exporting) .page { zoom: 1.1; }

  /* ── Top bar (brand + account) ── */
  .topbar {
    margin-bottom: 18px;
  }
  .brand-head {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 12px;
  }
  .brand-logo {
    height: 30px;
    width: auto;
    display: block;
  }
  .page-title {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1 1 auto;
    min-width: 0;
    font-size: 30px;
    font-weight: 600;
    letter-spacing: -0.02em;
    color: var(--text);
  }
  /* 可自訂的文件標題（輸入框；正式版自動變乾淨文字）*/
  .doc-title-input {
    field-sizing: content;        /* 依內容自動寬，兩格並排各自貼齊 */
    width: auto;
    min-width: 6ch;
    max-width: 100%;
    font-family: 'Noto Sans TC', sans-serif;
    font-size: 30px;
    font-weight: 600;
    letter-spacing: -0.02em;
    color: var(--text);
    background: transparent;
    border: none;
    outline: none;
    padding: 2px 4px;
    border-radius: var(--radius-sm);
  }
  .doc-title-input:focus { background: var(--surface2); }
  .doc-title-input::placeholder { color: var(--placeholder); }
  .doc-type-label { min-width: 3ch; }   /* 類型字樣較短（報價單／請款單）*/
  /* 可選副標題（空白時：編輯區顯示淡提示；正式版整列收合）*/
  .doc-subtitle-input {
    display: block;
    width: 100%;
    margin: 2px 0 6px;
    font-family: 'Noto Sans TC', sans-serif;
    font-size: 15px;
    font-weight: 400;
    color: var(--text2);
    background: transparent;
    border: none;
    outline: none;
    padding: 2px 4px;
    border-radius: var(--radius-sm);
  }
  .doc-subtitle-input:focus { background: var(--surface2); }
  .doc-subtitle-input::placeholder { color: var(--placeholder); }
  /* 登入/登出：靠右、低調 */
  .account-btn { margin-left: auto; }
  /* 客戶版標題再放大一點 */
  body.readonly .page-title, body.exporting .page-title { font-size: 34px; margin-left: 28px; }  /* 與 logo 拉開、標題往中間 */
  body.readonly .doc-title-input, body.exporting .doc-title-input { font-size: 34px; padding: 0; }
  body.readonly .doc-subtitle-input, body.exporting .doc-subtitle-input { font-size: 16px; padding: 0; }
  /* 正式版：空白副標題不顯示提示文字、整列收合，標題輸入框不顯示 placeholder */
  body.readonly .doc-title-input::placeholder, body.exporting .doc-title-input::placeholder,
  body.readonly .doc-subtitle-input::placeholder, body.exporting .doc-subtitle-input::placeholder { color: transparent; }
  body.readonly .doc-subtitle-input:placeholder-shown,
  body.exporting .doc-subtitle-input:placeholder-shown,
  /* box1 留空時客戶版／列印不留空格（box2 永遠有值不受影響）*/
  body.readonly .doc-title-input:placeholder-shown,
  body.exporting .doc-title-input:placeholder-shown { display: none !important; }
  body.readonly .brand-logo, body.exporting .brand-logo { height: 34px; }

  /* ── Toolbar (settings + actions) ── */
  .toolbar {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 24px;
  }
  .rate-box {
    display: inline-flex;
    align-self: flex-start;
    align-items: center;
    gap: 10px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 8px 14px;
  }
  .rate-box label {
    font-size: 12px;
    color: var(--text2);
    white-space: nowrap;
  }
  .rate-box input {
    width: 80px;
    border: none;
    background: transparent;
    font-family: 'DM Mono', monospace;
    font-size: 16px;
    font-weight: 500;
    color: var(--text);
    text-align: right;
    outline: none;
  }
  .rate-box span {
    font-size: 12px;
    color: var(--text3);
  }

  /* 動作列：左對齊、分組、組間細分隔線 */
  .action-bar {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    padding-top: 12px;
    border-top: 1px solid var(--border);
  }
  .tb-group { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
  .tb-sep { width: 1px; align-self: stretch; min-height: 22px; background: var(--border); margin: 0 4px; }

  /* 「更多」下拉選單 */
  .more-wrap { position: relative; }
  .more-wrap .caret { width: 12px; height: 12px; margin-left: -1px; opacity: .7; }
  .more-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 168px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: 0 8px 24px rgba(0,0,0,.10);
    padding: 5px;
    z-index: 60;
    display: none;
  }
  .more-menu.open { display: block; }
  .more-item {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    text-align: left;
    border: none;
    background: transparent;
    border-radius: var(--radius-sm);
    padding: 8px 10px;
    font-family: 'Noto Sans TC', sans-serif;
    font-size: 13px;
    color: var(--text2);
    cursor: pointer;
    white-space: nowrap;
    transition: background .12s, color .12s;
  }
  .more-item:hover { background: var(--surface2); color: var(--text); }
  .more-item .icon { color: var(--text3); }
  .more-sep { height: 1px; background: var(--border); margin: 5px 8px; }

  /* ── Meta (client / quote info) ── */
  .meta-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 12px;
    margin-bottom: 24px;
  }
  .meta-field {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 10px 14px;
  }
  .meta-field label {
    display: block;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.05em;
    color: var(--text3);
    margin-bottom: 5px;
  }
  .meta-field input, .meta-field textarea {
    width: 100%;
    border: none;
    background: transparent;
    font-family: 'Noto Sans TC', sans-serif;
    font-size: 15px;
    color: var(--text);
    outline: none;
  }
  /* 公司名可換行：textarea 隨內容自動長高（field-sizing 為主，rows=1 當退路） */
  .meta-field textarea {
    resize: none;
    line-height: 1.4;
    field-sizing: content;
    overflow: hidden;
  }
  .meta-field input::placeholder, .meta-field textarea::placeholder { color: var(--placeholder); }
  .meta-field .valid-hint { font-size: 11px; color: var(--text3); margin-top: 4px; }

  /* ── Summary cards ── */
  .summary {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
    margin-bottom: 8px;
  }
  .items-line { font-size: 12px; color: var(--text3); text-align: right; margin-bottom: 24px; }
  .items-line span { font-family: 'DM Mono', monospace; color: var(--text2); }
  /* 報價單號（正式版顯示於右上、列印區附近） */
  .doc-no { display: none; }
  body.readonly .doc-no, body.exporting .doc-no {
    display: block; text-align: right; font-family: 'DM Mono', monospace;
    font-size: 13px; color: var(--text2); margin-bottom: 8px;
  }
  .s-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 16px 20px;
  }
  .s-label {
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.02em;   /* text-transform:uppercase 對中文無效已移除；tracking 收窄避免中文字被拉開成「假英文 eyebrow」 */
    color: var(--text3);
    margin-bottom: 8px;
  }
  .s-value {
    font-family: 'DM Mono', monospace;
    font-size: 26px;
    font-weight: 500;
    color: var(--text);
    line-height: 1;
  }
  .s-value.green { color: var(--accent); }

  /* ── Phase block ── */
  .phase {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    margin-bottom: 14px;
    overflow: hidden;
  }
  .phase-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 18px;
    background: var(--surface2);
    border-bottom: 1px solid var(--border);
  }
  .phase-color { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
  .phase-name-input {
    flex: 1;
    min-width: 80px;
    font-family: 'Noto Sans TC', sans-serif;
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
    background: transparent;
    border: none;
    outline: none;
  }
  .phase-meta {
    font-family: 'DM Mono', monospace;
    font-size: 12px;
    color: var(--text3);
    white-space: nowrap;
  }
  .phase-btns { display: flex; gap: 6px; }

  .table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

  /* ── Buttons ── */
  .btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border: 1px solid var(--border);
    background: var(--surface);
    border-radius: var(--radius-sm);
    padding: 6px 11px;
    font-family: 'Noto Sans TC', sans-serif;
    font-size: 12px;
    color: var(--text2);
    cursor: pointer;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
    white-space: nowrap;
  }
  .btn:hover { background: var(--surface2); color: var(--text); }
  .btn.danger { color: var(--danger); border-color: #f0bebe; }
  .btn.danger:hover { background: var(--danger-light); }
  .btn.primary {
    background: var(--accent);
    color: white;
    border-color: var(--accent);
    font-weight: 500;
  }
  .btn.primary:hover { background: var(--accent-text); border-color: var(--accent-text); }
  .btn.ghost {
    border: 1.5px dashed var(--border2);
    color: var(--text3);
    background: transparent;
  }
  .btn.ghost:hover { color: var(--text); border-color: var(--text3); background: var(--surface2); }
  .phase-head .btn { background: transparent; }
  .phase-head .btn:hover { background: var(--surface); }

  /* ── Table ── */
  table { width: 100%; border-collapse: collapse; min-width: 720px; }
  thead tr { border-bottom: 1px solid var(--border); }
  th {
    padding: 8px 16px;
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text3);
    text-align: left;
  }
  th.r { text-align: right; }
  td {
    padding: 10px 16px;
    font-size: 14.5px;
    color: var(--text);
    border-bottom: 1px solid var(--border);
    vertical-align: middle;   /* 項目折成 2–3 行時，其他欄（說明/數量/單位/單價/金額）垂直置中對齊整列 */
  }
  tr:last-child td { border-bottom: none; }
  tbody tr:hover td { background: #fafaf8; }
  td.r { text-align: right; }
  td.mono {
    font-family: 'DM Mono', monospace;
    font-size: 14px;
  }
  td.price-cell {
    font-family: 'DM Mono', monospace;
    font-size: 14px;
    text-align: right;
    font-weight: 500;
    color: var(--accent-text);
    white-space: nowrap;   /* NT$ 與金額不換行，避免長金額時 NT$ 跑到上一行 */
  }
  td.idx { color: var(--text3); font-size: 12px; width: 36px; }

  .td-edit {
    border: none;
    background: transparent;
    font-family: 'Noto Sans TC', sans-serif;
    font-size: 14.5px;
    color: var(--text);
    width: 100%;
    outline: none;
    resize: none;
    overflow: hidden;
    line-height: 1.5;
    padding: 1px 0;
  }
  .td-edit:focus { color: var(--accent-text); }
  .del-btn {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text3);
    font-size: 16px;
    line-height: 1;
    padding: 2px 4px;
    border-radius: 4px;
    transition: color 0.12s, background 0.12s;
  }
  .del-btn:hover { color: var(--danger); background: var(--danger-light); }

  .add-row-row { border-top: 1px solid var(--border); }
  .add-row-row td { padding: 0; }
  .add-row-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    padding: 9px 16px;
    font-family: 'Noto Sans TC', sans-serif;
    font-size: 12px;
    color: var(--text3);
    background: transparent;
    border: none;
    cursor: pointer;
    transition: background 0.12s, color 0.12s;
  }
  .add-row-btn:hover { background: #f9f8f5; color: var(--text); }

  /* ── 補充明細表（自訂欄位的附表，純說明、不計入總額）── */
  .supplement { margin-top: 22px; }
  .sup-title { font-weight: 600; }
  .sup-table th { text-transform: none; letter-spacing: 0; font-size: 12.5px; font-weight: 600; color: var(--text2); position: relative; white-space: nowrap; }
  .sup-colh {
    border: none; background: transparent; font: inherit; color: inherit;
    width: 100%; min-width: 56px; outline: none; padding: 1px 14px 1px 0; font-weight: 600;
  }
  .sup-colh.r { text-align: right; padding-right: 0; }   /* 數字欄表頭靠右，與資料格對齊（右內距歸 0；刪欄 ✕ 在更右側不重疊）*/
  .sup-colh:focus { color: var(--accent-text); }
  .sup-coldel {
    position: absolute; top: 4px; right: 4px; font-size: 11px; line-height: 1;
    padding: 2px 4px; opacity: 0; transition: opacity 0.12s;
  }
  .sup-table th:hover .sup-coldel { opacity: 1; }
  .sup-table td { vertical-align: middle; }
  .sup-cell {
    border: none; background: transparent; font-family: 'Noto Sans TC', sans-serif;
    font-size: 14.5px; color: var(--text); width: 100%; min-width: 56px; outline: none; padding: 1px 0;
  }
  .sup-cell.r { text-align: right; font-family: 'DM Mono', monospace; font-size: 14px; }
  .sup-cell:focus { color: var(--accent-text); }
  .sup-actcol { width: 30px; }
  /* 補充明細表收合：預設收合（電腦／手機皆是），點標題列展開。收合狀態為暫時 UI 狀態。 */
  .sup-head { cursor: pointer; }
  .sup-toggle {
    background: none; border: none; cursor: pointer; padding: 4px; margin: -4px 2px -4px -4px;
    color: var(--text2); display: inline-flex; align-items: center; flex: 0 0 auto;
  }
  .sup-chevron { transition: transform 0.15s ease; }
  .supplement.collapsed .sup-chevron { transform: rotate(-90deg); }   /* 收合→指向右 */
  .supplement.collapsed .sup-body { display: none; }
  .sup-collapsed-hint { font-size: 12.5px; color: var(--text3); margin-left: 6px; white-space: nowrap; flex: 0 0 auto; }
  .supplement:not(.collapsed) .sup-collapsed-hint { display: none; }   /* 只在收合時顯示「共 N 列」 */

  /* ── Add phase ── */
  .bottom-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 20px;
    flex-wrap: wrap;
    gap: 10px;
  }
  .add-phase-btn {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 11px 18px;
    border: 1.5px dashed var(--border2);
    border-radius: var(--radius);
    background: transparent;
    font-family: 'Noto Sans TC', sans-serif;
    font-size: 13px;
    color: var(--text3);
    cursor: pointer;
    transition: all 0.12s;
    flex: 1;
    justify-content: center;
  }
  .add-phase-btn:hover { color: var(--text); border-color: var(--text3); background: var(--surface); }

  /* ── Billing summary ── */
  /* 印章放在總結金額（billing）左側的空白處 */
  .billing-wrap {
    display: flex; align-items: flex-end; gap: 24px; margin-top: 28px;
  }
  .billing-wrap .stamp-area {
    flex: 1 1 auto; min-width: 0; margin-top: 0;
    align-self: stretch;           /* 撐到與右側 billing 同高，才能垂直置中 */
    justify-content: center;       /* 印章置於左側空白區的水平中間 */
    align-items: center;           /* 垂直中間 */
  }
  .billing-wrap .billing { margin-top: 0; margin-left: 0; flex: 0 0 auto; }
  .billing {
    margin-top: 28px;
    margin-left: auto;
    max-width: 380px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 6px 20px;
  }
  .bill-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 11px 0;
    border-bottom: 1px solid var(--border);
    font-size: 13.5px;
    color: var(--text2);
  }
  .bill-row:last-child { border-bottom: none; }
  .bill-row label { display: flex; align-items: center; gap: 6px; }
  .bill-row .pct-input {
    width: 58px;
    border: 1px solid var(--border);
    background: var(--surface2);
    border-radius: var(--radius-sm);
    font-family: 'DM Mono', monospace;
    font-size: 13px;
    color: var(--text);
    text-align: right;
    outline: none;
    padding: 2px 5px;
  }
  .bill-row .pct-input:focus { border-color: var(--accent); }
  /* 折扣/四捨五入/訂金 數字框依內容自動長寬，「元」模式填大金額不被截（小數字維持 min-width 不縮）；舊瀏覽器退回 58px 固定寬 */
  @supports (field-sizing: content) {
    .bill-row .pct-input { field-sizing: content; width: auto; min-width: 48px; max-width: 12ch; }
  }
  /* 折扣/訂金 單位切換 %／元 */
  .bill-row .unit-sel {
    margin-left: 4px; border: 1px solid var(--border); background: var(--surface2);
    border-radius: var(--radius-sm); font-family: 'Noto Sans TC', sans-serif; font-size: 13px;
    color: var(--text2); padding: 2px 2px; cursor: pointer; outline: none;
  }
  .bill-row .unit-sel:focus { border-color: var(--accent); }
  body.readonly .unit-sel, body.exporting .unit-sel { border-color: transparent; background: transparent; -webkit-appearance: none; appearance: none; padding: 0; margin-left: 1px; width: auto; color: var(--text2); }
  /* 客戶版／匯出：折扣·訂金 數字框變純文字（去框、縮到內容寬、隱藏箭頭），讀起來像「折扣 10%」而非可編輯欄 */
  body.readonly .bill-row .pct-input, body.exporting .bill-row .pct-input {
    border-color: transparent; background: transparent; padding: 0; min-width: 0;
    width: 3.2ch; field-sizing: content; text-align: right;  /* 支援 field-sizing(Chromium)→縮到內容；否則用 3.2ch 約等寬 */
  }
  body.readonly .bill-row .pct-input::-webkit-inner-spin-button,
  body.readonly .bill-row .pct-input::-webkit-outer-spin-button,
  body.exporting .bill-row .pct-input::-webkit-inner-spin-button,
  body.exporting .bill-row .pct-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
  .bill-row input[type=checkbox] { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
  /* 客戶版／匯出：隱藏營業稅勾選框，讓「營業稅 5%」與小計/總額左緣對齊（不被勾選框推右）*/
  body.readonly .bill-row label input[type=checkbox], body.exporting .bill-row label input[type=checkbox] { display: none; }
  .bill-val {
    font-family: 'DM Mono', monospace;
    font-size: 14px;
    font-weight: 500;
    color: var(--text);
    white-space: nowrap;
  }
  .bill-val.neg { color: var(--danger); }
  .bill-row.total { padding: 14px 0; }
  .bill-row.total span:first-child { font-size: 14px; font-weight: 600; color: var(--text); }
  .bill-row.total .bill-val { font-size: 19px; }
  .bill-val.green { color: var(--accent); }
  .bill-row.deposit { color: var(--text3); }
  /* 客戶版／匯出列印：折扣/四捨五入/訂金 為 0 的列隱藏，畫面更整齊（編輯時恆顯示）*/
  body.readonly .bill-row.is-zero, body.exporting .bill-row.is-zero { display: none !important; }

  /* ── SVG icons ── */
  .icon { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; vertical-align: middle; flex-shrink: 0; }
  .icon-lg { width: 16px; height: 16px; }

  /* ── Saved indicator ── */
  .saved-dot {
    font-size: 11px;
    color: var(--text3);
    display: inline-flex;
    align-items: center;
    gap: 5px;
  }
  .saved-dot::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }

  /* ── Read-only (viewer) mode ── */
  body.readonly .editor-only,
  body.readonly .phase-btns,
  body.readonly .add-row-btn,
  body.readonly .add-row-row,
  body.readonly .add-phase-btn,
  body.readonly .bottom-actions,
  body.readonly .del-cell,
  body.readonly .del-btn,
  body.readonly .reset-wrap { display: none !important; }
  body.readonly .rate-box,
  body.readonly .meta-field { background: transparent; }
  body.readonly input:not(#entryCode),
  body.readonly textarea,
  body.readonly select { pointer-events: none; }   /* select 也鎖（客戶／已封存皆不可改狀態等下拉） */
  body.readonly .td-edit:focus { border-color: transparent; background: transparent; color: var(--text); }
  /* empty meta fields shouldn't show placeholder in viewer */
  body.readonly .meta-field input::placeholder { color: transparent; }

  /* 正式版（客戶檢視 / PDF / 列印）：把填寫用的「格子」變成乾淨文字、隱藏編輯工具
     （排除查詢頁的編號輸入框 #entryCode，它需要保留可見邊框） */
  body.readonly input:not(#entryCode), body.readonly textarea, body.readonly select,
  body.exporting input, body.exporting textarea, body.exporting select {
    border: none !important; background: transparent !important; box-shadow: none !important;
    -webkit-appearance: none; appearance: none; color: var(--text);
  }
  body.readonly .num-input, body.exporting .num-input { border-color: transparent !important; }
  /* 預設單價/幣別是編輯者工具，非報價內容 → 正式版隱藏 */
  body.readonly .rate-box, body.exporting .rate-box { display: none !important; }
  /* 正式版：上方欄位去掉方框，變乾淨「標籤：值」排版 */
  body.readonly .meta-field, body.exporting .meta-field {
    border: none !important; background: transparent !important; padding: 2px 0 !important;
  }
  body.readonly .meta-field label, body.exporting .meta-field label { margin-bottom: 1px; }
  body.readonly .meta-field input, body.readonly .meta-field select,
  body.exporting .meta-field input, body.exporting .meta-field select { padding: 0 !important; font-weight: 500; }
  /* 客戶版／匯出：客戶公司名稱改用可換行的純文字（input 無法換行，長名稱會被截斷）*/
  .meta-ro-val { display: none; }
  body.readonly .meta-field #m_client, body.exporting .meta-field #m_client { display: none; }
  body.readonly .meta-field .meta-ro-val, body.exporting .meta-field .meta-ro-val {
    display: block; white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word;
    font-size: 16px; font-weight: 500; color: var(--text); line-height: 1.45;
  }
  /* 單號改放右上（列印區旁），meta 裡的單號欄在正式版隱藏 */
  body.readonly #metaQuoteNo, body.exporting #metaQuoteNo { display: none !important; }
  /* 空白欄位（如未填統編）不顯示空框 */
  body.readonly .meta-field.meta-empty, body.exporting .meta-field.meta-empty { display: none !important; }
  /* 隱藏日期挑選器圖示，讓日期像純文字 */
  body.readonly input[type=date]::-webkit-calendar-picker-indicator,
  body.exporting input[type=date]::-webkit-calendar-picker-indicator { display: none; }
  /* iOS Safari 的 type=date 在隱藏挑選器圖示後會把日期值置中 → 強制靠左，和其他欄位(聯絡人/天數/統編)切齊 */
  body.readonly .meta-field input[type=date]::-webkit-date-and-time-value,
  body.exporting .meta-field input[type=date]::-webkit-date-and-time-value { text-align: left; margin: 0; }
  body.readonly .meta-field input[type=date]::-webkit-datetime-edit,
  body.exporting .meta-field input[type=date]::-webkit-datetime-edit { padding: 0; }
  /* 客戶版：文件字體放大，更清楚正式 */
  body.readonly td, body.readonly .td-edit { font-size: 15px; }
  /* 客戶版（螢幕）說明/項目截字修正：autoH 在 web font(Noto Sans TC) 載入前就算高 → 少一行被截。
     比照匯出用 field-sizing 讓 textarea 依實際渲染寬度自動長高（Chromium）；非支援瀏覽器由
     app.js 的 document.fonts.ready 補算 autoH 兜底。height:auto 蓋掉 autoH 搶跑留下的 inline 值。 */
  body.readonly .td-edit { field-sizing: content; height: auto !important; }
  body.readonly td.price-cell, body.readonly .num-input { font-size: 14.5px; }
  body.readonly .meta-field input, body.readonly .meta-field select { font-size: 16px; }
  body.readonly .meta-field label { font-size: 12px; }
  body.readonly .doc-footer { font-size: 16px; }

  /* 匯出（列印＋email PDF）字級放大貼齊客戶慣用的紙本範本（內文 ~13.5pt）、A4 印出來一目瞭然：
     明細/內文 18px、總額最大最粗、表頭與標籤次之。放在 readonly 規則之後以勝出。 */
  body.exporting td, body.exporting .td-edit { font-size: 18px; line-height: 1.45; }
  /* 關鍵：textarea 高度原靠 JS autoH 在「螢幕寬度」算，但 PDF 用「列印寬度」欄位更窄 → 高度不夠被截。
     改用 field-sizing 讓 textarea 在實際渲染寬度自動長高（height:auto 蓋掉 autoH 的 inline 值）。 */
  body.exporting .td-edit { field-sizing: content; height: auto !important; }
  body.exporting td.price-cell, body.exporting .num-input { font-size: 18px; }
  body.exporting thead th { font-size: 14px; }
  body.exporting .meta-field input, body.exporting .meta-field select, body.exporting .meta-field .meta-ro-val { font-size: 18px; }
  body.exporting .meta-field label { font-size: 14px; }
  body.exporting .phase-name-input { font-size: 18px; }
  body.exporting .phase-meta { font-size: 13.5px; }
  body.exporting .bill-row { font-size: 17px; }
  body.exporting .bill-row.total span:first-child { font-size: 18px; font-weight: 700; }
  body.exporting .bill-row.total .bill-val { font-size: 24px; font-weight: 800; }   /* 總額最大最粗 */
  body.exporting .doc-footer { font-size: 16.5px; }
  body.exporting .page-title, body.exporting .doc-title-input { font-size: 44px; }   /* 大標 33pt 貼齊參考單 */

  /* hide controls while capturing PDF（編輯工具一律不進 PDF，與客戶版 readonly 對齊）*/
  body.exporting .editor-only,
  body.exporting .action-bar,
  body.exporting .toolbar,
  body.exporting .bottom-actions,
  body.exporting .reset-wrap,
  body.exporting .phase-btns,
  body.exporting .add-row-row,
  body.exporting .sup-coldel,
  body.readonly .sup-actcol, body.exporting .sup-actcol,
  body.exporting .customer-print,
  body.exporting .account-btn,           /* 登入／登出鈕 */
  body.exporting .sup-toggle,            /* 展開時：收合鈕/提示不進 PDF */
  body.exporting .sup-collapsed-hint,
  body.exporting .del-cell { display: none !important; }
  /* 列印／PDF：收合的補充明細表整張不印（需要才展開→才會印出來） */
  body.exporting .supplement.collapsed { display: none !important; }

  /* 匯出 PDF / 列印：整份報價單加外框＋內距（讓整張有框、不貼邊）*/
  body.exporting .page {
    border: 1.5px solid var(--border2);
    border-radius: 8px;
    padding: 16px 18px;
    background: var(--surface);
  }
  /* 匯出共用（列印＋email 截圖）：解除表格 720 最小寬、縮格內距 → 字相對放大、欄位不被截 */
  body.exporting table { min-width: 0 !important; }
  body.exporting th, body.exporting td { padding-left: 8px !important; padding-right: 8px !important; }
  /* email PDF 走 html2canvas 截 .page（螢幕 media，不受 @page/viewport 影響）→ 鎖固定寬，
     讓 jsPDF 放大到 A4 時字級穩定一致（不隨寄送者視窗寬度飄移），比照列印的內容寬。 */
  body.pdfshot .page { width: 720px !important; max-width: 720px !important; }

  /* 客戶版（唯讀）右下固定「列印 / 存 PDF」鈕 */
  .customer-print {
    position: fixed; right: 22px; bottom: 22px; z-index: 50;
    display: none; align-items: center; gap: 7px;
    background: var(--accent); color: #fff; border: none; border-radius: 24px;
    padding: 11px 20px; font-size: 14px; font-weight: 600; cursor: pointer;
    box-shadow: 0 4px 14px rgba(0,0,0,0.18);
  }
  .customer-print:hover { background: var(--accent-text); }
  body.readonly .customer-print { display: inline-flex; }

  /* ── 列印（含瀏覽器「儲存成 PDF」）── */
  @media print {
    /* margin:0 → Chrome 沒有頁邊空間可畫「日期/檔名」頁首頁尾 → 不再出現；
       紙張留白改由 .page 自身 padding 補回（橫向每頁都有）。 */
    @page { margin: 0; }
    body { padding: 0 !important; background: #fff !important; }
    .page { max-width: none !important; margin: 0 auto !important; padding: 12mm !important; }
    /* 多頁表格分頁（避免整塊被推到下一頁留大空白）：表頭每頁重複、單列不裂開、階段可跨頁 */
    thead { display: table-header-group; }
    tr { break-inside: avoid; page-break-inside: avoid; }
    .phase { overflow: visible !important; break-inside: auto; page-break-inside: auto; }
    .customer-print, #toast, .page-loading, .toolbar, .account-btn { display: none !important; }
    /* 列印只留「已完成的簽名」(.accept-done)；互動式簽名板／待簽提示／客戶訊息一律不印
       （不依賴 body.exporting，避免 beforeprint 未套上時簽名板漏印） */
    .accept-box, .accept-pending, .accept-done-msg { display: none !important; }
    * { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; }
  }
  /* 正式版：補充明細表的空白欄位不顯示 placeholder */
  body.readonly .sup-title::placeholder, body.exporting .sup-title::placeholder,
  body.readonly .sup-colh::placeholder, body.exporting .sup-colh::placeholder,
  body.readonly .sup-cell::placeholder, body.exporting .sup-cell::placeholder { color: transparent; }

  /* ── Responsive ── */
  @media (max-width: 720px) {
    body { padding: 22px 12px 64px; }
    /* 標題在手機：縮字級＋佔滿整行。文字其實裝在 input 裡(無法換行,字太長只會被裁切)，
       故 .page-title 與 .doc-title-input 都要縮，且客戶版(readonly)原本固定 34px 必須一起降，
       否則手機仍以 34px 渲染、長標題右側被切掉。 */
    .brand-head { gap: 10px 14px; }
    .page-title { flex: 1 1 100%; min-width: 100%; font-size: 22px; }
    .doc-title-input { font-size: 22px; }
    body.readonly .page-title { font-size: 25px; }
    body.readonly .doc-title-input { font-size: 25px; }
    .rate-box { align-self: stretch; justify-content: space-between; }
    .rate-box input { width: 110px; }
    /* 手機版：隱藏分隔線，按鈕填滿排列 */
    .tb-sep { display: none; }
    .tb-group { flex: 1 1 100%; gap: 8px; }
    .action-bar .btn { flex: 1 1 auto; justify-content: center; min-height: 44px; }  /* 觸控目標 ≥44px */
    .more-wrap { flex: 1 1 auto; display: flex; }
    .more-wrap > .btn { width: 100%; }
    .more-menu { left: 0; right: 0; }
    /* 客戶版「列印/存PDF」鈕：手機不用 fixed 浮層（會蓋住品項/金額），改回正常流置於文件末端置中。
       列印是「看完再做」的終點動作，捲到底自然看到，且完全不遮擋內容。 */
    body.readonly .customer-print {
      position: static; display: flex; width: fit-content; margin: 20px auto 4px;
      right: auto; left: auto; bottom: auto; transform: none; min-height: 44px;
    }
    .meta-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
    .meta-grid > .meta-field:first-child { grid-column: 1 / -1; }  /* 客戶/公司 跨整列(名稱長、最重要) */
    .summary { grid-template-columns: 1fr; gap: 10px; }
    .s-card { display: flex; align-items: baseline; justify-content: space-between; padding: 13px 16px; }
    .s-label { margin-bottom: 0; }
    .s-value { font-size: 22px; }
    .billing { max-width: none; }
    /* 窄螢幕：印章與總結金額改為上下堆疊 */
    .billing-wrap { flex-wrap: wrap; }
    .billing-wrap .billing { width: 100%; }
    .billing-wrap .stamp-area { flex-basis: 100%; justify-content: space-evenly; }

    .phase { margin-bottom: 12px; }
    /* phase header: title full-width, buttons + meta below */
    .phase-head { flex-wrap: wrap; row-gap: 5px; padding: 12px 14px; }
    /* 字級階層(手機)：階段標題 17 > 項目名 15.5 > 數量/單價 15 > 說明 14 > 標籤 11 */
    .phase-name-input { flex: 1 1 100%; order: 1; font-size: 17px; }
    .phase-btns { order: 2; margin-left: 19px; }
    .phase-meta { order: 3; margin-left: auto; }
    .phase-head .btn { min-height: 38px; }

    /* table → one card per row */
    .table-scroll { overflow: visible; }
    table { min-width: 0; }
    thead { display: none; }
    table, tbody, tfoot, tr, td { display: block; width: auto; }
    tbody tr {
      position: relative;
      margin: 8px 10px;
      padding: 26px 12px 10px;
      border: 1px solid var(--border);
      border-radius: var(--radius-sm);
      background: var(--surface);
    }
    tbody tr:hover td { background: transparent; }
    tbody td {
      border: none;
      padding: 4px 0;
      display: flex;
      align-items: flex-start;
      gap: 10px;
    }
    tbody td::before {
      content: attr(data-label);
      flex: 0 0 58px;
      font-size: 11px;
      color: var(--text3);
      padding-top: 4px;
    }
    td.idx {
      position: absolute; top: 8px; left: 12px; padding: 0;
      display: block; font-size: 11px; font-weight: 600; color: var(--text3);
      white-space: nowrap;   /* 維持左上，只是「項目 ⠿ N」不折行（原本 36px 寬會被擠成兩行「項目」/「⠿ 1」） */
    }
    td.idx::before { content: '項目 '; }
    td.del-cell { position: absolute; top: 3px; right: 4px; padding: 0; display: block; }
    .del-btn { font-size: 18px; padding: 7px 9px; }
    td.r, td.price-cell { text-align: left; }
    td.price-cell { font-size: 14px; }
    /* 數量·單位·單價·金額：壓成一條橫向帶(label 上、值下、4 格並排)，取代各佔一行 → 卡片更矮 */
    tbody td[data-label="數量"], tbody td[data-label="單位"],
    tbody td[data-label="單價"], tbody td[data-label="金額"] {
      display: inline-flex; flex-direction: column; align-items: flex-start;
      width: auto; gap: 1px; padding: 6px 16px 0 0; vertical-align: top;
    }
    tbody td[data-label="數量"]::before, tbody td[data-label="單位"]::before,
    tbody td[data-label="單價"]::before, tbody td[data-label="金額"]::before { flex: none; padding-top: 0; }
    tbody td[data-label="數量"] .num-input, tbody td[data-label="單價"] .num-input {
      width: 72px; text-align: left; padding-left: 0; font-size: 15px;
    }
    tbody td[data-label="單位"] .num-input.unit { width: 56px; padding-left: 0; }
    /* 單位/數量/單價字較長時自動加寬，帶狀區放不下會折行(支援 field-sizing 的瀏覽器；其餘維持固定寬) */
    @supports (field-sizing: content) {
      tbody td[data-label="單位"] .num-input.unit { field-sizing: content; width: auto; min-width: 36px; max-width: 40vw; }
      tbody td[data-label="數量"] .num-input, tbody td[data-label="單價"] .num-input {
        field-sizing: content; width: auto; min-width: 48px; max-width: 40vw;
      }
    }
    /* 金額：獨立成卡片最後一行、靠右下（原本擠在數量/單位/單價同一帶尾端，窄螢幕會 wrap 到左下不好看） */
    tbody td[data-label="金額"].price-cell {
      display: flex; width: 100%; flex-direction: row; align-items: baseline;
      justify-content: flex-end; gap: 8px;
      padding: 3px 0 0; margin-top: 0;
      font-size: 17px; font-weight: 600;
    }
    .td-edit { font-size: 15px; }
    /* 項目名＝卡片主標(加粗)；說明＝次要內文(縮小、降一階灰色) */
    tbody td[data-label="項目"] .td-edit { font-size: 15.5px; font-weight: 600; }
    tbody td[data-label="說明"] .td-edit { font-size: 14px; color: var(--text2); }
    /* ── 客戶版(readonly)：卡片更緊湊，去除浪費的空間 ──
       編輯者手機版維持原樣（需要標籤與空欄位來編輯）；以下只壓縮客戶實際看到的版面。 */
    body.readonly tbody tr { padding: 26px 14px 12px; }
    body.readonly td.idx { top: 9px; }
    body.readonly tbody td { padding: 3px 0; }
    /* 空的說明／單位不佔行（render 時標 .ro-empty） */
    body.readonly tbody td.ro-empty { display: none; }
    /* 項目名前的「項目」標籤與左上「項目 N」重複 → 客戶版隱藏，項目名靠左對齊；
       並與上方「項目 N」拉開間距（否則兩者貼太緊、顯得擁擠）。 */
    body.readonly tbody td[data-label="項目"]::before { display: none; }
    body.readonly tbody td[data-label="項目"] { padding-top: 5px; }
    /* 說明：客戶版隱藏標籤，讓內文佔滿整行可換行（否則被 58px 標籤擠到右側、長字被截斷） */
    body.readonly tbody td[data-label="說明"]::before { display: none; }
    body.readonly tbody td[data-label="說明"] .td-edit { width: 100%; }
    /* 數量/單位/單價帶狀區：壓低上方留白 */
    body.readonly tbody td[data-label="數量"],
    body.readonly tbody td[data-label="單位"],
    body.readonly tbody td[data-label="單價"] { padding-top: 2px; }
    body.readonly tbody td[data-label="金額"].price-cell { padding-top: 2px; margin-top: 2px; }
    .add-row-btn { min-height: 44px; justify-content: center; }
    .add-phase-btn { min-height: 50px; }

    /* ── 補充明細表（手機版）──
       表頭(thead)在手機被隱藏 → 用 data-label(欄名) 當各值的行內標籤；每列一張卡，
       第一欄為卡片主標、其餘欄為「標籤 ─ 值(靠右)」；第一欄空的摘要列(總計/平均)改色塊。 */
    /* 收合標題列：chevron＋標題＋提示同一行（蓋掉手機版 phase-name-input 的 flex:1 1 100%）*/
    .sup-head { align-items: center; }
    .sup-head .sup-title { flex: 1 1 auto; min-width: 0; order: 0; font-size: 16px; }
    .sup-table tbody tr { padding: 14px 16px; }
    .sup-table tbody td { padding: 3px 0; gap: 12px; align-items: baseline; }
    .sup-table tbody td::before {
      content: attr(data-label);
      flex: 0 0 88px; font-size: 12px; color: var(--text3); padding-top: 0; white-space: nowrap;
    }
    .sup-table tbody td.sup-name { display: block; margin-bottom: 4px; }
    .sup-table tbody td.sup-name::before { display: none; }
    .sup-table tbody td.sup-name .sup-cell { font-size: 16px; font-weight: 600; width: 100%; text-align: left; padding-left: 0; }
    .sup-table tbody td.r { display: flex; }
    .sup-table tbody td.r .sup-cell.r { flex: 1 1 auto; width: auto; text-align: right; padding-right: 0; }
    /* 空值欄不佔行（客戶版；編輯者仍可編輯空格） */
    body.readonly .sup-table tbody td.sup-empty { display: none; }
    /* 摘要列：色塊，文字左、數字右靠齊，不顯示欄名標籤 */
    .sup-table tbody tr.sup-summary {
      display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
      padding: 12px 16px; background: #efeee9; border-color: #e2e0d8;
    }
    .sup-table tbody tr.sup-summary td { padding: 0; }
    .sup-table tbody tr.sup-summary td::before { display: none; }
    body.readonly .sup-table tbody tr.sup-summary td.sup-empty { display: none; }
    .sup-table tbody tr.sup-summary .sup-cell { width: auto; font-weight: 600; font-size: 15px; text-align: left; }
    @supports (field-sizing: content) {
      .sup-table tbody tr.sup-summary .sup-cell { field-sizing: content; }
    }
  }
  @media (max-width: 340px) {
    .meta-grid { grid-template-columns: 1fr; }   /* 極窄機才退回單欄 */
  }

  /* ── v2: 數量 / 單位 / 單價 欄位 ── */
  .num-input {
    width: 100%; border: 1px solid transparent; background: transparent;
    font-family: 'DM Mono', monospace; font-size: 14px; color: var(--text);
    text-align: right; outline: none; border-radius: var(--radius-sm);
    padding: 2px 4px; transition: border-color 0.12s;
  }
  /* 數量/單價填滿欄位 → 右對齊數字與右對齊表頭(及金額欄)對齊 */
  .num-input.unit { width: 56px; text-align: left; font-family: 'Noto Sans TC', sans-serif; border-bottom: 1px dashed var(--border); border-radius: 0; }
  .num-input.unit:hover { border-bottom-color: var(--border2); background: var(--surface2); }
  body.readonly .num-input.unit, body.exporting .num-input.unit { border-bottom-color: transparent; background: transparent; }
  .num-input.price { width: 100%; }
  /* 隱藏數字輸入框上下箭頭(spinner)，避免吃掉寬度造成數字被截斷 */
  .num-input[type=number]::-webkit-inner-spin-button,
  .num-input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
  .num-input[type=number] { -moz-appearance: textfield; appearance: textfield; }
  .num-input:focus { border-color: var(--border2); background: var(--surface2); }
  /* 數量/單價依內容自動長寬，5 位數以上不被截斷（小數字也會縮回）；不支援 field-sizing 的舊瀏覽器退回固定寬欄 */
  @supports (field-sizing: content) {
    .num-input:not(.unit) { field-sizing: content; width: auto; min-width: 3ch; max-width: 14ch; }
  }
  .rate-box .unit-mini {
    width: 48px; border: none; background: transparent;
    font-family: 'Noto Sans TC', sans-serif; font-size: 14px; color: var(--text); outline: none;
  }
  .rate-box .cur-sel {
    border: none; background: transparent; font-family: 'DM Mono', monospace; font-size: 14px;
    color: var(--text2); outline: none; cursor: pointer; padding-right: 2px; margin-right: 2px;
    border-right: 1px solid var(--border);
  }

  /* drag handle */
  .drag-handle { cursor: grab; color: var(--border2); font-size: 13px; padding: 0 2px; user-select: none; }
  .drag-handle:hover { color: var(--text3); }
  tr.dragging { opacity: 0.4; }
  tr.drag-over td { box-shadow: inset 0 2px 0 var(--accent); }

  /* status badge + meta select */
  .status-badge {
    display: inline-block; font-size: 11px; font-weight: 600; padding: 2px 10px;
    border-radius: 20px; vertical-align: middle; margin-left: 10px;
  }
  /* 狀態徽章移到標題下方獨立一行(原本浮在標題右上、與登出鈕擠在一起) */
  .status-line { margin: 2px 0 10px; }
  .status-line .status-badge { margin-left: 0; }
  .status-draft { background: var(--surface2); color: var(--text2); }
  .status-sent { background: #e6eef7; color: #1f5aa8; }
  .status-accepted { background: var(--accent-light); color: var(--accent-text); }
  .status-expired { background: var(--danger-light); color: var(--danger); }
  .status-archived { background: #e2e5ea; color: #4b5563; }   /* 已封存：中性石板灰，與草稿(暖灰)區隔 */

  /* 已封存橫幅（只在編輯者開啟已封存單據時由 JS 顯示）：提示鎖定＋提供 返回後台／解除封存 */
  .archived-bar {
    display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
    margin-bottom: 16px; padding: 12px 16px;
    background: #eef0f3; border: 1px solid #d6dae0; border-radius: var(--radius);
  }
  .archived-bar-label { font-size: 13.5px; color: #4b5563; font-weight: 500; }
  .archived-bar-acts { display: flex; gap: 8px; flex-shrink: 0; }
  @media print { .archived-bar { display: none !important; } }
  .valid-hint.expired { color: var(--danger); font-weight: 600; }
  select.meta-select {
    width: 100%; border: none; background: transparent;
    font-family: 'Noto Sans TC', sans-serif; font-size: 14px; color: var(--text);
    outline: none; cursor: pointer;
  }

  /* template cards */
  .tpl-card {
    display: block; width: 100%; text-align: left; cursor: pointer;
    padding: 14px 16px; border: 1px solid var(--border); background: var(--surface);
    border-radius: var(--radius); margin: 6px; font-family: 'Noto Sans TC', sans-serif;
    transition: border-color 0.12s, background 0.12s;
  }
  .tpl-card:hover { border-color: var(--accent); background: var(--accent-light); }
  .tpl-name { font-size: 15px; font-weight: 600; color: var(--text); margin-bottom: 3px; }
  .tpl-desc { font-size: 12.5px; color: var(--text2); }
  .tpl-meta { font-size: 11px; color: var(--text3); margin-top: 6px; font-family: 'DM Mono', monospace; }
  .tpl-user { position: relative; }
  .tpl-del { position: absolute; top: 8px; right: 8px; width: 22px; height: 22px; border:none; border-radius: 50%; background: var(--danger-light); color: var(--danger); cursor: pointer; font-size: 12px; }
  .tpl-tag { font-size: 10px; font-weight: 600; padding: 1px 6px; border-radius: 10px; background: #e6eef7; color: #1f5aa8; vertical-align: middle; margin-left: 4px; }
  .tpl-tag-full { background: var(--accent-light); color: var(--accent-text); }

  /* ── 印章：報價單上的簽章區 ── */
  .stamp-area {
    display: flex; flex-wrap: wrap; gap: 18px; align-items: flex-end;
    justify-content: center; min-height: 10px; margin-top: 12px;
  }

  /* 客戶確認 / 簽名 */
  .accept-area { margin-top: 22px; }
  .accept-box {
    border: 1px solid var(--accent); border-radius: var(--radius); padding: 18px 20px;
    background: var(--accent-light);
  }
  .accept-title { font-size: 16px; font-weight: 600; color: var(--accent-text); margin-bottom: 4px; }
  .accept-hint { font-size: 13px; color: var(--text2); margin-bottom: 12px; }
  .sig-pad {
    width: 100%; max-width: 600px; height: 180px; display: block;
    background: #fff; border: 1px dashed var(--border2); border-radius: var(--radius-sm);
    touch-action: none; cursor: crosshair;
  }
  /* 打字簽名（無障礙替代）：預設收合，不干擾手寫主流程 */
  .accept-type { margin-top: 10px; font-size: 13px; }
  .accept-type > summary { cursor: pointer; color: var(--accent-text); width: fit-content; }
  .accept-type-row { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
  .accept-type-input {
    flex: 1 1 180px; min-width: 0; min-height: 40px; padding: 6px 10px;
    border: 1px solid var(--border2); border-radius: var(--radius-sm); background: #fff; color: var(--text);
  }
  /* 送出前的明確聲明：與「用簽名承諾一筆金額」的權重相稱 */
  .accept-consent { margin-top: 12px; font-size: 13px; font-weight: 600; color: var(--accent-text); }
  .accept-actions { display: flex; gap: 8px; margin-top: 12px; }
  .accept-done {
    border: 1px solid var(--border); border-radius: var(--radius); padding: 14px 18px; background: var(--surface);
    display: inline-block;
  }
  /* 客戶剛簽完的安心確認訊息 */
  .accept-done-cust { display: block; }
  .accept-done-msg { font-size: 13.5px; color: var(--text2); margin-bottom: 10px; line-height: 1.6; max-width: 46ch; }
  .accept-done-head { font-size: 14px; font-weight: 600; color: var(--accent-text); margin-bottom: 8px; }
  .accept-when { font-family: 'DM Mono', monospace; font-weight: 400; color: var(--text2); font-size: 12.5px; }
  .accept-sig { display: block; height: 80px; width: auto; }
  .accept-pending { font-size: 12.5px; color: var(--text3); padding: 8px 0; }
  /* 匯出 PDF / 列印：只留「已完成的簽名」(含沿用報價簽名)；簽名板／待確認訊息／客戶提示不印 */
  body.exporting .accept-box, body.exporting .accept-pending, body.exporting .accept-done-msg { display: none !important; }
  /* 沿用報價簽名的註記 */
  .accept-carried-note { font-size: 12px; color: var(--text3); margin-top: 8px; }
  /* 沿用簽名後請款單被調整 → 提示需客戶補簽（螢幕＋PDF 皆顯示） */
  .sign-change-banner {
    margin: 18px 0 4px; padding: 10px 14px; border-radius: var(--radius);
    background: var(--danger-light); border: 1px solid #e6b8b8; color: var(--danger);
    font-size: 13.5px; font-weight: 600; line-height: 1.5;
  }
  /* 變更欄位／總額標紅（品項表格 td 與請款總額列）。!important 壓過客戶版/匯出的「格子變乾淨文字」色。 */
  td.chg { background: var(--danger-light) !important; }
  td.chg, td.chg .td-edit, td.chg input, td.chg textarea, td.chg .num-input,
  .bill-row.total.chg .bill-val { color: var(--danger) !important; }
  /* 客戶已補簽 → 橫幅轉為「已確認」的資訊語氣（綠） */
  .sign-change-banner.resolved { background: #eaf5ee; border-color: #b7dcc4; color: var(--accent-text); }
  /* 補簽板／補簽完成：與上方沿用簽名區塊拉開，補簽板加頂線區隔 */
  .accept-resign { margin-top: 14px; border-top: 1px dashed var(--line); padding-top: 14px; }
  .accept-redone { margin-top: 12px; }
  @media print { .accept-box, .accept-pending { display: none !important; } }
  .stamp-applied { position: relative; }
  .stamp-applied img { display: block; height: var(--stamp-h, 96px); width: auto; }
  /* 手機版：印章縮小並強制同一行（桌機維持 --stamp-h 設定的大小）。
     原本 3 枚 ×144px + 18px gap 會超出窄螢幕 → 第 3 枚換行；改每枚上限 28vw、不換行。
     ※ 放在 base 規則之後才壓得過 .stamp-applied img 的 height（同特異度比 source 順序）。 */
  @media (max-width: 720px) {
    .stamp-area { flex-wrap: nowrap; gap: 8px; justify-content: space-evenly; }
    .stamp-applied img { height: auto; width: auto; max-width: 28vw; max-height: var(--stamp-h, 96px); }
  }
  /* 客戶版（唯讀）印章防拷：擋右鍵另存、拖移、手機長按存圖。
     僅 body.readonly 生效（編輯者自己不受限）。注意：螢幕截圖與 DevTools 無法擋。 */
  body.readonly .stamp-applied img {
    pointer-events: none;
    -webkit-user-drag: none;
    user-select: none; -webkit-user-select: none;
    -webkit-touch-callout: none;
  }
  .stamp-ctrl {
    position: absolute; top: -12px; right: -8px; display: none; gap: 3px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 2px 4px;
    box-shadow: 0 2px 6px rgba(0,0,0,0.12); z-index: 5;
  }
  .stamp-applied:hover .stamp-ctrl { display: inline-flex; }
  .stamp-szbtn, .stamp-ctrl .stamp-x {
    width: 20px; height: 20px; border-radius: 50%; border: none; cursor: pointer;
    font-size: 13px; line-height: 1; display: inline-flex; align-items: center; justify-content: center;
  }
  .stamp-szbtn { background: var(--surface2); color: var(--text); }
  .stamp-szbtn:hover { background: var(--accent-light); }
  .stamp-ctrl .stamp-x { background: var(--danger); color: #fff; position: static; }
  body.readonly .stamp-ctrl, body.exporting .stamp-ctrl { display: none !important; }

  /* 印章庫面板 */
  .stamp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; padding: 6px; }
  .stamp-cell {
    position: relative; border: 1px solid var(--border); border-radius: var(--radius);
    background: #fbfbf9; padding: 10px; text-align: center; cursor: pointer;
    transition: border-color 0.12s, background 0.12s;
  }
  .stamp-cell:hover { border-color: var(--accent); background: var(--accent-light); }
  .stamp-cell img { height: 76px; width: auto; max-width: 100%; object-fit: contain; }
  .stamp-cell .stamp-name { font-size: 11px; color: var(--text2); margin-top: 6px; word-break: break-all; }
  .stamp-cell .stamp-del {
    position: absolute; top: 4px; right: 4px; width: 20px; height: 20px; border:none;
    border-radius: 50%; background: var(--danger-light); color: var(--danger); cursor: pointer; font-size: 12px;
  }
  .stamp-upload {
    grid-column: 1 / -1; border: 1.5px dashed var(--border2); border-radius: var(--radius);
    padding: 14px; text-align: center; color: var(--text3); font-size: 13px; cursor: pointer; background: transparent;
  }
  .stamp-upload:hover { color: var(--text); border-color: var(--text3); }

  /* 備註區 */
  .note-block {
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
    padding: 12px 16px; margin-bottom: 14px;
  }
  .note-label { display:block; font-size: 11px; font-weight: 500; letter-spacing: 0.05em; color: var(--text3); margin-bottom: 5px; }
  .note-input {
    width: 100%; border: none; background: transparent; resize: none; overflow: hidden;
    font-family: 'Noto Sans TC', sans-serif; font-size: 13.5px; color: var(--text); outline: none; line-height: 1.6;
  }
  .note-input::placeholder { color: var(--placeholder); }
  body.readonly .note-block:has(.note-input:placeholder-shown) { display: none; }

  /* 報價/請款 切換 */
  .doctype-toggle { display: inline-flex; gap: 0; margin-top: 10px; border: 1px solid var(--border2); border-radius: var(--radius-sm); overflow: hidden; }
  .dt-btn {
    border: none; background: var(--surface); color: var(--text2); cursor: pointer;
    font-family: 'Noto Sans TC', sans-serif; font-size: 13px; padding: 6px 16px; transition: background 0.12s, color 0.12s;
  }
  .dt-btn + .dt-btn { border-left: 1px solid var(--border2); }
  .dt-btn.active { background: var(--accent); color: #fff; font-weight: 600; }

  .qno-row { display: flex; align-items: center; gap: 4px; }
  .qno-row input { flex: 1; min-width: 0; }

  /* 後台總覽 */
  #listOverlay .overlay-box { max-width: 1040px; }
  /* 刪除區 7 欄需要 ~670px，預設 620px 裝不下會被 overflow:hidden 裁掉左緣 → 給足寬度 */
  #recycleOverlay .overlay-box { max-width: 820px; }
  .ql-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 14px; flex-wrap: wrap; border-bottom: 1px solid var(--border); }
  .ql-filters { display: inline-flex; border: 1px solid var(--border2); border-radius: var(--radius-sm); overflow: hidden; }
  .ql-pill { border: none; background: var(--surface); color: var(--text2); cursor: pointer; font-family: 'Noto Sans TC', sans-serif; font-size: 12.5px; padding: 5px 14px; }
  .ql-pill + .ql-pill { border-left: 1px solid var(--border2); }
  .ql-pill.active { background: var(--accent); color: #fff; font-weight: 600; }
  .ql-sum { font-size: 13px; color: var(--text2); font-family: 'DM Mono', monospace; }
  .ql-search { padding: 8px 14px 4px; }
  .ql-search input {
    width: 100%; border: 1px solid var(--border); border-radius: var(--radius-sm);
    padding: 7px 12px; font-family: 'Noto Sans TC', sans-serif; font-size: 13px; color: var(--text); outline: none; background: #fbfbf9;
  }
  .ql-search input:focus { border-color: var(--border2); }
  /* 狀態篩選膠囊 */
  .ql-statusbar { display: flex; flex-wrap: wrap; gap: 6px; padding: 10px 14px 2px; }
  .ql-pill-spacer { flex: 1 1 auto; }   /* 把「已封存」膠囊推到右邊，自成獨立一區 */
  .ql-pill-status {
    display: inline-flex; align-items: center; gap: 6px;
    border: 1px solid var(--border2); border-radius: 999px;
    background: var(--surface); color: var(--text2);
    font-family: 'Noto Sans TC', sans-serif; font-size: 12px; padding: 4px 11px; cursor: pointer;
  }
  .ql-pill-status::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: var(--text3); }
  .ql-pill-status.st-draft::before { background: #b9b7ad; }
  .ql-pill-status.st-sent::before { background: #1f5aa8; }
  .ql-pill-status.st-accepted::before { background: var(--accent); }
  .ql-pill-status.st-archived::before { background: #6b7280; }
  .ql-pill-status.st-expired::before { background: var(--danger); }
  .ql-pill-status:hover { border-color: var(--text3); }
  .ql-pill-status.active { background: var(--text); color: #fff; border-color: var(--text); }
  .ql-pill-n { font-family: 'DM Mono', monospace; font-size: 11px; font-weight: 600; opacity: .65; }
  .ql-pill-status.active .ql-pill-n { opacity: .85; }
  /* 後台彈窗 header 右側按鈕群 */
  .overlay-head-acts { display: inline-flex; align-items: center; gap: 8px; }
  /* 獨立後台分頁（?view=admin）：隱藏編輯頁、彈窗鋪成整頁 */
  body.admin-view .page { display: none; }
  body.admin-view #listOverlay { background: var(--bg); padding: 24px 16px; }
  body.admin-view #listOverlay .overlay-box { max-width: 1180px; max-height: calc(100vh - 48px); box-shadow: none; }
  body.admin-view .popout-only { display: none; }
  /* 標題、客戶名給更多空間（fr 提高）；加寬模態後複製/刪除(ql-acts)也露得出來 */
  .ql-colhead, .ql-row { display: grid; grid-template-columns: 86px minmax(150px, 1.9fr) minmax(120px, 1.5fr) 52px 104px 116px 80px 80px 44px; gap: 10px; align-items: center; padding: 9px 14px; }
  .ql-colhead { font-size: 11px; color: var(--text3); letter-spacing: 0.05em; border-bottom: 1px solid var(--border); }
  .ql-colhead .r, .ql-row .r { text-align: right; }
  .ql-row { border-bottom: 1px solid var(--border); cursor: pointer; font-size: 13.5px; color: var(--text); }
  .ql-row:last-child { border-bottom: none; }
  .ql-row:hover { background: var(--surface2); }
  .ql-type { font-size: 11px; font-weight: 600; padding: 2px 7px; border-radius: 4px; white-space: nowrap; }
  .ql-type.quo { background: var(--accent-light); color: var(--accent-text); }
  .ql-type.inv { background: #e6eef7; color: #1f5aa8; }
  .ql-read { display: inline-block; font-size: 10.5px; font-weight: 600; padding: 1px 6px; border-radius: 10px; background: var(--accent-light); color: var(--accent-text); vertical-align: middle; }

  /* 刪除區：編號 / 客戶 / 類型 / 金額 / 刪除日 / 保留 / 動作 */
  .rc-colhead, .rc-row { grid-template-columns: 86px minmax(90px, 1fr) 52px 116px 96px 64px 64px; }
  .rc-row { cursor: default; }
  .rc-row:hover { background: var(--surface2); }
  .rc-left { font-size: 12px; color: var(--text2); white-space: nowrap; }
  .rc-left.soon { color: var(--danger); font-weight: 600; }

  /* 同統一編號歷史單據：提示按鈕 + 清單列 */
  .siblings-btn {
    display: flex; align-items: center; gap: 8px; width: 100%;
    margin: 0 0 14px; padding: 10px 16px;
    background: var(--accent-light); color: var(--accent-text);
    border: 1px solid var(--accent); border-radius: var(--radius);
    font-size: 13.5px; font-weight: 500; cursor: pointer; text-align: left;
  }
  .siblings-btn:hover { filter: brightness(0.97); }
  .siblings-btn .icon { width: 16px; height: 16px; stroke: currentColor; flex: 0 0 auto; }
  .siblings-btn b { font-weight: 700; }
  .siblings-btn .siblings-arrow { margin-left: auto; font-weight: 600; white-space: nowrap; }
  body.exporting .siblings-btn { display: none !important; }   /* PDF 匯出不要這顆按鈕 */
  .sib-row { grid-template-columns: 56px minmax(180px, 1fr) 92px 116px 84px; align-items: center; }
  .sib-row.sib-current { cursor: default; background: var(--surface2); }
  .sib-row.sib-current:hover { background: var(--surface2); }
  .sib-cur { display: inline-block; font-size: 10.5px; font-weight: 600; padding: 1px 6px; border-radius: 10px; background: var(--border); color: var(--text2); vertical-align: middle; }
  .sib-titles { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
  .sib-title { font-weight: 600; color: var(--text); line-height: 1.35; }
  .sib-sub { font-size: 11.5px; color: var(--text3); line-height: 1.3; overflow: hidden; text-overflow: ellipsis; }
  /* 後台可編輯狀態下拉 */
  .li-status { display: inline-flex; align-items: center; gap: 5px; }
  .ql-status {
    font-family: 'Noto Sans TC', sans-serif;
    font-size: 11.5px; font-weight: 600;
    border: 1px solid var(--border2);
    border-radius: 5px;
    padding: 3px 17px 3px 7px;
    cursor: pointer;
    -webkit-appearance: none; appearance: none;
    max-width: 100%;
    background-color: var(--surface2);
    color: var(--text2);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%236b6960' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat;
    background-position: right 4px center;
  }
  .ql-status:hover { border-color: var(--text3); }
  .ql-status.status-draft { background-color: var(--surface2); color: var(--text2); }
  .ql-status.status-sent { background-color: #e6eef7; color: #1f5aa8; border-color: #c4d6ec; }
  .ql-status.status-accepted { background-color: var(--accent-light); color: var(--accent-text); border-color: #bfe0d0; }
  .ql-status.status-expired { background-color: var(--danger-light); color: var(--danger); border-color: #f0bebe; }
  .ql-expired { font-size: 10px; font-weight: 700; color: var(--danger); white-space: nowrap; }

  /* 儀表板 */
  #dashOverlay .overlay-box { max-width: 640px; }
  .dash-sec { font-size: 12px; font-weight: 600; color: var(--text3); letter-spacing: 0.05em; padding: 14px 16px 6px; }
  .dash-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; padding: 0 14px; }
  .dash-card { border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; background: #fbfbf9; }
  .dash-label { font-size: 11px; color: var(--text3); margin-bottom: 6px; }
  .dash-val { font-family: 'DM Mono', monospace; font-size: 18px; font-weight: 500; color: var(--text); }
  .dash-val.green { color: var(--accent); }
  .dash-val.red { color: var(--danger); }
  .dash-rank { padding: 4px 16px; }
  .dash-rank-row { display: grid; grid-template-columns: 110px 1fr auto; gap: 10px; align-items: center; padding: 5px 0; }
  .dash-rank-name { font-size: 13px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .dash-rank-bar { height: 8px; background: var(--surface2); border-radius: 5px; overflow: hidden; }
  .dash-rank-bar span { display: block; height: 100%; background: var(--accent); border-radius: 5px; }
  .dash-rank-val { font-family: 'DM Mono', monospace; font-size: 12.5px; color: var(--accent-text); white-space: nowrap; }
  .dash-note { font-size: 11px; color: var(--text3); padding: 12px 16px 6px; }
  .ql-acts { display: inline-flex; gap: 2px; justify-content: flex-end; }
  .ql-act { border: none; background: transparent; cursor: pointer; font-size: 14px; padding: 3px 4px; border-radius: 4px; opacity: 0.6; }
  .ql-act:hover { opacity: 1; background: var(--surface); }
  .ql-act.danger:hover { background: var(--danger-light); }
  @media (max-width: 560px) {
    .ql-colhead { display: none; }
    .ql-row { grid-template-columns: 1fr auto auto; row-gap: 3px; }
    .ql-row .li-title { grid-column: 1 / -1; font-weight: 500; }
    .ql-row .li-client { grid-column: 1 / -1; color: var(--text2); }
    .ql-row .li-date { display: none; }
    .sib-row { grid-template-columns: auto 1fr auto; }
    .sib-row .li-date { display: none; }
    .sib-row .li-no { grid-column: auto; }
    .rc-colhead { display: none; }
    .rc-row { grid-template-columns: 1fr auto auto; row-gap: 3px; }
    .rc-row .li-client { grid-column: 1 / -1; color: var(--text2); }
    .rc-row .li-date { display: none; }
  }

  body.readonly select,
  body.readonly .drag-handle { pointer-events: none; }
  body.readonly .drag-handle { display: none; }
  body.exporting .drag-handle { display: none; }

  /* ── Print styles ── */
  @media print {
    body { background: white; padding: 20px; }
    .phase-btns, .add-row-btn, .bottom-actions, .del-btn, .action-bar, .toolbar,
    .add-row-row, #toast, .reset-wrap, .drag-handle, .rate-box { display: none !important; }
    /* 階段分頁規則在上方 @media print（表頭重複、列不裂、可跨頁）；此處不再強制整塊不分頁 */
    .table-scroll { overflow: visible; }
    .meta-field, .s-card, .phase, .billing { border-color: #ccc; }
    /* 列印時輸入「格子」變乾淨文字 */
    input, textarea, select { border: none !important; background: transparent !important; box-shadow: none !important; -webkit-appearance: none; appearance: none; color: #1a1a18; }
  }

  /* ── Document footer (company letterhead + payment) ── */
  .doc-footer {
    margin-top: 30px;
    padding-top: 16px;
    border-top: 1px solid var(--border);
    font-size: 15px;
    color: var(--text2);
    line-height: 2;
  }
  .doc-footer .df-company {
    display: flex; gap: 14px; flex-wrap: wrap; align-items: baseline;
  }
  .doc-footer .df-company strong { font-size: 18px; color: var(--text); font-weight: 600; }
  .doc-footer .df-contact { display: flex; gap: 18px; flex-wrap: wrap; margin-top: 4px; }
  .doc-footer .df-addr { color: var(--text3); }
  .doc-footer .df-pay { margin-left: 6px; }
  .doc-footer .df-label {
    display: inline-block; background: var(--accent-light); color: var(--accent-text);
    font-size: 12.5px; padding: 2px 9px; border-radius: 4px; margin-right: 8px; font-weight: 500;
  }
  .doc-footer .df-acct { white-space: nowrap; }   /* 帳號 chip 與卡號不拆行：放不下時整段一起換行，號碼不被切成兩段 */
  .doc-footer .df-break { display: none; }
  /* 手機：固定 5 行（公司+統編／匯款資訊／銀行帳號／聯絡人+電話／Email+地址）。
     df-pay、df-break 用 flex-basis:100% 強制換行，桌機 df-break 隱藏不影響塞滿排版。 */
  @media (max-width: 560px) {
    .doc-footer { line-height: 1.7; }
    .doc-footer .df-company { gap: 6px 14px; }
    /* df-pay 往右縮 9px、匯款資訊 chip 用 -9px 拉回，使換行後的銀行那段對齊 chip 內文（原本中國信託突出綠框左側）。只動第一個 chip，帳號 chip 留在行內 */
    .doc-footer .df-pay { flex-basis: 100%; margin-left: 0; margin-top: 2px; padding-left: 9px; }
    .doc-footer .df-pay > .df-label:first-child { display: block; width: fit-content; margin: 0 0 2px -9px; }
    .doc-footer .df-contact { gap: 4px 14px; }
    .doc-footer .df-break { display: block; flex-basis: 100%; height: 0; }
  }

  /* ── Quote list overlay ── */
  .overlay {
    display: none;
    position: fixed; inset: 0;
    background: rgba(26,26,24,0.45);
    z-index: 900;
    align-items: flex-start;
    justify-content: center;
    padding: 60px 16px;
  }
  .overlay-box {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    width: 100%; max-width: 620px;
    max-height: 80vh; display: flex; flex-direction: column;
    overflow: hidden;
    box-shadow: 0 20px 50px rgba(0,0,0,0.2);
  }
  .overlay-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 14px 18px; border-bottom: 1px solid var(--border);
    font-weight: 600; font-size: 15px; background: var(--surface2);
  }
  .overlay-body { overflow-y: auto; overflow-x: auto; padding: 6px; }
  .li-no { font-family: 'DM Mono', monospace; font-weight: 500; }
  .li-title { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .li-client { color: var(--text2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .li-total { font-family: 'DM Mono', monospace; color: var(--accent-text); white-space: nowrap; }
  .li-date { color: var(--text3); font-size: 12px; white-space: nowrap; }
  @media (max-width: 560px) {
    .li-client { grid-column: 1 / -1; }
    .li-date { display: none; }
  }

  /* ── Toast ── */
  #toast {
    position: fixed;
    bottom: 32px;
    left: 50%;
    transform: translateX(-50%) translateY(20px);
    background: var(--text);
    color: white;
    padding: 10px 20px;
    border-radius: 30px;
    font-size: 13px;
    opacity: 0;
    transition: opacity 0.2s, transform 0.2s;
    pointer-events: none;
    z-index: 999;
  }
  #toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

  /* ── 全頁載入動畫（客戶查單時顯示）── */
  .page-loading {
    position: fixed; inset: 0; z-index: 9998;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 16px; background: var(--bg);
  }
  .page-spinner {
    width: 38px; height: 38px; border-radius: 50%;
    border: 3px solid var(--border); border-top-color: var(--accent);
    animation: page-spin 0.7s linear infinite;
  }
  .page-loading-msg { color: var(--text2); font-size: 14px; letter-spacing: 0.02em; }
  @keyframes page-spin { to { transform: rotate(360deg); } }

  /* 開機遮罩：init() 判斷要顯示「輸入單號查詢頁／報價內容」之前，先用不透明底色＋spinner 蓋住
     index.html 靜態的編輯器骨架，避免客戶在輸入單號／登入前閃過空殼表單。純 CSS，從第一次 paint
     就生效（連 app.js 尚未下載完都擋得住）；init() 決定後由 hidePageLoading()／renderEntryScreen() 移除 .booting。 */
  body.booting .page { visibility: hidden; }
  body.booting::before { content: ""; position: fixed; inset: 0; background: var(--bg); z-index: 9998; }
  body.booting::after {
    content: ""; position: fixed; top: 50%; left: 50%; width: 38px; height: 38px; margin: -19px 0 0 -19px;
    border-radius: 50%; border: 3px solid var(--border); border-top-color: var(--accent);
    animation: page-spin 0.7s linear infinite; z-index: 9999;
  }

/* 品項圖片：縮圖 + 點開放大 lightbox */
.row-img-row > td { padding: 0 12px 12px 40px; border-bottom: 1px solid var(--line); }
.row-img { display: block; max-width: 100%; max-height: 140px; border-radius: 8px; border: 1px solid var(--line); cursor: zoom-in; }
.row-img-add { display: inline-block; margin-top: 6px; font-size: 12px; color: var(--muted); cursor: pointer; }
.row-img-add:hover { color: var(--text); }
.row-img-del { display: inline-block; margin: 6px 0 0 8px; padding: 2px 8px; font-size: 12px; border: 1px solid var(--line); border-radius: 6px; background: #fff; color: var(--muted); cursor: pointer; }
.row-img-del:hover { border-color: var(--danger); color: var(--danger); }
/* 唯讀(客戶版)／匯出 PDF 時隱藏編輯鈕；沒圖的列整列收掉 */
body.readonly .row-img-edit, body.exporting .row-img-edit { display: none; }
body.readonly .row-img-row.no-img, body.exporting .row-img-row.no-img { display: none; }
/* lightbox 大圖(複用 .overlay 遮罩) */
#imgLightbox { cursor: zoom-out; z-index: 1000; align-items: center; padding: 16px; }
.lightbox-img { max-width: 92vw; max-height: 92vh; border-radius: 10px; box-shadow: 0 10px 40px rgba(0,0,0,0.4); }
body.exporting #imgLightbox { display: none !important; }

/* ── 鍵盤焦點可見（WCAG 2.4.7）──
   全站原本大量 outline:none 讓純鍵盤使用者看不到焦點在哪。用 :focus-visible 只在
   鍵盤操作時畫清楚的焦點環（滑鼠點擊不觸發，故不影響一般外觀）。置於檔末以壓過前面的 outline:none。
   客戶版(readonly)整份唯讀不需焦點環。 */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
body.readonly :focus-visible { outline: none; }
@media (prefers-reduced-motion: no-preference) {
  a:focus-visible, button:focus-visible { transition: outline-offset .1s ease-out; }
}
