    /* =========================================================
    * 点豆 DotBeads · 页面级样式（2026-10-29 设计稿四版：渐变底 + 黄油体面板标题）
    * 设计基准：Ardot 设计稿「01 首页·工作区 / 03 登录弹窗 / 04 积分钱包弹窗」
    * 渐变底 #FFFFFF→#FAFBFC→#F7F8FA + 面板描边 #E5E7EC + 豆黄 #FFD02F + 墨 #1F1D1A
    * 本文件只在拼豆页加载，token 覆盖不影响其他产品页。
    * ========================================================= */

    /* ===== 品牌字体：站酷庆科黄油体（设计稿指定） =====
     * 子集化 23 字「点豆一下，就有 + 上传图片选择画风生成结果 + 拼图纸交互」（4.4KB），
     * 覆盖品牌名、Hero 标题、三处面板标题与图纸页顶栏标题；其余字符自动回退到系统圆体栈。
     * 若文案改字，需重新生成子集：
     * https://fonts.googleapis.com/css2?family=ZCOOL+QingKe+HuangYou&text=<新文案>
     */
    @font-face {
      font-family: "ZCOOL QingKe HuangYou";
      font-style: normal;
      font-weight: 400;
      font-display: swap;
      src: url("assets/fonts/zcool-qingke-huangyou-brand.woff2") format("woff2");
      unicode-range: U+4E00, U+4E0A-4E0B, U+4E92, U+4EA4, U+4F20, U+56FE, U+5C31, U+6210, U+62E9, U+62FC, U+6709, U+679C, U+70B9, U+7247, U+751F, U+753B, U+7EB8, U+7ED3, U+8C46, U+9009, U+98CE, U+FF0C;
    }

    /* ===== Token 覆盖：墨色主 CTA / 渐变底 / 冷灰描边（2026-10-29 四版设计稿） ===== */
    :root {
      --bg: #F7F8FA;
      --border-soft: #E5E7EC;
      --btn-primary-bg:     #1F1D1A;
      --btn-primary-text:   #FFFFFF;
      --btn-primary-hover:  #3A3730;
      --btn-primary-active: #2A2722;
      --btn-secondary-bg:     #FFFFFF;
      --btn-secondary-border: #1F1D1A;
      --btn-secondary-text:   #1F1D1A;
      --btn-secondary-hover:  #F7F8FA;
      --input-bg:           #FFFFFF;
      --input-border:       #E5E7EC;
      --input-focus-border: #F0BB00;
      --card-selected-ring: 0 0 0 2px #FFFFFF, 0 0 0 4px #FFD02F;
      --card-hover-shadow:  0 6px 16px rgba(31, 41, 55, 0.10);
      --focus-ring: 0 0 0 3px rgba(240, 187, 0, 0.35);
    }

    /* ===== 布局（容器 / 顶栏 / Hero / 步骤 / 双栏） ===== */
    /* 页面底：垂直渐变（设计师 spec：#FFFFFF → 420px 处 #FAFBFC → #F7F8FA） */
    body {
      background-color: #F7F8FA;
      background-image: linear-gradient(180deg, #FFFFFF 0px, #FAFBFC 420px, #F7F8FA 100%);
      background-repeat: no-repeat;
      background-size: 100% 100%;
    }
    .topbar {
      position: sticky; top: 0; z-index: 20;
      background: var(--surface);
      border-bottom: 1px solid var(--border-soft);
    }
    .topbar-inner {
      max-width: var(--container-max); margin: 0 auto;
      padding: var(--space-3) var(--container-gutter);
      display: flex; align-items: center; justify-content: space-between;
    }
    .brand { display: flex; align-items: center; gap: 10px; font-size: 22px; font-weight: 400; letter-spacing: 0;
      font-family: "ZCOOL QingKe HuangYou", "Yuanti SC", "Hiragino Maru Gothic ProN", "YouYuan", "PingFang SC", sans-serif; }
    .brand-logo {
      width: 32px; height: 32px; border-radius: 10px;
      background: #FFD02F;
      display: inline-flex; align-items: center; justify-content: center;
      box-shadow: 0 2px 6px rgba(240, 187, 0, 0.45);
    }
    .brand-logo svg { width: 20px; height: 20px; display: block; }
    .brand-en { font-family: "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
      font-size: 11px; letter-spacing: 0.18em; color: #7A7A7A; font-weight: 600; padding-bottom: 2px; }

    /* 顶栏 pill（积分 / 我的）配色统一在 base.css 的 `.btn.pill`，此处不再覆写 */
    /* 兑换按钮不再单独覆写：统一用 .btn.primary，与「购买」同一套视觉 */
    /* 获取验证码：浅黄底（设计稿） */
    #btnSendCode {
      background: #FFE9A9; border-color: transparent; color: #1F1D1A; font-weight: 600;
    }
    #btnSendCode:hover { background: #FFDF7E; }
    #btnSendCode:active { background: #FFD65E; }

    .page {
      max-width: var(--container-max); margin: 0 auto;
      padding: var(--space-8) var(--container-gutter) var(--space-12);
    }

    /* Hero：居中式，手绘黄下划线衬「豆就有」（设计稿三版） */
    .hero { text-align: center; margin-bottom: var(--space-8); padding: var(--space-3) 0 0; }
    .hero h1 {
      font-family: "ZCOOL QingKe HuangYou", "Yuanti SC", "Hiragino Maru Gothic ProN", "YouYuan", "PingFang SC", sans-serif;
      font-size: clamp(34px, 4.5vw, 48px); font-weight: 400;
      line-height: 1.3; letter-spacing: 0; color: var(--fg);
    }
    .hero h1 em {
      font-style: normal; position: relative; display: inline-block; padding: 0 2px;
    }
    .hero h1 em::after {
      content: ''; position: absolute; left: 0; right: -2px; bottom: -8px; height: 9px;
      background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 14' preserveAspectRatio='none'%3E%3Cpath d='M3 10 Q 30 3 62 7 T 117 5' fill='none' stroke='%23FFD02F' stroke-width='7' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat center / 100% 100%;
    }
    .hero p {
      font-family: "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;
      margin-top: 8px; color: #5F6478; font-size: 14px; font-weight: 400; letter-spacing: 0;
    }

    /* 步骤条：居中圆形序号式，去药丸（设计稿三版）——当前步黄圆，未到步米圆 */
    .steps {
      display: flex; align-items: center; justify-content: center; gap: var(--space-3);
      flex-wrap: wrap; margin-bottom: var(--space-6);
    }
    .step {
      display: inline-flex; align-items: center; gap: 8px;
      font-size: 15px; font-weight: 500; color: var(--fg-2);
      padding: 0;
      background: transparent; border: none;
      transition: color var(--motion-base) var(--ease-standard);
    }
    .step-num {
      width: 28px; height: 28px; border-radius: var(--radius-full);
      background: #F2F3F6; color: #1F1D1A;
      display: inline-flex; align-items: center; justify-content: center;
      font-size: var(--text-xs); font-weight: var(--weight-announce);
      transition: background-color var(--motion-base) var(--ease-standard), color var(--motion-base) var(--ease-standard);
    }
    .step.active { color: var(--fg); font-weight: 600; }
    .step.active .step-num { background: #FFD02F; color: #1F1D1A; }
    .step.done { color: var(--success); }
    .step.done .step-num { background: #FFD02F; color: #1F1D1A; }
    .step-arrow { color: var(--meta); display: inline-flex; }

    .layout {
      display: grid;
      grid-template-columns: minmax(0, 1fr) 400px;
      gap: var(--space-5);
      align-items: start;
    }
    /* grid 子项默认 min-width:auto：里面一条 nowrap 的长文本（如超长文件名）
       会把轨道撑到内容宽，整页比视口宽出 400 多 px。iOS Safari 遇到比视口宽的
       页面会整页缩放（实际见过缩到 ~50%），表现为「整页变小、右边一片空白」，
       手机上极难自愈。这里把最小宽度交还给轨道，超长内容走各自的省略号。 */
    .layout > * { min-width: 0; }

    .panel {
      background: var(--surface);
      border: 1px solid var(--border-soft);
      border-radius: var(--radius-lg);
      box-shadow: var(--shadow-sm);
      padding: var(--space-6);
    }
    /* 面板标题：黄油体 20px 墨色（设计稿四版「上传图片 / 选择画风 / 生成结果」） */
    .panel-title {
      font-family: "ZCOOL QingKe HuangYou", "Yuanti SC", "Hiragino Maru Gothic ProN", "YouYuan", "PingFang SC", sans-serif;
      font-size: 20px; font-weight: 400;
      letter-spacing: 0;
      margin: var(--space-5) 0 var(--space-3);
      display: flex; align-items: center; gap: var(--space-2); color: var(--fg);
    }
    .panel-title:first-child { margin-top: 0; }
    .panel-title .icon { color: var(--muted); }

    .footer {
      margin-top: var(--space-10);
      text-align: center; font-size: var(--text-sm); color: var(--meta);
    }

    /* ===== 上传区（Empty / Dragover / 已选 三态） ===== */
    .upload-zone {
      min-height: 170px;
      border: 1.5px dashed #7A7A7A;
      border-radius: var(--radius-lg);
      background: var(--bg);
      cursor: pointer; outline: none;
      transition: border-color var(--motion-base) var(--ease-standard), background-color var(--motion-base) var(--ease-standard);
    }
    .upload-zone:hover { border-color: var(--amber-600); }
    .upload-zone.drag {
      border-style: solid; border-color: var(--amber-600);
      background: var(--amber-100);
    }
    .upload-zone.drag .upload-empty .icon,
    .upload-zone.drag .upload-main { color: var(--amber-700); }
    .upload-empty {
      min-height: 167px;
      display: flex; flex-direction: column; align-items: center; justify-content: center;
      gap: var(--space-2); text-align: center; padding: var(--space-4);
      color: var(--meta);
    }
    .upload-main { font-size: var(--text-base); font-weight: var(--weight-emphasis); color: var(--fg-2); }
    .upload-sub { font-size: var(--text-xs); color: var(--meta); }
    .upload-selected {
      display: flex; align-items: center; gap: var(--space-3);
      padding: var(--space-4); min-height: 167px;
    }
    .upload-thumb {
      width: 56px; height: 56px; border-radius: var(--radius-md);
      object-fit: cover; border: 1px solid var(--border); flex: none;
    }
    .upload-meta { min-width: 0; flex: 1; overflow: hidden; }
    .upload-name {
      font-size: var(--text-base); font-weight: var(--weight-emphasis); color: var(--fg);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .upload-size { font-size: var(--text-xs); color: var(--meta); margin-top: 2px; }
    .btn-remove-photo {
      width: 24px; height: 24px; flex: none; align-self: flex-start;
      display: inline-flex; align-items: center; justify-content: center;
      border: none; border-radius: var(--radius-full);
      background: transparent; color: var(--muted); cursor: pointer;
      transition: background-color var(--motion-fast) var(--ease-standard), color var(--motion-fast) var(--ease-standard);
    }
    .btn-remove-photo:hover { background: var(--danger-bg); color: var(--danger); }
    #errFile { margin-top: var(--space-2); }

    /* ===== 画风网格：选中黄描边（设计稿二版：白底） ===== */
    .style-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
      gap: var(--space-3);
    }
    .style-grid .hint { margin: 0; }
    /* 首屏骨架：占位块与真实画风卡同尺寸（92px 图 + 名称），带一层缓慢流光。
       画风列表本身很小（~1KB），骨架基本一闪而过；慢网下也不会出现「空着像坏了」的状态。 */
    .style-skel {
      display: block; height: 118px; border-radius: var(--radius-lg);
      border: 1.5px solid var(--border-soft);
      background: linear-gradient(100deg, var(--ink-50) 34%, #EEF1F5 50%, var(--ink-50) 66%);
      background-size: 260% 100%;
      animation: skel-sweep 1.15s linear infinite;
    }
    @keyframes skel-sweep {
      from { background-position: 140% 0; }
      to { background-position: -60% 0; }
    }
    @media (prefers-reduced-motion: reduce) {
      .style-skel { animation: none; }
    }
    .style-grid .link-btn {
      background: none; border: 0; padding: 0; cursor: pointer;
      font: inherit; color: var(--teal-700); text-decoration: underline; text-underline-offset: 2px;
    }
    .style-card {
      position: relative;
      border: 1.5px solid var(--border-soft); border-radius: var(--radius-lg);
      overflow: hidden; background: var(--surface);
      padding: 0; text-align: left;
      cursor: pointer; user-select: none; outline: none;
      transition:
        transform var(--motion-fast) var(--ease-standard),
        box-shadow var(--motion-fast) var(--ease-standard),
        border-color var(--motion-fast) var(--ease-standard),
        background-color var(--motion-fast) var(--ease-standard);
    }
    .style-card:hover {
      transform: translateY(-2px);
      box-shadow: var(--card-hover-shadow);
      border-color: var(--amber-300);
    }
    .style-card.cur {
      border-color: #FFD02F;
      background: var(--surface);
      box-shadow: 0 0 0 1px #FFD02F;
    }
    .style-card.cur .card-name { color: var(--fg); }
    .card-art {
      height: 92px; display: block; position: relative;
      background-color: var(--ink-50);
      background-position: center; background-size: cover; background-repeat: no-repeat;
    }
    .card-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
    .card-art .icon {
      position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
      color: var(--muted);
    }
    .card-check {
      position: absolute; top: var(--space-1); right: var(--space-1);
      width: 20px; height: 20px; border-radius: var(--radius-full);
      background: #FFD02F; color: #1F1D1A;
      display: none; align-items: center; justify-content: center;
    }
    .style-card.cur .card-check { display: inline-flex; }
    .card-name {
      display: block; padding: 6px 8px;
      font-size: var(--text-xs); font-weight: var(--weight-emphasis); color: var(--fg);
      text-align: center; letter-spacing: 0.01em;
      background: transparent;
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
      transition: color var(--motion-base) var(--ease-standard);
    }
    .style-letter {
      width: 100%; height: 100%;
      display: flex; align-items: center; justify-content: center;
      font-size: 24px; font-weight: 700; color: var(--muted);
    }
    /* 画风说明行：选中画风的生成效果说明，位置在「选择画风」标题下、网格上方
       大小/字重/颜色与「想调整的地方（可选）」的 .field-label（base.css）保持一致 */
    .style-desc {
      margin: 0 0 var(--space-3);
      font-size: var(--text-base); font-weight: var(--weight-body);
      color: var(--fg); line-height: 1.7;
    }
    .style-desc .style-demo-link {
      color: var(--teal-700); text-decoration: underline; text-underline-offset: 2px;
      white-space: nowrap;
    }

    /* ===== 备注（单行输入） ===== */
    .extra-row { margin-top: var(--space-5); }

    /* ===== 生成按钮：积分角标（白底墨字 pill，压在墨底上） ===== */
    .cost-tag {
      font-size: var(--text-xs); font-weight: var(--weight-announce);
      color: #1F1D1A;
      background: rgba(255, 255, 255, 0.92);
      border: none;
      border-radius: var(--radius-full);
      padding: 1px 8px;
    }
    /* 失败原文可能带整段上游 JSON（无空格长串）：断行 + 限高滚动，既不撑破面板也不丢内容 */
    #studioMsg {
      min-height: 20px;
      overflow-wrap: anywhere; word-break: break-word;
      max-height: 30vh; overflow-y: auto;
    }
    /* 墨色主按钮（设计稿二版） */
    .btn.primary { border-radius: var(--radius-md); }
    .btn.primary:hover { box-shadow: 0 4px 14px rgba(31, 29, 26, 0.28); }
    .btn.primary:active { box-shadow: none; }

    /* ===== 结果区（空 / 生成中 / 完成） ===== */
    .result-panel { display: flex; flex-direction: column; }
    /* flex: none —— 右栏是定高 flex 列，默认 flex-shrink 会把它压到 380px，
       而它带 overflow:hidden：出图后缩略图+按钮会被裁掉一截（2026-11-12 量到 57px）。
       「继续改这张」挪到结果区外面之后，这里被裁就会跟下面的面板视觉重叠。 */
    .result-stage {
      flex: none; aspect-ratio: auto; min-height: 320px;
      display: grid; place-items: center;
      border-radius: var(--radius-lg);
      background: var(--bg);
      border: 1px solid var(--border-soft);
      padding: var(--space-4);
      position: relative; overflow: hidden;
    }
    .result-empty { text-align: center; color: var(--meta); }
    .result-empty .icon { margin: 0 auto var(--space-2); }
    .result-empty p { font-size: var(--text-sm); }
    .result-loading { text-align: center; width: 100%; }
    .spinner {
      width: 40px; height: 40px; margin: 0 auto var(--space-4);
      border: 3px solid var(--amber-100); border-top-color: var(--amber-600);
      border-radius: 50%;
      animation: spin 0.8s linear infinite;
    }
    .loading-tip {
      font-size: var(--text-sm); color: var(--muted);
      max-width: 30ch; margin: 0 auto; line-height: 1.7;
    }
    .result-loading .btn { margin-top: var(--space-4); }
    /* C2 · 生图预览：底稿先出来时顶上摆一张小图，明确「这是底稿，图纸还在切」。
       方形容器 + contain：底稿比例不一，不裁切、不拉伸。 */
    .loading-preview {
      width: 168px; height: 168px; margin: 0 auto var(--space-4);
      border: 1px solid var(--border); border-radius: var(--radius-md);
      background: var(--ink-50);
      overflow: hidden;
      animation: pa-preview-in var(--motion-slow) var(--ease-exit);
    }
    .loading-preview img { display: block; width: 100%; height: 100%; object-fit: contain; }
    /* 有预览时把转圈缩小一半：图已经在那儿了，转圈只是「还在做」的提示 */
    .loading-preview + .spinner { width: 22px; height: 22px; border-width: 2px; margin-bottom: var(--space-3); }
    @keyframes pa-preview-in {
      from { opacity: 0; transform: translateY(6px) scale(0.98); }
      to { opacity: 1; transform: none; }
    }
    .result-done { text-align: left; width: 100%; }
    /* 绿色成功横幅（设计稿「图纸已生成！消耗 1 积分」） */
    .done-banner {
      display: flex; align-items: center; gap: 10px;
      background: var(--success-bg); border: 1px solid var(--success-border);
      border-radius: var(--radius-md); padding: 10px 14px;
      animation: pa-rise var(--motion-slow) var(--ease-exit);
    }
    .done-badge {
      width: 26px; height: 26px; flex: none;
      border-radius: var(--radius-full);
      background: #7DD3A0; color: #1F1D1A;
      display: inline-flex; align-items: center; justify-content: center;
    }
    @keyframes pa-rise {
      from { opacity: 0; transform: translateY(4px); }
      to { opacity: 1; transform: none; }
    }
    .gen-done-msg {
      font-size: var(--text-sm); font-weight: var(--weight-emphasis); color: var(--fg);
      line-height: 1.5;
    }
    .done-actions {
      display: flex; flex-wrap: wrap; gap: var(--space-2);
      margin-top: var(--space-5);
    }
    .done-actions .btn { flex: 1 1 132px; }
    /* 结果卡缩略图（A4）：先给一个「确实出图了」的实感；点它等同「打开图纸」 */
    .done-thumb {
      display: block;
      margin-top: var(--space-3);
      padding: var(--space-2);
      border-radius: var(--radius-lg);
      border: 1px solid var(--border-soft);
      background: #FFFFFF;
      min-width: 0;
      animation: pa-rise var(--motion-slow) var(--ease-exit);
    }
    .done-thumb img {
      display: block;
      width: 100%;
      max-height: 240px;
      object-fit: contain;
      border-radius: var(--radius-md);
      /* 像素图放大不要糊：最近生成 / 工作台里的缩略图同样受益 */
      image-rendering: pixelated;
    }
    /* 「合并相近色」的作用说明：把「不消耗积分」写在按钮外，按钮文案才能只讲动作 */
    .done-hint {
      margin: var(--space-2) 0 0;
      font-size: var(--text-xs);
      color: var(--muted);
      text-align: center;
    }
    .done-sub { margin: var(--space-3) 0 0; font-size: var(--text-xs); }
    .done-sub a { color: var(--teal-700); text-decoration: none; }
    .done-sub a:hover { text-decoration: underline; }

    /* ===== 最近生成（本地缩略图回看入口；图纸仅保存 72 小时） ===== */
    .recent { margin-top: var(--space-5); }
    /* 对齐头像页（成像）.history-title：轻量灰标题 + 行内「我的」引导链接 */
    .recent-title { margin: 0 0 var(--space-2); font-size: var(--text-sm); color: var(--muted); }
    .recent-link {
      margin-left: var(--space-1);
      font-size: var(--text-xs); font-weight: 510;
      color: var(--teal-700); text-decoration: none;
      white-space: nowrap;
    }
    .recent-link:hover { text-decoration: underline; }
    /* 对齐头像页 .history-strip：横向滑动（不换行），条本身必须能缩到父宽 */
    .recent-strip {
      display: flex; gap: var(--space-2);
      overflow-x: auto; padding-bottom: var(--space-1);
      min-width: 0;
      -webkit-overflow-scrolling: touch;
      scrollbar-width: thin;
    }
    .recent-item {
      width: 64px; height: 64px; padding: 0;
      border: 1px solid var(--border); border-radius: var(--radius-md);
      overflow: hidden; cursor: pointer; background: var(--bg);
      transition:
        transform var(--motion-fast) var(--ease-standard),
        box-shadow var(--motion-fast) var(--ease-standard),
        border-color var(--motion-fast) var(--ease-standard);
    }
    .recent-item:hover {
      transform: translateY(-2px);
      border-color: var(--amber-300);
      box-shadow: var(--card-hover-shadow);
    }
    .recent-item img { width: 100%; height: 100%; object-fit: cover; display: block; }

    /* ===== 提示与弹窗关闭钮 ===== */
    #studioMsg.warn, .hint.warn { color: var(--danger); }
    .btn-close-modal {
      border: none; background: #F2F3F6; color: var(--muted); cursor: pointer;
      border-radius: var(--radius-full);
      display: inline-flex; align-items: center; justify-content: center;
    }
    .btn-close-modal:hover { background: #E8EAEE; color: var(--fg); }

    /* ===== 响应式 ===== */
    @media (max-width: 899px) {
      .layout { grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }
      .page { padding-top: var(--space-5); }
      .hero h1 { font-size: var(--text-2xl); }
      .steps { margin-bottom: var(--space-5); }
    }
    @media (max-width: 640px) {
      :root { --container-gutter: 16px; }
      .btn.big { height: 44px; }
      .done-actions .btn { flex: 1 1 100%; }
    }

    /* ===== 生图通道提示点（左下角） =====
       腾讯=灰蓝，自研=琥珀。7px 圆点、半透明、无文字：只给知道的人看，
       不抢版面也不参与布局（position: fixed，不进文档流，窄屏不会撑宽）。 */
    .ch-dot {
      position: fixed;
      left: 12px;
      bottom: calc(12px + env(safe-area-inset-bottom, 0px));
      width: 8px;
      height: 8px;
      border-radius: 50%;
      background: #8aa1bb;              /* 默认腾讯；data-ch="self" 时由 JS 换成琥珀 */
      opacity: .55;                      /* 1x 屏幕上「一眼能找到、但不会注意」的档位 */
      box-shadow: 0 0 0 1px rgba(255, 255, 255, .85);
      z-index: 45;                      /* 低于弹窗(50)、高于内容 */
      cursor: default;
      transition: opacity .2s ease, transform .2s ease;
    }
    .ch-dot:hover { opacity: .95; transform: scale(1.25); }
    .ch-dot[data-ch="self"] { box-shadow: 0 0 0 1px rgba(255, 255, 255, .85), 0 0 0 3px rgba(217, 149, 60, .18); }
    @media (prefers-reduced-motion: reduce) {
      .ch-dot { transition: none; }
      .ch-dot:hover { transform: none; }
    }

    /* ===== C3 · 回访提示（「刚才那张图纸好了」） =====
       只在「关页 → 出图 → 重开」命中时出现一次：不打断当前操作，8 秒自收，
       点一下就进图纸页。DOM 由 app.js 注入（页面上不多一块固定结构）。 */
    .pa-toast {
      position: fixed;
      left: 50%;
      bottom: calc(20px + env(safe-area-inset-bottom, 0px));
      transform: translateX(-50%);
      display: flex; align-items: center; gap: 12px;
      max-width: min(92vw, 420px);
      padding: 10px 12px 10px 14px;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius-full);
      box-shadow: var(--shadow-lg);
      z-index: 46;                     /* 高于通道点(45)、低于弹窗(50) */
      animation: pa-toast-in var(--motion-slow) var(--ease-exit);
      font-size: var(--text-sm); color: var(--fg);
      line-height: 1.4;
    }
    .pa-toast-msg { flex: 1 1 auto; min-width: 0; }
    .pa-toast-act {
      flex: none;
      border: 0; cursor: pointer;
      background: var(--amber-500); color: #1F1D1A;
      font-weight: 600; font-size: var(--text-sm);
      padding: 6px 12px; border-radius: var(--radius-full);
    }
    .pa-toast-act:active { filter: brightness(.95); }
    .pa-toast-x {
      flex: none; border: 0; background: none; cursor: pointer;
      color: var(--meta); font-size: 16px; line-height: 1;
      padding: 2px 4px;
    }
    @keyframes pa-toast-in {
      from { opacity: 0; transform: translate(-50%, 10px); }
      to { opacity: 1; transform: translate(-50%, 0); }
    }
    @media (prefers-reduced-motion: reduce) {
      .pa-toast { animation: none; }
    }

    /* ===== UI 打磨 · 批 A（2026-11-10）=====
       设计评审稿里「换皮不动骨架」的部分，只改颜色/圆角/阴影/字重，不动栅格与断点。
       刻意没收的条目（hero 字号、右栏 sticky、空态 ①②③ 引导、画风卡尺寸、
       上传区边框变淡、福利条分界）都在批 B 候选版里单独验，理由见 commit。
       所有颜色走 base.css 的 token；品牌黄 #FFD02F 与黑底投影是设计语言本体，直接写。 */

    /* 1. 面板标题：图标进黄底圆角块（原为灰色线性图标，层级太扁） */
    .panel-title .icon {
      width: 18px; height: 18px; padding: 7px;
      box-sizing: content-box;
      border-radius: 8px;
      background: var(--amber-100);
      color: var(--amber-700);
    }

    /* 2. 上传区：大圆角 + 悬停给「可点」的反馈（边框色不动：
          #7A7A7A 对白底 4.4:1，是 3:1 底线内唯一提示可拖拽的线索） */
    .upload-zone {
      border-radius: var(--radius-xl);
      transition:
        border-color var(--motion-base) var(--ease-standard),
        background-color var(--motion-base) var(--ease-standard),
        box-shadow var(--motion-base) var(--ease-standard);
    }
    .upload-zone:hover {
      border-color: var(--amber-600);
      box-shadow: 0 4px 18px rgba(240, 187, 0, 0.12);
    }
    .upload-empty .icon {
      width: 22px; height: 22px; padding: 13px;
      box-sizing: content-box;
      border-radius: var(--radius-full);
      background: var(--amber-100);
      color: var(--amber-700);
      transition: transform var(--motion-base) var(--ease-standard);
    }
    .upload-zone:hover .upload-empty .icon { transform: translateY(-3px) scale(1.05); }
    .upload-main { font-size: 15px; }

    /* 3. 画风卡：圆角 + 悬停抬起 + 选中态黄色光晕（尺寸/字号不动，等真图验完再定） */
    .style-card { border-radius: 14px; }
    .style-card:hover {
      transform: translateY(-3px);
      box-shadow: 0 8px 20px rgba(31, 29, 26, 0.10);
    }
    .style-card.cur {
      box-shadow: 0 0 0 1.5px #FFD02F, 0 6px 16px rgba(240, 187, 0, 0.22);
    }

    /* 4. 主按钮：44 → 50px。圆角 10 → 14px 与卡片同语言（实测线上是 10px，
       不是胶囊：胶囊只给顶栏的 small pill 用） */
    .btn.primary.big {
      height: 50px;
      border-radius: 14px;
      font-size: 16px;
      font-weight: 600;
      letter-spacing: 0.01em;
      transition:
        transform var(--motion-fast) var(--ease-standard),
        box-shadow var(--motion-fast) var(--ease-standard),
        background-color var(--motion-fast) var(--ease-standard);
    }
    .btn.primary.big:hover { transform: translateY(-1px); box-shadow: 0 8px 22px rgba(31, 29, 26, 0.28); }
    .btn.primary.big:active { transform: none; box-shadow: none; }
    .cost-tag { padding: 2px 10px; }

    /* 5. 两个 <details>（高级参数 / 继续改图）：统一浅底圆角。
       它们的 margin/padding/border 是写在 index.html 的内联 style 上的，
       内联优先级高于任何选择器，所以这里必须 !important；
       哪天把那几个内联样式搬进 CSS，这里的 !important 就能全删。 */
    #perlerAdvanced,
    #editPanel {
      background: var(--ink-50) !important;
      border-color: var(--border-soft) !important;
      border-radius: 14px !important;
      padding: 10px 14px !important;
    }
    #perlerAdvanced[open],
    #editPanel[open] { background: var(--bg) !important; }
    #perlerAdvanced summary,
    #editPanel summary { padding: 3px 0; user-select: none; }
    #perlerAdvanced summary:hover,
    #editPanel summary:hover { color: var(--fg); }

    /* 6. 最近生成 / 结果卡 */
    .recent-item { border-radius: 12px; }
    .recent-item:hover { transform: translateY(-3px) scale(1.03); }
    .done-banner { border-radius: 12px; }
    .done-thumb {
      border-radius: 14px;
      transition: box-shadow var(--motion-base) var(--ease-standard);
    }
    .done-thumb:hover { box-shadow: 0 8px 24px rgba(31, 29, 26, 0.12); }

    /* 7. 页脚：加一条分隔线，正文到此为止更像一页 */
    .footer {
      margin-top: var(--space-12);
      padding-top: var(--space-5);
      border-top: 1px solid var(--border-soft);
    }

    /* 8. 表单 */
    .text-input { border-radius: 12px; }

/* ===== UI 打磨 · 批 B（2026-11-10）候选 =====
   与批 A 的差别：这些会动字号/尺寸/定位，逐条都在真站上量过再收。
   批 A 已上线（800e0a8），这里只放增量。 */

/* B1. Hero：桌面放大，但不动窄屏既有层级。
   线上 h1 = clamp(34,4.5vw,48)，≤899 走 --text-2xl(28)。
   设计稿一条 clamp(38,5vw,54) 会把 ≤899 也顶到 38（+36%），压过步骤条。 */
@media (min-width: 900px) {
  .hero h1 { font-size: clamp(40px, 3.6vw, 52px); letter-spacing: 0.01em; }
  .hero p { font-size: 15px; margin-top: 10px; }
}
@media (min-width: 641px) and (max-width: 899px) {
  .hero h1 { font-size: 32px; }
}

/* B2. 拼豆点阵：纯伪元素、不进 DOM，不占文档流。
   ≤720 隐藏（那时标题已贴到边，装饰会压字）；不透明度压到 .8，别抢标题。 */
.hero { position: relative; }
.hero::before,
.hero::after {
  content: '';
  position: absolute;
  top: 24px;
  width: 86px;
  height: 58px;
  pointer-events: none;
  opacity: 0.8;
  background-repeat: no-repeat;
  background-image:
    radial-gradient(circle 5px, #FFD02F 4px, transparent 5px),
    radial-gradient(circle 4px, #1F1D1A 3px, transparent 4px),
    radial-gradient(circle 6px, #FFE066 5px, transparent 6px),
    radial-gradient(circle 4px, #FFD02F 3px, transparent 4px);
  background-size: 22px 22px, 30px 30px, 26px 26px, 20px 20px;
  background-position: 0 6px, 18px 0, 40px 22px, 66px 10px;
}
.hero::before { left: calc(50% - 300px); transform: rotate(-8deg); }
.hero::after { right: calc(50% - 300px); transform: rotate(10deg) scale(0.9); }
@media (max-width: 720px) {
  .hero::before, .hero::after { display: none; }
}

/* B3. 右栏空态：图标进黄圈 + 正文加重。
   设计稿的 ①②③ 引导没要——`.steps` 步骤条就在左栏上方，两处还各写一套措辞，
   桌面相隔不到 60px；这里只留一句主文案，把「空」的感觉交给图标块和留白。 */
.result-empty .icon {
  width: 22px; height: 22px; padding: 14px;
  box-sizing: content-box;
  border-radius: var(--radius-full);
  background: var(--amber-100);
  color: var(--amber-700);
  margin: 0 auto var(--space-3);
}
.result-empty p { font-size: 15px; font-weight: 500; color: var(--fg-2); }
@media (min-width: 900px) {
  .result-stage { min-height: 380px; }
}

/* B4. 右栏 sticky。
   线上实测：顶栏 60px；游客态 platform.js 把 49px 福利条塞进同一个 sticky
   header 内部 → 109px。设计稿写死 top:76 会让面板标题压在绿条下面 33px。
   另外面板比视口高时（出图后挂着整张图纸）钉住就再也看不到下半截，
   所以同时给 max-height + 内部滚动，保证内容永远够得着。
   :has 不被支持时退回 68px（只多 8px 间隙，不会压字）。 */
@media (min-width: 900px) {
  .result-panel {
    position: sticky;
    top: 68px;
    max-height: calc(100vh - 76px);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .topbar:has(#pfNewUserHint:not([hidden])) ~ .page .result-panel {
    top: 117px;
    max-height: calc(100vh - 125px);
  }
}

/* B5. 画风卡：比例收紧（92 → 84），名字行字号 12 → 13。
   真图 260×260 走 object-fit: cover，只多裁 9% 高度，不变形。
   ⚠️ 必须限定 ≥641px：390 宽时网格内容宽只有 308px，
   gap 12 时 3 列要 312 放不下 → 2 列 148px；gap 10 刚好 308 → 翻成 3 列 96px，
   手机上图会缩掉三分之一。这条只有拿真图量才看得见，色块占位是看不出来的。 */
@media (min-width: 641px) {
  .style-grid { gap: 10px; }
  .card-art { height: 84px; }
  .card-name { font-size: 13px; padding: 7px 8px; }
}

/* B6. 顶栏毛玻璃。.86 时上方那片黄圈图标会在玻璃里洇成一片暖雾（局部放大对比过），
   所以取 .94 + blur 12：仍有「不是纯白硬边」的层次，又不会把彩色元素洇上来。 */
.topbar {
  background: rgba(255, 255, 255, 0.94);
  -webkit-backdrop-filter: saturate(1.4) blur(12px);
  backdrop-filter: saturate(1.4) blur(12px);
}

/* C1. 结果卡「打开图纸」改成链接（<a target="_blank">）：新标签打开图纸页，
   工作台留在原标签。全局 a 有下划线，这里去掉；视觉仍完全由 .btn.primary 决定。 */
.done-actions a.btn { text-decoration: none; }
