/* 第57回一橋祭 パンフレットビューア
 *
 * Tailwind から素の CSS に書き換えたもの。クラス名は BEM 風ではなく
 * 「役割の名前」で統一している（.header / .rail / .stage など）。
 * ビルド不要で、このファイルを直接編集すれば見た目が変わる。 */

:root {
  /* 第57回の誌面（テーマ「One Spectra」）から拾った値。紙は青みのある白
     （#f7f9f8、余白のティントは #edf0f3）、主調色は青緑〜紺（#356f8a /
     #2a4f60）、差し色が金（#efe5a6）。サイト共通の --themeocean (#0c5f81) /
     --themevintage (#324e5a) / --themeskyblue (#cbe8ec) とも揃えてある。

     A dark surround was the obvious choice for a page viewer, but it reads as
     a gallery or a photo app — the pamphlet stops looking like a booklet. A
     desk-toned surround lets each page sit on the background as a physical
     sheet instead. It has to be clearly darker than the paper, though: at
     only a shade off, the sheet edge disappears and the whole screen reads as
     one flat surface. 56回は紙の暖色に合わせて机も茶系だったが、57回は紙が
     寒色なので机も青灰にしている。
     彩度は誌面より低く保つ。以前の #a9c2c9 は表紙の青緑と同じくらい鮮やかで、
     机が誌面と同じ土俵に乗って見えた（2026-10-13）。
     --muted は帯の小さな文字（矢印キーの案内・総ページ数・トップページへ）にも
     使うので、--background の上で 3:1 を切らない濃さにしておく
     （#4a6673 で約 3.2:1。以前の #5e7a86 は約 2.4:1）。 */
  --background: #afc0c5;
  --surface: #f6f9f9;
  --foreground: #1f3a46;
  --accent: #0c5f81;
  --muted: #4a6673;
  --rule: rgba(31, 58, 70, 0.14);
  /* 目次のホバー・現在位置。黒の 5% だと目次だけ無彩色に見えたので青で（2026-10-13） */
  --toc-hover: rgba(12, 95, 129, 0.08);
  /* ボタンのホバーと押している間の背景。--surface に --accent を混ぜた不透明の色
     （ボタンの下地が誌面や机の色で透けないように）。ホバーは --toc-hover と同じ濃さ */
  --btn-hover: color-mix(in srgb, var(--accent) 8%, var(--surface));
  --btn-press: color-mix(in srgb, var(--accent) 16%, var(--surface));

  /* 紙の影。ページ・見開き・拡大表示で使い回す。 */
  --sheet-shadow:
    0 1px 1px rgba(31, 58, 70, 0.16),
    0 4px 10px rgba(31, 58, 70, 0.16),
    0 14px 28px rgba(31, 58, 70, 0.1);
}

/* ---- リセット（最小限） ---------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  height: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  min-height: 100%;
  margin: 0;
  background: var(--background);
  color: var(--foreground);
  /* サイト本体（common/common_general.css の body）と同じ Zen Kaku Gothic New。
     index.php が Google Fonts から読む。届くまでの間と読めなかったときは
     OS 標準の日本語ゴシック（ヒラギノ → Yu Gothic UI → メイリオ）。 */
  font-family: "Zen Kaku Gothic New", "Hiragino Sans", "Hiragino Kaku Gothic ProN",
    "Yu Gothic UI", "Yu Gothic", Meiryo, system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.6;
}

button {
  font: inherit;
  color: inherit;
  cursor: pointer;
}

a {
  color: inherit;
}

/* 数字を等幅に。ページ番号がちらつかない。 */
.tnum {
  font-variant-numeric: tabular-nums;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---- 共通の丸ボタン -------------------------------------------------- */

/* display が hidden 属性に勝たないように（.segmented と同じ取りこぼし） */
.pill[hidden] {
  display: none;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  white-space: nowrap;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--surface);
  padding: 0.375rem 0.875rem;
  font-size: 0.875rem;
  transition: border-color 0.15s, color 0.15s, opacity 0.15s, background-color 0.15s;
}

