.login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 24px;
  box-sizing: border-box;
  background:
    radial-gradient(circle at 50% 45%, #fff 0%, rgba(255, 255, 255, 0) 48%),
    linear-gradient(120deg, #e6e6e6 0%, #f5f5f5 48%, #e7e7e7 100%);
}

.login-shell {
  width: min(1000px, 100%);
  min-height: 570px;
  display: grid;
  grid-template-columns: 43.5% 56.5%;
  overflow: hidden;
  border-radius: 10px;
  background: #fff;
  box-shadow: 0 22px 60px rgba(0, 0, 0, 0.14);
}

.login-visual {
  min-height: 570px;
  overflow: hidden;
  background: #26363d;
}

.login-visual img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

.login-form-pane {
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 56px 64px;
  box-sizing: border-box;
}

.login-form-wrap {
  width: min(390px, 100%);
}

.login-title {
  margin-bottom: 8px;
  color: #111;
  font-size: 42px;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  letter-spacing: 10px;
  padding-left: 10px;
  font-family: "Microsoft YaHei", "PingFang SC", sans-serif;
}

.login-brand {
  height: 24px;
  margin-bottom: 34px;
  overflow: hidden;
  color: #a6a6a6;
  font-size: 12px;
  line-height: 24px;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.login-alert {
  margin-bottom: 18px;
}

.login-form .ant-form-item {
  margin-bottom: 22px;
}

.login-form .ant-input-affix-wrapper {
  min-height: 48px;
  padding-inline: 16px;
  border-color: #dedede;
  border-radius: 3px;
  box-shadow: none;
}

.login-form .ant-input-affix-wrapper:hover,
.login-form .ant-input-affix-wrapper-focused {
  border-color: #2196f3;
  box-shadow: 0 0 0 2px rgba(33, 150, 243, 0.08);
}

.login-form .ant-input-prefix {
  margin-inline-end: 12px;
  color: #9d9d9d;
  font-size: 18px;
}

.login-captcha-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 124px;
  gap: 12px;
  align-items: start;
}

.login-captcha-input {
  margin-bottom: 0 !important;
}

.login-captcha-image {
  width: 124px;
  height: 48px;
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: 3px;
  background: #202020;
  color: #fff;
  cursor: pointer;
}

.login-captcha-image img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

.login-captcha-help {
  min-height: 34px;
  margin-top: 6px;
  font-size: 12px;
}

.login-form .ant-form-item:has(.ant-checkbox-wrapper) {
  margin-top: 4px;
  margin-bottom: 14px;
}

.login-submit {
  height: 48px;
  border-radius: 3px;
  background: #2196f3;
  font-size: 18px;
  letter-spacing: 4px;
  box-shadow: none;
}

.login-submit:hover {
  background: #1688df !important;
}

@media (max-width: 820px) {
  .login-page {
    padding: 20px;
  }

  .login-shell {
    grid-template-columns: 1fr;
    min-height: 0;
  }

  .login-visual {
    min-height: 180px;
    max-height: 220px;
  }

  .login-form-pane {
    padding: 36px 24px 40px;
  }

  .login-title {
    font-size: 34px;
  }
}
html,
body,
#root {
  height: 100%;
  margin: 0;
  padding: 0;
}

body {
  font-family:
    -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB',
    'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 14px;
  background: #f5f7fa;
}

/*
 * 2026-10-22 对标站尺寸基线：
 *   · 管理页正文 14px，按钮 32px 高 / 4px 圆角，图标 16px；
 *   · 表头约 55px（16px 上下内边距），数据行随两行内容约 77px；
 *   · 工作台内部由 Workbench 根容器单独使用 13px 正文。
 */
.ant-btn {
  font-size: 14px;
}

.ant-btn-sm {
  height: 32px;
  padding-inline: 15px;
  border-radius: 4px;
  font-size: 14px;
}

.ant-btn-sm.ant-btn-icon-only {
  width: 32px;
  padding-inline: 0;
}

.ant-btn .anticon,
.ant-menu .anticon {
  font-size: 16px;
}

.ant-btn .wt-inline-icon {
  width: 16px;
  height: 16px;
}

.ant-table-wrapper .ant-table {
  font-size: 14px;
}

.ant-table-wrapper .ant-table-container {
  border-radius: 4px;
}

.ant-table-wrapper .ant-table-thead > tr > th {
  padding: 16px 12px !important;
  border-radius: 0;
  background: #f9fafd;
  font-size: 14px;
  font-weight: 400;
}

.ant-table-wrapper .ant-table-thead > tr > th:first-child {
  border-start-start-radius: 4px;
}

.ant-table-wrapper .ant-table-thead > tr > th:last-child {
  border-start-end-radius: 4px;
}

.ant-table-wrapper .ant-table-tbody > tr > td {
  padding: 16px 12px !important;
  font-size: 14px;
}

/* 表格里的长文本不要撑破布局 */
.wt-ellipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/*
 * 快捷回复 · 左栏「分组」树的行
 *
 * 【用户 2026-10-01】"顺便整理下这个分组组名的间隔，不美观"。
 * 原来一行是 Space + 内联 marginLeft 拼出来的：组名、部门/个人/小组标签、话术条数、
 * 编辑/删除两个按钮全靠内容自己撑，于是
 *   · 组名一长就把标签顶得贴上去，标签和组名之间只剩 6px 不到的视觉空隙；
 *   · 条数与按钮之间是 size={0}，两个图标按钮彼此也挨着；
 *   · 不同行（有没有标签、有没有按钮）的"名字到右边"的距离还不一样。
 * 统一成 flex：名字占满剩余宽度并省略号收尾，右侧「条数 + 按钮」不缩、间距固定。
 */
.wt-qr-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-width: 0;
}

.wt-qr-row-name {
  /* flex:1 + min-width:0 才能让里面的长组名真正省略号收尾（否则 flex 不肯缩） */
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 6px;
}

/* 标签自己不缩、且去掉 antd 默认的 margin-inline-end（间距交给上面的 gap） */
.wt-qr-row-name .ant-tag {
  flex: 0 0 auto;
  margin-inline-end: 0;
}

.wt-qr-row-side {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 4px;
}

/* 条数占固定宽度，数字从 1 位变 3 位时按钮不会跟着左右跳 */
.wt-qr-row-count {
  min-width: 18px;
  text-align: right;
}

/* 行高与左右内边距给足，悬停高亮才是完整一条 */
.wt-qr-tree .ant-tree-title {
  display: block;
  width: 100%;
}

/*
 * 行高与行间距（用户 2026-10-02："快捷回复 分组的间隔拉高一点，每个分组名称
 * 高度加高下，不要那么紧凑"）
 *
 * 原来只给了左右内边距，行高完全由 antd 的 24px 行盒决定 —— 组名、条数、
 * 两个按钮挤在 24px 里，密集列表看着很紧。这里把**上下内边距**给到 5px
 * （一行约 34px）、行与行之间再留 4px，并给整行一个圆角，
 * 悬停/选中的高亮跟着变成一个完整的"块"而不是一条线。
 */
