<?php
declare(strict_types=1);
require_once __DIR__ . '/_bootstrap.php';
require_login();

$frames    = frame_all();
$active     = active_frame_key();
$frameType  = frame_mainvisual_type($frames[$active] ?? []);
$isVideo    = ($frameType === 'video');
$isSlideshow = ($frameType === 'slideshow');
// frame.json の "mainvisual_count"（既定1）＝静止画タイプで使う画像の枚数。2枚組・3枚組レイアウトのフレーム用。
$mvCount    = frame_mainvisual_count($frames[$active] ?? []);
// テキスト・ボタンの入力を「1枚目だけ」にするか。2つのケースで真になる：
//  ①スライドショー＋ frame.json "mainvisual_shared_text": true（全スライド共通の1メッセージ型・例lp4）
//  ②静止画の複数枚（mainvisual_count>1）… 静止画のテキストは常に slides[0] の1セットしか使わないので、
//    2枚目以降に入力欄を出すと「入れても出ない欄」になり混乱するため。
// ※隠すだけで値は hidden 温存（下の mv_text_inputs の $hideText 経路）。
$sharedText = ($isSlideshow && !empty($frames[$active]['mainvisual_shared_text'])) || (!$isSlideshow && $mvCount > 1);
$alignLock  = !empty($frames[$active]['mainvisual_align_lock']); // frame.json で位置固定＝「テキストの位置」プルダウンを隠す
$textHide   = !empty($frames[$active]['mainvisual_text_hide']);   // frame.json でメイン画像のテキスト・ボタン入力欄を丸ごと隠す（ロゴ中央配置型など）
$noSp       = !empty($frames[$active]['mainvisual_no_sp']);       // frame.json でスマホ用画像/動画の入力欄を隠す（PC画像が小さい等でSP版を使わないフレーム）
$btnHide    = !empty($frames[$active]['mainvisual_no_button']);   // frame.json でメイン画像上のボタン入力欄だけ隠す（テキストは出す）
$sizeSelect = !empty($frames[$active]['mainvisual_size_select']); // frame.json で「文字サイズ（大中小）」プルダウンを出す（対応フレームのみtrue。既定=非表示）

