/* ============================================================================
 * FVJAPAN CRM — レイアウト（アプリシェル・ページの骨格・グリッド）
 *
 * 命名: `l-` 接頭辞（layout）。部品は components.css の `c-`。
 * 出典: web/components/layout/{app-shell,sidebar,topbar}.tsx と各 page.tsx の Tailwind クラス。
 * 寸法は docs/DESIGN.md §6（--sidebar-w 216px / --topbar-h 52px / --popover-w 320px）。
 *
 * **ブレークポイントだけは変数にできない**（CSS 変数は @media の条件に使えない）。
 * Tailwind v4 の既定値をそのまま rem で書く: sm = 40rem / md = 48rem / xl = 80rem。
 * 16px 基準で 640 / 768 / 1280px にあたる。xl が docs/DESIGN.md §6 の「最小想定幅 1280px」と同じ値である。
 * **未満の側は `@media not all and (min-width: 48rem)` と書く**（`(width < 48rem)` の範囲構文は iOS Safari 16.4 未満が
 * 解さず、ブロックごと捨てられる。`not all and (min-width: …)` は同じ幅の**ちょうど裏**になり、境目で両方が効く・
 * 両方が外れる幅が無い）。
 * ========================================================================== */

/* ---- アプリシェル（AppShell）--------------------------------------------- */
.l-shell {
  position: relative;
  display: flex;
  min-height: 100vh;
}

/* サイドバー（Sidebar）。幅は --sidebar-w。スクロールしても残る */
.l-sidebar {
  position: sticky;
  top: 0;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  width: var(--sidebar-w);
  height: 100vh;
  border-right: var(--border-w) solid var(--border);
  background-color: var(--color-surface);
}

.l-sidebar__brand {
  display: block;
  border-bottom: var(--border-w) solid var(--border);
  padding: calc(var(--spacing) * 4);
}
.l-sidebar__brand:hover {
  background-color: var(--color-gray-50);
}
.l-sidebar__brand-name {
  display: block;
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--color-teal-900);
}
.l-sidebar__brand-name-sub {
  color: var(--color-text);
}
.l-sidebar__brand-caption {
  display: block;
  font-size: var(--text-2xs);
  color: var(--color-text-muted);
}

/* ナビ（`_shell_nav.html`）。**`l-sidebar__nav` / `__link` / `__icon` / `__badge` はサイドバーと、
   48rem 未満のトップバーの「…」メニューの中とで同じクラスを共有する**（markup は1枚を2か所で include）。
   片方だけ変えたいときは `.l-sidebar …` / `.l-topbar__menu …` で絞る */
.l-sidebar__nav {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 1);
  padding: calc(var(--spacing) * 2);
}

/* ナビ項目。現在地はサーバーがパスを見て aria-current="page" を付ける（e2e の DOM 契約） */
.l-sidebar__link {
  display: flex;
  align-items: center;
  gap: calc(var(--spacing) * 3);
  border-radius: var(--radius-md);
  padding: calc(var(--spacing) * 2) calc(var(--spacing) * 3);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--color-text-muted);
}
.l-sidebar__link:hover {
  background-color: var(--color-gray-100);
  color: var(--color-text);
}
.l-sidebar__link[aria-current="page"] {
  background-color: var(--color-primary-soft);
  color: var(--color-teal-900);
}
.l-sidebar__icon {
  flex-shrink: 0;
  width: calc(var(--spacing) * 4);
  height: calc(var(--spacing) * 4);
  color: var(--color-accent-nontext);
}
.l-sidebar__link-note {
  margin-left: calc(var(--spacing) * 1);
  font-size: var(--text-2xs);
  font-weight: 400;
}
.l-sidebar__badge {
  margin-left: auto;
}

/* 見出し（大項目）ごとの群（2026-10-04）。見出しは `<p>`、群は `role="group"` ＋ `aria-labelledby`（`_shell_nav.html`）。
   **控えめに**: 小さく・muted・字間を広げるだけ。区切り線は引かない（見出しの上の余白が区切りを担う）。
   形は 2026-09-30 に消した予定の群の見出しを戻した。**ウェイトだけ 700 → 600**（700 は KPI の数値と主 CTA だけ ＝ ui-tokens 規約） */
.l-sidebar__group-label {
  padding: calc(var(--spacing) * 3) calc(var(--spacing) * 3) calc(var(--spacing) * 1);
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  color: var(--color-text-muted);
}
/* 先頭の見出しはブランドの真下なので、上の余白を詰める */
.l-sidebar__group-label:first-child {
  padding-top: calc(var(--spacing) * 1);
}
.l-sidebar__group {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 1);
}
/* 見出しが入って縦に伸びたので、低い画面ではサイドバーのナビの中だけを縦に送る（サイドバーは 100vh で止まっている）。
   48rem 未満の「…」の中は同じクラスを下の @media で別に送っている */