.wt-qr-tree .ant-tree-node-content-wrapper {
  padding: 5px 8px;
  border-radius: 6px;
}

.wt-qr-tree .ant-tree-treenode {
  padding-bottom: 4px;
  width: 100%;
}

/*
 * 快捷回复 / 基础素材 / 雷达素材：统一左栏分组标题的头部高度与行间距。
 *
 * 2026-10-22 用户要求三处“分组标题的高度间隙拉大，做统一”。页签仍各自保留，
 * 但卡片头、分组行高、行间空隙使用同一组尺寸，切换页面时视觉节奏一致。
 */
.wt-group-panel .ant-card-head {
  min-height: 50px;
  padding-inline: 12px;
}

.wt-group-panel .ant-card-head-title {
  padding: 14px 0;
  font-size: 14px;
  font-weight: 600;
  line-height: 22px;
}

.wt-group-panel .ant-card-body {
  padding: 10px !important;
}

.wt-group-panel .ant-tree-node-content-wrapper {
  display: flex;
  align-items: center;
  min-height: 40px;
  padding: 9px 10px;
}

.wt-group-panel .ant-tree-treenode {
  padding-bottom: 6px;
}

.wt-group-item {
  min-height: 40px;
  margin-bottom: 6px;
  padding: 9px 10px !important;
}

.wt-group-item:last-child {
  margin-bottom: 0;
}

/* 发布朋友圈的图片/视频选择预览统一为 90×90。 */
.moments-image-upload-90 .ant-upload-list-item-container,
.moments-image-upload-90 .ant-upload-select {
  width: 90px !important;
  height: 90px !important;
}

.moments-image-upload-90 .ant-upload-list-item {
  padding: 0 !important;
}

/* 行内那两个 link 按钮默认左右 padding 偏大、挤在一起时不好点 */
.wt-qr-tree .ant-tree-node-content-wrapper .ant-btn-sm {
  padding-inline: 4px;
}

/*
 * 分组拖动排序（用户 2026-10-01："快捷回复，分组可以上下拖动排序"）
 *
 * 【为什么只有这些样式】拖拽本身是原生 HTML5 事件（见 QuickReply.tsx 的行内注释），
 * CSS 只负责两件事：① 让"这行能拖"看得出来（握把 + grab 光标）；
 * ② 告诉用户会插到哪儿（目标行上沿/下沿一条蓝线）。
 * 不可拖的行也放一个等宽占位，否则同屏两种左边距。
 */
.wt-qr-grip,
.wt-qr-grip-spacer,
.wt-mat-grip,
.wt-mat-grip-spacer {
  flex: 0 0 auto;
  width: 12px;
  font-size: 12px;
  line-height: 1;
}

.wt-qr-grip,
.wt-mat-grip {
  color: #bfbfbf;
}

.wt-qr-draggable,
.wt-mat-draggable {
  cursor: grab;
}

.wt-qr-draggable:active,
.wt-mat-draggable:active {
  cursor: grabbing;
}

.wt-qr-draggable:hover .wt-qr-grip,
.wt-mat-draggable:hover .wt-mat-grip {
  color: #8c8c8c;
}

.wt-qr-row.is-dragging,
.wt-mat-row.is-dragging {
  opacity: 0.45;
}

.wt-qr-row.drop-before,
.wt-mat-row.drop-before {
  box-shadow: inset 0 2px 0 0 #1677ff;
}

.wt-qr-row.drop-after,
.wt-mat-row.drop-after {
  box-shadow: inset 0 -2px 0 0 #1677ff;
}

/*
 * 左侧菜单：文字超长时省略，不折行
 *
 * 【为什么需要】用户 2026-09-26 要求侧栏窄一点（220 → 188）。
 * antd 的菜单项默认会折行，一条四五行字的菜单名被折成两行之后，
 * 整个菜单的高度节奏就乱了（而且"会话工作台"这种名字折行看起来像两个菜单）。
 * 省略号 + antd 自带的 title 提示是可预期的降级。
 */
.wt-sider-menu .ant-menu-title-content {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/*
 * 浅蓝底侧栏（用户 2026-10-06 最终版）：当前页 = 蓝药丸 + 白字
 *
 * 【为什么在 CSS 里补这一层】药丸是实心主色 #1677ff、底色是 10%~17% 的淡蓝，
 * 本体对比已经够；这里补一层**主色同色**的淡投影（而不是灰/黑投影），
 * 让药丸像"浮"在底色上，且投影色相与整套蓝一致，不会发脏。
 *
 * 【为什么只给"叶子项"】antd 的 dark 主题里，"子菜单标题"在其下有选中项时
 * 会跟叶子项共用一部分选中样式；那会让「会话」这种分组标题也变成药丸，
 * 一屏出现两个"当前项"。这里用 :not(:hover) 只压常态背景，
 * 悬停态仍归 antd 的 darkItemHoverBg 管，免得把 hover 反馈一起压掉。
 */
.wt-sider-menu .ant-menu-item-selected {
  box-shadow: 0 2px 8px rgba(22, 119, 255, 0.32);
  font-weight: 400;
}

.wt-sider-menu .ant-menu-submenu-selected > .ant-menu-submenu-title:not(:hover) {
  background-color: transparent;
}

/*
 * 列表行里的"悬停才出现"动作（用户 2026-09-26：接待卡片的结束 × 要悬停显示）
 *
 * 【为什么用 CSS 而不是 JS 的 hover 状态】行组件（SessionRow）自己有一个 hover
 * state，但那个 state 是给"置顶/星标"用的；接线到它上面会让每个用到这一行的列表
 * 都要多传一个 prop。这里用纯 CSS：默认透明，`.ant-list-item:hover` 时淡入 ——
 * 鼠标一定在行内才会显示，也不会影响其它列表（只有带这个 class 的元素受影响）。
 */
.wt-row-action {
  opacity: 0;
  transition: opacity 0.15s;
}
.ant-list-item:hover .wt-row-action,
.wt-row-action:focus-visible {
  opacity: 1;
}

/*
 * 列表行的悬停背景（用户 2026-09-26："接待/会话列表通讯录，排队，已接待好友，
 * 视图，好友卡片都加个悬停背景色，比确定背景色颜色浅一点"）
 *
 * 【为什么是这个颜色】"确定背景色"= 选中态，用的是 `rgba(22,119,255,0.08)`
 * （见 Workbench 的 SessionRow / CustomViewPanel 里的 active 背景）。
 * 悬停用**同一个色相的一半浓度** `rgba(22,119,255,0.04)`：
 *   · 色相相同 → "划过"与"选中"是同一种语言的两档深浅，不会让人以为是两种状态；
 *   · 只有一半 → 选中态永远比悬停更重，不会出现"分不清哪个是当前会话"。
 * 用灰色（#f5f5f5）也能看出悬停，但会把整栏的色温往灰里带，与选中态的淡蓝打架。
 *
 * 【为什么用 CSS 类而不是 React 的 hover 状态】会话列表几百行，
 * 每行 `onMouseEnter` 记一个 state 就是几百次重渲染；而它纯粹是视觉反馈。
 * 行内已有的 hover state 只服务"按钮显隐"，不再兼管背景。
 *
 * 【为什么 !important】antd List.Item 自己有 hover 样式（`hoverable` 时），
 * 而我们的行是内联 style 提供选中态 —— 悬停规则要能盖住 antd 的那一份默认值。
 * 只影响 background 这一个属性。
 */
.wt-row-hover:hover {
  background-color: rgba(22, 119, 255, 0.04) !important;
}

/*
 * 选中态使用 antd 菜单选中色 #e6f4ff，和悬停的 4% 淡蓝明确分层。
 * hover 时仍保持更深一档，避免鼠标划过时看起来像"取消选中"。
 */
.wt-row-hover.wt-row-active {
  background-color: #e6f4ff !important;
}
.wt-row-hover.wt-row-active:hover {
  background-color: #d8eaff !important;
}

/* 可见视图的管理入口：默认不占视觉注意力，悬停/键盘聚焦时才显示竖向三点。 */
.wt-view-actions {
  display: inline-flex;
  align-items: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}
.wt-row-hover:hover .wt-view-actions,
.wt-view-actions:focus-within {
  opacity: 1;
  pointer-events: auto;
}

/*
 * 会话工作台发送工具栏
 *
 * 2026-10-18 用户："将会话工作台发布表情按钮跟后面其他按钮统一高度"。
 * antd 的 text / icon-only 小按钮默认高度不总是完全一致（外层 Popover/Tooltip
 * 还会影响行盒），所以在这一排统一钉成 28px；图标按钮同时固定宽度，
 * 避免新增名片按钮后出现一高一低。
 */
.wt-send-tools .ant-btn {
  height: 28px;
  display: inline-flex;
  align-items: center;
}

.wt-send-tools .ant-btn.ant-btn-icon-only {
  width: 28px;
  min-width: 28px;
  padding-inline: 0;
}

/* 只读/说明性质的代码块 */
.wt-note {
  background: #f6f8fa;
  border-left: 3px solid #1677ff;
  padding: 8px 12px;
  border-radius: 4px;
  color: #595959;
  font-size: 13px;
  line-height: 1.7;
}

.wt-mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
}

