/* ============================================================
 * PC 样式（>= 1024px 才是完整版式；768~1023 只换顶栏配色）
 * ============================================================
 * 设计目标：**真横版 PC 站**，不是「把手机版拉宽」。
 *
 *   ┌──────────────────────────────────────────────────────────┐
 *   │ 顶栏 64px：白底、品牌/返回、页面标题（tabbar 从底部搬上来）│
 *   ├────────────┬──────────────────────────┬──────────────────┤
 *   │ 左栏 272   │ 中间画布 1fr             │ 右栏 344         │
 *   │ 口号卡     │  上传投放区（虚线画布）   │ 已选规格          │
 *   │ 规格列表   │                          │ 底色 / 拍摄指南   │
 *   └────────────┴──────────────────────────┴──────────────────┘
 *
 * 🔴 三条铁律（改这个文件前必读）
 *  1. **一行 DOM、一行 JS 都不许改**。全部靠 CSS 把现有块重新摆放，
 *     事件绑定原样不动 ⇒ 功能不可能丢（用户明确要求「能力必须跟小程序一致」）。
 *     `*.html` 是 `_gen_page.py` 生成的，手改会被覆盖，所以只能走 CSS。
 *  2. **每条规则都要比 `p-*.css` 更具体**。加载顺序是
 *     web.css → app.css → pc.css → p-<页面>.css（见 _gen_page.py 的 HEAD），
 *     `p-*.css` **排在 pc.css 后面** ⇒ 同权重时它赢。所以这里一律用
 *     `.page:has(.指纹) ...`（0,2,0 起）压过 `p-*.css` 的 `.xxx`（0,1,0）。
 *     直接写 `.page { ... }` 是压不过 `p-xxx.css` 的 `.page{padding:...}` 的。
 *  3. **用 `:has(指纹)` 分页**。`.page` 是 17 页共用容器，不加限定就会串页。
 *     每页的指纹类见下面各段标题。
 *
 * 断点：<768 手机版 / 768~1023 居中窄站（只换顶栏配色）/ >=1024 完整 PC 版式。
 * ============================================================ */

/* ============================================================
 * 一、顶栏（768 起就换：手机版那条蓝通栏在 PC 上像「没做完」
 * ============================================================ */
