/* shogiground には CSS も駒画像も同梱されていない（npmパッケージに入っているのは
   esm/ と dist/ だけ）。そこで盤も駒も、画像を1枚も使わずCSSだけで描いている。
   駒は漢字のテキストなので、拡大しても滲まず、素材のライセンスも発生しない。 */

:root {
  /* ネイティブの部品（スクロールバー・select・入力欄）を地に合わせる。
     これが無いと暗い配色でスクロールバーだけ白いままになる。 */
  color-scheme: light;
  --paper: #f6f2e9;
  --paper-raised: #fffdf8;
  --ink: #24201b;
  --ink-soft: #6d6459;
  --rule: #ddd4c2;
  --board: #f9b34e;
  --board-edge: #6f5027;
  --line: #000;
  --accent: #b23a2c;
  --ok: #2f7d4f;
  /* 盤上の印は lishogi の値をそのまま使う（ui/common/css/theme/_dark.scss）。
     選択マスと着手可能マスの点を同じ色にしてあるのが要点で、色を分けると散らかる。 */
  --selected: rgba(20, 85, 30, .5);
  --selected-hover: rgba(20, 85, 30, .25);
  --last-dest: rgba(169, 199, 0, .41);
  --check: rgba(204, 51, 34, .5);
  /* 間隔の段。open-props の --size-* の作りに倣うが、値は open-props のものではなく
     このCSSで実際に多く使われていた8つをそのまま拾った（丸めていないので見た目は変わらない）。
     ここに無い値（.15rem, .55rem など）はリテラルのまま。増やすときは、
     新しい値を足すのではなく、まずこの段に寄せられないかを見る。 */
  --sp-1: .1rem;
  --sp-2: .2rem;
  --sp-3: .3rem;
  --sp-4: .4rem;
  --sp-5: .5rem;
  --sp-6: .6rem;
  --sp-7: .8rem;
  --sp-8: 1rem;

  /* 盤の大きさ。main.js が localStorage の値で上書きする。 */
  --board-scale: 100%;
  --board-scale-f: 1;
  --sans: system-ui, "Hiragino Sans", "Noto Sans JP", Meiryo, sans-serif;
  --serif: "Hiragino Mincho ProN", "Yu Mincho", "Noto Serif JP", "MS Mincho", serif;
}
/* 英語版は本文の書体を英語向けに。行間も日本語より詰める。 */
:root:lang(en) {
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  --serif: Georgia, "Times New Roman", "Noto Serif", serif;
}

/* 暗い配色。値は下の :root[data-theme="dark"] と同じものが2箇所ある。
   片方を変えたら両方直すこと（CSSにブロックを共有する書き方が無い）。
   :not([data-theme="light"]) が要点で、これが無いと端末が暗いときに
   歯車で「明るい」を選んでも効かない。 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --paper: #17161a;
    --paper-raised: #201e24;
    --ink: #ece7dd;
    --ink-soft: #9b9287;
    --rule: #35323a;
    /* 盤そのものの色は明暗で変えない。lishogiも盤テーマはテーマ非依存で、
       ここを暗くすると駒の朱字と成駒の判別が落ちる。 */
    --board-edge: #2b2018;
    --accent: #e0705f;
    --ok: #7cc79a;
  }
}
/* 歯車で「暗い」を選んだとき。端末の設定に関わらず効く。 */
:root[data-theme="dark"] {
    color-scheme: dark;
    --paper: #17161a;
    --paper-raised: #201e24;
    --ink: #ece7dd;
    --ink-soft: #9b9287;
    --rule: #35323a;
    /* 盤そのものの色は明暗で変えない。lishogiも盤テーマはテーマ非依存で、
       ここを暗くすると駒の朱字と成駒の判別が落ちる。 */
    --board-edge: #2b2018;
    --accent: #e0705f;
    --ok: #7cc79a;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  line-height: 1.6;
  -webkit-text-size-adjust: 100%;
  /* 触ったときの既定の青い矩形をやめ、墨の薄い色にする。 */
  -webkit-tap-highlight-color: color-mix(in srgb, var(--ink) 12%, transparent);
}

/* 押せるものはダブルタップの拡大待ち（約300ms）を待たない。
   盤は shogiground が touch-action を自前で持つので触らない。 */
button, a, label, summary, select, input[type="range"], input[type="checkbox"] {
  touch-action: manipulation;
}

/* 見出しは行末の1語だけが落ちるのを避ける。日本語の折り返し位置は budoux が決める。 */
h1, h2, h3 { text-wrap: balance; }

/* budoux が入れた <wbr> を効かせる。日本語は既定でどこでも折り返せるので、
   keep-all で「文節の切れ目だけ」に絞る。長すぎる語（URL等）は anywhere で逃がす。
   build.mjs の phraseJa が <wbr> を入れる範囲と、ここの選択子は必ず揃えること。 */
:lang(ja) h1, :lang(ja) h2, :lang(ja) h3,
:lang(ja) .lead, :lang(ja) .tagline, :lang(ja) .mode-desc {
  word-break: keep-all;
  overflow-wrap: anywhere;
}
:lang(en) body { line-height: 1.5; }

.app {
  max-width: calc(80rem * var(--board-scale-f, 1));
  margin: 0 auto;
  padding: var(--sp-6) 1.25rem 3rem;
  /* 切り欠き・ホームバーのある端末で端が隠れないようにする。 */
  padding-left: max(1.25rem, env(safe-area-inset-left));
  padding-right: max(1.25rem, env(safe-area-inset-right));
  padding-bottom: calc(3rem + env(safe-area-inset-bottom));
}

/* 本文へ飛ぶ。ふだんは見えず、Tabで最初に出る。 */
.skip-link {
  position: absolute;
  left: .5rem;
  top: -3rem;
  z-index: 20;
  padding: var(--sp-5) var(--sp-7);
  background: var(--paper-raised);
  color: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 4px;
  font-size: .875rem;
}
.skip-link:focus { top: .5rem; }

/* 読み上げにだけ残す文字。 */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ---- 上のバー ---- */

.topbar {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-6) var(--sp-8);
  flex-wrap: wrap;
  padding: .35rem 0 .55rem;
  margin-bottom: var(--sp-8);
  border-bottom: 1px solid var(--rule);
}
.logo {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-5);
  color: var(--ink);
  text-decoration: none;
  font-family: var(--serif);
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: .02em;
  white-space: nowrap;
}
.logo svg { width: 1.5rem; height: 1.5rem; color: var(--ink); }
.logo-dot { fill: var(--accent); }
.logo:hover .logo-dot { fill: var(--board); }
.menu {
  display: flex;
  align-items: center;
  gap: var(--sp-2) .9rem;
  margin-left: auto;
  font-size: .85rem;
}
.menu a, .menu button:not(.gear) {
  color: var(--ink-soft);
  text-decoration: none;
  background: none;
  border: 0;
  padding: .15rem 0;
  font: inherit;
  font-size: .85rem;
  cursor: pointer;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
}
.menu a:hover, .menu button:not(.gear):hover { color: var(--ink); }
.menu a.current { color: var(--ink); font-weight: 600; border-bottom-color: var(--accent); }
.menu .lang {
  padding: .05rem .45rem;
  border: 1px solid var(--rule);
  border-radius: 3px;
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .04em;
}
.gear {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  background: var(--paper-raised);
  color: var(--ink-soft);
  border: 1px solid var(--rule);
  border-radius: 4px;
  cursor: pointer;
}
.gear:hover { color: var(--ink); border-color: var(--ink-soft); }
.gear svg { width: 1.1rem; height: 1.1rem; fill: currentColor; }
.settings-pop {
  position: absolute;
  top: calc(100% + .4rem);
  right: 0;
  z-index: 5;
  display: grid;
  gap: var(--sp-6);
  width: 16rem;
  padding: var(--sp-7);
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 6px;
  box-shadow: 0 8px 24px -12px rgba(0, 0, 0, .5);
}
.settings-pop label {
  display: flex; flex-direction: column; gap: var(--sp-2);
  font-size: .75rem; color: var(--ink-soft); min-width: 0;
}
.settings-pop select { min-width: 0; width: 100%; }
.settings-pop label.check {
  flex-direction: row; align-items: center; gap: .45rem; cursor: pointer;
}
.settings-pop label.check input { margin: 0; accent-color: var(--accent); }
.pop-note { margin: 0; font-size: .7rem; color: var(--ink-soft); line-height: 1.5; }
@media (max-width: 40rem) {
  /* 狭いときは「玉分け将棋について」を畳む。ルールのページとホームから辿れる。 */
  .menu .menu-story { display: none; }
}

/* ---- ホーム ---- */

/* ホーム。見出しの下で2列に割り、左に設定、右に生成する盤（homeboard.js）。
   開始ボタンを押す前に盤が見え、1280×900 で下半分が空いていたのも埋まる。
   狭い画面では1列で、盤は設定の後ろ（開始ボタンを押し下げない）。 */
.home {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0 3rem;
  max-width: 44rem;
  margin: 0 auto;
  padding: var(--sp-5) 0 var(--sp-8);
}
@media (min-width: 56rem) {
  .home { max-width: 66rem; grid-template-columns: minmax(0, 1fr) minmax(16rem, 24rem); align-items: start; }
  .home > h1, .home > .tagline { grid-column: 1 / -1; }
  .home > .setup, .home > .intro { grid-column: 1; }
  .home > .home-board { grid-column: 2; grid-row: 3 / span 2; position: sticky; top: 1rem; }
}
/* 狭い画面では設定の後ろに回す（DOMでは設定より前にある。広い画面の2列目に置くため）。
   広い画面では下の grid-row の明示配置が効くので order は関係しない。 */
