@charset "UTF-8";

/*
 * 全画面の共通スタイル（管理画面と購入者フロント）。
 *
 * **Pico CSS の後に読み込む。** 素の HTML の見た目は Pico が付けるため、ここには
 * **Pico が持たないアプリ固有のレイアウト**と、**同じ要素の役割の書き分け**だけを置く。
 * Pico と同じことを書かない（同じ見た目を 2 箇所で持つと、いずれ片方だけが直る）。
 *
 * **クラス名を使わない。** 当てる相手は要素そのものである。例外は `message` の 2 つだけで、
 * メッセージの深刻度は HTML の要素では表せないためである。
 *
 * **色は下の「意匠のトークン」（`--flory-*`）で 1 度だけ決め、`--pico-*` へ流す。**
 * 意匠を変える人が触るのはそのブロックだけであり、管理画面と購入者フロントの両方に効く。
 * トークン以外の場所に色の値を書かない。
 *
 * **見た目を「セレクタで上書きする」のではなく、「Pico が読む変数を差し替える」。**
 * Pico のボタンは `[type=submit]`（詳細度 0,1,0）で色と余白を当てるため、`header button`
 * （0,0,2）では**後から読んでも負ける**。詳細度を上げて戦うと、`:hover` `:focus` の分まで
 * 追いかけることになる。**役割ごとの書き分けも、その範囲で変数を差し替えて行う**
 * （例: ヘッダの中では `--pico-primary-background` を secondary の値に向ける）。
 *
 * **系統ごとの差は `[data-front='...']` でスコープする**（値はレイアウトが埋める）。
 */

/* ------------------------------------------------------------------ *
 * 意匠のトークン（意匠の入口）
 *
 * **意匠を変えるときに触るのはこのブロックだけである。** 下の「Pico へ流す」で
 * `--pico-*` へ渡しており、管理画面と購入者フロントの両方が同じ値を読む。
 *
 * 色は白基調・低彩度とする（弔事の場面で使うため）。**純白と純黒は使わない**
 * （純白は眩しく、純黒は紙面が硬くなる）。
 * ------------------------------------------------------------------ */

:root {
  --flory-primary: #2f5d50;
  --flory-primary-hover: #24493f;
  --flory-primary-focus: rgba(47, 93, 80, 0.35);
  --flory-primary-inverse: #fff;
  --flory-primary-subtle: #e6efeb;

  --flory-surface: #faf9f7;
  --flory-surface-raised: #fff;
  --flory-surface-sunken: #f1efeb;
  --flory-border: #e3e1dc;

  --flory-text: #1f2328;
  --flory-text-muted: #5a6169;

  /*
   * 受注ステータスの印（地色と文字色の組）。**文字と地色のコントラスト比を 4.5 以上に保つ。**
   * 対応が要る状態を暖色、進んだ状態を主色、取り消した状態を灰色系に寄せる。
   */
  --flory-status-unprocessed: #f6ecd4;
  --flory-status-unprocessed-text: #6b4a0f;
  --flory-status-on-hold: #e4ebf1;
  --flory-status-on-hold-text: #2f4a63;
  --flory-status-confirmed: #dde9e4;
  --flory-status-confirmed-text: var(--flory-primary);
  --flory-status-rejected: #f3e1df;
  --flory-status-rejected-text: #7a2e2a;
  --flory-status-cancelled: #ecebe8;
  --flory-status-cancelled-text: var(--flory-text-muted);
  --flory-status-refunded: #e9e4ee;
  --flory-status-refunded-text: #4d3f5e;

  /* 操作結果の知らせ（地色・枠と文字色）。受注ステータスの印と同じ色味を使う */
  --flory-message-info: var(--flory-primary-subtle);
  --flory-message-info-border: var(--flory-primary);
  --flory-message-warning: var(--flory-status-unprocessed);
  --flory-message-warning-text: var(--flory-status-unprocessed-text);
  --flory-message-error: var(--flory-status-rejected);
  --flory-message-error-text: var(--flory-status-rejected-text);

  /* 指で操作する場面での対象の下限。`pointer: coarse` のときだけ効かせる */
  --flory-tap-size: 48px;
}

/* ------------------------------------------------------------------ *
 * Pico へ流す
 *
 * **セレクタでの上書きに頼らない。** Pico のボタンは `[type=submit]`（詳細度 0,1,0）で
 * 色と余白を当てるため、要素セレクタでは後から読んでも負ける。変数で変えられる範囲は
 * 変数で変える。
 *
 * **配色の変数は `:root:not([data-theme=dark])` で受ける。** Pico が同じ詳細度（0,2,0）で
 * 定義しており、素の `:root`（0,1,0）では後から読んでも負ける。
 * ------------------------------------------------------------------ */

:root:not([data-theme='dark']) {
  --pico-primary: var(--flory-primary);
  --pico-primary-background: var(--flory-primary);
  --pico-primary-border: var(--flory-primary);
  --pico-primary-underline: var(--flory-primary-focus);
  --pico-primary-hover: var(--flory-primary-hover);
  --pico-primary-hover-background: var(--flory-primary-hover);
  --pico-primary-hover-border: var(--flory-primary-hover);
  --pico-primary-hover-underline: var(--flory-primary-hover);
  --pico-primary-focus: var(--flory-primary-focus);
  --pico-primary-inverse: var(--flory-primary-inverse);

  --pico-background-color: var(--flory-surface);
  --pico-card-background-color: var(--flory-surface-raised);
  --pico-card-sectioning-background-color: var(--flory-surface);
  --pico-card-border-color: var(--flory-border);
  --pico-muted-border-color: var(--flory-border);
  --pico-form-element-background-color: var(--flory-surface-raised);

  --pico-color: var(--flory-text);
  --pico-muted-color: var(--flory-text-muted);
  --pico-h1-color: var(--flory-text);
  --pico-h2-color: var(--flory-text);
  --pico-h3-color: var(--flory-text);
  --pico-h4-color: var(--flory-text);
  --pico-h5-color: var(--flory-text);
  --pico-h6-color: var(--flory-text);
}

/* 配色以外は Pico も `:root` で定義しているため、同じ詳細度で足りる */
:root {
  /* 日本語は 1.5 だと行が詰まって見える */
  --pico-line-height: 1.75;

  /*
   * 日本語のフォントを明示する。Pico の既定は `system-ui` から始まるが、
   * **環境によっては日本語が明朝で描画される**（`system-ui` が日本語の字形を持たないため）。
   */
  --pico-font-family-sans-serif:
    system-ui, -apple-system, 'Segoe UI', 'Hiragino Sans', 'Noto Sans JP',
    Meiryo, sans-serif;

  /* 入力項目の見出しは太字にする。項目名が値の羅列の中で沈まないようにするため */
  --pico-form-label-font-weight: 700;
}

/* ------------------------------------------------------------------ *
 * 表示の段（ブレークポイント）
 *
 * **Pico が持つ幅をそのまま使い、独自の幅を作らない。** Pico は 576 / 768 / 1024 /
 * 1280 / 1536px で `body > main` の最大幅と `--pico-font-size` を切り替える。
 *
 * **文字サイズの倍率は全画面で反転させる。** Pico は画面が広いほど文字を大きくするが
 * （100% → 131.25%）、本システムは高齢の利用者が使うスマートフォンをいちばん大きくしたい。
 * 管理画面も同じ尺度で読む（PC 幅で 16px）。
 *
 * **最大幅の上書きは購入者フロントと入口だけに効かせる。** 段を 3 つに畳むのは購入者の画面の
 * 規約であり（入口も従う）、管理画面の版面はここでは変えない。
 * ------------------------------------------------------------------ */

:root {
  --pico-font-size: 106.25%; /* 17px */
}

@media (min-width: 576px) {
  :root {
    --pico-font-size: 106.25%;
  }
}

/*
 * スマートフォンの段は画面幅いっぱいにする。**Pico はここで 510px に絞り、左右の余白も
 * 0 にする**ため、幅を戻すのと同時に余白を戻す。
 *
 * **上限を区切る。** 区切らないと、後から読む分だけ上の段（768px 以降）の最大幅まで打ち消す。
 */
