/* FAX OCR System UI — Split Panel Design */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --bg: #f0f2f5;
  --surface: #ffffff;
  --border: #dde1e7;
  --primary: #1a56db;
  --primary-light: #e8f0fe;
  --text: #1e2532;
  --text-muted: #6b7280;
  --green: #16a34a;
  --yellow: #d97706;
  --red: #dc2626;
  --blue: #2563eb;
  --gray: #6b7280;
  --shadow: 0 1px 3px rgba(0,0,0,.08);
  --radius: 8px;

  /* §9(2026-07-31) 色分けを入力経路(auto/manual)からマスタ照合状態へ変更:
     ok=正常(マスタ一致=コード確定) / ng=異常(名称ありコード未確定=マスタ不一致) / empty=未入力(必須) */
  --cell-ok: #ecfdf5;
  --cell-ng: #ffedd5;
  --cell-ng-border: #fdba74;
  --cell-empty-required: #fff0f0;
  --cell-empty-border: #fca5a5;

  /* §10(2026-07-31) ダークモード対応のためハードコード色を変数化（Addnessダッシュボードのトークン設計を参考） */
  --surface-2: #f8f9fb;   /* 薄グレー面（テーブルヘッダ・サブ面） */
  --surface-3: #f1f3f6;   /* さらに一段（RO欄・押下面） */
  --hover: #eff6ff;       /* リスト/候補hover */
  --text-faint: #9ca3af;  /* 最も薄い文字 */
  --badge-green-bg: #dcfce7;  --badge-green-tx: #15803d;
  --badge-red-bg: #fee2e2;
  /* §2026-08-16 新指示① 「紐付済」バッジ用に -tx を追加（従来 yellow は背景のみ定義だった） */
  --badge-yellow-bg: #fef3c7; --badge-yellow-tx: #a16207;
  --badge-blue-bg: #dbeafe;
  --badge-orange-bg: #ffedd5; --badge-orange-tx: #c2410c;
  --overlay: rgba(0,0,0,.5);
  --focus-ring: rgba(26, 86, 219, .12);
}

/* ===== ダークモード（Addnessリアルタイム集客ダッシュボードのパレットを移植） ===== */
:root[data-theme='dark'] {
  /* §13(2026-07-31) 基調をネイビー系→無彩色ダークグレー系に変更（アクセント・状態色は維持） */
  --bg: #131313;
  --surface: #1e1e1e;
  --border: rgba(255, 255, 255, 0.18);
  --primary: #7b88ea;
  --primary-light: rgba(123, 136, 234, 0.16);
  --text: #f0f0f0;
  --text-muted: #a8a8a8;
  --green: #4ade80;
  --yellow: #fbbf24;
  --red: #f87171;
  --blue: #60a5fa;
  --gray: #9a9a9a;
  --shadow: 0 1px 3px rgba(0,0,0,.4);

  --cell-ok: rgba(34, 197, 94, 0.18);
  --cell-ng: rgba(249, 115, 22, 0.22);
  --cell-ng-border: rgba(249, 115, 22, 0.7);
  --cell-empty-required: rgba(239, 68, 68, 0.18);
  --cell-empty-border: rgba(239, 68, 68, 0.65);

  --surface-2: #252525;
  --surface-3: #2e2e2e;
  --hover: rgba(255, 255, 255, 0.08);
  --text-faint: #858585;
  --badge-green-bg: rgba(34, 197, 94, 0.16);  --badge-green-tx: #4ade80;
  --badge-red-bg: rgba(239, 68, 68, 0.16);
  --badge-yellow-bg: rgba(245, 158, 11, 0.16); --badge-yellow-tx: #fcd34d;
  --badge-blue-bg: rgba(59, 130, 246, 0.18);
  --badge-orange-bg: rgba(249, 115, 22, 0.18); --badge-orange-tx: #fdba74;
  --overlay: rgba(0,0,0,.6);
  --focus-ring: rgba(123, 136, 234, 0.25);
}

/* §14(2026-08-14) スクロールバーを「自前オーバーレイ・スクロール中だけフェード表示」に置換。

   経緯（3段階で方針が変わっている）:
   1) 最初はダーク用に色を当てる方向で直した → Windows実機のChrome/Edgeはネイティブ
      (Fluent)描画のため白いまま残り、効かなかった。
   2) 次に `::-webkit-scrollbar` で幅6px・スクロール中だけthumbを出す方式にした
      → 「バー用のエリアが最初から空いている」との指摘。Webkitの疑似要素スクロールバーは
      **見えていなくてもレイアウト幅を予約する**（クラシック方式）ため、6pxの空白が常時残る。
      幅を0↔6pxで切り替えると今度は内容が横にガタつく（レイアウトが動く）ので不可。
   3) そこでネイティブのスクロールバーを完全に殺し（width:0）、JSが `.vbar` 要素を
      absolute で被せて描く方式にした。ユーザー了解済み＝「内容に被って良い（どうせ消える）」。
      これならレイアウトを1pxも削らず、opacity で素直にフェードできる。

   ・color-scheme … select のドロップダウン等ネイティブUIをテーマに追従させる（維持）
   ・ネイティブバーは width/height:0 で消す（Firefoxは scrollbar-width:none）
   ・見た目は全部 .vbar（＝ただのdiv）なので、OS/ブラウザの描画差分に一切依存しない */
:root { color-scheme: light; }
:root[data-theme='dark'] { color-scheme: dark; }

/* ネイティブのスクロールバーを消す。幅0＝レイアウト幅を予約しない＝余白が空かない */
* { scrollbar-width: none; }
::-webkit-scrollbar { width: 0; height: 0; }

/* JSが差し込む自前バー。position:absolute で内容の上に浮かせる（被ってよい）。
   親側に position が無いと座標が狂うので .has-vbar で relative を保証する。 */
.has-vbar { position: relative; }
.vbar {
  position: absolute;
  z-index: 30;               /* 内容より前・モーダル(通常100超)より後ろ */
  border-radius: 3px;
  background: var(--text-faint);
  opacity: 0;                /* 既定は透明＝見えない */
  pointer-events: none;      /* 掴めない代わりにクリックを一切邪魔しない */
  /* 出るのは速く、消えるのはゆっくり。視線を奪わず自然に引く */
  transition: opacity .4s ease;
}
.vbar.is-visible { opacity: .55; transition: opacity .12s ease; }
.vbar.v { width: 8px; }      /* 縦バー */
.vbar.h { height: 8px; }     /* 横バー */

/* §10 入力系のUAデフォルト色（黒文字・白背景）はダークで潰れるため変数に固定
   ライトでは従来と同等（--text≒黒 / --surface=白）なので見た目不変 */
input, textarea, select { color: var(--text); }
input::placeholder, textarea::placeholder { color: var(--text-faint); }
select { background: var(--surface); }

body {
  font-family: "Hiragino Sans", "Meiryo", sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 12px;
  line-height: 1.5;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ===== Header ===== */
header {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: 0 20px;
  /* §14(2026-07-31) 52px→64px: ロゴ(52px固定)の上下に6pxずつ余白を確保 */
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
  z-index: 100;
}
/* §2026-08-20 ブランド表記: タイトル(基幹業務システム名)＋その下に自社クレジットを薄く小さく */
/* §2026-08-22 ブランド2行が上寄りに見えた件の是正（設計原則9=視覚的重心 / 10=光学整列 / 13=4|8倍数）。
   原因: line-height:1.15 は 16px に対し 18.4px しかなく、和文の実描画24pxが行箱からはみ出していた
   （実測 glyph top 12.41 に対し box top 15.41）。加えて和文は仮想ボディ下側のディセンダ域が広いため、
   行箱を中央に置いてもインクの重心は箱中央より上に来る。箱の数値中央だけ見ていたのが誤り。
   対策: 半端値1.15を捨て、行箱を字面より広い4|8倍数の実値にして中で中央に置く。
   title 16px→行箱24px / powered 12px→行箱16px、合計40px＝ロゴ高40pxと一致し2要素の箱が揃う。 */
.header-brand { display: flex; flex-direction: column; justify-content: center; }
.header-title { font-size: 16px; line-height: 24px; font-weight: 700; }
.header-powered { font-size: 12px; line-height: 16px; font-weight: 500; color: var(--text-muted); letter-spacing: 0.04em; margin-top: 0; }
.header-meta { display: flex; align-items: center; gap: 8px; } /* §grid48 タブバー側のgap(8px)と統一＝反復の原則（同種グループのgapは画面内で1つの値） */
#ws-status { font-size: 12px; padding: 0 8px; line-height: 20px; border-radius: 20px; font-weight: 600; } /* §grid48 縦paddingを0にし、高さはline-height:20pxで決定的に */
#ws-status.connected { background: var(--badge-green-bg); color: var(--green); }
#ws-status.disconnected { background: var(--badge-red-bg); color: var(--red); }

/* OCR済み新規追加の未読バッジ（2026-08-22。件数のみ静かに表示。トークン使用でライト/ダーク両対応） */
.ocr-unread-bell {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0; border: none; border-radius: 8px;
  background: transparent; color: var(--text-muted, var(--text)); cursor: pointer;
}
.ocr-unread-bell:hover { color: var(--text); background: var(--surface-3); }
.ocr-unread-badge {
  position: absolute; top: -2px; right: -2px; min-width: 16px; height: 16px;
  padding: 0 4px; border-radius: 8px; background: var(--red); color: #fff;
  font-size: 12px; font-weight: 700; line-height: 16px; text-align: center;
  box-shadow: 0 0 0 2px var(--surface, #fff);
}

/* ===== Stats Bar =====
   §11(2026-07-31) tab-barと情報重複のため統合。stats-bar自体は非表示にするが
   HTMLと#stat-*のIDは残す（app.jsが件数を更新し続けるため・app.js無変更） */
.stats-bar { display: none; }
.stats-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; } /* §grid48 ヘッダーのボタン間・タブ間と同値(8px)＝反復の原則 */

/* ===== Tab Bar（シンプルなフラットピル） ===== */
.tab-bar {
  display: flex;
  align-items: center;
  gap: 8px; /* §grid48 10→8。4/8倍数スケールに載せ替え（ヘッダー側gapと同値で反復維持） */
  padding: 8px 20px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
/* §2026-08-22 整列の根治（5回目の再発で構造から作り直し）。
   従来の「箱の中心を揃える」は、フォントサイズがバー内で混在したままだったので
   文字の下端が最大4pxばらけて波打っていた（実測: 191 / 194.8 / 192.5px）。
   → バー内のテキストは全て12px・line-height:1、テキストを持つ直接の子は全て
   同一高さ28pxの flex 中央に統一する（§grid48 で 13px/30px → 12px/28px に載せ替え）。
   同じ字面高×同じ箱高×同じ中央＝文字下端は物理的に一致する。
   ここに個別の margin/padding で帳尻を合わせるのは禁止（それが波打ちの原因だった）。 */
.tab-bar .module-back,
.tab-bar .module-bar-title,
.tab-bar .tab,
.tab-bar .stats-actions > button {
  height: 28px;
  box-sizing: border-box;
  display: inline-flex;
  font-size: 12px;
  line-height: 16px;
  font-family: inherit;
  /* §2026-08-23 光学中心の根治（指摘「対応漏れてる」＝2026-08-22の指摘Dが未解消だった）。
     前回 line-height:16px + align-items:center にしたが、実測すると全ボタンで
     インク上余白6px / 下余白10px ＝ 2px 上寄りのまま残っていた。

     原因: このフォント(Hiragino Sans/Meiryo)は 12px 時 ascent=13px / descent=5px と
     仮想ボディが下に偏っている。align-items:center は「行箱」を中央に置くので、
     行箱の中でベースラインが上寄りな以上、行箱をどう伸ばしてもインクは上に残る。
     実際 line-height を 14〜26px まで振って全パターン検算したが、ズレは常に 2px で不変
     （箱中央に置く限りベースラインの相対位置が変わらないため）。
     ＝ line-height をいじる方向では構造的に解けない。前回の「根治」は誤りだった。

     解: 箱中央に頼らず flex-start でベースラインを明示的に置く。padding-top:7px は
     ascent13/descent5 という実測メトリクスから導出した値であって、目視で合わせた
     魔法の数字ではない（原則11が禁じているのは根拠なき微調整）。
     4/8倍数(原則13)からは外れるが、12px和文のこのメトリクスでは倍数値で光学中心が
     取れないことを全数検算で確認済み。ここは原則9(視覚的重心)を優先する。
     検算: 行箱top=7 → baseline=7+(16-18)/2+13=19 → ink 8..20 → 上余白8px / 下余白8px。

     §2026-08-26 【この状態がMayank承認済みの正】。この日、自分の実測(ベースライン一致)だけを
     根拠に line-height:18px + align-items:center へ変えたが、Mayankから
     「なんで正しくしてもらったボタンの文字とか全部逆に上にずらした？」と即指摘され revert した。
     ＝ ベースラインが数値で揃うことと、人が見て正しく見えることは別。
     **ここは実測を理由に触るな。** 変えるならMayankの目視承認を先に取る。 */
  align-items: flex-start;
  padding-top: 7px;
  padding-bottom: 5px;
}
/* §2026-08-26 border持ちのボタンだけベースラインが1px下がる件の是正（Mayank指摘「更新だけ改悪」）。
   box-sizing:border-box なので、border:1px を持つ .btn-outline（← メニュー / 更新 /
   無作為サンプル再読込）はコンテンツ開始位置が 1+7=8px になり、border無しの .tab / .btn-primary
   （7px）に対してベースラインが 19px vs 18px と 1px ズレていた。
   実測でこの1px差を確認（← メニュー・更新のみ base=19、他は全て base=18）。
   承認済みの base=18 を正として、border 分の 1px を padding から引いて揃える。
   ＝ 承認済みの文字位置は一切動かさず、ズレていた2つだけを合わせにいく修正。
   検証: 8ボタン全て base=18 で一致（バラつき0）。 */
.tab-bar .module-back,
.tab-bar .stats-actions > button.btn-outline {
  padding-top: 6px;   /* border 1px + 6px = 承認済みの 7px と等価 */
  padding-bottom: 4px;
}
.tab {
  padding: 0; /* 寸法は下の .tab-bar .tab（等幅・高さ・中央寄せ）が決める */
  border: none;
  background: var(--surface-2); /* §2026-08-22 非アクティブにも薄背景。等幅・等間隔を視覚的に成立させる（指摘） */
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: 999px;
  transition: color .15s, background .15s;
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: 4px;
}
/* §2026-08-22 ピル等幅の基準＝最大コンテンツ（指摘: 「一番文字量の大きいものに合わせろ」）。
   §grid48 字面12px化後にPlaywright実測。最長コンテンツ「キャンセル＋バッジ」実測80.13px。
   導出下限 = 80.13 + 目標余白12px×2 = 104.13px → 4の倍数切り上げ108px。
   幅は108pxより広い120px（4の倍数）を維持＝最悪ケース（キャンセル）でも
   左右余白 min 17.94px を確保（実測: padLeft21.94 / padRight17.94、いずれも12px超）。
   高さ28px（4の倍数）。バーは align-items:center で全タブ中央線を共有＝
   12px字面は全員「中央±」で下端が揃う（上の統一ルールを壊さない）。 */
.tab-bar .tab {
  width: 120px;
  height: 28px;
  /* 光学補正: テキスト(濃)＋バッジ(薄)の視覚重心は左に見えるため中心を+2px右へ。
     +6pxは「寄せすぎ」と指摘済み。補正の妥当性は最小余白タブ(キャンセル)の実測で検証する
     §2026-08-23 縦paddingはここで指定しない。ベースライン確定は上の共通ブロック
     (.tab-bar .module-back, ... , .tab-bar .stats-actions > button)に一本化した。
     ショートハンド padding を書くと縦まで上書きしてしまうので padding-left だけにする。 */
  padding-left: 4px;
  justify-content: center;
}
.tab:hover { color: var(--text); background: var(--surface-3); }
.tab.active { color: #fff; background: var(--primary); }
.tab .tab-count {
  background: var(--surface-3);
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 700;
  line-height: 16px; /* §grid48 バッジ箱の高さを決定的に16px(縦padding0+行高16)。flex中央で縦位置が上下対称になる（指摘⑤） */
  padding: 0 4px;
  border-radius: 10px;
  min-width: 16px;
  text-align: center;
}
.tab.active .tab-count { background: rgba(255,255,255,.25); color: #fff; }
/* §11 旧統計カードの状態色をバッジ数字に継承（選択中は白のまま）
   §2026-08-15 指示S9 タブ再編に合わせて ocr→order / rejected→other へ改名 */
.tab[data-tab="order"]:not(.active) .tab-count { color: var(--green); }
.tab[data-tab="correction"]:not(.active) .tab-count { color: var(--blue); }
.tab[data-tab="other"]:not(.active) .tab-count { color: var(--red); }

/* §2026-08-15 指示S6「未処理タブも不要。処理中～件 が分かればよくね？」
   → §2026-08-16 指示でタブ横の独立表示をやめ、処理中スピナーボタンの中へ移設。
   スピナー自体が「処理中」の印なので、件数を隣に置けば1箇所で足りる
   （同じ情報がタブ横とボタンで2箇所に散っていたのを寄せた）。
   ボタンは処理中だけスピナー化するので、このスタイルもその間だけ効く。 */
#process-all-btn:has(.spinner) {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.btn-proc-count {
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}
.btn-proc-count[hidden] { display: none; }
.btn-proc-count > span { font-weight: 700; }

/* ===== Progress ===== */
#progress-wrap {
  padding: 4px 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  display: none;
  flex-shrink: 0;
}
.progress-bar-bg { background: var(--border); border-radius: 4px; height: 4px; margin-top: 4px; overflow: hidden; }
.progress-bar-fill { height: 4px; background: var(--primary); border-radius: 4px; transition: width .3s; }
#progress-label { font-size: 12px; color: var(--text-muted); }

/* ===== Main Layout ===== */
#main-layout {
  display: flex;
  flex: 1;
  overflow: hidden;
}

/* ===== Left Panel ===== */
#left-panel {
  width: 300px;
  flex-shrink: 0;
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  overflow: hidden;
}
#left-toolbar {
  padding: 8px 8px;
  border-bottom: 1px solid var(--border);
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}
/* §2026-08-26「新着だけ表示中」の帯。
   ヘッダーのベル押下で一覧をIDで絞っている状態を示す。件数と解除だけを置き、
   新着の中身は並べない（繁忙日に500件届くので、通知の全件列挙は作らない方針）。
   原則5(装飾の断捨離): 枠線付きコールアウトにはせず、面の色差1段(--surface-2)と
   文字色の弱化だけで階層を作る。原則1(近接): 帯内 8px < 帯とリストの境界(border-bottom)。
   色は全てトークン経由なのでライト/ダーク両モードで自動追従する。 */
