:root {
  color-scheme: dark;
  --bg: #0e1416;
  --panel: #182124;
  --panel-2: #202d30;
  --panel-3: #26383a;
  --line: #3a4d4f;
  --ink: #edf3ed;
  --muted: #9eada7;
  --gold: #e5b869;
  --gold-dark: #392f1e;
  --good: #9bd69e;
  --bad: #e78980;
  --blue: #91cbd5;
  --violet: #c0a7e5;
  --orange: #e5a26b;
  --hp-green: var(--good);
  --hp-green-light: #c8e8ca;
  --hp-green-dark: #356d3d;
  --hp-yellow: var(--gold);
  --hp-yellow-light: #f3d99b;
  --hp-yellow-dark: #765c28;
  --hp-red: var(--bad);
  --hp-red-light: #f1b6ae;
  --hp-red-dark: #713936;
  --hp-main: var(--hp-green);
  --hp-recovered-tone: var(--hp-green-light);
  --hp-recoverable-tone: var(--hp-green-dark);
  --hp-unrecoverable: #080c0d;
  --tree-col-width: 208px;
  --tree-col-gap: 46px;
  /* 反応の時間と曲線（issue #237）。**段は四つしかない。迷ったら短い方を使う。**
     --fx-tap    押した指への返事（押しているあいだだけ）
     --fx-quick  選ぶ・切り替える（結果はもう画面に出ている）
     --fx-step   画面や段が入れ替わる
     --fx-accent 得た・失った・変わった（数と色が同時に動く）
     曲線は戦闘の手応え（unit-hit / banner-word）と同じものを使い、
     キャンプと戦闘で**同じ速さの世界**に見せる。 */
  --fx-tap: 90ms;
  --fx-quick: 170ms;
  --fx-step: 260ms;
  --fx-accent: 460ms;
  --fx-ease: cubic-bezier(.2, .85, .3, 1);
}
* { box-sizing: border-box; }
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/*
 * 画面は操作対象であり、文章を読む画面ではない。
 * 文字を選べるのは、通常の会話本文・会話履歴と、実際に入力する欄だけにする。
 * ここを `.vn-text` のような汎用クラスで許可すると、巻き戻し演出や新しいモーダル
 * に同じクラスを使ったとき選択が復活するので、許可対象は `story-copy` に絞る。
 * pinch zoom は viewport 設定と touch-action の両方で抑止する。
 */
html,
body,
#app,
#app * {
  touch-action: pan-x pan-y;
}
html,
body,
#app,
#app * {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
#app .story-copy,
#app .story-copy *,
#app input,
#app input *,
#app textarea,
#app textarea *,
#app select,
#app [contenteditable="true"],
#app [contenteditable="true"] * {
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}
body {
  margin: 0;
  min-height: 100vh;
  background: radial-gradient(circle at 72% -10%, #2b4445 0, var(--bg) 48%);
  color: var(--ink);
  font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Hiragino Sans", sans-serif;
}
button, textarea, select { font: inherit; }
button { color: inherit; cursor: pointer; }
button:disabled { opacity: .38; cursor: not-allowed; }
.shell {
  width: min(100%, 720px);
  margin: 0 auto;
  padding: 18px 14px calc(30px + env(safe-area-inset-bottom));
}
.header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 4px 2px 16px;
}
.kicker, .eyebrow {
  margin: 0 0 4px;
  color: var(--gold);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .15em;
}
h1, h2, h3, p { margin-top: 0; }
h1 { margin-bottom: 3px; font-size: 28px; letter-spacing: -.045em; }
h2 { margin-bottom: 8px; font-size: 20px; }
h3 { margin-bottom: 7px; font-size: 13px; color: var(--muted); }
.subtitle, .muted, .hint { color: var(--muted); }
.subtitle { margin: 0; }
.hint { margin: 12px 0 0; font-size: 12px; }
.centered { text-align: center; }
.card {
  margin-bottom: 12px;
  padding: 17px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: linear-gradient(145deg, rgba(32, 45, 48, .97), rgba(21, 29, 31, .97));
  box-shadow: 0 12px 30px rgba(0,0,0,.16);
}
/*
 * タイトル画面。**この画面には情報が無い。**だから、置けるものは
 * 「表題の組み方」「余白」「一筋の罫」「押せる三つ」しかない。
 * 以前は ◈ を大きく置いて表題を一行で書いていたが、記号は意味を持たないので
 * 大きいほど安く見える。記号を外し、表題そのものを図像として組む。
 * 画像は使わない。空気は CSS の層だけで作り、起動に読み込み待ちを足さない。
 */
.title-shell {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

/* 画面いっぱいの空気。タイトルを出しているあいだだけ存在する。 */
/* 画は `analysis/art-web-assets.py` が原本から作る1枚（約 250KB）で、上3割は
   透明の余白（表題の場所）である。**画は下端に置き、画面いっぱいには広げない。**
   cover で広げると電話では顔だけに寄ってしまい、品書きが顔の上に乗る。
   **読み終わるまで出さない。**途中の帯だけが見えるのは、読み込み中の見た目として
   汚い（`html.title-art-ready` が付くまで透明のまま待ち、付いたら一度だけ現れる）。 */
.title-air {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: var(--bg);
}

.title-air::before {
  content: "";
  position: absolute;
  inset: 0;
  background: url("art/title-cast.webp") center bottom / auto 58% no-repeat;
  /* **絵は幕の向こうに置く。**わずかにぼかして彩度を落とすと、顔が最初に目を引かなくなる
     （はっきり写っていると、題より先に顔へ視線が行く。作者指摘 2026-09-13）。 */
  filter: blur(1.1px) saturate(.85);
  opacity: 0;
  transition: opacity .7s ease-out;
}

.title-art-ready .title-air::before { opacity: 1; }

/* 文字を読ませるための幕。上の光と、左右の切り口消しと、下へ落ちる暗がり。 */
.title-air::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    /* 題の高さに、弱い明かりを一つ置く。**画面で最初に見るのはここ。** */
    radial-gradient(78% 30% at 50% 15%, rgba(145, 203, 213, .16) 0, rgba(145, 203, 213, 0) 100%),
    linear-gradient(90deg,
      rgba(10, 15, 17, .92) 0,
      rgba(10, 15, 17, 0) 15%,
      rgba(10, 15, 17, 0) 85%,
      rgba(10, 15, 17, .92) 100%),
    linear-gradient(180deg,
      rgba(10, 15, 17, .86) 0,
      rgba(10, 15, 17, .72) 30%,
      rgba(10, 15, 17, .62) 56%,
      rgba(10, 15, 17, .40) 74%,
      rgba(6, 10, 11, .42) 100%);
}

.title-header {
  display: block;
  flex: 0 0 auto;
  padding: clamp(40px, 11vh, 104px) 14px 0;
  text-align: center;
}

.title-header .subtitle:empty {
  display: none;
}

/* 表題。**題は一つの言い回しなので、一行で読ませる。**
   "One Battle Ahead" は "one step ahead" の掛けで、「次の一戦が見えている」と
   「あと一戦だけやりたい」を同時に指す。だから ahead を小さな副題へ落とすと、
   題の意味が「ONE BATTLE（一戦）」へずれる。二語を同じ大きさ・同じ太さで並べ、
   意味を担う ahead にだけ金を置く。画面が狭いときは、語のあいだで自然に折り返す。 */
.wordmark {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 0 .32em;
  margin: 0;
  text-transform: uppercase;
  line-height: 1.08;
}

.wordmark-lead,
.wordmark-tail {
  font-size: clamp(27px, 7.9vw, 54px);
  font-weight: 800;
  letter-spacing: .045em;
  /* **題を画面で一番明るいものにする。**後ろの淡い光と、下の影。 */
  text-shadow: 0 0 42px rgba(163, 214, 222, .28), 0 3px 30px rgba(0, 0, 0, .75);
}

.wordmark-lead { color: var(--ink); }
.wordmark-tail { color: var(--gold); }

/* 中身は上下の中央に置き、そのうえで**下へ余白を足して、少し上に寄せる**。
   画面の真ん中に文字列が浮くより、目線の高さに標題が来るほうが落ち着く。 */
.title-screen {
  width: min(100%, 320px);
  margin: clamp(22px, 6vh, 48px) auto 0;
  padding-bottom: clamp(16px, 5vh, 48px);
  text-align: center;
}

/* 表題と品書きのあいだの一筋。端は消す。 */
.title-rule {
  height: 1px;
  margin: 0 auto clamp(18px, 4.5vh, 30px);
  background: linear-gradient(90deg,
    rgba(229, 184, 105, 0) 0,
    rgba(229, 184, 105, .5) 50%,
    rgba(229, 184, 105, 0) 100%);
}

.title-actions {
  display: grid;
  gap: 0;
  margin: 0;
}

/* 品書きの一行。箱で囲わず、罫で分ける。**指の当たりは行全体**にする。 */
.title-entry {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 13px;
  width: 100%;
  min-height: 56px;
  margin: 0;
  padding: 17px 10px;
  border: 0;
  background: transparent;
  color: rgba(237, 243, 237, .88);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: .22em;
  text-indent: .22em;
}

.title-entry + .title-entry {
  border-top: 1px solid rgba(237, 243, 237, .08);
}

/* いま押す一つ。金の文字と、名前の左右へ添えた細い印で示す。
   印は行の端ではなく**文字のすぐ横**に置く（端に置くと、ただの傷に見える）。 */
.title-entry.lead {
  color: var(--gold);
  font-size: 15px;
}

.title-entry.lead::before,
.title-entry.lead::after {
  content: "";
  flex: 0 0 auto;
  width: 14px;
  height: 1px;
  background: var(--gold);
  opacity: .75;
}

.title-entry:disabled { color: var(--muted); }
.title-entry:disabled::before,
.title-entry:disabled::after { display: none; }

.title-entry:not(:disabled):active {
  background: rgba(229, 184, 105, .12);
}

@media (hover: hover) {
  .title-entry:not(:disabled):hover {
    background: rgba(237, 243, 237, .04);
  }
}

.title-screen .save-summary {
  margin: clamp(18px, 4vh, 28px) 0 0;
  color: var(--muted);
  font-size: 11px;
  letter-spacing: .06em;
}

/* 控えの見出しは行を分ける。**中点で繋ぐと、日付の折り返しと混ざって読めない。** */
.title-screen .save-summary span {
  display: block;
  margin-bottom: 5px;
  color: var(--gold);
  font-size: 10px;
  font-weight: 750;
  letter-spacing: .18em;
  text-indent: .18em;
}

/* 保存枠を開く一行。入口の二つより一段下の扱いで、控えの一行の後ろに置く。 */
.title-link {
  display: block;
  width: 100%;
  margin: 12px 0 0;
  padding: 12px 10px;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .14em;
  text-indent: .14em;
}

.title-link:active { color: var(--ink); }

@media (hover: hover) {
  .title-link:hover { color: var(--ink); }
}

/* 読み込み画面。**表題はそのままの位置に残し、下に細い帯だけを出す。**
   読み終えたら同じ場所に入口が現れるので、画面が入れ替わったようには見えない。 */
.boot-screen {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

.boot-bar {
  width: min(100%, 190px);
  height: 2px;
  border-radius: 999px;
  background: rgba(237, 243, 237, .12);
  overflow: hidden;
}

.boot-bar i {
  display: block;
  width: 0;
  height: 100%;
  border-radius: inherit;
  background: var(--gold);
  transition: width .25s ease-out;
}

/* app.js が届く前の静的な印。まだ進み具合が分からないので、帯を往復させる。 */
.boot-static {
  margin-top: 38vh;
}

.boot-static .boot-bar i {
  width: 34%;
  animation: boot-sweep 1.25s ease-in-out infinite alternate;
}

@keyframes boot-sweep {
  from { transform: translateX(-100%); }
  to { transform: translateX(295%); }
}

/* 立ち上がりの一呼吸。上から順に置かれる。 */
@keyframes title-rise {
  from { opacity: 0; transform: translateY(9px); }
  to { opacity: 1; transform: translateY(0); }
}

.wordmark-lead { animation: title-rise .5s ease-out both; }
.wordmark-tail { animation: title-rise .5s ease-out .1s both; }
.title-rule { animation: title-rise .5s ease-out .18s both; }
.title-actions .title-entry:nth-child(1) { animation: title-rise .5s ease-out .24s both; }
.title-actions .title-entry:nth-child(2) { animation: title-rise .5s ease-out .3s both; }
.title-screen .save-summary { animation: title-rise .5s ease-out .36s both; }
.title-link { animation: title-rise .5s ease-out .42s both; }

@media (prefers-reduced-motion: reduce) {
  .wordmark-lead,
  .wordmark-tail,
  .title-rule,
  .title-actions .title-entry,
  .title-screen .save-summary,
  .title-link { animation: none; }
  .boot-static .boot-bar i { animation: none; width: 100%; opacity: .5; }
  .title-air::before { transition: none; }
}

/* 横向き・背の低い画面では、表題の上を詰める。 */
@media (max-height: 560px) {
  .title-header { padding-top: 22px; }
  .title-screen { margin-top: 20px; padding-bottom: 20px; }
  .title-entry { min-height: 46px; padding: 12px 10px; }
  /* 背が低い画面では、品書きと画が同じ高さに来る。**画を小さくし、幕を濃くする。** */
  .title-air::before { background-size: auto 48%; }
  .title-air::after {
    background:
      linear-gradient(90deg,
        rgba(10, 15, 17, .92) 0,
        rgba(10, 15, 17, 0) 15%,
        rgba(10, 15, 17, 0) 85%,
        rgba(10, 15, 17, .92) 100%),
      linear-gradient(180deg,
        rgba(10, 15, 17, .9) 0,
        rgba(10, 15, 17, .78) 40%,
        rgba(10, 15, 17, .66) 72%,
        rgba(6, 10, 11, .62) 100%);
  }
}

.build-trail i {
  display: grid;
  flex: 0 0 auto;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--gold);
  color: #1b201e;
  font-style: normal;
  font-size: 12px;
}

.button {
  width: 100%;
  margin-top: 13px;
  padding: 11px 15px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel-3);
  font-weight: 750;
}

.button.primary {
  border-color: var(--gold);
  background: var(--gold);
  color: #1d211f;
}

.primary-action {
  margin: 0 0 14px;
  padding: 10px 12px 12px;
  border: 1px solid var(--gold);
  border-radius: 12px;
  background: linear-gradient(145deg, rgba(57, 47, 30, .72), rgba(32, 45, 48, .94));
}
.primary-action-label {
  margin: 0 0 8px;
  color: var(--gold);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .08em;
}
.primary-action .button { margin-top: 0; }
.primary-action > .card { margin-bottom: 0; }

.progressive-details {
  margin-top: 12px;
}
.progressive-details > summary {
  cursor: pointer;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: rgba(23, 33, 36, .72);
  color: var(--ink);
  font-size: 11px;
  font-weight: 750;
}
.progressive-details[open] > summary {
  border-color: var(--gold);
  color: var(--gold);
}
.progressive-details > .enemy-grid,
.progressive-details > .enemy-board,
.progressive-details > .gear-grid {
  margin-top: 9px;
}

.build-stamp {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* R14 §1 — 戦闘予測とタブは一つの塊で上端に貼りつく。
   予測を見ながら技能・装備・隊列を触るのが、この遠征の中心の操作である。 */
.camp-top {
  position: sticky;
  top: 0;
  z-index: 3;
  margin: 0 -2px 8px;
  /* 下の余白は margin ではなく padding で取る。**margin では下をくぐる本文に効かない**
     ——貼りついた帯の下端へ、スクロールしてきた文がそのまま接してしまう（作者試遊、
     2026-09-11）。padding にすると、ぼかした帯そのものが下へ伸びる。 */
  padding: 4px 2px 12px;
  background: rgba(14, 20, 22, .95);
  backdrop-filter: blur(10px);
}
.camp-top .tabs {
  position: static;
  margin: 0;
  background: transparent;
  backdrop-filter: none;
}
/* 予測が出ている回だけ、盤面の枠に勝敗の色が乗る（箱そのものは .party-bar）。 */
.forecast-bar.loss { border-color: rgba(231, 137, 128, .7); }
.forecast-bar.win { border-color: rgba(155, 214, 158, .45); }
/* issue #237 — **危険な回だけ、窓の縁がゆっくり脈を打つ。**
   このまま挑めば負ける、という状態は画面で一番強い報せなので、色（赤）の上に
   一つだけ動きを足す。速くしない——急かす動きにすると、組み替える手が止まる。 */
@keyframes forecast-warn {
  0%, 100% { border-color: rgba(231, 137, 128, .45); box-shadow: inset 0 0 18px rgba(83, 153, 164, .08), 0 5px 18px rgba(0, 0, 0, .22); }
  50% { border-color: rgba(231, 137, 128, .95); box-shadow: inset 0 0 20px rgba(231, 137, 128, .12), 0 5px 18px rgba(0, 0, 0, .22); }
}
.forecaster-window.forecast-bar.loss { animation: forecast-warn 2.8s ease-in-out infinite; }
.forecast-head {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}
.forecaster-identity,
.forecast-readout { display: flex; align-items: center; min-width: 0; }
.forecaster-identity { flex: 1 1 auto; gap: 6px; }
.forecast-readout { flex: 0 1 auto; justify-content: flex-end; gap: 5px; }
.forecaster-lens,
.simulation-lens {
  position: relative;
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 18px;
  height: 18px;
  border: 1px solid rgba(145, 203, 213, .8);
  border-radius: 50%;
  box-shadow: 0 0 8px rgba(145, 203, 213, .32), inset 0 0 5px rgba(145, 203, 213, .24);
}
.forecaster-lens::before,
.simulation-lens::before {
  width: 8px;
  height: 8px;
  border: 1px solid var(--blue);
  border-radius: 50%;
  content: "";
}
.forecaster-lens::after,
.simulation-lens::after {
  position: absolute;
  inset: -3px;
  border: 1px dashed rgba(145, 203, 213, .45);
  border-radius: 50%;
  content: "";
  animation: forecaster-orbit 7s linear infinite;
}
.forecaster-lens i,
.simulation-lens i {
  position: absolute;
  width: 2px;
  height: 2px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 6px 2px var(--blue);
}
.forecast-title { color: var(--muted); font-size: 10px; font-weight: 750; letter-spacing: .08em; }
/* 読み値は**前の値の影**（.fx-ghost）を上へ重ねられるように、自分を基準にする。 */
.forecast-verdict { position: relative; color: var(--gold); font-size: 11px; font-weight: 750; white-space: nowrap; }
.forecast-bar.loss .forecast-verdict { color: var(--bad); }
.forecast-bar.win .forecast-verdict { color: var(--good); }
/* issue #159 — 上端は仲間の共通盤面。**POSITIONS そのままの3列×2行**で、
   戦闘中の盤面（.battle-row / .battle-units）と同じ並び・同じ読み方にする。
   横スクロールはしない——3列が iPhone 幅（390px）に必ず収まるよう、
   セルは等分して縮む。 */
.party-bar {
  position: relative;
  overflow: hidden;
  margin: 0 0 6px;
  padding: 8px 10px 9px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--panel);
}
.forecaster-window {
  background:
    radial-gradient(circle at 8% 0%, rgba(145, 203, 213, .12), transparent 34%),
    linear-gradient(180deg, rgba(24, 38, 41, .98), rgba(18, 29, 31, .98));
  box-shadow: inset 0 0 18px rgba(83, 153, 164, .08), 0 5px 18px rgba(0, 0, 0, .22);
}
.forecaster-window::before,
.simulation-vision::before,
.simulation-result::before {
  position: absolute;
  z-index: 1;
  inset: 4px;
  border: 1px solid rgba(145, 203, 213, .1);
  border-radius: 9px;
  background:
    linear-gradient(90deg, rgba(145, 203, 213, .28) 0 7px, transparent 7px calc(100% - 7px), rgba(145, 203, 213, .28) calc(100% - 7px)) top / 100% 1px no-repeat,
    linear-gradient(90deg, rgba(145, 203, 213, .28) 0 7px, transparent 7px calc(100% - 7px), rgba(145, 203, 213, .28) calc(100% - 7px)) bottom / 100% 1px no-repeat;
  content: "";
  pointer-events: none;
}
.forecaster-scan,
.simulation-scan {
  position: absolute;
  z-index: 1;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
  pointer-events: none;
}
.forecaster-scan::after,
.simulation-scan::after {
  position: absolute;
  inset: -35% 0 auto;
  height: 34%;
  background: linear-gradient(180deg, transparent, rgba(145, 203, 213, .1), transparent);
  content: "";
  animation: forecaster-sweep 5.5s ease-in-out infinite;
}
/* 作者指摘 2026-09-13 —「走査線が消えたのでは？」。消えてはいない（上から降りる
   一本は #266 のまま動いている）が、窓が下段の釦ぶん高くなり、一本だけでは
   **面がブラウン管であること**が読めなくなっていた。面そのものへ横の目を敷く。
   1px おきに 2px 空ける粗い目で、9〜13px の数字の可読性は落とさない濃さに留める。 */
.forecaster-scan::before,
.simulation-scan::before {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(180deg, rgba(145, 203, 213, .16) 0 1px, transparent 1px 3px);
  content: "";
  /* 濃さは**この一つ**で決める。読み直しの回はここを上げて戻すだけにして、
     目の濃さそのものを class で差し替えない（差し替えると、動きが終わった後も
     濃いままの窓が残る——class は次の描画まで外れない）。 */
  opacity: .3;
}
/* 作者要望 2026-09-13 — 試映と実戦は**窓の下に一段取って大きく置く。**
   見出し行の右端に二字で畳んでいた頃は、この窓で一番大事な操作なのに一番小さかった。
   二つ並ぶ回は等分、試映が出せない回（予測が無い回）は実戦が一段を占める。
   高さは 44px 以上——指で狙う最小の的（iOS の目安）を下回らせない。 */
.forecaster-actions {
  position: relative;
  z-index: 2;
  display: flex;
  gap: 6px;
  margin-top: 8px;
}
.forecaster-action {
  flex: 1 1 0;
  display: grid;
  grid-template-columns: 17px minmax(0, 1fr);
  align-items: center;
  gap: 7px;
  min-height: 44px;
  padding: 6px 10px;
  border: 1px solid rgba(145, 203, 213, .45);
  border-radius: 10px;
  background: rgba(9, 18, 20, .76);
  color: var(--blue);
  font: inherit;
  text-align: left;
}
.forecaster-action-copy { display: grid; gap: 1px; min-width: 0; }
.forecaster-action-copy b { font-size: 13px; font-weight: 800; letter-spacing: .1em; line-height: 1.1; }
.forecaster-action-copy small {
  overflow: hidden;
  color: var(--muted);
  font-size: 9px;
  font-weight: 600;
  line-height: 1.1;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.forecaster-action-icon { font-size: 15px; line-height: 1; text-align: center; text-shadow: 0 0 8px currentColor; }
/* 実戦は**この窓から出る唯一の不可逆な一手**なので、金で、盤面の側から光らせる。 */
.forecaster-action.engage {
  border-color: rgba(229, 184, 105, .66);
  background: linear-gradient(180deg, rgba(80, 59, 25, .92), rgba(48, 37, 22, .96));
  box-shadow: 0 0 14px rgba(229, 184, 105, .1), inset 0 1px 0 rgba(255, 236, 199, .12);
  color: var(--gold);
}
.forecaster-action.engage .forecaster-action-copy small { color: rgba(229, 184, 105, .68); }
@keyframes forecaster-orbit { to { transform: rotate(1turn); } }
@keyframes forecaster-sweep {
  0%, 18% { transform: translateY(-20%); opacity: 0; }
  35%, 70% { opacity: 1; }
  88%, 100% { transform: translateY(390%); opacity: 0; }
}
.party-board { display: grid; gap: 4px; }
.forecast-head + .party-board { margin-top: 7px; }
/* 行の見出しは戦闘盤（.battle-row）と同じ位置・同じ大きさに置く。 */
.party-row { display: grid; grid-template-columns: 24px 1fr; align-items: center; gap: 5px; }
.party-row-label { color: var(--muted); font-size: 9px; letter-spacing: .04em; }
.party-cells { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px; }
.party-cell {
  position: relative;
  isolation: isolate;
  display: grid;
  align-content: start;
  gap: 3px;
  min-width: 0;
  padding: 4px 5px 5px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--panel-2);
  color: inherit;
  text-align: center;
  font: inherit;
}
button.party-cell { cursor: pointer; }
.party-cell:not(.empty) {
  min-height: 55px;
  padding: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}
.character-face-watermark {
  position: absolute;
  z-index: 0;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  opacity: .38;
}
.character-face-watermark .portrait-svg {
  display: block;
  width: 100%;
  height: 100%;
  filter: saturate(1.05) contrast(1.04) brightness(1.04);
  transform: translate3d(var(--face-x, 0%), var(--face-y, 0%), 0) scale(var(--face-scale, 1));
  transform-box: fill-box;
  transform-origin: 50% 50%;
}
.party-cell > :not(.character-face-watermark),
.unit > .unit-top,
.unit > .unit-info-layer {
  position: relative;
  z-index: 1;
}
.party-character-face { opacity: .75; }
.unit-character-face { opacity: .62; }
/* 顔の大きさと目元の高さは元画像の余白差を吸収する。予測・戦闘・人物の札・小さな顔は
   同じ補正値を使う（作者要望 2026-09-16 で札と粒が増えたので、選択子を並べて共有する）。 */
