<script setup lang="ts">
import { ref, onMounted, computed, onBeforeUnmount } from 'vue'
import { useWishStore } from '@/stores/wish'
import { useAuthStore } from '@/stores/auth'
import WishPanel from '@/components/WishPanel.vue'
import UndoBanner from '@/components/UndoBanner.vue'

const mobilePanelOpen = ref(false)
const filterOpen = ref(false)
const isMobileViewport = ref(false)
const MOBILE_TREE_LIMIT = 9
const DESKTOP_TREE_LIMIT = 30

const CARD_COLORS = ['card-rose', 'card-amber', 'card-mint', 'card-sky', 'card-violet', 'card-peach'] as const

const STATUS_ICONS: Record<string, string> = {
  active: '\u{1F331}',
  expired: '\u{1F31F}',
  fulfilled: '\u{2728}',
}

const STATUS_LABELS: Record<string, string> = {
  active: '\u{1F331} 愿望实现中',
  expired: '\u{1F31F} 已过期',
  fulfilled: '\u{2728} 已实现',
}

const FILTER_OPTIONS = [
  { value: 'all', label: '全部' },
  { value: 'active', label: '未实现' },
  { value: 'fulfilled', label: '已实现' },
  { value: 'expired', label: '已过期' },
] as const

const wishStore = useWishStore()
const authStore = useAuthStore()

// Popover state
const hoveredWishId = ref<number | null>(null)
const popoverPos = ref({ x: 0, y: 0 })
let hoverTimer: ReturnType<typeof setTimeout> | null = null

const popoverWish = computed(() => {
  if (!hoveredWishId.value) return null
  return wishStore.treeWishes.find(w => w.id === hoveredWishId.value) ?? null
})

const isOwner = computed(() => {
  if (!popoverWish.value || !authStore.user) return false
  return popoverWish.value.user_id === authStore.user.id
})

const canFulfill = computed(() => {
  return isOwner.value && popoverWish.value?.is_fulfilled !== 1
})

function formatDateTime(ts: number) {
  const d = new Date(ts * 1000)
  const pad = (n: number) => String(n).padStart(2, '0')
  return `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())} (UTC+8)`
}

function onCardEnter(wish: any, event: MouseEvent) {
  if (isMobileViewport.value) return
  if (hoverTimer) { clearTimeout(hoverTimer); hoverTimer = null }
  const target = event.currentTarget as HTMLElement
  const rect = target.getBoundingClientRect()
  popoverPos.value = {
    x: rect.left + rect.width / 2,
    y: rect.bottom + 8,
  }
  hoveredWishId.value = wish.id
}

function onCardLeave() {
  if (isMobileViewport.value) return
  if (hoverTimer) clearTimeout(hoverTimer)
  hoverTimer = setTimeout(() => { hoveredWishId.value = null }, 200)
}

function onPopoverEnter() {
  if (isMobileViewport.value) return
  if (hoverTimer) { clearTimeout(hoverTimer); hoverTimer = null }
}

function onPopoverLeave() {
  if (isMobileViewport.value) return
  if (hoverTimer) clearTimeout(hoverTimer)
  hoverTimer = setTimeout(() => { hoveredWishId.value = null }, 200)
}

function updateViewportMode() {
  const nextIsMobile = window.innerWidth <= 768
  const nextLimit = nextIsMobile ? MOBILE_TREE_LIMIT : DESKTOP_TREE_LIMIT
  const limitChanged = wishStore.treeLimit !== nextLimit

  isMobileViewport.value = nextIsMobile
  wishStore.setTreeLimit(nextLimit)

  if (limitChanged && wishStore.treeWishes.length > 0) {
    wishStore.fetchTreeWishes(1, wishStore.treeFilter)
  }
}

function openWishDetail(wish: any, event: MouseEvent) {
  if (!isMobileViewport.value) {
    onCardEnter(wish, event)
    return
  }
  if (hoverTimer) { clearTimeout(hoverTimer); hoverTimer = null }
  hoveredWishId.value = wish.id
}

