/* ===========================================================================
   プロフィール帳モーダル（拡大縮小ビューワ）

   profsheet.html（一覧ページ）と index.html（/special/ トップ）の両方から
   読み込む。profsheet.css から分離した理由：
   profsheet.css は :root / html / body などページ全体の土台スタイルを含むため、
   index.html に丸ごと読ませるとトップページの背景が上書きされて壊れる。

   このファイルは :root のカスタムプロパティに依存しない（--pm-* は .pm-modal
   内で定義している）。単独で読み込んで成立する。

   設計書: docs/2026-08-17-special-profsheet-modal-design.md §2.2 / §4
   =========================================================================== */

/* ===== プロフィール帳モーダル ===== */

/* ProfileZoom が要求する必須スタイル。
   profsheet-zoom.js の README（_work/profile/js/README.md）から逐語で移したもの。1つも削らないこと。
   - touch-action: none —— Draggable は自身のトリガー要素にしか設定しないため、
     画像をフィット表示したときの余白（レターボックス）部分がカバーされない。
     そこからピンチを始めるとブラウザのネイティブズームが発動する。
   - .is-dragging —— モジュールがドラッグ中にこのクラスを付け外しする。
   - canvas と img の width/height はモジュールが実寸を設定するのでCSSで指定しない。 */
.pm-viewport {
  position: relative;
  overflow: hidden;
  touch-action: none;
  cursor: grab;
}

.pm-viewport.is-dragging {
  cursor: grabbing;
}

.pm-canvas {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
}

.pm-image {
  display: block;
  max-width: none;
  max-height: none;
  /* user-select / user-drag / touch-action はズーム・パン操作の成立に必須。
     保存防止のための指定ではないので、保存防止対応の見直し時にも消さないこと。 */
  user-select: none;
  -webkit-user-drag: none;
  touch-action: none;
  /* 画像保存防止。iOS Safari の長押しメニュー（画像を保存）を抑止する。
     PC の右クリックメニューは profsheet-modal.js の contextmenu ハンドラが担当し、
     この2つで対になる。
     サイト共通の方式（実画像をCSS背景にして透明画像を重ねる）は、ProfileZoom が
     <img> の実寸を測って canvas に transform をかける設計のため適用できない。
     開発者ツールからは取得可能で完全な防止はできない点も共通方式と同じ。
     設計書 §7 */
  -webkit-touch-callout: none;
}

.pm-modal {
  position: fixed;
  inset: 0;
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 0;
  border: none;
  background: transparent;
}

.pm-modal::backdrop {
  /* Figma実測（ノード2776-21718）: bg-[rgba(0,0,0,0.8)] */
  background: rgba(0, 0, 0, .8);
}

.pm-controls {
  position: absolute;
  top: 29px;
  right: 25px;
  display: flex;
  gap: 18.67px;
  z-index: 2;
}

.pm-controls button {
  width: 28px;
  height: 28px;
  padding: 0;
  border: none;
  background: transparent no-repeat center / contain;
  cursor: pointer;
}

/* Figma実測（ノード2776-21718 Frame 417）: アイコンはいずれも28×28、白抜き。
   zoom_out だけ Figma上は #A9A9A9（灰）で書き出されるが、白に統一している。
   Figmaはモーダルをフィット表示の状態（＝それ以上縮小できない）で描いているため、
   その「押せない」表現がアイコンの色として焼き付いたものと判断した。押せない状態は
   下の .pm-controls button:disabled の opacity で表現済みなので、アセットも灰色だと
   二重になり、押せるときまで無効に見えてしまう。
   セレクタは「.pm-controls 」を付けてクラス数2にし、上の「.pm-controls button」
   （クラス1+要素1）より詳細度を上げている。単なる「.pm-fullscreen」のようなクラス1個
   だけの詳細度だと、後方の記述でも「.pm-controls button」の background 一括指定に
   負けて background-image が反映されない（実機検証で発見）。 */
.pm-controls .pm-fullscreen { background-image: url(../img/icon_modal_fullscreen.svg); }
.pm-controls .pm-close      { background-image: url(../img/icon_modal_close.svg); }

/* zoom_in/zoom_out のSVGは21×21で書き出されており（fullscreen/closeは28×28で書き出され、
   絵柄自体は内側12.5%インセットで既に21×21相当）、共通ルールの contain のままだと
   28×28いっぱいに拡大されてしまい他の2つより一回り大きく見える。
   Figma実測どおりの見た目（28px枠に対し21px、12.5%インセット）に揃えるため
   サイズだけ明示指定する。 */
