/*
 * Gazelle 顧客向け画面の共通コンポーネント（docs/spec/12_web_ui.md）。
 *
 * 画面ごとの CSS ファイルを新設しないこと。画面固有の見た目が必要になったら、ここの
 * 定義を拡張する。カラーコードを直接書かず、tokens.css のカスタムプロパティを参照する。
 */

/* ========== ボタン ========== */
.gz-btn {
  display: inline-block;
  padding: var(--gz-space-1) var(--gz-space-2);
  border: 1px solid transparent;
  border-radius: var(--gz-radius);
  font-family: inherit;
  font-size: var(--gz-font-body);
  line-height: var(--gz-line-height);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}

/* 主要ボタン。1 画面につき 1 つに限る */
.gz-btn--primary {
  background-color: var(--gz-main-500);
  border-color: var(--gz-main-500);
  color: var(--gz-on-main);
}

.gz-btn--primary:hover {
  background-color: var(--gz-main-700);
  border-color: var(--gz-main-700);
  color: var(--gz-on-main);
}

/* 副次ボタン（取消・戻る等） */
.gz-btn--secondary {
  background-color: var(--gz-surface);
  border-color: var(--gz-main-500);
  color: var(--gz-main-500);
}

.gz-btn--secondary:hover {
  background-color: var(--gz-main-50);
  color: var(--gz-main-700);
}

/*
 * 削除ボタン。--gz-danger ではなく --gz-danger-strong を使う。--gz-danger は白文字との
 * コントラスト比が 3.36 で本文基準に届かない
 */
.gz-btn--danger {
  background-color: var(--gz-danger-strong);
  border-color: var(--gz-danger-strong);
  color: var(--gz-on-main);
}

.gz-btn--danger:hover {
  background-color: var(--gz-danger);
  border-color: var(--gz-danger);
  color: var(--gz-on-status);
}

.gz-btn:disabled,
.gz-btn[aria-disabled='true'] {
  background-color: var(--gz-ink-100);
  border-color: var(--gz-ink-300);
  color: var(--gz-ink-600);
  cursor: not-allowed;
}

/* 行内に並べる小さなボタン（搬送の並べ替え等）。本文中の操作なので高さを抑える */
.gz-btn--compact {
  padding: 0 var(--gz-space-1);
  font-size: var(--gz-font-small);
}

/* ボタンの並び */
.gz-btn-group {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gz-space-1);
  align-items: center;
}

/* ========== メッセージ帯 ========== */
/*
 * 処理結果の通知。背景は白のままにし、左辺の帯だけを状態色にする。面を状態色で塗ると
 * 一覧の状態バッジと同じ強さで目に入り、どちらが状態を表しているのか読み取れなくなる
 */
.gz-message {
  padding: var(--gz-space-2);
  background-color: var(--gz-surface);
  border: 1px solid var(--gz-ink-300);
  border-left-width: 6px;
  border-radius: var(--gz-radius);
  color: var(--gz-ink-900);
}

.gz-message + .gz-message {
  margin-top: var(--gz-space-1);
}

.gz-message-list {
  margin-bottom: var(--gz-space-3);
}

.gz-message--success {
  border-left-color: var(--gz-success);
}

.gz-message--warning {
  border-left-color: var(--gz-warning);
}

.gz-message--danger {
  border-left-color: var(--gz-danger);
}

/* ========== 状態バッジ ========== */
/*
 * 状態色の塗り + 黒文字 + 状態名の文言。**文言を省略しないこと。** 色を読み取れない
 * 利用者と、モノクロで印刷した紙でも状態が分かるようにするためである
 */
.gz-badge {
  display: inline-block;
  padding: 2px var(--gz-space-1);
  border-radius: var(--gz-radius);
  color: var(--gz-on-status);
  font-size: var(--gz-font-small);
  white-space: nowrap;
}

.gz-badge--success {
  background-color: var(--gz-success);
}

.gz-badge--warning {
  background-color: var(--gz-warning);
}

.gz-badge--danger {
  background-color: var(--gz-danger);
}

/* 状態を持たない・終了した対象。状態色を消費せずに中立色で示す */
.gz-badge--neutral {
  background-color: var(--gz-ink-100);
  border: 1px solid var(--gz-ink-300);
}