/*
 * 聊天侧边栏「图文内容」页签的渲染容器
 *
 * 【为什么必须有一个类】这段 HTML 是运维自己写的，会带 p / ul / img / table 等标签。
 * 不加基础排版的话：行高继承到 13px 等宽字体、图片会按原始尺寸撑破面板宽度、
 * 表格没有边框 —— 看起来像"内容坏了"，实际只是没给样式。
 *
 * 【为什么用类而不是内联样式】工作台的右侧面板与配置页的预览弹窗都要渲染它，
 * 两处的排版必须一致（否则"预览"就失去了意义）。这里是唯一的定义点。
 *
 * 【为什么不做成深色适配】本项目只用 antd 默认亮色主题（见 main.tsx 的 ConfigProvider，
 * 没有 darkAlgorithm）。运维写进来的 HTML 也不会自带深色样式，硬做一套反而更花。
 */
.wt-app-page {
  padding: 12px;
  background: #fff;
  border-radius: 6px;
  font-size: 13px;
  line-height: 1.75;
  color: rgba(0, 0, 0, 0.85);
  word-break: break-word;
  overflow-wrap: anywhere;
}
.wt-app-page p {
  margin: 0 0 8px;
}
.wt-app-page ul,
.wt-app-page ol {
  margin: 0 0 8px;
  padding-left: 20px;
}
.wt-app-page h1,
.wt-app-page h2,
.wt-app-page h3,
.wt-app-page h4 {
  margin: 0 0 8px;
  font-size: 15px;
  font-weight: 600;
}
.wt-app-page img {
  max-width: 100%;
  height: auto;
}
.wt-app-page a {
  color: #1677ff;
}
.wt-app-page table {
  width: 100%;
  border-collapse: collapse;
}
.wt-app-page th,
.wt-app-page td {
  border: 1px solid #f0f0f0;
  padding: 4px 8px;
  text-align: left;
}

/*
 * 聊天侧边栏的高度链
 *
 * 【为什么需要这几条】面板要和左侧的消息区**等高**（否则右边会比左边短一截，
 * 或者内部滚动条出现在奇怪的位置）。做法是：面板 flex 纵向撑满 Card body，
 * Tabs 占满剩余空间，页签内容区自己滚。
 *
 * 但 antd 的 Tabs 内部有 4 层容器（`.ant-tabs` → `.ant-tabs-content-holder`
 * → `.ant-tabs-content` → `.ant-tabs-tabpane`），其中只有前两层带 `flex: auto`，
 * 后两层是普通块级元素 —— `height: 100%` 到它们那里就断了。
 * 所以在这里把链补上。**这是依赖 antd 内部类名的**，升级 antd 时要复查
 * （判据：面板里的列表滚动条是不是出现在面板内部，而不是撑高整页）。
 */
.wt-side-panel .ant-tabs {
  height: 100%;
}
.wt-side-panel .ant-tabs-content-holder {
  min-height: 0;
}
.wt-side-panel .ant-tabs-content,
.wt-side-panel .ant-tabs-tabpane {
  height: 100%;
}

/*
 * 会话工作台右侧主导航（快捷回复 / 客户资料 / 群管理）：
 * 字号比 AntD small tabs 大一档，页签行高度与聊天标题栏、左侧三按钮栏一致。
 */
.wt-side-panel .wt-main-tabs > .ant-tabs-nav {
  min-height: 52px;
  align-items: flex-end;
}
.wt-side-panel .wt-main-tabs > .ant-tabs-nav::before {
  display: block !important;
  border-bottom: 1px dashed #d9d9d9 !important;
}
.wt-side-panel .wt-main-tabs > .ant-tabs-nav .ant-tabs-tab {
  height: 46px;
  margin: 6px 10px 0 0 !important;
  padding: 0 !important;
  align-items: center;
  font-size: 15px !important;
  background: #fff;
  border: 0;
  /*
   * 白色 tab 自身会盖住 nav::before 的底线；这里让未选中项自己绘制同一段虚线。
   * active 项用蓝底边覆盖，避免蓝块下面再露出一条灰线。
   */
  border-bottom: 1px dashed #d9d9d9 !important;
  box-sizing: border-box;
  border-radius: 0;
  transition: background-color .16s ease, border-color .16s ease, color .16s ease;
}
.wt-side-panel .wt-main-tabs > .ant-tabs-nav .ant-tabs-tab:hover {
  background: #e6f4ff;
}
.wt-side-panel .wt-main-tabs > .ant-tabs-nav .ant-tabs-tab-active {
  background: #1677ff;
  border-bottom-color: #1677ff !important;
}
.wt-side-panel .wt-main-tabs > .ant-tabs-nav .ant-tabs-tab-active:hover {
  background: #4096ff;
}
.wt-side-panel .wt-main-tabs > .ant-tabs-nav .ant-tabs-tab-btn {
  padding: 0 14px;
  font-size: 15px;
  line-height: 22px;
  color: #1677ff !important;
}
.wt-side-panel .wt-main-tabs > .ant-tabs-nav .ant-tabs-tab-btn a {
  color: #1677ff !important;
}
.wt-side-panel .wt-main-tabs > .ant-tabs-nav .ant-tabs-tab-active .ant-tabs-tab-btn,
.wt-side-panel .wt-main-tabs > .ant-tabs-nav .ant-tabs-tab-active .ant-tabs-tab-btn a {
  color: #fff !important;
}
.wt-side-panel .wt-main-tabs > .ant-tabs-nav .ant-tabs-ink-bar {
  display: none !important;
}

