/* ================================================================
   gravity-token.css
   Gravity Token カードの 3D 構造用スタイル。
   スコープは必ず .membership-page .gravityToken 配下に限定し、
   他ページへ波及しない設計。視覚変形は JS (gravity-token.js) が
   CSS 変数で注入する --gt-rx / --gt-ry / --gt-rz / --gt-float を
   使って合成される。
================================================================ */

/* ラッパ: membership-page 内にだけ効くように明示スコープ */
.membership-page .gravityToken {
  /* 初期値は intro 演出の開始点に合わせる (裏向き・-20px 浮遊下・縮小状態)。
     これにより、JS が動き出すまでの 1 フレームでも「0°で表がチラッ」
     と見えるちらつきを防ぐ。intro 後は JS が 0deg / 1.0 に収束させる。 */
  --gt-rx: 0deg;
  --gt-ry: -540deg;
  --gt-rz: 0deg;
  --gt-float: -20px;
  --gt-scale: 0.38;

  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* カーソルがカード本体(ボリューム)に触れたら grab、ドラッグで grabbing */
  cursor: default;
  -webkit-tap-highlight-color: transparent;
}

/* 遠近法ステージ: 子 (.gravityToken__card) に対して透視投影 */
.membership-page .gravityToken__stage {
  position: relative;
  width: 100%;
  height: 100%;
  perspective: 1400px;
  perspective-origin: 50% 50%;
  /* カードの描画をドラッグ時以外フルで受け取らない(ページスクロール優先) */
  pointer-events: auto;
}

/* カード本体 (表裏を preserve-3d で束ねる) */
.membership-page .gravityToken__card {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  inset: 0;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  -webkit-transform-style: preserve-3d;
  /* 合成 transform:
     scale: 全体の拡大縮小 (intro 時のみ 0.82 → 1.0)
     float: 上下の浮遊(px)
     rx/ry: JS が書き換える軸回転
     rz: わずかな左右ティルト */
  transform:
    scale(var(--gt-scale))
    translate3d(0, var(--gt-float), 0)
    rotateZ(var(--gt-rz))
    rotateX(var(--gt-rx))
    rotateY(var(--gt-ry));
  will-change: transform;
  user-select: none;
  -webkit-user-select: none;
  /* SP ドラッグ: pan-y だと縦方向タッチがブラウザのページスクロールに奪われ、
     card の pointer events に届かない (= ドラッグできない)。
     none にすることで縦横どちらの方向のドラッグも回転インタラクションに使える。
     代償として「カード上に指が乗っているとページスクロールできない」が、
     カードのサイズ的に支障は小さい。 */
  touch-action: none;
}

/* .is-grabbing 中はドラッグ中の慣性遷移を切る */
.membership-page .gravityToken.is-grabbing .gravityToken__card {
  cursor: grabbing;
}

/* 表裏の共通属性 */
.membership-page .gravityToken__face {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  /* 背景色 (--bg: #262e38) とほぼ同じトーンに合わせ、
     カードが独立した「黒い板」ではなく「場の中から静かに現れる」質感に。
     グラデーションは極めて弱く、右上から左下へ僅かに陰る程度に留める。 */
  background:
    radial-gradient(
      ellipse at 35% 25%,
      rgba(48, 56, 68, 0.50) 0%,
      rgba(38, 46, 56, 0.55) 55%,
      rgba(32, 40, 50, 0.60) 100%
    );
  border-radius: 14px;
  /* 影は極めて弱く。黒い床に置かれた物体感を出さず、
     背景に馴染むレベルの微細な浮遊感だけを残す。 */
  box-shadow:
    inset 0 0 0 1px rgba(214, 224, 234, 0.05),
    0 18px 40px -24px rgba(0, 0, 0, 0.35);
  /* カード SVG の細線が滲まないように */
  -webkit-font-smoothing: antialiased;
}

.membership-page .gravityToken__face--front {
  transform: translateZ(0.1px);
}
.membership-page .gravityToken__face--back {
  transform: rotateY(180deg) translateZ(0.1px);
}

