/* ============================================================================
 * FVJAPAN CRM — 部品（docs/DESIGN.md §4-B の実体の素の CSS 版）
 *
 * 命名規則: `c-<部品>` ／ 子要素 `c-<部品>__<要素>` ／ 見た目の差 `c-<部品>--<バリアント>`。
 *   例: <a class="c-button c-button--secondary c-button--sm">
 * **状態は修飾クラスで持たず、意味を持つ属性で持つ**（aria-disabled / aria-current /
 * aria-selected / aria-sort / aria-invalid / :checked / data-status 等）。
 * 見た目と支援技術への伝わり方が同じ1つの源から決まり、片方だけ付け忘れることが起きない。
 *
 * 出典は web/components/{ui,crm,customers}/*.tsx の Tailwind クラス（各節の先頭に元のファイル）。
 * **値は tokens.css の変数でのみ参照する。** 生の色・任意の px を書かない（DESIGN.md §5-D）。
 * 余白は calc(var(--spacing) * N)。N は Tailwind の `p-N` と同じ数なので、元のクラスと突き合わせられる。
 *
 * **スノーフレーク防止**（DESIGN.md §3 / §4-B）: 新しい見た目が要るときは既存の部品に
 * `--バリアント` を足し、§4-B の表を同じ変更で更新する。`c-button-primary` のような別部品を作らない。
 * ========================================================================== */


/* ============================================================================
 * Button（web/components/ui/button.tsx）
 *
 * <button> にも <a> にも同じクラスを当てる（リンクをボタンに見せる形。API契約 v1.1 裁定8）。
 * ========================================================================== */
.c-button {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  gap: calc(var(--spacing) * 1.5);
  height: var(--control-h-compact); /* h-8 = 32px（§4-A: 標準は 32px） */
  padding-inline: calc(var(--spacing) * 2.5);
  border: var(--border-w) solid transparent;
  border-radius: var(--radius-md);
  background-clip: padding-box;
  font-size: var(--text-sm);
  /* Tailwind 版は `font-medium`（500）。DESIGN.md §5-C は 400/600 の2種と定めており食い違うが、
     実装を優先して移した（報告済みのずれ） */
  font-weight: 500;
  white-space: nowrap;
  user-select: none;
  /* cursor はここで指定しない。押せるボタンの指は base.css の「押せるものは指にする」が一括で持つ
     （<a> に当てたときはリンクの既定の指）。押せないときの not-allowed は下の aria-disabled が持つ */
  text-decoration: none;
  /* outline-color を含む。base.css の `* { outline-color }` がこの遷移の始点を揃えている */
  transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke;
  transition-timing-function: var(--ease-standard);
  transition-duration: var(--duration-colors);
}
.c-button:focus-visible {
  border-color: var(--ring);
  /* shadcn 由来の `focus-visible:ring-2 ring-ring/50`。輪郭（outline）は base.css が描き、これは内側の淡い帯 */
  box-shadow: 0 0 0 var(--ring-w) color-mix(in oklab, var(--ring) 50%, transparent);
}
.c-button:active:not([aria-haspopup]):not([aria-disabled="true"]) {
  transform: translateY(var(--press-offset));
}
.c-button:disabled {
  pointer-events: none;
  opacity: 0.5; /* ネイティブ disabled の既定。**押せない操作は RestrictedAction（aria-disabled）で出す**ので業務画面では使わない */
}
.c-button svg {
  pointer-events: none;
  flex-shrink: 0;
  width: calc(var(--spacing) * 4);
  height: calc(var(--spacing) * 4);
}

/* ---- variant ---- */
/* 主 CTA（1画面1つ）。teal-700 背景＋白文字 */
.c-button--default {
  background-color: var(--primary);
  color: var(--primary-foreground);
}
.c-button--default:hover {
  background-color: var(--color-primary-hover);
}
/* 副次操作（Excel出力・戻る・編集） */
.c-button--secondary {
  background-color: var(--secondary);
  color: var(--secondary-foreground);
}
.c-button--secondary:hover {
  background-color: color-mix(in oklch, var(--secondary), var(--foreground) 5%);
}
.c-button--secondary[aria-expanded="true"] {
  background-color: var(--secondary);
  color: var(--secondary-foreground);
}
.c-button--outline {
  border-color: var(--border);
  background-color: var(--background);
}
.c-button--outline:hover,
.c-button--outline[aria-expanded="true"] {
  background-color: var(--muted);
  color: var(--foreground);
}
/* 弱い操作 */
.c-button--ghost:hover,
.c-button--ghost[aria-expanded="true"] {
  background-color: var(--muted);
  color: var(--foreground);
}
/* 破壊的操作（削除・別人として確定） */
.c-button--destructive {
  background-color: color-mix(in oklab, var(--destructive) 10%, transparent);
  color: var(--destructive);
}
.c-button--destructive:hover {
  background-color: color-mix(in oklab, var(--destructive) 20%, transparent);
}
.c-button--destructive:focus-visible {
  border-color: color-mix(in oklab, var(--destructive) 40%, transparent);
  box-shadow: 0 0 0 var(--ring-w) color-mix(in oklab, var(--destructive) 20%, transparent);
}
/* 状態を切り替える強い操作（優先対応フラグ）。破壊的ではないので枠線で表す */
.c-button--warning {
  border-color: var(--color-warning-border);
  background-color: var(--color-warning-bg);
  color: var(--color-warning-fg);
}
.c-button--warning:hover {
  border-color: var(--color-warning-fg);
}
/* AI 機能の起動（DESIGN.md §11） */
.c-button--ai {
  background-color: var(--color-ai-fg);
  color: var(--color-white);
}
.c-button--ai:hover {
  background-color: color-mix(in oklab, var(--color-ai-fg) 90%, transparent);
}
/* 「追加」の空きスロット（＋契約を追加 / ＋現在の条件を保存） */
.c-button--dashed {
  border-style: dashed;
  border-color: var(--color-gray-300);
  background-color: var(--color-surface);
  color: var(--color-text-muted);
}
.c-button--dashed:hover {
  border-color: var(--primary);
  color: var(--primary);
}

/* ---- size ---- */
.c-button--xs {
  gap: calc(var(--spacing) * 1);
  height: calc(var(--spacing) * 6);   /* 24px */
  padding-inline: calc(var(--spacing) * 2);
  font-size: var(--text-xs);
}
.c-button--xs svg {
  width: calc(var(--spacing) * 3);
  height: calc(var(--spacing) * 3);
}
.c-button--sm {
  gap: calc(var(--spacing) * 1);
  height: calc(var(--spacing) * 7);   /* 28px */
  padding-inline: calc(var(--spacing) * 2.5);
  font-size: var(--text-sm);
}
.c-button--sm svg {
  width: calc(var(--spacing) * 3.5);
  height: calc(var(--spacing) * 3.5);
}
/* 主 CTA のみ h-9（§4-A） */
.c-button--lg {
  height: var(--control-h-standard);  /* 36px */
}
.c-button--icon {
  width: var(--control-h-compact);
  height: var(--control-h-compact);
  padding-inline: 0;
}
/* 置かれた枠（グリッドのセル・包み）いっぱいに伸ばす。**寸法の段ではない**ので size と併用する
   （顧客詳細②の「＋ 契約を追加」が契約カードと同じ高さの枠になる形。移植元 `h-auto w-full` の枠の中の `h-full`） */
.c-button--stretch {
  width: 100%;
  height: 100%;
}

/* ---- aria-disabled（RestrictedAction の見た目）----
 * **variant の後ろに置く**（同じ詳細度なら後勝ち。hover は :hover を足して詳細度でも勝つ）。
 *   - **opacity で薄めない。** gray-900 の 50% は白背景で AA(4.5:1) を割る（§10）。
 *     面を gray-100・文字を text-muted にする（button.tsx の実測 5.37:1）
 *   - **pointer-events: none も付けない。** 付けるとホバーで理由が出せなくなる */
.c-button[aria-disabled="true"],
.c-button[aria-disabled="true"]:hover {
  cursor: not-allowed;
  border-color: var(--border);
  background-color: var(--color-gray-100);
  color: var(--color-text-muted);
  box-shadow: none;
}
.c-button--dashed[aria-disabled="true"],
.c-button--dashed[aria-disabled="true"]:hover {
  border-color: var(--border);
}


/* ============================================================================
 * RestrictedAction（web/components/crm/restricted-action.tsx）
 *
 * 押せない操作の**唯一の見せ方**（§9 ⑥・A-1）。構造は webui/components/restricted_action.html。
 *   <span class="c-restricted" data-restricted-action>
 *     <button class="c-button …" type="button" aria-disabled="true" aria-describedby="ID">…</button>
 *     <span id="ID" class="c-restricted__reason" aria-hidden="true">理由</span>   ← 常に DOM にある
 *   </span>
 *
 * 理由は**閉じているあいだも読み上げ専用として DOM に在る**（aria-describedby の参照先を絶やさない）。
 * 吹き出しとして見せるのは **ホバーまたはフォーカスのあいだ**（:hover / :focus-within）。
 * **JS が読み込まれなくても、ポインタでもキーボードでも理由が見える。**
 * JS（restricted-action.js）は WCAG 2.2 1.4.13 の Dismissible を足す:
 * Esc で data-dismissed="true" を付けて隠し、離れる（blur / mouseleave）まで開き直さない。
 * さらに、既定の位置（ボタンの下）が画面・切り取る箱の外へはみ出すときだけ、`data-placed` を付けて画面に固定し置き直す
 * （下の `[data-placed]` の規則。U-1 第3弾）。JS が無いときは既定の位置のまま（横幅だけは max-width が画面に収める）。
 * ========================================================================== */
.c-restricted {
  position: relative;
  display: inline-flex;
}
/* 閉じている: sr-only と同じ宣言（base.css の .sr-only の写しではなく、状態で切り替えるためにここに持つ） */
.c-restricted__reason {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border-width: 0;
}
/* ↑ 1px / -1px は sr-only の定型（base.css の注記）。 */
.c-restricted:is(:hover, :focus-within):not([data-dismissed="true"]) .c-restricted__reason {
  top: 100%;
  left: 0;
  z-index: 40;
  width: max-content;
  /* 狭い画面では、画面の幅から左右 spacing × 4 を引いた幅まで（JS が無くても横幅は画面に収まる。U-1 第3弾） */
  max-width: min(var(--popover-w), calc(100vw - calc(var(--spacing) * 8)));
  height: auto;
  margin: calc(var(--spacing) * 1) 0 0;
  overflow: visible;
  clip-path: none;
  white-space: normal;
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  padding: calc(var(--spacing) * 1) calc(var(--spacing) * 2);
  font-size: var(--text-sm);
  color: var(--color-text);
  box-shadow: var(--shadow-3);
}
/* **開いているあいだは包みごと前に出す**（2026-09-30・CI の Linux で見つかった重なり）。
   包みに `z-index` を持たせる画面がある（顧客詳細の契約カードの `__over-link` ＝ z-index 1。カード全体のリンクの上に載せるため）。
   そこでは包みが重なりの文脈を作り、吹き出しの z-index（40）はその中でしか効かない ——
   **後ろのカードの同じ包み（z-index 1）が、前のカードの吹き出しの上に描かれた**（2枚目の「編集」が1枚目の吹き出しを覆った）。
   開いている包みだけを**隣の包み（1）より1段前（2）**に出す。閉じているときは画面側の z-index のまま。
   **40 まで上げない** —— 包みは `position: relative` なので、上げた段にボタンごと載り、スクロールすると
   貼り付いたトップバー（30）・保存の帯（10）の上にボタンが描かれた（正しさレビュー Med）。
   吹き出しが帯に重なるときは、`restricted-action.js` が帯を避けて置き直す（帯の下に潜らせない） */
.c-restricted:is(:hover, :focus-within):not([data-dismissed="true"]) {
  z-index: 2;
}
/* ボタンと吹き出しの隙間（上の margin-top）を、吹き出し自身の見えない帯で覆う（WCAG 2.2 1.4.13 Hoverable）。
   帯は吹き出しの子なので、ポインタが帯の上にある間も包み（.c-restricted）の :hover が続き、
   ボタンから吹き出しへゆっくり動かしても途中で閉じない（a11y 監査 Med: ボタン下端＋1px で閉じていた）。
   高さは margin-top と枠線の和（隙間ちょうど。ボタンに重ねない） */
.c-restricted:is(:hover, :focus-within):not([data-dismissed="true"]) .c-restricted__reason::before {
  content: "";
  position: absolute;
  right: 0;
  bottom: 100%;
  left: 0;
  height: calc(var(--spacing) * 1 + var(--border-w));
}
/* 画面の右端に並ぶ操作は右寄せにしないとビューポートの外へはみ出す（align="end"） */
.c-restricted--end:is(:hover, :focus-within):not([data-dismissed="true"]) .c-restricted__reason {
  left: auto;
  right: 0;
}
/* ---- `--next-step`: 理由を**常に見せる**（2026-09-30・UX 批評〈次の一手が見えない〉）
   既定の吹き出しは「**権限が無い**」＝ 読んでもその人には解けない理由のための形で、
   ホバー／フォーカスのあいだだけ出せばよい。**「次の一手」＝ 読めばその場で解ける理由**
   （例: 「表の見出しで統合先を選ぶと統合できます。」）を同じ隠し方にすると、
   **解ける人に解き方が届かない**。**持ち主は1つのまま**（同じ要素を見せるだけなので、
   `aria-describedby` の結び先も見える文も同じ1文である）。
   包みは行に参加するので `inline-flex` をやめて縦に積む */
