/* ══════════════════════════════════════════════════════════════════════════
   admin/mobile.css — `/admin` のスマートフォン対応（≦767px）
   仕様: docs/admin-mobile-spec.md

   方針:
   - スマホ用の**別 UI を作らない**。同一 DOM・同一 JS を CSS で出し分ける。
     真実源の二重化は本プロジェクトが繰り返し事故を起こしている領域（CLAUDE.md
     「既知のリスク領域」8）なので、構造を分岐させない。
   - 既存 CSS の細かいブレークポイント（480/600/640/700/720/900/1023/1100）は
     **消さない**。消すと PC・タブレット側の回帰面積が広がる。ここは 767px 以下で
     上書きするだけに留める。
   - **生 hex 禁止**（check:redesign-tokens が pre-commit / CI で強制）。
     色は既存トークン（--text / --accent / --border / --bg-card 等）のみ。

   数値の根拠はすべて実測（docs/admin-mobile-spec.md §3）。見た目の好みではない。
   ══════════════════════════════════════════════════════════════════════════ */

/* 編集⇄プレビューの切替はスマホ幅でしか存在しない。既定は非表示（メディアクエリの
   外に置くこと。中だけで display:flex を指定すると PC で div の既定 block が出る）。 */
.mobile-mode { display: none; }

/* スマホ判定は「幅 767px 以下」または「横向きで高さ 480px 以下」。
   後者を入れないと、スマホを横に倒した瞬間（例 844×390）にすべての指定が外れて
   PC 用レイアウトに戻る。実測でもタップ44未満が 26 個復活していた。 */
