/*
 * くじカス占い。くじ券の見た目とめくり演出だけをここに置く。
 * 外側のカード・見出し・ボタンはスレッドの他の要素と揃えたいので Tailwind で書く。
 *
 * Tailwind の出力はすべてカスケードレイヤーの中にあるため、
 * レイヤーに属さないこのファイルの指定が読み込み順に関わらず優先される。
 */

.fortune {
  /* 券の色はプロトタイプで詰めたものをそのまま使う。実券に近い赤と金の帯 */
  --fortune-red: #ee423b;
  --fortune-red-dark: #d93631;
  --fortune-blue: #168bd1;
  --fortune-ink: #29292c;
  --fortune-face:
    linear-gradient(145deg,
      transparent 0 22%,
      rgba(255, 255, 255, .11) 22% 31%,
      transparent 31% 68%,
      rgba(246, 201, 52, .88) 68% 76%,
      transparent 76%),
    var(--fortune-red-dark);

  /* 粒子をこの中に収める */
  position: relative;

  /* 共有 URL のアンカーで飛んできたとき、追従ヘッダーに頭を隠されないようにする */
  scroll-margin-top: 72px;
}

/* ---------- 開くまでは畳んでおく ----------
   在庫と残数を見に来た人のスクロール量を増やさないよう、開く前は入口だけ出す。
   サーバーが返す時点でこの状態なので、共有 URL のアンカーで飛んできても
   読み込み後に位置がずれない。 */
.fortune-stage {
  display: none;
}

.fortune.is-expanded .fortune-stage {
  display: grid;
  animation: fortune-open .3s ease both;
}

.fortune.is-expanded .fortune-opener {
  display: none;
}

/* 開く前は入口だけの 1 行なので外側も詰めておく。
   開いたら盤面が主役になるので、そのときだけ余白を広げる。 */
.fortune.is-expanded {
  padding: 1rem;
}

@keyframes fortune-open {
  0% { opacity: 0; transform: translateY(-6px); }
  100% { opacity: 1; transform: none; }
}

/* ---------- 選択とめくりを同じ場所に重ねる ----------
   別レイアウトへ切り替えるとカードの高さが変わって画面が跳ねる。
   2 つの手順を同じセルに重ね、高さを高いほうに固定しておく。 */
.fortune-step {
  grid-area: 1 / 1;
  /* 高さは 2 つの手順の高いほうに固定される。低いほうは中央に置いて、
     余白が片側だけに寄らないようにする */
  align-self: center;
}

/* 選択盤。選ばれなかった券と操作部が先に引き、選んだ 1 枚だけが残ってから、
   盤ごと消える。券を飛ばして拡大するより、いったん消えたほうが素直に見える。
   時間は fortune_controller.js の定数と対になっている。 */
.fortune-select-step {
  transition:
    opacity .24s ease,
    transform .24s ease,
    visibility 0s linear 0s;
}

.fortune-select-step.is-hidden {
  opacity: 0;
  visibility: hidden;
  transform: scale(.98);
  pointer-events: none;
  transition:
    opacity .24s ease,
    transform .24s ease,
    visibility 0s linear .24s;
}

.fortune-select-step.is-drawing .fortune-board-head,
.fortune-select-step.is-drawing .fortune-panel,
.fortune-select-step.is-drawing .fortune-pick:not(.is-selected) {
  opacity: 0;
  transition: opacity .2s ease;
}

/* 選んだ 1 枚だけ、引かれる直前にもう一段持ち上がる */
.fortune-select-step.is-drawing .fortune-pick.is-selected {
  transform: translateY(-8px) scale(1.06);
  transition: transform .28s cubic-bezier(.2, .9, .25, 1);
}

/* めくり券。選択盤が消え切ってから、少し持ち上がりながら現れる */
.fortune-peel-step {
  transition:
    opacity .28s ease,
    transform .32s cubic-bezier(.2, .8, .2, 1),
    visibility 0s linear 0s;
}

