<template>
  <view class="aus-result">
    <view class="aus-result-texture"></view>

    <!-- 固定Header -->
    <view ref="fixedHeaderRef" class="aus-result-fixed-header">
      <view class="status-bar-placeholder" :style="{ height: statusBarHeight }"></view>
      <view class="aus-result-header">
        <view class="aus-result-back" @click="$emit('back')">‹</view>
        <text class="aus-result-title">择吉结果</text>
        <view class="aus-result-header-spacer"></view>
      </view>
    </view>

    <!-- 头部占位 -->
    <view class="aus-result-header-placeholder" :style="{ height: headerPlaceholderHeight }"></view>

    <scroll-view scroll-y class="aus-result-scroll">
      <view class="aus-result-container">
        <!-- Advice -->
        <view class="aus-advice-card">
          <view class="aus-advice-glow"></view>
          <view class="aus-advice-header">
            <view class="aus-advice-icon">吉</view>
            <view>
              <text class="aus-advice-title">择吉分析报告</text>
              <text class="aus-advice-sub">福主: {{ data.name }} · {{ data.birth_date }}</text>
            </view>
          </view>
          <view class="aus-advice-body">
            <view class="aus-advice-bullet">✦</view>
            <text class="aus-advice-text">
              {{ advice }}
            </text>
          </view>
        </view>

        <!-- Dates timeline -->
        <view class="aus-timeline">
          <view class="aus-timeline-line"></view>
          <view class="aus-timeline-list">
            <view v-for="(item, idx) in resolvedDates" :key="item.date + '_' + idx" class="aus-timeline-item"
              @click="handleDate(item, idx)">
              <view class="aus-timeline-dot" :class="isLocked(idx) ? 'is-locked' : 'is-open'"></view>

              <view class="aus-date-card" :class="isLocked(idx) ? 'is-locked' : 'is-open'">
                <view v-if="isLocked(idx)" class="aus-date-lock">
                  <view class="aus-date-lock-icon">🔒</view>
                  <view class="aus-date-lock-text">解锁后查看完整吉时与冲煞</view>
                </view>
                <view class="aus-date-inner">
                  <view class="aus-date-head">
                    <view>
                      <text class="aus-date-day">{{ item.date }}</text>
                      <text class="aus-date-lunar">{{ item.lunar }}</text>
                    </view>
                    <view class="aus-date-score">
                      <text class="aus-date-score-num">{{ item.score }}</text>
                      <text class="aus-date-score-label">吉运指数</text>
                    </view>
                  </view>
                  <view class="aus-date-desc">
                    <text>{{ item.desc }}</text>
                  </view>
                  <view class="aus-date-meta">
                    <view class="aus-date-meta-item">
                      <text>吉时</text>
                      <text>{{ displayHours(item, idx) }}</text>
                    </view>
                    <view class="aus-date-meta-item">
                      <text>冲</text>
                      <text>{{ displayClash(item, idx) }}</text>
                    </view>
                  </view>
                </view>
              </view>
            </view>
          </view>
        </view>

        <view v-if="!resolvedDates.length" class="aus-empty">
          <text class="aus-empty-title">{{ repairingDates ? '正在恢复择吉结果...' : '暂无可展示的择吉日期' }}</text>
          <text class="aus-empty-sub">
            {{ repairingDates ? '系统正在自动补全数据，请稍候' : (repairError || '请返回重试，或稍后再查看报告结果') }}
          </text>
          <button v-if="!repairingDates" class="aus-empty-action" @click="attemptRecalculate(true)">
            重新获取择吉结果
          </button>
        </view>

        <view class="aus-bottom-gap"></view>
      </view>
    </scroll-view>

    <!-- Pay sheet -->
    <view v-if="false && showPay && unlocked !== 'premium'" class="aus-paymask" @tap="showPay = false" @touchmove.stop.prevent>
      <view class="aus-paycard" @tap.stop>
        <view class="aus-pay-title-row">
          <text class="aus-pay-title">解锁完整择吉报告</text>
        </view>

        <view class="aus-pay-close" @tap="showPay = false">×</view>

        <view class="aus-pay-cards">
          <button class="aus-pay-card aus-pay-card-basic" @click="unlock('basic')">
            <view class="aus-pay-card-title">近期吉日</view>
            <view class="aus-pay-card-sub">未来30天精选</view>
            <view class="aus-pay-price">
              <text class="aus-pay-price-sign">¥</text>
              <text class="aus-pay-price-num">9.9</text>
            </view>
          </button>

          <button class="aus-pay-card aus-pay-card-premium" @click="unlock('premium')">
            <view class="aus-pay-card-top">
              <view class="aus-pay-card-title">全年尊享</view>
              <view class="aus-pay-chip">推荐</view>
            </view>
            <view class="aus-pay-card-sub">1年吉日 + 时辰</view>
            <view class="aus-pay-price">
              <text class="aus-pay-price-sign">¥</text>
              <text class="aus-pay-price-num">38</text>
              <text class="aus-pay-price-origin">99.9</text>
            </view>
          </button>
        </view>

        <button class="aus-pay-share" open-type="share" @click="prepareShareUnlock">
          <text class="aus-pay-share-text">分享到朋友圈免费解锁</text>
        </button>
        <text class="aus-pay-footnote">*每月限 1 次免费解锁机会</text>
      </view>
    </view>

    <!-- Poster -->
    <view v-if="showPoster && activeDate" class="aus-poster-mask" @click="showPoster = false">
      <view class="aus-poster" @click.stop>
        <div class="aus-poster-close" @click="showPoster = false">×</div>
        <view class="aus-poster-body">
          <view class="aus-poster-bar"></view>
          <view class="aus-poster-content">
            <view class="aus-poster-icon">吉</view>
            <text class="aus-poster-title">{{ label(data.zeji_type, data.zeji_purpose) }}大吉</text>
            <text class="aus-poster-sub">壹梵玄学 · 精准八字择吉</text>
            <view class="aus-poster-card">
              <view class="aus-poster-card-line"></view>
              <text class="aus-poster-date">{{ activeDate.date }}</text>
              <text class="aus-poster-lunar">{{ activeDate.lunar }}</text>
              <view class="aus-poster-meta">
                <view class="aus-poster-meta-block">
                  <text class="aus-poster-meta-label">吉时</text>
                  <text class="aus-poster-meta-text">{{ activeDate.hours }}</text>
                </view>
              </view>
              <view class="aus-poster-divider"></view>
              <text class="aus-poster-desc">“{{ activeDate.desc }}”</text>
            </view>
          </view>
          <!-- <view class="aus-poster-footer">
            <view class="aus-poster-owner">
              <text class="aus-poster-owner-label">福主</text>
              <text class="aus-poster-owner-name">{{ data.name }}</text>
            </view>
            <view class="aus-poster-qr">
              <view class="aus-poster-qr-box"></view>
              <text class="aus-poster-qr-tip">扫码测算</text>
            </view>
          </view> -->
        </view>
        <!-- <view class="aus-poster-actions">
          <button class="aus-poster-btn aus-poster-btn-dark">保存图片</button>
          <button class="aus-poster-btn aus-poster-btn-gold" @click="showPoster=false">关闭</button>
        </view> -->
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from "vue";
import { baziZejiApi, type BaziZejiCalculateRequest, type BaziZejiCalculateResponse } from "../../api";

