const { useState, useEffect, useRef, useCallback, useMemo } = React;

/* ============================================================
   颜色与字体 Token
   ============================================================ */
const COLORS = {
  bg: '#FFF0F3',
  bgSoft: '#FFE4EC',
  pink: '#FF6B8A',
  pinkDeep: '#E8476A',
  pinkLight: '#FFB3C1',
  cream: '#FFF8E7',
  yellow: '#FFD93D',
  yellowDeep: '#F5C400',
  text: '#5D2A3D',
  textSoft: '#8B5A6E',
  white: '#FFFFFF',
};

const FONTS = {
  display: "'Ma Shan Zheng', cursive",
  body: "'Noto Sans SC', sans-serif",
  fun: "'ZCOOL KuaiLe', cursive",
};

/* ============================================================
   背景爱心粒子组件
   ============================================================ */
function HeartParticles() {
  const canvasRef = useRef(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d');
    let w, h;
    let hearts = [];
    let rafId;

    const resize = () => {
      w = canvas.width = canvas.offsetWidth * window.devicePixelRatio;
      h = canvas.height = canvas.offsetHeight * window.devicePixelRatio;
    };

    const heartShape = (x, y, size) => {
      ctx.beginPath();
      const s = size;
      ctx.moveTo(x, y + s * 0.3);
      ctx.bezierCurveTo(x, y, x - s, y, x - s, y + s * 0.3);
      ctx.bezierCurveTo(x - s, y + s * 0.65, x, y + s, x, y + s * 1.15);
      ctx.bezierCurveTo(x, y + s, x + s, y + s * 0.65, x + s, y + s * 0.3);
      ctx.bezierCurveTo(x + s, y, x, y, x, y + s * 0.3);
      ctx.closePath();
    };

    const createHearts = () => {
      hearts = [];
      const count = 18;
      for (let i = 0; i < count; i++) {
        hearts.push({
          x: Math.random() * w,
          y: Math.random() * h,
          size: (6 + Math.random() * 14) * window.devicePixelRatio,
          speedY: (0.2 + Math.random() * 0.5) * window.devicePixelRatio,
          speedX: (Math.random() - 0.5) * 0.3 * window.devicePixelRatio,
          alpha: 0.15 + Math.random() * 0.35,
          sway: Math.random() * Math.PI * 2,
          swaySpeed: 0.01 + Math.random() * 0.02,
        });
      }
    };

    const draw = () => {
      ctx.clearRect(0, 0, w, h);
      hearts.forEach((ht) => {
        ht.y -= ht.speedY;
        ht.sway += ht.swaySpeed;
        ht.x += Math.sin(ht.sway) * 0.5 * window.devicePixelRatio;

        if (ht.y < -ht.size * 2) {
          ht.y = h + ht.size;
          ht.x = Math.random() * w;
        }
        if (ht.x < -ht.size) ht.x = w + ht.size;
        if (ht.x > w + ht.size) ht.x = -ht.size;

        ctx.fillStyle = `rgba(255, 107, 138, ${ht.alpha})`;
        heartShape(ht.x, ht.y, ht.size);
        ctx.fill();
      });
      rafId = requestAnimationFrame(draw);
    };

    resize();
    createHearts();
    draw();

    window.addEventListener('resize', () => {
      resize();
      createHearts();
    });

    return () => {
      cancelAnimationFrame(rafId);
    };
  }, []);

  return (
    <canvas
      ref={canvasRef}
      style={{
        position: 'absolute',
        inset: 0,
        width: '100%',
        height: '100%',
        pointerEvents: 'none',
        zIndex: 0,
      }}
    />
  );
}

/* ============================================================
   猫咪蝴蝶结与拟人星星背景装饰
   ============================================================ */
function CuteCharacterDecor() {
  const kittySpots = [
    { top: '6%', left: '4%', transform: 'rotate(-10deg) scale(0.86)' },
    { top: '43%', right: '3%', transform: 'rotate(9deg) scale(0.72)' },
    { bottom: '18%', left: '5%', transform: 'rotate(6deg) scale(0.78)' },
  ];
  const starSpots = [
    { top: '19%', right: '5%', transform: 'rotate(10deg) scale(0.82)' },
    { top: '61%', left: '2%', transform: 'rotate(-8deg) scale(0.68)' },
    { bottom: '5%', right: '7%', transform: 'rotate(6deg) scale(0.76)' },
  ];

  return (
    <div
      aria-hidden="true"
      style={{ position: 'absolute', inset: 0, overflow: 'hidden', pointerEvents: 'none', zIndex: 0 }}
    >
      {kittySpots.map((spot, index) => (
        <div
          key={`kitty-${index}`}
          className="kitty-decor"
          style={{ ...spot, animationDelay: `${index * 0.7}s` }}
        >
          <span className="kitty-ear kitty-ear-left" />
          <span className="kitty-ear kitty-ear-right" />
          <span className="kitty-bow">🎀</span>
          <span className="kitty-eye kitty-eye-left" />
          <span className="kitty-eye kitty-eye-right" />
          <span className="kitty-nose" />
          <span className="kitty-whisker kitty-whisker-left">≋</span>
          <span className="kitty-whisker kitty-whisker-right">≋</span>
        </div>
      ))}

      {starSpots.map((spot, index) => (
        <div
          key={`star-${index}`}
          className="star-buddy"
          style={{ ...spot, animationDelay: `${0.4 + index * 0.8}s` }}
        >
          <span className="star-shape">★</span>
          <span className="star-face">• ᴗ •</span>
          <span className="star-feet">⌒　⌒</span>
        </div>
      ))}

      <style>{`
        .kitty-decor {
          position: absolute;
          width: 58px;
          height: 47px;
          border: 2px solid rgba(255, 107, 138, 0.42);
          border-radius: 48% 48% 45% 45%;
          background: rgba(255, 255, 255, 0.72);
          opacity: 0.38;
          animation: kittyDrift 4.6s ease-in-out infinite;
        }
        .kitty-ear {
          position: absolute;
          top: -10px;
          width: 18px;
          height: 18px;
          border: 2px solid rgba(255, 107, 138, 0.38);
          background: rgba(255, 255, 255, 0.75);
          transform: rotate(45deg);
          z-index: -1;
        }
        .kitty-ear-left { left: 5px; }
        .kitty-ear-right { right: 5px; }
        .kitty-bow { position: absolute; top: -14px; right: -8px; font-size: 22px; }
        .kitty-eye {
          position: absolute;
          top: 18px;
          width: 4px;
          height: 7px;
          border-radius: 50%;
          background: rgba(93, 42, 61, 0.65);
        }
        .kitty-eye-left { left: 17px; }
        .kitty-eye-right { right: 17px; }
        .kitty-nose {
          position: absolute;
          left: 50%;
          top: 25px;
          width: 7px;
          height: 5px;
          border-radius: 50%;
          background: rgba(255, 193, 59, 0.9);
          transform: translateX(-50%);
        }
        .kitty-whisker { position: absolute; top: 27px; color: rgba(93, 42, 61, 0.45); font-size: 15px; }
        .kitty-whisker-left { left: -10px; transform: rotate(8deg); }
        .kitty-whisker-right { right: -10px; transform: scaleX(-1) rotate(8deg); }
        .star-buddy {
          position: absolute;
          width: 62px;
          height: 70px;
          opacity: 0.28;
          animation: starTwinkle 3.8s ease-in-out infinite;
        }
        .star-shape {
          position: absolute;
          inset: 0;
          color: #FFD93D;
          font-size: 64px;
          line-height: 1;
          text-shadow: 0 3px 0 rgba(245, 196, 0, 0.35);
        }
        .star-face {
          position: absolute;
          left: 13px;
          top: 25px;
          width: 40px;
          text-align: center;
          color: rgba(93, 42, 61, 0.75);
          font-size: 10px;
          font-weight: 700;
          white-space: nowrap;
        }
        .star-feet {
          position: absolute;
          left: 11px;
          bottom: -2px;
          color: rgba(93, 42, 61, 0.45);
          font-size: 10px;
          white-space: nowrap;
        }
        @keyframes kittyDrift {
          0%, 100% { margin-top: 0; }
          50% { margin-top: -10px; }
        }
        @keyframes starTwinkle {
          0%, 100% { margin-top: 0; filter: brightness(1); }
          50% { margin-top: -12px; filter: brightness(1.12); }
        }
      `}</style>
    </div>
  );
}