.fortune-peel-step.is-hidden {
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  pointer-events: none;
  /* 戻すときは滑らせない。次に出るときは必ず下から始める */
  transition:
    opacity .2s ease,
    transform 0s linear .2s,
    visibility 0s linear .2s;
}

/* ---------- 9 枚のくじ券 ---------- */
.fortune-board {
  max-width: 390px;
  margin: 0 auto;
  padding: 15px 13px 13px;
  border: 1px solid #ece8e2;
  border-radius: 14px;
  background: #faf9f7;
}

.fortune-board-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  margin-bottom: 12px;
  padding: 0 2px;
}

.fortune-board-head strong {
  font-size: 13px;
  font-weight: 900;
  color: #171717;
}

.fortune-board-head span {
  font-size: 10px;
  font-weight: 800;
  color: #777;
}

.fortune-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}

.fortune-pick {
  position: relative;
  aspect-ratio: 1.62 / 1;
  padding: 0;
  border: 0;
  border-radius: 3px;
  overflow: hidden;
  background: var(--fortune-face);
  box-shadow: 0 2px 6px rgba(0, 0, 0, .16);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition:
    transform .16s cubic-bezier(.2, .9, .25, 1),
    box-shadow .16s ease,
    outline-color .16s ease,
    opacity .16s ease;
}

.fortune-pick::before {
  content: "";
  position: absolute;
  inset: 4px;
  border: 1px solid rgba(255, 255, 255, .48);
}

.fortune-pick-label {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: #fff;
  font-size: 10px;
  font-weight: 900;
}

.fortune-pick-num {
  position: absolute;
  right: 5px;
  bottom: 3px;
  color: rgba(255, 255, 255, .86);
  font-size: 10px;
  font-weight: 900;
  line-height: 1;
}

.fortune-pick.is-selected {
  transform: translateY(-5px) scale(1.035);
  box-shadow: 0 9px 18px rgba(0, 0, 0, .24);
  outline: 3px solid #0f172a;
  outline-offset: 2px;
  z-index: 3;
}

.fortune-pick.is-dimmed {
  opacity: .55;
}

.fortune-pick:active {
  transform: translateY(-2px) scale(.99);
}

.fortune-pick[disabled] {
  cursor: default;
}

.fortune-panel {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 56px;
  margin-top: 13px;
  padding-top: 12px;
  border-top: 1px solid #ece8e2;
}

.fortune-panel-copy {
  min-width: 0;
}

.fortune-panel-copy span {
  display: block;
  font-size: 9px;
  font-weight: 800;
  color: #777;
  line-height: 1.4;
}

.fortune-panel-copy strong {
  display: block;
  margin-top: 2px;
  font-size: 14px;
  font-weight: 900;
  color: #171717;
  line-height: 1.4;
}

.fortune-confirm {
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 16px;
  border: 0;
  border-radius: 10px;
  background: #0f172a;
  color: #fff;
  font: inherit;
  font-size: 12px;
  font-weight: 900;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: opacity .16s ease, transform .16s ease;
}

.fortune-confirm[disabled] {
  opacity: .25;
  cursor: default;
}

.fortune-confirm:not([disabled]):active {
  transform: scale(.97);
}

/* ---------- めくる券 ----------
   見出しを外したので、選択盤とめくり券が同じ高さから始まるようにする */
.fortune-holder {
  width: 100%;
  max-width: 340px;
  margin: 0 auto;
  perspective: 1100px;
}

.fortune-ticket {
  position: relative;
  width: 100%;
  /* 横長すぎない、実券に近い比率 */
  aspect-ratio: 1.62 / 1;
  filter: drop-shadow(0 16px 22px rgba(0, 0, 0, .20));
  user-select: none;
  -webkit-user-select: none;
  transform-style: preserve-3d;
}

/* 外枠は最後まで残る。めくれるのは内側の券面だけ */
.fortune-outer {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background:
    linear-gradient(22deg, transparent 0 60%, rgba(255, 255, 255, .13) 60% 69%, transparent 69%),
    var(--fortune-red);
}