.c-restricted--next-step {
  flex-direction: column;
  align-items: flex-start;
  gap: calc(var(--spacing) * 1);
}
.c-restricted--next-step .c-restricted__reason {
  position: static;
  width: auto;
  height: auto;
  margin: 0;
  overflow: visible;
  clip-path: none;
  white-space: normal;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
/* 常に見えているので、吹き出しの枠も帯も出さない（二重に描かない） */
.c-restricted--next-step:is(:hover, :focus-within) .c-restricted__reason {
  top: auto;
  left: auto;
  max-width: none;
  border: 0;
  background-color: transparent;
  padding: 0;
}
.c-restricted--next-step:is(:hover, :focus-within) .c-restricted__reason::before { content: none; }
/* **はみ出すときだけ画面に固定して置き直す**（U-1 第3弾の a11y レビュー Med・2026-09-30）。
   上の既定の位置（ボタンの下）が、画面の左右・下、または切り取る箱（区画の `overflow: hidden`・表の枠の横スクロール）の
   外へ出るときに限り、`restricted-action.js` が `data-placed` を付け、`top` / `left` を算出値で書く。
   収まっている吹き出しには何もしない（位置が1px も変わらない）。
   `below` ＝ ボタンの下のまま（左右だけ画面の内側へ寄せる）／ `above` ＝ 下が足りないのでボタンの上 */
.c-restricted:is(:hover, :focus-within):not([data-dismissed="true"]) .c-restricted__reason[data-placed] {
  position: fixed;
  right: auto;
  bottom: auto;
  margin: 0;
}
/* 上に出したときは、ボタンとの隙間を覆う見えない帯（::before）も吹き出しの下側へ移す（1.4.13 Hoverable） */
.c-restricted:is(:hover, :focus-within):not([data-dismissed="true"]) .c-restricted__reason[data-placed="above"]::before {
  top: 100%;
  bottom: auto;
}


/* ============================================================================
 * Badge（web/components/ui/badge.tsx）
 * ========================================================================== */
.c-badge {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  gap: calc(var(--spacing) * 1);
  width: fit-content;
  height: calc(var(--spacing) * 5); /* h-5 = 20px */
  overflow: hidden;
  border: var(--border-w) solid transparent;
  border-radius: var(--radius-sm); /* 元は shadcn の rounded-4xl（globals.css で 4px の別名） */
  padding: calc(var(--spacing) * 0.5) calc(var(--spacing) * 2);
  font-size: var(--text-xs);
  font-weight: 500;
  white-space: nowrap;
}
/* 流入ブランド。意味を持たない識別ラベルなので無彩色 */
.c-badge--brand {
  background-color: var(--color-gray-100);
  color: var(--color-gray-700);
  font-size: var(--text-2xs);
  font-weight: 600;
}
/* 法人マーク */
.c-badge--corp {
  background-color: var(--color-gray-900);
  color: var(--color-white);
  font-size: var(--text-2xs);
  font-weight: 700;
}
/* 警告（アラートの要約）。danger は「対応が要る」の意味 */
.c-badge--alert {
  border-color: var(--color-danger-border);
  background-color: var(--color-danger-bg);
  color: var(--color-danger-fg);
  font-size: var(--text-2xs);
  font-weight: 600;
}
/* 重複候補（強さ区分を併記。「強さ区分」の語は sr-only で必ず添える・§11-B） */
.c-badge--ai {
  border-color: var(--color-ai-border);
  background-color: var(--color-ai-bg);
  color: var(--color-ai-fg);
  font-size: var(--text-2xs);
  font-weight: 700;
}
/* オプション契約（✓付き） */
.c-badge--option {
  border-color: var(--border);
  background-color: var(--color-gray-50);
  color: var(--color-gray-700);
  font-size: var(--text-2xs);
  font-weight: 600;
}
/* 件数。面を持たず色は親から継承する。opacity で薄くしない（§10） */
.c-badge--count {
  background-color: transparent;
  padding-inline: calc(var(--spacing) * 1);
  font-size: var(--text-2xs);
  font-weight: 600;
}
/* 優先対応フラグ */
.c-badge--flag {
  background-color: transparent;
  padding-inline: calc(var(--spacing) * 1);
  color: var(--color-warning-fg);
  font-size: var(--text-2xs);
  font-weight: 700;
}
/* 代表値の固定中（顧客詳細①「他の値」・S3b）。**警告ではない**ので `flag`（優先対応・警告色）と分けた。
   人が選んだ状態を示すだけの無彩色（`option` と同じ枠線の型・色は付けない） */
.c-badge--pinned {
  border-color: var(--border);
  background-color: transparent;
  color: var(--color-gray-700);
  font-size: var(--text-2xs);
  font-weight: 600;
}
/* **いま選ばれているもの**の印（突合表の列見出しの「統合先」・S6）。
   **`pinned`（代表値の固定中）を借りない** —— あちらは「人が固定した」という別の意味で、
   見た目だけ借りると変種の写しになる（`.claude/rules/ui-tokens.md` のスノーフレーク防止）。
   **新しい色は作らない** —— 面は選択に使っている `--color-primary-soft`、文字は
   `c-status--dup.c-status--tone-primary` と同じ `--color-teal-900`（10.9:1・実測） */
.c-badge--primary {
  background-color: var(--color-primary-soft);
  color: var(--color-teal-900);
  font-size: var(--text-2xs);
  font-weight: 700;
}
/* 未成年・高齢 */
.c-badge--caution {
  border-color: var(--color-warning-border);
  background-color: var(--color-warning-bg);
  color: var(--color-warning-fg);
  font-size: var(--text-2xs);
  font-weight: 700;
}
/* 回線会社での状態（`ServiceContract.carrier_status`。2026-10-06）。**枠線だけ**（面を塗らない）——
   面を塗る申込ステータスの札（`c-status--entry`）と並んでも別物に見えるように。**`c-status` を名乗らない**
   （同じ部品に見えると、受付状態 → 申込ステータスの対応表〈V-35・未決〉を画面が解いたことになる）。
   色は `data-tone` の3段で、決めるのは受付状態の語だけ（`customer_presenters.carrier_status_badge()`）。
   枠は文字と同じ色（`currentColor`）で引く —— `--color-*-border` は白の上で 1.3:1 前後しかなく、枠が見えない。
   文字の白比（実測・tokens.css の値から計算）: warning-fg 5.57 ／ success-fg 5.43 ／ gray-600 6.01。**新しい色は作らない** */
.c-badge--carrier {
  border-color: currentColor;
  background-color: transparent;
  color: var(--color-gray-600);
  font-size: var(--text-2xs);
  font-weight: 700;
}
.c-badge--carrier[data-tone="neutral"] { color: var(--color-gray-600); }
.c-badge--carrier[data-tone="warning"] { color: var(--color-warning-fg); }
.c-badge--carrier[data-tone="success"] { color: var(--color-success-fg); }
/* 語の中で折り返してよい札（2026-10-06。`c-status--wrap` / `c-product-tag--wrap` と同じ作法）。顧客詳細③の表は半画面で列が狭く、
   回線会社の語は語彙を閉じていない（未知の長い語もそのまま出す）ので、1行に固定すると枠の外へ切れた。
   2行目が隠れないのは `height: auto` で高さの固定を外すから（`.c-badge` の `overflow: hidden` は残したまま。高さが中身に合うので切れない）。
   `flex-shrink: 1` ＋ `min-width: 0` は狭い器で札が縮んで折れるため。**既定（nowrap・1行）は変えない** */
.c-badge--wrap {
  flex-shrink: 1;
  min-width: 0;
  height: auto;
  min-height: calc(var(--spacing) * 5);
  white-space: normal;
  text-align: start;
}


/* ============================================================================
 * Card（汎用の面）／ SectionCard ／ SummaryBox（web/components/crm/section-card.tsx）
 * ========================================================================== */
/* `rounded-lg border border-border bg-surface shadow-1 p-4`（ダッシュボードの KPI 等の頻出形） */
.c-card {
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
  padding: calc(var(--spacing) * 4);
  box-shadow: var(--shadow-1);
}
/* カードの見出し（見つからないときの本文 not_found.html の h1。移植元 `text-md font-semibold`） */
.c-card__title {
  font-size: var(--text-md);
  font-weight: 600;
}
.c-card--flush {
  padding: 0;
  box-shadow: none;
}
.c-card--ai {
  border-color: var(--color-ai-border);
}
/* 押せるカードだけ影を上げる（押せない数字を押せるように見せない） */
a.c-card:hover {
  box-shadow: var(--shadow-2);
}

.c-section-card {
  overflow: hidden;
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
  box-shadow: var(--shadow-1);
}
.c-section-card__head {
  display: flex;
  align-items: center;
  gap: calc(var(--spacing) * 2);
  border-bottom: var(--border-w) solid var(--border);
  background-color: var(--color-gray-50);
  padding: calc(var(--spacing) * 3) calc(var(--spacing) * 4);
  font-size: var(--text-md);
  font-weight: 600;
}
/* 見出し（h2）そのもの。番号・罫・文を横に並べる。右端の補助情報（__meta）は h2 の外の兄弟（section_card.html） */
.c-section-card__title {
  display: flex;
  align-items: center;
  gap: calc(var(--spacing) * 2);
  min-width: 0;
}
/* ①〜④ の番号バッジ */
.c-section-card__number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: calc(var(--spacing) * 4);
  height: calc(var(--spacing) * 4);
  border-radius: var(--radius-sm);
  background-color: var(--color-gray-200);
  font-size: var(--text-2xs);
  font-weight: 700;
  color: var(--color-gray-700);
}
/* アクセント罫。色は**意味**を運ぶ（DESIGN.md §1-2） */
.c-section-card__bar {
  width: calc(var(--spacing) * 1);
  height: calc(var(--spacing) * 4);
  border-radius: var(--radius-sm);
  background-color: var(--color-accent-nontext);
}
.c-section-card--warning .c-section-card__bar { background-color: var(--color-warning-fg); }
.c-section-card--danger  .c-section-card__bar { background-color: var(--color-danger-fg); }
.c-section-card--info    .c-section-card__bar { background-color: var(--color-info-fg); }
.c-section-card--ai      .c-section-card__bar { background-color: var(--color-ai-fg); }
.c-section-card__meta {
  margin-left: auto;
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--color-text-muted);
}
.c-section-card__body {
  padding: calc(var(--spacing) * 4);
}
/* 中身をはみ出して描く区画（押せない操作の理由の吹き出しを切らない。section_card.html の open）。
   切り抜きをやめる代わりに、見出しの面の角を枠に合わせて丸める */
.c-section-card--open {
  overflow: visible;
}
.c-section-card--open .c-section-card__head {
  border-top-left-radius: var(--radius-lg);
  border-top-right-radius: var(--radius-lg);
}

.c-summary-box {
  display: flex;
  align-items: center;
  gap: calc(var(--spacing) * 4);
  border-radius: var(--radius-md);
  background-color: var(--color-primary-soft);
  padding: calc(var(--spacing) * 3) calc(var(--spacing) * 4);
}
.c-summary-box__label {
  font-size: var(--text-sm);
  font-weight: 600;
}
.c-summary-box__note {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
.c-summary-box__value {
  margin-left: auto;
  font-size: var(--text-xl);
  font-weight: 700;
}


/* ============================================================================
 * DataTable（web/components/crm/data-table.tsx ／ .claude/rules/tables.md）
 *
 *   <div class="c-table-wrap">
 *     <table class="c-table" data-density="compact|standard">   ← 縦 padding は base.css の table[data-density]
 *       <thead class="c-table__head"><tr><th class="c-table__th" scope="col" aria-sort="…">
 *            <a class="c-table__sort" href="…">顧客番号</a></th>
 *       <tbody><tr class="c-table__row">（行全体を押せる行は c-table__row--link ＋ 本命のリンクに c-table__row-link）
 *            <td class="c-table__td c-table__td--num|--mono">
 *
 * **行高は table の data-density から決める**（Tailwind 版は <Tr density> と <table density> を
 * 別々に受けていた。1つの表で食い違う理由が無いので、表の属性1つに寄せた・報告済み）。
 * ========================================================================== */
/* 折り返さないセルの横溢れは表側で受ける（1280px 未満の横スクロール・§6。48rem 未満でも枠の中で横に送る ＝ 決定380）。
   `position: relative` は、セルの中の読み上げ専用テキスト（`.sr-only` ＝ `position: absolute`）の包含ブロックを
   この枠にするため。無いと枠の外（ページ）が包含ブロックになり、表の右端のセルの `.sr-only` がページを
   横に伸ばしていた（申込ビューが 390px 幅で 1016px。U-1 第2弾） */
.c-table-wrap {
  position: relative;
  width: 100%;
  overflow-x: auto;
}
/* **はみ出していない枠は切り抜かない**（島 `scroll-region.js` と同じ単位。2026-09-30・S3a の a11y 監査 Med）。
   `overflow-x: auto` は縦にも切り抜くので、枠の中の押せない操作の理由の吹き出しが読めなかった。
   はみ出しているかは島が `data-overflowing` で言う（付いていれば既定の横スクロール）。
   **島が測り終えた枠（`data-scroll-region="ready"`）だけ**に効かせる —— JS が無いときは島が動かないので、
   サーバーが描いたまま（横スクロールでき、`tabindex`・`role` で枠へ入れる）に倒れる */
.c-table-wrap[data-scroll-region="ready"]:not([data-overflowing]) { overflow: visible; }
/* 表の枠は横に送れる区画として焦点を受ける（`tabindex="0"`・`role="region"`・名前。U-13 を「する」で確定・2026-09-30）。
   輪郭は base.css の `:focus-visible` の共通の輪郭。枠の中の表の外周に沿わせるため内側へ引く */
.c-table-wrap:focus-visible {
  outline-offset: calc(var(--focus-outline-w) * -1);
}
/* 48rem 未満では、右に続きがあるときだけ右端を薄く陰らせる（横に送れることの手掛かり。U-1 第2弾）。
   2層の背景: ⑴ `local`（中身と一緒に動く）の面の色の帯が中身の右端に付き、⑵ `scroll`（枠に固定）の陰が枠の右端に付く。
   送り切ると ⑴ が ⑵ の上に重なって陰が消える。はみ出していなければ最初から重なっている。
   **面の色は `--color-surface` 固定**（表の枠はカードの上にだけ置く）。**`background` の一括指定を使わない**
   （`.c-card--flush` と併せたときの `background-color` を消さないため）。見出しの行は自分の背景で陰を覆う。
   **陰の濃さは 8%**: 陰の最も濃い所に `--color-success-fg` の文字が乗っても 4.5:1 を保つ上限（実測 4.67:1。
   12% では 4.27:1、9% で 4.55:1） */
.c-table-wrap {
  background-image:
    linear-gradient(to left, var(--color-surface), var(--color-surface)),
    linear-gradient(to left, color-mix(in oklab, var(--color-text) 8%, transparent), transparent);
  background-position: right center, right center;
  background-size: calc(var(--spacing) * 6) 100%, calc(var(--spacing) * 6) 100%;
  background-repeat: no-repeat;
  background-attachment: local, scroll;
}
/* **修飾 `c-table-wrap--scroll-cue` ＝ 上の陰を 48rem 以上でも出す**（2026-10-14・決定517 の範囲の読み方 ＝ 同日のコーディネーター。PM の確認待ち）。
   使うのは顧客DB一覧の2表だけ（列を縮めず、1280px でも表が枠より広いページは枠の中で横に送る ＝ 決定517。
   手掛かりが無く、1280px の3ページ目ではバッジ列が丸ごと枠の外に隠れていた ＝ UX High）。**新しい見た目は作らない** —— 宣言は上の1か所（2026-10-14 の構造レビュー Med で写しをやめた）で、
   はみ出しているときだけ見える（送り切ると消える）のも同じ。他の表の 48rem 以上の手掛かりは G-3 で未決。
   **⚠ 濃さ 8% では気づけない**（3巡目の UX の実測。1280px の 13/143 ページでバッジ列が丸ごと隠れる）—— 手掛かりの形は PM の判断 ＝ V-189 で、**2026-10-14 に ⑴ 先頭の列の固定に一部確定**（暫定・決定522。下の修飾 `c-table--sticky-first`。読み方 ⒜⒝ は未確認）。陰はそのまま残す */
/* 48rem 以上では陰を出さない（修飾 `--scroll-cue` の枠を除く）。陰の宣言を1か所に置き、ここで打ち消す */
@media (min-width: 48rem) {
  .c-table-wrap:not(.c-table-wrap--scroll-cue) { background-image: none; }
}
.c-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}
.c-table__head {
  /* 面は変数 `--c-table-row-bg` で持つ（行と同じ。先頭の列を残す表の固定のセルが継いで同じ面を塗る ＝ 下の `c-table--sticky-first`） */
  --c-table-row-bg: var(--color-gray-50);
  background-color: var(--c-table-row-bg);
  text-align: left;
  color: var(--color-text-muted);
}
.c-table__th {
  padding: calc(var(--spacing) * 2) calc(var(--spacing) * 3);
  font-weight: 600;
  white-space: nowrap;
}
/* ソート可能な見出しは**リンクで**並び替える（URL に載るので戻ったとき並び順が復元される・§1） */
.c-table__sort {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--spacing) * 1);
  font-weight: 600;
}
.c-table__sort:hover {
  color: var(--primary);
}
/* aria-sort の表示。記号は装飾なので読み上げない（`content: "…" / ""` の代替テキスト空）。
   状態そのものは th の aria-sort が支援技術に伝える */
