/* ============================================================
   《前女友清理计划》 — 手机外壳 & 视图样式
   手机尺寸：375 × 760（内容区），整体居中显示。
   ============================================================ */

:root {
  --phone-w: 375px;
  --phone-h: 760px;
  --screen-radius: 44px;
  --statusbar-h: 44px;
  --ui: #16171c;              /* 深色文字 */
  --ui-sub: #8a8f9c;          /* 次要文字 */
  --line: #ebecef;            /* 分隔线 */
  --brand: #7c83ff;           /* 进度主色 */
  --brand-photo: #ff8a5c;

  /* 手机外面那圈浏览器底色的「下面两层」—— 图上没加载出来时才看得见。
     ★ 10-14：把这两层抽成变量，是为了让 js 换背景时能只换上面那张图、
       底下的兜底渐变原样保留（app.js 的 paintBrowserBg 会拼
       `url(新图), var(--body-bg-glow), var(--body-bg-base)`）。
       渐变里没有 url()，所以放进自定义属性是安全的。 */
  --body-bg-glow: radial-gradient(900px 600px at 15% 0%, #ffffff 0%, rgba(255,255,255,0) 60%);
  --body-bg-base: linear-gradient(160deg, #eff1f6 0%, #e3e6ee 100%);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* ---------------- 全局禁止选中（10-14） ----------------
   在游戏里拖一下就把图标和文字刷成一片蓝，桌面 / 手机都出，纯干扰、跟玩法无关。
   `user-select` 是**继承属性**，写在 html 上就全覆盖了，不用挨个元素写。
   三件事一起做才算干净：
     1. user-select:none     —— 划过去不再出现蓝色选区（桌面 + 手机）；
     2. touch-callout:none   —— 手机长按不再弹「拷贝 / 查找 / 存储图像」那个系统小菜单（iOS）；
     3. -webkit-user-drag    —— 拖图标时不再拖出一个"半透明照片幽灵"（桌面）。
   例外：输入框要能选、能长按放光标（游戏里有输密码 / 微信号的地方），
   所以下面用更高优先级把它们放回来。 */
html {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

img, svg {
  -webkit-user-drag: none;
  user-select: none;
  -webkit-user-select: none;
}

input, textarea, [contenteditable="true"] {
  -webkit-user-select: text;
  -moz-user-select: text;
  -ms-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
}

body {
  font-family: "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", system-ui, -apple-system, "Segoe UI", sans-serif;
  /* 手机后面那层背景（浏览器里看到的底）：
     ★ 10-14：首选图改成 assets/相册/浏览器背景/ 里**第一张**（现在是 A1.jpg），
       跟设置里「更换背景」能选的那几张是同一批 —— 旧的那张独立壁纸不用了
       （assets/系统文件/浏览器壁纸.jpg 就是 A1 的副本，内容一样）。
       这张只是**启动时还没轮到 js 画之前**的兜底；js 一跑就用 data.content.js
       里扫出来的第一张重新铺（见 app.js 的 paintBrowserBg），改名 / 加图都跟着变。
     底下两层渐变抽成了变量，js 换图时会原样带上（见 :root 里的说明）。 */
  background:
    url("../assets/相册/浏览器背景/A1.jpg") center center / cover no-repeat,
    var(--body-bg-glow),
    var(--body-bg-base);
  color: var(--ui);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 16px;
}

/* ---------------- 舞台 & 手机 ---------------- */
.stage {
  display: flex; align-items: center; justify-content: center;
  /* 手机跟鼠标转起来那点小交互（裸眼 3D）要的透视。
     数值越大越「平」。1500 大概是「凑近了看手机」：近的那条棱会明显大一圈，
     侧面的厚度也更容易看出来（数越小透视越猛，但也越像广角畸变）。 */
  perspective: 1250px;
  perspective-origin: 50% 50%;
}

.phone {
  position: relative;
  /* ⚠️ 尺寸回到 10-06 那版（用户 10-07 拍板「还原到之前的效果图」）：
     金属带 **3px** + 黑边 9px = padding 12px，整机 +24px。
     10-07 中途我把它加宽到 6px 金属带，看起来像灰色塑料边，已回退。 */
  width: calc(var(--phone-w) + 24px);
  height: calc(var(--phone-h) + 24px);
  padding: 12px;
  border-radius: 56px;
  /* 钛金属中框的底色：中性银灰。
     ⚠️ 别用 conic-gradient（环向渐变会在四边四角留下「彩虹带」）。
     真正让它"像金属"的是 .phone::after 那四条「从边缘往里 4px」的白渐层，
     这里只要给一个中性偏亮的底色就行。 */
  background: linear-gradient(180deg,
    #dbe0e6 0%,
    #cdd2d8 34%,
    #bcc2c9 72%,
    #aeb4bc 100%);
  /* 只有外圈那一道轮廓线 + 投影。⚠️ 别往这里加 inset 环：
     那会变成「白边里再嵌一条暗线」，用户 10-07 明确说像画上去的线。 */
  box-shadow:
    0 0 0 1px rgba(40,46,58,.5),
    0 34px 70px -22px rgba(18,22,38,.62),
    0 12px 26px rgba(18,22,38,.24);

  /* 机身厚度。正面看只有这一层金属中框，一转到侧面四条 .phone__edge 才露出来。
     ⚠️ 现在是 **30px**（原来是 60px）。2026-10-07 用户拍板减半：
        「你既然没办法做写实，就把厚度变成之前的一半，穿帮会小一点」——
        厚度越大，转起来露出的侧板越宽、越容易露馅。
        代价是厚度感变弱，**别再自己调回去**。
        （历史：60px 是"一眼能看见"的下限，30px 几乎全被正面挡住。） */
  --thick: 30px;

  /* 按住手机后面的空白处拖动时，手机会跟着转（裸眼 3D 那点感觉）。
     转多少由 js/app.js 写进 --tilt-x / --tilt-y 两个角度变量。
     不拖的时候是恒等变换，等于没加这条。

     --phone-scale 也是 js/app.js 写的：只在**触屏**上小于 1。
     手机上屏幕比机身本体（399px）还窄，不缩的话机身铺满屏幕、四周一点空白都没有，
     手指就没有可以「按住拖」的地方。缩放写在最前面（先缩再转，两者互不干扰）。
     ⚠️ transform 不影响布局，所以布局尺寸仍然是 399×784、仍是溢出状态 ——
        靠 body 的 overflow:hidden 裁掉，机身视觉上照样居中
        （body 内容区中心 == 视口中心）。 */
  transform:
    scale(var(--phone-scale, 1))
    rotateX(var(--tilt-x, 0deg))
    rotateY(var(--tilt-y, 0deg));
  /* 有了它，四个侧面才会真的待在 3D 空间里，
     而不是被压扁贴在正面上（那样就白做了） */
  transform-style: preserve-3d;
}
/* 只有真的在转的时候才交给 GPU 合成 —— 平时不加 will-change，
   免得屏幕里的字被强行栅格化、看着发虚 */
.phone.is-tilting { will-change: transform; }

/* ---------------- 触屏（手机 / 平板）：把机身缩进屏幕 ----------------
   手机上机身布局尺寸（399×784）比视口还宽，视觉缩放后虽然看着小了，
   布局上仍然是溢出状态 —— 不裁就会露出横向滚动条、还能左右拖页面。
   ⚠️ 这里**不写 touch-action:none**：它是从触摸目标一路往上取交集的，
      写在 .stage / body 上会把机身里面的原生滚动（聊天记录、列表）一起废掉。
      拖动时的页面位移改由 js 在机身外的 touchstart 上 preventDefault 挡掉。 */
@media (hover: none) {
  html, body {
    overflow: hidden;
    overscroll-behavior: none;   /* 顺带按住 Chrome 的下拉刷新 / iOS 的橡皮筋 */
  }
}

/* 中框上那层「镜面渐层」—— 这是让金属像金属的关键（10-06 那版的写法）。
   四条边各来一道「从边缘往里 4px 内衰减到 0」的白，于是每一侧都是
   「最外沿最亮、往里渐暗」，很像真实中框的倒角反光。
   四道白的浓度按受光排：上 .95 > 右 .85 > 左 .7 > 下 .55。
   ⚠️ 别在这里再叠「暗线」：白的渐层是柔的，看着是光泽；
      一条硬的暗线会被读成「拿笔画了一道」。用户 10-07 报的「线」就是它。 */
.phone::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(255,255,255,.95), rgba(255,255,255,0) 4px),
    linear-gradient(0deg,   rgba(255,255,255,.55), rgba(255,255,255,0) 4px),
    linear-gradient(90deg,  rgba(255,255,255,.70), rgba(255,255,255,0) 4px),
    linear-gradient(270deg, rgba(255,255,255,.85), rgba(255,255,255,0) 4px);
}

/* ---------- 机身的四个侧面（厚度） ----------
   每一片都贴在正面的一条边上、绕那条边往里转 90°，
   于是它从「正面边缘」向屏幕里侧伸出去 --thick 那么多。
   颜色是钛金属侧边的味道：靠正面那条棱最亮（受光），越往里越暗。

   上下两片故意比整机短一截（inset 34px），
   不然圆角那块会从机身轮廓里支棱出来。 */
.phone__edge {
  position: absolute;
  pointer-events: none;
  /* ⚠️ 千万别加 backface-visibility: hidden ——
     侧面朝外那一面正好是它的「背面」，一隐藏就整片看不见了（踩过）。
     这里是块纯渐变的板子，正反看都一样，不需要隐藏背面。 */
}
.phone__edge--right,
.phone__edge--left {
  top: 48px; bottom: 48px;
  width: var(--thick);
}
/* 两端缩进去 48px（机身圆角是 56px，48 处轮廓只差半个像素）：
   侧片是垂直插在正面上的，转到四角时它的端头会从圆角轮廓里「支棱」出来，
   缩一截 + 端头削圆，看着才像正常收进机身里。
   代价是四个角那一小块没有厚度 —— 这么小的角度基本看不出来。 */
/* 左片：绕左边缘转进去 —— 它的「左边」就是靠正面那条棱，
   所以 90deg（从左往右）正好是「棱上最亮 → 往里越暗」 */
.phone__edge--left {
  left: 0;
  transform-origin: left center;
  transform: rotateY(90deg);
  border-radius: 16px;
  background: linear-gradient(90deg,
    #e2e5e9 0%, #cdd2d7 18%, #b3b9bf 48%, #969ca3 100%);
}
/* 右片：绕右边缘转进去 —— 它的「右边」才是靠正面那条棱，
   所以渐变得反过来写（270deg），不然亮暗是反的（踩过）。 */
.phone__edge--right {
  right: 0;
  transform-origin: right center;
  transform: rotateY(-90deg);
  border-radius: 16px;
  background: linear-gradient(270deg,
    #e2e5e9 0%, #cdd2d7 18%, #b3b9bf 48%, #969ca3 100%);
}
.phone__edge--top,
.phone__edge--bottom {
  left: 48px; right: 48px;
  height: var(--thick);
}
/* 上片：绕上边缘转进去，「上边」是靠正面那条棱 -> 180deg（从上往下）正合适 */
.phone__edge--top {
  top: 0;
  transform-origin: center top;
  transform: rotateX(-90deg);
  border-radius: 16px;
  background: linear-gradient(180deg,
    #e6e9ec 0%, #d1d5da 20%, #b7bcc2 50%, #999fa6 100%);
}
/* 下片：绕下边缘转进去，「下边」才是靠正面那条棱 -> 用 0deg（从下往上） */
.phone__edge--bottom {
  bottom: 0;
  transform-origin: center bottom;
  transform: rotateX(90deg);
  border-radius: 16px;
  background: linear-gradient(0deg,
    #e6e9ec 0%, #d1d5da 20%, #b7bcc2 50%, #999fa6 100%);
}

/* 屏幕上那点反光：手机一转，反光跟着挪一下（玻璃反光的味道）。
   不转的时候 opacity 是 0，等于不存在。 */
.phone__glare {
  position: absolute;
  left: 12px; top: 12px;
  width: var(--phone-w);
  height: var(--phone-h);
  border-radius: var(--screen-radius);
  pointer-events: none;
  z-index: 60;
  opacity: var(--glare-o, 0);
  background:
    radial-gradient(46% 30% at calc(50% + var(--glare-x, 0px)) calc(50% + var(--glare-y, 0px)),
      rgba(255,255,255,.16) 0%, rgba(255,255,255,.05) 45%, rgba(255,255,255,0) 78%);
}

/* 内侧：屏幕玻璃边（黑边）。真机是「细金属 + 宽黑边」：
   金属只留 3px（外沿最亮），黑边给足 9px。
   border-radius 要写 56 - 3 = 53px，才跟外框同心。 */
.phone::before {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 53px;
  background: #06070c;
  box-shadow:
    0 0 0 1px rgba(0,0,0,.85),
    0 1px 0 rgba(255,255,255,.24) inset,
    0 -1px 0 rgba(255,255,255,.07) inset,
    0 3px 9px rgba(0,0,0,.55);
  pointer-events: none;
}

/* ---------- 侧边按键 ----------
   真机（iPhone 15 Pro，就是这台：灵动岛 + 操作按钮）的排布：
     左侧 操作按钮 / 音量+ / 音量−，右侧 电源键。
   按键本身是一个「凸出机身侧面的立体块」，所以拆成两片来做：
     ① 元素本身  —— 落在机身轮廓外那 4px，是按键朝向观察者的那个面（正面看只有它）；
     ② ::after  —— 绕左/右边转 90°、往机身厚度方向伸 12px，是按键朝外的面。
                    这片垂直于屏幕，正面看投影宽度是 0，只有手机转起来才看得见。

   ⚠️ 正面片必须整片落在轮廓外面（left: -4px、width: 4px），
      不能用以前那种「跨过边缘」的写法（left: -2.5px、width: 4px）。
      一旦它压在机身金属上，两层共面就会 z-fighting —— 表现就是
      「按键透过金属糊成一片」（用户报的 bug，10-07 修）。 */
.phone__side {
  position: absolute;
  border-radius: 3px;
  /* 少了它，::after 那片侧面会被压扁贴在正面上，厚度白做 */
  transform-style: preserve-3d;
  /* 中性银灰 —— 别再往下压到 #23262b 那种近黑：
     实测参考图里按键就是 #7a7a7c 的灰，压黑了就"不像金属"（10-07 用户退回）。 */
  background: linear-gradient(180deg, #8f8f92 0%, #74747a 30%, #5e5e63 62%, #838387 100%);
  box-shadow:
    0 0 0 .5px rgba(0,0,0,.55),
    1px 0 2px rgba(0,0,0,.3);
}
/* 按键朝外的那个面（厚度）。靠正面那道棱最亮、往里越来越暗，
   跟机身侧板（.phone__edge--left/right）的受光保持一致。
   ⚠️ 深度跟着机身厚度一起减半了（12px → 6px），别单独往大调。 */
.phone__side::after {
  content: "";
  position: absolute;
  top: 0;
  height: 100%;
  width: 6px;
  background: linear-gradient(90deg, #8b8b8e 0%, #6c6c6f 40%, #55555a 100%);
}

/* 左侧三颗：贴左边缘外侧，向 -x 凸出 4px。
   位置/长度是按参考图量的（相对 784px 高的机身）：
   action 19.5%~23.2%、音量+ 26.6%~34.9%、音量− 36.2%~44.7%。 */
.phone__side--action   { left: -4px;  top: 153px; width: 4px; height: 29px; }
.phone__side--vol-up   { left: -4px;  top: 209px; width: 4px; height: 65px; }
.phone__side--vol-down { left: -4px;  top: 284px; width: 4px; height: 66px; }
/* 左侧的侧面片：绕「元素左边缘」转 90°，local x 增大 = 往机身里 => 90deg 渐变 */
.phone__side--action::after,
.phone__side--vol-up::after,
.phone__side--vol-down::after {
  left: 0;
  transform-origin: left center;
  transform: rotateY(90deg);
}

/* 右侧电源键：贴右边缘外侧，向 +x 凸出 4px（参考图 29.9%~44.8%） */
.phone__side--power    { right: -4px; top: 234px; width: 4px; height: 118px; }
/* 右侧的侧面片：绕「元素右边缘」转 -90°，local x 增大 = 往机身外
   => 亮暗要反着写（270deg），不然靠正面那条棱反而是最暗的（跟侧板同一个坑） */
.phone__side--power::after {
  right: 0;
  transform-origin: right center;
  transform: rotateY(-90deg);
  background: linear-gradient(270deg, #8b8b8e 0%, #6c6c6f 40%, #55555a 100%);
}

.screen {
  position: relative;
  width: var(--phone-w);
  height: var(--phone-h);
  border-radius: var(--screen-radius);
  overflow: hidden;
  background: #0d0d13;
  isolation: isolate;
}

/* 屏幕玻璃上的斜向反光（很淡，浅色页面上基本看不见） */
.screen::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 58;
  background:
    linear-gradient(122deg,
      rgba(255,255,255,.10) 0%, rgba(255,255,255,.03) 15%, rgba(255,255,255,0) 30%);
}

/* ---------------- 状态栏 ---------------- */
.statusbar {
  position: absolute;
  inset: 0 0 auto 0;
  height: var(--statusbar-h);
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px 0 30px;
  font-size: 13.5px;
  font-weight: 500;                  /* 10-15：用户嫌太粗，从 600 降下来 */
  letter-spacing: .2px;
  color: #fff;                       /* 主屏：白字 */
  pointer-events: none;
  transition: color .22s ease;
}
.screen.is-light .statusbar { color: #16171c; }   /* App 内：黑字 */

.statusbar__right { display: flex; align-items: center; gap: 5px; }
.sb-ico { fill: currentColor; }
.sb-battery {
  position: relative;
  display: inline-block;
  width: 24px; height: 12px;
  border: 1.4px solid currentColor;
  border-radius: 3.5px;
  opacity: .95;
}
.sb-battery::after {
  content: "";
  position: absolute; right: -3.6px; top: 3.4px;
  width: 2px; height: 4px;
  background: currentColor;
  border-radius: 0 1px 1px 0;
  opacity: .6;
}
.sb-battery i {
  position: absolute; left: 1.6px; top: 1.6px; bottom: 1.6px;
  width: 62%;
  background: currentColor;
  border-radius: 2px;
}
/* 电池右边的电量数字（10-15，5G 那个已按用户要求撤掉） */
.sb-num { font-size: 12px; line-height: 1; min-width: 24px; text-align: left; }

/* ---------------- 视图容器 ---------------- */
.view {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  opacity: 0;
  visibility: hidden;
  transform: scale(.97);
  transition: opacity .2s ease, transform .2s ease, visibility .2s;
}
.view.is-active { opacity: 1; visibility: visible; transform: none; }
.view[hidden] { display: none; }

/* ---------- 打开 App / 回桌面：iOS 那种「从图标放大展开」 ----------
   配合 js/app.js 里的 FLIP（先把页面摆成图标那么大 → 重排 → 撤掉，浏览器自己补间）。
   时长要跟 JS 里的 ZOOM_MS 对上。
   ⚠️ 这条 transition 会**整个替换**掉 .view 那条（含 visibility），
      所以退场那个页面要靠 .is-zoom-leaving 自己保住可见性。 */
.view.is-zoom-anim {
  transition:
    transform .42s cubic-bezier(.2, .72, .26, 1),
    opacity .30s ease,
    border-radius .36s ease;
}
/* 进 App：一边长大一边淡进来，早点实心才像「图标展开」 */
.view.is-zoom-anim.is-zoom-in {
  transition:
    transform .42s cubic-bezier(.2, .72, .26, 1),
    opacity .26s ease-out,
    border-radius .34s ease;
}
/* 回桌面：缩得干脆一点，**淡出压到最后**
   （opacity 带 .16s 延迟 + .24s 时长 = 跟 transform 同时结束）。
   ⚠️ 淡出必须一路到 0：以前缩到 .16 就停住不淡，结果是一小块残影赖在图标那儿，
      然后「啪」地消失 —— 用户 10-07 报的就是这个。 */
.view.is-zoom-anim.is-zoom-out {
  transition:
    transform .40s cubic-bezier(.42, .02, .3, 1),
    opacity .24s ease .16s,
    border-radius .36s ease;
}
/* 已经在退场、但还在做缩放动画的那个页面：别让它被 visibility:hidden 吞掉 */
.view.is-zoom-leaving { visibility: visible; }

/* 桌面被「压在底下」：跟着放大一点点 + 压暗 —— 像不像 iOS 有一半靠它。
   ⚠️ visibility: visible 不能少：进 App 时桌面已经不是 is-active 了，
      光靠 opacity/transform 会被 .view 的 visibility:hidden 整片吞掉，
      表现是「App 还小的时候四周一片黑」，完全没有 iOS 那种底下一层的味道。 */
.view--home.is-zoom-home {
  visibility: visible;
  transition: transform .42s cubic-bezier(.2, .72, .26, 1), opacity .42s ease;
}
.view--home.is-zoom-home.is-under { transform: scale(1.05); opacity: .62; }

/* ---------------- 主屏 ---------------- */
.view--home {
  background-image: url("../assets/wallpaper/home.svg");
  background-size: cover;
  background-position: center;
}

.home__scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: calc(var(--statusbar-h) + 12px) 18px 4px;
  scrollbar-width: none;
}
.home__scroll::-webkit-scrollbar { display: none; }

/* 进度卡 —— 竖排：顶上那行标语，下面「总进度环 + 每个 App 一行」 */
.glance {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 16px 14px;
  border-radius: 22px;
  background: rgba(255,255,255,.13);
  border: 1px solid rgba(255,255,255,.16);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}

/* 卡内顶部那行标语（文案在 data.static.js 的 ui.glance.homeTagline） */
.glance__tagline {
  margin: 0;
  text-align: center;
  font-size: 12.5px;
  letter-spacing: 1.4px;
  color: rgba(255,255,255,.82);
  text-shadow: 0 1px 7px rgba(0,0,0,.45);
}
.glance__tagline:empty { display: none; }

.glance__body {
  display: flex;
  align-items: center;
  gap: 14px;
}

/* 进度环 */
.ring { position: relative; flex: none; }
.ring svg { display: block; transform: rotate(-90deg); }
.ring circle { fill: none; stroke-linecap: round; }
.ring__track { stroke: rgba(255,255,255,.22); }
.ring__bar {
  stroke: var(--brand);
  stroke-dasharray: 263.9;      /* 2πr, r = 42 */
  stroke-dashoffset: 263.9;
  transition: stroke-dashoffset .45s cubic-bezier(.22,.61,.36,1);
}
.ring__text {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  color: #fff;
}
.ring__text b { font-size: 19px; font-weight: 700; letter-spacing: .3px; }
.ring__text span { font-size: 10px; opacity: .72; margin-top: 1px; }
.ring--total { width: 84px; height: 84px; }
.ring--total .ring__track { stroke-width: 7; }
.ring--total .ring__bar { stroke-width: 7; }

.glance__list { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 9px; }

.glance__row {
  display: flex; align-items: center; gap: 9px;
  color: #fff;
}
.glance__name {
  font-size: 13px;
  letter-spacing: .3px;
  white-space: nowrap;
}
.glance__num { font-size: 12px; opacity: .68; font-variant-numeric: tabular-nums; }

/* 行尾那个百分比数字 —— 用 margin-left:auto 顶到卡片右边，
   名字和进度条则贴着左边走（用户 10-07 定的排法：
   名字在左 → 条紧跟 → 右边写百分比）。 */
.glance__pct {
  margin-left: auto;
  font-size: 12px;
  font-weight: 600;
  opacity: .72;
  letter-spacing: .2px;
  white-space: nowrap;
}

/* 名字后面那根细长的进度条 —— 就是「电池电量条」那种：一条淡色底轨 +
   一段按百分比长的实色填充。
   用户 10-07：原来行首的圆环要拉成长条、更贴合卡片的外轮廓，
   不要百分比文字（百分比单独写在行尾），宽度翻倍（64 → 128px）。
   长度由 js 写进 --p（见 recalcDone）。
   ⚠️ 别放回圆环，也别在条里塞「0%」「0 / 26」。 */
.pctbar {
  position: relative;
  flex: none;
  width: 128px;
  height: 9px;
  border-radius: 4.5px;
  background: rgba(255,255,255,.2);
  overflow: hidden;
}
.pctbar__fill {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: var(--p, 0%);
  border-radius: inherit;
  background: var(--brand);
  transition: width .45s cubic-bezier(.22,.61,.36,1);
}

/* ---------------- 灵动岛：顶部进度胶囊 + 下拉面板 ---------------- */

/* 面板展开时压暗背景 */
.gmask {
  position: absolute;
  inset: 0;
  z-index: 76;
  background: rgba(8,8,14,.44);
  opacity: 0;
  visibility: hidden;
  transition: opacity .24s ease, visibility .24s;
}
.gmask.is-on { opacity: 1; visibility: visible; }

/* 胶囊和面板共用一个容器：关着时是胶囊宽，点开后展开成面板宽 */
.islandWrap {
  position: absolute;
  top: 10px;
  left: 50%;
  z-index: 78;
  width: 104px;
  transform: translateX(-50%);
  transition: width .42s cubic-bezier(.22,.61,.36,1);
}
.islandWrap.is-on { width: 344px; }

/* 胶囊本体（灵动岛那顆黑药丸） */
.island {
  position: relative;
  display: flex;
  align-items: center;
  gap: 5px;
  width: 100%;
  height: 30px;
  padding: 0 10px;
  border: 0;
  border-radius: 15px;
  background: #000;
  color: #fff;
  font-family: inherit;
  cursor: pointer;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
  box-shadow: 0 2px 10px rgba(0,0,0,.45), 0 0 0 .5px rgba(255,255,255,.08) inset;
  transition: border-radius .42s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease;
}
.islandWrap.is-on .island {
  border-radius: 19px 19px 0 0;
  box-shadow: none;
}
.island:active { transform: scale(.97); }

/* 胶囊里的小进度环 */
.island__ring { position: relative; flex: none; width: 18px; height: 18px; }
.island__ring svg { display: block; width: 100%; height: 100%; transform: rotate(-90deg); }
.island__ring circle { fill: none; }
.island__ring .ring__track { stroke: rgba(255,255,255,.24); stroke-width: 13; }
.island__ring .ring__bar {
  stroke: #34d97a;
  stroke-width: 13;
  stroke-dasharray: 263.9;
  stroke-dashoffset: 263.9;
  transition: stroke-dashoffset .45s cubic-bezier(.22,.61,.36,1);
}

.island__num {
  flex: none;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .2px;
  font-variant-numeric: tabular-nums;
}

/* 「总进度」和箭头只在展开后出现 */
.island__label,
.island__caret {
  flex: none;
  width: 0;
  opacity: 0;
  overflow: hidden;
  white-space: nowrap;
  transition: opacity .22s ease, width .42s cubic-bezier(.22,.61,.36,1);
}
.island__label { font-size: 11.5px; color: rgba(255,255,255,.62); }
.island__caret { display: flex; align-items: center; margin-left: auto; }
.islandWrap.is-on .island__label { width: 44px; opacity: 1; }
.islandWrap.is-on .island__caret { width: 16px; opacity: 1; }

/* 右端那颗前摄像头（藏在黑药丸里，只有一点冷调反光） */
.island__cam {
  flex: none;
  width: 7.5px;
  height: 7.5px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 32%,
    #1a2033 0%, #0c1026 46%, #05060f 76%, #03040a 100%);
  box-shadow:
    0 0 0 .5px rgba(140,170,235,.16),
    inset 0 0 1px rgba(110,150,240,.32);
}

/* 从胶囊下面「长」出来的面板 */
.islandPanel {
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  border-radius: 0 0 26px 26px;
  background: linear-gradient(180deg, #000 0%, #07070e 50%, #0d0d18 100%);
  box-shadow: 0 24px 46px -12px rgba(0,0,0,.6);
  transition: max-height .44s cubic-bezier(.22,.61,.36,1), opacity .26s ease;
}
.islandWrap.is-on .islandPanel { max-height: 470px; opacity: 1; }

.islandPanel__body { padding: 2px 16px 18px; }

/* 面板里的进度卡：去掉外框，融进黑底。
   ⚠️ 这里的结构跟桌面那张不一样（没有标语、也没有 .glance__body 包一层），
      所以必须把 .glance 的竖排改回横排，否则环和列表会上下叠。 */
.glance--sheet {
  flex-direction: row;
  align-items: center;
  gap: 14px;
  padding: 6px 2px 12px;
  background: none;
  border: 0;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.gpanel__sub {
  margin: 4px 0 10px;
  padding-left: 2px;
  font-size: 11px;
  letter-spacing: 1px;
  color: rgba(255,255,255,.48);
}

/* 还没开放的那几个：灰的、纯展示、两列排 */
.glance__list--locked {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px 12px;
  padding-bottom: 6px;
}
.glance__row.is-locked {
  gap: 8px;
  min-height: 34px;
  padding: 0 2px;
  color: rgba(255,255,255,.4);
  cursor: default;
}
.glance__row.is-locked .glance__lock {
  width: 26px; height: 26px;
  background: rgba(255,255,255,.06);
}
.glance__row.is-locked .glance__lock svg { width: 13px; height: 13px; }

/* 面板里的「收起」：黑底上换成半透明 */
.islandPanel .sheet__cancel {
  height: 46px;
  background: rgba(255,255,255,.1);
  color: rgba(255,255,255,.92);
  font-size: 15px;
}
.islandPanel .sheet__cancel:active { background: rgba(255,255,255,.19); }
.glance__lock {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px; height: 34px;
  border-radius: 50%;
  background: rgba(255,255,255,.07);
}
.glance__lock svg { fill: rgba(255,255,255,.45); }
.glance__row.is-locked .glance__name { font-size: 13px; }
/* 名字不再 flex:1 了（进度条那行要左对齐），所以「未开放」这三个字
   得自己顶到右边去，跟原来一样 */
.glance__row.is-locked .glance__num { font-size: 11px; opacity: 1; color: rgba(255,255,255,.34); margin-left: auto; }

/* 应用网格 */
.home__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px 8px;
  margin-top: 24px;
  padding-bottom: 6px;
}

.app {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: #fff;
  cursor: pointer;
}
.app__icon {
  position: relative;
  width: 60px; height: 60px;
  border-radius: 15px;
  transition: transform .16s cubic-bezier(.3,1.4,.5,1);
  box-shadow: 0 5px 12px -5px rgba(0,0,0,.5);
}
.app__icon img { width: 100%; height: 100%; display: block; border-radius: inherit; }
.app:active .app__icon { transform: scale(.9); }

.app__name {
  font-size: 11px;
  letter-spacing: .2px;
  text-shadow: 0 1px 3px rgba(0,0,0,.5);
  max-width: 68px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 图标右上角的红点：里面是「还剩多少件没做」，全做完就消失 */
.app__badge {
  position: absolute;
  top: -5px; right: -5px;
  min-width: 20px; height: 20px;
  padding: 0 5.5px;
  border-radius: 10px;
  background: #ff3b30;
  border: 1.6px solid rgba(255,255,255,.92);
  color: #fff;
  font-size: 11.5px;
  font-weight: 600;
  line-height: 17px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  box-shadow: 0 2px 6px rgba(200,32,28,.42);
  pointer-events: none;
}
.app__badge.is-off { display: none; }

/* 未开放的 App：打不开 —— 图标要**明显**灰下去、暗下去，
   跟能玩的（微信 / 相册，全彩）一眼拉开差距。
   ⚠️ 别调轻（试过 grayscale(.72) brightness(.92)，太接近全彩了看不出来）。
   去色拉满 + 压到 .58，名字也跟着淡。 */
.app.is-locked .app__icon {
  filter: grayscale(1) brightness(.58) contrast(.94);
  box-shadow: 0 4px 10px -6px rgba(0,0,0,.42);
}
.app.is-locked .app__name { opacity: .5; }

/* 底部固定栏：浮起来的磨砂长条（不贴边、不带文字） */
.dock {
  flex: none;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px;
  margin: 0 14px 14px;
  padding: 12px 10px;
  border-radius: 30px;
  background: rgba(255,255,255,.15);
  border: 1px solid rgba(255,255,255,.18);
  backdrop-filter: blur(24px) saturate(1.5);
  -webkit-backdrop-filter: blur(24px) saturate(1.5);
  box-shadow: 0 10px 26px -12px rgba(0,0,0,.55);
}
.dock .app { gap: 0; }
.dock .app__name { display: none; }

/* ---------------- App 内页（通用） ---------------- */
.view--app { background: #f7f7f9; color: var(--ui); }

/* 顶栏高度 = 状态栏 + 内容区。
   ★ 10-14 返回键 34 → 51（×1.5）→ **41（×0.8）**，内容区跟着 44 → 58 → 51。 */
.appbar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  height: calc(var(--statusbar-h) + 51px);
  padding: var(--statusbar-h) 12px 0;
  background: #f7f7f9;
  border-bottom: 1px solid var(--line);
}
/* 返回键：34 → 51（×1.5）→ **41（×0.8）**，图标 22 → 33 → **26**。
   ★ 白色圆角方块是 background-image，元素本身透明，
     阴影加在元素上会变成一个圆 -> 必须用 drop-shadow
     （它沿渲染结果的不透明像素走，只勾白方块的轮廓）。
   ★ 全站共用：index.html 里 12 处 `.appbar__back` 全走这一套。 */
.appbar__back {
  flex: none;
  width: 41px; height: 41px;
  border: 0; padding: 0;
  border-radius: 50%;
  background: transparent url("../assets/icons/back.svg") center / 26px 26px no-repeat;
  cursor: pointer;
  transition: background-color .15s ease;
  filter: drop-shadow(0 1px 1.5px rgba(15, 20, 35, .20))
          drop-shadow(0 3px 7px rgba(15, 20, 35, .10));
}
.appbar__back:hover { background-color: rgba(0,0,0,.05); }
.appbar__back:active { background-color: rgba(0,0,0,.1); }
.appbar__title {
  flex: 1;
  margin: 0;
  font-size: 16.5px;
  font-weight: 600;
  letter-spacing: .5px;
  text-align: center;
}
.appbar__slot { flex: none; width: 41px; }

/* 左右两侧内容不等宽时，标题用绝对定位兜住居中
   （现在只有「最近删除」用：右边多了个「全部删除」） */
.appbar--even { position: relative; }
.appbar--even .appbar__title {
  position: absolute;
  left: 53px; right: 53px;
  top: var(--statusbar-h);
  height: 51px;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

/* 顶栏右上角的文字按钮（红字，不带底）。
   现在只有「最近删除」页的「全部删除」在用。 */
.appbar__text {
  flex: none;
  margin-left: auto;
  border: 0;
  padding: 4px 2px;
  background: transparent;
  color: #ff3b30;
  font-family: inherit;
  font-size: 15.5px;
  letter-spacing: .4px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: opacity .15s ease;
}
.appbar__text:active { opacity: .5; }
.appbar__text[hidden] { display: none; }

/* ---------------- 微信顶栏：标题 + 右上角两个装饰图标 ---------------- */
.appbar--wechat { position: relative; }

/* 标题绝对居中（左右两侧内容宽度不一样，用 flex 会偏） */
.appbar--wechat .appbar__title {
  position: absolute;
  left: 53px; right: 53px;
  top: var(--statusbar-h);
  height: 51px;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.appbar__num { font-weight: 500; letter-spacing: .2px; }

.appbar__acts {
  margin-left: auto;
  flex: none;
  display: flex;
  align-items: center;
  gap: 5px;
  color: #1a1a1a;
}
/* 纯装饰：不响应点击，就是个图标摆在那儿 */
.appbar__act {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.appbar__act svg { display: block; }

/* 相册右上角的小回收站入口（故意做得淡一点、小一点） */
.appbar__trash {
  flex: none;
  width: 30px; height: 30px;
  border: 0; padding: 0;
  border-radius: 50%;
  background: transparent;
  color: #c2c6cd;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.appbar__trash svg { fill: currentColor; }
.appbar__trash:active { background: rgba(0,0,0,.06); color: #8a8f9c; }
.appbar__trash[hidden] { display: none; }

/* ---------------- 相册顶栏：标题必须跟灵动岛同一条竖线居中（10-10） ----------------
   左侧返回键 34px + 6px 间隙会把「flex:1 + text-align:center」的标题往右推 20px
   （用户：「现在太偏了」），所以跟微信顶栏一样改成绝对定位居中；
   右上角那个垃圾桶没有 flex:1 的标题顶着，得自己 margin-left:auto 靠右边。 */
.appbar--photo { position: relative; }
.appbar--photo .appbar__title {
  position: absolute;
  left: 53px; right: 53px;
  top: var(--statusbar-h);
  height: 51px;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.appbar--photo .appbar__trash { margin-left: auto; }

/* ---------------- 设置 App（仿 iOS 的分组列表，只做外观） ----------------
   底色调成 iOS 那个 #f2f2f7（比通用浅灰再灰一点点），
   分组是一张白卡片，行与行之间一根从图标后面起的分隔线。 */
.view--settings { background: #f2f2f7; }
.view--settings .appbar { background: #f2f2f7; border-bottom-color: #e4e4ea; }

/* ---------------- 游戏玩法：整屏一张图（★ 10-14） ----------------
   用户要「整张图片占满整个屏幕、不要留空隙」-> object-fit: cover，硬裁不留边。
   图 768×1376（比例 .558）、屏幕 375×760（.493）-> 左右各裁掉约 5.8%；
   实测图里内容最左到 6.5%（严格阈值，淡纸纹不算），所以裁不到字，安全。
   ⚠️ 别改成 contain —— 那样上下/左右会露出底色，就是「留空隙」。
   返回键直接复用 `.viewer__back`（深色玻璃圆，见下面大图页那块）。 */
.view--guide { background: #e6d8c8; }
.guide__img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
}

.setpage {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding-bottom: 26px;
  background: #f2f2f7;
}
.setpage::-webkit-scrollbar { display: none; }

/* 顶上那个搜索框：跟真的 iOS 一样，只是样子 */
.setsearch {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 36px;
  margin: 8px 16px 2px;
  padding: 0 10px;
  border-radius: 10px;
  background: rgba(118, 118, 128, .12);
  color: #8a8f9c;
  font-size: 14.5px;
  letter-spacing: .2px;
}
.setsearch svg { flex: none; }

/* 分组 */
.setgroup { margin: 22px 16px 0; }
.setgroup__head {
  margin: 0 0 7px 16px;
  font-size: 12.5px;
  color: #6d6d72;
  letter-spacing: .3px;
}
.setcard {
  background: #fff;
  border-radius: 11px;
  overflow: hidden;
}

/* 一行 */
.setrow {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  min-height: 44px;
  padding: 0 12px;
  border: 0;
  background: transparent;
  color: var(--ui);
  font: inherit;
  text-align: left;
  cursor: pointer;
  -webkit-appearance: none;
  transition: background-color .12s ease;
}
.setrow + .setrow::before {
  content: "";
  position: absolute;
  top: 0; left: 52px; right: 0;
  height: 1px;
  background: #e7e7ec;
}
.setrow:active { background: #e9e9ee; }

/* 左边那个彩色圆角小方块 */
.setrow__ico {
  flex: none;
  width: 29px; height: 29px;
  border-radius: 7.5px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.setrow__ico svg { display: block; }

.setrow__label {
  flex: 1;
  min-width: 0;
  font-size: 15.5px;
  letter-spacing: .2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.setrow__val {
  flex: none;
  font-size: 14.5px;
  color: #8a8f9c;
}
.setrow__chev { flex: none; color: #c4c6cd; }

/* 最底下那行小字 */
.setfoot {
  margin: 26px 16px 0;
  text-align: center;
  font-size: 12.5px;
  color: #a1a3ab;
  letter-spacing: .3px;
}

/* 最底下那颗「重新游玩」（10-15）：白底红字，iOS 那种自毁按钮 */
.setdanger {
  display: block;
  width: calc(100% - 32px);
  margin: 16px 16px 0;
  height: 50px;
  padding: 0;
  border: 0;
  border-radius: 13px;
  background: #fff;
  color: #ff3b30;
  font-family: inherit;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: .3px;
  cursor: pointer;
  transition: background-color .15s ease, transform .1s ease;
}
.setdanger:active { background: #f0f0f5; transform: scale(.99); }

/* 右上角三个点 */
.appbar__more {
  flex: none;
  width: 34px; height: 34px;
  border: 0; padding: 0;
  border-radius: 50%;
  background: transparent;
  color: #3a3d45;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background-color .15s ease;
}
.appbar__more svg { fill: currentColor; }
.appbar__more:hover { background-color: rgba(0,0,0,.05); }
.appbar__more:active { background-color: rgba(0,0,0,.1); }

.appbody {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: none;
}
.appbody::-webkit-scrollbar { display: none; }
.appbody--center { display: flex; align-items: center; justify-content: center; }
.empty { color: var(--ui-sub); font-size: 14px; }

/* ---------------- 秒表（只看这局玩了多久，不参与计分） ---------------- */
.view--stopwatch { background: #f2f2f7; }
.view--stopwatch .appbar { background: #f2f2f7; border-bottom-color: transparent; }

.sw {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  padding: 0 24px 56px;
}

/* 白色圆表盘 */
.sw__dial {
  width: 256px; height: 256px;
  border-radius: 50%;
  background: #fff;
  box-shadow:
    0 4px 18px rgba(0,0,0,.07),
    0 0 0 1px rgba(0,0,0,.02);
}
.sw__svg { display: block; width: 100%; height: 100%; }

/* 大号细体时间，跟 iPhone 秒表一个调。
   ⚠ 每个字符是一个定宽格子（JS 里拆的）：这个字体栈的 tabular-nums 不生效，
   不拆的话数字一变宽窄就变，整块会左右晃。.557em / .25em 是照本机实测调的。 */
.sw__time {
  display: flex;
  align-items: baseline;
  justify-content: center;
  font-size: 56px;
  font-weight: 300;
  line-height: 1.08;
  color: #1c1c1e;
  font-variant-numeric: tabular-nums;
}
.sw__ch {
  display: inline-block;
  width: .557em;
  text-align: center;
}
.sw__ch--dot { width: .25em; }
.sw__hint {
  font-size: 12px;
  letter-spacing: 3px;
  color: #8e8e93;
}

/* 列表（微信） */
.list { background: #fff; }
.list__item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 16px;
  border-bottom: 1px solid var(--line);
  cursor: pointer;
}
.list__item:last-child { border-bottom: 0; }
.list__item:active { background: #f2f2f5; }
.list__ava {
  flex: none;
  width: 46px; height: 46px;
  border-radius: 6px;
  background: #eceef2;
  object-fit: cover;
}
.list__main { flex: 1; min-width: 0; }
.list__top { display: flex; align-items: baseline; gap: 8px; }
.list__name { font-size: 15px; font-weight: 500; }
.list__time { margin-left: auto; font-size: 11px; color: var(--ui-sub); }
.list__desc {
  margin-top: 3px;
  font-size: 12.5px;
  color: var(--ui-sub);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 相册网格：每行 4 个（10-10 用户要求，缩略图变小一点） */
.gallery {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2px;
  padding: 2px;
}
.gallery__cell {
  position: relative;
  aspect-ratio: 1 / 1;
  border: 0; padding: 0;
  background: #e9eaee;
  cursor: pointer;
  overflow: hidden;
}
.gallery__cell img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gallery__cell:active img { transform: scale(1.04); }
.gallery__cell img { transition: transform .2s ease; }
/* 视频格子（私密空间里的 mp4）：只显示首帧，静音、不自动播、点不着，
   点击穿透给外面那个 button，跟图片一个手感 */
.gallery__cell video {
  width: 100%; height: 100%; object-fit: cover; display: block;
  background: #000;
  pointer-events: none;
}

/* 视频格子上的播放标记 */
.gallery__play {
  position: absolute;
  right: 6px;
  bottom: 6px;
  width: 0; height: 0;
  border-left: 11px solid #fff;
  border-top: 7px solid transparent;
  border-bottom: 7px solid transparent;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,.5));
  pointer-events: none;
}

/* 相册「壁纸」组里，正在用的那张**不加任何标记**（10-06 用户要求去掉绿框 + 「正在使用」） */

/* 相册一级：分类列表 */
.album { gap: 13px; }
.album__cover {
  flex: none;
  width: 46px; height: 46px;
  border-radius: 6px;
  object-fit: cover;
  background: #eceef2;
  display: block;
}
.album__name { flex: 1; }
.album__num {
  font-size: 13px;
  color: var(--ui-sub);
  font-variant-numeric: tabular-nums;
}

/* 私密空间：锁住的界面 */
.lock {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  height: 100%;
  border: 0;
  background: transparent;
  font-family: inherit;
  color: var(--ui-sub);
  cursor: pointer;
}
.lock svg { fill: #c4c7ce; }
.lock b { font-size: 16px; color: var(--ui); font-weight: 600; }
.lock span { font-size: 13px; }
.lock:active { background: #f2f2f5; }

.sect {
  padding: 14px 16px 6px;
  font-size: 12.5px;
  color: var(--ui-sub);
  letter-spacing: .4px;
}

/* ---------------- 聊天记录 ---------------- */
.view--chat { background: #ededed; }
.view--chat .appbar { background: #ededed; border-bottom-color: #dcdde1; }

.chatbody {
  flex: 1;
  min-height: 0;
  overflow-y: auto;              /* 记录长了能滚：滚轮 / 触屏滑动都行 */
  overflow-x: hidden;
  overscroll-behavior: contain;  /* 滑到头别把后面的东西带着动 */
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;         /* 滚动条藏起来，跟其他页一致 */
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 12px 14px;
}
.chatbody::-webkit-scrollbar { display: none; }
/* 记录少的时候从顶部开始（第一条贴着上面），跟微信一样；
   记录长了可滚动，打开时由 JS 滚到最后一条。
   ⚠ 别加 `.chatbody > :first-child { margin-top: auto }`：那会让
   记录少的时候也贴到底部（10-06 用户要求改成贴顶）。 */

.msg { display: flex; align-items: flex-start; gap: 8px; }
.msg--me { flex-direction: row-reverse; }

/* ★ 10-14 `#!` 占位行：界面上什么都不画，只负责把上下两条消息的间距拉开一点。
   .chatbody 是 column + gap:10px，所以相邻两条本来是 10px。
   这一格高度 10 + 上下各 -5 的负外边距 = 净增 10px
   -> 前面那条和后面那条之间变成 10 + 10 + 10 - 10 = **20px**（用户要的「两倍」）。
   ⚠️ 别改成 height:10px 不加负边距 —— 那样会变成 30px，是三倍不是两倍。 */
.msg-gap {
  flex: none;
  height: 10px;
  margin: -5px 0;
}

/* ★ 10-14 `##` 占位行：间距拉到**三倍**（10 -> 30px），中间再画一条细分界线。
   算式同 #!：10(上 gap) + h + mt + mb + 10(下 gap) = 30  ->  h = 20（负外边距不动）。
   ★ 界线走 ::after —— **不能加子节点**（`.msg-gap` 必须保持 0 子元素，别处有探针在数）。 */
.msg-gap--line { height: 20px; position: relative; }
.msg-gap--line::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  /* ★ 10-14 用户要求「短一点，是现在的 1/2 长」：62% -> 31% */
  width: 31%;
  height: 1px;
  transform: translate(-50%, -50%);
  background: rgba(0, 0, 0, .085);
  border-radius: 1px;
}

.msg__ava {
  flex: none;
  width: 34px; height: 34px;
  border-radius: 5px;
  object-fit: cover;
  background: #dcdde1;
}
.msg__bubble {
  max-width: 208px;
  padding: 8px 11px;
  border-radius: 6px;
  background: #fff;
  color: #16171c;
  font-size: 14px;
  line-height: 1.5;
  word-break: break-word;
  white-space: pre-wrap;
}
.msg--me .msg__bubble { background: #95ec69; }

/* 语音消息：喇叭 + 秒数。别人发的那条右边挂个「还没听」的红点 */
.msg__bubble--voice {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 10px 12px;
  white-space: normal;
}
.voice__ico { flex: none; }
.voice__sec { font-size: 14.5px; line-height: 1; }
.voice__dot {
  flex: none;
  align-self: center;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: #fa5151;
}

/* 通话消息：听筒 + 通话时长 */
.msg__bubble--call {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 10px 12px;
  white-space: normal;
}
.call__ico { flex: none; }
.call__text { font-size: 14.5px; line-height: 1; }

/* 转账 / 收款：微信那种橘黄气泡、白字，气泡左下角一个小「转账」 */
.msg__col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 0;
}
.msg__bubble--pay {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  /* 卡片固定大小：不再写名字之后，别让这个框缩水
     （10-06 用户说"整个框更小了"，就是因为名字变短、金额挤到同一行） */
  min-width: 212px;
  min-height: 76px;
  background: #fdce9c;
  color: #fff;
  white-space: normal;
}
/* 转出和收到都是同一个橘色（微信就这样），别跟着 --me 变绿 */
.msg--me .msg__bubble--pay { background: #fdce9c; }
.pay__ico { flex: none; }
.pay__col { display: flex; flex-direction: column; gap: 2px; }
.pay__amt { font-size: 16px; font-weight: 600; line-height: 1.35; }
.pay__sub { font-size: 12px; line-height: 1.2; opacity: .94; }
.pay__tag {
  margin-top: 3px;
  font-size: 11px;
  color: #9b9b9b;
}

/* ---- 文件卡片（★ 10-12，W 代号）----
   照微信「发文件」那条消息画的：上半 = 左边文件名 + 大小、右边压缩包图标，
   一条细线分隔，下半 = 绿微信标 + 「微信」来源行。
   卡片**恒定白底**（跟参考图一致），别跟着 --me 变绿。
   宽度要自己写：.msg__bubble 默认 max-width 208px 会把卡片压窄。 */
.msg__bubble--file,
.msg--me .msg__bubble--file {
  padding: 0;
  max-width: 236px;
  background: #fff;
  white-space: normal;
  overflow: hidden;
}
.filecard { width: 236px; }
.filecard__top {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 13px 12px 12px 13px;
}
.filecard__info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.filecard__name {
  font-size: 15px;
  color: #191919;
  line-height: 1.25;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.filecard__size { font-size: 12.5px; line-height: 1; color: #9a9a9a; }
.filecard__ico { flex: none; display: block; }
.filecard__src {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 8px 13px 9px;
  border-top: 1px solid rgba(0, 0, 0, .07);
  font-size: 12px;
  color: #8d8d8d;
}
.filecard__src svg { flex: none; display: block; }

/* 图片消息：气泡里塞图。整条只有图时用 --img 收掉气泡内边距 */
/* 整条就是一张图：气泡自己**不画底色、不留白** ——
   否则图片外面会套一圈「描边」（别人的白色、我的绿色）。
   图自己的圆角在 .msg__img 上，够用。（10-06 用户要求） */
.msg__bubble--img,
.msg--me .msg__bubble--img {
  padding: 0;
  background: transparent;
}

.msg__img {
  display: block;
  max-width: 100%;
  max-height: 240px;
  border-radius: 4px;
  background: #dcdde1;
  cursor: pointer;
}

/* 点开看大图：铺满整个手机屏，点哪都关 */
.imgzoom {
  position: absolute;
  inset: 0;
  z-index: 75;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 14px;
  background: rgba(0, 0, 0, .93);
}
.imgzoom.is-on { display: flex; }
.imgzoom img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 4px;
}

.msgtime {
  text-align: center;
  font-size: 11px;
  color: #a2a7b0;
  margin: 2px 0;
}

/* 系统提示（「说的话」一格以 D 开头）：
   没有头像、也没有气泡，就两行居中的灰字 ——
   跟微信「你已添加了 XXX，现在可以开始聊天了」那条长得一样。
   第一行是固定的提示（更浅），第二行才是正文（D 后面写的文案）。
   ★ 必须把 .msg 的 flex 关掉，不然会按气泡那一套排版。 */
.msg--sys {
  display: block;
  padding: 2px 22px 4px;
}
.sysmsg { text-align: center; line-height: 1.65; }
.sysmsg__hint { font-size: 11px; color: #b6bbc2; }
.sysmsg__text { font-size: 12.5px; color: #979da6; }

/* 聊天底部的输入栏：纯展示，点了没反应 */
.chatbar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px 26px;
  background: #f7f7f9;
  border-top: 1px solid #e6e8ec;
}
.chatbar__ico {
  flex: none;
  width: 30px; height: 30px;
  color: #6b7079;
  display: flex;
  align-items: center;
  justify-content: center;
}
.chatbar__ico svg { fill: currentColor; }
.chatbar__input {
  flex: 1;
  height: 36px;
  border-radius: 6px;
  background: #fff;
  border: 1px solid #e6e8ec;
}
.chatbar__input::after { content: none; }

/* ---------------- 聊天信息 ---------------- */
.cinfo-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  padding: 22px 0 20px;
  background: #fff;
}
.cinfo-head img { width: 58px; height: 58px; border-radius: 8px; object-fit: cover; background: #eceef2; }
.cinfo-head span { font-size: 15.5px; font-weight: 500; }

.cellgroup { margin-top: 10px; background: #fff; }

.cell {
  display: flex;
  align-items: center;
  min-height: 50px;
  padding: 0 16px;
  font-size: 15px;
  cursor: pointer;
  border-bottom: 1px solid var(--line);
}
.cell:last-child { border-bottom: 0; }
.cell:active { background: #f2f2f5; }
.cell__label { flex: 1; }
.cell--danger { justify-content: center; color: #e64340; }
.cell--note { color: var(--ui-sub); font-size: 12.5px; cursor: default; }
.cell--note:active { background: transparent; }

/* 开关 */
.switch {
  position: relative;
  flex: none;
  width: 44px; height: 26px;
  border-radius: 13px;
  background: #e5e5e5;
  transition: background-color .2s ease;
}
.switch::after {
  content: "";
  position: absolute; top: 2px; left: 2px;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.22);
  transition: transform .2s cubic-bezier(.3,1.3,.5,1);
}
.switch.is-on { background: #07c160; }
.switch.is-on::after { transform: translateX(18px); }

/* ---------------- 微信里的四个面板 ---------------- */
.pane { display: none; }
.pane.is-on { display: block; }

/* 通讯录右边那条竖着的 A~Z 索引（纯装饰，不响应点击，也不参与滚动） */
.idxbar {
  position: absolute;
  right: 2px;
  top: calc(var(--statusbar-h) + 51px);
  bottom: calc(58px + 22px);
  z-index: 12;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: space-evenly;
  width: 15px;
  font-size: 9.5px;
  line-height: 1.15;
  color: #7b7f87;
  pointer-events: none;      /* 就是个装饰，别挡着列表的点击 */
  user-select: none;
  -webkit-user-select: none;
}
/* 只在通讯录这一页露出来（#view-wechat 的 class 是 view--app，别写成 view--wechat） */
#view-wechat.is-contacts .idxbar { display: flex; }

/* 通讯录里的行右边多留一点，别跟字母条挤在一起 */
#paneContacts .cell,
#paneContacts .list__item { padding-right: 26px; }

/* ★ 10-13：通讯录上面那 4 个（新的朋友 / 群聊 / 标签 / 公众号）的图标，
   一度跟下面的联系人头像一样大（46px / 行高 68px）。
   ★ 10-14 用户要求「小一点，现在的 0.7 倍左右，占的行数也少一点」：
   图标 46 → **32**（×0.7），圆角 / 间距等比缩，行高 68 → **52**。
   ⚠️ 联系人那边（`.list__ava` 46px / `.list__item`）不受影响，别跟着改。 */
#paneContacts .cell { min-height: 52px; }
#paneContacts .cell__icon {
  width: 32px; height: 32px;
  border-radius: 8px;
  margin-right: 11px;
}
.idxbar__ch { display: block; }

/* 联系人上面的那个字母分组标题 */
.idx-head {
  margin-top: 10px;
  padding: 4px 16px 4px;
  background: #f1f2f5;
  font-size: 12.5px;
  color: #7b7f87;
}

/* 带图标的行（发现页 / 我页） */
.cell__icon {
  flex: none;
  width: 24px; height: 24px;
  margin-right: 13px;
  border-radius: 6px;
}
.cell__label { flex: 1; }

.cell__arrow {
  flex: none;
  width: 8px; height: 8px;
  margin-left: 6px;
  border-right: 1.6px solid #c4c7ce;
  border-bottom: 1.6px solid #c4c7ce;
  transform: rotate(-45deg);
}

/* 「我」页顶部的资料卡 */
.me-head {
  display: flex;
  align-items: flex-start;
  gap: 15px;
  padding: 22px 18px 20px;
  background: #fff;
}
.me-head__ava {
  flex: none;
  width: 62px; height: 62px;
  border: 0;
  padding: 0;
  border-radius: 10px;
  overflow: hidden;
  background: #eceef2;
  cursor: pointer;
  transition: transform .14s ease;
}
.me-head__ava:active { transform: scale(.93); }
.me-head__ava img { width: 100%; height: 100%; object-fit: cover; display: block; }
.me-head__info { flex: 1; min-width: 0; padding-top: 1px; }
.me-head__name { font-size: 19px; font-weight: 600; line-height: 1.25; }
/* 微信号那一行：字比原来大一点，后面跟一个小笔图标（点了单独弹出「更换微信号」） */
.me-head__id {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 6px;
  font-size: 14.5px;
  color: #8a8f9c;
}
.me-head__idtext {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.me-head__edit {
  flex: none;
  width: 24px; height: 24px;
  border: 0; padding: 0;
  border-radius: 50%;
  background: #f2f3f5;
  color: #8a8f9c;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform .14s ease, background .16s ease;
}
.me-head__edit:active { transform: scale(.9); background: #e9eaee; }
.me-head__chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.me-chip {
  display: inline-flex;
  align-items: center;
  height: 25px;
  padding: 0 11px;
  border-radius: 13px;
  border: 1px solid #e3e5ea;
  background: #fafafc;
  font-size: 12.5px;
  color: #5a5f6b;
}
.me-head__qr { flex: none; margin-top: 4px; color: #b6bac2; display: flex; }

/* 个性签名那一行 */
.cell.sig { min-height: 46px; }
.sig__text {
  flex: 1;
  font-size: 14px;
  color: #5a5f6b;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sig__text.is-empty { color: #b6bac2; }

/* ---------------- 通用选择弹层：换头像 / 换朋友圈封面 / 换个性签名 / 换微信号 ----------------
   ★ 10-14 照参考图重做成 iOS 风（旧的灰标题条 + 微信绿勾 + 白底黑字取消键已删）：
     面板 = #f8f8fa + 顶部圆角 22 + 底部 12；
     头部 = 抓取条 36×5 + 居中标题 16/600 + 右上圆形关闭钮（30 圆，rgba(120,120,128,.22)）；
     格子 = 3 列（左右 18 / 间隙 12 / 宽 105 / 封面 3:2 圆角 10）；
     选中 = 外描边 3px #3483fc + 右下角蓝勾（23，白圈 2px）；
     取消 = 通栏蓝色实心（高 53 / 圆角 16 / 白字 17/500）。
   参考图弹层宽 607px ÷ 本机 375px = 0.618，下面数值都按这个换算。 */
.picker {
  position: absolute;
  inset: 0;
  z-index: 82;
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s ease, visibility .2s;
}
.picker.is-on { opacity: 1; visibility: visible; }
.picker__mask { position: absolute; inset: 0; background: rgba(0,0,0,.42); }

.picker__panel {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding-bottom: 30px;
  background: #f8f8fa;
  border-radius: 22px 22px 0 0;
  transform: translateY(101%);
  transition: transform .28s cubic-bezier(.22,.61,.36,1);
}
.picker.is-on .picker__panel { transform: none; }

.picker__grab {
  width: 36px; height: 5px;
  margin: 6px auto 0;
  border-radius: 3px;
  background: rgba(60,60,67,.28);
}

.picker__head {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  padding: 0 56px;
}
.picker__title {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .3px;
  color: #16171c;
}
.picker__close {
  position: absolute;
  right: 16px;
  top: 50%;
  width: 30px; height: 30px;
  margin-top: -15px;
  border: 0; padding: 0;
  border-radius: 50%;
  background: rgba(120,120,128,.22);
  color: #55575c;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background .15s ease;
}
.picker__close svg { width: 16px; height: 16px; display: block; }
.picker__close:active { background: rgba(120,120,128,.34); }

/* 选项区：内容多了整块滚（3 行头像 + 6 行微信号也装得下） */
.picker__body {
  max-height: 400px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.picker__list {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  padding: 14px 18px 0;
}

/* 弹层开着时，底部那条 home 小白条照 iOS 的规矩浮在面板上面。
   （它本来 z-index 70 在面板下面；点一下回桌面的动作在弹层上会变成怪状态，所以顺手关掉点击） */
.screen:has(.picker.is-on) .home-indicator {
  z-index: 90;
  pointer-events: none;
}

.picker__item {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  border: 0;
  padding: 0;
  border-radius: 50%;
  background: #e8e9ee;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform .14s ease;
}
.picker__item img {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
.picker__item:active { transform: scale(.95); }
/* 选中：3px 描边画在格子**外面**（不动图片尺寸、不挤压邻居） */
.picker__item.is-on { box-shadow: 0 0 0 3px #3483fc; }
/* 右下角蓝勾 */
.picker__item.is-on::after {
  content: "";
  position: absolute;
  right: -1px; bottom: -1px;
  width: 23px; height: 23px;
  border-radius: 50%;
  background: #3483fc;
  box-shadow: 0 0 0 2px rgba(255,255,255,.92);
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23fff'%3E%3Cpath d='M9.6 16.7 5.3 12.4l-1.5 1.5 5.8 5.8L21.2 8.1l-1.5-1.5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 13px 13px;
}

/* 换封面：长方形（3:2），勾往里收一点别压到外描边 */
.picker__list.is-rect .picker__item {
  aspect-ratio: 3 / 2;
  border-radius: 10px;
}
.picker__list.is-rect .picker__item.is-on::after { right: 3px; bottom: 3px; }

/* ★ 10-14 换背景：只有几张图，所以**2 列、每张更大**（用户：「面积稍微大一点」）。
   形状 = 圆角矩形（16:10），不是换头像那种正圆。 */
.picker__list.is-wide { grid-template-columns: repeat(2, 1fr); }
.picker__list.is-wide .picker__item {
  aspect-ratio: 16 / 10;
  border-radius: 12px;
}
.picker__list.is-wide .picker__item.is-on::after { right: 4px; bottom: 4px; }

/* ★ 10-14 换壁纸：也是 2 列，但壁纸是竖图，所以格子比「换背景」再**高一些**
   （3:4，换背景是 16:10）。只有 4 张，两行刚好装下，所以这层把限高一起放宽。 */
.picker__list.is-tall { grid-template-columns: repeat(2, 1fr); }
.picker__list.is-tall .picker__item {
  aspect-ratio: 3 / 4;
  border-radius: 12px;
}
.picker__list.is-tall .picker__item.is-on::after { right: 4px; bottom: 4px; }
.picker__body:has(.picker__list.is-tall) { max-height: 474px; }

/* 换个性签名 / 换微信号：文字选项，一行一条，白色卡片分组（iOS 分组列表） */
.picker__list.is-text { display: block; }
.picker__list.is-text .picker__item {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 52px;
  aspect-ratio: auto;
  padding: 12px 46px;
  border-radius: 0;
  background: #fff;
  text-align: center;
  box-shadow: inset 0 -1px 0 #ececf0;
}
.picker__list.is-text .picker__item:first-child { border-radius: 12px 12px 0 0; }
.picker__list.is-text .picker__item:last-child {
  border-radius: 0 0 12px 12px;
  box-shadow: none;
}
.picker__list.is-text .picker__item:only-child { border-radius: 12px; }
.picker__list.is-text .picker__item:active { transform: none; background: #f4f5f7; }
.picker__list.is-text .picker__item.is-on { box-shadow: inset 0 -1px 0 #ececf0; }
.picker__list.is-text .picker__item.is-on:last-child { box-shadow: none; }
/* 文字行的勾挂在右边中间（不是右下角那个位置） */
.picker__list.is-text .picker__item.is-on::after {
  right: 16px;
  top: 50%;
  bottom: auto;
  margin-top: -11px;
  width: 22px; height: 22px;
  box-shadow: none;
  background-size: 12px 12px;
}
.picker__label {
  font-size: 14.5px;
  line-height: 1.45;
  color: #16171c;
  word-break: break-word;
}

/* 底部「取消」：通栏蓝色实心 */
.picker__cancel {
  display: block;
  width: calc(100% - 36px);
  height: 53px;
  margin: 18px auto 0;
  padding: 0;
  border: 0;
  border-radius: 16px;
  background: #3483fc;
  color: #fff;
  font-family: inherit;
  font-size: 17px;
  font-weight: 500;
  letter-spacing: .5px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background .16s ease, transform .12s ease;
}
.picker__cancel:active { background: #2b74e6; transform: scale(.985); }

/* ---------------- 游戏难度弹层（10-14 改的苹果风那版） ----------------
   比上面的通用 picker 多三样：每档一个彩色圆图标、名字下面一行灰说明、选中打勾。
   文案全在「文案」表（难度弹窗标题 / 难度弹窗说明 / 难度弹窗取消键
   + 游戏难度1/2/3 + 游戏难度说明1/2/3），见 xlsx2data.py 的 build_difficulty()。
   ★ 尺寸是照参考图量的（参考图弹层宽 592px ÷ 本机 375px = 0.633）。 */
.diffpick {
  position: absolute;
  inset: 0;
  z-index: 83;
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s ease, visibility .2s;
}
.diffpick.is-on { opacity: 1; visibility: visible; }
.diffpick__mask { position: absolute; inset: 0; background: rgba(0,0,0,.42); }

.diffpick__panel {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding-bottom: 12px;
  border-radius: 22px 22px 0 0;
  /* iOS 26 那层磨砂玻璃 —— 跟「结算前提醒」的 .dialog.is-ask 一个路子，别退回纯白 */
  background: linear-gradient(180deg, rgba(255,255,255,.94), rgba(255,255,255,.86));
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  box-shadow:
    inset 0 .5px 0 rgba(255,255,255,.9),
    0 -14px 40px rgba(8,14,30,.20);
  transform: translateY(101%);
  transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.diffpick.is-on .diffpick__panel { transform: none; }

/* 顶部那个小灰条 */
.diffpick__grab {
  width: 36px; height: 5px;
  margin: 6px auto 0;
  border-radius: 3px;
  background: rgba(60,60,67,.20);
}

.diffpick__head { padding: 6px 22px 4px; text-align: center; }
.diffpick__title {
  font-size: 19px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: .2px;
  color: #1c1c1e;
}
.diffpick__sub {
  margin-top: 5px;
  font-size: 13.5px;
  line-height: 1.35;
  color: #8a8a8e;
}
.diffpick__sub:empty { display: none; }

.diffpick__list { padding: 12px 12px 2px; }

.dprow {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 66px;
  padding: 10px 14px;
  border: 0;
  border-radius: 16px;
  background: transparent;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .16s ease;
}
/* 行之间的细分隔线：从文字左边起（= 图标 38 + 间距 12 + 内边距 14 = 64），不走满 */
.dprow + .dprow::before {
  content: '';
  position: absolute;
  left: 64px; right: 2px; top: 0;
  height: .5px;
  background: rgba(60,60,67,.16);
}
.dprow:active { background: rgba(120,120,128,.10); }
.dprow.is-on { background: rgba(52,199,89,.11); }

.dprow__ico {
  flex: none;
  width: 38px; height: 38px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
.dprow__txt { display: flex; flex-direction: column; min-width: 0; }
.dprow__name {
  font-size: 17px;
  line-height: 1.2;
  color: #1c1c1e;
}
.dprow__desc {
  margin-top: 2px;
  font-size: 13.5px;
  line-height: 1.3;
  color: #8a8a8e;
}
.dprow__check {
  flex: none;
  margin-left: auto;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: #34c759;
  display: flex; align-items: center; justify-content: center;
  opacity: 0;
}
.dprow.is-on .dprow__check { opacity: 1; }

.diffpick__cancel {
  display: block;
  width: calc(100% - 40px);
  height: 52px;
  margin: 6px auto 0;
  padding: 0;
  border: 0;
  border-radius: 15px;
  background: #eeedf2;
  color: #007aff;
  font-family: inherit;
  font-size: 19px;
  font-weight: 500;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background .16s ease, transform .12s ease;
}
.diffpick__cancel:active { background: #e4e4ea; transform: scale(.985); }

/* ---------------- 存档 / 读档 弹层（10-15，壳子照「游戏难度」那层来） ---------------- */
.savepick {
  position: absolute;
  inset: 0;
  z-index: 83;
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s ease, visibility .2s;
}
.savepick.is-on { opacity: 1; visibility: visible; }
.savepick__mask { position: absolute; inset: 0; background: rgba(0,0,0,.42); }
.savepick__panel {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding-bottom: 12px;
  border-radius: 22px 22px 0 0;
  background: linear-gradient(180deg, rgba(255,255,255,.94), rgba(255,255,255,.86));
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  box-shadow:
    inset 0 .5px 0 rgba(255,255,255,.9),
    0 -14px 40px rgba(8,14,30,.20);
  transform: translateY(101%);
  transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.savepick.is-on .savepick__panel { transform: none; }
.savepick__grab {
  width: 36px; height: 5px;
  margin: 6px auto 0;
  border-radius: 3px;
  background: rgba(60,60,67,.20);
}
.savepick__head { padding: 6px 22px 4px; text-align: center; }
.savepick__title {
  font-size: 19px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: .2px;
  color: #1c1c1e;
}
.savepick__sub { margin-top: 5px; font-size: 13.5px; line-height: 1.35; color: #8a8a8e; }
.savepick__sub:empty { display: none; }

/* 那串码：等宽字、能选中（★ 全站禁选在这里必须放行，不然复制不了） */
.savepick__area {
  display: block;
  width: calc(100% - 40px);
  height: 110px;
  margin: 12px auto 0;
  padding: 12px 13px;
  box-sizing: border-box;
  border: 0;
  border-radius: 14px;
  background: #f2f2f7;
  box-shadow: inset 0 0 0 .5px rgba(60,60,67,.14);
  color: #1c1c1e;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
  line-height: 1.5;
  word-break: break-all;
  resize: none;
  outline: none;
  -webkit-user-select: text;
  user-select: text;
}
.savepick__area::placeholder { color: #a5a5aa; }

.savepick__acts {
  display: flex;
  gap: 10px;
  width: calc(100% - 40px);
  margin: 10px auto 0;
}
.savepick__btn {
  flex: 1;
  height: 50px;
  border: 0;
  border-radius: 15px;
  background: #eeedf2;
  color: #1c1c1e;
  font-family: inherit;
  font-size: 17px;
  font-weight: 500;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background .16s ease, transform .12s ease;
}
.savepick__btn:active { background: #e4e4ea; transform: scale(.985); }
.savepick__btn.is-primary {
  background: linear-gradient(180deg, #4a90ff 0%, #2a6ef0 100%);
  color: #fff;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.36),
    0 6px 16px rgba(42,110,240,.34);
}
.savepick__btn.is-primary:active { background: linear-gradient(180deg, #3f84f5 0%, #2565e2 100%); }

.savepick__cancel {
  display: block;
  width: calc(100% - 40px);
  height: 52px;
  margin: 8px auto 0;
  padding: 0;
  border: 0;
  border-radius: 15px;
  background: #eeedf2;
  color: #007aff;
  font-family: inherit;
  font-size: 19px;
  font-weight: 500;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background .16s ease, transform .12s ease;
}
.savepick__cancel:active { background: #e4e4ea; transform: scale(.985); }

/* ---------------- 朋友圈 ---------------- */
.view--moments { background: #fff; }

/* 朋友圈的返回：跟顶栏那套不一样（这里叠在封面照片上，深色半透明圆）。
   ★ 10-14 跟着顶栏一起走 34 → 51 → **41**，阴影保留。 */
.moments-back {
  position: absolute;
  top: calc(var(--statusbar-h) + 4px);
  left: 12px;
  z-index: 20;
  width: 41px; height: 41px;
  border: 0; padding: 0;
  border-radius: 50%;
  background: rgba(0,0,0,.26);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .30);
}
.moments-back:active { background: rgba(0,0,0,.4); }

.moments-cover { height: 232px; background: #22304a; cursor: pointer; }
.moments-cover img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transition: opacity .16s ease;
}
.moments-cover:active img { opacity: .82; }

.moments-me {
  position: relative;
  display: flex;
  justify-content: flex-end;
  align-items: flex-end;
  gap: 12px;
  height: 44px;
  padding: 0 18px;
  background: #fff;
}
.moments-me__name {
  font-size: 16.5px;
  font-weight: 600;
  padding-bottom: 5px;
}
.moments-me__ava {
  width: 68px; height: 68px;
  border-radius: 10px;
  border: 3px solid #fff;
  object-fit: cover;
  transform: translateY(-34px);
  box-shadow: 0 3px 10px rgba(0,0,0,.18);
}

.moments-list { background: #fff; padding-bottom: 26px; }

.mom {
  display: flex;
  gap: 11px;
  padding: 14px 16px;
  border-bottom: 1px solid #f3f4f6;
}
.mom__ava {
  flex: none;
  width: 40px; height: 40px;
  border-radius: 6px;
  object-fit: cover;
  background: #eceef2;
}
.mom__main { flex: 1; min-width: 0; }
.mom__name { font-size: 14.5px; font-weight: 600; color: #576b95; }
.mom__text {
  margin: 5px 0 0;
  font-size: 14.5px;
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
}

.mom__imgs {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
  margin-top: 8px;
  max-width: 228px;
}
.mom__imgs[data-n="1"] { grid-template-columns: 1fr; max-width: 152px; }
.mom__imgs[data-n="2"] { grid-template-columns: repeat(2, 1fr); max-width: 160px; }
.mom__imgs img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: 4px;
  display: block;
  background: #eceef2;
  cursor: pointer;
}
.mom__imgs[data-n="1"] img { aspect-ratio: 4 / 3; }

.mom__time { display: block; margin-top: 8px; font-size: 12px; color: #9a9a9a; }

/* 发布时间那一行的右边：喜爱按钮（别人的）/ 三个点（自己的） */
.mom__foot {
  display: flex;
  align-items: center;
  min-height: 26px;
  margin-top: 7px;
}
.mom__time { flex: 1; margin-top: 0; }

.mom__like {
  flex: none;
  border: 0;
  padding: 3px 8px;
  margin-right: -8px;
  border-radius: 4px;
  background: none;
  font-family: inherit;
  font-size: 12.5px;
  color: #9a9a9a;
  cursor: pointer;
  transition: color .15s ease;
}
.mom__like:active { background: rgba(0,0,0,.05); }
.mom__like.is-on { color: #fa5151; }

.list__more.mom__more {
  flex: none;
  width: 26px; height: 26px;
  margin-left: 0;
  margin-right: -4px;
}

.mom__likes {
  margin-top: 8px;
  padding: 6px 9px;
  border-radius: 4px;
  background: #f7f7f9;
  font-size: 13px;
  line-height: 1.6;
  color: #576b95;
  word-break: break-word;
}
.mom__likes span { color: #9a9a9a; margin-right: 4px; }

/* ---------------- 支付 ---------------- */
.pay-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 14px 14px 4px;
  padding: 20px 18px;
  border-radius: 14px;
  background: linear-gradient(135deg, #2fb653 0%, #0f8a48 100%);
  color: #fff;
  box-shadow: 0 8px 20px -10px rgba(17,145,76,.7);
}
.pay-card b { font-size: 18px; letter-spacing: .5px; }
.pay-card span { font-size: 12px; opacity: .82; }

/* 自动续费的每一项 */
.sub {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 16px;
  background: #fff;
  border-bottom: 1px solid var(--line);
  cursor: pointer;
}
.sub:last-child { border-bottom: 0; }
.sub:active { background: #f2f2f5; }

.sub__icon {
  flex: none;
  width: 38px; height: 38px;
  border-radius: 9px;
  object-fit: cover;
}
.sub__main { flex: 1; min-width: 0; }
.sub__name { font-size: 15px; font-weight: 500; }
.sub__desc {
  margin-top: 3px;
  font-size: 12.5px;
  color: var(--ui-sub);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sub__right {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
}
.sub__status { font-size: 11.5px; color: var(--ui-sub); }
.sub__amount {
  font-size: 14px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.autopay-tip {
  padding: 12px 16px 2px;
  font-size: 12.5px;
  color: var(--ui-sub);
}

/* 底部标签栏 */
.tabbar {
  flex: none;
  display: grid;
  height: 58px;
  margin-bottom: 22px;
  align-items: center;
  text-align: center;
  background: #f7f7f7;
  border-top: 1px solid var(--line);
}
.tabbar--wechat { grid-template-columns: repeat(4, 1fr); }
.tabbar--photo  { grid-template-columns: repeat(2, 1fr); }
.tabbar__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  height: 100%;
  font-size: 12.5px;
  line-height: 1;
  color: #4f545c;
}
.tabbar__ico {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 25px;
  color: #4f545c;
}
.tabbar__ico svg { display: block; width: 26px; height: 24px; }

/* 底栏图标右上角的红色数字：这个页签里还有多少没做完
   （微信那四个：微信 / 通讯录 / 发现 / 我，数字怎么来的见 app.js 的 tabLeft()）
   位置挂在图标框上，别去挤标题；数字为 0 时加 .is-off 整个藏起来。 */
.tabbar__badge {
  position: absolute;
  /* ★ 10-13 第二次改（照参考图 SP_10.13_17.48.00 逐像素量的）：
     参考图里徽章基本「挂在图标右上角的外面」—— 只压住图标右边约 2px，
     不是压在图标头顶上。换算到这边（图标 26 宽 / 图形约 23 宽）：
       徽章左边 = 图形右边 - 2px  -> right: -16px
       徽章中线 = 图形顶部 + 3px  -> top: -2px
     圆角也往上抬到 8（约等于高的 47%，接近参考图那种圆滚滚的圆角矩形）。 */
  top: -2px;
  right: -16px;
  min-width: 20px;
  height: 17px;
  padding: 0 4.5px;
  border-radius: 8px;
  background: #fa5151;
  color: #fff;
  font-size: 10.5px;
  font-weight: 600;
  line-height: 17px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  pointer-events: none;
}
.tabbar__badge.is-off { display: none; }
/* 只有微信这一栏改成「图标在上、小字在下」的样式 */
.tabbar--wechat .tabbar__label { font-size: 11.5px; letter-spacing: .2px; }
.tabbar__item.is-on { color: #07C160; font-weight: 600; }
.tabbar__item.is-on .tabbar__ico { color: #07C160; }

/* 相册这一栏也是「图标在上、小字在下」，但选中色跟着 iOS 相册走蓝的 */
.tabbar--photo .tabbar__label { font-size: 11.5px; letter-spacing: .2px; }
.tabbar--photo .tabbar__ico svg { width: 25px; height: 23px; }
.tabbar--photo .tabbar__item.is-on { color: #007AFF; }
.tabbar--photo .tabbar__item.is-on .tabbar__ico { color: #007AFF; }

/* ---------------- 底部横条 ---------------- */
.home-indicator {
  position: absolute;
  left: 50%;
  bottom: 7px;
  transform: translateX(-50%);
  width: 118px; height: 5px;
  border-radius: 3px;
  background: rgba(0,0,0,.28);
  z-index: 70;
  cursor: pointer;
}
.view--home.is-active ~ .home-indicator { background: rgba(255,255,255,.6); }

/* ---------------- 支付密码键盘 ---------------- */
.keypad {
  position: absolute;
  inset: 0;
  z-index: 80;
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s ease, visibility .2s;
}
.keypad.is-on { opacity: 1; visibility: visible; }

.keypad__mask { position: absolute; inset: 0; background: rgba(0,0,0,.35); }

.keypad__panel {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 12px 6px 52px;
  border-radius: 22px 22px 0 0;
  /* 上浅下深的一点点渐变，跟参考图一样 */
  background: linear-gradient(180deg, #f8f7fb 0%, #f1f0f5 46%, #e9e8ee 100%);
  transform: translateY(101%);
  transition: transform .26s cubic-bezier(.22,.61,.36,1);
}
.keypad.is-on .keypad__panel { transform: none; }

/* 面板自带一条 home 指示条（盖住了桌面上那条） */
.keypad__panel::after {
  content: "";
  position: absolute;
  left: 50%; bottom: 7px;
  width: 136px; height: 6px;
  margin-left: -68px;
  border-radius: 3px;
  background: #0b0b0c;
}

.keypad__head {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 38px;
}
.keypad__title {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: .3px;
  color: #111216;
}
.keypad__cancel {
  position: absolute;
  left: 4px; top: 50%;
  width: 34px; height: 34px;
  margin-top: -17px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0; padding: 0;
  background: none;
  color: #4a5c94;
  cursor: pointer;
}
.keypad__cancel svg { display: block; }
.keypad__cancel:active { opacity: .45; }

/* 副标题：正常是「关闭「xxx」」，密码错的时候这行变红当提示用 */
.keypad__subject {
  min-height: 19px;
  margin-top: 6px;
  text-align: center;
  font-size: 13.5px;
  line-height: 19px;
  color: #8a8f9c;
}
.keypad__subject.is-err { color: #e64340; }

/* 密码格子：个数 = 要输几位，整体居中 */
.keypad__dots {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: 15px;
}
.keypad__dots i {
  position: relative;
  width: 40px;
  height: 38px;
  border-radius: 9px;
  background: #fff;
  box-shadow: 0 1px 1.5px rgba(24,26,38,.07);
}
.keypad__dots i.is-on::after {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  width: 9px; height: 9px;
  margin: -4.5px 0 0 -4.5px;
  border-radius: 50%;
  background: #16171c;
}
.keypad__dots.is-shake { animation: pp-shake .42s ease; }
@keyframes pp-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-8px); }
  40% { transform: translateX(7px); }
  60% { transform: translateX(-5px); }
  80% { transform: translateX(3px); }
}

.keypad__keys {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px 11px;
  margin-top: 21px;
}
.keypad__keys button {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 43px;
  border: 0;
  padding: 0;
  border-radius: 11px;
  background: #fff;
  box-shadow: 0 1px 1.5px rgba(24,26,38,.06);
  color: #111216;
  font-family: inherit;
  font-size: 23px;
  font-weight: 400;
  cursor: pointer;
  transition: background .12s ease;
}
.keypad__keys button:active { background: #e6e6ec; }
.keypad__keys button.is-fn { color: #16171c; }
.keypad__keys button.is-fn svg { display: block; }
.keypad__keys button.is-blank {
  background: none;
  box-shadow: none;
  cursor: default;
}

/* 已关闭的订阅 */
.sub.is-closed { opacity: .55; }
.sub.is-closed .sub__name { text-decoration: line-through; }

/* ---------------- 确认弹窗 ---------------- */
.dialog {
  position: absolute;
  inset: 0;
  z-index: 82;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity .18s ease, visibility .18s;
}
.dialog.is-on { opacity: 1; visibility: visible; }
.dialog__mask { position: absolute; inset: 0; background: rgba(0,0,0,.4); }

.dialog__box {
  position: relative;
  width: 274px;
  border-radius: 14px;
  overflow: hidden;
  background: #fff;
  transform: scale(.94);
  transition: transform .18s ease;
}
.dialog.is-on .dialog__box { transform: none; }

.dialog__body { padding: 22px 20px 18px; text-align: center; }
.dialog__title { display: block; font-size: 16px; font-weight: 600; }
.dialog__desc {
  margin: 8px 0 0;
  font-size: 13.5px;
  line-height: 1.62;
  color: var(--ui-sub);
  white-space: pre-line;      /* 文案里的换行会保留 */
}
.dialog__desc:empty { display: none; }

.dialog__foot { display: flex; border-top: 1px solid var(--line); }
.dialog__btn {
  flex: 1;
  height: 50px;
  border: 0;
  background: #fff;
  color: #5b5f66;
  font-family: inherit;
  font-size: 16.5px;
  letter-spacing: .5px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background .16s ease;
}
.dialog__btn + .dialog__btn { border-left: 1px solid var(--line); }
.dialog__btn:active { background: #f2f2f5; }
.dialog__btn.is-ok { color: #07c160; font-weight: 600; }
.dialog__btn.is-danger { color: #e64340; font-weight: 600; }

/* iOS 那版确认框（`showConfirm({ ios: true })`）——
   取消用系统蓝、危险项用系统红，标题也稍微大一点。
   只有需要「长得像苹果」的地方才挂这个类，别默认套上。 */
.dialog.is-ios .dialog__title { font-size: 17px; }
/* 卡片比默认宽一点：那句「并移至「最近删除」相簿，保留 30 天。」正好一行装下，不折成三行 */
.dialog.is-ios .dialog__box { width: 292px; }
.dialog.is-ios .dialog__btn { color: #007aff; font-size: 17px; }
.dialog.is-ios .dialog__btn.is-danger { color: #ff3b30; font-weight: 500; }
.dialog.is-ios .dialog__btn.is-ok { font-weight: 500; }

/* ---------------- 相册问答（进「出租」前先答对） ----------------
   复用 .dialog 这层壳，只把里边换成「蓝问号 + 题目 + 两列选项」。
   配色照参考图：浅蓝图标、浅灰圆角选项、选中的变蓝；底部两个按钮
   是分开的圆角块（跟普通确认框那条通栏分割线不一样，所以这里覆盖掉）。 */
.dialog.is-quiz .dialog__box { width: 300px; border-radius: 22px; }
.dialog.is-quiz .dialog__body { padding: 26px 18px 16px; }

.quiz__badge {
  width: 46px;
  height: 46px;
  margin: 0 auto 12px;
  border-radius: 50%;
  background: #e3edff;
  color: #3b7cff;
  font-size: 24px;
  font-weight: 700;
  line-height: 46px;
  text-align: center;
}
.quiz__badge[hidden] { display: none; }

.dialog.is-quiz .dialog__title { font-size: 17px; }
.dialog.is-quiz .dialog__desc {
  margin-top: 6px;
  font-size: 13px;
  color: var(--ui-sub);
}

.quiz__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-top: 18px;
}
.quiz__grid[hidden] { display: none; }

.quiz__opt {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 46px;
  padding: 0 14px;
  border: 1px solid transparent;
  border-radius: 12px;
  background: #f4f5f7;
  color: var(--ui);
  font: inherit;
  font-size: 14.5px;
  text-align: left;
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s;
}
.quiz__radio {
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  border: 1.5px solid #c9ccd4;
  border-radius: 50%;
  background: #fff;
}
.quiz__label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.quiz__opt.is-on {
  background: #e8f1ff;
  border-color: #3b7cff;
  color: #2f6fe4;
}
.quiz__opt.is-on .quiz__radio {
  border-color: #3b7cff;
  background: #3b7cff;
  box-shadow: inset 0 0 0 2.5px #e8f1ff;
}

.dialog.is-quiz .dialog__foot {
  border-top: 0;
  gap: 12px;
  padding: 4px 18px 18px;
}
.dialog.is-quiz .dialog__btn {
  height: 44px;
  border-radius: 12px;
  background: #f4f5f7;
  color: #4a4d55;
  font-size: 15px;
}
.dialog.is-quiz .dialog__btn + .dialog__btn { border-left: 0; }
.dialog.is-quiz .dialog__btn.is-ok {
  background: #3b7cff;
  color: #fff;
  font-weight: 600;
}
.dialog.is-quiz .dialog__btn:active { background: #eceef2; }
.dialog.is-quiz .dialog__btn.is-ok:active { background: #2f6fe4; }

/* ---------------- 结算前的提醒（总进度没到 95%，v261；玻璃质感 v262） ----------------
   照参考图：上面一张「纸 + 蓝感叹号」的图标，中间两行字（粗标题 + 灰说明），
   底下两颗并排药丸按钮 —— ★ 左边那颗（返回）是蓝的、右边（现在就看）是浅灰的，
   跟别的弹窗「主按钮在右」正好反着，别顺手改过来。
   图标只在 is-ask 这一版露出来（平时 hidden 由 CSS 控制，见 .ask__badge）。

   ★ 「层次」是四层摞出来的，少一层就不像玻璃了：
     ① 卡片本体 = 半透明白底（.80 左右）+ backdrop 模糊，背后桌面透出来但糊掉；
     ② 0.5px 冷白外描边 + 顶缘一道亮线（inset 高光）= 玻璃的「厚度」；
     ③ 底下两层投影：远的大扩散（悬起来）+ 近的贴地（贴住）；
     ④ 两颗按钮各自带内高光/彩色投影，蓝的那颗像一颗实体药丸。
   ⚠️ 卡片里的字号没动（跟 v261 一致），只改材质。 */
.dialog.is-ask .dialog__mask { background: rgba(6,12,26,.44); }

.dialog.is-ask .dialog__box {
  width: 292px;
  border-radius: 26px;
  background: linear-gradient(180deg, rgba(255,255,255,.84) 0%, rgba(255,255,255,.72) 100%);
  -webkit-backdrop-filter: blur(22px) saturate(180%);
  backdrop-filter: blur(22px) saturate(180%);
  box-shadow:
    0 0 0 .5px rgba(255,255,255,.46),                 /* 玻璃外圈的细亮边 */
    0 22px 54px rgba(8,14,30,.36),                    /* 远投影：把卡片「抬」起来 */
    0 4px 12px rgba(8,14,30,.22);                     /* 近投影：贴地那一下 */
}
/* 顶缘亮线 + 内壁高光 + 底缘一丝暗 —— 玻璃的厚度感全靠这一层 */
.dialog.is-ask .dialog__box::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.95),
    inset 0 0 0 .5px rgba(255,255,255,.44),
    inset 0 -18px 28px -22px rgba(255,255,255,.55),
    inset 0 -1px 1px rgba(0,0,0,.05);
}

.dialog.is-ask .dialog__body { padding: 16px 22px 16px; }

/* ★ 图标整块放大到 72px（原来 58 太小，跟参考图的比例对不上：
   参考图里「文档外框高 ÷ 卡宽」= 0.151，58px 那版只有 0.126）。
   里面那条注释写了每个零件的比例，改大小只动这里，别去改 SVG。 */
.ask__badge { display: none; width: 72px; height: 72px; margin: 0 auto 9px; }
.dialog.is-ask .ask__badge { display: block; }
.ask__badge svg { display: block; width: 100%; height: 100%; }

.dialog.is-ask .dialog__title {
  font-size: 17.5px;
  font-weight: 700;
  color: #111318;                                   /* 玻璃上要够黑才压得住 */
}
.dialog.is-ask .dialog__desc {
  margin-top: 7px;
  font-size: 13.5px;
  color: rgba(60,60,67,.62);                        /* iOS 次级文字色 */
}

.dialog.is-ask .dialog__foot {
  border-top: 0;
  gap: 10px;
  padding: 4px 18px 12px;
  flex-direction: row-reverse;   /* 10-15 定版：「返回」在右、「现在就看」在左（只这一层反，别的弹窗不动） */
}
.dialog.is-ask .dialog__btn {
  height: 46px;
  border-radius: 23px;
  background: rgba(120,120,128,.16);                /* 次级 = 半透明灰玻璃 */
  color: #1c1c1e;
  font-size: 15.5px;
  font-weight: 600;
  box-shadow: inset 0 0 0 .5px rgba(255,255,255,.5);
  transition: background .16s ease, transform .12s ease;
}
.dialog.is-ask .dialog__btn + .dialog__btn { border-left: 0; }
.dialog.is-ask .dialog__btn:active { background: rgba(120,120,128,.28); transform: scale(.975); }
.dialog.is-ask .dialog__btn.is-ok { background: rgba(120,120,128,.16); color: #1c1c1e; font-weight: 600; }
.dialog.is-ask .dialog__btn.is-ok:active { background: rgba(120,120,128,.28); }
/* ⚠️ `[data-dialog-cancel]` 连蒙层一起选中了（蒙层上也有这个属性），
   必须 `:not(.dialog__mask)` 挑出真正那颗按钮 —— 不然整屏都变蓝。 */
.dialog.is-ask [data-dialog-cancel]:not(.dialog__mask) {
  background: linear-gradient(180deg, #4a90ff 0%, #2a6ef0 100%);
  color: #fff;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.36),
    0 6px 16px rgba(42,110,240,.40);
}
.dialog.is-ask [data-dialog-cancel]:not(.dialog__mask):active {
  background: linear-gradient(180deg, #3f84f5 0%, #2565e2 100%);
  transform: scale(.975);
}
/* 满 100% 那层（.is-full）：跟上面反过来 —— 「查看」蓝色在右、「返回」灰在左。
   HTML 顺序本来就是 取消在左、确定在右，所以排回去、再把颜色对调就行。 */
.dialog.is-ask.is-full .dialog__foot { flex-direction: row; }
.dialog.is-ask.is-full [data-dialog-cancel]:not(.dialog__mask) {
  background: rgba(120,120,128,.16);
  color: #1c1c1e;
  box-shadow: inset 0 0 0 .5px rgba(255,255,255,.5);
}
.dialog.is-ask.is-full [data-dialog-cancel]:not(.dialog__mask):active {
  background: rgba(120,120,128,.28);
  transform: scale(.975);
}
.dialog.is-ask.is-full .dialog__btn.is-ok {
  background: linear-gradient(180deg, #4a90ff 0%, #2a6ef0 100%);
  color: #fff;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.36),
    0 6px 16px rgba(42,110,240,.40);
}
.dialog.is-ask.is-full .dialog__btn.is-ok:active {
  background: linear-gradient(180deg, #3f84f5 0%, #2565e2 100%);
}

/* ---------------- 底部选项菜单 ---------------- */
.sheet {
  position: absolute;
  inset: 0;
  z-index: 82;
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s ease, visibility .2s;
}
.sheet.is-on { opacity: 1; visibility: visible; }
.sheet__mask { position: absolute; inset: 0; background: rgba(0,0,0,.35); }

.sheet__panel {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding-bottom: 10px;
  transform: translateY(101%);
  transition: transform .28s cubic-bezier(.22,.61,.36,1);
}
.sheet.is-on .sheet__panel { transform: none; }

.sheet__title {
  padding: 15px 20px;
  text-align: center;
  font-size: 13px;
  letter-spacing: .5px;
  color: var(--ui-sub);
  background: #f7f7f9;
  border-radius: 16px 16px 0 0;
}
.sheet__title:empty { display: none; }

.sheet__list { background: #fff; }
.sheet__item {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 54px;
  font-size: 16.5px;
  border-bottom: 1px solid var(--line);
  cursor: pointer;
}
.sheet__item:last-child { border-bottom: 0; }
.sheet__item:active { background: #f2f2f5; }
.sheet__item.is-danger { color: #e64340; }

/* 底部的「取消」：整条白底、居中、不描边 —— sheet 和 picker 共用 */
.sheet__cancel {
  display: block;
  width: calc(100% - 20px);
  height: 54px;
  margin: 10px auto 0;
  padding: 0;
  border: 0;
  border-radius: 14px;
  background: #fff;
  color: #16171c;
  font-family: inherit;
  font-size: 17px;
  font-weight: 400;
  letter-spacing: .5px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background .16s ease, transform .12s ease;
}
.sheet__cancel:active { background: #ececf0; transform: scale(.985); }

/* ★ 10-12：「已删除的联系人变灰」那套（.list__item.is-cleared）已经删掉 ——
   删联系人就是整个人从列表里消失，不再有变灰的中间态。
   .list__more（三个点）还有别的页在用（朋友圈 / 收藏 / 个性签名），保留。 */

.list__more {
  flex: none;
  width: 32px; height: 32px;
  margin-left: 4px;
  border: 0; padding: 0;
  border-radius: 50%;
  background: transparent;
  color: #b6bac2;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.list__more svg { fill: currentColor; }
.list__more:active { background: rgba(0,0,0,.07); }

/* 相册一级：大图标卡片 */
.album-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  padding: 14px 14px 8px;
}

.album-card {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  border: 0;
  padding: 0;
  border-radius: 12px;
  overflow: hidden;
  background: #d9dce2;
  cursor: pointer;
  transition: transform .16s ease;
}
.album-card img { width: 100%; height: 100%; object-fit: cover; display: block; }
.album-card:active { transform: scale(.972); }

/* ★ 10-14 底下那排**装饰用的假相册**（Excel「相册」表 D/E 列）：
   就是几个「快做好了」的占位 —— 封面糊掉 + 稍微压暗，名字和张数照常写。
   模糊只加在 <img> 上（文字不受影响）；放大 1.18 是为了把糊出来的
   透明边顶到卡片外面（卡片自己 overflow:hidden 会裁掉）。
   它们点不进去（app.js 弹「正在制作中」那句），所以不给按下的缩放反馈。 */
.album-card--soon {
  cursor: default;
  /* ★ 10-14 用户要求：假相册高度压到真卡片的 **3/5**，拉成横着的长方形。
     真卡片是 1/1；高 = 宽 × 0.6 → 宽高比 5/3。 */
  aspect-ratio: 5 / 3;
  border-radius: 10px;
}
.album-card--soon:active { transform: none; }
/* 卡片矮了，底部那块渐变的留白也跟着收一点，免得文字被挤在中间 */
.album-card--soon .album-card__shade { padding: 15px 10px 8px; }
.album-card__blur { filter: blur(12px); transform: scale(1.18); }
.album-card--soon .album-card__shade {
  background: linear-gradient(transparent, rgba(0, 0, 0, .55));
}

.album-card__shade {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 22px 11px 9px 11px;
  text-align: left;
  color: #fff;
  background: linear-gradient(transparent, rgba(0,0,0,.66));
}
.album-card__name { display: block; font-size: 13.5px; font-weight: 600; }
.album-card__num { display: block; font-size: 11px; opacity: .82; margin-top: 1px; }

/* 卡片右上角那一簇小标记：要答题的锁 + 「还剩几张要删」的角标。
   两个都在 `right:10px / top:9px` 这一行里排（flex 竖着居中），
   所以角标宽一点窄一点都不会跟锁打架。两个都没有就不渲染这层。 */
.album-card__tags {
  position: absolute;
  top: 9px;
  right: 10px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 6px;
  pointer-events: none;
}

/* 「还剩几张要删」（10-11 改版，照参考图）：
   原来是右下角一块暗玻璃 + 发光的红数字，用户嫌丑、也不要红色。
   现在是右上角一颗灰毛玻璃胶囊 —— 左边一个白色图片小图标、右边白色数字，
   1px 浅边 + 内高光。高度 30px、圆角 8px（≈ 参考图 41px/10px 按卡片折算）。
   删光了就不渲染这个节点。 */
.album-card__dot {
  box-sizing: border-box;
  height: 24px;                     /* 10-11：用户嫌占比例太大，整体缩到 0.8 倍 */
  padding: 0 6.5px;
  display: flex;
  align-items: center;
  gap: 7px;
  border-radius: 6.5px;
  background: rgba(132, 129, 126, .44);
  border: 1px solid rgba(255, 255, 255, .42);
  -webkit-backdrop-filter: blur(13px) saturate(150%);
  backdrop-filter: blur(13px) saturate(150%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .26),
              0 2px 8px rgba(0, 0, 0, .18);
  color: #fff;
  pointer-events: none;
}
/* 那个图片小图标：白色圆角方块，中间用 evenodd 挖出「太阳 + 山」 */
.album-card__dot-ico { display: block; width: 12px; height: 9.6px; }
.album-card__dot-n {
  font-style: normal;
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: .2px;
}

/* 卡片右上角那把锁：这个相册要答题才能进、还没答对的时候才有。
   跟角标是一对（一个锁、一个数），排在同一行，答对就摘掉。 */
.album-card__lock {
  /* 跟着角标一起缩到 0.8 倍（26 → 21），不然锁比数字那块还大、主次颠倒 */
  width: 21px;
  height: 21px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 7px;
  background: linear-gradient(150deg, rgba(28, 28, 34, .56), rgba(28, 28, 34, .34));
  border: 1px solid rgba(255, 255, 255, .32);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
  backdrop-filter: blur(12px) saturate(160%);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .34), 0 2px 8px rgba(0, 0, 0, .18);
  pointer-events: none;
}
.album-card__lock svg { fill: currentColor; display: block; width: 11px; height: 11px; }

.album-card.is-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #e6e8ed;
}
.album-card.is-empty svg { fill: #b6bac2; }

/* ---------------- 照片放大 ---------------- */
.view--viewer { background: #0b0b0f; touch-action: pan-y; }

/* 上下两条黑色渐变：按钮浮在上面的地方压暗，免得照片白得扎眼 */
.view--viewer::before,
.view--viewer::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  z-index: 15;
  pointer-events: none;
}
.view--viewer::before {
  top: 0; height: 132px;
  background: linear-gradient(rgba(0,0,0,.58), rgba(0,0,0,.22) 58%, transparent);
}
.view--viewer::after {
  bottom: 0; height: 160px;
  background: linear-gradient(transparent, rgba(0,0,0,.26) 42%, rgba(0,0,0,.62));
}

.viewer__stage {
  position: relative;              /* 翻页时「幽灵」那张要绝对定位贴上去 */
  overflow: hidden;                /* 滑出去的那张别漏到屏幕外 */
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 照片尽量占满：左右不留边，上下只避开状态栏和底部那排按钮 */
  padding: var(--statusbar-h) 0 0;
  /* 横向手势归我们（拖着照片走），纵向留给浏览器 */
  touch-action: pan-y;
}
/* 翻页动画里那位「旧的」：盖在原图上，跟着一起滑出去。
   选择器要写两层，不然 `.viewer__stage img` 的 max-* 会盖过它，尺寸对不上 */
.viewer__stage .viewer__ghost {
  position: absolute;
  z-index: 5;
  margin: 0;
  max-width: none;
  max-height: none;
  object-fit: contain;
  pointer-events: none;
}
.viewer__stage img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
}
/* 大图页里的视频（私密空间那些 mp4）：能放、带原生控件 */
.viewer__stage video {
  max-width: 100%;
  max-height: 100%;
  background: #000;
  display: block;
}
/* 图片 / 视频二选一显示：hidden 一定要真的藏起来，
   不然两块会一起挤在中间那个 flex 里 */
#viewerImg[hidden],
#viewerVideo[hidden] { display: none; }

/* 顶栏两个圆按钮：左边返回（深色玻璃）、右边删除（浅色玻璃） */
.viewer__back,
.viewer__more,
.viewer__restore,
.viewer__del {
  position: absolute;
  top: calc(var(--statusbar-h) + 8px);
  z-index: 20;
  width: 44px; height: 44px;
  border: 0; padding: 0;
  border-radius: 50%;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  backdrop-filter: blur(12px) saturate(150%);
  -webkit-backdrop-filter: blur(12px) saturate(150%);
  transition: transform .14s ease, background .14s ease;
}
.viewer__back,
.viewer__more,
.viewer__restore,
.viewer__del {
  background: rgba(24, 24, 28, .44);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16);
}
.viewer__back { left: 14px; }
/* 顶栏右边那个主按钮：垃圾桶 / 回收站里的「复原」共用一个槽位 ——
   两个永远不会同时出现（回收站里不给「单独删除」，要清就整页「全部删除」）。
   44 → 66（×1.5）→ 56（×0.85），图标跟着缩；
   顶边往上收 6px（= 多出来的半高），跟返回保持同一条中心线。 */
.viewer__del,
.viewer__restore { right: 14px; width: 56px; height: 56px; top: calc(var(--statusbar-h) + 2px); }
.viewer__del svg,
.viewer__restore svg { width: 24px; height: 24px; }
.viewer__more { right: 14px; }
.viewer__back:active,
.viewer__more:active,
.viewer__restore:active,
.viewer__del:active { background: rgba(48, 48, 54, .66); transform: scale(.94); }
.viewer__more svg { fill: currentColor; }
.viewer__del svg,
.viewer__restore svg { fill: none; }

/* 被 `hidden` 藏起来的按钮别被 display:flex 顶回来 */
.viewer__back[hidden],
.viewer__more[hidden],
.viewer__restore[hidden],
.viewer__del[hidden] { display: none; }

/* 上一张 / 下一张：两个大圆按钮贴在底部两侧，计数浮在正中间 */
.viewer__bar {
  position: absolute;
  left: 48px; right: 48px;
  bottom: 32px;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.viewer__nav {
  width: 70px; height: 70px;
  flex: none;
  border: 0; padding: 0;
  border-radius: 50%;
  background: rgba(38, 38, 42, .46);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  backdrop-filter: blur(12px) saturate(150%);
  -webkit-backdrop-filter: blur(12px) saturate(150%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16);
  transition: opacity .18s ease, background .18s ease, transform .14s ease;
}
.viewer__nav svg { width: 31px; height: 31px; }
.viewer__nav:active { background: rgba(70, 70, 76, .60); transform: scale(.94); }
.viewer__nav.is-off { opacity: .22; pointer-events: none; }

.viewer__count {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  color: rgba(255,255,255,.86);
  font-size: 13.5px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: .6px;
  text-shadow: 0 1px 4px rgba(0,0,0,.5);
  pointer-events: none;
}

/* ---------------- 新的朋友 ---------------- */
.cell__badge {
  flex: none;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  margin-right: 8px;
  border-radius: 10px;
  background: #fa5151;
  color: #fff;
  font-size: 11.5px;
  line-height: 20px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.req {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  background: #fff;
  border-bottom: 1px solid var(--line);
}
.req:last-child { border-bottom: 0; }

.req__ava {
  flex: none;
  width: 52px; height: 52px;
  border-radius: 7px;
  object-fit: cover;
  background: #eceef2;
}
.req__main { flex: 1; min-width: 0; }
.req__name { font-size: 14.5px; font-weight: 500; line-height: 1.3; }
.req__msg {
  margin-top: 2px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--ui-sub);
  overflow: hidden;
  /* 最多两行 —— 三行把整条撑得太高，中间文字显得太多 */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
/* 来源：靠右，跟名字/留言错开（原来跟留言挤同一列，太宽太挤） */
.req__from {
  margin-top: 2px;
  font-size: 10.5px;
  line-height: 1.35;
  color: #a3a8b3;
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.req__acts { flex: none; display: flex; align-items: center; gap: 6px; }
.req__btn {
  height: 28px;
  padding: 0 10px;
  border: 0;
  border-radius: 5px;
  font-family: inherit;
  font-size: 12px;
  cursor: pointer;
  transition: transform .14s ease;
}
.req__btn:active { transform: scale(.94); }
.req__btn--ok { background: #07c160; color: #fff; font-weight: 500; }
.req__btn--no { background: #f2f3f5; color: #5a5f6b; }

.req__done {
  flex: none;
  font-size: 13px;
  color: var(--ui-sub);
}

/* ---------------- 收藏（10-06 照微信「收藏」重做：搜索框 + 页签 + 白卡片） ---------------- */
.view--favorites .appbar { border-bottom-color: transparent; }

.favbar {
  flex: none;
  padding: 0 10px 2px;
  background: #f7f7f9;
}

/* 搜索框：装饰用的，点不动（跟参考图一样是居中的「🔍 搜索」） */
.favsearch {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  height: 32px;
  border-radius: 8px;
  background: #ecedf1;
  color: #9aa0aa;
  font-size: 14px;
}
.favsearch svg { flex: none; }

/* 两个页签 + 最右边那个小箭头（箭头也是装饰） */
.favtabs {
  display: flex;
  align-items: center;
  gap: 22px;
  padding: 9px 6px 4px;
}
.favtab {
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  font-size: 14px;
  color: #5b6470;
  cursor: pointer;
  transition: color .15s ease;
}
.favtab.is-on { color: #576b95; font-weight: 500; }
.favtabs__caret {
  margin-left: auto;
  display: flex;
  color: #c2c6ce;
}

/* 列表：一条收藏一张白卡片，卡片之间露一条灰底 */
.favlist {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 6px 10px 18px;
}

.favcard {
  position: relative;
  padding: 12px;
  border-radius: 8px;
  background: #fff;
}

/* 图：左边一张缩略图（占卡片约 1/3 宽，右边留白，跟参考图一样），点了能放大 */
.favcard__img {
  display: block;
  width: 124px;
  height: 96px;
  border-radius: 4px;
  object-fit: cover;
  background: #eceef2;
  cursor: zoom-in;
}

/* 字：最多三行，超了省略号 */
.favcard__text {
  margin: 0;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ui);
  word-break: break-word;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.favcard__img + .favcard__text { margin-top: 10px; }

/* 底下一行：来源（左）· 时间（右）· 三个点（删除） */
.favcard__foot {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  font-size: 12px;
  color: #9ba1ab;
}
.favcard__from {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.favcard__time { flex: none; margin-left: auto; }
.favcard__more {
  flex: none;
  width: 26px; height: 26px;
  margin: 0 -5px 0 0;
  border: 0; padding: 0;
  border-radius: 50%;
  background: transparent;
  color: #c2c6ce;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.favcard__more svg { fill: currentColor; }
.favcard__more:active { background: rgba(0,0,0,.07); }

/* ---------------- 轻提示 ---------------- */
.toast {
  position: absolute;
  left: 50%;
  bottom: 96px;
  transform: translate(-50%, 12px);
  z-index: 90;
  max-width: 260px;
  padding: 9px 16px;
  border-radius: 12px;
  background: rgba(20,21,28,.86);
  color: #fff;
  font-size: 12.5px;
  letter-spacing: .3px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease, transform .2s ease;
  backdrop-filter: blur(8px);
}
.toast.is-on { opacity: 1; transform: translate(-50%, 0); }

/* ---------------- 结算（A 头图 + 结算报告 + 无限接 B，能滚的长图） ----------------
   整屏就是纸，没有顶栏 —— 顶上那行标题本来就印在 A 这张图上。
   回桌面走底下那条 home-indicator（全局都在）。
   结算报告里的字全部来自 Excel 的「结算」表，这里只管样子。
   ★★ 尺寸和间距**全部按用户给的参考图量出来的像素**定的：
     参考图 473px 宽 对应 本机屏 375px，缩放系数 = 375/473 = 0.7928。
     量出来的关键值（参考px -> 本机px）：
       标题字宽 137/4字=34.3 -> 27px ；状态大字 101/4字=25.3 -> 20px ；
       状态小字 171/10字=17.1 -> 13.5px ；圆勾直径 55 -> 44px ；
       进度条高 10 -> 8px ；用时数字高 21 -> 24px（单位 15 -> 12px）；
       统计数字高 21 -> 23px ；卡片标题 250/13字=19.2 -> 15px ；卡片说明 15.9 -> 12.5px 。
     间距：标题块底->圆勾 30px、圆勾->进度条 8.7、进度条->用时 18、
           用时数字->统计 33、统计数字底->卡片顶 25、卡片内标题->说明 ~1、
           卡片 padding ~11、卡片之间 ~12（都是本机 px）。
     **别再凭感觉放大缩小**，这张图上的值是量出来的，不是估的。 */
.view--settle { background: #e9e0d0; }

.settle {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  touch-action: pan-y;
  scrollbar-width: none;
}
.settle::-webkit-scrollbar { display: none; }

/* A 图完整铺开当纸，结算报告**直接压在它的纸面上**（不另外加底色块）。 */
.settle__hero { position: relative; }

/* 进结算先亮的那层「正在生成清理报告」——
   铺满整屏、盖在纸和底部提示之上，等 2 秒再撤（js: settleHome / settleLoad）。
   背景 = assets/系统文件/加载壁纸.jpg（米白柔光纸：左上窗影 + 下方绸缎）。 */
.settle__load {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: #efe9dc url("../assets/系统文件/加载壁纸.jpg") center center / cover no-repeat;
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity .34s ease, transform .34s ease, visibility .34s;
}
.settle__load.is-on { opacity: 1; visibility: visible; transform: none; }

/* 中间主体：环 + 文案 + 三步。整体略往上提一点（底部那行标语是绝对定位钉着的） */
.settle__ldmain {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: -30px;
}

/* ---- 进度环 ---- */
.settle__loader {
  position: relative;
  width: 116px;
  height: 116px;
  display: grid;
  place-items: center;
}
/* 环外那圈会呼吸的白光 */
.settle__loader::before {
  content: '';
  position: absolute;
  inset: -30px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, .5), rgba(255, 255, 255, 0) 70%);
  animation: settlePulse 2.6s ease-in-out infinite;
}
@keyframes settlePulse {
  0%, 100% { transform: scale(.94); opacity: .6; }
  50%      { transform: scale(1.04); opacity: 1; }
}
/* 环里面那面「玻璃」：上面亮、边上收，看着有厚度 */
.settle__loader::after {
  content: '';
  position: absolute;
  inset: 12px;
  border-radius: 50%;
  z-index: 2;
  background: radial-gradient(circle at 50% 32%,
    rgba(255, 255, 255, .6), rgba(255, 255, 255, .12) 60%, rgba(147, 134, 111, .09));
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, .85), 0 6px 16px rgba(147, 134, 111, .10);
}

.settle__ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);          /* 从 12 点方向开始长 */
  z-index: 1;
}
.settle__ring-glow,
.settle__ring-bg,
.settle__ring-fg { fill: none; stroke-linecap: round; }
.settle__ring-glow { stroke: rgba(255, 255, 255, .8); stroke-width: 1.3; }
.settle__ring-bg   { stroke: rgba(120, 110, 92, .16); stroke-width: 6.4; }
.settle__ring-fg   { stroke: #3f6b4c; stroke-width: 6.4; }

/* 中心那个百分比：定宽居中，数字位数变多也不会左右晃 */
.settle__pct {
  position: relative;
  z-index: 3;
  width: 92px;
  text-align: center;
  font-size: 29px;
  font-weight: 600;
  color: #3f6b4c;
}
.settle__pct i { font-style: normal; font-size: 29px; font-weight: 600; }
/* 数字 + %：一行，% 顶对齐、小一号（别用绝对定位 —— 下面还有一行「清理中」，
   absolute 不写 top 会停在流末尾，跑到第二行去） */
.settle__num {
  display: inline-flex;
  align-items: flex-start;
  line-height: 1;
}
.settle__num b {
  margin-left: 1px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.45;
  color: #6e8f77;
}
.settle__pct em {
  display: block;
  margin-top: 1px;
  font-style: normal;
  font-size: 8.5px;
  font-weight: 400;
  letter-spacing: 5px;
  text-indent: 5px;                /* 补掉字距在末字右边多出来的空，视觉才居中 */
  color: #8f8874;
}

/* ---- 阶段文案 ---- */
.settle__loadtext {
  margin-top: 46px;
  font-size: 20px;
  font-weight: 500;
  letter-spacing: 1.5px;
  color: #3b4437;
}
/* 每换一句就重放一次：淡入 + 轻轻往上浮。
   ⚠️ 起始 opacity 别写 0 —— 动画万一没播完（无头截图那种），整句会看着像没显示。 */
.settle__loadtext.is-swap { animation: settleStepIn .38s ease both; }
@keyframes settleStepIn {
  from { opacity: .2; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.settle__loadsub {
  margin-top: 14px;
  font-size: 12.5px;
  letter-spacing: .8px;
  color: #7e7869;
}

/* ---- 五步指示器（翻看相册 → 逐条核对 → 清点痕迹 → 分类打包 → 生成报告）---- */
.settle__steps {
  display: flex;
  align-items: flex-start;
  width: 348px;                /* 5×46 + 4×29.5 */
  margin-top: 42px;
}
.settle__step {
  flex: none;
  width: 46px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
.settle__step-ico {
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: #a49d8c;
  transition: width .3s ease, height .3s ease, margin .3s ease,
              color .3s ease, background .3s ease, box-shadow .3s ease;
}
.settle__step-ico svg { width: 19px; height: 19px; }
.settle__step-txt {
  font-size: 10px;
  letter-spacing: .2px;
  white-space: nowrap;
  color: #918b7a;
  transition: color .3s ease;
}
/* 正在做的那一步：白圆底 + 深绿图标 + 字色加深（放大到 36px 但中心点不动） */
.settle__step.is-on .settle__step-ico {
  width: 36px;
  height: 36px;
  margin-top: -5px;
  background: rgba(255, 255, 255, .92);
  color: #3f6b4c;
  box-shadow: 0 4px 12px rgba(120, 110, 92, .16);
}
.settle__step.is-on .settle__step-ico svg { width: 20px; height: 20px; }
.settle__step.is-on .settle__step-txt { color: #5d6a55; }
/* 做过的：淡绿 */
.settle__step.is-done .settle__step-ico { color: #8fae97; }
.settle__step.is-done .settle__step-txt { color: #8f9683; }

/* 连接线：细线 + 中间一个点，走过的那段变绿 */
.settle__line {
  flex: 1;
  position: relative;
  height: 1px;
  margin-top: 13px;
  background: #d0c8b4;
}
.settle__line b {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 0;
  background: #7ba087;
  transition: width .3s ease;
}
.settle__line::after {
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  width: 4px; height: 4px;
  margin: -2px 0 0 -2px;
  border-radius: 50%;
  background: #cfc7b4;
  transition: background .3s ease;
}
.settle__line.is-done b { width: 100%; }
.settle__line.is-done::after { background: #7ba087; }

/* ---- 底部那行小标语 ---- */
.settle__ldfoot {
  position: absolute;
  left: 0; right: 0;
  bottom: 84px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  font-size: 11.5px;
  letter-spacing: 2.4px;
  text-indent: 2.4px;
  color: #9e9784;
}
.settle__ldfoot i { width: 26px; height: 1px; background: #cdc5b2; }

/* 刚进结算时怼在屏幕底部那句「继续滑动，查看完整报告」——
   一滑 / 一拖就让 js 把 .is-on 摘掉，它自己淡出 + 往下收一点。 */
.settle__hint {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 36px;
  z-index: 0;                        /* 建个层叠上下文，下面那层雾才不会被父级背景吃掉 */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  color: #59513f;                    /* 比纸深两档 —— 原来那个色压在卡片上糊成一片 */
  font-size: 12.5px;
  letter-spacing: .3px;
  text-align: center;
  pointer-events: none;              /* 别挡着下面的滑动 */
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .32s ease, transform .32s ease;
}
/* 底下垫一层跟纸同色的雾（纸色量出来是 rgb(226,212,199)），
   这样提示压在卡片 / 正文上也能自己浮出来，不会跟内容糊在一起。 */
.settle__hint::before {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -38px;
  width: 130%;
  max-width: 520px;
  height: 150px;
  transform: translateX(-50%);
  z-index: -1;
  background: radial-gradient(58% 62% at 50% 72%,
              rgba(226,212,199,.97) 40%, rgba(226,212,199,.62) 72%,
              rgba(226,212,199,0));
}
.settle__hint.is-on { opacity: 1; transform: none; }
.settle__hint svg { display: block; opacity: .9; }

/* 每张都铺满宽度、竖着紧挨着排（display:block 才不会有行距缝） */
.settle__page {
  display: block;
  width: 100%;
  height: auto;
  -webkit-user-drag: none;
  user-select: none;
}

/* ---- 结算报告 ---- */
/* ⚠️ 绝对定位压在 A 图上，**不要加背景色** —— 加了就变成"另贴一块方块"，
   纸面本身的纹理和色差就断掉了（用户 10-13 明确要求写在原来的牛皮纸上）。
   top 改的是它离屏幕顶多远，也就是落在纸上哪个位置。 */
.settle__report {
  position: absolute;
  left: 0;
  right: 0;
  top: 31%;
  padding: 0 34px;
  color: #2f2e2a;
}

/* 顶上那条：左边「结算报告 / CLEANUP REPORT」，右上角两行小字 */
.report__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  padding-bottom: 11px;              /* 到下面那条细线的距离 */
  border-bottom: 1px solid rgba(92,85,68,.22);
}
.report__title {
  margin: 0;
  font-size: 27px;
  font-weight: 700;
  letter-spacing: .5px;
  line-height: 1.15;
}
.report__titleEn {
  margin-top: 10px;
  font-size: 10.5px;
  letter-spacing: 1.7px;
  color: #867f70;
}
.report__headR {
  flex: none;
  padding-top: 4px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  font-size: 12px;
  color: #867f70;
  white-space: nowrap;
}

/* 状态：圆勾 + 「清理完成」+ 一行小字 */
.report__state {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-top: 16px;
}
.report__check { flex: none; width: 44px; height: 44px; }
.report__check svg { display: block; width: 100%; height: 100%; }
.report__stateText { min-width: 0; }
.report__stateTitle {
  display: block;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: .5px;
}
.report__stateNote {
  margin: 1px 0 0;
  font-size: 13.5px;
  color: #867f70;
}

/* 进度条 + 右边那个百分比
   ⚠️ .report__pct 必须 line-height:1 —— 不然 20px 的字撑出 28px 行盒，
      整个 .report__bar 变高，垂直居中的进度条就被推下去 9px（用户 10-13 说"间距这么大"）。 */
.report__bar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 2px;
}
.report__barTrack {
  flex: 1;
  height: 6px;
  border-radius: 3px;
  background: #d8d0bf;
  overflow: hidden;
}
.report__barFill {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: #8a9a70;
}
.report__pct {
  flex: none;
  font-size: 20px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: .5px;
  color: #7d8f63;
}

/* 用时 */
.report__time { margin-top: 12px; }
.report__timeLabel {
  display: block;
  font-size: 12px;
  line-height: 1.2;
  color: #867f70;
}
.report__timeNum {
  display: flex;
  align-items: baseline;
  gap: 3px;
  margin-top: 3px;
  font-size: 24px;
  line-height: 1.15;
  font-weight: 700;
  letter-spacing: .5px;
}
.report__timeNum b { font-weight: 700; }
.report__timeNum i {
  font-style: normal;
  font-size: 12px;
  font-weight: 500;
  color: #6b6557;
}

/* ---- 用时下面那一行：删除 / 错删 / 未删（三列，等分） ---- */
.report__stats {
  display: flex;
  margin-top: 10px;
  padding-top: 7px;
  padding-bottom: 8px;
  border-top: 1px solid rgba(92,85,68,.22);
  border-bottom: 1px solid rgba(92,85,68,.22);      /* ★ 删除/错删/未删 底下也来一条 */
}
/* ★ 统计行下面紧跟的第一张卡：跟上面那条线拉开一点（卡片之间仍是 2px） */
.report__stats + .setnote { margin-top: 16px; }
/* ★ 10-14：统计行与第一张卡中间那句引导语（Excel「文案」表 分类 = 结算文案，可写多行） */
.report__lead {
  margin: 20px 0 0;
  padding-bottom: 16px;              /* 跟下面第一张卡的距离（+卡片自身 2px） */
  font-size: 13.5px;
  line-height: 1.5;
  text-align: center;
  color: #6b6557;
}
.report__stat { flex: 1; min-width: 0; }
.report__stat + .report__stat {
  border-left: 1px solid rgba(92,85,68,.22);
  padding-left: 14px;
}
.report__stat > span {
  display: block;
  font-size: 12px;
  color: #867f70;
}
.report__stat > div {
  display: flex;
  align-items: baseline;
  gap: 3px;
  margin-top: 4px;
}
.report__stat b { font-size: 23px; font-weight: 700; letter-spacing: .5px; }
.report__stat i {
  font-style: normal;
  font-size: 12px;
  font-weight: 500;
  color: #6b6557;
}

/* ---- 底部那些提示卡（内容来自 Excel「结算」表 ②③④⑤ 四块） ----
   ★ 10-14：底色换成 assets/系统文件/结算格子/ 里那批「纸底格子」（一张卡一张，
   JS 的 settleCardsHTML() 按 Excel 里的「标志」点名，点不到就按 L_数字 顺序轮流给）。
   ⚠️ 格子图自带左侧图标 + 右侧装饰，所以这里的 .setnote__icon 不再单独画；
   ⚠️ 卡片宽高比**跟着格子图的原比例**（--note-ratio，由 JS 从图片头里读出来），
      别写死、别改，一改格子就被拉变形。 */
/* ★ 10-15：卡片上面压的那条「花纹分割线」——
   图在 assets/系统文件/结算格子/分割线/（A1 / A2 / A3 循环用，JS 的 settleHrHTML 安排）。
   ★ 跟卡片等宽：一样左右各拉出 34px，铺满手机宽。
   排法是「线 -> 卡 -> 线 -> 卡 … -> 最后一张卡 -> 再来一条线收尾」。
   ★ 10-15 定版：**完整显示原图，不裁**（裁了会把图里的小装饰切掉）；
   上下也不留 margin —— 纸带直接贴着上下两张卡，线在纸带正中自带呼吸，
   空隙就是这么消掉的。 */
.report__hr { margin: 0 -34px; }
.report__hr img {
  display: block;
  width: 100%;
  height: auto;
  -webkit-user-drag: none;
  user-select: none;
  pointer-events: none;
}

.setnote {
  position: relative;
  display: flex;
  align-items: center;
  /* ★ 10-14 按用户口径：格子的左右两边 = 手机屏幕的两侧（满宽），
     所以往左右各顶出去 34px（报告内容区两边各留了 34px）。
     ★ 10-15：margin-top 归零 —— 上面就是分割线纸带，要贴住不留缝。 */
  margin: 0 -34px;
  /* ★ 10-15：用户把格子图里左侧那个图标删了 → 左边不用再让出 30%，
     文字往左挪（% 是相对报告内容宽 307，18% ≈ 55px ≈ 卡片宽的 15%）。
     右边 30% 照旧，让开图里右侧那堆装饰。 */
  padding: 0 30% 0 18%;
  aspect-ratio: var(--note-ratio, 787 / 250);
  min-height: min-content;         /* 字多到装不下就往下长，别溢出卡片 */
  background: rgba(150,140,118,.17) center / 100% 100% no-repeat;   /* 没格子图时的兜底灰底 */
}
.setnote__icon { display: none; }
.setnote__body { min-width: 0; }
.setnote__title {
  display: block;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.3;
  color: #1a1712;
}
.setnote__note {
  margin: 3px 0 0;
  font-size: 12px;
  line-height: 1.4;
  color: #241f18;
}

/* ---- 报告最末那张「清理人格」图（MBTI） ----
   它就是报告里的一个普通元素，接着上面那张卡往下排（宽度 = 报告内容宽）。
   ⚠️ 它自带米色纸底，别再套 background / 边框 / 圆角 / 阴影 —— 一套就变成"贴了块方块"。 */
.report__mbti {
  display: block;
  /* 跟按钮一样：左右负拉出报告的 34px 内边距，图铺满手机宽，两边不留空。
     ⚠️ **必须显式给宽度** —— <img> 是替换元素，width:auto 会退回原图的 768px，
        一下把报告撑到 768 宽、右边全被裁掉（10-13 踩过）。 */
  width: calc(100% + 68px);
  margin: 20px -34px 0;
  height: auto;
  aspect-ratio: 768 / 1376;
  -webkit-user-drag: none;
  user-select: none;
  pointer-events: none;
}

/* ---- 最底下那颗「重新游玩」 ----
   素材 `重新游玩.jpg` 是 524×164，药丸本来就只占中间 334px（左右各 95px 是纸色留白）。
   ⚠️ **就按素材原样显示，不要放大、不要再裁**（v225 我把它放到 588px 撑满 375，
      用户明确否掉：「不要让它这么大……就跟之前那么大，你不要改这个」）。
   这里只负责把它左右拉出报告的 34px 内边距（元素 375 宽），图跟着 100% 走，
   药丸 ≈ 239px 居中，跟以前一模一样。 */
.report__replay {
  display: block;
  /* 报告的左右各有 34px 内边距，这里负着拉出去 —— 元素正好铺满手机宽度 */
  width: calc(100% + 68px);
  /* 上边距压小一点：MBTI 图底下本来就自带留白，26px 叠上去太空 */
  margin: 12px -34px 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.report__replay img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 524 / 164;
  -webkit-user-drag: none;
  user-select: none;
}
.report__replay:active { transform: translateY(1px); }

/* ---------------- 游戏难度（只藏提示，一分都不动） ----------------
   困难起：底栏那四个红点、相册卡片右上角的张数徽章，全部藏掉；
   地狱：在困难基础上，进度数字改成「?%」（在 app.js 的 refreshProgress 里换，
         环和进度条也会一起空掉）—— 越难，提示越少。 */
body.diff-hard .tabbar__badge,
body.diff-hard .album-card__dot { display: none !important; }
/* 困难起：进了 App 就不报进度 —— 灵动岛里那个绿圈和数字收起来，回桌面才出现。
   整格照样能点（只是看着空），点开的进度面板照常弹。
   「在不在桌面上」= body 上有没有 at-home，由 js 的 showView / applyDifficulty 维护。 */
body.diff-hard:not(.at-home) .island__ring,
body.diff-hard:not(.at-home) .island__num { display: none; }
/* 地狱：连桌面上那两个 App 图标上的红点（微信 18 / 相册 70）也一起藏掉
   —— 这是「还剩多少」的总量提示，用户要求地狱下不给。 */
body.diff-hell .app__badge { display: none !important; }
