/* ============================================================
   NET/YOU — 派手なエフェクト（全ページで読み込む。2026-09-27 採用）
   FX LAB で試した11個のうち、「スクロールで傾く」「矢印の磁石」以外の9個。
   試作（ON/OFF パネル付き）は planning/design/archive/prototype-lab/songs-fx.html。
   色は既存の3色（シアン / マゼンタ / 蛍光イエロー）だけを使う。
   ============================================================ */

:root { --fx-c: #00e5ff; --fx-p: #ff2e9a; --fx-y: #f7ff3d; }

/* ---------- 1. 奥に流れるワイヤーフレームの床（Y2K のグリッド） ---------- */
/* 2026-10-24 変更（スマホで端末が熱くなる、とユーザー報告）: 床の流れを background-position の動きから transform の動きに替えた。
   background-position は毎フレーム画面いっぱいの床を描き直す（GPU に任せられない）。transform なら描いた床をずらすだけで済む。
   床は奥に向かって 60px（線1本分）ずらして戻すのを繰り返す。ずらしたぶん地平線より上にはみ出す端は clip-path で切る。
   切るのは床の箱（.fx-floor。fx.js が .fx-grid の中に作る）だけ。地平線の光（.fx-grid::after）は上にもにじむので切らない */
.fx-grid {
  display: block; position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden;
}
.fx-floor {
  position: absolute; inset: 0; overflow: hidden;
  perspective: 320px; perspective-origin: 50% 38%;
  clip-path: inset(45% 0 0 0);
}
/* 2026-10-24 変更（スマホ実機で格子が点滅する、とユーザー報告）: 床の奥行きを 140%（画面の高さ×1.4）から 330px にした。
   perspective 320px・72度の傾きだと、床は手前 336px（320 ÷ sin72°）でカメラの位置に届き、その先はカメラの後ろに回る。
   画面に映るのは手前およそ 260px までで、残りは見えないままカメラの後ろにあった。止まっているうちは問題が出なかったが、
   動かすとカメラをまたぐ部分の描き方がスマホの GPU で毎フレーム揺れて点滅していた（PC では出ない）。
   見えている部分の濃さが変わらないよう、透けていくグラデーションは前と同じ長さ（画面の高さ×1.4 の 70%）にする */
.fx-floor::before {
  content: ""; position: absolute; left: -50%; right: -50%; top: 45%; height: 330px;
  transform: rotateX(72deg); transform-origin: top;
  background:
    linear-gradient(#00e5ff40 1px, transparent 1px) 0 0 / 60px 60px,
    linear-gradient(90deg, #ff2e9a33 1px, transparent 1px) 0 0 / 60px 60px;
  mask-image: linear-gradient(#000 0%, transparent 70%);
  mask-size: 100% 140vh; mask-repeat: no-repeat;
  animation: fx-floor 2.4s linear infinite;
  will-change: transform;
}
.fx-grid::after {           /* 地平線の光 */
  content: ""; position: absolute; left: 0; right: 0; top: 45%; height: 2px;
  background: linear-gradient(90deg, transparent, var(--fx-p) 30%, var(--fx-c) 70%, transparent);
  box-shadow: 0 0 24px 4px #ff2e9a55;
}
@keyframes fx-floor { from { transform: rotateX(72deg) translateY(-60px); } to { transform: rotateX(72deg) translateY(0); } }
.route-stage { position: relative; z-index: 1; }
.catalogue-page { background: #050505d9; }
/* 楽曲一覧以外のページも、見出しの下（本文の節）は同じ暗さで床の線を沈める（2026-10-24 ユーザー「線の主張が強く本文が見づらい」）。
   .page-block は左右に余白（margin 0 9vw）があるので、影と clip-path で画面の端まで塗る */
.page-block { background: #050505d9; box-shadow: 0 0 0 100vmax #050505d9; clip-path: inset(0 -100vmax); }

/* ---------- 2. 見出しの常時 RGB ずれ＋スキャン帯 ---------- */
.page-heading-glitch h1 { position: relative; }
.page-heading-glitch .glitch-channel { opacity: .85; mix-blend-mode: screen; }
.page-heading-glitch .glitch-cyan { animation: fx-rgb-c 3.2s steps(1) infinite; }
.page-heading-glitch .glitch-magenta { animation: fx-rgb-p 2.7s steps(1) infinite; }
@keyframes fx-rgb-c {
  0%, 100% { transform: translate(-4px, 0); clip-path: inset(0 0 0 0); }
  12% { transform: translate(-14px, 2px); clip-path: inset(10% 0 58% 0); }
  14% { transform: translate(6px, -1px); clip-path: inset(62% 0 12% 0); }
  16% { transform: translate(-4px, 0); clip-path: inset(0 0 0 0); }
  71% { transform: translate(-22px, 0); clip-path: inset(40% 0 44% 0); }
  73% { transform: translate(-4px, 0); clip-path: inset(0 0 0 0); }
}
@keyframes fx-rgb-p {
  0%, 100% { transform: translate(4px, 0); clip-path: inset(0 0 0 0); }
  33% { transform: translate(16px, -2px); clip-path: inset(22% 0 50% 0); }
  35% { transform: translate(4px, 0); clip-path: inset(0 0 0 0); }
  82% { transform: translate(-10px, 1px); clip-path: inset(70% 0 4% 0); }
  84% { transform: translate(4px, 0); clip-path: inset(0 0 0 0); }
}
.page-intro { position: relative; overflow: hidden; }
.page-intro::after {     /* 上から下へ走る光の帯 */
  /* 2026-10-24 変更: top を動かすと毎フレーム配置の計算と描き直しが走るので、transform で動かす。
     帯（高さ 90px）を見出しの枠いっぱいの要素の真ん中に描き、枠の高さの半分＋45px ずつ上下にずらす（前と同じ、上の外から下の外へ） */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(transparent, #00e5ff18 45%, #00e5ff55 50%, #00e5ff18 55%, transparent) center / 100% 90px no-repeat;
  transform: translateY(calc(-50% - 45px));
  animation: fx-sweep 4.5s cubic-bezier(.5, 0, .5, 1) infinite;
  will-change: transform;
}
@keyframes fx-sweep { 0% { transform: translateY(calc(-50% - 45px)); } 60%, 100% { transform: translateY(calc(50% + 45px)); } }

/* ---------- 3. 曲名が流れるティッカー ---------- */
.fx-ticker {
  display: block; overflow: hidden; white-space: nowrap; border-block: 1px solid var(--fx-p);
  background: #000; font: 400 13px/1 "Archivo Black", "Noto Sans JP", sans-serif; letter-spacing: .04em;
  padding: 11px 0; position: relative; z-index: 2;
}
.fx-ticker-track { display: inline-flex; gap: 38px; animation: fx-ticker 38s linear infinite; }
.fx-ticker span { color: #fff; }
.fx-ticker span:nth-child(3n+1)::before { content: "✦ "; color: var(--fx-c); }
.fx-ticker span:nth-child(3n+2)::before { content: "✦ "; color: var(--fx-p); }
.fx-ticker span:nth-child(3n)::before { content: "✦ "; color: var(--fx-y); }
.fx-ticker:hover .fx-ticker-track { animation-play-state: paused; }
@keyframes fx-ticker { to { transform: translateX(-50%); } }

/* ---------- 4. リストのスポットライト（カーソルの位置が光る） ---------- */
.song-list { position: relative; }
.song-list::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 0; opacity: 0; transition: opacity .3s;
  background: radial-gradient(420px circle at var(--fx-mx, 50%) var(--fx-my, 50%), #00e5ff1f, #ff2e9a12 40%, transparent 70%);
}
.song-list:hover::before { opacity: 1; }
.song-row { position: relative; z-index: 1; }

/* ---------- 5. 行のホバー: ネオン枠・色帯・スキャン ---------- */
.song-row { position: relative; overflow: hidden; transition: opacity .75s var(--m-ease), background .2s, transform .25s cubic-bezier(.2,.85,.2,1), box-shadow .25s; }
.song-row.cyan   { --row: var(--fx-c); }
.song-row.pink   { --row: var(--fx-p); }
.song-row.yellow { --row: var(--fx-y); }
.song-row::after {       /* 左端から伸びる色の帯 */
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--row);
  box-shadow: 0 0 18px var(--row); transform: scaleY(0); transform-origin: top; transition: transform .25s;
}
.song-list .song-row.song-row:hover { transform: translateX(10px); background: #0d0d0d; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--row) 45%, transparent), 0 0 34px -10px var(--row); }
.song-row:hover::after { transform: scaleY(1); }
.song-row:hover h2 span { text-shadow: -2px 0 var(--fx-c), 2px 0 var(--fx-p); }
.song-row .fx-scan {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 30%, color-mix(in srgb, var(--row) 22%, transparent) 50%, transparent 70%);
  transform: translateX(-100%);
}
.song-row:hover .fx-scan { animation: fx-row-scan .55s cubic-bezier(.3,.7,.3,1) both; }
@keyframes fx-row-scan { to { transform: translateX(100%); } }

/* ---------- 6. 絞り込み時のグリッチ入れ替え ---------- */
.song-row.fx-glitch-in { animation: fx-glitch-in .42s steps(6, end) both; animation-delay: var(--fx-d, 0ms); }
@keyframes fx-glitch-in {
  /* 2026-10-24: filter（hue-rotate）を外した。filter の変化は毎回描き直しになり、行が多いと重い */
  0%   { opacity: 0; clip-path: inset(0 100% 0 0); transform: translateX(-24px); }
  30%  { opacity: 1; clip-path: inset(0 40% 0 0); transform: translateX(14px) skewX(-12deg); }
  55%  { clip-path: inset(30% 0 20% 0); transform: translateX(-8px); }
  80%  { clip-path: inset(0 0 0 0); transform: translateX(3px); }
  100% { opacity: 1; clip-path: none; transform: none; }
}
.filters button.active { box-shadow: 0 0 0 1px var(--fx-c), 0 0 22px -4px var(--fx-c); }

/* ---------- 7. クリックの衝撃波 ---------- */
.fx-ring {
  position: fixed; z-index: 9000; pointer-events: none; width: 20px; height: 20px; margin: -10px 0 0 -10px;
  border-radius: 50%; border: 2px solid var(--fx-c); box-shadow: 0 0 18px var(--fx-c), inset 0 0 12px var(--fx-p);
  animation: fx-ring .6s cubic-bezier(.1,.7,.3,1) forwards;
}
.fx-ring.b { border-color: var(--fx-p); animation-delay: .07s; box-shadow: 0 0 18px var(--fx-p); }
@keyframes fx-ring { from { transform: scale(0); opacity: 1; } to { transform: scale(26); opacity: 0; } }

/* ---------- 8. 検索語のハイライトと入力のパルス ---------- */
.search-box { transition: box-shadow .15s; }
.search-box.fx-pulse { box-shadow: 0 0 0 1px var(--fx-y), 0 0 26px -6px var(--fx-y); }
mark.fx-hit { background: var(--fx-y); color: #000; padding: 0 .08em; box-shadow: 0 0 12px #f7ff3d88; }

/* ---------- 9. カーソルの残像 ---------- */
.fx-trail {
  position: fixed; z-index: 8999; pointer-events: none; width: 6px; height: 6px; margin: -3px 0 0 -3px;
  background: var(--fx-c); box-shadow: 0 0 10px var(--fx-c); animation: fx-trail .5s linear forwards;
}
.fx-trail.p { background: var(--fx-p); box-shadow: 0 0 10px var(--fx-p); }
@keyframes fx-trail { to { transform: scale(0) translateY(10px); opacity: 0; } }

/* 動きを減らす設定の人には、動くものを全部止める */
@media (prefers-reduced-motion: reduce) {
  .fx-grid, .fx-ring, .fx-trail { display: none !important; }
  .fx-floor::before, .fx-ticker-track, .page-intro::after,
  .page-heading-glitch .glitch-channel, .song-row.fx-glitch-in, .fx-scan { animation: none !important; }
}
@media (max-width: 800px) {
  .song-list .song-row.song-row:hover { transform: none; }
}