const props = defineProps<{ data: BaziZejiCalculateResponse | Record<string, any> | null }>();
defineEmits<{
  back: [];
}>();

type UnlockLevel = "none" | "basic" | "premium";
type AnyRecord = Record<string, any>;

const unlocked = ref<UnlockLevel>("premium");
const showPay = ref(false);
const showPoster = ref(false);
const activeDate = ref<AnyRecord | null>(null);
const fixedHeaderRef = ref<any>(null);
const headerPlaceholderHeight = ref("120px");
const repairingDates = ref(false);
const repairedOnce = ref(false);
const repairError = ref("");
const hydratedData = ref<AnyRecord | null>(null);

declare const uni: any;

const statusBarHeight = ref("0px");
try {
  const systemInfo = uni?.getSystemInfoSync?.();
  statusBarHeight.value = `${Number(systemInfo?.statusBarHeight || 20)}px`;
} catch {
  statusBarHeight.value = "44px";
}

const updateHeaderPlaceholderHeight = () => {
  if (typeof window === "undefined") return;
  const el =
    (fixedHeaderRef.value?.$el as HTMLElement | undefined) ||
    (fixedHeaderRef.value as HTMLElement | null) ||
    (document.querySelector(".aus-result-fixed-header") as HTMLElement | null);
  if (!el) return;
  const measured = Math.ceil(el.getBoundingClientRect().height);
  if (measured > 0) {
    headerPlaceholderHeight.value = `${measured}px`;
    return;
  }
  headerPlaceholderHeight.value = `calc(${statusBarHeight.value} + 120rpx)`;
};

