/* モバイル */
html {
  font-size: 14px;
}

/* タブレット以上 */
@media (min-width: 768px) {
  html {
    font-size: 15px;
  }
}

/* PC以上 */
@media (min-width: 1200px) {
  html {
    font-size: 16px;
  }
}

/* iPhone Safari は入力欄の文字サイズが16px未満だとフォーカス時に自動ズームするため、
   モバイル・タブレット表示（1200px未満、html が16px未満の範囲）では
   入力系要素の文字サイズを16px以上にする。
   チェックボックス・ラジオはズーム対象外のため除外する */
@media (max-width: 1199px) {
  input:not([type="checkbox"]):not([type="radio"]),
  select,
  textarea,
  select.btn,
  .form-control {
    font-size: 16px;
  }
}

/* ベースフォント
 * デザイントークン（:root）と最小リセットは base.css に定義する */
body {
  font-family: var(--font-family-base);
  line-height: 1.6;
  height: 100svh;
}

/* 一覧を先頭から取り直す操作（プルリフレッシュ・アクティブなナビ再押下）。
   チャット以外の一覧画面だけ、base.htmlの{% block body_class %}で
   付与されるbody.common-list-refresh-pageに応じてブラウザ標準のプルリフレッシュを止める。
   overscroll-behaviorはbodyに指定してもビューポートへ伝播しないため、ルート要素(html)に指定する */
html:has(body.common-list-refresh-page) {
  overscroll-behavior-y: contain;
}

/* common */
::-webkit-scrollbar {
  display: none;
}

/* Safari はボタンの color が未設定だとシステムブルーになるため明示的にリセット */
button {
  color: inherit;
}

/* Chrome, Safari, Edge, Opera */
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-results-button,
input[type="search"]::-webkit-search-results-decoration {
  display: none;
}

/* Internet Explorer */
input[type="text"]::-ms-clear,
input[type="search"]::-ms-clear {
  display: none;
}

input[type="date"] {
  background-color: var(--color-bg-white);
  color: var(--color-text-primary);
  /* Safariのアウトラインを削除する場合 */
  -webkit-appearance: none;
  appearance: none;
  border: 1px solid var(--color-border-muted);
  border-radius: 4px;
  padding: 5px;
}

/* btn デフォルトのフォーカスリング・アクティブ枠を全体無効化 */
.btn:focus:not(:focus-visible),
.btn:active,
.btn:first-child:active {
  outline: none;
  box-shadow: none;
}

.btn:focus-visible {
  outline: 2px solid var(--color-accent-text);
  outline-offset: 2px;
  box-shadow: none;
}

/* btn-primary → 主操作の暗色塗りに統一（アプリアイコンの配色に合わせ、アクセントの金は
   差し色として温存する。白文字は--color-primary-fillに対し9.34:1でAAを満たす）。
   色は --btn-* トークンのみで指定する（generic .btn-*disabled等の状態は
   --btn-disabled-* 未設定時に --btn-* へフォールバックするため、base側の
   トークンのみで:disabled/[disabled]も含め全状態が揃う） */
.btn-primary {
  --btn-bg: var(--color-primary-fill);
  --btn-border-color: var(--color-primary-fill);
  --btn-hover-bg: var(--color-primary-fill);
  --btn-hover-border-color: var(--color-primary-fill);
  --btn-active-bg: var(--color-primary-fill-hover);
  --btn-active-border-color: var(--color-primary-fill-hover);
  --btn-color: var(--color-bg-white);
  --btn-hover-color: var(--color-bg-white);
  --btn-active-color: var(--color-bg-white);
  white-space: nowrap;
  width: auto;
}

/* :active/.active は --btn-active-* トークンのフォールバック（components.css の
   .btn:active, .btn.active）で解決されるため生宣言は不要。:focus と
   .show > .btn-primary.dropdown-toggle は .btn 基底にフォールバック定義が無いため
   ここで生宣言する */
.btn-primary:focus,
.show > .btn-primary.dropdown-toggle {
  background-color: var(--color-primary-fill-hover);
  border-color: var(--color-primary-fill-hover);
  color: var(--color-bg-white);
}

@media (hover: hover) {
  .btn-primary:hover {
    opacity: var(--opacity-hover);
  }
}

.btn-primary:focus-visible {
  outline: 3px solid var(--color-accent-text);
  outline-offset: 2px;
  box-shadow: none;
}

/* btn-outline-primary → btn-primary と同じ主操作の暗色に統一（枠線ボタンでも金は差し色として
   温存し、主従は塗りか枠線かで示す）。ホバー/アクティブは他のボタンと同じくopacityで
   表現し、塗り反転はしない（基底スタイルの色変化を無効化するため既定値のまま固定） */
.btn-outline-primary {
  --btn-color: var(--color-primary-fill);
  --btn-border-color: var(--color-primary-fill);
  --btn-hover-color: var(--color-primary-fill);
  --btn-hover-bg: transparent;
  --btn-hover-border-color: var(--color-primary-fill);
  --btn-active-color: var(--color-primary-fill);
  --btn-active-bg: transparent;
  --btn-active-border-color: var(--color-primary-fill);
  --btn-disabled-color: var(--color-primary-fill);
  --btn-disabled-border-color: var(--color-primary-fill);
}

@media (hover: hover) {
  .btn-outline-primary:hover {
    opacity: var(--opacity-hover);
  }
}

.btn-outline-primary:focus-visible {
  outline: 3px solid var(--color-accent-text);
  outline-offset: 2px;
  box-shadow: none;
}

@media (hover: hover) {
  .btn-neutral:hover {
    opacity: var(--opacity-hover);
  }
}

.btn-neutral:focus-visible,
.btn-subtle:focus-visible {
  outline: 2px solid var(--color-accent-text);
  outline-offset: 2px;
  box-shadow: none;
}

/* 削除ボタン（枠線のみ・くすんだ赤） */
.btn-delete {
  --btn-color: var(--color-danger-muted);
  --btn-border-color: var(--color-danger-muted);
  white-space: nowrap;
  width: auto;
}

@media (hover: hover) {
  .btn-delete:hover {
    opacity: var(--opacity-hover);
  }
}

.btn-delete:focus-visible {
  outline: 2px solid var(--color-danger-muted);
  outline-offset: 2px;
  box-shadow: none;
}

/* ボタン対の幅均一化・間隔（btn-row コンテナ内のみ） */
.btn-row .btn {
  min-width: 120px;
}

.btn-row .btn + .btn {
  margin-left: 12px;
}

/* ── フォーム要素アクセント色（主操作の暗色） ── */

/* ネイティブ form コントロール（ラジオ・チェックボックス・range 等）。選択済み状態は
   主操作と同じ暗色塗りに統一する（アクセントの金は差し色として温存） */
body {
  accent-color: var(--color-primary-fill);
}

/* form-check（チェックボックス・ラジオ）チェック済み状態 */
.form-check-input:checked {
  background-color: var(--color-primary-fill);
  border-color: var(--color-primary-fill);
}

/* form-check フォーカスリング。box-shadowは白背景上のフォーカスリングのため
   --color-accent-textを使う（白背景に対し4.89:1、WCAG 2.2 の1.4.11「3:1」を満たす）。
   border-colorはチェック済み時の塗りと同じ主操作の暗色に揃え、フォーカス中と選択済みで
   枠線の色がずれないようにする。チェック済み+フォーカス時はリングの内側がその暗色塗りに
   直接接するため、内側の境界だけを見ると約2.7:1にとどまるが、この基準が対象とする
   「隣接色」はリング（フォーカス表示の追加分）とその外側にある地の背景との境界であり、
   要素自体の塗りとの境界ではない。外側は白背景で4.89:1を確保できており、他の
   --color-accent-textによる2px枠のフォーカスリング（room.css・settings.css等）も同じ考え方 */
.form-check-input:focus {
  border-color: var(--color-primary-fill);
  box-shadow: 0 0 0 1px var(--color-accent-text);
}

/* テキスト入力・テキストエリア フォーカス */
.form-control:focus {
  border-color: var(--color-accent-text);
  box-shadow: 0 0 0 1px var(--color-accent-text);
  outline: none;
}

/* エラーのある入力欄を枠線色で示す。border-color のみの変更でレイアウトは変えない。
   field_input タグと showFieldError がエラー時に aria-invalid="true" を必ず付与するため、
   それを基準にする */
.form-control[aria-invalid="true"] {
  border-color: var(--color-danger-muted);
}

/* 上の .form-control[aria-invalid="true"] と .form-control:focus は詳細度が同じため、
   フォーカス時はアクセント色に戻るよう明示的に上書きする */
.form-control[aria-invalid="true"]:focus {
  border-color: var(--color-accent-text);
}

/* リンク・その他インタラクティブ要素のフォーカスリング */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--color-accent-text);
  outline-offset: 2px;
  box-shadow: none;
}

/* スピナー */
.loading-overlay {
  position: fixed;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  background: transparent;
  z-index: 999;
}

body.loading #loading {
  display: flex;
}

/* 通信中だけ表示 */
.spinner {
  width: 32px;
  height: 32px;
  border: 3px solid var(--color-border-light);
  border-top-color: var(--color-text-primary);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* header */
header {
  position: fixed;
  margin: 0;
  z-index: 200;
  width: 100%;
  height: var(--header-height);
  top: 0;
  left: 0;
  background: var(--color-bg-white);
  border-bottom: 1px solid var(--color-border-muted);
}

.header-logo {
  display: inline-flex;
  align-items: center;
  position: relative;
  min-height: 32px;
  text-decoration-line: none;
  white-space: nowrap;
}

/* ロゴリンクの見た目の高さ（32px / PC 40px、min-height）はLuxucomのタップ領域基準
   （44px）に満たないため、パターンB（.header-nav-link::after等と同じ、自身の幅
   いっぱい・高さ44px・縦方向中央基準）でタップ領域を広げる。ワードマーク下部の
   金の下線（.header-logo-wordmark::after）とは別要素（.header-logo自身の::after）
   のため衝突しない。幅は自身の幅（ワードマーク「Luxucom」で44pxを上回る）を使うため
   right隣のナビ（.header-nav-link）とは重ならず、高さ44pxはヘッダー本体
   （--header-height、モバイル48px・PC56px）に収まる */
.header-logo::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}

.header-logo-wordmark {
  font-family: var(--font-family-base);
  font-size: 1.2rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  line-height: 1;
  color: var(--color-text-brand);
  /* ::after（下線）の配置基準にする */
  position: relative;
}

/* アプリアイコン（resources/brand/lc-icon.svg）の文字下部にある金の下線を再現する装飾。
   ワードマークは.header-logoリンクの内側にあるが、この下線はリンクの意味を示すもの
   ではなく純粋な装飾のため、コントラスト要件（WCAG 1.4.11）の対象外とする。
   アイコン側の下線がグリフ幅の約70%であるため、その比率に合わせて幅70%にする */
.header-logo-wordmark::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -4px;
  width: 70%;
  height: 2px;
  transform: translateX(-50%);
  background: var(--color-accent);
  border-radius: 9999px;
}

/* PC */
@media (min-width: 768px) {
  .header-logo {
    min-height: 40px;
  }
}

@media (hover: hover) {
  .header-logo:hover {
    opacity: var(--opacity-hover);
  }
}

.header-nav-link {
  position: relative;
  text-decoration: none;
  color: var(--color-text-primary);
  font-weight: 400;
  margin-left: 1.2rem;
}

.header-nav-link:first-child {
  margin-left: 0;
}