/* ============================================================
 *  保存
 * ============================================================ */
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    require_post_csrf();
    $mv = setting_get_json('mainvisual');
    // 保存前に、いま mainvisual が参照しているファイル名を控えておく（差し替え・削除の掃除用）。
    // 保存後にこれを cms_cleanup_files_if_unused() に渡すと、
    // 「今回の保存で使われなくなり、かつ他のどこからも参照されていない」ものだけが物理削除される。
    // ※画面に出ていない温存スライドの画像は DB に残る＝参照ありと判定されるので消えない（安全）。
    $mvOldFiles = [];
    foreach (mainvisual_slides($mv) as $oldSlide) {
        if (!is_array($oldSlide)) continue;
        if (!empty($oldSlide['image']))    $mvOldFiles[] = (string)$oldSlide['image'];
        if (!empty($oldSlide['image_sp'])) $mvOldFiles[] = (string)$oldSlide['image_sp'];
    }
    if (!empty($mv['video']))    $mvOldFiles[] = (string)$mv['video'];
    if (!empty($mv['video_sp'])) $mvOldFiles[] = (string)$mv['video_sp'];
    $section = (string)($_POST['mv_section'] ?? '');

    if ($section === 'slides') {
        $slides = [];
        foreach ((array)($_POST['slides'] ?? []) as $idx => $row) {
            if (!is_array($row)) continue;
            $img = '';
            if (empty($row['del_image'])) {
                $img = resolve_image_value('slidefile_' . $idx, (string)($row['image'] ?? ''));
            }
            $imgSp = '';
            if (empty($row['del_image_sp'])) {
                $imgSp = resolve_image_value('slidefile_sp_' . $idx, (string)($row['image_sp'] ?? ''));
            }
            $catch = trim((string)($row['catch'] ?? ''));
            $sub   = trim((string)($row['sub'] ?? ''));
            $align = in_array(($row['align'] ?? ''), ['auto', 'left', 'center', 'right'], true) ? $row['align'] : 'auto';
            $b1t = trim((string)($row['btn1_text'] ?? '')); $b1u = trim((string)($row['btn1_url'] ?? ''));
            $b2t = trim((string)($row['btn2_text'] ?? '')); $b2u = trim((string)($row['btn2_url'] ?? ''));
            $b1s = mv_btn_style_in($row['btn1_style'] ?? '', 'fill');
            $b2s = mv_btn_style_in($row['btn2_style'] ?? '', 'inverse');
            $tcv = in_array(($row['text_color'] ?? ''), ['light', 'dark'], true) ? $row['text_color'] : '';
            $tsv = in_array(($row['text_size'] ?? ''), ['lg', 'md', 'sm'], true) ? $row['text_size'] : 'md';
            if ($img === '' && $catch === '' && $sub === '' && $b1t === '' && $b2t === '') continue;
            $slides[] = [
                'image' => $img, 'image_sp' => $imgSp, 'catch' => $catch, 'sub' => $sub, 'align' => $align,
                'text_color' => $tcv, 'text_size' => $tsv,
                'btn1_text' => $b1t, 'btn1_url' => $b1u, 'btn1_style' => $b1s,
                'btn2_text' => $b2t, 'btn2_url' => $b2u, 'btn2_style' => $b2s,
            ];
        }
        // 画面に出ていないスライドは消さずに温存する（着せ替えCMSの「消さない」原則）。
        // 例：スライドショーで5枚入れた人が「静止画2枚組」のフレームに切り替えて保存しても、
        //     3〜5枚目は裏で保持され、スライドショーに戻せば復活する。
        // ※従来は送信された分で丸ごと置き換えていたため、静止画フレームで保存すると2枚目以降が消えていた。
        // ※スライドショーは全スライドが画面に出ている＝「↓削除」で減らせるのが正なので温存しない
        //   （温存すると削除した最後の1枚が復活してしまう）。静止画タイプのときだけ温存する。
        if (!$isSlideshow) {
            $postedCount = count((array)($_POST['slides'] ?? []));
            foreach (array_slice(mainvisual_slides($mv), $postedCount) as $keep) {
                if (is_array($keep)) $slides[] = $keep;
            }
        }
        $mv['slides'] = $slides;
    } elseif ($section === 'video') {
        if (!empty($_POST['del_video'])) {
            $mv['video'] = '';
        } else {
            $mv['video'] = resolve_image_value('mv_video', (string)($mv['video'] ?? ''));
        }
        // スマホ用動画（任意）。未設定ならパソコン用動画を使う
        if (!empty($_POST['del_video_sp'])) {
            $mv['video_sp'] = '';
        } else {
            $mv['video_sp'] = resolve_image_value('mv_video_sp', (string)($mv['video_sp'] ?? ''));
        }
        $align = in_array(($_POST['valign'] ?? ''), ['auto', 'left', 'center', 'right'], true) ? $_POST['valign'] : 'auto';
        // テキストは slides[0] に保存＝静止画/スライドと共通（フレームを替えても引き継ぐ）
        $slides = mainvisual_slides($mv);
        $first  = (isset($slides[0]) && is_array($slides[0])) ? $slides[0] : [];
        $first['catch']      = trim((string)($_POST['vcatch'] ?? ''));
        $first['sub']        = trim((string)($_POST['vsub'] ?? ''));
        $first['align']      = $align;
        $first['text_color'] = in_array(($_POST['vtext_color'] ?? ''), ['light', 'dark'], true) ? $_POST['vtext_color'] : '';
        $first['text_size']  = in_array(($_POST['vtext_size'] ?? ''), ['lg', 'md', 'sm'], true) ? $_POST['vtext_size'] : 'md';
        $first['btn1_text']  = trim((string)($_POST['vbtn1_text'] ?? ''));
        $first['btn1_url']   = trim((string)($_POST['vbtn1_url'] ?? ''));
        $first['btn1_style'] = mv_btn_style_in($_POST['vbtn1_style'] ?? '', 'fill');
        $first['btn2_text']  = trim((string)($_POST['vbtn2_text'] ?? ''));
        $first['btn2_url']   = trim((string)($_POST['vbtn2_url'] ?? ''));
        $first['btn2_style'] = mv_btn_style_in($_POST['vbtn2_style'] ?? '', 'inverse');
        $slides[0] = $first;
        $mv['slides'] = array_values($slides);
        unset($mv['video_text']); // 旧バケツは廃止（テキストは slides に一本化）
    }
    // 旧形式キーは掃除（移行後）
    foreach (['images', 'catch', 'sub', 'align', 'btn1_text', 'btn1_url', 'btn2_text', 'btn2_url'] as $k) unset($mv[$k]);
    setting_set('mainvisual', json_encode($mv, JSON_UNESCAPED_UNICODE));
    // 差し替え・削除で未参照になった画像／動画を物理削除（uploads に残さない）。
    // 他の管理画面（サイト基本設定・パーツ・一覧記事など）と同じ作法。
    cms_cleanup_files_if_unused($mvOldFiles);
    flash_set('メイン画像を保存しました。');
    redirect('/admin/mainimg.php');
}