@media (min-width: 768px) {
  /* 蓝底白字 → 白底深字。sticky 保持不变（此时 body 还是 750px 居中容器，
     navbar 跟着容器走才是对的；>=1024 才改成 fixed 通栏） */
  .navbar {
    background: #fff;
    color: #1c2333;
    border-bottom: 1px solid #e6eaf2;
    box-shadow: 0 1px 4px rgba(28, 35, 51, 0.05);
  }
  .navbar-title { font-weight: 600; }
  /* 返回键：手机版是「‹」大字符，PC 上做成圆角小按钮 */
  .navbar-back {
    width: 34px;
    height: 34px;
    margin-left: 0;
    border-radius: 9px;
    background: #f4f6fb;
    font-size: 20px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #5c6780;
  }
  .navbar-back:hover { background: #e9eefb; color: #3d6deb; }
}

@media (min-width: 1024px) {

  /* ============================================================
   * 二、全局外壳
   * ============================================================ */

  /* 🔴 必须放开 body 的 750px 限宽
     `web.css` 在 >=768 段写了 `body{max-width:var(--app-w)}`（=750px 居中手机版）。
     这里是横版站点，容器要占满视口 ⇒ 不覆盖的话网格可用宽度只有 750-56=694px，
     减掉左右两栏 272+344 和间距 40 ⇒ 中间列被压成 **38px**（实测过）。 */
  body { max-width: none; box-shadow: none; background: #f5f7fb; }

  /* 顶栏通栏固定（首页是 tabbar 当顶栏，其他页是 navbar，两者同一套视觉） */
  .navbar {
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 64px;
    padding: 0 28px;
    display: flex;
    align-items: center;
    gap: 12px;
    z-index: 90;
    box-sizing: border-box;
  }
  .navbar-title {
    flex: 0 1 auto;
    text-align: left;
    font-size: 15px;
    letter-spacing: 0.2px;
  }
  /* 右上角品牌（伪元素：纯装饰，不占 flex 空间、不可点） */
  .navbar::after {
    content: '快照派';
    margin-left: auto;
    font-size: 13px;
    letter-spacing: 0.5px;
    color: #98a1b3;
  }

  /* 内容容器：除首页外的 13 页统一这个骨架 */
  .page:not(:has(.color-row)) {
    max-width: 1560px;
    margin: 0 auto;
    padding: 88px 28px 48px;      /* 顶 88 = 顶栏 64 + 间距 24 */
    box-sizing: border-box;
    min-height: 100vh;
  }

  /* 制作结果 / 工具执行 / 制作中：小程序里这三页是**全屏页、没有导航栏**，
     所以 mini.js 不会生成 `.navbar`，`#navbarHost` 是空的 ⇒ PC 上顶部会秃一块，
     跟其他页的白顶栏对不上。这里把空的 host 自己变成顶栏（纯装饰，只放品牌，
     不放假标题）。⚠️ 不要写 `content:'制作结果'` 这类假标题：页面自己已经有
     `.head-name`，会重名两处。 */
  body:has(.page .preview-area) #navbarHost,
  body:has(.page .pick) #navbarHost,
  body:has(.page .making) #navbarHost {
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 64px;
    box-sizing: border-box;   /* 不加的话 64 + 1px 下边框 = 65，和其他页顶栏差 1px */
    background: #fff;
    border-bottom: 1px solid #e6eaf2;
    box-shadow: 0 1px 4px rgba(28, 35, 51, 0.05);
    z-index: 90;
  }
  body:has(.page .preview-area) #navbarHost::before,
  body:has(.page .pick) #navbarHost::before,
  body:has(.page .making) #navbarHost::before {
    content: '快照派';
    position: absolute;
    left: 28px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 16px;
    font-weight: 600;
    letter-spacing: 0.5px;
    color: #1c2333;
  }

  /* ============================================================
   * 三、首页三栏工作台（指纹：.color-row 底色选择，只有首页有）
   * ============================================================ */

  /* 首页已经用 tabbar 当顶部导航了，小程序的 .navbar（「制作」标题条）
     再显示就是**两条导航叠着**，而且白占 44px ⇒ 首页 PC 上藏掉它。 */
  body:has(.page .color-row) .navbar { display: none; }

  /* tabbar：底部 → 顶部横排 */
  .web-tabbar {
    position: fixed;
    top: 0; bottom: auto;
    left: 0; right: 0;
    height: 64px;
    max-width: none;
    margin: 0;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 0 24px;
    box-sizing: border-box;
    border-top: 0;
    border-bottom: 1px solid #e6eaf2;
    background: rgba(255, 255, 255, 0.94);
    box-shadow: 0 1px 4px rgba(28, 35, 51, 0.05);
    backdrop-filter: saturate(180%) blur(8px);
  }
  .web-tabbar .tab {
    flex: 0 0 auto;
    flex-direction: row;
    gap: 7px;
    height: 40px;
    padding: 0 18px;
    border-radius: 10px;
    transition: background 0.15s;
  }
  .web-tabbar .tab:hover { background: #f2f6fe; }
  .web-tabbar .tab--on { background: #eaf1ff; }
  .web-tabbar .tab-ico { width: 19px; height: 19px; margin-bottom: 0; }
  .web-tabbar .tab-txt { font-size: 14px; line-height: 1; }
  .web-tabbar::before {
    content: '快照派';
    position: absolute;
    left: 28px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 16px;
    font-weight: 600;
    letter-spacing: 0.5px;
    color: #1c2333;
  }

  /* 首页网格。
     🔴 `height:100vh` + 行 3 用 `minmax(0,1fr)`：这样它是**真工作台**（画布吃满
        剩余高度、规格列表在栏内滚动），而不是「内容有多长页面就滚多长」。
        配 `overflow-y:auto` 兜底：视口特别矮时（<640）自动行撑不下还能滚，不裁内容。 */
  .page:has(.color-row) {
    display: grid;
    grid-template-columns: 272px minmax(0, 1fr) 344px;
    grid-template-rows: auto auto minmax(0, 1fr) auto;
    gap: 16px 20px;
    max-width: 1560px;
    margin: 0 auto;
    height: 100vh;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 88px 28px 24px;
    box-sizing: border-box;
  }

  /* 左栏顶：口号卡 */
  .page:has(.color-row) .hero {
    grid-column: 1; grid-row: 1;
    border-radius: 14px;
    padding: 18px 18px 20px;
    background: linear-gradient(150deg, #3d6deb 0%, #5a8df5 100%);
  }
  .page:has(.color-row) .hero-title { font-size: 16px; font-weight: 700; letter-spacing: 0; line-height: 1.5; }
  .page:has(.color-row) .hero-sub { margin-top: 8px; font-size: 11.5px; opacity: 0.88; line-height: 1.5; }

  /* 中栏顶：运营 banner */
  .page:has(.color-row) .banner {
    grid-column: 2; grid-row: 1;
    height: 86px;
    margin: 0;
    border-radius: 14px;
    box-shadow: none;
  }
  .page:has(.color-row) .banner-item { height: 86px; padding: 0 26px; }
  .page:has(.color-row) .banner-title { font-size: 16px; }
  .page:has(.color-row) .banner-sub { font-size: 12px; margin-top: 4px; }

  /* 右栏顶：当前选择（原来是 fixed 浮层，PC 改成卡片） */
  .page:has(.color-row) .current-tip {
    grid-column: 3; grid-row: 1;
    position: static;
    left: auto; right: auto; bottom: auto;
    max-width: none;
    margin: 0;
    background: #fff;
    border: 1px solid #e8edf6;
    border-radius: 14px;
    padding: 14px 16px;
    text-align: left;
    font-size: 13px;
    line-height: 1.5;
    color: #5c6780;
  }
  /* 「已选规格」前缀用伪元素，避免动 DOM。
     ⚠️ 不能写「当前选择」：DOM 里的正文本身就是「当前选择：一寸 · 25×35mm · 蓝底」，
        再加同名标题会重复两遍（实测截图里就是重了两行）。 */
  .page:has(.color-row) .current-tip::before {
    content: '已选规格';
    display: block;
    margin-bottom: 6px;
    font-size: 11px;
    letter-spacing: 1px;
    color: #98a1b3;
  }

  /* 两个 section-title 分别归位：`:has(+ …)` 精确区分（同名的有两个） */
  .page:has(.color-row) .section-title { margin: 0; font-size: 13px; font-weight: 600; color: #1c2333; padding: 0 2px; }
  .page:has(.color-row) .section-title:has(+ .spec-grid) { grid-column: 1; grid-row: 2; }
  .page:has(.color-row) .section-title:has(+ .color-row) { grid-column: 3; grid-row: 2; }
  .page:has(.color-row) .more { font-size: 12px; font-weight: 400; }

  /* 左栏：规格列表（一列滚动，带尺寸） */
  .page:has(.color-row) .spec-grid {
    grid-column: 1; grid-row: 3;
    padding: 0 2px 0 0;
    overflow-y: auto;
    overflow-x: hidden;
    min-height: 0;
    scrollbar-width: thin;
    scrollbar-color: #cbd5e6 transparent;
  }
  .page:has(.color-row) .spec-row { display: block; }
  .page:has(.color-row) .spec-card {
    width: 100%;
    margin: 0 0 8px;
    padding: 11px 14px;
    display: flex;
    align-items: baseline;
    gap: 8px;
    text-align: left;
    background: #fff;
    border: 1px solid #e8edf6;
    border-radius: 10px;
    box-shadow: none;
    box-sizing: border-box;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
  }
  .page:has(.color-row) .spec-card:hover { border-color: #b9cdf2; background: #fafcff; }
  .page:has(.color-row) .spec-card--active { border-color: #3d6deb; background: #f0f5ff; }
  .page:has(.color-row) .spec-name { font-size: 13.5px; font-weight: 500; flex: 1; }
  .page:has(.color-row) .spec-mm { margin: 0; font-size: 11.5px; color: #8a94a8; flex: 0 0 auto; }
  .page:has(.color-row) .spec-hot {
    position: static;
    order: -1;
    flex: 0 0 auto;
    padding: 1px 5px;
    border-radius: 4px;
    font-size: 10px;
    line-height: 1.6;
  }
  .page:has(.color-row) .spec-check {
    position: static;
    flex: 0 0 auto;
    width: 17px; height: 17px;
    line-height: 17px;
    font-size: 11px;
  }

  /* 左栏底：工具入口（横排两个小卡）
     align-self:start 必须加：默认 stretch 会被第 4 行（由右侧拍摄指南撑到 200px）
     拉成两个 200px 高的大方块（实测过）。 */
  .page:has(.color-row) .quick-row {
    grid-column: 1; grid-row: 4;
    margin: 0;
    padding: 0;
    gap: 10px;
    align-self: start;
  }
  .page:has(.color-row) .quick-card {
    flex: 1;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    padding: 11px 12px;
    border: 1px solid #e8edf6;
    border-radius: 10px;
    box-shadow: none;
  }
  .page:has(.color-row) .quick-card:hover { border-color: #b9cdf2; background: #fafcff; }
  .page:has(.color-row) .quick-ico { width: 20px; height: 20px; flex: 0 0 auto; }
  .page:has(.color-row) .quick-name { font-size: 12.5px; font-weight: 500; margin: 0; }
  .page:has(.color-row) .quick-desc { display: none; }

  /* ── 中间画布：把 .footer 从「底部按钮条」变成「上传投放区」 ──
     按钮还是那两个、事件还是 onChoose，只是从横排条变成大卡片居中。
     这样「上传能力」一点没变，视觉上就是 PC 版的投放画布。 */
  .page:has(.color-row) .footer {
    grid-column: 2; grid-row: 2 / 5;
    position: static;
    left: auto; right: auto; bottom: auto;
    max-width: none;
    margin: 0;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    min-height: 380px;
    padding: 36px;
    background: radial-gradient(circle at 50% 38%, #f5f9ff 0%, #fbfcff 62%);
    border: 2px dashed #ccd9f2;
    border-radius: 18px;
    box-shadow: none;
  }
  /* 画布中央图标（伪元素，纯装饰；图标是内联 SVG，和 app.css 里 .ico-* 同一套做法） */
  .page:has(.color-row) .footer::before {
    content: '';
    order: -3;
    flex: 0 0 auto;
    width: 68px;
    height: 68px;
    border-radius: 50%;
    background: #eef4ff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%233D6DEB' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z'/%3E%3Ccircle cx='12' cy='13' r='4'/%3E%3C/svg%3E") center / 32px no-repeat;
  }
  .page:has(.color-row) .footer::after {
    content: '上传照片后选择规格与底色，也可先选规格再上传';
    order: 0;
    margin-top: 2px;
    font-size: 12px;
    color: #98a1b3;
  }
  /* 🔴 flex:0 0 auto 必须写：app.css 里 .footer .btn 是 `flex:1 1 0%`（手机上并排各半），
     到 PC 竖排时两个按钮会把画布高度**平分**，各撑成 283px 高的大方块
     （实测：rect 高 283，看着像两个巨型色块，完全不是按钮）。 */
  .page:has(.color-row) .footer .btn {
    flex: 0 0 auto;
    width: 100%;
    max-width: 300px;
    height: 46px;
    line-height: 46px;
    padding: 0 16px;
    font-size: 14.5px;
    border-radius: 10px;
    box-sizing: border-box;
  }
  .page:has(.color-row) .footer .btn--primary {
    order: -2;           /* 主按钮紧跟图标（手机版是右），PC 竖排时更符合视线流 */
    box-shadow: 0 6px 16px rgba(61, 109, 235, 0.24);
  }
  /* 次按钮（相册选择）在浅色画布上原本几乎看不见（白底白边），补边框和字色 */
  .page:has(.color-row) .footer .btn--ghost {
    order: -1;
    background: #fff;
    border: 1px solid #d3e0f7;
    color: #3d6deb;
    box-shadow: 0 2px 8px rgba(28, 35, 51, 0.04);
  }

  /* 🔴 PC 端没有拍摄功能（用户 2026-10-21 拍板：「电脑端就不需要拍摄功能了，
     那是手机端的功能」）。
     原因不只是「没意义」：桌面浏览器里 `capture` 属性无效，点「开始拍摄」走的
     还是同一个文件选择框，和「相册选择」100% 等价 ⇒ 两个按钮并排会让人以为
     电脑能开摄像头，点了发现是选文件，体验反而差。PC 下只留一个「上传照片」。
     手机端（<1024px）不受影响，两个按钮原样保留。 */
  .page:has(.color-row) .footer [data-source="camera"] { display: none; }

  .page:has(.color-row) .footer [data-source="album"] {
    order: -2;                        /* 唯一的按钮，紧跟画布图标 */
    background: linear-gradient(135deg, #4d7ef0, #3d6deb);
    border: 0;
    color: #fff;
    font-size: 0;                     /* 藏掉「相册选择」四个字，PC 上叫「上传照片」 */
    box-shadow: 0 6px 16px rgba(61, 109, 235, 0.24);
  }
  .page:has(.color-row) .footer [data-source="album"]::after {
    /* web.css 全局 `button.btn::after {display:none !important}` 原本会把这个
       PC 文案一并隐藏，造成「只有蓝色空按钮」；本条选择器更具体，显式恢复。 */
    display: inline !important;
    content: '上传照片';
    font-size: 14.5px;
    letter-spacing: 0.5px;
  }

  /* 右栏：底色 */
  .page:has(.color-row) .color-row {
    grid-column: 3; grid-row: 3;
    background: #fff;
    border: 1px solid #e8edf6;
    border-radius: 14px;
    padding: 12px 10px 14px;
    align-content: flex-start;
    align-self: start;      /* 不跟着 1fr 行拉满高度（否则 6 个色点上方留一大片空白） */
  }
  .page:has(.color-row) .color-item { width: 33.33%; padding: 8px 0; }
  .page:has(.color-row) .color-dot { width: 40px; height: 40px; }
  .page:has(.color-row) .color-check { font-size: 18px; }
  .page:has(.color-row) .color-name { margin-top: 6px; font-size: 11.5px; }

  /* 右栏底：拍摄指南 */
  .page:has(.color-row) .guide {
    grid-column: 3; grid-row: 4;
    margin: 0;
    padding: 14px 16px;
    border: 1px solid #e8edf6;
    border-radius: 14px;
    box-shadow: none;
    background: #fff;
  }
  .page:has(.color-row) .guide-title { font-size: 13px; font-weight: 600; margin-bottom: 8px; }
  .page:has(.color-row) .guide-item { font-size: 12px; line-height: 1.75; }
  .page:has(.color-row) .guide-tip { margin-top: 8px; padding: 8px 10px; font-size: 11.5px; line-height: 1.6; border-radius: 8px; }

  /* ============================================================
   * 四、规格大全（指纹：.cats 分类条）
   * ------------------------------------------------------------
   * 手机版：搜索条 → 横滑分类 → 通栏长列表（一行一个）。
   * PC 版：左边竖排分类导航（240），右边卡片网格（3 列）。
   *
   * 🔴 `.cats` 要跨过所有分组行 ⇒ `grid-row: 2 / span 200`。
   *    分组是**兄弟节点**（没有共同父容器），没法用 flex 分栏，
   *    只能靠 grid 显式占位。多出来的隐式行高度为 0，不影响排版。
   * ============================================================ */
  .page:has(.cats) {
    display: grid;
    grid-template-columns: 236px minmax(0, 1fr);
    gap: 12px 24px;
    align-content: start;
  }
  .page:has(.cats) .search {
    grid-column: 1 / -1;
    grid-row: 1;
    padding: 0;
    max-width: 620px;
  }
  .page:has(.cats) .search-box {
    border: 1px solid #e3e9f4;
    border-radius: 10px;
    padding: 11px 14px;
    box-shadow: none;
    background: #fff;
  }
  .page:has(.cats) .search-box:focus-within { border-color: #3d6deb; box-shadow: 0 0 0 3px rgba(61, 109, 235, 0.12); }
  .page:has(.cats) .search-ico { width: 16px; height: 16px; margin-right: 8px; }
  .page:has(.cats) .search-input { font-size: 13.5px; outline: none; border: 0; background: transparent; }
  .page:has(.cats) .search-clear { font-size: 13px; cursor: pointer; }

  /* 左栏分类：横滑条 → 竖排导航 */
  .page:has(.cats) .cats {
    grid-column: 1;
    grid-row: 2 / span 200;
    white-space: normal;
    padding: 10px;
    background: #fff;
    border: 1px solid #e8edf6;
    border-radius: 14px;
    align-self: start;
    overflow: visible;
  }
  .page:has(.cats) .cat {
    display: block;
    margin: 0 0 2px;
    padding: 9px 12px;
    border-radius: 8px;
    background: transparent;
    font-size: 13px;
    color: #5c6780;
    cursor: pointer;
  }
  .page:has(.cats) .cat:hover { background: #f4f7fe; color: #3d6deb; }
  .page:has(.cats) .cat--active { background: #eaf1ff; color: #3d6deb; font-weight: 600; }

  /* 右栏：分组标题 + 3 列卡片 */
  .page:has(.cats) .group-title {
    grid-column: 2;
    margin: 10px 0 12px;
    font-size: 15px;
    font-weight: 700;
  }
  .page:has(.cats) .spec-list {
    grid-column: 2;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 10px;
  }
  .page:has(.cats) .spec-row {
    margin: 0;
    padding: 14px 16px;
    border: 1px solid #e8edf6;
    border-radius: 10px;
    box-shadow: none;
    background: #fff;
    cursor: pointer;
    transition: border-color 0.15s, box-shadow 0.15s;
  }
  .page:has(.cats) .spec-row:hover {
    border-color: #b9cdf2;
    box-shadow: 0 4px 14px rgba(61, 109, 235, 0.08);
  }
  .page:has(.cats) .spec-name { font-size: 14px; }
  .page:has(.cats) .spec-sub { font-size: 11.5px; margin-top: 4px; }
  .page:has(.cats) .spec-kb { font-size: 11px; margin-top: 4px; }
  .page:has(.cats) .spec-go { font-size: 12px; opacity: 0; transition: opacity 0.15s; }
  .page:has(.cats) .spec-row:hover .spec-go { opacity: 1; }
  .page:has(.cats) .empty { grid-column: 2; }
  .page:has(.cats) .tip { grid-column: 2; margin: 18px 0 0; font-size: 12px; text-align: left; }

  /* ============================================================
   * 五、制作结果（指纹：.preview-area 预览区）
   * ------------------------------------------------------------
   * 左：预览画布（吃满高度，图按比例居中）
   * 右：规格名 → 三个操作 → 提示 → 底部两按钮
   * ============================================================ */
  .page:has(.preview-area) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 360px;
    grid-template-rows: auto auto 1fr auto;
    gap: 14px 24px;
    align-content: start;
  }
  .page:has(.preview-area) .head { grid-column: 2; grid-row: 1; padding: 0; }
  .page:has(.preview-area) .head-name { font-size: 20px; }
  .page:has(.preview-area) .head-meta { font-size: 12.5px; margin-top: 4px; }
  .page:has(.preview-area) .head-vip { margin-top: 8px; font-size: 11.5px; padding: 3px 10px; }

  /* 预览画布：白卡 + 图按比例居中（不拉变形） */
  .page:has(.preview-area) .preview-area {
    grid-column: 1;
    grid-row: 1 / 5;
    margin: 0;
    padding: 28px;
    background: #fff;
    border: 1px solid #e8edf6;
    border-radius: 16px;
    box-sizing: border-box;
    justify-content: center;
    min-height: 460px;
  }
  /* 🔴 手机版 .preview-img 是 width:100%（按容器宽撑满）；
     PC 上容器有 700+ 宽 ⇒ 证件照会被拉成一面墙。
     改 max-width/max-height 双向夹，图自己按比例缩放。 */
  .page:has(.preview-area) .preview-img {
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: calc(100vh - 260px);
    border-radius: 12px;
    box-shadow: 0 10px 34px rgba(61, 109, 235, 0.14);
  }
  .page:has(.preview-area) .preview-loading { font-size: 13px; padding: 120px 0; }
  .page:has(.preview-area) .wm-tip { margin-top: 14px; font-size: 11.5px; }

  /* 右栏操作：横排三块 → 竖排三行 */
  .page:has(.preview-area) .actions {
    grid-column: 2;
    grid-row: 2;
    flex-direction: column;
    gap: 8px;
    margin: 0;
    padding: 8px;
    background: #fff;
    border: 1px solid #e8edf6;
    border-radius: 14px;
  }
  .page:has(.preview-area) .act {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 12px;
    border-radius: 9px;
    box-shadow: none;
    text-align: left;
    cursor: pointer;
    transition: background 0.15s;
  }
  .page:has(.preview-area) .act:hover { background: #f4f7fe; }
  .page:has(.preview-area) .act-ico { width: 20px; height: 20px; flex: 0 0 auto; }
  .page:has(.preview-area) .act-name { margin: 0; font-size: 13px; color: #1c2333; }
  .page:has(.preview-area) .free-tip { grid-column: 2; grid-row: 3; margin: 0; font-size: 11.5px; text-align: left; align-self: start; }

  /* 底部按钮条（fixed）→ 右栏底竖排 */
  .page:has(.preview-area) .footer {
    grid-column: 2;
    grid-row: 4;
    position: static;
    left: auto; right: auto; bottom: auto;
    max-width: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column-reverse;   /* 主按钮（保存电子照）在上，符合视线流 */
    gap: 8px;
    background: transparent;
    box-shadow: none;
    align-self: end;
  }
  .page:has(.preview-area) .footer .btn {
    flex: 0 0 auto;
    width: 100%;
    height: 44px;
    line-height: 44px;
    font-size: 14px;
    border-radius: 10px;
  }

  /* 底部弹层 → 居中模态（手机上从底部升起，PC 上从底部升起会很怪） */
  .page:has(.preview-area) .mask { align-items: center; justify-content: center; }
  .page:has(.preview-area) .sheet {
    width: 620px;
    max-width: calc(100vw - 64px);
    border-radius: 16px;
    padding: 26px 28px;
    box-shadow: 0 20px 60px rgba(15, 23, 42, 0.24);
  }
  .page:has(.preview-area) .sheet--lg { max-height: 78vh; }
  .page:has(.preview-area) .sheet-title { font-size: 17px; margin-bottom: 18px; }

  /* ============================================================
   * 六、冲印下单（指纹：.frow 表单行）
   * ------------------------------------------------------------
   * 左：表单卡；右：订单摘要 + 支付按钮（sticky 跟随）
   * ============================================================ */
  .page:has(.frow) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 360px;
    grid-template-rows: auto auto;
    gap: 16px 24px;
    align-content: start;
  }
  .page:has(.frow) .head { grid-column: 1; grid-row: 1; padding: 0 0 4px; }
  .page:has(.frow) .head-title { font-size: 22px; }
  .page:has(.frow) .head-sub { font-size: 12.5px; margin-top: 4px; }
  .page:has(.frow) .card {
    margin: 0;
    border: 1px solid #e8edf6;
    border-radius: 14px;
    box-shadow: none;
    padding: 22px 24px;
  }
  .page:has(.frow) .card.form { grid-column: 1; grid-row: 2; }
  .page:has(.frow) .card.info { grid-column: 2; grid-row: 1 / 3; align-self: start; position: sticky; top: 88px; }
  .page:has(.frow) .form-title { font-size: 14px; margin-bottom: 6px; }
  .page:has(.frow) .info-row { font-size: 13.5px; padding: 8px 0; }
  .page:has(.frow) .info-tip { font-size: 11.5px; }

  /* 表单项：手机版是「标签 + 裸输入框 + 一条下划线」，PC 上换成有边框的输入框
     （下划线样式在宽屏上看着像没做完的表单） */
  .page:has(.frow) .frow {
    border-bottom: 0;
    padding: 9px 0;
    gap: 12px;
  }
  .page:has(.frow) .flbl { width: 84px; font-size: 13px; flex: 0 0 auto; }
  .page:has(.frow) .finp {
    font-size: 13.5px;
    background: #f7f9fd;
    border: 1px solid #e8edf6;
    border-radius: 8px;
    padding: 10px 12px;
    box-sizing: border-box;
    outline: none;
  }
  .page:has(.frow) .finp:focus { border-color: #3d6deb; background: #fff; box-shadow: 0 0 0 3px rgba(61, 109, 235, 0.12); }
  .page:has(.frow) .finp--full { margin-top: 6px; }
  .page:has(.frow) .region-picker { display: flex; gap: 10px; flex: 1; }
  .page:has(.frow) .region-sel {
    flex: 1;
    min-width: 0;
    font-size: 13.5px;
    color: #1c2333;
    background: #f7f9fd;
    border: 1px solid #e8edf6;
    border-radius: 8px;
    padding: 10px 8px;
    outline: none;
    cursor: pointer;
  }
  .page:has(.frow) .region-sel:focus { border-color: #3d6deb; }

  /* 支付按钮：手机版是底部固定通栏 → PC 放到右侧摘要卡下方 */
  .page:has(.frow) .footer {
    grid-column: 2;
    grid-row: 3;
    position: static;
    left: auto; right: auto; bottom: auto;
    max-width: none;
    margin: 0;
    padding: 0;
    background: transparent;
    box-shadow: none;
    align-self: start;
  }
  .page:has(.frow) .footer .btn {
    width: 100%;
    height: 46px;
    line-height: 46px;
    font-size: 14.5px;
    border-radius: 10px;
    box-shadow: 0 6px 16px rgba(61, 109, 235, 0.22);
  }

  /* ============================================================
   * 七、我的（指纹：.ucard 用户卡）
   * ------------------------------------------------------------
   * 左：资料卡 + 资产三项；右：签到条 + 菜单
   * ============================================================ */
  .page:has(.ucard) {
    display: grid;
    grid-template-columns: 320px minmax(0, 1fr);
    grid-template-rows: auto auto auto;
    gap: 16px 24px;
    align-content: start;
    max-width: 1180px;
  }
  .page:has(.ucard) .ucard {
    grid-column: 1;
    grid-row: 1;
    border-radius: 14px;
    padding: 24px 22px;
    flex-direction: column;
    align-items: flex-start;
  }
  .page:has(.ucard) .avatar { width: 62px; height: 62px; border-width: 2px; }
  .page:has(.ucard) .uinfo { margin: 14px 0 0; }
  .page:has(.ucard) .uname { font-size: 17px; }
  .page:has(.ucard) .uvip { font-size: 11px; margin-top: 8px; padding: 2px 9px; }
  .page:has(.ucard) .unormal { font-size: 12px; margin-top: 8px; }
  /* 手机版靠负 margin 让资产条压住资料卡下沿；PC 上是两张并排卡，去掉负 margin */
  .page:has(.ucard) .assets {
    grid-column: 1;
    grid-row: 2;
    margin: 0;
    border: 1px solid #e8edf6;
    border-radius: 14px;
    box-shadow: none;
    padding: 16px 0;
    align-self: start;
  }
  .page:has(.ucard) .asset-num { font-size: 19px; }
  .page:has(.ucard) .asset-lbl { font-size: 11.5px; }
  .page:has(.ucard) .card.sign {
    grid-column: 2;
    grid-row: 1;
    margin: 0;
    border: 1px solid #e8edf6;
    border-radius: 14px;
    box-shadow: none;
    padding: 18px 20px;
    align-self: start;
  }
  .page:has(.ucard) .sign-title { font-size: 14px; }
  .page:has(.ucard) .sign-sub { font-size: 11.5px; }
  .page:has(.ucard) .menu {
    grid-column: 2;
    grid-row: 2;
    margin: 0;
    border: 1px solid #e8edf6;
    border-radius: 14px;
    box-shadow: none;
    align-self: start;
  }
  .page:has(.ucard) .mitem { padding: 15px 20px; cursor: pointer; }
  .page:has(.ucard) .mitem:hover { background: #fafcff; }
  .page:has(.ucard) .mtxt { font-size: 13.5px; }
  .page:has(.ucard) .mico { width: 26px; height: 20px; background-size: 18px 18px; }
  .page:has(.ucard) .marrow { font-size: 17px; }
  .page:has(.ucard) .foot { grid-column: 1 / -1; grid-row: 3; margin: 4px 0 0; font-size: 11.5px; }
  .page:has(.ucard) .kf-pop { width: 380px; border-radius: 16px; padding: 26px; }
  .page:has(.ucard) .kf-title { font-size: 16px; margin-bottom: 16px; }
  .page:has(.ucard) .kf-qr { width: 220px; height: 220px; }
  .page:has(.ucard) .kf-empty { width: 220px; min-height: 120px; font-size: 12px; }
  .page:has(.ucard) .kf-tip { font-size: 11.5px; }
  .page:has(.ucard) .kf-close { margin-top: 18px; height: 42px; line-height: 42px; font-size: 14px; border-radius: 10px; }

  /* ============================================================
   * 八、VIP（指纹：.plans 套餐区）
   * ============================================================ */
  .page:has(.plans) { max-width: 1120px; }
  .page:has(.plans) .hero {
    border-radius: 16px;
    padding: 30px 32px 34px;
  }
  .page:has(.plans) .hero-crown { width: 40px; height: 40px; }
  .page:has(.plans) .hero-title { font-size: 24px; }
  .page:has(.plans) .hero-sub { font-size: 13px; margin-top: 6px; }
  .page:has(.plans) .hero-vip,
  .page:has(.plans) .hero-quota { font-size: 11.5px; margin-top: 10px; padding: 3px 12px; }
  .page:has(.plans) .plans { padding: 22px 0 0; }
  .page:has(.plans) .group-tag { font-size: 11.5px; padding: 3px 11px; margin-bottom: 12px; }
  /* 手机版靠 flex + width:calc((100%-40)/3) 排三张；PC 上用 grid 更稳（不会因为
     容器宽度变化把第 3 张挤到下一行） */
  .page:has(.plans) .plan-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px;
  }
  .page:has(.plans) .plan {
    width: auto;
    border-radius: 14px;
    padding: 20px 18px;
    border: 1px solid #f3e3c6;
    box-shadow: none;
    transition: border-color 0.15s, box-shadow 0.15s;
  }
  .page:has(.plans) .plan:hover { border-color: #f0a93b; box-shadow: 0 8px 24px rgba(217, 154, 43, 0.14); }
  .page:has(.plans) .plan-name { font-size: 15px; }
  .page:has(.plans) .plan-days { font-size: 11.5px; }
  .page:has(.plans) .plan-price { font-size: 30px; margin: 10px 0 6px; }
  .page:has(.plans) .cur { font-size: 15px; }
  .page:has(.plans) .plan-desc { font-size: 11.5px; min-height: 34px; }
  .page:has(.plans) .plan .btn { font-size: 13.5px; line-height: 2.6; border-radius: 9px; }
  .page:has(.plans) .benefits {
    margin: 20px 0 0;
    border: 1px solid #e8edf6;
    border-radius: 14px;
    box-shadow: none;
    padding: 22px 24px;
  }
  .page:has(.plans) .ben-title { font-size: 14px; margin-bottom: 8px; }
  .page:has(.plans) .ben-item { font-size: 13px; line-height: 2; }

  /* ============================================================
   * 九、我的订单（指纹：.tabs 状态标签）
   * ------------------------------------------------------------
   * 手机版一行一个订单；PC 两列（`.tabs` / `.empty` 跨两列）。
   * ============================================================ */
  .page:has(.tabs) {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px 16px;
    align-content: start;
    max-width: 1180px;
  }
  .page:has(.tabs) .tabs {
    grid-column: 1 / -1;
    position: static;
    padding: 0;
    background: transparent;
    gap: 8px;
    margin-bottom: 4px;
  }
  .page:has(.tabs) .tab {
    flex: 0 0 auto;
    padding: 8px 18px;
    border-radius: 8px;
    background: #fff;
    border: 1px solid #e8edf6;
    font-size: 13px;
    cursor: pointer;
  }
  .page:has(.tabs) .tab:hover { border-color: #b9cdf2; }
  .page:has(.tabs) .tab--on { background: #3d6deb; border-color: #3d6deb; color: #fff; }
  .page:has(.tabs) .tab--on::after { display: none; }   /* 去掉手机版的下划线小条 */
  .page:has(.tabs) .empty { grid-column: 1 / -1; }
  .page:has(.tabs) .order {
    margin: 0;
    border: 1px solid #e8edf6;
    border-radius: 12px;
    box-shadow: none;
    padding: 16px 18px;
    cursor: pointer;
    transition: border-color 0.15s, box-shadow 0.15s;
  }
  .page:has(.tabs) .order:hover { border-color: #b9cdf2; box-shadow: 0 6px 18px rgba(61, 109, 235, 0.07); }
  .page:has(.tabs) .order-thumb { flex: 0 0 78px; width: 78px; margin-right: 14px; }
  .page:has(.tabs) .order-thumb-img,
  .page:has(.tabs) .order-thumb-ph { width: 78px; height: 104px; }
  .page:has(.tabs) .order-type { font-size: 14px; }

  /* ============================================================
   * 十、优惠券（指纹：.coupon 券卡）
   * ============================================================ */
  .page:has(.coupon) {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px 16px;
    align-content: start;
    max-width: 1180px;
    padding-top: 88px;
  }
  .page:has(.coupon) .head { grid-column: 1 / -1; padding: 0; font-size: 22px; }
  .page:has(.coupon) .empty { grid-column: 1 / -1; }
  .page:has(.coupon) .sec-title { grid-column: 1 / -1; margin: 8px 0 0; font-size: 13.5px; }
  .page:has(.coupon) .coupon {
    margin: 0;
    border: 1px solid #e8edf6;
    border-radius: 12px;
    box-shadow: none;
  }
  .page:has(.coupon) .c-left { width: 96px; padding: 18px 0; }
  .page:has(.coupon) .c-amt { font-size: 22px; }
  .page:has(.coupon) .c-thr { font-size: 10.5px; }
  .page:has(.coupon) .c-right { padding: 16px 18px; }
  .page:has(.coupon) .c-name { font-size: 13.5px; }
  .page:has(.coupon) .c-state { font-size: 11.5px; }
  .page:has(.coupon) .btn--xs { width: 62px; font-size: 11.5px; line-height: 2.2; }
  .page:has(.coupon) .back2 { grid-column: 1 / -1; margin: 8px 0 0; border-radius: 12px; }
  .page:has(.coupon) .back2-title { font-size: 13.5px; }
  .page:has(.coupon) .back2-sub { font-size: 12px; }

  /* ============================================================
   * 十一、签到（指纹：.calendar 日历）
   * ------------------------------------------------------------
   * 左：渐变头卡；右：7 天日历 + 签到按钮；下：积分说明
   * ============================================================ */
  .page:has(.calendar) {
    display: grid;
    grid-template-columns: 320px minmax(0, 1fr);
    grid-template-rows: auto auto auto auto;
    gap: 14px 24px;
    align-content: start;
    max-width: 1080px;
  }
  /* 🔴 渐变头卡**不要跨行**（原来写的 1/3 是错的）：跨行元素的 height 会被
     分摊到多个行里，日历那行一旦没数据（wx:if 不成立）行高塌成 0，
     头卡就只占半高、签到按钮被顶到它旁边去（实测截图就是这样）。
     现在头卡、按钮、提示全部堆在左列，日历独占右列。 */
  .page:has(.calendar) .hero {
    grid-column: 1;
    grid-row: 1;
    border-radius: 16px;
    padding: 26px 22px;
    align-self: start;
  }
  .page:has(.calendar) .hero-title { font-size: 20px; }
  .page:has(.calendar) .hero-sub { font-size: 12px; }
  .page:has(.calendar) .hero-score { font-size: 13px; margin-top: 12px; padding: 4px 14px; }
  .page:has(.calendar) .calendar {
    grid-column: 2;
    grid-row: 1 / 4;
    margin: 0;
    gap: 8px;
    align-content: start;
  }
  .page:has(.calendar) .cell { width: calc(14.28% - 7px); padding: 12px 0; border-radius: 10px; }
  .page:has(.calendar) .cell-day { font-size: 11.5px; }
  .page:has(.calendar) .cell-reward { font-size: 13px; margin-top: 4px; }
  .page:has(.calendar) .cell-check { font-size: 11px; top: 3px; right: 5px; }
  .page:has(.calendar) .sign-btn { grid-column: 1; grid-row: 2; margin: 0; }
  .page:has(.calendar) .signed-tip { grid-column: 1; grid-row: 3; margin: 0; font-size: 13px; }
  .page:has(.calendar) .card.rule {
    grid-column: 1 / -1;
    grid-row: 4;
    margin: 6px 0 0;
    border: 1px solid #e8edf6;
    border-radius: 14px;
    box-shadow: none;
    padding: 20px 24px;
  }
  .page:has(.calendar) .rule-title { font-size: 14px; margin-bottom: 6px; }
  .page:has(.calendar) .rule-item { font-size: 12.5px; line-height: 1.95; }

  /* ============================================================
   * 十二、工具箱（指纹：.cell-ico 工具图标）
   * ============================================================ */
  .page:has(.cell-ico) { max-width: 1180px; }
  .page:has(.cell-ico) .head { padding: 0 0 4px; }
  .page:has(.cell-ico) .head-title { font-size: 26px; }
  .page:has(.cell-ico) .head-sub { font-size: 13px; margin-top: 6px; }
  .page:has(.cell-ico) .grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px;
    padding: 18px 0 0;
  }
  .page:has(.cell-ico) .cell {
    width: auto;
    margin: 0;
    border: 1px solid #e8edf6;
    border-radius: 14px;
    box-shadow: none;
    padding: 18px 20px;
    cursor: pointer;
    transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s;
  }
  .page:has(.cell-ico) .cell:hover {
    border-color: #b9cdf2;
    box-shadow: 0 8px 22px rgba(61, 109, 235, 0.09);
    transform: translateY(-1px);
  }
  .page:has(.cell-ico) .cell-ico { width: 26px; height: 26px; }
  .page:has(.cell-ico) .cell-name { font-size: 15px; margin-top: 10px; }
  .page:has(.cell-ico) .cell-desc { font-size: 12px; margin-top: 5px; }

  /* ============================================================
   * 十三、单栏页（工具执行 / 订单详情 / 制作中 / 协议 / 支付 / 支付结果）
   * ------------------------------------------------------------
   * 这些页内容本身就是一列表单/文档，PC 上不硬拆两栏，
   * 只做三件事：① 收窄到阅读舒服的宽度 ② 卡片化 ③ 固定底栏改静态。
   * ============================================================ */
  .page:has(.pick),
  .page:has(.head-type),
  .page:has(.making),
  .page:has(.sec),
  .page:has(.pay-wrap),
  .page:has(.pr-wrap) {
    max-width: 760px;
    margin: 0 auto;
  }
  .page:has(.sec) { max-width: 860px; }
  .page:has(.pay-wrap),
  .page:has(.pr-wrap) { max-width: 560px; }

  .page:has(.pick) .head { margin-bottom: 14px; }
  .page:has(.pick) .head-title { font-size: 24px; }
  .page:has(.pick) .head-sub { font-size: 13px; }
  .page:has(.pick) .card { border: 1px solid #e8edf6; border-radius: 14px; box-shadow: none; }
  .page:has(.pick) .pick { min-height: 220px; }
  .page:has(.pick) .lbl { width: 88px; font-size: 13px; }
  .page:has(.pick) .inp { font-size: 13.5px; border: 1px solid #e8edf6; background: #f7f9fd; }
  .page:has(.pick) .seg-item { font-size: 13.5px; padding: 12px 0; }

  .page:has(.head-type) .card { border: 1px solid #e8edf6; border-radius: 14px; box-shadow: none; margin-top: 14px; }
  .page:has(.head-type) .card:first-child { margin-top: 0; }
  .page:has(.head-type) .head-type { font-size: 15px; }
  .page:has(.head-type) .head-status { font-size: 12px; }
  .page:has(.head-type) .head-amt { font-size: 19px; }
  .page:has(.head-type) .row { font-size: 13px; padding: 9px 0; }
  .page:has(.head-type) .photo-img,
  .page:has(.head-type) .photo-ph { height: 300px; }
  .page:has(.head-type) .footer {
    position: static;
    left: auto; right: auto; bottom: auto;
    max-width: none;
    margin: 16px 0 0;
    padding: 0;
    background: transparent;
    box-shadow: none;
    display: flex;
    gap: 10px;
  }
  .page:has(.head-type) .footer .btn { flex: 1; height: 44px; line-height: 44px; font-size: 14px; border-radius: 10px; }

  .page:has(.making) .making { padding-top: 8px; }
  .page:has(.making) .card { border: 1px solid #e8edf6; border-radius: 14px; box-shadow: none; }

  /* 协议：一页文档，给白纸卡片感。
     🔴 必须用 `margin-top:88px` 让白卡**从头栏下面开始**，不能靠 padding-top：
        背景色会连 padding 一起涂满 ⇒ 白卡从 y=0 铺起、把固定顶栏压在下面，
        标题第一行直接被挡住（实测截图就是这样）。 */
  .page:has(.sec) {
    background: #fff;
    border: 1px solid #e8edf6;
    border-radius: 16px;
    padding: 40px 48px 32px;
    box-sizing: border-box;
    margin-top: 88px;
    min-height: calc(100vh - 136px);
  }
  .page:has(.sec) .title { font-size: 24px; }
  .page:has(.sec) .sec { margin-bottom: 22px; }
  .page:has(.sec) .foot { margin-top: 8px; }

  /* 支付中转 / 支付结果：窄卡居中 */
  .page:has(.pay-wrap),
  .page:has(.pr-wrap) {
    background: #fff;
    border: 1px solid #e8edf6;
    border-radius: 18px;
    padding: 40px 36px;
    box-sizing: border-box;
    min-height: 0;
    margin-top: 88px;
    padding-top: 40px;
  }
}

/* 中窄屏（1024~1279）：三栏比例收一点，避免中间画布被压太窄 */
@media (min-width: 1024px) and (max-width: 1279px) {
  .page:has(.color-row) {
    grid-template-columns: 236px minmax(0, 1fr) 300px;
    gap: 12px 16px;
    padding-left: 20px;
    padding-right: 20px;
  }
  .page:has(.cats) { grid-template-columns: 200px minmax(0, 1fr); }
  .page:has(.cats) .spec-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .page:has(.preview-area),
  .page:has(.frow) { grid-template-columns: minmax(0, 1fr) 320px; }
  .page:has(.cell-ico) .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