.pill:hover:not(:disabled) {
  border-color: var(--accent);
}

.pill:disabled {
  opacity: 0.3;
  cursor: default;
}

.pill:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* 確認カードの「進む」側。リンクにも使うので下線を消す */
.pill.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  text-decoration: none;
}

.pill.primary:hover {
  background: var(--foreground);
  border-color: var(--foreground);
}

/* セグメント切替（見開き/スクロール、標準/大/特大） */

/* display: flex が hidden 属性に勝ってしまうので、hidden のときは明示的に消す。
   56回からあった取りこぼしで、見開き表示でも「標準/大/特大」が出ていた。 */
.segmented[hidden] {
  display: none;
}

.segmented {
  display: flex;
  align-items: center;
  gap: 0.125rem;
  flex-shrink: 0;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--surface);
  padding: 0.125rem;
}

.segmented button {
  border: 0;
  border-radius: 999px;
  background: transparent;
  padding: 0.25rem 0.625rem;
  font-size: 0.75rem;
  color: var(--muted);
  transition: background-color 0.15s, color 0.15s;
}

.segmented button:hover {
  color: var(--foreground);
}

.segmented button[aria-pressed="true"] {
  background: var(--accent);
  color: #fff;
}

/* スマホ幅では拡大の − / 100% / ＋ を出さない（指でつまめばよく、ヘッダーにも入りきらない）。
   「1ページ / 見開き」（.view-switch）は出す */
@media (max-width: 639px) {
  .segmented:not(.view-switch) {
    display: none;
  }
}

/* ---- ヘッダー -------------------------------------------------------- */

.header {
  position: sticky;
  top: 0;
  z-index: 30;
  border-bottom: 1px solid var(--rule);
  background: color-mix(in srgb, var(--background) 90%, transparent);
  backdrop-filter: blur(12px);
}

.header-inner {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  max-width: 56rem;
  margin: 0 auto;
  padding: 0.75rem 1rem;
}

/* 見開き表示のときはヘッダーの幅の上限を外す。56rem はスクロール表示の列幅に
   合わせたもので、見開き（ヘッダーレイアウト）では札が増えてタイトルが省略される */
html.spread-ui .header-inner {
  max-width: none;
}

.header-title {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font-size: 0.875rem;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.header-count {
  flex-shrink: 0;
  margin: 0;
  font-size: 0.875rem;
  color: var(--muted);
}

/* スマホはタイトルを出さない（タブに出ているし、ロゴのマークが左端にある）。
   ロゴ・目次・「1ページ / 見開き」・ページ番号が 360px 幅でも 1 行に入るよう、
   間隔と札の余白を詰める（見開きの「124-125 / 125」がいちばん長い） */
@media (max-width: 639px) {
  .header-title {
    display: none;
  }

  .header-inner {
    gap: 0.5rem;
    padding-inline: 0.75rem;
  }

  #toc-open {
    padding-inline: 0.625rem;
  }

  .view-switch button {
    padding-inline: 0.5rem;
  }

  .header-count {
    margin-left: auto;
    font-size: 0.9375rem;
  }

  /* iPhone は 16px 未満の入力欄を押すと画面ごと拡大する。
     後ろの .page-input の font: inherit に負けないよう2段で指定 */
  .header-count .page-input {
    font-size: 16px;
  }
}

/* ページ番号の入力欄。見た目は文字のままにして、下線だけで「書ける」と分からせる */
.header-count {
  display: flex;
  align-items: baseline;
}

.header-count span {
  margin-left: 0.35em;
}

.page-input {
  font: inherit;
  color: var(--foreground);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule);
  border-radius: 0;
  padding: 0 0.1rem;
  margin: 0;
  min-width: 3ch;
  text-align: right;
}

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

