:root {
  --bg: #10141c;
  --panel: #1b2232;
  --panel-border: #4a5877;
  --accent: #f4d35e;
  --hp-green: #3ddc84;
  --hp-red: #e94f5c;
  --text: #e8ecf4;
  --text-dim: #8f9bb3;
  --grid-line: #333d55;
  --caption-size: 8px; /* セクションタイトル・ヒント・ツールチップなど「説明書き」全般で統一するサイズ */
  font-size: 15px;
}

* {
  box-sizing: border-box;
}

canvas {
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}

html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  background: #05070c;
  color: var(--text);
  /* 英数字は Press Start 2P（日本語グリフなし）、日本語は DotGothic16 に自動フォールバックして見た目のドット感を揃える */
  font-family: 'Press Start 2P', 'DotGothic16', monospace;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  /* 2026-09-16：実機でページ読み込み直後の表示スケールがずれる不具合の対策。
     同一利用者の別プロジェクト（C:\src\bird-strike、同じ実機で崩れが
     出ていない）に合わせ、overflow/touch-action/overscroll-behaviorを
     html,body全体に明示し、ブラウザ側の意図しないパン・ズーム・オーバー
     スクロール判定の余地をなくす。 */
  overflow: hidden;
  touch-action: none;
  overscroll-behavior: none;
}

button {
  font-family: inherit;
}

.screen {
  width: 660px;
  max-width: 100vw;
  background: var(--bg);
  border: 4px solid var(--panel-border);
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px;
  margin: 12px;
}

.battle-row {
  display: flex;
  flex-direction: row;
  gap: 8px;
  align-items: stretch;
}