/* 768〜1199px：ヘッダー右側のアイコン間隔（--header-icon-gap、22px）は44×44pxの
   タップ領域を重ねない下限のため詰められない（768pxで実測、ロゴ〜ナビ周りが窮屈）。
   間隔（margin-left 1.2rem）ではなく文字サイズを縮めて幅を確保する。ナビ文字÷隣接
   アイコン（--header-icon-size）の比率がタブレット（13.5px/24px≈0.56）とPC
   （16px/28px≈0.57）でほぼ揃うよう0.9remにした。アイコン側も1200pxを境に大きさを
   切り替えている（base.cssの--header-icon-size）ため、同じ境界でナビ文字も切り替える。
   .header-nav-icon-wrap内の<i>は独自のfont-sizeを持たず.header-nav-linkから継承する
   ため、アイコンもこの文字サイズに連動して縮む（意図した挙動）。1200px以上は既定の
   1remのまま（margin-left・:first-childの0はどちらの帯でも変わらない） */
@media (min-width: 768px) and (max-width: 1199px) {
  .header-nav-link {
    font-size: 0.9rem;
  }
}

/* ナビ項目（オープンサロン・オープンギャラリー・プライベートルーム）のタップ判定を
   44pxへ広げる。.common-info-main-action::after と同じ考え方（自身の幅いっぱい・
   高さ44px・縦方向中央基準）で、隣接項目とはmargin-left（1.2rem）で離れているため
   重ならない。::afterの44px枠はヘッダー本体（PC 56px）に収まる */
.header-nav-link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}

/* position: absoluteのcontaining blockは.header-nav-link（position: relative）の
   padding boxで、borderは含まれない。.is-activeはborder-bottom 2pxを持つため、
   50%centerがpadding box基準のまま（border抜きの中心）だと、実際に見えているborder box
   （padding boxよりborder-bottom分だけ下に長い）の中心より1px（=border-bottom/2）
   上にずれ、44pxタップ領域の下端1行を取りこぼす。border-bottom/2だけtopを下げて補正する */
.header-nav-link.is-active::after {
  top: calc(50% + 1px);
}

@media (hover: hover) {
  .header-nav-link:hover {
    text-decoration: none;
    opacity: var(--opacity-hover);
  }
}

/* ここから続くヘッダーナビ・モバイルフッター・通知アイコンの.is-activeは、
   タブ・チップ・トグルのような「コントロールの選択中」ではなく「ページ内ナビゲーションの
   現在地」を示す別の役割のため、選択中の状態ロール名トークン--color-selected-fillではなく
   --color-text-primaryを使う（値は#2f2a22でAAは満たす）。選択中トークンへの集約対象は
   コントロールの選択状態のみで、現在地表示はこの意図的な例外 */
.header-nav-link.is-active {
  color: var(--color-text-primary);
  font-weight: 500;
  border-bottom: 2px solid var(--color-text-primary);
  padding-bottom: 2px;
}

.header-nav-link.is-active i {
  color: inherit;
}

.mobile-footer-item.is-active {
  color: var(--color-text-primary);
  font-weight: 500;
}

.mobile-footer-item.is-active i {
  color: inherit;
}

/* bottom: 0 + height（--mobile-footer-height）のみで構成し、safe-area用paddingを持たない。
   .pwa-banner（common.css内で後述）はbottom: calc(var(--mobile-footer-height) + var(--space-3))
   でこの高さの直上へvar(--space-3)浮かせて配置しており、この前提（高さそのものがフッターの
   全高であること）に依存しているため、将来 safe-area inset分のpaddingをこの要素に足す場合は
   .pwa-banner側の計算も合わせて見直すこと。
   .consent-banner（同意バナー）はこの前提に依存しない。画面下端基準（bottom:
   calc(var(--space-3) + env(safe-area-inset-bottom, 0px))）で浮くため、この高さの直上ではなく
   このナビの帯ごと覆って隠す */
.mobile-footer-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: var(--mobile-footer-height);
  background: var(--color-bg-white);
  border-top: 1px solid var(--color-border-light);
  display: flex;
  justify-content: space-around;
  align-items: center;
  z-index: 200;
  font-size: 11px;
  /* フッター本体はクリック不可にし、子要素リンクのみクリック可能にする */
  pointer-events: none;
}

.mobile-footer-item {
  flex: 1;
  min-width: 48px;
  min-height: var(--mobile-footer-height);
  align-self: stretch;
  text-decoration: none;
  color: var(--color-text-subtle);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  pointer-events: auto;
}

.mobile-footer-label {
  line-height: 1.1;
}

.header-nav-icon-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  margin-right: 4px;
}

.footer-nav-icon-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  font-size: 1rem;
}

.nav-chat-status-unread {
  position: absolute;
  top: -3px;
  right: -6px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: var(--color-accent);
  box-shadow: 0 0 0 2px var(--color-bg-white);
}

/* .nav-chat-status-unread とは異なりアイコン枠の内側に置く。ここはヘルプ・
   ユーザーアイコンと並ぶ fs-3 の大きいアイコン単体リンク（.header-notification-icon
   が position: relative）で、外側へはみ出させるより枠内に収めた方が他アイコンとの
   間隔が揃うため。 */
.nav-notification-unread {
  position: absolute;
  top: 0;
  right: 0;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: var(--color-accent);
  box-shadow: 0 0 0 2px var(--color-bg-white);
}

/* 左右のmargin（--header-icon-gapの半分ずつ）が隣接アイコンとの間隔を作る。
   position: relativeは下の::after（タップ領域拡張）の基準。header.htmlのDOM順は
   通知 → .dropdown(ヘルプ) → .dropdown(ユーザー)で、.header-userの後ろには
   覆う要素が無いためz-indexは不要（下の.header-help-icon, .header-notification-icon
   参照） */
.header-user {
  position: relative;
  display: flex;
  margin: 0 calc(var(--header-icon-gap) / 2);
  padding: 0;
  border-style: none;
}

@media (hover: hover) {
  .header-user:hover,
  .header-help-icon:hover,
  .header-notification-icon:hover,
  .dropdown-menu-icon:hover {
    opacity: var(--opacity-hover);
    background: transparent !important;
  }
}

.header-user-icon {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  object-fit: cover;
}

/* PC */
@media (min-width: 768px) {
  .header-user-icon {
    width: 36px;
    height: 36px;
  }
}

/* ヘッダー右側のアイコン単体リンク（ヘルプ・通知）に共通のスタイル。左右のmargin
   （--header-icon-gapの半分ずつ）が隣接アイコンとの間隔を作る（.header-userと同じ
   考え方）。z-index: 1は、header.htmlのDOM順（通知 → .dropdown(ヘルプ) →
   .dropdown(ユーザー)）でそれぞれの直後に続く.dropdown（components.css、
   position: relative・z-index: auto。通知の直後はヘルプを包む.dropdown、
   ヘルプ自身の直後はユーザーを包む.dropdown）がタップ領域の右端に約0.5px重なって
   前面に出てしまう（タップ領域同士は重なっていない）のを防ぐため。.dropdownより
   高いz-indexを明示し、アイコン本体・::afterとも前面へ出す */
.header-help-icon,
.header-notification-icon {
  position: relative;
  z-index: 1;
  margin: 0 calc(var(--header-icon-gap) / 2);
  padding: 0;
  border-style: none;
}

/* アイコン本体（<i>）のサイズ。以前はutilities.cssの.fs-3を直接付与していたが、
   モバイルだけ24px固定にする必要があり（--header-icon-size、base.css参照）、
   テンプレート側から.fs-3を外しここへ集約した */
.header-help-icon i,
.header-notification-icon i {
  font-size: var(--header-icon-size);
}

/* アイコン単体リンクのため .header-nav-link.is-active の下線は使わず色のみで現在地を示す。
   .btn を併用するため、生の color ではなく --btn-color トークンで指定する（そうしないと
   :hover 時に .btn:hover のフォールバックで既定の文字色へ戻ってしまう） */
.header-notification-icon.is-active {
  --btn-color: var(--color-text-primary);
}

.header-notification-icon.is-active i {
  color: inherit;
}

/* アイコン単体のタップ判定を実寸から44×44pxへ拡張する。通知ベル・ヘルプ・
   ユーザーの3アイコンに中央基準のタップ領域を足す。見た目（実寸・位置）は変えない。
   チャットヘッダー（chat.cssの.chat-header-right-live等）と同じく幅・高さとも
   44px固定の正方形にできるのは、--header-icon-gap（22px）を各アイコンの実寸に
   足すと中心間隔が常に44px以上になり、隣り合う::after同士が重ならないため
   （アイコン実寸の詳細はbase.cssの--header-icon-gap定義コメント参照） */
.header-help-icon::after,
.header-notification-icon::after,
.header-user::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

.dropdown-menu-icon {
  display: flex;
  padding: 0;
  border-style: none;
}

.dropdown-item {
  left: 0;
}

/* position: fixed のヘッダー内のメニューは、ページごとスクロールできない。項目を44pxにした
   ため横向きスマホでは画面を超えるので、高さを画面内に収めてメニュー内でスクロールさせる */
#header .dropdown-menu {
  max-height: calc(100vh - var(--header-height) - 8px);
  max-height: calc(100dvh - var(--header-height) - 8px);
  overflow-y: auto;
}

.dropdown-icon {
  width: 24px;
  text-align: center;
}

.dropdown-copyright {
  font-size: 0.8rem;
}

/* シェアメニュー3項目（サロンで紹介する<a> / リンクをコピー<button> / 他のアプリで共有<button>）。
   <a>と<button>が混在するため、祖先セレクタ（例: .room-header-actions a）による文字サイズ指定では
   一部の項目にしか当たらず、同一メニュー内でサイズが混在してしまう。置き場所に依らず一定サイズに
   なるよう、buildShareMenuItemsHtml（global/common.js）側でこのクラスを明示付与している。
   値は周囲の他メニュー項目（.list-card-dropdown-menu）に揃えている */
.share-menu-item {
  font-size: 0.9rem;
}

.window-close {
  margin: 10px;
  height: 30px;
}

.dropdown-menu .dropdown-item:active,
.dropdown-menu .dropdown-item:focus {
  background-color: transparent !important;
  color: inherit;
  outline: none;
}

@media (hover: hover) {
  .dropdown-menu .dropdown-item:hover {
    opacity: var(--opacity-hover);
    background-color: transparent !important;
  }
}

/* 上の :focus transparent !important より優先させるため !important を付与 */
.dropdown-menu .dropdown-item:focus-visible {
  opacity: var(--opacity-hover) !important;
  background-color: transparent !important;
  outline: 2px solid var(--color-accent-text);
  outline-offset: -2px;
}

nav {
  height: 100%;
  width: 100%;
}

main {
  padding-top: var(--header-height);
  padding-bottom: var(--mobile-footer-main-offset);
  background-color: var(--color-bg-white);
}

/* PC
   iPadはモバイル判定に含まれ768px以上でもバナーが出るため、フッターナビ消滅後もmainの
   padding-bottomを0で打ち消すと末尾のコンテンツがバナーカードの下に隠れる。バナー自身の
   高さ（--pwa-banner-offset）とカード化に伴う浮遊分（--pwa-banner-card-gap。いずれもPWAバナー・
   同意バナーが排他表示のため、表示中の一方をglobal/pwa_install.js・global/analytics_consent.js
   のいずれかが実行時に設定）を確保し、バナー非表示時は両方とも0にフォールバックすることでPCの
   見た目は従来どおりにする */
@media (min-width: 768px) {
  main {
    padding-bottom: calc(var(--pwa-banner-offset, 0px) + var(--pwa-banner-card-gap, 0px));
  }
}