const DEFAULT_ADVICE = "顺应天时，趋吉避凶。所选吉日均为黄道瑞日，结合福主八字喜用神，可助事半功倍，平安顺遂。";

const tryParseJson = (value: any): any => {
  if (value == null) return null;
  if (typeof value === "object") return value;
  if (typeof value !== "string") return null;
  const raw = value.trim();
  if (!raw) return null;
  try {
    return JSON.parse(raw);
  } catch {
    return null;
  }
};

const toText = (value: any): string => {
  if (value == null) return "";
  if (typeof value === "string") return value.trim();
  if (typeof value === "number" || typeof value === "boolean") return String(value);
  return "";
};

const toNumber = (value: any, fallback = 0): number => {
  const num = Number(value);
  return Number.isFinite(num) ? num : fallback;
};

const firstNonEmpty = (...values: any[]): any => {
  for (const value of values) {
    if (Array.isArray(value) && value.length) return value;
    const text = toText(value);
    if (text) return value;
    if (value && typeof value === "object" && !Array.isArray(value)) return value;
  }
  return null;
};

const toStringArray = (value: any): string[] => {
  if (Array.isArray(value)) {
    return value.map((item) => toText(item)).filter(Boolean);
  }
  if (typeof value === "string") {
    return value
      .split(/[,\uFF0C\u3001|/]/)
      .map((item) => item.trim())
      .filter(Boolean);
  }
  return [];
};

const normalizeHours = (value: any): string => {
  if (Array.isArray(value)) {
    return value.map((item) => toText(item)).filter(Boolean).join(", ");
  }
  if (value && typeof value === "object") {
    return Object.values(value)
      .map((item) => toText(item))
      .filter(Boolean)
      .join(", ");
  }
  return toText(value);
};

const looksLikeDateItem = (value: any): boolean => {
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
  return Boolean(
    firstNonEmpty(
      value.date,
      value.day,
      value.selected_date,
      value.good_date,
      value.target_date,
      value.lunar,
      value.desc,
      value.hours,
      value.clash,
      value.score
    )
  );
};

const DATE_LIST_KEYS = [
  "dates",
  "date_list",
  "auspicious_dates",
  "good_dates",
  "result_dates",
  "days",
  "list",
  "items",
];

const extractDateList = (source: any, depth = 0, visited = new Set<any>()): any[] => {
  if (source == null || depth > 8) return [];

  const parsed = tryParseJson(source);
  if (parsed && parsed !== source) {
    return extractDateList(parsed, depth + 1, visited);
  }

  if (Array.isArray(source)) {
    if (source.some((item) => looksLikeDateItem(tryParseJson(item) ?? item))) {
      return source;
    }
    for (const item of source) {
      const nested = extractDateList(item, depth + 1, visited);
      if (nested.length) return nested;
    }
    return [];
  }

  if (typeof source !== "object") return [];
  if (visited.has(source)) return [];
  visited.add(source);

  for (const key of DATE_LIST_KEYS) {
    const nested = extractDateList((source as AnyRecord)[key], depth + 1, visited);
    if (nested.length) return nested;
  }

  if (looksLikeDateItem(source)) {
    return [source];
  }

  for (const value of Object.values(source as AnyRecord)) {
    const nested = extractDateList(value, depth + 1, visited);
    if (nested.length) return nested;
  }

  return [];
};

const normalizeDateItem = (item: any): AnyRecord | null => {
  const value = tryParseJson(item) ?? item;

  if (typeof value === "string") {
    const date = value.trim();
    return date ? { date, lunar: "", desc: "", score: 0, hours: "", clash: "", suitable: [], avoid: [] } : null;
  }

  if (!value || typeof value !== "object") return null;

  const date = toText(
    firstNonEmpty(
      value.date,
      value.day,
      value.selected_date,
      value.good_date,
      value.target_date,
      value.gregorian_date,
      value.solar_date
    )
  );
  const lunar = toText(firstNonEmpty(value.lunar, value.lunar_date, value.nongli));
  const desc = toText(firstNonEmpty(value.desc, value.description, value.reason, value.summary, value.comment));
  const hours = normalizeHours(
    firstNonEmpty(value.hours, value.good_hours, value.lucky_hours, value.best_hours, value.time_ranges, value.time)
  );
  const clash = toText(firstNonEmpty(value.clash, value.chong, value.conflict, value.avoid_zodiac));
  const score = toNumber(firstNonEmpty(value.score, value.rate, value.rating), 0);
  const suitable = toStringArray(firstNonEmpty(value.suitable, value.yi, value.recommend, value.fit));
  const avoid = toStringArray(firstNonEmpty(value.avoid, value.ji, value.taboo, value.not_fit));

  if (!date && !desc && !hours && !clash) return null;

  return { date, lunar, desc, score, hours, clash, suitable, avoid };
};