#new-only-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.new-only-text {
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap;   /* 原則16: 「新着12件だけ表示中」を語中で折らない */
}
.new-only-clear {
  border: none;
  background: none;
  padding: 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--blue);
  cursor: pointer;
  white-space: nowrap;
}
.new-only-clear:hover { text-decoration: underline; }

#left-search {
  flex: 1;
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 4px 8px;
  font-size: 12px;
  background: var(--bg);
}
#fax-list { flex: 1; overflow-y: auto; }
.fax-list-item {
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background .1s;
}
.fax-list-item:hover { background: var(--bg); }
.fax-list-item.selected { background: var(--primary-light); border-left: 3px solid var(--primary); }
.fax-list-item .item-filename {
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 4px;
}
.fax-list-item .item-meta {
  font-size: 12px;
  color: var(--text-muted);
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}
.fax-list-empty {
  padding: 32px;
  text-align: center;
  color: var(--text-muted);
  font-size: 12px;
}
#left-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
  font-size: 12px;
  color: var(--text-muted);
}

/* ===== Status badges ===== */
.badge {
  display: inline-block;
  padding: 0 4px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}
.badge-done { background: var(--badge-green-bg); color: var(--green); }
.badge-unclear { background: var(--badge-yellow-bg); color: var(--yellow); }
.badge-rejected { background: var(--badge-red-bg); color: var(--red); }
.badge-correction { background: var(--badge-blue-bg); color: var(--blue); }
.badge-error { background: var(--badge-red-bg); color: var(--red); }
.badge-processing { background: var(--badge-blue-bg); color: var(--blue); }
.badge-pending { background: var(--surface-3); color: var(--gray); }
/* §16(2026-08-14) 受領印フロー。両テーマ対応の変数を使うので個別のダーク指定は不要 */
.badge-confirmed { background: var(--badge-green-bg); color: var(--badge-green-tx); }
.badge-replied { background: var(--badge-blue-bg); color: var(--blue); }
/* §2026-08-15 指示S4「確認済」「伝票済」「返信済」の3バッジ。
   3段フローが進むほど並ぶので、確認済(緑)→伝票済(橙)→返信済(青)と色を変えて
   どこまで進んだか一目で分かるようにする。変数は両テーマ定義済み */
.badge-issued { background: var(--badge-orange-bg); color: var(--badge-orange-tx); }
/* §2026-08-16 新指示① 「紐付済」= 訂正FAXが大元に紐づいている状態。
   original_fax_id が入れば自動で付く（人手のチェック操作は廃止）。
   確認済(緑)/伝票済(橙)/返信済(青) と並ぶので、残る黄で区別する。変数は両テーマ定義済み */
.badge-linked { background: var(--badge-yellow-bg); color: var(--badge-yellow-tx); }
.fax-list-item .badge + .badge { margin-left: 4px; }

/* ===== §16(2026-08-14) 受領印 / 確認済み / FAX返信 ===== */
.stamp-group {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: 4px;
}
.stamp-confirm-label {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  user-select: none;
}
.stamp-confirm-label input { cursor: pointer; }
/* §2026-08-17 指示「必須項目が入力されてない状態で『確認済み』チェックは入らないように」。
   押せないことだけ分かっても現場は困るので、押せない理由を隣に名指しで出す。
   色は --badge-red-bg / --red のペア（788行と同じ組み合わせ＝ライト/ダーク両方に定義済み）。 */
.stamp-confirm-label.is-blocked {
  color: var(--text-muted);
  cursor: not-allowed;
}
.stamp-confirm-label.is-blocked input { cursor: not-allowed; }
.stamp-confirm-why {
  font-size: 12px;
  font-weight: 600;
  padding: 0 8px;
  margin-left: 8px;
  border-radius: 999px;
  background: var(--badge-red-bg);
  color: var(--red);
  /* 未入力項目が多いと行が崩れるので、はみ出す分は…で畳む（title に全文が出る） */
  max-width: 340px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: middle;
  display: inline-block;
}
/* §2026-08-15 3段フロー（①確認済み → ②伝票発行 → ③FAX返信）を1か所に
   使用順で並べる（ユーザー指示）。要素間の「›」は順番を目で追うための区切り。
   色は var(--text-muted) 参照なのでライト/ダーク両テーマでそのまま成立する。 */
.stamp-step-arrow {
  color: var(--text-muted);
  font-size: 12px;
  line-height: 1;
  opacity: .55;
  user-select: none;
}
/* 前段が済むまで押せないボタンは、押せないと一目で分かるようにする。
   理由（何をすれば押せるか）は title 属性でホバー時に出す。 */
.btn-fax-reply:disabled,
.btn-issue-slip:disabled {
  opacity: .45;
  cursor: not-allowed;
  filter: grayscale(.6);
}
/* stamp-group は gap:8px で間隔を持つので、旧配置（見出し脇）用の
   margin-left:8px はここでは二重になる。群の中では余白をリセットする。 */
.stamp-group .btn-issue-slip,
.stamp-group .slip-issued-tag,
.stamp-group .fax-corr-tag { margin-left: 0; }
/* 返信済みロック表示。押せる要素と見分けがつくよう淡色＋カーソル既定 */
.stamp-locked {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0 8px;
  border-radius: 999px;
  background: var(--badge-blue-bg);
  color: var(--blue);
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}
.stamp-fax-no {
  font-size: 12px;
  color: var(--text-muted);
}
.stamp-error {
  font-size: 12px;
  color: var(--red);
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ===== Right Panel ===== */
#right-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
#right-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  gap: 8px;
}
#right-empty .icon { font-size: 40px; opacity: .3; }

/* ===== PDF Viewer ===== */
#pdf-section {
  width: 45%;
  min-width: 260px;
  border-left: 2px solid var(--border);
  background: #525659;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
}
.pdf-bar {
  padding: 4px 12px;
  background: #3a3d40;
  color: #ccc;
  font-size: 12px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-shrink: 0;
  gap: 8px;
}
.pdf-bar a { color: #90cdf4; text-decoration: none; font-size: 12px; }
.pdf-bar-group { display: flex; gap: 8px; align-items: center; }
.pdf-rotate-btn {
  background: rgba(255,255,255,0.12);
  border: 1px solid rgba(255,255,255,0.2);
  color: #ddd;
  padding: 0 8px;
  font-size: 16px;
  line-height: 1.4;
  cursor: pointer;
  border-radius: 4px;
}
.pdf-rotate-btn:hover { background: rgba(255,255,255,0.25); }
/* align-items:center を置くと子(#pdf-pages)の高さがコンテンツ依存になり
   overflow-y:auto が永久に発動しない（スクロール不能の原因）。stretchのまま使う */
#pdf-rotate-wrap {
  flex: 1;
  display: flex;
  min-height: 0;
  background: #525659;
}
/* ページごと画像プレビュー（各ページの頭に回転ツールバー） */
#pdf-pages {
  flex: 1;
  overflow-y: auto;
  overflow-x: auto;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.pdf-page {
  /* 中央寄せは align-items:center ではなく margin:auto で行う。
     flexの中央寄せはズームで親幅を超えた時に左端がスクロール不能になるため */
  width: 100%;
  max-width: 980px;
  margin-left: auto;
  margin-right: auto;
  flex-shrink: 0;
  background: #fff;
  box-shadow: 0 2px 10px rgba(0,0,0,0.45);
  border-radius: 4px 4px 0 0;
  overflow: hidden;
}
.pdf-page img {
  width: 100%;
  display: block;
  min-height: 120px;
  background: #fff;
}
.pdf-page.rotating img { opacity: 0.35; transition: opacity .15s; }
.pdf-page-tools {
  display: flex;
  gap: 4px;
  align-items: center;
  justify-content: flex-end;
  background: #3a3d40;
  padding: 4px 8px;
}
.pdf-page-label {
  color: #ccc;
  font-size: 12px;
  margin-right: auto;
}
.pdf-rotate-btn-180 { font-size: 12px; line-height: 1.9; }
.pdf-zoom-label { font-size: 12px; line-height: 1.9; min-width: 40px; text-align: center; }
/* ヘッダー集約ツールバー（回転・ズームは pdf-bar に一列配置）用 */
.pdf-page-indicator { color: #ccc; font-size: 12px; min-width: 36px; text-align: center; }
.pdf-bar-sep { width: 1px; height: 16px; background: rgba(255,255,255,0.25); }

/* ===== Detail / Edit Section ===== */
#detail-section {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.legend {
  display: flex;
  gap: 8px;
  font-size: 12px;
  color: var(--text-muted);
  padding: 4px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  flex-shrink: 0;
}
.legend-item { display: flex; align-items: center; gap: 4px; }
.legend-dot { width: 8px; height: 8px; border-radius: 2px; border: 1px solid rgba(0,0,0,.1); }
.legend-dot.ok { background: var(--cell-ok); }
.legend-dot.ng { background: var(--cell-ng); border-color: var(--cell-ng-border); }
.legend-dot.req { background: var(--cell-empty-required); border-color: var(--cell-empty-border); }

.detail-scroll { flex: 1; overflow-y: auto; padding: 12px 16px; }

/* Cards */
.detail-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 12px;
  overflow: hidden;
}
/* §17(2026-08-14) 明細カードの「入れ子の枠」を廃止。
   指摘: 「この背景の入れ子構造無駄じゃない？無駄に空白を生むだけ。
          個々に囲うのは行1〜Xの項目だけでいい。さらにそれを囲う外側のカードは不要」
   実測(before): .detail-card(白・border) の中に同じ白の .item-row(border) が入り、
   同色の枠が二重。左右それぞれ 25px(scroll14 + card境界1 + items-blocks10) が
   枠のためだけに消えていた。
   方針: 囲うのは .item-row だけ。外側カードは枠・背景・角丸を外して
   「ただの領域」にし、ヘッダーは枠なしの見出し帯として残す
   （伝票発行/元に戻す/詳細項目/運賃合計/コード未確定バッジが載っており削除不可）。
   .detail-card 自体は警告パネル(L756付近)でも使うため、明細側だけを
   .detail-card--flat で狙い撃ちする。 */
