/**
 * styles/viewport.css
 *
 * PC/スマホで再生領域のサイズを4段階に切り替えるための共通CSS変数。
 * body の viewport-{mobile|tablet|desktop|wide} class（core/GameViewport.js が付与）に
 * 応じて、各画面の「プレイ領域」を決める基準値を CSS変数として再定義する。
 *
 *   --play-root-max-width : #game-root（ヘッダー・メッセージ欄を含む外枠）の最大幅
 *   --play-area-max-width : #inline-game-area / #js-game-root（ゲーム本体）の最大幅
 *   --game-board-scale    : 各ゲームの盤面を拡大したい場合に参照できる倍率（任意・現状未使用）
 *
 * mobile は既定値（:root）のままで、現状の見た目を変えない。
 * tablet/desktop/wide で段階的に広げる。
 *
 * ゲームごとの例外は body.game-{id}.viewport-{tier} で --play-area-max-width のみを
 * 上書きする（個別ゲームのCSS自体は変更せず、外枠の幅だけを調整する）。
 */

:root {
  --play-root-max-width: 420px;
  --play-area-max-width: 370px;
  --game-board-scale: 1;

  /* ─── 高さベースの予算（PCでも盤面が1画面に収まるようにするための基準値） ───
     --play-header-height    : #game-root padding-top(16) + .screen-header(44) + #game-message(39)
                                の実測合計(≈99px)に少し余裕を足した値。
     --play-bottom-safe-area : #game-root の padding-bottom(180px, games.css)と同じ値。
                                キャラクター（.char-actor / 吹き出し）のための余白で、
                                ここを実際の padding-bottom と揃えないと高さ予算が
                                実態より緩くなり、PCで再びオーバーフローする。
     --play-available-height : 上記2つを差し引いた「盤面が使える高さ」の目安。
                                各ゲーム固有CSSでは、ここからさらにそのゲーム自身の
                                ヘッダー/ボタン等の高さを引いて盤面サイズの上限に使う。 */
  --play-header-height: 120px;
  --play-bottom-safe-area: 180px;
  --play-available-height: calc(100vh - var(--play-header-height) - var(--play-bottom-safe-area));
}

body.viewport-tablet {
  --play-root-max-width: 720px;
  --play-area-max-width: 620px;
  --game-board-scale: 1.08;
}

body.viewport-desktop {
  --play-root-max-width: 960px;
  --play-area-max-width: 760px;
  --game-board-scale: 1.18;
}

body.viewport-wide {
  --play-root-max-width: 1120px;
  --play-area-max-width: 900px;
  --game-board-scale: 1.28;
}

/* ─── ゲーム別の例外 ───────────────────────────────────────────
   各ゲーム固有の事情に合わせて --play-area-max-width のみを上書きする。
   ゲーム本体のCSS（games/*/game.css 等）は変更しない。 */

/* パズル: .pz-play-area の上限(380px)も同じ変数を参照するように変更済みのため、
   ここを広げると盤面自体も広がる。 */
body.game-puzzle.viewport-desktop {
  --play-area-max-width: 760px;
}

/* 福笑い: .fw-app が自前で max-width:900px を持つため、外枠がそれより
   狭くならないように確保するだけ（fw-app自体のCSSは変更しない）。 */
body.game-fukuwarai.viewport-desktop {
  --play-area-max-width: 960px;
}

/* 神経衰弱(memory-card): 4列カードグリッドが大きすぎると崩れやすいため、
   汎用値(760px)より控えめに広げる。 */
body.game-memory-card.viewport-desktop {
  --play-area-max-width: 560px;
}

body.game-memory-card.viewport-tablet {
  --play-area-max-width: 640px;
}

/* ESM版おなじカードさがしは #js-game-root 直下に #memory-card-root を生成する。
   親の align-items:center による shrink-wrap を防ぎ、#card-grid の width:100% が
   プレイ領域幅を正しく参照できるよう、ゲームルート自身を横いっぱいに伸ばす。 */
