/* 平台设计 token + 通用组件（按钮/表单/弹窗/登录/钱包），所有产品共用 */
    /* ============================================================
       Section 1: Design Tokens（来自 design-system/design-tokens.css）
       ============================================================ */
    :root {
      /* A1 · Identity：品牌主色（紫罗兰 Violet 阶） */
      --teal-50:  #EEF2FF;
      --teal-100: #DFE6FF;
      --teal-200: #C5D1FF;
      --teal-300: #A3B5FF;
      --teal-400: #7188FF;
      --teal-500: #4262FF;
      --teal-600: #3550D9;
      --teal-700: #2A41B6;
      --teal-800: #233491;
      --teal-900: #1B286B;

      /* A1 · Identity：点缀玫粉（AI 模式 / 主 CTA 专用） */
      --amber-100: #FFF4C4;
      --amber-300: #FFE066;
      --amber-500: #FFD02F;
      --amber-600: #F0BB00;
      --amber-700: #C99700;
      --amber-800: #A67C00;
      --amber-900: #746019;

      /* A1 · Identity：中性色阶（带紫倾向的冷灰） */
      --ink-900: #1C1C1E;
      --ink-700: #43485E;
      --ink-500: #5F6478;
      --ink-400: #8E91A0;
      --ink-200: #E5E7EC;
      --ink-100: #F2F3F6;
      --ink-50:  #F7F8FA;

      /* A1 · Identity：背景 / 表面 / 前景 */
      --bg:          #FFFFFF;
      --surface:     #FFFFFF;
      --fg:          var(--ink-900);
      --fg-2:        var(--ink-700);
      --muted:       var(--ink-500);
      --meta:        var(--ink-400);
      --border:      var(--ink-200);
      --border-soft: var(--ink-100);

      /* A1 · 辅助色（渐变映射专用） */
      --cyan-700: #4F46E5;
      --sky-500:  #3B82F6;

      /* A2 · Semantic：语义色 */
      --success:        #16A34A;
      --success-bg:     #F0FDF4;
      --success-border: #BBF7D0;
      --warning:        #D97706;
      --warning-bg:     #FFFBEB;
      --warning-border: #FDE68A;
      --danger:         #DC2626;
      --danger-hover:   #B91C1C;
      --danger-bg:      #FEF2F2;
      --danger-border:  #FECACA;

      /* A1 · Identity：字体族 */
      --font-display: "Inter", "Noto Sans SC", -apple-system, "PingFang SC", sans-serif;
      --font-body:    "Inter", "Noto Sans SC", -apple-system, "PingFang SC", sans-serif;
      --font-mono:    "JetBrains Mono", "SFMono-Regular", Consolas, monospace;

      /* A1 · Structure：字号阶梯（7 级） */
      --text-xs:   12px;
      --text-sm:   13px;
      --text-base: 14px;
      --text-md:   16px;
      --text-lg:   18px;
      --text-xl:   22px;
      --text-2xl:  28px;

      /* A2 · Structure：字重三级 */
      --weight-body:     400;
      --weight-emphasis: 510;
      --weight-announce: 590;

      /* A2 · Structure：间距（4px 网格） */
      --space-1:  4px;
      --space-2:  8px;
      --space-3:  12px;
      --space-4:  16px;
      --space-5:  20px;
      --space-6:  24px;
      --space-8:  32px;
      --space-10: 40px;
      --space-12: 48px;
      --space-16: 64px;

      /* A2 · Structure：圆角阶梯 */
      --radius-sm:   6px;
      --radius-md:   10px;
      --radius-lg:   16px;
      --radius-xl:   20px;
      --radius-full: 9999px;

      /* A2 · Structure：阴影两档（紫调） */
      --shadow-sm: 0 1px 2px rgba(5, 0, 56, 0.05), 0 1px 3px rgba(5, 0, 56, 0.04);
      --shadow-lg: 0 8px 24px rgba(5, 0, 56, 0.10), 0 2px 8px rgba(5, 0, 56, 0.05);

      /* A2 · Motion：动效（禁弹性缓动） */
      --motion-fast: 120ms;
      --motion-base: 180ms;
      --motion-slow: 300ms;
      --ease-standard: cubic-bezier(0.2, 0, 0, 1);
      --ease-exit:     cubic-bezier(0, 0, 0.2, 1);

      /* A2 · Focus */
      --focus-ring: 0 0 0 3px rgba(66, 98, 255, 0.30);

      /* A1 · Identity：品牌渐变（紫 → 粉） */
      --grad-brand: linear-gradient(135deg, #1C1C1E 0%, #2C2C34 100%);

      /* B · Slot：按钮 */
      --btn-primary-bg:      var(--grad-brand);
      --btn-primary-text:    #FFFFFF;
      --btn-primary-hover:   var(--grad-brand);
      --btn-primary-active:  var(--grad-brand);
      --btn-secondary-bg:    var(--teal-50);
      --btn-secondary-border: var(--teal-200);
      --btn-secondary-text:  var(--teal-700);
      --btn-secondary-hover: var(--teal-100);
      --btn-ghost-bg:        transparent;
      --btn-ghost-text:      var(--fg-2);
      --btn-ghost-hover:     var(--ink-50);
      --btn-ghost-active:    var(--ink-100);
      --btn-danger-bg:       var(--danger);
      --btn-danger-hover:    var(--danger-hover);

      /* B · Slot：顶栏 pill（「我的」入口与「积分」钱包共用一套视觉） */
      --pill-bg:     #FFE9A9;
      --pill-hover:  #FFDF7E;
      --pill-active: #FFD65E;
      --pill-text:   #1F1D1A;

      /* B · Slot：输入框 */
      --input-bg:           #FFFFFF;
      --input-border:       var(--border);
      --input-focus-border: var(--teal-600);
      --input-error-border: var(--danger);
      --input-disabled-bg:  var(--ink-50);
      --input-disabled-text: var(--ink-400);

      /* B · Slot：风格卡 / 上传 / 历史 */
      --card-selected-ring: 0 0 0 2px #FFFFFF, 0 0 0 4px var(--teal-500);
      --card-hover-shadow:  0 6px 16px rgba(5, 0, 56, 0.10);
      --art-icon-shadow:    0 1px 2px rgba(0, 0, 0, 0.18);

      /* C · Extension：模式徽标 */
      --badge-local-text:   var(--teal-700);
      --badge-local-bg:     var(--teal-50);
      --badge-local-border: var(--teal-200);
      --badge-ai-text:      #1C1C1E;
      --badge-ai-bg:        var(--amber-500);
      --badge-ai-bg-hover:  var(--amber-600);

      /* C · Extension：遮罩与微光 */
      --mask:         rgba(28, 28, 30, 0.4);
      --mask-strong:  rgba(28, 28, 30, 0.72);
      --overlay:      rgba(28, 28, 30, 0.45);
      --shimmer:      rgba(255, 255, 255, 0.65);

      /* C · Extension：12 风格渐变（对齐参考稿的多彩色卡） */
      --grad-cartoon:    linear-gradient(135deg, #EA580C, #FB923C);
      --grad-anime:      linear-gradient(135deg, #EC4899, #C4B5FD);
      --grad-toon3d:     linear-gradient(135deg, #1E293B, #64748B);
      --grad-pixel:      linear-gradient(135deg, #16A34A, #86EFAC);
      --grad-watercolor: linear-gradient(135deg, #38BDF8, #BAE6FD);
      --grad-sketch:     linear-gradient(135deg, #475569, #94A3B8);
      --grad-oil:        linear-gradient(135deg, #B45309, #F59E0B);
      --grad-cyberpunk:  linear-gradient(135deg, #6D28D9, #3B82F6);
      --grad-retro:      linear-gradient(135deg, #C2410C, #FB923C);
      --grad-flat:       linear-gradient(135deg, #94A3B8, #E2E8F0);
      --grad-illus:      linear-gradient(135deg, #EC4899, #F9A8D4);
      --grad-nebula:     linear-gradient(135deg, #8B5CF6, #C4B5FD);

      /* Layout */
      --container-max: 1120px;
      --container-gutter: 24px;
    }

    /* ============================================================
       Section 2: Reset 与基础
       ============================================================ */
    * { box-sizing: border-box; margin: 0; padding: 0; }
    /* 关键：让 hidden 属性优先于 display:flex 等任何自定义样式（上版本事故坑） */
    [hidden] { display: none !important; }
    html { -webkit-text-size-adjust: 100%; }
    body {
      font-family: var(--font-body);
      background-color: var(--bg);
      background-image: linear-gradient(180deg, #FFFFFF 0%, #FAFBFC 420px, #F7F8FA 100%);
      background-repeat: no-repeat;
      color: var(--fg);
      min-height: 100vh;
      font-size: var(--text-base);
      line-height: 1.6;
    }
    img { display: block; max-width: 100%; }
    button { font-family: inherit; }
    .icon {
      fill: none;
      stroke: currentColor;
      stroke-width: 1.5;
      stroke-linecap: round;
      stroke-linejoin: round;
      flex: none;
    }
    .icon-12 { width: 12px; height: 12px; }
    .icon-16 { width: 16px; height: 16px; }
    .icon-20 { width: 20px; height: 20px; }
    .icon-24 { width: 24px; height: 24px; }
    :is(button, [tabindex], input, select):focus-visible {
      outline: none;
      box-shadow: var(--focus-ring);
    }

    /* ============================================================
       Section 5: 按钮
       ============================================================ */
    .btn {
      height: 40px; padding: 0 var(--space-4);
      border-radius: var(--radius-md);
      border: 1px solid transparent;
      font-size: var(--text-base); font-weight: var(--weight-emphasis);
      display: inline-flex; align-items: center; justify-content: center;
      gap: var(--space-2); cursor: pointer;
      background: none; color: var(--fg-2);
      /* 按钮文字永不折行：窄屏下「我的」「登录」被挤成两行竖排过（2026-11-01 手机实测） */
      white-space: nowrap;
      transition:
        background-color var(--motion-fast) var(--ease-standard),
        border-color var(--motion-fast) var(--ease-standard),
        color var(--motion-fast) var(--ease-standard);
    }
    .btn.primary { background: var(--btn-primary-bg); color: var(--btn-primary-text); border-radius: var(--radius-full); }
    .btn.primary:hover { filter: brightness(1.15); box-shadow: 0 4px 14px rgba(28, 28, 30, 0.30); }
    .btn.primary:active { filter: brightness(0.95); box-shadow: none; }
    .btn.secondary {
      background: var(--btn-secondary-bg);
      border-color: var(--btn-secondary-border);
      color: var(--btn-secondary-text);
    }
    .btn.secondary:hover { background: var(--btn-secondary-hover); }
    .btn.secondary:active { background: var(--teal-200); }
    .btn.ghost { background: var(--btn-ghost-bg); color: var(--btn-ghost-text); }
    .btn.ghost:hover { background: var(--btn-ghost-hover); }
    .btn.ghost:active { background: var(--btn-ghost-active); }
    .btn.danger { background: var(--btn-danger-bg); color: #FFFFFF; }
    .btn.danger:hover { background: var(--btn-danger-hover); }
    .btn.ai-cta { background: var(--grad-brand); color: #FFFFFF; border-radius: var(--radius-full); }
    .btn.ai-cta:hover { filter: brightness(1.07); }
    .btn.ai-cta:active { filter: brightness(0.95); }
    .btn.big { width: 100%; height: 44px; font-size: var(--text-md); border-radius: var(--radius-md); }
    #btnGenerate { margin-top: var(--space-4); }
    .btn.small { height: 32px; padding: 0 var(--space-3); font-size: var(--text-sm); }
    .btn.icon-round {
      width: 40px; height: 40px; padding: 0; border-radius: var(--radius-full);
    }
    .btn:disabled { opacity: 0.5; cursor: not-allowed; }
    .btn .spin { animation: spin 0.8s linear infinite; }
    @keyframes spin { to { transform: rotate(360deg); } }

    /* ============================================================
       Section 8: 表单
       ============================================================ */
    .field-label {
      display: block; font-size: var(--text-sm); font-weight: var(--weight-emphasis);
      color: var(--fg-2); margin: var(--space-4) 0 var(--space-2);
    }
    .group-label {
      display: block; font-size: var(--text-sm); font-weight: var(--weight-emphasis);
      color: var(--muted); letter-spacing: 0.06em; text-transform: uppercase;
      margin: var(--space-5) 0 var(--space-2);
    }
    .group-label:first-of-type { margin-top: var(--space-4); }
    .field-error { margin-top: var(--space-1); font-size: var(--text-xs); color: var(--danger); }
    .helper-text { margin-top: var(--space-1); font-size: var(--text-xs); color: var(--meta); word-break: break-all; }
    .text-input {
      width: 100%; height: 40px; padding: 0 var(--space-3);
      font-size: var(--text-base); font-family: var(--font-body);
      border: 1px solid var(--input-border); border-radius: var(--radius-md);
      background: var(--input-bg); color: var(--fg); outline: none;
      transition: border-color var(--motion-fast) var(--ease-standard);
    }
    .text-input.mono { font-family: var(--font-mono); font-size: var(--text-sm); }
    .text-input:focus { border-color: var(--input-focus-border); }
    .text-input.input-error { border-color: var(--input-error-border); }
    select.text-input { appearance: auto; cursor: pointer; }

    /* ============================================================
       Section 9: 提示行
       ============================================================ */
    .hint { margin-top: var(--space-3); font-size: var(--text-sm); color: var(--muted); min-height: 20px; line-height: 1.5; }
    .hint.warn { color: var(--warning); }
    .hint a { color: var(--teal-600); text-decoration: none; }
    .hint a:hover { text-decoration: underline; }

    /* ============================================================
       Section 12: 弹窗（设置 / 大图预览）
       ============================================================ */
    .modal-mask {
      position: fixed; inset: 0; z-index: 50;
      background: var(--mask);
      display: flex; align-items: center; justify-content: center;
      padding: var(--space-4);
    }
    .modal {
      background: var(--surface);
      border-radius: var(--radius-xl);
      width: 480px; max-width: 100%;
      max-height: 90vh; overflow-y: auto;
      padding: var(--space-6);
      box-shadow: var(--shadow-lg);
      animation: rise var(--motion-slow) var(--ease-exit);
    }
    .modal-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
    /* 弹窗关闭钮：登录弹窗由平台层注入，样式必须落在共用层（不能依赖某个产品的 CSS） */
    .btn-close-modal {
      width: 32px; height: 32px; flex: none;
      display: inline-flex; align-items: center; justify-content: center;
      border: none; border-radius: var(--radius-full);
      background: var(--ink-100); color: var(--muted);
      font-size: 18px; line-height: 1;
      cursor: pointer; -webkit-appearance: none; appearance: none;
      transition: background-color var(--motion-fast) var(--ease-standard),
                  color var(--motion-fast) var(--ease-standard);
    }
    .btn-close-modal:hover { background: var(--border); color: var(--fg); }
    .modal-head h3 { font-size: var(--text-xl); font-weight: var(--weight-announce); }
    .modal-desc {
      margin: var(--space-3) 0 0;
      font-size: var(--text-sm); color: var(--muted); line-height: 1.7;
    }
    .modal-actions {
      margin-top: var(--space-5);
      display: flex; justify-content: flex-end; gap: var(--space-2);
    }

    /* ============================================================
       Section 13: 人工充值 / 客服（2026-11-04 起线上支付的替代通道）
       ------------------------------------------------------------
       xunhupay 商户还没下号，套餐卡只负责标价，钱走微信人工充值。
       这块要满足两个场景：钱包弹窗里紧凑版（150px 码 + 三步说明），
       以及页脚「联系客服」弹出来的大码版（220px，未登录也能开）。
       ============================================================ */
    .manual-pay {
      margin-top: var(--space-4);
      display: flex; align-items: center; gap: var(--space-4);
      padding: var(--space-4);
      border: 1px solid var(--border);
      border-radius: var(--radius-lg);
      background: var(--ink-50);
      transition: border-color var(--motion-fast) var(--ease-standard),
                  box-shadow var(--motion-fast) var(--ease-standard);
    }
    .manual-pay.flash {
      border-color: var(--teal-400);
      box-shadow: 0 0 0 3px rgba(66, 98, 255, .20);
    }
    .mp-qr {
      /* 168 不是随手取的：企业微信名片码模块多（57×57+），150px 时单模块只剩 2.6px，
         OpenCV 已解不出，手机扫也吃力。168px 是实测能稳定解的临界点。 */
      width: 168px; height: 168px; flex: none;
      border-radius: var(--radius-md);
      background: #fff;
      display: block;
    }
    .mp-body { min-width: 0; }
    .mp-title { font-size: var(--text-base); font-weight: var(--weight-announce); color: var(--fg); }
    .mp-desc { margin-top: 6px; font-size: var(--text-sm); color: var(--muted); line-height: 1.65; }
    .mp-desc b { color: var(--fg-2); font-weight: var(--weight-emphasis); }
    .mp-eta {
      margin-top: 8px;
      display: inline-block;
      font-size: var(--text-xs); font-weight: var(--weight-emphasis);
      color: var(--teal-700);
      background: var(--teal-50);
      border-radius: var(--radius-full);
      padding: 2px 9px;
    }
    .mp-tip { margin-top: 6px; font-size: var(--text-xs); color: var(--meta); }

    /* 客服弹窗（页脚入口，不需要登录） */
    .modal-contact { width: 460px; }
    .contact-qr-wrap {
      margin: var(--space-5) auto var(--space-4);
      /* fit-content 而不是写死 220：写死的话 padding 会把内容区压到 196，
         图片被 max-width 缩成 194 宽（不是正方），扫码反而更小 */
      width: fit-content; max-width: 100%;
      padding: var(--space-3);
      border: 1px solid var(--border);
      border-radius: var(--radius-lg);
      background: #fff;
    }
    .contact-qr { width: 220px; height: 220px; max-width: 100%; display: block; margin: 0 auto; }
    .contact-step {
      margin-top: var(--space-3);
      font-size: var(--text-sm); color: var(--muted); line-height: 1.75;
    }
    .contact-step b { color: var(--fg-2); font-weight: var(--weight-emphasis); }
    .contact-step a { color: var(--teal-600); text-decoration: none; }
    .contact-step a:hover { text-decoration: underline; }

    /* 顶栏客服入口（平台层注入，三页共用，首屏可见） */
    .topbar-actions .btn-contact {
      height: 34px; padding: 0 12px; gap: 5px;
      border-radius: var(--radius-full);
      font-size: var(--text-sm);
      white-space: nowrap;
      color: var(--teal-700);
      background: var(--teal-50);
      border-color: var(--teal-100);
    }
    .topbar-actions .btn-contact:hover { background: var(--teal-100); }
    /* 窄屏：顶栏要同时塞下「客服/登录(我的)/积分」，320–430px 会被撑出横向溢出
       （2026-11-04 回归抓到：登录态 414px 时 doc=513，整页会被手机缩放到 ~80%）。
       收法：客服只留图标、按钮内边距收紧、品牌英文让位（中文「点豆」+ Logo 仍可识别）。 */
    @media (max-width: 480px) {
      .topbar-actions { gap: 6px; }
      .topbar-actions .btn { padding: 0 9px; font-size: 13px; }
      .topbar-actions .btn-contact { padding: 0 9px; gap: 0; }
      .topbar-actions .btn-contact span { display: none; }
      .brand-en { display: none; }
    }
    /* 375/360（iPhone SE、多数安卓）：再紧一档，实测差 3–25px */
    @media (max-width: 400px) {
      .topbar-actions { gap: 3px; }
      .topbar-actions .btn { padding: 0 4px; font-size: 12px; }
      .topbar-actions .btn-contact { padding: 0 4px; }
      .topbar-inner { padding-left: 10px; padding-right: 10px; }
    }
    /* 320（iPhone SE 1 代等）：四颗按钮放不下，品牌只留 Logo，优先保住功能入口 */
    @media (max-width: 340px) {
      .brand > span:not(.brand-logo) { display: none; }
      .topbar-inner { padding-left: 10px; padding-right: 10px; }
      .topbar-actions { gap: 3px; }
      .topbar-actions .btn { padding: 0 4px; }
      .topbar-actions .btn-contact { padding: 0 4px; }
    }

    /* 窄屏：横排会把说明挤成窄柱，改上下堆叠 */
    @media (max-width: 560px) {
      .manual-pay { flex-direction: column; text-align: center; gap: var(--space-3); }
      .mp-qr { width: 168px; height: 168px; }
      .contact-qr { width: 200px; height: 200px; }
    }

    /* ============================================================
       Section 14: 动效无障碍
       ============================================================ */
    @media (prefers-reduced-motion: reduce) {
      *, *::before, *::after {
        animation-duration: 1ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 1ms !important;
      }
    }
    /* ============================================================
       Section S7: 登录与云同步（全部走既有 Token）
       ============================================================ */
    .topbar-actions { display: flex; align-items: center; gap: var(--space-2); flex: none; }
    /* 品牌文字不许换行：窄屏顶栏被按钮挤压时「点豆」会一个字一行（2026-11-04 375px 实测） */
    .brand { white-space: nowrap; }
    /* 「我的」入口用 <a> 承担按钮外观（与积分按钮同款），链接不该有下划线 */
    .topbar-actions a.btn { text-decoration: none; }
    /* 顶栏 pill：「我的」入口与「积分」钱包同一套视觉——浅黄底、无边框、粗字重。
       加 .pill 即可，产品不必再为各自的钱包按钮重写配色。 */
    .topbar-actions .btn.pill {
      background: var(--pill-bg);
      border-color: transparent;
      color: var(--pill-text);
      font-weight: 700;
    }
    .topbar-actions .btn.pill:hover { background: var(--pill-hover); }
    .topbar-actions .btn.pill:active { background: var(--pill-active); }
    #btnLogin {
      height: 34px; padding: 0 14px; gap: 6px;
      border-radius: var(--radius-full);
      font-size: var(--text-sm);
      background: var(--surface);
      border: 1px solid var(--border);
      color: var(--fg);
      box-shadow: var(--shadow-sm);
      transition:
        background-color var(--motion-fast) var(--ease-standard),
        border-color var(--motion-fast) var(--ease-standard),
        box-shadow var(--motion-fast) var(--ease-standard);
    }
    #btnLogin:hover {
      background: var(--teal-50);
      border-color: var(--teal-300);
      color: var(--teal-700);
      box-shadow: none;
    }
    #btnLogin:active { background: var(--teal-100); }
    #btnLogin .icon { flex: none; }
    .btn.secondary {
      background: var(--btn-secondary-bg);
      border: 1px solid var(--btn-secondary-border);
      color: var(--btn-secondary-text);
    }
    .btn.secondary:hover { background: var(--btn-secondary-hover); }
    .btn.secondary:active { background: var(--teal-200); }
    .user-chip {
      display: inline-flex; align-items: center; gap: 6px;
      padding: 4px 10px; border-radius: var(--radius-full);
      background: var(--teal-50); border: 1px solid var(--teal-200);
      color: var(--teal-700); font-size: var(--text-xs); font-weight: 510;
      max-width: 180px;
    }
    .user-chip .icon { flex: none; }
    .user-chip-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    .phone-row { display: flex; gap: var(--space-2); }
    .phone-row .text-input { flex: 1; min-width: 0; }
    .phone-row .btn { flex: none; white-space: nowrap; }
    .btn:disabled { opacity: 0.5; cursor: not-allowed; }
    .login-divider {
      display: flex; align-items: center; gap: var(--space-3);
      margin: var(--space-4) 0; color: var(--meta); font-size: var(--text-xs);
    }
    .login-divider::before, .login-divider::after {
      content: ''; flex: 1; height: 1px; background: var(--border-soft);
    }
    /* 余额卡：用品牌黄 --amber-500（与产品 logo 底框同色），是页面里唯一的
       重色块，用来强调余额；顶栏 pill 用淡黄 --pill-bg，两者刻意不同层。
       不要再各产品各写一份字面色值——那样迟早分叉。 */
    .wallet-balance {
      background: var(--amber-500);
      border-radius: var(--radius-lg);
      padding: 16px 20px 18px;
      margin: var(--space-4) 0 var(--space-2);
      display: flex; flex-direction: column; gap: 4px;
    }
    .wallet-balance .wb-label {
      font-size: var(--text-sm); font-weight: var(--weight-emphasis);
      color: rgba(31, 29, 26, 0.72);
    }
    .wallet-balance .wb-num {
      display: flex; align-items: baseline; gap: 8px;
      font-size: 15px; font-weight: 700; color: #1F1D1A;
    }
    .wallet-balance b {
      font-size: 44px; line-height: 1.1; letter-spacing: -0.02em;
      font-weight: 800; color: #1F1D1A;
    }
    .product-grid {
      display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-2);
    }
    .product-card {
      background: #F7F8FA; border: 1px solid #E5E7EC; border-radius: 14px;
      padding: var(--space-3) var(--space-2); text-align: center;
      display: flex; flex-direction: column; gap: 3px;
    }
    .product-card .p-name { font-size: var(--text-xs); color: var(--meta); }
    .product-card .p-credits { font-size: 18px; font-weight: 700; color: var(--fg); }
    .product-card .p-price {
      /* 价格是用户最想看的一项，12px 浅灰等于藏起来（2026-11-04 改）： */
      font-size: var(--text-md); font-weight: var(--weight-announce); color: var(--fg-2);
    }
    .product-card .btn {
      margin-top: 6px; height: 30px; font-size: var(--text-xs);
      border-radius: var(--radius-full);
    }
    /* 钱包弹窗右上关闭按钮（结构由平台层生成，这里给尺寸，不依赖产品图标集） */
    .wallet-close {
      width: 32px; height: 32px; padding: 0; flex: none;
      border-radius: var(--radius-full);
    }
    /* 弹窗底部：引导到 /my 的积分明细
       刻意做成「次级小按钮」——比弹窗里的主按钮矮一档、按内容收窄并居中，
       不做整宽 44px 的大按钮（那样会把弹窗压得头重脚轻）。
       配色写死中性值（不跟主题的 secondary），三个页面看起来才是同一个按钮 */
    .btn.wallet-more {
      display: flex; width: fit-content;
      margin: var(--space-4) auto 0;
      height: 34px; padding: 0 var(--space-4);
      font-size: var(--text-sm); font-weight: var(--weight-emphasis);
      border-radius: var(--radius-full);
      border: 1px solid #E5E7EC;
      background: var(--surface);
      color: #1F1D1A;
      text-decoration: none;
    }
    .btn.wallet-more:hover { background: #F7F8FA; border-color: #D8DBE3; }
    /* 明细列表：不做内部滚动（滚动条在移动端很难用，也挡内容），
       改成整页翻页——由 /my 的 JS 每页 10 条切片渲染。 */
    .txn-list {
      border: 1px solid var(--border-soft); border-radius: 10px;
      overflow: hidden;
    }
    .txn-pager {
      display: flex; align-items: center; justify-content: center;
      gap: var(--space-3); margin-top: var(--space-4);
    }
    .txn-pager .txn-page {
      min-width: 56px; text-align: center;
      font-size: var(--text-sm); color: var(--meta);
      font-variant-numeric: tabular-nums;
    }
    .txn-item {
      display: flex; align-items: center; gap: var(--space-2);
      padding: var(--space-2) var(--space-3);
      /* 没有副标题的行（老流水 / 充值）与有副标题的行保持同一高度，
         否则一页里高高低低，看着像排版错位 */
      min-height: 56px;
      border-bottom: 1px solid var(--border-soft);
      font-size: var(--text-xs);
    }
    .txn-item:last-child { border-bottom: none; }
    .txn-item .t-main { flex: 1; min-width: 0; }
    .txn-item .t-kind { color: var(--text); }
    .txn-item .t-note { color: var(--meta); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .txn-item .t-credits { font-weight: 500; white-space: nowrap; }
    .txn-item .t-credits.plus { color: var(--success); }
    .txn-item .t-credits.minus { color: var(--danger); }
    .txn-item .t-time { color: var(--meta); white-space: nowrap; }
    @media (max-width: 480px) {
      .product-grid { grid-template-columns: repeat(3, 1fr); }
    }

    /* ============================================================
       Section 16: 浮层提示（toast）
       「没点任何按钮就发生的结果」（如兑换链接自动到账）写在表单下方没人看，
       统一浮到页面顶部中间：4.5s 自动消失、点一下也能关、不抢焦点。
       ============================================================ */
    .pf-toast-wrap {
      /* 右上角：顶栏（约 62px）下方滑动出现。放正中会压住两页的主标题，
         放顶部居中又会盖住 logo / 积分按钮，右上角是唯一不打架的位置。 */
      position: fixed; top: 76px; right: 24px; left: auto;
      z-index: 90; width: auto; max-width: min(90vw, 420px);
      display: flex; flex-direction: column; align-items: flex-end; gap: 10px;
      pointer-events: none;
    }
    .pf-toast {
      pointer-events: auto; cursor: pointer;
      display: flex; align-items: center; gap: 10px;
      max-width: 100%; padding: 12px 16px;
      border-radius: var(--radius-md);
      background: var(--surface); color: var(--fg);
      border: 1px solid var(--border);
      box-shadow: 0 10px 30px rgba(28, 28, 30, .14);
      font-size: var(--text-base); line-height: 1.45;
      opacity: 0; transform: translateY(-8px) scale(.985);
      transition: opacity .2s ease, transform .2s ease;
    }
    .pf-toast.in { opacity: 1; transform: none; }
    .pf-toast.out { opacity: 0; transform: translateY(-6px); }
    .pf-toast-icon {
      flex: none; width: 20px; height: 20px; border-radius: 50%;
      display: inline-flex; align-items: center; justify-content: center;
      font-size: 12px; font-weight: 700; line-height: 1;
    }
    .pf-toast-text { min-width: 0; }
    .pf-toast-ok { border-color: var(--success-border); }
    .pf-toast-ok .pf-toast-icon { background: var(--success-bg); color: var(--success); }
    .pf-toast-error { border-color: var(--danger-border); }
    .pf-toast-error .pf-toast-icon { background: var(--danger-bg); color: var(--danger); }
    .pf-toast-info .pf-toast-icon { background: var(--teal-50); color: var(--teal-600); }
    @media (max-width: 480px) {
      .pf-toast-wrap {
        top: 64px; left: 12px; right: 12px; max-width: none; align-items: stretch;
      }
      .pf-toast { padding: 10px 12px; font-size: var(--text-sm); }
    }

    /* 游客福利条：挂在顶栏内、紧贴顶栏下方。顶部一条浅绿带，未登录常驻可见。
       以前是底部浮动小条，会挡住内容且用户很难一眼看到（2026-11-03 改）。
       点整条（或「免费领取」）打开登录框；× 可关掉并记入 sessionStorage。 */
    .pf-newuser-bar {
      background: linear-gradient(180deg, #F0FDF4 0%, #ECFDF5 100%);
      border-top: 1px solid var(--success-border);
      cursor: pointer; user-select: none;
    }
    .pf-newuser-bar[hidden] { display: none; }
    .pf-newuser-bar-inner {
      max-width: 1120px; margin: 0 auto;
      padding: 8px 24px;
      display: flex; align-items: center; justify-content: center;
      gap: 12px; flex-wrap: wrap;
      font-size: var(--text-sm); line-height: 1.4; color: #166534;
    }
    .pf-newuser-text {
      display: inline-flex; align-items: baseline; gap: 8px;
      min-width: 0; flex-wrap: wrap; justify-content: center;
    }
    .pf-newuser-gift { font-size: 16px; line-height: 1; flex: none; }
    .pf-newuser-main { font-weight: 700; color: #15803D; font-size: 15px; }
    .pf-newuser-sub { color: #166534; opacity: .9; font-size: 13px; }
    .pf-newuser-bar .btn { flex: none; }
    .pf-newuser-close {
      flex: none; width: 24px; height: 24px; padding: 0;
      border: none; background: none; cursor: pointer;
      border-radius: 50%; color: #166534;
      font-size: 16px; line-height: 1;
      display: inline-flex; align-items: center; justify-content: center;
    }
    .pf-newuser-close:hover { background: rgba(22, 101, 52, .10); }
    @media (max-width: 480px) {
      /* 窄屏保住一行：主文案 + 「共 N 次免费生成」+ 按钮 + ×  约 330px 可容纳 */
      .pf-newuser-bar-inner { padding: 8px 12px; gap: 8px; }
      .pf-newuser-sub { font-size: 12px; }
      .pf-newuser-main { font-size: 14px; }
      .pf-newuser-gift { font-size: 14px; }
    }

    /* 登录弹窗内的福利块：注册前就看得见送多少（比副标题一行更醒目） */
    .pf-welcome-note {
      display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
      margin-top: var(--space-3);
      padding: 10px 12px;
      border-radius: var(--radius-md, 10px);
      background: #F0FDF4; border: 1px solid var(--success-border);
      font-size: var(--text-sm); color: #166534;
    }
    .pf-welcome-note[hidden] { display: none; }
    .pf-welcome-main { font-weight: 700; color: #15803D; font-size: var(--text-base); }
    .pf-welcome-sub { opacity: .85; }