.l-sidebar > .l-sidebar__nav {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* 本文側の列（トップバー＋main） */
.l-shell__body {
  display: flex;
  flex: 1 1 0%;
  flex-direction: column;
  min-width: 0;
}

/* ---- トップバー（Topbar）------------------------------------------------- */
.l-topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: calc(var(--spacing) * 4);
  height: var(--topbar-h);
  border-bottom: var(--border-w) solid var(--border);
  background-color: var(--color-surface);
  padding-inline: calc(var(--spacing) * 6);
}

/* 現在地の束（パンくず＋テナント名の2行目）。**48rem 以上では箱を作らない**ので並びは従来どおり。
   2行目（`__where-tenant`）は 48rem 未満だけ出る（下の @media） */
.l-topbar__where {
  display: contents;
}
.l-topbar__where-tenant {
  display: none;
}

/* 畳む規則は仮置き ＝ V-167（docs/design/open-questions.md。G-3 は未決） */
/* ---- トップバーの並び（#311・2026-10-07）----------------------------------------------
   **どの要素も字の途中で折らない**（以前は幅 1024 でパンくず・テナント名・切替・利用者名が1字ずつ2〜3行に割れていた）。
   ⑴ **縮むのはパンくずだけ**。右の操作の束（`__actions`）は縮まない。パンくずは祖先から先に省略記号で縮み
      （祖先は「›」と「…」1字が入る幅まで）、現在地の画面名は祖先より後まで全文で残る
      （読み上げは全文のまま。全文は項目の `title` でも読める ＝ `base_app.html`）
   ⑵ それでも現在地が切れる・パンくずやバーからはみ出すなら、島 `topbar-fold.js` がバーに `data-account-folded` を立て、
      アカウント欄を操作中テナントの名前と利用者名だけにして、残りを「…」（`__more`）へ移す（下の節）
   ⑶ 畳んでもまだ入りきらなければ、島が `data-crumbs-collapsed` を足し、パンくずを現在地だけにする（48rem 未満と同じ形）。
      それでも入りきらなければ、現在地と、バーに残ったテナント名・利用者名が省略記号で縮む（「…」は画面の中に残る）
   **畳む境目の幅の数はどこにも書かない** —— テナント名・利用者名・パンくずの長さで変わるので、島が実際に収まるかを測る。
   **JS が無いとき（`scripting: none`）はパンくずも縮めない**（下の @media）—— 畳む島が無いのに祖先を縮めると、
   祖先が下限で止まった後に現在地がパンくずの外へ押し出されて見えなくなる（レビュー Med・2026-10-07）。
   字は折れず、入りきらない分はバーの右の外へ出て、頁の横スクロールで届く（§6 の帯の横スクロールの許容）。
   48rem 未満の形（パンくずは現在地だけ・アカウント欄は「メニュー」の中）は下の @media のまま */