/* ============================================================
   页面容器 - 手机竖屏适配
   ============================================================ */
function PhoneFrame({ children }) {
  return (
    <div
      style={{
        width: '100%',
        height: '100%',
        position: 'relative',
        overflow: 'hidden',
        background: `linear-gradient(180deg, ${COLORS.bg} 0%, ${COLORS.bgSoft} 100%)`,
      }}
    >
      <HeartParticles />
      <CuteCharacterDecor />
      <div
        style={{
          position: 'relative',
          zIndex: 1,
          width: '100%',
          height: '100%',
          overflow: 'hidden',
        }}
      >
        {children}
      </div>
    </div>
  );
}

/* ============================================================
   页面切换过渡
   - 所有页面始终挂载在 DOM 中，用 transform/opacity/pointer-events 控制可见性
   - 避免 React.Children.toArray 的 key 前缀问题导致页面找不到
   - 当前页 z-index 最高且可点击，其他页在视口外且不可交互
   ============================================================ */
function PageTransition({ currentKey, children }) {
  const childArray = React.Children.toArray(children);
  const total = childArray.length;
  const [direction, setDirection] = useState(0);
  const prevKeyRef = useRef(currentKey);

  useEffect(() => {
    if (currentKey !== prevKeyRef.current) {
      setDirection(currentKey > prevKeyRef.current ? 1 : -1);
      prevKeyRef.current = currentKey;
    }
  }, [currentKey]);

  return (
    <div style={{ position: 'absolute', inset: 0, overflow: 'hidden' }}>
      {childArray.map((child, i) => {
        // child.key 在 toArray 后可能带前缀，直接用索引 i+1 作为页号比较
        const pageNum = i + 1;
        const isActive = pageNum === currentKey;
        const offset = pageNum - currentKey;
        return (
          <div
            key={pageNum}
            style={{
              position: 'absolute',
              inset: 0,
              transform: `translateX(${offset * 100}%)`,
              opacity: isActive ? 1 : 0,
              transition: 'transform 380ms cubic-bezier(0.22, 1, 0.36, 1), opacity 280ms ease',
              pointerEvents: isActive ? 'auto' : 'none',
              zIndex: isActive ? 2 : 1,
            }}
          >
            {child}
          </div>
        );
      })}
    </div>
  );
}

/* ============================================================
   第一页：邀约页
   ============================================================ */