.c-table__th[aria-sort] .c-table__sort::after {
  font-size: var(--text-2xs);
  content: "◆";
  content: "◆" / "";
}
.c-table__th[aria-sort="ascending"] .c-table__sort::after {
  content: "▲";
  content: "▲" / "";
}
.c-table__th[aria-sort="descending"] .c-table__sort::after {
  content: "▼";
  content: "▼" / "";
}
.c-table__th--num {
  text-align: right;
}
/* 長い見出しだけ折り返す（既定は折り返さない） */
.c-table__th--wrap {
  white-space: normal;
}
.c-table__row {
  border-top: var(--border-w) solid var(--border);
  height: var(--row-h-standard);
  /* **行の面は変数 `--c-table-row-bg` で持つ**（2026-10-14）。行の状態（hover・いま追加した行・リンクの行の hover / 焦点・
     画面 CSS の行の面 ＝ 例 `customers.css` の優先の行）は**この変数だけを書く**（守らせる機構 ＝ `scripts/check_table_row_bg.py` と
     `e2e/geometry.spec.ts` の面の一致）。変数は `td` へ継がれるので、
     先頭の列を残す表（`c-table--sticky-first`）の固定のセルは同じ面を自分で塗れる（状態ごとの写しを持たない）。
     `tr` そのものを不透明にして `td` に `background-color: inherit` で継がせる形は採らない —— 行が不透明になると
     枠の右端の陰（`.c-table-wrap` の背景）が行に覆われて消えた（2026-10-14 の実測）。また既定の面の詳細度が優先の行の面に勝った */
  background-color: var(--c-table-row-bg, transparent);
}
.c-table[data-density="compact"] .c-table__row {
  height: var(--row-h-compact);
}
/* コンパクトは**横の余白も詰める**（§6 の密度規約の表: コンパクト ＝ 横 `--space-2` / 縦 4px、
   標準 ＝ 横 `--space-3` / 縦 `--space-2`。縦は base.css の `table[data-density]`）。
   2026-09-16 まで行高と縦の余白しか効いておらず、§6 の横の欄が実装されていなかった。
   列の多い一覧（顧客DB一覧 11列・申込ビュー 9列）を 1280px に収める余地は、ここが素のまま 12px だと出ない
   （1列あたり 8px ＝ 11列で 88px。実測は e2e/geometry.spec.ts）。
   **顧客DB一覧は例外**（2026-10-14・決定517）—— 1280px に収めることはもう約束ではない（列を縮めず、表が枠より広いページは
   枠の中で横に送る）。詰めた余白は「1280px でも横に送らずに済むページを増やす」ために残している。 */
.c-table[data-density="compact"] .c-table__th,
.c-table[data-density="compact"] .c-table__td {
  padding-inline: calc(var(--spacing) * 2);
}
.c-table__row:hover {
  --c-table-row-bg: var(--color-gray-100);
}
/* **いま追加した行**（2026-10-02・顧客詳細「この顧客のタスク」）。状態は属性 `aria-current="true"` で持つ */
.c-table__row[aria-current="true"] {
  --c-table-row-bg: var(--color-primary-soft);
}
/* 行全体を詳細へのリンクにする行（TrLink）。**JS を使わない stretched link**:
   行内の本命リンク（`c-table__row-link`。顧客名など）の ::after を行いっぱいに広げ、行のどこを選んでも
   そのリンクを押したことにする（Enter で同じ遷移ができるのはリンクそのものだから・tables.md）。
   行内の他の操作（重複候補のバッジなど）は ::after より上に載せて、それぞれの行き先を保つ。
   **`title` を持つ要素（省略した住所・カナ・流入ブランド・アラート等）も ::after より上に載せる**。
   覆われると、ホバーで出るのが本命リンクの title（氏名）になり、省略した全文をマウスで読む手段が無くなる
   （正しさレビュー Med 2026-09-14。`e2e/geometry.spec.ts` が elementFromPoint で固定）。
   受け入れた不利益: 行の文字をドラッグで選べない（選ぶと遷移になる）。`title` を持つ要素の上だけは、押しても遷移しない
   （その要素の外、同じ行の他の場所では遷移する）。
   `title` を持つ要素が本命リンクの祖先（td や包み要素）なら載せない。載せると ::after の包含ブロックが行から
   その要素に縮み、「行のどこを押しても詳細」が黙って効かなくなる（正しさレビュー Low 2026-09-14）。
   `position: relative` を行に置く（表の行を包含ブロックにできるのは現行の Chromium / Firefox / WebKit） */
.c-table__row--link {
  position: relative;
}
.c-table__row--link:hover,
.c-table__row--link:has(.c-table__row-link:focus-visible) {
  --c-table-row-bg: var(--color-primary-soft);
}
.c-table__row-link::after {
  content: "";
  position: absolute;
  inset: 0;
}
.c-table__row--link :is(a, button, [title]:not(:has(.c-table__row-link))):not(.c-table__row-link) {
  position: relative;
  z-index: 1;
}
/* **修飾 `c-table--sticky-first` ＝ 枠の中で横に送っても、先頭の列を左に残す**（2026-10-14。未決 V-189 の手掛かりの形を ⑴ で一部確定 ＝
   PM 佐々木「いったんこれで」＝ 暫定・決定522）。使うのは顧客DB一覧の2表だけ（先頭の列は顧客ID / FV番号・受付番号 / エントリー日 ＝
   その行を名指しする識別子）。右端の陰（8%）だけでは横に送れることに気づけなかった（地との差 約 1.1:1 ＝ 3巡目の UX）ので、
   送ると先頭の列の右の罫の下へ中身が潜っていく形で「送っている」ことを見せる。
   **48rem 以上だけ**（実装の判断・PM 未確認。V-189 は 1280px 幅の手掛かり ＝ G-3 の問いで、48rem 未満で 8.5rem の列を残すと
   390px で送れる幅が 6割に減る）。
   **重なり順**: 送った中身の `[title]`・リンクは `z-index: 1`（上の規則）なので、固定のセルは `z-index: 2` で覆う。
   **受け入れた不利益（実装の判断・PM 未確認）**: 固定のセルは重なりの文脈を作り、行のリンク（`::after`）より上に載る ——
   **先頭の列の上だけは押しても詳細へ遷移しない**（先頭の列はリンクにしない列 ＝ brief D-FV2。同じ行の他の場所では遷移する）。
   **`pointer-events: none` で抜けさせる案は試して採らなかった**（2026-10-14・開発の DB の 13 ページ × 1024 / 1280px × 送り 4 段の実測）:
   送っていないときは空いた所が全部行のリンクに抜けたが、送ると先頭の列の下に潜った `title` を持つ字（カナ・商材の札。`z-index: 1`）に
   当たる点が約 6% 出て、そこでは押しても遷移せず、見えない字の `title` が出た。潜った要素だけ受けないようにする手段は CSS に無い。
   先頭の列に同じ行き先のリンクをもう1本置く案は、表の冒頭の約束（顧客名のリンクより前に `/customers/` の `<a>` を置かない ＝
   チュートリアル）に当たるので採らない。
   **面**: 行の変数 `--c-table-row-bg`（上の `.c-table__row`）を継いで塗る。無ければ `--color-surface`（不透明でないと送った中身が透ける）。
   **罫は影で描く**（`border-collapse: collapse` の表では罫は表のもので、送ってもセルと一緒に動かず見えなかった ＝ 実測）。
   影は1つの宣言にまとめ、⑴ 行の上の罫（`.c-table__row` の `border-top` と同じ向き。固定のセルの面が行の罫を覆うため）
   ⑵ 右の罫 ⑶ 行の印（変数 `--c-table-row-mark`。画面 CSS が行に置く ＝ 例 `customers.css` の優先の行の左の罫）を重ねる。
   強制配色（`forced-colors: active`）では影が描かれないので、罫を疑似要素の枠で描き直す（下の `@media`）。
   焦点の付いた要素をこの列の下に隠さないのは島 `scroll-region.js` の `reveal()`（先頭のセルが sticky ならその幅を避ける） */
@media (min-width: 48rem) {
  .c-table--sticky-first :where(tr > :first-child) {
    position: sticky;
    left: 0;
    z-index: 2;
    background-color: var(--c-table-row-bg, var(--color-surface));
    box-shadow:
      var(--c-table-sticky-ring-start, 0 0 transparent),
      var(--c-table-sticky-ring-top, 0 0 transparent),
      var(--c-table-sticky-rule-top, 0 0 transparent),
      inset calc(var(--border-w) * -1) 0 0 var(--border),
      var(--c-table-row-mark, 0 0 transparent);
  }
  .c-table--sticky-first :where(.c-table__row) {
    --c-table-sticky-rule-top: inset 0 var(--border-w) 0 var(--border);
  }
  /* **枠に焦点があるときの輪郭の左辺と左上**（2026-10-14・a11y Low）。枠の輪郭は内側に引く（上の `.c-table-wrap:focus-visible`。
     外に出すと一覧のカードの `overflow: hidden` に切られる）ので、固定のセル（`z-index: 2`）に覆われていた。重なり順では解けない
     （枠に `isolation: isolate` を付けても覆われた ＝ 実測）ので、**固定のセルが同じ太さ・色の輪郭を自分の影で描く**（影の並びの先頭 ＝ いちばん上）。
     **下辺は描き直していない**（2026-10-20 に Chromium の `OverlayScrollbar` で実測。直すかどうかと直す形は #621 で判断待ち）: 横のスクロールバーが場所を取る環境では
     輪郭の下辺はスクロールバーの下に出るが、場所を取らない環境（オーバーレイ式）では最終行の固定のセルが下辺を覆う。
     面を持つ行（優先の行など）が最終行なら、その行の幅全体で覆う（右辺も、面を持つ行の高さの分は同じく覆われる）。
     CSS からはスクロールバーの種類が分からないので、最終行に描くと場所を取る環境では二重になる */
  .c-table-wrap:focus-visible > .c-table--sticky-first {
    --c-table-sticky-ring-start: inset var(--focus-outline-w) 0 0 var(--color-focus);
  }
  .c-table-wrap:focus-visible > .c-table--sticky-first :where(thead tr:first-child > :first-child) {
    --c-table-sticky-ring-top: inset 0 var(--focus-outline-w) 0 var(--color-focus);
  }
}
@media (min-width: 48rem) and (forced-colors: active) {
  /* 強制配色では影が描かれない（`box-shadow` は none に倒される）。罫 ⑴ ⑵ を疑似要素の枠で描き直す（色は系の字の色。焦点の輪郭だけ `Highlight`）。
     ⑶ 行の印は画面 CSS が同じ形で `::after` に描く（例 `customers.css` の優先の行） */
  .c-table--sticky-first :where(tr > :first-child)::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    border-inline-end: var(--border-w) solid;
  }
  .c-table--sticky-first :where(.c-table__row > :first-child)::before {
    border-block-start: var(--border-w) solid;
  }
  /* 焦点の輪郭の左辺・上辺は、枠の輪郭の本体と同じ色にする。強制配色は輪郭の色を `Highlight` に倒す（Chromium で実測）が、
     色を書かない枠は字の色（`CanvasText`）になり、左辺と上辺だけ色が違っていた（#595） */
  .c-table-wrap:focus-visible > .c-table--sticky-first :where(tr > :first-child)::before {
    border-inline-start: var(--focus-outline-w) solid Highlight;
  }
  .c-table-wrap:focus-visible > .c-table--sticky-first :where(thead tr:first-child > :first-child)::before {
    border-block-start: var(--focus-outline-w) solid Highlight;
  }
}
.c-table__td {
  padding: calc(var(--spacing) * 2) calc(var(--spacing) * 3);
  /* 折り返さない。折り返すと行高がばらついて縦の走査ができなくなる */
  white-space: nowrap;
}
/* 数量（金額・件数）。等幅＋桁揃え＋**右寄せ** */
.c-table__td--num {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  text-align: right;
}
/* 識別子（顧客番号・受付番号・電話番号・日付）。等幅＋桁揃えだが**左寄せのまま** */
.c-table__td--mono {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
}
/* 自由記述など、切ると意味が欠けるセルだけ折り返す（既定は行高を揃えるため折り返さない） */
.c-table__td--wrap {
  white-space: normal;
}
/* 48rem 未満では、折り返すセルに文字数ぶんの最小幅を持たせる。無いと折り返さない列に幅を取られて
   1字ずつ縦に折れ、行が 220〜278px になっていた（ファイル取込・確かめる行・更新記録・顧客詳細③。U-1 第2弾）。
   **全ての表の `--wrap` に掛ける**（2026-09-30 利用者の決定 (c)。2画面に絞ると、更新記録の「変わった項目」が
   52px に細って行が 278px になり、顧客詳細③の見出し「オプション契約」が1字ずつ縦に並んだ）。
   特に長い文が入る列は `--wrap-wide` で広げる。はみ出した分は表の枠の中で横に送る。
   **48rem 以上は変えない**（1280px の列幅は従来どおり） */
@media not all and (min-width: 48rem) {
  .c-table__td--wrap {
    min-width: var(--width-cell-wrap);
  }
  .c-table__td--wrap-wide {
    min-width: var(--width-cell-wrap-wide);
  }
}
/* 半画面に多くの列を収める表（顧客詳細③の7列・「この顧客の他の値」。移植元 `[&_td]:px-2 [&_th]:px-2 text-xs`）。
   行高は data-density のまま、**横の余白と字の大きさだけ**詰める。
   **横の余白は片側 4px**（2026-10-11・Issue #533。§6 のコンパクト〈横 `--space-2`〉より1段詰める・この修飾の表だけ。
   **⚠ 仮置き** ＝ 実装担当の判断で、どの列から幅を取るかの判断〈#533 のコメント〉の確定ではない。§6 の表の注記）——
   顧客詳細③は 1280px で器が 466px、日付4列が字の幅だけで約 270px を取り、`c-product-tag--keep-suffix` の札の最小幅
   （約 86px）を置くと表がはみ出した（7列 × 4px × 両側 ＝ 56px をここから回す）。罫線の無い表なので列の間は 8px 空く。
   セレクタを `.c-table.c-table--tight` にして、上の `.c-table[data-density="compact"]`（横 8px）と**詳細度を揃え、その後ろに
   置いて勝たせている**（**この規則を compact より前へ動かさない**）。従来の `.c-table--tight .c-table__th` は詳細度で
   compact に負け、compact の表ではこの修飾の横の余白が効いていなかった（どちらも 8px だったので見た目は同じ） */