/*
 * 会话工作台：三栏等高（底部对齐）
 *
 * 【为什么要这一条】改造前三栏各写各的高度（账号列 780 / 会话列表 620 /
 * 消息流 520），底部参差不齐，而且改一栏的数值永远不会想到去同步另外两栏。
 * 现在由一个常量（`WORKBENCH_H`）给出总高，三栏都用 flex 撑满 ——
 * 底部自然对齐，也不会再出现"改一处、歪三处"。
 *
 * 【为什么 Card 需要一条自己的规则】antd 的 `.ant-card` 是普通块级元素，
 * `.ant-card-body` 不会自动占满头部以下的空间 —— 不给 `flex: 1` 的话
 * 卡片高度还是由内容决定，撑不到 WORKBENCH_H。
 * **这是依赖 antd 内部类名的**（与上面 `.wt-side-panel` 那段同类），
 * 升级 antd 时要复查（判据：会话列表 / 消息流的底部是否还与账号列齐平）。
 */
.wt-fill-card {
  height: 100%;
  display: flex;
  flex-direction: column;
}
.wt-fill-card > .ant-card-body {
  flex: 1;
  min-height: 0;
}

/*
 * 会话工作台文字气泡的小尾巴。
 *
 * 昵称和时间已移到第一行，第二行是头像 + 气泡；尾巴必须朝头像一侧，
 * 让视觉上能明确连到发送者。只给纯文字/撤回消息加尾巴，图片、文件、
 * 语音和卡片继续使用各自的媒体容器，避免在缩略图外面再长出一个尖角。
 */
.wt-chat-bubble {
  position: relative;
}

.wt-chat-bubble::after {
  content: '';
  position: absolute;
  top: 10px;
  width: 0;
  height: 0;
  border-top: 7px solid transparent;
  border-bottom: 7px solid transparent;
  pointer-events: none;
}

.wt-chat-bubble--in::after {
  left: -7px;
  border-right: 7px solid #fff;
  filter: drop-shadow(-1px 0 0 #f0f0f0);
}

.wt-chat-bubble--out::after {
  right: -7px;
  border-left: 7px solid #1677ff;
}

.wt-chat-bubble--recalled::after {
  border-top-color: transparent;
  border-bottom-color: transparent;
  filter: none;
}

.wt-chat-bubble--in.wt-chat-bubble--recalled::after {
  border-right-color: #fafafa;
}

.wt-chat-bubble--out.wt-chat-bubble--recalled::after {
  border-left-color: #fafafa;
}

/*
 * 消息气泡上的「更多操作」（转发 / 多条转发 / 撤回）
 *
 * 【为什么要用 CSS 而不是 React 状态控制显隐】用 `onMouseEnter` 记一个
 * `hoveredId` 的话，鼠标在几百条消息里划一遍就会触发几百次 setState，
 * 整个消息列表跟着重渲染。悬停只是一个视觉状态，交给 CSS 是零成本的。
 *
 * 【为什么隐藏时是 pointer-events: none 而不是只调透明度】透明度 0 的元素
 * 仍然可以点到 —— 用户"随便在消息旁边点一下"就会误触出一个下拉菜单。
 *
 * 【selecting 时为什么常显】多选模式下这个位置放的是复选框（见 MessageBubble），
 * 它必须一直看得见，否则用户不知道该怎么勾。
 */
.wt-bubble .wt-msg-actions {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
  /*
   * 【2026-09-26 第二轮：操作区搬进"内容行"里了，这里不再需要任何 margin 微调】
   *
   * 第一版是"行的兄弟节点 + margin-top: 20px 手工对齐气泡顶部"，结果用户看到的是
   * "…对齐到上面那行微信昵称后面"。根因见 MessageBubble 里那段注释：
   * 靠 margin 猜位置，永远会在"气泡只有一行/多行/有撤回脚注"时错位。
   * 现在它和气泡在同一个 flex 行（alignItems: center），位置由布局保证。
   *
   * 只留一点点内边距把省略号按钮的点击区收紧到图标附近（antd 给 text 按钮
   * 默认留了约 7px 左右 padding，视觉上会让"…"离内容远一截）。
   */
  flex: 0 0 auto;
}
.wt-bubble .wt-msg-actions .ant-btn {
  padding-inline: 3px;
}
.wt-bubble:hover .wt-msg-actions,
.wt-bubble .wt-msg-actions:focus-within,
.wt-bubble.wt-selecting .wt-msg-actions,
.wt-bubble .wt-msg-actions.wt-actions-open {
  opacity: 1;
  pointer-events: auto;
}

/*
 * 群聊里的发送者昵称 —— **悬停它就能出动作菜单**
 *
 * 【用户 2026-09-26 第 3 条】"昵称后面 ... 的功能 改成悬停在昵称上面就显示，去掉 ..."。
 * 省略号已经删掉了，菜单改挂在昵称本身（见 MessageBubble 的 senderActionsRender）。
 *
 * 【为什么要给一个悬停反馈】没有任何图标提示的话，用户不会知道这个名字可以悬停。
 * 给一点下划线 + 手型光标，成本几乎为零，却把"这里能点"说清楚了。
 */
.wt-sender-name {
  cursor: pointer;
}
.wt-sender-name:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}

/*
 * 素材库列表项（图片缩略图上的「发送」遮罩 / 行内动作）
 *
 * 【为什么遮罩层 pointer-events: none，只有按钮 auto】素材缩略图本身
 * 是"点开看大图"的入口（antd Image）。如果整块遮罩吃掉了点击，
 * 用户在列表里就再也没法放大确认"这张到底是不是我要发的那张" ——
 * 而发错图是真实的客诉。所以：遮罩只负责视觉，点击穿透到图片；
 * 只有"发送"按钮自己接收点击。
 *
 * 【为什么用 CSS 而不是 hoveredId 状态】与 .wt-msg-actions 同理：
 * 列表可能有上百条素材，鼠标划一遍就是上百次 setState。
 */
.wt-mat-thumb {
  position: relative;
  width: 96px;
  height: 96px;
}
.wt-mat-mask {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.38);
  /* 见上：点击穿透到下面的缩略图 */
  pointer-events: none;
}
.wt-mat-thumb:hover .wt-mat-mask {
  display: flex;
}
.wt-mat-mask .ant-btn {
  pointer-events: auto;
}

