@seaverse/payment-sdk 0.9.2 → 0.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2196,24 +2196,19 @@ class PaymentModal {
2196
2196
  *
2197
2197
  * 设计风格:深色卡片 + 清晰信息层次 + 渐变 CTA 按钮
2198
2198
  */
2199
- /* ─── 设计 Token(深色主题) ─── */
2199
+ /* ─── 设计 Token(与 order-popups PendingPopup 一致) ─── */
2200
2200
  const D = {
2201
- // 背景
2202
- bgOverlay: 'rgba(0, 0, 0, 0.80)',
2203
- bgCard: 'linear-gradient(180deg, #1e293b 0%, #0f172a 100%)',
2204
- bgInnerCard: 'rgba(255, 255, 255, 0.04)',
2205
- bgInnerBorder: 'rgba(255, 255, 255, 0.08)',
2206
- // 文字
2207
- textWhite: '#fff',
2208
- textSecondary: 'rgba(255, 255, 255, 0.55)',
2209
- // 强调色
2210
- accentRed: '#f87171',
2211
- accentTeal: 'linear-gradient(135deg, #2dd4bf 0%, #22d3ee 100%)',
2212
- accentTealShadow: 'rgba(45, 212, 191, 0.35)',
2213
- // 分隔线
2214
- divider: 'rgba(255, 255, 255, 0.06)',
2215
- // 圆角
2216
- radiusCard: '20px',
2201
+ bgOverlay: 'rgba(0, 0, 0, 0.85)',
2202
+ bgCard: '#121212',
2203
+ bgCardBorder: 'rgba(44, 44, 46, 0.6)',
2204
+ bgSurface: '#1E1E1E',
2205
+ bgSurfaceHighlight: '#2A2A2E',
2206
+ borderSubtle: 'rgba(255, 255, 255, 0.05)',
2207
+ textWhite: '#FFFFFF',
2208
+ textMuted: '#A1A1AA',
2209
+ timerRed: '#EF4444',
2210
+ brandGreen: '#10B981',
2211
+ radiusCard: '24px',
2217
2212
  radiusInner: '12px',
2218
2213
  radiusBtn: '12px',
2219
2214
  };
@@ -2275,27 +2270,30 @@ class RetentionModal {
2275
2270
  */
2276
2271
  createModal() {
2277
2272
  const { language, productName, purchaseAmount, bonusAmount, discountPrice } = this.options;
2278
- const isZh = language === 'zh';
2273
+ const lang = language ?? 'en';
2274
+ const isZh = lang === 'zh' || lang === 'zh-TW';
2279
2275
  const t = isZh ? {
2280
2276
  title: '你有一笔订单待支付',
2281
- timePrefix: '请在',
2282
- timeSuffix: '内支付,超时订单将自动取消',
2283
- productLabel: 'Product:',
2284
- amountLabel: 'Amount:',
2285
- bonusLabel: 'Bonus:',
2277
+ timePrefix: '请在 ',
2278
+ timeSuffix: ' 内支付,超时自动取消',
2279
+ productLabel: '商品',
2280
+ quantityLabel: '数量',
2281
+ priceLabel: '优惠价',
2282
+ bonusLabel: '奖励',
2286
2283
  cancelBtn: '取消',
2287
2284
  continueBtn: '继续支付',
2288
2285
  } : {
2289
2286
  title: 'You have a pending order',
2290
- timePrefix: 'Please pay within',
2291
- timeSuffix: 'or the order will be automatically cancelled',
2287
+ timePrefix: 'Please pay within ',
2288
+ timeSuffix: ', auto-cancelled if timeout',
2292
2289
  productLabel: 'Product:',
2293
- amountLabel: 'Amount:',
2290
+ quantityLabel: 'Quantity:',
2291
+ priceLabel: 'Price:',
2294
2292
  bonusLabel: 'Bonus:',
2295
2293
  cancelBtn: 'Cancel',
2296
- continueBtn: 'Continue Payment',
2294
+ continueBtn: 'Pay Now',
2297
2295
  };
2298
- // ─── 遮罩 ───
2296
+ // ─── 遮罩(与 order-popups 一致) ───
2299
2297
  this.overlay = document.createElement('div');
2300
2298
  this.overlay.id = 'retention-modal-overlay';
2301
2299
  this.overlay.style.cssText = `
@@ -2303,137 +2301,130 @@ class RetentionModal {
2303
2301
  display: flex; align-items: center; justify-content: center;
2304
2302
  padding: 24px;
2305
2303
  background: ${D.bgOverlay};
2306
- backdrop-filter: blur(6px);
2304
+ backdrop-filter: blur(8px);
2307
2305
  animation: rm-fadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);
2308
2306
  `;
2309
- // ─── 卡片 ───
2307
+ // ─── 卡片(order-popups: bg-dark-card, rounded-[24px], border dark-border) ───
2310
2308
  this.modal = document.createElement('div');
2311
2309
  this.modal.style.cssText = `
2312
2310
  position: relative;
2313
- width: 90vw; max-width: 520px;
2311
+ width: 90vw; max-width: 500px; min-width: 420px;
2314
2312
  border-radius: ${D.radiusCard};
2315
2313
  background: ${D.bgCard};
2316
- box-shadow: 0 24px 48px -12px rgba(0, 0, 0, 0.6);
2314
+ border: 1px solid ${D.bgCardBorder};
2315
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
2316
+ padding: 24px;
2317
2317
  animation: rm-slideIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);
2318
2318
  overflow: hidden;
2319
2319
  `;
2320
- // ─── 构建 HTML ───
2320
+ // ─── 构建 HTML(与 order-popups PendingPopup + 图片布局一致) ───
2321
2321
  this.modal.innerHTML = `
2322
- <!-- 关闭按钮 -->
2322
+ <!-- 关闭按钮(order-popups: top-5 right-5, rounded-full, text-dark-muted) -->
2323
2323
  <button type="button" id="retention-modal-close-btn" style="
2324
- position: absolute; top: 18px; right: 18px; z-index: 10;
2325
- display: flex; width: 34px; height: 34px;
2324
+ position: absolute; top: 20px; right: 20px; z-index: 10;
2325
+ display: flex; width: 40px; height: 40px;
2326
2326
  align-items: center; justify-content: center;
2327
2327
  border-radius: 50%;
2328
- background: rgba(255,255,255,0.08);
2329
- color: rgba(255,255,255,0.5);
2328
+ background: transparent;
2329
+ color: ${D.textMuted};
2330
2330
  border: none; cursor: pointer;
2331
- transition: all 0.2s;
2331
+ transition: color 0.2s, background 0.2s;
2332
2332
  ">
2333
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none">
2334
- <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
2333
+ <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
2334
+ <line x1="18" y1="6" x2="6" y2="18"></line>
2335
+ <line x1="6" y1="6" x2="18" y2="18"></line>
2335
2336
  </svg>
2336
2337
  </button>
2337
2338
 
2338
- <!-- 标题区域 -->
2339
- <div style="padding: 44px 36px 28px; text-align: center;">
2340
- <h2 style="
2341
- margin: 0 0 14px;
2342
- font-size: 22px;
2339
+ <!-- 标题区域(order-popups: text-2xl font-bold, timer in red font-mono) -->
2340
+ <div style="padding: 16px 0 32px; text-align: center;">
2341
+ <h1 style="
2342
+ margin: 0 0 8px;
2343
+ font-size: 24px;
2343
2344
  font-weight: 700;
2344
2345
  color: ${D.textWhite};
2345
- letter-spacing: -0.3px;
2346
- ">${t.title}</h2>
2346
+ letter-spacing: -0.02em;
2347
+ ">${t.title}</h1>
2347
2348
  <p style="
2348
2349
  margin: 0;
2349
2350
  font-size: 14px;
2350
- color: ${D.textSecondary};
2351
- line-height: 1.5;
2351
+ color: ${D.textMuted};
2352
+ display: flex;
2353
+ align-items: center;
2354
+ justify-content: center;
2355
+ flex-wrap: wrap;
2356
+ gap: 2px;
2352
2357
  ">
2353
- ${t.timePrefix}
2354
- <span id="countdown-display" style="
2355
- color: ${D.accentRed};
2358
+ ${t.timePrefix}<span id="countdown-display" style="
2359
+ color: ${D.timerRed};
2356
2360
  font-weight: 700;
2357
2361
  font-variant-numeric: tabular-nums;
2358
- ">00:15:00</span>
2359
- ${t.timeSuffix}
2362
+ font-family: ui-monospace, monospace;
2363
+ ">00:15:00</span>${t.timeSuffix}
2360
2364
  </p>
2361
2365
  </div>
2362
2366
 
2363
- <!-- 分隔线 -->
2364
- <div style="height: 1px; background: ${D.divider}; margin: 0 36px;"></div>
2365
-
2366
- <!-- 订单详情 -->
2367
- <div style="padding: 28px 36px;">
2368
- <div style="
2369
- border-radius: ${D.radiusInner};
2370
- border: 1px solid ${D.bgInnerBorder};
2371
- background: ${D.bgInnerCard};
2372
- overflow: hidden;
2373
- ">
2374
- <!-- Product -->
2375
- <div style="
2376
- display: flex; align-items: center; justify-content: space-between;
2377
- padding: 16px 20px;
2378
- border-bottom: 1px solid ${D.divider};
2379
- ">
2380
- <span style="font-size: 14px; color: ${D.textSecondary};">${t.productLabel}</span>
2381
- <span style="font-size: 14px; font-weight: 600; color: ${D.textWhite};">${this.escapeHtml(productName)}</span>
2367
+ <!-- 订单详情卡片(order-popups: rounded-xl border border-white/5,上 part surface,下 part surfaceHighlight) -->
2368
+ <div style="
2369
+ border-radius: ${D.radiusInner};
2370
+ overflow: hidden;
2371
+ border: 1px solid ${D.borderSubtle};
2372
+ margin-bottom: 32px;
2373
+ ">
2374
+ <!-- 上:Product + Quantity -->
2375
+ <div style="background: ${D.bgSurface}; padding: 20px; display: flex; flex-direction: column; gap: 16px;">
2376
+ <div style="display: flex; justify-content: space-between; align-items: center; font-size: 14px;">
2377
+ <span style="color: ${D.textMuted}; min-width: 64px;">${t.productLabel}</span>
2378
+ <span style="color: ${D.textWhite}; font-weight: 500; text-align: right; word-break: break-word;">${this.escapeHtml(productName)}</span>
2382
2379
  </div>
2383
-
2384
- <!-- Amount -->
2385
- <div style="
2386
- display: flex; align-items: center; justify-content: space-between;
2387
- padding: 16px 20px;
2388
- border-bottom: 1px solid ${D.divider};
2389
- ">
2390
- <span style="font-size: 14px; color: ${D.textSecondary};">${t.amountLabel}</span>
2391
- <span style="font-size: 14px; font-weight: 600; color: ${D.textWhite};">${discountPrice}</span>
2380
+ <div style="display: flex; justify-content: space-between; align-items: center; font-size: 14px;">
2381
+ <span style="color: ${D.textMuted}; min-width: 64px;">${t.quantityLabel}</span>
2382
+ <span style="color: ${D.textWhite}; font-weight: 500; text-align: right;">${purchaseAmount.toLocaleString()}</span>
2392
2383
  </div>
2393
-
2394
2384
  ${bonusAmount ? `
2395
- <!-- Bonus -->
2396
- <div style="
2397
- display: flex; align-items: center; justify-content: space-between;
2398
- padding: 16px 20px;
2399
- border-bottom: 1px solid ${D.divider};
2400
- ">
2401
- <span style="font-size: 14px; color: ${D.textSecondary};">${t.bonusLabel}</span>
2402
- <span style="font-size: 14px; font-weight: 600; color: ${D.textWhite};">${bonusAmount.toLocaleString()}</span>
2385
+ <div style="display: flex; justify-content: space-between; align-items: center; font-size: 14px;">
2386
+ <span style="color: ${D.textMuted}; min-width: 64px;">${t.bonusLabel}</span>
2387
+ <span style="color: ${D.textWhite}; font-weight: 500; text-align: right;">${bonusAmount.toLocaleString()}</span>
2403
2388
  </div>
2404
2389
  ` : ''}
2405
-
2406
-
2390
+ </div>
2391
+ <!-- 下:Price(图片:大号绿色金额) -->
2392
+ <div style="
2393
+ background: ${D.bgSurfaceHighlight};
2394
+ padding: 20px;
2395
+ display: flex;
2396
+ justify-content: space-between;
2397
+ align-items: center;
2398
+ border-top: 1px solid ${D.borderSubtle};
2399
+ ">
2400
+ <span style="font-size: 14px; color: ${D.textMuted}">${t.priceLabel}</span>
2401
+ <span style="font-size: 24px; font-weight: 700; color: ${D.brandGreen}; letter-spacing: 0.02em;">${this.escapeHtml(discountPrice)}</span>
2407
2402
  </div>
2408
2403
  </div>
2409
2404
 
2410
- <!-- 按钮组 -->
2411
- <div style="display: flex; gap: 12px; padding: 0 36px 36px;">
2405
+ <!-- 按钮组(order-popups: grid grid-cols-2 gap-4, Cancel=white/5 border, Pay=#10b981) -->
2406
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px;">
2412
2407
  <button type="button" id="retention-cancel-btn" style="
2413
- flex: 1;
2414
2408
  padding: 14px 20px;
2415
2409
  border-radius: ${D.radiusBtn};
2416
- border: 1px solid rgba(255,255,255,0.15);
2417
- background: transparent;
2418
- color: ${D.textWhite};
2419
- font-size: 15px;
2420
- font-weight: 600;
2410
+ border: 1px solid rgba(255,255,255,0.1);
2411
+ background: rgba(255,255,255,0.05);
2412
+ color: ${D.textMuted};
2413
+ font-size: 14px;
2414
+ font-weight: 500;
2421
2415
  cursor: pointer;
2422
- transition: all 0.2s;
2416
+ transition: background 0.2s, color 0.2s, border-color 0.2s;
2423
2417
  ">${t.cancelBtn}</button>
2424
-
2425
2418
  <button type="button" id="retention-continue-btn" style="
2426
- flex: 1;
2427
2419
  padding: 14px 20px;
2428
2420
  border-radius: ${D.radiusBtn};
2429
2421
  border: none;
2430
- background: ${D.accentTeal};
2431
- color: #0f172a;
2432
- font-size: 15px;
2422
+ background: ${D.brandGreen};
2423
+ color: #000000;
2424
+ font-size: 14px;
2433
2425
  font-weight: 700;
2434
2426
  cursor: pointer;
2435
- transition: all 0.2s;
2436
- box-shadow: 0 4px 16px ${D.accentTealShadow};
2427
+ transition: box-shadow 0.2s, transform 0.1s;
2437
2428
  ">${t.continueBtn}</button>
2438
2429
  </div>
2439
2430
  `;
@@ -2468,20 +2459,20 @@ class RetentionModal {
2468
2459
  }
2469
2460
 
2470
2461
  #retention-modal-close-btn:hover {
2471
- background: rgba(255,255,255,0.15) !important;
2472
- color: #fff !important;
2473
- transform: rotate(90deg);
2462
+ background: rgba(255,255,255,0.05) !important;
2463
+ color: #FFFFFF !important;
2474
2464
  }
2475
2465
  #retention-cancel-btn:hover {
2476
- background: rgba(255,255,255,0.08) !important;
2477
- border-color: rgba(255,255,255,0.25) !important;
2466
+ background: rgba(255,255,255,0.1) !important;
2467
+ color: #FFFFFF !important;
2468
+ border-color: rgba(255,255,255,0.1) !important;
2478
2469
  }
2479
2470
  #retention-continue-btn:hover {
2480
- box-shadow: 0 6px 24px rgba(45, 212, 191, 0.50) !important;
2481
- transform: translateY(-1px);
2471
+ box-shadow: 0 0 20px rgba(16, 185, 129, 0.4) !important;
2472
+ transform: scale(1.02);
2482
2473
  }
