/* タロット pick 体験 (#458 / C-2+C-3 後半、所作 #467 / C-5)。
 *
 * - .card-fan: 伏せ札の扇。各札は単一 form の submit button で、--i (0 起点 index) と
 *   --fan-size から CSS だけで扇状に配置する (JS 不要)。裏絵柄 (#606) は占い師固有の SVG 資産で、
 *   扇が --card-back で渡し全札が継承する (解決は Sortis::Menu::CardBacks)。
 *   - --entrance (#467 / 段階化 #854): 到達描画にだけ server が付ける。ひと山でシャッフル →
 *     カットの見得を切ってから扇へ開く CSS-only の所作 (JS 無効でも動く)。
 *   - --drawing / .card-fan__card--drawing (#467): 選んだ札の抜き出し所作 (card-fan
 *     Stimulus controller が付け、所作の後に form submit する)。
 * - .spread-board (#467): spread 盤面。めくった札は定位置の枠 (位置ラベル付き)、未 pick は
 *   破線の空き枠。one_oracle は 1 枠、three_card は 3 枠。
 * - .card-pick-card: めくった札。大アルカナ (--major) は金色のグロー、逆位置 (--reversed) は
 *   反転フレームで強調する (判定は draw 結果の arcana / orientation のみ)。
 * - .card-flip (#606): 新規開示 (--revealing) の枠だけ実裏面 (.card-flip__back) を表に重ね、
 *   preserve-3d + backface-visibility で裏 → 表を 180° 返す。裏面は演出中の枠にしか出ない。
 * - [data-ritual-step] (#854): フリップの後に「位置の意味 → 出たもの → カードの言葉」を
 *   一息ずつ出す段階表示。隠すのは ritual controller が付ける .ritual-step--pending だけ。
 * - prefers-reduced-motion では全アニメーションを止めて即時表示する。
 */

.card-fan {
  --fan-size: 78;
  --fan-spread: 120deg; /* 扇の全開角 */
  --fan-radius: 12rem; /* 円弧の半径 (アンカー点から札中心まで) */
  position: relative;
  height: 12rem;
  margin: 0.5rem auto 0;
  max-width: 34rem;
  overflow: hidden;
}

/* コンテナ下方のアンカー点を中心に「自転 (rotate) → 半径ぶん持ち上げ (translateY)」で
 * 札を円弧上に並べる。--i (0 起点 index) と枚数だけから CSS で完結する。 */
.card-fan__slot {
  --angle: calc((var(--i) - (var(--fan-size) - 1) / 2) * (var(--fan-spread) / var(--fan-size)));
  position: absolute;
  left: 50%;
  top: 15rem; /* アンカー点 (コンテナ外・下方) */
  width: 3.4rem;
  height: 5.4rem;
  margin-left: -1.7rem;
  margin-top: -2.7rem;
  transform: rotate(var(--angle)) translateY(calc(var(--fan-radius) * -1));
  border-radius: 0.4rem;
}

/* 裏絵柄 (#606): 占い師固有の SVG 資産。--card-back は扇 (.card-fan) に一度だけ置かれ、
 * 78 枚の伏せ札がここで継承する (枚数ぶんの inline style を吐かないため)。SVG の viewBox は
 * スロットと同じ 68:108 なので cover で切れない。地色は資産の読み込み前・失敗時の下地。 */
.card-fan__card {
  cursor: pointer;
  background-color: oklch(20% 0.05 290);
  background-image: var(--card-back);
  background-size: cover;
  background-position: center;
  box-shadow: 0 1px 3px rgb(0 0 0 / 0.35);
  transition: transform 150ms ease-out, box-shadow 150ms ease-out;
}

.card-fan__card:hover,
.card-fan__card:focus-visible {
  transform: rotate(var(--angle)) translateY(calc(var(--fan-radius) * -1 - 0.9rem));
  box-shadow: 0 6px 14px rgb(0 0 0 / 0.4);
  z-index: 1;
}

.card-fan__slot--picked {
  border: 1px dashed oklch(60% 0.02 290 / 0.4);
  background: transparent;
  pointer-events: none; /* 空きスロットが隣の伏せ札へのクリックを奪わないように */
}

