/* v1.84：原 chatbase.css 的全局滚动约束，AI 小助手下线后迁到本文件 */
html {
    background: #fafafa;
    overflow-y: hidden;
}

._dash-loading {
    color: transparent;
    position: fixed;
    width: calc(544px / 2.5);
    height: calc(408px / 2.5);
    top: 50vh;
    left: 50vw;
    transform: translate(-50%, -50%);
    background-image: url("/assets/imgs/loading.webp");
    background-repeat: no-repeat;
    background-size: 100% 100%;
}

._dash-loading::after {
    content: '';
}

#login-form-container .ant-card-head-wrapper {
    text-align: center;
}

#login-form-container .ant-card-head-title {
    font-size: 26px !important;
    font-weight: bold;
}

/*滚动条自定义样式*/
*::-webkit-scrollbar-thumb {
    background-color: #bfbfbf;
    outline: none;
    border-radius: 6px;
}

*::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}

/*火狐浏览器*/
* {
    scrollbar-width: thin;
}
/* ===== 订单总览-商品明细：行状态底色（v1.86 按 UI 评审 P1-4 重构）
   原实现四色整行铺底（#b7eb8f 绿 / #ffe7ba 橙 / #bae7ff 蓝 / #ffccc7 红），
   红底上的红字对比度只有 2.38:1、整表像色卡。改为「极浅底 + 左侧 3px 竖条」：
   状态依旧一眼可辨，正文恢复可读，四色含义由图例（标题行 4 点）解释。 */
.ant-table-tbody tr.del-row-unsent td {
  background: #fffbe6 !important;
}
.ant-table-tbody tr.del-row-done td {
  background: #f6ffed !important;
}
/* 在途占用（已推 ERP/委派，占用中但未发完；不是「已发完」的绿） */
.ant-table-tbody tr.del-row-inflight td {
  background: #f0f9ff !important;
}
/* 售后占用（进行中/已退款，禁组货） */
.ant-table-tbody tr.del-row-refund td {
  background: #fff1f0 !important;
  color: rgba(0, 0, 0, 0.72) !important;
}
/* 左侧竖条：用首列 inset 阴影实现，不额外引入伪元素/抖动列宽 */
.ant-table-tbody tr.del-row-unsent td:first-child {
  box-shadow: inset 3px 0 0 #fa8c16;
}
.ant-table-tbody tr.del-row-done td:first-child {
  box-shadow: inset 3px 0 0 #52c41a;
}
.ant-table-tbody tr.del-row-inflight td:first-child {
  box-shadow: inset 3px 0 0 #1677ff;
}
.ant-table-tbody tr.del-row-refund td:first-child {
  box-shadow: inset 3px 0 0 #ff4d4f;
}
/* ===== v1.42 售后「待确认收货」：退货物流已签收 → 整行绿底（货到了，可确认收货） ===== */
.ant-table-tbody tr.refund-row-signed td {
  background: #b7eb8f !important;
}

/* ===== 首页·销售日历（AntdCalendar 版） =====
   回调写入 customCells 的完成率分档着色 + 底部图例
   分档与 callbacks/dashboard/page_bottom_c.py 的 _render_cal_rate 一致 */