/* 一覧の先頭からの取り直し（プルリフレッシュ）用インジケータ。
   マークアップと、表示・引っ張り量に応じたtransformの制御はresources/static/web/js/common/
   list_refresh.jsとpartials/list_refresh_indicator.htmlが担い、ここでは配置のみを定義する。
   見た目は既存の.spinnerをそのまま使い、新しい見た目は作らない */
.list-refresh-indicator {
  position: fixed;
  top: calc(var(--header-height) + env(safe-area-inset-top, 0px));
  left: 0;
  right: 0;
  z-index: 190;
  display: flex;
  justify-content: center;
  padding-top: var(--space-2);
  pointer-events: none;
}

/* position: relativeは下の::after（タップ領域拡張）の基準。.btnの基本定義
   （components.css）も同じposition: relativeを与えるが、この::afterの基準であることを
   明示するためここにも残している */
.common-close-btn {
  position: relative;
  --btn-color: var(--color-text-muted);
  border: none;
}

.common-close-btn i {
  font-size: 1.5rem;
}

/* アイコン単体ボタンで幅・高さとも44pxに満たないため、パターンA（44×44正方形・
   中央基準）でタップ領域を広げる。見た目（実寸・位置）は変えない */
.common-close-btn::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

@media (hover: hover) {
  .common-close-btn:hover {
    opacity: var(--opacity-hover);
  }
}

.common-close-btn:focus-visible {
  outline: 2px solid var(--color-accent-text);
  outline-offset: 2px;
  box-shadow: none;
}

/* エラーメッセージ */

/* Form/Section Alert 共通コンポーネント */
.form-alert {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-3);
  margin-bottom: var(--space-3);
  border: 1px solid transparent;
  border-radius: var(--radius-base);
}

.form-alert[hidden] {
  display: none;
}

.form-alert-icon {
  flex: none;
  font-size: 1.1rem;
  /* form-alert-message の1行の高さ（body: font-size 1rem, line-height 1.5）に揃え、
     複数行時にアイコンが本文の1行目と同じ位置から描画されるようにする */
  line-height: 1.5rem;
  /* Font Awesome アイコンは本来 vertical-align: -0.125em で文字と光学的に揃うが、
     flexコンテナ内ではvertical-alignが効かないため、同等のオフセットをpadding-topで再現する */
  padding-top: 0.125em;
}

.form-alert-body {
  flex: 1 1 auto;
  min-width: 0;
}

.form-alert-message {
  margin: 0;
  /* line-height は unitless のため祖先の font-size 縮小（例: chat.css の
     .chat-chat-container { font-size: 0.8rem }）を継承すると行高が変わってしまう。
     form-alert-icon の line-height（rem・root基準の絶対値）と一致させるため、
     font-size を root 基準の 1rem に固定して祖先の影響から独立させる */
  font-size: 1rem;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

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

.form-alert--error {
  background-color: var(--color-danger-pale);
  border-color: var(--color-danger-muted);
}

.form-alert--error .form-alert-icon {
  color: var(--color-danger-muted);
}

.form-alert--warning {
  background-color: var(--color-status-upcoming);
  border-color: var(--color-accent-muted);
}

.form-alert--warning .form-alert-icon {
  color: var(--color-accent-muted);
}

.form-alert--info {
  background-color: var(--color-status-inactive);
  border-color: var(--color-border-muted);
}

.form-alert--info .form-alert-icon {
  color: var(--color-border-muted);
}

.form-alert--success {
  background-color: var(--color-status-active);
  border-color: var(--color-success-muted);
}

.form-alert--success .form-alert-icon {
  color: var(--color-success-muted);
}

/* トースト通知（リダイレクト後の Django messages。extra_tags="modal" のみモーダルへ分岐する）
   既存の固定要素の z-index（header/.mobile-footer-nav: 200、.salon-fab: 300、
   .pwa-banner: 2000、.salon-compose-sheet: 2010、.message-modal/.history-modal: 2100）に対し、
   画面上部に固定表示することで下部固定要素（footer nav/FAB/PWAバナー）とは空間的に重ならず、
   z-index はモーダル類より低い 1500 とし、モーダル表示中は自然にモーダルの下に隠れるようにする
   （例外: コレクションの編集シートを開いている間は、collection.css が 2020 へ引き上げる） */
.toast-container {
  position: fixed;
  top: calc(var(--space-3) + env(safe-area-inset-top, 0px));
  left: 0;
  right: 0;
  z-index: 1500;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: 0 0.75rem;
  /* コンテナ自体はクリック不可にし、個々のトースト（閉じるボタン等）のみ操作可能にする */
  pointer-events: none;
}

/* header は position: fixed のため、header が実在するページ（header_off でない）でのみ
   main と同じ高さ分（--header-height）を上端オフセットに加算し、ヘッダーへの潜り込みを防ぐ */
header + .toast-container {
  top: calc(var(--header-height) + var(--space-3) + env(safe-area-inset-top, 0px));
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  width: 100%;
  max-width: 420px;
  padding: var(--space-3);
  border: 1px solid transparent;
  border-radius: var(--radius-base);
  background-color: var(--color-bg-white);
  box-shadow: 0 8px 24px rgba(15, 15, 15, 0.16);
  pointer-events: auto;
  opacity: 1;
  transform: translateY(0);
  transition:
    opacity 0.2s ease,
    transform 0.2s ease;
}

/* PC
   メディアクエリは詳細度を上げないため、基底の .toast ルールより後ろに置く。
   前に置くと max-width: 420px に負けて広がらない */
@media (min-width: 768px) {
  .toast {
    width: fit-content;
    min-width: 420px;
    max-width: 640px;
  }
}

.toast--closing {
  opacity: 0;
  transform: translateY(-8px);
}

@media (prefers-reduced-motion: reduce) {
  .toast {
    transition: none;
  }
}

.toast-icon {
  flex: none;
  font-size: 1.1rem;
  line-height: 1.5rem;
  padding-top: 0.125em;
}

.toast-message {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font-size: 1rem;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.toast-close-btn {
  position: relative;
  flex: none;
  background: none;
  border: none;
  padding: 0;
  margin-left: var(--space-1);
  color: var(--color-text-muted);
  font-size: 0.95rem;
  cursor: pointer;
  line-height: 1.5rem;
}

/* アイコン単体ボタンで幅・高さとも44pxに満たないため、パターンA（44×44正方形・
   中央基準）でタップ領域を広げる。見た目（実寸・位置）は変えない */
.toast-close-btn::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

@media (hover: hover) {
  .toast-close-btn:hover {
    opacity: var(--opacity-hover);
  }
}

.toast--error {
  border-color: var(--color-danger-muted);
}

.toast--error .toast-icon {
  color: var(--color-danger-muted);
}

.toast--warning {
  border-color: var(--color-accent-muted);
}

.toast--warning .toast-icon {
  color: var(--color-accent-muted);
}

.toast--info {
  border-color: var(--color-border-muted);
}

.toast--info .toast-icon {
  color: var(--color-border-muted);
}

.toast--success {
  border-color: var(--color-success-muted);
}

.toast--success .toast-icon {
  color: var(--color-success-muted);
}

/* 上余白は入力欄との間隔。field_error.html も showFieldError も、表示するエラーが
   ある場合にのみ ul を描画するため、常に非空の前提で付けてよい */
ul.errorlist {
  margin: var(--space-1) 0 0;
  padding: 0;
}

ul.errorlist li {
  color: var(--color-danger-muted);
  display: block;
  text-align: left;
  font-size: 0.8rem;
}

ul.infolist {
  margin-top: 5px;
  margin-bottom: 20px;
  padding: 0;
}

ul.infolist li:before {
  content: "* ";
}

ul.infolist li {
  display: block;
  text-align: left;
  font-size: 0.8rem;
}

.label-required {
  color: var(--color-danger-muted);
  font-size: 0.8rem;
}

/* フォーム */

#id_room_name {
  max-width: 100%;
  width: 500px;
}

#id_room_description {
  max-width: 100%;
  width: 500px;
  height: 100%;
  resize: none;
}

#id_user_address {
  max-width: none;
  width: 100%;
}

#id_user_profile {
  width: 100%;
}

#id_nick_name {
  max-width: 100%;
  width: 500px;
}

/* 画面共通 */

.main-common-container {
  max-width: 500px;
  margin: 30px auto;
  padding: 0 20px;
}

/* 認証画面の下部に縦に並べる補助リンクの行（中身は .standalone-link）。
   2行目以降は、隣の行のタップ領域（44px）と重ならないよう間隔を広げる */
.main-common-link-row {
  margin-top: 10px;
}

.main-common-link-row + .main-common-link-row {
  margin-top: 24px;
}

.common-container {
  position: relative;
  border-width: 0;
  border-style: none;
  height: 100%;
  width: 100svw;
  max-width: 760px;
  display: flex;
  flex-direction: column;
}

/* PC */
@media (min-width: 768px) {
  .common-container {
    border-width: 1px;
    border-style: solid;
    border-top: none;
    border-bottom: none;
    /* バナー表示分の退避をmainのpadding-bottomではなくこちらの内側で取る。mainの外側で取ると
       height: 100%の本要素が退避量ぶん短くなり、左右の枠線が画面下端の手前で途切れて見えるため。
       バナーが無いときは0pxに解決されるため、mainから移すだけで見た目は変わらない */
    padding-bottom: calc(var(--pwa-banner-offset, 0px) + var(--pwa-banner-card-gap, 0px));
  }

  /* 上のpadding-bottomと二重に退避しないよう、.common-containerを持つページではmain側を打ち消す。
     .common-containerを持たないページ（chat・gallery・landing_page・live_play・live_stream）は
     base.cssのmainの指定がそのまま効く */
  main:has(> .common-container) {
    padding-bottom: 0;
  }
}

.common-content-container {
  padding: 20px;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}

.common-info-content-container {
  padding: 0 20px;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}

.common-content {
  margin-top: 10px;
  margin-bottom: 10px;
  width: 100%;
  position: relative;
}

.common-edit-content {
  margin-top: 20px;
  margin-bottom: 20px;
  width: 100%;
  position: relative;
}

.edit-delete-action {
  margin: 30px 0;
  padding-bottom: var(--mobile-footer-action-offset);
}

/* PC */
@media (min-width: 768px) {
  .edit-delete-action {
    padding-bottom: 0;
  }
}

/* 編集画面共通 */

.common-container-header {
  position: relative;
  padding-top: 15px;
  padding-bottom: 15px;
  border-bottom: 1px solid var(--color-border-muted);
  box-shadow: 0 3px 5px rgba(0, 0, 0, 0.1);
}

.common-container-header-title {
  display: inline-block;
  margin: 0;
  white-space: nowrap;
  font-size: 1.2rem;
  font-weight: 400;
  line-height: normal;
  color: var(--color-text-primary);
}

.common-container-header-button {
  display: block;
  position: relative;
  text-decoration-line: none;
  font-size: 1rem;
  text-align: center;
  border-radius: 50px;
  margin-left: 20px;
  margin-right: 20px;
}

/* 右上「保存」ボタンの見た目の高さは維持し、タップ判定だけを44px
   （Luxucomのタップ領域の基準）へ広げる（.common-info-main-action::after と同じ
   パターンB）。.common-container-header-button は follow_list 等の空の配置用 div
   でも使われるため、実際にボタンとして機能する .btn-primary との組み合わせに絞る */
.btn-primary.common-container-header-button::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  width: auto; /* .btn 共通の ::after（components.css）の width を打ち消す */
  height: 44px;
  transform: translateY(-50%);
}

