/*
 * Order Battle — 画面(実装計画フェーズ7 / UI化粧直しv1.0)
 *
 * 方針(画面仕様v1.1 §0):
 *   - スマホファースト(縦持ち基準)。PCは同レイアウトの拡大
 *   - タップ領域は最低 44px
 *   - 装飾は最小限。読みやすさ(コントラスト・余白・行間)だけに投資する
 *   - ビルド工程なし。素のCSS(カスタムプロパティのみ使用)
 *
 * ★UI化粧直しv1.0(2026-08-02)で入れた2つの構造変更:
 *   ① **ドキュメントをスクロールさせない**(下の「アプリの器」参照)。
 *      レイアウトジャンプの根治。
 *   ② **アクセント色を4系統の変数に集約**(通常=青/危険=赤/報酬=金/回復=緑)。
 *      直書きの色はここへ寄せる — 同じ意味は同じ色、が変数側だけで守れる。
 */

:root {
  /* ------------------------------------------------------------ 面 */
  --bg:        #14161c;
  --bg-raise:  #1c1f27;
  --bg-sunken: #101218;
  --line:      #2c313d;
  --line-soft: #232733;

  /* モーダルの面。**ページ地色より明確に明るく**する — 同色だと「面」として
     読めず、暗くした地の上に同色の板が乗るので背後が透けて見える */
  --surface:      #262b37;
  --surface-line: #3c4356;
  --scrim:        rgba(4, 5, 8, .82);

  --text:      #e6e8ee;
  --text-dim:  #9aa2b4;
  --text-faint:#6b7484;

  /* ------------------------------------------ アクセント体系(4系統)
     意味ごとに色を決めて、画面はこの変数だけを見る。
     各系統は fg(文字・線画)/ line(縁)/ bg(面)/ glow(にじみ)の4段。 */

  /* 通常・進行・現在地 = 青 */
  --normal-fg:   #6fa8ff;
  --normal-line: #3d63a3;
  --normal-bg:   #2c4a7d;
  --normal-glow: rgba(111, 168, 255, .34);

  /* 危険・被弾・喪失 = 赤 */
  --danger-fg:   #ff6b6b;
  --danger-line: #7d3535;
  --danger-bg:   #5c2626;
  --danger-glow: rgba(255, 107, 107, .32);

  /* 報酬・注意・宝 = 金 */
  --reward-fg:   #ffc857;
  --reward-line: #6a5528;
  --reward-bg:   #4a4330;
  --reward-glow: rgba(255, 200, 87, .30);

  /* 回復・安全・全快 = 緑 */
  --heal-fg:     #5fd3a0;
  --heal-line:   #2f6b53;
  --heal-bg:     #1e3a2e;
  --heal-glow:   rgba(95, 211, 160, .30);

  /* ------------------------------------------------ 色帯4段(2026-08-11 裁定2)
     **ゲーム共通の等級の文法**。個体の振れも、装備のレア度も、同じ4色の物差しに乗る。
     無色 → 青 → 紫 → 橙 の順に珍しい。確率は画面に一切出さない(色と帯名だけ)。 */
  --band-common-fg:   #9aa4b2;  /* 無色 = 大多数。地の文字色に近く、目立たないことが役目 */
  --band-common-line: #39414f;
  --band-common-bg:   #262c36;

  --band-rare-fg:     #6fb8ff;  /* 青 */
  --band-rare-line:   #35618f;
  --band-rare-bg:     #21344b;

  --band-epic-fg:     #d7a3ff;  /* 紫 */
  --band-epic-line:   #6a4a86;
  --band-epic-bg:     #3a2b46;

  --band-legend-fg:   #ff9a3c;  /* 橙(危険ダンジョン専用・裁定3) */
  --band-legend-line: #8a5620;
  --band-legend-bg:   #4a3320;

  /* 装備のレア度は 2026-08-11 の裁定2で**青**へ移った(段階は増やしていない —
     既にある2値を共通の物差しの上へ置き直しただけ)。旧 --rare-* は紫のままだが、
     参照している箇所(タグ・隠し部屋)は「紫が欲しい」側なので触らない */
  --rare-fg:     #d7a3ff;
  --rare-line:   #6a4a86;
  --rare-bg:     #3a2b46;

  /* 旧名の別名。既存の記述を一度に書き換えないための橋渡し */
  --accent:      var(--normal-fg);
  --accent-dark: var(--normal-bg);
  --danger:      var(--danger-fg);
  --danger-dark: var(--danger-bg);
  --warn:        var(--reward-fg);
  --good:        var(--heal-fg);
  --rare:        var(--rare-fg);

  /* ------------------------------------------------ 探索マップの3段階
     「踏破 / 隣接シルエット / 未踏」が**一目で3段に見える**ことが要件。
     明度差だけに頼らず、壁は塗り+輪郭+斜線の質感で床と別物に見せる。 */
  --map-unknown:      #090b10;  /* 未踏 = ほぼ背景・輪郭なし(「何も知らない」の地) */
  --map-ghost-wall:   #171d27;  /* 隣接・壁(塗りつぶし) */
  --map-ghost-wall-e: #3b4759;  /* 同・輪郭 */
  --map-ghost-floor:  #242b38;  /* 隣接・床(うっすら床色) */
  --map-floor:        #3d475c;  /* 踏破 = 明るい床色 */
  --map-floor-e:      #515d76;  /* 同・輪郭 */
  --map-wall:         #1a2029;  /* 踏破済みの壁 */
  --map-wall-e:       #4a5770;  /* 同・輪郭 */
  --map-tile:         none;     /* 床の地紋(ステージ別。既定 = 敷かない) */

  --radius: 10px;
  --tap: 44px;

  --hud-h: 52px;
  --nav-h: 60px;

  /* マップ1マスの辺。JS側は repeat(n, var(--mcell)) を組むだけにする */
  --mcell: 28px;
  /* 探索画面で盤面以外が要る縦の量(HUD・見出し・凡例と注記・十字キー・余白の合計)。
     JS側が「十字キーが折り返しに収まる盤面の幅」をここから逆算する
     (★体験FB第7号: 16行の門道で十字キーの下端が画面外へ出ていた) */
  --map-reserve: 400px;

  --safe-b: env(safe-area-inset-bottom, 0px);
}

* { box-sizing: border-box; }

/* .hud / .nav は display を明示するので、UA の [hidden] が負ける。ここで勝たせる */
[hidden] { display: none !important; }

/* ------------------------------------------------------- アプリの器 */

/*
 * ★レイアウトジャンプの根治(UI化粧直しv1.0)。
 *
 * 以前は body がスクロールし、HUD が position:sticky で上に貼り付いていた。
 * その構成だと、モーダルが背後を止めるために html/body へ overflow:hidden を
 * 掛けた瞬間に**スクロールポートが消えて sticky が効かなくなり**、ヘッダーが
 * スクロール量そのままの距離だけ下へ流れる(= 上部に黒帯が出る/位置が飛ぶ)。
 *
 * そこで **ドキュメントは一切スクロールさせない**。器を画面高で固定し、
 * 中身(.screen)だけを唯一のスクロール容器にする。こうすると:
 *   - HUD と 下部ナビは flex の兄弟。貼り付ける必要がないので剥がれようがない
 *   - モーダルは position:fixed で画面を覆うだけ。背後を止める細工が要らない
 *   - 再描画時の scroll 復元は .screen.scrollTop の保存・復帰で完結する
 */
html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Hiragino Sans", "Noto Sans JP", "Yu Gothic", sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-text-size-adjust: 100%;
  overscroll-behavior: none;
}

/* PCの死に幅を埋める地の装飾。画像は使わず、上からの淡い光と四隅の陰りだけ。
   「淀みの空洞」側の空気は、この地の暗さと中央列の明るさの差で支える */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(120% 70% at 50% -10%, rgba(111, 168, 255, .07), transparent 60%),
    radial-gradient(90% 60% at 50% 110%, rgba(120, 90, 160, .05), transparent 60%),
    radial-gradient(140% 100% at 50% 50%, transparent 45%, rgba(0, 0, 0, .55) 100%);
}

#app {
  max-width: 560px;
  margin: 0 auto;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  position: relative;
  /* 中央列を地から浮かせる。PC幅で「黒い板に黒い箱」に見えないための細い境界 */
  background: linear-gradient(180deg, rgba(255, 255, 255, .022), transparent 140px);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .04), 0 0 60px rgba(0, 0, 0, .5);
}

/* ---------------------------------------------------------------- HUD */

.hud {
  flex: 0 0 var(--hud-h);
  height: var(--hud-h);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 14px;
  background: var(--bg-sunken);
  border-bottom: 1px solid var(--line);
}