.dashhome-cal-wrap {
  width: 100%;
  height: 100%;
}
/* 锁定当前月：隐藏 AntdCalendar 头部（年月选择 + 月/年切换），使日历不可翻月 */
.dashhome-cal-wrap .ant-picker-calendar-header {
  display: none;
}
.dashhome-cal-title {
  font-size: 15px;
  font-weight: 600;
  color: rgba(0, 0, 0, 0.85);
  margin-bottom: 6px;
  padding-left: 2px;
}
/* 达成率用 AntdTag 展示：压缩尺寸以适配日历格（覆盖 Antd 默认的 margin/padding） */
.dashhome-cal-wrap .dashhome-cal-tag {
  margin-inline-end: 0;
  margin-bottom: 1px;
  font-size: 14px;
  line-height: 20px;
  padding: 0 4px;
}
.dashhome-cal-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 10px;
  padding-left: 2px;
  font-size: 12px;
  color: rgba(0, 0, 0, 0.45);
}
.dashhome-cal-legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
}
.dashhome-cal-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
  background: #d9d9d9;
}
.dashhome-cal-dot.is-high { background: #52c41a; }
.dashhome-cal-dot.is-mid  { background: #1890ff; }
.dashhome-cal-dot.is-low  { background: #ff4d4f; }
.dashhome-cal-dot.is-none { background: #bfbfbf; }

/* ===== 首页·销售日历：万年历 hover 气泡 ===== */
/* 让「整个日期格」都能触发气泡（含日期号区域）：
   - 用 td.ant-picker-cell 作为定位参照，伪元素可覆盖整格（含 Antd 的格子内边距）；
   - 触发元素用绝对定位伪元素铺满整格，不改动 Antd 原有布局/行高；
   - 必须放开内容区 overflow（Antd 默认 overflow-y:auto 会把伪元素裁掉）。 */
.dashhome-cal-wrap .ant-picker-cell {
  position: relative;
}
.dashhome-cal-wrap .ant-picker-calendar-date-content {
  overflow: visible !important;
}
.dashhome-cal-hover {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  width: 100%;
  min-height: 22px;
  padding-bottom: 2px;
  cursor: default;
}
.dashhome-cal-hover::before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
.dashhome-lunar-tip {
  max-width: 420px;
  font-size: 12px;
  line-height: 18px;
}
.dashhome-lunar-head {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 6px;
  margin-bottom: 6px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.25);
  font-weight: 600;
}
.dashhome-lunar-date {
  font-variant-numeric: tabular-nums;
}
.dashhome-lunar-week {
  opacity: 0.85;
}
.dashhome-lunar-row {
  display: flex;
  gap: 8px;
  margin-top: 2px;
}
.dashhome-lunar-label {
  flex: 0 0 32px;
  opacity: 0.7;
}
.dashhome-lunar-value {
  flex: 1 1 auto;
  word-break: break-word;
}
.dashhome-lunar-value.is-yi { color: #b7eb8f; }
.dashhome-lunar-value.is-ji { color: #ffadd2; }
.dashhome-lunar-value.is-term { color: #ffd591; font-weight: 600; }
.dashhome-lunar-empty { opacity: 0.75; }

/* ===== 首页·导购业绩（日历右侧） ===== */
/* 上排两栏等高：AntdRow.align 不支持 stretch，用 class 覆盖为 stretch */
.dashhome-top-row {
  align-items: stretch !important;
}
.dashhome-staff-wrap {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}
/* 右栏表格体：内部滚动，高度由整行固定高度决定（与日历等高） */
.dashhome-staff-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
/* 滚动时表头固定 */
.dashhome-staff-body .ant-table-thead > tr > th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: #fafafa;
}
.dashhome-staff-title {
  flex: 0 0 auto;
  font-size: 15px;
  font-weight: 600;
  color: rgba(0, 0, 0, 0.85);
  margin-bottom: 6px;
  padding-left: 2px;
}

/* ===== 首页：矮窗口时内容区自身滚动 =====
   全局 html 设了 overflow-y: hidden，文档不滚动；
   本容器把高度收到视口内并内部滚动（与 delivery 页约定一致）。 */
.dashhome-scroll {
  width: 100%;
  max-height: calc(100vh - 120px);
  overflow-y: auto;
  overflow-x: hidden;
  padding-right: 4px;
}

/* ===== SSRS 报表 iframe：高度跟随可视区，矮窗口不再被挤到窗口外 =====
   全局 html 设了 overflow-y: hidden、文档不滚动，iframe 超出视口的部分会被直接裁掉，
   所以高度要自己收在可视区内：视口高 -（头部 50 + 头下间距 10 + 标签栏含边距约 62）≈ 130px。
   dvh 兜住移动端 / 钉钉 webview 的动态视口；矮到连 240px 都没有时给个下限（超出部分由
   iframe 内部滚动，参数栏和报表自己会滚）。 */
.ssrs-report-frame {
  display: block;
  width: 100%;
  border: 0;
  height: calc(100vh - 130px);
  height: calc(100dvh - 130px);
  min-height: 240px;
}

/* v1.94 加载动画统一为 dcc.Loading(type='circle')（v1.80.1 的 AntdSpin 段已废）。
   Dash 的指示器是 dcc.Loading 内一个 cover 层 <div id={loading-id} style="position:absolute;
   top:0;height:100%;width:100%;display:flex;justify-content:center;align-items:center">，
   默认按容器居中。数据看板「作业/经营」与参数配置的数据区高几千像素，按容器居中会把圈
   画到首屏之外 —— 这里把指示器层钉到视口中央（fixed 下 100% 高按视口解析，正好落在中间）。
   :not([style*="display: none"]) 用不上（Dash 隐藏时是把 style 清空、元素仍在），
   所以只钉位置，不碰 display：隐藏态该层无内容、宽高 auto → 0×0，不挡点击。 */
#dash-spin-work,
#dash-spin-biz,
#cfg-spin {
  position: fixed !important;
  top: 45vh !important;
  left: 50% !important;
  width: auto !important;
  height: auto !important;
  transform: translate(-50%, -50%);
  z-index: 1200;
}

/* v1.84 参数配置页签：yz_delivery_config 动态行（网格对齐，窄屏不挤成一团）
   v1.85：值列改只读展示（改值走弹窗），多出「操作」列 */
#cfg-root .cfg-row {
  display: grid;
  grid-template-columns: 240px minmax(200px, 1.6fr) minmax(180px, 1fr) 130px 76px;
  gap: 10px;
  align-items: center;
  padding: 9px 10px;
  border-bottom: 1px solid #f0f0f0;
  border-radius: 4px;
  transition: background-color 0.15s ease;
}
#cfg-root .cfg-row:last-child {
  border-bottom: 0;
}
/* 隔行变色：一眼能横向对齐，长值也不会看串行 */
#cfg-root .cfg-row:nth-child(even) {
  background: #f7f9fc;
}
#cfg-root .cfg-row:nth-child(odd) {
  background: #fff;
}
#cfg-root .cfg-row:hover {
  background: #eaf3ff;
}
/* 表头吸顶后加一道浅投影，滚动时与行区分开 */
#cfg-root .cfg-head {
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
}
#cfg-root .cfg-key {
  font-family: ui-monospace, Menlo, Consolas, 'Courier New', monospace;
  font-size: 13px;
  font-weight: 500;
  color: #1f3a93;
  word-break: break-all;
  line-height: 1.5;
}
/* 当前值：单行省略，长值/密钥靠 title 悬停看全文（避免行高忽大忽小） */
#cfg-root .cfg-val {
  color: #1f1f1f;
  font-size: 12px;
  font-family: ui-monospace, Menlo, Consolas, 'Courier New', monospace;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.6;
}
#cfg-root .cfg-val-empty {
  color: #bfbfbf;
  font-family: inherit;
  font-style: italic;
}
/* 修改弹窗：参数键与更新时间 */
#cfg-root .cfg-modal-key {
  font-family: ui-monospace, Menlo, Consolas, 'Courier New', monospace;
  font-size: 13px;
  color: #1f3a93;
  word-break: break-all;
}
#cfg-root .cfg-modal-meta {
  color: #8c8c8c;
  font-size: 12px;
  margin-top: 4px;
}
#cfg-root .cfg-desc {
  color: #595959;
  font-size: 12px;
  line-height: 1.5;
}
/* 分页条：常驻在滚动区下方（右对齐） */
#cfg-root .cfg-pager {
  display: flex;
  justify-content: flex-end;
  padding: 2px 4px 0;
}
#cfg-root .cfg-time {
  color: #8c8c8c;
  font-size: 12px;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
}
/* v1.94：转圈改 dcc.Loading，定位统一写在上面 #dash-spin-work/#dash-spin-biz/#cfg-spin 那段。 */