.c-table--tight {
  font-size: var(--text-xs);
}
.c-table.c-table--tight .c-table__th,
.c-table.c-table--tight .c-table__td {
  padding-inline: calc(var(--spacing) * 1);
}


/* ============================================================================
 * Chip（web/components/crm/chip.tsx）
 *
 * SSR では「押すと適用」「× で外す」はどちらも GET のリンク（<a>）になる。
 * 外したあとはページごと描き直されるので、Tailwind 版の「消える要素からフォーカスを逃がす」処理は要らない。
 * ========================================================================== */
.c-chip {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--spacing) * 2);
  border: var(--border-w) solid transparent;
  border-radius: var(--radius-sm);
  padding: calc(var(--spacing) * 1) calc(var(--spacing) * 3);
  font-size: var(--text-sm);
  font-weight: 600;
}
/* 保存検索（押すと適用） */
.c-chip--saved {
  background-color: var(--color-primary-soft);
  color: var(--color-teal-900);
}
/* 適用中のフィルタ（× 付き） */
.c-chip--filter {
  border-color: var(--color-info-border);
  background-color: var(--color-info-bg);
  color: var(--color-info-fg);
}
/* 追加の空きスロット */
.c-chip--dashed {
  border-style: dashed;
  border-color: var(--color-gray-300);
  background-color: var(--color-surface);
  color: var(--color-text-muted);
}
/* いま開いている保存検索（chip.html の current）。色だけに頼らず下線も引く（§10） */
.c-chip--saved:has(> .c-chip__action[aria-current="true"]) {
  border-color: var(--color-accent-nontext);
}
.c-chip__action[aria-current="true"] {
  text-decoration-line: underline;
}
.c-chip__remove {
  position: relative;
  font-weight: 700;
  /* Tailwind 版の `opacity-70 hover:opacity-100` をそのまま移した（×印の弱め。文字列ではなく記号） */
  opacity: 0.7;
}
.c-chip__remove:hover {
  opacity: 1;
}
/* 実寸は小さいので、不可視のヒット領域を広げる（WCAG 2.5.8） */
.c-chip__remove::after {
  content: "";
  position: absolute;
  inset: calc(var(--spacing) * -2);
}


/* ============================================================================
 * SegmentedControl（web/components/crm/segmented-control.tsx）
 *
 * フォームも送信ボタンも持たない（移行計画 D13改）。選択肢の渡し方で2つの形がある（segmented_control.html）:
 *   ① ラジオ（呼ぶ側のフォームに入る。矢印キーでの選択移動はブラウザのラジオが持つ）
 *     <div class="c-segmented" role="radiogroup" aria-label="…">
 *       <label class="c-segmented__option"><input class="c-segmented__input" type="radio" …>
 *         <span class="c-segmented__label">すべて</span></label>
 *   ② リンク（選ばれている方に aria-current="true"。状態は属性で持つ）
 *     <div class="c-segmented" role="group" aria-label="…">
 *       <a class="c-segmented__link" href="…" aria-current="true">顧客ビュー</a>
 * ========================================================================== */
.c-segmented {
  display: inline-flex;
  /* 選択肢の単位で折り返す（選択肢の中の語は割らない）。狭い幅で文字が縦に割れ、画面の外へ出ていた（U-1 第2弾）。
     1行に収まる幅では見た目は変わらない */
  flex-wrap: wrap;
  max-width: 100%;
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  padding: calc(var(--spacing) * 1);
}
.c-segmented__option {
  position: relative;
  display: inline-flex;
}
/* ラジオ自体は見せないが、フォーカスと選択は受け取る（display:none にしない） */
.c-segmented__input {
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
}
.c-segmented__label,
.c-segmented__link {
  border-radius: var(--radius-sm);
  padding: calc(var(--spacing) * 1) calc(var(--spacing) * 3);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-text-muted);
  transition-property: color, background-color;
  transition-timing-function: var(--ease-standard);
  transition-duration: var(--duration-colors);
}
.c-segmented__link {
  text-decoration: none;
}
.c-segmented__option:hover .c-segmented__label,
.c-segmented__link:hover {
  background-color: var(--color-gray-100);
  color: var(--color-text);
}
.c-segmented__input:checked + .c-segmented__label,
.c-segmented__link[aria-current="true"] {
  background-color: var(--primary);
  color: var(--color-white);
}
/* 選択肢に添える件数（顧客DB一覧の顧客区分。2026-09-16）。**名前の一部として読まれる**（aria-hidden にしない） */
.c-segmented__count {
  margin-left: calc(var(--spacing) * 1);
  font-weight: 400;
  /* 件数だけ書体が変わる（`.num` の等幅）ので、行の箱を書体の ascent/descent で太らせない（2026-10-05・#374。
     件数を持つ選択肢だけが機体のフォントしだいで 1〜2px 高くなっていた）。行の高さはラベルが持つ */
  line-height: 1;
}
/* 輪郭は見えている側（ラベル）に描く。入力は透明なので、そちらに描いても見えない */
/* 入力の誤り（選択肢に aria-invalid）。色だけで伝えない ＝ 文は呼ぶ側の fieldset が結ぶ */
.c-segmented:has(.c-segmented__input[aria-invalid="true"]) {
  border-color: var(--destructive);
}
.c-segmented__input:focus-visible + .c-segmented__label {
  outline: var(--focus-outline-w) solid var(--color-focus);
  outline-offset: var(--focus-outline-offset);
}


/* ============================================================================
 * ProductTabs（web/components/customers/product-tabs.tsx）
 *
 * role="tablist" のリンク列。確定は Enter（リンクの既定動作）。矢印・Home・End は tabs.js。
 * ========================================================================== */
.c-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--spacing) * 0.5);
  margin-bottom: calc(var(--spacing) * 4);
}
.c-tabs__tab {
  border-radius: var(--radius-md);
  padding: calc(var(--spacing) * 2) calc(var(--spacing) * 4);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-text-muted);
}
.c-tabs__tab:hover {
  background-color: var(--color-gray-100);
  color: var(--color-text);
}
.c-tabs__tab[aria-selected="true"],
.c-tabs__tab[aria-selected="true"]:hover {
  background-color: var(--primary);
  color: var(--color-white);
}
.c-tabs__count {
  margin-left: calc(var(--spacing) * 1);
}
/* **下線の帯**（`variant="segment"`。2026-10-07 に `primary` から改名 ＝ Button の `primary` と意味がぶつかるため。顧客DB一覧の1段目のタブ「顧客」「リード」＝ 決定470・design-brief 顧客DB一覧_顧客とリード §④）。
   商材タブ（塗りの札）と**形で**階層を分ける。帯の罫は全幅、選択中だけ太い下線（`--stripe-w` の `--primary`）。
   **選択を色だけで示さない**: 下線（形）＋字の濃さ＋ `aria-selected`。面は塗らない（色の面積を増やさない）。
   下線は罫に重ねる（`margin-bottom` を罫の幅だけ負に）。アニメーションは付けない（§8）。フォーカスは既存の `:focus-visible` のまま */
.c-tabs--segment {
  gap: 0;
  border-bottom: var(--border-w) solid var(--border);
  margin-bottom: 0;
}
.c-tabs--segment .c-tabs__tab {
  border-radius: 0;
  border-bottom: var(--stripe-w) solid transparent;
  margin-bottom: calc(var(--border-w) * -1);
  font-size: var(--text-md);
}
.c-tabs--segment .c-tabs__tab:hover {
  background-color: transparent;
  color: var(--color-text);
}
.c-tabs--segment .c-tabs__tab[aria-selected="true"],
.c-tabs--segment .c-tabs__tab[aria-selected="true"]:hover {
  background-color: transparent;
  color: var(--color-text);
  border-bottom-color: var(--primary);
}
/* 件数は1段大きく（`--text-2xs` → `--text-xs`。2026-10-07・UX Med: 母集団の件数は判断の材料なので札の字のままだと読みにくい）。
   商材タブの件数（既定の `.c-tabs__count`）は変えない */
.c-tabs--segment .c-tabs__count {
  font-size: var(--text-xs);
}
/* **枠の札**（`variant="sub"`。顧客DB一覧の商材名のタブ ＝ 商材タブの下の段・決定168・Issue #4・
   design-brief 顧客DB一覧_商材の下の段 §④・D-PN3）。変種の段を**形で**分ける（画面上の位置ではなく変種の段。商材名のタブは申込ビューでは2段目に来るので序数で呼ばない ＝ 決定481）: 1段目 ＝ 下線の帯（`segment`）／2段目 ＝ 塗りの札（既定）／3段目 ＝ 枠の札（`sub`）。
   **主張しない側**に置く（シグネチャは下線の帯）。字は商材タブと同じ（小ささは余白と枠で出す）。
   **選択を色だけで示さない**（2026-10-07・UX Med／a11y Low で直した）: 手掛かりは**枠の太さ**（選択中だけ `--border-w` の2倍 ＝ 形）
   ＋枠と字の主色＋ `aria-selected`。**淡い面（`--color-primary-soft`）は手掛かりに数えない** —— ページ面との差は
   1.02:1 で、見分けには効かない（実測。面は残すが添え物）。太くした分は余白から引き、札の大きさを変えない（並びが揺れない）。
   強制配色（Windows のハイコントラスト）では面と色が消えるので、枠の太さだけが残る（下の `@media (forced-colors: active)`）。
   件数とフォーカスは既定のまま（上書きしない）。アニメーションは付けない（§8） */
.c-tabs--sub {
  gap: calc(var(--spacing) * 2);
}
.c-tabs--sub .c-tabs__tab {
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius-sm);
  padding: calc(var(--spacing) * 1) calc(var(--spacing) * 3);
}
.c-tabs--sub .c-tabs__tab:hover {
  background-color: var(--muted);
  color: var(--color-text);
}
.c-tabs--sub .c-tabs__tab[aria-selected="true"],
.c-tabs--sub .c-tabs__tab[aria-selected="true"]:hover {
  background-color: var(--color-primary-soft);
  border-color: var(--primary);
  border-width: calc(var(--border-w) * 2);
  padding: calc(var(--spacing) * 1 - var(--border-w)) calc(var(--spacing) * 3 - var(--border-w));
  color: var(--primary);
}

/* **強制配色でも選択中を形で見分ける**（2026-10-07・a11y Low）。強制配色では背景が `Canvas` に、字と枠が
   `CanvasText` に置き換わる —— 塗りの札（既定・商材タブ）は**塗りが消えて選択中が見えなくなる**。
   塗りの札は選択中にだけ太い枠を足し（太さは枠の札と同じ `--border-w` の2倍・その分を余白から引く）、
   枠の札（`sub`・商材名のタブ）は上の規則の太さがそのまま残る。**塗りの札と枠の札で同じ規則**（選択中 ＝ 太い枠）に揃える。
   下線の帯（`segment`）は、選択していないタブの透明な下線が強制配色で**見える色に置き換わり**、全部のタブに下線が付いていた
   （実測）。選択していないタブの下線を面と同じ `Canvas` にして、選択中の下線だけを残す（作者が書いたシステム色は置き換わらない）。
   帯の罫を隠さないよう、選択していないタブは罫に重ねず（`margin-bottom: 0`）、その分だけ下線を細くする（高さは揃う） */
@media (forced-colors: active) {
  .c-tabs--segment .c-tabs__tab[aria-selected="false"] {
    margin-bottom: 0;
    border-bottom: calc(var(--stripe-w) - var(--border-w)) solid Canvas;
  }
  .c-tabs--segment .c-tabs__tab[aria-selected="true"] {
    border-bottom-color: CanvasText;
  }
  .c-tabs:not(.c-tabs--segment):not(.c-tabs--sub) .c-tabs__tab[aria-selected="true"] {
    border: calc(var(--border-w) * 2) solid CanvasText;
    padding: calc(var(--spacing) * 2 - var(--border-w) * 2) calc(var(--spacing) * 4 - var(--border-w) * 2);
  }
  .c-tabs--sub .c-tabs__tab[aria-selected="true"] {
    border-color: CanvasText;
  }
}


/* ============================================================================
 * LoadError（web/components/crm/load-error.tsx）
 *
 * ④エラー（network / badRequest / server）と⑥権限なし（forbidden）で**見た目が違う**。
 * ⑥は不具合ではないので赤で描かない（中立な面）。
 * ========================================================================== */
.c-load-error {
  border: var(--border-w) solid var(--color-danger-border);
  border-radius: var(--radius-lg);
  background-color: var(--color-danger-bg);
  padding: calc(var(--spacing) * 4);
}
.c-load-error__title {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--color-danger-fg);
}
.c-load-error__message,
.c-load-error__hint,
.c-load-error__note {
  margin-top: calc(var(--spacing) * 2);
  font-size: var(--text-sm);
}
.c-load-error__message {
  color: var(--color-danger-fg);
}
.c-load-error__hint,
.c-load-error__note {
  color: var(--color-text-muted);
}
.c-load-error__actions {
  margin-top: calc(var(--spacing) * 3);
}
/* ⑥ 権限なし */
.c-load-error--forbidden {
  border-color: var(--border);
  background-color: var(--color-gray-50);
}
.c-load-error--forbidden .c-load-error__title {
  color: inherit;
}
.c-load-error--forbidden .c-load-error__message {
  color: inherit;
}


/* ============================================================================
 * EmptyState（web/components/crm/empty-state.tsx）。②空は必ず次の一手を置く
 * ========================================================================== */