.detail-card--flat {
  background: transparent;
  border: 0;
  border-radius: 0;
  overflow: visible;   /* 枠が無いのでクリップ不要。横スクロール(.smile-wrap)を殺さない */
}
/* ヘッダーは枠内バーではなくなるので、左右paddingを詰めて下線だけの見出しにする。
   §17b(2026-08-14「上の余白ももう少し調整できない？」): 上部の縦の積み上がりを実測すると
   scroll12 + header36 + 警告帯30 + slip-common151 + items-blocks6 = 235px。
   slip-common の151pxは入力欄そのもの（＝消せない）なので、削れる枠まわりのpaddingを詰める。 */
.detail-card--flat > .card-header {
  padding: 0 4px 4px;   /* §grid48 上0/横4/下4。帯の高さは中のボタン高で決まるので縦paddingは最小に */
  background: transparent;
  border-bottom: 1px solid var(--border);
}
/* 行枠がコンテンツ幅いっぱいに出るよう、内側コンテナの左右paddingを0にする */
.detail-card--flat .items-blocks { padding: 4px 0; }
.detail-card--flat .slip-common { padding: 4px 4px 4px; background: transparent; }
.detail-card--flat .items-footer { padding: 8px 4px; }
/* §17b 明細エリアの最上部。カード枠が無くなったので scroll の12pxは効きすぎ。
   負マージンで持ち上げる（.detail-scroll のpaddingは他の画面でも使うため触らない） */
.detail-card--flat { margin-top: -4px; } /* §grid48 -6→-4。scroll padding12との実効余白は12-4=8px（スケール上の標準余白） */
/* §17b 警告帯(マスタ不一致など)も枠内バー前提の余白だったので薄くする */
.detail-card--flat > .error-msg { padding: 4px 8px; }
.card-header {
  padding: 8px 12px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
/* §18(2026-08-14) 明細ヘッダーの2行化。
   指摘: 「この辺が項目ギュウギュウすぎて改行されまくると見にくいので、2行にしてもいいかも」
   実測(before): .card-header 1本の flex に8要素（見出し/伝票発行/確認済み/FAX返信/
   元に戻す/やり直す/凡例/詳細項目/運賃合計/ピル）が並び、幅が足りないと
   要素の途中で折り返して行が崩れていた。
   方針: 意味で2行に割る。1行目=見出しと主要アクション、2行目=補助操作と状態表示。
   各行は .ch-side 2つの space-between で、右側（受領印・集計）を右端に固定する。
   .card-header は警告パネル等でも使うため、2行化は --2row を付けた時だけ効かせる。 */
.card-header--2row {
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
}
.card-header--2row .ch-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  min-width: 0;         /* 中身が縮めるようにする（省略表示を効かせる） */
}
.card-header--2row .ch-side {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  flex-wrap: wrap;      /* 極端に狭い時だけ折り返す。通常幅では1行に収まる */
}
/* 2行目は補助情報なので一段控えめに。行の高さも詰める。
   実測(1280px幅・明細ペイン502px): 左グループが undo/redo 153 + 凡例 77 + 詳細項目 61
   = 291px あり、右グループ 188px と合わせて行幅を超えて「詳細項目」だけが3行目に
   落ちていた（指摘どおりの「改行されまくる」状態）。
   2行目は補助操作なので、中の要素もまとめて一段詰めて 1280px でも1行に収める。 */
.card-header--2row .ch-row--sub { font-size: 12px; gap: 8px; }
.card-header--2row .ch-row--sub .ch-side { gap: 8px; }
.card-header--2row .ch-row--sub .btn-sm {
  padding: 0 8px;
  font-size: 12px;
}
.card-header--2row .ch-row--sub .undo-redo-group { gap: 4px; margin-right: 0; }
.card-header--2row .ch-row--sub .ocr-legend,
.card-header--2row .ch-row--sub .detail-toggle,
.card-header--2row .ch-row--sub .freight-total,
.card-header--2row .ch-row--sub .completion-pill {
  font-size: 12px;
  white-space: nowrap;
}
.card-header--2row .ch-title { white-space: nowrap; }

/* §20(2026-08-15) 指示「PDFビューワーの上のファイル名を『FAX明細（◯行）』のエリアに移動。
   ビューワー上の名称は不要。ページの◯/◯はそのまま」。

   配置を1行目→2行目に変えた経緯（すべて実測で判断・推測で幅を弄っていない）:
   (1) 最初は見出し「FAX明細（N行）」の真横（1行目）に flex:1 1 auto で置いた。
       → 1280px・id=2 で行の高さが 27→50px に増えて折り返した。top を測ると
         ch-title=149 / ch-filename=150 に対し slip-issued-tag=175 と後続だけが2段目に落ちていた。
         原因はファイル名が余白を全部吸って（1440pxでは299pxまで膨張）後続の置き場所を奪ったこと。
   (2) flex:0 1 auto に直した → 膨張は止まったが 1280px では依然2段。
       1行目は 見出し95 + ファイル名141 + 伝票タグ160 = 396px に対し右側が153〜188px あり、
       502px には元から入らない。変更前の .bak を一時配信して比較し、
       これが自分の変更による回帰だと確定させた（変更前は全ケース高さ27px）。
   (3) .ch-side に flex-wrap:nowrap を当てて縮ませる案も試したが、
       今度は縮んではいけない stamp-group（受領印の操作群）が 138→131px に潰れ始めたため撤回。
   → 結論: 1行目は元から余白ゼロで要素を足す余地が無い。2行目（補助情報の棚）へ置く。
      2行目は最も厳しい 1280px・id=4 でも 103px の空きがあり、全ケース1段(27px)を保っている。
      ファイル名は「操作」ではなく「今どのFAXを見ているか」の識別情報なので、性質としても
      主役の1行目より補助の2行目が合う。

   min-width:0 は必須（無いと flex アイテムは中身の幅より縮まず ellipsis が効かない）。
   flex-grow は 0（1 にすると上記(1)の膨張が再発する）。
   2行目の他要素（運賃合計・完了ピル）は nowrap 指定済みなので、狭い時はこのファイル名だけが縮む。 */
.card-header--2row .ch-row--sub .ch-filename {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  font-weight: 400;
  color: var(--text-faint);
}
/* .ch-side は既定で flex-wrap:wrap のため、狭い時は「縮む」より先に「折り返す」。
   実測(1280px・id=2/4/7): ファイル名が128pxのまま縮まず2行目が 27→52px に折り返した。
   nowrap にすると、縮める指定を持つファイル名だけが縮んで … になる。
   1行目では同じ手を撤回したが（受領印の操作群が潰れたため）、2行目の要素は
   元に戻す/やり直す・詳細項目・運賃合計・完了ピルすべて nowrap 指定済みの固定幅で、
   潰れて困る要素が無い＝ここでは安全。2行目は左右グループの両方に当てる
   （右だけでは左の「詳細項目」が2段目に落ちたまま＝実測 top=209 で確認）。
   これで 1280px・id=4（最も詰まる: 使用486px / 幅502px）でもファイル名だけが縮んで収まる。 */
.card-header--2row .ch-row--sub .ch-side { flex-wrap: nowrap; }
/* ただし縮みすぎて何のファイルか読めなくなっては本末転倒なので下限を置く。
   FAX名は 20251201195413687.pdf 形式の固定長なので、60pxあれば先頭の日付部分は読める。 */
.card-header--2row .ch-row--sub .ch-filename { min-width: 60px; }
/* 行が2段になる原因は、ファイル名の幅ではなくボタン内部のテキスト折り返しだった。
   実測のスクショで確認: 「元に戻す」が「元に戻/す」、「やり直す」が「やり直/す」と
   ボタンの中で2行に割れ、ボタン自体の高さが増えて行を 27→42px に押し上げていた。
   数値(幅)だけ見ていた時は「ファイル名がまだ縮む余地があるのに縮まない」と誤読していた。
   要素の幅ではなく中身が折り返していたので、ラベル側を nowrap にする。 */
.card-header--2row .ch-row--sub .btn-sm,
.card-header--2row .ch-row--sub .detail-toggle { white-space: nowrap; }
/* 実物のスクショで確認したところ、ファイル名が左隣の「詳細項目」トグル(left=472,w=69)の
   すぐ右(left=520)に並び、トグルの付随テキストのように見えて情報の切れ目が分からなかった。
   ファイル名は右グループ(.ch-side)の先頭なので、そこに区切り線を引いて左右の境界を示す。
   罫線は border-left（幅を食わない1px）で、pseudo要素は使わない（ellipsis と干渉するため）。 */
.card-header--2row .ch-row--sub .ch-filename {
  padding-left: 12px;
  border-left: 1px solid var(--border);
}
/* 2行になり横幅に余裕ができたので、凡例の余分な左マージンは不要 */
.card-header--2row .ocr-legend { margin-left: 0; }

/* §19(2026-08-15) 指摘「2行にしてくれたのはありがたいけど、もっと見やすさとデザイン改善できない？」
   2行に割っただけでは、59pxの帯に10要素がのっぺり並んでいるだけで
   「どれが主でどれが従か」「どこからどこまでが一組か」が読めなかった。
   実測(1440px・明細ペイン594px): 1行目は左169px/右142pxの間に約280pxの空白が空き、
   左右が無関係な島に見えていた。2行目は操作(元に戻す/やり直す)・凡例・設定(詳細項目)・
   集計(運賃合計/OK)という種類の違う4つが全て同じ見た目で並んでいた。
   方針: (1)1行目=主役、2行目=補助 の階層差を背景と文字サイズで作る
         (2)意味のグループの境目に細い縦線を入れて「一組」を可視化する
         (3)一番見たい集計(運賃合計・完了ピル)を2行目の中で格上げする
   色は既存変数のみ使用＝ライト・ダーク両テーマで自動追従する
   （feedback-light-dark-both-styles: 色付き要素は必ず両モード対応）。 */

/* (1) 1行目を主役に。見出しを大きくし、UPPERCASE由来の間延びを解除する */
.card-header--2row .ch-row--main .ch-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  text-transform: none;
  letter-spacing: 0.02em;
}
/* (2) 2行目は「補助操作の棚」。薄い面を敷いて1行目と分離する。
       .detail-card--flat のヘッダーは背景 transparent なので、この面だけが浮いて見える */
.card-header--2row .ch-row--sub {
  background: var(--surface-2);
  border-radius: 6px;
  padding: 4px 8px;
  margin-top: 0;
}
/* (3) 意味のグループ境界に細い縦線。
       「元に戻す/やり直す」(操作) と 「凡例・詳細項目」(情報) を分ける。
       隣接セレクタなので、undo-redo-group の直後に凡例が来た時だけ線が出る */
/* §19b(2026-08-15) 凡例は1行目へ移したので、区切りは「元に戻す/やり直す」と「詳細項目」の間に出す。
   移した理由（実測）: 1280px・id=4（運賃合計が実値 ¥7,000 の状態）で2行目が
   左289 + 右195 + gap6 + padding12 = 502px となり行幅502pxちょうど。1pxの余裕もなく
   「詳細項目」と「コード未確定 1」が3行目に落ちていた。
   これ以上フォントを詰めると読めなくなるので、要素を1つ1行目へ逃がす構造側の解決にした。
   凡例(85px)を選んだのは、操作ではなく情報表示であり、1行目右側（受領印グループの手前）に
   置いても意味が通るため。1行目は左169/右142で約280px空いていた。 */
.card-header--2row .ch-row--sub .undo-redo-group + .detail-toggle::before {
  content: "";
  display: inline-block;
  width: 1px;
  height: 16px;
  margin-right: 8px;
  vertical-align: -3px;
  /* --border(#dde1e7)では棚の面(--surface-2 #f8f9fb)との差が小さすぎて実質見えなかった
     （実測: 描画はされていたが目視できず）。--text-faint は
     ライト #9ca3af / ダーク #858585 と両テーマで定義済みで、
     どちらの面の上でも区切りとして認識できる濃さがある。 */
  background: var(--text-faint);
  opacity: 0.55;
}
/* (4) 集計(運賃合計・完了ピル)を2行目の中で格上げ。
       2行目全体は10pxに落としてあるが、ここは一番見たい情報なので11pxに戻す */
.card-header--2row .ch-row--sub .freight-total,
.card-header--2row .ch-row--sub .completion-pill {
  font-size: 12px;
}
.card-header--2row .ch-row--sub .ch-side:last-child { gap: 4px; }

.undo-redo-group {
  display: flex; gap: 4px; align-items: center; margin-right: 4px;
}
.undo-redo-group .btn-outline {
  font-size: 12px; padding: 0 8px; min-width: 0;
}
.undo-redo-group .btn-outline:disabled {
  opacity: 0.3; cursor: default;
}
.completion-pill {
  font-size: 12px;
  font-weight: 700;
  padding: 0 8px;
  border-radius: 10px;
  background: var(--surface-3);
  color: var(--text-muted);
  text-transform: none;
}
.completion-pill.ok { background: var(--badge-green-bg); color: var(--green); }
.completion-pill.warn { background: var(--badge-yellow-bg); color: var(--yellow); }
/* §2026-08-01 商品コード未確定が残っている状態。緑OKを出さず赤で残件を示す。
   --badge-red-bg / --red はライト・ダーク両テーマで定義済みのため両対応。 */
.completion-pill.ng { background: var(--badge-red-bg); color: var(--red); }

/* §2026-08-01 FAX1枚の運送運賃合計。荷主に請求する配送運賃の参考値。
   色は変数のみ使用＝ライト・ダーク両テーマで自動追従する。
   .partial(未計算あり)は黄色にして「この合計は全件ではない」と一目で分かるようにする。 */
.freight-total {
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  padding: 0 8px;
  border-radius: 10px;
  background: var(--surface-3);
  white-space: nowrap;
}
.freight-total:empty { display: none; }
.freight-total.partial { background: var(--badge-yellow-bg); color: var(--yellow); }
.freight-total.empty { color: var(--text-muted); font-weight: 600; }

/* Field rows */
.field-rows { padding: 4px 0; }
.field-row {
  display: flex;
  align-items: center;
  padding: 4px 12px;
  border-bottom: 1px solid var(--border);
  gap: 8px;
  min-height: 32px;
}
.field-row:last-child { border-bottom: none; }
.field-label {
  font-size: 12px;
  color: var(--text-muted);
  font-weight: 600;
  min-width: 88px;
  flex-shrink: 0;
}
.field-label.req::after { content: " ＊"; color: var(--red); font-size: 12px; }
.field-static { font-size: 12px; flex: 1; }
.field-static.empty { color: var(--red); font-style: italic; font-size: 12px; }

/* ===== Editable inputs ===== */
.editable-wrap { position: relative; flex: 1; }
.editable-input {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 4px 8px;
  font-size: 12px;
  font-family: inherit;
  background: var(--surface);
  transition: border-color .15s;
}
.editable-input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px var(--focus-ring); }
/* §9(2026-07-31) マスタ照合状態の色分け（伝票共通ペア: .ifield.pair 内 名称+コード）
   コードに値あり=マスタ一致(ok) / コード空+名称あり=マスタ不一致(ng) / 両方空=req-emptyの赤に委ねる */
