HTML/CSS/JavaScriptで作成した既存のWeb教材は、マニフェストファイル(imsmanifest.xml)の追加とSCORM APIの組み込みによって、LMSで配信・学習管理が可能なSCORM教材に変換できます。 この記事では、SCORM対応に必要な作業をステップバイステップで解説します。

1. SCORM対応とは何か

SCORM(Sharable Content Object Reference Model)対応とは、教材がLMS(学習管理システム)と正しくデータをやり取りできる状態にすることです。具体的には、以下の3つの要素が必要になります。

  • マニフェストファイル(imsmanifest.xml) — 教材の構成情報をLMSに伝えるXMLファイル
  • SCORM API連携 — 学習の開始・終了、進捗・スコアの送受信をJavaScriptで実装
  • パッケージング — 上記をまとめたZIPファイル(PIF: Package Interchange Format)の作成

既存のHTML教材がすでにブラウザで動作するなら、コンテンツ自体を大幅に書き換える必要はありません。上記3つを追加するだけでSCORM教材として機能します。

2. 全体のフォルダ構成

SCORM教材のZIPパッケージは、以下のような構成になります。

my-course/
├── imsmanifest.xml        ← マニフェストファイル(必須・ルート直下)
├── adlcp_rootv1p2.xsd     ← スキーマファイル群(SCORM 1.2の場合)
├── ims_xml.xsd
├── imscp_rootv1p1p2.xsd
├── imsmd_rootv1p2p1.xsd
├── index.html             ← 教材のエントリーポイント
├── css/
│   └── style.css
├── js/
│   ├── main.js
│   └── scorm-api.js       ← SCORM API ラッパー
└── images/
    └── ...

imsmanifest.xmlはZIPのルート直下に配置する必要があります。サブフォルダに入れるとLMSが認識できません。

3. imsmanifest.xmlの作成

マニフェストファイルはSCORMパッケージの心臓部です。以下はSCORM 1.2準拠の基本的な記述例です。

<?xml version="1.0" encoding="UTF-8"?>
<manifest identifier="course-html-to-scorm"
          version="1.0"
          xmlns="http://www.imsproject.org/xsd/imscp_rootv1p1p2"
          xmlns:adlcp="http://www.adlnet.org/xsd/adlcp_rootv1p2"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://www.imsproject.org/xsd/imscp_rootv1p1p2 imscp_rootv1p1p2.xsd
                              http://www.imsglobal.org/xsd/imsmd_rootv1p2p1 imsmd_rootv1p2p1.xsd
                              http://www.adlnet.org/xsd/adlcp_rootv1p2 adlcp_rootv1p2.xsd">

  <metadata>
    <schema>ADL SCORM</schema>
    <schemaversion>1.2</schemaversion>
  </metadata>

  <organizations default="org-1">
    <organization identifier="org-1">
      <title>HTML教材サンプルコース</title>
      <item identifier="item-1" identifierref="res-1">
        <title>第1章 はじめに</title>
      </item>
      <item identifier="item-2" identifierref="res-2">
        <title>第2章 実践演習</title>
      </item>
    </organization>
  </organizations>

  <resources>
    <resource identifier="res-1" type="webcontent"
              adlcp:scormtype="sco" href="chapter1/index.html">
      <file href="chapter1/index.html"/>
      <file href="css/style.css"/>
      <file href="js/scorm-api.js"/>
    </resource>
    <resource identifier="res-2" type="webcontent"
              adlcp:scormtype="sco" href="chapter2/index.html">
      <file href="chapter2/index.html"/>
      <file href="css/style.css"/>
      <file href="js/scorm-api.js"/>
    </resource>
  </resources>

</manifest>

imsmanifest.xmlの主要要素リファレンス