function PageInvite({ onYes }) {
  const [dodged, setDodged] = useState(false);
  const [cornerIndex, setCornerIndex] = useState(0);
  const [noTextIndex, setNoTextIndex] = useState(0);
  const [noClicks, setNoClicks] = useState(0);
  const [noStyle, setNoStyle] = useState({});
  const [yesStyle, setYesStyle] = useState({});
  const btnAreaRef = useRef(null);
  const yesBtnRef = useRef(null);
  const noBtnRef = useRef(null);
  const lastCorner = useRef(-1);

  const noTexts = [
    '不要',
    '再想想',
    '我还没想好',
    '给我点时间',
    '这太突然了',
    '让我冷静下',
    '下次一定啦',
    '假装没看见',
    '差一点心动',
    '你再努力嘛',
    '不许套路我',
    '哎呀点错了',
    '还是不答应',
    '有本事追我呀',
    '再哄哄我嘛',
    '求婚要有诚意',
    '心动但不说',
    '才不给你答案',
    '看你表现咯',
    '再浪漫一点',
    '你猜呀',
    '先叫声宝贝',
    '拿诚意来换',
    '再靠近一点',
    '这么喜欢我呀',
    '我可难追啦',
    '就不告诉你',
    '脸红不算答应',
    '你先证明一下',
    '差一点就答应',
    '别急呀笨蛋',
    '撒个娇再说',
    '抱一下再考虑',
    '再说句爱我',
    '让我矜持一下',
    '这就想娶我呀',
    '把余生交出来',
    '先宠我一辈子',
    '心跳太快了',
    '再问一次嘛',
    '我在等你哄',
    '答案藏心里',
    '嘴硬一下下',
    '快来抓住我',
    '想得美呀你',
    '就差一点点',
    '先把我哄笑',
    '偷偷心动中',
    '再认真一点',
    '先说非我不可',
    '让我拿捏一下',
    '先亲亲再说',
    '今天不许过关',
    '我才没心动',
    '追到我再说',
  ];

  const reactionTexts = [
    '拒绝无效，爱意 +1',
    '再考虑一下嘛',
    '心动进度偷偷上涨',
    '答案好像快变了',
    '戒指正在努力发光',
    '差一点就点头啦',
    '给你的偏爱已加满',
    '命运又把按钮送回来',
    '月老正在重新连线',
    '嘴硬，但心软了一点',
    '“我愿意”越来越大啦',
    '幸福正在向你靠近',
    '这次也算心动一次',
    '没关系，我会一直认真',
    '她在等你继续哄',
    '口是心非检测成功',
    '心跳速度悄悄 +1',
    '求婚诚意持续加载',
    '再坚持一下就赢了',
    '她只是想被偏爱',
    '拒绝按钮快没力气了',
    '别停，快要心软啦',
    '浪漫值正在飙升',
    '她的嘴角偷偷上扬',
    '再甜一点就答应',
    '心动信号已捕获',
    '害羞模式已经开启',
    '答案其实写在脸上',
    '她想听更多情话',
    '离“我愿意”又近一步',
    '这不是拒绝，是撒娇',
    '她在偷偷等你追',
    '耐心是最甜的告白',
    '坚定一点，她喜欢',
    '再靠近一点点嘛',
    '她正在努力矜持',
    '嘴硬一下也很可爱',
    '你的真心已被签收',
    '戒指表示不想放弃',
    '余生申请等待通过',
    '心动警报持续响起',
    '再问她一次试试看',
    '这次眼神已经躲开',
    '傲娇值下降了一点',
    '她的防线快融化啦',
    '抱紧希望不要松手',
    '答案正在害羞加载',
    '浪漫攻势继续生效',
    '结局一定会很甜',
    '再勇敢一点就好',
  ];

  const computeCorners = useCallback(() => {
    const area = btnAreaRef.current;
    const noBtn = noBtnRef.current;
    if (!area || !noBtn) return [];
    const areaRect = area.getBoundingClientRect();
    const noRect = noBtn.getBoundingClientRect();
    const pad = 10;
    const areaW = areaRect.width;
    const areaH = areaRect.height;
    const btnW = noRect.width;
    const btnH = noRect.height;
    // 四个角：左上、右上、右下、左下
    return [
      { left: pad, top: pad },
      { left: areaW - btnW - pad, top: pad },
      { left: areaW - btnW - pad, top: areaH - btnH - pad },
      { left: pad, top: areaH - btnH - pad },
    ];
  }, []);

  const pickNextCorner = useCallback((current, total) => {
    // 优先对角：0↔2, 1↔3
    const diagonal = (current + 2) % total;
    // 70% 概率去对角，30% 随机其他
    if (Math.random() < 0.7) return diagonal;
    const others = [];
    for (let i = 0; i < total; i++) {
      if (i !== current) others.push(i);
    }
    return others[Math.floor(Math.random() * others.length)];
  }, []);

  const handleNoClick = useCallback(() => {
    const corners = computeCorners();
    if (!corners.length) return;
    const nextClickCount = noClicks + 1;

    let next;
    if (!dodged) {
      // 首次：随机选一个角
      next = Math.floor(Math.random() * 4);
      setDodged(true);
    } else {
      next = pickNextCorner(cornerIndex, 4);
    }

    lastCorner.current = cornerIndex;
    setCornerIndex(next);
    setNoStyle({
      position: 'absolute',
      left: corners[next].left,
      top: corners[next].top,
      transform: `scale(${Math.max(0.76, 1 - nextClickCount * 0.018)}) rotate(${nextClickCount % 2 ? -2 : 2}deg)`,
      transition: 'all 360ms cubic-bezier(0.22, 1, 0.36, 1)',
      zIndex: 5,
    });
    setYesStyle({
      position: 'absolute',
      left: '50%',
      top: '50%',
      transform: `translate(-50%, -50%) scale(${1.04 + Math.min(nextClickCount, 10) * 0.028})`,
      zIndex: 10,
      transition: 'all 360ms cubic-bezier(0.34, 1.56, 0.64, 1)',
      animation: nextClickCount >= 4 ? 'yesPulse 1.2s ease-in-out infinite' : 'none',
    });
    setNoClicks(nextClickCount);
    setNoTextIndex((prev) => (prev + 1) % noTexts.length);
  }, [dodged, cornerIndex, noClicks, computeCorners, pickNextCorner, noTexts.length]);

  // 窗口大小变化时重新定位
  useEffect(() => {
    const handleResize = () => {
      if (dodged) {
        const corners = computeCorners();
        if (corners.length) {
          setNoStyle((prev) => ({
            ...prev,
            left: corners[cornerIndex].left,
            top: corners[cornerIndex].top,
          }));
        }
      }
    };
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, [dodged, cornerIndex, computeCorners]);

  return (
    <div
      style={{
        width: '100%',
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        padding: '48px 28px 32px',
      }}
    >
      {/* 顶部装饰 */}
      <div style={{ textAlign: 'center', marginBottom: 12 }}>
        <div style={{ fontSize: 14, color: COLORS.pinkDeep, letterSpacing: 4, fontWeight: 500 }}>
          ✦  CAN YOU MARRY ME  ✦
        </div>
      </div>

      {/* 标题 */}
      <div style={{ textAlign: 'center', marginTop: 16 }}>
        <h1
          style={{
            fontFamily: FONTS.display,
            fontSize: 42,
            color: COLORS.pinkDeep,
            fontWeight: 'normal',
            lineHeight: 1.2,
            marginBottom: 8,
          }}
        >
          小阳愿意
        </h1>
        <h1
          style={{
            fontFamily: FONTS.display,
            fontSize: 52,
            color: COLORS.pink,
            fontWeight: 'normal',
            lineHeight: 1.2,
            textShadow: '0 2px 12px rgba(255, 107, 138, 0.3)',
          }}
        >
          嫁给我嘛？
        </h1>
      </div>

      {/* 装饰分隔 */}
      <div
        style={{
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          gap: 12,
          margin: '24px 0',
        }}
      >
        <div style={{ width: 40, height: 1, background: COLORS.pinkLight, opacity: 0.6 }} />
        <svg width="20" height="20" viewBox="0 0 24 24" fill={COLORS.pink}>
          <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
        </svg>
        <div style={{ width: 40, height: 1, background: COLORS.pinkLight, opacity: 0.6 }} />
      </div>

      {/* 文案 */}
      <div style={{ textAlign: 'center', padding: '0 16px', flex: 1 }}>
        <p
          style={{
            fontFamily: FONTS.body,
            fontSize: 16,
            color: COLORS.textSoft,
            lineHeight: 1.9,
            marginBottom: 12,
          }}
        >
          从心动开始，想陪你很久
        </p>
        <p
          style={{
            fontFamily: FONTS.body,
            fontSize: 16,
            color: COLORS.textSoft,
            lineHeight: 1.9,
            marginBottom: 12,
          }}
        >
          想把往后的每一天
        </p>
        <p
          style={{
            fontFamily: FONTS.body,
            fontSize: 16,
            color: COLORS.textSoft,
            lineHeight: 1.9,
          }}
        >
          都认真地写进我们的故事
        </p>
      </div>

      {/* 按钮区域 */}
      <div
        ref={btnAreaRef}
        style={{
          position: 'relative',
          height: 200,
          width: '100%',
          marginTop: 'auto',
        }}
      >
        {dodged && (
          <div
            key={`reaction-${noClicks}`}
            style={{
              position: 'absolute',
              left: '50%',
              top: -22,
              transform: 'translateX(-50%)',
              whiteSpace: 'nowrap',
              padding: '6px 12px',
              borderRadius: 16,
              background: 'rgba(255, 255, 255, 0.78)',
              color: COLORS.pinkDeep,
              fontSize: 13,
              boxShadow: '0 4px 14px rgba(232, 71, 106, 0.12)',
              animation: 'reactionPop 420ms cubic-bezier(0.34, 1.56, 0.64, 1)',
              zIndex: 20,
            }}
          >
            💗 {reactionTexts[(noClicks - 1) % reactionTexts.length]} · {noClicks}
          </div>
        )}

        {dodged && (
          <div key={`burst-${noClicks}`} style={{ position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 15 }}>
            {['💗', '✨', '💞', '♡', '💍'].map((item, index) => (
              <span
                key={`${item}-${index}`}
                style={{
                  position: 'absolute',
                  left: `${27 + index * 11}%`,
                  top: '50%',
                  fontSize: 16 + (index % 2) * 4,
                  animation: `heartFloat 900ms ease-out ${index * 55}ms both`,
                }}
              >
                {item}
              </span>
            ))}
          </div>
        )}

        {/* 愿意按钮 */}
        <button
          ref={yesBtnRef}
          onClick={onYes}
          style={{
            position: dodged ? 'absolute' : 'absolute',
            left: dodged ? undefined : 'calc(50% - 110px)',
            top: dodged ? undefined : 20,
            ...yesStyle,
            width: 140,
            height: 56,
            border: 'none',
            borderRadius: 28,
            background: `linear-gradient(135deg, ${COLORS.pink} 0%, ${COLORS.pinkDeep} 100%)`,
            color: COLORS.white,
            fontSize: 20,
            fontFamily: FONTS.fun,
            fontWeight: 'normal',
            cursor: 'pointer',
            boxShadow: '0 8px 24px rgba(255, 107, 138, 0.45)',
            letterSpacing: 2,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            gap: 6,
          }}
        >
          <span>我愿意</span>
          <svg width="20" height="20" viewBox="0 0 24 24" fill="white">
            <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
          </svg>
        </button>

        {/* 不要按钮 */}
        <button
          ref={noBtnRef}
          onClick={handleNoClick}
          style={{
            position: dodged ? 'absolute' : 'absolute',
            left: dodged ? undefined : 'calc(50% - 110px)',
            top: dodged ? undefined : 96,
            ...noStyle,
            width: 132,
            height: 48,
            border: `2px solid ${COLORS.pinkLight}`,
            borderRadius: 24,
            background: COLORS.white,
            color: COLORS.pinkDeep,
            fontSize: 15,
            fontFamily: FONTS.body,
            fontWeight: 500,
            cursor: 'pointer',
            boxShadow: '0 4px 12px rgba(255, 107, 138, 0.15)',
            opacity: dodged ? 0.85 : 1,
          }}
        >
          {noTexts[noTextIndex]}
        </button>

        <style>{`
          @keyframes reactionPop {
            0% { opacity: 0; transform: translateX(-50%) translateY(8px) scale(0.85); }
            100% { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
          }
          @keyframes heartFloat {
            0% { opacity: 0; transform: translateY(8px) scale(0.4) rotate(0deg); }
            35% { opacity: 1; }
            100% { opacity: 0; transform: translateY(-82px) scale(1.25) rotate(18deg); }
          }
          @keyframes yesPulse {
            0%, 100% { box-shadow: 0 8px 24px rgba(255, 107, 138, 0.42); }
            50% { box-shadow: 0 10px 34px rgba(232, 71, 106, 0.7), 0 0 0 8px rgba(255, 179, 193, 0.18); }
          }
        `}</style>
      </div>
    </div>
  );
}

/* ============================================================
   第二页：确认页
   ============================================================ */
function PageConfirm({ onNext }) {
  const [bounce, setBounce] = useState(false);

  useEffect(() => {
    setBounce(true);
  }, []);

  return (
    <div
      style={{
        width: '100%',
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center',
        padding: '48px 32px',
      }}
    >
      {/* 害羞emoji */}
      <div
        style={{
          fontSize: 96,
          marginBottom: 32,
          transform: bounce ? 'scale(1) rotate(-5deg)' : 'scale(0.5)',
          transition: 'transform 600ms cubic-bezier(0.34, 1.56, 0.64, 1)',
          animation: 'wiggle 1.5s ease-in-out 600ms infinite',
        }}
      >
        🥰
      </div>

      <h2
        style={{
          fontFamily: FONTS.display,
          fontSize: 40,
          color: COLORS.pinkDeep,
          fontWeight: 'normal',
          marginBottom: 16,
          textAlign: 'center',
        }}
      >
        真的吗？！
      </h2>

      <p
        style={{
          fontSize: 17,
          color: COLORS.textSoft,
          lineHeight: 1.9,
          textAlign: 'center',
          marginBottom: 12,
        }}
      >
        小阳愿意嫁给我啦！
      </p>
      <p
        style={{
          fontSize: 17,
          color: COLORS.textSoft,
          lineHeight: 1.9,
          textAlign: 'center',
          marginBottom: 48,
        }}
      >
        往后的每一天，都想牵着你的手 ～ ♡
      </p>

      <button
        onClick={onNext}
        style={{
          width: 220,
          height: 58,
          border: 'none',
          borderRadius: 29,
          background: `linear-gradient(135deg, ${COLORS.pink} 0%, ${COLORS.pinkDeep} 100%)`,
          color: COLORS.white,
          fontSize: 20,
          fontFamily: FONTS.fun,
          cursor: 'pointer',
          boxShadow: '0 10px 28px rgba(255, 107, 138, 0.45)',
          letterSpacing: 3,
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          gap: 8,
        }}
      >
        <span>继续</span>
        <svg width="18" height="18" viewBox="0 0 24 24" fill="white">
          <path d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6z"/>
        </svg>
      </button>

      <style>{`
        @keyframes wiggle {
          0%, 100% { transform: rotate(-5deg) scale(1); }
          25% { transform: rotate(5deg) scale(1.05); }
          50% { transform: rotate(-5deg) scale(1); }
          75% { transform: rotate(5deg) scale(1.05); }
        }
      `}</style>
    </div>
  );
}

/* ============================================================
   第三页：时间选择页
   ============================================================ */
function PageTime({ onNext, onSetDate, onSetTime, dateVal, timeVal }) {
  const today = new Date();
  const tomorrow = new Date(today);
  tomorrow.setDate(tomorrow.getDate() + 1);
  const todayStr = today.toISOString().split('T')[0];

  const handleDateChange = (e) => onSetDate(e.target.value);
  const handleTimeChange = (e) => onSetTime(e.target.value);

  const formatDate = (dateStr) => {
    const d = new Date(dateStr);
    const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
    return `${d.getMonth() + 1}月${d.getDate()}日 ${weekDays[d.getDay()]}`;
  };

  return (
    <div
      style={{
        width: '100%',
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        padding: '52px 28px 32px',
      }}
    >
      <div style={{ textAlign: 'center', marginBottom: 8 }}>
        <div style={{ fontSize: 13, color: COLORS.pinkDeep, letterSpacing: 4, fontWeight: 500 }}>
          ✦  W E D D I N G  D A Y  ✦
        </div>
      </div>

      <h2
        style={{
          fontFamily: FONTS.display,
          fontSize: 36,
          color: COLORS.pinkDeep,
          fontWeight: 'normal',
          textAlign: 'center',
          marginTop: 12,
          marginBottom: 8,
        }}
      >
        黄道吉日
      </h2>
      <p
        style={{
          textAlign: 'center',
          color: COLORS.textSoft,
          fontSize: 14,
          marginBottom: 36,
        }}
      >
        选定属于我们的吉日与吉时
      </p>

      {/* 日期选择卡片 */}
      <div
        style={{
          background: COLORS.white,
          borderRadius: 20,
          padding: '24px 20px',
          marginBottom: 20,
          boxShadow: '0 8px 30px rgba(255, 107, 138, 0.12)',
        }}
      >
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 16 }}>
          <svg width="22" height="22" viewBox="0 0 24 24" fill={COLORS.pink}>
            <path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM9 10H7v2h2v-2zm4 0h-2v2h2v-2zm4 0h-2v2h2v-2zm-8 4H7v2h2v-2zm4 0h-2v2h2v-2zm4 0h-2v2h2v-2z"/>
          </svg>
          <span style={{ fontSize: 16, fontWeight: 500, color: COLORS.text }}>吉日</span>
        </div>
        <input
          type="date"
          value={dateVal}
          min={todayStr}
          onChange={handleDateChange}
          style={{
            width: '100%',
            height: 52,
            border: `2px solid ${COLORS.pinkLight}`,
            borderRadius: 14,
            padding: '0 16px',
            fontSize: 18,
            fontFamily: FONTS.body,
            color: COLORS.text,
            background: COLORS.cream,
            outline: 'none',
            appearance: 'none',
            WebkitAppearance: 'none',
          }}
        />
        {dateVal && (
          <div style={{ marginTop: 10, fontSize: 14, color: COLORS.pinkDeep, fontWeight: 500 }}>
            {formatDate(dateVal)}
          </div>
        )}
      </div>

      {/* 时间选择卡片 */}
      <div
        style={{
          background: COLORS.white,
          borderRadius: 20,
          padding: '24px 20px',
          marginBottom: 32,
          boxShadow: '0 8px 30px rgba(255, 107, 138, 0.12)',
        }}
      >
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 16 }}>
          <svg width="22" height="22" viewBox="0 0 24 24" fill={COLORS.pink}>
            <path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/>
          </svg>
          <span style={{ fontSize: 16, fontWeight: 500, color: COLORS.text }}>吉时</span>
        </div>
        <input
          type="time"
          value={timeVal}
          onChange={handleTimeChange}
          style={{
            width: '100%',
            height: 52,
            border: `2px solid ${COLORS.pinkLight}`,
            borderRadius: 14,
            padding: '0 16px',
            fontSize: 18,
            fontFamily: FONTS.body,
            color: COLORS.text,
            background: COLORS.cream,
            outline: 'none',
            appearance: 'none',
            WebkitAppearance: 'none',
          }}
        />
      </div>

      <div style={{ marginTop: 'auto', display: 'flex', justifyContent: 'center' }}>
        <button
          onClick={onNext}
          disabled={!dateVal || !timeVal}
          style={{
            width: 220,
            height: 58,
            border: 'none',
            borderRadius: 29,
            background: dateVal && timeVal
              ? `linear-gradient(135deg, ${COLORS.pink} 0%, ${COLORS.pinkDeep} 100%)`
              : '#D8C5CC',
            color: COLORS.white,
            fontSize: 20,
            fontFamily: FONTS.fun,
            cursor: dateVal && timeVal ? 'pointer' : 'not-allowed',
            boxShadow: dateVal && timeVal
              ? '0 10px 28px rgba(255, 107, 138, 0.45)'
              : 'none',
            letterSpacing: 3,
            transition: 'all 0.2s ease',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            gap: 8,
          }}
        >
          <span>定下吉日</span>
          <svg width="18" height="18" viewBox="0 0 24 24" fill="white">
            <path d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6z"/>
          </svg>
        </button>
      </div>
    </div>
  );
}