/* 非图片素材：默认干净，悬停才露出动作按钮 */
.wt-mat-row .wt-mat-act {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}
.wt-mat-row:hover .wt-mat-act,
.wt-mat-row .wt-mat-act:focus-within {
  opacity: 1;
  pointer-events: auto;
}

/*
 * 会话工作台 › 素材库（2026-10-22 按六张对标截图重排）
 *
 * 顶部范围三档 + 横向类型页签；图片/文件走三列网格，其余类型走纵向卡片。
 * 所有编辑动作默认隐藏，卡片悬停或选中后才出现，避免侧栏被一排按钮挤满。
 */
.wt-material-scope-row {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  padding: 8px 8px 6px;
}

.wt-material-kinds .ant-tabs-nav {
  margin: 0;
}

.wt-material-kinds .ant-tabs-nav::before {
  border-bottom-color: #f0f0f0;
}

.wt-material-kinds .ant-tabs-tab {
  padding: 8px 0;
  font-size: 13px;
}

.wt-material-kinds .ant-tabs-tab + .ant-tabs-tab {
  margin-left: 14px;
}

.wt-material-kinds .ant-tabs-nav-operations {
  width: 20px;
  min-width: 20px;
  align-self: center;
  margin-left: 2px;
}

.wt-material-kinds .ant-tabs-nav-operations .ant-tabs-nav-more {
  width: 20px !important;
  min-width: 20px !important;
  height: 24px !important;
  padding: 0 !important;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.wt-material-kinds .ant-tabs-nav-operations .ant-tabs-nav-more::after {
  display: none;
}

.wt-material-search-row {
  padding: 8px 10px 4px;
}

.wt-material-search-row .ant-input-affix-wrapper {
  min-height: 30px;
}

.wt-material-quick-row {
  display: flex;
  align-items: center;
  gap: 2px;
  min-height: 28px;
  padding: 0 10px 4px;
  color: #595959;
  font-size: 13px;
}

.wt-material-quick-label {
  margin-right: 4px;
}

.wt-material-quick-row .ant-btn-sm {
  width: 24px;
  min-width: 24px;
  height: 24px;
  color: #8c8c8c;
}

.wt-material-scroll {
  flex: 1;
  min-height: 0;
  min-width: 0;
  overflow-x: hidden;
  overflow-y: auto;
  padding: 6px 10px 10px;
}

.wt-material-scroll > .ant-alert {
  margin-bottom: 8px;
}

.wt-material-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px 8px;
  min-width: 0;
}

.wt-material-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.wt-material-card {
  position: relative;
  min-width: 0;
}

.wt-material-card.is-selected .wt-material-list-card,
.wt-material-list-card.is-selected {
  border-color: #91caff;
  background: #e6f4ff;
}

.wt-material-image-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  border-radius: 6px;
}

.wt-material-image-card.is-selected {
  background: #e6f4ff;
}

.wt-material-image-frame {
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  max-width: 100%;
}

.wt-material-image-frame .ant-image,
.wt-material-image-frame .ant-image-img,
.wt-material-image-frame .wt-media-thumb {
  width: 100% !important;
  height: 100% !important;
}

.wt-material-image-title {
  width: 100%;
  margin-top: 5px;
  color: #595959;
  font-size: 12px;
  line-height: 18px;
}

.wt-material-select {
  position: absolute;
  z-index: 4;
  top: 4px;
  left: 4px;
  padding: 1px 3px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.92);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}

.wt-material-card:hover .wt-material-select,
.wt-material-card.is-selected .wt-material-select,
.wt-material-select:focus-within {
  opacity: 1;
  pointer-events: auto;
}

.wt-material-card-actions {
  position: absolute;
  z-index: 3;
  right: 4px;
  bottom: 4px;
  display: flex;
  align-items: center;
  gap: 0;
  padding: 0 2px;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.94);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}

.wt-material-card:hover .wt-material-card-actions,
.wt-material-card-actions:focus-within {
  opacity: 1;
  pointer-events: auto;
}

.wt-material-card-actions .ant-btn {
  height: 24px;
  padding-inline: 5px;
  color: #595959;
  font-size: 12px;
}

.wt-material-image-more {
  position: absolute;
  z-index: 3;
  top: 4px;
  right: 4px;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.94);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}

.wt-material-image-card:hover .wt-material-image-more,
.wt-material-image-more:focus-within {
  opacity: 1;
  pointer-events: auto;
}

.wt-material-image-more .ant-btn {
  height: 24px;
  padding-inline: 4px;
  color: #595959;
  font-size: 12px;
}

.wt-material-pin {
  position: absolute;
  left: 2px;
  bottom: 26px;
  padding: 0 4px;
  border-radius: 3px;
  background: #fff7e6;
  color: #d46b08;
  font-size: 10px;
  line-height: 16px;
  pointer-events: none;
}

.wt-material-file-card {
  border-radius: 4px;
}

.wt-material-file-card.is-selected .wt-material-file-tile {
  box-shadow: 0 0 0 2px #91caff inset;
}

.wt-material-file-tile {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 96px;
  border-radius: 4px;
  color: #fff;
  font-size: 21px;
  font-weight: 600;
  letter-spacing: 0.5px;
  overflow: hidden;
}

.wt-material-list-card {
  box-sizing: border-box;
  padding: 9px 10px 27px;
  border: 1px solid #e8e8e8;
  border-radius: 4px;
  background: #fff;
}

.wt-material-source {
  min-width: 0;
  color: #8c8c8c;
  font-size: 12px;
  line-height: 18px;
}

.wt-material-channel-author {
  display: flex;
  align-items: center;
  gap: 6px;
  padding-bottom: 2px;
}