@media (min-width: 576px) and (max-width: 767.98px) {
  body[data-front='purchase'] > header,
  body[data-front='purchase'] > main,
  body[data-front='purchase'] > footer,
  body[data-front='entrance'] > header,
  body[data-front='entrance'] > main {
    max-width: none;
    padding-right: var(--pico-block-spacing-horizontal);
    padding-left: var(--pico-block-spacing-horizontal);
  }
}

/* タブレットの段。最大幅は Pico の既定（700px）をそのまま使う */
@media (min-width: 768px) {
  :root {
    --pico-font-size: 106.25%;
  }
}

@media (min-width: 1024px) {
  :root {
    --pico-font-size: 106.25%;
  }
}

/* まだタブレットの段である。Pico は 950px へ広げるが、段を増やさない（上限を区切る） */
@media (min-width: 1024px) and (max-width: 1279.98px) {
  body[data-front='purchase'] > header,
  body[data-front='purchase'] > main,
  body[data-front='purchase'] > footer,
  body[data-front='entrance'] > header,
  body[data-front='entrance'] > main {
    max-width: 700px;
  }
}

/* PC の段。最大幅は Pico の既定（1200px）をそのまま使う */
@media (min-width: 1280px) {
  :root {
    --pico-font-size: 100%; /* 16px */
  }
}

@media (min-width: 1536px) {
  :root {
    --pico-font-size: 100%;
  }

  /* 1 行が長くなりすぎると視線が戻れない。Pico の既定（1450px）は広すぎる */
  body[data-front='purchase'] > header,
  body[data-front='purchase'] > main,
  body[data-front='purchase'] > footer,
  body[data-front='entrance'] > header,
  body[data-front='entrance'] > main {
    max-width: 1200px;
  }
}

/* ------------------------------------------------------------------ *
 * ヘッダとナビゲーション
 *
 * Pico は `body > header` に余白を与えるが、並べ方は決めない。ナビゲーションを右端へ
 * 寄せるのは、この画面群の作りである。
 *
 * ヘッダの中のフォームは「ログアウト」だけである。本文のフォームと同じ見た目にすると
 * 主要な操作に見えてしまうため、控えめにする。
 * ------------------------------------------------------------------ */

header {
  /*
   * ヘッダの中のボタンは「ログアウト」だけである。本文の操作と同じ色にすると主要な操作に
   * 見えてしまうため、**この範囲だけ Pico が読む primary の値を secondary へ向ける**。
   * `:hover` `:focus` も Pico 側の規則がそのまま働く。
   */
  --pico-primary-background: var(--pico-secondary-background);
  --pico-primary-hover-background: var(--pico-secondary-hover-background);
  --pico-primary-border: var(--pico-secondary-border);
  --pico-primary-hover-border: var(--pico-secondary-hover-border);
  --pico-primary-inverse: var(--pico-secondary-inverse);

  display: flex;
  align-items: center;
  gap: var(--pico-spacing);
  border-bottom: var(--pico-border-width) solid var(--pico-muted-border-color);
}

/* ロゴは行き先が自明なので、リンクの装飾を外す */
header > a:first-child {
  flex: 0 0 auto;
  color: var(--pico-color);
  font-weight: 700;
  text-decoration: none;
}

/*
 * ヘッダのロゴ。**高さで揃え、幅は縦横比に任せる。**
 * 素材より大きく描くとぼやけるため、素材の原寸を超えない範囲に収める。
 */
header img {
  display: block;
  height: 2.5rem;
  width: auto;
}

/*
 * 管理画面の所属（ロゴの隣）とログイン中のユーザ（メニューの隣）は 1 行に収める。
 * **折り返すとヘッダの高さが名前の長さで変わる**ため、狭い画面では入りきらない分を省略する。
 *
 * 所属は、テナント・生花担当では所属の確認と切替へのリンク（`a`）、運営ではロール名（`strong`）である。
 */
[data-front='console'] header > a + a,
[data-front='console'] header > strong {
  flex: 0 1 auto;
  display: flex;
  align-items: center;
  gap: calc(var(--pico-spacing) * 0.375);
  min-width: 0;
  color: var(--flory-primary);
  font-size: 1.125rem;
  font-weight: 700;
  white-space: nowrap;
}

[data-front='console'] header > a + a {
  padding: calc(var(--pico-spacing) * 0.25) calc(var(--pico-spacing) * 0.625);
  background: var(--flory-primary-subtle);
  border: var(--pico-border-width) solid var(--flory-border);
  border-radius: var(--pico-border-radius);
  text-decoration: none;
}

[data-front='console'] header > a + a:hover,
[data-front='console'] header > a + a:focus-visible {
  border-color: var(--flory-primary);
}

[data-front='console'] header > a + a > strong {
  overflow: hidden;
  text-overflow: ellipsis;
}

[data-front='console'] header > a + a > svg {
  flex: 0 0 auto;
  width: 1.125rem;
  height: 1.125rem;
}

/*
 * メニューは常に畳む。**JavaScript を使わず `details` / `summary` で開閉する。**
 * 開いたときの見た目は幅によらず 1 通りである。
 *
 * ログイン中のユーザ名は、タブレット以上では開閉のボタンの中に三本線と並べ、
 * スマートフォンでは開いたメニューの最上段に出す（ボタンには三本線だけを残す）。
 */
header details {
  position: relative;
  flex: 0 1 auto;
  min-width: 0;
  margin: 0 0 0 auto;
  border: 0;
}

header summary {
  display: flex;
  align-items: center;
  gap: calc(var(--pico-spacing) * 0.5);
  margin: 0;
  padding: calc(var(--pico-spacing) * 0.25);
  color: var(--flory-text);
}

/* ライブラリは開いたときに下余白と文字色を足す。ヘッダの高さと色を開閉で変えない */
header details[open] > summary {
  margin-bottom: 0;
  color: var(--flory-text);
}

/* ライブラリが開閉の印（山形）を右に付ける。三本線のアイコンが印を兼ねる */
header summary::after {
  display: none;
}

header summary > svg {
  flex: 0 0 auto;
  width: 1.75rem;
  height: 1.75rem;
}

/* ユーザ名の文字は所属の表示と同じ大きさ・太さにする。入りきらない分は省略する */
header summary > span,
header details > nav > p {
  overflow: hidden;
  font-size: 1.125rem;
  font-weight: 700;
  white-space: nowrap;
  text-overflow: ellipsis;
}

header summary > span > svg,
header details > nav > p > svg {
  width: 1.125rem;
  height: 1.125rem;
  margin-right: calc(var(--pico-spacing) * 0.375);
  color: var(--flory-text-muted);
  vertical-align: -0.125em;
}

header summary > span {
  display: none;
}

header details > nav > p {
  margin: 0 0 calc(var(--pico-spacing) * 0.5);
  padding-bottom: calc(var(--pico-spacing) * 0.5);
  border-bottom: var(--pico-border-width) solid var(--flory-border);
}

@media (min-width: 768px) {
  header summary {
    padding: calc(var(--pico-spacing) * 0.25) calc(var(--pico-spacing) * 0.5)
      calc(var(--pico-spacing) * 0.25) calc(var(--pico-spacing) * 0.875);
    background: var(--flory-surface-sunken);
    border: var(--pico-border-width) solid var(--flory-border);
    border-radius: 1.5em;
  }

  header summary:hover,
  header details[open] > summary {
    border-color: var(--flory-text-muted);
  }

  header summary > span {
    display: block;
  }

  header summary > svg {
    width: 1.5rem;
    height: 1.5rem;
  }

  header details > nav > p {
    display: none;
  }
}

/* 開いた中身は本文の上に重ねる。ヘッダの高さを変えないため */
header details > nav {
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  min-width: 12rem;
  padding: var(--pico-spacing);
  background: var(--pico-card-background-color);
  border: var(--pico-border-width) solid var(--pico-card-border-color);
  border-radius: var(--pico-border-radius);
  box-shadow: var(--pico-card-box-shadow);
}