.pm-controls .pm-zoom-in {
  background-image: url(../img/icon_modal_zoomin.svg);
  background-size: 21px 21px;
}
.pm-controls .pm-zoom-out {
  background-image: url(../img/icon_modal_zoomout.svg);
  background-size: 21px 21px;
}

.pm-controls button:disabled {
  opacity: .35;
  cursor: default;
}

/* 画像エリアの寸法は「1440×1024フレーム基準の固定px」だけで決めない（C-1 / I-2）。
   --pm-img-w は次の3値の最小値：
     1) Figma基準の画像幅 1014px
     2) 画像左右マージンを確保した幅（100% - 2*side）
     3) ビューポート高さから逆算した幅（画像を高さ方向にも収める）
   3) を含めることで、ビューポート高さが1024pxより低い一般的な画面（1440×800等）でも
   画像が画面外に出ない。矢印は画像そのものの矩形ではなく --pm-img-w を基準に
   「画像の外側」へ位置決めするため、768〜1199.98pxのタブレット帯で画像左端が
   100pxマージンに張り付いても矢印が画像に重ならない（専用ブレークポイントを増やさずに
   768px超のすべての幅で成立する）。 */
.pm-modal {
  --pm-top: 129px;      /* 画像上端までの余白（Figma実測） */
  --pm-bottom: 175px;   /* 画像下端からモーダル下端まで（ボタン領域を含む） */
  --pm-side: 100px;     /* 画像左右の最小マージン */
  --pm-arrow-gap: 24px; /* 矢印と画像の間隔（Figma実測 約23〜26px） */
  --pm-slot-h: calc(100dvh - var(--pm-top) - var(--pm-bottom));
  --pm-img-w: min(1014px, calc(100% - 2 * var(--pm-side)), calc(var(--pm-slot-h) * 1014 / 720));
  --pm-img-top: calc(var(--pm-top) + var(--pm-slot-h) / 2); /* 画像エリアの垂直中心 */
}

/* 画像エリア。アスペクト比を固定して初期表示のガタつきを防ぐ */
/* 前段（ProfileZoom必須CSS）で position: relative を指定済みだが、
   ここで position: absolute に上書きする（ソース順に依存。順序を変えないこと）。 */
.pm-viewport {
  position: absolute;
  top: var(--pm-img-top);
  left: 50%;
  width: var(--pm-img-w);
  aspect-ratio: 1014 / 720;
  transform: translate(-50%, -50%);
}

.pm-prev,
.pm-next {
  position: absolute;
  top: var(--pm-img-top);
  width: 57px;
  height: 57px;
  padding: 0;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  z-index: 2;
  transform: translateY(-50%);
  /* Figma実測（ノード2776-21718 Group 260）: 白い円 + 黒（#33363B）矢印グラフィックが
     1枚のSVGに収まっている（円の背景色を別途指定する必要はない）。
     書き出されたアセットは向き（prev/next）に関わらず同一の左向き矢印だったため
     （Figma側のインスタンスの左右反転がエクスポートに反映されていない）、
     1つのアセットを共用し .pm-next 側だけ CSS で水平反転する。 */
  background: url(../img/icon_modal_arrow_prev.svg) no-repeat center / contain;
}

.pm-prev { left: calc(50% - var(--pm-img-w) / 2 - var(--pm-arrow-gap) - 57px); }
.pm-next {
  left: calc(50% + var(--pm-img-w) / 2 + var(--pm-arrow-gap));
  transform: translateY(-50%) scaleX(-1);
}

.pm-prev:disabled,
.pm-next:disabled {
  opacity: .35;
  cursor: default;
}

.pm-panel {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
}

/* PCでは下部パネル内の矢印（SP用）は使わない */
.pm-nav { display: none; }

.pm-actions {
  position: absolute;
  bottom: 59px; /* 1024 - 889 - 76 */
  left: 0;
  display: flex;
  justify-content: center;
  gap: 40px;
  width: 100%;
}

.pm-back,
.pm-detail {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 320px;
  height: 76px;
  text-decoration: none;
  /* Figma実測（ノード2776-21718 PC_button）:
     border-3 border-white border-solid / rounded-[5px] / text-[18px] font-bold text-white */
  border: 3px solid #fff;
  border-radius: 5px;
  background: transparent;
  color: #fff;
  font-size: 18px;
  font-weight: 700;
}

/* 疑似全画面: 下部パネルと矢印を隠して画像エリアを最大化する。
   Fullscreen API は使わない（iOS Safari が <video> 以外で非対応）。
   コントロール群は残す —— でないと解除できない。 */