/* 読み進めた位置 */
.progress {
  height: 2px;
  background: var(--accent);
  transition: width 0.15s;
}

/* ---- 目次パネル ------------------------------------------------------ */

.scrim {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(31, 58, 70, 0.4);
}

.toc {
  position: fixed;
  inset-block: 0;
  left: 0;
  z-index: 50;
  width: min(20rem, 85vw);
  overflow-y: auto;
  border-right: 1px solid var(--rule);
  background: var(--surface);
  padding: 1.5rem 1.25rem;
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.2);
}

.toc[hidden],
.scrim[hidden] {
  display: none;
}

.toc-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.25rem;
}

.toc-head h2 {
  margin: 0;
  font-size: 1rem;
  /* Zen Kaku Gothic New は 400/500/700 しか読んでいないので 600 は使わない */
  font-weight: 700;
}

.toc-close {
  border: 0;
  border-radius: 999px;
  background: transparent;
  padding: 0.375rem;
  line-height: 0;
  color: var(--muted);
  transition: background-color 0.15s, color 0.15s;
}

.toc-close:hover {
  background: var(--toc-hover);
  color: var(--foreground);
}

.toc ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.toc > ul > li + li {
  margin-top: 0.25rem;
}

/* 目次の行。ラベルとページ番号を両端に。 */
.toc-link {
  display: flex;
  width: 100%;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  border: 0;
  border-radius: 0.375rem;
  background: transparent;
  padding: 0.375rem 0.5rem;
  text-align: left;
  font-size: 0.875rem;
  font-weight: 500;
  transition: background-color 0.15s, color 0.15s;
}

.toc-link:hover {
  background: var(--toc-hover);
}

/* いま開いているページが入っている節。目次を開くたびに app.js（章9）が
   aria-current を付け直す。親の節には has-current が付く */
.toc-link[aria-current="true"] {
  color: var(--accent);
  background: var(--toc-hover);
}

.toc > ul > li.has-current > .toc-link {
  color: var(--accent);
}

.toc-link .page-no {
  font-size: 0.75rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* 子項目は字下げして左に薄い縦線。誌面の目次（表紙裏）と同じ構造に見せる。
   ★ セレクタは `.toc .toc-children` のまま。`.toc-children` だけだと上の
   `.toc ul { margin: 0; padding: 0 }` に詳細度で負けて余白が 0 に戻り、親と子が
   同じ列に並ぶ（2026-10-17 まで実際にそうなっていた） */
.toc .toc-children {
  margin: 0 0 0.25rem 0.5rem;
  border-left: 1px solid var(--rule);
  padding-left: 0.5rem;
}

.toc-children .toc-link {
  padding: 0.25rem 0.5rem;
  font-size: 13px;
  font-weight: 400;
  color: var(--muted);
}

.toc-children .toc-link:hover {
  color: var(--foreground);
}

.toc-children .toc-link[aria-current="true"] {
  color: var(--accent);
  font-weight: 500;
}

.toc-pdf {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 1.5rem;
  border: 1px solid var(--rule);
  border-radius: 0.5rem;
  padding: 0.625rem 0.75rem;
  font-size: 0.875rem;
  text-decoration: none;
  transition: border-color 0.15s, color 0.15s;
}

.toc-pdf:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* ---- スクロール表示（ページを縦に並べる） ---------------------------- */

.rail {
  margin: 0 auto;
  padding: 1rem 0.75rem 6rem;
  /* 列幅は JS が --rail-width に流し込む（標準/大/特大）。 */
  max-width: var(--rail-width, 680px);
  scrollbar-width: thin;
  scrollbar-color: var(--muted) transparent;
}

@media (min-width: 640px) {
  .rail {
    padding-inline: 1rem;
  }
}

.rail[hidden],
.stage[hidden] {
  display: none;
}

/* Each slot holds its page's aspect box (set inline from the manifest) so the
   121,000px scroll height is correct before any image arrives.
   Deliberately NOT using `content-visibility: auto` here: inside a skipped
   subtree the browser never starts the request for a lazily-loaded image, so
   jumping deep into the book left pages permanently blank. Plain lazy loading
   already keeps decode memory bounded, and it always fetches. */
.page-slot {
  position: relative;
  margin: 0 0 0.75rem;
  scroll-margin-top: 4rem;
  contain: layout paint;
}

.page-slot img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 2px;
  background: var(--surface);
  box-shadow: var(--sheet-shadow);
}