2483
2474
  #retention-continue-btn:active {
2484
- transform: translateY(0);
2475
+ transform: scale(0.98);
2485
2476
  }
2486
2477
  `;
2487
2478
  document.head.appendChild(style);
@@ -2852,6 +2843,64 @@ class DropinPaymentModal {
2852
2843
  }
2853
2844
  }
2854
2845
 
2846
+ /**
2847
+ * 共享配置文件
2848
+ * Shared configuration for CreditPackageModal and GenericPackageModal
2849
+ */
2850
+ /**
2851
+ * 环境配置映射表
2852
+ * SDK 根据 environment 参数自动选择对应的配置
2853
+ */
2854
+ const ENVIRONMENT_CONFIGS = {
2855
+ development: {
2856
+ scriptUrl: 'https://seaart-publish.sc-api-release.saconsole.com/payment-component/client.js',
2857
+ clientId: 'XF49NOfyZ54O16GujB0ptio2',
2858
+ orderApiUrl: 'https://payment.sg.seaverse.dev',
2859
+ walletApiUrl: 'https://wallet.sg.seaverse.dev',
2860
+ cssUrl: 'https://seaart-publish.sc-api-release.saconsole.com/payment-component/public/style.css',
2861
+ },
2862
+ production: {
2863
+ scriptUrl: 'https://seaart-publish.sc-api.saconsole.com/payment-component/client.js',
2864
+ clientId: 'XF11ik3u5AJ16IyDI3hebq5',
2865
+ orderApiUrl: 'https://payment.seaverse.com',
2866
+ walletApiUrl: 'https://wallet.seaverse.com',
2867
+ cssUrl: 'https://seaart-publish.sc-api.saconsole.com/payment-component/public/style.css',
2868
+ },
2869
+ };
2870
+ /**
2871
+ * 响应式断点配置
2872
+ * Responsive breakpoints for grid layout
2873
+ */
2874
+ const RESPONSIVE_BREAKPOINTS = {
2875
+ mobile: 768,
2876
+ tablet: 1200,
2877
+ laptop: 1400,
2878
+ desktop: Infinity,
2879
+ };
2880
+ /**
2881
+ * 网格列数配置
2882
+ * Grid columns for different screen sizes
2883
+ */
2884
+ const GRID_COLUMNS = {
2885
+ mobile: 1,
2886
+ tablet: 2,
2887
+ laptop: 2,
2888
+ desktop: 4,
2889
+ };
2890
+ /**
2891
+ * SDK 初始化配置
2892
+ */
2893
+ const SDK_CONFIG = {
2894
+ /** 默认脚本加载超时 (毫秒) */
2895
+ DEFAULT_SCRIPT_TIMEOUT: 10000,
2896
+ /** 默认 SDK 初始化超时 (毫秒) */
2897
+ DEFAULT_INIT_TIMEOUT: 30000,
2898
+ /** 默认最大重试次数 */
2899
+ DEFAULT_MAX_RETRIES: 1,
2900
+ /** 默认业务类型 (1=一次性购买, 2=订阅) */
2901
+ DEFAULT_BUSINESS_TYPE: 1,
2902
+ };
2903
+
2855
2904
  /**
2856
2905
  * SeaartPaymentSDK
2857
2906
  * 基于 SeaartPaymentComponent 的支付 SDK 封装
@@ -2888,22 +2937,22 @@ class SeaartPaymentSDK {
2888
2937
  return;
2889
2938
  }
2890
2939
  console.log('[SeaartPaymentSDK] Initializing...', {
2891
- scriptUrl: config.scriptUrl,
2892
- clientId: config.clientId,
2940
+ scriptUrl: ENVIRONMENT_CONFIGS[config.environment].scriptUrl,
2941
+ clientId: ENVIRONMENT_CONFIGS[config.environment].clientId,
2893
2942
  language: config.language,
2894
- cssUrl: config.cssUrl,
2943
+ cssUrl: ENVIRONMENT_CONFIGS[config.environment].cssUrl,
2895
2944
  });
2896
2945
  try {
2897
2946
  // 1. 并行加载 CSS 和 JavaScript
2898
2947
  const loadTasks = [
2899
2948
  ScriptLoader.loadSeaartPaymentComponent({
2900
- scriptUrl: config.scriptUrl,
2949
+ scriptUrl: ENVIRONMENT_CONFIGS[config.environment].scriptUrl,
2901
2950
  timeout: config.scriptTimeout || 10000,
2902
2951
  }),
2903
2952
  ];
2904
2953
  // 2. 如果提供了 CSS URL,则加载样式表
2905
- if (config.cssUrl) {
2906
- loadTasks.push(StylesheetLoader.loadPaymentStylesheet(config.cssUrl));
2954
+ if (ENVIRONMENT_CONFIGS[config.environment].cssUrl) {
2955
+ loadTasks.push(StylesheetLoader.loadPaymentStylesheet(ENVIRONMENT_CONFIGS[config.environment].cssUrl));
2907
2956
  }
2908
2957
  // 3. 等待所有资源加载完成
2909
2958
  await Promise.all(loadTasks);
@@ -3294,64 +3343,6 @@ async function getCreditDetail(apiHost, authToken) {
3294
3343
  }
3295
3344
  }
3296
3345
 
3297
- /**
3298
- * 共享配置文件
3299
- * Shared configuration for CreditPackageModal and GenericPackageModal
3300
- */
3301
- /**
3302
- * 环境配置映射表
3303
- * SDK 根据 environment 参数自动选择对应的配置
3304
- */
3305
- const ENVIRONMENT_CONFIGS = {
3306
- development: {
3307
- scriptUrl: 'https://seaart-publish.sc-api-release.saconsole.com/payment-component/client.js',
3308
- clientId: 'XF49NOfyZ54O16GujB0ptio2',
3309
- orderApiUrl: 'https://payment.sg.seaverse.dev',
3310
- walletApiUrl: 'https://wallet.sg.seaverse.dev',
3311
- cssUrl: 'https://seaart-publish.sc-api-release.saconsole.com/payment-component/public/style.css',
3312
- },
3313
- production: {
3314
- scriptUrl: 'https://seaart-publish.sc-api.saconsole.com/payment-component/client.js',
3315
- clientId: 'prod_client_id',
3316
- orderApiUrl: 'https://payment.seaverse.com',
3317
- walletApiUrl: 'https://wallet.seaverse.com',
3318
- cssUrl: 'https://seaart-publish.sc-api.saconsole.com/payment-component/public/style.css',
3319
- },
3320
- };
3321
- /**
3322
- * 响应式断点配置
3323
- * Responsive breakpoints for grid layout
3324
- */
3325
- const RESPONSIVE_BREAKPOINTS = {
3326
- mobile: 768,
3327
- tablet: 1200,
3328
- laptop: 1400,
3329
- desktop: Infinity,
3330
- };
3331
- /**
3332
- * 网格列数配置
3333
- * Grid columns for different screen sizes
3334
- */
3335
- const GRID_COLUMNS = {
3336
- mobile: 1,
3337
- tablet: 2,
3338
- laptop: 2,
3339
- desktop: 4,
3340
- };
3341
- /**
3342
- * SDK 初始化配置
3343
- */
3344
- const SDK_CONFIG = {
3345
- /** 默认脚本加载超时 (毫秒) */
3346
- DEFAULT_SCRIPT_TIMEOUT: 10000,
3347
- /** 默认 SDK 初始化超时 (毫秒) */
3348
- DEFAULT_INIT_TIMEOUT: 30000,
3349
- /** 默认最大重试次数 */
3350
- DEFAULT_MAX_RETRIES: 1,
3351
- /** 默认业务类型 (1=一次性购买, 2=订阅) */
3352
- DEFAULT_BUSINESS_TYPE: 1,
3353
- };
3354
-
3355
3346
  /**
3356
3347
  * 共享类型定义
3357
3348
  * Shared types for CreditPackageModal and GenericPackageModal
@@ -3761,8 +3752,9 @@ class PurchaseSuccessModal {
3761
3752
  */
3762
3753
  createModal() {
3763
3754
  const { data, language } = this.options;
3764
- const isZh = language === 'zh';
3765
- // 创建遮罩层
3755
+ const lang = language ?? 'en';
3756
+ const isZh = lang === 'zh' || lang === 'zh-TW';
3757
+ // 创建遮罩层(与 order-popups 一致:纯黑底)
3766
3758
  this.overlay = document.createElement('div');
3767
3759
  this.overlay.id = 'purchase-success-modal-overlay';
3768
3760
  this.overlay.style.cssText = `