function closeWishDetail() {
  hoveredWishId.value = null
}

async function fulfillWish() {
  if (!popoverWish.value) return
  await wishStore.fulfillWish(popoverWish.value.id)
  await wishStore.fetchTreeWishes()
  await wishStore.fetchMyWishes()
}

async function deleteWish() {
  if (!popoverWish.value) return
  await wishStore.deleteWish(popoverWish.value.id)
  hoveredWishId.value = null
  await wishStore.fetchTreeWishes()
  await wishStore.fetchMyWishes()
  await wishStore.fetchDeletedWishes()
}

const currentFilterLabel = computed(() => {
  const opt = FILTER_OPTIONS.find(o => o.value === wishStore.treeFilter)
  return opt ? opt.label : '全部'
})

async function handleUndo(wishId: number) {
  try {
    await wishStore.restoreWish(wishId)
    await wishStore.fetchTreeWishes()
    await wishStore.fetchMyWishes()
    await wishStore.fetchDeletedWishes()
  } catch {
    // restore failed — banner stays
  }
}

async function refreshDeletedState() {
  if (authStore.isAuthenticated) {
    await wishStore.fetchDeletedWishes()
  }
}

function setFilter(value: string) {
  filterOpen.value = false
  wishStore.fetchTreeWishes(1, value)
}

function closeFilter(e: MouseEvent) {
  if (filterOpen.value && !(e.target as HTMLElement).closest('.filter-dropdown')) {
    filterOpen.value = false
  }
}

function prevPage() {
  if (wishStore.treePage > 1) wishStore.fetchTreeWishes(wishStore.treePage - 1, wishStore.treeFilter)
}
function nextPage() {
  if (wishStore.treePage < wishStore.treeTotalPages) wishStore.fetchTreeWishes(wishStore.treePage + 1, wishStore.treeFilter)
}

onMounted(async () => {
  updateViewportMode()
  wishStore.fetchTreeWishes()
  await refreshDeletedState()
  document.addEventListener('click', closeFilter)
  window.addEventListener('resize', updateViewportMode)
})
onBeforeUnmount(() => {
  document.removeEventListener('click', closeFilter)
  window.removeEventListener('resize', updateViewportMode)
  if (hoverTimer) clearTimeout(hoverTimer)
})
</script>