/* ============================================================
 *  入力部品
 * ============================================================ */
/** ボタンスタイルの入力値を正規化（fill / inverse のみ。未指定は既定） */
function mv_btn_style_in($v, string $default): string {
    $v = (string)$v;
    return in_array($v, ['fill', 'inverse'], true) ? $v : $default;
}

/** ボタンのスタイル選択 <select> */
function mv_btn_style_select(string $nm, string $cur): string {
    $cur = $cur === '' ? '' : $cur;
    $opts = '';
    foreach (['fill' => '塗りつぶし', 'inverse' => '枠線'] as $v => $lbl) {
        $opts .= '<option value="' . $v . '"' . ($cur === $v ? ' selected' : '') . '>' . h($lbl) . '</option>';
    }
    return '<div class="fld"><label class="fld-label">スタイル</label><select name="' . h($nm) . '">' . $opts . '</select></div>';
}

/** 開閉ブロック（見出し＋中身）。中身は既定で閉じる */
function mv_collapse(string $title, string $body): string {
    return '<div class="adm-block is-collapsed">'
      . '<div class="adm-block-head"><button type="button" class="adm-block-label" data-block-toggle aria-expanded="false">'
      . '<span class="block-chevron" aria-hidden="true">▶</span>' . h($title) . '</button></div>'
      . '<div class="adm-block-body">' . $body . '</div></div>';
}

