/* ==========================================================
   カードストリーム (.cs-*) — 背景を流れるマゼモンカード
   ==========================================================
   「マゼモンのカードの種類はこんなにも多い!」を初見で伝えるための背景演出。
   PCで空いている左右の余白に、カードが**奥行きを持って雑多に**流れる。

   ■ 構成: 1辺につき「奥・中・手前」の3段

   .cs-layer
     └ .cs-col(左/右) … 画面の端からコンテンツ手前までの帯。overflow:hidden
         ├ .cs-track.cs-far   小さい・薄い・ぼけている・遅い
         ├ .cs-track.cs-mid
         └ .cs-track.cs-near  大きい・濃い・はっきり・速い

   3段は**同じ向きに違う速さ**で流れる(パララックス)。
   これが奥行きの主な手がかりになる。左右で向きだけ逆にしている。
   大きさは段ごとに約1.5倍ずつ差を付けている(js の DEPTHS)。

   **段が違うカードどうしは重なってよい**。
   そのぶん横位置を大きく振れるので、以前の「段ごとに横レーンを分ける」
   作りはやめ、1枚ごとに広い範囲から乱数で決めている。
   縦の間隔も1枚ごとに振っているため、きれいな一列にはならない。
   **カードは傾けない**(あくまで垂直)。

   ■ 帯は画面の端に接している

   手前のカードは帯幅に近い大きさなので、「帯の中に完全に収める」条件だと
   横にほとんど振れない。そこで帯を画面の端から始め、
   **画面の端側にだけ少しはみ出してよい**ことにして振れ幅を稼いでいる。
   コンテンツ側は絶対にはみ出させない(js の OUT_RATIO のコメント参照)。

   **【重要】はみ出す端はフェードさせること。**
   overflow:hidden に任せると画面端でカードが直線で切られ、
   「表示がおかしい」ように見える。
   上下と同じように mask で溶かして、画面外へ流れていく見え方にする。

   ■ 【重要】背景側(z-index: -1)に置くこと。コンテンツの上に出さない

   `.bg-datalines` と同じ方針。常時ループする演出をコンテンツに被せると
   文字や画像が読みにくくなる(2026-08-24 に一度やって差し戻した)。
   そのため `.page-light`(白地)のセクションではカードが隠れるが、
   **それは正しい挙動**。実測で背景が透けている割合は
   TOP 99% / 図鑑 100% / マゼモンとは? 21% / コロシアム 18% / 遊べる店舗 0%。

   ■ 絵は1枚のスプライト(**表示サイズの2倍**で持っている)

   `assets/card-stream/cards.webp`(48枚 / 4800×2512 / 約1.4MB)を
   `background-position` でずらして使う。

   **セルは実ピクセルで400×628、表示は200×314。**
   Retina(DPR2)では200pxのカードに400個の実ピクセルが要るため、
   等倍(200px)で持っていた頃は2倍に引き伸ばされて
   絵と文字がにじんでいた(2026-09-09 修正)。
   js が cards.json の pixelRatio で割って background-size を半分にするので、
   **見た目の大きさは変わらない**。
   層ごとに background-size を変えるとスプライトが倍率ぶん別々に
   ラスタライズされてメモリを食うので、大きさは transform: scale() で作る。
   生成は tools/card-stream/build_sprite.py。

   ■ 外すとき

   index.html の <link> と <script> の2行を消して、
   このファイル・js/card-stream.js・assets/card-stream/ を削除するだけ。
   他のCSSに `.cs-` は1つも書いていない。
   ========================================================== */

.cs-layer {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;

  /* スプライトの**表示上の**セル寸法(js が cards.json から入れ直す)。
     cards.json の cellW/cellH は実ピクセル(400×628)で、
     js が pixelRatio(=2)で割ってここに入れる。
     ここに書いてある値は js が動く前の初期値 */
  --cs-cell-w: 200px;
  --cs-cell-h: 314px;

  /* コンテンツ(960px = .zukan-inner)の左右に残る余白 */
  --cs-gutter: calc((100vw - 960px) / 2);
  /* カードを散らす帯の幅。14px はコンテンツとの最低の隙間 */
  --cs-band: min(320px, calc(var(--cs-gutter) - 14px));
  /* 帯は画面の端に接して置く(上の「帯は画面の端に接している」参照) */
  --cs-inset: 0px;

  /* 上下は切りっぱなしにせず、フェードで消す */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 12%, #000 88%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 12%, #000 88%, transparent 100%);

  /* 画面端のフェード幅。帯が狭い画面でも帯の1/3までに収める */
  --cs-fade: min(76px, calc(var(--cs-band) * 0.32));
}