.c-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--spacing) * 2);
  padding: calc(var(--spacing) * 12) calc(var(--spacing) * 4);
  text-align: center;
}
.c-empty__title {
  font-size: var(--text-sm);
  font-weight: 600;
}
.c-empty__description {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
.c-empty__action {
  margin-top: calc(var(--spacing) * 2);
}


/* ============================================================================
 * StatusBadge（web/components/crm/status.tsx）
 *
 * 3つの**別レイヤー**を1つの部品に集める。語彙（キー⇄ラベル）はこのファイルに持たない ——
 * 持ち主は api/domain/contracts/status.py（申込）等の Python 側で、テンプレートは受け取って描くだけ。
 * ========================================================================== */
/* ---- 申込ステータスの段（キーで色を引く。**数詞を書かない** ＝ tokens.css の同じ節） ---- */
.c-status--entry {
  display: inline-block;
  border-radius: var(--radius-sm);
  padding: calc(var(--spacing) * 1) calc(var(--spacing) * 2);
  font-size: var(--text-2xs);
  font-weight: 700;
  white-space: nowrap;
}
/* 語の中で折り返してよい札（2026-09-30）。顧客詳細③の表（半画面に7列）は「キャンセル申請中」の札が 112px を取り、
   商材名の札を読める幅が残らなかった。**既定（nowrap）は変えない** —— 表の段の札は1語で見せるのが原則 */
.c-status--wrap { white-space: normal; }
.c-status--entry[data-status="applied"]  { background-color: var(--color-entry-applied-bg);  color: var(--color-entry-applied-fg); }
.c-status--entry[data-status="callfail"] { background-color: var(--color-entry-callfail-bg); color: var(--color-entry-callfail-fg); }
.c-status--entry[data-status="calldone"] { background-color: var(--color-entry-calldone-bg); color: var(--color-entry-calldone-fg); }
.c-status--entry[data-status="entered"]  { background-color: var(--color-entry-entered-bg);  color: var(--color-entry-entered-fg); }
.c-status--entry[data-status="workdate"] { background-color: var(--color-entry-workdate-bg); color: var(--color-entry-workdate-fg); }
.c-status--entry[data-status="opened"]   { background-color: var(--color-entry-opened-bg);   color: var(--color-entry-opened-fg); }
.c-status--entry[data-status="cxlreq"]   { background-color: var(--color-entry-cxlreq-bg);   color: var(--color-entry-cxlreq-fg); }
.c-status--entry[data-status="cxl"]      { background-color: var(--color-entry-cxl-bg);      color: var(--color-entry-cxl-fg); }

/* ---- 顧客状態（導出の5値）。バッジではなくテキスト。鍵は domain/listing/customer_conditions.py の STATUS_KEYS ---- */
.c-status--customer {
  font-size: var(--text-sm);
  font-weight: 600;
  white-space: nowrap;
}
.c-status--customer[data-status="active"]      { color: var(--color-cstatus-active); }
.c-status--customer[data-status="applying"]    { color: var(--color-cstatus-applying); }
.c-status--customer[data-status="negotiating"] { color: var(--color-cstatus-negotiating); }
.c-status--customer[data-status="prospect"]    { color: var(--color-cstatus-prospect); }
/* 解約は色だけに頼らず取り消し線を併用する（§10） */
.c-status--customer[data-status="cancelled"]   { color: var(--color-cstatus-cancelled); text-decoration-line: line-through; }

/* ---- 名寄せ候補の状態6種 ----
   **色は語の補助**（語は必ず一緒に出る・§10）。状態は日本語の語そのものが持ち主
   （api/customers/dup_views.py の STATUS_RULES）なので、修飾クラスは tone で受ける。
   語→tone の写像は Python 側（templatetag）に置き、ここに6語を写さない。
     未確認=danger ／ 確認中=info ／ 確定=primary ／ 同一と判定=success ／ 別人と判定=neutral ／ 保留=warning
   **要確認顧客の組の状態（`c-status--review`。決定462・2026-10-05）も同じ宣言を共有する** —— 同じ型・同じ tone の語彙
   （新しい色を作らない）。**別の修飾名にするのは数えるため**で、宣言は写さずセレクタを並べる（片方だけ直して2つの札がずれない）——
   顧客詳細で `.c-status--dup` を数える e2e が帯の札を拾わないように。状態の綴りは `domain/merge/review_flags.py` の `PairState`、
   語→tone は `webui/needs_review_present.py`（未判断=warning ／ 保留=neutral ／ 不正の疑いあり=danger ／ 問題なし=success ／ 統合した=neutral）。
   **書き出しの状態（`c-status--export`。2026-10-12 ＝ #517）も同じ宣言を共有する** —— 語→tone は `webui/exports_present.py`
   （失敗=danger ／ 他はすべて neutral ＝ 色の付いた面は失敗だけ） */
.c-status--dup,
.c-status--review,
.c-status--export {
  display: inline-block;
  border-radius: var(--radius-sm);
  padding: calc(var(--spacing) * 0.5) calc(var(--spacing) * 2);
  font-size: var(--text-2xs);
  font-weight: 700;
  white-space: nowrap;
}
.c-status--dup.c-status--tone-danger,  .c-status--review.c-status--tone-danger, .c-status--export.c-status--tone-danger { background-color: var(--color-danger-bg);    color: var(--color-danger-fg); }
.c-status--dup.c-status--tone-info,    .c-status--review.c-status--tone-info, .c-status--export.c-status--tone-info { background-color: var(--color-info-bg);      color: var(--color-info-fg); }
.c-status--dup.c-status--tone-primary, .c-status--review.c-status--tone-primary, .c-status--export.c-status--tone-primary { background-color: var(--color-primary-soft); color: var(--color-teal-900); }
.c-status--dup.c-status--tone-success, .c-status--review.c-status--tone-success, .c-status--export.c-status--tone-success { background-color: var(--color-success-bg);   color: var(--color-success-fg); }
.c-status--dup.c-status--tone-neutral, .c-status--review.c-status--tone-neutral, .c-status--export.c-status--tone-neutral { background-color: var(--color-gray-100);     color: var(--color-gray-600); }
.c-status--dup.c-status--tone-warning, .c-status--review.c-status--tone-warning, .c-status--export.c-status--tone-warning { background-color: var(--color-warning-bg);   color: var(--color-warning-fg); }
.c-status__count {
  margin-left: calc(var(--spacing) * 1);
}

/* ---- 語彙に無い値。空セルにせず生のまま出す。意味の分からない値に色を付けない ---- */
.c-status--unknown {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}


/* ============================================================================
 * ProductTag（web/components/crm/product-tag.tsx）。商材10色。必ず商材名のテキストを伴う
 * ========================================================================== */
.c-product-tag {
  display: inline-block;
  border-radius: var(--radius-sm);
  padding: calc(var(--spacing) * 1) calc(var(--spacing) * 2);
  font-size: var(--text-2xs);
  font-weight: 600;
  white-space: nowrap;
}
/* 折り返してよい札（2026-09-30）。**1申込の札は字が商材名**（`Product.name`。長さの上限は器の 128字）なので、
   狭い器（顧客詳細②のカードの頭・③の7列の表・申込ビューと顧客ビューの商材の列）で 1行に収まらないことがある。
   **顧客詳細・契約詳細の札（見出し・商談記録・変更履歴）も全部これ** —— 320px で「レ点（商材未設定）」が
   ページを 5px 横に伸ばした（`e2e/components-responsive.spec.ts`・2026-10-01）。折れるのは器より長いときだけ
   nowrap のままだと表が横にはみ出す／カードの頭で申込ステータスの札が次の行に落ちる。
   **既定（nowrap）は変えない** —— 大分類の語だけの札（見込み商材・見本）は折れない方が縦に走査しやすい */
.c-product-tag--wrap {
  white-space: normal;
  min-width: 0;
  overflow-wrap: anywhere;
}
/* 札の字の「（商材未設定）」の側を**括弧の中で折らない**札（2026-10-11・Issue #533）。部品は字を常に本体と
   `__suffix` に分けて描くが、1行に保つのはこの修飾を付けた札だけ —— 折れ目は本体と括弧の間だけになる（「レ点 / （商材未設定）」）。
   **使うのは顧客詳細③の7列の表だけ**（`_q3_workflow.html`。`--wrap` と併せる）。札全体が `anywhere` のままだと、表の
   自動の列配分で商材の列が字1つぶんまで細り、1280px で「レ点（商材 / 未設定）」、1024px で1字ずつ縦に並んだ。
   括弧の字の幅（`--text-2xs` 10px × 7字 ＝ 70px）に札の左右の余白（16px）を足した約 86px がこの札の最小幅になる。
   **全ての札には掛けない** —— ②の契約カードの頭（札が `min-width: 0` で縮み、横のステータスの札は縮まない）では
   括弧が札の色の面から最大 45px はみ出し、900px で「開通」の札に重なった。320px の商談記録・変更履歴の列（約 70px）
   にも収まらない（2026-10-11 の ux-critic・a11y-auditor の実測）。表のセルは中身に合わせて広がるので、③の表では起きない */
.c-product-tag--keep-suffix .c-product-tag__suffix {
  white-space: nowrap;
}
.c-product-tag[data-product="elec"]   { background-color: var(--color-product-elec-bg);   color: var(--color-product-elec-fg); }
.c-product-tag[data-product="gas"]    { background-color: var(--color-product-gas-bg);    color: var(--color-product-gas-fg); }
.c-product-tag[data-product="mobile"] { background-color: var(--color-product-mobile-bg); color: var(--color-product-mobile-fg); }
.c-product-tag[data-product="net"]    { background-color: var(--color-product-net-bg);    color: var(--color-product-net-fg); }
.c-product-tag[data-product="wifi"]   { background-color: var(--color-product-wifi-bg);   color: var(--color-product-wifi-fg); }
.c-product-tag[data-product="ws"]     { background-color: var(--color-product-ws-bg);     color: var(--color-product-ws-fg); }
.c-product-tag[data-product="check"]  { background-color: var(--color-product-check-bg);  color: var(--color-product-check-fg); }
.c-product-tag[data-product="ins"]    { background-color: var(--color-product-ins-bg);    color: var(--color-product-ins-fg); }
.c-product-tag[data-product="tv"]     { background-color: var(--color-product-tv-bg);     color: var(--color-product-tv-fg); }
.c-product-tag[data-product="estate"] { background-color: var(--color-product-estate-bg); color: var(--color-product-estate-fg); }


/* ============================================================================
 * AIPanel ／ AiLevelChip ／ MatchChip（web/components/crm/ai.tsx）
 * ========================================================================== */
.c-ai-panel {
  border: var(--border-w) solid var(--color-ai-border);
  border-radius: var(--radius-lg);
  background-color: var(--color-ai-bg);
  padding: calc(var(--spacing) * 4);
}
.c-ai-panel__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: calc(var(--spacing) * 3);
}
/* 「AI」の印。装飾ではなく「AI の出力である」という意味を運ぶ（§4-B R-5 の食い違いは報告済み） */
.c-ai-panel__mark {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: var(--control-h-compact);
  height: var(--control-h-compact);
  border-radius: var(--radius-md);
  background-color: var(--color-ai-fg);
  font-size: var(--text-2xs);
  font-weight: 700;
  color: var(--color-white);
}
.c-ai-panel__main {
  flex: 1 1 0%;
  min-width: 0;
}
.c-ai-panel__title {
  font-size: var(--text-md);
  font-weight: 600;
}
.c-ai-panel__meta {
  margin-top: calc(var(--spacing) * 1);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
/* `dev_notice`（2026-09-22・ux-critic Med①）。開発用の偽物クライアントの打ち消し文を、
 * 本文（12px/400・埋もれていた）から切り離して見出し直下に独立させる。警告トーンで、
 * 確度バッジ（右上）を見た視線がすぐ拾える位置に置く */
.c-ai-panel__dev-notice {
  display: inline-block;
  margin-top: calc(var(--spacing) * 1);
  border: var(--border-w) solid var(--color-warning-border);
  border-radius: var(--radius-sm);
  background-color: var(--color-warning-bg);
  padding: calc(var(--spacing) * 1) calc(var(--spacing) * 2);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--color-warning-fg);
}
.c-ai-panel__body {
  margin-top: calc(var(--spacing) * 1);
  font-size: var(--text-sm);
}
.c-ai-panel__level {
  flex-shrink: 0;
  align-self: center;
}
.c-ai-panel__actions {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: calc(var(--spacing) * 2);
}
/* `reasons_label`（2026-09-22・ux-critic High②）。`reasons` が「AIの根拠」ではなく
 * 「AIに送った材料」であるときの前置き（AIを使った名寄せデモのみ渡す） */