.ifield.pair:has(.code-mini-input:not(:placeholder-shown)) .editable-input,
.ifield.pair:has(.code-mini-input:not(:placeholder-shown)) .code-mini-input { background: var(--cell-ok); }
.ifield.pair:has(.code-mini-input:placeholder-shown) .editable-input:not(:placeholder-shown),
.ifield.pair:has(.code-mini-input:placeholder-shown):has(.editable-input:not(:placeholder-shown)) .code-mini-input { background: var(--cell-ng); }
/* §2026-08-16 指示 マスタ未確定コード(00000004等)は「値が入っている」だけで
   上のルールでは緑(ok)になってしまう。[マスタ不一致]の警告が出ているのに緑では
   どの行を直せばいいか画面から分からない、という指摘への対応。
   JS(mkPairField)が .code-unresolved を付けた行は問答無用でオレンジ(ng)に上書きする。
   後方に置いて同詳細度で勝たせる。色は変数なのでライト/ダーク両テーマに自動追従。 */
.ifield.pair.code-unresolved .editable-input,
.ifield.pair.code-unresolved .code-mini-input { background: var(--cell-ng); }
.ifield.pair.code-unresolved .code-mini-input { border-color: var(--cell-ng-border); }

.editable-input.req-empty {
  background: var(--cell-empty-required) !important;
  border-color: var(--cell-empty-border) !important;
}

