<template>
  <Comp ref="luckyWheelRef" :wheelConfig="wheelConfig" @handle-prize-result="handlePrizeResult" />
  <Teleport to="body">
    <Transition name="result">
      <div
        v-if="showResult"
        class="fixed inset-0 z-[9999] bg-black/70 backdrop-blur flex flex-col items-center justify-center"
      >
        <template v-if="isThanksPrize">
          <div ref="blessingWrapRef" class="blessing-wrap">
            <div ref="blessingGlowRef" class="blessing-glow" aria-hidden="true" />

            <div ref="blessingFanSceneRef" class="blessing-fan-scene">
              <div ref="blessingTagSlotRef" class="blessing-tag-slot" aria-hidden="true" />

              <div ref="blessingFanRef" class="blessing-fan" aria-hidden="true">
                <div
                  v-for="(text, index) in fanStackTexts"
                  :key="`${text}-${index}`"
                  :ref="setFanItemRef"
                  class="blessing-fan-item"
                  :style="fanItemStyle(index, fanStackTexts.length)"
                  :data-angle="fanItemMotion(index, fanStackTexts.length).angle"
                  :data-x="fanItemMotion(index, fanStackTexts.length).xOffset"
                  :data-y="fanItemMotion(index, fanStackTexts.length).yOffset"
                  :data-scale="fanItemMotion(index, fanStackTexts.length).scale"
                >
                  <div class="blessing-fan-face">
                    <div class="blessing-fan-top">
                      <span class="blessing-fan-orb" aria-hidden="true" />
                      <span class="blessing-fan-string" />
                      <!-- <span class="blessing-fan-label">今日签</span> -->
                    </div>
                    <div class="blessing-fan-meta">
                      <span class="blessing-fan-divider" />
                      <span class="blessing-fan-headline">签语</span>
                      <span class="blessing-fan-divider" />
                    </div>
                    <div class="blessing-fan-text">
                      <span class="blessing-fan-emoji">{{ fanEmoji(index) }}</span>
                      <span
                        v-for="(char, charIndex) in text.split('')"
                        :key="`${char}-${charIndex}`"
                        class="blessing-fan-char"
                        :class="{ 'is-gap': char === ' ' }"
                      >
                        {{ char }}
                      </span>
                    </div>
                  </div>
                </div>
              </div>

              <div ref="blessingTagStageRef" class="blessing-tag-stage">
                <div ref="blessingTagRef" class="blessing-tag">
                  <div ref="blessingTagTopRef" class="blessing-tag-top">
                    <span class="blessing-tag-orb" aria-hidden="true" />
                    <span class="blessing-tag-string" />
                    <span class="blessing-tag-label">今日签</span>
                  </div>
                  <div class="blessing-tag-meta">
                    <span class="blessing-tag-divider" />
                    <span class="blessing-tag-headline">签语</span>
                    <span class="blessing-tag-divider" />
                  </div>
                  <div class="blessing-text" :class="{ 'is-long-text': blessingChars.length > 10 }">
                    <span
                      v-for="(char, index) in blessingChars"
                      :key="`${char}-${index}`"
                      :ref="setBlessingCharRef"
                      :class="{ 'is-gap': char === ' ' }"
                    >
                      {{ char }}
                    </span>
                  </div>
                  <div ref="blessingSealRef" class="blessing-tag-seal">大吉</div>
                </div>
              </div>
            </div>
          </div>

          <div ref="blessingCaptionRef" class="blessing-caption">
            <p class="blessing-caption-title">今日签语</p>
            <p class="blessing-caption-subtitle">抽一支好运电子签，把今天过得亮一点</p>
          </div>

          <el-button class="mt-8" type="primary" @click="closeResult">知道了</el-button>
        </template>

        <template v-else>
          <img :src="currentPrize?.prizeImageUrl" class="w-60 h-60 animate-pop" />
          <div class="mt-6 text-white text-3xl font-bold">
            恭喜获得 {{ currentPrize?.prizeName }}
          </div>
          <el-button class="mt-8" type="primary" @click="closeResult">知道了</el-button>
        </template>
      </div>
    </Transition>
  </Teleport>
</template>

<script setup lang="ts">
import type { ComponentPublicInstance } from 'vue'
import gsap from 'gsap'

