/* ===========================================================================
   移动端适配（v1.33.0）
   ===========================================================================

   为什么单独一个文件？
   ---------------------------------------------------------------------------
   console.css 里先后存在过两套互相打架的移动端规则：
     · 旧方案（约 1331 行）：侧栏横置顶部、菜单横向滑动 —— 已被淘汰；
     · 新方案（约 2319 行）：侧栏改左侧抽屉 + 右下角悬浮「菜单」按钮。
   新方案在源码里更靠后，赢了，但旧的半套仍在生效；更要命的是 skin.css
   最后加载，它的 .sidebar{width:var(--sidebar-w)} 与 .nav-item{height:var(--nav-h)}
   又把抽屉宽度压回 212px、菜单项压回 28px —— 手机上菜单只有指甲盖高。

   与其在三个文件里互相打补丁，这里放一份完整、自洽的窄屏实现，作为
   最后一层覆写。加载顺序固定为：
     console.css → dash2.css → board.css → skin.css → mobile.css
   所以本文件不需要 !important 就能盖住桌面规则。

   设计取舍
   ---------------------------------------------------------------------------
   1. 顶部常驻应用栏（汉堡 + 当前页标题）：抽屉方案最大的问题是「导航藏在
      屏幕外，而手机上又看不到当前在哪一页」。这里把「当前页面」提到顶部
      常驻，进任何一页都清楚自己在哪。
   2. 汉堡按钮放左上角 —— 用户最容易找的位置，替换掉原来右下角的悬浮
      「菜单」按钮（那个位置会盖住列表最后一行和聊天发送框）。
   3. 抽屉改从顶部栏下方滑出，宽度 min(86vw, 320px)，菜单项 44px 高，
      符合手指点击的最小尺寸。
   4. 抽屉里保留侧栏原有的品牌、当前页、主题、连接状态、通知铃与账号区，
      功能一个不少；桌面端完全不受影响（全部包在 @media 里）。
   5. 内容区补齐 min-width:0 / flex-wrap，消掉「子元素撑破父容器」这类
      中文后台最常见的溢出。
--------------------------------------------------------------------------- */

/* ---------------------------------------------------------------- 基础重置
   全站一直缺 body 的 margin 重置：控制台四周会留出 8px 白边，而 .app 又写死
   了 height:100dvh，等于每页都多出 8px 纵向滚动。只在这三个后台页面修，
   不碰官网（官网走自己的 index.html 内联样式）。 */
html, body {
  margin: 0;
  padding: 0;
  /* iOS 横屏与下拉回弹时避免整页抖动 */
  overscroll-behavior-y: none;
}

/* ------------------------------------------------------ 视口锁死（v1.39.0）
   手机的软键盘不会改变布局视口，但会改变可视视口。如果 body 本身可以滚动，
   Safari 为了让被键盘盖住的输入框露出来，会**把整页往上推**——表现为
   「点输入框的瞬间，顶栏和消息一起跳走一截」，收起键盘又弹回来。
   用户报的「页面乱跳」，一大半来自这里。

   所以手机上彻底关掉整页滚动：滚动只发生在 .chat-body / .conv-list /
   .page 这些内部容器里，页面外壳一寸都不动。高度的活交给 --vvh（由
   viewport.js 按可视视口实时写入）。 */
@media (max-width: 860px) {
  html, body {
    height: 100%;
    overflow: hidden;
    /* 老 iOS 用 fixed 锁住 body 最稳，但会和 .app 的 fixed 打架，
       这里只靠 overflow:hidden + touch-action 兜住 */
    touch-action: manipulation;
  }
}

/* 内核级点击高亮在深色主题下会闪一块蓝灰方块，换成更淡的反馈 */
html { -webkit-tap-highlight-color: rgba(79, 110, 247, 0.12); }

/* 移动端底部安全区：抽屉、弹窗、输入框都要吃到，先给变量兜底 */
:root {
  --mbar-h: 52px;
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}