/* ページ番号は普段は隠し、ホバーで出す。 */
.page-slot figcaption {
  position: absolute;
  right: 0.5rem;
  bottom: 0.5rem;
  border-radius: 0.25rem;
  background: rgba(31, 58, 70, 0.7);
  padding: 0.125rem 0.375rem;
  font-size: 11px;
  color: #fff;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.15s;
}

.page-slot:hover figcaption {
  opacity: 1;
}

/* ---- 見開き表示 ------------------------------------------------------
 * PC は常に見開き。スマホはヘッダーで「見開き」を選んだとき（下の「スマホ」の節）。
 *
 * The scrolling rail wastes a desktop window twice over: it uses a narrow
 * column and still runs a single page taller than the viewport. Here the
 * spread is sized to the window height instead, so a whole facing pair is
 * visible at once — the way the book was actually laid out. */

.stage {
  /* Height available to a leaf: the window, less the sticky header and the
     stage's own vertical padding. Declared as a variable because the leaf
     has to size against it directly (see .spread-leaf). */
  --stage-h: calc(100dvh - 3.6rem - 2.5rem);
  /* 横幅も同じ考え方（左右の padding を引く）。幅で決まる窓（スマホ）で、
     見開きの右のページが画面からはみ出さないように .spread-leaf が使う */
  --stage-w: calc(100vw - 7rem);

  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: calc(100dvh - 3.6rem);
  padding: 1.25rem 3.5rem;
  overflow: hidden;
  /* 指の操作（つまむ・払う・ダブルタップ）は app.js 章8 が受ける。ブラウザ自身の
     拡大やスクロールに取られないようにする */
  touch-action: none;
}

/* ---- 帯レイアウト（app.js 章6c）---------------------------------------
   横長の画面ではヘッダーを消し、見開きを画面の高さいっぱいにして、
   ボタン類は左右の帯に縦に並べる。帯が狭い窓では html.gutter-ui が付かず、
   ヘッダーのまま。 */
html.gutter-ui .header {
  display: none;
}

html.gutter-ui .stage {
  --stage-h: calc(100dvh - 1rem);
  --stage-w: calc(100vw - 13rem);
  height: 100dvh;
  padding: 0.5rem 6.5rem;
}

.gutter {
  position: absolute;
  top: 0.75rem;
  /* 下端まで伸ばす。左の帯ではロゴを margin-top: auto で下端に付けるため */
  bottom: 0.75rem;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  /* 帯は ‹ › と矢印キーの案内の上に重なるので、帯そのものはクリックを通し、
     中のボタンだけが受ける */
  pointer-events: none;
  /* 拡大の − / 100% / ＋ を横に並べた幅（約 7rem）が入る広さ。
     app.js の GUTTER_MIN_REM と合わせること（帯がこれより狭い窓ではヘッダーに戻る） */
  width: 8rem;
}

.gutter.left {
  left: 0.25rem;
}

.gutter.right {
  right: 0.25rem;
}

html:not(.gutter-ui) .gutter {
  display: none;
}

.gutter > * {
  pointer-events: auto;
}

/* 帯の中ではページ番号と総ページ数を上下に */
.gutter .header-count {
  flex-direction: column;
  align-items: center;
}

.gutter .header-count span {
  margin-left: 0;
}