/* ============================================================
   第四页：餐食选择页
   ============================================================ */
const FOOD_ITEMS = [
  { id: 'hotpot', name: '火锅', emoji: '🍲' },
  { id: 'bbq', name: '烤肉', emoji: '🥩' },
  { id: 'sushi', name: '日料', emoji: '🍣' },
  { id: 'noodle', name: '拉面', emoji: '🍜' },
  { id: 'seafood', name: '海鲜', emoji: '🦞' },
  { id: 'dessert', name: '甜品', emoji: '🍰' },
  { id: 'burger', name: '汉堡', emoji: '🍔' },
  { id: 'chinese', name: '中餐', emoji: '🥢' },
  { id: 'brunch', name: '早午餐', emoji: '🥐' },
];

function PageFood({ onSelect, selectedFood }) {
  return (
    <div
      style={{
        width: '100%',
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        padding: '52px 24px 32px',
        overflow: 'hidden',
      }}
    >
      <div style={{ textAlign: 'center', marginBottom: 8 }}>
        <div style={{ fontSize: 13, color: COLORS.pinkDeep, letterSpacing: 4, fontWeight: 500 }}>
          ✦  W E D D I N G  F E A S T  ✦
        </div>
      </div>

      <h2
        style={{
          fontFamily: FONTS.display,
          fontSize: 36,
          color: COLORS.pinkDeep,
          fontWeight: 'normal',
          textAlign: 'center',
          marginTop: 12,
          marginBottom: 8,
        }}
      >
        结婚用膳？
      </h2>
      <p
        style={{
          textAlign: 'center',
          color: COLORS.textSoft,
          fontSize: 14,
          marginBottom: 24,
        }}
      >
        选一份婚后第一餐的心头好
      </p>

      {/* 3 列网格 */}
      <div
        style={{
          display: 'grid',
          gridTemplateColumns: 'repeat(3, 1fr)',
          gap: 12,
          flex: 1,
          alignContent: 'center',
        }}
      >
        {FOOD_ITEMS.map((item) => {
          const isSelected = selectedFood?.id === item.id;
          return (
            <button
              key={item.id}
              onClick={() => onSelect(item)}
              style={{
                aspectRatio: '1 / 1',
                border: isSelected ? `3px solid ${COLORS.pink}` : '2px solid transparent',
                borderRadius: 18,
                background: isSelected
                  ? `linear-gradient(135deg, #FFE4EC 0%, #FFD1DC 100%)`
                  : COLORS.white,
                cursor: 'pointer',
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                justifyContent: 'center',
                gap: 6,
                boxShadow: isSelected
                  ? '0 6px 20px rgba(255, 107, 138, 0.3)'
                  : '0 4px 16px rgba(255, 107, 138, 0.1)',
                transition: 'all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1)',
                transform: isSelected ? 'scale(1.05)' : 'scale(1)',
                position: 'relative',
                padding: 8,
              }}
            >
              <span style={{ fontSize: 36 }}>{item.emoji}</span>
              <span style={{ fontSize: 13, fontWeight: 500, color: COLORS.text }}>{item.name}</span>
              {isSelected && (
                <div
                  style={{
                    position: 'absolute',
                    top: 6,
                    right: 6,
                    width: 24,
                    height: 24,
                    borderRadius: '50%',
                    background: COLORS.pink,
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                  }}
                >
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="white">
                    <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>
                  </svg>
                </div>
              )}
            </button>
          );
        })}
      </div>
    </div>
  );
}