.fortune-outer::before {
  content: "";
  position: absolute;
  inset: 6px;
  border: 1px solid rgba(255, 255, 255, .70);
}

.fortune-outer-tl,
.fortune-outer-tr,
.fortune-outer-bl {
  position: absolute;
  color: #fff;
  line-height: 1;
}

.fortune-outer-tl {
  left: 13px;
  top: 11px;
  font-size: 7px;
  font-weight: 900;
  letter-spacing: .04em;
}

.fortune-outer-tr {
  right: 16px;
  top: 11px;
  font-size: 6px;
  font-weight: 800;
  opacity: .9;
}

.fortune-outer-bl {
  left: 14px;
  bottom: 13px;
  font-size: 6px;
  font-weight: 800;
}

.fortune-window {
  position: absolute;
  left: 15px;
  right: 15px;
  top: 29px;
  bottom: 25px;
  overflow: visible;
  border-radius: 1px;
  background: var(--fortune-ink);
  z-index: 2;
  transform-style: preserve-3d;
}

/* ミシン目。本家の再現は狙わず、券面に馴染む程度に留める */
.fortune-perforation {
  position: absolute;
  inset: -4px;
  width: calc(100% + 8px);
  height: calc(100% + 8px);
  z-index: 21;
  overflow: visible;
  pointer-events: none;
}

.fortune-perforation path {
  fill: none;
  stroke: rgba(255, 255, 255, .48);
  stroke-width: 1.3;
  stroke-dasharray: 5 6;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

/* ---------- 結果面 ---------- */
.fortune-result {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--fortune-ink);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .16);
}

.fortune-result-top {
  display: flex;
  align-items: center;
  height: 23%;
  padding: 0 13px;
  background: var(--fortune-blue);
  color: #fff;
  font-size: 8px;
  font-weight: 900;
}

.fortune-result-body {
  position: absolute;
  left: 0;
  right: 0;
  top: 23%;
  bottom: 0;
  display: flex;
  align-items: center;
  padding: 0 15px;
  color: #fff;
}

/* まず目に入るのはここ。良し悪しを結果名より先に伝える。
   「大吉」「大凶」の 2 文字が収まる幅を確保しつつ、
   結果名が読めなくなるほどは取らない */
.fortune-result-rank {
  /* 幅は文字の分だけ取る。枠を固定すると「凶」のような一文字のときに
     右が大きく空いて、結果名との間が間延びする */
  flex: 0 0 auto;
  font-size: 38px;
  font-weight: 900;
  line-height: .95;
  letter-spacing: -.03em;
  white-space: nowrap;
}

.fortune-result-copy {
  min-width: 0;
  /* ランクと結果名の間隔。幅が可変になったぶん、ここで一定に保つ */
  padding-left: 14px;
}

.fortune-result-mini {
  font-size: 7px;
  font-weight: 900;
  letter-spacing: .1em;
  color: #c8c8c8;
  line-height: 1.2;
}

/* 結果名は 1 行で見せる。「物欲センサー注意」のような長い名前は券の幅に入らないので、
   実際に描かれた幅を JavaScript が測って倍率を入れる。--fortune-name-fit は 1 以下 */
.fortune-result-name {
  margin-top: 3px;
  font-size: calc(23px * var(--fortune-name-fit, 1));
  font-weight: 900;
  line-height: 1.05;
  white-space: nowrap;
}

.fortune-result-quote {
  margin-top: 7px;
  font-size: 8.5px;
  font-weight: 800;
  color: #e2e2e2;
  line-height: 1.35;
}

.fortune-result-note {
  position: absolute;
  right: 9px;
  bottom: 5px;
  font-size: 5px;
  font-weight: 800;
  color: #aaa;
}

/* ---------- めくる前の券面 ---------- */
.fortune-closed {
  position: absolute;
  inset: 0;
  z-index: 5;
  overflow: hidden;
  background: var(--fortune-face);
  will-change: clip-path;
}

.fortune-closed::before {
  content: "";
  position: absolute;
  inset: 6px;
  border: 1px solid rgba(255, 255, 255, .30);
}

