/* ================================================
   カスタムプロパティ
   後続のスクロールアニメーション系スニペット
   （stagger / count-up 等）が同じトークンで
   出現演出の距離・時間を揃えられるよう、ここで
   一元管理する。
   ================================================ */
:root {
  --fade-color-text:        #2b2b2b;
  --fade-color-text-muted:  #555;
  --fade-color-border:      #e0e0e0;
  --fade-color-bg:          #ffffff;
  --fade-color-accent:      #3ba9e0;

  --fade-radius:            8px;
  --fade-card-padding-y:    24px;
  --fade-card-padding-x:    24px;

  /* 出現演出のトークン
     --fade-distance: 初期位置のずらし量（スライド距離）
     --fade-duration: フェード/スライドの所要時間
     --fade-easing:   減速して止まる自然なイージング */
  --fade-distance:          24px;
  --fade-duration:          0.6s;
  --fade-easing:            cubic-bezier(0.16, 1, 0.3, 1);
}

/* ================================================
   ベースリセット（デモページ用）
   ================================================ */
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue",
    "Hiragino Sans", "Noto Sans JP", sans-serif;
  color: var(--fade-color-text);
  background-color: #fafafa;
  line-height: 1.7;
}

code {
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  font-size: 0.92em;
  padding: 0.1em 0.35em;
  background-color: #eef0f3;
  border-radius: 4px;
}

/* ================================================
   l-main / p-section: デモページのレイアウト
   ================================================ */
.l-main {
  max-width: 720px;
  margin-inline: auto;
  padding: 40px 20px;
}

.p-section__title {
  font-size: 22px;
  font-weight: 700;
  margin: 0 0 16px;
}

.p-section__text {
  margin: 0 0 24px;
  color: var(--fade-color-text-muted);
}

@media (min-width: 768px) {
  .p-section__title {
    font-size: 28px;
  }
}

/* ================================================
   c-fade: 出現演出するカードのリスト
   縦に並べ、十分なスクロール量を確保することで
   デモページ上で出現タイミングを確認できる。
   ================================================ */
.c-fade {
  display: flex;
  flex-direction: column;
  gap: 24px;

  /* スクロールで出現する様子を確認できるよう、
     ビューポートより縦に長くなる余白を確保する。 */
  padding-bottom: 60vh;
}

/* ================================================
   c-fade__item: 出現演出の対象カード
   ================================================ */
.c-fade__item {
  padding: var(--fade-card-padding-y) var(--fade-card-padding-x);
  background-color: var(--fade-color-bg);
  border: 1px solid var(--fade-color-border);
  border-left: 4px solid var(--fade-color-accent);
  border-radius: var(--fade-radius);
}

/* ================================================
   c-fade__row: カードを横一列に並べるラッパー
   モバイル幅では縦積み、768px 以上で 3 列に切り替える。
   遅延差（data-fade-delay）の効果を「同じ方向・同じ位置関係」で
   見比べられるよう、行内のカードは出現方向を揃える前提で使う。
   ================================================ */
.c-fade__row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
}

@media (min-width: 768px) {
  .c-fade__row {
    grid-template-columns: repeat(3, 1fr);
  }
}

.c-fade__heading {
  margin: 0 0 8px;
  font-size: 18px;
  font-weight: 700;
}

.c-fade__text {
  margin: 0;
  color: var(--fade-color-text-muted);
}

/* ================================================
   出現演出の本体
   プログレッシブエンハンスメント:
   - JS が動く環境では html.js が付与される。
     このときだけ初期状態を「透明＋ずらした位置」にし、
     .is-visible が付くまで隠す。
   - JS 無効・このスクリプトが届かない環境では html.no-js の
     ままになり、下記ルールが効かないため、要素は最初から
     通常表示される（コンテンツが消えない）。
   ================================================ */
.js .c-fade__item[data-fade-in] {
  opacity: 0;
  transform: translateY(var(--fade-distance));
  transition:
    opacity var(--fade-duration) var(--fade-easing),
    transform var(--fade-duration) var(--fade-easing);
  /* 不可視の間はクリック/フォーカス対象にしない（透明な要素の誤操作を防ぐ）。
     レイアウトは確保したまま、表示後に pointer-events を auto へ戻す。 */
  pointer-events: none;
  will-change: opacity, transform;
}

/* 出現方向の切り替え（初期位置のずらし方向だけを変える） */
.js .c-fade__item[data-fade-direction="down"] {
  transform: translateY(calc(var(--fade-distance) * -1));
}

.js .c-fade__item[data-fade-direction="left"] {
  transform: translateX(calc(var(--fade-distance) * -1));
}

.js .c-fade__item[data-fade-direction="right"] {
  transform: translateX(var(--fade-distance));
}

/* 純フェード（動きなし）: transform を一切当てず、opacity だけで出現させる。
   初期状態は opacity: 0 のみ。translate を打ち消すのではなく最初から付与
   しないため、transition も opacity だけにして無駄な合成を避ける。 */
.js .c-fade__item[data-fade-direction="none"] {
  transform: none;
  transition: opacity var(--fade-duration) var(--fade-easing);
  will-change: opacity;
}

/* ビューポート進入後に付与される最終状態
   どの方向指定でも translate を 0 に戻し、本来の位置へ。
   will-change はワンショット表示の都合上、出現後はもう不要になる。
   CSS 側の最終状態で auto に戻すことで、表示後も合成レイヤーが残り
   続けるのを防ぐ（要素数が多いページでのメモリ常駐を回避）。
   状態管理を JS に分散させず .is-visible に集約できるため、後続の
   出現演出系スニペットも同じ作法で踏襲しやすい。 */
.js .c-fade__item.is-visible {
  opacity: 1;
  transform: translate(0, 0);
  /* 表示されたら操作可能に戻す。 */
  pointer-events: auto;
  will-change: auto;
}

/* ================================================
   prefers-reduced-motion: 動きを減らす設定への配慮
   前庭機能障害等で OS の「視差効果を減らす」を有効に
   しているユーザーには、フェード/スライドを行わず
   即時に最終状態（表示）で見せる。
   出現演出を中核とする本シリーズでは、全パターン共通の
   前提として軸となるこのスニペットで先行導入する。
   ================================================ */
@media (prefers-reduced-motion: reduce) {
  .js .c-fade__item[data-fade-in] {
    opacity: 1;
    transform: none;
    transition: none;
    /* 即時表示されるため、表示と同時に操作可能にする
       （可視なのに操作不可になる不整合を防ぐ）。 */
    pointer-events: auto;
    will-change: auto;
  }
}