/* PC */
@media (min-width: 768px) {
  .common-container-header .common-container-header-title {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
}

@media (max-width: 767px) {
  body:has(.common-mobile-headerless) header,
  body:has(.common-edit-page) header {
    display: none;
  }

  body:has(.common-mobile-headerless) main,
  body:has(.common-edit-page) main {
    padding-top: 0;
  }

  /* header 自体は display: none だが header + .toast-container の隣接セレクタは
     DOM 構造にのみ依存し表示状態を見ないため、main と同様にオフセットを打ち消す */
  body:has(.common-mobile-headerless) header + .toast-container,
  body:has(.common-edit-page) header + .toast-container {
    top: calc(var(--space-3) + env(safe-area-inset-top, 0px));
  }

  /* header自体が非表示のため、インジケータのオフセットもheader分を差し引く */
  body:has(.common-mobile-headerless) .list-refresh-indicator,
  body:has(.common-edit-page) .list-refresh-indicator {
    top: env(safe-area-inset-top, 0px);
  }

  /* .common-slim-header はモバイルで画面タイトルヘッダーを細くする共通クラス。
     編集画面専用の .common-edit-header と見た目のルールを共有する */
  .common-edit-header,
  .common-slim-header {
    display: grid !important;
    /* 左右カラムは 64px 固定だとボタンが内容幅未満に縮み、テキスト周りの余白が潰れるため内容に応じて広がれるようにする */
    grid-template-columns: minmax(64px, auto) minmax(0, 1fr) minmax(64px, auto);
    gap: 6px;
    align-items: center;
    padding: calc(4px + env(safe-area-inset-top)) 10px 4px;
    box-shadow: none;
  }

  .common-edit-header-side {
    min-width: 0;
  }

  .common-edit-header-title-wrap {
    min-width: 0;
  }

  /* グリッドの各カラムが内容幅未満に縮めるようにする（編集画面の
     .common-edit-header-side / -title-wrap と同じ役割） */
  .common-slim-header > div {
    min-width: 0;
  }

  .common-edit-header .common-container-header-title,
  .common-slim-header .common-container-header-title {
    display: block;
    width: 100%;
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.1;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .common-edit-header .common-container-header-button,
  .common-slim-header .common-container-header-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 40px;
    min-height: 40px;
    margin: 0;
    padding: 0 8px;
  }

  .common-edit-header .common-close-btn,
  .common-slim-header .common-close-btn {
    padding: 0;
  }

  .common-edit-header .common-close-btn i,
  .common-slim-header .common-close-btn i {
    font-size: 1.1rem;
  }

  .common-edit-header .btn-primary.common-container-header-button,
  .common-slim-header .btn-primary.common-container-header-button {
    /* 共通ルールの min-width: 40px ではコンテンツ幅を下回りうるため、
       自動最小サイズを明示して padding の余白が潰れないようにする */
    min-width: auto;
    min-height: 0;
    border-radius: 9999px;
    padding: 4px 14px;
    font-size: 0.9rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
  }

  .common-edit-header .btn-primary.common-container-header-button span,
  .common-slim-header .btn-primary.common-container-header-button span {
    line-height: 1.5;
  }
}

.card-container {
  position: relative;
  padding-bottom: 20px;
}

.card-content {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  background: var(--color-bg-white);
  box-shadow: var(--shadow-card);
  transition: var(--transition-hover);
}

/* ルームカードはカード全体を1つのリンクにする（内側にリンクを入れ子にしない） */
.room-card-link {
  display: block;
  color: inherit;
  text-decoration: none;
}

/* タッチ端末でのホバー固着を避けるためホバー可能なデバイスに限定 */
@media (hover: hover) {
  .card-thumb a:hover {
    opacity: var(--opacity-hover);
  }

  /* NFTカードのオーナーリンク（アバター＋名前）のみを対象にする。ルームカードは全体が
     .room-card-link 1本のリンクのため、単純な a:hover だと
     カードのどこにマウスを乗せてもオーナー表示がフェードしてしまう。 */
  .nft-card-user-block a:hover {
    opacity: var(--opacity-hover);
  }
}

.card-content:focus-visible,
.card-content:has(:focus-visible) {
  background: var(--color-bg-hover);
}

@media (prefers-reduced-motion: reduce) {
  .card-content {
    transition: none;
  }
}

.card-thumb {
  position: relative;
  overflow: hidden;
  border-top-left-radius: var(--radius-card);
  border-top-right-radius: var(--radius-card);
}

/* .card-thumb（.ratio）の直接の子として.ratio > *の絶対配置を受け、
   内側のimg/video/動画マークを重ねるための単一ラッパー */
.room-card-media {
  overflow: hidden;
}

.card-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.room-card-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.3s ease;
  /* カードのタップ／クリックはリンクの遷移に委ねる（動画自身は操作対象にしない） */
  pointer-events: none;
}

.room-card-video.is-playing {
  opacity: 1;
}

/* 静止している動画カードのみ左上に表示する小さな動画マーク。
   is-playing付与時は隣接セレクタで非表示にする（再生状態はis-playingを唯一の情報源とする）。 */
.room-card-video-mark {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4px 6px;
  font-size: 0.75rem;
  color: var(--color-bg-white);
  background: rgba(0, 0, 0, 0.55);
  border-radius: var(--radius-pill);
  /* 押下対象にしない（クリック／タップはカード全体のリンクに委ねる） */
  pointer-events: none;
}

.room-card-video.is-playing ~ .room-card-video-mark {
  display: none;
}

.card-title {
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.4;
  margin-bottom: 0.25rem;
  /* OpenSeaリンク時は.card-title-linkがinline-flexになり、空白を含まない長い
     作品名だとbreak-wordではmin-content幅が縮まず折り返せずカード枠を突き抜ける
     ため、min-content自体を縮小するanywhereで確実に折り返す */
  overflow-wrap: anywhere;
}

.card-title-clamp {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1 1 auto;
  min-width: 0;
}

.card-desc {
  font-size: 0.9rem;
  color: var(--color-text-subtle);
  line-height: 1.4;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  word-break: normal;
  word-wrap: break-word;
}

.card-desc-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card-desc-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.8rem;
  white-space: nowrap;
  /* 同一カード内での開閉操作であり外部への遷移ではないため下線は付けない。
     操作要素であることは金色（リンクと同じ配色）とシェブロンアイコンで示す */
  text-decoration: none;
  --btn-color: var(--color-accent-text);
  --btn-hover-color: var(--color-accent-text-hover);
}

/* タイトルのリンクの ::after（高さ 44px）が上のサムネイルへ食い込まないよう、操作メニューの
   有無によらずタイトル行の高さを操作メニュー（32px）に揃える */
.nft-card-title-row {
  min-height: 32px;
}

/* 説明文が空のとき、タイトル行とオーナー・ルームのリンクの間隔を広げ、両者の ::after が
   重ならないようにする（間隔は下の要素の上マージンと相殺され、この値に揃う） */
.card-content .card-desc-area:has(> .card-desc:empty) {
  margin-bottom: 16px;
}

/* NFT カード内の「続きを読む」（btn-link のため .btn 共通の ::after の対象外）。見た目は
   変えず、タップ判定のみ高さ 44px へ広げる。直下のオーナー・ルームのリンクの ::after と
   重ならないよう、操作要素の無い上（説明文）へだけ伸ばす。
   サロンのカード内の同クラスは list_card.css が別に扱う */
.card-content .card-desc-toggle::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 2px;
  height: 44px;
}

@media (hover: hover) {
  .card-desc-toggle:hover {
    opacity: var(--opacity-hover);
  }
}

/* NFTカードのオーナー名もアイコンと同じリンクに含めるため、見た目は変えない */
.nft-card-user-block a {
  color: inherit;
  text-decoration: none;
}

/* オーナー・ルームへのリンクは単独の行のため、見た目は変えずタップ判定のみ高さ 44px へ
   広げる（position: relative は付与側の position-relative クラスが担う）。
   下のいいねボタンの ::after とは .card-footer の padding-top で間隔を確保する */
.nft-card-user-block a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}

.card-user-avatar {
  width: 25px;
  height: 25px;
  border-radius: 50%;
  object-fit: cover;
}

.card-user-text {
  flex: 1 1 auto;
  min-width: 0;
}

.card-user-label {
  font-size: 0.75rem;
  color: var(--color-text-muted);
  line-height: 1.1;
}

.card-user-name {
  font-size: 0.85rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

.card-user-badge-empty {
  background: var(--color-bg-subtle);
  color: var(--color-text-subtle);
  border: 1px solid var(--color-border);
  font-weight: 500;
  border-radius: 9999px;
  padding: 2px 8px;
  font-size: 0.75rem;
}

/* 上の padding は、直上のリンクといいねボタンの ::after が重ならないよう、
   従来の 0.25rem に 10px を足している */
.card-footer {
  border-top: none;
  background: transparent;
  padding: calc(0.25rem + 10px) 0.75rem 0.25rem;
}

.card-like-btn {
  --btn-bg: var(--color-bg-white);
  --btn-border-color: transparent;
  width: 100%;
  font-size: 0.8rem;
  padding-top: 0.25rem;
  padding-bottom: 0.25rem;
}

@media (hover: hover) {
  .card-like-btn:hover {
    opacity: var(--opacity-hover);
  }
}

/* 共通の ::after（.btn、中央基準）を 3px 下へずらし、直上のオーナー・ルームのリンクの
   ::after と重ならないようにする */
.card-like-btn::after {
  top: calc(50% + 3px);
}

.card-like-btn:focus-visible {
  opacity: var(--opacity-hover);
}

.card-heart-icon {
  color: var(--color-text-faint);
}

.card-heart-liked {
  color: var(--color-heart-liked);
}

.card-footer-link {
  margin-top: auto;
}

.card-footer-actions {
  display: inline-flex;
  align-items: center;
}

/* イメージモーダル。PWAスタンドアロンのノッチ・ホームバーに隠れないよう、
   safe-area分の余白を確保する */
.image-modal {
  display: none;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px)
    env(safe-area-inset-left, 0px);
  background-color: rgba(0, 0, 0, 0.8);
  z-index: 999;
}

/* 横向きスマホなど縦が足りない画面でも、内側をスクロールして調整ボタンに届くようにする */
.image-modal-content {
  width: min(92vw, 720px);
  max-height: 100%;
  overflow-y: auto;
  text-align: center;
  background-color: var(--color-bg-white);
}

/* トリミングの操作領域。枠は固定し、画像側をドラッグ・ピンチ・ホイールで動かす。
   ブラウザ標準のスクロール・ズームに奪われないよう touch-action を無効にする */
.crop-stage {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: min(60vh, 480px);
  height: min(60svh, 480px);
  background-color: var(--color-bg-white);
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  cursor: grab;
}

.crop-stage:active {
  cursor: grabbing;
}

/* 位置・サイズ・拡大率は image_cropper.js が transform とサイズで指定する */
.crop-image {
  position: absolute;
  top: 0;
  left: 0;
  max-width: none;
  max-height: none;
  transform-origin: 0 0;
}

/* 切り抜き枠。位置とサイズは image_cropper.js が指定する。枠の外側は白基調のマスクで覆い、
   box-shadow の広がりで表現するため、ステージの大きさに依らず枠外全体を覆える */
.crop-frame {
  position: absolute;
  pointer-events: none;
  box-shadow:
    0 0 0 1px var(--color-border-muted),
    0 0 0 100vmax var(--color-bg-white-translucent);
}

/* アバター（円形に切り抜く画像）用 */
.crop-frame-circle {
  border-radius: 50%;
}