.home > .setup { order: 1; }
.home > .home-board { order: 2; }
.home > .intro { order: 3; }
/* 誰と指すか。3つのタブ。選んだものは墨で塗る（主ボタンと同じ色）。 */
.opp {
  display: grid; grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--rule); border-radius: 8px; background: var(--paper-raised); overflow: hidden;
}
.opp button {
  position: relative; display: grid; gap: .05rem; justify-items: center; min-width: 0;
  padding: .65rem var(--sp-4) .55rem; background: transparent; color: inherit; border: 0; border-right: 1px solid var(--rule);
  font: inherit; cursor: pointer;
}
.opp button:last-child { border-right: 0; }
.opp button:hover { background: color-mix(in srgb, var(--rule) 30%, transparent); }
.opp button:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }
.opp button[aria-checked="true"] { background: var(--ink); color: var(--paper); }
.opp .t { font-family: var(--serif); font-weight: 700; font-size: 1.05rem; white-space: nowrap; }
.opp .s { font-size: .72rem; color: var(--ink-soft); white-space: nowrap; }
.opp button[aria-checked="true"] .s { color: color-mix(in srgb, var(--paper) 70%, transparent); }
/* 待合の募集の数。他のタブに居ても人が居ることが分かる。 */
.opp .badge {
  position: absolute; top: .4rem; right: .45rem; min-width: 1.3rem; padding: 0 .35rem; border-radius: 1rem;
  background: var(--accent); color: #fff; font-size: .7rem; font-weight: 700; line-height: 1.3rem; text-align: center;
  font-variant-numeric: tabular-nums;
}
/* 狭い画面では副題を省く（3つ並べて折り返さないため）。英語は語が長いので少し早めに省く。 */
@media (max-width: 30rem) { .opp .s { display: none; } .opp .t { font-size: .95rem; } }
:lang(en) .opp .t { font-family: var(--sans); font-size: .95rem; }
@media (max-width: 36rem) { :lang(en) .opp .s { display: none; } }
/* ボタンの下の一行（友達: リンクを知らない人は入れない／待合: 誰でも入れる）。 */
.setup-note { margin: -.5rem 0 0; font-size: .8rem; color: var(--ink-soft); }
/* 待合。公開で募集中の部屋。1行に名前・何の対局か・参加。設定の中にあり、待合タブだけに出る。 */
.lobby h2 { margin: 0 0 var(--sp-4); font-size: .75rem; font-weight: 600; letter-spacing: .1em; color: var(--ink-soft); }
.lobby .lobby-seek-head { margin: 1.2rem 0 0; }
.lobby-note { margin: 0; font-size: .8rem; color: var(--ink-soft); }
.lobby-note:empty { display: none; }
.seeks { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-4); }
.seeks li {
  display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto; gap: var(--sp-3) var(--sp-7); align-items: center;
  padding: var(--sp-5) var(--sp-7); background: var(--paper-raised); border: 1px solid var(--rule); border-radius: 6px; font-size: .85rem;
}
.seeks .seek-who { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 10rem; }
.seeks .seek-info { color: var(--ink-soft); font-size: .8rem; }
.seeks button {
  padding: var(--sp-4) var(--sp-7); background: var(--ink); color: var(--paper); border: 1px solid var(--ink); border-radius: 4px;
  font: inherit; font-size: .8rem; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.seeks button:disabled { opacity: .45; cursor: not-allowed; }
@media (max-width: 34rem) { .seeks li { grid-template-columns: minmax(0, 1fr) auto; } .seeks .seek-info { grid-column: 1 / -1; } }
.setup-grid input[type="text"] {
  width: 100%; min-width: 0; padding: .45rem var(--sp-5);
  background: var(--paper-raised); color: var(--ink); border: 1px solid var(--rule); border-radius: 4px;
  font: inherit; font-size: .9rem;
}
.home-board { display: grid; gap: var(--sp-5); justify-items: center; margin: 1.6rem auto 0; max-width: 20rem; width: 100%; }
@media (min-width: 56rem) { .home-board { margin: 0; max-width: none; } }
.home-board canvas { display: block; width: 100%; aspect-ratio: 1; }
.home-board-cap { margin: 0; font-size: .78rem; color: var(--ink-soft); line-height: 1.6; text-align: center; }
/* モード札の小盤。空の盤（布石将棋）と、両玉だけ置いた盤（玉分け将棋）。 */
.mode-fig { grid-column: 2; grid-row: 1 / 3; width: 3.6rem; height: 3.6rem; justify-self: end; align-self: start; }
.mode-fig rect { fill: var(--board); stroke: var(--board-edge); stroke-width: 3; }
.mode-fig .l path { stroke: #000; stroke-width: 1; opacity: .8; }
.mode-fig .k { fill: #fbf3d5; stroke: var(--accent); stroke-width: 2.2; stroke-linejoin: round; }
.home h1 {
  margin: 0;
  font-family: var(--serif);
  font-size: 2rem;
  letter-spacing: .04em;
  line-height: 1.3;
}
.tagline { margin: .25rem 0 1.4rem; color: var(--ink-soft); font-size: .95rem; }
.setup { display: grid; gap: var(--sp-8); }
.modes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-7);
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}
.modes legend {
  grid-column: 1 / -1;
  padding: 0;
  margin-bottom: var(--sp-2);
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .1em;
  color: var(--ink-soft);
}
@media (max-width: 34rem) { .modes { grid-template-columns: 1fr; } }
.mode-card {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  /* 名前・説明・帯の3行。説明の行が余りを取るので、2枚の札の帯が同じ高さに揃う
     （説明の長さが違っても、片方の札の下だけ空かない）。 */
  grid-template-rows: auto 1fr auto;
  gap: var(--sp-3) var(--sp-7);
  padding: .9rem var(--sp-8);
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 8px;
  cursor: pointer;
  min-width: 0;
}
.mode-card:hover { border-color: var(--ink-soft); }
.mode-card:has(input:checked) { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.mode-card:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.mode-card input { position: absolute; width: 1px; height: 1px; margin: -1px; opacity: 0; }
.mode-name { font-family: var(--serif); font-size: 1.2rem; font-weight: 700; }
/* 名前の隣の小さな札。二つのルールの関係（基本／その釣り合い形）を一語で。 */
.mode-tag {
  display: inline-block; vertical-align: .2em; margin-left: .2em; padding: 0 .45em;
  font-family: var(--sans); font-size: .66rem; font-weight: 600; letter-spacing: .04em;
  color: var(--ink-soft); border: 1px solid var(--rule); border-radius: 999px; line-height: 1.6; white-space: nowrap;
}
.mode-desc { font-size: .84rem; color: var(--ink-soft); line-height: 1.5; text-wrap: pretty; }
/* カードの中の1局の流れ。対局画面のフェーズ帯（.stepper / .step）と同じ部品で、
   この将棋だけの段は塗り、普通の将棋の段は破線。段の本体の見た目は「右のパネル」の節。 */
.stepper.mini { margin-top: var(--sp-3); grid-column: 1 / -1; }
.stepper.mini .step { cursor: inherit; text-align: center; padding: .15rem .25rem; font-size: .68rem;
                      color: var(--ink-soft); background: color-mix(in srgb, var(--rule) 35%, transparent); }
.stepper.mini .step.shogi { border-style: dashed; background: transparent; }
.stepper.mini .step .t { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 英語は段の名前が長い（Place kings / Choose side）。切らずに折り返し、4段の副題は省く。 */
:lang(en) .stepper.mini .step .t { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: normal; hyphens: auto; line-height: 1.2; }
:lang(en) .stepper.mini.four .step .s { display: none; }
/* 英語の4段は「Placement」が等幅の段に入りきらない。段の幅を語に合わせる（他の段は2行に折れる）。 */
:lang(en) .stepper.mini.four .step { flex: 1 1 auto; }
.setup-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-6) var(--sp-7); }
@media (max-width: 34rem) { .setup-grid { grid-template-columns: 1fr; } }
.setup-grid label {
  display: flex; flex-direction: column; gap: .15rem;
  font-size: .75rem; color: var(--ink-soft); min-width: 0;
}
.setup-grid label[hidden] { display: none; }
.setup-grid select { width: 100%; min-width: 0; }
.setup select, .settings-pop select {
  padding: .45rem var(--sp-5);
  background: var(--paper-raised);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 4px;
  font: inherit;
  font-size: .9rem;
}
.setup select:disabled { opacity: .5; cursor: not-allowed; }
.settings-pop input[type="range"] {
  width: 100%;
  height: 1.1rem;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}
.boot { margin: 0; min-height: 1.4em; font-size: .8rem; color: var(--ink-soft); }
.boot.error { color: var(--accent); }
.buttons { display: flex; flex-wrap: wrap; gap: var(--sp-5); }
.buttons button {
  flex: 1 1 auto;
  padding: .7rem var(--sp-8);
  background: var(--paper-raised);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 6px;
  font: inherit;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
}
.buttons button:hover:not(:disabled) { border-color: var(--ink-soft); }
.buttons button.primary { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.buttons button:disabled { opacity: .45; cursor: not-allowed; }
.intro { margin-top: 2rem; font-size: .9rem; color: var(--ink-soft); }
.intro h2 { margin: 0 0 var(--sp-3); font-size: .75rem; font-weight: 600; letter-spacing: .1em; }
.intro p { margin: var(--sp-3) 0; }
.intro a { color: inherit; }

/* ---- 対局画面 ---- */

.layout {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 56rem) {
  .layout {
    grid-template-columns: minmax(0, 1fr) 19rem;
    /* パネルは盤の列の高さに合わせて伸びる。中身で高さを決めない（棋譜だけが縮む）。
       パネルの中の並べ方は「右のパネル」の節の末尾（詳細度を上げて後ろに置いてある）。 */
    align-items: stretch;
  }
}

/* 評価ゲージ。lishogiの縦の帯を、盤の左に立てる。
   通常フェーズだけ出す。布石フェーズの「採用手の確率」は方策の自信であって
   優劣ではないので、両側に振れる帯には載せない（main.js の renderGauge）。 */
.eval-gauge {
  position: relative;
  width: 100%;
  height: 6px;
  margin-bottom: var(--sp-5);
  background: var(--rule);
  border-radius: 2px;
  overflow: hidden;
}
.eval-gauge-fill {
  position: absolute;
  left: 0;
  bottom: 0;
  width: calc(var(--eval-p, .5) * 100%);
  height: 100%;
  background: var(--ink);
  transition: width .25s ease, height .25s ease;
}
@media (prefers-reduced-motion: reduce) {
  .eval-gauge-fill { transition: none; }
}
/* ゲージが出入りするたびに盤の大きさが変わる。終局した瞬間に評価を見せる作りなので、
   投了したら盤が一回り縮んで右へずれた（1440幅で盤 716.7px → 701px）。
   場所は常に取り、見せるか見せないかだけを切り替える。
   [hidden] の display:none（ファイル末尾・!important）より特異度が高いので勝つ。
   広いときは盤の左の8px、狭いときは盤の上の6px。どちらの跳ねも これで止まる。 */
.eval-gauge[hidden] { display: block !important; visibility: hidden; }

/* エンジンの言い分。読み筋（通常フェーズ）と評価。 */
.engine { display: grid; gap: var(--sp-1); font-size: .75rem; color: var(--ink-soft); }
.engine p { margin: 0; }
.engine-head { font-weight: 600; }
.engine-pv { overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.engine-pv:empty { display: none; }

/* ---- 盤まわり ---- */

.board-column { position: relative; display: flex; flex-direction: column; }
/* 広いときは座標を盤の外へ出すので、上に筋の数字ぶんの場所を空ける。
   段の漢数字は盤と駒台のあいだの gap(2vmin) に収まる。 */
@media (min-width: 56rem) {
  /* 広いときはゲージを盤の左に立てる。行にしても盤の大きさの計算は変わらない
     （.sg-wrap の幅は width:100% と下の max-width で決まる）。 */
  /* align-self: start が要る。.layout は align-items: stretch で、盤の列も行の高さまで
     引き伸ばされる。この列は row の flex なので、伸びた高さがそのまま .sg-wrap の
     高さになり、盤が正方形を保とうとして横にも太る。 */
  .board-column { padding-top: 1.3rem; flex-direction: row; align-items: stretch; gap: .7rem;
                  align-self: start; }
  .board-column > .sg-wrap { flex: 1 1 auto; min-width: 0; }
  .eval-gauge { flex: 0 0 8px; width: 8px; height: auto; margin: 0; }
  .eval-gauge-fill { width: 100%; height: calc(var(--eval-p, .5) * 100%); }
  /* 盤は幅だけでなく画面の高さでも頭を押さえる。lishogiも同じことをしている
     （$col3-uniboard-main-max-height が 100vh から引いている）。
     これが無いと 1366x768 のような横長の画面で盤の下端が画面外に出て、
     指すたびにスクロールすることになる（ページ高1036px / 画面768pxだった）。
     .sg-wrap の高さは盤の高さと同じで、幅の 9/11（左右の駒台ぶん）。
     8rem は上のバーと上下の余白の実測。 */
  .board-column > .sg-wrap { max-width: calc((100vh - 8rem) * 11 / 9); }
}
/* 盤の大きさ。画面の広さで決まる幅に倍率を掛ける。lishogiにも同じ調整がある。
   広いとき: .app の横幅ごと伸縮させる（盤と右のパネルが一緒に動く）。
     .sg-wrap の幅を直接いじると、列より広くしたぶんがはみ出す。
   狭いとき: 盤は既に横幅いっぱいなので、縮める方向にだけ効かせる。
     100%を超えさせるとページ全体に横スクロールが出る（430px幅で実際に出た）。 */
@media (max-width: 55.999rem) {
  .board-column > .sg-wrap { width: min(var(--board-scale, 100%), 100%); margin: 0 auto; }

  /* 盤を画面幅いっぱいに。.app の左右paddingをちょうど打ち消す。 */
  .board-column { margin-inline: -1.25rem; }

  /* 相手の席を盤の上へ、自分の席を盤の直下へ。lishogiは相手＝上、自分＝下で固定。
     自分の席を棋譜の後ろに置くと、秒読み中に自分の時計が画面の外に出る（実際に出ていた）。
     縦積みだと .panel が .board-column の後ろに来るので、#seat-top が盤の下に落ちる。
     DOMを付け替えず、.panel を透明にして .layout の直接の子として並べ替える。
     .panel 自身の gap は display:contents で消えるので、.layout の gap がその役をする。

     セレクタを .layout > .panel にしているのは詳細度のため。 */
  .layout > .panel { display: contents; }
  .layout { gap: var(--sp-7); }
  /* 指で押す寸法。44px を下回っていた（棋譜ナビ30px・操作32px・棋譜の行22px）。広い画面は変えない。 */
  .kifu-nav button { padding: .65rem 0; }
  .actions button { padding: .7rem var(--sp-5); }
  .kifu li, .variation li { padding: .35rem var(--sp-3); }
  .candidates li { padding: var(--sp-4) var(--sp-5); }

  #seat-top       { order: 1; }
  .board-column   { order: 2; }
  #seat-bottom    { order: 3; }
  .stepper        { order: 4; }
  .status         { order: 5; }
  .actions        { order: 6; }
  .kifu-box       { order: 7; }
  .eval-chart     { order: 8; }
  .engine         { order: 9; }
}

/* 盤と駒台の配置。lishogi と同じで、狭いときは盤の上下、広いときは盤の左右に
   駒台を置く（ui/common/css/component/_board.scss）。
   .sg-wrap の直下が sg-hand-wrap / sg-board / sg-hand-wrap の順に並ぶのは
   shogiground の hands.inlined が作る構造。
   行・列を auto と fr で割ってあるので高さの計算は要らない。盤は
   aspect-ratio で自分の幅から高さを決め、駒台の1コマは常にマス1つ分になる。 */
.sg-wrap {
  position: relative;
  display: grid;
  width: 100%;
  gap: var(--sp-6);
  grid-template-areas: 'sg-hand-top' 'sg-board' 'sg-hand-bottom';
}
sg-board { grid-area: sg-board; }
sg-hand-wrap.hand-top { grid-area: sg-hand-top; }
sg-hand-wrap.hand-bottom { grid-area: sg-hand-bottom; justify-self: end; }

@media (min-width: 56rem) {
  .sg-wrap {
    /* 9マスの盤に対して駒台を左右1マスずつ。列がマス1つ分になるので、
       駒台の駒と盤の駒が同じ大きさになる。 */
    grid-template-columns: 1fr 9fr 1fr;
    grid-template-areas: 'sg-hand-top sg-board sg-hand-bottom';
    gap: 2vmin;
  }
  /* 駒台は盤の端に揃える。後手は上、先手は下。
     align-self を指定しないと stretch で列いっぱいに伸び、
     column-reverse が中身を下へ寄せるので後手の駒台だけ1コマ下がる。 */
  sg-hand-wrap.hand-top { align-self: start; }
  sg-hand-wrap.hand-bottom { align-self: end; }
}

sg-board {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 1;
  /* 木目。lishogi の既定盤 wood.png は「縦方向に完全一様で、横方向にだけ
     約200本の帯が入った画像」なので、周期の違う縞を重ねれば同じものが出る。
     実測（明度 mean 189.0 / sd 2.84 / コントラスト幅 6.8%）に合わせてある。
     画像を持たないのは、lishogi の盤画像が AGPLv3+ でこのリポジトリの
     GPL-3.0-only と混ざるため（THIRD_PARTY.md）。 */
  background-color: var(--board);
  background-image:
    repeating-linear-gradient(90deg, #00000007 0 1px, #0000 1px 4px),
    repeating-linear-gradient(90deg, #ffffff09 0 1px, #0000 1px 7px),
    repeating-linear-gradient(90deg, #00000004 0 2px, #0000 2px 11px),
    repeating-linear-gradient(90deg, #ffffff06 0 3px, #0000 3px 17px),
    repeating-linear-gradient(90deg, #00000004 0 1px, #0000 1px 23px);
  border: 2px solid var(--board-edge);
  border-radius: 2px;
  box-shadow: 0 1px 0 #0002, 0 8px 24px #0000001f;
  font-size: clamp(9px, 2.2vw, 15px);   /* 盤内の文字はここを基準に決まる */
}
/* 41手目からは盤の縁の色を変える。文を読まなくても、ルールが変わったことが見える。
   色は幕（.toast）と一緒に0.4秒で変わる。 */
sg-board { transition: border-color .4s ease; }
@media (prefers-reduced-motion: reduce) { sg-board { transition: none; } }
.sg-wrap.phase-normal sg-board { border-color: var(--ink); }

sg-squares {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-template-rows: repeat(9, 1fr);
}

/* 罫線は lishogi と同じく上と左を sg-squares、下と右を各マスが持つ。 */
sg-squares { border-top: 1px solid var(--line); border-left: 1px solid var(--line); }

sq {
  position: relative;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

/* 星。3四・6四・3七・6七の交点に置く。マス目の左上角が交点なので、
   点の直径の半分だけ負のマージンで引き戻す。 */
sq:nth-child(31)::after,
sq:nth-child(34)::after,
sq:nth-child(58)::after,
sq:nth-child(61)::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 10%;
  height: 10%;
  margin: -5%;
  background: var(--line);
  border-radius: 50%;
}

/* 布石フェーズは手番側の陣（自陣四段）を淡く塗る。置ける範囲が駒を掴む前から見え、
   41手目で塗りが消えるので「ルールが変わった」が幕と二重に見える。
   :where() で特異度を sq と同じに落とし、下の last-dest / selected / dest の塗りに負けるようにする。
   マスの並びは表示上の位置（sg-squares の子の順、左上から）。手前の4段は 46 番目から。 */
:where(.sg-wrap.zone-bottom) sq:where(:nth-child(n+46)),
:where(.sg-wrap.zone-top) sq:where(:nth-child(-n+36)) { background-color: rgba(70, 35, 0, .085); }

sq.last-dest { background-color: var(--last-dest); }
sq.check { background-color: var(--check); }
sq.selected { background-color: var(--selected); }

/* 着手可能なマスの印。空きマスは点、駒がいるマス(.oc)は輪。
   どちらも選択マスと同じ色で描く（lishogi の _shogiground.scss と同じ）。 */
sq.dest { background: radial-gradient(var(--selected) 19%, rgba(0, 0, 0, 0) 20%); }
sq.dest.oc { background: radial-gradient(transparent 0%, transparent 80%, var(--selected) 80%); }
/* 掴んだ駒が乗っているマス。lishogi と同じで、色を変えるのは着手できるマスだけ。
   どのマスでも白く光らせると、置けないマスまで反応しているように見える。
   駒が今どこにあるかは sg-square-over の黒い丸が示す。 */
sq.dest.hover { background: var(--selected-hover); }
sq.last-dest.dest.oc:not(.hover) {
  background: radial-gradient(var(--last-dest) 0%, var(--last-dest) 80%, var(--selected) 80%);
}

sg-pieces { position: absolute; inset: 0; display: block; }
/* 矢印と印の層（検討の候補手）。盤の高さを壊さないよう位置を固定し、**クリックを通す**。
   通さないと、駒台の駒を選んだ後の盤のマスへのクリックがこの層に取られて打てなくなる
   （実際に起きた。駒の選択は駒台側なので効き、置く側だけが黙って落ちる）。 */
sg-board > .sg-shapes,
sg-board > .sg-custom-svgs,
sg-board > sg-free-pieces { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

/* 成りの選択ダイアログ。着手先のマスの上に2択（成/不成）を積む。
   ここも絶対配置にしないと、開いた瞬間に盤の高さが崩れる。 */
/* 開いている間は盤を暗く落とす。lishogi と同じで、どのマスの話かを見失わせない。 */
sg-board > sg-promotion { position: absolute; inset: 0; z-index: 4; background-color: #0000003f; }
sg-promotion-square {
  position: absolute;
  top: 0;
  left: 0;
  width: calc(100% / 9);
  height: calc(100% / 9);
}
sg-promotion-choices {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
  padding: 2px;
  background: var(--paper-raised);
  border-radius: 3px;
  box-shadow: 0 3px 12px #00000059;
}
sg-promotion-choices.reversed { top: auto; bottom: 0; flex-direction: column-reverse; }
sg-promotion-choices piece { position: relative; width: 100%; aspect-ratio: 1; }

/* 掴んだ駒が今どのマスの上にいるか。lishogi は黒い円で、駒の下から覗く。 */
sg-square-over {
  position: absolute;
  top: 0; left: 0;
  box-sizing: content-box;
  width: calc(100% / 9);
  height: calc(100% / 9);
  padding: 6%;
  margin: -6%;
  background: #00000050;
  border-radius: 50%;
  pointer-events: none;
}

/* ---- 駒 ---- */

/* 駒は画像。lishogiの kanji_light（Ka-hu / CC BY 4.0）をそのまま使う。
   駒の五角形も朱字もSVGの中に入っているので、CSS側では形を描かない。
   後手の駒は 1*.svg という**別のファイル**で、既に180度回った状態で入っている。
   ここでCSSのrotateを使ってはいけない。shogiground は駒の位置を transform の
   translate で与えており、CSSの合成順は translate -> rotate なので、駒を回すと
   後から掛かる translate が回転後の座標系で効いて駒が盤の外へ飛ぶ。 */
piece {
  display: block;
  cursor: pointer;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  user-select: none;
  filter: drop-shadow(0 1px 1px #00000024);
}

/* 駒の絵は色ごとに向きが焼き込んである（1*.svg が180度回した側）。
   盤を後手向きにしたら、手前＝自分の駒が上を向いていないと自分の駒に見えない。
   後手向きのときは色と絵の対応を入れ替える。回転（transform）は使えない。
   盤上の駒の位置は shogiground が inline の transform: translate() で書いていて、
   CSSのtransformは負けるし、rotateプロパティを足すと平行移動まで回って位置がずれる。
   .orientation-gote は .sg-wrap と sg-hand-wrap の両方に付くので、
   盤・駒台・掴んでいる駒・成りの選択肢が1つの前置きで揃う。
   影（drop-shadow）は下向きのまま。光の向きは盤を回しても変わらない。 */
piece.sente.pawn, .orientation-gote piece.gote.pawn { background-image: url("pieces/0FU.svg"); }
piece.gote.pawn, .orientation-gote piece.sente.pawn { background-image: url("pieces/1FU.svg"); }
piece.sente.lance, .orientation-gote piece.gote.lance { background-image: url("pieces/0KY.svg"); }
piece.gote.lance, .orientation-gote piece.sente.lance { background-image: url("pieces/1KY.svg"); }
piece.sente.knight, .orientation-gote piece.gote.knight { background-image: url("pieces/0KE.svg"); }
piece.gote.knight, .orientation-gote piece.sente.knight { background-image: url("pieces/1KE.svg"); }
piece.sente.silver, .orientation-gote piece.gote.silver { background-image: url("pieces/0GI.svg"); }
piece.gote.silver, .orientation-gote piece.sente.silver { background-image: url("pieces/1GI.svg"); }
piece.sente.gold, .orientation-gote piece.gote.gold { background-image: url("pieces/0KI.svg"); }
piece.gote.gold, .orientation-gote piece.sente.gold { background-image: url("pieces/1KI.svg"); }
piece.sente.bishop, .orientation-gote piece.gote.bishop { background-image: url("pieces/0KA.svg"); }
piece.gote.bishop, .orientation-gote piece.sente.bishop { background-image: url("pieces/1KA.svg"); }
piece.sente.rook, .orientation-gote piece.gote.rook { background-image: url("pieces/0HI.svg"); }
piece.gote.rook, .orientation-gote piece.sente.rook { background-image: url("pieces/1HI.svg"); }
piece.sente.tokin, .orientation-gote piece.gote.tokin { background-image: url("pieces/0TO.svg"); }
piece.gote.tokin, .orientation-gote piece.sente.tokin { background-image: url("pieces/1TO.svg"); }
piece.sente.promotedlance, .orientation-gote piece.gote.promotedlance { background-image: url("pieces/0NY.svg"); }
piece.gote.promotedlance, .orientation-gote piece.sente.promotedlance { background-image: url("pieces/1NY.svg"); }
piece.sente.promotedknight, .orientation-gote piece.gote.promotedknight { background-image: url("pieces/0NK.svg"); }
piece.gote.promotedknight, .orientation-gote piece.sente.promotedknight { background-image: url("pieces/1NK.svg"); }
piece.sente.promotedsilver, .orientation-gote piece.gote.promotedsilver { background-image: url("pieces/0NG.svg"); }
piece.gote.promotedsilver, .orientation-gote piece.sente.promotedsilver { background-image: url("pieces/1NG.svg"); }
piece.sente.horse, .orientation-gote piece.gote.horse { background-image: url("pieces/0UM.svg"); }
piece.gote.horse, .orientation-gote piece.sente.horse { background-image: url("pieces/1UM.svg"); }
piece.sente.dragon, .orientation-gote piece.gote.dragon { background-image: url("pieces/0RY.svg"); }
piece.gote.dragon, .orientation-gote piece.sente.dragon { background-image: url("pieces/1RY.svg"); }
/* 玉と王だけは向きのほかに文字が違う（先手が玉将・後手が王将）。色の約束なので
   盤を回しても入れ替えない。上下だけ替えた絵が両方あるのでそれを使う
   （0OU=上向きの王 / 1GY=逆さの玉）。 */
piece.sente.king { background-image: url("pieces/0GY.svg"); }
piece.gote.king { background-image: url("pieces/1OU.svg"); }
.orientation-gote piece.gote.king { background-image: url("pieces/0OU.svg"); }
.orientation-gote piece.sente.king { background-image: url("pieces/1GY.svg"); }

sg-pieces piece,
sg-board > piece {
  position: absolute;
  top: 0;
  left: 0;
  width: calc(100% / 9);
  height: calc(100% / 9);
  will-change: transform;
}
sg-pieces piece.anim { transition: transform .25s; }
sg-pieces piece.fading { opacity: .5; transition: opacity .25s; }
/* 動きを減らす設定では駒を滑らせない。着手の結果は残るので情報は落ちない。 */
@media (prefers-reduced-motion: reduce) {
  sg-pieces piece.anim,
  sg-pieces piece.fading { transition: none; }
}
piece.ghost { opacity: .3; }
sg-board > piece.dragging { cursor: grabbing; z-index: 3; filter: drop-shadow(0 4px 6px #0006); }
/* 指で掴んだときは駒を指の上へ逃がす。これが無いと駒が指の下に隠れて、
   どこへ置こうとしているのかが見えない。shogiground が .touch を付けてくれる
   （node_modules/shogiground/src/drag.ts）。 */
sg-board > piece.dragging.touch { top: -50px; }

/* ---- 座標 ---- */

/* 座標。lishogi の既定は Coords.OUTSIDE（modules/pref/src/main/Pref.scala）で、
   広い画面では盤の外に出す。内側に置くのは狭い画面のときだけ。 */
sg-board > coords {
  position: absolute;
  display: flex;
  z-index: 1;
  font-size: clamp(8px, 1.5vw, 11px);
  font-weight: 700;
  line-height: 1;
  pointer-events: none;
  user-select: none;
}
coords.files { left: 0; width: 100%; flex-direction: row; }
coords.files.gote { flex-direction: row-reverse; }
coords.ranks { top: 0; height: 100%; flex-direction: column-reverse; }
coords.ranks.gote { flex-direction: column; }
coords.files coord { flex: 1; text-align: center; }
coords.ranks coord { flex: 1; display: flex; align-items: center; justify-content: center; }

/* 狭いとき: 盤の外に出す余地が無いので内側。
   白抜きにすると盤（#f9b34e）に対して1.81:1、駒地に対して1.18:1しかなく
   ほとんど読めない。濃い色に明るい縁を付けると、盤で7.6:1、駒地で11.7:1になる。 */
sg-board > coords { color: #3a2a12; text-shadow: 0 0 2px #f7ecc9, 0 0 3px #f7ecc9; }
coords.files { top: .15em; height: 1.4em; }
coords.ranks { right: .15em; width: 1.1em; }

/* 広いとき: 盤の外。駒に重ならないので影は要らず、本文と同じ色でよい。 */
@media (min-width: 56rem) {
  sg-board > coords { color: var(--ink-soft); text-shadow: none; }
  coords.files { top: -1.5em; height: 1.2em; }
  coords.ranks { right: -1.7em; width: 1.1em; }
}

/* ---- 持ち駒 ---- */

/* 布石は玉を含めて8種。shogiground が駒種の数だけ r-8 のようなクラスを付けるので
   （wrap.ts の roleCntCls）、そこに寸法を掛ける。lishogi が定義しているのは
   r-5/r-4/r-3/r-0 だけなので、8種ぶんはこちらで書く。 */
sg-hand-wrap {
  display: block;
  font-size: clamp(9px, 2.2vw, 15px);   /* 個数バッジの基準。盤と揃える */
}
sg-hand-wrap.r-8 { width: calc(100% / 9 * 8); }

sg-hand {
  display: flex;
  flex-direction: row;
  width: 100%;
  height: 100%;
}
/* 後手側は並びを鏡にする。駒が180度回っているので、これで後手から見た並びが
   先手と同じになる（盤の左右に立てたときの column-reverse と同じ理屈）。 */
sg-hand-wrap.hand-top sg-hand { flex-direction: row-reverse; }

/* flex-grow を効かせてはいけない。駒台を縦に立てたときに8個で高さを割りにいって、
   aspect-ratio が潰れて駒が縦長になる。大きさはマス1つ分に固定する。 */
sg-hp-wrap {
  position: relative;
  flex: 0 0 12.5%;    /* 8種で駒台の幅ちょうど */
  aspect-ratio: 1;
}
sg-hand piece { position: absolute; inset: 0; width: 100%; height: 100%; }

/* 広いときは盤の左右に立てる。列がマス1つ分の幅なので、駒はそのまま盤と同じ大きさ。 */
@media (min-width: 56rem) {
  sg-hand-wrap.r-8 { width: 100%; }
  sg-hand { flex-direction: column; }
  sg-hp-wrap { flex: 0 0 auto; width: 100%; }
  /* 後手の駒台は上下を返す。駒自体が180度回っているので、これで
     後手から見た並びが先手と同じ（玉が手前、歩が奥）になる。 */
  sg-hand-wrap.hand-top sg-hand { flex-direction: column-reverse; }
}

sg-hp-wrap::after {
  content: attr(data-nb);
  position: absolute;
  right: 0;
  bottom: 0;
  min-width: 1.15em;
  padding: 0 .15em;
  background: var(--paper-raised);
  color: var(--ink);
  border: 1px solid var(--ink-soft);
  border-radius: .3em;
  font-size: .8em;
  font-weight: 700;
  line-height: 1.3;
  text-align: center;
  z-index: 2;
}
/* 後手側はバッジを上に出す。駒が180度回っているので、下だと隣の駒に被る。 */
sg-hand-wrap.hand-top sg-hp-wrap::after { bottom: auto; top: 0; }
/* 持っていない駒はほぼ消す。lishogi は .1 まで落とす。 */
sg-hp-wrap[data-nb="0"] { opacity: .1; }
sg-hp-wrap[data-nb="0"]::after,
sg-hp-wrap[data-nb="1"]::after { display: none; }
/* 選んだ駒は盤のマスと同じ色で背面を塗る。盤上の selected と揃うので、
   「今この駒を持っている」が駒台と盤で同じ意味に見える。 */
sg-hp-wrap.selected {
  opacity: 1;
  background-color: var(--selected);
  border-radius: 3px;
}
sg-hp-wrap.last-dest { background-color: var(--last-dest); border-radius: 3px; }

/* 天秤将棋で置く人の番は、駒台の玉だけが押せる。ほかの駒は薄くして「今はこれ」を示す。
   2手目に押す後手玉は向こうの駒台（広い画面では左の列の手前寄り）にあり、王は回しても同じ形なので、
   輪郭も付けて「この駒」と言う。 */
.sg-wrap.kings-only sg-hp-wrap:not(:has(piece.king)) { opacity: .25; }
.sg-wrap.kings-only sg-hp-wrap:has(piece.king):not([data-nb="0"]) { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 4px; }

/* ---- 先後を選ぶ：両玉の札と輪 ---- */

/* 盤の中には置かない（shogiground の持ち物）。.board-column に重ねて、main.js が
   盤の矩形を測って位置を書く。 */
.king-tags { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.king-ring {
  position: absolute;
  border: 3px solid var(--accent);
  border-radius: 50%;
  box-shadow: 0 0 0 3px #ffffffaa, 0 0 0 6px color-mix(in srgb, var(--accent) 35%, transparent);
  opacity: .55;
}
.king-ring.pending { opacity: 1; animation: ring-pulse 1.1s ease-in-out infinite alternate; }
.king-ring.dim { opacity: .3; border-style: dashed; box-shadow: none; }
@keyframes ring-pulse {
  from { transform: scale(1); }
  to { transform: scale(1.08); }
}
@media (prefers-reduced-motion: reduce) { .king-ring.pending { animation: none; } }
.king-label {
  position: absolute;
  transform: translate(-50%, 0);
  padding: 0 .4em;
  background: var(--paper-raised);
  color: var(--ink);
  border: 1px solid var(--ink-soft);
  border-radius: 3px;
  font-size: clamp(9px, 1.4vw, 12px);
  font-weight: 700;
  line-height: 1.5;
  white-space: nowrap;
}
.king-label.pending { background: var(--accent); color: var(--paper-raised); border-color: var(--accent); }
.king-label.placed { border-color: var(--rule); font-weight: 600; opacity: .95; }
/* 置く陣の札。陣の境目の線に掛けて、手前の陣なら線の下（陣の中）、向こうの陣なら線の上。
   記号は紙地の上だけに置く決まりなので、地は紙。 */
.zone-hint {
  position: absolute;
  transform: translate(-50%, 0);
  padding: .15em .7em;
  background: var(--paper-raised);
  color: var(--ink);
  border: 1.5px solid var(--accent);
  border-radius: 999px;
  font-size: clamp(10px, 1.5vw, 13px);
  font-weight: 700;
  line-height: 1.5;
  white-space: nowrap;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
}
.zone-hint.bottom { transform: translate(-50%, 2px); }
.zone-hint.top { transform: translate(-50%, calc(-100% - 2px)); }
/* 選べる玉の上ではカーソルを手にする。shogiground は触れない駒でも pointer にするので、
   逆に「触れない」ことを示すために、選ぶ最中は玉以外を既定に戻す。 */
.sg-wrap.choosing piece { cursor: default; }
.sg-wrap.choosing piece.king { cursor: pointer; }

/* 段の境目の幕。盤の中央に浮いて1.6秒で消える（先後が決まった・41手目）。
   強い動きはここと終局の帯にだけ使い、ほかは静かなままにしておく。 */
.toast {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 6;
  transform: translate(-50%, -50%);
  display: grid;
  gap: var(--sp-1);
  justify-items: center;
  text-align: center;
  max-width: calc(100% - 2rem);
  padding: .75rem 1.5rem var(--sp-7);
  background: color-mix(in srgb, var(--ink) 94%, transparent);
  color: var(--paper);
  border-radius: 6px;
  box-shadow: 0 12px 32px -12px #000c;
  pointer-events: none;
  /* 秒数と曲線は sonner（emilkowalski/sonner の src/styles.css）に合わせた。
     入り400ms・出200msで、動かすのは transform と opacity だけ。 */
  animation: toast-in .4s ease;
}
.toast b { font-family: var(--serif); font-size: clamp(1.1rem, 3vw, 1.6rem); font-weight: 700; letter-spacing: .08em; line-height: 1.3; }
.toast span { font-size: .8rem; opacity: .85; }
.toast span:empty { display: none; }
.toast.leaving { opacity: 0; transition: opacity .2s ease; }
@keyframes toast-in {
  from { opacity: 0; transform: translate(-50%, -50%) scale(.96); }
}
/* 終局の帯。盤の上に結果と行き先。数秒で消える。パネルの結果枠と4つのボタンは残る。 */
.result-banner {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 7;
  transform: translate(-50%, -50%);
  width: min(22rem, calc(100% - 2rem));
  padding: .9rem 1.1rem var(--sp-8);
  background: var(--paper-raised);
  color: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 6px;
  box-shadow: 0 16px 40px -14px #000c;
  text-align: center;
  animation: toast-in .4s ease;
}
.rb-line { margin: 0; font-family: var(--serif); font-size: 1.35rem; font-weight: 700; letter-spacing: .04em; line-height: 1.3; }
.rb-sub { margin: .15rem 0 0; font-size: .82rem; color: var(--ink-soft); }
.rb-sub:empty { display: none; }
.rb-actions { display: flex; gap: var(--sp-5); margin-top: var(--sp-7); }
.rb-actions button {
  flex: 1 1 0;
  padding: .55rem var(--sp-6);
  background: var(--paper-raised);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 4px;
  font: inherit;
  font-size: .875rem;
  font-weight: 600;
  cursor: pointer;
}
.rb-actions button:hover { border-color: var(--ink-soft); }
.rb-actions button.primary { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.result-banner.leaving { opacity: 0; transition: opacity .2s ease; pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
  .toast, .result-banner { animation: none; }
  .toast.leaving, .result-banner.leaving { transition: none; }
}

/* Cookieの同意の帯。下に出す（割り込まない・盤を隠さない）。
   出すかどうかは consent.js が決めるので、ここは見た目だけ。 */
.consent {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 30;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-5) var(--sp-8);
  padding: var(--sp-7) var(--sp-8);
  padding-bottom: calc(var(--sp-7) + env(safe-area-inset-bottom));
  background: var(--paper-raised);
  color: var(--ink);
  border-top: 1px solid var(--rule);
  box-shadow: 0 -12px 32px -20px #000c;
  font-size: .8125rem;
  animation: consent-in .2s ease;
}
@keyframes consent-in { from { transform: translateY(100%); } }
.consent-text { margin: 0; max-width: 46rem; line-height: 1.6; }
.consent-actions { display: flex; gap: var(--sp-5); flex: 0 0 auto; }
/* 断るほうも同じ大きさ・同じ見え方。片方だけ目立たせない。 */
.consent-actions button {
  padding: var(--sp-4) var(--sp-8);
  min-width: 7rem;
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 4px;
  font: inherit;
  font-size: .8125rem;
  font-weight: 600;
  cursor: pointer;
}
.consent-actions button:hover { background: color-mix(in srgb, var(--rule) 40%, transparent); }
.consent-actions button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .consent { animation: none; } }
/* 帯が出ているあいだは、その分だけ下を空ける（フッターのライセンス表記が隠れる）。 */
body:has(.consent:not([hidden])) .app { padding-bottom: 10rem; }

/* ---- 右のパネル ---- */

.panel { display: flex; flex-direction: column; gap: .55rem; }

/* 席（対局者と時計）。lishogiは盤の向こう側と手前を棋譜で挟む。 */
.seat {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  padding: .35rem var(--sp-6);
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 4px;
  font-size: .8125rem;
  min-width: 0;
}
.seat-name {
  display: flex; align-items: center; gap: var(--sp-4); color: var(--ink-soft);
  min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 手番の側に印を出す。文字だけだとどちらの番か一目で分からない。 */
.seat-name::before {
  content: "";
  flex: 0 0 auto;
  width: .5rem;
  height: .5rem;
  border-radius: 50%;
  background: var(--rule);
}
/* 役の札（玉分け将棋）。名前の隣に付け、時計は右端のまま。 */
.seat-role {
  flex: 0 0 auto;
  margin-right: auto;
  padding: .05rem var(--sp-4);
  border: 1px solid var(--rule);
  border-radius: 999px;
  font-size: .68rem;
  line-height: 1.4;
  color: var(--ink-soft);
  white-space: nowrap;
}
.seat.turn { border-color: var(--accent); }
/* AIが考えている間。通常フェーズは1手に数秒かかるので、
   何も動かないと固まったように見える。手番の丸印を脈打たせる。 */
.seat.thinking .seat-name::before { animation: seat-pulse 1s ease-in-out infinite alternate; }
@keyframes seat-pulse {
  from { opacity: 1; transform: scale(1); }
  to { opacity: .25; transform: scale(.7); }
}
@media (prefers-reduced-motion: reduce) {
  .seat.thinking .seat-name::before { animation: none; }
}
.seat.turn .seat-name { color: var(--ink); font-weight: 600; }
.seat.turn .seat-name::before { background: var(--accent); }
.clock {
  min-width: 4.2em;
  text-align: center;
  padding: var(--sp-1) .45rem;
  border-radius: 3px;
  background: color-mix(in srgb, var(--rule) 40%, transparent);
  font-variant-numeric: tabular-nums;
  font-size: .9375rem;
  font-weight: 600;
  letter-spacing: .02em;
  white-space: nowrap;
}
.seat.turn .clock { background: var(--accent); color: var(--paper-raised); }
/* AI側には持ち時間が無いので clockText が空を返す。枠だけ残さない。 */
.clock:empty { display: none; }
/* 残り30秒を切ったか、秒読みに入ったか。 */
.clock.low { color: var(--accent); font-weight: 700; }

/* フェーズ帯。終わった段は薄く、今の段は縁を強く、これからの段は破線。 */
.stepper {
  display: flex;
  gap: 3px;
  margin: 0;
  padding: 0;
  list-style: none;
  min-width: 0;
}
.step {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  display: grid;
  align-content: start;
  gap: 0;
  padding: var(--sp-3) var(--sp-3);
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 4px;
  font-size: .7rem;
  line-height: 1.35;
  cursor: help;
}
:lang(en) .step { font-size: .66rem; padding-inline: .25rem; }
/* 2段のときだけ布石の段を広く取る。4段では幅が足りず、段の名前が折れる。 */
.step.wide { flex: 1.6 1 0; }
.stepper.four .step.wide { flex: 1 1 0; }
.step .t { font-weight: 700; overflow-wrap: anywhere; }
/* 4段のときは1段が4remほどしか無い。段名は折らず（「先後を選／ぶ」になった）、済みの段の
   副題は省く。英語は語の切れ目で折ってよい（Choose side が2行になるのは読める）。 */
.stepper.four .step { font-size: .66rem; padding-inline: .25rem; }
.stepper.four .step .t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
:lang(en) .stepper.four .step .t { white-space: normal; overflow-wrap: normal; }
.step .s { color: var(--ink-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.step .s:empty { display: none; }
.step.done { background: color-mix(in srgb, var(--rule) 45%, transparent); color: var(--ink-soft); }
/* 済みの印は段名の前に置かない（幅を食って段名が折れる）。右上の角に小さく。 */
.step.done::after { content: "✓"; position: absolute; top: .1rem; right: .2rem; color: var(--ok); font-size: .6rem; line-height: 1; }
.step.done .t { padding-right: .55rem; }
.step.now { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.step.now .t { color: var(--accent); }
.step.next { border-style: dashed; color: var(--ink-soft); }
.step .bar { height: 3px; margin-top: .25rem; background: var(--rule); border-radius: 2px; overflow: hidden; }
.step .bar i { display: block; height: 100%; width: var(--p, 0%); background: var(--accent); transition: width .25s ease; }

.status {
  padding: var(--sp-6) var(--sp-7);
  min-height: 4.6rem;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
}
.status-line {
  margin: 0; font-weight: 600; font-size: .9rem; line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.status-sub {
  margin: .15rem 0 0; color: var(--ink-soft); font-size: .78rem; line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.status-sub:empty { display: none; }
/* 玉を置く・先後を選ぶあいだは説明が長い。行数の上限を緩め、下に天秤の図を出す。 */
.status.scale .status-sub { -webkit-line-clamp: 4; }
/* 天秤の図。前の版は梁が細い線・支柱が縦線・皿が枠だけで、天秤に見えるまで時間が
   かかった（実際にそう言われた）。天秤だと形で分かるのは次の4つなので、全部描く。
     ・三角の台に梁が載っている（傾く道具だと分かる）
     ・支点の軸受け
     ・皿が鎖で梁から吊り下がっている（V字の2本）
     ・皿の上に錘が載っている
   錘は塗り＝先手・白抜き＝後手で、盤の印（☗☖）と同じ約束にしてある。 */
.scale-fig { display: block; width: 100%; max-width: 18rem; height: auto; margin: var(--sp-4) auto 0; }
.scale-fig[hidden] { display: none; }
.scale-fig path { fill: none; stroke: var(--ink-soft); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.scale-fig .stand { fill: var(--ink-soft); stroke: none; }
.scale-fig .beam { stroke: var(--ink); stroke-width: 2.5; }
.scale-fig .pivot { fill: var(--ink); stroke: none; }
.scale-fig .chain { stroke: var(--ink-soft); stroke-width: 1.1; }
.scale-fig .pan { fill: var(--paper-raised); stroke: var(--ink); stroke-width: 1.4; }
.scale-fig .weight { stroke: var(--ink); stroke-width: 1.2; }
.scale-fig .weight.solid { fill: var(--ink); }
.scale-fig .weight.hollow { fill: var(--paper-raised); }
.scale-fig text { fill: var(--ink-soft); font-family: var(--sans); font-size: 10.5px; text-anchor: middle; }
.scale-fig text.h { fill: var(--ink); font-size: 12.5px; font-weight: 700; }

/* 操作枠。三つの中身のうち、パネルの data-state に合うものだけを出す。 */
.actions > div { display: none; }
.panel[data-state="play"] .actions-play,
.panel[data-state="idle"] .actions-play { display: flex; gap: var(--sp-4); flex-wrap: wrap; }
/* オンラインでは投了・待った・引き分け・反転の4つ。2つずつ2行に折り返す
   （折り返せる行の最小幅は最長のボタン1つぶんで、パネルが横に伸びない）。 */
.actions .actions-play button { flex: 1 1 5.5rem; }
.panel.online .actions .actions-play button { flex-basis: 7.5rem; }
/* 相手からの申し出。操作枠の中で、ボタンの行の下に1行。 */
.panel[data-state="play"] .offer-row:not([hidden]) { display: flex; gap: var(--sp-4); align-items: center; margin-top: var(--sp-4); flex-wrap: wrap; }
.offer-row .offer-text { flex: 1 1 100%; font-size: .78rem; color: var(--ink); line-height: 1.4; }
.offer-row button { flex: 1 1 0; }
.panel[data-state="choose"] .actions-choose { display: grid; gap: var(--sp-4); }
.panel[data-state="over"] .actions-over { display: grid; gap: var(--sp-4); }
.panel[data-state="analyze"] .actions-analyze { display: grid; gap: var(--sp-4); }
/* オンラインで相手を待つあいだ。招待リンクとコピー・共有。 */
.panel[data-state="wait"] .actions-wait { display: grid; gap: var(--sp-4); }
.wait-link-label { display: flex; flex-direction: column; gap: var(--sp-2); font-size: .72rem; color: var(--ink-soft); }
.wait-link-label input {
  width: 100%; min-width: 0; padding: var(--sp-4) var(--sp-5);
  background: var(--paper); color: var(--ink);
  border: 1px solid var(--rule); border-radius: 4px;
  font: inherit; font-size: .78rem;
}
.join-eyebrow { margin: 0 0 var(--sp-2); font-size: .72rem; letter-spacing: .08em; color: var(--ink-soft); }
.moves-io-actions button.primary { background: var(--ink); color: var(--paper); border-color: var(--ink); font-weight: 600; }
.moves-io-actions button.primary:hover { color: var(--paper); border-color: var(--ink); }
.moves-io-actions button:disabled { opacity: .45; cursor: not-allowed; }
.analyze-row { display: flex; gap: var(--sp-4); }
.actions button {
  flex: 1 1 0;
  min-width: 0;
  padding: var(--sp-4) var(--sp-5);
  background: var(--paper-raised);
  color: var(--ink-soft);
  border: 1px solid var(--rule);
  border-radius: 4px;
  font: inherit;
  font-size: .8125rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
}
.actions button:hover:not(:disabled) { color: var(--ink); border-color: var(--ink-soft); }
.actions button:disabled { opacity: .4; cursor: not-allowed; }
.actions button.primary { background: var(--ink); color: var(--paper); border-color: var(--ink); font-weight: 600; }
.actions button.primary:hover:not(:disabled) { color: var(--paper); border-color: var(--ink); }
/* 投了の確認待ち。押すと戻せないので、見た目で1回止める。 */
.actions button.armed {
  background: var(--accent);
  color: var(--paper-raised);
  border-color: var(--accent);
  font-weight: 600;
}
/* 先後の2択。同じ大きさで並べ、押した（仮）ほうだけ縁を立てる。 */
.choice-row { display: flex; gap: var(--sp-4); }
.choice-row button.selected { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); color: var(--ink); }
/* 終局後の行き先。4つを2×2にし、5つ目（本将棋以降のKIF）は1行を使う。 */
.result-actions { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-4); }
.result-actions > #btn-copy-kif41 { grid-column: 1 / -1; }
.result-actions > button:disabled { opacity: .45; cursor: not-allowed; }
.result-note { margin: 0; font-size: .72rem; color: var(--ink-soft); line-height: 1.4; }
.result-note:empty { display: none; }

/* 過去の局面を見ている間は盤の縁を変えて、対局中の局面でないことを示す。 */
.sg-wrap.reviewing sg-board { border-color: var(--accent); }

/* 評価グラフ。lishogi の解析画面と同じ「先手が良いと上、面で塗る」形。
   縦軸は先手の勝率で、ゲージと同じ換算（main.js の winRateOf）。 */
.eval-chart {
  height: 4.5rem;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 4px;
  overflow: hidden;
  cursor: pointer;
  touch-action: none;   /* なぞってその手へ。縦スクロールに取られない */
}
.eval-chart svg { display: block; width: 100%; height: 100%; }
.eval-chart .grid { stroke: var(--rule); stroke-width: 1; }
.eval-chart .mid { stroke: var(--ink-soft); stroke-width: 1; opacity: .6; }
.eval-chart .divider { stroke: var(--ink-soft); stroke-width: 1; stroke-dasharray: 3 3; }
.eval-chart .area-sente { fill: var(--ink); opacity: .75; }
.eval-chart .area-gote { fill: var(--rule); }
.eval-chart .line { fill: none; stroke: var(--ink); stroke-width: 1; opacity: .5; }
.eval-chart .cursor { stroke: var(--accent); stroke-width: 1.5; }
.eval-chart .dot { fill: var(--accent); }
.eval-chart .kings { fill: var(--ink-soft); }
.eval-chart text { fill: var(--ink-soft); font-size: 9px; font-family: var(--sans); }
.eval-chart text.tip { fill: var(--accent); font-weight: 600; font-variant-numeric: tabular-nums; }

.kifu-box { display: flex; flex-direction: column; min-width: 0; }
/* 役の見出し行。棋譜の枠の上に一行。 */
.kifu-head {
  margin: 0 0 .25rem;
  padding: 0 var(--sp-3);
  font-size: .72rem;
  line-height: 1.4;
  color: var(--ink-soft);
  letter-spacing: .02em;
}
.kifu {
  margin: 0;
  padding: var(--sp-3);
  max-height: 22rem;
  min-height: 6rem;
  overflow-y: auto;
  list-style: none;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 4px;
  font-size: .8125rem;
}
.kifu li { display: flex; gap: var(--sp-5); padding: var(--sp-1) var(--sp-3); cursor: pointer; }
.kifu li:hover { background: color-mix(in srgb, var(--ink-soft) 18%, transparent); }
.kifu li:nth-child(odd) { background: color-mix(in srgb, var(--rule) 30%, transparent); }
.kifu .n { flex: 0 0 auto; width: 2.2em; text-align: right; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.kifu .m { font-family: var(--serif); }
:lang(en) .kifu .m { font-family: var(--sans); font-variant-numeric: tabular-nums; }
.kifu li.gote .m { color: var(--ink-soft); }
/* 直前の手。lishogiも現在の手を1行だけ塗って示す。 */
.kifu li.current { background: color-mix(in srgb, var(--accent) 18%, transparent); }
.kifu li.current .m,
.kifu li.current .n { color: var(--ink); font-weight: 600; }
/* 区切り。先後の選択の行と、41手目の行の上に線と一言を置く。 */
.kifu li.divider { flex-wrap: wrap; }
.kifu li.divider::before {
  content: attr(data-divider);
  flex: 1 0 100%;
  margin: var(--sp-2) 0 var(--sp-1);
  padding-top: .15rem;
  border-top: 1px dashed var(--ink-soft);
  color: var(--ink-soft);
  font-size: .7rem;
  letter-spacing: .06em;
}
.kifu li.choice .m { font-family: var(--sans); font-weight: 600; }

/* 検討で試している変化。本譜の下に1本だけ、縁を立てて別物だと分かるようにする。 */
.variation {
  margin: var(--sp-3) 0 0;
  padding: .25rem var(--sp-3);
  max-height: 6rem;
  overflow-y: auto;
  list-style: none;
  background: var(--paper-raised);
  border: 1px solid var(--accent);
  border-radius: 4px;
  font-size: .8125rem;
}
.variation::before {
  content: attr(data-head);
  display: block;
  margin: 0 var(--sp-3) var(--sp-1);
  color: var(--accent);
  font-size: .7rem;
  letter-spacing: .06em;
}
.variation li { display: flex; gap: var(--sp-5); padding: var(--sp-1) var(--sp-3); cursor: pointer; }
.variation li:hover { background: color-mix(in srgb, var(--ink-soft) 18%, transparent); }
.variation .n { flex: 0 0 auto; width: 2.2em; text-align: right; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.variation .m { font-family: var(--serif); }
:lang(en) .variation .m { font-family: var(--sans); font-variant-numeric: tabular-nums; }
.variation li.current { background: color-mix(in srgb, var(--accent) 18%, transparent); }
.variation li.current .m { font-weight: 600; }

/* 検討の候補手。評価・指し手・読み筋を1行ずつ。押すとその手を指し、なぞると矢印が出る。 */
/* 候補手は1本1行（評価・手・読み筋を同じ行に。読み筋は省略記号で切る）。読み筋を2行目にすると
   3本で6行になり、グラフ・操作2行と合わせて棋譜の高さを食う（1920×1080 で棋譜が3行になった）。 */
.candidates { margin: .15rem 0 0; padding: 0; list-style: none; display: grid; gap: var(--sp-1); }
.candidates li {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr);
  align-items: baseline;
  gap: var(--sp-1) var(--sp-5);
  padding: .15rem var(--sp-4);
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--paper-raised);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
  min-width: 0;
}
.candidates li:hover, .candidates li.hover { border-color: var(--accent); }
.candidates .ev { font-weight: 700; color: var(--ink); white-space: nowrap; min-width: 3.4em; }
.candidates .mv { color: var(--ink); font-family: var(--serif); font-weight: 600; white-space: nowrap; }
.candidates .pv { color: var(--ink-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: .72rem; }
.candidates .pv:empty { display: none; }
/* 布石の候補（確率と手だけ）は札を横に並べる。5本で2行ほど。 */
.candidates.chips { display: flex; flex-wrap: wrap; gap: .25rem; }
.candidates.chips li { display: flex; gap: .35em; padding: var(--sp-1) var(--sp-5); border-radius: 999px; }
.candidates.chips .ev { min-width: 0; }
:lang(en) .candidates .mv { font-family: var(--sans); }

/* 検討で盤に出す矢印と印（shogiground の drawable）。ブラシ名がそのままクラスになる。 */
.sg-shapes { pointer-events: none; overflow: visible; z-index: 2; }
.sg-shapes g { fill: none; }
.sg-shapes g.primary { stroke: var(--accent); stroke-opacity: .8; }
.sg-shapes g.alt { stroke: #3b6db3; stroke-opacity: .55; }
.sg-shapes marker#arrowhead-primary path { fill: var(--accent); fill-opacity: .8; }
.sg-shapes marker#arrowhead-alt path { fill: #3b6db3; fill-opacity: .55; }
.sg-shapes g.description ellipse { fill: var(--paper-raised); stroke: var(--accent); stroke-width: .2; }
.sg-shapes g.description text { fill: var(--ink); font-size: 3px; font-weight: 700; stroke: none; }
/* 検討中は盤の縁を変える（さかのぼり中と同じ色）。 */
.sg-wrap.analyzing sg-board { border-color: var(--accent); }

/* 棋譜をさかのぼるボタン。lishogiと同じ4つ。 */
.kifu-nav { display: flex; gap: 1px; margin-top: var(--sp-4); }
.kifu-nav button {
  flex: 1;
  padding: var(--sp-3) 0;
  background: var(--paper-raised);
  color: var(--ink-soft);
  border: 1px solid var(--rule);
  border-radius: 0;
  font: inherit;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}
.kifu-nav button svg {
  display: block;
  width: 1.1rem;
  height: 1.1rem;
  margin: 0 auto;
  fill: currentColor;
}
.kifu-nav button:first-child { border-radius: 4px 0 0 4px; }
.kifu-nav button:last-child { border-radius: 0 4px 4px 0; }
.kifu-nav button:hover:not(:disabled) { color: var(--ink); border-color: var(--ink-soft); }
.kifu-nav button:disabled { opacity: .3; cursor: default; }

/* 広い画面では、パネルは固定スロットの grid。席・帯・状態・操作・棋譜・グラフ・エンジン・席の
   8行で、棋譜の行だけが余りを取り、内側でスクロールする。ほかの行は中身で決まるので、
   状態が変わっても動くのは棋譜の高さだけになる。
   hidden の要素は grid から抜けて後ろの行が繰り上がるので、hidden になりうるもの
   （グラフ・エンジン枠）は 1fr の棋譜より**後ろ**に置く。前に置くと棋譜が auto の行に落ちる。
   .layout > .panel と書くのは詳細度のため。上の .panel { display: flex } と同じ詳細度だと
   後に書いたほうが勝つので、こちらを上げておく（.kifu の max-height も同じ）。 */
@media (min-width: 56rem) {
  .layout > .panel {
    display: grid;
    /* 棋譜の行は余りを取るが、9rem は下回らない（検討では状態・操作2行・グラフ・候補手が並び、
       盤の高さに収めると棋譜が3行に潰れた）。足りなければパネルが盤より高くなり、ページが伸びる。 */
    grid-template-rows: auto auto auto auto minmax(9rem, 1fr) auto auto auto;
    gap: .55rem;
    min-height: 0;
  }
  .layout > .panel .kifu-box { min-height: 0; }
  .layout > .panel .kifu { flex: 1 1 0; min-height: 0; max-height: none; }
}

/* 局面の受け渡しはダイアログ。パネルの中に置くと、開いたときにパネルが盤より
   背高になってレイアウトが崩れる。dialog はフローの外なので盤にも席にも触らない。 */
.io-dialog {
  width: min(34rem, calc(100vw - 2rem));
  overscroll-behavior: contain;
  max-height: calc(100dvh - 2rem);
  overflow-y: auto;
  padding: var(--sp-8) 1.1rem 1.2rem;
  background: var(--paper-raised);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 8px;
  font-size: .8125rem;
}
.io-dialog::backdrop { background: rgba(0, 0, 0, .45); }

/* 開閉をなめらかにする。gui-challenges（argyleink）は JS でアニメの完了を待つ作りだが、
   @starting-style と allow-discrete を使えばCSSだけで済む（対応していないブラウザでは
   従来どおり瞬間で出る＝壊れない）。秒数は幕と揃えて .2s。 */
.io-dialog {
  opacity: 0;
  transform: translateY(4px);
  transition: opacity .2s ease, transform .2s ease, overlay .2s allow-discrete, display .2s allow-discrete;
}
.io-dialog[open] { opacity: 1; transform: none; }
@starting-style {
  .io-dialog[open] { opacity: 0; transform: translateY(4px); }
}
.io-dialog::backdrop {
  opacity: 0;
  transition: opacity .2s ease, overlay .2s allow-discrete, display .2s allow-discrete;
}
.io-dialog[open]::backdrop { opacity: 1; }
@starting-style {
  .io-dialog[open]::backdrop { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .io-dialog, .io-dialog::backdrop { transition: none; }
  .io-dialog { transform: none; }
}
.io-dialog-head { display: flex; align-items: center; gap: var(--sp-6); margin-bottom: var(--sp-6); }
.io-dialog-head h2, .leave-dialog h2 { flex: 1 1 auto; margin: 0; font-size: 1rem; }
.io-close {
  padding: var(--sp-2) var(--sp-5);
  background: none; color: var(--ink-soft);
  border: 1px solid var(--rule); border-radius: 4px;
  font: inherit; cursor: pointer;
}
.io-close:hover { color: var(--ink); border-color: var(--ink-soft); }
.io-dialog > label {
  display: flex; flex-direction: column; gap: var(--sp-2); margin-top: var(--sp-6);
  color: var(--ink-soft);
}
.io-dialog textarea,
.io-dialog input[type="text"] {
  width: 100%;
  min-width: 0;
  padding: var(--sp-4) var(--sp-5);
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 4px;
  font: inherit;
  font-size: .8125rem;
  resize: vertical;
}
.moves-io-actions { display: flex; gap: var(--sp-4); margin-top: var(--sp-5); flex-wrap: wrap; }
.moves-io-actions button {
  flex: 1;
  padding: var(--sp-4) var(--sp-5);
  background: var(--paper);
  color: var(--ink-soft);
  border: 1px solid var(--rule);
  border-radius: 4px;
  font: inherit;
  font-size: .8125rem;
  cursor: pointer;
  white-space: nowrap;
}
.moves-io-actions button:hover { color: var(--ink); border-color: var(--ink-soft); }
.moves-io-actions button.danger { background: var(--accent); color: var(--paper-raised); border-color: var(--accent); font-weight: 600; }
.io-note { margin: var(--sp-4) 0 0; line-height: 1.5; color: var(--ink-soft); font-size: .75rem; }
.io-note:empty { display: none; }
.leave-dialog { width: min(26rem, calc(100vw - 2rem)); }
.leave-dialog .io-note { margin-top: var(--sp-5); }

:where(button, select, input, a):focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.app-footer {
  margin-top: 2.5rem;
  padding-top: var(--sp-8);
  border-top: 1px solid var(--rule);
  color: var(--ink-soft);
  font-size: .75rem;
}
.app-footer p { margin: var(--sp-2) 0; }
.app-footer a { color: inherit; }

/* ---- 文章のページ（ルール・コラム） ---- */

.page { max-width: 42rem; margin: 0 auto; padding: var(--sp-5) 0 2rem; font-size: .95rem; line-height: 1.85; }
:lang(en) .page { line-height: 1.6; }
.page h1 { margin: 0 0 var(--sp-3); font-family: var(--serif); font-size: 1.9rem; line-height: 1.3; letter-spacing: .03em; }
.page .lead { margin: 0 0 1.6rem; color: var(--ink-soft); }
.page h2 { margin: 2rem 0 var(--sp-5); font-family: var(--serif); font-size: 1.3rem; line-height: 1.35; }
.page h3 { margin: 1.4rem 0 var(--sp-4); font-size: 1rem; }
.page p { margin: var(--sp-5) 0; }
.page ul, .page ol { padding-left: 1.4rem; }
.page li { margin: var(--sp-2) 0; }
.page table { width: 100%; border-collapse: collapse; font-size: .85rem; margin: var(--sp-6) 0 var(--sp-8); }
.page th, .page td { text-align: left; vertical-align: top; padding: var(--sp-4) var(--sp-5); border-bottom: 1px solid var(--rule); }
.page th { color: var(--ink-soft); font-size: .75rem; font-weight: 600; letter-spacing: .04em; }
.page td.n, .page th.n { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.page .scroll { overflow-x: auto; }
.page blockquote {
  margin: var(--sp-7) 0; padding: var(--sp-5) .9rem;
  border-left: 3px solid var(--accent);
  background: var(--paper-raised);
  border-radius: 0 4px 4px 0;
}
.page blockquote p { margin: var(--sp-2) 0; }
.page code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .86em; background: color-mix(in srgb, var(--rule) 45%, transparent); padding: .05em .3em; border-radius: 3px; }
.page a { color: inherit; }
.page .note { font-size: .82rem; color: var(--ink-soft); }
/* 案内のページ（/balance/）の「対局する」。対局画面の primary ボタンと同じ見た目のリンク。 */
.page .cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-6) var(--sp-8); margin: var(--sp-8) 0 1.4rem; }
.page a.cta {
  display: inline-block;
  padding: .55rem 1.3rem;
  background: var(--ink);
  color: var(--paper);
  border: 1px solid var(--ink);
  border-radius: 6px;
  font-weight: 600;
  text-decoration: none;
}
.page a.cta:hover { background: var(--ink-soft); border-color: var(--ink-soft); }
.page .cta-note { font-size: .82rem; color: var(--ink-soft); }
.page figure { margin: var(--sp-8) 0; }
.page figcaption { font-size: .78rem; color: var(--ink-soft); margin-top: var(--sp-3); }
/* 両玉の価値表のヒートマップ。段×筋の升に色を塗る。 */
.heat { display: grid; gap: var(--sp-8); grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); }
.heat-board { display: grid; gap: var(--sp-3); font-size: .72rem; }
.heat-title { font-weight: 600; }
.heat-grid { display: grid; grid-template-columns: repeat(9, 1fr); gap: 2px; }
.heat-cell {
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  border-radius: 2px;
  font-size: .62rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.heat-scale { display: flex; align-items: center; gap: var(--sp-4); font-size: .72rem; color: var(--ink-soft); }
.heat-scale i { flex: 1; height: 8px; border-radius: 2px; background: linear-gradient(90deg, #4e79c4, #f4f2ea 50%, #d9542d); }
.heat-note { font-size: .75rem; color: var(--ink-soft); }
.roles { display: grid; gap: var(--sp-6); grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); margin: var(--sp-7) 0; }
.roles div { padding: var(--sp-6) var(--sp-7); background: var(--paper-raised); border: 1px solid var(--rule); border-radius: 6px; font-size: .85rem; }
.roles b { display: block; font-family: var(--serif); font-size: 1.05rem; margin-bottom: var(--sp-2); }
.stat { display: grid; gap: var(--sp-6); grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); margin: var(--sp-7) 0; }
.stat div { padding: var(--sp-5) .7rem; background: var(--paper-raised); border: 1px solid var(--rule); border-radius: 6px; }
.stat b { display: block; font-size: 1.3rem; font-variant-numeric: tabular-nums; line-height: 1.2; }
.stat span { font-size: .75rem; color: var(--ink-soft); }

/* コラムの図。SVGはページに直接書き、色は必ずトークンか currentColor から取る。
   片方のテーマにしか無い色を使うと、もう片方で図が消える。 */
.page svg.fig { display: block; width: 100%; height: auto; margin: var(--sp-2) 0 0; overflow: visible; }
.page svg.fig text { fill: currentColor; font-family: inherit; font-size: 12px; }
.page svg.fig .t-soft { fill: var(--ink-soft); font-size: 11px; }
.page svg.fig .t-num { font-variant-numeric: tabular-nums; }
.page svg.fig .t-head { font-weight: 600; }
.page svg.fig .bar { fill: currentColor; opacity: .2; }
.page svg.fig .bar-on { fill: var(--accent); opacity: .85; }
.page svg.fig .dot { fill: currentColor; fill-opacity: .35; }
.page svg.fig .dot-on { fill: var(--accent); fill-opacity: .45; }
.page svg.fig .box { fill: var(--paper-raised); stroke: var(--rule); }
.page svg.fig .rule { stroke: var(--rule); fill: none; }
.page svg.fig .axis { stroke: currentColor; opacity: .45; fill: none; }
.page svg.fig .mid { stroke: var(--accent); stroke-dasharray: 3 3; opacity: .7; }
.page svg.fig .link { stroke: currentColor; opacity: .3; fill: none; }

/* ---- ルールの図（盤・駒の帯・手順） ----

   盤図は shogiground を使わない。対局盤は状態を持つ部品で、静的な図に持ち込むと
   JSが要る。ここは 9×9 のCSSグリッドで、マス目を背景の格子で描き、駒だけを置く。
   駒は対局盤とまったく同じ <piece class="sente pawn"> の絵（pieces/*.svg）なので、
   図と実物で駒が食い違わない。置き場所は筋 .f1〜.f9 と段 .r1〜.r9 のクラスで、
   盤の座標のまま書ける（例: 5八の先手玉は class="sente king f5 r8"）。
   インラインの style= は使えない（CSPの style-src が 'self' のみ）ので、
   位置も色もすべてクラスで持つ。 */

.diag {
  container-type: inline-size;
  position: relative;
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-template-rows: repeat(9, 1fr);
  aspect-ratio: 1;
  background-color: var(--board);
  background-image:
    repeating-linear-gradient(to right, color-mix(in srgb, var(--line) 65%, transparent) 0 1px, transparent 1px calc(100% / 9)),
    repeating-linear-gradient(to bottom, color-mix(in srgb, var(--line) 65%, transparent) 0 1px, transparent 1px calc(100% / 9));
  border: 2px solid var(--board-edge);
  border-radius: 2px;
}
/* 自陣4段だけを描く図（二歩の禁じ手）。段は6〜9のまま書けるように読み替える。 */
.diag.camp {
  grid-template-rows: repeat(4, 1fr);
  aspect-ratio: 9 / 4;
  background-image:
    repeating-linear-gradient(to right, color-mix(in srgb, var(--line) 65%, transparent) 0 1px, transparent 1px calc(100% / 9)),
    repeating-linear-gradient(to bottom, color-mix(in srgb, var(--line) 65%, transparent) 0 1px, transparent 1px calc(100% / 4));
}
.diag.camp .r6 { grid-row: 1; }
.diag.camp .r7 { grid-row: 2; }
.diag.camp .r8 { grid-row: 3; }
.diag.camp .r9 { grid-row: 4; }

.diag .f9 { grid-column: 1; }
.diag .f8 { grid-column: 2; }
.diag .f7 { grid-column: 3; }
.diag .f6 { grid-column: 4; }
.diag .f5 { grid-column: 5; }
.diag .f4 { grid-column: 6; }
.diag .f3 { grid-column: 7; }
.diag .f2 { grid-column: 8; }
.diag .f1 { grid-column: 9; }
.diag .r1 { grid-row: 1; }
.diag .r2 { grid-row: 2; }
.diag .r3 { grid-row: 3; }
.diag .r4 { grid-row: 4; }
.diag .r5 { grid-row: 5; }
.diag .r6 { grid-row: 6; }
.diag .r7 { grid-row: 7; }
.diag .r8 { grid-row: 8; }
.diag .r9 { grid-row: 9; }

/* 図の駒は掴めない。対局盤の piece は cursor:pointer なので戻す。 */
.diag piece { width: 100%; height: 100%; cursor: default; }

/* 打てる範囲の塗り。先手は朱、後手は墨（サイトの約束＝塗りが先手）。 */
.diag .zone {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 2%;
}
.diag .zone.b { grid-row: 6 / 10; background: color-mix(in srgb, var(--accent) 26%, transparent); }
.diag .zone.w { grid-row: 1 / 5; background: color-mix(in srgb, var(--ink) 17%, transparent); }
.diag .zone span {
  font-size: 3.4cqi;
  font-weight: 600;
  letter-spacing: .04em;
  color: #2a2018;
  background: color-mix(in srgb, #fffdf8 82%, transparent);
  border-radius: 3px;
  padding: .15em .5em;
  text-align: center;
}

/* 升の印。✕（打てない）・○（打てる）・輪（注目）。 */
.diag .mk {
  display: grid;
  place-items: center;
  font-size: 7.5cqi;
  font-weight: 700;
  line-height: 1;
  /* 盤（朱でも墨でもない橙）の上に置くので、紙色の縁で浮かせる。 */
  text-shadow: 0 0 .18em #fffdf8, 0 0 .35em #fffdf8, 0 0 .5em #fffdf8;
}
.diag .mk.bad { color: var(--accent); }
.diag .mk.ok { color: var(--ok); }

/* 利きの線。盤と同じ 9×9（自陣図は 9×4）の座標で引く。 */
.diag .rays { grid-area: 1 / 1 / -1 / -1; width: 100%; height: 100%; pointer-events: none; }
.diag .rays path { fill: none; stroke: var(--accent); stroke-width: .1; stroke-linecap: round; opacity: .9; }
.diag .rays .head { fill: var(--accent); stroke: none; opacity: .9; }

.page figure > .diag { max-width: 22rem; margin-inline: auto; }

/* 図を横に並べる枠。狭い画面では縦に積む。 */
.page .diag-row { display: grid; gap: .9rem; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); align-items: start; }
.page .diag-row > figure { margin: 0; }
.page .diag-row h4 { margin: 0 0 var(--sp-3); font-size: .82rem; font-weight: 600; }
.page .diag-row h4 .tag,
.page figcaption .tag { font-weight: 700; margin-right: .15em; }
.page .diag-row h4 .tag.bad,
.page figcaption .tag.bad { color: var(--accent); }
.page .diag-row h4 .tag.ok,
.page figcaption .tag.ok { color: var(--ok); }

/* 打つ20枚の内訳。駒の絵をそのまま並べ、枚数を下に置く。 */
.page .piece-set { display: flex; flex-wrap: wrap; gap: var(--sp-5); margin: var(--sp-7) 0; padding: 0; list-style: none; }
.page .piece-set li {
  margin: 0;
  display: grid;
  justify-items: center;
  gap: var(--sp-1);
  padding: var(--sp-4) var(--sp-3) var(--sp-3);
  min-width: 3.2rem;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 6px;
}
.page .piece-set piece { width: 2rem; height: 2rem; cursor: default; }
.page .piece-set b { font-size: .8rem; font-variant-numeric: tabular-nums; }
.page .piece-set li.total {
  align-content: center;
  padding-inline: .7rem;
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--paper-raised));
}
.page .piece-set li.total b { font-family: var(--serif); font-size: 1.4rem; line-height: 1.1; }
.page .piece-set li.total span { font-size: .7rem; color: var(--ink-soft); }

/* 天秤将棋の手順。ミニ盤を役の札つきで並べる。 */
.page .steps { display: grid; gap: var(--sp-7); grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); margin: var(--sp-7) 0; padding: 0; list-style: none; }
.page .steps > li { display: grid; gap: var(--sp-3); align-content: start; margin: 0; }
.page .steps .who {
  justify-self: start;
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .06em;
  padding: var(--sp-1) .45rem;
  border-radius: 999px;
  border: 1px solid var(--rule);
  color: var(--ink-soft);
}
.page .steps .who.place { color: var(--paper-raised); background: var(--ink); border-color: var(--ink); }
.page .steps .who.pick { color: var(--paper-raised); background: var(--accent); border-color: var(--accent); }
.page .steps .what { font-size: .82rem; font-weight: 600; line-height: 1.5; }
.page .steps .what em { font-style: normal; color: var(--ink-soft); font-weight: 400; }
/* 先後の2択。手順3は局面が変わらないので、盤の下に札だけを出す。 */
.page .steps .pick-row { display: flex; gap: var(--sp-3); }
.page .steps .pick-row span {
  flex: 1;
  text-align: center;
  padding: var(--sp-3) var(--sp-2);
  font-size: .76rem;
  font-weight: 600;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 4px;
}
.page .steps .pick-row span.on { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }

/* 天秤の図（対局画面の #scale-fig と同じ絵）。文章のページでは常に出す。 */
.page .scale-fig { max-width: 22rem; margin: var(--sp-6) auto 0; }

/* 棋譜の分解。1文字ずつに意味の札を付ける。 */
.page .usi { display: flex; gap: .35rem; align-items: flex-start; margin: var(--sp-6) 0; flex-wrap: wrap; }
.page .usi > div { display: grid; justify-items: center; gap: .25rem; }
.page .usi code { font-size: 1.15rem; padding: .2em .45em; background: var(--paper-raised); border: 1px solid var(--rule); }
.page .usi span { font-size: .72rem; color: var(--ink-soft); text-align: center; line-height: 1.4; }

/* hidden 属性は作者スタイルの display に負ける。詳細度が同じなら後に書いた方が、
   高ければそちらが勝つ。ここは「隠す」という一点だけの規則なので !important で押し切る。
   落とさないと、見えないまま場所を取り、クリックまで横取りする。 */
[hidden] { display: none !important; }