@@ -3773,21 +3765,24 @@ class PurchaseSuccessModal {
3773
3765
  align-items: center;
3774
3766
  justify-content: center;
3775
3767
  padding: 20px;
3776
- background: rgba(15, 23, 42, 0.75);
3768
+ background: rgba(0, 0, 0, 0.85);
3777
3769
  backdrop-filter: blur(8px);
3778
3770
  animation: fadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);
3779
3771
  overflow: hidden;
3780
3772
  `;
3781
- // 创建弹窗卡片
3773
+ // 创建弹窗卡片(order-popups: dark-card #121212, rounded-[24px], border dark-border)
3782
3774
  this.modal = document.createElement('div');
3783
3775
  this.modal.style.cssText = `
3784
3776
  position: relative;
3785
3777
  width: 90vw;
3786
- max-width: 480px;
3787
- border-radius: 16px;
3788
- background: linear-gradient(to bottom, #0f172a, #1e293b);
3789
- box-shadow: 0 20px 40px -10px rgba(0, 0, 0, 0.5);
3778
+ max-width: 500px;
3779
+ min-width: 420px;
3780
+ border-radius: 24px;
3781
+ background: #121212;
3782
+ border: 1px solid rgba(44, 44, 46, 0.6);
3783
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
3790
3784
  animation: slideInUp 0.3s cubic-bezier(0.4, 0, 0.2, 1);
3785
+ overflow: hidden;
3791
3786
  `;
3792
3787
  this.modal.innerHTML = this.getModalHTML(data, isZh);
3793
3788
  this.overlay.appendChild(this.modal);
@@ -3806,211 +3801,121 @@ class PurchaseSuccessModal {
3806
3801
  message: '感谢您的购买。您的积分已成功添加到账户中。',
3807
3802
  packLabel: '套餐名称',
3808
3803
  creditsLabel: '积分数量',
3809
- amountLabel: '支付金额',
3810
- badge: '已支付',
3811
- } : {
3804
+ amountLabel: '支付金额'} : {
3812
3805
  title: 'Purchase Successful!',
3813
3806
  subtitle: 'Your credits have been added',
3814
3807
  greeting: 'Hi there,',
3815
3808
  message: 'Thank you for your purchase. Your credits have been successfully added to your account.',
3816
3809
  packLabel: 'Package',
3817
3810
  creditsLabel: 'Credits',
3818
- amountLabel: 'Amount',
3819
- badge: 'PAID',
3820
- };
3811
+ amountLabel: 'Amount'};
3821
3812
  const currency = getCurrencySymbol(data.currency || 'USD');
3813
+ const creditsText = isZh ? `${data.credits.toLocaleString()} 积分` : `${data.credits.toLocaleString()} Credits`;
3822
3814
  return `
3823
- <!-- 关闭按钮 -->
3815
+ <!-- 关闭按钮(order-popups: top-5 right-5, rounded-full, text-dark-muted, hover:bg-white/5) -->
3824
3816
  <button
3825
3817
  type="button"
3826
3818
  id="success-modal-close-btn"
3827
3819
  style="
3828
3820
  position: absolute;
3829
- top: 14px;
3830
- right: 14px;
3821
+ top: 20px;
3822
+ right: 20px;
3831
3823
  z-index: 10;
3832
3824
  display: flex;
3833
- width: 32px;
3834
- height: 32px;
3825
+ width: 40px;
3826
+ height: 40px;
3835
3827
  align-items: center;
3836
3828
  justify-content: center;
3837
3829
  border-radius: 50%;
3838
- background: rgba(255, 255, 255, 0.1);
3839
- color: rgba(255, 255, 255, 0.7);
3830
+ background: transparent;
3831
+ color: #A1A1AA;
3840
3832
  border: none;
3841
3833
  cursor: pointer;
3842
- transition: all 0.2s;
3834
+ transition: color 0.2s, background 0.2s;
3843
3835
  "
3844
3836
  >
3845
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none">
3846
- <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
3837
+ <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
3838
+ <line x1="18" y1="6" x2="6" y2="18"></line>
3839
+ <line x1="6" y1="6" x2="18" y2="18"></line>
3847
3840
  </svg>
3848
3841
  </button>
3849
3842
 
3850
- <!-- 头部 -->
3843
+ <!-- 成功状态与标题(与图片一致:大号绿色勾 + 紧凑布局) -->
3851
3844
  <div style="
3852
- border-radius: 16px 16px 0 0;
3853
- background: linear-gradient(to bottom, rgba(16, 185, 129, 0.1), transparent);
3854
- padding: 32px 24px;
3845
+ display: flex;
3846
+ flex-direction: column;
3847
+ align-items: center;
3855
3848
  text-align: center;
3849
+ padding: 32px 24px 24px;
3856
3850
  ">
3857
- <!-- Success Icon -->
3851
+ <!-- Success Icon:绿色实心圆 + 白色勾 -->
3858
3852
  <div style="
3859
- margin: 0 auto 12px;
3860
- width: 64px;
3861
- height: 64px;
3853
+ width: 72px;
3854
+ height: 72px;
3855
+ margin-bottom: 20px;
3862
3856
  animation: scaleIn 0.4s cubic-bezier(0.4, 0, 0.2, 1);
3863
3857
  ">
3864
- <svg width="64" height="64" viewBox="0 0 80 80" fill="none">
3865
- <circle cx="40" cy="40" r="36" fill="#10B981" fill-opacity="0.1" />
3866
- <circle cx="40" cy="40" r="28" fill="#10B981" fill-opacity="0.2" />
3867
- <path d="M28 40L36 48L52 32" stroke="#10B981" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
3858
+ <svg width="72" height="72" viewBox="0 0 72 72" fill="none">
3859
+ <circle cx="36" cy="36" r="36" fill="#52AD5F"/>
3860
+ <path d="M22 36 L32 46 L50 26" stroke="#FFFFFF" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
3868
3861
  </svg>
3869
3862
  </div>
3870
-
3871
- <!-- Title -->
3872
- <h2 style="
3873
- margin: 0 0 6px;
3874
- font-size: 24px;
3863
+ <h1 style="
3864
+ margin: 0 0 12px;
3865
+ font-size: 28px;
3875
3866
  font-weight: 700;
3876
- color: white;
3877
- animation: fadeInUp 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.2s backwards;
3878
- ">${texts.title}</h2>
3879
-
3880
- <!-- Subtitle -->
3867
+ color: #FFFFFF;
3868
+ letter-spacing: 0.02em;
3869
+ ">${texts.title}</h1>
3881
3870
  <p style="
3882
3871
  margin: 0;
3883
- font-size: 13px;
3884
- color: rgba(255, 255, 255, 0.6);
3885
- animation: fadeInUp 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.3s backwards;
3872
+ font-size: 16px;
3873
+ color: #A1A1AA;
3886
3874
  ">${texts.subtitle}</p>
3887
3875
  </div>
3888
3876
 
3889
- <!-- 内容区域 -->
3890
- <div style="padding: 0 24px 32px;">
3891
- <!-- 确认卡片 -->
3877
+ <!-- 详情卡片(order-popups: bg-dark-surface/50, rounded-xl, border border-white/5) -->
3878
+ <div style="
3879
+ margin: 0 24px 24px;
3880
+ padding: 20px;
3881
+ border-radius: 12px;
3882
+ background: rgba(30, 30, 30, 0.5);
3883
+ border: 1px solid rgba(255, 255, 255, 0.05);
3884
+ ">
3885
+ <!-- 问候语(border-b border-white/10) -->
3892
3886
  <div style="
3893
- overflow: hidden;
3894
- border-radius: 12px;
3895
- border: 1px solid rgba(255, 255, 255, 0.1);
3896
- background: #1e293b;
3897
- animation: fadeInUp 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.4s backwards;
3887
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
3888
+ padding-bottom: 16px;
3889
+ margin-bottom: 16px;
3898
3890
  ">
3899
- <!-- 卡片头部 -->
3900
- <div style="
3901
- display: flex;
3902
- align-items: center;
3903
- justify-content: space-between;
3904
- border-bottom: 1px solid rgba(255, 255, 255, 0.05);
3905
- background: #0f172a;
3906
- padding: 16px;
3907
- ">
3908
- <div style="
3909
- display: flex;
3910
- align-items: center;
3911
- gap: 8px;
3912
- color: #10B981;
3913
- ">
3914
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none">
3915
- <path d="M12 2L2 7L12 12L22 7L12 2Z" fill="currentColor" opacity="0.3" />
3916
- <path d="M2 17L12 22L22 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
3917
- <path d="M2 12L12 17L22 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
3918
- </svg>
3919
- <span style="
3920
- font-size: 15px;
3921
- font-weight: 600;
3922
- ">SeaVerse</span>
3923
- </div>
3924
- <div style="
3925
- border-radius: 9999px;
3926
- border: 1px solid rgba(168, 85, 247, 0.3);
3927
- background: rgba(168, 85, 247, 0.1);
3928
- padding: 4px 12px;
3929
- font-size: 11px;
3930
- font-weight: 500;
3931
- color: #a855f7;
3932
- ">${texts.badge}</div>
3933
- </div>
3891
+ <h2 style="
3892
+ margin: 0 0 8px;
3893
+ font-size: 18px;
3894
+ font-weight: 600;
3895
+ color: #FFFFFF;
3896
+ ">${texts.greeting}</h2>
3897
+ <p style="
3898
+ margin: 0;
3899
+ font-size: 14px;
3900
+ line-height: 1.6;
3901
+ color: #A1A1AA;
3902
+ ">${texts.message}</p>
3903
+ </div>
3934
3904
 
3935
- <!-- 问候语 -->
3936
- <div style="
3937
- border-bottom: 1px solid rgba(255, 255, 255, 0.05);
3938
- padding: 20px 16px;
3939
- ">
3940
- <p style="
3941
- margin: 0 0 8px;
3942
- font-size: 13px;
3943
- font-weight: 600;
3944
- color: rgba(255, 255, 255, 0.9);
3945
- ">${texts.greeting}</p>
3946
- <p style="
3947
- margin: 0;
3948
- font-size: 12px;
3949
- line-height: 1.6;
3950
- color: rgba(255, 255, 255, 0.7);
3951
- ">${texts.message}</p>
3905
+ <!-- 套餐/积分/金额行(order-popups: space-y-4, label muted, value white/right, amount 绿色) -->
3906
+ <div style="display: flex; flex-direction: column; gap: 16px;">
3907
+ <div style="display: flex; justify-content: space-between; align-items: center; font-size: 14px;">
3908
+ <span style="color: #A1A1AA;">${texts.packLabel}</span>
3909
+ <span style="color: #FFFFFF; font-weight: 500; text-align: right;">${this.escapeHtml(data.packName)}</span>
3952
3910
  </div>
3953
-
3954
- <!-- 详情列表 -->
3955
- <div style="
3956
- background: rgba(15, 23, 42, 0.5);
3957
- padding: 16px;
3958
- ">
3959
- <div style="
3960
- display: flex;
3961
- align-items: center;
3962
- justify-content: space-between;
3963
- border-bottom: 1px solid rgba(255, 255, 255, 0.05);
3964
- padding: 12px 0;
3965
- ">
3966
- <span style="
3967
- font-size: 12px;
3968
- font-weight: 500;
3969
- color: rgba(255, 255, 255, 0.6);
3970
- ">${texts.packLabel}</span>
3971
- <span style="
3972
- font-size: 13px;
3973
- font-weight: 600;
3974
- color: rgba(255, 255, 255, 0.95);
3975
- ">${this.escapeHtml(data.packName)}</span>
3976
- </div>
3977
- <div style="
3978
- display: flex;
3979
- align-items: center;
3980
- justify-content: space-between;
3981
- border-bottom: 1px solid rgba(255, 255, 255, 0.05);
3982
- padding: 12px 0;
3983
- ">
3984
- <span style="
3985
- font-size: 12px;
3986
- font-weight: 500;
3987
- color: rgba(255, 255, 255, 0.6);
3988
- ">${texts.creditsLabel}</span>
3989
- <span style="
3990
- font-size: 13px;
3991
- font-weight: 600;
3992
- color: rgba(255, 255, 255, 0.95);
3993
- ">${data.credits.toLocaleString()} Credits</span>
3994
- </div>
3995
- <div style="
3996
- display: flex;
3997
- align-items: center;
3998
- justify-content: space-between;
3999
- background: linear-gradient(to right, rgba(16, 185, 129, 0.05), transparent);
4000
- margin: 0 -16px;
4001
- padding: 12px 16px;
4002
- ">
4003
- <span style="
4004
- font-size: 12px;
4005
- font-weight: 500;
4006
- color: rgba(255, 255, 255, 0.6);
4007
- ">${texts.amountLabel}</span>
4008
- <span style="
4009
- font-size: 16px;
4010
- font-weight: 600;
4011
- color: #10B981;
4012
- ">${currency}${this.escapeHtml(data.amount)}</span>
4013
- </div>
3911
+ <div style="display: flex; justify-content: space-between; align-items: center; font-size: 14px;">
3912
+ <span style="color: #A1A1AA;">${texts.creditsLabel}</span>
3913
+ <span style="color: #FFFFFF; font-weight: 500; text-align: right;">${creditsText}</span>
3914
+ </div>
3915
+ <div style="height: 1px; background: rgba(255, 255, 255, 0.1); margin: 4px 0;"></div>
3916
+ <div style="display: flex; justify-content: space-between; align-items: center; padding-top: 4px;">
3917
+ <span style="font-size: 14px; color: #A1A1AA;">${texts.amountLabel}</span>
3918
+ <span style="font-size: 20px; font-weight: 700; color: #10B981; letter-spacing: 0.02em;">${currency}${this.escapeHtml(data.amount)}</span>
4014
3919
  </div>
4015
3920
  </div>
4016
3921
  </div>
@@ -4089,9 +3994,8 @@ class PurchaseSuccessModal {
4089
3994
  }
4090
3995
 
4091
3996
  #success-modal-close-btn:hover {
4092
- background: rgba(255, 255, 255, 0.15) !important;
4093
- color: white !important;
4094
- transform: rotate(90deg);
3997
+ background: rgba(255, 255, 255, 0.05) !important;
3998
+ color: #FFFFFF !important;
4095
3999
  }