import Comp from './components/LuckyWheel.vue'
import type { LuckWheelResultDto, WheelConfigDto } from '@/api'

const { wheelConfig } = defineProps<{
  wheelConfig: WheelConfigDto
}>()

const showResult = ref(false)
const currentPrize = ref<LuckWheelResultDto | null>(null)
const luckyWheelRef = ref<InstanceType<typeof Comp>>()

const blessingWrapRef = ref<HTMLElement | null>(null)
const blessingGlowRef = ref<HTMLElement | null>(null)
const blessingFanSceneRef = ref<HTMLElement | null>(null)
const blessingFanRef = ref<HTMLElement | null>(null)
const blessingTagSlotRef = ref<HTMLElement | null>(null)
const blessingTagStageRef = ref<HTMLElement | null>(null)
const blessingTagRef = ref<HTMLElement | null>(null)
const blessingTagTopRef = ref<HTMLElement | null>(null)
const blessingSealRef = ref<HTMLElement | null>(null)
const blessingCaptionRef = ref<HTMLElement | null>(null)
const fanItemRefs = ref<HTMLElement[]>([])
const blessingCharRefs = ref<HTMLElement[]>([])

let blessingTimeline: gsap.core.Timeline | null = null
let floatTween: gsap.core.Tween | null = null

const blessingEmojiList = ['·ᴗ·', '^_^', '◕‿◕', '✦ᴗ✦', '˶ᵔ ᵕ ᵔ˶', '•‿•', '๑´ڡ`๑']

const isThanksPrize = computed(() => currentPrize.value?.prizeId == null)
const blessingChars = computed(() => {
  const text = (currentPrize.value?.blessingText || '').trim()
  return text ? text.split('') : ['好', '运', '常', '在']
})

const fanPreviewTexts = [
  '钱包鼓鼓 烦恼全无',
  '年年有鱼摸 岁岁越平安',
  '干啥啥都顺 吃嘛嘛都香',
  '狂吃不胖 熬夜不秃',
  '凡是发生皆有利于我',
  '内核强大 所向披靡',
  '逆风如解意 税后十个亿',
  '恶缘退散 好人靠近',
  '发发发 发量爆棚',
  '桃旺旺 钱财多多',
  '拒绝精神内耗 本人配享太庙',
]

const fanStackTexts = computed(() => {
  const texts = [...fanPreviewTexts]
  const selectedText = (currentPrize.value?.blessingText || '').trim()

  if (!isThanksPrize.value || !selectedText) {
    return texts
  }

  const selectedIndex = texts.indexOf(selectedText)
  if (selectedIndex === -1) {
    return texts
  }

  const [selectedItem] = texts.splice(selectedIndex, 1)
  const centerIndex = Math.floor(texts.length / 2)
  texts.splice(centerIndex, 0, selectedItem as string)

  return texts
})

const fanItemMotion = (index: number, total: number) => {
  const center = (total - 1) / 2
  const offset = index - center
  const spreadRatio = center === 0 ? 0 : offset / center
  const angle = spreadRatio * 30
  const xOffset = offset * 40
  const yOffset = Math.abs(offset) * 4
  const scale = 1 - Math.abs(spreadRatio) * 0.08

  return {
    angle,
    xOffset,
    yOffset,
    scale,
  }
}

const fanItemStyle = (index: number, total: number) => {
  const { angle, xOffset, yOffset, scale } = fanItemMotion(index, total)

  return {
    '--angle': `${angle}deg`,
    '--x-offset': `${xOffset}px`,
    '--y-offset': `${yOffset}px`,
    '--scale': `${scale}`,
  }
}

const fanEmoji = (index: number) => blessingEmojiList[index % blessingEmojiList.length]

const setFanItemRef = (el: Element | ComponentPublicInstance | null) => {
  if (el instanceof HTMLElement) {
    fanItemRefs.value.push(el)
  }
}

const setBlessingCharRef = (el: Element | ComponentPublicInstance | null) => {
  if (el instanceof HTMLElement) {
    blessingCharRefs.value.push(el)
  }
}

const clearBlessingAnimation = () => {
  blessingTimeline?.kill()
  blessingTimeline = null
  floatTween?.kill()
  floatTween = null
}

