Files
shaguabijia-app-server/h5/mine/index.html
T
xiebing d304057e62 feat(h5): 我的页改 H5(mine 页 + shared bridge/api)
- h5/mine/index.html: 个人中心「我的页」H5 实现
- h5/shared/bridge.js, api.js: H5↔客户端桥与 API 封装(mine 依赖)
2026-06-28 10:43:13 +08:00

7772 lines
347 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>比价APP 高保真原型 (外卖版)</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html { background: #000; }
body { font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif; background: #000; display: flex; justify-content: center; align-items: center; min-height: 100vh; -webkit-user-select: none; -moz-user-select: none; user-select: none; -webkit-touch-callout: none; }
/* WebView 长按禁止文字选区/蓝色高亮(导购页非可选文档);输入框单独恢复可选 */
input, textarea { -webkit-user-select: text; user-select: text; }
:root {
--primary: #FFD600; --primary-dark: #F5C500; --primary-light: #FFEB3B; --primary-bg: #FFFDE7;
--primary-pale: #FFFAEC;
--primary-gradient: linear-gradient(180deg, #FFE066 0%, #FFD600 100%);
--primary-gradient-soft: linear-gradient(180deg, #FFFAEC 0%, #FFEEB0 100%);
--accent-orange: #FF5722; --accent-red: #E53935;
--success: #4CAF50; --success-bg: #E8F5E9; --warning: #FFC107; --error: #F44336; --info: #2196F3;
--coin: #FFB300; --coin-bg: #FFF8E1;
--gray-900: #1A1A1A; --gray-800: #333; --gray-700: #4D4D4D; --gray-600: #666; --gray-500: #999; --gray-400: #B3B3B3; --gray-300: #CCC; --gray-200: #E5E5E5; --gray-100: #F5F5F5; --gray-50: #FAFAFA; --bg: #F5F5F5;
/* Onboarding 统一 tokenB 方案) */
--cta-radius: 25px;
--cta-height: 50px;
--cta-font-size: 17px;
--cta-font-weight: 700;
--cta-letter-spacing: 1.5px;
--cta-shadow: 0 6px 18px rgba(255,179,0,.38), inset 0 1px 0 rgba(255,255,255,.55);
--cta-shadow-active: 0 3px 10px rgba(255,179,0,.30), inset 0 1px 0 rgba(255,255,255,.55);
--shadow-card-sm: 0 2px 8px rgba(0,0,0,.06);
--shadow-card-md: 0 6px 18px rgba(0,0,0,.08);
}
.device { width: 375px; height: 812px; background: #fff; border-radius: 32px; overflow: hidden; position: relative; box-shadow: 0 20px 60px rgba(0,0,0,0.5); }
.screen { position: absolute; inset: 0; display: none; flex-direction: column; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; }
.screen.active { display: flex; }
.screen.noscroll { overflow-y: hidden; }
.screen::-webkit-scrollbar { display: none; }
/* 通用样式 */
.header { display: flex; align-items: center; justify-content: space-between; padding: 40px 16px 12px; background: #fff; flex-shrink: 0; }
.header-title { font-size: 17px; font-weight: 600; color: var(--gray-900); }
.back-btn { font-size: 15px; font-weight: 600; color: var(--gray-800); cursor: pointer; background: none; border: none; }
.btn { display: flex; align-items: center; justify-content: center; border: none; border-radius: 14px; font-weight: 600; cursor: pointer; transition: opacity .15s; }
.btn:active { opacity: .7; }
.btn-primary { background: var(--primary); color: #1a1a1a; }
.btn-outline { background: transparent; border: 1.5px solid var(--primary); color: #1a1a1a; }
.btn-secondary { background: var(--primary-bg); color: var(--primary); }
.btn-lg { padding: 12px 24px; font-size: 17px; width: 100%; }
.btn-md { padding: 8px 16px; font-size: 15px; }
.btn-sm { padding: 8px 16px; font-size: 13px; }
/* ===== Onboarding 统一 CTAB 方案)===== */
.btn-cta {
display: inline-flex; align-items: center; justify-content: center;
border: none; cursor: pointer;
background: var(--primary-gradient);
color: var(--gray-900);
font-family: inherit;
font-size: var(--cta-font-size);
font-weight: var(--cta-font-weight);
letter-spacing: var(--cta-letter-spacing);
border-radius: var(--cta-radius);
height: var(--cta-height);
box-shadow: var(--cta-shadow);
transition: transform .12s ease, box-shadow .2s ease, opacity .15s ease;
}
.btn-cta:active { transform: translateY(1px); box-shadow: var(--cta-shadow-active); }
.btn-cta.size-lg { width: 100%; padding: 0 24px; }
.btn-cta.size-md { padding: 0 24px; height: 44px; font-size: 15px; letter-spacing: 1px; border-radius: 24px; }
.btn-cta.size-pill { padding: 0 16px; height: 36px; font-size: 13px; letter-spacing: .5px; border-radius: 18px; }
/* 文字辅助按钮(取消、放弃等) */
.btn-text {
background: none; border: none; cursor: pointer;
color: var(--gray-500); font-size: 14px; font-weight: 500;
font-family: inherit; transition: opacity .15s;
}
.btn-text:active { opacity: .6; }
/* ===== Splash CTA Variants ===== */
.splash-cta { width: 100%; border: none; padding: 16px 0; border-radius: 14px; font-size: 17px; font-weight: 700; cursor: pointer; transition: transform .15s, box-shadow .25s; position: relative; overflow: hidden; }
.splash-cta:active { transform: scale(.97); }
/* V1 红橙渐变(当前) */
.splash-cta-v1 { background: linear-gradient(135deg, #FE2C55, #FF6B3D); color: #fff; box-shadow: 0 6px 16px rgba(255,68,68,.30); }
/* V2 黄底黑字(品牌主色) */
.splash-cta-v2 { background: #FFD600; color: #1a1a1a; box-shadow: 0 6px 16px rgba(255,214,0,.45); }
/* V3 黑底黄字(高对比) */
.splash-cta-v3 { background: #1a1a1a; color: #FFD600; box-shadow: 0 6px 16px rgba(0,0,0,.25); }
/* V4 黄→金渐变 + 光泽扫过 */
.splash-cta-v4 { background: linear-gradient(135deg, #FFEB3B 0%, #FFD600 50%, #FFA000 100%); color: #1a1a1a; box-shadow: 0 6px 20px rgba(249,168,37,.45); }
.splash-cta-v4::after { content: ""; position: absolute; top: 0; left: -75%; width: 50%; height: 100%; background: linear-gradient(120deg, transparent, rgba(255,255,255,.6), transparent); transform: skewX(-25deg); animation: ctaShine 2.6s infinite; }
@keyframes ctaShine { 0% { left: -75%; } 60%, 100% { left: 125%; } }
/* V5 玻璃质感 黄+白光 */
.splash-cta-v5 { background: linear-gradient(180deg, #FFEB3B, #FFC400); color: #1a1a1a; box-shadow: inset 0 1px 0 rgba(255,255,255,.7), inset 0 -2px 0 rgba(0,0,0,.08), 0 8px 20px rgba(255,193,7,.35); }
/* V6 描边款(克制风) */
.splash-cta-v6 { background: #fff; color: #1a1a1a; border: 2px solid #1a1a1a; box-shadow: 4px 4px 0 #FFD600; }
.splash-cta-v6:active { box-shadow: 2px 2px 0 #FFD600; transform: translate(2px, 2px); }
/* V7 红包红(喜庆款) */
.splash-cta-v7 { background: linear-gradient(135deg, #E53935 0%, #E02E24 100%); color: #FFD600; box-shadow: 0 6px 18px rgba(198,40,40,.40); text-shadow: 0 1px 2px rgba(0,0,0,.2); }
/* V8 跳动呼吸款(黄底) */
.splash-cta-v8 { background: #FFD600; color: #1a1a1a; box-shadow: 0 6px 16px rgba(255,214,0,.45); animation: ctaPulse 1.6s ease-in-out infinite; }
@keyframes ctaPulse { 0%,100% { transform: scale(1); box-shadow: 0 6px 16px rgba(255,214,0,.45);} 50% { transform: scale(1.03); box-shadow: 0 10px 24px rgba(255,214,0,.65);} }
/* V9 蜜糖渐变(黄→琥珀,温暖软渐变,无扫光)*/
.splash-cta-v9 { background: linear-gradient(180deg, #FFE066 0%, #FFB300 100%); color: #1a1a1a; box-shadow: 0 8px 22px rgba(255,140,0,.4); }
/* V10 金币描边(品牌黄 + 深金细边 + 内嵌高光,模拟铸币感)*/
.splash-cta-v10 { background: linear-gradient(180deg, #FFE066 0%, #FFD600 100%); color: #1a1a1a; border: 1.5px solid #8B6914; box-shadow: inset 0 1px 0 rgba(255,255,255,.7), 0 6px 18px rgba(184,134,11,.35); }
/* ===== Coupon Subtitle Variants ===== */
.cps { font-family: inherit; }
/* V1 当前灰色基线 */
.cps-v1 { font-size: 13px;font-weight: 500;color: var(--gray-500);line-height: 1.5; }
/* V2 系列:金币胶囊家族 */
.cps-v2 { display: inline-flex;align-items: center;gap: 6px;padding: 6px 12px;border-radius: 999px;background: linear-gradient(180deg,#FFE066,#FFC400);color: #5A3A00;font-size: 12px;font-weight: 600;letter-spacing: .2px;box-shadow: inset 0 1px 0 rgba(255,255,255,.7),0 2px 6px rgba(255,179,0,.35); }
.cps-v2 .cps-coin { width: 14px;height: 14px;border-radius: 50%;background: radial-gradient(circle at 35% 30%,#FFE0B2,#FFA000);box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);display: inline-flex;align-items: center;justify-content: center;font-size: 10px;font-weight: 900;color: #7A4F00; }
/* V2b 金币翻转动效 */
.cps-v2b { display: inline-flex;align-items: center;gap: 6px;padding: 6px 12px;border-radius: 999px;background: linear-gradient(180deg,#FFE066,#FFC400);color: #5A3A00;font-size: 12px;font-weight: 600;letter-spacing: .2px;box-shadow: inset 0 1px 0 rgba(255,255,255,.7),0 2px 6px rgba(255,179,0,.35); }
.cps-v2b .cps-coin { width: 14px;height: 14px;border-radius: 50%;background: radial-gradient(circle at 35% 30%,#FFE0B2,#FFA000);box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);display: inline-flex;align-items: center;justify-content: center;font-size: 10px;font-weight: 900;color: #7A4F00;animation: coinFlip 2.4s ease-in-out infinite; }
@keyframes coinFlip { 0%,70%,100% { transform: rotateY(0); } 80% { transform: rotateY(180deg); } 90% { transform: rotateY(360deg); } }
/* V2c 双色分段 */
.cps-v2c { display: inline-flex;align-items: center;padding: 0;border-radius: 999px;background: linear-gradient(180deg,#FFE066,#FFC400);font-size: 12px;font-weight: 600;letter-spacing: .2px;box-shadow: inset 0 1px 0 rgba(255,255,255,.7),0 2px 6px rgba(255,179,0,.35);overflow: hidden; }
.cps-v2c .cps-tag { background: #1a1a1a;color: #FFD600;padding: 6px 8px;font-weight: 900;letter-spacing: .5px;display: inline-flex;align-items: center;gap: 2px; }
.cps-v2c .cps-text { padding: 6px 12px 6px 8px;color: #5A3A00; }
/* V2d 闪光描边(轻盈款) */
.cps-v2d { position: relative;display: inline-flex;align-items: center;gap: 6px;padding: 6px 12px;border-radius: 999px;background: #FFFDF5;color: #1a1a1a;font-size: 12px;font-weight: 600;letter-spacing: .2px;border: 1.5px solid transparent;background-image: linear-gradient(#FFFDF5,#FFFDF5),linear-gradient(135deg,#FFD600,#F9A825,#FFD600);background-origin: border-box;background-clip: padding-box,border-box;box-shadow: 0 2px 8px rgba(255,179,0,.2); }
.cps-v2d .cps-coin { width: 14px;height: 14px;border-radius: 50%;background: radial-gradient(circle at 35% 30%,#FFE0B2,#FFA000);box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);display: inline-flex;align-items: center;justify-content: center;font-size: 10px;font-weight: 900;color: #7A4F00; }
/* V2e 数字嵌入款 */
.cps-v2e { display: inline-flex;align-items: center;gap: 6px;padding: 4px 12px 4px 8px;border-radius: 999px;background: linear-gradient(180deg,#FFE066,#FFC400);color: #5A3A00;font-size: 12px;font-weight: 600;letter-spacing: .2px;box-shadow: inset 0 1px 0 rgba(255,255,255,.7),0 2px 6px rgba(255,179,0,.35); }
.cps-v2e .cps-amount { display: inline-flex;align-items: baseline;background: #1a1a1a;color: #FFD600;padding: 2px 8px;border-radius: 999px;font-weight: 900;font-size: 12px;letter-spacing: .3px; }
.cps-v2e .cps-amount small { font-size: 10px;font-weight: 700;opacity: .85;margin-left: 2px; }
/* V2f 双图标夹击 */
.cps-v2f { display: inline-flex;align-items: center;gap: 4px;padding: 6px 12px;border-radius: 999px;background: linear-gradient(180deg,#FFE066,#FFC400);color: #5A3A00;font-size: 12px;font-weight: 600;letter-spacing: .2px;box-shadow: inset 0 1px 0 rgba(255,255,255,.7),0 2px 6px rgba(255,179,0,.35); }
.cps-v2f .cps-coin { width: 14px;height: 14px;border-radius: 50%;background: radial-gradient(circle at 35% 30%,#FFE0B2,#FFA000);box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);display: inline-flex;align-items: center;justify-content: center;font-size: 10px;font-weight: 900;color: #7A4F00; }
.cps-v2f .cps-bolt { width: 12px;height: 12px;display: inline-flex;align-items: center;justify-content: center; }
.cps-v2f .cps-bolt svg { display: block; }
/* V2g 立体浮起 */
.cps-v2g { display: inline-flex;align-items: center;gap: 6px;padding: 6px 12px;border-radius: 999px;background: linear-gradient(180deg,#FFE066 0%,#FFD600 50%,#FFA000 100%);color: #5A3A00;font-size: 12px;font-weight: 900;letter-spacing: .2px;box-shadow: inset 0 1.5px 0 rgba(255,255,255,.85),inset 0 -1.5px 0 rgba(184,134,11,.3),0 6px 14px rgba(249,168,37,.45),0 1px 2px rgba(0,0,0,.1);text-shadow: 0 1px 0 rgba(255,255,255,.4); }
.cps-v2g .cps-coin { width: 15px;height: 15px;border-radius: 50%;background: radial-gradient(circle at 35% 30%,#FFE0B2,#FFA000);box-shadow: inset 0 -1.5px 0 rgba(0,0,0,.2),0 1px 1px rgba(0,0,0,.15);display: inline-flex;align-items: center;justify-content: center;font-size: 10px;font-weight: 900;color: #7A4F00; }
.cps-v3f { display: inline-flex;align-items: center;gap: 6px;padding: 4px 12px;border-radius: 999px;background: rgba(255,179,0,.18);color: #8B6914;font-size: 12px;font-weight: 600;letter-spacing: .2px; }
.cps-v3f .cps-coin { display: inline-flex;align-items: center;justify-content: center;font-size: 15px;line-height: 1; }
/* V3 关键词高亮 */
.cps-v3 { font-size: 13px;font-weight: 500;color: var(--gray-700);line-height: 1.5; }
.cps-v3 em { font-style: normal;font-weight: 900;color: #1a1a1a;background: linear-gradient(to top,#FFD600 45%,transparent 45%);padding: 0 2px; }
/* V4 优惠券齿边小票 */
.cps-v4 { position: relative;display: inline-flex;align-items: stretch;background: #fff;border: 1.5px dashed #FFB300;border-radius: 8px;padding: 4px 12px;font-size: 12px;font-weight: 600;color: #E02E24;letter-spacing: .3px;box-shadow: 0 1px 4px rgba(255,179,0,.25); }
.cps-v4::before, .cps-v4::after { content: "";position: absolute;top: 50%;width: 8px;height: 8px;border-radius: 50%;background: #FFF3C4;transform: translateY(-50%); }
.cps-v4::before { left: -5px; }
.cps-v4::after { right: -5px; }
.cps-v4 .cps-amt { color: #1a1a1a;background: #FFD600;padding: 2px 6px;border-radius: 4px;margin: 0 4px;font-weight: 900; }
/* V5 数字驱动徽章 */
.cps-v5 { display: inline-flex;align-items: center;gap: 8px;padding: 4px 6px 4px 12px;border-radius: 999px;background: rgba(26,26,26,.06);font-size: 12px;font-weight: 600;color: var(--gray-800); }
.cps-v5 .cps-pill { display: inline-flex;align-items: baseline;gap: 2px;padding: 2px 8px;border-radius: 999px;background: #1a1a1a;color: #FFD600;font-weight: 900;font-size: 12px;letter-spacing: .3px; }
.cps-v5 .cps-pill small { font-size: 10px;font-weight: 700;opacity: .85; }
/* V6 双行节奏 */
.cps-v6 { display: flex;flex-direction: column;align-items: center;gap: 2px;line-height: 1.3; }
.cps-v6 .cps-top { font-size: 11px;font-weight: 600;color: var(--gray-500);letter-spacing: .5px;text-transform: uppercase; }
.cps-v6 .cps-bot { font-size: 13px;font-weight: 600;color: #E02E24; }
.cps-v6 .cps-bot em { font-style: normal;color: #1a1a1a;background: linear-gradient(to top,#FFD600 45%,transparent 45%);padding: 0 2px;font-weight: 900; }
/* ===== Tweaks Panel ===== */
.tweaks-panel { position: fixed; right: 20px; bottom: 20px; width: 280px; background: #fff; border-radius: 14px; box-shadow: 0 8px 32px rgba(0,0,0,.18); padding: 16px; z-index: 9998; font-family: -apple-system, sans-serif; display: none; }
.tweaks-panel.open { display: block; }
.tweaks-panel h3 { font-size: 14px; font-weight: 700; color: #1a1a1a; margin-bottom: 4px; }
.tweaks-panel .tweaks-sub { font-size: 11px; color: #999; margin-bottom: 12px; }
.tweaks-panel .tweaks-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.tweaks-opt { padding: 8px 8px; border-radius: 8px; border: 1.5px solid #e5e5e5; cursor: pointer; font-size: 12px; font-weight: 600; color: #333; background: #fff; text-align: center; transition: all .15s; }
.tweaks-opt:hover { border-color: #999; }
.tweaks-opt.active { background: #FFD600; border-color: #FFD600; color: #1a1a1a; }
.tweaks-opt small { display: block; font-size: 10px; font-weight: 500; color: #999999; margin-top: 2px; }
.tweaks-opt.active small { color: #5A3A00; }
.tweaks-close { position: absolute; top: 10px; right: 10px; width: 22px; height: 22px; border-radius: 12px; background: #f0f0f0; border: none; cursor: pointer; font-size: 13px; line-height: 1; color: #666; }
.card { background: #fff; border-radius: 14px; padding: 16px; box-shadow: 0 2px 8px rgba(0,0,0,.06); }
.section-title { font-size: 17px; font-weight: 600; color: var(--gray-900); margin-bottom: 12px; }
.badge { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
/* Tab bar — 4 tab + 中央 AI 领券 FAB(平 tab bar + FAB 站在上面) */
.tab-bar { display: flex; height: 60px; background: #fff; border-top: .5px solid var(--gray-200); flex-shrink: 0; position: relative; overflow: visible; }
.tab-item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; cursor: pointer; position: relative; z-index: 1; }
.tab-icon { width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; }
.tab-label { font-size: 11px; color: var(--gray-800); font-weight: 400; }
.tab-item.active .tab-label { color: var(--gray-900); font-weight: 700; }
.tab-icon .i-outline { display: block; }
.tab-icon .i-filled { display: none; }
.tab-item.active .tab-icon .i-outline { display: none; }
.tab-item.active .tab-icon .i-filled { display: block; }
.welfare-tab-dot {
position: absolute;
left: 50%;
top: 9px;
width: 10px;
height: 10px;
border-radius: 50%;
background: #FF3B30;
border: 1px solid #FFFFFF;
box-shadow: 0 2px 5px rgba(255, 59, 48, .32);
transform: translateX(7px);
display: none;
pointer-events: none;
z-index: 3;
}
.tab-item.has-welfare-dot .welfare-tab-dot { display: block; }
/* 横幅轮播 */
@keyframes marqueeScroll { 0%{transform: translateX(0);} 100%{transform: translateX(-50%);} }
.marquee-wrap { overflow: hidden;border-radius: 8px;background: #FFF3E0;margin-bottom: 8px;height: 32px;display: flex;align-items: center; }
/* 用户案例翻页横幅 */
.flip-banner { height: 36px;border-radius: 18px;background: linear-gradient(90deg,#FFF3E0,#FFE0B2);margin-bottom: 12px;perspective: 800px;padding: 0 6px 0 4px; }
.flip-banner-stage { width: 100%;height: 100%;position: relative;transform-style: preserve-3d;transition: transform .55s cubic-bezier(.5,0,.4,1); }
.flip-banner.flipping .flip-banner-stage { transform: rotateX(-180deg); }
.flip-banner-face { position: absolute;inset: 0;display: flex;align-items: center;gap: 8px;backface-visibility: hidden;-webkit-backface-visibility: hidden;padding: 0 8px 0 4px;overflow: hidden; }
.flip-banner-face.back { transform: rotateX(180deg); }
.flip-banner-avatar { width: 28px;height: 28px;border-radius: 14px;display: flex;align-items: center;justify-content: center;font-size: 16px;flex-shrink: 0;box-shadow: 0 1px 3px rgba(0,0,0,.08); }
.flip-banner-text { flex: 1;font-size: 12px;font-weight: 500;color: var(--gray-700);white-space: nowrap;overflow: hidden;text-overflow: ellipsis; }
.flip-banner-text .flip-name { color: var(--gray-900);font-weight: 700;margin-right: 4px; }
.flip-banner-text em { font-style: normal;color: #FF5722;font-weight: 600;margin-left: 2px; }
.marquee-track { display: flex;white-space: nowrap;animation: marqueeScroll 20s linear infinite; }
.marquee-item { display: inline-flex;align-items: center;padding: 0 24px;font-size: 12px;font-weight: 600;color: var(--gray-700); }
/* 浮窗 */
.floating-btn { position: absolute; right: 16px; bottom: 80px; width: 56px; height: 56px; border-radius: 24px; background: var(--primary); color: #1a1a1a; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 600; box-shadow: 0 4px 12px rgba(255,87,34,.4); cursor: pointer; z-index: 100; animation: pulse 2s infinite; }
@keyframes pulse { 0%,100% { box-shadow: 0 4px 12px rgba(255,87,34,.4); } 50% { box-shadow: 0 4px 24px rgba(255,87,34,.6); } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes cardHint { 0%,100% { box-shadow: 0 2px 8px rgba(255,87,34,.1); } 50% { box-shadow: 0 2px 16px rgba(255,87,34,.3); } }
@keyframes splashTickerScroll { 0% { transform: translateX(0); } 100% { transform: translateX(-50%); } }
@keyframes splashFadeIn { from { opacity: 0; } to { opacity: 1; } }
/* ===== Splash · 全图方案:splash-full-bg 含印章+taglineHTML 仅放按钮 ===== */
.splash-illustration {
position: absolute;
top: 80px; left: 0; right: 0;
height: 575px;
background-image: url('../../assets/onboarding/index/full-bg.png');
background-size: 375px auto;
background-position: top center;
background-repeat: no-repeat;
background-color: transparent;
overflow: hidden;
z-index: 1;
}
.splash-illustration::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 90px;
background: linear-gradient(to top, rgba(253,250,249,0) 0%, rgba(253,250,249,.55) 55%, rgba(253,250,249,1) 100%);
pointer-events: none;
z-index: 1;
}
/* 底部渐变:仅最末端消接缝,远离"下单前先比价"避免糊字 */
.splash-illustration::after {
content: '';
position: absolute;
bottom: 0; left: 0; right: 0;
height: 14px;
background: linear-gradient(to bottom, rgba(253,250,249,0) 0%, rgba(253,250,249,1) 100%);
pointer-events: none;
}
.splash-start-btn {
position: absolute;
bottom: 60px;
left: 50%;
transform: translateX(-50%);
width: 220px;
height: 52px;
border-radius: 24px;
background: linear-gradient(180deg, #FFEB3B 0%, #FFD600 50%, #FFC400 100%);
color: #1A1A1A;
font-size: 17px;
font-weight: 700;
letter-spacing: 4px;
text-indent: 4px;
border: none;
cursor: pointer;
z-index: 10;
box-shadow: 0 8px 22px rgba(255,193,0,.45), inset 0 1px 0 rgba(255,255,255,.55), inset 0 -2px 0 rgba(180,110,0,.10);
transition: transform .12s ease, box-shadow .2s ease, opacity .15s ease;
}
.splash-start-btn:active {
transform: translateX(-50%) scale(0.97);
opacity: 0.92;
box-shadow: 0 4px 12px rgba(255,193,0,.35), inset 0 1px 0 rgba(255,255,255,.55);
}
@keyframes safetySlideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
@keyframes safetyPopIn { from { transform: scale(.92); opacity: 0; } to { transform: scale(1); opacity: 1; } }
@keyframes confettiDrop {
0% { transform: translateY(0) translateX(0) rotate(0deg) rotateY(0deg); opacity: 1; }
25% { translateX(var(--sway)); }
50% { transform: translateY(400px) translateX(calc(var(--sway) * -1)) rotate(360deg) rotateY(540deg); opacity: 1; }
75% { translateX(var(--sway)); }
100% { transform: translateY(850px) translateX(var(--sway)) rotate(720deg) rotateY(1080deg); opacity: 0; }
}
@keyframes confettiFloat {
0% { transform: translateY(0) translateX(0) rotate(0deg) rotateX(0deg) scale(1); opacity: 1; }
100% { transform: translateY(var(--dy)) translateX(var(--dx)) rotate(var(--spin)) rotateX(1080deg) scale(0.5); opacity: 0; }
}
/* 导航指示 */
.nav-hint { position: absolute; bottom: 8px; left: 50%; transform: translateX(-50%); font-size: 11px; color: var(--gray-400); background: rgba(255,255,255,.8); padding: 4px 12px; border-radius: 12px; z-index: 50; }
/* 方案切换控制面板 */
.variant-toggle { position: fixed; top: 16px; left: 16px; z-index: 9999; }
.variant-btn { width: 36px; height: 36px; border-radius: 18px; background: #333; color: #fff; border: none; font-size: 16px; cursor: pointer; box-shadow: 0 2px 8px rgba(0,0,0,.3); display: flex; align-items: center; justify-content: center; }
.variant-btn:hover { background: #666666; }
.variant-panel { display: none; position: absolute; top: 44px; left: 0; background: #fff; border-radius: 14px; box-shadow: 0 4px 24px rgba(0,0,0,.15); padding: 16px; min-width: 260px; max-height: 70vh; overflow-y: auto; }
.variant-panel.open { display: block; }
.variant-panel h3 { font-size: 14px; font-weight: 700; color: #333; margin-bottom: 12px; }
.variant-module { margin-bottom: 12px; }
.variant-module:last-child { margin-bottom: 0; }
.variant-module-label { font-size: 12px; font-weight: 600; color: #666; margin-bottom: 6px; }
.variant-options { display: flex; gap: 6px; flex-wrap: wrap; }
.variant-opt { padding: 4px 12px; border-radius: 32px; border: 1.5px solid #e5e5e5; font-size: 12px; font-weight: 600; cursor: pointer; background: #fff; color: #666; transition: all .15s; }
.variant-opt:hover { border-color: #999; }
.variant-opt.active { background: #FFD600; border-color: #FFD600; color: #1a1a1a; }
.variant-empty { font-size: 12px; color: #999; text-align: center; padding: 16px 0; }
/* 平台icon浮动动画 */
@keyframes float1 { 0%,100%{transform: translateY(0)} 50%{transform: translateY(-6px)} }
@keyframes float2 { 0%,100%{transform: translateY(0)} 50%{transform: translateY(-8px)} }
@keyframes float3 { 0%,100%{transform: translateY(0)} 50%{transform: translateY(-5px)} }
.fly-icon.fly1 { animation: float1 3s ease-in-out infinite; }
.fly-icon.fly2 { animation: float2 2.5s ease-in-out infinite .3s; }
.fly-icon.fly3 { animation: float3 3.2s ease-in-out infinite .6s; }
/* 下滑手势动画:底部开始→往上滑→底部消失 */
@keyframes swipeDown { 0%{transform: translateY(30px) rotate(-15deg);opacity: 0} 50%{transform: translateY(-30px) rotate(-15deg);opacity: 1} 100%{transform: translateY(30px) rotate(-15deg);opacity: 0} }
.swipe-hand { animation: swipeDown 2s ease-in-out infinite; }
/* 首个卡片呼吸光效 */
@keyframes breathGlow { 0%,100%{box-shadow: 0 2px 8px rgba(255,87,34,.06)} 50%{box-shadow: 0 2px 16px rgba(255,87,34,.18)} }
.platform-card-first { animation: breathGlow 2s ease-in-out infinite; border-color: #FFD600 !important; }
/* 点击手势提示 */
@keyframes tapHint { 0%,100%{transform: translate(0,0) scale(1)} 50%{transform: translate(-2px,2px) scale(.92)} }
.tap-hand { animation: tapHint 1.2s ease-in-out infinite; }
.gesture-hand-img { display: block; width: 100%; height: 100%; object-fit: contain; }
/* 加号二级高亮:贴近原按钮的双层呼吸圈 */
.demo-plus-focus {
display: none;
position: absolute;
z-index: 14;
width: 46px;
height: 46px;
border-radius: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
}
.demo-plus-focus.circle { border-radius: 50%; }
.demo-plus-focus.pill { border-radius: 999px; }
.demo-plus-focus.rect { border-radius: 12px; }
.demo-plus-focus.confirm { border-radius: 4px 24px 24px 4px; }
.demo-plus-focus.clickable {
cursor: pointer;
pointer-events: auto;
}
.demo-plus-focus::before,
.demo-plus-focus::after {
content: "";
position: absolute;
inset: 5px;
border-radius: inherit;
border: 2px solid rgba(255,214,0,.92);
box-shadow: 0 0 12px rgba(255,214,0,.58);
transform-origin: 50% 50%;
animation: plusGuidePulse 1.45s ease-out infinite;
}
.demo-plus-focus::after {
inset: 3px;
border-color: rgba(255,255,255,.85);
animation-delay: .48s;
}
.demo-plus-core {
position: absolute;
left: 50%;
top: 50%;
width: calc(100% - 12px);
height: calc(100% - 12px);
transform: translate(-50%, -50%);
border-radius: inherit;
border: 2px solid #fff;
outline: 2px solid #FFD600;
box-shadow: 0 0 0 3px rgba(255,214,0,.18), 0 0 12px rgba(255,214,0,.68);
}
@keyframes plusGuidePulse {
0% { transform: scale(.76); opacity: .95; }
100% { transform: scale(1.38); opacity: 0; }
}
@keyframes plusGuideTap {
0%,100% { transform: translate(0,0) scale(1); }
50% { transform: translate(3px,-3px) scale(.93); }
}
#demoFinger.demo-plus-finger {
z-index: 14;
animation: plusGuideTap 1.18s ease-in-out infinite;
}
#demoFinger.demo-plus-finger .gesture-hand-img {
transform: scaleX(-1) rotate(-14deg);
}
/* 平台选择卡片 hover 效果 */
.platform-card:hover { border-color: #FF5722 !important; box-shadow: 0 0 0 1px #FF5722, 0 4px 14px rgba(255,87,34,.12); }
.platform-card:active { transform: scale(.98); }
/* 开始比价按钮光晕 */
@keyframes btnGlow {
0%,100% { box-shadow: 0 0 12px 4px rgba(218,165,0,.45), 0 0 28px 8px rgba(218,165,0,.15); }
50% { box-shadow: 0 0 22px 10px rgba(218,165,0,.6), 0 0 45px 16px rgba(218,165,0,.25); }
}
@keyframes btnGlowRing {
0% { transform: translate(-50%,-50%) scale(.85); opacity: .7; }
100% { transform: translate(-50%,-50%) scale(1.5); opacity: 0; }
}
@keyframes fadeInUp {
0% { opacity: 0; transform: translateY(20px); }
100% { opacity: 1; transform: translateY(0); }
}
@keyframes welcomeRing {
0% { transform: scale(1); opacity: .6; }
100% { transform: scale(1.4); opacity: 0; }
}
/* ===== Agent toast 数字暴涨动效 ===== */
@keyframes couponNumPop {
0% { transform: scale(1); }
30% { transform: scale(1.32); }
65% { transform: scale(.92); }
100% { transform: scale(1); }
}
.coupon-num-pop { animation: couponNumPop .28s ease-out; }
@keyframes couponPlusFly {
0% { opacity: 0; transform: translate(-50%, 0) scale(.6); }
20% { opacity: 1; transform: translate(calc(-50% + var(--dx, 0px) * .25), calc(var(--dy, -8px) * .25)) scale(1.1); }
100% { opacity: 0; transform: translate(calc(-50% + var(--dx, 0px)), var(--dy, -34px)) scale(.7); }
}
.coupon-plus-particle {
position: absolute; left: 50%; top: 6px;
font-size: 13px; font-weight: 900; color: #FF3D00;
text-shadow: 0 1px 4px rgba(255,107,0,.4);
pointer-events: none;
z-index: 3;
animation: couponPlusFly .85s ease-out forwards;
}
@keyframes couponBarFlow {
0% { width: 8%; }
100% { width: 92%; }
}
@keyframes couponBarShine {
0% { transform: translateX(-100%); }
100% { transform: translateX(400%); }
}
@keyframes giftAwait {
0%, 100% {
transform: translateY(-50%) scale(1) rotate(-8deg);
filter: drop-shadow(0 2px 4px rgba(255,180,0,.55));
}
50% {
transform: translateY(-72%) scale(1.18) rotate(8deg);
filter: drop-shadow(0 4px 10px rgba(255,180,0,.95));
}
}
/* ===== 比价副文案红包动效(摇摆 + 光晕 + sparkle===== */
@keyframes redpacketBob {
0%, 100% { transform: translateY(0) rotate(-3deg); }
50% { transform: translateY(-3px) rotate(3deg); }
}
@keyframes redpacketGlow {
0%, 100% { opacity: .35; transform: scale(.85); }
50% { opacity: 1; transform: scale(1.18); }
}
@keyframes redpacketSparkleA {
0%, 100% { opacity: 0; transform: scale(.4); }
30%, 65% { opacity: 1; transform: scale(1); }
}
@keyframes redpacketSparkleB {
0%, 100% { opacity: 0; transform: scale(.4); }
20%, 55% { opacity: 1; transform: scale(1); }
}
.redpacket-bob { animation: redpacketBob 2.4s ease-in-out infinite; }
/* ===== AI 接管橘黄色流动光晕 ===== */
@property --aiGlowAngle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
@keyframes aiGlowRotate { to { --aiGlowAngle: 360deg; } }
@keyframes aiGlowPulse {
0% { opacity: .7; }
50% { opacity: 1; }
100% { opacity: .7; }
}
@keyframes aiGlowBreathe {
0% { transform: scale(1); opacity: .85; }
50% { transform: scale(1.015); opacity: 1; }
100% { transform: scale(1); opacity: .85; }
}
.ai-takeover-glow {
display: none;
position: absolute;
inset: 0;
pointer-events: none;
z-index: 14;
border-radius: 32px;
}
.ai-takeover-glow.active { display: block; }
/* 外层流动光带:粗一圈 + 大模糊,形成柔和橘黄光晕 */
.ai-takeover-glow::before {
content: '';
position: absolute;
inset: 0;
padding: 8px;
border-radius: 32px;
background: conic-gradient(
from var(--aiGlowAngle, 0deg),
#FFE082 0%,
#FFC107 12%,
#FF8F00 24%,
#FF6B00 36%,
#FFB300 50%,
#FFD54F 62%,
#FF9800 75%,
#FF6B00 87%,
#FFE082 100%
);
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
filter: blur(7px);
animation: aiGlowRotate 5s linear infinite, aiGlowBreathe 3.2s ease-in-out infinite;
}
/* 内层柔光:从边缘向内渗透的橘色辉光,强化"光晕"感 */
.ai-takeover-glow::after {
content: '';
position: absolute;
inset: 0;
border-radius: 32px;
box-shadow: inset 0 0 36px rgba(255, 152, 0, .55),
inset 0 0 80px rgba(255, 107, 0, .28),
inset 0 0 140px rgba(255, 87, 34, .12);
animation: aiGlowPulse 2.6s ease-in-out infinite;
}
/* ===== 新手礼包弹窗 ===== */
.gift-overlay { position: absolute; inset: 0; background: rgba(0,0,0,.6); display: none; align-items: center; justify-content: center; z-index: 200; backdrop-filter: blur(2px); }
.gift-overlay.show { display: flex; animation: fadeIn .25s ease-out; }
.gift-card { width: 304px; background: #fff; border-radius: 24px; padding: 24px 16px; position: relative; box-shadow: 0 24px 60px rgba(0,0,0,.4); animation: giftPop .4s cubic-bezier(.34,1.56,.64,1); overflow: hidden; }
.gift-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 120px; background: linear-gradient(180deg, #FFE066 0%, #FFD600 50%, transparent 100%); opacity: .6; pointer-events: none; }
.gift-close { position: absolute; top: 12px; right: 12px; width: 28px; height: 28px; border-radius: 14px; background: rgba(0,0,0,.08); display: flex; align-items: center; justify-content: center; font-size: 14px; color: #666; cursor: pointer; border: none; z-index: 2; }
.gift-confetti { font-size: 22px; text-align: center; letter-spacing: 4px; margin-bottom: 8px; position: relative; z-index: 1; }
.gift-title { font-size: 24px; font-weight: 600; color: #1a1a1a; text-align: center; margin-bottom: 4px; position: relative; z-index: 1; }
.gift-subtitle { font-size: 13px; color: var(--gray-700); text-align: center; margin-bottom: 16px; position: relative; z-index: 1; }
.gift-chest-wrap { position: relative; width: 160px; height: 160px; margin: 8px auto 16px; display: flex; align-items: center; justify-content: center; }
.gift-chest-glow { position: absolute; inset: 0; border-radius: 32px; background: radial-gradient(circle, rgba(255,214,0,.7) 0%, rgba(255,214,0,0) 65%); animation: chestGlow 2s ease-in-out infinite; }
.gift-chest-emoji { font-size: 48px; position: relative; z-index: 2; animation: chestBob 2s ease-in-out infinite; transition: transform .3s; }
.gift-card.opening .gift-chest-emoji { animation: chestShake .3s ease-out; }
/* 光线 burst */
.gift-burst { position: absolute; inset: 0; pointer-events: none; opacity: 0; }
.gift-card.opened .gift-burst { animation: burstFlash .6s ease-out; }
.gift-burst-ray { position: absolute; top: 50%; left: 50%; width: 6px; height: 80px; background: linear-gradient(180deg, rgba(255,214,0,1) 0%, rgba(255,214,0,0) 100%); transform-origin: 3px 0; }
.gift-burst-ray:nth-child(1) { transform: translate(-50%, 0) rotate(0deg); }
.gift-burst-ray:nth-child(2) { transform: translate(-50%, 0) rotate(60deg); }
.gift-burst-ray:nth-child(3) { transform: translate(-50%, 0) rotate(120deg); }
.gift-burst-ray:nth-child(4) { transform: translate(-50%, 0) rotate(180deg); }
.gift-burst-ray:nth-child(5) { transform: translate(-50%, 0) rotate(240deg); }
.gift-burst-ray:nth-child(6) { transform: translate(-50%, 0) rotate(300deg); }
.gift-amount { font-size: 48px; font-weight: 900; color: #FF5722; text-align: center; line-height: 1.1; display: none; }
.gift-amount-suffix { font-size: 18px; font-weight: 700; color: var(--gray-800); margin-left: 4px; }
.gift-amount-hint { font-size: 13px; color: var(--gray-700); text-align: center; margin: 6px 0 16px; display: none; }
.gift-card.opened .gift-stage-a { display: none; }
.gift-card.opened .gift-amount,
.gift-card.opened .gift-amount-hint { display: block; }
.gift-btn { width: 100%; height: 48px; border: none; border-radius: 24px; background: linear-gradient(180deg, #FFEB3B 0%, #FFD600 100%); color: #1a1a1a; font-size: 17px; font-weight: 700; cursor: pointer; box-shadow: 0 4px 16px rgba(255,214,0,.5); position: relative; z-index: 1; }
.gift-btn:active { opacity: .85; transform: translateY(1px); }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes giftPop { 0% { opacity: 0; transform: scale(.7) translateY(20px); } 100% { opacity: 1; transform: scale(1) translateY(0); } }
@keyframes chestBob { 0%,100% { transform: translateY(0) rotate(-2deg); } 50% { transform: translateY(-8px) rotate(2deg); } }
@keyframes chestGlow { 0%,100% { transform: scale(1); opacity: .6; } 50% { transform: scale(1.15); opacity: .9; } }
@keyframes chestShake { 0%,100% { transform: scale(1); } 25% { transform: scale(1.15) rotate(-8deg); } 75% { transform: scale(1.15) rotate(8deg); } }
@keyframes burstFlash { 0% { opacity: 0; transform: scale(.4); } 30% { opacity: 1; transform: scale(1.1); } 100% { opacity: 0; transform: scale(1.6); } }
/* 飞行金币 */
.fly-coin { position: absolute; left: 50%; top: 50%; font-size: 28px; line-height: 1; pointer-events: none; z-index: 250;
transform: translate(-50%, -50%);
animation: coinFly 1100ms cubic-bezier(.55,.05,.7,.4) forwards;
animation-delay: var(--d, 0ms);
--tx: 0px; --ty: 0px; --bx: 0px; --by: 0px;
filter: drop-shadow(0 2px 4px rgba(255,179,0,.6));
}
@keyframes coinFly {
0% { opacity: 0; transform: translate(-50%, -50%) scale(.4); }
15% { opacity: 1; transform: translate(calc(-50% + var(--bx)*.2), calc(-50% + var(--by)*.2)) scale(1.4); }
35% { opacity: 1; transform: translate(calc(-50% + var(--bx)), calc(-50% + var(--by))) scale(1.2); }
100% { opacity: 0; transform: translate(calc(-50% + var(--tx)), calc(-50% + var(--ty))) scale(.5); }
}
/* 福利 tab pulse + +5000 飘字 */
.tab-pulse { animation: tabPulse .6s ease-out; }
@keyframes tabPulse { 0% { transform: scale(1); } 40% { transform: scale(1.3); filter: drop-shadow(0 0 12px rgba(255,214,0,.9)); } 100% { transform: scale(1); } }
.tab-coin-badge { position: absolute; bottom: 50px; left: 50%; transform: translateX(-50%); background: linear-gradient(180deg,#FFEB3B,#FFD600); color: #1a1a1a; font-size: 13px; font-weight: 600; padding: 4px 8px; border-radius: 32px; box-shadow: 0 4px 12px rgba(255,179,0,.6); pointer-events: none; opacity: 0; z-index: 150; white-space: nowrap; }
.tab-coin-badge.show { animation: floatUp 1.2s ease-out forwards; }
@keyframes floatUp { 0% { opacity: 0; transform: translate(-50%, 0) scale(.7); } 20% { opacity: 1; transform: translate(-50%, -8px) scale(1.1); } 100% { opacity: 0; transform: translate(-50%, -32px) scale(1); } }
/* === 登录页 · E1 方案:PNG 背景 + 纯白渐变蒙版(分界 ~62%,红包区不糊) === */
/* 背景层:PNG 满屏 + 横向渐变兜底色(PNG 加载失败时不会露白) */
#login {
background: url("../../assets/login/index/redpacket-bg.png") center top / cover no-repeat,
linear-gradient(90deg, #FEE7B7 0%, #FDEFD0 50%, #FEE7B7 100%);
}
/* E1 渐变蒙版:28% 起、52.5% 之前完全透明(保红包+优惠券不糊),57% 处 .95,64% 处完全不透明 */
#login::before {
content: '';
position: absolute;
left: 0; right: 0; top: 28%; bottom: 0;
background: linear-gradient(180deg,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0) 34%,
rgba(255, 255, 255, .55) 38%,
rgba(255, 255, 255, .95) 40.5%,
rgba(255, 255, 255, 1) 50%);
pointer-events: none;
z-index: 1;
}
/* 登录按钮去掉黄色光晕(全局 --cta-shadow 是黄底配黄阴影,登录页是白底要换中性阴影) */
#login .btn-cta {
box-shadow: 0 4px 14px rgba(0, 0, 0, .08), inset 0 1px 0 rgba(255, 255, 255, .55);
}
#login .btn-cta:active {
box-shadow: 0 2px 6px rgba(0, 0, 0, .06), inset 0 1px 0 rgba(255, 255, 255, .55);
}
/* 登录控件区:按钮位置沿用上一版,协议固定到底部 */
.lg-bottom { position: absolute; inset: 0; z-index: 5; }
.login-quick { position: absolute; inset: 0; display: block; }
.login-masked-phone { position: absolute; left: 0; right: 0; top: 64%; text-align: center; font-size: 28px; font-weight: 600; color: var(--gray-900); letter-spacing: .02em; line-height: 1; font-variant-numeric: tabular-nums; }
.login-main-btn { position: absolute; left: 7.5%; right: 7.5%; top: 71%; width: auto !important; height: 7.8%; min-height: 50px; font-size: 18px; }
.login-other-link { position: absolute; left: 0; right: 0; top: 81.5%; display: flex; align-items: center; justify-content: center; gap: 2px; border: 0; background: transparent; color: #999999; font-size: 13px; font-weight: 600; letter-spacing: .02em; cursor: pointer; font-family: inherit; }
.login-other-link .arrow { font-size: 15px; line-height: 1; color: inherit; transform: translateY(-.5px); }
.login-agreement { position: absolute; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 6; display: inline-flex; align-items: center; gap: 8px; border: 0; background: transparent; color: #999999; font-size: 12px; line-height: 1; white-space: nowrap; cursor: pointer; font-family: inherit; padding: 0; }
.login-agreement .check { width: 16px; height: 16px; margin-top: 2px; border-radius: 50%; border: 1.5px solid #CCCCCC; background: #fff; flex: 0 0 auto; position: relative; }
.login-agreement.checked .check { border-color: transparent; background: transparent url("data:image/svg+xml;utf8,<svg xmlns='http: //www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16' stroke='%23D85A1F' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><circle cx='8' cy='8' r='7'/><path d='M5 8.25 7 10 11 6'/></svg>") center/100% 100% no-repeat; background-origin: border-box; }
.login-agreement .link, .login-agreement-sheet-copy .link { color: #E65100; font-weight: 700; }
.login-phone-panel { position: absolute; left: 40px; right: 40px; top: 61%; z-index: 6; }
/* 祝贺页底部登录面板(方案 A:完整 banner + 白底简洁登录,celebration 屏内嵌一键登录) */
.celeb-login {
flex-shrink: 0; padding: 16px 24px 24px;
background: #fff; border-top: 1px solid var(--gray-200);
position: relative; z-index: 11; /* 高于 confettiCanvasz-index: 10 */
display: flex; flex-direction: column; align-items: stretch;
}
.celeb-login-phone {
text-align: center; font-size: 24px; font-weight: 600;
color: var(--gray-900); letter-spacing: .02em; margin-bottom: 12px;
font-variant-numeric: tabular-nums; line-height: 1;
}
.celeb-login > .btn-cta { width: 100%; }
.celeb-login-other {
display: block; width: 100%; margin-top: 12px;
border: 0; background: transparent; cursor: pointer; font-family: inherit;
text-align: center; color: #999999; font-size: 13px; font-weight: 600; letter-spacing: .02em;
}
.celeb-login-other .arrow { font-size: 14px; vertical-align: -1px; color: inherit; }
.celeb-login-agreement {
position: static !important; transform: none !important;
margin: 12px auto 0; display: inline-flex; left: auto; right: auto; bottom: auto;
align-self: center;
}
/* 入口页协议 · 底部抽屉(一键登录场景) */
.login-agreement-sheet-layer { display: none; position: absolute; inset: 0; z-index: 30; align-items: flex-end; background: rgba(0,0,0,.48); }
.login-agreement-sheet { width: 100%; padding: 24px 24px 32px; border-radius: 24px 24px 0 0; background: #FFFDF5; color: #1A1A1A; text-align: center; box-shadow: 0 -12px 30px rgba(0,0,0,.16); animation: loginSheetIn .24s cubic-bezier(.22,1,.36,1); }
@keyframes loginSheetIn { from { transform: translateY(24px); opacity: .75; } to { transform: translateY(0); opacity: 1; } }
.login-agreement-sheet-title { font-size: 17px; font-weight: 600; letter-spacing: .01em; margin-bottom: 12px; }
.login-agreement-sheet-copy { font-size: 13px; line-height: 1.6; color: #666666; margin-bottom: 16px; }
.login-agreement-sheet-primary { width: 100%; height: 50px; border: 0; border-radius: 999px; background: linear-gradient(180deg, #FFE066 0%, #FFD600 55%, #FFC400 100%); color: #5A3A00; font-size: 16px; font-weight: 700; letter-spacing: .04em; box-shadow: 0 12px 24px rgba(255, 200, 0, .28), inset 0 1px 0 rgba(255, 255, 255, .65); cursor: pointer; font-family: inherit; }
.login-agreement-sheet-secondary { margin-top: 12px; border: 0; background: transparent; color: #999999; font-size: 13px; cursor: pointer; font-family: inherit; padding: 8px 16px; }
/* 独立手机号登录页 */
#loginPhone { background: #fff; }
.lp-topbar { position: absolute; top: 44px; left: 0; right: 0; height: 44px; display: flex; align-items: center; padding: 0 8px; z-index: 10; }
.lp-back { width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; font-size: 24px; color: var(--gray-900); background: none; border: none; cursor: pointer; font-family: inherit; }
.lp-title { position: absolute; left: 0; right: 0; top: 132px; text-align: center; font-size: 24px; font-weight: 600; color: var(--gray-900); letter-spacing: .04em; }
.lp-form { position: absolute; left: 32px; right: 32px; top: 220px; }
.lp-input-row { display: flex; align-items: center; height: 50px; border-bottom: 1px solid var(--gray-200); }
.lp-input-row.focused { border-bottom-color: var(--gray-900); }
.lp-cc { font-size: 17px; font-weight: 600; color: var(--gray-900); letter-spacing: .02em; display: inline-flex; align-items: center; gap: 4px; margin-right: 12px; flex-shrink: 0; }
.lp-cc .chev { font-size: 10px; color: var(--gray-700); margin-left: 2px; }
.lp-divider { width: 1px; height: 18px; background: var(--gray-200); margin-right: 16px; flex-shrink: 0; }
.lp-input { flex: 1; height: 100%; border: none; padding: 0; font-size: 17px; font-weight: 500; color: var(--gray-900); letter-spacing: .04em; font-variant-numeric: tabular-nums; outline: none; background: transparent; }
.lp-input::placeholder { color: var(--gray-400); font-weight: 400; }
.lp-cta { width: 100%; margin-top: 40px; margin-bottom: 16px; }
.lp-cta.disabled { background: linear-gradient(180deg, #FFE0B2 0%, #FFE066 100%); color: rgba(26,26,26,.45); box-shadow: none; pointer-events: none; }
.lp-agreement { display: flex; align-items: flex-start; gap: 8px; color: #999999; font-size: 12px; line-height: 1.55; padding-right: 8px; cursor: pointer; border: 0; background: transparent; text-align: left; font-family: inherit; width: 100%; }
.lp-agreement .check { width: 16px; height: 16px; border-radius: 50%; border: 1.5px solid #CCCCCC; background: #fff; flex: 0 0 auto; margin-top: 2px; position: relative; }
.lp-agreement.checked .check { border-color: transparent; background: transparent url("data:image/svg+xml;utf8,<svg xmlns='http: //www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16' stroke='%23D85A1F' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><circle cx='8' cy='8' r='7'/><path d='M5 8.25 7 10 11 6'/></svg>") center/100% 100% no-repeat; background-origin: border-box; }
.lp-agreement .link { color: #E65100; font-weight: 600; }
/* 验证码步骤(沿用原 step2 视觉,放在新页内) */
.lp-sms-hint { font-size: 13px; color: var(--gray-500); margin-bottom: 16px; }
.lp-sms-boxes { display: flex; gap: 8px; justify-content: center; margin-bottom: 16px; }
.lp-sms-boxes input { width: 40px; height: 48px; border-radius: 12px; border: 1.5px solid var(--gray-200); text-align: center; font-size: 20px; font-weight: 700; outline: none; }
.lp-sms-actions { display: flex; justify-content: center; gap: 16px; }
.lp-sms-actions span { font-size: 13px; cursor: pointer; }
/* 手机号页协议 · 居中弹窗 */
.lp-modal-layer { display: none; position: absolute; inset: 0; z-index: 30; align-items: center; justify-content: center; padding: 0 32px; background: rgba(0,0,0,.5); }
.lp-modal-card { width: 100%; padding: 24px 24px 16px; border-radius: 18px; background: #fff; color: #1A1A1A; text-align: center; box-shadow: 0 20px 60px rgba(0,0,0,.3); animation: lpModalIn .24s cubic-bezier(.22,1,.36,1); }
@keyframes lpModalIn { from { transform: scale(.94); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.lp-modal-title { font-size: 17px; font-weight: 600; letter-spacing: .01em; margin-bottom: 12px; color: var(--gray-900); }
.lp-modal-copy { font-size: 13px; line-height: 1.7; color: var(--gray-700); margin-bottom: 24px; text-align: left; }
.lp-modal-copy .link { color: #E65100; font-weight: 600; }
.lp-modal-primary { width: 100%; height: 44px; border: 0; border-radius: 24px; background: linear-gradient(180deg, #FFE066 0%, #FFD600 100%); color: var(--gray-900); font-size: 15px; font-weight: 700; letter-spacing: .04em; box-shadow: 0 4px 14px rgba(0, 0, 0, .08), inset 0 1px 0 rgba(255, 255, 255, .55); cursor: pointer; font-family: inherit; }
.lp-modal-secondary { margin-top: 4px; height: 40px; border: 0; background: transparent; color: var(--gray-500); font-size: 13px; cursor: pointer; font-family: inherit; padding: 8px 16px; }
/* 新人礼包 · 优惠券样式 */
.gift-coupon { position: relative; background: linear-gradient(90deg,#FF6B6B 0%,#FF5722 100%); border-radius: 24px; padding: 16px 16px 16px 24px; display: flex; align-items: center; gap: 12px; box-shadow: 0 6px 18px rgba(255,87,34,.35); color: #fff; overflow: visible; }
.gift-coupon::before { content: ''; position: absolute; top: 50%; left: -6px; transform: translateY(-50%); width: 12px; height: 12px; background: #FFF8E1; border-radius: 50%; }
.gift-coupon::after { content: ''; position: absolute; left: 16px; top: 12px; bottom: 12px; width: 1px; background-image: linear-gradient(180deg, rgba(255,255,255,.5) 50%, transparent 50%); background-size: 1px 6px; }
.gift-coupon .gc-icon { flex-shrink: 0; font-size: 48px; line-height: 1; filter: drop-shadow(0 2px 6px rgba(0,0,0,.2)); }
.gift-coupon .gc-title { font-size: 18px; font-weight: 900; color: #fff; margin-bottom: 4px; }
.gift-coupon .gc-sub { font-size: 12px; color: rgba(255,255,255,.9); }
/* 新人礼包 · 7 方案样式(用于 ?giftvariant= 切换) */
.gv-base { position: relative; border-radius: 24px; display: flex; align-items: center; gap: 12px; }
.gv-a { background: linear-gradient(135deg,#FFF3E0,#FFE0B2); padding: 16px; box-shadow: 0 4px 16px rgba(255,179,0,.18); }
.gv-a .gv-icon { flex-shrink: 0; font-size: 48px; line-height: 1; }
.gv-a .gv-title { font-size: 18px; font-weight: 600; color: #1a1a1a; margin-bottom: 4px; }
.gv-a .gv-sub { font-size: 12px; color: var(--gray-700); }
.gv-b { background: linear-gradient(135deg,#FFF3E0,#FFE0B2); padding: 16px; box-shadow: 0 4px 16px rgba(255,179,0,.18); }
.gv-b .gv-icon { flex-shrink: 0; font-size: 48px; line-height: 1; }
.gv-b .gv-title { font-size: 18px; font-weight: 600; color: #1a1a1a; margin-bottom: 4px; }
.gv-b .gv-sub { font-size: 12px; color: var(--gray-700); }
.gv-b .gv-stamp { position: absolute; top: -10px; right: 14px; background: linear-gradient(135deg,#FF5722,#E65100); color: #fff; font-size: 11px; font-weight: 600; padding: 6px 12px; border-radius: 12px 12px 12px 4px; box-shadow: 0 4px 10px rgba(255,87,34,.4); transform: rotate(8deg); }
.gv-c { background: linear-gradient(135deg,#FFF3E0,#FFE0B2); padding: 16px; box-shadow: 0 4px 16px rgba(255,179,0,.18); }
.gv-c .gv-icon { flex-shrink: 0; font-size: 48px; line-height: 1; }
.gv-c .gv-title { font-size: 18px; font-weight: 600; color: #1a1a1a; margin-bottom: 6px; }
.gv-c .gv-cd { display: inline-flex; align-items: center; gap: 4px; background: #1a1a1a; color: #FFD600; font-size: 11px; font-weight: 600; padding: 4px 8px; border-radius: 8px; font-variant-numeric: tabular-nums; }
.gv-c .gv-blink { animation: gvBlink 1s infinite; }
@keyframes gvBlink { 50% { opacity: .3; } }
.gv-d { background: linear-gradient(135deg,#FFE0B2 0%,#FFE066 50%,#FFE066 100%); padding: 24px 16px; box-shadow: 0 8px 24px rgba(255,87,34,.25), inset 0 1px 0 rgba(255,255,255,.6); overflow: hidden; }
.gv-d .gv-iconwrap { position: relative; flex-shrink: 0; width: 70px; height: 70px; display: flex; align-items: center; justify-content: center; }
.gv-d .gv-icon { position: relative; font-size: 48px; line-height: 1; filter: drop-shadow(0 4px 8px rgba(255,87,34,.3)); }
.gv-d .gv-text { position: relative; z-index: 1; }
.gv-d .gv-title { font-size: 20px; font-weight: 900; color: #1a1a1a; margin-bottom: 4px; letter-spacing: -.3px; }
.gv-d .gv-sub { font-size: 13px; color: #5A3A00; font-weight: 600; }
.gv-f { background: radial-gradient(circle at 50% 20%, rgba(255,255,255,.8), transparent 50%), linear-gradient(135deg,#FFF3E0,#FFE0B2); padding: 24px 16px 24px; box-shadow: 0 8px 24px rgba(255,179,0,.25); flex-direction: column; text-align: center; overflow: hidden; }
.gv-f .gv-rays { position: absolute; top: -20px; left: 50%; transform: translateX(-50%); width: 200px; height: 200px; pointer-events: none; background: conic-gradient(from 0deg, rgba(255,213,79,.3) 0deg, transparent 30deg, rgba(255,213,79,.3) 60deg, transparent 90deg, rgba(255,213,79,.3) 120deg, transparent 150deg, rgba(255,213,79,.3) 180deg, transparent 210deg, rgba(255,213,79,.3) 240deg, transparent 270deg, rgba(255,213,79,.3) 300deg, transparent 330deg); border-radius: 50%; animation: gvSpin 12s linear infinite; opacity: .6; }
@keyframes gvSpin { to { transform: translateX(-50%) rotate(360deg); } }
.gv-f .gv-iconwrap { position: relative; z-index: 1; margin-bottom: 8px; }
.gv-f .gv-icon { font-size: 48px; line-height: 1; display: inline-block; animation: gvBob 2.5s infinite ease-in-out; filter: drop-shadow(0 6px 12px rgba(255,87,34,.3)); }
@keyframes gvBob { 50% { transform: translateY(-4px); } }
@keyframes gvPop { 0% { transform: scale(.4); opacity: 0; } 60% { transform: scale(1.08); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
.gv-f .gv-title { position: relative; z-index: 1; font-size: 22px; font-weight: 900; color: #1a1a1a; margin-bottom: 4px; letter-spacing: -.3px; }
.gv-f .gv-sub { position: relative; z-index: 1; font-size: 12px; color: #5A3A00; font-weight: 600; }
.gv-g { background: linear-gradient(135deg,#FFF3E0,#FFE0B2); padding: 16px; box-shadow: 0 4px 16px rgba(255,179,0,.18); overflow: hidden; }
.gv-g .gv-iconwrap { position: relative; flex-shrink: 0; width: 56px; height: 56px; display: flex; align-items: center; justify-content: center; }
.gv-g .gv-icon { font-size: 48px; line-height: 1; }
.gv-g .gv-spark { position: absolute; width: 6px; height: 6px; background: #FFD600; border-radius: 50%; box-shadow: 0 0 8px #FFD600; }
.gv-g .gv-s1 { top: 0; right: 4px; animation: gvSparkle 1.8s infinite; }
.gv-g .gv-s2 { bottom: 4px; left: 0; animation: gvSparkle 1.8s infinite .6s; }
.gv-g .gv-s3 { top: 50%; right: -4px; animation: gvSparkle 1.8s infinite 1.2s; }
@keyframes gvSparkle { 0%,100% { transform: scale(0); opacity: 0; } 50% { transform: scale(1); opacity: 1; } }
.gv-g .gv-title { font-size: 18px; font-weight: 900; color: #1a1a1a; margin-bottom: 4px; }
.gv-g .gv-title em { font-style: normal; background: linear-gradient(90deg, #FF5722, #FFB300); -webkit-background-clip: text; background-clip: text; color: transparent; margin-left: 4px; font-weight: 900; }
.gv-g .gv-sub { font-size: 12px; color: var(--gray-700); }
body.gv-embed .variant-toggle { display: none !important; }
/* ===== Coupon prompt 变体 · 平台选择卡通用样式 ===== */
.cp-card { transition: all .2s; cursor: pointer; }
.cp-card[data-checked="false"] { opacity: .5; }
.cp-card[data-checked="false"] .cp-check { background: var(--gray-300) !important; }
.cp-card[data-checked="false"] .cp-check svg { opacity: 0; }
/* 选中态边框色按主题分 */
.cp-card-pink[data-checked="false"] { border-color: var(--gray-200) !important; }
.cp-card-red[data-checked="false"] { border-color: var(--gray-200) !important; }
.cp-card-yellow[data-checked="false"] { border-color: var(--gray-200) !important; }
.cp-card-yellow[data-checked="false"] .cp-toggle { background: var(--gray-200) !important; }
.cp-card-yellow[data-checked="false"] .cp-toggle::after { transform: translateX(0) !important; }
/* ============================================
一键领券完成 · 迭代 6 配色 B(朱红卡包风)
============================================ */
.coupon-done-k-mask {
position: absolute; inset: 0;
background: rgba(0,0,0,.55);
z-index: 28;
animation: kFadeIn .3s ease-out;
}
@keyframes kFadeIn { from { opacity: 0; } to { opacity: 1; } }
.coupon-done-k {
/* 配色 B · 朱红 */
--v6-bg-top: #FF1744;
--v6-bg-bottom: #C62828;
--v6-pocket-top: #FF5252;
--v6-pocket-bottom: #E53935;
--v6-notch: #C62828;
position: absolute; left: 50%; top: 50%;
transform: translate(-50%, -50%);
z-index: 30;
width: 296px;
background: linear-gradient(180deg, var(--v6-bg-top) 0%, var(--v6-bg-bottom) 65%, var(--v6-bg-bottom) 100%);
border-radius: 24px;
box-shadow: 0 20px 50px rgba(0,0,0,.4);
overflow: visible;
animation: kPopIn .5s cubic-bezier(.34,1.56,.64,1);
}
@keyframes kPopIn {
0% { opacity: 0; transform: translate(-50%, -50%) scale(.85); }
100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
/* 顶部居中品牌 logo(与 splash / 浮窗一致:黄色圆角方块 + 机器人 SVG + 文字) */
.coupon-done-k .coupon-done-logo {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 16px 0 2px;
position: relative;
z-index: 3;
}
.coupon-done-k .coupon-done-logo .logo-mark {
width: 32px; height: 32px;
border-radius: 8px;
background: linear-gradient(135deg, #FFD600, #FFB300);
display: flex; align-items: center; justify-content: center;
flex-shrink: 0;
box-shadow: 0 4px 10px rgba(0,0,0,.22);
}
.coupon-done-k .coupon-done-logo .logo-text {
font-size: 15px; font-weight: 900;
color: #fff;
letter-spacing: 0.8px;
text-shadow: 0 1px 2px rgba(0,0,0,.22);
}
/* sparkle 黄色星光 */
.coupon-done-k .v6-sparkle {
position: absolute;
width: 7px; height: 7px;
background: #FFE066; border-radius: 50%;
box-shadow: 0 0 8px #FFE082;
animation: kSparkleTwinkle 1.5s infinite ease-in-out;
z-index: 2;
}
.coupon-done-k .v6-sparkle.s1 { top: 14px; left: 22px; }
.coupon-done-k .v6-sparkle.s2 { top: 22px; right: 28px; animation-delay: .3s; }
.coupon-done-k .v6-sparkle.s3 { top: 60px; left: 28px; animation-delay: .6s; width: 5px; height: 5px; }
.coupon-done-k .v6-sparkle.s4 { top: 50px; right: 32px; animation-delay: .9s; width: 5px; height: 5px; }
.coupon-done-k .v6-sparkle.s5 { top: 38px; left: 50%; animation-delay: 1.1s; width: 4px; height: 4px; }
@keyframes kSparkleTwinkle {
0%, 100% { opacity: .3; transform: scale(.6); }
50% { opacity: 1; transform: scale(1.2); }
}
/* 头部双行渐变文案(票卡删除后改为页面中心展示) */
.coupon-done-k .v6-head {
text-align: center;
padding: 24px 16px 24px;
color: #fff; position: relative; z-index: 1;
}
.coupon-done-k .v6-head .lead-line {
font-size: 20px; font-weight: 600;
margin-bottom: 12px;
background: linear-gradient(180deg, #fff 30%, #FFE0B2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
letter-spacing: 1px;
}
.coupon-done-k .v6-head .num-line {
font-size: 28px; font-weight: 900;
line-height: 1.1;
text-shadow: 0 2px 10px rgba(0,0,0,.28);
letter-spacing: 0.5px;
}
.coupon-done-k .v6-head .num-line .num {
color: #FFE066;
font-family: -apple-system, "DIN Alternate", sans-serif;
font-size: 36px;
margin-right: 2px;
}
.coupon-done-k .v6-head .num-line .rest {
background: linear-gradient(180deg, #fff 30%, #FFE066 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
/* 平台来源:"来自 + 两个 logo",不写平台名 */
.coupon-done-k .v6-from {
display: flex; align-items: center; justify-content: center;
gap: 8px;
padding: 6px 16px 12px;
position: relative; z-index: 1;
}
.coupon-done-k .v6-from .label {
font-size: 12px; font-weight: 600;
color: rgba(255,255,255,.85);
letter-spacing: 0.04em;
}
.coupon-done-k .v6-from .lgs { display: flex; align-items: center; gap: 6px; }
.coupon-done-k .v6-from .lg {
width: 28px; height: 28px;
border-radius: 8px; overflow: hidden;
border: 2px solid #fff;
box-shadow: 0 2px 6px rgba(0,0,0,.25);
background: #fff;
}
.coupon-done-k .v6-from .lg img { width: 100%; height: 100%; object-fit: cover; }
/* v3:标题内联式 — 把"领取自 + 平台 logo"嵌入第一行文案,密度最高 */
.coupon-done-k .v6-head .lead-line-inline {
display: inline-flex; align-items: center; justify-content: center;
flex-wrap: wrap; gap: 4px;
/* 取消渐变文字,避免与内联图片混搭显得别扭 */
background: none;
-webkit-text-fill-color: #fff;
color: #fff;
letter-spacing: .3px;
}
.coupon-done-k .v6-head .lead-line-inline .lg-inline {
display: inline-block;
width: 28px; height: 28px;
border-radius: 8px; overflow: hidden;
box-shadow: 0 1px 4px rgba(0,0,0,.25);
vertical-align: middle;
}
.coupon-done-k .v6-head .lead-line-inline .lg-inline img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* v2:领取自上提(顶部胶囊;与领取数量绑定为同一信息块) */
.coupon-done-k .v6-from-top {
display: inline-flex; align-items: center; gap: 6px;
margin: 0 auto 12px;
padding: 4px 12px 4px 8px;
background: rgba(255,255,255,.16);
border: 1px solid rgba(255,255,255,.22);
border-radius: 999px;
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
}
.coupon-done-k .v6-from-top .label {
font-size: 11px; font-weight: 700;
color: rgba(255,255,255,.92);
letter-spacing: 0.04em;
}
.coupon-done-k .v6-from-top .lgs { gap: 4px; }
.coupon-done-k .v6-from-top .lg {
width: 18px; height: 18px;
border-width: 1.5px;
box-shadow: 0 1px 3px rgba(0,0,0,.2);
}
/* 整体 head 容器在使用 v6-from-top 时改 flex column 居中(让胶囊上居中) */
.coupon-done-k .v6-head:has(> .v6-from-top) {
display: flex; flex-direction: column; align-items: center;
padding-top: 12px;
}
.coupon-done-k .v6-head:has(> .v6-from-top) .lead-line {
margin-bottom: 8px;
}
/* 白色票卡 */
.coupon-done-k .v6-tickets {
display: flex; gap: 12px;
padding: 6px 16px 16px;
position: relative; z-index: 1;
}
.coupon-done-k .v6-tickets .pl {
flex: 1;
background: #fff;
border-radius: 8px;
padding: 12px 6px;
text-align: center;
position: relative;
box-shadow: 0 4px 12px rgba(0,0,0,.15);
}
/* 票卡左右切角 */
.coupon-done-k .v6-tickets .pl::before,
.coupon-done-k .v6-tickets .pl::after {
content: '';
position: absolute;
width: 12px; height: 12px;
background: var(--v6-bg-top);
border-radius: 50%;
top: 50%; transform: translateY(-50%);
}
.coupon-done-k .v6-tickets .pl::before { left: -6px; clip-path: inset(0 0 0 50%); }
.coupon-done-k .v6-tickets .pl::after { right: -6px; clip-path: inset(0 50% 0 0); }
.coupon-done-k .v6-tickets .pl .num {
font-size: 24px; font-weight: 900; color: #E02E24;
font-family: -apple-system, "DIN Alternate", sans-serif;
line-height: 1; letter-spacing: -0.5px;
}
.coupon-done-k .v6-tickets .pl .num small {
font-size: 11px; color: #E02E24; font-weight: 700; margin-left: 2px;
}
.coupon-done-k .v6-tickets .pl .dash {
margin: 8px 4px;
border-top: 1px dashed #FFCDD2;
}
.coupon-done-k .v6-tickets .pl .lg {
width: 32px; height: 32px;
border-radius: 8px; overflow: hidden;
background: #FFF8E1; margin: 0 auto;
box-shadow: 0 2px 5px rgba(0,0,0,.06);
}
.coupon-done-k .v6-tickets .pl .lg img { width: 100%; height: 100%; object-fit: cover; }
/* pocket 上层(浅)+ U 形凹口 */
.coupon-done-k .v6-pocket {
background: linear-gradient(180deg, var(--v6-pocket-top) 0%, var(--v6-pocket-bottom) 100%);
padding: 24px 16px 12px;
position: relative;
z-index: 1;
border-radius: 24px;
box-shadow: 0 -6px 14px rgba(0,0,0,.18);
}
.coupon-done-k .v6-pocket-notch {
position: absolute;
top: 0; left: 50%;
transform: translateX(-50%);
width: 44px; height: 16px;
background: var(--v6-notch);
border-radius: 0 0 32px 32px;
z-index: 2;
}
.coupon-done-k .v6-expiry {
text-align: center;
color: #fff;
font-size: 13px;
font-weight: 600;
margin-bottom: 12px;
margin-top: 4px;
letter-spacing: 0.3px;
position: relative; z-index: 2;
}
.coupon-done-k .v6-expiry .time-box {
display: inline-block;
background: #fff;
color: #E02E24;
padding: 2px 4px;
border-radius: 4px;
font-weight: 600;
font-size: 13px;
font-family: -apple-system, "DIN Alternate", sans-serif;
margin: 0 2px;
letter-spacing: -0.5px;
box-shadow: 0 1px 3px rgba(0,0,0,.15);
}
.coupon-done-k .v6-cta {
width: 100%;
background: linear-gradient(135deg, #FFEB3B 0%, #FFD600 50%, #FFC400 100%);
color: #1a1a1a;
border: none;
padding: 12px;
border-radius: 24px;
font-size: 15px;
font-weight: 900;
cursor: pointer;
box-shadow: inset 0 -2px 0 rgba(184,134,11,.18);
position: relative; z-index: 2;
letter-spacing: 1px;
}
/* ===== 比价结果页:全网最低价徽章(图片) + N2 chip ===== */
.card.with-ribbon { overflow: visible; }
.ribbon-vi {
position: absolute;
top: -16px; right: -6px;
width: 104px;
height: auto;
z-index: 3;
pointer-events: none;
filter: drop-shadow(0 4px 10px rgba(220,40,40,0.25));
}
/* 价格旁红 chip "比原选择省 ¥X" — 强调"省了多少",刻意放大 */
.save-chip-red {
background: linear-gradient(135deg, #FE2C55, #FF6B3D);
color: #fff;
border-radius: 8px;
padding: 4px 12px;
font-size: 15px;
font-weight: 600;
letter-spacing: 0.2px;
align-self: center;
display: inline-flex; align-items: baseline; gap: 2px;
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
white-space: nowrap;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.save-chip-red .small { font-size: 12px; opacity: 1; font-weight: 700; }
.result-cta {
flex-shrink: 0;
min-height: 34px;
padding: 6px 16px;
border: none;
border-radius: 999px;
font-size: 13px;
font-weight: 700;
line-height: 1;
cursor: pointer;
background: var(--gray-100);
color: var(--gray-800);
display: inline-flex;
align-items: center;
justify-content: center;
gap: 2px;
white-space: nowrap;
}
.result-cta .arrow {
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--gray-500);
font-size: 15px;
line-height: 1;
transform: translateY(-.5px);
}
/* 用户原选 chip:店名旁描边方角 */
.badge-userorig {
flex-shrink: 0;
display: inline-flex; align-items: center;
background: transparent;
border: 1px solid #CCCCCC;
border-radius: 4px;
padding: 2px 8px;
font-size: 11px; font-weight: 600;
color: #666666; letter-spacing: .3px;
white-space: nowrap;
}
/* ===== Kickoff 引导卡(首次进店)— L·I 升级版:黄 header + 米黄 body ===== */
.kickoff-card {
position: relative;
border-radius: 14px;
box-shadow: 0 14px 30px rgba(0,0,0,.32), 0 4px 14px rgba(255,179,0,.22);
}
/* 气泡上方的 journey 排版字(无卡片背景,闲鱼式:白字 + 关键词黄字 + 弧线下划) */
.kickoff-promo {
position: absolute;
bottom: 100%;
left: 0; right: 0;
margin-bottom: 24px;
text-align: center;
pointer-events: none;
}
.kickoff-promo .promo-line {
font-size: 22px;
font-weight: 900;
color: #fff;
line-height: 1.35;
letter-spacing: .5px;
-webkit-text-stroke: 0.4px currentColor; /* 在 900 之上再加描边,视觉更粗 */
text-stroke: 0.4px currentColor;
text-shadow: 0 2px 12px rgba(0,0,0,.7), 0 1px 3px rgba(0,0,0,.55), 0 0 2px rgba(0,0,0,.35);
}
.kickoff-promo .promo-accent {
position: relative;
display: inline-block;
padding: 0 2px;
color: #FFEB3B;
}
/* SVG 手绘风弧线下划,仿闲鱼那种"标注"感(按字号同比例放大) */
.kickoff-promo .promo-accent::after {
content: '';
position: absolute;
left: -2px; right: -2px;
bottom: -7px;
height: 9px;
background: url("data:image/svg+xml;utf8,<svg xmlns='http: //www.w3.org/2000/svg' viewBox='0 0 100 9' preserveAspectRatio='none'><path d='M2 5 Q 25 1 50 4.5 T 98 4.5' stroke='%23FFE34D' stroke-width='2.8' fill='none' stroke-linecap='round'/></svg>") no-repeat center / 100% 100%;
}
.kickoff-head {
background: linear-gradient(135deg, #FFEB3B 0%, #FFD600 100%);
padding: 8px 12px 8px;
display: flex; align-items: center; gap: 8px;
border-radius: 14px 14px 0 0;
}
.kickoff-dot {
width: 6px; height: 6px; border-radius: 50%;
background: #1a1a1a;
flex-shrink: 0;
}
.kickoff-title {
font-size: 14px; font-weight: 900; color: #1a1a1a;
letter-spacing: .5px; line-height: 1.2;
}
.kickoff-body {
background: #FFF8E1;
padding: 12px 12px 12px;
font-size: 13px; font-weight: 700; color: #1a1a1a;
line-height: 1.5;
border-radius: 0 0 14px 14px;
}
.kickoff-leader {
position: absolute;
bottom: -36px; left: 50%; margin-left: -1px;
width: 2px; height: 36px;
background: linear-gradient(180deg, rgba(255,214,0,0) 0%, #FFD600 30%, #FFD600 100%);
border-radius: 4px;
pointer-events: none;
}
.kickoff-leader::before {
content: '';
position: absolute; bottom: -4px; left: -4px;
width: 10px; height: 10px; border-radius: 50%;
background: #fff;
border: 2px solid #1a1a1a;
box-sizing: border-box;
box-shadow: 0 0 0 3px rgba(255,214,0,.55), 0 1px 3px rgba(0,0,0,.25);
animation: kickoffLeaderDot 1.6s ease-in-out infinite;
}
@keyframes kickoffLeaderDot {
0%, 100% { box-shadow: 0 0 0 3px rgba(255,214,0,.55), 0 1px 3px rgba(0,0,0,.25); }
50% { box-shadow: 0 0 0 6px rgba(255,214,0,.2), 0 1px 3px rgba(0,0,0,.25); }
}
/* 比价流程内引导气泡的黄色连接线(动态长度+方向,dot 落点贴住 spotlight 边缘) */
#demoGuide .demo-guide-leader {
position: absolute;
left: 50%; margin-left: -1px;
width: 2px;
border-radius: 4px;
pointer-events: none;
}
#demoGuide .demo-guide-leader.dir-down {
top: 100%;
background: linear-gradient(180deg, rgba(255,214,0,0) 0%, #FFD600 30%, #FFD600 100%);
}
#demoGuide .demo-guide-leader.dir-down::before {
content: '';
position: absolute; bottom: -4px; left: -4px;
width: 10px; height: 10px; border-radius: 50%;
background: #fff;
border: 2px solid #1a1a1a;
box-sizing: border-box;
box-shadow: 0 0 0 3px rgba(255,214,0,.55), 0 1px 3px rgba(0,0,0,.25);
animation: kickoffLeaderDot 1.6s ease-in-out infinite;
}
#demoGuide .demo-guide-leader.dir-up {
bottom: 100%;
background: linear-gradient(0deg, rgba(255,214,0,0) 0%, #FFD600 30%, #FFD600 100%);
}
#demoGuide .demo-guide-leader.dir-up::before {
content: '';
position: absolute; top: -4px; left: -4px;
width: 10px; height: 10px; border-radius: 50%;
background: #fff;
border: 2px solid #1a1a1a;
box-sizing: border-box;
box-shadow: 0 0 0 3px rgba(255,214,0,.55), 0 1px 3px rgba(0,0,0,.25);
animation: kickoffLeaderDot 1.6s ease-in-out infinite;
}
/* 一键比价入口 · 右下角 kickoff 卡(leader 偏右对齐侧贴按钮中心)*/
.start-compare-kickoff {
position: absolute;
right: 14px;
width: 310px;
bottom: 246px;
z-index: 16;
pointer-events: none;
}
.start-compare-kickoff .kickoff-leader {
left: auto;
right: 50px;
margin-left: 0;
}
/* 比价中浮窗 · 三平台并行 mini icons */
.cmp-platform-mini { position: relative; width: 24px; height: 24px; }
.cmp-platform-mini > img { width: 100%; height: 100%; border-radius: 4px; object-fit: cover; display: block; }
.cmp-platform-mini.done::after {
content: ''; position: absolute; bottom: -3px; right: -3px;
width: 12px; height: 12px; border-radius: 50%; background: #22C55E;
border: 1.5px solid #fff;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M2 5l2 2 4-5' stroke='%23fff' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
background-size: 8px; background-repeat: no-repeat; background-position: center;
}
.cmp-platform-mini.active::after {
content: ''; position: absolute; inset: -4px;
border: 2px solid #FFD600; border-top-color: transparent;
border-radius: 50%; animation: spin 0.8s linear infinite;
}
.cmp-platform-mini.pending { opacity: 0.4; filter: grayscale(0.6); }
/* ============ 2. VIDEO 教程页 (vt-) ============ */
#video .vt-video-player {
flex-shrink: 0; height: 667px; background: #000;
position: relative; overflow: hidden;
}
#video .vt-poster {
position: absolute; inset: 0;
background: radial-gradient(ellipse at 25% 15%, rgba(255,255,255,.45) 0%, transparent 55%),
radial-gradient(ellipse at 80% 90%, rgba(255,87,34,.18) 0%, transparent 60%),
linear-gradient(160deg, #FFE57F 0%, #FFD54F 35%, #FFB300 75%, #F57F17 100%);
display: flex; align-items: center; justify-content: center;
cursor: pointer; overflow: hidden;
}
#video .vt-poster::before {
content: ''; position: absolute; inset: 0;
background: radial-gradient(circle at 18% 88%, rgba(255,255,255,.15) 0%, transparent 8%),
radial-gradient(circle at 88% 22%, rgba(255,255,255,.18) 0%, transparent 6%);
pointer-events: none;
}
#video .vt-video-player.paused .vt-poster::after,
#video .vt-video-player.initial .vt-poster::after {
content: ''; position: absolute; inset: 0;
background: rgba(0,0,0,.18); z-index: 2; pointer-events: none;
}
/* 商品对比卡 */
#video .vt-poster-compare {
display: flex; align-items: center; gap: 8px;
background: rgba(255,255,255,.95); border-radius: 18px;
padding: 12px 16px;
box-shadow: 0 14px 36px rgba(140,70,0,.22), 0 2px 6px rgba(0,0,0,.08);
z-index: 2; position: relative;
}
#video .vt-pc-card {
display: flex; flex-direction: column; align-items: center;
gap: 4px; padding: 4px 8px; min-width: 70px; position: relative;
}
#video .vt-pc-label { font-size: 10px; color: #999; font-weight: 600; letter-spacing: .3px; }
#video .vt-pc-card.win .vt-pc-label {
color: #fff; background: linear-gradient(135deg, #FF6B6B, #E53935);
padding: 2px 8px; border-radius: 4px;
box-shadow: 0 2px 4px rgba(229,57,53,.3);
}
#video .vt-pc-price {
font-size: 22px; font-weight: 800; color: #1a1a1a;
font-variant-numeric: tabular-nums; letter-spacing: -.5px;
}
#video .vt-pc-price.strike { color: #CCCCCC; text-decoration: line-through; font-size: 18px; font-weight: 600; }
#video .vt-pc-price.now { color: #E53935; font-size: 24px; }
#video .vt-pc-arrow { color: #E65100; font-size: 22px; font-weight: 600; text-shadow: 0 2px 4px rgba(255,111,0,.3); }
#video .vt-pc-save-tag {
position: absolute; top: -10px; right: -8px;
font-size: 10px; font-weight: 600; color: #fff;
background: linear-gradient(135deg, #FF6B6B, #E53935);
padding: 2px 6px; border-radius: 8px 8px 8px 4px;
box-shadow: 0 2px 6px rgba(229,57,53,.45);
transform: rotate(8deg); white-space: nowrap;
}
/* 装饰金币 */
#video .vt-coin {
position: absolute; z-index: 1; border-radius: 50%;
background: linear-gradient(135deg, #FFE066 0%, #FFC300 50%, #FFA000 100%);
display: flex; align-items: center; justify-content: center;
font-weight: 800; color: #5A3A00;
box-shadow: 0 4px 10px rgba(120,60,0,.25),
inset 0 1px 2px rgba(255,255,255,.7),
inset 0 -1px 2px rgba(139,69,19,.3);
border: 1.5px solid rgba(180,100,30,.25);
}
#video .vt-coin-tl { top: 14%; left: 10%; width: 36px; height: 36px; font-size: 17px; transform: rotate(-12deg); animation: vtFloatA 3.2s ease-in-out infinite; }
#video .vt-coin-tr { top: 22%; right: 9%; width: 28px; height: 28px; font-size: 13px; transform: rotate(18deg); animation: vtFloatB 3.6s ease-in-out infinite .3s; }
#video .vt-coin-bl { bottom: 28%; left: 14%; width: 24px; height: 24px; font-size: 12px; transform: rotate(8deg); animation: vtFloatA 3.8s ease-in-out infinite .6s; }
#video .vt-coin-br { bottom: 18%; right: 12%; width: 32px; height: 32px; font-size: 15px; transform: rotate(-15deg); animation: vtFloatB 3.4s ease-in-out infinite .9s; }
@keyframes vtFloatA { 0%,100% { transform: rotate(-12deg) translateY(0); } 50% { transform: rotate(-12deg) translateY(-8px); } }
@keyframes vtFloatB { 0%,100% { transform: rotate(18deg) translateY(0); } 50% { transform: rotate(18deg) translateY(-10px); } }
/* 闪光 */
#video .vt-sparkle {
position: absolute; z-index: 1; width: 8px; height: 8px;
background: linear-gradient(to bottom, transparent 45%, rgba(255,255,255,.9) 50%, transparent 55%),
linear-gradient(to right, transparent 45%, rgba(255,255,255,.9) 50%, transparent 55%);
transform: rotate(45deg);
animation: vtSparkle 2.4s ease-in-out infinite;
}
#video .vt-sparkle-1 { top: 38%; left: 22%; }
#video .vt-sparkle-2 { top: 56%; right: 24%; animation-delay: .6s; }
#video .vt-sparkle-3 { top: 70%; left: 38%; width: 6px; height: 6px; animation-delay: 1.2s; }
@keyframes vtSparkle { 0%,100% { opacity: 0; transform: rotate(45deg) scale(.5); } 50% { opacity: 1; transform: rotate(45deg) scale(1); } }
/* dim overlay */
#video .vt-dim-overlay {
position: absolute; inset: 0; z-index: 4;
background: rgba(0,0,0,.5); pointer-events: none;
opacity: 0; transition: opacity .35s;
}
#video .vt-video-player.ended .vt-dim-overlay { opacity: 1; }
/* center play */
#video .vt-center-play {
position: absolute; left: 50%; top: 50%;
width: 72px; height: 72px;
background: rgba(0,0,0,.5); border-radius: 50%;
display: flex; align-items: center; justify-content: center;
transform: translate(-50%, -50%); cursor: pointer;
box-shadow: 0 8px 24px rgba(0,0,0,.3);
transition: opacity .2s, background .15s; z-index: 6;
}
#video .vt-center-play svg { width: 30px; height: 30px; fill: #fff; margin-left: 2px; }
#video .vt-video-player.playing .vt-center-play { opacity: 0; pointer-events: none; }
#video .vt-video-player.paused .vt-center-play,
#video .vt-video-player.initial .vt-center-play {
opacity: 1; visibility: visible; pointer-events: auto;
}
#video .vt-video-player.ended .vt-center-play {
width: 80px; height: 80px;
background: rgba(255,255,255,.18);
border: 2px solid rgba(255,255,255,.45);
backdrop-filter: blur(8px);
}
#video .vt-video-player.ended .vt-center-play svg { width: 32px; height: 32px; margin-left: 0; }
/* controls */
#video .vt-controls {
position: absolute; left: 0; right: 0; bottom: 0;
padding: 12px 12px 16px;
background: linear-gradient(180deg, transparent, rgba(0,0,0,.7) 55%);
z-index: 3;
}
#video .vt-progress-row { display: flex; align-items: center; gap: 8px; }
#video .vt-time {
font-size: 11px; font-weight: 600; color: #fff;
min-width: 32px; text-align: center; font-variant-numeric: tabular-nums;
}
#video .vt-ctrl-pill {
width: 36px; height: 36px; border-radius: 50%;
background: rgba(255,255,255,.18);
display: flex; align-items: center; justify-content: center;
cursor: pointer; flex-shrink: 0;
transition: background .15s, transform .12s;
backdrop-filter: blur(4px);
}
#video .vt-ctrl-pill:active { transform: scale(.92); }
#video .vt-ctrl-pill svg { width: 16px; height: 16px; fill: #fff; }
/* track 24px 大命中区 */
#video .vt-progress-track {
flex: 1; height: 24px; background: transparent;
display: flex; align-items: center; position: relative; cursor: pointer;
}
#video .vt-progress-track::before {
content: ''; position: absolute; left: 0; right: 0; top: 50%;
transform: translateY(-50%); height: 4px;
background: rgba(255,255,255,.3); border-radius: 4px;
pointer-events: none;
}
#video .vt-progress-fill {
position: absolute; left: 0; top: 50%;
transform: translateY(-50%); height: 4px;
background: linear-gradient(90deg, #FFE066, #FFD600);
border-radius: 4px; pointer-events: none;
transition: width .08s linear; width: 0%;
}
#video .vt-progress-fill::after {
content: ''; position: absolute; right: -5px; top: 50%;
width: 11px; height: 11px; background: #FFD600;
border-radius: 50%; transform: translateY(-50%);
box-shadow: 0 0 0 3px rgba(255,214,0,.25);
}
/* desc */
#video .vt-desc-body {
flex: 1; display: flex; align-items: center; justify-content: center;
text-align: center; padding: 16px 24px;
}
#video .vt-desc {
font-size: 22px; font-weight: 600; color: var(--gray-700);
letter-spacing: .5px; line-height: 1.4;
}
/* CTA */
#video .vt-cta-bar { padding: 12px 16px 32px; flex-shrink: 0; }
#video .vt-cta-btn {
width: 100%; padding: 16px 0; border: none;
background: linear-gradient(135deg, #FFE066 0%, #FFD600 50%, #FFB300 100%);
color: #1a1a1a; border-radius: 14px;
font-size: 17px; font-weight: 700; cursor: pointer;
box-shadow: 0 6px 18px rgba(255,179,0,.45),
inset 0 1px 0 rgba(255,255,255,.6);
position: relative; overflow: hidden;
letter-spacing: .5px; transition: transform .15s;
}
#video .vt-cta-btn:active { transform: scale(.98); }
#video .vt-cta-btn.disabled {
background: #E5E5E5 !important;
background-image: none !important;
color: #CCCCCC !important;
box-shadow: none !important;
cursor: not-allowed; font-weight: 600; letter-spacing: 0;
}
/* ============ Home v2026-05-10 (image-asset driven) ============ */
#home .home-scroll { padding: 40px 0 16px; }
/* 顶部 Banner —— 整图 */
#home .home-banner {
margin: 4px 12px 12px;
border-radius: 18px;
overflow: hidden;
box-shadow: 0 6px 20px rgba(255,179,0,.18);
cursor: pointer;
}
#home .home-banner img {
width: 100%;
display: block;
}
/* 5 类别快捷入口(无白底卡片,直接贴页面背景) */
#home .home-cats {
display: grid; grid-template-columns: repeat(5, 1fr);
margin: 0 12px;
padding: 12px 4px 6px;
background: transparent;
border-radius: 0;
box-shadow: none;
}
#home .home-cat {
display: flex; flex-direction: column; align-items: center;
cursor: pointer; transition: transform .12s;
padding: 0 2px;
}
#home .home-cat:active { transform: scale(.94); }
#home .home-cat img {
width: 62px; height: 62px; display: block; margin-bottom: 6px;
border-radius: 14px;
}
#home .home-cat-label {
font-size: 12px; font-weight: 600; color: #1a1a1a; letter-spacing: .2px;
}
/* 三联:左 双数据卡(HTML+CSS)+ 右 一键领优惠(橙色整卡) */
#home .home-tri {
display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
padding: 12px 12px 12px;
align-items: stretch;
}
#home .tri-stats {
display: flex; flex-direction: column; gap: 8px;
height: 100%;
}
#home .tri-stat {
position: relative;
flex: 1; min-height: 84px;
border-radius: 14px;
background: linear-gradient(135deg,#FFF3E0 0%,#FFE0B2 100%);
padding: 12px 12px;
cursor: pointer; transition: transform .12s;
box-shadow: 0 4px 14px rgba(255,140,60,.10);
overflow: hidden;
}
#home .tri-stat:active { transform: translateY(1px); }
#home .tri-stat-label {
font-size: 13px; font-weight: 700; color: #1a1a1a; letter-spacing: .2px;
line-height: 1;
}
#home .tri-stat-amount {
margin-top: 8px;
color: #FF5722; font-weight: 900;
display: inline-flex; align-items: baseline; gap: 0;
letter-spacing: -.5px; line-height: 1;
}
#home .tri-stat-amount .yuan { font-size: 18px; font-weight: 900; margin-right: 2px; }
#home .tri-stat-amount .num { font-size: 28px; line-height: 1; }
#home .tri-stat-amount .dec { font-size: 14px; font-weight: 900; margin-left: 2px; }
#home .tri-stat-art {
position: absolute; right: 6px; bottom: 4px;
width: 70px; height: 64px;
pointer-events: none;
user-select: none;
filter: drop-shadow(0 4px 6px rgba(180,80,20,.12));
}
#home .tri-stat-art img {
width: 100%; height: 100%; object-fit: contain; object-position: right bottom; display: block;
}
#home .tri-claim {
position: relative; overflow: hidden;
border-radius: 14px;
cursor: pointer; transition: transform .12s;
box-shadow: 0 8px 22px rgba(255,87,34,.22);
background: linear-gradient(140deg,#FFE066 0%,#FF5722 55%,#FF5722 100%);
padding: 12px 12px 8px;
display: flex; flex-direction: column;
color: #fff;
}
#home .tri-claim:active { transform: translateY(1px); }
#home .tri-claim-bg {
position: absolute; inset: -2px;
background-image: url('../../assets/home/index/coupon-claim-bg.png');
background-size: cover; background-position: center bottom;
background-repeat: no-repeat;
pointer-events: none;
}
#home .tri-claim-inner {
position: relative; z-index: 1;
display: flex; flex-direction: column; height: 100%;
}
#home .tri-claim-title {
font-size: 22px; font-weight: 900; color: #fff;
letter-spacing: .5px; line-height: 1;
text-shadow: 0 2px 6px rgba(180,50,0,.22);
}
#home .tri-claim-sub {
margin-top: 8px;
font-size: 12px; font-weight: 600; color: #fff;
opacity: .95; letter-spacing: .3px;
text-shadow: 0 1px 3px rgba(180,50,0,.18);
}
#home .tri-claim-spacer { flex: 1; min-height: 56px; }
#home .tri-claim-cta {
align-self: stretch;
background: #fff; color: #FF5722;
border-radius: 999px;
padding: 8px 12px;
font-size: 14px; font-weight: 600; letter-spacing: .3px;
display: inline-flex; align-items: center; justify-content: center; gap: 4px;
box-shadow: 0 4px 10px rgba(180,60,0,.18);
}
#home .tri-claim-cta .arrow { font-size: 14px; font-weight: 900; margin-left: 2px; }
/* "已领"态:领券完成后回到首页时替换 .tri-claim 默认态 */
#home .tri-claim-done {
background: linear-gradient(140deg,#FF6B3D 0%,#FF5722 55%,#E65100 100%);
padding: 12px 12px 8px;
}
#home .tri-claim-bg-done {
background-image: none;
background: radial-gradient(circle at 80% 18%, rgba(255,224,160,.45) 0%, rgba(255,160,80,0) 55%);
}
#home .tcd-head {
font-size: 12px; font-weight: 600; color: #fff;
display: inline-flex; align-items: center; gap: 4px;
opacity: .98; letter-spacing: .2px;
text-shadow: 0 1px 2px rgba(180,50,0,.18);
}
#home .tcd-check {
width: 14px; height: 14px; border-radius: 50%;
background: rgba(255,255,255,.95); color: #FF5722;
font-size: 10px; font-weight: 900; line-height: 14px;
display: inline-flex; align-items: center; justify-content: center;
}
#home .tcd-num {
margin-top: 6px;
display: inline-flex; align-items: baseline; gap: 4px;
text-shadow: 0 2px 6px rgba(180,50,0,.25);
}
#home .tcd-num .num {
font-size: 28px; font-weight: 900; color: #fff;
line-height: 1; letter-spacing: -1px;
font-family: -apple-system, "DIN Alternate", sans-serif;
}
#home .tcd-num .unit {
font-size: 12px; font-weight: 600; color: #FFF3E0;
letter-spacing: .2px;
}
#home .tcd-from {
align-self: stretch;
background: rgba(255,255,255,.18);
border-radius: 999px;
padding: 4px 8px 4px 8px;
font-size: 11px; font-weight: 600;
display: inline-flex; align-items: center; gap: 6px; justify-content: center;
color: #fff; letter-spacing: .2px;
backdrop-filter: blur(2px);
}
#home .tcd-from-label { opacity: .9; }
#home .tcd-logos { display: inline-flex; align-items: center; gap: 2px; }
#home .tcd-logos img {
width: 16px; height: 16px; border-radius: 4px;
border: 1.5px solid rgba(255,255,255,.95);
background: #fff; object-fit: cover;
box-shadow: 0 1px 3px rgba(120,40,0,.25);
}
/* 推荐信息流 */
#home .home-feed-wrap {
background: #fff;
border-radius: 14px 14px 0 0;
margin: 8px 0 0;
overflow: hidden;
padding-bottom: 0;
}
#home .home-feed-head {
display: flex; align-items: center; justify-content: space-between;
padding: 12px 16px 8px;
}
#home .home-feed-title {
font-size: 17px; font-weight: 600; color: #1a1a1a; letter-spacing: -.2px;
display: inline-flex; align-items: center; gap: 4px;
}
#home .home-feed-title .feed-fire { font-size: 18px; line-height: 1; }
#home .feed-promo-tag {
background: linear-gradient(90deg, #FF6B3D, #FF5722);
color: #fff;
font-size: 10px;
font-weight: 600;
padding: 2px 8px;
border-radius: 999px;
display: inline-flex;
align-items: center;
letter-spacing: 0;
white-space: nowrap;
box-shadow: 0 2px 5px rgba(255,90,61,.22);
}
#home .feed-promo-tag .dot {
opacity: .85;
margin: 0 2px;
}
#home .home-feed {
display: flex; flex-direction: column;
padding: 0;
background: #fff;
}
#home .feed-card {
background: transparent;
border-radius: 0;
box-shadow: none;
cursor: pointer;
display: flex; flex-direction: row; align-items: stretch;
position: relative;
padding: 8px 12px;
}
#home .feed-card:active { background: #fafafa; }
#home .feed-img {
flex: 0 0 110px; width: 110px; height: 110px; aspect-ratio: 1/1;
border-radius: 8px;
overflow: hidden;
background: #fafafa;
}
#home .feed-img img {
width: 100%; height: 100%;
object-fit: cover;
display: block;
}
#home .feed-body {
flex: 1; min-width: 0;
padding: 0 0 0 12px;
display: flex; flex-direction: column;
gap: 4px;
}
#home .feed-title {
font-size: 13px; font-weight: 500; color: #1a1a1a; line-height: 1.35;
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
overflow: hidden;
padding-right: 4px;
}
#home .feed-title .shop-name { color: #FF5722; font-weight: 600; }
#home .feed-title .title-sep { color: #CCCCCC; margin: 0 2px; font-weight: 400; }
#home .feed-meta {
display: flex; align-items: center; gap: 8px;
font-size: 11px; color: #999;
padding-right: 0;
}
#home .feed-meta .meta-left {
color: #999; font-weight: 400;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
flex: 1 1 auto; min-width: 0;
}
#home .feed-meta .meta-right {
color: #999; font-weight: 400;
white-space: nowrap; flex-shrink: 0;
}
#home .feed-pricerow {
display: flex; align-items: baseline; gap: 4px;
margin-top: auto;
padding-right: 40px;
}
#home .feed-price {
display: inline-flex; align-items: baseline; gap: 0;
color: #E53935; font-weight: 700;
}
#home .feed-price .yuan { font-size: 12px; font-weight: 700; margin-right: 2px; }
#home .feed-price .num { font-size: 18px; letter-spacing: -.5px; line-height: 1; font-weight: 700; }
#home .feed-price .num small { font-size: 12px; font-weight: 700; }
#home .feed-original {
font-size: 12px; color: #999999; text-decoration: line-through;
font-weight: 400;
}
#home .feed-subsidy {
font-size: 10px; color: #E53935; font-weight: 400;
letter-spacing: .1px;
padding-right: 40px;
}
#home .feed-grab {
position: absolute; right: 14px; bottom: 14px;
background: linear-gradient(135deg,#FFE066,#FFD600); color: #1A1A1A;
font-size: 12px; font-weight: 600;
width: 38px; height: 38px;
border-radius: 14px 14px 14px 4px;
display: flex; align-items: center; justify-content: center;
box-shadow: 0 3px 8px rgba(255,179,0,.34),
inset 0 1px 0 rgba(255,255,255,.65);
letter-spacing: 1px;
z-index: 2;
}
/* ===== R8 福利页设计规范(仅作用在 .scheme-r8 节点内) ===== */
.scheme-r8 {
--r8-yellow: #FFD600;
--r8-yellow-deep: #FFC107;
--r8-orange: #FF6A1A;
--r8-green: #21C45A;
--r8-bg: #FBFAF6;
--r8-card: #FFFFFF;
--r8-divider: #EEE8D7;
--r8-aux: #8A8A8A;
--r8-text: #1F1F1F;
background: var(--r8-bg) !important;
padding: 0 12px 16px !important;
}
.r8-status-bar {
height: 40px;
padding: 12px 8px 0;
display: flex;
align-items: flex-start;
justify-content: space-between;
color: #1A1A1A;
font-size: 14px;
font-weight: 700;
letter-spacing: 0;
}
.r8-status-icons {
display: inline-flex;
align-items: center;
gap: 6px;
height: 18px;
}
.r8-signal {
display: inline-flex;
align-items: flex-end;
gap: 2px;
height: 13px;
}
.r8-signal span {
width: 3px;
border-radius: 4px;
background: #1A1A1A;
}
.r8-signal span:nth-child(1) { height: 5px; }
.r8-signal span:nth-child(2) { height: 8px; }
.r8-signal span:nth-child(3) { height: 11px; }
.r8-signal span:nth-child(4) { height: 13px; }
.r8-wifi {
position: relative;
width: 16px;
height: 12px;
}
.r8-wifi::before,
.r8-wifi::after {
content: "";
position: absolute;
left: 50%;
border: 2px solid #1A1A1A;
border-left-color: transparent;
border-right-color: transparent;
border-bottom: none;
transform: translateX(-50%);
}
.r8-wifi::before {
top: 0;
width: 16px;
height: 9px;
border-radius: 14px 14px 0 0;
}
.r8-wifi::after {
top: 5px;
width: 9px;
height: 5px;
border-radius: 8px 8px 0 0;
}
.r8-wifi span {
position: absolute;
left: 50%;
bottom: 0;
width: 3px;
height: 3px;
transform: translateX(-50%);
border-radius: 50%;
background: #1A1A1A;
}
.r8-battery {
position: relative;
width: 24px;
height: 12px;
border: 1.8px solid #1A1A1A;
border-radius: 4px;
}
.r8-battery::before {
content: "";
position: absolute;
right: -4px;
top: 3px;
width: 2px;
height: 5px;
border-radius: 0 4px 4px 0;
background: #1A1A1A;
}
.r8-battery::after {
content: "";
position: absolute;
left: 2px;
top: 2px;
width: 17px;
height: 6px;
border-radius: 4px;
background: #1A1A1A;
}
.r8-page-header {
height: 50px;
padding: 4px 0 8px;
display: flex;
align-items: center;
justify-content: space-between;
}
.r8-page-title {
display: flex;
align-items: baseline;
gap: 8px;
flex: 1;
min-width: 0;
}
.r8-page-title strong {
font-size: 24px;
line-height: 1;
font-weight: 900;
color: #1A1A1A;
letter-spacing: 0;
flex-shrink: 0;
white-space: nowrap;
}
.r8-page-title .sub {
font-size: 11px;
line-height: 1;
color: #666666;
font-weight: 500;
white-space: nowrap;
flex-shrink: 0;
}
.r8-page-title .star {
color: var(--r8-yellow);
font-size: 12px;
font-weight: 900;
transform: translateY(-10px);
flex-shrink: 0;
}
.r8-reward-btn {
height: 32px;
padding: 0 8px 0 8px;
border: none;
border-radius: 18px;
background: rgba(255,255,255,.92);
color: #1A1A1A;
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 12px;
font-weight: 700;
box-shadow: 0 5px 14px rgba(173,128,18,.12);
cursor: pointer;
white-space: nowrap;
margin-left: 8px;
}
.r8-reward-btn svg {
width: 18px;
height: 18px;
flex-shrink: 0;
}
.r8-asset-card {
position: relative;
border-radius: 18px;
background: radial-gradient(ellipse 125% 86% at 4% 8%, rgba(255,255,255,.98) 0%, rgba(255,255,255,.56) 38%, rgba(255,255,255,0) 68%),
linear-gradient(155deg, #FFF5BF 0%, #FFE982 46%, #FFF9E4 100%);
min-height: 132px;
padding: 12px 16px 8px;
overflow: hidden;
border: 1px solid rgba(255,255,255,.78);
box-shadow: 0 8px 22px rgba(185,137,18,.10), inset 0 1px 0 rgba(255,255,255,.9);
}
.r8-asset-illustration {
position: absolute;
right: 6px; bottom: 17px;
width: 96px;
z-index: 2;
pointer-events: none; user-select: none;
}
.r8-corner-cut {
position: absolute; right: 0; top: 0;
width: 148px; height: 70px;
z-index: 1; pointer-events: none;
}
.r8-stars {
position: absolute; right: 98px; top: 42px;
width: 106px; height: 50px;
z-index: 1; pointer-events: none;
}
.r8-asset-header {
display: flex; align-items: baseline; gap: 8px;
position: relative; z-index: 3;
}
.r8-asset-title {
font-size: 18px; font-weight: 900; color: var(--r8-text);
letter-spacing: 0;
line-height: 1.08;
}
.r8-asset-withdraw {
font-size: 12px; color: #8B6914;
font-weight: 800; cursor: pointer;
}
.r8-asset-grid {
display: flex; align-items: flex-start; gap: 8px; margin-top: 16px;
position: relative; z-index: 3;
}
.r8-asset-col {
display: flex; flex-direction: column; gap: 6px;
flex: 0 1 auto; cursor: pointer;
}
.r8-asset-col:first-child {
width: 110px;
}
.r8-asset-col + .r8-asset-col {
min-width: 94px;
padding-left: 6px;
border-left: none;
}
.r8-asset-label-row {
display: flex; align-items: center; gap: 4px;
white-space: nowrap;
transform: translateX(-1px);
}
.r8-asset-coin-icon, .r8-asset-cash-icon-svg {
width: 17px; height: 17px; flex-shrink: 0; object-fit: contain;
margin-left: -3px;
}
.r8-asset-coin-label, .r8-asset-cash-label {
font-size: 13px; color: var(--r8-text); font-weight: 800;
display: inline-flex; align-items: center; gap: 2px;
}
.r8-asset-arrow {
font-size: 11px; color: #999999; font-weight: 600;
margin-left: 2px;
}
.r8-asset-coin-val, .r8-asset-cash-val {
font-size: 22px; font-weight: 800; color: #1A1A1A;
line-height: 1; letter-spacing: -.2px;
white-space: nowrap;
}
.r8-asset-coin-val, .r8-asset-cash-val {
color: var(--r8-orange);
}
.r8-asset-cash-val .unit {
font-size: 11px; font-weight: 800; margin-left: 2px;
}
.r8-asset-tip {
font-size: 10px; color: #999999;
margin-top: 12px;
position: relative; z-index: 3;
display: flex; align-items: center; gap: 4px;
line-height: 1.25;
white-space: nowrap;
}
.r8-info-icon {
width: 12px; height: 12px; border-radius: 50%;
background: rgba(138,138,138,.25); color: var(--r8-aux);
display: inline-flex; align-items: center; justify-content: center;
font-size: 10px; font-weight: 700; font-style: italic;
flex-shrink: 0;
}
.r8-checkin-card {
margin-top: 12px;
min-height: 58px;
background: linear-gradient(90deg, #FFE0B2 0%, #FFE066 100%);
border-radius: 18px;
padding: 6px 12px 6px 16px;
display: flex; align-items: center; gap: 8px;
box-shadow: 0 8px 18px rgba(185,137,18,.08);
cursor: pointer;
}
.r8-checkin-calendar {
width: 44px; height: 44px;
flex-shrink: 0; object-fit: contain;
}
.r8-checkin-text { flex: 1; min-width: 0; }
.r8-checkin-headline {
font-size: 16px; font-weight: 900; color: var(--r8-text);
display: flex; align-items: baseline; gap: 2px;
white-space: nowrap;
line-height: 1.08;
}
.r8-checkin-headline .num {
font-size: 22px; font-weight: 900; color: #FF5722;
margin: 0 4px;
}
.r8-checkin-sub {
font-size: 11px; color: #999999;
margin-top: 2px;
font-weight: 600;
white-space: nowrap;
display: none;
}
.r8-checkin-cta {
height: 32px;
background: #FFFFFF; border-radius: 32px;
padding: 0 12px 0 8px;
font-size: 12px; font-weight: 800; color: var(--r8-text);
border: none; cursor: pointer;
display: inline-flex; align-items: center; gap: 4px;
flex-shrink: 0; white-space: nowrap;
box-shadow: 0 4px 12px rgba(185,137,18,.08);
}
.r8-checkin-cta .check-tick {
display: inline-flex; align-items: center; justify-content: center;
width: 16px; height: 16px; border-radius: 4px;
background: var(--r8-green); color: #fff;
font-size: 11px; font-weight: 900;
}
.r8-section-title {
font-size: 17px; font-weight: 800; color: var(--r8-text);
margin: 0 0 8px;
}
.r8-task-card {
background: var(--r8-card);
border-radius: 14px;
padding: 12px 16px 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.04);
margin-top: 16px;
}
.r8-task-row {
display: flex; align-items: center; padding: 0;
border-bottom: none;
margin-top: 12px;
}
.r8-task-row:first-of-type { margin-top: 0; }
.r8-task-icon {
display: none;
}
.r8-task-info { flex: 1; min-width: 0; }
.r8-task-titlerow {
display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.r8-task-title {
font-size: 15px; font-weight: 800; color: var(--r8-text);
}
.r8-task-coin {
display: inline-flex; align-items: center; gap: 0;
font-size: 12px; font-weight: 700; color: var(--r8-orange);
}
.r8-task-coin .ci {
width: 18px; height: 18px; flex-shrink: 0;
margin-right: -2px;
transform: scale(1.12);
transform-origin: center;
}
.r8-task-sub {
font-size: 12px; color: var(--r8-aux); margin-top: 2px; font-weight: 500;
}
.r8-task-cta {
background: var(--r8-yellow); color: var(--r8-text);
border: none; border-radius: 32px;
padding: 6px 12px;
font-size: 12px; font-weight: 800;
cursor: pointer; flex-shrink: 0;
}
.r8-checkin-task-row {
display: block;
margin-top: 8px;
padding: 2px 0 16px;
border-bottom: 1px solid #F0F0F0;
cursor: pointer;
transition: margin .18s ease;
}
.r8-checkin-task-main {
min-width: 0;
}
.r8-checkin-task-head {
display: flex;
align-items: flex-start;
gap: 8px;
}
.r8-checkin-task-copy {
flex: 1;
min-width: 0;
}
.r8-checkin-task-title {
color: var(--r8-text);
font-size: 15px;
line-height: 1.18;
font-weight: 800;
white-space: nowrap;
}
.r8-checkin-task-sub {
margin-top: 2px;
color: var(--r8-aux);
font-size: 12px;
line-height: 1.25;
font-weight: 500;
white-space: nowrap;
}
.r8-checkin-task-cta {
flex: 0 0 auto;
min-width: 54px;
height: auto;
border: none;
border-radius: 999px;
background: var(--r8-yellow);
color: var(--r8-text);
font-family: inherit;
padding: 6px 12px;
font-size: 12px;
font-weight: 800;
box-shadow: none;
cursor: pointer;
}
.r8-checkin-timeline {
position: relative;
display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr));
column-gap: 2px;
margin-top: 16px;
}
.r8-checkin-timeline::before {
content: '';
position: absolute;
left: 20px;
right: 20px;
top: 32px;
height: 2px;
border-radius: 32px;
background: #E5E5E5;
}
.r8-checkin-step {
position: relative;
z-index: 1;
min-width: 0;
display: grid;
grid-template-rows: 18px 22px 15px;
justify-items: center;
align-items: center;
row-gap: 2px;
}
.r8-checkin-step-label {
min-height: 18px;
color: #999999;
font-size: 11px;
line-height: 18px;
font-weight: 650;
white-space: nowrap;
}
.r8-checkin-step-badge {
padding: 0 8px;
border-radius: 999px;
background: #fff;
color: #FFA000;
font-size: 11px;
line-height: 18px;
font-weight: 900;
box-shadow: 0 2px 8px rgba(0,0,0,.08);
white-space: nowrap;
}
.r8-checkin-step-icon {
box-sizing: border-box;
width: 22px;
height: 22px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.r8-checkin-step-icon img {
display: block;
width: 22px;
height: 22px;
object-fit: contain;
}
.r8-checkin-step.done .r8-checkin-step-icon {
background: #FFF3E0;
border: 1px solid #FFE066;
box-shadow: inset 0 1px 0 rgba(255,255,255,.72);
}
.r8-checkin-step.done .r8-checkin-step-icon img {
display: none;
}
.r8-checkin-step.done .r8-checkin-step-icon::before {
content: '✓';
color: #FFA000;
font-size: 13px;
line-height: 1;
font-weight: 900;
}
.r8-checkin-step.just-done .r8-checkin-step-icon {
animation: r8CheckDonePop .38s cubic-bezier(.22, 1.4, .36, 1);
}
.r8-checkin-step.current .r8-checkin-step-icon {
animation: r8CheckCoinPulse .42s ease-out;
}
@keyframes r8CheckDonePop {
0% { transform: scale(.68); opacity: .55; }
64% { transform: scale(1.12); opacity: 1; }
100% { transform: scale(1); opacity: 1; }
}
@keyframes r8CheckCoinPulse {
0% { transform: scale(.86); }
64% { transform: scale(1.1); }
100% { transform: scale(1); }
}
.r8-checkin-step.most .r8-checkin-step-icon img {
width: 22px;
height: 22px;
}
.r8-checkin-step-amount {
color: #999999;
font-size: 11px;
line-height: 1;
font-weight: 650;
font-variant-numeric: tabular-nums;
white-space: nowrap;
}
.r8-badge-update {
background: rgba(255,106,26,0.10); color: var(--r8-orange);
border: 1px solid rgba(255,106,26,0.35);
font-size: 10px; padding: 2px 4px; border-radius: 4px; font-weight: 700;
}
.r8-rule-entry {
margin: 16px auto 8px;
border: none;
background: transparent;
color: #999999;
font-family: inherit;
font-size: 12px;
font-weight: 500;
line-height: 18px;
display: flex;
align-items: center;
justify-content: center;
gap: 2px;
cursor: pointer;
}
.r8-rule-entry span {
font-size: 13px;
transform: translateY(-.5px);
}
.welfare-rules-screen {
background: #FAFAFA !important;
color: #1A1A1A;
}
.welfare-rules-body {
flex: 1;
overflow-y: auto;
padding: 12px 16px 24px;
}
.welfare-rules-card {
background: #fff;
border-radius: 14px;
padding: 16px 16px 16px;
box-shadow: 0 4px 14px rgba(0,0,0,.04);
}
.welfare-rules-title {
font-size: 18px;
font-weight: 600;
color: #1A1A1A;
margin-bottom: 12px;
}
.welfare-rules-list {
display: grid;
gap: 12px;
}
.welfare-rules-item {
display: grid;
grid-template-columns: 20px 1fr;
gap: 8px;
align-items: start;
}
.welfare-rules-index {
width: 20px;
height: 20px;
border-radius: 50%;
background: #FFF3C4;
color: #8B6914;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 11px;
font-weight: 600;
}
.welfare-rules-text {
font-size: 13px;
line-height: 20px;
font-weight: 400;
color: #666666;
}
.welfare-rules-text strong {
display: block;
margin-bottom: 2px;
font-size: 14px;
line-height: 20px;
font-weight: 700;
color: #1A1A1A;
}
.r8-record-task-block {
margin-top: 12px;
}
.r8-record-task-row {
margin-top: 0;
}
.r8-record-rewards {
position: relative;
margin-top: 8px;
display: grid;
grid-template-columns: repeat(6, minmax(0, 1fr));
gap: 2px;
}
.r8-record-milestone {
position: relative;
z-index: 1;
min-width: 0;
display: flex;
flex-direction: column;
align-items: center;
}
.r8-record-reward-box {
-webkit-appearance: none;
appearance: none;
width: 42px;
height: 50px;
border-radius: 8px;
background: #F0F0F0;
border: none;
font-family: inherit;
box-shadow: inset 0 1px 0 rgba(255,255,255,.75);
display: grid;
grid-template-rows: 10px 18px 13px;
align-content: center;
justify-items: center;
row-gap: 2px;
padding: 2px 2px;
position: relative;
transition: transform .12s ease, box-shadow .12s ease, background .12s ease;
}
button.r8-record-reward-box {
cursor: pointer;
-webkit-tap-highlight-color: transparent;
}
button.r8-record-reward-box:active {
transform: translateY(1px);
}
button.r8-record-reward-box:focus-visible {
outline: 2px solid rgba(255, 184, 0, .5);
outline-offset: 2px;
}
button.r8-record-reward-box.done,
button.r8-record-reward-box:disabled {
cursor: default;
pointer-events: none;
}
.r8-record-reward-box.done {
background: #FAFAFA;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
row-gap: 2px;
}
.r8-record-reward-box.active {
background: #FFF3E0;
box-shadow: inset 0 0 0 1px #FFD979;
}
.r8-record-status {
position: static;
text-align: center;
font-size: 10px;
line-height: 1;
font-weight: 800;
color: var(--r8-orange);
white-space: nowrap;
}
.r8-record-reward-box.done .r8-record-status {
font-size: 10px;
color: #999999;
}
.r8-record-reward-box.active .r8-record-status {
color: #FFA000;
}
.r8-record-reward-box.locked .r8-record-status {
color: #999999;
}
.r8-record-coin {
width: 18px;
height: 18px;
object-fit: contain;
flex-shrink: 0;
transform: scale(1.12);
transform-origin: center;
}
.r8-record-num {
font-size: 12px;
line-height: 1;
font-weight: 800;
color: var(--r8-orange);
letter-spacing: 0;
white-space: nowrap;
}
.r8-record-reward-box.done .r8-record-num {
font-size: 10px;
color: #999999;
font-weight: 750;
}
.r8-record-reward-box.active .r8-record-num {
font-size: 13px;
color: var(--r8-orange);
}
.r8-record-label {
margin-top: 4px;
font-size: 10px;
line-height: 1;
font-weight: 750;
color: #666666;
white-space: nowrap;
}
.r8-task-cta.is-done {
background: #F0F0F0;
color: #999999;
cursor: default;
}
@keyframes rewardToastIn {
0% { opacity: 0; transform: translate(-50%, -48%) scale(.86); }
68% { opacity: 1; transform: translate(-50%, -50%) scale(1.04); }
100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes rewardToastOut {
from { opacity: 1; transform: translate(-50%, -50%) scale(1); }
to { opacity: 0; transform: translate(-50%, -54%) scale(.96); }
}
.reward-toast {
position: absolute;
left: 50%;
top: 48%;
width: 176px;
min-height: 164px;
border-radius: 18px;
background: rgba(56, 56, 68, .98);
box-shadow: 0 18px 42px rgba(0,0,0,.24);
z-index: 10020;
pointer-events: none;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 16px 12px 16px;
color: #FFFFFF;
text-align: center;
animation: rewardToastIn .26s cubic-bezier(.18, .9, .25, 1.15) both;
}
.reward-toast.is-leaving {
animation: rewardToastOut .22s ease both;
}
.reward-toast-icon {
width: 72px;
height: 54px;
object-fit: contain;
display: block;
margin-bottom: 8px;
filter: drop-shadow(0 7px 10px rgba(255, 169, 27, .18));
}
.reward-toast-amount {
font-size: 28px;
line-height: 1;
font-weight: 900;
letter-spacing: 0;
color: #FFFFFF;
}
.reward-toast-title {
margin-top: 16px;
font-size: 20px;
line-height: 1;
font-weight: 700;
color: rgba(255,255,255,.9);
white-space: nowrap;
}
/* ===== 收益明细 / 提现 ===== */
.income-nav {
display: flex;
align-items: center;
justify-content: space-between;
padding: 40px 16px 16px;
background: #fff;
flex-shrink: 0;
}
.income-nav-title {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 18px;
font-weight: 500;
color: var(--gray-900);
letter-spacing: 0;
}
.income-nav-back,
.income-nav-link {
position: relative;
z-index: 1;
border: none;
background: none;
cursor: pointer;
font-family: inherit;
}
.income-nav-back {
width: 44px;
min-width: 44px;
height: 32px;
display: inline-flex;
align-items: center;
justify-content: flex-start;
padding: 0;
text-align: left;
font-size: 24px;
line-height: 1;
font-weight: 400;
color: var(--gray-800);
}
.income-nav-link {
min-width: 72px;
text-align: right;
font-size: 14px;
font-weight: 400;
color: var(--gray-500);
}
.income-rate {
padding: 0 16px 8px;
font-size: 12px;
line-height: 18px;
font-weight: 400;
color: var(--gray-500);
flex-shrink: 0;
}
.income-summary-card {
margin: 0 16px 16px;
padding: 24px 16px;
border-radius: 18px;
background: linear-gradient(135deg, #FFF3E0 0%, #FFFDE7 100%);
flex-shrink: 0;
}
.income-summary-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
.income-summary-label {
font-size: 13px;
font-weight: 400;
color: var(--gray-600);
margin-bottom: 6px;
}
.income-summary-value {
font-size: 28px;
line-height: 1;
font-weight: 700;
color: #FF5722;
letter-spacing: .2px;
}
.income-chip-btn {
margin-top: 8px;
height: 28px;
padding: 0 12px;
border-radius: 999px;
border: 1.5px solid #FF5722;
background: transparent;
color: #FF5722;
font-size: 13px;
font-weight: 500;
cursor: pointer;
font-family: inherit;
}
.income-chip-btn.filled {
background: #FF5722;
color: #fff;
}
.income-tabs {
position: relative;
display: flex;
padding: 0 16px;
border-bottom: 2px solid var(--gray-200);
flex-shrink: 0;
}
.income-tab {
flex: 1;
border: none;
background: none;
padding: 16px 0 12px;
text-align: center;
font-family: inherit;
font-size: 15px;
font-weight: 400;
color: var(--gray-500);
cursor: pointer;
}
.income-tab.active {
color: #000;
font-weight: 400;
}
.income-tab-indicator {
position: absolute;
left: 16px;
bottom: -2px;
width: calc((100% - 32px) / 2);
height: 2px;
background: #1a1a1a;
transition: transform .24s ease;
}
.income-tabs[data-active="cash"] .income-tab-indicator {
transform: translateX(100%);
}
.income-record-shell {
flex: 1;
overflow: hidden;
background: #fff;
touch-action: pan-y;
user-select: none;
-webkit-user-select: none;
}
.income-record-track {
height: 100%;
display: flex;
width: 200%;
transition: transform .24s ease;
}
.income-record-track.cash-active {
transform: translateX(-50%);
}
.income-record-panel {
width: 50%;
min-width: 50%;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
padding: 0 16px 16px;
}
.income-record-row {
min-height: 72px;
display: flex;
align-items: center;
border-bottom: .5px solid var(--gray-100);
}
.income-record-main {
flex: 1;
min-width: 0;
}
.income-record-title {
font-size: 15px;
font-weight: 400;
color: #1A1A1A;
line-height: 1.3;
}
.income-record-date {
margin-top: 4px;
font-size: 13px;
font-weight: 400;
color: var(--gray-400);
}
.income-record-amount {
margin-left: 8px;
font-size: 16px;
font-weight: 400;
color: #FF5722;
white-space: nowrap;
}
.income-record-amount.cash {
color: #FE2C55;
}
.income-footer {
padding: 12px 16px 24px;
border-top: .5px solid var(--gray-200);
text-align: center;
flex-shrink: 0;
background: #fff;
}
.income-footer-note {
margin-bottom: 8px;
font-size: 14px;
font-weight: 400;
color: var(--gray-500);
}
.income-footer-note strong {
color: #FF5722;
font-weight: 500;
}
.income-footer .btn {
font-weight: 400;
}
.withdraw-screen {
background: #fff !important;
color: var(--gray-900);
}
#withdrawal .income-nav-title {
font-size: 16px;
font-weight: 500;
}
#withdrawal .income-nav {
background: transparent;
}
#withdrawal .income-nav-back {
font-size: 22px;
font-weight: 400;
}
.withdraw-nav-links {
min-width: 104px;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 6px;
font-size: 12px;
font-weight: 400;
color: var(--gray-700);
}
.withdraw-nav-links button {
border: none;
background: none;
padding: 0;
font: inherit;
color: inherit;
cursor: pointer;
}
.withdraw-nav-sep {
width: 1px;
height: 12px;
background: var(--gray-300);
}
.withdraw-top {
flex-shrink: 0;
background: linear-gradient(126deg, #FFF3C4 0%, #FFFFFF 52%, #E8F5E9 100%);
border-bottom: .5px solid rgba(0,0,0,.04);
}
.withdraw-notice {
min-height: 40px;
display: flex;
align-items: center;
gap: 6px;
padding: 0 16px;
border-top: .5px solid rgba(0,0,0,.04);
border-bottom: .5px solid rgba(0,0,0,.05);
background: rgba(255,255,255,.50);
color: var(--gray-700);
font-size: 11px;
font-weight: 400;
}
.withdraw-notice-icon {
width: 14px;
height: 14px;
border-radius: 50%;
border: 1.3px solid currentColor;
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
font-size: 10px;
line-height: 1;
}
.withdraw-notice-text {
flex: 1;
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.withdraw-notice-close {
border: none;
background: none;
color: var(--gray-700);
font-size: 18px;
font-weight: 400;
line-height: 1;
cursor: pointer;
}
.withdraw-content {
flex: 1;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
padding: 24px 16px 24px;
background: #fff;
}
.withdraw-balance-card {
display: block;
text-align: center;
padding: 12px 0 32px;
margin-bottom: 0;
}
.withdraw-balance-amount {
font-size: 48px;
line-height: 1;
font-weight: 800;
color: #FFA000;
letter-spacing: 0;
}
.withdraw-balance-amount span {
font-size: 14px;
font-weight: 400;
margin-left: 4px;
}
.withdraw-balance-sub {
display: none;
}
.withdraw-method {
margin-bottom: 24px;
}
.withdraw-method-head {
display: flex;
align-items: center;
gap: 8px;
min-height: 26px;
margin-bottom: 12px;
}
.withdraw-method-title {
flex: 1;
font-size: 15px;
font-weight: 600;
color: var(--gray-900);
}
.withdraw-wechat-logo {
width: 22px;
height: 22px;
border-radius: 50%;
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
background: #22C55E;
}
.withdraw-wechat-logo svg {
width: 16px;
height: 16px;
display: block;
}
.withdraw-amount-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
}
.withdraw-amount {
min-height: 66px;
border: 1px solid #F0F0F0;
border-radius: 12px;
background: #FAFAFA;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
cursor: pointer;
font-family: inherit;
font-size: 18px;
font-weight: 700;
color: #1A1A1A;
box-shadow: 0 5px 14px rgba(0,0,0,.032);
}
.withdraw-amount small {
font-size: 12px;
font-weight: 400;
margin-left: 2px;
}
.withdraw-amount.active {
border-color: #FFD600;
background: #FFFDE7;
color: #1A1A1A;
box-shadow: inset 0 0 0 1px #FFD600, 0 7px 16px rgba(255,214,0,.13);
}
.wechat-bind-layer {
display: none;
position: absolute;
inset: 0;
z-index: 285;
overflow: hidden;
}
.wechat-bind-layer.open {
display: block;
}
.wechat-bind-mask {
position: absolute;
inset: 0;
background: rgba(0,0,0,.56);
}
.wechat-bind-sheet {
position: absolute;
left: 0;
right: 0;
bottom: 0;
min-height: 520px;
border-radius: 24px 24px 0 0;
background: #FAFAFA;
padding: 24px 16px 24px;
animation: exchangeSheetUp .24s ease-out;
}
.wechat-bind-close {
width: 38px;
height: 38px;
border-radius: 18px;
border: none;
background: #F0F0F0;
display: inline-flex;
align-items: center;
justify-content: center;
color: #1A1A1A;
font-size: 28px;
font-weight: 400;
line-height: 1;
cursor: pointer;
font-family: inherit;
}
.wechat-bind-amount-label {
margin-top: 4px;
text-align: center;
font-size: 17px;
font-weight: 400;
color: var(--gray-600);
}
.wechat-bind-amount {
margin-top: 8px;
text-align: center;
font-size: 48px;
line-height: 1;
font-weight: 700;
color: #1A1A1A;
}
.wechat-bind-amount small {
font-size: 18px;
font-weight: 400;
margin-left: 4px;
}
.wechat-bind-card {
margin-top: 64px;
min-height: 92px;
border-radius: 14px;
background: #fff;
display: flex;
align-items: center;
gap: 12px;
padding: 0 16px;
box-shadow: 0 6px 20px rgba(0,0,0,.03);
}
.wechat-bind-card-logo {
width: 34px;
height: 34px;
border-radius: 18px;
background: #22C55E;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.wechat-bind-card-logo svg {
width: 24px;
height: 24px;
}
.wechat-bind-card-title {
font-size: 17px;
font-weight: 600;
color: #1A1A1A;
}
.wechat-bind-card-sub {
margin-top: 6px;
font-size: 14px;
font-weight: 400;
color: var(--gray-500);
}
.wechat-bind-cta {
position: absolute;
left: 20px;
right: 20px;
bottom: 28px;
height: 56px;
border: none;
border-radius: 14px;
background: linear-gradient(90deg, #FFE066 0%, #FFD600 52%, #FFE066 100%);
color: #1A1A1A;
font-family: inherit;
font-size: 17px;
font-weight: 600;
cursor: pointer;
}
.exchange-layer {
display: none;
position: absolute;
inset: 0;
z-index: 280;
overflow: hidden;
}
.exchange-layer.open {
display: block;
}
.exchange-mask {
position: absolute;
inset: 0;
background: rgba(0,0,0,.72);
}
.exchange-sheet {
position: absolute;
left: 0;
right: 0;
bottom: 0;
background: #fff;
border-radius: 24px 24px 0 0;
padding: 24px 16px 24px;
animation: exchangeSheetUp .24s ease-out;
}
@keyframes exchangeSheetUp {
from { transform: translateY(100%); }
to { transform: translateY(0); }
}
.exchange-close {
position: absolute;
top: 18px;
right: 18px;
width: 38px;
height: 38px;
border-radius: 18px;
border: none;
background: #F0F0F0;
color: #1A1A1A;
font-size: 24px;
line-height: 1;
cursor: pointer;
font-family: inherit;
}
.exchange-title {
font-size: 20px;
font-weight: 900;
color: #1A1A1A;
margin-bottom: 8px;
}
.exchange-balance {
font-size: 15px;
font-weight: 600;
color: var(--gray-500);
margin-bottom: 24px;
}
.exchange-balance strong {
color: var(--gray-700);
font-weight: 800;
}
.exchange-convert-card {
height: 64px;
border-radius: 8px;
background: #FAFAFA;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 16px 0 16px;
margin-bottom: 24px;
}
.exchange-coin-side {
display: flex;
align-items: center;
gap: 8px;
}
.exchange-coin-icon {
width: 30px;
height: 30px;
border-radius: 14px;
background: radial-gradient(circle at 35% 30%, #FFE0B2, #FFB300);
display: flex;
align-items: center;
justify-content: center;
color: #8B6914;
font-weight: 900;
font-size: 16px;
}
.exchange-coin-num {
font-size: 24px;
font-weight: 900;
color: #000;
}
.exchange-cash-num {
font-size: 28px;
font-weight: 900;
color: #FE2C55;
}
.exchange-cash-num small {
font-size: 17px;
margin-left: 2px;
}
.exchange-presets {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
margin-bottom: 12px;
}
.exchange-preset {
height: 48px;
border-radius: 8px;
border: 1px solid #F0F0F0;
background: #fff;
color: var(--gray-400);
font-family: inherit;
font-size: 16px;
font-weight: 700;
cursor: pointer;
}
.exchange-preset.active {
border-color: #FF6B6B;
color: #FE2C55;
background: #FAFAFA;
}
.exchange-error {
min-height: 22px;
color: #FE2C55;
font-size: 14px;
font-weight: 700;
margin-bottom: 24px;
}
.exchange-rule {
text-align: center;
font-size: 15px;
font-weight: 600;
color: var(--gray-500);
margin-bottom: 24px;
}
.exchange-submit {
width: 100%;
height: 56px;
border: none;
border-radius: 8px;
background: #FE2C55;
color: #fff;
font-family: inherit;
font-size: 18px;
font-weight: 700;
cursor: pointer;
}
/* === 标准返回按钮 (统一 design.md - icons.back-chevron) === */
.btn-back {
width: 44px; height: 44px;
display: flex; align-items: center; justify-content: center;
background: transparent; border: none; padding: 0;
cursor: pointer; -webkit-tap-highlight-color: transparent;
flex-shrink: 0;
}
.btn-back:active { opacity: 0.5; }
.btn-back svg { width: 24px; height: 24px; display: block; }
</style>
<style>
/* === 跳转动画(原 shared/transitions.css 内嵌) === */
/* tokens.css 是空文件已废弃,未内嵌;token 由各 HTML 的 :root 单独定义 */
/**
* 7 种跳转动画
* 用法:JS 给 body 加 .transitioning-{词} class,触发对应动画
*/
/* push: 右进左出(进入下一层级) */
@keyframes nav-push-out {
from { transform: translateX(0); opacity: 1; }
to { transform: translateX(-30%); opacity: 0.6; }
}
body.transitioning-push { animation: nav-push-out 280ms ease-in forwards; }
/* pop: 左进右出(返回) */
@keyframes nav-pop-out {
from { transform: translateX(0); opacity: 1; }
to { transform: translateX(100%); opacity: 0.8; }
}
body.transitioning-pop { animation: nav-pop-out 280ms ease-in forwards; }
/* modal: 从底弹起(即将离开页面,向上让位) */
@keyframes nav-modal-out {
from { transform: translateY(0); opacity: 1; }
to { transform: translateY(-8%); opacity: 0.6; }
}
body.transitioning-modal { animation: nav-modal-out 280ms ease-in forwards; }
/* dismiss: 向下收起 */
@keyframes nav-dismiss-out {
from { transform: translateY(0); opacity: 1; }
to { transform: translateY(100%); opacity: 0.4; }
}
body.transitioning-dismiss { animation: nav-dismiss-out 280ms ease-in forwards; }
/* replace: 直接替换(淡出) */
@keyframes nav-replace-out {
from { opacity: 1; }
to { opacity: 0; }
}
body.transitioning-replace { animation: nav-replace-out 200ms ease-out forwards; }
/* fade: 淡入淡出(splash 类过渡) */
@keyframes nav-fade-out {
from { opacity: 1; }
to { opacity: 0; }
}
body.transitioning-fade { animation: nav-fade-out 400ms ease-in-out forwards; }
/* tab: 无动画(瞬切) */
body.transitioning-tab { /* no animation */ }
/* 进入动画(DOMContentLoaded 前的初始状态由 body.preanim 控制,可选) */
@keyframes nav-fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
body { /* nav-fade-in disabled — tab 切换闪烁源头 */ }
</style>
<!-- webview 改造:H5↔原生桥 + 同源后端调用层(必须在页面其他脚本之前加载) -->
<script src="../shared/bridge.js"></script>
<script src="../shared/api.js"></script>
</head>
<body data-cc-id="cc-1" style="cursor: crosshair; background-color: rgb(0, 0, 0);">
<!--
@page: profile
@path: app/profile
@source: 2026-05-18.html
TODO: 补充 @owner / @from / @to / @notes(参照 FLOW.md
-->
<!-- 方案切换控制面板 -->
<div class="variant-toggle" id="variantToggle">
<button class="variant-btn" onclick="toggleVariantPanel()" title="方案切换"></button>
<div class="variant-panel" id="variantPanel">
<h3>方案切换</h3>
<div id="variantList"><div class="variant-empty">暂无多方案模块<br><span style="font-size: 11px;">在 variants 配置中添加模块即可</span></div></div>
</div>
</div>
<div class="device" id="app">
<!-- 调试返回按钮 -->
<div id="debugBack" onclick="debugGoBack()" style="position: absolute; left: 0px; bottom: 0px; z-index: 99999; background: rgb(0, 0, 0); color: rgb(255, 255, 255); font-size: 11px; font-weight: 700; padding: 8px 8px; border-radius: 0px 4px 0px 0px; cursor: pointer; opacity: 0.7; line-height: 1; letter-spacing: 1px;" data-cc-id="cc-11">返回</div>
<!-- ===== 11. LOGIN ===== -->
<!-- screen #login removed for split -->
<!-- 入口页协议 · 底部抽屉(device 级 overlay,可跨屏触发:login / celebration 都用) -->
<div id="agreeModal" class="login-agreement-sheet-layer">
<div class="login-agreement-sheet">
<div class="login-agreement-sheet-title">用户协议及隐私保护</div>
<div class="login-agreement-sheet-copy">我已阅读并同意<span class="link">用户协议</span><span class="link">基本功能隐私政策</span></div>
<button class="login-agreement-sheet-primary" type="button" onclick="agreeAndLogin()">同意并登录</button>
<button class="login-agreement-sheet-secondary" type="button" onclick="closeAgreeModal()">不同意</button>
</div>
</div>
<!-- 通用 Toastdevice 级,跨屏可见) -->
<div id="loginToast" style="display: none;position: absolute;left: 50%;bottom: 120px;transform: translateX(-50%);background: rgba(0,0,0,.75);color: #fff;font-size: 13px;font-weight: 500;padding: 8px 16px;border-radius: 8px;white-space: nowrap;z-index: 40;"></div>
<!-- ===== 11b. LOGIN PHONE(独立手机号登录页) ===== -->
<!-- screen #loginPhone removed for split -->
<!-- ===== HOME TAB ===== -->
<!-- screen #home removed for split -->
<!-- [ECOM-ONLY] BLIND BOX screen removed for waimai V1 -->
<!-- Original: 150+ lines of blind box full-page screen with card slider -->
<!-- ===== WELFARE TAB (红果风格) ===== -->
<!-- screen #welfare removed for split -->
<!-- ===== WELFARE RULES / 活动规则 ===== -->
<!-- screen #welfareRules removed for split -->
<!-- ===== PROFILE TAB ===== -->
<style>
/* —— 我的页 (profile) —— */
#profile {
background: radial-gradient(circle at 84% 17%, rgba(255,255,255,.82) 0 36px, transparent 37px),
radial-gradient(circle at 98% 20%, rgba(255,255,255,.66) 0 42px, transparent 43px),
linear-gradient(180deg, #FFF1D9 0%, #FFF6E8 28%, #FFF8EF 48%, #F8F8F8 70%, #F7F7F7 100%);
}
.prof-statusbar { position: absolute; left: 0; right: 0; top: 0; height: 42px; z-index: 20; display: flex; align-items: center; justify-content: space-between; padding: 8px 32px 0 32px; pointer-events: none; color: #000; }
.prof-status-time { font-size: 15px; font-weight: 600; letter-spacing: .1px; line-height: 1; font-variant-numeric: tabular-nums; }
.prof-status-icons { display: flex; align-items: center; gap: 8px; }
.prof-cell { display: flex; align-items: flex-end; gap: 2px; height: 14px; }
.prof-cell i { display: block; width: 3px; border-radius: 4px; background: #000; }
.prof-cell i:nth-child(1) { height: 5px; }
.prof-cell i:nth-child(2) { height: 8px; }
.prof-cell i:nth-child(3) { height: 11px; }
.prof-cell i:nth-child(4) { height: 14px; }
.prof-wifi { position: relative; width: 17px; height: 13px; overflow: hidden; }
.prof-wifi::before, .prof-wifi::after { content: ''; position: absolute; left: 50%; border: 3px solid #000; border-color: #000 transparent transparent transparent; border-radius: 50%; transform: translateX(-50%); }
.prof-wifi::before { width: 21px; height: 21px; top: 1px; }
.prof-wifi::after { width: 11px; height: 11px; top: 6px; }
.prof-wifi i { position: absolute; left: 50%; bottom: 0; width: 5px; height: 5px; margin-left: -2.5px; border-radius: 50%; background: #000; }
.prof-battery { position: relative; width: 23px; height: 12px; border: 1.7px solid #000; border-radius: 4px; padding: 2px; }
.prof-battery::before { content: ''; position: absolute; right: -3.7px; top: 3.1px; width: 2px; height: 5px; border-radius: 0 4px 4px 0; background: #000; }
.prof-battery i { display: block; width: 100%; height: 100%; border-radius: 4px; background: #000; }
.prof-scroll { flex: 1; overflow-y: auto; overflow-x: hidden; }
.prof-hero { position: relative; padding: 64px 16px 0; min-height: 154px; overflow: visible; }
.prof-clouds { position: absolute; left: 0; right: 0; top: 0; width: 100%; height: 174px; object-fit: cover; opacity: .72; pointer-events: none; }
.prof-piggy { position: absolute; top: 36px; right: -12px; width: 160px; height: auto; pointer-events: none; z-index: 1; filter: drop-shadow(0 10px 18px rgba(255,125,50,.16)); }
.prof-hero::after { content: ''; position: absolute; right: 160px; top: 114px; width: 9px; height: 9px; background: #FFB300; transform: rotate(45deg); box-shadow: 7px 0 0 -3px rgba(255,179,0,.75), 0 7px 0 -3px rgba(255,179,0,.75); z-index: 1; }
.prof-id { position: relative; z-index: 2; display: flex; align-items: center; gap: 12px; }
.prof-avatar { width: 64px; height: 64px; border-radius: 50%; flex-shrink: 0; background: radial-gradient(circle at 42% 32%, #FFE0B2 0%, #FFE066 43%, #FFEB3B 100%); border: 3px solid #fff; box-shadow: 0 6px 16px rgba(255,137,32,.20); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.prof-avatar svg { width: 60px; height: 60px; display: block; }
.prof-meta { flex: 1; min-width: 0; min-height: 64px; display: flex; align-items: center; }
.prof-name { max-width: 9em; font-size: 17.5px; font-weight: 600; color: #000000; line-height: 1.2; letter-spacing: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; word-break: break-all; }
.prof-phone { font-size: 13px; color: rgba(0,0,0,.58); margin-top: 6px; letter-spacing: .1px; font-variant-numeric: tabular-nums; }
.prof-badge { display: inline-flex; align-items: center; gap: 4px; margin-top: 8px; padding: 4px 8px 4px 6px; background: rgba(255,255,255,.58); border: 1px solid rgba(255,255,255,.95); border-radius: 999px; font-size: 12px; line-height: 1; font-weight: 700; color: #FF5722; box-shadow: 0 2px 8px rgba(143,84,25,.08); backdrop-filter: blur(4px); }
.prof-badge svg { width: 15px; height: 15px; }
.prof-badge svg path:first-child { fill: #FFA000; }
.prof-badge svg path:last-child { stroke: #fff; }
.prof-body-inner { position: relative; z-index: 3; padding: 12px 16px 16px; }
/* —— 累计帮省卡片 —— */
.prof-savings-card { position: relative; border-radius: 24px; padding: 16px 22px 17px; background: linear-gradient(180deg, #FF6A00 0%, #FF5722 52%, #FFA000 100%); box-shadow: inset 0 1px 0 rgba(255,255,255,.30); overflow: hidden; color: #fff; border: 1px solid rgba(255,172,63,.55); }
.prof-savings-card::before { content: ''; position: absolute; inset: 0; background: radial-gradient(circle at 18% 26%, rgba(255,255,255,.10), transparent 18%), radial-gradient(circle at 75% 35%, rgba(255,255,255,.08), transparent 24%); pointer-events: none; }
.prof-savings-deco { position: absolute; left: -14px; bottom: -12px; width: 160px; height: 128px; object-fit: contain; object-position: left bottom; opacity: .30; pointer-events: none; }
.prof-savings-coin { position: absolute; top: auto; bottom: 112px; right: 18px; width: 44px; height: 44px; opacity: .82; pointer-events: none; transform: rotate(-22deg); }
.prof-savings-head { position: relative; z-index: 1; display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.prof-savings-title { display: inline-flex; align-items: center; gap: 5px; font-size: 16px; font-weight: 700; color: #fff; line-height: 1.2; }
.prof-savings-title .spark { font-size: 12px; color: #FFEB3B; }
.prof-savings-label { position: relative; z-index: 1; font-size: 15px; line-height: 1.1; font-weight: 700; color: rgba(255,255,255,.96); text-align: center; letter-spacing: .2px; }
.prof-amount-row { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; gap: 8px; height: 62px; margin: 5px 0 5px; }
.prof-amount-row::before { content: none; }
.prof-wheat { width: 46px; height: 64px; flex: 0 0 auto; opacity: .58; background-image: url('../../assets/profile/index/laurel.png'); background-repeat: no-repeat; background-size: 230px 77px; pointer-events: none; }
.prof-wheat.left { background-position: 17% center; }
.prof-wheat.right { background-position: 83% center; }
.prof-laurel { display: none; }
.prof-laurel.left { object-position: left center; }
.prof-laurel.right { object-position: right center; transform: scaleX(-1); }
.prof-amount { position: relative; z-index: 1; display: inline-flex; align-items: baseline; font-family: "DIN Alternate", "Helvetica Neue", sans-serif; font-size: 36px; font-weight: 900; color: #fff; line-height: 1; letter-spacing: -0.5px; text-shadow: 0 2px 6px rgba(160,50,0,.16); font-variant-numeric: tabular-nums; }
.prof-currency { font-size: 26px; margin-right: 4px; font-weight: 800; }
.prof-cents { font-size: 20px; font-weight: 800; margin-left: 1px; }
.prof-stats-row { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; gap: 0; margin: 4px 0 0; padding-top: 10px; border-top: 1px solid rgba(255,255,255,.35); }
.prof-stats-row > div:not(.prof-stats-div) { flex: 1; text-align: center; }
.prof-stat-num { font-family: "DIN Alternate", "Helvetica Neue", sans-serif; font-size: 18px; font-weight: 900; color: #fff; line-height: 1; font-variant-numeric: tabular-nums; }
.prof-stat-num .prof-stat-cur { font-size: 13px; font-weight: 800; margin-right: 1px; }
.prof-stat-unit { font-size: 12px; font-weight: 700; margin-left: 1px; font-family: -apple-system, "PingFang SC", sans-serif; }
.prof-stat-key { font-size: 12px; font-weight: 600; color: rgba(255,255,255,.88); margin-bottom: 4px; }
.prof-stats-div { width: 1px; height: 34px; background: rgba(255,255,255,.33); }
.prof-savings-btn { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; gap: 6px; width: 142px; height: 34px; margin: 12px auto 0; padding: 0 16px; background: #fff; border: none; border-radius: 999px; font-size: 14px; font-weight: 600; color: #FF5722; cursor: pointer; box-shadow: 0 6px 12px rgba(214,82,0,.14); }
.prof-savings-btn span { font-size: 18px; line-height: 1; margin-left: 0; display: inline-block; transform: translateY(-1px); }
/* —— 未比价锁定蒙层(不透明,盖住示例数据)—— */
.prof-lock-overlay { display: none; position: absolute; inset: 0; z-index: 6; flex-direction: column; align-items: center; justify-content: center; gap: 8px; padding: 0 24px; text-align: center; background: linear-gradient(180deg, #FF6A00 0%, #FF5722 52%, #FFA000 100%); border-radius: 24px; }
#profSavingsCard.locked .prof-lock-overlay { display: flex; }
.prof-lock-ico { width: 38px; height: 38px; border-radius: 50%; background: rgba(255,255,255,.92); display: flex; align-items: center; justify-content: center; font-size: 18px; box-shadow: 0 6px 14px rgba(0,0,0,.18); margin-bottom: 2px; }
.prof-lock-text { font-size: 14px; font-weight: 700; color: #fff; line-height: 1.35; text-shadow: 0 2px 4px rgba(160,50,0,.30); max-width: 240px; }
.prof-lock-cta { display: inline-flex; align-items: center; gap: 4px; height: 34px; padding: 0 18px; background: #fff; border: none; border-radius: 999px; font-size: 14px; font-weight: 700; color: #FF5722; cursor: pointer; box-shadow: 0 6px 14px rgba(0,0,0,.18); margin-top: 2px; }
.prof-lock-cta .arr { font-size: 16px; line-height: 1; }
/* —— 去点餐选平台弹窗(移植自首页 home-picker)—— */
.home-picker-mask { display: none; position: absolute; inset: 0; z-index: 250; background: rgba(20,12,4,.5); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); align-items: center; justify-content: center; padding: 24px; }
.home-picker-mask.show { display: flex; animation: homePickerFade .22s ease-out; }
@keyframes homePickerFade { from { opacity: 0; } to { opacity: 1; } }
.home-picker-modal { width: 100%; max-width: 304px; background: linear-gradient(180deg, #FFFAF0 0%, #FFFFFF 70%); border-radius: 24px; padding: 22px 18px 20px; box-shadow: 0 24px 60px rgba(120,80,30,.28), 0 2px 8px rgba(0,0,0,.06), inset 0 1px 0 rgba(255,255,255,.85); border: 1px solid rgba(255,220,120,.4); animation: homePickerIn .35s cubic-bezier(.22,1,.36,1); position: relative; overflow: hidden; }
.home-picker-modal::before { content: ''; position: absolute; top: -60px; left: 50%; transform: translateX(-50%); width: 220px; height: 120px; background: radial-gradient(ellipse at center, rgba(255,214,0,.25), transparent 65%); pointer-events: none; }
@keyframes homePickerIn { from { opacity: 0; transform: scale(.86) translateY(-6px); } to { opacity: 1; transform: scale(1) translateY(0); } }
.home-picker-close { position: absolute; top: 12px; right: 12px; width: 28px; height: 28px; border-radius: 14px; background: rgba(0,0,0,.06); display: flex; align-items: center; justify-content: center; font-size: 13px; color: #4D4D4D; cursor: pointer; font-weight: 700; z-index: 2; }
.home-picker-emoji { width: 38px; height: 38px; margin: 0 auto 6px; border-radius: 12px; background: linear-gradient(135deg, #FFE066 0%, #FFB300 100%); box-shadow: 0 4px 10px rgba(255,160,0,.35), inset 0 1px 0 rgba(255,255,255,.6); display: flex; align-items: center; justify-content: center; font-size: 20px; position: relative; }
.home-picker-title { font-size: 18px; font-weight: 900; color: #1a1a1a; text-align: center; letter-spacing: .3px; margin-bottom: 4px; position: relative; }
.home-picker-sub { font-size: 12px; color: #4D4D4D; text-align: center; margin-bottom: 18px; line-height: 1.5; position: relative; }
.home-picker-sub strong { color: #FF5722; font-weight: 800; }
.home-picker-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; position: relative; }
.home-picker-item { position: relative; background: linear-gradient(180deg, #FFFFFF 0%, #FFFDF5 100%); border: 1.5px solid #F2EBD8; border-radius: 14px; padding: 14px 6px 12px; text-align: center; cursor: pointer; transition: transform .15s, border-color .15s, box-shadow .15s; -webkit-tap-highlight-color: transparent; box-shadow: 0 2px 6px rgba(120,80,20,.05); }
.home-picker-item:active { transform: scale(.94); border-color: #FFD600; box-shadow: 0 4px 14px rgba(255,179,0,.25); }
.home-picker-item .home-picker-logo { width: 46px; height: 46px; border-radius: 12px; margin: 0 auto 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,.08); }
.home-picker-item .home-picker-logo img { width: 100%; height: 100%; object-fit: cover; }
.home-picker-item .home-picker-name { font-size: 12px; font-weight: 700; color: #1a1a1a; line-height: 1.2; letter-spacing: .2px; }
.home-picker-item.uninstalled { background: #FAFAFA; border-color: #ECECEC; box-shadow: none; }
.home-picker-item.uninstalled .home-picker-logo { box-shadow: 0 1px 3px rgba(0,0,0,.04); }
.home-picker-item.uninstalled .home-picker-logo img { filter: grayscale(.7); opacity: .55; }
.home-picker-item.uninstalled .home-picker-name { color: #BBB; }
.home-picker-install-chip { position: absolute; top: 6px; right: 6px; width: 18px; height: 18px; border-radius: 50%; background: #FFD600; box-shadow: 0 0 0 1.5px rgba(255,179,0,.35); display: flex; align-items: center; justify-content: center; }
/* —— 省钱战绩卡 —— */
.prof-card { background: rgba(255,255,255,.96); border-radius: 18px; padding: 12px 12px; margin-top: 12px; box-shadow: 0 6px 18px rgba(151,93,35,.08); border: 1px solid rgba(255,255,255,.82); }
.prof-achv-title { display: flex; align-items: center; gap: 6px; font-size: 16px; font-weight: 600; color: #1A1A1A; margin-bottom: 12px; letter-spacing: 0; }
.prof-achv-title .prof-trophy { width: 23px; height: 23px; display: inline-flex; align-items: center; justify-content: center; background: transparent; border-radius: 0; font-size: 20px; filter: drop-shadow(0 3px 5px rgba(255,133,0,.22)); }
.prof-achv-title .prof-spark { color: #FFEB3B; font-size: 14px; margin-left: 2px; }
.prof-achv-row { display: flex; align-items: stretch; gap: 0; }
.prof-achv-item { position: relative; flex: 1; display: flex; align-items: flex-start; justify-content: center; gap: 0; min-width: 0; padding: 0 8px; text-align: center; }
.prof-achv-item > div { display: grid; grid-template-rows: 17px 23px 14px; justify-items: center; align-items: center; }
.prof-achv-item::after { content: ''; position: absolute; right: 0; top: 3px; bottom: 3px; width: 1px; background: #F0F0F0; }
.prof-achv-item:last-child::after { display: none; }
.prof-achv-ico { width: 34px; height: 34px; border-radius: 18px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
.prof-achv-ico.ico-orange { background: linear-gradient(180deg,#FFF3C4 0%,#FFE066 100%); }
.prof-achv-ico.ico-green { background: linear-gradient(180deg,#E8F5E9 0%,#CCCCCC 100%); }
.prof-achv-ico.ico-blue { background: linear-gradient(180deg,#E3F2FD 0%,#DDDDDD 100%); }
.prof-achv-ico svg { width: 19px; height: 19px; }
.prof-achv-item .prof-achv-key { font-size: 12px; color: #1A1A1A; font-weight: 500; line-height: 1.15; white-space: nowrap; }
.prof-achv-item .prof-achv-val { font-size: 18px; font-weight: 900; color: #FF5722; line-height: 1; margin-top: 0; font-variant-numeric: tabular-nums; }
.prof-achv-item .prof-achv-val span { font-size: 12px; font-weight: 500; color: #1A1A1A; margin-left: 2px; }
/* —— 菜单卡 —— */
.prof-menu-card { padding: 8px 12px; }
.prof-menu-item { display: flex; align-items: center; gap: 12px; padding: 6px 0; cursor: pointer; border-bottom: .5px solid #F0F0F0; }
.prof-menu-item:last-child { border-bottom: none; }
.prof-menu-ico { width: 34px; height: 34px; flex-shrink: 0; filter: drop-shadow(0 4px 6px rgba(49,99,180,.10)); }
.prof-report-ico { transform: scale(0.79); transform-origin: center center; }
.prof-menu-text { flex: 1; min-width: 0; }
.prof-menu-title { font-size: 14px; font-weight: 600; color: #1A1A1A; line-height: 1.2; }
.prof-report-title { position: relative; display: inline-flex; align-items: center; overflow: visible; }
.prof-report-badge { position: absolute; top: -7px; right: -34px; height: 14px; padding: 0 4px; background: #FF3D00; color: #fff; font-size: 8px; font-weight: 700; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; line-height: 1; white-space: nowrap; box-shadow: 0 1px 3px rgba(255,61,0,.25); }
.prof-menu-sub { font-size: 12px; color: #666666; margin-top: 2px; }
.prof-menu-right { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }
.prof-menu-dot { width: 6px; height: 6px; border-radius: 50%; background: #FF3D00; flex-shrink: 0; }
.prof-menu-arrow { width: 10px; height: 14px; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; color: #999999; font-size: 0; line-height: 1; }
.prof-menu-arrow::before { content: ''; width: 7px; height: 7px; border-top: 2px solid currentColor; border-right: 2px solid currentColor; transform: rotate(45deg); }
/* —— 未登录 —— */
.prof-unlogged-hero { position: relative; padding: 64px 16px 24px; text-align: center; }
.prof-unlogged-hero .prof-avatar { margin: 0 auto 12px; background: linear-gradient(180deg,#F0F0F0 0%,#DDDDDD 100%); }
.prof-unlogged-cta { margin-top: 6px; background: linear-gradient(180deg,#FFD600 0%,#FFB300 100%); border: none; padding: 8px 24px; border-radius: 999px; font-size: 14px; font-weight: 700; color: #1a1a1a; cursor: pointer; box-shadow: 0 4px 12px rgba(255,180,52,.35); }
</style>
<div class="screen active" id="profile">
<div class="prof-statusbar">
<div class="prof-status-time">9:41</div>
<div class="prof-status-icons">
<span class="prof-cell"><i></i><i></i><i></i><i></i></span>
<span class="prof-wifi"><i></i></span>
<span class="prof-battery"><i></i></span>
</div>
</div>
<!-- 未登录态 -->
<div id="profileUnlogged" class="prof-scroll">
<div class="prof-hero prof-unlogged-hero">
<img class="prof-clouds" src="../../assets/profile/index/top-clouds.png" alt="">
<div class="prof-avatar"><svg viewBox="0 0 64 64" fill="none"><circle cx="32" cy="26" r="11" fill="#fff" opacity=".7"/><path d="M14 54c2-8 9-12 18-12s16 4 18 12" stroke="#fff" stroke-width="3" stroke-linecap="round" opacity=".8" fill="none"/></svg></div>
<div class="prof-name">未登录</div>
<div class="prof-phone" style="margin-bottom: 8px;">登录后查看你的省钱战绩</div>
<button class="prof-unlogged-cta" onclick="loginFrom='profile'; try{localStorage.setItem('proto_loginFrom','profile');}catch(e){}go('login');">立即登录</button>
</div>
<div class="prof-body-inner">
<div class="prof-card prof-menu-card" style="margin-top: 0;">
<div class="prof-menu-item" onclick="loginFrom='profile'; try{localStorage.setItem('proto_loginFrom','profile');}catch(e){}go('login');"><img src="../../assets/profile/index/lower-price-report-medal.png" class="prof-menu-ico prof-report-ico" alt=""><div class="prof-menu-text"><div class="prof-menu-title prof-report-title">上报更低价<span class="prof-report-badge">赚金币</span></div></div><span class="prof-menu-arrow"></span></div>
<div class="prof-menu-item" onclick="loginFrom='profile'; try{localStorage.setItem('proto_loginFrom','profile');}catch(e){}go('login');"><img src="../../assets/profile/index/orders.svg" class="prof-menu-ico" alt=""><div class="prof-menu-text"><div class="prof-menu-title">比价记录</div></div><span class="prof-menu-arrow"></span></div>
<div class="prof-menu-item" onclick="go('feedback')"><img src="../../assets/profile/index/help.png" class="prof-menu-ico" alt=""><div class="prof-menu-text"><div class="prof-menu-title">意见反馈</div></div><span class="prof-menu-arrow"></span></div>
<div class="prof-menu-item" onclick="loginFrom='profile'; try{localStorage.setItem('proto_loginFrom','profile');}catch(e){}go('login');"><img src="../../assets/profile/index/settings.png" class="prof-menu-ico" alt=""><div class="prof-menu-text"><div class="prof-menu-title">设置</div></div><span class="prof-menu-arrow"></span></div>
</div>
</div>
</div>
<!-- 已登录态 -->
<div id="profileLogged" class="prof-scroll" style="display: none;">
<div class="prof-hero">
<img class="prof-clouds" src="../../assets/profile/index/top-clouds.png" alt="">
<img class="prof-piggy" src="../../assets/profile/index/piggy-coins.png" alt="">
<div class="prof-id">
<div class="prof-avatar">
<svg viewBox="0 0 80 80" fill="none">
<defs>
<radialGradient id="profAvatarBg" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(31 24) rotate(58) scale(52)">
<stop offset="0" stop-color="#FFF5B5"/>
<stop offset=".58" stop-color="#FFD45F"/>
<stop offset="1" stop-color="#FFB43A"/>
</radialGradient>
<linearGradient id="profFace" x1="39" y1="25" x2="39" y2="55" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFE0B0"/>
<stop offset="1" stop-color="#FFC783"/>
</linearGradient>
<linearGradient id="profHood" x1="40" y1="45" x2="40" y2="78" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFD742"/>
<stop offset="1" stop-color="#FFA923"/>
</linearGradient>
</defs>
<circle cx="40" cy="40" r="40" fill="url(#profAvatarBg)"/>
<path d="M15 72c2.5-13 12.2-21 25-21s22.5 8 25 21H15z" fill="url(#profHood)"/>
<path d="M26 62c2.8 4.8 7.4 7.4 14 7.4 6.5 0 11.2-2.6 14-7.4-2.6-7.2-7.2-10.8-14-10.8S28.6 54.8 26 62z" fill="#FFE789" opacity=".8"/>
<path d="M20.5 37.5c0-13.2 8.3-22.2 20.3-22.2 11.7 0 19.7 8.8 19.7 22.1 0 2.4-.3 4.6-.8 6.8H21.3c-.5-2.2-.8-4.5-.8-6.7z" fill="#3B2416"/>
<path d="M23.5 36.3c.8-11.4 7.7-18 17.1-18 9.8 0 16.4 6.9 16.8 18.3-3.3-5.2-8.1-7.7-14.4-7.5-3.1.1-5.2 1.6-8 1.6-3.8 0-7.7 1.5-11.5 5.6z" fill="#5B3520"/>
<path d="M22.8 39.6c-2.9.1-5.2 2.5-5.1 5.7.1 3.1 2.4 5.3 5.5 5.4l.5-11.1h-.9z" fill="#FFC783"/>
<path d="M57.2 39.6c2.9.1 5.2 2.5 5.1 5.7-.1 3.1-2.4 5.3-5.5 5.4l-.5-11.1h.9z" fill="#FFC783"/>
<path d="M22.5 38.4c0-10.5 7.2-17.7 17.5-17.7s17.5 7.2 17.5 17.7v5.8c0 10.2-7.2 17.2-17.5 17.2s-17.5-7-17.5-17.2v-5.8z" fill="url(#profFace)"/>
<path d="M22.7 35.8c2.5-8.7 9.7-13.2 18-13.2 7.7 0 13.7 4.4 16.1 11.9-4.8-.3-8.5-2.5-11-6.5-3.2 4.7-10 7.8-23.1 7.8z" fill="#3B2416"/>
<circle cx="31.3" cy="42.5" r="2.1" fill="#3A2113"/>
<circle cx="48.7" cy="42.5" r="2.1" fill="#3A2113"/>
<circle cx="28.2" cy="48.4" r="3.2" fill="#FF916C" opacity=".54"/>
<circle cx="51.8" cy="48.4" r="3.2" fill="#FF916C" opacity=".54"/>
<path d="M35.8 50.8c2.7 2.1 5.7 2.1 8.4 0" stroke="#6B2C19" stroke-width="1.8" stroke-linecap="round"/>
<path d="M27 34.2c1.8-3.2 3.9-5.7 6.3-7.3-1.7 3.3-2.5 6.6-2.4 9.8-1.2-.8-2.5-1.6-3.9-2.5zM39.5 22c-4.1 1.7-7.2 4.1-9.4 7.3 5.8-.1 10.5-1.6 14-4.5L39.5 22z" fill="#2A170E"/>
<path d="M33 63.7c3.7 1.8 10.3 1.8 14 0" stroke="#FFF2B3" stroke-width="2.2" stroke-linecap="round" opacity=".75"/>
</svg>
</div>
<div class="prof-meta">
<div class="prof-name" id="profName" data-fullname="省钱小能手省钱小能手省钱小能手省钱小能手">省钱小能手省钱小能手省钱小能手省钱小能手</div>
</div>
</div>
</div>
<div class="prof-body-inner">
<!-- 省钱战绩 -->
<div class="prof-savings-card" id="profSavingsCard">
<img class="prof-savings-deco" src="../../assets/profile/index/savings-bg.png" alt="">
<img class="prof-savings-coin" src="../../assets/profile/index/coin.png" alt="">
<div class="prof-savings-label">累计发现可省</div>
<div class="prof-amount-row">
<span class="prof-wheat left" aria-hidden="true"></span>
<span class="prof-amount"><span class="prof-currency">¥</span>1,287<span class="prof-cents">.50</span></span>
<span class="prof-wheat right" aria-hidden="true"></span>
</div>
<div class="prof-stats-row">
<div><div class="prof-stat-key">领取优惠券</div><div class="prof-stat-num">18<span class="prof-stat-unit"></span></div></div>
<div class="prof-stats-div"></div>
<div><div class="prof-stat-key">完成比价</div><div class="prof-stat-num">23<span class="prof-stat-unit"></span></div></div>
<div class="prof-stats-div"></div>
<div><div class="prof-stat-key">赚取金币</div><div class="prof-stat-num">580<span class="prof-stat-unit"></span></div></div>
</div>
<!-- 未比价锁定态:不透明蒙层盖住示例数据,点「立即开始」弹去点餐选平台窗 -->
<div class="prof-lock-overlay">
<div class="prof-lock-ico">🔒</div>
<div class="prof-lock-text">完成首次比价<br>解锁你的专属省钱战绩</div>
<button class="prof-lock-cta" type="button" onclick="if(window.SGBridge){SGBridge.navigate('home')}else{openComparePicker()}">立即开始 <span class="arr"></span></button>
</div>
</div>
<!-- 菜单 -->
<div class="prof-card prof-menu-card">
<div class="prof-menu-item" onclick="window.SGBridge&&SGBridge.navigate('reportFlow')"><img src="../../assets/profile/index/lower-price-report-medal.png" class="prof-menu-ico prof-report-ico" alt=""><div class="prof-menu-text"><div class="prof-menu-title prof-report-title">上报更低价<span class="prof-report-badge">赚金币</span></div></div><span class="prof-menu-arrow"></span></div>
<div class="prof-menu-item" onclick="window.SGBridge&&SGBridge.navigate('compareRecords')"><img src="../../assets/profile/index/orders.svg" class="prof-menu-ico" alt=""><div class="prof-menu-text"><div class="prof-menu-title">比价记录</div></div><span class="prof-menu-arrow"></span></div>
<div class="prof-menu-item" onclick="window.SGBridge&&SGBridge.navigate('feedback')"><img src="../../assets/profile/index/help.png" class="prof-menu-ico" alt=""><div class="prof-menu-text"><div class="prof-menu-title">意见反馈</div></div><span class="prof-menu-arrow"></span></div>
<div class="prof-menu-item" onclick="window.SGBridge&&SGBridge.navigate('settings')"><img src="../../assets/profile/index/settings.png" class="prof-menu-ico" alt=""><div class="prof-menu-text"><div class="prof-menu-title">设置</div></div><span class="prof-menu-arrow"></span></div>
</div>
</div>
</div><!-- end profileLogged -->
<div class="tab-bar">
<div class="tab-item" onclick="go('home')"><span class="tab-icon"><svg class="i-outline" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12l9-8 9 8"></path><path d="M5 10v9a1 1 0 001 1h3v-5h6v5h3a1 1 0 001-1v-9"></path></svg><svg class="i-filled" width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M3 12l9-8 9 8" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M5 10v9a1 1 0 001 1h3v-5h6v5h3a1 1 0 001-1v-9" fill="#FFD600" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></span><span class="tab-label">首页</span></div>
<div class="tab-item" id="homeTabWelfare" onclick="go('welfare')"><span class="welfare-tab-dot" aria-hidden="true"></span><span class="tab-icon" id="homeTabWelfareIcon"><svg class="i-outline" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="8" width="18" height="4" rx="1"></rect><path d="M12 8v12"></path><path d="M5 12v7a1 1 0 001 1h12a1 1 0 001-1v-7"></path><path d="M7.5 8C6 8 5 6.5 6 5.5S9 4 9.5 5.5c.4 1.2 2.5 2.5 2.5 2.5s2.1-1.3 2.5-2.5C15 4 17 4.5 18 5.5s-1 2.5-2.5 2.5"></path></svg><svg class="i-filled" width="24" height="24" viewBox="0 0 24 24" fill="none"><rect x="3" y="8" width="18" height="4" rx="1" fill="#FFD600" stroke="#1a1a1a" stroke-width="2"></rect><path d="M5 12v7a1 1 0 001 1h12a1 1 0 001-1v-7" fill="#FFD600" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 8v12" stroke="#1a1a1a" stroke-width="2"></path><path d="M7.5 8C6 8 5 6.5 6 5.5S9 4 9.5 5.5c.4 1.2 2.5 2.5 2.5 2.5s2.1-1.3 2.5-2.5C15 4 17 4.5 18 5.5s-1 2.5-2.5 2.5" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></span><span class="tab-label">福利</span></div>
<div class="tab-item" onclick="go('history')"><span class="tab-icon"><svg class="i-outline" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="2.5"></rect><path d="M8 9h8"></path><path d="M8 13h8"></path><path d="M8 17h5"></path></svg><svg class="i-filled" width="24" height="24" viewBox="0 0 24 24" fill="none"><rect x="4" y="4" width="16" height="16" rx="2.5" fill="#FFD600" stroke="#1a1a1a" stroke-width="2"></rect><path d="M8 9h8" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round"></path><path d="M8 13h8" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round"></path><path d="M8 17h5" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round"></path></svg></span><span class="tab-label">记录</span></div>
<div class="tab-item active" onclick="go('profile')"><span class="tab-icon"><svg class="i-outline" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"></circle><path d="M4 20c0-4 4-6 8-6s8 2 8 6"></path></svg><svg class="i-filled" width="24" height="24" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="8" r="4" fill="#FFD600" stroke="#1a1a1a" stroke-width="2"></circle><path d="M4 20c0-4 4-6 8-6s8 2 8 6" fill="#FFD600" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></span><span class="tab-label">我的</span></div>
</div>
<!-- 去点餐选平台弹窗(锁定态「立即开始」触发,移植自首页)-->
<div class="home-picker-mask" id="comparePickerMask">
<div class="home-picker-modal">
<div class="home-picker-close" onclick="closeComparePicker()"></div>
<div class="home-picker-emoji">🍱</div>
<div class="home-picker-title">请选择您常用的平台</div>
<div class="home-picker-sub">进入平台选好商品后,<strong>AI 一键替你比多家</strong></div>
<div class="home-picker-grid" id="comparePickerGrid"><!-- 动态渲染 --></div>
</div>
</div>
</div>
<!-- ===== INVITE FRIENDS ===== -->
<!-- screen #invite removed for split -->
<!-- ===== COMPARISON RESULT ===== -->
<!-- screen #compresult removed for split -->
<!-- ===== WITHDRAWAL / 提现(参考图二) ===== -->
<!-- screen #withdrawal removed for split -->
<div id="wechatBindSheet" class="wechat-bind-layer" aria-hidden="true">
<div class="wechat-bind-mask" onclick="closeWechatBindSheet()"></div>
<div class="wechat-bind-sheet" onclick="event.stopPropagation()">
<button class="wechat-bind-close" onclick="closeWechatBindSheet()" aria-label="关闭">×</button>
<div class="wechat-bind-amount-label">提现金额</div>
<div class="wechat-bind-amount"><span id="wechatBindAmount">0.3</span><small></small></div>
<div class="wechat-bind-card">
<span class="wechat-bind-card-logo" aria-hidden="true">
<svg viewBox="0 0 32 32" fill="none" aria-hidden="true">
<path d="M13.7 7.2C8 7.2 3.5 10.8 3.5 15.3c0 2.6 1.5 4.9 3.8 6.4l-.9 2.9 3.3-1.7c1.2.3 2.5.5 4 .5 5.6 0 10.2-3.6 10.2-8.1S19.3 7.2 13.7 7.2Z" fill="#fff"/>
<path d="M21 13.2c4.3.5 7.5 3.4 7.5 7 0 2.2-1.2 4.1-3.2 5.4l.7 2.4-2.8-1.5c-.9.2-1.9.4-3 .4-3.9 0-7.2-2.1-8.2-5.1.6.1 1.2.2 1.8.2 6.2 0 11.2-4 11.2-8.9v-.2Z" fill="#fff" opacity=".86"/>
<circle cx="10.1" cy="13.8" r="1" fill="#07C160"/>
<circle cx="16.7" cy="13.8" r="1" fill="#07C160"/>
</svg>
</span>
<div>
<div class="wechat-bind-card-title">暂未绑定微信账户</div>
<div class="wechat-bind-card-sub">绑定后才可提现,可以更换和解绑</div>
</div>
</div>
<button class="wechat-bind-cta" onclick="showPrototypeToast('原型演示:跳转微信授权绑定')">去微信绑定并提现</button>
</div>
</div>
<!-- ===== COIN HISTORY / 收益明细 ===== -->
<!-- screen #coinhistory removed for split -->
<div id="exchangeSheet" class="exchange-layer" aria-hidden="true">
<div class="exchange-mask" onclick="closeExchangeSheet()"></div>
<div class="exchange-sheet" onclick="event.stopPropagation()">
<button class="exchange-close" onclick="closeExchangeSheet()" aria-label="关闭">×</button>
<div class="exchange-title">金币兑换现金</div>
<div class="exchange-balance">金币余额:<strong id="exchangeBalanceText">28,967</strong></div>
<div class="exchange-convert-card">
<div class="exchange-coin-side">
<span class="exchange-coin-icon">¥</span>
<span class="exchange-coin-num" id="exchangeCoinAmount">28,967</span>
</div>
<div class="exchange-cash-num">= <span id="exchangeCashAmount">2.89</span><small></small></div>
</div>
<div class="exchange-presets">
<button class="exchange-preset" onclick="selectExchangeAmount(1000, this)">1000</button>
<button class="exchange-preset" onclick="selectExchangeAmount(2000, this)">2000</button>
<button class="exchange-preset" onclick="selectExchangeAmount(3000, this)">3000</button>
<button class="exchange-preset active" id="exchangePresetAll" onclick="selectExchangeAmount('all', this)">全部兑换</button>
</div>
<div class="exchange-error" id="exchangeError"></div>
<div class="exchange-rule">最低 100 金币,不足 100 的金币将原路返回</div>
<button class="exchange-submit" onclick="confirmExchange()">立即兑换</button>
</div>
</div>
<!-- ===== PURCHASE RECORDS ===== -->
<!-- screen #records removed for split -->
<!-- ===== SETTINGS ===== -->
<!-- screen #settings removed for split -->
<!-- 退出登录确认弹窗 -->
<div id="logoutConfirm" style="display: none;position: absolute;top: 0;left: 0;right: 0;bottom: 0;z-index: 260;background: rgba(0,0,0,.45);align-items: center;justify-content: center;padding: 40px 32px;overflow: hidden;">
<div style="background: #fff;border-radius: 18px;max-width: 295px;width: 100%;padding: 24px 24px 16px;text-align: center;">
<div style="font-size: 18px;font-weight: 700;color: var(--gray-900);margin-bottom: 8px;">退出登录</div>
<div style="font-size: 14px;color: var(--gray-500);line-height: 22px;margin-bottom: 24px;">退出后将无法继续累积金币收益</div>
<div style="display: flex;gap: 12px;">
<button onclick="closeLogoutConfirm()" style="flex: 1;padding: 12px;border-radius: 12px;border: 1px solid var(--gray-300);background: #fff;font-size: 15px;font-weight: 600;color: var(--gray-700);cursor: pointer;">取消</button>
<button onclick="doLogout()" style="flex: 1;padding: 12px;border-radius: 12px;border: none;background: var(--error);font-size: 15px;font-weight: 600;color: #fff;cursor: pointer;">确认退出</button>
</div>
</div>
</div>
<!-- 注销账号确认弹窗 -->
<div id="deleteConfirm" style="display: none;position: absolute;top: 0;left: 0;right: 0;bottom: 0;z-index: 260;background: rgba(0,0,0,.45);align-items: center;justify-content: center;padding: 40px 32px;overflow: hidden;">
<div style="background: #fff;border-radius: 18px;max-width: 295px;width: 100%;padding: 24px 24px 16px;text-align: center;">
<div style="font-size: 48px;margin-bottom: 12px;">⚠️</div>
<div style="font-size: 18px;font-weight: 700;color: var(--error);margin-bottom: 8px;">确认注销账号?</div>
<div style="font-size: 14px;color: var(--gray-500);line-height: 22px;margin-bottom: 8px;">注销后以下数据将<span style="color: var(--error);font-weight: 600;">永久删除且无法恢复</span></div>
<div style="text-align: left;background: var(--gray-50);border-radius: 8px;padding: 12px 16px;margin-bottom: 24px;font-size: 13px;color: var(--gray-600);line-height: 22px;">
· 全部金币余额和现金收益<br>
· 比价记录和购买战绩<br>
· 邀请好友关系和返佣收益
</div>
<div style="display: flex;gap: 12px;">
<button onclick="closeDeleteConfirm()" style="flex: 1;padding: 12px;border-radius: 12px;border: 1px solid var(--gray-300);background: #fff;font-size: 15px;font-weight: 600;color: var(--gray-700);cursor: pointer;">我再想想</button>
<button onclick="doDeleteAccount()" style="flex: 1;padding: 12px;border-radius: 12px;border: none;background: var(--error);font-size: 15px;font-weight: 600;color: #fff;cursor: pointer;">确认注销</button>
</div>
</div>
</div>
<!-- ===== FEEDBACK ===== -->
<!-- screen #feedback removed for split -->
<!-- ===== 领券流程屏(与新手引导同款,复用 demoSteps 的前 6 步:弹窗 → agentFlow → 完成 toast ===== -->
<!-- screen #comparing removed for split -->
<!-- ===== 一键领券 · 完成 toast(提到 device 级别,让结算弹窗显示在首页背景上而非 agent 流的截图上) ===== -->
<div id="demoCouponDoneToast" style="display: none;position: absolute;inset: 0;z-index: 200;">
<div class="coupon-done-k-mask"></div>
<div class="coupon-done-k">
<div class="coupon-done-logo">
<span class="logo-mark">
<span style="font-size: 12px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;letter-spacing: 0;">傻瓜<br>比价</span>
</span>
</div>
<div class="v6-sparkle s1"></div>
<div class="v6-sparkle s2"></div>
<div class="v6-sparkle s3"></div>
<div class="v6-sparkle s4"></div>
<div class="v6-head">
<div class="lead-line lead-line-inline">今日已从<span class="lg-inline"><img src="../../assets/shared/logos/meituan.png" alt=""></span><span class="lg-inline"><img src="../../assets/shared/logos/taobao.png" alt=""></span>帮您领取</div>
<div class="num-line"><span class="rest" style="margin-right: 6px;"></span><span class="num" id="demoCouponDoneCount">0</span><span class="rest">张优惠券</span></div>
</div>
<div class="v6-pocket">
<div class="v6-pocket-notch"></div>
<div class="v6-expiry">
<span class="time-box" id="cdH">23</span>:<span class="time-box" id="cdM">58</span>:<span class="time-box" id="cdS">27</span> 后失效
</div>
<button class="v6-cta" onclick="demoNext()">开心收下,立即使用</button>
</div>
</div>
</div>
<!-- ===== 签到弹窗 ===== -->
<style>
@keyframes checkinPopIn { 0%{transform: translateY(18px) scale(.96);opacity: 0;} 100%{transform: translateY(0) scale(1);opacity: 1;} }
.checkin-popup-layer {
display: none;
position: absolute;
inset: 0;
z-index: 200;
background: rgba(0,0,0,.55);
backdrop-filter: blur(1px);
align-items: center;
justify-content: center;
padding: 0 16px;
overflow: hidden;
}
.checkin-popup-card {
width: 100%;
border-radius: 18px;
padding: 16px 12px 12px;
background: linear-gradient(180deg, #FFE0B2 0%, #FFFDE7 30%, #FFFFFF 72%);
box-shadow: 0 20px 40px rgba(0,0,0,.12);
position: relative;
overflow: visible;
animation: checkinPopIn .26s cubic-bezier(.22,1,.36,1);
}
.checkin-close {
position: absolute;
left: 50%;
bottom: -52px;
width: 34px;
height: 34px;
transform: translateX(-50%);
border: none;
border-radius: 50%;
background: rgba(255,255,255,.58);
color: rgba(0,0,0,.46);
box-shadow: 0 6px 18px rgba(0,0,0,.08);
display: flex;
align-items: center;
justify-content: center;
font-size: 22px;
line-height: 1;
cursor: pointer;
z-index: 4;
}
.checkin-banner {
position: relative;
z-index: 2;
width: 206px;
height: 16px;
margin: -4px auto 8px;
border-radius: 999px;
background: rgba(255,255,255,.92);
box-shadow: 0 4px 14px rgba(255,174,0,.14);
border: 1px solid rgba(255,184,0,.24);
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
color: #7A4F00;
font-size: 10px;
font-weight: 600;
white-space: nowrap;
}
.checkin-banner .star {
width: 9px;
height: 9px;
background: #FFB300;
clip-path: polygon(50% 0%, 62% 37%, 100% 50%, 62% 63%, 50% 100%, 38% 63%, 0% 50%, 38% 37%);
flex-shrink: 0;
}
.checkin-title {
position: relative;
z-index: 2;
margin: 0;
text-align: center;
color: #1A1A1A;
font-size: 20px;
line-height: 1.1;
font-weight: 900;
letter-spacing: 0;
}
.checkin-sub {
position: relative;
z-index: 2;
margin-top: 8px;
text-align: center;
color: #666;
font-size: 11px;
line-height: 1.2;
font-weight: 500;
white-space: nowrap;
}
.checkin-sub b {
color: #FF6A00;
font-weight: 600;
}
.checkin-rewards {
position: relative;
z-index: 2;
margin-top: 12px;
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 6px;
}
.checkin-reward-card {
position: relative;
min-height: 64px;
border-radius: 8px;
background: rgba(255,255,255,.88);
border: 1px solid #F0F0F0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 6px;
padding: 8px 2px 6px;
color: #1A1A1A;
font-weight: 600;
box-shadow: inset 0 1px 0 rgba(255,255,255,.75);
}
.checkin-reward-card.claimed {
background: rgba(247,247,247,.96);
border-color: #E5E5E5;
box-shadow: none;
color: #999999;
}
.checkin-reward-card.current {
border-color: #FFB300;
box-shadow: 0 8px 15px rgba(255,184,0,.14);
background: rgba(255,255,255,.96);
}
.checkin-reward-icon {
min-height: 26px;
display: flex;
align-items: center;
justify-content: center;
color: #999999;
font-size: 10px;
line-height: 1;
font-weight: 850;
white-space: nowrap;
}
.checkin-reward-card img {
width: 29px;
height: 29px;
object-fit: contain;
display: block;
}
.checkin-reward-card .icon-chest {
width: 36px;
height: 33px;
}
.checkin-reward-amount {
color: #1A1A1A;
font-size: 12px;
line-height: 1;
font-weight: 850;
}
.checkin-reward-card.claimed .checkin-reward-amount {
color: #999999;
}
.checkin-progress {
margin: 12px 0 0;
position: relative;
height: 42px;
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 6px;
align-items: start;
}
.checkin-progress-lines {
position: absolute;
top: 4.5px;
left: 0;
right: 0;
height: 3px;
pointer-events: none;
z-index: 0;
}
.checkin-segment {
position: absolute;
top: 0;
height: 3px;
border-radius: 32px;
}
.checkin-segment.solid {
background: var(--line-color);
}
.checkin-segment.dashed {
background-repeat: no-repeat;
}
.checkin-node {
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
color: #666;
font-size: 10px;
line-height: 1;
white-space: nowrap;
}
.checkin-dot {
box-sizing: border-box;
width: 12px;
height: 12px;
border-radius: 50%;
background: #FFFFFF;
border: 2px solid #DDDDDD;
}
.checkin-node.done .checkin-dot {
background: #FFB300;
border-color: #FFB300;
}
.checkin-node.current .checkin-dot {
background: #FFFFFF;
border: 2.5px solid #FFB300;
}
.checkin-popup-cta {
position: relative;
z-index: 2;
margin: 8px auto 0;
width: 252px;
height: 40px;
border: none;
border-radius: 24px;
background: linear-gradient(180deg, #FFE066 0%, #FFB300 100%);
color: #1A1A1A;
font-size: 17px;
font-weight: 900;
box-shadow: 0 14px 28px rgba(255,184,0,.22);
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
cursor: pointer;
font-family: inherit;
}
.checkin-popup-cta img {
width: 18px;
height: 18px;
object-fit: contain;
display: block;
}
.checkin-popup-cta b {
color: #FF6A00;
font-size: 22px;
line-height: 1;
}
</style>
<div id="checkinPopup" class="checkin-popup-layer">
<div class="checkin-popup-card" onclick="event.stopPropagation()">
<button class="checkin-close" onclick="closeCheckinPopup()" aria-label="关闭">×</button>
<div class="checkin-banner" id="checkinBanner"><span class="star"></span>连续签到14天 最高可领2888金币</div>
<h2 class="checkin-title" id="checkinPopupTitle">签到领取今日金币</h2>
<div class="checkin-sub" id="checkinPopupSub">已连续签到 <b>2</b> 天,今天可领 <b>220</b> 金币</div>
<div class="checkin-rewards" id="checkinRewards" aria-label="连续签到奖励">
<div class="checkin-reward-card claimed">
<div class="checkin-reward-icon">已领取</div>
<div class="checkin-reward-amount">180</div>
</div>
<div class="checkin-reward-card claimed">
<div class="checkin-reward-icon">已领取</div>
<div class="checkin-reward-amount">380</div>
</div>
<div class="checkin-reward-card current">
<div class="checkin-reward-icon"><img src="../../assets/welfare/index/checkin-coin-single.png" alt=""></div>
<div class="checkin-reward-amount">220</div>
</div>
<div class="checkin-reward-card">
<div class="checkin-reward-icon"><img src="../../assets/welfare/index/checkin-coin-single.png" alt=""></div>
<div class="checkin-reward-amount">260</div>
</div>
<div class="checkin-reward-card">
<div class="checkin-reward-icon"><img src="../../assets/welfare/index/checkin-coins-600.png" alt=""></div>
<div class="checkin-reward-amount">888</div>
</div>
</div>
<div class="checkin-progress" id="checkinProgress" aria-label="签到进度">
<div class="checkin-progress-lines" id="checkinProgressLines"></div>
<div class="checkin-node done" data-day="1"><span class="checkin-dot"></span><span>第1天</span></div>
<div class="checkin-node done" data-day="2"><span class="checkin-dot"></span><span>第2天</span></div>
<div class="checkin-node current" data-day="3"><span class="checkin-dot"></span><span>今天</span></div>
<div class="checkin-node" data-day="4"><span class="checkin-dot"></span><span>明天</span></div>
<div class="checkin-node" data-day="7"><span class="checkin-dot"></span><span>第7天</span></div>
</div>
<button id="checkinBtn" class="checkin-popup-cta" onclick="doCheckin()">签到领 <img src="../../assets/welfare/index/checkin-coin-single.png" alt=""><b>220</b></button>
<button id="checkinReminderBtn" class="checkin-popup-cta" onclick="doCheckinReminder()" style="display: none;">打开签到提醒</button>
</div>
</div>
<!-- ===== 签到提醒权限弹窗 ===== -->
<div id="calendarPermPopup" style="display: none;position: absolute;top: 0;left: 0;right: 0;bottom: 0;z-index: 250;background: rgba(0,0,0,.55);align-items: center;justify-content: center;padding: 40px 24px;overflow: hidden;">
<div style="background: #fff;border-radius: 18px;max-width: 327px;width: 100%;padding: 24px 24px;position: relative;">
<div onclick="closeCalendarPerm()" style="position: absolute;top: 14px;right: 14px;width: 28px;height: 28px;border-radius: 14px;background: var(--gray-100);display: flex;align-items: center;justify-content: center;cursor: pointer;font-size: 14px;color: var(--gray-500);"></div>
<div style="text-align: center;">
<div style="font-size: 20px;font-weight: 700;color: var(--gray-900);margin-bottom: 8px;">日历权限未开启</div>
<div style="font-size: 14px;color: var(--gray-500);line-height: 1.6;">开启提醒失败,请前往设置-傻瓜比价打开日历权限后重试</div>
</div>
<button onclick="closeCalendarPerm()" style="width: 100%;margin-top: 16px;background: linear-gradient(180deg,#FFE066 0%,#FFC400 100%);color: #1A1A1A;border: none;padding: 12px;border-radius: 24px;font-size: 17px;font-weight: 700;cursor: pointer;box-shadow: inset 0 1px 0 rgba(255,255,255,.7), 0 2px 6px rgba(255,179,0,.35);">去开启</button>
</div>
</div>
<!-- 页面导航提示 -->
<!-- ===== 全部权限开启完成 · 祝贺弹窗(A/B/C 内容动态注入) ===== -->
<div id="celebrationModal" onclick="closeCelebrationModal()" style="display: none;position: absolute;top: 0;left: 0;right: 0;bottom: 0;z-index: 260;background: rgba(0,0,0,.55);align-items: center;justify-content: center;padding: 0 24px;overflow: hidden;">
<div onclick="event.stopPropagation()" id="celebrationModalCard" style="background: #fff;border-radius: 24px;width: 100%;max-width: 327px;padding: 24px 24px 24px;position: relative;animation: safetyPopIn .3s cubic-bezier(.22,1,.36,1);"></div>
</div>
<!-- ===== 权限未开启提示弹窗(居中卡片式,复用于无障碍/悬浮窗) ===== -->
<div id="safetyModal" onclick="closeSafetyModal()" style="display: none;position: absolute;top: 0;left: 0;right: 0;bottom: 0;z-index: 250;background: rgba(0,0,0,.55);align-items: center;justify-content: center;padding: 0 24px;overflow: hidden;">
<div onclick="event.stopPropagation()" style="background: #fff;border-radius: 24px;width: 100%;max-width: 327px;padding: 24px 24px 24px;position: relative;animation: safetyPopIn .3s cubic-bezier(.22,1,.36,1);">
<!-- 关闭按钮 -->
<button onclick="closeSafetyModal()" aria-label="关闭" style="position: absolute;top: 14px;right: 14px;width: 28px;height: 28px;border-radius: 14px;background: #f0f0f0;border: none;cursor: pointer;font-size: 16px;line-height: 1;color: #666;display: flex;align-items: center;justify-content: center;padding: 0;z-index: 2;">×</button>
<!-- 警示图标 -->
<div style="width: 60px;height: 60px;border-radius: 32px;background: #FFF3E0;display: flex;align-items: center;justify-content: center;margin: 0 auto 12px;font-size: 28px;">⚠️</div>
<!-- 标题 -->
<div id="safetyModalTitle" style="font-size: 20px;font-weight: 800;color: var(--gray-900);text-align: center;margin-bottom: 8px;">比价功能未开启</div>
<div style="font-size: 13px; color: rgb(0, 0, 0); line-height: 20px; text-align: center; margin-bottom: 16px; white-space: nowrap;">
<span id="safetyModalBody">在「已安装的应用」中找到「傻瓜比价」并开启</span><span id="safetyModalPermName" style="display: none;">无障碍</span>
</div>
<!-- 安全承诺区(压缩版) -->
<div id="safetyPromiseBlock" style="background: var(--gray-100);border-radius: 14px;padding: 12px 12px 12px;margin-bottom: 16px;">
<div style="font-size: 14px;font-weight: 700;color: var(--gray-700);margin-bottom: 8px;">我们的安全承诺</div>
<ul style="list-style: disc;padding-left: 16px;margin: 0;font-size: 12px;color: var(--gray-500);line-height: 19px;">
<li style="margin-bottom: 6px;">仅在您开启比价时启用,用完即停</li>
<li style="margin-bottom: 6px;">全程端侧加密,全方位守护您的隐私</li>
<li>您随时可在设置中关闭</li>
</ul>
</div>
<!-- 底部按钮 -->
<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;" onclick="goToPermFromSafetyModal()">继续开启</button>
</div>
</div>
<!-- ===== 反馈底部半屏面板 ===== -->
<style>
@keyframes sheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
.feedback-sheet { animation: sheetUp .3s ease-out; }
.fb-platform.selected { border-color: #FF5722 !important; background: #FFF3E0; color: #FF5722; }
</style>
<div id="feedbackSheet" style="display: none;position: absolute;top: 0;left: 0;right: 0;bottom: 0;z-index: 260;overflow: hidden;">
<!-- 遮罩 -->
<div onclick="closeFeedbackSheet()" style="position: absolute;inset: 0;background: rgba(0,0,0,.4);"></div>
<!-- 面板 -->
<div class="feedback-sheet" style="position: absolute;bottom: 0;left: 0;right: 0;background: #fff;border-radius: 18px 18px 0 0;max-height: 75%;overflow-y: auto;">
<!-- 拖动条 -->
<div style="padding: 12px 0 0;text-align: center;"><div style="width: 40px;height: 4px;border-radius: 4px;background: var(--gray-300);margin: 0 auto;"></div></div>
<!-- 标题 -->
<div style="padding: 16px 16px 12px;">
<div style="font-size: 18px;font-weight: 700;">比价结果反馈</div>
<div style="font-size: 13px;color: var(--gray-500);margin-top: 4px;">审核通过可获得 <span style="color: #FF5722;font-weight: 600;">2,000 金币</span> 奖励</div>
</div>
<!-- 步骤1:选择反馈类型 -->
<div id="fbStep1" style="padding: 0 16px 16px;">
<div style="font-size: 14px;font-weight: 600;color: var(--gray-700);margin-bottom: 12px;">选择反馈类型</div>
<div onclick="selectFbType('lower_price')" style="display: flex;align-items: center;gap: 12px;padding: 16px;border: 1.5px solid var(--gray-200);border-radius: 14px;cursor: pointer;margin-bottom: 8px;transition: all .15s;" id="fbTypeLower">
<div style="width: 44px;height: 44px;border-radius: 12px;background: linear-gradient(135deg,#FFF3E0,#FFE0B2);display: flex;align-items: center;justify-content: center;font-size: 22px;flex-shrink: 0;">💰</div>
<div><div style="font-size: 15px;font-weight: 600;">我发现了更低价格</div><div style="font-size: 12px;color: var(--gray-500);margin-top: 2px;">在其他平台找到了同款更便宜的</div></div>
<span style="margin-left: auto;font-size: 18px;color: var(--gray-400);"></span>
</div>
<div onclick="selectFbType('wrong_match')" style="display: flex;align-items: center;gap: 12px;padding: 16px;border: 1.5px solid var(--gray-200);border-radius: 14px;cursor: pointer;transition: all .15s;" id="fbTypeWrong">
<div style="width: 44px;height: 44px;border-radius: 12px;background: linear-gradient(135deg,#E3F2FD,#E3F2FD);display: flex;align-items: center;justify-content: center;font-size: 22px;flex-shrink: 0;"></div>
<div><div style="font-size: 15px;font-weight: 600;">外卖不是同一家</div><div style="font-size: 12px;color: var(--gray-500);margin-top: 2px;">比价结果中有外卖匹配错误</div></div>
<span style="margin-left: auto;font-size: 18px;color: var(--gray-400);"></span>
</div>
</div>
<!-- 步骤2A:更低价格表单 -->
<div id="fbFormLower" style="display: none;padding: 0 16px 24px;">
<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 16px;">
<button class="btn-back" onclick="backToFbStep1()" aria-label="返回上一步"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15 6L9 12L15 18" stroke="#1A1A1A" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg></button>
<div style="font-size: 15px;font-weight: 600;">我发现了更低价格</div>
</div>
<div style="font-size: 14px;font-weight: 600;color: var(--gray-700);margin-bottom: 8px;">粘贴外卖链接</div>
<input type="text" placeholder="粘贴更低价外卖的链接" style="width: 100%;border: 1.5px solid var(--gray-200);border-radius: 12px;padding: 12px;font-size: 14px;outline: none;margin-bottom: 16px;">
<div style="font-size: 14px;font-weight: 600;color: var(--gray-700);margin-bottom: 8px;">上传截图 <span style="font-weight: 400;color: var(--gray-400);">(含价格信息)</span></div>
<div style="display: flex;gap: 8px;margin-bottom: 16px;">
<div style="width: 80px;height: 80px;border: 1.5px dashed var(--gray-300);border-radius: 12px;display: flex;align-items: center;justify-content: center;font-size: 24px;color: var(--gray-400);cursor: pointer;">+</div>
<div style="width: 80px;height: 80px;border: 1.5px dashed var(--gray-300);border-radius: 12px;display: flex;align-items: center;justify-content: center;font-size: 24px;color: var(--gray-400);cursor: pointer;">+</div>
</div>
<button onclick="submitFeedback()" style="width: 100%;background: var(--primary);border: none;padding: 12px;border-radius: 14px;font-size: 16px;font-weight: 700;color: #1a1a1a;cursor: pointer;">提交反馈</button>
</div>
<!-- 步骤2B:非同款表单 -->
<div id="fbFormWrong" style="display: none;padding: 0 16px 24px;">
<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 16px;">
<button class="btn-back" onclick="backToFbStep1()" aria-label="返回上一步"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15 6L9 12L15 18" stroke="#1A1A1A" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg></button>
<div style="font-size: 15px;font-weight: 600;">外卖不是同一家</div>
</div>
<div style="font-size: 14px;font-weight: 600;color: var(--gray-700);margin-bottom: 8px;">哪个平台的结果有误?</div>
<div id="fbPlatformList" style="display: flex;flex-wrap: wrap;gap: 8px;margin-bottom: 16px;"></div>
<div style="font-size: 14px;font-weight: 600;color: var(--gray-700);margin-bottom: 8px;">上传截图或描述问题</div>
<div style="display: flex;gap: 8px;margin-bottom: 12px;">
<div style="width: 80px;height: 80px;border: 1.5px dashed var(--gray-300);border-radius: 12px;display: flex;align-items: center;justify-content: center;font-size: 24px;color: var(--gray-400);cursor: pointer;">+</div>
</div>
<textarea placeholder="描述哪里不同(可选)" style="width: 100%;border: 1.5px solid var(--gray-200);border-radius: 12px;padding: 12px;font-size: 14px;outline: none;height: 60px;resize: none;font-family: inherit;margin-bottom: 16px;"></textarea>
<button onclick="submitFeedback()" style="width: 100%;background: var(--primary);border: none;padding: 12px;border-radius: 14px;font-size: 16px;font-weight: 700;color: #1a1a1a;cursor: pointer;">提交反馈</button>
</div>
<!-- 提交成功 -->
<div id="fbSuccess" style="display: none;padding: 24px 16px 32px;text-align: center;">
<div style="font-size: 48px;margin-bottom: 12px;"></div>
<div style="font-size: 18px;font-weight: 700;margin-bottom: 4px;">反馈已提交</div>
<div style="font-size: 14px;color: var(--gray-500);line-height: 22px;">系统正在验证,审核通过后<br><span style="color: #FF5722;font-weight: 600;">2,000 金币</span> 将自动到账</div>
<div style="font-size: 12px;color: var(--gray-400);margin-top: 12px;">审核结果将通过推送通知告知您</div>
<button onclick="closeFeedbackSheet()" style="margin-top: 16px;width: 100%;background: var(--primary);border: none;padding: 12px;border-radius: 14px;font-size: 16px;font-weight: 700;color: #1a1a1a;cursor: pointer;">知道了</button>
</div>
</div>
</div>
<div class="nav-hint" id="navHint" style="display: none;"></div>
<!-- 结果页预览浮层 -->
<div id="resultPreviewOverlay" onclick="hideResultPreview()" style="display: none;position: absolute;inset: 0;z-index: 300;background: #fff;cursor: pointer;">
<img id="resultPreviewImg" src="" style="width: 100%;height: 100%;object-fit: cover;object-position: top;">
</div>
<!-- ===== 新手礼包弹窗 ===== -->
<div class="gift-overlay" id="welcomeGiftPopup">
<div class="gift-card" id="welcomeGiftCard">
<button class="gift-close" onclick="closeWelcomeGift(true)"></button>
<div class="gift-stage-a">
<div class="gift-confetti">🎉🎊✨🎊🎉</div>
<div class="gift-title">新手大礼包</div>
<div class="gift-subtitle">专享新客福利,开启领取</div>
</div>
<div class="gift-chest-wrap">
<div class="gift-chest-glow"></div>
<div class="gift-burst">
<div class="gift-burst-ray"></div>
<div class="gift-burst-ray"></div>
<div class="gift-burst-ray"></div>
<div class="gift-burst-ray"></div>
<div class="gift-burst-ray"></div>
<div class="gift-burst-ray"></div>
</div>
<div class="gift-chest-emoji" id="giftChestEmoji">🎁</div>
</div>
<div class="gift-amount" id="giftAmount">+5,000<span class="gift-amount-suffix">金币</span></div>
<div class="gift-amount-hint">已存入「福利」,随时可提现</div>
<button class="gift-btn" id="giftMainBtn" onclick="openGiftBox()">✨ 开启礼包</button>
</div>
</div>
<!-- 福利 tab 上方 +5000 飘字(device 级,z-index 高于 overlay -->
<div class="tab-coin-badge" id="welfareTabBadge" style="z-index: 260;">+5,000 金币</div>
</div>
<script>
function showResultPreview(imgSrc) {
if (!imgSrc) return;
document.getElementById('resultPreviewImg').src = imgSrc;
document.getElementById('resultPreviewOverlay').style.display = 'block';
}
function hideResultPreview() {
document.getElementById('resultPreviewOverlay').style.display = 'none';
}
// 结果数据
// [WAIMAI-ONLY] 外卖比价结果数据 — 真实窑鸡王订单
const results = [
{
status: 'found',
platform: '淘宝',
platformIcon: '../../assets/shared/logos/taobao.png',
shop: '窑鸡王(康营店)',
delivery: '商家自配',
lowest: true,
items: [
{ name: '招牌窑鸡★★ 整只-原味', spec: '原味 × 1', price: 69.9, original: 99.9 }
],
fees: [
{ label: '打包费', amount: 5 },
{ label: '配送费', amount: 5, original: 12, note: '惊喜减7元' }
],
discounts: [
{ label: '店铺活动/券', amount: 1 },
{ label: '平台红包(超级吃货卡)', amount: 21 }
],
totalPrice: 57.9,
totalSaved: 59,
bonuses: [{ label: '下单返豆', detail: '返110吃货豆' }],
resultImage: '../../assets/onboarding/index/platform-flows/taobao/result.jpg'
},
{
status: 'found',
platform: '美团',
platformIcon: '../../assets/shared/logos/meituan.png',
shop: '窑鸡王(康营店)',
delivery: '商家自配',
lowest: false,
items: [
{ name: '招牌窑鸡(整只)', spec: '1只, 招牌整只原味 × 1', price: 69.9 }
],
fees: [
{ label: '打包费', amount: 5 },
{ label: '配送费', amount: 5.8, original: 12, note: '活动减6.2元' }
],
discounts: [
{ label: '美团红包(神券包)', amount: 18 }
],
totalPrice: 62.7,
totalSaved: 24.2,
bonuses: [],
resultImage: '../../assets/onboarding/index/platform-flows/meituan/result.jpg'
},
{
status: 'not-found',
platform: '京东',
platformIcon: '../../assets/shared/logos/jd.png',
reason: '未找到店铺'
}
];
// --- 同价 corner case 备用数据(取消注释可切换演示)---
// results[1].status = 'same-price';
// results[1].totalPrice = 57.9;
function renderFoundCard(r, idx, ctx) {
const isLowest = r.lowest;
const isUserOrig = ctx && ctx.userOrigId && r._id === ctx.userOrigId;
const borderColor = isLowest ? 'var(--primary)' : 'var(--gray-200)';
const cardBorder = isLowest ? '2px' : '1.5px';
const cardClass = isLowest ? 'card with-ribbon lowest' : 'card';
// 标识:最低价 → M2 斜挂红 ribbon(右上角);用户原选 → 描边方角 chip(店名旁 inline
const lowestRibbon = isLowest ? '<img class="ribbon-vi" src="../../assets/shared/badges/lowest-price.png" alt="全网最低">' : '';
const userOrigChip = isUserOrig ? '<span class="badge-userorig">原选择</span>' : '';
// 收集所有 AI 帮领的优惠(配送费减免 + 优惠券 + 店铺活动)
const aiDiscountItems = [];
r.fees.forEach(f => {
if (f.note) aiDiscountItems.push({ label: f.note, amount: f.original - f.amount });
});
r.discounts.forEach(d => {
aiDiscountItems.push({ label: d.label, amount: d.amount });
});
// AI 优惠标签
const aiTagsHtml = aiDiscountItems.map(d =>
`<span style="display: inline-flex;align-items: center;gap: 2px;background: #E8F5E9;border-radius: 4px;padding: 2px 8px;font-size: 11px;color: #2E7D32;white-space: nowrap;">${d.label} <b>-¥${d.amount}</b></span>`
).join('');
// N2 chip:仅最低价 + 有正向价差时显示
let chipHtml = '';
if (isLowest && ctx && ctx.savings > 0) {
chipHtml = `<span class="save-chip-red"><span class="small">比原选择省</span>¥${ctx.savings}</span>`;
}
// CTA:新手引导里弱化购买入口,所有卡片统一使用"查看"浅灰次级胶囊
const ctaHtml = `<button class="result-cta" onclick="event.stopPropagation();showResultPreview('${r.resultImage || ''}')">查看<span class="arrow"></span></button>`;
return `
<div class="${cardClass}" style="background: #fff;border-radius: 14px;padding: 12px 16px;border:${cardBorder} solid ${borderColor};position: relative;">
${lowestRibbon}
<!-- 头部:平台 logo + 店铺名 + 原选择 chip -->
<div style="display: flex;align-items: center;gap: 6px;${isLowest?'padding-right: 92px;':''}">
<img src="${r.platformIcon}" style="width: 28px;height: 28px;border-radius: 8px;flex-shrink: 0;" onerror="this.style.display='none'">
<span style="font-size: 14px;font-weight: 600;color: var(--gray-800);min-width: 0;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">${r.shop}</span>
${userOrigChip}
</div>
<!-- 傻瓜比价 AI 优惠 -->
<div style="margin-top: 8px;">
<div style="font-size: 12px;color: var(--gray-500);margin-bottom: 6px;">🤖 傻瓜比价已帮您领取以下优惠:</div>
<div style="display: flex;flex-wrap: wrap;gap: 4px;">
${aiTagsHtml}
</div>
</div>
<!-- 价格 + chip + CTA -->
<div style="display: flex;justify-content: space-between;align-items: center;margin-top: 12px;gap: 8px;">
<div style="display: flex;align-items: baseline;gap: 6px;flex-wrap: wrap;">
<span style="font-size: 13px;font-weight: 700;color: #FF5722;">¥</span>
<span style="font-size: 24px;font-weight: 800;color: #FF5722;line-height: 1;">${r.totalPrice}</span>
${chipHtml}
</div>
${ctaHtml}
</div>
</div>
`;
}
function renderNotFoundCard(r) {
// 从其他 found 结果中取店铺名
const shopName = (results.find(x => x.status === 'found') || {}).shop || '';
return `
<div style="background: #fff;border-radius: 14px;padding: 12px 16px;border: 1.5px solid var(--gray-200);position: relative;">
<!-- 头部:平台 -->
<div style="display: flex;align-items: center;gap: 8px;">
<img src="${r.platformIcon}" style="width: 28px;height: 28px;border-radius: 8px;" onerror="this.style.display='none'">
<span style="font-size: 14px;font-weight: 600;color: var(--gray-800);">${r.platform}</span>
</div>
<!-- 未找到提示 -->
<div style="margin-top: 12px;padding: 16px;background: var(--gray-50);border-radius: 8px;text-align: center;">
<div style="font-size: 13px;color: var(--gray-500);line-height: 20px;">该平台未找到「${shopName}」</div>
</div>
</div>
`;
}
function renderResults(containerId) {
const c = document.getElementById(containerId);
// 给每条结果赋稳定 id,便于 ctx 引用
results.forEach((r, i) => { if (r._id == null) r._id = '_r' + i; });
// 计算"用户原选"= 找到的非最低里最贵那条;savings = userOrig 价 - lowest 价
const foundResults = results.filter(r => r.status === 'found' || r.status === 'same-price');
const lowestResult = results.find(r => r.lowest);
const otherFound = foundResults.filter(r => !r.lowest);
const userResult = otherFound.length ? otherFound.reduce((a, b) => a.totalPrice >= b.totalPrice ? a : b) : null;
const savings = (lowestResult && userResult && userResult.totalPrice > lowestResult.totalPrice)
? (userResult.totalPrice - lowestResult.totalPrice).toFixed(1)
: 0;
const ctx = {
userOrigId: userResult ? userResult._id : null,
savings: Number(savings),
};
// 排序:lowest → found 按价格升序 → same-price → not-found
const order = { 'found': 1, 'same-price': 2, 'not-found': 3 };
const sorted = [...results].sort((a, b) => {
if (a.lowest && !b.lowest) return -1;
if (!a.lowest && b.lowest) return 1;
const oa = order[a.status] || 9, ob = order[b.status] || 9;
if (oa !== ob) return oa - ob;
if (a.totalPrice && b.totalPrice) return a.totalPrice - b.totalPrice;
return 0;
});
c.innerHTML = sorted.map((r, i) => {
if (r.status === 'not-found') return renderNotFoundCard(r);
return renderFoundCard(r, i, ctx);
}).join('');
}
function renderCelebrationSavings() {
const card = document.getElementById('celebSavingsCard');
if (!card) return;
card.innerHTML = `
<img src="../../assets/onboarding/index/first-banner.png" alt="恭喜您完成首次比价" style="display: block;width: 100%;height: auto;">
`;
}
// 无障碍全屏引导流程
const accessibilityImages = ['../../assets/onboarding/index/guide-1.jpg', '../../assets/onboarding/index/guide-2.jpg', '../../assets/onboarding/index/guide-3.jpg', '../../assets/onboarding/index/guide-4.jpg'];
let accessibilityIdx = 0;
function startAccessibilityFlow() {
accessibilityIdx = 0;
document.getElementById('accessFlowImg').src = accessibilityImages[0];
document.getElementById('accessStep4Overlay').style.display = 'none';
go('accessibility-flow');
}
function nextAccessibilityStep() {
accessibilityIdx++;
if (accessibilityIdx < accessibilityImages.length) {
document.getElementById('accessFlowImg').src = accessibilityImages[accessibilityIdx];
// 无障碍4(index=3)显示允许/拒绝覆盖层,禁用全屏点击
if (accessibilityIdx === 3) {
document.getElementById('accessStep4Overlay').style.display = 'block';
}
}
}
function onAllowClick(e) {
e.stopPropagation();
document.getElementById('accessStep4Overlay').style.display = 'none';
go('permission-step2');
}
function onRejectClick(e) {
e.stopPropagation();
document.getElementById('accessStep4Overlay').style.display = 'none';
go('permission-step1');
// 权限未开启 → 弹出提示弹窗
setTimeout(function() { openSafetyModal('无障碍'); }, 300);
}
function openSafetyModal(permName) {
document.getElementById('safetyModalPermName').textContent = permName;
document.getElementById('safetyModalTitle').textContent =
permName === '悬浮窗' ? '比价按钮未开启' : '比价功能未开启';
// 文案随权限上下文切换:无障碍 → 在「已安装的应用」中找;悬浮窗 → 直接在列表中找
var bodyEl = document.getElementById('safetyModalBody');
if (bodyEl) {
bodyEl.textContent = permName === '悬浮窗'
? '在列表中找到「傻瓜比价」并开启'
: '在「已安装的应用」中找到「傻瓜比价」并开启';
}
// 仅无障碍弹窗显示安全承诺,悬浮窗弹窗隐藏
var promise = document.getElementById('safetyPromiseBlock');
if (promise) promise.style.display = (permName === '悬浮窗') ? 'none' : 'block';
document.getElementById('safetyModal').style.display = 'flex';
}
function closeSafetyModal() {
document.getElementById('safetyModal').style.display = 'none';
}
// 「继续开启」按钮:关弹窗 + 直接进入对应权限设置页
function goToPermFromSafetyModal() {
const permName = document.getElementById('safetyModalPermName').textContent;
closeSafetyModal();
if (permName === '悬浮窗') {
startOverlayFlow();
} else {
startAccessibilityFlow();
}
}
// 悬浮窗引导流程
function startOverlayFlow() {
go('overlay-flow');
}
function onOverlayAllowClick(e) {
e.stopPropagation();
go('productselect');
openCelebrationModal();
}
// ===== 祝贺弹窗(多版本) =====
var celebrationVariants = {
// V1 「轻收尾·重期待」:承上小灰,起下大黑,行为按钮含次要引导
v1: '' +
'<div style="display: flex;align-items: center;justify-content: center;gap: 6px;font-size: 12px;color: var(--gray-500);margin-bottom: 8px;"><span style="display: inline-flex;align-items: center;justify-content: center;width: 16px;height: 16px;border-radius: 8px;background: #22C55E;color: #fff;font-size: 11px;font-weight: 700;">✓</span>全部设置已完成</div>' +
'<div style="font-size: 24px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.3;margin-bottom: 8px;">下一步,体验<br>傻瓜式一键比价</div>' +
'<div style="font-size: 14px;color: var(--gray-600);text-align: center;margin-bottom: 24px;">先选一个你常用的外卖平台</div>' +
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;" onclick="closeCelebrationModal()">选个常用平台开始体验</button>',
// V2 「分割式」:顶部承上小条 + 中部起下标题 + 底部行为引导,节奏分明
v2: '' +
'<div style="text-align: center;margin-bottom: 12px;"><span style="display: inline-flex;align-items: center;gap: 6px;padding: 4px 12px;border-radius: 32px;background: #E8F5E9;color: #2E7D32;font-size: 12px;font-weight: 600;">✓ 已完成全部设置</span></div>' +
'<div style="font-size: 22px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.35;margin-bottom: 16px;">来体验傻瓜式<br>一键比价</div>' +
'<div style="height: 1px;background: var(--gray-200);margin-bottom: 16px;"></div>' +
'<div style="font-size: 13px;color: var(--gray-500);text-align: center;margin-bottom: 8px;">第一步</div>' +
'<div style="font-size: 15px;font-weight: 700;color: var(--gray-900);text-align: center;margin-bottom: 16px;">选择一个常用的外卖平台</div>' +
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;" onclick="closeCelebrationModal()">选个常用平台开始体验</button>',
// V3 「叙事流」:递进式三行,承上→起下→行为,逐级加重(采用 V5 的绿圆勾徽章)
v3: '' +
'<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 16px;">' +
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 20px;height: 20px;border-radius: 50%;background: #22C55E;box-shadow: 0 0 0 3px rgba(34,197,94,.18);flex-shrink: 0;"><svg width="11" height="11" viewBox="0 0 10 10"><path d="M2.2 5.2l2 2 3.8-4.6" stroke="#fff" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span>' +
'<span style="font-size: 13px;color: var(--gray-700);font-weight: 600;">设置已完成</span>' +
'</div>' +
'<div style="background: linear-gradient(135deg,#FFFDE7,#FFF8E1);border-radius: 14px;padding: 16px 16px;margin-bottom: 16px;text-align: center;">' +
'<div style="font-size: 12px;color: #F9A825;font-weight: 600;margin-bottom: 6px;">下一步</div>' +
'<div style="font-size: 18px;font-weight: 800;color: var(--gray-900);">用傻瓜比价,找全网底价</div>' +
'</div>' +
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;width: 100%;" onclick="closeCelebrationModal()">选外卖平台开始体验</button>',
// V4 「行为优先」:承上完全收为一行小提示,起下并入按钮上方副文,主舞台让给行为
v4: '' +
'<div style="font-size: 11px;color: var(--gray-500);letter-spacing: 1px;text-align: center;margin-bottom: 8px;text-transform: uppercase;">SETUP COMPLETE</div>' +
'<div style="font-size: 24px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.25;margin-bottom: 8px;">选一个常用<br>外卖平台</div>' +
'<div style="font-size: 13px;color: var(--gray-600);text-align: center;margin-bottom: 24px;">即可开启傻瓜式一键比价</div>' +
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;" onclick="closeCelebrationModal()">现在选择</button>',
// V5 「徽章+行动卡」:左对齐绿圆勾徽章承上,黄色行动卡承载"下一步 + 体验傻瓜式一键比价"
v5: '' +
'<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 16px;">' +
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 20px;height: 20px;border-radius: 50%;background: #22C55E;box-shadow: 0 0 0 3px rgba(34,197,94,.18);flex-shrink: 0;"><svg width="11" height="11" viewBox="0 0 10 10"><path d="M2.2 5.2l2 2 3.8-4.6" stroke="#fff" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span>' +
'<span style="font-size: 13px;color: var(--gray-700);font-weight: 600;">设置已完成</span>' +
'</div>' +
'<div style="position: relative;background: linear-gradient(135deg,#FFFDE7,#FFF3C4);border-radius: 14px;padding: 24px 16px 16px;margin: 12px 0 16px;border: 1.5px solid #FFE082;text-align: center;">' +
'<div style="position: absolute;top: -12px;left: 50%;transform: translateX(-50%);font-size: 11px;color: #F57F17;font-weight: 800;background: #fff;padding: 4px 12px;border-radius: 32px;letter-spacing: .6px;border: 1.5px solid #FFE082;white-space: nowrap;">下一步</div>' +
'<div style="font-size: 20px;font-weight: 800;color: var(--gray-900);line-height: 1.3;">用傻瓜比价,找全网底价</div>' +
'</div>' +
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;width: 100%;" onclick="closeCelebrationModal()">选外卖平台开始体验</button>',
// V6 「进度条」:完成段绿+待办段黄色脉动,强化推进感
v6: '' +
'<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 12px;">' +
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 20px;height: 20px;border-radius: 50%;background: #22C55E;box-shadow: 0 0 0 3px rgba(34,197,94,.18);flex-shrink: 0;"><svg width="11" height="11" viewBox="0 0 10 10"><path d="M2.2 5.2l2 2 3.8-4.6" stroke="#fff" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span>' +
'<span style="font-size: 13px;color: var(--gray-700);font-weight: 600;">设置已完成</span>' +
'</div>' +
'<div style="display: flex;align-items: center;gap: 6px;margin-bottom: 24px;">' +
'<div style="flex: 1;height: 6px;border-radius: 4px;background: #22C55E;"></div>' +
'<div style="flex: 1;height: 6px;border-radius: 4px;background: linear-gradient(90deg,#FFD600,#FFB300);box-shadow: 0 0 10px rgba(255,214,0,.55);animation: gvBob 1.6s ease-in-out infinite;"></div>' +
'</div>' +
'<div style="font-size: 13px;color: #F57F17;font-weight: 800;text-align: center;margin-bottom: 6px;letter-spacing: .5px;">最后一步</div>' +
'<div style="font-size: 22px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.3;margin-bottom: 24px;">选个常用平台</div>' +
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;width: 100%;" onclick="closeCelebrationModal()">立即选择</button>',
// V7 「数字步骤」:① 已完成 → ② 当前 双步骤连线,明确流程位置
v7: '' +
'<div style="display: flex;align-items: center;justify-content: center;gap: 8px;margin-bottom: 24px;">' +
'<div style="display: flex;align-items: center;gap: 6px;opacity: .85;">' +
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 20px;height: 20px;border-radius: 50%;background: #22C55E;flex-shrink: 0;"><svg width="11" height="11" viewBox="0 0 10 10"><path d="M2.2 5.2l2 2 3.8-4.6" stroke="#fff" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span>' +
'<span style="font-size: 12px;color: var(--gray-500);font-weight: 600;">设置完成</span>' +
'</div>' +
'<div style="width: 20px;height: 2px;background: var(--gray-200);border-radius: 4px;"></div>' +
'<div style="display: flex;align-items: center;gap: 6px;">' +
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 20px;height: 20px;border-radius: 50%;background: var(--primary);color: #1a1a1a;font-size: 12px;font-weight: 800;flex-shrink: 0;box-shadow: 0 0 0 3px rgba(255,214,0,.25);">2</span>' +
'<span style="font-size: 12px;color: var(--gray-900);font-weight: 700;">选平台</span>' +
'</div>' +
'</div>' +
'<div style="font-size: 22px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.3;margin-bottom: 8px;">选个常用外卖平台</div>' +
'<div style="font-size: 13px;color: var(--gray-600);text-align: center;margin-bottom: 24px;">即可开启傻瓜式一键比价</div>' +
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;display: flex;align-items: center;justify-content: center;gap: 6px;width: 100%;" onclick="closeCelebrationModal()">选择平台<span style="font-size: 18px;line-height: 1;">→</span></button>',
// V8 「极简专注」:单行小绿勾承上,舞台全部让给主标题
v8: '' +
'<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 24px;">' +
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 20px;height: 20px;border-radius: 50%;background: #22C55E;box-shadow: 0 0 0 3px rgba(34,197,94,.18);flex-shrink: 0;"><svg width="11" height="11" viewBox="0 0 10 10"><path d="M2.2 5.2l2 2 3.8-4.6" stroke="#fff" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span>' +
'<span style="font-size: 13px;color: var(--gray-600);font-weight: 500;">设置已完成</span>' +
'</div>' +
'<div style="font-size: 24px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.25;margin-bottom: 8px;letter-spacing: -.3px;">选个常用平台</div>' +
'<div style="font-size: 14px;color: var(--gray-600);text-align: center;margin-bottom: 24px;line-height: 1.5;">现在体验<span style="font-weight: 700;color: var(--gray-900);background: linear-gradient(to top,var(--primary) 40%,transparent 40%);padding: 0 2px;">傻瓜式一键比价</span></div>' +
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;width: 100%;" onclick="closeCelebrationModal()">开始体验</button>',
// V9 「iOS 极简·一图一字一按钮」:80px 大圆勾 + 大字标题 + 单按钮,零嵌套盒子
v9: '' +
'<div style="display: flex;justify-content: center;margin: 6px 0 16px;">' +
'<div style="width: 80px;height: 80px;border-radius: 50%;background: linear-gradient(135deg,#34D399,#10B981);display: flex;align-items: center;justify-content: center;box-shadow: 0 10px 28px rgba(16,185,129,.35), 0 0 0 8px rgba(16,185,129,.10);animation: gvPop .5s cubic-bezier(.34,1.56,.64,1) both;">' +
'<svg width="42" height="42" viewBox="0 0 42 42" fill="none">' +
'<path d="M11 21.5 L18 28.5 L31.5 14.5" stroke="#fff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>' +
'</svg>' +
'</div>' +
'</div>' +
'<div style="font-size: 24px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.3;margin-bottom: 8px;letter-spacing: -.3px;">就差最后一步</div>' +
'<div style="font-size: 14px;color: var(--gray-600);text-align: center;line-height: 1.55;margin-bottom: 24px;">选个常用平台 · 立刻体验傻瓜式一键比价</div>' +
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;font-weight: 700;" onclick="closeCelebrationModal()">选外卖平台开始体验</button>',
// V10 「Stripe / Linear 风」:左对齐、小绿勾 + 大字 + 黑底按钮,冷峻 SaaS 调性
v10: '' +
'<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 24px;">' +
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 18px;height: 18px;border-radius: 50%;background: #10B981;flex-shrink: 0;"><svg width="10" height="10" viewBox="0 0 10 10"><path d="M2.2 5.2l2 2 3.8-4.6" stroke="#fff" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span>' +
'<span style="font-size: 12px;color: var(--gray-500);font-weight: 500;letter-spacing: .3px;">Setup complete</span>' +
'</div>' +
'<div style="font-size: 28px;font-weight: 800;color: var(--gray-900);line-height: 1.2;margin-bottom: 8px;letter-spacing: -.6px;">选个常用<br>外卖平台</div>' +
'<div style="font-size: 14px;color: var(--gray-600);line-height: 1.55;margin-bottom: 24px;">即可开启傻瓜式一键比价 — AI 会自动跨平台比价、领券、下单。</div>' +
'<button style="background: #1A1A1A;color: #fff;border: none;border-radius: 14px;font-size: 15px;height: 50px;width: 100%;font-weight: 600;display: flex;align-items: center;justify-content: center;gap: 8px;cursor: pointer;" onclick="closeCelebrationModal()">' +
'<span>开始体验</span>' +
'<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 7h8m0 0l-3.5-3.5M11 7l-3.5 3.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
'</button>',
// V11 「沉浸彩屏 hero」:负 margin 把顶部 bleed 成黄色渐变 hero,礼包大图标占主舞台,电商喜庆调性
v11: '' +
'<div style="margin: -28px -22px 16px;border-radius: 24px 24px 0 0;background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 55%,#fff 100%);padding: 32px 24px 16px;text-align: center;position: relative;overflow: hidden;">' +
'<div style="position: absolute;top: -30px;left: -30px;width: 120px;height: 120px;border-radius: 50%;background: radial-gradient(circle,rgba(255,255,255,.6),transparent 70%);"></div>' +
'<div style="position: absolute;bottom: -40px;right: -30px;width: 140px;height: 140px;border-radius: 50%;background: radial-gradient(circle,rgba(255,179,0,.25),transparent 70%);"></div>' +
'<div style="width: 96px;height: 96px;margin: 0 auto 12px;position: relative;animation: gvPop .55s cubic-bezier(.34,1.56,.64,1) both;">' +
'<div style="position: absolute;inset: 0;border-radius: 50%;background: radial-gradient(circle,rgba(255,255,255,.85) 0%,rgba(255,255,255,0) 70%);"></div>' +
'<div style="position: absolute;inset: 6px;border-radius: 50%;background: linear-gradient(135deg,#FFD600 0%,#FF9800 100%);display: flex;align-items: center;justify-content: center;box-shadow: 0 14px 32px rgba(255,152,0,.45), inset 0 -6px 14px rgba(0,0,0,.08);">' +
'<span style="font-size: 46px;line-height: 1;filter: drop-shadow(0 2px 4px rgba(0,0,0,.15));">🎁</span>' +
'</div>' +
'</div>' +
'<div style="display: inline-block;font-size: 11px;font-weight: 800;color: #D84315;letter-spacing: 1.2px;background: #fff;padding: 4px 12px;border-radius: 32px;margin-bottom: 8px;box-shadow: 0 2px 6px rgba(216,67,21,.18);">SETUP COMPLETE</div>' +
'<div style="font-size: 24px;font-weight: 900;color: var(--gray-900);line-height: 1.25;letter-spacing: -.3px;">傻瓜比价 · 准备就绪</div>' +
'</div>' +
'<div style="font-size: 14px;color: var(--gray-600);text-align: center;line-height: 1.55;margin-bottom: 16px;">选个常用平台 · 立刻领券一键比价</div>' +
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 52px;width: 100%;font-weight: 700;box-shadow: 0 8px 22px rgba(255,179,0,.42);display: flex;align-items: center;justify-content: center;gap: 6px;" onclick="closeCelebrationModal()">' +
'<span>选外卖平台开始体验</span><span style="font-size: 18px;line-height: 1;">→</span>' +
'</button>',
// V12 「步骤推进 2/2」:顶部细进度条 100% + 双步骤指示,强化"最后一步"流程感
v12: '' +
'<div style="display: flex;align-items: center;gap: 8px;margin-bottom: 8px;">' +
'<div style="font-size: 11px;font-weight: 700;color: var(--gray-500);letter-spacing: .4px;">2 / 2</div>' +
'<div style="flex: 1;height: 5px;border-radius: 4px;background: var(--gray-200);overflow: hidden;display: flex;">' +
'<div style="flex: 1;background: #10B981;border-radius: 4px 0 0 4px;"></div>' +
'<div style="flex: 1;background: linear-gradient(90deg,var(--primary),#FFB300);border-radius: 0 4px 4px 0;box-shadow: 0 0 8px rgba(255,179,0,.5);animation: gvBob 1.6s ease-in-out infinite;"></div>' +
'</div>' +
'</div>' +
'<div style="display: flex;align-items: center;gap: 6px;margin-bottom: 24px;font-size: 11px;">' +
'<span style="display: inline-flex;align-items: center;justify-content: center;width: 13px;height: 13px;border-radius: 50%;background: #10B981;flex-shrink: 0;"><svg width="8" height="8" viewBox="0 0 10 10"><path d="M2.2 5.2l2 2 3.8-4.6" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span>' +
'<span style="color: var(--gray-500);font-weight: 500;">设置完成</span>' +
'<span style="color: var(--gray-300);margin: 0 2px;"></span>' +
'<span style="color: var(--coin);font-weight: 800;letter-spacing: .2px;">现在选平台</span>' +
'</div>' +
'<div style="font-size: 24px;font-weight: 800;color: var(--gray-900);text-align: center;line-height: 1.25;margin-bottom: 8px;letter-spacing: -.3px;">就差最后一步</div>' +
'<div style="font-size: 14px;color: var(--gray-600);text-align: center;line-height: 1.55;margin-bottom: 24px;">选个常用平台开启<span style="font-weight: 700;color: var(--gray-900);">傻瓜式一键比价</span></div>' +
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;font-weight: 700;display: flex;align-items: center;justify-content: center;gap: 6px;" onclick="closeCelebrationModal()">' +
'<span>立即选择</span><span style="font-size: 18px;line-height: 1;">→</span>' +
'</button>'
};
var currentCelebrationVariant = 'v1';
var celebrationModalHTML = celebrationVariants[currentCelebrationVariant];
function openCelebrationModal() {
document.getElementById('celebrationModalCard').innerHTML = celebrationVariants[currentCelebrationVariant] || celebrationVariants.v1;
document.getElementById('celebrationModal').style.display = 'flex';
if (typeof fireConfetti === 'function') {
fireConfetti();
}
}
function closeCelebrationModal() {
document.getElementById('celebrationModal').style.display = 'none';
}
function onOverlayRejectClick(e) {
e.stopPropagation();
go('permission-step2');
// 权限未开启 → 弹出提示弹窗
setTimeout(function() { openSafetyModal('悬浮窗'); }, 300);
}
// 礼花彩纸特效 — 从顶部散落的彩色纸片
function fireConfetti() {
var container = document.getElementById('app');
var colors = ['#FFD600', '#FF5722', '#4CAF50', '#2196F3', '#E91E63', '#FF9800', '#9C27B0', '#00BCD4'];
for (var i = 0; i < 60; i++) {
var particle = document.createElement('div');
var color = colors[Math.floor(Math.random() * colors.length)];
var w = Math.random() * 6 + 4;
var h = Math.random() * 14 + 8;
var left = Math.random() * 100;
var dx = (Math.random() - 0.5) * 100;
var dy = 700 + Math.random() * 200;
var spin = (Math.random() - 0.5) * 1440;
var delay = Math.random() * 0.6;
var duration = Math.random() * 1.5 + 1.5;
particle.style.cssText = 'position:absolute;width:' + w + 'px;height:' + h + 'px;background:' + color + ';border-radius:1px;left:' + left + '%;top:-20px;z-index:9999;pointer-events:none;opacity:1;animation:confettiFloat ' + duration + 's ease-in ' + delay + 's forwards;--dx:' + dx + 'px;--dy:' + dy + 'px;--spin:' + spin + 'deg;';
container.appendChild(particle);
(function(p, t) { setTimeout(function() { p.remove(); }, t); })(particle, (duration + delay) * 1000 + 100);
}
}
// 权限检测 → 两个都开启才能进入下一步
function checkPermAndGo() {
var accDone = document.getElementById('accessibilityBtn').disabled;
var ovlDone = document.getElementById('overlayBtn').disabled;
if (accDone && ovlDone) {
go('productselect');
} else {
showToast('请先完成前置步骤再继续');
}
}
// Toast 提示:对齐 DESIGN.md patterns.toast
function showCenteredToast(msg) {
var existing = document.getElementById('globalToast');
if (existing) existing.remove();
var toast = document.createElement('div');
toast.id = 'globalToast';
toast.textContent = msg;
toast.style.cssText = 'position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);max-width:310px;background:rgba(0,0,0,.78);color:#fff;font-size:14px;font-weight:400;line-height:20px;padding:12px 20px;border-radius:10px;z-index:9999;text-align:center;pointer-events:none;opacity:1;transition:opacity .25s;white-space:nowrap;';
document.getElementById('app').appendChild(toast);
setTimeout(function() { toast.style.opacity = '0'; }, 1500);
setTimeout(function() { toast.remove(); }, 1800);
}
function showToast(msg) { showCenteredToast(msg); }
function showFeedbackReturnToast(msg) { showCenteredToast(msg); }
// 从意见反馈页提交后回流:在「我的」页落地弹一次 toast
// 用 pageshow 是因为 history/back-forward cache 恢复时 DOMContentLoaded 不会重跑
window.addEventListener('pageshow', function() {
var submitted = /(?:\?|&)feedback=1(?:&|$)/.test(window.location.search);
try { submitted = submitted || localStorage.getItem('proto_feedbackSubmitted') === '1'; } catch(e) {}
if (!submitted) return;
try { localStorage.removeItem('proto_feedbackSubmitted'); } catch(e) {}
if (window.history && typeof window.history.replaceState === 'function') {
window.history.replaceState(null, '', window.location.pathname + window.location.hash);
}
setTimeout(function() {
showFeedbackReturnToast('提交成功,感谢反馈');
}, 350);
});
// 登录状态 —— webview 改造:优先取原生桥登录态,无桥(浏览器调试)回退 localStorage
let isLoggedIn = (window.SGBridge ? !!SGBridge.getAuthState().loggedIn
: (typeof localStorage !== 'undefined' && localStorage.getItem('proto_isLoggedIn') !== 'false'));
// ===== webview 改造(阶段0):我的页真实数据接入 =====
// 战绩卡(累计可省/完成比价/赚取金币)从 app-server 真接口拉;无桥/无后端环境静默降级,保留原型 mock 展示。
function sgFmtYuan(cents){ return (Number(cents||0)/100).toLocaleString('zh-CN',{minimumFractionDigits:2,maximumFractionDigits:2}); }
// 【临时调试浮层 — 诊断数据接通,定位后删】顶部黑条显示登录态/token/各接口结果
// sgDbg:诊断输出改走 console.log → WebChromeClient 落 logcat "[H5]",不再在屏上画黑底绿字浮层。
// (顶部满屏后该浮层会顶到屏幕最上沿露脸;排 #1「数据没显示」仍可凭 logcat 里的 [sgDbg] 行诊断。)
function sgDbg(m){ try{ console.log('[sgDbg] '+m); }catch(e){} }
// 路①修重复刷新:切回本 tab 时 onResume 有多个触发源(NavBackStackEntry lifecycle + 宿主 LaunchedEffect),
// 真机实测 ~27ms 内连调 loadMineData 2 次(重复拉 3 接口 + 刷 DOM)。这里加时间去重:800ms 内重复调用只跑一次;
// 正常切回/回前台(间隔 >800ms)不受影响,仍会刷新最新数据。
var _loadMineLast = 0;
function loadMineData(){
var _now = Date.now();
if (_now - _loadMineLast < 800) { sgDbg('loadMineData 去重跳过('+(_now-_loadMineLast)+'ms)'); return; }
_loadMineLast = _now;
if (!window.SGApi || !window.SGBridge) { sgDbg('无 SGApi/SGBridge(非 webview 环境)'); return; }
var auth = SGBridge.getAuthState();
sgDbg('loggedIn='+(auth&&auth.loggedIn)+' nick='+(auth&&auth.nickname)+' token='+((SGBridge.getToken()||'(空)').slice(0,12))+'...');
if (!auth || !auth.loggedIn) { sgDbg('→ 未登录,停止拉数据'); return; }
if (auth.nickname){ var n=document.getElementById('profName'); if(n){ n.textContent=auth.nickname; n.setAttribute('data-fullname', auth.nickname); } }
// 真实头像(仅 http(s) 远程;本地 content:// URI WebView 加载受限 → 保留默认卡通头像)
if (auth.avatarUrl && /^https?:/.test(auth.avatarUrl)){ var av=document.querySelector('#profileLogged .prof-avatar'); if(av){ av.innerHTML='<img src="'+auth.avatarUrl+'" style="width:100%;height:100%;border-radius:50%;object-fit:cover" onerror="this.style.display=\'none\'">'; } }
// 累计发现可省(主额) + 完成比价次数 + 锁定态 ← /compare/stats(comparison_record 比价口径,
// 对齐原生 ProfileViewModel:比价就计、不要求下单。原 /savings/* 是下单成交口径,会误锁,已换。
SGApi.get('/compare/stats').then(function(s){
sgDbg('compare/stats OK compare_count='+(s&&s.compare_count)+' discovered_saved='+(s&&s.discovered_saved_cents));
if(!s) return;
var amt=document.querySelector('#profSavingsCard .prof-amount');
if(amt) amt.innerHTML='<span class="prof-currency">¥</span>'+sgFmtYuan(s.discovered_saved_cents);
var nums=document.querySelectorAll('#profSavingsCard .prof-stat-num'); // [0]领券 [1]完成比价 [2]赚取金币
if(nums[1]) nums[1].innerHTML=(s.compare_count||0)+'<span class="prof-stat-unit">次</span>';
if(typeof applySavingsLock==='function') applySavingsLock((s.compare_count||0)===0);
}).catch(function(e){ sgDbg('compare/stats ERR: '+(e&&e.message)); });
// 累计赚取金币
SGApi.get('/wallet/account').then(function(a){
if(!a) return;
var nums=document.querySelectorAll('#profSavingsCard .prof-stat-num');
if(nums[2]) nums[2].innerHTML=(a.total_coin_earned||0)+'<span class="prof-stat-unit">个</span>';
}).catch(function(){});
// 领取优惠券张数
SGApi.get('/coupon/stats').then(function(c){
if(!c) return;
var nums=document.querySelectorAll('#profSavingsCard .prof-stat-num');
if(nums[0]) nums[0].innerHTML=(c.coupon_count||0)+'<span class="prof-stat-unit">张</span>';
}).catch(function(){});
}
document.addEventListener('DOMContentLoaded', loadMineData);
if (window.SGBridge){
SGBridge.on('onResume', loadMineData); // 回前台重拉
SGBridge.on('onBalanceChange', loadMineData); // 余额变重拉
SGBridge.on('onAuthChange', function(){ try{ location.reload(); }catch(e){} }); // 登录态变整页刷新
// 未登录态 CTA 走原生登录:把 go('login') 接到极光一键登录(不改各处 onclick)
var _origGo=window.go;
window.go=function(id){ if(id==='login'){ SGBridge.requestLogin(); return; } if(typeof _origGo==='function') return _origGo.apply(this, arguments); };
}
// webview 样式校正(真 webview 或浏览器加 ?wv=1 预览):撑掉原型"手机壳"(.device 固定 375×812 居中)铺满 + 隐藏自带底栏。
// .device 用 position:fixed 钉满视口(不依赖 100vh,更稳);body 不动(fixed 脱离文档流,原 flex 居中对它无效)。
if (window.SGBridge || /[?&]wv=1/.test(location.search)){
var _wvCss=document.createElement('style');
_wvCss.textContent='html,body{background-color:#fff!important}.device{position:fixed!important;top:0!important;left:0!important;right:0!important;bottom:0!important;width:auto!important;height:auto!important;border-radius:0!important;box-shadow:none!important}.tab-bar{display:none!important}.prof-statusbar{display:none!important}.variant-panel{display:none!important}#debugBack{display:none!important}';
(document.head||document.documentElement).appendChild(_wvCss);
}
let loginFrom = (typeof localStorage !== 'undefined' && localStorage.getItem('proto_loginFrom')) || 'home';
let welfareVisited = (typeof localStorage !== 'undefined' && localStorage.getItem('proto_welfareVisited') === 'true');
let profileVisited = (typeof localStorage !== 'undefined' && localStorage.getItem('proto_profileVisited') === 'true');
// 新手礼包流程
let welcomeGiftShown = (typeof localStorage !== 'undefined' && localStorage.getItem('proto_welcomeGiftShown') === 'true');
let welcomeGiftClaimed = false;
let welfareCoinBalance = 28967;
let welfareCashBalance = 2.89;
let recordComparisonRewardClaimed = false;
let messageReminderRewardClaimed = false;
let videoRewardClaimed = false;
// 导航
// ===== 方案切换系统 =====
// 配置:在这里注册需要多方案对比的模块
// 格式:screenId: { current: 'a', options: { a: '方案名', b: '方案名' } }
// 方案A的screen id = 原id(如 productselect
// 方案B的screen id = 原id--b(如 productselect--b
// 方案C的screen id = 原id--c(如 productselect--c
// inPlace 模块:不换 screen,只跑 onChange 回调(用于原地切类名/样式)
const variants = {
'省钱战绩': {
inPlace: true,
current: 'unlocked',
options: { locked: '锁定', unlocked: '未锁定' },
onChange: function(v) { applySavingsLock(v === 'locked'); }
}
};
// 省钱战绩卡锁定/解锁:locked=盖不透明蒙层(未比价),unlocked=显示真实战绩
function applySavingsLock(locked) {
var card = document.getElementById('profSavingsCard');
if (!card) return;
card.classList.toggle('locked', !!locked);
}
function resolveScreenId(id) {
if (variants[id] && !variants[id].inPlace) {
const v = variants[id].current;
return v === 'a' ? id : id + '--' + v;
}
return id;
}
function switchVariant(moduleId, variant) {
if (!variants[moduleId]) return;
variants[moduleId].current = variant;
renderVariantPanel();
if (typeof variants[moduleId].onChange === 'function') {
variants[moduleId].onChange(variant);
}
if (variants[moduleId].inPlace) return;
// 如果当前正在看这个模块的某个方案,立即切换
const allScreens = document.querySelectorAll('.screen');
let isViewing = false;
allScreens.forEach(s => {
if (s.classList.contains('active') && (s.id === moduleId || s.id.startsWith(moduleId + '--'))) {
isViewing = true;
}
});
if (isViewing) go(moduleId);
}
function toggleVariantPanel() {
const p = document.getElementById('variantPanel');
p.classList.toggle('open');
if (p.classList.contains('open')) renderVariantPanel();
}
function renderVariantPanel() {
const list = document.getElementById('variantList');
const keys = Object.keys(variants);
if (keys.length === 0) {
list.innerHTML = '<div class="variant-empty">暂无多方案模块<br><span style="font-size: 11px;">在 variants 配置中添加模块即可</span></div>';
return;
}
list.innerHTML = keys.map(id => {
const v = variants[id];
const opts = Object.entries(v.options).map(([key, label]) =>
`<div class="variant-opt ${v.current===key?'active':''}" onclick="switchVariant('${id}','${key}')">${label}</div>`
).join('');
return `<div class="variant-module"><div class="variant-module-label">${id}</div><div class="variant-options">${opts}</div></div>`;
}).join('');
}
// 页面加载时初始化面板
document.addEventListener('DOMContentLoaded', renderVariantPanel);
// 调试:URL hash 直跳(如 #home / #welfare / #profile
document.addEventListener('DOMContentLoaded', function() {
var h = (location.hash || '').replace(/^#/, '');
if (h && document.getElementById(h)) {
setTimeout(function(){ try { go(h); } catch(e){} }, 80);
}
});
// ===== 用户案例翻页横幅 =====
var FLIP_AVATARS = ['🦊','🐱','🐶','🐻','🐼','🐨','🐯','🦁','🐮','🐷','🐸','🐵','🐔','🐧','🦆','🦅','🦉','🐺','🐗','🦄','🐝','🦋','🐞','🦜','🦩','🐢','🐙','🦀','🐠','🐬','🐳','🦈','🌸','🌻','🌺','🌷','🍎','🍑','🍓','🍉','🍊','🥭','🍇','🥝','🌶','🌮','🍔','🍕','🍜','🥟'];
var FLIP_BG = ['#FFE0B2','#FFCCBC','#FFAB91','#F8BBD0','#E1BEE7','#C5CAE9','#B3E5FC','#B2EBF2','#B2DFDB','#C8E6C9','#DCEDC8','#F0F4C3','#FFF59D','#FFE082','#FFCC80','#FFAB91','#BCAAA4','#CFD8DC','#FFCDD2','#D1C4E9'];
var FLIP_NAMES = [
'省钱小达人','抠门大魔王','优惠券猎人','比价老司机','折扣专家',
'拼单狂魔','薅羊毛达人','一只小鹿','花猫不喝酒','天天吃辣条',
'想变有钱人','哈哈哈是我','安静的咸鱼','奶茶续命中','干饭人本人',
'云上漫步者','向日葵不晒','糖醋排骨饭','北漂十年','打工累了',
'不熬夜星人','早睡早起队','宇宙小行星','深夜放毒','贪吃的橘子',
'永远不胖派','减肥进行时','咖啡因爱好者','下班想躺平','键盘侠本侠',
'佛系青年','努力上进鸡','摸鱼小能手','加班狗一只','周一不想动',
'周五最快乐','双十一战神','凑单小能手','满减狂魔','省一块是一块',
'外卖红包党','比价才下单','看完三家再买','不冲动消费','理智剁手党',
'存钱罐已满','月光警告','钱包瘦身中','大脑买买买','手刹车住'
];
var FLIP_VERBS = [
'通过比价省了','点外卖省了','刚省了','单笔省了','下单时省了',
'比价后省了','用券省了','薅到了','这单省了'
];
function buildFlipCases() {
var cases = [];
for (var i = 0; i < FLIP_NAMES.length; i++) {
var amount = (Math.random() * 27 + 3).toFixed(1); // 3.0 - 30.0
cases.push({
avatar: FLIP_AVATARS[i % FLIP_AVATARS.length],
bg: FLIP_BG[i % FLIP_BG.length],
name: FLIP_NAMES[i],
verb: FLIP_VERBS[i % FLIP_VERBS.length],
amount: amount,
});
}
// 洗牌一下避免按顺序露馅
for (var j = cases.length - 1; j > 0; j--) {
var k = Math.floor(Math.random() * (j + 1));
var t = cases[j]; cases[j] = cases[k]; cases[k] = t;
}
return cases;
}
function flipCaseHTML(c) {
return '<span class="flip-banner-avatar" style="background: ' + c.bg + '">' + c.avatar + '</span>'
+ '<span class="flip-banner-text"><span class="flip-name">' + c.name + '</span>' + c.verb + '<em>¥' + c.amount + '</em></span>';
}
var flipCases = [];
var flipIdx = 0;
var flipping = false;
function startFlipBanner() {
var banner = document.getElementById('flipBanner');
var front = document.getElementById('flipBannerFront');
var back = document.getElementById('flipBannerBack');
if (!banner || !front || !back) return;
flipCases = buildFlipCases();
front.innerHTML = flipCaseHTML(flipCases[0]);
back.innerHTML = flipCaseHTML(flipCases[1 % flipCases.length]);
setInterval(function() {
if (flipping) return;
flipping = true;
banner.classList.add('flipping');
setTimeout(function() {
flipIdx = (flipIdx + 1) % flipCases.length;
// 翻转完成后,把当前 back 内容搬到 front,瞬时复位(无 transition
front.innerHTML = flipCaseHTML(flipCases[flipIdx]);
var stage = document.getElementById('flipBannerStage');
stage.style.transition = 'none';
banner.classList.remove('flipping');
void stage.offsetWidth; // 强制重排
stage.style.transition = '';
back.innerHTML = flipCaseHTML(flipCases[(flipIdx + 1) % flipCases.length]);
flipping = false;
}, 560);
}, 2800);
}
document.addEventListener('DOMContentLoaded', startFlipBanner);
// 页面历史栈(同时驱动左下角调试按钮和页面内的「← 返回」按钮)
var screenHistory = ['splash'];
// 统一返回:pop 一格回到上一步,不再 push
function goBack() {
if (screenHistory.length <= 1) return; // 已经在起点,无效
screenHistory.pop();
var prev = screenHistory[screenHistory.length - 1];
_activateScreen(prev, /*pushHistory=*/false);
}
// 调试按钮(左下角)走同一逻辑
function debugGoBack() { goBack(); }
function openProfileCompareHistory() {
location.href = '../history/index.html?from=profile';
}
// 仅切换 DOM active 态(不触发登录拦截、不入栈),供 goBack 复用
function _activateScreen(resolvedId, pushHistory) {
document.querySelectorAll('.screen').forEach(function(s) { s.classList.remove('active'); });
document.getElementById(resolvedId).classList.add('active');
if (pushHistory && screenHistory[screenHistory.length - 1] !== resolvedId) {
screenHistory.push(resolvedId);
}
}
function go(id) {
// 未登录 + 首次进入福利/我的 → 先跳登录页
if (!isLoggedIn && id === 'welfare' && !welfareVisited) {
welfareVisited = true; try{localStorage.setItem('proto_welfareVisited','true');}catch(e){}
loginFrom='welfare'; try{localStorage.setItem('proto_loginFrom','welfare');}catch(e){}
id = 'login';
}
if (!isLoggedIn && id === 'profile' && !profileVisited) {
profileVisited = true; try{localStorage.setItem('proto_profileVisited','true');}catch(e){}
loginFrom='profile'; try{localStorage.setItem('proto_loginFrom','profile');}catch(e){}
id = 'login';
}
// 方案切换:解析实际 screen id
var resolvedId = resolveScreenId(id);
_activateScreen(resolvedId, /*pushHistory=*/true);
// 切换福利页登录态
if (id === 'welfare') {
document.getElementById('welfareUnlogged').style.display = isLoggedIn ? 'none' : 'block';
document.getElementById('welfareLogged').style.display = isLoggedIn ? 'block' : 'none';
updateWelfareCheckinTask();
if (isLoggedIn) {
animateWelfareAssetIntro();
}
if (isLoggedIn && !checkinDone && !checkinShown && !checkinPending) {
checkinPending = true;
setTimeout(function() {
checkinPending = false;
var active = document.querySelector('.screen.active');
if (isLoggedIn && !checkinDone && !checkinShown && active && active.id === 'welfare') {
checkinShown = true; try{localStorage.setItem('proto_checkinShown','true');}catch(e){}
showCheckinPopup();
}
}, 500);
}
}
// 切换我的页登录态
if (id === 'profile') {
document.getElementById('profileUnlogged').style.display = isLoggedIn ? 'none' : 'block';
document.getElementById('profileLogged').style.display = isLoggedIn ? 'block' : 'none';
}
if (id === 'productselect') { startPlatformScan(); }
if (id === 'celebResults' || id === 'celebration') { renderCelebrationSavings(); renderResults('celebResults'); startConfetti(); }
if (id === 'compresult') { renderResults('compResultList'); }
if (id === 'comparing') { startComparison(); }
if (id === 'home') { if (typeof renderTriClaim === 'function') renderTriClaim(); }
}
// 登录页返回 → 走统一的 goBack(pop 历史栈)
function loginGoBack() { goBack(); }
// ===== 签到弹窗 =====
const CHECKIN_MAX_DAY = 14;
const CHECKIN_REWARD_RULES = [
{ day: 1, amount: 180 },
{ day: 2, amount: 380 },
{ day: 3, amount: 220 },
{ day: 4, amount: 260 },
{ day: 5, amount: 320 },
{ day: 6, amount: 420 },
{ day: 7, amount: 888 },
{ day: 8, amount: 360 },
{ day: 9, amount: 460 },
{ day: 10, amount: 520 },
{ day: 11, amount: 680 },
{ day: 12, amount: 1088 },
{ day: 13, amount: 1688 },
{ day: 14, amount: 2888 },
];
const CHECKIN_REWARD_ASSETS = {
coin: '../../assets/welfare/index/checkin-coin-single.png',
coins: '../../assets/welfare/index/checkin-coins-600.png',
bigCoins: '../../assets/welfare/index/checkin-coins-3888.png',
chest: '../../assets/welfare/index/checkin-chest-8888.png'
};
let checkinShown = (typeof localStorage !== 'undefined' && localStorage.getItem('proto_checkinShown') === 'true');
let checkinPending = false;
let checkinDone = false;
let checkinCompletedBeforeToday = 2;
function getCheckinTodayDay() {
return Math.min(checkinCompletedBeforeToday + 1, CHECKIN_MAX_DAY);
}
function getCheckinCurrentStreak() {
return Math.min(checkinCompletedBeforeToday + (checkinDone ? 1 : 0), CHECKIN_MAX_DAY);
}
function getCheckinReward(day) {
var found = CHECKIN_REWARD_RULES.find(function(item) { return item.day === day; });
return found ? found.amount : 0;
}
function getCheckinMaxReward() {
return CHECKIN_REWARD_RULES.reduce(function(max, item) {
return Math.max(max, item.amount);
}, 0);
}
function getCheckinRewardAsset(day) {
var amount = getCheckinReward(day);
if (day === CHECKIN_MAX_DAY) return CHECKIN_REWARD_ASSETS.chest;
if (amount >= 1000) return CHECKIN_REWARD_ASSETS.bigCoins;
if (amount >= 680) return CHECKIN_REWARD_ASSETS.coins;
return CHECKIN_REWARD_ASSETS.coin;
}
function getCheckinLabel(day) {
var today = getCheckinTodayDay();
if (day === today) return '今天';
if (day === today + 1) return '明天';
return '第' + day + '天';
}
function getCheckinVisibleDays() {
var today = getCheckinTodayDay();
var days = [];
var start = Math.max(1, today - 2);
for (var day = start; day <= today; day++) days.push(day);
if (today < CHECKIN_MAX_DAY) days.push(today + 1);
[7, 14].some(function(milestone) {
if (milestone > today + 1) {
days.push(milestone);
return true;
}
return false;
});
for (var next = today + 2; next <= CHECKIN_MAX_DAY && days.length < 5; next++) {
days.push(next);
}
days = Array.from(new Set(days)).sort(function(a, b) { return a - b; });
while (days.length < 5 && days[0] > 1) {
days.unshift(days[0] - 1);
}
return days.slice(-5);
}
function getCheckinStep(day) {
var today = getCheckinTodayDay();
var completed = getCheckinCurrentStreak();
var isToday = day === today;
var isTomorrow = day === today + 1;
var isDone = day <= completed;
var isNextTarget = (!checkinDone && isToday) || (checkinDone && isTomorrow);
return {
day: day,
amount: getCheckinReward(day),
label: getCheckinLabel(day),
isDone: isDone,
isToday: isToday,
isTomorrow: isTomorrow,
isCurrent: isNextTarget,
isJustDone: checkinDone && isToday,
isMilestone: day === 7 || day === CHECKIN_MAX_DAY,
img: getCheckinRewardAsset(day)
};
}
function getCheckinSteps() {
return getCheckinVisibleDays().map(getCheckinStep);
}
function renderWelfareCheckinTimeline() {
var timeline = document.getElementById('r8CheckinTimeline');
if (!timeline) return;
timeline.innerHTML = getCheckinSteps().map(function(step) {
var classes = ['r8-checkin-step'];
if (step.isDone) classes.push('done');
if (step.isCurrent) classes.push('current');
if (step.isJustDone) classes.push('just-done');
if (step.day === CHECKIN_MAX_DAY) classes.push('most');
var top = step.isCurrent
? '<div class="r8-checkin-step-badge">' + (step.isTomorrow ? '明天' : '今天领') + '</div>'
: '<div class="r8-checkin-step-label">' + step.label + '</div>';
var icon = step.isDone
? '<div class="r8-checkin-step-icon"></div>'
: '<div class="r8-checkin-step-icon"><img src="' + step.img + '" alt=""></div>';
return '<div class="' + classes.join(' ') + '">' + top + icon + '<div class="r8-checkin-step-amount">' + step.amount + '</div></div>';
}).join('');
}
function renderCheckinPopupRewards() {
var rewards = document.getElementById('checkinRewards');
if (!rewards) return;
rewards.innerHTML = getCheckinSteps().map(function(step) {
var classes = ['checkin-reward-card'];
if (step.isDone) classes.push('claimed');
if (!step.isDone && step.isToday && !checkinDone) classes.push('current');
var icon = step.isDone
? '<div class="checkin-reward-icon">已领取</div>'
: '<div class="checkin-reward-icon"><img' + (step.day === CHECKIN_MAX_DAY ? ' class="icon-chest"' : '') + ' src="' + step.img + '" alt=""></div>';
return '<div class="' + classes.join(' ') + '">' + icon + '<div class="checkin-reward-amount">' + step.amount + '</div></div>';
}).join('');
}
function renderCheckinPopupProgress() {
var progress = document.getElementById('checkinProgress');
if (!progress) return;
progress.innerHTML = '<div class="checkin-progress-lines" id="checkinProgressLines"></div>' + getCheckinSteps().map(function(step) {
var classes = ['checkin-node'];
if (step.isDone) classes.push('done');
if (step.isCurrent) classes.push('current');
return '<div class="' + classes.join(' ') + '" data-day="' + step.day + '"><span class="checkin-dot"></span><span>' + step.label + '</span></div>';
}).join('');
}
function updateCheckinPopupCopy() {
var banner = document.getElementById('checkinBanner');
var title = document.getElementById('checkinPopupTitle');
var sub = document.getElementById('checkinPopupSub');
var btn = document.getElementById('checkinBtn');
var reminderBtn = document.getElementById('checkinReminderBtn');
var today = getCheckinTodayDay();
var streak = getCheckinCurrentStreak();
var todayReward = getCheckinReward(today);
var nextDay = Math.min(today + 1, CHECKIN_MAX_DAY);
var nextReward = getCheckinReward(nextDay);
if (banner) banner.innerHTML = '<span class="star"></span>连续签到14天 最高可领' + getCheckinMaxReward() + '金币';
if (title) title.textContent = checkinDone ? '今日金币已领取' : '签到领取今日金币';
if (sub) {
if (checkinDone && today >= CHECKIN_MAX_DAY) {
sub.innerHTML = '已完成 <b>14</b> 天签到,今日大奖已领取';
} else if (checkinDone) {
sub.innerHTML = '已连续签到 <b>' + streak + '</b> 天,明天可领 <b>' + nextReward + '</b> 金币';
} else {
sub.innerHTML = '已连续签到 <b>' + streak + '</b> 天,今天可领 <b>' + todayReward + '</b> 金币';
}
}
if (btn) {
btn.innerHTML = '签到领 <img src="' + CHECKIN_REWARD_ASSETS.coin + '" alt=""><b>' + todayReward + '</b>';
btn.style.display = checkinDone ? 'none' : 'flex';
}
if (reminderBtn) reminderBtn.style.display = checkinDone ? 'flex' : 'none';
}
function renderCheckinPopup() {
updateCheckinPopupCopy();
renderCheckinPopupRewards();
renderCheckinPopupProgress();
requestAnimationFrame(renderCheckinProgressLines);
}
function updateWelfareCheckinTask() {
var taskCard = document.getElementById('r8TaskCard');
var row = document.getElementById('r8CheckinTaskRow');
var recordBlock = document.getElementById('r8RecordTaskBlock');
var title = document.getElementById('r8CheckinTaskTitle');
var sub = document.getElementById('r8CheckinTaskSub');
var cta = document.getElementById('r8CheckinTaskCta');
var headline = document.getElementById('r8CheckinHeadline');
var cardCta = document.getElementById('r8CheckinCardCta');
if (!taskCard || !row || !recordBlock) return;
var today = getCheckinTodayDay();
var streak = getCheckinCurrentStreak();
var todayReward = getCheckinReward(today);
var nextDay = Math.min(today + 1, CHECKIN_MAX_DAY);
var nextReward = getCheckinReward(nextDay);
row.classList.toggle('is-done', checkinDone);
taskCard.insertBefore(row, recordBlock);
if (title) title.textContent = '新人签到领金币';
if (sub) {
sub.textContent = checkinDone
? (today >= CHECKIN_MAX_DAY ? '已完成14天签到,今日大奖已领取' : '已连续签到 ' + streak + ' 天,明天可领 ' + nextReward + ' 金币')
: '已连续签到 ' + streak + ' 天,今日可领 ' + todayReward + ' 金币';
}
if (cta) cta.textContent = checkinDone ? '去查看' : '去签到';
renderWelfareCheckinTimeline();
if (checkinDone) {
if (headline) headline.innerHTML = '已连续签到<span class="num">' + streak + '</span>天';
if (cardCta) cardCta.innerHTML = '<span class="check-tick">✓</span>今日已签';
} else {
if (headline) headline.textContent = '今日签到领金币';
if (cardCta) cardCta.textContent = '去签到';
}
}
function openCheckinTask() {
showCheckinPopup();
}
function renderCheckinProgressLines() {
var progress = document.getElementById('checkinProgress');
var lines = document.getElementById('checkinProgressLines');
if (!progress || !lines) return;
var nodes = Array.prototype.slice.call(progress.querySelectorAll('.checkin-node'));
if (nodes.length < 2) return;
lines.innerHTML = '';
var progressRect = progress.getBoundingClientRect();
var completed = getCheckinCurrentStreak();
var targetDay = checkinDone ? Math.min(getCheckinTodayDay() + 1, CHECKIN_MAX_DAY) : getCheckinTodayDay();
nodes.forEach(function(node, index) {
var next = nodes[index + 1];
if (!next) return;
var dot = node.querySelector('.checkin-dot');
var nextDot = next.querySelector('.checkin-dot');
if (!dot || !nextDot) return;
var dotRect = dot.getBoundingClientRect();
var nextDotRect = nextDot.getBoundingClientRect();
var x1Center = dotRect.left + dotRect.width / 2 - progressRect.left;
var x2Center = nextDotRect.left + nextDotRect.width / 2 - progressRect.left;
var dotRadius = dotRect.width / 2;
var nextDotRadius = nextDotRect.width / 2;
var day = Number(node.dataset.day || 0);
var nextDay = Number(next.dataset.day || 0);
var isDashed = nextDay - day > 1;
var x1 = isDashed ? x1Center + dotRadius : x1Center;
var x2 = isDashed ? x2Center - nextDotRadius : x2Center;
var width = Math.max(0, x2 - x1);
var color = (nextDay <= completed || nextDay === targetDay) ? '#FFB800' : '#D9D9D9';
var segment = document.createElement('span');
segment.className = 'checkin-segment ' + (isDashed ? 'dashed' : 'solid');
segment.style.left = x1 + 'px';
segment.style.width = width + 'px';
segment.style.setProperty('--line-color', color);
if (isDashed) {
var dashCount = 4;
var gap = Math.max(4, Math.min(5, width / 10));
var dash = Math.max(4, (width - gap * (dashCount + 1)) / dashCount);
for (var i = 0; i < dashCount; i++) {
var dashEl = document.createElement('i');
dashEl.style.cssText = 'position:absolute;top:0;height:3px;border-radius:99px;background:' + color + ';left:' + (gap + i * (dash + gap)) + 'px;width:' + dash + 'px;';
segment.appendChild(dashEl);
}
}
lines.appendChild(segment);
});
}
window.addEventListener('resize', function() {
var popup = document.getElementById('checkinPopup');
if (popup && getComputedStyle(popup).display !== 'none') renderCheckinProgressLines();
});
function showCheckinPopup() {
var popup = document.getElementById('checkinPopup');
if (!popup) return;
popup.style.display = 'flex';
renderCheckinPopup();
}
function closeCheckinPopup() {
document.getElementById('checkinPopup').style.display = 'none';
}
function doCheckin() {
if (checkinDone) return;
var todayReward = getCheckinReward(getCheckinTodayDay());
checkinDone = true;
updateWelfareCheckinTask();
renderCheckinPopup();
claimTaskReward('签到奖励', todayReward);
}
function doCheckinReminder() {
// 模拟权限弹窗
document.getElementById('calendarPermPopup').style.display = 'flex';
}
function closeCalendarPerm() {
document.getElementById('calendarPermPopup').style.display = 'none';
closeCheckinPopup();
}
// ===== 新手礼包 + 优惠券流程 =====
function showWelcomeGiftPopup() {
document.getElementById('welcomeGiftPopup').classList.add('show');
}
function openGiftBox() {
if (welcomeGiftClaimed) return;
var card = document.getElementById('welcomeGiftCard');
var chest = document.getElementById('giftChestEmoji');
var btn = document.getElementById('giftMainBtn');
// 阶段 A → B:宝箱开盖
card.classList.add('opening');
setTimeout(function() {
chest.textContent = '📦';
card.classList.remove('opening');
card.classList.add('opened');
flyCoinsToWelfareTab();
// 福利 tab 数字滚动 + badge + pulse
setTimeout(function() {
var tabItem = document.getElementById('homeTabWelfare');
var tabIcon = document.getElementById('homeTabWelfareIcon');
if (tabItem) {
// 临时提升 z-index 让 tab 浮在 overlay 之上
tabItem.style.position = 'relative';
tabItem.style.zIndex = '260';
}
if (tabIcon) {
tabIcon.classList.remove('tab-pulse');
// 触发重排以重启动画
void tabIcon.offsetWidth;
tabIcon.classList.add('tab-pulse');
}
var badge = document.getElementById('welfareTabBadge');
badge.classList.remove('show');
void badge.offsetWidth;
badge.classList.add('show');
// 余额在当前 mock 基数上累加新手礼包。
var coinStart = welfareCoinBalance;
var coinEnd = coinStart + 5000;
var cashEl = document.getElementById('welfareCashBalance');
var cashStart = parseFloat((cashEl && cashEl.textContent || '0').replace(/,/g, '')) || 0;
var cashEnd = cashStart + 0.5;
welfareCoinBalance = coinEnd;
welfareCashBalance = cashEnd;
animateNumber(document.getElementById('welfareCoinBalance'), coinStart, coinEnd, 1200, function(v) {
return v.toLocaleString();
});
animateNumber(cashEl, cashStart, cashEnd, 1200, function(v) {
return v.toFixed(2);
});
}, 600);
// 主按钮切换
btn.textContent = '开心收下,立即使用';
btn.onclick = claimGift;
}, 300);
}
function flyCoinsToWelfareTab() {
var card = document.getElementById('welcomeGiftCard');
var device = document.getElementById('app');
var tabIcon = document.getElementById('homeTabWelfareIcon');
if (!card || !device || !tabIcon) return;
var deviceRect = device.getBoundingClientRect();
var cardRect = card.getBoundingClientRect();
var tabRect = tabIcon.getBoundingClientRect();
// 宝箱中心相对于 device 的坐标
var startX = (cardRect.left + cardRect.width / 2) - deviceRect.left;
var startY = (cardRect.top + cardRect.height / 2) - deviceRect.top;
// 福利 tab 图标中心
var endX = (tabRect.left + tabRect.width / 2) - deviceRect.left;
var endY = (tabRect.top + tabRect.height / 2) - deviceRect.top;
var COIN_COUNT = 16;
for (var i = 0; i < COIN_COUNT; i++) {
var coin = document.createElement('div');
coin.className = 'fly-coin';
coin.textContent = '🪙';
// 起点定位(绝对定位 in device)
coin.style.left = startX + 'px';
coin.style.top = startY + 'px';
// burst 散射点(爆开瞬间)
var angle = (Math.PI * 2 * i) / COIN_COUNT + Math.random() * 0.4;
var burstDist = 60 + Math.random() * 60;
var bx = Math.cos(angle) * burstDist;
var by = Math.sin(angle) * burstDist - 30; // 略偏上
// 终点偏移(相对起点)
var tx = endX - startX + (Math.random() - 0.5) * 16;
var ty = endY - startY + (Math.random() - 0.5) * 8;
coin.style.setProperty('--bx', bx + 'px');
coin.style.setProperty('--by', by + 'px');
coin.style.setProperty('--tx', tx + 'px');
coin.style.setProperty('--ty', ty + 'px');
coin.style.setProperty('--d', (i * 18) + 'ms');
device.appendChild(coin);
// 动画结束后移除
coin.addEventListener('animationend', function() {
this.remove();
});
}
}
function animateWelfareAssetIntro() {
animateNumber(document.getElementById('welfareCoinBalance'), 0, welfareCoinBalance, 760, function(v) {
return Math.round(v).toLocaleString();
});
animateNumber(document.getElementById('welfareCashBalance'), 0, welfareCashBalance, 760, function(v) {
return v.toFixed(2);
});
}
function claimTaskReward(title, amount) {
var start = welfareCoinBalance;
welfareCoinBalance += amount;
animateNumber(document.getElementById('welfareCoinBalance'), start, welfareCoinBalance, amount >= 1000 ? 860 : 680, function(v) {
return Math.round(v).toLocaleString();
});
showRewardToast(title, amount);
}
function showRewardToast(title, amount) {
var existing = document.getElementById('rewardToast');
if (existing) existing.remove();
var toast = document.createElement('div');
toast.id = 'rewardToast';
toast.className = 'reward-toast';
var icon = document.createElement('img');
icon.className = 'reward-toast-icon';
icon.src = '../../assets/welfare/index/checkin-coins-600.png';
icon.alt = '';
var amountEl = document.createElement('div');
amountEl.className = 'reward-toast-amount';
amountEl.textContent = '+' + Math.round(amount).toLocaleString();
var titleEl = document.createElement('div');
titleEl.className = 'reward-toast-title';
titleEl.textContent = title;
toast.appendChild(icon);
toast.appendChild(amountEl);
toast.appendChild(titleEl);
document.getElementById('app').appendChild(toast);
setTimeout(function() {
toast.classList.add('is-leaving');
}, 1450);
setTimeout(function() {
if (toast.parentNode) toast.remove();
}, 1700);
}
function claimVideoReward() {
if (videoRewardClaimed) return;
videoRewardClaimed = true;
claimTaskReward('任务奖励', 1859);
var cta = document.getElementById('r8VideoTaskCta');
if (cta) {
cta.textContent = '已领取';
cta.classList.add('is-done');
cta.disabled = true;
}
}
function claimMessageReminderReward() {
if (messageReminderRewardClaimed) return;
messageReminderRewardClaimed = true;
claimTaskReward('任务奖励', 10000);
var cta = document.getElementById('r8MessageTaskCta');
var sub = document.getElementById('r8MessageTaskSub');
if (sub) sub.textContent = '消息提醒已开启';
if (cta) {
cta.textContent = '已开启';
cta.classList.add('is-done');
cta.disabled = true;
}
}
function claimRecordComparisonReward() {
if (recordComparisonRewardClaimed) return;
recordComparisonRewardClaimed = true;
var activeBox = document.querySelector('#r8RecordTaskBlock .r8-record-reward-box.active');
if (activeBox) {
activeBox.classList.remove('active');
activeBox.classList.add('done');
var status = activeBox.querySelector('.r8-record-status');
if (status) status.textContent = '已领取';
var coin = activeBox.querySelector('.r8-record-coin');
if (coin) coin.remove();
if (activeBox.tagName === 'BUTTON') {
activeBox.disabled = true;
activeBox.setAttribute('aria-label', '第2次记录比价奖励已领取180金币');
}
}
claimTaskReward('比价奖励', 180);
}
function animateNumber(el, from, to, duration, formatter) {
if (!el) return;
el.__animateNumberToken = (el.__animateNumberToken || 0) + 1;
var token = el.__animateNumberToken;
var start = performance.now();
function frame(now) {
if (token !== el.__animateNumberToken) return;
var t = Math.min(1, (now - start) / duration);
var eased = 1 - Math.pow(1 - t, 3); // ease-out cubic
var v = from + (to - from) * eased;
el.textContent = formatter ? formatter(v) : Math.round(v).toString();
if (t < 1) requestAnimationFrame(frame);
else el.textContent = formatter ? formatter(to) : to.toString();
}
requestAnimationFrame(frame);
}
function claimGift() {
welcomeGiftClaimed = true;
closeWelcomeGift(false);
}
function closeWelcomeGift(skipped) {
document.getElementById('welcomeGiftPopup').classList.remove('show');
// 还原 tab 的 z-index
var tabItem = document.getElementById('homeTabWelfare');
if (tabItem) {
tabItem.style.position = '';
tabItem.style.zIndex = '';
}
if (skipped) {
// 重置卡片为初始状态以备重弹(但目前 welcomeGiftShown 已 true,不会重弹)
var card = document.getElementById('welcomeGiftCard');
card.classList.remove('opened');
document.getElementById('giftChestEmoji').textContent = '🎁';
var btn = document.getElementById('giftMainBtn');
btn.textContent = '✨ 开启礼包';
btn.onclick = openGiftBox;
}
}
// ===== 登录流程 =====
let pendingLoginAction = null; // 记录待执行的登录动作
function showToast(msg) {
var t = document.getElementById('loginToast');
t.textContent = msg;
t.style.display = 'block';
setTimeout(function(){ t.style.display = 'none'; }, 2000);
}
function toggleAgreeCheck() {
var chk = document.getElementById('agreeCheck');
chk.classList.toggle('checked');
var hint = document.getElementById('agreeHint');
if (hint) hint.style.display = chk.classList.contains('checked') ? 'none' : 'block';
}
function toggleAgreeCheckCeleb() {
var chk = document.getElementById('agreeCheckCeleb');
chk.classList.toggle('checked');
}
function isAgreedCeleb() {
return document.getElementById('agreeCheckCeleb').classList.contains('checked');
}
function celebOnboardingLogin() {
if (!isAgreedCeleb()) { showAgreeModal('celeb-quick'); return; }
doLogin();
}
function togglePhoneAgree() {
var chk = document.getElementById('agreeCheckPhone');
chk.classList.toggle('checked');
}
function isAgreed() {
return document.getElementById('agreeCheck').classList.contains('checked');
}
function isPhoneAgreed() {
return document.getElementById('agreeCheckPhone').classList.contains('checked');
}
function showAgreeModal(action) {
pendingLoginAction = action;
document.getElementById('agreeModal').style.display = 'flex';
}
function closeAgreeModal() {
document.getElementById('agreeModal').style.display = 'none';
pendingLoginAction = null;
}
function agreeAndLogin() {
// 入口页(一键登录):勾选入口页协议并继续
var chk = document.getElementById('agreeCheck');
if (chk && !chk.classList.contains('checked')) chk.classList.add('checked');
// 祝贺页内嵌登录的协议同步勾选
var chkCeleb = document.getElementById('agreeCheckCeleb');
if (chkCeleb && !chkCeleb.classList.contains('checked')) chkCeleb.classList.add('checked');
document.getElementById('agreeModal').style.display = 'none';
if (pendingLoginAction === 'quick' || pendingLoginAction === 'celeb-quick') {
doLogin();
} else if (pendingLoginAction === 'phone') {
doPhoneLogin();
}
pendingLoginAction = null;
}
function showAgreePhoneModal() {
document.getElementById('agreePhoneModal').style.display = 'flex';
}
function closeAgreePhoneModal() {
document.getElementById('agreePhoneModal').style.display = 'none';
}
function agreeAndContinuePhone() {
var chkP = document.getElementById('agreeCheckPhone');
if (chkP && !chkP.classList.contains('checked')) chkP.classList.add('checked');
document.getElementById('agreePhoneModal').style.display = 'none';
doSendSms();
}
function doLogin() {
isLoggedIn = true; try{localStorage.setItem('proto_isLoggedIn','true');}catch(e){}
var target = loginFrom || 'home';
go(target);
// 主路径登录(不是从福利/我的回流的) + 首次 → 弹新手礼包
if (!welcomeGiftShown && target === 'home') {
welcomeGiftShown = true; try{localStorage.setItem('proto_welcomeGiftShown','true');}catch(e){}
setTimeout(showWelcomeGiftPopup, 400);
}
}
function onboardingLogin() {
if (!isAgreed()) { showAgreeModal('quick'); return; }
doLogin();
}
function showPhoneLogin() {
// 进入独立手机号登录页(Step1)
document.getElementById('lpStep1').style.display = 'block';
document.getElementById('lpStep2').style.display = 'none';
go('loginPhone');
setTimeout(function(){
var inp = document.getElementById('phoneInput');
if (inp) inp.focus();
}, 80);
}
function showQuickLogin() {
// 用于其他位置返回入口页(保留兼容)
if (smsTimer) { clearInterval(smsTimer); smsTimer = null; }
go('login');
}
function updatePhoneCta() {
var inp = document.getElementById('phoneInput');
var cta = document.getElementById('lpCta');
if (!inp || !cta) return;
if (inp.value.length >= 11) cta.classList.remove('disabled');
else cta.classList.add('disabled');
}
function backToPhoneStep1() {
document.getElementById('lpStep2').style.display = 'none';
document.getElementById('lpStep1').style.display = 'block';
if (smsTimer) { clearInterval(smsTimer); smsTimer = null; }
}
let smsTimer = null;
function doSendSms() {
var phone = document.getElementById('phoneInput').value;
if (phone.length < 11) { showToast('请输入正确的手机号'); return; }
// 显示手机号提示(脱敏)
var masked = phone.substring(0,3) + '****' + phone.substring(7);
document.getElementById('smsPhoneHint').textContent = '验证码已发送至 ' + masked;
// 切换到 Step2
document.getElementById('lpStep1').style.display = 'none';
document.getElementById('lpStep2').style.display = 'block';
// 清空验证码输入框
var boxes = document.getElementById('smsCodeBoxes').querySelectorAll('input');
boxes.forEach(function(b){ b.value = ''; });
boxes[0].focus();
// 倒计时
var btn = document.getElementById('smsBtn');
var sec = 60;
btn.style.color = 'var(--gray-400)';
btn.style.cursor = 'default';
btn.onclick = null;
btn.textContent = sec + 's 后重发';
smsTimer = setInterval(function(){
sec--;
if (sec <= 0) {
clearInterval(smsTimer);
smsTimer = null;
btn.style.color = '#FFD600';
btn.style.cursor = 'pointer';
btn.textContent = '重新发送';
btn.onclick = function(){ doSendSms(); };
} else {
btn.textContent = sec + 's 后重发';
}
}, 1000);
}
function sendSmsCode() {
// 手机号页有独立的协议勾选状态 + 独立居中弹窗
if (!isPhoneAgreed()) { showAgreePhoneModal(); return; }
doSendSms();
}
function smsCodeComplete() {
// 6位验证码全部填完,自动登录
var boxes = document.getElementById('smsCodeBoxes').querySelectorAll('input');
var code = '';
boxes.forEach(function(b){ code += b.value; });
if (code.length === 6) {
isLoggedIn = true; try{localStorage.setItem('proto_isLoggedIn','true');}catch(e){}
go(loginFrom || 'home');
}
}
// ===== 平台选择流程 =====
// 全量平台列表,外卖版优先;同系优先外卖版,有外卖版则隐藏主站版
const allApps = [
{ id: 'meituan-waimai', name: '美团', icon: '../../assets/shared/logos/meituan.png', color: '#FF6B00', bg: '#FFF3E0', desc: '外卖·美食·买菜', installed: true, replaces: 'meituan' },
{ id: 'taobao-shanguang', name: '淘宝', icon: '../../assets/shared/logos/taobao.png', color: '#FF6A00', bg: '#FFF3E0', desc: '外卖·超市·买药', installed: true, replaces: 'taobao' },
{ id: 'jd-waimai', name: '京东', icon: '../../assets/shared/logos/jd.png', color: '#E1251B', bg: '#FFEBEE', desc: '品质外卖·新人立减', installed: false, replaces: 'jd' },
{ id: 'meituan', name: '美团', icon: '../../assets/shared/logos/meituan.png', color: '#FFD600', bg: '#FFFDE7', desc: '团购·到店·买菜', installed: true },
{ id: 'taobao', name: '淘宝', icon: '../../assets/shared/logos/taobao.png', color: '#FF5000', bg: '#FFF3E0', desc: '网购·百亿补贴', installed: true },
{ id: 'jd', name: '京东', icon: '../../assets/shared/logos/jd.png', color: '#E1251B', bg: '#FFEBEE', desc: '又好又便宜', installed: true },
];
// 外卖版是这个产品的画布:只要 allApps 里有外卖版条目,就隐藏对应主站版(不论主站是否安装)。
// 未安装的外卖版仍然在列表里以 disabled 形态展示,强调"我们能比 3 个平台,但你少了 1 个"。
function getVisibleApps() {
const replacedIds = new Set(allApps.filter(a => a.replaces).map(a => a.replaces));
return allApps.filter(a => !replacedIds.has(a.id));
}
// 进入 productselect 时渲染平台列表
let platformScanDone = false;
function startPlatformScan() {
if (platformScanDone) return;
platformScanDone = true;
renderPlatformList();
startRewardCountdown();
}
function renderPlatformList() {
const visible = getVisibleApps();
// 已装 + 未装合并到同一列表,外形对齐,用样式区分 disabled 态
document.getElementById('installedApps').innerHTML = visible.map((app, i) => {
if (app.installed) {
return '' +
'<div onclick="selectPlatform(\'' + app.id + '\')" data-pcard="' + i + '" class="platform-card" style="background: #fff;border-radius: 14px;padding: 16px 16px;cursor: pointer;display: flex;align-items: center;gap: 12px;border: 1.5px solid var(--gray-200);margin-bottom: 8px;position: relative;transition: border-color .25s,box-shadow .25s,transform .15s;">' +
'<img src="' + app.icon + '" style="width: 48px;height: 48px;border-radius: 12px;flex-shrink: 0;object-fit: cover;" />' +
'<div style="flex: 1;min-width: 0;">' +
'<div style="font-size: 20px;font-weight: 700;color: var(--gray-900);letter-spacing: -.2px;">' + app.name + '</div>' +
'</div>' +
'<svg width="20" height="20" viewBox="0 0 20 20" fill="none" style="flex-shrink: 0;color: var(--gray-300);"><path d="M7.5 4.5l5.5 5.5-5.5 5.5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
'</div>';
}
return '' +
'<div class="platform-card-disabled" aria-disabled="true" onclick="onPlatformInstallClick(\'' + app.id + '\')" style="background: #FAFAFA;border-radius: 14px;padding: 16px 16px;cursor: pointer;display: flex;align-items: center;gap: 12px;border: 1.5px solid #ECECEC;margin-bottom: 8px;position: relative;">' +
'<img src="' + app.icon + '" style="width: 48px;height: 48px;border-radius: 12px;flex-shrink: 0;object-fit: cover;filter: grayscale(.7);opacity: .55;" />' +
'<div style="flex: 1;min-width: 0;">' +
'<div style="font-size: 20px;font-weight: 700;color: var(--gray-400);letter-spacing: -.2px;">' + app.name + '</div>' +
'</div>' +
'<span style="flex-shrink: 0;display: inline-flex;align-items: center;gap: 8px;">' +
'<span style="font-size: 15px;font-weight: 700;color: var(--gray-900);line-height: 1;">去安装</span>' +
'<svg width="20" height="20" viewBox="0 0 20 20" fill="none" style="color: var(--gray-300);"><path d="M7.5 4.5l5.5 5.5-5.5 5.5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
'</span>' +
'</div>';
}).join('');
// 旧的次级"未安装"分区不再使用
document.getElementById('notInstalledSection').style.display = 'none';
}
// 领券浮窗 / 比价浮窗顶部的平台进度 mini icons —— 只渲染已安装的平台
// states: { 'platform-id': 'done' | 'active' | 'pending' }
function renderFloatPlatforms(containerId, states) {
const container = document.getElementById(containerId);
if (!container) return;
const installed = getVisibleApps().filter(a => a.installed);
container.innerHTML = installed.map(app => {
const state = (states && states[app.id]) || 'pending';
return '<div class="cmp-platform-mini ' + state + '"><img src="' + app.icon + '" alt="' + app.name + '"/></div>';
}).join('');
}
// 一键领券弹窗 · 3 平台卡片渲染。已装:黄边 + ✓;未装(方案 C):灰底 + 黄圆 ↓ 角标
function couponChipShortName(name) {
return name.replace(/外卖$|闪购$/, '');
}
function renderCouponPromptPlatforms() {
const grid = document.getElementById('couponPlatformGrid');
if (!grid) return;
const platforms = getVisibleApps(); // 3 张外卖版卡片
grid.innerHTML = platforms.map(app => {
const shortName = couponChipShortName(app.name);
if (app.installed) {
return '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;">' +
'<img src="' + app.icon + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/>' +
'<div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + shortName + '</div>' +
'<span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;">' +
'<svg width="10" height="10" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg>' +
'</span>' +
'</div>';
}
return '<div class="cp-card-uninstalled" aria-disabled="true" style="background: #FAFAFA;border: 1.5px solid #ECECEC;border-radius: 14px;padding: 12px 4px 8px;position: relative;">' +
'<img src="' + app.icon + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;filter: grayscale(.7);opacity: .55;"/>' +
'<div style="font-size: 12px;font-weight: 700;color: #BBB;margin-top: 8px;">' + shortName + '</div>' +
'<span style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFD600;box-shadow: 0 0 0 1.5px rgba(255,179,0,.35);display: flex;align-items: center;justify-content: center;">' +
'<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M5 1.5v5.5m0 0L2.5 4.5M5 7l2.5-2.5M2 9h6" stroke="#1a1a1a" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
'</span>' +
'</div>';
}).join('');
}
let selectedAppForBubble = null;
function selectPlatform(platformId) {
const app = allApps.find(a => a.id === platformId);
if (!app) return;
selectedAppForBubble = app;
go('comparing');
}
// 未安装平台 → 跳应用市场(原型 stub)
function onPlatformInstallClick(platformId) {
const app = allApps.find(a => a.id === platformId);
if (!app) return;
console.log('[install] 跳应用市场下载:', app.name);
}
/* ===== 去点餐选平台弹窗(省钱战绩锁定态「立即开始」触发)===== */
function renderComparePickerPlatforms() {
var grid = document.getElementById('comparePickerGrid');
if (!grid || typeof getVisibleApps !== 'function') return;
grid.innerHTML = getVisibleApps().map(function(app) {
if (app.installed) {
return '<div class="home-picker-item" data-platform="' + app.name + '">' +
'<div class="home-picker-logo"><img src="' + app.icon + '" alt=""></div>' +
'<div class="home-picker-name">' + app.name + '</div></div>';
}
return '<div class="home-picker-item uninstalled" data-platform="' + app.name + '" data-uninstalled="true">' +
'<div class="home-picker-logo"><img src="' + app.icon + '" alt=""></div>' +
'<div class="home-picker-name">' + app.name + '</div>' +
'<span class="home-picker-install-chip">' +
'<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M5 1.5v5.5m0 0L2.5 4.5M5 7l2.5-2.5M2 9h6" stroke="#1a1a1a" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
'</span></div>';
}).join('');
}
function openComparePicker() {
renderComparePickerPlatforms();
var mask = document.getElementById('comparePickerMask');
if (mask) mask.classList.add('show');
}
function closeComparePicker() {
var mask = document.getElementById('comparePickerMask');
if (mask) mask.classList.remove('show');
}
(function() {
var mask = document.getElementById('comparePickerMask');
if (!mask) return;
mask.addEventListener('click', function(e) {
if (e.target === mask) { closeComparePicker(); return; }
var item = e.target.closest('.home-picker-item');
if (!item) return;
var nameEl = item.querySelector('.home-picker-name');
var name = nameEl ? nameEl.textContent : '';
closeComparePicker();
if (item.dataset.uninstalled === 'true') {
if (typeof showToast === 'function') showToast('请先安装「' + name + '」APP');
var app = (typeof allApps !== 'undefined') ? allApps.find(function(a){return a.name === name;}) : null;
if (app && typeof onPlatformInstallClick === 'function') onPlatformInstallClick(app.id);
} else {
if (typeof showToast === 'function') showToast('已跳「' + name + '」');
}
});
})();
// 省钱战绩锁定态初始化:按 variants['省钱战绩'].current 应用(默认未比价=锁定)
// 切换入口:左上角 ⚙ 方案切换面板 → 省钱战绩 → 锁定 / 未锁定
(function() {
function init() {
var mod = (typeof variants !== 'undefined') && variants['省钱战绩'];
applySavingsLock(mod ? mod.current === 'locked' : true);
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
else init();
})();
function showWelcomeBubble() {
const mask = document.getElementById('welcomeMask');
const bubble = document.getElementById('welcomeBubble');
const title = document.getElementById('welcomeTitle');
const app = selectedAppForBubble || { name: '美团' };
title.textContent = '已为您唤起' + app.name;
mask.style.display = 'block';
bubble.style.display = 'block';
// 强制重排,让初始 opacity:0 / scale .92 生效
void bubble.offsetWidth;
requestAnimationFrame(() => {
mask.style.opacity = '1';
bubble.style.opacity = '1';
bubble.style.transform = 'translate(-50%,-50%) scale(1)';
});
setTimeout(() => {
mask.style.opacity = '0';
bubble.style.opacity = '0';
setTimeout(() => {
mask.style.display = 'none';
bubble.style.display = 'none';
}, 450);
}, 2000);
}
// 红包倒计时
let countdownInterval;
let rewardPhase = 0; // 0=首次, 1=已过期, 2=二次机会
function startRewardCountdown() {
let total = 300; // 5分钟
rewardPhase = 0;
updateRewardCard('active');
runCountdown(total);
}
function runCountdown(totalSeconds) {
let remaining = totalSeconds * 10; // 1/10秒为单位
const el = document.getElementById('rewardCountdown');
if (!el) return;
clearInterval(countdownInterval);
countdownInterval = setInterval(() => {
remaining--;
if (remaining <= 0) {
clearInterval(countdownInterval);
remaining = 0;
onCountdownEnd();
}
const totalSec = Math.floor(remaining / 10);
const tenths = remaining % 10;
const m = String(Math.floor(totalSec / 60)).padStart(2, '0');
const s = String(totalSec % 60).padStart(2, '0');
el.textContent = m + ':' + s + '.' + tenths;
}, 100);
}
function onCountdownEnd() {
if (rewardPhase === 0) {
// 首次过期 → 显示过期状态
rewardPhase = 1;
updateRewardCard('expired');
// 2秒后给二次机会
setTimeout(() => {
rewardPhase = 2;
updateRewardCard('second-chance');
runCountdown(180); // 二次机会 3分钟
}, 2000);
} else {
// 二次也过期 → 最终过期
updateRewardCard('final-expired');
}
}
function updateRewardCard(state) {
const card = document.getElementById('rewardCard');
if (!card) return;
if (state === 'active') {
card.style.background = 'linear-gradient(135deg,#FFF8E1,#FFECB3)';
card.style.opacity = '1';
card.innerHTML = `
<div style="flex-shrink: 0;font-size: 36px;line-height: 1;">🧧</div>
<div style="flex: 1;">
<div style="font-size: 14px;font-weight: 700;color: var(--gray-900);">完成首次比价领红包奖励</div>
</div>`;
} else if (state === 'expired') {
card.style.background = 'var(--gray-100)';
card.style.opacity = '.6';
card.innerHTML = `
<div style="flex-shrink: 0;font-size: 36px;line-height: 1;filter: grayscale(1);">🧧</div>
<div style="flex: 1;">
<div style="font-size: 14px;font-weight: 700;color: var(--gray-500);">红包已过期</div>
<div style="font-size: 12px;color: var(--gray-400);margin-top: 2px;">很遗憾,活动已结束</div>
</div>`;
} else if (state === 'second-chance') {
card.style.background = 'linear-gradient(135deg,#FFEBEE,#FFCDD2)';
card.style.opacity = '1';
card.innerHTML = `
<div style="flex-shrink: 0;font-size: 36px;line-height: 1;">🎁</div>
<div style="flex: 1;">
<div style="font-size: 14px;font-weight: 700;color: #E53935;">再给你一次机会!</div>
<div style="font-size: 12px;color: #FF5722;font-weight: 600;margin-top: 2px;">最后 <span id="rewardCountdown">03:00.0</span></div>
</div>`;
} else if (state === 'final-expired') {
card.style.background = 'var(--gray-100)';
card.style.opacity = '.5';
card.innerHTML = `
<div style="flex-shrink: 0;font-size: 36px;line-height: 1;filter: grayscale(1);">🧧</div>
<div style="flex: 1;">
<div style="font-size: 14px;font-weight: 600;color: var(--gray-400);">新人红包奖励已过期</div>
</div>`;
}
}
// 卡片轮流高亮
let cardRotationInterval;
function startCardRotation(count) {
let active = 0;
function highlight() {
document.querySelectorAll('[data-pcard]').forEach((el, i) => {
if (i === active) {
el.style.borderColor = '#FF5722';
el.style.boxShadow = '0 0 0 1px #FF5722';
el.querySelector('.tap-hand-icon').style.opacity = '1';
el.querySelector('.tap-hand-icon').classList.add('tap-hand');
} else {
el.style.borderColor = 'var(--gray-200)';
el.style.boxShadow = 'none';
el.querySelector('.tap-hand-icon').style.opacity = '0';
el.querySelector('.tap-hand-icon').classList.remove('tap-hand');
}
});
active = (active + 1) % count;
}
highlight();
clearInterval(cardRotationInterval);
cardRotationInterval = setInterval(highlight, 2100);
}
// 省钱数字滚动动画(已弃用但保留兼容)
function animateSavingCounter() {
const el = document.getElementById('savingCounter');
const target = 12847;
const duration = 1500;
const start = performance.now();
function tick(now) {
const p = Math.min((now - start) / duration, 1);
const ease = 1 - Math.pow(1 - p, 3);
el.textContent = Math.floor(target * ease).toLocaleString();
if (p < 1) requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
}
// 商品点击 → 过渡提示 → 进入比价(兼容旧调用)
function startProductCompare() {
selectPlatform('meituan-waimai');
}
// ===== 反馈面板 =====
function openFeedbackSheet() {
const sheet = document.getElementById('feedbackSheet');
// 重置到步骤1
document.getElementById('fbStep1').style.display = 'block';
document.getElementById('fbFormLower').style.display = 'none';
document.getElementById('fbFormWrong').style.display = 'none';
document.getElementById('fbSuccess').style.display = 'none';
// 动态生成平台选项(仅显示 found/same-price 的平台)
const pl = document.getElementById('fbPlatformList');
if (pl) {
pl.innerHTML = results.filter(r => r.status !== 'not-found').map(r =>
`<div class="fb-platform" onclick="this.classList.toggle('selected')" style="padding: 8px 16px;border: 1.5px solid var(--gray-200);border-radius: 32px;font-size: 13px;font-weight: 600;cursor: pointer;display: flex;align-items: center;gap: 4px;"><img src="${r.platformIcon}" style="width: 16px;height: 16px;border-radius: 4px;"> ${r.platform}</div>`
).join('');
}
sheet.style.display = 'block';
}
function closeFeedbackSheet() {
document.getElementById('feedbackSheet').style.display = 'none';
}
function selectFbType(type) {
document.getElementById('fbStep1').style.display = 'none';
if (type === 'lower_price') {
document.getElementById('fbFormLower').style.display = 'block';
} else {
document.getElementById('fbFormWrong').style.display = 'block';
}
}
function backToFbStep1() {
document.getElementById('fbFormLower').style.display = 'none';
document.getElementById('fbFormWrong').style.display = 'none';
document.getElementById('fbStep1').style.display = 'block';
}
function submitFeedback() {
document.getElementById('fbFormLower').style.display = 'none';
document.getElementById('fbFormWrong').style.display = 'none';
document.getElementById('fbSuccess').style.display = 'block';
}
// 提现金额选择
function selectWd(el) {
document.querySelectorAll('.wd-opt').forEach(e => { e.style.borderColor='var(--gray-200)'; e.style.background='#fff'; });
el.style.borderColor='#FF5722'; el.style.background='#FFF3E0';
}
function showPrototypeToast(msg) {
var existing = document.getElementById('prototypeToast');
if (existing) existing.remove();
var toast = document.createElement('div');
toast.id = 'prototypeToast';
toast.textContent = msg;
toast.style.cssText = 'position:absolute;left:50%;bottom:118px;transform:translateX(-50%);max-width:310px;background:rgba(0,0,0,.78);color:#fff;font-size:13px;font-weight:600;line-height:18px;padding:10px 16px;border-radius:12px;z-index:9999;text-align:center;pointer-events:none;opacity:1;transition:opacity .25s;white-space:nowrap;';
document.getElementById('app').appendChild(toast);
setTimeout(function() { toast.style.opacity = '0'; }, 1500);
setTimeout(function() { if (toast.parentNode) toast.remove(); }, 1800);
}
function selectWithdrawAmount(el) {
document.querySelectorAll('.withdraw-amount').forEach(function(item) {
item.classList.remove('active');
});
el.classList.add('active');
openWechatBindSheet(el.dataset.amount || el.textContent.replace('元', '').trim());
}
function openWechatBindSheet(amount) {
var layer = document.getElementById('wechatBindSheet');
var amountEl = document.getElementById('wechatBindAmount');
if (amountEl) amountEl.textContent = amount || '0.3';
if (!layer) return;
layer.classList.add('open');
layer.setAttribute('aria-hidden', 'false');
}
function closeWechatBindSheet() {
var layer = document.getElementById('wechatBindSheet');
if (!layer) return;
layer.classList.remove('open');
layer.setAttribute('aria-hidden', 'true');
}
var incomeCurrentTab = 'coin';
function openIncomeHistory(tab) {
go('coinhistory');
setIncomeTab(tab);
}
function setIncomeTab(tab) {
incomeCurrentTab = tab === 'cash' ? 'cash' : 'coin';
var tabs = document.getElementById('incomeTabs');
var coinTab = document.getElementById('incomeTabCoin');
var cashTab = document.getElementById('incomeTabCash');
var track = document.getElementById('incomeRecordTrack');
var note = document.getElementById('incomeFooterNote');
var btn = document.getElementById('incomeFooterBtn');
if (tabs) tabs.dataset.active = incomeCurrentTab;
if (coinTab) coinTab.classList.toggle('active', incomeCurrentTab === 'coin');
if (cashTab) cashTab.classList.toggle('active', incomeCurrentTab === 'cash');
if (track) track.classList.toggle('cash-active', incomeCurrentTab === 'cash');
if (note) {
note.innerHTML = incomeCurrentTab === 'coin'
? '累计收益 <strong>2.18 元</strong>'
: '累计到账 <strong>2.36 元</strong>';
}
if (btn) btn.textContent = incomeCurrentTab === 'coin' ? '立即提现' : '去提现';
}
function initIncomeSwipe() {
var shell = document.getElementById('incomeRecordShell');
if (!shell) return;
var startX = 0;
var startY = 0;
var tracking = false;
function begin(x, y) {
startX = x;
startY = y;
tracking = true;
}
function finish(x, y) {
if (!tracking) return;
tracking = false;
var dx = x - startX;
var dy = y - startY;
if (Math.abs(dx) < 46 || Math.abs(dx) < Math.abs(dy) * 1.1) return;
if (dx < 0 && incomeCurrentTab === 'coin') setIncomeTab('cash');
if (dx > 0 && incomeCurrentTab === 'cash') setIncomeTab('coin');
}
shell.addEventListener('touchstart', function(e) {
if (!e.touches || !e.touches[0]) return;
begin(e.touches[0].clientX, e.touches[0].clientY);
}, { passive: true });
shell.addEventListener('touchend', function(e) {
var touch = e.changedTouches && e.changedTouches[0];
if (!touch) return;
finish(touch.clientX, touch.clientY);
}, { passive: true });
shell.addEventListener('mousedown', function(e) {
begin(e.clientX, e.clientY);
});
shell.addEventListener('mouseup', function(e) {
finish(e.clientX, e.clientY);
});
}
var EXCHANGE_COIN_BALANCE = 28967;
var currentExchangeAmount = EXCHANGE_COIN_BALANCE;
function exchangeCashText(coins) {
return (Math.floor(coins / 100) / 100).toFixed(2);
}
function selectExchangeAmount(amount, el) {
currentExchangeAmount = amount === 'all' ? EXCHANGE_COIN_BALANCE : Number(amount);
document.querySelectorAll('.exchange-preset').forEach(function(item) {
item.classList.remove('active');
});
if (el) el.classList.add('active');
var coinAmount = document.getElementById('exchangeCoinAmount');
var cashAmount = document.getElementById('exchangeCashAmount');
var error = document.getElementById('exchangeError');
if (coinAmount) coinAmount.textContent = currentExchangeAmount.toLocaleString('zh-CN');
if (cashAmount) cashAmount.textContent = exchangeCashText(currentExchangeAmount);
if (error) {
if (currentExchangeAmount > EXCHANGE_COIN_BALANCE) {
error.textContent = '超过已拥有金币数';
} else if (currentExchangeAmount < 100) {
error.textContent = '最低 100 金币起兑';
} else {
error.textContent = '';
}
}
}
function openExchangeSheet() {
var layer = document.getElementById('exchangeSheet');
if (!layer) return;
layer.classList.add('open');
layer.setAttribute('aria-hidden', 'false');
selectExchangeAmount('all', document.getElementById('exchangePresetAll'));
}
function closeExchangeSheet() {
var layer = document.getElementById('exchangeSheet');
if (!layer) return;
layer.classList.remove('open');
layer.setAttribute('aria-hidden', 'true');
}
function confirmExchange() {
if (currentExchangeAmount > EXCHANGE_COIN_BALANCE || currentExchangeAmount < 100) return;
closeExchangeSheet();
showPrototypeToast('兑换申请已提交,现金到账可能会有延迟');
}
document.addEventListener('DOMContentLoaded', function() {
initIncomeSwipe();
setIncomeTab('coin');
updateWelfareCheckinTask();
});
// ===== 退出登录 / 注销账号 =====
function showLogoutConfirm() {
document.getElementById('logoutConfirm').style.display = 'flex';
}
function closeLogoutConfirm() {
document.getElementById('logoutConfirm').style.display = 'none';
}
function doLogout() {
closeLogoutConfirm();
isLoggedIn = false; try{localStorage.setItem('proto_isLoggedIn','false');}catch(e){}
welfareVisited = false; try{localStorage.setItem('proto_welfareVisited','false');}catch(e){}
profileVisited = false; try{localStorage.setItem('proto_profileVisited','false');}catch(e){}
checkinShown = false; try{localStorage.setItem('proto_checkinShown','false');}catch(e){}
go('home');
}
function showDeleteConfirm() {
document.getElementById('deleteConfirm').style.display = 'flex';
}
function closeDeleteConfirm() {
document.getElementById('deleteConfirm').style.display = 'none';
}
function doDeleteAccount() {
closeDeleteConfirm();
isLoggedIn = false; try{localStorage.setItem('proto_isLoggedIn','false');}catch(e){}
welfareVisited = false; try{localStorage.setItem('proto_welfareVisited','false');}catch(e){}
profileVisited = false; try{localStorage.setItem('proto_profileVisited','false');}catch(e){}
checkinShown = false; try{localStorage.setItem('proto_checkinShown','false');}catch(e){}
go('home');
}
// Splash 不再自动跳转,等用户点击 CTA "开始体验"
// (旧的 splashCounter 累计数字动画已移除 — Option C 设计无大数字)
// Video 模拟
// ============ Video tutorial 状态机 (vt-) ============
const vt = {
status: 'initial', // initial | playing | paused | ended
elapsed: 0, // 已播毫秒
duration: 5000, // 5s 模拟一分钟,真实视频接入后改成视频时长
intervalId: null,
hasFinished: false,
isDragging: false,
};
const VT_PLAY = '<path d="M8 5v14l11-7z"/>';
const VT_PAUSE = '<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/>';
const VT_REPLAY = '<path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/>';
function vtRender() {
const player = document.getElementById('vt-video');
if (!player) return;
const fill = document.getElementById('vt-fill');
const cur = document.getElementById('vt-current');
const cta = document.getElementById('vt-cta');
const cIco = document.getElementById('vt-center-icon');
const bIco = document.getElementById('vt-bottom-icon');
player.className = 'vt-video-player ' + vt.status;
const progress = Math.min(vt.elapsed / vt.duration, 1);
fill.style.width = (progress * 100) + '%';
// 5s 真时长 → 显示成 1 分钟视频
const totalSec = Math.floor(progress * 60);
const min = Math.floor(totalSec / 60);
const sec = totalSec % 60;
cur.textContent = min + ':' + (sec < 10 ? '0' : '') + sec;
cIco.innerHTML = (vt.status === 'ended') ? VT_REPLAY : VT_PLAY;
bIco.innerHTML = (vt.status === 'playing') ? VT_PAUSE : VT_PLAY;
if (vt.hasFinished) {
cta.classList.remove('disabled');
cta.textContent = '进入快速设置';
} else {
cta.classList.add('disabled');
cta.textContent = '看完后继续';
}
}
function vtStopTimer() {
if (vt.intervalId !== null) { clearInterval(vt.intervalId); vt.intervalId = null; }
}
function vtStartTimer() {
vtStopTimer();
vt.intervalId = setInterval(() => {
vt.elapsed += 50;
if (vt.elapsed >= vt.duration) {
vt.elapsed = vt.duration;
vt.status = 'ended';
vt.hasFinished = true;
vtStopTimer();
}
vtRender();
}, 50);
}
function vtToggle() {
if (vt.status === 'playing') {
vtStopTimer();
vt.status = 'paused';
} else if (vt.status === 'ended') {
vt.elapsed = 0;
vt.status = 'playing';
vtStartTimer();
} else {
vt.status = 'playing';
vtStartTimer();
}
vtRender();
}
function vtNext() {
if (!vt.hasFinished) return;
vtStopTimer();
go('permission-step1');
}
let vtInited = false;
function vtInit() {
if (vtInited) return;
const player = document.getElementById('vt-video');
if (!player) return;
const track = document.getElementById('vt-track');
vtInited = true;
// 1. 点视频本身切换播放/暂停(排除 controls 与 center-play 的内联 onclick
player.addEventListener('click', (e) => {
if (e.target.closest('.vt-controls')) return;
if (e.target.closest('.vt-center-play')) return;
vtToggle();
});
// 2. 进度条拖动(playing / paused 都支持)
function vtSeekFromX(clientX) {
const rect = track.getBoundingClientRect();
const ratio = Math.max(0, Math.min((clientX - rect.left) / rect.width, 1));
vt.elapsed = ratio * vt.duration;
if (ratio >= 1) {
vt.status = 'ended';
vt.hasFinished = true;
vtStopTimer();
} else if (vt.status === 'ended') {
vt.status = 'paused';
}
vtRender();
}
track.addEventListener('mousedown', (e) => {
e.preventDefault(); e.stopPropagation();
vt.isDragging = true; vtSeekFromX(e.clientX);
});
document.addEventListener('mousemove', (e) => { if (vt.isDragging) vtSeekFromX(e.clientX); });
document.addEventListener('mouseup', () => { vt.isDragging = false; });
track.addEventListener('touchstart', (e) => {
e.stopPropagation();
vt.isDragging = true; vtSeekFromX(e.touches[0].clientX);
}, {passive: true});
document.addEventListener('touchmove', (e) => { if (vt.isDragging) vtSeekFromX(e.touches[0].clientX); }, {passive: true});
document.addEventListener('touchend', () => { vt.isDragging = false; });
}
// startVideo 由"进入教程"触发:进入即自动播放
function startVideo() {
vtInit();
vt.elapsed = 0;
vt.hasFinished = false;
vtStopTimer();
vt.status = 'playing';
vtStartTimer();
vtRender();
}
// startVideo 由用户点击"进入教程"触发
// 商品选择
function selectProduct(el) {
document.querySelectorAll('.product-option').forEach(e => { e.style.borderColor='transparent'; e.style.background='var(--gray-50)'; });
el.style.borderColor='var(--primary)'; el.style.background='var(--primary-bg)';
document.getElementById('selectBtn').style.display='block';
}
// 比价模拟
// ===== 截图演示比价流程 =====
// spotlight: { top, left, width, height } 相对于375x812设备
// finger: { top, left } 手指位置
// guidePos: { top, left } 文案位置, 'above' = 聚光灯上方居中
const demoSteps = [
// ===== 一键领券前置流程 =====
{
img: '../../assets/onboarding/index/platform-flows/meituan/1-home.jpg',
mode: 'couponPrompt',
},
// TODO: 替换为真实的美团神券中心 / 饿了么神券中心截图
{
img: '../../assets/onboarding/index/platform-flows/meituan/1-home.jpg',
mode: 'agentFlow',
agentText: '正在打开美团神券中心...',
platforms: { 'meituan-waimai': 'active' },
},
{
img: '../../assets/onboarding/index/platform-flows/meituan/1-home.jpg',
mode: 'agentFlow',
agentText: '已领取美团红包',
couponDelta: 8,
platforms: { 'meituan-waimai': 'done' },
},
{
img: '../../assets/onboarding/index/platform-flows/taobao/2-coupon-center.jpg',
mode: 'agentFlow',
agentText: '正在领取淘宝神券...',
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
},
{
img: '../../assets/onboarding/index/platform-flows/taobao/3-coupon-claimed.jpg',
mode: 'agentFlow',
agentText: '已领取淘宝神券',
couponDelta: 12,
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'done' },
},
{
img: '../../assets/onboarding/index/platform-flows/meituan/1-home.jpg',
mode: 'couponDone',
},
// ===== 比价引导流程 =====
{
img: '../../assets/onboarding/index/platform-flows/meituan/1-home.jpg',
guide: '• 点击下方店铺,并找到商品准备比价',
guideTitle: '找到待比价的商品',
kickoff: true,
spotlight: { top: 517, left: 7, width: 361, height: 125 },
finger: { top: 590, left: 312 },
},
{
img: '../../assets/onboarding/index/platform-flows/meituan/2-shop-top.jpg',
guide: '下滑找到待比价的商品',
mode: 'swipe',
},
{
img: '../../assets/onboarding/index/waimai-guide/add-to-cart.png',
guide: '点击「+」加入购物车',
spotlight: { top: 174, left: 70, width: 301, height: 152 },
plusFocus: { top: 295, left: 352 },
finger: { top: 306, left: 274, size: 60, plusGuide: true },
guideTop: 344,
guideLeft: 187.5,
clickTarget: 'plus',
spotlightRadius: 8,
spotlightOpacity: .62,
},
{
img: '../../assets/onboarding/index/waimai-guide/missing-required.png',
guide: '点击添加必选品',
spotlight: { top: 719, left: 0, width: 375, height: 93 },
plusFocus: { top: 755, left: 311, width: 128, height: 54, shape: 'rect' },
finger: { top: 771, left: 236, size: 60, plusGuide: true },
guideTop: 664,
guideLeft: 187.5,
clickTarget: 'plus',
spotlightRadius: 0,
spotlightOpacity: .62,
},
{
img: '../../assets/onboarding/index/waimai-guide/add-required-item.png',
guide: '点击「+」添加',
spotlight: { top: 306, left: 76, width: 296, height: 134 },
plusFocus: { top: 403, left: 352, width: 46, height: 46, shape: 'circle' },
finger: { top: 414, left: 274, size: 60, plusGuide: true },
guideTop: 458,
guideLeft: 187.5,
clickTarget: 'plus',
spotlightRadius: 8,
spotlightOpacity: .62,
},
{
img: '../../assets/onboarding/index/platform-flows/meituan/5-shop-cart.jpg',
guide: '点击去结算',
spotlight: { top: 719, left: 0, width: 375, height: 93 },
plusFocus: { top: 790, left: 315, width: 112, height: 46, shape: 'pill' },
finger: { top: 735, left: 320, size: 60, imgTransform: 'rotate(-90deg)' },
guideTop: 660,
guideLeft: 187.5,
clickTarget: 'plus',
spotlightRadius: 0,
spotlightOpacity: .62,
},
{
img: '../../assets/onboarding/index/platform-flows/meituan/6-checkout.jpg',
guide: '请选择待使用的红包',
spotlight: { top: 636, left: 14, width: 347, height: 48 },
finger: { top: 660, left: 315, size: 60, imgTransform: 'rotate(6deg)' },
guideTop: 580,
guideLeft: 187.5,
spotlightRadius: 20,
spotlightOpacity: .62,
},
{
img: '../../assets/onboarding/index/platform-flows/meituan/7-coupon-select.jpg',
guide: '点击确认',
spotlight: { top: 752, left: 9, width: 354, height: 55 },
plusFocus: { top: 780, left: 312, width: 104, height: 52, shape: 'confirm' },
finger: { top: 729, left: 313, size: 60, imgTransform: 'rotate(-90deg)' },
guideTop: 696,
guideLeft: 187.5,
clickTarget: 'plus',
spotlightRadius: 24,
spotlightOpacity: .62,
},
{
img: '../../assets/onboarding/index/platform-flows/meituan/8-checkout-coupon.jpg',
mode: 'startCompare',
},
// ===== 淘宝 Agent 自动比价流程 =====
// 比价阶段:美团已用作起点(done),淘宝为当前 active 平台
{
img: '../../assets/onboarding/index/platform-flows/taobao/1-home.jpg',
mode: 'agentFlow',
agentText: '正在打开淘宝...',
retentionPercent: 11,
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
},
{
img: '../../assets/onboarding/index/platform-flows/taobao/4-search.jpg',
mode: 'agentFlow',
agentText: '正在搜索「窑鸡王」...',
retentionPercent: 26,
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
},
{
img: '../../assets/onboarding/index/platform-flows/taobao/5-shop-top.jpg',
mode: 'agentFlow',
agentText: '正在浏览菜单...',
retentionPercent: 40,
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
},
{
img: '../../assets/onboarding/index/platform-flows/taobao/6-shop-item.jpg',
mode: 'agentFlow',
agentText: '搜索同款商品中...',
retentionPercent: 55,
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
},
{
img: '../../assets/onboarding/index/platform-flows/taobao/7-spec.jpg',
mode: 'agentFlow',
agentText: '正在确认商品规格...',
retentionPercent: 70,
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
},
{
img: '../../assets/onboarding/index/platform-flows/taobao/8-checkout.jpg',
mode: 'agentFlow',
agentText: '正在应用所有优惠...',
retentionPercent: 85,
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
},
{
img: '../../assets/onboarding/index/platform-flows/taobao/result.jpg',
mode: 'agentFlow',
agentText: '正在获取淘宝最终价格',
retentionPercent: 100,
last: true,
platforms: { 'meituan-waimai': 'done', 'taobao-shanguang': 'active' },
},
];
let demoStep = 0;
let couponTotal = 0;
let pendingDemoStartStep = null;
function startComparison() {
demoStep = pendingDemoStartStep != null ? pendingDemoStartStep : 0;
pendingDemoStartStep = null;
couponTotal = 0;
const numEl = document.getElementById('demoCouponNum');
if (numEl) numEl.textContent = '0';
renderDemoStep();
}
// 距下一个 0 点倒计时(每秒更新 v6-expiry 三个 time-box
let __midnightTimer = null;
function startMidnightCountdown() {
function pad(n) { return n < 10 ? '0' + n : '' + n; }
function tick() {
var hEl = document.getElementById('cdH');
var mEl = document.getElementById('cdM');
var sEl = document.getElementById('cdS');
if (!hEl || !mEl || !sEl) { stopMidnightCountdown(); return; }
var now = new Date();
var midnight = new Date(now);
midnight.setHours(24, 0, 0, 0);
var diff = Math.max(0, Math.floor((midnight - now) / 1000));
var h = Math.floor(diff / 3600);
var m = Math.floor((diff % 3600) / 60);
var s = diff % 60;
hEl.textContent = pad(h);
mEl.textContent = pad(m);
sEl.textContent = pad(s);
}
stopMidnightCountdown();
tick();
__midnightTimer = setInterval(tick, 1000);
}
function stopMidnightCountdown() {
if (__midnightTimer) { clearInterval(__midnightTimer); __midnightTimer = null; }
}
// 高频弹跳:N 次连续 +1,每次都触发数字弹跳 + 多向粒子喷射(F2 样式)
// K 方案:从 0 缓出到目标值(用于"领券完成"弹窗的总数和分平台数)
function runKCountUp(elId, target, duration, delay) {
const el = document.getElementById(elId);
if (!el) return;
el.textContent = '0';
setTimeout(() => {
let start = null;
const step = ts => {
if (!start) start = ts;
const p = Math.min((ts - start) / duration, 1);
const eased = 1 - Math.pow(1 - p, 3);
el.textContent = Math.round(target * eased);
if (p < 1) requestAnimationFrame(step);
};
requestAnimationFrame(step);
}, delay || 0);
}
function playCouponDelta(delta) {
const numEl = document.getElementById('demoCouponNum');
const numBlock = document.getElementById('demoCouponNumBlock');
if (!numEl || !numBlock) return;
const tickInterval = 130;
for (let i = 0; i < delta; i++) {
setTimeout(() => {
couponTotal += 1;
numEl.textContent = couponTotal;
numEl.classList.remove('coupon-num-pop');
void numEl.offsetWidth;
numEl.classList.add('coupon-num-pop');
const particleCount = 1 + Math.floor(Math.random() * 2);
for (let k = 0; k < particleCount; k++) {
const angle = -Math.PI / 2 + (Math.random() - 0.5) * 1.6;
const dist = 26 + Math.random() * 18;
const p = document.createElement('div');
p.className = 'coupon-plus-particle';
p.textContent = '+1';
p.style.setProperty('--dx', Math.cos(angle) * dist + 'px');
p.style.setProperty('--dy', Math.sin(angle) * dist + 'px');
numBlock.appendChild(p);
setTimeout(() => p.remove(), 900);
}
}, i * tickInterval);
}
}
function renderDemoStep() {
const s = demoSteps[demoStep];
document.getElementById('demoScreenshot').src = s.img;
// AI 接管橘黄光晕:仅在 agentFlow 阶段(块 1 一键领券 + 块 3 自动比价)开启
const aiGlow = document.getElementById('aiTakeoverGlow');
if (aiGlow) aiGlow.classList.toggle('active', s.mode === 'agentFlow');
// 进度条已移除(原 demoProgressBar),不再做按 step 计算宽度的逻辑
const spot = document.getElementById('demoSpotlight');
const plusFocus = document.getElementById('demoPlusFocus');
const finger = document.getElementById('demoFinger');
const guide = document.getElementById('demoGuide');
const guideText = document.getElementById('demoGuideText');
const kickoff = document.getElementById('demoKickoff');
const swipeOverlay = document.getElementById('demoSwipeOverlay');
const startOverlay = document.getElementById('demoStartOverlay');
const agentOverlay = document.getElementById('demoAgentOverlay');
const couponPrompt = document.getElementById('demoCouponPrompt');
const couponDoneToast = document.getElementById('demoCouponDoneToast');
// 先全部隐藏
swipeOverlay.style.display = 'none';
startOverlay.style.display = 'none';
agentOverlay.style.display = 'none';
couponPrompt.style.display = 'none';
couponDoneToast.style.display = 'none';
kickoff.style.display = 'none';
plusFocus.style.display = 'none';
plusFocus.className = 'demo-plus-focus';
plusFocus.style.width = '46px';
plusFocus.style.height = '46px';
finger.classList.remove('demo-plus-finger');
finger.style.width = '58px';
finger.style.height = '58px';
finger.style.zIndex = '15';
const fingerImg = finger.querySelector('.gesture-hand-img');
fingerImg.style.transform = '';
// ===== 一键领券弹窗 =====
if (s.mode === 'couponPrompt') {
spot.style.display = 'none';
finger.style.display = 'none';
guide.style.display = 'none';
renderCouponPromptPlatforms();
couponPrompt.style.display = 'flex';
return;
}
// ===== 一键领券完成 toast =====
if (s.mode === 'couponDone') {
spot.style.display = 'none';
finger.style.display = 'none';
guide.style.display = 'none';
// home 模式:toast 应展示在首页背景之上,先切回 home 再弹
if (homeClaimMode) {
go('home');
}
couponDoneToast.style.display = 'block';
// 0 → N 计数动画;不自动消失,等用户点击 CTA 才推进
runKCountUp('demoCouponDoneCount', couponTotal || 20, 1500, 200);
// 启动距 0 点倒计时(每秒滴答)
startMidnightCountdown();
return;
}
if (s.mode === 'swipe') {
spot.style.display = 'none';
finger.style.display = 'none';
guide.style.display = 'none';
swipeOverlay.style.display = 'flex';
swipeOverlay.querySelector('.swipe-text').textContent = s.guide;
return;
}
if (s.mode === 'startCompare') {
spot.style.display = 'none';
finger.style.display = 'none';
guide.style.display = 'none';
startOverlay.style.display = 'block';
return;
}
if (s.mode === 'agentFlow') {
spot.style.display = 'none';
finger.style.display = 'none';
guide.style.display = 'none';
agentOverlay.style.display = 'block';
// 块 1(领券) vs 块 3(比价)切换浮窗形态
const firstSpotlightIdx = demoSteps.findIndex(d => d.spotlight || d.mode === 'swipe' || d.mode === 'startCompare');
const inCouponPhase = firstSpotlightIdx > 0 && demoStep < firstSpotlightIdx;
const agentFloat = document.getElementById('demoAgentFloat');
const comparingFloat = document.getElementById('demoComparingFloat');
if (inCouponPhase) {
// 块 1:领券阶段 → 显示已领券计数浮窗(显式 flex,避免清掉 inline display:flex
if (agentFloat) agentFloat.style.display = 'flex';
if (comparingFloat) comparingFloat.style.display = 'none';
document.getElementById('demoAgentText').textContent = s.agentText;
if (s.couponDelta) playCouponDelta(s.couponDelta);
renderFloatPlatforms('demoAgentPlatforms', s.platforms);
} else {
// 块 3:比价阶段 → 显示合并比价浮窗(无已领券计数,红包激励融入副文案动效)
if (agentFloat) agentFloat.style.display = 'none';
if (comparingFloat) comparingFloat.style.display = 'block';
document.getElementById('demoComparingText').textContent = s.agentText;
if (s.retentionPercent != null) {
const fill = document.getElementById('demoComparingFill');
if (fill) fill.style.width = s.retentionPercent + '%';
}
renderFloatPlatforms('demoComparingPlatforms', s.platforms);
}
return;
}
// 默认:聚光灯模式
spot.style.display = 'block';
spot.style.top = s.spotlight.top + 'px';
spot.style.left = s.spotlight.left + 'px';
spot.style.width = s.spotlight.width + 'px';
spot.style.height = s.spotlight.height + 'px';
spot.style.borderRadius = (s.spotlightRadius ? s.spotlightRadius + 'px' : '12px');
spot.style.boxShadow = '0 0 0 9999px rgba(0,0,0,' + (s.spotlightOpacity != null ? s.spotlightOpacity : .5) + ')';
spot.style.pointerEvents = s.clickTarget === 'plus' ? 'none' : 'auto';
spot.style.cursor = s.clickTarget === 'plus' ? 'default' : 'pointer';
if (s.plusFocus) {
plusFocus.style.display = 'block';
plusFocus.style.top = s.plusFocus.top + 'px';
plusFocus.style.left = s.plusFocus.left + 'px';
plusFocus.style.width = (s.plusFocus.width || 46) + 'px';
plusFocus.style.height = (s.plusFocus.height || 46) + 'px';
plusFocus.classList.add(s.plusFocus.shape || 'circle');
if (s.clickTarget === 'plus') plusFocus.classList.add('clickable');
}
if (s.finger) {
finger.style.display = 'block';
finger.style.top = s.finger.top + 'px';
finger.style.left = s.finger.left + 'px';
finger.style.width = (s.finger.size || 58) + 'px';
finger.style.height = (s.finger.size || 58) + 'px';
if (s.finger.plusGuide) {
finger.classList.add('demo-plus-finger');
finger.style.transform = 'none';
} else {
finger.style.transform = s.finger.mirror ? 'scaleX(-1)' : 'none';
if (s.finger.imgTransform) {
fingerImg.style.transform = s.finger.imgTransform;
}
}
} else {
finger.style.display = 'none';
}
if (s.kickoff && s.guide) {
// Kickoff 黄卡:标题 + 虚线 + 圆形箭头 + 引线
guide.style.display = 'none';
document.getElementById('demoKickoffTitle').textContent = s.guideTitle || '下一步,比出全网最低价';
document.getElementById('demoKickoffText').textContent = s.guide;
kickoff.style.display = 'block';
// 让卡片底部到引线落点正好对齐 spotlight 顶部
const cardEl = kickoff.querySelector('.kickoff-card');
const leaderH = 36;
const cardH = cardEl.offsetHeight;
kickoff.style.top = (s.spotlight.top - leaderH - cardH) + 'px';
} else if (s.guide) {
guide.style.display = 'block';
guideText.textContent = s.guide;
var bubbleTopY = null;
if (s.guideTop != null) {
guide.style.top = s.guideTop + 'px';
guide.style.left = (s.guideLeft != null ? s.guideLeft + 'px' : '50%');
guide.style.right = 'auto';
guide.style.transform = 'translateX(-50%)';
bubbleTopY = s.guideTop;
} else if (s.guidePos === 'above') {
const offset = s.guideOffset || -50;
guide.style.top = (s.spotlight.top + offset) + 'px';
bubbleTopY = s.spotlight.top + offset;
if (s.guideAlign === 'spotlight') {
var cx = s.spotlight.left + s.spotlight.width / 2;
// 渲染后检查是否超出屏幕,先设置位置
guide.style.left = cx + 'px';
guide.style.transform = 'translateX(-50%)';
// 延迟检查边界并修正
setTimeout(function() {
var rect = guide.getBoundingClientRect();
var device = document.getElementById('app').getBoundingClientRect();
if (rect.right > device.right - 8) {
guide.style.left = 'auto';
guide.style.right = '8px';
guide.style.transform = 'none';
}
}, 10);
} else {
guide.style.left = '50%';
guide.style.right = 'auto';
guide.style.transform = 'translateX(-50%)';
}
}
// 动态定位 leaderdot 中心贴在 spotlight 最近的边缘上
var leader = guide.querySelector('.demo-guide-leader');
if (leader) {
leader.classList.remove('dir-down', 'dir-up');
leader.style.height = '';
leader.style.display = '';
if (bubbleTopY != null && s.spotlight) {
var bubbleH = guideText.offsetHeight;
var bubbleBottomY = bubbleTopY + bubbleH;
var targetTop = s.spotlight.top;
var targetBottom = s.spotlight.top + s.spotlight.height;
if (bubbleBottomY <= targetTop) {
leader.classList.add('dir-down');
leader.style.height = Math.max(0, targetTop - bubbleBottomY + 1) + 'px';
} else if (bubbleTopY >= targetBottom) {
leader.classList.add('dir-up');
leader.style.height = Math.max(0, bubbleTopY - targetBottom + 1) + 'px';
} else {
leader.style.display = 'none';
}
} else {
leader.style.display = 'none';
}
}
} else {
guide.style.display = 'none';
}
}
function demoPlusHit(event) {
event.stopPropagation();
const el = event.currentTarget;
const rect = el.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
if (el.classList.contains('circle')) {
const radius = Math.min(rect.width, rect.height) / 2;
const dx = x - rect.width / 2;
const dy = y - rect.height / 2;
if ((dx * dx + dy * dy) > radius * radius) {
return;
}
}
if (el.classList.contains('pill')) {
const radius = rect.height / 2;
const leftCap = radius;
const rightCap = rect.width - radius;
const inCenter = x >= leftCap && x <= rightCap && y >= 0 && y <= rect.height;
const dx = x < leftCap ? x - leftCap : x - rightCap;
const dy = y - radius;
if (!inCenter && (dx * dx + dy * dy) > radius * radius) {
return;
}
}
if (el.classList.contains('confirm')) {
const leftRadius = 4;
const rightRadius = rect.height / 2;
const inMiddle = y >= 0 && y <= rect.height && x >= leftRadius && x <= rect.width - rightRadius;
const inLeft = x >= 0 && x < leftRadius && y >= leftRadius && y <= rect.height - leftRadius;
const inRight = x > rect.width - rightRadius && x <= rect.width && y >= 0 && y <= rect.height;
const dx = x - (rect.width - rightRadius);
const dy = y - rightRadius;
if (!inMiddle && !inLeft && (!inRight || (dx * dx + dy * dy) > rightRadius * rightRadius)) {
return;
}
}
demoNext();
}
function demoNext() {
// 离开 couponDone 弹窗时关掉倒计时
stopMidnightCountdown();
const s = demoSteps[demoStep];
// home 一键领券模式:couponDone toast CTA → 回首页并切换"已领"态
if (homeClaimMode && s && s.mode === 'couponDone') {
onHomeCouponClaimDone();
return;
}
if (s.last) {
renderCelebrationSavings();
renderResults('celebResults');
go('celebration');
return;
}
if (demoStep < demoSteps.length - 1) {
demoStep++;
renderDemoStep();
}
}
// ===== 一键领券弹窗按钮 =====
function onClaimCouponConfirm() {
// 首页卡片入口:先在首页弹确认,确认后再进入平台领券 agent flow。
const prompt = document.getElementById('demoCouponPrompt');
if (prompt) prompt.style.display = 'none';
const comparing = document.getElementById('comparing');
if (homeClaimMode && comparing && !comparing.classList.contains('active')) {
const firstAgentIdx = demoSteps.findIndex(d => d.mode === 'agentFlow');
pendingDemoStartStep = firstAgentIdx > 0 ? firstAgentIdx : 1;
go('comparing');
return;
}
demoNext();
}
// ===== 首页"一键领优惠"卡片:去领取 → 弹窗 → agent 领券 → 完成 → 回首页 =====
let homeClaimMode = false;
let homeCouponClaimed = false;
let homeCouponClaimSummary = null; // { total, platforms: [{ id, name, icon }] }
function onTriClaimClick() {
// 已领取过:tile 仅作展示,再次点击不重启流程
if (homeCouponClaimed) return;
homeClaimMode = true;
demoStep = 0;
couponTotal = 0;
const numEl = document.getElementById('demoCouponNum');
if (numEl) numEl.textContent = '0';
renderCouponPromptPlatforms();
const prompt = document.getElementById('demoCouponPrompt');
const app = document.getElementById('app');
if (prompt && app) {
app.appendChild(prompt);
prompt.style.display = 'flex';
}
}
function closeHomeCouponClaim() {
// 关闭弹窗 → 回首页(保持未领状态)
document.getElementById('demoCouponPrompt').style.display = 'none';
homeClaimMode = false;
stopMidnightCountdown();
go('home');
}
function onCouponPromptMaskClick(e) {
// 点击弹窗外侧蒙层关闭(home 模式才生效;点中卡片不关)
if (!homeClaimMode) return;
if (e.target && e.target.id === 'demoCouponPrompt') closeHomeCouponClaim();
}
function onHomeCouponClaimDone() {
homeClaimMode = false;
homeCouponClaimed = true;
stopMidnightCountdown();
// toast 现在是 device 级 overlay,跳页时不会自动消失,需要手动关
const toast = document.getElementById('demoCouponDoneToast');
if (toast) toast.style.display = 'none';
// 汇总:领券数(demoSteps couponDelta 累加得到的 couponTotal + 已安装平台
const platforms = (typeof getVisibleApps === 'function' ? getVisibleApps() : [])
.filter(a => a.installed)
.map(a => ({ id: a.id, name: a.name, icon: a.icon }));
homeCouponClaimSummary = {
total: couponTotal || 20,
platforms: platforms,
};
go('home');
renderTriClaim();
}
function renderTriClaim() {
const def = document.getElementById('triClaimDefault');
const done = document.getElementById('triClaimDone');
if (!def || !done) return;
if (!homeCouponClaimed || !homeCouponClaimSummary) {
def.style.display = '';
done.style.display = 'none';
return;
}
def.style.display = 'none';
done.style.display = '';
const numEl = document.getElementById('triClaimDoneNum');
if (numEl) numEl.textContent = homeCouponClaimSummary.total;
const logosEl = document.getElementById('triClaimDoneLogos');
if (logosEl) {
// 取前 3 个 logo(一行内放得下),更多则用 +N 表示
const ps = homeCouponClaimSummary.platforms || [];
const shown = ps.slice(0, 3);
let html = shown.map(p => '<img src="' + p.icon + '" alt="' + p.name + '">').join('');
if (ps.length > shown.length) {
html += '<span style="font-size: 10px;font-weight: 700;color: #fff;margin-left: 2px;">+' + (ps.length - shown.length) + '</span>';
}
logosEl.innerHTML = html;
}
}
// ===== 一键领券弹窗 · 多版本(平台选择中部 + 视觉风格切换)=====
function toggleCouponPlatform(el) {
if (!el) return;
el.dataset.checked = el.dataset.checked === 'true' ? 'false' : 'true';
}
const couponPromptVariants = {
// V2 「快手糖果风」粉橙渐变外卡 + 白色内卡 3 列网格
v2: '' +
'<div style="background: linear-gradient(180deg,#FF6B9E 0%,#FF8FAB 55%,#FFAA8C 100%);border-radius: 24px;padding: 16px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,80,120,.45);text-align: center;">' +
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
'<div style="font-size: 17px;font-weight: 900;color: #fff;line-height: 1.4;margin-bottom: 12px;text-shadow: 0 1px 2px rgba(0,0,0,.08);">您今日还有大额优惠券可领</div>' +
'<div style="background: linear-gradient(180deg,#fff 70%,#FFF1F4 100%);border-radius: 18px;padding: 12px 12px;margin-bottom: 16px;">' +
'<div style="font-size: 11px;color: var(--gray-600);font-weight: 600;margin-bottom: 12px;">已为您发现 <span style="color: #FF4081;font-weight: 800;">3</span> 个平台都有大额优惠</div>' +
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
['美团', '../../assets/shared/logos/meituan.png', '淘宝', '../../assets/shared/logos/taobao.png', '京东', '../../assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-pink" style="background: #fff;border: 2px solid #FF6B9E;border-radius: 12px;padding: 8px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 36px;height: 36px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 11px;font-weight: 700;color: var(--gray-900);margin-top: 6px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 4px;right: 4px;width: 16px;height: 16px;border-radius: 50%;background: #FF4081;display: flex;align-items: center;justify-content: center;"><svg width="9" height="9" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>'; }, '') +
'</div>' +
'</div>' +
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;width: 100%;background: linear-gradient(180deg,#FFE066,#FFD600);color: #1a1a1a;font-weight: 900;box-shadow: 0 6px 16px rgba(255,179,0,.5);" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
'</div>',
// V3 「品牌黄横向选择卡」黄→白渐变外卡 + 3 张并排选择卡(琥珀边框态)+ 黄色品牌按钮(加深收尾保对比)
v3: '' +
'<div style="background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 50%,#FFFDF5 100%);border-radius: 24px;padding: 24px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,193,7,.4);text-align: center;">' +
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
'<div style="font-size: 18px;font-weight: 900;color: var(--gray-900);line-height: 1.4;margin-bottom: 12px;">您今日还有大额优惠券可领</div>' +
'<div style="background: #fff;border-radius: 18px;padding: 12px 8px;margin-bottom: 8px;box-shadow: 0 2px 12px rgba(255,193,7,.15);">' +
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
['美团', '../../assets/shared/logos/meituan.png', '淘宝', '../../assets/shared/logos/taobao.png', '京东', '../../assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;"><svg width="10" height="10" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>'; }, '') +
'</div>' +
'</div>' +
'<div style="font-size: 12px;color: var(--gray-500);font-weight: 500;margin-bottom: 12px;">将在以上平台领取</div>' +
'<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFD600 0%,#FFA000 100%);color: #1a1a1a;font-weight: 900;box-shadow: 0 8px 22px rgba(255,140,0,.5);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
'</div>',
// V4 「黄色品牌风」白底外卡 + 纵向 3 行平台列表 + 黄色 toggle 开关
v4: '' +
'<div style="background: #fff;border-radius: 24px;padding: 24px 16px 16px;width: 100%;text-align: center;box-shadow: 0 16px 48px rgba(0,0,0,.3);border-top: 6px solid #FFD600;">' +
'<div style="width: 56px;height: 56px;border-radius: 14px;margin: 0 auto 12px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 18px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
'<div style="font-size: 18px;font-weight: 800;color: var(--gray-900);line-height: 1.4;margin-bottom: 12px;">您今日还有大额优惠券可领</div>' +
'<div style="background: var(--gray-100);border-radius: 14px;padding: 8px;margin-bottom: 16px;display: flex;flex-direction: column;gap: 6px;">' +
['美团', '../../assets/shared/logos/meituan.png', '淘宝', '../../assets/shared/logos/taobao.png', '京东', '../../assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 1.5px solid #FFD600;border-radius: 12px;padding: 8px 12px;display: flex;align-items: center;gap: 8px;text-align: left;"><img src="' + arr[i+1] + '" style="width: 36px;height: 36px;border-radius: 8px;flex-shrink: 0;"/><div style="flex: 1;font-size: 14px;font-weight: 700;color: var(--gray-900);">' + arr[i] + '</div><span class="cp-toggle" style="position: relative;width: 36px;height: 20px;border-radius: 8px;background: #FFD600;flex-shrink: 0;transition: background .2s;"><span style="position: absolute;top: 2px;left: 2px;width: 16px;height: 16px;border-radius: 50%;background: #fff;box-shadow: 0 1px 3px rgba(0,0,0,.2);transform: translateX(16px);transition: transform .2s;"></span></span></div>'; }, '') +
'</div>' +
'<button class="btn btn-primary btn-lg" style="border-radius: 24px;font-size: 16px;height: 48px;width: 100%;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
'</div>',
// ===== V3 副标题处理方案 a~e(仅副标题区域不同,其他与 V3 一致)=====
// V3a 「机制副标题」副标题改讲"AI 自动 · 跨平台"机制,13px / 600 / 暗金
v3a: '' +
'<div style="background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 50%,#FFFDF5 100%);border-radius: 24px;padding: 24px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,193,7,.4);text-align: center;">' +
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
'<div style="font-size: 18px;font-weight: 900;color: var(--gray-900);line-height: 1.4;margin-bottom: 6px;">您今日还有大额优惠券可领</div>' +
'<div style="font-size: 13px;font-weight: 600;color: #8B6914;line-height: 1.5;margin-bottom: 12px;">AI 跨平台一键领取,无需手动切换 APP</div>' +
'<div style="background: #fff;border-radius: 18px;padding: 12px 8px;margin-bottom: 8px;box-shadow: 0 2px 12px rgba(255,193,7,.15);">' +
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
['美团', '../../assets/shared/logos/meituan.png', '淘宝', '../../assets/shared/logos/taobao.png', '京东', '../../assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;"><svg width="10" height="10" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>'; }, '') +
'</div>' +
'</div>' +
'<div style="font-size: 12px;color: var(--gray-500);font-weight: 500;margin-bottom: 12px;">将在以上平台领取</div>' +
'<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFD600 0%,#FFA000 100%);color: #1a1a1a;font-weight: 900;box-shadow: 0 8px 22px rgba(255,140,0,.5);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
'</div>',
// V3b 「黄色胶囊标签」副标题文案不变,但用黄色 pill 包裹 + 🎁 emoji
v3b: '' +
'<div style="background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 50%,#FFFDF5 100%);border-radius: 24px;padding: 24px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,193,7,.4);text-align: center;">' +
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
'<div style="font-size: 18px;font-weight: 900;color: var(--gray-900);line-height: 1.4;margin-bottom: 8px;">您今日还有大额优惠券可领</div>' +
'<div style="display: inline-block;background: rgba(255,179,0,.18);color: #8B6914;font-size: 12px;font-weight: 700;padding: 4px 12px;border-radius: 32px;margin-bottom: 12px;">🎁 领取后立享更低好价</div>' +
'<div style="background: #fff;border-radius: 18px;padding: 12px 8px;margin-bottom: 8px;box-shadow: 0 2px 12px rgba(255,193,7,.15);">' +
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
['美团', '../../assets/shared/logos/meituan.png', '淘宝', '../../assets/shared/logos/taobao.png', '京东', '../../assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;"><svg width="10" height="10" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>'; }, '') +
'</div>' +
'</div>' +
'<div style="font-size: 12px;color: var(--gray-500);font-weight: 500;margin-bottom: 12px;">将在以上平台领取</div>' +
'<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFD600 0%,#FFA000 100%);color: #1a1a1a;font-weight: 900;box-shadow: 0 8px 22px rgba(255,140,0,.5);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
'</div>',
// V3c 「特性 chip 行」三枚迷你 pill:AI 自动 · 30 秒 · 安全
v3c: '' +
'<div style="background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 50%,#FFFDF5 100%);border-radius: 24px;padding: 24px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,193,7,.4);text-align: center;">' +
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
'<div style="font-size: 18px;font-weight: 900;color: var(--gray-900);line-height: 1.4;margin-bottom: 8px;">您今日还有大额优惠券可领</div>' +
'<div style="display: flex;justify-content: center;gap: 6px;flex-wrap: wrap;margin-bottom: 12px;">' +
'<span style="background: rgba(255,179,0,.18);color: #8B6914;font-size: 11px;font-weight: 700;padding: 4px 8px;border-radius: 32px;">🤖 AI 自动</span>' +
'<span style="background: rgba(255,179,0,.18);color: #8B6914;font-size: 11px;font-weight: 700;padding: 4px 8px;border-radius: 32px;">⚡ 30 秒完成</span>' +
'<span style="background: rgba(255,179,0,.18);color: #8B6914;font-size: 11px;font-weight: 700;padding: 4px 8px;border-radius: 32px;">🛡️ 安全无感</span>' +
'</div>' +
'<div style="background: #fff;border-radius: 18px;padding: 12px 8px;margin-bottom: 8px;box-shadow: 0 2px 12px rgba(255,193,7,.15);">' +
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
['美团', '../../assets/shared/logos/meituan.png', '淘宝', '../../assets/shared/logos/taobao.png', '京东', '../../assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;"><svg width="10" height="10" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>'; }, '') +
'</div>' +
'</div>' +
'<div style="font-size: 12px;color: var(--gray-500);font-weight: 500;margin-bottom: 12px;">将在以上平台领取</div>' +
'<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFD600 0%,#FFA000 100%);color: #1a1a1a;font-weight: 900;box-shadow: 0 8px 22px rgba(255,140,0,.5);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
'</div>',
// V3d 「顶部小标签 + 单标题」副标题取消,logo 下方加「今日福利」黄色小 pill
v3d: '' +
'<div style="background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 50%,#FFFDF5 100%);border-radius: 24px;padding: 24px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,193,7,.4);text-align: center;">' +
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
'<div style="display: inline-block;background: #FFD600;color: #1a1a1a;font-size: 11px;font-weight: 800;letter-spacing: .5px;padding: 2px 8px;border-radius: 32px;margin-bottom: 8px;">今日福利</div>' +
'<div style="font-size: 18px;font-weight: 900;color: var(--gray-900);line-height: 1.4;margin-bottom: 12px;">发现您有未领取的大额优惠券</div>' +
'<div style="background: #fff;border-radius: 18px;padding: 12px 8px;margin-bottom: 8px;box-shadow: 0 2px 12px rgba(255,193,7,.15);">' +
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
['美团', '../../assets/shared/logos/meituan.png', '淘宝', '../../assets/shared/logos/taobao.png', '京东', '../../assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;"><svg width="10" height="10" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>'; }, '') +
'</div>' +
'</div>' +
'<div style="font-size: 12px;color: var(--gray-500);font-weight: 500;margin-bottom: 12px;">将在以上平台领取</div>' +
'<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFD600 0%,#FFA000 100%);color: #1a1a1a;font-weight: 900;box-shadow: 0 8px 22px rgba(255,140,0,.5);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
'</div>',
// V3e 「紧迫感副标题」副标题强调时效,⏰ + 暖红色,13px / 700
v3e: '' +
'<div style="background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 50%,#FFFDF5 100%);border-radius: 24px;padding: 24px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,193,7,.4);text-align: center;">' +
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
'<div style="font-size: 18px;font-weight: 900;color: var(--gray-900);line-height: 1.4;margin-bottom: 6px;">您今日还有大额优惠券可领</div>' +
'<div style="font-size: 13px;font-weight: 700;color: #D9534F;line-height: 1.5;margin-bottom: 12px;">⏰ 仅今日有效,错过自动失效</div>' +
'<div style="background: #fff;border-radius: 18px;padding: 12px 8px;margin-bottom: 8px;box-shadow: 0 2px 12px rgba(255,193,7,.15);">' +
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
['美团', '../../assets/shared/logos/meituan.png', '淘宝', '../../assets/shared/logos/taobao.png', '京东', '../../assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;"><svg width="10" height="10" viewBox="0 0 9 9"><path d="M2 4.5l1.5 1.5 3-4" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>'; }, '') +
'</div>' +
'</div>' +
'<div style="font-size: 12px;color: var(--gray-500);font-weight: 500;margin-bottom: 12px;">将在以上平台领取</div>' +
'<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFD600 0%,#FFA000 100%);color: #1a1a1a;font-weight: 900;box-shadow: 0 8px 22px rgba(255,140,0,.5);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
'</div>',
// V3f 「流程植入副标题」副标题植入产品流程:先领券 → AI 比价 → 找底价
v3f: '' +
'<div style="background: linear-gradient(180deg,#FFE066 0%,#FFF3C4 50%,#FFFDF5 100%);border-radius: 24px;padding: 24px 16px 16px;width: 100%;box-shadow: 0 16px 48px rgba(255,193,7,.4);text-align: center;">' +
'<div style="width: 52px;height: 52px;border-radius: 13px;margin: 0 auto 8px;background: #FFD600;display: flex;align-items: center;justify-content: center;box-shadow: 0 4px 14px rgba(255,179,0,.5);"><span style="font-size: 17px;font-weight: 900;color: #1a1a1a;line-height: 1.05;text-align: center;">傻瓜<br>比价</span></div>' +
'<div style="font-size: 18px;font-weight: 900;color: var(--gray-900);line-height: 1.4;margin-bottom: 8px;">您今日还有大额优惠券可领</div>' +
'<div style="display: inline-flex;align-items: center;gap: 6px;background: rgba(255,179,0,.18);color: #8B6914;font-size: 12px;font-weight: 700;padding: 4px 12px;border-radius: 32px;margin-bottom: 12px;"><svg width="14" height="12" viewBox="0 0 22 18" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M2 7.2 V10.8 A1.4 1.4 0 0 0 3.4 12.2 H5.4 L11.2 16.4 A0.8 0.8 0 0 0 12.5 15.7 V2.3 A0.8 0.8 0 0 0 11.2 1.6 L5.4 5.8 H3.4 A1.4 1.4 0 0 0 2 7.2 Z" fill="#8B6914"/><path d="M14.6 4.4 C16 6 16 12 14.6 13.6" stroke="#8B6914" stroke-width="1.4" stroke-linecap="round" fill="none"/><path d="M16.8 2.6 C19.2 5.2 19.2 12.8 16.8 15.4" stroke="#8B6914" stroke-width="1.4" stroke-linecap="round" fill="none" opacity=".55"/><circle cx="6.2" cy="14.4" r="1.5" fill="#8B6914"/></svg>先领券再比价</div>' +
'<div style="background: #fff;border-radius: 18px;padding: 12px 8px;margin-bottom: 8px;box-shadow: 0 2px 12px rgba(255,193,7,.15);">' +
'<div style="display: grid;grid-template-columns: repeat(3,1fr);gap: 8px;">' +
['美团', '../../assets/shared/logos/meituan.png', '淘宝', '../../assets/shared/logos/taobao.png', '京东', '../../assets/shared/logos/jd.png'].reduce(function(acc, _, i, arr){ if (i % 2) return acc; return acc + '<div data-checked="true" onclick="toggleCouponPlatform(this)" class="cp-card cp-card-yellow" style="background: #fff;border: 2px solid #FFB300;border-radius: 14px;padding: 12px 4px 8px;position: relative;"><img src="' + arr[i+1] + '" style="width: 42px;height: 42px;border-radius: 8px;margin: 0 auto;display: block;"/><div style="font-size: 12px;font-weight: 700;color: var(--gray-900);margin-top: 8px;">' + arr[i] + '</div><span class="cp-check" style="position: absolute;top: 6px;right: 6px;width: 18px;height: 18px;border-radius: 50%;background: #FFB300;display: flex;align-items: center;justify-content: center;"><svg width=\"10\" height=\"10\" viewBox=\"0 0 9 9\"><path d=\"M2 4.5l1.5 1.5 3-4\" stroke=\"#fff\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\"/></svg></span></div>'; }, '') +
'</div>' +
'</div>' +
'<div style="font-size: 12px;color: var(--gray-500);font-weight: 500;margin-bottom: 12px;">将在以上平台领取</div>' +
'<button class="btn btn-lg" style="border-radius: 24px;font-size: 16px;height: 50px;width: 100%;background: linear-gradient(180deg,#FFD600 0%,#FFA000 100%);color: #1a1a1a;font-weight: 900;box-shadow: 0 8px 22px rgba(255,140,0,.5);border: none;" onclick="onClaimCouponConfirm()">一键自动领取</button>' +
'</div>'
};
function applyCouponPromptVariant(v) {
const card = document.getElementById('demoCouponPromptCard');
if (!card || !couponPromptVariants[v]) return;
card.style.cssText = 'width:100%;max-width:330px;animation:fadeInUp .45s cubic-bezier(.34,1.56,.64,1);';
card.innerHTML = couponPromptVariants[v];
}
function showCouponPromptForPreview() {
// 预览模式:直接强制显示弹窗,不走 demo flow
document.querySelectorAll('.screen').forEach(function(s){ s.classList.remove('active'); s.style.display = ''; });
const cmp = document.getElementById('comparing');
if (cmp) { cmp.classList.add('active'); cmp.style.display = 'flex'; }
const prompt = document.getElementById('demoCouponPrompt');
if (prompt) prompt.style.display = 'flex';
}
function onClaimCouponDecline() {
// 残忍放弃:跳过领券,直接进入比价引导第一步
document.getElementById('demoCouponPrompt').style.display = 'none';
const firstSpotlightIdx = demoSteps.findIndex(d => d.spotlight || d.mode === 'swipe' || d.mode === 'startCompare');
if (firstSpotlightIdx > 0) {
demoStep = firstSpotlightIdx;
renderDemoStep();
} else {
demoNext();
}
}
// 跳过新人体验流程 → 召回弹窗(居中卡片式)
function onSkipExperienceRequest() {
const modal = document.getElementById('skipConfirmModal');
if (modal) modal.style.display = 'flex';
}
function closeSkipConfirmModal() {
const modal = document.getElementById('skipConfirmModal');
if (modal) modal.style.display = 'none';
}
function confirmSkipExperience() {
closeSkipConfirmModal();
// 真的跳过 → 直接进入 login(不走 demo 比价 + celebration
go('login');
}
// [ECOM-ONLY] 盲盒解锁 + 滑动引擎 removed for waimai V1
// ===== 礼花爆炸特效 =====
function startConfetti() {
const canvas = document.getElementById('confettiCanvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
canvas.width = 375;
canvas.height = 812;
const colors = ['#FF5722','#FFD600','#4CAF50','#2196F3','#E91E63','#FF9800','#9C27B0','#00BCD4','#FF4081'];
const pieces = [];
const shapes = ['rect','circle','strip'];
// 从两侧底部发射两簇礼花
function burst(originX, originY, count) {
for (let i = 0; i < count; i++) {
const angle = -Math.PI/2 + (Math.random() - 0.5) * 1.2; // 向上扇形
const speed = Math.random() * 8 + 5;
pieces.push({
x: originX,
y: originY,
vx: Math.cos(angle) * speed * (originX < 187 ? 1 : -1) * (0.3 + Math.random() * 0.7),
vy: Math.sin(angle) * speed - Math.random() * 3,
w: Math.random() * 10 + 4,
h: Math.random() * 6 + 2,
color: colors[Math.floor(Math.random() * colors.length)],
rot: Math.random() * 360,
vr: (Math.random() - 0.5) * 12,
gravity: 0.12 + Math.random() * 0.06,
friction: 0.98,
opacity: 1,
shape: shapes[Math.floor(Math.random() * shapes.length)],
wobble: Math.random() * 10,
wobbleSpeed: 0.05 + Math.random() * 0.1,
});
}
}
// 左右两侧各爆一簇
burst(60, 350, 50);
burst(315, 350, 50);
// 稍后中间再爆一簇
setTimeout(() => burst(187, 300, 40), 300);
let frame = 0;
function draw() {
ctx.clearRect(0, 0, 375, 812);
let alive = 0;
pieces.forEach(p => {
if (p.opacity <= 0) return;
alive++;
p.vx *= p.friction;
p.vy *= p.friction;
p.vy += p.gravity;
p.vx += Math.sin(p.wobble) * 0.3;
p.wobble += p.wobbleSpeed;
p.x += p.vx;
p.y += p.vy;
p.rot += p.vr;
p.vr *= 0.99;
// 慢慢淡出
if (frame > 80) p.opacity = Math.max(0, p.opacity - 0.006);
ctx.save();
ctx.translate(p.x, p.y);
ctx.rotate(p.rot * Math.PI / 180);
ctx.globalAlpha = p.opacity;
ctx.fillStyle = p.color;
if (p.shape === 'circle') {
ctx.beginPath();
ctx.arc(0, 0, p.w/2, 0, Math.PI*2);
ctx.fill();
} else if (p.shape === 'strip') {
ctx.fillRect(-p.w/2, -1, p.w, 2.5);
} else {
ctx.fillRect(-p.w/2, -p.h/2, p.w, p.h);
}
ctx.restore();
});
frame++;
if (alive > 0 && frame < 400) requestAnimationFrame(draw);
else ctx.clearRect(0, 0, 375, 812);
}
draw();
}
// ===== 新人礼包方案切换(URL 参数驱动,用于 gift-variants 对比页) =====
const giftVariantTemplates = {
A: '<div class="gv-base gv-a"><div class="gv-icon">🎁</div><div><div class="gv-title">新人专享礼包</div><div class="gv-sub">完成体验立即到账</div></div></div>',
B: '<div class="gv-base gv-b"><div class="gv-stamp">价值 ¥88</div><div class="gv-icon">🎁</div><div><div class="gv-title">新人专享礼包</div><div class="gv-sub">完成体验立即到账</div></div></div>',
C: '<div class="gv-base gv-c"><div class="gv-icon">🎁</div><div><div class="gv-title">新人专享礼包</div><div class="gv-cd"><span>⏱</span><span id="gvCd">23:45<span class="gv-blink">:</span>12</span><span>后失效</span></div></div></div>',
D: '<div class="gv-base gv-d"><div class="gv-iconwrap"><div class="gv-icon">🎁</div></div><div class="gv-text"><div class="gv-title">新人专享礼包</div><div class="gv-sub">完成体验立即到账</div></div></div>',
E: '<div class="gift-coupon"><div class="gc-icon">🎁</div><div style="flex: 1;min-width: 0;"><div class="gc-title">新人专享礼包</div><div class="gc-sub">完成体验立即到账</div></div></div>',
F: '<div class="gv-base gv-f"><div class="gv-rays"></div><div class="gv-iconwrap"><div class="gv-icon">🎁</div></div><div class="gv-title">新人专享礼包</div><div class="gv-sub">完成体验立即到账</div></div>',
G: '<div class="gv-base gv-g"><div class="gv-iconwrap"><span class="gv-spark gv-s1"></span><span class="gv-spark gv-s2"></span><span class="gv-spark gv-s3"></span><div class="gv-icon">🎁</div></div><div><div class="gv-title">新人专享<em>大礼包</em></div><div class="gv-sub">完成体验立即到账</div></div></div>'
};
let __gvCdTimer = null;
function __gvStartCountdown() {
let total = 23 * 3600 + 45 * 60 + 12;
if (__gvCdTimer) clearInterval(__gvCdTimer);
const tick = () => {
total = Math.max(0, total - 1);
const h = String(Math.floor(total / 3600)).padStart(2, '0');
const m = String(Math.floor((total % 3600) / 60)).padStart(2, '0');
const s = String(total % 60).padStart(2, '0');
const el = document.getElementById('gvCd');
if (el) el.innerHTML = h + ':' + m + '<span class="gv-blink">:</span>' + s;
};
tick();
__gvCdTimer = setInterval(tick, 1000);
}
function applyGiftVariant(letter) {
const container = document.getElementById('giftCardContainer');
if (!container) return;
const key = (letter || 'E').toUpperCase();
const tpl = giftVariantTemplates[key] || giftVariantTemplates.E;
container.innerHTML = tpl;
if (key === 'C') __gvStartCountdown();
}
(function applyGiftVariantURLParams() {
try {
const params = new URLSearchParams(location.search);
const variant = params.get('giftvariant');
const celebVariant = params.get('celebrationvariant');
const celebrate = params.get('celebrate') === '1';
const couponVariant = params.get('couponvariant');
const showCoupon = params.get('showcoupon') === '1';
const ctaVariantParam = params.get('ctavariant');
const screen = params.get('screen');
const embed = params.get('embed') === '1';
const run = function() {
if (embed) document.body.classList.add('gv-embed');
if (variant) applyGiftVariant(variant);
if (celebVariant && celebrationVariants[celebVariant]) {
currentCelebrationVariant = celebVariant;
}
if (screen) { try { go(screen); } catch (e) {} }
if (celebrate) {
try { openCelebrationModal(); } catch (e) {}
}
if (couponVariant && typeof applyCouponPromptVariant === 'function') {
try { applyCouponPromptVariant(couponVariant); } catch (e) {}
}
if (showCoupon && typeof showCouponPromptForPreview === 'function') {
try { showCouponPromptForPreview(); } catch (e) {}
}
if (ctaVariantParam && typeof applyCtaVariant === 'function') {
try { applyCtaVariant(parseInt(ctaVariantParam, 10)); } catch (e) {}
}
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', run);
} else {
run();
}
} catch (e) {}
})();
// 我的页展示完整测试昵称,方便检视长用户名排版
(function () {
function renderProfileNickname() {
var el = document.getElementById('profName');
if (!el) return;
var full = el.getAttribute('data-fullname') || el.textContent || '';
var chars = Array.from(full);
el.textContent = chars.length > 19 ? chars.slice(0, 18).join('') + '...' : full;
el.setAttribute('title', full);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', renderProfileNickname);
} else {
renderProfileNickname();
}
})();
</script>
<!-- ===== Tweaks Panel ===== -->
<div id="tweaksPanel" class="tweaks-panel">
<button class="tweaks-close" onclick="closeTweaks()">×</button>
<h3>「开启省钱之旅」按钮样式</h3>
<div class="tweaks-sub">点击切换,预览不同方案</div>
<div class="tweaks-grid">
<div class="tweaks-opt" data-v="1">红橙渐变<small>当前</small></div>
<div class="tweaks-opt" data-v="2">黄底黑字<small>品牌主色</small></div>
<div class="tweaks-opt" data-v="3">黑底黄字<small>高对比</small></div>
<div class="tweaks-opt" data-v="4">金色光泽<small>动态扫光</small></div>
<div class="tweaks-opt" data-v="5">玻璃质感<small>立体黄</small></div>
<div class="tweaks-opt" data-v="6">描边偏移<small>克制款</small></div>
<div class="tweaks-opt" data-v="7">红包喜庆<small>红+金</small></div>
<div class="tweaks-opt" data-v="8">呼吸跳动<small>动效款</small></div>
<div class="tweaks-opt" data-v="9">蜜糖渐变<small>黄→琥珀</small></div>
<div class="tweaks-opt" data-v="10">金币描边<small>深金细边</small></div>
</div>
<div style="height: 1px;background: #E5E5E5;margin: 16px 0 12px;"></div>
<h3>领券弹窗副标题样式</h3>
<div class="tweaks-sub">主标题下那行小字,强化"收益"信号</div>
<div class="tweaks-grid">
<div class="tweaks-opt sub-opt" data-sv="1">基线灰<small>当前最弱</small></div>
<div class="tweaks-opt sub-opt" data-sv="2">金币胶囊<small>品牌黄徽章</small></div>
<div class="tweaks-opt sub-opt" data-sv="3">关键词高亮<small>黄色荧光笔</small></div>
<div class="tweaks-opt sub-opt" data-sv="4">优惠券小票<small>齿边+朱红</small></div>
<div class="tweaks-opt sub-opt" data-sv="5">数字徽章<small>预计立省¥</small></div>
<div class="tweaks-opt sub-opt" data-sv="6">双行节奏<small>预告+承诺</small></div>
<div class="tweaks-opt sub-opt" data-sv="7">V2b 金币翻转<small>动效活力</small></div>
<div class="tweaks-opt sub-opt" data-sv="8">V2c 双色分段<small>黑黄拼接</small></div>
<div class="tweaks-opt sub-opt" data-sv="9">V2d 闪光描边<small>轻盈款</small></div>
<div class="tweaks-opt sub-opt" data-sv="10">V2e 数字嵌入<small>¥18+ 内嵌</small></div>
<div class="tweaks-opt sub-opt" data-sv="11">V2f 双图标<small>金币+闪电</small></div>
<div class="tweaks-opt sub-opt" data-sv="12">V2g 立体浮起<small>金属高光</small></div>
<div class="tweaks-opt sub-opt" data-sv="13">流程植入<small>领券→比价→底价</small></div>
</div>
<div style="height: 1px;background: #E5E5E5;margin: 16px 0 12px;"></div>
<h3>「完成设置」弹窗版式</h3>
<div class="tweaks-sub">点击切换,下次进入弹窗即生效</div>
<div class="tweaks-grid">
<div class="tweaks-opt celeb-opt" data-cv="v1">轻收尾·重期待<small>承上小,起下大</small></div>
<div class="tweaks-opt celeb-opt" data-cv="v2">分割式<small>三段节奏</small></div>
<div class="tweaks-opt celeb-opt" data-cv="v3">叙事流<small>递进式</small></div>
<div class="tweaks-opt celeb-opt" data-cv="v4">行为优先<small>主舞台让给行为</small></div>
<div class="tweaks-opt celeb-opt" data-cv="v5">徽章+行动卡<small>chip 强调最后一步</small></div>
<div class="tweaks-opt celeb-opt" data-cv="v6">进度条推进<small>脉动黄推进感</small></div>
<div class="tweaks-opt celeb-opt" data-cv="v7">数字步骤<small>① ✓ → ② 当前</small></div>
<div class="tweaks-opt celeb-opt" data-cv="v8">极简专注<small>大字承担引导</small></div>
</div>
<button onclick="previewCelebration()" style="margin-top: 12px;width: 100%;padding: 8px;border-radius: 8px;border: 1px solid #ddd;background: #fff;font-size: 13px;font-weight: 600;cursor: pointer;">▶ 预览当前版式</button>
</div>
<script>
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
"ctaVariant": 5,
"celebVariant": "v3",
"couponSubVariant": 13
}/*EDITMODE-END*/;
let currentCtaVariant = TWEAK_DEFAULTS.ctaVariant || 1;
let currentCouponSubVariant = TWEAK_DEFAULTS.couponSubVariant || 1;
currentCelebrationVariant = TWEAK_DEFAULTS.celebVariant || 'v1';
const couponSubMarkup = {
1: '<div class="cps cps-v1">领取后将为您解锁更低好价</div>',
2: '<div class="cps cps-v2"><span class="cps-coin">¥</span>领取后解锁今日最低价</div>',
3: '<div class="cps cps-v3">领取后将为您解锁<em>全网最低价</em></div>',
4: '<div class="cps cps-v4">已为您锁定 <span class="cps-amt">¥18+</span> 神券</div>',
5: '<div class="cps cps-v5">领取后预计立省<span class="cps-pill">¥8<small>~</small>25</span></div>',
6: '<div class="cps cps-v6"><span class="cps-top">· 预计 3 秒完成 ·</span><span class="cps-bot">领券解锁<em>今日最低价</em></span></div>',
7: '<div class="cps cps-v2b"><span class="cps-coin">¥</span>领取后解锁今日最低价</div>',
8: '<div class="cps cps-v2c"><span class="cps-tag">立省</span><span class="cps-text">解锁今日最低价</span></div>',
9: '<div class="cps cps-v2d"><span class="cps-coin">¥</span>领取后解锁今日最低价</div>',
10: '<div class="cps cps-v2e"><span class="cps-amount">¥18<small>+</small></span>解锁今日最低价</div>',
11: '<div class="cps cps-v2f"><span class="cps-coin">¥</span>领取后解锁<span class="cps-bolt"><svg width="10" height="11" viewBox="0 0 10 11"><path d="M6 0L0 6h3l-1 5 6-6H5z" fill="#1a1a1a"/></svg></span>今日最低价</div>',
12: '<div class="cps cps-v2g"><span class="cps-coin">¥</span>领取后解锁今日最低价</div>',
13: '<div class="cps cps-v3f"><span class="cps-coin"><svg width="15" height="13" viewBox="0 0 22 18" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M2 7.2 V10.8 A1.4 1.4 0 0 0 3.4 12.2 H5.4 L11.2 16.4 A0.8 0.8 0 0 0 12.5 15.7 V2.3 A0.8 0.8 0 0 0 11.2 1.6 L5.4 5.8 H3.4 A1.4 1.4 0 0 0 2 7.2 Z" fill="#8B6914"/><path d="M14.6 4.4 C16 6 16 12 14.6 13.6" stroke="#8B6914" stroke-width="1.4" stroke-linecap="round" fill="none"/><path d="M16.8 2.6 C19.2 5.2 19.2 12.8 16.8 15.4" stroke="#8B6914" stroke-width="1.4" stroke-linecap="round" fill="none" opacity=".55"/><circle cx="6.2" cy="14.4" r="1.5" fill="#8B6914"/></svg></span>先领券,再比价</div>'
};
function applyCouponSubVariant(v) {
currentCouponSubVariant = v;
const slot = document.getElementById('demoCouponSubtitleSlot');
if (slot) slot.innerHTML = couponSubMarkup[v] || couponSubMarkup[1];
document.querySelectorAll('#tweaksPanel .sub-opt').forEach(el => {
el.classList.toggle('active', String(el.dataset.sv) === String(v));
});
}
function applyCelebVariant(cv) {
currentCelebrationVariant = cv;
document.querySelectorAll('#tweaksPanel .celeb-opt').forEach(el => {
el.classList.toggle('active', el.dataset.cv === cv);
});
}
function previewCelebration() {
if (typeof openCelebrationModal === 'function') openCelebrationModal();
}
function applyCtaVariant(v) {
currentCtaVariant = v;
const btn = document.getElementById('splashCTA');
if (!btn) return;
btn.className = 'splash-cta splash-cta-v' + v;
document.querySelectorAll('#tweaksPanel .tweaks-opt').forEach(el => {
el.classList.toggle('active', String(el.dataset.v) === String(v));
});
}
function closeTweaks() {
document.getElementById('tweaksPanel').classList.remove('open');
try { window.parent.postMessage({type:'__edit_mode_dismissed'},'*'); } catch(e){}
}
window.addEventListener('message', (e) => {
const d = e.data || {};
if (d.type === '__activate_edit_mode') document.getElementById('tweaksPanel').classList.add('open');
if (d.type === '__deactivate_edit_mode') document.getElementById('tweaksPanel').classList.remove('open');
});
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('#tweaksPanel .tweaks-opt:not(.celeb-opt):not(.sub-opt)').forEach(el => {
el.addEventListener('click', () => {
const v = parseInt(el.dataset.v, 10);
applyCtaVariant(v);
try { window.parent.postMessage({type:'__edit_mode_set_keys', edits:{ctaVariant: v}}, '*'); } catch(e){}
});
});
document.querySelectorAll('#tweaksPanel .sub-opt').forEach(el => {
el.addEventListener('click', () => {
const v = parseInt(el.dataset.sv, 10);
applyCouponSubVariant(v);
try { window.parent.postMessage({type:'__edit_mode_set_keys', edits:{couponSubVariant: v}}, '*'); } catch(e){}
});
});
document.querySelectorAll('#tweaksPanel .celeb-opt').forEach(el => {
el.addEventListener('click', () => {
const cv = el.dataset.cv;
applyCelebVariant(cv);
try { window.parent.postMessage({type:'__edit_mode_set_keys', edits:{celebVariant: cv}}, '*'); } catch(e){}
});
});
applyCtaVariant(currentCtaVariant);
applyCouponSubVariant(currentCouponSubVariant);
applyCelebVariant(currentCelebrationVariant);
try { window.parent.postMessage({type:'__edit_mode_available'},'*'); } catch(e){}
});
</script>
<script>
(function() {
var ID_TO_PATH = {
"login": "app/login/inapp.html",
"loginPhone": "app/login/phone.html",
"home": "app/home",
"welfare": "app/welfare",
"welfareRules": "app/welfare/rules.html",
"profile": "app/profile",
"invite": "app/welfare/invite.html",
"compresult": "app/compare",
"withdrawal": "app/welfare/withdrawal.html",
"coinhistory": "app/welfare/coinhistory.html",
"reports": "app/profile/reports.html",
"settings": "app/profile/settings.html",
"feedback": "app/profile/feedback.html",
"comparing": "app/compare",
"history": "app/history"
};
var PREFIX = '../../';
function navigate(id) {
// 抢救 inline onclick 设置的 window.loginFrom(隐式 global,不会进 let 绑定)
if (window.loginFrom && typeof window.loginFrom === 'string') {
try { localStorage.setItem('proto_loginFrom', window.loginFrom); } catch(e) {}
}
var p = ID_TO_PATH[id];
if (!p) { console.warn('[nav] unknown id:', id); return; }
location.href = PREFIX + p + (p.indexOf('.html') !== -1 ? '' : '/index.html');
}
window.go = navigate;
window._activateScreen = function(id) { navigate(id); };
window.goBack = function() { if (history.length > 1) history.back(); else navigate('home'); };
window.debugGoBack = window.goBack;
})();
</script>
<script>
// ============================================
// V3: 页面级初始化
// 替代原 go(id) 切到本屏时跑的逻辑
// ============================================
document.addEventListener('DOMContentLoaded', function() {
var isLogged = false;
try { isLogged = localStorage.getItem('proto_isLoggedIn') !== 'false'; } catch(e) {}
var activeScreen = document.querySelector('.screen.active');
if (!activeScreen) return;
var id = activeScreen.id;
// welfare 登录态切换
if (id === 'welfare') {
var wu = document.getElementById('welfareUnlogged');
var wl = document.getElementById('welfareLogged');
if (wu) wu.style.display = isLogged ? 'none' : 'block';
if (wl) wl.style.display = isLogged ? 'block' : 'none';
// 已登录 + 没显示过签到弹窗 → 弹一次
if (isLogged && typeof showCheckinPopup === 'function') {
var checkinShown = false;
try { checkinShown = localStorage.getItem('proto_checkinShown') === 'true'; } catch(e) {}
if (!checkinShown) setTimeout(showCheckinPopup, 500);
}
}
// profile 登录态切换
if (id === 'profile') {
var pu = document.getElementById('profileUnlogged');
var pl = document.getElementById('profileLogged');
if (!isLogged) {
// 未登录默认自动跳登录页;URL 带 ?view=unlogged 表示从 login 返回,显示未登录态
var profParams = new URLSearchParams(window.location.search);
if (profParams.get('view') === 'unlogged') {
if (pu) pu.style.display = 'block';
if (pl) pl.style.display = 'none';
} else {
try { localStorage.setItem('proto_loginFrom', 'profile'); } catch(e) {}
location.replace('../login/inapp.html');
return;
}
} else {
if (pu) pu.style.display = 'none';
if (pl) pl.style.display = 'block';
}
}
// productselect 自动开始平台扫描
if (id === 'productselect') {
if (typeof startPlatformScan === 'function') {
try { startPlatformScan(); } catch(e) { console.warn(e); }
}
}
// celebration 动画 + 数据
if (id === 'celebration') {
if (typeof renderCelebrationSavings === 'function') try { renderCelebrationSavings(); } catch(e){}
if (typeof renderResults === 'function') try { renderResults('celebResults'); } catch(e){}
if (typeof startConfetti === 'function') try { startConfetti(); } catch(e){}
}
// comparing 自动开始比价动画
if (id === 'comparing') {
if (typeof startCompareAnimation === 'function') try { startCompareAnimation(); } catch(e){}
if (typeof startComparing === 'function') try { startComparing(); } catch(e){}
}
});
</script>
<script>
// === 调试用:右下角"重置"按钮,仅 file:// 本地预览可见 ===
(function() {
if (location.protocol !== 'file:') return;
if (document.getElementById('debugReset')) return;
function mount() {
var btn = document.createElement('div');
btn.id = 'debugReset';
btn.textContent = '↻ 重置'; // ↻ 重置
btn.title = '清空 localStorage 并刷新(仅本地预览可见)';
btn.style.cssText = 'position:fixed;right:0;bottom:0;z-index:99999;background:#000;color:#fff;font-size:11px;font-weight:700;padding:8px;border-radius:4px 0 0 0;cursor:pointer;opacity:.7;line-height:1;letter-spacing:1px;font-family:inherit;';
btn.onclick = function() {
try { localStorage.clear(); } catch(e) {}
location.reload();
};
document.body.appendChild(btn);
}
if (document.body) mount();
else document.addEventListener('DOMContentLoaded', mount);
})();
</script>
<script>
(function() {
function getTodayKey() {
var d = new Date();
return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
}
function updateWelfareCheckinTabDot() {
var tab = document.getElementById('homeTabWelfare');
if (!tab) return;
var done = false;
try { done = localStorage.getItem('proto_checkinDoneDate') === getTodayKey(); } catch(e) {}
tab.classList.toggle('has-welfare-dot', !done);
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', updateWelfareCheckinTabDot);
else updateWelfareCheckinTabDot();
})();
</script>
</body>
</html>