/* ===== 初期状態は「表示済み」。JSが動く環境でだけ隠す ===== */
.js .r { opacity: 0; transform: translateY(8px); }
.js .r.is-in {
  animation: rUp .55s cubic-bezier(.2, .8, .2, 1) both;
  animation-delay: var(--d, 0s);
}
@keyframes rUp { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* 見出し：行ごとにマスクの下から立ち上がる */
.mask { display: block; overflow: hidden; }
.js .mask > .line { display: block; transform: translateY(105%); }
.js .mask > .line.is-in {
  animation: rRise .75s cubic-bezier(.65, 0, .35, 1) both;
  animation-delay: var(--d, 0s);
}
@keyframes rRise { from { transform: translateY(105%); } to { transform: none; } }

/* 画像：左からワイプで開く。`.r` と併記されたとき source order ではなく
   詳細度で勝てるよう `.r--wipe` を2回書く（後続CSSの読み込み順に左右されない）。 */
.js .r--wipe.r--wipe { opacity: 1; transform: none; clip-path: inset(0 0 0 100%); }
.js .r--wipe.is-in {
  animation: rWipe .9s cubic-bezier(.65, 0, .35, 1) both;
  animation-delay: var(--d, .15s);
}
@keyframes rWipe { from { clip-path: inset(0 0 0 100%); } to { clip-path: inset(0 0 0 0); } }

/* 罫線：横に伸びる。詳細度の理由は .r--wipe と同じ。 */
.js .r--rule.r--rule { opacity: 1; transform: scaleX(0); }
.js .r--rule.is-in {
  animation: rRule .8s cubic-bezier(.65, 0, .35, 1) both;
  animation-delay: var(--d, .1s);
}
@keyframes rRule { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* ===== スタッキング（仕様書 §7.2） ===== */
.stack { position: sticky; top: 0; box-shadow: 0 -18px 40px rgba(0, 0, 0, .55); }

/* ===== ピン留めスクラブ（仕様書 §7.3） =====
   JS無効時は3枚のコピーが縦に並んで全部読める状態にしておく。
   重ね合わせ（grid-area: 1/1）と非表示は .js が付いたときだけ適用する。 */
.scrub { position: relative; }
/* JS無効時は普通のセクションとして縦に流す。height/overflow を素で当てると
   3枚が重なったまま切り落とされ、コンテンツが読めなくなる。 */
.scrub__stick { display: grid; align-content: center; }
.js .scrub__stick {
  position: sticky; top: 0;
  height: 100svh; min-height: 560px;
  overflow: hidden;
}
.scrub__cap { grid-area: auto; transition: opacity .3s, transform .3s; }
.js .scrub__cap { grid-area: 1 / 1; }
/* 見た目だけ切り替え、アクセシビリティツリーからは外さない。aria-hidden で
   隠すと、見出しリストやローターで移動する利用者に3枚中1枚しか存在せず、
   scroll を発火させずに移動するため残り2枚へ到達する手段が無くなる。 */
.js .scrub__cap[data-active="false"] { opacity: 0; transform: translateY(8px); transition-delay: 0s; }
.js .scrub__cap[data-active="true"] { opacity: 1; transform: none; transition-delay: .14s; }
.scrub__bar { height: 1px; background: var(--line); }
.scrub__bar > i { display: block; height: 100%; width: 0; background: var(--fg); }

/* ===== reduced-motion：全停止し最終状態を即時表示 ===== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
  .js .r,
  .js .mask > .line,
  .js .r--wipe,
  .js .r--rule {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
  }
  .stack { position: static; box-shadow: none; }
  /* `.js .scrub__stick` の方が詳細度が高いので !important が要る。 */
  .scrub { height: auto !important; }
  .scrub__stick { position: static !important; height: auto !important; overflow: visible !important; }
  .js .scrub__cap { grid-area: auto; opacity: 1 !important; transform: none !important; }
  .js .scrub__cap[data-active="false"] { opacity: 1 !important; transform: none !important; }
  /* 絵は3枚重ねなので、全部見せると重なって潰れる。1枚目だけ残す。
     scrub.js は reduced-motion のとき何もしないので data-active は初期値のまま。 */
  .scrub__media { position: static; aspect-ratio: auto; max-height: none; }
  .scrub__media img { position: static; opacity: 1 !important; transform: none !important; }
  .scrub__media img:not(:first-child) { display: none; }
}