<template>
  <div class="min-h-screen bg-page-bg">
    <!-- Hero -->
    <section class="px-6 pt-7 pb-4 md:px-10">
      <a
        href="https://jerry20062016-clouduse.hf.space/"
        class="inline-flex items-center px-3.5 py-2 rounded-full bg-gold/12 text-gold-deep text-xs font-bold tracking-widest uppercase transition-colors hover:bg-gold/18 focus:outline-none focus:ring-2 focus:ring-gold/30"
      >
        Wish Tree
      </a>
      <h1 class="mt-3.5 mb-2.5 text-[clamp(2.3rem,4vw,4.4rem)] leading-[0.96] tracking-tight font-semibold text-text-main">
        把愿望挂上树，让它在时间里慢慢发芽。
      </h1>
      <p class="max-w-[760px] text-text-soft leading-[1.72]">
        在这里许下你的心愿。每一个愿望都是一颗种子，有人为你浇灌，有人为你守护。愿所有美好的期许，都能在时光中生根。
      </p>
    </section>

    <!-- Two-column layout -->
    <div class="flex gap-4 px-6 md:px-10">
      <!-- Sidebar panel (desktop) -->
      <div class="hidden lg:block w-[340px] flex-shrink-0">
        <div class="sticky top-4 rounded-xl bg-white/96 border border-gold/18">
          <WishPanel />
        </div>
      </div>

      <!-- Mobile panel toggle -->
      <button
        type="button"
        class="lg:hidden fixed bottom-4 right-4 z-50 w-12 h-12 rounded-full bg-gold text-white shadow-lg flex items-center justify-center text-xl"
        @click="mobilePanelOpen = !mobilePanelOpen"
      >
        {{ mobilePanelOpen ? '\u2715' : '\u{1F331}' }}
      </button>

      <!-- Mobile panel overlay -->
      <Transition name="slide">
        <div
          v-if="mobilePanelOpen"
          class="lg:hidden fixed inset-0 z-40 bg-black/30"
          @click.self="mobilePanelOpen = false"
        >
          <div class="absolute right-0 top-0 bottom-0 w-[340px] max-w-[90vw] bg-page-bg overflow-y-auto shadow-2xl">
            <div class="p-4">
              <button
                type="button"
                class="ml-auto block text-text-muted hover:text-text-soft text-lg"
                @click="mobilePanelOpen = false"
              >
                Close
              </button>
            </div>
            <WishPanel />
          </div>
        </div>
      </Transition>

      <!-- Tree area -->
      <div class="relative flex-1 min-w-0">
        <!-- Undo Banner -->
        <UndoBanner v-if="wishStore.deletedWishes.length > 0" @undo="handleUndo" />

        <!-- Filter -->
        <div class="mb-3 relative filter-dropdown">
          <button
            type="button"
            class="inline-flex items-center gap-2 bg-panel-bg rounded-lg px-4 py-2 border border-gold/10 text-sm hover:bg-white/60 transition-colors"
            @click.stop="filterOpen = !filterOpen"
          >
            <span class="text-text-soft font-medium">{{ currentFilterLabel }}</span>
            <svg class="w-4 h-4 text-text-muted transition-transform" :class="{ 'rotate-180': filterOpen }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
            </svg>
          </button>
          <Transition name="fade">
            <div
              v-if="filterOpen"
              class="absolute top-full left-0 mt-1 w-36 bg-white rounded-lg border border-gold/10 shadow-lg z-20 py-1 overflow-hidden"
            >
              <button
                v-for="opt in FILTER_OPTIONS"
                :key="opt.value"
                type="button"
                class="w-full text-left px-3.5 py-2 text-sm hover:bg-gold/8 transition-colors"
                :class="wishStore.treeFilter === opt.value ? 'text-gold font-semibold bg-gold/6' : 'text-text-main'"
                @click="setFilter(opt.value)"
              >
                {{ opt.label }}
              </button>
            </div>
          </Transition>
        </div>

        <!-- Tree Wallpaper Background -->
        <div class="tree-wallpaper">
          <svg class="tree-wallpaper-svg" viewBox="0 0 1200 800" preserveAspectRatio="xMidYMid slice" xmlns="http://www.w3.org/2000/svg">
            <!-- Tree 1 - far left -->
            <g class="mini-tree" transform="translate(80, 520) scale(0.6)">
              <polygon points="50,0 100,70 0,70" fill="currentColor" opacity="0.5" />
              <polygon points="50,30 110,110 -10,110" fill="currentColor" opacity="0.45" />
              <polygon points="50,70 120,150 -20,150" fill="currentColor" opacity="0.4" />
              <rect x="43" y="150" width="14" height="40" rx="3" fill="currentColor" opacity="0.3" />
            </g>
            <!-- Tree 2 - left-center -->
            <g class="mini-tree" transform="translate(260, 440) scale(0.8)">
              <polygon points="50,0 95,65 5,65" fill="currentColor" opacity="0.4" />
              <polygon points="50,25 105,100 -5,100" fill="currentColor" opacity="0.35" />
              <polygon points="50,60 115,140 -15,140" fill="currentColor" opacity="0.3" />
              <rect x="44" y="140" width="12" height="35" rx="3" fill="currentColor" opacity="0.25" />
            </g>
            <!-- Tree 3 - center-left -->
            <g class="mini-tree" transform="translate(480, 380) scale(1.0)">
              <polygon points="50,0 90,60 10,60" fill="currentColor" opacity="0.35" />
              <polygon points="50,20 100,90 0,90" fill="currentColor" opacity="0.3" />
              <polygon points="50,50 110,130 -10,130" fill="currentColor" opacity="0.25" />
              <rect x="44" y="130" width="12" height="35" rx="3" fill="currentColor" opacity="0.2" />
            </g>
            <!-- Tree 4 - center (tallest) -->
            <g class="mini-tree" transform="translate(680, 300) scale(1.1)">
              <polygon points="50,0 85,55 15,55" fill="currentColor" opacity="0.3" />
              <polygon points="50,18 95,82 5,82" fill="currentColor" opacity="0.25" />
              <polygon points="50,45 105,120 -5,120" fill="currentColor" opacity="0.2" />
              <rect x="44" y="120" width="12" height="32" rx="3" fill="currentColor" opacity="0.18" />
            </g>
            <!-- Tree 5 - right-center -->
            <g class="mini-tree" transform="translate(900, 420) scale(0.75)">
              <polygon points="50,0 92,62 8,62" fill="currentColor" opacity="0.38" />
              <polygon points="50,22 102,95 -2,95" fill="currentColor" opacity="0.32" />
              <polygon points="50,55 112,135 -12,135" fill="currentColor" opacity="0.27" />
              <rect x="43" y="135" width="14" height="36" rx="3" fill="currentColor" opacity="0.22" />
            </g>
            <!-- Tree 6 - far right -->
            <g class="mini-tree" transform="translate(1080, 500) scale(0.55)">
              <polygon points="50,0 96,68 4,68" fill="currentColor" opacity="0.45" />
              <polygon points="50,28 108,108 -8,108" fill="currentColor" opacity="0.4" />
              <polygon points="50,65 118,148 -18,148" fill="currentColor" opacity="0.35" />
              <rect x="43" y="148" width="14" height="38" rx="3" fill="currentColor" opacity="0.28" />
            </g>
            <!-- Small accent trees -->
            <g class="mini-tree" transform="translate(170, 600) scale(0.4)">
              <polygon points="50,0 90,60 10,60" fill="currentColor" opacity="0.35" />
              <polygon points="50,25 100,90 0,90" fill="currentColor" opacity="0.3" />
              <rect x="44" y="90" width="12" height="28" rx="3" fill="currentColor" opacity="0.2" />
            </g>
            <g class="mini-tree" transform="translate(780, 580) scale(0.35)">
              <polygon points="50,0 88,58 12,58" fill="currentColor" opacity="0.32" />
              <polygon points="50,22 98,88 2,88" fill="currentColor" opacity="0.27" />
              <rect x="44" y="88" width="12" height="25" rx="3" fill="currentColor" opacity="0.18" />
            </g>
          </svg>
        </div>

        <!-- Wish Cards Grid -->
        <TransitionGroup :name="isMobileViewport ? '' : 'card-enter'" tag="div" class="wish-grid">
          <div
            v-for="(wish, i) in wishStore.treeWishes"
            :key="wish.id"
            class="wish-card-slot"
            :class="[
              CARD_COLORS[i % CARD_COLORS.length],
              { 'is-expired': wish.status === 'expired', 'is-fulfilled': wish.status === 'fulfilled' },
            ]"
            @mouseenter="onCardEnter(wish, $event)"
            @mouseleave="onCardLeave"
          >
            <button type="button" class="cursor-pointer w-full" @click="openWishDetail(wish, $event)">
              <span class="text-base">{{ STATUS_ICONS[wish.status] || '\u{1F331}' }}</span>
              <div class="mt-1 text-sm font-extrabold leading-tight truncate wish-card-title">{{ wish.animal_name }}</div>
              <div class="text-[11px] font-semibold opacity-80 wish-card-meta">W{{ wish.id }}</div>
            </button>
          </div>
        </TransitionGroup>

        <!-- Card Detail Popover -->
        <Transition name="popover">
          <div
            v-if="popoverWish"
            class="card-popover"
            :style="{ left: popoverPos.x + 'px', top: popoverPos.y + 'px' }"
            @mouseenter="onPopoverEnter"
            @mouseleave="onPopoverLeave"
          >
            <div class="card-popover-arrow" />
            <div class="p-4 text-sm space-y-1.5">
              <div class="flex items-center gap-2 mb-2">
                <span class="text-base">{{ STATUS_LABELS[popoverWish.status] || STATUS_LABELS.active }}</span>
              </div>
              <div><span class="text-text-muted">许愿的人:</span> <span class="font-semibold text-text-main">{{ popoverWish.animal_name }}</span></div>
              <div><span class="text-text-muted">TA的愿望:</span> {{ popoverWish.content }}</div>
              <div><span class="text-text-muted">创建时间:</span> {{ formatDateTime(popoverWish.created_at) }}</div>
              <div><span class="text-text-muted">过期时间:</span> {{ formatDateTime(popoverWish.expires_at) }}</div>
              <div v-if="popoverWish.ai_response" class="pt-2 mt-2 border-t border-gold/10 text-text-soft leading-relaxed italic">
                "{{ popoverWish.ai_response }}"
              </div>
              <div v-if="isOwner" class="flex items-center gap-2 pt-2 mt-2 border-t border-gold/10">
                <button
                  v-if="canFulfill"
                  type="button"
                  class="px-3 h-7 rounded-md bg-amber-500 text-white text-xs font-medium hover:bg-amber-600 transition-colors"
                  @click.stop="fulfillWish"
                >
                  还愿
                </button>
                <button
                  type="button"
                  class="px-3 h-7 rounded-md bg-red-500 text-white text-xs font-medium hover:bg-red-600 transition-colors"
                  @click.stop="deleteWish"
                >
                  删除
                </button>
              </div>
            </div>
          </div>
        </Transition>

        <Transition name="sheet">
          <div v-if="popoverWish && isMobileViewport" class="mobile-detail-overlay" @click.self="closeWishDetail">
            <div class="mobile-detail-sheet">
              <div class="mobile-detail-handle" />
              <div class="p-4 text-sm space-y-1.5">
                <div class="flex items-center justify-between gap-3 mb-2">
                  <span class="text-base">{{ STATUS_LABELS[popoverWish.status] || STATUS_LABELS.active }}</span>
                  <button type="button" class="text-text-muted text-lg leading-none" @click="closeWishDetail">&times;</button>
                </div>
                <div><span class="text-text-muted">许愿的人:</span> <span class="font-semibold text-text-main">{{ popoverWish.animal_name }}</span></div>
                <div><span class="text-text-muted">TA的愿望:</span> {{ popoverWish.content }}</div>
                <div><span class="text-text-muted">创建时间:</span> {{ formatDateTime(popoverWish.created_at) }}</div>
                <div><span class="text-text-muted">过期时间:</span> {{ formatDateTime(popoverWish.expires_at) }}</div>
                <div v-if="popoverWish.ai_response" class="pt-2 mt-2 border-t border-gold/10 text-text-soft leading-relaxed italic">
                  "{{ popoverWish.ai_response }}"
                </div>
                <div v-if="isOwner" class="flex items-center gap-2 pt-2 mt-2 border-t border-gold/10">
                  <button
                    v-if="canFulfill"
                    type="button"
                    class="px-3 h-9 rounded-md bg-amber-500 text-white text-sm font-medium"
                    @click.stop="fulfillWish"
                  >
                    还愿
                  </button>
                  <button
                    type="button"
                    class="px-3 h-9 rounded-md bg-red-500 text-white text-sm font-medium"
                    @click.stop="deleteWish"
                  >
                    删除
                  </button>
                </div>
              </div>
            </div>
          </div>
        </Transition>

        <!-- Pagination -->
        <div class="flex items-center justify-between gap-4 mt-6 px-1 pb-6">
          <button
            type="button"
            class="px-3.5 h-10 rounded-lg bg-white/76 border border-gold/10 text-sm font-medium text-text-main hover:bg-white transition-colors disabled:opacity-40"
            :disabled="wishStore.treePage <= 1"
            @click="prevPage"
          >
            ← 上一页
          </button>
          <span class="text-center text-text-soft text-sm font-bold flex-1">
            {{ wishStore.treePage }}/{{ wishStore.treeTotalPages }}
            <span class="text-text-muted ml-2">共 {{ wishStore.treeTotal }} 个愿望</span>
          </span>
          <button
            type="button"
            class="px-3.5 h-10 rounded-lg bg-white/76 border border-gold/10 text-sm font-medium text-text-main hover:bg-white transition-colors disabled:opacity-40"
            :disabled="wishStore.treePage >= wishStore.treeTotalPages"
            @click="nextPage"
          >
            下一页 →
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
/* Tree wallpaper background */
.tree-wallpaper {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 0;
}