/*
 * メニューの項目は行の全体を押せるようにする（文字の上だけでなく、行の余白でも遷移する）。
 * 行どうしは隙間を空けずに接し、押せない帯を作らない。
 */
header details > nav > a {
  display: block;
  margin: 0 calc(var(--pico-spacing) * -0.5);
  padding: calc(var(--pico-spacing) * 0.375) calc(var(--pico-spacing) * 0.5);
  border-radius: var(--pico-border-radius);
}

header details > nav > a:hover,
header details > nav > a:focus-visible {
  background: var(--flory-surface-sunken);
}

header details > nav > form {
  margin-top: calc(var(--pico-spacing) * 0.5);
}

/*
 * 購入者フロントのカートは右端に置く。**`a:last-child` では当てない** ── カートを
 * 置いていない画面ではロゴ自身が該当し、ロゴが右へ寄る。
 */
[data-front='purchase'] header > a + a {
  margin-left: auto;
}

/*
 * カート。**`a`（点数あり）と `span`（点数なし）の両方へ当てる** ── 片方だけに当てると、
 * 点数が入った時点でヘッダの高さが変わる。
 */
[data-front='purchase'] header > a + a {
  position: relative;
}

/* 点数の印。アイコンの肩に重ねる */
[data-front='purchase'] header > a + a > small {
  position: absolute;
  top: -0.2em;
  left: 0.9em;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 1.4em;
  height: 1.4em;
  padding: 0 0.35em;
  background: var(--flory-primary);
  border-radius: 1em;
  color: var(--flory-primary-inverse);
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1;
}

[data-front='purchase'] header > a + a,
[data-front='purchase'] header > span {
  display: flex;
  align-items: center;
  gap: calc(var(--pico-spacing) * 0.25);
  margin-left: auto;
  overflow: visible;
  color: var(--flory-text);
  text-decoration: none;
}

[data-front='purchase'] header > a + a > svg,
[data-front='purchase'] header > span > svg {
  flex: 0 0 auto;
  width: 1.5rem;
  height: 1.5rem;
}

header form {
  display: inline;
  margin: 0;
}

/* ヘッダの高さを詰める。**色ではなく余白の変数を差し替える**（上と同じ理由） */
header button {
  --pico-form-element-spacing-vertical: 0.5rem;
  --pico-form-element-spacing-horizontal: 1rem;
}

/* ------------------------------------------------------------------ *
 * 本文
 * ------------------------------------------------------------------ */

/* 画面の説明文は操作対象と読み分けられるよう控えめにする */
main > p,
main > ul {
  color: var(--pico-muted-color);
}

/* 印刷するのは本文だけである。外枠と画面間の導線を紙に出さない */
@media print {
  body > header,
  body > footer,
  main > nav {
    display: none;
  }
}

/* ------------------------------------------------------------------ *
 * フォーム
 *
 * 画面の主役であるフォーム（`main` の直下）だけを格子に並べる。一覧の中にある
 * 1 ボタンのフォーム（`td form`）は別に扱う。**同じ `form` でも役割が違うため**である。
 * ------------------------------------------------------------------ */

main > form {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--pico-spacing);
  max-width: 520px;
  padding: var(--pico-block-spacing-vertical)
    var(--pico-block-spacing-horizontal);
  background: var(--pico-card-background-color);
  border: var(--pico-border-width) solid var(--pico-card-border-color);
  border-radius: var(--pico-border-radius);
}

/*
 * 項目が多いフォームだけを複数列にする。
 *
 * ログイン（2 項目）と、テナント登録（11 項目）を同じ列数で並べると、どちらかが必ず読みにくい。
 * **項目数で切り替える**（6 個目の項目があるかどうかを見る）。クラス名を足さずに済ませるための書き方。
 *
 * `:has()` が使えない環境では 1 列のまま表示される。**崩れる側ではなく、狭い側に倒れる。**
 */
main > form:has(> div:nth-of-type(6)) {
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  max-width: none;
}

/*
 * 管理画面はタブレット以上の段で、入力の器を版面いっぱいに広げ、項目を横に並べる
 * （項目の数によらない）。送信ボタンは行の幅いっぱいに伸ばさず、左に寄せる。
 */
@media (min-width: 768px) {
  [data-front='console'] main > form {
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    max-width: none;
  }

  /*
   * ボタンと戻る導線は新しい行の 1 列目に置く。**行の全体に渡すと空いた列を畳めず**、
   * 項目の少ないフォームで版面の右側が空く（`auto-fit` は何も置かれていない列だけを畳む）。
   */
  [data-front='console'] main > form > button,
  [data-front='console'] main > form > a {
    grid-column: 1 / auto;
  }

  [data-front='console'] main > form > button {
    justify-self: start;
    width: auto;
    min-width: 12rem;
  }
}

/*
 * 項目の行（`field` を束ねた `div`）。並べ方を画面で決めたいときに、行ごとに束ねる。
 * タブレット以上では行が格子の 1 行を占め、行の中の項目を等分して横に並べる。
 */
[data-front='console'] main > form > div:not(.field):has(> .field) {
  display: grid;
  gap: var(--pico-spacing);
}

[data-front='console'] main > form > div:not(.field) > div.field > :last-child {
  margin-bottom: 0;
}

@media (min-width: 768px) {
  [data-front='console'] main > form > div:not(.field):has(> .field) {
    grid-column: 1 / -1;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  }

  /* 複数行の入力欄は 1 行を占める（隣の項目の行まで縦に伸ばさない） */
  [data-front='console'] main > form > div.field:has(> textarea) {
    grid-column: 1 / -1;
  }

  /* 項目のまとまり（`fieldset`）も 1 行を占め、中の項目の行はフォームの直下の行と同じに並べる */
  [data-front='console']
    main
    > form
    > fieldset:has(> div:not(.field) > .field) {
    grid-column: 1 / -1;
  }

  [data-front='console']
    main
    > form
    > fieldset
    > div:not(.field):has(> .field) {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--pico-spacing);
    margin-bottom: var(--pico-spacing);
  }
}

/* チェックボックスの項目は、説明をラベルの行に流し込まない */
[data-front='console']
  main
  > form
  div.field
  > label:has(> input[type='checkbox']) {
  display: block;
}

/*
 * チェックボックスの補足は `label` の後ろに続くため、ライブラリが入力欄の補足に当てる見た目
 * （`input + small`）が効かない。他の項目の補足とそろえ、折り返しは文節の切れ目に寄せる。
 */
[data-front='console']
  main
  > form
  div.field
  > label:has(> input[type='checkbox'])
  + small {
  display: block;
  margin-top: calc(var(--pico-spacing) * -0.5);
  color: var(--pico-muted-color);
  word-break: auto-phrase;
}

/* 隠しフィールド（CSRF トークン）は格子の枠を 1 つ消費してしまうため、並びから外す */
main > form > input[type='hidden'] {
  display: none;
}

/* 送信ボタンと戻る導線は行いっぱいに置く（入力欄と混ざると押し間違える） */
main > form > button,
main > form > a {
  grid-column: 1 / -1;
}

main > form > a {
  justify-self: start;
}

/* 項目のまとまりの下余白は格子の gap に任せる（Pico が入力欄に付ける余白と二重にしない） */
main > form > div > :last-child {
  margin-bottom: 0;
}

/* 補足文（help_text）は入力欄より控えめにする */
main > form > div > p {
  margin: calc(var(--pico-spacing) * 0.25) 0 0;
  color: var(--pico-muted-color);
  font-size: 0.875em;
}

/* 管理画面の検索条件は、幅に余裕がある限り横に並べる。**項目の数では切り替えない** */
[data-front='console'] main > form[method='get'] {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  max-width: none;
  margin-bottom: var(--pico-spacing);
}

[data-front='console'] main > form[method='get'] > div {
  flex: 1 1 10rem;
}

/* ライブラリは送信ボタンを行の幅いっぱいに広げる。条件と同じ行に置くため文字の幅に戻す */
[data-front='console'] main > form[method='get'] > button {
  flex: 0 0 auto;
  align-self: flex-end;
  width: auto;
  margin-bottom: 0;
}