.wt-material-card-title {
  margin-top: 4px;
  color: #262626;
  font-size: 14px;
  font-weight: 500;
  line-height: 21px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.wt-material-card-summary {
  display: -webkit-box;
  margin-top: 4px;
  overflow: hidden;
  color: #8c8c8c;
  font-size: 12px;
  line-height: 19px;
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.wt-material-content-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.wt-material-square-cover {
  display: flex;
  flex: 0 0 54px;
  align-items: center;
  justify-content: center;
  width: 54px;
  height: 54px;
  overflow: hidden;
  border-radius: 4px;
  background: #f5f5f5;
}

.wt-material-wide-cover {
  display: flex;
  width: 100%;
  margin-top: 8px;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border-radius: 3px;
  background: #f5f5f5;
}

.wt-material-mini-cover {
  height: 100px;
}

.wt-material-channel-cover {
  height: 158px;
}

.wt-material-wide-cover .ant-image,
.wt-material-wide-cover .ant-image-img,
.wt-material-wide-cover .wt-media-thumb {
  width: 100% !important;
  max-width: 100%;
  height: 100% !important;
  object-fit: cover;
}

.wt-material-cover-fallback {
  display: inline-flex;
  width: 100%;
  height: 100%;
  align-items: center;
  justify-content: center;
  color: #bfbfbf;
  font-size: 22px;
}

.wt-material-note-body {
  display: -webkit-box;
  margin-top: 6px;
  overflow: hidden;
  color: #595959;
  font-size: 13px;
  line-height: 20px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
}

/*
  侧边栏「个人话术」卡片：鼠标指定（悬停）才露出编辑/删除图标

  【用户 2026-09-24】"修改直接在话术卡片上面鼠标指定的时候出来编辑跟删除
  图标按钮不要文字说明" —— 与上面素材那套同一个交互，写成 CSS 而不是
  per-item 的 React state：话术列表可能很长，每条都挂 onMouseEnter 会让
  滚动与勾选都变慢，纯 CSS 不参与渲染。
*/
.wt-qr-item .wt-qr-actions {
  position: absolute;
  top: 2px;
  right: 4px;
  display: flex;
  gap: 2px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
  /* 半透明白底：话术是多行文本，图标直接压上去会糊在一起看不清 */
  background: rgba(255, 255, 255, 0.92);
  border-radius: 6px;
}
.wt-qr-item:hover .wt-qr-actions,
.wt-qr-item .wt-qr-actions:focus-within {
  opacity: 1;
  pointer-events: auto;
}

/*
 * 滚动条：细 + 浅（用户 2026-09-26："界面里面的下拉条做细颜色做浅"）
 *
 * 【为什么做成全站一条规则】工作台一屏里有五个滚动区（账号列 / 会话列 /
 * 消息流 / 侧边栏 / 素材库），历史消息与表格页各自还有。浏览器默认的
 * 滚动条是 15~17px 的深灰立体条，压在浅色界面上非常抢眼 —— 而且**每处
 * 各写一遍**必然有一处漏掉，表现就是"这个地方的滚动条还是粗的"。
 *
 * 【为什么用 `*` 而不是一个类】滚动容器散落在各个组件里（内联 style 的
 * overflowY、antd 自己的弹层），没有统一的类名可以挂。`*` 覆盖所有元素，
 * 也就不存在漏网。
 *
 * 【三处必须一起写】
 *   · `scrollbar-width` / `scrollbar-color` → Firefox（新版 Chrome 也认）
 *   · `::-webkit-scrollbar-*`              → Chrome / Edge / Safari
 * 只写一边的话，另一半浏览器看起来像"根本没改"。
 *
 * 【为什么滑轨透明、滑块才给颜色】滑轨（track）上色会把每条滚动区都画成
 * 一道灰带，反而更花；透明滑轨 + 浅灰滑块才是"该看见时才看见"。
 */
* {
  scrollbar-width: thin;
  scrollbar-color: #dcdcdc transparent;
}
*::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
*::-webkit-scrollbar-track,
*::-webkit-scrollbar-corner {
  background: transparent;
}
*::-webkit-scrollbar-thumb {
  background: #dcdcdc;
  border-radius: 3px;
}
*::-webkit-scrollbar-thumb:hover {
  /* 悬停才稍微深一点：给"我正抓着这根条"一个反馈 */
  background: #c6c6c6;
}

/*
 * 下拉菜单 / 下拉选项：行更细、选中色更浅（与上面那条同一个诉求）
 *
 * 【为什么也要改这里】"下拉条"用户可能就是指着点开的那一串菜单说的 ——
 * antd 默认每一项上下各 5px 内边距、选中是 #e6f4ff（偏重的蓝）。
 * 会话工作台里有两个常用下拉（托管账号筛选、小组切换），菜单只有 2~6 项，
 * 默认那套显得又厚又重。这里统一收细一档、把选中色压浅。
 *
 * 【为什么用 !important】antd v5 的样式是运行时注入的 CSS-in-JS，
 * 注入顺序在我们这份静态 CSS **之后** —— 选择器权重相同时它赢。
 * 只有这几个视觉属性用了 !important，不涉及布局逻辑。
 */
.ant-dropdown-menu-item,
.ant-select-item-option,
.ant-cascader-menu-item {
  padding-top: 3px !important;
  padding-bottom: 3px !important;
  font-size: 13px;
}
.ant-dropdown-menu-item-selected,
.ant-select-item-option-selected {
  background-color: #f2f7ff !important;
}

/*
 * 所有头像统一加一圈浅色描边（用户 2026-10-01："所有头像加一个边，颜色浅一点
 * 有个轮廓就行"）
 *
 * 【为什么用全局 CSS 而不是逐个改调用点】全站有 33 处 `<Avatar>`（会话列表、
 * 通讯录、聊天气泡、客户列表、选人器、群成员、转发弹窗、顶栏…），
 * 逐处加样式必然漏 —— 而这类"漏一处"的表现是"这一栏有边、那一栏没有"，
 * 用户会当成 bug 再报一次。antd 的头像只有一个类名 `.ant-avatar`，
 * 收在这里一处生效、以后新增的页面自动带上。
 *
 * 【为什么用 ::after 描边，而不是 border / box-shadow】
 *   · `border` 会改变盒子尺寸：antd 的 `.ant-avatar` 是定宽定高，
 *     加 1px 边框要么把头像撑大 2px、要么把内层图片压小，两种都会让
 *     "同一排头像大小不一样"；
 *   · `box-shadow: inset` 画在**父元素的背景之上、子元素之下** ——
 *     头像是 `<img>` 子元素，会把这圈影子盖住，等于没加；
 *   · `::after` 是父元素的**子层**，天然画在图片上面，且 `inset: 0` 不占布局。
 *
 * 【为什么是 rgba(0,0,0,0.1)】在浅色底（白卡 / #fafafa 消息区）上约等于 #e6e6e6，
 * 刚好是"有个轮廓"而不是"画了个框"；头像底图五颜六色，用固定灰色才不会被
 * 某张偏色的头像吃掉。想更明显就调这一个数字。
 *
 * 【为什么要 position: relative】伪元素按父元素定位。antd 自己就是 relative，
 * 这里再写一遍是兜底：万一某个版本改了，头像会变成"描边跑满整屏"那种事故。
 */
.ant-avatar {
  position: relative;
}
/*
 * 方形头像的圆角：**一个值，全站生效**（用户 2026-10-16："头像图片圆角太大，减小圆角"）
 *
 * 【为什么从 8 改成 4】原来是 8（聊天窗 7、列表 8、几处小头像 3/5/6/9，本身就是**四个值**），
 * 用户看过真实页面后要更小的圆角。取 4：与"微信/企微头像本身是小圆角方形"一致，
 * 也还能看出"这是方的"（0 会显得像缩略图）。
 *
 * 【为什么收在这里而不是逐处改】与上面那圈描边同一条纪律：全站十几处 `<Avatar>`，
 * 逐处改必然漏一处 —— 而"漏一处"的表现就是"这一栏圆角大、那一栏小"。
 * 调用点里那些内联 `borderRadius` 这一轮已经全部对齐成 4（脚本扫过一遍），
 * 加上这条兜底规则，**新写的头像不写圆角也是对的**（antd 方形头像默认是 6）。
 */
.ant-avatar-square {
  border-radius: 4px;
}
.ant-avatar::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  /* 2026-10-26：去掉头像边框颜色，只保留方形/圆形本身的圆角。 */
  border: 0;
  pointer-events: none;
}

/*
 * 群管理成员头像取消所有外框层级。
 * Avatar 本体、内部 img、antd 的 ::after 描边三层都清掉，避免不同浏览器
 * 或 antd 版本下仍残留一条细线。其它位置的全站头像样式保持不变。
 */
.ant-avatar.wt-group-member-avatar,
.ant-avatar.wt-group-member-avatar > img {
  border: 0 !important;
  outline: 0 !important;
  box-shadow: none !important;
}
.ant-avatar.wt-group-member-avatar::after {
  content: none !important;
  display: none !important;
  border: 0 !important;
  box-shadow: none !important;
}
.wt-chat-image-gallery .ant-image-preview-switch-left {
  right: auto;
  left: clamp(32px, 25vw, 560px);
}

.wt-chat-image-gallery .ant-image-preview-switch-right {
  right: clamp(32px, 25vw, 560px);
  left: auto;
}

/*
 * 侧边栏行内确认/取消：只显示一个字符，不绘制按钮边框或悬停底色。
 * antd Button 的 :hover/:focus 样式是运行时注入的，所以这里显式覆盖。
 */
.ant-btn.wt-sidebar-text-action,
.ant-btn.wt-sidebar-text-action:hover,
.ant-btn.wt-sidebar-text-action:focus,
.ant-btn.wt-sidebar-text-action:active {
  padding: 0 !important;
  border: 0 !important;
  box-shadow: none !important;
  background: transparent !important;
}

/*
 * 朋友圈 › 跟圈
 *
 * 配置项原来全部塞进一个 Space wrap 里，桌面端会形成一条很长、换行位置随宽度
 * 漂移的表单，既难扫读也显得拥挤。这里把状态和表单各自分成明确的块：
 * 顶部只展示运行状态与关键数据；配置表单按「跟圈对象 / 转发设置」分组，
 * 开关独立成行，操作按钮收口在表单底部。小屏再降为单列，不依赖固定像素宽度。
 */
.wt-follow-status-card {
  overflow: hidden;
  border-color: #e6f0ff;
  background:
    radial-gradient(circle at 94% -30%, rgba(22, 119, 255, 0.1), transparent 34%),
    #fff;
}

.wt-follow-status {
  display: flex;
  align-items: center;
  gap: 24px;
  min-width: 0;
}

.wt-follow-status__summary {
  display: flex;
  flex: 1 1 300px;
  align-items: flex-start;
  gap: 12px;
  min-width: 0;
}

.wt-follow-status__dot {
  position: relative;
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  margin-top: 7px;
  border-radius: 50%;
  background: #52c41a;
  box-shadow: 0 0 0 4px rgba(82, 196, 26, 0.12);
}

.wt-follow-status__dot.is-paused {
  background: #fa8c16;
  box-shadow: 0 0 0 4px rgba(250, 140, 22, 0.12);
}

.wt-follow-status__dot.is-loading {
  background: #bfbfbf;
  box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.05);
}