@media (max-width: 767px), (max-height: 480px) and (orientation: landscape) {

  /* ── 1. 上部の固定要素は「1つだけ」にする ────────────────────────────
     実測（390×844）では admin-topbar(h140) / sections-nav(h45) / form-toolbar(h90)
     が **3つとも top:0 に sticky で積まれ、重なっていた**。z-index は 100 > 30 > 5
     なので、クイック移動と検索ツールバーはトップバーの裏に隠れて操作できない。
     上に残すのはトップバーだけにし、他は通常フローへ戻す。 */
  .sections-nav,
  .form-toolbar {
    position: static;
  }

  /* トップバーを1段（52px）に収める。実測 140px は brand＋メールアドレス＋
     ビルド状態バッジが3行に折り返していたため。狭幅では装飾・参考情報を落とす。
     ⋯（ログアウト／パスワード変更の唯一の入口）と ←ページ一覧は必ず残す。 */
  .admin-topbar {
    flex-wrap: nowrap;
    gap: 8px;
    padding-left: 10px;
    padding-right: 10px;
  }
  .admin-topbar .admin-brand,
  .admin-topbar .user-email {
    display: none;
  }
  /* トップバーで唯一「縮んでよい」のがビルド状態バッジ。flex-basis を 0 にして
     ここだけを可変にする（auto のままだと本文幅を主張して行が 433px へ伸び、
     モバイルでは**レイアウトビューポートごと広がって全画面に横スクロールが出る**）。 */
  .admin-topbar .build-health {
    flex: 1 1 0;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  /* help.js が「使い方」ボタンを .user-area へ後から挿し込む。redesign.css の
     flex-wrap:wrap のままだと 390px で2段に折れ、トップバーが 113px になっていた
     （実測）。ここは折り返さず、縮むのはビルド状態バッジ側に任せる。 */
  .admin-topbar .user-area {
    flex-wrap: nowrap;
    gap: 6px;
    /* 「⋯」はログアウト等の唯一の入口なので絶対に押し出させない。縮むのは現在地表示
       （.topbar-context・ellipsis）とビルド状態バッジ側。実測（320px）で現在地を足した際に
       user-area が 110→60px に潰れ、⋯が画面外 360px へ出てレイアウトビューポートごと広がった。 */
    flex-shrink: 0;
  }
  /* 現在地「編集中: ◯◯」は狭幅では真っ先に縮む（min-width:0 は redesign.css 側）。 */
  .admin-topbar .topbar-context {
    flex: 1 1 0;
  }

  /* ── 2. コンテンツ種別タブ: 横スクロールをやめて折り返す ──────────────
     実測 scrollWidth 633 / clientWidth 350 で「⚙ 設定」が right=652.9px（画面外）。
     横スクロールできることを示す手掛かりが無く、到達できない項目が生まれていた。
     このタブ列は sticky ではないので、折り返して縦に伸びても占有し続けない。 */
  .tabs {
    flex-wrap: wrap;
    overflow-x: visible;
    gap: 2px;
  }
  .tabs .tab-btn {
    flex: 1 1 auto;
    min-height: 44px;
    padding: 10px 12px;
  }

  /* ── 3. 編集 ⇄ プレビューの切替（中核）─────────────────────────────
     狭幅では .admin-main--split が1カラムに落ち、プレビューがフォームの下へ積まれる。
     実測ではプレビュー開始位置が **6,889px**（画面8.2枚ぶん下）で、フォームと
     プレビューが同時に画面へ出ない。これは不便なのではなく、
     「左のこの項目＝右のここ」を示す双方向ハイライト（CLAUDE.md 既知のリスク領域12）
     が成立しなくなる＝機能が死ぬ。縦積みをやめ、排他表示にする。

     ★ DOM は絶対に消さない。保存は readFormData() が [data-path] を走査して
       JSON を再構築する契約なので、非表示側を remove()/innerHTML="" で落とすと
       「画面に出ていない項目が公開でサイトから消える」（既知のリスク領域11と同型）。
       切替は display のみで行う。 */
  .mobile-mode {
    display: flex;
    gap: 6px;
    padding: 6px 10px;
    background: var(--bg-card);
    border-bottom: 1px solid var(--border);
    position: sticky;
    /* トップバーの直下に貼り付く。高さは JS が実測して --mobile-topbar-h に入れる。
       ここを固定値（旧コードの top:76px 等）にすると、トップバーが折り返した瞬間に
       裏へ潜る。既存コードが同じマジックナンバーで踏んだ轍を繰り返さない。 */
    top: var(--mobile-topbar-h, 52px);
    z-index: 90;
  }
  .mobile-mode__btn {
    flex: 1 1 0;
    min-height: 44px;
    padding: 8px 10px;
    font-family: inherit;
    font-size: 1rem;
    font-weight: 600;
    color: var(--text-muted);
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    cursor: pointer;
  }
  .mobile-mode__btn.is-active {
    color: var(--bg-card);
    background: var(--accent);
    border-color: var(--accent);
  }
  .mobile-mode__btn:focus-visible {
    outline: 3px solid var(--border-focus);
    outline-offset: -3px;
  }

  /* 編集モード（既定）: プレビュー列を畳む。 */
  body[data-mobile-pane="edit"] .preview-column { display: none; }

  /* プレビューモード: フォーム本体だけを畳み、保存バーは残す。
     #save-bar は .editor-column の**中**にあるため、列ごと display:none にすると
     プレビュー中に保存できなくなる。子だけを落として保存導線を維持する。 */
  body[data-mobile-pane="preview"] .editor-column > *:not(#save-bar) {
    display: none;
  }

  /* プレビュー列は通常フローのまま、高さだけ「画面の残り」に固定する。
     position:fixed は使わない。モバイルの fixed は**レイアウトビューポート**基準で、
     実測では包含ブロックが 1044px 高（画面 844px）にずれて top/bottom が意図どおりに
     効かなかった。高さを直接与えるほうが確実。
     横幅の暴走（実測 812px はみ出し）は preview.css の grid トラックを
     minmax(0,1fr) に直して根本で塞いだ（1fr は min-content=1180px まで伸びる）。 */
  body[data-mobile-pane="preview"] .preview-column {
    height: calc(100dvh
                 - var(--mobile-topbar-h, 52px)
                 - var(--mobile-mode-h, 44px)
                 - var(--mobile-savebar-h, 0px));
    min-height: 320px;
    max-height: none;
    min-width: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    /* 保存バー（同じ .editor-column 内）より前に出す。DOM 順では後ろにあるため。 */
    order: -1;
  }
  /* コンテンツ種別タブはプレビュー中に押しても見えないものを切り替えるだけなので隠す。
     これで .admin-main がモード切替バーの直下から始まり、プレビューが画面の残りに
     ぴったり収まる（隠さないとタブぶん下へ押し出され、下端が保存バーの裏に入る）。 */
  body[data-mobile-pane="preview"] .tabs,
  body[data-mobile-pane="preview"] div:has(> .tabs) { display: none; }
  body[data-mobile-pane="preview"] .admin-main { padding-top: 0; }

  /* 動的要素に関する長い注意書き（3行）はプレビュー本体を 100px 近く圧迫する。
     スマホでは畳む。内容は PC 幅で読める（幅が戻れば自動的に再表示される）。
     状態バッジ（編集中／公開済み）とクリック編集の案内は残す — 前者は「なぜ本番と
     違うのか」の答え、後者は**プレビューが編集の入口である**ことの唯一の告知。 */
  body[data-mobile-pane="preview"] .preview-static-note { display: none; }

  /* 列 → パネル → タブパネル → プレビュー枠 まで flex を通し、枠に残り全部を渡す。
     どこか1段でも途切れると枠が min-height(240px) のまま縮む。 */
  body[data-mobile-pane="preview"] .preview-panel,
  body[data-mobile-pane="preview"] .preview-tabpanel:not([hidden]) {
    flex: 1 1 auto;
    min-height: 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
  }
  body[data-mobile-pane="preview"] .preview-panel { overflow: hidden; }
  /* プレビュー枠は列の残り全部を使う（高さの固定値を置かない）。 */
  body[data-mobile-pane="preview"] .live-preview-mount {
    flex: 1 1 auto;
    height: auto;
    min-height: 240px;
    min-width: 0;
  }
  /* プレビュー中は .editor-column の中身が保存バーだけになる。グリッド行の順序を
     入れ替えてプレビューを上に置く（保存バーは sticky bottom のまま画面下に残る）。 */
  body[data-mobile-pane="preview"] .editor-column { order: 0; }

  /* ── 4. 保存バー: safe-area と高さ ────────────────────────────────
     実測 149px（3行に折り返し）。ホームインジケータ（iPhone）に重ならないよう
     env(safe-area-inset-bottom) を必ず加算する。0 のときは通常の余白のまま。 */
  #save-bar {
    padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px));
    gap: 8px;
    justify-content: stretch;
  }
  #save-bar .save-status {
    flex: 1 1 100%;
    min-width: 0;
  }
  #save-bar .save-actions {
    width: 100%;
    margin-left: 0;
    gap: 8px;
  }
  #save-bar .save-actions .btn {
    flex: 1 1 0;
    min-height: 48px;
  }

  /* トップへ戻るボタンは保存バーの上へ退避（重なると保存が押せない）。
     実測 39.6×39.6px だったので 44px も確保する。 */
  .back-to-top {
    width: 44px;
    height: 44px;
    min-width: 44px;
    min-height: 44px;
    /* 保存バーの実測高さぶん上へ逃がす（重なると「公開する」が押せない）。 */
    top: auto;
    bottom: calc(var(--mobile-savebar-h, 0px) + 12px);
  }

  /* トーストは保存バーの上に出す。既定の bottom:24px だと、保存直後に出る通知が
     保存バー（特に「公開する」）へ重なる（z-index 9999 でトースト側が必ず勝つ）。 */
  #toast-container {
    bottom: calc(var(--mobile-savebar-h, 0px) + 12px);
    left: 12px;
    right: 12px;
  }

  /* ハブ表示中は編集画面用の切替を出さない（押しても意味が無いため）。 */
  #editor-view.is-hub .mobile-mode { display: none; }

  /* ── 5. タップ領域 44px を「面」で満たす ─────────────────────────
     実測で 390px 幅の編集画面に 20 個、414px で 38 個の未達があった。個別 padding
     の積み増しではなく、共通クラスの基底値を上げて構造的に解消する。 */
  .btn,
  .btn-sm,
  .btn-outline,
  .btn-primary,
  .btn-danger,
  .btn-icon,
  .preview-tabs__btn,
  .viewport-toggle button,
  .split-preset button,
  .topbar-more__item,
  .page-card,
  .sections-nav__title,
  summary {
    min-height: 44px;
  }
  /* 幅方向が潰れやすいアイコンだけのボタン。 */
  .btn-icon,
  .viewport-toggle button,
  .split-preset button {
    min-width: 44px;
  }

  /* セクションカードの本体ボタンが幅 11.1px まで潰れていた（414px で実測）。
     min-width:0 ＋ flex:1 の組み合わせで、同じ行の他の要素に押し切られている。
     行を折り返して1本まるごと使わせる。 */
  .sec-card__open {
    flex: 1 1 100%;
    min-width: 44px;
  }

  /* 本文へスキップ（キーボード/スクリーンリーダ利用者の最初の操作）も 44px。 */
  .skip-link {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  /* チェックボックス／ラジオ本体を 44px に膨らませると見た目が壊れるので、
     入力は 24px にし、**ラベル全体**を 44px のタップ領域にする。 */
  input[type="checkbox"],
  input[type="radio"] {
    width: 24px;
    height: 24px;
    min-width: 24px;
    min-height: 24px;
  }
  label:has(> input[type="checkbox"]),
  label:has(> input[type="radio"]),
  .checkbox-label,
  .toggle-label {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 44px;
  }

  /* 「?」ヒント: 見た目は小さいまま、当たり判定だけ 44px へ広げる（実測 16×16）。 */
  /* 「?」ヒントは装飾的な補足で、44px の丸を描くと本文が読みにくくなる。
     実寸は WCAG 2.5.8(AA) の下限 24px まで広げ、当たり判定だけ ::after で 44px にする。 */
  /* help.js は実行時に <style> を注入する＝mobile.css より後ろに来るので、
     同じ詳細度では負ける。クラスを2回書いて 0,2,0 にして勝つ。 */
  .sh-hint.sh-hint {
    position: relative;
    width: 24px;
    height: 24px;
    flex: 0 0 24px;
    font-size: 13px;
  }
  .sh-hint::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }

  /* ── 6. iOS の入力ズーム防止 ─────────────────────────────────────
     16px 未満の入力へフォーカスすると iOS Safari はページ全体を自動ズームし、
     **元の倍率へ戻らない**。以降の操作がすべてずれるので例外を作らない。
     実測: .form-toolbar__search 14.4px / #scroll-sync-toggle 13.3px /
           .pv-zoom__select 13px。 */
  input,
  select,
  textarea,
  /* input[type="search"] は style.css で .9rem。属性セレクタは詳細度が
     クラス相当（0,1,1）で `.form-toolbar__search`（0,1,0）に勝つため、
     同じ形で書かないと上書きできない。 */
  input[type="search"],
  .form-toolbar__search,
  .pv-zoom__select {
    font-size: 16px;
  }
  /* 入力欄の高さも 44px（実測 40px）。チェック/ラジオは別途 24px 指定があるので除く。 */
  input:not([type="checkbox"]):not([type="radio"]),
  select,
  .form-toolbar__search {
    min-height: 44px;
  }
  /* select は 16px だと狭幅で溢れやすいので、高さで詰める（font-size は下げない）。 */
  select,
  .pv-zoom__select {
    min-height: 44px;
    padding: 8px 6px;
  }

  /* ── 7. ログイン画面 ────────────────────────────────────────────
     入口が押しにくいと何も始まらない。実測 268×34.4 / 268×20。 */
  #login-btn,
  #login-google-btn {
    min-height: 48px;
  }

  /* ── 8. コラム一覧: 1行 266px を詰める ──────────────────────────
     行内に操作が6個あり、縦に伸びて一覧性が失われていた。
     操作は既存の「⋯」に集約済みなので、ここでは行の詰めだけ行う。 */
  .cols-admin-item {
    padding: 8px 10px;
    gap: 8px;
  }
  .cols-admin-item__title {
    flex: 1 1 100%;
    min-width: 0;
  }

  /* ── 9. 写真の置き場所: 1列では一覧にならない ───────────────────
     実測はグリッド1列（362px）で、1枚ずつしか見えなかった。 */
  .ml-grid,
  .media-grid {
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 8px;
  }

  /* ── 10. 右ペイン見出しの操作群 ─────────────────────────────────
     プレビュー幅切替・分割プリセットは狭幅では意味が薄い。分割プリセットは
     **そもそも分割していない**ので隠す（押せるのに何も起きない操作を残さない）。 */
  /* 詳細度に注意: 素の `.split-preset` (0,1,0) は preview.css の `.admin-main--split .split-preset`
     (0,2,0) に、素の `.sync-toggle` は本ファイルの `label:has(> input[type="checkbox"])` (0,1,1) に
     負けて **一度も効いていなかった**（実測 computed=inline-flex）。親を付けて (0,2,0) にする。 */
  .pv-more__menu .split-preset { display: none; }
  /* スクロール同期は「左右が同時に見えている」ことが前提の機能。排他表示では
     同期する相手が画面に無いので、操作を残しても意味が無い。 */
  .pv-more__menu .sync-toggle { display: none; }
  /* プレビュー見出しが縦に伸びるとプレビュー本体の取り分が減る（実測で 453px を
     占有していた）。「タブ1行＋操作1行」の2行に固定する。
     タブ群を1行に押し込もうとすると幅 138px に潰れてボタンが3段に折れ、かえって
     高くなった（実測 130px）。行を分けたうえで3等分するのが正解。 */
  .preview-panel__head {
    flex-wrap: wrap;
    gap: 6px;
    padding: 6px 8px;
  }
  .preview-tabs {
    flex: 1 1 100%;
    display: flex;
    flex-wrap: nowrap;
  }
  .preview-tabs__btn {
    flex: 1 1 0;
    min-width: 0;
  }
  .preview-head-controls {
    flex-wrap: nowrap;
    gap: 6px;
    /* overflow-x:auto にしない。overflow-y も auto に昇格して高さ 46px のスクロールコンテナになり、
       「⋯」のポップオーバー（position:absolute）が枠外に描かれて中の操作が1つも押せなくなる
       （実測: elementFromPoint が倍率セレクトの位置で背後の要素を返した）。
       常時露出はビューポート切替3つ＋「⋯」だけなので 320px でも収まり、横スクロールは要らない。 */
    overflow: visible;
  }
  /* ポップオーバー内は縦積み（倍率セレクトだけが残る）。 */
  .pv-more__menu { min-width: 200px; }
  .pv-zoom__lab { display: none; }
}