.fortune-closed-copy {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #fff;
}

.fortune-closed-copy strong {
  font-size: 20px;
  font-weight: 900;
  letter-spacing: .03em;
}

.fortune-closed-copy span {
  margin-top: 6px;
  font-size: 7px;
  font-weight: 800;
}

.fortune-barcode {
  position: absolute;
  right: 10px;
  bottom: 9px;
  width: 58px;
  height: 18px;
  opacity: .8;
  background: repeating-linear-gradient(90deg,
    #fff 0 1px, transparent 1px 3px, #fff 3px 4px, transparent 4px 6px);
}

/* ---------- めくり口 ----------
   スクロールを奪うのはこのつまみの上だけにする。券の他の場所を触っても
   ページは普通に縦スクロールできる。 */
.fortune-handle {
  position: absolute;
  left: 0;
  top: 22%;
  width: 50px;
  height: 56%;
  z-index: 15;
  display: flex;
  align-items: center;
  padding: 0 0 0 6px;
  border: 0;
  background: #fff;
  clip-path: polygon(0 0, 68% 0, 100% 50%, 68% 100%, 0 100%);
  box-shadow: 2px 0 4px rgba(0, 0, 0, .15);
  font: inherit;
  color: #444;
  cursor: grab;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}

.fortune-handle span {
  writing-mode: vertical-rl;
  font-size: 6.5px;
  font-weight: 900;
  line-height: 1;
}

.fortune-handle b {
  margin-left: 4px;
  font-size: 14px;
}

.fortune-ticket.is-dragging .fortune-handle {
  cursor: grabbing;
}

/* ---------- 剥がれて立ち上がる紙 ---------- */
.fortune-paper {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0;
  z-index: 12;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  transform-origin: right center;
  transform-style: preserve-3d;
  will-change: width, transform;
  filter: drop-shadow(5px 3px 6px rgba(0, 0, 0, .24));
}

.fortune-paper::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 25px;
  background: linear-gradient(90deg,
    rgba(255, 255, 255, 0),
    rgba(255, 255, 255, .62) 35%,
    rgba(0, 0, 0, .18) 62%,
    rgba(255, 255, 255, .92) 82%,
    rgba(0, 0, 0, .14));
}

.fortune-paper-front {
  position: absolute;
  inset: 0;
  background: var(--fortune-face);
}

.fortune-paper-front::before {
  content: "";
  position: absolute;
  inset: 6px;
  border: 1px solid rgba(255, 255, 255, .25);
}

.fortune-paper-back {
  position: absolute;
  inset: 0;
  opacity: 0;
  background: repeating-linear-gradient(90deg, #f6f6f4 0 1px, #e7e7e4 1px 3px, #faf9f6 3px 6px);
}

/* 剥がれ目。指と一緒に右へ動く */
.fortune-curl {
  position: absolute;
  top: -2px;
  bottom: -2px;
  left: 0;
  width: 24px;
  z-index: 13;
  opacity: 0;
  pointer-events: none;
  background: linear-gradient(90deg,
    rgba(255, 255, 255, .10) 0%,
    rgba(255, 255, 255, .96) 30%,
    rgba(182, 182, 182, .72) 52%,
    rgba(255, 255, 255, .88) 72%,
    rgba(0, 0, 0, .17) 100%);
  filter: drop-shadow(4px 0 5px rgba(0, 0, 0, .22));
}

.fortune-curl::after {
  content: "";
  position: absolute;
  left: 1px;
  top: 4px;
  bottom: 4px;
  width: 3px;
  background: repeating-linear-gradient(to bottom,
    rgba(145, 145, 145, .95) 0 3px, transparent 3px 7px);
}

/* ---------- 手順の案内と結果後のボタン ---------- */
.fortune-hint {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: max-content;
  margin: 18px auto 0;
  color: #666;
  font-size: 11px;
  font-weight: 900;
  transition: opacity .2s ease;
  animation: fortune-hint 1.35s ease-in-out infinite;
}

.fortune-hint b {
  font-size: 18px;
  color: #222;
}

@keyframes fortune-hint {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(14px); }
}