/*
 * 進行中の対象（安置中・追跡中）。搬送の追跡状態は 4 値あり状態色の 3 色へ割り当てられず、
 * かついずれも正常な業務の進行であって「警告」「危険」を意味しない。状態色をここで消費すると
 * 画面上の色が通知の判定結果を指さなくなるため、メインカラーの淡色で表す
 */
.gz-badge--active {
  background-color: var(--gz-main-100);
  border: 1px solid var(--gz-main-300);
}

/* ========== フォーム ========== */
.gz-field {
  margin-bottom: var(--gz-space-2);
}

.gz-field__label {
  margin-bottom: 2px;
}

/*
 * 必須の印。状態色を使わない。必須であることは「状態」ではなく項目の属性であり、かつ
 * 危険色で表すと、同じ欄に検証エラーが出たときに「必須」と「エラー」を色で区別できなくなる
 */
.gz-field__required {
  margin-left: var(--gz-space-1);
  padding: 0 var(--gz-space-1);
  background-color: var(--gz-main-100);
  border: 1px solid var(--gz-main-300);
  border-radius: var(--gz-radius);
  color: var(--gz-main-900);
  font-size: var(--gz-font-small);
  font-weight: normal;
}

.gz-field__help {
  color: var(--gz-ink-600);
  font-size: var(--gz-font-small);
}

/* 入力欄の直下に出す検証エラー */
.gz-field__error {
  color: var(--gz-danger-strong);
  font-size: var(--gz-font-small);
  font-weight: bold;
}

.gz-field--invalid input,
.gz-field--invalid select,
.gz-field--invalid textarea {
  border-color: var(--gz-danger-strong);
}

/* 入力欄を横に並べる行。画面幅が狭いときは縦積みになる */
.gz-field-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gz-space-2);
}

.gz-field-row > .gz-field {
  flex: 1 1 200px;
}

/*
 * 入力する文字数が決まっている項目（日付等）。他の項目と同じ比率で伸ばすと、日付欄だけが
 * 不必要に広くなる。狭い画面では他の項目と同様に 1 行を占める
 */
.gz-field-row > .gz-field--narrow {
  flex: 0 1 14rem;
}

/*
 * 繰り返し入力の 1 行（搬送の入力欄等）。左辺にメインカラーの帯を引いて、どこからどこまでが
 * 1 件分なのかを示す。状態色は使わない（入力欄の集まりは状態ではない）
 */
.gz-formset-row {
  margin: 0 0 var(--gz-space-2);
  padding: var(--gz-space-2);
  background-color: var(--gz-surface);
  border: 1px solid var(--gz-ink-300);
  border-left: 6px solid var(--gz-main-300);
  border-radius: var(--gz-radius);
}

/* 凡例。件数の表示と並べ替えの操作部品を 1 行に収める */
.gz-formset-row__legend {
  display: flex;
  gap: var(--gz-space-2);
  align-items: center;
  padding: 0 var(--gz-space-1);
  color: var(--gz-main-900);
  font-weight: bold;
}

/* 並べ替えの操作部品。JS が有効なときだけ表示する（テンプレートで hidden にしてある） */
.gz-formset-row__tools {
  display: flex;
  gap: var(--gz-space-1);
  align-items: center;
}

/* `hidden` は display を持つ指定に負けるため、明示的に打ち消す */
.gz-formset-row__tools[hidden] {
  display: none;
}

/*
 * ドラッグの取っ手。掴める領域であることを塗りと枠で示し、**掴み損ねないだけの幅を持たせる**。
 * 文字 1 つ分では、狙って押さえるのに精度が要る
 */
.gz-formset-row__handle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 5rem;
  padding: 2px var(--gz-space-2);
  background-color: var(--gz-main-100);
  border: 1px solid var(--gz-main-300);
  border-radius: var(--gz-radius);
  color: var(--gz-main-900);
  letter-spacing: 2px;
  cursor: grab;
  user-select: none;
}

/* ドラッグ中の行。掴んでいる行がどれかを示す */
.gz-formset-row--dragging {
  opacity: 0.5;
}

/*
 * 削除を指定した行。凡例の文言は読み上げ用で画面に出ないため、確定前に削除対象が分かるよう
 * 見た目を落とす。**入力欄は使えるままにする**（指定を取り消して編集を続けられるようにする）
 */
.gz-formset-row--deleted {
  opacity: 0.55;
}

