  /* ============================================================================
     对外网站 zb.jc95.cn —— QQ 频道风格（2026-09-23 定稿）
     结构：左竖条（我的头像 + 我绑定的群）｜中间（封面 + 设置项列表，一行一个）
          点设置项 → 整屏覆盖的设置页（左上角返回）
     ⚠️ 单文件内联：CDN/宝塔的 try_files 会在任意路径（如 /oauth/qq/callback）
        返回本页，引用相对路径的 css/js 会 404，所以不拆文件。
     ========================================================================== */
  * { box-sizing: border-box; }
  html, body { height: 100%; }
  body {
    margin: 0; background: #f5f6f8; color: #1f2329;
    font: 14px/1.5 -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif;
  }
  input, select, textarea, button {
    font-family: inherit; font-size: 13px; border-radius: 8px;
    border: 1px solid #dcdce6; padding: 7px 10px; outline: none;
    background: #fff; color: #1f2329;
  }
  input:focus, select:focus, textarea:focus { border-color: #1a8cff; }
  .btn { padding: 8px 16px; border: none; background: #1a8cff; color: #fff; cursor: pointer; border-radius: 8px; font-size: 13px; }
  .btn:hover { filter: brightness(.94); }
  .btn.ghost { background: #fff; color: #4a4f5e; border: 1px solid #dcdce6; }
  .btn.danger { background: #fff; color: #e0483d; border: 1px solid #f3c3bf; }
  .btn.dirty { background: #f59e0b; }          /* 配置页：有改动还没保存（按钮变黄 + 文案带"未保存"） */
  .btn:disabled { opacity: .55; cursor: default; }
  .dim { color: #9aa0b2; }
  .card { background: #fff; border-radius: 12px; padding: 14px 16px; margin-bottom: 12px; }
  .card h3 { margin: 0 0 10px; font-size: 14px; font-weight: 600; }
  .card h3 .hint { font-weight: 400; font-size: 12px; color: #9aa0b2; margin-left: 8px; }
  .field { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid #f2f3f6; }
  .field:last-child { border-bottom: none; }
  .field label { flex: 0 0 220px; font-size: 13px; color: #1f2329; }
  .field .ctl { flex: 1; }
  /* 「选择提示」行（退群提示）：复用 .field 布局，右侧显示当前选择 + 细线 chevron */
  .field.pick-row { cursor: pointer; border-radius: 8px; transition: background .15s ease; }
  .field.pick-row:hover { background: #f6f9ff; }
  .pick-val { text-align: right; color: #8b90a0; font-size: 12.5px; }
  .pick-arrow {
    flex: 0 0 auto; width: 7px; height: 7px; margin: 0 4px 0 8px;
    border-right: 1.6px solid #8b90a0; border-bottom: 1.6px solid #8b90a0;
    border-radius: 0 1px 0 0; transform: rotate(-45deg);   /* 朝右（和功能卡片同一套细线箭头） */
  }
  /* 欢迎词模板下面那行提示 + 「查看可用变量」胶囊 */
  .field-tip { font-size: 12px; color: #9aa0b2; margin-top: 6px; line-height: 1.9; }
  .var-chip {
    display: inline-block; margin-right: 8px; padding: 2px 9px; border-radius: 999px;
    background: rgba(26,140,255,.1); color: #1a8cff; cursor: pointer; font-size: 12px;
  }
  .var-chip:hover { background: rgba(26,140,255,.18); }
  /* 通用列表弹窗（退群提示选择 / 可用变量）的行 */
  .pick-list { max-height: 52vh; overflow-y: auto; margin-top: 10px; }
  .pick-item { display: flex; align-items: center; gap: 10px; padding: 10px; border-radius: 8px; cursor: pointer; }
  .pick-item:hover { background: #f6f9ff; }
  .pick-item.on { background: #eef5ff; }
  .pick-main { flex: 1; min-width: 0; }
  .pick-t { font-size: 13.5px; color: #1f2329; overflow-wrap: anywhere; }
  .pick-s { font-size: 12px; color: #9aa0b2; margin-top: 2px; }
  .pick-tick { flex: 0 0 auto; color: #1a8cff; font-weight: 700; }
  .field input[type=text], .field input[type=number], .field select { width: 100%; }
  textarea { width: 100%; min-height: 62px; resize: vertical; }
  .switch { position: relative; width: 42px; height: 23px; background: #d8dae3; border-radius: 12px; cursor: pointer; transition: .18s; flex: 0 0 42px; }
  .switch::after { content: ''; position: absolute; top: 2px; left: 2px; width: 19px; height: 19px; background: #fff; border-radius: 50%; transition: .18s; }
  .switch.on { background: #1a8cff; } .switch.on::after { left: 21px; }
  table { width: 100%; border-collapse: collapse; font-size: 13px; }
  th, td { text-align: left; padding: 7px 8px; border-bottom: 1px solid #f0f0f5; vertical-align: top; overflow-wrap: break-word; }
  /* 表格若还是比卡片宽 → 在**卡片内部**横向滚动，绝不把整页撑宽（手机上就不会左右移动） */
  .tbl-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  /* 表格里的数字输入框：浏览器默认宽约 170px（按 20 字符算），会把「字数超出」那列撑出屏外 → 收窄居中。
     ⚠️ 只作用在 table 内，.field 里的数字框不受影响。 */
  .card table input[type=number] { width: 82px; max-width: 100%; padding: 6px 6px; text-align: center; }
  th { color: #8b90a0; font-weight: 500; font-size: 12px; }
  tr:last-child td { border-bottom: none; }
  .tag { display: inline-block; padding: 2px 8px; border-radius: 6px; font-size: 11px; background: #f0f1f6; color: #6b7083; }
  .tag.ok { background: #e6f7ee; color: #1a9c58; }
  .tag.warn { background: #fff4e5; color: #b97500; }
  .row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
  /* 日志页「近 N 天统计」小格子（窄屏自动折行，不会撑破卡片） */
  .stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(86px, 1fr)); gap: 8px; }
  .stat-it { background: #f7f8fb; border-radius: 8px; padding: 8px 6px; text-align: center; }
  .stat-it b { display: block; font-size: 16px; color: #1a8cff; }
  .stat-it span { font-size: 11.5px; color: #8b90a0; }
  .loading { color: #9aa0b2; font-size: 13px; padding: 10px 0; }

  /* ---------- 登录 ---------- */
  .login-wrap { display: flex; align-items: center; justify-content: center; height: 100%; padding: 20px; }
  .login { width: 100%; max-width: 430px; }
  .login h1 { margin: 0 0 6px; font-size: 21px; }
  .login .step { margin: 14px 0 4px; padding-left: 18px; font-size: 13px; color: #5b6070; }
  .login .step li { margin-bottom: 5px; }
  .err { color: #e0483d; font-size: 13px; margin-top: 12px; display: none; }
  .btn.qq { background: #12b7f5; font-size: 15px; padding: 11px 22px; }

  /* ---------- 应用框架 ---------- */
  .app-ch { display: flex; max-width: 1120px; margin: 0 auto; height: 100vh; height: 100dvh; overflow: hidden; position: relative; }

  /* ① 左竖条 */
  .rail { width: 76px; flex: 0 0 76px; background: #fff; border-right: 1px solid #eceef2; display: flex; flex-direction: column; align-items: center; padding: 12px 0; gap: 12px; overflow-y: auto; overflow-x: hidden; }
  /* 头像外面套一层「拟变体（Neumorphism）」面板 —— jq22 code3031 的 `.button` 手法：
     左上白色高光 + 右下暗影 = 凸起；按下 / 选中时换成 inset 阴影 = 凹陷（原版就是 :active 时 box-shadow 归零）。
     ⚠️ 三个连带影响（不改就会出问题）：
       ① `.r-item` 从"就是头像"变成"比头像大一圈"（靠 padding 托起来）→ `.r-item.on::before`
          那根蓝竖条的 left 要跟着重算（本来 -14px 正好贴栏左边，现在会被挪到栏外、被裁掉）；
       ② `.rail` 必须补 `overflow-x: hidden`：它已经是 overflow-y:auto，按规范另一轴会**隐式变 auto**
          → 面板的阴影撑出横向滚动条（和"手机上能左右拖"是同一类坑）；
       ③ 头像自己不再投影（深度交给面板），否则两层影子糊在一起。 */
  .rail .r-item {
    position: relative; cursor: pointer;
    padding: 5px; border-radius: 21px;                    /* 21 - 5 = 16，正好等于头像圆角 */
    background: linear-gradient(145deg, #ffffff, #eef1f7);
    box-shadow: -2px -2px 6px #ffffff, 2px 3px 6px rgba(31, 45, 80, .16), inset 0 -2px 0 #e7eaf1;
    transition: box-shadow .13s ease-in-out, transform .13s ease-in-out;
  }
  .rail .r-item:active,
  .rail .r-item.on {
    box-shadow: inset 2px 3px 6px rgba(31, 45, 80, .18), inset -2px -2px 5px #ffffff;
    transform: translateY(1px);
  }
  /* 左上角「我」= 圆形头像 + **jq22 code899 的「摆动圆斑」当头像框**（canvas 由 app.js 挂）。
     这一格**不再套拟变体面板**：面板只有 58px 宽、光斑要 ~60px 才晃得开、才露得出来。 */
  #btnMe { border-radius: 50%; padding: 0; background: none; box-shadow: none; }
  #btnMe:active { box-shadow: none; transform: none; }    /* 别的格子按下会"凹陷"，这格不参与 */
  /* 画布居中在自己这格上（用 50%+translate 而不是写死偏移，桌面/手机两档头像尺寸都不用改）
     尺寸由 JS 按 dpr 写进 inline style */
  #btnMe .me-canvas {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    z-index: 0; pointer-events: none;
  }
  /* 头像盖在光斑中心 → 只看到外面那圈会摆动/自转的光晕。
     ⚠️ 这里把「我」收到 40px（群头像 48px）：光斑最大半径约 29px，
        48px 头像半径就有 24px → 只剩 5px 光晕、几乎看不见；40px（半径 20）能露出 ~9px。
        圆形 + 略小，正好读作"带光环的个人头像"，不会和方形的群头像混。 */
  #btnMe .r-av { position: relative; z-index: 1; width: 40px; height: 40px; }
  .rail .r-av { width: 48px; height: 48px; border-radius: 16px; background: #c3c8d2; display: flex; align-items: center; justify-content: center; font-size: 16px; font-weight: 600; color: #fff; user-select: none; overflow: hidden; }
  .rail .r-av img { width: 100%; height: 100%; object-fit: cover; }
  .rail .r-item.on::before { content: ''; position: absolute; left: -9px; top: 50%; transform: translateY(-50%); width: 4px; height: 26px; border-radius: 0 3px 3px 0; background: #1a8cff; }
  .rail .r-item.on .r-av { box-shadow: 0 0 0 2px #1a8cff; }
  .rail .r-sep { width: 32px; height: 1px; background: #eceef2; flex: 0 0 1px; }
  .rail .r-add { width: 48px; height: 48px; border-radius: 16px; border: 1px dashed #cfd4de; background: #fafbfc; color: #9aa0b2; font-size: 22px; line-height: 1; cursor: pointer; flex: 0 0 48px; }
  .rail .r-add:hover { border-color: #1a8cff; color: #1a8cff; }
  #groupRail { display: flex; flex-direction: column; align-items: center; gap: 12px; }

  /* ② 中间：封面 + 设置列表 */
  .chl { flex: 1 1 auto; min-width: 0; background: #f5f6f8; display: flex; flex-direction: column; }
  .banner { position: relative; height: 132px; flex: 0 0 132px; background: linear-gradient(135deg, #4f6f92, #7896b4 55%, #b9a897); color: #fff; }
  /* 封面尺寸变量：JS 每次 fit / resize 都会刷成真实值；这几行是**兜底**（JS 没跑到、元素隐藏时量不到）
     + 手机两档高度。素材一律用 --bw / --bh / --bu / --bvmin，不要再写 vw/vh/vmin（视口单位在 132px 高的封面里会失控）。 */
  #banner { --bw: 1044px; --bh: 132px; --bu: 132px; --bvmin: 132px; }
  .banner .b-in { position: absolute; left: 16px; right: 16px; bottom: 12px; }
  /* 群昵称字号：2026-09-25 用户说「可以小一些」→ 20px 改 **17px**（手机档见下面断点里的 .b-name）。
     ⚠️ 只想再调大小的话改这两处数字就行，别动下面的 ellipsis（长群名靠它截断）。 */
  .banner .b-name { font-size: 17px; font-weight: 700; text-shadow: 0 1px 6px rgba(0,0,0,.3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .banner .b-sub { font-size: 12px; margin-top: 5px; color: #eaf0f6; display: flex; align-items: center; gap: 7px; }
  .banner .on-dot { width: 8px; height: 8px; border-radius: 50%; background: #12d18e; box-shadow: 0 0 0 3px rgba(18,209,142,.3); flex: 0 0 8px; }
  /* 群身份徽章（2026-09-25）：原来那句口语「你是群主 / 你被授权」→ 换成小胶囊。
     owner = 你就是拿验证码绑这个群的人（绑定主人）；admin = 你被主人授权一起管。 */
  .banner .b-tag {
    display: inline-flex; align-items: center; flex: 0 0 auto;
    height: 17px; padding: 0 7px; border-radius: 9px;
    font-size: 11px; font-weight: 600; letter-spacing: .2px; line-height: 1;
    color: #fff; background: rgba(255,255,255,.20);
    border: 1px solid rgba(255,255,255,.45); backdrop-filter: blur(3px);
    white-space: nowrap;
  }
  .banner .b-tag.owner {                       /* 群主：金色实心，一眼能认出来 */
    background: linear-gradient(135deg, #ffe07a, #f5b62d); color: #5b3a02;
    border-color: rgba(255,255,255,.72); box-shadow: 0 1px 7px rgba(0,0,0,.22);
  }
  .banner .b-tag.admin { background: rgba(255,255,255,.22); color: #fff; }   /* 管理员：磨砂白 */
  /* 封面右下角：「⋯」更多操作（原来右上角一排按钮 + 右下角一个解绑键 → 全收进这里，封面更干净） */
  .banner .b-in { right: 56px; }           /* 只需给那一个 32px 的按钮腾位置 */
  .banner .b-more {
    position: absolute; right: 12px; bottom: 12px; z-index: 3;
    width: 32px; height: 32px; padding: 0; border-radius: 9px;
    border: 1px solid rgba(255,255,255,.38); background: rgba(0,0,0,.28); color: #fff;
    font-size: 16px; line-height: 1; cursor: pointer; backdrop-filter: blur(4px);
    transition: background .15s ease;
  }
  .banner .b-more:hover { background: rgba(0,0,0,.46); }
  /* 「⋯」的下拉菜单：fixed 定位（每次打开由 JS 按按钮位置算坐标）。
     放在 .banner **外面** —— 封面有 overflow:hidden，在里面会被裁掉。 */
  .b-menu {
    position: fixed; z-index: 120; min-width: 172px; padding: 6px;
    display: flex; flex-direction: column; gap: 2px;
    background: #fff; border: 1px solid #eceef2; border-radius: 12px;
    box-shadow: 0 12px 32px rgba(20, 30, 60, .22);
  }
  .bm-item {
    width: 100%; text-align: left; background: none; border: 0;
    padding: 9px 10px; border-radius: 8px; font-size: 13px; color: #1f2329; cursor: pointer;
  }
  .bm-item:hover { background: #f2f6ff; }
  .bm-item.danger { color: #e0483d; }
  .bm-item.danger:hover { background: #fff1f0; }
  .bm-item:disabled { color: #c2c6d0; cursor: default; background: none; }
  .chl-body { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 4px 8px 30px; }
  .search { width: 100%; margin: 8px 0 4px; }
  .grp { font-size: 12px; color: #9aa0b2; padding: 12px 8px 6px; display: flex; align-items: center; gap: 6px; }
  .ch-item { display: flex; align-items: center; gap: 12px; background: #fff; border-radius: 12px; padding: 12px 12px; margin-bottom: 8px; cursor: pointer; }
  .ch-item:hover { background: #f4f8ff; }
  .ch-item.on { background: #eaf2ff; }
  /* 展开箭头：**纯 CSS 画的细线 chevron**（原来是 '›' 字符 —— 各系统字形粗细/基线不一，看着"脏"）。
     两条 border 转 -45° = 朝右，展开时 .open 里改成 +45° = 朝下。
     ⚠️ 为什么坚持用箭头而不是 +/-：NN/g 136 人 first-click 实验里 caret 最稳，
        `+` 只与"无图标"持平，右向箭头 ▶ 更是和无图标无显著差异 → 不要改成 ▶、也不要去掉图标。 */
  .ch-item::after {
    content: ''; flex: 0 0 auto; width: 7px; height: 7px; margin: 0 4px 0 10px;
    border-right: 1.6px solid currentColor; border-bottom: 1.6px solid currentColor;
    border-radius: 0 1px 0 0; transform: rotate(-45deg); color: #8b90a0; opacity: .85;
  }
  .ci-icon { width: 42px; height: 42px; flex: 0 0 42px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 18px; }
  .ci-body { flex: 1; min-width: 0; }
  .ci-name { font-size: 15px; font-weight: 600; color: #1f2329; }
  .ci-sub { font-size: 12px; color: #9aa0b2; margin-top: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* ③ 设置页：整屏覆盖 */
  .det { position: absolute; inset: 0; z-index: 50; display: none; flex-direction: column; background: #f5f6f8; }
  .det.on { display: flex; }
  .det-top { display: flex; align-items: center; gap: 10px; padding: 10px 14px; background: #fff; border-bottom: 1px solid #eceef2; flex-wrap: wrap; }
  .det-top .hd-back { border: none; background: none; font-size: 22px; line-height: 1; cursor: pointer; color: #1f2329; padding: 0 6px 0 0; }
  .det-top .hd-title { font-size: 16px; font-weight: 600; }
  .det-top .sp { flex: 1; }
  .det-body { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 14px 16px 40px; }
  .det-body > .pane { max-width: 800px; margin: 0 auto; }
  /* 折叠外壳（.dwrap）：整屏页时撑满剩余高度、内容照旧自己滚 */
  .dwrap { flex: 1; min-height: 0; display: grid; grid-template-rows: 1fr; }
  .dwrap > .det-body { min-height: 0; }
  .hint-line { font-size: 12px; color: #9aa0b2; margin: 0 2px 10px; }

  /* ---------- 功能折叠：设置内容**就地展开**在功能卡片下方（不再整屏跳页） ---------- */
  .det.inline { position: static; inset: auto; z-index: auto; background: transparent; }
  /* 展开时**不再重复显示标题条**（卡片上已经有名字/图标了）：
     JS 会把这整条挪到内容**下面**当操作栏 → 这里把 ‹ 返回 / 图标 / 标题藏掉，只留按钮，并去掉卡片外观 */
  .det.inline .det-top {
    position: static; z-index: auto; background: transparent;
    border: 0; border-top: 1px solid #eceef2; border-radius: 0;
    box-shadow: none; margin: 0; padding: 10px 0 2px;
  }
  .det.inline .det-top .hd-back,
  .det.inline .det-top .hd-icon,
  .det.inline .det-top .hd-title { display: none; }
  .det.inline .det-body > .pane { max-width: none; margin: 0; }

  /* ---------- 「卡片式菜单」折叠动效（借 jq22 code4484 的卡片语言） ----------
     原 demo 是整屏接管式导航（fixed + body.no-scroll + 4 张卡各 25vh），结构不适合搬；
     但它的动效很适合我们的就地折叠，这里逐条移植：
       ① 被点中的卡片 = 从牌堆里「被抽出来」：抬起 + 大阴影（demo: box-shadow 0 .5em .5em）
       ② 卡片图标 0→1 过冲弹出（demo 原式 cubic-bezier(.42,0,.58,1.5)）
       ③ 箭头缩掉（demo 的 .nav--open .nav__arrow: opacity 0 + scale(0)）
       ④ 下方卡片「依次下滑」让位：内容用 grid-rows 0fr→1fr 平滑撑开（不再是「啪」地跳出来），
          下方卡片再叠一层逐级延迟的 cardPush 小动画，做出 demo 那种「依次」的节奏。 */
  /* 展开 / 收起节奏：0.36s → 0.24s。曲线 `.2,.8,.2,1` = 前段快、末段缓，
     比原来的匀速感利落得多（12 张卡片连点时"跟手感"差别很明显）。
     ⚠️ 改这里时记得 `collapseFeature()` 里那个 `setTimeout(..., 380)` 是配合动画时长等的
        —— 它只影响"把设置块搬回原位"的时机，改长了也不会有视觉问题（里面还有 CUR_FEAT 守卫）。 */
  .det.inline .dwrap { flex: none; grid-template-rows: 0fr; transition: grid-template-rows .24s cubic-bezier(.2,.8,.2,1); }
  .det.inline.on .dwrap { grid-template-rows: 1fr; }
  .det.inline .dwrap > .det-body { overflow: hidden; padding: 0 0 4px; opacity: 0; transition: opacity .16s ease .04s; }
  .det.inline.on .dwrap > .det-body { opacity: 1; }
  .det.inline.on { animation: none; }                    /* 关掉整屏页的 pageIn，改由高度动画进场 */

  /* ① 展开的那张卡：白底 + 一圈**内描边**（inset 阴影不占位，不会把卡片撑大/抖一下）。
        不再用"抬起 + 大阴影"那套（见上面「简化」说明：那是第三层影子）。 */
  .ch-item.on.open {
    background: #fff; z-index: 3;
    box-shadow: inset 0 0 0 1px #d7e6ff;
  }
  /* ③ 箭头：展开时 → 朝下（+45°）。给一点点回弹，和整体节奏一致；
        颜色走 currentColor，所以 hover / 展开变蓝不用再写第二遍 */
  .ch-item::after { transition: transform .24s cubic-bezier(.42, 0, .58, 1.5), color .15s ease, opacity .15s ease; }
  .ch-item:hover::after { color: #1a8cff; opacity: 1; }
  .ch-item.open::after { transform: rotate(45deg); color: #1a8cff; opacity: 1; }
  /* （原来 `.ch-item.open .ci-icon { scale(1.08) }` 的"图标弹一下"已删：安静版不需要，
        而且 12 张卡片连点时会显得很跳。） */
  /* ④ 下方卡片：依次下滑让位（延迟仍由 JS 逐张设 animation-delay，播完把 .push 摘掉）。
        原来 .34s + 逐级 35ms，12 张卡要 0.77s 才收尾 → 压到 .22s / 位移 10px→8px。 */
  .ch-item.push { animation: cardPush .22s cubic-bezier(.22, .9, .28, 1) both; }
  @keyframes cardPush { from { transform: translateY(-8px); } to { transform: none; } }
  @media (max-width: 760px) {
    .det.inline .det-top { padding: 8px 0 2px; gap: 8px; }
    .det.inline .det-top .btn { padding: 6px 10px; font-size: 12px; }
  }

  /* ---------- 弹窗 / toast ---------- */
  .modal { position: fixed; inset: 0; background: rgba(20,22,30,.45); z-index: 200; display: flex; align-items: center; justify-content: center; padding: 20px; }
  .modal-box { background: #fff; border-radius: 12px; padding: 16px 18px; width: 100%; max-width: 420px; }
  .modal-title { font-size: 15px; font-weight: 600; margin-bottom: 6px; }
  .modal-desc { font-size: 13px; color: #5b6070; line-height: 1.6; white-space: pre-wrap; }
  .modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
  .toast { position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%); background: #2b2f3a; color: #fff; padding: 9px 18px; border-radius: 8px; font-size: 13px; opacity: 0; transition: .2s; pointer-events: none; z-index: 300; }
  .toast.show { opacity: 1; }

  /* ---------- 美化细节 ---------- */
  .app-ch { box-shadow: 0 0 0 1px #edeff3; }
  /* 细滚动条 */
  .chl-body::-webkit-scrollbar, .det-body::-webkit-scrollbar, .rail::-webkit-scrollbar { width: 8px; }
  .chl-body::-webkit-scrollbar-thumb, .det-body::-webkit-scrollbar-thumb, .rail::-webkit-scrollbar-thumb { background: #d6dae2; border-radius: 4px; }
  .chl-body::-webkit-scrollbar-track, .det-body::-webkit-scrollbar-track, .rail::-webkit-scrollbar-track { background: transparent; }

  /* 封面：柔光 + 群头像 */
  .banner::before {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background: radial-gradient(120% 80% at 12% 6%, rgba(255,255,255,.30), transparent 62%);
  }
  .banner .b-in { display: flex; align-items: center; gap: 12px; }
  .banner .b-av {
    width: 52px; height: 52px; flex: 0 0 52px; border-radius: 16px; background: #8a94a6;
    display: flex; align-items: center; justify-content: center;
    font-size: 20px; font-weight: 700; color: #fff;
    border: 2px solid rgba(255,255,255,.85); box-shadow: 0 4px 14px rgba(0,0,0,.22);
  }
  .banner .b-txt { min-width: 0; flex: 1; }
  /* （旧封面右上角那排按钮已收进 ⋯ 菜单 → .b-acts / .b-btn 规则全部删除） */

  /* 功能卡片：左侧渐变色条 + 悬停微亮。
     ⚠️ 2026-09-24 简化（原来是"影子套影子"：hover 位移+阴影 / 选中阴影 / 展开大阴影+位移 三层叠加，
        手机上 hover 还容易粘住）→ 现在**只留两个状态信号**：
          ① 左侧色条（选中 / 展开时加宽到 5px）  ② 背景色（hover 淡蓝 / 展开纯白）
        与 USWDS 的做法一致（它的 accordion 完全没有 shadow token，纯靠背景与留白分层）。 */
  .ch-item {
    position: relative; overflow: hidden; border-radius: 12px;
    transition: background .16s ease;
  }
  .ch-item::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--accent, #1a8cff); transition: width .16s ease; }
  .ch-item:hover { background: #f6f9ff; }
  .ch-item.on { background: #eef5ff; }
  .ch-item.on::before, .ch-item.open::before { width: 5px; }
  /* 图标块：去掉投影（emoji + 渐变色块本身已经够有存在感，阴影只会让列表变"脏"） */
  .ci-icon { font-size: 20px; }
  .list-head { display: flex; align-items: center; gap: 8px; padding: 14px 8px 6px; font-size: 12px; color: #9aa0b2; }
  .list-head .n { background: #eef1f6; color: #6b7083; border-radius: 8px; padding: 1px 7px; font-size: 11px; }
  /* 分区头（全部功能）：可点折叠 / 展开，默认展开，右侧箭头跟着转 */
  .list-head { cursor: pointer; user-select: none; border-radius: 8px; transition: background .15s ease; }
  .list-head:hover { background: #f1f4f8; }
  .list-head .sp { flex: 1; }
  /* 「全部功能」的指引箭头：和功能卡片**统一成同一套**（纯 CSS 细线 chevron + 挪到右边）。
     原来它是 '›' 字符放在标题**前面** → 同一屏里"分区头在左、卡片在右"两套约定，看着不统一；
     而 iOS / shadcn / Material 的列表都是右侧 disclosure，所以以卡片为准，统一到右。
     ⚠️ rotate 基准：基础几何 = "朝右"（-45°）；展开时朝下（+45°），收起时回朝右（-45°）。 */
  .list-head .tgl {
    display: block; order: 9; margin-left: auto;   /* order + auto margin = 挪到整行最右，不用改 HTML 结构 */
    width: 12px; height: 12px; flex: 0 0 12px; color: #9aa0b2;
    transition: transform .22s cubic-bezier(.42, 0, .58, 1.5), color .15s ease;
  }
  .list-head .tgl::before {
    content: ''; display: block; width: 6px; height: 6px; margin: 1px auto 0;
    border-right: 1.6px solid currentColor; border-bottom: 1.6px solid currentColor;
    border-radius: 0 1px 0 0; transform: rotate(45deg);          /* 展开 = 朝下 */
  }
  .list-head:hover .tgl { color: #1a8cff; }
  .list-head.collapsed .tgl::before { transform: rotate(-45deg); }   /* 收起 = 朝右 */
  /* 折叠动画：与设置面板同一套 grid-rows（1fr ↔ 0fr）手法 */
  .lwrap { display: grid; grid-template-rows: 1fr; transition: grid-template-rows .3s cubic-bezier(.22, .9, .28, 1); }
  .lwrap.collapsed { grid-template-rows: 0fr; }
  .lwrap-in { min-height: 0; overflow: hidden; }   /* 折叠时靠它裁切；只裁掉约 1px 的阴影，看不出 */

  /* 左竖条 */
  .rail { background: linear-gradient(180deg, #ffffff, #fbfcfd); }
  /* 左上角「我的头像」用**圆形**（绑定群头像是圆角方形，两种形状区分开）。
     用 id 提高优先级，手机媒体查询里的 .rail .r-av 也盖不过它。 */
  #btnMe .r-av { border-radius: 50%; }

  /* ---------- 左竖条：添加机器人入口 + 「我的机器人」页 ---------- */
  .rail .r-bot { background: linear-gradient(135deg, #7c3aed, #4f46e5); font-size: 21px; }
  /* （机器人视图顶部原来有条「‹ 返回全部功能」(.cv-head)，2026-09-24 用户要求删除 →
      规则一并删掉，别再往 #viewBot 里加返回条；回去靠「再点一次 🤖」或点左竖条的群。） */
  .rb-row { display: flex; align-items: center; gap: 8px; padding: 7px 0; font-size: 13px; }
  .rb-row .k { color: #8b90a0; flex: 0 0 72px; }
  .rb-row .v { flex: 1; min-width: 0; overflow-wrap: anywhere; }
  .rb-av { width: 42px; height: 42px; border-radius: 12px; object-fit: cover; flex: 0 0 42px;
           background: #eef1f6; display: flex; align-items: center; justify-content: center; font-size: 20px;
           overflow: hidden; }                       /* 里面放 <img> 时按圆角裁掉 */
  .rb-av img { width: 100%; height: 100%; object-fit: cover; display: block; }
  /* 「我的机器人」卡片头：头像 + 名称 + 在线状态一行（头像来自 QQ 官方，见 app.js renderRobots） */
  .rb-head { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
  .rb-head-txt { min-width: 0; flex: 1; }
  .rb-av-lg { width: 52px; height: 52px; flex: 0 0 52px; border-radius: 14px; font-size: 24px; }
  .rb-name { font-size: 15px; font-weight: 600; }
  .rb-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: #d8dae3; margin-right: 6px; }
  .rb-dot.on { background: #12d18e; box-shadow: 0 0 0 3px rgba(18,209,142,.25); }
  .rb-dot.off { background: #e0483d; }
  .rb-tip { font-size: 12.5px; color: #8b90a0; line-height: 1.75; }
  .rb-acts { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
  .rb-acts.center { justify-content: center; }         /* 「点击登录 / 取消」居中排 */
  .rb-qr { text-align: center; padding: 6px 0 2px; }
  .rb-qr img { width: 186px; height: 186px; border-radius: 12px; background: #fff; padding: 8px;
               box-shadow: 0 2px 12px rgba(31,45,80,.14); }
  /* 「点击登录 / 免费邀请」这类**做成按钮的链接**：`.btn` 原本只为 <button> 写，
     放到 <a> 上要补 inline-flex 对齐 + 去下划线，才能和普通 .btn 长得一模一样 */
  a.btn { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }
  /* 「点击登录」= 液态（果冻）按钮：里面那张 canvas 只是**会晃的背景**，文字仍由 DOM 画
     —— 这样清晰、可选中，canvas 万一没起来按钮也照样有字、照样能点。
     canvas 的位置/尺寸（比按钮大一圈 margin）由 app.js 的 LiquidButton 按参数写 inline style。 */
  .lb-btn {
    position: relative; display: inline-flex; align-items: center; justify-content: center;
    width: 190px; height: 50px; text-decoration: none; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .lb-canvas { position: absolute; pointer-events: none; }
  .lb-text { position: relative; z-index: 1; color: #fff; font-size: 15px; font-weight: 600; letter-spacing: .5px; }
  /* （头像自己不再投影：深度由外面那块拟变体面板负责，两层影子会糊） */
  .rail .r-av { transition: transform .16s ease, box-shadow .16s ease; }
  .rail .r-item:hover .r-av { transform: scale(1.05); }
  .rail .r-item:active .r-av,
  .rail .r-item.on .r-av { transform: scale(.98) translateY(1px); }   /* 按下/选中 = 跟着面板一起沉下去 */
  /* 选中：头像加一圈蓝环（配合左侧蓝竖条，保证"当前是哪个群"一眼可辨 —— 光靠凹陷不够明显） */
  .rail .r-item.on .r-av { box-shadow: 0 0 0 2px #1a8cff; }

  /* 设置页：进场动画 + 标题带功能图标 */
  .det.on { animation: pageIn .18s ease; }
  @keyframes pageIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
  .det-top .hd-icon {
    width: 30px; height: 30px; border-radius: 9px; display: none;
    align-items: center; justify-content: center; font-size: 15px;
    box-shadow: 0 2px 6px rgba(31,45,80,.16);
  }
  .det-top .hd-icon.on { display: flex; }
  /* 内容卡片：标题前加小色块 */
  .card h3 { display: flex; align-items: center; gap: 8px; }
  .card h3::before { content: ''; width: 3px; height: 14px; border-radius: 2px; background: #1a8cff; flex: 0 0 3px; }

  /* ---------- 手机 ---------- */
  @media (max-width: 760px) {
    .rail { width: 64px; flex-basis: 64px; padding: 10px 0; gap: 10px; }
    .rail .r-av, .rail .r-add { width: 42px; height: 42px; border-radius: 14px; font-size: 14px; }
    .rail .r-item { padding: 4px; border-radius: 18px; }   /* 18 - 4 = 14，跟手机档头像圆角对齐 */
    .rail .r-item.on::before { left: -7px; }               /* 64 - (42+8) = 14 → 每边正好 7 */
    .banner { height: 104px; flex-basis: 104px; }
    #banner { --bw: 375px; --bh: 104px; --bu: 104px; --bvmin: 104px; }
    .banner .b-name { font-size: 15px; }   /* 窄屏档：18 → 15，与桌面档（17px）同步缩小 */
    .banner .b-in { right: 50px; }
    .banner .b-more { right: 10px; bottom: 10px; width: 30px; height: 30px; }
    .ch-item { padding: 11px 8px; }
    .field label { flex-basis: 130px; }
    .det-top { padding: 10px 12px; }
  }
  @media (max-width: 480px) {
    .banner { height: 96px; flex-basis: 96px; }
    #banner { --bh: 96px; --bu: 96px; --bvmin: 96px; }
    .ci-icon { width: 34px; height: 34px; flex-basis: 34px; border-radius: 10px; font-size: 16px; }
    th, td { padding: 6px 5px; }                          /* 小屏：表格内边距收一收 */
    .card table input[type=number] { width: 72px; }
  }

  /* ==========================================================================
     封面像素波纹（参考 jq22「像素化加载器」的像素网格波纹）
     ⚠️ 与原 demo 的区别：**不做常驻 requestAnimationFrame 循环**
        —— 原版是加载动画，像素会一直闪；当背景常驻会抢焦点、手机上还费电。
        这里改成：网格由 JS 生成一次，切群/进页面时跑 0.95s 波纹，停在很淡的静态点阵上。
     ========================================================================== */
  .banner { overflow: hidden; }
  .px-layer {
    position: absolute; inset: 0; z-index: 1; pointer-events: none;
    display: grid; grid-template-columns: repeat(26, 1fr); grid-auto-rows: 1fr;
  }
  .px-layer i {
    display: block; opacity: 0; transform: scale(.35);
    background: var(--px, rgba(255,255,255,.9)); border-radius: 1px;
  }
  .px-layer.run i {
    animation: pxIn .95s cubic-bezier(.22,.7,.3,1) forwards;
    animation-delay: var(--d, 0s);
  }
  @keyframes pxIn {
    0%   { opacity: 0;   transform: scale(.3); }
    30%  { opacity: .46; transform: scale(1); }
    100% { opacity: .10; transform: scale(1); }
  }
  .banner .scrim {
    position: absolute; inset: 0; z-index: 2; pointer-events: none;
    background: linear-gradient(90deg, rgba(10,16,28,.46), rgba(10,16,28,.14) 55%, rgba(10,16,28,.34));
  }
  .banner::before { z-index: 0; }
  .banner .b-in { z-index: 3; }
  @media (prefers-reduced-motion: reduce) {
    .px-layer.run i { animation: none; opacity: .10; transform: none; }
  }

  /* ==========================================================================
     封面背景：**一个素材一个文件** → site-assets/banners/bg-01-xxx.js …
     这里只放「容器」样式；每套背景自己的 .banner.bg-<id> 规则由素材文件注入。
     加/删/改某一套背景 = 只动那一个文件，不用改 style.css。
     ========================================================================== */
  /* ⚠️ width/height 必须显式写 100%：canvas 是**替换元素**，只给 inset:0 不会拉伸，
     它会按 `c.width/c.height`（= w×dpr 的物理像素）的原尺寸显示 → 手机上画布会变成两倍大。
     写成 100% 后，画布永远铺满封面（引擎只管内部像素，不再写 style.width/height）。 */
  .b-canvas { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; display: none; pointer-events: none; }
  .banner.live .b-canvas { display: block; }
  /* WebGL2 素材的画布（片元着色器类）：同样由 CSS 铺满封面，只在 .livegl 时显示。
     ⚠️ 这里的 width/height:100% 是必须的 —— canvas 是替换元素，不给尺寸它会按内部像素原尺寸显示。 */
  .b-gl { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; display: none; pointer-events: none; }
  .banner.livegl .b-gl { display: block; }

  /* 背景选择列表（点封面右上角 🎲 弹出）：**一行 5 个**的文字格子，点哪个就是哪个 */
  #bgModal .modal-box { max-width: 760px; }      /* 5 列要够宽，否则名字被截断 */
  .bg-grid {
    display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px;
    margin-top: 12px; max-height: 58vh; overflow-y: auto; padding: 2px;
  }
  .bg-row {
    display: flex; align-items: center; justify-content: center; gap: 3px;
    padding: 9px 6px; font-size: 12px; line-height: 1.25; text-align: center;
    color: #1f2329; cursor: pointer; overflow: hidden;
    background: #fff; border: 1px solid #e6e9ef; border-radius: 8px;
  }
  .bg-row:hover { background: #f4f8ff; border-color: #cfe2ff; }
  .bg-row.on { background: #eef5ff; border-color: #1a8cff; color: #0b63d6; font-weight: 600; }
  .bg-row .bg-tick { flex: none; font-size: 11px; color: #1a8cff; }
  .bg-row .bg-nm { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .bg-row .bg-sub { display: none; }             /* 5 列太窄，右侧小字说明不显示 */
  /* 窄屏（手机）降到一行 3 个，别把字挤没 */
  @media (max-width: 560px) {
    .bg-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  }