/* 表紙・裏表紙では総ページ数を出さない（renderCounter）が、帯の中では2行目の
   高さを空白で確保する。無いと表紙からめくった瞬間に下の拡大・全画面ボタンが
   1行ぶん下に落ちる（2026-10-13 に指摘あり） */
.gutter .header-count span:empty::before {
  content: "\00a0";
}

.gutter .page-input {
  text-align: center;
}

/* 帯の中の札も、拡大の − / 100% / ＋ や ‹ › と同じ不透明の --surface。
   以前は 85% の半透明にしていたが、隣のボタンと色が違って見えた（2026-10-13） */

#fullscreen[aria-pressed="true"] {
  color: var(--accent);
}

#fullscreen {
  gap: 0;
}

/* 字の無い札は行の高さが無く、目次などの札より低くなる。幅の無い字で1行ぶんを確保する */
#fullscreen::before {
  content: "\200b";
}

#fullscreen svg {
  display: block;
}

#fullscreen[aria-pressed="true"] .fs-enter,
#fullscreen:not([aria-pressed="true"]) .fs-exit {
  display: none;
}

.spread-sheet {
  display: flex;
  /* No gap: facing pages were one sheet, and artwork crosses the gutter. */
  gap: 0;
  /* その場の拡大（app.js 章6b）。中央を原点に transform で大きくする。
     will-change: transform はここに書かないこと。Chrome はそれが付いた要素を
     100% の大きさで一度だけ描き、拡大はその絵を引き伸ばすので、何倍に寄っても
     文字がぼやけたまま（2026-10-13 実測）。ドラッグ中だけ下で付ける。 */
  transform-origin: center center;
  align-items: stretch;
  max-width: 100%;
  max-height: 100%;
  box-shadow:
    0 1px 1px rgba(31, 58, 70, 0.16),
    0 6px 14px rgba(31, 58, 70, 0.16),
    0 20px 40px rgba(31, 58, 70, 0.12);

  /* 両方の葉が同時に現れる（settled spread を参照）。
     No transition: a fade here reads as a flicker on every page turn —
     the point is for the swap to be unnoticeable, not animated. The
     outgoing spread simply stays put until the next one can replace it
     whole. */
}

/* Each <picture> must shrink to its image. Left as a normal flex item it
   stretches to an equal share of the row, and the image then letterboxes
   inside it — which opens a gap right where the gutter should be. */
.spread-sheet > picture {
  display: block;
  flex: 0 0 auto;
  min-width: 0;
}

/* 抜いたページの代わりの紙（app.js の blankLeaf）。大きさは中の .spread-leaf が
   本物のページと同じ規則で決め、ロゴを真ん中に小さく重ねる */
.spread-sheet > .spread-blank {
  position: relative;
  flex: 0 0 auto;
  min-width: 0;
}

/* 下地の --surface は少し青みがあり、隣の白い誌面と並ぶと色の違いが目立つ */
.spread-blank .spread-leaf {
  background: #fff;
}

.spread-blank-logo {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 40%;
  transform: translate(-50%, -50%);
  opacity: 0.35;
  -webkit-user-drag: none;
  user-select: none;
}

/* Size the leaf against the viewport directly rather than chaining `height:
   100%` up through the flex parents: the sheet's height comes from
   `max-height`, which a percentage child cannot resolve against, so the
   image would fall back to its intrinsic 1759px and overflow the window.

   The fallback in var() matters. `--stage-h` is declared on .stage, so for
   the moment before that rule applies the variable is unresolved and the
   image briefly lays out at its natural 1240x1759 — which is the flash of a
   hugely magnified page on first paint. The fallback repeats the same
   calculation in viewport units, which need no ancestor to resolve, so the
   leaf is correctly sized from the very first frame. */