/* シャッフル → カット → 配置の所作 (#467、段階化 #854)。ひと山 (rotate 0 / 半径 0.55 倍) の
 * まま 0-40% で左右に切り混ぜ (シャッフル)、40-65% で山を持ち上げて置き直し (カット)、
 * 以降で各札の定位置 (--angle) へ開く (配置)。3 段階を 1200ms の中に収めるので、待ち時間は
 * #467 から増えない。fill-mode backwards で delay 中も山に留め、終了後は素の扇配置へ戻す
 * (forwards だと最終フレームが :hover の持ち上げを永久に上書きしてしまう)。
 * stagger は総量 240ms を枚数で割り、デッキ枚数に依らず一定にする。 */
@keyframes card-fan-deal {
  from {
    transform: rotate(0deg) translateY(calc(var(--fan-radius) * -0.55));
  }

  15% {
    transform: rotate(-6deg) translateY(calc(var(--fan-radius) * -0.52));
  }

  30% {
    transform: rotate(6deg) translateY(calc(var(--fan-radius) * -0.58));
  }

  40% {
    transform: rotate(0deg) translateY(calc(var(--fan-radius) * -0.55));
  }

  /* カット: 山ごと横へずらして持ち上げ (上半分を抜く見得) … */
  52% {
    transform: rotate(-2deg) translateX(2.2rem) translateY(calc(var(--fan-radius) * -0.68));
  }

  /* … 下へ置き直して 1 つの山に戻す */
  65% {
    transform: rotate(0deg) translateX(0) translateY(calc(var(--fan-radius) * -0.5));
  }

  to {
    transform: rotate(var(--angle)) translateY(calc(var(--fan-radius) * -1));
  }
}

.card-fan--entrance .card-fan__slot {
  animation: card-fan-deal 1200ms cubic-bezier(0.33, 1, 0.68, 1) backwards;
  animation-delay: calc(var(--i) * 240ms / var(--fan-size));
}

/* 抜き出し所作 (#467): 選んだ札を扇からせり上げる。card-fan controller が --drawing を
 * 付けて所作の後に submit する。抜き出し中は他の札への連打 (多重 pick) を pointer で塞ぐ。 */
.card-fan--drawing .card-fan__card {
  pointer-events: none;
}

/* :hover (0,2,0) と同特異度になるよう二重 class にし、後置で勝たせる */
.card-fan__card.card-fan__card--drawing {
  transform: rotate(var(--angle)) translateY(calc(var(--fan-radius) * -1 - 2.4rem)) scale(1.08);
  transition-duration: 300ms; /* card-fan controller の DRAW_MS と揃える */
  box-shadow: 0 10px 22px rgb(0 0 0 / 0.45);
  z-index: 2;
}

/* spread 盤面 (#467): 枠数 (--slots) の等分 grid。扇と同じ幅感に収める。 */
.spread-board {
  display: grid;
  grid-template-columns: repeat(var(--slots, 1), minmax(0, 1fr));
  gap: 0.75rem;
  max-width: 34rem;
  margin-inline: auto;
  width: 100%;
}

.spread-board__label {
  text-align: center;
  font-size: 0.75rem;
  opacity: 0.65;
  margin-bottom: 0.25rem;
}

.spread-board__card {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  height: 100%;
}

.spread-board__image {
  width: clamp(3.5rem, 55%, 5rem);
}

/* ルーンの札面 (#1164): 表絵柄の代わりに字形を石の面として置く。ブランクの石は空の面。
 * 逆位置は .rotate-180 で返すので inline-flex にする (inline の要素は transform が効かない)。 */
.rune-face {
  align-self: center;
  width: clamp(3.5rem, 55%, 5rem);
  aspect-ratio: 3 / 4;
  border-radius: 45% 45% 40% 40%;
  background: var(--color-base-200, oklch(94% 0.01 290));
  font-size: 2.5rem;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: oklch(45% 0.09 290); /* 伏せ札 (card-fan) と同系の紫 */
}

.spread-board__placeholder {
  height: 100%;
  min-height: 8rem;
  border: 1px dashed oklch(60% 0.02 290 / 0.4);
  border-radius: 0.5rem;
}

/* めくった札 */
.card-pick-card {
  border: 1px solid var(--color-base-300, oklch(80% 0.02 290));
  border-radius: 0.5rem;
  padding: 0.75rem 1rem;
  background: var(--color-base-100, white);
}

.card-pick-card--major {
  border-color: oklch(80% 0.13 85);
  box-shadow: 0 0 0.6rem oklch(80% 0.13 85 / 0.45);
}