/* 削除の指定。チェックボックスとラベルを横に並べる */
.gz-formset-row__delete {
  display: flex;
  gap: var(--gz-space-1);
  align-items: center;
  margin-top: var(--gz-space-1);
  padding-top: var(--gz-space-1);
  border-top: 1px solid var(--gz-ink-300);
}

.gz-formset-row__delete label {
  font-weight: normal;
}

.gz-formset-row__delete input[type='checkbox'] {
  width: auto;
}

.gz-form__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gz-space-1);
  margin-top: var(--gz-space-3);
  padding-top: var(--gz-space-2);
  border-top: 1px solid var(--gz-ink-300);
}

/* ========== 検索条件パネル ========== */
/* 一覧の上部に置く。開閉はしない（条件を常に見せる） */
.gz-search {
  margin-bottom: var(--gz-space-3);
  padding: var(--gz-space-2);
  background-color: var(--gz-main-50);
  border: 1px solid var(--gz-ink-300);
  border-radius: var(--gz-radius);
}

.gz-search__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gz-space-1);
  margin-top: var(--gz-space-1);
}

/* ========== 件数・補足の表示 ========== */
.gz-summary {
  margin-bottom: var(--gz-space-1);
  color: var(--gz-ink-600);
  font-size: var(--gz-font-small);
}

/* ========== ログイン ========== */
.gz-login {
  max-width: 24rem;
  margin: var(--gz-space-4) auto;
}

/* ========== ページャ ========== */
.gz-pager {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gz-space-1);
  justify-content: center;
  margin-top: var(--gz-space-3);
}

.gz-pager__item {
  display: inline-block;
  min-width: 2.5rem;
  padding: 2px var(--gz-space-1);
  background-color: var(--gz-surface);
  border: 1px solid var(--gz-ink-300);
  border-radius: var(--gz-radius);
  color: var(--gz-main-500);
  text-align: center;
  text-decoration: none;
}

.gz-pager__item:hover {
  background-color: var(--gz-main-50);
}

.gz-pager__item--current {
  background-color: var(--gz-main-500);
  border-color: var(--gz-main-500);
  color: var(--gz-on-main);
  font-weight: bold;
}

.gz-pager__item--current:hover {
  background-color: var(--gz-main-500);
  color: var(--gz-on-main);
}

/* ========== 定義リスト（詳細画面の項目表示） ========== */
.gz-detail {
  display: grid;
  grid-template-columns: 12rem 1fr;
  gap: 1px;
  background-color: var(--gz-ink-300);
  border: 1px solid var(--gz-ink-300);
  border-radius: var(--gz-radius);
  overflow: hidden;
}

.gz-detail__label {
  padding: var(--gz-space-1) var(--gz-space-2);
  background-color: var(--gz-main-100);
  font-weight: bold;
}

.gz-detail__value {
  padding: var(--gz-space-1) var(--gz-space-2);
  background-color: var(--gz-surface);
}

/*
 * 1 行に「ラベル + 値」を 2 組並べる定義リスト。項目数が少ない詳細表示で、縦に間延びさせない
 * ために使う
 */
.gz-detail--pair {
  grid-template-columns: 10rem 1fr 10rem 1fr;
}

/* 対にする相手を持たない値。行の残りをすべて占める */
.gz-detail__value--full {
  grid-column: 2 / -1;
}

/*
 * 画面幅が 1024px 未満のとき、2 組の横並びを 1 組に戻す。値が短い項目でも、1 行に 2 組
 * 置くと事務所の標準的なノート PC で葬家名が折り返す
 */
@media (max-width: 1023px) {
  .gz-detail--pair {
    grid-template-columns: 12rem 1fr;
  }

  .gz-detail__value--full {
    grid-column: auto;
  }
}

@media (max-width: 767px) {
  .gz-detail {
    grid-template-columns: 1fr;
  }
}

/* ========== ジオフェンスの選択欄 ========== */
/*
 * 「出発地点」「到着地」の入力欄（apps.geofence.widgets.GeofencePickerWidget）。選択済みの
 * 名称を表示する欄と、検索モーダルを開く導線を横に並べる。画面幅が足りなくなると折り返す
 */
.gz-picker {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gz-space-1);
  align-items: center;
}