要素必須説明
ルート要素。identifier属性で一意のIDを指定
SCORMバージョン情報( +
教材の構成(目次構造)を定義。default属性で既定の組織を指定
1つのコース構成。</code>で名称を記述</td></tr> <tr><td><code><item></code></td><td>○</td><td>学習単位(章・セクション)。<code>identifierref</code>でリソースと紐付け</td></tr> <tr><td><code><resources></code></td><td>○</td><td>教材ファイルの一覧を格納</td></tr> <tr><td><code><resource></code></td><td>○</td><td>1つのSCO/Assetを定義。<code>href</code>で起動ファイルを指定</td></tr> <tr><td><code><file></code></td><td>△</td><td>リソースに含まれるファイル。省略可能だが記載推奨</td></tr> <tr><td><code>adlcp:scormtype</code></td><td>○</td><td><code>sco</code>(LMSと通信)または<code>asset</code>(通信なし)を指定</td></tr> </tbody></table> <p><strong>ポイント:</strong> <code>scormtype="sco"</code>を指定したリソースはSCORM APIでLMSと通信できます。静的な参考資料など通信不要なリソースは<code>asset</code>にします。</p> <h2 id="4-scorm-apiラッパーの実装">4. SCORM APIラッパーの実装</h2> <p>LMSはブラウザのウィンドウオブジェクトにAPIを公開します。教材側のJavaScriptからこのAPIを探索・呼び出しすることで、学習データの読み書きが可能になります。</p> <p>以下は、SCORM 1.2に対応した基本的なAPIラッパーの実装例です。</p> <pre><code>/** * SCORM 1.2 API ラッパー */ const ScormAPI = (() => { let api = null; // LMSが公開するAPIオブジェクトをウィンドウ階層から探索 function findAPI(win) { let attempts = 0; while (!win.API && win.parent && win.parent !== win && attempts < 10) { win = win.parent; attempts++; } return win.API || null; } function getAPI() { if (api) return api; api = findAPI(window); if (!api && window.opener) { api = findAPI(window.opener); } return api; } return { // 学習セッションの開始 initialize() { const lmsAPI = getAPI(); if (!lmsAPI) { console.error("SCORM API が見つかりません"); return false; } const result = lmsAPI.LMSInitialize(""); // 初回アクセス時はステータスを設定 if (this.getValue("cmi.core.lesson_status") === "not attempted") { this.setValue("cmi.core.lesson_status", "incomplete"); } return result === "true"; }, // 値の取得 getValue(key) { const lmsAPI = getAPI(); return lmsAPI ? lmsAPI.LMSGetValue(key) : ""; }, // 値の設定 setValue(key, value) { const lmsAPI = getAPI(); return lmsAPI ? lmsAPI.LMSSetValue(key, value) === "true" : false; }, // データの永続化 commit() { const lmsAPI = getAPI(); return lmsAPI ? lmsAPI.LMSCommit("") === "true" : false; }, // 学習セッションの終了 terminate() { this.commit(); const lmsAPI = getAPI(); return lmsAPI ? lmsAPI.LMSFinish("") === "true" : false; }, // スコアの送信(0〜100) setScore(score) { this.setValue("cmi.core.score.raw", score); this.setValue("cmi.core.score.min", "0"); this.setValue("cmi.core.score.max", "100"); // スコアに応じて合否判定(例: 80点以上で合格) const status = score >= 80 ? "passed" : "failed"; this.setValue("cmi.core.lesson_status", status); this.commit(); }, // 学習完了の記録 setComplete() { this.setValue("cmi.core.lesson_status", "completed"); this.commit(); } }; })(); </code></pre> <h3 id="教材htmlへの組み込み例">教材HTMLへの組み込み例</h3> <pre><code><script src="js/scorm-api.js"></script> <script> // ページ読み込み時にSCORM接続を開始 window.addEventListener("load", () => { ScormAPI.initialize(); }); // ページ離脱時にSCORM接続を終了 window.addEventListener("beforeunload", () => { ScormAPI.terminate(); }); // 学習完了ボタンの例 document.getElementById("btn-complete").addEventListener("click", () => { ScormAPI.setComplete(); alert("学習完了を記録しました"); }); </script> </code></pre> <h2 id="5-scorm-12とscorm-2004のapi比較">5. SCORM 1.2とSCORM 2004のAPI比較</h2> <p>開発時には対象バージョンを明確にしておくことが重要です。主なAPI名の違いを以下にまとめます。</p> <table> <thead><tr><th>操作</th><th>SCORM 1.2</th><th>SCORM 2004</th></tr></thead> <tbody> <tr><td>API検索対象</td><td><code>window.API</code></td><td><code>window.API_1484_11</code></td></tr> <tr><td>初期化</td><td><code>LMSInitialize("")</code></td><td><code>Initialize("")</code></td></tr> <tr><td>値の取得</td><td><code>LMSGetValue(key)</code></td><td><code>GetValue(key)</code></td></tr> <tr><td>値の設定</td><td><code>LMSSetValue(key, value)</code></td><td><code>SetValue(key, value)</code></td></tr> <tr><td>コミット</td><td><code>LMSCommit("")</code></td><td><code>Commit("")</code></td></tr> <tr><td>終了</td><td><code>LMSFinish("")</code></td><td><code>Terminate("")</code></td></tr> <tr><td>エラーコード取得</td><td><code>LMSGetLastError()</code></td><td><code>GetLastError()</code></td></tr> <tr><td>完了ステータスのキー</td><td><code>cmi.core.lesson_status</code></td><td><code>cmi.completion_status</code></td></tr> <tr><td>スコアのキー</td><td><code>cmi.core.score.raw</code></td><td><code>cmi.score.raw</code></td></tr> </tbody></table> <p>SCORM 2004ではデータモデルのキー名も変更されています。両バージョンに対応する場合は、API検索を分岐させるラッパーを用意するのが一般的です。</p> <h2 id="6-パッケージングzip化">6. パッケージング(ZIP化)</h2> <p>すべてのファイルが準備できたら、ZIP形式にパッケージングします。</p> <p><strong>手順:</strong></p> <ol> <li>教材フォルダのルートに<code>imsmanifest.xml</code>があることを確認</li> <li>フォルダの<strong>中身を直接</strong>ZIP圧縮する(フォルダごとではない)</li> <li>ZIPを開いたとき、最上位に<code>imsmanifest.xml</code>が見える状態が正解</li> </ol> <pre><code># コマンドラインでの例(macOS / Linux) cd my-course/ zip -r ../my-course.zip ./* </code></pre> <p><strong>よくある失敗:</strong> フォルダごとZIP化すると<code>my-course/imsmanifest.xml</code>というパスになり、LMSがマニフェストを検出できません。必ずZIPのルート直下に<code>imsmanifest.xml</code>を配置してください。</p> <h2 id="7-テストと検証">7. テストと検証</h2> <h3 id="scorm-cloudでのテスト">SCORM Cloudでのテスト</h3> <p>作成したパッケージはRustici社の<a href="https://cloud.scorm.com/" class="text-primary-600 underline hover:text-primary-700">SCORM Cloud</a>で無料テストできます。</p> <ol> <li>SCORM Cloudにアカウントを作成</li> <li>「Add Content」からZIPファイルをアップロード</li> <li>「Launch」でコンテンツを実行し、動作を確認</li> <li>「Activity Report」で学習データ(ステータス、スコア)が正しく記録されているか検証</li> </ol> <h3 id="ブラウザの開発者ツールによるデバッグ">ブラウザの開発者ツールによるデバッグ</h3> <p>SCORM APIの呼び出しをデバッグするには、ラッパーにログ出力を追加すると効率的です。</p> <pre><code>// デバッグ用:API呼び出しをコンソールに出力 setValue(key, value) { console.log(`[SCORM] SetValue: ${key} = ${value}`); const lmsAPI = getAPI(); return lmsAPI ? lmsAPI.LMSSetValue(key, value) === "true" : false; } </code></pre> <h2 id="8-よくある失敗とその対策">8. よくある失敗とその対策</h2> <table> <thead><tr><th>症状</th><th>原因</th><th>対策</th></tr></thead> <tbody> <tr><td>LMSにアップロードできない</td><td>ZIPの階層が深い(マニフェストがルートにない)</td><td>フォルダの中身を直接ZIP化する</td></tr> <tr><td>「通信エラー」と表示される</td><td>SCORM APIが見つからない</td><td><code>findAPI</code>の探索ロジックを確認。<code>opener</code>も対象にする</td></tr> <tr><td>ステータスが記録されない</td><td><code>LMSCommit</code>を呼んでいない</td><td><code>setValue</code>の後に必ず<code>commit()</code>を実行</td></tr> <tr><td>2回目以降のアクセスでリセットされる</td><td><code>cmi.core.lesson_location</code>を使っていない</td><td>中断位置をブックマークとして保存・復元する</td></tr> <tr><td>スコアが反映されない</td><td><code>score.min</code>/<code>score.max</code>を設定していない</td><td><code>score.raw</code>と合わせて3つとも設定する</td></tr> <tr><td>マニフェストのバリデーションエラー</td><td>XML名前空間やスキーマ参照の記述ミス</td><td>公式スキーマファイルをパッケージに含め、パスを正確に記述する</td></tr> </tbody></table> <h2 id="9-よくある質問faq">9. よくある質問(FAQ)</h2> <h3 id="q1-既存のhtml教材にscorm対応するのにどれくらいの工数がかかりますか">Q1. 既存のHTML教材にSCORM対応するのにどれくらいの工数がかかりますか?</h3> <p>シンプルな教材(数ページのHTML)であれば、マニフェスト作成とAPI組み込みで<strong>半日〜1日程度</strong>が目安です。ただし、テスト結果の送信やブックマーク(中断・再開)機能を実装する場合は、追加で1〜2日を見込んでください。複数SCOで構成される大規模教材や、SCORM 2004のシーケンシング設定が必要な場合はさらに工数が増えます。</p> <h3 id="q2-scorm-12と2004のどちらを選ぶべきですか">Q2. SCORM 1.2と2004のどちらを選ぶべきですか?</h3> <p>日本国内のLMSはSCORM 1.2対応が圧倒的に多く、互換性の面で<strong>SCORM 1.2を推奨</strong>します。SCORM 2004は学習順序の制御(シーケンシング)や詳細なインタラクション記録が可能ですが、LMS側の対応にばらつきがあり、マニフェストの記述も複雑になります。特別な要件がない限り、まずはSCORM 1.2で作成するのが安全です。</p> <h3 id="q3-scoとassetの違いは何ですか">Q3. SCOとAssetの違いは何ですか?</h3> <p><strong>SCO(Sharable Content Object)</strong> はSCORM APIを通じてLMSと通信するコンテンツです。学習ステータスやスコアを記録できます。一方、<strong>Asset</strong> はLMSとの通信を行わない静的リソース(画像、PDF、参考ページなど)です。マニフェストの<code>adlcp:scormtype</code>属性で区別します。</p> <h3 id="q4-imsmanifestxmlをツールで自動生成できますか">Q4. imsmanifest.xmlをツールで自動生成できますか?</h3> <p>はい。SCORM用のオーサリングツール(iSpring、Articulate Storylineなど)を使えば、GUIでマニフェストを自動生成できます。かつてはReload Editorという無料ツールもありましたが、現在は開発が停滞しています。手書きで構造を理解しておくと、ツール生成後の微調整やトラブルシューティングが格段に楽になります。</p> <h3 id="q5-動画教材もscorm対応にできますか">Q5. 動画教材もSCORM対応にできますか?</h3> <p>可能です。HTMLページ内に<code><video></code>タグで動画を埋め込み、JavaScriptで再生完了を検知してSCORM APIに完了ステータスを送信する方法が一般的です。動画ファイルはパッケージに含めるか、外部CDNから配信してHTMLで参照します。</p> <h2 id="10-まとめ">10. まとめ</h2> <p>HTML教材のSCORM対応は、以下のステップで実現できます。</p> <ul> <li><strong>imsmanifest.xmlを作成</strong> — 教材の構成・リソース情報をXMLで記述し、ZIPのルートに配置する</li> <li><strong>SCORM APIラッパーを実装</strong> — LMSとの通信処理をJavaScriptで記述し、<code>initialize</code> / <code>setValue</code> / <code>commit</code> / <code>terminate</code>の基本サイクルを組み込む</li> <li><strong>パッケージをZIP化</strong> — マニフェストがルート直下にある状態でZIP圧縮する</li> <li><strong>SCORM Cloudなどでテスト</strong> — アップロード・実行し、ステータスやスコアが正しく記録されることを検証する</li> <li><strong>SCORM 1.2を基本に</strong> — 国内LMSとの互換性を重視するなら、まずはSCORM 1.2で対応する</li> </ul> <p>技術的にはシンプルな仕組みですが、マニフェストの記述ミスやAPI呼び出しの順序誤りなど、細かいハマりどころが多いのも事実です。</p> <hr> <p>HTML教材のSCORM対応でお困りの方は、<strong>eラーニング専門18年・3,000件超の制作実績</strong>を持つエレファンキューブにご相談ください。既存教材の変換から新規開発、LMSへの搭載テストまでワンストップで対応いたします。</p> <!-- CTA --> <div class="mt-12 bg-gradient-to-r from-primary-800 to-primary-600 rounded-2xl p-8 lg:p-10 text-center text-white"> <h3 class="text-2xl font-bold mb-4" style="border:none; padding:0; margin:0 0 1rem 0; color:#fff;">SCORMのことなら、何でもご相談ください</h3> <p class="mb-6 max-w-lg mx-auto" style="color:#bfdbfe;">SCORM変換・教材制作・技術トラブルの解決まで、ワンストップで対応します。ご相談・お見積もりは無料です。</p> <a href="../#contact" class="inline-flex items-center justify-center px-8 py-4 bg-accent-500 hover:bg-accent-600 text-white text-lg font-bold rounded-full shadow-xl hover:shadow-2xl transition-all hover:-translate-y-0.5"> 無料で相談する <svg class="ml-2 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"/></svg> </a> </div> <!-- 著者情報 --> <div class="mt-10 flex items-start gap-5 bg-gray-50 rounded-xl p-6 border border-gray-200"> <div class="w-16 h-16 bg-primary-100 rounded-full flex items-center justify-center flex-shrink-0"> <svg class="w-8 h-8 text-primary-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"/></svg> </div> <div> <p class="font-bold text-gray-900 mb-1">株式会社エレファンキューブ</p> <p class="text-sm text-gray-600 leading-relaxed">eラーニング教材制作の専門会社。2008年の創業以来、3,000件超の制作実績を持ち、SCORM 1.2 / SCORM 2004 / xAPI / cmi5など各種規格に精通。企画からLMS搭載まで、ワンストップで対応しています。</p> <a href="https://www.elephancube.co.jp/" target="_blank" rel="noopener noreferrer" class="inline-flex items-center text-primary-600 text-sm font-medium mt-2 hover:underline"> コーポレートサイト <svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/></svg> </a> </div> </div> </article> <!-- サイドバー --> <aside class="hidden lg:block"> <div class="sticky top-24 space-y-6 max-h-[calc(100vh-7rem)] overflow-y-auto pr-1"> <!-- CTA --> <div class="bg-gradient-to-b from-primary-800 to-primary-600 rounded-2xl p-6 text-center text-white"> <p class="font-bold text-lg mb-3">SCORMでお困りですか?</p> <p class="text-blue-200 text-sm mb-5">まずはお気軽にご相談ください。無料でご対応します。</p> <a href="../#contact" class="block w-full py-3 bg-accent-500 hover:bg-accent-600 text-white font-bold rounded-full text-sm transition">無料で相談する</a> </div> <!-- 目次 --> <div class="bg-white border border-gray-200 rounded-xl p-5"> <p class="font-bold text-gray-900 text-sm mb-3">目次</p> <ol class="space-y-2 text-xs text-gray-500 list-decimal pl-4"> <li><a href="#1-scorm対応とは何か" class="hover:text-primary-600 transition">1. SCORM対応とは何か</a></li> <li><a href="#2-全体のフォルダ構成" class="hover:text-primary-600 transition">2. 全体のフォルダ構成</a></li> <li><a href="#3-imsmanifestxmlの作成" class="hover:text-primary-600 transition">3. imsmanifest.xmlの作成</a></li> <li><a href="#4-scorm-apiラッパーの実装" class="hover:text-primary-600 transition">4. SCORM APIラッパーの実装</a></li> <li><a href="#5-scorm-12とscorm-2004のapi比較" class="hover:text-primary-600 transition">5. SCORM 1.2とSCORM 2004のAPI比較</a></li> <li><a href="#6-パッケージングzip化" class="hover:text-primary-600 transition">6. パッケージング(ZIP化)</a></li> <li><a href="#7-テストと検証" class="hover:text-primary-600 transition">7. テストと検証</a></li> <li><a href="#8-よくある失敗とその対策" class="hover:text-primary-600 transition">8. よくある失敗とその対策</a></li> <li><a href="#9-よくある質問faq" class="hover:text-primary-600 transition">9. よくある質問(FAQ)</a></li> <li><a href="#10-まとめ" class="hover:text-primary-600 transition">10. まとめ</a></li> </ol> </div> <!-- 関連記事 --> <div class="bg-white border border-gray-200 rounded-xl p-5"> <p class="font-bold text-gray-900 text-sm mb-4">関連記事</p> <div class="space-y-4"> <a href="../column/?slug=ppt-to-scorm" class="block group"> <p class="text-xs text-primary-600 font-bold mb-1">実践ガイド</p> <p class="text-sm font-bold text-gray-800 group-hover:text-primary-600 transition leading-snug">PowerPointをSCORM教材に変換する方法【3つのアプローチ】</p> </a> <a href="../column/?slug=video-to-scorm" class="block group"> <p class="text-xs text-primary-600 font-bold mb-1">実践ガイド</p> <p class="text-sm font-bold text-gray-800 group-hover:text-primary-600 transition leading-snug">動画(MP4)をSCORM対応にする方法——変換手順と注意点</p> </a> <a href="../column/?slug=scorm-cost" class="block group"> <p class="text-xs text-primary-600 font-bold mb-1">実践ガイド</p> <p class="text-sm font-bold text-gray-800 group-hover:text-primary-600 transition leading-snug">SCORM変換を外注する場合の費用相場と選び方</p> </a> <a href="../column/?slug=pdf-to-scorm" class="block group"> <p class="text-xs text-primary-600 font-bold mb-1">実践ガイド</p> <p class="text-sm font-bold text-gray-800 group-hover:text-primary-600 transition leading-snug">PDFをSCORM教材にする方法——閲覧追跡と完了判定を組み込むには</p> </a> </div> </div> </div> </aside> </div> </div> </div> </main> <footer id="company" class="bg-gray-900 text-gray-400 pt-16 pb-8" role="contentinfo"> <div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8"> <div class="grid gap-10 md:grid-cols-4 mb-12"> <div class="md:col-span-1"> <a href="../" class="text-2xl font-extrabold text-white tracking-tight" style="font-family:'Sora',sans-serif;">scorm<span class="text-primary-400">.jp</span></a> <p class="mt-4 text-sm leading-relaxed">SCORMに関するあらゆるお悩みを解決する、eラーニング専門のサービスサイトです。</p> </div> <div> <h4 class="text-white font-bold text-sm mb-4">サービス</h4> <ul class="space-y-2 text-sm"> <li><a href="../service/consultation.php" class="hover:text-white transition">無料相談</a></li> <li><a href="../service/conversion.php" class="hover:text-white transition">SCORM変換</a></li> <li><a href="../service/production.php" class="hover:text-white transition">SCORM対応教材制作</a></li> </ul> </div> <div> <h4 class="text-white font-bold text-sm mb-4">情報</h4> <ul class="space-y-2 text-sm"> <li><a href="../works/" class="hover:text-white transition">制作実績</a></li> <li><a href="../column/" class="hover:text-white transition">SCORMコラム</a></li> <li><a href="../faq/" class="hover:text-white transition">よくある質問</a></li> </ul> </div> <div> <h4 class="text-white font-bold text-sm mb-4">会社情報</h4> <ul class="space-y-2 text-sm"> <li><a href="https://www.elephancube.co.jp/" target="_blank" rel="noopener noreferrer" class="hover:text-white transition">運営会社(株式会社エレファンキューブ)</a></li> <li><a href="../privacy/" class="hover:text-white transition">プライバシーポリシー</a></li> <li><a href="../contact/" class="hover:text-white transition">お問い合わせ</a></li> </ul> </div> </div> <div class="border-t border-gray-800 pt-8 flex flex-col md:flex-row items-center justify-between gap-4"> <p class="text-xs">運営: <a href="https://www.elephancube.co.jp/" target="_blank" rel="noopener noreferrer" class="hover:text-white transition">株式会社エレファンキューブ</a></p> <p class="text-xs">© 2026 Elephancube Inc. All rights reserved.</p> </div> </div> </footer> <script> const menuBtn = document.getElementById('menuBtn'); const mobileMenu = document.getElementById('mobileMenu'); menuBtn.addEventListener('click', () => mobileMenu.classList.toggle('hidden')); mobileMenu.querySelectorAll('a').forEach(link => { link.addEventListener('click', () => mobileMenu.classList.add('hidden')); }); const header = document.querySelector('header'); window.addEventListener('scroll', () => { header.classList.toggle('shadow-md', window.scrollY > 10); header.classList.toggle('shadow-sm', window.scrollY <= 10); }); </script> </body> </html>