/* カーソルをカードに近づけたときの hover クラス
   (JS が .is-hovering を付けて、CSS で cursor を調整) */
.membership-page .gravityToken.is-hovering .gravityToken__card {
  cursor: grab;
}

/* 初回登場: membership.js のアニメ管理対象 (.membershipToken__frame) 側で
   opacity / transform を扱うため、ここでは触らない。
   ただし触れたときに bg の滑らかさを損ねないよう will-change は必要最小限。 */

/* ============================================================
   内部信号演出 (gtSignal / gtAxis / gtRipple / gtBackRings)

   Token 全体が静かに生きている気配を作るためのレイヤー。
   - 色は既存ラインと同じ rgba(214,224,234,...) 系の寒色ホワイト
   - 派手な発光 (強い blur/ color) は使わず、opacity と dashoffset の
     微小な変化だけで「信号が通り過ぎた」印象を作る
   - 強弱: L字 > 十字 > 中央波紋 > 裏面リング (裏面表示時のみ目立つ)
   ============================================================ */

/* 共通: 光の走る trace の初期状態。
   JS 側の animateTrace が dasharray を実長ベースで設定 + dashoffset を
   rAF で直接書き込むことで、線分の始点から終点まで確実に光が走る。
   初期は opacity=0 で見えず、発火時のみ表示される。 */
.gtSignal__trace,
.gtAxis__trace {
  fill: none;
  stroke: rgba(220, 232, 244, 0.95);
  stroke-width: 1.1;
  stroke-linecap: round;
  opacity: 0;
  pointer-events: none;
  /* Chromium の 3D 描画コンテキスト下で短い path の描画バッファが
     省略されることがあるため、vector-effect でバッファ確保を強制。 */
  vector-effect: non-scaling-stroke;
}

/* 表面中央サークル: 5 重の波紋。
   中央サークル (r=62) から外へリングが一斉に拡大・透明化。
   各リングは最終スケールが少しずつ異なり、外側ほど遠くまで広がる。 */
.gtRipple {
  transform-origin: 480px 280px;
  transform-box: view-box;
}
.gtRipple__wave {
  transform-origin: 480px 280px;
  transform-box: view-box;
}
.gtRipple.is-active .gtRipple__wave--0 { animation: gtRippleOut0 2.4s cubic-bezier(0.22, 0, 0.36, 1) forwards; }
.gtRipple.is-active .gtRipple__wave--1 { animation: gtRippleOut1 2.6s cubic-bezier(0.22, 0, 0.36, 1) 0.12s forwards; }
.gtRipple.is-active .gtRipple__wave--2 { animation: gtRippleOut2 2.8s cubic-bezier(0.22, 0, 0.36, 1) 0.24s forwards; }
.gtRipple.is-active .gtRipple__wave--3 { animation: gtRippleOut3 3.0s cubic-bezier(0.22, 0, 0.36, 1) 0.36s forwards; }
.gtRipple.is-active .gtRipple__wave--4 { animation: gtRippleOut4 3.2s cubic-bezier(0.22, 0, 0.36, 1) 0.48s forwards; }

@keyframes gtRippleOut0 {
  0%   { transform: scale(1);   stroke: rgba(214,224,234,0.55); }
  70%  {                         stroke: rgba(214,224,234,0.08); }
  100% { transform: scale(2.2); stroke: rgba(214,224,234,0);    }
}
@keyframes gtRippleOut1 {
  0%   { transform: scale(1);   stroke: rgba(214,224,234,0.50); }
  70%  {                         stroke: rgba(214,224,234,0.07); }
  100% { transform: scale(2.9); stroke: rgba(214,224,234,0);    }
}
@keyframes gtRippleOut2 {
  0%   { transform: scale(1);   stroke: rgba(214,224,234,0.45); }
  70%  {                         stroke: rgba(214,224,234,0.06); }
  100% { transform: scale(3.7); stroke: rgba(214,224,234,0);    }
}
@keyframes gtRippleOut3 {
  0%   { transform: scale(1);   stroke: rgba(214,224,234,0.40); }
  70%  {                         stroke: rgba(214,224,234,0.05); }
  100% { transform: scale(4.6); stroke: rgba(214,224,234,0);    }
}
@keyframes gtRippleOut4 {
  0%   { transform: scale(1);   stroke: rgba(214,224,234,0.35); }
  70%  {                         stroke: rgba(214,224,234,0.04); }
  100% { transform: scale(5.6); stroke: rgba(214,224,234,0);    }
}