const uniqueBy = (items: AnyRecord[]): AnyRecord[] => {
  const seen = new Set<string>();
  const result: AnyRecord[] = [];
  for (const item of items) {
    const key = `${item.date}|${item.lunar}|${item.desc}|${item.hours}|${item.clash}`;
    if (seen.has(key)) continue;
    seen.add(key);
    result.push(item);
  }
  return result;
};

const sourceData = computed<AnyRecord | null>(() => {
  return (hydratedData.value || props.data || null) as AnyRecord | null;
});

const resolvedDates = computed<AnyRecord[]>(() => {
  const rawList = extractDateList(sourceData.value);
  const normalized = uniqueBy(
    rawList.map((item) => normalizeDateItem(item)).filter(Boolean) as AnyRecord[]
  );
  if (normalized.length) return normalized;

  const fallback = normalizeDateItem(sourceData.value);
  return fallback ? [fallback] : [];
});

const safeData = computed<AnyRecord>(() => {
  const base =
    sourceData.value && typeof sourceData.value === "object" && !Array.isArray(sourceData.value)
      ? (sourceData.value as AnyRecord)
      : {};
  const nested = [
    base.data,
    base.result,
    base.report,
    base.payload,
    tryParseJson(base.result_json),
    tryParseJson(base.result_data),
    tryParseJson(base.report_json),
    tryParseJson(base.detail_json),
    tryParseJson(base.extra_data),
  ];
  const merged: AnyRecord = { ...base };
  for (const candidate of nested) {
    if (candidate && typeof candidate === "object" && !Array.isArray(candidate)) {
      Object.assign(merged, candidate);
    }
  }
  return merged;
});

const advice = computed(() => {
  return (
    toText(
      firstNonEmpty(
        safeData.value.advice,
        safeData.value.summary,
        safeData.value.recommendation,
        safeData.value.description
      )
    ) || DEFAULT_ADVICE
  );
});

const normalizeGender = (input: any): "male" | "female" | null => {
  const value = toText(input).toLowerCase();
  if (!value) return null;
  if (value === "male" || value === "m" || value === "1" || value === "男") return "male";
  if (value === "female" || value === "f" || value === "0" || value === "女") return "female";
  return null;
};

const buildRepairRequest = (): BaziZejiCalculateRequest | null => {
  const data = safeData.value;
  const name = toText(firstNonEmpty(data.name, data.user_name, data.username));
  const gender = normalizeGender(firstNonEmpty(data.gender, data.sex, data.user_gender));
  const birthDate = toText(firstNonEmpty(data.birth_date, data.birthDate, data.birth_date_display));
  const birthDateApi = toText(firstNonEmpty(data.birth_date_api, data.birth_datetime, data.birth_date_api_value, data.birth_date));
  const birthPlace = toText(firstNonEmpty(data.birth_place, data.birthPlace, data.city, data.location));
  const zejiType = toText(firstNonEmpty(data.zeji_type, data.event_type, data.type));
  const zejiPurpose = toText(firstNonEmpty(data.zeji_purpose, data.event_name, data.purpose, data.target));
  const dateRangeStart = toText(firstNonEmpty(data.date_range_start, data.start_date, data.range_start));
  const dateRangeEnd = toText(firstNonEmpty(data.date_range_end, data.end_date, data.range_end));

  if (!name || !gender || !birthDate || !birthDateApi || !birthPlace || !zejiType || !zejiPurpose || !dateRangeStart || !dateRangeEnd) {
    return null;
  }

  return {
    name,
    gender,
    birth_date: birthDate,
    birth_date_api: birthDateApi,
    birth_place: birthPlace,
    zeji_type: zejiType as any,
    zeji_purpose: zejiPurpose,
    date_range_start: dateRangeStart,
    date_range_end: dateRangeEnd,
  };
};

