/* ==========================================================================
   白璃电竞陪练系统 · 设计系统（H5）
   玻璃拟态：半透明磨砂面板 + 环境光背景 + 半透明按钮
   ========================================================================== */

:root {
  /*
   * 品牌色（会被分站主题色覆盖 --zc-theme）—— 电竞青蓝
   * ⚠️ 换配色时要同时改这四处，只改 CSS 没用（分站主题色会在运行时覆盖）：
   *    public/assets/css/base.css 的 :root
   *    config.json 的 site.themeColor
   *    data/tenants.json 里每个分站的 themeColor
   *    ui.js applyTheme() 里的兜底值
   */
  --zc-theme: #2563EB;
  --brand: #2563EB;
  --brand-2: #0EA5E9;
  --brand-soft: rgba(37, 99, 235, .12);
  --brand-softer: rgba(37, 99, 235, .06);
  /* 品牌色的几档透明度：阴影、描边、光晕都该用这些，别硬编码 rgba。
     applyTheme() 会按分站主题色重算并覆盖，所以能跟着站长选的颜色走。 */
  --brand-a08: rgba(37, 99, 235, .08);
  --brand-a14: rgba(37, 99, 235, .14);
  --brand-a22: rgba(37, 99, 235, .22);
  --brand-a35: rgba(37, 99, 235, .35);
  --brand-a45: rgba(37, 99, 235, .45);
  /* 全透明端点：写渐变淡出用它，别用 CSS 的 transparent 关键字
     （transparent 是 rgba(0,0,0,0)，老 Safari 插值时会在中间透出灰黑） */
  --brand-a00: rgba(37, 99, 235, 0);
  /* 品牌色底上的文字色（#2563EB 的亮度 0.153 < 0.179，所以配白字）
     applyTheme() 会按实际主题色的亮度重算，站长换淡色主题时自动变深字 */
  --on-brand: #FFFFFF;

  /* 中性色 */
  --bg: #F5F8FF;
  --bg-2: #FFFFFF;
  --card: rgba(255, 255, 255, .86);
  --card-solid: #FFFFFF;

  /* —— 玻璃拟态（浅色版）—— */
  --glass: rgba(255, 255, 255, .82);          /* 面板底 */
  --glass-strong: rgba(255, 255, 255, .93);   /* 需要更实的面板 */
  --glass-weak: rgba(255, 255, 255, .58);     /* 更透的底 */
  --glass-line: rgba(255, 255, 255, .85);     /* 玻璃边的亮线 */
  --glass-edge: rgba(16, 24, 40, .06);        /* 描边：发丝线，不是白边 */
  --glass-blur: saturate(170%) blur(18px);
  --glass-blur-sm: saturate(160%) blur(12px);

  --text: #0F1115;
  --text-1: #363B47;
  --text-2: #6B7280;
  --text-3: #9BA1AE;
  /* 分隔线：玻璃面板上要看得见，所以用低透明度灰蓝而不是白色 */
  --line: rgba(16, 24, 40, .075);
  --line-2: rgba(16, 24, 40, .13);

  /* 功能色 */
  --green: #0EA371;
  --green-soft: rgba(18, 183, 106, .14);
  --orange: #E08407;
  --orange-soft: rgba(247, 144, 9, .14);
  --red: #E23D31;
  --red-soft: rgba(240, 68, 56, .12);
  --blue: #2E90FA;
  --blue-soft: rgba(46, 144, 250, .13);

  /* 尺寸 */
  --r-sm: 10px;
  --r: 18px;
  --r-lg: 22px;
  --r-xl: 28px;
  /* 暗色下阴影几乎不可见，层级靠 --line 描边 + 底色差；这几个保留给需要层次的少数场景 */
  --shadow-s: 0 1px 2px rgba(16, 24, 40, .04);
  --shadow: 0 1px 2px rgba(16, 24, 40, .04), 0 6px 18px rgba(16, 24, 40, .045);
  --shadow-l: 0 12px 36px rgba(16, 24, 40, .12);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-top, 0px);

  --font: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB",
          "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
}

/* 环境光背景：极淡的品牌色微光，不能盖住 --bg（否则整页变暗） */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(120% 46% at 50% -8%, var(--brand-a08), var(--brand-a00) 70%),
    radial-gradient(70% 34% at 108% 8%, rgba(46, 144, 250, .05), rgba(46, 144, 250, 0) 70%),
    linear-gradient(180deg, #FFFFFF 0%, var(--bg) 100%);
}

body { overscroll-behavior-y: none; }

a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; border: 0; }
button, input, textarea, select { font-family: inherit; font-size: inherit; color: inherit; }
button { cursor: pointer; border: 0; background: none; padding: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, h5 { margin: 0; font-weight: 600; }
p { margin: 0; }
input, textarea { outline: none; }

::-webkit-scrollbar { width: 0; height: 0; }

/* --------------------------------------------------------------------------
   页面骨架
   -------------------------------------------------------------------------- */

.zc-app {
  max-width: 480px;
  margin: 0 auto;
  min-height: 100vh;
  background: transparent;
  position: relative;
  display: flex;
  flex-direction: column;
}

@media (min-width: 900px) {
  body { background: #E9EBF0; }
  .zc-app {
    max-width: 460px;
    box-shadow: 0 0 0 1px var(--line), 0 30px 70px rgba(16, 24, 40, .18);
    min-height: 100vh;
  }
  /* 桌面端把环境光收进手机视口里，两侧留白更干净 */
  body::before { opacity: .92; }
}

.zc-main {
  flex: 1;
  padding: 0 14px;
  padding-bottom: calc(24px + var(--safe-b));
}
.zc-main.has-tabbar { padding-bottom: calc(86px + var(--safe-b)); }
.zc-main.no-pad { padding-left: 0; padding-right: 0; }

/* --------------------------------------------------------------------------
   顶栏
   -------------------------------------------------------------------------- */

.zc-nav {
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 10px;
  height: 52px;
  padding: 0 14px;
  padding-top: var(--safe-t);
  /*
   * 顶栏：比底栏实一点。
   * 顶栏里有搜索输入框，太透的话页面内容会叠在输入框上，看着很乱；
   * 底栏只有图标，可以压到 .38 那种很透的玻璃。
   */
  background: rgba(255, 255, 255, .72);
  backdrop-filter: saturate(180%) blur(22px);
  -webkit-backdrop-filter: saturate(180%) blur(22px);
  border-bottom: 1px solid transparent;
  transition: border-color .2s;
}
.zc-nav.scrolled { border-bottom-color: var(--line); }
.zc-nav__title {
  flex: 1;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -.2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.zc-nav__title.center { text-align: center; }
.zc-nav__btn {
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 10px;
  font-size: 18px;
  color: var(--text-1);
  transition: background .15s;
  flex-shrink: 0;
}
.zc-nav__btn:active { background: var(--line); }
/* 品牌头：金底 + 深色字（金底白字对比度只有 2:1，糊成一片） */
.zc-nav--brand {
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  color: var(--on-brand);
  border-bottom: 0;
}
.zc-nav--brand .zc-nav__btn { color: var(--on-brand); }
.zc-nav--brand .zc-nav__btn:active { background: rgba(15, 16, 20, .14); }
.zc-nav--transparent { background: transparent; border-bottom: 0; }

/* --------------------------------------------------------------------------
   底部 Tab
   -------------------------------------------------------------------------- */

/*
 * 底部导航：胶囊形玻璃条
 * ① 形状：border-radius: 999px 是「胶囊」——两端完整半圆，不是圆角矩形
 * ② 玻璃感：不透明度必须低（.38）。.5 以上在白色卡片上就看着像实心白了。
 *    配合 30px 模糊 + 白色描边 + 顶部内高光，才有「一块玻璃浮在内容上」的感觉。
 */
.zc-tabbar {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(10px + env(safe-area-inset-bottom));
  width: calc(100% - 26px);
  max-width: 440px;
  z-index: 70;
  display: flex;
  padding: 6px;
  gap: 2px;
  background: rgba(255, 255, 255, .38);
  backdrop-filter: saturate(200%) blur(30px);
  -webkit-backdrop-filter: saturate(200%) blur(30px);
  border: 1px solid rgba(255, 255, 255, .55);
  border-radius: 999px;
  overflow: hidden;
  box-shadow: 0 10px 34px rgba(16, 24, 40, .14), inset 0 1px 0 rgba(255, 255, 255, .9);
  color: var(--text-3);
}
@media (min-width: 900px) { .zc-tabbar { max-width: 420px; } }
.zc-tabbar__item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 6px 0 7px;
  color: var(--text-3);
  position: relative;
  transition: color .15s;
}
/* 图标外层：只负责 box 与文字之间的排布 */
.zc-tabbar__ico { display: flex; align-items: center; justify-content: center; line-height: 0; }
/* 图标容器：胶囊形（跟外层胶囊呼应），选中时铺 --brand-soft 淡色底 */
.zc-tabbar__ico-box {
  width: 46px; height: 30px;
  border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  background: transparent;
  color: inherit;
  transition: background .18s, color .18s, transform .18s;
}
.zc-tabbar__ico-box svg { display: block; }
.zc-tabbar__tx { font-size: 10.5px; line-height: 1.2; color: inherit; transition: color .15s; }
.zc-tabbar__item.active { color: var(--brand); }
.zc-tabbar__item.active .zc-tabbar__ico-box { background: var(--brand-soft); }
.zc-tabbar__item.active .zc-tabbar__tx { color: var(--brand); font-weight: 600; }
.zc-tabbar__item:active .zc-tabbar__ico-box { transform: scale(.93); }
/* 动作型 tab（底部的「客服」）：它是 <button> 不是 <a>，点了不切页、不加 .active，
   只在按下后 160ms 内挂一个 .is-pressed，让用户知道点到了（ui.js 的 bindCsTab 负责加/摘）。
   gap:0 是必须的：.zc-tabbar__item 上那条 gap 在 <a> 上不生效，换成 <button> 会真的多出 4px，
   底部胶囊会整体变高；这里抵消掉，保证换成动作 tab 后高度和别的 tab 一模一样。 */
.zc-tabbar__item[data-tab] { gap: 0; }
.zc-tabbar__item.is-pressed { color: var(--brand); }
.zc-tabbar__item.is-pressed .zc-tabbar__ico-box { background: var(--brand-soft); }

/* ---------------- 免责声明（ui.js 自动挂到每个 H5 页面底部）---------------- */
.zc-disclaimer {
  margin: 22px 16px calc(112px + var(--safe-b));
  padding: 14px 16px;
  border-radius: 14px;
  background: var(--glass);
  border: 1px solid var(--line);
  -webkit-backdrop-filter: var(--glass-blur-sm);
  backdrop-filter: var(--glass-blur-sm);
}
.zc-disclaimer__t {
  font-size: 11.5px; font-weight: 600; color: var(--text-3);
  letter-spacing: .4px; margin-bottom: 6px;
}
.zc-disclaimer__c {
  font-size: 11.5px; line-height: 1.75; color: var(--text-3);
  word-break: break-word;
}
/* 桌面端 H5 是居中手机框，免责声明跟着框走 */
@media (min-width: 900px) {
  .zc-disclaimer { margin-left: 16px; margin-right: 16px; }
}

.zc-tabbar__item .dot {
  position: absolute;
  top: 3px;
  left: 50%;
  margin-left: 8px;
  min-width: 15px; height: 15px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--red);
  color: var(--on-brand);
  font-size: 9px;
  line-height: 15px;
  text-align: center;
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   卡片
   -------------------------------------------------------------------------- */

.card {
  background: var(--card);
  border-radius: var(--r);
  box-shadow: var(--shadow-s);
  margin-bottom: 12px;
  overflow: hidden;
}
.card--flat { box-shadow: none; border: 1px solid var(--line); }
.card--pad { padding: 16px; }
.card--lg { border-radius: var(--r-lg); }

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 16px 8px;
}
.card-head h3 { font-size: 15.5px; letter-spacing: -.2px; }
.card-head .more { font-size: 12.5px; color: var(--text-3); display: flex; align-items: center; gap: 2px; }

.section-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 18px 2px 10px;
}
.section-title h3 { font-size: 16px; letter-spacing: -.2px; }
.section-title .more { font-size: 12.5px; color: var(--text-3); }

/* --------------------------------------------------------------------------
   按钮
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 44px;
  padding: 0 18px;
  border-radius: 12px;
  font-size: 15px;
  font-weight: 500;
  background: var(--line);
  color: var(--text-1);
  transition: transform .12s, opacity .15s, background .15s;
  white-space: nowrap;
  user-select: none;
}
.btn:active { transform: scale(.975); }
.btn--primary {
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  color: var(--on-brand);
  box-shadow: 0 4px 14px var(--brand-a22);
}
.btn--ghost { background: var(--brand-soft); color: var(--brand); }
.btn--line { background: transparent; border: 1px solid var(--line-2); color: var(--text-1); }
.btn--danger { background: var(--red-soft); color: var(--red); }
.btn--white { background: var(--card-solid); color: var(--text); border: 1px solid var(--line); }
.btn--block { display: flex; width: 100%; }
.btn--sm { height: 32px; padding: 0 12px; font-size: 13px; border-radius: 9px; }
.btn--xs { height: 26px; padding: 0 10px; font-size: 12px; border-radius: 8px; }
.btn--lg { height: 50px; font-size: 16px; border-radius: 14px; }
.btn[disabled], .btn.is-disabled { opacity: .45; pointer-events: none; }
.btn--loading { pointer-events: none; opacity: .7; }

.btn-row { display: flex; gap: 10px; }
.btn-row .btn { flex: 1; }

/* 底部固定操作栏 */
.action-bar {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: 0;
  width: 100%;
  max-width: 480px;
  z-index: 65;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px calc(10px + var(--safe-b));
  background: rgba(255, 255, 255, .94);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-top: 1px solid var(--line);
}
@media (min-width: 900px) { .action-bar { max-width: 460px; } }
.action-bar .price-box { flex: 1; min-width: 0; }
.action-bar .btn { min-width: 130px; }

/* --------------------------------------------------------------------------
   标签 / 徽章
   -------------------------------------------------------------------------- */

.tag {
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 7px;
  border-radius: 6px;
  font-size: 11px;
  line-height: 1;
  background: var(--line);
  color: var(--text-2);
  white-space: nowrap;
}
.tag--brand { background: var(--brand-soft); color: var(--brand); }
.tag--green { background: var(--green-soft); color: var(--green); }
.tag--orange { background: var(--orange-soft); color: var(--orange); }
.tag--red { background: var(--red-soft); color: var(--red); }
.tag--blue { background: var(--blue-soft); color: var(--blue); }
.tag--line { background: transparent; border: 1px solid var(--line-2); }
.tag--lg { height: 24px; padding: 0 9px; font-size: 12px; border-radius: 8px; }

.tags { display: flex; flex-wrap: wrap; gap: 5px; }

.dot-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--text-2);
}
.dot-badge::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--text-3);
}
.dot-badge.online { color: var(--green); }
.dot-badge.online::before { background: var(--green); box-shadow: 0 0 0 3px rgba(18,183,106,.15); }

/* --------------------------------------------------------------------------
   头像
   -------------------------------------------------------------------------- */