4096
4000
  `;
4097
4001
  document.head.appendChild(style);
@@ -4274,6 +4178,7 @@ class BasePackageModal {
4274
4178
  console.log(`[${this.constructor.name}] Using environment:`, config.environment);
4275
4179
  // 3. Initialize SeaartPaymentSDK
4276
4180
  await SeaartPaymentSDK.getInstance().init({
4181
+ environment: config.environment,
4277
4182
  scriptUrl: finalConfig.scriptUrl,
4278
4183
  clientId: finalConfig.clientId,
4279
4184
  language: this.language,
@@ -5141,8 +5046,9 @@ class PaymentVerificationModal {
5141
5046
  * 创建弹窗元素
5142
5047
  */
5143
5048
  createModal() {
5144
- const isZh = this.options.language === 'zh';
5145
- // 创建遮罩层
5049
+ const lang = this.options.language ?? 'en';
5050
+ const isZh = lang === 'zh' || lang === 'zh-TW';
5051
+ // 遮罩(与 PurchaseSuccessModal 一致)
5146
5052
  this.overlay = document.createElement('div');
5147
5053
  this.overlay.id = 'payment-verification-modal-overlay';
5148
5054
  this.overlay.style.cssText = `
@@ -5153,20 +5059,21 @@ class PaymentVerificationModal {
5153
5059
  align-items: center;
5154
5060
  justify-content: center;
5155
5061
  padding: 20px;
5156
- background: rgba(15, 23, 42, 0.85);
5157
- backdrop-filter: blur(4px);
5158
- animation: fadeIn 0.2s cubic-bezier(0.4, 0, 0.2, 1);
5062
+ background: rgba(0, 0, 0, 0.85);
5063
+ backdrop-filter: blur(8px);
5064
+ animation: fadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5159
5065
  overflow: hidden;
5160
5066
  `;
5161
- // 创建弹窗卡片
5067
+ // 弹窗卡片(PurchaseSuccessModal 风格)
5162
5068
  this.modal = document.createElement('div');
5163
5069
  this.modal.style.cssText = `
5164
5070
  position: relative;
5165
5071
  width: 90vw;
5166
- max-width: 560px;
5167
- border-radius: 16px;
5168
- background: linear-gradient(145deg, #1e2d3d 0%, #162234 100%);
5169
- border: 1px solid rgba(255, 255, 255, 0.08);
5072
+ max-width: 500px;
5073
+ min-width: 420px;
5074
+ border-radius: 24px;
5075
+ background: #121212;
5076
+ border: 1px solid rgba(44, 44, 46, 0.6);
5170
5077
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
5171
5078
  animation: slideInUp 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5172
5079
  overflow: hidden;
@@ -5184,52 +5091,50 @@ class PaymentVerificationModal {
5184
5091
  const texts = this.getTexts(isZh);
5185
5092
  const paymentType = this.options.paymentMethodName || 'Debit/Credit Card';
5186
5093
  return `
5187
- <!-- 关闭按钮 -->
5094
+ <!-- 关闭按钮(与 PurchaseSuccessModal 一致) -->
5188
5095
  <button
5189
5096
  type="button"
5190
5097
  id="verification-modal-close-btn"
5191
5098
  style="
5192
5099
  position: absolute;
5193
- top: 16px;
5194
- right: 16px;
5100
+ top: 20px;
5101
+ right: 20px;
5195
5102
  z-index: 10;
5196
5103
  display: flex;
5197
- width: 32px;
5198
- height: 32px;
5104
+ width: 40px;
5105
+ height: 40px;
5199
5106
  align-items: center;
5200
5107
  justify-content: center;
5201
5108
  border-radius: 50%;
5202
- background: rgba(255, 255, 255, 0.1);
5203
- color: rgba(255, 255, 255, 0.6);
5109
+ background: transparent;
5110
+ color: #A1A1AA;
5204
5111
  border: none;
5205
5112
  cursor: pointer;
5206
- transition: all 0.2s;
5113
+ transition: color 0.2s, background 0.2s;
5207
5114
  "
5208
5115
  >
5209
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
5210
- <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
5116
+ <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
5117
+ <line x1="18" y1="6" x2="6" y2="18"></line>
5118
+ <line x1="6" y1="6" x2="18" y2="18"></line>
5211
5119
  </svg>
5212
5120
  </button>
5213
5121
 
5214
5122
  <!-- 内容区域 -->
5215
- <div style="padding: 40px 32px 28px;">
5216
- <!-- 标题 -->
5217
- <h2 style="
5218
- margin: 0 0 12px;
5123
+ <div style="padding: 24px 24px 24px;">
5124
+ <h1 style="
5125
+ margin: 0 0 8px;
5219
5126
  font-size: 24px;
5220
5127
  font-weight: 700;
5221
- color: #ffffff;
5128
+ color: #FFFFFF;
5222
5129
  text-align: center;
5223
- line-height: 1.3;
5224
- letter-spacing: -0.3px;
5225
- ">${texts.title} ${paymentType}</h2>
5130
+ letter-spacing: -0.02em;
5131
+ ">${texts.title} ${paymentType}</h1>
5226
5132
 
5227
- <!-- 提示文本 -->
5228
5133
  <p style="
5229
5134
  margin: 0 0 20px;
5230
- font-size: 15px;
5135
+ font-size: 14px;
5231
5136
  line-height: 1.6;
5232
- color: rgba(255, 255, 255, 0.7);
5137
+ color: #A1A1AA;
5233
5138
  text-align: center;
5234
5139
  ">${texts.message}</p>
5235
5140
 
@@ -5238,16 +5143,19 @@ class PaymentVerificationModal {
5238
5143
  position: relative;
5239
5144
  margin: 0 0 24px;
5240
5145
  min-height: 56px;
5146
+ padding: 16px;
5147
+ border-radius: 12px;
5148
+ background: rgba(30, 30, 30, 0.5);
5149
+ border: 1px solid rgba(255, 255, 255, 0.05);
5241
5150
  ">
5242
5151
  <p style="
5243
5152
  margin: 0;
5244
5153
  font-size: 13px;
5245
5154
  line-height: 1.7;
5246
- color: rgba(255, 255, 255, 0.5);
5155
+ color: #A1A1AA;
5247
5156
  text-align: center;
5248
5157
  ">${texts.helpText}</p>
5249
5158
 
5250
- <!-- 加载状态遮罩(默认隐藏,Processing 时显示) -->
5251
5159
  <div id="verification-loading-overlay" style="
5252
5160
  display: none;
5253
5161
  position: absolute;
@@ -5255,71 +5163,47 @@ class PaymentVerificationModal {
5255
5163
  align-items: center;
5256
5164
  justify-content: center;
5257
5165
  gap: 12px;
5258
- background: rgba(22, 34, 52, 0.92);
5259
- backdrop-filter: blur(2px);
5260
- border-radius: 8px;
5166
+ background: rgba(18, 18, 18, 0.92);
5167
+ backdrop-filter: blur(4px);
5168
+ border-radius: 12px;
5261
5169
  ">
5262
5170
  <div id="verification-spinner" style="
5263
5171
  width: 24px;
5264
5172
  height: 24px;
5265
- border: 3px solid rgba(13, 148, 136, 0.25);
5266
- border-top-color: #14b8a6;
5173
+ border: 3px solid rgba(16, 185, 129, 0.25);
5174
+ border-top-color: #10B981;
5267
5175
  border-radius: 50%;
5268
5176
  animation: verificationSpin 0.8s linear infinite;
5269
5177
  flex-shrink: 0;
5270
5178
  "></div>
5271
- <span style="
5272
- font-size: 14px;
5273
- color: rgba(255, 255, 255, 0.8);
5274
- white-space: nowrap;
5275
- ">${texts.checkingStatus}</span>
5179
+ <span style="font-size: 14px; color: #A1A1AA; white-space: nowrap;">${texts.checkingStatus}</span>
5276
5180
  </div>
5277
5181
  </div>
5278
5182
 
5279
- <!-- 按钮组 -->
5280
- <div style="
5281
- display: flex;
5282
- gap: 16px;
5283
- justify-content: center;
5284
- ">
5285
- <!-- Cancel 按钮 -->
5286
- <button
5287
- type="button"
5288
- id="verification-cancel-btn"
5289
- style="
5290
- flex: 1;
5291
- max-width: 240px;
5292
- height: 48px;
5293
- border-radius: 10px;
5294
- border: 1px solid rgba(255, 255, 255, 0.15);
5295
- background: transparent;
5296
- color: rgba(255, 255, 255, 0.8);
5297
- font-size: 15px;
5298
- font-weight: 500;
5299
- cursor: pointer;
5300
- transition: all 0.2s;
5301
- "
5302
- >${texts.cancelButton}</button>
5303
-
5304
- <!-- Complete Payment / Processing 按钮 -->
5305
- <button
5306
- type="button"
5307
- id="verification-complete-btn"
5308
- style="
5309
- flex: 1;
5310
- max-width: 240px;
5311
- height: 48px;
5312
- border-radius: 10px;
5313
- border: none;
5314
- background: linear-gradient(135deg, #0d9488 0%, #3b82f6 100%);
5315
- color: white;
5316
- font-size: 15px;
5317
- font-weight: 600;
5318
- cursor: pointer;
5319
- transition: all 0.2s;
5320
- box-shadow: 0 4px 12px rgba(13, 148, 136, 0.3);
5321
- "
5322
- >${texts.completeButton}</button>
5183
+ <!-- 按钮组(与 PurchaseSuccessModal 一致) -->
5184
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px;">
5185
+ <button type="button" id="verification-cancel-btn" style="
5186
+ padding: 14px 20px;
5187
+ border-radius: 12px;
5188
+ border: 1px solid rgba(255,255,255,0.1);
5189
+ background: rgba(255,255,255,0.05);
5190
+ color: #A1A1AA;
5191
+ font-size: 14px;
5192
+ font-weight: 500;
5193
+ cursor: pointer;
5194
+ transition: background 0.2s, color 0.2s, border-color 0.2s;
5195
+ ">${texts.cancelButton}</button>
5196
+ <button type="button" id="verification-complete-btn" style="
5197
+ padding: 14px 20px;
5198
+ border-radius: 12px;
5199
+ border: none;
5200
+ background: #10B981;
5201
+ color: #000000;
5202
+ font-size: 14px;
5203
+ font-weight: 700;
5204
+ cursor: pointer;
5205
+ transition: box-shadow 0.2s, transform 0.1s;
5206
+ ">${texts.completeButton}</button>
5323
5207
  </div>
5324
5208
  </div>
5325
5209
  `;
@@ -5397,24 +5281,23 @@ class PaymentVerificationModal {
5397
5281
  }
5398
5282
 
5399
5283
  #verification-modal-close-btn:hover {
5400
- background: rgba(255, 255, 255, 0.2) !important;
5401
- color: white !important;
5402
- transform: rotate(90deg);
5284
+ background: rgba(255, 255, 255, 0.05) !important;
5285
+ color: #FFFFFF !important;
5403
5286
  }
5404
5287
 
5405
5288
  #verification-cancel-btn:hover {
5406
- background: rgba(255, 255, 255, 0.06) !important;
5407
- border-color: rgba(255, 255, 255, 0.25) !important;
5289
+ background: rgba(255, 255, 255, 0.1) !important;
5290
+ color: #FFFFFF !important;
5291
+ border-color: rgba(255, 255, 255, 0.1) !important;
5408
5292
  }
5409
5293
 
5410
5294
  #verification-complete-btn:hover {
5411
- background: linear-gradient(135deg, #0f766e 0%, #2563eb 100%) !important;
5412
- box-shadow: 0 6px 16px rgba(13, 148, 136, 0.4) !important;
5413
- transform: translateY(-1px);
5295
+ box-shadow: 0 0 20px rgba(16, 185, 129, 0.4) !important;
5296
+ transform: scale(1.02);
5414
5297
  }
5415
5298
 
5416
5299
  #verification-complete-btn:active {
5417
- transform: translateY(0);
5300
+ transform: scale(0.98);
5418
5301
  }