.l-breadcrumb {
  min-width: 0;
  overflow: hidden; /* 祖先が下限で止まってもまだ入りきらない一瞬（島が畳む前）に、はみ出た字をヘルプの上に描かない */
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
/* JS が無いとき: パンくずは縮まない（`min-width: auto` ＝ 中身の全幅。切り取りもしない）。バーの外へ出た分は頁の横スクロールで届く */
@media (scripting: none) and (min-width: 48rem) {
  .l-breadcrumb {
    min-width: auto;
    overflow: visible;
  }
}
.l-breadcrumb__list,
.l-breadcrumb__item {
  display: flex;
  align-items: center;
  gap: calc(var(--spacing) * 2);
}
.l-breadcrumb__list {
  min-width: 0;
}
.l-breadcrumb__item > [aria-hidden="true"] {
  flex-shrink: 0;
}
/* 現在地は縮まない（祖先が先に縮む）。パンくずの幅そのものより長いときだけ、その幅で省略記号になる */
.l-breadcrumb__item:last-child {
  flex-shrink: 0;
  max-width: 100%;
}
/* 祖先は「›」と「…」1字が入る幅（spacing × 8）までしか縮まない —— 0 まで縮むと区切りの「›」だけが並んで読めない。
   **下限を明示する**のは、flex の既定の下限（中身の最小幅）が1行で折らない名前の全幅になり、祖先が1px も縮まなくなるため */
.l-breadcrumb__item:not(:last-child) {
  min-width: calc(var(--spacing) * 8);
}
.l-breadcrumb__text,
.l-breadcrumb__current {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-topbar[data-crumbs-collapsed] .l-breadcrumb__item:not(:last-child),
.l-topbar[data-crumbs-collapsed] .l-breadcrumb__item:last-child > [aria-hidden="true"] {
  display: none;
}
.l-breadcrumb__current {
  font-size: var(--text-base);
  font-weight: 700;
  color: var(--color-text);
}

.l-topbar__actions {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: calc(var(--spacing) * 3);
  margin-left: auto;
}
/* アカウント欄（テナント・切替・利用者名・アバター・ログアウト）の束。中身は `_shell_account.html`。
   48rem 未満では束ごと隠れ、「…」メニューの中に同じ部品が出る（下の @media）。
   **間は spacing × 2**（2026-10-14・Issue #172）。切替を `button.html`（ghost・sm）にして左右の余白と枠の約 22px が増え、
   1280px の契約詳細で全角5字の利用者名から操作が「…」へ畳まれるようになった（UX 実機確認 Med）。並ぶ操作の多くは
   ghost のボタンで、字の間は部品の左右の余白（spacing × 2.5）が既に空けているので、束の間を詰めて取り戻す（部品の寸法は変えない） */
.l-topbar__account {
  display: flex;
  align-items: center;
  gap: calc(var(--spacing) * 2);
  white-space: nowrap;
}
/* 「…」メニュー（`<details class="c-popover l-topbar__menu">`）。**48rem 以上では出さない** */
.l-topbar__menu {
  display: none;
}
/* アカウント欄の「…」（`<details class="c-popover l-topbar__more">`・#311）。**畳んだときだけ、48rem 以上でだけ出す**。
   畳んだバーに残すのは操作中テナントの名前（F-61「常に見せる」）と利用者名（名前を変更へのリンク）。
   残りの操作（テナントを切り替え・パスワードを変更・通知の設定・ログアウト）は「…」の中のアカウント欄から選ぶ */
.l-topbar__more {
  display: none;
}
@media (min-width: 48rem) {
  .l-topbar[data-account-folded] .l-topbar__more {
    display: block;
  }
  .l-topbar[data-account-folded] .l-topbar__account .l-topbar__account-row > :not(.l-topbar__tenant, .l-topbar__user-link) {
    display: none;
  }
  /* 畳んでパンくずを現在地だけにしても入りきらない（テナント名・利用者名が長い）ときは、バーに残った2つも省略記号で縮む。
     縮まないと「…」（切替・パスワード・通知の設定・ログアウトへの唯一の入口）が画面の右の外へ出る。
     **パンくずを現在地だけにする段（⑶）の後でだけ縮める** —— 先に縮めると、祖先を消す前にテナント名が切れる。
     全文は読み上げ（字はそのまま DOM にある）で届く。テナント名は `title` でも（`_shell_tenant.html`）、利用者名は行き先の「名前を変更」の画面でも見える */
  .l-topbar[data-crumbs-collapsed] .l-topbar__actions,
  .l-topbar[data-crumbs-collapsed] .l-topbar__account,
  .l-topbar[data-crumbs-collapsed] .l-topbar__user-link {
    flex-shrink: 1;
    min-width: 0;
  }
  .l-topbar[data-crumbs-collapsed] .l-topbar__actions > :not(.l-topbar__account),
  .l-topbar[data-crumbs-collapsed] .l-topbar__avatar {
    flex-shrink: 0;
  }
  .l-topbar[data-crumbs-collapsed] .l-topbar__account .l-topbar__tenant,
  .l-topbar[data-crumbs-collapsed] .l-topbar__account .l-topbar__user {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}
/* 「…」の中は、バーから外した操作だけを縦に1列で並べる（テナント名と利用者名はバーに残っているので出さない）。
   上にナビが無いので区切り線も引かない（48rem 未満の「メニュー」はナビの下に線を引き、テナント行・利用者行の2行で出す） */
.l-topbar__more .l-topbar__menu-account {
  align-items: flex-start;
  border-top: 0;
}
.l-topbar__more .l-topbar__menu-account .l-topbar__account-row {
  display: contents;
}
.l-topbar__more .l-topbar__account-row > :is(.l-topbar__tenant, .l-topbar__user-link) {
  display: none;
}
/* 「…」の中の「テナントを切り替え」も、並ぶ3つと同じ `button.html`（ghost・sm）で描く（`_shell_account.html`。どこでも同じ）。
   **ここにボタンの見た目を書かない**（以前は写していた ＝ 部品の写し・レビュー Med・2026-10-07）。ここで決めるのは左に寄せることだけ
   （下の `.l-topbar__menu-account` の右寄せを打ち消す） */
.l-topbar__more .l-topbar__menu-account :is(.l-topbar__tenant-switch, form) {
  margin-left: 0;
}
/* アカウント欄の中の2行（テナント行・利用者行）。**トップバーでは箱を作らない**（display: contents）ので、
   48rem 以上の並びは束（`.l-topbar__account`）の1行のまま変わらない。「…」メニューの中でだけ行になる（下） */
.l-topbar__account-row {
  display: contents;
}
/* メニューの中のアカウント欄。ナビの下に区切り線を引き、**パネルの下端に置いたまま動かさない**
   （ナビが長く、低い画面 ＝ 320×568 ではパネルに収まらない。欄が下に隠れて気づけない、を防ぐ）。
   `position: sticky` で貼り付けると、Tab で進んだナビの最後の項目が欄の下に潜る（WCAG 2.2 2.4.11）ので、
   **縦に送るのはナビだけ**にし、欄はその下に並べる（下の @media の `.l-topbar__menu > .c-popover__panel`） */
.l-topbar__menu-account {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 1);
  border-top: var(--border-w) solid var(--border);
  background-color: var(--color-surface);
  padding: calc(var(--spacing) * 2);
}
.l-topbar__menu-account .l-topbar__account-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--spacing) * 3);
  padding-left: calc(var(--spacing) * 3);
}
/* メニューの中では「テナントを切り替え」（テナント行）とログアウト（利用者行）を行の右端へ寄せる。
   見た目（色・太さ・hover）はどちらも `button.html`（ghost・sm）が持つ（Issue #172。以前は切替だけここで手書きしていた）。
   切替の高さだけは 48rem 未満の「…」の中で下の例外が上書きする */