.avatar {
  position: relative;
  width: 44px; height: 44px;
  border-radius: 14px;
  background: linear-gradient(135deg, var(--brand-soft), var(--brand-a22));
  color: var(--brand);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  font-weight: 600;
  overflow: hidden;
  flex-shrink: 0;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar--sm { width: 34px; height: 34px; border-radius: 11px; font-size: 13px; }
.avatar--lg { width: 60px; height: 60px; border-radius: 18px; font-size: 22px; }
.avatar--xl { width: 72px; height: 72px; border-radius: 22px; font-size: 26px; }
.avatar--round { border-radius: 50%; }

.avatar .online-dot {
  position: absolute;
  right: -1px; bottom: -1px;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--green);
  border: 2px solid var(--card-solid);
}

/* --------------------------------------------------------------------------
   列表
   -------------------------------------------------------------------------- */

.list { background: var(--card); border-radius: var(--r); overflow: hidden; }
.list-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  position: relative;
  transition: background .15s;
}
.list-item:active { background: rgba(255, 255, 255, .05); }
.list-item + .list-item::before {
  content: '';
  position: absolute;
  left: 16px; right: 0; top: 0;
  height: 1px;
  background: var(--line);
}
.list-item__body { flex: 1; min-width: 0; }
.list-item__title {
  font-size: 14.5px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.list-item__desc {
  font-size: 12.5px;
  color: var(--text-3);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.list-item__extra { color: var(--text-3); font-size: 13px; display: flex; align-items: center; gap: 6px; }
.list-item__arrow { color: var(--line-2); font-size: 16px; }

/* --------------------------------------------------------------------------
   网格
   -------------------------------------------------------------------------- */

.grid { display: grid; gap: 10px; }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
.grid--5 { grid-template-columns: repeat(5, 1fr); }

/* --------------------------------------------------------------------------
   表单
   -------------------------------------------------------------------------- */

.field { margin-bottom: 14px; }
.field__label {
  display: block;
  font-size: 13px;
  color: var(--text-2);
  margin-bottom: 7px;
  font-weight: 500;
}
.field__label .req { color: var(--red); margin-left: 2px; }
.field__hint { font-size: 12px; color: var(--text-3); margin-top: 6px; line-height: 1.5; }

.input, .textarea, .select {
  width: 100%;
  height: 46px;
  padding: 0 14px;
  border-radius: 12px;
  background: var(--card-solid);
  border: 1px solid var(--line-2);
  transition: border-color .15s, box-shadow .15s;
  font-size: 15px;
}
.textarea { height: auto; min-height: 92px; padding: 12px 14px; resize: vertical; line-height: 1.6; }
.input:focus, .textarea:focus, .select:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-a14);
}
.input::placeholder, .textarea::placeholder { color: var(--text-3); }
.input[disabled] { background: rgba(255, 255, 255, .05); color: var(--text-3); }
.select {
  appearance: none;
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%239BA1B4' d='M1.4 1.4 6 6l4.6-4.6L12 2.8 6 8.8 0 2.8z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 36px;
}

.input-group {
  display: flex;
  align-items: center;
  gap: 0;
  border: 1px solid var(--line-2);
  border-radius: 12px;
  background: var(--card-solid);
  overflow: hidden;
  transition: border-color .15s, box-shadow .15s;
}
.input-group:focus-within { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-a14); }
.input-group .input { border: 0; border-radius: 0; box-shadow: none !important; height: 44px; }
.input-group .prefix, .input-group .suffix {
  padding: 0 12px;
  color: var(--text-3);
  font-size: 14px;
  flex-shrink: 0;
}

.switch {
  position: relative;
  width: 46px; height: 27px;
  border-radius: 14px;
  background: var(--line-2);
  transition: background .2s;
  flex-shrink: 0;
}
.switch::after {
  content: '';
  position: absolute;
  top: 3px; left: 3px;
  width: 21px; height: 21px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.16);
  transition: transform .2s;
}
.switch.on { background: var(--brand); }
.switch.on::after { transform: translateX(19px); }

/* 选项组 */
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  height: 34px;
  padding: 0 14px;
  border-radius: 10px;
  background: rgba(255, 255, 255, .06);
  border: 1px solid var(--line-2);
  color: var(--text-1);
  font-size: 13.5px;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  flex-shrink: 0;
  transition: all .15s;
}
.chip.active {
  background: var(--brand-soft);
  border-color: var(--brand);
  color: var(--brand);
  font-weight: 500;
}

/* 单/复选 */
.check {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 13px;
  color: var(--text-2);
  line-height: 1.5;
}
.check input { margin: 2px 0 0; width: 16px; height: 16px; accent-color: var(--brand); flex-shrink: 0; }

/* --------------------------------------------------------------------------
   价格
   -------------------------------------------------------------------------- */

.price { color: var(--red); font-weight: 600; font-variant-numeric: tabular-nums; }
.price .sym { font-size: .72em; margin-right: 1px; }
.price .num { font-size: 1.12em; }
.price--lg .num { font-size: 1.5em; }
.price--xl .num { font-size: 1.9em; }
.price--muted { color: var(--text-2); }
.price-old { color: var(--text-3); text-decoration: line-through; font-size: 12px; font-weight: 400; }

/* --------------------------------------------------------------------------
   状态 / 空态 / 骨架
   -------------------------------------------------------------------------- */

.empty {
  padding: 56px 20px;
  text-align: center;
  color: var(--text-3);
}
.empty__icon { font-size: 44px; margin-bottom: 12px; opacity: .8; }
.empty__text { font-size: 13.5px; }
.empty .btn { margin-top: 16px; }

.loading { padding: 40px; text-align: center; color: var(--text-3); font-size: 13px; }

.skeleton {
  background: linear-gradient(90deg, rgba(255,255,255,.05) 25%, rgba(255,255,255,.10) 37%, rgba(255,255,255,.05) 63%);
  background-size: 400% 100%;
  animation: skeleton 1.3s ease infinite;
  border-radius: 8px;
}
@keyframes skeleton { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

.spinner {
  width: 18px; height: 18px;
  border: 2px solid rgba(255,255,255,.35);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin .7s linear infinite;
  display: inline-block;
}
.spinner--dark { border-color: var(--brand-a22); border-top-color: var(--brand); }
@keyframes spin { to { transform: rotate(360deg); } }

/* --------------------------------------------------------------------------
   Toast / 弹层
   -------------------------------------------------------------------------- */

.zc-toast {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%) scale(.94);
  z-index: 9999;
  max-width: 74vw;
  padding: 13px 20px;
  border-radius: 14px;
  background: rgba(28, 32, 56, .88);
  color: #FFFFFF;
  font-size: 14px;
  line-height: 1.5;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s, transform .2s;
  backdrop-filter: blur(8px);
}
.zc-toast.show { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.zc-toast--top { top: 84px; transform: translate(-50%, 0) scale(.94); }
.zc-toast--top.show { transform: translate(-50%, 0) scale(1); }

.mask {
  position: fixed;
  inset: 0;
  background: rgba(20,22,31,.42);
  z-index: 200;
  opacity: 0;
  pointer-events: none;
  transition: opacity .22s;
  backdrop-filter: blur(2px);
}
.mask.show { opacity: 1; pointer-events: auto; }

.sheet {
  position: fixed;
  left: 50%;
  bottom: 0;
  transform: translate(-50%, 100%);
  width: 100%;
  max-width: 480px;
  max-height: 86vh;
  z-index: 201;
  background: var(--card-solid);
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  transition: transform .28s cubic-bezier(.32,.72,.3,1);
  display: flex;
  flex-direction: column;
  padding-bottom: var(--safe-b);
}
@media (min-width: 900px) { .sheet { max-width: 460px; } }
.sheet.show { transform: translate(-50%, 0); }
.sheet__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 18px 10px;
  flex-shrink: 0;
}
.sheet__head h3 { font-size: 16.5px; }
.sheet__close { width: 30px; height: 30px; border-radius: 50%; background: var(--line); color: var(--text-2); display: flex; align-items: center; justify-content: center; font-size: 15px; }
.sheet__body { padding: 4px 18px 18px; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.sheet__foot { padding: 12px 18px calc(16px + var(--safe-b)); border-top: 1px solid var(--line); flex-shrink: 0; }

.dialog {
  position: fixed;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%) scale(.94);
  width: 82vw;
  max-width: 340px;
  z-index: 202;
  background: var(--card-solid);
  border-radius: var(--r-lg);
  padding: 22px 20px 16px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s, transform .2s;
}
.dialog.show { opacity: 1; pointer-events: auto; transform: translate(-50%, -50%) scale(1); }
.dialog h3 { font-size: 16.5px; text-align: center; margin-bottom: 8px; }
.dialog p { font-size: 13.5px; color: var(--text-2); text-align: center; line-height: 1.6; }
.dialog__foot { display: flex; gap: 10px; margin-top: 20px; }
.dialog__foot .btn { flex: 1; }

/* --------------------------------------------------------------------------
   通用小件
   -------------------------------------------------------------------------- */

.flex { display: flex; }
.flex-c { display: flex; align-items: center; }
.flex-b { display: flex; align-items: center; justify-content: space-between; }
.flex-1 { flex: 1; min-width: 0; }
.gap-4 { gap: 4px; } .gap-6 { gap: 6px; } .gap-8 { gap: 8px; } .gap-10 { gap: 10px; } .gap-12 { gap: 12px; }
.mt-4 { margin-top: 4px; } .mt-6 { margin-top: 6px; } .mt-8 { margin-top: 8px; }
.mt-10 { margin-top: 10px; } .mt-12 { margin-top: 12px; } .mt-16 { margin-top: 16px; } .mt-20 { margin-top: 20px; }
.mb-8 { margin-bottom: 8px; } .mb-12 { margin-bottom: 12px; } .mb-16 { margin-bottom: 16px; }
.p-14 { padding: 14px; } .p-16 { padding: 16px; }
.tc { text-align: center; } .tr { text-align: right; }
.muted { color: var(--text-3); }
.muted-2 { color: var(--text-2); }
.strong { font-weight: 600; }
.fz-11 { font-size: 11px; } .fz-12 { font-size: 12px; } .fz-13 { font-size: 13px; } .fz-14 { font-size: 14px; }
.fz-15 { font-size: 15px; } .fz-16 { font-size: 16px; } .fz-17 { font-size: 17px; } .fz-18 { font-size: 18px; } .fz-20 { font-size: 20px; }
.ellipsis { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.divider { height: 1px; background: var(--line); margin: 12px 0; }
.hidden { display: none !important; }

/* --------------------------------------------------------------------------
   业务组件
   -------------------------------------------------------------------------- */

/* 搜索框 */
.search-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 12px;
  border-radius: 12px;
  background: rgba(255,255,255,.22);
  color: var(--on-brand);
}
.search-bar input {
  flex: 1;
  border: 0;
  background: transparent;
  color: var(--on-brand);
  font-size: 14px;
  min-width: 0;
}
.search-bar input::placeholder { color: rgba(15, 16, 20, .6); }
.search-bar--light { background: rgba(255, 255, 255, .07); border: 1px solid var(--line); color: var(--text); }
.search-bar--light input { color: var(--text); }
.search-bar--light input::placeholder { color: var(--text-3); }

/* 首页头部 */
.home-head {
  background: linear-gradient(150deg, var(--brand) 0%, var(--brand-2) 100%);
  padding: 0 14px 54px;
  padding-top: calc(10px + var(--safe-t));
  border-radius: 0 0 26px 26px;
  color: var(--on-brand);
  position: relative;
  overflow: hidden;
}
.home-head::after {
  content: '';
  position: absolute;
  right: -50px; top: -60px;
  width: 190px; height: 190px;
  border-radius: 50%;
  background: rgba(255,255,255,.10);
}
.home-head::before {
  content: '';
  position: absolute;
  right: 40px; top: 60px;
  width: 90px; height: 90px;
  border-radius: 50%;
  background: rgba(255,255,255,.07);
}
.home-head__brand { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; position: relative; z-index: 1; }
.home-head__logo {
  width: 34px; height: 34px;
  border-radius: 11px;
  background: rgba(255,255,255,.22);
  display: flex; align-items: center; justify-content: center;
  font-size: 17px;
  overflow: hidden;
}
.home-head__logo img { width: 100%; height: 100%; object-fit: cover; }
.home-head__name { font-size: 16px; font-weight: 600; letter-spacing: -.2px; }
.home-head__slogan { font-size: 11.5px; opacity: .8; margin-top: 1px; }
.home-head .search-bar { position: relative; z-index: 1; }

.home-body { margin-top: -42px; position: relative; z-index: 2; }