/* ------------------------------------------------------------------ *
 * フッター（購入者フロント）
 *
 * Pico は `body > footer` に余白を与えるが、並べ方は決めない。
 * ------------------------------------------------------------------ */

/*
 * **内容が短くてもフッターを画面の下端に置く。** 内容が長いときは普通に流れる
 * （画面へ貼り付けない ── 貼り付けるとスマートフォンで縦を常時奪い、
 * 入力中はソフトキーボードと重なる）。
 *
 * `dvh` はアドレスバーの伸縮を含まない高さである。**古い順に並べ、後勝ちで効かせる。**
 */
body[data-front='purchase'] {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

body[data-front='purchase'] > main {
  flex: 1 0 auto;
}

/* 著作権表記は画面の末端に 1 行で置く */
[data-front='purchase'] footer small {
  display: block;
  margin-top: calc(var(--pico-spacing) * 0.5);
  color: var(--flory-text-muted);
  text-align: center;
}

footer nav {
  flex-wrap: wrap;
  gap: var(--pico-spacing);
  justify-content: center;
}

footer nav span {
  color: var(--pico-muted-color);
}

/* ------------------------------------------------------------------ *
 * 一覧
 *
 * 表そのものの見た目は Pico が付ける。ここで扱うのは、一覧の中に置く 1 ボタンの
 * フォームだけである（行の高さを崩さないよう小さく置く）。
 * ------------------------------------------------------------------ */

td form {
  display: inline;
  margin: 0;
}

/* ライブラリは送信ボタンを行の幅いっぱいに広げる。一覧の中では文字の幅に戻す */
[data-front='console'] main td button {
  width: auto;
  margin: 0;
}

/*
 * 一覧の中のボタンは行の 1 操作である。**この範囲だけ primary の値を secondary へ向け、
 * 余白の変数を詰める**（`td button` では Pico の `[type=submit]` に詳細度で負けるため、
 * 色と余白を直接指定しない）。
 */
td button {
  --pico-primary-background: var(--pico-secondary-background);
  --pico-primary-hover-background: var(--pico-secondary-hover-background);
  --pico-primary-border: var(--pico-secondary-border);
  --pico-primary-hover-border: var(--pico-secondary-hover-border);
  --pico-primary-inverse: var(--pico-secondary-inverse);
  --pico-form-element-spacing-vertical: 0.25rem;
  --pico-form-element-spacing-horizontal: 0.6rem;
  --pico-font-size: 0.875rem;
}

/* ------------------------------------------------------------------ *
 * 画像
 *
 * **写真とプリセットのイラストで縦横比が揃わない。** 枠の比率を決めて切り抜き、
 * 並んだときに行の高さが崩れないようにする。
 * ------------------------------------------------------------------ */

/* 管理画面で登録内容を確かめるための画像。**版面を占有させない** */
main img {
  max-width: 15rem;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: var(--pico-border-radius);
}

/* 管理画面の表は列の境目に縦の罫線を引く（ライブラリは行の下線だけを引く） */
[data-front='console'] main table {
  border-top: var(--pico-border-width) solid var(--pico-table-border-color);
}

[data-front='console'] main :is(th, td) {
  border-inline: var(--pico-border-width) solid var(--pico-table-border-color);
}

/*
 * 画面幅が 1024px 未満では、表を版面の幅に収めて横にスクロールさせる。**収めないと表の幅で
 * ページ全体が広がり、表以外（ヘッダ・検索条件）が画面の左に寄って縮む。** セルは折り返さない
 * （1 文字ずつ折り返して行が縦に伸びる）。
 */
@media (max-width: 1023.98px) {
  [data-front='console'] main table {
    display: block;
    overflow-x: auto;
  }

  [data-front='console'] main :is(th, td) {
    white-space: nowrap;
  }
}

/* 見出しの行は罫線を太くせず（ライブラリは太くする）、地色で本文の行と分ける */
[data-front='console'] main thead :is(th, td) {
  --pico-border-width: inherit;
  background-color: var(--flory-surface-sunken);
}

/*
 * 本文の中の導線（`nav`）。戻る・修正へ進むといった操作を促すリンクと、一覧の下のページ送りである。
 * **文中のリンクと見分けるため、枠を付けたボタンの見た目にする。**
 * Pico は `nav` を両端揃えの帯にし、段落と一覧に余白を、リンクに負の余白を付けるため、打ち消す。
 */
[data-front='console'] main nav {
  flex-wrap: wrap;
  justify-content: flex-start;
  align-items: center;
  gap: calc(var(--pico-spacing) * 0.5);
  margin-bottom: var(--pico-spacing);
}

/* 表の中の導線は行の高さを変えない（ボタンと同じ行に並べる） */
[data-front='console'] main td > nav {
  display: inline-flex;
  flex-wrap: nowrap;
  margin: 0;
}

/* フォームの器の直後に置いた戻る導線を、器の枠から離す */
[data-front='console'] main > form + nav {
  margin-top: var(--pico-spacing);
}

/* ページ送りは件数の表示を左、送りの導線を右に置く */
[data-front='console'] main > nav:has(> p) {
  justify-content: space-between;
}

[data-front='console'] main nav > p,
[data-front='console'] main nav > ul {
  margin: 0;
}

[data-front='console'] main nav li {
  padding: 0 0 0 calc(var(--pico-spacing) * 0.5);
}

[data-front='console'] main nav a {
  display: inline-block;
  margin: 0;
  padding: calc(var(--pico-spacing) * 0.375) var(--pico-spacing);
  background: var(--flory-surface-raised);
  border: var(--pico-border-width) solid var(--flory-primary);
  border-radius: var(--pico-border-radius);
  color: var(--flory-primary);
  font-size: 0.875rem;
  line-height: 1.5;
  text-decoration: none;
}

[data-front='console'] main nav a:hover,
[data-front='console'] main nav a:focus-visible {
  background: var(--flory-primary);
  color: var(--flory-primary-inverse);
}

/*
 * 見出しの横に、表示した時点と更新の導線を並べる（運営ホームのやることリスト）。
 * 画面幅が狭いときは、更新の導線をアイコンだけにする（名前は `aria-label` が持つ）。
 */
[data-front='console'] main > section > div:has(> h2 + p + nav) {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--pico-spacing) * 0.75);
  margin: calc(var(--pico-spacing) * 2) 0;
}

[data-front='console']
  main
  > section
  > div:has(> h2 + p + nav)
  > :is(h2, p, nav) {
  margin: 0;
  white-space: nowrap;
}

[data-front='console'] main > section > div:has(> h2 + p + nav) > p {
  color: var(--flory-text-muted);
  font-size: 0.875rem;
}

[data-front='console'] main > section > div:has(> h2 + p + nav) a > svg {
  width: 1.125rem;
  height: 1.125rem;
  margin-right: calc(var(--pico-spacing) * 0.375);
  vertical-align: -0.2em;
}