/* ============================================================
   v1.85：《有赞订单发货》发货记录页视觉校准（UI 评审 P1-2/4/6/7）
   注意：这里只做「静态样式」得事 —— 行内 style 优先级更高，
   组件上已写的 fontSize/color 不会被覆盖（发货单号 14px/500 仍生效）。
   ============================================================ */
/* 状态标签对比度：Antd 预设 green/success 是 #52c41a on #f6ffed，实测 2.21:1
   （WCAG AA 需 4.5:1）→ 小字号标签在浅绿底上发虚。压深文字不改底色，
   保住「绿 = 已发货」的语义。 */
.ant-tag-green,
.ant-tag-success {
  color: #237804;
}
/* 发货记录表：单号/运单号等可复制文本用等宽数字（列宽稳定，逐位比对不吃力） */
#delivery-records-table .ant-table-tbody .ant-typography {
  font-family: ui-monospace, Menlo, Consolas, 'Courier New', monospace;
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  color: #595959;
}
/* 复制图标平时淡出、悬停才出现 —— 一行 3~4 个蓝色小图标会持续抢注意力 */
#delivery-records-table .ant-typography-copy {
  opacity: 0.35;
  transition: opacity 0.2s ease;
}
#delivery-records-table .ant-typography:hover .ant-typography-copy {
  opacity: 1;
}
/* 筛选行：标签固定宽 + 右对齐，让 8 个控件左边缘成一条竖线
   （inline 表单不吃 labelCol，只能靠 label 自身撑宽） */