.tree-wallpaper-svg {
  width: 100%;
  height: 100%;
  color: #8bba7a;
  opacity: 0.6;
  filter: saturate(0.82) blur(0.2px);
}

.tree-wallpaper::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(255, 250, 241, 0.12) 0%, rgba(255, 250, 241, 0.36) 100%),
    linear-gradient(90deg, rgba(255, 250, 241, 0.32) 0%, rgba(255, 250, 241, 0.08) 42%, rgba(255, 250, 241, 0.18) 100%);
}

/* Wish cards grid */
.wish-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  gap: 16px;
  padding: 16px 0;
}

.wish-card-slot {
  position: relative;
}

.wish-card-slot::before {
  content: "";
  position: absolute;
  left: 50%;
  top: -34px;
  width: 2px;
  height: 36px;
  margin-left: -1px;
  background: linear-gradient(180deg, rgba(248, 229, 182, 0.96) 0%, rgba(151, 118, 52, 0.38) 100%);
  z-index: 0;
}

.wish-card-slot::after {
  content: "";
  position: absolute;
  left: 50%;
  top: -6px;
  width: 12px;
  height: 12px;
  margin-left: -6px;
  border-radius: 999px;
  background: #f4d061;
  box-shadow: 0 1px 4px rgba(73, 52, 28, 0.18);
  z-index: 1;
}