/** テキスト＋ボタン入力（開閉式の2ブロックで返す。$np=name接頭辞 例 "slides[0]" / "v"） */
function mv_text_inputs(string $np, bool $bracket, array $d, bool $hideAlign = false, bool $hideText = false, bool $hideButton = false, bool $showSize = false): string {
    $name = fn(string $k) => $bracket ? $np . '[' . $k . ']' : $np . $k;
    $align = (string)($d['align'] ?? 'auto');
    if (!in_array($align, ['auto', 'left', 'center', 'right'], true)) $align = 'auto';
    $opts = '';
    foreach (['auto' => 'おまかせ（フレーム標準）', 'left' => '左', 'center' => '中央', 'right' => '右'] as $v => $lbl) {
        $opts .= '<option value="' . $v . '"' . ($align === $v ? ' selected' : '') . '>' . h($lbl) . '</option>';
    }
    // 文字色（スライド別）
    $tc = (string)($d['text_color'] ?? '');
    $tcOpts = '';
    foreach (['' => '標準（フレームのまま）', 'light' => '白文字（暗い画像向け）', 'dark' => '濃い文字（明るい画像向け）'] as $v => $lbl) {
        $tcOpts .= '<option value="' . $v . '"' . ($tc === $v ? ' selected' : '') . '>' . h($lbl) . '</option>';
    }
    // 文字サイズ（大中小・既定=中）
    $ts = (string)($d['text_size'] ?? 'md');
    if (!in_array($ts, ['lg', 'md', 'sm'], true)) $ts = 'md';
    $tsOpts = '';
    foreach (['lg' => '大', 'md' => '中', 'sm' => '小'] as $v => $lbl) {
        $tsOpts .= '<option value="' . $v . '"' . ($ts === $v ? ' selected' : '') . '>' . h($lbl) . '</option>';
    }
    $b1s = (string)($d['btn1_style'] ?? 'fill');
    $b2s = (string)($d['btn2_style'] ?? 'inverse');

    $textBody = ''
      . '<div class="fld"><label class="fld-label">キャッチコピー（改行OK）</label>'
      . '<textarea name="' . h($name('catch')) . '" rows="2">' . h((string)($d['catch'] ?? '')) . '</textarea></div>'
      . '<div class="fld"><label class="fld-label">サブテキスト（改行OK）</label>'
      . '<p class="adm-note" style="margin:.2rem 0 .4rem;">小さな端末では非表示になる場合があります。</p>'
      . '<textarea name="' . h($name('sub')) . '" rows="2">' . h((string)($d['sub'] ?? '')) . '</textarea></div>'
      . ($hideAlign
          ? ('<div class="fld"><label class="fld-label">文字色（画像に重なって読みづらい時）</label>'
            . '<select name="' . h($name('text_color')) . '">' . $tcOpts . '</select></div>')
          : ('<div class="cols2-admin">'
            . '<div class="fld"><label class="fld-label">テキストの位置</label>'
            . '<select name="' . h($name('align')) . '">' . $opts . '</select></div>'
            . '<div class="fld"><label class="fld-label">文字色（画像に重なって読みづらい時）</label>'
            . '<select name="' . h($name('text_color')) . '">' . $tcOpts . '</select></div>'
            . '</div>'))
      . ($showSize
          ? ('<div class="fld"><label class="fld-label">文字サイズ</label>'
            . '<select name="' . h($name('text_size')) . '">' . $tsOpts . '</select></div>')
          : ('<input type="hidden" name="' . h($name('text_size')) . '" value="' . h($ts) . '">')); // 非対応フレームは値だけ温存

    $btnBody = '<div class="cols3-admin">'
      . '<div class="fld"><label class="fld-label">ボタン1の文字</label><input type="text" name="' . h($name('btn1_text')) . '" placeholder="例：詳しく見る" value="' . h((string)($d['btn1_text'] ?? '')) . '"></div>'
      . '<div class="fld"><label class="fld-label">ボタン1のリンク先</label><input type="text" name="' . h($name('btn1_url')) . '" placeholder="service または https://..." value="' . h((string)($d['btn1_url'] ?? '')) . '"></div>'
      . mv_btn_style_select($name('btn1_style'), $b1s)
      . '<div class="fld"><label class="fld-label">ボタン2の文字</label><input type="text" name="' . h($name('btn2_text')) . '" value="' . h((string)($d['btn2_text'] ?? '')) . '"></div>'
      . '<div class="fld"><label class="fld-label">ボタン2のリンク先</label><input type="text" name="' . h($name('btn2_url')) . '" value="' . h((string)($d['btn2_url'] ?? '')) . '"></div>'
      . mv_btn_style_select($name('btn2_style'), $b2s)
      . '</div>';

    // 隠す項目は「消さずに hidden で温存」する。ボタン無し/テキスト無しのフレームで保存しても
    // 値が消えず、ボタン有り/テキスト有りのフレームに戻したときに復活する（SP画像の温存と同じ方針）。
    $hid = fn(string $k, string $v) => '<input type="hidden" name="' . h($name($k)) . '" value="' . h($v) . '">';
    $btnHiddens =
          $hid('btn1_text', (string)($d['btn1_text'] ?? '')) . $hid('btn1_url', (string)($d['btn1_url'] ?? '')) . $hid('btn1_style', $b1s)
        . $hid('btn2_text', (string)($d['btn2_text'] ?? '')) . $hid('btn2_url', (string)($d['btn2_url'] ?? '')) . $hid('btn2_style', $b2s);

    if ($hideText) {
        // mainvisual_text_hide：テキストもボタンも欄を出さないが、全ての値を hidden で温存する。
        return $hid('catch', (string)($d['catch'] ?? '')) . $hid('sub', (string)($d['sub'] ?? ''))
             . $hid('align', $align) . $hid('text_color', $tc) . $hid('text_size', $ts) . $btnHiddens;
    }

    return mv_collapse('メイン画像上のテキスト', $textBody)
         . ($hideButton ? $btnHiddens : mv_collapse('メイン画像上のボタン', $btnBody));
}