@media (max-width: 767.98px) {
  [data-front='console'] main > section > div:has(> h2 + p + nav) {
    flex-wrap: nowrap;
    gap: calc(var(--pico-spacing) * 0.5);
  }

  [data-front='console'] main > section > div:has(> h2 + p + nav) a > span {
    display: none;
  }

  [data-front='console'] main > section > div:has(> h2 + p + nav) > h2 {
    font-size: 1.375rem;
  }

  /* 見出しを小さくした分、配下の小見出しも下げて大小関係を保つ */
  [data-front='console'] main > section:has(> div > h2 + p + nav) > h3 {
    font-size: 1.125rem;
  }

  /* 時点は詰めて、それでも入らなければ末尾を省く（ボタンを画面の外へ押し出さない） */
  [data-front='console'] main > section > div:has(> h2 + p + nav) > p {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  [data-front='console'] main > section > div:has(> h2 + p + nav) a {
    padding-inline: calc(var(--pico-spacing) * 0.5);
  }

  [data-front='console'] main > section > div:has(> h2 + p + nav) a > svg {
    margin-right: 0;
  }
}

/* ------------------------------------------------------------------ *
 * 唯一のクラス指定
 *
 * **要素では表せない差だけをクラスで書く。** ここ以外にクラス名を置かない。
 *
 * フォームの部品（`field` で始まるもの）はこの例外である。**入力欄の HTML を画面
 * テンプレートに書く**ため、器と印を要素だけでは区別できない（`ADR-0016`）。
 * ------------------------------------------------------------------ */

/*
 * 1 項目の器。ラベル・入力欄・エラー・補足をまとめる。
 * **ラベルと入力欄を 1 つの item にまとめる** ── 別々にすると、折り返しでラベルと
 * その欄が別の行に分かれる（どの欄の名前かが読み取れなくなる）。
 */
[data-front='purchase'] main > form[method='get'] > .field {
  flex: 1 1 12rem;
}

[data-front='purchase'] main > form > .field,
[data-front='entrance'] main > form > .field {
  margin-bottom: 0;
}

[data-front='purchase'] main > form > div.field > label,
[data-front='purchase'] main > form > fieldset.field > legend,
[data-front='entrance'] main > form > div.field > label {
  display: inline-block;
  font-weight: var(--pico-form-label-font-weight);
}

/* 選択肢は横に並べる。**隣の選択肢と 8px 以上離す** */
[data-front='purchase'] main > form > fieldset.field {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--pico-spacing) * 0.5) var(--pico-spacing);
  align-items: center;
}

/* 項目名とエラーは行を分ける（選択肢と同じ行に混ぜない） */
[data-front='purchase'] main > form > fieldset.field > legend,
[data-front='purchase'] main > form > fieldset.field > .field__error {
  flex: 0 0 100%;
}

[data-front='purchase'] main > form > fieldset.field > label {
  display: inline-flex;
  gap: calc(var(--pico-spacing) * 0.5);
  align-items: center;
  margin-bottom: 0;
}

/*
 * 補足。**ライブラリは入力欄が不正なとき、後ろに続く `small` を赤で描く。**
 * 補足はエラーではないため、色を戻す。
 */
[data-front='purchase'] main > form > .field > small:not(.field__optional),
[data-front='entrance'] main > form > .field > small:not(.field__optional) {
  display: block;
  color: var(--pico-muted-color);
  font-size: 0.875em;
}

/* 任意の印。項目名の脇に小さく置く */
.field__optional {
  margin-left: calc(var(--pico-spacing) * 0.25);
}

/*
 * 管理画面でも印を項目名と同じ行に置く。**ライブラリは `label` と `small` をどちらも
 * ブロックにする**ため、印の有無で入力欄の高さが項目ごとにずれる。
 */
[data-front='console'] main > form div.field > label {
  display: inline-block;
}

[data-front='console'] main > form div.field > .field__optional {
  display: inline-block;
  width: auto;
  margin-top: 0;
  margin-bottom: 0;
}

/* その項目のエラー。**入力欄の直下に置く**（どの欄を直すのかを離さない） */
.field__error {
  margin: calc(var(--pico-spacing) * 0.25) 0 0;
  color: var(--pico-del-color);
  font-size: 0.875em;
}

.message {
  margin-bottom: calc(var(--pico-spacing) * 0.5);
  padding: calc(var(--pico-spacing) * 0.5) var(--pico-spacing);
  background: var(--pico-card-sectioning-background-color);
  border: var(--pico-border-width) solid var(--pico-card-border-color);
  border-radius: var(--pico-border-radius);
}

/* 知らせは深刻度ごとに地色を付け、本文と見分ける */
.message--info,
.message--success {
  background: var(--flory-message-info);
  border-color: var(--flory-message-info-border);
}

.message--warning {
  background: var(--flory-message-warning);
  border-color: var(--flory-message-warning-text);
  color: var(--flory-message-warning-text);
}

.message--error {
  background: var(--flory-message-error);
  border-color: var(--flory-message-error-text);
  color: var(--flory-message-error-text);
}

/* 受注ステータスの印。**色だけで意味を伝えない** ── 状態の名前を必ず文字で出す */
.status {
  display: inline-block;
  padding: 0.125em 0.75em;
  border-radius: 1em;
  font-size: 0.875em;
  font-weight: 700;
  line-height: 1.5;
  white-space: nowrap;
}

.status--unprocessed {
  background: var(--flory-status-unprocessed);
  color: var(--flory-status-unprocessed-text);
}

.status--on_hold {
  background: var(--flory-status-on-hold);
  color: var(--flory-status-on-hold-text);
}

.status--confirmed {
  background: var(--flory-status-confirmed);
  color: var(--flory-status-confirmed-text);
}

.status--rejected {
  background: var(--flory-status-rejected);
  color: var(--flory-status-rejected-text);
}

.status--auto_cancelled,
.status--cancelled {
  background: var(--flory-status-cancelled);
  color: var(--flory-status-cancelled-text);
}

.status--refunded {
  background: var(--flory-status-refunded);
  color: var(--flory-status-refunded-text);
}

/* 消費税率の適用の状態（SC-222） */
.status--tax_current {
  background: var(--flory-status-confirmed);
  color: var(--flory-status-confirmed-text);
}

.status--tax_scheduled {
  background: var(--flory-status-on-hold);
  color: var(--flory-status-on-hold-text);
}

.status--tax_past {
  background: var(--flory-status-cancelled);
  color: var(--flory-status-cancelled-text);
}

/* 発注ステータス（取消・中止の漏れに残るもの） */
.status--unconfirmed {
  background: var(--flory-status-unprocessed);
  color: var(--flory-status-unprocessed-text);
}

.status--accepted {
  background: var(--flory-status-on-hold);
  color: var(--flory-status-on-hold-text);
}

/* ユーザ・招待の状態 */
.status--active {
  background: var(--flory-status-confirmed);
  color: var(--flory-status-confirmed-text);
}

.status--inactive,
.status--expired {
  background: var(--flory-status-cancelled);
  color: var(--flory-status-cancelled-text);
}

/* テナント・生花担当組織の状態（SC-211 SC-214）。有効と否認は上の印を使い回す */
.status--pending {
  background: var(--flory-status-unprocessed);
  color: var(--flory-status-unprocessed-text);
}

.status--approved {
  background: var(--flory-status-confirmed);
  color: var(--flory-status-confirmed-text);
}

.status--suspended {
  background: var(--flory-status-cancelled);
  color: var(--flory-status-cancelled-text);
}

/*
 * 受付期間の外にある商品。**色だけで意味を伝えない** ── 選べない理由は必ず文言で出す。
 * **文字は薄めない**（コントラスト比を落とさない）。薄めるのは写真だけである。
 * **購入者フロントにだけ効かせる。**
 */
/*
 * **地色で塗り分けない** ── 並べたときにそのカードだけ枠が消える。枠の線で示す。
 */
[data-front='purchase'] main article.product--unavailable {
  border: var(--pico-border-width) dashed var(--pico-muted-border-color);
  box-shadow: none;
}

/* 選べない理由。**説明文と同じ体裁にしない**（読み飛ばされる） */
[data-front='purchase'] main article.product--unavailable > p:last-of-type {
  padding: calc(var(--pico-spacing) * 0.5);
  background: var(--flory-surface);
  border-radius: var(--pico-border-radius);
  color: var(--flory-text);
}

[data-front='purchase'] main article.product--unavailable img {
  filter: grayscale(1);
}

/* ------------------------------------------------------------------ *
 * 購入者フロント
 *
 * **`data-front` は 3 枚のレイアウトだけが埋める**（`templates/layouts/`）。
 * 画面テンプレートは埋めない（`make review_lint` の `template-layout` が検出する）。
 *
 * 管理画面と土台を分けるのは、購入者フロントが**スマートフォンを主とし、指で操作される**
 * ためである。同じ要素でも置かれている場所で役割が違う場合と同じ扱いで、セレクタで書き分ける。
 *
 * **入口（`entrance`）も同じ土台に従う**（`docs/spec/10_web_ui.md`「入口の画面規約」）。
 * ------------------------------------------------------------------ */