/* ---- 裏面同心円: 中心→外へ時間差でパルス伝播 (常時ループ) ----
   各リングは普段 opacity=0、animation で一瞬明るくなって消える。
   delay を 0.07 秒ずつずらして、中心→外へ素早く伝播。
   最外リング (--5) の発火と同時に、そこからさらに外へ広がる burst 3 重が
   時間差で出て、「一番外の円から波が重なって放たれた」印象を作る。
   1 サイクル 5 秒 (伝播 ~0.8 秒 + burst ~1.5 秒 + 休止 ~2.7 秒)。 */
.gtBackRings__pulse {
  stroke: rgba(220, 232, 244, 0.80);
  opacity: 0;
  animation: gtBackRingPulse 5s ease-in-out infinite;
}
.gtBackRings__pulse--0 { animation-delay: 0.00s; }
.gtBackRings__pulse--1 { animation-delay: 0.07s; }
.gtBackRings__pulse--2 { animation-delay: 0.14s; }
.gtBackRings__pulse--3 { animation-delay: 0.21s; }
.gtBackRings__pulse--4 { animation-delay: 0.28s; }
.gtBackRings__pulse--5 { animation-delay: 0.35s; }

@keyframes gtBackRingPulse {
  0%    { opacity: 0;    }
  4%    { opacity: 0.68; }
  14%   { opacity: 0.30; }
  22%   { opacity: 0;    }
  100%  { opacity: 0;    }
}

/* burst: 最外リング発火 (0.35s) と同時に r=240 からさらに外へ広がる。
   3 重の波が 0.12 秒ずつ時間差で発動し、重なりながら外へ。
   これで「一番外の円から連続した波が解き放たれる」印象を作る。 */
.gtBackRings__burst {
  stroke: rgba(220, 232, 244, 0.70);
  stroke-width: 0.6;
  opacity: 0;
  transform-origin: 480px 280px;
  transform-box: view-box;
  animation: gtBackRingBurst 5s ease-out infinite;
}
.gtBackRings__burst--0 { animation-delay: 0.35s; }
.gtBackRings__burst--1 { animation-delay: 0.47s; }
.gtBackRings__burst--2 { animation-delay: 0.59s; }

@keyframes gtBackRingBurst {
  0%    { transform: scale(1);    opacity: 0;    }
  4%    { transform: scale(1.05); opacity: 0.65; }
  30%   {                          opacity: 0.15; }
  40%   { transform: scale(2.0);  opacity: 0;    }
  100%  { transform: scale(2.0);  opacity: 0;    }
}

/* reduced-motion: すべての内部信号演出を停止 */
@media (prefers-reduced-motion: reduce) {
  .gtSignal__trace,
  .gtAxis__trace,
  .gtRipple__wave,
  .gtBackRings__pulse,
  .gtBackRings__burst {
    animation: none !important;
  }
}

/* ============================================================
   SP (max-width: 768): GT カードが縮小描画されるため、
   PC base の stroke-width: 1.1 だと相対的に太く見える。
   SP のみ少し細く調整して、 PC と同じ視覚太さ感に揃える。
   (animation 速度は gravity-token.js 側で SP 用に伸ばしている)
   ============================================================ */
@media (max-width: 768px) {
  .gtSignal__trace,
  .gtAxis__trace {
    stroke-width: 0.85;
  }
}