body.game-memory-card #memory-card-root {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* ─── 幅・高さ両方の予算でフィットさせる共通primitive（Issue #820） ───────────
   aspect-ratioを持つ盤面を、横幅の予算（--play-area-max-width）だけでなく
   利用可能な高さの予算（--play-available-height、またはゲーム側が渡す
   より正確なheight budget）からも上限を算出し、小さい方を採用する。
   mobile/tablet/desktop/wide全tierで同じ式を使い、tier別の個別分岐を
   増やさない（mobileでも高さが十分にあれば従来どおり横幅上限が採用される
   ため、縦長スマホの見た目は変わらない）。

   ゲーム側は対象要素に .gv-fit-max-width クラスを付与し、次の4つの
   CSS変数だけを宣言すればよい（いずれも省略可・既定値あり）。
     --gv-fit-height-budget  : 利用可能な高さの予算。既定は
                                var(--play-available-height)。ゲーム自身が
                                より正確な予算（下限floor込み等）を持つ場合は
                                ここを上書きしてよい。
     --gv-fit-aspect         : 対象盤面の width ÷ height 比（例: 4:3なら 4/3）。
     --gv-fit-height-overhead: 対象要素の縦方向の固定オーバーヘッド
                                （ヘッダー・gap・padding-block等、盤面の
                                aspect-ratioで決まらない縦方向固定分の合計px）。
     --gv-fit-width-chrome   : 対象要素の横方向の固定オーバーヘッド
                                （矢印用padding-inline等、盤面幅には含まれない
                                横方向固定分の合計px。既定0）。
                                対象要素に「aspect-ratio付きの内側盤面 +
                                盤面数に依存しうる横chrome（矢印分の
                                padding等）」がある場合、この横chromeを
                                heightBudget側の一次式（下記）へ折り込むと、
                                盤面数ごとにchrome量が違うのに同じ
                                height-overheadを使い回すことになり、
                                chromeが大きい構成ほど内側盤面が不必要に
                                縮む（Issue #820 Codexレビュー指摘）。
                                縦overheadと横chromeを別変数に分けることで、
                                内側盤面のサイズはchrome量に依存せず一定に
                                保たれる。

   計算は次の2つの小さい方を max-width として採用する。
     - 横幅の予算（--play-area-max-width）
     - (高さの予算 − 縦overhead) × aspect + 横chrome
   puzzle/memory-card が個別に持つ min() 式も同じ考え方を使う。
   Issue #853では既存selector契約を維持しつつ、実DOMの縦overhead・横chrome・
   現行grid形状に合わせて個別式を更新している。 */
.gv-fit-max-width {
  --gv-fit-height-budget: var(--play-available-height, calc(100vh - 300px));
  --gv-fit-aspect: 1;
  --gv-fit-height-overhead: 0px;
  --gv-fit-width-chrome: 0px;
  max-width: min(
    var(--play-area-max-width, 370px),
    calc(
      (var(--gv-fit-height-budget) - var(--gv-fit-height-overhead, 0px)) * var(--gv-fit-aspect, 1)
      + var(--gv-fit-width-chrome, 0px)
    )
  );
}

/* ─── 高さも考慮した盤面サイズ（PCでスクロールが出ないようにする） ───────────
   横幅だけを var(--play-area-max-width) で広げると、PCでは縦方向の余白を
   考えずに正方形/グリッドが巨大化し、#screen-play(overflow-y:auto) 内で
   縦スクロールが必要になってしまう（パズル・神経衰弱で発生していた問題）。
   ここでは「横幅の上限」と「高さから逆算した上限」を min() で比較し、
   小さい方を最終サイズに使う。mobile（:root既定）は変更しないため、
   tablet/desktop/wide にのみ適用する。 */

/* パズル: .pz-play-area は「正方形の .pz-board-wrap + gap 8px +
   固定幅100pxの .pz-next-area」の横並び。高さ予算を使うのは正方形boardであり、
   play-area全体ではないため、高さから外側幅へ戻す際は横chrome 108pxを加える。
   98px = .pz-root の padding-top(8) + .pz-header(60+margin10) + padding-bottom(20)
          という、パズル自身がさらに必要とする縦の余白。 */
body.game-puzzle.viewport-tablet .pz-play-area,
body.game-puzzle.viewport-desktop .pz-play-area,
body.game-puzzle.viewport-wide .pz-play-area {
  width: min(
    calc(100vw - 16px),
    calc(var(--play-available-height, calc(100vh - 300px)) - 98px + 108px),
    var(--play-area-max-width, 380px)
  );
}

/* 神経衰弱(memory-card): 現行難易度は easy 3x3 / normal 4x4 / hard 5x5。
   全難易度で cols === rows、各カードは aspect-ratio:1、gapも縦横9pxなので
   #card-grid全体も正方形になる。旧4列x6行前提の2/3変換は使わず、
   高さ予算を1:1でgrid幅上限へ変換する。
   48px = 現行 .mc-header（手数 + もういっかい）の高さ・marginを含む安全余白。 */
body.game-memory-card.viewport-tablet #card-grid,
body.game-memory-card.viewport-desktop #card-grid,
body.game-memory-card.viewport-wide #card-grid {
  max-width: min(
    var(--play-area-max-width, 370px),
    calc(var(--play-available-height, calc(100vh - 300px)) - 48px)
  );
}

/* coarse pointerのdesktopは既存どおりbottom safe areaを別扱いする特別height budgetを
   維持する。ただしgrid自体は正方形なので、ここでも旧4x6の2/3変換は行わない。 */
@media (pointer: coarse) and (max-width: 1366px) {
  body.game-memory-card.viewport-desktop #card-grid {
    max-width: min(
      var(--play-area-max-width, 370px),
      calc(100vh - var(--play-header-height, 120px) - 64px - 48px)
    );
  }
}

/* ─── ゲーム選択カルーセルの縦描画余白（Issue #500 再対応） ───────────
   activeカードは中央基準で最大1.08倍に拡大されるため、従来の上padding 18pxでは
   カード上側の描画余白が不足しやすい。カード自体は追加縮小せず、全viewport共通で
   track上paddingだけを増やしてカード群のY位置を下げる。paddingはtrack自身の高さにも
   含まれるため、増えた分だけ下方向の描画・縦スクロール範囲も自然に拡張される。
   Issue #546の切り分けに伴い、PR #543で試した136pxからPR #542の36pxへ戻す。 */
.gs-lanes .carousel-track {
  padding-top: 36px;
}