/* 应用外壳：高度用 dvh，但必须 border-box，
   否则 .main 的 padding 会把内容顶出屏幕（内容盒模型下 height+padding 会超出）。 */
.app,
.main,
.sidebar,
.page {
  box-sizing: border-box;
}

/* =========================================================== 窄屏：手机 / 平板竖屏 */
@media (max-width: 860px) {

  /* -------------------------------------------------- 顶部应用栏（新增结构）
     三等分：左汉堡 44，中间标题自适应，右侧留 8px 呼吸。 */
  .mbar {
    display: flex;
    align-items: center;
    gap: 10px;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 100;
    height: calc(var(--mbar-h) + var(--safe-top));
    padding: var(--safe-top) 12px 0 58px;
    box-sizing: border-box;
    background: var(--panel);
    border-bottom: 1px solid var(--line);
    /* 顶栏要压在页面内容之上，但不抢抽屉与弹窗的层级 */
    transition: background 0.3s ease;
  }
  .mbar-title {
    min-width: 0;
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    gap: 1px;
  }
  .mbar-title b {
    font-size: 15px;
    font-weight: 650;
    color: var(--text);
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .mbar-title small {
    font-size: 10.5px;
    color: var(--muted-2);
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* 当前页有未读时，标题旁点一个红点，不用展开抽屉也知道有新消息（由 common.js 置位） */
  .mbar-title b .mbar-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    margin-left: 6px;
    vertical-align: 2px;
    border-radius: 50%;
    background: var(--danger);
  }

  /* -------------------------------------------------- 汉堡按钮：左上角常驻
     原来它在右下角、42px 高、浮在内容上；现在移到顶栏左侧，44x44 标准触区。 */
  .sidebar-trigger {
    display: inline-flex;
    position: fixed;
    top: var(--safe-top);
    left: 6px;
    z-index: 112;                 /* 高于抽屉与 scrim，打开后还能点它关掉 */
    width: 44px;
    height: var(--mbar-h);
    min-width: 0;
    padding: 0;
    align-items: center;
    justify-content: center;
    gap: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    color: var(--text-2);
    font: inherit;
  }
  .sidebar-trigger:active { background: var(--panel-3); }
  /* 把「菜单 / 会话」文字收进屏幕阅读器，视觉上只留三道杠 */
  .sidebar-trigger > span:not(.sidebar-trigger-icon) {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
  .sidebar-trigger-icon,
  .sidebar-trigger-icon::before,
  .sidebar-trigger-icon::after {
    width: 18px;
    height: 2px;
  }
  .sidebar-trigger-icon::before { top: -6px; }
  .sidebar-trigger-icon::after { top: 6px; }
  /* 展开时三道杠变 X */
  .app.sidebar-open .sidebar-trigger-icon { background: transparent; }
  .app.sidebar-open .sidebar-trigger-icon::before { top: 0; transform: rotate(45deg); }
  .app.sidebar-open .sidebar-trigger-icon::after { top: 0; transform: rotate(-45deg); }
  .sidebar-trigger-icon,
  .sidebar-trigger-icon::before,
  .sidebar-trigger-icon::after {
    transition: transform 0.2s ease, background 0.2s ease, top 0.2s ease;
  }

  /* -------------------------------------------------- 侧栏 → 左侧抽屉
     skin.css 用 --sidebar-w 把宽度锁死在 212px，这里显式改写宽度与内边距。
     注意：app.js 用内联 style 把 .app 设成 display:flex（不是 block），
     所以这里只能改 flex-direction，不能指望 display:block 生效。 */
  .app {
    /* v1.39.0：外壳高度跟着「可视视口」走，而不是 100dvh。
       dvh 只反映浏览器地址栏，不反映软键盘——键盘弹出时它一点不变，
       于是底部的输入框正好落在键盘背后。--vvh 由 viewport.js 实时写入，
       JS 没跑起来时回落到 100dvh，不会白屏。

       position:fixed 是为了让外壳脱离文档流：body 一旦不能滚，
       外壳就必须自己钉在视口上，否则高度变化会把内容顶出去。
       transform 同时把 fixed 定位的顶栏/抽屉/弹窗的包含块从「布局视口」
       改成「这个外壳」，等于它们自动被约束在键盘上方的可见区里。 */
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    flex-direction: column;
    height: 100vh;
    height: 100dvh;
    height: var(--vvh, 100dvh);
    transform: translateY(var(--vv-top, 0px));
    overflow: hidden;             /* 滚动交给 .page，抽屉不会带着整页一起晃 */
  }
  .sidebar {
    position: fixed;
    top: calc(var(--mbar-h) + var(--safe-top));
    left: 0;
    bottom: 0;
    width: min(86vw, 320px);
    max-width: 320px;
    flex: none;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 10px 12px calc(10px + var(--safe-bottom));
    box-sizing: border-box;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    border-right: 1px solid var(--line-2);
    border-bottom: 0;
    border-radius: 0 14px 14px 0;
    box-shadow: 18px 0 44px rgba(0, 0, 0, 0.28);
    z-index: 101;
    transform: translateX(-102%);
    transition: transform 0.22s cubic-bezier(0.32, 0.72, 0.28, 1);
    will-change: transform;
  }
  .app.sidebar-open .sidebar { transform: translateX(0); }

  /* 抽屉里的品牌与当前页：手机上隐藏顶部的 brand-txt 会重复，这里保留
     抽屉内的完整信息（抽屉是「我是谁 + 我在哪」的权威位置） */
  .brand { padding: 2px 4px 12px; gap: 9px; }
  .brand-logo { width: 32px; height: 32px; border-radius: 9px; font-size: 15px; }
  .brand-txt { display: block; }
  .side-current {
    display: block;
    margin: 0 0 8px;
    padding: 7px 10px;
  }
  .side-current > span { display: block; }
  .side-current b { font-size: 12.5px; }
  .side-current small { display: block; }

  /* 菜单项：44px 高（--nav-h 的 28px 在手机上点不中） */
  .nav {
    flex: 0 1 auto;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    padding: 0 0 4px;
    overflow-x: hidden;
    overflow-y: auto;
    min-height: 0;
  }
  .nav-item {
    flex: 0 0 auto;
    height: 44px;
    min-height: 44px;
    padding: 0 10px;
    font-size: 13.5px;
    gap: 10px;
    border-radius: 9px;
  }
  .nav-item > span:not(.nav-ic) {
    display: inline;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .nav-item .nav-ic,
  .nav-item .nav-ic svg { width: 17px; height: 17px; }
  .nav-item.active::before { content: none; }
  .nav-item:hover::after { content: none; }
  .nav-badge { position: static; margin-left: auto; padding: 1px 7px; }

  /* 侧栏工具区：整行铺开，主题、连接、通知铃都够点 */
  .side-tools {
    display: flex;
    flex: 0 0 auto;
    width: 100%;
    box-sizing: border-box;
    margin-top: 6px;
    padding-top: 8px;
    gap: 6px;
  }
  .side-tools .theme-switch { width: 100%; justify-content: space-between; }
  .side-tools .theme-dot { width: 30px; height: 30px; }
  .side-tools .conn,
  .side-tools .sv-pill { height: 30px; padding: 0 9px; font-size: 11px; }
  .side-tools .notify-bell { width: 34px; height: 34px; }
  /* 通知面板：抽屉本身带 transform，里面再用 position:fixed 会变成相对抽屉定位、
     而且被抽屉的 overflow 裁掉。改成「向上弹、横跨抽屉宽度」的下拉面板，
     不用管视口，也不会被裁。 */
  .side-tools { position: relative; }
  .side-tools .notify-panel {
    position: absolute;
    top: auto;
    right: 0;
    bottom: calc(100% + 8px);
    left: 0;
    width: auto;
    max-width: none;
    max-height: 52vh;
    box-shadow: 0 -8px 28px rgba(0, 0, 0, 0.18);
  }
  .side-tools .side-tool-wide { height: 34px; }

  .side-foot {
    display: block;
    flex: 0 0 auto;
    margin-top: 6px;
    padding-top: 8px;
    border-top: 1px solid var(--line);
  }
  .side-user { padding: 6px; gap: 9px; }
  .side-user > div:not(.avatar) { display: block; overflow: hidden; min-width: 0; }
  .side-user b,
  .side-user span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .side-user .avatar { width: 30px; height: 30px; }
  .side-user #logoutBtn,
  .side-user .btn-icon { width: 36px; height: 36px; }

  /* 遮罩：从顶栏下方开始，顶部栏始终可见可点 */
  .sidebar-scrim {
    display: block;
    position: fixed;
    top: calc(var(--mbar-h) + var(--safe-top));
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 99;
    border: 0;
    padding: 0;
    background: rgba(4, 9, 18, 0.55);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
  }
  .app.sidebar-open .sidebar-scrim { opacity: 1; pointer-events: auto; }

  /* -------------------------------------------------- 主内容区 */
  .main {
    width: 100%;
    flex: 1 1 auto;
    min-height: 0;
    height: auto;
    padding-top: calc(var(--mbar-h) + var(--safe-top));
    /* console.css 的窄屏段还留着 padding-bottom: calc(56px + 安全区)，
       那是「底部固定导航条」时代的占位。导航早就改成抽屉了，这条没删，
       于是每页底部都空出一条 56px 的带子——聊天页尤其明显：输入框离屏幕
       底边远了一截，看着像「显示不全」。内边距统一交给 .page 自己给。 */
    padding-bottom: 0;
    overflow: hidden;
  }
  .page {
    padding: 12px 12px calc(16px + var(--safe-bottom));
    -webkit-overflow-scrolling: touch;
  }
  /* 聊天页绝对不能自己滚（v1.39.0）：消息在 .chat-body 里滚，会话在
     .conv-list 里滚。外层如果还能滚，手指滑到边界就会「滚着滚着换了个
     容器」，加上键盘一弹高度变化，表现就是整页乱跳。这里锁成单层滚动。 */
  .page.page-chat {
    padding: 0;
    overflow: hidden;
  }
  .page.page-chat .chat-wrap {
    min-height: 0;
    overflow: hidden;
  }

  /* -------------------------------------------------- 通用防溢出
     中文后台最常见的溢出源：flex 子项默认 min-width:auto，
     长别名 / 长网址 / 时间戳会把整行顶宽。 */
  .toolbar,
  .card-head,
  .chat-head,
  .field-row,
  .dash-bar,
  .dash-bar-r,
  .monitor-bar { flex-wrap: wrap; min-width: 0; }
  .card,
  .card-head > *,
  .toolbar > *,
  .field,
  .field > *,
  .stat,
  .chat-head > * { min-width: 0; }

  /* 输入框与下拉：iOS 上 font-size < 16px 会触发自动放大，
     这里只把「会聚焦的」提到 16px，纯文本沿用 13px。 */
  input,
  textarea,
  select {
    max-width: 100%;
    min-width: 0;
    box-sizing: border-box;
  }
  input:not([type='checkbox']):not([type='radio']),
  select,
  textarea {
    font-size: 16px;
    line-height: 1.4;
  }
  .search input { width: 100%; min-width: 0; }
  .search { flex: 1 1 auto; min-width: 0; }

  /* 一行里塞两个 width:100% 的输入框（宽/高、起止时间这类），
     在 flex 行里会各占 100% 加间距，直接把卡片顶宽。改成等分。 */
  .field > div > input[type='number'],
  .field > div > input[type='text'],
  .field > div > input:not([type]) {
    width: auto;
    flex: 1 1 0;
    min-width: 0;
  }
  /* 取色器：桌面端 27px 高，手机上加到 40 并铺满一行 */
  input[type='color'] {
    width: 100%;
    height: 40px;
    padding: 3px;
    border-radius: 10px;
  }

  /* 触控尺寸兜底：页面内可点控件不低于 34px，
     原生复选框 13~15px 太小，放大到 18px 并让整行 label 都可点 */
  .page button,
  .page .btn,
  .page select,
  .modal button,
  .modal .btn,
  .modal select { min-height: 34px; }
  input[type='checkbox'],
  input[type='radio'] {
    width: 18px;
    height: 18px;
    flex: 0 0 auto;
    margin: 0;
  }
  /* label 里含复选框时，把整行抬到 40px 高，手指才点得准。
     不改 display：.cl-check / .sv-auto / 内联 flex 各有各的排版方式。 */
  label:not(.switch):has(> input[type='checkbox']),
  label:not(.switch):has(> input[type='radio']) {
    min-height: 40px;
    align-items: center;
    cursor: pointer;
  }

  /* 分段控件与筛选条：一排按钮放不下时自己横滑，不撑破卡片 */
  .toolbar .seg,
  .seg {
    max-width: 100%;
    overflow-x: auto;
    flex-wrap: nowrap;
    scrollbar-width: none;
  }
  .seg::-webkit-scrollbar { display: none; }
  .seg button { flex: 0 0 auto; white-space: nowrap; min-height: 32px; }

  /* -------------------------------------------------- 统计卡 */
  .stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .stat { padding: 13px 14px; }
  .stat-val { font-size: 23px; }
  .grid-2, .grid-2.eq, .grid-3, .grid-4 { grid-template-columns: 1fr; }

  /* -------------------------------------------------- 表格
     宽表在手机上只能横滑，但必须「滑得动且不顶宽」：
     滚动容器放在 .card 上，表体用 max-content 撑开。 */
  .page .card { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .table { width: max-content; min-width: 100%; }
  .table th,
  .table td { white-space: nowrap; padding: 10px 9px; }
  .table th { max-width: 180px; overflow: hidden; text-overflow: ellipsis; }
  .table td { max-width: 220px; overflow: hidden; text-overflow: ellipsis; }
  .table td .badge,
  .table td .row-actions { white-space: nowrap; }

  /* 监控条（v1.39.0）：商户端聊天页顶部那条「在线客服 N/M · 客服台 URL ·
     复制入口 · 打开客服台」，手机上折成三行、固定吃掉 81px，每看一条消息
     都要被它挤一次。这里收成一行，只留最常用的「在线数 + 去客服台」；
     URL 文本和复制按钮在手机上本来也用不上（要复制不如直接点开）。 */
  .page.page-chat .monitor-bar {
    flex-wrap: nowrap;
    min-height: 0;
    height: 34px;
    padding: 0 10px;
    gap: 8px;
    font-size: 11.5px;
    overflow: hidden;
  }
  .page.page-chat .monitor-bar code,
  .page.page-chat .monitor-bar #mbCopyAgent { display: none; }
  .page.page-chat .monitor-bar .mb-spacer { flex: 1 1 auto; }
  .page.page-chat .monitor-bar .btn {
    height: 26px !important;
    min-height: 26px;
    padding: 0 8px;
    font-size: 11px;
  }
  .page.page-chat .monitor-bar .mb-dot { flex: 0 0 auto; }

  /* -------------------------------------------------- 聊天页：列表 / 会话二选一 */
  .page.page-chat { flex-direction: column; }
  .chat-wrap {
    flex-direction: column;
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    height: 100%;
    /* 资料面板平时停在右侧屏外（translateX(102%)），
       不给这里加 overflow:hidden 会把整页顶宽 */
    overflow: hidden;
  }
  .chat-list {
    width: 100%;
    flex: 1 1 auto;
    min-width: 0;
    /* v1.39.0：flex 子项默认 min-height:auto，会被内容撑开。手机上会话
       一多，列表就长到一两千 px，被 .chat-wrap 的 overflow:hidden 裁掉，
       底部的会话既看不见也滚不到（看起来就是「列表显示不全」）。
       补上 min-height:0，滚动交给里面的 .conv-list。 */
    min-height: 0;
    overflow: hidden;
    border-right: 0;
    border-bottom: 0;
    max-height: none;
  }
  .chat-list-head { flex-wrap: wrap; gap: 8px; }
  .chat-main { display: none; flex: 1 1 auto; min-height: 0; width: 100%; }
  .chat-wrap.show-chat .chat-list { display: none; }
  .chat-wrap.show-chat .chat-main { display: flex; }
  .chat-back { display: inline-flex; width: 40px; height: 40px; }
  /* 会话头（v1.39.0）：原来是 nowrap + 固定 54px 高，可商户端的动作区最多
     有 8 个按钮加一个三段控件，375px 宽根本放不下——右侧整块被裁掉，
     按钮看得见摸不着。现在允许换行：第一行只留「返回 + 标题 + 访客信息」，
     动作区独占第二行横滑，一个都不少。 */
  .chat-head {
    height: auto;
    flex: 0 0 auto;
    min-height: 54px;
    flex-wrap: wrap;
    padding: 7px 12px;
    gap: 8px;
    align-content: center;
  }
  .chat-head h3 { font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .chat-head .sub { display: none; }
  .chat-head-txt { flex: 1 1 110px; }
  .chat-head #chatActions {
    order: 9;
    flex: 0 0 100%;
    width: 100%;
    min-width: 0;
    flex-wrap: nowrap;
    align-items: center;
    gap: 6px;
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: 1px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  .chat-head #chatActions::-webkit-scrollbar { display: none; }
  .chat-head #chatActions > * { flex: 0 0 auto; }
  /* 还没选会话时动作区是空的，别让它白占一行 */
  .chat-head #chatActions:empty { display: none; }
  /* 「监控模式」这类纯说明标记最占地方，标题副文案已经表达过 */
  .chat-head #chatActions .badge { display: none; }
  .chat-head #chatActions .btn {
    height: 32px !important;
    min-height: 32px;
    padding: 0 10px !important;
    font-size: 12px;
  }
  .chat-head #chatActions .as-staff { max-width: 100px; height: 32px; font-size: 12px; }
  .chat-head #chatActions .stage-seg { display: flex; flex: 0 0 auto; }
  .chat-head #chatActions .stage-seg button { height: 32px; padding: 0 9px; font-size: 12px; }

  /* 资料面板：桌面端是右侧 236px 一栏，手机上没地方放，原来干脆 display:none ——
     于是手机上看不到访客手机号 / IP / 来源，也改不了会话备注，功能等于少一半。
     这里改成「覆盖式第三屏」：由头部那颗 ⓘ 按钮拉开，盖住聊天区，
     头部保持可见，再点一次收回去。 */
  .chat-info-toggle { display: none; }
  .chat-wrap:has(.chat-info) .chat-info-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    padding: 0;
    border-radius: 10px;
    border: 1px solid var(--line-2);
    background: var(--panel);
    color: var(--text-2);
    cursor: pointer;
  }
  .chat-info-toggle svg { width: 17px; height: 17px; }
  .chat-wrap.show-info .chat-info-toggle {
    border-color: var(--accent);
    color: var(--accent);
    background: var(--accent-soft);
  }
  .chat-main { position: relative; }
  .chat-info {
    display: block;
    position: absolute;
    top: 54px;                 /* 让开 .chat-head，按钮始终可点 */
    right: 0;
    bottom: 0;
    left: 0;
    width: auto;
    flex: none;
    z-index: 6;
    padding: 12px;
    background: var(--panel);
    border-left: 0;
    border-top: 1px solid var(--line);
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    transform: translateX(102%);
    transition: transform 0.22s cubic-bezier(0.32, 0.72, 0.28, 1);
    will-change: transform;
  }
  .chat-wrap.show-info .chat-info { transform: translateX(0); }
  /* 资料面板（v1.39.0）：头部改成两行后高度不再固定，原来写死的 top:54px
     会让面板盖住第二行动作按钮。改成从 0 开始、用 padding 让出头部实测高度
     （--chat-head-h 由 common.js 的 ResizeObserver 写入），同时把头部抬到
     面板之上，那颗 ⓘ 按钮任何时候都点得到。 */
  .chat-head { position: relative; z-index: 8; }
  .chat-info {
    top: 0;
    padding-top: calc(var(--chat-head-h, 54px) + 12px);
  }

  /* 消息区：手机上唯一的滚动容器；contain 让内部增删不触发外层重排 */
  .chat-body {
    padding: 12px 12px 8px;
    min-height: 0;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    /* 发消息时内容变高，浏览器默认「锚定」当前位置不动；我们要贴底，
       所以关掉锚定，由 JS 显式滚到底 */
    overflow-anchor: none;
  }
  .chat-foot {
    flex: 0 0 auto;
    padding: 8px 10px calc(8px + var(--safe-bottom));
  }
  /* 键盘弹出时，底部已经由键盘占位，再留 34px 安全区就是一条白缝 */
  html.kb-open { --safe-bottom: 0px; }
  html.kb-open .chat-foot { padding-bottom: 8px; }
  /* 打字时收起话术条和「对方正在输入」：键盘吃掉半屏后，这两行会把消息区
     压到只剩几十像素——用户看到的就是「消息显示不全」 */
  html.kb-open .chat-foot .quick-bar,
  html.kb-open .chat-foot .typing { display: none; }
  /* 话术面板：手机上浮在整个输入区上方，而不是按桌面那个固定 66px */
  .chat-foot .quick-panel {
    top: auto;
    bottom: calc(100% + 4px);
    left: 8px;
    right: 8px;
    max-height: 46vh;
  }

  /* 输入行（v1.39.0）：桌面是「工具按钮 + 输入框 + 发送」一行排开，手机上
     放不下——商户端有图片 / 文件 / 收款码三个按钮，375px 宽时输入框被挤到
     只剩 50 多 px，打一个字换一行，等于没法用。
     现在把工具按钮收进 .chat-tools，换到第二行横滑；输入框独占第一行，
     和发送按钮并排。工具按钮不多的端（只有一个「文件」）也一致，不再特例。 */
  .chat-input-row {
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 8px;
  }
  .chat-input-row .chat-tools {
    order: 3;
    flex: 0 0 100%;
    width: 100%;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 6px;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .chat-input-row .chat-tools::-webkit-scrollbar { display: none; }
  .chat-input-row .chat-tools > * { flex: 0 0 auto; }
  .chat-input-row .chat-tools .btn {
    height: 34px !important;
    min-height: 34px;
    padding: 0 12px !important;
    font-size: 12.5px;
  }
  .chat-input-row .chat-tools > .btn-icon {
    width: 34px;
    padding: 0 !important;
  }
  .chat-input-row textarea {
    order: 1;
    flex: 1 1 0;
    min-width: 0;
    min-height: 40px;
    max-height: 96px;
    font-size: 16px;              /* < 16px 会触发 iOS 聚焦自动放大 */
    line-height: 1.45;
    padding: 8px 11px;
  }
  .chat-input-row .btn-primary {
    order: 2;
    flex: 0 0 auto;
    height: 40px !important;
    min-height: 40px;
    padding: 0 14px !important;
  }
  /* 没被 .chat-tools 包住的老结构：让它的按钮跟在发送键后面，别掉到下一行 */
  .chat-input-row > .btn:not(.btn-primary):not(.btn-icon) { order: 2; }
  .msg { max-width: 85%; }
  .conv-last { overflow: hidden; text-overflow: ellipsis; }

  /* -------------------------------------------------- 弹窗：底部抽屉式 */
  .modal-mask { align-items: flex-end; padding: 0; }
  .modal {
    max-width: none;
    width: 100%;
    box-sizing: border-box;
    border-radius: 18px 18px 0 0;
    max-height: 90vh;
    max-height: 90dvh;
    /* 键盘弹出时 dvh 不会缩，弹窗底部会被盖住；按可视视口再校一次 */
    max-height: min(90dvh, calc(var(--vvh, 100dvh) - 16px));
    padding: 18px 16px calc(16px + var(--safe-bottom));
    animation: mSheetUp 0.22s cubic-bezier(0.2, 0.9, 0.3, 1.05);
  }
  .modal-foot {
    position: sticky;
    bottom: 0;
    background: var(--panel);
    padding-top: 10px;
    margin-top: 12px;
    gap: 8px;
    flex-wrap: wrap;
  }
  .modal-foot .btn { flex: 1 1 auto; min-height: 40px; }
  @keyframes mSheetUp {
    from { transform: translateY(24px); opacity: 0.4; }
  }

  /* 提示条改贴底，避免顶栏遮挡 */
  .toast-wrap {
    top: auto;
    bottom: calc(12px + var(--safe-bottom));
    left: 10px;
    right: 10px;
    align-items: stretch;
  }
  .toast { max-width: none; }

  /* 按钮统一抬到 40px，方便点 */
  .btn { min-height: 40px; }
  .btn-sm { min-height: 34px; }
  .btn-icon { width: 40px; padding: 0; }

  /* 登录页：手机上移除左右分栏的装饰图，只留表单 */
  .auth-screen {
    grid-template-columns: 1fr;
    /* 键盘弹出时表单要跟着缩，否则密码框和小键盘之间隔着一屏 */
    height: var(--vvh, 100dvh);
  }
  /* 登录 / 注册的主按钮是整屏最重要的一个可点区域，给到 46px */
  .auth-form button[type='submit'],
  .auth-form .btn-primary { min-height: 46px; font-size: 14.5px; }
  .auth-form .field { margin-bottom: 12px; }
  /* 密码框右侧的「显示」眼睛按钮，别缩成 20px */
  .auth-form .pw-eye { width: 42px; min-height: 40px; }
}

/* =========================================================== 超窄屏（320~380） */
@media (max-width: 380px) {
  .mbar { padding-right: 8px; }
  .mbar-title b { font-size: 14px; }
  .page { padding: 10px 10px calc(14px + var(--safe-bottom)); }
  .stat-grid { grid-template-columns: 1fr; }
  .btn { min-height: 38px; padding: 0 11px; }
  .nav-item { font-size: 13px; }
}

/* =========================================================== 平板横屏（861~1180） */
@media (min-width: 861px) and (max-width: 1180px) {
  /* 桌面端中屏：侧栏已经收窄，这里只保证抽屉相关元素不出现 */
  .mbar,
  .sidebar-trigger,
  .sidebar-scrim { display: none; }
}

/* 宽屏下这些移动端结构必须彻底消失，否则会挡住内容 */
@media (min-width: 861px) {
  .mbar { display: none; }
}

/* 尊重系统的「减少动效」偏好 */
@media (prefers-reduced-motion: reduce) {
  .sidebar,
  .sidebar-scrim,
  .sidebar-trigger-icon,
  .sidebar-trigger-icon::before,
  .sidebar-trigger-icon::after { transition: none !important; }
  .modal { animation: none !important; }
}