const startFloating = () => {
  if (!blessingTagRef.value) {
    return
  }

  floatTween?.kill()
  floatTween = gsap.to(blessingTagRef.value, {
    y: -10,
    rotation: 0.8,
    duration: 2.6,
    repeat: -1,
    yoyo: true,
    ease: 'sine.inOut',
  })
}

const playBlessingAnimation = () => {
  const wrap = blessingWrapRef.value
  const glow = blessingGlowRef.value
  const scene = blessingFanSceneRef.value
  const fan = blessingFanRef.value
  const slot = blessingTagSlotRef.value
  const tag = blessingTagRef.value
  const tagTop = blessingTagTopRef.value
  const seal = blessingSealRef.value
  const caption = blessingCaptionRef.value
  const fanItems = [...fanItemRefs.value]
  const chars = [...blessingCharRefs.value]

  if (
    !wrap ||
    !glow ||
    !scene ||
    !fan ||
    !slot ||
    !tag ||
    !tagTop ||
    !seal ||
    !caption ||
    !fanItems.length
  ) {
    return
  }

  clearBlessingAnimation()

  gsap.set(wrap, { transformPerspective: 1400 })
  gsap.set(scene, { y: 20, opacity: 0 })
  gsap.set(glow, { opacity: 0, scale: 0.78 })
  gsap.set(slot, { opacity: 0, scaleX: 0.72, transformOrigin: '50% 50%' })
  gsap.set(fan, { y: 34, opacity: 0 })
  gsap.set(blessingTagStageRef.value, {
    opacity: 0,
    y: 26,
    filter: 'blur(8px)',
    transformOrigin: '50% 100%',
  })
  gsap.set(fanItems, {
    opacity: 0,
    y: 78,
    rotate: (_index, target) => Number(target.getAttribute('data-angle') || 0) * 0.4,
    scale: (_index, target) => Number(target.getAttribute('data-scale') || 1) - 0.08,
    transformOrigin: '50% 100%',
  })
  gsap.set(tag, {
    opacity: 0,
    y: 356,
    scale: 0.94,
    rotation: 0,
    transformOrigin: '50% 100%',
    filter: 'blur(10px)',
  })
  gsap.set(tagTop, { opacity: 0.65 })
  gsap.set(chars, { opacity: 0, y: 10 })
  gsap.set(seal, { opacity: 0, y: 8 })
  gsap.set(caption, { opacity: 0, y: 20 })

  blessingTimeline = gsap.timeline({
    defaults: { ease: 'power2.out' },
    onComplete: () => {
      startFloating()
    },
  })

  blessingTimeline
    .to(scene, { opacity: 1, y: 0, duration: 0.35 })
    .to(glow, { opacity: 0.95, scale: 1, duration: 0.55, ease: 'sine.out' }, '<')
    .to(slot, { opacity: 1, scaleX: 1, duration: 0.42 }, '-=0.26')
    .to(fan, { opacity: 1, y: 0, duration: 0.34 }, '<')
    .to(
      fanItems,
      {
        opacity: 1,
        y: (_index, target) => Number(target.getAttribute('data-y') || 0),
        rotate: (_index, target) => Number(target.getAttribute('data-angle') || 0),
        scale: (_index, target) => Number(target.getAttribute('data-scale') || 1),
        duration: 0.7,
        ease: 'back.out(1.08)',
        stagger: {
          each: 0.042,
          from: 'center',
        },
      },
      '+=0.02',
    )
    .to(
      fanItems,
      {
        x: (_index, target) => Number(target.getAttribute('data-x') || 0) * 0.1,
        duration: 0.26,
        ease: 'power1.inOut',
        stagger: {
          each: 0.016,
          from: 'edges',
        },
        yoyo: true,
        repeat: 1,
      },
      '+=0.18',
    )
    .to(
      blessingTagStageRef.value,
      {
        opacity: 1,
        y: 0,
        filter: 'blur(0px)',
        duration: 0.36,
        ease: 'power2.out',
      },
      '+=0.01',
    )
    .to(
      tag,
      {
        y: 272,
        opacity: 0.5,
        scale: 0.97,
        filter: 'blur(6px)',
        duration: 0.34,
        ease: 'power2.out',
      },
      '<',
    )
    .to(
      tag,
      {
        y: 44,
        opacity: 1,
        scale: 1.01,
        filter: 'blur(1px)',
        duration: 0.82,
        ease: 'power3.out',
      },
      '+=0.08',
    )
    .to(
      tag,
      {
        y: 18,
        rotation: -1.4,
        scale: 1.015,
        filter: 'blur(0px)',
        duration: 0.24,
        ease: 'power2.out',
      },
      '-=0.14',
    )
    .to(
      tag,
      {
        y: 24,
        rotation: 0.4,
        scale: 1,
        filter: 'blur(0px)',
        duration: 0.26,
        ease: 'back.out(1.5)',
      },
      '+=0.01',
    )
    .to(tagTop, { opacity: 1, duration: 0.18 }, '<')
    .to(
      chars,
      {
        opacity: 1,
        y: 0,
        duration: 0.28,
        stagger: 0.035,
      },
      '-=0.08',
    )
    .to(
      seal,
      {
        opacity: 1,
        y: 0,
        duration: 0.22,
      },
      '-=0.12',
    )
    .to(
      caption,
      {
        opacity: 1,
        y: 0,
        duration: 0.34,
      },
      '-=0.02',
    )
}