const attemptRecalculate = async (force = false) => {
  if (repairingDates.value) return;
  if (resolvedDates.value.length && !force) return;
  if (repairedOnce.value && !force) return;

  const request = buildRepairRequest();
  if (!request) {
    repairError.value = "缺少关键参数，无法自动恢复，请返回择吉表单重新提交。";
    return;
  }

  repairedOnce.value = true;
  repairingDates.value = true;
  repairError.value = "";
  try {
    const result = await baziZejiApi.calculateBaziZeji(request);
    hydratedData.value = result as AnyRecord;
  } catch (error: any) {
    repairError.value = toText(error?.message || error?.msg) || "自动恢复失败，请稍后重试";
  } finally {
    repairingDates.value = false;
    nextTick(updateHeaderPlaceholderHeight);
  }
};

const label = (type: string, purpose?: string) => {
  const map: Record<string, string> = {
    wedding: "婚嫁择吉",
    business: "开业择吉",
    move: "搬家择吉",
    travel: "出行择吉",
    investment: "投资择吉",
    surgery: "手术择吉",
    contract: "签约择吉",
    other: purpose || "择吉",
  };
  return map[type] || purpose || "择吉";
};

const isLocked = (_idx: number) => false;

const displayHours = (item: AnyRecord, idx: number): string => {
  if (isLocked(idx)) return "解锁查看";
  const hours = normalizeHours(item?.hours);
  if (!hours) return "暂无";
  const segments = hours
    .split(/[,\uFF0C\u3001|/]/)
    .map((value) => value.trim())
    .filter(Boolean);
  return segments.length > 1 ? `${segments[0]}...` : segments[0];
};

const displayClash = (item: AnyRecord, idx: number): string => {
  if (isLocked(idx)) return "解锁查看";
  return toText(item?.clash) || "暂无";
};

const prepareShareUnlock = () => {
  showPay.value = false;
};

const handleDate = (item: AnyRecord, _idx: number) => {
  activeDate.value = item;
  showPoster.value = true;
};

const unlock = async (_level: "basic" | "premium") => {
  unlocked.value = "premium";
  showPay.value = false;
};

onMounted(() => {
  nextTick(() => {
    updateHeaderPlaceholderHeight();
    setTimeout(updateHeaderPlaceholderHeight, 0);
  });

  if (typeof window !== "undefined") {
    window.addEventListener("resize", updateHeaderPlaceholderHeight);
  }

  // 不在此自动调用 calculate 接口：会重复创建择吉任务（例如从「我的方案」进入详情、
  // 或返回上一页时若误触发 watch/挂载）。需要补算时由用户点击「重新获取择吉结果」。
});

onBeforeUnmount(() => {
  if (typeof window !== "undefined") {
    window.removeEventListener("resize", updateHeaderPlaceholderHeight);
  }
});

watch(
  () => props.data,
  () => {
    hydratedData.value = null;
    repairedOnce.value = false;
    repairError.value = "";
    nextTick(() => {
      updateHeaderPlaceholderHeight();
    });
  },
  { deep: true }
);
</script>

<style scoped>
.aus-result {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #f0efe9;
  position: relative;
  overflow: hidden;
  font-family: SimSun, "Songti SC", "Songti TC", "Noto Serif SC", STSong, serif;
}

.aus-result-texture {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.4;
  mix-blend-mode: multiply;
  background-image: url("https://www.transparenttextures.com/patterns/rice-paper.png");
  z-index: 0;
}

/* 固定头部容器 */
.aus-result-fixed-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  background: #f0efe9;
}

/* 状态栏占位 */
.status-bar-placeholder {
  width: 100%;
}

/* 头部占位 */
.aus-result-header-placeholder {
  height: calc(var(--status-bar-height, 0) + 100rpx);
  flex-shrink: 0;
}

.aus-result-header {
  position: relative;
  z-index: 10;
  padding: 24rpx 32rpx;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: rgba(253, 251, 247, 0.9);
  border-bottom: 1px solid #e5e5e5;
  backdrop-filter: blur(8px);
  box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.05);
}

.aus-result-back {
  padding: 16rpx;
  margin-left: -8rpx;
  color: #5a5a5a;
  background: transparent;
  border: none;
}

.aus-result-title {
  font-size: 18px;
  font-weight: bold;
  color: #2c2c2c;
  letter-spacing: 0.3em;
}

.aus-result-header-spacer {
  width: 32rpx;
}

.aus-result-scroll {
  flex: 1;
  position: relative;
  z-index: 5;
  padding: 24rpx 24rpx 40rpx;
  height: 0;
}