#delivery-records-search-form .ant-form-item-label > label {
  display: inline-block;
  min-width: 76px;
  text-align: right;
}
#delivery-records-search-form .ant-form-item {
  margin-bottom: 8px;
}

/* =====================================================================
   v1.86 订单详情抽屉（UI 评审 P0/P1/P2 落实）
   ===================================================================== */
/* 明细表：金额/数量列等宽数字，小数点竖直对齐（右对齐只是第一步） */
#delivery-detail-items .ant-table-tbody td {
  font-variant-numeric: tabular-nums;
}
/* 「主动退款」是资金动作，用更深的红（原 #ff4d4f 在浅红底上偏飘） */
#delivery-detail-items .ant-btn-dangerous {
  color: #a8071a;
}
/* 复制图标热区从 12px 图标撑到 28×28，鼠标不用瞄太准 */
#delivery-order-drawer .ant-typography-copy {
  padding: 6px;
  margin: -6px 0 -6px 2px;
  border-radius: 4px;
  transition: background 0.2s ease;
}
#delivery-order-drawer .ant-typography-copy:hover {
  background: rgba(0, 0, 0, 0.04);
}
/* 组包空态：antd 默认空表格 129px（大插画 + 暂无数据），压到 88px 以内 */
#delivery-packages-table .ant-empty-image {
  display: none;
}
#delivery-packages-table .ant-table-placeholder {
  height: 88px;
}
#delivery-packages-table .ant-table-placeholder .ant-empty {
  margin: 0;
}
#delivery-packages-table .ant-empty-description {
  font-size: 12px;
  color: #bfbfbf;
}
/* Drawer footer 常驻操作条：与 body 之间一条细线，高度紧凑 */
#delivery-order-drawer .ant-drawer-footer {
  padding: 0 16px;
  border-top: 1px solid #f0f0f0;
}
/* 信息区 label 定宽后，长内容（收件地址等）不允许把格子撑变形 */
#delivery-order-drawer .ant-descriptions-item-label {
  white-space: nowrap;
}



/* =====================================================================
   v1.87 订单列表页（UI 评审 P0/P1/P2 落实）
   原则：行内 style 优先级更高，这里只做「组件上写不了」的静态样式；
   选择器全部用 #delivery-orders-table / #delivery-orders-search-form 收口，
   不影响发货记录页（#delivery-records-table）与辅助发货页。
   ===================================================================== */
/* 表头 60px → 44px：14px 字上下各 20px 空白，比数据行还高，看不出是「表头」 */
#delivery-orders-table .ant-table-thead > tr > th {
  height: 44px;
  padding: 8px;
  font-size: 13px;
  font-weight: 600;
  line-height: 20px;
  color: #595959;
}
/* 数据行垂直居中：单号两行、备注两行、金额一行 —— 不居中会「数字吊在顶上」 */
#delivery-orders-table .ant-table-tbody > tr > td {
  vertical-align: middle;
  padding: 8px;
}
/* 数字列一律 tabular-nums（金额小数点、已发/总数 的斜杠竖向对齐） */
#delivery-orders-table .ant-table-tbody td {
  font-variant-numeric: tabular-nums;
}
/* 复制图标平时淡出、悬停才出现 —— 一屏 11 行 × 3 个蓝图标会持续抢注意力 */
#delivery-orders-table .ant-typography-copy {
  opacity: 0.35;
  transition: opacity 0.2s ease;
}
#delivery-orders-table .ant-typography:hover .ant-typography-copy {
  opacity: 1;
}
/* 履约超时：整行左侧 3px 竖条（复用订单详情四条状态色的 inset 阴影手法），不加底色。
   红色从「每行一个红胶囊」上移到行首，扫读时是一列竖条而不是满屏噪声。 */