/* ===== Autocomplete ===== */
/* position / top / left / width are set dynamically by setupAc() in app.js */
.ac-list {
  position: fixed;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 4px 20px rgba(0,0,0,.14);
  z-index: 9999;
  max-height: 220px;
  overflow-y: auto;
  display: none;
}
.ac-list.open { display: block; }
.ac-item {
  padding: 8px 12px;
  font-size: 12px;
  cursor: pointer;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.ac-item:last-child { border-bottom: none; }
.ac-item:hover, .ac-item.hi { background: var(--primary-light); }
.ac-code { color: var(--text-muted); font-size: 12px; font-family: monospace; flex-shrink: 0; }
.ac-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ac-empty { padding: 8px 12px; font-size: 12px; color: var(--text-muted); font-style: italic; }

/* ===== Items table ===== */
.items-wrap { overflow-x: auto; }
.items-tbl {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  min-width: 700px;
}
.items-tbl th {
  background: var(--surface-2);
  padding: 8px 8px;
  text-align: left;
  font-size: 12px;
  color: var(--text-muted);
  font-weight: 700;
  white-space: nowrap;
  border-bottom: 1px solid var(--border);
}
.items-tbl th.req::after { content: " ＊"; color: var(--red); }
.items-tbl td {
  padding: 4px 4px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.items-tbl tr:last-child td { border-bottom: none; }
.items-tbl .editable-input { padding: 4px 8px; font-size: 12px; }
.row-num { text-align: center; color: var(--text-muted); font-size: 12px; padding: 0 8px; width: 28px; }

/* ===== Action bar ===== */
.action-bar {
  padding: 8px 16px;
  background: var(--surface);
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.required-status { font-size: 12px; color: var(--text-muted); flex: 1; }
.required-status .all-done { color: var(--green); font-weight: 700; }
.required-status strong { color: var(--text); }

/* ===== Read-only rows ===== */
.info-row {
  display: flex;
  gap: 8px;
  padding: 4px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 12px;
}
.info-row:last-child { border-bottom: none; }
.info-row .key { color: var(--text-muted); min-width: 88px; flex-shrink: 0; }
.info-row .val { flex: 1; word-break: break-all; }
.error-msg { color: var(--red); font-size: 12px; padding: 8px 12px; background: var(--cell-empty-required); }

/* Readonly items */
.ro-items th, .ro-items td { padding: 4px 12px; font-size: 12px; }
.ro-items th { background: var(--surface-2); border-bottom: 1px solid var(--border); font-weight: 700; color: var(--text-muted); font-size: 12px; }
.ro-items td { border-bottom: 1px solid var(--border); }

/* 参考運賃列（SMILE取込対象外・人の検算用） */
.freight-col { text-align: right; white-space: nowrap; }
th.freight-col { color: var(--text-faint); }
.freight-val { color: var(--text-muted); font-variant-numeric: tabular-nums; }
.freight-city { color: var(--text-faint); font-size: 12px; margin-left: 4px; }
.freight-na { color: var(--text-faint); }

/* ===== Buttons ===== */
button {
  border: none;
  border-radius: var(--radius);
  padding: 8px 16px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity .15s;
}
button:hover:not(:disabled) { opacity: .85; }
button:disabled { opacity: .45; cursor: not-allowed; }
.btn-primary { background: var(--primary); color: #fff; }
.btn-success { background: var(--green); color: #fff; }
.btn-outline { background: var(--surface); color: var(--text); border: 1px solid var(--border); }
.btn-danger { background: #ef4444; color: #fff; border: none; }
.btn-danger:hover:not(:disabled) { background: #dc2626; }
.btn-reset-all { color: #92400e; border-color: #d97706; }
.btn-reset-all:hover:not(:disabled) { background: var(--badge-yellow-bg); }
/* §2026-08-20 admin ロール限定要素。既定は非表示。body.role-admin が付いたときだけ出す。 */
.admin-only { display: none !important; }
body.role-admin .admin-only { display: inline-flex !important; }
/* §2026-08-20 TESTモード限定要素（無作為サンプル再読込など）。admin かつ TESTモードON のときだけ出す。 */
.testmode-only { display: none !important; }
body.role-admin.testmode-on .testmode-only { display: inline-flex !important; }

/* §2026-08-20 TESTモードの赤バナー（テストプロセス:8001 でのみ表示）。
   画面最上部に固定し、「本番ではない」ことを常時明示する。誤操作防止の要。 */
#testmode-banner {
  position: fixed; top: 0; left: 0; right: 0; z-index: 9999;
  display: flex; align-items: center; justify-content: center; gap: 16px;
  height: 40px; padding: 0 16px;
  background: #b91c1c; color: #fff;
  font-size: 12px; font-weight: 600;
  box-shadow: 0 2px 8px rgba(0,0,0,0.25);
}
#testmode-banner strong { font-weight: 800; }
#testmode-banner #testmode-exit-btn {
  border: 1px solid rgba(255,255,255,0.7); background: transparent; color: #fff;
  padding: 4px 12px; border-radius: 5px; font-size: 12px; font-weight: 600; cursor: pointer;
}
#testmode-banner #testmode-exit-btn:hover { background: rgba(255,255,255,0.15); }
/* バナーぶん本文を押し下げる（固定バナーが中身に被らないように） */
body.has-testmode-banner { padding-top: 40px; }

/* §2026-08-20 本番プロセス側(admin)の「TESTモードへ」ボタン。ヘッダーに出す。 */
.testmode-enter-btn { color: #b91c1c; border-color: #b91c1c; }
.testmode-enter-btn:hover:not(:disabled) { background: rgba(185,28,28,0.08); }
:root[data-theme='dark'] .testmode-enter-btn { color: #f87171; border-color: #b91c1c; }

.btn-sm { padding: 4px 12px; font-size: 12px; border-radius: 5px; }
/* §2026-08-22 ヘッダーのボタン(⚙設定/🧪TESTモードへ)をタブバーのボタンと同寸(13px/30px)に統一
   （指摘「ボタンサイズもヘッダーとタブバーとで変わっちゃった」）。
   .btn-sm は設定モーダル等でも多用されているためグローバルには変えず、ヘッダー内だけ上書きする。 */
.header-meta .btn-sm {
  height: 28px;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  font-size: 12px;
  line-height: 1;
  padding: 0 12px;
}

/* ===== Toast ===== */
#toast {
  position: fixed;
  bottom: 20px; right: 20px;
  background: #1e2532;
  color: #fff;
  padding: 12px 16px;
  border-radius: var(--radius);
  font-size: 12px;
  opacity: 0;
  transition: opacity .25s;
  pointer-events: none;
  z-index: 999;
  max-width: 300px;
}
#toast.show { opacity: 1; }
#toast.ok { background: var(--green); }
#toast.ng { background: var(--red); }

/* ===== Setup modal ===== */
#setup-overlay {
  position: fixed; inset: 0;
  background: var(--overlay);
  z-index: 900;
  display: flex; align-items: center; justify-content: center;
}
#setup-overlay.hidden { display: none; }
.setup-card {
  background: var(--surface); border-radius: 12px; padding: 28px;
  width: 460px; max-width: 95vw;
  box-shadow: 0 8px 32px rgba(0,0,0,.2);
}
.setup-card h2 { font-size: 16px; margin-bottom: 8px; }
.setup-card p { font-size: 12px; color: var(--text-muted); margin-bottom: 16px; }
.form-group { margin-bottom: 16px; }
.form-group label { display: block; font-size: 12px; font-weight: 600; margin-bottom: 4px; }
.form-group input, .form-group select {
  width: 100%; border: 1px solid var(--border);
  border-radius: 8px; padding: 8px 12px; font-size: 12px;
}
.form-group .hint { font-size: 12px; color: var(--text-faint); margin-top: 4px; }

/* §2026-08-22 テーマ選択（個人設定タブ）。
   ラジオは .form-group input の width:100% に巻き込まれるので、この2つだけ実寸に戻す。
   選択肢どうしの間隔(24px) > ラジオと文字の間隔(8px) ＝ 近接の不等式（設計原則1）。
   枠線や背景パネルは足さない。ラベル文字だけで意味が通る（原則5・6）。 */
.theme-choice { display: flex; align-items: center; gap: 24px; margin-top: 4px; }
/* .form-group label { display:block; font-weight:600; margin-bottom:4px } と同じ詳細度だと
   後勝ちで block に潰され、gap が無効化してラジオと文字が密着した（実測 0px）。
   margin-left で押すのは対症療法なので、詳細度を上げて inline-flex を効かせて根本解決する。 */
.form-group label.theme-choice-item {
  display: inline-flex; align-items: center; gap: 8px;
  /* .form-group label の block/600/margin を打ち消して、選択肢の文字は本文ウェイトに戻す */
  margin-bottom: 0; font-weight: 400; font-size: 12px; cursor: pointer;
}
.theme-choice-item input[type="radio"] {
  width: 16px; height: 16px; margin: 0; padding: 0; flex-shrink: 0;
  accent-color: var(--primary);  /* ライト/ダーク両方でトークン追従 */
}
.setup-footer { display: flex; justify-content: flex-end; gap: 8px; margin-top: 20px; }
#setup-error { color: #dc2626; font-size: 12px; margin-top: 4px; display: none; }

/* APIキーをお持ちでない方リンク */
.setup-guide-link {
  color: var(--primary); font-size: 12px; text-decoration: none; font-weight: 600;
}
.setup-guide-link:hover { text-decoration: underline; }

/* APIキー発行 解説画面 */
.setup-guide .setup-back {
  background: none; border: none; color: var(--text-muted);
  font-size: 12px; cursor: pointer; padding: 0 0 12px; display: inline-block;
}
.setup-guide .setup-back:hover { color: var(--text); }
.setup-guide h2 { font-size: 16px; margin-bottom: 8px; }
.setup-guide > p { font-size: 12px; color: var(--text-muted); margin-bottom: 16px; line-height: 1.6; }
.setup-steps {
  margin: 0 0 16px; padding-left: 24px; font-size: 12px; color: var(--text);
  line-height: 1.7;
}
.setup-steps li { margin-bottom: 8px; }
.setup-steps code {
  background: var(--overlay); border: 1px solid var(--border);
  border-radius: 4px; padding: 0 4px; font-size: 12px;
}
.setup-open-link {
  display: inline-flex; align-items: center; justify-content: center;
  text-decoration: none; width: 100%; padding: 12px 0; font-size: 16px; font-weight: 600;
}
.setup-guide-note { font-size: 12px; color: var(--text-faint); margin: 8px 0 16px; }
.setup-back-btn {
  background: none; border: 1px solid var(--border); color: var(--text);
  border-radius: 8px; padding: 8px 16px; font-size: 12px; cursor: pointer; width: 100%;
}
.setup-back-btn:hover { background: var(--overlay); }

/* ログインオーバーレイ（テナントID・入室者名・パスワード） */
#login-overlay {
  position: fixed; inset: 0;
  background: var(--overlay);
  z-index: 950;
  display: flex; align-items: center; justify-content: center;
}
/* §2026-08-22 未認証時はメインUIを一切描画しない（プライバシー）
   ログイン前に背後でテナントのロゴ・業務構成・稼働状況が読めていた問題の根治。
   個別要素を列挙せず「ログイン画面以外のbody直下」を全て閉じる＝将来要素が増えても自動で守られる。
   オーバーレイ自身も不透明にして、透過で何かが覗く余地を残さない。 */
body.pre-auth > *:not(#login-overlay) { display: none !important; }
body.pre-auth #login-overlay { background: var(--bg); }
body.pre-auth { overflow: hidden; }

/* §2026-08-22 ログイン画面はライトモード限定（指示）。
   ダークだとサービスロゴの PLACEHOLDER が背景に沈んで読めず、顧客ロゴ2枚だけが
   白い箱として浮いて不揃いに見えた＝ブランド面として成立していなかった。
   ログイン後は従来どおりユーザーの faxTheme 設定（ライト/ダーク）に戻る。
   実装: 個別セレクタを色ごとに上書きするのではなく（＝キメラコードになる）、
   このスコープでライトのトークンを再宣言して一括で解決する。変数名は :root と同一なので
   配下の既存ルールは一切書き換えずにライト配色へ切り替わる。
   色値は :root（ライト）からの写しで、ライト側を変えたらここも合わせる。 */
#login-overlay {
  color-scheme: light;
  --bg: #f0f2f5;
  --surface: #ffffff;
  --border: #dde1e7;
  --primary: #1a56db;
  --primary-light: #e8f0fe;
  --text: #1e2532;
  --text-muted: #6b7280;
  --text-faint: #9ca3af;
  --surface-2: #f8f9fb;
  --surface-3: #f1f3f6;
  --hover: #eff6ff;
  --shadow: 0 1px 3px rgba(0,0,0,.08);
  --focus-ring: rgba(26, 86, 219, .12);
  --red: #dc2626;
  color: var(--text);
}
/* オーバーレイの地色も同じライト値で塗る（body側の背景がダークのままだと縁が黒く残る） */
body.pre-auth #login-overlay { background: #f0f2f5; }

#login-overlay.hidden { display: none; }
.login-box {
  background: var(--surface); border-radius: 12px; padding: 32px;
  /* §2026-08-22 ロゴ拡大(指示)に合わせて版面も広げる。420px なら顧客ロゴ2枚(実寸56px相当)＋
     間隔24px が横並びのまま収まり、折り返しが起きない。padding は 28→32px（8の倍数）。 */
  width: 420px; max-width: 92vw;
  box-shadow: 0 8px 32px rgba(0,0,0,.2);
}
/* §2026-08-22 ログイン画面の3段構成
   上段(.login-brand): サービスロゴ＋タイトル＋自社クレジット。中央揃え
   中段(.login-clients): 顧客ロゴを横並び中央（複数可）
   下段: 入力フォーム。ラベル/入力は左揃えのまま（視線の起点を左端に固定）
   近接の不等式: ブランド内 8px < 段と段の間 24px < 中段と下段 32px */
.login-brand { text-align: center; }
.login-brand h2 { font-size: 20px; margin-bottom: 0; }
/* §2026-08-22 「ロゴはもう少し大きくても良いでしょ」→ 40px→56px。
   タイトル(20px)に対する比が 2.0→2.8倍になり、上段の主役がロゴだと一目で分かる（対比・原則4）。
   下の margin 8px は据え置き＝ロゴとタイトルは1つの塊のまま（近接・原則1）。 */
.login-service-logo { height: 56px; width: auto; color: var(--text); margin-bottom: 8px; }
.login-powered {
  font-size: 12px; font-weight: 500; color: var(--text-muted);
  letter-spacing: 0.04em; margin-bottom: 0;
}
.login-clients {
  display: flex; align-items: center; justify-content: center;
  flex-wrap: wrap; gap: 24px;
  margin-top: 24px; padding-top: 24px;
  border-top: 1px solid var(--border);
}
/* 顧客ロゴは元画像が白背景前提（透過PNGと白地JPGが混在）。ダークだと片方が沈み片方だけ白い箱に
   なって不揃いになるため、両モードとも白い版面に載せて見え方を揃える。
   padding 8px は「要素内の余白」＝ロゴ間 24px より小さく保ち、近接の不等式を崩さない。 */
.login-client-logo {
  /* §2026-08-22 32px→48px。目視すると 40px では白padding(8px)込みの箱が56pxになる一方で
     ロゴ本体は40pxしかなく、サービスロゴ(56px)に対して脇役になりすぎていた。
     48px なら本体比 56:48 で序列は保ったまま、顧客名が読める大きさになる。 */
  height: 48px; width: auto;
  background: #fff; border-radius: 4px; padding: 8px;
  box-sizing: content-box;
}
.login-lead {
  font-size: 12px; color: var(--text-muted);
  margin-top: 32px; margin-bottom: 16px;
}
.login-box h2 { font-size: 20px; margin-bottom: 8px; }
.login-box p { font-size: 12px; color: var(--text-muted); margin-bottom: 16px; }
.color-swatches { display: flex; flex-wrap: wrap; gap: 8px; }
.color-swatch {
  width: 28px; height: 28px; border-radius: 50%;
  border: 2px solid transparent; cursor: pointer;
  transition: transform .12s ease, border-color .12s ease;
}
.color-swatch:hover { transform: scale(1.1); border-color: var(--border); }
.color-swatch.selected { border-color: var(--text); transform: scale(1.1); }
.login-error {
  color: #dc2626; font-size: 12px; margin-top: 12px;
  background: rgba(220,38,38,.08); border: 1px solid rgba(220,38,38,.25);
  border-radius: 6px; padding: 8px 12px;
}
.login-error.hidden { display: none; }

/* Spinner */
.spinner {
  display: inline-block; width: 12px; height: 12px;
  border: 2px solid var(--border); border-top-color: var(--primary);
  border-radius: 50%; animation: spin .6s linear infinite; vertical-align: middle;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ===== §5 SMILE式明細レイアウト（2026-07-05）=====
   伝票共通セクション1回＋列ヘッダー1回＋1明細=3段固定グリッド。
   段構成は画面幅で変えない（旧§2のflex-wrap折り返しを廃止）。
   狭幅は .smile-wrap の横スクロールで逃がす。
   列幅（--icols1〜3）は桁数ベースのch固定＋名称・摘要系のみminmax可変。
   §8(2026-07-31): 列ヘッダーは廃止し、ラベルは各セルの真上に表示（伝票共通と同方式）。 */
.smile-wrap {
  overflow-x: auto;
  /* §6 pair化(2026-07-05): 商品・倉庫を名称+コードの縦積み1列に統合し列数を削減。
     数量+単位も1セルに統合。列が減ることで列ズレ耐性も上がる。 */
  /* 段1: 商品[名+コード] / 数量[数+単位] / 入数 / 行削除
     ※§8追記(2026-07-31): 行番号は段グリッド外の独立列(.item-lineno)へ移動

     §2026-08-26 ラベル下限の導入（Mayank指摘「OCRの●マークと必須の*マークと文字とが重なってる。
     余裕がないなら左の商品名エリアを短くするとかいくらでも方法はあるよね？こういうことないようにして欲しい」）。
     真因: 列幅を「値の桁数」だけで決めていたため、真上に出すラベル（項目名+必須*+OCR●）の実幅が
     列幅を超えた列で、.ifield-label が white-space:nowrap のまま .igrid > *{min-width:0} で
     セルを潰され、中身が右へあふれて隣のラベルに重なっていた。
     実測(font-size:12px/weight:600, 1ch=8.13px):
       数量（単位）*● 必要92.1px vs 9ch=73.2px → 18.9px超過（ユーザーが見た重なり）
       明細区分●     必要60.0px vs 5ch=40.7px → 19.3px超過（detail-onlyで隠れていただけ）
       摘要コード●   必要72.0px vs 8ch=65.0px → 7.0px超過（同上）
     対策: 各列を max(値に要る桁数, ラベルに要る幅) にして「ラベルが列幅の下限を決める」構造にする。
     以後どの列も、ラベルを長くしても列がラベルより狭くならない＝同じ重なりが再発しない。
     --lbl-* はラベル実測幅を4の倍数chへ切り上げたもの（原則13）。 */
  /* ラベル下限。※単位はpx。ch は .smile-wrap のフォント基準で解決され、
     ラベル(12px/600)の実測 1ch=8.13px と一致しないため使わない（実測で 12ch が 89.4px にしかならず不足した）。
     値 = ラベル実測幅を 4 の倍数 px へ切り上げ ＋ 左右パディング相当 8px（原則13）。 */
  --lbl-qty: 104px;     /* 数量（単位）*● 92.1px */
  --lbl-pieces: 48px;   /* 入数●         36.0px */
  --lbl-best: 72px;     /* 賞味期限●     60.0px */
  --lbl-orderno: 68px;  /* 発注No.●      57.6px */
  --lbl-weight: 48px;   /* 重量●         36.0px */
  --lbl-freight: 68px;  /* 運賃(参考)     59.8px */
  --lbl-dclass: 72px;   /* 明細区分●     60.0px */
  --lbl-tax: 48px;      /* 課税●         36.0px */
  --lbl-calc: 48px;     /* 金計●         36.0px */
  --lbl-sumcode: 80px;  /* 摘要コード●   72.0px */
  --icols1: minmax(11em, 1fr) max(9ch, var(--lbl-qty)) max(8ch, var(--lbl-pieces)) 34px;
  /* 段2: 倉庫[名+コード] / 賞味期限 / 発注No. / 重量 / 運賃(参考・読取専用)
     ※§2026-08-01追記: 末尾に運賃列を追加。金額は最大6桁(¥100,000)想定で10ch確保 */
  --icols2: minmax(10em, 1fr) max(12ch, var(--lbl-best)) max(12ch, var(--lbl-orderno))
            max(9ch, var(--lbl-weight)) max(10ch, var(--lbl-freight));
  /* 段3: 明細区分 / 課税 / 金計 / 摘要コード / 行摘要１ / 行摘要２ */
  --icols3: max(5ch, var(--lbl-dclass)) max(5ch, var(--lbl-tax)) max(5ch, var(--lbl-calc))
            max(8ch, var(--lbl-sumcode)) minmax(7em, 1fr) minmax(7em, 1fr);
}
/* 伝票共通セクション（全行に反映される項目。ラベル付き .ifield を流用） */
.slip-common {
  padding: 8px 12px 8px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  min-width: min-content;
}
/* §6 上揃え(2026-07-05指示): 下揃え(end)だと pair/非pairで底が揃い頭がガタつく。
   start で各セルの上端(ラベル/名称の頭)を横一線に揃える。 */
.sc-grid { display: grid; gap: 4px 8px; align-items: start; }
/* 段1(§8で並び替え): 伝票日付 / 担当者 / [詳細: 伝票No. / 処理連番 / 請求 / 売掛 / 取引 / 属性]
   ※ max-content は input の固有min-content(約180px)を拾って暴発するため固定ch必須 */
.sc-g1 {
  grid-template-columns: 9ch minmax(8em, 1fr) 9ch 10ch 4.5ch 4.5ch 4.5ch 4.5ch;
  margin-bottom: 4px;
}
/* §8 項目最小化: 詳細トグルOFF時は区分値・摘要系(.detail-only)を隠し、
   段1グリッドは常時表示2項目(伝票日付・担当者)分の列定義に切り替える */
.smile-wrap:not(.show-detail) .detail-only { display: none; }
.smile-wrap:not(.show-detail) .sc-g1 { grid-template-columns: 9ch minmax(8em, 20em); }
.detail-toggle {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 12px; color: var(--text-muted); font-weight: 600;
  margin-left: 12px; cursor: pointer; user-select: none;
  white-space: nowrap;
}
.detail-toggle input { accent-color: var(--primary); cursor: pointer; }
/* 段2: 得意先名１(ペア) / 得意先名２ / 納品先名(ペア) */
.sc-g2 { grid-template-columns: minmax(13em, 2fr) minmax(9em, 1fr) minmax(13em, 2fr); }
/* .ifield の旧折り返し用固定幅はグリッド内では列幅に任せる。
   min-width:0 はグリッドアイテムのauto min size(=inputの固有幅)を殺す定石 */
.sc-grid .ifield,
.sc-grid .ifield.pair { width: auto; max-width: none; min-width: 0; }
.igrid > * { min-width: 0; }
/* §8(2026-07-31): 離れた列ヘッダー(.items-colhdr)は廃止。ラベルは各セルの真上
   (.igrid .ifield / .cell-pair / .qty-cell 先頭の .ifield-label)に出す。 */
/* §6 上揃え(2026-07-05指示): pairセル(名称+コード2段)と単段セルが混在するため
   start で各セルの頭を揃える。削除ボタンだけ後段で中央維持に上書き。 */
.igrid { display: grid; gap: 4px 8px; align-items: start; }
.igrid-l1 { grid-template-columns: var(--icols1); }
.igrid-l2 { grid-template-columns: var(--icols2); }
.igrid-l3 { grid-template-columns: var(--icols3); }
.items-blocks {
  padding: 4px 12px 8px;
  display: flex; flex-direction: column; gap: 8px;
  min-width: min-content;
}
/* §8追記(2026-07-31): 行番号の真下に他の欄が来ない視認性指示 →
   .item-row を「左=行番号の縦通し列 / 右=段1〜3の積み」の2カラムflexにする */
.item-row {
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  padding: 4px 8px;
  display: flex; gap: 8px; align-items: stretch;
}
.item-lineno {
  flex: 0 0 auto;
  padding-right: 8px;
  border-right: 1px dashed var(--border);
}
.item-lineno .ifield { width: auto; max-width: none; min-width: 0; }
/* ※.item-row .editable-input(同特異性・後方)にpaddingを上書きされないよう3クラスで強める */
.item-row .item-lineno .editable-input {
  width: 3.5ch; min-width: 3.5ch;
  text-align: center; padding: 4px 4px;
}
.item-stages { flex: 1 1 auto; min-width: 0; }
/* §8 段の意味グルーピング(1段目=商品・数量 / 2段目=物流 / 3段目=会計・摘要)を
   破線で軽く区切って視覚化。ラベルが各段に付いた分、段の境界を明示する */
.item-stages .igrid + .igrid {
  margin-top: 8px; padding-top: 4px;
  border-top: 1px dashed var(--border);
}
.item-row .editable-input { padding: 4px 8px; font-size: 12px; }
/* §8 明細セルも .ifield 化(ラベル+入力の縦積み)。伝票共通(.sc-grid .ifield)と同じく
   旧固定幅を打ち消してグリッド列幅に任せる */
.igrid .ifield { width: auto; max-width: none; min-width: 0; }
.code-cell { font-family: monospace; }
/* app.js injectStyles の旧テーブル用 .btn-row-del（display:none / absolute・tr:hover前提）を
   グリッド内では常時表示のボタンに上書きする */
.item-row .btn-row-del {
  display: inline-block; position: static; transform: none;
  width: auto; height: auto; padding: 4px 8px; font-size: 12px;
  justify-self: center; align-self: center; /* §6 行上揃え(start)でも削除ボタンは縦中央 */
}
.ifield {
  display: flex; flex-direction: column; gap: 4px;
  width: 128px; flex-grow: 1; max-width: 220px;
}
.ifield.pair { width: 168px; max-width: 260px; }
.ifield-label {
  font-size: 12px; color: var(--text-muted); font-weight: 600;
  white-space: nowrap; display: flex; align-items: center; gap: 4px;
}
/* §16(2026-08-14) 必須マーク。
   旧: `.ifield-label.req::after` で出していたが、::after は要素の**末尾**にしか置けず、
   OCRマーク●のさらに右＝隣のセルとの中間に＊が浮いて、どの項目の必須マークか
   分からなくなっていた（ユーザー指摘「数量（単位）●＊ 入数」）。
   新: HTML側(fieldLabelHtml)で項目名の直後に <sup class="req-mark"> を挿入する。
   ・親が display:flex なので sup の vertical-align は効かない。align-self:flex-start で上寄せする
   ・gap:4px を margin-left:-4px で打ち消し、項目名にぴったり密着させる
   ・line-height:1 + 上に微調整で「名前の右肩」に見せる。行の高さは変えない
     （明細行の高さが変わるとレイアウトが動くため）
   微調整(2026-08-14 追加指示): 「左も右も余白を小さく、文字ももっと小さく」。
   ・文字は全角＊→**半角***に変更（app.js側）。全角は文字送りが1emでグリフ自体が
     左右に余白を持つため、半角化だけで左右の余白が構造的に半減する（ユーザー提案）
   ・font-size 11px→9px、margin-left -3px→-4px（gap相殺+1px）、margin-right -1px を追加
     ＝＊の右（●との間）も詰める */
.req-mark {
  color: var(--red);
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  margin-left: -4px;      /* §grid48 flexのgap(4px)をちょうど打ち消し、項目名に密着させる */
  margin-right: 0;        /* §grid48 -1px→0。4/8倍数外の魔法数字を排除（詰め効果1px分は許容差） */
  align-self: flex-start; /* 中央揃えの親の中で、この文字だけ上に寄せる＝右肩 */
  position: relative;
  top: -1px;
}

/* §2026-08-01 明細1行の運賃セル。
   §2026-08-16 指示で **編集可能** にした（運賃表に無い納品先・特例料金・値引きが実在し、
   自動計算では出せない行があるため）。他の30項目と同じ .editable-input を土台にし、
   金額なので右寄せ＋等幅数字だけ足す。色は変数のみ＝ライト・ダーク両テーマ対応。 */
.freight-val {
  padding: 4px 8px; font-size: 12px; font-weight: 700;
  color: var(--text); background: var(--surface-3);
  border: 1px dashed var(--border); border-radius: 4px;
  text-align: right; white-space: nowrap; cursor: default;
}
.freight-val.empty { color: var(--text-muted); font-weight: 400; text-align: center; }
.ifield .editable-input.freight-input {
  text-align: right; font-variant-numeric: tabular-nums; font-weight: 700;
}
.ifield .editable-input.freight-input::placeholder {
  font-weight: 400; text-align: center; color: var(--text-faint);
}
/* 「自動」ボタン＝手入力の印を外して自動計算に戻す。手入力中の行にだけ出る。
   ラベル「運賃」の右に小さく置く（列幅を増やさないため）。 */
.freight-auto-btn {
  margin-left: 4px; padding: 0 4px; font-size: 12px; line-height: 16px;
  font-weight: 700; border-radius: 3px; cursor: pointer;
  color: var(--blue); background: var(--surface-3);
  border: 1px solid var(--border);
}
.freight-auto-btn:hover { background: var(--blue); color: #fff; border-color: var(--blue); }
.ocr-mark { color: var(--blue); font-size: 8px; }
.ocr-legend { font-size: 12px; color: var(--text-muted); font-weight: 400; margin-left: 8px; }
.ifield .editable-input { padding: 4px 8px; font-size: 12px; }
.ro-input {
  background: var(--surface-3) !important; color: var(--text-muted);
  border-style: dashed; cursor: default;
}
/* コード⇔名称ペアのコード欄（名称の下に細く） */
.code-mini-input {
  width: 100%;
  border: 1px solid var(--border); border-radius: 4px;
  padding: 0 4px; font-size: 12px; font-family: monospace;
  background: var(--surface);
  transition: border-color .15s;
}
.code-mini-input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px var(--focus-ring); }
.code-mini-input.req-empty {
  background: var(--cell-empty-required) !important;
  border-color: var(--cell-empty-border) !important;
}
/* §2 早出し引取不可冷蔵庫 → 蛍光黄（マスタ照合背景より優先） */
.editable-input.wh-early-ng { background: #fef08a !important; border-color: #eab308 !important; }
/* §3 伝票発行ボタン・タグ */
.btn-issue-slip {
  background: var(--primary); color: #fff;
  padding: 4px 12px; font-size: 12px; border-radius: 5px; margin-left: 8px;
}
.slip-issued-tag {
  display: inline-block; margin-left: 8px;
  background: var(--badge-green-bg); color: var(--badge-green-tx);
  font-size: 12px; font-weight: 700;
  padding: 0 8px; border-radius: 10px;
}
/* §2026-08-15 指示⑤ 発行した伝票PDF（納品書3枚1セット / 出庫伝票）を開くリンク。
   発行済みタグのすぐ右に並べる＝「発行した結果の実物はここ」と読める位置。
   色はテーマ変数だけで組む（ライト/ダーク両方で成立させるため。片方だけ実装しない）。 */
.slip-pdf-link {
  display: inline-block; margin-left: 8px;
  background: var(--badge-blue-bg); color: var(--blue);
  font-size: 12px; font-weight: 700;
  padding: 0 8px; border-radius: 10px;
  text-decoration: none;
  border: 1px solid transparent;
}
.slip-pdf-link:hover { border-color: var(--blue); }
.slip-pdf-link:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--focus-ring); }
/* §3 一覧側の発行済みバッジ: 詳細のタグ(.slip-issued-tag)と同系色で、狭い一覧行に収まる小型版 */
.list-issued-badge {
  display: inline-block;
  background: var(--badge-green-bg); color: var(--badge-green-tx);
  font-size: 12px; font-weight: 700;
  padding: 0 8px; border-radius: 8px;
  vertical-align: middle;
}
.fax-corr-tag {
  display: inline-block; margin-left: 8px;
  background: var(--badge-orange-bg); color: var(--badge-orange-tx);
  font-size: 12px; font-weight: 700;
  padding: 0 8px; border-radius: 10px;
}
/* ===== §6 明細のpairセル・数量統合セル（2026-07-05）=====
   商品・倉庫: 名称input(上)＋コードinput(下)の縦積み=伝票共通のpairと同じ見た目。
   数量: 数量input＋単位inputの縦積み(単位はplaceholder表記)。
   1grid列に収めるため .editable-wrap を縦に2つ並べる。 */
.cell-pair, .qty-cell { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cell-pair .editable-wrap, .qty-cell .editable-wrap { width: 100%; }
/* pair下段・数量下段のコード/単位欄は細く（伝票共通 .code-mini-input と同トーン） */
.item-row .cell-pair .code-cell {
  width: 100%;
  border: 1px solid var(--border); border-radius: 4px;
  padding: 0 4px; font-size: 12px; font-family: monospace;
  background: var(--surface); transition: border-color .15s;
}
.item-row .cell-pair .code-cell:focus {
  outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px var(--focus-ring);
}
/* §9(2026-07-31) マスタ照合状態の色分け（明細ペア: .cell-pair 内 名称+コード） */
.cell-pair:has(.code-cell:not(:placeholder-shown)) .editable-input,
.item-row .cell-pair:has(.code-cell:not(:placeholder-shown)) .code-cell { background: var(--cell-ok); }
.cell-pair:has(.code-cell:placeholder-shown) .editable-input:not(:placeholder-shown),
.item-row .cell-pair:has(.code-cell:placeholder-shown):has(.editable-input:not(:placeholder-shown)) .code-cell { background: var(--cell-ng); }
.item-row .cell-pair .code-cell.req-empty {
  background: var(--cell-empty-required) !important;
  border-color: var(--cell-empty-border) !important;
}
/* §2026-08-16 指示A② 「＋マスタ登録」ボタン（商品コード欄の右端に重ねる）。
   マスタに実在しないコード or コード未入力の行だけ出す（表示制御はJS refreshMasterRegButtons）。
   色は全て変数なのでライト/ダーク両テーマに自動追従する。 */
.item-row .cell-pair .editable-wrap.has-master-reg .code-cell { padding-right: 72px; }
.btn-master-reg {
  position: absolute; right: 3px; top: 50%; transform: translateY(-50%);
  padding: 0 4px; font-size: 12px; font-weight: 600; line-height: 1.5;
  color: var(--primary); background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 3px;
  cursor: pointer; white-space: nowrap;
  transition: background .15s, border-color .15s;
}
.btn-master-reg:hover { background: var(--hover); border-color: var(--primary); }
.btn-master-reg:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--focus-ring); }
.btn-master-reg[hidden] { display: none; }
/* 数量下段(単位)は数量よりさらに控えめに */
.item-row .qty-cell .qty-unit {
  font-size: 12px; padding: 0 4px; color: var(--text-muted);
}
.items-empty-cell { padding: 16px 12px; font-size: 12px; color: var(--text-muted); font-style: italic; }

/* ===== §7 訂正FAX紐づけパネル（2026-07-04指示・Stage D）===== */
.link-panel {
  margin: 8px 12px 12px; padding: 12px 12px;
  background: #fff7ed; border: 1px solid #fed7aa; border-radius: 8px;
}
.link-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.link-select {
  flex: 1; min-width: 220px; max-width: 520px;
  padding: 4px 8px; font-size: 12px;
  border: 1px solid var(--border); border-radius: 6px; background: var(--surface);
}
.link-status { margin-top: 4px; font-size: 12px; color: var(--text-muted); }
.link-status b { color: var(--badge-orange-tx); }
.link-status .link-orig { color: var(--blue); text-decoration: underline; cursor: pointer; }
.link-none { font-style: italic; }
/* §2026-08-16 新指示① 「紐づけ完了」チェックボックスのスタイル
   （.link-confirm-label / .list-link-label / .list-link-cb）は、
   チェックUI自体を廃止したため削除した。紐づけ状態は .badge-linked が表す。 */

/* ===== §2026-08-16 訂正FAXの明細マージ ===== */
/* 色は全て変数なのでライト/ダーク両テーマに自動追従する。
   使用変数は両ブロックに定義済みであることを実測確認済み。 */

/* 「訂正を大元に反映」ボタン。実行すると大元の明細が書き換わる操作なので、
   通常の btn-outline より一段強い見え方にして、押す前に気づけるようにする */
.btn-merge {
  background: var(--primary); color: #fff;
  border: 1px solid var(--primary); border-radius: 6px;
  cursor: pointer; font-family: inherit;
}
.btn-merge:hover:not(:disabled) { filter: brightness(1.08); }
.btn-merge:disabled { opacity: .45; cursor: not-allowed; }

.merge-overlay {
  position: fixed; inset: 0; z-index: 10002;
  background: var(--overlay);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.merge-dialog {
  width: min(760px, 100%); max-height: 88vh; overflow-y: auto;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 12px 40px rgba(0,0,0,.28);
  padding: 16px 20px 16px;
}
.merge-head {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
  padding-bottom: 12px; margin-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.merge-title { font-size: 16px; font-weight: 700; }
.merge-sub { font-size: 12px; color: var(--text-muted); margin-top: 4px; }
.merge-x {
  background: none; border: none; cursor: pointer;
  font-size: 20px; line-height: 1; color: var(--text-muted); padding: 4px 8px;
}
.merge-x:hover { color: var(--text); }

/* 訂正FAXに書かれていた文言。どの行を直すかを人が判断する一番の材料なので必ず出す */
.merge-note {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 6px; padding: 8px 12px; margin-bottom: 12px;
}
.merge-note-h { font-size: 12px; font-weight: 700; color: var(--text-muted); margin-bottom: 4px; }
.merge-note-b { font-size: 12px; line-height: 1.65; white-space: pre-wrap; }

/* 反映によって巻き戻るもの（確認済み・伝票No.）の予告。押す前に見せる */
.merge-warn {
  background: var(--badge-yellow-bg); color: var(--badge-yellow-tx);
  border-radius: 6px; padding: 8px 12px; margin-bottom: 12px;
  font-size: 12px; line-height: 1.7;
}

.merge-sec-h {
  font-size: 12px; font-weight: 700; color: var(--text-muted);
  margin: 16px 0 8px; padding-bottom: 4px;
  border-bottom: 1px solid var(--border);
}

/* §2026-08-17 マージ画面のFAX原本ビュー（訂正と大元を見比べる）。
   2つのPDFは結合せず、連続ページで縦に流して境目に区切り帯を出す方式。
   色は全てテーマ変数で組むのでライト/ダーク両方に自動追従する。 */
.merge-pv { margin-bottom: 4px; }
.merge-pv-chips { display: flex; gap: 8px; margin-bottom: 8px; }
.merge-pv-chip {
  font-size: 12px; padding: 4px 12px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text-muted); cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.merge-pv-chip:hover { background: var(--surface-2); color: var(--text); }
.merge-pv-chip.active {
  background: var(--primary); border-color: var(--primary); color: #fff; font-weight: 700;
}
.merge-pv-chip:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
/* 高さを固定して中だけスクロールさせる。min-height:0 が無いと
   flex/grid の子として縮まず overflow-y が効かない（2026-08-17 の再発防止） */
.merge-pv-scroll {
  max-height: 46vh; min-height: 0; overflow-y: auto;
  background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 6px;
  padding: 8px;
}
.merge-pv-band {
  position: sticky; top: -8px; z-index: 1;
  font-size: 12px; font-weight: 700;
  padding: 8px 8px; margin: 0 0 8px;
  border-radius: 4px;
}
.merge-pv-band:not(:first-child) { margin-top: 16px; }
/* 訂正＝黄（注意を引く側）／大元＝緑（今の確定内容）。既存バッジの配色に揃える */
.merge-pv-band-corr { background: var(--badge-yellow-bg); color: var(--badge-yellow-tx); }
.merge-pv-band-orig { background: var(--badge-green-bg); color: var(--badge-green-tx); }
.merge-pv-page { margin-bottom: 12px; }
.merge-pv-pagenum {
  font-size: 12px; color: var(--text-faint); margin-bottom: 4px;
}
.merge-pv-page img {
  width: 100%; height: auto; display: block;
  background: #fff;
  border: 1px solid var(--border); border-radius: 4px;
}
.merge-pv-missing {
  font-size: 12px; color: var(--text-muted);
  padding: 16px 12px; text-align: center;
  background: var(--surface); border: 1px dashed var(--border); border-radius: 4px;
  margin-bottom: 12px;
}
.merge-row {
  padding: 8px 12px; margin-bottom: 8px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 6px;
}
.merge-src { font-size: 12px; font-weight: 600; }
.merge-arrow { font-size: 12px; color: var(--text-muted); margin: 4px 0 4px; }
.merge-action {
  width: 100%; padding: 8px 8px;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: 5px;
  font-size: 12px; font-family: inherit;
}
.merge-action:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--focus-ring); }

/* 何も選ばずに「大元に反映する」を押したとき、操作すべき場所を目で示す。
   色は --red を使うのでライト/ダーク両モードとも自動で合う */
.merge-action.merge-need {
  border-color: var(--red);
  animation: merge-need-blink 1.1s ease-out 1;
}
@keyframes merge-need-blink {
  0%, 100% { box-shadow: 0 0 0 0 transparent; }
  20%, 60% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--red) 35%, transparent); }
}
/* アニメを切っている環境では枠色だけで伝える */
@media (prefers-reduced-motion: reduce) {
  .merge-action.merge-need { animation: none; }
}

.merge-del {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; margin-bottom: 4px;
  border: 1px solid var(--border); border-radius: 5px;
  font-size: 12px; cursor: pointer;
}
.merge-del:hover { background: var(--hover); }
.merge-empty { font-size: 12px; color: var(--text-muted); padding: 8px 4px; }
.merge-hint { font-size: 12px; color: var(--text-muted); margin-top: 4px; line-height: 1.6; }

.merge-foot {
  display: flex; justify-content: flex-end; gap: 8px;
  margin-top: 16px; padding-top: 12px;
  border-top: 1px solid var(--border);
}

/* ===== §2026-08-16 新指示② 一覧の右クリックメニュー ===== */
/* body直下に生成して position:fixed で座標指定する（一覧の overflow に切られないため）。
   色は全て変数なのでライト/ダーク両テーマに自動追従する。 */
.ctx-menu {
  position: fixed; z-index: 10001;
  min-width: 200px; max-width: 300px;
  padding: 4px;
  background: var(--surface);
  border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
  font-size: 12px;
  user-select: none;
}
/* 対象のファイル名。どのFAXを操作しているかを取り違えないための見出し */
.ctx-menu .ctx-head {
  padding: 8px 12px 8px;
  font-weight: 700; color: var(--text-muted); font-size: 12px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  border-bottom: 1px solid var(--border);
  margin-bottom: 4px;
}
.ctx-menu .ctx-item {
  display: block; width: 100%;
  padding: 8px 12px; text-align: left;
  background: none; border: none; border-radius: 5px;
  color: var(--text); font-size: 12px; font-family: inherit;
  cursor: pointer;
}
.ctx-menu .ctx-item:hover:not(:disabled) { background: var(--hover); }
.ctx-menu .ctx-item:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--focus-ring); }
/* 確認済み以降は押せない。押せないことが見て分かるようにする（無言の空振りを作らない） */
.ctx-menu .ctx-item:disabled { color: var(--text-muted); opacity: .5; cursor: not-allowed; }
.ctx-menu .ctx-sep { height: 1px; background: var(--border); margin: 4px 0; }
/* なぜ押せないかの理由。理由を書かないと「壊れている」と誤解される */
.ctx-menu .ctx-note {
  padding: 8px 12px 4px; margin-top: 4px;
  font-size: 12px; line-height: 1.5; color: var(--text-muted);
  border-top: 1px solid var(--border);
}