/* ---------- 左：敵パネル ---------- */
.left-panel {
  width: 260px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.enemy-status {
  background: var(--panel);
  border: 2px solid var(--panel-border);
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.enemy-name {
  font-size: 12px;
  letter-spacing: 1px;
}

.hp-row {
  font-size: 10px;
  color: var(--text-dim);
  display: flex;
  gap: 6px;
  align-items: center;
}

.hp-label {
  color: var(--accent);
}

.hp-bar {
  width: 100%;
  height: 12px;
  background: #000;
  border: 2px solid var(--panel-border);
  padding: 1px;
}

.hp-bar-fill {
  height: 100%;
  background: var(--hp-green);
  width: 100%;
  transition: width 0.35s steps(10);
}

.hp-bar.player .hp-bar-fill {
  background: var(--hp-red);
}

/* 敵の次の攻撃までの残り手数バッジ（画面右上固定、2026-09-16：ターン制に
   変更するのに伴い、時間制ゲージから数字表示へ置き換え） */
.next-attack-badge {
  position: fixed;
  top: calc(8px + env(safe-area-inset-top, 0px));
  right: 8px;
  z-index: 2000;
  background: var(--panel);
  border: 2px solid var(--panel-border);
  padding: 4px 10px;
  text-align: center;
  pointer-events: none;
}

.next-attack-label {
  font-size: 7px;
  letter-spacing: 1px;
  color: var(--text-dim);
  white-space: nowrap;
}

.next-attack-count {
  font-size: 20px;
  line-height: 1.2;
  color: var(--accent);
}

.next-attack-count.danger {
  color: var(--hp-red);
}

.battle-view {
  position: relative;
  flex: 1;
  min-height: 330px;
  border: 2px solid var(--panel-border);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.battle-view.shake {
  animation: shakeAnim 0.3s;
}

@keyframes shakeAnim {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(4px); }
}

.fx-slash {
  position: absolute;
  top: 50%;
  left: 50%;
  height: 6px;
  width: 120px;
  background: #fff;
  opacity: 0;
}

.fx-slash.play {
  animation: slashPlay 0.35s ease-out forwards;
}

@keyframes slashPlay {
  0%   { opacity: 0; transform: translate(-50%, -50%) rotate(var(--ang, -25deg)) scaleX(0); }
  15%  { opacity: 1; }
  60%  { opacity: 1; transform: translate(-50%, -50%) rotate(var(--ang, -25deg)) scaleX(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(var(--ang, -25deg)) scaleX(1); }
}

.fx-impact {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  opacity: 0;
  box-shadow: 0 0 0 0 var(--fx-color, #fff);
}

.fx-impact.play {
  animation: impactPlay 0.4s ease-out forwards;
}

@keyframes impactPlay {
  0%   { opacity: 0.9; box-shadow: 0 0 0 0 var(--fx-color, #fff); }
  100% { opacity: 0; box-shadow: 0 0 0 40px transparent; }
}

/* 攻撃力が高い帯で使う全画面フラッシュ */
.fx-flash {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.08s ease-out;
}

/* 消したブロックから敵へ飛ぶ光の演出（2026-09-19追加、ユーザーフィード
   バックを受けて尾を引く光線風に調整）。document.bodyに直接
   position:fixedで追加される細長い要素で、`transform-origin:0% 50%`を
   発射元セルに置き、JS側が--ang（発射角）・--dist（発射元セルから見た
   到達距離）をセットする。`rotate(--ang) translateX(--dist)`で発射角の
   まま直進させ（回転してから自軸方向へ平行移動、という定番の直線移動
   テクニック）、背景をtransparent→ブロック色→白のグラデーションにする
   ことで進行方向の先端が明るく、後方に尾を引くように見せている。 */
.fx-light-orb {
  position: fixed;
  height: 5px;
  border-radius: 3px;
  transform-origin: 0% 50%;
  pointer-events: none;
  z-index: 5000;
  opacity: 0;
}

.fx-light-orb.fly {
  animation: lightOrbFly 0.18s linear forwards;
}

@keyframes lightOrbFly {
  0%   { opacity: 0; transform: rotate(var(--ang, 0deg)) translateX(0) scaleX(0.35); }
  10%  { opacity: 1; }
  80%  { opacity: 1; }
  100% { opacity: 0; transform: rotate(var(--ang, 0deg)) translateX(var(--dist, 0px)) scaleX(1); }
}

/* ラスボステマエの「ブロック強制破壊」演出（2026-09-18追加）：#backpackGrid
   上に対象セルと同じ色・同じ位置で重ね、縮小・回転・落下フェードアウト
   させる（JS側でセルごとにanimation-delayをずらして連鎖的に見せる）。 */
.fx-crumble-cell {
  position: absolute;
  box-sizing: border-box;
  pointer-events: none;
  z-index: 6;
  opacity: 1;
}

.fx-crumble-cell.play {
  animation: blockCrumble 0.38s ease-in forwards;
}

@keyframes blockCrumble {
  0%   { transform: scale(1) rotate(0deg) translateY(0); opacity: 1; }
  100% { transform: scale(0.15) rotate(55deg) translateY(20px); opacity: 0; }
}

/* アカイトリの風のバリア：発動中ずっと表示される持続系エフェクト
   （2026-09-18追加）。斜め縞模様をbackground-positionアニメーションで
   ループさせるだけの軽量な表現（JS側の毎フレーム処理は不要）。 */
.wind-barrier-fx {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  background-image: repeating-linear-gradient(
    115deg,
    rgba(160, 220, 255, 0.18) 0px,
    rgba(160, 220, 255, 0.18) 10px,
    rgba(160, 220, 255, 0) 10px,
    rgba(160, 220, 255, 0) 26px
  );
  background-size: 200% 200%;
  box-shadow: inset 0 0 26px rgba(120, 200, 255, 0.5);
  animation: windBarrierDrift 1.6s linear infinite;
}

.wind-barrier-fx[hidden] {
  display: none;
}

@keyframes windBarrierDrift {
  from { background-position: 0 0; }
  to   { background-position: -120px 60px; }
}

/* モンスターの背景：草原（表示順6以降は.darkが付き夜の草原に切り替わる。JS側で敵ごとに切り替え） */
.battle-bg {
  position: absolute;
  inset: 0;
  background-color: #14161f;
  background-image: url('resource/grassland.jpg');
  background-size: cover;
  background-position: center;
}

.battle-bg.dark {
  background-image: url('resource/grassland_dark.jpg');
}

.pixel-enemy {
  position: relative;
  width: 160px;
  height: 120px;
  filter: drop-shadow(0 6px 0 rgba(0,0,0,0.35));
}

.enemy-image {
  position: relative;
  object-fit: contain;
  filter: drop-shadow(0 8px 10px rgba(0,0,0,0.5));
}

.enemy-image.size-small { max-width: 68%; max-height: 68%; }
.enemy-image.size-medium { max-width: 85%; max-height: 85%; }
.enemy-image.size-large { max-width: 100%; max-height: 100%; }
.enemy-image.size-xlarge { max-width: 118%; max-height: 118%; }

/* ダメージ数値のフォントサイズは「迫力を出したい」との要望を受け、
   2026-09-19に全体を一回り（+4px）大きくした。 */
.floating-damage {
  position: absolute;
  font-size: 22px;
  color: var(--hp-red);
  text-shadow: 2px 2px 0 #000;
  opacity: 0;
  pointer-events: none;
}

.floating-damage.enemy {
  top: 40%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.floating-damage.player {
  top: 6px;
  right: 10px;
  font-size: 17px;
}

.floating-damage.critical {
  color: var(--accent);
  text-shadow: 2px 2px 0 #000, 0 0 10px rgba(244, 211, 94, 0.8);
}

.floating-damage.enemy.critical {
  font-size: 26px;
}

.floating-damage.player.critical {
  font-size: 19px;
}

.floating-damage.enemy.show {
  animation: floatUpCenter 0.9s ease-out forwards;
}

.floating-damage.player.show {
  animation: floatUpCorner 0.9s ease-out forwards;
}

@keyframes floatUpCenter {
  0%   { opacity: 1; transform: translate(-50%, -50%) translateY(0); }
  100% { opacity: 0; transform: translate(-50%, -50%) translateY(-40px); }
}

@keyframes floatUpCorner {
  0%   { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-24px); }
}

/* コンボ表示（2026-09-16追加）：ライン消しが連続するたびに敵の上に表示 */
.combo-badge {
  position: absolute;
  top: 12%;
  left: 50%;
  font-size: 16px;
  color: var(--accent);
  text-shadow: 2px 2px 0 #000, 0 0 8px rgba(244, 211, 94, 0.7);
  opacity: 0;
  pointer-events: none;
  white-space: nowrap;
}

.combo-badge.show {
  animation: comboPop 0.7s ease-out forwards;
}

@keyframes comboPop {
  0%   { opacity: 0; transform: translate(-50%, 0) scale(0.6); }
  25%  { opacity: 1; transform: translate(-50%, 0) scale(1.15); }
  40%  { opacity: 1; transform: translate(-50%, 0) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -14px) scale(1); }
}

/* 盤面ぜんぶ消し（パーフェクトクリア）の必殺技バナー（2026-09-16追加） */
.perfect-clear-banner {
  position: absolute;
  top: 50%;
  left: 50%;
  font-size: 22px;
  letter-spacing: 2px;
  color: #fff;
  text-shadow:
    2px 0 0 #ff2d55, -2px 0 0 #ff2d55, 0 2px 0 #ff2d55, 0 -2px 0 #ff2d55,
    0 0 16px rgba(255, 45, 85, 0.9);
  opacity: 0;
  pointer-events: none;
  white-space: nowrap;
  z-index: 10;
}

.perfect-clear-banner.show {
  animation: perfectClearSweep 1.1s ease-out forwards;
}

@keyframes perfectClearSweep {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.4) rotate(-4deg); }
  20%  { opacity: 1; transform: translate(-50%, -50%) scale(1.2) rotate(-4deg); }
  35%  { opacity: 1; transform: translate(-50%, -50%) scale(1) rotate(0deg); }
  80%  { opacity: 1; transform: translate(-50%, -50%) scale(1) rotate(0deg); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.05) rotate(0deg); }
}

/* 敵撃破時の残像フェード演出（2026-09-19追加）。以前は画面暗転＋「タップ
   して　つづける」表示でユーザーの操作を待っていたが、演出だけで自動的に
   次の敵（またはクリア画面）へ進む方式に変更した。ブロック操作の無効化は
   `boardLocked`フラグ（game.js、`playEnemyDefeatFade`の実行中true）で行う。
   敵スプライトの複製を`animation-delay`をずらして重ね、それぞれ拡大・
   フェードアウトさせることで「残像を残しつつ消える」見た目にしている。 */
.fx-enemy-ghost {
  position: absolute;
  pointer-events: none;
  opacity: 0;
  object-fit: contain;
  image-rendering: pixelated;
  z-index: 3;
}

.fx-enemy-ghost.play {
  animation: enemyGhostFade 0.6s ease-out forwards;
}

@keyframes enemyGhostFade {
  0%   { opacity: 0.8; filter: brightness(1.3) saturate(0.5); transform: scale(1) translateY(0); }
  100% { opacity: 0; filter: brightness(1.8) saturate(0); transform: scale(1.15) translateY(-18px); }
}

/* ---------- 右：プレイヤーパネル ---------- */
.right-panel {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.player-status {
  position: relative;
  overflow: hidden;
  background: var(--panel);
  border: 2px solid var(--panel-border);
  padding: 10px;
  display: flex;
  gap: 10px;
}

.hit-flash {
  position: absolute;
  inset: 0;
  background: var(--hp-red);
  opacity: 0;
  pointer-events: none;
}

.hit-flash.show {
  animation: hitFlashAnim 0.4s ease-out;
}

@keyframes hitFlashAnim {
  0%   { opacity: 0.55; }
  100% { opacity: 0; }
}

.stat-block {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.stat-label {
  font-size: 9px;
  color: var(--text-dim);
}

.cmd-btn {
  flex: 1;
  padding: 14px 0;
  font-family: inherit;
  font-size: 13px;
  color: var(--text);
  background: var(--panel);
  border: 3px solid var(--panel-border);
  cursor: pointer;
  letter-spacing: 2px;
}

.cmd-btn:active {
  transform: translateY(2px);
}

.cmd-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  transform: none;
}

/* ---------- インベントリパネル ---------- */
.inventory-panel {
  background: var(--panel);
  border: 2px solid var(--panel-border);
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
}

.section-title {
  font-size: var(--caption-size);
  color: var(--text-dim);
  margin-bottom: 6px;
}

/* TEMPORARY／TRASHの見出し行：下のstash-trash-rowと同じ幅配分で隙間なく並べる（幅はJSで設定） */
.stash-trash-title-row {
  display: flex;
}

.stash-trash-title-row .section-title {
  margin-bottom: 6px;
}

/* 回転ボタン・ゴミ箱の見出し：下の.trash-rotate-groupと同じ幅配分・同じgapで並べる */
#trashTitle {
  display: flex;
  gap: 4px;
}

#trashTitle span {
  flex: 1;
  min-width: 0;
}

/* 一時置き場＋ゴミ箱：幅の合計がインベントリの幅と一致するように隙間なく並べる */
.stash-trash-row {
  display: flex;
}

/* 一時置き場（実際にインベントリへ置いたときと同じ見た目でプレビュー） */
.stash-slot {
  position: relative;
  border: 2px dashed var(--panel-border);
  background-color: #0b0e16;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: visible;
  touch-action: none;
}

.stash-slot.filled {
  border-style: solid;
}

.stash-slot.drop-hover {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 2px var(--accent);
}

/* ゴミ箱＋回転ボタン：横並びの小さなグループとして扱う（2026-09-19、
   回転ボタンをゴミ箱と同じ描画サイズにして並べて表示する要望に対応）。
   幅・高さは`updateCellSize()`がゴミ箱と全く同じ値（trashW）を両方に
   設定するため、常に同じ大きさの正方形が並ぶ。 */
.trash-rotate-group {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}

/* ゴミ箱：回転ボタンの右隣、大きめのドロップ枠（2026-09-20：回転ボタンと
   位置を入れ替え、一時置き場に隣接しなくなったため`border-left: none`は
   回転ボタン側に移した） */
.trash-can {
  flex-shrink: 0;
  border: 2px solid var(--panel-border);
  background: #0b0e16;
  display: flex;
  align-items: center;
  justify-content: center;
  touch-action: none;
}

/* 2026-09-19更新：trash.pngを新しい正方形キャンバス（256×256）のフラット
   アイコンに差し替え。中身の実際の描画は横方向に約80%しか埋まっておらず
   （左右に余白あり）、隣の.rotate-icon（縦横ほぼ100%まで埋まっている）と
   同じ70%指定のままだと見た目の大きさが揃わなかったため、trash側だけ
   85%に引き上げて実際の見た目のサイズ感を合わせた。回転アイコンと同じ
   `filter: brightness(0) invert(1)`で白一色にし、色味も統一した。 */
.trash-can-img {
  width: 85%;
  height: 85%;
  object-fit: contain;
  filter: brightness(0) invert(1);
}

.trash-can.drop-hover {
  border-color: var(--hp-red);
  box-shadow: inset 0 0 0 2px var(--hp-red);
}

/* ゴミ箱の隣に置く回転ボタン（2026-09-19追加）。TEMPORARY上の未配置
   ブロックをダブルタップ/ダブルクリックする従来の回転操作はそのまま残し、
   こちらはボタンでも同じ`rotateStagedPiece()`を呼べるようにしたもの。
   アイコンは黒一色のPNG（`resource/rotate.png`、ユーザー提供）を
   `<img>`＋`filter: brightness(0) invert(1)`（不透明ピクセルを一度
   真っ黒にしてから反転＝白にする、透過は保持される）で白く表示する
   （HTML要素への`mask-image`はブラウザによって対応にばらつきがあり
   表示されない不具合があったため、より対応の広いこの手法にした）。
   2026-09-20：ゴミ箱と位置を入れ替え、一時置き場の隣（先頭）に来たため、
   `.cmd-btn`の3px枠から`.trash-can`と同じ2px枠に変更し、隣接する
   `.stash-slot`との間で二重線にならないよう`border-left`を消している。 */
.rotate-btn {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 2px solid var(--panel-border);
  border-left: none;
  background: #0b0e16; /* ゴミ箱（.trash-can）と背景色を揃える（2026-09-19）。.cmd-btnのvar(--panel)より上書き */
}

.rotate-icon {
  width: 70%;
  height: 70%;
  object-fit: contain;
  filter: brightness(0) invert(1);
}

/* バックパックグリッド：マス目の背景模様はJS側（updateCellSize）が設定する
   --cell-px に追従させ、グリッド自体のサイズを変えてもズレないようにする */
.backpack-grid {
  position: relative;
  width: 240px;
  height: 240px;
  background-color: #0b0e16;
  background-image:
    repeating-linear-gradient(to right, var(--grid-line) 0 1px, transparent 1px var(--cell-px, 40px)),
    repeating-linear-gradient(to bottom, var(--grid-line) 0 1px, transparent 1px var(--cell-px, 40px));
  border: 2px solid var(--panel-border);
  touch-action: none;
  transition: box-shadow 0.3s ease-out, border-color 0.3s ease-out;
}

/* 武器ブロック（実セルのみ着色し、実際の形をそのまま表す） */
/* コンテナ自体は形状の外接矩形（くぼみ部分も含む）を占有するため、
   当たり判定はコンテナではなく実セル（.weapon-cell）側に持たせる。
   これにより、L字/T字のくぼみに別の武器が配置されていても、
   透明な余白部分がクリックを奪わず、くぼみの武器を操作できる。 */
.weapon-block {
  position: relative;
  cursor: grab;
  user-select: none;
  pointer-events: none;
  touch-action: none; /* スマホでドラッグ中にページがスクロールしてしまうのを防ぐ */
}

.weapon-block.dragging {
  cursor: grabbing;
  opacity: 0.85;
  z-index: 1000;
  pointer-events: auto; /* ドラッグ中はbody直下に浮くオーバーレイなので外接矩形全体でよい */
}

/* 光沢感：左上に明るいハイライト、右下に影を重ねてプラスチックのような質感にする。
   背景色は background-color で設定される（JS側）ため、background-image と独立して重なる。 */
.weapon-cell {
  position: absolute;
  box-sizing: border-box;
  border: 2px solid rgba(0,0,0,0.5);
  box-shadow: inset 0 0 0 2px rgba(255,255,255,0.15);
  background-image: linear-gradient(135deg,
    rgba(255,255,255,0.55) 0%,
    rgba(255,255,255,0.15) 22%,
    rgba(255,255,255,0) 45%,
    rgba(0,0,0,0) 65%,
    rgba(0,0,0,0.28) 100%);
  pointer-events: auto;
  touch-action: none;
}

.weapon-block.dragging .weapon-cell {
  box-shadow: inset 0 0 0 2px rgba(255,255,255,0.15), 0 0 0 2px var(--accent);
}

/* 固定済み（配置後にロックされた）セル。backpackGrid直下に1マスずつ描画する。
   グロス感は.weapon-cellと同じテクスチャを流用するが、操作対象ではないので
   pointer-eventsは持たない。 */
.locked-cell {
  position: absolute;
  box-sizing: border-box;
  border: 2px solid rgba(0,0,0,0.5);
  box-shadow: inset 0 0 0 2px rgba(255,255,255,0.15);
  background-image: linear-gradient(135deg,
    rgba(255,255,255,0.55) 0%,
    rgba(255,255,255,0.15) 22%,
    rgba(255,255,255,0) 45%,
    rgba(0,0,0,0) 65%,
    rgba(0,0,0,0.28) 100%);
  pointer-events: none;
  touch-action: none;
}

/* ラスボスの特殊能力：3ターンの間消去できないブロック（2026-09-16追加） */
.locked-cell.frozen-cell {
  filter: grayscale(0.55) brightness(0.8);
  box-shadow: inset 0 0 0 2px rgba(130, 210, 255, 0.9), 0 0 6px rgba(130, 210, 255, 0.6);
}

/* 敵の特殊能力によるマス目オーバーレイ（毒／配置禁止、2026-09-16追加） */
.board-overlay-cell {
  position: absolute;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  touch-action: none;
  z-index: 3;
}

.poison-cell {
  background: rgba(168, 85, 247, 0.5);
  border: 2px solid rgba(168, 85, 247, 0.9);
  box-shadow: inset 0 0 10px rgba(168, 85, 247, 0.85);
  animation: poisonPulse 1.3s ease-in-out infinite;
}

@keyframes poisonPulse {
  0%, 100% { opacity: 0.65; }
  50% { opacity: 1; }
}

.denied-cell {
  background: rgba(0, 0, 0, 0.55);
  border: 2px dashed rgba(255, 90, 90, 0.9);
  color: #ff5a5a;
  font-weight: bold;
  font-size: 20px;
}

/* TEMPORARY欄の右上に重ねる次のブロックのミニプレビュー */
.next-preview-wrap {
  position: absolute;
  top: 4px;
  right: 4px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  background: rgba(0,0,0,0.55);
  padding: 3px;
  pointer-events: none;
  touch-action: none;
  z-index: 5;
}

.next-preview-label {
  font-size: 7px;
  color: var(--text-dim);
  letter-spacing: 1px;
}

.next-preview-box {
  position: relative;
}

.next-preview-cell {
  position: absolute;
  box-sizing: border-box;
  border: 1px solid rgba(0,0,0,0.6);
}

/* 武器ツールチップ（マウスオーバー） */
/* ---------- メッセージウィンドウ ---------- */
/* 表示行数が変わると全体のレイアウトがガタつくため、常に2行分の高さで固定する
   （1行のメッセージでも余白ができ、3行以上になる場合は下端で切れる）。 */
.message-window {
  background: var(--panel);
  border: 3px solid #ffffff;
  padding: 14px 16px;
  --msg-fs: 13px;
  font-size: var(--msg-fs);
  line-height: 1.8;
  height: calc(var(--msg-fs) * 1.8 * 2 + 28px);
  overflow: hidden;
  color: var(--text);
  box-shadow: 0 0 0 1px rgba(0,0,0,0.4), 0 4px 10px rgba(0,0,0,0.4);
}

/* 2行に収まらない長いメッセージ（英語や大コンボ時）は、箱の高さを変えずに
   小さめの文字で3行（さらに収まらなければ4行）表示にする（2026-09-29、setMessageが判定して付ける） */
.message-window.compact {
  font-size: calc(var(--msg-fs) * 0.8);
  line-height: calc(var(--msg-fs) * 1.2);
}
/* それでも収まらないときは4行 */
.message-window.compact2 {
  font-size: calc(var(--msg-fs) * 0.64);
  line-height: calc(var(--msg-fs) * 0.9);
}

.message-window.pulse {
  animation: messagePulse 0.4s ease-out;
}

@keyframes messagePulse {
  0%   { box-shadow: 0 0 0 4px var(--accent), 0 4px 10px rgba(0,0,0,0.4); }
  100% { box-shadow: 0 0 0 1px rgba(0,0,0,0.4), 0 4px 10px rgba(0,0,0,0.4); }
}

.title-screen[hidden], .gameover-screen[hidden], .clear-screen[hidden] {
  display: none;
}

/* ---------- タイトル画面 ---------- */
.title-screen {
  position: fixed;
  inset: 0;
  z-index: 3000;
  background: #05070c;
  background-image:
    radial-gradient(circle at 50% 35%, #1b2232 0%, #05070c 70%),
    repeating-linear-gradient(to right, rgba(255,255,255,0.02) 0 2px, transparent 2px 26px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 28px;
}

.title-text {
  font-size: 26px;
  line-height: 1.9;
  color: var(--accent);
  text-align: center;
  letter-spacing: 2px;
  max-width: 90vw;
  text-shadow:
    3px 0 0 #7a1f28, -3px 0 0 #7a1f28,
    0 3px 0 #7a1f28, 0 -3px 0 #7a1f28,
    3px 3px 0 #7a1f28, -3px -3px 0 #7a1f28,
    3px -3px 0 #7a1f28, -3px 3px 0 #7a1f28,
    0 6px 0 rgba(0,0,0,0.5);
}

/* タイトル画面のメニュー（2026-09-21：全体クリックで開始する方式から、
   「ゲーム開始／ハイスコア／あそびかた」の3ボタン構成に変更） */
.title-menu {
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: min(260px, 70vw);
}

.title-menu-btn {
  flex: none;
  padding: 14px 0;
  font-size: 14px;
  letter-spacing: 3px;
}

/* Xなどアプリ内ブラウザでの描画崩れ（原因不明・対策済みだが解消しないため
   ユーザーへの回避策案内として追加、2026-09-23）向けの控えめな注意書き */
.title-browser-note {
  margin: -14px 0 0;
  font-size: var(--caption-size);
  line-height: 1.6;
  color: var(--text-dim);
  text-align: center;
}

.title-start-btn {
  border-color: var(--accent);
  box-shadow: 0 3px 0 #8a6f1c;
}

.title-start-btn:active {
  box-shadow: none;
}

/* ---------- あそびかた画面 ---------- */
/* html,body全体はtouch-action:noneだが、この画面だけは縦スクロールを
   許可する必要があるため、touch-actionをpan-yで明示的に上書きする。 */
.help-screen {
  position: fixed;
  inset: 0;
  z-index: 3200;
  background: rgba(5, 7, 12, 0.97);
  display: flex;
  justify-content: center;
  padding: 16px;
  padding-top: calc(16px + env(safe-area-inset-top, 0px));
  padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  box-sizing: border-box;
  overflow-y: auto;
  touch-action: pan-y;
  overscroll-behavior: contain;
}

.help-screen[hidden] {
  display: none;
}

.help-content {
  width: 100%;
  max-width: 480px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.help-title {
  font-size: 18px;
  color: var(--accent);
  letter-spacing: 3px;
  margin: 4px 0;
}

.help-section {
  width: 100%;
  box-sizing: border-box;
  background: var(--panel);
  border: 2px solid var(--panel-border);
  padding: 12px;
}

.help-section h3 {
  font-size: 12px;
  color: var(--accent);
  letter-spacing: 1px;
  margin: 0 0 10px;
}

.help-section p {
  font-size: 12px;
  line-height: 1.9;
  color: var(--text);
  margin: 10px 0 0;
}

.help-image {
  display: block;
  width: 100%;
  max-width: 260px;
  margin: 0 auto;
  border: 2px solid var(--panel-border);
}

#btnCloseHelp {
  flex: none;
  padding: 12px 32px;
  margin: 4px 0 8px;
}

/* ---------- ゲームオーバー画面 ---------- */
.gameover-screen {
  position: fixed;
  inset: 0;
  z-index: 3000;
  background: rgba(5, 7, 12, 0.92);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 30px;
}

.gameover-text {
  font-size: 28px;
  color: var(--hp-red);
  letter-spacing: 4px;
  text-shadow: 4px 4px 0 rgba(0,0,0,0.6);
}

.gameover-buttons {
  display: flex;
  gap: 14px;
}

.gameover-buttons .cmd-btn {
  padding: 14px 22px;
  border-color: var(--accent);
  box-shadow: 0 3px 0 #8a6f1c;
}

.gameover-buttons .cmd-btn:active {
  box-shadow: none;
}

/* ---------- クリア画面 ---------- */
.clear-screen {
  position: fixed;
  inset: 0;
  z-index: 3000;
  background: rgba(5, 7, 12, 0.92);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* 名前入力欄の追加（2026-09-21）で縦に長くなったため、狭い画面や大きな広告が
     入った場合に上端が切れて到達できなくならないよう、はみ出したら上寄せに
     切り替えて縦スクロールできるようにする（html,bodyはtouch-action:noneなので
     この画面だけpan-yを許可）。`safe center`非対応の環境では従来の中央寄せのまま。 */
  justify-content: safe center;
  overflow-y: auto;
  touch-action: pan-y;
  overscroll-behavior: contain;
  gap: 18px;
}

.clear-screen > * {
  flex-shrink: 0;
}

.clear-text {
  font-size: 28px;
  color: var(--accent);
  letter-spacing: 4px;
  text-shadow: 4px 4px 0 rgba(0,0,0,0.6);
}

.clear-rank {
  font-size: 48px;
  letter-spacing: 2px;
  text-shadow: 0 0 16px currentColor, 4px 4px 0 rgba(0,0,0,0.6);
}

.clear-rank.rank-SSS, .clear-rank.rank-SS { color: #ffd23f; }
.clear-rank.rank-S { color: var(--accent); }
.clear-rank.rank-A, .clear-rank.rank-B { color: var(--hp-green); }
.clear-rank.rank-C, .clear-rank.rank-D { color: var(--text-dim); }
.clear-rank.rank-E { color: var(--hp-red); }

.clear-stats {
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--panel);
  border: 2px solid var(--panel-border);
  padding: 14px 24px;
  min-width: 220px;
}

.clear-row {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  font-size: 12px;
  color: var(--text-dim);
}

.clear-row span:last-child {
  color: var(--text);
}

.clear-score-row {
  border-top: 2px solid var(--panel-border);
  padding-top: 8px;
  margin-top: 2px;
  font-size: 14px;
}

.clear-score-row span:last-child {
  color: var(--accent);
}

/* 自己ベスト行（2026-09-21追加）。更新時は「NEW RECORD!」を金色で点滅表示 */
.clear-best-row {
  font-size: 13px;
}

.clear-best-row.is-new-record span {
  color: #ffd23f;
  animation: newRecordPulse 0.9s ease-in-out infinite alternate;
}

@keyframes newRecordPulse {
  from { opacity: 1; }
  to { opacity: 0.45; }
}

@media (prefers-reduced-motion: reduce) {
  .clear-best-row.is-new-record span { animation: none; }
}

/* クリア画面の名前入力欄（2026-09-21追加、上限20文字）。スマホのブラウザは
   16px未満の入力欄にフォーカスすると自動ズームするため、文字サイズは16px。 */
.clear-name {
  display: flex;
  align-items: center;
  gap: 8px;
  width: min(340px, 92vw);
}

.clear-name-label {
  flex: none;
  font-size: 11px;
  letter-spacing: 1px;
  color: var(--text-dim);
}

.clear-name-input {
  flex: 1;
  min-width: 0;
  font-family: inherit;
  font-size: 16px;
  color: var(--text);
  background: var(--bg);
  border: 2px solid var(--panel-border);
  border-radius: 0;
  padding: 8px 10px;
}

.clear-name-input::placeholder {
  color: var(--text-dim);
  font-size: 12px;
}

.clear-name-input:focus {
  outline: none;
  border-color: var(--accent);
}

.clear-name-btn {
  flex: none;
  padding: 10px 12px;
  font-size: 12px;
}

.clear-name-btn:disabled,
.clear-name-input:disabled {
  opacity: 0.6;
  cursor: default;
}

/* クリア画面の「Xでシェア」ボタン（2026-09-22追加）。ボタンではなくリンク（<a>）なので、
   ポップアップとして扱われて止められることがなく、長押しでURLのコピーもできる。 */
.share-x-btn {
  flex: none;
  box-sizing: border-box;
  display: block;
  width: min(340px, 92vw);
  padding: 12px 0;
  text-align: center;
  text-decoration: none;
  color: #fff;
  background: #000;
  border-color: #e8ecf4;
}

.share-x-btn:hover,
.share-x-btn:focus-visible {
  border-color: var(--accent);
  outline: none;
}

/* ---------- ハイスコア画面（2026-09-21追加）。枠はあそびかた画面と共通 ---------- */
.ranking-status {
  min-height: 1.6em;
  font-size: 12px;
  color: var(--text-dim);
  text-align: center;
  line-height: 1.6;
}

.ranking-list {
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.ranking-row {
  display: grid;
  grid-template-columns: 2.6em minmax(0, 1fr) auto 3.2em;
  align-items: center;
  gap: 8px;
  background: var(--panel);
  border: 2px solid var(--panel-border);
  padding: 8px 10px;
  font-size: 12px;
}

.ranking-row.is-mine {
  border-color: var(--accent);
}

.ranking-pos {
  text-align: right;
  color: var(--text-dim);
}

.ranking-row:nth-child(-n+3) .ranking-pos {
  color: #ffd23f;
}

.ranking-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
}

.ranking-score {
  text-align: right;
  color: var(--accent);
}

.ranking-rank {
  text-align: right;
  color: var(--text-dim);
}

.ranking-rank.rank-SSS, .ranking-rank.rank-SS { color: #ffd23f; }
.ranking-rank.rank-S { color: var(--accent); }
.ranking-rank.rank-A, .ranking-rank.rank-B { color: var(--hp-green); }
.ranking-rank.rank-E { color: var(--hp-red); }

.ranking-me, .ranking-own {
  width: 100%;
  font-size: 12px;
  text-align: center;
  line-height: 1.7;
  color: var(--text-dim);
}

.ranking-me {
  color: var(--accent);
}

#btnCloseRanking {
  flex: none;
  padding: 12px 32px;
}

.clear-buttons {
  display: flex;
  gap: 14px;
}

.clear-buttons .cmd-btn {
  padding: 14px 22px;
  border-color: var(--accent);
  box-shadow: 0 3px 0 #8a6f1c;
}

.clear-buttons .cmd-btn:active {
  box-shadow: none;
}

/* PC表示専用（スマホ側の@media (max-width: 700px)とは排他。2026-09-30） */
@media (min-width: 701px) {
  /* NEXT ATTACKバッジをメッセージウィンドウ内の右端に収める。
     バッジは.screenの子なので、.screen基準のabsoluteで重ねる
     （メッセージ側はpadding-rightでバッジの分だけ文字を避ける）。 */
  .screen { position: relative; }
  .next-attack-badge { position: absolute; top: 26px; right: 23px; }
  .message-window { padding-right: 140px; }

  /* TRASHをROTATEの下に積み、TEMPORARY＋ROTATE/TRASHの幅をインベントリ幅
     （6マス）に揃える。右パネルは中身の幅ぴったりにして右側の余白をなくし、
     浮いた分は敵表示側に回す。 */
  .left-panel { width: auto; flex: 1; min-width: 0; }
  .right-panel { flex: none; }
  .trash-rotate-group { flex-direction: column; gap: 0; }
  .trash-can { border-left: none; border-top: none; }
  /* 見出しはROTATEのみ（TRASHは真下に積まれ見出しを置く場所がない）。
     幅はJSが2個分をinlineで指定するため上書きする */
  #trashTitle { width: auto !important; }
  #trashTitle span + span { display: none; }
}

@media (max-width: 700px) {
  /* スマホでの縦方向のはみ出しを抑えるため、余白・隙間・敵表示エリアの
     高さを詰める。 */
  /* iPhoneのノッチ／Dynamic Islandの直下に表示順1番目（`.enemy-status`）の
     敵名・HPバーがかぶって隠れてしまう不具合の対策（2026-09-18）。
     `#nextAttackBadge`/`.help-screen`は既にenv(safe-area-inset-*)を
     考慮していたが、`.screen`本体（バトル画面のメイン枠）は考慮しておらず、
     6px程度の固定paddingしかなかったためノッチの高さ（機種により約
     44〜59px）を吸収できていなかった。 */
  .screen {
    width: 100%;
    margin: 0;
    border-width: 0 0 4px 0;
    padding: 6px;
    padding-top: calc(6px + env(safe-area-inset-top, 0px));
    padding-bottom: calc(6px + env(safe-area-inset-bottom, 0px));
    gap: 6px;
  }

  /* 表示順を「モンスターHP→敵画像→メッセージ→主人公HP→その他」に組み替える。
     battle-row/left-panel/right-panelはdisplay:contentsで箱をなくし、
     中身（enemy-status/battle-view/player-status/...）を.screenの直接の
     flex子要素にした上でorderで並べ替える（HTML/JSの構造は変更しない）。 */
  .battle-row, .left-panel, .right-panel { display: contents; }
  .enemy-status { order: 1; }
  .battle-view { order: 2; }
  .message-window { order: 3; }
  .player-status { order: 4; }
  .inventory-panel { order: 5; }
  /* min-heightだけだと高さが確定せず画像のmax-height:100%が効かないため、
     heightで確定させる（敵画像が原寸のまま表示されてしまう問題の修正）。
     ベースのflex:1（flex-basis:0%）が残っていると、この高さ指定より
     flexの伸長計算が優先されてしまうため、flexそのものを無効化する。 */
  .battle-view { flex: none; height: 170px; min-height: 0; }
  .enemy-status { padding: 6px; }
  .player-status { padding: 6px; }
  .inventory-panel { padding: 6px; gap: 8px; }
  /* グリッド本体：vw（画面幅基準）で幅を決めていると、.screen/.inventory-panelの
     余白や.stash-sectionの実際の幅とズレて横はみ出しの原因になっていた
     （2026-09-13発覚）。vwをやめ、同じ行内でflexboxの比率だけに揃えることで、
     実際のコンテナ幅から必ず正しく収まるようにする。JS側（updateCellSize/
     renderInventory）がbackpackGrid.clientWidthを見て自動追従するため、
     この比率を変えるだけでTEMPORARY/TRASH欄やマス目模様も含め全て連動する。 */
  .backpack-grid { width: 100%; height: auto; aspect-ratio: 1; }

  /* インベントリ本体を左、TEMPORARY/TRASHを右に縦積みする配置に変更し、
     縦方向のスペースを大きく節約する（グリッドの上に横並びで置いていた
     従来レイアウトだと縦に約120px余分にかかっていた）。
     グリッド:TEMPORARY/TRASH列 = 6マス:4マス = 3:2 の比率でflex-growさせる
     ことで、cellSize（グリッド由来）とTEMPORARY/TRASHの実際の幅が
     ぴったり一致するようにしている（flex-basis:0%前提。ずれるとJS側の
     stashSlot.style.widthがこの列の実幅を超えてはみ出す）。 */
  .inventory-panel { flex-direction: row; align-items: flex-start; }
  .backpack-section { order: 0; flex: 3; min-width: 0; }
  .stash-section {
    order: 1;
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 2;
    min-width: 0;
  }
  /* ラッパーdiv自体はレイアウトに関与させず（display:contents）、
     中の見出し・箱を直接orderで「見出し→箱→見出し→箱」の縦並びに組み替える。
     `.trash-rotate-group`はdisplay:contentsにしない（ゴミ箱＋回転ボタンを
     常に横並びのまま1つのブロックとして扱うため、2026-09-19追加）。 */
  .stash-trash-title-row, .stash-trash-row { display: contents; }
  /* JSがcellSize由来のpx幅を指定するため、万一この列の実幅とズレても
     はみ出さないようにする保険 */
  #stashTitle, #stashSlot, #trashTitle, .trash-rotate-group { max-width: 100%; }
  #stashTitle { order: 0; }
  #stashSlot { order: 1; }
  #trashTitle { order: 2; }
  .trash-rotate-group { order: 3; }
}

/* スマホ縦向き（〜430px程度）：文字サイズが小さく読みにくかった箇所を底上げする。
   6×6インベントリ本体（.backpack-grid、固定240px）はこの幅でも収まるため変更しない。 */
@media (max-width: 430px) {
  :root {
    --caption-size: 10px; /* ツールチップ・見出し等の「説明書き」全般 */
  }
  .enemy-name { font-size: 13px; }
  .hp-row { font-size: 11px; }
  .stat-label { font-size: 10px; }
  .next-attack-label { font-size: 8px; }
  .next-attack-count { font-size: 24px; }
  .message-window { --msg-fs: 15px; }
  .cmd-btn { font-size: 14px; }
}

/* ゲームオーバー／クリア画面のボタン行：極端に狭い画面でもはみ出さず折り返す保険 */
.gameover-buttons, .clear-buttons {
  flex-wrap: wrap;
  justify-content: center;
  max-width: 92vw;
}

.clear-stats {
  max-width: 92vw;
}

/* 広告枠（忍者AdMax、2026-09-21追加）。タイトル画面は全体クリックで
   ゲーム開始になるため、広告クリックが伝播しないようJS側でも止めている。 */
.ad-slot {
  max-width: 100%;
  overflow: hidden;
  text-align: center;
  margin-top: 8px;
}