/* ============================================================
   第五页：结婚场景选择页
   ============================================================ */
const SCENE_ITEMS = [
  { id: 'beach', name: '海边', emoji: '🏖️', note: '听海浪说我愿意' },
  { id: 'grass', name: '草地', emoji: '🌿', note: '在风与花香里相拥' },
  { id: 'snow', name: '雪景', emoji: '❄️', note: '一起走到白头' },
  { id: 'indoor', name: '室内', emoji: '🏛️', note: '温暖又浪漫的仪式' },
  { id: 'other', name: '其他', emoji: '✨', note: '写下你的专属场景' },
];

function PageScene({ onSelect, selectedScene }) {
  const [otherActive, setOtherActive] = useState(selectedScene?.id === 'other');
  const [otherValue, setOtherValue] = useState(selectedScene?.id === 'other' ? selectedScene.name : '');

  const chooseScene = (item) => {
    if (item.id === 'other') {
      setOtherActive(true);
      return;
    }
    setOtherActive(false);
    onSelect(item);
  };

  const submitOther = () => {
    const customName = otherValue.trim();
    if (!customName) return;
    onSelect({ id: 'other', name: customName, emoji: '💫', note: '我们的专属浪漫场景' });
  };

  return (
    <div
      style={{
        width: '100%',
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        padding: '46px 24px 28px',
        overflow: 'hidden',
      }}
    >
      <div style={{ textAlign: 'center', marginBottom: 6 }}>
        <div style={{ fontSize: 13, color: COLORS.pinkDeep, letterSpacing: 4, fontWeight: 500 }}>
          ✦  W E D D I N G  S C E N E  ✦
        </div>
      </div>

      <h2
        style={{
          fontFamily: FONTS.display,
          fontSize: 36,
          color: COLORS.pinkDeep,
          fontWeight: 'normal',
          textAlign: 'center',
          marginTop: 10,
          marginBottom: 6,
        }}
      >
        想在哪里结婚？
      </h2>
      <p style={{ textAlign: 'center', color: COLORS.textSoft, fontSize: 14, marginBottom: 18 }}>
        选一个属于我们的浪漫场景
      </p>

      <div
        style={{
          display: 'grid',
          gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
          gap: 12,
        }}
      >
        {SCENE_ITEMS.map((item) => {
          const isOther = item.id === 'other';
          const isSelected = isOther ? otherActive : selectedScene?.id === item.id;
          return (
            <button
              key={item.id}
              onClick={() => chooseScene(item)}
              style={{
                minHeight: isOther ? 76 : 104,
                gridColumn: isOther ? '1 / -1' : 'auto',
                border: isSelected ? `3px solid ${COLORS.pink}` : '2px solid transparent',
                borderRadius: 18,
                background: isSelected
                  ? 'linear-gradient(135deg, #FFE4EC 0%, #FFD1DC 100%)'
                  : 'rgba(255, 255, 255, 0.92)',
                cursor: 'pointer',
                display: 'flex',
                flexDirection: isOther ? 'row' : 'column',
                alignItems: 'center',
                justifyContent: 'center',
                gap: isOther ? 12 : 4,
                boxShadow: isSelected
                  ? '0 7px 22px rgba(255, 107, 138, 0.28)'
                  : '0 4px 16px rgba(255, 107, 138, 0.1)',
                transition: 'all 0.24s cubic-bezier(0.34, 1.56, 0.64, 1)',
                transform: isSelected ? 'scale(1.025)' : 'scale(1)',
                padding: '10px 8px',
              }}
            >
              <span style={{ fontSize: isOther ? 30 : 34 }}>{item.emoji}</span>
              <span>
                <span style={{ display: 'block', fontSize: 15, fontWeight: 600, color: COLORS.text }}>
                  {item.name}
                </span>
                <span style={{ display: 'block', marginTop: 2, fontSize: 11, color: COLORS.textSoft }}>
                  {item.note}
                </span>
              </span>
            </button>
          );
        })}
      </div>

      {otherActive && (
        <div
          style={{
            marginTop: 14,
            padding: 12,
            borderRadius: 18,
            background: 'rgba(255, 255, 255, 0.92)',
            boxShadow: '0 6px 20px rgba(255, 107, 138, 0.12)',
            animation: 'sceneInputIn 320ms ease-out',
          }}
        >
          <input
            type="text"
            value={otherValue}
            maxLength={16}
            onChange={(event) => setOtherValue(event.target.value)}
            onKeyDown={(event) => {
              if (event.key === 'Enter') submitOther();
            }}
            placeholder="例如：花园、教堂、城堡……"
            style={{
              width: '100%',
              height: 44,
              border: `2px solid ${COLORS.pinkLight}`,
              borderRadius: 14,
              padding: '0 14px',
              background: COLORS.cream,
              color: COLORS.text,
              fontSize: 15,
              outline: 'none',
            }}
          />
          <button
            onClick={submitOther}
            disabled={!otherValue.trim()}
            style={{
              width: '100%',
              height: 44,
              marginTop: 9,
              border: 'none',
              borderRadius: 22,
              background: otherValue.trim()
                ? `linear-gradient(135deg, ${COLORS.pink} 0%, ${COLORS.pinkDeep} 100%)`
                : '#D8C5CC',
              color: COLORS.white,
              fontFamily: FONTS.fun,
              fontSize: 17,
              cursor: otherValue.trim() ? 'pointer' : 'not-allowed',
            }}
          >
            记录这个场景
          </button>
        </div>
      )}

      {!otherActive && (
        <div style={{ marginTop: 'auto', textAlign: 'center', fontSize: 12, color: COLORS.textSoft }}>
          💍 选好后会自动记录到结婚请帖
        </div>
      )}

      <style>{`
        @keyframes sceneInputIn {
          from { opacity: 0; transform: translateY(8px); }
          to { opacity: 1; transform: translateY(0); }
        }
      `}</style>
    </div>
  );
}