.c-ai-panel__reasons-label {
  margin-top: calc(var(--spacing) * 3);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-text-muted);
}
/* 根拠は常に展開（§11 G11）。畳まない */
.c-ai-panel__reasons {
  display: grid;
  gap: calc(var(--spacing) * 2);
  margin-top: calc(var(--spacing) * 3);
}
/* `reasons_label` が在るときは、その直下に詰める（見出し→内容の関係を保つ） */
.c-ai-panel__reasons-label + .c-ai-panel__reasons {
  margin-top: calc(var(--spacing) * 1);
}
@media (min-width: 48rem) {
  .c-ai-panel__reasons { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.c-ai-panel__reason {
  display: flex;
  align-items: flex-start;
  gap: calc(var(--spacing) * 2);
}
.c-ai-panel__reason .c-match {
  flex-shrink: 0;
  margin-top: calc(var(--spacing) * 0.5);
}
.c-ai-panel__reason-text {
  font-size: var(--text-sm);
}
.c-ai-panel__caution {
  margin-top: calc(var(--spacing) * 3);
  border: var(--border-w) solid var(--color-warning-border);
  border-radius: var(--radius-md);
  background-color: var(--color-warning-bg);
  padding: calc(var(--spacing) * 2) calc(var(--spacing) * 3);
  font-size: var(--text-sm);
  color: var(--color-warning-fg);
}
.c-ai-panel__caution b {
  font-weight: 600;
}
/* 却下したあとの1行（role="status"）。ai-panel.js が切り替える */
.c-ai-panel__dismissed {
  display: flex;
  align-items: center;
  gap: calc(var(--spacing) * 3);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* AIを使った名寄せデモ（AI_MERGE_DEMO・既定 off・社内検証用）の確度（%）。
 * 決定84の例外（決定195・DESIGN.md §11-B 2026-09-22 追記）——このデモに限り、
 * ai_panel.html の confidence_percent を渡したときだけ描く。**バーは持たない**（数値のみ）。
 *
 * **2026-09-22（ux-critic High②の実測）**: 以前は c-level--high と同じ2トークン
 * （--color-ai-bg / --color-ai-fg）を流用しており、隣の「強さ区分」チップと
 * 背景色・文字色・太さ・サイズが完全に同一で見分けが付かなかった。**塗り（c-level）に
 * 対して枠線のみ**で色・形を分けた。
 *
 * **2026-09-22（後刻・ux-critic Med＋a11y-auditor High の再指摘で色を作り直した）**:
 * ⑴ ux-critic: 枠線を --color-info-* に変えたことで、**§5-B「--ai は AI が生成した
 * 内容にのみ使う」の意味論が逆転**した——パネル全体（紫の枠・AI の印）は規則由来の根拠を
 * 含んだまま紫を名乗るのに、真に AI 由来の確度だけが紫でなくなっていた。
 * ⑵ a11y-auditor: **--color-info-border 自体がほぼ見えていなかった**（実測 3件とも
 * 3:1 未達 —— 塗り〈白〉↔パネル背景 1.11:1／枠線↔塗り 1.49:1／枠線↔パネル背景 1.34:1）。
 * **--color-ai-border（#d5c2f4）も同じ理由で不採用**（パネル背景に対し 1.47:1・実測）。
 * **白地＋--color-ai-fg の枠線・文字**にした（実測: --color-ai-fg ↔ パネル背景 7.64:1、
 * ↔ 白地 8.47:1。いずれも 3:1 を大きく超える）。**新しいトークンは作っていない**
 * （既存の --color-ai-fg・--radius-md を流用） */
.c-ai-panel__confidence {
  flex-shrink: 0;
  align-self: center;
  display: inline-flex;
  align-items: baseline;
  gap: calc(var(--spacing) * 1);
  border: var(--border-w) solid var(--color-ai-fg);
  border-radius: var(--radius-md);
  padding: calc(var(--spacing) * 1) calc(var(--spacing) * 3);
  background-color: var(--color-white);
  font-size: var(--text-sm);
  white-space: nowrap;
  color: var(--color-ai-fg);
}
.c-ai-panel__confidence .num {
  font-size: var(--text-md);
  font-weight: 700;
}

/* 強さ区分（高／中／低）。確度（%）とバーは持たない（決定 84・§11-B）。
 * **例外は AIPanel の confidence_percent（上の .c-ai-panel__confidence）だけ**
 * —— この .c-level 自体は確度を持たない・バーを持たないままである */
.c-level {
  display: inline-block;
  border-radius: var(--radius-sm);
  padding: calc(var(--spacing) * 0.5) calc(var(--spacing) * 2);
  font-size: var(--text-2xs);
  font-weight: 700;
  white-space: nowrap;
}
.c-level--lg {
  padding: calc(var(--spacing) * 1) calc(var(--spacing) * 3);
  font-size: var(--text-md);
}
.c-level--high { background-color: var(--color-ai-bg);      color: var(--color-ai-fg); }
.c-level--mid  { background-color: var(--color-warning-bg); color: var(--color-warning-fg); }
.c-level--low  { background-color: var(--color-gray-100);   color: var(--color-gray-600); }
.c-level-caption {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--spacing) * 1);
  text-align: center;
}
.c-level-caption__text {
  font-size: var(--text-2xs);
  color: var(--color-text-muted);
}

/* 突合・検知根拠の印。色を持つのは same / sim / diff の3値だけ。single / empty は無彩色の面（§5-B3 の分岐表） */
.c-match {
  display: inline-block;
  border-radius: var(--radius-sm);
  padding: calc(var(--spacing) * 0.5) calc(var(--spacing) * 2);
  font-size: var(--text-2xs);
  font-weight: 600;
}
.c-match--same   { background-color: var(--color-success-bg); color: var(--color-success-fg); }
.c-match--sim    { background-color: var(--color-warning-bg); color: var(--color-warning-fg); }
.c-match--diff   { background-color: var(--color-danger-bg);  color: var(--color-danger-fg); }
.c-match--single,
.c-match--empty  { background-color: var(--color-gray-100);   color: var(--color-gray-600); }


/* ============================================================================
 * Stepper（web/components/crm/stepper.tsx）
 * ========================================================================== */
.c-stepper {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 1);
}
.c-stepper__bar {
  display: flex;
  gap: calc(var(--spacing) * 1);
}
.c-stepper__seg {
  flex: 1 1 0%;
  height: calc(var(--spacing) * 1);
  border-radius: var(--radius-sm);
}
.c-stepper__seg--done { background-color: var(--color-accent-nontext); }
.c-stepper__seg--todo { background-color: var(--color-gray-200); }
.c-stepper__seg--warn { background-color: var(--color-danger-fg); }
/* 中止は未着手と明度が近いので斜線を重ねる（base.css の .stripe-cxl と併用する） */
.c-stepper__seg--cxl  { background-color: var(--color-gray-300); }
/* キャンセル申請中（**W-7** / 判断モック **D17**・2026-09-17 の第5束）。**確定（中止）と読み分ける** ——
 * 代理店が申し出ただけで、キャリアの確定まで 12日かかった例がある。
 * 色は申込ステータスのチップと同じ `--color-entry-cxlreq-fg`（同じ段に2つ目の色を作らない）。
 * **斜線は重ねない**（`.stripe-cxl` は「中止」の印で、テンプレートが `cxl` の段にだけ付ける）。 */
.c-stepper__seg--cxlreq { background-color: var(--color-entry-cxlreq-fg); }
/* **その段の記録があるか**（台帳 **Y-8** の確定 ＝ Wiki 意思決定の記録 **155**・利用者判断・2026-09-17）。
 * **完了数（`done` / `total`）は1つも変えていない** —— 塗りも「N/M 完了」も今までどおりで、
 * **記録の無い段だけを破線にする**（開通日だけが入った行は「5/5 完了」のまま、工事日確定が破線になる）。
 * **色を足さない**（DESIGN.md §10「色だけで意味を伝えない」）—— 段の状態の色は `--seg--*` がそのまま持ち、
 * ここは**形（実線／破線）だけ**を変える。`transparent` の側は段の色がそのまま透ける。
 *
 * **縞は `--color-surface`（白）。`--color-gray-400` から替えた**（2026-09-17 の a11y レビュー **High**）——
 * **WCAG 1.4.11 の 3:1 に届いていなかった**。実測（画面担当が相対輝度を計算し直した値）:
 *   gray-400 と done の下地 teal-600 … **1.52:1**（不可）／ gray-400 と todo の下地 gray-200 … **1.96:1**（不可）
 *   **白と teal-600 … 3.69:1**（可）／ 白と danger-fg … 6.70:1（可）／ gray-900 と danger-fg … 2.65:1（不可）
 * **印が付くのは `done` の段だけ**になった（`_MARKED_STATES`）ので、**下地は teal-600 だけ** ＝ **3.69:1** である。
 * **契約カードには段名も丸も無く、破線が唯一の視覚的な担い手**なので、ここが届かないと弱視の人に何も残らない
 * （`sr-only` は目に見えず、1.4.11 にテキスト代替の免除は無い）。
 * **新しいトークンは作っていない** —— `--color-surface` と `--stripe-w` の再利用（Y-3 の確定と同じ作法）。
 *
 * **`data-recordable` は選ばない** —— 「まだ記録がない」と「記録する欄が無い」の区別は**語**が持つ
 * （`.c-stepper__no-column`）。見た目の語彙は2つのままにする（3つ目の印を作らない ＝ Y-8 の細部 ⑵）。 */
.c-stepper__seg[data-recorded="no"] {
  background-image: repeating-linear-gradient(
    90deg,
    transparent 0 var(--stripe-w),
    var(--color-surface) var(--stripe-w) calc(var(--stripe-w) * 2)
  );
}
/* 段名（棒の下。**なぜその段なのか**を読めるようにする・2026-09-17 の UX レビュー Med）。
 * 各段は棒のセグメントと同じ `flex: 1 1 0%` で、名前が対応するセグメントの真下に来る。
 * 状態は**色ではなく濃さ**で持つ（済んだ段は本文色、これからの段は控えめな色）。 */
.c-stepper__stages {
  display: flex;
  gap: calc(var(--spacing) * 1);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* **折り返しを許す**（2026-09-17 の a11y レビュー High ＝ WCAG 1.4.4 Resize text）。
 * それまで `word-break: keep-all` を敷いており、**箱が縮んでも段名が縮まず、外へ溢れて隣に重なった**
 * （実測: 1024px で 2px・640px で 40px。**640px は 1280px を 200% ズームしたときの CSS ビューポート**で、
 * そこでは「申込込確認電話完了エントリー完了…」と潰れて判読できない）。
 * **省略記号は使わない**（内容が欠ける）。`overflow-wrap: anywhere` も要る ——
 * 禁則で行頭に置けない「ー」があり（「エントリー完了」）、`word-break: normal` だけでは
 * 割れない2文字の塊が残る。 */
.c-stepper__stage {
  flex: 1 1 0%;
  min-width: 0;
  font-size: var(--text-2xs);
  line-height: var(--leading-head);
  color: var(--color-text-muted);
  word-break: normal;
  overflow-wrap: anywhere;
}
.c-stepper__stage[data-state="done"] {
  color: var(--color-text);
  font-weight: 600;
}
/* 48rem 未満は段名を棒の下に**縦に1段ずつ**並べる（U-1 第3弾）。横に並べたままだと 1段が 48〜62px になり、
 * 段名が語の途中で折れていた（「申し込/み中」「エントリ/ー完了」）。語は変えない・字も詰めない。
 * 棒のセグメントの真下という位置の対応は失うが、並びは `ol` の順（＝ 進む順）のまま、状態は濃さ・色・取り消し線、
 * 記録の有無は頭の印（`::before`）が持ち続ける。48rem 以上は横並びのまま */
@media not all and (min-width: 48rem) {
  .c-stepper__stages { flex-direction: column; }
  /* 段でない行を段名と見分けられるように（UX Med）: ⑴ 印の無い段（未着手・キャンセル）にも印と同じ幅の空きを置き、
     段名の文字の左端をそろえる ⑵ 「記録する欄がありません」は段名の文字の左端まで字下げ（印 spacing × 2 ＋ 間 spacing × 1）
     ⑶ 集計（「n/5 完了」）の前に段1つ分ほどの間。**段名を出さない契約カードの集計は動かさない**（`__stages +` に限る） */
  .c-stepper__stage:not([data-recorded])::before {
    content: "";
    display: inline-block;
    width: calc(var(--spacing) * 2);
    margin-right: calc(var(--spacing) * 1);
  }
  .c-stepper__no-column { padding-left: calc(var(--spacing) * 3); }
  .c-stepper__stages + .c-stepper__caption { margin-top: calc(var(--spacing) * 3); }
}
.c-stepper__stage[data-state="warn"] { color: var(--color-danger-fg); }
/* **キャンセル側の2段は段名の行でも描き分ける**（2026-09-17 の a11y レビュー Low）。
 * 棒（`__seg--cxlreq` / `__seg--cxl` ＋ `.stripe-cxl`）は3つを描き分けているのに、
 * 段名の行は `cxlreq` も `cxl` も `todo` も同じ見た目で、**情報が落ちていた**。
 * 申請中は棒と同じ色（申込ステータスのチップと同じ `--color-entry-cxlreq-fg`。新しい色を作らない）、
 * 確定は**取り消し線** ＝ 棒に重ねる斜線（`.stripe-cxl`）の文字版である。 */
.c-stepper__stage[data-state="cxlreq"] { color: var(--color-entry-cxlreq-fg); }
.c-stepper__stage[data-state="cxl"] { text-decoration: line-through; }
/* **その段の記録があるか**を段名の頭の印でも描く（同じ Y-8）。**塗り ＝ 記録あり／白抜き ＝ 記録なし**で、
 * **色は当てない**（`currentColor` ＝ 段の状態が既に持っている色をそのまま使う。§10 は**形**が担う）。
 * **`content: ""` の擬似要素**なので読み上げには乗らない —— 語は同じ `<li>` の `sr-only`
 * （`（完了・記録なし）`）が持ち、**二重に読まれない**。
 * **印が描けない段（キャンセル ＝ Y-5 未決・再現中）には `data-recorded` が付かない**ので、印も出ない。 */
.c-stepper__stage[data-recorded]::before {
  content: "";
  display: inline-block;
  width: calc(var(--spacing) * 2);
  height: calc(var(--spacing) * 2);
  margin-right: calc(var(--spacing) * 1);
  border-radius: var(--radius-sm); /* 8px の正方形なので丸になる */
  vertical-align: middle;
}
.c-stepper__stage[data-recorded="yes"]::before { background-color: currentColor; }
/* 白抜き（記録なし）。`box-sizing: border-box`（base.css）なので外寸は塗りと同じ。
 * **枠の太さは `--stripe-w`（2px）** —— 棒の縞と同じ幅で、`calc(var(--spacing) * 0.5)` は使わない
 * （`.claude/rules/ui-tokens.md` の端数の許しは**コントロールの寸法**に限られ、擬似要素の印は当たらない）。 */
.c-stepper__stage[data-recorded="no"]::before {
  border: var(--stripe-w) solid currentColor;
}
/* **記録する欄がそもそも無い**ことを言う語（段名の直下）。**印ではない** ——
 * 見た目の語彙は塗り／白抜きの2つのままで、ここは**語**が足りない分を埋める
 * （2026-09-17 の UX レビュー Med。読み上げにしか無く、晴眼の人には1文字も届いていなかった）。
 * **段名より従属**させる（`--color-text-muted`。大きさは親の `--text-2xs` を継ぐ）。
 * **システム全体で工事日確定の1段だけ**に出るので、常駐の説明文にはならない。 */
.c-stepper__no-column {
  display: block;
  color: var(--color-text-muted);
  font-weight: 400;
}
.c-stepper__caption {
  font-size: var(--text-2xs);
  color: var(--color-text-muted);
}
.c-stepper__exceptions {
  margin-left: calc(var(--spacing) * 2);
  font-weight: 600;
  color: var(--color-warning-fg);
}


/* ============================================================================
 * KeyValueList ／ KeyValue（web/components/crm/key-value.tsx）
 * ========================================================================== */
.c-kv {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: calc(var(--spacing) * 2) calc(var(--spacing) * 4);
  font-size: var(--text-sm);
}
.c-kv--cols-1 {
  grid-template-columns: repeat(1, minmax(0, 1fr));
}
.c-kv__item {
  display: flex;
  gap: calc(var(--spacing) * 2);
}
.c-kv__item--wide {
  grid-column: 1 / -1;
}
.c-kv__label {
  flex-shrink: 0;
  width: calc(var(--spacing) * 24); /* sm = 96px（項目名が短い） */
  color: var(--color-text-muted);
}
.c-kv--label-md .c-kv__label {
  width: calc(var(--spacing) * 32); /* md = 128px（「エントリー完了日」など長い） */
}
.c-kv__value {
  flex: 1 1 0%;
  min-width: 0;
  font-weight: 600;
  overflow-wrap: break-word;
}
.c-kv__value--warning { color: var(--color-warning-fg); }
.c-kv__value--danger  { color: var(--color-danger-fg); }
/* 値が空 → 「—」。tone は効かせない（空に警告色を付けない） */
.c-kv__value--empty,
.c-kv__value--empty.c-kv__value--warning,
.c-kv__value--empty.c-kv__value--danger {
  font-weight: 400;
  color: var(--color-text-muted);
}
/* 48rem 未満は1列（`--cols-1` と同じ）にし、項目名は左に置いたまま幅だけ縮める。固定幅（96px / 128px）のままだと
   値の欄が 10〜27px まで細っていた（契約詳細・取込1回の結果・AI利用額。U-1 第2弾）。長い項目名は折り返す。
   `--label-md` の宣言（2クラス）にも勝つよう同じ詳細度で書く。**KeyValue の修飾はこれより前に書く** */
@media not all and (min-width: 48rem) {
  .c-kv {
    grid-template-columns: minmax(0, 1fr);
  }
  .c-kv__label,
  .c-kv--label-md .c-kv__label {
    width: var(--width-kv-label-narrow);
  }
}


/* ============================================================================
 * Timeline ／ TimelineItem（web/components/crm/timeline.tsx）
 * ========================================================================== */
.c-timeline {
  display: flex;
  flex-direction: column;
  font-size: var(--text-sm);
}
/* 監査ログ。件数が多く読み流す前提なので1段細く */
.c-timeline--audit {
  font-size: var(--text-xs);
}
.c-timeline__item {
  display: flex;
  gap: calc(var(--spacing) * 3);
  border-bottom: var(--border-w) solid var(--border);
  padding-block: calc(var(--spacing) * 2);
}
.c-timeline__item:last-child {
  border-bottom-width: 0;
}
.c-timeline__date {
  flex-shrink: 0;
  width: calc(var(--spacing) * 24);
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  color: var(--color-text-muted);
}
.c-timeline__who {
  flex-shrink: 0;
  width: calc(var(--spacing) * 16);
  font-weight: 600;
  color: var(--primary);
}
.c-timeline__body {
  flex: 1 1 0%;
  min-width: 0;
  overflow-wrap: break-word;
}
/* 名寄せ由来の記録（§11） */
.c-timeline__item--ai .c-timeline__body {
  font-weight: 600;
  color: var(--color-ai-fg);
}


/* ============================================================================
 * Pagination（web/components/crm/pagination.tsx）
 * ========================================================================== */
.c-pagination {
  display: flex;
  /* 幅が足りなければ折り返す（出すページ番号の数は変えない。U-1 第2弾） */
  flex-wrap: wrap;
  justify-content: center;
  gap: calc(var(--spacing) * 1.5);
  margin-top: calc(var(--spacing) * 4);
}
.c-pagination__cell {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: calc(var(--spacing) * 7);
  height: calc(var(--spacing) * 7);
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  padding-inline: calc(var(--spacing) * 2);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
a.c-pagination__cell:hover {
  border-color: var(--primary);
  color: var(--primary);
}
/* 端で押せない ‹ › */
.c-pagination__cell--disabled {
  color: var(--color-text-disabled);
}
/* 省略の「…」 */
.c-pagination__cell--gap {
  border-color: transparent;
}
.c-pagination__cell[aria-current="page"],
.c-pagination__cell[aria-current="page"]:hover {
  border-color: var(--primary);
  background-color: var(--primary);
  font-weight: 700;
  color: var(--color-white);
}


/* ============================================================================
 * Popover（web/components/layout/topbar.tsx の Popover を <details> 基盤で）
 *
 *   <details class="c-popover" data-popover>
 *     <summary class="c-popover__trigger" aria-label="このシステムの使い方">…</summary>
 *     <div class="c-popover__panel">
 *       <h2 class="c-popover__title">このシステムの使い方</h2>
 *       <div class="c-popover__footer">…</div>
 *
 * **パネルに `role="dialog"` を付けない**（2026-10-04・a11y レビュー Low）。振る舞いは開閉（Disclosure）で、
 * 焦点を閉じ込めず、開いても焦点は summary に残る。dialog を名乗ると、読み上げが対話の箱に入ったと告げて食い違う。
 * 開閉の状態は `<details>` / `<summary>` が素で伝える。
 *
 * 開閉は <details> が持つ（JS なしでも開ける）。Esc で閉じてフォーカスを summary へ戻す・
 * 外側を押すと閉じる、は popover.js。
 * いま使うのはトップバーのヘルプと、48rem 未満で出る「…」メニュー（`l-topbar__menu`。U-1 第1弾・2026-09-30）、
 * **通知（ベル。2026-10-03 に戻した）**、それに見本（`/design`）。2026-09-30 に通知の Popover を消して一覧の行の CSS も
 * 消したが、**出所（`notifications.Notification`）ができたので一覧の行 `__list` / `__item`・補足 `__muted`・空 `__empty` を戻し、
 * 島が出す1文 `__note` を足した**（2026-10-03）。本文 `__body` は戻していない（呼び手が無い）。
 * **48rem 未満でトップバーの直下に全幅で出す配置は部品ではなくシェルが持つ**（`layout.css` の
 * `.l-topbar .c-popover__panel`）—— 本文の中に置いた Popover まで飛ばさないため。
 * ========================================================================== */
.c-popover {
  position: relative;
}
.c-popover__trigger {
  display: flex;
  align-items: center;
  justify-content: center;
  width: calc(var(--spacing) * 7);
  height: calc(var(--spacing) * 7);
  border-radius: var(--radius-md);
  color: var(--color-text-muted);
  list-style: none;
}
.c-popover__trigger::-webkit-details-marker {
  display: none;
}
.c-popover__trigger:hover {
  background-color: var(--color-gray-100);
  color: var(--color-text);
}
.c-popover__trigger svg {
  width: calc(var(--spacing) * 4);
  height: calc(var(--spacing) * 4);
}
.c-popover__panel {
  position: absolute;
  top: calc(var(--spacing) * 8);
  right: 0;
  z-index: 40;
  width: var(--popover-w);
  overflow: hidden;
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
  box-shadow: var(--shadow-3);
}
.c-popover__title {
  border-bottom: var(--border-w) solid var(--border);
  background-color: var(--color-gray-50);
  padding: calc(var(--spacing) * 2) calc(var(--spacing) * 4);
  font-size: var(--text-sm);
  font-weight: 600;
}
.c-popover__footer {
  border-top: var(--border-w) solid var(--border);
  padding: calc(var(--spacing) * 3);
}
/* ---- バリアント `--list`: 一覧を持つパネル（通知のベル。2026-10-04）--------------------------------
   **パネルを画面の高さに収め、一覧だけを縦に送る。** 見出し・新着の1文・足元の操作は常に見える。
   以前は8件で約970px になり、1280×800 で足元（すべて既読にする・通知をすべて見る）が画面の外へ出ていた。
   48rem 未満の配置（トップバーの直下に全幅）は `layout.css` の `.l-topbar .c-popover__panel--list` が持つ */
.c-popover__panel--list {
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - var(--topbar-h) - var(--spacing) * 4);
}
.c-popover__panel--list > * {
  flex-shrink: 0;
}
.c-popover__panel--list > .c-popover__list {
  flex-shrink: 1;
  min-height: 0;
  overflow-y: auto;
}
/* ---- 一覧の行（通知。2026-10-03 に戻した）。**件数は呼ぶ側が絞る**（ベルは新しい8件 ＝ `notifications_present.BELL_LIMIT`） ---- */
.c-popover__list > li {
  border-bottom: var(--border-w) solid var(--border);
}
.c-popover__list > li:last-child {
  border-bottom-width: 0;
}
/* 1件は2行（2026-10-04）: ⑴ 件名と「未読 ・ 時刻」 ⑵ 本文を1行で切る。**切るのは見た目だけ**（リンクの名前には全文が入る。
   全文は一覧の画面 `/notifications` にも出る） */
.c-popover__item {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 1);
  padding: calc(var(--spacing) * 2) calc(var(--spacing) * 3);
  font-size: var(--text-sm);
}
.c-popover__item-head {
  display: flex;
  align-items: baseline;
  gap: calc(var(--spacing) * 2);
}
.c-popover__item-head > .c-popover__item-title {
  flex: 1;
  min-width: 0;
}
.c-popover__item-head > .c-popover__muted {
  flex-shrink: 0;
}
.c-popover__item-body {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--color-text-muted);
}
a.c-popover__item:hover {
  background-color: var(--color-gray-50);
}
/* 行の見出し。**未読は太く**（字の補い。未読であることは補足の行の語「未読」が言う ＝ §10） */
.c-popover__item-title {
  display: block;
  font-weight: 400;
}
.c-popover__item[data-unread="true"] .c-popover__item-title {
  font-weight: 600;
}
.c-popover__muted {
  color: var(--color-text-muted);
}
.c-popover__empty,
.c-popover__note {
  padding: calc(var(--spacing) * 3) calc(var(--spacing) * 4);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
/* 島が「新しい通知が届いた」と出す1文。**開いたときの一覧は古いまま**なので、一覧の上に区切って出す */
.c-popover__note {
  border-bottom: var(--border-w) solid var(--border);
  background-color: var(--color-gray-50);
  color: var(--color-text);
}
/* 足元の操作（すべて既読・すべて見る・設定）を1行に並べ、足りなければ折り返す */
.c-popover__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--spacing) * 2);
}