/* ===== §3 詳細検索（2026-07-04指示③）===== */
/* AC最下部の「詳細検索…」常設ボタン行 */
.ac-more {
  padding: 8px 12px; font-size: 12px; font-weight: 600;
  color: var(--primary); background: var(--surface-2);
  border-top: 1px solid var(--border);
  cursor: pointer; text-align: center;
}
.ac-more:hover { background: var(--hover); }
/* 詳細検索モーダル（settings-modal流儀・ac-list(9999)より上のz-index 10000） */
#msm-overlay {
  position: fixed; inset: 0;
  background: var(--overlay);
  display: none; align-items: center; justify-content: center;
  z-index: 10000;
}
#msm-overlay.open { display: flex; }
.msm-box {
  background: var(--surface); border-radius: 12px;
  width: 640px; max-width: 92vw; max-height: 80vh;
  display: flex; flex-direction: column; overflow: hidden;
  box-shadow: 0 8px 32px rgba(0, 0, 0, .25);
}
.msm-hdr {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.msm-hdr h3 { font-size: 16px; font-weight: 700; }
.msm-close {
  border: none; background: none; font-size: 16px; color: var(--text-muted);
  cursor: pointer; padding: 4px 8px; border-radius: 5px;
}
.msm-close:hover { background: var(--surface-3); color: var(--text); }
.msm-controls { display: flex; gap: 8px; padding: 12px 16px 4px; flex-shrink: 0; }
.msm-controls input {
  flex: 1; padding: 8px 12px; font-size: 12px;
  border: 1px solid var(--border); border-radius: 6px;
}
.msm-controls input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px var(--focus-ring); }
.msm-controls select {
  padding: 8px 8px; font-size: 12px;
  border: 1px solid var(--border); border-radius: 6px; background: var(--surface);
}
.msm-count { padding: 0 16px 8px; font-size: 12px; color: var(--text-muted); flex-shrink: 0; }
.msm-list { overflow-y: auto; flex: 1; padding: 0 8px 8px; }
.msm-row {
  display: flex; gap: 8px; align-items: baseline;
  padding: 8px 8px; border-radius: 6px; cursor: pointer; font-size: 12px;
}
.msm-row:hover { background: var(--hover); }
.msm-code { font-family: monospace; color: var(--primary); flex-shrink: 0; min-width: 64px; }
.msm-name { flex: 1; }
.msm-idx { color: var(--text-faint); font-size: 12px; flex-shrink: 0; }
.msm-empty { padding: 24px; text-align: center; color: var(--text-muted); font-size: 12px; }