.aus-result-container {
  width: 96%;
  display: flex;
  flex-direction: column;
  gap: 32rpx;
}

.aus-advice-card {
  position: relative;
  background: linear-gradient(135deg, #2c2c2c, #1a1a1a);
  color: #f2e6d8;
  border-radius: 20rpx;
  padding: 32rpx;
  overflow: hidden;
  box-shadow: 0 16rpx 24rpx -12rpx rgba(0, 0, 0, 0.35);
}

.aus-advice-glow {
  position: absolute;
  top: -24rpx;
  right: -24rpx;
  width: 160rpx;
  height: 160rpx;
  background: #d4af37;
  opacity: 0.18;
  filter: blur(80rpx);
  border-radius: 50%;
}

.aus-advice-header {
  display: flex;
  align-items: center;
  gap: 16rpx;
  margin-bottom: 16rpx;
}

.aus-advice-icon {
  width: 72rpx;
  height: 72rpx;
  border-radius: 50%;
  background: #d4af37;
  color: #1a1a1a;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  font-size: 22px;
  border: 2rpx solid rgba(255, 255, 255, 0.2);
}

.aus-advice-title {
  font-size: 18px;
  font-weight: bold;
  color: #f2e6d8;
  display: block;
}

.aus-advice-sub {
  font-size: 10px;
  color: #ccc;
  letter-spacing: 0.1em;
}

.aus-advice-body {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12rpx;
  padding: 20rpx;
  display: flex;
  align-items: flex-start;
  gap: 10rpx;
  backdrop-filter: blur(4px);
}

.aus-advice-bullet {
  color: #d4af37;
  margin-top: 2rpx;
  flex-shrink: 0;
}

.aus-advice-text {
  font-size: 14px;
  line-height: 1.7;
  color: #e5e5e5;
}

.aus-timeline {
  position: relative;
}

.aus-timeline-line {
  position: absolute;
  left: 48rpx;
  top: 16rpx;
  bottom: 16rpx;
  width: 2rpx;
  background: #dcd3c9;
}

.aus-timeline-list {
  display: flex;
  flex-direction: column;
  gap: 24rpx;
}

.aus-timeline-item {
  position: relative;
  padding-left: 88rpx;
}

.aus-timeline-dot {
  position: absolute;
  left: 42rpx;
  top: 32rpx;
  width: 12rpx;
  height: 12rpx;
  border-radius: 50%;
  border: 4rpx solid #f0efe9;
  z-index: 2;
}

.aus-timeline-dot.is-open {
  background: #8b2323;
}

.aus-timeline-dot.is-locked {
  background: #ccc;
}

.aus-date-card {
  position: relative;
  background: #fffdf9;
  border: 1px solid #d4af37;
  border-radius: 16rpx;
  overflow: hidden;
  box-shadow: 0 10rpx 16rpx -8rpx rgba(0, 0, 0, 0.16);
}

.aus-date-card.is-locked {
  border-color: #e5e5e5;
  opacity: 0.85;
}

.aus-date-card.is-open {
  border-color: rgba(212, 175, 55, 0.3);
}

.aus-date-lock {
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, 0.4);
  backdrop-filter: blur(2px);
  z-index: 10;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8rpx;
}

.aus-date-lock-icon {
  width: 64rpx;
  height: 64rpx;
  background: #2c2c2c;
  color: #d4af37;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 8rpx 14rpx rgba(0, 0, 0, 0.2);
}

.aus-date-lock-text {
  font-size: 12px;
  font-weight: bold;
  color: #2c2c2c;
  background: rgba(255, 255, 255, 0.8);
  padding: 6rpx 12rpx;
  border-radius: 8rpx;
}

.aus-date-inner {
  padding: 24rpx;
  display: flex;
  flex-direction: column;
  gap: 16rpx;
}

.aus-date-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12rpx;
}

.aus-date-day {
  font-size: 20px;
  font-weight: bold;
  color: #2c2c2c;
  display: block;
}

.aus-date-lunar {
  font-size: 12px;
  color: #8b2323;
}

.aus-date-score {
  text-align: right;
}

.aus-date-score-num {
  font-size: 24px;
  font-weight: bold;
  color: #d4af37;
  display: block;
}

.aus-date-score-label {
  font-size: 10px;
  color: #999;
}