watch(
  () => showResult.value,
  async (visible) => {
    if (!visible) {
      clearBlessingAnimation()
      return
    }

    if (!isThanksPrize.value) {
      clearBlessingAnimation()
      return
    }

    await nextTick()
    playBlessingAnimation()
  },
)

onBeforeUpdate(() => {
  fanItemRefs.value = []
  blessingCharRefs.value = []
})

onBeforeUnmount(() => {
  clearBlessingAnimation()
})

const handlePrizeResult = (prize: LuckWheelResultDto) => {
  currentPrize.value = prize
  showResult.value = true
}

const closeResult = () => {
  showResult.value = false
  luckyWheelRef.value?.stopSpinMusic()
}
</script>

<style>
.result-enter-active {
  animation: resultFadeIn 0.42s ease;
}

.result-leave-active {
  animation: resultFadeOut 0.24s ease forwards;
}

@keyframes resultFadeIn {
  from {
    opacity: 0;
    transform: scale(1.03);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes resultFadeOut {
  from {
    opacity: 1;
    transform: scale(1);
  }
  to {
    opacity: 0;
    transform: scale(0.985);
  }
}

.animate-pop {
  animation: pop 0.8s ease-out;
}

@keyframes pop {
  0% {
    transform: scale(0.3);
    opacity: 0;
  }
  60% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

.blessing-wrap {
  position: relative;
  width: min(92vw, 520px);
  min-height: min(84vh, 680px);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  isolation: isolate;
}

.blessing-glow {
  position: absolute;
  left: 50%;
  bottom: 120px;
  width: 460px;
  height: 300px;
  border-radius: 50%;
  background: radial-gradient(
    ellipse at center,
    rgba(255, 247, 219, 0.32) 0%,
    rgba(244, 229, 188, 0.16) 36%,
    rgba(244, 229, 188, 0.06) 54%,
    rgba(244, 229, 188, 0) 76%
  );
  transform: translateX(-50%);
  filter: blur(34px);
  z-index: 0;
  pointer-events: none;
}

.blessing-fan-scene {
  position: relative;
  width: min(92vw, 520px);
  height: 510px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 1;
}

.blessing-fan {
  position: absolute;
  left: 50%;
  bottom: 28px;
  width: min(92vw, 520px);
  height: 408px;
  transform: translateX(-50%);
  z-index: 1;
}

.blessing-tag-stage {
  position: absolute;
  left: 50%;
  bottom: 28px;
  width: 188px;
  height: 550px;
  transform: translateX(-50%);
  z-index: 2;
}

.blessing-fan-item {
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 88px;
  height: 450px;
  transform-origin: center 100%;
  transform: translateX(calc(-50% + var(--x-offset))) translateY(var(--y-offset))
    rotate(var(--angle)) scale(var(--scale));
}

.blessing-fan-face {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 1.45rem;
  background:
    radial-gradient(circle at top, rgba(255, 255, 255, 0.34), transparent 42%),
    linear-gradient(180deg, #fffdf8 0%, #f8f0de 58%, #efe1bf 100%);
  border: 1px solid rgba(216, 200, 169, 0.7);
  box-shadow:
    0 18px 32px rgba(58, 39, 18, 0.16),
    0 8px 18px rgba(138, 105, 61, 0.12),
    inset 0 1px 0 rgba(255, 255, 255, 0.85);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 14px 8px 16px;
  overflow: hidden;
}

.blessing-fan-face::before {
  content: '';
  position: absolute;
  inset: 8px;
  border-radius: 1.1rem;
  border: 1px solid rgba(210, 192, 157, 0.45);
  pointer-events: none;
}

.blessing-fan-face::after {
  content: '';
  position: absolute;
  left: 14px;
  right: 14px;
  top: 10px;
  height: 56px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.45);
  filter: blur(18px);
  pointer-events: none;
}

.blessing-fan-top {
  position: relative;
  z-index: 1;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.blessing-fan-orb {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #c14a3f;
  box-shadow: 0 0 0 3px rgba(193, 74, 63, 0.08);
}

.blessing-fan-string {
  width: 1.5px;
  height: 16px;
  margin-top: 3px;
  border-radius: 999px;
  background: linear-gradient(180deg, #c14a3f, rgba(193, 74, 63, 0.1));
}

.blessing-fan-label {
  margin-top: 6px;
  color: #9d8460;
  font-size: 8px;
  font-weight: 800;
  letter-spacing: 0.22em;
}

.blessing-fan-meta {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 10px;
  color: #b29467;
}

.blessing-fan-headline {
  font-size: 8px;
  font-weight: 500;
  letter-spacing: 0.08em;
}

.blessing-fan-divider {
  width: 12px;
  height: 1px;
  background: rgba(204, 181, 141, 0.55);
}

.blessing-fan-text {
  position: relative;
  z-index: 1;
  margin-top: 16px;
  flex: 1 1 auto;
  width: 100%;
  padding: 10px 4px 18px;
  color: #503821;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0.08em;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  border-radius: 1rem;
  border: 1px solid rgba(255, 255, 255, 0.5);
  background: rgba(255, 255, 255, 0.18);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.38);
  text-shadow: 0 1px 0 rgba(255, 251, 224, 0.2);
}

.blessing-fan-emoji {
  margin-bottom: 12px;
  color: rgba(104, 69, 0, 0.82);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.08em;
  line-height: 1;
}

.blessing-fan-char {
  position: relative;
  line-height: 1;
}

.blessing-fan-char.is-gap {
  margin: 10px 0;
  opacity: 0;
}

.blessing-fan-char::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -2px;
  width: 2px;
  height: 2px;
  border-radius: 50%;
  background: rgba(167, 119, 7, 0.22);
  transform: translateX(-50%);
}

.blessing-fan-char:last-child::after {
  display: none;
}

.blessing-fan-char.is-gap::after {
  display: none;
}

.blessing-tag {
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 7.5rem;
  min-height: 32rem;
  padding: 20px 14px 26px;
  border-radius: 2.2rem;
  background:
    radial-gradient(circle at top, rgba(255, 255, 255, 0.34), transparent 42%),
    linear-gradient(180deg, #fffdf8 0%, #f8f0de 58%, #efe1bf 100%);
  border: 1px solid rgba(216, 200, 169, 0.7);
  box-shadow:
    0 24px 60px rgba(58, 39, 18, 0.16),
    0 10px 24px rgba(138, 105, 61, 0.12),
    inset 0 1px 0 rgba(255, 255, 255, 0.85);
  display: flex;
  flex-direction: column;
  align-items: center;
  overflow: hidden;
  transform: translateX(-50%);
  z-index: 3;
}

.blessing-tag::before {
  content: '';
  position: absolute;
  inset: 11px;
  border-radius: 1.75rem;
  border: 1px solid rgba(210, 192, 157, 0.45);
  pointer-events: none;
}

.blessing-tag::after {
  content: '';
  position: absolute;
  left: 20px;
  right: 20px;
  top: 14px;
  height: 80px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.45);
  filter: blur(24px);
  pointer-events: none;
}

.blessing-tag-stage::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.16;
  mix-blend-mode: multiply;
  background-image: radial-gradient(rgba(146, 118, 72, 0.28) 0.6px, transparent 0.6px);
  background-size: 7px 7px;
  pointer-events: none;
}

.blessing-tag-top {
  position: relative;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  z-index: 1;
}

.blessing-tag-orb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #c14a3f;
  box-shadow: 0 0 0 4px rgba(193, 74, 63, 0.08);
}

.blessing-tag-string {
  width: 2px;
  height: 26px;
  margin-top: 4px;
  border-radius: 999px;
  background: linear-gradient(180deg, #c14a3f, rgba(193, 74, 63, 0.1));
}

.blessing-tag-label {
  margin-top: 8px;
  color: #9d8460;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.42em;
}

.blessing-tag-meta {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
  color: #b29467;
  font-size: 12px;
  letter-spacing: 0.12em;
}

.blessing-tag-headline {
  color: #b29467;
  font-size: 11px;
  font-weight: 500;
}

.blessing-tag-divider {
  width: 24px;
  height: 1px;
  background: rgba(204, 181, 141, 0.55);
}

.blessing-text {
  position: relative;
  z-index: 1;
  margin: 16px 0;
  width: 100%;
  flex: 1;
  justify-content: center;
  color: #503821;
  font-size: 24px;
  font-weight: 700;
  letter-spacing: 0.14em;
  line-height: 1.26;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 20px 8px;
  border-radius: 1.6rem;
  border: 1px solid rgba(255, 255, 255, 0.5);
  background: rgba(255, 255, 255, 0.18);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.38);
  writing-mode: vertical-rl;
  text-orientation: mixed;
}

.blessing-text.is-long-text {
  font-size: 21px;
}

.blessing-text > span {
  display: inline-block;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.24);
}