/* 切り抜き範囲の調整ボタン群（ドラッグ・ピンチ操作の代替）。
   6個のアイコンボタンをプレビュー下に並べ、幅が足りない画面ではflex-wrapで折り返す */
.image-modal-adjust-group {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 16px;
  padding: 12px 16px;
}

/* .pwa-dismiss-btn::afterと同じ考え方で、見た目の高さはbtn-smのまま維持し、
   タップ判定のみ44×44pxへ拡大する。btn-smのアイコン単体ボタンは実寸30px前後のため、
   ::afterを中央配置する。.image-modal-adjust-groupのgap(16px)は
   (44px - 30px) / 2 = 7pxの張り出しの2倍(14px)を上回るため、隣接ボタンの::after同士は重ならない */
.image-modal-adjust-btn {
  position: relative;
}

.image-modal-adjust-btn::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

/* メッセージモーダル */
.message-modal {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0.6);
  z-index: 2100;
  justify-content: center;
  align-items: center;
}

.message-modal:not([hidden]) {
  display: flex;
}

.message-modal-content {
  background-color: var(--color-bg-white);
  padding: 24px;
  max-width: 480px;
  width: 90%;
  border-radius: 12px;
  box-shadow: 0 18px 40px rgba(15, 15, 15, 0.12);
}

.message-modal-message {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.message-modal-icon {
  display: flex;
  color: var(--color-text-faint);
  font-size: 1.5rem;
  align-self: center;
  align-items: center;
  justify-content: center;
}

.message-modal-message-body {
  flex: 1 1 auto;
  min-width: 0;
  margin-top: 0.5rem;
  overflow-wrap: anywhere;
}

.message-modal-guide-link {
  color: var(--color-text-muted);
  text-decoration: underline;
  text-decoration-color: var(--color-text-muted-translucent);
}

.message-modal-guide-link:hover {
  color: var(--color-text-muted);
  text-decoration: underline;
  text-decoration-color: var(--color-text-muted);
}

.message-modal-footer {
  display: flex;
  justify-content: center;
  margin-top: 0.8rem;
}

.message-modal-footer button {
  min-width: 6rem;
}

.message-modal-cancel-btn {
  margin-right: 12px;
}

/* ログイン誘導用テキストリンク。色・下線はbase.cssの`a`既定（--color-link、金）を継承する。
   widthをfit-contentにしmargin autoで中央寄せすることで、ボックス幅をテキスト幅に一致させ、
   リンク以外の余白が誤タップの当たり判定にならないようにする。
   .salon-disabled-overlay-signup-btn::after と同じ考え方で、見た目の高さは文字サイズのまま維持し
   タップ判定のみ44px（Luxucomのタップ領域の基準）へ広げる。幅は自身の幅いっぱい（left/right: 0）。
   直上に #id_message_modal_close_btn のタップ領域があり、縦中央基準（上下均等にはみ出す形）だと
   上側のタップ領域とめり込むため、自身の上端を基準に下方向のみへ広げる（上へは張り出さない） */
.message-modal-login-link {
  position: relative;
  width: fit-content;
  margin: 0.8rem auto 0;
  font-size: 0.875rem;
}

.message-modal-login-link:not([hidden]) {
  display: block;
}

.message-modal-login-link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 44px;
}

@media (hover: hover) {
  .message-modal-login-link:hover {
    opacity: var(--opacity-hover);
  }
}

.feed-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  background: var(--color-bg-light);
  color: var(--color-text-primary);
  font-size: 0.8rem;
  text-decoration: none;
  font-weight: 500;
  white-space: nowrap;
  flex-shrink: 0;
}

/* ボタンの見た目の高さ（31〜33px前後）は維持し、タップ判定だけを44px
   （Luxucomのタップ領域の基準）へ広げる（.common-info-main-action::after と同じ
   パターンB。実測幅が常に44pxを上回るため left/right: 0 で足りる）。上下に
   約5〜7pxはみ出すため、親コンテナ側（.feed-tabs）でクリップを避けるpadding/margin
   を用意している */
.feed-tab::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}

/* PC */
@media (min-width: 768px) {
  .feed-tab {
    font-size: 0.9rem;
  }
}

@media (hover: hover) {
  .feed-tab:hover {
    opacity: var(--opacity-hover);
    text-decoration: none;
  }
}

.feed-tab.is-active {
  background: var(--color-selected-fill);
  color: var(--color-selected-text);
}

/* .overflow-x-auto（utilities.css）はoverflow-x: auto指定に伴い、CSS仕様上
   overflow-yもautoとして計算される（overflow-xが可視以外の値だとoverflow-yの
   visibleがautoへ変換される）。.feed-tab::afterが上下に約5〜7pxはみ出すタップ
   領域を持つため、そのままだとクリップまたは縦スクロール化してしまう。上下に
   padding 8pxを足してクリップを避ける。
   上側はこの要素が.rowの最初の子（gy-2）で、.row側の margin-top: calc(-1 * --gutter-y)
   と.row > *側の margin-top: var(--gutter-y)（utilities.css）が打ち消し合い元々の
   実効余白が0のため、padding-top 8pxだけを打ち消せばよい。ただし.feed-tabsは
   .row > *と同じ詳細度（クラス1つ）でutilities.cssより後に読み込まれるcommon.css側が
   margin-topそのものを丸ごと上書きしてしまうため、-8pxを直書きすると--gutter-y分の
   打ち消しが失われフィードタブ列が--gutter-y分（約7〜7.5px）余分に上へ動く回帰になる。
   var(--gutter-y)を明示的に含めたcalc(var(--gutter-y) - 8px)にすることで、
   .row > *のmargin-topを実質的に引き継ぎつつpadding-top 8pxだけを相殺する。
   下側は真下の絞り込みボタン（.gallery-status-toggle::after、上方向へ約4.8pxはみ出す）
   と.feed-tab::afterの下方向のはみ出し（約7.05px）を合算すると行間の gy-2（約7px）を
   4.85px超えるため、margin-bottomは-8pxではなく-3px（正味の下余白5px）にとどめ、
   タップ領域同士が重ならないだけの間隔を残す。以前の.pb-1（0.25rem、モバイルで3.5px）
   から見ると+1.5px広がるが、他のブレークポイントも含め見た目に影響しない範囲の調整
   （768px以上もcol-12で縦積みのまま、1200px以上は横並びになり本ルールの影響は小さい） */
.feed-tabs {
  padding-top: 8px;
  padding-bottom: 8px;
  margin-top: calc(var(--gutter-y) - 8px);
  margin-bottom: -3px;
}

.search-form {
  width: 100%;
}

.header-search {
  position: relative;
  /* ステータス絞り込みボタンと同じ行に収まるよう伸縮させる（固定100%幅だとボタンが
     必ず折り返され、折り返し後の左寄せボタンを起点にドロップダウンメニューを
     右寄せすると画面外へはみ出すため）。flex-basisは0%にし、内部input(width:100%)の
     コンテンツサイズをフレックスの基準サイズ計算に持ち込ませない */
  flex: 1 1 0%;
  min-width: 0;
  margin: 0;
}

/* PC。タブ列と検索フォームが同じ行に並ぶのは1200px以上（.col-xl-auto/.col-xl）のみのため、
   検索ボックスの右寄せ・固定幅化もこの境界に合わせる。1200px未満はタブ列と検索フォームが
   別行になり、検索フォームがコンテナ全幅を使うため、モバイルと同じ全幅の伸縮のままでよい */
@media (min-width: 1200px) {
  .header-search {
    flex: 0 1 420px;
    /* 検索ボックス（＋その右のステータス絞り込みボタン）を行内で右寄せする */
    margin-left: auto;
  }

  /* html が16px基準のため 0.88rem で従来サイズを維持する */
  .header-search input[type="text"],
  .header-search input[type="search"],
  .header-search input {
    font-size: 0.88rem;
  }
}

.header-search input[type="text"],
.header-search input[type="search"],
.header-search input {
  width: 100%;
  height: 36px;
  padding: 0 14px 0 34px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-bg-subtle);
  color: var(--color-text-primary);
  outline: none;
  box-shadow: none;
}

.header-search input[type="text"]:focus,
.header-search input[type="search"]:focus,
.header-search input:focus {
  border-color: var(--color-accent-text) !important;
  box-shadow: none !important;
  outline: none;
}

/* ギャラリーのルームステータス絞り込みトリガー。背景・枠は持たず、アイコン＋ラベルを
   常に表示する（PC/モバイルで出し分けない）。条件変更の有無によらず文字色は固定し
   （通常の文字色のまま）、選択中の表現はメニュー内のチップ側（gallery-status-chip）
   に一本化する。文字サイズはhtmlの基準フォントサイズ（14/15/16px）に関わらず検索ボックスと
   同じ操作群として一貫して見えることを優先し、remではなくpx直値でモバイル・タブレット・PC
   共通の値にする */
.gallery-status-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 6px 4px;
  border: none;
  background: transparent;
  color: var(--color-text-primary);
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  flex-shrink: 0;
}

/* ボタンの見た目の高さは維持し、タップ判定だけを44px（Luxucomのタップ領域の基準）へ
   広げる（.common-info-main-action::after と同じパターンB。アイコン＋ラベルにより
   実測幅が常に44pxを上回るため left/right: 0 で足りる） */
.gallery-status-toggle::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}

/* アイコンのline-heightをフォントサイズに固定し、align-items: centerでのラベル
   文言との上下中央揃えが崩れないようにする。サイズも文字色同様PC/モバイルで出し分けない */
.gallery-status-toggle i {
  font-size: 17px;
  line-height: 1;
}

@media (hover: hover) {
  .gallery-status-toggle:hover {
    opacity: var(--opacity-hover);
  }
}

/* ステータス絞り込みメニュー。カテゴリ単位で拡張できる構造
   （将来、期間・鍵などのカテゴリが増える前提。現時点はステータスの1カテゴリのみ）。
   幅は最もラベルが長い言語（英語）の4チップが1行に収まる値で固定し、言語間で幅を
   揃える（width: max-contentだと言語ごとに幅が変わってしまうため）。
   モバイルはチップの余白が広く必要幅も広いので別値とし、狭い端末でははみ出さないよう
   92vwで頭打ちにする。
   .gallery-status-chipsのflex-wrap: wrap（既定）は維持しており、将来ラベルが伸びて
   この固定幅に収まらなくなった場合ははみ出さず折り返して劣化する */
.gallery-status-menu {
  width: 332px;
}

@media (max-width: 767px) {
  .gallery-status-menu {
    width: min(350px, 92vw);
  }
}

.gallery-status-category {
  padding: 0 1rem;
}

.gallery-status-category + .gallery-status-category {
  margin-top: 1rem;
}

.gallery-status-category-title {
  margin: 0 0 0.5rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-text-muted);
}

.gallery-status-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  /* 折り返した2行目のチップの::afterが1行目のタップ判定を奪わないよう、行間を広げる */
  row-gap: 12px;
}

/* チップ間の横gapのみ最小限詰める（padding・文字サイズ・タップ領域は変更しない）。
   375px幅で英語4選択肢が1行に収まるようにするための調整。行間（row-gap）は
   上の12pxのまま変えない */
@media (max-width: 767px) {
  .gallery-status-chips {
    column-gap: 0.35rem;
  }
}