5419
5302
  `;
5420
5303
  document.head.appendChild(style);
@@ -5493,7 +5376,8 @@ class PaymentVerificationModal {
5493
5376
  // 更新按钮文本为 Processing...
5494
5377
  const completeBtn = document.getElementById('verification-complete-btn');
5495
5378
  if (completeBtn) {
5496
- const isZh = this.options.language === 'zh';
5379
+ const lang = this.options.language ?? 'en';
5380
+ const isZh = lang === 'zh' || lang === 'zh-TW';
5497
5381
  completeBtn.textContent = isZh ? '处理中...' : 'Processing...';
5498
5382
  completeBtn.style.pointerEvents = 'none';
5499
5383
  completeBtn.style.opacity = '0.85';
@@ -5511,7 +5395,8 @@ class PaymentVerificationModal {
5511
5395
  // 恢复按钮文本
5512
5396
  const completeBtn = document.getElementById('verification-complete-btn');
5513
5397
  if (completeBtn) {
5514
- const isZh = this.options.language === 'zh';
5398
+ const lang = this.options.language ?? 'en';
5399
+ const isZh = lang === 'zh' || lang === 'zh-TW';
5515
5400
  completeBtn.textContent = isZh ? '我已完成支付' : 'I\'ve Completed Payment';
5516
5401
  completeBtn.style.pointerEvents = '';
5517
5402
  completeBtn.style.opacity = '';
@@ -5635,8 +5520,9 @@ class PaymentFailedModal {
5635
5520
  */
5636
5521
  createModal() {
5637
5522
  const { language } = this.options;
5638
- const isZh = language === 'zh';
5639
- // 创建遮罩层(与验证弹框一致)
5523
+ const lang = language ?? 'en';
5524
+ const isZh = lang === 'zh' || lang === 'zh-TW';
5525
+ // 遮罩(与 PurchaseSuccessModal 一致)
5640
5526
  this.overlay = document.createElement('div');
5641
5527
  this.overlay.id = 'payment-failed-modal-overlay';
5642
5528
  this.overlay.style.cssText = `