.blessing-text > span.is-gap {
  margin: 12px 0;
  opacity: 0;
}

.blessing-tag-seal {
  position: relative;
  z-index: 1;
  margin-top: 18px;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid rgba(199, 93, 79, 0.2);
  background: rgba(185, 65, 53, 0.1);
  color: #b33f34;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.28em;
  box-shadow: 0 4px 10px rgba(185, 65, 53, 0.08);
}

.blessing-caption {
  margin-top: 34px;
  text-align: center;
}

.blessing-caption-title {
  margin: 0;
  color: rgba(255, 255, 255, 0.96);
  font-size: 34px;
  font-weight: 700;
  letter-spacing: 3px;
}

.blessing-caption-subtitle {
  margin: 12px 0 0;
  color: rgba(255, 255, 255, 0.72);
  font-size: 15px;
  letter-spacing: 1px;
}

@media (max-width: 640px) {
  .blessing-wrap {
    width: min(94vw, 390px);
    min-height: 560px;
  }

  .blessing-glow {
    width: 320px;
    height: 220px;
    bottom: 112px;
  }

  .blessing-fan-scene {
    width: min(94vw, 390px);
    height: 434px;
  }

  .blessing-fan {
    width: min(94vw, 390px);
    height: 350px;
    bottom: 24px;
  }

  .blessing-fan-item {
    width: 74px;
    height: 304px;
  }

  .blessing-fan-face {
    padding: 12px 6px 12px;
  }

  .blessing-tag-stage {
    width: 160px;
    height: 484px;
    bottom: 24px;
  }

  .blessing-tag {
    width: 9.6rem;
    min-height: 27rem;
    padding: 18px 12px 22px;
  }

  .blessing-fan-text {
    margin-top: 12px;
    padding: 14px 2px;
    font-size: 13px;
    gap: 6px;
  }

  .blessing-fan-emoji {
    margin-bottom: 8px;
    font-size: 14px;
  }

  .blessing-fan-char.is-gap {
    margin: 8px 0;
  }

  .blessing-fan-label,
  .blessing-fan-headline {
    font-size: 7px;
  }

  .blessing-text {
    font-size: 20px;
    padding: 18px 6px;
  }

  .blessing-text.is-long-text {
    font-size: 18px;
  }

  .blessing-text > span.is-gap {
    margin: 10px 0;
  }

  .blessing-caption-title {
    font-size: 28px;
  }
}
</style>