.hud-stamina { display: flex; align-items: baseline; gap: 6px; }
.hud-stamina .val { font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; }
.hud-stamina .max { font-size: 13px; color: var(--text-faint); }
.hud-label { font-size: 11px; color: var(--text-faint); letter-spacing: .08em; }
.hud-full  { font-size: 12px; color: var(--text-dim); }
.hud-res   { margin-left: auto; font-size: 13px; color: var(--text-dim); display: flex; gap: 10px; }
.hud-res b { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
/* 交換に必要な量(個体獲得ポイント)。残高より一段弱く、分母だと分かる形で */
.hud-res .goal { color: var(--text-faint); font-variant-numeric: tabular-nums; }
/* 届いたら分母をやめて「交換可」に差し替える(体験FB第3号「108/100 は読めない」) */
.hud-res .goal-met { color: var(--heal-fg); font-size: 11px; margin-left: 3px; }

.hud.is-blocked .hud-stamina .val { color: var(--danger-fg); }

/* ------------------------------------------------------------- Screen */

/* 唯一のスクロール容器。overscroll-behavior で、端まで来ても外へ伝播させない */
.screen {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 16px 14px calc(24px + var(--safe-b));
  min-width: 0;
}

/* 下部ナビは器の中に居る(fixed をやめた)ので、下駄を履かせる必要がない */
.screen.has-nav { padding-bottom: 20px; }

h1 { font-size: 20px; margin: 0 0 4px; letter-spacing: .02em; }
h2 { font-size: 16px; margin: 22px 0 8px; letter-spacing: .02em; }
h3 { font-size: 14px; margin: 14px 0 6px; color: var(--text-dim); }
p  { margin: 0 0 10px; }

/* 画面の見出しは一段強く。どの画面に居るかが最初に目に入る */
h1 { font-weight: 700; }
h2 {
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 8px;
}
h2::before {
  content: "";
  width: 3px;
  height: 14px;
  border-radius: 2px;
  background: var(--normal-line);
  flex: 0 0 auto;
}

.sub    { color: var(--text-dim); font-size: 13px; margin: 0 0 14px; }
.muted  { color: var(--text-faint); font-size: 12px; }
.center { text-align: center; }
.tabnum { font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------- Nav */

.nav {
  flex: 0 0 auto;
  z-index: 20;
  height: calc(var(--nav-h) + var(--safe-b));
  padding-bottom: var(--safe-b);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: var(--bg-sunken);
  border-top: 1px solid var(--line);
}

.nav button {
  appearance: none;
  border: 0;
  background: none;
  color: var(--text-faint);
  font: inherit;
  font-size: 11px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  cursor: pointer;
  min-height: var(--tap);
  transition: color .12s;
}

.nav button .ico { display: flex; align-items: center; justify-content: center; height: 32px; }

/* ドット絵アイコン(nav_*.png 128px)。32px = 整数1/4縮小 + NEAREST 固定。
   非選択タブはアイコンを沈めて(減光+彩度落とし)、選択タブとの差を絵の側でも出す */
.nav button .nav-ico {
  width: 32px;
  height: 32px;
  image-rendering: pixelated;
  opacity: .55;
  filter: saturate(.35);
  transition: opacity .12s, filter .12s;
}
.nav button.is-active .nav-ico { opacity: 1; filter: none; }

.nav button.is-active { color: var(--normal-fg); }

/* 選択中のタブは上端に細い線。色だけだと弱い */
.nav button.is-active { box-shadow: inset 0 2px 0 var(--normal-fg); }

.svgico { display: block; }

/* ------------------------------------------------------------ Buttons */

button, .btn {
  font: inherit;
  font-size: 15px;
  color: var(--text);
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 12px 16px;
  min-height: var(--tap);
  cursor: pointer;
  text-align: center;
  transition: background .12s, border-color .12s, opacity .12s;
}

button:active { background: #262b36; }
button:disabled { opacity: .4; cursor: default; }

.btn-primary {
  background: var(--normal-bg);
  border-color: var(--normal-line);
  font-weight: 600;
}
.btn-primary:active { background: #365891; }
.btn-danger  { background: var(--danger-bg); border-color: var(--danger-line); }
.btn-ghost   { background: none; }
.btn-block   { display: block; width: 100%; }
.btn-lg      { font-size: 17px; padding: 16px; font-weight: 600; }
.btn-sm      { font-size: 13px; padding: 7px 11px; min-height: 34px; border-radius: 8px; }

/* 画面の主役(街の「出発する」等)。1画面に1つだけ置く */
.btn-hero {
  font-size: 18px;
  font-weight: 700;
  padding: 18px 16px;
  letter-spacing: .04em;
  background: linear-gradient(180deg, #35598f, var(--normal-bg));
  border-color: var(--normal-line);
  box-shadow: 0 4px 20px var(--normal-glow);
}
.btn-hero:active { background: #2b4877; }

/* 主役の隣に置く脇役。面を持たせず、押せることだけ分かればよい */
.btn-quiet { background: none; border-color: var(--line-soft); color: var(--text-dim); }

.btn-row { display: flex; gap: 8px; flex-wrap: wrap; }
.btn-row > * { flex: 1 1 0; min-width: 120px; }

/* -------------------------------------------------------------- Cards */

.card {
  background: var(--bg-raise);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 14px;
  margin-bottom: 10px;
}

/* 一段引いたカード(主役を食わせないための脇役) */
.card.recede { background: none; border-color: var(--line-soft); }

.card.tappable { cursor: pointer; }
.card.tappable:active { background: #232833; }

/* タップできるカードは本物の <button>(ui.js cardButton)。
   button の既定(中央寄せ・固定font-size)だけ打ち消して、見た目は .card のまま */
button.card {
  display: block;
  width: 100%;
  text-align: left;
  font-size: inherit;
  line-height: inherit;
  color: var(--text);
}

button:focus-visible {
  outline: 2px solid var(--normal-fg);
  outline-offset: 2px;
}

.card-head { display: flex; align-items: baseline; gap: 8px; }
.card-head .name { font-weight: 600; font-size: 16px; }
.card-head .meta { margin-left: auto; font-size: 12px; color: var(--text-faint); }

/* 種別を縁で一目にする(危険ダンジョン等)。中身の並びは変えない */
.card.is-danger {
  border-color: var(--danger-line);
  background: linear-gradient(180deg, rgba(92, 38, 38, .22), transparent 70%), var(--bg-raise);
}
.card.is-danger .card-head .name { color: #ffb3b3; }

.tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  padding: 2px 7px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--text-dim);
  background: var(--bg-sunken);
  white-space: nowrap;
}
/* 色帯4段(2026-08-11 裁定2)。装備のレア度も個体の帯も**同じクラスを使う** —
   共通の文法にした以上、同じ色が2つの書き方で出てはいけない。
   `.tag.rare` が青なのは裁定の「装備レア=青へ色替え」そのもの(段階は増えていない) */
.tag.band-common { color: var(--band-common-fg); border-color: var(--band-common-line); }
.tag.rare,
.tag.band-rare   { color: var(--band-rare-fg);   border-color: var(--band-rare-line); }
.tag.band-epic   { color: var(--band-epic-fg);   border-color: var(--band-epic-line); }
.tag.band-legend {
  color: var(--band-legend-fg);
  border-color: var(--band-legend-line);
  background: var(--band-legend-bg);
}
.tag.common { color: var(--text-dim); }

/* 立ち絵・顔サムネの帯縁取り。**色だけで等級が読める**のが裁定2の狙いなので、
   絵のほうにも同じ色を回す(文字を読まなくても手が止まる) */
.unit-face.band-rare,
.unit-face-bg.band-rare,
.bface.band-rare,
.hp-face.band-rare   { box-shadow: 0 0 0 2px var(--band-rare-line); }
.unit-face.band-epic,
.unit-face-bg.band-epic,
.bface.band-epic,
.hp-face.band-epic   { box-shadow: 0 0 0 2px var(--band-epic-line); }
.unit-face.band-legend,
.unit-face-bg.band-legend,
.bface.band-legend,
.hp-face.band-legend { box-shadow: 0 0 0 2px var(--band-legend-fg); }
.tag.danger { color: var(--danger-fg); border-color: var(--danger-line); }
.tag.good   { color: var(--heal-fg);   border-color: var(--heal-line); }
/* 推奨レベル帯の危険度(ステージ選択・改訂案v1.1 §3)。warn=帯下1〜2 / faint=帯を超過 */
.tag.warn   { color: var(--reward-fg); border-color: var(--reward-line); }
.tag.faint  { color: var(--text-faint); border-color: var(--line-soft); }

/* 職バッジ(アイコン + 名前)。名前が既定名(職名)のときはアイコンだけ出す */
.tag .svgico { margin: -1px 0; }
.jobchip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--text-dim);
  font-size: 11px;
}

.rows { display: flex; flex-direction: column; gap: 2px; }
.row  { display: flex; gap: 8px; align-items: baseline; font-size: 14px; }
.row .k { color: var(--text-faint); min-width: 5.5em; font-size: 13px; }
.row .v { font-variant-numeric: tabular-nums; }

.empty {
  color: var(--text-faint);
  font-size: 13px;
  text-align: center;
  padding: 24px 12px;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
}

.notice {
  font-size: 13px;
  color: var(--text-dim);
  background: var(--bg-sunken);
  border-left: 3px solid var(--normal-line);
  border-radius: 4px;
  padding: 10px 12px;
  margin: 0 0 12px;
}
/* 直感で分からない仕組みの1行(2026-08-10 裁定)。説明文(.muted)より一段だけ
   目に留まるが、見出しにはしない — 読まないと分からない部分の注記であって、
   語彙の売り文句ではない */
.note {
  font-size: 12px;
  color: var(--text-dim);
  border-left: 2px solid var(--normal-line);
  padding: 2px 0 2px 8px;
  margin-top: 5px;
}

.notice.warn   { border-left-color: var(--reward-fg); }
.notice.danger { border-left-color: var(--danger-fg); }
.notice.good   { border-left-color: var(--heal-fg); }

.banner {
  display: flex;
  align-items: center;
  gap: 10px;
  background: none;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 9px 11px;
  margin-bottom: 14px;
  font-size: 12.5px;
  color: var(--text-dim);
}
.banner .grow { flex: 1 1 auto; }

.error-text { color: var(--danger-fg); font-size: 13px; margin: 8px 0 0; }

/* --------------------------------------------------------------- Tabs */

.tabs {
  display: flex;
  gap: 6px;
  margin-bottom: 14px;
  overflow-x: auto;
  padding-bottom: 2px;
}
.tabs button {
  flex: 0 0 auto;
  font-size: 13px;
  padding: 8px 14px;
  min-height: 38px;
  border-radius: 999px;
  color: var(--text-dim);
}
.tabs button.is-active {
  background: var(--normal-bg);
  border-color: var(--normal-line);
  color: var(--text);
}

/* ------------------------------------------------------- Stat display */

.statgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin: 10px 0; }
.stat {
  background: var(--bg-sunken);
  border: 1px solid var(--line-soft);
  border-radius: 8px;
  padding: 8px 6px;
  text-align: center;
}
.stat .k { font-size: 11px; color: var(--text-faint); }
.stat .v { font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; }
.stat .breakdown { font-size: 10px; color: var(--text-faint); line-height: 1.35; margin-top: 2px; }
.stat .breakdown i { font-style: normal; }
.stat .breakdown .alloc { color: var(--normal-fg); }
.stat .breakdown .equip { color: var(--heal-fg); }
/* 生まれつき(2026-08-11 裁定1)。振り分け(青)・装備(緑)と別の色にするのは、
   この段だけが**育成で動かない**ものだから — 3つが同じ色だと段の意味が消える */
.stat .breakdown .innate { color: var(--reward-fg); }

/* 一覧カードの中に置く小さいステータス行(ユニット一覧)。
   開くまで白紙だった状態をやめ、選ぶのに要る4つをその場で見せる */
.ministats {
  display: flex;
  gap: 10px;
  margin-top: 5px;
  font-size: 11px;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}
.ministats b { color: var(--text-dim); font-weight: 600; }

/* ユニット一覧の1枚。空白を詰めて、1画面に並ぶ数を増やす */
.unit-card { padding: 10px 12px; margin-bottom: 0; }
.unit-card .card-head { align-items: center; gap: 7px; }
.unit-card .card-head .name { font-size: 15px; }
/* Lv・次までは右端寄せだと立ち絵の顔に乗るため、名前の直後に置く */
.unit-card .card-head .meta { margin-left: 0; }
.unit-card .hstack { gap: 6px; row-gap: 4px; }

.stack.list-tight { gap: 7px; }

/* 報酬は金系(アクセント体系の「報酬=金」)。値の意味を色でも言う */
.reward-text { color: var(--reward-fg); font-size: 13px; }

/* 1行しか無い並び(ステージカードの報酬など)は、見出し幅を詰めて間延びを消す */
.rows.compact .k { min-width: 3.2em; }

.alloc-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  border-bottom: 1px solid var(--line-soft);
}
.alloc-row .k { width: 3em; font-size: 13px; color: var(--text-dim); }
.alloc-row .n { width: 2.5em; text-align: center; font-variant-numeric: tabular-nums; font-weight: 600; }
.alloc-row button { min-height: 38px; min-width: 44px; padding: 6px; }

/* ----------------------------------------------------- Formation grid */

/*
 * 3×3は**幅を絞って正方形の小セル**にする。全幅のままだと1マスが180pxになり、
 * グリッドだけで1画面を食って候補一覧が同時に見えない(編成は「見比べて置く」画面)。
 */
.fgrid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 5px;
  margin: 6px auto;
  /* 3×3で1画面を食わない上限。ここを広げると行動順の一覧が折り返しの下へ落ちる */
  width: min(100%, 258px);
}

.fcell {
  aspect-ratio: 1 / 1;
  background: var(--bg-sunken);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 4px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  font-size: 11px;
  line-height: 1.25;
  overflow: hidden;
  min-height: 0;
  cursor: pointer;
}
/* 編成セルの色帯(2026-08-11 裁定2)。輪郭だけ替える — 塗ると盤面の
   「空き / 埋まり / 移動中」の3状態が読みにくくなる */
.fcell.band-rare   { border-color: var(--band-rare-line); }
.fcell.band-epic   { border-color: var(--band-epic-line); }
.fcell.band-legend { border-color: var(--band-legend-fg); }
.fcell .nm  { font-size: 11.5px; font-weight: 600; text-align: center; word-break: break-all; }
.fcell .jb  { color: var(--text-faint); font-size: 10px; display: flex; align-items: center; gap: 2px; }
.fcell .tc  { color: var(--normal-fg); font-size: 10px; }
.fcell .od  { position: absolute; }
/* 編成マスの現在HPバー(裁定A)。flexの中央寄せで幅0に潰れないよう明示する */
.fcell .hpbar { width: 72%; margin-top: 3px; }

/* 空マスは**文字を置かない**。薄い点線の枠だけで「ここに置ける」は伝わる */
.fcell.is-empty {
  border-style: dashed;
  border-color: var(--line-soft);
  background: none;
  color: transparent;
}
.fcell.is-empty:active { background: var(--bg-sunken); }
.fcell.is-armed { border-color: var(--normal-fg); box-shadow: inset 0 0 0 1px var(--normal-bg); }

.fcell-wrap { position: relative; }
.fcell-wrap .order-badge {
  position: absolute;
  top: 3px; left: 4px;
  font-size: 10px;
  color: var(--text-faint);
  background: var(--bg);
  border-radius: 4px;
  padding: 0 4px;
  font-variant-numeric: tabular-nums;
}

.front-hint { font-size: 11px; color: var(--text-faint); text-align: center; margin: 0 0 4px; }

/* ------------------------------------------------------- Exploration */

.map-wrap {
  position: relative;
  background:
    radial-gradient(90% 70% at 50% 40%, rgba(111, 168, 255, .05), transparent 70%),
    var(--bg-sunken);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 26px 10px 10px;
  margin-bottom: 6px;
  overflow-x: auto;
}

/* 今どこの何階かを枠の中に小さく置く(探索中いつでも見える) */
.map-floor {
  position: absolute;
  top: 7px; left: 11px;
  font-size: 11px;
  color: var(--text-faint);
  letter-spacing: .06em;
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.map-floor b { color: var(--text-dim); font-weight: 600; font-size: 12px; }

.map {
  display: grid;
  gap: 2px;
  margin: 0 auto;
  /* 器いっぱいに広げ、伸びすぎはJS側の max-width(列数 × --mcell)が止める。
     幅13のフロアが狭い端末で右にはみ出して切れていたのを、縮めて収める側に倒した */
  width: 100%;
}

/* 盤面の中のマスだけは正方形を保ったまま伸縮する(凡例の .mcell は固定辺のまま) */
.map > .mcell {
  width: auto;
  height: auto;
  aspect-ratio: 1 / 1;
}

/* 既定 = 未踏。ほぼ背景に沈める(「まだ何も知らない」が地の色) */
.mcell {
  width: var(--mcell);
  height: var(--mcell);
  border-radius: 4px;
  background: var(--map-unknown);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  line-height: 1;
  color: var(--text-faint);
  position: relative;
}

/* ---- 段階②: 隣接シルエット(2026-08-02 裁定)
   踏破より暗く、未踏よりはっきり明るい中間トーン。壁は**塗り+輪郭+斜線**で
   質感を変える — 明るさだけの差だと「暗い床」と見分けがつかない。
   2026-08-09 裁定で壁は記憶されるようになったので、隣の壁は段階③(.v-wall)で描かれる。
   .s-wall が出るのは記憶がまだ空の滞在(裁定より前に始まっていた行)だけの受け皿 */
.mcell.s-floor {
  background: var(--map-ghost-floor);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .05);
}
/* 隣の階段(2026-08-10 裁定・体験FB第7号 項目26)。**シルエットの段のまま**、
   踏破済みの階段(.v-stair_*)と同じ色相へ寄せて一段沈める — 「そこが動線である」ことは
   言うが、まだ踏んでいないので明るさは未踏の側に置く。記号(<>)も出す:
   隣が階段だと分かるのに印が無ければ、結局どれが階段か読めない */
.mcell.s-stairs {
  background: #332e4a;
  color: #b6a4dd;
  box-shadow: inset 0 0 0 1px #5b4e82;
  font-weight: 700;
}
.mcell.s-wall {
  background: var(--map-ghost-wall);
  box-shadow: inset 0 0 0 1px var(--map-ghost-wall-e);
  background-image: repeating-linear-gradient(
    45deg,
    rgba(255, 255, 255, .13) 0 1.5px,
    transparent 1.5px 4.5px
  );
}

/* ---- 段階③: 踏破済み = 明るい床色。ここが一番明るいのが読みの起点 */
.mcell.v-plain { background: var(--map-floor); box-shadow: inset 0 0 0 1px var(--map-floor-e); }

.mcell.v-entrance   { background: #2f6b53; color: #b9f2d8; box-shadow: inset 0 0 0 1px #4a9c7c; font-weight: 700; }
.mcell.v-checkpoint { background: var(--reward-bg); color: var(--reward-fg); box-shadow: inset 0 0 0 1px var(--reward-line); font-weight: 700; }
.mcell.v-stair_up,
.mcell.v-stair_down { background: #453d63; color: #e0ccff; box-shadow: inset 0 0 0 1px #6a5b95; font-weight: 700; }
/* 外れの候補マスは通常マスと見分けがつかない(見た目で当たりが割れないための同色) */
.mcell.v-hidden_candidate { background: var(--map-floor); box-shadow: inset 0 0 0 1px var(--map-floor-e); }

/* ステージの床の地紋(tile_*.png)。**踏破済みの床のマスにだけ**薄く敷く —
   未踏・壁・記号を持つマスに乗せると3段の明度差と記号の読みを壊す。
   外れの候補マスは通常の床と**同じ見た目でなければならない**ので同じ地紋を敷く。
   現在地は駒(顔チップ)が乗るマスなので敷かない。
   縮小は 128px → 32px の**整数1/4 + NEAREST**(image-rendering: pixelated)固定 —
   PC幅(--mcell: 32px)でちょうどタイル1枚、狭い端末では同じ倍率のまま繰り返す。
   地紋であって主役ではないので、色はマスの床色のまま(opacity で沈める)。
   タイルを持たないステージでは --map-tile が none なので、何も敷かれない */
.map > .mcell.v-plain:not(.is-current)::before,
.map > .mcell.v-hidden_candidate:not(.is-current)::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-image: var(--map-tile);
  background-position: center;
  background-size: 32px 32px;
  background-repeat: repeat;
  image-rendering: pixelated;
  opacity: .18;
  pointer-events: none;
}

/* 踏破済みの壁。床と同じ「知っている」段だが、通れないことを斜線で言う。
   ★体験FB第2号「壁と未踏の色が似ていて一瞬迷う」(2ペルソナで再現)への対処:
   塗りを持ち上げるのではなく**輪郭と斜線をはっきりさせた**。未踏は輪郭も斜線も
   持たない地の色なので、質感の有無で分かれるほうが床との3段構造を壊さない */
.mcell.v-wall {
  background: var(--map-wall);
  box-shadow: inset 0 0 0 1px var(--map-wall-e);
  background-image: repeating-linear-gradient(
    45deg,
    rgba(255, 255, 255, .15) 0 1.5px,
    transparent 1.5px 4.5px
  );
}

/* 開いた隠し部屋。踏破していなくても描かれる唯一のマス群(2026-07-30 裁定) */
.mcell.v-hidden_room     { background: var(--rare-bg); color: var(--rare-fg); box-shadow: inset 0 0 0 1px var(--rare-line); }
.mcell.v-hidden_treasure { background: var(--reward-bg); color: var(--reward-fg); box-shadow: inset 0 0 0 1px var(--reward-fg); font-size: 10px; font-weight: 700; }
.mcell.v-hidden_boss     { background: #4d2630; color: #ff9b9b; box-shadow: inset 0 0 0 1px var(--danger-fg); font-size: 10px; font-weight: 700; }
/* 取り切った宝箱・倒したボスは部屋の床に戻る(まだ在ると誤読させない) */
.mcell.is-spent {
  background: var(--rare-bg);
  color: var(--text-faint);
  box-shadow: inset 0 0 0 1px var(--rare-line);
  font-size: 12px;
  font-weight: 400;
  opacity: .7;
}

/* ★体験FB第4号・裁定キュー項目3(2026-08-10 裁定「門番の気配」):
   一度隣に立った門番のマス。**一目で他と違うと分かる**ことが要件なので、色は危険側に振り、
   記号(門)も持たせる。踏破色にも壁にも負けないよう、描画の優先順はJS側が持つ。
   隠し部屋のボス(.v-hidden_boss)と同系色にしてあるのは「ここには主が居る」という
   語彙を1つに保つため — 別の色を足すと、凡例で覚える色がまた1つ増える */
.mcell.v-boss {
  background: #5a2530;
  color: #ffc2c2;
  box-shadow: inset 0 0 0 2px var(--danger-fg);
  font-size: 11px;
  font-weight: 700;
}

/* 討った後。関門だった印は残すが、もう待ってはいない(.is-spent と同じ「決着済み」の語彙)。
   ★体験FB第6号の検証走行: 沈め方が強すぎて「門」がほぼ見えず、初心者に
   「門番を倒したマスから赤い『門番』マークが消えてオレンジ枠のCPだけになっている。
    凡例には門番が残っているのに、地図の見た目と説明が食い違って見える」(手番53)と読まれた。
   **関門だった印は残す**が裁定の中身なので、地の全体opacityで文字ごと薄めるのをやめ、
   文字は読める明度(--text-dim)に上げる。背景と枠の「沈んだ」語彙は変えない */
.mcell.v-boss.is-spent {
  background: var(--map-floor);
  color: var(--text-dim);
  box-shadow: inset 0 0 0 1px var(--danger-line);
  font-weight: 400;
  opacity: 1;
}

/* ★体験FB第4号・裁定キュー項目5(2026-08-10 裁定「地形の持ち越し」):
   前の滞在までに歩いた道。裁定どおり**既存の踏破色を一段沈めるだけ**で、凝った描き分けは
   しない — 分かればよいのは「ここは前に通った / 今回はまだ通っていない」の1点だけ */
.mcell.is-past { opacity: .45; }

/* 押すとそこまで自動で歩くマス(2026-08-10 裁定・項目8)。
   色は変えない — 踏破色そのものが「知っている道」の意味で、押せることは指の側の話 */
.mcell.is-walkable { cursor: pointer; }
.mcell.is-walkable:active { filter: brightness(1.25); }

/* 直近のチェックポイント(敗北時の送還先)。金の輪で常に見つけられるように */
.mcell.is-last-cp { outline: 2px solid var(--reward-fg); outline-offset: -1px; }

/* ---- プレイヤートークン: マス一杯 + 最後に動いた向き
   小さい点だと、7×7の中で自分がどこに居るかを毎回探すことになる */
.mcell.is-current {
  background: var(--normal-fg);
  color: #0b0d12;
  box-shadow: 0 0 0 2px var(--normal-glow), inset 0 0 0 1px #cfe2ff;
  z-index: 1;
}
.mcell.is-current .facing { display: block; color: #0b0d12; }
.mcell.is-current .facing .svgico { display: block; }

/* ★体験FB第6号「重ねず並べて出せば済む話」(上級者・手番100): 1マスに記号が2つ要る時の
   逃がし場所。主の記号(向きの三角・門)はそのままに、押し出された方を角へ small に置く。
   ここに載るのは**既に盤面のどこかで説明されている記号だけ**(入口E・CP・階段・門)なので、
   凡例に新しい項目は増えない */
.mcell > .cell-mark {
  position: absolute;
  right: 1px;
  bottom: 1px;
  font-size: 9px;
  line-height: 1;
  font-weight: 700;
  pointer-events: none;
}
/* 門番のマスが兼ねているチェックポイント。倒れた時の送還先なので、凡例のCPと同じ金で言う。
   赤地の上で9pxが沈まないよう、地の色で縁を1周させる。
   2026-08-26 裁定でCは**常時併記**になった(踏破・現在地に依存しない) */
.mcell.v-boss:not(.is-current) > .cell-mark {
  color: var(--reward-fg);
  text-shadow: 0 0 2px #5a2530, 0 0 2px #5a2530;
}
/* 門番マスに立った手番だけ角が2つ要る(常駐のC=右下 + 押し出された門=左上) */
.mcell > .cell-mark.at-tl {
  right: auto;
  bottom: auto;
  left: 1px;
  top: 1px;
}
/* 現在地のトークンは明るい地なので、角の印は常に黒(マスの種別によらず) */
.mcell.is-current > .cell-mark { color: #0b0d12; }

/* 凡例は**実際のマスの見た目をそのまま**小さく並べる(色見本の再発明をしない) */
.map-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  font-size: 11px;
  color: var(--text-faint);
  margin-top: 10px;
  justify-content: center;
}
.map-legend span { display: inline-flex; align-items: center; gap: 4px; }
.map-legend .mcell {
  --mcell: 13px;
  border-radius: 3px;
  font-size: 8px;
  flex: 0 0 auto;
}
/* 凡例の角の小印(門番のC)。13pxのマスに9pxでは溢れるので一段落とす */
.map-legend .cell-mark { font-size: 6px; right: 0; bottom: 0; }

/* 凡例の下の一行(チェックポイントが何をしてくれる場所か)。凡例と同じ小ささで、
   マップの枠の中に収める — 地図の読み方の説明は地図の側に置く */
.map-note {
  font-size: 11px;
  color: var(--text-faint);
  text-align: center;
  margin-top: 6px;
  line-height: 1.5;
}

/* ---- D-pad: マップ直下にコンパクトな4方格子 */
.dpad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 4px;
  width: min(168px, 56%);
  margin: 0 auto 12px;
}
.dpad button {
  aspect-ratio: 1 / 1;
  min-height: 0;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9px;
  background: var(--bg-raise);
  border-color: var(--line);
  color: var(--text);
}
.dpad button:active { background: var(--normal-bg); border-color: var(--normal-line); }
/* 進めない方向はその場で分かる。押せてしまうと「行けるのに弾かれた」と読める */
.dpad button:disabled {
  opacity: 1;
  background: none;
  border-color: var(--line-soft);
  border-style: dashed;
  color: #333a48;
}
.dpad .spacer { visibility: hidden; }
.dpad .n { grid-area: 1 / 2; }
.dpad .w { grid-area: 2 / 1; }
.dpad .e { grid-area: 2 / 3; }
.dpad .s { grid-area: 3 / 2; }
.dpad .c { grid-area: 2 / 2; }

.bag-list { display: flex; flex-wrap: wrap; gap: 6px; }

.stamina-block {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--bg-sunken);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 12px;
  margin-bottom: 12px;
}
.stamina-block.is-blocked { border-color: var(--danger-line); }
/* 探索画面のスタミナは1行に畳んだ(★体験FB第7号・十字キーが画面外に出ていた)。
   街の .stamina-block はそのまま — あちらは折り返しに余裕があり、
   「持ち出せるか」を出発前に見る場所でもある */
.stamina-line { margin: 0 0 8px; }
.stamina-block .big { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; }
.stamina-block .blocked-label { color: var(--danger-fg); font-weight: 700; font-size: 15px; }

/* ------------------------------------------------------- Battle stage */

.battle { display: flex; flex-direction: column; gap: 6px; }

.battle-side-label {
  font-size: 11px;
  color: var(--text-faint);
  letter-spacing: .1em;
  text-align: center;
}

.bgrid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 5px;
  align-items: stretch;
}

.bcell {
  position: relative;
  background: var(--bg-sunken);
  border: 1px solid var(--line-soft);
  border-radius: 7px;
  padding: 5px 6px;
  min-height: 58px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  font-size: 11px;
  line-height: 1.25;
  transition: box-shadow .12s, border-color .12s, opacity .2s;
}

/* 戦闘再生カードの顔サムネ(絵の第四弾)。切り出しの数字は tachie.js(FACE_CENTER・FACE_WINDOW)
   が全部の器に共通で持つ — 同じ絵の同じ顔が、名簿でも盤面でも同じ位置に出る。
   カードは3列で幅が細いので、絶対配置で**左端に寄せて**本文の行組みには触らない
   (行の中へ入れると、名前・作戦・HPの3行が顔の高さに引きずられる) */
.bcell.has-face { padding-left: 30px; }
/* .tachie-face を後ろに読ませないため、合成側と同じ強さで position を上書きする */
.bface.tachie-face {
  position: absolute;
  left: 4px;
  top: 50%;
  transform: translateY(-50%);
  border-radius: 5px;
}

/* 敵は**同じ絵に敵側トーン**(絵仕様書v1 §1・敵専用絵は描かない)。
   赤縁 + 彩度落としで、盤面のどちら側かを絵だけでも読ませる */
.bface.is-foe {
  filter: saturate(.35) brightness(.82);
  border-color: var(--danger-line);
  box-shadow: 0 0 0 1px var(--danger-line);
}

/*
 * 空マスは**行ごと薄く畳む**。3×3を同じ大きさで9枚描くと、居ないマスが
 * 盤面の2/3を占めて縦に間延びする。min-height を落としておけば、
 * 空だけの行はその高さまで縮み、ユニットの居る行が自然に主役になる。
 */
.bcell.empty {
  border-style: dashed;
  border-color: var(--line-soft);
  background: none;
  opacity: .3;
  min-height: 14px;
  padding: 0;
}

.bcell .nm { font-weight: 600; font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: flex; align-items: center; gap: 4px; }
.bcell .nm .svgico { flex: 0 0 auto; opacity: .85; }
.bcell .nm .t { overflow: hidden; text-overflow: ellipsis; }
.bcell .tc { color: var(--text-faint); font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bcell .hp { font-size: 10px; color: var(--text-dim); font-variant-numeric: tabular-nums; }

/* 敵味方を縁の色で言う。名前だけの灰カードだと、どちらが自軍か毎回読む必要がある */
.bcell.side-mine { box-shadow: inset 3px 0 0 var(--normal-line); }
.bcell.side-foe  { box-shadow: inset 3px 0 0 var(--danger-line); }

.hpbar { height: 4px; background: #0b0d12; border-radius: 999px; overflow: hidden; }
.hpbar > i { display: block; height: 100%; background: var(--heal-fg); border-radius: 999px; transition: width .18s linear; }
.hpbar.low > i { background: var(--reward-fg); }
.hpbar.crit > i { background: var(--danger-fg); }

/* 場外(街・編成・探索)のHPバー行(HP持ち越し・裁定A)。戦闘再生と同じ配色規則 */
.hp-row { display: flex; align-items: center; gap: 8px; font-size: 12px; }
.hp-row .nm { min-width: 6.5em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
.hp-row .bar { flex: 1; min-width: 60px; }
.hp-row .hpv { font-size: 11px; color: var(--text-dim); font-variant-numeric: tabular-nums; white-space: nowrap; }
.hp-row .eta { font-size: 10px; color: var(--text-faint); white-space: nowrap; }

/* 探索中だけ使う、行内に畳んだレベル(2026-08-10 体験FB第5号)。
   街の部隊カードは副行(.hp-sub)のままで、そちらは「次のLvまで」「未振り」も出す */
.hp-row .lv {
  font-size: 10.5px;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* 街・探索の部隊カードのバーは太く。遠目で「まだ戦えるか」を測る道具 */
.hp-row.thick .hpbar { height: 8px; }
.hp-row.thick .nm { font-size: 12.5px; }

/* 成長の副行(2026-08-09 体験FB第4号)。HPの1行の下に、次のレベルまでと振り忘れを置く。
   名前の幅(.nm と同じ)だけ字下げして、どの個体の話かを線で追わせない */
.hp-unit + .hp-unit { margin-top: 3px; }

/* 街の部隊カードの行頭に置く顔(絵の第二弾の立ち絵を顔だけ拡大トリミング)。
   立ち絵は胸像で顔が上部中央(縦3割・横やや左)にあるので、240%へ拡大してそこを器の中心へ寄せる。
   立ち絵の無い職は .blank の空箱で桁だけ揃え、全行の名前とバーの開始位置を揃える */
.hp-unit.with-face { display: flex; align-items: center; gap: 10px; }
/* 顔が入ると行の背が高いので、見出しの直下と行間を空ける(.rows の gap 2px と足して約10px)。
   顔なしの名簿(探索・編成)の詰め具合は変えたくないので with-face 限定 */
.rows > .hp-unit.with-face:first-child { margin-top: 8px; }
.hp-unit.with-face + .hp-unit.with-face { margin-top: 8px; }
.hp-unit.with-face .hp-unit-main { flex: 1; min-width: 0; }
/* 顔の切り出し(位置・倍率)はここに無い — 2026-08-23 の合成化で tachie.js の tachieFace
   (FACE_CENTER・FACE_WINDOW)に移った。旧1枚絵向けの background-size/position は
   新素体(2026-09-07)で数が合わなくなったので、迷い先にならないよう外した */
.hp-face {
  width: 32px;
  height: 32px;
  flex: none;
  border-radius: 7px;
  border: 1px solid var(--line-soft);
}
.hp-face.blank { border-color: transparent; }

/* 名簿の行 + その場で使える1ボタン(2026-08-12・探索中の携行薬)。
   行の中身は今までどおりの幅を使い、ボタンぶんだけ右に寄る。
   ボタンの44pxを引くと1行に収まらなくなるので、行の中は**折り返させる** —
   「全快まで○分」は削らない(待つのも選択肢のうちで、薬を使う判断の対になる材料) */
.party-row { display: flex; align-items: center; gap: 8px; }
.party-row > :first-child { flex: 1; min-width: 0; }
.party-row .hp-row { flex-wrap: wrap; row-gap: 2px; }
.party-row .potion-use { flex: 0 0 auto; min-width: 44px; padding: 6px 8px; }

/* 部隊カードの見出しだけは品名を折り返さない。所持数の札を足したぶんで
   「部 / 隊」と縦に割れると、カードの主語が読めなくなる。
   他のカード(長いステージ名等)は今までどおり折り返す — あちらは折り返る方が正しい */
.card-head.party-head .name { white-space: nowrap; }
.hp-sub {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px 10px;
  margin: 0 0 0 calc(6.5em + 8px);
  font-size: 10.5px;
  line-height: 1.3;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}
/* 副行のタグは行の高さを増やさない。マップは既に「小さい」と言われている場所で、
   ここが太るぶんだけ盤面が下へ押し出される */
.hp-sub .tag {
  padding: 0 5px;
  font-size: 10px;
  line-height: 15px;
  border-radius: 7px;
}

.bcell.is-actor {
  border-color: var(--normal-fg);
  box-shadow: 0 0 0 2px var(--normal-glow), inset 3px 0 0 var(--normal-fg);
}
.bcell.is-target {
  border-color: var(--danger-fg);
  box-shadow: 0 0 0 2px var(--danger-glow);
  animation: hitshake .32s ease-out;
}
.bcell.is-heal {
  border-color: var(--heal-fg);
  box-shadow: 0 0 0 2px var(--heal-glow);
  animation: healpulse .5s ease-out;
}
.bcell.is-dead { opacity: .3; }

@keyframes hitshake {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-4px); }
  35% { transform: translateX(4px); }
  55% { transform: translateX(-3px); }
  75% { transform: translateX(2px); }
}
@keyframes healpulse {
  0%   { background-color: rgba(95, 211, 160, .28); }
  100% { background-color: transparent; }
}

/* 技の絵と再生速度に連動する動きは fx.css。 */

/* ダメージ・回復量。技の絵より手前に表示する。 */
.bcell .pop {
  font-size: 19px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  text-align: center;
  line-height: 1.1;
  letter-spacing: -.02em;
  animation: popin .28s cubic-bezier(.2, 1.5, .4, 1);
}
.bcell .pop.dmg  { color: var(--danger-fg); text-shadow: 0 0 12px var(--danger-glow); }
.bcell .pop.heal { color: var(--heal-fg);   text-shadow: 0 0 12px var(--heal-glow); }

/* ダメージの数字だけは**大きく弾んで落ちる**。回復は静かなままでよい —
   同じ動きを両方に付けると、痛い手番と助かった手番の区別が動きから消える */
.bcell .pop.dmg { animation: fxpopdrop .36s cubic-bezier(.18, 1.4, .35, 1) both; }
@keyframes fxpopdrop {
  0%   { transform: scale(.4) translateY(-7px); opacity: 0; }
  34%  { transform: scale(1.34) translateY(0);  opacity: 1; }
  62%  { transform: scale(1.02) translateY(3px); }
  100% { transform: scale(1) translateY(0);     opacity: 1; }
}

@keyframes popin {
  from { transform: scale(.5) translateY(6px); opacity: 0; }
  to   { transform: scale(1) translateY(0); opacity: 1; }
}

.battle-mid {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  color: var(--text-faint);
  margin: 1px 0;
}
.battle-mid hr { flex: 1 1 auto; border: 0; border-top: 1px solid var(--line-soft); }

/* 行動主と、いま何をしたかの1行ティッカー。盤面のハイライトだけだと
   「誰が動いたか」は分かっても「何をしたか」が落ちる */
.battle-ticker {
  min-height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  font-size: 13px;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--bg-sunken);
  border: 1px solid var(--line-soft);
  color: var(--text-dim);
  text-align: center;
}
.battle-ticker .who { font-weight: 700; color: var(--text); }
.battle-ticker .act { color: var(--normal-fg); font-weight: 600; }
.battle-ticker.is-foe .who { color: #ffb3b3; }
.battle-ticker:empty { visibility: hidden; }

.battle-log {
  background: var(--bg-sunken);
  border: 1px solid var(--line-soft);
  border-radius: 8px;
  padding: 8px 10px;
  height: 84px;
  overflow-y: auto;
  overscroll-behavior: contain;
  font-size: 12.5px;
  line-height: 1.5;
  scroll-behavior: smooth;
}
.battle-log .line { color: var(--text-faint); padding: 1px 0; }
.battle-log .line.cur { color: var(--text); }
.battle-log .line .cyc { color: var(--text-faint); font-size: 11px; margin-right: 5px; font-variant-numeric: tabular-nums; }
.battle-log .line em { font-style: normal; color: var(--normal-fg); }
.battle-log .line b  { color: var(--danger-fg); font-weight: 700; }
.battle-log .line .hl { color: var(--heal-fg); }

.battle-controls { display: flex; gap: 6px; align-items: center; }
.battle-controls button { flex: 1 1 0; font-size: 13px; padding: 9px 6px; min-height: 42px; }
.battle-controls .prog { flex: 0 0 auto; font-size: 11px; color: var(--text-faint); font-variant-numeric: tabular-nums; min-width: 56px; text-align: right; }

.result-banner {
  text-align: center;
  padding: 12px;
  border-radius: var(--radius);
  font-weight: 700;
  font-size: 17px;
  margin: 4px 0;
}
.result-banner.win  { background: var(--heal-bg);   color: var(--heal-fg);   box-shadow: inset 0 0 0 1px var(--heal-line); }
.result-banner.lose { background: #3a1e1e; color: var(--danger-fg); box-shadow: inset 0 0 0 1px var(--danger-line); }

/* ----------------------------------------------------------- Overlays */

.overlays { position: relative; z-index: 50; }

.overlay {
  position: fixed;
  inset: 0;
  /* 背後を確実に沈める。パネル側と2段の明度差を作るのが目的 */
  background: var(--scrim);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 0;
  animation: fade .14s ease-out;
  /* 自分をスクロール容器にして、行き場のないホイールを外へ渡さない
     (背後の .screen を動かさないのは、これと position:fixed の2枚で足りる) */
  overflow: hidden;
  overscroll-behavior: contain;
}
@keyframes fade { from { opacity: 0; } }

.overlay-panel {
  /* **不透明**かつページ地色より明るい面。ここが --bg のままだと、
     暗くした地の上に同色の板が乗るので「背景が無い」ように見える */
  background-color: var(--surface);
  width: 100%;
  max-width: 560px;
  max-height: 92dvh;
  border-radius: 14px 14px 0 0;
  border-top: 1px solid var(--surface-line);
  box-shadow: 0 -8px 40px rgba(0, 0, 0, .55);
  display: flex;
  flex-direction: column;
  animation: rise .18s ease-out;
  overscroll-behavior: contain;
}
@keyframes rise { from { transform: translateY(18px); } }

.overlay.center-mode { align-items: center; padding: 16px; }
.overlay.center-mode .overlay-panel {
  border-radius: 14px;
  border: 1px solid var(--surface-line);
  max-height: 86dvh;
  box-shadow: 0 12px 48px rgba(0, 0, 0, .6);
}

/* 全画面モード: 戦闘の自動再生・リプレイはビューポートを覆い切る。
   スクロールはパネル内部(.overlay-body)だけで起きる */
.overlay.full-mode { align-items: stretch; padding: 0; }
.overlay.full-mode .overlay-panel {
  height: 100%;
  max-height: none;
  border-radius: 0;
  border-top: 0;
  box-shadow: none;
}

/* 面の上では、地色前提の内側パーツを一段持ち上げて境界を保つ */
.overlay-panel .card { background: #2e3441; border-color: var(--surface-line); }
.overlay-panel .stat,
.overlay-panel .battle-log,
.overlay-panel .battle-ticker,
.overlay-panel .bcell,
.overlay-panel .notice { background: #1b1f28; }
.overlay-panel .bcell.empty { background: none; }
.overlay-panel button { border-color: var(--surface-line); }
.overlay-panel .btn-primary { border-color: var(--normal-line); }
.overlay-panel .btn-danger  { border-color: var(--danger-line); }

.overlay-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line-soft);
  flex: 0 0 auto;
}
.overlay-head .title { font-weight: 600; font-size: 15px; }
.overlay-head .close { margin-left: auto; min-height: 38px; padding: 6px 12px; font-size: 13px; }

.overlay-body {
  padding: 14px;
  overflow-y: auto;
  overscroll-behavior: contain;
  flex: 1 1 auto;
  padding-bottom: calc(20px + var(--safe-b));
}

/*
 * 戦闘再生(全画面)は「盤面は縮まない / ログが余りを吸う / 操作列は常に底」。
 *
 * 盤面の高さは中身で決まるので、余白の受け皿を**行動ログ**にする。こうすると
 * 短い画面でも操作列が最後に来て、スキップに手が届かない事故が起きない。
 * それでも溢れる極端な画面のために、操作列は sticky で底に貼り付けておく。
 *
 * 再生の中身は expedition 側で1枚 div に包まれて渡ってくるので、
 * 器 → 包み → .battle の3段に高さを通す。
 */
.overlay.full-mode .overlay-body { display: flex; flex-direction: column; }
.overlay.full-mode .overlay-body > * { flex: 0 0 auto; }
/* 「伸びるが**縮まない**」。縮ませると中身が器から溢れて、結果カードが
   盤面に重なる(伸ばすのは余白を配るためで、詰めるためではない) */
.overlay.full-mode .overlay-body > :first-child {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}
.overlay.full-mode .battle { flex: 1 0 auto; }
/* 盤面・ティッカー・結果は**縮ませない**(縮むとカードが潰れて重なる)。
   余りを引き受けるのは行動ログだけ — この1行が後に来る順序に意味がある */
.overlay.full-mode .battle > * { flex: 0 0 auto; }
/* 起点は既定の高さのまま、余った分だけ伸ばす。basis を auto にすると
   「全ログ行ぶんの高さ」が起点になって、スクロールする箱でなくなる */
.overlay.full-mode .battle-log { flex: 1 1 84px; min-height: 64px; }

.overlay.full-mode .battle-controls {
  position: sticky;
  bottom: calc(-1 * var(--safe-b));
  padding: 6px 0 calc(4px + var(--safe-b));
  background: var(--surface);
}

/* ------------------------------------------------------------ Toasts */

.toasts {
  position: fixed;
  left: 0; right: 0;
  bottom: calc(var(--nav-h) + 16px + var(--safe-b));
  z-index: 80;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  pointer-events: none;
  padding: 0 16px;
}

.toast {
  background: #2b303c;
  border: 1px solid var(--line);
  color: var(--text);
  border-radius: 999px;
  padding: 9px 16px;
  font-size: 13px;
  max-width: 100%;
  animation: fade .14s ease-out;
  box-shadow: 0 4px 18px rgba(0, 0, 0, .4);
}
.toast.err  { background: #48262a; border-color: var(--danger-line); }
.toast.good { background: var(--heal-bg); border-color: var(--heal-line); }
/* 門番の気配(2026-08-10 裁定)。err ほど強くない「身構えろ」の色 = 注意の金 */
.toast.warn { background: var(--reward-bg); border-color: var(--reward-line); }

/* ------------------------------------------------------- Settlement */

.settle-stage { animation: fade .2s ease-out; }
.settle-step-label { font-size: 12px; color: var(--text-faint); letter-spacing: .08em; margin-bottom: 4px; }
.settle-title { font-size: 19px; font-weight: 700; margin: 0 0 12px; }
.settle-tap { text-align: center; color: var(--text-faint); font-size: 12px; margin-top: 18px; }

.loot-line { display: flex; align-items: baseline; gap: 8px; padding: 5px 0; border-bottom: 1px solid var(--line-soft); font-size: 14px; }
.loot-line .amt { margin-left: auto; font-variant-numeric: tabular-nums; font-weight: 600; }

/* --------------------------------------------------------- Utilities */

.stack  { display: flex; flex-direction: column; gap: 10px; }
.hstack { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.spacer { flex: 1 1 auto; }
.mt  { margin-top: 12px; }
.mt2 { margin-top: 22px; }
.mb0 { margin-bottom: 0; }
.nowrap { white-space: nowrap; }

.spinner {
  width: 26px; height: 26px;
  border: 2px solid var(--line);
  border-top-color: var(--normal-fg);
  border-radius: 50%;
  margin: 40px auto;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* PC は同レイアウトの拡大(画面仕様v1.1 §0)。カラムを増やさない。
   死に幅は body::before の地の装飾が受け持ち、列だけを少し広げて余白を設計する */
@media (min-width: 640px) {
  html, body { font-size: 17px; }
  :root { --mcell: 32px; }
  #app { max-width: 620px; }
  .screen { padding-left: 22px; padding-right: 22px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ==================================================== 絵の導入(第一弾) */
/* 生成絵は「看板・帯」の形でだけ使い、情報パネルの構造には触れない。
   絵の下端をページ地色へ溶かすグラデーションは、暗部の絵と UI の境目が
   線で切れると安く見えるための処置 */

.stage-banner {
  height: 88px;
  margin: -14px -14px 10px;             /* .card の padding(14px) いっぱいまで広げる */
  border-radius: var(--radius) var(--radius) 0 0;
  background-size: cover;
  background-position: center 42%;
  border-bottom: 1px solid var(--line-soft);
  /* 看板はドット調素材(第二世代)。地図記号と同じく NEAREST 側 — 滲むとドットの意味が消える */
  image-rendering: pixelated;
}

.town-art {
  height: 128px;
  border-radius: var(--radius);
  border: 1px solid var(--line-soft);
  background-image:
    linear-gradient(180deg, rgba(20, 22, 28, 0) 55%, rgba(20, 22, 28, .82)),
    url('img/town_band.png');
  background-size: cover;
  background-position: center 45%;
  margin: 2px 0 12px;
}

/* 闘技場のヘッダ帯。街の帯(.town-art)と**同じ寸法・同じ暗幕**にしてあるのは、
   街と闘技場が同じ階層の場所だと形で言うため(片方だけ大きいと主従が生まれる) */
.arena-art {
  height: 128px;
  border-radius: var(--radius);
  border: 1px solid var(--line-soft);
  background-image:
    linear-gradient(180deg, rgba(20, 22, 28, 0) 55%, rgba(20, 22, 28, .82)),
    url('img/arena_band.png');
  background-size: cover;
  background-position: center 45%;
  margin: 2px 0 12px;
}

/* ステージ固有の地色 — 看板の色が地図の床・壁へ流れる。
   構造(3段の明度差・斜線の壁)は共通のまま、色温度だけをステージで変える。
   --map-tile はそのステージの床の地紋(踏破済みの床にだけ薄く敷く。下の .map > .mcell) */
.map-wrap.theme-normal_01_gate {
  --map-floor:       #4a4331;
  --map-floor-e:     #6d6349;
  --map-wall:        #242015;
  --map-wall-e:      #5a513a;
  --map-ghost-floor: #2c2a1f;
  --map-ghost-wall:  #1c1912;
  --map-ghost-wall-e:#4a4331;
  --map-tile: url('img/tiles/tile_gate.png');
}
.map-wrap.theme-normal_02_ruins {
  --map-floor:       #3a4a68;
  --map-floor-e:     #55678e;
  --map-wall:        #171e2d;
  --map-wall-e:      #48597c;
  --map-ghost-floor: #232c3f;
  --map-ghost-wall:  #151b29;
  --map-ghost-wall-e:#3c4d6c;
  --map-tile: url('img/tiles/tile_ruins.png');
}
/* 淀みの空洞(苔緑)。看板 banner_normal_03_hollow の色をそのまま床・壁へ流す */
.map-wrap.theme-danger_01_hollow {
  --map-floor:       #3b4a35;
  --map-floor-e:     #57694d;
  --map-wall:        #171e14;
  --map-wall-e:      #47593e;
  --map-ghost-floor: #242c20;
  --map-ghost-wall:  #151a13;
  --map-ghost-wall-e:#3d4d36;
  --map-tile: url('img/tiles/tile_hollow.png');
}

/* 職の立ち絵(絵の第二弾 → 2026-08-23 でパーツ合成へ)。カードの行高を壊さない小さな顔。
   寸法は合成側が付ける(整数分の1を守るため)ので、ここでは形だけを決める */
.unit-face { border-radius: 8px; align-self: center; }
.unit-face.lg { border-radius: 10px; }

/* ==================================================== 絵の第三弾 */

/* 玄関のタイトル絵。下端をページ地色へ溶かす */
.title-hero {
  height: 42vh;
  border-radius: var(--radius);
  background-image:
    linear-gradient(180deg, rgba(20, 22, 28, 0) 60%, rgba(20, 22, 28, .92)),
    url('img/title_hero.png');
  background-size: cover;
  background-position: center 30%;
  margin: 8px 0 0;
}

/* 探索ヘッダの看板帯(ステージ看板の使い回し・細く) */
.exp-banner {
  height: 52px;
  border-radius: var(--radius);
  border: 1px solid var(--line-soft);
  background-size: cover;
  background-position: center 40%;
  margin: 8px 0 2px;
  /* 看板はドット調素材(第二世代)。NEAREST 側の扱いは .stage-banner と同じ */
  image-rendering: pixelated;
}

/* 装備・消耗品の種別アイコン */
.item-ico {
  width: 20px;
  height: 20px;
  object-fit: contain;
  flex: none;
  align-self: center;
}

/* 地図記号の図像。文字記号と同じ場所に、マスの8割で置く */
.mcell-ico {
  width: 80%;
  height: 80%;
  object-fit: contain;
  display: block;
  margin: auto;
  pointer-events: none;
  /* 地図記号はドット調(第二世代・2026-08-31納品)。キャラ絵だけが滑らか縮小へ移った
     裁定(同日)の中でも、ドット調素材は NEAREST 維持の側 — 滲むとドットの意味が消える */
  image-rendering: pixelated;
}
.map-legend .mcell-ico { width: 12px; height: 12px; display: inline-block; vertical-align: -2px; }

/* HUD・手持ちの資源アイコン */
.hud-ico {
  width: 14px;
  height: 14px;
  object-fit: contain;
  vertical-align: -2px;
}

/* 街の施設の小絵(治療師・酒場・商店) */
.fac-ico {
  width: 40px;
  height: 40px;
  border-radius: 8px;
  object-fit: cover;
  flex: none;
  border: 1px solid var(--line-soft);
  align-self: center;
}

/* 勝敗バナーに結果の帯絵を敷く。文字の可読を優先して暗幕を重ねる */
.result-banner.win {
  background-image:
    linear-gradient(180deg, rgba(15, 30, 22, .62), rgba(15, 30, 22, .78)),
    url('img/band_victory.png');
  background-size: cover;
  background-position: center 45%;
}
.result-banner.lose {
  background-image:
    linear-gradient(180deg, rgba(38, 18, 18, .66), rgba(38, 18, 18, .82)),
    url('img/band_defeat.png');
  background-size: cover;
  background-position: center 45%;
}

/* 一覧カードの立ち絵は右端に大きく敷き、左へ溶かす(名簿の1行を「顔の見える隊員カード」に)。
   合成立ち絵は 1/8(106x158)の固定寸で来るので、カードの高さで下を切り落とす */
.unit-card { position: relative; overflow: hidden; }
.unit-card .unit-face-bg {
  position: absolute;
  top: -4px;
  right: 8px;
  /* 左へ溶かす + カードの底で切れる脚を下へ溶かす(硬い切り口を作らない) */
  -webkit-mask-image:
    linear-gradient(90deg, transparent 0, #000 55%),
    linear-gradient(180deg, #000 55%, transparent 100%);
  mask-image:
    linear-gradient(90deg, transparent 0, #000 55%),
    linear-gradient(180deg, #000 55%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
  pointer-events: none;
}
/* 文字が絵の不透明部に乗らないよう、右に絵のぶんの余白を取り、乗る分は影で浮かす */
.unit-card .card-head,
.unit-card .ministats,
.unit-card .hstack {
  padding-right: 72px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .85), 0 0 6px rgba(0, 0, 0, .6);
}

/* ------------------------------------------- Formation: 移動モード */

/* 移動元のマス。どれを動かしているのかが一目で分かる強調 */
.fcell.is-moving {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

/* グリッド直上の1行案内。移動モードの間だけ出る */
.move-hint {
  font-size: 11.5px;
  color: var(--accent);
  text-align: center;
  margin: 0 0 4px;
}

/* ------------------------------------------------------------ Arena
   闘技場(対人)。新しい部品は階級バッジ1つだけで、あとは既存の
   .card / .rows / .tag をそのまま使う。 */

/* 勝点の大見出し。街のスタミナ(.stamina-block)と同じ形にして、
   「その画面で一番大事な数」の置き場を揃える */
.arena-rating {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--bg-sunken);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 12px;
  margin: 8px 0;
}
.arena-rating .big { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; }

/* 勝点のアイコン。見出しの脇(18px)と順位表の行(HUDと同じ14px = .hud-ico)の2寸法。
   資源アイコン(res_*)の流儀に揃えてあるので、勝点も「持ち物の一種」として読める */
.res-ico {
  width: 18px;
  height: 18px;
  object-fit: contain;
  vertical-align: -3px;
  margin-right: 3px;
}

/* 階級バッジ。**絵の差し込み場所**(絵は後段) —
   画像が入れば図像、無ければ枠の中の1文字で出る(立ち絵と同じ落とし方)。
   img が読めなければ JS 側が要素ごと畳むので、文字だけが残る */
.tier-badge {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  flex: none;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--bg-sunken);
  overflow: hidden;
}
.tier-badge img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.tier-badge-text {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-dim);
}
/* 絵が入ったら文字は下に隠れる(img が上に乗る) */
.tier-badge.is-silver .tier-badge-text { color: var(--band-rare-fg); }
.tier-badge.is-gold .tier-badge-text,
.tier-badge.is-crown .tier-badge-text { color: var(--reward-fg); }

/* 順位表の自分の行。名簿の中から自分を探す手間を消す */
.row.is-me { color: var(--accent); font-weight: 700; }
.row.is-me .k { color: var(--accent); }

/* ==================================================== 立ち絵の合成(2026-08-23) */

/* パーツ合成の土台。同寸のレイヤーを z順に(0,0)へ重ねるだけ。
   縮小は**滑らか**(2026-08-31 ユーザー裁定)。キャラ絵は滑らかな2D素材なので、
   NEAREST で縮めるとドット化ではなくただのジャギーになる — 「整数分の1 + NEAREST」の
   縛りはドット調素材(タイル・地図記号・看板・アイコン)の側にだけ残る */
.tachie-stack { position: relative; flex: none; }
.tachie-layer {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* 顔サムネの器。中の立ち絵を顔の中心で切り出す(はみ出しは隠す) */
.tachie-face {
  position: relative;
  overflow: hidden;
  flex: none;
  border-radius: 7px;
  border: 1px solid var(--line-soft);
  background: var(--bg-sunken);
}
.tachie-face.blank { border-color: transparent; background: none; }
/* 色帯の縁(既存の .hp-face / .unit-face と同じ規則) */
.tachie-face.band-rare   { box-shadow: 0 0 0 2px var(--band-rare-line); }
.tachie-face.band-epic   { box-shadow: 0 0 0 2px var(--band-epic-line); }
.tachie-face.band-legend { box-shadow: 0 0 0 2px var(--band-legend-fg); }

/* 敵は同じ絵に敵側トーン(絵仕様書v1 §1・敵専用絵は描かない) */
.tachie-face.is-foe {
  filter: saturate(.35) brightness(.82);
  border-color: var(--danger-line);
  box-shadow: 0 0 0 1px var(--danger-line);
}

/* 盤面の顔チップ(30x30・1/16 固定)。マスの中央へ置く */
.tachie-chip { position: relative; }
.mcell .tachie-chip {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -54%);
  pointer-events: none;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .55));
}

/* 外見の選び直し(街)。素体2つ + 髪型8つを並べるだけの小さな面 */
.appearance-picker { display: flex; flex-wrap: wrap; gap: 6px; }
.appearance-picker .btn-sm.is-on {
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 700;
}

/* 編成マスの顔(2026-08-23)。名前より先に「誰を置いたか」を読ませる小さな顔 */
.fcell .fcell-face { margin-bottom: 1px; border-radius: 6px; }

/* 街の主役 = 司令官の全身立ち絵(2026-08-23)。夜の街の帯を背にして常時立つ。
   人物を縮小しても街の背景の高さは維持する */
.town-hero {
  height: 175px;
  box-sizing: border-box;
  position: relative;
  display: flex;
  justify-content: center;
  align-items: flex-end;
  border-radius: var(--radius);
  border: 1px solid var(--line-soft);
  overflow: hidden;
  margin: 2px 0 12px;
  background-image:
    linear-gradient(180deg, rgba(20, 22, 28, 0) 50%, rgba(20, 22, 28, .88)),
    url('img/town_band.png');
  background-size: cover;
  background-position: center 40%;
}
@media (min-width: 640px) and (min-height: 1000px) {
  .town-hero { height: 247px; }
}
.town-hero .commander-figure { margin-bottom: 0; }

/* 窓(オーバーレイ)が開いている間は街の立ち絵を消す(2026-08-31)。
   見た目変更窓のプレビューと、緞帳越しに透ける街の立ち絵が同じ位置に重なって
   「窓が半透明」に見えていた — 窓のパネル自体は不透明(--surface)なので、
   遮蔽するのは緞帳の側で透けている本人だけでよい。夜の街の帯は残す(場所の気配は保つ) */
body.has-overlay .town-hero .commander-figure { visibility: hidden; }

/* 外見選択(開始直後・2026-08-31 裁定)。玄関と同じ1カラムの面にプレビューを据える */
.appearance-stage {
  display: flex;
  justify-content: center;
  margin: 10px 0 6px;
}