/*
 * 指で操作するときだけ対象を大きくする。**幅で判定しない** ── タブレットを横向きにすると
 * 幅は PC と同じになるが、操作しているのは指である。
 */
@media (pointer: coarse) {
  [data-front='purchase'] button,
  [data-front='purchase'] [type='submit'],
  [data-front='purchase'] select,
  [data-front='purchase'] main nav ul a,
  [data-front='purchase'] main article > h2 > a,
  [data-front='purchase'] main article > p > a,
  [data-front='purchase'] main > p > a,
  [data-front='purchase'] main > nav > ol > li > a,
  [data-front='purchase'] main > form > fieldset.field > label,
  [data-front='purchase'] main > details > summary,
  [data-front='entrance'] button,
  [data-front='entrance'] main > p > a,
  [data-front='entrance'] main > ul > li > a {
    min-width: var(--flory-tap-size);
    min-height: var(--flory-tap-size);
  }

  /*
   * カードの見出しのリンクは当たり判定を `::after` でカード全体へ広げてあるため、ここには入れない。
   */
  [data-front='purchase'] main > p > a,
  [data-front='purchase'] main > nav > ol > li > a,
  [data-front='entrance'] main > p > a,
  [data-front='entrance'] main > ul > li > a {
    display: inline-flex;
    align-items: center;
  }
}

/*
 * iOS Safari は 16px 未満の入力欄にフォーカスすると画面を拡大し、そのまま戻さない。
 * 根の文字サイズが小さい段でも 16px を下回らせない。
 */
[data-front='purchase'] input:not([type='checkbox']):not([type='radio']),
[data-front='purchase'] select,
[data-front='purchase'] textarea,
[data-front='entrance'] input:not([type='checkbox']):not([type='radio']),
[data-front='entrance'] select,
[data-front='entrance'] textarea {
  font-size: max(1rem, 16px);
}

/* **ライブラリは `[type=search]` の上で `--pico-border-radius` を `5rem` に置き換える**。戻す */
[data-front='purchase'] input[type='search'] {
  --pico-border-radius: 0.25rem;
}

/*
 * フォームは**送る方法で書き分ける**。検索（`get`）は条件を横に並べ、申込の入力（`post`）は
 * 縦に積む。**同じ当て方にすると、広い画面で申込の項目が 1 行に並んで読み取れなくなる。**
 */
[data-front='purchase'] main > form[method='get'] {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--pico-spacing) * 0.5);
  align-items: flex-start;
  max-width: none;
}

/* 申込の入力は 1 列に積む。**1 行の長さを読める幅で止める** */
[data-front='purchase'] main > form[method='post'],
[data-front='entrance'] main > form[method='post'] {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--pico-spacing);
  max-width: 34rem;
}

/* 入力欄を持たないフォーム（送信だけの 1 枚）に器を出さない */
[data-front='purchase'] main > form:not(:has(.field)),
[data-front='entrance'] main > form:not(:has(.field)),
[data-front='console']
  main
  > form:not(:has(input:not([type='hidden']), select, textarea)),
[data-front='console']
  main
  > section
  > form:not(:has(input:not([type='hidden']), select, textarea)) {
  padding: 0;
  background: none;
  border: 0;
}

/* 器を外したボタンは行の幅いっぱいに広げない（ライブラリの既定は 100%、格子も枠いっぱいに伸ばす） */
[data-front='console']
  main
  > form:not(:has(input:not([type='hidden']), select, textarea))
  > button,
[data-front='console']
  main
  > section
  > form:not(:has(input:not([type='hidden']), select, textarea))
  > button {
  justify-self: start;
  width: auto;
}

/*
 * 送信だけのフォームを `div` で束ねたものは、並んだボタンの幅を最も長いものに揃える
 * （格子の列が最も長いボタンの幅になり、ボタンはライブラリの既定で列の幅いっぱいに広がる）。
 */
[data-front='console'] main > div:has(> form),
[data-front='console'] main > section > div:has(> form) {
  display: inline-grid;
  gap: var(--pico-spacing);
  margin-bottom: var(--pico-spacing);
}

[data-front='console'] main > div:has(> form) > form,
[data-front='console'] main > section > div:has(> form) > form {
  margin: 0;
}

[data-front='console'] main > div:has(> form) button,
[data-front='console'] main > section > div:has(> form) button {
  margin: 0;
}

/* 1 項目の器（`field`）の見た目は「唯一のクラス指定」の節が持つ */

[data-front='purchase'] main > form[method='get'] > button {
  flex: 0 0 auto;
}

/*
 * 検索のボタンは**タブレット以上で内容の幅にする** ── ライブラリは `button[type='submit']` に
 * `width: 100%` を当てるため、そのままでは版面の幅の帯になる。
 * 申込の入力のボタンは 1 列の幅いっぱいのままにする（画面の主要な操作である）。
 */
@media (min-width: 768px) {
  [data-front='purchase'] main > form[method='get'] > button {
    /*
     * 同じ行に入力欄が並ぶときは、ラベルではなく入力欄の側へ揃える。
     * **ライブラリはボタンにも下余白を付ける**ため、揃える前に外す（行の間隔は `gap` が持つ）。
     */
    align-self: flex-end;
    width: auto;
    min-width: 14rem;
    margin-bottom: 0;
  }
}

/*
 * 画面の主要な操作。**スマートフォンでは版面いっぱいにする** ── 下に続く戻る導線と
 * 同じ幅で並ぶと、どちらが主かが読み取れない。
 */
[data-front='purchase'] main > p > a[role='button'],
[data-front='purchase'] main article > p > a[role='button'] {
  display: flex;
  justify-content: center;
  width: 100%;
}

@media (min-width: 768px) {
  /* **`flex` のままでは版面いっぱいに伸びる**（親が block のため）。行の中の箱に戻す */
  [data-front='purchase'] main > p > a[role='button'] {
    display: inline-flex;
    width: auto;
    min-width: 18rem;
  }
}

/*
 * 市区などの行き先の一覧。**操作の並びではない**ため、Pico が `nav ul` に与える横並びを
 * 打ち消し、狭い画面では 1 列、広い画面では自動で列を増やす。
 */
/* Pico の `nav` は横並びの帯である。行き先の一覧は縦に積むため、並べ方を戻す */
[data-front='purchase'] main nav {
  display: block;
}

[data-front='purchase'] main nav ul {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: calc(var(--pico-spacing) * 0.5);

  /* Pico は横並びのナビを想定して負の余白を付ける。縦の一覧では枠が本文からはみ出す */
  margin: 0;
  padding: 0;
  list-style: none;
}

/* 行き先が 1 つだけのときは内容の幅に収める（1 本の戻る導線を折り返させない） */
[data-front='purchase'] main nav ul:has(> li:only-child) {
  grid-template-columns: auto;
  justify-content: start;
}

[data-front='purchase'] main nav ul li {
  margin: 0;
  padding: 0;
}

[data-front='purchase'] main nav ul a {
  display: flex;
  align-items: center;
  margin: 0;
  padding: calc(var(--pico-spacing) * 0.5) var(--pico-spacing);
  background: var(--flory-surface-raised);
  border: var(--pico-border-width) solid var(--flory-border);
  border-radius: var(--pico-border-radius);
  text-decoration: none;
}

/*
 * 見出しの列は折り返さない。折り返すと項目名が 2 行になり、値との対応が読み取りにくい。
 * **表は内容の幅に収める** ── 版面いっぱいに広げると、罫線だけが空白の上を伸びる。
 */
[data-front='purchase'] main table {
  width: auto;
  max-width: 100%;
}

/*
 * **割合で指定しない** ── 割合は表の幅を基準に解決するため、幅を内容に合わせる表では
 * 表そのものが版面いっぱいまで広がる。折り返さない最小の幅に潰す。
 */
[data-front='purchase'] main table th {
  width: 1px;
  white-space: nowrap;
}

/*
 * 折り畳み。**ライブラリの既定は版面いっぱいの 1 行**であり、開く印が本文の右端に離れて出る。
 * 押せる 1 つの箱として置く。
 */
[data-front='purchase'] main > details {
  margin-bottom: var(--pico-block-spacing-vertical);
  border-bottom: 0;
}