/* 重大度の点。**色だけで意味を伝えない**ので、語（sr-only など）を必ず添える */
.c-dot {
  flex-shrink: 0;
  width: calc(var(--spacing) * 2);
  height: calc(var(--spacing) * 2);
  margin-top: calc(var(--spacing) * 1);
  border-radius: var(--radius-sm);
  background-color: var(--color-gray-400);
}
/* 1行の文と中心を揃えて並べる点（ダッシュボードのリンクの行）。既定は複数行の文の1行目に揃える上余白を持つ */
.c-dot--centered { margin-top: 0; }
.c-dot--danger  { background-color: var(--color-danger-fg); }
.c-dot--warning { background-color: var(--color-warning-fg); }
.c-dot--info    { background-color: var(--color-info-fg); }
.c-dot--ai      { background-color: var(--color-ai-fg); }


/* ============================================================================
 * Input ／ Label ／ Select ／ Checkbox（web/components/ui/{input,label}.tsx・search-panel.tsx）
 * ラベルは項目の上。必須・任意を両方明示する（.claude/rules/forms.md）
 * ========================================================================== */
.c-field {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 1);
}
.c-label {
  display: flex;
  align-items: center;
  gap: calc(var(--spacing) * 2);
  font-size: var(--text-sm);
  font-weight: 500; /* Tailwind 版 `font-medium`。§5-C とのずれは報告済み */
  line-height: 1;
  user-select: none;
}
.c-label__required {
  font-size: var(--text-2xs);
  color: var(--color-danger-fg);
}
.c-label__optional {
  font-size: var(--text-2xs);
  color: var(--color-text-muted);
}
/* 錠（代理店のシートが正である間は編集できない欄・2026-09-20）。**必須・任意の位置に置き換わる。**
   **色は意味を持つときだけ**（§2）—— これは失敗でも危険でもないので、注意の色を当てず、
   面だけを一段だけ起こして「印である」ことを示す（欄そのものは `.c-input[readonly]` の面で描かれる）。 */
.c-label__locked {
  font-size: var(--text-2xs);
  color: var(--color-text-muted);
  background-color: var(--color-gray-100);
  border-radius: var(--radius-sm);
  padding: 0 calc(var(--spacing) * 1);
}
/* 欄のまとまり（ラジオ・チェックボックスの fieldset）。枠と余白を消し、格子の中で縮めるようにする（2026-09-16） */
fieldset.c-field {
  margin: 0;
  border: 0;
  padding: 0;
  min-width: 0;
}
legend.c-label { padding: 0; margin-bottom: calc(var(--spacing) * 1); }
/* 欄の縦並び（flex の column）の中でも、ラジオの切替は中身の幅のまま（行いっぱいに伸ばさない） */
.c-field > .c-segmented { align-self: flex-start; }
/* チェックボックスの並び（見込み商材。2026-09-16） */
.c-field__options {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--spacing) * 2) calc(var(--spacing) * 4);
}
.c-field__option {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--spacing) * 1.5);
  font-size: var(--text-sm);
}
/* 欄の中の読む行（入力欄のすぐ下・ヒントの上。「この申込のFV番号: …」・2026-10-08・Issue #424 PR③b）。
   **値なので本文の色**（ヒントの muted にしない）。字の大きさは入力欄の値と同じ段 */