.aus-date-desc {
  background: #f9f7f2;
  border-radius: 12rpx;
  padding: 14rpx;
  font-size: 12px;
  color: #5a5a5a;
  line-height: 1.6;
}

.aus-date-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-top: 1px solid #f0f0f0;
  padding-top: 12rpx;
  font-size: 10px;
  color: #999;
}

.aus-date-meta-item {
  display: flex;
  align-items: center;
  gap: 6rpx;
}

.aus-empty {
  background: #fffdf9;
  border: 1px dashed #d4af37;
  border-radius: 16rpx;
  padding: 28rpx 24rpx;
  display: flex;
  flex-direction: column;
  gap: 8rpx;
  margin-left: 88rpx;
}

.aus-empty-title {
  font-size: 14px;
  font-weight: bold;
  color: #2c2c2c;
}

.aus-empty-sub {
  font-size: 12px;
  color: #6a6a6a;
  line-height: 1.6;
}

.aus-empty-action {
  margin-top: 8rpx;
  align-self: flex-start;
  background: #2c2c2c;
  color: #fdfbf7;
  border: none;
  border-radius: 999rpx;
  padding: 0 20rpx;
  height: 56rpx;
  line-height: 56rpx;
  font-size: 12px;
}

.aus-bottom-gap {
  height: 120rpx;
}

.aus-paymask {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(6px);
}

.aus-pay-close {
  position: absolute;
  right: 28rpx;
  top: 24rpx;
  width: 56rpx;
  height: 56rpx;
  border-radius: 999rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.06);
  color: #5a5a5a;
  font-size: 22px;
}

.aus-paycard {
  background: #fdfbf7;
  border-top-left-radius: 24rpx;
  border-top-right-radius: 24rpx;
  position: relative;
  padding: 40rpx 32rpx;
  padding-bottom: calc(150rpx + env(safe-area-inset-bottom, 0px));
}

.aus-pay-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 24rpx;
}

.aus-pay-title {
  font-weight: bold;
  color: #2c2c2c;
  font-size: 18px;
}

.aus-pay-badge {
  font-size: 10px;
  color: #8b2323;
  background: rgba(139, 35, 35, 0.1);
  padding: 6rpx 12rpx;
  border-radius: 999rpx;
  border: 1rpx solid rgba(139, 35, 35, 0.2);
}

.aus-pay-cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 30rpx;
  margin-bottom: 12rpx;
}

.aus-pay-card {
  border-radius: 16rpx;
  padding: 14rpx;
  border: 1rpx solid #e5e5e5;
  text-align: left;
  box-shadow: 0 10rpx 20rpx -12rpx rgba(0, 0, 0, 0.16);
  display: flex;
  flex-direction: column;
  gap: 2rpx;
  width: 100%;
}

.aus-pay-card-basic {
  background: #fff;
  color: #2c2c2c;
}

.aus-pay-card-premium {
  background: #2c2c2c;
  color: #fdfbf7;
  border-color: #2c2c2c;
}

.aus-pay-card-title {
  font-weight: bold;
  font-size: 14px;
}

.aus-pay-card-sub {
  font-size: 10px;
  color: #5a5a5a;
}

.aus-pay-card-premium .aus-pay-card-sub {
  color: #dcd3c9;
}

.aus-pay-price {
  display: flex;
  align-items: baseline;
  gap: 2rpx;
  margin-top: 0;
}

.aus-pay-price-sign {
  font-size: 11px;
  color: inherit;
}

.aus-pay-price-num {
  font-size: 20px;
  font-weight: bold;
  color: inherit;
}

.aus-pay-price-origin {
  font-size: 10px;
  color: #999;
  text-decoration: line-through;
}

.aus-pay-card-premium .aus-pay-price-origin {
  color: rgba(253, 251, 247, 0.6);
}

.aus-pay-card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.aus-pay-chip {
  font-size: 10px;
  color: #2c2c2c;
  background: #f7d774;
  padding: 4rpx 10rpx;
  border-radius: 999rpx;
}

.aus-pay-share {
  width: 100%;
  background: #16c05d;
  color: #fdfbf7;
  border: none;
  border-radius: 12rpx;
  padding: 20rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12rpx;
  font-weight: bold;
  box-shadow: 0 12rpx 24rpx -12rpx rgba(22, 192, 93, 0.5);
}

.aus-pay-share-icon {
  font-size: 16px;
}

.aus-pay-share-text {
  font-size: 14px;
}