.l-topbar__menu-account :is(.l-topbar__tenant-switch, form) {
  margin-left: auto;
}
/* **部品の寸法を上書きする唯一の例外**（DESIGN.md §4-B の Topbar の行に明記・Issue #172・構造レビュー Med の裁定 ⒞）。
   48rem 未満の「…」の中の「テナントを切り替え」だけは、**ナビの行と同じ高さの押しやすい大きさ**にする（U-1 第1弾・2026-09-30 の形を守る）。
   上書きするのは高さと上下の余白だけ —— 部品の sm（28px）の固定の高さを外し、上下の余白をナビの行（`.l-sidebar__link` の spacing × 2）と
   そろえる。色・太さ・hover は部品が持つ。36px の size は `lg` しか無く、§4-A が主 CTA に取っているので使わない。
   ⑶ 48rem 以上で畳んだ「…」（`l-topbar__more`）は並ぶ3つと同じ sm のまま（ここは `.l-topbar__menu` に絞る）。**他で同じ上書きをしない** */
.l-topbar__menu .l-topbar__menu-account .l-topbar__tenant-switch {
  height: auto;
  padding-block: calc(var(--spacing) * 2);
}
/* 操作中テナント（F-61・決定205・決定208・2026-09-23）。#topbar-tenant-name は e2e の手掛かり */
.l-topbar__tenant {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-text);
}
/* 名前とアバターを包む「名前を変更」へのリンク（2026-10-05）。名前は動詞ではないので、**常に下線**でリンクと分かるようにする
   （`.l-text-link` と同じ理由・WCAG 1.4.1。太さは足さない ＝ トップバーを重くしない）。色は名前の色のまま（新しい色を作らない） */
.l-topbar__user-link {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--spacing) * 3); /* 名前とアバターの間は、包む前と同じ（束の gap） */
  border-radius: var(--radius-md);
}
.l-topbar__user-link .l-topbar__user {
  text-decoration-line: underline;
}
.l-topbar__user-link:hover .l-topbar__user,
.l-topbar__user-link:focus-visible .l-topbar__user {
  color: var(--color-text);
}
/* #topbar-user-name は e2e がこの1要素だけを見る手掛かり（DOM 契約） */
.l-topbar__user {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
.l-topbar__avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: calc(var(--spacing) * 7);
  height: calc(var(--spacing) * 7);
  border-radius: 50%; /* Tailwind `rounded-full`。正方形を円にする定型で、角丸3段の外 */
  background-color: var(--primary);
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--color-white);
}

/* ---- トップバーのベル（通知。2026-10-03 に戻した）--------------------------------------
   未読数は部品の札（`c-badge--alert`）を使い、**置き場所だけ**をここで決める（アイコンの右上に重ねる）。
   見た目の差（色・大きさ）を作らない ＝ 部品の中身を上書きしない（§5-D2） */
.l-topbar__bell {
  position: relative;
  display: flex;
}
.l-topbar__bell-count {
  position: absolute;
  top: calc(var(--spacing) * -3);
  right: calc(var(--spacing) * -3);
}

/* ---- どの画面でも出る結果の文（本文の先頭。2026-10-04）。部品は `c-alert`。ここが持つのは本文との間だけ ---- */
.l-shell-result {
  margin-bottom: calc(var(--spacing) * 4);
}

/* ---- 重要で未読のお知らせの帯（本文の先頭。2026-10-03）---------------------------------
   部品は `c-alert--caution`（失敗ではないが放っておけない ＝ §4-B の Alert）。ここが持つのは本文との間だけ */
.l-announcement-banner {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 1);
  margin-bottom: calc(var(--spacing) * 4);
}

/* ---- 本文 ------------------------------------------------------------------
   id="main-content" はスキップリンクの行き先（e2e の DOM 契約）。 */
.l-main {
  flex: 1 1 0%;
  padding: calc(var(--spacing) * 6);
}

/* ---- 48rem 未満のシェル（U-1 第1弾・2026-09-30）----------------------------------
   ⑴ サイドバーを並びから外し、トップバーの「…」メニューにナビとアカウント欄を出す（ヘルプはバーに残す）
   ⑵ トップバーは1行。パンくずは今いる画面の名前だけを、はみ出す分は省略記号で出す（祖先は出さない）
   ⑶ 本文の左右余白は docs/DESIGN.md §6 のコンパクト値（--space-4 ＝ spacing × 4）
   ⑷ ヘルプと「…」の当たり判定を 44px 四方に広げる（見た目の 28px は変えない）
   **48rem 以上の見た目は変えない**（ここの宣言は全部この @media の中）。
   書き方はファイル冒頭の注記（`not all and (min-width: 48rem)` ＝ 下のグリッドの `(min-width: 48rem)` のちょうど裏） */