/* ===== テーマ切替（シンプルなアイコンボタン） ===== */
.theme-btn {
  background: none;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-muted);
  width: 28px;
  height: 28px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: color .15s, background .15s;
}
.theme-btn:hover { color: var(--text); background: var(--surface-3); }
.theme-btn .icon-sun { display: none; }
.theme-btn .icon-moon { display: block; }
:root[data-theme='dark'] .theme-btn .icon-sun { display: block; }
:root[data-theme='dark'] .theme-btn .icon-moon { display: none; }

/* ===== ダークモード個別調整 ===== */
/* 早出しNG倉庫の蛍光黄はダークでは暗色ベースに反転（!important同士で上書き） */
:root[data-theme='dark'] .editable-input.wh-early-ng {
  background: #713f12 !important;
  border-color: #a16207 !important;
  color: #fef9c3;
}
/* 訂正FAX紐づけパネル・全件再読込ボタンのライト専用色をダークで置き換え */
:root[data-theme='dark'] .link-panel {
  background: rgba(249, 115, 22, 0.10);
  border-color: rgba(249, 115, 22, 0.35);
}
:root[data-theme='dark'] .btn-reset-all { color: #fbbf24; border-color: #b45309; }

/* app.js注入CSS（ライト前提の固定色）のダーク上書き — app.js本体は無変更。
   特異性 (0,2,0)+属性 で注入側 (0,1,0) に勝つため読み込み順に依存しない */
:root[data-theme='dark'] #resize-handle { background: var(--surface-3); }
:root[data-theme='dark'] #resize-handle:hover,
:root[data-theme='dark'] #resize-handle.dragging { background: var(--primary); }
/* §2026-08-22 ログイン画面のダーク専用上書き2行を削除。
   #login-overlay スコープでライトのトークンを再宣言する方式に一本化したため、
   ここで var(--surface)/var(--text-muted) を再指定しても同じ値になり意味を持たない。 */
:root[data-theme='dark'] .color-swatch.selected,
:root[data-theme='dark'] .color-swatch:hover { border-color: var(--text); }
:root[data-theme='dark'] .settings-box { background: var(--surface); }
:root[data-theme='dark'] .settings-hdr { border-bottom-color: var(--border); }
:root[data-theme='dark'] .settings-tabs { background: var(--surface); border-bottom-color: var(--border); }
:root[data-theme='dark'] .stab { color: var(--text-muted); }
:root[data-theme='dark'] .stab.active { color: #fff; background: var(--primary); }
:root[data-theme='dark'] .gdrive-row { border-bottom-color: var(--surface-3); }
:root[data-theme='dark'] .sync-banner.success { background: var(--badge-green-bg); color: var(--badge-green-tx); }
:root[data-theme='dark'] .sync-banner.error { background: var(--badge-red-bg); color: var(--red); }
:root[data-theme='dark'] .btn-icon { color: var(--text-muted); }
:root[data-theme='dark'] .btn-icon:hover { background: var(--surface-3); }
:root[data-theme='dark'] .code-badge { background: rgba(96,165,250,.14); color: #93c5fd; border-color: rgba(96,165,250,.35); }
:root[data-theme='dark'] .code-badge em { color: var(--text-faint); }
:root[data-theme='dark'] .code-mini-input { background: var(--surface-3); color: var(--text); border-color: var(--border); }
:root[data-theme='dark'] .code-mini-input:focus { outline-color: var(--primary); border-color: var(--primary); background: var(--surface); }
:root[data-theme='dark'] .code-mini-input.req-empty { border-color: var(--cell-empty-border); background: var(--cell-empty-required); }
:root[data-theme='dark'] .btn-row-del { background: var(--badge-red-bg); border-color: rgba(239,68,68,.4); }
:root[data-theme='dark'] .btn-row-del:hover { background: rgba(239,68,68,.3); }
:root[data-theme='dark'] .items-footer { border-top-color: var(--border); }
:root[data-theme='dark'] .btn-row-add { border-color: rgba(96,165,250,.5); color: #93c5fd; }
:root[data-theme='dark'] .btn-row-add:hover { background: rgba(96,165,250,.12); }
:root[data-theme='dark'] .sort-select { border-color: var(--border); background: var(--surface); color: var(--text); }
/* unclear警告カードのインラインstyle（app.js L728-733）は属性セレクタ＋!importantで反転 */
:root[data-theme='dark'] .card-header[style*="fff7ed"] { background: rgba(249,115,22,.12) !important; color: #fdba74 !important; }
:root[data-theme='dark'] div[style*="92400e"] { color: #fdba74 !important; }

/* ===== §2026-08-15 指示S5 確認済み以降は編集不可 =====
   「確認済み以降のステータスのものは編集できないようにして欲しい」
   ただの disabled だけだと「なぜ入力できないのか」が伝わらないので理由を添える。
   §2026-08-15 追加指示: 上部にポップアップ（背景付きのバー）を出すのはやめ、
   緑字のテキストだけを出す。バーだと明細が押し下がって本来見たいものが隠れるため。
   色は両テーマ定義済みの変数だけで組む。

   §2026-08-15 再指示「ここボタンと見出しで分けてよ。ボタンの文字が窮屈になって
   改行されちゃうじゃん」。見出しの右横（＝ボタンと同じ横並びの行）に置くと、
   文言が伸びたぶんだけ右のボタン群が圧縮されて「確認済 / み」と改行していた。
   見出し＋ボタンの行の“下”に独立した1行として置き、ボタンの幅に一切影響させない。
   そのため span ではなく block 要素として扱う（margin-left は不要）。 */
.edit-lock-note {
  display: block;
  width: 100%;
  margin: 4px 0 0;
  color: var(--badge-green-tx);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.5;
}
/* ===== §2026-08-15 指示B/D 自動補完した値は見て分かるようにする =====
   「補完したことがUIとログで分かるようにする（黙って埋めない）」
   未入力のまま確認済みを押した時にだけ機械が入れた値（入数10・商品コード00000004）。
   人が手で直した値（manual）とは別カラム（auto_filled_fields）で管理しているので、
   ここで色を分けても「人が確認した値」と混ざらない。
   トーストは消えるが、この下線は開き直しても残る＝後から見ても追える。 */
.editable-input[data-origin="autofill"],
.code-cell[data-origin="autofill"] {
  border-bottom: 2px dashed var(--badge-orange-tx);
  background: var(--badge-orange-bg);
}
/* 明細の商品コード欄には `.cell-pair:has(.code-cell:not(:placeholder-shown))` で
   緑(--cell-ok)を塗るルールがある（「名称とコードが揃った」ことを示す表示）。
   機械が補完した値にもこれが当たるため、補完値が緑のまま＝人が確認した値と見分けがつかなかった。

   実DOM（app.js L1167-1172）:
   `.item-row > .item-stages > .igrid > .cell-pair > .editable-wrap > input.code-cell`

   緑のルール `.item-row .cell-pair:has(.code-cell:not(:placeholder-shown)) .code-cell` の
   詳細度は 0-5-0。`:has()` と `:not()` は**中身も詳細度に算入される**ので、
   見た目のクラス数（3個）ではなく
   `.item-row` + `.cell-pair` + has内`.code-cell` + not内`:placeholder-shown` + `.code-cell` の5個。

   ここを 0-4-0（`.item-row`+`.cell-pair`+`.code-cell`+`[data-origin]`）で書いていたため
   1つ足りず緑に負け続けていた（下線＝border-bottom は緑ルールが指定していないので
   autofill 側が通り、「下線はオレンジなのに背景だけ緑」というちぐはぐな見た目になっていた）。
   CDP の getMatchedStylesForNode で採用順を実測して確定（推測ではない）。

   `[data-field]` を足して 0-5-0 → 同点かつ後方＝勝つ。
   !important は必須未入力(.req-empty)など他の状態表示を巻き込むので使わない。 */
.item-row .cell-pair .code-cell[data-origin="autofill"][data-field],
.item-row .cell-pair .editable-input[data-origin="autofill"][data-field] {
  background: var(--badge-orange-bg);
  border-bottom: 2px dashed var(--badge-orange-tx);
}

/* §2026-08-16 指示 マスタ未確定コード(00000004/99999999)は「値が入っている」だけで
   上の緑ルールに拾われる。[マスタ不一致]の警告が出ているのに緑では、どの行を直せば
   いいか画面から分からない、という指摘への対応。JS(mkCellPair)が付けた
   .code-unresolved が付いている行は問答無用でオレンジ(ng)にする。

   詳細度: 緑ルールは 0-5-0（上のコメント参照）。
   こちらは `.item-row`+`.cell-pair`+`.code-unresolved`+`.code-cell`+`[data-field]` で
   0-5-0 の同点。同点なら後方が勝つのでこの位置（緑ルールより後ろ）に置くこと。
   !important を使わないのは .req-empty など他の状態表示を巻き込まないため。
   色は変数なのでライト/ダーク両テーマに自動追従する。 */
.item-row .cell-pair.code-unresolved .code-cell[data-field],
.item-row .cell-pair.code-unresolved .editable-input[data-field] {
  background: var(--cell-ng);
}
.item-row .cell-pair.code-unresolved .code-cell[data-field] {
  border-color: var(--cell-ng-border);
}

/* §2026-08-16 指示 確認済みのFAXでは「マスタ不一致」の警告色を出さない。
   人が見て確認済みにした＝コードをどうするかの判断は済んでいる。編集もできない状態で
   オレンジ（要対応）を出し続けると「まだ直す所がある」と誤読させる。
   JS側のマーカー(.code-unresolved)は残したまま、表示だけ通常の入力欄に戻す
   （確認済みを外せば .edit-locked が消えてオレンジが自動で復活する）。
   詳細度: 上のオレンジルール 0-5-0 に .edit-locked を足した 0-6-0 なので確実に勝つ。
   背景色は変数なのでライト/ダーク両テーマに自動追従する。 */
.edit-locked .item-row .cell-pair.code-unresolved .code-cell[data-field],
.edit-locked .item-row .cell-pair.code-unresolved .editable-input[data-field],
.edit-locked .ifield.pair.code-unresolved .editable-input,
.edit-locked .ifield.pair.code-unresolved .code-mini-input {
  background: var(--surface);
}
.edit-locked .item-row .cell-pair.code-unresolved .code-cell[data-field],
.edit-locked .ifield.pair.code-unresolved .code-mini-input {
  border-color: var(--border);
}

/* ロック中の入力欄は「押しても反応しない」ことが見て分かる程度に落とす。
   読めなくなるほど薄くはしない（確認のために中身を見る画面なので） */
.edit-locked input:disabled,
.edit-locked select:disabled,
.edit-locked textarea:disabled {
  opacity: .72;
  cursor: not-allowed;
}
.edit-locked button:disabled { opacity: .45; cursor: not-allowed; }
/* 受領フロー（確認済みを外す唯一の口）はロック中でもはっきり見せる */
.edit-locked .stamp-group input,
.edit-locked .stamp-group button,
.edit-locked .stamp-group label { opacity: 1; cursor: pointer; }

/* ===== §2026-08-15 伝票プレビュー（納品書・出庫伝票の画面内表示）=====
   指摘「納品書とか出庫伝票押しても表示されない」の対策。
   別タブでPDFを開く方式はブラウザの「PDFは常にダウンロード」設定に負けるため、
   FAX原本プレビューと同じくサーバー側でページ画像に変換して画面内に出す。
   z-index は詳細検索モーダル(10000)より上に置く。 */
#slip-preview-overlay {
  position: fixed; inset: 0;
  background: var(--overlay);
  display: none; align-items: center; justify-content: center;
  z-index: 10001;
}
#slip-preview-overlay.open { display: flex; }
.slip-preview-box {
  background: var(--surface); border-radius: 12px;
  width: 900px; max-width: 94vw; max-height: 92vh;
  display: flex; flex-direction: column; overflow: hidden;
  box-shadow: 0 8px 32px rgba(0, 0, 0, .25);
}
.slip-preview-hdr {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.slip-preview-hdr h3 { font-size: 16px; font-weight: 700; }
.slip-preview-actions { display: flex; align-items: center; gap: 8px; }
/* 「PDFを保存」は <a> だがボタンと同じ見た目に揃える */
a.btn-outline.btn-sm { text-decoration: none; display: inline-flex; align-items: center; }
.slip-preview-body {
  overflow-y: auto; flex: 1;
  padding: 16px; background: var(--surface-2);
  display: flex; flex-direction: column; align-items: center; gap: 16px;
}
.slip-preview-page {
  width: 100%; max-width: 820px; height: auto; display: block;
  background: #fff; border: 1px solid var(--border); border-radius: 4px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .12);
}
.slip-preview-loading {
  padding: 40px 0; font-size: 12px; color: var(--text-muted);
}

/* 印刷時はプレビュー中の伝票だけを紙に出す（画面のUIは全部隠す） */

/* §2026-08-17 指示「印刷時は余白無しで印刷して、3つとも自然な同余白になるようにして欲しい。
   印刷ボタンでその設定が適用されてると尚良し」。

   伝票PDFは A4 の紙面いっぱいを使い、余白（上下左右24pt）も切り取り線も
   PDF側で持っている。ここでブラウザ既定の印刷余白（Chrome だと約12.7mm）が
   乗ると、その分ページが縮小されて
     ・3等分の切り取り線が A4 の 1/3 の位置からずれる
     ・伝票全体が小さくなり、複写紙・既存の運用と寸法が合わない
   という事故になる。@page で余白を 0 にして PDF の寸法をそのまま紙に出す。
   size: A4 も併記して、既定用紙が Letter の環境でも A4 として出す。 */
@page {
  size: A4;
  margin: 0;
}

@media print {
  body > *:not(#slip-preview-overlay) { display: none !important; }
  /* 余白0なので、画面用に付けている余白・背景を全部落とす */
  html, body { margin: 0 !important; padding: 0 !important; background: #fff !important; }
  #slip-preview-overlay.open {
    position: static; display: block !important; background: none;
  }
  .slip-preview-box {
    width: auto; max-width: none; max-height: none;
    box-shadow: none; border-radius: 0;
  }
  .slip-preview-hdr { display: none !important; }
  .slip-preview-body {
    overflow: visible; padding: 0; background: none; display: block;
  }
  .slip-preview-page {
    max-width: none; border: none; box-shadow: none;
    page-break-after: always; break-after: page;
    /* 余白0の紙面いっぱいに敷く。PDFはA4比で描かれているので歪まない */
    display: block; width: 100%; height: auto; margin: 0;
  }
  .slip-preview-page:last-child { page-break-after: auto; break-after: auto; }
}


/* ===================================================================
   §2026-08-16 指示 トップメニュー（メインページ＝モジュール一覧）
   色は全て既存のテーマ変数を使う。変数側がライト/ダークで差し替わる
   作りなので、ここで両モード分を書き分ける必要はない（実測で確認）。
   下のダーク上書きは、変数に無い「タイルの淡い塗り」だけを直している。
   =================================================================== */
/* §2026-08-17 スクロール不能の修正（3箇所すべて死んでいた件）。
   body は height:100vh / overflow:hidden の固定レイアウトなので、
   body直下の要素が自分で「flex:1 + min-height:0 + overflow」を持たないと
   はみ出た分がどこにも逃げられず、中の overflow-y:auto も発動しない。
   #module-fax は 2026-08-16 にラッパーとして新設したがCSSを書き忘れており、
   #main-layout → #left-panel → #fax-list の高さ連鎖が切れて
   左リスト・右詳細・トップメニューの3箇所すべてがスクロール不能になっていた。
   min-height:0 は必須（既定の auto だとflex子が縮まず overflow が効かない）。 */
#module-fax {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

#top-menu {
  /* §2026-08-16 1100px だと1440px画面で右が大きく空いた（実測）ので広げる。
     ただし無制限にはしない。横に伸びきると1枚あたりが細長くなって説明文が読みにくい。 */
  max-width: 1320px;
  margin: 0 auto;
  padding: 40px 24px 64px;
  /* §2026-08-17 body直下の flex子として自分でスクロールを持つ。
     max-width と margin:0 auto を活かすため width:100% を明示する
     （flex子は既定で auto 幅になり中央寄せが効かなくなるため）。 */
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  width: 100%;
}
.tm-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 24px; flex-wrap: wrap;
  padding-bottom: 16px; margin-bottom: 24px;
  border-bottom: 1px solid var(--border);
}
.tm-title {
  margin: 0; font-size: 24px; font-weight: 700; letter-spacing: .02em;
  color: var(--text);
}
.tm-sub {
  margin: 4px 0 0; font-size: 12px; color: var(--text-muted);
}
.tm-progress { text-align: right; white-space: nowrap; }
.tm-progress-num {
  display: block; font-size: 24px; font-weight: 700; color: var(--primary);
  font-variant-numeric: tabular-nums;
}
.tm-progress-label { font-size: 12px; color: var(--text-faint); }

/* §2026-08-16 列数は auto-fill に任せず明示する。
   auto-fill + minmax(240px,1fr) にしたところ、1440px幅でも2列にしかならなかった
   （実測。タイル内の説明文が最小幅を押し広げて4列分の枠に収まらないため）。
   結果、右半分が丸ごと空いて7枚が縦に伸びる形になっていた。
   幅ごとに列数を決め打ちすれば、この押し広げの影響を受けない。 */
.tm-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}
@media (min-width: 900px)  { .tm-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1240px) { .tm-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.tm-tile {
  position: relative;
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
  padding: 20px 16px 16px;
  text-align: left; font: inherit;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  min-height: 152px;
}
.tm-icon { font-size: 24px; line-height: 1; }
.tm-name { font-size: 16px; font-weight: 700; color: var(--text); }
.tm-desc { font-size: 12px; line-height: 1.55; color: var(--text-muted); }
.tm-stat {
  margin-top: auto; font-size: 12px; color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}
.tm-badge {
  position: absolute; top: 12px; right: 12px;
  padding: 0 8px; border-radius: 999px;
  font-size: 12px; font-weight: 700; letter-spacing: .04em;
}

/* 稼働中＝押せる。押せることが見た目で分かるよう、ここだけ手前に出す */
.tm-tile.ready {
  cursor: pointer;
  border-color: var(--green);
  box-shadow: var(--shadow);
  transition: transform .12s ease, box-shadow .12s ease;
}
.tm-tile.ready:hover { transform: translateY(-2px); box-shadow: 0 6px 18px rgba(0,0,0,.12); }
.tm-tile.ready:active { transform: translateY(0); }
.tm-tile.ready:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.tm-tile.ready .tm-badge { background: var(--badge-green-bg); color: var(--badge-green-tx); }

/* 一部実装＝押せない（飛ばす先がまだ無い）。
   §2026-08-16 ただし未着手と同じ薄さにしてはいけない。実測で並べたところ、
   外部データ連携・マスタ管理（どちらもCSV出力は既に動いている）が、
   まだ1行も書いていない売上管理・請求管理と見分けが付かなかった。
   平林側から見ると「動いている部分まで未着手に見える」＝進捗の過小申告になる。
   そこで未着手より濃く出し、左端に色帯を入れて「途中まで出来ている」を示す。 */
.tm-tile.partial { opacity: .88; }
.tm-tile.partial::before {
  content: ''; position: absolute; left: 0; top: 12px; bottom: 12px; width: 4px;
  border-radius: 0 3px 3px 0;
  background: var(--badge-yellow-tx);
}
.tm-tile.partial .tm-badge { background: var(--badge-yellow-bg); color: var(--badge-yellow-tx); }

/* 未着手＝押せない。押せるのに空画面、を避けるため見た目から落とす */
.tm-tile.todo { opacity: .52; }
.tm-tile.todo .tm-badge { background: var(--surface-3); color: var(--text-faint); }
.tm-tile.partial, .tm-tile.todo { cursor: default; }

/* モジュール内の戻り導線 */
/* §2026-08-22 .module-bar(独立段)は廃止。中身は .tab-bar 左端へ移設した。
   タイトル系クラスは移設先でそのまま流用する。 */
/* §2026-08-22 整列の根治は .tab-bar 側の統一ルール（height:28px/12px/line-height:1）が正。
   ここではタイトル固有の見た目だけを持つ。 */
.module-bar-title {
  font-weight: 700; color: var(--text); white-space: nowrap;
  gap: 8px; /* 「受注管理」と「FAX OCR」の間（指摘②） */
}
/* サブもタイトルと同じ12pxに統一（サイズがずれると文字下端が波打つ）。
   ヒエラルキーはサイズでなくウェイト(700→400)と色(faint)で付ける（指摘④） */
.module-bar-sub { font-size: 12px; font-weight: 400; color: var(--text-faint); margin-left: 0; }
/* タブバー左端の戻りボタンと、タブ群を分ける縦の区切り線 */
.tab-bar .module-back { flex-shrink: 0; }
.tabbar-divider {
  /* 近接の原則: タイトル群とタブ群は別グループ。グループ間距離(8+8+1+8+8=33px)を
     タブ同士の距離(8px)より明確に広くする。margin両側同値なので左右対称は維持 */
  width: 1px; height: 16px; align-self: center; margin: 0 8px;
  background: var(--border); flex-shrink: 0;
}

/* 視覚ウェイト補正: 塗りボタン(btn-primary)は同寸のアウトラインより大きく・重く見える。
   ヘッダー/タブバーのアウトライン側に薄背景を与えてウェイト差を縮める
   （非アクティブピルの薄背景と同じ手法＝反復の原則） */
.header-meta .btn-outline,
.tab-bar .btn-outline { background: var(--surface-2); }
.header-meta .btn-outline:hover,
.tab-bar .btn-outline:hover { background: var(--surface-3); }

/* ダークだけの微調整。淡い塗りは変数に無いのでここで当てる */
:root[data-theme='dark'] .tm-tile { background: var(--surface-2); }
:root[data-theme='dark'] .tm-tile.ready:hover { box-shadow: 0 6px 18px rgba(0,0,0,.45); }

@media (max-width: 640px) {
  #top-menu { padding: 24px 16px 40px; }
  .tm-grid { grid-template-columns: 1fr; }
}

/* ===== OCR未設定バナー（テナントにAPIキー未登録のとき表示・クリックで設定へ）2026-08-21 ===== */
#ocr-setup-banner {
  display: flex; align-items: center; gap: 12px;
  margin: 12px 20px 0; padding: 12px 16px;
  background: var(--badge-orange-bg);
  border: 1px solid var(--badge-orange-tx);
  border-radius: 10px;
  color: var(--badge-orange-tx);
  cursor: pointer;
  transition: filter .15s ease;
}
#ocr-setup-banner:hover { filter: brightness(0.97); }
#ocr-setup-banner.hidden { display: none; }
.ocr-setup-banner-icon { font-size: 16px; line-height: 1; flex-shrink: 0; }
.ocr-setup-banner-text { font-size: 12px; color: var(--text); line-height: 1.5; }
.ocr-setup-banner-text strong { color: var(--badge-orange-tx); }
.ocr-setup-banner-cta {
  margin-left: auto; flex-shrink: 0;
  font-size: 12px; font-weight: 700; color: var(--badge-orange-tx); white-space: nowrap;
}
@media (max-width: 640px) {
  #ocr-setup-banner { margin: 12px 16px 0; flex-wrap: wrap; }
  .ocr-setup-banner-cta { margin-left: 0; }
}

/* OCR設定タブ冒頭の平易な説明文 */
.sm-ocr-lead {
  font-size: 12px; color: var(--text-muted); line-height: 1.7;
  margin: 0 0 16px; padding: 12px 16px;
  background: var(--surface-2); border-radius: 8px;
}

/* 個人設定タブ冒頭の「本人だけの設定」注記 */
.settings-scope-note {
  font-size: 12px; color: var(--text-muted); line-height: 1.6;
  margin: 0 0 16px; padding: 12px 12px;
  background: var(--surface-2); border-left: 3px solid var(--primary); border-radius: 6px;
}

/* 2026-08-21 追加タブ（返信/通知/データ）で使う共通レイアウト */
.form-row { display: flex; gap: 12px; }
.form-row > .form-group { flex: 1; min-width: 0; }
@media (max-width: 640px) { .form-row { flex-wrap: wrap; } }

.checkbox-line {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--text); line-height: 1.6;
  margin: 4px 0; cursor: pointer;
}
.checkbox-line input[type="checkbox"] { width: auto; margin: 0; flex: 0 0 auto; }

.settings-section-divider { height: 1px; background: var(--border); margin: 16px 0; }