/* ── 横向き（高さが極端に低い）────────────────────────────────────
   844×390 では上下の固定要素だけで 289px（74%）を占め、本文が 101px しか残らない。
   この向きではトップバーの固定を解除してスクロールで送り出す。保存バーは残す
   （保存導線を失うほうが害が大きい）。 */
@media (max-width: 950px) and (max-height: 480px) and (orientation: landscape) {
  /* トップバーはスクロールで送り出す（固定し続けるだけの縦幅が無い）。 */
  .admin-topbar { position: static; }
  .mobile-mode { top: 0; }

  /* 保存バーを1段に詰める。縦積み（状態1行＋ボタン1行＝145px）のままだと上下の固定要素で
     画面の 51.6% を占め、本文が 48.4% しか残らなかった（実測）。 */
  #save-bar {
    padding: 6px 10px calc(6px + env(safe-area-inset-bottom, 0px));
    flex-wrap: nowrap;
  }
  #save-bar .save-status { flex: 1 1 auto; }
  #save-bar .save-actions { width: auto; flex: 0 1 auto; margin-left: auto; }
  #save-bar .save-actions .btn { min-height: 44px; }

  /* トップバーが固定でなくなったぶん、プレビューの取り分を戻す。 */
  body[data-mobile-pane="preview"] .preview-column {
    height: calc(100dvh - var(--mobile-mode-h, 44px) - var(--mobile-savebar-h, 0px));
    min-height: 180px;
  }
  body[data-mobile-pane="preview"] .live-preview-mount { min-height: 140px; }

  /* 横向きは画面高が 390px しかなく、案内文2行（約50px）がプレビュー本体の 1/4 を食う。
     この向きでは畳む（縦向き・PC では出る）。状態バッジは残す。 */
  body[data-mobile-pane="preview"] .preview-cte-hint { display: none; }
  body[data-mobile-pane="preview"] .preview-state-badge { margin: 4px 8px; }

  /* 横向きは幅が 844px あるので、タブと操作群は同じ行に収まる。縦向き用の
     「タブだけで1行（flex-basis:100%）」を引きずると見出しが 109px になり、
     ただでさえ足りない縦を無駄に食う（実測: これだけでプレビューが 140px に潰れた）。 */
  .preview-panel__head { flex-wrap: nowrap; }
  .preview-tabs { flex: 0 1 auto; }
  .mobile-mode { padding: 3px 10px; }
}

/* 画面幅が広がったら（PC・タブレット）モバイル用の出し分けは一切効かせない。
   data-mobile-pane 属性はメディアクエリの外では参照しないので、属性が残っていても
   PC 表示は完全に元のまま（左右分割）になる。 */