.c-field__lead {
  font-size: var(--text-sm);
  color: var(--color-text);
}
.c-field__hint {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
.c-field__error {
  font-size: var(--text-xs);
  color: var(--color-danger-fg);
}

.c-input {
  width: 100%;
  min-width: 0;
  height: var(--control-h-compact);
  border: var(--border-w) solid var(--input);
  border-radius: var(--radius-md);
  background-color: transparent;
  padding: calc(var(--spacing) * 1) calc(var(--spacing) * 2.5);
  font-size: var(--text-base);
  transition-property: color, background-color, border-color, outline-color;
  transition-timing-function: var(--ease-standard);
  transition-duration: var(--duration-colors);
}
/* Tailwind 版は `text-base md:text-sm`。48rem 以上では 12px になる */
@media (min-width: 48rem) {
  .c-input { font-size: var(--text-sm); }
}
/* 複数行（備考・商談記録の内容。2026-09-16）。高さは中身と rows に任せ、縦だけ伸縮できる */
.c-input--multiline {
  height: auto;
  min-height: calc(var(--spacing) * 16);
  padding-block: calc(var(--spacing) * 2);
  line-height: 1.6;
  resize: vertical;
}
/* ファイル選択（CSV取込。2026-09-17）。ブラウザ既定のボタンが欄の中に入るので、
   高さは中身なりにする（--control-h-compact のままだと OS によってボタンが切れる） */
.c-input--file {
  height: auto;
  padding-block: calc(var(--spacing) * 2);
  font-size: var(--text-sm);
}
/* 読み取り専用（権限が無い）。値は読める（opacity で薄めない・§10）。面だけ変えて入力できないことを伝える。
   **セレクタは `[readonly]` 属性で書く**（2026-09-17・a11y M2）—— `:read-only` 擬似クラスは
   HTML の仕様で `input[type=file]` にも一致するので、`c-input--file`（CSV取込の**編集できる**欄）が
   「権限が無くて入力できない」面で描かれていた。属性で見れば、実際に `readonly` を付けた欄だけに当たる。 */
.c-input[readonly] {
  background-color: var(--color-gray-50);
}
/* 1行に他の欄と並べる入力（詳細条件の値。幅は中身なり・字は常に sm） */
.c-input--inline {
  width: auto;
  font-size: var(--text-sm);
}
.c-input::placeholder {
  color: var(--color-text-placeholder);
}
.c-input:focus-visible,
.c-select:focus-visible {
  border-color: var(--ring);
  box-shadow: 0 0 0 var(--ring-w) color-mix(in oklab, var(--ring) 50%, transparent);
}
/* ネイティブの `disabled`（readonly を持てない欄だけ。file / checkbox）。
   **`opacity` で薄めない**（§10。gray-900 の 50% は白背景で AA 4.5:1 を割る）——
   2026-09-17 に `opacity: 0.5` を文字色に替えた（a11y M4）。面と文字色だけで「触れない」を伝える。 */
.c-input:disabled {
  pointer-events: none;
  cursor: not-allowed;
  background-color: var(--color-gray-50);
  color: var(--color-text-muted);
}
/* 入力の誤り。aria-invalid="true" を付けると枠が赤くなる（色だけでなく近くに文を出す・forms.md） */
.c-input[aria-invalid="true"],
.c-select[aria-invalid="true"] {
  border-color: var(--destructive);
  box-shadow: 0 0 0 var(--ring-w) color-mix(in oklab, var(--destructive) 20%, transparent);
}

.c-select {
  height: var(--control-h-compact);
  border: var(--border-w) solid var(--color-border-input);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  padding-inline: calc(var(--spacing) * 2);
  font-size: var(--text-sm);
}

/* ============================================================================
 * Combobox（`webui/components/combobox.html` ＋ 島 `combobox.js`。2026-10-02・DESIGN §4-B）
 *   検索語の欄＋「探す」＋候補の listbox＋選んだ姿＋JS 無しのラジオ。**JS が無ければ listbox は出ない**（`hidden` のまま）。
 *   状態は属性で持つ: 開閉 ＝ listbox の `hidden`／矢印で指す候補 ＝ `aria-selected="true"`／読込中 ＝ listbox の `aria-busy`／
 *   ④ ＝ 件数の文の `data-tone="error"`。
 *   **候補1行は 48rem 以上で4列の格子**（名前・番号・電話・市区町村が候補をまたいで揃う）、**48rem 未満はセル単位で折り返す**
 *   （語の途中で折らない ＝「電／話」にしない。2026-10-02 のレビュー a11y Low）。
 * ========================================================================== */
.c-combobox,
.c-combobox__selected,
.c-combobox__search {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 1);
}
/* `display: flex` は `hidden` 属性の既定（display: none）に勝つので、明示して戻す */
.c-combobox__selected[hidden],
.c-combobox__search[hidden] { display: none; }
/* 欄の名前と件数の文を1行に（件数は候補の listbox に隠れない位置 ＝ 欄の上） */
.c-combobox__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: calc(var(--spacing) * 1) calc(var(--spacing) * 3);
}
/* 件数・0件・短い・失敗の文（`role="status"`）。**空でも場所を描く**（読み上げの器を消さない） */
.c-combobox__status {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
.c-combobox__status[data-tone="error"] { color: var(--color-danger-fg); }
/* 欄と「探す」の行。listbox はこの行の幅いっぱいに、欄の真下へ重ねる（下の欄を押し下げない ＝ 位置が飛ばない） */
.c-combobox__row {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: calc(var(--spacing) * 2);
}
.c-combobox__input { flex: 1 1 auto; }
.c-combobox__listbox {
  position: absolute;
  top: calc(100% + var(--spacing) * 1);
  left: 0;
  right: 0;
  z-index: 40;
  margin: 0;
  padding: calc(var(--spacing) * 1) 0;
  list-style: none;
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  box-shadow: var(--shadow-3);
}
.c-combobox__option {
  padding: calc(var(--spacing) * 2) calc(var(--spacing) * 3);
  font-size: var(--text-sm);
  cursor: pointer;
}
/* ホバー（指の位置）と矢印で指す候補は**別の見え方**にする（2026-10-02 のレビュー a11y Low）。
   指す候補は主色の淡い面＋左の罫（色だけにしない）、ホバーは灰の面だけ */
.c-combobox__option:hover {
  background-color: var(--color-gray-100);
}
.c-combobox__option[aria-selected="true"] {
  background-color: var(--color-primary-soft);
  box-shadow: inset var(--ring-w) 0 0 var(--color-focus);
}
/* 候補1行の中身（名前｜番号｜電話の下4桁｜市区町村）。48rem 未満はセル単位で折り返す */
.c-combobox__cells {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: calc(var(--spacing) * 1);
}
.c-combobox__cell { white-space: nowrap; }
.c-combobox__cell--main { font-weight: 600; white-space: normal; }
.c-combobox__sep { color: var(--color-text-muted); }
@media (min-width: 48rem) {
  /* 4列の格子（区切りの記号は格子の線の代わりに要らない）。listbox・ラジオ・選んだ姿で同じ列 */
  /* **列の数はセルの数に追従する**（`grid-auto-flow: column`。呼び手がセルを増減しても列がずれない）。
     先頭（名前）だけ広く、残りは同じ幅。区切りの記号は display: none なので列を取らない */
  .c-combobox__option .c-combobox__cells,
  .c-combobox__candidate .c-combobox__cells {
    display: grid;
    grid-auto-flow: column;
    grid-template-columns: minmax(0, 3fr);
    grid-auto-columns: minmax(0, 2fr);
    column-gap: calc(var(--spacing) * 3);
    width: 100%;
  }
  .c-combobox__option .c-combobox__sep,
  .c-combobox__candidate .c-combobox__sep { display: none; }
}
/* 選んだ1件と「選び直す」。欄の高さにそろえる */
.c-combobox__chosen {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--spacing) * 3);
  min-height: var(--control-h-compact);
}
.c-combobox__value { font-size: var(--text-sm); }
/* JS が無いときの候補（ラジオ）。1人1行で積む。ラジオはネイティブのまま、面の色だけ主色に寄せる */
.c-combobox__candidates {
  gap: calc(var(--spacing) * 2);
  margin-top: calc(var(--spacing) * 2);
}
.c-combobox__candidate {
  display: flex;
  align-items: center;
  gap: calc(var(--spacing) * 2);
  font-size: var(--text-sm);
}
.c-combobox__radio {
  flex-shrink: 0;
  width: calc(var(--spacing) * 4);
  height: calc(var(--spacing) * 4);
  accent-color: var(--primary);
}

/* チェックボックスはネイティブのまま。面の色だけを主色に寄せる。
   縦に積むラジオ（`c-radio`。要確認顧客の判断の3択。2026-10-05）も同じ宣言 —— ネイティブのまま、面の色だけを主色に寄せる
   （宣言は写さずセレクタを並べる）。2〜3択を1行に並べる切替は `c-segmented`（別の部品）で、
   こちらは選択肢ごとに補足の1文を持つ縦の並びに使う */
.c-checkbox,
.c-radio {
  flex-shrink: 0;
  width: calc(var(--spacing) * 4);
  height: calc(var(--spacing) * 4);
  accent-color: var(--primary);
}


/* ============================================================================
 * 注記
 *
 *   c-state-note  … 状態を再現中であることの注記（StateSwitcher の note）
 *   （c-sample-note〈「顧客DBの内容ではない」の印〉と c-dummy-note〈「開発用のダミー」の告知〉は
 *     2026-09-30 に部品ごと消した）
 * ========================================================================== */


/* ============================================================================
 * CustomerId（`webui/components/customer_id.html`。顧客を名乗る字「顧客ID n」。変種は無い）
 *
 * **語「顧客ID」と番号の間で折らない**（2026-10-21・Issue #636）。全部の呼び手で同じ性質で、呼び手は包まない。
 * 包むのは語と番号だけ —— 部品の外（前置き）との間と、括弧の FV番号（`.c-customer-id` の外）の前では折れてよい。
 * ========================================================================== */
.c-customer-id {
  white-space: nowrap;
}


/* ============================================================================
 * StateSwitcher（web/components/crm/state-switcher.tsx）。**開発用**。DEBUG のときだけ描く
 * ========================================================================== */
.c-state-switcher {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--spacing) * 2);
}
.c-state-switcher__label,
.c-state-note {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
.c-state-switcher__link {
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius-sm);
  padding: calc(var(--spacing) * 1) calc(var(--spacing) * 2);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
.c-state-switcher__link:hover {
  background-color: var(--color-gray-100);
}
/* 6状態の列は aria-current="page"、別軸（⑥閲覧・__masters 等）は aria-current="true" */
.c-state-switcher__link:is([aria-current="page"], [aria-current="true"]),
.c-state-switcher__link:is([aria-current="page"], [aria-current="true"]):hover {
  /* Tailwind 版の選択中は枠線を持たない（border クラスが無い）。枠の 1px ぶん小さくなる点も含めて移した */
  border-width: 0;
  background-color: var(--primary);
  font-weight: 600;
  color: var(--color-white);
}


/* ============================================================================
 * Alert（web/app/login/login-form.tsx の `role="alert"` の枠）
 * ========================================================================== */
.c-alert {
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius-md);
  background-color: var(--color-gray-50);
  padding: calc(var(--spacing) * 2) calc(var(--spacing) * 3);
  font-size: var(--text-sm);
}
.c-alert--danger {
  border-color: var(--color-danger-border);
  background-color: var(--color-danger-bg);
  color: var(--color-danger-fg);
}
/* **2026-09-17 追加**（W-5 / 判断モック D01）。申込ステータスの「確認が必要」——
   **失敗ではない**（保存は通っている）が、放っておくと古い段のまま運用される。
   `--danger` と同じ強さで出すと、保存に失敗したかのように読める。 */
.c-alert--caution {
  border-color: var(--color-warning-border);
  background-color: var(--color-warning-bg);
  color: var(--color-warning-fg);
}
/* **2026-10-11 追加**（ユーザー作成の2段目の枝の帯・「すでにこの組織に居る」の答え）。
   **失敗でも注意でもない**、いまどの枝に居るかの知らせ。既定（灰）の面は結果の文と同じで読み飛ばされ、
   `--caution` だと「放っておけない」に読める。色は情報のトークン（`--color-info-*`）だけ。
   **枠線だけで意味を運ばない** —— `--color-info-border` は面との差が小さい（`.c-ai-panel__confidence` の注記の実測）ので、
   意味は文と面の色が持つ（色だけにも頼らない ＝ §10。帯の1行目の文が枝を言う） */
.c-alert--info {
  border-color: var(--color-info-border);
  background-color: var(--color-info-bg);
  color: var(--color-info-fg);
}



/* ============================================================================
 * Dialog（モーダル。`webui/components/dialog.html`・JS の島 `dialog.js`。2026-10-01・run lead-dedup の段 CD）
 *
 * **部品は1つ。修飾（`c-dialog--*`）を作らない**（design-briefs/00_共通_モーダル.md §2・DESIGN.md §4-C）。
 * 実体は**ネイティブの `<dialog>`** を `showModal()` で開く。フォーカスの閉じ込め・背景の不活性化・
 * Esc（`cancel`）・top layer はブラウザが持ち、CSS は見た目だけを足す。
 *   <dialog id class="c-dialog" aria-labelledby="ID-title" [aria-describedby="ID-desc"]>
 *     <h2 id="ID-title" class="c-dialog__title">…</h2>
 *     <div class="c-dialog__body">[<p id="ID-desc" class="c-dialog__lead">…</p>] …</div>
 *     <div class="c-dialog__actions" data-dialog-initial="primary|dismiss">やめる／閉じる ＋ 主の操作</div>
 *   </dialog>
 *
 * - 幅は `min(--width-dialog〈560px〉, 100% − spacing×8)`。**48rem 未満は画面下からの全幅のシート**（末尾の @media）
 * - 本文が長いときは **本文（`__body`）だけがスクロールし、見出しと操作の行は常に見える**
 *   （`[open]` で縦の flex にし、`__body` に `min-block-size: 0` と `overflow: auto`。はみ出したときだけ島が器に
 *   `tabindex="0"`・`role="region"` を付ける ＝ キーボードで入れる。scroll-region.js と同じ手当て）
 * - **`overflow` は `visible`**（UA の `dialog:modal { overflow: auto }` を上書き）——
 *   操作の行の押せない操作（`restricted_action.html`）の吹き出しを箱で切らない。はみ出したときは
 *   `restricted-action.js` が画面に固定して置き直す
 * - 幕は `::backdrop` に `--color-scrim`。**押しても閉じない**（JS が幕の押下を拾わない）
 * - **開いている間、背景はスクロールしない**（`html:has(dialog.c-dialog[open])`。JS で状態を持たない）
 * - 開閉のアニメーションは付けない（§1・§8）。z-index は要らない（top layer に出る）
 * ========================================================================== */
.c-dialog {
  width: min(var(--width-dialog), 100% - calc(var(--spacing) * 8));
  max-width: 100%;
  /* 上下の余白ぶんを引く。`dvh` はビューポートそのもの（`scripts/check_webui_tokens.py` が規則で許す） */
  max-block-size: calc(100dvh - calc(var(--spacing) * 16));
  /* base.css のリセット（`* { margin: 0 }`）が UA の `dialog { margin: auto }` に勝つので、中央に置く margin を戻す */
  margin: auto;
  padding: 0;
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
  color: var(--color-text);
  box-shadow: var(--shadow-4);
  overflow: visible;
}
/* 閉じたときの `display: none`（UA）を壊さないため、flex は開いている間だけ */
.c-dialog[open] {
  display: flex;
  flex-direction: column;
}
.c-dialog::backdrop {
  background-color: var(--color-scrim);
}
.c-dialog__title {
  flex: none;
  padding: calc(var(--spacing) * 4) calc(var(--spacing) * 4) calc(var(--spacing) * 2);
  font-size: var(--text-lg);
  font-weight: 600;
  line-height: var(--leading-head);
}
.c-dialog__body {
  flex: 1 1 auto;
  min-block-size: 0;
  overflow: auto;
  padding: 0 calc(var(--spacing) * 4) calc(var(--spacing) * 3);
  font-size: var(--text-base);
  line-height: var(--leading-body);
}
/* 導入の1文（`lead`。`aria-describedby` の結び先）。本文の先頭に置く */
.c-dialog__lead {
  margin-bottom: calc(var(--spacing) * 2);
}
/* 操作の行。DOM の順は やめる／閉じる → 主の操作（右寄せなので主の操作が右端 ＝ 新城が確かめた見本 mockups.html と同じ。
   2026-10-01 のレビューで「主 → やめる」から改めた）。
   **`overflow` を付けない**（押せない操作の吹き出しを切らない） */
.c-dialog__actions {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: calc(var(--spacing) * 2);
  border-top: var(--border-w) solid var(--border);
  padding: calc(var(--spacing) * 3) calc(var(--spacing) * 4);
}
/* 開いている間、背景はスクロールしない（背景は `inert` なので、位置だけを止める）。
   古典的なスクロールバー（Windows・Linux）では `overflow: hidden` でバーが消えて背景が横に動くので、
   `scrollbar-gutter: stable` で幅を残す（仕様上は overflow が hidden でも溝を残す）。
   **mac の headless は overlay で、この手当ての効き目は手元で実測できていない**（`::-webkit-scrollbar` で作った
   擬似的なバーでは動いた ＝ 2026-10-01）。受け入れた不利益: スクロールしない短い画面では、開いている間だけ溝が出る */
html:has(dialog.c-dialog[open]) {
  overflow: hidden;
  scrollbar-gutter: stable;
}
/* 48rem 未満は画面下からの全幅のシート（U-1 と同じ境目。書き方は layout.css 冒頭の約束） */
@media not all and (min-width: 48rem) {
  .c-dialog {
    width: 100%;
    max-block-size: calc(100dvh - calc(var(--spacing) * 8));
    margin-block: auto 0;
    margin-inline: 0;
    border-width: var(--border-w) 0 0;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  }
}
/* 読み取りだけの受け皿（`open_label`）。開閉の実体 <summary> は button.html で描けないので見た目だけ c-button を当てる
   （§4-B1 の Button の行の先例）。JS が読み込まれると <details> は隠れ、同じ文の起動ボタンが出る */
.c-dialog__summary {
  list-style: none;
}
.c-dialog__summary::-webkit-details-marker {
  display: none;
}
.c-dialog__details-body {
  margin-top: calc(var(--spacing) * 3);
  font-size: var(--text-base);
}