.card-pick-card--reversed {
  border-style: dashed;
  background: linear-gradient(180deg, oklch(55% 0.06 290 / 0.08), transparent 55%);
}

/* めくり (#606): 実裏面 (占い師固有の裏絵柄) を表の上に重ねて 180° 返す。裏面は
 * .card-flip--revealing (新規開示の枠) のときだけ DOM に入るので、素の .card-flip は
 * ただのラッパ — 3D 文脈も演出中の枠だけに閉じる。 */
.card-flip--revealing {
  perspective: 600px;
}

/* --reveal-order (#854): 同じ応答で複数枚が開く (おまかせ) ときは 1 枚ずつ順に返す。
 * backwards で待ち時間中は伏せたまま留める (= 先に表が見えてしまわない)。1 枚だけの
 * 開示は order 0 なので #606 から挙動が変わらない。 */
.card-flip--revealing .card-flip__inner {
  position: relative;
  transform-style: preserve-3d;
  animation: card-flip-turn 500ms ease-out backwards;
  animation-delay: calc(var(--reveal-order, 0) * 200ms);
}

/* 裏面は表と同じ箱を占める。表の高さ (画像 + 短文 + キーワード) が箱を決めるので、箱の縦横比は
 * 短文長・キーワード数で動く。cover だと絵柄が切れ、3 種で共有している枠・コーナー装飾という
 * 一番切れてはいけない部分から先に欠ける。contain にして絵柄は必ず全体を見せ、余った帯は
 * 地色で埋める (3 種とも縁は暗色なので馴染む)。扇 (68:108 固定) 側は比が一致するので cover のまま。 */
.card-flip__back {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background-color: oklch(14% 0.02 290);
  border-radius: 0.5rem; /* .card-pick-card と揃える */
  transform: rotateY(180deg);
}

.card-flip--revealing .card-pick-card,
.card-flip__back {
  backface-visibility: hidden;
}

@keyframes card-flip-turn {
  from {
    transform: rotateY(180deg);
  }
  to {
    transform: rotateY(0deg);
  }
}

@keyframes card-pick-glow {
  0%, 100% {
    box-shadow: 0 0 0.6rem oklch(80% 0.13 85 / 0.45);
  }
  50% {
    box-shadow: 0 0 1.2rem oklch(80% 0.13 85 / 0.8);
  }
}

/* 直近にめくった大アルカナはフリップ後にグローを 2 拍打つ (回転は .card-flip__inner 側)。
 * delay はその枠のフリップ完了に合わせる (--reveal-order のぶん後ろへずらす)。 */
.card-pick-card--just-revealed.card-pick-card--major {
  animation: card-pick-glow 900ms ease-in-out calc(500ms + var(--reveal-order, 0) * 200ms) 2;
}

/* 儀式の段階表示 (#854)。位置の意味 → 出たもの → カードの言葉 を一息ずつ出す。
 * 隠すのは ritual controller が付ける --pending だけ — JS 無効なら最初から全部見えており、
 * prefers-reduced-motion では controller が付けないので即時表示になる。 */
[data-ritual-step] {
  transition: opacity 240ms ease-out, transform 240ms ease-out;
}

.ritual-step--pending {
  opacity: 0;
  transform: translateY(0.3rem);
}

/* 狭幅 (スマホ) では半径と札サイズを縮め、扇の両端がコンテナ外に切れないようにする */
@media (max-width: 480px) {
  .card-fan {
    --fan-radius: 9.5rem;
    height: 11.5rem;
  }

  .card-fan__slot {
    top: 14rem;
    width: 2.6rem;
    height: 4.2rem;
    margin-left: -1.3rem;
    margin-top: -2.1rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .card-pick-card--just-revealed.card-pick-card--major,
  .card-flip--revealing .card-flip__inner,
  .card-fan--entrance .card-fan__slot {
    animation: none; /* シャッフル所作もフリップも無効化し、即時表示する (#467) */
  }

  /* 回転しない = 裏面が表を覆ったまま残るので、裏面ごと落として表を即時表示する (#606) */
  .card-flip__back {
    display: none;
  }

  .card-fan__card,
  .card-fan__card:hover,
  .card-fan__card:focus-visible,
  .card-fan__card.card-fan__card--drawing,
  [data-ritual-step] {
    transition: none;
  }
}