.wt-follow-status__copy {
  min-width: 0;
}

.wt-follow-status__title {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 22px;
  white-space: nowrap;
}

.wt-follow-status__title > .ant-typography {
  font-size: 16px;
  line-height: 22px;
}

.wt-follow-status__title .ant-tag {
  padding-inline: 8px;
  font-size: 12px;
  line-height: 20px;
}

.wt-follow-status__help {
  color: #8c8c8c;
  cursor: help;
  font-size: 14px;
}

.wt-follow-status__description {
  display: block;
  margin-top: 3px;
  font-size: 13px;
  line-height: 20px;
}

.wt-follow-metrics {
  display: grid;
  flex: 0 1 520px;
  grid-template-columns: repeat(4, minmax(82px, 1fr));
  gap: 8px;
  min-width: 380px;
}

.wt-follow-metric {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  padding: 2px 14px;
  border-left: 1px solid #edf1f7;
}

.wt-follow-metric .ant-typography {
  overflow: hidden;
  font-size: 12px;
  line-height: 18px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.wt-follow-metric strong {
  color: #1f2937;
  font-size: 20px;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  line-height: 26px;
}

.wt-follow-metric strong span {
  color: #8c8c8c;
  font-size: 14px;
  font-weight: 400;
}

.wt-follow-status__action {
  flex: 0 0 auto;
}

.wt-follow-status__alert {
  margin-top: 14px;
}

.wt-follow-editor .ant-card-head {
  min-height: 72px;
  padding-inline: 20px;
}

.wt-follow-editor .ant-card-head-title {
  padding-block: 15px;
}

.wt-follow-editor .ant-card-body {
  padding: 20px;
}

.wt-follow-editor__title {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.wt-follow-editor__title > .ant-typography:first-child {
  font-size: 15px;
  line-height: 22px;
}

.wt-follow-editor__title > .ant-typography-secondary {
  font-size: 12px;
  font-weight: 400;
  line-height: 18px;
}

.wt-follow-form__section + .wt-follow-form__section {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid #f0f2f5;
}

.wt-follow-form__heading {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 15px;
}

.wt-follow-form__heading > div {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.wt-follow-form__heading .ant-typography {
  margin: 0;
  line-height: 20px;
}

.wt-follow-form__heading .ant-typography-secondary {
  font-size: 12px;
  line-height: 18px;
}

.wt-follow-form__step {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 22px;
  border-radius: 5px;
  background: #e6f4ff;
  color: #1677ff;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  letter-spacing: 0.2px;
}

.wt-follow-form__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  align-items: start;
}

.wt-follow-form__grid--settings {
  grid-template-columns: minmax(0, 1.4fr) minmax(220px, 0.6fr);
}

.wt-follow-form__grid .ant-form-item {
  margin-bottom: 0;
}

.wt-follow-form .ant-form-item-label {
  padding-bottom: 6px;
}

.wt-follow-form .ant-form-item-label > label {
  height: 20px;
  color: #344054;
  font-size: 13px;
  font-weight: 500;
}

.wt-follow-form .ant-form-item-extra {
  min-height: 18px;
  margin-top: 4px;
  color: #8c8c8c;
  font-size: 12px;
  line-height: 18px;
}

.wt-follow-form .ant-input-number-group-wrapper {
  width: 100%;
}

.wt-follow-switch-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-top: 16px;
}

.wt-follow-switch-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 62px;
  padding: 11px 14px;
  border: 1px solid #eef1f5;
  border-radius: 7px;
  background: #fafbfc;
}

.wt-follow-switch-option > div:first-child {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.wt-follow-switch-option .ant-typography {
  margin: 0;
  line-height: 20px;
}

.wt-follow-switch-option .ant-typography-secondary {
  font-size: 12px;
  line-height: 18px;
}

.wt-follow-switch-option .ant-switch {
  flex: 0 0 auto;
}

.wt-follow-form__notice {
  margin-top: 16px;
}

.wt-follow-form__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid #f0f2f5;
}

.wt-follow-form__footer > .ant-typography {
  font-size: 12px;
  line-height: 20px;
}