@media not all and (min-width: 48rem) {
  .l-sidebar,
  .l-topbar__account {
    display: none;
  }
  .l-topbar__menu {
    display: block;
  }
  .l-topbar {
    gap: calc(var(--spacing) * 2);
    padding-inline: calc(var(--spacing) * 4);
  }
  .l-topbar__actions {
    flex-shrink: 0;
  }
  /* 現在地の束は縦に2行: パンくず（今いる画面の名前）と、操作中テナント（F-61。切替は「…」の中）。
     同じ行に並べると 320px では両方が数文字で切れるので、幅を1行ずつ使える縦積みにした。高さは --topbar-h のまま */
  .l-topbar__where {
    display: flex;
    flex: 1 1 0%;
    flex-direction: column;
    justify-content: center;
    min-width: 0;
  }
  .l-topbar__where-tenant {
    display: block;
    overflow: hidden;
    font-size: var(--text-2xs);
    font-weight: 400;
    color: var(--color-text-muted);
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* 1行・省略記号は幅によらず上の「トップバーの並び」が持つ（#311）。ここは祖先と区切りを出さないだけ */
  .l-breadcrumb,
  .l-breadcrumb__list {
    min-width: 0;
  }
  .l-breadcrumb__item:not(:last-child),
  .l-breadcrumb__item:last-child > [aria-hidden="true"] {
    display: none;
  }
  .l-main {
    padding-inline: calc(var(--spacing) * 4);
  }
  /* 狭い幅で円が潰れない（390px 監査で幅12pxになっていた。メニューの中の利用者行） */
  .l-topbar__avatar {
    flex-shrink: 0;
  }
  /* ⑷ 当たり判定。見た目の箱（28px）の外へ spacing × 2 ずつ広げる。隣どうしが重ならないよう間隔を spacing × 4 にする */
  .l-topbar__actions {
    gap: calc(var(--spacing) * 4);
  }
  .l-topbar .c-popover__trigger {
    position: relative;
  }
  .l-topbar .c-popover__trigger::after {
    content: "";
    position: absolute;
    inset: calc(var(--spacing) * -2);
  }
  /* 開いた元（28px の箱）の右端に揃えると 320px 幅で左へはみ出すので、トップバーの直下に画面の幅いっぱい
     （左右に spacing × 2 の余白）で出す。縦に長ければパネルの中だけ縦に送る。
     **シェルの事情なのでシェルが持つ**（部品の `.c-popover__panel` 全体に掛けると、本文の中の Popover まで
     トップバーの直下へ飛ぶ）。layout.css は components.css より先に読むが、セレクタが強いのでこちらが勝つ */
  .l-topbar .c-popover__panel {
    position: fixed;
    top: calc(var(--topbar-h) + var(--spacing) * 1);
    right: calc(var(--spacing) * 2);
    left: calc(var(--spacing) * 2);
    width: auto;
    max-height: calc(100dvh - var(--topbar-h) - var(--spacing) * 4);
    overflow-y: auto;
  }
  /* 一覧を持つパネル（ベル）は**パネル自体を送らない** —— 一覧だけを送り、足元の操作を常に見せる（components.css の `--list`） */
  .l-topbar .c-popover__panel--list {
    overflow: hidden;
  }
  /* 「…」のパネルは縦に2段: ナビ（縦に送る）とアカウント欄（下端に残る）。パネル自体は送らない */
  .l-topbar__menu > .c-popover__panel {
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  .l-topbar__menu .l-sidebar__nav {
    min-height: 0;
    overflow-y: auto;
  }
}

/* ============================================================================
 * 1280px（docs/DESIGN.md §6「最小想定幅」）の扱い
 *
 * **Tailwind 版は min-width を一切設定していない**（web/ を 1280 で grep して、画面の骨格には0件。
 * 出てくるのは customer-table / entry-table / search-panel の「1280px に収める」注記だけ）。
 * §6 の「それ未満では横スクロールを許容し、レイアウトを崩さない」は、
 * 各表の横スクロール（.c-table-wrap）と e2e/geometry.spec.ts の実測で担保されていた。
 * **例外: 顧客DB一覧の2表は 1280px 以上でも表を枠に収めない**（2026-10-14・決定517 ＝ 列を縮めず、表が枠より広いページは
 * 枠の中で横に送る。ページ全体は送らない。`screens/customers.css` の「表は列を縮めず、枠の中で横に送る」の節）。
 * **ここでも min-width は足さない**（足すとスマホ閲覧（要件の非機能）の見え方が変わり、
 * それは移植ではなく仕様変更になる）。
 * ========================================================================== */

/* ---- ページの骨格 ----------------------------------------------------------
   <main> と余白はシェル側が持つ。ページの中で <main> を重ねない（landmark が2つになる）。 */
.l-page {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 4);
  width: 100%;
}

/* 見出し帯（h1 ＋ StateSwitcher 等） */
.l-page-header {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 2);
}
.l-page-title {
  font-size: var(--text-lg);
  font-weight: 600;
}
.l-page-title__sub {
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--color-text-muted);
}