/* ============================================================
   第六页：摘要与保存页
   ============================================================ */
function PageSummary({ dateVal, timeVal, food, scene, onSave }) {
  const formatDate = (dateStr) => {
    const d = new Date(dateStr);
    const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
    return `${d.getFullYear()}.${String(d.getMonth() + 1).padStart(2, '0')}.${String(d.getDate()).padStart(2, '0')} ${weekDays[d.getDay()]}`;
  };

  const formatTime = (timeStr) => {
    return timeStr;
  };

  return (
    <div
      style={{
        width: '100%',
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        padding: '28px 24px 24px',
        overflow: 'hidden',
      }}
    >
      {/* 爱心插画 */}
      <div
        style={{
          display: 'flex',
          justifyContent: 'center',
          marginBottom: 6,
        }}
      >
        <div
          style={{
            width: 96,
            height: 96,
            borderRadius: '50%',
            background: `radial-gradient(circle, rgba(255,107,138,0.2) 0%, transparent 70%)`,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            position: 'relative',
          }}
        >
          <svg width="62" height="62" viewBox="0 0 24 24" fill={COLORS.pink}>
            <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
          </svg>
          {/* 小爱心装饰 */}
          <div style={{ position: 'absolute', top: 10, left: 20, animation: 'float 2s ease-in-out infinite' }}>
            <svg width="20" height="20" viewBox="0 0 24 24" fill={COLORS.pinkLight}>
              <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
            </svg>
          </div>
          <div style={{ position: 'absolute', bottom: 15, right: 15, animation: 'float 2.5s ease-in-out 0.5s infinite' }}>
            <svg width="16" height="16" viewBox="0 0 24 24" fill={COLORS.pinkLight}>
              <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
            </svg>
          </div>
          <div style={{ position: 'absolute', top: 30, right: 10, animation: 'float 2.2s ease-in-out 0.3s infinite' }}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill={COLORS.pinkDeep}>
              <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
            </svg>
          </div>
        </div>
      </div>

      <h2
        style={{
          fontFamily: FONTS.display,
          fontSize: 30,
          color: COLORS.pinkDeep,
          fontWeight: 'normal',
          textAlign: 'center',
          marginBottom: 2,
        }}
      >
        结婚日期已约定
      </h2>
      <p
        style={{
          textAlign: 'center',
          color: COLORS.textSoft,
          fontSize: 14,
          marginBottom: 12,
        }}
      >
        好期待呀 ♡
      </p>

      {/* 摘要卡片 */}
      <div
        style={{
          background: COLORS.white,
          borderRadius: 22,
          padding: '14px 18px',
          boxShadow: '0 10px 32px rgba(255, 107, 138, 0.15)',
          marginBottom: 16,
        }}
      >
        <SummaryRow icon="📅" label="吉日" value={formatDate(dateVal)} />
        <Divider />
        <SummaryRow icon="⏰" label="吉时" value={formatTime(timeVal)} />
        <Divider />
        <SummaryRow
          icon={food?.emoji || '🍽️'}
          label="用膳"
          value={food?.name || '未选择'}
        />
        <Divider />
        <SummaryRow
          icon={scene?.emoji || '💒'}
          label="场景"
          value={scene?.name || '未选择'}
        />
      </div>

      {/* 保存按钮 */}
      <div style={{ marginTop: 'auto', display: 'flex', justifyContent: 'center' }}>
        <button
          onClick={onSave}
          style={{
            width: 240,
            height: 56,
            border: 'none',
            borderRadius: 30,
            background: `linear-gradient(135deg, ${COLORS.yellow} 0%, ${COLORS.yellowDeep} 100%)`,
            color: '#6B4C00',
            fontSize: 20,
            fontFamily: FONTS.fun,
            cursor: 'pointer',
            boxShadow: '0 10px 28px rgba(255, 217, 61, 0.5)',
            letterSpacing: 3,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            gap: 10,
            fontWeight: 500,
          }}
        >
          <svg width="22" height="22" viewBox="0 0 24 24" fill="#6B4C00">
            <path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
          </svg>
          <span>保存请帖</span>
        </button>
      </div>

      <style>{`
        @keyframes float {
          0%, 100% { transform: translateY(0); }
          50% { transform: translateY(-8px); }
        }
      `}</style>
    </div>
  );
}