#delivery-orders-table .ant-table-tbody tr.del-row-late td:first-child {
  box-shadow: inset 3px 0 0 #ff4d4f;
}
/* 空态：与组包区一致的紧凑占位（antd 默认 129px 大插画 + 暂无数据） */
#delivery-orders-table .ant-empty-image {
  display: none;
}
#delivery-orders-table .ant-table-placeholder {
  height: 88px;
}
/* 「只看」chip 组：24px 高、12px 字、去方框 —— 整颗 chip 就是开关，
   与 32px 的输入框/按钮同排时不额外撑高筛选行（三枚 AntdSwitch 原本占 420px） */
#delivery-orders-search-form .ant-checkbox-group {
  display: inline-flex;
  gap: 6px;
}
#delivery-orders-search-form .ant-checkbox-wrapper {
  height: 24px;
  margin-inline-end: 0;
  padding: 0 8px;
  border: 1px solid #d9d9d9;
  border-radius: 12px;
  background: #fff;
  font-size: 12px;
  line-height: 22px;
  transition: color .2s ease, border-color .2s ease, background .2s ease;
}
#delivery-orders-search-form .ant-checkbox-wrapper .ant-checkbox {
  display: none;
}
#delivery-orders-search-form .ant-checkbox-wrapper > span:last-child {
  padding: 0;
}
#delivery-orders-search-form .ant-checkbox-wrapper:hover {
  border-color: #91caff;
  color: #0958d9;
}
#delivery-orders-search-form .ant-checkbox-wrapper:has(.ant-checkbox-checked) {
  background: #e6f4ff;
  border-color: #91caff;
  color: #0958d9;
}


/* ==========================================================================
   v1.88 五个页签统一表格规格（辅助发货 / 缺货 / 悬赏 / 售后 / 操作日志）
   订单列表在 v1.87 已单独收口；其余页签此前各写各的，实测表头 39px、14px 黑字，
   数据行高在 40 / 61 / 93 三档之间摆动 —— 行高不统一时，任何字号/间距微调都会被
   行高差抵消。这里一次把「表头 44px / 13px 600 #595959」「td padding 8」「数字列
   tabular-nums」钉住，各页只负责把自己的内容压到 56px 基线内。
   用 :is() 列 id 而不是 .ant-table 全局命中，避免影响抽屉里的明细表/内嵌子表。
   ========================================================================== */
:is(#assist-table, #stockout-table, #bounty-table, #bounty-mine-table,
    #refund-table, #delivery-logs-table) .ant-table-thead > tr > th {
  height: 44px;
  padding: 8px;
  background: #fafafa;
  border-bottom: 1px solid #f0f0f0;
  font-size: 13px;
  font-weight: 600;
  line-height: 20px;
  color: #595959;
}

:is(#assist-table, #stockout-table, #bounty-table, #bounty-mine-table,
    #refund-table, #delivery-logs-table) .ant-table-tbody > tr > td {
  padding: 8px;
  vertical-align: middle;
  /* 数字/金额/时间一律等宽，扫读时小数点与冒号能竖向对齐 */
  font-variant-numeric: tabular-nums;
}

/* 单号列：13px 等宽 + 不折行（26 位 tid 在比例字体里必然把复制图标挤到第二行） */
.dsh-no {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* 复制图标：平时 .35、悬停 1（与订单列表一致） */
:is(#assist-table, #stockout-table, #bounty-table, #bounty-mine-table,
    #refund-table, #delivery-logs-table) .ant-typography-copy {
  opacity: 0.35;
  transition: opacity 0.2s ease;
}

:is(#assist-table, #stockout-table, #bounty-table, #bounty-mine-table,
    #refund-table, #delivery-logs-table) .ant-typography:hover .ant-typography-copy {
  opacity: 1;
}

/* 空态：统一 88px 紧凑占位 + 隐藏大插画（悬赏子表原本 320px） */
:is(#assist-table, #stockout-table, #bounty-table, #bounty-mine-table,
    #refund-table, #delivery-logs-table) .ant-empty-image {
  display: none;
}

:is(#assist-table, #stockout-table, #bounty-table, #bounty-mine-table,
    #refund-table, #delivery-logs-table) .ant-table-placeholder {
  height: 88px;
}

/* v1.88b（用户反馈）：窗口变窄时缺货内容压到隔壁列 —— tableLayout=fixed 只固定列宽，
   单元格内容仍按 min-content 撑开。这里给五张表补裁剪 + 两行行内截断。 */
:is(#assist-table, #stockout-table, #bounty-table, #bounty-mine-table,
    #refund-table, #delivery-logs-table) .ant-table-tbody > tr > td {
  overflow: hidden;
}

:is(#assist-table, #stockout-table, #bounty-table, #bounty-mine-table,
    #refund-table, #delivery-logs-table) .ant-table-cell {
  word-break: break-word;
}

.dsh-clamp2 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  word-break: break-all;
  white-space: normal;
}