/* ステータス選択肢のチップ。inputはDOM上に残しつつキーボードフォーカスを保つため
   display: noneにはせず視覚的にのみ隠す（フォーム送信・バリデーション・JSは変更しない）。
   英語の"No"のように内容が短いと幅が44pxを下回るため、button-rules.md「サイズとタップ領域」の
   btn-smと同様min-width: 44pxで確保する（::afterでは幅を確保しない。隣接チップとのgapが
   0.3〜0.35rem＝4.5〜4.9pxしか無く、::after側で44pxへ広げると隣のチップの::afterへ食い込み
   タップ判定が競合するため）。中央寄せのためjustify-content: centerを追加する */
.gallery-status-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  padding: 6px 14px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-bg-white);
  cursor: pointer;
}

/* 見た目の高さは維持し、タップ判定のみ44pxへ広げる（button-rules.md「サイズとタップ領域」）。
   ::afterの基準はpadding boxのため、枠線（未選択1px・選択中2px）の太さによらず外形を覆えるよう
   中央基準で4px広くする。行間（row-gap）・列間隔（gap）は、隣のチップの::afterと重ならない値 */
.gallery-status-chip::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(100% + 4px);
  height: 44px;
  transform: translate(-50%, -50%);
}

/* btn-link のため .btn 共通の ::after の対象外。見た目は変えず、タップ判定のみ 44px へ
   広げる。英語の「Reset」のように幅が 44px に届かない場合に備え、幅は max(100%, 44px)
   の中央基準にする */
.gallery-status-reset-btn::after,
.gallery-cleanup-saved-rooms-btn::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: max(100%, 44px);
  height: 44px;
  transform: translate(-50%, -50%);
}

.gallery-status-chip input {
  position: absolute;
  margin: 0;
  opacity: 0;
}

.gallery-status-chip-label {
  font-size: 0.85rem;
  color: var(--color-text-primary);
  white-space: nowrap;
}

/* PC・タブレット。モバイルはタップ領域を優先して現状のサイズを維持し、PC・タブレット
   のみ左右paddingとgapを詰める。文字サイズは変えない */
@media (min-width: 768px) {
  .gallery-status-chips {
    column-gap: 0.3rem;
  }

  .gallery-status-chip {
    padding: 6px 8px;
  }
}

/* 選択状態は:has()で表現する（segmented-option・settings-segmented-btnと
   同方針）。ただしこのチップは複数選択（オン/オフ）であり、.feed-tab.is-activeのような
   単一選択のタブとは選択の型が異なるため、表現も分ける。単一選択は塗り、複数選択は
   枠線のみで示し、背景は未選択と同じ白のまま変えない（淡いゴールド背景
   var(--color-accent-pale-soft)＋ゴールドの枠線・文字は金が選択中の表現として
   主張してしまうため使わない）。
   選択・未選択の色表現はPC/モバイルで統一する（サイズ・余白のみ上記メディアクエリ
   で出し分ける）。
   枠線を1px→2pxに太くする分、このルール側でpaddingを上下左右1pxずつ詰め、
   border+paddingの合計を未選択時と同じに保つ。.gallery-status-chip（ベース）側の
   paddingは詰めない。ベースを詰めると未選択のチップまで小さくなり、かつ選択の
   有無で外形が変わってチップを押すたびに隣のチップの位置がずれてしまうため。
   絞り込みメニューは英語4チップが1行に収まる固定幅（.gallery-status-menuの332px）
   なので、外形が変わらないことがこの固定幅の前提になっている */
.gallery-status-chip:has(input:checked) {
  padding: 5px 13px;
  border-color: var(--color-selected-fill);
  border-width: 2px;
}

/* .gallery-status-chip:has(input:checked)は上の無条件ルールと詳細度が同じため、
   メディアクエリの有無に関わらずソース順で後に書かれた方が勝つ。このPC・タブレット
   向け上書きを上の@media (min-width: 768px)ブロック側（無条件ルールより前）に
   置くと、無条件ルールに上書きされて効かなくなる（一度このバグを踏んでいる）。
   必ず無条件ルールより後ろに置くこと */
@media (min-width: 768px) {
  .gallery-status-chip:has(input:checked) {
    padding: 5px 7px;
  }
}

.gallery-status-chip:has(input:checked) .gallery-status-chip-label {
  /* colorは宣言せず未選択と同じ--color-text-primaryを効かせる（白背景に白文字を
     避けるため）。色以外の手がかり（WCAG 1.4.1）としてfont-weightのみ変える */
  font-weight: 600;
}

/* :has() 未対応ブラウザ向けフォールバック。選択状態が文字色の変化だけでも判別できるようにする。
   背景（塗り）は変わらないため文字色には--color-selected-textではなく--color-selected-fillを使う */
@supports not selector(:has(a)) {
  .gallery-status-chip input:checked ~ .gallery-status-chip-label {
    color: var(--color-selected-fill);
    font-weight: 600;
  }
}

/* PCはgapを詰めているため、outline-offsetが大きいと隣接チップとリングが接触する。
   offset:1pxに詰めて隣接チップとの間隔を確保する */
.gallery-status-chip:has(input:focus-visible) {
  outline: 2px solid var(--color-accent-text);
  outline-offset: 1px;
}

@supports not selector(:has(a)) {
  .gallery-status-chip:focus-within {
    outline: 2px solid var(--color-accent-text);
    outline-offset: 1px;
  }
}

@media (hover: hover) {
  .gallery-status-chip:not(:has(input:checked)):hover {
    opacity: var(--opacity-hover);
  }
}

/* 開始日絞り込みの日付入力2つを「〜」区切りで横並びにする。両方のボックスを
   flex: 1 1 0%で伸縮させ、絞り込みメニューの固定幅（.gallery-status-menu、
   モバイルは345px前後）に収まるようにする（ネイティブのdate入力はテキスト入力より
   幅が必要なため、.header-search inputと同じ固定幅にはしない） */
.gallery-date-range {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* ルーム編集の日時ピッカー（.room-datetime-field、resources/static/web/css/room.css）と
   同じ構成。ネイティブのdate入力（.gallery-date-input）はブラウザのロケール依存の書式
   （例: mm/dd/yyyy）でしか表示できないため、入力自体は透明化してこの箱に重ね、
   アプリの言語設定に沿った書式の.gallery-date-valueを代わりに表示する。
   min-heightは.room-datetime-fieldと同じくLuxucomのタップ領域の基準（44px）に合わせる
   （高さはheightではなくmin-heightで指定し、align-items: centerで文字を縦中央に保つ） */
.gallery-date-field {
  position: relative;
  display: inline-flex;
  flex: 1 1 0%;
  min-width: 0;
  align-items: center;
  min-height: 44px; /* Luxucomのタップ領域の基準 */
  padding: 0 8px;
  color: var(--color-text-primary);
  background: var(--color-bg-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
  cursor: pointer;
}

.gallery-date-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  cursor: pointer;
}

.gallery-date-field:has(.gallery-date-input:focus-visible) {
  outline: 2px solid var(--color-accent-text);
  outline-offset: 2px;
}

/* :has() 未対応ブラウザ向けフォールバック（フォーカス可視化を保証） */
@supports not selector(:has(a)) {
  .gallery-date-field:focus-within {
    outline: 2px solid var(--color-accent-text);
    outline-offset: 2px;
  }
}

.gallery-date-value {
  overflow: hidden;
  font-size: 0.85rem;
  white-space: nowrap;
  text-overflow: ellipsis;
  pointer-events: none;
}

.gallery-date-value.is-placeholder {
  color: var(--color-text-muted);
}

.gallery-date-range-separator {
  flex-shrink: 0;
  color: var(--color-text-muted);
  font-size: 0.85rem;
}

.gallery-status-menu-footer {
  padding: 0.25rem 1rem 0;
}

.header-search-icon {
  position: absolute;
  top: 50%;
  left: 12px;
  transform: translateY(-50%);
  color: var(--color-text-muted);
  font-size: 0.9rem;
  line-height: 1;
  pointer-events: none;
}

/* display: inline-flex はアイコン・テキストの間隔を gap で統一するために .btn 基底の
   inline-block から変更している。align-items/justify-content は inline-block 時と
   同じ見た目（内容の縦横中央揃え）を保つための付随指定 */
.common-info-main-action {
  --btn-border-color: var(--color-text-primary);
  --btn-bg: rgba(255, 255, 255, 0.95);
  --btn-color: var(--color-text-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 500;
  line-height: 1;
  padding: 9px 14px;
}

/* モバイル・タブレット・PC共通で36pxに統一している。以前はモバイル30px・
   PC以上36pxで分けていたが、モバイルは見た目30pxに対しタップ判定が44×44pxへ
   広がるためタップ領域どうしが隙間なく接していた。36pxへ広げることで
   タップ領域のはみ出しを抑え、.room-header-actions側のgapを詰められるように
   している（詳細はroom.cssのコメント参照） */
.common-info-sub-action {
  --btn-border-color: var(--color-border-medium);
  --btn-bg: rgba(255, 255, 255, 0.95);
  --btn-color: var(--color-text-primary);
  width: 36px;
  height: 36px;
  padding: 0;
  font-size: 0.85rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  margin-right: 0;
}

@media (hover: hover) {
  .common-info-main-action:hover,
  .common-info-sub-action:hover {
    opacity: var(--opacity-hover);
  }
}

/* ボタンの見た目の高さ（31〜36px）は維持し、タップ判定のみを 44px
   （Luxucomのタップ領域の基準）へ広げる。
   .common-info-main-action はピル型で padding・アイコン・テキストにより実測幅が
   常に 44px を上回るため、::after は left/right: 0（自身の幅いっぱい）で足りる。
   .common-info-sub-action は円形アイコンボタン（36px）で幅が 44px に満たないため、
   ::after 自体を 44×44px にして中央配置する。隣接ボタン同士の間隔は、この
   ::after 同士が重ならないよう利用側（.room-header-actions 等）の gap で
   確保する（room.css のコメント参照） */
.common-info-main-action,
.common-info-sub-action {
  position: relative;
}

.common-info-main-action::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  width: auto; /* .btn 共通の ::after（components.css）の width を打ち消す */
  height: 44px;
  transform: translateY(-50%);
}

.common-info-sub-action::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

.common-delete-icon {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: var(--color-bg-white);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}

@media (hover: hover) {
  .common-delete-icon:hover {
    opacity: var(--opacity-hover);
  }
}

.common-delete-icon i {
  font-size: 14px;
}

/* 画像を3列の正方形タイルで並べるグリッド（サロン投稿・チャットの複数画像表示と、サロン投稿前プレビューで共通）。
   タイルは中央トリミング（object-fit: cover）で揃える。PCで1枚が大きくなりすぎないよう最大幅を持つ */
.image-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-1);
  max-width: 420px;
}

.image-grid-item {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  border-radius: var(--radius-card);
}

.image-grid-item img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* アクセス解析・広告計測の同意バナー（電気通信事業法の外部送信規律対応）
   .consent-bannerと.pwa-banner（次のブロック）は排他である。同意Cookieが未設定の間はこの
   バナーが表示され、その間はglobal/pwa_install.jsがPWAインストールバナーの表示を抑止する
   （両者が画面下部の同じスロットを奪い合わないようにするため）。--pwa-banner-offset /
   --pwa-banner-card-gap（下端固定要素の退避に使うCSS変数。chat.css等が参照）は両者で共有する。
   .pwa-bannerはJS制御でdisplay: none + .is-visibleにより出し分けるが、こちらはサーバー側の
   {% if show_analytics_consent_banner %}分岐で出力有無が決まるため、JS無効環境でも表示・
   操作できるようdisplay: flexを初期値にする */