$mv     = setting_get_json('mainvisual');
$slides = mainvisual_slides($mv);
$video   = (string)($mv['video'] ?? '');
$videoSp = (string)($mv['video_sp'] ?? '');
// 動画のテキスト欄は slides[0] と共通（空なら旧 video_text を後方互換で表示）
$vtext   = mv_primary_text($mv, $slides);

// フレーム同梱フォールバック（未設定の間サイトに出る画像/動画）を管理画面でも「初期素材」として見せる
$fbImages = frame_default_mainimages($active, $frameType, $mvCount);
$fbVideo  = frame_default_video($active);
$hasCustomerImages = (bool) array_filter($slides, fn($s) => !empty($s['image']));

admin_header('メイン画像', 'mainimg');
?>
<h1 class="adm-h1">メイン画像（トップページ）</h1>
<p class="adm-note">使用中フレーム「<?= h($frames[$active]['name'] ?? $active) ?>」は <strong><?= h(['static' => '静止画', 'slideshow' => 'スライドショー', 'video' => '動画'][$frameType] ?? '静止画') ?></strong>タイプです。<a href="<?= h(url('/')) ?>" target="_blank" rel="noopener">サイトを表示 ↗</a></p>
<p class="adm-note" style="font-size:.84rem;"><?= h(cms_upload_formats_note()) ?></p>
<?php flash_render(); ?>

<?php if ($isVideo): ?>
  <!-- 動画タイプ -->
  <?php if ($video === '' && $fbVideo): ?>
    <p class="adm-note" style="background:#fffbeb;border:1px solid #fde68a;">動画が未設定のため、いまサイトには<b>このフレーム標準の動画</b>が表示されています。自分の動画に変えるには下でアップしてください（アップすると差し替わります）。</p>
  <?php endif; ?>
  <form method="post" enctype="multipart/form-data" class="adm-form">
    <input type="hidden" name="_csrf" value="<?= h(csrf_token()) ?>">
    <input type="hidden" name="mv_section" value="video">
    <div class="adm-block">
      <div class="adm-block-head"><span class="adm-block-label">動画</span></div>
      <div class="fld">
        <label class="fld-label">動画ファイル（パソコン用・mp4）</label>
        <?php if ($video !== ''): ?>
          <video class="fld-thumb big" src="<?= h(upload_url($video)) ?>" muted controls></video>
          <label class="fld-check"><input type="checkbox" name="del_video" value="1"> 動画を削除する</label>
        <?php elseif (!empty($fbVideo['video_url'])): ?>
          <video class="fld-thumb big" style="opacity:.6" src="<?= h($fbVideo['video_url']) ?>" muted controls></video>
          <span class="fld-current">初期素材（フレーム標準）。アップすると差し替わります</span>
        <?php endif; ?>
        <input type="file" name="mv_video" accept="video/mp4">
      </div>
      <?php if (!$noSp): ?>
      <div class="fld">
        <label class="fld-label">スマホ用動画（任意・mp4）</label>
        <p class="adm-note" style="margin:.2rem 0 .5rem;">縦長や軽いサイズの動画を入れると、スマホ表示でこちらが使われます。未設定ならパソコン用動画をそのまま使います。</p>
        <?php if ($videoSp !== ''): ?>
          <video class="fld-thumb big" src="<?= h(upload_url($videoSp)) ?>" muted controls></video>
          <label class="fld-check"><input type="checkbox" name="del_video_sp" value="1"> スマホ用動画を削除する</label>
        <?php endif; ?>
        <input type="file" name="mv_video_sp" accept="video/mp4">
      </div>
      <?php endif; ?>
      <?= mv_text_inputs('v', false, $vtext, $alignLock, $textHide, $btnHide, $sizeSelect) ?>
    </div>
    <button class="adm-btn primary" type="submit">保存</button>
  </form>