[data-front='purchase'] main > details > summary {
  display: inline-flex;
  align-items: center;
  padding: calc(var(--pico-spacing) * 0.5) var(--pico-spacing);
  background: var(--flory-surface-raised);
  border: var(--pico-border-width) solid var(--flory-border);
  border-radius: var(--pico-border-radius);
}

/* 検索の条件と、その下に続く結果を離す */
[data-front='purchase'] main > form {
  margin-bottom: var(--pico-block-spacing-vertical);
}

/* 入口のフォームの後ろに続く導線を、フォームの枠から離す */
[data-front='entrance'] main > form {
  margin-bottom: var(--pico-block-spacing-vertical);
}

/* 入口の知らせはフォームと同じ幅に収める */
[data-front='entrance'] main > .message {
  max-width: 34rem;
}

/*
 * 項目名と値の並び。**ライブラリは `dl` の余白しか決めない**ため、素のままだと値が
 * ブラウザ既定の字下げで並び、項目名との対応が読み取れない。
 *
 * 狭い画面では縦に積み、タブレット以上では 2 列にする。管理画面と購入者フロントで同じ見た目にする。
 */
main dl {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
}

main dt {
  padding-top: calc(var(--pico-spacing) * 0.5);
  color: var(--pico-muted-color);
  font-size: 0.875em;
}

main dd {
  margin: 0;
  padding-bottom: calc(var(--pico-spacing) * 0.5);
  border-bottom: var(--pico-border-width) solid var(--flory-border);
}

/* 金額のように読み取ってほしい値は大きく出す */
[data-front='purchase'] main dd > strong,
[data-front='purchase'] main > section > p > strong {
  font-size: 1.25em;
}

@media (min-width: 768px) {
  main dl {
    grid-template-columns: minmax(8rem, max-content) 1fr;
    column-gap: var(--pico-spacing);
  }

  main dt {
    padding-top: calc(var(--pico-spacing) * 0.5);
    border-bottom: var(--pico-border-width) solid var(--flory-border);
  }
}

/* 続けて置いた `dl` は 1 つの並びに見せる（行の区切りを変えたいところで `dl` を分ける） */
main dl:has(+ dl) {
  margin-bottom: 0;
}

/*
 * 管理画面は画面幅が 1024px 以上で、1 行に項目を 2 組ずつ並べる（右半分を空けない）。
 * `dt` と `dd` が必ず対で並ぶため、格子へ順に流すだけで左から右へ読む順に埋まる。
 */
@media (min-width: 1024px) {
  [data-front='console'] main dl {
    grid-template-columns:
      minmax(8rem, max-content) 1fr
      minmax(8rem, max-content) 1fr;
    column-gap: calc(var(--pico-spacing) * 1.5);
  }
}

/*
 * カードの格子。幅に応じて列を増やす。**1 列に固定しない** ── 広い画面で
 * 1 件ずつ縦に並べると、一覧を見渡すのに何度もスクロールすることになる。
 *
 * **同じ `section` でも、葬儀場ページの器は格子ではない。** 中に何を置いたかで書き分ける
 * （カードの格子は `article` を、葬儀場ページの器は写真を直接持つ）。
 *
 * **列の最小幅は `min()` で版面に頭打ちさせる。** `minmax()` の最小値は版面より広くても
 * 縮まないため、そのまま書くと狭い画面で格子が版面からはみ出す（横スクロールが出る）。
 */
[data-front='purchase'] main > section:has(> article) {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(18rem, 100%), 1fr));
  gap: var(--pico-spacing);
}

/*
 * **カード以外は行いっぱいに置く。** 器の子はすべて格子の枠を 1 つ取るため、置かないと
 * 見出しや導線がカードの隣に並ぶ。
 */
[data-front='purchase'] main > section:has(> article) > :not(article) {
  grid-column: 1 / -1;
}

/* 商品のカード（画像の並びを持つ方）。施設のカードより広く取る */
[data-front='purchase'] main > section:has(> article > div) {
  grid-template-columns: repeat(auto-fill, minmax(min(24rem, 100%), 1fr));
}

/*
 * カードの中身を縦に積み、**次へ進む導線をカードの下端へ落とす** ── 落とさないと、
 * 説明文の長さで導線の高さが 1 枚ずつずれる。
 */
[data-front='purchase'] main > section:has(> article) > article {
  display: flex;
  flex-direction: column;
}

[data-front='purchase'] main article > p:last-child:has(> a[role='button']) {
  margin-top: auto;
}

/*
 * 検索結果のカードは、見出しだけでなく**カードのどこを押しても施設のページへ入る。**
 * 読み上げの対象は見出しのリンク 1 つのままにし、当たり判定だけを広げる
 * （リンクを増やすと、1 枚のカードで同じ行き先を繰り返し読み上げることになる）。
 */
[data-front='purchase'] main article:has(> h2 > a) {
  position: relative;
}

[data-front='purchase'] main article > h2 > a::after {
  position: absolute;
  inset: 0;
  content: '';
}

/*
 * カードの中の取り消し。**主要な操作の色を当てない** ── 進む導線より目立つと、
 * 取り消しを押させる画面になる（`td button` と同じ扱いで変数を差し替える）。
 */
[data-front='purchase'] main article form button {
  /* 版面いっぱいにしない。**主要な操作と同じ形にすると、押す先を取り違える** */
  width: auto;

  --pico-primary-background: var(--pico-secondary-background);
  --pico-primary-hover-background: var(--pico-secondary-hover-background);
  --pico-primary-border: var(--pico-secondary-border);
  --pico-primary-hover-border: var(--pico-secondary-hover-border);
  --pico-primary-inverse: var(--pico-secondary-inverse);
  --pico-font-size: 0.875rem;
}

/* 検索結果のカード。見出しから施設のページへ入る */
[data-front='purchase'] main article > h2 {
  margin-bottom: calc(var(--pico-spacing) * 0.5);
  font-size: 1.125rem;
}

[data-front='purchase'] main article > h2 > a {
  text-decoration: none;
}

[data-front='purchase'] main article > p {
  margin-bottom: 0;
  color: var(--flory-text-muted);
}

/* カードから次の画面へ進む導線。**指で押せる大きさを取れるように行の箱を作る** */
[data-front='purchase'] main article > p > a {
  display: inline-flex;
  align-items: center;
}

/*
 * 札。縦書きで組む。
 *
 * **高さを与える** ── 与えないと 1 文字分の幅に潰れて溢れる。
 * **英数字を正立させる** ── 既定では横倒しになる。
 */
[data-front='purchase'] main article > blockquote {
  /*
   * **幅を固定し、行を中央に組む。** 縦書きでは行数がそのまま幅になるため、
   * 内容の幅に任せると名称の有無で札の大きさが変わる。
   */
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 9rem;
  min-height: 12rem;
  margin: 0 0 var(--pico-spacing);
  padding: var(--pico-spacing);
  background: var(--flory-surface);
  border-left: none;
  font-size: 1.125rem;
  writing-mode: vertical-rl;
  text-orientation: upright;
}

[data-front='purchase'] main article > blockquote > p {
  margin: 0;
}

/*
 * 札を出すカードは、**札の隣に商品の写真を置く** ── 札は縦書きで幅を取らないため、
 * 右に余白が残る。
 */
[data-front='purchase'] main > section > article:has(> blockquote) {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  column-gap: var(--pico-spacing);
}

/* 見出し・金額・理由・操作は行いっぱいに置く */
[data-front='purchase']
  main
  > section
  > article:has(> blockquote)
  > :not(blockquote):not(img) {
  grid-column: 1 / -1;
}

/* **切り取らずに収める** ── 供花は丈が分かることに意味がある */
[data-front='purchase'] main > section > article:has(> blockquote) > img {
  width: 100%;
  max-width: none;
  max-height: 16rem;
  margin-bottom: var(--pico-spacing);
  aspect-ratio: auto;
  object-fit: contain;
}