.pm-modal.is-fullscreen .pm-panel,
.pm-modal.is-fullscreen .pm-prev,
.pm-modal.is-fullscreen .pm-next {
  display: none;
}

.pm-modal.is-fullscreen .pm-viewport {
  top: 67px;
  left: 0;
  width: 100%;
  max-width: none;
  height: calc(100% - 67px);
  aspect-ratio: auto;
  transform: none;
}

/* 画像の読み込みに失敗した状態。ズームボタンはJS側で disabled にしている */
.pm-modal.is-image-error .pm-viewport::after {
  content: "画像を読み込めませんでした";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #ffffff;
}

/* 読み込み中の表示。新しい画像ファイルは追加せず、CSSのみのスピナーで表現する。
   タップ直後や矢印での前後送り直後は canvas に前の選手の画像（または空）が
   残ったままなので、半透明の幕で覆って「前の選手の画像がそのまま新しい選手の
   画像であるかのように見える」ことを防ぐ（profsheet.js の showAt() 参照）。
   is-image-error の ::after と同じく .pm-viewport 基準の inset:0 にすることで、
   PC/タブレット/SPどのブレークポイントでも画像エリアの実寸に自動で追従する。 */
.pm-loading {
  display: none;
  position: absolute;
  inset: 0;
  align-items: center;
  justify-content: center;
  background: rgba(51, 54, 59, .55);
  z-index: 1;
}

.pm-modal.is-loading .pm-loading {
  display: flex;
}

.pm-spinner {
  width: 48px;
  height: 48px;
  border: 5px solid rgba(255, 255, 255, .35);
  border-top-color: #FF6623;
  border-radius: 50%;
  animation: pm-spin .8s linear infinite;
}

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