/* 余白が足りない画面では出さない(js側でもDOMを作らない) */
@media (max-width: 1199px) {
  .cs-layer { display: none; }
}

/* 図鑑ページでは出さない。
   `.zukan-inner.dex-inner` は 1000px以上で **1220px幅の2カラム**になるので、
   960px前提で置いたこの帯と重なり、並んでいるカードの裏から
   別のカードが覗いて見える(実測 1440px幅で114pxかぶる)。
   図鑑はそもそもカードを大量に並べるページなので、背景で足す必要もない。

   :has() を使っているのは、ページの出し入れが .page[hidden] の
   付け外しだけで行われており(js/main.js の router)、
   body 側にページ名のクラスが付かないため */
body:has(.page[data-page="dictionary"]:not([hidden])) .cs-layer {
  display: none;
}

.cs-col {
  position: absolute;
  top: 0;
  width: var(--cs-band);
  height: 100%;
  overflow: hidden;
}

/* 画面端側だけフェードさせる。コンテンツ側は帯の端でぴたりと止める
   (そちらはカードがはみ出さないので切れ目が出ない) */
.cs-col-l {
  left: var(--cs-inset);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--cs-fade));
  mask-image: linear-gradient(90deg, transparent 0, #000 var(--cs-fade));
}
.cs-col-r {
  right: var(--cs-inset);
  -webkit-mask-image: linear-gradient(270deg, transparent 0, #000 var(--cs-fade));
  mask-image: linear-gradient(270deg, transparent 0, #000 var(--cs-fade));
}

/* 3段を重ねるので絶対配置。
   中身は同じ並びを2コピー入れてあり、-50% まで動かすと
   ちょうど1周分ずれて継ぎ目なくループする */
.cs-track {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  will-change: transform;
  animation: cs-flow var(--cs-dur, 90s) linear infinite;
  /* 層ごとに開始位置をずらす(js が負の値を入れる)。
     入れないと3層の切り替わりが同時に来て、縞のように見える */
  animation-delay: var(--cs-delay, 0s);
}

/* 右の帯は逆向き(下から上)に流す */
.cs-col-r .cs-track { animation-direction: reverse; }

@keyframes cs-flow {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, -50%, 0); }
}

/* --- 奥行き ---
   小さいものは「薄く・ぼけて・遅い」。この3つを揃えるのが要点で、
   大きさだけ変えても奥行きには見えない。
   速さ(--cs-dur)は js が段ごとに渡す。

   手前は**カードがしっかり読める濃さ**にしてある。
   ここを上げるほど「種類の多さ」は伝わるが、
   コンテンツの裏で気になり始めるので 0.9 を上限の目安にする */
.cs-far  { opacity: 0.28; filter: blur(2px); }
.cs-mid  { opacity: 0.5;  filter: blur(0.8px); }
.cs-near { opacity: 0.9; }

/* カード1枚。大きさと横位置は js が custom property で渡す。
   ・--cs-s  倍率(奥行きの段)
   ・--cs-dx 横位置(1枚ごとの乱数)
   縦の間隔は js が margin-bottom を直接入れる
   (倍率で見た目の高さが変わるため、CSSだけでは決められない)

   **傾きは付けない**(カードはあくまで垂直)。
   以前は ±5° 振っていたが、外接矩形が広がるぶん横に振れる幅が減るうえ、
   「整列していない感じ」は横位置のばらつきだけで足りる */
.cs-card {
  width: var(--cs-cell-w);
  height: var(--cs-cell-h);
  flex: 0 0 auto;
  border-radius: 5px;
  background-image: var(--cs-sheet);
  /* 【重要】ここは等倍のまま。層ごとに変えるとスプライトが
     倍率ぶん別々にラスタライズされる(冒頭のコメント参照) */
  background-size: var(--cs-sheet-w) var(--cs-sheet-h);
  background-repeat: no-repeat;
  background-position: var(--cs-bx) var(--cs-by);
  transform: translateX(var(--cs-dx, 0px)) scale(var(--cs-s, 1));
  box-shadow:
    0 0 0 1px rgba(157, 252, 255, 0.22),
    0 0 16px rgba(0, 169, 255, 0.26);
}

/* タブが裏に回っている間は止める(js が付け外しする) */
.cs-paused .cs-track { animation-play-state: paused; }

/* 動きを減らす設定のときは流さない。
   ただしカード自体は出す —— 「種類が多い」ことは静止でも伝わるため */
@media (prefers-reduced-motion: reduce) {
  .cs-track { animation: none; }
}