.aus-pay-footnote {
  display: block;
  text-align: center;
  font-size: 10px;
  color: #999;
  margin-top: 12rpx;
}

.aus-poster-mask {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.8);
  backdrop-filter: blur(6px);
  padding: 16rpx;
}

.aus-poster {
  background: #fdfbf7;
  width: 100%;
  max-width: 640rpx;
  border-radius: 16rpx;
  overflow: hidden;
  box-shadow: 0 18rpx 32rpx rgba(0, 0, 0, 0.35);
  position: relative;
  display: flex;
  flex-direction: column;
}

.aus-poster-close {
  position: absolute;
  top: 24rpx;
  right: 24rpx;
  z-index: 20;
  color: #5a5a5a;
  background: rgba(255, 255, 255, 0.6);
  border-radius: 50%;
  padding: 10rpx;
  border: none;
  width: 15px;
  height: 15px;
}

.aus-poster-body {
  width: 100%;
  background: url("https://www.transparenttextures.com/patterns/rice-paper.png");
  padding-bottom: 24rpx;
}

.aus-poster-bar {
  height: 8rpx;
  background: #8b2323;
  width: 100%;
}

.aus-poster-content {
  padding: 48rpx 32rpx 0;
  text-align: center;
}

.aus-poster-icon {
  width: 128rpx;
  height: 128rpx;
  margin: 0 auto 24rpx;
  background: #8b2323;
  color: #fdfbf7;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 6rpx solid #d4af37;
  box-shadow: 0 10rpx 18rpx rgba(0, 0, 0, 0.2);
  font-size: 28px;
  font-weight: bold;
}

.aus-poster-title {
  font-size: 20px;
  font-weight: bold;
  color: #2c2c2c;
  letter-spacing: 0.2em;
  display: block;
  margin-bottom: 6rpx;
}

.aus-poster-sub {
  font-size: 12px;
  color: #5a5a5a;
  margin-bottom: 24rpx;
}

.aus-poster-card {
  background: #fffdf9;
  border: 1px solid #e5e5e5;
  border-radius: 12rpx;
  padding: 24rpx;
  position: relative;
  overflow: hidden;
}

.aus-poster-card-line {
  position: absolute;
  top: 0;
  left: 0;
  height: 6rpx;
  width: 100%;
  background: linear-gradient(90deg, transparent, #d4af37, transparent);
}

.aus-poster-date {
  font-size: 32px;
  font-weight: bold;
  color: #8b2323;
  display: block;
  margin-bottom: 8rpx;
}

.aus-poster-lunar {
  font-size: 16px;
  font-weight: bold;
  color: #2c2c2c;
  display: block;
  margin-bottom: 12rpx;
}

.aus-poster-meta {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 16rpx;
  font-size: 12px;
  color: #5a5a5a;
  margin-bottom: 16rpx;
}

.aus-poster-meta-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6rpx;
}

.aus-poster-meta-label {
  color: #8b2323;
}

.aus-poster-meta-text {
  color: #5a5a5a;
}

.aus-poster-divider {
  height: 2rpx;
  width: 100%;
  background: #e5e5e5;
  margin: 12rpx 0;
}

.aus-poster-desc {
  font-size: 14px;
  color: #2c2c2c;
  font-style: italic;
}

.aus-poster-footer {
  margin-top: 24rpx;
  padding: 0 32rpx 24rpx;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
}

.aus-poster-owner-label {
  font-size: 10px;
  color: #999;
  display: block;
}

.aus-poster-owner-name {
  font-size: 14px;
  font-weight: bold;
  color: #2c2c2c;
}

.aus-poster-qr {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6rpx;
}

.aus-poster-qr-box {
  width: 72rpx;
  height: 72rpx;
  background: #2c2c2c;
}

.aus-poster-qr-tip {
  font-size: 10px;
  color: #999;
}

.aus-poster-actions {
  background: #fff;
  border-top: 1px solid #e5e5e5;
  padding: 24rpx 16rpx;
  padding-bottom: calc(32rpx + env(safe-area-inset-bottom, 0px));
  display: flex;
  gap: 12rpx;
}

.aus-poster-btn {
  flex: 1;
  padding: 16rpx;
  border-radius: 12rpx;
  font-weight: bold;
  border: none;
  font-size: 14px;
}

.aus-poster-btn-dark {
  background: #2c2c2c;
  color: #fdfbf7;
}

.aus-poster-btn-gold {
  background: #d4af37;
  color: #2c2c2c;
}
</style>