/* 指が触れた時点で案内の役目は終わり。引っぱっている最中も矢印が往復していると、
   券に集中できないうえ「引っぱる」と言っている手前、間が抜けて見える */
.fortune.is-peeling .fortune-hint,
.fortune.is-revealed .fortune-hint,
/* めくり券が引っ込んでいるあいだも出さない。「もう一枚引く」の直後に
   案内が復活して跳ね始めると、消えていく券の上でチラついて見える */
.fortune-peel-step.is-hidden .fortune-hint {
  opacity: 0;
  animation: none;
}

/* 高さは常に確保しておく。結果が出た瞬間にボタン分だけ跳ねるのを避ける */
/* 出し入れは pointer-events と inert で切り替える。visibility を
   時間差付きのトランジションで切り替えると、切り替わった直後のタップを
   取りこぼす端末がある */
.fortune-actions {
  margin-top: 18px;
  opacity: 0;
  transform: translateY(7px);
  pointer-events: none;
  transition: opacity .3s ease, transform .3s ease;
}

.fortune.is-revealed .fortune-actions {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* ---------- 特殊結果 ----------
   画面全体を光らせたり、揺らしたり、驚かせたりはしない。
   券の周りだけが、少し綺麗になる。 */
.fortune-aura {
  position: absolute;
  inset: -18px;
  z-index: 17;
  opacity: 0;
  border-radius: 10px;
  pointer-events: none;
  filter: blur(1px);
}

.fortune-sheen {
  position: absolute;
  inset: 0;
  z-index: 17;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

.fortune-sheen::before {
  content: "";
  position: absolute;
  top: -40%;
  bottom: -40%;
  left: -45%;
  width: 32%;
  transform: skewX(-17deg);
  background: linear-gradient(90deg,
    transparent,
    rgba(255, 255, 255, .16),
    rgba(255, 255, 255, .72),
    rgba(255, 255, 255, .12),
    transparent);
}

.fortune-ticket.is-revealed.is-effect-gold .fortune-aura,
.fortune-ticket.is-revealed.is-effect-rainbow .fortune-aura {
  animation: fortune-aura 1.35s ease-out .10s both;
}

/* 最高結果だけ、光を二度ふくらませてから濃いまま残す。
   派手さではなく「まだ光っている」時間の長さで格を出す */
.fortune-ticket.is-revealed.is-effect-ultimate .fortune-aura {
  animation: fortune-aura-ultimate 2.1s ease-out .06s both;
}

.fortune-ticket.is-revealed.is-effect-gold .fortune-sheen,
.fortune-ticket.is-revealed.is-effect-rainbow .fortune-sheen,
.fortune-ticket.is-revealed.is-effect-ultimate .fortune-sheen {
  opacity: 1;
}

.fortune-ticket.is-revealed.is-effect-gold .fortune-sheen::before,
.fortune-ticket.is-revealed.is-effect-rainbow .fortune-sheen::before,
.fortune-ticket.is-revealed.is-effect-ultimate .fortune-sheen::before {
  animation: fortune-sheen 1.05s cubic-bezier(.18, .72, .2, 1) .18s both;
}

@keyframes fortune-aura {
  0% { opacity: 0; transform: scale(.96); }
  34% { opacity: .95; transform: scale(1.015); }
  100% { opacity: .38; transform: scale(1); }
}

/* 明暗を往復させるとチラついて見えるので、ひと息で立ち上げて、あとは落とすだけにする */
@keyframes fortune-aura-ultimate {
  0% { opacity: 0; transform: scale(.92); }
  22% { opacity: 1; transform: scale(1.035); }
  100% { opacity: .5; transform: scale(1); }
}

@keyframes fortune-sheen {
  0% { left: -45%; opacity: 0; }
  18% { opacity: 1; }
  100% { left: 115%; opacity: 0; }
}

/* 券面そのものにも、柔らかい当たりを一度だけ */
.fortune-ticket.is-revealed .fortune-result.is-special {
  animation: fortune-card-pop .72s cubic-bezier(.18, .9, .26, 1) .08s both;
}

.fortune-ticket.is-revealed .fortune-result.is-special .fortune-result-name {
  animation: fortune-name-pop .7s cubic-bezier(.15, 1.2, .24, 1) .16s both;
}

@keyframes fortune-card-pop {
  0% { transform: scale(.94); filter: brightness(.82) saturate(.9); }
  42% { transform: scale(1.035); filter: brightness(1.22) saturate(1.18); }
  100% { transform: scale(1); filter: brightness(1) saturate(1); }
}

@keyframes fortune-name-pop {
  0% { transform: scale(.82); opacity: .45; }
  42% { transform: scale(1.12); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* 神引き：金の光。強い白フラッシュは使わず、いつもと違うと感じる程度に留める */
.fortune-result.is-effect-gold {
  background:
    radial-gradient(circle at 32% 50%, rgba(255, 224, 111, .14), transparent 28%),
    radial-gradient(circle at 70% 50%, rgba(255, 224, 111, .15), transparent 29%),
    linear-gradient(135deg, #332d1b, #171717 68%);
}

.fortune-result.is-effect-gold .fortune-result-top {
  background: linear-gradient(90deg, #d8a52d, #f3d66f, #c99118);
  color: #191919;
}

/* 最高結果より一段控えめにする。金の格を、光の強さでも分からせる */
.fortune-ticket.is-effect-gold .fortune-aura {
  background:
    radial-gradient(circle at 33% 50%, rgba(255, 209, 73, .30), transparent 30%),
    radial-gradient(circle at 70% 50%, rgba(255, 235, 140, .30), transparent 30%);
}

.fortune-ticket.is-effect-gold::after {
  content: "";
  position: absolute;
  inset: 22% 24%;
  z-index: 16;
  border: 1.5px solid rgba(255, 226, 104, 0);
  border-radius: 50%;
  pointer-events: none;
}

.fortune-ticket.is-revealed.is-effect-gold::after {
  animation: fortune-gold-ring 1.05s ease-out .12s both;
}

@keyframes fortune-gold-ring {
  0% { opacity: 0; transform: scale(.45); border-color: rgba(255, 226, 104, 0); }
  30% { opacity: .7; border-color: rgba(255, 226, 104, .5); }
  100% { opacity: 0; transform: scale(1.5); border-color: rgba(255, 226, 104, 0); }
}

/* 虹引き吉：必ず虹色。派手さではなく綺麗さで分からせる */
.fortune-result.is-effect-rainbow {
  background:
    linear-gradient(120deg,
      rgba(255, 80, 80, .34),
      rgba(255, 176, 64, .34),
      rgba(255, 230, 75, .30),
      rgba(72, 210, 120, .28),
      rgba(65, 170, 255, .30),
      rgba(125, 95, 255, .28),
      rgba(235, 85, 210, .30)),
    #202126;
}

.fortune-result.is-effect-rainbow .fortune-result-top {
  background: linear-gradient(90deg, #ef625c, #f0a94c, #e5cf4b, #59b96f, #4e9fda, #7b6cc9, #d46db7);
  color: #fff;
}

.fortune-ticket.is-effect-rainbow .fortune-aura {
  background: conic-gradient(from 15deg,
    rgba(255, 90, 90, .44),
    rgba(255, 190, 65, .44),
    rgba(255, 230, 80, .42),
    rgba(80, 220, 130, .42),
    rgba(70, 170, 255, .43),
    rgba(135, 105, 255, .43),
    rgba(235, 90, 215, .43),
    rgba(255, 90, 90, .44));
  filter: blur(13px);
}

.fortune-ticket.is-revealed.is-effect-rainbow {
  animation: fortune-rainbow-breath 1.45s ease-out .06s both;
}

@keyframes fortune-rainbow-breath {
  0% { filter: saturate(.85) brightness(.88); }
  38% { filter: saturate(1.35) brightness(1.12); }
  100% { filter: saturate(1.05) brightness(1); }
}

/* 超神引き吉：上品な金。最高結果感は出すが、驚かせない */
.fortune-result.is-effect-ultimate {
  background:
    radial-gradient(circle at 73% 42%, rgba(255, 230, 130, .26), transparent 30%),
    linear-gradient(135deg, #3d3218, #181817 68%);
}

.fortune-result.is-effect-ultimate .fortune-result-top {
  background: linear-gradient(90deg, #c99721, #f1d36c, #b98316);
  color: #1b1607;
}

/* 中心を塗ると券面の文字が濁るので、券の縁が光るリングにする。
   券の外へはみ出すぶんが「まだ光っている」感じになる */
.fortune-ticket.is-effect-ultimate .fortune-aura {
  background:
    radial-gradient(circle at 50% 50%,
      rgba(255, 233, 145, .16) 0 33%,
      rgba(255, 214, 84, .62) 52%,
      rgba(255, 198, 56, .30) 67%,
      transparent 79%);
  filter: blur(12px);
}

/* 券そのものが持ち上がる。二枚抜きには無い動きなので、ここが一番の違いになる */
.fortune-ticket.is-revealed.is-effect-ultimate {
  animation: fortune-ultimate-lift 1.35s cubic-bezier(.18, .85, .25, 1) .06s both;
}

@keyframes fortune-ultimate-lift {
  0% { transform: translateY(5px) scale(.93); }
  40% { transform: translateY(-5px) scale(1.06); }
  72% { transform: translateY(1px) scale(.996); }
  100% { transform: none; }
}

/* にじんで広がる金。二枚抜きの細いリングとは形が違うので、見間違えない */
.fortune-ticket.is-effect-ultimate::after {
  content: "";
  position: absolute;
  inset: -7%;
  z-index: 16;
  border-radius: 14px;
  opacity: 0;
  pointer-events: none;
  background:
    radial-gradient(circle at 50% 50%,
      rgba(255, 233, 152, .55),
      rgba(255, 214, 90, .18) 45%,
      transparent 68%);
  filter: blur(9px);
}

.fortune-ticket.is-revealed.is-effect-ultimate::after {
  animation: fortune-ultimate-bloom 1.7s cubic-bezier(.16, .72, .2, 1) .05s both;
}

@keyframes fortune-ultimate-bloom {
  0% { opacity: 0; transform: scale(.7); }
  30% { opacity: .9; transform: scale(1.02); }
  100% { opacity: 0; transform: scale(1.45); }
}

/* 券面の文字にも金をにじませる。最高結果だけの仕上げ */
.fortune-result.is-effect-ultimate .fortune-result-rank,
.fortune-result.is-effect-ultimate .fortune-result-name {
  text-shadow: 0 0 15px rgba(255, 228, 128, .6);
}

/* 券の周りだけに出る、小さくて静かな粒子 */
.fortune-particle {
  position: absolute;
  z-index: 6;
  width: var(--fortune-particle-size, 6px);
  height: var(--fortune-particle-size, 6px);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  animation: fortune-particle var(--fortune-particle-duration) ease-out forwards;
}

@keyframes fortune-particle {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(.4);
  }
  18% {
    opacity: .95;
    transform: translate(-50%, -50%) scale(1);
  }
  100% {
    opacity: 0;
    transform:
      translate(calc(-50% + var(--fortune-particle-dx)), calc(-50% + var(--fortune-particle-dy)))
      scale(.45);
  }
}

@media (max-width: 360px) {
  .fortune-grid { gap: 9px; }
  .fortune-board { padding: 13px 11px 12px; }
  .fortune-result-rank { font-size: 34px; }
  .fortune-result-name { font-size: calc(21px * var(--fortune-name-fit, 1)); }
}

@media (prefers-reduced-motion: reduce) {
  .fortune,
  .fortune *,
  .fortune *::before,
  .fortune *::after,
  .fortune-particle {
    animation: none !important;
    transition-duration: .01ms !important;
  }
}