function SummaryRow({ icon, label, value }) {
  return (
    <div
      style={{
        display: 'flex',
        alignItems: 'center',
        gap: 12,
        padding: '4px 0',
      }}
    >
      <div
        style={{
          width: 38,
          height: 38,
          borderRadius: 12,
          background: COLORS.bgSoft,
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          fontSize: 20,
          flexShrink: 0,
        }}
      >
        {icon}
      </div>
      <div style={{ flex: 1 }}>
        <div
          style={{
            fontSize: 10,
            color: COLORS.pinkDeep,
            letterSpacing: 2,
            fontWeight: 600,
            marginBottom: 2,
            opacity: 0.7,
          }}
        >
          {label}
        </div>
        <div style={{ fontSize: 15, fontWeight: 600, color: COLORS.text }}>{value}</div>
      </div>
    </div>
  );
}

function Divider() {
  return (
    <div
      style={{
        height: 1,
        background: COLORS.bgSoft,
        margin: '4px 0 4px 50px',
      }}
    />
  );
}

/* ============================================================
   Canvas 图片生成工具
   ============================================================ */
async function generateImage({ dateVal, timeVal, food, scene }) {
  const canvas = document.createElement('canvas');
  const W = 1080;
  const H = 1440;
  canvas.width = W;
  canvas.height = H;
  const ctx = canvas.getContext('2d');

  // 背景渐变
  const bgGrad = ctx.createLinearGradient(0, 0, 0, H);
  bgGrad.addColorStop(0, '#FFF0F3');
  bgGrad.addColorStop(1, '#FFE4EC');
  ctx.fillStyle = bgGrad;
  ctx.fillRect(0, 0, W, H);

  // 装饰爱心 - 背景散落
  ctx.fillStyle = 'rgba(255, 107, 138, 0.08)';
  const drawBgHeart = (x, y, s) => {
    ctx.beginPath();
    ctx.moveTo(x, y + s * 0.3);
    ctx.bezierCurveTo(x, y, x - s, y, x - s, y + s * 0.3);
    ctx.bezierCurveTo(x - s, y + s * 0.65, x, y + s, x, y + s * 1.15);
    ctx.bezierCurveTo(x, y + s, x + s, y + s * 0.65, x + s, y + s * 0.3);
    ctx.bezierCurveTo(x + s, y, x, y, x, y + s * 0.3);
    ctx.closePath();
    ctx.fill();
  };
  for (let i = 0; i < 30; i++) {
    const x = Math.random() * W;
    const y = Math.random() * H;
    const s = 15 + Math.random() * 40;
    drawBgHeart(x, y, s);
  }

  // 顶部装饰
  ctx.fillStyle = '#E8476A';
  ctx.font = '600 28px "Noto Sans SC", sans-serif';
  ctx.textAlign = 'center';
  ctx.fillText('✦  C A N  Y O U  M A R R Y  M E  ✦', W / 2, 120);

  // 大标题
  ctx.fillStyle = '#E8476A';
  ctx.font = '88px "Ma Shan Zheng", cursive';
  ctx.textAlign = 'center';
  ctx.fillText('我们的婚约', W / 2, 230);

  // 大爱心
  const heartX = W / 2;
  const heartY = 420;
  const heartSize = 120;
  const heartGrad = ctx.createRadialGradient(heartX, heartY, 10, heartX, heartY, heartSize * 2);
  heartGrad.addColorStop(0, 'rgba(255, 107, 138, 0.3)');
  heartGrad.addColorStop(1, 'rgba(255, 107, 138, 0)');
  ctx.fillStyle = heartGrad;
  ctx.beginPath();
  ctx.arc(heartX, heartY, heartSize * 2, 0, Math.PI * 2);
  ctx.fill();

  ctx.fillStyle = '#FF6B8A';
  ctx.beginPath();
  ctx.moveTo(heartX, heartY + heartSize * 0.3);
  ctx.bezierCurveTo(heartX, heartY - heartSize * 0.5, heartX - heartSize, heartY - heartSize * 0.5, heartX - heartSize, heartY + heartSize * 0.3);
  ctx.bezierCurveTo(heartX - heartSize, heartY + heartSize * 0.9, heartX, heartY + heartSize * 1.2, heartX, heartY + heartSize * 1.4);
  ctx.bezierCurveTo(heartX, heartY + heartSize * 1.2, heartX + heartSize, heartY + heartSize * 0.9, heartX + heartSize, heartY + heartSize * 0.3);
  ctx.bezierCurveTo(heartX + heartSize, heartY - heartSize * 0.5, heartX, heartY - heartSize * 0.5, heartX, heartY + heartSize * 0.3);
  ctx.closePath();
  ctx.fill();

  // 小爱心
  const miniHearts = [
    { x: heartX - 140, y: heartY - 60, s: 25, c: '#FFB3C1' },
    { x: heartX + 150, y: heartY - 40, s: 20, c: '#FFB3C1' },
    { x: heartX - 100, y: heartY + 80, s: 18, c: '#E8476A' },
    { x: heartX + 120, y: heartY + 100, s: 22, c: '#FFB3C1' },
  ];
  miniHearts.forEach((h) => {
    ctx.fillStyle = h.c;
    ctx.beginPath();
    ctx.moveTo(h.x, h.y + h.s * 0.3);
    ctx.bezierCurveTo(h.x, h.y, h.x - h.s, h.y, h.x - h.s, h.y + h.s * 0.3);
    ctx.bezierCurveTo(h.x - h.s, h.y + h.s * 0.7, h.x, h.y + h.s, h.x, h.y + h.s * 1.15);
    ctx.bezierCurveTo(h.x, h.y + h.s, h.x + h.s, h.y + h.s * 0.7, h.x + h.s, h.y + h.s * 0.3);
    ctx.bezierCurveTo(h.x + h.s, h.y, h.x, h.y, h.x, h.y + h.s * 0.3);
    ctx.closePath();
    ctx.fill();
  });

  // 卡片
  const cardX = 100;
  const cardY = 700;
  const cardW = W - 200;
  const cardH = 560;
  const cardRadius = 40;

  // 卡片阴影
  ctx.shadowColor = 'rgba(255, 107, 138, 0.2)';
  ctx.shadowBlur = 40;
  ctx.shadowOffsetY = 12;

  // 卡片背景
  ctx.fillStyle = '#FFFFFF';
  roundRect(ctx, cardX, cardY, cardW, cardH, cardRadius);
  ctx.fill();
  ctx.shadowColor = 'transparent';

  // 卡片内容
  const rowY = [cardY + 70, cardY + 190, cardY + 310, cardY + 430];
  const icons = ['📅', '⏰', food?.emoji || '🍽️', scene?.emoji || '💒'];

  // 日期
  const d = new Date(dateVal);
  const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
  const dateStr = `${d.getFullYear()}.${String(d.getMonth() + 1).padStart(2, '0')}.${String(d.getDate()).padStart(2, '0')} ${weekDays[d.getDay()]}`;
  const values = [dateStr, timeVal, food?.name || '未选择', scene?.name || '未选择'];
  const labels = ['吉日', '吉时', '用膳', '场景'];

  rowY.forEach((y, i) => {
    // icon 圆
    ctx.fillStyle = '#FFE4EC';
    ctx.beginPath();
    ctx.arc(cardX + 70, y, 36, 0, Math.PI * 2);
    ctx.fill();

    ctx.font = '40px sans-serif';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(icons[i], cardX + 70, y);

    // label
    ctx.fillStyle = 'rgba(232, 71, 106, 0.7)';
    ctx.font = '600 22px "Noto Sans SC", sans-serif';
    ctx.textAlign = 'left';
    ctx.textBaseline = 'alphabetic';
    ctx.fillText(labels[i], cardX + 130, y - 10);

    // value
    ctx.fillStyle = '#5D2A3D';
    ctx.font = '600 38px "Noto Sans SC", sans-serif';
    ctx.fillText(values[i], cardX + 130, y + 35);

    // 分隔线（除最后一行）
    if (i < rowY.length - 1) {
      ctx.strokeStyle = '#FFE4EC';
      ctx.lineWidth = 2;
      ctx.beginPath();
      ctx.moveTo(cardX + 130, y + 75);
      ctx.lineTo(cardX + cardW - 40, y + 75);
      ctx.stroke();
    }
  });

  // 底部文案
  ctx.fillStyle = '#E8476A';
  ctx.font = '48px "Ma Shan Zheng", cursive';
  ctx.textAlign = 'center';
  ctx.fillText('良辰吉日，共赴余生 ♡', W / 2, 1360);

  return canvas;
}