.wt-follow-list {
  overflow: hidden;
  border: 1px solid #eef0f3;
  border-radius: 8px;
  background: #fff;
}

.wt-follow-list__heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 58px;
  padding: 10px 16px;
  border-bottom: 1px solid #f0f2f5;
}

.wt-follow-list__heading > div {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.wt-follow-list__heading .ant-typography {
  margin: 0;
  line-height: 20px;
}

.wt-follow-list__heading .ant-typography-secondary {
  font-size: 12px;
  line-height: 18px;
}

.wt-follow-list__heading .ant-tag {
  margin-inline-end: 0;
  color: #595959;
}

.wt-follow-log-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 14px;
  border: 1px solid #eef1f5;
  border-radius: 7px;
  background: #fafbfc;
}

.wt-follow-log-toolbar__title {
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  gap: 1px;
}

.wt-follow-log-toolbar__title .ant-typography {
  margin: 0;
  line-height: 20px;
}

.wt-follow-log-toolbar__title .ant-typography-secondary {
  font-size: 12px;
  line-height: 18px;
}

@media (max-width: 1100px) {
  .wt-follow-status {
    flex-wrap: wrap;
    gap: 16px;
  }

  .wt-follow-status__summary {
    flex: 1 1 calc(100% - 140px);
  }

  .wt-follow-metrics {
    order: 3;
    flex: 1 1 100%;
    min-width: 0;
  }

  .wt-follow-metric:first-child {
    padding-left: 0;
    border-left: 0;
  }

  .wt-follow-form__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .wt-follow-form__grid > .ant-form-item:first-child {
    grid-column: 1 / -1;
  }
}

@media (max-width: 760px) {
  .wt-follow-status__summary {
    flex-basis: 100%;
  }

  .wt-follow-status__action {
    width: 100%;
  }

  .wt-follow-metrics {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: 12px;
  }

  .wt-follow-metric:nth-child(odd) {
    padding-left: 0;
    border-left: 0;
  }

  .wt-follow-form__grid,
  .wt-follow-form__grid--settings,
  .wt-follow-switch-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .wt-follow-form__grid > .ant-form-item:first-child {
    grid-column: auto;
  }

  .wt-follow-editor .ant-card-head {
    padding-inline: 16px;
  }

  .wt-follow-editor .ant-card-body {
    padding: 16px;
  }

  .wt-follow-form__footer,
  .wt-follow-log-toolbar {
    align-items: stretch;
    flex-direction: column;
  }

  .wt-follow-form__footer > .ant-space,
  .wt-follow-form__footer .ant-btn {
    width: 100%;
  }
}

/* 跟圈总开关：按参考图的单行状态区展示。 */
.wt-follow-master-card .ant-card-head {
  min-height: 52px;
  padding-inline: 20px;
}

.wt-follow-master-card .ant-card-head-title {
  padding-block: 14px;
  font-size: 15px;
  font-weight: 600;
}

.wt-follow-master-card .ant-card-body {
  border-top: 1px solid #f0f0f0;
}

.wt-follow-master-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 28px;
}

.wt-follow-master-toggle,
.wt-follow-master-state {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
}

.wt-follow-master-state--paused {
  color: #fa8c16;
}

.wt-follow-master-state--running {
  color: #52c41a;
}

.wt-follow-master-card .wt-follow-status__alert {
  margin-top: 12px;
  padding: 0;
  border: 0;
  background: transparent;
}

.wt-follow-master-card .wt-follow-status__alert .ant-alert-message {
  color: #fa8c16;
  font-size: 13px;
  line-height: 20px;
}

/* 自动跟圈配置：单列逐行表单，标签固定左列，控件保持可扫读宽度。 */
.wt-follow-editor .ant-card-head-title {
  padding-block: 16px;
  font-size: 15px;
  font-weight: 600;
}

.wt-follow-form__description {
  display: block;
  max-width: 930px;
  margin-bottom: 20px;
  font-size: 13px;
  line-height: 21px;
}

.wt-follow-form .ant-form-item {
  display: flex;
  margin-bottom: 16px;
}

.wt-follow-form .ant-form-item-row {
  width: 100%;
  flex-wrap: nowrap;
}

.wt-follow-form .ant-form-item-label {
  flex: 0 0 120px;
  max-width: 120px;
  padding: 0 16px 0 0;
  text-align: left;
}

.wt-follow-form .ant-form-item-label > label {
  height: 32px;
  color: #262626;
  font-size: 14px;
  font-weight: 500;
}

.wt-follow-form .ant-form-item-control {
  flex: 0 1 500px;
  max-width: 500px;
}

.wt-follow-form .ant-form-item-control-input {
  min-height: 32px;
}

.wt-follow-form .ant-form-item-extra {
  min-height: 0;
  margin-top: 4px;
  font-size: 12px;
  line-height: 18px;
}

.wt-follow-inline-switch {
  display: flex;
  min-height: 32px;
  align-items: center;
  gap: 8px;
}

.wt-follow-inline-switch .ant-typography {
  font-size: 13px;
  line-height: 20px;
}

.wt-follow-form__notice {
  max-width: 620px;
  margin: 4px 0 0 120px;
}

.wt-follow-form__footer {
  justify-content: flex-start;
  margin-top: 22px;
  padding: 18px 0 0 120px;
  border-top: 1px solid #f0f0f0;
}

@media (max-width: 760px) {
  .wt-follow-master-row {
    align-items: flex-start;
    flex-direction: column;
    gap: 8px;
  }

  .wt-follow-form .ant-form-item {
    display: block;
  }

  .wt-follow-form .ant-form-item-row {
    display: block;
  }

  .wt-follow-form .ant-form-item-label {
    max-width: none;
    padding: 0 0 6px;
  }

  .wt-follow-form .ant-form-item-label > label {
    height: 20px;
  }

  .wt-follow-form .ant-form-item-control {
    max-width: none;
  }

  .wt-follow-form__notice {
    margin-left: 0;
  }

  .wt-follow-form__footer {
    padding-left: 0;
  }
}

/*
 * 页面级功能切换按钮。
 *
 * 与快捷回复的「公共话术 / 个人话术 / 小组话术」共用同一套尺寸：选中态使用
 * antd 主按钮，未选中态使用默认按钮。原来各页分别使用 Tabs 下划线或 Segmented，
 * 同一类入口出现了三种视觉语言；统一后相似功能区一眼可辨。
 */
.wt-button-tabs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-start;
  gap: 24px;
  margin-bottom: 12px;
}

.wt-button-tabs .ant-btn {
  min-width: 110px;
  height: 38px;
  text-align: center;
}

.wt-button-tabs.is-reorderable .ant-btn {
  cursor: grab;
  user-select: none;
}

.wt-button-tabs.is-reorderable .ant-btn:active {
  cursor: grabbing;
}

.wt-button-tabs.wt-material-tabs {
  margin-bottom: 0;
}

@media (max-width: 760px) {
  .wt-button-tabs {
    gap: 8px;
  }
}

