ゲーム用ステータスボード 作成指示書
================================


この指示書の全文を Muse に渡し、「この仕様で、データを保存できる対話型アーティファクト（フルスタック）として作成してください」と依頼すれば、同等のボードを再現できます。
slug は `space` を推奨します（GM 運用ルール側がこの slug を前提にしているため）。既に使われている場合は別の slug でも構いませんが、その場合は運用ルール側の slug 記載も合わせてください。
本番データは空の状態から始めること。検証用のダミーデータを本番に入れないこと。


LLM が GM を務めるテキストゲームのための状態管理ボード。
本文（ナラティブ）はチャットで進行し、状態（Count・日時・現在地・所持品など）はこのボード側に保存・表示する。本文の末尾に UI を付けずに済ませ、チャットのトークン消費を抑えるのが狙い。
複数のキャンペーンを保持でき、切り替えて表示できること。


キャンペーン 1 件は以下の項目を持つ。

- id（自動採番）
- title：キャンペーン名
- worldName：世界観の名称
- worldSummary：世界観の概要（長文可）
- count：GM 応答カウンタ（#0001〜#9999 として表示）
- gameDate：作中日付（文字列。例「2102年春・1日目」）
- timeOfDay：おおよその時刻（文字列。例「昼すぎ」）
- location：現在地
- funds：資金（文字列。金額でも「なし（物々交換が中心）」のような記述でもよい）
- situations：直近の状況。{text} のリスト、最大 5 件。過去ログの要約ではなく「いま進行中の要素」を書く欄
- キャラクターシート：charName（名前）、charRace（種族）、charAge（年齢）、charGender（性別）、charJob（職業・立場）、charOrigin（出自・来歴）、charGoal（目的）
- inventory：所持品。{name（必須）, qty, note} のリスト
- companions：「仲間」欄。同行 NPC・コンパニオン用。{name（必須）, role, status, note} のリスト
- retinue：「配下・編成」欄。社員や部隊人員などの管理用。{name（必須）, kind（種別、自由記述）, count（数）, status, note} のリスト
- knowledge：知識メモ。情報の非対称性（誰が何を知り、何を知らないか）の管理用。{who（必須）, knows, doesntKnow} のリスト


- 出来事ログ：作らない。履歴はチャットログと、別途作るセーブファイル（章ダイジェスト）で扱うため、ボードには不要。
- ターン履歴・スナップショット・復元機能：作らない。


表示順は以下とする。

1. 現況ヘッダー：Count（#NNNN）、作中日付、おおよその時刻、キャラクター名、現在地、資金、直近の状況（最大 5 件）
2. 世界観：worldName と worldSummary
3. キャラクター
4. 所持品
5. 仲間
6. 配下・編成
7. 知識メモ

- キャンペーンの切り替え UI を用意する
- すべての項目をボード上で直接編集できること（追加・編集・削除を含む）
- キャンペーンの新規作成と削除ができること。作成時に他のキャンペーンを消さないこと
- 空の欄も含め、すべてのセクションが正常に描画されること
- PC（デスクトップ）とスマートフォンの両方で崩れないこと


以下のアクションを公開すること。名前と意味はこの通りに合わせる（GM 側のチャットがこの名前で呼び出すため）。

- listcampaigns：全キャンペーンの一覧（id、title、charName、count、gameDate、location、worldName、更新日時などの要約）
- getcampaign：1 件の全状態を返す（id を指定）
- createcampaign：新規作成（title は必須、他の開始時項目は任意）。新しい id を返す
- updatecampaign：任意の項目の部分更新（id と patch を指定）。patch に含まれない項目は変更しない
- applyturn：1 ターン分の更新を適用する（id を指定）。与えられた項目だけを反映し、指定があれば Count を +1 して新しい Count を返す。部分更新が原則で、含まれない項目（companions / retinue を含む）は変更しない。companions / retinue は、patch 内またはトップレベルで渡された時だけ置き換える
- bumpcount：Count だけを +1 する（id を指定）
- deletecampaign：1 件を削除する（id を指定）

後方互換：applyturn が旧式の引数（addEvents、note、events など）を含んでいても、エラーにせず黙って無視し、通常の状態更新は成功させること。


- ゲーム開始の宣言時に、Start 設定に基づいてキャンペーンを作成する
- 各ターンの終わりに applyturn で状態を更新する。ボードの更新にユーザーの承認は不要
- ボードに存在する項目はチャット欄に出力しない。末尾 UI も付けない
- 仲間・配下・編成などの欄は、変化があった時だけ更新する


過去に「パネルが真っ白になる」不具合があったため、以下を必ず実装すること。

- localStorage へのアクセスはすべて例外安全にする（埋め込み表示などでストレージが拒否されても起動時に例外で落ちない）
- 描画エラー時は真っ白にせず、「データは保存されている」旨の案内と再読み込みボタンを出すエラー境界を設ける
- JavaScript が届く前から見える静的な「読み込み中…」のプレースホルダを用意し、読み込みが 8 秒を超えたら開き直しを案内する文面に切り替える。読み込み失敗時にも再試行できるようにする
- 外部リクエストを発生させない。特に Web フォント（Google Fonts など）を読み込まない。フォントは端末のローカルフォントで賄う


作成後、以下を確認すること。

- キャンペーンを 2 件作っても互いに干渉せず、Count が独立している
- applyturn の部分更新で、送らなかった項目（特に companions / retinue）が消えずに残る
- applyturn に旧式の引数（addEvents、note）を混ぜてもエラーにならない
- セクションの表示順が指定通りになっている
- 本番データに検証用データが残っていない


- この指示書で再現できるのは機能と仕様です。既存ボードの保存データ（進行中キャンペーンの内容）は含まれません。再現先では空の状態から始まります
- 見た目の細部（配色や余白など）は、作成する側のビルドによって多少異なる場合があります