/* バナー表示中の退避量のフォールバック。--pwa-banner-offset / --pwa-banner-card-gap は
   global/analytics_consent.jsが実測してdocumentElementのインラインスタイルへ設定するため、
   JS有効時はそちらが優先される。ここでの値はJS無効環境と、JS実行前の初回描画にだけ効く概算。
   モバイルの95pxは320px幅（実測94.4px）を、768px以上の56pxは横並びのタブレット・PC幅
   （実測48.5〜51.6px）を、いずれもわずかに上回るよう切り上げた値。下回ると末尾のコンテンツが
   バーに隠れるため、文言を伸ばすときは必ずこの値を見直すこと。
   :has()はバナーを出力したときだけ効かせるために使う。
   .pwa-bannerには対応するフォールバックが無い。display: noneが初期値で、
   global/pwa_install.jsがis-visibleを付与しない限り可視化されずJS前提のため、
   JS無効環境では退避自体が不要 */
:root:has(#analytics-consent-banner) {
  --pwa-banner-offset: 95px;
  --pwa-banner-card-gap: calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
  /* カードは画面下端からvar(--space-3)浮くだけで、フッターナビの直上には浮かず、
     フッターナビに重なって隠す。フッターナビ（--mobile-footer-height）はカードの裏に
     隠れており占有していないため、base.cssの既定式（max(フッターナビ高さ, card-gap)）から
     フッターナビ側を外す。一方、カードが画面下端から浮いている分（--pwa-banner-card-gap）は
     引き続き占有しているため、そちらは残す。フッターナビ側を残したままだと、隠れている
     フッターナビ分（52px）を二重に確保してしまい、0pxにすると逆にカードの浮遊分（14px）が
     計算から落ちてFAB・mainの余白が不足する。768px以上はフッターナビ自体が無いため、
     この式のままで同じ理由が成立する（--mobile-footer-heightを使う他の宣言はいずれも
     768px以上で上書き・非表示になるため影響しない） */
  --mobile-footer-occupied-height: var(--pwa-banner-card-gap, 0px);
  /* base.cssの--mobile-footer-main-offset / --mobile-footer-action-offsetは、
     occupied（セーフエリアを含まない）+ gap + --mobile-safe-area-offset + offsetという式で、
     --mobile-footer-occupied-heightがセーフエリアを含まないことを前提にしている。しかし
     同意バー表示中の--pwa-banner-card-gapはcalc(var(--space-3) + env(safe-area-inset-bottom,
     0px))で画面下端までの実距離としてセーフエリアを含むため、そのまま--mobile-footer-
     occupied-heightへ代入すると前提が崩れ、+--mobile-safe-area-offsetの項と二重に加算される。
     occupied側からセーフエリア分を引いて帳尻を合わせる方法は採れない。chat.cssの
     .chat-main-contentが--mobile-footer-occupied-heightを「カード下端までの実距離」として
     直接参照しており、そちらはセーフエリアを含んだままが正しいため。代わりに、同意バー表示中
     はこの2つの退避量トークン自体を、追加の--mobile-safe-area-offsetを含まない式で
     上書きする（--mobile-safe-area-offset自体を0pxにはしない。salon.cssの
     .salon-compose-sheetが別の目的で参照しているため） */
  --mobile-footer-main-offset: calc(
    var(--mobile-footer-occupied-height) + var(--mobile-footer-main-gap) + var(--pwa-banner-offset, 0px)
  );
  --mobile-footer-action-offset: calc(
    var(--mobile-footer-occupied-height) + var(--mobile-footer-action-gap) + var(--pwa-banner-offset, 0px)
  );
}

@media (min-width: 768px) {
  :root:has(#analytics-consent-banner) {
    --pwa-banner-offset: 56px;
    --pwa-banner-card-gap: calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
  }
}

/* モバイル・768px以上とも、画面下端からvar(--space-3)浮くカードとして共通のbottomを使う
   （フッターナビの直上ではなく画面下端を基準にするため、フッターナビの帯にカードが
   重なって覆い隠す。隠れているフッターナビ分の占有量の二重確保は、上の:root:has()ブロックで
   --mobile-footer-occupied-heightからフッターナビの高さを外して防ぐ。カードが画面下端から
   浮いている分は依然として占有するため、そちらは残す）。bottomが両幅で同値になったため、
   下のメディアクエリ側では重複するbottomの再指定を持たない。
   左右のインセットはvar(--space-2)とし、.pwa-banner（var(--space-3)）より詰めてカード幅を
   広げ、その分を本文の左右paddingへ回す（下端の浮遊量var(--space-3)とは値が異なるため
   「下・左・右で同じインセット」ではない）。
   主要コンテンツを覆わないよう本文は通常1〜2行（最小幅の320pxでは3行）＋操作1行の
   薄さに収めるため、paddingは.pwa-bannerの--pwa-banner-padding-block / -inline
   （0.875rem / 1.25rem）を共有せず、より小さいスペーシングトークンを直接指定する。
   本文とボタンのgapはvar(--space-2)で、上下のpaddingと揃えて詰めている。
   .consent-banner-btn::afterのタップ領域が本文末尾のプライバシーポリシーの
   リンクと競合しないのは、gapの広さではなく::after自体を
   上端基準にして下方向だけへ伸ばしているため（詳細は.consent-banner-btn::afterの
   コメント参照） */
.consent-banner {
  display: flex;
  flex-direction: column;
  position: fixed;
  bottom: calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
  left: var(--space-2);
  right: var(--space-2);
  z-index: 2000;
  background: var(--color-bg-white);
  color: var(--color-text-primary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: var(--space-2) var(--space-3);
  gap: var(--space-2);
  font-family: var(--font-family-base);
  box-shadow: var(--shadow-card);
}

/* 768px以上ではカードとして中央寄せの最大幅を与える。カード自体の見た目
   （left/right/bottom/border/border-radius/box-shadow）はモバイルから共通のため基本ルール側に
   持たせ、ここでは768px以上固有の並び・最大幅だけを上書きする。本文が1〜2行に収まる長さの
   ため、.pwa-bannerと同じテキスト左・ボタン右の横並びにする（720px幅ならテキスト列に
   約468px残り窮屈にならない）。モバイルで横並びにしないのは、ボタン対が約196pxを占め
   テキスト列が107pxしか残らず、行数が増えてかえって厚くなるため */
@media (min-width: 768px) {
  .consent-banner {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    max-width: 720px;
    margin-inline: auto;
  }
}

.consent-banner-message {
  margin: 0;
  color: var(--color-text-muted);
  font-size: 0.75rem;
  line-height: var(--line-height-tight);
}

.consent-banner-message a {
  color: var(--color-text-primary);
  /* 320px幅でも「プライバシーポリシー」が単語の途中で折り返さないようにする */
  white-space: nowrap;
}

/* ボタンはモバイルではメッセージの下、768px以上ではメッセージの右に並び、
   いずれも行内では右寄せにする。flex-shrink: 0は、横並びのときに
   .btn-outline-primary（white-space: nowrapを持たない）が潰されて
   「送信を停止する」が折り返し、バーが厚くなるのを防ぐため */
.consent-banner-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  flex-shrink: 0;
}

.consent-banner-btn {
  position: relative;
  /* 「送信を停止する / OK」の対になるボタンの最小幅。
     .message-modal-footer buttonや.btn-row .btnと同様、対になるボタンへ最小幅を与える既存の慣習に合わせ、
     最も近い確認モーダル（.message-modal-footer button { min-width: 6rem; }）の値を踏襲する。
     6remはhtmlのfont-size（モバイル14px/タブレット15px/PC16px）に連動し84～96pxとなるが、
     いずれも::after（高さ44px確保用）のタップ領域が幅方向で44px以上になる副次効果もある */
  min-width: 6rem;
}

/* .pwa-dismiss-btn::after等と同じ考え方で、見た目の高さは維持しタップ判定のみ44pxへ広げる。
   幅はleft/right: 0（自身の幅いっぱい）とし、min-widthで確保した幅をそのまま使う。
   中央基準（top: 50% + transform: translateY(-50%)）にはせず、top: 0で下方向だけへ
   伸ばす。直上に本文末尾のプライバシーポリシーのリンクが来るため、中央基準だと
   上方向にも張り出してリンクのタップ領域と競合する（gap: var(--space-2)は7pxしかなく、
   はみ出し量約8.3pxを吸収できない）。下方向はバーの余白とフッターナビの覆われた帯
   しか無く、奪う操作が無いためそちらへ寄せる */
.consent-banner-btn::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  /* .btn 共通の ::after（components.css）の width・transform を打ち消す */
  width: auto;
  height: 44px;
  transform: none;
}

/* PWA インストールバナー。モバイルから同意バナー（.consent-banner）と同じ構成のカードとして
   配置する（left/right/border/border-radius/box-shadowはモバイルから共通のため基本ルール側に
   持たせ、768px以上固有の配置・最大幅は下のメディアクエリ側で上書きする） */
.pwa-banner {
  display: none;
  position: fixed;
  /* .mobile-footer-nav（高さ--mobile-footer-height）の直上へvar(--space-3)浮かせて配置する。
     同じCSS変数を参照するため、.mobile-footer-navの高さが変わればここにも追随する */
  bottom: calc(var(--mobile-footer-height) + var(--space-3));
  left: var(--space-3);
  right: var(--space-3);
  z-index: 2000;
  background: var(--color-bg-white);
  color: var(--color-text-primary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: var(--pwa-banner-padding-block) var(--pwa-banner-padding-inline);
  align-items: center;
  justify-content: space-between;
  gap: var(--pwa-banner-content-gap);
  font-family: var(--font-family-base);
  box-shadow: var(--shadow-cta);
}

/* iPadはモバイル判定（isMobile）に含まれるため、768px以上でもモバイル用バナーが出うる。
   カードとしての見た目（left/right/border/border-radius/box-shadow）はモバイルから
   共通のため基本ルール側で持ち、ここでは768px以上固有の下端位置・最大幅だけを上書きする。
   max-width: 600pxは、.pwa-banner-messageが1行に収まる最小幅を実測して決めた値。
   英語版のiOS向け案内文（'Tap "Add to Home Screen" from the share button to open Luxucom
   anytime.'）が日本語訳より長く、768px・1440pxいずれの幅でもインストールボタンを含む
   Android向け文言と合わせて2行になるまで本文領域を必要とするため、これを基準に選定した
   （日本語文言はより狭い幅でも1行に収まる）。768px幅（タブレット縦）でも左右に十分な余白が
   残り、カードの見た目のままモバイルUIの引き伸ばしにはならない */
@media (min-width: 768px) {
  .pwa-banner {
    bottom: calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
    max-width: 600px;
    margin-inline: auto;
  }
}

.pwa-banner.is-visible {
  display: flex;
}

.pwa-banner-info {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1;
  min-width: 0;
}

.pwa-banner-icon {
  border-radius: 9px;
  flex-shrink: 0;
}

.pwa-banner-text {
  min-width: 0;
}

.pwa-banner-message {
  color: var(--color-text-muted);
  font-size: 0.8rem;
  white-space: normal;
  line-height: 1.35;
  display: -webkit-box;
  /* アプリ名の行を削除した分、本文の上限を2行から3行へ広げても最大行数は変わらず
     （アプリ名1行＋本文2行→本文3行）、本文の行の高さの方が小さいため最大高はむしろ下がる */
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pwa-banner-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

.pwa-install-btn {
  display: none;
  position: relative;
  background: var(--color-primary-fill);
  color: var(--color-bg-white);
  border: none;
  border-radius: 6px;
  padding: 7px 16px;
  font-weight: 600;
  font-size: 0.85rem;
  cursor: pointer;
}

.pwa-install-btn.is-visible {
  display: inline-block;
}

/* アイコンフォント（Font Awesome）が読み込めない環境では中の<i>のグリフ幅が0になり、
   ボーダーボックスの寸法をアイコンの字形に頼っているとボタンごと0pxへ潰れる。
   .pwa-bannerは全ページに固定表示され、この閉じるボタン以外に消す手段が無いため、
   アイコンの読み込み可否に関わらずボタン自体に明示的な幅・高さを持たせる。
   34pxは.pwa-install-btn（padding: 7px 16px + line-height基準の可変高さ）の実測高さ
   （375px幅で約33px・768px幅で約34px・1440px幅で約36px）に合わせた値で、
   隣接するインストールボタンとの見た目の釣り合いを取っている。中央寄せはinline-flexで
   行うため、左右のpaddingは付与しない */
.pwa-dismiss-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  background: none;
  border: none;
  color: var(--color-text-muted);
  font-size: 1rem;
  cursor: pointer;
  line-height: 1;
}

/* ボタンの見た目の高さは維持し、タップ判定のみを44px（Luxucomのタップ領域の基準）へ
   広げる。settings.cssの.settings-wallet-btn等と同じ考え方（common-info-main-action /
   common-info-sub-actionのコメントも参照）。.pwa-install-btnはテキストラベル付きの帯状
   ボタンで実測幅が44pxを上回るため、::afterは left/right: 0（自身の幅いっぱい）で足りる。
   .pwa-dismiss-btnはアイコン単体ボタンで幅が44pxに満たないため、::after自体を44×44pxに
   して中央配置する */
.pwa-install-btn::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}