.spread-leaf {
  display: block;
  width: auto;
  height: auto;
  max-height: var(--stage-h, calc(100dvh - 6.1rem));
  /* 葉の数（--leaves。app.js の paintSpread が付ける）で舞台の幅を分ける */
  max-width: calc(var(--stage-w, 100vw) / var(--leaves, 1));
  background: var(--surface);
  /* ドラッグで見開きを動かすので、画像そのもののドラッグ（ゴースト）は止める */
  -webkit-user-drag: none;
  user-select: none;
}

/* 寄っているときはドラッグで動かせる（app.js 章6b） */
.stage.zoomed {
  cursor: grab;
}

.stage.dragging {
  cursor: grabbing;
}

/* ドラッグ中だけ GPU の層に乗せて滑らかに動かす。離すと外れて、
   いまの倍率で描き直される（上の .spread-sheet の注記）。マウスのドラッグだけ。
   指の操作では付けない（操作中ずっとぼやけるため。app.js 章8） */
.stage.dragging .spread-sheet {
  will-change: transform;
}

/* 寄っているときは ‹ › を見開きの上に出す（見開きが端まで広がるため） */
.stage.zoomed .pager {
  z-index: 1;
}

/* ヘッダーの拡大率。− / 100% / ＋ */
.zoom-switch #spread-zoom-reset {
  min-width: 4.5ch;
}

/* No gutter shading. A soft crease down the middle was meant to suggest a
   bound book, but on a static spread it reads as a page caught mid-turn —
   an animation that isn't there. The pages meet flush instead. */

/* The arrow keys do the real paging; these are a visible affordance for
   anyone who doesn't try them. (ホイールは拡大に使うので、ページ送りはしない)
   以前はホバーするまで薄くしていたが、ほぼ見えず気づかれなかったので
   常に丸ボタンとして出す（2026-10-13）。矢印キーの案内の札と同じ導線。 */
.pager {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  color: var(--foreground);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 999px;
  transition: opacity 0.15s, border-color 0.15s, color 0.15s, background-color 0.15s;
}

.pager.prev {
  left: 0.5rem;
}

.pager.next {
  right: 0.5rem;
}

.pager:hover:not(:disabled) {
  border-color: var(--accent);
}

.pager svg {
  display: block;
}

/* 他の札（.pill:disabled）と同じ薄さ。0.15 だと白い丸だけがぼんやり残って見えた */
.pager:disabled {
  opacity: 0.3;
  cursor: default;
}

/* 帯レイアウトでは、帯の列（端から 0.25rem、幅 8rem）の中央に置いて、
   真下の矢印キーの案内と軸を揃える。0.25rem + 4rem − 1.25rem = 3rem */
html.gutter-ui .pager.prev {
  left: 3rem;
}

html.gutter-ui .pager.next {
  right: 3rem;
}

/* ---- スマホ・タブレット縦（〜1023px）---------------------------------
   ヘッダーで「見開き」を選んだとき。左右の余白（‹ › の場所）はページに回し、
   ‹ › は下の帯に置く。 */
@media (max-width: 1023px) {
  .stage {
    --stage-h: calc(100dvh - 3.6rem - 5rem);
    --stage-w: calc(100vw - 1rem);
    padding: 0.5rem 0.5rem 4.5rem;
  }

  /* 指で押すので PC（2.5rem = 40px）より大きく。iPhone の目安 44pt を超える 48px */
  .pager {
    top: auto;
    bottom: 0.75rem;
    translate: none;
    width: 3rem;
    height: 3rem;
  }

  .pager.prev {
    left: 0.75rem;
  }

  .pager.next {
    right: 0.75rem;
  }

  .pager svg {
    width: 22px;
    height: 22px;
  }
}