/* 顧客詳細の見出しカード（web/app/customers/[id]/page.tsx の <header>） */
.l-detail-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--spacing) * 4);
  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);
}
.l-detail-header__title {
  display: flex;
  align-items: center;
  gap: calc(var(--spacing) * 2);
  font-size: var(--text-lg);
  font-weight: 600;
}
.l-detail-header__meta {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
/* 札の行（商材タグ・リード・流入）。**全幅に折る** —— 氏名の横に並べると、札が増えた分だけ操作が2段目へ押し出される
   （run lead-dedup の L8c・2026-10-02。1280 で実測 +84px）。**HTML の並びは 氏名 → 札 → 出典 → 操作**（読み上げと 48rem 未満の
   見た目はこの順。この人が誰かを読む札の行を操作で割らない ＝ 2026-10-02 の ux-critic の指摘・PR #344）。48rem 以上だけ下の `order` で
   札と出典を操作の後ろの全幅の行に置く —— `.l-quadrants` が `order` を避ける理由（見た目と Tab・読み上げの順のずれ）は、
   札と出典にフォーカスできる要素が無いのでここには当たらない（読み上げは HTML の順のまま）。
   行が空にならないのは流入の札が常にあるため（テンプレートは要素を条件で落としていない） */
.l-detail-header__tags {
  display: flex;
  flex-basis: 100%;
  min-width: 0;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--spacing) * 2);
}
.l-detail-header__actions {
  display: flex;
  flex-shrink: 0;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--spacing) * 2);
  margin-left: auto;
}
/* 顧客の出典の1行（run 2026-09-30-lead-dedup の L8c・U-L9 ⒜）。**全幅に折って、札の行の下に置く**（48rem 以上では操作の行の後ろ）——
   札の横に並べると 1280 で操作が2段目へ押し出される（骨格は出典を独立した1行に描く）。全幅は幅によらず効く */
.l-detail-header__source,
.l-detail-header__note {
  flex-basis: 100%;
  min-width: 0;
}
/* 48rem 以上: 氏名の行の右に操作を残し、札の行と出典の行はその下に置く（HTML の並びは変えない。理由は `__tags` の注記）。
   札の直下の1文（`__note`。取込を取り消したシートのリードを判定していない旨）は出典と同じ段で、HTML の並び（札 → 1文 → 出典）のまま */
@media (min-width: 48rem) {
  .l-detail-header__tags { order: 1; }
  .l-detail-header__source,
  .l-detail-header__note { order: 2; }
}
/* 48rem 未満は見出しの下の行に並べる（戻る・編集・優先対応が右の外へ出ていた。U-1 第2弾）。
   左寄せにして、ボタンが多ければ折り返す。48rem 以上は上のまま（1行で折り返さない幅がある） */
@media not all and (min-width: 48rem) {
  .l-detail-header__actions {
    flex-basis: 100%;
    flex-shrink: 1;
    min-width: 0;
    margin-left: 0;
  }
}

/* 詳細画面の4象限（顧客詳細・契約詳細）。**分割しない**（DESIGN.md §1-1「1画面で顧客の全体像」）。
   48rem 以上は2列、48rem 未満は1列に**積む**（DESIGN.md §1・決定380。U-1 第2弾）。積むのであって分割ではない
   （4区画は同じ1画面に並んだまま縦へ送る）。**積む順は HTML の並び**（CSS の `order` で見た目だけ入れ替えない ——
   見た目と Tab・読み上げの順がずれる）。
   Tailwind 版は `grid grid-cols-2 gap-4` でブレークポイントを持たない */
.l-quadrants {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: calc(var(--spacing) * 4);
}
@media not all and (min-width: 48rem) {
  .l-quadrants {
    grid-template-columns: minmax(0, 1fr);
  }
}
/* 番号の付いた4区画（顧客詳細 ①②③④）は **HTML を番号順**に並べ、48rem 以上では**列ごとに**置く
   （左列 ①②・右列 ③④。2026-09-30 利用者の決定 ＝ 48rem 未満で ①②③④ の順に積むため）。
   行は2列で共有するので、同じ行の区画（①と③、②と④）は今までどおり高い方に揃う。
   `grid-auto-flow: column` にしないのは、後ろの全列にまたがる区画（`.l-span-all`）が列の決まった項目として
   先に1行目へ置かれてしまうため。明示した4つの後ろへは、全列の区画が3行目から自動で並ぶ。
   PC の Tab 順は ①→②→③→④（列の順）になる（利用者が了承済み） */
@media (min-width: 48rem) {
  .l-quadrants--by-column > :nth-child(1) { grid-area: 1 / 1; }
  .l-quadrants--by-column > :nth-child(2) { grid-area: 2 / 1; }
  .l-quadrants--by-column > :nth-child(3) { grid-area: 1 / 2; }
  .l-quadrants--by-column > :nth-child(4) { grid-area: 2 / 2; }
}