/* 検索結果のカードの画像。**カードの幅いっぱいに置く**（管理画面の上限を打ち消す） */
[data-front='purchase'] main article > img {
  width: 100%;
  max-width: none;
  margin-bottom: calc(var(--pico-spacing) * 0.5);
}

/*
 * 商品のカードの画像。**下の `button` と `small` はテンプレートに無い** ──
 * `static/js/carousel.js` が足す。
 */
[data-front='purchase'] main article > div {
  position: relative;
  margin-bottom: calc(var(--pico-spacing) * 0.5);
}

/* **送りの帯は出さない**（送りはボタンと指で行う。帯が出ると画像の下に線が 1 本増える） */
[data-front='purchase'] main article > div > ul {
  display: flex;
  margin: 0;
  padding: 0;
  overflow-x: auto;
  scrollbar-width: none;
  scroll-snap-type: x mandatory;
  list-style: none;
}

[data-front='purchase'] main article > div > ul::-webkit-scrollbar {
  display: none;
}

[data-front='purchase'] main article > div > ul > li {
  flex: 0 0 100%;
  margin: 0;
  padding: 0;
  scroll-snap-align: center;
}

/*
 * **枚数が違っても高さを揃える。** 揃えないと、カードの格子で行の高さがばらつく。
 * **切り取らずに収める** ── `cover` にするとスタンドの丈が切れ、大きさが読めなくなる。
 */
[data-front='purchase'] main article > div > ul > li > img {
  width: 100%;
  max-width: none;
  aspect-ratio: 4 / 3;
  background: var(--flory-surface);
  object-fit: contain;
}

/* 送りのボタン。**画像が 2 枚以上のときだけ `carousel.js` が足す** */
[data-front='purchase'] main article > div > button {
  position: absolute;
  top: 50%;
  width: var(--flory-tap-size);
  height: var(--flory-tap-size);
  padding: 0;
  background: var(--flory-surface-raised);
  border-color: var(--flory-border);
  border-radius: 50%;
  color: var(--flory-text);
  line-height: 1;
  transform: translateY(-50%);
}

[data-front='purchase'] main article > div > button:first-of-type {
  left: calc(var(--pico-spacing) * 0.25);
}

[data-front='purchase'] main article > div > button:last-of-type {
  right: calc(var(--pico-spacing) * 0.25);
}

/* 何枚目かの表示。**押せる対象ではない**ため、写真の上に小さく重ねる */
[data-front='purchase'] main article > div > small {
  position: absolute;
  right: calc(var(--pico-spacing) * 0.25);
  bottom: calc(var(--pico-spacing) * 0.25);
  padding: 0 calc(var(--pico-spacing) * 0.25);
  background: var(--flory-surface-raised);
  border-radius: var(--pico-border-radius);
  color: var(--flory-text-muted);
}

/*
 * 葬儀場ページは、案内と写真を並べる。**写真を版面いっぱいに出さない** ── 施設の情報より
 * 写真が主役に見えてしまう。
 */
[data-front='purchase'] main > section:has(> img) > img {
  width: 100%;
  max-width: none;
  margin-bottom: var(--pico-spacing);
}

/*
 * タブレット以上では 2 段にし、案内を左・写真を右に置く。
 * **切り替える幅はライブラリが持つ 5 つの値だけを使う**（独自の幅を作らない）。
 */
@media (min-width: 768px) {
  [data-front='purchase'] main > section:has(> img) {
    display: grid;
    grid-template-columns: 1fr minmax(0, 20rem);
    gap: var(--pico-spacing);
  }

  [data-front='purchase'] main > section:has(> img) > img {
    grid-row: 1;
    grid-column: 2;
    margin-bottom: 0;
  }

  [data-front='purchase'] main > section:has(> img) > div {
    grid-row: 1;
    grid-column: 1;
  }
}

/*
 * 注文の入力の画面は、**内容を 1 列にして版面の中央へ寄せる**。1 行の長さを読める幅で
 * 止めているため、広い画面では左端に寄って右が空く。
 *
 * **商品を選ぶ画面は対象にしない** ── カードの格子は版面いっぱいを使う。
 */
@media (min-width: 1280px) {
  [data-front='purchase'] main:has(> form[method='post']) > *,
  [data-front='purchase'] main:has(> section > article > blockquote) > * {
    max-width: 46rem;
    margin-inline: auto;
  }

  /*
   * 葬儀場ページは案内と写真を半々にする。**写真の欄を固定の幅で置くと、版面が広い段では
   * 写真だけが小さく残る**（案内の側は内容の幅で足りてしまう）。
   */
  [data-front='purchase'] main > section:has(> img) {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  /* 札のカードは中身の量に合わせて幅を止める。**列の左端に揃える**（下の導線と縁を合わせる） */
  [data-front='purchase']
    main:has(> section > article > blockquote)
    > section
    > article {
    max-width: 28rem;
    justify-self: start;
  }

  /*
   * 札のカードは**空いた列を畳む**。畳まないと、1 枚のときに列の幅のまま左へ寄り、
   * 右が空く。
   */
  [data-front='purchase']
    main:has(> section > article > blockquote)
    > section:has(> article) {
    grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
  }

  /* 選んだ商品の写真は控えめに置く（入力欄を折り返しの下へ押し下げない） */
  [data-front='purchase']
    main:has(> form[method='post'])
    article
    > div
    > ul
    > li
    > img {
    max-height: 16rem;
  }
}

/*
 * 手順の現在地。**12 枚のフローで迷子にしないために常に出す。**
 * 現在地は `aria-current="step"` が示す（色だけで伝えない）。
 */
[data-front='purchase'] main > nav > ol {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--pico-spacing) * 0.5);
  padding: 0;
  color: var(--flory-text-muted);
  font-size: 0.875rem;
  list-style: none;
}

/*
 * 段の番号を添える。**語を並べるだけでは手順に見えない**（画面の行き先の一覧と区別が付かない）。
 */
[data-front='purchase'] main > nav > ol {
  counter-reset: order-step;
}

[data-front='purchase'] main > nav > ol > li {
  display: flex;
  gap: calc(var(--pico-spacing) * 0.25);
  align-items: center;
  counter-increment: order-step;
}

[data-front='purchase'] main > nav > ol > li::before {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.5em;
  height: 1.5em;
  background: var(--flory-surface-raised);
  border: var(--pico-border-width) solid var(--flory-border);
  border-radius: 50%;
  content: counter(order-step);
  font-size: 0.875em;
}

[data-front='purchase'] main > nav > ol > li > a {
  color: inherit;
}

[data-front='purchase'] main > nav > ol > li[aria-current='step'] {
  color: var(--flory-primary);
  font-weight: 700;
}

[data-front='purchase'] main > nav > ol > li[aria-current='step']::before {
  background: var(--flory-primary);
  border-color: var(--flory-primary);
  color: var(--flory-primary-inverse);
}

/*
 * 通り過ぎた段。**現在地より前にあることを `:has()` で見る** ── 済んだかどうかを表す印を
 * テンプレートへ足さずに済ませる。
 */
[data-front='purchase']
  main
  > nav
  > ol
  > li:has(~ li[aria-current='step'])::before {
  background: var(--flory-border);
  border-color: var(--flory-border);
  color: var(--flory-text-muted);
}

/*
 * 狭い画面では段の一覧を畳み、**いま何番目かの 1 行だけを出す**。7 段を並べると 3 行を占め、
 * 画面の上端が手順で埋まる。
 */
[data-front='purchase'] main > nav > p {
  margin-bottom: calc(var(--pico-spacing) * 0.5);
  color: var(--flory-text-muted);
  font-size: 0.875rem;
}

@media (max-width: 767.98px) {
  [data-front='purchase'] main > nav > ol > li:not([aria-current='step']) {
    display: none;
  }

  /*
   * **番号の丸を出さない。** 畳んだ段は箱を持たず、番号を数える対象から外れるため、
   * 現在地の丸には常に 1 が入る。何番目かは上の 1 行が示す。
   */
  [data-front='purchase'] main > nav > ol > li::before {
    display: none;
  }
}

@media (min-width: 768px) {
  [data-front='purchase'] main > nav > p {
    display: none;
  }
}
