/* ===== デザイントークン =====
   色・フォント・影・アニメーション時間などをCSS変数にまとめておく。
   後で色味や動きの速さを調整したいときは、ここだけ直せばよい。 */
:root {
  /* カラートークン：メインはパステルピンク、サブにパステルブルー、差し色にレモンイエロー。
     ＝LOVEのCDジャケット（プールモチーフ・シトロンモチーフ）の配色を参考にしたオリジナル配色。 */
  --color-primary: #ff6fa8;         /* メインのパステルピンク */
  --color-primary-dark: #ff4f96;    /* 見出しや強調テキスト、濃いめのピンク */
  --color-primary-light: #ffe1ee;   /* ホバー時の淡い光・背景アクセント */
  --color-secondary: #6fbdf2;       /* サブカラーのパステルブルー */
  --color-secondary-light: #dff2ff; /* 背景グラデーションや淡いアクセント */
  --color-accent: #ffd93d;          /* レモンイエロー。正解演出やキラキラなど特別な演出の差し色 */
  --color-accent-soft: #fff2bf;     /* 差し色の淡いバージョン（バッジや正解セルの背景など） */
  --color-call-glow: #ff9f43;       /* ライブコールモードの現在コール強調専用、発光のオレンジ側
                                        （黄色側は--color-accentを流用。2026-08-06、本人要望で
                                        「ライブ会場のペンライト」を意識した暖色の発光に変更） */
  --color-danger: #ff6b6b;          /* 不正解・エラー用のやわらかい赤 */
  --color-song-favorite: #ff8a5c;   /* 曲のお気に入りハート専用のコーラルオレンジ。
                                        メンバーの「推し」ハート（--color-primaryのピンク）と
                                        見分けがつくよう、あえて別系統の暖色にしている（2026-08-04） */
  --color-danger-soft: #fff0ee;     /* 不正解セルなど、赤の淡いバージョン */
  --color-background-start: #fff7f9; /* 背景グラデーションの開始色 */
  --color-background-end: #dff2ff;   /* 背景グラデーションの終了色（パステルブルー） */
  --color-surface: #ffffff;          /* 不透明な背景（結果一覧の行など） */
  --color-surface-glass: rgba(255, 255, 255, 0.6); /* ガラス風カードの半透明背景 */
  --color-card-border: rgba(255, 255, 255, 0.8);   /* ガラス風カードの縁取り */
  --color-text: #4a2e42;          /* 基本の文字色 */

  /* 【2026-11-XX追加・本人指示：iPhone下部の白い帯バグの恒久対策】.game-frameを
     viewport高さへ固定している画面（クイズ回答中・ライブコールモード等）で使う、
     「dvhでも届かない、物理的な画面最下端まで」の高さ。
     【根拠】センターお祝いポップアップ（.modal-overlay.celebration-overlay、このファイル内
     「17-17章」のコメント参照）を実機診断した結果、「iOSのstandalone PWAでは、
     window.innerHeight（＝dvh系の単位も含むCSSレイアウトビューポート）自体が、
     ホームインジケーターのsafe-area分だけ画面の物理的な最下端より短く報告される」ことが
     実機の数値で確定していた。その対策（bottom: calc(-1 * env(safe-area-inset-bottom))で
     物理的な最下端まで伸ばす）と全く同じ考え方を、height指定で組む.game-frame系にも
     一般化して適用する。safe-area-inset-bottomが無い環境（notch/ホームインジケーターの
     無い端末・PC等）では0pxに解決されるため、100dvhと完全に同じ挙動のまま変化しない。 */
  /* 【2026-09-05改訂・本人指示：クイズ画面が最初だけ上に寄る不具合の根本対応】
     100dvhというCSS単位そのものが、iOS Safariでは「ページを開いた直後の最初の1回だけ」
     正しい値に確定していないことがある（ブラウザのツールバー収縮状態が確定する前の、
     暫定的な値のまま描画されてしまう）。これまでは効果音設定モーダルを開閉した際の
     副作用（js/scrollLock.jsのposition:fixed切り替え）でこの再計算がたまたま誘発され、
     ユーザーが操作するまで正しい位置にならない、という不具合として現れていた。
     js/viewportMeasurement.jsが、実際に見えているビューポートの高さを
     window.visualViewport（無ければwindow.innerHeight）からJSで直接測定し、
     --measured-viewport-heightへ書き込む（読み込み直後・複数フレーム後・画面表示後・
     resize/orientationchange時に測り直す）。100dvhの代わりにこの測定値を使うことで、
     ブラウザ内部のdvh確定タイミングに依存せず、常に「今実際に見えている高さ」を使える。
     JSが実行される前（理論上のみ、通常は発生しない）や、visualViewport非対応の環境では
     100dvhへ自然にフォールバックする。 */
  --game-frame-safe-height: calc(var(--measured-viewport-height, 100dvh) + env(safe-area-inset-bottom, 0px));

  /* ガラス風カードの影・ぼかし */
  --shadow-card: 0 24px 60px -14px rgba(255, 79, 150, 0.38), 0 6px 18px rgba(255, 79, 150, 0.16);
  --blur-glass: 20px;

  /* 背景演出の濃さ。強すぎるとカードの読みやすさを邪魔するので、控えめな値にしている */
  --pattern-opacity: 0.28;
  --vinyl-opacity: 0.12;
  --blob-opacity: 0.38;
  --sparkle-opacity: 0.85;

  /* フォント：丸みのある読みやすい日本語フォントを優先し、
     読み込めない環境ではOS標準の丸みのあるゴシックにフォールバックする */
  /* 【2026-10-30改訂】M PLUS Rounded 1c が読み込めないとき（オフライン・通信が遅いとき）の代わりを増やした。
     iPhone/Mac＝ヒラギノ丸ゴ・ヒラギノ角ゴ、Windows＝游ゴシック・メイリオ、Android＝Noto Sans JP の順 */
  --font-family-base: "M PLUS Rounded 1c", "Hiragino Maru Gothic ProN", "Hiragino Kaku Gothic ProN", "Hiragino Sans",
    "Yu Gothic UI", "Yu Gothic", YuGothic, Meiryo, "Noto Sans JP", "Noto Sans CJK JP", sans-serif;

  /* モーション（アニメーションの速さ）。演出自体は後のステップで追加する */
  --transition-fast: 120ms;
  --transition-base: 200ms;
  --transition-slow: 400ms;
}

* {
  box-sizing: border-box;
}

/* 【2026-09-05新設・本人指示：アプリ全体でユーザー操作によるページ拡大縮小を禁止】
   このゲームUIはボタン・文字サイズを端末幅に合わせて設計済みで、アプリ内に拡大表示が
   必要なコンテンツ（地図・細かい文書・画像の拡大確認等）が無いため、ダブルタップズーム・
   ピンチズームを画面全体で防ぐ方針にした（本人指示）。
   【以前の方針との関係】直下の「16px未満で自動ズーム」対策コメントにある通り、
   以前は「viewportのuser-scalable=noは、他画面のピンチズーム・アクセシビリティに
   影響するため使わない」という方針だった。今回はその方針自体を本人指示で見直し、
   ズーム無効化を明示的な仕様として全画面へ適用する（＝これは方針転換であり、矛盾ではない）。
   【なぜviewportのuser-scalable=noではなくtouch-actionなのか】user-scalable=noは
   ブラウザによっては強すぎる副作用（意図せずスクロール自体が不安定になる等）の
   報告があるため使わない。代わりに、既に一部の画面（オンライン対戦ロビー・結果画面・
   クイズ回答画面等、下の該当コメント参照）で実機確認済みの「touch-actionでpan-x/pan-yだけを
   許可する」方式を、html/body全体（＝アプリの全画面）へ一般化するだけに留める。
   pan-x（横方向のパン）・pan-y（縦方向のパン）だけを許可すると、縦スクロール・
   横スクロール（曲名検索の候補チップ等）はそのまま動作しつつ、ピンチズーム・
   ダブルタップズームだけが仕様上抑えられる（ズームの許可がpan-x/pan-yの一覧に
   含まれていないため）。個別のボタン等に付いている既存のtouch-action:manipulation
   （ダブルタップズーム対策＋タップ反応速度向上）は、このルールと矛盾しないため
   そのまま残している（重複しても無害、既存の実機確認済みの挙動を壊さないため）。
   iOS Safariの一部バージョン向けの補助対策（gesturestart等のpreventDefault）は
   js/main.js側に追加している。 */
html,
body {
  touch-action: pan-x pan-y;
}

/* 【2026-09-06新設、本人指示：実機フィードバック】iOS Safari/PWAは、フォーカスした
   <input>のフォントサイズが16px未満だと、文字が読みやすいよう画面全体を自動的に
   拡大する（そのまま倍率が戻りにくくなることがある）。viewportのuser-scalable=no等で
   雑にズーム自体を禁止するのではなく（他画面のピンチズーム・アクセシビリティに
   影響するため）、この「16px未満だと自動ズームされる」というブラウザ側の挙動そのものを
   起こさせないのが安全な対策とされている。アプリ内のほぼ全ての検索欄・名前入力欄が
   実際には16px未満（0.85〜0.9rem等）だったため、input要素全体に対して一括で
   16px以上を保証する（個別のクラスごとのfont-size指定は、詳細度の関係でこの汎用ルールに
   上書きされる。デザイン上の見た目はほぼ変わらない範囲での調整）。 */
body input[type="text"],
body input[type="search"],
body input[type="tel"],
body input[type="email"],
body input:not([type]),
body textarea {
  font-size: 16px;
}

body {
  margin: 0;
  /* 【2026-11-XX修正・本人指示：iPhone下部の白い帯バグの調査結果】以前はここが
     min-height: 100vh; だった。iOSのstandalone PWAでは、vh/dvh系の単位や
     window.innerHeightが、ホームインジケーターのsafe-area分だけ画面の物理的な
     最下端より短く報告されることが実機診断で確定済み（このファイル上部の
     --game-frame-safe-height の説明、および「17-16・17-17章」「ライブコール
     モード再生画面UI/UX第4版」のコメント参照）。bodyの背景（グラデーション）が
     この分だけ画面の物理的な最下端に届かず、その外側にブラウザ標準の白い
     キャンバスが透けて見えていたと考えられる（htmlタグ自体に背景色指定が無いため）。
     既にセンターお祝いポップアップ・一部のgame-frame（クイズ回答画面等）へ
     実機で効果を確認済みの--game-frame-safe-height（100dvh + safe-area-inset-bottom）
     をbodyにも適用し、背景を画面の物理的な最下端まで確実に届かせる。
     safe-area-inset-bottomが無い環境（notch/ホームインジケーターの無い端末・PC等）
     では0pxに解決されるため、実質100dvhと同じ挙動のまま変化しない。 */
  min-height: var(--game-frame-safe-height);
  font-family: var(--font-family-base);
  color: var(--color-text);
  background: linear-gradient(135deg, var(--color-background-start), var(--color-background-end));

  /* ゲームフレームを画面の中央に配置する。
     viewport-fit=cover対応：上だけDynamic Island・ノッチ分のセーフエリアを確保する。
     【重要】paddingショートハンドの中でenv()・calc()・max()を組み合わせると、
     実機のSafariで値全体が解釈できず上下左右すべて0扱いになる不具合を実機検証で確認した。
     そのため、padding-top等を個別のプロパティとして指定している（ショートハンドに戻さないこと）。 */
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding-top: max(64px, calc(env(safe-area-inset-top) + 20px));
  padding-right: 16px;
  padding-bottom: 40px;
  padding-left: 16px;
}

/* ===== 自動更新の適用通知（2026-08-29新設） =====
   Service Workerの自動更新が実際に適用された直後の1回の読み込みだけ表示する、
   ピンク系の控えめな通知。押す操作は不要で、約10秒後にjs/main.js側が自動的にhidden属性を
   付け直して消す。どの画面が表示中でも必ず見えるよう、game-frameの外・画面最上部に固定し、
   Dynamic Island・ノッチのsafe areaぶんも確保する（クイズ画面のヘッダーと同じ考え方）。 */
.update-applied-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50; /* モーダル（20）・センターお祝いポップアップより必ず手前に表示する */
  padding: max(10px, env(safe-area-inset-top)) 16px 10px;
  background: linear-gradient(120deg, var(--color-primary-dark), var(--color-primary));
  color: #ffffff;
  font-size: 0.82rem;
  font-weight: 700;
  text-align: center;
  box-shadow: 0 4px 14px -4px rgba(255, 79, 150, 0.55);
  animation: updateAppliedBannerEnter 320ms cubic-bezier(0.22, 1, 0.36, 1);
}

.update-applied-banner[hidden] {
  display: none;
}

@keyframes updateAppliedBannerEnter {
  from {
    opacity: 0;
    transform: translateY(-100%);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ===== 背景演出 =====
   うっすらギンガムチェック・ステージライトのようににじむ光・ぼかしたレコード盤・キラキラの粒で、
   ＝LOVEらしい華やかさと音楽ゲームらしさを、カードの外側（背景）で表現する。 */

/* 背景演出をまとめて画面に固定する入れ物。
   光の玉やレコード盤は画面の外側にはみ出す配置にしているため、
   ここで必ず切り取ることで、ページ本体の縦スクロールに影響を与えないようにする
   （結果画面など、内容が長くなってスクロールする画面でも、背景はここに固定されたまま動かない）。 */
.bg-decorations {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

/* うっすらギンガムチェック模様。＝LOVEの衣装に多いチェック柄を、控えめな透かし模様として */
.bg-pattern {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: var(--pattern-opacity);
  background-image:
    linear-gradient(45deg, var(--color-primary-light) 25%, transparent 25%, transparent 75%, var(--color-primary-light) 75%),
    linear-gradient(45deg, var(--color-primary-light) 25%, transparent 25%, transparent 75%, var(--color-primary-light) 75%);
  background-size: 26px 26px;
  background-position: 0 0, 13px 13px;
}

/* 背景に漂わせる、ぼかしたレコード盤のシルエット。音楽ゲームらしさを遠景でさりげなく主張する */
.bg-vinyl {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  opacity: var(--vinyl-opacity);
  filter: blur(1.5px);
  background:
    repeating-radial-gradient(circle at 50% 50%, transparent 0 9px, rgba(255, 255, 255, 0.55) 9px 10px),
    conic-gradient(from 0deg, var(--color-primary), var(--color-secondary), var(--color-accent), var(--color-primary));
}

.bg-vinyl.v1 {
  width: 300px;
  height: 300px;
  top: 4%;
  right: -110px;
  animation: spinSlow 46s linear infinite;
}

.bg-vinyl.v2 {
  width: 220px;
  height: 220px;
  bottom: -60px;
  left: -70px;
  animation: spinSlow 60s linear infinite reverse;
}

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

/* ステージライトのようににじむ光の玉。3色をそれぞれゆっくり漂わせる */
.light-blob {
  position: absolute;
  border-radius: 50%;
  filter: blur(64px);
  opacity: var(--blob-opacity);
  pointer-events: none;
}

.light-blob.pink {
  width: 46vw;
  height: 46vw;
  max-width: 420px;
  max-height: 420px;
  background: radial-gradient(circle, var(--color-primary) 0%, transparent 70%);
  top: -12%;
  left: -14%;
  animation: drift1 16s ease-in-out infinite;
}

.light-blob.blue {
  width: 40vw;
  height: 40vw;
  max-width: 380px;
  max-height: 380px;
  background: radial-gradient(circle, var(--color-secondary) 0%, transparent 70%);
  top: 8%;
  right: -16%;
  animation: drift2 19s ease-in-out infinite;
}

.light-blob.yellow {
  width: 30vw;
  height: 30vw;
  max-width: 300px;
  max-height: 300px;
  background: radial-gradient(circle, var(--color-accent) 0%, transparent 72%);
  bottom: -8%;
  left: 18%;
  animation: drift3 14s ease-in-out infinite;
}

@keyframes drift1 {
  0%, 100% {
    transform: translate(0, 0) scale(1);
  }
  50% {
    transform: translate(4%, 5%) scale(1.08);
  }
}

@keyframes drift2 {
  0%, 100% {
    transform: translate(0, 0) scale(1);
  }
  50% {
    transform: translate(-5%, 4%) scale(1.05);
  }
}

@keyframes drift3 {
  0%, 100% {
    transform: translate(0, 0) scale(1);
  }
  50% {
    transform: translate(3%, -6%) scale(1.1);
  }
}

/* キラキラの粒（音符・星・ハート）。生成自体はjs/decorations.jsが行う */
.sparkle-field {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.spark {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--s);
  height: var(--s);
  opacity: 0;
  color: var(--spark-color, var(--color-accent));
  animation: twinkle 3.2s ease-in-out infinite;
  animation-delay: var(--d);
}

.spark svg {
  width: 100%;
  height: 100%;
  display: block;
}

@keyframes twinkle {
  0%, 100% {
    opacity: 0;
    transform: scale(0.4) rotate(0deg);
  }
  50% {
    opacity: var(--sparkle-opacity);
    transform: scale(1) rotate(20deg);
  }
}

/* クイズ画面だけは、プレイ中に一番長く見る画面なので、
   問題文・タイマー・選択肢の見やすさを最優先にして背景演出を控えめにする。
   （screens.jsがbodyのdata-screen属性を更新し、ここで画面ごとに参照している） */
body[data-screen="quiz"] {
  --pattern-opacity: 0.1;
  --blob-opacity: 0.16;
  --vinyl-opacity: 0.05;
  --sparkle-opacity: 0.3;
  --color-surface-glass: rgba(255, 255, 255, 0.82);
}

/* ===== ゲームフレーム =====
   PCで開いても「スマホゲームをプレイしている」ように見せるための、中央に浮かぶカード。 */
.game-frame {
  z-index: 2; /* 背景演出より必ず手前に表示する */
  position: relative; /* 上端のリボンラインの位置基準にする */
  width: 100%;
  max-width: 480px;
  background: var(--color-surface-glass);
  backdrop-filter: blur(var(--blur-glass)) saturate(150%);
  -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(150%);
  border: 1px solid var(--color-card-border);
  border-radius: 24px;
  /* 外側のふんわりした影に、ガラスの縁が光を受けているような内側のハイライトを重ねる */
  box-shadow: var(--shadow-card), inset 0 1px 0 rgba(255, 255, 255, 0.6);
  overflow: hidden;
}

/* ミニプレイヤーが表示されている間、.game-frame下端のコンテンツがミニプレイヤーの
   裏に隠れないよう、余白を確保する（body.has-mini-playerはjs/miniPlayer.jsが付け外しする。
   UI/UX再設計で追加）。 */
body.has-mini-player .game-frame {
  padding-bottom: 76px;
}

/* オンライン対戦の曲選択画面が固定バー（.song-picker-sticky-bar）の裏に隠れないよう、
   下に余白を確保する（2026-08-28新設）。data-screenで絞り込むだけでよく、
   ミニプレイヤーのようなJS側でのクラス付け外しは不要（既存のdata-screen機構をそのまま使う）。 */
body[data-screen="onlineBattleSongPicker"] .game-frame {
  padding-bottom: 96px;
}

/* オンライン対戦：曲選択画面専用の、下部固定の選択状況バー（2026-08-28新設）。
   ミニプレイヤーと全く同じ理由・同じ配置方針（.game-frameの外・bodyの直下・
   position:fixed）を踏襲する。z-indexもミニプレイヤーと同じ12にしているが、
   曲選択画面とミニプレイヤーが同時に表示されることは実質的に無いため、
   重なりは想定しなくてよい。 */
.song-picker-sticky-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 12;
  display: flex;
  flex-direction: column;
  padding: 10px 16px;
  padding-bottom: max(10px, env(safe-area-inset-bottom));
  background: var(--color-surface-glass);
  backdrop-filter: blur(var(--blur-glass)) saturate(150%);
  -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(150%);
  border-top: 1px solid var(--color-card-border);
  box-shadow: 0 -6px 18px -8px rgba(0, 0, 0, 0.25);
}

.song-picker-sticky-bar[hidden] {
  display: none;
}

.song-picker-sticky-bar-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.song-picker-sticky-toggle {
  display: flex;
  align-items: center;
  gap: 4px;
  flex: none;
  background: none;
  border: none;
  padding: 8px 4px;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-text);
  white-space: nowrap;
}

.song-picker-sticky-toggle strong {
  color: var(--color-primary-dark);
  font-size: 1rem;
}

.song-picker-sticky-toggle .chevron {
  width: 16px;
  height: 16px;
  transition: transform 0.2s ease;
}

.song-picker-sticky-toggle[aria-expanded="true"] .chevron {
  transform: rotate(-90deg);
}

.song-picker-sticky-bar-row .primary-button {
  flex: 1;
  margin: 0;
  padding: 12px 16px;
  font-size: 0.9rem;
}

/* 「選択中○曲」をタップすると開く、選択中の曲を確認・解除できる小さなトレイ。
   曲数が多くても画面を圧迫しないよう、最大高さを決めて内部スクロールにする。 */
.song-picker-review-panel {
  max-height: 34vh;
  overflow-y: auto;
  margin-bottom: 8px;
  padding: 4px 2px;
}

.song-picker-review-panel[hidden] {
  display: none;
}

.song-picker-review-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.song-picker-review-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 5px 6px 5px 10px;
  border-radius: 999px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-size: 0.78rem;
  font-weight: 700;
  max-width: 100%;
}

.song-picker-review-chip span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.song-picker-review-chip button {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.7);
  color: var(--color-primary-dark);
  font-size: 0.75rem;
  line-height: 1;
  padding: 0;
}

/* 【2026-09-06新設・本人指示：圏外プレイ結果の自動反映通知】オンライン復帰時などに
   未送信だったランキング記録を自動送信できたことを知らせる、控えめなトースト。
   ミニプレイヤーと同じ理由で.game-frameの外・bodyの直下に置き、常に画面下端付近に表示する。
   z-indexはミニプレイヤー（12）より前面、モーダル（20）より背面にする
   （モーダル表示中に重なって邪魔にならないよう、あくまで控えめな通知にとどめる）。 */
.ranking-auto-sync-toast {
  position: fixed;
  left: 16px;
  right: 16px;
  bottom: max(14px, env(safe-area-inset-bottom));
  z-index: 15;
  margin: 0 auto;
  max-width: 448px;
  padding: 12px 18px;
  border-radius: 999px;
  background: var(--color-surface-glass);
  backdrop-filter: blur(var(--blur-glass)) saturate(150%);
  -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(150%);
  border: 1px solid var(--color-card-border);
  box-shadow: var(--shadow-card);
  color: var(--color-text);
  font-size: 0.85rem;
  font-weight: 700;
  text-align: center;
  pointer-events: none;
}

.ranking-auto-sync-toast[hidden] {
  display: none;
}

/* 連続再生のミニプレイヤー。他のモーダルと同じ理由で.game-frameの外・bodyの直下に置き、
   常に画面の実際の下端に固定表示する（.game-frameのbackdrop-filterの影響を受けない）。
   z-indexは背景演出（0）・.game-frame（2）より前面、モーダル（20）より背面にする。 */
.mini-player {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 12;
  display: flex;
  justify-content: center;
  padding: 0 16px;
  padding-bottom: max(14px, env(safe-area-inset-bottom));
}

.mini-player[hidden] {
  display: none;
}

.mini-player-inner {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  max-width: 480px;
  padding: 8px 10px;
  border-radius: 999px;
  background: var(--color-surface-glass);
  backdrop-filter: blur(var(--blur-glass)) saturate(150%);
  -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(150%);
  border: 1px solid var(--color-card-border);
  box-shadow: var(--shadow-card);
}

.mini-player-main {
  display: flex;
  align-items: center;
  gap: 9px;
  flex: 1;
  min-width: 0;
  padding: 4px;
  border: none;
  border-radius: 999px;
  background: none;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.mini-player-icon {
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

.mini-player-icon svg {
  width: 16px;
  height: 16px;
}

.mini-player-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.mini-player-title {
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--color-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 状態文（再生中/一時停止中）と経過時間を同じ行に並べる。
   経過時間は本人からの追加要望（2026-08-06、タイトル行を増やさず1行にまとめて表示）。 */
.mini-player-subline {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
}

.mini-player-status {
  font-size: 0.64rem;
  opacity: 0.6;
  flex: none;
}

.mini-player-time {
  font-size: 0.64rem;
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mini-player-control-button {
  flex: none;
  width: 36px;
  height: 36px;
  border: none;
  border-radius: 50%;
  background: var(--color-primary);
  color: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.mini-player-control-button svg {
  width: 16px;
  height: 16px;
}

/* 再生/一時停止ボタン：連続再生画面の.continuous-play-control-buttonと同じ、
   svgの出し分けでアイコンを切り替える方式（js/miniPlayer.jsがis-playingを付け外しする）。 */
.mini-player-control-button .icon-pause {
  display: none;
}

.mini-player-control-button.is-playing .icon-play {
  display: none;
}

.mini-player-control-button.is-playing .icon-pause {
  display: block;
}

.mini-player-control-button.is-stop {
  width: 30px;
  height: 30px;
  background: rgba(74, 46, 66, 0.08);
  color: var(--color-text);
  opacity: 0.6;
}

.mini-player-control-button:active {
  transform: scale(0.92);
}

/* カード上端の三色リボンライン。ピンク→ブルー→イエローの配色をひと目で示す */
.game-frame::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 5px;
  background: linear-gradient(90deg, var(--color-primary), var(--color-secondary) 50%, var(--color-accent));
}

/* ===== 画面切り替え用の共通クラス =====
   screens.js が .is-active を付け外しして、start/quiz/result画面の表示を切り替える。 */
.screen {
  display: none;
  padding: 24px;
}

.screen.is-active {
  display: block;
  /* 画面が切り替わった瞬間、ふわっと浮かび上がるように表示する */
  animation: screenEnter 480ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* 【2026-09-13追加・本人指示：オンライン対戦の初回問題が無音・無表示になる不具合の調査】
   画面が切り替わった直後は、まだフェードイン中で視認しづらいにもかかわらず、ボタン類は
   最初から操作可能だった。カウントダウン終了の瞬間に指が画面に触れたままだった場合、
   切り替わった直後のクイズ画面のボタン（例：選択肢1つ目）へ意図しないタップが
   そのまま届いてしまい、「1問目が無反応のまま2問目へ進んだように見える」原因になりうる
   と判断した。フェードインが終わる直前まではクリック・タップを一切受け付けないようにし、
   この種の「ゴーストタップ」を全画面共通で防ぐ（quiz画面に限らない一般的な安全策）。
   pointer-eventsはCSSアニメーションのキーフレームとして扱える（連続値ではなく、指定した
   区切りで切り替わる）ため、新しいJSのタイマー等を増やさずに実現できる。 */
@keyframes screenEnter {
  from {
    opacity: 0;
    transform: translateY(14px) scale(0.98);
    pointer-events: none;
  }
  99% {
    pointer-events: none;
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: auto;
  }
}

/* ===== タイトル周りの装飾 ===== */

/* カード上端に添える小さな星の飾り。カード（.game-frame）基準の絶対位置に表示する */
.ribbon-charm {
  position: absolute;
  top: 10px;
  right: 22px;
  width: 16px;
  height: 16px;
  color: var(--color-accent);
  filter: drop-shadow(0 2px 4px rgba(255, 217, 61, 0.5));
  animation: titleTwinkle 2.4s ease-in-out infinite;
}

.title-block {
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* 「MUSIC INTRO QUIZ」の小さなラベルチップ */
.eyebrow-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 14px;
  padding: 5px 15px;
  border-radius: 999px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  color: var(--color-primary-dark);
}

.eyebrow-chip .mini-star {
  width: 9px;
  height: 9px;
  flex: none;
}

/* ===== ロゴ：パステルカラーのレコード盤がゆっくり回転する ===== */
.logo-badge {
  position: relative;
  width: 62px;
  height: 62px;
  margin: 0 0 14px;
  animation: logoFloat 3.4s ease-in-out infinite;
}

@keyframes logoFloat {
  0%, 100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-6px);
  }
}

.vinyl-spin {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background:
    repeating-radial-gradient(circle at 50% 50%, transparent 0 6px, rgba(255, 255, 255, 0.75) 6px 7px),
    conic-gradient(from 200deg, var(--color-primary-light), var(--color-secondary-light) 40%, var(--color-accent-soft) 70%, var(--color-primary-light));
  border: 1px solid var(--color-card-border);
  box-shadow: 0 10px 22px -8px rgba(255, 111, 168, 0.55), inset 0 0 0 1px rgba(255, 255, 255, 0.4);
  animation: spinSlow 7s linear infinite;
}

/* レコード盤に映り込む、光の反射 */
.vinyl-spin::after {
  content: "";
  position: absolute;
  top: 8%;
  left: 18%;
  width: 30%;
  height: 14%;
  background: rgba(255, 255, 255, 0.65);
  border-radius: 50%;
  filter: blur(1px);
  transform: rotate(-25deg);
}

/* レコード盤の中心ラベル */
.vinyl-center {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 22px;
  height: 22px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--color-primary), var(--color-primary-dark));
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
}

.vinyl-center svg {
  width: 11px;
  height: 11px;
  color: #ffffff;
}

/* ===== 見出し ===== */
h1 {
  position: relative;
  margin: 0;
  text-align: center;
  font-size: clamp(1.4rem, 5vw, 1.7rem);
  font-weight: 800;
  color: var(--color-text);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
}

h1 .eq {
  color: var(--color-primary-dark);
}

/* タイトル左右の、星を添えた特別仕様の音符アイコン */
h1 .note-icon {
  width: 1.05em;
  height: 1.05em;
  flex: none;
}

h1 .note-icon.left {
  color: var(--color-secondary);
}

h1 .note-icon.right {
  color: var(--color-primary);
}

h1 .note-icon svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* タイトルの左右上に瞬く、小さな星 */
.title-spark {
  position: absolute;
  width: 12px;
  height: 12px;
  color: var(--color-accent);
  animation: titleTwinkle 2.2s ease-in-out infinite;
}

.title-spark.tl {
  top: -10px;
  left: 6%;
  animation-delay: 0.3s;
}

.title-spark.tr {
  top: -12px;
  right: 4%;
  animation-delay: 0.9s;
}

@keyframes titleTwinkle {
  0%, 100% {
    opacity: 0.35;
    transform: scale(0.8) rotate(0deg);
  }
  50% {
    opacity: 1;
    transform: scale(1.15) rotate(18deg);
  }
}

/* ===== 音源の読み込み状況（PWA対応） =====
   音源はサーバーに置かず、利用者が選んだファイルを端末内（IndexedDB）に保存する方式のため、
   その状況を表示し、読み込みボタンを提供する。控えめな見た目のチップ風パネルにする。 */
/* データ管理（音源・歌詞読み込み）の折りたたみ。初回セットアップ以降はほとんど
   使わないため、ホーム画面の一番下でdetails/summaryにより畳んでおく（2026-08-04追加）。 */
.data-management-section {
  margin: 18px 0 4px;
  padding: 10px 14px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.3);
  border: 1px dashed var(--color-card-border);
}

.data-management-section summary {
  cursor: pointer;
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.65;
  list-style: none;
}

.data-management-section summary::-webkit-details-marker {
  display: none;
}

.data-management-section summary::before {
  content: "▸";
  display: inline-block;
  width: 1em;
  margin-right: 4px;
  transition: transform 0.15s ease;
}

.data-management-section[open] summary::before {
  transform: rotate(90deg);
}

.data-management-section .audio-import-section {
  margin-top: 12px;
}

/* 【2026-08-27追加】音源・歌詞・コール・コールガイドを種類ごとに個別に読み込む機能の折りたたみ。
   通常ユーザーは「追加データパックを読み込む」だけで完結するため、.data-management-section
   （外側の折りたたみ）の中に、さらに一段折りたたんで目立たなくしている。
   見た目は.data-management-sectionと同じパターンを再利用し、入れ子であることが分かるよう
   余白だけ内側に寄せている。 */
.advanced-data-management-section {
  margin: 14px 0 4px;
  padding: 8px 12px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.2);
  border: 1px dashed var(--color-card-border);
}

.advanced-data-management-section summary {
  cursor: pointer;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.6;
  list-style: none;
}

.advanced-data-management-section summary::-webkit-details-marker {
  display: none;
}

.advanced-data-management-section summary::before {
  content: "▸";
  display: inline-block;
  width: 1em;
  margin-right: 4px;
  transition: transform 0.15s ease;
}

.advanced-data-management-section[open] summary::before {
  transform: rotate(90deg);
}

.audio-import-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin: 4px 0 8px;
  padding: 8px 14px;
  border-radius: 14px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  text-align: center;
  opacity: 0.88;
}

.audio-import-status {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.75;
}

.audio-import-button {
  display: inline-flex;
  align-items: center;
  padding: 5px 14px;
  border: 1.5px solid var(--color-primary);
  border-radius: 999px;
  color: var(--color-primary-dark);
  font-size: 0.74rem;
  font-weight: 700;
  cursor: pointer;
}

.audio-import-button:active {
  transform: scale(0.96);
}

.audio-import-result {
  margin: 0;
  font-size: 0.7rem;
  color: var(--color-text);
  opacity: 0.65;
}

.audio-import-result[hidden] {
  display: none;
}

/* ===== 歌詞データの読み込み状況 =====
   音源（必須）とは違い、なくても普通に遊べる任意の追加機能のため、
   構造は.audio-import-sectionと揃えつつ、背景・縁取りを一段控えめにして
   優先度の違いが自然に伝わるようにする。色そのものは既存のブランドカラーの範囲内で揃える。 */
.lyrics-import-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin: 0 0 10px;
  padding: 8px 14px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.35);
  border: 1px dashed var(--color-card-border);
  text-align: center;
}

.lyrics-import-caption {
  margin: 0;
  font-size: 0.68rem;
  color: var(--color-text);
  opacity: 0.7;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex-wrap: wrap;
}

.optional-tag {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  border: 1px solid var(--color-secondary);
  color: var(--color-secondary);
  font-size: 0.62rem;
  font-weight: 700;
  white-space: nowrap;
}

.lyrics-import-status {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.75;
}

.lyrics-import-button {
  display: inline-flex;
  align-items: center;
  padding: 5px 14px;
  border: 1.5px solid var(--color-secondary);
  border-radius: 999px;
  color: #2c6ea8;
  font-size: 0.74rem;
  font-weight: 700;
  cursor: pointer;
}

.lyrics-import-button:active {
  transform: scale(0.96);
}

.lyrics-import-result {
  margin: 0;
  font-size: 0.7rem;
  color: var(--color-text);
  opacity: 0.65;
  white-space: pre-line;
}

.lyrics-import-result[hidden] {
  display: none;
}

/* ===== 歌詞の警告確認パネル =====
   1ファイルずつモーダルを出さず、警告があるファイルをまとめて1つのパネルに表示し、
   「保存する/しない」をまとめて選んでもらう構成。 */
.lyrics-warning-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  margin-top: 4px;
  padding: 10px;
  border-radius: 12px;
  background: var(--color-accent-soft);
  border: 1px solid var(--color-accent);
  text-align: left;
}

.lyrics-warning-panel[hidden] {
  display: none;
}

.lyrics-warning-panel-title {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-text);
}

.lyrics-warning-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 240px;
  overflow-y: auto;
}

/* 【2026-11-XX追加・本人指示：[hidden]系CSSの全面監査で発見】.breakdown-chip-rowと
   同じ原因のため、同じ対策を追加。 */
.lyrics-warning-list[hidden] {
  display: none;
}

.lyrics-warning-item {
  padding: 6px 8px;
  border-radius: 8px;
  background: var(--color-surface);
  font-size: 0.72rem;
}

.lyrics-warning-item summary {
  cursor: pointer;
  font-weight: 700;
  color: var(--color-text);
}

.lyrics-warning-item ul {
  margin: 6px 0 0;
  padding-left: 18px;
  color: var(--color-text);
  opacity: 0.8;
}

.lyrics-warning-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* 【2026-10-29追加】display:flex が [hidden] に勝ってしまい、「最新版データを読み込む」の「やめる／この内容で読み込む」が
   ファイルを選ぶ前から・読み込みのあとも見えていた（js/unifiedPackImportUi.js は hidden を正しく付けていた）。 */
.lyrics-warning-actions[hidden] {
  display: none;
}

.lyrics-warning-actions .secondary-button {
  font-size: 0.72rem;
  padding: 8px;
}

/* ===== センターお祝いポップアップ（2026-08-24新設、同日全面刷新・本人指示） =====
   本人がChatGPTで作成した1枚の完成画像（assets/images/）をそのまま背景として使用し、
   点線枠の位置に実際のMVサムネイル、「MVを見る」「見た！」の位置に透明なクリック領域を
   重ねるだけの構成にする。色・文字・装飾はCSS/SVGで再現しない（本人指示）。
   .modal-overlayの共通スタイル（position:fixed; inset:0で背後のホーム画面を完全に
   ブロックする）を土台にしつつ、背景色だけこのクラスで上書きする。 */
.celebration-overlay {
  background: rgba(20, 40, 60, 0.55);
  padding: 16px;
  /* 【2026-08-26・17-16章で撤去】カード下から画面最下部にかけて白い領域が残る不具合の対策として、
     一時期ここに`height:100vh;height:100dvh;`を追加し、さらにJS側でvisualViewport等から
     算出した高さをインラインstyleで上書きしていたが、実機で直らなかった（17-12・17-13・17-15章）。
     調べ直した結果、全く同じ「bodyをposition:fixedにしてスクロールロックする」構成の中で、
     既に実機で問題なく動いている.lyrics-fullscreen-overlay（js/lyricsFullscreen.js）は、
     このような明示的なheight指定を一切持たず、.modal-overlayと同じposition:fixed; inset:0;
     だけで画面いっぱいに広がっている。CSSの仕様上、top・bottom・heightを同時に指定すると
     （このケースではinset:0のbottom:0と、追加していたheightが競合する）、bottomの値は
     無視されてtop+heightから再計算される。つまり、良かれと思って追加していたheight指定が、
     本来inset:0だけで正しく機能していたはずのbottom:0を上書きしてしまい、私たちが計算した
     heightの数値がわずかでもずれていれば、その分だけ確実に隙間が残る状態を自ら作っていた
     可能性が高いと判断した。そこで、height指定を完全に撤去し、実機で実績のある
     .lyrics-fullscreen-overlayと同じ「position:fixed; inset:0;のみに任せる」構成に統一した。 */
}

/* 【2026-08-26・17-17章】17-16章の対策後、本人がiPhone実機で一時的な診断モード
   （html=緑・body=青・overlay=半透明の赤に着色し、画面上に数値パネルを表示するもの）を
   使って確認した結果、次のことが実測で判明した：
     ・overlay.getBoundingClientRect().bottom は window.innerHeight と完全に一致していた
       （＝オーバーレイ自体はCSS上のビューポート最下端まで正しく届いていた。17-16章の
       対策は有効に機能している）。
     ・それにもかかわらず、そのビューポートのさらに下（実機の画面最下端との間）に、
       青（＝body要素の背景色）が実際に見えていた。
   つまり今回の白い（正確には見えていたのはbodyの背景色）領域の正体は、
   「オーバーレイの高さ計算の誤り」ではなく、「iOSのstandalone PWAにおいて、
   window.innerHeight（CSSのレイアウトビューポート）自体が、ホームインジケーターの
   セーフエリア分だけ画面の物理的な最下端より短く報告されている」ことだったと実機の数値で
   確定した。index.htmlの<meta name="viewport">にはviewport-fit=coverが既に指定されている
   ものの、iOS Safari（standalone表示含む）は`inset:0`／`window.innerHeight`を、
   viewport-fit=coverの有無にかかわらずセーフエリアを除いた「安全な」領域基準で計算する
   実装になっている（bodyの背景描画自体はセーフエリアの下まで塗られるため、そこだけが
   「オーバーレイに覆われていない、bodyの背景がそのまま見える領域」として残っていた）。
   対策として、オーバーレイの下端だけをenv(safe-area-inset-bottom)分だけさらに下へ伸ばす
   （bottomをinset:0の0pxから、セーフエリア分だけマイナス方向へ広げる）。
   safe-area-inset-bottomが無い環境（notch/ホームインジケーターの無い端末・PC等）では
   env(..., 0px)が0pxに解決されるため、bottom:0pxと完全に同じ挙動のまま変化しない
   （既存の見た目・他画面への影響は無い）。
   【指定方法についての注意】.modal-overlayの`inset:0`（bottom:0を含む）と同じ詳細度
   （クラスセレクタ1つ）のルールでbottomだけを上書きしようとすると、CSSの読み込み順序
   （.modal-overlayの定義がこのファイルの後ろにある）によってはinset:0側のbottom:0が
   優先されてしまう。そのため、詳細度を確実に上回るよう、両方のクラスを持つ要素にだけ
   一致する複合セレクタ（.modal-overlay.celebration-overlay）を使っている。 */
.modal-overlay.celebration-overlay {
  bottom: calc(-1 * env(safe-area-inset-bottom, 0px));
}

/* 背景画像とオーバーレイ要素（サムネイル・クリック領域）の入れ物。
   画像自体の縦横比がそのままこの入れ物の高さを決めるため、375/390/430pxいずれの
   画面幅で表示しても、中の%指定の要素が画像と同じ比率で一緒に伸縮し、位置がずれない
   （本人指示：固定pxでの位置決めは使わない）。 */
.celebration-frame {
  position: relative;
  width: 100%;
  max-width: 420px;
  border-radius: 22px;
  overflow: hidden;
  box-shadow: 0 24px 48px -18px rgba(10, 40, 60, 0.6);
}

.celebration-bg {
  display: block;
  width: 100%;
  height: auto;
}

/* 点線枠の内側に実際のMVサムネイルを重ねる部分。位置・サイズ（left/top/width/height）は、
   背景画像ごとに異なるため、CSSでは固定せず、js/centerCelebration.jsが各お祝いの
   layoutデータ（実測したピクセル位置を画像全体に対する%に変換した値）から
   インラインstyleとして毎回設定する（2026-08-25、複数件対応に伴いCSS固定値から変更）。 */
.celebration-thumb-overlay {
  position: absolute;
  border-radius: 3.2% / 5.2%;
  overflow: hidden;
  display: block;
}

.celebration-thumb-overlay img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.celebration-thumb-overlay img[hidden] {
  display: none;
}

/* 「MVを見る」「見た！」は背景画像に描かれている見た目をそのまま使うため、ここでは
   見えない透明なクリック領域だけを同じ位置に重ねる（本人指示：新しいボタンを描き直さない）。
   位置（left/top/width/height）は、サムネイル枠と同じく背景画像ごとに異なるため、
   js/centerCelebration.jsがインラインstyleとして毎回設定する（2026-08-25〜）。 */
.celebration-hotspot {
  position: absolute;
  border: none;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* ===== イコライザー風の飾り区切り。曲が流れているような臨場感を添える ===== */
.eq-divider {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 4px;
  height: 22px;
  margin: 14px 0 20px;
}

.eq-divider span {
  width: 3.5px;
  border-radius: 3px;
  background: linear-gradient(180deg, var(--color-secondary), var(--color-primary) 60%, var(--color-accent));
  height: 6px;
  animation: eqBounce 1.1s ease-in-out infinite;
}

@keyframes eqBounce {
  0%, 100% {
    height: 5px;
  }
  50% {
    height: var(--peak, 16px);
  }
}

h2 {
  position: relative;
  margin: 0;
  text-align: center;
  font-size: clamp(1.3rem, 4.5vw, 1.5rem);
  font-weight: 800;
  color: var(--color-primary-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
}

/* ===== 出題数・カテゴリの選択エリア ===== */
fieldset {
  border: 2px solid var(--color-primary);
  border-radius: 16px;
  margin-bottom: 16px;
  padding: 12px 16px;
}

legend {
  color: var(--color-primary-dark);
  font-weight: 700;
  padding: 0 6px;
}

/* ラジオボタン本体は見た目上は隠すが、キーボード操作や読み上げ機能のためにDOM上には残す */
fieldset input[type="radio"] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* labelタグ自体を、チップ（丸っこいボタン）風の見た目にする */
fieldset label {
  display: inline-flex;
  align-items: center;
  position: relative;
  margin: 4px 6px 4px 0;
  padding: 10px 18px;
  border: 2px solid var(--color-primary);
  border-radius: 999px;
  background-color: var(--color-surface);
  color: var(--color-text);
  font-weight: 700;
  cursor: pointer;
  transition: background-color var(--transition-fast), color var(--transition-fast), transform var(--transition-fast);
}

/* 選択されている項目は、ピンク→ブルーのグラデーションで塗りつぶし、左側に小さなキラキラ印を添える */
fieldset label:has(input:checked) {
  background: linear-gradient(120deg, var(--color-primary-dark), var(--color-primary) 55%, var(--color-secondary));
  color: #ffffff;
  border-color: transparent;
  box-shadow: 0 6px 16px -4px rgba(255, 79, 150, 0.55);
}

fieldset label:has(input:checked)::before {
  content: "✦";
  margin-right: 4px;
  font-size: 0.75em;
  color: var(--color-accent-soft);
}

fieldset label:active {
  transform: scale(0.96);
}

@media (hover: hover) {
  fieldset label:hover {
    box-shadow: 0 0 0 4px var(--color-primary-light);
  }
}

/* キーボードのTabキーで選んだときも、見た目でどこにいるか分かるようにする */
fieldset label:has(input:focus-visible) {
  outline: 3px solid var(--color-primary-dark);
  outline-offset: 2px;
}

/* 出題数の選択肢を3個・2個の2段に固定するための行。
   PC幅で5個を並べても最後の1個だけが余って見えないよう、段ごとに中央寄せする。
   gapで間隔を取り、labelどうしの右マージンとの二重取りを避けるため
   このコンテナ内だけlabelの右マージンを打ち消す。 */
.option-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
}

/* 【2026-09-07修正・本人指示：モード選択グリッド崩れの調査】オンライン対戦ロビーの
   「モードを変更する」だけは、.option-rowを本来の用途（出題数チップ等、内容の幅に応じて
   自然に折り返す行）とは違う目的、「常に2列×3段で固定表示したいペア」として使っている。
   選択中の項目には fieldset label:has(input:checked)::before の「✦」が付き、その分だけ
   横幅が伸びるため、375px前後の実機では特定の行（長いモード名の組）だけ2つ目が
   はみ出して折り返し、「2列/2列/2列」だったはずの表示が選択直後に
   「2列/2列/1列/1列」へ崩れる不具合が実機で報告されていた（本人指示・調査項目④）。
   .option-row自体は他の多くの画面（出題数・カテゴリ等の可変個数チップ）で意図どおり
   内容依存の折り返しを必要としているため、このクラス自体は変更せず、
   「常に2列固定」であるべきモード変更だけをgridへ切り替えて隔離する。 */
#online-battle-lobby-mode-change-fieldset .option-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  justify-content: stretch;
}

#online-battle-lobby-mode-change-fieldset .option-row label {
  margin: 0;
}

.option-row label {
  margin: 4px 0;
}

/* カテゴリの選択肢だけ、出題数のチップ型とは違い、横幅いっぱいの1行として扱い、
   「カテゴリ名＋曲数」のまとまりをボタン中央に配置する。
   PC幅で余白が右だけに偏らず、スマホ幅でも同じCSSで自然に中央に来る。 */
.category-option {
  display: flex;
  align-items: center;
  width: 100%;
  margin: 4px 0;
}

.category-option-content {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  min-width: 0;
}

/* 選択中だけ表示する「✦」。未選択時も同じ幅を確保しておくことで、
   選択前後でカテゴリ名・曲数の位置がずれないようにする
   （fieldset全体で共通の::beforeによる✦は、下の打ち消しルールでこの要素だけに置き換える）。 */
.category-option-star {
  flex: none;
  font-size: 0.75em;
  color: var(--color-accent-soft);
  visibility: hidden;
}

.category-option:has(input:checked) .category-option-star {
  visibility: visible;
}

.category-option:has(input:checked)::before {
  content: none;
}

/* 【2026-XX-XX追加・本人指示：旧ルール名（ノーマル/ハード/LOVE連チャン）を
   タイムアタック/正解数バトル/ノーミスチャレンジへ全面改称した際、3ルールの選択カードへ
   短い説明文を追加】タイムアタック（js/timeAttackScreen.js）・ランダム再生クイズ
   （js/randomPlaybackScreen.js）・1台対戦（js/localBattleScreen.js）・オンライン対戦
   ルーム設定（js/onlineBattleScreen.js）の4箇所すべてで共通して使う、ルール選択専用の
   カード表示。既存のfieldset label（丸っこいチップ）をベースにしつつ、
   タイトル（大きめ・太字）の下に説明文（小さめ・少し薄い色）を縦に積む形へ拡張する。
   3枚を常に横並び・同じ高さで揃え、狭い画面でも横スクロールさせない。 */
.rule-option-row {
  display: flex;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: 6px;
}

fieldset label.rule-option-card {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  text-align: left;
  border-radius: 14px;
  padding: 10px 10px 10px 14px;
  margin: 4px 0;
}

.rule-option-card-title {
  font-weight: 800;
  font-size: 0.95rem;
  line-height: 1.25;
}

/* 選択中でも説明文の視覚的優先度がタイトルを超えないよう、weightは上げず
   opacityだけ僅かに上げて読みやすさを保つ（本人指示：「選択状態でも説明文の視覚的
   優先度は上げすぎない」）。 */
.rule-option-card-desc {
  display: block;
  margin-top: 3px;
  font-size: 0.68rem;
  font-weight: 500;
  line-height: 1.3;
  opacity: 0.7;
}

fieldset label.rule-option-card:has(input:checked) .rule-option-card-desc {
  opacity: 0.85;
}

/* 【重要】fieldset labelの通常の::before（「✦」）は、labelがdisplay:flexの
   縦積み（flex-direction:column）になったこのカードでは独立した1行として
   浮いてしまう。ここでは打ち消し、代わりにタイトルの直前にだけ差し込む
   （js\data\guideContent.js等の説明文には影響しない、見た目だけの対応）。 */
fieldset label.rule-option-card::before {
  content: none;
}

fieldset label.rule-option-card:has(input:checked) .rule-option-card-title::before {
  content: "✦ ";
  font-size: 0.85em;
  color: var(--color-accent-soft);
}

/* 狭い画面（320px付近）では左右のpaddingとgapを詰め、3枚横並びを維持したまま
   文字サイズだけ僅かに縮める（本人指示：3カードは常に同じ高さ・横スクロール無し）。 */
@media (max-width: 360px) {
  .rule-option-row {
    gap: 4px;
  }
  fieldset label.rule-option-card {
    padding: 8px 6px 8px 10px;
  }
  .rule-option-card-title {
    font-size: 0.82rem;
  }
  .rule-option-card-desc {
    font-size: 0.62rem;
  }
}

.category-option-name {
  min-width: 0;
}

/* カテゴリの選択肢に添える、現在の対象曲数（songs.jsから自動集計、控えめな見た目） */
.count-hint {
  flex: none;
  white-space: nowrap;
  font-size: 0.8em;
  opacity: 0.7;
}

/* ===== オンライン対戦：ルーム作成画面の対戦モード選択（2026-08-08新設） =====
   .category-optionと同じ「横幅いっぱいの行」の考え方だが、モード名の下に短い説明文を
   添えたいため、横並びではなく縦積みにする。一度ルームを作った後はモードを変更できない
   仕様のため、作成前にここで遊び方が伝わることを優先している。 */
.game-mode-option {
  display: flex;
  width: 100%;
  margin: 4px 0;
}

.game-mode-option-content {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
  min-width: 0;
}

.game-mode-option-name {
  font-weight: 700;
}

.game-mode-option-description {
  font-size: 0.8em;
  font-weight: 400;
  opacity: 0.85;
}

/* 選択中の項目は文字色が白になるため、説明文の不透明度を少し上げて視認性を保つ */
.game-mode-option:has(input:checked) .game-mode-option-description {
  opacity: 0.95;
}

/* 選択した出題数が対象曲数を上回っているときだけ表示する案内文 */
.question-count-notice {
  text-align: center;
  font-size: 0.78rem;
  color: var(--color-text);
  opacity: 0.7;
  margin: -6px 0 14px;
}

/* ===== ボタン共通 =====
   ピンク→ブルーのグラデーションに、常時ゆるく光るパルスと、
   時々横切る光沢（シャイン）を加えて、ステージのライトのような高級感を出す。 */
.primary-button {
  position: relative;
  display: block;
  width: 100%;
  margin-top: 16px;
  padding: 14px;
  border: none;
  border-radius: 999px;
  overflow: hidden;
  background: linear-gradient(120deg, var(--color-primary-dark), var(--color-primary) 45%, var(--color-secondary));
  background-size: 200% auto;
  color: #ffffff;
  font-family: inherit;
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 14px 30px -10px rgba(255, 79, 150, 0.55);
  animation: primaryButtonGlow 2.6s ease-in-out infinite;
  transition: transform var(--transition-fast) cubic-bezier(0.34, 1.56, 0.64, 1),
    box-shadow var(--transition-base), background-position 0.6s ease;
}

/* ボタンの上を斜めに横切る光沢。曲が流れるステージのスポットライットのような演出 */
.primary-button::after {
  content: "";
  position: absolute;
  top: 0;
  left: -60%;
  width: 40%;
  height: 100%;
  background: linear-gradient(120deg, transparent, rgba(255, 255, 255, 0.65), transparent);
  transform: skewX(-20deg);
  animation: primaryButtonShine 3.4s ease-in-out infinite;
}

@keyframes primaryButtonShine {
  0% {
    left: -60%;
  }
  35%,
  100% {
    left: 130%;
  }
}

/* 条件を満たしていないときの主ボタン（例：オリジナル問題作成モードで4曲未満のとき）。
   光る演出を止め、押せない状態であることが見た目でも伝わるようにする。 */
.primary-button:disabled {
  opacity: 0.5;
  cursor: default;
  animation: none;
  box-shadow: none;
}

.primary-button:disabled::after {
  content: none;
}

@keyframes primaryButtonGlow {
  0%,
  100% {
    box-shadow: 0 14px 30px -10px rgba(255, 79, 150, 0.55);
  }
  50% {
    box-shadow: 0 14px 38px -6px rgba(255, 79, 150, 0.75), 0 0 0 6px rgba(111, 189, 242, 0.12);
  }
}

/* hidden属性が付いているときは、display:blockより優先して非表示にする */
.primary-button[hidden] {
  display: none;
}

/* 押した瞬間に少し縮んで、指で押している感覚を出す。バウンドするような戻り方にして押し心地を強調する */
.primary-button:active {
  transform: scale(0.95);
  box-shadow: 0 6px 14px -6px rgba(255, 79, 150, 0.5);
}

/* マウスでホバーできる端末でだけ、光沢の位置を流しつつ少し浮き上がらせる */
@media (hover: hover) {
  .primary-button:hover {
    background-position: 100% center;
    box-shadow: 0 18px 36px -8px rgba(255, 79, 150, 0.65);
    transform: translateY(-1px);
  }
}

/* ===== スキップ・答えを見るボタン =====
   「次へ」ボタンほど目立たせたくないので、塗りつぶさず枠線だけの控えめな見た目にする。 */
#quiz-actions {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

#quiz-actions[hidden] {
  display: none;
}

.secondary-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex: 1;
  padding: 10px;
  border: 2px solid var(--color-primary);
  border-radius: 999px;
  background-color: transparent;
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
  transition: transform var(--transition-fast) cubic-bezier(0.34, 1.56, 0.64, 1), background-color var(--transition-base);
}

/* displayの指定がhidden属性より優先されてしまう問題への対策（#new-record-badgeと同じ原因） */
.secondary-button[hidden] {
  display: none;
}

.secondary-button .button-icon {
  width: 15px;
  height: 15px;
  flex: none;
}

.secondary-button:active {
  transform: scale(0.94);
}

@media (hover: hover) {
  .secondary-button:hover {
    background-color: var(--color-primary-light);
  }
}

/* ===== クイズ画面：4択ボタン =====
   通常は2×2グリッド。狭い画面向けの調整は下のメディアクエリで行う。 */
#choice-buttons {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin: 16px 0;
}

.choice-button {
  position: relative; /* キラキラ演出（::after）・番号バッジ（::before）の位置の基準にする */
  min-height: 44px; /* タップしやすいように最小の高さを確保 */
  padding: 14px 8px;
  border: 2px solid var(--color-primary);
  border-radius: 16px;
  background-color: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 700;
  cursor: pointer;
  transition: transform var(--transition-fast) cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow var(--transition-base);
}

/* 左上の小さな番号バッジ。キーボードの1〜4キーで選べることが一目で分かるようにする */
.choice-button::before {
  content: "";
  position: absolute;
  top: -8px;
  left: -8px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  color: var(--color-primary-dark);
  font-size: 0.7rem;
  font-weight: 800;
  box-shadow: 0 2px 6px -2px rgba(255, 79, 150, 0.4);
}

#choice-buttons .choice-button:nth-child(1)::before {
  content: "1";
}
#choice-buttons .choice-button:nth-child(2)::before {
  content: "2";
}
#choice-buttons .choice-button:nth-child(3)::before {
  content: "3";
}
#choice-buttons .choice-button:nth-child(4)::before {
  content: "4";
}

.choice-button:active {
  transform: scale(0.94);
}

/* 【2026-11-XX新設・本人指示：回答ボタンの操作性改善】js/answerButtonInteraction.jsが
   pointerdown〜pointerup/キャンセルの間だけ付け外しするクラス。ネイティブの:activeだけに
   頼ると、スライドアウトでキャンセルした瞬間に見た目を戻す等の細かい制御ができないため、
   JS側で管理する.is-pressedを正としつつ、見た目は既存の:active（scale(0.94)）と揃える。 */
.choice-button.is-pressed {
  transform: scale(0.94);
}

@media (hover: hover) {
  .choice-button:hover {
    box-shadow: 0 0 0 4px var(--color-primary-light);
  }
}

/* ===== 回答後の正解・不正解演出 ===== */

/* 正解の選択肢：黄色く縁取りしつつ、軽く跳ねるように拡大縮小し、✨マークを飛ばす */
.choice-button.is-correct {
  border-color: var(--color-accent);
  background-color: var(--color-accent-soft);
  animation: correctPop var(--transition-slow) ease-out;
}

.choice-button.is-correct::after {
  content: "✨";
  position: absolute;
  top: -10px;
  right: -6px;
  font-size: 1.2rem;
  animation: sparkle var(--transition-slow) ease-out;
}

@keyframes correctPop {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.06);
  }
  100% {
    transform: scale(1);
  }
}

@keyframes sparkle {
  0% {
    opacity: 0;
    transform: scale(0.4) rotate(-10deg);
  }
  50% {
    opacity: 1;
    transform: scale(1.1) rotate(8deg);
  }
  100% {
    opacity: 0;
    transform: scale(0.9) translateY(-6px);
  }
}

/* 不正解として選んでしまった選択肢：赤みを帯びて、軽く横に揺れる */
.choice-button.is-wrong {
  border-color: var(--color-danger);
  background-color: var(--color-danger-soft);
  animation: shake var(--transition-slow) ease-in-out;
}

@keyframes shake {
  0%, 100% {
    transform: translateX(0);
  }
  20% {
    transform: translateX(-6px);
  }
  40% {
    transform: translateX(5px);
  }
  60% {
    transform: translateX(-4px);
  }
  80% {
    transform: translateX(3px);
  }
}

/* ===== クイズ画面：途中でタイトルへ戻る入口 =====
   収録曲一覧・プレイ履歴画面の.back-linkと同じ見た目だが、あちらは.list-header（グリッド）専用の
   grid-column/justify-selfを持つため、グリッドを使わないこの画面向けに専用クラスにしている。
   進捗ピル（#question-progress、中央寄せ）とは横に並べず、その上に独立した左寄せの行として置くことで、
   スマホ幅でも進捗表示と干渉しないようにしている。 */
/* 「タイトルへ」と効果音ボタンを横並びにする行（2026-08-06追加）。 */
.quiz-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.quiz-header-row .quiz-back-link {
  margin-bottom: 0;
}

/* ===== 「🔇 音が出ない」救済ボタン（2026-09-16新設、本人指示）=====
   小さく控えめな自己申告ボタン。.quiz-header-rowのすぐ下・.quiz-middle-zone
   （スクロール領域）の外に置くことで、スクロールしなくても常に見える位置を保つ。
   表示/非表示・有効/無効の切り替え自体はjs/main.js側が行う（[hidden]属性の
   既定display:noneをそのまま使えるよう、ボタン自体にはdisplayプロパティを指定しない。
   .quiz-back-linkでdisplay:inline-flexを指定してしまい[hidden]が効かなくなった
   過去の不具合〈2026-09-15発見〉と同じ轍を踏まないための意図的な選択）。 */
.quiz-audio-trouble-row {
  display: flex;
  justify-content: flex-end;
  margin: 2px 0 0;
}

.quiz-audio-trouble-button {
  margin: 0;
  padding: 4px 10px;
  border: 1px solid var(--color-card-border);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.35);
  color: var(--color-text);
  opacity: 0.7;
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
}

.quiz-audio-trouble-button:active {
  transform: scale(0.94);
  opacity: 0.9;
}

.quiz-audio-trouble-button:disabled {
  opacity: 0.4;
  cursor: default;
}

/* ===== 効果音ON/OFFボタン（クイズ画面・スタート画面で共用、2026-08-06追加） =====
   アイコンの出し分けは.mini-player-control-button等と同じ、SVGの表示切り替え方式。 */
.sfx-toggle-button .icon-sfx-off {
  display: none;
}

.sfx-toggle-button.is-muted .icon-sfx-on {
  display: none;
}

.sfx-toggle-button.is-muted .icon-sfx-off {
  display: block;
}

.sfx-toggle-button.is-muted {
  color: var(--color-danger);
}

/* スタート画面側：ラベル付きの行（データ管理の折りたたみの上、常時表示）。 */
.sfx-settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 12px;
  padding: 8px 12px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid var(--color-card-border);
}

.sfx-settings-label {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.7;
}

.sfx-settings-detail-link {
  flex: none;
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  background: none;
  border: none;
  padding: 4px 2px;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ===== 効果音の詳細設定モーダル（2026-08-10新設） ===== */
.sfx-settings-modal-card {
  text-align: left;
}

.sfx-settings-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 4px;
  border-bottom: 1px solid var(--color-card-border);
}

.sfx-settings-toggle-text {
  min-width: 0;
}

.sfx-settings-toggle-label {
  margin: 0;
  font-size: 0.92rem;
  font-weight: 800;
  color: var(--color-text);
}

.sfx-settings-toggle-description {
  margin: 2px 0 0;
  font-size: 0.72rem;
  opacity: 0.65;
  line-height: 1.4;
}

.sfx-settings-toggle-row .sfx-toggle-button {
  flex: none;
  min-width: 56px;
  padding: 7px 14px;
  border-radius: 999px;
  border: 1.5px solid var(--color-primary);
  background: var(--color-primary);
  color: #ffffff;
  font-size: 0.78rem;
  font-weight: 800;
  text-align: center;
}

.sfx-settings-toggle-row .sfx-toggle-button.is-muted {
  background: rgba(255, 255, 255, 0.5);
  border-color: var(--color-card-border);
  color: var(--color-text);
  opacity: 0.6;
}

.sfx-settings-section {
  margin-top: 16px;
}

.sfx-settings-section-title {
  margin: 0 0 8px;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--color-text);
  opacity: 0.75;
}

.sfx-theme-option-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sfx-theme-option {
  width: 100%;
  text-align: left;
  padding: 10px 14px;
  border-radius: 14px;
  background: var(--color-surface-glass);
  border: 1.5px solid var(--color-card-border);
}

.sfx-theme-option.is-selected {
  background: var(--color-primary-light);
  border-color: var(--color-primary);
}

.sfx-theme-option-name {
  margin: 0;
  font-size: 0.88rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.sfx-theme-option.is-selected .sfx-theme-option-name::before {
  content: "✓ ";
}

.sfx-theme-option-description {
  margin: 2px 0 0;
  font-size: 0.74rem;
  color: var(--color-text);
  opacity: 0.7;
  line-height: 1.4;
}

/* 【2026-09-26新設・本人指示：サウンドシステム全面整備】各テーマカード内の
   「▶ テーマを試聴」。カード全体（テーマ選択）のクリック領域の中にあるが、
   stopPropagation()でテーマ選択とは独立して動作する。 */
.sfx-theme-option-preview-button {
  margin-top: 8px;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1.5px solid var(--color-primary);
  background: var(--color-surface);
  color: var(--color-primary-dark);
  font-size: 0.72rem;
  font-weight: 800;
}

.sfx-settings-section-hint {
  margin: 4px 0 10px;
  font-size: 0.7rem;
  color: var(--color-text);
  opacity: 0.6;
  line-height: 1.5;
}

/* 【2026-09-05新設・本人指示：オフライン問題中の簡易効果音設定】OFF/小/中/大の
   4段階ボタン。.sfx-theme-option（選択中カード）と同じ配色ルールで統一感を持たせる。 */
.quick-sfx-volume-option-list {
  display: flex;
  gap: 8px;
}

.quick-sfx-volume-option {
  flex: 1 1 0;
  padding: 10px 4px;
  border-radius: 12px;
  background: var(--color-surface-glass);
  border: 1.5px solid var(--color-card-border);
  color: var(--color-text);
  font-size: 0.82rem;
  font-weight: 800;
  text-align: center;
}

.quick-sfx-volume-option.is-selected {
  background: var(--color-primary-light);
  border-color: var(--color-primary);
  color: var(--color-primary-dark);
}

.quick-sfx-volume-option:active {
  transform: scale(0.96);
}

/* 詳細設定（音ごとの個別変更）：折りたたみ式にして、普段の設定画面を大きくしない。 */
.sfx-settings-advanced {
  margin-top: 16px;
  border-top: 1px solid var(--color-card-border);
  padding-top: 12px;
}

.sfx-settings-advanced-summary {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  list-style: none;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--color-text);
  opacity: 0.85;
}

.sfx-settings-advanced-summary::-webkit-details-marker {
  display: none;
}

.sfx-settings-advanced-summary::before {
  content: "▸";
  color: var(--color-primary-dark);
}

.sfx-settings-advanced[open] .sfx-settings-advanced-summary::before {
  content: "▾";
}

.sfx-settings-advanced-badge {
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-size: 0.66rem;
  font-weight: 800;
}

.sfx-settings-reset-overrides-button {
  display: block;
  margin: 4px 0 10px;
  background: none;
  border: none;
  padding: 4px 2px;
  color: var(--color-primary-dark);
  font-size: 0.72rem;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* このプロジェクトの規約：display:を明示指定した要素は、hidden属性を付けても
   ブラウザ既定の[hidden]{display:none}が上書きされてしまうため、個別に打ち消す
   （css/style.css内の他の[hidden]系ルールと同じパターン）。 */
.sfx-settings-reset-overrides-button[hidden] {
  display: none;
}

.sfx-settings-advanced-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.sfx-settings-advanced-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 4px;
  border-bottom: 1px solid var(--color-card-border);
}

.sfx-settings-advanced-row-label-block {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.sfx-settings-advanced-row-label {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sfx-settings-advanced-row-badge {
  flex: none;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-size: 0.6rem;
  font-weight: 800;
}

.sfx-settings-advanced-row-controls {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
}

.sfx-settings-advanced-row-select {
  font-size: 0.72rem;
  padding: 4px 6px;
  border-radius: 8px;
  border: 1px solid var(--color-card-border);
  background: var(--color-surface);
  color: var(--color-text);
  max-width: 34vw;
}

.sfx-settings-advanced-row-preview-button {
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1.5px solid var(--color-primary);
  background: var(--color-surface);
  color: var(--color-primary-dark);
  font-size: 0.7rem;
}

.sfx-settings-volume-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.sfx-settings-volume-value {
  font-size: 0.82rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
}

.sfx-settings-volume-range {
  width: 100%;
  margin-top: 6px;
}

#sfx-toggle-button-start {
  width: auto;
  height: auto;
  padding: 5px 12px;
  border-radius: 999px;
  gap: 5px;
  font-size: 0.72rem;
  font-weight: 700;
}

#sfx-toggle-button-start svg {
  width: 14px;
  height: 14px;
}

.quiz-back-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin: 0 0 6px;
  padding: 6px 4px;
  border: none;
  background: none;
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
}

/* 【2026-09-15発見・修正・実機回帰バグ】display:inline-flexを明示指定しているため、
   [hidden]の既定（display:none）を上書きしてしまう（12章の教訓と同じ既知パターン）。
   この上書きが無かったため、オンライン対戦の結果画面でホスト専用の「⌂ホームへ戻る」
   リンク（ゲストには本来hidden=trueになるはず）が、ホスト・ゲストを問わず常に
   表示されたままになっていた（本人の実機報告「ゲストにホスト用ボタンが出る」の
   直接原因の1つ）。 */
.quiz-back-link[hidden] {
  display: none;
}

.quiz-back-link:active {
  transform: scale(0.94);
}

/* キーボード操作時のフォーカス表示。ブラウザ標準の黒い矩形だと世界観から浮いて見えるため、
   .single-group-header（収録曲一覧のアコーディオン見出し）と同じ考え方でテーマカラーに寄せる。
   .back-link（収録曲一覧・プレイ履歴の「戻る」）も同じ理由で未対応だったので、あわせて揃える。 */
.quiz-back-link:focus-visible,
.back-link:focus-visible {
  outline: 2px solid var(--color-primary-dark);
  outline-offset: 2px;
  border-radius: 8px;
}

/* ===== タイマー（経過秒数）・進捗表示 =====
   タイマーはゲームのHUD（状態表示）なので、少し大きめ・太めにして目立たせる。 */
#question-progress {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: fit-content;
  margin: 0 auto 4px;
  padding: 5px 14px;
  border-radius: 999px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

#question-progress::before {
  content: "♪";
  color: var(--color-secondary);
  font-size: 0.9em;
}

/* 出題の進み具合を示すドット。答え終えた問題・今の問題・まだの問題で見た目を変える */
.progress-dots {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin: 8px 0 4px;
}

.progress-dots .dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 2px solid var(--color-primary);
  background-color: var(--color-surface);
  transition: background-color var(--transition-fast), width var(--transition-fast), height var(--transition-fast);
}

.progress-dots .dot.is-done {
  background-color: var(--color-primary);
}

/* 「今の問題」のドットは、表示された瞬間に軽くポップして目に留まりやすくする */
.progress-dots .dot.is-current {
  width: 14px;
  height: 14px;
  background-color: var(--color-accent);
  border-color: var(--color-accent);
  animation: dotPop 320ms ease-out;
}

@keyframes dotPop {
  0% {
    transform: scale(0.4);
  }
  60% {
    transform: scale(1.25);
  }
  100% {
    transform: scale(1);
  }
}

#timer-display {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 6px;
  width: fit-content;
  margin: 4px auto 0;
  padding: 8px 22px;
  border-radius: 999px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  box-shadow: 0 6px 16px -8px rgba(255, 79, 150, 0.35);
  font-size: 1.7rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums; /* 秒数の桁が変わっても数字の位置がガタつかないようにする */
  color: var(--color-primary-dark);
}

#timer-display::before {
  content: "⏱";
  font-size: 0.55em;
  color: var(--color-secondary);
}

/* スタート画面：選択中の出題数・カテゴリに対応する自己ベストを示す、控えめなチップ。
   主役はスタートボタンなので、目立たせすぎない小さめのサイズにしている。
   条件部分（5問・全曲など）は控えめに、ベストの点数は少し強調して、情報の優先順位を分けている。 */
.mode-best-chip {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 6px;
  width: fit-content;
  margin: 4px auto 18px;
  padding: 6px 16px;
  border-radius: 999px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  font-size: 0.78rem;
}

.mode-best-icon {
  width: 14px;
  height: 14px;
  align-self: center;
  flex: none;
  color: var(--color-accent);
}

.mode-best-condition {
  color: var(--color-text);
  opacity: 0.6;
  font-weight: 700;
}

.mode-best-value {
  color: var(--color-primary-dark);
  font-weight: 800;
}

/* 記録がまだない組み合わせのときは、トロフィーと点数表示を控えめなグレー系にする。
   「達成できていない」ことが色でも伝わるようにする。 */
.mode-best-chip.is-empty .mode-best-icon {
  color: var(--color-text);
  opacity: 0.5;
}

.mode-best-chip.is-empty .mode-best-value {
  color: var(--color-text);
  opacity: 0.6;
}

/* ===== メッセージ類 ===== */
.error-message {
  color: var(--color-danger);
  background-color: var(--color-danger-soft);
  border: 1px solid var(--color-danger);
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 0.85rem;
  text-align: center;
}

/* 送信失敗ではなく「今は押せない理由」の案内用（赤いエラーに見せない）。 */
.error-message.is-notice {
  color: var(--color-text);
  background-color: rgba(150, 150, 150, 0.12);
  border: 1px solid rgba(150, 150, 150, 0.35);
}

/* 【2026-09-08新設・本人指示F：早押し成功表示の再デザイン】早押しバトルで勝者が確定した
   瞬間だけの専用スタイル。汎用の.error-message/.is-noticeの薄いグレー表示から、
   答え合わせカード（.lyrics-quiz-answer-reveal）と同じピンク×ゴールド系の配色へ変える
   ことで、他の「お知らせ」文言と混同せず、「勝った」という特別さが一目で伝わるようにする。 */
.error-message.is-steal-success {
  position: relative;
  color: var(--color-primary-dark);
  background: linear-gradient(120deg, var(--color-primary-light), #fff2bf 160%);
  border: 1px solid rgba(255, 111, 168, 0.4);
  font-size: 0.95rem;
  font-weight: 800;
  padding: 10px 12px;
  box-shadow: 0 8px 18px -10px rgba(255, 105, 180, 0.45);
  animation: answerRevealPop 320ms cubic-bezier(0.22, 1, 0.36, 1);
}

@media (prefers-reduced-motion: reduce) {
  .error-message.is-steal-success {
    animation: none;
  }
}

.feedback-message {
  text-align: center;
  font-size: 1.2rem;
  font-weight: 800;
  color: var(--color-text);
}

/* 正解・不正解を、文字色でも一目で分かるようにする */
.feedback-message.is-correct {
  color: var(--color-primary-dark);
  animation: feedbackPop 320ms ease-out;
}

.feedback-message.is-wrong {
  color: var(--color-danger);
  animation: feedbackPop 320ms ease-out;
}

@keyframes feedbackPop {
  0% {
    opacity: 0;
    transform: translateY(4px) scale(0.9);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* ===== 結果画面 ===== */

/* ボタンを並べる汎用の入れ物。横並び・縦並びどちらにも使えるよう、
   並び方向は使う場所ごとに指定する */
.button-row {
  display: flex;
  gap: 10px;
}

/* 【2026-09-15発見・修正・実機回帰バグ】display:flexを明示指定しているため、[hidden]の
   既定（display:none）を上書きしてしまう（12章の教訓と同じ既知パターン、.quiz-back-link
   と全く同じ原因）。この上書きが無かったため、オンライン対戦の結果画面でホスト専用の
   ボタン行（elements.resultHostActions等、「もう一度」「ルーム設定に戻る」）が、
   hidden=trueを設定してもゲスト端末で常に表示されたままになっていた。本人の実機報告
   「ゲストにもう一度／ルーム設定に戻るボタンが出る」の根本原因。ホスト・自動移譲・PWA
   更新のズレは無関係で、CSSの詳細度バグにより毎回・全モードで再現する問題だった。 */
.button-row[hidden] {
  display: none;
}

/* 【2026-09-06発見・修正、本人指示：実機フィードバック⑦⑨】.primary-buttonは単独で
   画面いっぱいに使う前提（width:100%・margin-top:16px）で設計されているため、
   .button-row（.secondary-buttonと横並びにする想定のflexコンテナ）の中へそのまま
   置くと、flexの初期値（flex-basis:auto）がwidth:100%を基準に取ってしまい、
   .primary-button側が不釣り合いに広い領域を占有し、.secondary-button側が極端に
   狭く押しつぶされて文字が折り返される、という崩れが起きることを実機フィードバックの
   確認中に発見した（回答確認モーダルの「回答する」「戻る」ボタンで発覚したが、
   同じ構造（.button-row内にprimary-button＋secondary-button）を使う他のモーダル
   （例：試合後の確認系）にも同じ問題があったと考えられる）。.button-rowの中でだけ、
   両ボタンが均等にflex:1で幅を分け合うよう上書きする（.button-row外の単独使用には
   影響しない）。 */
.button-row .primary-button {
  width: auto;
  flex: 1;
  margin-top: 0;
}

/* 【2026-09-05新設、同日改訂・実機報告で発覚したバグ修正】対戦中、ホストだけに見える
   「ルーム設定へ戻る」ボタン（js/onlineBattleScreen.js・js/onlineLyricsQuizBattleScreen.js・
   js/onlineInstantBattleScreen.js・js/onlineInstantCoopBattleScreen.js制御）。
   常時表示の「✕対戦をやめる」より目立たせすぎないよう、小さめ・控えめな見た目にする。
   【バグの原因】.secondary-buttonはflex:1（.button-row等のflex親の中で使われる前提）を
   持つが、#quiz-screen・#online-lyrics-battle-question-screen・
   #instant-challenge-question-screenは`.is-active`時にdisplay:flex;flex-direction:column
   になる（安全域対応のための既存レイアウト、13629行目付近参照）。このボタンをその直下に
   置いたことで、flex:1がそのまま効いて画面の残り高さいっぱいに縦へ引き伸ばされ、
   border-radius:999pxとあいまって画面を覆う巨大な縦長カプセルになってしまっていた
   （一瞬バトル・一瞬協力の対戦画面は同じdisplay:flex化がされていないため、
   このバグは発生していなかった）。flex:noneで打ち消すことで、どの画面に置いても
   常に控えめな大きさになるようにする。 */
.online-battle-back-to-lobby-button {
  flex: none;
  display: inline-flex;
  width: auto;
  align-self: center;
  margin: 6px auto 0;
  padding: 5px 14px;
  min-height: 0;
  font-size: 0.7rem;
  opacity: 0.75;
}

/* 結果画面のボタン列：スマホでの押しやすさを優先し、縦2段に並べる。
   「もう一度挑戦する」（主ボタン）を上、「タイトルに戻る」（副ボタン）を下にする。 */
#result-actions {
  flex-direction: column;
}

/* 縦並びのときに、副ボタンが余った高さまで伸びてしまわないようにする
   （.secondary-buttonは元々、横並びのスキップ/答えを見るボタン用にflex:1になっているため） */
#result-actions .secondary-button {
  flex: none;
}

/* 得点・ランク・自己ベストをまとめる、達成感を演出するパネル */
.result-stats {
  background: rgba(255, 255, 255, 0.5);
  border: 1px solid var(--color-card-border);
  border-radius: 20px;
  padding: 18px 16px 14px;
  margin: 4px 0 18px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6);
}

#total-score-display {
  text-align: center;
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

/* ===== 今回間違えた曲（結果画面・復習結果画面で共通） =====
   通常プレイの結果でも、復習プレイの結果（まだ間違えた曲がある場合）でも、
   同じ仕組み・同じ見た目で出し分ける。間違いが1曲もなければセクションごと隠す。 */
.missed-songs-section {
  margin: 4px 0 16px;
}

.missed-songs-heading {
  margin: 0 0 8px;
  text-align: center;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.7;
}

.missed-songs-chip-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  margin-bottom: 10px;
}

.missed-song-chip {
  padding: 4px 12px;
  border-radius: 999px;
  background: var(--color-danger-soft);
  border: 1px solid var(--color-danger);
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-text);
}

/* 苦手曲モード確認画面の対象曲チップ（2026-08-06変更）。.missed-song-chip（単純な丸ピル）とは
   あえて別クラスにしている。「なぜ選ばれたか」の理由を2行目に表示する必要があり、
   .missed-song-chipは結果画面等でも共用しているため、そちらには手を加えたくないため。
   #weak-songs-chip-row自体は既存の.missed-songs-chip-row（flex-wrap）をそのまま流用する。 */
.weak-song-chip {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 12px;
  border-radius: 14px;
  background: var(--color-danger-soft);
  border: 1px solid var(--color-danger);
  max-width: 100%;
}

.weak-song-chip-title {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-text);
}

.weak-song-chip-reason {
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--color-danger);
  opacity: 0.85;
}

/* .secondary-buttonはもともと横並び用にinline-flex（幅は中身に合わせる）なので、
   ここでは他のボタンと揃うよう、ブロック要素として全幅にする */
.missed-songs-review-button {
  display: block;
  width: 100%;
}

/* ===== ランクバッジ =====
   結果画面の主役。文字そのものは常に単色でくっきり読めるようにし、
   特別感（縁取り・光・アイコン）はメダル側で段階的に表現する。
   ランクごとの見た目は rank-s/rank-a/rank-b/rank-c のクラスで切り替わる（main.jsが付け外しする）。 */
.rank-badge {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  margin: 6px 0 10px;
}

.rank-label {
  margin: 0;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  color: var(--color-text);
  opacity: 0.6;
}

/* 外枠：王冠・星などのはみ出す飾りの位置基準。ここではクリップしない */
.rank-medal {
  position: relative;
  width: 88px;
  height: 88px;
  animation: rankPop var(--transition-slow) ease-out;
}

/* 円そのもの。背景・縁取り・光の演出はここに閉じ込め、円の外にははみ出させない */
.rank-medal-circle {
  position: relative; /* 光の演出（::after）の位置基準にする */
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  overflow: hidden;
  border: 2px solid transparent;
  background: var(--color-surface);
}

.rank-letter {
  font-size: 2.4rem;
  font-weight: 800;
  line-height: 1;
}

/* ワンポイントの星飾り。デフォルトでは非表示にしておき、ランクごとに必要な分だけ表示する。
   王冠（メダルの真上）と高さ・位置をずらし、密集して見えないようにしている。 */
.rank-medal-spark {
  display: none;
  position: absolute;
  top: -3px;
  width: 14px;
  height: 14px;
}

.rank-medal-spark-left {
  left: -9px;
}

.rank-medal-spark-right {
  right: -9px;
}

/* 王冠。Sランクのときだけ表示する。星飾りより少し小さめにして、密集感を抑えている */
.rank-crown {
  display: none;
  position: absolute;
  top: -12px;
  left: 50%;
  width: 26px;
  height: 17px;
  transform: translateX(-50%);
}

@keyframes rankPop {
  0% {
    transform: scale(0.7);
    opacity: 0;
  }
  60% {
    transform: scale(1.15);
    opacity: 1;
  }
  100% {
    transform: scale(1);
  }
}

/* ----- Sランク：金色のメダル。縁取り・光ともに最も強く、王冠と星、光が走る演出付き ----- */
.rank-s .rank-medal-circle {
  border: 3px solid #f6cf6b;
  background: radial-gradient(circle at 32% 28%, #ffe9a8 0%, #e3ab3c 55%, #b8790e 100%);
  box-shadow: 0 0 0 5px rgba(245, 196, 81, 0.22), 0 14px 30px -10px rgba(184, 121, 14, 0.65);
}

.rank-s .rank-letter {
  color: #5c3a08;
}

.rank-s .rank-crown,
.rank-s .rank-medal-spark {
  display: block;
  color: var(--color-accent);
}

/* メダルの上を斜めに光が横切る演出（円の中だけにクリップされる） */
.rank-s .rank-medal-circle::after {
  content: "";
  position: absolute;
  top: 0;
  left: -60%;
  width: 40%;
  height: 100%;
  background: linear-gradient(120deg, transparent, rgba(255, 255, 255, 0.75), transparent);
  transform: skewX(-20deg);
  animation: rankMedalShine 2.6s ease-in-out infinite;
}

@keyframes rankMedalShine {
  0% {
    left: -60%;
  }
  40%, 100% {
    left: 130%;
  }
}

/* ----- Aランク：濃いピンクのメダル。白文字＋星1つ。
   飾りを増やすのではなく、内側の二重リングと上部のハイライトで
   「金属的な質感のあるメダル」に近づけている（単なる丸ボタンに見えないように） ----- */
.rank-a .rank-medal-circle {
  border: 2px solid rgba(255, 255, 255, 0.85);
  background:
    radial-gradient(ellipse at 50% 14%, rgba(255, 255, 255, 0.4), transparent 55%),
    linear-gradient(160deg, var(--color-primary), var(--color-primary-dark));
  box-shadow:
    0 10px 24px -10px rgba(255, 79, 150, 0.55),
    inset 0 0 0 3px rgba(255, 255, 255, 0.22);
}

.rank-a .rank-letter {
  color: #ffffff;
}

.rank-a .rank-medal-spark-right {
  display: block;
  color: var(--color-accent);
}

/* ----- Bランク：パステルブルーの二重リング。銀メダルのような落ち着いた見た目 ----- */
.rank-b .rank-medal-circle {
  border: 2px solid #eaf6ff;
  background: linear-gradient(160deg, #eaf6ff, #bfe4fb);
  box-shadow: 0 0 0 3px var(--color-secondary), 0 8px 18px -12px rgba(111, 189, 242, 0.4);
}

.rank-b .rank-letter {
  color: #2c6ea8;
}

/* ----- Cランク：薄い実線の縁取り。メダルというより「よくがんばりました」に近い、優しい見た目。
   点線は「無効状態・未設定」のUIと誤解されやすいため、薄い一重の実線に変更した（2026-07-27）。
   光や飾りを足さず、4段階の中で一番シンプルな見た目のままにしている。 ----- */
.rank-c .rank-medal-circle {
  border: 2px solid #cfc6db;
  background: linear-gradient(160deg, #f3f0f8, #dcd6e6);
}

.rank-c .rank-letter {
  color: #6b6478;
}

#high-score-display {
  text-align: center;
  font-size: 0.95rem;
  color: var(--color-text);
}

/* 自己ベスト更新のお知らせ。他の丸いチップ類と揃えた見た目にする */
#new-record-badge {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: fit-content;
  margin: 10px auto 0;
  font-size: 1rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background-color: var(--color-accent-soft);
  border: 1px solid var(--color-accent);
  border-radius: 999px;
  padding: 8px 18px;
  box-shadow: 0 8px 20px -10px rgba(255, 217, 61, 0.7);
  animation: rankPop var(--transition-slow) ease-out;
}

/* display:flexの指定がhidden属性より優先されてしまい、JSで非表示にしても
   表示され続けていた不具合の修正。hidden属性がある場合は必ずdisplay:noneにする。 */
#new-record-badge[hidden] {
  display: none;
}

/* ===== 称号（実績）アイコンメダル =====
   結果画面のチップ・称号一覧のカード、両方の称号名の横に添える小さな円形アイコン。
   js/achievementIcons.jsが組み立てたSVGを、ここで称号ごとの色に染める
   （.is-{iconKey}は.achievement-icon-medal自身に付く。旧.title-icon-medal／
   [data-title-id]方式は、称号システム刷新（2026-08-07）にともない全面的に置き換えた）。 */
.achievement-icon-medal {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

.achievement-icon-medal svg {
  width: 58%;
  height: 58%;
}

/* 成長段階系3系統（イントロ＝青系／シャッフル＝紫系／リリック＝珊瑚系）：
   系統内はビギナー→チャレンジャー→エースの順に色だけ濃くする（形は共通、
   js/achievementIcons.jsのHEADPHONE_PATH／SHUFFLE_PATH／LYRIC_CARD_PATH参照）。
   エースだけアイコンに星バッジが追加され、かつ縁取りを付けて一段階だけ特別感を出すが、
   ノーミスマスターや表マスター・裏称号・複合称号より必ず控えめに留める
   （発光アニメーションは使わない。本人指示：既存の最上位称号より地味に）。 */
.achievement-icon-medal.is-intro_beginner {
  background: linear-gradient(160deg, #cfe6ff, #8fbdf0);
  color: #1c3a5e;
}
.achievement-icon-medal.is-intro_challenger {
  background: linear-gradient(160deg, #9cc6f5, #4f8fd9);
  color: #0f2942;
}
.achievement-icon-medal.is-intro_ace {
  background: linear-gradient(160deg, #6fb1ff, #2a6fc9);
  color: #ffffff;
  border: 1.5px solid rgba(255, 255, 255, 0.85);
}

/* 【2026-08-30追加・本人指示④】アウトロ系＝ピンク系（既存の.is-intro/shuffle/lyricと
   区別できる新しい色相として、アプリ全体のブランドカラーである--color-primary系を採用）。 */
.achievement-icon-medal.is-outro_beginner {
  background: linear-gradient(160deg, #ffd6e8, #ff9dc2);
  color: #6b1638;
}
.achievement-icon-medal.is-outro_challenger {
  background: linear-gradient(160deg, #ff9dc2, #ff5f96);
  color: #4a0f28;
}
.achievement-icon-medal.is-outro_ace {
  background: linear-gradient(160deg, #ff6fa8, #d92e6b);
  color: #ffffff;
  border: 1.5px solid rgba(255, 255, 255, 0.85);
}

.achievement-icon-medal.is-shuffle_beginner {
  background: linear-gradient(160deg, #e3d6ff, #b9a0f0);
  color: #3a215e;
}
.achievement-icon-medal.is-shuffle_challenger {
  background: linear-gradient(160deg, #cbadf5, #9868dd);
  color: #2c1447;
}
.achievement-icon-medal.is-shuffle_ace {
  background: linear-gradient(160deg, #b18cf0, #7c3fd0);
  color: #ffffff;
  border: 1.5px solid rgba(255, 255, 255, 0.85);
}

.achievement-icon-medal.is-lyric_beginner {
  background: linear-gradient(160deg, #ffe0cf, #ffb695);
  color: #6b2f10;
}
.achievement-icon-medal.is-lyric_challenger {
  background: linear-gradient(160deg, #ffc19c, #ff9159);
  color: #5c2308;
}
.achievement-icon-medal.is-lyric_ace {
  background: linear-gradient(160deg, #ff9d68, #f06a2c);
  color: #ffffff;
  border: 1.5px solid rgba(255, 255, 255, 0.85);
}

/* 【2026-08-30追加・本人指示⑦】一瞬チャレンジ系＝ティール系（他4系統と区別できる新色相）。 */
.achievement-icon-medal.is-instant_beginner {
  background: linear-gradient(160deg, #cdf5ec, #7fdfca);
  color: #06392c;
}
.achievement-icon-medal.is-instant_challenger {
  background: linear-gradient(160deg, #7fdfca, #34b797);
  color: #04241b;
}
.achievement-icon-medal.is-instant_ace {
  background: linear-gradient(160deg, #34c9a3, #0f8f70);
  color: #ffffff;
  border: 1.5px solid rgba(255, 255, 255, 0.85);
}

/* ノーミスマスター：金色の盾（2026-08-14：ブロンズ/シルバー/ゴールド/プラチナは
   成長段階系（イントロビギナー/チャレンジャー/エース）と条件が完全重複していたため廃止した）。 */
.achievement-icon-medal.is-no_miss_master {
  background: radial-gradient(circle at 32% 28%, #fff3c4 0%, #ffd93d 55%, #b8790e 100%);
  color: #5c3a08;
  border: 1.5px solid rgba(255, 255, 255, 0.85);
}

.achievement-icon-medal.is-full_chorus_master,
.achievement-icon-medal.is-song_master,
.achievement-icon-medal.is-outro_master,
.achievement-icon-medal.is-instant_master {
  background: linear-gradient(160deg, var(--color-primary), var(--color-primary-dark));
  color: #ffffff;
}

.achievement-icon-medal.is-lightning_fast {
  background: var(--color-primary-dark);
  color: #fff9d6;
}

/* 【2026-08-30追加・本人指示⑬⑭】完全終曲（アウトロ裏チャレンジ）。 */
.achievement-icon-medal.is-complete_finale {
  background: linear-gradient(160deg, #6fa8ff, var(--color-primary-dark));
  color: #ffffff;
}

.achievement-icon-medal.is-melody_ace {
  background: linear-gradient(135deg, #b18cf0, #6fa8ff);
  color: #ffffff;
}

.achievement-icon-medal.is-lyric_master {
  background: linear-gradient(160deg, #ffb37a, var(--color-accent));
  color: #5c3a08;
}

/* 【2026-08-30追加・本人指示⑦⑬】即聞即答（一瞬チャレンジ裏チャレンジ）。 */
.achievement-icon-medal.is-instant_flash_answer {
  background: linear-gradient(135deg, #34c9a3, #0f8f70);
  color: #ffffff;
}

/* 王冠のviewBoxは正方形のSVG表示枠に収める際、縦方向が余って小さく表示されてしまう
   （横長の絵を正方形の枠に収めるので、上下に隙間ができる）ため、表示サイズを引き上げて補正している。
   さらに、このメダルは称号を初めて獲得したとき「composite」の金色チップの上に乗ることが多く、
   メダルの金色とチップの金色が同化して見えにくくなるため、細い白の縁取りで輪郭を出している。 */
.achievement-icon-medal.is-equal_love_master,
.achievement-icon-medal.is-equal_love_complete {
  background: radial-gradient(circle at 32% 28%, #ffe9a8 0%, #e3ab3c 55%, #b8790e 100%);
  color: #5c3a08;
  border: 1.5px solid rgba(255, 255, 255, 0.85);
}

.achievement-icon-medal.is-equal_love_master svg,
.achievement-icon-medal.is-equal_love_complete svg {
  width: 72%;
  height: 72%;
}

/* ロック中（称号一覧で未取得の間）の、鍵マークだけのメダル。
   称号ごとの色指定（上のルール群）より必ず後に書くことで、詳細度が同じでも
   ロック中は確実にこの控えめな見た目が勝つようにする。 */
.achievement-icon-medal.is-locked {
  background: rgba(74, 46, 66, 0.08);
  color: var(--color-text);
  border: none;
  opacity: 0.55;
}

/* ＝LOVEマスター・＝LOVE完全制覇専用：鍵アイコンに切り替えず、王冠・王冠+ダイヤの
   形はそのまま見せつつ配色だけグレーに落とす（本人指示・2026-08-07：「未取得状態でも
   形や説明は見えるようにし、取得するとカラーと発光が解放される」）。
   is-equal_love_master／is-equal_love_complete（形・サイズ補正）より後に書き、
   詳細度が同じでもロック中はこちらの控えめな配色が勝つようにする。 */
.achievement-icon-medal.is-equal_love_master.is-locked-preview,
.achievement-icon-medal.is-equal_love_complete.is-locked-preview {
  background: rgba(74, 46, 66, 0.1);
  color: rgba(74, 46, 66, 0.4);
  border: 1.5px dashed rgba(74, 46, 66, 0.25);
}

/* ステップアップ（growth）バッジ：形はそのまま・彩度だけ落とす汎用ルール（2026-08-17追加）。
   is-intro_beginner等9種の色指定はそのまま活かし、grayscale()フィルターだけで
   「未取得（これから狙う形）」を表現する。1行で9種類をまとめて処理できるため、
   称号ごとに個別のlocked-preview配色を書かずに済む。 */
.achievement-icon-medal.is-locked-preview {
  filter: grayscale(0.85) opacity(0.6);
}

/* ===== 称号（実績）獲得演出 =====
   結果画面で、称号を獲得した瞬間に1件ずつポップに登場するチップ。
   ランクバッジ（Sランクの金メダル・Aランクのピンクメダル）と同じ配色・光の演出を流用し、
   「称号を取ると、ランクバッジに次ぐご褒美がもらえる」という統一感を出している。
   イントロクイズ・タイムアタック・ランダム再生クイズ・歌詞クイズの4つの結果画面すべてが、
   同じこのクラス一式（.achievement-event-list以下）を共有する。 */

.achievement-event-list {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
}

.achievement-event {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 9px 18px;
  border-radius: 16px;
  font-size: 0.85rem;
  text-align: center;
  /* js/achievementDisplay.jsのENTRANCE_ANIMATION_NAMEと名前を一致させる必要がある。
     animationendを起点に次のチップへ進むキュー方式になっているため、
     ここで名前がずれるとチップが正しいタイミングで切り替わらなくなる。 */
  animation: achievement-event-enter 480ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* 軽い反転＋フェード＋ポップ。ランクバッジのrankPopと同じ「ポップ」の感触を保ちつつ、
   称号らしい特別感を足すために、浅い角度のrotateXで一瞬だけ裏返るような動きを添えている
   （perspectiveの値を大きめにして、めまいがするような強い3D回転にはしていない）。 */
@keyframes achievement-event-enter {
  0% {
    opacity: 0;
    transform: perspective(600px) rotateX(-55deg) scale(0.85);
  }
  60% {
    opacity: 1;
    transform: perspective(600px) rotateX(6deg) scale(1.04);
  }
  100% {
    opacity: 1;
    transform: perspective(600px) rotateX(0deg) scale(1);
  }
}

/* 日本語には単語間のスペースがなく、ブラウザは初期設定でどの文字の間でも改行してよいと
   判断してしまう。チップのように横幅が窮屈になりやすい場所でこれを許すと、
   スマホ幅で称号名が1文字ずつバラバラに折り返されてしまう。称号名・キャプション・NEWバッジは
   どれも文字数が短く、1行のままでも画面からはみ出す心配がないため、改行させない指定にする。 */
.achievement-event-name {
  font-weight: 800;
  white-space: nowrap;
}

.achievement-event-caption {
  font-weight: 700;
  opacity: 0.85;
  white-space: nowrap;
}

.achievement-event-condition {
  font-size: 0.72rem;
  opacity: 0.8;
  max-width: 78vw;
}

/* 複合称号だけが持つ、特典・推しアイコン変化の予告（本人指示：見やすい場所に表示）。 */
.achievement-event-reward {
  margin-top: 2px;
  font-size: 0.74rem;
  font-weight: 800;
  max-width: 78vw;
}

.achievement-event-badge {
  display: inline-flex;
  align-items: center;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

.achievement-event-badge::before {
  content: "✦ ";
}

/* ----- 通常の称号：Sランクの金メダルと同じグラデーション・光が走る演出を流用する ----- */
.achievement-event--normal {
  position: relative;
  overflow: hidden;
  color: #5c3a08;
  background: radial-gradient(circle at 30% 25%, #ffe9a8 0%, #ffd93d 55%, #e3ab3c 100%);
  box-shadow: 0 0 0 3px rgba(255, 217, 61, 0.35), 0 10px 22px -10px rgba(184, 121, 14, 0.6);
}

.achievement-event--normal .achievement-event-badge {
  background: #5c3a08;
  color: #ffe9a8;
}

.achievement-event--normal::after {
  content: "";
  position: absolute;
  top: 0;
  left: -60%;
  width: 40%;
  height: 100%;
  background: linear-gradient(120deg, transparent, rgba(255, 255, 255, 0.8), transparent);
  transform: skewX(-20deg);
  animation: rankMedalShine 1.6s ease-in-out 1;
}

/* ----- 複合称号（＝LOVEマスター・＝LOVE完全制覇）：通常よりひと回り大きく、
   虹色の光が縁を巡る、一番豪華な演出にする（本人指示：「通常より豪華な演出」） ----- */
.achievement-event--composite {
  position: relative;
  overflow: hidden;
  padding: 14px 24px;
  color: #ffffff;
  font-size: 1rem;
  background: linear-gradient(135deg, #b18cf0, #ff8fc0 45%, #ffd93d 100%);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.5), 0 14px 30px -12px rgba(120, 60, 140, 0.55);
  animation: achievement-event-enter 480ms cubic-bezier(0.22, 1, 0.36, 1) both,
    achievement-composite-glow 1400ms ease-in-out 480ms infinite;
}

@keyframes achievement-composite-glow {
  0%,
  100% {
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.5), 0 14px 30px -12px rgba(120, 60, 140, 0.55);
  }
  50% {
    box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.75), 0 18px 40px -12px rgba(120, 60, 140, 0.75);
  }
}

.achievement-event--composite .achievement-event-name {
  font-size: 1.1rem;
}

.achievement-event--composite .achievement-event-badge {
  background: #ffffff;
  color: #7a4a9a;
}

.achievement-event--composite::after {
  content: "";
  position: absolute;
  top: 0;
  left: -60%;
  width: 40%;
  height: 100%;
  background: linear-gradient(120deg, transparent, rgba(255, 255, 255, 0.9), transparent);
  transform: skewX(-20deg);
  animation: rankMedalShine 1.8s ease-in-out 1;
}

/* 【2026-11-XX新設・本人指示27：推しアイコンに特別バッジが付く3称号の獲得演出を、
   イントロマスター＜＝LOVEマスター＜＜＝LOVE完全制覇の順で段階的に豪華にする】
   ----- イントロマスター：通常よりひと回り豪華だが、複合称号（＝LOVEマスターへの道の
   完成）ほどではない中間の格。イントロマスター専用バッジ（js/oshiBadge.js、銀灰色の
   メダル）と同じトーンの、通常よりやや落ち着いた金〜銀のグラデーションにする ----- */
.achievement-event--special {
  position: relative;
  overflow: hidden;
  padding: 11px 20px;
  color: #4a2e42;
  font-size: 0.92rem;
  background: radial-gradient(circle at 30% 25%, #fff8e6 0%, #ffe9a8 45%, #d9b45c 100%);
  box-shadow: 0 0 0 3px rgba(255, 233, 168, 0.55), 0 12px 26px -11px rgba(184, 121, 14, 0.55);
  animation: achievement-event-enter 480ms cubic-bezier(0.22, 1, 0.36, 1) both,
    achievement-composite-glow 1500ms ease-in-out 480ms 2;
}

.achievement-event--special .achievement-event-name {
  font-size: 1.02rem;
}

.achievement-event--special .achievement-event-badge {
  background: #4a2e42;
  color: #ffe9a8;
}

.achievement-event--special::after {
  content: "";
  position: absolute;
  top: 0;
  left: -60%;
  width: 40%;
  height: 100%;
  background: linear-gradient(120deg, transparent, rgba(255, 255, 255, 0.85), transparent);
  transform: skewX(-20deg);
  animation: rankMedalShine 1.7s ease-in-out 1;
}

/* ----- ＝LOVE完全制覇：表裏ともに極めた最高到達点にふさわしい、3段階の中で最も豪華な
   演出。複合称号の紫〜ピンク〜金のグラデーションに、完全制覇バッジ（ダイヤ）のトーンである
   青紫を足し、光の輪も一段強くする（本人指示：「小さく表示されても完全制覇だと分かる
   専用エンブレム級」を、獲得演出でも一貫させる） ----- */
.achievement-event--supreme {
  position: relative;
  overflow: hidden;
  padding: 16px 26px;
  color: #ffffff;
  font-size: 1.05rem;
  background: linear-gradient(135deg, #6fa8ff 0%, #b18cf0 40%, #ff8fc0 70%, #ffd93d 100%);
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.6), 0 16px 34px -12px rgba(74, 46, 130, 0.6);
  animation: achievement-event-enter 480ms cubic-bezier(0.22, 1, 0.36, 1) both,
    achievement-supreme-glow 1300ms ease-in-out 480ms infinite;
}

@keyframes achievement-supreme-glow {
  0%,
  100% {
    box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.6), 0 16px 34px -12px rgba(74, 46, 130, 0.6);
  }
  50% {
    box-shadow: 0 0 0 7px rgba(255, 255, 255, 0.85), 0 20px 46px -12px rgba(74, 46, 130, 0.85);
  }
}

.achievement-event--supreme .achievement-event-name {
  font-size: 1.16rem;
}

.achievement-event--supreme .achievement-event-badge {
  background: #ffffff;
  color: #5457b8;
}

.achievement-event--supreme::after,
.achievement-event--supreme::before {
  content: "";
  position: absolute;
  top: 0;
  left: -60%;
  width: 40%;
  height: 100%;
  background: linear-gradient(120deg, transparent, rgba(255, 255, 255, 0.95), transparent);
  transform: skewX(-20deg);
}

.achievement-event--supreme::after {
  animation: rankMedalShine 2s ease-in-out 1;
}

/* 2本目の光をわずかに遅らせて流し、通常・特別・複合よりもさらに豪華な「二重の光」にする。 */
.achievement-event--supreme::before {
  animation: rankMedalShine 2s ease-in-out 0.4s 1;
}

/* .rules-linkはdisplay:blockを明示しているため、hidden属性だけでは非表示にならない。
   #new-record-badge・.modal-overlay等と同じ原因なので、同じ対策を入れておく。 */
.rules-link[hidden] {
  display: none;
}

#answer-log-list {
  list-style: none;
  padding: 0;
}

#answer-log-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border-radius: 8px;
  padding: 8px 12px;
  margin-bottom: 6px;
}

.answer-log-text {
  flex: 1;
  min-width: 0; /* 曲名が長いときに、右側のバッジを押し出さず折り返せるようにする */
}

/* 回答時間を示す、時計アイコン付きの小さなバッジ */
.answer-time-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  flex: none;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  font-size: 0.72rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--color-primary-dark);
  white-space: nowrap;
}

.answer-time-badge::before {
  content: "⏱";
  font-size: 0.85em;
  color: var(--color-secondary);
}

/* 正解した問題は正解の選択肢と同じ黄色系トーンに、不正解は赤系トーンにして一目で分かるようにする */
#answer-log-list li.is-correct-row {
  background-color: var(--color-accent-soft);
}

#answer-log-list li.is-wrong-row {
  background-color: var(--color-danger-soft);
}

/* ===== ルール説明モーダル =====
   スタート画面の「あそびかた」リンクから開く、得点表・ランク基準・カテゴリの意味をまとめた画面。
   start/quiz/resultの3画面切り替えとは独立した、単純な表示/非表示のオーバーレイとして実装している。
   結果画面ほど演出を効かせず、読みやすさを優先した見た目にしている。 */

/* あそびかた・収録曲一覧、2つの入口をまとめる場所。スタートボタンより下に、控えめに並べる */
/* スタートボタンより目立たせたくないので、下線付きのテキストリンクだけの控えめな見た目にする */
.rules-link {
  display: block;
  width: fit-content;
  margin: 0;
  padding: 4px;
  border: none;
  background: none;
  color: var(--color-text);
  opacity: 0.65;
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 700;
  text-decoration: underline;
  cursor: pointer;
}

/* イントロクイズ本体の説明のため、スタートボタンの真下・中央に置く
   （本人フィードバック：以前は画面最下部で他の機能と見分けがつかなかった）。 */
.start-rules-link {
  display: block;
  width: fit-content;
  margin: 10px auto 0;
  text-align: center;
}

/* 【2026-08-30追加、本人指示】「あそびかた・とくてんのルール」「遊び方ガイド」の2つを
   横並びで中央にまとめる入れ物。スタートボタン直下という、初めて遊ぶ人が必ず目にする
   位置に「説明系リンク」を集約する（遊び方ガイドはホーム上部クイックナビから移動してきた）。
   狭い画面では自然に折り返す（.start-rules-linkの個別margin:0で二重の余白を防ぐ）。 */
.start-help-links {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 18px;
  margin-top: 10px;
}

.start-help-links .start-rules-link {
  margin: 0;
}

.rules-link:active {
  opacity: 0.9;
}

/* 画面全体を覆うオーバーレイ。中央にモーダルカードを配置する */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 20; /* 背景演出（z-index:0）・ゲームフレーム（z-index:2）より必ず手前に表示する */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(74, 46, 66, 0.45);
}

/* displayの指定がhidden属性より優先されてしまう問題への対策
   （#new-record-badge・.secondary-buttonと同じ原因なので、同じ対策を最初から入れておく） */
.modal-overlay[hidden] {
  display: none;
}

/* モーダルの中身。他の画面のようなガラスの透け感は使わず、不透明な背景で文字の読みやすさを優先する */
/* 【2026-09-06新設、本人指示：実機フィードバック②】回答確認モーダル
   （js/answerConfirmPrompt.js）の曲名部分だけ、他の見出しと見分けやすいよう強調する。
   【2026-09-06改訂・本人のiPhone実機報告：長い曲名でレイアウトが崩れる】以前は
   「「曲名」で回答しますか？」を1つの文として横並びのままcenter寄せしていたため、
   長い英語曲名（例：「Sweetest girl」）のとき、ブラウザが単語・かぎ括弧・末尾の
   「で回答しますか？」まで区別なく折り返し、意味のまとまりを無視した不自然な分割に
   なっていた。曲名部分（かぎ括弧込み）と末尾の定型文言を別ブロック（縦積み）に分け、
   曲名だけが独立して2行まで自然に折り返せるようにし、末尾の定型文言は常に1行のまま
   崩れないようにする。 */
.answer-confirm-modal-title {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  text-align: center;
}

.answer-confirm-modal-title-song {
  overflow-wrap: break-word;
}

.answer-confirm-modal-title-song span {
  color: var(--color-primary-dark);
}

.answer-confirm-modal-title-suffix {
  white-space: nowrap;
}

.modal-card {
  position: relative;
  width: 100%;
  max-width: 400px;
  max-height: 85vh;
  overflow-y: auto;
  /* 縦スクロールは必要だが、横方向は常に隠す。overflow-yをautoにすると仕様上overflow-xも
     autoとして扱われてしまい、中の要素が1pxでもはみ出すと横スクロールバーが出てしまうため、
     明示的にhiddenで打ち消しておく（×ボタンの当たり判定拡張がこの原因になった実績があるため）。 */
  overflow-x: hidden;
  /* 中身が長くてスクロールバーが出る/出ないで右端の見た目・当たり判定が変わらないよう、
     スクロールバーの分の余白を常に確保しておく（対応ブラウザのみ。非対応でも実害はない）。
     ×ボタンがスクロールバーと近い位置にあり、下側が押しづらいという指摘があったための対策。 */
  scrollbar-gutter: stable;
  background: var(--color-surface);
  border: 1px solid var(--color-card-border);
  border-radius: 20px;
  padding: 26px 20px 20px;
  box-shadow: var(--shadow-card);
  animation: screenEnter var(--transition-slow) cubic-bezier(0.22, 1, 0.36, 1);
  /* 【2026-08-15追加・本人報告の不具合対応】PCでマウスホイール操作をしていると、
     モーダル内のスクロールが端まで達した瞬間に「スクロールの連鎖」が起き、
     背後のページ（ライブコールモードの曲一覧など）まで一緒に動いてしまう現象があった。
     containを指定すると、このモーダルの中でスクロールが完結し、背後には伝わらなくなる。 */
  overscroll-behavior: contain;
}

/* ×ボタン：見た目の丸と実際のクリック領域を必ず一致させるため、
   width/heightで固定サイズを確保したうえでdisplay:flexで×を中央揃えにする。
   paddingはボタンのサイズ計算に混ぜたくないので0にし、サイズはwidth/heightだけで決める。
   タップ対象として小さすぎないよう、丸の見た目自体も44×44pxを確保する
   （ルール説明・称号一覧、両方のモーダルの×ボタンで共通して使うクラス）。 */
.modal-close-button {
  position: absolute;
  top: 6px;
  right: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  margin: 0;
  border: none;
  border-radius: 50%;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

/* 見た目の丸はそのままに、クリック判定だけを一回り広げる。
   端ギリギリを押したときの反応を良くするための、見た目に影響しない当たり判定の拡張。
   ボタンはモーダルカードの右端から6px（.modal-close-buttonのtop/right）の位置にあるため、
   ここを6px以上広げるとカードの外側にはみ出し、横スクロールバーの原因になる。
   安全に収まる4pxにとどめている。 */
.modal-close-button::after {
  content: "";
  position: absolute;
  inset: -4px;
}

.modal-close-button:active {
  transform: scale(0.92);
}

.modal-card h3 {
  margin: 18px 0 8px;
  font-size: 0.95rem;
  color: var(--color-primary-dark);
}

.modal-lead {
  text-align: center;
  margin: 4px 0 0;
  font-size: 0.9rem;
}

/* 得点表。9段階を省略せずすべて表示する（自己ベストやランクに直接関わる情報なので正確さを優先する） */
.score-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.score-table th,
.score-table td {
  padding: 6px 8px;
  border-bottom: 1px solid var(--color-card-border);
  text-align: left;
}

.score-table th:last-child,
.score-table td:last-child {
  text-align: right;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.score-table tbody tr:nth-child(even) {
  background: rgba(255, 111, 168, 0.06);
}

/* ランク判定の4段階を横並びで見せる場所 */
.rules-rank-list {
  display: flex;
  justify-content: space-between;
  gap: 6px;
}

/* 結果画面の.rank-badgeを縮小して流用する。色・縁取り・光の演出はrank-s/a/b/cのCSSがそのまま効く */
.rules-rank-badge {
  margin: 0;
  gap: 4px;
}

.rules-rank-badge .rank-medal {
  width: 46px;
  height: 46px;
}

.rules-rank-badge .rank-letter {
  font-size: 1.2rem;
}

.rules-rank-badge .rank-crown {
  top: -7px;
  width: 14px;
  height: 9px;
}

.rules-rank-badge .rank-medal-spark {
  top: -2px;
  width: 8px;
  height: 8px;
}

.rules-rank-badge .rank-medal-spark-left {
  left: -5px;
}

.rules-rank-badge .rank-medal-spark-right {
  right: -5px;
}

.rules-rank-condition {
  margin: 0;
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.75;
}

.modal-category-list {
  margin: 0;
  padding-left: 18px;
  font-size: 0.85rem;
  line-height: 1.6;
}

/* ===== 収録曲一覧画面 =====
   81曲をシングル単位のアコーディオンで一覧し、各曲の試聴もできる画面。
   中身（アコーディオンの各行）はjs/songlist.jsがSONGSから組み立てる。 */

/* ヘッダー：左に「戻る」、中央にタイトル。両端をgridの1frずつにすることで、
   「戻る」の実際の文字幅に関わらずタイトルが常に中央に来るようにしている。 */
.list-header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: start;
  gap: 8px;
  margin-bottom: 4px;
}

.list-header .title-block {
  grid-column: 2;
}

.back-link {
  grid-column: 1;
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px 4px;
  border: none;
  background: none;
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
  /* 【2026-09-07追加・最終QAで発見】.list-headerは3列グリッド（戻るボタン/タイトル/空き列、
     両端1fr）で中央のタイトル列がauto（コンテンツに合わせて伸びる）のため、タイトルが
     長い画面（例：「オリジナル問題作成モード」）では中央列がタイトル全体を1行に収めようと
     広がり、その分だけ両端の戻るボタン列が圧迫され、アイコンと「戻る」の文字が2行に
     折り返されてしまっていた（オリジナル問題作成モードの選択画面で発見）。戻るボタン自体を
     折り返させない（white-space:nowrap）ことで、幅が足りない場合はタイトル側（日本語なので
     自然に複数行へ折り返せる）で吸収させる。 */
  white-space: nowrap;
}

.back-link-icon {
  width: 14px;
  height: 14px;
  flex: none;
}

.back-link:active {
  transform: scale(0.94);
}

/* 判定ルール等の説明モーダルを開く「？」ボタン。.list-headerの3列目（右端）に配置する。
   .modal-close-button（モーダルを閉じる×ボタン）と似た円形だが、一回り小さくしている。 */
.info-link-button {
  grid-column: 3;
  justify-self: end;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 800;
  cursor: pointer;
}

.info-link-button:active {
  transform: scale(0.92);
}

/* 【2026-11-XX追加・本人指示：[hidden]系CSSの全面監査で発見】.breakdown-chip-rowと
   同じ原因のため、同じ対策を追加（#live-call-mode-fullscreen-button等が対象）。 */
.info-link-button[hidden] {
  display: none;
}

/* .list-headerの3列目に、？ボタンだけでなくコールガイドボタンも並べて置くための
   ラッパー（2026-08-06追加）。中の.info-link-buttonはgrid-column指定を持つが、
   このラッパー自体がgridの子要素になるため、中のgrid-column指定はブラウザに無視され問題ない。 */
.list-header-actions {
  grid-column: 3;
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 6px;
}

.live-call-mode-guide-button {
  border: none;
  border-radius: 999px;
  padding: 6px 12px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
}

.live-call-mode-guide-button:active {
  transform: scale(0.96);
}

/* ===== コールガイドパネル（js/callGuidePanel.js、2026-08-06新設） ===== */

.call-guide-modal-card {
  max-width: 640px;
}

.call-guide-tab-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 14px 0;
}

.call-guide-tab-button {
  border: none;
  border-radius: 999px;
  padding: 7px 14px;
  background: rgba(255, 111, 168, 0.1);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  cursor: pointer;
}

.call-guide-tab-button.is-active {
  background: var(--color-primary);
  color: #fff;
}

.call-guide-tab-panel {
  max-height: 50vh;
  overflow-y: auto;
  /* .modal-cardの中にさらにスクロール領域が入れ子になっているため、ここでも
     スクロール連鎖を止めておく（.modal-cardのoverscroll-behavior:containと同じ理由）。 */
  overscroll-behavior: contain;
}

.call-guide-empty-state {
  color: var(--color-text);
  opacity: 0.7;
  font-size: 0.88rem;
  text-align: center;
  padding: 12px 0;
}

/* 「コールは必須ではありません」の初心者向けバナー、MIX・口上タブの一番上に置く
   （2026-08-24追加、本人指示セクション18）。強制感を出さない、やわらかい配色にする。 */
.call-guide-not-mandatory-banner {
  margin: 0 0 10px;
  padding: 10px 14px;
  border-radius: 12px;
  background: rgba(93, 200, 130, 0.14);
  color: #1c7a44;
  font-size: 0.84rem;
  font-weight: 700;
  line-height: 1.5;
  text-align: center;
}

/* MIX・口上・ガチ恋・ペンライト指定の用語を1〜2文で説明する導入ブロック
   （2026-08-24追加、本人指示セクション17：「専門用語を並べるだけにしないでください」）。
   375px幅でも読みやすいよう、用語名と説明文の間で折り返せる横並びレイアウトにする。 */
.call-guide-glossary {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 0 0 12px;
  padding: 10px 12px;
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.035);
}

.call-guide-glossary-row {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--color-text);
  opacity: 0.85;
}

.call-guide-glossary-row strong {
  color: var(--color-primary-dark);
  opacity: 1;
}

.penlight-color-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px 3px 5px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.045);
  font-size: 0.78rem;
  font-weight: 600;
}

.penlight-color-swatch {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, 0.15);
  flex-shrink: 0;
}

.penlight-source-note {
  margin: 4px 0 8px;
  color: var(--color-text);
  opacity: 0.7;
  font-size: 0.78rem;
}

.call-credit-badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(93, 111, 224, 0.14);
  color: #4a4fc4;
  font-size: 0.76rem;
  font-weight: 700;
}

.member-call-guide-list,
.song-call-guide-list,
.song-penlight-guide-list,
.mix-type-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.member-call-guide-row,
.song-call-guide-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.5);
}

.member-call-guide-name,
.song-call-guide-title,
.song-penlight-guide-title {
  font-weight: 700;
  font-size: 0.9rem;
}

.member-call-guide-chips,
.song-call-guide-badges,
.song-penlight-guide-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.song-penlight-guide-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.5);
}

/* コールガイドを開いたときに再生中だった曲の行を目立たせる（2026-08-06）。 */
.song-call-guide-row.is-current-song,
.song-penlight-guide-card.is-current-song {
  background: var(--color-primary-light);
  outline: 2px solid var(--color-primary);
  outline-offset: -2px;
}

.mix-type-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 12px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.5);
}

.mix-type-card.is-current-song {
  background: var(--color-primary-light);
  outline: 2px solid var(--color-primary);
  outline-offset: -2px;
}

.mix-type-header-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

.mix-type-label {
  font-weight: 700;
  font-size: 0.9rem;
}

.mix-type-song-specific-badge {
  display: inline-flex;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--color-accent-soft);
  color: #8a6d00;
  font-size: 0.68rem;
  font-weight: 700;
}

.mix-type-badge-row {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.mix-type-tag {
  display: inline-flex;
  padding: 2px 9px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.06);
  font-size: 0.7rem;
  font-weight: 600;
}

.mix-type-tag-difficulty-beginner {
  background: rgba(93, 200, 130, 0.18);
  color: #1c7a44;
}

.mix-type-tag-difficulty-intermediate {
  background: rgba(255, 179, 71, 0.2);
  color: #93590a;
}

.mix-type-tag-difficulty-advanced {
  background: rgba(255, 107, 107, 0.18);
  color: #a52b2b;
}

/* 情報の出所バッジ（2026-08-17追加、本人指示：「🌟メンバー考案／📣ライブ定番」等）。
   メンバー本人発信は最も目立つブランドピンクで強調し、他は控えめなグレー系にする。 */
.mix-type-tag-source-self {
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-weight: 800;
}

.mix-type-tag-source-official {
  background: rgba(93, 150, 200, 0.18);
  color: #1c4a7a;
}

.mix-type-tag-source-fan,
.mix-type-tag-source-reliable {
  background: rgba(0, 0, 0, 0.06);
  color: var(--color-text);
  opacity: 0.8;
}

.mix-type-summary {
  margin: 4px 0 0;
  font-size: 0.82rem;
  color: var(--color-text);
  opacity: 0.7;
}

.mix-type-text-lines {
  margin: 6px 0 0;
  padding-left: 1.4em;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.86rem;
  font-weight: 600;
}

.mix-type-text-reading {
  margin-left: 4px;
  font-size: 0.72rem;
  font-weight: 400;
  opacity: 0.7;
}

/* 行数が多い本文（曲専用ガチ恋キャンセル等）を折りたたむ「全文を見る」表示
   （2026-08-15追加、本人指示セクション13）。ネイティブの<details>/<summary>を使い、
   JS側で開閉状態を管理する必要がないようにしている。 */
.mix-type-text-details {
  margin: 6px 0 0;
}

.mix-type-text-details > .mix-type-text-lines {
  margin-top: 8px;
}

.mix-type-text-summary {
  cursor: pointer;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  list-style: none;
}

.mix-type-text-summary::-webkit-details-marker {
  display: none;
}

.mix-type-text-summary::before {
  content: "▶ ";
  display: inline-block;
  transition: transform var(--transition-fast, 0.15s);
}

.mix-type-text-details[open] > .mix-type-text-summary::before {
  transform: rotate(90deg);
}

/* 「①単語ごとに覚える」に続く「②実際に続けて唱えるとこうなる」の一続き表示
   （2026-08-24追加、本人指示セクション1・2）。矢印つなぎの1本の流れを、375px幅でも
   単語の途中で改行が起きないようword-break/line-heightを調整する。 */
.mix-type-continuous-line {
  margin: 6px 0 0;
  padding: 8px 10px;
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.04);
  font-size: 0.88rem;
  font-weight: 700;
  line-height: 1.7;
  word-break: keep-all;
  overflow-wrap: anywhere;
}

/* 「掛け声」見出し・「ワンポイント」box（2026-08-17追加）。掛け声本文を主役にし、
   375px幅でもリズム・区切りが1行に詰め込まれず読めるようにする（本人指示）。 */
.mix-type-text-heading {
  margin: 6px 0 0;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  opacity: 0.6;
}

.mix-type-beginner-tip {
  margin: 8px 0 0;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(255, 217, 61, 0.2);
  font-size: 0.78rem;
  line-height: 1.5;
  color: #6b4f00;
}

.mix-song-specific-banner {
  margin: 0 0 8px;
  padding: 8px 12px;
  border-radius: 12px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-weight: 700;
  font-size: 0.82rem;
  text-align: center;
}

/* 2026-08-15改訂：以前はカテゴリー絞り込みボタン（すべて/基本MIX/口上…）を切り替えて
   表示する方式だったが、「まず覚えたいMIX」の3件がボタン側の一覧にも重複して出てしまい
   分かりにくいという指摘があったため廃止した。代わりに、①〜④の見出しを常に上から順に
   並べる構成にした（js/callGuidePanel.jsのappendMixSection参照）。このクラスは
   4つの見出し全てで共通して使う。 */
.mix-section-heading {
  margin: 14px 0 8px;
  font-weight: 800;
  font-size: 0.88rem;
  color: var(--color-primary-dark);
}

/* 作品単位のお気に入り一括登録/解除の完了案内。
   .custom-quiz-presets-saved-bannerと同じ考え方・見た目（2026-08-04追加）。 */
.songlist-action-banner {
  width: fit-content;
  max-width: 100%;
  margin: 0 auto 10px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--color-song-favorite);
  background-color: rgba(255, 138, 92, 0.12);
  color: var(--color-song-favorite);
  font-size: 0.8rem;
  font-weight: 700;
  text-align: center;
}

.songlist-action-banner[hidden] {
  display: none;
}

/* 「すべての曲」「お気に入り」タブ（2026-08-04追加）。カテゴリバッジと似た配色にしつつ、
   タブであることが分かるよう、選択中は塗りつぶし・下線の代わりに背景色で強調する。 */
.songlist-tab-bar {
  display: flex;
  gap: 8px;
  margin: 4px 0 10px;
}

.songlist-tab-button {
  flex: 1;
  padding: 8px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-text);
  opacity: 0.6;
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  cursor: pointer;
  transition: background-color 0.15s ease, opacity 0.15s ease;
}

.songlist-tab-button.is-active {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #ffffff;
  opacity: 1;
}

/* お気に入り一覧・プレイリスト詳細で使う、シングル区分（アコーディオン）なしの
   フラットな曲リスト。.single-group-tracksは開閉アコーディオン専用（初期状態が
   display:noneなので流用できない）、.track-listはディスコグラフィーの別の見た目
   （区切り線つき）を持つ既存クラスのため、あえて名前を分けている（2026-08-04追加）。 */
.flat-track-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* 総曲数チップ。自己ベストチップと同じ、控えめな見た目に揃える */
.total-count-chip {
  display: block;
  width: fit-content;
  margin: 8px auto 8px;
  padding: 5px 14px;
  border-radius: 999px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.75;
}

.total-count-chip strong {
  color: var(--color-primary-dark);
  opacity: 1;
  font-variant-numeric: tabular-nums;
}

/* カテゴリ別の内訳チップ。「全81曲収録」チップの下に、小さめのチップで並べる */
.breakdown-chip-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  margin: 0 0 16px;
}

/* 【2026-11-XX追加・本人指示：[hidden]系CSSの全面監査で発見】displayを明示指定して
   いるため、[hidden]属性の既定（display:none）が上書きされてしまっていた
   （tests/cssHiddenAttributeEffectiveness.test.jsと同じ既知パターン）。 */
.breakdown-chip-row[hidden] {
  display: none;
}

.breakdown-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 3px;
  padding: 4px 12px;
  border-radius: 999px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.85;
}

.breakdown-chip strong {
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
}

/* シングル単位の折りたたみ1つ分 */
.single-group {
  border: 1.5px solid var(--color-card-border);
  border-radius: 16px;
  margin-bottom: 10px;
  background: rgba(255, 255, 255, 0.4);
  overflow: hidden;
}

.single-group-header {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border: none;
  background: none;
  font-family: inherit;
  text-align: left;
  color: var(--color-text);
  cursor: pointer;
}

.single-group-header:focus-visible {
  outline: 2px solid var(--color-primary-dark);
  outline-offset: -2px;
}

/* 見出し行の入れ物。「開閉」（.single-group-header）と、それとは別の操作領域
   （.single-group-bulk-actions＝全選択・全解除、または作品単位のお気に入りボタン）を
   横に並べる。横幅が足りないときは自然に2行へ折り返す。
   オリジナル問題作成モードの選曲画面（全選択・全解除）と、収録曲一覧（作品単位お気に入り、
   2026-08-04追加）の両方で使う共通クラス。 */
.single-group-header-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}

.single-group-bulk-actions {
  flex: none;
  display: flex;
  gap: 4px;
  padding: 8px 14px 8px 0;
}

.single-group-bulk-button {
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--color-card-border);
  background: none;
  font-family: inherit;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  white-space: nowrap;
  cursor: pointer;
}

.single-group-bulk-button:active {
  background: var(--color-primary-light);
}

/* 作品単位のお気に入り一括登録ボタン（収録曲一覧、2026-08-04追加）。
   曲ごとのハート（丸いアイコンのみ）とは違い、「全曲」という文字ラベルを添えた
   横長のピル型にして、押し間違えないよう見た目をはっきり区別している。
   未登録／一部登録済み／全登録済みの3状態を色で示す。 */
.single-group-favorite-button {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px 4px 8px;
  border-radius: 999px;
  border: 1px solid var(--color-card-border);
  background: none;
  font-family: inherit;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.75;
  white-space: nowrap;
  cursor: pointer;
}

.single-group-favorite-button svg {
  width: 13px;
  height: 13px;
  fill: currentColor;
}

.single-group-favorite-button:active {
  transform: scale(0.95);
}

/* 一部の曲だけ登録済み：枠線と文字をお気に入り色にして「途中」であることを示す */
.single-group-favorite-button.is-partial {
  border-color: var(--color-song-favorite);
  color: var(--color-song-favorite);
  opacity: 1;
}

/* 全曲登録済み：塗りつぶしてひと目で分かるようにする */
.single-group-favorite-button.is-full {
  border-color: var(--color-song-favorite);
  background: var(--color-song-favorite);
  color: #ffffff;
  opacity: 1;
}

/* 作品単位の一括選択ボタン（プレイリストへの曲追加画面、UI/UX再設計で追加）。
   お気に入りの一括登録ボタンと同じ「未選択／一部／全選択」3状態の考え方だが、
   お気に入りのコーラルオレンジと混同しないよう、こちらは寒色（--color-secondary系）にする。
   本人希望によりスマホでのタップ領域を44px前後確保する。 */
.single-group-select-button {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  min-height: 44px;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1.5px solid var(--color-card-border);
  background: var(--color-surface);
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.8;
  white-space: nowrap;
  cursor: pointer;
}

.single-group-select-button svg {
  width: 14px;
  height: 14px;
  flex: none;
}

.single-group-select-button:active {
  transform: scale(0.96);
}

.single-group-select-button.is-partial {
  border-color: var(--color-secondary);
  color: #2c6ea8;
  opacity: 1;
}

.single-group-select-button.is-full {
  border-color: var(--color-secondary);
  background: var(--color-secondary);
  color: #ffffff;
  opacity: 1;
}

.chevron {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--color-primary-dark);
  transition: transform var(--transition-base) ease;
}

.single-group.is-open .chevron {
  transform: rotate(90deg);
}

.single-group-name {
  flex: 1;
  min-width: 0;
  font-weight: 800;
  font-size: 0.92rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.track-count-chip {
  flex: none;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.55;
  font-variant-numeric: tabular-nums;
}

/* 収録曲がまだ出揃っていないシングルの見出し直下に添える案内（2026-08-17追加、
   song.comingSoonNote参照）。見出し行（曲名・曲数）とは横幅を取り合わない、独立した行にする
   （見出し行に押し込むと、375px幅で長い曲名が極端に潰れる不具合があったため）。 */
.coming-soon-note {
  /* .single-group-headerのpadding-left(14px)+chevron幅(16px)+gap(10px)と揃え、
     曲名の頭の位置に文字が始まるようにする。 */
  margin: -4px 0 8px 40px;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  opacity: 0.75;
}

.single-group-tracks {
  display: none;
  padding: 0 10px 10px;
}

.single-group.is-open .single-group-tracks {
  display: block;
}

/* 1曲分の行 */
.track-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border-radius: 10px;
  transition: background-color var(--transition-base) ease;
}

/* 検索で一致しない曲を隠すためのhidden属性が、display:flexに上書きされないようにする
   （.song-select-row[hidden]と同じ対策。12章の教訓：displayを明示指定した要素に
   hidden属性を使うときは、必ずこの上書きルールとセットにする）。 */
.track-row[hidden] {
  display: none;
}

.track-row.is-playing {
  background: var(--color-primary-light);
}

.play-button {
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-surface);
  color: var(--color-primary-dark);
  box-shadow: 0 3px 8px -3px rgba(255, 79, 150, 0.4);
  cursor: pointer;
  transition: transform var(--transition-fast) ease;
}

.play-button:active {
  transform: scale(0.9);
}

.play-button svg {
  width: 13px;
  height: 13px;
}

/* 音源がまだ存在しない曲の、押せない再生ボタンの代わりの印
   （2026-08-17追加）。.play-buttonと同じ32px円形の場所を保ち、他の行と左端の位置を揃えつつ、
   影・カーソルを消して「押せるボタンではない」ことが見た目でも伝わるようにする。 */
.play-button-placeholder {
  box-shadow: none;
  cursor: default;
  opacity: 0.4;
}

/* 音源・歌詞のどちらも利用できない曲の案内文（.track-audio-status-note、2026-08-17追加）。
   曲名の下に添える他のtrack-meta-lineと同じ流れに置きつつ、単なる説明文と見分けがつくよう
   コールガイドのcoming-soon-noteと同じ色・太字にする。.track-meta-line側の
   opacity:0.6を確実に上書きするため、あえて2クラス分の詳細度で指定する
   （定義順に依存せず、ファイル内でどこに書いても.track-meta-line単体より必ず勝つように）。 */
.track-meta-line.track-audio-status-note {
  color: var(--color-primary-dark);
  font-weight: 700;
  opacity: 0.75;
}

/* 「この曲を再生できませんでした」の案内文（.track-playback-error-note、2026-09-05追加）。
   「音源・歌詞 Coming Soon」（＝未読み込み）とは意味が異なる（読み込み済みだが再生失敗）ため、
   混同されないよう赤系（--color-danger、不正解と同じ色）にして、はっきり区別できるようにする。
   .track-meta-line側のopacity:0.6を確実に上書きするため、上と同じく2クラス分の詳細度で指定する。 */
.track-meta-line.track-playback-error-note {
  color: var(--color-danger);
  font-weight: 700;
  opacity: 0.85;
}

/* 再生/一時停止アイコンの切り替え。
   hidden属性・hiddenプロパティはインラインSVG要素への反映がブラウザによって不安定なため使わず、
   行の.is-playingクラスだけで見た目を決める、より確実なクラスベースの方式にしている。 */
.icon-pause {
  display: none;
}

.track-row.is-playing .icon-play {
  display: none;
}

.track-row.is-playing .icon-pause {
  display: block;
}

/* 選択中(is-playing)かつ一時停止中(is-audio-paused)は、アイコンを再生アイコンに戻す。
   クラス数が多い分セレクタの詳細度が上がるため、上記2ルールより後ろに書かなくても優先される。 */
.track-row.is-playing.is-audio-paused .icon-play {
  display: block;
}

.track-row.is-playing.is-audio-paused .icon-pause {
  display: none;
}

.track-row.is-playing .play-button {
  background: var(--color-primary-dark);
  color: #ffffff;
}

.track-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* 曲名は省略せず、長い場合はここだけ自然に折り返す
   （再生ボタン・カテゴリバッジはflex:noneで幅を保つため、押しつぶされない）
   2026-09-16改訂・本人指示：UI一貫性ルール（曲名は常に濃いピンク＋太字）。
   収録曲一覧・お気に入り一覧・プレイリスト詳細（すべてこの.track-titleを共用）で
   曲名の見え方が揃うよう、色をブランドピンク（--color-primary-dark）に統一した。
   カード自体（.track-row）がすでに再生ボタン・メタ情報を伴う十分な視認性を持つため、
   ピル化（背景・枠線）まではせず、色・太さだけの調整にとどめている。 */
.track-title {
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  overflow-wrap: break-word;
}

/* 歌唱メンバー・センター・補足説明：曲名より小さく薄い文字にし、自然に折り返す。
   人数の多いユニット曲でも、再生ボタン・カテゴリバッジと重ならないようにしている */
.track-meta-line {
  font-size: 0.7rem;
  line-height: 1.5;
  color: var(--color-text);
  opacity: 0.6;
  overflow-wrap: break-word;
}

/* 特別クレジット（作詞・MV監督など、通常と異なる曲だけに付く補足情報）。
   .track-meta-lineの見た目をベースに、他の行と紛れないよう少しだけ強調する
   （2026-08-23追加）。 */
.track-meta-line.track-credit-line {
  font-style: italic;
}

.track-credit-link {
  font-style: normal;
  color: var(--color-primary-dark);
  text-decoration: underline;
}

/* track-credit-linkをボタン要素で使う場合（アプリ内の別画面へ移動するクレジット）に、
   ブラウザ標準のボタン見た目をリセットしてリンクと同じ見た目に揃える */
button.track-credit-link {
  font: inherit;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

/* 試聴中の曲だけに表示する、再生位置バー */
.track-seek {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-top: 4px;
}

/* displayの指定がhidden属性より優先されてしまう問題への対策
   （.modal-overlay等と同じ理由なので、同じ対策を最初から入れておく） */
.track-seek[hidden] {
  display: none;
}

.seek-controls {
  display: flex;
  align-items: center;
  gap: 6px;
}

/* ネイティブのrange要素をそのまま使い、accent-colorだけでブランドカラーに合わせる。
   トラック・つまみの形状を作り込まないことで、ブラウザごとの見た目の違いをそのまま許容し、
   操作できることとコードのシンプルさを優先している */
.seek-range {
  flex: 1;
  width: 100%;
  height: 20px;
  margin: 0;
  accent-color: var(--color-primary-dark);
}

.seek-skip-button {
  flex: none;
  border: none;
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-primary-dark);
  font-size: 0.62rem;
  font-weight: 700;
  padding: 4px 7px;
  cursor: pointer;
}

.seek-skip-button:active {
  transform: scale(0.9);
}

/* 歌詞の全画面表示を開くボタン。±10秒ボタンと同じ行に収める小さいアイコンボタン。 */
.lyrics-fullscreen-open-button {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--color-surface);
  color: var(--color-primary-dark);
  cursor: pointer;
}

.lyrics-fullscreen-open-button svg {
  width: 13px;
  height: 13px;
}

.lyrics-fullscreen-open-button:active {
  transform: scale(0.9);
}

/* display:flexを指定しているクラスは、hidden属性を上書きしてしまう（CSSの優先順位で
   author側の指定がブラウザ標準の[hidden]より強くなるため）。歌詞データが無い曲で
   ボタンが消えなかった不具合の原因はこれだった（2026-08-03）。 */
.lyrics-fullscreen-open-button[hidden] {
  display: none;
}

/* 「プレイリストに追加」ボタン。歌詞全画面ボタンと同じ大きさ・並びにする（2026-08-04追加） */
.playlist-add-open-button {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--color-surface);
  color: var(--color-primary-dark);
  cursor: pointer;
}

.playlist-add-open-button svg {
  width: 13px;
  height: 13px;
}

.playlist-add-open-button:active {
  transform: scale(0.9);
}

/* ===== 同期歌詞パネル（試聴中の歌詞表示、収録曲一覧・オリジナル問題作成モード共通） =====
   歌詞データがある曲を再生したときだけ、js/lyricsSync.jsが行を描画してhiddenを解除する。
   スマホでも操作ボタンを圧迫しないよう、高さを固定してスクロール領域にする。 */
.synced-lyrics-panel {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 150px;
  overflow-y: auto;
  margin-top: 6px;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.5);
  border: 1px solid var(--color-card-border);
  scrollbar-gutter: stable;
}

/* displayの指定がhidden属性より優先されてしまう問題への対策（12章の教訓を踏襲） */
.synced-lyrics-panel[hidden] {
  display: none;
}

.synced-lyrics-line {
  margin: 0;
  padding: 2px 4px;
  font-size: 0.72rem;
  color: var(--color-text);
  opacity: 0.5;
  cursor: pointer;
  transition: opacity var(--transition-base), color var(--transition-base);
}

/* タップ/クリックできることが伝わるよう、ホバー時にわずかに濃くする
   （現在行の強調＝opacity:1とは区別できる範囲にとどめる） */
.synced-lyrics-line:hover {
  opacity: 0.8;
}

/* 現在再生中の行だけ強調する。前後の行は薄いまま（.synced-lyrics-lineの既定opacity）にする */
.synced-lyrics-line.is-current-lyrics-line {
  opacity: 1;
  color: var(--color-primary-dark);
  font-weight: 700;
  /* 【2026-10-23】強調が「付く」ときはフェードを待たず即座に切り替える（実際の歌より遅れて見えないように）。
     外れるときは .synced-lyrics-line の transition が効くので、これまでどおりなめらかに薄くなる。 */
  transition-duration: 0s;
}

/* 全文表示モードでは、どの行も同じ濃さで読みやすく表示する（ハイライトなしのため） */
.synced-lyrics-panel.is-full-text-mode .synced-lyrics-line {
  opacity: 1;
}

/* ===== ライブコールモード：コール表示（js/callSync.jsが歌詞パネルへ差し込む）=====
   歌詞行（.synced-lyrics-line）とひと目で区別できるよう、本人の要望どおり赤系の配色にする
   （既存の.mv-link-buttonと同じ--color-danger系トークンを使い、配色の一貫性を保つ）。
   ただし「今まさに発声中」の強調（.is-current-lyrics-line）だけは、本人要望により
   オレンジ〜黄色の発光（--color-call-glow・--color-accent）に変更している
   （通常時の赤系との対比で、現在行がより目立つようにする狙い）。
   2026-08-06新設。 */
.synced-call-line {
  position: relative; /* 下の::afterリング演出を、レイアウトに影響させず重ねて出すため */
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 3px 6px;
  border-radius: 6px;
  /* 現在行になったときだけ縁取りを足す（下のis-current-lyrics-line参照）。
     非現在行のうちから同じ太さの透明な縁を確保しておくことで、縁が付いたり消えたり
     するタイミングで箱の大きさが変わらないようにしている（レイアウトが動かないため）。 */
  border: 2px solid transparent;
  background: var(--color-danger-soft);
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--color-danger);
  opacity: 0.75;
  cursor: pointer;
  transition: opacity var(--transition-base), background-color var(--transition-base),
    color var(--transition-base), border-color var(--transition-base), box-shadow var(--transition-base);
}

.synced-call-line:hover {
  opacity: 1;
}

/* 今まさに発声するタイミングのコールを、ライブ会場のような派手さで強調する
   （.synced-lyrics-line.is-current-lyrics-lineと同じクラスを使って判定基準を統一している）。
   2026-08-06、本人要望で「ペンライトを振っていて一瞬で気付けるくらい」の
   インパクトを最優先にアップグレード（flat→ポップ→この版の順で2段階目の強化）：
   ・登場（synced-call-pop、480ms・1回だけ）：transform（scale＋rotate）のみで、
     手前に飛び出してから軽く弾んで震え、収まる。layoutプロパティは一切使わず、
     隣接する歌詞・コール行は押し出さない（transformは要素の見た目だけを動かす）。
   ・持続中のグロー（synced-call-glow-pulse、登場が終わってから緩くループ）：
     box-shadowの色・広がりだけを揺らす。box-shadowもwidth/heightを持たないため
     隣接行を押さない。長いコールでもずっと明滅し続けるが、周期を1.1秒とゆったり
     させ、変化量も抑えているため、低スペック端末でも極端に重くはならない設計。
   ・外側へのリング（下の::after、synced-call-ring-burst）：登場と同時に1回だけ、
     縁が外側へ広がりながら消える「衝撃波」のような演出。position:absoluteのため
     これもレイアウトには一切影響しない。
   ・色の変化だけに頼らず、白い縁取り・拡大・文字の光彩（text-shadow）でも
     現在行だと分かるようにしている（色覚特性に配慮）。
   ・「視差効果を減らす」設定時は、下の共通ルール（このファイル末尾）が
     animation-durationを一律ほぼ0にするため、このクラス側で個別対応する必要はない
     （ループするglow-pulseも実質止まって見える）。
   ・複数のコールがほぼ同時にアクティブになる場合でも、classList.toggleで
     クラスが外れて付け直されるたびにアニメーションが最初から再生されるため、
     見た目が壊れることはない（js/callSync.jsのapplyActiveIndex参照）。
     ただし現状は「同時に2件を強調表示する」設計にはなっていない
     （1件だけを現在行とする既存のfindActiveLineIndexの仕様。変更は今回のスコープ外）。 */
.synced-call-line.is-current-lyrics-line {
  opacity: 1;
  background: linear-gradient(135deg, var(--color-call-glow), var(--color-accent));
  color: #ffffff;
  border-color: #ffffff;
  text-shadow: 0 0 4px rgba(255, 255, 255, 0.9), 0 0 10px var(--color-call-glow);
  z-index: 1; /* 拡大時に隣の行の上に重なって見えるようにする（重なっても隣の位置は動かない） */
  animation: synced-call-pop 480ms cubic-bezier(0.34, 1.56, 0.64, 1) both,
    synced-call-glow-pulse 1100ms ease-in-out 480ms infinite;
}

/* 登場演出：手前に飛び出す→弾む→軽く震える→収まる、の4拍子。 */
@keyframes synced-call-pop {
  0% {
    transform: scale(0.7) rotate(0deg);
  }
  30% {
    transform: scale(1.45) rotate(-3deg);
  }
  50% {
    transform: scale(0.92) rotate(2deg);
  }
  70% {
    transform: scale(1.12) rotate(-1.5deg);
  }
  85% {
    transform: scale(0.97) rotate(0.5deg);
  }
  100% {
    transform: scale(1) rotate(0deg);
  }
}

/* 持続中のグロー：オレンジ〜黄色の光が外側へゆっくり呼吸するように広がる。 */
@keyframes synced-call-glow-pulse {
  0%,
  100% {
    box-shadow: 0 0 10px 1px rgba(255, 159, 67, 0.55), 0 0 22px 4px rgba(255, 217, 61, 0.35);
  }
  50% {
    box-shadow: 0 0 18px 3px rgba(255, 159, 67, 0.85), 0 0 34px 8px rgba(255, 217, 61, 0.55);
  }
}

/* 登場と同時に1回だけ、縁が衝撃波のように外側へ広がって消える演出。
   position:absoluteのため、隣接する行のレイアウトには一切影響しない。 */
.synced-call-line.is-current-lyrics-line::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: inherit;
  border: 2px solid var(--color-accent);
  opacity: 0;
  pointer-events: none;
  animation: synced-call-ring-burst 480ms ease-out both;
}

@keyframes synced-call-ring-burst {
  0% {
    transform: scale(0.9);
    opacity: 0.9;
  }
  100% {
    transform: scale(1.7);
    opacity: 0;
  }
}

/* ===== 短いコールの「飛び出しバースト」演出（js/callSync.jsのtriggerCallBurst）=====
   「Hi!」「Yeah!」のような一瞬で終わる短い掛け声を、画面中央に大きく一瞬だけ
   表示して目立たせる（本人要望：「ペンライトを振っていても一瞬でコールだと
   分かる」インパクトを最優先）。position:fixedのため、歌詞パネルや隣接する
   コール・歌詞行のレイアウトには一切影響しない。低スペック端末を考慮し、
   動かすプロパティはtransform/opacityのみ（box-shadow/text-shadowは動かさず
   固定値のまま使う）。「視差効果を減らす」設定時は、このファイル末尾の
   共通ルールがanimation-durationを一律ほぼ0にするため、個別対応は不要。 */
.call-burst-layer {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  z-index: 500;
  opacity: 0;
}

.call-burst-layer.is-bursting {
  opacity: 1;
}

.call-burst-text {
  display: inline-block;
  max-width: 92vw;
  padding: 14px 32px;
  border-radius: 20px;
  border: 4px solid #ffffff;
  background: linear-gradient(135deg, var(--color-call-glow), var(--color-accent));
  color: #ffffff;
  font-size: clamp(2.2rem, 12vw, 4rem);
  font-weight: 900;
  text-align: center;
  letter-spacing: 0.02em;
  text-shadow: 0 0 8px rgba(255, 255, 255, 0.9), 0 0 20px var(--color-call-glow);
  box-shadow: 0 0 30px 8px rgba(255, 159, 67, 0.7), 0 0 60px 16px rgba(255, 217, 61, 0.45);
  transform: scale(0);
}

.call-burst-layer.is-bursting .call-burst-text {
  animation: call-burst-fly-in 900ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* 手前へ勢いよく飛び出し、弾みながら少し引いて収まり、最後にふっと消える。 */
@keyframes call-burst-fly-in {
  0% {
    transform: scale(0.2) rotate(-10deg);
    opacity: 0;
  }
  /* 【2026-10-23】表示の立ち上がりを短縮（不透明になるまで 180ms → 約55ms）。演出の動き自体は同じ */
  6% {
    opacity: 1;
  }
  30% {
    transform: scale(1.5) rotate(5deg);
  }
  45% {
    transform: scale(1.1) rotate(-3deg);
  }
  60% {
    transform: scale(1.28) rotate(2deg);
  }
  78% {
    transform: scale(1.18) rotate(0deg);
    opacity: 1;
  }
  100% {
    transform: scale(1.3) rotate(0deg);
    opacity: 0;
  }
}

/* ===== 長いコール（MIX・口上など）の「本文を主役にした持続表示」演出 =====
   （js/callSync.jsのshowLongCallDisplay/hideLongCallDisplayが.is-activeを付け外しする）
   2026-08-06：まず画面全体が光る一瞬の演出として追加／2026-08-07：本人要望により、
   コールがアクティブな間ずっと本文を大きく表示し続ける方式へ拡張。

   ・表示/非表示は外側の.call-longform-overlay自体のtransition（opacity・transform）に
     任せている。.is-activeを付けると拡大しながらフェードイン、外すと縮小しながら
     フェードアウトする（「開始時に大きく表示→終了時に自然に縮小・フェードアウト」を
     1つのtransitionの往復で表現している）。
   ・持続中の光の脈動（.call-longform-overlay-text側のcall-longform-glow-pulse）は、
     .is-activeが付いている間だけ無限ループするkeyframeアニメーション。
     動かすのはbox-shadowのみで、要素自体の大きさ・位置には影響しない。
   ・本文の長さに応じて4段階の文字サイズ（is-length-tier-*、js側のgetLongCallDisplayLengthTier
     が判定）に切り替えることで、非常に長い本文でも内部スクロールなしで画面内に収める
     （DOM計測を使わない、シンプルで軽い方式）。
   ・最大幅90vw・最大高さ80vhで、画面のはみ出し・横スクロールが起きないようにしている。
   ・歌詞行側の光り方（.synced-call-line.is-current-lyrics-line）や短いコールの
     バースト演出（.call-burst-layer）には一切手を加えていない、完全に独立した
     position:fixedの重ね書きレイヤーのため、既存のレイアウト・タイミング判定には
     影響しない。
   ・「視差効果を減らす」設定時は、このファイル末尾の共通ルールがanimation-duration・
     transition-durationを一律ほぼ0にするため、個別対応は不要。 */
.call-longform-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  pointer-events: none;
  z-index: 490; /* 短いコールのバースト（z-index:500）より少し奥、通常UIより手前 */
  opacity: 0;
  transform: scale(0.85);
  transition: opacity 420ms ease, transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.call-longform-overlay.is-active {
  opacity: 1;
  transform: scale(1);
  /* 【2026-10-23】表示されるときの立ち上がりを短縮（420ms → 不透明まで120ms）。消えるときは上の420msのまま */
  transition: opacity 120ms ease-out, transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
}

.call-longform-overlay-text {
  margin: 0;
  max-width: 90vw;
  max-height: 80vh;
  overflow: hidden;
  padding: 20px 26px;
  border-radius: 24px;
  border: 4px solid #ffffff;
  background: linear-gradient(135deg, var(--color-call-glow), var(--color-accent));
  color: #ffffff;
  font-weight: 900;
  text-align: center;
  line-height: 1.4;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  text-shadow: 0 0 10px rgba(255, 255, 255, 0.9), 0 0 22px var(--color-call-glow);
  box-shadow: 0 0 24px 6px rgba(255, 159, 67, 0.55), 0 0 46px 14px rgba(255, 217, 61, 0.35);
}

/* 持続中はゆっくり光が脈打つ（.is-activeが付いている間だけループ）。tier別の演出
   （下記is-call-tier-medium/long）が上書きしなかった場合の共通の土台になる。 */
.call-longform-overlay.is-active .call-longform-overlay-text {
  animation: call-longform-glow-pulse 1400ms ease-in-out infinite;
}

@keyframes call-longform-glow-pulse {
  0%,
  100% {
    box-shadow: 0 0 24px 6px rgba(255, 159, 67, 0.55), 0 0 46px 14px rgba(255, 217, 61, 0.35);
  }
  50% {
    box-shadow: 0 0 34px 10px rgba(255, 159, 67, 0.8), 0 0 64px 20px rgba(255, 217, 61, 0.5);
  }
}

/* ===== MEDIUM／LONGで演出の強さを変える（UI/UX第6版で追加） =====
   これまでSHORT以外は全部同じ「フェードイン＋一定の光の脈動」だけで、本人から
   「画面を大きく使っている割には演出が弱い」という指摘を受けた。tier（js/callSync.jsの
   showLongCallDisplayが付ける is-call-tier-medium／is-call-tier-long）で下記のように
   差をつける。動かすプロパティはtransform/opacity/box-shadow/filterのみ（本人指示：
   低スペック端末を考慮し、DOM再構築やレイアウトに影響するプロパティは使わない）。
   回転を使う場合は「登場時だけ」または「背景要素だけ」に留め、本文そのものを
   ぐるぐる回して読みにくくすることはしない（本人指示）。
   「視差効果を減らす」設定時は、このファイル末尾の共通ルールがanimation-durationを
   一律ほぼ0にするため、個別対応は不要（既存のSHORT/カラオケHUD演出と同じ扱い）。 */

/* MEDIUM：数秒間だけ続く、勢いのあるコール。画面中央へ大きくスライドイン＋少し
   オーバーシュートしてから収まり、表示中は控えめにpulseする「ライブ感」を出す。 */
.call-longform-overlay.is-call-tier-medium .call-longform-overlay-text {
  animation: call-longform-glow-pulse 1000ms ease-in-out infinite, callMediumEntrance 460ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes callMediumEntrance {
  0% {
    transform: scale(0.5) translateY(36px);
    opacity: 0;
  }
  /* 【2026-10-23】文字が読める濃さになるまでを短縮（約280ms → 約70ms）。弾む動きはそのまま */
  15% {
    opacity: 1;
  }
  60% {
    transform: scale(1.1) translateY(-6px);
    opacity: 1;
  }
  100% {
    transform: scale(1) translateY(0);
  }
}

/* LONG：MIX・口上のような長く続くコール。表示されている間ずっと、ライブ照明のような
   光がゆっくり回り込む背景（::before）を添え、本文は大きくズームインしたあと、
   非常に緩やかな呼吸pulseで「今もライブが続いている」感じを保つ。 */
.call-longform-overlay.is-call-tier-long .call-longform-overlay-text {
  position: relative;
  z-index: 1;
  animation: call-longform-glow-pulse 2600ms ease-in-out infinite, callLongEntrance 640ms cubic-bezier(0.22, 1, 0.36, 1),
    callLongBreathe 4200ms ease-in-out 640ms infinite;
}

@keyframes callLongEntrance {
  0% {
    transform: scale(0.35) rotate(-5deg);
    opacity: 0;
  }
  /* 【2026-10-23】文字が読める濃さになるまでを短縮（約350ms → 約80ms）。ズームの動きはそのまま */
  12% {
    opacity: 1;
  }
  55% {
    transform: scale(1.08) rotate(2deg);
    opacity: 1;
  }
  100% {
    transform: scale(1) rotate(0deg);
  }
}

@keyframes callLongBreathe {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.015);
  }
}

/* LONGのときだけ、画面全体にゆっくり回るぼんやりした光のリングを背景に添える
   （本人指示：回転させるのは背景・光の要素だけで、本文そのものは回さない）。 */
.call-longform-overlay.is-call-tier-long::before {
  content: "";
  position: absolute;
  inset: -25%;
  z-index: 0;
  border-radius: 50%;
  background: conic-gradient(
    from 0deg,
    rgba(255, 217, 61, 0) 0%,
    rgba(255, 217, 61, 0.4) 18%,
    rgba(255, 159, 67, 0) 38%,
    rgba(255, 89, 150, 0.32) 58%,
    rgba(255, 217, 61, 0) 78%,
    rgba(255, 217, 61, 0.4) 100%
  );
  filter: blur(28px);
  animation: callLongRingRotate 7s linear infinite;
  pointer-events: none;
}

@keyframes callLongRingRotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

/* 文字数に応じた4段階の文字サイズ（js側getLongCallDisplayLengthTier参照）。
   clamp()で画面幅にもある程度追従させつつ、tierごとの上限を変えて長文ほど小さくする。 */
.call-longform-overlay-text.is-length-tier-compact {
  font-size: clamp(1.6rem, 7.5vw, 2.6rem);
}

.call-longform-overlay-text.is-length-tier-cozy {
  font-size: clamp(1.3rem, 6vw, 2.1rem);
}

.call-longform-overlay-text.is-length-tier-roomy {
  font-size: clamp(1.05rem, 4.6vw, 1.7rem);
}

.call-longform-overlay-text.is-length-tier-packed {
  font-size: clamp(0.85rem, 3.6vw, 1.3rem);
}

.synced-call-type-badge {
  flex: none;
  padding: 1px 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.6);
  font-size: 0.6rem;
}

.synced-call-line.is-current-lyrics-line .synced-call-type-badge {
  background: rgba(255, 255, 255, 0.35);
}

.synced-call-text {
  flex: 1;
  min-width: 0;
  overflow-wrap: break-word;
}

/* 「通常歌詞のみ」に切り替えたとき、コール行だけ非表示にする。
   歌詞側の全文表示切替ボタン（.lyrics-mode-toggle-button）とは別の、
   独立したコール専用の切替ボタン（左上に配置し、歌詞側の右上ボタンと重ならないようにする）。 */
.synced-lyrics-panel.calls-hidden .synced-call-line {
  display: none;
}

.calls-toggle-button {
  align-self: flex-start;
  position: sticky;
  top: 0;
  z-index: 1;
  flex: none;
  font-size: 0.62rem;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--color-danger);
  background: rgba(255, 255, 255, 0.85);
  color: var(--color-danger);
  cursor: pointer;
}

/* ===== ライブコールモード：曲一覧画面 =====
   .special-mode-cardと同じ見た目の行だが、収録曲一覧（songlist.js）とは
   コード上も完全に独立した専用のクラスにしている（本人の希望）。 */
.live-call-song-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 14px;
  border-radius: 14px;
  margin-bottom: 10px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid var(--color-card-border);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.live-call-song-row:active {
  transform: scale(0.98);
}

.live-call-song-row-title {
  flex: 1;
  min-width: 0;
  font-size: 0.9rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

/* ===== ライブコールモード：再生画面 UI/UX第4版（2026-08-09） =====
   本人の実機フィードバック「歌詞表示領域の下に大きな白い空白がある」を受け、
   カラオケ同期画面と同じ3ゾーン固定レイアウト（①ヘッダー②中央スクロール③下部固定）へ
   再構成した。使える縦幅はできる限り歌詞＋コール表示（中央ゾーン）へ回す。 */
body[data-screen="liveCallModePlayer"] {
  padding-top: 0;
  padding-bottom: 0;
}

body[data-screen="liveCallModePlayer"] .game-frame {
  height: var(--game-frame-safe-height);
  max-height: var(--game-frame-safe-height);
  display: flex;
  flex-direction: column;
}

#live-call-mode-player-screen {
  padding: 0;
}

#live-call-mode-player-screen.is-active {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

.live-call-player-header-zone {
  flex: none;
  padding: max(16px, env(safe-area-inset-top)) 20px 10px;
}

/* ②中央ゾーン：歌詞＋コール表示だけがここに入る。内容量に関わらずここだけが縦スクロールする。 */
.live-call-player-middle-zone {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 0 20px;
  display: flex;
  flex-direction: column;
}

/* 中央ゾーンいっぱいに広げる（従来の320px固定を廃止）。base(.synced-lyrics-panel)の
   max-height:150pxを、専用の再生画面ではここで打ち消す。 */
#live-call-mode-lyrics-panel {
  flex: 1;
  min-height: 0;
  max-height: none;
  margin-top: 0;
}

/* ③下部ゾーン：最低限の再生操作だけを固定表示する。 */
.live-call-player-footer-zone {
  flex: none;
  padding: 10px 20px max(14px, env(safe-area-inset-bottom));
  background: var(--color-surface);
  border-top: 1.5px solid var(--color-card-border);
  box-shadow: 0 -10px 24px -16px rgba(74, 46, 66, 0.3);
}

.live-call-mode-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* 専用の再生画面のため、一覧行の.play-buttonより一段大きくタップしやすいサイズにする。 */
.live-call-mode-play-button {
  width: 44px;
  height: 44px;
}

.live-call-mode-play-button svg {
  width: 18px;
  height: 18px;
}

.live-call-mode-time {
  flex: none;
  font-size: 0.72rem;
  color: var(--color-text);
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
}

/* 全画面表示ボタンをヘッダーへ移動（UI/UX第4版）。既存の.info-link-button（？ボタン）と
   同じ丸アイコンの見た目を流用し、アイコンだけこのサイズで上書きする。 */
.live-call-mode-fullscreen-icon-button svg {
  width: 14px;
  height: 14px;
}

/* 再生/一時停止ボタンのアイコン切り替え。既存の.icon-play/.icon-pause出し分け方式は
   「.track-row.is-playing 配下の.play-button」専用のセレクタしかなく、収録曲一覧の行の
   中にないこの単独ボタン（.play-buttonにis-playingを自分自身へ付け外しする）には
   効かなかった（実際の再生/一時停止のJS処理自体は正しく動いていたが、アイコンの見た目だけ
   切り替わらない不具合になっていた。本人からの報告で発覚。2026-08-06修正）。
   .mini-player-control-button.is-playingと同じ、ボタン自身にクラスが付く場合の
   セレクタを追加する。 */
#live-call-mode-play-button.is-playing .icon-play {
  display: none;
}

#live-call-mode-play-button.is-playing .icon-pause {
  display: block;
}

/* 表示モードの切替ボタン。パネルをスクロールしても見失わないようsticky表示にする。 */
.lyrics-mode-toggle-button {
  align-self: flex-end;
  position: sticky;
  top: 0;
  z-index: 1;
  flex: none;
  font-size: 0.62rem;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--color-card-border);
  background: rgba(255, 255, 255, 0.85);
  color: var(--color-primary-dark);
  cursor: pointer;
}

.seek-time {
  align-self: flex-end;
  font-size: 0.65rem;
  color: var(--color-text);
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
}

/* 「MVを見る」：公式YouTubeへ別タブで飛ぶリンク（2026-08-05追加）。試聴中の操作ボタン群とは
   役割が違う（アプリの外へ出る操作）ため、ボタンではなくリンクらしい見た目にしている。
   再生ボタン・お気に入りハート・カテゴリバッジのどれとも混同されないよう、
   曲情報欄（.track-info）の右下寄りに単独の行として配置し、align-self:flex-endで
   お気に入りハートの左側に寄せる（再生前・再生中どちらでも位置が変わらない。
   本人フィードバックで「再生前から見えるように」と移動。2026-08-05）。
   youtubeUrlが無い曲では、songlist.js側でそもそもこの要素自体を作らない。 */
/* 収録曲一覧のMVサムネイル（2026-08-24追加、本人指示。3曲での確認を経て全曲へ展開）。
   曲名・センター情報のすぐ下、「MVを見る」ボタンのすぐ上に置く。play-button（32px）と
   track-action-column（お気に入り・カテゴリバッジ）の間の、track-info自身の幅いっぱいに
   広げるが、行の高さを圧迫しすぎないよう最大幅・アスペクト比（16:9）で頭打ちにする。 */
.track-mv-thumb {
  display: block;
  width: 100%;
  max-width: 220px;
  aspect-ratio: 16 / 9;
  margin: 4px 0 2px;
  border-radius: 8px;
  overflow: hidden;
  background: var(--color-primary-light);
}

.track-mv-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* .youtube-playlist-link（再生リストを見るボタン、2026-08-24追加）は、
   「MVを見る」ボタンと全く同じ見た目にして統一感を出す（本人指示）。 */
.mv-link-button,
.youtube-playlist-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  align-self: flex-end;
  width: fit-content;
  margin-top: 4px;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1.5px solid var(--color-danger);
  background: var(--color-danger-soft);
  color: var(--color-danger);
  font-size: 0.7rem;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
}

/* 見た目の大きさはそのままに、タップ判定だけ一回り広げる
   （.track-favorite-button::afterと同じ、スマホでの誤タップ対策）。 */
.mv-link-button::after,
.youtube-playlist-link::after {
  content: "";
  position: absolute;
  inset: -6px;
}

.mv-link-button svg,
.youtube-playlist-link svg {
  width: 12px;
  height: 12px;
  flex: none;
}

.mv-link-button:active,
.youtube-playlist-link:active {
  transform: scale(0.96);
}

/* MVを見る・歌詞を見る・全画面表示ボタンをまとめて右寄せに並べる入れ物（2026-08-25追加）。
   どれか1つしか無い曲でも常に同じ右寄せの並びになる。
   【2026-08-29修正】以前はflex-wrap:wrapにしていたが、この行の横幅は曲ごとに変わる
   （右側のtrack-action-columnがカテゴリバッジの文字数分だけ幅を取るため、「ユニット曲」
   （5文字）のように長いバッジの曲ほどこの行の幅が狭くなる。「僕のヒロイン」のような、
   歌唱・振付クレジットが付くユニット曲＋カテゴリバッジの組み合わせで、MVを見る・歌詞を見る
   の2つのボタンが横幅に収まりきらず、意図せず2行に折り返して縦積みに見えてしまっていた。
   この「収まりきるか」は曲名や特別クレジットの有無に依存し84曲すべてで安全とは言えないため、
   個別の曲に対処するのではなく、そもそも折り返させない（flex-wrap:nowrap）方針に変更した。
   代わりに下のmin-width:0で、幅が足りない場合はボタン内の文字だけを折り返させて縦幅を
   増やす形にし、ボタン同士が横並びのまま保たれるようにしている。 */
.track-action-buttons {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  justify-content: flex-end;
  gap: 6px;
  margin-top: 4px;
}

.track-action-buttons .mv-link-button,
.track-action-buttons .lyrics-view-button {
  margin-top: 0;
  /* 横幅が足りないときにボタン自体が横に押し出されて右端がはみ出すのを防ぎ、
     代わりにボタン内のテキストが折り返して縦に伸びられるようにする
     （flex-shrinkは既定でも効くが、min-widthの初期値autoはコンテンツの
     最小サイズを保とうとするため、明示的に0にして縮小を妨げないようにする）。 */
  min-width: 0;
}

/* 歌詞を見るボタン：MVを見るボタンと同じ形・大きさで、配色だけブランドのサブカラー
   （青系）にして役割の違いを表す。 */
.lyrics-view-button {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  width: fit-content;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1.5px solid var(--color-secondary);
  background: var(--color-secondary-light);
  color: var(--color-secondary);
  font-size: 0.7rem;
  font-weight: 700;
  cursor: pointer;
}

.lyrics-view-button::after {
  content: "";
  position: absolute;
  inset: -6px;
}

.lyrics-view-button svg {
  width: 12px;
  height: 12px;
  flex: none;
}

.lyrics-view-button:active {
  transform: scale(0.96);
}

/* 歌詞データが無い曲を「歌詞を見る」で開いたときの案内文。エラー表示にはせず、
   既存のパネルの見た目のまま控えめに表示する。 */
.synced-lyrics-panel[data-empty-state] {
  padding: 12px;
  font-size: 0.8rem;
  color: var(--color-text-muted, #8a7a86);
  text-align: center;
}

/* 再生中だけ表示する、ブランド共通のイコライザー演出（スタート画面の.eq-dividerと同じモチーフ） */
.now-playing-tag {
  display: none;
  align-items: center;
  gap: 5px;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.track-row.is-playing .now-playing-tag {
  display: inline-flex;
}

/* 「再生中」の文字とイコライザー演出は、実際に音が鳴っているときだけ表示する。
   一時停止中は紛らわしいため隠す（アイコン切り替えと同じ考え方）。 */
.track-row.is-playing.is-audio-paused .now-playing-tag {
  display: none;
}

.now-playing-eq {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 10px;
}

.now-playing-eq span {
  width: 2.5px;
  border-radius: 2px;
  background: var(--color-primary-dark);
  height: 4px;
  animation: eqBounce 0.9s ease-in-out infinite;
}

.now-playing-eq span:nth-child(2) {
  animation-delay: 0.15s;
}

.now-playing-eq span:nth-child(3) {
  animation-delay: 0.3s;
}

@keyframes eqBounce {
  0%, 100% {
    height: 3px;
  }
  50% {
    height: 10px;
  }
}

/* ===== 歌詞の全画面表示オーバーレイ =====
   既存の.modal-overlay（中央に小さいカードを出す用）とは別に新設。
   一覧内の同期歌詞パネル（.synced-lyrics-panel）を、開いている間だけこの中へ移動して表示する
   （js/lyricsFullscreen.js）。新しいaudio要素・新しい歌詞DOMはここでは作らない。 */
.lyrics-fullscreen-overlay {
  position: fixed;
  inset: 0;
  z-index: 40; /* 更新通知バナー（z-index:30）よりもさらに手前に表示する */
  display: flex;
  flex-direction: column;
  background: linear-gradient(135deg, var(--color-background-start), var(--color-background-end));
  box-sizing: border-box;
  overflow: hidden; /* 万が一の横はみ出しを防ぐ最終防衛ライン */
  /* 【重要】paddingショートハンドの中でenv()・calc()・max()を組み合わせると実機のSafariで
     値全体が無効になる不具合を確認したため、個別プロパティで指定している。
     上だけ、bodyと同じ理由でenv()の上乗せをあてにせず固定値を下限にする。 */
  padding-top: max(56px, calc(env(safe-area-inset-top) + 16px));
  padding-right: max(16px, env(safe-area-inset-right));
  padding-bottom: max(16px, env(safe-area-inset-bottom));
  padding-left: max(16px, env(safe-area-inset-left));
}

.lyrics-fullscreen-overlay[hidden] {
  display: none;
}

.lyrics-fullscreen-header {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 12px;
}

.lyrics-fullscreen-title {
  margin: 0;
  min-width: 0; /* text-overflow:ellipsisをflexアイテムで効かせるための定番指定 */
  font-size: 1rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lyrics-fullscreen-close-button {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

.lyrics-fullscreen-close-button:active {
  transform: scale(0.92);
}

/* 歌詞エリアは、ヘッダーと下部操作バーの間の残り全部を使う */
.lyrics-fullscreen-lyrics-slot {
  flex: 1;
  min-height: 0; /* flexアイテム内でoverflow-y:autoを効かせるための定番指定 */
  display: flex;
}

/* パネル自体は既存の.synced-lyrics-panelのまま。全画面のときだけ、このクラスで見た目を上書きする。
   文字サイズ・行間は、まず1.15〜1.25rem程度を基準にする（実機確認後に調整予定）。 */
.synced-lyrics-panel.is-fullscreen-lyrics {
  flex: 1;
  max-height: none;
  margin-top: 0;
  padding: 12px 14px;
}

.synced-lyrics-panel.is-fullscreen-lyrics .synced-lyrics-line {
  font-size: 1.2rem;
  line-height: 2;
  padding: 6px 4px;
}

.lyrics-fullscreen-controls {
  flex: none;
  padding-top: 12px;
}

.lyrics-fullscreen-seek-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.lyrics-fullscreen-time {
  flex: none;
  font-size: 0.75rem;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

.lyrics-fullscreen-buttons {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 24px;
  margin-top: 10px;
}

/* 全画面用の再生/一時停止ボタンは、一覧内のものより大きくタップしやすいサイズにする。
   .play-buttonの基本スタイルはそのまま踏襲し、サイズだけこのクラスで上書きする
   （このルールを.play-buttonより後ろに書いているため、詳細度が同じでも後勝ちで反映される）。 */
.lyrics-fullscreen-play-button {
  width: 56px;
  height: 56px;
}

.lyrics-fullscreen-play-button svg {
  width: 22px;
  height: 22px;
}

/* アイコンの切り替えは、ボタン自身のis-playingクラス（audio.pausedの実際の値）で判定する。
   一覧行のis-playingとは無関係の、この全画面ボタン専用の状態。 */
.lyrics-fullscreen-play-button .icon-pause {
  display: none;
}

.lyrics-fullscreen-play-button.is-playing .icon-play {
  display: none;
}

.lyrics-fullscreen-play-button.is-playing .icon-pause {
  display: block;
}

.category-pill {
  flex: none;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.66rem;
  font-weight: 700;
}

.category-pill.title-track {
  background: var(--color-primary-dark);
  color: #ffffff;
}

.category-pill.group-song {
  background: var(--color-secondary-light);
  color: #2c6ea8;
}

.category-pill.unit-song {
  background: var(--color-accent-soft);
  color: #8a6a10;
}

/* 特別枠（Overture）は、ランクCの落ち着いた配色（12章参照）に揃える */
.category-pill.special {
  background: #f3f0f8;
  color: #6b6478;
}

/* お気に入りハート・カテゴリバッジをまとめて右端に縦に並べる列（2026-08-04追加）。 */
.track-action-column {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
}

/* 曲のお気に入りハートボタン。メンバー一覧の「推し」ハートと形は揃えつつ、
   混同しないよう色をコーラルオレンジ系（--color-song-favorite）にしている。 */
.track-favorite-button {
  flex: none;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(255, 138, 92, 0.12);
  color: #c9bcc3;
  cursor: pointer;
  transition: transform 0.15s ease;
}

/* 見た目はそのままに、タップ判定だけ一回り広げる（.modal-close-button::afterと同じ手法）。 */
.track-favorite-button::after {
  content: "";
  position: absolute;
  inset: -6px;
}

.track-favorite-button svg {
  width: 14px;
  height: 14px;
  fill: currentColor;
}

.track-favorite-button:active {
  transform: scale(0.9);
}

.track-favorite-button.is-favorite {
  color: var(--color-song-favorite);
  background: rgba(255, 138, 92, 0.18);
}

/* プレイリスト詳細画面だけで使う「上へ/下へ/削除」ボタン列（2026-08-04追加）。 */
.track-playlist-controls {
  flex: none;
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: 4px;
}

.track-playlist-control-button {
  flex: none;
  width: 26px;
  height: 26px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(255, 111, 168, 0.1);
  color: var(--color-primary-dark);
  font-size: 0.8rem;
  line-height: 1;
  cursor: pointer;
}

.track-playlist-control-button:active {
  transform: scale(0.9);
}

.track-playlist-control-button:disabled {
  opacity: 0.35;
  cursor: default;
}

.track-playlist-control-button.is-remove {
  color: #c94b4b;
  background: rgba(201, 75, 75, 0.1);
}

/* ===== 称号一覧モーダル =====
   称号1件＝1枚のカードとして、ガラス風カードの世界観に合わせたパステルな見た目にする。
   未取得のカードは、彩度を落とした一重の実線・鍵アイコンで「まだ手が届いていない」ことを
   伝えつつ、名前・条件文はロックせず常に読める状態にする（本人指示）。
   分類（ノーミスランク・表マスター・裏称号・最終称号）ごとにセクション分けして表示する。 */
#title-list-container {
  display: flex;
  flex-direction: column;
  gap: 18px;
  margin-top: 14px;
}

.achievement-category-heading {
  margin: 0 0 8px;
  font-size: 0.82rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  color: var(--color-primary-dark);
}

/* ===== ステップアップ（growth）専用のトロフィー風バッジUI（2026-08-17再設計） =====
   本人フィードバック「説明カードっぽい・格好良くない」を受け、称号・アイコンを主役にし、
   条件文は補助情報にする（バッジ→問題数→称号名→条件、の順で視線が流れる構成）。
   イントロ／シャッフル／リリックの3系統を、系統ごとに横並び3枚（ビギナー→チャレンジャー→
   エース）で見せることで「揃えたい」という収集欲求を刺激する。既存のmasterPath・
   backChallengeの.achievement-card系スタイルとは完全に独立させている。 */
.growth-series-block {
  margin-bottom: 16px;
}

.growth-series-block:last-child {
  margin-bottom: 0;
}

.growth-series-label {
  margin: 0 0 8px;
  font-size: 0.76rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  opacity: 0.85;
}

/* 【2026-08-30改訂・本人指示④】ビギナー/チャレンジャー/エースの3段階からマスターを加えた
   4段階へ変更したため、3列→4列にする（狭い画面は下のメディアクエリで2列×2段に切り替える）。
   一瞬チャレンジ系・新設のマスター称号ブロック（4マスター）はこのデフォルト（4列）のまま使う。 */
.growth-series-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}

/* 【2026-08-30再改訂・本人指示③】マスターを切り出したイントロ／アウトロ／シャッフル／
   リリックの4系統は3段階に戻ったため、この修飾クラスで3列グリッドへ切り替える
   （4列のまま3枚だけ並べると1列分が余って不自然に見えるため）。 */
.growth-series-row--three {
  grid-template-columns: repeat(3, 1fr);
}

/* 【2026-08-30新設・本人指示③】「マスター称号（＝LOVEマスターへの道）」専用ブロック。
   通常のステップアップ・裏チャレンジと見分けが付くよう、王冠にちなんだ淡いゴールドの
   背景で軽く強調する（--color-accent-softを流用。既存のパステルカード世界観を崩さない
   範囲の控えめな装飾に留める）。 */
.master-path-section {
  padding: 14px;
  border-radius: 16px;
  background: linear-gradient(180deg, var(--color-accent-soft), rgba(255, 242, 191, 0.25));
  border: 1px solid rgba(255, 217, 61, 0.5);
}

.master-path-composite-grid {
  margin-top: 12px;
}

/* 【2026-11-XX新設・本人指示：称号一覧の再監査】マスター称号5件＋＝LOVEマスターを
   1称号＝1カードの詳細表示（挑戦条件のチェックリスト付き）へ変更したことに伴い、
   .achievement-card-gridの既定2列グリッドを1列へ上書きする。挑戦条件の行数が称号ごとに
   バラつくため、2列のままだと高さが揃わず不自然になるため（本人指示：「1称号＝1カードを
   基本に」）。 */
/* 【2026-11-XX修正】.achievement-card-gridの既定ルール（2列）がこのファイル内で後に
   定義されており、単一クラスの詳細度が同じだとソース順で2列側が勝ってしまっていたため、
   .achievement-card-gridと組み合わせた詳細度の高いセレクタにして確実に1列にする。 */
.achievement-card-grid.master-path-single-column-grid {
  grid-template-columns: 1fr;
}

.growth-badge-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  min-width: 0;
  padding: 12px 6px 10px;
  border-radius: 16px;
  border: 1px solid var(--color-card-border);
}

.growth-badge-card.is-unlocked {
  background: linear-gradient(165deg, #ffffff, var(--color-primary-light) 220%);
  border-color: rgba(255, 111, 168, 0.3);
}

.growth-badge-card.is-locked {
  background: rgba(74, 46, 66, 0.035);
}

.growth-badge-medal-wrap {
  position: relative;
  margin-bottom: 6px;
}

/* 一覧・結果チップ共通の28px基準（.achievement-icon-medal）より一回り大きくし、
   トロフィーらしい存在感を出す（他の使用箇所には影響しない、この文脈だけの上書き）。 */
.growth-badge-medal.achievement-icon-medal {
  width: 52px;
  height: 52px;
}

.growth-badge-check {
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: 18px;
  height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--color-primary);
  color: #fff;
  font-size: 0.62rem;
  font-weight: 900;
  border: 2px solid #fff;
}

.growth-badge-tier {
  margin: 0;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  opacity: 0.6;
}

.growth-badge-name {
  margin: 1px 0 0;
  font-size: 0.78rem;
  font-weight: 800;
  line-height: 1.3;
  color: var(--color-primary-dark);
  overflow-wrap: break-word;
}

.growth-badge-card.is-locked .growth-badge-name {
  color: var(--color-text);
  opacity: 0.75;
}

.growth-badge-guidance {
  margin: 4px 0 0;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.6rem;
  font-weight: 800;
  background: rgba(255, 111, 168, 0.12);
  color: var(--color-primary-dark);
  border: 1px dashed rgba(255, 111, 168, 0.5);
}

.growth-badge-condition {
  margin: 5px 0 0;
  font-size: 0.64rem;
  line-height: 1.4;
  opacity: 0.7;
}

.growth-badge-status {
  margin: 5px 0 0;
  font-size: 0.6rem;
  font-weight: 700;
  opacity: 0.55;
}

.growth-badge-status.is-achieved {
  opacity: 1;
  color: var(--color-primary-dark);
  font-weight: 800;
}

@media (max-width: 380px) {
  /* 【2026-08-30追加】4列だと1枚あたりが狭すぎて一瞬チャレンジ系の長いラベル
     （例：「1.5秒・4択・3問」）が窮屈になるため、狭い画面だけ2列×2段に切り替える。 */
  .growth-series-row {
    grid-template-columns: repeat(2, 1fr);
    gap: 6px;
  }
  .growth-badge-medal.achievement-icon-medal {
    width: 44px;
    height: 44px;
  }
  .growth-badge-name {
    font-size: 0.72rem;
  }
}

.achievement-card-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.achievement-card {
  padding: 14px 16px;
  border-radius: 16px;
  border: 1px solid var(--color-card-border);
  max-width: 100%;
  min-width: 0;
}

.achievement-card.is-unlocked {
  background: linear-gradient(165deg, #ffffff, var(--color-primary-light) 200%);
  border-color: rgba(255, 111, 168, 0.35);
}

/* ロック中の見た目は、背景・縁取りの淡いトーンだけで表現する（本人指示・2026-08-07：
   「未取得称号も文字が薄すぎて読めない状態にはしない」）。以前はカード全体にopacity:0.75を
   掛けていたが、.achievement-card-conditionが元から持つopacity:0.75と重なり合ってしまい
   （0.75×0.75で実質0.56相当）、条件文がかなり薄くなって読みにくくなっていたため廃止した。
   ロック感は、アイコンの鍵マーク・称号名の色・背景色の違いだけで十分に伝わる。 */
.achievement-card.is-locked {
  background: rgba(74, 46, 66, 0.035);
  border-color: var(--color-card-border);
}

/* 複合称号（＝LOVEマスター・＝LOVE完全制覇）は、1段組みで幅いっぱいに使い、
   他のカードより大きく特別に見せる（本人指示：「他より大きい特別カードにして構わない」）。 */
.achievement-card--composite {
  grid-column: 1 / -1;
}

/* ＝LOVEマスター・＝LOVE完全制覇、それぞれ専用の取得済みデザイン（本人指示・2026-08-07：
   「格上なのでカードにも特別感を、ただし派手すぎず」）。
   ＝LOVEマスター＝ピンク＋ゴールド系で柔らかく発光、＝LOVE完全制覇＝ピンク＋水色/紫系の
   上品なグラデーションで、ひと回り強めに発光させて格の違いを出す。
   prefers-reduced-motionの環境では発光アニメーションを止め、静止した配色のみにする。 */
.achievement-card--composite[data-achievement-id="equal_love_master"].is-unlocked {
  background: linear-gradient(155deg, #fff7e0, #ffe3f0 55%, #ffd9a0 100%);
  border-color: rgba(255, 200, 60, 0.7);
  box-shadow: 0 10px 24px -14px rgba(184, 121, 14, 0.5);
  animation: achievementMasterCardGlow 2.6s ease-in-out infinite;
}

.achievement-card--composite[data-achievement-id="equal_love_complete"].is-unlocked {
  background: linear-gradient(155deg, #ffe9f4, #e8e0ff 55%, #d3ecff 100%);
  border-color: rgba(150, 130, 255, 0.55);
  box-shadow: 0 10px 26px -12px rgba(140, 130, 255, 0.5);
  animation: achievementCompleteCardGlow 2.2s ease-in-out infinite;
}

@keyframes achievementMasterCardGlow {
  0%,
  100% {
    box-shadow: 0 10px 24px -14px rgba(255, 180, 60, 0.45);
  }
  50% {
    box-shadow: 0 10px 30px -10px rgba(255, 200, 90, 0.8);
  }
}

@keyframes achievementCompleteCardGlow {
  0%,
  100% {
    box-shadow: 0 10px 26px -12px rgba(140, 130, 255, 0.5);
  }
  50% {
    box-shadow: 0 12px 34px -8px rgba(120, 190, 255, 0.9);
  }
}

@media (prefers-reduced-motion: reduce) {
  .achievement-card--composite.is-unlocked {
    animation: none;
  }
}

.achievement-card-header {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 4px;
}

.achievement-card-name {
  margin: 0;
  padding-top: 3px; /* 28pxのアイコンと2行時の文字の視覚的な重心を合わせるための微調整 */
  font-size: 0.92rem;
  font-weight: 800;
  line-height: 1.3;
  color: var(--color-primary-dark);
  /* 称号名を「…」で省略しない（本人指示・2026-08-07：「称号は名前そのものが重要」）。
     長い名前は2行まで自然に折り返し、カードの高さは内容に合わせて可変にする
     （.achievement-cardにheight固定は指定していない）。 */
  overflow-wrap: break-word;
}

.achievement-card.is-locked .achievement-card-name {
  color: var(--color-text);
  opacity: 0.7;
}

.achievement-card-condition {
  margin: 0 0 8px;
  font-size: 0.76rem;
  line-height: 1.5;
  /* 本人指示・2026-08-07：ロック中カードで条件文が薄すぎて読みにくかったため、
     0.75→0.85へ引き上げ（.achievement-card.is-lockedの全体opacityは廃止済みなので、
     これが実質的な最終コントラストになる）。 */
  opacity: 0.85;
}

/* 「挑戦条件」の詳細箇条書き（本人指示・2026-08-14追加）。マスター・裏称号の単体称号だけが
   持つ、conditionText（短文）を補う完全な条件一覧。一覧を開いた瞬間に見えるよう、
   隠さず常に表示する（既存の「未取得でも条件は常に読める」方針を踏襲）。 */
.achievement-card-challenge {
  margin: 0 0 8px;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(74, 46, 66, 0.05);
}

.achievement-card-challenge-title {
  margin: 0 0 4px;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  opacity: 0.75;
}

.achievement-card-challenge-list {
  margin: 0;
  padding-left: 1.1em;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.achievement-card-challenge-list li {
  font-size: 0.72rem;
  line-height: 1.5;
  opacity: 0.85;
}

/* 成長段階系（ステップアップ）9個専用のコンパクト版（本人指示・2026-08-15）。
   マスター・裏称号の「挑戦条件」と同じ仕組みを再利用しつつ、条件が単純な分、
   見出し・行間・余白を一回り小さくして、カードが縦長になりすぎないようにする。 */
.achievement-card-challenge--compact {
  padding: 6px 9px;
}

.achievement-card-challenge--compact .achievement-card-challenge-title {
  margin: 0 0 3px;
  font-size: 0.64rem;
}

.achievement-card-challenge--compact .achievement-card-challenge-list {
  gap: 1px;
}

.achievement-card-challenge--compact .achievement-card-challenge-list li {
  font-size: 0.68rem;
  line-height: 1.4;
}

.achievement-card-status {
  display: inline-flex;
  align-items: center;
  font-size: 0.74rem;
  font-weight: 700;
  padding: 3px 12px;
  border: 1px solid var(--color-card-border);
  border-radius: 999px;
  color: var(--color-text);
  opacity: 0.6;
}

.achievement-card-status.is-achieved {
  border-color: var(--color-primary);
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-weight: 800;
  opacity: 1;
}

.achievement-card-status.is-achieved::before {
  content: "✦ ";
}

/* 初心者向けの案内バッジ（本人指示・2026-08-07）。
   ノーミスマスターだけは「最初の大きな目標」というやわらかい水色系、
   ブロンズ〜プラチナの「次の目標」はピンクの点線縁取りで、称号一覧の金・銀色と被らない
   控えめな差し色にしている。称号名・条件文と同じく、ロック中でも読みやすい濃さを保つ。 */
.achievement-card-guidance {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  max-width: 100%;
  margin: 2px 0 0;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 800;
  /* 本人指摘・2026-08-15：「🔰 まずはここから」が「まずはここ／ら」のように不自然に
     折り返される不具合の修正。バッジは短い1フレーズのため、途中で改行させない。
     万一カード幅より長くなる場合の保険としてellipsis省略も付けておく。 */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.achievement-card-guidance.is-next-step {
  background: rgba(255, 111, 168, 0.12);
  color: var(--color-primary-dark);
  border: 1px dashed rgba(255, 111, 168, 0.5);
}

/* 複合称号カード内の「獲得条件」チェックリスト（本人指示・2026-08-07：
   「どの称号を集めれば最終称号になるのか」を名前入りで一目で分かるようにする）。
   数字だけの進捗（旧.achievement-card-progress）から、名前つきの一覧表示に置き換えた。 */
.achievement-card-requirements {
  margin: 8px 0 0;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.55);
  border: 1px solid rgba(74, 46, 66, 0.08);
}

.achievement-card-requirements-title {
  margin: 0 0 4px;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  opacity: 0.65;
}

.achievement-requirement-item {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 2px 0;
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1.3;
}

.achievement-requirement-item.is-fulfilled {
  color: var(--color-primary-dark);
}

.achievement-requirement-item.is-fulfilled::before {
  content: "✓";
  flex: none;
  color: var(--color-primary);
  font-weight: 900;
}

.achievement-requirement-item.is-pending {
  color: var(--color-text);
  opacity: 0.75;
}

.achievement-requirement-item.is-pending::before {
  content: "○";
  flex: none;
  opacity: 0.55;
}

/* 複合称号だけが持つ、特典・推しアイコン変化の予告。未取得のうちから見せて、
   目指す理由が一目で伝わるようにする（本人指示：見やすい場所に表示）。 */
.achievement-card-reward {
  margin: 8px 0 0;
  padding: 6px 10px;
  border-radius: 10px;
  background: rgba(255, 217, 61, 0.25);
  font-size: 0.76rem;
  font-weight: 800;
  color: #7a4a20;
}

/* 375px幅では複合称号以外も1列にし、カード内の文字がはみ出さないようにする。 */
@media (max-width: 380px) {
  .achievement-card-grid {
    grid-template-columns: 1fr;
  }
}

/* ===== プレイ履歴画面 =====
   過去のプレイ結果を新しい順に一覧できる画面。サマリー（総プレイ回数・総回答数・全体正答率）と、
   履歴カードの一覧、全削除ボタンで構成する。中身はjs/historyScreen.jsが組み立てる。
   出題数が異なると得点をそのまま比較できないため、サマリーには平均得点を置いていない。 */

/* サマリー：収録曲一覧の内訳チップと似た、ガラス風の小さなチップを3つ横に並べる */
.history-summary-row {
  display: flex;
  gap: 8px;
  margin: 12px 0 16px;
}

.history-summary-chip {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 10px 6px;
  border-radius: 14px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
}

.history-summary-value {
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
}

.history-summary-label {
  font-size: 0.65rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.6;
}

/* 【2026-08-08追加】モード絞り込みチップ（すべて／イントロ／ランダム／歌詞／タイムアタック／対戦）。
   数が多くなっても崩れないよう、横スクロール可能なチップ列にする（本人指示）。 */
/* 【2026-09-09新設・本人指示3-1：プレイ履歴のオフライン/オンライン分離】
   下の細かいモードチップより1段階上の、主要な切り替えであることが分かるよう、
   等幅2分割のセグメントコントロール風の見た目にする。 */
.history-tabs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  padding: 4px;
  border-radius: 14px;
  background: rgba(0, 0, 0, 0.05);
  margin-bottom: 14px;
}

.history-tab {
  padding: 9px 10px;
  border-radius: 10px;
  border: none;
  background: transparent;
  color: var(--color-text);
  opacity: 0.65;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 800;
  cursor: pointer;
}

.history-tab.is-active {
  background: #ffffff;
  opacity: 1;
  color: var(--color-primary-dark);
  box-shadow: var(--shadow-card);
}

.history-filter-chips {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding-bottom: 4px;
  margin-bottom: 12px;
  scrollbar-width: none;
}

.history-filter-chips::-webkit-scrollbar {
  display: none;
}

.history-filter-chip {
  flex: none;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid var(--color-card-border);
  background: rgba(255, 255, 255, 0.5);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.76rem;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
}

.history-filter-chip.is-active {
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark));
  border-color: transparent;
  color: #ffffff;
}

/* 履歴が1件もないときの案内。空っぽの画面に見えないよう、ガラス風カードの中に文章だけを収める */
.history-empty-state {
  margin: 24px 0;
  padding: 20px 16px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid var(--color-card-border);
  text-align: center;
  font-size: 0.85rem;
  line-height: 1.6;
  color: var(--color-text);
  opacity: 0.75;
}

/* displayの指定がhidden属性より優先されてしまう問題への対策（.modal-overlay等と同じ理由） */
.history-empty-state[hidden] {
  display: none;
}

/* 【2026-10-30 fix-live】ライブコールモード（前の版）の曲一覧が空のときの案内。行き止まりにしないよう、データを足す場所へのボタンを出す */
.live-call-mode-empty-state {
  opacity: 1;
}
.live-call-mode-empty-title {
  margin: 0 0 6px;
  font-size: 0.95rem;
  font-weight: 800;
}
.live-call-mode-empty-text {
  margin: 0 0 12px;
  font-size: 0.85rem;
}
.live-call-mode-empty-actions {
  display: grid;
  gap: 8px;
}
.live-call-mode-empty-button {
  min-height: 44px;
  padding: 8px 12px;
  border: none;
  border-radius: 14px;
  background: linear-gradient(120deg, var(--color-primary-dark), var(--color-primary));
  color: #ffffff;
  font-family: inherit;
  font-size: 0.875rem;
  font-weight: 800;
  cursor: pointer;
}
.live-call-mode-empty-button.is-secondary {
  background: var(--color-surface);
  color: var(--color-primary-dark);
  border: 1.5px solid var(--color-primary);
}
.live-call-mode-empty-button:active {
  transform: scale(0.97);
}

/* 履歴カード1件分。タップで詳細画面を開けるよう<button>にしているため、
   ブラウザ標準のボタンの見た目（枠線・中央寄せ等）を打ち消して元のカードの見た目に揃える。 */
.history-entry {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 12px 14px;
  border-radius: 14px;
  margin-bottom: 8px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid var(--color-card-border);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.history-entry:active {
  transform: scale(0.98);
}

/* カードの中身（日時・ランク・モード・得点・称号バッジ）をまとめる入れ物。
   シェブロンアイコンと区別し、曲名等が長くても幅いっぱいに広がれるようにする。 */
.history-entry-content {
  flex: 1;
  min-width: 0;
}

/* 「タップで詳細に進める」ことを示すシェブロン */
.history-entry-chevron {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--color-primary);
  opacity: 0.6;
}

.history-entry-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 2px;
}

.history-entry-date {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
}

/* ランクの色分けだけを示す小さなチップ。結果画面のメダルほど演出は付けない、一覧用の簡易表示 */
.history-rank-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  font-size: 0.72rem;
  font-weight: 800;
  flex: none;
}

.history-rank-chip.rank-s {
  background: linear-gradient(160deg, #ffe9a8, #e3ab3c);
  color: #5c3a08;
}

.history-rank-chip.rank-a {
  background: linear-gradient(160deg, var(--color-primary), var(--color-primary-dark));
  color: #ffffff;
}

.history-rank-chip.rank-b {
  background: linear-gradient(160deg, #eaf6ff, #bfe4fb);
  color: #2c6ea8;
}

.history-rank-chip.rank-c {
  background: linear-gradient(160deg, #f3f0f8, #dcd6e6);
  color: #6b6478;
}

.history-new-record-mark {
  font-size: 0.68rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.history-entry-mode {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 700;
  opacity: 0.75;
}

.history-entry-score {
  margin: 2px 0 0;
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

/* 【2026-08-08追加】全モード共通タイムラインのカード用。ヘッダー行にモード名アイコン
   （js/specialModeIcons.jsを再利用）＋モード名＋日時、その下にモードごとの要約行を並べる。 */
.history-entry-mode-label {
  font-size: 0.82rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.history-entry-line {
  margin: 2px 0 0;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--color-text);
  opacity: 0.85;
}

.history-entry .special-mode-icon {
  flex: none;
  width: 34px;
  height: 34px;
}

/* 【2026-08-08追加】プレイ履歴詳細モーダル。他のモーダル（ルール説明・称号一覧）と
   同じ.modal-overlay/.modal-cardの土台を使い、中身だけこの画面専用にする。 */
.history-detail-modal-card {
  max-height: 80vh;
  overflow-y: auto;
}

.history-detail-modal-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 12px;
}

.history-detail-modal-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--color-card-border);
}

.history-detail-modal-label {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.65;
  flex: none;
}

.history-detail-modal-value {
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  text-align: right;
  overflow-wrap: anywhere;
}

.history-detail-modal-speed-heading {
  margin: 14px 0 6px;
  font-size: 0.78rem;
  font-weight: 700;
  opacity: 0.65;
}

.history-title-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 6px;
}

.history-title-badge {
  font-size: 0.68rem;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--color-accent-soft);
  color: var(--color-primary-dark);
  /* 称号名は日本語なので、文字単位で折り返されないようにする（12章の教訓と同じ対策） */
  white-space: nowrap;
}

/* 履歴の全削除ボタン。押しやすい主ボタンとは違い、あえて控えめな見た目にして誤操作を防ぐ */
.history-clear-button {
  display: block;
  width: fit-content;
  margin: 16px auto 0;
  padding: 6px 4px;
  border: none;
  background: none;
  color: var(--color-danger);
  opacity: 0.7;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  text-decoration: underline;
  cursor: pointer;
}

.history-clear-button[hidden] {
  display: none;
}

.history-clear-button:active {
  opacity: 1;
}

/* 削除確認モーダルのボタン列（.button-row）に上余白を足すためだけの専用クラス */
.history-clear-confirm-actions {
  margin-top: 16px;
}

/* クイズ中断・確認モーダルのボタン列：結果画面（#result-actions）と同じ縦2段構成にする。
   .primary-buttonは元々横並び用にwidth:100%を持たないため、縦並びでないと2つ並べたときに崩れる。 */
.quiz-quit-confirm-actions {
  margin-top: 16px;
  flex-direction: column;
}

.quiz-quit-confirm-actions .secondary-button {
  flex: none;
}

/* お気に入り／プレイリストの確認モーダル用（2026-08-28新設）。.primary-buttonは
   width:100%が既定のため、.secondary-buttonと横並び（flex-row）のままだと
   .primary-button側に押し負けてもう片方の文字が縦に潰れてしまう。
   #quiz-quit-confirm-actions等と同じく縦積みにして解決する。 */
.online-battle-song-list-confirm-actions {
  margin-top: 16px;
  flex-direction: column;
}

.online-battle-song-list-confirm-actions .secondary-button {
  flex: none;
}

/* 歌詞クイズ・中断確認モーダルのボタン列も、上の.quiz-quit-confirm-actionsと全く同じ理由で
   縦2段構成にする（このモーダルを新規追加した際、この上書きを付け忘れると、
   .primary-buttonがwidth:100%相当に広がろうとして.secondary-buttonが極端に狭く
   潰れてしまう不具合が起きる）。 */
.lyrics-quiz-quit-confirm-actions {
  margin-top: 16px;
  flex-direction: column;
}

.lyrics-quiz-quit-confirm-actions .secondary-button {
  flex: none;
}

/* 新曲お知らせ「追加済み・今後表示しない」確認モーダルのボタン列も、上の2つと全く同じ理由で
   縦2段構成にする（実際にこの上書きを付け忘れて、ボタンが巨大な円形に崩れる不具合を確認済み）。 */
.new-single-announcement-done-confirm-actions {
  margin-top: 16px;
  flex-direction: column;
}

.new-single-announcement-done-confirm-actions .secondary-button {
  flex: none;
}

/* 「削除する」ボタン：primary-button相当の押しやすさを保ちつつ、
   危険な操作だと伝わるよう赤系の配色にする */
.danger-button {
  flex: 1;
  padding: 10px;
  border: none;
  border-radius: 999px;
  background: var(--color-danger);
  color: #ffffff;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
  transition: transform var(--transition-fast) cubic-bezier(0.34, 1.56, 0.64, 1);
}

.danger-button:active {
  transform: scale(0.95);
}

/* ===== プレイ履歴 詳細画面 =====
   履歴一覧のカードをタップすると開く、曲別の内訳画面。中身はjs/historyDetailScreen.jsが組み立てる。 */

.history-detail-summary {
  padding: 14px;
  border-radius: 16px;
  margin: 12px 0 16px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  text-align: center;
}

.history-detail-date {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
}

.history-detail-mode {
  margin: 2px 0 0;
  font-size: 0.85rem;
  font-weight: 700;
  opacity: 0.8;
}

/* 結果画面の.rank-badgeと同じ構造・クラスを流用し、ここでは一覧の小さなチップ（22px）よりは
   大きく、結果画面の主役サイズ（88px）よりは控えめな、中間サイズに調整する。 */
.history-detail-rank-badge {
  margin: 8px auto 4px;
}

.history-detail-rank-badge .rank-medal {
  width: 64px;
  height: 64px;
}

.history-detail-rank-badge .rank-letter {
  font-size: 1.8rem;
}

.history-detail-rank-badge .rank-crown {
  top: -9px;
  width: 20px;
  height: 13px;
}

.history-detail-rank-badge .rank-medal-spark {
  top: -2px;
  width: 11px;
  height: 11px;
}

.history-detail-rank-badge .rank-medal-spark-left {
  left: -7px;
}

.history-detail-rank-badge .rank-medal-spark-right {
  right: -7px;
}

.history-detail-score {
  margin: 4px 0 0;
  font-size: 1rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.history-detail-average-time {
  margin: 2px 0 0;
  font-size: 0.78rem;
  color: var(--color-secondary);
  font-weight: 700;
}

.history-detail-summary .history-new-record-mark {
  display: block;
  margin-top: 4px;
}

.history-detail-summary .history-title-badges {
  justify-content: center;
}

/* 全問正解のとき、復習エリアの代わりに表示する一言 */
.history-detail-all-correct-message {
  margin: 4px 0 16px;
  padding: 12px;
  border-radius: 14px;
  background: var(--color-accent-soft);
  border: 1px solid var(--color-card-border);
  text-align: center;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.history-detail-all-correct-message[hidden] {
  display: none;
}

.history-detail-answer-list {
  list-style: none;
  padding: 0;
  margin: 4px 0 0;
}

.history-detail-answer-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  padding: 8px 4px;
  border-top: 1px solid var(--color-card-border);
}

.history-detail-answer-row:first-child {
  border-top: none;
}

.history-detail-answer-number {
  flex: none;
  width: 26px;
  font-size: 0.75rem;
  color: var(--color-text);
  opacity: 0.55;
  font-variant-numeric: tabular-nums;
}

/* 2026-09-16改訂・本人指示：UI一貫性ルール（曲名はピンクのピル表示に統一）。
   js/onlineBattleScreen.jsの共有曲一覧チップ（.online-battle-collab-song-chip）と
   同じ配色・角丸を採用し、履歴詳細でも曲名がひと目で分かるようにした。 */
.history-detail-answer-title {
  flex: 1 1 100px;
  min-width: 0;
  padding: 2px 10px;
  border-radius: 999px;
  background: var(--color-primary-light);
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  overflow-wrap: break-word;
}

/* 結果タグ4種類。色で正解/不正解/スキップ/答えを見た、を一目で区別できるようにする */
.history-detail-answer-tag {
  flex: none;
  display: inline-flex;
  align-items: center;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  white-space: nowrap;
}

.history-detail-answer-tag.is-correct {
  background: var(--color-accent-soft);
  color: var(--color-primary-dark);
}

.history-detail-answer-tag.is-wrong {
  background: var(--color-danger-soft);
  color: var(--color-danger);
}

.history-detail-answer-tag.is-skip {
  background: rgba(74, 46, 66, 0.08);
  color: var(--color-text);
  opacity: 0.75;
}

.history-detail-answer-tag.is-reveal {
  background: var(--color-secondary-light);
  color: #2c6ea8;
}

/* 得点・回答時間。幅が足りないときは、この2つがまとめて次の行に折り返る
   （メディアクエリを使わず、flex-wrapだけでスマホ幅・PC幅どちらにも自然に対応する） */
.history-detail-answer-meta {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.history-detail-answer-score {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
}

.history-detail-answer-time {
  font-size: 0.72rem;
  color: var(--color-text);
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
}

/* 内訳を最後まで見たことが分かる終端表示 */
.history-detail-list-end {
  margin: 10px 0 0;
  text-align: center;
  font-size: 0.72rem;
  color: var(--color-text);
  opacity: 0.5;
}

/* ===== 特別モード =====
   通常プレイ（スタートボタン）とは別の遊び方をまとめる、スタート画面の入口・一覧画面・
   苦手曲モードの確認画面。中身はjs/specialModesScreen.js・js/weakSongsScreen.jsが組み立てる。 */

/* スタート画面の情報リンク群（.start-footer-links）と、特別モードの入口を見た目で区切る線。
   通常プレイが主役であることが伝わるよう、あえて独立した扱いにしている。 */
.special-modes-divider {
  width: 60%;
  max-width: 200px;
  height: 1px;
  margin: 18px auto 14px;
  background: var(--color-card-border);
}

.special-modes-intro {
  margin: 4px 0 16px;
  text-align: center;
  font-size: 0.82rem;
  color: var(--color-text);
  opacity: 0.7;
}

/* 【2026-11-XX新設・本人指示：「一緒に遊ぶ」】フレンド一覧直前の短い案内文。
   .special-modes-introと同じ控えめなトーンだが、一覧の直上という別の位置で使うため
   専用クラスにしている。 */
.fan-profiles-invite-hint {
  margin: 0 0 12px;
  text-align: center;
  font-size: 0.8rem;
  color: var(--color-text);
  opacity: 0.7;
}

/* ランキング画面：通常クイズからも参加できることを伝える一言（2026-08-16追加）。
   上の.special-modes-intro（条件の説明）とは分けて、招待の一言だけ軽く強調する。 */
.leaderboard-mode-invite {
  margin: -8px 0 8px;
  padding: 8px 14px;
  border-radius: 12px;
  background: var(--color-primary-light);
  text-align: center;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

/* ランキング画面：「フレンド」公開設定が必要という注記（2026-08-16追加）。本人指示により、
   上の説明文・招待文より目立たせず、末尾に小さく添えるだけにとどめる。 */
.leaderboard-privacy-note {
  margin: 0 0 16px;
  text-align: center;
  font-size: 0.72rem;
  color: var(--color-text);
  opacity: 0.6;
}

/* ランキング画面：出題タイプ・出題数・カテゴリーの各タブ行が、それぞれ何を選ぶ軸なのか
   一目で分かるようにする小さな見出し（2026-08-16追加、本人指示）。画面をうるさくしすぎない
   よう、タブボタンそのものより小さく・控えめな色にする。 */
.leaderboard-tab-axis-label {
  margin: 14px 0 2px;
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.55;
  letter-spacing: 0.02em;
}

.leaderboard-tab-axis-label:first-of-type {
  margin-top: 4px;
}

/* ===== 特別モードのアイコン（js/specialModeIcons.js） =====
   本人指示（2026-08-07）：「8枚を見た瞬間、それぞれ別のモードだと視覚的に分かる」ように、
   モードごとに異なるパステルカラーの丸背景をアイコンに付ける。生のUnicode絵文字は
   OS・端末で見た目が変わってしまうためSVGで統一し（js/achievementIcons.jsと同じ方針）、
   色の違いだけをここ（CSS側）で塗り分ける。カード本体の白基調・ピンクのアクセントは
   維持しつつ、アイコン背景だけに薄いパステルカラーを使うことで世界観を壊さないようにしている。
   装飾目的のみ（aria-hidden="true"）なので、モード名・説明文は今までどおり別途表示する。 */
.special-mode-icon {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  color: #ffffff;
}

.special-mode-icon svg {
  width: 55%;
  height: 55%;
}

/* 【2026-08-08追加】通常イントロクイズ用（統一プレイ履歴で使う。8つの特別モードには無い）。 */
.special-mode-icon.is-intro {
  background: linear-gradient(155deg, #ff9ec4, var(--color-primary));
}

.special-mode-icon.is-weakSongs {
  background: linear-gradient(155deg, #b98cf0, #8a5fd6);
}

.special-mode-icon.is-originalQuiz {
  background: linear-gradient(155deg, #ffd766, #e3ab3c);
}

.special-mode-icon.is-timeAttack {
  background: linear-gradient(155deg, #ffb37a, #ff8a5c);
}

.special-mode-icon.is-randomPlayback {
  background: linear-gradient(155deg, #6fe0c0, #3fb894);
}

/* ペンライトの発光部分（アイコン内で#ff6fa8＝ブランドピンクを使用）が背景に埋もれないよう、
   他のカードより一段深いプラム系の背景にしている（本人指示・2026-08-07：メガホン→ペンライト）。 */
.special-mode-icon.is-liveCallMode {
  background: linear-gradient(155deg, #c96fa0, #8a3f68);
}

.special-mode-icon.is-lyricsQuiz {
  background: linear-gradient(155deg, #7fd0ff, var(--color-secondary));
}

.special-mode-icon.is-localBattle {
  background: linear-gradient(155deg, #ff9d8a, #f2665f);
}

.special-mode-icon.is-onlineBattle {
  background: linear-gradient(155deg, #9db4ff, #6f8bf2);
}

/* 【2026-09-15新設】パーティー対戦（旧1台対戦の暖色系を引き継ぎつつ、お祭り感のあるオレンジ〜ピンク）。 */
.special-mode-icon.is-partyBattle {
  background: linear-gradient(155deg, #ffb46b, #ff6f8e);
}

/* 2026-08-30追加：アウトロクイズ・一瞬チャレンジ。 */
.special-mode-icon.is-outroQuiz {
  background: linear-gradient(155deg, #b7a0e8, #6f5aa8);
}

.special-mode-icon.is-instantChallenge {
  background: linear-gradient(155deg, #ffe066, #f2a33f);
}

.special-mode-card.is-coming-soon .special-mode-icon {
  filter: grayscale(45%);
}

/* 特別モード一覧のカード1件分。プレイ履歴カードと同じ「ボタン＋シェブロン」の構成。 */
.special-mode-card {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 14px;
  border-radius: 14px;
  margin-bottom: 10px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid var(--color-card-border);
}

/* カード本体のタップ領域。「？」ヘルプボタンと兄弟要素にするため、カード全体ではなく
   ここだけを<button>にしている（<button>の中に<button>は入れられないため）。 */
.special-mode-card-tap-target {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
  padding: 0;
  border: none;
  background: none;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.special-mode-card-tap-target:active {
  transform: scale(0.98);
}

.special-mode-card-content {
  flex: 1;
  min-width: 0;
}

/* モードカードの「？」ヘルプボタン。weakSongsRulesLink等で使っている.info-link-buttonと
   同じ見た目にしているが、あちらはグリッドレイアウト前提のgrid-column指定を持つため、
   flexレイアウトのこのカードでは流用せず専用クラスにしている。 */
.special-mode-card-help-button {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 800;
  cursor: pointer;
}

.special-mode-card-help-button:active {
  transform: scale(0.92);
}

.special-mode-card-title {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.special-mode-card-description {
  margin: 2px 0 0;
  font-size: 0.78rem;
  color: var(--color-text);
  opacity: 0.7;
}

.special-mode-card-chevron {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--color-primary);
  opacity: 0.6;
}

/* まだ実装されていないモード：<button>ではなく<div>にしているのでcursor:pointerを打ち消し、
   タップできないことが見た目でも伝わるよう全体を薄くする。 */
.special-mode-card.is-coming-soon {
  cursor: default;
  opacity: 0.55;
}

/* 【2026-08-30追加】新モードにだけ添える「NEW」表示。近日追加予定バッジ
   （.special-mode-card-badge、直下）とは別クラスにし、赤系の目立つ色にする。 */
.special-mode-card-new-badge {
  flex: none;
  align-self: flex-start;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--color-danger);
  color: #ffffff;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

.special-mode-card-badge {
  flex: none;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-text);
  white-space: nowrap;
}

/* ===== ホーム画面：特別モード10件を2列×5段で直接表示するグリッド（2026-08-07追加、2026-08-30に8件→10件） =====
   カードそのもの（.special-mode-card一式）はjs/specialModesScreen.jsの
   buildAvailableCard/buildComingSoonCardをそのまま再利用しており、HTML構造・JSロジックは
   一覧画面（#special-modes-list）と完全に同じ。ここではホーム画面の狭い2列幅に収まるよう、
   このグリッドの中に限定してCSSだけで見た目を調整している（本人の指示通り、名称が長い
   カードは文字サイズと改行で対応）。
   ・PC・スマホとも基本2列（grid-template-columns: 1fr 1fr）を維持する。
   ・375px幅でも重ならない・はみ出さない・横スクロールしないことをブラウザで確認済み。 */
.home-special-modes-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin: 4px 0 16px;
}

/* 一覧画面（横に長い1列の行）と違い、ここでは縦積みのコンパクトなカードにする。 */
.home-special-modes-grid .special-mode-card {
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  width: auto;
  min-width: 0;
  padding: 10px 10px 12px;
  margin-bottom: 0;
  position: relative;
}

.home-special-modes-grid .special-mode-card-tap-target {
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  width: 100%;
  min-width: 0;
  padding-right: 24px; /* 右上の？ヘルプボタンと文字が重ならないよう余白を確保 */
}

.home-special-modes-grid .special-mode-card-content {
  width: 100%;
  min-width: 0;
}

/* ホーム画面の2列カードは縦積み（flex-direction:columnのtapTarget内で、アイコンが
   最初の子要素として上段に来る）なので、一覧画面より小さめのサイズにして、
   タイトル・説明の横に窮屈な余白を残さないようにする。 */
.home-special-modes-grid .special-mode-icon {
  width: 32px;
  height: 32px;
  margin-bottom: 6px;
}

.home-special-modes-grid .special-mode-card-title {
  font-size: 0.8rem;
  line-height: 1.3;
  overflow-wrap: break-word;
}

.home-special-modes-grid .special-mode-card-description {
  font-size: 0.66rem;
  line-height: 1.35;
  overflow-wrap: break-word;
}

/* 2列の狭いカードではチェブロン（一覧画面の「タップで進める」矢印）を省略する。
   カード全体がタップできる見た目（アイコンや角丸カード）で十分に伝わるため。 */
.home-special-modes-grid .special-mode-card-chevron {
  display: none;
}

/* 「？」ヘルプボタンはカード右上に固定し、タイトル・説明の横幅を圧迫しないようにする。 */
.home-special-modes-grid .special-mode-card-help-button {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 22px;
  height: 22px;
  font-size: 0.7rem;
}

.home-special-modes-grid .special-mode-card-badge {
  margin-top: 4px;
  align-self: flex-start;
  white-space: normal;
  font-size: 0.62rem;
}

/* 非常に狭い端末（350px未満）だけ1列へ切り替える。375pxでは2列を維持する（本人指示）。 */
@media (max-width: 349px) {
  .home-special-modes-grid {
    grid-template-columns: 1fr;
  }
}

.weak-songs-explanation {
  margin: 4px 0 14px;
  text-align: center;
  font-size: 0.8rem;
  color: var(--color-text);
  opacity: 0.75;
}

.weak-songs-count {
  margin: 0 0 10px;
  text-align: center;
  font-size: 0.85rem;
  color: var(--color-text);
}

.weak-songs-count strong {
  font-size: 1.1rem;
  color: var(--color-primary-dark);
}

/* オリジナル問題作成モードの選曲画面 */

.custom-quiz-selected-count {
  margin: 4px 0 12px;
  text-align: center;
  font-size: 0.85rem;
  color: var(--color-text);
}

.custom-quiz-selected-count strong {
  font-size: 1.1rem;
  color: var(--color-primary-dark);
}

/* 1曲分の選択行。チェック部分（.song-select-label）と試聴ボタンを横に並べる入れ物。
   試聴ボタンをlabelの外に出しているのは、labelの中に置くと試聴ボタンを押したときに
   チェックボックスまで反応してしまうため。 */
.song-select-row {
  display: flex;
  align-items: center;
  gap: 4px;
}

.song-select-row[hidden] {
  display: none;
}

/* チェックできる範囲。行のどこをタップしてもチェックできる */
.song-select-label {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  flex: 1;
  min-width: 0;
  padding: 8px;
  border-radius: 10px;
  cursor: pointer;
}

.song-select-label:active {
  background: var(--color-primary-light);
}

.song-select-label input[type="checkbox"] {
  flex: none;
  width: 18px;
  height: 18px;
  accent-color: var(--color-primary);
}

/* すでにプレイリストに入っている曲の行（プレイリストへの曲追加画面）。
   チェック済み・操作不可の状態を、見た目でも「もう入っている」と分かるように薄くする。 */
.song-select-label.is-already-added {
  opacity: 0.55;
  cursor: default;
}

/* 2026-09-16改訂・本人指示：UI一貫性ルール（曲名は常に濃いピンク＋太字）。
   プレイリストへの曲追加画面・オンライン対戦の出題曲選択画面（どちらもこの
   .song-select-titleを共用）で、曲名の色を.track-titleと同じブランドピンクに揃えた。 */
.song-select-title {
  flex: 1;
  min-width: 0;
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  overflow-wrap: break-word;
}

/* 2026-09-15新設・本人指示：曲選択画面を開いたまま、他の参加者がその曲を選んでいるかを
   確認できるバッジ（js/onlineBattleSongPicker.jsのupdateOnlineBattleSongPickerLiveSelections()
   参照）。.song-select-labelにflex-basis:100%で常に新しい行へ折り返させ、チェックボックス＋
   隙間の幅ぶんだけインデントして曲名の真下に来るようにする。 */
.song-select-others-badge {
  flex-basis: 100%;
  margin: 0 0 0 28px;
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.song-select-others-badge[hidden] {
  display: none;
}

/* 試聴ボタン自体は、収録曲一覧の.play-buttonをそのまま使い回している。
   行が試聴中（is-playing）のときのアイコン切り替え・色も、.track-rowと同じ考え方で揃える。 */
.song-select-row.is-playing .icon-play {
  display: none;
}

.song-select-row.is-playing .icon-pause {
  display: block;
}

.song-select-row.is-playing .play-button {
  background: var(--color-primary-dark);
  color: #ffffff;
}

/* 名前・メモの入力欄と保存ボタンをまとめた入れ物。新規作成・既存プリセットを開いた場合の
   両方で表示する（内容の埋め込み・ボタン文言の切り替えはjs/customQuizScreen.jsが行う）。 */
#custom-quiz-save-section {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--color-card-border);
}

.custom-quiz-field {
  display: block;
  margin-bottom: 10px;
}

.custom-quiz-field span {
  display: block;
  margin-bottom: 4px;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.75;
}

.custom-quiz-field input[type="text"],
.custom-quiz-field textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.7);
  color: var(--color-text);
  font-family: inherit;
  /* 【2026-09-06修正、本人指示：実機フィードバック】16px未満だとiOS Safariが
     フォーカス時に自動ズームしてしまうため16pxへ引き上げた（css/style.css冒頭の
     body input[type="text"]等と同じ理由。この規則は詳細度がより高く上書きされて
     しまうため、個別に直接修正した）。 */
  font-size: 16px;
}

/* メモ欄：縦方向にだけ手動で広げられるようにする（横方向のresizeはレイアウトが崩れるため許可しない） */
.custom-quiz-field textarea {
  resize: vertical;
  line-height: 1.5;
}

.custom-quiz-field input[type="text"]:focus-visible,
.custom-quiz-field textarea:focus-visible {
  outline: 2px solid var(--color-primary-dark);
  outline-offset: 1px;
}

/* 丸みのある検索欄。プリセット一覧の検索・選曲画面の曲名検索、両方で共通して使う */
.pill-search-input {
  display: block;
  width: 100%;
  margin: 4px 0 14px;
  padding: 10px 12px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.7);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.85rem;
}

.pill-search-input:focus-visible {
  outline: 2px solid var(--color-primary-dark);
  outline-offset: 1px;
}

/* 検索欄＋「×」クリアボタンの入れ物。収録曲一覧・オリジナル問題作成モードの
   選曲画面、両方の曲名検索で共通して使う。margin（縦の余白）は本来.pill-search-input
   が持っていたものをこちらに移し、入力欄自体はmargin: 0にする
   （こうしないと、上下の余白が非対称なぶん×ボタンの縦中央がずれてしまうため）。 */
.search-field-row {
  position: relative;
  margin: 4px 0 14px;
}

.search-field-row .pill-search-input {
  margin: 0;
  padding-right: 38px;
}

/* 検索語が入っているときだけ表示する「×」ボタン。見た目の丸とクリック領域を
   width/heightで固定したうえでdisplay:flexで×を中央揃えにする（.modal-close-buttonと同じ考え方）。
   hidden属性とdisplay:flexが競合しないよう、[hidden]用の上書きルールを必ず用意する
   （12章の教訓：display指定のある要素にhidden属性を使うときの定石）。 */
.search-clear-button {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.08);
  color: var(--color-text);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

.search-clear-button[hidden] {
  display: none;
}

/* 見た目の丸はそのままに、クリック判定だけを一回り広げる（.modal-close-buttonと同じ考え方）。 */
.search-clear-button::after {
  content: "";
  position: absolute;
  inset: -6px;
}

.search-clear-button:active {
  transform: translateY(-50%) scale(0.9);
}

/* オリジナル問題作成モードの選曲画面：画面全体を対象にした一括選択ボタン。
   シングルごとの全選択/全解除（.single-group-bulk-button）と見た目を揃えつつ、
   独立した行として配置する。 */
.custom-quiz-bulk-actions {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin: 4px 0 10px;
}

/* 試聴の共通ミニプレイヤー。何か試聴中（一時停止中も含む）のときだけ表示する。
   収録曲一覧の再生行と近い部品（.play-button・.seek-range・.seek-skip-button）を
   そのまま流用し、見た目のトーンを揃えている。 */
.custom-quiz-preview-player {
  margin: 4px 0 14px;
  padding: 10px 12px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 14px;
  background: var(--color-primary-light);
}

.custom-quiz-preview-player[hidden] {
  display: none;
}

.custom-quiz-preview-title {
  margin: 0 0 6px;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  text-align: center;
  overflow-wrap: break-word;
}

.custom-quiz-preview-seek-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.custom-quiz-preview-time {
  flex: none;
  font-size: 0.68rem;
  color: var(--color-text);
  opacity: 0.7;
  font-variant-numeric: tabular-nums;
}

.custom-quiz-preview-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
}

/* ミニプレイヤーの再生/一時停止ボタンは.play-buttonを流用するが、
   再生中かどうかはこのプレイヤー自身の.is-playingクラスで判定する
   （試聴中の行のis-playingとは別に、常に「今まさに音が鳴っているか」を表す）。
   アイコンを普段は非表示にする.icon-pauseの基本ルールは、songlist.js用の既存定義を共有する。 */
.custom-quiz-preview-player.is-playing .icon-play {
  display: none;
}

.custom-quiz-preview-player.is-playing .icon-pause {
  display: block;
}

.custom-quiz-preview-player.is-playing .play-button {
  background: var(--color-primary-dark);
  color: #ffffff;
}

/* 「選択済みの曲だけ表示」トグル。他のチェックボックス付きラベルと同じ、
   飾らないシンプルな見た目にする */
.custom-quiz-selected-only-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 12px;
  font-size: 0.8rem;
  color: var(--color-text);
  cursor: pointer;
}

.custom-quiz-selected-only-toggle input[type="checkbox"] {
  accent-color: var(--color-primary);
}

/* 保存/更新の完了バナー。#new-record-badgeと同じ「丸いお知らせチップ」の見た目に揃える。
   数秒で自動的に消えるので、演出も控えめにしている。 */
.custom-quiz-presets-saved-banner {
  width: fit-content;
  max-width: 100%;
  margin: 0 auto 12px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--color-accent);
  background-color: var(--color-accent-soft);
  color: var(--color-primary-dark);
  font-size: 0.82rem;
  font-weight: 700;
  text-align: center;
}

/* displayの指定がhidden属性より優先されてしまう問題への対策（#new-record-badge等と同じ理由） */
.custom-quiz-presets-saved-banner[hidden] {
  display: none;
}

#custom-quiz-save-section .secondary-button {
  display: block;
  width: 100%;
  margin-top: 4px;
}

/* プリセット一覧のカード：「タップで選曲画面を開く」メインボタンと「収録曲を見る」を
   別々の操作領域にするため、.special-mode-cardとは違い外枠（このクラス）を
   ボタンではなく入れ物にしている。見た目は.special-mode-cardと揃える。 */
.preset-card {
  border-radius: 14px;
  margin-bottom: 10px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid var(--color-card-border);
  overflow: hidden;
}

/* メインボタン（タップで選曲・編集画面を開く）と削除アイコンを横に並べる入れ物。
   削除は独立した操作領域にし、誤操作を防ぐため小さく・控えめに配置する。 */
.preset-card-top {
  display: flex;
  align-items: stretch;
}

.preset-card-main {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
  padding: 14px;
  border: none;
  background: none;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.preset-card-main:active {
  background: var(--color-primary-light);
}

/* 複製・削除、どちらも小さな独立アイコンボタンとして共通の見た目にする。
   押したときの色だけ、複製＝テーマカラー／削除＝警告色で区別する。 */
.preset-card-icon-button {
  flex: none;
  width: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  color: var(--color-text);
  opacity: 0.4;
  cursor: pointer;
}

.preset-card-icon-button svg {
  width: 18px;
  height: 18px;
}

.preset-card-copy-icon:active {
  opacity: 0.8;
  color: var(--color-primary-dark);
}

.preset-card-delete-icon:active {
  opacity: 0.8;
  color: var(--color-danger);
}

/* メモは一覧では1行に省略する。全文は詳細モーダルで確認できる */
.preset-card-memo {
  margin: 2px 0 0;
  font-size: 0.72rem;
  color: var(--color-text);
  opacity: 0.6;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 「▶ プレイ」「収録曲を見る」の2ボタン行。カード本体（タップで選曲・編集画面を開く）
   とは別の操作領域として、はっきり区切って並べる。 */
.preset-card-actions {
  display: flex;
  border-top: 1px solid var(--color-card-border);
}

.preset-card-play-button,
.preset-card-detail-link {
  flex: 1;
  padding: 8px 10px;
  border: none;
  background: rgba(255, 255, 255, 0.3);
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.76rem;
  font-weight: 700;
  text-align: center;
  cursor: pointer;
}

.preset-card-play-button {
  border-right: 1px solid var(--color-card-border);
}

.preset-card-play-button:active,
.preset-card-detail-link:active {
  background: var(--color-primary-light);
}

/* プリセット詳細モーダル：曲数・ダミー選択肢モードのサマリー行 */
.custom-quiz-preset-detail-summary {
  margin: 4px 0 14px;
  text-align: center;
  font-size: 0.8rem;
  color: var(--color-text);
  opacity: 0.75;
}

/* シングル単位の全曲名（読み取り専用）。開閉はできず、常に展開した状態で並べる */
.preset-detail-group {
  margin-bottom: 12px;
}

.preset-detail-group-label {
  margin: 0 0 4px;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

/* 2026-09-16改訂・本人指示：UI一貫性ルール（曲名は常にピンクのピル表示に統一）。
   js/onlineBattleScreen.jsの共有曲一覧チップ（.online-battle-collab-song-chip /
   -chip-list）と同じ配色・角丸・並べ方にして、曲名表示のスタイルをアプリ全体で揃えた。 */
.preset-detail-song-chip-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.preset-detail-song-chip {
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-size: 0.74rem;
  font-weight: 700;
}

/* 結果画面：特別モードの結果でだけ表示する短い案内。自己ベスト欄の代わりに表示するため、
   同じ立ち位置になるよう#high-score-displayに近い見た目にする。 */
.special-mode-notice {
  text-align: center;
  font-size: 0.85rem;
  color: var(--color-text);
  opacity: 0.75;
}

/* ===== ＝LOVEをもっと知る（スタート画面の入口） ===== */

/* スタート画面の「プレイヤー・推しメン」カード（2026-08-03追加、2026-08-04拡大）。
   「誰が遊んでいるか」を一番に伝える要素として、音源・歌詞の読み込みUIより
   目立つ大きさ・存在感にしている。 */
.player-hero-card {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 12px auto 14px;
  padding: 12px 16px;
  max-width: 340px;
  border-radius: 20px;
  background: linear-gradient(135deg, rgba(255, 111, 168, 0.16), rgba(111, 189, 242, 0.16));
  border: 1.5px solid var(--color-card-border);
  box-shadow: 0 10px 24px -16px rgba(74, 46, 66, 0.35);
}

/* 【2026-11-XX改訂・本人指示：招待通知を表示する画面を拡大】以前はホーム画面内の
   通常のページ内カードだったが、複数の画面で表示できるようbodyの直下へ移動したため、
   #update-applied-banner（.update-applied-banner）と同じposition:fixed＋safe-area対応の
   考え方に変更した。実際のfixed配置・safe-area paddingは親の.invite-notification-stack
   側で行い、このクラス自体は見た目（カードのデザイン）だけを担当する。 */
.invite-notification-stack {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 45; /* update-applied-banner（50）より奥、モーダル（20）より手前 */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: max(10px, env(safe-area-inset-top)) 16px 0;
  pointer-events: none; /* 何も無い部分はタップを素通りさせる */
}

.invite-notification-stack > * {
  pointer-events: auto;
}

.room-invite-banner {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  max-width: 340px;
  padding: 14px 16px;
  border-radius: 20px;
  background: linear-gradient(135deg, rgba(111, 189, 242, 0.18), rgba(255, 111, 168, 0.14));
  border: 1.5px solid var(--color-card-border);
  box-shadow: 0 10px 24px -16px rgba(74, 46, 66, 0.35);
}

/* 【本人指示済みの既知パターン：tests/cssHiddenAttributeEffectiveness.test.js参照】
   display:flexを明示指定するクラスは、[hidden]属性の打ち消しルールを個別に持たないと、
   JS側でhidden=trueにしても実際には非表示にならない（著者スタイルシートの詳細度が
   ブラウザ標準の[hidden]{display:none}に勝ってしまうため）。招待が無いときにこのバナーが
   ホーム画面に表示され続けてしまう回帰を防ぐため、他の同種クラスと同じ対応をここでも行う。 */
.room-invite-banner[hidden] {
  display: none;
}

/* 【2026-11-XX新設・本人指示：「あとで」のUX再設計】有効な招待がすべて「あとで」で
   隠れている間だけ表示する、小さな再確認チップ。フルサイズのバナーより控えめな見た目にし、
   押すとまた通常のバナーへ戻る（js/roomInviteUi.js・js/playInviteUi.js共通で使う）。 */
.invite-reminder-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1.5px solid var(--color-card-border);
  background: rgba(255, 255, 255, 0.75);
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 6px 16px -10px rgba(74, 46, 66, 0.35);
}

.invite-reminder-chip[hidden] {
  display: none;
}

.invite-reminder-chip:active {
  transform: scale(0.96);
}

/* 【2026-11-XX新設・本人の実機テスト指摘：招待通知の二段階UI】招待到着直後に出す、
   1行だけのコンパクトな通知。以前の3択パネルが実機でDynamic Island下の「戻る」
   リンク等を覆ってしまっていたため、まずはこの小さな通知だけを出し、
   「確認する」を押した人だけ詳細（3択・.room-invite-banner）を開く設計にした。
   横幅が足りない場合はテキストを省略して1行に収める（本人指示：「長いユーザー名の
   場合もレイアウトを壊さず」）。 */
.invite-compact-notice {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  max-width: 340px;
  padding: 10px 14px;
  border-radius: 999px;
  background: linear-gradient(135deg, rgba(111, 189, 242, 0.22), rgba(255, 111, 168, 0.18));
  border: 1.5px solid var(--color-card-border);
  box-shadow: 0 8px 20px -14px rgba(74, 46, 66, 0.4);
}

.invite-compact-notice[hidden] {
  display: none;
}

.invite-compact-text {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--color-text);
}

.invite-compact-confirm-button {
  flex: none;
  padding: 7px 14px;
  border-radius: 999px;
  border: none;
  background: linear-gradient(120deg, var(--color-primary-dark), var(--color-primary));
  color: #ffffff;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
}

.invite-compact-confirm-button:active {
  transform: scale(0.95);
}

/* 【2026-11-XX新設・本人指示】相手の操作結果を伝えるだけの受信トースト
   （「今回は一緒に遊べませんでした」等）。.invite-compact-noticeのボタン付き通知と
   見た目で区別できるよう、ボタンが無い＝タップ不要であることが伝わる控えめな配色にし、
   中央寄せの1行テキストにする（本人指示：能動的な確認が要る通知と、結果を知らせるだけの
   受け身の通知を混同しないUIにする）。 */
.invite-flash-notice {
  justify-content: center;
  text-align: center;
  background: rgba(120, 120, 130, 0.14);
  border-color: var(--color-card-border);
  margin: 0;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--color-text-muted, var(--color-text));
}

/* 【2026-11-XX新設・本人指示：送信者側の状態バーをコンパクト化】以前は
   「◯◯さんを招待しています…」＋大きめの「招待を取り消す」ボタンが縦にかなりの
   高さを取っていた。1行のバーへ変更し、状態に応じてボタンが入れ替わる
   （通常は［取消］、後からの参加希望への回答待ちは［今回はやめる］［一緒に遊ぶ］）。 */
.play-invite-outgoing-actions {
  display: flex;
  flex: none;
  gap: 6px;
}

.play-invite-outgoing-actions button {
  flex: none;
  padding: 6px 12px;
  font-size: 0.76rem;
  white-space: nowrap;
}

/* 【本人指示：3択（参加する／あとで／断る）】340px幅の中に3つ並べると、端末幅や
   フォントサイズ次第で収まりきらないことがあるため、折り返しを許可し、各ボタンが
   均等に伸縮する形にする（固定pxで幅を決め打ちしない）。 */
.room-invite-banner-actions {
  flex-wrap: wrap;
}

/* 【2026-11-XX修正・実機相当バグ発見：320px幅で文字が縦1文字ずつに潰れる】
   以前はmin-width: 0を指定していたが、これは「内容の幅より小さくは絶対に縮めない」
   というボタンのデフォルト挙動（min-width: auto）を打ち消してしまっていた。
   min-widthを指定しない（＝既定のauto）に戻すことで、内容の最小幅より縮められなくなる。
   ただし日本語テキストは英単語と違い、どの文字と文字の間でも改行できてしまうため、
   min-width: autoが基準にする「最小内容幅（min-content）」が実質1文字分にしかならず、
   これだけでは3つのボタンが同じ行に無理やり並んで縦1文字ずつに潰れる崩れを防げなかった
   （320px幅の実機相当テストで発見）。white-space: nowrapでボタン内テキストの折り返し
   自体を禁止することで、min-content幅が「文言全体の横幅」まで正しく広がり、
   1行に収まりきらない分は上のflex-wrap: wrapどおりボタンごと次の行へ折り返されるようになる
   （文字が潰れるのではなく、ボタンが2段になる本来の設計に戻る）。 */
.room-invite-banner-actions button {
  flex: 1 1 auto;
  white-space: nowrap;
}

/* 【2026-11-XX追加・同じ調査で発見】.button-row .primary-button（2026-09-06追加、上記
   2417行目付近）が「参加する」ボタンにflex: 1（flex-basis: 0%）を指定しており、これが
   上のflex: 1 1 autoより詳細度で勝ってしまう（クラス2つ vs クラス1つ+要素1つ）。
   flex-basisが0%のままだと、折り返すかどうかの判定（ブラウザが行間の折返し可否を
   決める計算）はこの「0%」を基準に行われるため、実際にはmin-widthで下限が効いて
   3つ目のボタンだけがコンテナ幅からはみ出す（折り返さずに右へ食い込む）崩れになる。
   ここだけflex-basisをautoへ戻し、他の2ボタンと同じ土俵で折返し判定させる
   （詳細度はどちらもクラス2つで並ぶため、後に書いた本ルールが有効になる）。 */
.room-invite-banner-actions .primary-button {
  flex-basis: auto;
}

.room-invite-banner-text {
  font-size: 0.86rem;
  font-weight: 700;
  line-height: 1.5;
}

.room-invite-banner-more-label {
  font-size: 0.72rem;
  opacity: 0.75;
}

/* 【2026-11-XX新設・本人指示：「一緒に遊ぶ」送信者側の待機表示】受信側の招待バナー
   （.invite-notification-stack、画面上部）とぶつからないよう、あえて画面下部に固定する。
   #update-applied-bannerと同じposition:fixed＋safe-area対応の考え方。 */
/* 【2026-11-XX改訂・本人指示：送信者側の状態バーをコンパクト化】以前は縦積みの
   カードで、フレンド一覧をかなり押し下げていた。1行の細いバーへ変更し、
   .invite-compact-noticeと同じ「テキスト＋右側にボタン」の考え方に揃えた
   （ただし位置は画面下部のまま。受信側の通知スタック（画面上部）とぶつからない）。 */
.play-invite-outgoing-card {
  position: fixed;
  left: 16px;
  right: 16px;
  bottom: max(14px, env(safe-area-inset-bottom));
  z-index: 45;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: 340px;
  margin: 0 auto;
  padding: 10px 14px;
  border-radius: 999px;
  background: linear-gradient(135deg, rgba(255, 111, 168, 0.22), rgba(111, 189, 242, 0.16));
  border: 1.5px solid var(--color-card-border);
  box-shadow: 0 10px 24px -16px rgba(74, 46, 66, 0.35);
}

/* 【本人指示済みの既知パターン：tests/cssHiddenAttributeEffectiveness.test.js参照】
   display:flexを明示指定するクラスは、[hidden]属性の打ち消しルールを個別に持たないと
   実際には非表示にならない。 */
.play-invite-outgoing-card[hidden] {
  display: none;
}

.play-invite-outgoing-text {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.82rem;
  font-weight: 700;
}

.room-invite-picker-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 10px;
}

.room-invite-picker-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 12px;
  background: var(--color-surface-soft, rgba(0, 0, 0, 0.04));
}

.room-invite-picker-row-name {
  font-size: 0.86rem;
  font-weight: 700;
  /* 【2026-09-06修正・最終QAフェーズで発見】min-width:0が無いと、長い表示名の相手を
     招待しようとしたとき、flexアイテムが縮まずに「招待する」ボタンを画面外へ押し出し、
     ボタンが押せなくなる不具合があった。.online-lobby-player-nameと同じ対策を適用する。 */
  min-width: 0;
  overflow-wrap: anywhere;
}

.room-invite-picker-row-button {
  flex: none;
  font-size: 0.76rem;
  padding: 6px 10px;
}

.player-hero-swatch {
  position: relative;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  color: #fff;
  box-shadow: 0 4px 10px -4px rgba(0, 0, 0, 0.3), inset 0 -3px 6px rgba(0, 0, 0, 0.1);
}

.player-hero-swatch svg {
  width: 22px;
  height: 22px;
}

.player-hero-swatch.is-placeholder {
  background: linear-gradient(145deg, #e8dde3, #d8c8d2);
  color: rgba(255, 255, 255, 0.85);
}

/* ===== 推しアイコンへの特別バッジ装飾（js/oshiBadge.js） =====
   ＝LOVEマスター取得で王冠、＝LOVE完全制覇取得でダイヤ、イントロマスター取得でメダルを
   表示する（本人指示）。
   【2026-11-XX全面改訂・本人指示：3個同時表示】以前はCSSの::before/::afterだけ（最大2つ）で
   表現し、下位のメダルは上位2つを持っていると隠す「代表1つだけ表示」の仕組みだった。
   今回「所持している特別バッジは3個すべて同時に表示する」という指示を受け、疑似要素では
   なく実際のDOM子要素（.oshi-badge-layer配下の.oshi-badge、js/oshiBadge.js参照）へ作り替えた。
   3個とも常にアイコン本体の外周へのoverlayとして重ね、アイコン本体のサイズには一切触れない
   （本人指示：「バッジのために推しアイコンを縮小しない」）。クリック操作を邪魔しないよう、
   レイヤー自体・各バッジともpointer-events:noneにしている。
   【配置】3個同時が最悪ケースのため、右上（＝LOVE完全制覇・最も豪華）・右下（＝LOVEマスター）・
   左下（イントロマスター）の3つの角へ分散させ、名前・順位・スコア等が続くことが多い右側の
   スペースを最小限しか使わないようにしている。 */
.oshi-badge-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.oshi-badge {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  /* 【2026-11-XX改訂・本人指示Q5：52pxプロフィール詳細モーダルでのバッジスケーリング】
     --badge-scaleは既定で1（＝このファイルの元々の44px基準サイズ）。個別のpx指定を
     サイズごとに増やすのではなく、アイコンを囲む.fan-profile-swatch側で
     --badge-scaleだけを設定すれば、下の.oshi-badge--medal/crown/diamondが
     calc()で自動的に比例スケールする設計にした。22px版（.fan-profile-swatch--sm）は
     既存の手動調整済み固定pxのままこのルールを上書きするため、この変更による
     見た目の変化は無い（詳細はそちらのコメント参照）。 */
  border: calc(1.5px * var(--badge-scale, 1)) solid #ffffff;
  border-radius: 50%;
  pointer-events: none;
}

/* 【2026-11-XX追加・本人指示：実装方式の最終確認】絵文字（OSフォント依存）をやめ、
   js/achievementIcons.jsと同じ「currentColorで塗るSVGパス」方式にしたことに伴う
   サイズ指定。svgをバッジ円より一回り小さくして余白を作り、視認性を保つ。 */
.oshi-badge svg {
  width: 62%;
  height: 62%;
}

/* イントロマスター（メダル）：3つの中で最も控えめな銀灰色・最小サイズ（本人指示の豪華さの
   順：イントロマスター＜＝LOVEマスター＜＜＝LOVE完全制覇、を大きさと配色で表現）。 */
.oshi-badge--medal {
  bottom: calc(-4px * var(--badge-scale, 1));
  left: calc(-5px * var(--badge-scale, 1));
  width: calc(16px * var(--badge-scale, 1));
  height: calc(16px * var(--badge-scale, 1));
  color: #5c5460;
  background: radial-gradient(circle at 32% 28%, #f4f1f6 0%, #b9aebd 70%);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

/* ＝LOVEマスター（王冠）：金色・中間の豪華さ。 */
.oshi-badge--crown {
  bottom: calc(-6px * var(--badge-scale, 1));
  right: calc(-6px * var(--badge-scale, 1));
  width: calc(19px * var(--badge-scale, 1));
  height: calc(19px * var(--badge-scale, 1));
  color: #5c3a08;
  background: radial-gradient(circle at 32% 28%, #ffe9a8 0%, #e3ab3c 70%);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
}

/* ＝LOVE完全制覇（ダイヤ）：3つの中で最も目立つ位置（右上）・最大サイズ・最も強い発光で、
   「小さく表示されても完全制覇だと分かる」豪華さを表現する（本人指示）。 */
.oshi-badge--diamond {
  top: calc(-7px * var(--badge-scale, 1));
  right: calc(-6px * var(--badge-scale, 1));
  width: calc(21px * var(--badge-scale, 1));
  height: calc(21px * var(--badge-scale, 1));
  color: #ffffff;
  background: radial-gradient(circle at 32% 26%, #f3e8ff 0%, #b18cf0 45%, #6fa8ff 100%);
  box-shadow: 0 0 0 2px rgba(177, 140, 240, 0.35), 0 3px 6px -1px rgba(74, 46, 66, 0.4);
}

/* ===== みんなのプロフィール（js/fanProfilesScreen.js、2026-08-07新設） =====
   このアプリを使っているファン同士で、表示名・推し・称号を見せ合える一覧画面。
   対戦・ランキングではないため、派手な演出やスコア表示は使わず、白・ピンク・パステルの
   既存トーンに合わせた落ち着いたカードにする（本人指示）。 */

/* 「🏅称号一覧」ボタン（2026-08-29改訂・本人指示）：フレンド1人ずつの詳細モーダルからは
   削除し、フレンドページ自体のヘッダー右側へ移動した。.list-headerは
   grid-template-columns: 1fr auto 1fr（左＝戻る、中央＝タイトル）なので、3列目
   （今まで空いていた右側の1fr）にこのボタンを置くだけで、戻る・タイトルの位置関係を
   崩さずに済む（#continuous-play-screenの設定アイコンボタンと同じ考え方）。 */
#fan-profiles-screen .list-header {
  align-items: center;
}

.fan-profiles-title-list-button {
  grid-column: 3;
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 7px 12px;
  border-radius: 999px;
  border: 1.5px solid var(--color-primary);
  background: var(--color-surface);
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 800;
  white-space: nowrap;
  cursor: pointer;
}

.fan-profiles-title-list-button:active {
  transform: scale(0.96);
  background: var(--color-primary);
  color: #ffffff;
}

.fan-profiles-settings-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  margin-bottom: 14px;
  border-radius: 16px;
  background: linear-gradient(165deg, #ffffff, var(--color-primary-light) 220%);
  border: 1px solid rgba(255, 111, 168, 0.3);
}

.fan-profiles-settings-text {
  flex: 1;
  min-width: 0;
}

.fan-profiles-settings-title {
  margin: 0 0 2px;
  font-size: 0.88rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.fan-profiles-settings-description {
  margin: 0;
  font-size: 0.72rem;
  line-height: 1.5;
  opacity: 0.8;
}

.fan-profiles-loading,
.fan-profiles-empty {
  padding: 24px 16px;
  text-align: center;
  font-size: 0.82rem;
  line-height: 1.6;
  opacity: 0.75;
}

/* 「🆔 あなたのID」表示（2026-08-16追加）。目立たせすぎず、必要な人だけが参照する
   補助情報という位置づけにするため、小さく控えめなテキストにする。 */
/* クイズランキングの後追い同期状況（2026-08-16新設）。設定カードとIDの間に、
   控えめな1行として表示する（本人指示：大げさなモーダルは不要）。 */
.fan-profiles-ranking-sync-status {
  margin: -6px 0 12px;
  padding: 6px 12px;
  border-radius: 10px;
  background: var(--color-primary-light);
  text-align: center;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.fan-profiles-my-id {
  margin: 0 0 14px;
  font-size: 0.7rem;
  line-height: 1.5;
  opacity: 0.6;
  word-break: break-all;
}

.fan-profiles-my-id code {
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 0.68rem;
}

/* 管理者専用「🔧バックアップ管理」入口ボタン（2026-08-29新設）。
   通常は非表示（hidden）で、管理者判定がtrueのときだけjs/fanProfilesScreen.jsが表示する。 */
.admin-backup-link-button {
  width: 100%;
  margin-bottom: 14px;
}

/* バックアップ管理画面（#admin-backup-screen）の見出し・一覧まわり（2026-08-29新設）。
   既存の.history-empty-state・.lyrics-import-section等と統一感のある、
   控えめなカード行の並びにする。 */
.admin-backup-section-title {
  margin: 20px 0 8px;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.85;
}

.admin-backup-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.admin-backup-row {
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--color-surface);
  border: 1px solid color-mix(in srgb, var(--color-primary) 16%, transparent);
}

.admin-backup-row-title {
  margin: 0 0 4px;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-text);
}

.admin-backup-row-detail {
  margin: 0 0 2px;
  font-size: 0.72rem;
  color: var(--color-text);
  opacity: 0.75;
  word-break: break-all;
}

/* 【2026-09-23新設・本人指示：新規プレイのたびに第1問だけ無音になる問題の再調査】
   音源診断ログ画面の記録表示欄。等幅フォント・折り返し無しの横スクロールで、
   時刻の桁がずれずに読めるようにする（本人指示のコピー先での可読性を優先）。 */
.debug-audio-log-textarea {
  width: 100%;
  box-sizing: border-box;
  margin-top: 10px;
  padding: 10px;
  border-radius: 10px;
  border: 1px solid var(--color-card-border);
  background: var(--color-surface);
  color: var(--color-text);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.68rem;
  line-height: 1.5;
  white-space: pre;
  overflow-x: auto;
  resize: vertical;
}

.admin-backup-select {
  display: block;
  width: 100%;
  margin: 8px 0;
  padding: 8px 10px;
  border-radius: 10px;
  border: 1.5px solid color-mix(in srgb, var(--color-primary) 30%, transparent);
  font-size: 0.78rem;
  font-family: inherit;
  background: var(--color-surface);
  color: var(--color-text);
}

.admin-backup-resolve-result {
  margin-top: 6px;
}

/* 【2026-09-04新設、緊急対応】backupsに該当が無い場合の、公開プロフィールからの
   称号だけ復元セクション。誤操作を招かないよう、通常の紐付け操作とは視覚的に
   区切っている（点線区切り＋控えめな余白）。 */
.admin-backup-fallback-section {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px dashed color-mix(in srgb, var(--color-primary) 25%, transparent);
}

.admin-backup-fallback-search-row {
  display: flex;
  gap: 8px;
  margin: 6px 0;
}

.admin-backup-fallback-search-row input {
  flex: 1;
  min-width: 0;
}

/* 管理者用「UID移行・重複修復」（2026-09-22追加）。候補カード：実行不可は赤枠、完了は薄く */
.admin-uid-repair-section {
  margin: 12px 0 18px;
}
.admin-uid-repair-card {
  border: 1px solid rgba(120, 100, 130, 0.25);
  border-radius: 14px;
  padding: 12px;
  margin: 10px 0;
  background: rgba(255, 255, 255, 0.55);
}
.admin-uid-repair-card.is-blocked {
  border-color: rgba(192, 57, 43, 0.6);
}
.admin-uid-repair-card.is-done {
  opacity: 0.6;
}
.admin-uid-repair-subtitle {
  margin-top: 8px;
  font-weight: 700;
}
.admin-uid-repair-evidence {
  color: #1b7a3d;
}
.admin-uid-repair-risk,
.admin-uid-repair-log-error {
  color: #c0392b;
  font-weight: 700;
}
.admin-uid-repair-log-ok {
  color: #1b7a3d;
}
.admin-uid-repair-log-warn {
  color: #b7791f;
}
.admin-uid-repair-confirm-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 10px;
}
.admin-uid-repair-report {
  margin-top: 12px;
}
.admin-uid-repair-report-text {
  width: 100%;
  box-sizing: border-box;
  margin-top: 8px;
  font-size: 0.7rem;
  font-family: ui-monospace, Menlo, Consolas, monospace;
  white-space: pre-wrap;
  word-break: break-all;
  overflow: auto;
}
.admin-uid-repair-log {
  margin-top: 8px;
  padding: 8px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.04);
  max-height: 260px;
  overflow: auto;
}

.admin-backup-fallback-match-row {
  padding: 8px 10px;
  margin-top: 6px;
  border-radius: 10px;
  background: var(--color-primary-light);
}

/* 復旧依頼の削除ボタン（2026-08-29追加）。危険な操作用の既存クラス.danger-buttonを
   そのまま使い、赤系の配色にする。
   【2026-09-05改訂】以前はバックアップ本体の削除機能を意図的に用意していなかったが、
   オンライン対戦の負荷テストで作った大量のダミーバックアップを整理する必要が生じたため、
   本人指示によりバックアップ本体を削除するボタンにもこの同じクラスを流用することにした
   （js/adminBackupScreen.jsのbuildBackupRow()参照。削除前に必ずwindow.confirm()で
   内容を見せ、1件ずつしか削除できないようにすることで誤操作のリスクを抑えている）。 */
.admin-backup-delete-request-button {
  margin-top: 8px;
  display: block;
  width: 100%;
}

/* 【2026-11-XX追加・本人指示：[hidden]系CSSの全面監査で発見】.breakdown-chip-rowと
   同じ原因のため、同じ対策を追加。 */
.admin-backup-delete-request-button[hidden] {
  display: none;
}

/* バックアップ一覧で「名前未設定＝テストデータの可能性が高い」ことを示す注意書き。
   断定ではなく目安であることが伝わるよう、警告色だが控えめな太さにする。 */
.admin-backup-suspicious-note {
  color: #c0392b;
  font-weight: 600;
  opacity: 1;
}

/* 【2026-09-05新設】バックアップ一覧の「表示中を全て選択」「選択解除」ボタンを
   横並びにする。件数が多いときに1件ずつ削除するのが大変という本人指示への対応
   （複数選択→まとめて削除、js/adminBackupScreen.js参照）。 */
.admin-backup-bulk-actions {
  display: flex;
  gap: 8px;
  margin-bottom: 6px;
}

.admin-backup-bulk-actions .secondary-button {
  flex: 1;
}

.admin-backup-row-select-toggle {
  margin-bottom: 8px;
}

/* データ管理画面の「データを復旧する」（2026-08-29新設）。復旧依頼番号を大きく・
   読み上げやすい間隔で表示し、電話やLINEで他人に伝える数字であることが一目で伝わるようにする。 */
.data-recovery-code-panel {
  margin-top: 12px;
  padding: 14px;
  border-radius: 14px;
  background: var(--color-surface);
  border: 1px solid color-mix(in srgb, var(--color-primary) 16%, transparent);
  text-align: center;
}

.data-recovery-code-display {
  margin: 6px 0 12px;
  font-size: 2rem;
  font-weight: 800;
  letter-spacing: 0.25em;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
}

/* 機種変更・データ引き継ぎ（2026-08-29新設）。① 発行する方／② 入力する方を
   見た目でもはっきり2つに分けるための小見出し・区切り。 */
.device-transfer-subsection {
  margin-bottom: 16px;
  padding-bottom: 16px;
  border-bottom: 1px dashed color-mix(in srgb, var(--color-primary) 20%, transparent);
}

.device-transfer-subsection:last-child {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: none;
}

.device-transfer-subsection-title {
  margin: 0 0 6px;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

/* 引き継ぎコードは6桁の数字ではなく長い英数字のため、.data-recovery-code-displayの
   大きな文字サイズのままだとはみ出す。ここだけ小さめの等幅寄りの表示に上書きする。 */
.device-transfer-code-display {
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  word-break: break-all;
  font-family: "SFMono-Regular", Consolas, monospace;
}

.device-transfer-warning {
  color: var(--color-danger);
  font-weight: 700;
}

.device-transfer-code-input {
  display: block;
  width: 100%;
  margin: 8px 0;
  padding: 10px;
  border-radius: 10px;
  border: 1.5px solid color-mix(in srgb, var(--color-primary) 30%, transparent);
  /* 【2026-09-06修正、本人指示：実機フィードバック】16px未満だとiOS Safariが
     フォーカス時に自動ズームしてしまうため16pxへ引き上げた。 */
  font-size: 16px;
  font-family: "SFMono-Regular", Consolas, monospace;
  background: var(--color-surface);
  color: var(--color-text);
  resize: vertical;
}

/* 管理者専用の削除ボタン付きカード行（2026-08-16追加）。button要素の中にbutton要素は
   置けないため、削除ボタンがあるときだけカード本体をこの行でラップして横に並べる。 */
.fan-profile-card-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.fan-profile-card-row .fan-profile-card {
  margin-bottom: 0;
}

.fan-profile-admin-delete-button {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid rgba(220, 53, 69, 0.35);
  background: rgba(220, 53, 69, 0.08);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
}

.fan-profile-admin-delete-button:active {
  transform: scale(0.95);
}

/* 【2026-11-XX新設・本人指示：「一緒に遊ぶ」】カードの下にもう1段「一緒に遊ぶ」ボタンを
   足すためのラッパー。.fan-profile-card-row（管理者削除ボタンとの横並び行）とは独立した
   概念のため、削除ボタンの有無に関わらずこの縦積みコンテナで包む
   （js/fanProfileCard.jsのbuildProfileCard()参照）。 */
.fan-profile-card-wrap {
  margin-bottom: 10px;
}

.fan-profile-card-wrap .fan-profile-card,
.fan-profile-card-wrap .fan-profile-card-row {
  margin-bottom: 6px;
}

.fan-profile-play-invite-row {
  display: flex;
  justify-content: flex-end;
}

.fan-profile-play-invite-button {
  padding: 6px 16px;
  font-size: 0.8rem;
}

.fan-profile-play-invite-button:disabled {
  opacity: 0.55;
  cursor: default;
}

/* 【2026-09-05新設・本人指示：実機フィードバックによる改善】既に同じオンライン
   ルームにいるフレンドの状態表示。ボタンではなく、既存のオンライン状態チップ
   （.fan-profile-card-presence等）と同じ「短い文字だけ」の見せ方に揃える。 */
.fan-profile-play-invite-same-room-status {
  padding: 6px 4px;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.65;
}

.fan-profile-card {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 14px;
  margin-bottom: 10px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.55);
  border: 1px solid var(--color-card-border);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.fan-profile-card:active {
  transform: scale(0.99);
}

.fan-profile-swatch {
  position: relative;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  color: #fff;
  box-shadow: 0 4px 10px -4px rgba(0, 0, 0, 0.3), inset 0 -3px 6px rgba(0, 0, 0, 0.1);
}

.fan-profile-swatch.is-placeholder {
  background: linear-gradient(145deg, #e8dde3, #d8c8d2);
}

/* 【2026-09-26新設・本人指示：オンライン対戦総合改修19-8章】ロビー一覧・スコア表示・
   結果画面など、名前の隣に小さく並べる用途向けの縮小版。王冠・ダイヤ・メダルの特別バッジ
   （.oshi-badge等、js/oshiBadge.js）は44px基準のサイズのままだと22pxの丸に対して大きすぎる
   ため、この修飾クラスの中でだけ縮小する（js/onlineParticipantIcon.jsのbuildParticipantIcon()
   が付与する）。 */
.fan-profile-swatch--sm {
  width: 22px;
  height: 22px;
  box-shadow: none;
}

/* 【2026-11-XX改訂・本人指示：3個同時表示】ロビー一覧・スコア表示等の縮小アイコン
   （22px基準）向けに、.oshi-badge 3種すべてを比例縮小する。3個同時でも角が重ならないよう、
   フルサイズ版と同じ3隅（右上＝ダイヤ・右下＝王冠・左下＝メダル）の配置は維持する。 */
.fan-profile-swatch--sm .oshi-badge--medal {
  width: 9px;
  height: 9px;
  bottom: -2px;
  left: -3px;
  border-width: 1px;
}

.fan-profile-swatch--sm .oshi-badge--crown {
  width: 10px;
  height: 10px;
  bottom: -3px;
  right: -3px;
  border-width: 1px;
}

.fan-profile-swatch--sm .oshi-badge--diamond {
  width: 11px;
  height: 11px;
  top: -3px;
  right: -3px;
  border-width: 1px;
}

.fan-profile-card-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.fan-profile-card-name {
  font-size: 0.92rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  line-height: 1.3;
  overflow-wrap: break-word; /* 長い表示名も省略せず2行まで折り返す（称号名と同じ方針） */
}

/* 【2026-11-XX新設・本人指示：フレンドのオンライン状態】表示名の隣に、一目で分かる
   オンライン/最終ログイン表示を添える。既存の名前の見た目・行間は変えない。 */
.fan-profile-card-name-row {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.fan-profile-card-presence {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-text-soft, #8a8a99);
  white-space: nowrap;
}

.fan-profile-card-presence.is-online {
  color: var(--color-primary-dark);
}

.fan-profile-card-oshi,
.fan-profile-card-meta {
  font-size: 0.76rem;
  line-height: 1.4;
  opacity: 0.8;
}

.fan-profile-card-chevron {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--color-primary);
  opacity: 0.6;
}

/* 375px幅ではプロフィールカードは1列（本人指示に基づき、名前・推し・称号の3行を
   ゆったり読めるよう、特別モードの2列カードとは違い常に横に長い1行カードにする）。 */

.fan-profile-detail-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 4px 0 14px;
  /* 右上の×ボタン（44px幅・right:6px）と重ならないよう、この行だけ右側に余白を
     確保しておく（2026-08-29追加、本人指示：「🏅称号一覧」ボタンをこの行に置くため）。 */
  padding-right: 52px;
}

.fan-profile-detail-swatch {
  flex: none;
}

.fan-profile-detail-swatch .fan-profile-swatch {
  width: 52px;
  height: 52px;
  /* 【2026-11-XX追加・本人指示Q5】アイコン本体は52px（44px基準の約1.18倍）だが、
     以前は特別バッジ（.oshi-badge、上記参照）が44px基準の絶対pxのままだったため、
     52pxアイコンに対して相対的に小さく見えていた。個別のpxを増やすのではなく、
     --badge-scaleを1つ設定するだけで.oshi-badge側のcalc()が自動的に比例スケールする。
     アイコン本体（このルール自身のwidth/height）には触れていないため、
     「推しアイコン本体は縮小しない」という既存方針とも矛盾しない。 */
  --badge-scale: 1.1818;
}

/* 名前・推しのテキスト部分（2026-08-29追加）。flex:1にして「🏅称号一覧」ボタンぶんの
   幅を確実に空け、表示名が長くても折り返してボタンに重ならないようにする。 */
.fan-profile-detail-header-text {
  flex: 1;
  min-width: 0;
}

/* プレイヤー名の右側に置く、ゲーム全体の称号一覧を開くボタン（2026-08-29追加、本人指示）。
   フレンドページヘッダーの.fan-profiles-title-list-buttonと同じ見た目・同じ役割
   （このプレイヤー個人のデータは一切使わず、既存の称号一覧モーダルを開くだけ）。 */
.fan-profile-detail-title-list-button {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 6px 10px;
  border-radius: 999px;
  border: 1.5px solid var(--color-primary);
  background: var(--color-surface);
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.66rem;
  font-weight: 800;
  white-space: nowrap;
  cursor: pointer;
}

.fan-profile-detail-title-list-button:active {
  transform: scale(0.96);
  background: var(--color-primary);
  color: #ffffff;
}

.fan-profile-detail-oshi {
  margin: 2px 0 0;
  font-size: 0.8rem;
  opacity: 0.75;
}

/* ===== フレンドプロフィールの「代表称号」（2026-08-29新設・本人指示の再設計） =====
   ランキング順位は使わず、称号の総数・ランク感・代表称号（最大3個）だけで実力が
   一目で伝わるようにする。中身の組み立てはjs/fanProfileCard.jsが担当し、ここでは
   見た目だけを整える。 */
/* 【2026-10-29追加】フレンドのデータの曲数（音源・歌詞・コール）。称号の数の上に1行で */
.fan-profile-detail-data-status {
  margin: 0 0 10px;
  padding: 8px 12px;
  border-radius: 12px;
  background: rgba(111, 189, 242, 0.14);
  text-align: left;
}

.fan-profile-detail-data-status-text {
  margin: 0;
  font-size: 0.84rem;
  font-weight: 800;
  line-height: 1.5;
  color: var(--color-text);
}

.fan-profile-detail-data-status-text.is-empty {
  font-weight: 700;
  opacity: 0.75;
}

.fan-profile-detail-data-status-detail {
  margin: 2px 0 0;
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--color-text);
  opacity: 0.8;
}

.fan-profile-detail-data-status-detail[hidden] {
  display: none;
}

.fan-profile-detail-achievement-count {
  margin: 0 0 10px;
  font-size: 0.92rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.fan-profile-achievement-summary {
  margin-bottom: 12px;
}

/* ランク感ラベル：これから挑戦／CHALLENGER／代表称号（本人指示：称号の獲得状況によって
   プロフィールの見せ方を変え、初心者のプロフィールが寂しく見えすぎないようにする）。 */
.fan-profile-rank-label {
  display: inline-flex;
  align-items: center;
  margin: 0 0 10px;
  padding: 4px 13px;
  border-radius: 999px;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.08em;
}

.fan-profile-rank-label.is-empty {
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  color: var(--color-text);
  opacity: 0.75;
}

.fan-profile-rank-label.is-challenger {
  background: var(--color-secondary-light);
  color: #14507a;
}

.fan-profile-rank-label.is-representative {
  background: linear-gradient(120deg, var(--color-accent-soft), var(--color-accent));
  color: #5c3a08;
}

.fan-profile-rank-empty-hint {
  margin: 2px 0 0;
  font-size: 0.82rem;
  opacity: 0.75;
}

.fan-profile-rank-empty-hint:first-of-type {
  margin-top: 0;
}

.fan-profile-representative-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.fan-profile-representative-chip {
  padding: 10px 12px;
  border-radius: 14px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
}

/* マスター系・裏チャレンジ系だけ、代表チップ自体もひと目で分かるよう色味を強める
   （本人指示：「上級者は強い称号がしっかり目立つ」）。裏チャレンジ系のほうがさらに濃い
   トーンにし、優先順位（裏チャレンジ＞マスター）が見た目にも伝わるようにする。 */
.fan-profile-representative-chip:has(.fan-profile-representative-tag--masterPath) {
  background: linear-gradient(120deg, rgba(255, 217, 61, 0.16), rgba(255, 217, 61, 0.32));
  border-color: rgba(184, 121, 14, 0.35);
}

.fan-profile-representative-chip:has(.fan-profile-representative-tag--backChallenge) {
  background: linear-gradient(120deg, rgba(255, 79, 150, 0.14), rgba(255, 111, 168, 0.28));
  border-color: rgba(255, 79, 150, 0.4);
}

.fan-profile-representative-tag {
  display: inline-block;
  margin: 0 0 6px;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.04em;
}

.fan-profile-representative-tag--masterPath {
  background: var(--color-accent);
  color: #5c3a08;
}

.fan-profile-representative-tag--backChallenge {
  background: var(--color-primary-dark);
  color: #ffffff;
}

.fan-profile-representative-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.fan-profile-representative-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.fan-profile-representative-name {
  margin: 0;
  font-size: 0.88rem;
  font-weight: 800;
  line-height: 1.3;
  color: var(--color-primary-dark);
  overflow-wrap: break-word;
}

.fan-profile-representative-condition {
  margin: 0;
  font-size: 0.74rem;
  line-height: 1.35;
  opacity: 0.75;
  overflow-wrap: break-word;
}

/* 「次のチャレンジ」案内カード（2026-08-29追加・本人指示）：3系統（イントロ／ランダム再生／
   歌詞クイズ）のうち称号0個の系統があるときだけ表示する、控えめな案内。代表称号（ピンク・
   ゴールド系）とは違う水色系にして、主役の代表称号より目立たせすぎない。 */
.fan-profile-next-challenge {
  margin-top: 8px;
  padding: 9px 12px;
  border-radius: 12px;
  background: var(--color-secondary-light);
  border: 1px solid rgba(111, 189, 242, 0.4);
}

.fan-profile-next-challenge-title {
  margin: 0 0 2px;
  font-size: 0.72rem;
  font-weight: 800;
  color: #14507a;
}

.fan-profile-next-challenge-text {
  margin: 0;
  font-size: 0.76rem;
  line-height: 1.4;
  color: #14507a;
  opacity: 0.85;
  overflow-wrap: break-word;
}

/* 「すべての称号を見る」：代表称号には出ない、この人が取得済みの称号を全部確認できる導線
   （本人指示：右上の「🏅称号一覧」＝ゲーム全体の称号・条件を見る、とは役割が違うので
   混同しない）。押すたびに開閉するアコーディオン方式で、新しいモーダルは作らない。 */
.fan-profile-detail-all-toggle {
  display: block;
  width: 100%;
  margin: 2px 0 12px;
  padding: 10px;
  border-radius: 999px;
  border: 1.5px solid var(--color-card-border);
  background: var(--color-surface);
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 700;
  text-align: center;
  cursor: pointer;
}

.fan-profile-detail-all-toggle:active {
  transform: scale(0.97);
  border-color: var(--color-primary);
}

/* 【2026-11-XX追加・本人指示：[hidden]系CSSの全面監査で発見】.breakdown-chip-rowと
   同じ原因のため、同じ対策を追加（称号を1つも持たないフレンドの詳細を開くと、
   本来非表示のはずの「すべての称号を見る」ボタンが常に見えてしまっていた）。 */
.fan-profile-detail-all-toggle[hidden] {
  display: none;
}

.fan-profile-detail-all-achievements {
  padding-top: 4px;
  border-top: 1px solid var(--color-card-border);
}

/* 「すべての称号を見る」の系統ごとのブロック（2026-08-29追加）。 */
.fan-profile-achievement-block {
  margin-bottom: 14px;
}

.fan-profile-achievement-block-heading {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 8px;
  font-size: 0.78rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.fan-profile-achievement-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 10px;
}

.fan-profile-achievement-card {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid var(--color-card-border);
}

.fan-profile-achievement-name {
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--color-primary-dark);
  overflow-wrap: break-word;
}

.fan-profile-achievement-empty {
  padding: 12px 4px;
  font-size: 0.8rem;
  opacity: 0.75;
}

/* ＝LOVEマスター／＝LOVE完全制覇専用の特別カード（2026-08-29追加、本人指示：
   「明らかに特別な称号と分かる専用デザインに」）。既存の称号一覧モーダル
   （.achievement-card--composite、js/achievementList.js）と同じ配色・発光アニメーションを
   そのまま再利用し、ゲーム全体でこの2称号の見た目に一貫性を持たせる（新しい色は作らない）。
   通常称号の2列グリッドには入れず、常に横幅いっぱいの単独カードにする。 */
.fan-profile-special-achievement-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px;
  border-radius: 18px;
  border: 1.5px solid transparent;
}

.fan-profile-special-achievement-card .achievement-icon-medal {
  width: 44px;
  height: 44px;
  flex: none;
}

/* ＝LOVEマスター＝表攻略の最終到達点：金・王冠系の柔らかい発光
   （achievementMasterCardGlowはjs/achievementList.js側のカードと共通のkeyframes）。 */
.fan-profile-special-achievement-card--equal_love_master {
  background: linear-gradient(155deg, #fff7e0, #ffe3f0 55%, #ffd9a0 100%);
  border-color: rgba(255, 200, 60, 0.7);
  box-shadow: 0 10px 24px -14px rgba(184, 121, 14, 0.5);
  animation: achievementMasterCardGlow 2.6s ease-in-out infinite;
}

/* ＝LOVE完全制覇＝裏攻略の最終到達点：紫〜水色のオーラ系の発光を、＝LOVEマスターより
   ひと回り強めにして格の違いを出す（achievementCompleteCardGlowも同じく共通keyframes）。 */
.fan-profile-special-achievement-card--equal_love_complete {
  background: linear-gradient(155deg, #ffe9f4, #e8e0ff 55%, #d3ecff 100%);
  border-color: rgba(150, 130, 255, 0.55);
  box-shadow: 0 10px 26px -12px rgba(140, 130, 255, 0.5);
  animation: achievementCompleteCardGlow 2.2s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .fan-profile-special-achievement-card {
    animation: none;
  }
}

.fan-profile-special-achievement-text {
  flex: 1;
  min-width: 0;
}

.fan-profile-special-achievement-name {
  margin: 0;
  font-size: 1.02rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  overflow-wrap: break-word;
}

.fan-profile-special-achievement-tagline {
  margin: 2px 0 0;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  color: #7a4a20;
  opacity: 0.85;
}

.fan-profile-special-achievement-condition {
  margin: 4px 0 0;
  font-size: 0.78rem;
  line-height: 1.4;
  opacity: 0.8;
  overflow-wrap: break-word;
}

@media (max-width: 380px) {
  .fan-profile-achievement-grid {
    grid-template-columns: 1fr;
  }
}

.player-hero-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
}

.player-hero-name {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: inherit;
  font-size: 1rem;
  font-weight: 800;
  color: var(--color-text);
  background: transparent;
  border: none;
  padding: 2px 0;
  cursor: pointer;
  max-width: 100%;
}

.player-hero-name span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.player-hero-edit-icon {
  flex: none;
  width: 13px;
  height: 13px;
  color: var(--color-primary-dark);
  opacity: 0.6;
}

.player-hero-oshi {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  text-align: left;
}

.player-hero-oshi-arrow {
  display: none;
  font-size: 0.78rem;
  transition: transform 0.15s ease;
}

/* 推し未登録のときは、押せば設定できることが一目で伝わるよう、はっきりした
   ボタン（ピル型・塗り背景・矢印つき）にする（2026-08-04追加）。 */
.player-hero-oshi.is-empty {
  color: #fff;
  background: linear-gradient(120deg, var(--color-primary), #ff2f7e);
  padding: 6px 14px;
  border-radius: 999px;
  box-shadow: 0 4px 10px -4px rgba(255, 47, 126, 0.6);
}

.player-hero-oshi.is-empty .player-hero-oshi-arrow {
  display: inline-block;
}

.player-hero-oshi.is-empty:active .player-hero-oshi-arrow {
  transform: translateX(2px);
}

.player-hero-card:active,
.player-hero-name:active,
.player-hero-oshi:active {
  transform: scale(0.98);
}

/* プレイヤー管理モーダルの一覧 */
.player-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 14px 0;
  max-height: 40vh;
  overflow-y: auto;
}

.player-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 14px;
  background: var(--color-surface);
  transition: border-color 0.15s ease, background 0.15s ease;
}

.player-row.is-active {
  border-color: var(--color-primary);
  background: var(--color-primary-light);
}

.player-row-avatar {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: linear-gradient(145deg, var(--color-primary), var(--color-primary-dark));
  color: #fff;
  font-size: 0.78rem;
  font-weight: 800;
}

.player-row-switch-button {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  text-align: left;
  font-family: inherit;
  background: transparent;
  border: none;
  padding: 4px;
  cursor: pointer;
  min-width: 0;
}

.player-row-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.84rem;
  font-weight: 700;
  color: var(--color-text);
}

.player-row-active-tag {
  flex: none;
  font-size: 0.62rem;
  font-weight: 800;
  color: #fff;
  background: #d3286c; /* 【2026-10-30】白い文字が読めるように（淡いピンク #ff6fa8 では 約2.6:1 → 約4.9:1） */
  padding: 2px 8px;
  border-radius: 999px;
}

.player-row-rename-input {
  /* flex:1だけだとinput要素は縮まず（初期値min-width:autoのため）、横幅の狭いスマホ画面で
     隣の✓保存ボタンが右側にはみ出して見えなくなる・押せなくなる不具合があったため、
     min-width:0を明示して必ず縮められるようにする（2026-08-04、実機での不具合報告により追加）。 */
  flex: 1;
  min-width: 0;
  font-family: inherit;
  font-size: 0.82rem;
  padding: 6px 10px;
  border: 1.5px solid var(--color-primary);
  border-radius: 10px;
}

.player-row-icon-button {
  position: relative;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  font-size: 0.85rem;
  line-height: 1;
  color: var(--color-primary-dark);
  background: rgba(255, 111, 168, 0.1);
  border: none;
  border-radius: 50%;
  cursor: pointer;
}

/* 見た目の丸はそのままに、タップ判定だけを一回り広げる（.modal-close-button::afterと同じ手法）。
   ボタン同士は8pxの間隔があるため、片側4pxずつ広げても隣とぶつからない（2026-08-04追加）。 */
.player-row-icon-button::after {
  content: "";
  position: absolute;
  inset: -4px;
}

.player-row-icon-button:active {
  transform: scale(0.92);
}

.player-row-icon-button.is-save {
  color: #fff;
  background: var(--color-primary);
}

.player-row-icon-button.is-delete {
  color: #c94b4b;
  background: rgba(201, 75, 75, 0.1);
}

/* 【2026-10-29改訂・本人の iPad での報告】「どこで入力して、何がOKなのか分からない」。
   「使う人を選ぶ」と「＋ 新しいプレイヤーを追加」を区画に分け、見出し・説明・名前の欄・幅のある登録ボタン・
   理由（エラー）／結果の表示を縦に並べる。登録ボタンは .primary-button（幅いっぱい）を使う。 */
.player-modal-section {
  margin-top: 14px;
  text-align: left;
}

.modal-card .player-modal-section-title {
  margin: 0 0 2px;
  font-size: 0.92rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.player-modal-section-lead {
  margin: 0;
  font-size: 0.74rem;
  line-height: 1.55;
  color: var(--color-text);
  opacity: 0.8;
}

.player-modal-section .player-list {
  margin: 10px 0 0;
}

/* 白い枠（--color-card-border）は白いモーダルの上では見えず、使用中でない人が「押せる行」に見えなかった */
.player-modal-section .player-row {
  border-color: rgba(74, 46, 66, 0.18);
}

.player-modal-section .player-row.is-active {
  border-color: var(--color-primary);
}

.player-unnamed-note {
  margin: 8px 0 0;
  padding: 8px 10px;
  border-radius: 12px;
  background: var(--color-accent-soft);
  font-size: 0.76rem;
  font-weight: 700;
  line-height: 1.55;
  color: var(--color-text);
}

.player-unnamed-note[hidden] {
  display: none;
}

.player-add-section {
  margin-top: 16px;
  padding: 12px;
  border-radius: 16px;
  background: rgba(255, 111, 168, 0.07);
  border: 1.5px dashed rgba(255, 79, 150, 0.4);
}

.player-add-label {
  display: block;
  margin: 10px 0 4px;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--color-text);
}

.player-add-input {
  display: block;
  box-sizing: border-box;
  width: 100%;
  min-width: 0;
  font-family: inherit;
  /* 16px 未満だと iPhone の Safari が入力のたびに画面を拡大してしまうため 1rem にする */
  font-size: 1rem;
  padding: 11px 14px;
  border: 2px solid rgba(74, 46, 66, 0.28);
  border-radius: 12px;
  background: var(--color-surface);
  color: var(--color-text);
}

.player-add-input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(255, 111, 168, 0.25);
}

.player-add-input.is-invalid {
  border-color: #c0392b;
}

.player-add-input:disabled {
  opacity: 0.7;
}

/* 理由（エラー）と結果を、欄のすぐ下に出す。色だけに頼らず、文の先頭にも ✓ ／ 理由を書く */
.player-add-message {
  margin: 6px 0 0;
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1.5;
}

.player-add-message[hidden] {
  display: none;
}

.player-add-message.is-error {
  color: #b3261e;
}

.player-add-message.is-success {
  color: #1e7b45;
}

.player-add-section .player-add-button {
  margin-top: 10px;
  padding: 12px;
  font-size: 0.95rem;
  /* 【2026-10-30】白い文字が読める濃さのピンク（今までの淡いピンクの所は 約2.6:1 → 約4.7:1 以上） */
  background: linear-gradient(120deg, #c81e63, #d92672);
}

.player-add-section .player-add-button:disabled {
  cursor: default;
  opacity: 1;
  background: #1e7b45; /* 「✓ 登録しました」：白い文字と 約5.3:1（今までの明るい緑は 約3.4:1） */
}

/* 一覧の文字のボタン（✎ 名前を変える・保存・やめる）。丸い記号だけより、押すと何が起きるか分かるようにする */
.player-row-text-button {
  flex: none;
  min-height: 36px;
  padding: 6px 10px;
  font-family: inherit;
  font-size: 0.74rem;
  font-weight: 800;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--color-primary-dark);
  background: rgba(255, 111, 168, 0.12);
  border: none;
  border-radius: 999px;
  cursor: pointer;
}

.player-row-text-button:active {
  transform: scale(0.96);
}

.player-row-text-button.is-save {
  color: #fff;
  background: var(--color-primary-dark);
}

.player-row-text-button.is-cancel {
  color: var(--color-text);
  background: rgba(74, 46, 66, 0.08);
}

.player-row-text-button:disabled {
  opacity: 0.6;
  cursor: default;
}

/* 切り替えられる人の「切り替える」の印（使用中の印とは見た目を分ける） */
.player-row-switch-tag {
  flex: none;
  font-size: 0.62rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  border: 1.5px solid rgba(255, 79, 150, 0.45);
  padding: 1px 7px;
  border-radius: 999px;
}

.player-row-switch-button {
  min-height: 40px;
}

.player-row-wrapper {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.player-row-rename-hint {
  margin: 0 4px;
  font-size: 0.7rem;
  line-height: 1.5;
  color: var(--color-text);
  opacity: 0.8;
}

.player-row.is-renaming .player-row-rename-input {
  font-size: 1rem; /* iPhone の自動拡大を防ぐ */
}

/* スマホの幅では、名前・使用中の印を1段目、「✎ 名前を変える」「×」を2段目にする
   （1段に並べると、390px で「（名前未設定）」が切れ、320px では名前が見えなくなっていた） */
@media (max-width: 480px) {
  .player-modal-section .player-row:not(.is-renaming) {
    flex-wrap: wrap;
    row-gap: 4px;
  }

  .player-modal-section .player-row:not(.is-renaming) .player-row-switch-button {
    flex: 1 1 calc(100% - 40px);
  }

  .player-modal-section .player-row:not(.is-renaming) .player-row-text-button.is-rename {
    margin-left: auto;
  }
}

/* 狭い画面（320px 前後）では、名前の変更中の行を2段にする（欄が潰れて打てなくならないように） */
@media (max-width: 360px) {
  .player-row.is-renaming {
    flex-wrap: wrap;
  }

  .player-row.is-renaming .player-row-rename-input {
    flex-basis: calc(100% - 40px);
  }

  .player-row.is-renaming .player-row-text-button {
    flex: 1;
  }
}

/* 【2026-10-30 夜間の修正】切り替えた行：閉じる前の一瞬「✓ 切り替えました」（緑の印。白文字とのコントラスト 約6:1） */
.player-row.is-just-switched .player-row-active-tag {
  background: #1e6e40;
  animation: player-row-switched-in 0.2s ease-out;
}

@keyframes player-row-switched-in {
  from {
    transform: scale(0.85);
  }
  to {
    transform: scale(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .player-row.is-just-switched .player-row-active-tag {
    animation: none;
  }
}

/* 【2026-10-30 夜間の修正】320px などでモーダルの中を下に動かしても、× が見えたままにする（カードの中で上に貼り付ける）。
   float で右に寄せるので、見出しの位置は今までと同じ（× の分だけ見出しが右で折り返す）。 */
#player-modal .modal-close-button {
  position: sticky;
  top: -20px; /* 貼り付く位置は、カードの上の余白（26px）から 20px 上＝今までの × と同じ（カードの上から 6px） */
  float: right;
  z-index: 3;
  margin: -20px -14px 0 8px;
  box-shadow: 0 2px 8px -2px rgba(74, 46, 66, 0.35);
}

/* 登録・切り替えのあと、閉じたホームの上に短く出す知らせ（js/playerScreen.js の showPlayerToast） */
.player-toast {
  position: fixed;
  left: 50%;
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  z-index: 10000;
  transform: translateX(-50%);
  width: max-content;
  max-width: calc(100vw - 32px);
  padding: 10px 18px;
  border-radius: 14px;
  background: rgba(30, 110, 64, 0.94);
  color: #fff;
  font-size: 0.9rem;
  font-weight: 800;
  line-height: 1.5;
  text-align: center;
  box-shadow: 0 10px 24px -10px rgba(0, 0, 0, 0.5);
  animation: player-toast-in 0.22s ease-out;
}

.player-toast[hidden] {
  display: none;
}

@keyframes player-toast-in {
  from {
    opacity: 0;
    transform: translate(-50%, 8px);
  }
  to {
    opacity: 1;
    transform: translate(-50%, 0);
  }
}

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

/* ===== プレイリスト一覧画面 =====
   プレイヤー管理モーダルの.player-row系と見た目・構造をほぼ揃えているが、
   別画面（モーダルではない）である点と、「タップで詳細へ」という役割の違いがあるため、
   クラス名は独立させている（2026-08-04新設）。 */
.playlist-create-row {
  display: flex;
  gap: 8px;
  margin: 4px 0 16px;
}

.playlist-create-row input {
  flex: 1;
  min-width: 0;
  font-family: inherit;
  font-size: 0.85rem;
  padding: 10px 14px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 999px;
}

.playlist-create-row .secondary-button {
  flex: none;
  white-space: nowrap;
}

/* プレイリストへの曲追加画面：選択数と「追加する」ボタンを上部にまとめて、
   曲一覧が長くてもスクロールせず操作できるようにする（UI/UX再設計で新設）。
   .game-frameはoverflow:hiddenで内部スクロールを持たないため、position:stickyでは
   画面に正しく張り付かないと判断し、常時上部固定にはしていない）。 */
.add-songs-action-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}

.add-songs-selected-count {
  margin: 0;
  font-size: 0.8rem;
  font-weight: 700;
  opacity: 0.75;
  white-space: nowrap;
}

.add-songs-selected-count strong {
  color: var(--color-primary-dark);
  font-size: 0.95rem;
}

#playlist-add-songs-submit-button {
  flex: none;
  width: auto;
  margin-top: 0;
  padding: 10px 18px;
  font-size: 0.82rem;
}

#playlist-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.playlist-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 14px;
  background: var(--color-surface);
}

.playlist-row-open-button {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  text-align: left;
  font-family: inherit;
  background: transparent;
  border: none;
  padding: 4px;
  cursor: pointer;
}

.playlist-row-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--color-text);
}

.playlist-row-count {
  flex: none;
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  opacity: 0.8;
}

.playlist-row-rename-input {
  flex: 1;
  min-width: 0;
  font-family: inherit;
  font-size: 0.85rem;
  padding: 6px 10px;
  border: 1.5px solid var(--color-primary);
  border-radius: 10px;
}

.playlist-row-icon-button {
  position: relative;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  font-size: 0.85rem;
  line-height: 1;
  color: var(--color-primary-dark);
  background: rgba(255, 111, 168, 0.1);
  border: none;
  border-radius: 50%;
  cursor: pointer;
}

.playlist-row-icon-button::after {
  content: "";
  position: absolute;
  inset: -4px;
}

.playlist-row-icon-button:active {
  transform: scale(0.92);
}

.playlist-row-icon-button.is-save {
  color: #fff;
  background: var(--color-primary);
}

.playlist-row-icon-button.is-delete {
  color: #c94b4b;
  background: rgba(201, 75, 75, 0.1);
}

/* プレイリスト詳細画面：「＋曲を追加する」（編集）と「連続再生」（聴く）は役割が違うため、
   間隔を大きく空けて別々の操作だと自然に伝わるようにする（本人フィードバックにより2回調整）。 */
#playlist-detail-screen .total-count-chip {
  margin-bottom: 24px;
}

#playlist-detail-continuous-play-button {
  display: flex;
  width: 100%;
  margin-top: 28px;
}

/* 0曲のときだけ見せる空状態（アイコン・見出し・補足を1つにまとめ、以前あった
   「案内文が2つ同時に出て重なる」不具合を構造的に解消する。本人フィードバック反映）。 */
.playlist-detail-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  margin-top: 28px;
  padding: 22px 16px;
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px dashed var(--color-card-border);
}

.playlist-detail-empty-state[hidden] {
  display: none;
}

.playlist-detail-empty-icon {
  width: 34px;
  height: 34px;
  margin-bottom: 8px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

.playlist-detail-empty-icon svg {
  width: 18px;
  height: 18px;
}

.playlist-detail-empty-heading {
  margin: 0 0 4px;
  font-size: 0.86rem;
  font-weight: 800;
  color: var(--color-text);
}

.playlist-detail-empty-sub {
  margin: 0;
  font-size: 0.74rem;
  opacity: 0.6;
  line-height: 1.6;
}

/* プレイリスト一覧：見出しの下に添える短い1行説明（本人フィードバックで短縮済み）。 */
.playlist-list-intro {
  margin: 0 0 14px;
  padding: 10px 14px;
  border-radius: 14px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1.6;
}

/* ===== 「プレイリストに追加」モーダル ===== */
/* 2026-09-16追加・本人指示：UI一貫性ルール（曲名は常に濃いピンク＋太字）。
   「〇〇をプレイリストに追加」の対象曲名（<strong>）を、他の曲名表示と同じ色に揃えた。 */
#add-to-playlist-song-name {
  color: var(--color-primary-dark);
}

.add-to-playlist-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 14px 0;
  max-height: 40vh;
  overflow-y: auto;
}

.add-to-playlist-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 10px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 14px;
  background: var(--color-surface);
}

/* オンライン対戦：「お気に入りから選ぶ」「プレイリストから選ぶ」の確認モーダル用、
   曲名だけを並べる読み取り専用の一覧（2026-08-28新設）。.add-to-playlist-listと
   同じ「最大高さを決めて内部スクロール」という考え方を踏襲している。 */
.online-battle-song-list-confirm-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 12px 0;
  padding: 0;
  max-height: 40vh;
  overflow-y: auto;
}

.online-battle-song-list-confirm-list li {
  padding: 8px 12px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 12px;
  background: var(--color-surface);
  font-size: 0.84rem;
  font-weight: 700;
  color: var(--color-text);
}

.add-to-playlist-row-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.84rem;
  font-weight: 700;
  color: var(--color-text);
}

.add-to-playlist-row-button {
  flex: none;
  padding: 6px 12px;
  border: 1.5px solid var(--color-primary);
  border-radius: 999px;
  background: transparent;
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.76rem;
  font-weight: 700;
  cursor: pointer;
}

.add-to-playlist-row-button.is-added {
  border-color: var(--color-card-border);
  background: var(--color-surface-glass);
  color: var(--color-text);
  opacity: 0.6;
  cursor: default;
}

.add-to-playlist-new-row {
  display: flex;
  gap: 8px;
  margin-top: 4px;
  padding-top: 14px;
  border-top: 1px dashed var(--color-card-border);
}

.add-to-playlist-new-row input {
  flex: 1;
  min-width: 0;
  font-family: inherit;
  font-size: 0.82rem;
  padding: 9px 12px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 999px;
}

.add-to-playlist-new-row .secondary-button {
  flex: none;
  white-space: nowrap;
}

.know-more-title {
  margin: 0 0 10px;
  text-align: center;
  font-size: 0.85rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.know-more-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.know-more-button {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 14px 8px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.35);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  text-align: center;
  cursor: pointer;
  transition: box-shadow 0.2s ease, transform 0.15s ease, border-color 0.2s ease;
}

/* ステージのスポットライトのような、控えめな放射状グラデーション。カードの役割を
   色でも示す（＝LOVE全体＝ピンク寄り、メンバー個人＝ブルー寄り）。2026-08-03追加 */
.know-more-button::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 30% 15%, rgba(255, 111, 168, 0.22), transparent 65%);
  pointer-events: none;
}

#members-link::before {
  background: radial-gradient(circle at 30% 15%, rgba(111, 189, 242, 0.22), transparent 65%);
}

.know-more-button > * {
  position: relative;
  z-index: 1;
}

/* タイトルを主役にするため、アイコンは小さめに固定する（2026-08-03、本人希望） */
.know-more-icon {
  width: 32px;
  height: 32px;
  flex: none;
  filter: drop-shadow(0 0 4px rgba(255, 111, 168, 0.4));
}

#members-link .know-more-icon {
  filter: drop-shadow(0 0 4px rgba(111, 189, 242, 0.4));
}

.know-more-label {
  font-size: 0.8rem;
}

.know-more-description {
  font-size: 0.66rem;
  font-weight: 400;
  color: var(--color-text);
  opacity: 0.6;
}

.know-more-button:hover {
  border-color: var(--color-primary);
}

#members-link:hover {
  border-color: var(--color-secondary);
}

.know-more-button:active {
  transform: scale(0.96);
  box-shadow: 0 0 0 3px rgba(255, 111, 168, 0.18);
}

#members-link:active {
  box-shadow: 0 0 0 3px rgba(111, 189, 242, 0.18);
}

/* ===== 「曲を聴く」タイルグループ（UI/UX再設計） =====
   以前は収録曲一覧・プレイリスト・連続再生などが、下線付きの小さいテキストリンクとして
   横一列に並んでいるだけで、同じ役割（曲を聴く）でまとまって見えなかった。
   カード1枚の中にタイルとして並べ、視線がひと目でグループとして認識できるようにする。 */
.listen-section {
  margin: 16px 0 0;
  padding: 14px 12px;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid var(--color-card-border);
}

.listen-section-title {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 10px;
  padding: 0 2px;
  font-size: 0.84rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.listen-section-title-icon {
  width: 16px;
  height: 16px;
  flex: none;
}

.listen-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.listen-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  padding: 14px 8px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 16px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 800;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.2s ease, transform 0.15s ease;
}

.listen-tile-icon {
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

.listen-tile-icon svg {
  width: 18px;
  height: 18px;
}

.listen-tile.is-coral .listen-tile-icon {
  background: rgba(255, 138, 92, 0.16);
  color: var(--color-song-favorite);
}

.listen-tile.is-blue .listen-tile-icon {
  background: var(--color-secondary-light);
  color: #2c6ea8;
}

.listen-tile.is-gold .listen-tile-icon {
  background: var(--color-accent-soft);
  color: #8a6a10;
}

.listen-tile-desc {
  font-size: 0.6rem;
  font-weight: 400;
  opacity: 0.6;
  line-height: 1.4;
  margin-top: -3px;
}

/* 「今いくつあるか」が一瞬で分かるよう、数字は大きく太く強調する（本人フィードバック反映）。 */
.listen-tile-count {
  font-size: 0.95rem;
  font-weight: 900;
  color: var(--color-primary-dark);
  line-height: 1.3;
}

.listen-tile-badge {
  position: absolute;
  top: 8px;
  right: 8px;
  font-size: 0.56rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  background: var(--color-primary-dark);
  color: #ffffff;
  padding: 1px 7px;
  border-radius: 999px;
}

.listen-tile:active {
  transform: scale(0.96);
  border-color: var(--color-primary);
}

/* 「記録を見る」：称号一覧・プレイ履歴の2つをまとめた横並びピル（UI/UX再設計）。 */
.record-pill-row {
  display: flex;
  gap: 8px;
  margin-bottom: 4px;
}

.record-pill {
  flex: 1;
  padding: 10px 6px;
  border-radius: 999px;
  border: 1.5px solid var(--color-card-border);
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  text-align: center;
  cursor: pointer;
}

.record-pill:active {
  transform: scale(0.97);
  border-color: var(--color-primary);
}

/* グループ見出しの下に添える一言説明（2026-08-15追加、記録・やり込みセクション用）。
   .know-more-titleより一段控えめな見た目にする。 */
.know-more-subtitle {
  margin: -6px 0 10px;
  text-align: center;
  font-size: 0.68rem;
  font-weight: 400;
  color: var(--color-text);
  opacity: 0.6;
}

/* ===== ホーム上部のクイックナビ（遊び方ガイド／プレイヤー広場、2026-08-15追加） =====
   「＝LOVEをもっと知る」の.know-more-buttonと同じカード構造を再利用しつつ、
   プレイヤー情報のすぐ下という、最も見つけやすい位置に独立して置くための専用クラス。 */
.home-quicknav-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
  margin: 14px 0 0;
}

.home-quicknav-button {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 12px 8px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.4);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: var(--color-text);
  font-family: inherit;
  text-align: center;
  cursor: pointer;
  transition: box-shadow 0.2s ease, transform 0.15s ease, border-color 0.2s ease;
}

.home-quicknav-icon {
  font-size: 1.3rem;
  line-height: 1;
}

.home-quicknav-label {
  font-size: 0.8rem;
  font-weight: 800;
}

.home-quicknav-description {
  font-size: 0.62rem;
  font-weight: 400;
  opacity: 0.65;
  line-height: 1.3;
}

.home-quicknav-button:hover {
  border-color: var(--color-primary);
}

.home-quicknav-button:active {
  transform: scale(0.96);
  box-shadow: 0 0 0 3px rgba(255, 111, 168, 0.18);
}

/* ===== 新曲追加のお知らせバナー（2026-08-27新設） =====
   ホーム画面上部、クイックナビ（遊び方ガイド等）のすぐ下に表示する。アプリ全体の
   パステルカラーに馴染ませつつ、お祝い演出（center-celebration）ほど大きくは主張しない、
   控えめな「気付ける」程度の存在感を狙っている。差し色のレモンイエロー
   （--color-accent）を縁取りに使い、「新しい情報がある」ことを視覚的に伝える。 */
.new-single-announcement-banner {
  margin: 14px 0 0;
  padding: 12px 14px;
  border-radius: 16px;
  background: rgba(255, 217, 61, 0.14);
  border: 1.5px solid var(--color-accent);
}

.new-single-announcement-banner[hidden] {
  display: none;
}

.new-single-announcement-title {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  font-weight: 800;
  color: #b8145f; /* 【2026-10-30】淡い黄色の地の上でも読める濃さ（#ff4f96 では 約3:1） */
}

.new-single-announcement-body {
  margin: 4px 0 0;
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--color-text);
  opacity: 0.85;
}

.new-single-announcement-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}

.new-single-announcement-open-button {
  padding: 7px 14px;
  border: none;
  border-radius: 999px;
  background: var(--color-accent);
  color: #a3195b; /* 【2026-10-30】黄色の地の上の文字（#ff4f96 では 約2.2:1 → 約5.4:1） */
  font-family: inherit;
  font-size: 0.68rem;
  font-weight: 800;
  cursor: pointer;
}

.new-single-announcement-dismiss-button {
  padding: 7px 12px;
  border: 1px solid var(--color-card-border);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.5);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.68rem;
  font-weight: 700;
  opacity: 0.75;
  cursor: pointer;
}

/* プレイヤー管理モーダル内の注意書き・ストレージ許可状況表示（2026-08-15追加）。 */
.player-modal-note {
  margin: 10px 0;
  font-size: 0.68rem;
  line-height: 1.5;
  color: var(--color-text);
  opacity: 0.65;
}

.storage-persistence-status {
  margin: 12px 0 0;
  padding-top: 10px;
  border-top: 1px dashed var(--color-card-border);
  font-size: 0.68rem;
  line-height: 1.5;
  color: var(--color-text);
  opacity: 0.7;
  min-height: 1.5em;
}

.storage-persistence-status.is-protected {
  color: #1b7a3d;
  opacity: 0.9;
}

.storage-persistence-status.is-unprotected {
  color: #a8660f;
  opacity: 0.9;
}

/* ===== 初回セットアップ画面（プレイヤー名＋推しメン必須登録、2026-08-15新設） ===== */
.onboarding-intro {
  text-align: center;
  margin-bottom: 22px;
}

.onboarding-title {
  margin: 10px 0 8px;
  font-size: 1.3rem;
  font-weight: 900;
  color: var(--color-primary-dark);
}

.onboarding-lead {
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.6;
  color: var(--color-text);
  opacity: 0.75;
}

.onboarding-step {
  margin: 0 0 22px;
  padding: 16px 14px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.4);
}

.onboarding-step-heading {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 12px;
  font-size: 0.9rem;
  font-weight: 800;
  color: var(--color-text);
}

.onboarding-step-number {
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--color-primary);
  color: #ffffff;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.03em;
}

.onboarding-field-label {
  display: block;
  margin: 0 0 6px;
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.8;
}

.onboarding-name-input {
  width: 100%;
  box-sizing: border-box;
  padding: 12px 14px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 12px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.95rem;
}

.onboarding-name-input:focus {
  outline: none;
  border-color: var(--color-primary);
}

.onboarding-member-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}

.onboarding-member-option {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 10px 4px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 14px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.68rem;
  font-weight: 700;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.onboarding-member-swatch {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.8);
  box-shadow: 0 0 0 1px var(--color-card-border);
}

.onboarding-member-option.is-selected {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 2px rgba(255, 111, 168, 0.3);
  background: var(--color-primary-light);
}

.onboarding-member-option:active {
  transform: scale(0.95);
}

/* ===== 遊び方ガイド画面（2026-08-15新設） ===== */
.guide-toc-group {
  margin: 0 0 22px;
}

/* 【2026-09-15新設・本人指示：アプリ紹介動画への導線】遊び方ガイド目次の最上部に固定表示する
   動画カード。目次ボタン（.guide-toc-entry）と同じ角丸・枠・面の質感を踏襲しつつ、幅いっぱいの
   横長1枚にして「まずはここ」と分かるようにする。<a>なのでボタン風の見た目でも既定の下線・
   文字色を打ち消す。 */
.guide-video-card {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 18px;
  padding: 14px 14px;
  border: 1.5px solid var(--color-primary);
  border-radius: 16px;
  background: linear-gradient(135deg, var(--color-primary-light), var(--color-surface));
  color: var(--color-text);
  text-decoration: none;
  box-shadow: 0 8px 20px -10px rgba(255, 79, 150, 0.45);
  transition: transform 0.15s ease, border-color 0.15s ease;
}

.guide-video-card:active {
  transform: scale(0.98);
}

.guide-video-card-icon {
  flex: none;
  font-size: 1.6rem;
  line-height: 1;
}

.guide-video-card-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.guide-video-card-title {
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.guide-video-card-desc {
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1.45;
}

.guide-video-card-note {
  font-size: 0.68rem;
  line-height: 1.45;
  color: rgba(74, 46, 66, 0.72);
}

.guide-video-card-cta {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  max-width: 34%;
}

.guide-video-card-cta-label {
  padding: 9px 12px;
  border-radius: 999px;
  background: var(--color-primary);
  color: #fff;
  font-size: 0.78rem;
  font-weight: 800;
  white-space: nowrap;
}

.guide-video-card-external {
  font-size: 0.6rem;
  line-height: 1.3;
  text-align: center;
  color: rgba(74, 46, 66, 0.72);
}

/* オフライン時にカードをタップしたときだけ、数秒間表示する注意文（トースト方式ではなく
   カード直下のインライン表示。ガイド画面はスクロールする通常画面のため、固定位置の
   トーストよりカードの近くに出す方が「押した結果」として分かりやすい）。 */
.guide-video-offline-note {
  margin: -10px 0 16px;
  padding: 8px 12px;
  border-radius: 12px;
  background: var(--color-danger-soft);
  color: var(--color-danger);
  font-size: 0.78rem;
  font-weight: 700;
  text-align: center;
}

.guide-video-offline-note[hidden] {
  display: none;
}

@media (max-width: 380px) {
  .guide-video-card {
    flex-wrap: wrap;
  }

  .guide-video-card-cta {
    max-width: none;
    width: 100%;
    flex-direction: row;
    justify-content: center;
    gap: 10px;
  }
}

.guide-toc-group-heading {
  margin: 0 0 10px;
  font-size: 0.85rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.guide-toc-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.guide-toc-entry {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 10px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 14px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.76rem;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.guide-toc-entry-icon {
  flex: none;
  font-size: 1.1rem;
  line-height: 1;
}

.guide-toc-entry:hover {
  border-color: var(--color-primary);
}

.guide-toc-entry:active {
  transform: scale(0.96);
}

.guide-toc-back-link {
  margin: 0 0 14px;
}

/* 攻略本の1ページを開いたような見た目にする（過剰演出は避け、縁取り・余白で表現）。 */
.guide-detail-card {
  padding: 22px 18px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.5);
  text-align: center;
}

.guide-detail-icon {
  margin: 0 0 6px;
  font-size: 2.2rem;
  line-height: 1;
}

.guide-detail-title {
  margin: 0 0 8px;
  font-size: 1.15rem;
  font-weight: 900;
  color: var(--color-primary-dark);
}

.guide-detail-tagline {
  margin: 0 0 20px;
  font-size: 0.8rem;
  line-height: 1.7;
  color: var(--color-text);
  opacity: 0.8;
}

.guide-detail-steps-heading {
  margin: 0 0 10px;
  font-size: 0.78rem;
  font-weight: 800;
  text-align: left;
  color: var(--color-text);
}

.guide-detail-steps {
  margin: 0 0 18px;
  padding: 0;
  list-style: none;
  counter-reset: guide-step;
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-align: left;
}

.guide-detail-steps li {
  counter-increment: guide-step;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 0.8rem;
  line-height: 1.5;
}

.guide-detail-steps li::before {
  content: counter(guide-step);
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--color-primary);
  color: #ffffff;
  font-size: 0.66rem;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
}

.guide-detail-point {
  margin: 0;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--color-accent-soft);
  color: var(--color-text);
  font-size: 0.74rem;
  line-height: 1.6;
  text-align: left;
}

/* ===== メンバー・ディスコグラフィー画面共通：詳細ページのパーツ =====
   作品詳細画面（js/discographyScreen.js）とメンバー詳細画面（js/membersScreen.js）の
   両方から使う共通クラス。役割ごとに項目を分けて縦に積む構成（10-25章までの知見と同じく、
   情報量が多い画面ほど「見出し＋カード」で区切ると読みやすくなるため）。 */

.section-heading {
  margin: 20px 0 8px;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.section-heading::before {
  content: "";
  width: 3px;
  height: 14px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--color-secondary), var(--color-primary));
}

.detail-hero {
  text-align: center;
  padding: 18px 14px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid var(--color-card-border);
  border-radius: 18px;
}

.type-badge {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
  padding: 3px 12px;
  border-radius: 999px;
}

.fact-list {
  margin-top: 10px;
}

.fact-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 2px;
  border-bottom: 1px solid rgba(74, 46, 66, 0.08);
  font-size: 0.82rem;
}

.fact-row:last-child {
  border-bottom: none;
}

.fact-row-key {
  color: var(--color-text);
  opacity: 0.6;
  flex: none;
}

.fact-row-value {
  color: var(--color-text);
  font-weight: 700;
  text-align: right;
}

.fact-row-value.is-unconfirmed {
  font-weight: 400;
  font-style: italic;
  opacity: 0.45;
}

/* メンバーカラー・ペンライトカラーの行だけ、色名の左に小さな色見本を添える */
.color-fact-value {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 4px;
}

.color-swatch-dot {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, 0.9);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
  flex: none;
}

/* 丸と色名（例：●黄色）が改行時にバラバラにならないよう1つのまとまりにする */
.color-swatch-pair {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
}

/* ペンライトカラーが3色以上のとき、2色ごとに改行するための「見えない改行係」。
   .color-fact-valueはdisplay:flexのため<br>が効かず、flex-basis:100%の空要素で
   強制的に折り返す（2026-08-03、瀧脇笙古の3色表示対応）。 */
.color-fact-linebreak {
  flex-basis: 100%;
  width: 0;
  height: 0;
}

.empty-state-note {
  margin: 4px 0 0;
  font-size: 0.78rem;
  color: var(--color-text);
  opacity: 0.55;
}

.official-link-button {
  display: block;
  padding: 10px 14px;
  margin-bottom: 8px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 12px;
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 0.82rem;
  font-weight: 700;
  text-decoration: none;
}

.official-link-button:active {
  transform: scale(0.98);
}

/* ===== ＝LOVE公式YouTubeチャンネル・イコノイジョイチャンネルの紹介（2026-08-24追加、本人指示） =====
   再生リストが多いため、チャンネルごとにアコーディオンで開閉できるようにする
   （収録曲一覧の.single-groupと同じ考え方・見た目のトーンを踏襲）。 */
.youtube-channels-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.youtube-channel-group {
  border: 1.5px solid var(--color-card-border);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.4);
  overflow: hidden;
}

.youtube-channel-header {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border: none;
  background: none;
  font-family: inherit;
  text-align: left;
  color: var(--color-text);
  cursor: pointer;
}

.youtube-channel-header:focus-visible {
  outline: 2px solid var(--color-primary-dark);
  outline-offset: -2px;
}

.youtube-channel-group.is-open .chevron {
  transform: rotate(90deg);
}

.youtube-channel-name {
  flex: 1;
  min-width: 0;
  font-weight: 800;
  font-size: 0.86rem;
  line-height: 1.4;
}

.youtube-channel-count-chip {
  flex: none;
  font-size: 0.66rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.55;
  white-space: nowrap;
}

.youtube-channel-body {
  display: none;
  padding: 0 14px 14px;
}

.youtube-channel-group.is-open .youtube-channel-body {
  display: block;
}

.youtube-channel-description {
  margin: 0 0 10px;
  font-size: 0.78rem;
  line-height: 1.65;
  color: var(--color-text);
  opacity: 0.75;
}

.youtube-playlist-heading {
  margin: 14px 0 8px;
  font-size: 0.7rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  opacity: 0.8;
}

.youtube-playlist-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.youtube-playlist-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  background: var(--color-surface);
  border: 1px solid var(--color-card-border);
  border-radius: 12px;
}

.youtube-playlist-name {
  margin: 0;
  font-size: 0.82rem;
  font-weight: 800;
  color: var(--color-text);
}

.youtube-playlist-description {
  margin: 0;
  font-size: 0.72rem;
  line-height: 1.55;
  color: var(--color-text);
  opacity: 0.65;
}

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.song-chip {
  font-size: 0.75rem;
  font-weight: 700;
  background: var(--color-accent-soft);
  border: 1px solid var(--color-accent);
  color: var(--color-text);
  padding: 4px 10px;
  border-radius: 999px;
}

/* ===== ディスコグラフィー画面：タブ ===== */

.tab-row {
  display: flex;
  gap: 4px;
  padding: 4px;
  margin-bottom: 16px;
  background: rgba(255, 255, 255, 0.45);
  border: 1px solid var(--color-card-border);
  border-radius: 999px;
}

.tab-button {
  flex: 1;
  padding: 8px 6px;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  opacity: 0.55;
  cursor: pointer;
}

.tab-button.is-active {
  background: linear-gradient(120deg, var(--color-primary), var(--color-primary-dark));
  color: #fff;
  opacity: 1;
  box-shadow: 0 6px 14px -6px rgba(255, 79, 150, 0.5);
}

.tab-panel {
  display: none;
}

.tab-panel.is-active {
  display: block;
}

/* ===== ディスコグラフィー画面：年表タブ ===== */

.member-count-card {
  padding: 14px 16px;
  margin-bottom: 18px;
  background: var(--color-primary-light);
  border-radius: 14px;
}

.member-count-founding {
  margin: 0;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.member-count-current {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed rgba(74, 46, 66, 0.15);
  font-size: 0.8rem;
  color: var(--color-text);
}

.member-count-badge {
  font-size: 0.68rem;
  font-weight: 800;
  color: #fff;
  background: var(--color-secondary);
  padding: 2px 9px;
  border-radius: 999px;
}

.timeline {
  position: relative;
  padding-left: 18px;
}

.timeline::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 4px;
  bottom: 4px;
  width: 2px;
  background: linear-gradient(180deg, var(--color-primary), var(--color-secondary));
  opacity: 0.5;
}

.timeline-year {
  margin: 18px 0 8px;
  font-size: 0.85rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.timeline-year:first-child {
  margin-top: 0;
}

.timeline-item {
  position: relative;
  margin-bottom: 12px;
}

.timeline-item::before {
  content: "";
  position: absolute;
  left: -17px;
  top: 4px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--color-accent);
  border: 2px solid var(--color-surface);
}

/* 卒業・結成発表等の節目イベントは、リリース（黄）と見分けられるよう色を変える */
.timeline-item.type-graduation::before {
  background: var(--color-primary);
}

.timeline-item.type-milestone::before {
  background: var(--color-secondary);
  width: 11px;
  height: 11px;
  left: -18px;
}

/* ライブ・周年記念の節目も年表に含める（2026-08-23追加。本人指示：映像商品化の有無に
   関わらず、＝LOVEの成長が分かる重要な出来事を年表へ拡張してほしい）。
   詳細な会場・映像商品情報はライブタブ（LIVE_EVENTS）側に持たせたままにし、
   年表側は「日付・タイトルだけの節目」として軽量に重複させる方針。 */
.timeline-item.type-live::before {
  background: var(--color-call-glow);
}

.timeline-item.type-anniversary::before {
  background: var(--color-danger);
  width: 11px;
  height: 11px;
  left: -18px;
}

/* 年表の色付き丸が何を表すかの凡例。横並び・折り返し可能な小さなチップにして、
   年表本体を圧迫しないようにする（2026-08-03追加） */
.timeline-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 12px;
  margin-bottom: 16px;
}

.timeline-legend-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.68rem;
  color: var(--color-text);
  opacity: 0.75;
}

.timeline-legend-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-accent);
  flex: none;
}

.timeline-legend-dot.type-graduation {
  background: var(--color-primary);
}

.timeline-legend-dot.type-milestone {
  background: var(--color-secondary);
}

.timeline-legend-dot.type-live {
  background: var(--color-call-glow);
}

.timeline-legend-dot.type-anniversary {
  background: var(--color-danger);
}

/* ライブタブ：掲載基準の注記（2026-08-03追加） */
.live-list-notice {
  margin: 0 0 14px;
  font-size: 0.72rem;
  line-height: 1.6;
  color: var(--color-text);
  opacity: 0.65;
}

/* ライブタブ：ライブ・ツアー履歴のカード一覧（2026-08-03追加） */
.live-event-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.live-event-card {
  padding: 12px 14px;
  background: var(--color-surface);
  border: 1px solid var(--color-card-border);
  border-radius: 14px;
}

.live-event-tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 6px;
}

.live-event-tag {
  display: inline-block;
  font-size: 0.65rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
  padding: 1px 9px;
  border-radius: 999px;
}

.live-event-tag.is-anniversary {
  color: #9a5b12;
  background: #fbedd9;
}

.live-event-tag.is-announced {
  color: #1c5f8a;
  background: #e1f0fa;
}

.live-event-tag.is-graduation {
  color: #7a3b6e;
  background: #f3e3ef;
}

/* 映像商品化されている公演を一目で分かるようにするタグ（2026-08-23追加） */
.live-event-tag.is-video-available {
  color: #1f7a4d;
  background: #dff3e7;
}

/* 映像商品の発売が決まっているが、まだ発売前の公演（2026-10-23追加） */
.live-event-tag.is-video-upcoming {
  color: #1c5f8a;
  background: #e1f0fa;
}

.live-event-product-links {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}

.live-event-product-link {
  margin-bottom: 0;
  padding: 8px 12px;
  font-size: 0.72rem;
}

.live-event-title {
  margin: 0 0 4px;
  font-size: 0.88rem;
  font-weight: 800;
  color: var(--color-text);
}

.live-event-date {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.85;
}

.live-event-venue {
  margin: 2px 0 0;
  font-size: 0.76rem;
  color: var(--color-text);
  opacity: 0.7;
}

.live-event-bluray {
  margin: 6px 0 0;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.live-event-note {
  margin: 4px 0 0;
  font-size: 0.72rem;
  color: var(--color-text);
  opacity: 0.65;
}

.timeline-date {
  margin: 0;
  font-size: 0.7rem;
  color: var(--color-text);
  opacity: 0.5;
  font-variant-numeric: tabular-nums;
}

.timeline-title {
  margin: 1px 0 0;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--color-text);
}

/* ===== ディスコグラフィー画面：作品一覧タブ／作品詳細画面 ===== */

.work-card {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 12px 14px;
  margin-bottom: 10px;
  border: 1px solid var(--color-card-border);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.4);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.work-card:active {
  transform: scale(0.98);
}

.work-card-info {
  flex: 1;
  min-width: 0;
}

.work-card-type {
  display: inline-block;
  font-size: 0.68rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
  padding: 1px 9px;
  border-radius: 999px;
  margin-bottom: 3px;
}

.work-card-title {
  margin: 0;
  font-size: 0.9rem;
  font-weight: 800;
  color: var(--color-text);
}

.work-card-date {
  margin: 2px 0 0;
  font-size: 0.72rem;
  color: var(--color-text);
  opacity: 0.55;
  font-variant-numeric: tabular-nums;
}

.work-card-chevron {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--color-primary);
  opacity: 0.6;
}

.track-list {
  padding: 4px 14px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid var(--color-card-border);
  border-radius: 14px;
}

.discography-track-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 0;
  border-bottom: 1px solid rgba(74, 46, 66, 0.08);
  font-size: 0.82rem;
}

.discography-track-row:last-child {
  border-bottom: none;
}

.track-tag {
  flex: none;
  font-size: 0.65rem;
  font-weight: 800;
  padding: 2px 7px;
  border-radius: 999px;
}

.track-tag.is-title {
  background: var(--color-accent-soft);
  color: #8a6d00;
}

.track-tag.is-coupling {
  background: rgba(74, 46, 66, 0.06);
  color: var(--color-text);
  opacity: 0.6;
}

.track-name {
  font-weight: 700;
  color: var(--color-text);
}

.track-center {
  margin-left: auto;
  flex: none;
  font-size: 0.7rem;
  color: var(--color-text);
  opacity: 0.5;
  white-space: nowrap;
}

.work-description {
  padding: 12px 14px;
  margin: 0;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid var(--color-card-border);
  border-radius: 14px;
  font-size: 0.82rem;
  color: var(--color-text);
  opacity: 0.85;
}

/* ===== メンバー一覧画面 ===== */

.member-section-label-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin: 4px 0 10px;
}

.member-section-label-row h3 {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.member-section-count {
  font-size: 0.72rem;
  color: var(--color-text);
  opacity: 0.5;
}

.member-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

/* カード全体（詳細への遷移ボタン＋推しハートボタンをまとめる枠）。
   2026-08-03、推しハートボタンを追加する際に、button内にbuttonを置けないため
   「枠のdiv＋中の2つのbutton」という構造に分割した。見た目（枠線・背景・影）は
   引き続きここで持たせる。 */
.member-card {
  position: relative;
  border: 1px solid var(--color-card-border);
  border-radius: 16px;
  background: var(--color-surface);
  box-shadow: 0 8px 20px -14px rgba(74, 46, 66, 0.3);
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

/* カード本体がタップできることを、ホバー・フォーカス時の軽い反応で伝える
   （2026-08-07追加。カード全体をタップすると詳細が開くことに気づきにくい、という指摘への対応）。
   スマホ（ホバー非対応）では:activeのscaleだけが効く。 */
@media (hover: hover) {
  .member-card:hover {
    transform: translateY(-1px);
    box-shadow: 0 12px 24px -14px rgba(74, 46, 66, 0.4);
    border-color: var(--color-primary-light);
  }
}

.member-card:has(.member-card-tap-target:focus-visible) {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-light);
}

.member-card:active {
  transform: scale(0.98);
}

/* 現在詳細を表示している（または直前に見た）メンバーのカードを強調する。
   優先度低めの機能だが、実装コストが小さいため本実装から採用している。 */
.member-card.is-selected {
  border: 2px solid var(--color-primary);
  box-shadow: 0 0 0 4px var(--color-primary-light), 0 10px 22px -12px rgba(255, 79, 150, 0.4);
}

.member-card-tap-target {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 14px 8px 12px;
  border: none;
  border-radius: inherit;
  background: transparent;
  font-family: inherit;
  cursor: pointer;
}

/* カード全体の押下反応は親.member-card側の:active（scale(0.98)）に統一しているため、
   ここでは重ねて縮小させない。 */

/* 推し・最推しバッジの凡例（2026-08-04追加） */
.member-favorite-legend {
  display: flex;
  justify-content: center;
  gap: 16px;
  margin: 0 0 10px;
  font-size: 0.7rem;
  color: var(--color-text);
  opacity: 0.7;
}

.member-favorite-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.member-favorite-legend-heart {
  color: var(--color-primary);
  font-size: 0.85rem;
}

.member-favorite-legend-star {
  color: #c9910a;
  font-size: 0.8rem;
}

/* 一覧カードの「最推し（星）」「推し（ハート）」ボタン列。★→♡の順で並べ、
   凡例（★最推し・♡推し）と同じ並び順にする。2つのボタンがくっつきすぎて
   誤タップしないよう、間に4pxの隙間を空けている（2026-08-04、星ボタンを
   一覧から直接押せるように分離した際にまとめて調整）。 */
.member-card-action-row {
  position: absolute;
  top: 6px;
  right: 6px;
  display: flex;
  align-items: center;
  gap: 4px;
}

.member-card-favorite-button,
.member-card-star-button {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1.5px solid rgba(255, 255, 255, 0.9);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.9);
  box-shadow: 0 3px 8px -2px rgba(0, 0, 0, 0.3);
  color: #c9bcc3;
  transition: transform 0.15s ease;
}

.member-card-favorite-button:active,
.member-card-star-button:active {
  transform: scale(0.88);
}

.member-card-favorite-button svg,
.member-card-star-button svg {
  width: 17px;
  height: 17px;
  fill: currentColor;
}

.member-card-favorite-button.is-favorite {
  color: var(--color-primary);
}

/* 最推しの星ボタンは、金色に塗りつぶしてひと目で分かるようにする。 */
.member-card-star-button.is-most-oshi {
  color: #fff;
  background: linear-gradient(145deg, #ffcf4d, var(--color-accent));
  border-color: #fff;
  box-shadow: 0 0 0 2px rgba(255, 217, 61, 0.55), 0 4px 10px -2px rgba(255, 178, 0, 0.5);
}

.member-card-star-button.is-most-oshi svg {
  fill: #7a4b00;
}

.member-card-swatch {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.9);
  box-shadow: 0 6px 14px -6px rgba(0, 0, 0, 0.3), inset 0 -4px 8px rgba(0, 0, 0, 0.12);
}

.member-card-name {
  margin: 0;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--color-text);
  text-align: center;
}

.member-graduated-block {
  margin-top: 22px;
}

.member-section-heading {
  margin: 0 0 4px;
  font-size: 0.82rem;
  font-weight: 800;
  color: var(--color-text);
  opacity: 0.7;
}

.member-graduated-note {
  margin: 0 0 12px;
  font-size: 0.75rem;
  color: var(--color-text);
  opacity: 0.6;
}

.graduated-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  margin-bottom: 8px;
  background: rgba(255, 255, 255, 0.35);
  border: 1px dashed var(--color-card-border);
  border-radius: 14px;
  filter: saturate(0.75);
}

.graduated-card-swatch {
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.9);
}

.graduated-card-info {
  flex: 1;
  min-width: 0;
}

.graduated-card-name {
  margin: 0;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--color-text);
}

.graduated-card-period,
.graduated-card-center {
  margin: 2px 0 0;
  font-size: 0.68rem;
  color: var(--color-text);
  opacity: 0.55;
}

.graduated-card-link {
  display: inline-block;
  margin-top: 4px;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.graduated-card-tag {
  flex: none;
  font-size: 0.65rem;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(74, 46, 66, 0.08);
  color: var(--color-text);
  opacity: 0.65;
  white-space: nowrap;
}

/* ===== メンバー詳細画面 ===== */

.member-detail-swatch {
  display: block;
  width: 80px;
  height: 80px;
  margin: 0 auto 12px;
  border-radius: 50%;
  border: 4px solid rgba(255, 255, 255, 0.9);
  box-shadow: 0 10px 22px -8px rgba(0, 0, 0, 0.35), inset 0 -6px 12px rgba(0, 0, 0, 0.12);
}

.member-detail-name {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 800;
  color: var(--color-text);
}

.member-detail-reading {
  margin: 2px 0 0;
  font-size: 0.72rem;
  color: var(--color-text);
  opacity: 0.55;
}

.member-detail-attendance {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
  padding: 3px 12px;
  border-radius: 999px;
}

.member-detail-badge-row {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin-top: 8px;
  flex-wrap: wrap;
}

.member-detail-role-badge {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 800;
  color: #fff;
  background: linear-gradient(120deg, var(--color-primary), var(--color-primary-dark));
  padding: 3px 12px;
  border-radius: 999px;
}

/* メンバー詳細画面の「推しに登録」「最推しにする」ボタン列（2026-08-03追加） */
.member-detail-oshi-row {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: 14px;
  flex-wrap: wrap;
}

.oshi-action-button {
  font-family: inherit;
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1.5px solid var(--color-card-border);
  border-radius: 999px;
  padding: 7px 16px;
  cursor: pointer;
}

.oshi-action-button:active {
  transform: scale(0.96);
}

.oshi-action-button.is-active {
  color: #fff;
  background: linear-gradient(120deg, var(--color-primary), var(--color-primary-dark));
  border-color: transparent;
}

.oshi-action-button.is-most-oshi-button.is-active {
  background: linear-gradient(120deg, #ffb545, var(--color-accent));
}

/* メンバー一覧カードの小さな役割タグ（リーダー等） */
.member-card-role-tag {
  font-size: 0.62rem;
  font-weight: 800;
  color: #fff;
  background: var(--color-primary);
  padding: 2px 9px;
  border-radius: 999px;
}

/* 「プロフィールを見る ›」案内文言。カード本体タップで詳細が開くことに気づいてもらうための、
   主張しすぎない小さな導線（2026-08-07追加）。 */
.member-card-view-hint {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  margin-top: 2px;
  font-size: 0.6rem;
  font-weight: 700;
  color: var(--color-primary);
  opacity: 0.75;
}

.member-card-view-hint-icon {
  width: 9px;
  height: 9px;
}

/* 情報源が公式・本人発信以外（メディア報道・ファン定着）のときだけ添える小さな注記チップ */
.source-badge {
  display: inline-block;
  margin-left: 6px;
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--color-text);
  background: rgba(74, 46, 66, 0.08);
  padding: 2px 8px;
  border-radius: 999px;
  vertical-align: middle;
}

/* 紹介文・加入前の活動・志望動機など、1件のテキストを見せるカード */
.text-card {
  padding: 12px 14px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid var(--color-card-border);
  border-radius: 14px;
}

.text-card-body {
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.7;
  color: var(--color-text);
}

/* 個人活動・レギュラー企画のカード一覧 */
.activity-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.activity-card {
  display: block;
  padding: 10px 12px;
  background: var(--color-surface);
  border: 1px solid var(--color-card-border);
  border-radius: 12px;
  text-decoration: none;
  color: inherit;
}

.activity-card-type {
  display: inline-block;
  font-size: 0.65rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
  padding: 1px 9px;
  border-radius: 999px;
  margin-right: 4px;
}

/* 活動の現況（continue/annual/irregular/ended/past）ごとの色分けタグ */
.activity-card-status {
  display: inline-block;
  font-size: 0.65rem;
  font-weight: 800;
  padding: 1px 9px;
  border-radius: 999px;
}

.activity-card-status.is-ongoing {
  color: #1b7a3d;
  background: #e2f5e8;
}

.activity-card-status.is-annual {
  color: #1c5f8a;
  background: #e1f0fa;
}

.activity-card-status.is-irregular {
  color: #9a5b12;
  background: #fbedd9;
}

.activity-card-status.is-ended,
.activity-card-status.is-past {
  color: #6b6470;
  background: #ece7ea;
}

.activity-card-title {
  margin: 6px 0 0;
  font-size: 0.85rem;
  font-weight: 800;
  color: var(--color-text);
}

.activity-card-description {
  margin: 2px 0 0;
  font-size: 0.75rem;
  color: var(--color-text);
  opacity: 0.7;
}

.activity-card-link {
  display: inline-block;
  margin-top: 8px;
}

/* 愛称・ファンネームのチップ */
.nickname-chip {
  font-size: 0.78rem;
  font-weight: 700;
  background: var(--color-surface);
  border: 1px solid var(--color-card-border);
  color: var(--color-text);
  padding: 5px 12px;
  border-radius: 999px;
}

.nickname-chip.is-fanname {
  background: var(--color-accent-soft);
  border-color: var(--color-accent);
}

/* ＝LOVEについてタブ */
.about-text-block {
  margin-bottom: 4px;
}

.about-text-body {
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.8;
  color: var(--color-text);
}

.producer-card {
  margin-top: 20px;
  padding: 14px 16px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid var(--color-card-border);
  border-radius: 14px;
}

.producer-name {
  margin: 0 0 8px;
  font-size: 0.9rem;
  font-weight: 800;
  color: var(--color-text);
}

.producer-facts {
  margin: 0 0 10px;
  padding-left: 18px;
  font-size: 0.8rem;
  line-height: 1.7;
  color: var(--color-text);
  opacity: 0.85;
}

/* ===== 姉妹グループ紹介カード（＝LOVEについてタブ、プロデューサー欄の近く） ===== */
.sister-group-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.sister-group-card {
  padding: 12px 14px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid var(--color-card-border);
  border-radius: 14px;
}

.sister-group-name {
  margin: 0 0 4px;
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.sister-group-reading {
  margin-left: 6px;
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.55;
}

.sister-group-description {
  margin: 0 0 10px;
  font-size: 0.8rem;
  line-height: 1.6;
  color: var(--color-text);
  opacity: 0.85;
}

/* 姉妹グループカード内の「リーダー：○○」表記、グループ合同楽曲カード内の参加グループ・
   クレジット表記など、目立たせすぎたくない小さな補足行に共通で使う（2026-08-23追加） */
.sister-group-leader {
  margin: 0 0 6px;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.6;
}

.sister-group-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.sister-group-links .official-link-button {
  flex: 1;
  min-width: 120px;
  margin-bottom: 0;
  text-align: center;
}

/* ===== 発売前作品カード（作品一覧タブの先頭） ===== */
.upcoming-release-card {
  padding: 14px 16px;
  margin-bottom: 14px;
  background: linear-gradient(135deg, var(--color-primary-light), rgba(255, 255, 255, 0.5));
  border: 1.5px solid var(--color-primary);
  border-radius: 16px;
}

.upcoming-release-badge {
  display: inline-block;
  font-size: 0.66rem;
  font-weight: 800;
  color: #fff;
  background: var(--color-primary-dark);
  padding: 2px 10px;
  border-radius: 999px;
  margin-bottom: 8px;
}

.upcoming-release-label {
  margin: 0;
  font-size: 0.7rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  opacity: 0.8;
}

.upcoming-release-title {
  margin: 2px 0 4px;
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--color-text);
}

.upcoming-release-date {
  margin: 0 0 10px;
  font-size: 0.78rem;
  color: var(--color-text);
  opacity: 0.7;
  font-variant-numeric: tabular-nums;
}

.upcoming-release-card .official-link-button {
  margin-bottom: 0;
}

/* 卒業メンバーカードの拡張パーツ（齊藤なぎさ等、卒業後の活動を追加表示する場合） */
.graduated-card-predebut,
.graduated-card-current {
  margin: 4px 0 0;
  font-size: 0.68rem;
  color: var(--color-text);
  opacity: 0.7;
}

.graduated-card-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 4px;
}

.graduated-card-links a {
  font-size: 0.66rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

/* ===== レスポンシブ：スマホ幅（520px以下） =====
   ゲームフレームを画面幅いっぱいに広げ、カードらしい丸み・影は外して画面に馴染ませる。
   【重要】このpadding: 0;が、47行目付近で指定しているセーフエリア対応のpadding-topを
   後から上書きしてしまい、iPhoneのDynamic Island・ノッチとヘッダーが重なる不具合の
   原因になっていた（実機調査で特定済み）。上だけセーフエリア分を維持し、
   左右・下は既存の「画面いっぱいに表示する」デザインのまま0を維持する。 */
@media (max-width: 520px) {
  body {
    padding-top: max(64px, calc(env(safe-area-inset-top) + 20px));
    padding-right: 0;
    padding-bottom: 0;
    padding-left: 0;
    align-items: stretch;
  }

  .game-frame {
    max-width: 100%;
    /* 【2026-11-XX修正】bodyと同じ理由（上記コメント参照）で100vhからの置き換え。
       スマホ幅ではgame-frame自体が画面いっぱい（border-radius:0）に広げる設計のため、
       特にコンテンツが短い画面（例：フォロー一覧・診断ログ画面等、一部のクイズ画面
       専用ルールが別途上書きしない画面）で、枠が画面の物理的な最下端まで届かず
       白い帯が残っていた可能性が高い。 */
    min-height: var(--game-frame-safe-height);
    border-radius: 0;
    box-shadow: none;
  }

  /* スマホ幅では、カテゴリ名の折り返しを妨げないよう曲数の文字をさらに小さくする */
  .category-option .count-hint {
    font-size: 0.72rem;
  }
}

/* ===== レスポンシブ：非常に狭いスマホ幅（360px以下） =====
   4択ボタンが窮屈にならないよう、2×2グリッドから縦1列表示に切り替える。 */
@media (max-width: 360px) {
  #choice-buttons {
    grid-template-columns: 1fr;
  }

  #quiz-actions {
    flex-direction: column;
  }
}

/* ===== 連続再生画面 =====（2026-08-04新設、同日中に1画面構成へ改訂）
   設定と再生操作を1つの画面にまとめる。設定パネルは折りたたみ式にし、閉じている間も
   要約チップ（.continuous-play-settings-summary）で今の選択内容が分かるようにする。 */

/* 「聴くこと」が主役の画面のため、設定の入口は常時表示エリアの末尾に控えめに置く
   （UI/UX再設計：以前は目立つ帯状ボタンだったが、本人フィードバックでさらにトーンを落とした）。
   ヘッダーの⚙アイコン（.header-icon-button、汎用クラス）からも同じパネルを開ける。 */
.continuous-play-settings-entry {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 7px 4px;
  margin-top: 10px;
  border: none;
  border-top: 1px dashed var(--color-card-border);
  background: none;
  color: var(--color-text);
  opacity: 0.45;
  font-family: inherit;
  font-size: 0.7rem;
  font-weight: 700;
  cursor: pointer;
}

.continuous-play-settings-summary {
  flex: 1;
  min-width: 0;
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.continuous-play-settings-entry .chevron {
  flex: none;
  width: 14px;
  height: 14px;
  transition: transform var(--transition-fast) ease;
}

.continuous-play-settings-entry.is-open .chevron {
  transform: rotate(90deg);
}

/* ヘッダーの丸いアイコンボタン（汎用）。連続再生画面の設定入口として使う。
   聴くことを邪魔しないよう、通常時は淡く、開いている間だけ主張する。 */
.header-icon-button {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1.5px solid var(--color-card-border);
  background: rgba(255, 255, 255, 0.5);
  color: var(--color-text);
  opacity: 0.55;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.header-icon-button svg {
  width: 15px;
  height: 15px;
}

.header-icon-button.is-open {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #ffffff;
  opacity: 1;
}

/* 【2026-11-XX新設・本人指示：右上の音量ボタンが何のボタンか分かりにくい】
   クイズ画面右上のSFX ON/OFFボタンは、丸いアイコンのみの.header-icon-buttonのままだと
   近くにある「🔇 音が出ない」ボタンと役割が見分けづらいという実プレイでの指摘を受け、
   アイコンの隣に短い文字ラベル「音量」を添えた横長のピル形状へ変更する（既存のピンク・白
   基調のデザイン・色は変えず、形だけを丸から横長の角丸へ変更するだけに留める）。 */
.quiz-header-sfx-toggle-button {
  width: auto;
  height: auto;
  padding: 5px 10px 5px 8px;
  border-radius: 999px;
  gap: 4px;
}

.quiz-header-sfx-toggle-label {
  font-size: 0.68rem;
  font-weight: 700;
  white-space: nowrap;
}

/* list-headerに3つ目の要素（設定アイコン）が入るときも、戻るボタン・タイトルの
   位置関係が崩れないようにする。 */
#continuous-play-screen .list-header {
  align-items: center;
}

.continuous-play-settings-panel {
  margin-bottom: 18px;
  padding: 14px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.5);
  border: 1px solid var(--color-card-border);
}

.continuous-play-settings-panel[hidden] {
  display: none;
}

.continuous-play-section-label {
  margin: 16px 0 8px;
  font-size: 0.78rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  opacity: 0.85;
}

.continuous-play-section-label:first-child {
  margin-top: 0;
}

.continuous-play-source-tabs,
.continuous-play-order-toggle {
  display: flex;
  gap: 8px;
}

.continuous-play-source-button,
.continuous-play-order-button {
  position: relative;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 10px 8px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-text);
  opacity: 0.55;
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 700;
  cursor: pointer;
  transition: background-color 0.15s ease, opacity 0.15s ease, box-shadow 0.15s ease;
}

.continuous-play-order-button svg {
  width: 15px;
  height: 15px;
  flex: none;
}

/* 選択中のボタンは、濃いピンクの塗りつぶし＋太字＋右上のチェックバッジで、
   未選択とのコントラストをはっきりさせる（本人・ChatGPTレビューでの指摘により強化）。 */
.continuous-play-source-button.is-active,
.continuous-play-order-button.is-active {
  background: var(--color-primary-dark);
  border-color: var(--color-primary-dark);
  color: #ffffff;
  opacity: 1;
  font-weight: 800;
  box-shadow: 0 6px 14px -6px rgba(255, 79, 150, 0.6);
}

.continuous-play-source-button.is-active::after,
.continuous-play-order-button.is-active::after {
  content: "✓";
  position: absolute;
  top: -6px;
  right: -6px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #ffffff;
  color: var(--color-primary-dark);
  font-size: 0.6rem;
  font-weight: 900;
  line-height: 16px;
  text-align: center;
  box-shadow: 0 1px 4px rgba(74, 46, 66, 0.3);
}

/* 開いたときだけ見せる短い説明文（初見向け。UI/UX再設計で追加）。 */
.continuous-play-explain {
  margin: 6px 2px 0;
  font-size: 0.68rem;
  opacity: 0.55;
  line-height: 1.6;
}

/* 「お気に入り」を再生元に選んだときの対象曲数表示（UI/UX再設計：選んでも変化が
   分かりにくいという指摘への対応）。 */
.continuous-play-favorites-ok {
  margin: 10px 0 0;
  padding: 9px 12px;
  border-radius: 12px;
  background: rgba(255, 138, 92, 0.12);
  color: var(--color-song-favorite);
  font-size: 0.76rem;
  font-weight: 700;
}

.continuous-play-favorites-empty {
  margin-top: 10px;
  padding: 16px 12px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.5);
  text-align: center;
}

.continuous-play-favorites-empty p {
  margin: 2px 0;
  font-size: 0.76rem;
  opacity: 0.65;
}

.continuous-play-favorites-empty .secondary-button {
  margin-top: 10px;
  width: auto;
  display: inline-flex;
  padding: 9px 18px;
}

/* プレイリスト選択欄（「プレイリスト」を再生元に選んだときだけ表示） */
.continuous-play-playlist-picker {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
}

.continuous-play-playlist-picker[hidden] {
  display: none;
}

/* 選択済みプレイリストのコンパクト表示。選ぶと自動でここへ切り替わる
   （UI/UX再設計：一覧を開いたままにせず、選んだら自動で閉じてほしいという指摘への対応）。 */
.continuous-play-playlist-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  margin-top: 10px;
  padding: 10px 12px;
  border-radius: 12px;
  border: 1.5px solid var(--color-primary);
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 800;
  cursor: pointer;
}

.continuous-play-playlist-summary[hidden] {
  display: none;
}

.continuous-play-playlist-summary-check {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--color-primary);
  position: relative;
  vertical-align: -2px;
}

.continuous-play-playlist-summary-check::after {
  content: "✓";
  position: absolute;
  inset: 0;
  color: #ffffff;
  font-size: 0.56rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.continuous-play-playlist-change-label {
  font-size: 0.68rem;
  font-weight: 700;
  opacity: 0.8;
}

.continuous-play-playlist-option {
  padding: 10px 14px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 14px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
}

.continuous-play-playlist-option.is-active {
  border-color: var(--color-primary);
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

.continuous-play-playlist-option:disabled {
  opacity: 0.45;
  cursor: default;
}

#continuous-play-apply-button {
  display: block;
  width: 100%;
  margin-top: 20px;
}

/* ---- 常時表示の再生中エリア ---- */
#continuous-play-now-playing {
  text-align: center;
}

/* 収録曲一覧への入口リンク（songlist-screen）。他のリンクと同じ控えめな見た目にしつつ、
   タブ列のすぐ下にまとめて視線の流れを妨げないようにする（2026-08-04追加）。 */
.continuous-play-entry-link {
  display: block;
  margin: 8px 0 0;
}

/* 「次に再生」プレビューカードと「再生キューを見る」入口（UI/UX再設計で新設）。
   今の曲だけでなく、この後どうなるかが伝わるようにする。タップすると再生キュー画面へ移動する
   ボタンのため、widthやcursorなどボタンの初期値を上書きしておく。 */
.continuous-play-next-card {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  margin: 14px 0 8px;
  padding: 10px 14px;
  border-radius: 14px;
  border: 1.5px dashed var(--color-card-border);
  background: rgba(255, 255, 255, 0.4);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.continuous-play-next-card[hidden] {
  display: none;
}

.continuous-play-next-label {
  flex: none;
  font-size: 0.62rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
  padding: 3px 9px;
  border-radius: 999px;
}

/* 2026-09-16改訂・本人指示：UI一貫性ルール（曲名は常に濃いピンク＋太字）。
   「次に再生」プレビューカードの曲名も、他の曲名表示と同じブランドピンクに揃えた。 */
.continuous-play-next-title {
  flex: 1;
  min-width: 0;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.continuous-play-queue-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  margin-bottom: 14px;
  padding: 10px 14px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.35);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
}

.continuous-play-queue-link[hidden] {
  display: none;
}

.continuous-play-queue-link-label {
  display: flex;
  align-items: center;
  gap: 6px;
}

.continuous-play-queue-link-label svg {
  width: 16px;
  height: 16px;
  flex: none;
}

.continuous-play-queue-link-count {
  opacity: 0.55;
  font-weight: 700;
  white-space: nowrap;
}

.continuous-play-queue-link:active {
  border-color: var(--color-primary);
}

/* 再生キュー画面の1行（UI/UX再設計で新設）。再生中の曲を強調し、それ以外は
   タップでその曲へ移動できる。ボタンの中にボタンを置けないため、行自体は<div>にし、
   「タップで移動」部分（.queue-row-main）と「並び替え操作」部分
   （.queue-row-reorder-controls）を兄弟要素にしている（ドラッグ並び替え追加で改訂）。 */
.queue-row {
  display: flex;
  align-items: center;
  gap: 4px;
  width: 100%;
  padding: 4px 6px 4px 10px;
  margin-bottom: 4px;
  border-radius: 14px;
  background: transparent;
  color: var(--color-text);
  transition: background-color 0.12s ease;
}

.queue-row.is-current {
  background: var(--color-primary-light);
}

/* 次に流れる曲も薄く強調し、「次は何か」が一瞬で分かるようにする（本人フィードバック反映）。 */
.queue-row.is-next {
  background: rgba(255, 111, 168, 0.06);
}

/* ドラッグ中の行は、少し浮き上がったように見せて操作対象であることを分かりやすくする。 */
.queue-row.is-dragging {
  background: var(--color-surface);
  box-shadow: 0 8px 20px -6px rgba(74, 46, 66, 0.35);
  position: relative;
  z-index: 1;
}

.queue-row-main {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  min-width: 0;
  padding: 7px 4px;
  border: none;
  border-radius: 12px;
  background: transparent;
  color: inherit;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.queue-row-main:disabled {
  cursor: default;
}

.queue-row-next-badge {
  flex: none;
  font-size: 0.56rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
  padding: 2px 7px;
  border-radius: 999px;
}

.queue-row-index {
  flex: none;
  width: 22px;
  text-align: center;
  font-size: 0.72rem;
  font-weight: 800;
  opacity: 0.5;
  font-variant-numeric: tabular-nums;
}

.queue-row.is-current .queue-row-index {
  opacity: 1;
  color: var(--color-primary-dark);
}

.queue-row-title {
  flex: 1;
  min-width: 0;
  font-size: 0.82rem;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.queue-row.is-current .queue-row-title {
  color: var(--color-primary-dark);
  font-weight: 800;
}

.queue-row-now-badge {
  flex: none;
  font-size: 0.6rem;
  font-weight: 800;
  color: #ffffff;
  background: var(--color-primary);
  padding: 3px 9px;
  border-radius: 999px;
}

/* 並び替え操作（↑↓ボタン＋ドラッグハンドル）。行のタップ領域とは別に、右端にまとめる。 */
.queue-row-reorder-controls {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: none;
}

.queue-row-move-button {
  flex: none;
  width: 26px;
  height: 26px;
  border: none;
  border-radius: 50%;
  background: rgba(74, 46, 66, 0.06);
  color: var(--color-text);
  font-size: 0.7rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.queue-row-move-button:disabled {
  opacity: 0.3;
  cursor: default;
}

/* ドラッグハンドル：タップ領域は44px前後を確保しつつ、視覚的な大きさは控えめにする。
   touch-action:noneで、スマホでのドラッグ中にページが一緒にスクロールしてしまうのを防ぐ
   （本人希望：長押し・ドラッグ操作とスクロールが競合しないこと）。 */
.queue-row-drag-handle {
  flex: none;
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--color-text);
  opacity: 0.45;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: grab;
  touch-action: none;
}

.queue-row-drag-handle svg {
  width: 18px;
  height: 18px;
}

.queue-row.is-dragging .queue-row-drag-handle {
  cursor: grabbing;
  opacity: 1;
  color: var(--color-primary-dark);
}

.continuous-play-position-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin-bottom: 2px;
}

.continuous-play-position {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
}

/* リピートの循環ボタン（なし→全体→1曲→なし）。使用頻度が低いため、常時表示エリアの
   中でも一番小さく控えめに置く（UI/UX再設計：以前は再生元・再生方法と同じ大きさの
   3択ボタンだったが、本人フィードバックで格下げした）。 */
.continuous-play-repeat-cycle-button {
  position: relative;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1.5px solid var(--color-card-border);
  background: rgba(255, 255, 255, 0.5);
  color: var(--color-text);
  opacity: 0.55;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.continuous-play-repeat-cycle-button svg {
  width: 13px;
  height: 13px;
}

.continuous-play-repeat-cycle-button.is-active {
  opacity: 1;
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #ffffff;
}

.continuous-play-repeat-badge {
  position: absolute;
  bottom: -3px;
  right: -3px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: #ffffff;
  color: var(--color-primary-dark);
  font-size: 0.52rem;
  font-weight: 900;
  line-height: 13px;
  text-align: center;
  box-shadow: 0 1px 3px rgba(74, 46, 66, 0.3);
}

/* 再生中の曲名。この画面の中で最も目立たせたい情報なので、一番大きく太くする */
.continuous-play-song-title {
  margin: 6px 0 2px;
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  line-height: 1.4;
  word-break: break-word;
}

.continuous-play-song-meta {
  margin: 0 0 4px;
  font-size: 0.74rem;
  color: var(--color-text);
  opacity: 0.6;
}

.continuous-play-status-text {
  margin: 0 0 4px;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.7;
}

.continuous-play-notice {
  margin: 4px auto 0;
  max-width: 320px;
  font-size: 0.72rem;
  color: var(--color-text);
  opacity: 0.65;
}

.continuous-play-notice[hidden] {
  display: none;
}

/* シークバー行。見た目の線は細くても、input自体の高さを32pxにしてタップしやすくする
   （本人フィードバック：見た目が細くても当たり判定は広めに、という指示に対応）。 */
.continuous-play-seek-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 14px 0 4px;
}

/* [hidden]属性はCSSのdisplay指定より優先度が低いため、display:flexを指定している
   要素では明示的に上書きしないとhidden="true"でも消えない（このファイルの他の箇所でも
   繰り返し踏んでいる既知の落とし穴）。 */
.continuous-play-seek-row[hidden] {
  display: none;
}

.continuous-play-time {
  flex: none;
  width: 38px;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
}

.continuous-play-time:last-child {
  text-align: right;
}

.continuous-play-seek-range {
  flex: 1;
  width: 100%;
  height: 32px;
  margin: 0;
  accent-color: var(--color-primary-dark);
}

.continuous-play-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 18px;
  margin: 10px 0 6px;
}

.continuous-play-controls[hidden] {
  display: none;
}

/* 前へ/次へ・再生/一時停止ボタン。スマホでも押しやすいよう44px以上を確保し、
   メインの再生/一時停止ボタン（.is-main）はさらに大きくして一番の主役にする。 */
.continuous-play-control-button {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border: none;
  border-radius: 50%;
  background: var(--color-surface);
  color: var(--color-primary-dark);
  box-shadow: 0 4px 12px -4px rgba(255, 79, 150, 0.4);
  cursor: pointer;
  transition: transform var(--transition-fast) ease;
}

.continuous-play-control-button svg {
  width: 18px;
  height: 18px;
}

.continuous-play-control-button.is-main {
  width: 64px;
  height: 64px;
  background: var(--color-primary);
  color: #ffffff;
}

.continuous-play-control-button.is-main svg {
  width: 24px;
  height: 24px;
}

.continuous-play-control-button:active {
  transform: scale(0.92);
}

.continuous-play-control-button:disabled {
  opacity: 0.35;
  cursor: default;
  transform: none;
}

/* 再生/一時停止アイコンの切り替え。.play-button（収録曲一覧）と同じ考え方。 */
.continuous-play-control-button.is-main .icon-pause {
  display: none;
}

.continuous-play-control-button.is-main.is-playing .icon-play {
  display: none;
}

.continuous-play-control-button.is-main.is-playing .icon-pause {
  display: block;
}

.continuous-play-empty-message {
  margin: 20px 0;
  padding: 16px;
  border-radius: 14px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  color: var(--color-text);
  font-size: 0.85rem;
  text-align: center;
  line-height: 1.6;
}

.continuous-play-empty-message[hidden] {
  display: none;
}

/* 同期歌詞エリア。歌詞データがない曲では#continuous-play-lyrics-section自体を
   非表示にする（枠だけ残って空白になるのを防ぐ）。パネル本体は.synced-lyrics-panel
   （収録曲一覧と共通）をそのまま使い、ここでは連続再生画面向けの微調整だけ行う。 */
.continuous-play-lyrics-section {
  margin-top: 16px;
  text-align: left;
}

.continuous-play-lyrics-section[hidden] {
  display: none;
}

.continuous-play-lyrics-panel {
  max-height: 190px;
}

.continuous-play-lyrics-fullscreen-button {
  margin: 6px auto 0;
}

/* ===== タイムアタック結果画面 ===== （2026-08-06新設） */
#time-attack-result-new-record {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: fit-content;
  margin: 10px auto 0;
  padding: 6px 16px;
  border-radius: 999px;
  font-size: 1rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background-color: var(--color-accent-soft);
}

#time-attack-result-new-record[hidden] {
  display: none;
}

/* LOVE連チャンルールで、全問クリアできずに終了したときだけ表示する（2026-08-06追加）。
   新記録バッジ（黄色・お祝い）とは対照的に、赤系の色でひと目で「失敗」と分かるようにしている。 */
#time-attack-result-fail-status {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: fit-content;
  max-width: 100%;
  margin: 10px auto 0;
  padding: 6px 16px;
  border-radius: 999px;
  font-size: 0.9rem;
  font-weight: 700;
  text-align: center;
  color: var(--color-danger);
  background-color: var(--color-danger-soft);
}

#time-attack-result-fail-status[hidden] {
  display: none;
}

/* 【2026-09-15追加】通常ランダム再生の結果：スキップ・答えを見るを使った回の案内
   （失敗表示と同じピル型。色は注意色ではなく控えめなグレー系にして「失敗」と区別する）。 */
.time-attack-result-note {
  display: flex;
  align-items: center;
  justify-content: center;
  width: fit-content;
  max-width: 100%;
  margin: 10px auto 0;
  padding: 6px 16px;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 600;
  text-align: center;
  color: var(--color-text-muted, #6b6b6b);
  background-color: rgba(0, 0, 0, 0.05);
}

.time-attack-result-note[hidden] {
  display: none;
}

.time-attack-result-total-label {
  margin: 18px 0 2px;
  text-align: center;
  font-size: 0.8rem;
  opacity: 0.6;
}

.time-attack-result-total-time {
  margin: 0 0 18px;
  text-align: center;
  font-size: 2.2rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
}

.time-attack-result-stats-row {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
}

.time-attack-result-stat {
  flex: 1;
  padding: 10px;
  border-radius: 12px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  text-align: center;
}

.time-attack-result-stat-label {
  margin: 0 0 2px;
  font-size: 0.68rem;
  opacity: 0.6;
}

.time-attack-result-stat-value {
  margin: 0;
  font-size: 1rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
}

/* 【2026-09-30新設・本人指示：オンライン対戦総合改修 第3ラウンド・一瞬協力結果画面の
   デザイン強化】チーム全体で1つの成績しか無い一瞬協力の結果画面向けに、他モードの
   個人順位メダルに相当する「主役」の数値表示を作る。既存の.time-attack-result-statより
   一回り大きく、中央寄せの主役カードにする（本人指示：情報を無理に増やさず、
   見やすいカード構成にすること）。 */
.online-instant-coop-result-hero-stat {
  margin-bottom: 14px;
  padding: 18px 16px;
  border-radius: 16px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  text-align: center;
}

.online-instant-coop-result-hero-stat-label {
  margin: 0 0 4px;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.75;
}

.online-instant-coop-result-hero-stat-value {
  margin: 0;
  font-size: 1.8rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
}

/* 【2026-09-05新設・本人指示：実機フィードバックによる結果画面改善】今回のMVP。
   .online-instant-coop-result-hero-statの見た目（グラスカード）はそのまま流用し、
   名前部分・内訳部分だけ専用クラスで調整する。 */
.online-instant-coop-mvp-names {
  margin: 0;
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  overflow-wrap: anywhere;
}

.online-instant-coop-mvp-detail {
  margin: 4px 0 0;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.75;
  font-variant-numeric: tabular-nums;
}

.time-attack-result-best-time {
  margin: 0 0 18px;
  text-align: center;
  font-size: 0.82rem;
  opacity: 0.75;
}

.time-attack-result-best-time[hidden] {
  display: none;
}

/* ===== 平均回答時間・速度称号（電光石火・メロディアス）への進捗表示（2026-08-09新設） =====
   結果画面（イントロ／タイムアタック／ランダム再生）・履歴詳細モーダル・称号一覧カードの
   すべてから共通で使う（js/speedAchievementProgress.js参照）。 */
.average-response-time-display {
  margin: 0 0 8px;
  text-align: center;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

.average-response-time-display[hidden] {
  display: none;
}

/* 【2026-08-29追加】称号一覧・ランキングへの入口を横並びにする行（通常クイズ結果画面）。
   .rules-linkはdisplay:blockのままだと縦積みになるため、行だけflexにして横並びにする
   （見た目自体は.rules-linkの意匠をそのまま使う）。 */
.result-link-row {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.result-link-row .rules-link {
  margin: 0;
}

/* 【2026-08-29追加、本人指示（追加1・追加4）】合計タイム・平均回答時間（全問対象）・
   このモードの自己ベスト。既存の.average-response-time-displayと見た目の統一感を持たせつつ、
   別の指標であることが一目で分かるよう軽くカード状にまとめる。 */
.result-total-time-block {
  margin: 0 0 14px;
  padding: 10px 14px;
  border-radius: 14px;
  text-align: center;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
}

.result-total-time-block[hidden] {
  display: none;
}

.result-total-time-heading {
  margin: 0 0 4px;
  font-size: 0.72rem;
  font-weight: 700;
  opacity: 0.65;
}

.result-total-time-display,
.result-total-time-average-display {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

.result-total-time-best-display {
  margin: 6px 0 0;
  font-size: 0.78rem;
  opacity: 0.75;
}

.result-total-time-best-display[hidden] {
  display: none;
}

.speed-progress-block {
  margin: 0 0 14px;
  padding: 10px 14px;
  border-radius: 14px;
  text-align: center;
  background: var(--color-accent-soft);
  border: 1px solid rgba(255, 217, 61, 0.6);
}

.speed-progress-block:empty {
  display: none;
}

.speed-progress-block.is-achieved {
  background: var(--color-primary-light);
  border-color: rgba(255, 111, 168, 0.45);
}

.speed-progress-block.is-blocked {
  background: var(--color-surface-glass);
  border-color: var(--color-card-border);
}

.speed-progress-label {
  margin: 0 0 2px;
  font-size: 0.68rem;
  opacity: 0.65;
}

.speed-progress-line {
  margin: 0;
  font-size: 0.92rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.speed-progress-block.is-blocked .speed-progress-line {
  color: var(--color-text);
}

.speed-progress-sub {
  margin: 2px 0 0;
  font-size: 0.8rem;
  font-weight: 700;
  opacity: 0.85;
}

.speed-progress-block--best {
  margin: 10px 0 0;
}

/* 結果画面のボタン群（2026-08-06変更）：①もう一度挑戦する（主）②タイムアタック設定へ戻る（副）を
   縦並びにし、両方とも同じ横幅にする（.secondary-buttonは本来flex:1で横並びの行の中で使う想定の
   クラスだが、flex:noneで打ち消し、縦並びの列の中でも幅いっぱいに広がるようにしている）。
   スマホで指が近づきすぎないよう、間隔は16pxを確保した。 */
.time-attack-result-actions {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 18px;
}

.time-attack-result-actions .primary-button {
  margin-top: 0; /* .primary-button本来のmargin-topは、行の先頭に来る前提の値なのでここでは打ち消す */
}

.time-attack-result-setup-button {
  flex: none;
  padding: 14px; /* 「もう一度挑戦する」と同程度の押しやすさになるよう、通常のsecondary-buttonより大きめにする */
  font-size: 0.95rem;
}

/* タイムアタック設定画面の「タイムアタック履歴」ボタン。開始ボタンより控えめな2番手の扱いにする */
.time-attack-history-link {
  margin-top: 10px;
}

/* ===== タイムアタック履歴 一覧・詳細画面（2026-08-06新設） =====
   一覧のカード構造（.history-entry系）は、通常プレイ履歴（プレイ履歴画面）のスタイルを
   そのまま流用し、タイムアタック特有の項目（タイム・正解/ミス・失敗表示）だけ専用クラスを足す。 */
.time-attack-history-entry-time {
  margin: 2px 0 0;
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
}

.time-attack-history-entry-stats {
  margin: 1px 0 0;
  font-size: 0.75rem;
  opacity: 0.7;
  font-variant-numeric: tabular-nums;
}

/* LOVE連チャンで全問クリアできずに終了した回の「失敗」マーク。
   新記録マーク（.history-new-record-mark、ピンク系）とは対照的に、赤系にして一目で区別できるようにする。 */
.time-attack-history-fail-mark {
  font-size: 0.68rem;
  font-weight: 800;
  color: var(--color-danger);
}

/* 詳細画面のサマリー部分は、通常プレイ履歴の.history-detail-summaryをそのまま流用し、
   合計タイム・正解/ミスの2項目だけ結果画面と同じ.time-attack-result-*クラスを流用する。 */
.time-attack-history-detail-summary {
  padding: 14px;
  border-radius: 16px;
  margin: 12px 0 16px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  text-align: center;
}

.time-attack-history-detail-summary .time-attack-result-total-time {
  font-size: 1.6rem;
  margin: 6px 0 12px;
}

.time-attack-history-detail-summary .history-new-record-mark {
  display: block;
  margin-top: 4px;
}

#time-attack-history-detail-fail-status {
  display: block;
  margin: 4px 0 0;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-danger);
}

#time-attack-history-detail-fail-status[hidden],
#time-attack-history-detail-new-record[hidden] {
  display: none;
}

.time-attack-history-detail-question-list {
  list-style: none;
  padding: 0;
  margin: 4px 0 0;
}

.time-attack-history-detail-question-row {
  padding: 10px 4px;
  border-top: 1px solid var(--color-card-border);
}

.time-attack-history-detail-question-row:first-child {
  border-top: none;
}

.time-attack-history-detail-question-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 3px;
}

.time-attack-history-detail-question-number {
  font-size: 0.75rem;
  color: var(--color-text);
  opacity: 0.55;
  font-variant-numeric: tabular-nums;
}

/* 正解/不正解のタグ。プレイ履歴詳細の.history-detail-answer-tagと同じ色分けにしている */
.time-attack-history-detail-question-tag {
  display: inline-flex;
  align-items: center;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  white-space: nowrap;
}

.time-attack-history-detail-question-tag.is-correct {
  background: var(--color-accent-soft);
  color: var(--color-primary-dark);
}

.time-attack-history-detail-question-tag.is-wrong {
  background: var(--color-danger-soft);
  color: var(--color-danger);
}

.time-attack-history-detail-question-answer {
  margin: 0 0 2px;
  font-size: 0.85rem;
  font-weight: 700;
}

.time-attack-history-detail-question-choices,
.time-attack-history-detail-question-selected {
  margin: 0 0 2px;
  font-size: 0.76rem;
  opacity: 0.75;
  word-break: break-word;
}

.time-attack-history-detail-question-meta {
  display: flex;
  gap: 10px;
  margin-top: 3px;
  font-size: 0.72rem;
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
}

/* ===== タイムアタック：グローバルランキング（TOP10、2026-08-07新設） =====
   推しアイコン・王冠/ダイヤ装飾は.fan-profile-swatch（js/fanProfileCard.jsのbuildOshiSwatch）を
   そのまま再利用しているため、ここでは順位バッジ・行レイアウト・タブだけを定義する。 */
.leaderboard-tab-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 10px 0;
}

.leaderboard-tab-button {
  padding: 7px 14px;
  border-radius: 999px;
  border: 1.5px solid var(--color-card-border);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.leaderboard-tab-button.is-active {
  color: #fff;
  background: linear-gradient(120deg, var(--color-primary), var(--color-primary-dark));
  border-color: transparent;
  box-shadow: 0 4px 10px -4px rgba(255, 79, 150, 0.5);
}

.leaderboard-tab-button:active {
  transform: scale(0.96);
}

.leaderboard-state-note {
  text-align: center;
  padding: 24px 12px;
  color: var(--color-text);
  opacity: 0.7;
  font-size: 0.85rem;
}

.leaderboard-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}

/* 【2026-08-16バグ修正】display:flexを指定すると、ブラウザ標準のhidden属性（display:noneの
   はずが上書きされてしまい効かなくなる。JS側でelements.listContainer.hidden = trueを
   設定しても実際には非表示にならず、出題タイプ切り替え直後に前のタブのTOP10行が
   一瞬〜そのまま残って見えてしまうバグの直接原因だった。hidden属性が付いているときは
   確実にdisplay:noneへ戻すことで、JS側のhidden切り替えを正しく機能させる。 */
.leaderboard-list[hidden] {
  display: none;
}

.leaderboard-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 14px;
  border: 1px solid var(--color-card-border);
  background: var(--color-surface);
}

/* 自分の行だけ、ピンク枠で識別できるようにする（本人指示）。 */
.leaderboard-row.is-own-row {
  border: 2px solid var(--color-primary);
  background: var(--color-primary-light);
}

.leaderboard-rank-badge {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--color-text);
  background: rgba(74, 46, 66, 0.08);
  font-variant-numeric: tabular-nums;
}

/* 上位3人（金・銀・銅）。派手すぎない程度の彩度に抑える（本人指示）。 */
.leaderboard-rank-badge.is-gold {
  color: #7a5300;
  background: linear-gradient(145deg, #ffe9a8, #ffcf4d);
}

.leaderboard-rank-badge.is-silver {
  color: #52565c;
  background: linear-gradient(145deg, #eef0f2, #c9ced4);
}

.leaderboard-rank-badge.is-bronze {
  color: #6b3a1c;
  background: linear-gradient(145deg, #e8b78a, #cd8a53);
}

.leaderboard-row-body {
  flex: 1;
  min-width: 0; /* 表示名が長い場合に2行折り返しさせるため、flexアイテムの最小幅制限を外す */
}

.leaderboard-row-name {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 800;
  color: var(--color-text);
  word-break: break-word; /* 表示名が1行に収まらない場合は2行にしてよい（本人指示）。タイムは絶対に切らない */
}

.leaderboard-row-oshi {
  margin: 2px 0 0;
  font-size: 0.72rem;
  opacity: 0.7;
}

/* プレイ方法・ルールの小さなバッジ（2026-08-16追加）。rank/name/timeより目立たせない
   参考情報として、行の下にごく小さく添えるだけにとどめる（本人指示セクション13）。 */
.leaderboard-row-meta {
  margin: 2px 0 0;
  font-size: 0.68rem;
  opacity: 0.55;
}

/* 管理者にだけ出す「ID末尾／登録日」（2026-09-22追加。同一人物の重複整理で見た目が同じ2行を区別するため） */

/* クリアタイムと平均タイムを縦に並べて右端にまとめる箱（2026-08-24追加）。
   .leaderboard-rowのalign-items:centerで箱ごと縦中央に来るので、中はtop寄せでよい。 */
.leaderboard-row-time-block {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
}

.leaderboard-row-time {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
  white-space: nowrap; /* タイムは横スクロールなしで絶対に切れないようにする（本人指示） */
}

/* 1問あたりの平均タイム。クリアタイムより控えめに、小さく添える（本人指示：
   デザインを大きく変えず、クリアタイム周辺に小さく追加する程度に） */
.leaderboard-row-average {
  margin: 0;
  font-size: 0.65rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.55;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* 管理者専用のランキング記録削除ボタン（2026-08-17追加）。一般ユーザーには
   このボタン自体が生成されないため、ここは常に管理者だけが目にするスタイル。 */
.leaderboard-admin-delete-button {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid rgba(220, 53, 69, 0.35);
  background: rgba(220, 53, 69, 0.08);
  font-size: 0.85rem;
  line-height: 1;
  cursor: pointer;
}

.leaderboard-admin-delete-button:active {
  transform: scale(0.95);
}

/* ランキング記録削除の確認モーダル内、削除対象の要約表示（プレイヤー名・記録・
   モード・ルール・問題数・カテゴリー、本人指示で全項目を確認画面に出す）。 */
.leaderboard-admin-delete-summary {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 10px;
  margin: 12px 0;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--color-primary-light);
  font-size: 0.82rem;
}

.leaderboard-admin-delete-summary div {
  display: contents;
}

.leaderboard-admin-delete-summary dt {
  color: var(--color-text);
  opacity: 0.65;
}

.leaderboard-admin-delete-summary dd {
  margin: 0;
  font-weight: 700;
  color: var(--color-text);
  word-break: break-word;
}

.leaderboard-my-record {
  margin-top: 14px;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--color-surface-glass);
  border: 1px dashed var(--color-primary);
  text-align: center;
}

#time-attack-leaderboard-my-record-text {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

/* 結果画面のランキング送信状況（成功/失敗/非公開/オフライン）。控えめな注記として表示する。 */
.time-attack-result-leaderboard-status {
  margin: 8px 0 0;
  font-size: 0.78rem;
  text-align: center;
  opacity: 0.85;
}

.time-attack-result-leaderboard-status[hidden] {
  display: none;
}

/* ===== オンライン対戦：出題する曲の選択（2026-08-08新設） =====
   曲選択画面自体（.single-group系・.song-select-row等）は、オリジナル問題作成モードの
   選曲画面と完全に同じグローバルクラスをそのまま再利用しているため、ここでは
   ロビー内の小さな「曲を選ぶ」ボタン行だけを定義する。 */
.battle-manual-song-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  margin-top: 8px;
}

/* display:flexを明示指定しているため、[hidden]の既定（display:none）を上書きしてしまう分の
   対策（12章の教訓：.song-select-row[hidden]と同じパターン）。 */
.battle-manual-song-row[hidden] {
  display: none;
}

/* 2026-08-27新設：「全曲から選ぶ／お気に入り／プレイリスト」の3ボタンを横並びにする入れ物。
   スマホ幅で3つ並べると窮屈になるため、折り返しを許可する（flex-wrap）。 */
.battle-song-source-button-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.battle-manual-song-row .secondary-button {
  flex: none;
  width: auto;
  padding: 8px 16px;
  font-size: 0.82rem;
}

.battle-manual-song-count {
  margin: 0;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

/* 2026-09-14新設・本人指示：共同選曲の「誰がどの曲を選んだか」「共有曲一覧」を
   開閉式で確認できるようにするための見た目。既存の.song-picker-sticky-toggleと
   似た軽いテキストボタンにし、パネル自体はカードっぽく囲って情報の塊として見せる。 */
.song-picker-review-toggle {
  align-self: flex-start;
  background: none;
  border: none;
  padding: 4px 0;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-primary);
  cursor: pointer;
}

.online-battle-collab-details-panel {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
}

/* .battle-manual-song-row同様、display:flexを明示指定しているクラスは[hidden]の既定
   （display:none）を上書きしてしまうため、明示的な上書きが必要
   （このプロジェクトで繰り返し踏んでいるCSS詳細度の既知パターン）。 */
.online-battle-collab-details-panel[hidden] {
  display: none;
}

.online-battle-collab-breakdown-empty {
  margin: 0;
  font-size: 0.78rem;
  color: var(--color-text);
  opacity: 0.7;
}

.online-battle-collab-breakdown-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.online-battle-collab-breakdown-row {
  padding: 8px 10px;
  border-radius: 10px;
  /* 2026-09-26改訂・本人指示：オンライン対戦総合改修19-1章。以前は中立グレー背景
     （--color-surface）で、共有曲一覧側のピンク基調のデザインと浮いて見えていた。
     ごく薄いピンクの背景に変え、「同じ画面内の同じ選曲情報」と分かる統一感を持たせる。 */
  background: var(--color-primary-light);
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.online-battle-collab-breakdown-name {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.online-battle-collab-breakdown-songs {
  /* 2026-09-26改訂・本人指示：以前は「、」区切りの1本のテキストだったが、共有曲一覧と
     同じ「曲名＝丸いチップ」という見た目の言語に揃えるため、曲ごとに個別のチップへ分割する。 */
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.online-battle-collab-breakdown-songs-empty {
  font-size: 0.74rem;
  color: var(--color-text);
  opacity: 0.6;
}

.online-battle-collab-breakdown-song-chip {
  /* 【2026-09-30改訂・本人指示：オンライン対戦総合改修 第2ラウンド4章】以前は「参加者ごとの
     選択」だけ縁取りのチップにして、共有曲一覧（.online-battle-collab-song-chip、塗りつぶし）
     とわずかに見た目を変えていたが、「完全に統一してほしい」との指示により、
     .online-battle-collab-song-chipと全く同じ塗りつぶしスタイルへ揃えた。 */
  padding: 3px 10px;
  border-radius: 999px;
  border: 1.5px solid transparent;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-size: 0.74rem;
  font-weight: 700;
  max-width: 100%;
  overflow-wrap: break-word;
}

.online-battle-collab-song-chip-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.online-battle-collab-song-chip {
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--color-primary-light);
  border: 1.5px solid transparent;
  color: var(--color-primary-dark);
  font-size: 0.74rem;
  font-weight: 700;
  max-width: 100%;
  overflow-wrap: break-word;
}

/* 【2026-09-15新設・本人指示：ルール確認画面に出題対象曲一覧を追加】
   .song-picker-review-toggleと同じ軽いテキストボタンの見た目に揃える。 */
.online-battle-confirm-song-list-toggle {
  align-self: flex-start;
  background: none;
  border: none;
  padding: 4px 0;
  margin-top: 4px;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-primary);
  cursor: pointer;
  width: auto;
  min-height: 0;
}

.online-battle-confirm-song-list-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 6px;
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
}

/* display:flexを明示指定しているクラスは[hidden]の既定表示を上書きしてしまうため、
   明示的な上書きが必要（このプロジェクトで繰り返し踏んでいるCSS詳細度の既知パターン）。 */
.online-battle-confirm-song-list-panel[hidden] {
  display: none;
}

.online-battle-confirm-song-list-heading {
  margin: 0;
  font-size: 0.76rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

/* カテゴリー対象外だが選択状態が保存されている曲の見出し。「今回は出ない」ことが
   ひと目で分かるよう、有効な出題対象曲の見出しとは明確に色味を分ける
   （危険色の赤ではなく、注意喚起の中間トーン）。 */
.online-battle-confirm-song-list-heading-excluded {
  margin-top: 4px;
  color: var(--color-text);
  opacity: 0.7;
}

/* 2026-08-27新設：参加者全員が実際に利用できる共通曲の数を知らせる注意書き
   （js/onlineBattleScreen.js・js/onlineLyricsQuizBattleScreen.js参照）。
   「制限が発生している」ことを伝えるための表示なので、目立ちすぎない黄色系にする
   （エラーではなく、あくまで情報提供のため.error-message等の赤系は使わない）。 */
.battle-common-song-notice {
  margin: 6px 0 0;
  padding: 8px 12px;
  border-radius: 12px;
  background: var(--color-accent-soft);
  color: var(--color-text);
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1.6;
}

/* 共通曲が0曲（対戦を開始できない）ときは、はっきり注意を引く赤系にする。 */
.battle-common-song-notice.is-empty {
  background: var(--color-danger-soft);
  color: var(--color-danger);
}

/* ===== オンライン対戦：プレイリストから選ぶモーダル（2026-08-27新設） =====
   #add-to-playlist-modalの一覧（.add-to-playlist-list）をそのまま流用し、
   行だけボタン要素として独自定義する（あちらはプレイリストへ「追加」する行、
   こちらはプレイリストを「選ぶ」行で役割が違うため）。 */
.online-battle-playlist-picker-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  width: 100%;
  padding: 10px 14px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 14px;
  background: var(--color-surface);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.online-battle-playlist-picker-row:disabled {
  opacity: 0.5;
  cursor: default;
}

.online-battle-playlist-picker-name {
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.online-battle-playlist-picker-count {
  font-size: 0.76rem;
  color: var(--color-primary-dark);
}

/* ===== 対戦モード（ローカル対戦、2026-08-06新設） =====
   モックアップ（dev/battleModeMockup.html）で検証済みの見た目を、実アプリのcss/style.cssに
   移植したもの。既存のクラス（.primary-button・.secondary-button・.special-mode-card等）を
   なるべく流用し、対戦モード特有の見た目だけをここに追加している。 */
.battle-mode-select-row {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 16px;
}

.battle-mode-big-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  width: 100%;
  padding: 20px;
  border-radius: 18px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  box-shadow: var(--shadow-card);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: transform var(--transition-fast) cubic-bezier(0.34, 1.56, 0.64, 1);
}

.battle-mode-big-card:active {
  transform: scale(0.98);
}

.battle-mode-big-card-icon {
  font-size: 1.6rem;
}

.battle-mode-big-card-title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.battle-mode-big-card-desc {
  margin: 0;
  font-size: 0.8rem;
  opacity: 0.75;
}

.battle-code-display {
  margin: 16px 0;
  padding: 20px 12px;
  border-radius: 16px;
  background: var(--color-surface);
  border: 2px dashed var(--color-primary);
  text-align: center;
}

.battle-code-value {
  margin: 0;
  font-size: 1.3rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
  word-break: break-all;
}

.battle-config-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 12px 0;
}

/* 【2026-09-08新設・本人指示O：現在のルールの簡単説明】チップ一覧の下に添える、
   選択中ルールの1〜2文の説明。ホストの設定画面（.lyrics-battle-rule-option-description等）
   より控えめに、しかしチップより読みやすいサイズにする。 */
.battle-rule-description {
  margin: -6px 0 12px;
  font-size: 0.78rem;
  line-height: 1.5;
  opacity: 0.75;
}

.battle-rule-description:empty {
  display: none;
}

/* 【2026-09-09新設・本人指示：ロビー専用の詳細説明書】タイトルと「？」ボタンを
   横並びにする、汎用のヘッダー行。 */
.online-lobby-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

/* 【2026-11-XX追加・本人指示：優先度11「？」ボタンの強化】.secondary-buttonの既定は
   flex:1（横幅いっぱいに伸びる想定）だが、ここではタイトル横に収まる大きさで十分。
   小さすぎた旧「？」丸ボタンより確実に押しやすいサイズは保ちつつ、行全体を占領しない
   ようflex:noneで幅を文字数なりに戻す。 */
.online-battle-lobby-help-button {
  flex: none;
  padding: 8px 14px;
  font-size: 0.78rem;
  white-space: nowrap;
}

.online-lobby-help-section-heading {
  margin: 18px 0 8px;
  font-size: 0.8rem;
  font-weight: 800;
  opacity: 0.7;
}

.online-lobby-help-current-mode {
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  margin: 0 0 4px;
}

/* 2026-09-14新設・本人指示：「順位の決まり方」見出し。本体（.online-lobby-help-current-mode）
   より一回り小さくし、直後のルール説明文とセットで視認できるよう上に余白を空ける。 */
.online-battle-ranking-heading {
  font-size: 0.85rem;
  margin-top: 10px;
}

.online-lobby-help-current-description {
  font-size: 0.82rem;
  opacity: 0.75;
  margin: 0 0 10px;
}

.online-lobby-help-mode-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* 【2026-11-XX全面改訂・本人指示：優先度3「ルール・遊び方」の内容拡充】以前は名前＋
   一行説明だけの静的なカードだったが、6モードそれぞれを<details>アコーディオンにし、
   開くと詳しい説明（遊び方・回答方法・勝敗条件・得点・出題数・共同選曲・注意点）が
   読めるようにした。閉じている間は名前＋一行説明だけで、以前と同じ省スペースな
   見た目のまま一覧できる。 */
.online-lobby-help-mode-item {
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--color-surface);
  border: 1px solid var(--color-card-border);
  margin-bottom: 8px;
}

.online-lobby-help-mode-item-summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  flex-direction: column;
}

.online-lobby-help-mode-item-summary::-webkit-details-marker {
  display: none;
}

/* 開閉状態が一目で分かるよう、summaryの右に矢印を添える（本人指示の「独立した
   セクション/カード/アコーディオン等」を、既存のdetails/summaryパターンで実現）。 */
.online-lobby-help-mode-item-summary::after {
  content: "▾ タップして詳しく見る";
  align-self: flex-start;
  margin-top: 4px;
  font-size: 0.68rem;
  color: var(--color-primary-dark);
  opacity: 0.7;
}

.online-lobby-help-mode-item[open] > .online-lobby-help-mode-item-summary::after {
  content: "▴ 閉じる";
}

.online-lobby-help-mode-item-name {
  font-weight: 800;
  font-size: 0.85rem;
}

.online-lobby-help-mode-item-description {
  font-size: 0.78rem;
  opacity: 0.75;
  margin-top: 2px;
}

.online-lobby-help-mode-item.is-current {
  border-color: var(--color-primary);
  background: var(--color-primary-light);
}

.online-lobby-help-mode-item-body {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed var(--color-card-border);
}

.online-lobby-help-detail-list {
  margin: 0;
}

.online-lobby-help-detail-list dt {
  font-size: 0.76rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  margin: 10px 0 3px;
}

.online-lobby-help-detail-list dt:first-child {
  margin-top: 0;
}

.online-lobby-help-detail-list dd {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.65;
  color: var(--color-text);
  /* 本文中の\nを改行として見せる（js/onlineBattleScreen.jsのbuildDetailList参照）。 */
  white-space: pre-line;
}

/* 歌詞クイズ対戦だけが持つ、3ルール（正解数/早押し/ポイントバトル）ぶんの小ブロック。 */
.online-lobby-help-rule-block {
  margin-top: 14px;
  padding: 10px 10px 4px;
  border-radius: 10px;
  background: var(--color-secondary-light);
}

.online-lobby-help-rule-block h4 {
  margin: 0 0 2px;
  font-size: 0.8rem;
  color: var(--color-text);
}

#online-battle-lobby-help-guide-link {
  width: 100%;
  margin-top: 18px;
}

.battle-config-chip {
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--color-secondary-light);
  font-size: 0.75rem;
  font-weight: 700;
  color: #2c6ea8;
}

.battle-notice-box {
  margin: 12px 0;
  padding: 12px 14px;
  border-radius: 12px;
  background: rgba(111, 189, 242, 0.12);
  border: 1px solid var(--color-secondary);
  font-size: 0.76rem;
  line-height: 1.6;
}

.battle-warning-box {
  margin: 12px 0;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--color-danger-soft);
  border: 1px solid var(--color-danger);
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-danger);
  line-height: 1.6;
}

.battle-warning-box[hidden] {
  display: none;
}

.battle-check-ok {
  margin: 12px 0;
  padding: 10px 14px;
  border-radius: 12px;
  background: var(--color-accent-soft);
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.battle-code-input {
  width: 100%;
  padding: 14px;
  border-radius: 14px;
  border: 2px solid var(--color-primary);
  background: var(--color-surface);
  font-family: inherit;
  font-size: 1.1rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-align: center;
  color: var(--color-text);
  box-sizing: border-box;
}

.battle-code-input::placeholder {
  color: rgba(74, 46, 66, 0.35);
  font-weight: 700;
}

.battle-field-label {
  display: block;
  margin: 14px 0 4px;
  font-size: 0.75rem;
  font-weight: 700;
  opacity: 0.7;
}

/* 【2026-09-02新設、本人指示：人数拡張】ルーム作成画面の「プレイヤー最大人数」セレクト用。
   ラベルとプルダウンを横並びにするが、狭い画面では折り返して縦積みにする
   （.battle-field-labelにmarginが付いているため、ここでは上書きしてrow内で詰めて揃える）。 */
.battle-field-label-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 14px 0 4px;
}

.battle-field-label-row .battle-field-label {
  margin: 0;
}

.battle-select-input {
  flex: 1;
  min-width: 120px;
  padding: 10px 14px;
  border-radius: 12px;
  border: 1.5px solid var(--color-card-border);
  background: var(--color-surface);
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--color-text);
  box-sizing: border-box;
}

.battle-player-name-input {
  width: 100%;
  padding: 10px 14px;
  border-radius: 12px;
  border: 1.5px solid var(--color-card-border);
  background: var(--color-surface);
  font-family: inherit;
  font-size: 0.9rem;
  color: var(--color-text);
  box-sizing: border-box;
}

/* 【2026-09-30新設・本人指示：オンライン対戦総合改修 第2ラウンド23-29章】結果画面の
   「ルーム設定に戻る」個別対応パネル・「もう一度」提案パネルで共通に使う枠。
   js/onlineBattleScreen.js・js/onlineLyricsQuizBattleScreen.js・
   js/onlineInstantBattleScreen.js・js/onlineInstantCoopBattleScreen.jsの結果画面すべてで
   同じクラスを再利用する（本人指示：共通処理は再利用する）。 */
.online-battle-result-return-panel {
  margin: 14px 0;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* 【2026-11-XX発見・修正・実機回帰バグの根本原因】display:flexを明示指定しているため、
   [hidden]の既定（display:none）を上書きしてしまう（.quiz-back-link[hidden]・
   .button-row[hidden]と全く同じ既知パターン、12章の教訓のはずが、このクラスだけ
   対応が漏れていた）。この上書きが無かったため、4画面すべての「もう一度」提案パネル
   （online-battle-result-rematch-panel／online-lyrics-battle-result-rematch-panel／
   online-instant-battle-result-rematch-panel／online-instant-coop-battle-result-rematch-panel）
   は、JS側がelements.resultRematchPanel.hidden=trueを正しく設定していても実際には
   非表示にならず、confirmingRematchが本当はfalseの間もHTMLの初期状態（＝ゲスト向けの
   「ホストが『もう一度』を選びました」文言＋「準備OK」ボタン）がそのまま見え続けていた。
   ホスト・ゲストのJS側ロジック（resolveRematchToggleButtonLabel等）は実際には正しく
   動作していたが、その結果がDOMに一切反映されない状態だったため、何度JS側を直しても
   実機では「直っていない」ように見えていた——これが再戦UIバグの真の根本原因。 */
.online-battle-result-return-panel[hidden] {
  display: none;
}

.online-battle-result-return-heading {
  margin: 0;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--color-text);
}

.online-battle-result-return-status-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.online-battle-result-return-status-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 0.78rem;
}

.online-battle-result-return-status-name {
  font-weight: 700;
  color: var(--color-primary-dark);
  min-width: 0;
  overflow-wrap: anywhere;
}

.online-battle-result-return-status-badge {
  flex: none;
  font-size: 0.66rem;
  font-weight: 800;
  padding: 3px 9px;
  border-radius: 999px;
}

.online-battle-result-return-status-badge.is-done {
  background: var(--color-accent-soft);
  color: var(--color-primary-dark);
}

.online-battle-result-return-status-badge.is-waiting {
  background: var(--color-danger-soft);
  color: var(--color-danger);
}

.battle-rank-list {
  list-style: none;
  margin: 16px 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.battle-rank-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
}

.battle-rank-row.is-rank-1 {
  background: linear-gradient(160deg, #ffe9a8, #fff2bf);
  border-color: var(--color-accent);
}

/* 【2026-09-09新設・本人指示2-6：結果画面のデザイン】2位・3位も、1位ほど目立たせずに
   軽く装飾する（銀・銅を連想させる控えめなトーン。＝LOVEのピンク系パレットから外れない
   範囲でグレー・オレンジ味を少しだけ足す程度に留める）。 */
.battle-rank-row.is-rank-2 {
  background: linear-gradient(160deg, #eef0f4, #f8f9fb);
  border-color: #b8c0cc;
}

.battle-rank-row.is-rank-3 {
  background: linear-gradient(160deg, #f3e2d3, #faf1e8);
  border-color: #d3a87c;
}

.battle-rank-medal {
  flex: none;
  font-size: 1.3rem;
  width: 30px;
  text-align: center;
}

.battle-rank-info {
  flex: 1;
  min-width: 0;
}

/* 【2026-09-13改訂・本人指示8：結果画面の参加者名・文字デザインを改善】以前は既定の
   文字色・サイズのままで、ゲーム画面としてはやや素っ気なかった。名前をやや大きく・
   ブランドカラーに寄せることで、結果画面全体の「賑やかさ」を底上げする（本人指示の
   恒久ルール：新しいUIは＝LOVEクイズアプリ全体の見た目に合わせてから完成とすること）。 */
.battle-rank-name {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  letter-spacing: 0.01em;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}

/* 【2026-09-26新設・本人指示：オンライン対戦総合改修19-15章】結果画面の名前も
   タップしてプロフィールを開けるようにする。js/onlineBattleScreen.jsの
   .online-lobby-player-name-buttonと同じ、ボタン化リセット＋押せる見た目。 */
/* 結果画面で「自分の行」だとひと目でわかる、名前の横に添える小さいバッジ。
   名前の文字列に直接連結すると、表示名が長い参加者で2行に折り返りやすくなるため、
   独立したバッジ要素として分けている（本人の指摘、2026-08-08）。 */
.battle-rank-me-badge {
  flex: none;
  font-size: 0.62rem;
  font-weight: 800;
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--color-accent-soft);
  color: var(--color-primary-dark);
  white-space: nowrap;
}

.battle-rank-meta {
  margin: 2px 0 0;
  font-size: 0.7rem;
  opacity: 0.7;
}

.battle-rank-time {
  flex: none;
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* ノーマルルールの結果行だけ、最終記録（ペナルティ込み）とその内訳を2行で表示する。 */
.battle-rank-time-final {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
}

.battle-rank-time-breakdown {
  margin: 2px 0 0;
  font-size: 0.62rem;
  font-weight: 600;
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* 対戦の設定画面・ルール確認画面で、選んだルールの勝敗条件を短く案内する。 */
.battle-rule-hint {
  margin: 10px 0 0;
  padding: 10px 12px;
  border-radius: 10px;
  background: rgba(111, 189, 242, 0.1);
  font-size: 0.72rem;
  line-height: 1.5;
  opacity: 0.85;
}

.battle-collect-list {
  list-style: none;
  margin: 12px 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.battle-collect-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--color-surface-glass);
  font-size: 0.8rem;
}

.battle-collect-row-name {
  font-weight: 700;
}

.battle-collect-row-check {
  color: var(--color-primary-dark);
  font-weight: 800;
}

.battle-progress-label {
  margin: 10px 0 4px;
  font-size: 0.8rem;
  font-weight: 700;
  text-align: center;
}

/* ===== オンライン対戦（Firebase）画面 ===== */

.online-battle-lead-text {
  font-size: 0.82rem;
  line-height: 1.6;
  opacity: 0.75;
  margin: 0 0 16px;
}

/* 【2026-11-XX追加・本人指示：結果/再戦フロー最終仕様】「同じ条件でもう一度」ボタンの
   下に添える、何が起きるかの補足説明。親の.button-rowはdisplay:flex（横並び）のため、
   flex-basis:100%でボタンの下に自分の行として折り返させる。
   【2026-11-XX修正・実機バグ調査：ボタンが縦長に潰れる】親の.button-rowはnowrap（既定値）
   のままだったため、「ボタン（flex-basis:0）＋この説明文（flex-basis:100%）」の合計が
   コンテナ幅を超え、flexの縮小計算でボタン側の実際の幅がほぼ0まで押しつぶされ、
   「同じ条件でもう一度」の文字が1文字ずつ縦に折り返される不具合が実機で発生していた。
   .button-rowは他の画面で「ボタン2つを横並びにする」用途にも広く使われているため、
   グローバルにflex-wrapを変えるのではなく、この説明文を持つ組み合わせを使う
   #online-battle-result-host-actionsだけへ限定してflex-wrap:wrapを指定する。 */
#online-battle-result-host-actions {
  flex-wrap: wrap;
}

.online-battle-result-rematch-hint {
  flex-basis: 100%;
  margin: 4px 0 0;
  font-size: 0.76rem;
  line-height: 1.5;
  opacity: 0.7;
  text-align: center;
}

.online-lobby-player-count {
  text-align: center;
  font-size: 0.85rem;
  font-weight: 800;
  margin: 12px 0 0;
}

.online-lobby-max-players {
  text-align: center;
  font-size: 0.7rem;
  opacity: 0.6;
  margin: 2px 0 14px;
}

/* 対戦モードは作成後に変更できないため、常に見える控えめな表示にする（2026-08-08新設）。
   .online-lobby-max-playersのすぐ下に並ぶ想定で、隣接するmargin同士はCSSの仕様上
   大きい方（14px）だけが有効になるため、二重の余白にはならない。 */
.online-lobby-game-mode {
  text-align: center;
  font-size: 0.7rem;
  opacity: 0.6;
  margin: 2px 0 14px;
}

.online-lobby-player-list {
  list-style: none;
  margin: 0 0 16px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.online-lobby-player-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
}

/* 【2026-08-30新設、本人指示】ホスト専用の「キック」「ホストを渡す」ボタンの並び。
   名前・バッジと同じ行に収まらない場合は、行の右端に折り返す
   （.online-lobby-player-rowのflex-wrapと組み合わせて、狭い画面でも崩れないようにする）。 */
.online-lobby-player-actions {
  flex: none;
  display: flex;
  gap: 6px;
  margin-left: auto;
}

.online-lobby-mini-button {
  font-size: 0.68rem;
  font-weight: 700;
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid var(--color-card-border);
  background: var(--color-surface);
  color: var(--color-text);
  white-space: nowrap;
}

.online-lobby-mini-button:active {
  transform: scale(0.96);
}

.online-lobby-mini-button-danger {
  border-color: var(--color-danger);
  color: var(--color-danger);
  background: var(--color-danger-soft);
}

.online-lobby-player-row.is-me {
  border-color: var(--color-accent);
  background: var(--color-accent-soft);
}

.online-lobby-player-oshi-dot {
  flex: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  /* 白い内枠で推しカラーの発色をくっきりさせ、外側にピンク系のリングを添えて
     「推しカラー」であることが一目で伝わるようにする（メンバー紹介ページの
     色見本 .color-swatch-dot と同じ考え方で、球体風の立体感も加えている）。 */
  border: 2px solid #fff;
  box-shadow:
    0 0 0 1.5px var(--color-primary-light),
    0 2px 4px -1px rgba(0, 0, 0, 0.25),
    inset 0 -2px 3px rgba(0, 0, 0, 0.15);
}

/* 【2026-09-13改訂・本人指示12：ロビー参加者名のフォント改善】結果画面の名前
   （.battle-rank-name）と同じ考え方で、ブランドカラーに寄せて少し華やかにする。 */
.online-lobby-player-name {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  min-width: 0;
  overflow-wrap: anywhere;
}

/* 【2026-09-05新設・本人指示：一瞬協力結果画面「メンバーの活躍」】各自の正解選択数
   （X / 総問題数問）。.online-lobby-player-actions（キック等のボタン群）と同じ
   margin-left: autoで、行の右端へ寄せる。 */
.online-lobby-player-stat {
  flex: none;
  margin-left: auto;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  opacity: 0.85;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* 【2026-09-07新設・本人指示：ルーム参加者プロフィール】名前をタップして簡易プロフィールを
   見られることが分かるよう、ボタン化した分のリセット＋押せる見た目を追加する。
   マージンをマイナスにしてタップ領域だけ広げ、周囲のレイアウト（行の高さ・間隔）は
   今までどおりに保つ（実機での押しにくさ対策、本人指示の完成基準に合わせた調整）。 */
.online-lobby-player-name-button {
  background: none;
  border: none;
  padding: 4px 2px;
  margin: -4px -2px;
  /* 【2026-10-01修正・実機バグ調査】以前はここを`font: inherit`（ショートハンド）に
     していたが、これはfont-family・font-sizeだけでなくfont-weightまで親要素からの
     継承値へ一括で上書きしてしまう。同じ要素に付く.online-lobby-player-name側の
     font-weight: 700・color指定と詳細度が同点で、CSSの記述順で後にあるこちらが
     勝つため、参加者名が「ピンクだが細字」（実機で報告された状態）や「黒っぽい細字」
     （前回のバグ）になっていた。ボタン化のリセットとしてfont-familyだけを継承し、
     font-weight・font-size・colorには一切触れないことで、
     .online-lobby-player-name側の指定がそのまま反映されるようにする。 */
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  border-radius: 6px;
  text-decoration: underline;
  text-decoration-color: rgba(0, 0, 0, 0.2);
  text-underline-offset: 2px;
}

.online-lobby-player-name-button:active {
  background: rgba(0, 0, 0, 0.06);
}

.online-lobby-player-badges {
  flex: none;
  display: flex;
  gap: 6px;
}

.online-lobby-badge {
  font-size: 0.62rem;
  font-weight: 800;
  padding: 3px 8px;
  border-radius: 999px;
  white-space: nowrap;
}

.online-lobby-badge-host {
  background: var(--color-accent);
  color: var(--color-primary-dark);
}

.online-lobby-badge-connected {
  background: var(--color-accent-soft);
  color: var(--color-primary-dark);
}

.online-lobby-badge-disconnected {
  background: var(--color-danger-soft);
  color: var(--color-danger);
}

/* 【2026-09-05新設】在席確認システムのバッジ（js/onlineBattlePresence.js）。
   「在席確認中」は黄系（まだ様子見の段階）、「離席中」は赤系（切断中と同じ危険度合い）
   で色分けし、テキストラベルで意味の違いを明示する。 */
.online-lobby-badge-presence-checking {
  background: var(--color-accent-soft);
  color: var(--color-primary-dark);
}

.online-lobby-badge-presence-away {
  background: var(--color-danger-soft);
  color: var(--color-danger);
}

/* 【2026-09-05新設】在席確認中に画面下部へ出す、控えめなバナー。どこをタップしても
   （バナー自体を含め）js/onlineBattlePresence.jsのdocument全体のイベント監視が拾って
   自動的に消えるため、閉じるボタンは持たせていない。 */
.online-presence-checking-banner {
  position: fixed;
  left: 12px;
  right: 12px;
  /* 【2026-11-XX修正・仕様総監査で発見】他の下部固定UI（.mini-player・
     .song-picker-sticky-bar等）はenv(safe-area-inset-bottom)を考慮しているのに、
     このバナーだけ固定12pxのままだった。ホームインジケーターのある端末では
     画面最下端に近すぎるため、同じ考え方で安全マージンを確保する。 */
  bottom: max(12px, env(safe-area-inset-bottom));
  z-index: 500;
  padding: 12px 16px;
  border-radius: 14px;
  background: var(--color-primary-dark);
  color: #fff;
  font-size: 0.8rem;
  font-weight: 700;
  text-align: center;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.2);
}

/* ===== オンライン対戦Step2：ロビーの対戦設定・準備完了・開始まわり ===== */

.online-battle-ready-changed-notice {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-danger);
  background: var(--color-danger-soft);
  border-radius: 10px;
  padding: 8px 12px;
  margin: 10px 0;
}

.online-battle-start-hint {
  font-size: 0.75rem;
  opacity: 0.7;
  text-align: center;
  margin: 8px 0 0;
}

.online-battle-countdown-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: 60vh;
}

.online-battle-countdown-label {
  font-size: 0.9rem;
  opacity: 0.7;
}

.online-battle-countdown-number {
  font-size: 5rem;
  font-weight: 800;
  color: var(--color-accent);
}

/* 【2026-09-16修正・本人指摘：一瞬バトルと同じチラつきパターン】以前はここに
   `animation: ... infinite`を直接指定しており、数字が変わらない間も1秒ごとに
   無関係な拍動を繰り返してチラついて見えていた。js/localReplayCountdown.jsで採用した
   「数字が切り替わった瞬間だけis-tickingクラスを付け直して1回だけ再生」という
   恒久ルール準拠の方式に合わせた（js/onlineBattleScreen.jsのtick()参照）。 */
.online-battle-countdown-number.is-ticking {
  animation: online-battle-countdown-pulse 1s ease-in-out;
}

@keyframes online-battle-countdown-pulse {
  0% { transform: scale(0.85); opacity: 0.6; }
  30% { transform: scale(1.05); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* 【2026-09-05新設】各問題の音源再生直前に出す、軽量な3→2→1（js/localReplayCountdown.js）。
   上のonline-battle-countdown-*（対戦開始・1回きり・60vh確保）と違い、問題画面の一部として
   何度も出し入れするため、コンパクトなサイズ・余白にしている。数字の演出（拍動）は
   既存のonline-battle-countdown-pulseをそのまま再利用し、見た目の一貫性を保つ。 */
.local-replay-countdown {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 20px 0;
}

/* display:flexをクラスセレクタで持つ要素は、hidden属性のデフォルト表示（display:none）より
   詳細度が高く上書きしてしまう（既知のバグパターン、.lyrics-quiz-answer-reveal[hidden]等と
   同じ理由）。将来hidden=trueで隠す使い方をしても正しく隠れるよう保険を付けておく。 */
.local-replay-countdown[hidden] {
  display: none;
}

/* ===== 対戦開始前ルール確認画面（2026-09-13新設・本人指示） ===== */

.online-battle-confirm-rule-box {
  padding: 16px 18px;
  border-radius: 16px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  margin: 12px 0 4px;
}

.online-battle-confirm-all-done-notice {
  margin: 14px 0;
  padding: 12px 14px;
  border-radius: 12px;
  text-align: center;
  font-size: 0.85rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background: var(--color-accent-soft);
  border: 1px solid var(--color-accent);
  /* 【本人指示32：現れた瞬間だけ華やかに、その後は静止】1回だけポップして、そのまま
     静止する（歌詞クイズの答え合わせ点滅バグの反省を踏まえ、infiniteループは使わない）。 */
  animation: answerRevealPop 320ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* 確認OKボタン：押した後は済んでいることが一目でわかるよう配色を変える（トグル式のため、
   もう一度押せば解除できることも見た目から伝わるよう、押しやすい主要ボタンのまま維持）。 */
#online-battle-confirm-toggle-button.is-confirmed {
  background: var(--color-accent-soft);
  color: var(--color-primary-dark);
  border-color: var(--color-accent);
}

.online-battle-confirm-cancel-button {
  display: block;
  margin: 10px auto 0;
}

.local-replay-countdown-number {
  font-size: 3rem;
  font-weight: 800;
  color: var(--color-accent);
}

/* 【2026-09-15修正・実機バグ：チラつき】以前はここに`animation: ... infinite`を直接
   指定しており、数字が「3」→「2」→「1」と表示され続けている0.5秒間隔とは無関係に
   拍動アニメーションが永遠にループし続けていた（表示している数字は変わっていないのに
   0.5秒ごとに縮小・減光→拡大を繰り返すため、実機では明滅・チラつきとして見えてしまう）。
   本プロジェクトの恒久ルール「アニメーションは登場時のみ、その後は静止させる（infinite
   ループ禁止）」に従い、数字が切り替わった瞬間だけis-tickingクラスを付け直して1回だけ
   拍動を再生し、そのまま静止させるよう修正した（js/localReplayCountdown.js参照）。 */
.local-replay-countdown-number.is-ticking {
  animation: online-battle-countdown-pulse 0.5s ease-in-out;
}

/* 【2026-09-06新設、本人指示：実機フィードバック⑦】3→2→1の後は「♪ この曲は？」へ
   差し替え、回答フェーズ中はそのまま表示し続ける（js/localReplayCountdown.js参照）。
   数字のときの大きな拍動する演出とは変え、カード風の軽い演出に留めることで、
   回答選択肢を邪魔しない適度な存在感にした。 */
.local-replay-countdown-number.is-question-prompt {
  font-size: 1rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
  padding: 8px 22px;
  border-radius: 999px;
  letter-spacing: 0.03em;
  animation: local-replay-countdown-prompt-in 0.35s ease-out;
}

@keyframes local-replay-countdown-prompt-in {
  0% { transform: scale(0.9); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}

/* ===== オンライン対戦Step3：クイズ中の簡易進捗・待機画面・結果画面 ===== */

/* クイズ画面の隅に小さく出す、他プレイヤーの進捗（回答数／完了・切断状態だけ）。
   正解数・ミス数・経過時間・暫定順位は出さない（本人の要望）。 */
.online-battle-quiz-progress-strip {
  font-size: 0.68rem;
  line-height: 1.5;
  opacity: 0.65;
  text-align: center;
  margin: 2px 0 8px;
  overflow-wrap: anywhere;
}

/* 待機画面の参加者一覧は、ロビーの参加者一覧（.online-lobby-player-*）と同じ見た目を再利用しつつ、
   「進捗中」バッジだけ、既存のconnected/disconnectedのどちらでもない中立な色を新設する。 */
.online-lobby-badge-progress {
  background: var(--color-surface-glass);
  color: var(--color-primary-dark);
  border: 1px solid var(--color-card-border);
}

/* 結果を送信できなかった参加者（DNF）の行は、少し控えめな見た目にする。 */
.battle-rank-row.is-dnf {
  opacity: 0.55;
}

/* ===== 問題別結果アコーディオン（2026-09-12新設・本人指示：結果画面の問題別結果を完成させる）
   js/battleQuestionBreakdownUi.jsが描画する。対戦結果画面・オンラインプレイ履歴の詳細モーダル、
   両方の画面で共通のスタイルを使う（表示ロジックだけでなく見た目も1箇所にまとめている）。 ===== */

.battle-question-breakdown-section {
  margin: 18px 0;
}

.battle-question-breakdown-heading {
  margin: 0 0 8px;
  font-size: 0.85rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.battle-question-breakdown-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* ネイティブの<details>要素をカードふうに見せる。既定で閉じている（本人指示：問題数が
   多い場合はアコーディオンで、デフォルトは折りたたみ）ため、openを付けない限り本文は隠れる。 */
.battle-question-breakdown-item {
  border-radius: 12px;
  border: 1px solid var(--color-card-border);
  background: var(--color-surface-glass);
  overflow: hidden;
}

.battle-question-breakdown-item > summary {
  padding: 10px 14px;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-text);
  cursor: pointer;
  list-style: none;
}

/* Safari/Chrome標準の三角マーカーを消し、開閉に合わせて回転する自前の矢印に差し替える
   （既存の.online-lobby-help-mode-item等、他のアコーディオン風UIとの見た目の統一）。 */
.battle-question-breakdown-item > summary::-webkit-details-marker {
  display: none;
}

.battle-question-breakdown-item > summary::before {
  content: "▸";
  display: inline-block;
  margin-right: 6px;
  color: var(--color-accent);
  transition: transform var(--transition-fast, 0.15s) ease;
}

.battle-question-breakdown-item[open] > summary::before {
  transform: rotate(90deg);
}

.battle-question-breakdown-body {
  padding: 0 14px 12px;
}

.battle-question-breakdown-team-answer {
  margin: 0 0 8px;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.battle-question-breakdown-rows {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.battle-question-breakdown-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 10px;
  border-radius: 10px;
  background: var(--color-surface);
  border: 1px solid var(--color-card-border);
}

.battle-question-breakdown-row.is-correct {
  border-color: var(--color-accent);
  background: var(--color-accent-soft);
}

.battle-question-breakdown-row.is-wrong {
  border-color: var(--color-danger);
  background: var(--color-danger-soft);
}

/* 2026-09-15改訂・本人指示：UI色・フォントの統一。参加者名は.online-lobby-player-name・
   .battle-rank-nameと同じブランドピンクへ揃える（本人指示の恒久ルール：黒一色に見せない）。 */
.battle-question-breakdown-row-name {
  font-size: 0.75rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.battle-question-breakdown-row-answer {
  font-size: 0.72rem;
  color: var(--color-primary-dark);
  opacity: 0.8;
}

/* ===== 歌詞クイズモード（1人用MVP、2026-08-09新設） =====
   設定・結果画面は既存のタイムアタック・ランダム再生クイズと同じクラス
   （fieldset/option-row・time-attack-result-stats-row等）をそのまま使うため、
   ここでは問題画面専用のスタイルだけを新規に定義する。 */

.lyrics-quiz-question-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.75;
}

.lyrics-quiz-elapsed-time {
  font-variant-numeric: tabular-nums;
}

/* 一瞬チャレンジ専用：「もう一度聞く」「次の問題へ」（2026-08-30追加、本人指示⑧⑨）。
   .secondary-buttonはflex:1で.button-row内での利用を前提にしているため、単独配置では
   幅・余白を明示的に指定し直す。 */
.instant-challenge-replay-button {
  display: flex;
  width: 100%;
  margin: 0 0 14px;
}

.instant-challenge-replay-button:disabled {
  opacity: 0.45;
  cursor: default;
}

.instant-challenge-next-button {
  margin-top: 18px;
}

/* 歌詞ヒントの表示カード。読みやすさを優先し、十分な行間・横スクロールなしにする
   （本人の要望どおり）。 */
.lyrics-quiz-hint-card {
  padding: 20px 16px;
  margin-bottom: 16px;
  border-radius: 16px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  text-align: center;
}

.lyrics-quiz-hint-level {
  margin: 0 0 10px;
  font-size: 0.75rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  letter-spacing: 0.04em;
}

/* 開放済みのヒント段階へ自由に行き来できるボタン列。「次のヒントを見る」（新しい段階を
   開く操作）とは役割が違うため、あえて控えめな見た目（枠線のみ）にして混同を避けている。
   タップしやすいよう、最低44px相当の高さを確保する。 */
.lyrics-quiz-hint-level-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin: 0 0 14px;
}

.lyrics-quiz-hint-level-button {
  min-width: 64px;
  min-height: 40px;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1.5px solid var(--color-card-border);
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 700;
}

.lyrics-quiz-hint-level-button:disabled {
  opacity: 0.35;
  cursor: default;
}

.lyrics-quiz-hint-level-button.is-active {
  border-color: var(--color-primary-dark);
  background: var(--color-primary-dark);
  color: #ffffff;
}

/* これまでに出したヒントの行を、歌詞の登場順に積み上げて表示する一覧。
   段階が進んでも前のヒントを消さず、常に見返せるようにする（本人の指摘への対応：
   以前は別の区間へ切り替わると前のヒントが消え「情報が減った」ように見えていた）。
   answer-listより低いmax-heightにし、回答候補欄が画面外に追い出されないようにしている。 */
.lyrics-quiz-hint-list {
  list-style: none;
  margin: 0 0 16px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 32vh;
  overflow-y: auto;
  text-align: left;
}

.lyrics-quiz-hint-line {
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--color-surface);
  border: 1px solid var(--color-card-border);
}

.lyrics-quiz-hint-line.is-current {
  border-color: var(--color-primary-dark);
}

/* 新しく開放されたヒントだけに付ける、登場時1回きりの軽いフェードイン（本人指示：
   歌詞クイズ4モード共通のヒント表示仕様）。既存のanswerRevealPopキーフレームを再利用する。 */
.lyrics-quiz-hint-line.is-newly-revealed {
  animation: answerRevealPop 0.35s ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .lyrics-quiz-hint-line.is-newly-revealed {
    animation: none;
  }
}

.lyrics-quiz-hint-line-badge {
  display: inline-block;
  margin-bottom: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--color-primary-dark);
  color: #ffffff;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.03em;
}

.lyrics-quiz-hint-line-text {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.8;
  color: var(--color-text);
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

.lyrics-quiz-next-hint-button {
  width: 100%;
}

.lyrics-quiz-next-hint-button:disabled {
  opacity: 0.45;
  cursor: default;
}

.lyrics-quiz-answer-section {
  margin-bottom: 14px;
}

.lyrics-quiz-answer-label {
  margin: 0 0 8px;
  font-size: 0.85rem;
  font-weight: 700;
  opacity: 0.75;
}

.lyrics-quiz-answer-search-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

/* 【2026-09-13追加・本人指示：一瞬バトルの答え合わせが下に追いやられる不具合の修正】
   display:flexを持つクラスセレクタは、hidden属性のデフォルト表示（display:none、
   ブラウザ標準スタイル）と同じ詳細度のため、後から読み込まれるこちらが勝ってしまい、
   JS側でelement.hidden=trueにしても実際には隠れない（.lyrics-quiz-answer-reveal[hidden]
   等、既存の同種バグと同じパターン）。曲名検索欄・選択肢一覧・50音ジャンプバーの
   3箇所すべてに同じ抜け漏れがあり、大きな曲プール（30／50／全曲）で回答を確定しても
   これらが隠れず、答え合わせカードが画面の下（スクロールしないと見えない位置）まで
   追いやられていた（本人の実機報告で発覚）。 */
.lyrics-quiz-answer-search-row[hidden] {
  display: none;
}

.lyrics-quiz-answer-search-input {
  flex: 1;
  min-height: 40px;
  padding: 8px 12px;
  border-radius: 999px;
  border: 1px solid var(--color-card-border);
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.9rem;
}

.lyrics-quiz-answer-count {
  flex: none;
  font-size: 0.75rem;
  font-weight: 700;
  opacity: 0.6;
  white-space: nowrap;
}

/* 回答候補一覧：4択・10択は短い一覧なのでそのまま並び、30択以上は本人の要望どおり
   スクロール可能な一覧にする（max-heightを超えた分だけ縦スクロール）。 */
.lyrics-quiz-answer-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 42vh;
  overflow-y: auto;
  /* 【2026-09-06追加・本人の実機報告】縦スクロールだけをブラウザ自身に明示しておくことで、
     「このドラッグはスクロールなのかタップなのか」というブラウザ側の判定を安定させる
     （#quiz-screen等の.quiz-middle-zoneで既に使っている考え方と同じ、pan-y以外は
     JS側のタップ判定に委ねる）。js/answerButtonInteraction.jsのscrollTop実測による
     判定と合わせて、二重に確実性を高める。 */
  touch-action: pan-y;
  padding-right: 2px;
}

/* 【2026-11-XX追加・本人指示Q1：固定回答候補UIの統一】4択・10択のような「決められた数の
   候補から答える」画面は、歌詞クイズ対戦（.online-lyrics-battle-answer-grid）と同じ
   「2列グリッド」へ統一する（対象：歌詞クイズ単体・一瞬チャレンジ・一瞬バトル・一瞬協力の
   4画面。js側がpool.length<LARGE_ANSWER_POOL_THRESHOLD〈=検索欄を出さない、全曲検索
   ではない〉のときだけこのクラスを付与する。全曲検索・30/50択の大きなプールは
   従来どおり縦1列＋検索＋50音のままで、このクラスは付かない）。
   同じ行のカード高さを揃える（align-items:stretchが既定のため明示不要）・少ない行数でも
   縦に間延びしないようにする（align-content:start、オンライン歌詞クイズ対戦の
   .online-lyrics-battle-answer-gridで既に確立した対策と同じ）という2点は、
   あちらと全く同じ考え方。検索欄を出さない画面のため「1〜2件だけヒットして巨大化する」
   ケース自体が発生しない（絞り込む手段が無い）ので、ボタン側のalign-self対策は不要。 */
.lyrics-quiz-answer-list.is-fixed-choice-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  align-content: start;
  max-height: none;
  overflow-y: visible;
}

/* 【2026-09-13追加・本人指示：一瞬バトルの答え合わせが下に追いやられる不具合の修正】
   上の.lyrics-quiz-answer-search-row[hidden]と同じ理由。 */
.lyrics-quiz-answer-list[hidden] {
  display: none;
}

.lyrics-quiz-answer-button {
  width: 100%;
  text-align: center;
  /* 【2026-11-XX追加・本人指示：検索で候補が1〜2件になったときの巨大化対策】静的なCSSの
     読み取りでは、この一覧（縦のflexboxで並べているだけ）が候補を伸縮させる指定は
     見当たらなかった（このコメントの直前の.lyrics-quiz-answer-listはflex-direction:columnの
     ままで、子要素へflex-grow等は与えていない）。原因を特定できないまま推測でCSSを
     足しすぎないよう、ここでは「候補数に関係なく、ボタン自身の高さは中身に応じた
     自然な高さのまま伸縮させない」ことを明示的に固定するだけの、安全な予防策として
     flex-shrink/flex-growを両方0にしておく（実機で万一これでも直らない場合は、
     別の原因を疑う必要がある）。 */
  flex: 0 0 auto;
}

/* .choice-buttonの番号バッジ（::before）は#choice-buttons専用のnth-childルールで数字を
   入れる作りのため、ここでは中身のない空の丸だけが残ってしまう。歌詞クイズの回答候補は
   曲数が可変（4〜81件）でキーボード番号選択も無いため、バッジ自体を非表示にする。 */
.lyrics-quiz-answer-button::before {
  content: none;
}

.lyrics-quiz-skip-button {
  width: 100%;
}

/* ===== 歌詞クイズ：不正解・スキップ時の正解確認カード（2026-08-07追加） =====
   10択・30択・50択・全曲検索のように、正解の選択肢が検索結果の外・スクロール先など
   画面外になりうる回答方式で、不正解／スキップの直後に自動で次の問題へ進まず、
   本人が「次の問題へ」を押すまでとどまるカード（js/lyricsQuizScreen.js参照）。
   4択のときはこのカードを使わず、選択肢の中で直接光る従来演出のまま自動進行する。 */
.lyrics-quiz-answer-reveal {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 24px 16px 20px;
  border-radius: 16px;
  text-align: center;
  background: linear-gradient(165deg, #ffffff, var(--color-primary-light) 200%);
  border: 1px solid rgba(255, 111, 168, 0.35);
  /* 【2026-09-07新設・本人指示：答え合わせカードのデザイン改善】＝LOVEらしい
     ガラス風カード＋軽いキラキラ感を出すための、控えめな外側の光彩と内側のハイライト。
     派手にしすぎない範囲（本人指示）に留めるため、色味は既存のピンク系のまま濃さだけ調整。 */
  box-shadow: 0 12px 28px -14px rgba(255, 105, 180, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.7);
  animation: answerRevealPop 320ms cubic-bezier(0.22, 1, 0.36, 1);
  /* 上端の帯で正誤を色でも伝える（文字色だけに頼らない、本人指示Cの「色だけでなく
     文字・アイコン・レイアウトでも分かるように」に対応）。既定は不正解寄りの
     控えめなトーンにしておき、正解時だけ:has()で華やかな配色へ切り替える。 */
  overflow: hidden;
}

.lyrics-quiz-answer-reveal::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 5px;
  background: linear-gradient(90deg, #9aa3b8, #c3c9d6);
}

/* 【2026-09-08新設・本人指示C：答え合わせUIの再デザイン】正解時はカード全体の
   トーンを一段華やかにする（上端の帯をピンク×ゴールドへ、四隅にごく控えめな
   スパークルを添える）。過剰演出にならないよう、色味は既存のピンク系パレットの
   範囲内に収め、新しい色は追加しない。 */
.lyrics-quiz-answer-reveal:has(.is-correct-answer-reveal-status)::before {
  background: linear-gradient(90deg, var(--color-primary), var(--color-accent-soft), var(--color-primary));
}

/* 【2026-09-13改訂・本人指示：答え合わせを読んでいる間ずっと点滅する不具合の修正】
   以前はinfinite（無限ループ）で、答え合わせカードを表示している間ずっとキラキラが
   明滅し続けていた。本人指示により「現れた瞬間だけ華やかに、その後は静止」という
   恒久ルールに合わせ、1回だけ再生してそのまま静止する演出へ変更する。 */
.lyrics-quiz-answer-reveal:has(.is-correct-answer-reveal-status)::after {
  content: "✦";
  position: absolute;
  top: 10px;
  right: 14px;
  font-size: 0.9rem;
  color: var(--color-accent-soft);
  opacity: 0.85;
  animation: answerRevealSparkle 700ms ease-in-out 1;
}

@keyframes answerRevealSparkle {
  0% { opacity: 0.3; transform: scale(0.7) rotate(0deg); }
  50% { opacity: 1; transform: scale(1.15) rotate(12deg); }
  100% { opacity: 0.85; transform: scale(1) rotate(0deg); }
}

@media (prefers-reduced-motion: reduce) {
  .lyrics-quiz-answer-reveal:has(.is-correct-answer-reveal-status)::after {
    animation: none;
  }
}

@keyframes answerRevealPop {
  from {
    opacity: 0;
    transform: scale(0.94) translateY(4px);
  }
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .lyrics-quiz-answer-reveal {
    animation: none;
  }
}

/* display:flexの指定がhidden属性より優先されてしまう既知の問題への対策
   （#new-record-badge[hidden]等と同じ理由。JSのhidden切り替えを確実に効かせる）。 */
.lyrics-quiz-answer-reveal[hidden] {
  display: none;
}

.lyrics-quiz-answer-reveal-status {
  margin: 4px 0 4px;
  font-size: 1.05rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  color: var(--color-danger);
}

/* 【2026-09-03新設】オフライン版はこのカードを「不正解」時にしか使わないため赤固定だったが、
   オンライン版は自分の正誤どちらでもこのカードを使うため、正解時用の色を追加した
   （.online-battle-outcome-badge.is-correct-answer-badgeと同じ配色に揃えている）。 */
.lyrics-quiz-answer-reveal-status.is-correct-answer-reveal-status {
  color: var(--color-primary-dark);
}

/* 【2026-09-06新設・本人指示：実機フィードバック第3弾⑤】一瞬協力で「チーム全員が
   わからないを選んだ」特殊ケース用。不正解（赤系）と一緒くたにしない、というのが
   本人の意図のため、危険色ではない中間トーンにする。 */
.lyrics-quiz-answer-reveal-status.is-neutral-answer-reveal-status {
  color: var(--color-text);
  opacity: 0.75;
}

/* 一瞬協力：投票が同数でタイブレークになったことを知らせる専用バッジ
   （答え合わせカード本体の正誤バッジとは視覚的に区別する）。 */
.online-instant-coop-tiebreak-badge {
  display: inline-block;
  margin: 0 0 10px;
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 800;
  color: #8a5a00;
  background: rgba(255, 200, 60, 0.3);
}

.online-instant-coop-tiebreak-badge[hidden] {
  display: none;
}

/* 【2026-09-15新設・本人指示6：一瞬協力のチーム回答の決定理由を分かりやすく表示】
   「全員一致」「最多票」「同票」「全員わからない」等、実際の判定処理と一致する理由を
   1行で説明する。目立たせすぎず、補足情報としてブランドピンクへ寄せた控えめな色にする。 */
.online-instant-coop-decision-reason {
  margin: 6px 0 0;
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  opacity: 0.85;
}

.lyrics-quiz-answer-reveal-caption {
  margin: 0;
  font-size: 0.78rem;
  opacity: 0.7;
}

.lyrics-quiz-answer-reveal-title {
  margin: 2px 0 6px;
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  line-height: 1.35;
  /* 曲名が長くても375px幅からはみ出さないよう、必要なら折り返す
     （結果画面チップ等とは違い、ここは1行固定にする必要がないため）。 */
  overflow-wrap: break-word;
  max-width: 100%;
}

/* 【2026-09-08改訂・本人指示C：答え合わせUIの再デザイン】獲得ポイント等の情報を、
   ただのテキストではなく小さなバッジ（チップ）として見せる。中身は「+1pt」
   「獲得：+2pt」のような短い断片のみのため、pill型にしても横はみ出しは起きない。 */
.lyrics-quiz-answer-reveal-meta {
  display: inline-block;
  margin: 2px 0 14px;
  padding: 4px 14px;
  border-radius: 999px;
  background: rgba(255, 111, 168, 0.14);
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  opacity: 0.9;
}

.lyrics-quiz-answer-reveal-meta:empty {
  display: none;
}

/* 【2026-09-06新設・本人指示：実機フィードバック第3弾①】「あなたの回答：○○」欄。
   正解曲名（.lyrics-quiz-answer-reveal-title）より控えめに、しかし獲得ポイント欄より
   目立つ中間の強さにして、答え合わせの読む順序（正解→自分の回答→獲得pt）が
   自然に伝わるようにする。 */
.lyrics-quiz-answer-reveal-my-answer {
  margin: 0 0 6px;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.8;
  overflow-wrap: break-word;
  max-width: 100%;
}

.lyrics-quiz-answer-reveal-my-answer[hidden] {
  display: none;
}

.lyrics-quiz-answer-reveal .primary-button {
  width: 100%;
}

/* ===== 歌詞クイズ：結果画面の問題ごとの内訳（折りたたみ） ===== */
.lyrics-quiz-breakdown-details {
  margin: 4px 0 18px;
  padding: 10px 14px;
  border-radius: 12px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
}

.lyrics-quiz-breakdown-details summary {
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.lyrics-quiz-breakdown-list {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.lyrics-quiz-breakdown-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 4px;
  border-top: 1px solid var(--color-card-border);
  font-size: 0.8rem;
}

.lyrics-quiz-breakdown-row:first-child {
  border-top: none;
}

.lyrics-quiz-breakdown-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lyrics-quiz-breakdown-status {
  flex: none;
  font-weight: 800;
}

.lyrics-quiz-breakdown-status.is-correct {
  color: var(--color-primary-dark);
}

.lyrics-quiz-breakdown-status.is-wrong {
  color: var(--color-danger);
}

/* スマホ幅では歌詞ヒントの文字サイズ・行間・最大高さを少し詰め、スクロールしすぎないようにする。 */
@media (max-width: 480px) {
  .lyrics-quiz-hint-level-nav {
    margin-bottom: 10px;
  }

  .lyrics-quiz-hint-level-button {
    min-width: 56px;
    min-height: 36px;
    padding: 4px 10px;
    font-size: 0.8rem;
  }

  .lyrics-quiz-hint-list {
    /* ヒント段階ボタンの分だけ縦幅を取るようになったため、その分を差し引いて
       回答候補欄が画面外へ追い出されすぎないようにする。 */
    max-height: 22vh;
  }

  .lyrics-quiz-hint-line-text {
    font-size: 0.95rem;
    line-height: 1.7;
  }

  .lyrics-quiz-answer-list {
    max-height: 38vh;
  }
}

/* ===== 歌詞クイズ オンライン対戦（Phase6） =====
   js/lyricsQuizBattleUi.js（Phase5）が生成するDOM構造に対応するスタイル。
   dev/lyricsQuizBattleUiMockup.htmlのインラインスタイルで確認済みの見た目を、
   本番のCSS変数（--color-*）を使う形に置き換えて移植した。 */

.lyrics-battle-rule-options {
  border: none;
  padding: 0;
  margin: 0 0 16px;
}

.lyrics-battle-rule-options legend {
  font-weight: 800;
  margin-bottom: 6px;
  padding: 0;
}

.lyrics-battle-rule-option {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 10px;
  border-radius: 10px;
  background: var(--color-card-bg-soft, rgba(0, 0, 0, 0.04));
  margin-bottom: 6px;
  cursor: pointer;
}

.lyrics-battle-rule-option input {
  margin-top: 3px;
}

.lyrics-battle-rule-option-description {
  display: block;
  font-size: 0.78rem;
  opacity: 0.75;
}

.lyrics-battle-pool-size-options {
  border: none;
  padding: 0;
  margin: 0 0 16px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.lyrics-battle-pool-size-options legend {
  width: 100%;
  font-weight: 800;
  margin-bottom: 6px;
  padding: 0;
}

.lyrics-battle-pool-size-option {
  padding: 6px 10px;
  border-radius: 999px;
  background: var(--color-card-bg-soft, rgba(0, 0, 0, 0.06));
  font-size: 0.8rem;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
}

.lyrics-battle-settings-field {
  margin-bottom: 12px;
}

.lyrics-battle-settings-field label {
  display: block;
  font-size: 0.8rem;
  font-weight: 700;
  margin-bottom: 4px;
}

.lyrics-battle-settings-field select {
  width: 100%;
  padding: 8px;
  border-radius: 8px;
  border: 1px solid var(--color-card-border);
}

/* 【2026-09-26改訂・本人指示：オンライン対戦総合改修19-6章】以前は4項目を想定した
   2列グリッドの大きなガラス風カードだったが、現在このHUDが出るのは「📊 みんなのスコア」
   自体が意図的に隠れている早押しバトルの回答収集中だけ（js/onlineLyricsQuizBattleScreen.js
   のrenderCurrentQuestionState()参照）で、項目も「現在のポイント」1つだけになった。
   縦スペースを大きく占領して回答候補を押し下げていたという本人指摘を踏まえ、1行に
   収まる小さな横並びのチップへ縮小する（役割＝早押し中に自分の得点を確認する手段、は
   維持したまま、見た目だけをコンパクトにする）。 */
.lyrics-battle-hud {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 14px;
}

.lyrics-battle-hud dt {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.7;
}

.lyrics-battle-hud dd {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
  border-radius: 999px;
  padding: 3px 12px;
  font-variant-numeric: tabular-nums;
}

/* 【2026-09-06新設・本人指示：実機フィードバック第3弾②】以前のtable形式
   （.lyrics-battle-result-table、順位／表示名／獲得ポイント／使用ヒント数／回答時間／
   ミス回数／わからない回数の7列）は、スマホ幅では列が窮屈に折り返され読みにくかった
   ため、「1人1枚のカード」形式に置き換えた（js/lyricsQuizBattleUi.jsの
   renderResultCards()参照）。既存の対戦中HUD（.lyrics-battle-hud）・結果画面の
   ガラス風カード（.time-attack-result-stat）と同じ質感に揃えている。 */
.lyrics-battle-result-card-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  list-style: none;
  margin: 0 0 4px;
  padding: 0;
}

.lyrics-battle-result-card {
  padding: 14px 16px;
  border-radius: 16px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  box-shadow: var(--shadow-card);
}

.lyrics-battle-result-card.is-you {
  border-color: rgba(255, 105, 180, 0.55);
  background: linear-gradient(165deg, rgba(255, 105, 180, 0.12), var(--color-surface-glass) 70%);
}

/* 上位3位は、派手になりすぎない範囲で少しだけ縁取りを強調する（本人指示：
   「派手すぎない、アプリらしい装飾」）。 */
.lyrics-battle-result-card.is-medal-rank {
  border-color: rgba(255, 189, 89, 0.6);
  box-shadow: 0 8px 20px -10px rgba(255, 165, 60, 0.45);
}

.lyrics-battle-result-card.is-dnf {
  opacity: 0.6;
}

.lyrics-battle-result-card-rank {
  margin: 0 0 4px;
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--color-text);
  opacity: 0.8;
}

.lyrics-battle-result-card.is-medal-rank .lyrics-battle-result-card-rank {
  font-size: 1.05rem;
  opacity: 1;
}

.lyrics-battle-result-card-name-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px;
  margin-bottom: 6px;
}

/* 2026-09-15改訂・本人指示：UI色・フォントの統一。参加者名はブランドピンクへ揃える。 */
.lyrics-battle-result-card-name {
  font-size: 1rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  overflow-wrap: break-word;
}

.lyrics-battle-result-card-primary-stat {
  margin: 0 0 10px;
  font-size: 1.4rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
}

.lyrics-battle-result-card-dnf-note {
  margin: 0;
  font-size: 0.8rem;
  opacity: 0.75;
}

/* 【2026-XX-XX追加・本人指示11：ポイントバトル結果配置修正】「正解数」のような
   fullWidth指定の項目を、ヒント1〜4の2×2グリッドとは別に、独立した1行として置くための
   スタイル。primary-stat（獲得ポイント）ほど大きくはしないが、2×2グリッドの1マスより
   目立たせることで「正解数バトルと混同しないでください」という本人指示どおり、
   あくまで補助情報であることが伝わるようにする。 */
.lyrics-battle-result-card-secondary-stat {
  margin: 0 0 10px;
  padding: 6px 10px;
  border-radius: 10px;
  background: var(--color-card-bg-soft, rgba(0, 0, 0, 0.04));
}

.lyrics-battle-result-card-secondary-stat-label {
  margin: 0;
  font-size: 0.68rem;
  font-weight: 700;
  opacity: 0.6;
  letter-spacing: 0.02em;
}

.lyrics-battle-result-card-secondary-stat-value {
  margin: 2px 0 0;
  font-size: 1.05rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.lyrics-battle-result-card-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px 10px;
  margin: 0;
}

.lyrics-battle-result-card-stat dt {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.6;
  letter-spacing: 0.02em;
}

.lyrics-battle-result-card-stat dd {
  margin: 2px 0 0;
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

.lyrics-battle-oshi-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin-right: 4px;
}

.lyrics-battle-host-badge,
.lyrics-battle-you-badge {
  display: inline-block;
  font-size: 0.65rem;
  padding: 1px 6px;
  border-radius: 999px;
  margin-left: 4px;
  background: var(--color-card-bg-soft, rgba(0, 0, 0, 0.1));
}

.lyrics-battle-readiness-status {
  padding: 10px;
  border-radius: 10px;
  font-size: 0.85rem;
  margin-top: 8px;
}

.lyrics-battle-readiness-status.is-ready {
  background: rgba(80, 200, 120, 0.15);
}

.lyrics-battle-readiness-status.is-not-ready {
  background: rgba(255, 100, 100, 0.15);
}

.lyrics-battle-readiness-status.is-checking {
  background: rgba(180, 180, 180, 0.15);
}

.lyrics-battle-readiness-status ul {
  margin: 6px 0 0;
  padding-left: 18px;
}

.lyrics-battle-own-missing {
  margin-top: 10px;
  padding: 10px;
  border-radius: 10px;
  background: rgba(255, 200, 60, 0.15);
  font-size: 0.82rem;
}

/* ===== 歌詞クイズ対戦：対戦中画面（HUD・ヒント・回答候補）専用のレイアウト =====
   【2026-09-05改訂、本人指摘：実機で見た目が簡素すぎる・下半分が空きすぎ】
   トークン未定義のvar(--color-card-bg-soft)（実質グレー、枠線なし）に頼っていた
   ブロックを、他のクイズ画面と同じ「ガラス風カード＋淡いピンクの影」の質感へ揃え、
   余白も一回り広げて画面の密度を上げた。HTML構造・JSのtextContent/classList操作は
   一切変更していない（既存クラスへのスタイル追加のみ）。 */

/* 【2026-10-01新設・本人指示：歌詞クイズ問題画面モバイルレイアウト再設計5章】
   ヘッダー2ボタン（対戦をやめる／ルーム設定へ戻る）を横並びにする専用行。
   .quiz-header-row自体は既存のsafe-area対応・space-between・flex:noneをそのまま使い、
   このクラスでは375px幅でボタン文言が窮屈になりすぎないよう、文字サイズだけを
   少し絞る（ボタンの見た目のクラス・タップ領域自体は変更しない）。 */
.online-lyrics-battle-header-row .quiz-back-link,
.online-lyrics-battle-header-row .online-battle-back-to-lobby-button {
  font-size: 0.78rem;
  white-space: nowrap;
}

/* 【2026-10-01新設・本人指示：歌詞クイズ問題画面モバイルレイアウト再設計5章】
   「歌詞クイズ対戦」（h2）と「第N問/全N問」ピルを1行にまとめたコンパクトな見出し。
   以前はh2が独立した中央寄せブロック（margin-bottom込みでかなりの高さ）＋
   その下に別のピルという2段構成で、375px幅では回答候補の表示領域を圧迫していた。
   タイトルは補助的な情報（画面を見れば歌詞クイズ対戦中であることは自明）のため
   小さく添え、「第N問/全N問」の方を主役として通常のピルの大きさのまま残す。 */
.online-lyrics-battle-compact-heading {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 10px;
}

.online-lyrics-battle-compact-heading h2 {
  font-size: 0.9rem;
  opacity: 0.7;
}

/* 【2026-11-XX追加・本人指示：優先度2】今のルール名（正解数/早押し/ポイントバトル）を
   一目で分かるようにするバッジ。「第N問」の進捗ピルより控えめな色にし、タイトルの
   一部として自然に読める見た目にする（新しい行・新しい高さを専用に確保しない）。 */
.online-lyrics-battle-rule-badge {
  display: table;
  margin: 0;
  padding: 3px 12px;
  border-radius: 999px;
  background: var(--color-secondary-light);
  color: var(--color-text);
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  opacity: 0.85;
}

.online-lyrics-battle-progress {
  display: table; /* text-alignだけでなく、中身の幅にフィットしたピル型にするため */
  margin: 0;
  padding: 5px 16px;
  border-radius: 999px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.02em;
}

/* 【2026-09-01新設・本人指示：ライブスコアボード】他プレイヤーの現在の累計スコアを見せる、
   問題画面上部の一覧。375px幅を意識し、プレイヤー名が長い場合・人数が多い場合の折り返しにも
   耐えるよう、一覧はchip状にflex-wrapさせる。
   【2026-09-30改訂・本人指示：オンライン対戦総合改修 第2ラウンド12章】開閉できる<details>
   要素だったが、開閉の仕組み自体を無くし常に見える<section>へ変更した（index.html参照）。 */
.online-lyrics-battle-scoreboard {
  margin: 0 0 10px;
  border-radius: 14px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  overflow: hidden;
}

.online-lyrics-battle-scoreboard[hidden] {
  display: none;
}

.online-lyrics-battle-scoreboard-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 14px 6px;
  margin: 0;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--color-text);
}

/* 【2026-10-01改訂・本人指示：歌詞クイズ問題画面モバイルレイアウト再設計5章】以前は
   見出し・あなたの順位と同じ1行に並べていたが、375px幅では見出しが折り返してしまう
   問題があった。優先度の低い補足情報のため、見出し行の下に独立した小さな1行として移した。 */
.online-lyrics-battle-scoreboard-summary-hint {
  margin: 0 14px 8px;
  font-size: 0.66rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.6;
}

.online-lyrics-battle-scoreboard-summary-hint:empty {
  display: none;
}

/* 【2026-10-01新設・本人指示：歌詞クイズ問題画面モバイルレイアウト再設計5章】
   横スクロールするスコア一覧をスクロールしなくても、自分が今何位・何ptなのかが
   常に見える固定表示。summary行（スクロールしない領域）に置くことで実現する。 */
.online-lyrics-battle-my-rank {
  flex: none;
  font-size: 0.74rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
  border-radius: 999px;
  padding: 3px 10px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.online-lyrics-battle-my-rank:empty {
  display: none;
}

/* 【2026-10-01改訂・本人指示：歌詞クイズ問題画面モバイルレイアウト再設計5章】以前は
   flex-wrapで折り返す一覧だったため、参加人数が多いと縦方向にどんどん伸びて
   回答候補の表示領域を圧迫していた。横スクロールする1行のコンパクトなチップ列へ
   変更し、人数に関わらず縦方向の専有を一定に保つ（自分の行は#online-lyrics-battle-my-rankで
   別途固定表示するため、横スクロールで一時的に見えなくなっても実害が無い）。 */
.online-lyrics-battle-scoreboard-list {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  gap: 6px;
  margin: 0;
  padding: 0 12px 12px;
  list-style: none;
}

.online-lyrics-battle-scoreboard-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  /* 【2026-10-01改訂】横スクロール列の中の1チップとして、内容ぶんの幅を保ったまま
     並ぶようにする（flex:noneで潰れて省略されるのを防ぐ。親のoverflow-x:autoが
     はみ出しぶんを横スクロールで吸収する）。 */
  flex: none;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--color-surface);
  border: 1px solid var(--color-card-border);
}

/* 自分自身の行だけ縁取り・背景をブランドカラーにして見分けやすくする
   （2026-09-26改訂・本人指示：背景も少し強調し、枠線だけより一目で分かるようにする）。 */
.online-lyrics-battle-scoreboard-item.is-me {
  border-color: var(--color-primary);
  background: var(--color-primary-light);
}

.online-lyrics-battle-scoreboard-rank {
  flex: none;
  font-size: 0.64rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.5;
}

.online-lyrics-battle-scoreboard-name {
  min-width: 0;
  max-width: 32vw;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.72rem;
  font-weight: 700;
  /* 2026-09-26改訂・本人指示：UI恒久ルール（黒一色に見せない）。参加者名は
     .online-lobby-player-name・.battle-rank-nameと同じブランドピンクへ揃える。 */
  color: var(--color-primary-dark);
}

/* 恒久デザインルール：重要な数値情報（スコア）は濃い色＋太字にする。 */
.online-lyrics-battle-scoreboard-value {
  flex: none;
  font-size: 0.78rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
}

/* 【2026-10-01改訂・本人指示：歌詞クイズ問題画面モバイルレイアウト再設計5章】ソフトウェア
   キーボード表示相当（375×600程度）でも回答候補の表示領域をできるだけ確保するため、
   このブロック自体の余白を少し切り詰めた（ヒント文の文字サイズ・行間はそのまま）。 */
.online-lyrics-battle-hint-box {
  padding: 14px 18px;
  border-radius: 20px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  box-shadow: var(--shadow-card);
  margin: 0 0 12px;
}

.online-lyrics-battle-hint-level {
  font-weight: 800;
  font-size: 0.78rem;
  margin: 0 0 8px;
  color: var(--color-primary-dark);
  letter-spacing: 0.04em;
  text-align: center;
}

.online-lyrics-battle-hint-lines {
  display: flex;
  flex-direction: column;
  gap: 10px;
  /* 【2026-11-XX改訂・本人指示：ヒントの表示順と番号（hintLevel）を分離】以前はCSSカウンター
     でDOM順に「1」「2」…と自動採番していたが、ヒントの表示順（歌詞の時系列）と抽選順
     （hintLevel）が別物になったため、DOM順の自動採番は使えなくなった。各ヒント項目
     （.online-lyrics-battle-hint-summary-item）側がバッジとして本来のhintLevelを明示する
     方式へ統一した（回答確定後の一覧・早押しバトルと全く同じ見た目にした）。
     【2026-10-01新設・本人指示：歌詞クイズ問題画面モバイルレイアウト再設計5章】以前は
     ヒントが増えるほどこのブロック自体が無制限に縦へ伸び、下にある回答候補一覧
     （#online-lyrics-battle-question-screen .online-lyrics-battle-answer-gridのflex:1）の
     表示領域を圧迫していた（ヒント4/4まで開くと375×812でも回答候補が1行も見えない
     状態になっていた）。ヒント行だけを最大2行ぶんの高さに制限し、それを超える分は
     ここだけの内部スクロールにする（回答候補一覧と同じ考え方）。最新のヒントへ
     視線が行くよう、新しいヒントが追加されるたびにJS側で一番下までスクロールする
     （js/onlineLyricsQuizBattleScreen.js参照）。 */
  max-height: 152px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding-right: 2px;
}

/* 【2026-10-01新設・本人指示：歌詞クイズ問題画面モバイルレイアウト再設計5章】答え合わせ
   カード表示中（.online-lyrics-battle-answer-gridに.is-showing-revealが付き、回答候補一覧が
   flex:1のスクロール領域から通常のブロック表示へ切り替わっている間）は、回答候補一覧との
   高さの奪い合いがそもそも発生しないため、上のmax-height制限は不要かつ「ヒント1〜4を
   全部並べて振り返りたい」という答え合わせ本来の目的の妨げになる。この間だけ制限を解除する。 */
.quiz-middle-zone-inner:has(.online-lyrics-battle-answer-grid.is-showing-reveal) .online-lyrics-battle-hint-lines {
  max-height: none;
  overflow-y: visible;
}

/* 【2026-09-13新設・本人指示：答え合わせ時にヒント1〜4をすべて表示】ヒント4段階ぶんを
   まとめて見せるためのコンパクトな一覧。正誤・正解曲・自分の回答・獲得ポイントと合わせて、
   通常のiPhone画面でできるだけ1画面に収まるようにする（本人指示：「ヒント1〜4＋正誤＋
   正解曲＋自分の回答＋獲得ポイントが可能な限り1画面で把握できること」）。
   【2026-11-XX改訂】以前は回答確定後専用（.online-lyrics-battle-hint-summary-list）と
   回答前専用（.online-lyrics-battle-hint-line、DOM順のCSSカウンター採番）でクラスを
   分けていたが、ヒントの表示順と番号（hintLevel）が別物になったことに合わせて、
   回答前・回答後・早押しバトルのすべてでこの一覧スタイルへ統一した。 */
.online-lyrics-battle-hint-summary-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.online-lyrics-battle-hint-summary-item {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  padding: 8px 10px;
  border-radius: 10px;
  background: var(--color-surface);
  border: 1px solid var(--color-card-border);
  font-size: 0.82rem;
  line-height: 1.5;
}

.online-lyrics-battle-hint-summary-level {
  flex: none;
  font-size: 0.65rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background: var(--color-accent-soft);
  border-radius: 999px;
  padding: 2px 8px;
  white-space: nowrap;
}

/* 【2026-09-17改訂・本人指示：重要な情報は常に濃い色＋太字】以前は色・太さの指定が無く、
   継承された細い文字のまま表示されていた。出題中のヒント（.online-lyrics-battle-hint-line-text）
   と同じ「濃い色＋太字」に揃え、答え合わせ画面でもヒント文がひと目で読めるようにした。 */
.online-lyrics-battle-hint-summary-text {
  flex: 1;
  min-width: 0;
  font-weight: 700;
  color: var(--color-text);
}

/* 新しく開放されたヒントだけに付ける、登場時1回きりの軽いフェードイン
   （本人指示：歌詞クイズ4モード共通のヒント表示仕様。offline側の
   .lyrics-quiz-hint-line.is-newly-revealedと同じ考え方・同じキーフレームを使う）。 */
.online-lyrics-battle-hint-summary-item.is-newly-revealed {
  animation: answerRevealPop 0.35s ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .online-lyrics-battle-hint-summary-item.is-newly-revealed {
    animation: none;
  }
}

/* 【2026-08-31新設、本人指示：歌詞クイズ3ルール全面改修】正解数バトル・ポイントバトルの
   「ヒントNを見る」「わからない」ボタン。早押しバトルでは使わない（常にhidden）。
   §9のモバイル配慮：ヒント欄がボタンで縦に大きく伸びすぎないよう、小さめの高さに抑える。 */
.online-lyrics-battle-hint-actions {
  display: flex;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  /* 【2026-10-01改訂・本人指示：歌詞クイズ問題画面モバイルレイアウト再設計5章】
     ソフトウェアキーボード表示相当でも回答候補の表示領域を少しでも広げるため
     下余白を切り詰めた（以前は20px）。 */
  margin: -8px 0 10px;
}

.online-lyrics-battle-hint-actions[hidden] {
  display: none;
}

.online-lyrics-battle-hint-open-button,
.online-lyrics-battle-give-up-button {
  flex: none;
  width: auto;
  min-height: 38px;
  padding: 8px 18px;
  font-size: 0.82rem;
}

/* 早押しバトル：歌詞の該当箇所が1文字ずつ表示される演出。ヒント段階の通し番号バッジ
   （.online-lyrics-battle-hint-line::before）は「段階」の概念が無いこのモードには
   そぐわないため非表示にし、代わりに文字を目で追いやすいよう少し大きめの文字にする。 */
/* 【2026-09-06修正、本人指示：実機フィードバック⑧】文字数が増えるにつれて改行位置・
   表示領域が不自然になる問題への対応。overflow-wrap/word-breakで横はみ出しを防ぐ、
   line-heightを広めに取って読みやすくした。 */
/* 【2026-09-08修正・本人指示：実機フィードバック】以前はここにmax-height（約3行分）＋
   overflow-y:autoを付け、3行を超えた分をこの領域内だけでスクロールさせていたが、
   1文字ずつ増えていく演出中は新しく表示された文字がスクロール範囲外（枠の下）に
   隠れたまま追従しないため、実機では「3行を超えると文字が途中で切れる」ように見える
   不具合になっていた（本人からの実機報告で発覚）。この領域自体の高さ制限・独自スクロールを
   廃止し、歌詞が何行になっても内容に合わせて自然に伸びるようにした。画面全体がその分
   縦に収まらない場合は、#quiz-screen等と同じ既存の仕組み（.quiz-middle-zone自体が
   上詰め＋ページ全体でスクロールに切り替わる設計）にそのまま任せる。 */
.online-lyrics-battle-reveal-line {
  padding-left: 16px;
  padding-right: 4px;
  font-size: 1.15rem;
  line-height: 1.7;
  letter-spacing: 0.02em;
  min-height: 1.7em;
  overflow-wrap: break-word;
  word-break: normal;
}

.online-lyrics-battle-reveal-line::before {
  content: none;
}

/* 【2026-08-31新設】30・50・全曲プールの検索欄。オフライン歌詞クイズの
   .lyrics-quiz-answer-search-row等と同じ見た目にして統一感を保つ。 */
.online-lyrics-battle-answer-search-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.online-lyrics-battle-answer-search-row[hidden] {
  display: none;
}

.online-lyrics-battle-answer-search-row input {
  flex: 1;
  min-height: 40px;
  padding: 8px 12px;
  border-radius: 999px;
  border: 1px solid var(--color-card-border);
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.9rem;
}

.online-lyrics-battle-answer-count {
  flex: none;
  font-size: 0.75rem;
  font-weight: 700;
  opacity: 0.6;
  white-space: nowrap;
}

/* 全曲プール専用の50音ジャンプバー（「すべて｜あ｜か｜さ｜…」）。検索を必須にせず、
   曲名の読みが分かればブラウズできるようにするための一覧（本人指示）。 */
.online-lyrics-battle-answer-jump-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 10px;
}

/* 【2026-09-13追加・本人指示：一瞬バトルの答え合わせが下に追いやられる不具合の修正】
   上の.lyrics-quiz-answer-list[hidden]と同じ理由。 */
.online-lyrics-battle-answer-jump-bar[hidden] {
  display: none;
}

.online-lyrics-battle-answer-jump-bar[hidden] {
  display: none;
}

.online-lyrics-battle-jump-chip {
  flex: none;
  width: auto;
  min-height: 30px;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--color-card-border);
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
}

.online-lyrics-battle-jump-chip.is-active {
  border-color: var(--color-primary);
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

.online-lyrics-battle-answer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 10px;
  margin-bottom: 20px;
  /* 【2026-11-XX修正・実機バグ調査：仕様総監査で発見】検索で候補が1〜2件になり行数が
     少ないとき、Gridの初期値（align-content: stretch相当）だと余った縦の空きスペースが
     この少ない行自体に配られてカードが巨大化する。align-content: startで「行は上詰めで
     並べ、余りは配らない」ことをコンテナ側で解決する（下のalign-items:stretch＝各行内で
     カードの高さを揃える、という既定の挙動には触れない）。 */
  align-content: start;
}

/* 【2026-08-31新設】30・50・全曲プールでは、通常のボタン格子ではなく縦スクロールする
   一覧に切り替える（オフライン歌詞クイズの.lyrics-quiz-answer-listと同じ考え方）。
   全曲プール（50音ジャンプバーと組み合わせる）はフル幅の1列、30・50プールは
   本人指示どおりコンパクトな2列にする。2クラス分の詳細度により、上のグリッド指定・
   後述のスマホ用2列指定より必ず優先される。
   【2026-09-30改訂・本人指示：オンライン対戦総合改修 第3ラウンド・スクロール構造改善】
   max-height:42vhという固定値をやめ、次のブロック（#online-lyrics-battle-question-screen
   スコープ）でflex:1・min-height:0による「残り高さぶんだけ内部スクロールする」構造に
   差し替える。ヒント・スコア・検索欄・50音は常にその場に固定されたまま動かない
   （本人指示：画面全体を長大なスクロール領域にしない）。 */
.online-lyrics-battle-answer-grid.online-lyrics-battle-answer-list {
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  padding-right: 2px;
}

.online-lyrics-battle-answer-grid.online-lyrics-battle-answer-list-compact {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  overflow-y: auto;
  padding-right: 2px;
  /* 上の.online-lyrics-battle-answer-gridと同じ理由（少ない行数のときの巨大化対策）。 */
  align-content: start;
}

/* 【2026-09-30新設・本人指示：オンライン対戦総合改修 第3ラウンド・歌詞クイズのスクロール
   構造改善】以前は.quiz-middle-zone全体（ヒント・スコア・検索欄・50音・回答候補一覧の
   すべて）が1つの外側スクロール領域で、その内側で回答候補一覧（30/50/全曲プール）が
   さらに独自の固定42vhスクロールを持つ「二重スクロール」構造になっていた。外側の
   スクロールが先に効き、検索欄・50音バーが画面外へ押し出されることがあった
   （本人からの実機報告）。歌詞クイズ対戦の問題画面だけ、外側の丸ごとスクロールをやめ、
   回答候補一覧だけがflex:1で「ヒント・スコア・検索欄・50音より下に残った高さ」を
   埋めて内部スクロールする構造に変更する。
   【ソフトウェアキーボード対応】.game-frame（親要素）は既にheight:100dvhで、
   キーボード表示時にブラウザが動的に縮めてくれる実際の表示可能高さに追従する設計
   （このファイル内、#quiz-screen等の解説コメント参照）。回答候補一覧の高さもこの
   dvh基準の残り高さから自動的に決まるため、キーボードが出た状態でも検索欄・検索結果を
   両方見ながら選べる（JS側で新しい高さ計算を持つ必要はない）。
   【4択/10択（通常グリッド、-list/-list-compact修飾クラスが付かない場合）への影響】
   flex:1のまま自然な高さで収まるため、大量候補時と同じ構造でも見た目上の実害は無い
   （4〜10個のボタンが画面に収まりきらないことは通常起きないため、実質的に今までどおり）。 */
/* 【安全設計】.quiz-middle-zone自体のoverflow-y:auto（既存の安全側フォールバック、
   ファイル冒頭のコメント参照）はあえて上書きしない。.quiz-middle-zone-inner側を
   flex:1・min-height:0の子として正しく制約すれば、回答候補一覧（下のflex:1）が
   「ヒント・スコア・検索欄・50音より下に残った高さ」を自分の内部スクロールだけで
   吸収し、外側が実際にスクロールを必要とする場面が構造的に起きなくなる
   （＝外側のoverflow-y:autoは常に待機状態のフォールバックのまま、二重スクロールは
   発生しない）。答え合わせカード表示中に万一収まらない場合も、この外側のautoが
   そのまま安全網として働く。 */
#online-lyrics-battle-question-screen .quiz-middle-zone-inner {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  margin: 8px 0 0;
}

/* 【重要】flexアイテムの既定値（flex-shrink:1）のままだと、画面が極端に低い
   （ソフトウェアキーボード表示時等）場合に、ヒント・スコア・検索欄・50音といった
   「固定領域」まで一緒に圧縮されて潰れてしまう（実機確認で発覚：スコアボードの高さが
   1px未満まで潰れる現象）。回答候補一覧（flex:1、下で指定）だけが縮んでスクロールする
   対象になるよう、それ以外の直接の子要素はすべてflex-shrink:0で「絶対に潰れない」
   固定領域にする。 */
#online-lyrics-battle-question-screen .quiz-middle-zone-inner > * {
  flex-shrink: 0;
}

#online-lyrics-battle-question-screen .online-lyrics-battle-answer-grid {
  flex: 1 1 0;
  min-height: 60px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

#online-lyrics-battle-question-screen .online-lyrics-battle-answer-grid.online-lyrics-battle-answer-list,
#online-lyrics-battle-question-screen .online-lyrics-battle-answer-grid.online-lyrics-battle-answer-list-compact {
  max-height: none;
}

/* 4択/10択（通常グリッド）は数個のボタンしかなく内部スクロールが不要なため、
   flex:1で余白を持て余さないよう、答え合わせカード表示中と同じく自然な高さに戻す。 */
#online-lyrics-battle-question-screen .online-lyrics-battle-answer-grid:not(.online-lyrics-battle-answer-list):not(.online-lyrics-battle-answer-list-compact) {
  flex: none;
  overflow-y: visible;
}

/* 【2026-09-06新設・本人指示：実機フィードバック第3弾①】答え合わせが確定した瞬間、
   選択肢一覧（グリッド／スクロール一覧）のレイアウトを解除し、中の答え合わせカードが
   本来のカード幅・カード高さでそのまま表示されるようにする。 */
.online-lyrics-battle-answer-grid.is-showing-reveal {
  display: block;
  max-height: none;
  overflow: visible;
  margin-bottom: 20px;
}

.online-lyrics-battle-answer-list .online-lyrics-battle-answer-button,
.online-lyrics-battle-answer-list-compact .online-lyrics-battle-answer-button {
  min-height: 44px;
  padding: 10px 8px;
  font-size: 0.84rem;
}

.online-lyrics-battle-answer-button {
  min-height: 48px;
  padding: 14px 10px;
  border-radius: 16px;
  border: 2px solid var(--color-primary);
  background: var(--color-surface);
  font-family: inherit;
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--color-text);
  cursor: pointer;
  box-shadow: 0 4px 14px -8px rgba(255, 79, 150, 0.4);
  transition: transform var(--transition-fast, 0.15s), box-shadow var(--transition-fast, 0.15s), background-color var(--transition-base, 0.2s), border-color var(--transition-base, 0.2s);
  /* 【2026-11-XX追加・本人指示：検索で候補が1〜2件になったときの巨大化対策】
     js/lyricsQuizScreen.jsの.lyrics-quiz-answer-buttonと同じ予防策（詳しい経緯は
     そちらのコメント参照）。flexコンテナ（.online-lyrics-battle-answer-list）に
     置かれても、候補数に関係なくボタン自身が縦方向に伸縮しないよう明示的に固定する。
     【2026-11-XX修正・実機バグ調査：仕様総監査で発見】以前はここにalign-self: startも
     付けていたが、gridコンテナ（.online-lyrics-battle-answer-grid/-list-compact）側では
     それが「同じ行内のカードの高さを揃える」既定の挙動（align-items: stretch）まで
     打ち消してしまい、曲名が1行のカードと2行に折り返すカードが同じ行に混在すると
     外枠の高さが不揃いになっていた。少ない行数のときの巨大化対策は、align-self（各カード側）
     ではなくalign-content（グリッドコンテナ側、上で追加済み）で解決するよう役割を分けた。 */
  flex: 0 0 auto;
}

.online-lyrics-battle-answer-button:active:not(:disabled) {
  transform: scale(0.96);
}

/* 【2026-11-XX新設・本人指示：回答ボタンの操作性改善】js/answerButtonInteraction.jsが
   早押し（steal）ルールの回答ボタンへ付け外しする押下中クラス。見た目は既存の:activeと揃える。 */
.online-lyrics-battle-answer-button.is-pressed:not(:disabled) {
  transform: scale(0.96);
}

.online-lyrics-battle-answer-button:disabled {
  opacity: 0.5;
  cursor: default;
  box-shadow: none;
}

.online-lyrics-battle-answer-button.is-selected {
  border-color: var(--color-primary);
  background: var(--color-primary-light);
  font-weight: 800;
}

/* 【2026-09-03改訂、本人指摘】以前は緑・灰色系でアプリ本体（ピンク基調）と統一感が
   無かったため、本体で使っている配色トークンに揃えた。また、正解確認後は
   button:disabledの一律opacity:0.5が、せっかく色分けした正解／不正解のボタンまで
   薄くしてしまっていたため、この2つのクラスだけopacityを1に戻して見やすくした。 */
.online-lyrics-battle-answer-button.is-correct-answer {
  border-color: var(--color-primary);
  background: var(--color-accent-soft, var(--color-primary-light));
  color: var(--color-primary-dark);
  font-weight: 800;
}

.online-lyrics-battle-answer-button.is-my-wrong-answer {
  border-color: var(--color-danger);
  background: var(--color-danger-soft);
  color: var(--color-danger);
  font-weight: 800;
}

.online-lyrics-battle-answer-button.is-correct-answer:disabled,
.online-lyrics-battle-answer-button.is-my-wrong-answer:disabled {
  opacity: 1;
  box-shadow: none;
}

/* 【2026-09-06新設、本人指示：3分無操作の放置救済】ホストにだけ見える通知。
   複数人が同時に該当する可能性があるため、行を縦に並べられる形にしてある。 */
.online-lyrics-battle-idle-notice {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 14px;
}

.online-lyrics-battle-idle-notice[hidden] {
  display: none;
}

.online-lyrics-battle-idle-notice-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 14px;
  border-radius: 14px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  box-shadow: var(--shadow-card);
}

.online-lyrics-battle-idle-notice-text {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-text);
}

.online-lyrics-battle-idle-notice-button {
  flex: none;
  width: auto;
  min-height: 36px;
  padding: 6px 14px;
  font-size: 0.76rem;
}

/* 【2026-09-15新設・本人指示：一瞬バトルの同期方式への全面書き換え】もう一度聞くボタンの
   近くに常に見せる、順位ルールの要点だけの短い文。ピンク寄りの控えめな色にし、目立たせ
   すぎない（本人指示の恒久ルール：本文・補足テキストは黒ではなくブランドカラー寄りに）。 */
.online-instant-battle-rank-hint {
  margin: 4px 0 0;
  font-size: 0.72rem;
  color: var(--color-primary-dark);
  opacity: 0.85;
  text-align: center;
}

.online-instant-battle-rank-hint[hidden] {
  display: none;
}

/* 【2026-09-16新設・本人指示：実機フィードバック項23-24「わからないボタンが回答候補
   一覧の下に押し出される」の修正】「もう一度聞く」と「わからない」を横並びの操作行に
   まとめ、375px幅でも回答候補一覧より前・スクロールなしで必ず見える位置に固定する。
   .button-rowは.primary-button＋.secondary-button用に既にある共通の横並びflexコンテナ
   （.secondary-button自体がflex:1を持つため、そのままでも均等割りされる）。 */
.online-instant-battle-action-row {
  margin-bottom: 14px;
}

/* .instant-challenge-replay-buttonは単独配置（画面いっぱいの幅）を前提にwidth:100%・
   margin付きで設計されているため、.button-row内ではその想定を上書きする
   （直上にある.button-row .primary-buttonの上書きと同じ理由・同じパターン）。 */
.online-instant-battle-action-row .instant-challenge-replay-button {
  width: auto;
  margin: 0;
}

/* 「わからない」ボタンは短いテキストのため、隣の「もう一度聞く」と高さを揃えつつ
   縦積みでの間延びを防ぐ。 */
.online-instant-battle-action-row .secondary-button {
  min-height: 44px;
}

/* 【本人指示12・13：回答内容は秘密のまま、状態だけを見せる】ルーム参加順で
   「回答済み／未回答」のバッジだけを並べる一覧。.online-lobby-player-rowと同じ質感に揃える。 */
.online-instant-battle-answer-status-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
}

/* display:flexを明示指定しているクラスは[hidden]の既定表示（display:none）より詳細度が
   高く上書きしてしまうため、明示的な上書きが必要（このプロジェクトで繰り返し踏んでいる
   CSS詳細度の既知パターン）。一瞬協力側でこのクラスをUL要素へ直接使う際に必要になった。 */
.online-instant-battle-answer-status-list[hidden] {
  display: none;
}

.online-instant-battle-answer-status-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: 12px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
}

.online-instant-battle-answer-status-name {
  flex: 1;
  min-width: 0;
  font-size: 0.8rem;
  font-weight: 700;
  /* 2026-09-26改訂・本人指示：UI恒久ルール（黒一色に見せない）。参加者名は
     .online-lobby-player-name・.battle-rank-nameと同じブランドピンクへ揃える。 */
  color: var(--color-primary-dark);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.online-instant-battle-answer-status-badge {
  flex: none;
  font-size: 0.68rem;
  font-weight: 800;
  padding: 3px 10px;
  border-radius: 999px;
  color: var(--color-text);
  opacity: 0.6;
  background: var(--color-surface);
  border: 1px solid var(--color-card-border);
}

.online-instant-battle-answer-status-badge.is-answered {
  opacity: 1;
  color: var(--color-primary-dark);
  background: var(--color-accent-soft);
  border-color: var(--color-primary);
}

/* 【本人指示11・18：5秒間の答え合わせ画面】参加者ごとに、回答・正誤・その問題で使った
   再視聴回数・通算成績を375px幅でも1行に収まる簡潔な形で見せる。 */
.online-instant-battle-reveal-player-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
  text-align: left;
}

.online-instant-battle-reveal-player-list[hidden] {
  display: none;
}

.online-instant-battle-reveal-player-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 8px;
  padding: 8px 12px;
  border-radius: 12px;
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
}

.online-instant-battle-reveal-player-row.is-correct {
  border-color: var(--color-primary);
  background: var(--color-accent-soft);
}

.online-instant-battle-reveal-player-name {
  flex: none;
  font-size: 0.78rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  min-width: 5.5em;
}

.online-instant-battle-reveal-player-answer {
  flex: 1;
  min-width: 0;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.online-instant-battle-reveal-player-meta {
  flex: none;
  width: 100%;
  font-size: 0.66rem;
  color: var(--color-primary-dark);
  opacity: 0.75;
}

/* 【2026-09-16新設・本人指示：実機フィードバック項25-26】最終結果画面、各プレイヤーの
   成績カード。以前は「正解1問／正解した問題での再視聴0回（参考：総再視聴0回・不正解2・
   わからない0）」という1行の長文を薄い文字で表示していたが、短いラベル＋太字の数字を
   使ったチップを2段（順位判定に直結する数値の段／参考記録の段）に分けて配置し直した。
   375px幅でも縦に間延びしないよう、1段あたり最大2チップの横並びに留めている。 */
.online-instant-battle-result-stat-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 6px;
}

.online-instant-battle-result-stat-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.online-instant-battle-result-stat-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--color-surface);
  border: 1px solid var(--color-card-border);
}

/* 正解数・正解した問題での再視聴回数：順位判定に直結する最重要の2値
   （js/instantBattleMatchProgress.jsのcompareInstantBattlePlayerResults()参照）。
   背景を差し色つきにして視覚的に一段目立たせる。 */
.online-instant-battle-result-stat-row.is-primary .online-instant-battle-result-stat-chip {
  background: var(--color-accent-soft);
  border-color: var(--color-accent);
}

.online-instant-battle-result-stat-icon {
  font-size: 0.85rem;
  line-height: 1;
}

.online-instant-battle-result-stat-value {
  font-weight: 800;
  color: var(--color-primary-dark);
  font-variant-numeric: tabular-nums;
}

/* 正解数：このカードの中で最も重要な数値のため、最も大きく表示する。 */
.online-instant-battle-result-stat-chip.is-correct-count .online-instant-battle-result-stat-value {
  font-size: 1.15rem;
}

/* 正解した問題での再視聴回数：同率タイブレークに使う2番目に重要な数値。
   太字は保ちつつ、正解数よりは控えめなサイズにする。 */
.online-instant-battle-result-stat-chip.is-replay-count .online-instant-battle-result-stat-value {
  font-size: 0.92rem;
}

.online-instant-battle-result-stat-row.is-primary .online-instant-battle-result-stat-label {
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  opacity: 0.8;
}

/* 不正解数・わからない数：順位には一切影響しない参考記録。数値である以上、薄すぎる
   色にはせず基本文字色（濃い色）は保ったまま、太さ・大きさだけを上の2値より
   控えめにして「参考記録である」ことを視覚的に区別する。 */
.online-instant-battle-result-stat-row.is-reference .online-instant-battle-result-stat-chip {
  background: transparent;
  border-color: transparent;
  padding: 2px 6px;
}

.online-instant-battle-result-stat-row.is-reference .online-instant-battle-result-stat-icon {
  font-size: 0.72rem;
  opacity: 0.75;
}

.online-instant-battle-result-stat-row.is-reference .online-instant-battle-result-stat-value {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.8;
}

.online-instant-battle-result-stat-row.is-reference .online-instant-battle-result-stat-label {
  font-size: 0.62rem;
  font-weight: 600;
  color: var(--color-text);
  opacity: 0.65;
}

.online-instant-battle-result-stat-footnote {
  margin: 0;
  font-size: 0.62rem;
  font-weight: 600;
  color: var(--color-text);
  opacity: 0.55;
}

.online-lyrics-battle-status-message {
  text-align: center;
  font-size: 0.85rem;
  font-weight: 700;
  padding: 10px;
  border-radius: 12px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  margin-bottom: 14px;
}

/* スマホ幅では回答候補ボタンを2列に固定し、タップしやすい大きさを確保する。 */
@media (max-width: 480px) {
  .online-lyrics-battle-answer-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ===== ライブコールモード：再生方法選択画面（2026-08-09新設） ===== */
.live-call-play-type-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 8px;
}

.live-call-play-type-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 18px 20px;
  border: none;
  border-radius: 20px;
  background: var(--color-surface-glass);
  backdrop-filter: blur(var(--blur-glass));
  border: 1.5px solid var(--color-card-border);
  box-shadow: var(--shadow-card);
  text-align: left;
  font-family: inherit;
  cursor: pointer;
  transition: transform var(--transition-fast) cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow var(--transition-base);
}

.live-call-play-type-card:active {
  transform: scale(0.97);
}

@media (hover: hover) {
  .live-call-play-type-card:hover {
    box-shadow: 0 20px 44px -12px rgba(255, 79, 150, 0.45);
    transform: translateY(-2px);
  }
}

.live-call-play-type-icon {
  font-size: 1.8rem;
  line-height: 1;
}

.live-call-play-type-name {
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.live-call-play-type-description {
  font-size: 0.82rem;
  color: var(--color-text);
  opacity: 0.75;
}

/* ===== ライブコールモード：カラオケ同期・初心者ナビ画面 UI/UX第3版（2026-08-09） =====
   本人の最重要フィードバック：「機能や情報が多すぎて、カラオケ中に何を見て何を押せば
   いいのか分かりにくい」。【設定画面】から【カラオケ中専用HUD】へ全面再設計し、画面の
   情報優先順位を S=現在のコール > A=NEXT CALL・カウントダウン > B=現在の歌詞 >
   C=タイミング調整 > D=曲名 > E=その他設定 の順に統一した（曲名や状態表示が主役より
   目立っていたUI/UX第2版からの反省）。
   本人の別の最重要フィードバック：「歌詞・コールの表示内容が変わっても、下部の操作ボタンの
   位置が1pxも動いてはいけない」は継続方針。この画面だけ.game-frame自体をviewport高さに
   固定したうえで、画面を①ヘッダー②中央（ここだけスクロール）③下部固定の3ゾーンに分ける
   flexレイアウトにする（ページ本体のdocumentスクロールに一切依存しない）。
   body[data-screen="..."]はjs/screens.jsのshowScreen()が既に自動で付け外ししている
   属性をそのまま使っており、この画面専用の新しいJSは書いていない。 */

body[data-screen="liveCallModeKaraoke"] {
  padding-top: 0;
  padding-bottom: 0;
}

body[data-screen="liveCallModeKaraoke"] .game-frame {
  height: var(--game-frame-safe-height);
  max-height: var(--game-frame-safe-height);
  display: flex;
  flex-direction: column;
}

#live-call-mode-karaoke-screen {
  padding: 0;
}

#live-call-mode-karaoke-screen.is-active {
  display: flex;
  flex-direction: column;
  /* flex-basis:autoではなく0にする（flex:1の省略形）。.game-frame→この画面→中央ゾーンと
     flexが3階層ネストしており、flex-basis:autoだと内側の内容量を先に見てしまい、
     「残り空間を100%埋める」が期待通りに働かない実機不具合を確認したため。 */
  flex: 1;
  min-height: 0;
}

/* ダブルタップズーム対策（本人指示：viewportのuser-scalable=noは使わず、この画面の
   操作ボタンだけに絞ってtouch-action:manipulationを当てる。ピンチズーム自体は
   アプリ全体で引き続き可能なまま）。 */
#live-call-mode-karaoke-screen button,
#karaoke-more-menu-modal button {
  touch-action: manipulation;
}

/* クイズ回答中の誤操作防止（2026-08-28新設、2026-08-29改訂×2・本人指示）。
   【改訂の経緯①】2026-08-28時点ではtouch-action:pan-y・overscroll-behavior:containだけで
   対応していたが、実機で「ピンチズーム・ドラッグ操作をすると、ページ自体の表示位置が
   ずれる」現象を防ぎきれないという報告があった。touch-action等はbody（またはhtml）を
   スクロール可能な状態のまま抑え込もうとする対症療法のため、ブラウザ・OSによっては
   完全には防げない。
   【新しい方針①】viewport自体のuser-scalable=noは使わない（本人の既存方針を踏襲）。
   代わりに、ライブコールモード・カラオケ同期画面（#live-call-mode-karaoke-screen、
   上記コメント参照）で実績のある「.game-frame自体をviewport高さ（100dvh）に固定し、
   ページ本体のdocumentスクロールに一切依存しない」設計を、回答中の3画面
   （#quiz-screen・#lyrics-quiz-question-screen・#online-lyrics-battle-question-screen）
   にもそのまま適用する。
   【改訂の経緯②・本人からの実機報告】①の直後は、iPhoneで「戻る」ボタンがステータスバー・
   Dynamic Islandと重なって押しづらい／UIが上に詰まって下に大きな空白ができる／
   まだほんの少しだけ縦にスクロールできる、という3つの不具合が起きていた。原因は次の3つ：
   ①bodyのpadding-topを0にした際、元々あった安全域確保
   （padding-top: max(64px, calc(env(safe-area-inset-top) + 20px))）も一緒に消してしまい、
   代わりに#quiz-screen.is-active側で入れていたpaddingが固定値（20px）でsafe-area-inset-topを
   見ていなかった（＝ノッチ/Dynamic Island環境で戻るボタンが実際の表示可能領域より上に
   はみ出していた）。
   ②.quiz-middle-zone（中央ゾーン）の中身が、天井（ヘッダー直下）に寄せたまま並んでいた
   （中身が少ない画面ではflex:1の余白がすべて下に残ってしまう見た目になる）。
   ③.game-frameはheight:100dvhで正確に画面に合わせているのに対し、bodyはmin-height:100vh
   のままだった。iOSでは100vh（アドレスバー等が引っ込んだ最大状態を基準にした値）が
   100dvh（今実際に見えている値）よりわずかに大きくなることがあり、bodyの箱自体が
   game-frameより少しだけ縦に大きくなって、その差分だけスクロールできてしまっていた。
   【今回の対策】
   ・#quiz-screen.is-active等のpadding-topをsafe-area-inset-topを見た値に変更（①の修正）。
   ・.quiz-middle-zoneをflex縦並びにし、中身を.quiz-middle-zone-innerで包んでmargin:auto 0を
     指定。余白があるときは自動的に上下中央へ寄り、中身が画面に収まりきらない場合は
     auto marginが0になり今までどおり上詰め＋内部スクロールに自然に切り替わる
     （justify-content:centerだと一部ブラウザで「収まらない時に上側が見えなくなる」不具合が
     あるため、あえてmargin:autoの方式を使っている）（②の修正）。
   ・bodyにoverflow:hiddenを追加し、100vh/100dvhの差やその他の丸め誤差が万一あっても、
     body自体が縦横どちらにも一切スクロールしない状態を保証する（③の修正、最終防衛線）。
   【中身が画面に収まらない場合】「隠れて操作不能になる」事故を防ぐフォールバックとして、
   ヘッダー以外（.quiz-middle-zone）だけに限定してoverflow-y:autoを持たせる
   （#lyrics-quiz-question-screenの回答候補一覧のように、既存の内部スクロール領域とも
   干渉しない）。通常の画面サイズでは、既存のレイアウトのままこのスクロールが
   発生する場面はほぼ無い想定。 */
body[data-screen="quiz"],
body[data-screen="lyricsQuizQuestion"],
body[data-screen="onlineLyricsBattleQuestion"],
/* 【2026-08-30追加・本人報告の不具合対応】一瞬チャレンジの問題画面（HTML側の
   .quiz-middle-zoneラッパー自体は既にあったが、この画面固定ルールの対象に
   入れ忘れていたため、クイズ中に上下スクロールできてしまっていた）。 */
body[data-screen="instantChallengeQuestion"] {
  padding-top: 0;
  padding-bottom: 0;
  overflow: hidden;
}

body[data-screen="quiz"] .game-frame,
body[data-screen="lyricsQuizQuestion"] .game-frame,
body[data-screen="onlineLyricsBattleQuestion"] .game-frame,
body[data-screen="instantChallengeQuestion"] .game-frame {
  height: var(--game-frame-safe-height);
  max-height: var(--game-frame-safe-height);
  display: flex;
  flex-direction: column;
}

#quiz-screen.is-active,
#lyrics-quiz-question-screen.is-active,
#online-lyrics-battle-question-screen.is-active,
#instant-challenge-question-screen.is-active {
  display: flex;
  flex-direction: column;
  /* 【2026-08-29再改訂】固定値20pxではなく、Dynamic Island・ノッチのsafe areaぶんを
     必ず確保する（実機で戻るボタンがステータスバーと重なっていた不具合の修正）。
     【2026-11-XX再改訂・本人指示：iPhone実機で上部UIがステータスバーに寄りすぎている
     不具合の修正】.game-frameをviewport高さへ固定する設計へ移行した際（このコメントブロック
     の上にある「①bodyのpadding-topを0にした際」の記録参照）、元々bodyが持っていた
     max(64px, calc(env(safe-area-inset-top) + 20px))という余裕のある安全域確保が、
     この画面側のmax(16px, env(safe-area-inset-top))という控えめな値に置き換わって
     しまっており、safe-area-inset-topぴったりの位置に「戻る」リンクが接するため、
     Dynamic Island環境で時刻表示・ステータスバーと窮屈に重なって見える・押しにくいという
     実機報告につながっていた。安全域の実測値そのものに、追加で12pxの余白を必ず足す
     （下限も20pxへ引き上げ、safe-areaが取得できない環境でも最低限の余白を確保する）。
     以前の64pxほど大きくはしない（本人指示：「下げすぎて無駄な空白だらけにはしないで」＝
     .quiz-middle-zone側の内部スクロールfallbackへ不必要に頼らせない範囲で、わずかに
     増やすだけに留める）。
     【2026-09-05再々改訂・本人指示：最初だけ上に寄る不具合の根本対応】env(safe-area-inset-top)も
     dvhと同様、iOS Safariでは画面表示直後の最初の1回だけ0に近い値のまま確定していないことが
     あり、それがこの「最初だけ上に詰まって見え、効果音設定を開閉すると直る」不具合の原因の
     1つだった（js/viewportMeasurement.js参照、--game-frame-safe-heightの説明と同じ理由）。
     env()の代わりに、JSで実測して書き込む--measured-safe-area-inset-topを優先的に使い、
     測定前・非対応環境ではenv(safe-area-inset-top)へ自然にフォールバックする。 */
  padding: max(20px, calc(var(--measured-safe-area-inset-top, env(safe-area-inset-top, 0px)) + 12px)) 20px 0;
  flex: 1;
  min-height: 0;
}

#quiz-screen.is-active .quiz-header-row,
#lyrics-quiz-question-screen.is-active .quiz-header-row,
#online-lyrics-battle-question-screen.is-active .quiz-header-row,
#instant-challenge-question-screen.is-active .quiz-header-row {
  flex: none;
}

/* ②中央ゾーン：この中だけが縦スクロールする（カラオケ画面の.karaoke-middle-zoneと同じ考え方）。
   touch-action:pan-yは、万一の縦スクロール発生時に指の操作を素直に受け付けるためのもので、
   ピンチズーム（複数指操作）は仕様上pan-y指定時点で抑えられる。
   【2026-08-29追加】縦並びのflexにし、.quiz-middle-zone-inner（中身側）で上下位置を調整する。
   中身が画面に収まらないときは（下のmargin-bottom:auto実装により）自動的にauto分が0になるため、
   overflow-y:autoによる内部スクロールへ滑らかに切り替わる（安全側のフォールバックは維持）。 */
.quiz-middle-zone {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  overscroll-behavior-y: contain;
  padding-bottom: max(20px, env(safe-area-inset-bottom));
}

/* 【2026-08-29再々改訂・本人指示】中央へ完全に寄せる（margin:auto 0）と、実機で
   問題エリアが画面中央付近まで下がりすぎて見た目が不自然という指摘があった。
   「戻る」ボタンの少し下に自然な余白を空けて問題エリアを配置し、余った空間は
   下側にだけ残す方針に変更する（margin-top:固定値・margin-bottom:auto）。
   中身が画面に収まらない場合はmargin-bottom:autoが0になり、今までどおり上詰め＋
   .quiz-middle-zoneの内部スクロールへ自然に切り替わる（この安全側のフォールバックは
   変更していない）。
   【2026-08-29四訂・本人指示】上のmargin-top:16pxでもまだ問題エリアが下すぎるとの
   指摘があり、「戻る」ボタンの安全な位置はそのままに、問題エリアだけをさらに上へ
   寄せるため8pxへ縮小した（「戻る」自体の余白は#quiz-screen.is-active側のpadding-topと
   .quiz-back-link自身のpadding・margin-bottom:0で確保しており、ここでは変更していない）。 */
.quiz-middle-zone-inner {
  width: 100%;
  margin: 8px 0 auto;
}

/* 回答ボタン・選択肢まわりはダブルタップズームだけ追加で防ぐ（カラオケ画面と同じ考え方）。 */
#choice-buttons button,
.lyrics-quiz-answer-list button,
#online-lyrics-battle-answer-choices button {
  touch-action: manipulation;
}

/* 【2026-11-XX新設・本人指示：クイズ実プレイ中の長押し文字選択防止】回答ボタン・問題文等を
   長押しすると、iPhone等で文字が青く選択されたりテキスト選択UIが表示される。早押しクイズの
   実プレイ中はこれが邪魔になるため防止する。
   【適用範囲について本人指示厳守】アプリ全体へ無条件のuser-select:noneは絶対に掛けない
   （管理者用音源診断ログ・ロビーrender診断ログ画面、入力欄、検索、コピーが必要な画面、
   説明文等では今後も文字選択・コピーが必要なため）。実際に即時回答型の選択肢を持つ
   「クイズ実プレイ画面」だけに限定してscopeする（下のセレクタ一覧が対象の全画面）。
   入力欄（歌詞クイズ大規模プール検索窓等）は、ここでuser-select:textを明示的に上書きして
   従来どおり選択・タイプできるようにする（フォームコントロール自体は元々ancestorの
   user-select:noneの影響を受けにくいが、念のため明示しておく）。 */
#quiz-screen.is-active,
#lyrics-quiz-question-screen.is-active,
#online-lyrics-battle-question-screen.is-active,
#instant-challenge-question-screen.is-active,
#online-instant-battle-question-screen.is-active,
#online-instant-coop-battle-question-screen.is-active {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

#quiz-screen.is-active input,
#quiz-screen.is-active textarea,
#lyrics-quiz-question-screen.is-active input,
#lyrics-quiz-question-screen.is-active textarea,
#online-lyrics-battle-question-screen.is-active input,
#online-lyrics-battle-question-screen.is-active textarea,
#instant-challenge-question-screen.is-active input,
#instant-challenge-question-screen.is-active textarea,
#online-instant-battle-question-screen.is-active input,
#online-instant-battle-question-screen.is-active textarea,
#online-instant-coop-battle-question-screen.is-active input,
#online-instant-coop-battle-question-screen.is-active textarea {
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}

/* 【2026-09-30新設・本人指示：オンライン対戦総合改修 第2ラウンド7章】オンライン対戦の
   ロビー・ルール確認・結果画面での誤ったピンチズーム／ダブルタップズームを防ぐ。
   クイズ回答画面（#quiz-screen等）は「game-frameをviewport高さに固定」という
   縦スクロール自体が発生しない専用設計だが、ロビー・ルール確認・結果画面は元々
   縦に長く、通常のページスクロールが必要な画面のため、同じ固定化はできない。
   代わりに、body側にtouch-action:pan-yを当てて「縦方向の指1本操作だけ」を許可する
   （2本指のピンチ操作はpan-y指定時点で仕様上抑えられる。横スクロール自体が元々
   発生しない画面のため、pan-yに絞っても既存の見え方は変わらない）。 */
body[data-screen="onlineBattleLobby"],
body[data-screen="onlineBattleConfirm"],
body[data-screen="onlineBattleRematchReady"],
body[data-screen="onlineBattleResult"],
body[data-screen="onlineLyricsBattleResult"],
body[data-screen="onlineInstantBattleResult"],
body[data-screen="onlineInstantCoopBattleResult"] {
  touch-action: pan-y;
  overscroll-behavior-y: contain;
}

/* 上記画面内のボタンは、ダブルタップズームだけ追加で防ぐ（タップの反応速度への
   悪影響が無いよう、manipulationはズーム抑制のみでクリック自体は今までどおり）。 */
#online-battle-lobby-screen button,
#online-battle-confirm-screen button,
#online-battle-rematch-ready-screen button,
#online-battle-result-screen button,
#online-lyrics-battle-result-screen button,
#online-instant-battle-result-screen button,
#online-instant-coop-battle-result-screen button {
  touch-action: manipulation;
}

/* ①ヘッダーゾーン：戻る・曲名・「⋯」・？を1行に収める最小構成（本人指示：1〜2行まで）。
   高さは内容なりで、伸び縮みしない。 */
.karaoke-header-zone {
  flex: none;
  padding: max(10px, env(safe-area-inset-top)) 14px 8px;
  border-bottom: 1px solid var(--color-card-border);
}

.karaoke-header-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.karaoke-header-title {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.karaoke-icon-button {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 1rem;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
}

.karaoke-icon-button[hidden] {
  display: none;
}

.karaoke-icon-button:active {
  transform: scale(0.92);
}

.karaoke-icon-button .back-link-icon {
  width: 16px;
  height: 16px;
}

/* ②中央ゾーン：内容によって高さが変わるのはここだけ。ここだけが縦スクロールする
   （min-height:0がFlexboxでoverflow:autoを効かせるために必須）。
   スクロールバーは機能を残したまま見た目だけ抑え、「アプリらしい」質感にする
   （本人指示：webページっぽさを減らす）。 */
.karaoke-middle-zone {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 4px 20px 16px;
  scrollbar-width: none;
}

.karaoke-middle-zone::-webkit-scrollbar {
  display: none;
}

/* ===== STATE A：開始前パネル。最小構成（本人指示：いきなり大量の設定を見せない） ===== */
.karaoke-start-panel {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  padding: 16px 4px 8px;
  text-align: center;
}

.karaoke-start-panel[hidden] {
  display: none;
}

.karaoke-start-instruction {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  margin-bottom: 6px;
}

.karaoke-inline-notice {
  font-size: 0.78rem;
  color: var(--color-text);
  background: var(--color-surface-glass);
  border: 1px solid var(--color-card-border);
  border-radius: 10px;
  padding: 8px 10px;
  margin: 0 0 12px;
}

.karaoke-inline-notice[hidden] {
  display: none;
}

.karaoke-start-button {
  width: 100%;
  padding: 26px 16px;
  margin-top: 8px;
  border: none;
  border-radius: 28px;
  background: linear-gradient(120deg, var(--color-primary-dark), var(--color-primary) 45%, var(--color-secondary));
  background-size: 200% auto;
  color: #ffffff;
  font-family: inherit;
  font-size: 1.3rem;
  font-weight: 800;
  cursor: pointer;
  box-shadow: 0 18px 40px -12px rgba(255, 79, 150, 0.6);
  animation: primaryButtonGlow 2.6s ease-in-out infinite;
  transition: transform var(--transition-fast) cubic-bezier(0.34, 1.56, 0.64, 1);
}

.karaoke-start-button:active {
  transform: scale(0.95);
}

.karaoke-start-note {
  font-size: 0.8rem;
  color: var(--color-text);
  opacity: 0.7;
  margin-top: 10px;
}

/* ===== STATE B：同期中パネル。UI/UX第4版で「現在の歌詞（複数行）」を復活させ、
   「歌詞で現在位置を追える」＋「コールは通常再生より圧倒的に分かりやすい」の両立を目指す
   （本人指示：どちらか一方に寄せすぎない）。中身（歌詞パネル・HUDカード）をflexで
   縦に並べ、S=現在のコール＞A=NEXT CALL＞B=現在の歌詞の優先順位のまま、両方を同時に見せる。 */
.karaoke-middle-zone {
  display: flex;
  flex-direction: column;
}

.karaoke-sync-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
  min-height: 0;
}

.karaoke-sync-panel[hidden] {
  display: none;
}

/* B：現在の歌詞（複数行・スクロール可能）。既存の.synced-lyrics-panelをそのまま流用し、
   ハイライト・自動追従スクロール・全文表示切替・行タップ（js/karaokeSyncScreen.jsの
   handleLyricTapSeek）まで、通常再生画面と同じロジックを1行も複製せずに再利用している。
   base(.synced-lyrics-panel)のmax-height:150pxをここで打ち消し、flexで高さを配分する。 */
.karaoke-lyrics-context-panel {
  flex: 1 1 0;
  min-height: clamp(70px, 15vh, 140px);
  max-height: none;
  margin-top: 0;
  transition: flex-grow var(--transition-base), opacity var(--transition-base);
}

.karaoke-lyrics-context-panel .synced-lyrics-line {
  font-size: 0.85rem;
  padding: 4px 6px;
  /* ダブルタップズーム対策（本人指示：スクロール自体は妨げないtouch-action:manipulationのみ使う）。 */
  touch-action: manipulation;
}

.karaoke-lyrics-context-panel .synced-lyrics-line.is-current-lyrics-line {
  font-size: 0.95rem;
}

/* 長い口上・MIXが実際に鳴っている間だけ、歌詞コンテキストを控えめに縮めてコール本文へ意識を
   集中させる。ただし完全には消さない（本人の最重要指示：歌詞1行表示には戻さない）。
   終わったら自動で元の比率に戻る（js/karaokeSyncScreen.jsがクラスを付け外しするだけ）。 */
.karaoke-sync-panel.is-long-call-active .karaoke-lyrics-context-panel {
  flex-grow: 0.45;
  opacity: 0.55;
}

.karaoke-sync-panel.is-long-call-active .karaoke-call-hud-card {
  flex-grow: 2.6;
}

/* S・A：現在のコール／NEXT CALLカード。画面の主役として、中央ゾーンの過半を占める。
   色だけでなく、見出し文言・文字サイズ・アニメーションでも「今は何も言わない／もうすぐ言う／
   今言う」の3段階を伝える（本人指示、色だけに依存しない）。 */
.karaoke-call-hud-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex: 1.6 1 0;
  min-height: clamp(150px, 32vh, 300px);
  padding: 24px 18px;
  border-radius: 24px;
  background: var(--color-surface-glass);
  border: 1.5px solid var(--color-card-border);
  box-shadow: var(--shadow-card);
  text-align: center;
  transition: box-shadow var(--transition-base), background var(--transition-base), border-color var(--transition-base),
    flex-grow var(--transition-base);
}

.karaoke-call-hud-eyebrow {
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  color: var(--color-secondary);
}

.karaoke-call-hud-text {
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  word-break: break-word;
}

.karaoke-call-hud-countdown {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

/* NEXT予告（UI/UX第6版で追加）：現在／次のコールより優先度を落とした、ごく小さな2件までの
   予告表示。本文の主役はあくまでcallHudText側のため、文字サイズ・彩度ともに控えめにする
   （本人指示：優先順位は「現在・もうすぐ」＞「次のコール」＞「その次」＞「さらにその次」）。 */
.karaoke-call-hud-preview-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 4px 8px;
  margin: 2px 0 0;
  max-width: 100%;
}

.karaoke-call-hud-preview-row[hidden] {
  display: none;
}

.karaoke-call-hud-preview-label {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.55;
}

.karaoke-call-hud-preview-item {
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--color-secondary);
  opacity: 0.85;
  max-width: 40vw;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.karaoke-call-hud-preview-item[hidden] {
  display: none;
}

/* 次の予告は、その次の予告よりわずかに強調する（★★☆☆☆＞★☆☆☆☆の優先順位を、
   彩度の差だけで表現する。文言や色分けの断定表現は使わない）。 */
.karaoke-call-hud-preview-item + .karaoke-call-hud-preview-item {
  opacity: 0.6;
}

/* もうすぐ！段階：見出しをオレンジ系に変え、カウントダウンの数字を大きく発光させる */
.karaoke-call-hud-card.is-imminent {
  animation: karaokeImminentPulse 1s ease-in-out infinite;
}

.karaoke-call-hud-card.is-imminent .karaoke-call-hud-eyebrow {
  color: var(--color-call-glow);
}

.karaoke-call-hud-card.is-imminent .karaoke-call-hud-countdown {
  font-size: 2.4rem;
  font-weight: 800;
  color: var(--color-call-glow);
  line-height: 1;
}

@keyframes karaokeImminentPulse {
  0%,
  100% {
    box-shadow: var(--shadow-card);
    transform: scale(1);
  }
  50% {
    box-shadow: 0 0 0 8px rgba(255, 159, 67, 0.35), var(--shadow-card);
    transform: scale(1.02);
  }
}

/* コール中！段階：カードそのものを一段強く発光させ、本文をtier別の大きさで主役にする
   （tierはjs/karaokeSync.jsのgetCallDisplayTier。既存の飛び出しバースト演出と同じ基準で
   「短い」を判定し、はい！／オレ！のような一言はSHORTで画面いっぱいに、MIX・口上のような
   長文はLONGで読める大きさに抑える）。 */
.karaoke-call-hud-card.is-now {
  border-color: var(--color-accent);
  background: var(--color-accent-soft);
  box-shadow: 0 0 0 6px rgba(255, 217, 61, 0.4), var(--shadow-card);
}

/* SHORT：「はい！」「オレ！」のような一瞬で言う一言コール。ポンッと勢いよく拡大・発光し、
   すぐ通常サイズへ収まる。既存の飛び出しバースト演出（.call-burst-text）と同じ色味・
   質感を踏襲しつつ、画面全体を覆うfixedレイヤーは使わずカード内で完結させている
   （UI/UX第3版の「長文コールが画面を乗っ取る」問題の再発を避けるため）。 */
.karaoke-call-hud-card.is-now.is-tier-short {
  animation: karaokeShortCallFlash 500ms ease-out;
}

.karaoke-call-hud-card.is-now.is-tier-short .karaoke-call-hud-text {
  font-size: clamp(2.2rem, 13vw, 3.4rem);
  text-shadow: 0 0 10px rgba(255, 255, 255, 0.85), 0 0 22px var(--color-call-glow);
  animation: karaokeCallPop 420ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes karaokeShortCallFlash {
  0% {
    box-shadow: 0 0 0 16px rgba(255, 217, 61, 0.55), var(--shadow-card);
  }
  100% {
    box-shadow: 0 0 0 6px rgba(255, 217, 61, 0.4), var(--shadow-card);
  }
}

@keyframes karaokeCallPop {
  0% {
    transform: scale(0.6) rotate(-3deg);
    opacity: 0;
  }
  55% {
    transform: scale(1.12) rotate(2deg);
    opacity: 1;
  }
  100% {
    transform: scale(1) rotate(0deg);
  }
}

/* MEDIUM：短文ほど瞬間的ではない中程度のコール。文字が動きすぎて読みにくくならないよう、
   軽く浮き上がるだけの控えめな演出にとどめる（本人指示）。 */
.karaoke-call-hud-card.is-now.is-tier-medium {
  animation: karaokeMediumCallLift 320ms ease-out;
}

.karaoke-call-hud-card.is-now.is-tier-medium .karaoke-call-hud-text {
  font-size: clamp(1.5rem, 7vw, 2rem);
}

@keyframes karaokeMediumCallLift {
  0% {
    transform: translateY(8px);
    opacity: 0.6;
  }
  100% {
    transform: translateY(0);
    opacity: 1;
  }
}

/* LONG：MIX・口上のような長いコール。「読みやすさ」を最優先し、文字自体は動かさず、
   カード周囲の光がゆっくり脈打つだけにとどめる（本人指示：画面全体の点滅・激しい動きは禁止）。
   コールが終わるとis-now自体が外れるため、演出も自動的に解除される。 */
.karaoke-call-hud-card.is-now.is-tier-long {
  animation: karaokeLongCallGlow 2.2s ease-in-out infinite;
}

.karaoke-call-hud-card.is-now.is-tier-long .karaoke-call-hud-text {
  width: 100%;
  max-height: 38vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  font-size: clamp(1rem, 4.3vw, 1.2rem);
  line-height: 1.5;
  text-align: left;
}

@keyframes karaokeLongCallGlow {
  0%,
  100% {
    box-shadow: 0 0 0 6px rgba(255, 217, 61, 0.4), var(--shadow-card);
  }
  50% {
    box-shadow: 0 0 0 11px rgba(255, 217, 61, 0.6), var(--shadow-card);
  }
}

/* 初心者ナビOFF：NEXT CALLの見出し・カウントダウン・NEXT予告といった装飾を省き、
   コール本文だけを見せる（本人指示：カラオケに慣れている人は表示をシンプルにできる）。 */
.karaoke-call-hud-card.is-nav-minimal .karaoke-call-hud-eyebrow,
.karaoke-call-hud-card.is-nav-minimal .karaoke-call-hud-countdown,
.karaoke-call-hud-card.is-nav-minimal .karaoke-call-hud-preview-row {
  display: none;
}

/* 曲が最後まで再生し終えたときの案内（本人指示：「同期中」のまま延々と残らないように）。 */
.karaoke-song-end-banner {
  margin-top: 16px;
  padding: 18px 16px;
  border-radius: 18px;
  background: var(--color-surface-glass);
  border: 1.5px solid var(--color-card-border);
  text-align: center;
}

.karaoke-song-end-banner[hidden] {
  display: none;
}

.karaoke-song-end-title {
  font-weight: 800;
  color: var(--color-primary-dark);
  margin-bottom: 10px;
}

.karaoke-song-end-actions {
  display: flex;
  gap: 8px;
}

.karaoke-song-end-button {
  flex: 1;
  min-height: 44px;
  border: none;
  border-radius: 14px;
  background: linear-gradient(120deg, var(--color-primary-dark), var(--color-primary));
  color: #ffffff;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
}

.karaoke-song-end-button:active {
  transform: scale(0.95);
}

#karaoke-song-end-choose-button {
  background: var(--color-surface);
  color: var(--color-primary-dark);
  border: 1.5px solid var(--color-primary);
}

/* ③下部ゾーン：タイミング調整だけを常時固定表示する。中央の内容がどう変わっても
   ここの位置・高さは変えない。position:relativeは、トースト（.karaoke-toast）を
   絶対配置で重ねて表示するための基準。 */
.karaoke-footer-zone {
  position: relative;
  flex: none;
  padding: 10px 20px max(14px, env(safe-area-inset-bottom));
  background: var(--color-surface);
  border-top: 1.5px solid var(--color-card-border);
  box-shadow: 0 -10px 24px -16px rgba(74, 46, 66, 0.3);
}

.karaoke-footer-zone[hidden] {
  display: none;
}

/* ボタンを押した瞬間の短いフィードバック（本人指示：「0.5秒遅らせました」等）。
   【重要】position:absoluteで下部ゾーンの外（境界線のすぐ上）に浮かせて表示する。
   通常のフローに入れてしまうと、表示/非表示の切り替わりで下部ゾーン自体の高さが
   変わり、タイミング調整ボタンの位置が動いてしまう（本人が最も嫌っていた現象そのもの）ため、
   トーストの表示状態が他の要素の位置に一切影響しない設計にしている。 */
.karaoke-toast {
  position: absolute;
  left: 50%;
  bottom: 100%;
  z-index: 1;
  margin-bottom: 6px;
  text-align: center;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
  border-radius: 999px;
  padding: 5px 12px;
  width: max-content;
  max-width: calc(100% - 24px);
  pointer-events: none;
  opacity: 0;
  transform: translateX(-50%) translateY(4px);
  transition: opacity 160ms ease, transform 160ms ease;
}

.karaoke-toast[hidden] {
  display: none;
}

.karaoke-toast.is-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(-4px);
}

/* 一時停止／再開ボタン（UI/UX第5版で独立した行へ分離。2026-08-09）。
   タイミング調整の数値ボタン列に混ぜると「意味が違うボタンなのに紛れて分かりにくい」という
   本人指摘を受け、専用の1行・アイコン＋文字ラベル入りボタンにした。既定では楽曲＋コール同期の
   両方をまとめて一時停止／再開する操作になる（個別に止めたい場合はヘッダーの「⋯」から）。
   既存の.icon-play/.icon-pause出し分け方式は「非playing時にicon-play」基準の他コンポーネントと
   逆（カラオケは同期開始直後が「再生中」＝アイコンはicon-pauseを既定表示にしたい）のため、
   汎用ルールに頼らずこのクラス配下だけで独自に出し分ける。 */
.karaoke-pause-resume-button {
  width: 100%;
  min-height: 46px;
  margin-bottom: 10px;
  padding: 8px 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: none;
  border-radius: 16px;
  background: linear-gradient(120deg, var(--color-primary-dark), var(--color-primary));
  color: #ffffff;
  font-family: inherit;
  font-size: 0.92rem;
  font-weight: 800;
  cursor: pointer;
  transition: transform var(--transition-fast) cubic-bezier(0.34, 1.56, 0.64, 1), background var(--transition-base);
}

.karaoke-pause-resume-button:active {
  transform: scale(0.97);
}

.karaoke-pause-resume-button svg {
  width: 18px;
  height: 18px;
  flex: none;
}

.karaoke-pause-resume-button .icon-play {
  display: none;
}

.karaoke-pause-resume-button.is-paused .icon-pause {
  display: none;
}

.karaoke-pause-resume-button.is-paused .icon-play {
  display: block;
}

.karaoke-pause-resume-button.is-paused {
  background: linear-gradient(120deg, var(--color-accent), var(--color-call-glow));
  color: var(--color-primary-dark);
}

.karaoke-pause-resume-label {
  line-height: 1;
}

/* タイミング調整。「曲が流れている最中に何度も押すか？」の基準で、常時表示するのは
   一時停止/再開ボタンとこの5ボタンだけに絞った（本人指示の判断基準）。符号の向きは
   js/karaokeSync.jsのadjustOffsetMs()と完全に対応させている：右（+側）＝早める、左（−側）＝遅らせる。 */
.karaoke-timing-heading {
  margin: 0 0 6px;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.65;
  text-align: center;
}

.karaoke-timing-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1.3fr 1fr 1fr;
  gap: 6px;
}

.karaoke-timing-button {
  min-height: 44px;
  padding: 8px 3px;
  border: 1.5px solid var(--color-secondary);
  border-radius: 14px;
  background-color: transparent;
  color: var(--color-secondary);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  cursor: pointer;
  transition: transform var(--transition-fast) cubic-bezier(0.34, 1.56, 0.64, 1), background-color var(--transition-base);
}

.karaoke-timing-button:active {
  transform: scale(0.94);
  background-color: var(--color-primary-light);
}

.karaoke-timing-reset-button {
  min-height: 44px;
  padding: 8px 3px;
  border: none;
  border-radius: 16px;
  background: linear-gradient(120deg, var(--color-primary-dark), var(--color-primary));
  color: #ffffff;
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 800;
  cursor: pointer;
}

.karaoke-timing-reset-button:active {
  transform: scale(0.94);
}

.karaoke-timing-caption-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 6px;
}

.karaoke-timing-caption {
  font-size: 0.68rem;
  color: var(--color-text);
  opacity: 0.6;
}

.karaoke-offset-inline-label {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-text);
  text-align: center;
}

/* ===== 「⋯」メニュー（UI/UX第3版で新設）。頻繁には押さない操作をまとめた副次的な画面。
   既存の.modal-overlay/.modal-cardをそのまま流用し、中身だけこの画面専用にする。 ===== */
.karaoke-more-menu-card {
  max-width: 380px;
}

.karaoke-more-menu-card h2 {
  margin: 0 0 12px;
  font-size: 1.05rem;
  color: var(--color-primary-dark);
  text-align: center;
}

.karaoke-more-menu-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  width: 100%;
  padding: 14px 10px;
  border: none;
  border-bottom: 1px solid var(--color-card-border);
  background: none;
  color: var(--color-text);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.karaoke-more-menu-item:last-child {
  border-bottom: none;
}

.karaoke-more-menu-item:active {
  background: var(--color-primary-light);
}

.karaoke-more-menu-item-icon {
  flex: none;
  font-size: 1.3rem;
  line-height: 1.3;
}

.karaoke-more-menu-item-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.karaoke-more-menu-item-name {
  font-weight: 700;
  color: var(--color-primary-dark);
  font-size: 0.92rem;
}

.karaoke-more-menu-item-description {
  font-size: 0.76rem;
  color: var(--color-text);
  opacity: 0.7;
  line-height: 1.4;
}

.karaoke-more-menu-item.is-caution .karaoke-more-menu-item-name {
  color: var(--color-danger);
}

/* ===== アクセシビリティ：モーションを減らす設定への対応 =====
   OS/ブラウザで「視差効果を減らす」等が有効なときは、
   すべてのアニメーション・トランジションをほぼ瞬時に終わらせる。 */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* 【2026-09-15新設】フレンド画面：旧IDからの引き継ぎ案内カード（js/uidSupersession.js）。
   公開設定カード（.fan-profiles-settings-card）の見た目を流用し、ボタンを縦に並べる。 */
.fan-profiles-uid-merge-card {
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
}
.fan-profiles-uid-merge-card .modal-category-list {
  margin: 8px 0 0;
  font-size: 0.85rem;
  line-height: 1.5;
}
.fan-profiles-uid-merge-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}


/* =====================================================================
   パーティー対戦（2026-09-15新設、本人指示）
   1台のスマホ／タブレットを机の中央に置き、2〜4人で囲んで早押しするローカル対戦。
   設定画面（.party-setup-*）・席選択の図（.party-seat-figure）・開始前チェック・
   対戦盤面（.party-play-*）・結果画面（.party-result-* / .party-winner-*）。
   盤面は「スマホ／タブレット」の選択を作らず、viewportの実寸と向きで自動的に伸縮する
   （本人確定）。4人4択の16ボタンは小型端末でも維持し、曲名はclamp／可変font-sizeで収める。
   ===================================================================== */

/* このアプリのCSSには全体共通の[hidden]ルールが無く、display指定を持つ要素はhidden属性だけでは
   隠れない。パーティー対戦の要素はここでまとめてhiddenを効かせる（既存の各クラスと同じ方針）。 */
#party-battle-setup-screen [hidden],
#party-battle-song-picker-screen [hidden],
#party-battle-preflight-screen [hidden],
#party-battle-play-screen [hidden],
#party-battle-result-screen [hidden] {
  display: none !important;
}

/* ---------- 席の識別色（色だけに頼らず、名前・枠・P番号も常に併用する） ---------- */
:root {
  --party-red: #f2665f;
  --party-red-soft: #ffe6e3;
  --party-blue: #4f8df2;
  --party-blue-soft: #e1edff;
  --party-green: #3fae6b;
  --party-green-soft: #dff6e7;
  --party-yellow: #e8a70d;
  --party-yellow-soft: #fff3cc;
}

[data-color="red"] { --seat-color: var(--party-red); --seat-color-soft: var(--party-red-soft); }
[data-color="blue"] { --seat-color: var(--party-blue); --seat-color-soft: var(--party-blue-soft); }
[data-color="green"] { --seat-color: var(--party-green); --seat-color-soft: var(--party-green-soft); }
[data-color="yellow"] { --seat-color: var(--party-yellow); --seat-color-soft: var(--party-yellow-soft); }

/* ---------- 設定画面 ---------- */
/* 【2026-09-15 第1回実機QA修正・本人のiPhone／iPad実機スクリーンショットで確認】
   以前は .party-setup-grid を grid-template-columns: 1fr（＝minmax(auto,1fr)：最小幅がmin-content）にし、
   タブレットは columns:2 の段組みにしていた。iOS Safariでは
     ・fieldset の既定 min-inline-size: min-content
     ・出題タイプの「auto-fill」による可変列（min-content計算で複数トラック分に膨らむ）
     ・<input>／<select> の固有幅（size属性由来の幅）が min-content に乗る
   の組み合わせで列の最小幅がviewportを超え、iPhoneでは全fieldsetが右へはみ出し、iPadでは段組みの
   列幅を超えたfieldsetが隣の列へ重なっていた。対策：
     ・すべてのトラックを minmax(0, 1fr) にして min-content を一切参照しない
     ・party設定画面内の fieldset は min-inline-size: 0 / max-width: 100% / box-sizing: border-box
     ・フレックス子要素は min-width: 0、入力欄・selectは width を明示（固有幅を寄与させない）
     ・タブレットは段組みではなく「独立した2つの列（.party-setup-col）」を minmax(0,1fr) の2トラックへ置く
   これは #party-battle-setup-screen のスコープ内だけに当て、アプリ全体の fieldset には影響させない。 */
.party-setup-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
  width: 100%;
  min-width: 0;
}

.party-setup-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
  max-width: 100%;
}

#party-battle-setup-screen fieldset {
  box-sizing: border-box;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  min-inline-size: 0;
  margin: 0 0 12px;
}

#party-battle-setup-screen fieldset > .option-row,
#party-battle-setup-screen fieldset > .rule-option-row {
  min-width: 0;
  max-width: 100%;
}

#party-battle-setup-screen fieldset label {
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
}

/* 回答方式・お手つきのカード（2枚）は横並びのまま、幅は必ず折半（min-contentに依存しない） */
#party-battle-setup-screen .rule-option-row:not(.party-quiz-type-row) {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
}

#party-battle-setup-screen .rule-option-row label.rule-option-card {
  margin: 4px 0;
  width: auto;
}

/* 出題タイプ（5枚）は2列固定（auto-fill は使わない：iOS Safariの min-content 計算で列幅が膨らむため） */
.party-quiz-type-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
}

.party-quiz-type-row label.rule-option-card {
  padding: 8px 8px 8px 12px;
}

/* タブレット以上：2列。列同士は独立して縦に流れるため、重なりは構造上起きない */
@media (min-width: 720px) {
  body[data-screen="partyBattleSetup"] .game-frame,
  body[data-screen="partyBattlePreflight"] .game-frame,
  body[data-screen="partyBattleResult"] .game-frame,
  body[data-screen="partyBattleSongPicker"] .game-frame {
    max-width: 860px;
  }

  .party-setup-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 16px;
    align-items: start;
  }
}

@media (min-width: 1100px) {
  body[data-screen="partyBattleSetup"] .game-frame {
    max-width: 1000px;
  }
}

.party-help-row {
  margin: -6px 0 12px;
  text-align: center;
}

.party-field-sublabel {
  margin: 8px 0 2px;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.party-player-name-fields {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.party-player-name-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.party-player-badge {
  flex: none;
  min-width: 34px;
  padding: 6px 8px;
  border-radius: 999px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-size: 0.72rem;
  font-weight: 800;
  text-align: center;
}

.party-player-name-input {
  flex: 1 1 0;
  width: 0; /* 固有幅（size属性由来）を親の最小幅計算に寄与させない。実際の幅はflexで決まる */
  min-width: 0;
  box-sizing: border-box;
  padding: 10px 12px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 12px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-weight: 700;
}

.party-recent-names {
  margin-top: 10px;
}

.party-recent-names-label {
  margin: 0 0 6px;
  font-size: 0.7rem;
  font-weight: 700;
  opacity: 0.75;
}

.party-recent-names-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-width: 0;
}

.party-recent-name-chip {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.party-recent-name-chip {
  padding: 6px 12px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
}

.party-seat-help {
  margin: 0 0 8px;
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1.5;
  opacity: 0.85;
}

/* 端末を上から見た図：黒い丸角の「端末」の中に2×2の席タイル */
.party-seat-figure-wrap {
  display: flex;
  justify-content: center;
}

.party-seat-figure {
  width: min(100%, 300px);
  aspect-ratio: 3 / 4;
  max-width: 100%;
  box-sizing: border-box;
  min-width: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 8px;
  padding: 14px 10px;
  border-radius: 26px;
  background: #1f1b26;
  box-shadow: inset 0 0 0 3px #3a3444;
}

.party-seat-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 6px;
  border: 3px solid var(--seat-color);
  border-radius: 14px;
  background: var(--seat-color);
  color: #fff;
  font-family: inherit;
  cursor: pointer;
  transition: opacity 0.15s ease, transform 0.15s ease;
}

.party-seat-tile:active {
  transform: scale(0.97);
}

.party-seat-tile.is-empty {
  background: #4a4554;
  border-color: #7c7591;
  border-style: dashed;
  opacity: 0.9;
}

.party-seat-tile-title {
  font-size: 0.8rem;
  font-weight: 800;
}

.party-seat-tile-desc {
  font-size: 0.62rem;
  font-weight: 700;
  opacity: 0.9;
}

.party-source-detail {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  min-width: 0;
  margin-top: 8px;
}

.party-source-detail > * {
  min-width: 0;
  max-width: 100%;
}

.party-source-summary {
  font-size: 0.8rem;
  font-weight: 700;
}

.party-source-button {
  padding: 8px 16px;
  font-size: 0.8rem;
}

.party-playlist-select {
  width: 100%;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
  padding: 10px 12px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 12px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 16px;
  font-weight: 700;
}

.party-source-status {
  margin: 6px 0 0;
  text-align: center;
  font-size: 0.72rem;
  font-weight: 700;
  opacity: 0.75;
}

.party-song-picker-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 12px 0 16px;
}

/* ---------- 開始前チェック ---------- */
.party-preflight-summary {
  margin-bottom: 12px;
}

.party-preflight-list {
  margin: 0 0 14px;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.party-preflight-list li {
  padding: 10px 12px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 14px;
  background: var(--color-surface);
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1.5;
}

.party-voice-test-box {
  margin: 12px 0;
  padding: 12px 14px;
  border: 1.5px solid var(--color-secondary);
  border-radius: 16px;
  background: var(--color-secondary-light);
}

.party-voice-test-title {
  margin: 0 0 6px;
  font-size: 0.9rem;
  font-weight: 800;
}

.party-voice-test-desc,
.party-voice-test-result,
.party-voice-test-note {
  margin: 6px 0;
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1.5;
}

.party-voice-test-result {
  padding: 8px 10px;
  border-radius: 10px;
  background: var(--color-surface);
}

.party-voice-test-note {
  opacity: 0.8;
  font-weight: 600;
}

.party-voice-diagnostics-toggle {
  margin: 6px 0 0;
  padding: 4px 10px;
  border: 1px solid var(--color-card-border);
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.68rem;
  font-weight: 700;
  cursor: pointer;
}

.party-voice-diagnostics {
  margin: 6px 0 0;
  padding: 8px 10px;
  max-height: 180px;
  overflow: auto;
  border-radius: 10px;
  background: #1f1b26;
  color: #e8e4f0;
  font-size: 0.62rem;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-all;
}

/* ---------- 対戦盤面（全画面固定） ---------- */
body[data-screen="partyBattlePlay"] {
  padding-top: 0;
  padding-bottom: 0;
  overflow: hidden;
  --pattern-opacity: 0.06;
  --blob-opacity: 0.1;
  --vinyl-opacity: 0.03;
  --sparkle-opacity: 0.15;
}

/* 盤面は机の中央で全員が使うため、PC向けの480px制限を外して画面いっぱいに広げる */
body[data-screen="partyBattlePlay"] .game-frame {
  max-width: none;
  width: 100%;
  height: var(--game-frame-safe-height);
  max-height: var(--game-frame-safe-height);
  border-radius: 0;
  border: none;
  box-shadow: none;
  display: flex;
  flex-direction: column;
}

#party-battle-play-screen.is-active {
  display: block;
  padding: 0;
  flex: 1;
  min-height: 0;
  animation: none;
}

.party-play-root {
  position: relative;
  box-sizing: border-box;
  width: 100%;
  height: var(--game-frame-safe-height);
  padding: calc(var(--measured-safe-area-inset-top, env(safe-area-inset-top, 0px)) + 6px) 6px
    calc(var(--measured-safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)) + 6px);
  display: grid;
  gap: 6px;
  /* タッチ事故対策（この盤面だけに限定）：ダブルタップズーム・ピンチ・選択・スクロール・長押しメニュー */
  touch-action: none;
  overscroll-behavior: contain;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  overflow: hidden;
}

/* 4人（3人）：縦向きは「上段2席／中央／下段2席」、横向きは「左2席／中央／右2席」。
   中央を独立したセルにして席と重ねない（席の面積を最大化しつつ、四隅＝各プレイヤーの位置は維持）。 */
.party-play-root[data-layout="four"][data-orientation="portrait"] {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) auto minmax(0, 1fr);
}

.party-play-root[data-layout="four"][data-orientation="landscape"] {
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
}

.party-play-root[data-layout="two"][data-orientation="portrait"] {
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) auto minmax(0, 1fr);
}

.party-play-root[data-layout="two"][data-orientation="landscape"] {
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
}

/* 席の入れ物はグリッドに参加させず、子（席）を直接rootのグリッドへ置く */
.party-play-seats {
  display: contents;
}

.party-seat {
  position: relative;
  min-width: 0;
  min-height: 0;
  border: 3px solid var(--seat-color);
  border-radius: 18px;
  background: var(--seat-color-soft);
  overflow: hidden;
  transition: box-shadow 0.15s ease, opacity 0.2s ease;
}

.party-play-root[data-layout="four"][data-orientation="portrait"] .party-seat[data-seat-id="topLeft"] { grid-area: 1 / 1; }
.party-play-root[data-layout="four"][data-orientation="portrait"] .party-seat[data-seat-id="topRight"] { grid-area: 1 / 2; }
.party-play-root[data-layout="four"][data-orientation="portrait"] .party-seat[data-seat-id="bottomLeft"] { grid-area: 3 / 1; }
.party-play-root[data-layout="four"][data-orientation="portrait"] .party-seat[data-seat-id="bottomRight"] { grid-area: 3 / 2; }
.party-play-root[data-layout="four"][data-orientation="portrait"] .party-play-center { grid-area: 2 / 1 / 3 / 3; }

.party-play-root[data-layout="four"][data-orientation="landscape"] .party-seat[data-seat-id="topLeft"] { grid-area: 1 / 1; }
.party-play-root[data-layout="four"][data-orientation="landscape"] .party-seat[data-seat-id="topRight"] { grid-area: 1 / 3; }
.party-play-root[data-layout="four"][data-orientation="landscape"] .party-seat[data-seat-id="bottomLeft"] { grid-area: 2 / 1; }
.party-play-root[data-layout="four"][data-orientation="landscape"] .party-seat[data-seat-id="bottomRight"] { grid-area: 2 / 3; }
.party-play-root[data-layout="four"][data-orientation="landscape"] .party-play-center { grid-area: 1 / 2 / 3 / 3; }

.party-play-root[data-layout="two"][data-orientation="portrait"] .party-seat[data-seat-id="top"] { grid-area: 1 / 1; }
.party-play-root[data-layout="two"][data-orientation="portrait"] .party-play-center { grid-area: 2 / 1; }
.party-play-root[data-layout="two"][data-orientation="portrait"] .party-seat[data-seat-id="bottom"] { grid-area: 3 / 1; }

.party-play-root[data-layout="two"][data-orientation="landscape"] .party-seat[data-seat-id="top"] { grid-area: 1 / 1; }
.party-play-root[data-layout="two"][data-orientation="landscape"] .party-play-center { grid-area: 1 / 2; }
.party-play-root[data-layout="two"][data-orientation="landscape"] .party-seat[data-seat-id="bottom"] { grid-area: 1 / 3; }

/* 3人対戦の空席：枠だけ薄く残す（4分割グリッドの3枠をそのまま使う。本人確定） */
.party-seat.is-empty {
  border-style: dashed;
  border-color: rgba(74, 46, 66, 0.2);
  background: rgba(255, 255, 255, 0.25);
}

.party-seat.is-claimer {
  box-shadow: 0 0 0 4px var(--seat-color), 0 0 24px var(--seat-color);
}

.party-seat.is-spectator {
  opacity: 0.55;
}

.party-seat-inner {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

/* 席の向き：席コンテナ単位で回転（文字だけが逆さまにならない） */
.party-seat[data-rotation="180"] .party-seat-inner {
  transform: rotate(180deg);
}

.party-seat[data-rotation="90"] .party-seat-inner,
.party-seat[data-rotation="-90"] .party-seat-inner {
  position: absolute;
  top: 50%;
  left: 50%;
}

.party-seat[data-rotation="90"] .party-seat-inner {
  transform: translate(-50%, -50%) rotate(90deg);
}

.party-seat[data-rotation="-90"] .party-seat-inner {
  transform: translate(-50%, -50%) rotate(-90deg);
}

.party-seat-header {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-size: clamp(0.62rem, 2.2vmin, 1rem);
  font-weight: 800;
  color: var(--seat-color);
}

.party-seat-badge {
  flex: none;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--seat-color);
  color: #fff;
}

.party-seat-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--color-text);
}

.party-seat-score {
  flex: none;
  color: var(--color-text);
}

.party-seat-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.party-choice-grid {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: minmax(0, 1fr);
  gap: 5px;
}

.party-choice-button {
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 3px 5px;
  border: 2px solid var(--seat-color);
  border-radius: 12px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-weight: 800;
  cursor: pointer;
  overflow: hidden;
  transition: transform 0.08s ease, opacity 0.15s ease;
}

/* 【2026-09-15 第1回実機QA修正】押下表現はJS（js/answerButtonInteraction.js）が付け外しする .is-pressed を正とする
   （:activeだけだと、指をボタン外へスライドしてキャンセルした瞬間に見た目を戻せない）。 */
.party-choice-button.is-pressed:not(:disabled),
.party-choice-button:active:not(:disabled) {
  transform: scale(0.95) translateY(1px);
  background: var(--seat-color-soft);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.12);
}

.party-choice-button:disabled {
  cursor: default;
  opacity: 0.55;
}

.party-choice-button.is-eliminated {
  opacity: 0.3;
  background: #d9d3dd;
  border-color: #b9b1bf;
  text-decoration: line-through;
}

.party-choice-letter {
  font-size: clamp(0.55rem, 1.9vmin, 0.7rem);
  color: var(--seat-color);
  line-height: 1;
}

.party-play-root[data-orientation="portrait"] .party-choice-title {
  -webkit-line-clamp: 3;
}

.party-choice-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  text-align: center;
  font-size: clamp(0.6rem, 2.6vmin, 1.3rem);
  line-height: 1.2;
  word-break: break-all;
}

.party-answer-button {
  flex: 1;
  min-height: 0;
  border: 3px solid var(--seat-color);
  border-radius: 16px;
  background: var(--seat-color);
  color: #fff;
  font-family: inherit;
  font-size: clamp(1.2rem, 6vmin, 2.4rem);
  font-weight: 900;
  letter-spacing: 0.05em;
  cursor: pointer;
  transition: transform 0.08s ease, opacity 0.15s ease;
}

.party-answer-button.is-pressed:not(:disabled),
.party-answer-button:active:not(:disabled) {
  transform: scale(0.96) translateY(1px);
  filter: brightness(0.92);
  box-shadow: inset 0 3px 10px rgba(0, 0, 0, 0.18);
}

.party-answer-button:disabled {
  opacity: 0.45;
  cursor: default;
}

.party-seat-lock {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 12px;
  background: rgba(40, 30, 40, 0.5);
  color: #fff;
  font-size: clamp(0.8rem, 3.5vmin, 1.3rem);
  font-weight: 900;
  letter-spacing: 0.08em;
  pointer-events: none;
}

/* 中央の共通情報（問題番号・カウント・全員PASS・歌詞）。回転しない中立配置 */
.party-play-center {
  position: relative;
  z-index: 3;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 8px 10px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: 0 10px 24px -12px rgba(255, 79, 150, 0.45);
  text-align: center;
  overflow: hidden;
}

.party-play-root[data-layout="four"][data-orientation="portrait"] .party-play-center {
  width: 100%;
  min-height: 64px;
  max-height: 34vh;
}

.party-play-root[data-layout="four"][data-orientation="landscape"] .party-play-center {
  width: min(30vw, 300px);
  height: 100%;
  max-height: none;
}

.party-play-root[data-layout="two"][data-orientation="portrait"] .party-play-center {
  width: 100%;
  min-height: 64px;
  max-height: 40vh;
}

.party-play-root[data-layout="two"][data-orientation="landscape"] .party-play-center {
  width: min(36vw, 320px);
  height: 100%;
  max-height: none;
}

.party-center-question-label {
  margin: 0;
  font-size: clamp(0.7rem, 2.4vmin, 1.1rem);
  font-weight: 800;
  color: var(--color-primary-dark);
}

.party-center-status {
  margin: 0;
  font-size: clamp(0.7rem, 2.4vmin, 1.1rem);
  font-weight: 700;
  line-height: 1.3;
}

.party-center-status.is-countdown {
  font-size: clamp(2rem, 9vmin, 3.6rem);
  font-weight: 900;
  line-height: 1;
  color: var(--color-primary-dark);
  animation: partyCountPop 0.5s ease;
}

.party-center-status.is-start {
  font-size: clamp(1.5rem, 7vmin, 2.8rem);
  color: var(--party-green);
}

@keyframes partyCountPop {
  from { transform: scale(1.35); opacity: 0.4; }
  to { transform: scale(1); opacity: 1; }
}

.party-center-lyrics {
  width: 100%;
  max-height: 30vh;
  overflow-y: auto;
  padding: 4px 6px;
  border-radius: 10px;
  background: var(--color-primary-light);
  text-align: left;
  touch-action: pan-y;
}

/* 【2026-09-15 第3回実機QA修正】2人対戦の歌詞は同じ進行を2方向へ同時表示（1 state・2 view）。
   縦向き：上（相手側=180度回転）／下（通常）。横向き：左（90度）／右（-90度）を横に並べ、
   90度系は js/partyBattlePlayScreen.js が幅と高さを入れ替えて指定する（席の回転と同じ方式）。 */
.party-center-lyrics.is-dual {
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: 6px;
  max-height: 40vh;
  overflow: hidden;
  padding: 4px;
  background: transparent;
}

.party-center-lyrics.is-dual[data-orientation="landscape"] {
  grid-template-rows: none;
  grid-template-columns: 1fr 1fr;
  /* 中央カード（縦flex）の残り高さを使うが、問題番号・状態文・操作ボタンぶん（約160px）は必ず残す。
     height:100% にすると問題番号が上端へ押し出され「終了｜長押し」と重なった（QA harnessで確認） */
  flex: 1 1 0;
  height: auto;
  max-height: calc(100% - 160px);
  min-height: 0;
}

.party-lyric-view {
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  padding: 4px 6px;
  border-radius: 10px;
  background: var(--color-primary-light);
}

.party-lyric-view[data-rotation="180"] {
  transform: rotate(180deg);
}

.party-center-lyrics.is-dual[data-orientation="landscape"] {
  position: relative;
}

.party-center-lyrics.is-dual[data-orientation="landscape"] .party-lyric-view {
  position: absolute;
  top: 50%;
  box-sizing: border-box;
}

.party-center-lyrics.is-dual[data-orientation="landscape"] .party-lyric-view[data-rotation="90"] {
  left: 25%;
  transform: translate(-50%, -50%) rotate(90deg);
}

.party-center-lyrics.is-dual[data-orientation="landscape"] .party-lyric-view[data-rotation="-90"] {
  left: 75%;
  transform: translate(-50%, -50%) rotate(-90deg);
}

/* 中央の操作（🔁もう一度聴く／全員PASS）：横に並べ、狭いときは折り返す。縦に伸ばさない */
.party-center-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 6px;
  width: 100%;
  min-width: 0;
}

.party-center-actions > * {
  flex: none;
  max-width: 100%;
}

.party-replay-button {
  padding: 8px 14px;
  border: 2px solid var(--color-secondary);
  border-radius: 999px;
  background: var(--color-secondary-light);
  color: var(--color-text);
  font-family: inherit;
  font-size: clamp(0.68rem, 2.3vmin, 0.85rem);
  font-weight: 800;
  cursor: pointer;
  white-space: nowrap;
}

.party-replay-button:active,
.party-replay-button.is-pressed {
  transform: scale(0.96);
}

.party-replay-button[hidden] {
  display: none;
}

/* 【2026-09-15 第4回実機QA修正・本人指示】歌詞ヒントは「ヒントN」バッジ＋本文を同じ1行（flex row）に置き、
   最新のヒントを一番上へ積む。バッジは本文より小さく淡く（1行を独占しない）、本文だけ自然に折り返す。
   オンライン早押し歌詞対戦の .online-lyrics-battle-hint-summary-item と同じ構造・同系の色。 */
.party-lyric-row {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin: 2px 0;
  font-size: clamp(0.78rem, 2.6vmin, 1rem);
  font-weight: 800;
  line-height: 1.5;
}

.party-lyric-level {
  flex: none;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--color-accent-soft);
  color: var(--color-primary-dark);
  font-size: 0.68em;
  font-weight: 800;
  white-space: nowrap;
  opacity: 0.85;
}

.party-lyric-text {
  flex: 1 1 0;
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.party-lyric-row.is-latest .party-lyric-level {
  background: var(--color-primary);
  color: #fff;
  opacity: 1;
}

.party-lyric-row.is-latest {
  color: var(--color-primary-dark);
}

.party-lyric-row.is-placeholder {
  opacity: 0.5;
}

/* 【第7回】まだ公開されていない固定スロット：位置だけ取っておき、薄い「…」で示す（曲名や歌詞は一切出さない） */
.party-lyric-row.is-pending {
  opacity: 0.35;
  min-height: 1.5em;
}

.party-lyric-row.is-pending .party-lyric-level {
  background: transparent;
  color: var(--color-text);
  opacity: 0.6;
}

.party-pass-button {
  position: relative;
  flex: none;
  padding: 8px 16px;
  border: 2px solid var(--color-primary);
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: clamp(0.68rem, 2.3vmin, 0.85rem);
  font-weight: 800;
  overflow: hidden;
  cursor: pointer;
  touch-action: none;
}

.party-pass-button[hidden] {
  display: none;
}

.party-pass-button.is-pressed {
  transform: scale(0.95) translateY(1px);
  background: var(--color-primary-light);
  box-shadow: inset 0 2px 6px rgba(255, 79, 150, 0.25);
}

.party-pass-button-label {
  position: relative;
  z-index: 1;
}

.party-pass-progress,
.party-quit-progress {
  position: absolute;
  inset: 0;
  background: var(--color-primary);
  opacity: 0.35;
  transform: scaleX(0);
  transform-origin: left center;
  pointer-events: none;
}

.party-quit-button {
  position: absolute;
  z-index: 4;
  top: calc(var(--measured-safe-area-inset-top, env(safe-area-inset-top, 0px)) + 4px);
  left: 50%;
  transform: translateX(-50%);
  padding: 4px 10px;
  border: 1px solid rgba(74, 46, 66, 0.25);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.85);
  color: rgba(74, 46, 66, 0.75);
  font-family: inherit;
  font-size: 0.62rem;
  font-weight: 800;
  overflow: hidden;
  cursor: pointer;
  touch-action: none;
}

.party-quit-button span:first-child {
  position: relative;
  z-index: 1;
}

.party-quit-progress {
  background: var(--color-danger);
}

/* 終了ボタンは小さく指で隠れるため、長押し中はボタン全体を赤系に変えて「反応している」ことを伝える */
.party-quit-button.is-pressed {
  transform: translateX(-50%) scale(0.95);
  background: var(--color-danger-soft);
  border-color: var(--color-danger);
  color: var(--color-danger);
}

/* 上部中央の終了ボタンが4人時の上段の席と重ならないよう、席側に少しだけ上余白を与える */
.party-play-root[data-layout="four"] .party-seat[data-seat-id="topLeft"] .party-seat-inner,
.party-play-root[data-layout="four"] .party-seat[data-seat-id="topRight"] .party-seat-inner {
  padding-bottom: 18px; /* 180度回転しているため、画面上では上側の余白になる */
}

.party-play-root[data-layout="two"][data-orientation="portrait"] .party-seat[data-seat-id="top"] .party-seat-inner {
  padding-bottom: 18px;
}

/* ---------- 盤面のオーバーレイ ---------- */
.party-intro-overlay,
.party-result-overlay,
.party-voice-overlay,
.party-pause-overlay {
  position: absolute;
  inset: 0;
  z-index: 6;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 24px;
  text-align: center;
}

.party-intro-overlay[hidden],
.party-result-overlay[hidden],
.party-voice-overlay[hidden],
.party-pause-overlay[hidden],
.party-notice[hidden] {
  display: none;
}

.party-intro-overlay {
  background: rgba(255, 255, 255, 0.72);
  font-size: clamp(1.4rem, 7vmin, 2.6rem);
  font-weight: 900;
  color: var(--color-primary-dark);
  pointer-events: none;
  animation: partyCountPop 0.4s ease;
}

/* 【2026-09-16 第5回実機QA修正・本人指示：結果表示を「みんなで遊ぶクイズ番組」らしく】
   正解＝ピンク〜金のグラデーション＋大きな⭕がポップ、不正解＝赤みの背景＋❌が短くシェイク、全員PASS＝落ち着いた青灰。
   要素は「内容の高さ」だけを取り（.party-result-overlay > * { flex:none }）、縦長画面では上下の余白を
   アイコン・回答者チップ・得点・曲名・スコアボードで埋める（ボタンは伸ばさない）。 */
.party-result-overlay {
  padding: 16px;
  background: rgba(255, 255, 255, 0.55);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

/* 結果カード本体：盤面の中央に「カード」として置く（盤面全体を真っ白に塗りつぶさず、背景の席がうっすら見える）。
   縦長画面では上下の余白がカードの外側（背景）になるので、寂しい空白ではなく「盤面の上に結果カードが乗った」見え方になる */
.party-result-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: min(440px, 100%);
  max-height: 100%;
  box-sizing: border-box;
  padding: 18px 16px 16px;
  border: 2px solid rgba(255, 255, 255, 0.9);
  border-radius: 24px;
  background: rgba(255, 255, 255, 0.96);
  box-shadow: 0 22px 50px -24px rgba(31, 27, 38, 0.55);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  text-align: center;
}

.party-result-card > * {
  flex: none;
  max-width: 100%;
}

.party-result-overlay[data-kind="correct"] .party-result-card,
.party-result-overlay[data-kind="rescued"] .party-result-card {
  border-color: rgba(255, 217, 61, 0.8);
  background:
    radial-gradient(circle at 50% 22%, rgba(255, 244, 179, 0.9), rgba(255, 244, 179, 0) 45%),
    linear-gradient(180deg, rgba(255, 233, 243, 0.98), rgba(255, 255, 255, 0.97));
}

.party-result-overlay[data-kind="wrong"] .party-result-card,
.party-result-overlay[data-kind="voided"] .party-result-card {
  border-color: rgba(230, 80, 90, 0.5);
  background: linear-gradient(180deg, rgba(255, 232, 230, 0.98), rgba(255, 248, 247, 0.97));
}

.party-result-overlay[data-kind="pass"] .party-result-card {
  border-color: rgba(183, 187, 209, 0.8);
  background: linear-gradient(180deg, rgba(236, 240, 250, 0.98), rgba(255, 255, 255, 0.97));
}

/* 大きな結果アイコン（⭕／❌／PASS）。円の中に置き、登場時にポップする */
.party-result-icon {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(64px, 18vmin, 110px);
  height: clamp(64px, 18vmin, 110px);
  border-radius: 50%;
  font-size: clamp(2rem, 9vmin, 3.6rem);
  font-weight: 900;
  line-height: 1;
  background: var(--color-surface);
  box-shadow: 0 10px 30px -12px rgba(255, 79, 150, 0.6);
}

.party-result-overlay[data-kind="correct"] .party-result-icon,
.party-result-overlay[data-kind="rescued"] .party-result-icon {
  color: var(--color-primary);
  border: 4px solid var(--color-primary);
}

.party-result-overlay[data-kind="wrong"] .party-result-icon,
.party-result-overlay[data-kind="voided"] .party-result-icon {
  color: var(--color-danger);
  border: 4px solid var(--color-danger);
}

.party-result-overlay[data-kind="pass"] .party-result-icon {
  font-size: clamp(0.95rem, 4.2vmin, 1.4rem);
  letter-spacing: 0.08em;
  color: #6b6f8a;
  border: 4px dashed #b7bbd1;
}

.party-result-headline {
  margin: 0;
  font-size: clamp(1.6rem, 8vmin, 3rem);
  font-weight: 900;
  color: var(--color-primary-dark);
  letter-spacing: 0.02em;
}

.party-result-overlay[data-kind="wrong"] .party-result-headline,
.party-result-overlay[data-kind="voided"] .party-result-headline {
  color: var(--color-danger);
}

.party-result-overlay[data-kind="pass"] .party-result-headline {
  color: #4f5470;
}

/* 回答者チップ（席の色） */
.party-result-player {
  margin: 0;
  padding: 4px 14px;
  border-radius: 999px;
  border: 2px solid var(--seat-color, var(--color-primary));
  background: var(--seat-color-soft, var(--color-primary-light));
  color: var(--color-text);
  font-size: clamp(0.9rem, 3.6vmin, 1.2rem);
  font-weight: 900;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.party-result-points {
  margin: 0;
  font-size: clamp(1.4rem, 7vmin, 2.4rem);
  font-weight: 900;
  color: var(--color-primary);
  line-height: 1.1;
}

.party-result-overlay[data-kind="pass"] .party-result-points,
.party-result-overlay[data-kind="voided"] .party-result-points {
  color: #6b6f8a;
}

.party-result-song-label {
  margin: 4px 0 0;
  padding: 2px 10px;
  border-radius: 999px;
  background: var(--color-accent-soft);
  color: var(--color-primary-dark);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.1em;
}

.party-result-song {
  margin: 0;
  font-size: clamp(1.15rem, 5.5vmin, 1.9rem);
  font-weight: 900;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

.party-result-detail {
  margin: 0;
  font-size: clamp(0.78rem, 3vmin, 1rem);
  font-weight: 700;
  opacity: 0.9;
}

.party-result-detail:empty {
  display: none;
}

/* 全員の現在得点（小さなスコアボード）。得点が動いた人だけ席の色で強調し、+1／-1 の小バッジを付ける */
.party-result-scores {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  max-width: 100%;
  margin-top: 2px;
}

.party-result-scores:empty {
  display: none;
}

.party-result-score-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1.5px solid var(--seat-color, var(--color-card-border));
  background: var(--color-surface);
  font-size: 0.72rem;
  font-weight: 800;
  max-width: 46%;
}

.party-result-score-chip.is-scored {
  background: var(--seat-color-soft);
  box-shadow: 0 0 0 2px var(--seat-color);
}

.party-result-score-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.party-result-score-value {
  flex: none;
  color: var(--seat-color, var(--color-primary-dark));
}

.party-result-score-delta {
  position: absolute;
  top: -9px;
  right: -6px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--color-primary);
  color: #fff;
  font-size: 0.6rem;
  font-weight: 900;
}

/* ----- 登場演出（新しい結果のときだけ .is-entering を付け直す。js/partyBattlePlayScreen.js playResultEffect） ----- */
.party-result-overlay.is-entering .party-result-icon {
  animation: partyResultIconPop 0.5s cubic-bezier(0.22, 1.4, 0.36, 1);
}

.party-result-overlay.is-entering .party-result-headline {
  animation: partyResultTextIn 0.4s ease-out;
}

.party-result-overlay.is-entering[data-kind="correct"] .party-result-card,
.party-result-overlay.is-entering[data-kind="rescued"] .party-result-card {
  animation: partyResultCardIn 0.45s cubic-bezier(0.22, 1.2, 0.36, 1), partyResultFlash 0.6s ease-out;
}

.party-result-overlay.is-entering[data-kind="wrong"] .party-result-card,
.party-result-overlay.is-entering[data-kind="voided"] .party-result-card,
.party-result-overlay.is-entering[data-kind="pass"] .party-result-card {
  animation: partyResultCardIn 0.35s ease-out;
}

@keyframes partyResultCardIn {
  from { transform: scale(0.92) translateY(10px); opacity: 0; }
  to { transform: scale(1) translateY(0); opacity: 1; }
}

/* 正解のキラッ（アイコンの周りに広がる光の輪） */
.party-result-overlay[data-kind="correct"] .party-result-icon::after,
.party-result-overlay[data-kind="rescued"] .party-result-icon::after {
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 3px solid rgba(255, 217, 61, 0.9);
  opacity: 0;
}

.party-result-overlay.is-entering[data-kind="correct"] .party-result-icon::after,
.party-result-overlay.is-entering[data-kind="rescued"] .party-result-icon::after {
  animation: partyResultRing 0.7s ease-out 0.1s;
}

.party-result-overlay.is-entering[data-kind="wrong"] .party-result-icon,
.party-result-overlay.is-entering[data-kind="voided"] .party-result-icon {
  animation: partyResultShake 0.45s ease-in-out;
}

@keyframes partyResultIconPop {
  0% { transform: scale(0.3); opacity: 0; }
  70% { transform: scale(1.12); opacity: 1; }
  100% { transform: scale(1); }
}

@keyframes partyResultTextIn {
  from { transform: translateY(8px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

@keyframes partyResultFlash {
  0% { box-shadow: inset 0 0 0 0 rgba(255, 217, 61, 0); }
  30% { box-shadow: inset 0 0 0 14px rgba(255, 217, 61, 0.55); }
  100% { box-shadow: inset 0 0 0 0 rgba(255, 217, 61, 0); }
}

@keyframes partyResultRing {
  0% { transform: scale(0.8); opacity: 0.9; }
  100% { transform: scale(1.7); opacity: 0; }
}

@keyframes partyResultShake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-8px); }
  40% { transform: translateX(8px); }
  60% { transform: translateX(-5px); }
  80% { transform: translateX(5px); }
}

/* タブレット横向き（高さ 768px 前後）では vmin 基準の文字・アイコンが大きくなりすぎてカードが縦に収まらないことがあるため、
   中くらいの高さでは一段階小さくする */
@media (max-height: 800px) and (min-height: 521px) and (min-width: 600px) {
  .party-result-icon {
    width: 84px;
    height: 84px;
    font-size: 2.6rem;
  }

  .party-result-headline {
    font-size: 2.2rem;
  }

  .party-result-points {
    font-size: 1.8rem;
  }

  .party-result-song {
    font-size: 1.5rem;
  }
}

/* 小さめの縦長スマホ（375×667 など、高さ 700px 以下）：救済候補や4人ぶんの得点チップが加わっても
   カードがスクロールにならないよう、少し詰める */
@media (max-height: 700px) and (min-height: 521px) and (max-width: 599px) {
  .party-result-card {
    gap: 4px;
    padding: 12px 14px;
  }

  .party-result-icon {
    width: 56px;
    height: 56px;
    font-size: 1.7rem;
    border-width: 3px;
  }

  .party-result-overlay[data-kind="pass"] .party-result-icon {
    font-size: 0.85rem;
  }

  .party-result-headline {
    font-size: 1.5rem;
  }

  .party-result-points {
    font-size: 1.3rem;
  }

  .party-result-song-label {
    margin-top: 0;
  }

  .party-result-song {
    font-size: 1.15rem;
  }

  .party-result-detail {
    font-size: 0.74rem;
  }

  .party-result-next-button {
    margin-top: 4px;
  }
}

/* 横向きスマホ（高さ 393px 前後）では結果カードが縦に収まらないため、詰めた配置にする。
   はみ出す場合はオーバーレイ内でスクロールできるようにし、「次へ」が画面外で押せなくなることを防ぐ
   （safe center：収まるときは中央、収まらないときは先頭から）。 */
@media (max-height: 520px) {
  .party-result-overlay {
    gap: 3px;
    padding: 10px 16px;
    justify-content: safe center;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  .party-result-icon {
    width: 44px;
    height: 44px;
    font-size: 1.5rem;
    border-width: 3px;
  }

  .party-result-overlay[data-kind="pass"] .party-result-icon {
    font-size: 0.8rem;
  }

  .party-result-headline {
    font-size: 1.35rem;
  }

  .party-result-player {
    padding: 2px 10px;
    font-size: 0.9rem;
  }

  .party-result-points {
    font-size: 1.15rem;
  }

  .party-result-song-label {
    margin-top: 0;
    font-size: 0.62rem;
  }

  .party-result-song {
    font-size: 1.05rem;
  }

  .party-result-detail {
    font-size: 0.72rem;
  }

  .party-result-scores {
    gap: 4px;
  }

  .party-result-score-chip {
    padding: 1px 8px;
    font-size: 0.64rem;
  }

  .party-result-next-button {
    margin-top: 4px;
    min-height: 40px;
    padding-top: 8px;
    padding-bottom: 8px;
  }

  .party-override-button {
    padding: 5px 12px;
    font-size: 0.72rem;
  }

  .party-result-card {
    gap: 3px;
    padding: 10px 14px;
  }

  /* 救済候補は最低1件ぶん見えるだけの高さを確保し、足りない分はカード全体のスクロールに任せる
     （箱だけが見出し1行に潰れて中身が読めない状態を避ける） */
  .party-result-overlay .party-result-card > .party-rescue-box {
    flex: none;
    min-height: 0;
    max-height: 132px;
  }
}

/* 【2026-09-15 第2回実機QA修正・iPhone実機で「判定を修正」が画面中央を縦いっぱいに占有した不具合】
   原因：アプリ共通の .secondary-button は flex: 1（横並びの .button-row で幅を等分するための指定）を持つ。
   盤面のオーバーレイ（.party-result-overlay／.party-voice-overlay／.party-pause-overlay）は
   「縦方向の flex コンテナ（flex-direction: column、inset:0 で盤面全体の高さ）」なので、その中に置いた
   .secondary-button は flex:1 が「縦方向の伸長」として働き、残りの高さすべてを奪って細長いカプセルになった。
   同じ理由で .primary-button（display:block; width:100%）も盤面の中では横幅いっぱいになる。
   対策：盤面（.party-play-root）の中に置く共通ボタンは、盤面スコープで flex:none／幅を内容＋上限に固定する
   （共通ボタンの定義そのものは変えない：他画面の .button-row 等に影響させないため）。
   これは出題タイプ（イントロ／ランダム／アウトロ／一瞬／歌詞）・人数・向きに関係なく、全オーバーレイ共通の修正。 */
.party-play-root .secondary-button,
.party-play-root .primary-button {
  flex: none;
  align-self: center;
  width: auto;
  min-width: 200px;
  max-width: min(340px, 100%);
  box-sizing: border-box;
}

.party-result-next-button {
  margin-top: 10px;
  min-width: 220px;
}

.party-override-button {
  padding: 8px 16px;
  font-size: 0.8rem;
  min-width: 160px;
}

/* 【2026-09-15 第4回実機QA修正・本人指示】正解公開後の音声回答の救済候補。結果オーバーレイの中で
   「内容の高さ」だけを取り、候補が多いときはこの箱の中だけスクロール（「次へ」を画面外へ押し出さない）。 */
.party-result-card > .party-rescue-box {
  flex: 0 1 auto;
  min-height: 96px; /* 少なくとも候補1件が読める高さ。足りない分はカード全体のスクロールへ */
  max-height: min(42%, 240px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  width: min(360px, 100%);
  box-sizing: border-box;
  margin-top: 6px;
  padding: 8px 10px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 12px;
  background: var(--color-surface);
  text-align: left;
}

.party-rescue-box[hidden] {
  display: none;
}

.party-rescue-title {
  margin: 0 0 4px;
  font-size: 0.78rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.party-rescue-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px 0;
  border-top: 1px dashed var(--color-card-border);
}

.party-rescue-info {
  margin: 0;
  font-size: 0.76rem;
  font-weight: 700;
  line-height: 1.45;
  overflow-wrap: anywhere;
}

.party-rescue-note {
  margin: 0;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-danger);
}

.party-rescue-button {
  align-self: flex-start;
  flex: none;
  padding: 6px 12px;
  border: 2px solid var(--color-primary);
  border-radius: 999px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.74rem;
  font-weight: 800;
  cursor: pointer;
}

.party-rescue-button:active {
  transform: scale(0.96);
}

/* オーバーレイ内の文章・ボタンはどれも「内容の高さ」だけを取り、縦方向に伸ばさない */
.party-result-overlay > *,
.party-voice-overlay > *,
.party-pause-overlay > * {
  flex: none;
  max-width: 100%;
}

.party-voice-overlay {
  background: rgba(31, 27, 38, 0.92);
  color: #fff;
}

.party-voice-player {
  margin: 0;
  font-size: clamp(1rem, 4.5vmin, 1.5rem);
  font-weight: 900;
}

.party-voice-timer {
  margin: 0;
  font-size: clamp(1.3rem, 6vmin, 2.2rem);
  font-weight: 900;
  color: var(--color-accent);
}

.party-voice-transcript,
.party-voice-hint {
  margin: 0;
  font-size: clamp(0.8rem, 3vmin, 1rem);
  font-weight: 700;
  line-height: 1.5;
}

.party-voice-hint {
  opacity: 0.85;
}

.party-judge-row {
  display: flex;
  gap: 14px;
  margin-top: 12px;
  width: 100%;
  max-width: 480px;
}

.party-judge-row[hidden] {
  display: none;
}

.party-judge-button {
  flex: 1;
  padding: 18px 8px;
  border: none;
  border-radius: 18px;
  font-family: inherit;
  font-size: clamp(1.1rem, 5vmin, 1.7rem);
  font-weight: 900;
  color: #fff;
  cursor: pointer;
}

.party-judge-button.is-correct {
  background: var(--party-green);
}

.party-judge-button.is-wrong {
  background: var(--color-danger);
}

.party-notice {
  position: absolute;
  z-index: 7;
  left: 12px;
  right: 12px;
  top: calc(var(--measured-safe-area-inset-top, env(safe-area-inset-top, 0px)) + 34px);
  padding: 10px 14px;
  border-radius: 12px;
  background: var(--color-accent-soft);
  color: var(--color-text);
  font-size: 0.8rem;
  font-weight: 800;
  text-align: center;
  box-shadow: var(--shadow-card);
}

.party-notice[data-kind="error"] {
  background: var(--color-danger-soft);
  color: var(--color-danger);
}

.party-pause-overlay {
  z-index: 8;
  background: rgba(255, 255, 255, 0.96);
}

.party-pause-title {
  margin: 0;
  font-size: clamp(1.1rem, 5vmin, 1.6rem);
  font-weight: 900;
  color: var(--color-primary-dark);
}

.party-pause-desc {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 700;
}

/* ---------- 結果画面 ---------- */
.party-result-list {
  margin: 12px 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.party-result-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border: 2px solid var(--seat-color);
  border-radius: 14px;
  background: var(--seat-color-soft);
  animation: partyRowIn 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes partyRowIn {
  from { transform: translateY(14px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

.party-result-rank {
  flex: none;
  min-width: 40px;
  font-weight: 900;
  color: var(--seat-color);
}

.party-result-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 800;
}

.party-result-score {
  flex: none;
  font-weight: 900;
}

.party-winner-card {
  position: relative;
  margin: 12px 0;
  padding: 22px 16px;
  border: 3px solid var(--seat-color);
  border-radius: 22px;
  background: linear-gradient(160deg, var(--seat-color-soft), var(--color-accent-soft));
  text-align: center;
  animation: partyWinnerIn 0.7s cubic-bezier(0.22, 1, 0.36, 1);
  box-shadow: 0 18px 40px -18px var(--seat-color);
}

@keyframes partyWinnerIn {
  0% { transform: scale(0.6); opacity: 0; }
  60% { transform: scale(1.08); opacity: 1; }
  100% { transform: scale(1); }
}

.party-winner-label {
  margin: 0;
  font-size: 1.8rem;
  font-weight: 900;
  letter-spacing: 0.2em;
  color: var(--seat-color);
  animation: partyWinnerGlow 1.4s ease-in-out infinite alternate;
}

/* 【2026-09-16 第5回実機QA修正】優勝カードの周りに放射状に飛ぶ小さな光（sparkle）。JS（spawnWinnerBurst）が
   --burst-x／--burst-y／--burst-delay／--burst-hue を1粒ずつ指定する。confetti（画面全体に降る紙吹雪）とは別の、カード起点の演出 */
.party-winner-burst {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: visible;
}

.party-winner-burst-piece {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 10px;
  height: 10px;
  margin: -5px 0 0 -5px;
  border-radius: 2px;
  background: hsl(var(--burst-hue, 45), 95%, 62%);
  opacity: 0;
  animation: partyWinnerBurst 1.1s ease-out var(--burst-delay, 0s) forwards;
}

@keyframes partyWinnerBurst {
  0% { transform: translate(0, 0) scale(0.4) rotate(0deg); opacity: 1; }
  100% { transform: translate(var(--burst-x, 0px), var(--burst-y, 0px)) scale(1) rotate(540deg); opacity: 0; }
}

.party-winner-trophy {
  margin: 0 0 4px;
  font-size: 2.6rem;
  line-height: 1;
  animation: partyTrophyBounce 1.2s ease-in-out infinite alternate;
}

@keyframes partyTrophyBounce {
  from { transform: translateY(0) rotate(-6deg); }
  to { transform: translateY(-6px) rotate(6deg); }
}

.party-winner-card.is-final {
  animation: partyWinnerIn 0.7s cubic-bezier(0.22, 1, 0.36, 1), partyWinnerPulse 1.6s ease-in-out 0.8s infinite alternate;
}

@keyframes partyWinnerPulse {
  from { box-shadow: 0 18px 40px -18px var(--seat-color); }
  to { box-shadow: 0 18px 48px -12px var(--seat-color), 0 0 0 6px rgba(255, 217, 61, 0.35); }
}

@keyframes partyWinnerGlow {
  from { text-shadow: 0 0 0 rgba(255, 217, 61, 0); }
  to { text-shadow: 0 0 18px rgba(255, 217, 61, 0.9); }
}

.party-winner-name {
  margin: 6px 0 0;
  font-size: 1.9rem;
  font-weight: 900;
  word-break: break-all;
}

.party-winner-points {
  margin: 4px 0 0;
  font-size: 1rem;
  font-weight: 800;
  opacity: 0.85;
}

.party-confetti {
  position: fixed;
  inset: 0;
  z-index: 9;
  pointer-events: none;
  overflow: hidden;
}

.party-confetti-piece {
  position: absolute;
  top: -12px;
  width: 8px;
  height: 14px;
  border-radius: 2px;
  background: hsl(var(--confetti-hue, 330), 90%, 62%);
  animation-name: partyConfettiFall;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
}

@keyframes partyConfettiFall {
  0% { transform: translateY(0) rotate(0deg); opacity: 1; }
  100% { transform: translateY(110vh) rotate(720deg); opacity: 0; }
}

.party-result-note {
  margin: 8px 0;
  text-align: center;
  font-size: 0.8rem;
  font-weight: 700;
  opacity: 0.85;
}

.party-result-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 12px;
}

.party-result-actions > .secondary-button,
.party-result-actions > .primary-button {
  flex: none;
  width: 100%;
  margin-top: 0;
}

.party-result-actions[hidden] {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .party-winner-card,
  .party-winner-card.is-final,
  .party-result-row,
  .party-intro-overlay,
  .party-center-status.is-countdown,
  .party-result-overlay.is-entering,
  .party-result-overlay.is-entering .party-result-card,
  .party-result-overlay.is-entering .party-result-icon,
  .party-result-overlay.is-entering .party-result-icon::after,
  .party-result-overlay.is-entering .party-result-headline,
  .party-winner-burst-piece,
  .party-winner-trophy {
    animation: none;
  }

  .party-winner-label {
    animation: none;
  }
}

/* ===== メンバー個人ページ：STAGE（舞台・朗読劇）／VOICE（声優・ボイス出演）（2026-10-01） =====
   見た目の土台は個人活動カード（.activity-card）を流用し、配役行・日程・展開UIだけを足している。 */
.stage-voice-heading-sub {
  font-weight: 700;
  font-size: 0.72rem;
  color: var(--color-text);
  opacity: 0.7;
}

.stage-voice-year {
  display: inline-block;
  font-size: 0.65rem;
  font-weight: 800;
  color: #6b6470;
  background: #ece7ea;
  padding: 1px 9px;
  border-radius: 999px;
}

.stage-voice-period {
  margin: 4px 0 0;
  font-size: 0.7rem;
  color: var(--color-text);
  opacity: 0.65;
  overflow-wrap: anywhere;
}

/* 本人の配役行（「野口衣織 ／ オーロックス 役」）。ピンクの淡い帯で目立たせる */
.stage-voice-role {
  margin: 6px 0 0;
  padding: 5px 10px;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
  border-radius: 8px;
  overflow-wrap: anywhere;
}

.stage-voice-card .stage-voice-description {
  margin-top: 6px;
}

.stage-voice-card[hidden] {
  display: none;
}

.stage-voice-link-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.stage-voice-cast-details {
  margin-top: 8px;
  border: 1px solid var(--color-card-border);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.5);
}

.stage-voice-cast-summary {
  cursor: pointer;
  padding: 7px 10px;
  font-size: 0.75rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.stage-voice-cast-list {
  list-style: none;
  margin: 0;
  padding: 2px 10px 8px;
}

.stage-voice-cast-item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 6px;
  padding: 4px 0;
  border-top: 1px dashed var(--color-card-border);
  font-size: 0.75rem;
}

.stage-voice-cast-item:first-child {
  border-top: none;
}

.stage-voice-cast-item.is-self {
  font-weight: 800;
  color: var(--color-primary-dark);
}

.stage-voice-cast-name {
  font-weight: 800;
}


.stage-voice-cast-role {
  margin-left: auto;
  text-align: right;
  overflow-wrap: anywhere;
}

.stage-voice-more-button {
  display: block;
  width: 100%;
  margin-top: 8px;
  padding: 9px 12px;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  background: var(--color-surface);
  border: 1px solid var(--color-card-border);
  border-radius: 12px;
  cursor: pointer;
}

/* 白いカードの上でも「押せるボタン」と分かるよう、枠線を足す（個人活動カードの同ボタンと同寸法） */
.stage-voice-link-row .official-link-button {
  border: 1px solid var(--color-card-border);
}

/* グループ画面の舞台カード内の「全キャスト・配役を見る」：本文との間隔だけ調整 */
.group-stage-card .stage-voice-cast-details {
  margin: 0 0 10px;
}

/* ===== 「＝LOVEについて」ANIME SONG（アニメ主題歌）カード（2026-10-01） ===== */
.anime-song-theme-tag {
  display: inline-block;
  padding: 1px 9px;
  border-radius: 999px;
  font-size: 0.65rem;
  font-weight: 800;
}

.anime-song-theme-tag.is-op {
  color: #1c5f8a;
  background: #e1f0fa;
}

.anime-song-theme-tag.is-ed {
  color: #9a5b12;
  background: #fbedd9;
}

.anime-song-credits {
  margin-bottom: 8px;
}

.anime-song-cast {
  margin-bottom: 10px;
}

.anime-song-sub-links {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin: 10px 0 0;
  font-size: 0.72rem;
}

.anime-song-sub-link {
  color: var(--color-primary-dark);
  font-weight: 700;
  text-decoration: underline;
}

/* フレンド画面：オンライン状態の送信の診断表示（2026-10-11、表示専用） */
.fan-profiles-presence-diag {
  margin: 6px 0 10px;
  padding: 8px 12px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.55);
  border: 1px solid var(--color-card-border);
}

.fan-profiles-presence-diag[data-tone="ok"] {
  background: #e8f7ee;
}

.fan-profiles-presence-diag[data-tone="ng"] {
  background: #fdecec;
}

.fan-profiles-presence-diag-verdict {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 800;
  color: var(--color-text);
}

.fan-profiles-presence-diag-detail {
  margin: 2px 0 0;
  font-size: 0.66rem;
  color: var(--color-text);
  opacity: 0.7;
  overflow-wrap: anywhere;
}

/* 【2026-10-23追加】個人活動の「開始予定」タグ（放送開始前の番組など） */
.activity-card-status.is-upcoming {
  color: #6a3fa0;
  background: #efe6fb;
}

/* 【2026-10-23追加】開催予定のまま日程が過ぎた公演（公式の開催結果を反映するまでの表示） */
.live-event-tag.is-date-passed {
  color: #6b6470;
  background: #ece7ea;
}

/* ===== 【2026-10-23】フレンド画面：一覧を主役にした並び（公開設定・詳細情報は一覧の下） ===== */
.fan-profiles-section-title {
  margin: 26px 0 8px;
  font-size: 0.85rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.fan-profiles-private-note {
  margin: 0 0 12px;
  padding: 8px 12px;
  font-size: 0.75rem;
  line-height: 1.6;
  color: var(--color-text);
  background: rgba(255, 255, 255, 0.55);
  border: 1px dashed var(--color-card-border);
  border-radius: 12px;
}

.fan-profiles-details {
  margin: 4px 0 14px;
  padding: 6px 12px;
  border: 1px solid var(--color-card-border);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.4);
}

.fan-profiles-details-summary {
  cursor: pointer;
  padding: 6px 0;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-text);
  opacity: 0.75;
}

.fan-profiles-details[open] .fan-profiles-details-summary {
  margin-bottom: 6px;
}

/* ===== 【2026-10-23】CM・広告出演 ===== */
.commercial-title {
  font-weight: 700;
}

.commercial-group-note {
  margin-top: 10px;
  padding: 10px 12px;
  border: 1px dashed var(--color-card-border);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.5);
}

.commercial-group-note-text {
  margin: 0;
  font-size: 0.75rem;
  line-height: 1.6;
  color: var(--color-text);
}

#group-cm-section {
  scroll-margin-top: 12px;
}

/* ===== 【2026-10-23新設】全体検索・歌詞検索 ===== */
/* ホーム上部の検索入口（検索バー風のボタン。押すと検索画面へ） */
.home-search-entry {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  margin: 14px 0 0;
  padding: 11px 14px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(255, 111, 168, 0.08);
}

.home-search-entry:active {
  transform: scale(0.98);
}

.home-search-entry-icon,
.search-screen-field-icon {
  display: inline-flex;
  width: 20px;
  height: 20px;
  flex: none;
  color: var(--color-primary-dark);
}

.home-search-entry-icon svg,
.search-screen-field-icon svg {
  width: 100%;
  height: 100%;
}

/* 「アプリ内を検索する…」は必ず1行で見せ、幅が足りないときは右の補足の方を省略する（375px幅で確認） */
.home-search-entry-placeholder {
  flex: 1 0 auto;
  white-space: nowrap;
  font-size: 0.85rem;
  font-weight: 700;
  opacity: 0.7;
}

.home-search-entry-hint {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.62rem;
  opacity: 0.55;
}

/* 「曲を聴く」直下の歌詞検索の入口（横長タイル） */
.listen-wide-tile {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  margin-top: 10px;
  padding: 12px 14px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 16px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 800;
  text-align: left;
  cursor: pointer;
}

.listen-wide-tile:active {
  transform: scale(0.98);
}

.listen-wide-tile-text {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 2px;
}

.listen-wide-tile-arrow {
  color: var(--color-primary-dark);
}

/* 【2026-10-24新設】全体検索画面の上部：「全体検索」（今いる画面）と「歌詞検索へ」の切り替え */
.search-mode-switch {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin: 8px 0 4px;
}

.search-mode-tab {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 56px;
  padding: 8px 10px;
  border: 1.5px solid var(--color-primary-light);
  border-radius: 16px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  text-align: left;
}

button.search-mode-tab {
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(255, 111, 168, 0.12);
}

button.search-mode-tab:active {
  transform: scale(0.98);
}

.search-mode-tab.is-current {
  border-color: var(--color-primary);
  background: linear-gradient(135deg, var(--color-primary-light), #fff);
  color: var(--color-primary-dark);
}

.search-mode-tab-icon {
  flex: none;
  width: 22px;
  height: 22px;
  color: var(--color-primary-dark);
}

.search-mode-tab-text {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.search-mode-tab-text strong {
  font-size: 0.86rem;
  font-weight: 800;
}

.search-mode-tab-text small {
  font-size: 0.66rem;
  opacity: 0.7;
  line-height: 1.3;
}

.search-mode-tab-arrow {
  flex: none;
  color: var(--color-primary-dark);
  font-size: 1.3rem;
  font-weight: 800;
}

/* 検索画面共通 */
.search-screen-field {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 10px 0 8px;
  padding: 8px 10px 8px 14px;
  border: 1.5px solid var(--color-primary-light);
  border-radius: 999px;
  background: var(--color-surface);
  box-shadow: 0 2px 10px rgba(255, 111, 168, 0.1);
}

.search-screen-input {
  flex: 1;
  min-width: 0;
  padding: 6px 0;
  border: none;
  outline: none;
  background: transparent;
  color: var(--color-text);
  font-family: inherit;
  /* 16px未満だとiPhoneで入力時に画面が拡大されるため */
  font-size: 16px;
}

/* ブラウザ標準の×は使わず、状態もリセットする独自の×ボタンだけを出す */
.search-screen-input::-webkit-search-cancel-button {
  display: none;
}

.search-screen-clear {
  flex: none;
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 50%;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-size: 1rem;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
}

.search-category-row {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding: 2px 0 8px;
  scrollbar-width: none;
}

.search-category-row::-webkit-scrollbar {
  display: none;
}

.search-category-chip {
  flex: none;
  padding: 6px 12px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.75rem;
  font-weight: 700;
  cursor: pointer;
}

.search-category-chip.is-active {
  border-color: var(--color-primary);
  background: var(--color-primary);
  color: #fff;
}

.search-category-chip.is-empty:not(.is-active) {
  opacity: 0.45;
}

.search-screen-status {
  margin: 4px 2px 10px;
  font-size: 0.78rem;
  line-height: 1.6;
  opacity: 0.8;
}

.search-result-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.search-result-item {
  border: 1.5px solid var(--color-card-border);
  border-radius: 14px;
  background: var(--color-surface);
  overflow: hidden;
}

.search-result-header {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 11px 12px;
  border: none;
  background: transparent;
  color: var(--color-text);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.search-result-category {
  flex: none;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-size: 0.62rem;
  font-weight: 800;
}

.search-result-category.is-song,
.search-result-category.is-live {
  background: var(--color-secondary-light);
  color: #2c6ea8;
}

.search-result-category.is-cm,
.search-result-category.is-program,
.search-result-category.is-work {
  background: var(--color-accent-soft);
  color: #8a6a10;
}

.search-result-category.is-guide,
.search-result-category.is-feature,
.search-result-category.is-setting {
  background: #e7f6ec;
  color: #1f7a4d;
}

.search-result-heading {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.search-result-title {
  margin: 0;
  font-size: 0.88rem;
  font-weight: 800;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.search-result-subtitle {
  font-size: 0.68rem;
  opacity: 0.65;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.search-result-chevron {
  flex: none;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--color-primary-dark);
  border-bottom: 2px solid var(--color-primary-dark);
  transform: rotate(45deg);
  transition: transform 0.15s ease;
}

.search-result-item.is-expanded .search-result-chevron {
  transform: rotate(-135deg);
}

.search-result-body {
  padding: 0 12px 12px;
  border-top: 1px dashed var(--color-primary-light);
}

.search-result-line {
  margin: 8px 0 0;
  font-size: 0.78rem;
  line-height: 1.6;
  overflow-wrap: anywhere;
}

.search-result-links {
  margin-top: 10px;
}

.search-result-action {
  display: block;
  width: 100%;
  margin-top: 8px;
  padding: 10px 12px;
  border: none;
  border-radius: 12px;
  background: var(--color-primary);
  color: #fff;
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 800;
  cursor: pointer;
}

.search-result-action.is-secondary {
  background: var(--color-secondary-light);
  color: #2c6ea8;
}

.search-more-button {
  display: block;
  width: 100%;
  margin-top: 10px;
  padding: 10px 12px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 12px;
  background: var(--color-surface);
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 800;
  cursor: pointer;
}

.search-suggestions {
  margin-top: 12px;
  padding: 12px;
  border: 1.5px dashed var(--color-primary-light);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.5);
}

.search-suggestions-title {
  margin: 0 0 8px;
  font-size: 0.75rem;
  font-weight: 800;
}

.search-suggestion-button {
  display: block;
  width: 100%;
  margin-top: 6px;
  padding: 9px 12px;
  border: 1px solid var(--color-card-border);
  border-radius: 12px;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.8rem;
  text-align: left;
  cursor: pointer;
}

.search-highlight {
  padding: 0 1px;
  border-radius: 3px;
  background: var(--color-accent);
  color: inherit;
}

/* 検索結果から開いたカード・曲を、少しの間目立たせる */
.is-search-focus {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
}

/* 歌詞検索 */
.lyrics-search-result,
.lyrics-search-similar {
  padding: 12px;
}

.lyrics-search-result-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.lyrics-search-match-count {
  flex: none;
  font-size: 0.68rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.lyrics-search-snippets {
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
}

.lyrics-search-snippet {
  margin-top: 4px;
  padding: 6px 10px;
  border-left: 3px solid var(--color-primary-light);
  border-radius: 0 8px 8px 0;
  background: rgba(255, 225, 238, 0.25);
}

.lyrics-search-snippet-line,
.lyrics-search-full-line {
  margin: 0;
  font-size: 0.8rem;
  line-height: 1.7;
  overflow-wrap: anywhere;
}

.lyrics-search-snippet-line.is-similar {
  margin-top: 6px;
  opacity: 0.85;
}

.lyrics-search-more-note,
.lyrics-search-audio-note {
  margin: 6px 0 0;
  font-size: 0.68rem;
  opacity: 0.7;
}

.lyrics-search-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.lyrics-search-full {
  margin-top: 10px;
  padding: 10px 12px;
  border-radius: 12px;
  background: rgba(223, 242, 255, 0.35);
}

.lyrics-search-not-installed {
  margin: 8px 0;
  padding: 12px;
  border: 1.5px dashed var(--color-primary-light);
  border-radius: 14px;
  background: var(--color-surface);
  font-size: 0.8rem;
  line-height: 1.6;
}

.lyrics-search-not-installed p {
  margin: 0;
}

/* =========================================================
   【2026-10-24新設・本人指示】＝LOVEライブ初心者ガイド（#live-guide-screen、js/liveGuideScreen.js）
   既存のカード・ピンク系のトークンを使い、派手なアニメーションは付けない。
   ========================================================= */
.know-more-button-wide {
  grid-column: 1 / -1;
}

#live-guide-link::before {
  background: radial-gradient(circle at 20% 20%, rgba(255, 217, 61, 0.26), transparent 60%),
    radial-gradient(circle at 80% 80%, rgba(255, 111, 168, 0.18), transparent 60%);
}

.live-guide-content {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding-bottom: 32px;
}

.live-guide-hero {
  padding: 18px 16px;
  border: 1.5px solid var(--color-primary-light);
  border-radius: 20px;
  background: linear-gradient(140deg, #fff, var(--color-primary-light));
  box-shadow: 0 4px 16px rgba(255, 111, 168, 0.14);
}

.live-guide-hero-title {
  margin: 0 0 10px;
  color: var(--color-primary-dark);
  font-size: 1.15rem;
  font-weight: 800;
  line-height: 1.5;
}

.live-guide-hero-notice {
  margin: 10px 0 0;
  padding: 8px 10px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.75);
  font-size: 0.72rem;
  line-height: 1.6;
}

.live-guide-text {
  margin: 0 0 6px;
  font-size: 0.82rem;
  line-height: 1.75;
}

.live-guide-text.is-small {
  font-size: 0.72rem;
  opacity: 0.8;
}

.live-guide-toc {
  padding: 12px 14px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 16px;
  background: var(--color-surface);
}

.live-guide-toc-title,
.live-guide-block-title {
  margin: 0 0 8px;
  color: var(--color-primary-dark);
  font-size: 0.84rem;
  font-weight: 800;
}

.live-guide-toc-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}

@media (max-width: 380px) {
  .live-guide-toc-list {
    grid-template-columns: 1fr;
  }
}

.live-guide-toc-item {
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 6px 8px;
  border: 1px solid var(--color-primary-light);
  border-radius: 12px;
  background: #fff;
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.74rem;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
}

.live-guide-toc-number {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-size: 0.66rem;
}

.live-guide-chapter {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 18px;
  background: var(--color-surface-glass);
  scroll-margin-top: 12px;
}

.live-guide-chapter-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 2px;
  color: var(--color-text);
  font-size: 1rem;
  font-weight: 800;
}

.live-guide-chapter-icon {
  font-size: 1.2rem;
}

.live-guide-block {
  padding: 10px 12px;
  border-radius: 14px;
  background: #fff;
  border-left: 4px solid var(--color-primary-light);
}

.live-guide-block.is-official {
  border-left-color: var(--color-secondary);
}

.live-guide-block.is-varies {
  border-left-color: var(--color-accent);
  background: #fffdf3;
}

.live-guide-block.is-creator {
  border-left-color: var(--color-primary);
}

.live-guide-kind {
  display: inline-block;
  margin: 0 0 6px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-size: 0.64rem;
  font-weight: 800;
}

.live-guide-kind.is-official {
  background: var(--color-secondary-light);
  color: #2c6ea8;
}

.live-guide-kind.is-varies {
  background: var(--color-accent-soft);
  color: #8a6100;
}

.live-guide-kind.is-fan {
  background: #eef7e6;
  color: #3d7a1f;
}

.live-guide-list {
  margin: 0;
  padding-left: 1.2em;
  font-size: 0.8rem;
  line-height: 1.7;
}

.live-guide-list li + li {
  margin-top: 4px;
}

.live-guide-block-sources {
  margin: 6px 0 0;
  font-size: 0.66rem;
  line-height: 1.6;
  opacity: 0.85;
}

.live-guide-source-link {
  color: #2c6ea8;
  word-break: break-all;
}

.live-guide-checklist {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.live-guide-checklist-group {
  padding: 10px 12px;
  border-radius: 14px;
  background: #fff;
}

.live-guide-checklist-title {
  margin: 0 0 4px;
  font-size: 0.82rem;
  font-weight: 800;
}

.live-guide-checklist-group.is-must .live-guide-checklist-title {
  color: var(--color-primary-dark);
}

.live-guide-checklist-note {
  margin: 0 0 6px;
  font-size: 0.7rem;
  opacity: 0.75;
  line-height: 1.6;
}

.live-guide-check {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  font-size: 0.8rem;
  cursor: pointer;
}

.live-guide-check input {
  flex: none;
  width: 20px;
  height: 20px;
  accent-color: var(--color-primary-dark);
}

.live-guide-checklist-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.live-guide-checklist-progress {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.live-guide-secondary-button {
  min-height: 40px;
  padding: 6px 14px;
  border: 1.5px solid var(--color-primary-light);
  border-radius: 999px;
  background: #fff;
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.74rem;
  font-weight: 700;
  cursor: pointer;
}

.live-guide-planner {
  padding: 12px;
  border-radius: 14px;
  background: #fff;
  border: 1.5px dashed var(--color-primary-light);
}

.live-guide-planner-fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 6px;
}

.live-guide-planner-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.74rem;
  font-weight: 700;
}

.live-guide-planner-field input {
  min-height: 40px;
  padding: 4px 8px;
  border: 1.5px solid var(--color-primary-light);
  border-radius: 10px;
  font-family: inherit;
  /* 16px未満だとiPhoneで入力時に画面が拡大されるため */
  font-size: 16px;
  color: var(--color-text);
  background: #fff;
}

.live-guide-planner-options {
  display: flex;
  flex-direction: column;
}

.live-guide-planner-message {
  margin: 6px 0;
  font-size: 0.72rem;
  opacity: 0.8;
  line-height: 1.6;
}

.live-guide-planner-result {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.live-guide-planner-result li {
  display: flex;
  gap: 10px;
  align-items: baseline;
  font-size: 0.8rem;
  line-height: 1.6;
}

.live-guide-planner-time {
  flex: none;
  min-width: 3.2em;
  color: var(--color-primary-dark);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.live-guide-color-grid {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px 10px;
}

@media (max-width: 480px) {
  .live-guide-color-grid {
    grid-template-columns: 1fr;
  }
}

.live-guide-color-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.78rem;
}

.live-guide-color-swatches {
  display: inline-flex;
  flex: none;
}

.live-guide-color-swatch {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1.5px solid #fff;
  box-shadow: 0 0 0 1px rgba(74, 46, 66, 0.15);
}

.live-guide-color-swatch + .live-guide-color-swatch {
  margin-left: -5px;
}

.live-guide-color-name {
  font-weight: 700;
}

.live-guide-color-label {
  font-size: 0.68rem;
  opacity: 0.7;
}

.live-guide-actions {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.live-guide-action {
  min-height: 44px;
  padding: 8px 14px;
  border: 1.5px solid var(--color-primary);
  border-radius: 14px;
  background: linear-gradient(135deg, #fff, var(--color-primary-light));
  color: var(--color-primary-dark);
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 800;
  text-align: left;
  cursor: pointer;
}

.live-guide-action:active,
.live-guide-toc-item:active {
  transform: scale(0.98);
}

.live-guide-timeline {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
}

.live-guide-timeline-step {
  position: relative;
  display: flex;
  gap: 10px;
  padding-bottom: 12px;
}

.live-guide-timeline-step:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 13px;
  top: 28px;
  bottom: 0;
  width: 2px;
  background: var(--color-primary-light);
}

.live-guide-timeline-number {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--color-primary);
  color: #fff;
  font-size: 0.78rem;
  font-weight: 800;
}

.live-guide-timeline-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: 3px;
  font-size: 0.78rem;
  line-height: 1.6;
}

.live-guide-faq {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.live-guide-faq-item {
  border-radius: 12px;
  background: #fff;
  border: 1px solid var(--color-primary-light);
}

.live-guide-faq-item summary {
  min-height: 44px;
  display: flex;
  align-items: center;
  padding: 8px 12px;
  font-size: 0.82rem;
  font-weight: 800;
  cursor: pointer;
  list-style: none;
}

.live-guide-faq-item summary::-webkit-details-marker {
  display: none;
}

.live-guide-faq-item summary::before {
  content: "Q";
  flex: none;
  margin-right: 8px;
  color: var(--color-primary-dark);
}

.live-guide-faq-item[open] summary {
  border-bottom: 1px dashed var(--color-primary-light);
}

.live-guide-faq-item .live-guide-text {
  padding: 8px 12px 10px;
  margin: 0;
}

.live-guide-footer {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px;
  border-radius: 18px;
  background: var(--color-surface);
  border: 1.5px solid var(--color-card-border);
}

.live-guide-source-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 0.72rem;
  line-height: 1.6;
}

.live-guide-source-list .live-guide-kind {
  margin: 0 6px 0 0;
}

/* ===== 歴代センター一覧（2026-10-27新設・js/centersScreen.js） =====
   スマホで横に長い表にしないため、1曲＝1枚の小さなカードにする。
   右側の「センターのマス」はメンバーカラーを背景にし、文字色（黒／白）は js/centerChart.js が
   背景の明るさから選ぶ。どちらでも読みにくい色には has-outline で縁取りを付ける。 */
.centers-entry-button {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  margin: 4px 0 14px;
  padding: 12px 14px;
  border: 1.5px solid var(--color-primary-light);
  border-radius: 16px;
  background: linear-gradient(120deg, #fff, var(--color-primary-light));
  color: var(--color-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  box-shadow: 0 3px 12px rgba(255, 111, 168, 0.12);
}

.centers-entry-button:active {
  transform: scale(0.98);
}

.centers-entry-swatches {
  display: grid;
  grid-template-columns: repeat(2, 12px);
  gap: 3px;
  flex-shrink: 0;
}

.centers-entry-swatches span {
  width: 12px;
  height: 12px;
  border-radius: 3px;
}

.centers-entry-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}

.centers-entry-label {
  font-size: 0.92rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.centers-entry-description {
  font-size: 0.72rem;
  color: #7a6170;
}

.centers-entry-arrow {
  font-weight: 800;
  color: var(--color-primary-dark);
}

.centers-content {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-bottom: 32px;
}

.centers-intro {
  padding: 12px 14px;
  border-radius: 16px;
  background: var(--color-surface);
  border: 1.5px solid var(--color-card-border);
}

.centers-intro-text {
  margin: 0 0 8px;
  font-size: 0.8rem;
  line-height: 1.6;
}

.centers-legend summary {
  font-size: 0.78rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  cursor: pointer;
}

.centers-legend-list {
  margin: 8px 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.centers-legend-list li {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.centers-legend-list .center-evidence-badge {
  flex-shrink: 0;
  min-width: 7.5em;
  text-align: center;
}

.centers-legend-text {
  font-size: 0.72rem;
  line-height: 1.55;
  color: #6b5462;
}

.centers-controls .search-field-row {
  margin-bottom: 8px;
}

.center-member-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.center-member-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 10px;
  border: 1.5px solid var(--color-card-border);
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit;
  font-size: 0.74rem;
  font-weight: 700;
  cursor: pointer;
}

.center-member-chip.is-active {
  border-color: var(--color-primary);
  background: var(--color-primary-light);
  color: var(--color-primary-dark);
}

.center-member-chip-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, 0.15);
}

.centers-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  font-size: 0.75rem;
}

.centers-summary {
  margin: 8px 0 0;
  font-size: 0.72rem;
  color: #7a6170;
}

.center-row-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.center-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 10px 12px;
  border-radius: 14px;
  background: var(--color-surface);
  border: 1px solid var(--color-card-border);
}

.center-row-info {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  min-width: 0;
}

.center-row-tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
}

.center-tag {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 0.62rem;
  font-weight: 800;
  color: #5f4a57;
  background: #f1ecef;
}

.center-tag.is-role-title {
  color: var(--color-primary-dark);
  background: var(--color-primary-light);
}

.center-tag.is-role-unit {
  color: #1c5f8a;
  background: #e1f0fa;
}

.center-tag.is-work-album,
.center-tag.is-work-digital,
.center-tag.is-work-special {
  color: #7a4d00;
  background: #fff0c9;
}

.center-row-date {
  font-size: 0.64rem;
  color: #8a7482;
}

.center-row-title {
  padding: 0;
  border: none;
  background: none;
  color: var(--color-text);
  font: inherit;
  font-size: 0.92rem;
  font-weight: 800;
  line-height: 1.35;
  text-align: left;
  text-decoration: underline dotted rgba(74, 46, 66, 0.35);
  text-underline-offset: 3px;
  cursor: pointer;
  overflow-wrap: anywhere;
}

.center-row-note {
  margin: 0;
  font-size: 0.68rem;
  line-height: 1.5;
  color: #7a6170;
}

.center-cells {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 7.6em;
}

.center-cells-label {
  font-size: 0.6rem;
  font-weight: 800;
  text-align: center;
  color: #8a7482;
}

/* センターのマス本体（メンバーカラーが背景） */
.center-cell {
  display: block;
  width: 100%;
  padding: 8px 4px;
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 9px;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 800;
  line-height: 1.25;
  text-align: center;
  cursor: pointer;
}

.center-cell:active {
  transform: scale(0.97);
}

.center-cell:disabled {
  cursor: default;
}

/* 背景と文字のコントラストが足りない色だけ、文字に縁取りを付ける */
.center-cell.has-outline[data-text-tone="dark"],
.center-cell.is-all {
  text-shadow: 0 0 2px #fff, 0 0 2px #fff, 0 0 3px #fff;
}

.center-cell.has-outline[data-text-tone="light"] {
  text-shadow: 0 0 2px rgba(0, 0, 0, 0.7), 0 0 3px rgba(0, 0, 0, 0.5);
}

.center-cell.is-all {
  color: #24151f;
  cursor: default;
}

.center-cell.is-none {
  color: #6b5a66;
  background: repeating-linear-gradient(135deg, #f3f0f2, #f3f0f2 6px, #e9e4e8 6px, #e9e4e8 12px);
  cursor: default;
}

.center-cell.is-unconfirmed {
  color: #8a7482;
  background: transparent;
  border-style: dashed;
  cursor: default;
}

/* ソロ・2人の曲の「歌っているメンバー」は、センターと区別するため小さく・控えめに */
.center-cell.is-singer {
  padding: 5px 4px;
  font-size: 0.72rem;
  opacity: 0.85;
}

/* 根拠のラベル（公式／報道／メンバー発言／ファン資料のみ／本人指定・公式記載なし／根拠未確認） */
.center-evidence-badge {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 0.64rem;
  font-weight: 800;
  line-height: 1.6;
  text-decoration: none;
  white-space: nowrap;
}

.center-evidence-badge.is-official {
  color: #1d6b3c;
  background: #dff3e6;
}

.center-evidence-badge.is-press {
  color: #1c5f8a;
  background: #e1f0fa;
}

.center-evidence-badge.is-member {
  color: #5b3a8c;
  background: #ece3f7;
}

.center-evidence-badge.is-fan {
  color: #8a4b00;
  background: #ffe9c7;
}

.center-evidence-badge.is-user {
  color: #8c2f5d;
  background: #fbe3ee;
}

.center-evidence-badge.is-unknown {
  color: #5f5a5d;
  background: #ebe8ea;
}

.track-center-line .center-evidence-badge {
  vertical-align: 1px;
}

.track-centers-link {
  font-size: 0.7rem;
}

@media (max-width: 360px) {
  .center-cells {
    width: 6.6em;
  }
}

/* ===== ライブのセットリスト・「ライブでの披露」（2026-10-27新設・js/setlistView.js） ===== */
.live-setlist {
  margin-top: 8px;
  border-top: 1px dashed var(--color-primary-light);
  padding-top: 6px;
}

.live-setlist-summary {
  font-size: 0.76rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  cursor: pointer;
}

.live-setlist-body {
  margin-top: 6px;
}

.live-setlist-meta,
.live-setlist-note,
.live-setlist-sources {
  margin: 0 0 4px;
  font-size: 0.7rem;
  line-height: 1.5;
  color: #7a6170;
}

.live-setlist-source-link {
  color: var(--color-primary-dark);
}

.setlist-items {
  margin: 6px 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.setlist-item {
  display: grid;
  grid-template-columns: 2em minmax(0, 1fr);
  gap: 6px;
  padding: 3px 0;
  border-bottom: 1px solid rgba(74, 46, 66, 0.06);
  font-size: 0.78rem;
}

.setlist-item.is-encore,
.setlist-item.is-double-encore {
  background: rgba(111, 189, 242, 0.08);
}

.setlist-item.is-reference {
  opacity: 0.7;
}

.setlist-item-order {
  text-align: right;
  font-weight: 800;
  color: #8a7482;
}

.setlist-item-body {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 6px;
  min-width: 0;
}

.setlist-item-title {
  font-weight: 700;
  overflow-wrap: anywhere;
}

.setlist-item-title.is-link {
  padding: 0;
  border: none;
  background: none;
  color: var(--color-text);
  font: inherit;
  font-weight: 700;
  text-align: left;
  text-decoration: underline dotted rgba(74, 46, 66, 0.4);
  text-underline-offset: 3px;
  cursor: pointer;
}

.setlist-item-tag {
  padding: 0 6px;
  border-radius: 999px;
  font-size: 0.6rem;
  font-weight: 800;
  color: #1c5f8a;
  background: #e1f0fa;
}

.setlist-item-note {
  flex-basis: 100%;
  font-size: 0.66rem;
  line-height: 1.45;
  color: #7a6170;
}

/* 収録曲一覧の行（.track-row は横並び）の2段目に、行の幅いっぱいで出す */
.track-row.has-live-section {
  flex-wrap: wrap;
}

.track-row > .song-live-section {
  flex: 0 0 calc(100% - 42px);
  margin: -4px 0 0 42px;
  min-width: 0;
}

.song-live-section-summary {
  font-size: 0.74rem;
  font-weight: 800;
  color: var(--color-primary-dark);
  cursor: pointer;
}

.song-live-section-body {
  margin-top: 6px;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(255, 225, 238, 0.35);
}

.song-live-sentence,
.song-live-caption {
  margin: 0 0 4px;
  font-size: 0.72rem;
  line-height: 1.55;
}

.song-live-caption {
  color: #7a6170;
}

.song-live-subheading {
  margin: 8px 0 4px;
  font-size: 0.72rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.song-live-performances,
.song-live-videos {
  margin: 4px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.song-live-performance,
.song-live-video {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  font-size: 0.72rem;
  line-height: 1.45;
}

.song-live-performance-link {
  padding: 0;
  border: none;
  background: none;
  color: var(--color-primary-dark);
  font: inherit;
  font-weight: 700;
  text-align: left;
  text-decoration: underline;
  cursor: pointer;
}

.song-live-performance-text {
  font-weight: 700;
}

.song-live-performance-meta,
.song-live-performance-note,
.song-live-video-note {
  font-size: 0.66rem;
  color: #7a6170;
}

.song-live-video-tag {
  padding: 0 7px;
  border-radius: 999px;
  font-size: 0.6rem;
  font-weight: 800;
  color: #1d6b3c;
  background: #dff3e6;
}

.song-live-video-tag.is-undisclosed {
  color: #5f5a5d;
  background: #ebe8ea;
}

.song-live-video-link {
  font-size: 0.66rem;
  color: var(--color-primary-dark);
}

/* ===== 【2026-10-28追加】曲からライブ映像を探す・映像商品の一覧・セットリストのタグ ===== */
.song-live-video-meta {
  display: block;
  font-size: 0.66rem;
  color: #5c4a55;
}

.song-live-video-meta.is-streaming-available {
  color: #1d6b3c;
  font-weight: 700;
}

.song-live-video-links {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
}

.live-event-tag.is-setlist-full {
  color: #7a3b8f;
  background: #f1e3f7;
}

.live-event-tag.is-setlist-partial {
  color: #6b5a2a;
  background: #f5edd3;
}

.song-video-finder,
.video-product-list {
  margin: 12px 0 16px;
  padding: 12px 14px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.85);
  box-shadow: 0 2px 10px rgba(232, 106, 160, 0.12);
}

.song-video-finder-input {
  width: 100%;
  box-sizing: border-box;
  margin: 6px 0 4px;
  padding: 10px 14px;
  border: 1.5px solid var(--color-primary-light);
  border-radius: 999px;
  font: inherit;
  font-size: 0.9rem;
  background: #fff;
}

.song-video-finder-song {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px dashed var(--color-primary-light);
}

.video-product {
  margin-top: 8px;
  border-top: 1px dashed var(--color-primary-light);
  padding-top: 6px;
}

/* 【2026-10-28 本人指示】歴代センターの「全員」は、特定のメンバーの色を使わず、アプリの基調色（ピンク〜ラベンダー）だけで表す */
.center-cell.is-all {
  color: var(--color-primary-dark);
  background: linear-gradient(135deg, #ffe4f0 0%, #f6e6ff 55%, #e6efff 100%);
  border: 1.5px solid var(--color-primary-light);
  letter-spacing: 0.2em;
  text-shadow: none;
}

.center-app-rule {
  display: inline-block;
  margin-top: 4px;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 0.62rem;
  font-weight: 700;
  color: #6a4f8a;
  background: #efe7f8;
}