<?php else: ?>
  <!-- 静止画／スライドショー -->
  <p class="adm-note"><?php
    if ($textHide) {
        echo 'このフレームはメイン画像に<b>画像のみ</b>を表示します。テキスト・ボタンは使いません。';
    } else {
        if (!$isSlideshow)      echo $mvCount > 1 ? ('このフレームは静止画を' . $mvCount . '枚まとめて表示します。並べ方はフレームのデザインで決まっています。テキスト・ボタンは1枚目だけ入力できます（2枚目以降は画像のみ）。') : '静止画タイプなので1枚だけ使います。';
        elseif ($sharedText)   echo 'このフレームは全スライドに共通の1メッセージを表示します。テキスト・ボタンは1枚目だけ入力できます（2枚目以降は画像のみ）。';
        else                   echo 'スライドは上から順に表示されます。各スライドにテキストを入れられます。';
        echo ' ボタン・テキストは未入力なら表示されません。';
    }
  ?></p>
  <?php if (!$hasCustomerImages && $fbImages): ?>
    <p class="adm-note" style="background:#fffbeb;border:1px solid #fde68a;">画像が未設定のため、いまサイトには<b>このフレーム標準のメイン画像（<?= count($fbImages) ?>枚）</b>が表示されています（下に薄く表示）。自分の画像に変えるには各枠でアップしてください。<b>1枚でもアップして保存すると、フレーム標準はオフになり、アップした分だけが表示されます（全部入れ替えがおすすめ）。</b></p>
  <?php endif; ?>
  <form method="post" enctype="multipart/form-data" class="adm-form">
    <input type="hidden" name="_csrf" value="<?= h(csrf_token()) ?>">
    <input type="hidden" name="mv_section" value="slides">
    <div class="rep" data-rep>
      <div class="rep-rows" data-rep-rows>
        <?php
        if ($isSlideshow) {
            if ($hasCustomerImages) {
                $showSlides = $slides;                    // お客さんのスライドを表示
            } else {
                // 未設定：フレーム標準の枚数ぶん枠を開く（テキストは slides[k] を引き継ぎ）
                $cnt = max(count($fbImages), 1);
                $showSlides = [];
                for ($k = 0; $k < $cnt; $k++) $showSlides[$k] = $slides[$k] ?? [];
            }
        } else {
            // 静止画：frame.json の mainvisual_count 枚ぶん枠を出す（既定1＝従来どおり）。
            // 足りない分は空枠。超える分は画面に出さないが、保存時に温存される（上の保存処理）。
            $showSlides = [];
            for ($k = 0; $k < $mvCount; $k++) $showSlides[$k] = $slides[$k] ?? [];
        }
        if (!$showSlides) $showSlides = [[]]; // 空が1つ
        foreach ($showSlides as $i => $s):
        ?>
          <div class="rep-row mv-slide" data-rep-row>
            <div class="adm-block-head">
              <span class="adm-block-label"><?= $isSlideshow ? 'スライド' : ('メイン画像' . ($mvCount > 1 ? (string)($i + 1) : '')) ?></span>
              <?php if ($isSlideshow): ?>
              <span class="adm-block-tools">
                <button type="button" class="adm-btn ghost sm" data-rep-up>↑</button>
                <button type="button" class="adm-btn ghost sm" data-rep-down>↓</button>
                <button type="button" class="adm-btn danger sm" data-rep-del>削除</button>
              </span>
              <?php endif; ?>
            </div>
            <div class="fld"><label class="fld-label">画像（パソコン用）</label>
              <?php if (!empty($s['image'])): ?>
                <img class="fld-thumb" src="<?= h(upload_url((string)$s['image'])) ?>" alt="">
                <label class="fld-check"><input type="checkbox" name="slides[<?= $i ?>][del_image]" value="1"> 画像を削除</label>
              <?php elseif (!$hasCustomerImages && !empty($fbImages[$i]['image_url'])): ?>
                <img class="fld-thumb" style="opacity:.55" src="<?= h($fbImages[$i]['image_url']) ?>" alt="">
                <span class="fld-current">初期素材（フレーム標準）。アップすると差し替わります</span>
              <?php endif; ?>
              <input type="hidden" name="slides[<?= $i ?>][image]" value="<?= h((string)($s['image'] ?? '')) ?>">
              <input type="file" name="slidefile_<?= $i ?>" accept="image/*">
            </div>
            <?php if (!$noSp): ?>
            <div class="fld"><label class="fld-label">スマホ用画像（任意）</label>
              <p class="adm-note" style="margin:.2rem 0 .5rem;">縦長や小さめの画像を入れると、スマホ表示でこちらが使われます。未設定ならパソコン用画像をそのまま使います。</p>
              <?php if (!empty($s['image_sp'])): ?>
                <img class="fld-thumb" src="<?= h(upload_url((string)$s['image_sp'])) ?>" alt="">
                <label class="fld-check"><input type="checkbox" name="slides[<?= $i ?>][del_image_sp]" value="1"> スマホ用画像を削除</label>
              <?php endif; ?>
              <input type="hidden" name="slides[<?= $i ?>][image_sp]" value="<?= h((string)($s['image_sp'] ?? '')) ?>">
              <input type="file" name="slidefile_sp_<?= $i ?>" accept="image/*">
            </div>
            <?php else: /* SP欄は隠すが、既存のスマホ用画像値は保存時に消えないよう hidden で温存 */ ?>
            <input type="hidden" name="slides[<?= $i ?>][image_sp]" value="<?= h((string)($s['image_sp'] ?? '')) ?>">
            <?php endif; ?>
            <?php // 2枚目以降のテキスト・ボタンを隠すケース（共通テキスト型スライドショー／静止画の複数枚）。
                  // 入力欄を出さないだけで全項目 hidden で温存する（$hideText=true の経路）＝保存しても値が消えない ?>
            <?= mv_text_inputs('slides[' . $i . ']', true, $s, $alignLock, ($textHide || ($sharedText && $i > 0)), $btnHide, $sizeSelect) ?>
          </div>
        <?php endforeach; ?>
      </div>
      <?php if ($isSlideshow): ?>
        <button type="button" class="adm-btn ghost" data-rep-add>＋ スライドを追加</button>
        <template data-rep-tpl>
          <div class="rep-row mv-slide" data-rep-row>
            <div class="adm-block-head">
              <span class="adm-block-label">スライド</span>
              <span class="adm-block-tools">
                <button type="button" class="adm-btn ghost sm" data-rep-up>↑</button>
                <button type="button" class="adm-btn ghost sm" data-rep-down>↓</button>
                <button type="button" class="adm-btn danger sm" data-rep-del>削除</button>
              </span>
            </div>
            <div class="fld"><label class="fld-label">画像（パソコン用）</label>
              <input type="hidden" name="slides[__IDX__][image]" value="">
              <input type="file" name="slidefile___IDX__" accept="image/*">
            </div>
            <?php if (!$noSp): ?>
            <div class="fld"><label class="fld-label">スマホ用画像（任意）</label>
              <p class="adm-note" style="margin:.2rem 0 .5rem;">未設定ならパソコン用画像を使います。</p>
              <input type="hidden" name="slides[__IDX__][image_sp]" value="">
              <input type="file" name="slidefile_sp___IDX__" accept="image/*">
            </div>
            <?php endif; ?>
            <?php if (!$sharedText): // 共通テキストフレームでは追加スライドにテキスト欄を出さない ?>
            <?= mv_text_inputs('slides[__IDX__]', true, [], $alignLock, $textHide, $btnHide, $sizeSelect) ?>
            <?php endif; ?>
          </div>
        </template>
      <?php endif; ?>
    </div>
    <button class="adm-btn primary" type="submit">保存</button>
  </form>
<?php endif; ?>

<?php admin_footer(); ?>