@media (max-width: 767.98px) {
  .pm-controls {
    top: 8px;
    right: 19px;
  }

  /* .pm-viewport は「画像を覗く窓」であり、「フィット時の画像サイズ」そのものではない。
     旧実装（d026f18以前）はこの2つを混同し、.pm-viewport の top/width を
     375×812でのフィット時実測値（top:252, width:351）とほぼ同じ値で固定し、
     さらに PC から継承した aspect-ratio:1014/720 で高さまで画像比率に固定していた。
     窓＝画像サイズにしてしまうと、実機（iPhone SE、Safari UIを除いた実質375×565）では
     コントロール下から画像上端まで107pxもの空白が残ったまま画像を置く高さが足りず、
     d026f18 はその不足分を「画像幅を縮める」ことで帳尻合わせしていた
     （--pm-sp-img-w が高さから逆算した幅を採用し、351px→279pxに縮小）。
     横向き（667×375等）は直ったが、縦向きの低い機種で画像が縮む回帰を生んでいた。

     Figmaで確認した設計は次の2ノードから裏付けられる。
       - 拡大時ノード 2776:22259（Frame 151）: 画像フレームは x=0, y=113, 1046×742
         （border-radius:10px）。窓はコントロール群の下 y=113 から始まり、
         横幅は画面いっぱい。下部パネルが半透明（rgba(103,103,103,.9)）なのは、
         窓がパネルの裏まで続いており、画像がパネルに透けて見える設計だから。
       - フィット時ノード 2776:22224: 画像は 351×249、y=252（左右12pxの余白）。
     コントロール群は top:67px + 高さ28px = 下端95pxなので、その18px下が y=113。

     このブロックでは .pm-viewport を「窓」として、コントロール群の直下から
     下部パネル手前までの高さで定義する。aspect-ratio は PC から継承した
     1014/720 を auto で打ち消し、拡大前画像の縦横比に関係なく窓の高さを明示する。
     2026-08-08の実機フィードバックを受け、拡大画像をできるだけ広く見られるよう、
     上部コントロールと下部パネルの余白を必要最小限に詰めている。
     窓が画像比率より縦長になる分は上下にレターボックスができ、
     ProfileZoom（.pm-viewport への ResizeObserver。
     profsheet-zoom.js:514-517）が窓のサイズ変化を検知してフィット倍率を
     自動再計算し、画像を窓の中央に置く（touch-action:none はこのレターボックス
     部分でネイティブズームが暴発するのを防ぐために必須なので消さないこと）。

     --pm-sp-viewport-top : 窓の上端。コントロール下端から8px空ける。
     --pm-sp-panel-h       : 下部パネルの高さ（.pm-panelと同じ値を単一ソース化）。
     --pm-sp-panel-top     : パネル上端のY座標（100dvh - パネル高さ）。
     --pm-sp-gap           : 窓下端とパネル上端の間の最小余白。
     --pm-sp-viewport-h    : 窓の高さ（パネル上端 - 窓上端 - gap）。
       100dvhが極端に低い場合に負値になり得るので
       max(0px, …) でクランプする（実機に存在しない高さでも計算式が破綻しないため）。

     d026f18で導入した --pm-sp-img-w（高さから画像幅を逆算する変数）は
     「窓＝画像」モデル専用の値だったため、この修正で不要になり削除した。
     横向き（667×375, 736×414）で画像が画面外やパネルの裏に出ない、というd026f18の
     成果自体は、--pm-sp-viewport-h が画面高に応じて縮み、ProfileZoomが
     高さ基準で画像をフィットさせる（窓が横長になるほど画像は高さ制限を受け、
     左右にレターボックスができる）ことでそのまま維持される。 */
  .pm-modal {
    --pm-sp-viewport-top: 44px;
    --pm-sp-panel-h: 125px;
    --pm-sp-panel-top: calc(100dvh - var(--pm-sp-panel-h));
    --pm-sp-gap: 4px;
    --pm-sp-viewport-h: max(0px, calc(var(--pm-sp-panel-top) - var(--pm-sp-viewport-top) - var(--pm-sp-gap)));
  }

  .pm-viewport {
    top: var(--pm-sp-viewport-top);
    left: 12px;
    width: calc(100% - 24px);
    height: var(--pm-sp-viewport-h);
    aspect-ratio: auto;
    max-width: none;
    transform: none;
  }

  /* PCの左右矢印は隠し、下部パネル内のラベル付きボタンを使う（設計書 §10.4） */
  .pm-prev,
  .pm-next {
    display: none;
  }

  .pm-panel {
    height: var(--pm-sp-panel-h);
    /* Figma実測（ノード2776-22224/22259/22294）: bg-[rgba(103,103,103,0.9)]
       拡大時（2776-22259）も同じ値で、画像が半透明パネルを透けて見える */
    background: rgba(103, 103, 103, .9);
  }

  .pm-nav {
    position: absolute;
    top: 8px;
    left: 50%;
    display: flex;
    gap: 24px;
    transform: translateX(-50%);
  }

  .pm-nav button {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 142px;
    height: 57px;
    padding: 0;
    border: none;
    cursor: pointer;
    /* Figma実測（ノード2776-22224 Frame 690）: ブラック（#33363B）地のピル形。
       角丸は高さの半分（28.5px）でスタジアム型にする。文字は白・14px・太字。 */
    border-radius: 28.5px;
    background: #33363b;
    color: #fff;
    font-size: 14px;
    font-weight: 700;
  }

  /* ピルの端に重なる丸アイコン（白円+黒矢印）。PCの矢印と同一アセットを共用し、
     「次の選手」側だけ水平反転する（アセット自体は常に左向きで書き出されるため）。
     アイコン分だけテキスト側にpaddingを入れ、残りの幅の中でテキストを中央寄せする。 */
  .pm-nav button::before {
    content: "";
    position: absolute;
    top: 0;
    width: 57px;
    height: 57px;
    background: url(../img/icon_modal_arrow_prev.svg) no-repeat center / contain;
  }

  /* 詳細度は「.pm-nav 」を付けてクラス2個にし、上の「.pm-nav button」
     （クラス1+要素1）より優先させる（PCコントロールと同じ理由。実機検証で必須と判明）。 */
  .pm-nav .pm-prev-sp {
    padding-left: 57px;
  }

  .pm-prev-sp::before {
    left: 0;
  }

  .pm-nav .pm-next-sp {
    padding-right: 57px;
  }

  .pm-next-sp::before {
    right: 0;
    transform: scaleX(-1);
  }

  .pm-nav button:disabled {
    opacity: .35;
    cursor: default;
  }

  .pm-actions {
    bottom: 8px;
    gap: 12px;
  }

  .pm-back,
  .pm-detail {
    width: 160px;
    height: 44px;
    /* Figma実測（ノード2776-22224 SP_button）:
       border-[1.265px] border-white border-solid / rounded-[4px] / text-[14px] */
    border: 1.265px solid #fff;
    border-radius: 4px;
    font-size: 14px;
  }

  .pm-modal.is-fullscreen .pm-viewport {
    top: var(--pm-sp-viewport-top);
    left: 0;
    width: 100%;
    height: calc(100% - var(--pm-sp-viewport-top));
  }

  .pm-spinner {
    width: 36px;
    height: 36px;
    border-width: 4px;
  }
}