function roundRect(ctx, x, y, w, h, r) {
  ctx.beginPath();
  ctx.moveTo(x + r, y);
  ctx.lineTo(x + w - r, y);
  ctx.quadraticCurveTo(x + w, y, x + w, y + r);
  ctx.lineTo(x + w, y + h - r);
  ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
  ctx.lineTo(x + r, y + h);
  ctx.quadraticCurveTo(x, y + h, x, y + h - r);
  ctx.lineTo(x, y + r);
  ctx.quadraticCurveTo(x, y, x + r, y);
  ctx.closePath();
}

/* ============================================================
   保存 / 分享处理
   ============================================================ */
async function handleSave({ dateVal, timeVal, food, scene }) {
  const canvas = await generateImage({ dateVal, timeVal, food, scene });

  canvas.toBlob(async (blob) => {
    if (!blob) return;

    const file = new File([blob], 'marriage-invitation.png', { type: 'image/png' });

    // 尝试使用 Web Share API
    if (navigator.share && navigator.canShare && navigator.canShare({ files: [file] })) {
      try {
        await navigator.share({
          title: '结婚请帖',
          text: '我们的黄道吉日已约定 ♡',
          files: [file],
        });
        return;
      } catch (err) {
        // 用户取消或分享失败，降级为下载
      }
    }

    // 降级：直接下载
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'marriage-invitation.png';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  }, 'image/png');
}

/* ============================================================
   主应用
   ============================================================ */
function App() {
  const [page, setPage] = useState(1);
  const [dateVal, setDateVal] = useState('');
  const [timeVal, setTimeVal] = useState('17:00');
  const [food, setFood] = useState(null);
  const [scene, setScene] = useState(null);

  // 初始化日期为明天
  useEffect(() => {
    const tomorrow = new Date();
    tomorrow.setDate(tomorrow.getDate() + 1);
    setDateVal(tomorrow.toISOString().split('T')[0]);
  }, []);

  const goNext = () => setPage((p) => Math.min(p + 1, 6));

  const handleFoodSelect = (item) => {
    setFood(item);
    // 选中后自动进入结婚场景页
    setTimeout(() => setPage(5), 500);
  };

  const handleSceneSelect = (item) => {
    setScene(item);
    // 选中后自动进入最终记录页
    setTimeout(() => setPage(6), 500);
  };

  const saveInvitation = useCallback(() => {
    handleSave({ dateVal, timeVal, food, scene });
  }, [dateVal, timeVal, food, scene]);

  return (
    <PhoneFrame>
      <PageTransition currentKey={page}>
        <PageInvite key="1" onYes={goNext} />
        <PageConfirm key="2" onNext={goNext} />
        <PageTime
          key="3"
          onNext={goNext}
          onSetDate={setDateVal}
          onSetTime={setTimeVal}
          dateVal={dateVal}
          timeVal={timeVal}
        />
        <PageFood key="4" onSelect={handleFoodSelect} selectedFood={food} />
        <PageScene key="5" onSelect={handleSceneSelect} selectedScene={scene} />
        <PageSummary
          key="6"
          dateVal={dateVal}
          timeVal={timeVal}
          food={food}
          scene={scene}
          onSave={saveInvitation}
        />
      </PageTransition>
    </PhoneFrame>
  );
}

/* ============================================================
   渲染 & 升级宣告
   ============================================================ */
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

function announceUpgrade() {
  window.parent.postMessage({ type: 'miaoda:upgrade:available', kind: 'interactive-prototype' }, '*');
}
announceUpgrade();
if (document.readyState !== 'complete') {
  window.addEventListener('load', announceUpgrade, { once: true });
}