/*
 * 選択済みの名称。読み取り専用であることを背景で示す（無効状態と同じ塗り）。キーボードからは
 * 到達できるままにしてあり、選んだ内容を読み上げで確認できる。
 *
 * **`input` を付けて詳細度を上げる。** base.css の `input[type='text']` が背景色を持つため、
 * クラスだけの指定では負けて白のままになる（読み取り専用であることが見た目に出ない）
 */
input.gz-picker__name {
  flex: 1 1 10rem;
  background-color: var(--gz-ink-100);
}

/* 「選択」「解除」。JS が有効なときだけ表示する（テンプレートで hidden にしてある） */
.gz-picker__tools {
  display: flex;
  gap: var(--gz-space-1);
  align-items: center;
}

/* `hidden` は display を持つ指定に負けるため、明示的に打ち消す */
.gz-picker__tools[hidden] {
  display: none;
}

/* ========== 検索モーダル ========== */
/*
 * 一覧から 1 件を選ぶためのモーダル（ジオフェンスの検索）。`<dialog>` を使い、フォーカスの
 * 閉じ込め・Esc での閉じ・背後の操作の抑止はブラウザに任せる。
 *
 * **display は `[open]` の側に書く。** `.gz-modal` に直接書くと `<dialog>` が閉じている
 * ときの `display: none` を打ち消してしまい、常に表示されたままになる
 */
.gz-modal {
  width: min(40rem, 92vw);
  max-height: 85vh;
  padding: var(--gz-space-3);
  background-color: var(--gz-surface);
  border: 1px solid var(--gz-main-300);
  border-radius: var(--gz-radius);
  color: var(--gz-ink-900);
}

.gz-modal[open] {
  display: flex;
  flex-direction: column;
  gap: var(--gz-space-2);
}

.gz-modal::backdrop {
  background-color: var(--gz-overlay);
}

.gz-modal__title {
  margin: 0;
}

/* 検索条件。名称・種別・検索ボタンを横に並べ、幅が足りなくなると折り返す */
.gz-modal__search {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gz-space-2);
  align-items: flex-start;
}

.gz-modal__search > .gz-field {
  flex: 1 1 12rem;
  margin-bottom: 0;
}

.gz-modal__search > .gz-field--narrow {
  flex: 0 1 12rem;
}

/* 検索ボタンは入力欄のラベルの分だけ下げ、入力欄と高さを揃える */
.gz-modal__search-action {
  padding-top: calc(var(--gz-line-height) * 1em + 2px);
}

/* 件数・切り詰め・失敗を伝える文。色だけでなく必ず文言で示す */
.gz-modal__status {
  margin: 0;
  color: var(--gz-ink-600);
  font-size: var(--gz-font-small);
}

/*
 * 検索結果。件数が上限に達しても画面からあふれないよう、この枠の中だけを縦にスクロール
 * させる（モーダル全体が伸びると、下端の「閉じる」が画面外へ出る）
 */
.gz-modal__results {
  flex: 1 1 auto;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  border-top: 1px solid var(--gz-ink-300);
  list-style: none;
}

.gz-modal__result {
  border-bottom: 1px solid var(--gz-ink-300);
}

/*
 * 結果の 1 件。行の全幅を押下の対象にする。一覧の行と違ってこれは選択の操作そのものであり、
 * ボタンとして表しているためキーボードからも到達できる
 */
.gz-modal__result-button {
  display: flex;
  gap: var(--gz-space-2);
  align-items: baseline;
  justify-content: space-between;
  width: 100%;
  padding: var(--gz-space-1);
  background-color: transparent;
  border: none;
  color: var(--gz-ink-900);
  font-family: inherit;
  font-size: var(--gz-font-body);
  line-height: var(--gz-line-height);
  text-align: left;
  cursor: pointer;
}

.gz-modal__result-button:hover {
  background-color: var(--gz-main-50);
}

.gz-modal__result-name {
  flex: 1 1 auto;
}

/* 種別。名称と同じ大きさで並べると、どちらが名前なのか読み取りにくい */
.gz-modal__result-type {
  flex: 0 0 auto;
  color: var(--gz-ink-600);
  font-size: var(--gz-font-small);
}

/* 閉じる導線。モーダルの下端に右寄せで置く */
.gz-modal__actions {
  display: flex;
  gap: var(--gz-space-1);
  justify-content: flex-end;
}