/* 公告 */
.notice-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 14px;
  background: var(--card-solid);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: none;
  font-size: 12.5px;
  color: var(--text-1);
  overflow: hidden;
}
.notice-bar .ico { color: var(--orange); font-size: 14px; flex-shrink: 0; }
.notice-bar .txt { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 轮播 */
.swiper {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding: 2px 14px;
  margin: 0 -14px;
  scrollbar-width: none;
}
.swiper::-webkit-scrollbar { display: none; }
.swiper__item {
  flex: 0 0 86%;
  scroll-snap-align: center;
  height: 116px;
  border-radius: var(--r-lg);
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  color: var(--on-brand);
  padding: 18px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
  overflow: hidden;
  box-shadow: 0 8px 22px rgba(16, 24, 40, .12);
}
.swiper__item h4 { font-size: 19px; letter-spacing: -.4px; margin-bottom: 4px; position: relative; z-index: 1; }
.swiper__item p { font-size: 12.5px; opacity: .88; position: relative; z-index: 1; }
.swiper__item::after {
  content: '';
  position: absolute;
  right: -30px; bottom: -40px;
  width: 130px; height: 130px;
  border-radius: 50%;
  background: rgba(255,255,255,.14);
}
.swiper__item img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.dots { display: flex; justify-content: center; gap: 5px; margin-top: 10px; }
.dots i { width: 5px; height: 5px; border-radius: 3px; background: var(--line-2); transition: all .2s; }
.dots i.on { width: 14px; background: var(--brand); }

/* 游戏分类 */
.cat-scroll {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 2px 14px;
  margin: 0 -14px;
  scrollbar-width: none;
}
.cat-scroll::-webkit-scrollbar { display: none; }
.cat-item {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  width: 62px;
  padding: 10px 4px;
  border-radius: 14px;
  background: var(--card-solid);
  box-shadow: none;
  transition: all .15s;
}
.cat-item.active { background: var(--brand); color: var(--on-brand); box-shadow: 0 6px 16px rgba(16, 24, 40, .12); }
.cat-item__icon { font-size: 21px; line-height: 1; }
.cat-item__name { font-size: 11.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.cat-item:active { transform: scale(.95); }

/* 服务卡 */
.svc-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.svc-card {
  background: var(--card-solid);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 14px;
  box-shadow: none;
  transition: transform .15s;
}
.svc-card:active { transform: scale(.98); }
.svc-card__icon { font-size: 24px; margin-bottom: 8px; }
.svc-card__name { font-size: 14.5px; font-weight: 600; margin-bottom: 3px; }
.svc-card__desc { font-size: 11.5px; color: var(--text-3); height: 32px; overflow: hidden; line-height: 1.45; }
.svc-card__foot { display: flex; align-items: baseline; justify-content: space-between; margin-top: 8px; }

/* 陪练师卡 */
.player-card {
  display: flex;
  gap: 12px;
  background: var(--card-solid);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 14px;
  box-shadow: none;
  margin-bottom: 10px;
  transition: transform .15s;
}
.player-card:active { transform: scale(.99); }
.player-card__main { flex: 1; min-width: 0; }
.player-card__name { display: flex; align-items: center; gap: 6px; font-size: 15px; font-weight: 600; }
.player-card__meta { font-size: 12px; color: var(--text-3); margin-top: 3px; }
.player-card__tags { margin-top: 7px; }
.player-card__foot { display: flex; align-items: flex-end; justify-content: space-between; margin-top: 9px; }
.player-card__right { text-align: right; flex-shrink: 0; display: flex; flex-direction: column; justify-content: space-between; align-items: flex-end; }

.rank-badge {
  display: inline-flex;
  align-items: center;
  height: 19px;
  padding: 0 7px;
  border-radius: 6px;
  font-size: 10.5px;
  background: linear-gradient(135deg, var(--brand-a22), var(--brand-a14));
  color: var(--brand);
  font-weight: 500;
}
.rank-badge--blue { background: rgba(46, 144, 250, .16); color: #7DB8F7; }

/* 订单卡 */
.order-card {
  background: var(--card-solid);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 14px 16px;
  margin-bottom: 10px;
  box-shadow: none;
}
.order-card__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.order-card__no { font-size: 11.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.order-card__status { font-size: 13px; font-weight: 600; }
.order-card__status.s-pending_pay { color: var(--orange); }
.order-card__status.s-paid { color: var(--blue); }
.order-card__status.s-accepted { color: var(--brand); }
.order-card__status.s-serving { color: var(--brand); }
.order-card__status.s-finished { color: var(--green); }
.order-card__status.s-settled { color: var(--green); }
.order-card__status.s-cancelled { color: var(--text-3); }
.order-card__status.s-refunded { color: var(--text-3); }
.order-card__status.s-disputed { color: var(--red); }

.order-card__body { display: flex; gap: 12px; }
.order-card__info { flex: 1; min-width: 0; }
.order-card__title { font-size: 15px; font-weight: 600; margin-bottom: 4px; }
.order-card__sub { font-size: 12.5px; color: var(--text-3); }
.order-card__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

/* 步骤条 */
.steps { display: flex; padding: 6px 0; }
.steps__item { flex: 1; text-align: center; position: relative; }
.steps__item::before {
  content: '';
  position: absolute;
  top: 8px; left: -50%;
  width: 100%; height: 2px;
  background: var(--line-2);
}
.steps__item:first-child::before { display: none; }
.steps__item.done::before, .steps__item.active::before { background: var(--brand); }
.steps__dot {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--line-2);
  margin: 0 auto 6px;
  position: relative;
  z-index: 1;
  display: flex; align-items: center; justify-content: center;
  font-size: 10px;
  color: var(--on-brand);
}
.steps__item.done .steps__dot, .steps__item.active .steps__dot { background: var(--brand); }
.steps__label { font-size: 11px; color: var(--text-3); }
.steps__item.done .steps__label, .steps__item.active .steps__label { color: var(--text-1); font-weight: 500; }

/* 时间轴 */
.timeline { padding-left: 4px; }
.timeline__item { position: relative; padding: 0 0 16px 20px; }
.timeline__item::before {
  content: '';
  position: absolute;
  left: 3px; top: 6px;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--line-2);
}
.timeline__item:first-child::before { background: var(--brand); box-shadow: 0 0 0 3px var(--brand-a14); }
.timeline__item::after {
  content: '';
  position: absolute;
  left: 6px; top: 16px; bottom: 0;
  width: 1px;
  background: var(--line);
}
.timeline__item:last-child { padding-bottom: 0; }
.timeline__item:last-child::after { display: none; }
.timeline__text { font-size: 13.5px; }
.timeline__time { font-size: 11.5px; color: var(--text-3); margin-top: 2px; }

/* 统计块 */
.stat-row { display: flex; }
.stat-cell { flex: 1; text-align: center; padding: 4px 0; }
.stat-cell__num { font-size: 19px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -.4px; }
.stat-cell__label { font-size: 11.5px; color: var(--text-3); margin-top: 2px; }

/* 筛选栏 */
.filter-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  overflow-x: auto;
  scrollbar-width: none;
  background: var(--bg);
  position: sticky;
  top: 52px;
  z-index: 50;
}
.filter-bar::-webkit-scrollbar { display: none; }
.filter-bar .chip { flex-shrink: 0; height: 32px; font-size: 13px; }

/* 底部安全占位 */
.safe-bottom { height: 20px; }

/* 表单行 */
.form-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 16px;
  background: var(--card-solid);
  position: relative;
}
.form-row + .form-row::before {
  content: '';
  position: absolute; left: 16px; right: 0; top: 0;
  height: 1px; background: var(--line);
}
.form-row__label { width: 82px; font-size: 14px; color: var(--text-1); flex-shrink: 0; }
.form-row__label .req { color: var(--red); }
.form-row input, .form-row textarea, .form-row select {
  flex: 1;
  border: 0;
  background: transparent;
  font-size: 14.5px;
  min-width: 0;
  padding: 0;
}
.form-row textarea { resize: none; min-height: 24px; line-height: 1.6; padding: 3px 0; }
.form-row .arrow { color: var(--line-2); font-size: 16px; flex-shrink: 0; }

/* 上传 */
.upload-box {
  width: 84px; height: 84px;
  border-radius: 14px;
  border: 1px dashed var(--line-2);
  background: rgba(255, 255, 255, .04);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  color: var(--text-3);
  font-size: 11.5px;
  position: relative;
  overflow: hidden;
}
.upload-box .plus { font-size: 22px; line-height: 1; color: var(--line-2); }
.upload-box img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.upload-box input[type=file] { position: absolute; inset: 0; opacity: 0; }

/* 客服浮标 */
.cs-float {
  position: fixed;
  right: 14px;
  bottom: calc(78px + var(--safe-b));
  width: 46px; height: 46px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .92);
  border: 1px solid var(--line);
  box-shadow: 0 6px 20px rgba(16, 24, 40, .14);
  display: flex; align-items: center; justify-content: center;
  font-size: 21px;
  z-index: 64;
}
@media (min-width: 900px) { .cs-float { right: calc(50% - 216px); } }

/* 数据表（H5 内的简易表） */
.kv { display: flex; justify-content: space-between; padding: 7px 0; font-size: 13.5px; }
.kv .k { color: var(--text-2); }
.kv .v { color: var(--text); font-weight: 500; text-align: right; }

/* 富文本 */
.rich { font-size: 14px; line-height: 1.8; color: var(--text-1); white-space: pre-wrap; word-break: break-word; }

/* 等宽数字/编号 */
.mono { font-family: ui-monospace, "SFMono-Regular", Consolas, "Courier New", monospace; font-variant-numeric: tabular-nums; }