/* ---- トップページへ（ロゴ）-------------------------------------------
   サイトの他のページと同じく、ロゴを押すとトップページに戻る。
   ヘッダーレイアウトでは、サイトの他のページのヘッダーと同じく枠や背景を付けずに
   下地に直接置く。スマホ（〜639px）はヘッダー左端にマークだけ、PC のヘッダーでは
   ロゴだけ（幅が足りず、「トップページへ」まで入れるとタイトルが省略される）。
   帯レイアウトでは左の帯の下端に、マークを ‹ › や全画面と同じ丸ボタンに入れ、
   その下に「トップページへ」を小さく添える。横長のロゴを 8rem に縮めると
   文字が読めず、尾だけが目立っていた（2026-10-13）。
   ★ 子要素の display は `.site-logo .xxx` の形で書く。`.site-logo img` より
   弱い指定だと負けて、ロゴとマークの両方が出る。 */
.site-logo {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
  padding: 0.25rem 0.375rem;
  border-radius: 0.5rem;
  color: var(--foreground);
  font-size: 0.75rem;
  text-decoration: none;
  transition: opacity 0.15s, color 0.15s;
}

.site-logo:hover {
  opacity: 0.75;
  color: var(--accent);
}

.site-logo:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.site-logo img {
  display: block;
  height: 1.75rem;
  width: auto;
}

.site-logo .site-logo-mark,
.site-logo .site-logo-label {
  display: none;
}

@media (max-width: 639px) {
  .site-logo .site-logo-full {
    display: none;
  }

  .site-logo .site-logo-mark {
    display: block;
  }
}

/* 帯レイアウト。幅は .gutter と同じ 8rem。左の帯の下端に付ける（本から出る導線
   なので、目次・ページ番号の「本の中の移動」からは離す。app.js 章6c） */
html.gutter-ui .site-logo {
  margin-top: auto;
  flex-direction: column;
  gap: 0.375rem;
  width: 8rem;
  padding: 0.5rem 0.5rem 0.25rem;
  text-align: center;
  color: var(--muted);
}

html.gutter-ui .site-logo:hover {
  opacity: 1;
  color: var(--foreground);
}

html.gutter-ui .site-logo .site-logo-full {
  display: none;
}

/* マークを丸ボタンに。大きさ・色・枠は .pager と同じ */
html.gutter-ui .site-logo .site-logo-mark {
  display: block;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0.5rem;
  object-fit: contain;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 999px;
  transition: border-color 0.15s, background-color 0.15s;
}

html.gutter-ui .site-logo:hover .site-logo-mark {
  border-color: var(--accent);
}

html.gutter-ui .site-logo .site-logo-label {
  display: block;
}

/* ---- ボタンのホバーと押している間 -----------------------------------
   枠線の色が変わるだけでは目立たなかったので、背景にも薄く色を付ける（2026-10-28）。
   押している間はもう一段濃く、押した瞬間に付けて離したら 0.15s で戻す。
   選ばれている側（aria-pressed）と塗りの .pill.primary は自前の色があるので除く。
   ホバーはマウスのある端末だけ。スマホはタップの後にホバーの色が残ることがある */
@media (hover: hover) {
  .pill:not(.primary):hover:not(:disabled),
  .pager:hover:not(:disabled),
  .segmented button:not([aria-pressed="true"]):hover:not(:disabled),
  html.gutter-ui .site-logo:hover .site-logo-mark {
    background-color: var(--btn-hover);
  }
}

.pill:not(.primary):active:not(:disabled),
.pager:active:not(:disabled),
.segmented button:not([aria-pressed="true"]):active:not(:disabled),
html.gutter-ui .site-logo:active .site-logo-mark {
  background-color: var(--btn-press);
  transition-duration: 0s;
}

/* スクロール表示の末尾（スマホ） */
.rail-end[hidden] {
  display: none;
}

.rail-end {
  display: flex;
  justify-content: center;
  /* .rail の下余白 6rem のうち 4rem を使う */
  margin-top: -4rem;
  padding: 0 1rem 4rem;
}

.rail-end .pill {
  text-decoration: none;
}