.wish-card-slot button {
  min-height: 74px;
  padding: 10px 8px;
  border-radius: 12px;
  border: 1px solid rgba(67, 48, 31, 0.14);
  box-shadow: 0 12px 24px rgba(70, 50, 30, 0.14);
  font-weight: 700;
  white-space: normal;
  line-height: 1.2;
  width: 100%;
  text-align: left;
  background: none;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
}

/* Card colors */
.card-rose button { background: linear-gradient(135deg, rgba(255, 213, 222, 0.96) 0%, rgba(255, 235, 239, 0.98) 100%); color: #6d2436; }
.card-amber button { background: linear-gradient(135deg, rgba(255, 228, 181, 0.96) 0%, rgba(255, 242, 215, 0.98) 100%); color: #71440a; }
.card-mint button { background: linear-gradient(135deg, rgba(217, 245, 234, 0.96) 0%, rgba(239, 251, 246, 0.98) 100%); color: #1e5743; }
.card-sky button { background: linear-gradient(135deg, rgba(216, 235, 255, 0.96) 0%, rgba(238, 246, 255, 0.98) 100%); color: #1a467d; }
.card-violet button { background: linear-gradient(135deg, rgba(234, 220, 255, 0.96) 0%, rgba(245, 239, 255, 0.98) 100%); color: #51317e; }
.card-peach button { background: linear-gradient(135deg, rgba(255, 220, 202, 0.96) 0%, rgba(255, 241, 232, 0.98) 100%); color: #7a3d21; }

.wish-card-title {
  letter-spacing: 0.01em;
}

.wish-card-meta {
  color: rgba(47, 38, 29, 0.74);
}

/* Card hover popover */
.card-popover {
  position: fixed;
  z-index: 100;
  width: min(320px, calc(100vw - 32px));
  transform: translateX(-50%);
  background: rgba(255, 253, 247, 0.98);
  border: 1px solid rgba(98, 73, 43, 0.12);
  border-radius: 16px;
  box-shadow: 0 20px 60px rgba(47, 38, 29, 0.18);
  backdrop-filter: blur(12px);
}

.card-popover-arrow {
  position: absolute;
  top: -6px;
  left: 50%;
  transform: translateX(-50%) rotate(45deg);
  width: 12px;
  height: 12px;
  background: rgba(255, 253, 247, 0.98);
  border-left: 1px solid rgba(98, 73, 43, 0.12);
  border-top: 1px solid rgba(98, 73, 43, 0.12);
}

/* Popover transition */
.popover-enter-active,
.popover-leave-active {
  transition: opacity 0.15s ease, transform 0.15s ease;
}

.popover-enter-from,
.popover-leave-to {
  opacity: 0;
  transform: translateX(-50%) translateY(4px);
}

.mobile-detail-overlay {
  position: fixed;
  inset: 0;
  z-index: 110;
  background: rgba(26, 20, 12, 0.32);
  display: flex;
  align-items: flex-end;
}

.mobile-detail-sheet {
  width: 100%;
  background: rgba(255, 253, 247, 0.98);
  border-radius: 20px 20px 0 0;
  box-shadow: 0 -12px 36px rgba(47, 38, 29, 0.18);
  backdrop-filter: blur(12px);
  padding-bottom: max(16px, env(safe-area-inset-bottom));
}

.mobile-detail-handle {
  width: 44px;
  height: 5px;
  border-radius: 999px;
  background: rgba(120, 96, 61, 0.24);
  margin: 10px auto 2px;
}

/* Card states */
.wish-card-slot.is-expired button {
  background: linear-gradient(135deg, #e6e1da 0%, #f4f1ed 100%) !important;
  color: #7a7064 !important;
  box-shadow: 0 8px 18px rgba(90, 80, 68, 0.1) !important;
  filter: saturate(0.4);
}

.wish-card-slot.is-fulfilled button {
  background: linear-gradient(135deg, #dbead2 0%, #edf6e8 100%) !important;
  color: #47613d !important;
  border-color: rgba(71, 97, 61, 0.18) !important;
  box-shadow: 0 12px 24px rgba(71, 97, 61, 0.14) !important;
}

/* Mobile responsive */
@media (max-width: 768px) {
  .card-popover {
    display: none;
  }

  .wish-grid {
    grid-template-columns: repeat(auto-fill, minmax(98px, 1fr));
    gap: 12px;
  }

  .wish-card-slot button {
    min-height: 64px;
    padding: 8px 6px;
    font-size: 0.78rem;
  }

  .wish-card-slot::before {
    height: 28px;
    top: -28px;
  }

  .wish-card-slot::after {
    width: 10px;
    height: 10px;
    top: -5px;
    margin-left: -5px;
  }

  .card-enter-enter-active,
  .card-enter-leave-active {
    position: relative;
    transition: none !important;
  }

  .card-enter-enter-from,
  .card-enter-leave-to {
    opacity: 1;
    transform: none;
  }
}

.sheet-enter-active,
.sheet-leave-active {
  transition: opacity 0.2s ease;
}

.sheet-enter-active .mobile-detail-sheet,
.sheet-leave-active .mobile-detail-sheet {
  transition: transform 0.2s ease;
}

.sheet-enter-from,
.sheet-leave-to {
  opacity: 0;
}

.sheet-enter-from .mobile-detail-sheet,
.sheet-leave-to .mobile-detail-sheet {
  transform: translateY(100%);
}

/* Card enter animation */
.card-enter-enter-active {
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.card-enter-enter-from {
  opacity: 0;
  transform: translateY(8px) scale(0.97);
}
.card-enter-leave-active {
  position: absolute;
  transition: opacity 0.14s ease;
}
.card-enter-leave-to {
  opacity: 0;
}

/* Filter dropdown transition */
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.15s ease;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

/* Mobile panel transition */
.slide-enter-active,
.slide-leave-active {
  transition: opacity 0.2s ease;
}

.slide-enter-active > div,
.slide-leave-active > div {
  transition: transform 0.2s ease;
}

.slide-enter-from,
.slide-leave-to {
  opacity: 0;
}

.slide-enter-from > div,
.slide-leave-to > div {
  transform: translateX(100%);
}
</style>