/* ダッシュボードの KPI 列（`grid gap-4 sm:grid-cols-2 xl:grid-cols-4`） */
.l-grid-kpi {
  display: grid;
  gap: calc(var(--spacing) * 4);
}
@media (min-width: 40rem) {
  .l-grid-kpi { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 80rem) {
  /* **枚数に依存しない**（2026-09-28）: 1行にカードの数だけ等幅の列を作る。出所の無い
     「アラートあり顧客」を消して3枚になり（2026-09-30 に DEBUG からも消した）、
     `repeat(4, …)` 固定では右に空きが残った */
  .l-grid-kpi { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); }
}

/* ダッシュボードの2段組（`grid gap-4 xl:grid-cols-2`）。
   1列の状態でも列の幅を明示する（指定が無いと列幅が中身任せになり、390px で本文より 76px 広がった。U-1 第2弾） */
.l-grid-halves {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: calc(var(--spacing) * 4);
}
@media (min-width: 80rem) {
  .l-grid-halves { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* カードの並び（名寄せ一覧の `grid gap-4 md:grid-cols-2 xl:grid-cols-4`・見本の md:2 列） */
.l-grid-cards {
  display: grid;
  gap: calc(var(--spacing) * 4);
}
@media (min-width: 48rem) {
  .l-grid-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 80rem) {
  .l-grid-cards--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ---- 汎用の並び（Tailwind の `flex flex-wrap items-center gap-N` の頻出形）----
   画面ごとに BEM を起こすほどでもない並びのために、gap を段で持つ。値はスケール内だけ。 */
.l-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--spacing) * 2);
}
.l-row--gap-1 { gap: calc(var(--spacing) * 1); }
.l-row--gap-3 { gap: calc(var(--spacing) * 3); }
.l-row--gap-4 { gap: calc(var(--spacing) * 4); }
.l-row--gap-6 { gap: calc(var(--spacing) * 6); }
.l-stack {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 2);
}
.l-stack--gap-1 { gap: calc(var(--spacing) * 1); }
.l-stack--gap-3 { gap: calc(var(--spacing) * 3); }
.l-stack--gap-4 { gap: calc(var(--spacing) * 4); }
.l-row--end { justify-content: flex-end; }
.l-push-end { margin-left: auto; }

/* ---- 汎用の小道具（**画面をまたいで使う1行の型はここに1つだけ**）----------------------
   2026-09-14 の構造レビュー Med で、画面 CSS（screens/*.css）に同じ名前で中身の違う小道具
   （`.s-muted` が顧客画面では色だけ、ダッシュボードでは色＋字の大きさ）ができていたのを寄せた。
   **画面 CSS に汎用の小道具を作らない**（`api/tests/test_webui.py` の画面 CSS の検査が、画面の接頭辞の無い
   クラスと画面同士の名前の重複を落とす）。値はトークンだけ。
   **部品（`c-`）の見た目を上書きしない** —— このファイルは components.css より先に読むので、同じ詳細度では
   部品の宣言が勝つ。部品に要る差は components.css の修飾（`c-*--*`）で作る。 */
.l-mt-1 { margin-top: calc(var(--spacing) * 1); }
.l-mt-2 { margin-top: calc(var(--spacing) * 2); }
.l-mt-3 { margin-top: calc(var(--spacing) * 3); }
.l-mt-4 { margin-top: calc(var(--spacing) * 4); }
.l-block { display: block; }
.l-min0 { min-width: 0; }
.l-grow { flex: 1 1 0%; min-width: 0; }
.l-fill { width: 100%; }
/* 折り返し（表のセルは既定で折り返さない ＝ c-table__td。長い見出し・自由記述だけ折り返す） */
.l-wrap { white-space: normal; }
.l-nowrap { flex-wrap: nowrap; white-space: nowrap; }
/* グリッドの全列にまたがる（顧客詳細の下段の履歴・監査ログ） */
.l-span-all { grid-column: 1 / -1; }
/* 文字の色と太さ（**意味は語で運ぶ**。色だけで状態を伝えない・§10） */
.l-text { color: var(--color-text); }
.l-text-muted { color: var(--color-text-muted); }
.l-text-sm { font-size: var(--text-sm); }
.l-text-xs { font-size: var(--text-xs); }
.l-text-strong { font-weight: 600; }
.l-text-warning { color: var(--color-warning-fg); }
.l-text-danger { font-weight: 600; color: var(--color-danger-fg); }
.l-text-info { color: var(--color-info-fg); }
/* 補足の1行（小さく・薄く） */
.l-caption { font-size: var(--text-xs); color: var(--color-text-muted); }
/* 表の中の本文リンク（下線はホバーだけ） */
.l-link:hover { text-decoration-line: underline; }
/* **表の外の本文リンク**（文や行の中に置くリンク。2026-10-02・DESIGN §4-B の Link）。`base.css` の
   `a { color: inherit; text-decoration: inherit }` のままだと周りの文と見分けが付かない（WCAG 1.4.1）ので、
   **常に下線と太さ**で示す（色だけにしない。誤りの文の中では誤りの色のまま下線で分かる）。新しい色は作らない。
   顧客画面にあった同じ定義3つ（統合の帯・書き出しのモーダル・誤りのまとめ）は 2026-10-02 にこれへ寄せた */