.pwa-dismiss-btn::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

@media (hover: hover) {
  .pwa-install-btn:hover,
  .pwa-dismiss-btn:hover {
    opacity: var(--opacity-hover);
  }
}

/* 履歴表示モーダル（入退室履歴・ライブ履歴で共用） */
.history-modal {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0.6);
  z-index: 2100;
  justify-content: center;
  align-items: center;
}

.history-modal:not([hidden]) {
  display: flex;
}

.history-modal-content {
  display: flex;
  flex-direction: column;
  background-color: var(--color-bg-white);
  padding: 24px;
  max-width: 480px;
  width: 90%;
  max-height: 70vh;
  border-radius: 12px;
  box-shadow: 0 18px 40px rgba(15, 15, 15, 0.12);
}

.history-modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

/* 見出し要素（h2）に付けるクラスのため、base.cssの見出し既定（margin, line-height）を打ち消す */
.history-modal-title {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
  line-height: inherit;
}

.history-modal-close-btn {
  --btn-color: var(--color-text-primary);
  padding: 0;
  font-size: 1.1rem;
}

@media (hover: hover) {
  .history-modal-close-btn:hover {
    opacity: var(--opacity-hover);
  }
}

.history-modal-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* 画像拡大表示モーダル（チャット添付画像・サロン投稿画像で共用） */
.image-viewer-modal {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0.85);
  z-index: 2050;
  justify-content: center;
  align-items: center;
  /* 画面に収めて表示するときの上限。非ズーム時の max-width/max-height とズーム時の幅計算
     （収めた表示の幅 × ズーム倍率）で共有する */
  --image-viewer-fit-max-w: 92vw;
  --image-viewer-fit-max-h: 88svh;
  --image-viewer-zoom-scale: 2.5;
}

.image-viewer-modal:not([hidden]) {
  display: flex;
}

.image-viewer-content {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
}

.image-viewer-zoom-container {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
}

/* ズーム中はコンテナをスクロール領域にする。中央寄せ（justify-content/align-items: center）の
   ままだと、はみ出した分が先頭側へ溢れて隠れスクロールできないブラウザがあるため、起点は
   左上のままにして、画像側の margin: auto で中央寄せする（auto マージンは、はみ出す方向では
   0 に潰れてスクロールでき、画面に収まる方向では中央に置かれる） */
.image-viewer-modal.is-zoomed .image-viewer-zoom-container {
  overflow: auto;
  justify-content: flex-start;
  align-items: flex-start;
}

/* touch-action: manipulation はブラウザ標準のダブルタップ拡大を止める（JS のダブルタップ判定と
   競合させない）。ピンチは残る */
.image-viewer-image {
  max-width: var(--image-viewer-fit-max-w);
  max-height: var(--image-viewer-fit-max-h);
  object-fit: contain;
  touch-action: manipulation;
}

.image-viewer-image.is-zoomable {
  cursor: zoom-in;
}

/* ズーム時の幅は「画面に収めた表示の幅」の固定倍率。収めた幅は元の幅・上限の幅・上限の高さに
   収まる幅（高さ上限 × 縦横比）の最小値で、非ズーム時の max-* による描画と一致する（元が小さい
   画像は拡大されないため元の幅になり、その倍率で拡大する）。元のサイズは、JS がズーム可能な間
   （読み込み完了後）だけ単位なしの数値でカスタムプロパティへ設定し、読み込み中・失敗時は外す */
.image-viewer-modal.is-zoomed .image-viewer-image {
  width: calc(
    min(
        var(--image-viewer-natural-w) * 1px,
        var(--image-viewer-fit-max-w),
        var(--image-viewer-fit-max-h) * var(--image-viewer-natural-w) / var(--image-viewer-natural-h)
      ) *
      var(--image-viewer-zoom-scale)
  );
  height: auto;
  max-width: none;
  max-height: none;
  flex-shrink: 0;
  margin: auto;
  cursor: zoom-out;
}

.image-viewer-close-btn,
.image-viewer-nav-btn,
.image-viewer-zoom-btn {
  --btn-color: var(--color-bg-white);
  position: absolute;
  padding: 0;
  font-size: 1.5rem;
}

.image-viewer-close-btn {
  top: var(--space-3);
  right: var(--space-3);
}

.image-viewer-prev-btn {
  left: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
}

.image-viewer-next-btn {
  right: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
}

/* 前後ボタンは幅が狭く画面端に寄せているため、.btn 共通の中央基準だと ::after が画面の
   外側へはみ出す。画面端（ボタンの位置 --space-3 と枠線 1px の外側）から、ボタンの中心の先
   22px までを覆う（画面端とボタンの間も当たる）。共通ルールの値を打ち消すため、宣言しない側
   （right / left）も明示する */
.image-viewer-prev-btn::after,
.image-viewer-next-btn::after {
  content: "";
  position: absolute;
  width: max(44px, calc(var(--space-3) + 50% + 23px));
  height: 44px;
  top: 50%;
  transform: translateY(-50%);
}

.image-viewer-prev-btn::after {
  left: calc(-1 * var(--space-3) - 1px);
  right: auto;
}

.image-viewer-next-btn::after {
  left: auto;
  right: calc(-1 * var(--space-3) - 1px);
}

/* 閉じるボタンの左に並べる。閉じるボタンの実寸はズーム中(44px)と非ズーム時(アイコンのみ)で
   異なるが、ズーム中の実寸を基準にオフセットを確保しておけば非ズーム時も重ならない */
.image-viewer-zoom-btn {
  top: var(--space-3);
  right: calc(var(--space-3) + 44px + var(--space-2));
}

/* 非ズーム時のボタン実寸（アイコンのみ、375px幅で約23×34px）はLuxucomのタップ領域基準
   （44px）に届かないため、見た目を変えずに::afterでタップ領域だけ44×44pxへ拡張する
   （既存のパターンA、例: .image-modal-adjust-btn::after と同じ考え方）。ズーム中は
   ボタン自身が既に44×44pxのため、この::afterは実質的にボタンの実寸と重なるだけになる */
.image-viewer-zoom-btn::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

@media (hover: hover) {
  .image-viewer-close-btn:hover,
  .image-viewer-nav-btn:hover,
  .image-viewer-zoom-btn:hover {
    opacity: var(--opacity-hover);
  }
}

/* ズーム中は拡大した画像の明るい部分に重なり白いアイコンが見えなくなるため、
   モーダル背景と同じ濃さ（rgba(0, 0, 0, 0.85)）の円形背景を敷いて視認性を保つ。
   .btnの状態フォールバック（:hover/:active時にvar(--btn-hover-bg, var(--btn-bg))へ解決）を
   壊さないよう、生のbackground-colorではなく--btn-bgで指定する。
   実寸を44×44px（Luxucomのタップ領域の基準）にするため、ここではafterによる
   タップ領域の拡張ではなく要素自体の寸法を変える。非ズーム時は変更しない */
.image-viewer-modal.is-zoomed .image-viewer-close-btn,
.image-viewer-modal.is-zoomed .image-viewer-nav-btn,
.image-viewer-modal.is-zoomed .image-viewer-zoom-btn {
  --btn-bg: rgba(0, 0, 0, 0.85);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
}

.image-viewer-counter {
  position: absolute;
  bottom: var(--space-3);
  left: 50%;
  transform: translateX(-50%);
  color: var(--color-bg-white);
  font-size: var(--font-size-nav);
}

.image-viewer-modal.is-zoomed .image-viewer-counter {
  padding: var(--space-1) var(--space-3);
  background-color: rgba(0, 0, 0, 0.85);
  border-radius: var(--radius-pill);
}

/* ヘルプ動画の再生モーダル（ヘッダーのヘルプメニューから開く）。
   動画は画面に収まる幅で、動画（ポスター）本来の比率のまま表示する（紹介動画は16:9、使い方動画は21:9）。
   幅を「PCの上限・左右の余白を除いた幅・高さに収まる幅」の最小値で決め、video自体は width: 100% と
   aspect-ratio で高さを解決させる。`auto 16 / 9` は、固有サイズがわかれば動画本来の比率、
   読み込み前は16:9で高さを確保する（置換要素は固有サイズが無い間 height: auto が 0 になりうるため、
   aspect-ratio を必ず付ける） */
.help-video-modal {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0.85);
  /* 画像拡大モーダルと同値。通知モーダル（.message-modal: 2100）より下にして、通知を最前面に出す */
  z-index: 2050;
  justify-content: center;
  align-items: center;
}

.help-video-modal:not([hidden]) {
  display: flex;
}

/* 幅の3つ目の値は、動画が高さに収まる幅。120px は縦に動画以外が占める分
   （ヘッダー行 44px + gap 8px + 上下の余白 約34px × 2）。16:9 前提の計算だが、21:9 など横長の動画は
   同じ幅で高さがさらに低くなるだけなので収まる。
   100% は position: fixed の全面モーダル（親）の幅（100vw はスクロールバー分を含むため使わない） */
.help-video-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: min(960px, calc(100% - var(--space-3) * 2), calc((100vh - 120px) * 16 / 9));
  width: min(960px, calc(100% - var(--space-3) * 2), calc((100dvh - 120px) * 16 / 9));
}

.help-video-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

/* 見出し要素（h2）に付けるクラスのため、base.cssの見出し既定（margin, line-height）を打ち消す */
.help-video-title {
  min-width: 0;
  margin: 0;
  color: var(--color-bg-white);
  font-size: 1rem;
  font-weight: 600;
  line-height: inherit;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.help-video-close-btn {
  --btn-color: var(--color-bg-white);
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  font-size: 1.5rem;
}

@media (hover: hover) {
  .help-video-close-btn:hover {
    opacity: var(--opacity-hover);
  }
}

/* video の直後に置く Tab の境界要素（help_video_modal.js が閉じるボタンへ循環させる）。
   flex の gap や見た目に影響しないよう、フロー外に置いて大きさを持たせない */
.help-video-focus-guard {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.help-video-player {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: auto 16 / 9;
  background-color: var(--color-bg-black);
  object-fit: contain;
}