@@ -5647,20 +5533,21 @@ class PaymentFailedModal {
5647
5533
  align-items: center;
5648
5534
  justify-content: center;
5649
5535
  padding: 20px;
5650
- background: rgba(15, 23, 42, 0.85);
5651
- backdrop-filter: blur(4px);
5652
- animation: fadeIn 0.2s cubic-bezier(0.4, 0, 0.2, 1);
5536
+ background: rgba(0, 0, 0, 0.85);
5537
+ backdrop-filter: blur(8px);
5538
+ animation: fadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5653
5539
  overflow: hidden;
5654
5540
  `;
5655
- // 创建弹窗卡片(与验证弹框一致)
5541
+ // 弹窗卡片(PurchaseSuccessModal 风格:dark-card #121212, rounded 24px)
5656
5542
  this.modal = document.createElement('div');
5657
5543
  this.modal.style.cssText = `
5658
5544
  position: relative;
5659
5545
  width: 90vw;
5660
- max-width: 560px;
5661
- border-radius: 16px;
5662
- background: linear-gradient(145deg, #1e2d3d 0%, #162234 100%);
5663
- border: 1px solid rgba(255, 255, 255, 0.08);
5546
+ max-width: 500px;
5547
+ min-width: 420px;
5548
+ border-radius: 24px;
5549
+ background: #121212;
5550
+ border: 1px solid rgba(44, 44, 46, 0.6);
5664
5551
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
5665
5552
  animation: slideInUp 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5666
5553
  overflow: hidden;
@@ -5683,58 +5570,62 @@ class PaymentFailedModal {
5683
5570
  const hasDetails = !!this.options.details;
5684
5571
  const hasRetry = !!this.options.onRetry;
5685
5572
  return `
5686
- <!-- 关闭按钮 -->
5573
+ <!-- 关闭按钮(与 PurchaseSuccessModal 一致) -->
5687
5574
  <button
5688
5575
  type="button"
5689
5576
  id="failed-modal-close-btn"
5690
5577
  style="
5691
5578
  position: absolute;
5692
- top: 16px;
5693
- right: 16px;
5579
+ top: 20px;
5580
+ right: 20px;
5694
5581
  z-index: 10;
5695
5582
  display: flex;
5696
- width: 32px;
5697
- height: 32px;
5583
+ width: 40px;
5584
+ height: 40px;
5698
5585
  align-items: center;
5699
5586
  justify-content: center;
5700
5587
  border-radius: 50%;
5701
- background: rgba(255, 255, 255, 0.1);
5702
- color: rgba(255, 255, 255, 0.6);
5588
+ background: transparent;
5589
+ color: #A1A1AA;
5703
5590
  border: none;
5704
5591
  cursor: pointer;
5705
- transition: all 0.2s;
5592
+ transition: color 0.2s, background 0.2s;
5706
5593
  "
5707
5594
  >
5708
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
5709
- <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
5595
+ <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
5596
+ <line x1="18" y1="6" x2="6" y2="18"></line>
5597
+ <line x1="6" y1="6" x2="18" y2="18"></line>
5710
5598
  </svg>
5711
5599
  </button>
5712
5600
 
5713
- <!-- 内容区域 -->
5714
- <div style="padding: 40px 32px 28px;">
5715
- <!-- 标题 -->
5716
- <h2 style="
5717
- margin: 0 0 12px;
5601
+ <!-- 标题与消息 -->
5602
+ <div style="padding: 24px 24px 0;">
5603
+ <h1 style="
5604
+ margin: 0 0 8px;
5718
5605
  font-size: 24px;
5719
5606
  font-weight: 700;
5720
- color: #ffffff;
5607
+ color: #FFFFFF;
5721
5608
  text-align: center;
5722
- line-height: 1.3;
5723
- letter-spacing: -0.3px;
5724
- ">${this.escapeHtml(title)}</h2>
5725
-
5726
- <!-- 消息 -->
5609
+ letter-spacing: -0.02em;
5610
+ ">${this.escapeHtml(title)}</h1>
5727
5611
  <p style="
5728
- margin: 0 0 ${hasDetails ? '24px' : '28px'};
5729
- font-size: 15px;
5612
+ margin: 0 0 24px;
5613
+ font-size: 14px;
5730
5614
  line-height: 1.6;
5731
- color: rgba(255, 255, 255, 0.7);
5615
+ color: #A1A1AA;
5732
5616
  text-align: center;
5733
5617
  ">${this.escapeHtml(this.options.message)}</p>
5618
+ </div>
5734
5619
 
5735
- <!-- 详情展开/折叠 -->
5736
- ${hasDetails ? `
5737
- <div style="margin-bottom: 24px;">
5620
+ <!-- 详情展开/折叠(放入内卡片风格) -->
5621
+ ${hasDetails ? `
5622
+ <div style="margin: 0 24px 24px;">
5623
+ <div style="
5624
+ padding: 20px;
5625
+ border-radius: 12px;
5626
+ background: rgba(30, 30, 30, 0.5);
5627
+ border: 1px solid rgba(255, 255, 255, 0.05);
5628
+ ">
5738
5629
  <button
5739
5630
  type="button"
5740
5631
  id="failed-modal-details-toggle"
@@ -5744,15 +5635,15 @@ class PaymentFailedModal {
5744
5635
  align-items: center;
5745
5636
  justify-content: center;
5746
5637
  gap: 8px;
5747
- padding: 10px;
5638
+ padding: 10px 12px;
5748
5639
  border: 1px solid rgba(255, 255, 255, 0.1);
5749
- border-radius: 10px;
5640
+ border-radius: 8px;
5750
5641
  background: rgba(255, 255, 255, 0.03);
5751
- color: rgba(255, 255, 255, 0.5);
5642
+ color: #A1A1AA;
5752
5643
  font-size: 13px;
5753
5644
  font-weight: 500;
5754
5645
  cursor: pointer;
5755
- transition: all 0.2s;
5646
+ transition: background 0.2s, color 0.2s, border-color 0.2s;
5756
5647
  "
5757
5648
  >
5758
5649
  <span id="failed-modal-details-toggle-text">${detailsToggleText}</span>
@@ -5771,91 +5662,69 @@ class PaymentFailedModal {
5771
5662
  <div style="
5772
5663
  margin-top: 12px;
5773
5664
  padding: 16px;
5774
- border-radius: 10px;
5775
- background: rgba(239, 68, 68, 0.05);
5776
- border: 1px solid rgba(239, 68, 68, 0.1);
5665
+ border-radius: 8px;
5666
+ background: rgba(239, 68, 68, 0.06);
5667
+ border: 1px solid rgba(239, 68, 68, 0.12);
5777
5668
  ">
5778
5669
  <pre style="
5779
5670
  margin: 0;
5780
- font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
5671
+ font-family: ui-monospace, monospace;
5781
5672
  font-size: 12px;
5782
5673
  line-height: 1.6;
5783
- color: rgba(255, 255, 255, 0.5);
5674
+ color: #A1A1AA;
5784
5675
  white-space: pre-wrap;
5785
5676
  word-break: break-word;
5786
5677
  ">${this.escapeHtml(this.options.details || '')}</pre>
5787
5678
  </div>
5788
5679
  </div>
5789
5680
  </div>
5790
- ` : ''}
5791
-
5792
- <!-- 按钮组 -->
5793
- <div style="
5794
- display: flex;
5795
- gap: 16px;
5796
- justify-content: center;
5797
- ">
5798
- ${hasRetry ? `
5799
- <!-- 关闭按钮(有重试时) -->
5800
- <button
5801
- type="button"
5802
- id="failed-modal-close-bottom-btn"
5803
- style="
5804
- flex: 1;
5805
- max-width: 240px;
5806
- height: 48px;
5807
- border-radius: 10px;
5808
- border: 1px solid rgba(255, 255, 255, 0.15);
5809
- background: transparent;
5810
- color: rgba(255, 255, 255, 0.8);
5811
- font-size: 15px;
5812
- font-weight: 500;
5813
- cursor: pointer;
5814
- transition: all 0.2s;
5815
- "
5816
- >${closeText}</button>
5817
-
5818
- <!-- 重试按钮 -->
5819
- <button
5820
- type="button"
5821
- id="failed-modal-retry-btn"
5822
- style="
5823
- flex: 1;
5824
- max-width: 240px;
5825
- height: 48px;
5826
- border-radius: 10px;
5827
- border: none;
5828
- background: linear-gradient(135deg, #0d9488 0%, #3b82f6 100%);
5829
- color: white;
5830
- font-size: 15px;
5831
- font-weight: 600;
5832
- cursor: pointer;
5833
- transition: all 0.2s;
5834
- box-shadow: 0 4px 12px rgba(13, 148, 136, 0.3);
5835
- "
5836
- >${retryText}</button>
5837
- ` : `
5838
- <!-- 关闭按钮(无重试时,居中显示) -->
5839
- <button
5840
- type="button"
5841
- id="failed-modal-close-bottom-btn"
5842
- style="
5843
- flex: 0;
5844
- min-width: 160px;
5845
- max-width: 240px;
5846
- height: 48px;
5847
- border-radius: 10px;
5848
- border: 1px solid rgba(255, 255, 255, 0.15);
5849
- background: transparent;
5850
- color: rgba(255, 255, 255, 0.8);
5851
- font-size: 15px;
5852
- font-weight: 500;
5853
- cursor: pointer;
5854
- transition: all 0.2s;
5855
- "
5856
- >${closeText}</button>
5857
- `}
5858
5681
  </div>
5682
+ ` : '<div style="margin-bottom: 24px;"></div>'}
5683
+
5684
+ <!-- 按钮组(与 PurchaseSuccessModal / RetentionModal 一致) -->
5685
+ <div style="display: grid; grid-template-columns: ${hasRetry ? '1fr 1fr' : '1fr'}; gap: 16px; padding: 0 24px 24px; justify-items: center;">
5686
+ ${hasRetry ? `
5687
+ <button type="button" id="failed-modal-close-bottom-btn" style="
5688
+ width: 100%;
5689
+ max-width: 240px;
5690
+ padding: 14px 20px;
5691
+ border-radius: 12px;
5692
+ border: 1px solid rgba(255,255,255,0.1);
5693
+ background: rgba(255,255,255,0.05);
5694
+ color: #A1A1AA;
5695
+ font-size: 14px;
5696
+ font-weight: 500;
5697
+ cursor: pointer;
5698
+ transition: background 0.2s, color 0.2s, border-color 0.2s;
5699
+ ">${closeText}</button>
5700
+ <button type="button" id="failed-modal-retry-btn" style="
5701
+ width: 100%;
5702
+ max-width: 240px;
5703
+ padding: 14px 20px;
5704
+ border-radius: 12px;
5705
+ border: none;
5706
+ background: #10B981;
5707
+ color: #000000;
5708
+ font-size: 14px;
5709
+ font-weight: 700;
5710
+ cursor: pointer;
5711
+ transition: box-shadow 0.2s, transform 0.1s;
5712
+ ">${retryText}</button>
5713
+ ` : `
5714
+ <button type="button" id="failed-modal-close-bottom-btn" style="
5715
+ min-width: 160px;
5716
+ max-width: 240px;
5717
+ padding: 14px 20px;
5718
+ border-radius: 12px;
5719
+ border: 1px solid rgba(255,255,255,0.1);
5720
+ background: rgba(255,255,255,0.05);
5721
+ color: #A1A1AA;
5722
+ font-size: 14px;
5723
+ font-weight: 500;
5724
+ cursor: pointer;
5725
+ transition: background 0.2s, color 0.2s, border-color 0.2s;
5726
+ ">${closeText}</button>
5727
+ `}
5859
5728
  </div>
5860
5729
  `;
5861
5730
  }
@@ -5902,30 +5771,29 @@ class PaymentFailedModal {
5902
5771
  }
5903
5772
 
5904
5773
  #failed-modal-close-btn:hover {
5905
- background: rgba(255, 255, 255, 0.2) !important;
5906
- color: white !important;
5907
- transform: rotate(90deg);
5774
+ background: rgba(255, 255, 255, 0.05) !important;
5775
+ color: #FFFFFF !important;
5908
5776
  }
5909
5777
 
5910
5778
  #failed-modal-details-toggle:hover {
5911
5779
  background: rgba(255, 255, 255, 0.06) !important;
5912
- border-color: rgba(255, 255, 255, 0.2) !important;
5913
- color: rgba(255, 255, 255, 0.7) !important;
5780
+ border-color: rgba(255, 255, 255, 0.15) !important;
5781
+ color: #FFFFFF !important;
5914
5782
  }
5915
5783
 
5916
5784
  #failed-modal-close-bottom-btn:hover {
5917
- background: rgba(255, 255, 255, 0.06) !important;
5918
- border-color: rgba(255, 255, 255, 0.25) !important;
5785
+ background: rgba(255, 255, 255, 0.1) !important;
5786
+ color: #FFFFFF !important;
5787
+ border-color: rgba(255, 255, 255, 0.1) !important;
5919
5788
  }
5920
5789
 
5921
5790
  #failed-modal-retry-btn:hover {
5922
- background: linear-gradient(135deg, #0f766e 0%, #2563eb 100%) !important;
5923
- box-shadow: 0 6px 16px rgba(13, 148, 136, 0.4) !important;
5924
- transform: translateY(-1px);
5791
+ box-shadow: 0 0 20px rgba(16, 185, 129, 0.4) !important;
5792
+ transform: scale(1.02);
5925
5793
  }
5926
5794
 
5927
5795
  #failed-modal-retry-btn:active {
5928
- transform: translateY(0);
5796
+ transform: scale(0.98);
5929
5797
  }
5930
5798
  `;
5931
5799
  document.head.appendChild(style);
@@ -5978,7 +5846,8 @@ class PaymentFailedModal {
5978
5846
  * 切换详情展开/折叠
5979
5847
  */
5980
5848
  toggleDetails() {
5981
- const isZh = this.options.language === 'zh';
5849
+ const lang = this.options.language ?? 'en';
5850
+ const isZh = lang === 'zh' || lang === 'zh-TW';
5982
5851
  const detailsToggleText = isZh ? '查看详情' : 'View Details';
5983
5852
  const detailsHideText = isZh ? '隐藏详情' : 'Hide Details';
5984
5853
  this.detailsExpanded = !this.detailsExpanded;
@@ -8509,16 +8378,6 @@ class CreditPackageModal extends BasePackageModal {
8509
8378
  this.isFetchingPackages = false;
8510
8379
  }
8511
8380
  }
8512
- /**
8513
- * Parse purchase limit string to day_limit number
8514
- * Example: "Daily limit: 1" => 1
8515
- */
8516
- parsePurchaseLimit(limit) {
8517
- if (!limit)
8518
- return 0;
8519
- const match = limit.match(/\d+/);
8520
- return match ? parseInt(match[0]) : 0;
8521
- }
8522
8381
  /**
8523
8382
  * 覆盖 BasePackageModal 的 handlePaymentFlow 方法
8524
8383
  * 使用 PaymentCheckoutModal 替代旧的 DropinPaymentModal
@@ -8653,6 +8512,7 @@ class CreditPackageModal extends BasePackageModal {
8653
8512
  if (modalElement) {
8654
8513
  modalElement.style.background = '#0a0a0f';
8655
8514
  modalElement.style.border = '1px solid rgba(255, 255, 255, 0.1)';
8515
+ modalElement.style.borderRadius = '24px';
8656
8516
  }
8657
8517
  // Modify title style
8658
8518
  const titleElement = document.querySelector('.payment-modal-title');
@@ -8663,6 +8523,31 @@ class CreditPackageModal extends BasePackageModal {
8663
8523
  titleElement.style.padding = '32px 32px 0 32px';
8664
8524
  titleElement.style.marginBottom = '16px';
8665
8525
  titleElement.style.letterSpacing = '-0.01em';
8526
+ titleElement.style.display = 'none'; // Hide default title, we use custom header in renderContent
8527
+ }
8528
+ // Add responsive styles for cards
8529
+ if (!document.getElementById('credit-package-responsive-styles')) {
8530
+ const style = document.createElement('style');
8531
+ style.id = 'credit-package-responsive-styles';
8532
+ style.textContent = `
8533
+ @media (max-width: 768px) {
8534
+ .credit-pack-card-container {
8535
+ width: 100% !important;
8536
+ max-width: 320px;
8537
+ margin: 0 auto;
8538
+ }
8539
+ .credit-pack-card {
8540
+ width: 100% !important;
8541
+ height: 260px !important;
8542
+ }
8543
+ .payment-modal {
8544
+ width: 95vw !important;
8545
+ max-height: 90vh !important;
8546
+ overflow-y: auto !important;
8547
+ }
8548
+ }
8549
+ `;
8550
+ document.head.appendChild(style);
8666
8551
  }
8667
8552
  // Modify close button color and add hover animation
8668
8553
  const closeButton = document.querySelector('.payment-modal-close');
@@ -8695,7 +8580,8 @@ class CreditPackageModal extends BasePackageModal {
8695
8580
  if (!container) {
8696
8581
  throw new Error('Modal content container not found');
8697
8582
  }
8698
- const isZh = this.language === 'zh';
8583
+ const lang = this.language ?? 'en';
8584
+ const isZh = lang === 'zh' || lang === 'zh-TW';
8699
8585
  const styles = this.getResponsiveStyles();
8700
8586
  container.innerHTML = `