.l-text-link {
  font-weight: 600;
  text-decoration-line: underline;
}

/* ---- 見本ページ（/design）の骨格。業務画面では使わない ------------------------
   `mx-auto flex w-full max-w-6xl flex-col gap-8 p-6`。max-w-6xl は Tailwind v4 で 72rem。 */
.l-showcase {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 8);
  width: 100%;
  max-width: var(--width-showcase);
  margin-inline: auto;
  padding: calc(var(--spacing) * 6);
}
.l-showcase__header {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 1);
}
.l-showcase__row {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 3);
}
.l-showcase__row-head {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 1);
  border-bottom: var(--border-w) solid var(--border);
  padding-bottom: calc(var(--spacing) * 2);
}
.l-showcase__row-title {
  font-size: var(--text-md);
  font-weight: 600;
}
.l-showcase__row-note {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
/* 見本1つぶん（**どれが何の見本か画面から読める**ようにする・2026-09-17 の UX / a11y レビュー Low。
 * それまで進捗バーが5本並んで、違いを説明する文がテンプレートのコメントにしか無かった）。 */
.l-showcase__sample {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 2);
}
.l-showcase__sample-name {
  font-size: var(--text-2xs);
  color: var(--color-text-muted);
}
/* フォームの見本の幅（`max-w-md` = 28rem） */
.l-showcase__narrow {
  max-width: var(--width-form);
}
/* サイドバー下部の告知（margin-top: auto で下に寄る）を見本の中で再現する枠 */
.l-showcase__frame {
  display: flex;
  flex-direction: column;
  min-height: calc(var(--spacing) * 24);
}

/* ============================================================================
 * ログイン（web/app/login/page.tsx ＋ login-form.tsx）。シェル外。
 * 背景は**単色**（モックのグラデーションは §8 AI スロップ禁止リストに当たるので落とした・移植元の注記）
 * ========================================================================== */
.l-login {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(var(--spacing) * 6);
  min-height: 100vh;
  background-color: var(--color-teal-900);
  padding: calc(var(--spacing) * 6);
}
.l-login__card {
  width: 100%;
  max-width: var(--width-form);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
  padding: calc(var(--spacing) * 8);
  box-shadow: var(--shadow-4);
}
/* ブランドは**見出しではない**（`<h1>` は画面の目的。a11y 監査 Med・2026-09-16）。装飾の1行として小さく置く */
.l-login__brand {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-text-muted);
}
.l-login__brand-mark {
  color: var(--primary);
}
.l-login__title {
  margin-top: calc(var(--spacing) * 1);
  font-size: var(--text-xl);
  font-weight: 700;
}
.l-login__caption {
  margin-top: calc(var(--spacing) * 1);
  margin-bottom: calc(var(--spacing) * 6);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
.l-login__form {
  display: flex;
  flex-direction: column;
  gap: calc(var(--spacing) * 4);
}
.l-login__submit {
  width: 100%;
  margin-top: calc(var(--spacing) * 2);
}
/* 確認コードの画面（`login_code.html`）の副次の操作（再送・やり直し）。主 CTA の下に弱く並べる */
.l-login__aside {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--spacing) * 2);
  margin-top: calc(var(--spacing) * 4);
}
/* 再送のフォーム。待ちのあいだは、ボタンの下に理由（「あとN秒で再送できます。」）を出す */
.l-login__resend {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(var(--spacing) * 1);
}
.l-login__resend-wait {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
/* 「届かないときは迷惑メールフォルダも」。**常設の1文**（失敗していなくても出る・UX レビュー Low） */
.l-login__hint {
  margin-top: calc(var(--spacing) * 3);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
.l-login__footer {
  margin-top: calc(var(--spacing) * 6);
  border-top: var(--border-w) solid var(--border);
  padding-top: calc(var(--spacing) * 4);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
.l-login__dev {
  width: 100%;
  max-width: var(--width-form);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
  padding: calc(var(--spacing) * 3);
}
/* 開発用に出す確認コード（2026-09-18）。**製品の UI に見せない** —— 前後の行は状態切替と同じ
   `c-state-note`（小さい・控えめ）で、目立つのはコードの数字だけにする。
   数字は `--font-num`（`num`）で桁を読み違えにくくし、`<code>` に入れて選択しやすくする */
.l-login__dev-code {
  display: flex;
  align-items: baseline;
  gap: calc(var(--spacing) * 2);
  padding-top: calc(var(--spacing) * 1);
  padding-bottom: calc(var(--spacing) * 1);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
.l-login__dev-code code {
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius-sm);
  background-color: var(--color-gray-50);
  padding: calc(var(--spacing) * 1) calc(var(--spacing) * 2);
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  color: var(--color-text);
  user-select: all; /* 1回の選択で6桁が丸ごと選べる（Computer Use・手の両方で読み取りやすい） */
}

/* ---- エラー画面（404 / 500 / CSRF）。シェル無しのときだけ中央の枠に入れる ---- */
.l-error-standalone {
  max-width: var(--width-prose);
  margin: calc(var(--spacing) * 12) auto;
  padding: calc(var(--spacing) * 6);
}