.character-face-watermark[data-character="warden"],
.character-face-chip[data-character="warden"] { --face-scale: 1.4; }
.character-face-watermark[data-character="lancer"],
.character-face-chip[data-character="lancer"] {
  --face-scale: 1.1;
  --face-y: -8%;
}
.character-face-watermark[data-character="tactician"],
.character-face-chip[data-character="tactician"] { --face-scale: 1.1; }
.character-face-watermark[data-character="mender"],
.character-face-chip[data-character="mender"] {
  --face-scale: 1;
  --face-y: -22%;
}
.character-face-watermark[data-character="guardian"],
.character-face-chip[data-character="guardian"] {
  --face-scale: .9;
  --face-y: -30%;
}
.party-cell.empty { border-style: dashed; background: transparent; }
.party-cell.defeated { border-color: var(--bad); background: rgba(231, 137, 128, .12); }
/* 選択中の一人。**金の枠は「いま操作の主語である」の意味だけに使う。** */
.party-cell.selected { border-color: var(--gold); background: var(--gold-dark); }
/* 治療の対象選択中だけ、選べる／選べないを枠で分ける。対象外も**消さずに残す**。 */
.party-cell.pickable { border-color: var(--good); }
.party-cell.unpickable { opacity: .38; }
.party-empty { color: var(--muted); font-size: 15px; line-height: 1.1; }
.party-empty-text { color: var(--muted); font-size: 9px; }
/* issue #235 — セルは2行。1行目＝人物と資源、2行目＝HPバー（数値を重ねる）と増減。 */
.party-figures { display: flex; align-items: center; justify-content: center; gap: 4px; min-width: 0; }
.party-res { display: flex; flex: none; align-items: center; gap: 3px; margin-left: 1px; }
.party-note {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 7px 0 0;
  color: var(--muted);
  font-size: 10px;
  line-height: 1.5;
}
.party-note > span { flex: 1 1 auto; min-width: 0; }
.party-note b { color: var(--ink); white-space: nowrap; }
.party-note.picking { color: var(--gold); }
.party-note .tiny-button { flex: 0 0 auto; margin-left: auto; }
.forecast-info-layer {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 2px;
  width: 100%;
  box-sizing: border-box;
  padding: 12px 5px 4px;
  background: linear-gradient(180deg, rgba(13, 19, 21, 0) 0%, rgba(13, 19, 21, .7) 42%, rgba(13, 19, 21, .96) 100%);
}
.forecast-member-head { display: flex; align-items: center; justify-content: flex-end; gap: 3px; min-width: 0; min-height: 7px; }
.forecast-member-head b {
  overflow: hidden;
  font-size: 10px;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* **数値はバーの中に置く。**別の行にすると、同じHPの話で2行を使うことになる。 */
.forecast-hp-bar {
  position: relative;
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  height: 14px;
  border-radius: 4px;
  background: #10191b;
  overflow: hidden;
}
.forecast-hp-end { background: var(--good); }
.forecast-hp-loss { background: var(--bad); }
.forecast-hp-values {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 9px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  text-shadow: 0 1px 2px rgba(6, 11, 12, .9), 0 0 3px rgba(6, 11, 12, .75);
}
.forecast-hp-values b { color: #fff; font-size: 10px; font-weight: 800; }
.forecast-hp-values small { color: rgba(255, 255, 255, .8); font-size: 9px; }
.forecast-delta { position: relative; flex: none; font-size: 11px; font-weight: 750; font-variant-numeric: tabular-nums; white-space: nowrap; }
.forecast-delta.down { color: var(--bad); }
.forecast-delta.up { color: var(--good); }
.forecast-delta.flat { color: var(--muted); }
.forecast-delta.fatal { color: var(--bad); }
.forecast-note { margin: 7px 0 0; color: var(--muted); font-size: 10px; line-height: 1.5; }
.forecast-note b { color: var(--ink); }

/* 未来の試映は文字札ではなく、青緑の投影面・走査線・レンズを戦闘から結果まで連続させる。 */
.simulation-vision,
.simulation-result,
.simulation-projection { border-color: rgba(145, 203, 213, .62); }
.simulation-vision,
.simulation-result {
  position: relative;
  overflow: hidden;
  background:
    repeating-linear-gradient(180deg, rgba(145, 203, 213, .025) 0 1px, transparent 1px 4px),
    radial-gradient(circle at 50% 42%, rgba(94, 190, 202, .13), transparent 58%),
    var(--panel);
  box-shadow: inset 0 0 34px rgba(80, 176, 189, .1), 0 0 22px rgba(80, 176, 189, .08);
}
.simulation-vision > :not(.simulation-lens):not(.simulation-scan),
.simulation-result > :not(.simulation-lens):not(.simulation-scan) { position: relative; z-index: 2; }
.simulation-vision > .simulation-lens,
.simulation-result > .simulation-lens {
  position: absolute;
  z-index: 3;
  top: 10px;
  right: 10px;
  width: 24px;
  height: 24px;
}
.simulation-vision > .section-head {
  /* 右上の投影レンズとステージ名が同じ領域を使わない。 */
  padding-right: 34px;
}
.simulation-vision .battle-field { filter: saturate(.78) sepia(.05) hue-rotate(132deg) contrast(1.06); }
.simulation-result .verdict-mark { color: var(--blue); text-shadow: 0 0 14px rgba(145, 203, 213, .55); }
.simulation-projection { background: linear-gradient(135deg, rgba(145, 203, 213, .06), var(--panel)); }

@media (max-width: 430px) {
  .forecast-readout { gap: 3px; }
  .forecast-verdict { font-size: 10px; }
  .forecaster-action { gap: 6px; padding: 5px 8px; }
  .forecaster-action-copy b { font-size: 12px; }
  .board-mode { padding-inline: 6px; }
}

@media (prefers-reduced-motion: reduce) {
  .forecaster-lens::after,
  .simulation-lens::after,
  .forecaster-scan::after,
  .simulation-scan::after,
  .forecaster-window.forecast-bar.loss { animation: none; }
}

.tabs {
  position: sticky;
  top: 0;
  z-index: 2;
  display: grid;
  /* issue #235 — キャンプは編成タブを廃止して4枚。ギルドは5枚あるので、枚数は
     `--tab-count` で渡す。**折り返させない**——作者指摘 2026-09-15 の「タブが
     整理されていない」は、5枚目（図鑑）だけが二段目にぶら下がっていた形のことである。 */
  grid-template-columns: repeat(var(--tab-count, 4), minmax(0, 1fr));
  gap: 4px;
  margin: 0 -2px 12px;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(14, 20, 22, .93);
  backdrop-filter: blur(10px);
}
.tab {
  padding: 8px 4px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
}
.tab.active { background: var(--panel-3); color: var(--gold); }
/* 作者指摘 2026-09-15（二度目）— 読み物の札（根城・図鑑）と、毎回必ず通る仕度の札
   （投資・設計図・遠征）を、縦線一本で分ける。**並びは人がたどる順のままにする**ので、
   分けるのに順を入れ替えない。 */
.tabs .tab.group-start {
  border-left: 1px solid var(--line);
  border-radius: 0 8px 8px 0;
  margin-left: 3px;
  padding-left: 7px;
}
.section-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
.stage, .count { color: var(--gold); font-size: 12px; white-space: nowrap; }
.selection-note {
  margin: 14px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 12px;
}
/* issue #159 — 隊列盤（.formation-board / .formation-slot）はここにあった。
   **上端の .party-board が同じ盤面を持つ**ので、編成タブ側の複製は消した。 */
/* issue #159 — 盤面で選んだ一人の中身。**盤面が出しているもの（立ち位置・顔・名前）を
   繰り返さず、説明・役割・基礎値だけを足す。** */
.member-detail {
  margin-top: 14px;
  padding: 11px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: #172124;
}
.member-detail-head { display: flex; align-items: center; gap: 9px; }
.member-detail-head h3 { margin: 2px 0; font-size: 15px; }
.member-detail-head small { display: block; color: var(--muted); font-size: 10px; line-height: 1.35; }
.member-detail-res { display: inline-flex; align-items: center; gap: 5px; margin-left: auto; }
.member-detail-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
  margin-top: 10px;
}
.member-detail-stats span { display: grid; gap: 1px; text-align: center; }
.member-detail-stats small { color: var(--muted); font-size: 9px; }
.member-detail-stats b { font-size: 12px; font-variant-numeric: tabular-nums; }
/* 職種アイコンの札（.avatar / .avatar.small）は 2026-09-16 に全画面から外した。
   人物を指す手掛かりは顔（.character-face-watermark / .character-face-chip）だけである。 */
.character-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 9px;
  margin-top: 14px;
}
.character-card {
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: #172124;
}
.character-card.in-party { border-color: #65724f; }
.character-card.selected { box-shadow: 0 0 0 1px var(--gold) inset; background: #292a21; }
.character-main {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 8px;
  padding: 0;
  border: 0;
  background: transparent;
  text-align: left;
}
.character-copy { min-width: 0; flex: 1; }
.character-copy b, .character-copy small { display: block; }
.character-copy b { font-size: 13px; }
.character-copy small { margin-top: 3px; color: var(--muted); font-size: 10px; line-height: 1.35; }
.check { flex: 0 0 auto; color: var(--gold); font-size: 11px; font-weight: 750; }
/* issue #236 — 能力値は軸をそろえて、軸名を小さく・数を大きく出す。
   仲間カードと人物の札（.character-panel）が**同じ形**を使う（statAxesHtml）。
   札は HP をバーで出すので、そこだけ HP 抜きの3軸になる。 */
.character-stats {
  display: flex;
  justify-content: space-between;
  gap: 3px;
  margin-top: 9px;
  padding-top: 8px;
  border-top: 1px solid rgba(58,77,79,.65);
  color: var(--blue);
  font-size: 10px;
}
.character-stats > span {
  display: flex;
  flex: 1 1 0;
  min-width: 0;
  flex-direction: column;
  align-items: center;
  gap: 1px;
}
.character-stats small {
  color: var(--muted);
  font-size: 9px;
  letter-spacing: .02em;
}
.character-stats b {
  color: var(--ink);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.character-stats b small { color: var(--muted); font-size: 9px; }
.tiny-button, .icon-button {
  border: 1px solid var(--line);
  border-radius: 7px;
  background: #253438;
  padding: 6px 8px;
  font-size: 10px;
  white-space: nowrap;
}
.character-card > .tiny-button { width: 100%; margin-top: 8px; }
.primary-mini { border-color: var(--gold); color: var(--gold); }
.quiet { border-style: dashed; background: rgba(23, 33, 36, .55); }
.member-tabs {
  display: flex;
  gap: 6px;
  margin: 14px 0;
  overflow-x: auto;
  padding-bottom: 2px;
}
/* ギルドの仲間の帯。**5人が横へ流れずに一段へ収まる**ようにする（iPhone 幅では、
   はみ出た一人は無いのと同じである）。伸びはするが縮まないので、6人目が来たら
   そのときだけ横へ流れる。 */
.member-tab {
  display: inline-flex;
  flex: 1 0 auto;
  justify-content: center;
  align-items: center;
  gap: 5px;
  padding: 6px 7px;
  border: 1px solid var(--line);
  /* その人の色は縁の一本が出す。図像の札まで並べると 5 人目が iPhone 幅ではみ出す。 */
  border-left: 2px solid var(--accent, var(--line));
  border-radius: 8px;
  background: #172124;
  color: var(--muted);
  font-size: 11px;
  white-space: nowrap;
}
.member-tab.active {
  border-color: var(--gold);
  border-left: 2px solid var(--accent, var(--gold));
  color: var(--gold);
  background: var(--gold-dark);
}
.member-summary, .member-head {
  display: flex;
  align-items: center;
  gap: 9px;
}
.member-summary {
  margin: 8px 0 14px;
  padding: 10px;
  border-radius: 10px;
  background: rgba(14,20,22,.45);
}
.member-summary b, .member-summary small, .member-head b, .member-head small { display: block; }
.member-summary small, .member-head small { color: var(--muted); font-size: 10px; }
.slot-group { margin-top: 12px; }
.slot-heading {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 4px;
  color: var(--muted);
  font-size: 11px;
}
.slot-heading small { color: var(--gold); }
.installed-row {
  display: flex;
  align-items: center;
  gap: 7px;
  min-height: 34px;
  padding: 5px 0;
  border-top: 1px solid rgba(58,77,79,.55);
}
.installed-row.disabled { opacity: .55; }
.order, .bullet {
  display: grid;
  flex: 0 0 auto;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 6px;
  background: var(--gold);
  color: #1b201e;
  font-size: 11px;
}
.bullet { background: var(--violet); }
.installed-copy { min-width: 0; flex: 1; }
.installed-copy b, .installed-copy small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.installed-copy b { font-size: 12px; }
.installed-copy small { color: var(--muted); font-size: 10px; }
.reorder { display: flex; gap: 3px; }
.icon-button { width: 26px; padding: 4px 2px; }
.skill-toggle { margin: 0; }
.skill-state {
  flex: none;
  padding: 3px 6px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--good);
  font-size: 9px;
  white-space: nowrap;
}
.installed-row.disabled .skill-state { color: var(--muted); }
.node-locked {
  margin: 6px 0 0;
  color: var(--muted);
  font-size: 9px;
  line-height: 1.45;
}
.rule-note {
  padding: 8px 10px;
  border-left: 2px solid var(--gold);
  border-radius: 0 8px 8px 0;
  background: rgba(229, 184, 105, .07);
}
/* R12 — 名簿（ギルドカード）。読み物なので、行間を戦闘画面より広く取る。 */
.dossier-card {
  border: 1px solid var(--line, rgba(255,255,255,.12));
  border-left: 3px solid var(--accent, #91cbd5);
  border-radius: 10px;
  padding: 14px 14px 12px;
  margin-top: 12px;
  background: rgba(255,255,255,.02);
}
.dossier-head { display: flex; align-items: center; gap: 12px; }
.dossier-bust {
  flex: 0 0 62px;
  width: 62px;
  height: 74px;
  overflow: hidden;
  border-radius: 8px;
  background: rgba(0,0,0,.22);
}
.dossier-bust .portrait-svg { display: block; width: 100%; height: 118px; margin-top: -6px; }
.dossier-name b { display: block; color: var(--accent, #91cbd5); font-size: 1.02em; }
.dossier-name small { display: block; margin-top: 2px; color: var(--muted); }
.dossier-body { margin-top: 10px; }
.dossier-section { margin-top: 12px; }
/* 節の見出しは**罫と一緒に置く。**続けて読む文の壁を、節ごとに切り分ける。 */
.dossier-section > b {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 5px;
  font-size: .74em;
  letter-spacing: .12em;
  color: var(--muted);
}
.dossier-section > b::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, var(--accent, #91cbd5), transparent);
  opacity: .35;
}
.dossier-progress {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  padding-top: 11px;
  border-top: 1px dashed var(--line, rgba(255,255,255,.14));
}
.dossier-progress > .glyph {
  width: 14px;
  height: 14px;
  color: var(--muted);
}
.dossier-progress .meter { flex: 1; }
.dossier-progress .meter-label { font-size: 9.5px; }
.dossier-sealed + .dossier-progress,
.dossier-progress + .dossier-sealed {
  margin-top: 8px;
  padding-top: 0;
  border-top: 0;
}
.dossier-section p { margin: 0 0 4px; line-height: 1.85; }
.dossier-section.bonds p {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-left: 10px;
  margin-bottom: 8px;
  border-left: 1px solid var(--line, rgba(255,255,255,.12));
}
.dossier-section.bonds i { font-style: normal; font-size: .86em; }
.dossier-sealed {
  margin: 14px 0 0;
  padding-top: 10px;
  border-top: 1px dashed var(--line, rgba(255,255,255,.14));
  font-size: .84em;
  font-style: italic;
  color: var(--muted);
}

/* R12 — 精算の締めの一行。数字の下に、拾い屋の側の言い方を置く。 */
.settle-closing {
  margin: 10px 0 0;
  padding-top: 10px;
  border-top: 1px solid var(--line, rgba(255,255,255,.12));
  font-size: .9em;
  line-height: 1.7;
  color: var(--muted);
}

/* R12 — 設計図の由来。archive を「持ち物一覧」から「遠征の記録」へ寄せる。 */
.blueprint-origin {
  margin: 4px 0 0;
  font-size: .82em;
  font-style: italic;
  color: var(--muted);
}

/* R12 — 敵カードの「拾い屋のあいだで言われていること」。
   規則（狙い）と混ざらないように、字を落として傾ける。 */
.enemy-lore {
  margin: 6px 0 0;
  padding-top: 6px;
  border-top: 1px dashed var(--line, rgba(255,255,255,.14));
  font-size: .82em;
  font-style: italic;
  color: var(--muted);
}

/* R13 — 根城。家にあるものは「一覧」ではなく「読み物」なので、
   カードの枠を弱くして、行間だけ広く取る。 */
.fixture-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
  margin-top: 12px;
}
.fixture-card {
  padding: 10px 12px;
  border-left: 2px solid var(--line, rgba(255,255,255,.16));
  background: rgba(255,255,255,.015);
}
.fixture-card b { display: block; margin-bottom: 4px; color: var(--accent, #91cbd5); font-size: .95em; }
.fixture-card p { margin: 0 0 4px; font-size: .9em; line-height: 1.8; color: var(--muted); }

/* 読み返せる根城の場面。**押せることが分かる形にする**（読み物ではなく導線）。 */
.scene-list { display: grid; gap: 8px; margin-top: 10px; }
.scene-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--line, rgba(255,255,255,.12));
  border-radius: 10px;
  background: rgba(255,255,255,.02);
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.scene-row b { font-size: .95em; }
.scene-row small { color: var(--muted); font-size: .8em; }

/* R13 — 図鑑（R8 §3.2）。狙い（規則）・噂・図鑑の一節を、字で三層に分ける。 */
.codex-grid { display: grid; gap: 10px; margin-top: 12px; }
.codex-card {
  padding: 10px 12px;
  border: 1px solid var(--line, rgba(255,255,255,.12));
  border-radius: 10px;
  background: rgba(255,255,255,.02);
}
.codex-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.codex-head b { font-size: .98em; }
.codex-head small { color: var(--muted); font-size: .78em; white-space: nowrap; }
.codex-targeting { margin: 6px 0 0; font-size: .88em; line-height: 1.7; }
.codex-line {
  margin: 6px 0 0;
  font-size: .86em;
  line-height: 1.85;
  color: var(--muted);
}

/* R13 — 世界の声。**規則ではない**ので、どの画面でも同じ見え方にする。 */
.world-voice {
  margin: 10px 0 0;
  padding: 8px 0 0;
  border-top: 1px dashed var(--line, rgba(255,255,255,.14));
  font-size: .84em;
  font-style: italic;
  line-height: 1.8;
  color: var(--muted);
}
.item-voice {
  margin: 6px 0 0;
  font-size: .8em;
  font-style: italic;
  line-height: 1.75;
  color: var(--muted);
}

.skill-node {
  min-height: 168px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #172124;
}
/* issue #236 — `.skill-node.unlocked`（取得済みだが未装着）はここにあった。
   その状態そのものを廃止したので、中間の見た目も消した。 */
/* 取得可能は案内として残すが、取得済みより目立たせない。 */
.skill-node.available { border-color: #8a7d50; background: rgba(138, 125, 80, .08); }
.skill-node.prerequisite { border-color: #53635f; opacity: .68; }
.skill-node.locked { border-color: #4b5a57; opacity: .58; }
/* 取得済みは現在の編成を示す最優先状態。オフにすると薄くなる。 */
.skill-node.equipped {
  border-color: var(--gold);
  background: var(--gold-dark);
  box-shadow: 0 0 0 1px var(--gold), 0 0 0 3px rgba(229, 184, 105, .2);
}
.skill-node.equipped.disabled { opacity: .62; }
.node-top {
  display: flex;
  justify-content: space-between;
  margin-bottom: 7px;
}
.kind {
  display: inline-block;
  padding: 2px 5px;
  border-radius: 4px;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .04em;
}
.kind-active { background: var(--gold); color: #1b201e; }
.kind-reactive { background: var(--violet); color: #1b201e; }
.kind-equipment { background: var(--blue); color: #1b201e; }
.kind-passive { background: var(--good); color: #1b201e; }
.bullet.passive { background: var(--good); }
.tier { color: var(--muted); font-size: 10px; }
.skill-node b { display: block; font-size: 13px; }
.skill-node p { min-height: 48px; margin: 5px 0; color: var(--muted); font-size: 11px; line-height: 1.35; }
.skill-node > small { display: block; min-height: 27px; color: var(--blue); font-size: 9px; line-height: 1.35; }
.node-action { margin-top: 6px; }
.locked-reason { color: var(--muted); font-size: 10px; }
.gear-grid, .reward-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  margin-top: 14px;
}
.gear-card, .reward-card {
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: #172124;
}
.gear-card.selected { border-color: var(--gold); background: var(--gold-dark); }
.gear-card.broken { border-color: var(--bad); }
.gear-main {
  display: flex;
  width: 100%;
  align-items: flex-start;
  gap: 8px;
  padding: 0;
  border: 0;
  background: transparent;
  text-align: left;
}
.gear-icon { color: var(--blue); font-size: 20px; }
.gear-copy { min-width: 0; flex: 1; }
.gear-copy b, .gear-copy small { display: block; }
.gear-copy b { font-size: 12px; }
.gear-copy small { margin-top: 3px; color: var(--muted); font-size: 10px; line-height: 1.35; }
.gear-state { color: var(--gold); font-size: 10px; text-align: right; white-space: nowrap; }
.gear-member-grid { display: grid; gap: 10px; }
.gear-member { padding: 10px; border: 1px solid rgba(58,77,79,.8); border-radius: 11px; background: #172124; }
.equipment-slots { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-top: 9px; }
.equipment-slot { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.equip-slot-button {
  display: flex;
  min-height: 55px;
  align-items: center;
  gap: 7px;
  padding: 7px;
  border: 1px dashed var(--line);
  border-radius: 8px;
  background: #202d30;
  text-align: left;
}
.equip-slot-button.ready { border-color: var(--gold); background: var(--gold-dark); }
.equip-slot-button b, .equip-slot-button small { display: block; }
.equip-slot-button b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; }
.equip-slot-button small { color: var(--muted); font-size: 9px; }
.slot-number { display: grid; flex: 0 0 auto; place-items: center; width: 19px; height: 19px; border-radius: 5px; background: var(--blue); color: #172124; font-size: 10px; }
.codex-list { display: flex; flex-wrap: wrap; gap: 6px; }
.codex-chip { display: flex; flex-direction: column; gap: 2px; padding: 6px 8px; border: 1px solid var(--line); border-radius: 7px; background: #172124; font-size: 10px; }
.codex-chip small { color: var(--muted); font-size: 9px; }
.codex-chip.locked { opacity: .6; }
.map-progress {
  display: flex;
  align-items: center;
  gap: 4px;
  margin: 14px 0 18px;
}
.map-node {
  position: relative;
  display: flex;
  flex: 1;
  flex-direction: column;
  min-width: 0;
  align-items: center;
  justify-content: center;
  height: 27px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: #172124;
  color: var(--muted);
  font-size: 11px;
}
.map-node.done {
  border-color: rgba(155, 214, 158, .55);
  background: #2a4936;
  color: var(--good);
}
.map-node.current {
  border: 2px solid var(--gold);
  background: var(--gold-dark);
  color: var(--gold);
  box-shadow: 0 0 0 1px rgba(229, 184, 105, .35);
}
.map-node.unreached { color: var(--muted); }
.map-node-number { line-height: 1; }
.map-kind-badge {
  display: block;
  width: auto;
  height: 9px;
  border: 0;
  border-radius: 0;
  background: transparent;
  font-size: 8px;
  line-height: 1;
}
.map-node.kind-elite .map-kind-badge { color: var(--orange); }
.map-node.kind-boss .map-kind-badge { color: var(--bad); }
.map-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 5px 10px;
  margin: -7px 0 14px;
  color: var(--muted);
  font-size: 10px;
}
.map-legend span { display: inline-flex; align-items: center; gap: 4px; }
.map-legend-mark, .map-legend-symbol {
  display: inline-grid;
  place-items: center;
  width: 13px;
  height: 13px;
  font-style: normal;
  line-height: 1;
}
.map-legend-mark { border: 1px solid var(--line); border-radius: 4px; }
.map-legend-mark.state-done { border-color: rgba(155, 214, 158, .55); background: #2a4936; color: var(--good); }
.map-legend-mark.state-current { border: 2px solid var(--gold); background: var(--gold-dark); }
.map-legend-mark.state-unreached { background: #172124; }
.map-legend-symbol.kind-elite { color: var(--orange); }
.map-legend-symbol.kind-boss { color: var(--bad); }
.enemy-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin-top: 12px; }
.enemy-board {
  display: grid;
  gap: 7px;
}
.enemy-board .battle-row { margin: 0; }
.enemy-board .battle-units { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.enemy-board-empty {
  min-height: 62px;
  border: 1px dashed rgba(58, 77, 79, .55);
  border-radius: 9px;
}
.enemy-board-cell {
  display: flex;
  min-width: 0;
  min-height: 62px;
  flex-direction: column;
  justify-content: space-between;
  gap: 4px;
  padding: 7px 6px 6px;
  border: 1px solid rgba(231, 137, 128, .42);
  border-radius: 9px;
  background: #251c1e;
  color: inherit;
  text-align: left;
  font: inherit;
  line-height: 1.15;
  appearance: none;
}
.enemy-board-cell:hover,
.enemy-board-cell:focus-visible {
  border-color: var(--gold);
}
.enemy-board-cell.selected {
  border-color: var(--gold);
  background: var(--gold-dark);
  box-shadow: 0 0 0 1px rgba(229, 184, 105, .3);
}
.enemy-board-cell.boss { border-color: var(--gold); }
.enemy-board-cell-top {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 4px;
}
.enemy-board-cell-top b {
  min-width: 0;
  overflow: hidden;
  color: var(--ink);
  font-size: 9px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.enemy-board-icon {
  flex: 0 0 auto;
  color: var(--bad);
  font-size: 13px;
}
.enemy-board-cell-stats {
  display: flex;
  justify-content: space-between;
  gap: 4px;
  color: var(--muted);
  font-size: 8px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.enemy-board-badges {
  overflow: hidden;
  color: var(--gold);
  font-size: 8px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.enemy-selection-detail {
  margin-top: 9px;
}
.enemy-selection-detail .enemy-card { margin: 0; }
.enemy-card {
  padding: 10px;
  border: 1px solid rgba(231,137,128,.42);
  border-radius: 10px;
  background: rgba(78, 37, 37, .28);
}
.enemy-top { display: flex; align-items: center; gap: 8px; }
.enemy-mark { color: var(--bad); }
.enemy-top b, .enemy-top small { display: block; }
.enemy-top small { color: var(--muted); font-size: 10px; }
.enemy-card p { min-height: 34px; margin: 7px 0 0; color: #e8c4bd; font-size: 10px; line-height: 1.35; }
.targeting-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 0;
  border-top: 1px solid rgba(58,77,79,.55);
  font-size: 11px;
}
.targeting-line span { color: var(--blue); text-align: right; }
.battle-plan-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 0;
  border-top: 1px solid rgba(58,77,79,.55);
}
.battle-plan-row > div { min-width: 105px; }
.battle-plan-row b, .battle-plan-row small { display: block; }
.battle-plan-row small { color: var(--muted); font-size: 10px; }
.battle-plan-row > span:last-child { margin-left: auto; color: var(--blue); font-size: 10px; text-align: right; }
.plan-list { margin-top: 16px; }
.replay-progress {
  height: 7px;
  overflow: hidden;
  border-radius: 999px;
  background: #101719;
}
.replay-progress span { display: block; height: 100%; border-radius: inherit; background: var(--gold); transition: width .15s linear; }
.replay-now {
  margin: 13px 0;
  padding: 12px;
  border-left: 3px solid var(--gold);
  background: #2a3026;
  color: var(--ink);
  font-weight: 750;
}
.replay-columns, .result-actors {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 9px;
  margin-top: 15px;
}
.replay-actor, .result-actor {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #172124;
}
.replay-actor b, .replay-actor small, .result-actor b, .result-actor small { display: block; }
.replay-actor small, .result-actor small { color: var(--muted); font-size: 9px; }
.replay-actor.defeated { opacity: .5; border-color: var(--bad); }
.events { list-style: none; margin: 13px 0 0; padding: 0; }
.event {
  display: flex;
  align-items: baseline;
  gap: 9px;
  padding: 7px 0;
  border-bottom: 1px solid rgba(58,77,79,.5);
  font-size: 12px;
}
.event-round { min-width: 23px; color: var(--gold); font-size: 10px; }
.replay-events { max-height: 280px; overflow: auto; }
.replay-controls { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 5px; margin-top: 12px; }
.replay-controls .button { margin-top: 0; padding: 9px 4px; font-size: 11px; }
.verdict { text-align: center; }
.verdict-context {
  margin: 5px 0 0;
  color: var(--gold);
  font-size: 12px;
}
.verdict-mark { font-size: 40px; }
.verdict.win .verdict-mark { color: var(--good); }
.verdict.loss .verdict-mark { color: var(--bad); }
.metrics {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 5px;
  margin-top: 15px;
  padding-top: 13px;
  border-top: 1px solid var(--line);
}
.metrics b, .metrics small { display: block; }
.metrics b { font-size: 19px; }
.metrics small { color: var(--muted); font-size: 9px; }
.result-gear-list { margin-top: 10px; }
.result-gear {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  padding: 7px 0;
  border-top: 1px solid rgba(58,77,79,.55);
  font-size: 11px;
}
.result-gear span { color: var(--gold); }
.reward-card h3 { margin: 8px 0 4px; color: var(--ink); font-size: 14px; }
.reward-card p { min-height: 43px; margin-bottom: 5px; color: var(--muted); font-size: 11px; }
.reward-card small { color: var(--blue); font-size: 10px; }
.reward-card .button { margin-top: 10px; }
.reward-kind { display: inline-block; padding: 2px 5px; border-radius: 4px; font-size: 9px; font-weight: 800; }
.reward-special { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 8px; }
.reward-card.special { background: #202d30; }
.build-trail { display: grid; gap: 8px; margin-top: 16px; text-align: left; }
.build-trail span { display: flex; align-items: center; gap: 8px; }
label { display: block; margin-top: 12px; color: var(--muted); font-size: 12px; }
textarea, select {
  display: block;
  width: 100%;
  margin-top: 5px;
  padding: 9px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: #12191b;
  color: var(--ink);
}
textarea { min-height: 70px; resize: vertical; }
.error { margin: 12px 0; padding: 9px 12px; border-radius: 9px; background: var(--bad); color: #201212; font-size: 12px; }
details { margin-top: 13px; color: var(--muted); }
pre { max-height: 340px; overflow: auto; white-space: pre-wrap; color: #d0dbd5; font: 10px/1.55 ui-monospace, monospace; }
footer { margin-top: 18px; color: #697873; text-align: center; font-size: 9px; }
@media (max-width: 520px) {
  .shell { padding-left: 10px; padding-right: 10px; }
  .card { padding: 14px; }
  .character-grid, .gear-grid, .enemy-grid, .reward-grid { grid-template-columns: 1fr; }
}
@media (max-width: 380px) {
  h1 { font-size: 25px; }
  .three-up { gap: 4px; }
  .three-up .card { padding: 11px 6px; }
  .three-up span { font-size: 9px; }
  .replay-columns, .result-actors { grid-template-columns: 1fr; }
  .metrics small { font-size: 8px; }
}

.tab { display: grid; gap: 2px; line-height: 1.1; }
.tab small { color: #82938b; font-size: 9px; font-weight: 600; }
.tab.active small { color: var(--blue); }
/* 技能の見出しにあった「技能点 · 隊全体」の札（.skill-points-badge）は 2026-09-16 に
   落とした。技能点はタブの札・人物の札・ツリーの貼りつく帯が出す。 */
/* ============================================================ 人物の札（作者要望 2026-09-16）

   **人物は、どの画面でも同じ形で出る。**戦闘盤（.unit）と予測セル（.party-cell）が
   先に持っていた考え——顔が主語で、読み値はその隣（DESIGN §5.2）——を、ギルドの
   「連れていく隊」と技能・装備タブの帯へも広げた。職種アイコン（[拳]）と役どころ
   （「強打」）と紹介文は、どの画面でも出さない。 */
/* 札は一列に積む。**顔を左に立てた横長の札**は、2列に割ると顔も読み値も潰れる。 */
.character-panels {
  display: grid;
  gap: 7px;
}
.character-panel {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 138px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-left: 2px solid var(--accent, var(--line));
  border-radius: 11px;
  background: var(--panel-2);
}
.character-panel > .character-panel-info { position: relative; z-index: 1; }
/* **顔の枠は、顔の帯（240x150）を縦に丸ごと収める形にしてある。**だから盤面のセル用の
   寄せ（--face-scale）と持ち上げ（--face-y）は、札では掛けない——掛けると頭の上が切れて、
   髪の形で人を見分けられなくなる（作者指摘 2026-09-16、実機のヒバナとツグミ）。
   **属性で受けること。**人物別補正は `[data-character]` を持つので、クラス一つの選択子では
   詳細度で負け、札にもセル用の持ち上げが掛かったままになる。 */
.panel-character-face {
  right: auto;
  /* 縦長の枠は横が深く切られる（顔の帯は幅の1.6倍ある）ので、広がった髪まで入るよう
     少し広く取る。126px で帯の横半分が見え、ヒバナの左右の髪も枠の中に残る。 */
  width: 126px;
  border-right: 1px solid var(--line);
  opacity: 1;
}
.panel-character-face[data-character] {
  --face-scale: 1;
  --face-y: 0%;
}
/* ヒバナだけは原本の顔が大きく、髪も左右へ広がっている。縦長の枠でも髪の上が枠へ触るので、
   少しだけ下げて、ゴーグルごと枠の中へ入れる（下は顎までで、切れる場所は残らない）。 */
.panel-character-face[data-character="guardian"] { --face-y: 5%; }
/* 読み値は顔の右。**顔へ文字を重ねない**（DESIGN 5.2）。 */
.character-panel-info {
  display: grid;
  flex: 1 1 auto;
  align-content: center;
  gap: 4px;
  margin-left: 126px;
  padding: 9px 10px 10px;
}
.character-panel-head { display: flex; align-items: center; gap: 5px; min-width: 0; }
.character-panel-name {
  overflow: hidden;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .04em;
  white-space: nowrap;
  text-overflow: ellipsis;
  text-shadow: 0 1px 3px rgba(6, 11, 12, .95);
}
/* 払える点と必殺の印は名前の反対側へ寄せる（予測セルと同じ並び）。 */
.character-panel-head .party-res { margin-left: auto; }
.character-panel-head .party-ultimate { margin-left: auto; }
.character-panel-head .party-ultimate + .party-res { margin-left: 0; }
.character-panel-hp { height: 13px; }
.character-panel .character-stats { margin-top: 2px; padding-top: 6px; }
/* その画面でしか要らない読み値。**枠の外へはみ出さず、折り返して縦に伸びる。** */
.character-panel-extras {
  display: flex;
  flex-wrap: wrap;
  gap: 3px 9px;
  margin-top: 2px;
  padding-top: 6px;
  border-top: 1px solid rgba(58, 77, 79, .65);
}
.panel-readout { display: flex; align-items: baseline; gap: 3px; min-width: 0; }
.panel-readout.wide { flex: 1 1 100%; }
.panel-readout small { color: var(--muted); font-size: 9px; letter-spacing: .02em; }
.panel-readout b { color: var(--ink); font-size: 12px; font-variant-numeric: tabular-nums; }
.panel-readout .panel-readout-extra { color: var(--muted); font-size: 9px; }
.panel-readout.wide b { font-size: 10px; font-weight: 700; }
.character-panel-action { flex: 0 0 auto; }
.character-panel-action .tiny-button { margin: 0; }
/* まだ顔を見せられない相手（この区画で加わる仲間）も、同じ形の札で置く。 */
.character-panel.unknown { min-height: 62px; border-left-color: var(--line); opacity: .6; }
.character-panel.unknown .character-panel-info { margin-left: 0; }
.character-panel-note { margin: 0; color: var(--muted); font-size: 9.5px; }
/* 技能・装備タブの一枚は読み値が一段多い（その画面でしか要らない粒）ので、少し高い。 */
.member-context { margin: 13px 0 15px; min-height: 152px; }
/* 伏せ札は読み値を持たないので、顔の札の高さまで引き伸ばさない。 */
.character-panel.unknown { min-height: 86px; align-self: start; }
/* 名前の隣に置く小さな顔（貼りつく帯・結果画面の行）。 */
.character-face-chip {
  position: relative;
  display: block;
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  overflow: hidden;
  border: 1px solid var(--accent, var(--line));
  border-radius: 9px;
  background: #101a1c;
}
/* 粒は正方形で、顔の帯（240x150）の真ん中を縦いっぱいに切る。**持ち上げは掛けない**
   （30px では数%のずれが目元を切る）。寄せだけは人物別の値を使う。 */
.character-face-chip[data-character] { --face-y: 0%; }
.character-face-chip .portrait-svg {
  display: block;
  width: 100%;
  height: 100%;
  transform: translate3d(var(--face-x, 0%), var(--face-y, 0%), 0) scale(var(--face-scale, 1));
  transform-box: fill-box;
  transform-origin: 50% 50%;
}
/* 旧・帯の中の役どころ（.member-tab small）は 2026-09-15 に外した。名簿の見出しが
   「役 · 年 · 出」で既に出しており、並べると 5 人目が iPhone 幅ではみ出す。 */
.tree-legend { display: flex; flex-wrap: wrap; gap: 8px; color: var(--muted); font-size: 10px; }
.tree-legend span { display: inline-flex; align-items: center; gap: 4px; }
.tree-legend .kind { font-size: 8px; }
/* 作者指摘 2026-09-17（二度目）— **貼りつく帯を一枚減らす。**
   この帯は固定帯（.camp-top、実測 284px）の下へもう一枚貼りついて、iPhone の実質
   660px から 46px を常に取っていた（issue #236 のころは、画面の上端に貼って盤面を
   隠していたのを直した帯である）。顔と名前は上端の盤面（金の枠）と人物の札が既に
   言っているので落とし、残る技能点と予約先はツリーの操作の行（.tree-controls）へ
   同居させる。**貼るのをやめたので、`--camp-top-h` を見る必要も無い。** */
.skill-build-summary {
  display: flex;
  flex: 0 1 auto;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  margin: 0;
  padding: 0;
}
.summary-points { display: flex; flex: none; align-items: baseline; gap: 5px; }
.summary-points small { color: var(--muted); font-size: 9px; }
.summary-points b { color: var(--gold); font-size: 15px; font-variant-numeric: tabular-nums; }
.summary-points .summary-party { color: var(--muted); font-size: 9px; }
/* R19（issue #137）— 技能ツリー。**節を tier の箱へ並べるのをやめ、requires から
   組んだ森を、実座標の格子に置く。**列（x）は前提からの深さそのもの、行（y）は
   組み方から出た順。前提と派生は、列の間に引いた実線で結ぶ（インデントの目分量に
   頼らない）。列は固定幅にして、深いツリーほど横スクロールで場所を取る。 */
/* 作者指摘 2026-09-17（二度目）—「ちょっと狭いなあ。固定窓が多すぎるからですかね？」
   種別の札は**一行**にする（名前と数を縦に積むと、それだけで 57px 取っていた）。 */
.tree-tabs { display: flex; gap: 6px; margin: 10px 0 6px; }
.tree-tab {
  display: flex;
  flex: 1;
  min-height: 32px;
  align-items: baseline;
  justify-content: center;
  gap: 5px;
  padding: 5px 6px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #172124;
  color: var(--muted);
  text-align: center;
}
.tree-tab b { font-size: 12px; }
.tree-tab small { font-size: 9px; }
.tree-tab.active { border-color: var(--gold); background: var(--gold-dark); color: var(--ink); }
.tree-tab.active b { color: var(--gold); }
.tree-summary { margin: 0 0 6px; color: var(--muted); font-size: 10px; line-height: 1.5; }
.tree-summary b { color: var(--gold); }
/* 横スクロールできる帯。**列を固定幅にするので、深いツリーほど横に長くなる。**
   これが「もっと広く場所を取る」の実体である（縮めて収めない）。 */
.skill-tree-scroll { overflow-x: auto; overflow-y: hidden; padding-bottom: 10px; }
/* align-items:start が無いと、既定の stretch で同じ行の節が全部同じ高さへ
   伸ばされる。**最初の子は親と同じ行を継ぐ**ので、選択中の節（説明が開いて高い）
   と同じ行に短い節が並ぶことがあり、stretch のままだと形が崩れ、
   layoutSkillTreeConnectors() が測る中心もズレる。 */
.skill-tree-forest {
  position: relative;
  display: grid;
  align-items: start;
  column-gap: var(--tree-col-gap);
  row-gap: 10px;
  padding: 6px 4px;
}
/* 前提 → 派生の実線。**列の間の余白（column-gap）に、実際の節どうしを結ぶ
   直角線を引く。**どこと繋がっているかを、目分量のインデントではなく線そのもので見せる。 */
/* svgは幅・高さの指定が無いと既定の300×150に収まる（inset:0だけでは広がらない）。
   width/height を明示して初めて、forest 全体に重なる。 */
.tree-lines { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.tree-line { fill: none; stroke: #4d5b57; stroke-width: 1.5px; }
.tree-cell { position: relative; min-width: 0; }
/* 選択したとき、前提ルート（上流）と派生先（下流）だけを残す。 */
.tree-cell.faded { opacity: .32; }
.tree-cell.on-path > .skill-node { border-color: var(--blue); box-shadow: inset 3px 0 0 var(--blue); }
.tree-cell.derived > .skill-node { border-color: var(--good); box-shadow: inset 3px 0 0 var(--good); }
.tree-line.on-path { stroke: var(--blue); stroke-width: 2px; }
.tree-line.derived { stroke: var(--good); stroke-width: 2px; }
.tree-line.faded { stroke: #35403d; opacity: .5; }
.skill-node { min-height: 0; padding: 0; overflow: hidden; }
/* align-items:start（center ではない）。**バッジの数で1行にも2行にも
   なる node-copy** のせいで center だと丸印の高さが節ごとにブレる。
   start にして丸印を常にボタン上端の同じ位置へ固定し、同じ行に並ぶ節の
   線の高さ（layoutSkillTreeConnectors() が .node-icon の中心を測る）を揃える。 */
.skill-node-button {
  display: grid;
  grid-template-columns: 29px minmax(0, 1fr) auto;
  width: 100%;
  min-height: 62px;
  align-items: start;
  gap: 7px;
  padding: 8px;
  border: 0;
  background: transparent;
  color: var(--ink);
  text-align: left;
}
.skill-node-button:hover, .skill-node.selected .skill-node-button { background: rgba(224, 195, 116, .09); }
/* 説明が節の中で開かなくなったので、**いま操作盤が指している節**は地図の上で
   分かる必要がある（開いた高さがその印だった）。 */
.tree-cell.selected > .skill-node { border-color: var(--gold); box-shadow: 0 0 0 2px rgba(229, 184, 105, .45); }
.node-icon {
  display: grid;
  place-items: center;
  width: 27px;
  height: 27px;
  border: 1px solid var(--gold);
  border-radius: 50%;
  background: #252b26;
  color: var(--gold);
  font-size: 14px;
  font-weight: 800;
}
.skill-node.locked .node-icon, .skill-node.prerequisite .node-icon { border-color: #5f6c68; color: #82938b; }
.skill-node.available .node-icon { border-color: #8a7d50; background: rgba(138, 125, 80, .16); color: #c9b66e; }
.skill-node.equipped .node-icon { border-color: var(--gold); background: var(--gold); color: #1b201e; }
.skill-node.equipped.disabled .node-icon { border-color: var(--muted); background: #53605b; color: var(--ink); }
.node-copy { min-width: 0; }
.node-copy b, .node-copy small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.node-copy b { font-size: 11px; }
.node-copy small { margin-top: 3px; color: var(--muted); font-size: 9px; }
.node-status { color: var(--blue); font-size: 9px; text-align: right; white-space: nowrap; }
.skill-node.locked .node-status { color: var(--muted); }
.skill-node.available .node-status { color: #c9b66e; }
.skill-node.prerequisite .node-status { color: #82938b; }
.skill-node.equipped .node-status { color: var(--gold); font-weight: 800; }
.skill-node.equipped.disabled .node-status { color: var(--muted); }
/* 作者指摘 2026-09-17 —「スキルの一覧性、取得しやすさに難がある」。
   見方の切り替え（一覧／地図）と「いま取れる」の絞り込みは、同じ一行に置く。
   どちらも**何を見せるか**の操作で、節そのものは触らない。 */
.tree-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: 0 0 6px; }
.view-switch { display: flex; flex: none; gap: 2px; padding: 2px; border: 1px solid var(--line); border-radius: 8px; background: #172124; }
.view-tab { min-height: 28px; padding: 4px 12px; border: 0; border-radius: 6px; background: transparent; color: var(--muted); font-size: 11px; }
.view-tab.on { background: var(--gold-dark); color: var(--gold); font-weight: 800; }
/* 「いま取れる」。**取れるものがある回だけ出る**ので、数はいつも 1 以上である。 */
.ready-chip {
  display: flex;
  flex: 0 1 auto;
  min-height: 28px;
  align-items: center;
  gap: 5px;
  padding: 4px 9px;
  border: 1px solid #8a7d50;
  border-radius: 999px;
  background: rgba(138, 125, 80, .12);
  color: #c9b66e;
  font-size: 10px;
}
.ready-chip b { font-size: 11px; font-weight: 800; }
.ready-chip.on { border-color: var(--gold); background: var(--gold-dark); color: var(--gold); }
/* 種別タブの右肩に「いま取れる数」。三つの森を押して回らなくても、点の使い道が
   どちらに在るかが分かる。 */
.tree-tab { position: relative; }
.tab-ready {
  position: absolute;
  top: -6px;
  right: -4px;
  min-width: 16px;
  padding: 1px 4px;
  border-radius: 999px;
  background: var(--gold);
  color: #1b201e;
  font-size: 9px;
  font-style: normal;
  font-weight: 800;
  text-align: center;
}
/* 一覧。**縦だけで読む。**横スクロールは持たず、深さはインデントで見せる。 */
.skill-tree-list { display: grid; gap: 4px; padding: 2px 0 8px; }
.tree-cell.list-row { margin-left: calc(var(--indent, 0) * 11px); }
/* 深さの段差が「どこから伸びた節か」を言う。線は地図の役目なので引かない。 */
.tree-cell.list-row > .skill-node { border-left-width: 1px; }
.list-row .skill-node-button { min-height: 44px; align-items: center; gap: 8px; padding: 6px 9px; }
.list-row .node-copy b { font-size: 12px; }
.list-row .node-copy small { font-size: 10px; }
/* いま取れる節は、一覧の中で先に目に入る（金の縁）。 */
.tree-cell.list-row.ready > .skill-node { border-color: var(--gold); box-shadow: inset 3px 0 0 var(--gold); }
.tree-empty { margin: 10px 2px; font-size: 11px; line-height: 1.5; }

/* 作者指摘 2026-09-13 — **操作盤は画面の下端へ貼る。**選んだ節の説明と釦は、地図の
   中（列幅 176px）ではなくここに出る。貼りついているので、地図を横へどれだけ動かしても
   操作はいつも同じ場所にあり、節を押しても地図は組み変わらない。
   z-index は技能ツリー要約帯（2）より上、キャンプの固定帯（3）と手引きの札（4）より
   下に置く（盤は要約帯の上を通ってよいが、盤面の固定帯と、いまの一手を言う札を
   隠してはいけない）。 */
.skill-sheet {
  position: sticky;
  bottom: 0;
  z-index: 2;
  max-height: 56vh;
  margin-top: 8px;
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--gold);
  border-radius: 12px;
  background: rgba(20, 29, 31, .98);
  box-shadow: 0 -8px 20px rgba(0, 0, 0, .42);
}
.skill-sheet.available { border-color: #8a7d50; }
.skill-sheet.locked, .skill-sheet.prerequisite { border-color: #53635f; }
.skill-sheet.reserved { border-color: var(--blue); }
.skill-sheet-head {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 9px;
  border-bottom: 1px solid rgba(224, 195, 116, .2);
  background: rgba(20, 29, 31, .98);
}
.sheet-title { display: grid; flex: 1 1 auto; min-width: 0; gap: 1px; }
.sheet-title b { overflow: hidden; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
.sheet-title small { color: var(--muted); font-size: 9px; }
.sheet-close {
  flex: none;
  width: 28px;
  height: 28px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #1b2528;
  color: var(--muted);
  font-size: 11px;
}
/* 盤の中では、指で押す釦をツリーの札より大きくする（列の中に居たころは、
   176px の幅に収めるために小さいままだった）。 */
.skill-sheet .skill-detail { padding: 9px 10px 11px; border-top: 0; background: transparent; }
.skill-sheet .skill-detail p { font-size: 11px; line-height: 1.5; }
/* 取得・段上げ・予約・予約取消は**一行**。入り切らないときだけ折り返す。
   釦は指で押す大きさ（36px）を保ち、横は内容ぶんだけ取る。 */
.skill-sheet .node-action { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.skill-sheet .node-action .tiny-button { flex: 1 1 auto; min-height: 36px; padding: 7px 9px; font-size: 11px; }
/* 1点で変わる数（130% → 146%）は釦の隣。行が埋まっていれば次の行へ落ちる。 */
.skill-sheet .node-action .level-step { flex: 0 1 auto; }
.skill-sheet .node-locked { margin: 6px 0 0; }
.skill-detail {
  padding: 8px 9px 10px 44px;
  border-top: 1px solid rgba(224, 195, 116, .2);
  background: rgba(9, 15, 16, .35);
}
.skill-detail p { min-height: 0; margin: 0 0 5px; font-size: 10px; line-height: 1.4; }
.skill-detail > small { display: block; min-height: 0; color: var(--blue); font-size: 9px; line-height: 1.35; }
.skill-detail .node-action { margin-top: 7px; }
.skill-detail .tiny-button { margin-top: 0; }
/* 節の上で読める札。**種別・消費・いつ出るか・深さを、開かずに見せる。** */
.node-copy .node-badges { display: flex; flex-wrap: wrap; gap: 4px; white-space: normal; }
.node-badges i { font-style: normal; }
.node-badges .kind { padding: 1px 4px; font-size: 8px; }
.badge-cost { color: var(--gold); font-weight: 800; }
.badge-when { color: var(--muted); }
.badge-depth { color: var(--blue); }
.node-fork { color: var(--good); font-weight: 800; }
/* R19（issue #137）— 現在レベル／最大レベル。上位互換を別技能で増やさないので、
   「この節がどこまで伸びるのか」を節の上で読ませる。 */
.badge-level { color: var(--violet); font-weight: 800; }
.badge-level.maxed { color: var(--gold); }
.badge-level.flat { color: #6d7c77; font-weight: 400; }
.level-action { margin-top: 6px; padding-top: 6px; border-top: 1px dashed rgba(224, 195, 116, .16); }
/* 1点で説明文のどの数字がいくつになるか。**倍率ではなく、変わる数そのものを出す。** */
.level-now { margin-top: 5px; }
.level-now b { color: var(--violet); font-weight: 800; }
/* 説明文が Lv1 の値ではないことを、本文の末尾で一言。 */
.level-now-tag {
  margin-left: 6px;
  padding: 1px 5px;
  border-radius: 6px;
  background: rgba(150, 120, 220, .16);
  color: var(--violet);
  font-size: 9px;
  font-weight: 800;
  white-space: nowrap;
}
.member-head-button {
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  text-align: left;
}
.member-focus { margin-left: auto; color: var(--gold); font-size: 9px; white-space: nowrap; }
.gear-member.selected { border-color: #647152; background: rgba(61, 67, 43, .28); }
.flow-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.flow-actions .button { margin-top: 10px; }
.battle-error-message { overflow-wrap: anywhere; }
.diagnostic-events { max-height: 380px; overflow: auto; }

@media (max-width: 520px) {
  .tab { font-size: 11px; }
  .tab small { font-size: 8px; }
  :root { --tree-col-width: 176px; --tree-col-gap: 34px; }
}

@media (max-width: 380px) {
  .flow-actions { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------- 戦闘の絵
   ログは主役ではなくデバッグ用に降ろした。名前とHPの箱を人数分並べ、
   踏み込み・揺れ・箱の上に浮かぶ数字で「誰が誰を殴ったか」を見せる。 */
.battle-card .replay-progress { margin-bottom: 4px; }
.replay-progress-fill {
  display: block;
  width: 0;
  height: 100%;
  border-radius: inherit;
  /* 端を明るくして、いまどこまで来たかを目の端で拾えるようにする。 */
  background: linear-gradient(90deg, #8a6a2c 0%, var(--gold) 62%, #fff1cd 100%);
  box-shadow: 0 0 9px -2px rgba(229, 184, 105, .85);
  transition: width .3s ease;
}
.battle-field {
  position: relative;
  display: grid;
  gap: 9px;
  margin: 12px 0 6px;
  padding: 13px 11px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 13px;
  background: linear-gradient(180deg, #241b1d 0%, #162022 47%, #16221f 100%);
}
/* 上（敵）と下（味方）から差す光と、四隅を落とす影。**ゆっくり息をするだけ**で、
   盤面の字には掛からない（z-index 0 に置き、箱と拍の行は 1 に上げる）。 */
.battle-field::before,
.battle-field::after {
  position: absolute;
  z-index: 0;
  content: "";
  inset: 0;
  pointer-events: none;
}
.battle-field::before {
  background:
    radial-gradient(125% 44% at 50% -8%, rgba(231, 137, 128, .17), rgba(231, 137, 128, 0) 74%),
    radial-gradient(125% 44% at 50% 108%, rgba(155, 214, 158, .13), rgba(155, 214, 158, 0) 74%);
  animation: field-breath 6.5s ease-in-out infinite;
}
.battle-field::after {
  background: radial-gradient(132% 94% at 50% 50%, rgba(0, 0, 0, 0) 40%, rgba(4, 8, 9, .55) 100%);
}
@keyframes field-breath {
  0%, 100% { opacity: .68; }
  50% { opacity: 1; }
}
/* 着弾の揺れ。**重さの三段をそのまま揺れの三段にする。**盤面ごと動かすのは、
   箱一つの揺れでは「当たった」で終わり「重かった」が出ないため。 */
@keyframes field-shake {
  0% { transform: translate3d(0, 0, 0); }
  14% { transform: translate3d(calc(var(--shake) * -1), calc(var(--shake) * .42), 0); }
  31% { transform: translate3d(var(--shake), calc(var(--shake) * -.5), 0); }
  52% { transform: translate3d(calc(var(--shake) * -.6), calc(var(--shake) * .25), 0); }
  74% { transform: translate3d(calc(var(--shake) * .38), 0, 0); }
  100% { transform: translate3d(0, 0, 0); }
}
.battle-field.shake-1 { --shake: 2px; animation: field-shake .2s ease-out; }
.battle-field.shake-2 { --shake: 4px; animation: field-shake .3s ease-out; }
.battle-field.shake-3 { --shake: 7px; animation: field-shake .44s cubic-bezier(.2, .9, .3, 1); }
.battle-side { position: relative; z-index: 1; display: grid; gap: 7px; }
.battle-side-label {
  color: var(--muted);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .18em;
}
.battle-side[data-side="enemy"] .battle-side-label { color: var(--bad); }
.battle-side[data-side="ally"] .battle-side-label { color: var(--good); }
.battle-row { display: grid; grid-template-columns: 30px 1fr; align-items: center; gap: 7px; }
.battle-row-label { color: var(--muted); font-size: 9px; letter-spacing: .06em; }
/* 2×3 をそのまま格子で出す。空き枠は詰めない——**どこが空いているかが情報**。 */
.battle-units { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.unit-empty {
  border: 1px dashed rgba(58, 77, 79, .55);
  border-radius: 9px;
}
.unit {
  position: relative;
  min-width: 0;
  padding: 7px 6px 8px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--panel);
  transition: border-color .18s ease, box-shadow .18s ease, opacity .3s ease,
    transform .2s cubic-bezier(.2, .8, .3, 1), filter .3s ease;
}
.battle-side[data-side="enemy"] .unit { background: #251c1e; }
.unit-info-layer { position: relative; z-index: 1; }
.battle-side[data-side="ally"] .unit {
  display: flex;
  min-height: 84px;
  flex-direction: column;
  justify-content: flex-end;
  padding: 0 6px 6px;
  overflow: hidden;
}
.battle-side[data-side="ally"] .unit-info-layer {
  width: calc(100% + 12px);
  margin: 0 -6px -6px;
  padding: 20px 6px 6px;
  box-sizing: border-box;
  background: linear-gradient(180deg, rgba(13, 19, 21, 0) 0%, rgba(13, 19, 21, .72) 43%, rgba(13, 19, 21, .96) 100%);
}
.battle-side[data-side="ally"] .unit-top { display: none; }
.battle-side[data-side="ally"] .unit-bar { margin-top: 0; }
.battle-side[data-side="ally"] .unit-cast {
  height: 0;
  margin-top: 0;
}
.battle-side[data-side="ally"] .unit-cast.show {
  height: 15px;
  margin-top: 4px;
}
.unit-top { display: flex; align-items: center; gap: 5px; }
.unit-icon {
  display: grid;
  width: 17px;
  height: 17px;
  flex: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel-3);
  font-size: 10px;
  place-items: center;
}
.battle-side[data-side="enemy"] .unit-icon { border-color: #5e3f3d; background: #3b2726; color: var(--bad); }
.unit-name { overflow: hidden; font-size: 10px; text-overflow: ellipsis; white-space: nowrap; }
.unit-bar {
  position: relative;
  height: 6px;
  margin-top: 6px;
  border-radius: 999px;
  background: #0d1315;
}
.unit-fill,
.unit-recovered,
.unit-recoverable,
.unit-unrecoverable {
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  display: block;
  width: 0;
  max-width: 100%;
  height: 100%;
  border-radius: 0;
  pointer-events: none;
  transition: left .34s cubic-bezier(.2, .7, .3, 1), width .34s cubic-bezier(.2, .7, .3, 1);
}
.unit-fill { background: var(--hp-main); }
.unit-recovered { background: var(--hp-recovered-tone); }
.unit-recoverable { background: var(--hp-recoverable-tone); }
.unit-unrecoverable { background: var(--hp-unrecoverable); }
.unit.hp-tone-green {
  --hp-main: var(--hp-green);
  --hp-recovered-tone: var(--hp-green-light);
  --hp-recoverable-tone: var(--hp-green-dark);
}
.unit.hp-tone-yellow {
  --hp-main: var(--hp-yellow);
  --hp-recovered-tone: var(--hp-yellow-light);
  --hp-recoverable-tone: var(--hp-yellow-dark);
}
.unit.hp-tone-red {
  --hp-main: var(--hp-red);
  --hp-recovered-tone: var(--hp-red-light);
  --hp-recoverable-tone: var(--hp-red-dark);
}
.unit-barrier-fill {
  position: absolute;
  z-index: 2;
  top: -3px;
  left: 0;
  display: block;
  width: 0;
  max-width: 100%;
  height: 3px;
  border-radius: 999px;
  background: #a3aaa6;
  box-shadow: 0 0 0 1px rgba(14, 20, 22, .6);
  pointer-events: none;
  transition: width .34s cubic-bezier(.2, .7, .3, 1);
}
.unit-stats { display: flex; align-items: center; gap: 4px; margin-top: 4px; min-height: 12px; font-size: 9px; }
.unit-hp { flex: none; color: var(--muted); font-variant-numeric: tabular-nums; }
/* 防壁と状態異常。数が増えても箱の高さを変えない（動き自体が読めなくなるため）。 */
.unit-marks { display: flex; min-width: 0; flex: 1; gap: 3px; overflow: hidden; }
.mark {
  padding: 0 3px;
  border-radius: 3px;
  font-size: 8px;
  font-weight: 700;
  line-height: 12px;
  white-space: nowrap;
}
.mark.barrier { background: rgba(145, 203, 213, .18); color: var(--blue); }
.mark.block { background: rgba(192, 167, 229, .2); color: var(--violet); }
.mark.guard { background: rgba(158, 173, 167, .16); color: var(--muted); }
.mark.bad { background: rgba(231, 137, 128, .2); color: var(--bad); }
.mark.good { background: rgba(155, 214, 158, .18); color: var(--good); }
/* 行動権（金）と反応権（青）の粒。**尽きた粒は残す**ので、
   使い切ったのか元から無いのかが見分けられる。 */
.unit-pips { display: flex; flex: none; align-items: center; gap: 2px; margin-left: auto; }
/* 形でも見分ける。**色だけだと 9px では読めない。**行動権は菱形、反応権は丸。 */
.pip { flex: none; border: 1px solid var(--line); }
.pip.ap { width: 6px; height: 6px; border-radius: 1px; transform: rotate(45deg); }
.pip.rp { width: 4px; height: 4px; border-radius: 50%; }
.pip.ap.on { border-color: var(--gold); background: var(--gold); }
.pip.rp.on { border-color: var(--blue); background: var(--blue); }
.pip-gap { width: 3px; }
/* 行動権を使い切った＝そのラウンドの主行動を終えている。 */
.unit.spent { background: #141c1e; }
.battle-side[data-side="enemy"] .unit.spent { background: #1e1719; }
.unit.spent .unit-name { color: var(--muted); }
.unit-cast {
  height: 15px;
  margin-top: 5px;
  overflow: hidden;
  border-radius: 5px;
  background: var(--gold-dark);
  color: var(--gold);
  font-size: 9px;
  line-height: 15px;
  opacity: 0;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: height .18s ease, margin-top .18s ease, opacity .18s ease;
}
.unit-cast.show { opacity: 1; }
.unit-cast.prep { background: #23303a; color: var(--blue); }
/* 倒れた箱は色を抜く。**消さずに残す**ので、どこが空いたのかは盤面で読める。 */
.unit.defeated { border-color: #4b3336; opacity: .42; filter: grayscale(.8) brightness(.85); }
.unit.defeated .unit-fill { background: #5c4245; }
/* HPの色はバー内だけに効かせ、カード枠は従来の行動・被弾状態のままにする。 */
.unit.is-aimed { border-color: var(--gold); box-shadow: 0 0 0 1px rgba(229, 184, 105, .3); }
/* いま動いている箱は**一段手前へ出す。**枠だけを金にしていたころは、盤面の中で
   どれが主語なのかを枠の色差だけで探す必要があった。 */
.unit.is-acting {
  z-index: 2;
  border-color: var(--gold);
  box-shadow: 0 0 18px -2px rgba(229, 184, 105, .3), inset 0 0 20px -10px rgba(255, 226, 163, .95);
  transform: scale(1.035);
}

/* ---------------------------------------------------------------- 手応えの層（.unit-fx）
 *
 * 閃き・衝撃輪・斬線・照準の四枚。**箱の中だけで動く**ので、盤面の並びは変わらない。
 * どれも既定は透明で、拍が付ける状態クラス（is-hit / is-healed / …）だけが動かす。 */
.unit-fx {
  position: absolute;
  z-index: 2;
  overflow: hidden;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
}
.unit-fx > i {
  position: absolute;
  display: block;
  opacity: 0;
}
.fx-flash {
  inset: 0;
  background: radial-gradient(closest-side, rgba(255, 255, 255, .85), rgba(255, 255, 255, 0) 78%);
}
.fx-ring {
  top: 50%;
  left: 50%;
  width: 20px;
  height: 20px;
  margin: -10px 0 0 -10px;
  border: 2px solid currentColor;
  border-radius: 50%;
  color: var(--bad);
}
.fx-slash {
  top: -32%;
  left: -12%;
  width: 124%;
  height: 164%;
  background: linear-gradient(104deg,
    rgba(255, 255, 255, 0) 43%, rgba(255, 246, 224, .95) 50%, rgba(255, 255, 255, 0) 57%);
}
/* 弾着と銃口の閃光（作者要望 2026-09-14「技術は銃撃のイメージ」）。
 * **一枚で二役**——撃つ側では銃口の閃光として箱の前縁へ、受ける側では弾着の火花として
 * 箱の中央へ出る。位置を変えるのは下の `.is-striking` / `.is-hit` の節である。 */
.fx-shot {
  top: 50%;
  left: 50%;
  width: 26px;
  height: 26px;
  margin: -13px 0 0 -13px;
  color: var(--gold);
  background:
    radial-gradient(closest-side, rgba(255, 255, 255, .95), rgba(255, 236, 198, 0) 72%),
    linear-gradient(currentColor 0 0) 50% 50% / 100% 2px no-repeat,
    linear-gradient(currentColor 0 0) 50% 50% / 2px 100% no-repeat;
}
/* 狙われている箱の四隅。枠の色だけだと、隣の「行動中」の金と見分けが付きにくい。 */
.fx-reticle {
  inset: 2px;
  background:
    linear-gradient(var(--gold) 0 0) 0 0 / 8px 1px no-repeat,
    linear-gradient(var(--gold) 0 0) 0 0 / 1px 8px no-repeat,
    linear-gradient(var(--gold) 0 0) 100% 0 / 8px 1px no-repeat,
    linear-gradient(var(--gold) 0 0) 100% 0 / 1px 8px no-repeat,
    linear-gradient(var(--gold) 0 0) 0 100% / 8px 1px no-repeat,
    linear-gradient(var(--gold) 0 0) 0 100% / 1px 8px no-repeat,
    linear-gradient(var(--gold) 0 0) 100% 100% / 8px 1px no-repeat,
    linear-gradient(var(--gold) 0 0) 100% 100% / 1px 8px no-repeat;
}
@keyframes fx-flash {
  0% { opacity: 0; }
  14% { opacity: .72; }
  100% { opacity: 0; }
}
@keyframes fx-ring {
  0% { opacity: .95; transform: scale(.22); }
  100% { opacity: 0; transform: scale(3.4); }
}
@keyframes fx-slash {
  0% { opacity: 0; transform: translateX(-48%) skewX(-9deg); }
  22% { opacity: 1; }
  100% { opacity: 0; transform: translateX(48%) skewX(-9deg); }
}
@keyframes fx-muzzle {
  0% { opacity: 0; transform: scale(.35) rotate(-12deg); }
  16% { opacity: 1; transform: scale(1.15) rotate(6deg); }
  100% { opacity: 0; transform: scale(.9) rotate(14deg); }
}
@keyframes fx-shot {
  0% { opacity: 0; transform: scale(2.1) rotate(-20deg); }
  20% { opacity: 1; transform: scale(.8) rotate(0); }
  100% { opacity: 0; transform: scale(1.4) rotate(6deg); }
}
@keyframes fx-reticle {
  0% { opacity: 0; transform: scale(1.5); }
  45% { opacity: 1; transform: scale(1); }
  100% { opacity: .75; transform: scale(1); }
}
.unit.is-aimed .fx-reticle { animation: fx-reticle .42s cubic-bezier(.2, .85, .3, 1) forwards; }

/* ---------------------------------------------------------------- 踏み込みと被弾
 *
 * 踏み込みは**溜めてから出る。**真っ直ぐ出るだけだと、同じ拍に何度も出たとき
 * どれが新しい一撃なのか分からなくなる。左右の寄せ（--lunge-x）は画面側が
 * 狙った相手の列から決める。 */
@keyframes unit-lunge-up {
  0% { transform: translate3d(0, 0, 0) scale(1.035); }
  22% { transform: translate3d(calc(var(--lunge-x, 0px) * -.3), 5px, 0) scale(.97, 1.07); }
  46% { transform: translate3d(var(--lunge-x, 0px), -14px, 0) scale(1.08, .96); }
  70% { transform: translate3d(calc(var(--lunge-x, 0px) * .35), -3px, 0) scale(1.02, 1.01); }
  100% { transform: translate3d(0, 0, 0) scale(1.035); }
}
@keyframes unit-lunge-down {
  0% { transform: translate3d(0, 0, 0) scale(1.035); }
  22% { transform: translate3d(calc(var(--lunge-x, 0px) * -.3), -5px, 0) scale(.97, 1.07); }
  46% { transform: translate3d(var(--lunge-x, 0px), 14px, 0) scale(1.08, .96); }
  70% { transform: translate3d(calc(var(--lunge-x, 0px) * .35), 3px, 0) scale(1.02, 1.01); }
  100% { transform: translate3d(0, 0, 0) scale(1.035); }
}
.battle-side[data-side="ally"] .unit.is-striking { animation: unit-lunge-up .38s cubic-bezier(.3, .85, .25, 1); }
.battle-side[data-side="enemy"] .unit.is-striking { animation: unit-lunge-down .38s cubic-bezier(.3, .85, .25, 1); }
.unit.is-striking .fx-slash {
  background: linear-gradient(104deg,
    rgba(255, 226, 163, 0) 44%, rgba(255, 232, 183, .72) 50%, rgba(255, 226, 163, 0) 56%);
  animation: fx-slash .3s cubic-bezier(.2, .8, .3, 1) .06s;
}

/* -------------------------------------------------- 腕力＝斬撃 ／ 技術＝銃撃
 *
 * 作者要望 2026-09-14。**分け方は盤面の規則そのものである。**腕力の攻撃は前へ出て
 * 当てるので後列から出すと 40% へ落ち、技術の攻撃はその場から届く（R11 §5）。
 * だから腕力は「踏み込んで斬る」、技術は「動かずに撃つ」で描く。型の判定は
 * ecology/attack-style.mjs にあり、ここは付いた class を絵にするだけである。
 *
 * 型が読めない一撃（裂傷・装備の破片）には class が付かないので、上の既定——
 * 踏み込みと斬線——がそのまま出る。 */

/* 銃撃は踏み込まない。**反動だけが後ろへ抜ける。** */
@keyframes unit-recoil-up {
  0% { transform: translate3d(0, 0, 0) scale(1.035); }
  14% { transform: translate3d(calc(var(--lunge-x, 0px) * -.12), 5px, 0) scale(1.055, .965); }
  46% { transform: translate3d(0, 1px, 0) scale(1.015, 1.015); }
  100% { transform: translate3d(0, 0, 0) scale(1.035); }
}
@keyframes unit-recoil-down {
  0% { transform: translate3d(0, 0, 0) scale(1.035); }
  14% { transform: translate3d(calc(var(--lunge-x, 0px) * -.12), -5px, 0) scale(1.055, .965); }
  46% { transform: translate3d(0, -1px, 0) scale(1.015, 1.015); }
  100% { transform: translate3d(0, 0, 0) scale(1.035); }
}
.battle-side[data-side="ally"] .unit.is-striking.strike-technique {
  animation: unit-recoil-up .32s cubic-bezier(.16, .9, .3, 1);
}
.battle-side[data-side="enemy"] .unit.is-striking.strike-technique {
  animation: unit-recoil-down .32s cubic-bezier(.16, .9, .3, 1);
}
/* 撃つ側に刃は出さない。代わりに、敵へ向いた縁で銃口が光る。 */
.unit.is-striking.strike-technique .fx-slash { animation: none; }
.unit.is-striking.strike-technique .fx-shot {
  width: 30px;
  height: 18px;
  margin: -9px 0 0 -15px;
  background:
    radial-gradient(closest-side, rgba(255, 255, 255, .95), rgba(255, 226, 163, .35) 62%, rgba(255, 226, 163, 0) 100%),
    linear-gradient(currentColor 0 0) 50% 50% / 100% 2px no-repeat;
  animation: fx-muzzle .2s ease-out;
}
.battle-side[data-side="ally"] .unit.is-striking.strike-technique .fx-shot { top: 16%; }
.battle-side[data-side="enemy"] .unit.is-striking.strike-technique .fx-shot { top: 84%; }
@keyframes unit-hit {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0); }
  18% { transform: translate3d(calc(var(--hit) * -1), 0, 0) rotate(calc(var(--hit-tilt) * -1)); }
  42% { transform: translate3d(var(--hit), 0, 0) rotate(var(--hit-tilt)); }
  66% { transform: translate3d(calc(var(--hit) * -.45), 0, 0) rotate(0); }
  85% { transform: translate3d(calc(var(--hit) * .2), 0, 0) rotate(0); }
}
.unit.is-hit {
  --hit: 4px;
  --hit-tilt: 0deg;
  border-color: var(--bad);
  animation: unit-hit .3s cubic-bezier(.3, .9, .35, 1);
}
.unit.is-hit .fx-flash {
  background: radial-gradient(closest-side, rgba(255, 224, 216, .92), rgba(231, 137, 128, 0) 76%);
  animation: fx-flash .26s ease-out;
}
.unit.is-hit .fx-slash { animation: fx-slash .28s cubic-bezier(.2, .8, .3, 1); }
.unit.is-hit .fx-ring { color: var(--bad); animation: fx-ring .4s cubic-bezier(.15, .85, .3, 1); }
/* 受けた側も型で分ける。斬撃は刃が箱を横切り、銃撃は一点で弾ける。 */
.unit.is-hit.hit-technique .fx-slash { animation: none; }
.unit.is-hit.hit-technique .fx-shot { color: #ffd0c8; animation: fx-shot .3s cubic-bezier(.2, .85, .3, 1); }
.unit.is-hit.hit-technique .fx-ring { animation-duration: .3s; }
/* 重い一撃ほど大きく、長く揺れる。段は最大HPに対する割合で画面側が決める。 */
.unit.hit-2 { --hit: 7px; --hit-tilt: 1deg; animation-duration: .36s; }
.unit.hit-3 { --hit: 11px; --hit-tilt: 2.4deg; animation-duration: .46s; }
.unit.hit-2 .fx-ring { animation-duration: .48s; }
.unit.hit-3 .fx-ring { animation-duration: .6s; border-width: 3px; }
.unit.hit-3 .fx-flash { animation-duration: .34s; }
/* 倒れた瞬間だけの一拍。以後は `.defeated` の灰色がそのまま残る。 */
@keyframes unit-downed {
  0% { filter: brightness(2.1) saturate(.2); transform: translate3d(0, -2px, 0) rotate(0); }
  26% { filter: brightness(1.4) saturate(.5); transform: translate3d(0, -4px, 0) rotate(-1.5deg); }
  100% { filter: none; transform: translate3d(0, 4px, 0) rotate(2.5deg); }
}
.unit.is-downed { animation: unit-downed .6s cubic-bezier(.25, .8, .3, 1); }
@keyframes unit-pulse-good {
  0% { box-shadow: 0 0 0 0 rgba(155, 214, 158, .6); }
  100% { box-shadow: 0 0 0 12px rgba(155, 214, 158, 0); }
}
.unit.is-healed { border-color: var(--good); animation: unit-pulse-good .5s ease; }
.unit.is-healed .fx-flash {
  background: radial-gradient(closest-side, rgba(203, 243, 205, .7), rgba(155, 214, 158, 0) 74%);
  animation: fx-flash .42s ease-out;
}
.unit.is-healed .fx-ring { color: var(--good); animation: fx-ring .58s cubic-bezier(.2, .8, .3, 1) reverse; }
@keyframes unit-pulse-blue {
  0% { box-shadow: 0 0 0 0 rgba(145, 203, 213, .6); }
  100% { box-shadow: 0 0 0 12px rgba(145, 203, 213, 0); }
}
.unit.is-shielded { border-color: var(--blue); animation: unit-pulse-blue .5s ease; }
.unit.is-shielded .fx-ring { color: var(--blue); animation: fx-ring .5s cubic-bezier(.2, .8, .3, 1) reverse; }
.unit.is-shielded .fx-flash {
  background: radial-gradient(closest-side, rgba(196, 235, 243, .6), rgba(145, 203, 213, 0) 74%);
  animation: fx-flash .4s ease-out;
}
/* 止めた一撃。**受けた側は揺れず、硬く縮んで弾き返す。** */
@keyframes unit-blocked {
  0%, 100% { transform: scale(1); }
  28% { transform: scale(.955); }
  58% { transform: scale(1.025); }
}
.unit.is-blocked { border-color: var(--violet); animation: unit-blocked .34s cubic-bezier(.25, .9, .3, 1); }
.unit.is-blocked .fx-ring { color: var(--violet); animation: fx-ring .38s cubic-bezier(.15, .85, .3, 1); }

/* ---------------------------------------------------------------- 浮く数字
 *
 * 数字は盤面の層（`.battle-floats`）に置き、受けた箱の真上へ座標で刺す。
 * 箱の中に置いていたころは、味方の箱（顔のために overflow を閉じている）で
 * 消え、敵では一つ上の箱の中に出て持ち主が読めなかった。 */
.battle-floats {
  position: absolute;
  z-index: 5;
  overflow: hidden;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
}
/* 踏み込んだ先を結ぶ線。盤面の層に置き、二つの箱の中心を一度だけ結ぶ。 */
.strike-line {
  position: absolute;
  height: 3px;
  margin-top: -1.5px;
  border-radius: 999px;
  background: linear-gradient(90deg,
    rgba(255, 226, 163, 0) 0%, rgba(255, 247, 226, .95) 46%, rgba(255, 226, 163, 0) 100%);
  box-shadow: 0 0 10px 0 rgba(229, 184, 105, .95);
  opacity: 0;
  transform-origin: 0 50%;
  animation: strike-line .36s cubic-bezier(.1, .85, .3, 1) both;
  pointer-events: none;
}
@keyframes strike-line {
  0% { opacity: 0; clip-path: inset(0 100% 0 0); }
  20% { opacity: 1; clip-path: inset(0 0 0 0); }
  62% { opacity: .9; clip-path: inset(0 0 0 0); }
  100% { opacity: 0; clip-path: inset(0 0 0 72%); }
}
/* ---------------------------------------------------------------- 着弾の印
 *
 * 作者試遊 2026-09-14 — 型の違いを箱の中だけで描くと、100×72 の枠と丸角に切られて
 * 実機では読めない。**印は箱よりひと回り大きく、盤面の層へ置く。**
 * 違うのは光り方ではなく**形**である——斬撃は×、銃撃は一点で弾ける星。 */
.impact-mark {
  position: absolute;
  display: block;
  opacity: 0;
  pointer-events: none;
}
/* 斬撃。**二本の太刀が上から下へ走る。**作者指摘 2026-09-14 — 貼りついた×は
 * 「斬った」にならない。一の太刀・二の太刀の順に、刃の向きへ引かれ、同じ向きへ消える。
 * 引き方は `.strike-line`（飛ぶ線）と同じ clip-path の作りで、向きは各々の回転が持つ。 */
.impact-mark.weapon { opacity: 1; }
.impact-mark.weapon::before,
.impact-mark.weapon::after {
  position: absolute;
  top: 50%;
  left: -9%;
  width: 118%;
  height: 5px;
  margin-top: -2.5px;
  border-radius: 999px;
  content: "";
  background: linear-gradient(90deg,
    rgba(255, 226, 163, 0) 0%, rgba(255, 255, 255, .99) 38%,
    rgba(255, 240, 205, .95) 74%, rgba(255, 226, 163, 0) 100%);
  filter: drop-shadow(0 0 6px rgba(255, 205, 122, .95));
}
/* 一の太刀は右下へ、二の太刀は左下へ。**どちらも上の端から引かれ、下の端で消える。** */
.impact-mark.weapon::before {
  transform: rotate(62deg);
  animation: slash-draw .3s cubic-bezier(.12, .85, .3, 1) both;
}
.impact-mark.weapon::after {
  height: 3px;
  margin-top: -1.5px;
  transform: rotate(118deg);
  animation: slash-draw .3s cubic-bezier(.12, .85, .3, 1) .085s both;
}
@keyframes slash-draw {
  0% { opacity: 0; clip-path: inset(0 100% 0 0); }
  10% { opacity: 1; }
  32% { clip-path: inset(0 0 0 0); }
  60% { opacity: 1; clip-path: inset(0 0 0 0); }
  100% { opacity: 0; clip-path: inset(0 0 0 100%); }
}
/* 銃撃。芯が白く飛び、四方と斜めへ棘が伸びる。 */
.impact-mark.technique {
  background:
    radial-gradient(closest-side, rgba(255, 255, 255, .95) 0 11%, rgba(255, 236, 196, 0) 56%),
    linear-gradient(rgba(255, 252, 242, 1) 0 0) 50% 50% / 100% 3px no-repeat,
    linear-gradient(rgba(255, 252, 242, 1) 0 0) 50% 50% / 3px 100% no-repeat,
    linear-gradient(45deg, rgba(255, 246, 224, 0) 48.8%, rgba(255, 246, 224, .85) 50%, rgba(255, 246, 224, 0) 51.2%),
    linear-gradient(-45deg, rgba(255, 246, 224, 0) 48.8%, rgba(255, 246, 224, .85) 50%, rgba(255, 246, 224, 0) 51.2%);
  filter: drop-shadow(0 0 7px rgba(255, 226, 163, 1));
  animation: impact-shot .34s cubic-bezier(.12, .9, .3, 1) both;
}
@keyframes impact-shot {
  0% { opacity: 0; transform: scale(1.45) rotate(-10deg); }
  12% { opacity: 1; transform: scale(.72) rotate(0); }
  62% { opacity: 1; transform: scale(.86) rotate(0); }
  100% { opacity: 0; transform: scale(1.3) rotate(6deg); }
}

/* **線の飛び方は型で変えない。**作者指摘 2026-09-14 —「相手に線が飛ぶ従来の攻撃
 * モーションはかなりかっこいい」。光を一粒ずつ走らせる弾道も試したが、同じ距離が遅く
 * 見えて、その速さが消える。銃撃は**同じ速さのまま細く白く**するだけにして、型の差は
 * 着弾の印（×と星）と銃口の閃光が持つ。 */
.strike-line.technique {
  height: 2px;
  margin-top: -1px;
  background: linear-gradient(90deg,
    rgba(255, 226, 163, 0) 0%, rgba(255, 253, 246, 1) 52%, rgba(255, 226, 163, 0) 100%);
  box-shadow: 0 0 9px 0 rgba(255, 240, 205, .9);
}
/* 銃口の閃光。**線とは別の札**にする（線は clip-path で削られていくので、
 * 同じ札に乗せると閃光まで一緒に切り落とされる）。位置と角度は線と同じ計算から出る。 */
.muzzle-flash {
  position: absolute;
  width: 36px;
  height: 20px;
  margin: -10px 0 0 -18px;
  border-radius: 50%;
  opacity: 0;
  transform-origin: 50% 50%;
  background: radial-gradient(closest-side,
    rgba(255, 255, 255, .95), rgba(255, 226, 163, .5) 52%, rgba(255, 226, 163, 0) 100%);
  animation: muzzle-bloom .18s ease-out both;
  pointer-events: none;
}
@keyframes muzzle-bloom {
  0% { opacity: 0; scale: .4 .6; }
  20% { opacity: 1; scale: 1.15 1; }
  100% { opacity: 0; scale: .9 .8; }
}
.float {
  position: absolute;
  padding: 1px 6px;
  border-radius: 999px;
  font-size: 15px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .85);
  white-space: nowrap;
  animation: float-rise 1.2s cubic-bezier(.16, .84, .3, 1) both;
}
.float .float-cause {
  margin-left: 4px;
  color: var(--muted);
  font-size: 9px;
  font-style: normal;
  font-weight: 700;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .9);
}
/* **出たがりの一拍**。小さく飛び出して行き過ぎ、戻ってから昇って消える。 */
@keyframes float-rise {
  0% { opacity: 0; transform: translate(calc(-50% + var(--float-shift, 0px)), calc(-50% + 12px)) scale(.5) rotate(-5deg); }
  14% { opacity: 1; transform: translate(calc(-50% + var(--float-shift, 0px)), calc(-50% - 11px)) scale(1.3) rotate(2deg); }
  30% { opacity: 1; transform: translate(calc(-50% + var(--float-shift, 0px)), calc(-50% - 17px)) scale(1) rotate(0); }
  100% { opacity: 0; transform: translate(calc(-50% + var(--float-shift, 0px)), calc(-50% - 40px)) scale(.95) rotate(0); }
}
/* 芯を明るく、まわりを色で光らせる。9px の盤面では、塗りつぶしの色より
   「光っている字」のほうが遠くから読める。 */
.float.damage {
  color: #ffd0c8;
  text-shadow: 0 0 12px rgba(231, 137, 128, .9), 0 2px 0 #2b1112, 0 1px 4px rgba(0, 0, 0, .95);
}
.float.heal {
  color: #d6f4d7;
  text-shadow: 0 0 12px rgba(155, 214, 158, .85), 0 2px 0 #12240f, 0 1px 4px rgba(0, 0, 0, .95);
}
.float.barrier {
  color: #d3f0f6;
  text-shadow: 0 0 12px rgba(145, 203, 213, .85), 0 2px 0 #0f2228, 0 1px 4px rgba(0, 0, 0, .95);
}
/* 重い一撃は字も大きい。段は `.unit` の揺れと同じ割合（15% / 30%）で決まるので、
   **大きい字と大きい揺れが必ず一緒に出る。** */
.float.damage.heavy { font-size: 20px; }
.float.damage.crush {
  color: #fff3ec;
  font-size: 25px;
  text-shadow: 0 0 18px rgba(231, 137, 128, 1), 0 0 6px rgba(255, 236, 230, .9), 0 2px 0 #2b1112;
}
.float.heal.heavy { font-size: 18px; }
.float.heal.crush { font-size: 21px; }
.float.blocked { background: rgba(192, 167, 229, .2); color: var(--violet); font-size: 11px; }
.float.defeat {
  border: 1px solid rgba(231, 137, 128, .55);
  background: rgba(52, 18, 18, .82);
  color: #ffd7d0;
  font-size: 12px;
  letter-spacing: .16em;
}
.float.reaction { background: rgba(192, 167, 229, .16); color: var(--violet); font-size: 10px; font-weight: 700; }
.float.wear, .float.move { color: var(--muted); font-size: 10px; font-weight: 700; }
.float.bad { background: rgba(231, 137, 128, .2); color: var(--bad); font-size: 10px; }
.float.good { background: rgba(155, 214, 158, .18); color: var(--good); font-size: 10px; }
/* サブ行動・パッシブ由来は、主行動の数字より控えめに出す。
   同時に出るので、同じ強さだと何が主だったのか読めなくなる。 */
.float.from-rule { font-size: 12px; font-weight: 700; opacity: .92; text-shadow: 0 1px 3px rgba(0, 0, 0, .85); }

/* ---------------------------------------------------------------- 幕の帯
 *
 * 戦闘の開始・ラウンドの頭・決着だけ、盤面の真ん中で一度だけ大きく言う。
 * **拍の長さも順序も変えない**（帯は拍の中で始まり、拍の中で消える）。
 * 読み上げは拍の行が既に持っているので、帯は aria-hidden のまま二重に読ませない。 */
.battle-banner {
  position: absolute;
  z-index: 4;
  top: 50%;
  left: 0;
  display: none;
  width: 100%;
  margin-top: -26px;
  text-align: center;
  pointer-events: none;
}
.battle-banner.show { display: block; }
.battle-banner::before,
.battle-banner::after {
  position: absolute;
  z-index: -1;
  content: "";
  inset: -8px -6px;
  transform: skewX(-12deg);
}
/* 帯の地。**盤面と角度を変える**ので、一枚だけで「別の層」に見える。 */
.battle-banner::before {
  background: linear-gradient(90deg,
    rgba(10, 15, 16, 0) 0%, rgba(10, 15, 16, .9) 18%,
    rgba(10, 15, 16, .9) 82%, rgba(10, 15, 16, 0) 100%);
}
/* 上下の細い線。端は溶かす（角度の付いた帯に角を作らない）。 */
.battle-banner::after {
  color: var(--banner-ink, var(--gold));
  background:
    linear-gradient(90deg, transparent, currentColor 26%, currentColor 74%, transparent) 0 0 / 100% 1px no-repeat,
    linear-gradient(90deg, transparent, currentColor 26%, currentColor 74%, transparent) 0 100% / 100% 1px no-repeat;
  opacity: .6;
}
.battle-banner b {
  display: block;
  color: #fff6e4;
  font-size: 27px;
  font-weight: 800;
  letter-spacing: .18em;
  line-height: 1.05;
  text-shadow: 0 0 20px var(--banner-glow, rgba(229, 184, 105, .95)), 0 2px 0 #16100a;
}
.battle-banner i {
  display: block;
  margin-top: 3px;
  color: var(--banner-ink, var(--gold));
  font-size: 10px;
  font-style: normal;
  font-weight: 700;
  letter-spacing: .34em;
}
.battle-banner.win { --banner-ink: var(--good); --banner-glow: rgba(155, 214, 158, .95); }
.battle-banner.lose { --banner-ink: var(--bad); --banner-glow: rgba(231, 137, 128, .95); }
.battle-banner.draw { --banner-ink: var(--muted); --banner-glow: rgba(158, 173, 167, .8); }
@keyframes banner-word {
  0% { opacity: 0; letter-spacing: .7em; transform: scale(1.25); }
  24% { opacity: 1; letter-spacing: .18em; transform: scale(1); }
  70% { opacity: 1; }
  100% { opacity: 0; transform: scale(1.05); }
}
@keyframes banner-sub {
  0%, 12% { opacity: 0; transform: translateY(4px); }
  34% { opacity: 1; transform: translateY(0); }
  70% { opacity: 1; }
  100% { opacity: 0; }
}
@keyframes banner-band {
  0% { opacity: 0; transform: skewX(-12deg) scaleX(.34); }
  26% { opacity: .85; transform: skewX(-12deg) scaleX(1); }
  70% { opacity: .85; }
  100% { opacity: 0; transform: skewX(-12deg) scaleX(1.07); }
}
.battle-banner.run b { animation: banner-word .66s cubic-bezier(.17, .89, .25, 1) both; }
.battle-banner.run i { animation: banner-sub .66s ease-out both; }
.battle-banner.run::before,
.battle-banner.run::after { animation: banner-band .66s cubic-bezier(.17, .89, .25, 1) both; }
/* 作者試遊 2026-09-13 — **決着の帯は残す。**開始とラウンドの帯は次の拍へ場所を
 * 譲るので流れて消えるが、VICTORY / DEFEAT はそこで再生が止まる拍なので、
 * 同じ入りかたをしたまま終わりだけを開いた状態で止める（`.hold`）。 */
@keyframes banner-word-hold {
  0% { opacity: 0; letter-spacing: .7em; transform: scale(1.25); }
  24%, 100% { opacity: 1; letter-spacing: .18em; transform: scale(1); }
}
@keyframes banner-sub-hold {
  0%, 12% { opacity: 0; transform: translateY(4px); }
  34%, 100% { opacity: 1; transform: translateY(0); }
}
@keyframes banner-band-hold {
  0% { opacity: 0; transform: skewX(-12deg) scaleX(.34); }
  26%, 100% { opacity: .85; transform: skewX(-12deg) scaleX(1); }
}
/* 帯が残っているあいだ、拍の行は場所を譲る（ラウンドと拍数は帯の外なので残す）。
 * 消すのは見た目だけで、読み上げ（aria-live）はそのまま拍の行が持つ。 */
.battle-field.verdict-hold .beat-text { opacity: 0; }
.battle-banner.run.hold b { animation-name: banner-word-hold; }
.battle-banner.run.hold i { animation-name: banner-sub-hold; }
.battle-banner.run.hold::before,
.battle-banner.run.hold::after { animation-name: banner-band-hold; }
.battle-beat {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 9px;
  padding: 9px 11px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-left: 3px solid var(--beat-accent, var(--gold));
  border-radius: 9px;
  background: linear-gradient(100deg, #253031 0%, #1c2527 70%);
  box-shadow: inset 0 0 22px -14px var(--beat-accent, var(--gold));
  min-height: 54px;
  transition: border-color .2s ease;
}
/* 拍の種類で左の帯の色を変える。**いま何の拍なのか**は、読む前に色で分かる。 */
.battle-beat[data-kind="declare"] { --beat-accent: var(--gold); }
.battle-beat[data-kind="impact"] { --beat-accent: var(--gold); }
.battle-beat[data-kind="ultimate"] { --beat-accent: #ffd98a; }
.battle-beat[data-kind="defeat"] { --beat-accent: var(--bad); }
.battle-beat[data-kind="opening"],
.battle-beat[data-kind="round"],
.battle-beat[data-kind="prepare"] { --beat-accent: var(--blue); }
.battle-beat[data-kind="blocked"],
.battle-beat[data-kind="skipped"],
.battle-beat[data-kind="sub"] { --beat-accent: var(--violet); }
.battle-beat[data-kind="move"] { --beat-accent: var(--muted); }
.battle-beat[data-kind="ending"] { --beat-accent: var(--good); }
/* 拍が変わるたびに一度だけ光が横切る。**盤面ではなく行が変わった**ことの合図。 */
.battle-beat.pulse::after {
  position: absolute;
  z-index: 0;
  content: "";
  inset: 0;
  background: linear-gradient(100deg,
    rgba(255, 255, 255, 0) 32%, rgba(255, 255, 255, .1) 50%, rgba(255, 255, 255, 0) 68%);
  animation: beat-sweep .5s ease-out;
  pointer-events: none;
}
@keyframes beat-sweep {
  0% { opacity: 0; transform: translateX(-62%); }
  28% { opacity: 1; }
  100% { opacity: 0; transform: translateX(62%); }
}
.beat-round, .beat-text, .beat-count { position: relative; z-index: 1; }
.beat-round {
  padding: 2px 5px;
  border: 1px solid var(--beat-accent, var(--gold));
  border-radius: 5px;
  color: var(--beat-accent, var(--gold));
  font-size: 10px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
/* **一行と二行で高さを変えない。**拍ごとに盤面が上下すると、
   踏み込みや揺れが読めなくなる（動かしたいのは箱であって、盤面ではない）。 */
.beat-text {
  display: -webkit-box;
  overflow: hidden;
  margin: 0;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.35;
}
.beat-count { color: var(--muted); font-size: 9px; font-variant-numeric: tabular-nums; }
@keyframes beat-in {
  0% { opacity: 0; transform: translateX(-7px); }
  55% { opacity: 1; }
  100% { opacity: 1; transform: translateX(0); }
}
.beat-text.pulse { animation: beat-in .26s cubic-bezier(.2, .85, .3, 1); }
.replay-transport { display: grid; grid-template-columns: 1fr 1.5fr 1fr; gap: 5px; margin-top: 12px; }
.replay-transport .button { margin-top: 0; padding: 9px 4px; font-size: 11px; }
.replay-speed { display: flex; align-items: center; gap: 5px; margin-top: 7px; }
.replay-speed-label { color: var(--muted); font-size: 10px; }
.speed-button {
  flex: 1;
  padding: 6px 4px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--panel-2);
  color: var(--muted);
  font-size: 10px;
}
.speed-button.active { border-color: var(--gold); background: var(--gold-dark); color: var(--gold); }
/* 作者試遊 2026-09-13 — 前進の釦。［一気に決着へ］と［次へ］は同じ場所で
 * 入れ替わるので、隠したほうは場所も取らない（`hidden` を明示的に畳む）。 */
.replay-finish > .button[hidden] { display: none; }
.debug-log { margin-top: 13px; }
.debug-log summary { color: var(--muted); cursor: pointer; font-size: 11px; }
.debug-log .replay-events { max-height: 260px; }
.debug-log .event.current { color: var(--gold); }
.debug-log .event.from-rule .event-type { color: var(--violet); }
.event-type { margin-left: auto; color: #6d7d77; font: 9px/1.4 ui-monospace, monospace; }
/* ---------------------------------------------------------------- 必殺のカットイン（issue #242）
 *
 * **必殺は一人一遠征に一度きり**なので、ここだけは盤面を止めて一拍ぶん奪う。
 * 拍そのものは `replay-beats.mjs` が組んでいる（`kind: "ultimate"`）。この節は
 * その一拍の絵だけを持ち、**速さや順序には触らない**（飛ばす手段は速度変更と一手送り）。
 */
.battle-field { position: relative; }
.battle-field.ultimate-hold .battle-side,
.battle-field.ultimate-hold .battle-beat {
  /* 盤面をもう一段深く沈める。**帯だけが前に出ている**ことを、明るさと彩度の
     両方で言う（枠線の色を変えると、行動中・被弾の枠表示と混ざる）。 */
  filter: saturate(.32) brightness(.46);
  transition: filter .2s ease;
}
.battle-field.ultimate-hold .battle-side { transform: scale(.985); transition: filter .2s ease, transform .2s ease; }
.ultimate-cutin {
  position: absolute;
  z-index: 3;
  display: none;
  place-items: center;
  inset: 0;
  overflow: hidden;
  border-radius: 13px;
  pointer-events: none;
}
.ultimate-cutin.show { display: grid; }
/* 速度線。斜めの細い線が帯より速く走り抜ける。 */
.cutin-lines {
  position: absolute;
  inset: -30% -20%;
  background: repeating-linear-gradient(100deg,
    rgba(255, 243, 214, 0) 0 9px,
    rgba(255, 243, 214, .16) 9px 10px,
    rgba(255, 243, 214, 0) 10px 21px);
  opacity: 0;
}
/* 斬線。帯の上を一度だけ横切る。 */
.cutin-slash {
  position: absolute;
  inset: -60% -10%;
  background: linear-gradient(102deg,
    rgba(255, 255, 255, 0) 44%, rgba(255, 250, 235, .95) 50%, rgba(255, 255, 255, 0) 56%);
  opacity: 0;
}
.cutin-sheet {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 14px;
  /* 斜めに走る帯。**盤面の長方形と角度を変える**ので、一枚だけで「別の層」に見える。 */
  background:
    linear-gradient(100deg, rgba(14, 20, 22, 0) 0%, rgba(14, 20, 22, .94) 7%,
      rgba(44, 34, 19, .98) 50%, rgba(14, 20, 22, .94) 93%, rgba(14, 20, 22, 0) 100%);
  border-block: 1px solid rgba(229, 184, 105, .55);
  box-shadow: 0 0 26px -6px rgba(229, 184, 105, .55);
}
/* 閃光。中心から一度だけ開いて消える。 */
.cutin-burst {
  position: absolute;
  inset: -40% -10%;
  background: radial-gradient(closest-side, rgba(255, 243, 214, .5), rgba(255, 243, 214, 0) 70%);
  opacity: 0;
}
.cutin-figure {
  position: relative;
  flex: 0 0 auto;
  width: 58px;
  height: 58px;
  overflow: hidden;
  border: 1px solid var(--accent, var(--gold));
  border-radius: 50%;
  background: rgba(9, 13, 14, .85);
  box-shadow: 0 0 14px -4px var(--accent, var(--gold));
}
.cutin-figure .portrait-svg { width: 100%; height: auto; }
.cutin-copy { display: grid; gap: 2px; min-width: 0; }
.cutin-who { color: var(--accent, var(--gold)); font-size: 10px; letter-spacing: .18em; }
.cutin-skill {
  color: #fff6e0;
  font-size: 17px;
  letter-spacing: .04em;
  line-height: 1.2;
  text-shadow: 0 0 12px rgba(229, 184, 105, .85), 0 1px 0 #1b1405;
}
.cutin-traits { display: flex; flex-wrap: wrap; gap: 4px; }
.cutin-traits span {
  padding: 1px 6px;
  border: 1px solid rgba(229, 184, 105, .7);
  border-radius: 999px;
  color: var(--gold);
  font-size: 9px;
}
/* 動きは「来た一拍」だけ。`.run` は画面側が拍の頭で付け直す。 */
.ultimate-cutin.run .cutin-sheet { animation: cutin-sheet .34s cubic-bezier(.17, .89, .25, 1) both; }
.ultimate-cutin.run .cutin-burst { animation: cutin-burst .62s ease-out both; }
.ultimate-cutin.run .cutin-figure { animation: cutin-figure .46s cubic-bezier(.17, .89, .25, 1) both; }
.ultimate-cutin.run .cutin-skill { animation: cutin-skill .4s ease-out .08s both; }
.ultimate-cutin.run .cutin-lines { animation: cutin-lines .56s cubic-bezier(.1, .8, .3, 1) both; }
.ultimate-cutin.run .cutin-slash { animation: cutin-slash .46s cubic-bezier(.2, .85, .25, 1) .1s both; }
.ultimate-cutin.run .cutin-who { animation: cutin-who .44s ease-out .04s both; }
@keyframes cutin-sheet {
  0% { opacity: 0; transform: translateX(-14%) skewX(-7deg); }
  100% { opacity: 1; transform: translateX(0) skewX(0); }
}
@keyframes cutin-burst {
  0% { opacity: 0; transform: scale(.5); }
  18% { opacity: 1; }
  100% { opacity: 0; transform: scale(1.35); }
}
@keyframes cutin-figure {
  0% { opacity: 0; transform: translateX(-18px) scale(.82); }
  100% { opacity: 1; transform: translateX(0) scale(1); }
}
@keyframes cutin-skill {
  0% { opacity: 0; clip-path: inset(0 100% 0 0); }
  100% { opacity: 1; clip-path: inset(0 0 0 0); }
}
@keyframes cutin-lines {
  0% { opacity: 0; transform: translateX(-26%); }
  30% { opacity: 1; }
  100% { opacity: 0; transform: translateX(26%); }
}
@keyframes cutin-slash {
  0% { opacity: 0; transform: translateX(-58%) skewX(-10deg); }
  26% { opacity: 1; }
  100% { opacity: 0; transform: translateX(58%) skewX(-10deg); }
}
@keyframes cutin-who {
  0% { opacity: 0; letter-spacing: .52em; }
  100% { opacity: 1; letter-spacing: .18em; }
}
@media (prefers-reduced-motion: reduce) {
  /* **カットインそのものは残す**（必殺が出たことが読めなくなる）。動きだけ止める。 */
  .ultimate-cutin.run .cutin-sheet,
  .ultimate-cutin.run .cutin-burst,
  .ultimate-cutin.run .cutin-figure,
  .ultimate-cutin.run .cutin-skill,
  .ultimate-cutin.run .cutin-lines,
  .ultimate-cutin.run .cutin-slash,
  .ultimate-cutin.run .cutin-who { animation: none; }
  .battle-field.ultimate-hold .battle-side,
  .battle-field.ultimate-hold .battle-beat { transition: none; }
  .battle-field.ultimate-hold .battle-side { transform: none; transition: none; }
}

@media (max-width: 380px) {
  .cutin-figure { width: 48px; height: 48px; }
  .cutin-skill { font-size: 15px; }
  .battle-row { grid-template-columns: 22px 1fr; }
  .battle-units { gap: 4px; }
  .unit { padding: 5px 4px 6px; }
  .unit { padding: 6px; }
  .beat-text { font-size: 12px; }
  .battle-banner b { font-size: 23px; }
  .float.damage.crush { font-size: 22px; }
}
/* **動きだけを止める。**色・数字・印は動かない側にも全部残るので、何が起きたかは
   止めても読める（帯とカットインは出したまま、走らせるのをやめる）。 */
@media (prefers-reduced-motion: reduce) {
  .unit, .unit-fill, .unit-recovered, .unit-recoverable, .unit-unrecoverable, .unit-barrier-fill, .beat-text, .replay-progress-fill { animation: none !important; transition: none !important; }
  .battle-field, .battle-field::before, .battle-beat.pulse::after, .unit-fx > i { animation: none !important; }
  .battle-field.ultimate-hold .battle-side { transform: none; }
  .unit.is-acting { transform: none; }
  .unit.is-aimed .fx-reticle { opacity: .75; }
  .float { animation: none; opacity: 1; transform: translate(calc(-50% + var(--float-shift, 0px)), calc(-50% - 16px)); }
  .strike-line { animation: none; opacity: .85; }
  /* 動きを止めても**どちらの型で当たったかは残す。**銃撃は弾着の火花を出したままにし、
   * 撃つ側の銃口の閃光だけを消す（線と火花で、誰がどう当てたかは読める）。 */
  .unit.is-hit.hit-technique .fx-shot { opacity: .85; }
  .impact-mark { animation: none; opacity: .9; }
  /* 二本の太刀は**引かれずに、引かれ終わった形**で出す（動きだけを止める）。 */
  .impact-mark.weapon::before,
  .impact-mark.weapon::after { animation: none; opacity: .9; clip-path: none; }
  .muzzle-flash { animation: none; opacity: .9; }
  /* 帯は**出したまま**にする（動きだけ止める）。決着の帯は元から止まったままなので、
   * `.hold` も同じに扱えばよい。 */
  .battle-banner.run b,
  .battle-banner.run i,
  .battle-banner.run::before,
  .battle-banner.run::after,
  .battle-banner.run.hold b,
  .battle-banner.run.hold i,
  .battle-banner.run.hold::before,
  .battle-banner.run.hold::after { animation: none; }
}

/* ------------------------------------------------------------------ PHASE B
   遠征を仕立てる画面、ギルド投資、補給、精算。
   R6 §15.1（遠征開始に全部出す）と §15.2（base 値・鍛錬・run 内補正を分ける）。
   iPhone 実寸（390px）で主要操作が画面内に収まることを ecology-trial が見る。 */

.pack-list { display: grid; gap: 6px; margin-top: 12px; }
.pack-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 10px;
  padding: 9px 10px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--panel-2);
}
.pack-row b { grid-column: 1; font-size: 12px; }
.pack-row small { grid-column: 1; color: var(--muted); font-size: 10px; line-height: 1.4; }
.pack-row span { grid-column: 2; grid-row: 1 / span 2; align-self: center; font-size: 10px; }
.pack-row.on { border-color: var(--gold); }
.pack-row.on span { color: var(--gold); }
.pack-row.off { opacity: .55; }

/* 遠征の形。**12戦を並べれば、幕もボスの位置も説明せずに読める。** */
/* 旧 .act-*（3幕12戦の並び）は 2026-09-15 に撤去した。どの区画でも同じ並びだった。 */

.boss-at {
  margin-left: auto;
  color: var(--muted);
  font-size: 10px;
  white-space: nowrap;
}

/* 区画で分かること。**読み物ではなく、持って入る覚え書き。** */
/* 旧 .learning-notes（区画の学びの覚え書き）は 2026-09-15 に撤去した。 */

.boss-grid { display: grid; gap: 8px; margin-top: 12px; }
.boss-card {
  padding: 10px;
  border: 1px solid rgba(231,137,128,.42);
  border-radius: 10px;
  background: rgba(78, 37, 37, .28);
}
.boss-card p { margin: 7px 0 0; color: #e8c4bd; font-size: 11px; line-height: 1.5; }
.boss-counters { margin: 7px 0 0; padding-left: 16px; color: var(--muted); font-size: 10px; line-height: 1.6; }
.boss-top { display: flex; align-items: center; gap: 8px; }
.boss-top b, .boss-top small { display: block; }
.boss-top small { color: var(--gold); font-size: 10px; }

.difficulty-grid { display: grid; gap: 6px; margin: 12px 0; }
.difficulty-card {
  display: grid;
  gap: 3px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--panel-2);
  color: var(--ink);
  text-align: left;
}
.difficulty-card b {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
}
.difficulty-card small { color: var(--muted); font-size: 10px; line-height: 1.4; }
/* 踏破済みの印。**色ではなく形で出す**（色だけの違いは、色が読めない画面で消える）。 */
.stage-clear-mark { display: inline-flex; color: var(--good); }
.stage-clear-mark .glyph { width: 12px; height: 12px; }
/* 作者指摘 2026-09-15 — 札が持つのは**札どうしで違う三つの数**だけ。同行者の名前を
   並べていた旧版は、全員が揃ったあとの区画で同じ一行を何枚も繰り返していた。 */
.difficulty-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin-top: 2px;
  color: var(--blue);
  font-size: 10px;
}
.difficulty-meta > span { display: inline-flex; align-items: center; gap: 3px; }
.difficulty-meta .glyph { width: 11px; height: 11px; opacity: .8; }
.difficulty-card.selected { border-color: var(--gold); background: var(--gold-dark); }
.difficulty-card.selected .difficulty-meta { color: var(--gold); }

/* ---- ギルドの貼りつく上端（作者指摘 2026-09-15）。
   キャンプの `.camp-top` と同じ作りで、活動資金と札を一つの塊にする。
   **活動資金は画面に一度だけ。**開いた先の見出しで言い直さない。 */
.guild-top {
  position: sticky;
  top: 0;
  z-index: 3;
  margin: 0 -2px 10px;
  /* 下の余白は padding で取る（.camp-top と同じ理由——margin では下をくぐる本文に効かない）。 */
  padding: 4px 2px 10px;
  background: rgba(14, 20, 22, .95);
  backdrop-filter: blur(10px);
}
.guild-top .tabs {
  position: static;
  margin: 0;
  background: transparent;
  backdrop-filter: none;
}
.guild-funds {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: 6px;
  padding: 0 6px 5px;
  color: var(--gold);
}
.guild-funds .guild-funds-mark {
  width: 13px;
  height: 13px;
  align-self: center;
  opacity: .85;
}
.guild-funds b { font-size: 15px; letter-spacing: .02em; }
.guild-funds small { color: var(--muted); font-size: 9.5px; }

/* 節の一行注記。**規則の段を置くほどではないもの**（ここは何の画面か、戦闘には効かない）。 */
.tab-note {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin: 8px 0 12px;
  color: var(--muted);
  font-size: 10.5px;
  line-height: 1.5;
}
.tab-note .glyph { width: 13px; height: 13px; flex: 0 0 auto; margin-top: 1px; opacity: .8; }
/* 取り消せない買い物。**赤い一行は画面に一つだけ。**増やすと、どれも読まれない。 */
.guild-caution {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 8px 0 2px;
  color: var(--bad);
  font-size: 11px;
  font-weight: 700;
}
.guild-caution .glyph { width: 13px; height: 13px; }

/* 連れていく隊。**能力値は issue #236 の共通形をそのまま使う**ので、ここが持つのは
   行の枠と、投資へ飛ぶ釦の置き場だけである（旧 .cast-chip は隊の行が引き取った）。 */
.plan-stage { margin: 2px 0 12px; }
.plan-stage b { display: block; color: var(--gold); font-size: 15px; }
/* 旧・隊の行（.roster-row）は 2026-09-16 に人物の札（.character-panel）へ移した。
   図像と役どころで人を指すのをやめ、顔で指すようにしたので、行そのものが要らなくなった。 */

/* 絞り込みの粒。**折り返さず横へ流す**（旧版は 8 個の釦が 2 列 5 段になっていた）。 */
.filter-chips {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  margin: 10px 0;
  padding-bottom: 3px;
}
.filter-chips .tiny-button { flex: 0 0 auto; margin: 0; }

/* 出撃の一枚。**この札の用は出ることだけなので、釦は札の頭に置く。**
   作者指摘 2026-09-15（二度目）「遠征に進むボタンがめっちゃ下にある」。 */
.launch-card .button { margin-top: 12px; }
.launch-card .help-details {
  margin: 12px 0 0;
  border: 0;
  border-top: 1px solid var(--line);
  border-radius: 0;
  padding: 0;
  background: transparent;
}
.launch-card .help-details summary { padding: 10px 0 0; }

.purchase-list { display: grid; gap: 6px; margin-top: 10px; }
/* 作者要望 2026-09-13 — 投資の行は「記号・中身・値段」の三列。**段は目盛りが言う。** */
.purchase-row {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: var(--panel-2);
}
.purchase-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background: var(--panel-3);
  color: var(--gold);
}
.purchase-mark .glyph { width: 16px; height: 16px; }
.purchase-copy { display: grid; gap: 4px; }
.purchase-copy b { display: block; font-size: 12px; }
.purchase-copy small { display: block; color: var(--muted); font-size: 10px; line-height: 1.4; }
.purchase-copy .meter { margin-top: 1px; }
.purchase-copy .meter-label {
  min-width: 46px;
  color: var(--muted);
  font-size: 9.5px;
  font-variant-numeric: tabular-nums;
}
.purchase-buy {
  display: grid;
  justify-items: end;
  gap: 4px;
}
.purchase-cost { color: var(--gold); font-size: 11px; font-variant-numeric: tabular-nums; }
.purchase-done { display: flex; color: var(--good); }
.purchase-done .glyph { width: 16px; height: 16px; }
.purchase-row .tiny-button { margin: 0; }
.purchase-row.done { border-color: rgba(155,214,158,.35); }
.purchase-row.done .purchase-mark { color: var(--good); }
.purchase-row.done .purchase-cost { color: var(--muted); }
/* 買えない行は**消さずに沈める。**何が買えないかは、値段と一緒に見えていてよい。 */
.purchase-row.short .purchase-cost { color: var(--muted); }
/* 鍛錬の行。基礎値 → 現在値 → 次の一段を、矢印一本で並べる。 */
.train-row .purchase-copy b {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}
.train-values {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.train-values i {
  color: var(--muted);
  font-size: 9.5px;
  font-style: normal;
}
.train-values em {
  color: var(--ink);
  font-size: 14px;
  font-style: normal;
}
.train-next { color: var(--gold); font-size: 11px; }
.train-stall { color: var(--orange) !important; font-size: 9.5px !important; }
/* 旧 .train-summary（「鍛える相手 ゴウ」の札）と .warn-grid（赤い規則の段）は、
   作者指摘 2026-09-15 で撤去した。相手は仲間の帯が、取り消せないことは
   `.guild-caution` の一行が言う。 */
/* issue #159 — 治療専用の対象一覧（.treatment-target-picker）はここにあった。
   対象は上端の共通盤面から選ぶ。 */
.supply-treatment-result {
  margin: 10px 0;
  padding: 9px 10px;
  border: 1px solid var(--good);
  border-radius: 9px;
  background: rgba(37, 73, 54, .35);
}
.supply-treatment-result p {
  margin: 0;
  line-height: 1.55;
}
.supply-treatment-result p + p { margin-top: 4px; }
.training-heading { margin-top: 16px; color: var(--ink); font-size: 13px; }

.supplies-bar { margin-top: 10px; }
.supplies-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.supplies-head b { font-size: 13px; }
.supplies-head span { color: var(--muted); font-size: 10px; }
.supplies-head b .glyph { margin-right: 5px; color: var(--gold); }
.supplies-bar .meter { margin: 9px 0 2px; }
/* 用途の名札。**三つ並ぶことが「取り合い」の説明である。** */
.supply-uses-grid { grid-template-columns: 1fr 1fr 1fr; gap: 5px; }
.supply-uses-grid .rule-cell {
  grid-template-columns: 1fr;
  justify-items: center;
  gap: 5px;
  padding: 8px 6px;
  text-align: center;
}
.supply-uses-grid .rule-copy { justify-content: center; }
.supply-uses-grid .rule-copy small { font-size: 9px; }

.act-line { margin: 0 0 6px; color: var(--blue); font-size: 11px; }
.enemy-card.boss { border-color: var(--gold); background: rgba(90, 68, 26, .3); }
.enemy-badges { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.enemy-badges .badge {
  padding: 2px 6px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--gold);
  font-size: 9px;
}
.enemy-card p.small { min-height: 0; font-size: 9px; }

.reward-picker { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 8px; }
.reward-pick {
  padding: 5px 8px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel-2);
  color: var(--muted);
  font-size: 10px;
}
.reward-pick.selected { border-color: var(--gold); background: var(--gold-dark); color: var(--gold); }
.reward-reroll { margin-top: 12px; }
.reward-reroll small { display: block; margin-top: 5px; color: var(--muted); font-size: 10px; line-height: 1.5; }

/* 精算の締め。合計は**一つだけ大きく**する（並べて大きくすると、どれも大きくない）。 */
.settle-total {
  margin-top: 11px;
  padding-top: 9px;
  border-top: 1px solid var(--line);
}
.settle-row.grand { align-items: baseline; }
.settle-row.grand span { color: var(--ink); }
.settle-row.grand b { font-size: 19px; }
/* 開いた区画。**「が開いた」と書く代わりに、旗を立てる。** */
.unlock-card {
  display: flex;
  align-items: center;
  gap: 12px;
  border-color: rgba(229,184,105,.45);
  background: linear-gradient(140deg, rgba(90,68,26,.4), rgba(21,29,31,.95));
}
.unlock-glyph {
  width: 26px;
  height: 26px;
  color: var(--gold);
}
.unlock-card small {
  display: block;
  color: var(--muted);
  font-size: 10px;
  letter-spacing: .05em;
}
.unlock-card b {
  display: block;
  margin-top: 2px;
  color: var(--gold);
  font-size: 15px;
}
/* 決着の一枚の中では、数のタイルと二列は**左揃え**に戻す（中央揃えの数は読みにくい）。 */
.verdict-plate .stat-tiles,
.verdict-plate .split-columns { text-align: left; }
.stage .glyph,
.count .glyph { margin-right: 4px; vertical-align: -2px; }

.settle-list { display: grid; gap: 4px; margin-top: 10px; }
.settle-row {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 7px 9px;
  border-bottom: 1px solid var(--line);
  font-size: 12px;
}
.settle-row span { color: var(--muted); }
.settle-row b { font-variant-numeric: tabular-nums; }
.settle-row.total b { color: var(--gold); }
.fund-line { display: flex; align-items: baseline; gap: 10px; margin: 8px 0 12px; }
.fund-line b { color: var(--gold); font-size: 20px; font-variant-numeric: tabular-nums; }
.fund-line small { color: var(--muted); font-size: 10px; }

.scrap-line {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  margin: 8px 0 4px;
  color: var(--muted);
  font-size: 11px;
}
.scrap-line b { color: var(--ink); }
.scrap-line .tiny-button { margin: 0; }

.character-stats .trained { color: var(--gold); font-style: normal; }

/* ---------------------------------------------------------------- 遠征装備と Blueprint
 *
 * 装備等級と効果品質は、色だけでなく格番号・文字・枠でも区別する。
 * iPhone の小さい画面でも「装備全体」と「個別効果」を混同しないための表示。 */
.rarity-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: 6px;
  padding: 2px 7px 2px 5px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .01em;
  vertical-align: middle;
}
.rarity-rank, .effect-rarity-rank {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 14px;
  height: 14px;
  border-radius: 50%;
  background: rgba(0,0,0,.22);
  font-size: 8px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.rarity-chip.rarity-common, .effect-rarity.rarity-common {
  color: var(--muted);
  border-color: #536466;
}
.rarity-chip.rarity-rare, .effect-rarity.rarity-rare {
  color: var(--blue);
  border-color: #3f6068;
  background: rgba(63,96,104,.16);
}
.rarity-chip.rarity-epic, .effect-rarity.rarity-epic {
  color: var(--violet);
  border-color: #66528a;
  background: rgba(102,82,138,.16);
}
.rarity-chip.rarity-legendary, .effect-rarity.rarity-legendary {
  color: var(--gold);
  border-color: #8b692d;
  background: var(--gold-dark);
}
.rarity-chip.rarity-mythic, .effect-rarity.rarity-mythic {
  color: #f2a4bd;
  border-color: #8d5069;
  background: rgba(141,80,105,.18);
}
.rarity-chip.rarity-oopart, .effect-rarity.rarity-oopart {
  color: #80e8e2;
  border-color: #388d91;
  background: linear-gradient(100deg, rgba(56,141,145,.18), rgba(147,104,201,.2));
}
.effect-rarity {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  width: fit-content;
  padding: 2px 5px;
  border: 1px solid currentColor;
  border-radius: 6px;
  font-size: 9px;
  font-weight: 800;
  line-height: 1.1;
  white-space: nowrap;
}
.equipment-effect-details {
  display: grid;
  gap: 4px;
  margin: 6px 0 7px;
}
.equipment-effect-detail {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr);
  align-items: start;
  gap: 4px;
  font-size: 10px;
}
.effect-detail-label {
  color: var(--ink);
  font-weight: 800;
  white-space: nowrap;
}
.effect-detail-summary {
  min-width: 0;
  color: var(--muted);
  line-height: 1.35;
}
.equipment-rule-line {
  margin: 4px 0 0;
  color: var(--muted);
  font-size: 10px;
  line-height: 1.35;
}
.risk-line {
  margin: 6px 0 0;
  padding: 5px 7px;
  border-left: 3px solid #d36b64;
  border-radius: 4px;
  color: #f0aaa4;
  background: rgba(143, 54, 49, .18);
  font-size: 10px;
  line-height: 1.4;
}
.gear-copy .equipment-rule-line {
  margin-top: 4px;
}
.reward-card .equipment-rule-line {
  min-height: 0;
  margin-bottom: 5px;
}
.rarity-callout {
  display: flex;
  min-height: 0;
  align-items: center;
  gap: 5px;
  margin: 5px 0 7px;
  padding: 5px 7px;
  border: 1px solid currentColor;
  border-radius: 7px;
  font-size: 10px;
  font-weight: 800;
}
.rarity-callout-mark {
  font-size: 14px;
  line-height: 1;
}
.rarity-callout.rarity-epic {
  color: #c7a9f4;
  background: rgba(102,82,138,.2);
}
.rarity-callout.rarity-legendary {
  color: var(--gold);
  background: var(--gold-dark);
}
.rarity-callout.rarity-mythic {
  color: #f2a4bd;
  background: rgba(141,80,105,.18);
}
.rarity-callout.rarity-oopart {
  color: #80e8e2;
  background: linear-gradient(100deg, rgba(56,141,145,.18), rgba(147,104,201,.2));
}
.reward-card.rarity-card-epic {
  border-color: #66528a;
}
.reward-card.rarity-card-legendary {
  border-color: #8b692d;
  background: linear-gradient(145deg, rgba(57,47,30,.98), rgba(21,29,31,.97));
  box-shadow: 0 0 0 1px rgba(229,184,105,.1), 0 12px 30px rgba(0,0,0,.2);
}
.reward-card.rarity-card-mythic {
  border-color: #8d5069;
  background: linear-gradient(145deg, rgba(56,34,45,.98), rgba(21,29,31,.97));
  box-shadow: 0 0 0 1px rgba(242,164,189,.1), 0 12px 30px rgba(0,0,0,.2);
}
.reward-card.rarity-card-oopart {
  border-color: #388d91;
  background: linear-gradient(145deg, rgba(25,59,61,.98), rgba(38,30,57,.97));
  box-shadow: 0 0 0 1px rgba(128,232,226,.12), 0 12px 30px rgba(0,0,0,.2);
}

.carried-chip {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--panel-3);
  color: var(--blue);
  font-size: 10px;
  vertical-align: middle;
}

.gear-card .gear-copy small + small { margin-top: 3px; }

.reward-card.disabled { opacity: .55; }
.keystone-line { color: var(--gold); font-size: 11px; }

.blueprint-card { display: flex; flex-direction: column; }
.blueprint-card.selected { border-color: var(--gold); background: var(--gold-dark); }
.blueprint-card small { display: block; margin-top: 6px; }
.blueprint-card .tiny-button { margin-top: 8px; }

/* ---------------------------------------------------------------- R9 チュートリアルの物語
 *
 * 会話は説明画面ではないので、カードの中で読み物として落ち着かせる。
 * **飛ばすボタンを目立たせる**（既知になった後の再訪で税にしない）。 */
.story-card .story-lines { display: flex; flex-direction: column; gap: 10px; margin: 6px 0 12px; }
.story-line { margin: 0; display: flex; gap: 10px; align-items: baseline; font-size: 13px; }
.story-line b { flex: 0 0 4.5em; color: var(--gold); font-size: 11px; }
.story-line span { color: var(--ink); }
.story-line.narration { color: var(--muted); font-style: italic; padding-left: calc(4.5em + 10px); }
.story-footer { border-top: 1px solid var(--line); padding-top: 8px; }

/* 精算画面の読み返しに添える小さな立ち絵。 */
.story-busts { display: flex; gap: 6px; justify-content: center; margin-bottom: 10px; }
.story-bust {
  width: 76px;
  height: 84px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-bottom-color: var(--accent, var(--gold));
  border-radius: 12px 12px 4px 4px;
  background: linear-gradient(180deg, rgba(255,255,255,.05), rgba(0,0,0,.35));
}
.story-bust .portrait-svg { width: 100%; height: 104px; margin-top: -6px; display: block; }

/* ---------------------------------------------------------------- 立ち絵つきの会話
 *
 * **近年のスマホゲームの対話に寄せた画面。**舞台のどこを叩いても進み、
 * 喋っている人だけが前へ出る。AUTO・スキップ・履歴は舞台の外へ置いて、
 * 「進めるつもりの指」に巻き込まれないようにする。 */
.vn { margin-bottom: 12px; }
.vn-stage {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  min-height: 460px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: #0b1113;
  overflow: hidden;
  cursor: pointer;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
}
.vn-stage:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* 背景。mood ごとに色調だけを変える（素材は増やさない）。 */
.vn-sky { position: absolute; inset: 0; background: radial-gradient(120% 80% at 50% 8%, #2c4245 0, #10181a 62%, #0a1012 100%); }
.vn[data-mood="dawn"] .vn-sky { background: radial-gradient(120% 80% at 50% 8%, #4a4534 0, #1b1d18 62%, #0d0f0c 100%); }
.vn[data-mood="dusk"] .vn-sky { background: radial-gradient(120% 80% at 50% 8%, #3a3140 0, #171420 62%, #0c0a10 100%); }
.vn[data-mood="ember"] .vn-sky { background: radial-gradient(110% 70% at 50% 92%, #56331f 0, #1d1512 55%, #0d0a09 100%); }
.vn[data-mood="defeat"] .vn-sky { background: radial-gradient(120% 80% at 50% 8%, #43282a 0, #17100f 62%, #0b0707 100%); }

/* 灰。ゆっくり流れる霞で、静止画に見えないようにする。 */
.vn-haze {
  position: absolute;
  inset: -20% -30%;
  background:
    radial-gradient(38% 26% at 22% 30%, rgba(255,255,255,.05), transparent 70%),
    radial-gradient(30% 20% at 74% 22%, rgba(255,255,255,.045), transparent 70%),
    radial-gradient(44% 24% at 52% 72%, rgba(0,0,0,.35), transparent 70%);
  animation: vn-drift 26s ease-in-out infinite alternate;
}
@keyframes vn-drift {
  from { transform: translate3d(-2%, 0, 0) scale(1); }
  to { transform: translate3d(2%, -2%, 0) scale(1.06); }
}

.vn-place {
  position: absolute;
  top: 12px;
  left: 14px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 10px;
  border-left: 2px solid var(--gold);
  background: rgba(8, 12, 13, .55);
  border-radius: 0 8px 8px 0;
}
.vn-place b { font-size: 12px; letter-spacing: .04em; }
.vn-place span { color: var(--muted); font-size: 10px; }

/* 立ち絵の並び。中央・左・右に、外側の二枠を足した五枠（R12）。
   **外の二枠は一回り小さく、奥に立つ。**5人が横に並んでも、
   誰が手前で喋っているかが読めるようにするため。 */
.vn-figures {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 138px;
  z-index: 2;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 0;
  height: 330px;
  pointer-events: none;
  /* **足元は台詞窓へ溶かす。**切り落としの直線が出ると紙人形に見える。 */
  -webkit-mask-image: linear-gradient(180deg, #000 78%, rgba(0,0,0,0) 100%);
  mask-image: linear-gradient(180deg, #000 78%, rgba(0,0,0,0) 100%);
}
.vn-figure {
  flex: 0 1 38%;
  --portrait-scale: 1;
  --portrait-y: 0px;
  /*
   * 画像差し替え後も、会話舞台の縦高は変えない。
   * 横幅だけ240pxまで使えるようにし、SVGの等比表示で下側を舞台へ溶かす。
   * これで腕を横から切らず、人物の見た目だけが小さくなるのを防ぐ。
   */
  max-width: 240px;
  aspect-ratio: 3 / 4;
  max-height: 280px;
  transition: filter .28s ease, opacity .28s ease, transform .28s ease;
  transform-origin: 50% 100%;
}
.vn-figure[data-character="warden"] {
  --portrait-scale: 1.4;
  /* 1.4倍で頭頂部が上端へ寄るため、下側を台詞窓へ逃がして頭を見せる。 */
  --portrait-y: 60px;
}

.vn-figure[data-character="lancer"],
.vn-figure[data-character="tactician"] {
  --portrait-scale: 1.1;
}
.vn-figure[data-character="guardian"] {
  --portrait-scale: 0.9;
}
.vn-figure .portrait-svg { display: block; width: 100%; height: 100%; }
.vn-figure.at-left { transform: translateX(6%) translateY(var(--portrait-y)) scale(var(--portrait-scale)); }
.vn-figure.at-right { transform: translateX(-6%) translateY(var(--portrait-y)) scale(var(--portrait-scale)); }
.vn-figure.at-center { z-index: 1; transform: translateY(var(--portrait-y)) scale(var(--portrait-scale)); }
/* 外側の二枠。奥行きを出すため縮めて沈める。 */
.vn-figure.at-far_left,
.vn-figure.at-far_right { flex: 0 1 30%; max-width: 168px; z-index: 0; opacity: .92; }
.vn-figure.at-far_left { transform: translateX(14%) translateY(var(--portrait-y)) scale(calc(.88 * var(--portrait-scale))); transform-origin: 50% 100%; }
.vn-figure.at-far_right { transform: translateX(-14%) translateY(var(--portrait-y)) scale(calc(.88 * var(--portrait-scale))); transform-origin: 50% 100%; }
.vn-figure.at-far_left.speaking { transform: translateX(14%) translateY(calc(-6px + var(--portrait-y))) scale(calc(.95 * var(--portrait-scale))); }
.vn-figure.at-far_right.speaking { transform: translateX(-14%) translateY(calc(-6px + var(--portrait-y))) scale(calc(.95 * var(--portrait-scale))); }

/* **喋っている人だけを前へ出す。**他は暗く沈める（消さない）。 */
.vn-figure.speaking { z-index: 2; filter: drop-shadow(0 8px 18px rgba(0,0,0,.5)); }
.vn-figure.at-left.speaking { transform: translateX(6%) translateY(calc(-6px + var(--portrait-y))) scale(calc(1.05 * var(--portrait-scale))); }
.vn-figure.at-right.speaking { transform: translateX(-6%) translateY(calc(-6px + var(--portrait-y))) scale(calc(1.05 * var(--portrait-scale))); }
.vn-figure.at-center.speaking { transform: translateY(calc(-6px + var(--portrait-y))) scale(calc(1.05 * var(--portrait-scale))); }
.vn-figure.muted-figure { filter: brightness(.55) saturate(.6) blur(.3px); opacity: .86; }
/* 地の文の行では、直前に喋っていた人だけ沈めきらない。**舞台から人が消えて見えない。** */
.vn-figure.attentive { filter: brightness(.86) saturate(.9); opacity: .95; }
.vn-figure.entering { animation: vn-enter .42s ease-out both; }
@keyframes vn-enter {
  from { opacity: 0; transform: translateY(22px) scale(.96); }
  to { opacity: 1; }
}

/* 台詞窓。 */
.vn-box {
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 10px;
  z-index: 4;
  min-height: 128px;
  padding: 20px 16px 26px;
  border: 1px solid rgba(160, 190, 190, .22);
  border-radius: 14px;
  background: linear-gradient(180deg, rgba(10, 16, 18, .93), rgba(6, 10, 11, .97));
  box-shadow: 0 -8px 26px rgba(0,0,0,.45);
  backdrop-filter: blur(3px);
}
.vn-name {
  position: absolute;
  top: -13px;
  left: 14px;
  padding: 4px 14px;
  border: 1px solid var(--accent, var(--gold));
  border-radius: 999px;
  background: #0b1113;
  color: var(--accent, var(--gold));
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .06em;
}
.vn-text {
  margin: 0;
  min-height: 3.4em;
  color: var(--ink);
  font-size: 15px;
  line-height: 1.85;
  letter-spacing: .01em;
}
.vn-box.narration .vn-text { color: #cddad3; font-style: italic; }
.vn-caret {
  position: absolute;
  right: 14px;
  bottom: 8px;
  color: var(--gold);
  font-size: 11px;
  opacity: 0;
}
.vn.typed .vn-caret { opacity: 1; animation: vn-blink 1.1s ease-in-out infinite; }
@keyframes vn-blink { 0%, 100% { transform: translateY(0); opacity: .35; } 50% { transform: translateY(3px); opacity: 1; } }
.vn-progress { position: absolute; left: 16px; bottom: 8px; color: var(--muted); font-size: 10px; letter-spacing: .08em; }

/* 作者試遊 2026-09-11 — 会話の門（STORY_GATES）。**舞台に被せて、ど真ん中に一つだけ。**
   「時間が巻き戻る」は物語の出来事なので、システム画面の一項目にしない。
   文字送りが終わるまでは出さない（`.vn.typed` が出す）——最後の一行を読み終えた
   瞬間に現れる、という間そのものが演出である。 */
.vn-gate {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  place-items: center;
  padding: 16px;
  background: radial-gradient(ellipse at center, rgba(6, 10, 11, .82) 0%, rgba(6, 10, 11, .62) 55%, rgba(6, 10, 11, .28) 100%);
  opacity: 0;
  pointer-events: none;
  transition: opacity .5s ease-out;
}
.vn.typed .vn-gate { opacity: 1; pointer-events: auto; }
.vn-gate-inner {
  display: grid;
  justify-items: center;
  gap: 10px;
  width: min(100%, 320px);
  transform: translateY(8px);
  transition: transform .5s ease-out;
}
.vn.typed .vn-gate-inner { transform: translateY(0); }
.vn-gate-button {
  width: 100%;
  padding: 16px 18px;
  font-size: 16px;
  letter-spacing: .08em;
  box-shadow: 0 0 0 1px rgba(229, 184, 105, .5), 0 0 28px rgba(229, 184, 105, .28);
  animation: vn-gate-pulse 2.6s ease-in-out infinite;
}
@keyframes vn-gate-pulse {
  0%, 100% { box-shadow: 0 0 0 1px rgba(229, 184, 105, .5), 0 0 22px rgba(229, 184, 105, .2); }
  50% { box-shadow: 0 0 0 1px rgba(229, 184, 105, .8), 0 0 34px rgba(229, 184, 105, .42); }
}
@media (prefers-reduced-motion: reduce) {
  .vn-gate, .vn-gate-inner { transition: none; }
  .vn-gate-button { animation: none; }
}

/* issue #200 — 巻き戻しの演出（rewind）。**「押した瞬間に次の会話」では巻き戻らない。**
   舞台（`.vn-stage`）はそのまま残し、いま読んだ行を逆順に消しながら、画面ごと逆走させる。
   素材は増やさない——帯・筋・閃光・揺れはすべて gradient と keyframes である。
   `prefers-reduced-motion` では、動くものを全部止めて短い静止表示へ落とす（最後の @media）。 */
.rewind-stage {
  /* 色が抜けて、記録された像に見える。 */
  filter: saturate(.34) contrast(1.22) brightness(.94);
  animation: rewind-shudder .26s steps(2, end) infinite;
}
@keyframes rewind-shudder {
  0% { transform: translateY(0) skewX(0deg); }
  50% { transform: translateY(-2px) skewX(.4deg); }
  100% { transform: translateY(1px) skewX(-.3deg); }
}
/* 霞は逆へ、速く流す。**前へ流れる霞は、巻き戻しと矛盾する。** */
.rewind-stage .vn-haze { animation: vn-drift 5s linear infinite reverse; }

/* 走査線。上へ送ると、テープが逆に回っているように見える。 */
.rewind-bands {
  position: absolute;
  inset: -20% 0;
  z-index: 3;
  pointer-events: none;
  mix-blend-mode: screen;
  background: repeating-linear-gradient(180deg,
    rgba(255, 255, 255, .06) 0 2px, rgba(255, 255, 255, 0) 2px 6px);
  animation: rewind-bands .6s linear infinite;
}
@keyframes rewind-bands { from { transform: translateY(0); } to { transform: translateY(-24px); } }
/* 追跡の乱れ。太い帯が一本、下から上へ抜ける。 */
.rewind-bands::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 16%;
  background: linear-gradient(180deg, rgba(255,255,255,0), rgba(214, 235, 255, .16), rgba(255,255,255,0));
  animation: rewind-tracking 1.1s linear infinite;
}
@keyframes rewind-tracking { from { top: 100%; } to { top: -18%; } }

/* 光の筋。**右から左へ**走らせる（進む向きの逆）。 */
.rewind-streaks { position: absolute; inset: 0; z-index: 3; overflow: hidden; pointer-events: none; }
.rewind-streaks i {
  position: absolute;
  right: -50%;
  width: 56%;
  height: 1px;
  background: linear-gradient(90deg, rgba(229,184,105,0), rgba(229,184,105,.5), rgba(255,255,255,.72), rgba(229,184,105,0));
  animation: rewind-streak .82s linear infinite;
}
.rewind-streaks i:nth-child(1) { top: 18%; animation-duration: .74s; animation-delay: -.1s; }
.rewind-streaks i:nth-child(2) { top: 37%; animation-duration: .96s; animation-delay: -.42s; }
.rewind-streaks i:nth-child(3) { top: 56%; animation-duration: .68s; animation-delay: -.26s; }
.rewind-streaks i:nth-child(4) { top: 71%; animation-duration: 1.05s; animation-delay: -.58s; }
@keyframes rewind-streak {
  0% { transform: translateX(0); opacity: 0; }
  12% { opacity: 1; }
  100% { transform: translateX(-240%); opacity: 0; }
}

/* 杭が鳴る一拍。腰の高さから一度だけ閃く。 */
.rewind-veil {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(58% 42% at 50% 76%,
    rgba(255, 242, 208, .92) 0%, rgba(229, 184, 105, .42) 42%, rgba(6, 10, 11, 0) 78%);
}
.rewind-stage.firing .rewind-veil { animation: rewind-fire .46s ease-out 1 both; }
@keyframes rewind-fire {
  0% { opacity: 0; transform: scale(.72); }
  16% { opacity: 1; }
  100% { opacity: 0; transform: scale(1.5); }
}

/* 逆走の印。**◀◀ だけ。**語で説明しない。 */
.rewind-mark {
  position: absolute;
  top: 12px;
  right: 14px;
  z-index: 5;
  color: var(--gold);
  font-size: 13px;
  letter-spacing: .3em;
  animation: rewind-mark .5s steps(2, end) infinite;
}
@keyframes rewind-mark {
  0%, 100% { opacity: .35; transform: translateX(3px); }
  50% { opacity: 1; transform: translateX(-3px); }
}

/* 残りの帯。通常の会話が「1 / 3」を出す位置（台詞窓の下端）に置き、
   **右端に寄せて、右から左へ減る。** */
.rewind-meter {
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 12px;
  z-index: 5;
  height: 2px;
  border-radius: 2px;
  background: rgba(229, 184, 105, .18);
  overflow: hidden;
}
.rewind-meter-fill {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 100%;
  background: var(--gold);
  box-shadow: 0 0 8px rgba(229, 184, 105, .55);
  transition: width .16s linear;
}

/* 消えていく行。末尾に消しかけの頭を置く。 */
.rewind-text::after {
  content: "";
  display: inline-block;
  width: .6em;
  height: 1em;
  margin-left: 1px;
  background: rgba(229, 184, 105, .5);
  vertical-align: -.14em;
  animation: rewind-erase .22s steps(2, end) infinite;
}
@keyframes rewind-erase { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }

/* 行が切り替わる拍で、舞台を一度だけ突かせる（テープが噛む感じ）。 */
.vn.rewind.jolt .vn-figures,
.vn.rewind.jolt .rewind-box { animation: rewind-jolt .2s steps(2, end) 1; }
@keyframes rewind-jolt {
  0% { transform: translateY(0); }
  50% { transform: translateY(-7px) scaleY(1.03); }
  100% { transform: translateY(0); }
}

.rewind-stage.settled .rewind-text::after { display: none; }

/* 止まる。揺れ・帯・筋・印を落とし、色が戻る。 */
.rewind-stage.settled {
  animation: none;
  filter: saturate(.82) contrast(1.04) brightness(1.06);
  transition: filter .34s ease-out;
}
.rewind-stage.settled .rewind-bands,
.rewind-stage.settled .rewind-streaks,
.rewind-stage.settled .rewind-mark,
.rewind-stage.settled .rewind-meter { opacity: 0; transition: opacity .3s ease-out; }
.rewind-stage.settled .vn-haze { animation: vn-drift 26s ease-in-out infinite alternate; }

/* 白へ抜ける。**次の会話は朝である。** */
.rewind-out {
  position: absolute;
  inset: 0;
  z-index: 6;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(120% 90% at 50% 40%, #fbf6e8 0%, #e8e2d2 70%, #d9d3c4 100%);
}
.rewind-stage.out .rewind-out { animation: rewind-out .42s ease-in forwards; }
@keyframes rewind-out { from { opacity: 0; } to { opacity: 1; } }

/* 読み上げ用の一言。画面には出さない（画面は ◀◀ と逆走そのものが言う）。 */
.rewind-status {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* prefers-reduced-motion。**逆走そのものは残す**（消すと何が起きたか分からない）。
   動くのは行の差し替えだけで、揺れ・帯・筋・閃光・消しかけの頭は出さない。 */
@media (prefers-reduced-motion: reduce) {
  .rewind-stage,
  .vn.rewind.jolt .vn-figures,
  .vn.rewind.jolt .rewind-box,
  .rewind-stage .vn-haze,
  .rewind-mark,
  .rewind-text::after { animation: none; }
  .rewind-bands, .rewind-streaks { display: none; }
  .rewind-stage.firing .rewind-veil { animation: none; opacity: 0; }
  .rewind-meter-fill { transition: none; }
  .rewind-stage.settled { transition: none; }
  .rewind-stage.out .rewind-out { animation: none; opacity: 1; }
}

/* 一行だけの演出。**画面を一度だけ揺らす。**繰り返さない。 */
.vn-stage.impact { animation: vn-shake .42s ease-out 1; }
@keyframes vn-shake {
  0% { transform: translate3d(0,0,0); }
  20% { transform: translate3d(-6px, 3px, 0); }
  40% { transform: translate3d(5px, -3px, 0); }
  60% { transform: translate3d(-4px, 2px, 0); }
  80% { transform: translate3d(3px, -1px, 0); }
  100% { transform: translate3d(0,0,0); }
}

.vn-note {
  margin: 10px 0 0;
  padding: 10px 12px;
  border-left: 2px solid var(--gold);
  border-radius: 0 10px 10px 0;
  background: rgba(57, 47, 30, .35);
  color: #e8dcc2;
  font-size: 12px;
  line-height: 1.7;
}

.vn-controls { display: flex; gap: 8px; justify-content: flex-end; margin-top: 10px; }
.vn-chip {
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(24, 33, 36, .8);
  padding: 7px 14px;
  font-size: 11px;
  letter-spacing: .06em;
}
.vn-chip.on { border-color: var(--gold); background: var(--gold-dark); color: var(--gold); }
.vn-hint { margin-top: 8px; }

/* 履歴。舞台の上に重ねる。 */
.vn-log {
  position: absolute;
  inset: 0;
  z-index: 6;
  display: flex;
  flex-direction: column;
  border-radius: 18px;
  background: #070b0c;
}
.vn { position: relative; }
.vn-log-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
}
.vn-log-body { flex: 1; overflow-y: auto; padding: 12px 14px 18px; }
.vn-log-line { margin: 0 0 10px; display: flex; gap: 10px; font-size: 13px; line-height: 1.7; }
.vn-log-line b { flex: 0 0 4.5em; font-size: 11px; }
.vn-log-line.narration { color: var(--muted); font-style: italic; padding-left: calc(4.5em + 10px); }

@media (max-width: 420px) {
  .vn-stage { min-height: 420px; }
  .vn-figures { height: 296px; bottom: 132px; }
  .vn-text { font-size: 14px; }
}
@media (prefers-reduced-motion: reduce) {
  .vn-haze, .vn-stage.impact, .vn-figure.entering, .vn.typed .vn-caret { animation: none; }
}


/* R10 — local save slots */

/* issue #235 — 盤面の役を切り替える一つのボタン。予測の見出し行に同居させ、
   固定領域の高さを増やさない。**押している間だけ盤面が隊列の組み替えになる。** */
.board-mode {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px 8px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 10px;
  font-weight: 750;
  line-height: 1.3;
  cursor: pointer;
}
.board-mode.active { border-color: var(--gold); background: var(--gold-dark); color: var(--gold); }

/* issue #235 — 遠征タブの末尾。**離れる操作は、次へ進む操作より下にしか置かない。** */
.expedition-tools .expedition-tool-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px;
  margin-bottom: 9px;
}
.expedition-tools .button.quiet {
  background: transparent;
  color: var(--muted);
}
/* 手取りチュートリアル。**札の見た目は隊列・技能・補給・必殺技で一つ**にする
   （組み立ても app.js の `tutorialNoteCard` 一箇所から出す）。光る先と同じ段の
   説明だけを置き、操作の探し方を画面ごとに変えない。

   作者要望 2026-09-14（デザイン面の改善）— 札は錠の最中だけ固定帯の下へ貼りつく。
   貼りついている間は**帯の高さを食う**ので、以前より一回り小さく組む
   （見出し 13px、段は縦の一覧ではなく横一列）。 */
.tutorial-note-card {
  margin: 0 0 12px;
  padding: 11px 13px 12px;
  border-color: var(--gold);
  border-radius: 13px;
  background: var(--gold-dark);
  box-shadow: 0 10px 22px rgba(0, 0, 0, .35);
}
/* **送った先でも読める。**錠が掛かっているあいだだけ、固定帯の真下へ貼りつく。
   技能ツリーの奥まで送っても「いまの段」と「なぜ押すのか」が視界から出ない。
   錠が外れた段（"done"）では普通の一枚へ戻す——そこから先は自由な探索なので、
   札が帯の下に居座ると画面を食うだけになる。 */
/* 作者指摘 2026-09-17 — **貼りついた札の手前へ、技能の操作盤が出ていた。**
   札（z-index 2・DOM では前）と操作盤（`.skill-sheet`、同じ 2・DOM では後）が
   同じ段に居たので、盤が伸びた回に札の本文を覆っていた。札は「いま何をするか」を
   言う唯一の場所なので、**盤より手前**に置く。固定帯（`.camp-top`、3）とは
   `--camp-top-h` のぶんだけ下へずらして貼るので、重なることはない。 */
.tutorial-note-card.pinned {
  position: sticky;
  top: calc(var(--camp-top-h, 215px) + 6px);
  z-index: 4;
}
/* 見出しの行。**札の名前と、いま何手目かを同じ行に置く。**
   以前は進捗を出すのが補給だけで、他の三つは何手あるのかが読めなかった。 */
.tutorial-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin: 0 0 2px;
}
.tutorial-head .eyebrow { margin: 0; }
.tutorial-progress {
  flex: 0 0 auto;
  color: var(--muted);
  font-size: 10px;
  letter-spacing: .04em;
}
.tutorial-progress b { color: var(--gold); font-variant-numeric: tabular-nums; }
.tutorial-note-card h3 { margin: 0 0 5px; color: var(--ink); font-size: 13px; }
.tutorial-note-card .tutorial-note { margin: 0; font-size: 12px; line-height: 1.6; }
/* 段の一覧。**横一列の小さな印**にする。縦に積むと、段が四つある技能チュートリアルで
   札が本文より高くなる。折り返すので、名前が長い回も欠けない。 */
.tutorial-steps {
  display: flex;
  flex-wrap: wrap;
  gap: 3px 8px;
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
}
.tutorial-steps li {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--muted);
  font-size: 10px;
  line-height: 1.4;
}
.tutorial-steps li > span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 15px;
  height: 15px;
  border: 1px solid var(--line);
  border-radius: 50%;
  font-size: 9px;
  font-variant-numeric: tabular-nums;
}
.tutorial-steps li > i { font-style: normal; }
.tutorial-steps li.current { color: var(--ink); font-weight: 600; }
.tutorial-steps li.current > span { border-color: var(--gold); background: var(--gold); color: #1b1a16; }
.tutorial-steps li.done { color: var(--good); }
.tutorial-steps li.done > i { text-decoration: line-through; }
/* 済んだ段は数字を伏せて印だけにする。**残っている段の数字だけが読み値になる。** */
.tutorial-steps li.done > span {
  position: relative;
  border-color: var(--good);
  color: transparent;
}
.tutorial-steps li.done > span::before {
  content: "✓";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--good);
  font-size: 10px;
}

/* issue #240 — 必殺技チュートリアル。**札の作りは他の手取りチュートリアルと同じ**にする
   （手取りの札が二通りの見た目を持つと、同じ種類の場面だと読めなくなる）。
   違うのは最後の一行だけで、そこには「いまの予測」を出す——構える前と後で帯が変わる
   ことが、この一戦の教材そのものである。 */
.tutorial-forecast {
  display: inline-flex;
  gap: 6px;
  align-items: center;
  margin-top: 9px;
  padding: 3px 9px;
  border: 1px solid var(--gold);
  border-radius: 999px;
  color: var(--muted);
  font-size: 10px;
}
.tutorial-forecast b { color: var(--gold); font-size: 12px; }
/* 必殺技だけは、段の一覧の下にもう一行（予測の帯）が付く。 */
.ultimate-tutorial .tutorial-steps { margin-bottom: 2px; }

/* 光る先。**釦でもセルでも同じ光**にする（押す場所は一種類だと読めるように）。 */
.tutorial-spot {
  position: relative;
  z-index: 1;
  border-color: var(--gold) !important;
  animation: tutorial-pulse 1.5s ease-in-out infinite;
}
@keyframes tutorial-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(229, 184, 105, .55); }
  50% { box-shadow: 0 0 0 5px rgba(229, 184, 105, 0); }
}
/* 錠。押せない場所は**残したまま沈める**（消すと、何が選べる場面なのか読めなくなる）。 */
.tutorial-blocked {
  opacity: .4;
  pointer-events: none;
  filter: saturate(.5);
}
/* 盤面のセルだけは沈めない。**錠の最中も、HPと予測は読ませる**（この一手の理由は
   そこに出ている）。押せないことは、光っていないことで足りる。 */
.party-cell.tutorial-blocked { opacity: .72; filter: none; }
@media (prefers-reduced-motion: reduce) {
  /* **光そのものは残す。**止めるのは脈だけ（どこを押すか分からなくなるので消せない）。 */
  .tutorial-spot { animation: none; box-shadow: 0 0 0 2px rgba(229, 184, 105, .55); }
}
/* 凡例はヘルプの中でだけ出す（本文からは外した）。 */
.map-legend-help .map-legend { margin: 4px 0 0; }

.save-menu-card {
  display: grid;
  gap: 0.8rem;
}

.save-menu-footer {
  margin-top: 0.2rem;
  padding-top: 0.8rem;
  border-top: 1px solid var(--line);
}

.save-menu-footer .button,
.guild-actions .button {
  margin-top: 0;
}

.save-slot-list {
  display: grid;
  gap: 0.55rem;
}

.save-slot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  border-radius: 0.7rem;
  background: var(--panel-2);
}

.save-slot.auto {
  border-color: var(--gold);
  background: rgba(229, 184, 105, .08);
}

.save-slot.empty {
  opacity: 0.68;
}

.save-slot b,
.save-slot small {
  display: block;
}

.save-slot small {
  margin-top: 0.2rem;
  color: var(--muted);
}

.save-slot-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0.45rem;
}

.save-notice {
  margin: 0;
  color: var(--gold);
}

.future-roster {
  margin-top: 0.8rem;
  color: var(--muted);
}

.future-roster summary {
  cursor: pointer;
  color: var(--ink);
}

@media (max-width: 560px) {
  .save-slot {
    align-items: flex-start;
    flex-direction: column;
  }

  .save-slot-actions {
    width: 100%;
    justify-content: flex-start;
  }
}

/* ---------------------------------------------------------------- 立ち絵サイズ確認用の開発画面 */
.portrait-test-shell {
  width: min(100%, 1040px);
}

.portrait-test-page {
  background: radial-gradient(circle at 72% -10%, #2b4445 0, var(--bg) 48%);
}

.portrait-test-header {
  padding-top: 18px;
}

.portrait-test-card {
  overflow: hidden;
}

.portrait-test-stage {
  position: relative;
  min-height: 560px;
  margin-top: 14px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: #0b1113;
}

.portrait-test-sky {
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 80% at 50% 8%, #2c4245 0, #10181a 62%, #0a1012 100%);
}

.portrait-test-haze {
  position: absolute;
  inset: -20% -30%;
  background:
    radial-gradient(38% 26% at 22% 30%, rgba(255,255,255,.05), transparent 70%),
    radial-gradient(30% 20% at 74% 22%, rgba(255,255,255,.045), transparent 70%),
    radial-gradient(44% 24% at 52% 72%, rgba(0,0,0,.35), transparent 70%);
}

.portrait-test-floor {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 0;
  height: 26%;
  background: linear-gradient(180deg, rgba(10,16,18,0), rgba(4,8,9,.7));
}

.portrait-test-figures {
  position: absolute;
  right: 10px;
  bottom: 28px;
  left: 10px;
  z-index: 1;
  display: flex;
  height: 460px;
  align-items: flex-end;
  justify-content: center;
  gap: 0;
  padding: 0 40px;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(180deg, #000 84%, rgba(0,0,0,0) 100%);
  mask-image: linear-gradient(180deg, #000 84%, rgba(0,0,0,0) 100%);
}

.portrait-test-figure {
  flex: 1 1 0;
  width: auto;
  min-width: 0;
  max-width: 190px;
  max-height: 440px;
  aspect-ratio: 3 / 4;
  transform: translateY(var(--portrait-test-y, 0px)) scale(var(--portrait-test-scale, 1));
  transform-origin: 50% 100%;
  transition: transform .28s ease;
}

.portrait-test-figure .portrait-svg {
  display: block;
  width: 100%;
  height: 100%;
}

.portrait-test-figure[data-character="warden"] {
  --portrait-test-scale: 1.4;
}

.portrait-test-figure[data-character="lancer"],
.portrait-test-figure[data-character="tactician"] {
  --portrait-test-scale: 1.1;
}

.portrait-test-figure[data-character="mender"] {
  --portrait-test-scale: 1;
}

.portrait-test-figure[data-character="guardian"] {
  --portrait-test-scale: 0.9;
}

.portrait-test-legend {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 8px;
  margin-top: 12px;
}

.portrait-test-legend > div {
  min-width: 0;
  padding: 8px 9px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #172124;
}

.portrait-test-legend b,
.portrait-test-legend small {
  display: block;
}

.portrait-test-legend b {
  font-size: 12px;
}

.portrait-test-legend small {
  margin-top: 3px;
  color: var(--muted);
  font-size: 10px;
}

.portrait-test-note {
  margin: 12px 0 0;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.7;
}

@media (max-width: 560px) {
  .portrait-test-stage {
    min-height: 660px;
  }

  .portrait-test-figures {
    top: 44px;
    bottom: 24px;
    height: auto;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-rows: repeat(2, minmax(0, 1fr));
    align-items: end;
    padding: 18px 10px 14px;
  }

  .portrait-test-figure {
    width: 100%;
    max-width: 105px;
    max-height: 210px;
    justify-self: center;
  }

  .portrait-test-legend {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ---------------------------------------------------------------- 顔の補正確認用の開発画面 */
.portrait-calibration-shell { width: min(100%, 1040px); }
.portrait-calibration-page {
  background: radial-gradient(circle at 72% -10%, #2b4445 0, var(--bg) 48%);
}
.portrait-calibration-header { padding-top: 18px; }
.portrait-calibration-card { overflow: hidden; }
.portrait-calibration-row {
  display: grid;
  gap: 9px;
  margin-top: 18px;
}
.portrait-calibration-row-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.portrait-calibration-row-head h3 {
  margin: 0;
  color: var(--ink);
  font-size: 13px;
}
.portrait-calibration-row-head small {
  color: var(--muted);
  font-size: 10px;
}
.portrait-calibration-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 8px;
}
.portrait-calibration-cell {
  min-width: 0;
}
.portrait-calibration-frame {
  position: relative;
  isolation: isolate;
  min-height: 68px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #101719;
}
.portrait-calibration-battle .portrait-calibration-frame { min-height: 92px; }
/* 2026-09-16 — 人物の札の縦長の枠（連れていく隊・技能・装備で共有する一つの形）。 */
.portrait-calibration-side .portrait-calibration-frame { width: 126px; min-height: 152px; }
.portrait-calibration-chip-strip { display: flex; flex-wrap: wrap; gap: 8px; }
.portrait-calibration-eye-line {
  position: absolute;
  top: 46%;
  right: 0;
  left: 0;
  z-index: 1;
  border-top: 1px dashed rgba(229, 162, 107, .48);
  pointer-events: none;
}
.portrait-calibration-info {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 2;
  display: grid;
  gap: 3px;
  padding: 18px 7px 6px;
  background: linear-gradient(180deg, rgba(13, 19, 21, 0), rgba(13, 19, 21, .95) 68%);
  color: var(--muted);
  font-size: 9px;
}
.portrait-calibration-bar {
  display: block;
  height: 5px;
  overflow: hidden;
  border-radius: 999px;
  background: #0d1315;
}
.portrait-calibration-bar i {
  display: block;
  width: 72%;
  height: 100%;
  border-radius: inherit;
  background: var(--good);
}
.portrait-calibration-label {
  display: grid;
  gap: 2px;
  margin-top: 6px;
  text-align: center;
}
.portrait-calibration-label b {
  overflow: hidden;
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.portrait-calibration-label small {
  overflow: hidden;
  color: var(--muted);
  font-size: 9px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.portrait-calibration-note {
  margin: 18px 0 0;
  color: var(--muted);
  font-size: 11px;
  line-height: 1.7;
}
@media (max-width: 700px) {
  .portrait-calibration-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 430px) {
  .portrait-calibration-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* Issue #163 — 情報を主操作の後ろへまとめる。details はiPhoneで一回のタップで開閉し、
   開いた内容は同じ画面の再描画後も app.js が保持する。 */
.help-details {
  padding: 0;
  overflow: hidden;
}
.help-details > summary {
  padding: 13px 15px;
  color: var(--ink);
  cursor: pointer;
  font-weight: 750;
  list-style-position: inside;
}
.help-details[open] > summary {
  border-bottom: 1px solid var(--line);
  color: var(--gold);
}
.help-body {
  padding: 1px 15px 13px;
}
.help-body p {
  margin: 9px 0 0;
  line-height: 1.65;
}
/* issue #176 — 状態（バフ・デバフ）の用語集。ヘルプの中に一覧で出す。 */
.glossary {
  margin: 9px 0 0;
  display: grid;
  gap: 8px;
}
.glossary-row {
  display: grid;
  grid-template-columns: 56px 1fr;
  gap: 8px;
  align-items: baseline;
}
.glossary-row .status-term {
  font-size: 12px;
  letter-spacing: .04em;
}
.glossary-row .status-term.good { color: var(--good); }
.glossary-row .status-term.bad { color: var(--bad); }
.glossary-row small {
  color: var(--muted);
  line-height: 1.6;
}

/* 装着した行動が無条件で出るか。**無条件を上に置くと下は出ない**ことの手掛かり。 */
.firing-chip {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--panel-3);
  font-size: 10px;
  font-weight: 600;
  vertical-align: middle;
}
.firing-chip.always { color: var(--orange); }
.firing-chip.conditional { color: var(--blue); }

.operation-note {
  margin: 8px 0 0;
  color: var(--ink);
  font-size: 12px;
  line-height: 1.55;
}
.context-line {
  margin: 7px 0 0;
  color: var(--muted);
  font-size: 10px;
  line-height: 1.5;
}
.context-line b { color: var(--ink); }
.selected-loadout {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}
.selected-loadout h3 { margin-bottom: 6px; color: var(--ink); }
.skill-detail-status, .skill-level-readout, .level-readout {
  color: var(--blue);
}
.level-readout b, .skill-level-readout b { color: var(--violet); }
.battle-hint { margin: 9px 0 0; }
.battle-history > summary { cursor: pointer; }
.battle-history .technical-log {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px dashed var(--line);
}
.technical-log summary {
  color: var(--muted);
  cursor: pointer;
  font-size: 10px;
}
.technical-events, .technical-log pre {
  max-height: 280px;
  overflow: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  color: var(--muted);
  font: 9px/1.45 ui-monospace, monospace;
}


/* ============================================================ 記号の語彙（issue #177）
   **通常のゲームシステムは、文章ではなく形と色で見せる。**
   数えるものは点、量はバー、順番は目盛り、テーマと能力値は色。
   意味の対応表は畳んだヘルプ（.symbol-legend）に一度だけ置く。 */
:root {
  --branch-strike: #e5a26b;
  --branch-guard: #91cbd5;
  --branch-care: #9bd69e;
  --branch-order: #e5b869;
  --branch-base: #9eada7;
  --stat-might: #e5a26b;
  --stat-focus: #91cbd5;
  --stat-guard: #9bd69e;
}
/* 数えるもの。AP は金、RP は紫、代償の HP は赤。 */
.pips { display: inline-flex; align-items: center; gap: 2px; }
.pips i { width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.pips b { font-size: 8px; font-weight: 800; }
.pips.ap { color: var(--gold); }
.pips.rp { color: var(--violet); }
.pips.hp { color: var(--bad); }
.pips.free i { background: transparent; border: 1px solid var(--muted); }
/* 段は素直に文字で。**ほとんどの節が Lv1 なので、目盛りは読めない。** */
.level-tag { color: var(--violet); font-size: 9px; font-weight: 800; }
.level-tag small { font-size: 8px; font-weight: 400; opacity: .7; }
.level-tag.maxed { color: var(--gold); }
/* 量は能力値の色の小チップ。印（腕・技・受・HP）と数を並べ、桁で比べさせる。 */
.yield-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 2px;
  padding: 1px 4px;
  border: 1px solid currentColor;
  border-radius: 3px;
  font-size: 10px;
  font-weight: 800;
  line-height: 1.3;
}
.yield-chip i { font-style: normal; font-size: 9px; opacity: .9; }
.yield-chip small { font-size: 8px; font-weight: 400; opacity: .8; }
.yield-chip.stat-might { color: var(--stat-might); }
.yield-chip.stat-focus { color: var(--stat-focus); }
.yield-chip.stat-guard { color: var(--stat-guard); }
.yield-chip.stat-max_hp { color: var(--bad); }
.yield-stat.stat-might { color: var(--stat-might); }
.yield-stat.stat-focus { color: var(--stat-focus); }
.yield-stat.stat-guard { color: var(--stat-guard); }
/* 発動条件は、名前の下に短い薄字で。**丸は消費だけに譲る。** */
.node-when {
  display: -webkit-box;
  margin-top: 2px;
  overflow: hidden;
  color: #7f8f89;
  font-size: 9px;
  line-height: 1.3;
  /* 二行までは出す。**一行で切ると「HP50%以下の敵がい…」で終わって読めない。** */
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
/* 取得の状態。丸は消費だけで、持っているかどうかは鉤で出す。 */
.node-mark {
  display: inline-grid;
  place-items: center;
  align-self: start;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  font-size: 9px;
  font-weight: 800;
}
.node-mark.equipped { border-radius: 4px; background: var(--gold); color: #1b201e; }
.node-mark.equipped.off { background: transparent; box-shadow: inset 0 0 0 1px var(--muted); color: var(--muted); }
/* issue #236 — `.node-mark.owned`（取得済み・未装着）はここにあった。状態を廃止した。 */
.node-mark.cost { border: 1px solid #6d7c77; border-radius: 4px; color: #8fa09a; }
.node-mark.cost.ready { border: 1px solid var(--gold); color: var(--gold); }
.node-mark.cost.gated { opacity: .6; }
.node-mark.prerequisite-levels { border: 1px dashed #6d7c77; border-radius: 4px; color: #8fa09a; }
.node-cost-chain { display: inline-flex; align-items: center; gap: 3px; align-self: start; }
.cost-plus { color: var(--muted); font-size: 10px; line-height: 1; }
/* テーマ。色と印だけで絞り込む。 */
.branch-filter { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 4px; }
.branch-chip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px 8px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 12px;
  line-height: 1;
}
.branch-chip small { font-size: 8px; opacity: .75; }
.branch-chip.on { border-width: 2px; background: rgba(255, 255, 255, .06); }
.branch-chip.branch-strike { color: var(--branch-strike); border-color: rgba(229, 162, 107, .5); }
.branch-chip.branch-guard { color: var(--branch-guard); border-color: rgba(145, 203, 213, .5); }
.branch-chip.branch-care { color: var(--branch-care); border-color: rgba(155, 214, 158, .5); }
.branch-chip.branch-order { color: var(--branch-order); border-color: rgba(229, 184, 105, .5); }
.branch-chip.branch-base { color: var(--branch-base); border-color: rgba(158, 173, 167, .5); }
.node-icon.branch-strike { border-color: var(--branch-strike); color: var(--branch-strike); }
.node-icon.branch-guard { border-color: var(--branch-guard); color: var(--branch-guard); }
.node-icon.branch-care { border-color: var(--branch-care); color: var(--branch-care); }
.node-icon.branch-order { border-color: var(--branch-order); color: var(--branch-order); }
.node-icon.branch-base { border-color: var(--branch-base); color: var(--branch-base); }
.skill-node.equipped .node-icon { border-color: var(--gold); background: var(--gold); color: #1b201e; }
/* 節の上の計器。名前の下に並べる。
   作者指摘 2026-09-17 — **段の添え字（/10）が列の右端で切れていた。**列幅は
   iPhone で 176px しかなく、一列固定（nowrap）のままだと「● 腕 146% Lv2/10」が
   入り切らず、`.node-copy small` の `overflow: hidden` が末尾を食っていた。
   **数を削るのではなく、入らない回だけ折り返す。**計器は一つずつが読めればよく、
   一行に収まっているかどうかは読み手にとって意味を持たない。 */
.node-copy .node-meters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  /* 横の間は詰める。**ふだんは一列のまま**で、入らない回だけ下の段へ落ちる。 */
  gap: 3px 4px;
  overflow: visible;
  white-space: nowrap;
}
.node-copy .node-meters > * { flex: 0 0 auto; }
/* 装着行。**出番は目盛り、代償は点。** */
.installed-copy .row-marks { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; margin-top: 3px; }
.installed-copy .node-when { white-space: normal; }
.turn-share { display: inline-flex; gap: 2px; margin-top: 3px; }
.turn-share i { width: 9px; height: 3px; border-radius: 2px; background: rgba(224, 195, 116, .25); }
.turn-share i.on { background: var(--gold); }
.slot-heading .slot-budget { display: inline-flex; align-items: center; margin-left: auto; }
.slot-heading .slot-over { margin-left: 5px; color: var(--bad); font-size: 11px; }
.installed-row.over { box-shadow: inset 2px 0 0 var(--bad); }
/* 入切は摘み（スイッチ）。**丸は払うものだけに譲る。** */
.skill-switch {
  flex: 0 0 auto;
  width: 30px;
  height: 17px;
  padding: 2px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(255, 255, 255, .05);
}
.skill-switch i { display: block; width: 11px; height: 11px; border-radius: 50%; background: var(--muted); }
.skill-switch.on { border-color: var(--gold); background: rgba(229, 184, 105, .18); }
.skill-switch.on i { margin-left: 13px; background: var(--gold); }
.level-tag { display: inline-flex; align-items: center; gap: 1px; line-height: 1; white-space: nowrap; }
/* 詳細。文章を許すのは技能の説明文だけ。 */
.skill-detail .scope-mark {
  margin-right: 5px;
  padding: 1px 4px;
  border: 1px solid var(--line);
  border-radius: 3px;
  color: var(--blue);
  font-size: 9px;
  font-style: normal;
}
/* 記号の意味。**一度だけ、畳んだ中に置く。** */
.symbol-legend { display: grid; grid-template-columns: 22px 1fr; gap: 5px 8px; align-items: center; }
.symbol-legend dt { display: grid; place-items: center; }
.symbol-legend dd { margin: 0; color: var(--muted); font-size: 10px; line-height: 1.35; }
/* issue #159 — 立ち位置と HP の小さな印（.formation-mark / .hp-mark）はここにあった。
   上端の共通盤面がその二つを兼ねるので消した。帯の見出し（.member-context-head）も
   2026-09-16 に人物の札の頭（.character-panel-head）へ移した。 */
/* 順番の帯（issue #177）。装着順が結果にどう出たかを、ラウンド順に並べる。 */
.turn-strip { display: grid; gap: 6px; }
.turn-row { display: flex; align-items: center; gap: 8px; }
.turn-cells { display: flex; flex-wrap: wrap; gap: 4px; }
/* ラウンドごとに束ねる。行動点2の人物が二つ出しても、拍が縦に揃う。 */
.turn-round { display: inline-flex; gap: 2px; padding-right: 3px; border-right: 1px solid rgba(255, 255, 255, .06); }
.turn-round:last-child { border-right: 0; }
.turn-cell {
  display: inline-grid;
  place-items: center;
  width: 15px;
  height: 15px;
  border: 1px solid var(--line);
  border-radius: 3px;
  font-size: 9px;
  font-style: normal;
}
.turn-cell.idle { border-style: dashed; opacity: .4; }
.turn-cell.branch-strike { border-color: var(--branch-strike); color: var(--branch-strike); }
.turn-cell.branch-guard { border-color: var(--branch-guard); color: var(--branch-guard); }
.turn-cell.branch-care { border-color: var(--branch-care); color: var(--branch-care); }
.turn-cell.branch-order { border-color: var(--branch-order); color: var(--branch-order); }
.turn-cell.branch-base { border-color: var(--branch-base); color: var(--branch-base); }
.level-step { display: inline-block; margin-left: 7px; color: var(--muted); font-size: 10px; }
.level-step b { color: var(--violet); }
.empty-slot { color: var(--muted); font-size: 12px; }

/* ---------------------------------------------------------------- 必殺技（issue #238）
 *
 * **印は「払うもの」なので丸ではなく菱形（✹）で出す。**丸は行動点・反応点・
 * 代償HPに譲ってある（issue #177）ので、同じ形を別の意味へ使わない。
 *
 * 作者指摘 2026-09-13 — 隊全体の合計（菱形の並び）はやめた。**印は人物ごと**に、
 * 盤面のセルの中で四段で出す（`.party-ultimate`、この節の下）。
 */
.ultimate-card .context-line { color: var(--muted); font-size: 11px; }
.ultimate-row {
  display: flex;
  align-items: center;
  gap: 7px;
  min-height: 34px;
  padding: 5px 0;
  border-top: 1px solid rgba(58, 77, 79, .55);
}
.ultimate-row.selected { box-shadow: inset 2px 0 0 var(--gold); }
.ultimate-pick {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  gap: 7px;
  padding: 2px 4px;
  border: 0;
  background: none;
  color: inherit;
  text-align: left;
}
.ultimate-pick .ultimate-mark { color: var(--gold); opacity: .28; font-size: 13px; }
.ultimate-row.selected .ultimate-pick .ultimate-mark { opacity: 1; }
.ultimate-copy { display: flex; flex-direction: column; gap: 3px; }
.ultimate-traits { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.ultimate-trait {
  padding: 1px 5px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  font-size: 10px;
}
.ultimate-row.selected .ultimate-trait { border-color: var(--gold); color: var(--gold); }
/* 盤面のセル。**どの一戦に印を賭けているかは盤面から読める。** */
.party-ultimate { margin-left: 4px; color: var(--gold); font-size: 11px; }
/* 帯のなかの必殺。系統の色は残し、印と枠だけを立てる。 */
.turn-cell.ultimate { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold) inset; }
/* 装着行のなかの必殺。**枠を足さず、行そのものに宿らせる。**
 *
 * 作者要望 2026-09-12「必殺技を使おうとしている時はもっとかっこよくスキルを光らせて」。
 * 三段に分ける。**段の差がそのまま状態の差**なので、文字を足さずに読める。
 *
 *   .ultimate         … 指定だけ（古い保存から来る。長押しすれば構えに上がる）
 *   .ultimate.armed   … この一戦で構えている。金が脈打つ
 *   .ultimate.firing  … 予測が「本当に出る」と言っている。光が走る
 *   .ultimate.spent   … この遠征では放ち終えた。脈を止めて沈める
 */
.installed-row.ultimate {
  position: relative;
  border-radius: 0 10px 10px 0;
  box-shadow: inset 2px 0 0 var(--gold);
}
.installed-row.ultimate.armed {
  background: linear-gradient(90deg, rgba(229, 184, 105, .22), rgba(229, 184, 105, .07) 58%, transparent);
  animation: ultimate-armed 2.4s ease-in-out infinite;
}
/* **印は行ごと金に寄せる。**変換の札（全体へ・量3倍…）が普段の薄字のままだと、
   構えた行だけが持つ情報が、構えていない行と同じ重さで並ぶ。 */
.installed-row.ultimate.armed .ultimate-trait { border-color: rgba(229, 184, 105, .8); color: var(--gold); }
.installed-row.ultimate.armed .installed-copy > b { color: #fff3dc; }
.installed-row.ultimate.firing .installed-copy > b { text-shadow: 0 0 11px rgba(229, 184, 105, .6); }
.installed-row.ultimate.spent .ultimate-trait { border-color: var(--line); color: var(--muted); }
@keyframes ultimate-armed {
  0%, 100% {
    box-shadow: inset 3px 0 0 var(--gold), 0 0 0 1px rgba(229, 184, 105, .26),
      0 0 10px -3px rgba(229, 184, 105, .22);
  }
  50% {
    box-shadow: inset 3px 0 0 var(--gold), 0 0 0 1px rgba(229, 184, 105, .58),
      0 0 18px -3px rgba(229, 184, 105, .55);
  }
}
/* 走る光。**出ると分かっている一戦だけ**に付けるので、光が「予測」を意味する。 */
.installed-row.ultimate.firing { overflow: hidden; }
.installed-row.ultimate.firing::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(104deg, transparent 38%, rgba(255, 240, 203, .20) 50%, transparent 62%);
  animation: ultimate-sheen 3.2s ease-in-out infinite;
}
@keyframes ultimate-sheen {
  0%, 62%, 100% { transform: translateX(-125%); }
  92% { transform: translateX(125%); }
}
.installed-row.ultimate.spent { animation: none; background: none; }
/* ✹ は操作ではなく状態の印。**押す場所は行そのもの一つだけ**にした（長押し）。 */
.ultimate-seal {
  flex: 0 0 auto;
  width: 22px;
  color: var(--gold);
  font-size: 14px;
  line-height: 1;
  text-align: center;
  opacity: .42;
}
.installed-row.ultimate.armed .ultimate-seal { font-size: 16px; }
.installed-row.ultimate.armed .ultimate-seal {
  opacity: 1;
  text-shadow: 0 0 7px rgba(229, 184, 105, .65);
  animation: ultimate-seal-beat 2.4s ease-in-out infinite;
}
.installed-row.ultimate.firing .ultimate-seal { animation-duration: 1.3s; }
.installed-row.ultimate.spent .ultimate-seal { opacity: .28; text-shadow: none; animation: none; }
@keyframes ultimate-seal-beat {
  0%, 100% { transform: scale(1); text-shadow: 0 0 6px rgba(229, 184, 105, .45); }
  50% { transform: scale(1.22); text-shadow: 0 0 13px rgba(229, 184, 105, .9); }
}
.installed-row[data-longpress],
.installed-row[data-longpress] * {
  touch-action: pan-y;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
}
/* 長押しの手応え（作者要望 2026-09-13）。**押している時間そのものを、左から右へ
   伸びる光の帯で出す。**右端まで届いた拍が、必殺がセットされる拍である。指を離すか
   スクロールすると帯ごと消える（＝取り消し）。
   帯の長さは JS が `--long-press-ms` で渡す（長押しの判定と同じ値）。 */
.installed-row[data-longpress] { position: relative; overflow: hidden; }
.installed-row[data-longpress].pressing::before {
  content: "";
  position: absolute;
  z-index: 0;
  inset: 0;
  /* 二枚重ね。**面**（左から満ちる光）と、行の下端を走る**線**（どこまで来たか）。
     どちらも同じ clip-path で切るので、線の先端が光の右端と必ず一致する。 */
  background:
    linear-gradient(90deg,
      rgba(229, 184, 105, .10) 0%, rgba(229, 184, 105, .42) 86%,
      rgba(255, 243, 214, .95) 100%),
    linear-gradient(var(--gold), var(--gold)) bottom left / 100% 2px no-repeat;
  box-shadow: 0 0 16px -2px rgba(229, 184, 105, .55);
  clip-path: inset(0 100% 0 0);
  animation: longpress-fill var(--long-press-ms, 450ms) linear forwards;
  pointer-events: none;
}
/* 既に構えている行の長押しは**解く**操作なので、帯の色も変える。 */
.installed-row[data-longpress].ultimate.armed.pressing::before {
  background:
    linear-gradient(90deg,
      rgba(158, 173, 167, .06) 0%, rgba(158, 173, 167, .30) 86%,
      rgba(237, 243, 237, .8) 100%),
    linear-gradient(var(--muted), var(--muted)) bottom left / 100% 2px no-repeat;
  box-shadow: none;
}
/* 帯の下に行の中身が隠れないようにする（帯は背景であって、覆いではない）。 */
.installed-row[data-longpress] > * { position: relative; z-index: 1; }
@keyframes longpress-fill {
  from { clip-path: inset(0 100% 0 0); }
  to { clip-path: inset(0 0 0 0); }
}
.ultimate-trait.idle { border-style: dashed; opacity: .7; }
/* 盤面のセルの ✹（作者指摘 2026-09-13）。**四段で、誰が残していて誰が使い終えたかを出す。**
 *
 *   ready  … 薄い金の ✹ … まだ残っている（構えていない）
 *   armed  … 金の ✹    … 構えているが、この一戦では条件が揃わない
 *   firing … 光る ✹    … この一戦で出る（予測が言っている）
 *   spent  … 灰の ✧    … この遠征ではもう放った。補充されない
 */
.party-ultimate.ready { opacity: .36; }
.party-ultimate.armed { opacity: 1; text-shadow: 0 0 6px rgba(229, 184, 105, .55); }
.party-ultimate.firing {
  opacity: 1;
  text-shadow: 0 0 8px rgba(229, 184, 105, .7);
  animation: ultimate-seal-beat 1.6s ease-in-out infinite;
}
.party-ultimate.spent { color: var(--muted); opacity: .55; }
@media (prefers-reduced-motion: reduce) {
  /* **長押しの帯だけは止めない。**あれは装飾ではなく、押している時間の目盛りである
     （止めると「いつ離してよいか」が画面から消える）。 */
  .installed-row.ultimate.armed,
  .installed-row.ultimate.armed .ultimate-seal,
  .party-ultimate.firing { animation: none; }
  .installed-row.ultimate.firing::after { animation: none; opacity: .35; transform: none; }
  .installed-row.ultimate.armed {
    box-shadow: inset 3px 0 0 var(--gold), 0 0 0 1px rgba(229, 184, 105, .5);
  }
}

/* ============================================================ 装備の候補（PR #255）
 *
 * 作者指摘 2026-09-12：「装備は2つとも画面に収める。少なくとも iPhone 16e では
 * スクロールなしで選べてほしい。ヴァンパイアサバイバーズを参考に。もし可能なら、
 * 今後ギルド画面から候補を3つにするアップグレードが来ても大丈夫なようになると理想。」
 *
 * なので札は**横幅いっぱいの行**で縦に並べ、一枚の高さを候補数から締める。
 * `data-count` が 3 以上になっても同じ規則で収まるよう、余白・行間・文字を
 * 段階的に詰める（数値を JS へ持たせず、ここ一箇所で決める）。
 */
.reward-card-shell { padding: 11px 12px; }
.reward-card-shell .section-head { margin-bottom: 2px; }
.reward-card-shell .section-head h2 { font-size: 15px; }
.verdict-slim { padding: 10px 14px; text-align: left; }
.verdict-slim-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  margin: 0;
  font-size: 12px;
}
.verdict-slim-line b { color: var(--good); font-size: 14px; }
.verdict-slim-line span { color: var(--muted); }

.reward-choices {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
  margin-top: 10px;
}
.reward-choice {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 10px 11px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: #172124;
}
.reward-choice header {
  display: flex;
  align-items: center;
  gap: 7px;
  justify-content: space-between;
}
.reward-choice h3 {
  margin: 0;
  color: var(--ink);
  font-size: 14px;
  line-height: 1.25;
}
.reward-keystone {
  margin: 0;
  padding: 4px 7px;
  border-radius: 6px;
  background: var(--gold-dark);
  color: var(--gold);
  font-size: 11px;
  font-weight: 700;
  line-height: 1.35;
}
.reward-risk {
  margin: 0;
  padding: 4px 7px;
  border-left: 3px solid #d36b64;
  border-radius: 4px;
  background: rgba(143, 54, 49, .18);
  color: #f0aaa4;
  font-size: 11px;
  line-height: 1.35;
}
.reward-effect-list {
  display: grid;
  gap: 3px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.reward-effect-list li {
  display: flex;
  align-items: baseline;
  gap: 5px;
  color: var(--ink);
  font-size: 11.5px;
  line-height: 1.3;
}
.reward-more, .reward-meta {
  margin: 0;
  color: var(--muted);
  font-size: 10px;
}
.reward-meta { margin-right: 8px; }
.reward-choice .reward-full { margin-top: 0; }
.reward-choice .reward-full summary { color: var(--blue); font-size: 11px; }
.reward-choice .reward-full .equipment-rule-line {
  margin: 4px 0 0;
  font-size: 11px;
  line-height: 1.45;
}
.reward-choice .reward-take { margin-top: 2px; padding: 10px; font-size: 13px; }
.reward-choice.disabled { opacity: .6; }
.reward-choices[data-count="3"] { gap: 6px; }
.reward-choices[data-count="3"] .reward-choice { gap: 3px; padding: 7px 9px; }
.reward-choices[data-count="3"] .reward-choice h3 { font-size: 12.5px; }
.reward-choices[data-count="3"] .reward-effect-list li { font-size: 11px; line-height: 1.25; }
.reward-choices[data-count="3"] .reward-rule-head { font-size: 10px; }
.reward-choices[data-count="3"] .reward-choice .reward-full summary { font-size: 10px; }
.reward-choices[data-count="3"] .reward-choice .reward-take { padding: 7px; font-size: 12px; }
.reward-choices[data-count="4"] .reward-choice,
.reward-choices[data-count="5"] .reward-choice { gap: 3px; padding: 7px 9px; }
.reward-choice.rarity-card-epic { border-color: #66528a; }
.reward-choice.rarity-card-legendary {
  border-color: #8b692d;
  background: linear-gradient(145deg, rgba(57,47,30,.98), rgba(21,29,31,.97));
}
.reward-choice.rarity-card-mythic {
  border-color: #8d5069;
  background: linear-gradient(145deg, rgba(56,34,45,.98), rgba(21,29,31,.97));
}
.reward-choice.rarity-card-oopart {
  border-color: #388d91;
  background: linear-gradient(145deg, rgba(25,59,61,.98), rgba(38,30,57,.97));
}
.reward-reroll .button { padding: 9px; font-size: 12px; }

/* 残す設計図の選択（issue #151）。 */
.keep-list { display: grid; gap: 8px; margin-top: 10px; }
.keep-card {
  padding: 9px 10px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: #172124;
}
.keep-card.selected { border-color: var(--gold); background: var(--gold-dark); }
.keep-main {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 8px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  text-align: left;
}
.keep-mark {
  display: inline-flex;
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--gold);
  font-size: 13px;
}
.keep-card.selected .keep-mark { border-color: var(--gold); }
.keep-name { flex: 1 1 auto; font-size: 13px; font-weight: 700; }
.keep-card .reward-full summary { color: var(--blue); font-size: 11px; }
.effect-always {
  flex: 0 0 auto;
  padding: 1px 5px;
  border: 1px solid var(--line);
  border-radius: 4px;
  color: var(--good);
  font-size: 9px;
  font-weight: 800;
}

/* rule の見出し（PR #255）。**いつ・何を払い・何回**を効果の真上に置く。
 * 作者試遊 2026-09-12「結局、条件と消費も見ないと選べないです」。 */
.reward-rule { display: grid; gap: 3px; }
.reward-rule + .reward-rule { margin-top: 4px; }
.reward-rule-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 5px;
  margin: 0;
  font-size: 10.5px;
  line-height: 1.25;
}
.reward-rule-head b { color: var(--blue); font-weight: 700; }
.reward-rule-head span {
  padding: 0 5px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  font-size: 10px;
}
.reward-effect-list li::before {
  color: var(--muted);
  content: "→";
  font-size: 10px;
}
.reward-choice > .reward-effect-list li::before { content: none; }

/* 技能の取得予約 */
.node-state-marks {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
  min-width: 24px;
}
.node-reservation-mark {
  color: var(--blue);
  font-size: 14px;
  font-weight: 800;
  line-height: 1;
}
.skill-node.reserved {
  border-color: var(--blue);
}
.skill-node.reserved .node-icon {
  box-shadow: 0 0 0 2px rgba(125, 190, 213, .22);
}
.summary-reservation {
  display: flex;
  flex: 0 1 42%;
  min-width: 0;
  flex-direction: column;
  gap: 1px;
  color: var(--blue);
  font-size: 9px;
  line-height: 1.15;
}
.summary-reservation small {
  color: var(--muted);
  font-size: 8px;
}
.summary-reservation b {
  overflow: hidden;
  color: var(--blue);
  font-size: 10px;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.reservation-action {
  padding-top: 6px;
  border-top: 1px dashed rgba(125, 190, 213, .22);
}
.reservation-button {
  border-color: var(--blue);
  color: var(--blue);
}
.reservation-note {
  margin: 6px 0 0;
  color: var(--blue);
  font-size: 9px;
  line-height: 1.45;
}
@media (max-width: 420px) {
  .summary-reservation { flex-basis: 35%; }
}

.reservation-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}
.reservation-buttons .reservation-button {
  flex: 1 1 auto;
}
.reservation-buttons .reservation-button:disabled {
  border-color: rgba(125, 190, 213, .42);
  color: var(--blue);
  opacity: .72;
}

/* ============================================================ 反応（issue #237）
 *
 * **操作の結果に、短い反応をひとつだけ返す。**
 *
 * ここは飾りの層ではなく、因果を見せるための層である。キャンプの操作は
 * これまで静かに切り替わるだけで、押したことが通ったのか、何が変わったのかが
 * 画面から返ってこなかった（issue #237 の観測）。
 *
 * 画面は毎回まるごと描き直すので、「何が変わったか」を知っているのは app.js の
 * 反応の仕組み（`fx()` と `data-fx-watch`）だけである。あちらが class を載せ、
 * ここがその class に共通の時間・曲線・色を一つずつ与える。
 *
 * 色は既存の語彙のまま使う。
 *   金   得た・確定した・選んだ        青   先見機と装備（情報の側）
 *   緑   癒えた・入れた                赤   拒まれた・減った
 *   菫   必殺
 *
 * 守ること。
 *   - **反応が出なくても、色・記号・数・ラベルで同じことが読める。**
 *     反応は理解の足しであって、条件ではない（issue #237 完了条件）。
 *   - 反応は描き終わったあとに class が付くだけで、**次の操作を待たせない。**
 *   - 繰り返す操作ほど短くする。長い反応は「得た」「変わった」だけに使う。
 *   - prefers-reduced-motion は、この節の最後で一括して止める。
 */

/* ---- 押した指への返事。**押しているあいだだけ沈む。**離せば戻る。 */
.button,
.tiny-button,
.icon-button,
.tab,
button.party-cell,
.board-mode,
.forecaster-action,
.character-main,
.gear-main,
.equip-slot-button,
.skill-node-button,
.member-tab,
.difficulty-card,
.scene-row,
.sheet-close {
  transition:
    transform var(--fx-tap) var(--fx-ease),
    filter var(--fx-tap) var(--fx-ease),
    border-color var(--fx-quick) ease,
    background-color var(--fx-quick) ease,
    color var(--fx-quick) ease;
}
.button:active:not(:disabled),
.tiny-button:active:not(:disabled),
.icon-button:active:not(:disabled),
.tab:active:not(:disabled),
button.party-cell:active:not(:disabled),
.board-mode:active:not(:disabled),
.character-main:active:not(:disabled),
.gear-main:active:not(:disabled),
.equip-slot-button:active:not(:disabled),
.skill-node-button:active:not(:disabled),
.member-tab:active:not(:disabled),
.difficulty-card:active:not(:disabled),
.scene-row:active:not(:disabled),
.sheet-close:active:not(:disabled) {
  transform: scale(.972);
  filter: brightness(1.12);
}
/* 先見機の二つの釦は主操作なので、沈みを少しだけ強く出す。 */
.forecaster-action:active:not(:disabled) { transform: scale(.965) translateY(1px); filter: brightness(1.16); }

/* ---- 画面と段の入れ替わり。**中身だけが立ち上がる。**
   キャンプでは上端の盤面（.camp-top）を動かさない——貼りついた盤が毎回跳ねると、
   タップ対象が動いて押し間違える（issue #237 完了条件「タップ対象の移動」）。 */
@keyframes fx-view-enter {
  from { opacity: 0; transform: translateY(7px); }
  to { opacity: 1; transform: none; }
}
.fx-view-enter { animation: fx-view-enter var(--fx-step) var(--fx-ease); }
/* 作者指摘 2026-09-15 —「アニメーションが全然ない」。ギルドは札を押すたびに中身が
   まるごと入れ替わる画面なので、**箱ごと一度動かすのではなく、節が一枚ずつ着地する。**
   立ち上がりの合計は 0.26s + 0.17s で、待ちは一つも増えない（押した先は最初から居る）。 */
.guild-view.fx-view-enter { animation: none; }
@keyframes guild-card-enter {
  from { opacity: 0; transform: translateY(9px); }
  to { opacity: 1; transform: none; }
}
.guild-view.fx-view-enter > .card,
.guild-view.fx-view-enter > .help-details {
  animation: guild-card-enter var(--fx-step) var(--fx-ease) backwards;
}
.guild-view.fx-view-enter > :nth-child(2) { animation-delay: 55ms; }
.guild-view.fx-view-enter > :nth-child(3) { animation-delay: 110ms; }
.guild-view.fx-view-enter > :nth-child(n+4) { animation-delay: 165ms; }
/* キャンプへ入った回だけ、先見機の窓が灯るように降りてくる。 */
@keyframes fx-board-enter {
  from { opacity: 0; transform: translateY(-5px); }
  to { opacity: 1; transform: none; }
}
.fx-board-enter { animation: fx-board-enter var(--fx-step) var(--fx-ease); }

/* ---- 選んだ。**枠がひと呼吸で締まる。**繰り返す操作なので一番短い段を使う。 */
@keyframes fx-select {
  0% { box-shadow: 0 0 0 0 rgba(229, 184, 105, .55); }
  45% { box-shadow: 0 0 0 5px rgba(229, 184, 105, .2); }
  100% { box-shadow: 0 0 0 0 rgba(229, 184, 105, 0); }
}
.fx-select { animation: fx-select var(--fx-quick) var(--fx-ease); }

/* ---- タブを選んだ。押した札が入り込む。 */
@keyframes fx-pick {
  0% { transform: scale(.9); }
  58% { transform: scale(1.035); }
  100% { transform: none; }
}
.fx-pick { animation: fx-pick var(--fx-quick) var(--fx-ease); }

/* ---- 隊列を入れ替えた。**二つの枠が同時に着地する。** */
@keyframes fx-swap {
  0% { transform: scale(.9); box-shadow: 0 0 0 0 rgba(229, 184, 105, .6); }
  55% { transform: scale(1.03); box-shadow: 0 0 0 6px rgba(229, 184, 105, .18); }
  100% { transform: none; box-shadow: 0 0 0 0 rgba(229, 184, 105, 0); }
}
.fx-swap { animation: fx-swap var(--fx-step) var(--fx-ease); }

/* ---- 盤面の役が変わった（見るだけ ⇄ 隊列の組み替え）。 */
@keyframes fx-mode {
  from { opacity: .3; transform: scale(.986); }
  to { opacity: 1; transform: none; }
}
.fx-mode { animation: fx-mode var(--fx-quick) var(--fx-ease); }

/* ---- 得た。**金が内側から満ちて、枠の外へ一度だけ広がる。** */
@keyframes fx-gain {
  0% { transform: scale(.94); filter: brightness(1.85) saturate(.75); box-shadow: 0 0 0 0 rgba(229, 184, 105, .65); }
  40% { transform: scale(1.02); filter: brightness(1.25); box-shadow: 0 0 0 7px rgba(229, 184, 105, .2); }
  100% { transform: none; filter: none; box-shadow: 0 0 0 0 rgba(229, 184, 105, 0); }
}
.fx-gain { animation: fx-gain var(--fx-accent) var(--fx-ease); }

/* ---- 段が上がった。得たのと同じ金だが、**下から突き上げる**ので区別できる。 */
@keyframes fx-level {
  0% { transform: translateY(6px); filter: brightness(1.7); }
  46% { transform: translateY(-3px); filter: brightness(1.22); }
  100% { transform: none; filter: none; }
}
.fx-level { animation: fx-level var(--fx-step) var(--fx-ease); }

/* ---- 入れた／切った。入れたら緑が差し、切ったら灰が一度差す。 */
@keyframes fx-on {
  0% { box-shadow: inset 3px 0 0 var(--good), 0 0 0 0 rgba(155, 214, 158, .5); }
  50% { box-shadow: inset 3px 0 0 var(--good), 0 0 0 6px rgba(155, 214, 158, .14); }
  100% { box-shadow: inset 0 0 0 0 rgba(155, 214, 158, 0), 0 0 0 0 rgba(155, 214, 158, 0); }
}
.fx-on { animation: fx-on var(--fx-step) var(--fx-ease); }
@keyframes fx-off {
  0% { box-shadow: inset 3px 0 0 var(--muted); transform: scale(.985); }
  100% { box-shadow: inset 0 0 0 0 transparent; transform: none; }
}
.fx-off { animation: fx-off var(--fx-quick) var(--fx-ease); }

/* ---- 並べ替えた。**動いた向きへ入ってくる。**向きを取り違えると意味が反転するので、
   上げたときと下げたときで別の反応にする。 */
@keyframes fx-move-up {
  0% { transform: translateY(9px); opacity: .45; }
  100% { transform: none; opacity: 1; }
}
@keyframes fx-move-down {
  0% { transform: translateY(-9px); opacity: .45; }
  100% { transform: none; opacity: 1; }
}
.fx-move-up { animation: fx-move-up var(--fx-quick) var(--fx-ease); }
.fx-move-down { animation: fx-move-down var(--fx-quick) var(--fx-ease); }

/* ---- 装着した／外した。装備の色は青（先見機と同じ情報の側）。 */
@keyframes fx-equip {
  0% { transform: scale(.965); border-color: var(--blue); box-shadow: 0 0 0 0 rgba(145, 203, 213, .6); }
  45% { transform: scale(1.015); border-color: var(--blue); box-shadow: 0 0 0 7px rgba(145, 203, 213, .16); }
  100% { transform: none; box-shadow: 0 0 0 0 rgba(145, 203, 213, 0); }
}
.fx-equip { animation: fx-equip var(--fx-step) var(--fx-ease); }
@keyframes fx-unequip {
  0% { box-shadow: inset 0 0 20px rgba(158, 173, 167, .38); transform: scale(1.012); }
  100% { box-shadow: inset 0 0 0 rgba(158, 173, 167, 0); transform: none; }
}
.fx-unequip { animation: fx-unequip var(--fx-quick) var(--fx-ease); }

/* ---- 癒えた・戻ってきた。 */
@keyframes fx-heal {
  0% { filter: brightness(1.5); box-shadow: 0 0 0 0 rgba(155, 214, 158, .6); }
  45% { filter: brightness(1.15); box-shadow: 0 0 0 8px rgba(155, 214, 158, .18); }
  100% { filter: none; box-shadow: 0 0 0 0 rgba(155, 214, 158, 0); }
}
.fx-heal { animation: fx-heal var(--fx-accent) var(--fx-ease); }

/* ---- 必殺を構えた／降ろした。菫は戦闘のカットインと同じ色。 */
@keyframes fx-ultimate {
  0% { filter: brightness(1.75); box-shadow: 0 0 0 0 rgba(192, 167, 229, .7); }
  40% { filter: brightness(1.2); box-shadow: 0 0 0 9px rgba(192, 167, 229, .18); }
  100% { filter: none; box-shadow: 0 0 0 0 rgba(192, 167, 229, 0); }
}
.fx-ultimate { animation: fx-ultimate var(--fx-accent) var(--fx-ease); }

/* ---- 引き直した。**候補が配り直される。**取った品は画面ごと変わるので、
   ここは引き直しだけが持つ反応である。 */
@keyframes fx-reroll {
  0% { opacity: .1; filter: blur(3px); transform: translateY(5px); }
  100% { opacity: 1; filter: none; transform: none; }
}
.fx-reroll { animation: fx-reroll var(--fx-step) var(--fx-ease); }

/* ---- 拒まれた。**画面の中で唯一、横に揺れる反応。**足りない・できないは
   これだけが持つ（成功の反応と取り違えようがない）。 */
@keyframes fx-deny {
  0%, 100% { transform: translateX(0); }
  18% { transform: translateX(-4px); }
  42% { transform: translateX(4px); }
  68% { transform: translateX(-2px); }
}
.error { animation: fx-deny 320ms var(--fx-ease); }

/* ---- 数が変わった。**増えたら金、減ったら赤、どちらとも言えないなら青。**
   読み値は `<b>` や `<small>` の中にあることが多く、inline のままでは transform が
   効かない。色と光だけで出す（数そのものは常に読める）。 */
@keyframes fx-up {
  0% { filter: brightness(1.6); text-shadow: 0 0 10px var(--gold), 0 0 3px var(--gold); }
  100% { filter: none; text-shadow: none; }
}
@keyframes fx-down {
  0% { filter: brightness(1.4); text-shadow: 0 0 10px var(--bad), 0 0 3px var(--bad); }
  100% { filter: none; text-shadow: none; }
}
@keyframes fx-change {
  0% { filter: brightness(1.5); text-shadow: 0 0 9px var(--blue); }
  100% { filter: none; text-shadow: none; }
}
.fx-up { animation: fx-up var(--fx-accent) var(--fx-ease); }
.fx-down { animation: fx-down var(--fx-accent) var(--fx-ease); }
.fx-change { animation: fx-change var(--fx-accent) var(--fx-ease); }

/* ---- 予測が計算し直された。**窓はブラウン管で、同期が一度外れる。**
   （作者指摘 2026-09-13「窓と数字が一瞬光るだけで、全く機械っぽさがない」）
   光らせるのをやめ、**装置が像を作り直す様子**そのものを出す。四枚が同時に走る。

     1. 像を引き直す硬い線が一度降りる（`fx-rescan`。常時の一本とは別の面に置く）
     2. 面の横の目が濃くなって転がる（`fx-crt-roll`。垂直同期が滑っている）
     3. 読み値の面が段で左右へ飛ぶ（`fx-crt-desync` / `fx-crt-tear`。水平同期が外れた）
     4. 変わった数だけ色分離してブレ、**前の値が横へ千切れてから**新しい値が座る
        （`fx-crt-value` / `fx-crt-ghost`）

   曲線は `steps(1, end)` にする。**ブラウン管は補間しない。**滑らかに寄せると
   「光った」に戻ってしまい、ジジッという当たりが消える。時間は他の反応と同じ
   `--fx-accent` 一段で、終わるのを待たずに次を押せる長さのままにする。

   **釦（.forecaster-actions）だけは動かさない。**ブレている最中に押される場所なので、
   的が左右へ飛んではいけない（貼りついた上端を動かさないのと同じ理由）。

   **class の下で静的な見た目を差し替えない。**反応の class は次の描画まで外れないので、
   背景や濃さを塗り替えると、動きが終わったあとの窓にそれが残る。 */
@keyframes fx-rescan {
  0% { transform: translateY(-40%); opacity: 0; }
  22% { opacity: 1; }
  100% { transform: translateY(400%); opacity: 0; }
}
@keyframes fx-rescan-frame {
  0% { border-color: rgba(145, 203, 213, .9); box-shadow: inset 0 0 30px rgba(83, 153, 164, .34), 0 5px 18px rgba(0, 0, 0, .22); }
  18% { border-color: rgba(145, 203, 213, .45); box-shadow: inset 0 0 18px rgba(83, 153, 164, .1), 0 5px 18px rgba(0, 0, 0, .22); }
  30% { border-color: rgba(145, 203, 213, .85); box-shadow: inset 0 0 26px rgba(83, 153, 164, .28), 0 5px 18px rgba(0, 0, 0, .22); }
  100% { border-color: var(--line); box-shadow: inset 0 0 18px rgba(83, 153, 164, .08), 0 5px 18px rgba(0, 0, 0, .22); }
}
/* 横の目が濃くなり、下へ一度転がる。**100% は書かない。**書かない終端は元の
   `.forecaster-scan::before` の濃さそのものへ戻るので、戻り先が二箇所に散らない。 */
@keyframes fx-crt-roll {
  0% { opacity: 1; transform: translateY(-6px); }
  35% { opacity: .8; transform: translateY(4px); }
  60% { opacity: .55; transform: translateY(-2px); }
}
/* 面が段で左右へ飛ぶ。見出し行と盤面で振り幅と拍をずらす——**同じだけ動かすと
   「窓ごと揺れた」になり、帯ごとに像がずれるブラウン管には見えない。** */
@keyframes fx-crt-desync {
  0% { transform: translateX(-6px) skewX(-1.4deg); filter: brightness(1.55) contrast(1.2); }
  12% { transform: translateX(5px) skewX(1deg); }
  24% { transform: translateX(-3px); filter: brightness(1.3); }
  36% { transform: translateX(4px) skewX(-.6deg); }
  48% { transform: translateX(-2px); filter: brightness(1.12); }
  62% { transform: translateX(1px); }
  74%, 100% { transform: none; filter: none; }
}
@keyframes fx-crt-tear {
  0% { transform: translateX(4px) skewX(1.2deg); filter: brightness(1.4) contrast(1.15); }
  12% { transform: translateX(-5px) skewX(-.9deg); }
  26% { transform: translateX(3px); filter: brightness(1.22); }
  40% { transform: translateX(-2px) skewX(.5deg); }
  54% { transform: translateX(2px); filter: brightness(1.08); }
  68%, 100% { transform: none; filter: none; }
}
/* 変わった数。**色が分離してから合う。**向きの色（金／赤／青）は最後の残光に残し、
   ブレている間は赤と青緑へ割る（ブラウン管の色ずれ）。
   黒い裏打ち（0 1px 2px …）は**どの拍でも落とさない。**落とすと、明るいHPバーの上で
   白い数字が読めなくなる——ブレている最中も、数そのものは読めたままにする。 */
@keyframes fx-crt-value {
  0% { transform: translateX(-5px); text-shadow: -2px 0 rgba(231, 137, 128, .95), 2px 0 rgba(145, 203, 213, .95), 0 1px 2px rgba(6, 11, 12, .9); }
  14% { transform: translateX(6px); text-shadow: 3px 0 rgba(231, 137, 128, .9), -3px 0 rgba(145, 203, 213, .9), 0 1px 2px rgba(6, 11, 12, .9); }
  28% { transform: translateX(-3px); text-shadow: -2px 0 rgba(231, 137, 128, .8), 2px 0 rgba(145, 203, 213, .8), 0 1px 2px rgba(6, 11, 12, .9); }
  42% { transform: translateX(3px); text-shadow: 1px 0 rgba(231, 137, 128, .6), -1px 0 rgba(145, 203, 213, .6), 0 1px 2px rgba(6, 11, 12, .9); }
  56% { transform: translateX(-1px); text-shadow: 0 0 10px var(--fx-crt-tint), 0 0 3px var(--fx-crt-tint), 0 1px 2px rgba(6, 11, 12, .9); }
  70% { text-shadow: 0 0 8px var(--fx-crt-tint), 0 1px 2px rgba(6, 11, 12, .9); }
  100% { transform: none; }
}
/* 前の値。**新しい値の上へ一枚だけ重ね、横へ千切れて消える。**
   読み値そのものは最初から新しい値である（差し替えを遅らせない——遅らせると、
   速く押した回に古い数が残る）。消えるのは影のほうだけ。 */
@keyframes fx-crt-ghost {
  0% { opacity: .95; transform: translateX(-7px) scaleY(1.2); }
  18% { opacity: .75; transform: translateX(8px) scaleY(.82); }
  34% { opacity: .5; transform: translateX(-11px) scaleY(1.3); }
  50% { opacity: .28; transform: translateX(15px) scaleY(.6); }
  64%, 100% { opacity: 0; transform: translateX(22px) scaleY(.4); }
}
/* 変わったのが誰かは、枠そのものが一度ずれて言う。**輝度は上げない**——セルの中は
   HPバー（明るい緑）なので、brightness を掛けると帯が白く飛んで数が読めなくなる。
   代わりに枠の内側へ青緑の光を一度差す（面が引き直された、と枠だけが言う）。 */
@keyframes fx-crt-cell {
  0% { transform: translateX(-3px); box-shadow: inset 0 0 0 1px rgba(145, 203, 213, .8), inset 0 0 16px rgba(83, 153, 164, .4); }
  16% { transform: translateX(3px); box-shadow: inset 0 0 0 1px rgba(145, 203, 213, .35), inset 0 0 10px rgba(83, 153, 164, .2); }
  32% { transform: translateX(-2px); box-shadow: inset 0 0 0 1px rgba(145, 203, 213, .7), inset 0 0 14px rgba(83, 153, 164, .32); }
  50% { transform: translateX(2px); box-shadow: inset 0 0 8px rgba(83, 153, 164, .18); }
  66%, 100% { transform: none; }
}
/* 読み直しは、危険な回の脈（.forecast-bar.loss）より強く出す。**いま読み直した**ほうが
   新しい報せなので、同じ数の class で後ろに置いて勝たせる。 */
.forecaster-window.forecast-bar.fx-recalc,
.forecaster-window.fx-recalc { animation: fx-rescan-frame var(--fx-accent) steps(1, end); }
/* 読み直しの走査は**常時の一本とは別の面**へ置く。同じ面を class で塗り替えると、
   動きが終わったあとも明るい線が窓の上端へ居座る（class は次の描画まで外れない）。
   こちらは `forwards` で下へ抜けきったところに留め、常時の一本は止めない。
   ぼかしただけの常時の帯と違い、**像を引き直している硬い線**が降りてくる。 */
.forecaster-window.fx-recalc::after {
  position: absolute;
  z-index: 1;
  inset: -18% 0 auto;
  height: 30%;
  background: linear-gradient(180deg,
    transparent 0%, rgba(145, 203, 213, .2) 72%, rgba(198, 236, 243, .5) 93%, rgba(214, 245, 250, .9) 98%, transparent 100%);
  content: "";
  pointer-events: none;
  animation: fx-rescan calc(var(--fx-accent) * .8) var(--fx-ease) forwards;
}
.forecaster-window.fx-recalc .forecaster-scan::before { animation: fx-crt-roll var(--fx-accent) steps(1, end); }
.forecaster-window.fx-recalc .forecast-head { animation: fx-crt-desync var(--fx-accent) steps(1, end); }
.forecaster-window.fx-recalc .party-board { animation: fx-crt-tear var(--fx-accent) steps(1, end); }
/* 変わった数だけが、窓の中でブラウン管の差し替わり方をする。**窓の外の読み値は
   これまでどおり色で光るだけ**（タブの札の数まで割れると、画面中が壊れて見える）。 */
.forecaster-window [data-fx-watch].fx-up { --fx-crt-tint: var(--gold); }
.forecaster-window [data-fx-watch].fx-down { --fx-crt-tint: var(--bad); }
.forecaster-window [data-fx-watch].fx-change { --fx-crt-tint: var(--blue); }
.forecaster-window [data-fx-watch].fx-up,
.forecaster-window [data-fx-watch].fx-down,
.forecaster-window [data-fx-watch].fx-change {
  animation: fx-crt-value var(--fx-accent) steps(1, end);
}
.forecaster-window .fx-ghost {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: grid;
  place-items: center;
  opacity: 0;
  color: rgba(198, 236, 243, .92);
  font: inherit;
  white-space: nowrap;
  text-shadow: -1px 0 rgba(231, 137, 128, .8), 1px 0 rgba(145, 203, 213, .8), 0 1px 2px rgba(6, 11, 12, .9);
  pointer-events: none;
  animation: fx-crt-ghost var(--fx-accent) steps(1, end);
}
.forecaster-window .party-cell.fx-crt { animation: fx-crt-cell var(--fx-accent) steps(1, end); }

@media (prefers-reduced-motion: reduce) {
  /* **動きは消すが、状態は消さない。**色・記号・数・ラベルは元から動いていない。 */
  .guild-view.fx-view-enter > .card,
  .guild-view.fx-view-enter > .help-details,
  .fx-view-enter,
  .fx-board-enter,
  .fx-select,
  .fx-pick,
  .fx-swap,
  .fx-mode,
  .fx-gain,
  .fx-level,
  .fx-on,
  .fx-off,
  .fx-move-up,
  .fx-move-down,
  .fx-equip,
  .fx-unequip,
  .fx-heal,
  .fx-ultimate,
  .fx-reroll,
  .fx-up,
  .fx-down,
  .fx-change,
  .error,
  .forecaster-window.forecast-bar.fx-recalc,
  .forecaster-window.fx-recalc,
  .forecaster-window.fx-recalc::after,
  .forecaster-window.fx-recalc .forecaster-scan::before,
  .forecaster-window.fx-recalc .forecast-head,
  .forecaster-window.fx-recalc .party-board,
  .forecaster-window [data-fx-watch].fx-up,
  .forecaster-window [data-fx-watch].fx-down,
  .forecaster-window [data-fx-watch].fx-change,
  .forecaster-window .party-cell.fx-crt,
  .forecaster-window .fx-ghost { animation: none; }
  /* 動きを止めた回は、**置くこと自体をやめる。**止めた姿（前の値の影、上端で
     止まった走査線）がそのまま残るほうが、動かないことより読みにくい。 */
  .forecaster-window .fx-ghost,
  .forecaster-window.fx-recalc::after { display: none; }
  .button,
  .tiny-button,
  .icon-button,
  .tab,
  button.party-cell,
  .board-mode,
  .forecaster-action,
  .character-main,
  .gear-main,
  .equip-slot-button,
  .skill-node-button,
  .sheet-close { transition: none; }
  .button:active:not(:disabled),
  .tab:active:not(:disabled),
  button.party-cell:active:not(:disabled),
  .forecaster-action:active:not(:disabled),
  .skill-node-button:active:not(:disabled) { transform: none; filter: brightness(1.12); }
}


/* ================================================================ 図で言う（作者要望 2026-09-13）
 *
 * **文章で説明する画面はダサい。**規則・内訳・状態・因果は、段落ではなく
 * 記号・数・目盛り・流れで出す。ここはその共通語彙で、画面ごとに似た形を作らない。
 * app.js の glyph() / statTiles() / ruleGrid() / flowStrip() / segmentMeter() /
 * ledgerRows() / splitColumns() が、ここの形だけを使って描く。
 */
.glyph {
  width: 15px;
  height: 15px;
  flex: none;
  vertical-align: -2px;
}

/* 数の並び。**数が主、名が従。**左端の一筋がその数の役目（金＝得るもの、
   赤＝失ったもの、緑＝残るもの）を、読む前に伝える。 */
.stat-tiles {
  display: grid;
  grid-template-columns: repeat(var(--tiles, auto-fit), minmax(74px, 1fr));
  gap: 6px;
  margin-top: 12px;
}
.stat-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  overflow: hidden;
  padding: 9px 10px 8px 12px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: linear-gradient(150deg, rgba(38,56,58,.82), rgba(20,28,30,.92));
}
.stat-tile::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 2px;
  background: var(--line);
}
.stat-tile .tile-glyph {
  width: 13px;
  height: 13px;
  color: var(--muted);
}
.stat-tile b {
  font-size: 20px;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
  line-height: 1.05;
}
.stat-tile b i {
  margin-left: 2px;
  color: var(--muted);
  font-size: 11px;
  font-style: normal;
}
.stat-tile small {
  color: var(--muted);
  font-size: 9.5px;
  letter-spacing: .02em;
  line-height: 1.35;
}
.stat-tile.wide { grid-column: 1 / -1; }
.stat-tile.tone-gold::before { background: var(--gold); }
.stat-tile.tone-gold b,
.stat-tile.tone-gold .tile-glyph { color: var(--gold); }
.stat-tile.tone-good::before { background: var(--good); }
.stat-tile.tone-good b,
.stat-tile.tone-good .tile-glyph { color: var(--good); }
.stat-tile.tone-bad::before { background: var(--bad); }
.stat-tile.tone-bad b,
.stat-tile.tone-bad .tile-glyph { color: var(--bad); }
.stat-tile.tone-blue::before { background: var(--blue); }
.stat-tile.tone-blue b,
.stat-tile.tone-blue .tile-glyph { color: var(--blue); }
.stat-tile.tone-quiet { opacity: .74; }

/* 規則の一段。**記号ひとつ・見出し一語・十数文字。**二行要るなら規則が二つある。 */
.rule-grid {
  display: grid;
  gap: 6px;
  margin-top: 10px;
}
.rule-grid.two { grid-template-columns: 1fr 1fr; }
.rule-cell {
  display: grid;
  grid-template-columns: 30px 1fr;
  gap: 9px;
  align-items: center;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: rgba(24,33,36,.55);
}
.rule-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background: var(--panel-3);
  color: var(--gold);
  font-size: 13px;
}
.rule-mark .glyph { width: 16px; height: 16px; }
.rule-copy {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 7px;
}
.rule-copy b { font-size: 12px; }
.rule-copy em {
  color: var(--gold);
  font-size: 11px;
  font-style: normal;
  font-variant-numeric: tabular-nums;
}
.rule-copy small {
  flex-basis: 100%;
  color: var(--muted);
  font-size: 10px;
  line-height: 1.5;
}
.rule-cell.tone-bad .rule-mark { color: var(--bad); }
.rule-cell.tone-good .rule-mark { color: var(--good); }
.rule-cell.tone-blue .rule-mark { color: var(--blue); }
.rule-cell.tone-quiet { opacity: .72; }
.rule-cell.tone-quiet .rule-mark { color: var(--muted); }

/* 順のあること。**矢印は「この次に何が起きるか」だけに使う。** */
.flow-strip {
  display: flex;
  align-items: stretch;
  gap: 4px;
  margin-top: 10px;
}
.flow-step {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 9px 5px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: rgba(24,33,36,.55);
  text-align: center;
}
.flow-glyph {
  width: 17px;
  height: 17px;
  color: var(--muted);
}
.flow-step b { font-size: 11px; }
.flow-step small {
  color: var(--muted);
  font-size: 9px;
  line-height: 1.4;
}
.flow-step.tone-gold { border-color: rgba(229,184,105,.55); }
.flow-step.tone-gold .flow-glyph,
.flow-step.tone-gold b { color: var(--gold); }
.flow-step.tone-bad .flow-glyph,
.flow-step.tone-bad b { color: var(--bad); }
.flow-step.tone-good .flow-glyph,
.flow-step.tone-good b { color: var(--good); }
.flow-arrow {
  flex: none;
  align-self: center;
  width: 8px;
  height: 8px;
  border-top: 1.6px solid var(--muted);
  border-right: 1.6px solid var(--muted);
  opacity: .8;
  transform: rotate(45deg);
}

/* 段のあるもの。**12段までは目盛り、それ以上は帯。** */
.meter {
  display: flex;
  align-items: center;
  gap: 8px;
}
.meter-label {
  color: var(--muted);
  font-size: 10px;
  white-space: nowrap;
}
.meter-pips {
  display: flex;
  flex: 1;
  gap: 3px;
}
.meter-pips i {
  flex: 1;
  height: 6px;
  border-radius: 2px;
  background: rgba(255,255,255,.1);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.08);
}
.meter-pips i.on { background: var(--gold); box-shadow: none; }
.meter-pips i.next {
  background: rgba(229,184,105,.22);
  box-shadow: inset 0 0 0 1px rgba(229,184,105,.85);
}
.meter-track {
  position: relative;
  flex: 1;
  height: 6px;
  overflow: hidden;
  border-radius: 999px;
  background: rgba(255,255,255,.07);
}
.meter-track i {
  display: block;
  height: 100%;
  background: var(--gold);
}
.meter.tone-good .meter-pips i.on,
.meter.tone-good .meter-track i { background: var(--good); }
.meter.tone-bad .meter-pips i.on,
.meter.tone-bad .meter-track i { background: var(--bad); }

/* 内訳。**長さで比べる。**数字の列だけでは、どれが効いたか読めない。 */
.ledger {
  display: grid;
  gap: 5px;
  margin-top: 10px;
}
.ledger-row {
  display: grid;
  grid-template-columns: minmax(104px, 46%) 1fr auto;
  gap: 8px;
  align-items: center;
  font-size: 10.5px;
}
.ledger-label {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
}
.ledger-label .glyph { width: 13px; height: 13px; }
.ledger-bar {
  height: 5px;
  overflow: hidden;
  border-radius: 999px;
  background: rgba(255,255,255,.07);
}
.ledger-bar i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(229,184,105,.4), var(--gold));
}
.ledger-row b {
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}
.ledger-row.empty { opacity: .4; }
.ledger-row.empty b { color: var(--muted); }

/* 残るもの／消えるもの。**同じ画面に両方を出す。** */
.split-columns {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin-top: 10px;
}
.split-col {
  padding: 9px 10px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: rgba(24,33,36,.55);
}
.split-col b {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 10.5px;
  letter-spacing: .03em;
}
.split-col b .glyph { width: 13px; height: 13px; }
.split-col ul {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 7px 0 0;
  padding: 0;
  list-style: none;
}
.split-col li {
  padding: 3px 7px;
  border-radius: 999px;
  background: var(--panel-3);
  color: var(--muted);
  font-size: 10px;
}
.split-col.keep b { color: var(--good); }
.split-col.keep li { color: var(--ink); }
.split-col.lose b { color: var(--bad); }

/* 決着の一枚（敗北・精算・完走）。**印は図で置き、縁の空気で場の重さを出す。** */
.verdict-plate {
  position: relative;
  overflow: hidden;
  padding-top: 21px;
}
.verdict-plate::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 70% at 50% 0%, rgba(255,255,255,.05), transparent 62%);
  pointer-events: none;
}
.verdict-plate.loss { border-color: rgba(231,137,128,.4); }
.verdict-plate.win { border-color: rgba(229,184,105,.45); }
.verdict-plate > * { position: relative; }
.verdict-plate h2 { margin: 4px 0 0; letter-spacing: .06em; }
.verdict-sigil {
  display: block;
  width: 76px;
  height: 76px;
  margin: 0 auto;
}
.verdict-sigil .sigil-ring {
  stroke-width: 1;
  stroke-dasharray: 3 6;
  opacity: .45;
  transform-origin: 32px 32px;
  animation: sigil-turn 26s linear infinite;
}
.verdict-sigil .sigil-core { stroke-width: 1.5; opacity: .85; }
.verdict-sigil .sigil-slash { stroke-width: 2.6; }
.verdict.win .verdict-sigil {
  color: var(--gold);
  filter: drop-shadow(0 0 12px rgba(229,184,105,.28));
}
.verdict.loss .verdict-sigil {
  color: var(--bad);
  filter: drop-shadow(0 0 12px rgba(231,137,128,.22));
}
@keyframes sigil-turn {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
/* どこで止まったか。**数で言う前に、位置で見せる。** */
.verdict-rail {
  margin: 13px auto 0;
  max-width: 300px;
}
.verdict-rail .meter { gap: 9px; }
.verdict-rail .meter-label { color: var(--gold); font-size: 10.5px; }
@media (prefers-reduced-motion: reduce) {
  .verdict-sigil .sigil-ring { animation: none; }
}

/* 戦闘の凡例（作者要望 2026-09-13）。**盤面と同じ帯・同じ色・同じ大きさの点を並べる。**
   文で言い換えるより短く、盤面と一対一で照らし合わせられる。 */
.legend-heading {
  margin: 14px 0 0;
  color: var(--muted);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .08em;
}
.legend-heading:first-child { margin-top: 4px; }
.legend-bar {
  position: relative;
  display: flex;
  height: 9px;
  margin: 8px 0 2px;
  border-radius: 3px;
  overflow: hidden;
  background: #0b1113;
}
.legend-bar .seg { display: block; height: 100%; }
.legend-bar .seg.main { background: var(--hp-green); }
.legend-bar .seg.recovered { background: var(--hp-green-light); }
.legend-bar .seg.recoverable { background: var(--hp-green-dark); }
.legend-bar .seg.unrecoverable { background: var(--hp-unrecoverable); }
.legend-bar .seg.barrier {
  position: absolute;
  top: 0;
  left: 0;
  width: 52%;
  height: 3px;
  background: #9eada7;
}
.legend-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 5px;
  margin-top: 7px;
}
.legend-item {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: 8px;
  align-items: center;
  padding: 6px 8px;
  border-radius: 8px;
  background: rgba(24,33,36,.6);
}
.legend-swatch {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
}
.legend-copy b { display: block; font-size: 11px; }
.legend-copy small { display: block; color: var(--muted); font-size: 9px; line-height: 1.4; }
.legend-swatch .chip {
  width: 16px;
  height: 9px;
  border-radius: 2px;
}
.legend-swatch .chip.main { background: var(--hp-green); }
.legend-swatch .chip.recovered { background: var(--hp-green-light); }
.legend-swatch .chip.recoverable { background: var(--hp-green-dark); }
.legend-swatch .chip.unrecoverable { background: var(--hp-unrecoverable); box-shadow: inset 0 0 0 1px rgba(255,255,255,.12); }
.legend-swatch .chip.barrier { background: #9eada7; height: 4px; }
.legend-swatch .chip.tone-green { background: var(--hp-green); }
.legend-swatch .chip.tone-yellow { background: var(--hp-yellow); }
.legend-swatch .chip.tone-red { background: var(--hp-red); }
/* 一撃の重さは**点の大きさそのもの**で出す（「三段です」と書かない）。 */
.legend-swatch .hit {
  border-radius: 999px;
  background: var(--bad);
}
.legend-swatch .hit-1 { width: 6px; height: 6px; opacity: .7; }
.legend-swatch .hit-2 { width: 11px; height: 11px; opacity: .85; }
.legend-swatch .hit-3 { width: 17px; height: 17px; box-shadow: 0 0 9px rgba(231,137,128,.5); }
.legend-swatch .box {
  width: 14px;
  height: 16px;
  border: 1px solid var(--line);
  border-radius: 3px;
  background: var(--panel-3);
}
.legend-swatch .box.lunge { transform: translateX(4px); border-color: var(--gold); }
.legend-swatch .box.shake { transform: rotate(-6deg); border-color: var(--bad); }
.legend-swatch .line {
  width: 20px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, var(--gold));
}
.legend-swatch .aim {
  position: relative;
  width: 16px;
  height: 16px;
  border: 1px solid transparent;
  background:
    linear-gradient(var(--gold), var(--gold)) 0 0 / 5px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 0 0 / 1px 5px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 0 / 5px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 0 / 1px 5px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 0 100% / 5px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 0 100% / 1px 5px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 100% / 5px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 100% / 1px 5px no-repeat;
}
.legend-swatch .legend-number {
  color: var(--bad);
  font-size: 13px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
@media (max-width: 380px) {
  .legend-grid { grid-template-columns: 1fr; }
}

/* 名前の名札（締めの一枚）。**「今回の仲間: A、B、C」と書かず、札で並べる。** */
.name-chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 5px;
  margin-top: 8px;
}
.name-chips span {
  padding: 4px 9px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(24,33,36,.6);
  font-size: 10.5px;
}
.name-chips .empty { color: var(--muted); }
.complete-trail { margin-top: 13px; }
/* 得たもの一行。**数の変化は金の札で出す。** */
.gain-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 12px 0 0;
  padding: 5px 10px;
  border: 1px solid rgba(229,184,105,.45);
  border-radius: 999px;
  background: rgba(90,68,26,.3);
  color: var(--gold);
  font-size: 11px;
  font-weight: 700;
}
.gain-chip .glyph { width: 14px; height: 14px; }

/* 図鑑の札。**見た数・倒した数は札で、書き足しまでの残りは目盛りで出す。** */
.codex-counts {
  display: flex;
  gap: 8px;
  color: var(--muted);
  font-size: 9.5px;
  white-space: nowrap;
}
.codex-counts span {
  display: inline-flex;
  align-items: center;
  gap: 3px;
}
.codex-counts .glyph { width: 12px; height: 12px; }
.codex-seal {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding-top: 9px;
  border-top: 1px dashed var(--line);
}
.codex-seal > .glyph {
  width: 14px;
  height: 14px;
  color: var(--muted);
}
.codex-seal .meter { flex: 1; }
.codex-seal .meter-label { font-size: 9.5px; }


/* 十二戦の作戦盤。**上端の窓と同じ先見機が映している像**なので、窓の作りを
   `.forecaster-window` から丸ごと借りる（縁・下地・角の括弧・走査線・見出しの一行）。
   作者要望 2026-09-15 —「同じ先見機なのに、上と下で別の機械に見える」。
   踏破済みの回だけ、走査を止めて読み値を緑へ寄せ、「これは記録だ」と言う。 */
.encounter-archive {
  position: relative;
  /* 作者指摘 2026-09-15 — 窓の中の重なり（見出し z-index 2・走査線 1）は、**窓の中で
     閉じる。**閉じないと、貼りついたチュートリアルの札（`.tutorial-note-card.pinned`、
     同じ z-index 2 で DOM 上は前）の手前へ見出しが出る。上端の窓は `.camp-top`
     （z-index 3 の sticky）が既に文脈を作っているので、こちらだけが漏れていた。 */
  isolation: isolate;
  overflow: hidden;
  padding: 8px 10px 10px;
  border-radius: 12px;
}
.encounter-archive.mode-record {
  background:
    radial-gradient(circle at 8% 0%, rgba(155, 214, 158, .08), transparent 34%),
    linear-gradient(180deg, rgba(26, 38, 34, .98), rgba(19, 28, 26, .98));
  box-shadow: inset 0 0 18px rgba(155, 214, 158, .05), 0 5px 18px rgba(0, 0, 0, .22);
}
.encounter-archive.mode-record::before { border-color: rgba(155, 214, 158, .1); }
.encounter-archive .map-progress { position: relative; margin: 9px 0 10px; }
.encounter-archive .map-node {
  padding: 0;
  color: var(--muted);
  font: inherit;
  appearance: none;
  cursor: pointer;
}
.encounter-archive .map-node.available { border-color: rgba(145, 203, 213, .28); }
.encounter-archive.mode-forecast .map-node.inspected {
  border: 2px solid var(--blue);
  background: rgba(52, 103, 111, .42);
  color: var(--ink);
  box-shadow: 0 0 0 1px rgba(145, 203, 213, .25), 0 0 13px rgba(83, 153, 164, .22);
}
.encounter-archive.mode-forecast .map-node.inspected.current {
  border-color: var(--gold);
  box-shadow: 0 0 0 1px rgba(145, 203, 213, .35), 0 0 13px rgba(83, 153, 164, .22);
}
.encounter-archive.mode-record .map-node.inspected {
  border: 2px solid var(--good);
  background: #2a4936;
  color: var(--good);
  box-shadow: 0 0 0 1px rgba(155, 214, 158, .2);
}
.encounter-archive .map-node.current::before {
  position: absolute;
  top: -4px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 7px var(--gold);
  content: "";
}

/* 見出しは上端の窓と同じ一行（`.forecast-head` が並びを持つ）。
   ここで足すのは、右端の読み値が「02/12」であることだけ。 */
.encounter-console > .forecast-readout > strong {
  font: 800 20px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: -.05em;
}
/* 未来は先見機の青、踏破済みは戦歴の緑。**読み値の色だけが過去と未来を分ける。** */
.encounter-console.forecast > .forecast-readout > strong { color: var(--blue); }
.encounter-console > .forecast-readout > strong small {
  margin-left: 2px;
  color: var(--muted);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0;
}
.encounter-console.record > .forecast-readout > strong { color: var(--good); }
.encounter-console.record .forecast-title { color: var(--muted); }
.encounter-console-mark {
  display: grid;
  width: 18px;
  height: 18px;
  flex: none;
  place-items: center;
  border-radius: 50%;
  background: rgba(155, 214, 158, .1);
  color: var(--good);
}
.encounter-console-mark .glyph { width: 11px; height: 11px; }
.encounter-console-signal {
  display: flex;
  align-items: center;
  gap: 3px;
  margin-right: 2px;
  color: var(--blue);
}
.encounter-console-signal i {
  width: 3px;
  height: 9px;
  border-radius: 2px;
  background: currentColor;
  opacity: .25;
  animation: encounter-signal 900ms steps(2, end) infinite;
}
.encounter-console-signal i:nth-child(2) { height: 14px; animation-delay: 150ms; }
.encounter-console-signal i:nth-child(3) { height: 6px; animation-delay: 300ms; }

/* 投影の面は**窓の中身**であって、もう一枚の箱ではない。枠も下地も持たせず、
   窓の走査線（.forecaster-scan）がそのまま乗るようにする。 */
.encounter-projection {
  position: relative;
  padding: 0;
  border: 0;
  background: transparent;
}
.encounter-projection.forecast { animation: future-projection-in var(--fx-step) steps(4, end); }
.encounter-projection .enemy-details { margin-top: 9px; }

.encounter-report {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 4px;
}
.encounter-report-cell {
  display: grid;
  min-width: 0;
  grid-template-columns: 16px minmax(0, 1fr);
  align-items: center;
  gap: 4px;
  padding: 6px 4px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: rgba(15, 23, 25, .55);
}
.encounter-report-cell > .glyph { width: 14px; height: 14px; color: var(--muted); }
.encounter-report-cell > span,
.encounter-report-cell b,
.encounter-report-cell small { display: block; min-width: 0; }
.encounter-report-cell b {
  overflow: hidden;
  color: var(--ink);
  font-size: 11px;
  line-height: 1.05;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.encounter-report-cell small {
  overflow: hidden;
  color: var(--muted);
  font-size: 7px;
  line-height: 1.1;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.encounter-projection.forecast .encounter-report-cell {
  border-color: rgba(145, 203, 213, .17);
  background: rgba(11, 25, 27, .72);
}
.encounter-projection.forecast .encounter-report-cell > .glyph,
.encounter-projection.forecast .encounter-report-cell b { color: var(--blue); }
.encounter-projection.record .encounter-report-cell:first-child > .glyph,
.encounter-projection.record .encounter-report-cell:first-child b { color: var(--gold); }
.encounter-projection.record .encounter-report-cell:nth-child(2) > .glyph,
.encounter-projection.record .encounter-report-cell:nth-child(2) b { color: var(--good); }
.result-encounter-report { padding: 9px; }

.enemy-stat-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 4px;
  margin-top: 9px;
}
.enemy-stat-grid > span {
  display: grid;
  min-width: 0;
  place-items: center;
  padding: 5px 2px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: rgba(15, 23, 25, .5);
}
.enemy-stat-grid small { color: var(--muted); font-size: 7px; }
.enemy-stat-grid b { font-size: 11px; font-variant-numeric: tabular-nums; }
.enemy-targeting {
  display: flex;
  align-items: flex-start;
  gap: 7px;
  margin-top: 8px;
  padding: 8px;
  border-left: 2px solid var(--line);
  background: rgba(78, 37, 37, .16);
}
.enemy-card .enemy-targeting p {
  min-height: 0;
  margin: 0;
  color: #e8c4bd;
}
.enemy-detail-mark { flex: 0 0 auto; color: var(--muted); font-size: 12px; }
.enemy-skill-list { display: grid; gap: 5px; margin-top: 8px; }
.enemy-skill-row {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: 7px;
  align-items: start;
  padding-top: 6px;
  border-top: 1px solid rgba(58, 77, 79, .55);
}
.enemy-skill-row > span:last-child,
.enemy-skill-row b,
.enemy-skill-row small { display: block; min-width: 0; }
.enemy-skill-row b { color: var(--ink); font-size: 10px; }
.enemy-skill-row small { color: var(--muted); font-size: 8px; line-height: 1.35; }
.enemy-skill-kind {
  display: grid;
  width: 22px;
  height: 22px;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 5px;
  color: var(--muted);
  font: 800 9px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
}
.encounter-projection.forecast .enemy-board-cell {
  border-color: rgba(145, 203, 213, .28);
  background: rgba(11, 25, 27, .72);
}
.encounter-projection.forecast .enemy-board-cell.selected {
  border-color: var(--blue);
  background: rgba(52, 103, 111, .3);
  box-shadow: 0 0 0 1px rgba(145, 203, 213, .22);
}
.encounter-projection.forecast .enemy-card {
  border-color: rgba(145, 203, 213, .25);
  background: rgba(11, 25, 27, .62);
}
.encounter-projection.forecast .enemy-stat-grid > span {
  border-color: rgba(145, 203, 213, .18);
  background: rgba(11, 25, 27, .72);
}
.encounter-projection.forecast .enemy-targeting {
  border-left-color: var(--blue);
  background: rgba(83, 153, 164, .09);
}
.encounter-projection.forecast .enemy-card .enemy-targeting p { color: #c8e8ed; }
.encounter-projection.forecast .enemy-detail-mark,
.encounter-projection.forecast .enemy-skill-kind { color: var(--blue); }
.encounter-projection.forecast .enemy-skill-kind { border-color: rgba(145, 203, 213, .45); }

@keyframes encounter-signal {
  0%, 100% { opacity: .2; transform: scaleY(.55); }
  50% { opacity: .9; transform: scaleY(1); }
}
@keyframes future-projection-in {
  0% { opacity: .38; transform: translateX(-4px); filter: contrast(1.5) brightness(1.45); }
  30% { opacity: .8; transform: translateX(3px); }
  55% { transform: translateX(-1px); filter: contrast(1.15) brightness(1.1); }
  100% { opacity: 1; transform: none; filter: none; }
}
@media (prefers-reduced-motion: reduce) {
  .encounter-console-signal i,
  .encounter-projection.forecast { animation: none; }
}