8701
8587
  <div style="
@@ -8705,10 +8591,10 @@ class CreditPackageModal extends BasePackageModal {
8705
8591
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
8706
8592
  ">
8707
8593
  <!-- Credit Packs - credit package purchase title -->
8708
- <div style="margin: 0 auto ${this.SPACING.lg}; max-width: 80rem; text-align: center;">
8594
+ <div style="margin: 0 auto ${styles.headerMargin}; max-width: 80rem; text-align: center;">
8709
8595
  <h3 style="
8710
8596
  margin-bottom: ${this.SPACING.xs};
8711
- font-size: 24px;
8597
+ font-size: ${styles.titleFontSize};
8712
8598
  font-weight: 700;
8713
8599
  color: ${this.COLORS.text.primary};
8714
8600
  letter-spacing: -0.02em;
@@ -8716,11 +8602,11 @@ class CreditPackageModal extends BasePackageModal {
8716
8602
  ${isZh ? '需要更多积分?' : 'Need More Credits?'}
8717
8603
  </h3>
8718
8604
  <p style="
8719
- font-size: 16px;
8605
+ font-size: ${styles.subtitleFontSize};
8720
8606
  color: ${this.COLORS.text.secondary};
8721
8607
  line-height: 1.6;
8722
8608
  ">
8723
- ${isZh ? '随时购买永久积分包' : 'Purchase unlimited credit packages anytime'}
8609
+ ${isZh ? '随时购买永久积分包' : 'Get credits (Valid for all platform products)'}
8724
8610
  </p>
8725
8611
  </div>
8726
8612
 
@@ -8728,7 +8614,8 @@ class CreditPackageModal extends BasePackageModal {
8728
8614
  <div style="
8729
8615
  display: grid;
8730
8616
  grid-template-columns: ${styles.packGridColumns};
8731
- gap: 16px;
8617
+ gap: ${styles.gridGap};
8618
+ justify-items: center;
8732
8619
  ">
8733
8620
  ${this.getPackages().map((pkg, index) => this.renderPackageCard(pkg, index)).join('')}
8734
8621
  </div>
@@ -8743,30 +8630,55 @@ class CreditPackageModal extends BasePackageModal {
8743
8630
  */
8744
8631
  getResponsiveStyles() {
8745
8632
  const isMobile = window.matchMedia('(max-width: 768px)').matches;
8746
- const isTablet = window.matchMedia('(max-width: 1200px)').matches;
8633
+ const isTablet = window.matchMedia('(max-width: 1024px)').matches;
8747
8634
  const isLaptop = window.matchMedia('(max-width: 1400px)').matches;
8748
8635
  let computeColumns = 5;
8749
8636
  let packColumns = 4;
8750
8637
  let padding = '0 60px 60px';
8638
+ let titleSize = '32px';
8639
+ let subtitleSize = '16px';
8640
+ let headerMargin = this.SPACING.lg;
8641
+ let gridGap = '24px';
8751
8642
  if (isMobile) {
8752
8643
  computeColumns = 1;
8753
8644
  packColumns = 1;
8754
- padding = '0 20px 20px';
8645
+ padding = '0 16px 32px';
8646
+ titleSize = '24px';
8647
+ subtitleSize = '14px';
8648
+ headerMargin = this.SPACING.md;
8649
+ gridGap = '16px';
8755
8650
  }
8756
8651
  else if (isTablet) {
8757
8652
  computeColumns = 2;
8758
8653
  packColumns = 2;
8759
- padding = '0 30px 30px';
8654
+ padding = '0 32px 48px';
8655
+ titleSize = '28px';
8656
+ subtitleSize = '15px';
8657
+ headerMargin = this.SPACING.md;
8658
+ gridGap = '20px';
8760
8659
  }
8761
8660
  else if (isLaptop) {
8762
8661
  computeColumns = 3;
8763
- packColumns = 2;
8764
- padding = '0 40px 40px';
8662
+ packColumns = 3;
8663
+ padding = '0 48px 60px';
8664
+ titleSize = '32px';
8665
+ subtitleSize = '16px';
8666
+ headerMargin = this.SPACING.lg;
8667
+ gridGap = '24px';
8668
+ }
8669
+ // Adjust columns based on package count if small
8670
+ const packageCount = this.getPackages().length;
8671
+ if (!isMobile && packageCount < packColumns) {
8672
+ packColumns = packageCount;
8765
8673
  }
8766
8674
  return {
8767
8675
  containerPadding: padding,
8768
8676
  computeGridColumns: `repeat(${computeColumns}, 1fr)`,
8769
8677
  packGridColumns: `repeat(${packColumns}, 1fr)`,
8678
+ titleFontSize: titleSize,
8679
+ subtitleFontSize: subtitleSize,
8680
+ headerMargin: headerMargin,
8681
+ gridGap: gridGap,
8770
8682
  };
8771
8683
  }
8772
8684
  /**
@@ -8922,8 +8834,8 @@ class GenericPackageModal extends BasePackageModal {
8922
8834
  if (!container) {
8923
8835
  throw new Error('Modal content container not found');
8924
8836
  }
8925
- // Directly render card content without any outer wrapper
8926
- container.innerHTML = this.options.packages.map((pkg, index) => this.renderPackageCard(pkg, index)).join('');
8837
+ const cardsHtml = this.options.packages.map((pkg, index) => this.renderPackageCard(pkg, index)).join('');
8838
+ container.innerHTML = `<div style="display:flex;flex-wrap:wrap;justify-content:center;gap:24px;padding:0;">${cardsHtml}</div>`;
8927
8839
  // Attach event listeners
8928
8840
  this.attachEventListeners(container);
8929
8841
  }
@@ -9018,199 +8930,229 @@ class GenericPackageModal extends BasePackageModal {
9018
8930
  };
9019
8931
  }
9020
8932
  /**
9021
- * Render package card
8933
+ * Render package card (Credits.html / 参考图一比一风格)
9022
8934
  */
9023
8935
  renderPackageCard(pkg, index) {
9024
8936
  const hasBonus = pkg.bonus_credits && parseInt(pkg.bonus_credits) > 0;
9025
- const hasBonusPercentage = pkg.bonus_percentage && pkg.bonus_percentage > 0;
9026
- // Determine title based on package type
9027
- let packageTitle = '';
9028
- if (pkg.package_type === 'iceBreaker' || pkg.package_type === 'firstCharge') {
9029
- packageTitle = 'One-time Only';
9030
- }
8937
+ const hasBonusPercentage = pkg.bonus_percentage != null && pkg.bonus_percentage > 0;
8938
+ const baseNum = this.formatNumber(pkg.base_credits || pkg.credits);
8939
+ const bonusNum = hasBonus ? this.formatNumber(pkg.bonus_credits) : '';
8940
+ const originalPrice = pkg.original_price;
8941
+ const svgClose = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
8942
+ const svgZap = '<svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon></svg>';
8943
+ const svgCheck = '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>';
8944
+ const svgSparkles = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z"></path></svg>';
9031
8945
  return `
9032
8946
  <div
9033
8947
  data-package-id="${pkg.id}"
8948
+ class="generic-package-card"
9034
8949
  style="
9035
8950
  position: relative;
9036
8951
  display: flex;
9037
8952
  flex-direction: column;
9038
- justify-content: center;
9039
8953
  align-items: center;
9040
- gap: 48px;
9041
- border-radius: 16px;
9042
- border: 1px solid rgba(255, 255, 255, 0.1);
9043
- background: #000000;
9044
- padding: 80px 60px;
9045
8954
  text-align: center;
9046
- cursor: pointer;
9047
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
9048
8955
  width: 100%;
9049
- height: 100%;
8956
+ max-width: 384px;
8957
+ min-width: 340px;
8958
+ margin: 0 auto;
9050
8959
  box-sizing: border-box;
8960
+ border-radius: 24px;
8961
+ border: 1px solid rgba(255, 255, 255, 0.1);
8962
+ background: #171717;
8963
+ padding: 40px 32px 32px;
8964
+ overflow: hidden;
9051
8965
  "
9052
- onmouseover="this.style.borderColor='rgba(255, 255, 255, 0.2)';"
9053
- onmouseout="this.style.borderColor='rgba(255, 255, 255, 0.1)';"
9054
8966
  >
9055
- <!-- Package title - top center of card -->
9056
- ${packageTitle ? `
9057
- <div style="
9058
- position: absolute;
9059
- top: 32px;
9060
- left: 50%;
9061
- transform: translateX(-50%);
9062
- font-size: 44px;
9063
- line-height: 1;
9064
- font-weight: 400;
9065
- color: white;
9066
- letter-spacing: -0.02em;
9067
- white-space: nowrap;
9068
- ">
9069
- ${packageTitle}
9070
- </div>
9071
- ` : ''}
8967
+ <!-- Background Ambient Glow (参考图中部绿色光晕) -->
8968
+ <div style="
8969
+ position: absolute;
8970
+ bottom: 25%;
8971
+ right: 25%;
8972
+ width: 240px;
8973
+ height: 240px;
8974
+ background: rgba(6, 182, 212, 0.1);
8975
+ border-radius: 50%;
8976
+ filter: blur(100px);
8977
+ pointer-events: none;
8978
+ z-index: 0;
8979
+ "></div>
9072
8980
 
9073
- <!-- Close button - top right -->
8981
+ <!-- Close button (右上角圆形按钮) -->
9074
8982
  <button
8983
+ type="button"
9075
8984
  onclick="this.closest('[data-package-id]').dispatchEvent(new CustomEvent('close-modal', { bubbles: true }));"
9076
8985
  style="
9077
8986
  position: absolute;
9078
- top: 24px;
9079
- right: 24px;
9080
- width: 32px;
9081
- height: 32px;
8987
+ top: 16px;
8988
+ right: 16px;
8989
+ width: 34px;
8990
+ height: 34px;
9082
8991
  border-radius: 50%;
9083
8992
  border: none;
9084
- background: rgba(255, 255, 255, 0.1);
9085
- color: rgba(255, 255, 255, 0.7);
8993
+ background: rgba(255, 255, 255, 0.05);
8994
+ color: rgba(255, 255, 255, 0.4);
9086
8995
  cursor: pointer;
9087
8996
  display: flex;
9088
8997
  align-items: center;
9089
8998
  justify-content: center;
9090
- font-size: 20px;
9091
- line-height: 1;
9092
8999
  transition: all 0.2s;
9093
- z-index: 100;
9000
+ z-index: 10;
9094
9001
  "
9095
- onmouseover="this.style.background='rgba(255, 255, 255, 0.2)'; this.style.color='white';"
9096
- onmouseout="this.style.background='rgba(255, 255, 255, 0.1)'; this.style.color='rgba(255, 255, 255, 0.7)';"
9097
- >
9098
- ×
9099
- </button>
9002
+ onmouseover="this.style.background='rgba(255,255,255,0.1)'; this.style.color='#FFFFFF';"
9003
+ onmouseout="this.style.background='rgba(255,255,255,0.05)'; this.style.color='rgba(255,255,255,0.4)';"
9004
+ >${svgClose}</button>
9100
9005
 
9101
- <!-- Discount tag - below close button -->
9102
- ${hasBonusPercentage ? `
9103
- <div style="
9104
- position: absolute;
9105
- top: 92px;
9106
- right: 30px;
9107
- background: linear-gradient(135deg, #fa8c42 0%, #ff5a00 100%);
9108
- color: white;
9109
- padding: 8px 16px;
9110
- border-radius: 8px;
9111
- font-size: 20px;
9112
- font-weight: 800;
9113
- box-shadow: 0 4px 16px rgba(255, 90, 0, 0.5);
9114
- white-space: nowrap;
9115
- z-index: 10;
9116
- ">
9117
- +${pkg.bonus_percentage}%
9006
+ <div style="position: relative; z-index: 1; width: 100%; display: flex; flex-direction: column; align-items: center;">
9007
+ <!-- Value badge: +N% EXTRA VALUE (深色底, 金色边框) -->
9008
+ ${hasBonusPercentage ? `
9009
+ <div style="
9010
+ display: inline-flex;
9011
+ align-items: center;
9012
+ gap: 6px;
9013
+ margin-bottom: 24px;
9014
+ padding: 4px 12px;
9015
+ border-radius: 9999px;
9016
+ background: rgba(249, 176, 22, 0.1);
9017
+ border: 1px solid rgba(249, 176, 22, 0.2);
9018
+ color: #F9B016;
9019
+ font-size: 12px;
9020
+ font-weight: 700;
9021
+ box-shadow: 0 0 15px rgba(249, 176, 22, 0.1);
9022
+ ">
9023
+ <span style="display:inline-flex;">${svgZap}</span>
9024
+ <span>+${pkg.bonus_percentage}% EXTRA VALUE</span>
9025
+ </div>
9026
+ ` : '<div style="height:16px;"></div>'}
9027
+
9028
+ <!-- Main credits: 巨大白字 + CREDITS -->
9029
+ <div style="margin-bottom: 0;">
9030
+ <span style="
9031
+ display: block;
9032
+ font-size: 60px;
9033
+ line-height: 1;
9034
+ font-weight: 800;
9035
+ color: #FFFFFF;
9036
+ letter-spacing: -0.05em;
9037
+ filter: drop-shadow(0 20px 30px rgba(0,0,0,0.5));
9038
+ ">${baseNum}</span>
9039
+ <span style="
9040
+ display: block;
9041
+ margin-top: 4px;
9042
+ font-size: 14px;
9043
+ font-weight: 500;
9044
+ color: #A3A3A3;
9045
+ letter-spacing: 0.1em;
9046
+ text-transform: uppercase;
9047
+ ">CREDITS</span>
9118
9048
  </div>
9119
- ` : ''}
9120
9049
 
9121
- <!-- Credits display area - ensure no line break -->
9122
- <div style="
9123
- display: flex;
9124
- flex-direction: column;
9125
- align-items: center;
9126
- justify-content: center;
9127
- gap: 0;
9128
- width: 100%;
9129
- margin-top: 60px;
9130
- ">
9050
+ <!-- Separator: 渐变线 + 加号 (缩短线条长度) -->
9131
9051
  <div style="
9132
9052
  display: flex;
9133
- align-items: baseline;
9053
+ align-items: center;
9134
9054
  justify-content: center;
9135
9055
  gap: 12px;
9136
- flex-wrap: nowrap;
9056
+ width: 100%;
9057
+ margin: 12px 0;
9058
+ opacity: 0.4;
9137
9059
  ">
9138
- <!-- Base credits -->
9139
- <span style="
9140
- font-size: 80px;
9141
- line-height: 1;
9142
- font-weight: 400;
9143
- color: white;
9144
- letter-spacing: -0.04em;
9145
- white-space: nowrap;
9146
- ">
9147
- ${this.formatNumber(pkg.base_credits || pkg.credits)}
9148
- </span>
9149
-
9150
- <!-- credits text -->
9151
- <span style="
9152
- font-size: 52px;
9153
- line-height: 1;
9154
- font-weight: 400;
9155
- color: white;
9156
- letter-spacing: -0.04em;
9157
- white-space: nowrap;
9158
- ">
9159
- credits
9160
- </span>
9060
+ <span style="width: 40px; height: 1px; background: linear-gradient(to right, transparent, #FFFFFF);"></span>
9061
+ <span style="color: #FFFFFF; font-size: 18px; font-weight: 300; line-height: 1;">+</span>
9062
+ <span style="width: 40px; height: 1px; background: linear-gradient(to left, transparent, #FFFFFF);"></span>
9063
+ </div>
9161
9064
 
9162
- <!-- Bonus credits -->
9163
- ${hasBonus ? `
9065
+ <!-- Bonus credits: 绿色数字 + BONUS CREDITS -->
9066
+ ${hasBonus ? `
9067
+ <div style="margin-bottom: 32px; position: relative;">
9068
+ <div style="position: absolute; inset: -16px; background: rgba(34, 197, 94, 0.1); filter: blur(20px); border-radius: 50%;"></div>
9164
9069
  <span style="
9165
- font-size: 52px;
9070
+ display: block;
9071
+ position: relative;
9072
+ font-size: 36px;
9166
9073
  line-height: 1;
9167
- font-weight: 400;
9168
- color: #00ff88;
9169
- letter-spacing: -0.04em;
9170
- white-space: nowrap;
9171
- ">
9172
- +${this.formatNumber(pkg.bonus_credits)} bonus
9173
- </span>
9174
- ` : ''}
9074
+ font-weight: 700;
9075
+ color: transparent;
9076
+ background: linear-gradient(to bottom, #86EFAC, #22C55E);
9077
+ -webkit-background-clip: text;
9078
+ background-clip: text;
9079
+ ">${bonusNum}</span>
9080
+ <div style="display:inline-flex;position: relative;align-items:center;gap:6px;margin-top:4px;">
9081
+ <span style="display:inline-flex;color:#4ADE80;">${svgSparkles}</span>
9082
+ <span style="font-size:14px;font-weight:600;color:#4ADE80;letter-spacing:0.05em;text-transform:uppercase;">Bonus Credits</span>
9083
+ </div>
9084
+ </div>
9085
+ ` : '<div style="height:32px;"></div>'}
9086
+
9087
+ <!-- Validity badge (深色小胶囊) -->
9088
+ <div style="
9089
+ display: inline-flex;
9090
+ align-items: center;
9091
+ gap: 6px;
9092
+ margin-bottom: 32px;
9093
+ padding: 6px 12px;
9094
+ border-radius: 8px;
9095
+ background: rgba(255, 255, 255, 0.05);
9096
+ color: #737373;
9097
+ font-size: 12px;
9098
+ ">
9099
+ <span style="display:inline-flex;">${svgCheck}</span>
9100
+ <span>Valid for all platform products</span>
9175
9101
  </div>
9176
- </div>
9177
9102
 
9178
- <!-- Subtitle - Valid for all platform products -->
9179
- <div style="
9180
- font-size: 22px;
9181
- line-height: 1.4;
9182
- font-weight: 300;
9183
- color: rgba(255, 255, 255, 0.75);
9184
- letter-spacing: -0.015em;
9185
- ">
9186
- Valid for all platform products
9187
- </div>
9103
+ <!-- CTA Button (渐变大按钮, 右侧带价格深色块) -->
9104
+ <button
9105
+ data-package-button="${pkg.id}"
9106
+ type="button"
9107
+ style="
9108
+ width: 100%;
9109
+ border: none;
9110
+ border-radius: 16px;
9111
+ padding: 4px 4px 4px 24px;
9112
+ background: linear-gradient(to right, #34D399, #06B6D4);
9113
+ color: #171717;
9114
+ font-size: 18px;
9115
+ font-weight: 700;
9116
+ cursor: pointer;
9117
+ display: flex;
9118
+ align-items: center;
9119
+ justify-content: space-between;
9120
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
9121
+ box-sizing: border-box;
9122
+ position: relative;
9123
+ overflow: hidden;
9124
+ "
9125
+ onmouseover="this.style.transform='scale(1.02)';"
9126
+ onmouseout="this.style.transform='scale(1)';"
9127
+ onmousedown="this.style.transform='scale(0.98)';"
9128
+ >
9129
+ <!-- Hover Shine Effect -->
9130
+ <div style="
9131
+ position: absolute;
9132
+ top: 0;
9133
+ left: -100%;
9134
+ height: 100%;
9135
+ width: 100%;
9136
+ background: linear-gradient(to right, transparent, rgba(255,255,255,0.3), transparent);
9137
+ transform: skewX(-20deg);
9138
+ transition: left 0.5s;
9139
+ " onmouseover="this.style.left='100%'" onmouseout="this.style.left='-100%'"></div>
9188
9140
 
9189
- <!-- Buy button -->
9190
- <button
9191
- data-package-button="${pkg.id}"
9192
- style="
9193
- margin-top: 0;
9194
- width: auto;
9195
- min-width: 280px;
9196
- max-width: 400px;
9197
- border-radius: 50px;
9198
- border: none;
9199
- background: linear-gradient(135deg, #00ff88 0%, #00f2fe 100%);
9200
- padding: 16px 48px;
9201
- font-size: 20px;
9202
- font-weight: 600;
9203
- color: #000000;
9204
- cursor: pointer;
9205
- transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
9206
- box-shadow: 0 4px 20px rgba(0, 255, 136, 0.35);
9207
- letter-spacing: 0.01em;
9208
- "
9209
- onmouseover="this.style.background='linear-gradient(135deg, #00ff88 0%, #00f2fe 100%)'; this.style.boxShadow='0 6px 28px rgba(0, 255, 136, 0.5)'; this.style.transform='translateY(-2px) scale(1.02)';"
9210
- onmouseout="this.style.background='linear-gradient(135deg, #00ff88 0%, #00f2fe 100%)'; this.style.boxShadow='0 4px 20px rgba(0, 255, 136, 0.35)'; this.style.transform='translateY(0) scale(1)';"
9211
- >
9212
- Buy $ ${pkg.price}
9213
- </button>
9141
+ <span>Unlock Now</span>
9142
+ <div style="
9143
+ display: flex;
9144
+ align-items: center;
9145
+ gap: 8px;
9146
+ background: rgba(0, 0, 0, 0.2);
9147
+ padding: 10px 10px;
9148
+ border-radius: 8px;
9149
+ backdrop-filter: blur(4px);
9150
+ ">
9151
+ ${originalPrice ? `<span style="font-size:14px;font-weight:700;color:rgba(255, 255, 255, 0.6);text-decoration:line-through;">$${originalPrice}</span>` : ''}
9152
+ <span style="font-size:16px;font-weight:600;color:#FFFFFF;">$${pkg.price}</span>
9153
+ </div>
9154
+ </button>
9155
+ </div>
9214
9156
  </div>
9215
9157
  `;
9216
9158
  }