.rail-end .pill img {
  display: block;
  height: 1.25rem;
  width: auto;
}

/* ---- 矢印キーの案内（app.js 章6d）------------------------------------
   「← キーで前へ」「→ キーで次へ」の2枚。ヘッダーレイアウトではタイトルの
   隣に横並び、帯レイアウトでは ‹ › それぞれの真下に2段で出す。帯は見開きでも
   8rem 残るので、表紙でも見開きでもページに被らない。
   常に出しておく（消す仕組みは app.js 章6d のコメント参照）。 */
.key-hints[hidden] {
  display: none;
}

.key-hints {
  display: flex;
  gap: 0.5rem;
  flex-shrink: 0;
}

/* 押せるものではないので、ボタンと同じ白い札にはしない（2026-10-13）。
   キーの形（kbd）と文字だけを下地に直接置く。 */
.key-hint {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
  margin: 0;
  font-size: 0.75rem;
  /* 常に出しておくもの（app.js 章6d）なので、ボタンより一段薄い色にして
     ‹ › や目次の札より目立たないようにする（2026-10-13） */
  color: var(--muted);
}

.key-hint-keys {
  display: inline-flex;
  gap: 0.25rem;
}

.key-hint kbd {
  font: inherit;
  line-height: 1.4;
  min-width: 1.5rem;
  padding: 0 0.35rem;
  text-align: center;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-bottom: 2px solid rgba(31, 58, 70, 0.3);
  border-radius: 0.25rem;
}

/* 帯レイアウト。入れ物は消して2枚を stage に直接置く。.pager は top: 50% で
   高さ 2.5rem なので、その下端から少し離す。幅は .gutter と同じ 8rem
   （端からの 0.25rem も同じ）で、帯の列に揃える。
   ★ :not([hidden]) が無いと、この指定が .key-hints[hidden] に勝って
   スクロール表示でも出てしまう。 */
html.gutter-ui .key-hints:not([hidden]) {
  display: contents;
}

html.gutter-ui .key-hint {
  position: absolute;
  z-index: 2;
  top: calc(50% + 1.75rem);
  width: 8rem;
  flex-direction: column;
  gap: 0.25rem;
  text-align: center;
}

html.gutter-ui .key-hint.prev {
  left: 0.25rem;
}

html.gutter-ui .key-hint.next {
  right: 0.25rem;
}

/* ---- トップページへ戻る前の確認（app.js 章9b）------------------------ */

.confirm {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  /* 目次のスクリムと同じ色 */
  background: rgba(31, 58, 70, 0.4);
}

.confirm[hidden] {
  display: none;
}

.confirm-card {
  width: min(22rem, 100%);
  padding: 1.25rem 1.5rem;
  border-radius: 0.75rem;
  background: var(--surface);
  box-shadow: var(--sheet-shadow);
}

.confirm-card h2 {
  margin: 0 0 0.25rem;
  font-size: 1rem;
  font-weight: 700;
}

.confirm-note {
  margin: 0 0 1rem;
  font-size: 0.875rem;
  color: var(--muted);
}

.confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
}

/* ---- 読み込み中 / エラー --------------------------------------------- */

.notice {
  max-width: 32rem;
  margin: 4rem auto;
  padding: 1.5rem;
  text-align: center;
  color: var(--muted);
}

.notice[hidden] {
  display: none;
}

/* 起動中（app.js 章11 の reveal まで）。ヘッダー・見開き・帯はまだ組み上がって
   いないので見せず、「読み込んでいます…」だけ出す。display ではなく visibility
   なので、隠れている間も画像とフォントは読み込まれ、見せた瞬間にそろっている。
   以前はヘッダーのレイアウトが先に映り、JSON が届いた瞬間に帯レイアウトへ
   組み替わるのが見えていた（2026-10-14 に指摘あり。index.php 先頭のコメント） */
html.booting body > :not(.notice) {
  visibility: hidden;
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