/* 提示条 */
.tip-box {
  display: flex;
  gap: 9px;
  padding: 12px 14px;
  border-radius: 12px;
  font-size: 12.5px;
  line-height: 1.7;
  margin-bottom: 12px;
  background: var(--brand-soft);
  color: var(--brand);
}
.tip-box--warn { background: var(--orange-soft); color: #E8A33D; }
.tip-box--info { background: var(--blue-soft); color: #7DB8F7; }
.tip-box--danger { background: var(--red-soft); color: #F08A80; }
.tip-box--ok { background: var(--green-soft); color: #4FD1A5; }
.tip-box b { font-weight: 600; }
.tip-box + .tip-box { margin-top: -4px; }

/* 不可用遮罩页 */
.blocked { padding: 60px 24px; text-align: center; }

/* ==========================================================================
   玻璃拟态主题层
   —— 所有「面板 / 按钮 / 输入框 / 弹层」统一改成半透明磨砂
   —— 放在文件最后，靠层叠顺序覆盖上面的基础样式；想换回实心风格，
      把这一整段删掉即可，上面的规则本身是完整的
   ========================================================================== */

/* ---------------- 1. 固定在屏幕上的三条玻璃条 ----------------
 * ⚠️ 这几条原来都在这里重新声明了 background / backdrop-filter，
 * 把上面那些 .55 / .38 的玻璃值又覆盖成 .72 / .86（半实心），
 * 所以「改成玻璃态看着没变化」。现在只保留滚动后的加深，其余交给上面的定义。
 */

.zc-nav.scrolled {
  background: rgba(255, 255, 255, .87);
  border-bottom-color: var(--glass-edge);
}
/* 品牌头：金底 + 深色字（金底白字只有 2:1，糊成一片） */
.zc-nav--brand {
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  color: var(--on-brand);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: none;
}
.zc-nav--brand .zc-nav__btn { color: var(--on-brand); }

/*
 * ⚠️ 这里原来还有一条 .zc-tabbar 规则（玻璃拟态主题层），把背景重新设成 .5、模糊 26px，
 * 结果把上面那条改成 .38 / 30px 的胶囊玻璃又覆盖回去了 —— 改了没效果就是这个原因。
 * 底栏的样式统一由上面那一条负责，这里不再重复声明。
 */

.action-bar {
  background: rgba(255, 255, 255, .55);
  -webkit-backdrop-filter: saturate(180%) blur(22px);
  backdrop-filter: saturate(180%) blur(22px);
  border-top: 1px solid var(--glass-edge);
  box-shadow: none;
}

.cs-float {
  background: rgba(255, 255, 255, .92);
  -webkit-backdrop-filter: var(--glass-blur-sm);
  backdrop-filter: var(--glass-blur-sm);
  border: 1px solid var(--glass-edge);
  box-shadow: 0 6px 20px rgba(16, 24, 40, .14);
}

/* ---------------- 2. 面板 / 卡片 ---------------- */

.card,
.list,
.notice-bar,
.player-card,
.order-card,
.svc-card,
.cat-item,
.ranking-item,
.review-item {
  background: var(--glass);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-edge);
  box-shadow: none;
}

.card { border-radius: var(--r); }
.card--flat { background: var(--glass-weak); box-shadow: none; }

.player-card,
.order-card,
.svc-card { border-radius: 16px; }

.cat-item { background: var(--glass-weak); box-shadow: none; }
.cat-item.active {
  background: var(--brand);
  border-color: transparent;
  color: var(--on-brand);
  box-shadow: 0 6px 16px rgba(16, 24, 40, .10);
}
.cat-item.active .cat-item__name { font-weight: 600; }

.list-item:active { background: rgba(255, 255, 255, .06); }
.list-item + .list-item::before { background: var(--line); }

.divider { background: var(--line); }

/* 表单行（个人中心 / 入驻页用的那种） */
.form-row { background: var(--glass); }
.form-row + .form-row::before { background: var(--line); }

/* ---------------- 3. 按钮：半透明磨砂 ---------------- */

.btn {
  background: rgba(255, 255, 255, .07);
  border: 1px solid var(--glass-edge);
  color: var(--text-1);
  border-radius: 12px;
  font-weight: 500;
  -webkit-backdrop-filter: var(--glass-blur-sm);
  backdrop-filter: var(--glass-blur-sm);
  box-shadow: none;
  transition: background .16s, box-shadow .16s, transform .12s;
}
.btn:hover { background: rgba(255, 255, 255, .12); }
.btn:active { transform: scale(.975); }

.btn--primary {
  background: var(--brand);
  border: 1px solid transparent;
  color: var(--on-brand);
  -webkit-backdrop-filter: var(--glass-blur-sm);
  backdrop-filter: var(--glass-blur-sm);
  box-shadow: 0 8px 20px rgba(16, 24, 40, .10);
}
.btn--primary:hover { filter: brightness(1.06); }

.btn--ghost {
  background: var(--brand-soft);
  border-color: transparent;
  color: var(--brand);
  box-shadow: none;
}

.btn--line {
  background: transparent;
  border: 1px solid var(--line-2);
  color: var(--text-1);
  box-shadow: none;
}
.btn--line:hover { background: rgba(16, 24, 40, .05); }

.btn--danger {
  background: var(--red-soft);
  border-color: rgba(240, 68, 56, .28);
  color: var(--red);
  box-shadow: none;
}

.btn--white {
  background: var(--card-solid);
  border: 1px solid var(--glass-edge);
  color: var(--text);
  box-shadow: none;
}

/* ---------------- 4. 表单控件 ---------------- */

.input, .textarea, .select {
  background: var(--card-solid);
  border: 1px solid var(--line-2);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: none;
}
.input:focus, .textarea:focus, .select:focus {
  background: var(--card-solid);
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-a08);
}
.input[disabled] { background: rgba(255, 255, 255, .05); }

.input-group {
  background: var(--card-solid);
  border: 1px solid var(--line-2);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: none;
}
.input-group .input { background: transparent; border: 0; box-shadow: none !important; }
.input-group:focus-within { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-a08); }

.chip {
  background: rgba(255, 255, 255, .06);
  border: 1px solid transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: none;
  font-weight: 500;
  color: var(--text-2);
}
.chip.active {
  background: var(--brand);
  border-color: transparent;
  color: var(--on-brand);
  box-shadow: none;
}

.search-bar--light {
  background: rgba(255, 255, 255, .07);
  border: 1px solid transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.search-bar { background: rgba(255, 255, 255, .08); border: 1px solid var(--line-2); }

.switch { background: rgba(255, 255, 255, .16); }
.switch.on { background: var(--brand); }
.switch::after { box-shadow: 0 1px 3px rgba(16, 24, 40, .12); }

.upload-box {
  background: rgba(255, 255, 255, .05);
  border: 1px dashed var(--line-2);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* ---------------- 5. 标签 / 徽章 ---------------- */

.tag {
  background: rgba(255, 255, 255, .07);
  border: 1px solid transparent;
  color: var(--text-2);
  font-weight: 500;
}
.tag--brand { background: var(--brand-soft); border-color: transparent; color: var(--brand); }
.tag--green { background: var(--green-soft); border-color: transparent; color: #4FD1A5; }
.tag--orange { background: var(--orange-soft); border-color: transparent; color: #E8A33D; }
.tag--red { background: var(--red-soft); border-color: transparent; color: #F08A80; }
.tag--blue { background: var(--blue-soft); border-color: transparent; color: #7DB8F7; }
.tag--line { background: transparent; border: 1px solid var(--line-2); color: var(--text-3); }

.avatar {
  background: var(--brand-soft);
  border: 1px solid var(--glass-edge);
  box-shadow: none;
}
.avatar .online-dot { border-color: var(--card-solid); }

/* ---------------- 6. 弹层 ---------------- */

.mask {
  background: rgba(0, 0, 0, .55);
  -webkit-backdrop-filter: blur(4px) saturate(120%);
  backdrop-filter: blur(4px) saturate(120%);
}

.sheet {
  background: var(--card-solid);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-edge);
  border-bottom: 0;
  box-shadow: 0 -12px 40px rgba(16, 24, 40, .16);
}
.sheet__foot { background: transparent; border-top: 1px solid var(--line); }
.sheet__close { background: rgba(255, 255, 255, .08); border: 0; }

.dialog {
  background: var(--card-solid);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-edge);
  box-shadow: 0 24px 60px rgba(16, 24, 40, .18);
}

/* Toast：改成浅底深字，暗色底上才看得清 */
.zc-toast {
  background: rgba(28, 32, 56, .88);
  color: #FFFFFF;
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  backdrop-filter: blur(14px) saturate(160%);
  border: 0;
  box-shadow: 0 12px 32px rgba(16, 24, 40, .16);
}

/* ---------------- 7. 首页头部 & 轮播 ---------------- */

.home-head {
  background: linear-gradient(150deg, var(--brand) 0%, var(--brand-2) 100%);
  color: var(--on-brand);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: 0 14px 40px rgba(16, 24, 40, .14);
}

.swiper__item {
  border: 1px solid var(--line-2);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
.swiper__item::after { background: rgba(255, 255, 255, .16); }

/* ---------------- 8. 状态色块 & 提示条 ---------------- */

.tip-box {
  background: var(--brand-soft);
  border: 1px solid var(--brand-a22);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: var(--brand);
}
.tip-box--warn { background: var(--orange-soft); border-color: rgba(247, 144, 9, .2); color: #E8A33D; }
.tip-box--info { background: var(--blue-soft); border-color: rgba(46, 144, 250, .18); color: #7DB8F7; }
.tip-box--danger { background: var(--red-soft); border-color: rgba(240, 68, 56, .18); color: #F08A80; }
.tip-box--ok { background: var(--green-soft); border-color: rgba(18, 183, 106, .18); color: #4FD1A5; }

.skeleton { background: linear-gradient(90deg, rgba(255,255,255,.05) 25%, rgba(255,255,255,.10) 37%, rgba(255,255,255,.05) 63%); background-size: 400% 100%; }

/* ---------------- 9. 不支持毛玻璃时的兜底 ---------------- */

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .card, .list, .notice-bar, .player-card, .order-card, .svc-card, .cat-item,
  .form-row, .zc-nav, .zc-tabbar, .action-bar, .sheet, .dialog,
  .hm-stats, .hm-good, .hm-search {
    background: var(--card-solid);
  }
  .btn { background: var(--card-solid); }
  .btn--primary { background: var(--brand); }
  .input, .textarea, .select, .input-group { background: var(--card-solid); }
  /* 底部 Tab：浮动胶囊在不支持毛玻璃时用不透明深色，避免透出内容 */
  .zc-tabbar { background: var(--card-solid); }
  body::before { opacity: .6; }
}

/* ==========================================================================
   首页组件（2025 重做）
   —— 去掉大色块、彩色方格和 emoji，改成排版驱动 + 线性图标
   ========================================================================== */

/* 图标占位容器：<i> 里包 SVG，统一消掉基线间隙 */
.hm-iconbtn i,
.hm-sec__head a i,
.me-grid .ico i { display: flex; align-items: center; justify-content: center; line-height: 0; }
.hm-sec__head a i { margin-top: 1px; }

/* ---------------- 顶栏 ---------------- */

.hm-nav { display: flex; align-items: center; gap: 8px; }
.hm-brand { display: flex; align-items: center; gap: 9px; flex: 1; min-width: 0; }
.hm-logo {
  width: 34px; height: 34px; border-radius: 11px;
  background: var(--brand); color: var(--on-brand);
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 600; overflow: hidden; flex-shrink: 0;
}
.hm-logo img { width: 100%; height: 100%; object-fit: cover; }
.hm-brand__name { font-size: 15px; font-weight: 600; letter-spacing: -.2px; line-height: 1.2; }
.hm-brand__slogan {
  font-size: 11px; color: var(--text-3); margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hm-iconbtn {
  width: 36px; height: 36px; border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-1); position: relative; flex-shrink: 0;
  transition: background .15s;
}
.hm-iconbtn:active { background: rgba(255, 255, 255, .08); }
.hm-iconbtn .dot {
  position: absolute; top: 7px; right: 8px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--red); border: 1.5px solid var(--card-solid);
}

/* ---------------- Hero：大 Banner 海报（商城风） ---------------- */

.hm-hero {
  position: relative;
  margin-top: 4px;
  height: 192px;
  border-radius: 16px;
  overflow: hidden;
  background: rgba(255, 255, 255, .05);
  box-shadow: none;
  border: 1px solid var(--line);
}
.hm-hero__track {
  display: flex;
  height: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.hm-hero__track::-webkit-scrollbar { display: none; }
.hm-hero__slide {
  flex: 0 0 100%;
  height: 100%;
  position: relative;
  scroll-snap-align: start;
  padding: 24px 18px 0;
  color: var(--on-brand);
  background: linear-gradient(140deg, var(--brand) 0%, var(--brand-2) 100%);
}
.hm-hero__slide > img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
}
.hm-hero__slide::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(16,24,40,.06) 0%, rgba(16,24,40,.46) 100%);
  pointer-events: none;
}
.hm-hero__tx { position: relative; z-index: 1; }
.hm-hero__eyebrow { font-size: 11px; letter-spacing: 1.2px; opacity: .82; }
.hm-hero__title { font-size: 24px; font-weight: 700; letter-spacing: -.7px; line-height: 1.26; margin-top: 6px; }
.hm-hero__sub { font-size: 12.5px; opacity: .88; margin-top: 7px; }

.hm-hero__dots {
  position: absolute; right: 14px; top: 16px; z-index: 3;
  display: flex; gap: 4px;
}
.hm-hero__dots i {
  width: 5px; height: 5px; border-radius: 3px;
  background: rgba(255, 255, 255, .45);
  transition: width .2s, background .2s;
}
.hm-hero__dots i.on { width: 14px; background: var(--on-brand); }

/* 搜索框叠在 Banner 上 */
.hm-search {
  position: absolute;
  left: 14px; right: 14px; bottom: 14px;
  z-index: 3;
  display: flex; align-items: center; gap: 7px;
  height: 40px; padding: 0 14px;
  border-radius: 20px;
  background: rgba(255, 255, 255, .93);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: 0 4px 14px rgba(16, 24, 40, .12);
  color: var(--text-3);
}
.hm-search input {
  flex: 1; min-width: 0;
  border: 0; background: transparent; outline: none;
  font-size: 13px; color: var(--text);
  font-family: inherit;
}
.hm-search input::placeholder { color: var(--text-3); }

/* 数据条 */
.hm-stats {
  display: flex; align-items: stretch;
  margin-top: 10px;
  padding: 11px 4px;
  background: var(--glass);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-edge);
  border-radius: 14px;
  box-shadow: none;
}
.hm-stat { flex: 1; text-align: center; position: relative; }
.hm-stat + .hm-stat::before {
  content: ''; position: absolute; left: 0; top: 3px; bottom: 3px;
  width: 1px; background: var(--line);
}
.hm-stat__n {
  font-size: 16.5px; font-weight: 600; letter-spacing: -.4px;
  font-variant-numeric: tabular-nums; color: var(--text);
}
.hm-stat__n small { font-size: 11px; font-weight: 500; color: var(--text-3); margin-left: 1px; }
.hm-stat__l { font-size: 10.5px; color: var(--text-3); margin-top: 1px; }

/* ---------------- 分类：方形缩略图（商城风） ---------------- */

.hm-cats {
  display: flex; gap: 10px;
  overflow-x: auto;
  scrollbar-width: none;
  margin: 0 -14px;
  padding: 2px 14px 4px;
}
.hm-cats::-webkit-scrollbar { display: none; }

.hm-cat { width: 68px; flex-shrink: 0; }
.hm-cat__box {
  width: 68px; height: 68px;
  border-radius: 14px;
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  font-size: 29px;
  background: rgba(255, 255, 255, .05);
  border: 1px solid var(--glass-edge);
  box-shadow: none;
}
.hm-cat__box img { width: 100%; height: 100%; object-fit: cover; }
.hm-cat__name {
  font-size: 11px; color: var(--text-2);
  margin-top: 6px; line-height: 1.35; text-align: center;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.hm-cat:active .hm-cat__box { transform: scale(.96); }

/* ---------------- 区块标题（带图标前缀） ---------------- */

.hm-sec { margin-top: 22px; }
.hm-sec__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px;
  margin: 0 2px 11px;
}
.hm-sec__head h2 {
  display: flex; align-items: center; gap: 6px;
  font-size: 16px; font-weight: 600; letter-spacing: -.35px;
}
.hm-sec__head h2 i { display: flex; color: var(--brand); }
.hm-sec__head a { font-size: 12.5px; color: var(--text-3); display: inline-flex; align-items: center; gap: 2px; flex-shrink: 0; }
.hm-sec__head a:active { color: var(--brand); }

/* ---------------- 商品网格（3 列，商城风） ---------------- */

.hm-goods { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }

.hm-good {
  display: flex; flex-direction: column;
  background: var(--glass);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-edge);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: none;
  transition: transform .14s;
}
.hm-good:active { transform: scale(.985); }

.hm-good__box {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  display: flex; align-items: center; justify-content: center;
  font-size: 34px;
  background: rgba(255, 255, 255, .05);
  overflow: hidden;
}
.hm-good__box img { width: 100%; height: 100%; object-fit: cover; }
.hm-good__tag {
  position: absolute; left: 6px; top: 6px;
  height: 18px; padding: 0 6px;
  border-radius: 6px;
  background: rgba(0, 0, 0, .62);
  color: #fff;
  font-size: 10px; line-height: 18px; font-weight: 500;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

.hm-good__body { padding: 9px 10px 10px; display: flex; flex-direction: column; flex: 1; }
.hm-good__name {
  font-size: 12.5px; font-weight: 500; line-height: 1.35; color: var(--text);
  min-height: 34px;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.hm-good__foot {
  margin-top: auto; padding-top: 8px;
  display: flex; align-items: center; justify-content: space-between; gap: 5px;
}
.hm-good__price {
  color: var(--red);
  font-size: 14px; font-weight: 600; letter-spacing: -.3px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden;
}
.hm-good__price small { font-size: 10px; font-weight: 500; opacity: .78; margin-left: 1px; }
.hm-good__price--muted { color: var(--text-3); font-size: 12px; font-weight: 500; }
.hm-good__plus {
  width: 22px; height: 22px; flex-shrink: 0;
  border-radius: 50%;
  border: 1.5px solid var(--red);
  color: var(--red);
  display: flex; align-items: center; justify-content: center;
  transition: background .14s, color .14s;
}
.hm-good__plus:active { background: var(--red); color: #fff; }

/* ---------------- 陪练师卡片（重做） ---------------- */

.player-card {
  display: flex;
  gap: 13px;
  padding: 13px 14px;
  align-items: flex-start;
}
.player-card .avatar--lg { width: 54px; height: 54px; border-radius: 16px; font-size: 19px; }
.player-card__main { padding-top: 1px; }
.player-card__name {
  font-size: 15px; font-weight: 600; letter-spacing: -.25px;
  display: flex; align-items: center; gap: 6px;
}
.player-card__meta {
  font-size: 12px; color: var(--text-3); margin-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.player-card__meta b { color: var(--text-2); font-weight: 500; }
.player-card__tags { margin-top: 8px; }
.player-card__foot {
  margin-top: 10px;
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
}
.player-card__foot .price { font-size: 16px; }
.player-card__foot .price .num { font-weight: 600; }

/* ---------------- 公告列表（首页底部） ---------------- */

.hm-notice { padding: 2px 0; }
.hm-notice__item { display: flex; gap: 10px; padding: 13px 14px; position: relative; }
.hm-notice__item + .hm-notice__item::before {
  content: ''; position: absolute; left: 14px; right: 14px; top: 0;
  height: 1px; background: var(--line);
}
.hm-notice__dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--brand); flex-shrink: 0; margin-top: 7px;
}
.hm-notice__t { font-size: 13.5px; font-weight: 500; letter-spacing: -.15px; }
.hm-notice__c {
  font-size: 12px; color: var(--text-3); margin-top: 3px; line-height: 1.6;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.hm-notice__d { font-size: 11px; color: var(--text-3); margin-top: 5px; }

/* ==========================================================================
   分类页：左侧分类栏 + 右侧商品网格
   ========================================================================== */

.ct-wrap {
  display: flex;
  height: calc(100vh - 52px);
  overflow: hidden;
}
@supports (height: 100dvh) {
  .ct-wrap { height: calc(100dvh - 52px); }
}

/* 左侧分类栏 */
.ct-aside {
  width: 94px;
  flex-shrink: 0;
  overflow-y: auto;
  background: rgba(255, 255, 255, .04);
  padding: 6px 0 calc(92px + var(--safe-b));
  scrollbar-width: none;
}
.ct-aside::-webkit-scrollbar { display: none; }

.ct-cat {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  min-height: 54px;
  padding: 9px 6px;
  font-size: 12.5px;
  color: var(--text-2);
  text-align: center;
  line-height: 1.3;
  word-break: break-all;
  transition: background .15s, color .15s;
}
/*
 * ★ 2026-10-14 第八批：分类图标位（老模板，老板「之前的模板也要有图片」）
 *   .ct-cat 本来就是竖排 flex（图标在上、名字在下、数量再下一行），这里只补图标那格的尺寸。
 *   ⚠️ 只**新增**这些类，上面 .ct-cat 的规则一个字没动 —— 老模板那些锁死的断言不看它。
 *   ⚠️ 图片和 emoji 两种都要好看：给了固定 22×22 的圆角方块（img 用 object-fit 铺满，
 *      emoji 用 font-size 撑起来），所以站长传方图/长图都不会把左栏撑变形。
 *   ⚠️ 图挂了由页面里的 bindIcoFallback 换回 emoji，不留破图（灰线图标不用在这儿）。
 */
.ct-cat__ico {
  width: 22px; height: 22px; border-radius: 7px; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 2px; flex-shrink: 0;
}
.ct-cat__ico img { width: 100%; height: 100%; object-fit: cover; }
.ct-ico__emo { font-style: normal; font-size: 17px; line-height: 1; }
/*
 * ★ 2026-10-15：分类图标图（public/h5/category.html 的 catIcoHtml 输出）的**兜底尺寸**。
 *
 * ⚠️ 为什么要有它：catIcoHtml 出的是裸 <img>，尺寸靠各上下文自己写 img 规则 ——
 *    「分组小标题」那处漏写了，站长把一级分类图标传成**图片**时，这张图就按**原尺寸**渲染：
 *    撑满整屏、把「王者荣耀 N 件」挤成一字宽的竖排、从右边跑出边界
 *    （老板 2026-10-15 截图「大图没修复」就是这个）。
 *    有了这一条，以后任何**忘了写规则**的新上下文最多是个 22px 小图标，不会再撑爆页面。
 * ⚠️ 各上下文用的是**后代选择器**（.ct-cat__ico img 等，权重 0,1,1 > 这里的 0,1,0），
 *    所以这条不会盖掉已经在用的大图卡 / 左栏图标。
 */
.ct-ico__img { width: 22px; height: 22px; border-radius: 7px; object-fit: cover; flex: 0 0 auto; }
/* 首页分类格里的图片图标（.hm-cat__box 是那个 40×40 的圆角方块） */
.hm-cat__ico { width: 100%; height: 100%; object-fit: cover; }
.ct-cat__n { font-size: 10px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.ct-cat.active {
  background: var(--card-solid);
  color: var(--brand);
  font-weight: 600;
}
.ct-cat.active .ct-cat__n { color: var(--brand); opacity: .7; }
.ct-cat.active::before {
  content: '';
  position: absolute; left: 0; top: 50%;
  transform: translateY(-50%);
  width: 3px; height: 18px;
  border-radius: 0 3px 3px 0;
  background: var(--brand);
}
.ct-cat:active { background: rgba(255, 255, 255, .08); }

/* 右侧内容 */
.ct-main {
  flex: 1;
  min-width: 0;
  overflow-y: auto;
  padding: 12px 12px calc(92px + var(--safe-b));
  -webkit-overflow-scrolling: touch;
}
.ct-head {
  display: flex; align-items: center; gap: 6px;
  margin: 2px 2px 12px;
  font-size: 15px; font-weight: 600; letter-spacing: -.3px;
}
.ct-head span { font-size: 11.5px; font-weight: 400; color: var(--text-3); }
.ct-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.ct-grid .hm-good__box { font-size: 40px; }
.ct-grid .hm-good__name { font-size: 13px; min-height: 36px; }
.ct-grid .hm-good__price { font-size: 15px; }
.ct-grid .hm-good__plus { width: 24px; height: 24px; }

/* 分类页的吸附小标题（「全部」视图里按游戏分组时用） */
.ct-group { margin-bottom: 18px; }
.ct-group__h {
  display: flex; align-items: center; gap: 6px;
  margin: 0 2px 9px;
  font-size: 13.5px; font-weight: 600;
  color: var(--text-1);
}
.ct-group__h span { font-size: 11px; font-weight: 400; color: var(--text-3); }
/*
 * ⚠️⚠️ 分组小标题里的分类图标**必须限死尺寸**（2026-10-15 修的就是这一条）。
 *
 *   .ct-group__h 原来是「图标 + 名字 + N 件」的 flex 行，可**只给了 span 字号、没给 img 尺寸**
 *   （左栏 .ct-cat__ico img、大图卡 .ct-big__i img 那两处都写了，就这一处漏了）。
 *   站长把一级分类图标传成**图片**时（第八批起 icon 允许 ≤500 字的图片地址）：
 *     · 图按原尺寸渲染 → 一行标题被撑成整屏大图；
 *     · 名字被挤到只剩一个字的宽度 → 中文逐字换行（看着像竖排）并从右边跑出边界。
 *   → 这就是老板 2026-10-15 截图说的「大图没修复」。
 *   ⚠️ 和 2026-10-14 那次 transform 事故**不是一回事**（那次是动画改了绝对定位子元素的参照系，
 *      见 docs/发版规范.md:1659）—— 这次是**图没尺寸**。两处现在都各自修好了，别再混为一谈。
 *   ⚠️ 它是「图标」不是「大图」，18px 和标题的 15px 是一档；别为了好看放大它。
 */
.ct-group__h img { width: 18px; height: 18px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }

/* ==========================================================================
   在线客服浮层（public/assets/js/chat.js 动态创建，前缀 ch-）
   —— 浮标复用上面已有的 .cs-float（右下角那颗），这里只加红点数字和面板
   ========================================================================== */

/* 浮标本体（定位 / 尺寸）在上面那条 .cs-float 里，这里只补交互和红点 */
.cs-float { cursor: pointer; padding: 0; }
.cs-float:active { transform: scale(.94); }
/* 图标居中：svg 用 block + margin auto（不用 flex，免得父级的居中把红点的 display:none 顶掉） */
.cs-float .ch-ico { display: block; line-height: 0; color: var(--brand); }
.cs-float .ch-ico svg { display: block; margin: 0 auto; }
.ch-badge {
  position: absolute;
  top: -3px; right: -3px;
  min-width: 18px; height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--red);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  line-height: 18px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 2px 6px rgba(16, 24, 40, .22);
}
.ch-badge--hide { display: none; }

/* 面板：手机上贴底整宽，桌面上固定在右下角 */
.ch-panel {
  position: fixed;
  left: 12px; right: 12px;
  bottom: calc(78px + var(--safe-b));
  height: 72vh;
  max-height: 520px;
  display: none;
  flex-direction: column;
  z-index: 68;
  background: var(--glass-strong);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-l);
  overflow: hidden;
}
.ch-panel.open { display: flex; }
@media (min-width: 900px) {
  .ch-panel {
    left: auto;
    width: 360px;
    right: calc(50% - 216px);
    bottom: 132px;
    height: 480px;
  }
}

.ch-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}
.ch-head__ico {
  width: 32px; height: 32px; border-radius: 11px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--brand-soft); color: var(--brand);
}
.ch-head__main { flex: 1; min-width: 0; }
.ch-head__t { font-size: 14.5px; font-weight: 600; letter-spacing: -.2px; }
.ch-head__s { font-size: 11.5px; color: var(--text-3); margin-top: 1px; }
.ch-x {
  width: 30px; height: 30px; flex-shrink: 0;
  border: 0; background: transparent; color: var(--text-2);
  border-radius: 10px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  line-height: 0;
}
.ch-x:active { background: var(--line); }

/* 消息区 */
.ch-body {
  flex: 1; min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 12px 14px;
  display: flex; flex-direction: column; gap: 10px;
}
.ch-tip {
  text-align: center;
  font-size: 11.5px;
  color: var(--text-3);
  line-height: 1.7;
  padding: 4px 8px;
}
.ch-row { display: flex; gap: 8px; align-items: flex-end; max-width: 100%; }
.ch-row--me { flex-direction: row-reverse; }
.ch-avatar {
  width: 28px; height: 28px; border-radius: 10px; flex-shrink: 0;
  background: var(--brand-soft); color: var(--brand);
  display: flex; align-items: center; justify-content: center;
  font-size: 11.5px; font-weight: 600;
  overflow: hidden;
}
.ch-avatar img { width: 100%; height: 100%; object-fit: cover; }
.ch-bubble {
  max-width: 78%;
  padding: 9px 12px;
  border-radius: 14px 14px 14px 5px;
  background: var(--card-solid);
  border: 1px solid var(--line);
  font-size: 13.5px;
  line-height: 1.62;
  color: var(--text);
  word-break: break-word;
  white-space: pre-wrap;
}
.ch-row--me .ch-bubble {
  border-radius: 14px 14px 5px 14px;
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-brand);
}
.ch-bubble img { display: block; max-width: 100%; border-radius: 10px; }
.ch-name { font-size: 10.5px; color: var(--text-3); margin-bottom: 3px; }

/* 订单卡片 */
.ch-order {
  display: block;
  min-width: 168px;
  padding: 9px 11px;
  border-radius: 12px;
  background: var(--brand-a08);
  border: 1px solid var(--brand-a22);
  color: var(--text);
  font-size: 12.5px;
  line-height: 1.6;
}
.ch-row--me .ch-order { background: rgba(255, 255, 255, .18); border-color: rgba(255, 255, 255, .3); color: var(--on-brand); }
.ch-order__t { font-weight: 600; display: flex; align-items: center; gap: 5px; }
.ch-order__no { font-size: 11px; opacity: .8; font-family: ui-monospace, Consolas, monospace; }

/* 输入区 */
.ch-foot {
  flex-shrink: 0;
  display: flex; align-items: flex-end; gap: 8px;
  padding: 10px 12px calc(10px + var(--safe-b));
  border-top: 1px solid var(--line);
}
.ch-input {
  flex: 1; min-width: 0;
  min-height: 38px; max-height: 96px;
  padding: 9px 12px;
  border-radius: 12px;
  border: 1px solid var(--line-2);
  background: rgba(255, 255, 255, .86);
  color: var(--text);
  font-family: var(--font);
  font-size: 13.5px;
  line-height: 1.5;
  resize: none;
  outline: none;
}
.ch-input:focus { border-color: var(--brand-a45); }
.ch-send {
  flex-shrink: 0;
  height: 38px; padding: 0 15px;
  border: 0; border-radius: 12px;
  background: var(--brand); color: var(--on-brand);
  font-size: 13.5px; font-weight: 600;
  cursor: pointer;
}
.ch-send:disabled { opacity: .5; cursor: default; }
.ch-send:active { transform: scale(.97); }

/* 手机端：面板贴底时不要被 tabbar 顶住 */
@media (max-width: 899px) {
  .ch-panel { border-radius: var(--r-lg) var(--r-lg) var(--r) var(--r); }
}

/* ==========================================================================
   在线客服 · 整页（public/h5/service.html，chat.js 的 ZCChat.mountPage 建）
   —— 气泡 / 头像 / 订单卡 / 输入框全部复用上面那套 .ch-*，这里只加骨架
   ========================================================================== */

/*
 * 高度口径和 .zc-main.has-tabbar 完全一致（86px + --safe-b 是给胶囊 tabbar 留的位置）：
 *   视口 - 顶栏 52px - 底栏预留 86px - 安全区
 * 所以输入栏永远不会被 tabbar 压住，消息区也不会跑到屏幕外。
 *   · 1dvh 优先：手机上键盘弹起时它跟着缩，光靠 CSS 就能用
 *   · 不认 dvh 的浏览器退回 100vh，并由 chat.js 的 visualViewport 写 --svc-h 兜底
 *   · --safe-t 不额外减：页面顶栏自己带了 padding-top: var(--safe-t)
 */
.ch-page {
  position: relative;          /* 「回到最新」按钮的定位上下文 */
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: var(--svc-h, calc(100vh - 138px - var(--safe-b)));
}
@supports (height: 100dvh) {
  .ch-page { height: var(--svc-h, calc(100dvh - 138px - var(--safe-b))); }
}
/* 窄屏横屏 / 小高度设备：只留 100px 给消息区，别把输入栏挤没 */
@media (max-height: 460px) {
  .ch-page { min-height: 260px; }
}

/* 页头：和浮层 .ch-head 一个观感（图标 + 客服名 + 状态行） */
.ch-page__hd {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}
.ch-page__hd .ch-head__ico { width: 36px; height: 36px; border-radius: 12px; }
.ch-page__t { font-size: 15.5px; font-weight: 600; letter-spacing: -.25px; }
.ch-page__s { font-size: 11.5px; color: var(--text-3); margin-top: 1px; }

/* 消息区：占满剩余高度，独立滚动 */
.ch-page__body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
/*
 * 整页比浮层宽，气泡放到 82% 更舒展。
 * ⚠️ 气泡自己在 .ch-bubble 上写着 max-width: 78%，但**行内容的宽度是行内样式**
 *    (rowHtml 里的 <div style="min-width:0;max-width:78%">)，行内样式声明优先级最高，
 *    所以只能按位置选到它，不能靠提高选择器权重。改 rowHtml 会动到浮层，不改。
 */
.ch-page__body .ch-row > div { max-width: 82%; }
.ch-page__body .ch-bubble,
.ch-page__body .ch-order { max-width: 100%; }

/* 状态行（正在连接…）：和浮层 .ch-tip 同款，整页居中一点 */
.ch-page__tip {
  margin: auto;
  text-align: center;
  font-size: 12.5px;
  color: var(--text-3);
  line-height: 1.7;
  padding: 4px 8px;
}

/* 空态：未登录 / 连不上（图标 + 标题 + 说明 + 按钮） */
.ch-empty {
  margin: auto;
  padding: 18px 12px;
  text-align: center;
  color: var(--brand);
}
.ch-empty svg { margin: 0 auto 14px; opacity: .9; }
.ch-empty__t { font-size: 14.5px; font-weight: 600; color: var(--text); letter-spacing: -.2px; }
.ch-empty__s { font-size: 12.5px; color: var(--text-3); margin-top: 6px; line-height: 1.75; }
.ch-empty .btn { display: inline-flex; }

/* 消息时间戳：气泡/订单卡下面一行小字，自己的靠右、客服的靠左 */
.ch-time {
  font-size: 10.5px;
  color: var(--text-3);
  margin-top: 3px;
  font-variant-numeric: tabular-nums;
  line-height: 1.4;
}
.ch-row--me .ch-time { text-align: right; }

/* 「回到最新」：上翻看历史、又有新消息时才冒出来 */
.ch-fresh {
  position: absolute;
  left: 50%;
  bottom: 76px;
  transform: translate(-50%, 8px);
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 7px 14px;
  border-radius: 999px;
  background: var(--brand);
  color: var(--on-brand);
  font-size: 12px;
  font-weight: 600;
  box-shadow: 0 6px 18px var(--brand-a35);
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s, transform .18s;
}
.ch-fresh.show { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.ch-fresh:active { transform: translate(-50%, 0) scale(.96); }

/* 输入栏：底部要避开手机安全区（和 .ch-foot 同一口径） */
.ch-page__ft {
  flex-shrink: 0;
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding: 10px 14px calc(10px + var(--safe-b));
  border-top: 1px solid var(--line);
  background: var(--glass-strong);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
}
.ch-page__ft .ch-input { font-size: 14px; }
.ch-page__ft .ch-send { height: 40px; padding: 0 18px; font-size: 14px; }
/* 桌面端 H5 是居中的手机框，整页跟着 .zc-app 走，不用额外定位 */

/* 整页是聊天界面，不是内容页：底部免责声明会让它在下方再撑出一块空白 */
.zc-disclaimer.is-chat-page { display: none; }

/* ==========================================================================
   在线客服 · 发图片 / 选订单（2026-10-15 加，老板：「客服这个页面需要可以
   上传图片 以及可以选择订单」）
   --------------------------------------------------------------------------
   ⚠️ 全是**新增**选择器（.ch-tool / .ch-img / .zc-imgview / .ch-od__*），
      不覆盖上面任何一个既有类 —— 首页浮标、其它 H5 页面的观感一个像素都不动。
   ⚠️ 写在这里而不是各页面里：浮层是**全站都有**的（ui.js 自动挂），
      CSS 只有放进 base.css 才能让每个页面都拿到，不用逐页加 link。
   ========================================================================== */

/*
 * 隐藏的文件选择框（客户侧 / 两个客服端各留一个，id 不同、类名都是 .ch-file）
 * ⚠️ 用 position:fixed 挪到屏幕外，**不用 display:none** 也不用 createElement 游离节点：
 *   · display:none 的 input 在个别老 WebView 上点了不出文件框；
 *   · 游离节点会被浏览器回收（探针踩过「文件框开了但节点没了」）。
 */
.ch-file {
  position: fixed;
  left: -9999px;
  top: 0;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* 输入栏左边的工具位（图片 / 选订单）。浮层和整页共用一套尺寸口径 */
.ch-tool {  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  border: 1px solid var(--line-2);
  border-radius: 12px;
  background: rgba(255, 255, 255, .86);
  color: var(--text-2);
  font-size: 12.5px;
  font-family: var(--font);
  cursor: pointer;
  white-space: nowrap;
}
.ch-tool svg { display: block; }
.ch-tool:active { background: var(--line); color: var(--text); }
.ch-tool:disabled { opacity: .5; cursor: default; }
/* 「选订单」是文字按钮：宽一点，但一样收着（390 宽下消息框还得有地方） */
.ch-tool--t { width: auto; padding: 0 9px; }
/* 订单群聊里没有订单卡片这回事（/api/chat/group-send 只认文本和图片） */
.ch-tool--hide { display: none; }
.ch-page__ft .ch-tool { height: 40px; }

/*
 * 图片消息：图 + 兜底文案 + 可选的一句附言
 * ⚠️ 破图绝不能留白（老板的话：「图片消息要有加载失败兜底（别留破图）」）：
 *    img 自己藏起来、.ch-img__fb 顶上来，点它重试（见 chat.js 的 wireTools）。
 */
.ch-bubble--img { padding: 6px; }
.ch-img { display: block; min-width: 76px; min-height: 34px; }
.ch-img img { display: block; max-width: 100%; border-radius: 10px; cursor: zoom-in; }
.ch-img.is-fail img { display: none; }
.ch-img__fb {
  display: none;
  padding: 9px 10px;
  font-size: 12.5px;
  font-style: normal;
  line-height: 1.6;
  color: var(--text-3);
  background: var(--line);
  border-radius: 10px;
  text-align: center;
}
.ch-img.is-fail .ch-img__fb { display: block; }
.ch-row--me .ch-img.is-fail .ch-img__fb { background: rgba(255, 255, 255, .22); color: var(--on-brand); }
.ch-img__cap { margin: 6px 6px 2px; font-size: 13px; line-height: 1.6; word-break: break-word; }

/* 看大图：整屏遮罩 + contain 的图，点哪儿都关（chat.js 的 openViewer 建） */
.zc-imgview {
  position: fixed;
  inset: 0;
  z-index: 9998;                 /* 比 .sheet(201) / .ch-panel(68) 高，比 toast(9999) 低 */
  display: none;
  align-items: center;
  justify-content: center;
  padding: 18px;
  background: rgba(10, 12, 20, .92);
}
.zc-imgview.show { display: flex; }
.zc-imgview img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 10px; }
.zc-imgview__x {
  position: absolute;
  top: calc(14px + var(--safe-t));
  right: 16px;
  width: 34px; height: 34px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .18);
  color: #fff;
  font-style: normal; font-size: 15px;
  display: flex; align-items: center; justify-content: center;
}

/* 「选订单」弹层里的订单行：订单号 / 商品 / 金额 / 状态 / 时间 */
.ch-od__tip { padding: 6px 2px 10px; font-size: 12.5px; color: var(--text-3); line-height: 1.7; }
.ch-od__i {
  display: block;
  width: 100%;
  margin-bottom: 8px;
  padding: 11px 12px;
  text-align: left;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--card-solid);
  font-family: var(--font);
  cursor: pointer;
}
.ch-od__i:active { background: var(--brand-a08); border-color: var(--brand-a22); }
.ch-od__hd { display: flex; align-items: baseline; gap: 8px; }
.ch-od__n {
  flex: 1; min-width: 0;
  font-size: 13.5px; font-weight: 500; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ch-od__s {
  flex-shrink: 0;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--brand-a08);
  color: var(--brand);
  font-size: 11px; font-style: normal;
}
.ch-od__m {
  display: block;
  margin-top: 4px;
  font-size: 12px; color: var(--text-3);
  font-variant-numeric: tabular-nums;
  word-break: break-all;
}
.ch-od__more { margin-top: 2px; }

/* ==========================================================================
   订单群聊（打手接单后自动建的群）—— 浮层头部按钮 / 群列表 / 角色标签
   --------------------------------------------------------------------------
   全部挂在既有的 .ch-* 命名空间下，只在**群聊**相关的元素上用，
   客服浮层和客服整页一个字节都不受影响（老的 DOM 结构没变过）。
   逻辑见 public/assets/js/chat.js 的「订单群聊」那几段。
   ========================================================================== */

/* 浮层头部的两个小按钮：「群聊」（去群列表）/「返回」（回刚才那个会话） */
.ch-hbtn {
  flex-shrink: 0;
  height: 26px;
  padding: 0 9px;
  margin-right: 4px;
  border: 0;
  border-radius: 9px;
  background: var(--line);
  color: var(--text-2);
  font-size: 12px;
  line-height: 26px;
  white-space: nowrap;
  cursor: pointer;
}
.ch-hbtn:active { transform: scale(.96); }
.ch-hbtn--hide { display: none; }
/* 群列表视图：没有「发消息」这回事，输入栏收起来 */
.ch-panel--groups .ch-foot { display: none; }

/* 群里的角色标签（「张三（站长）」里的那个「站长」），跟在名字后面 */
.ch-role {
  display: inline-block;
  margin-left: 4px;
  padding: 0 5px;
  border-radius: 6px;
  background: var(--brand-a12, rgba(37, 99, 235, .12));
  color: var(--brand);
  font-style: normal;
  font-size: 10px;
  line-height: 15px;
  vertical-align: 1px;
}
/* 自己的那条消息：名字跟气泡同侧（靠右） */
.ch-name--me { text-align: right; }

/* 系统消息（「订单群已创建：…」）：居中一行灰字，不是谁说的话 */
.ch-sys {
  margin: 6px auto;
  max-width: 88%;
  padding: 5px 10px;
  border-radius: 8px;
  background: var(--line);
  color: var(--text-3);
  font-size: 11.5px;
  line-height: 1.6;
  text-align: center;
  word-break: break-word;
}

/* 群列表：一行一个群 */
.ch-group {
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  cursor: pointer;
}
.ch-group:active { background: var(--line); }
.ch-group__hd { display: flex; align-items: center; gap: 6px; }
.ch-group__t {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ch-group__n {
  flex-shrink: 0;
  min-width: 16px;
  height: 16px;
  padding: 0 5px;
  border-radius: 8px;
  background: var(--danger, #E23D31);
  color: #fff;
  font-style: normal;
  font-size: 10.5px;
  line-height: 16px;
  text-align: center;
}
.ch-group__s {
  margin-top: 3px;
  font-size: 11.5px;
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ==========================================================================
   ★ 2026-10-14 老模板【首页】动画（老板「我自己的首页没有动态效果啊」）

   ⚠️⚠️ 为什么这里**只做 opacity、不做位移**（血的教训，别改回去）：
     上一版给首页商品卡加了带 transform 的入场动画 → 老板截图「一张封面图撑满整屏、
     文字跑出边界」。根因：**带 transform 的元素会成为绝对定位后代的 containing block**，
     而首页商品卡里就是「position:absolute; width/height:100%」的封面图 ⇒ 参照系变了 ⇒ 图放大。
     ⇒ 规矩：**给元素加 transform 动画之前，先查它有没有 position:absolute/fixed 的后代**；
        有 → 只能 opacity；没有 → 才可以位移。
     （"只动 transform/opacity"那条只防重排，防不住这个 —— 两件事。）

   ⚠️ 作用域：只挂在首页网格的**直接子元素**上（.hm3-goods 是首页独有），
      所以这一版只有首页动，别的页面一字节不变（老板要求"一次一页"）。
   ⚠️ 级联 30ms × 20 = 600ms 封顶（老板那条"delay 累计 ≤600ms"）；第 21 个往后不动。
   ========================================================================== */
@keyframes hm-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.hm3-goods > .hm3-good {
  animation: hm-fade .26s ease both;
}
.hm3-goods > .hm3-good:nth-child(1) { animation-delay: 0ms; }
.hm3-goods > .hm3-good:nth-child(2) { animation-delay: 30ms; }
.hm3-goods > .hm3-good:nth-child(3) { animation-delay: 60ms; }
.hm3-goods > .hm3-good:nth-child(4) { animation-delay: 90ms; }
.hm3-goods > .hm3-good:nth-child(5) { animation-delay: 120ms; }
.hm3-goods > .hm3-good:nth-child(6) { animation-delay: 150ms; }
.hm3-goods > .hm3-good:nth-child(7) { animation-delay: 180ms; }
.hm3-goods > .hm3-good:nth-child(8) { animation-delay: 210ms; }
.hm3-goods > .hm3-good:nth-child(9) { animation-delay: 240ms; }
.hm3-goods > .hm3-good:nth-child(10) { animation-delay: 270ms; }
.hm3-goods > .hm3-good:nth-child(11) { animation-delay: 300ms; }
.hm3-goods > .hm3-good:nth-child(12) { animation-delay: 330ms; }
.hm3-goods > .hm3-good:nth-child(13) { animation-delay: 360ms; }
.hm3-goods > .hm3-good:nth-child(14) { animation-delay: 390ms; }
.hm3-goods > .hm3-good:nth-child(15) { animation-delay: 420ms; }
.hm3-goods > .hm3-good:nth-child(16) { animation-delay: 450ms; }
.hm3-goods > .hm3-good:nth-child(17) { animation-delay: 480ms; }
.hm3-goods > .hm3-good:nth-child(18) { animation-delay: 510ms; }
.hm3-goods > .hm3-good:nth-child(19) { animation-delay: 540ms; }
.hm3-goods > .hm3-good:nth-child(20) { animation-delay: 570ms; }
/* 第 21 个往后：不动画（不让它"等一秒才出现"） */
.hm3-goods > .hm3-good:nth-child(n+21) { animation: none; }
/* 用户系统里关了动效 → 不动 */
@media (prefers-reduced-motion: reduce) {
  .hm3-goods > .hm3-good { animation: none; }
}

/* ==========================================================================
   ★ 2026-10-14 老模板分类页「大图卡」那一排（老板「分类弄大图」，照参考站）

   参考站 390 实测（_evidence/px2/dom/ref-category.json）：
     圆 41.59 · 卡宽 85 · 缝 8.33（行距 93.33）· 名字 10.4px（选中 600 / 未选 500）
     选中态 = 圆外面**一圈橙**（不是整卡填色）· 名字色 选中 rgb(74,35,7) / 未选 rgb(26,26,26)

   ⚠️ 这一排是老模板**新加**的（它原来只有"左栏一级 + 右栏分组"那个布局）；
      有这一排时左栏那列用 body.ct-has-big 隐藏 —— 因为左栏也是"一级"，留着同一件事会显示两遍。
      想回退：把 body 上的 ct-has-big 去掉即可（或删掉这段 CSS）。
   ⚠️ 动画只做 opacity：老模板刚出过「transform 改绝对定位子元素参照系」的事故，这里保持最保守。
   ========================================================================== */
.ct-bigrow {
  display: flex; gap: 8.33px; align-items: flex-start;
  padding: 10px 12.47px 4px;
  overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
}
.ct-bigrow::-webkit-scrollbar { display: none; }
.ct-big {
  flex: 0 0 85px; width: 85px;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 8px 3px 6px; border-radius: 12.48px;
  font-size: 10.4px; line-height: 14px; color: rgb(26, 26, 26); font-weight: 500;
  animation: ct-big-fade .26s ease both;
}
@keyframes ct-big-fade { from { opacity: 0; } to { opacity: 1; } }
/* 级联 30ms（20 个封顶 570ms，卡住"累计 ≤600ms"） */
.ct-big:nth-child(1) { animation-delay: 0ms; }
.ct-big:nth-child(2) { animation-delay: 30ms; }
.ct-big:nth-child(3) { animation-delay: 60ms; }
.ct-big:nth-child(4) { animation-delay: 90ms; }
.ct-big:nth-child(5) { animation-delay: 120ms; }
.ct-big:nth-child(6) { animation-delay: 150ms; }
.ct-big:nth-child(7) { animation-delay: 180ms; }
.ct-big:nth-child(8) { animation-delay: 210ms; }
.ct-big:nth-child(9) { animation-delay: 240ms; }
.ct-big:nth-child(10) { animation-delay: 270ms; }
.ct-big:nth-child(11) { animation-delay: 300ms; }
.ct-big:nth-child(12) { animation-delay: 330ms; }
.ct-big:nth-child(13) { animation-delay: 360ms; }
.ct-big:nth-child(14) { animation-delay: 390ms; }
.ct-big:nth-child(15) { animation-delay: 420ms; }
.ct-big:nth-child(16) { animation-delay: 450ms; }
.ct-big:nth-child(17) { animation-delay: 480ms; }
.ct-big:nth-child(18) { animation-delay: 510ms; }
.ct-big:nth-child(19) { animation-delay: 540ms; }
.ct-big:nth-child(20) { animation-delay: 570ms; }
.ct-big:nth-child(n+21) { animation: none; }
.ct-big__i {
  width: 41.59px; height: 41.59px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(20, 20, 30, .06);   /* 未选中：浅灰底 */
  overflow: hidden; line-height: 0;
}
.ct-big__i img { width: 100%; height: 100%; object-fit: cover; }
.ct-big__i .ct-ico__emo { font-size: 22px; }
/* 选中：圆外面一圈橙（参考站就是这一圈，整卡不填色） */
.ct-big.active .ct-big__i { box-shadow: 0 0 0 2px var(--brand); background: #fff; }
.ct-big.active { color: rgb(74, 35, 7); font-weight: 600; }
.ct-big__t { max-width: 79px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/*
 * ⚠️ 2026-10-14 改：左栏**不再收起** —— 老板要「跟仿的那种一样」=
 *   上面大图卡（管一级）+ 左侧**二级竖排**（这一列）+ 右侧商品网格。
 *   左栏现在渲染的是二级（见 public/h5/category.html 的 renderCats），必须有内容、不能被藏。
 */
body.ct-has-big .ct-aside { display: block; }
/* 用户系统里关了动效 → 不动 */
@media (prefers-reduced-motion: reduce) { .ct-big { animation: none; } }

/* ==========================================================================
   ★ 2026-10-15 老模板【其余页面】：卡片依次淡入（只做 opacity，绝不位移）

   老板口径（tools/_push-oldhome.js 里写着）：**别说成"全站都有"**、一页一页来。
   首页那一段（本文件 :2369 起，.hm3-goods > .hm3-good）已经做完，
   这一段是接着往下的每一页 —— 分类 / 选人 / 详情 / 我的 / 搜索 / 订单 /
   钱包 / 邀请 / 接单台 work / 商家 merchant / 管事 manager。

   ⚠️「消息」这一页老模板【没有】：public/h5/ 下没有消息列表页
      （消息列表只在新模板 public/h5-snake/messages.html；老模板客户侧是
       service.html + /assets/js/chat.js 的聊天气泡）→ 这一段里没有它，不是漏了。

   ⚠️⚠️ 做法**逐字照抄首页那一版**（复用同一个 @keyframes hm-fade，全站只定义一次）：
     · **只做 opacity、绝不做位移**：带 transform 的元素会成为「绝对定位后代的
       containing block」—— 那次「封面图撑满整屏、文字跑出边界」的事故就是这么来的
       （tools/_old-anim-rollback.js 的原话 + 交接说明第三节 10）；
     · 0.26s ease both；级联 30ms × 20 = 600ms 封顶；第 21 个往后 animation: none；
     · prefers-reduced-motion: reduce → 整条不跑（收敛态 = 本来样子，能点不变形）。

   ⚠️ 作用域（老板「一次一页」+「只加不改」）：
     base.css 是 admin / super / portal / agent / player / kefu 一起加载的，
     而且有几个卡片类名**跨页复用**：
       .order-card 在 work.html（陪练师接单台）也有一份
       .stat-cell  在 player.html（陪练师主页）也有一份
       .list-item  在 merchant / manager / feedback / coupons 等页都有一份
     ⇒ 每一段都拿「**只有那一页有**的容器/类名」钉住（每段注释里写了命中数），
       绝不写裸类名；想回退某一页：单独删掉它那一段（含末了自己那条 reduce）即可。
   ⚠️ 列表为空时这一页不动 —— 和首页空分类一样（没卡片就没有动画），不是坏了。
   ========================================================================== */

/* ---- ① 分类页 category.html：商品卡 .hm-good（容器 .ct-grid 全站只此一处）----
   ⚠️ 卡里 .hm-good__tag 是 position:absolute（base.css:1760）→ 所以这里只敢做 opacity。 */
.ct-grid > .hm-good { animation: hm-fade .26s ease both; }
.ct-grid > .hm-good:nth-child(1) { animation-delay: 0ms; }
.ct-grid > .hm-good:nth-child(2) { animation-delay: 30ms; }
.ct-grid > .hm-good:nth-child(3) { animation-delay: 60ms; }
.ct-grid > .hm-good:nth-child(4) { animation-delay: 90ms; }
.ct-grid > .hm-good:nth-child(5) { animation-delay: 120ms; }
.ct-grid > .hm-good:nth-child(6) { animation-delay: 150ms; }
.ct-grid > .hm-good:nth-child(7) { animation-delay: 180ms; }
.ct-grid > .hm-good:nth-child(8) { animation-delay: 210ms; }
.ct-grid > .hm-good:nth-child(9) { animation-delay: 240ms; }
.ct-grid > .hm-good:nth-child(10) { animation-delay: 270ms; }
.ct-grid > .hm-good:nth-child(11) { animation-delay: 300ms; }
.ct-grid > .hm-good:nth-child(12) { animation-delay: 330ms; }
.ct-grid > .hm-good:nth-child(13) { animation-delay: 360ms; }
.ct-grid > .hm-good:nth-child(14) { animation-delay: 390ms; }
.ct-grid > .hm-good:nth-child(15) { animation-delay: 420ms; }
.ct-grid > .hm-good:nth-child(16) { animation-delay: 450ms; }
.ct-grid > .hm-good:nth-child(17) { animation-delay: 480ms; }
.ct-grid > .hm-good:nth-child(18) { animation-delay: 510ms; }
.ct-grid > .hm-good:nth-child(19) { animation-delay: 540ms; }
.ct-grid > .hm-good:nth-child(20) { animation-delay: 570ms; }
/* 第 21 个往后：不动画（不让它"等一秒才出现"） */
.ct-grid > .hm-good:nth-child(n+21) { animation: none; }
/* 用户系统里关了动效 → 不动 */
@media (prefers-reduced-motion: reduce) { .ct-grid > .hm-good { animation: none; } }

/* ---- ② 选人页 players.html：陪练师卡 .pk-card（容器 .pk-list 全站只此一处）----
   ⚠️ 卡里 .pk-av__on（在线小绿点）是 position:absolute（players.html:84）
      → 只做 opacity，参照系不变。 */
.pk-list .pk-card { animation: hm-fade .26s ease both; }
.pk-list .pk-card:nth-child(1) { animation-delay: 0ms; }
.pk-list .pk-card:nth-child(2) { animation-delay: 30ms; }
.pk-list .pk-card:nth-child(3) { animation-delay: 60ms; }
.pk-list .pk-card:nth-child(4) { animation-delay: 90ms; }
.pk-list .pk-card:nth-child(5) { animation-delay: 120ms; }
.pk-list .pk-card:nth-child(6) { animation-delay: 150ms; }
.pk-list .pk-card:nth-child(7) { animation-delay: 180ms; }
.pk-list .pk-card:nth-child(8) { animation-delay: 210ms; }
.pk-list .pk-card:nth-child(9) { animation-delay: 240ms; }
.pk-list .pk-card:nth-child(10) { animation-delay: 270ms; }
.pk-list .pk-card:nth-child(11) { animation-delay: 300ms; }
.pk-list .pk-card:nth-child(12) { animation-delay: 330ms; }
.pk-list .pk-card:nth-child(13) { animation-delay: 360ms; }
.pk-list .pk-card:nth-child(14) { animation-delay: 390ms; }
.pk-list .pk-card:nth-child(15) { animation-delay: 420ms; }
.pk-list .pk-card:nth-child(16) { animation-delay: 450ms; }
.pk-list .pk-card:nth-child(17) { animation-delay: 480ms; }
.pk-list .pk-card:nth-child(18) { animation-delay: 510ms; }
.pk-list .pk-card:nth-child(19) { animation-delay: 540ms; }
.pk-list .pk-card:nth-child(20) { animation-delay: 570ms; }
/* 第 21 个往后：不动画（不让它"等一秒才出现"） */
.pk-list .pk-card:nth-child(n+21) { animation: none; }
/* 用户系统里关了动效 → 不动 */
@media (prefers-reduced-motion: reduce) { .pk-list .pk-card { animation: none; } }

/* ---- ③ 商品详情 goods.html：主块依次淡入（容器 .gd-main 全站只此一处）----
   ⚠️ 这一页**没有卡片列表**：正文就是「轮播图 + 价格主卡 + 规格卡 + 评价卡 + 详情卡」，
      所以按同一套做法让这几块**主块**自上而下依次淡入（间隔同样 30ms）；
      规格按钮 .gd-spec 是可选中的控件、评价行 .gd-rev 是明细 → 都不逐条动。
   ⚠️ .gd-gal 里有 position:absolute 的 .gd-gal__n / .gd-gal__mask（goods.html:33/41）
      → 只做 opacity，参照系不变。 */
.gd-main > .gd-gal,
.gd-main > .gd-head,
.gd-main > .card { animation: hm-fade .26s ease both; }
.gd-main > :nth-child(1) { animation-delay: 0ms; }
.gd-main > :nth-child(2) { animation-delay: 30ms; }
.gd-main > :nth-child(3) { animation-delay: 60ms; }
.gd-main > :nth-child(4) { animation-delay: 90ms; }
.gd-main > :nth-child(5) { animation-delay: 120ms; }
.gd-main > :nth-child(6) { animation-delay: 150ms; }
/* 第 7 个往后：不动画（主块最多 5 块，这条只是兜底） */
.gd-main > :nth-child(n+7) { animation: none; }
/* 用户系统里关了动效 → 不动 */
@media (prefers-reduced-motion: reduce) {
  .gd-main > .gd-gal,
  .gd-main > .gd-head,
  .gd-main > .card { animation: none; }
}

/* ---- ④ 我的页 me.html：更多功能格子 .mp-cell（容器 .mp-grid 全站只此一处）----
   ⚠️ 这一格里有 position:absolute 的东西吗？没有（就一个圆底图标 + 一行字）——
      但旁边那四格 .mp-stat 里有（.badge 绝对定位），这一版**不动** .mp-stat。
   ⚠️⚠️ 多出来的那一行 :active —— 动画带 both 填充时，动画里的 opacity 会一直压着
      普通声明，.mp-cell:active 原本按下变淡（me.html:191）就永远不生效了；
      要让「按下反馈」照旧，只能用 !important（important 的普通声明才盖得住动画）。
      值还是原来的 .62，一个像素都没改 —— 只是把既有反馈保住。 */
.mp-grid > .mp-cell { animation: hm-fade .26s ease both; }
.mp-grid > .mp-cell:nth-child(1) { animation-delay: 0ms; }
.mp-grid > .mp-cell:nth-child(2) { animation-delay: 30ms; }
.mp-grid > .mp-cell:nth-child(3) { animation-delay: 60ms; }
.mp-grid > .mp-cell:nth-child(4) { animation-delay: 90ms; }
.mp-grid > .mp-cell:nth-child(5) { animation-delay: 120ms; }
.mp-grid > .mp-cell:nth-child(6) { animation-delay: 150ms; }
.mp-grid > .mp-cell:nth-child(7) { animation-delay: 180ms; }
.mp-grid > .mp-cell:nth-child(8) { animation-delay: 210ms; }
.mp-grid > .mp-cell:nth-child(9) { animation-delay: 240ms; }
.mp-grid > .mp-cell:nth-child(10) { animation-delay: 270ms; }
.mp-grid > .mp-cell:nth-child(11) { animation-delay: 300ms; }
.mp-grid > .mp-cell:nth-child(12) { animation-delay: 330ms; }
.mp-grid > .mp-cell:nth-child(13) { animation-delay: 360ms; }
.mp-grid > .mp-cell:nth-child(14) { animation-delay: 390ms; }
.mp-grid > .mp-cell:nth-child(15) { animation-delay: 420ms; }
.mp-grid > .mp-cell:nth-child(16) { animation-delay: 450ms; }
.mp-grid > .mp-cell:nth-child(17) { animation-delay: 480ms; }
.mp-grid > .mp-cell:nth-child(18) { animation-delay: 510ms; }
.mp-grid > .mp-cell:nth-child(19) { animation-delay: 540ms; }
.mp-grid > .mp-cell:nth-child(20) { animation-delay: 570ms; }
/* 第 21 个往后：不动画（不让它"等一秒才出现"） */
.mp-grid > .mp-cell:nth-child(n+21) { animation: none; }
#mePage .mp-cell:active { opacity: .62 !important; }
/* 用户系统里关了动效 → 不动 */
@media (prefers-reduced-motion: reduce) { .mp-grid > .mp-cell { animation: none; } }

/* ---- ⑤ 搜索页 search.html：商品结果卡 .sr-good（容器 .sr-goods 全站只此一处）----
   ⚠️ 搜索页另一个页签是陪练师结果 .sr-pl（不是商品卡）→ 这一版不动它。 */
.sr-goods > .sr-good { animation: hm-fade .26s ease both; }
.sr-goods > .sr-good:nth-child(1) { animation-delay: 0ms; }
.sr-goods > .sr-good:nth-child(2) { animation-delay: 30ms; }
.sr-goods > .sr-good:nth-child(3) { animation-delay: 60ms; }
.sr-goods > .sr-good:nth-child(4) { animation-delay: 90ms; }
.sr-goods > .sr-good:nth-child(5) { animation-delay: 120ms; }
.sr-goods > .sr-good:nth-child(6) { animation-delay: 150ms; }
.sr-goods > .sr-good:nth-child(7) { animation-delay: 180ms; }
.sr-goods > .sr-good:nth-child(8) { animation-delay: 210ms; }
.sr-goods > .sr-good:nth-child(9) { animation-delay: 240ms; }
.sr-goods > .sr-good:nth-child(10) { animation-delay: 270ms; }
.sr-goods > .sr-good:nth-child(11) { animation-delay: 300ms; }
.sr-goods > .sr-good:nth-child(12) { animation-delay: 330ms; }
.sr-goods > .sr-good:nth-child(13) { animation-delay: 360ms; }
.sr-goods > .sr-good:nth-child(14) { animation-delay: 390ms; }
.sr-goods > .sr-good:nth-child(15) { animation-delay: 420ms; }
.sr-goods > .sr-good:nth-child(16) { animation-delay: 450ms; }
.sr-goods > .sr-good:nth-child(17) { animation-delay: 480ms; }
.sr-goods > .sr-good:nth-child(18) { animation-delay: 510ms; }
.sr-goods > .sr-good:nth-child(19) { animation-delay: 540ms; }
.sr-goods > .sr-good:nth-child(20) { animation-delay: 570ms; }
/* 第 21 个往后：不动画（不让它"等一秒才出现"） */
.sr-goods > .sr-good:nth-child(n+21) { animation: none; }
/* 用户系统里关了动效 → 不动 */
@media (prefers-reduced-motion: reduce) { .sr-goods > .sr-good { animation: none; } }

/* ---- ⑥ 订单页 orders.html：订单卡 .order-card ----
   ⚠️ .order-card **不是这一页独有的**（work.html 的接单台也在用同一个类），
      所以用这一页独有的 .od-tabs 当锚点钉住（它是 .zc-main 前面的兄弟节点）——
      这一条选择器在别的页面命中 0 个，绝不会连带改到 work.html。 */
.od-tabs ~ .zc-main .order-card { animation: hm-fade .26s ease both; }
.od-tabs ~ .zc-main .order-card:nth-child(1) { animation-delay: 0ms; }
.od-tabs ~ .zc-main .order-card:nth-child(2) { animation-delay: 30ms; }
.od-tabs ~ .zc-main .order-card:nth-child(3) { animation-delay: 60ms; }
.od-tabs ~ .zc-main .order-card:nth-child(4) { animation-delay: 90ms; }
.od-tabs ~ .zc-main .order-card:nth-child(5) { animation-delay: 120ms; }
.od-tabs ~ .zc-main .order-card:nth-child(6) { animation-delay: 150ms; }
.od-tabs ~ .zc-main .order-card:nth-child(7) { animation-delay: 180ms; }
.od-tabs ~ .zc-main .order-card:nth-child(8) { animation-delay: 210ms; }
.od-tabs ~ .zc-main .order-card:nth-child(9) { animation-delay: 240ms; }
.od-tabs ~ .zc-main .order-card:nth-child(10) { animation-delay: 270ms; }
.od-tabs ~ .zc-main .order-card:nth-child(11) { animation-delay: 300ms; }
.od-tabs ~ .zc-main .order-card:nth-child(12) { animation-delay: 330ms; }
.od-tabs ~ .zc-main .order-card:nth-child(13) { animation-delay: 360ms; }
.od-tabs ~ .zc-main .order-card:nth-child(14) { animation-delay: 390ms; }
.od-tabs ~ .zc-main .order-card:nth-child(15) { animation-delay: 420ms; }
.od-tabs ~ .zc-main .order-card:nth-child(16) { animation-delay: 450ms; }
.od-tabs ~ .zc-main .order-card:nth-child(17) { animation-delay: 480ms; }
.od-tabs ~ .zc-main .order-card:nth-child(18) { animation-delay: 510ms; }
.od-tabs ~ .zc-main .order-card:nth-child(19) { animation-delay: 540ms; }
.od-tabs ~ .zc-main .order-card:nth-child(20) { animation-delay: 570ms; }
/* 第 21 个往后：不动画（不让它"等一秒才出现"） */
.od-tabs ~ .zc-main .order-card:nth-child(n+21) { animation: none; }
/* 用户系统里关了动效 → 不动 */
@media (prefers-reduced-motion: reduce) { .od-tabs ~ .zc-main .order-card { animation: none; } }

/* ---- ⑦ 钱包页 wallet.html：收支明细行 .wl-item（这个类名全站只此一处）----
   ⚠️ 行上的分隔线是 .wl-item + .wl-item::before（position:absolute，wallet.html:18），
      而 .wl-item 自己本来就是 position:relative → 只做 opacity，参照系不变。
   ⚠️ 顶上那三条 .stat-cell（累计收入 / 支出 / 提现处理中）是"一块卡里的一行"，
      不算卡片列表 → 这一版不动（player.html 也在用 .stat-cell，动它会串页）。 */
.wl-item { animation: hm-fade .26s ease both; }
.wl-item:nth-child(1) { animation-delay: 0ms; }
.wl-item:nth-child(2) { animation-delay: 30ms; }
.wl-item:nth-child(3) { animation-delay: 60ms; }
.wl-item:nth-child(4) { animation-delay: 90ms; }
.wl-item:nth-child(5) { animation-delay: 120ms; }
.wl-item:nth-child(6) { animation-delay: 150ms; }
.wl-item:nth-child(7) { animation-delay: 180ms; }
.wl-item:nth-child(8) { animation-delay: 210ms; }
.wl-item:nth-child(9) { animation-delay: 240ms; }
.wl-item:nth-child(10) { animation-delay: 270ms; }
.wl-item:nth-child(11) { animation-delay: 300ms; }
.wl-item:nth-child(12) { animation-delay: 330ms; }
.wl-item:nth-child(13) { animation-delay: 360ms; }
.wl-item:nth-child(14) { animation-delay: 390ms; }
.wl-item:nth-child(15) { animation-delay: 420ms; }
.wl-item:nth-child(16) { animation-delay: 450ms; }
.wl-item:nth-child(17) { animation-delay: 480ms; }
.wl-item:nth-child(18) { animation-delay: 510ms; }
.wl-item:nth-child(19) { animation-delay: 540ms; }
.wl-item:nth-child(20) { animation-delay: 570ms; }
/* 第 21 个往后：不动画（不让它"等一秒才出现"） */
.wl-item:nth-child(n+21) { animation: none; }
/* 用户系统里关了动效 → 不动 */
@media (prefers-reduced-motion: reduce) { .wl-item { animation: none; } }

/* ---- ⑧ 邀请页 invite.html：邀请记录行 .iv-row（这个类名全站只此一处）----
   ⚠️ 行上的分隔线同样是 .iv-row + .iv-row::before（position:absolute，invite.html:65）
      + .iv-row 自己是 position:relative → 只做 opacity。
   ⚠️ 新站「还没有好友通过你的邀请码注册」时这一页没有行 → 和首页空分类一样不动，
      不是坏了；顶上那三格 .iv-stat 是统计（不是卡片列表）→ 这一版不动。 */
.iv-row { animation: hm-fade .26s ease both; }
.iv-row:nth-child(1) { animation-delay: 0ms; }
.iv-row:nth-child(2) { animation-delay: 30ms; }
.iv-row:nth-child(3) { animation-delay: 60ms; }
.iv-row:nth-child(4) { animation-delay: 90ms; }
.iv-row:nth-child(5) { animation-delay: 120ms; }
.iv-row:nth-child(6) { animation-delay: 150ms; }
.iv-row:nth-child(7) { animation-delay: 180ms; }
.iv-row:nth-child(8) { animation-delay: 210ms; }
.iv-row:nth-child(9) { animation-delay: 240ms; }
.iv-row:nth-child(10) { animation-delay: 270ms; }
.iv-row:nth-child(11) { animation-delay: 300ms; }
.iv-row:nth-child(12) { animation-delay: 330ms; }
.iv-row:nth-child(13) { animation-delay: 360ms; }
.iv-row:nth-child(14) { animation-delay: 390ms; }
.iv-row:nth-child(15) { animation-delay: 420ms; }
.iv-row:nth-child(16) { animation-delay: 450ms; }
.iv-row:nth-child(17) { animation-delay: 480ms; }
.iv-row:nth-child(18) { animation-delay: 510ms; }
.iv-row:nth-child(19) { animation-delay: 540ms; }
.iv-row:nth-child(20) { animation-delay: 570ms; }
/* 第 21 个往后：不动画（不让它"等一秒才出现"） */
.iv-row:nth-child(n+21) { animation: none; }
/* 用户系统里关了动效 → 不动 */
@media (prefers-reduced-motion: reduce) { .iv-row { animation: none; } }

/* ---- ⑨ 接单台 work.html：大厅接单行 .ac-row（这个类名全站只此一处）----
   ⚠️ 全部收在 #hlPage 下（work.html:305 的根节点）→ 只影响这一页。
   ⚠️ 这一页另外还有 .order-card（我的单），跟订单页共用类名 → 这里**故意不动**它：
      要动的话得再找一个本页独有锚点，风险不值当。 */
#hlPage .ac-row { animation: hm-fade .26s ease both; }
#hlPage .ac-row:nth-child(1) { animation-delay: 0ms; }
#hlPage .ac-row:nth-child(2) { animation-delay: 30ms; }
#hlPage .ac-row:nth-child(3) { animation-delay: 60ms; }
#hlPage .ac-row:nth-child(4) { animation-delay: 90ms; }
#hlPage .ac-row:nth-child(5) { animation-delay: 120ms; }
#hlPage .ac-row:nth-child(6) { animation-delay: 150ms; }
#hlPage .ac-row:nth-child(7) { animation-delay: 180ms; }
#hlPage .ac-row:nth-child(8) { animation-delay: 210ms; }
#hlPage .ac-row:nth-child(9) { animation-delay: 240ms; }
#hlPage .ac-row:nth-child(10) { animation-delay: 270ms; }
#hlPage .ac-row:nth-child(11) { animation-delay: 300ms; }
#hlPage .ac-row:nth-child(12) { animation-delay: 330ms; }
#hlPage .ac-row:nth-child(13) { animation-delay: 360ms; }
#hlPage .ac-row:nth-child(14) { animation-delay: 390ms; }
#hlPage .ac-row:nth-child(15) { animation-delay: 420ms; }
#hlPage .ac-row:nth-child(16) { animation-delay: 450ms; }
#hlPage .ac-row:nth-child(17) { animation-delay: 480ms; }
#hlPage .ac-row:nth-child(18) { animation-delay: 510ms; }
#hlPage .ac-row:nth-child(19) { animation-delay: 540ms; }
#hlPage .ac-row:nth-child(20) { animation-delay: 570ms; }
/* 第 21 个往后：不动画（不让它"等一秒才出现"） */
#hlPage .ac-row:nth-child(n+21) { animation: none; }
/* 用户系统里关了动效 → 不动 */
@media (prefers-reduced-motion: reduce) { #hlPage .ac-row { animation: none; } }

/* ---- ⑩ 商家端 merchant.html：我的单 / 我的商品行 .mh-row ----
   ⚠️ 探针表里写的是 .list-item，但**商家页正文一行 .list-item 都没有**：
      那个类在这页只出现在两个弹层里（订单详情 sheet:1378、客服会话 sheet:1452），
      而正文的卡片行是 .mh-row（:327 我的单、:416 我的商品）→ 所以这里按 .mh-row 做。
   ⚠️ 全部收在 #mhPage 下（merchant.html:145 的根节点）；本页那条 position:absolute
      是弹层里的 .mh-img__x（图片删除按钮），不在 .mh-row 里。 */
#mhPage .mh-row { animation: hm-fade .26s ease both; }
#mhPage .mh-row:nth-child(1) { animation-delay: 0ms; }
#mhPage .mh-row:nth-child(2) { animation-delay: 30ms; }
#mhPage .mh-row:nth-child(3) { animation-delay: 60ms; }
#mhPage .mh-row:nth-child(4) { animation-delay: 90ms; }
#mhPage .mh-row:nth-child(5) { animation-delay: 120ms; }
#mhPage .mh-row:nth-child(6) { animation-delay: 150ms; }
#mhPage .mh-row:nth-child(7) { animation-delay: 180ms; }
#mhPage .mh-row:nth-child(8) { animation-delay: 210ms; }
#mhPage .mh-row:nth-child(9) { animation-delay: 240ms; }
#mhPage .mh-row:nth-child(10) { animation-delay: 270ms; }
#mhPage .mh-row:nth-child(11) { animation-delay: 300ms; }
#mhPage .mh-row:nth-child(12) { animation-delay: 330ms; }
#mhPage .mh-row:nth-child(13) { animation-delay: 360ms; }
#mhPage .mh-row:nth-child(14) { animation-delay: 390ms; }
#mhPage .mh-row:nth-child(15) { animation-delay: 420ms; }
#mhPage .mh-row:nth-child(16) { animation-delay: 450ms; }
#mhPage .mh-row:nth-child(17) { animation-delay: 480ms; }
#mhPage .mh-row:nth-child(18) { animation-delay: 510ms; }
#mhPage .mh-row:nth-child(19) { animation-delay: 540ms; }
#mhPage .mh-row:nth-child(20) { animation-delay: 570ms; }
/* 第 21 个往后：不动画（不让它"等一秒才出现"） */
#mhPage .mh-row:nth-child(n+21) { animation: none; }
/* 用户系统里关了动效 → 不动 */
@media (prefers-reduced-motion: reduce) { #mhPage .mh-row { animation: none; } }

/* ---- ⑪ 管事端 manager.html：陪练师 / 抽成行 .mg-row ----
   ⚠️ 全部收在 #mgPage 下（manager.html:54 的根节点）；这一页没有任何
      position:absolute 的规则（只有 + 相邻的 border-top 分隔线）→ 位移也不怕，
      但规矩是规矩：**还是只做 opacity**。 */
#mgPage .mg-row { animation: hm-fade .26s ease both; }
#mgPage .mg-row:nth-child(1) { animation-delay: 0ms; }
#mgPage .mg-row:nth-child(2) { animation-delay: 30ms; }
#mgPage .mg-row:nth-child(3) { animation-delay: 60ms; }
#mgPage .mg-row:nth-child(4) { animation-delay: 90ms; }
#mgPage .mg-row:nth-child(5) { animation-delay: 120ms; }
#mgPage .mg-row:nth-child(6) { animation-delay: 150ms; }
#mgPage .mg-row:nth-child(7) { animation-delay: 180ms; }
#mgPage .mg-row:nth-child(8) { animation-delay: 210ms; }
#mgPage .mg-row:nth-child(9) { animation-delay: 240ms; }
#mgPage .mg-row:nth-child(10) { animation-delay: 270ms; }
#mgPage .mg-row:nth-child(11) { animation-delay: 300ms; }
#mgPage .mg-row:nth-child(12) { animation-delay: 330ms; }
#mgPage .mg-row:nth-child(13) { animation-delay: 360ms; }
#mgPage .mg-row:nth-child(14) { animation-delay: 390ms; }
#mgPage .mg-row:nth-child(15) { animation-delay: 420ms; }
#mgPage .mg-row:nth-child(16) { animation-delay: 450ms; }
#mgPage .mg-row:nth-child(17) { animation-delay: 480ms; }
#mgPage .mg-row:nth-child(18) { animation-delay: 510ms; }
#mgPage .mg-row:nth-child(19) { animation-delay: 540ms; }
#mgPage .mg-row:nth-child(20) { animation-delay: 570ms; }
/* 第 21 个往后：不动画（不让它"等一秒才出现"） */
#mgPage .mg-row:nth-child(n+21) { animation: none; }
/* 用户系统里关了动效 → 不动 */
@media (prefers-reduced-motion: reduce) { #mgPage .mg-row { animation: none; } }

/* ==========================================================================
   ★ 2026-10-15 底部 tab「消息」的红点 + 消息列表页（public/h5/messages.html）

   老板：「客服这里类似仿独眼蛇模板那种，客服改成消息，上面有个系统通知和平台客服」；
   二次修改：「系统通知像平台客服那种 框里面删除」（= 删掉那两个分区小标题）。
   这一整段都是**新加**的，只服务这两件事，别的地方一条选择器都不动：
     · .zc-tabbar__dot         底部第 4 项（消息）上的未读红点数字
     · .msg-list / .msg-row    消息列表页的行（用的是 .list / .list-item 那套底子，
                               这里只补「会话行」需要的几处：一列行的外壳、头像圆角块、
                               没有内容时那一行的淡化态、右上的时间、未读小胶囊、
                               箭头颜色、以及公告弹层里的正文排版）

   ⚠️ 红点用的是**自己的类名**，没有复用上面那段 .zc-tabbar__item .dot（那是给
      首页公告条 .hm3-notice 用的定位：margin-left:8px，挂在图标右上角）。
      消息这一项的红点要挂在图标右上角**更靠外**一点，和 10.5px 的「消息」两个字错开。
   ========================================================================== */

/* ---------------- 底部 tab「消息」的未读红点 ---------------- */
.zc-tabbar__dot {
  position: absolute;
  top: 2px;
  left: 50%;
  margin-left: 7px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--red);
  color: #fff;
  font-size: 9.5px;
  font-style: normal;
  font-weight: 600;
  line-height: 16px;
  text-align: center;
  box-shadow: 0 1px 4px rgba(16, 24, 40, .22);
  pointer-events: none;
}

/* ---------------- 消息列表页 ---------------- */
/*
 * 一列消息行的外壳。
 *
 * ★ 老板二次修改（他圈了两个框）：「系统通知像平台客服那种 框里面删除」——
 *   原来每条消息上面那个灰色的**分区小标题**（「平台客服」「系统通知」）已经删掉，
 *   页面就是一行一行排下来（像微信消息列表）；所以这里**不再有 .msg-sec 那种样式**。
 *   行与行之间留 10px（.list 自己是一张白卡，两行之间要分开一点才看得出是两行）。
 */
.msg-list { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.msg-list .list { margin-bottom: 0; }

.msg-row { align-items: center; }

/*
 * 「这一行没有内容」的状态：**不用大空框**，只是把这一行整体淡一点
 * （用在「系统通知」没公告时那句「暂无通知」上）。
 * ⚠️ 挂的是 .msg-row.is-off —— class 里**只多这一个词**，其余和平台客服那一行逐字相同
 *    （探针拿两行的 className 逐字比，多一个光秃秃的 is-off 是允许的、写死成别的就红）。
 * ⚠️ 淡的是文字和图标，行本身照样可点、照样有箭头 —— 点进去是公告列表。
 */
.msg-row.is-off .list-item__title { font-weight: 500; color: var(--text-2); }
.msg-row.is-off .list-item__desc { color: var(--text-3); }
.msg-row.is-off .msg-row__av { background: var(--brand-softer); color: var(--text-3); }

/*
 * 会话头像：圆角方块 + 淡色底（.list-item 自带的 gap:12px 负责它和正文的间距）
 *
 * ⚠️ **所有消息行共用这一个 class，不给每行单独的颜色**：
 *    老板要的是「系统通知像平台客服那种」＝ 同一套行样式；
 *    探针会把两行的 className 和 DOM 结构逐字比，多一个 --cs / --sys 就不算同一套了。
 *    两行靠**里面的线框图标**区分（气泡 = 平台客服，公告纸 = 系统通知）。
 */
.msg-row__av {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--brand-soft);
  color: var(--brand);
  line-height: 0;
}
.msg-row__av svg { display: block; }

/* 标题行：标题吃掉剩余宽度（长了省略号），时间靠右不换行 */
.msg-row__hd { display: flex; align-items: baseline; }
.msg-row__hd .list-item__title { flex: 1; min-width: 0; }
.msg-row__time { flex-shrink: 0; margin-left: 8px; font-size: 11.5px; color: var(--text-3); }

/*
 * ⚠️ 正文那一格必须 overflow:hidden（这一条是看截图发现的，探针的 scrollWidth 抓不到）：
 *    .list-item__desc 自带 overflow:hidden，但它自己**要参与 flex 计算**
 *    （flex-basis:auto + 很长的长文本）→ 它的 max-content 宽度会把 .list-item__body
 *    撑得比卡片还宽，那张白卡的右半边就**跑到屏幕外**去了。
 *    因为溢出发生在 .list 的圆角框内部，document.scrollWidth 一直是 390，
 *    「不横向溢出」那条断言照样绿 —— 只有真截图看得出来。
 *    修法：body 这一格自己裁掉溢出（width:100% + overflow:hidden），
 *    里面的标题/副标题才吃得住 ellipsis。
 */
.msg-row .list-item__body { width: 100%; min-width: 0; overflow: hidden; }

/* 未读小胶囊（和红色红点同一个色系，但它是「条数」不是「有没有」） */
.msg-row__badge {
  flex-shrink: 0;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--red);
  color: #fff;
  font-style: normal;
  font-size: 11px;
  font-weight: 600;
  line-height: 18px;
  text-align: center;
}

/* 箭头：ui.js 用的是 chevron（指向右），这里统一成这一页的浅色小箭头 */
.msg-row .list-item__arrow { display: flex; line-height: 0; color: var(--text-3); opacity: .55; }

/* 加载占位（会话行还没回来时那一行） */
.msg-sk { display: flex; align-items: center; gap: 12px; padding: 14px 16px; }
.msg-sk .skeleton { display: block; }

/* 「系统通知」点开后的公告弹层：一条一段，段间一条细线 */
.msg-nt { padding: 2px 0 14px; }
.msg-nt--sep { border-top: 1px solid var(--line); padding-top: 14px; }
.msg-nt__t { font-size: 14.5px; font-weight: 600; letter-spacing: -.2px; color: var(--text); }
.msg-nt__c { margin-top: 6px; font-size: 13px; line-height: 1.75; color: var(--text-2); word-break: break-word; }
.msg-nt__d { margin-top: 8px; font-size: 11.5px; color: var(--text-3); }