/* 终态行降权：辅助发货里 10/11 行都是已完结，整行吃掉注意力却不可操作 */
.ant-table-tbody tr.dsh-row-muted > td {
  color: #8c8c8c;
}

/* 展开区容器：与主行区分（原来只有一条细线，像同一张表在延续） */
.dsh-expand-panel {
  background: #fafafa;
  padding: 16px;
  border-top: 1px solid #f0f0f0;
}

/* 分区标题：2px 中性竖条。订单列表已把「左侧 3px 竖条」用于超时状态，
   这里再用蓝色竖条会在同一模块里撞语义 */
.dsh-section-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 16px 0 8px;
  font-size: 13px;
  font-weight: 600;
  color: #1f1f1f;
}

.dsh-section-title::before {
  content: "";
  width: 2px;
  height: 12px;
  background: #d9d9d9;
}


/* ============================================================
   v1.91：六个页签的列表撑满视口（订单列表 / 发货记录 / 辅助发货 /
   缺货面板 / 操作日志 / 售后处理）

   原实现：根容器固定 calc(100vh - 220px) + overflowY: auto，
   表格 maxHeight 写成 min(600px, calc(100vh - Npx)) —— 600 是硬顶，
   窗口再高表格也只到 600px，列表下方留一大片空白。

   现实现：与「参数配置」页签（config_ui.build_config_tab）同一手法 ——
   根做 flex 列，头部的筛选区固定高度，表格吃满剩余高度并把分页条钉在底部。
   注意：antd 把 maxHeight 写成 .ant-table-body 的 inline max-height，
   必须 !important 才能盖成 none（配合 flex 的最小高度约束）。

   .dsh-fill-body 是给 dcc.Loading 之类不收 className 的组件外包的一层：
   dcc.Loading 会插入无类名的 div，flex 链会在这里断掉，故用
   .dsh-fill-body 自己的后代选择器把内容层一直接到表格（细节见下方注释）。
   ============================================================ */
.dsh-fill-tab {
  display: flex;
  flex-direction: column;
  min-height: 0;
  box-sizing: border-box;
  overflow: hidden;
}

/* 直接子节点（筛选卡 / 汇总条等）按内容高度，不参与拉伸 */
.dsh-fill-tab > * {
  flex: 0 0 auto;
  min-height: 0;
}

/* 承接表格的那一层（含 dcc.Loading 包裹层）吃满剩余高度 */
/* dcc.Loading 的 DOM 是：
     <div style="position:relative">
       <div> 内容层（表格在这一支里） </div>
       <div id="xxx-loading"></div>   ← 指示器空壳，是**兄弟节点**
     </div>
   所以这一组只给「内容层」加 flex:1（用 :first-child 指名），
   指示器空壳拿不到规则、flex-grow 默认为 0，高度就是 0；
   若一并给 flex:1 它会和表格平分高度 —— 实测缺货面板表格只吃到
   903px 而容器有 1651px，正是这个坑。子节点多于一个时 Dash 会再套一层，
   故铺到第三层。 */
.dsh-fill-body,
.dsh-fill-body > div,
.dsh-fill-body > div > div:first-child,
.dsh-fill-body > div > div:first-child > div:first-child {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

/* antd Table 内部这条链要一路 flex 下去，表体才能算出「剩余高度」 */
.dsh-fill-tab .ant-table-wrapper {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.dsh-fill-tab .ant-spin-nested-loading,
.dsh-fill-tab .ant-spin-container {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.dsh-fill-tab .ant-table {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.dsh-fill-tab .ant-table-container {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* 表头固定，只有表体滚动 */
.dsh-fill-tab .ant-table-header {
  flex: 0 0 auto;
}

.dsh-fill-tab .ant-table-body {
  flex: 1 1 auto;
  min-height: 0;
  /* 盖掉 antd 由 maxHeight 写进来的 inline max-height（min(600px, ...)） */
  max-height: none !important;
  overflow-y: auto;
}

/* 分页条钉在滚动区外：表体滚到哪儿都能翻页 */
.dsh-fill-tab .ant-table-pagination {
  flex: 0 0 auto;
  margin: 12px 0 0 !important;
}

