﻿/* 全局样式：语义色、首屏、登录页背景、顶栏、多页签、内容区、主题抽屉。

   我们自己的面板、顶栏、页签一律走下面的语义色变量，不再写死颜色：
   亮 / 暗两套只要改变量值即可，避免「背景变了文字没变」导致整片内容隐形。
   暗色由 ThemeService 切 antd 官方 dark.css，同时给 <body> 加 erp-dark 触发覆盖值。
   主色直接读 AntDesign 的变量，抽屉里改主色时自定义类跟着一起变。 */
:root {
    --erp-surface: #ffffff;                     /* 面板、卡片、顶栏底色 */
    --erp-surface-alt: #fafafa;                 /* 表头、行悬停等次级底色 */
    --erp-layout-bg: #f5f6fa;                   /* 内容区底色 */
    --erp-border: #f0f0f0;                      /* 分割线 */
    --erp-border-strong: #d9d9d9;               /* 输入控件描边 */
    --erp-divider: rgba(0, 0, 0, 0.06);         /* 下拉内部分隔线 */
    --erp-text: rgba(0, 0, 0, 0.85);            /* 主文本 */
    --erp-text-secondary: rgba(0, 0, 0, 0.65);  /* 次文本 */
    --erp-text-tertiary: rgba(0, 0, 0, 0.45);   /* 弱化文本 */
    --erp-hover-bg: rgba(0, 0, 0, 0.04);        /* 悬停底色 */
    --erp-hover-bg-soft: rgba(0, 0, 0, 0.02);   /* 更弱的悬停底色 */
    --erp-primary: var(--ant-primary-color, #1677ff);
    --erp-tab-active-bg: rgba(22, 119, 255, 0.06); /* 激活页签的浅色底 */
    --erp-primary-bg: rgba(22, 119, 255, 0.08); /* 主色极浅底 */
    --erp-radius: 6px;
}

/* ===== 个人中心 / 用户管理（2026-10-10）：现代卡片与列表 =====
   颜色一律走上面的语义变量 + 主色变量，暗色下自动跟着变，不写死色值。 */

/* 个人中心：身份条（放进标准卡片 .erp-wb-card 里用，不另起一套渐变底 ——
   项目统一视觉基线是「圆角 12 + 两层柔和阴影 + --erp-surface」（坑 26），自建渐变底会跟其它页面脱节）。 */
.erp-profile-head {
    display: flex;
    align-items: center;
    gap: 18px;
    min-width: 0;
}

.erp-profile-avatar {
    flex: none;
    width: 64px;
    height: 64px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 24px;
    font-weight: 600;
    color: #fff;
    background: linear-gradient(135deg, var(--erp-primary), #7c4dff);
}

.erp-profile-name {
    font-size: 20px;
    font-weight: 600;
    line-height: 1.25;
    color: var(--erp-text);
    word-break: break-all;
}

.erp-profile-sub {
    margin-top: 6px;
    font-size: 13px;
    color: var(--erp-text-secondary);
}

.erp-profile-chip {
    display: inline-flex;
    align-items: center;
    margin: 0 6px 4px 0;
    padding: 2px 10px;
    border-radius: 999px;
    font-size: 12px;
    background: var(--erp-hover-bg);
    color: var(--erp-text-secondary);
}

.erp-profile-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
}

.erp-profile-item {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 10px 12px;
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    background: var(--erp-surface-alt);
    min-width: 0;
}

.erp-profile-item > span {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

.erp-profile-item > div {
    font-size: 14px;
    color: var(--erp-text);
    word-break: break-all;
}

/* 邮箱认证：虚线框把「发码 + 填码」框成一步操作，跟上面的资料区区分开 */
.erp-verify-box {
    margin-top: 14px;
    padding: 16px;
    border: 1px dashed var(--erp-border-strong);
    border-radius: var(--erp-radius);
    background: var(--erp-surface-alt);
}

.erp-verify-tip {
    font-size: 12px;
    color: var(--erp-text-tertiary);
    margin-bottom: 10px;
}

.erp-verify-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

/* 认证落地页（/verify-email）：匿名壳里的居中结果区，不套后台布局 */
.erp-verify-page {
    padding: 32px 24px;
}

.erp-verify-center {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    margin-top: 16px;
    text-align: center;
    font-size: 13px;
    color: var(--erp-text-secondary);
}

/* 软徽标：比 antd Tag 轻，用来标「已认证 / 未认证」 */
.erp-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 12px;
    white-space: nowrap;
}

.erp-badge-success {
    background: rgba(82, 196, 26, 0.14);
    color: #52c41a;
}

.erp-badge-muted {
    background: var(--erp-hover-bg);
    color: var(--erp-text-tertiary);
}

/* 用户管理：用户名单元格（头像 + 两行文本） */
.erp-user-cell {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.erp-user-avatar {
    flex: none;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    font-weight: 600;
    color: #fff;
    background: linear-gradient(135deg, var(--erp-primary), #7c4dff);
}

.erp-user-cell-text {
    display: flex;
    flex-direction: column;
    line-height: 1.3;
    min-width: 0;
}

.erp-user-cell-name {
    font-weight: 500;
    color: var(--erp-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.erp-user-cell-sub {
    font-size: 12px;
    color: var(--erp-text-tertiary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.erp-email-cell {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.erp-email-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

body.erp-dark {
    --erp-surface: #1f1f1f;
    --erp-surface-alt: #262626;
    --erp-layout-bg: #141414;
    --erp-border: #303030;
    --erp-border-strong: #434343;
    --erp-divider: rgba(255, 255, 255, 0.12);
    --erp-text: rgba(255, 255, 255, 0.88);
    --erp-text-secondary: rgba(255, 255, 255, 0.65);
    --erp-text-tertiary: rgba(255, 255, 255, 0.55);
    --erp-hover-bg: rgba(255, 255, 255, 0.08);
    --erp-hover-bg-soft: rgba(255, 255, 255, 0.04);
    --erp-tab-active-bg: rgba(22, 119, 255, 0.18);
    --erp-primary-bg: rgba(22, 119, 255, 0.22);
}

/* 暗色下平台标签：底色加浓、文字提亮，避免浅彩字压在深底上看不清。 */
body.erp-dark .erp-pos-plat.is-tianma,
body.erp-dark .erp-pos-tag.is-tianma {
    color: #69b1ff;
    background: rgba(22, 119, 255, .25);
    border-color: rgba(22, 119, 255, .55);
}

body.erp-dark .erp-pos-plat.is-duobao,
body.erp-dark .erp-pos-tag.is-duobao {
    color: #95de64;
    background: rgba(82, 196, 26, .25);
    border-color: rgba(82, 196, 26, .50);
}

body.erp-dark .erp-pos-plat.is-maiju,
body.erp-dark .erp-pos-tag.is-maiju {
    color: #ffc069;
    background: rgba(250, 140, 22, .25);
    border-color: rgba(250, 140, 22, .55);
}

body.erp-dark .erp-pos-plat.is-selfoperated,
body.erp-dark .erp-pos-tag.is-selfoperated {
    color: #b37feb;
    background: rgba(114, 46, 209, .28);
    border-color: rgba(114, 46, 209, .55);
}

/* antd 的 dark.css 没有把「禁用态文字」与「危险色」调亮：
   亮色下的禁用文字是 0.3 白、危险文字是深红 #a61d24，放到 #141414 / #1f1f1f 上几乎看不见，
   操作列的「修改 / 删除」会整片糊掉。这里在暗色下单独提亮。 */
body.erp-dark .ant-btn[disabled],
body.erp-dark .ant-btn[disabled] > span {
    color: rgba(255, 255, 255, 0.55);
}

body.erp-dark .ant-btn-dangerous:not([disabled]),
body.erp-dark .ant-btn-dangerous:not([disabled]) > span,
body.erp-dark .ant-typography-danger {
    color: #ff7875;
}

body.erp-dark .ant-btn-dangerous:not([disabled]):hover,
body.erp-dark .ant-btn-dangerous:not([disabled]):hover > span {
    color: #ffa39e;
}

/* 占位文字与面包屑分隔符用的是 0.3 / 0.45 白，深底上同样偏暗。 */
body.erp-dark .ant-select-selection-placeholder,
body.erp-dark .ant-input::placeholder,
body.erp-dark .ant-input-number-input::placeholder {
    color: rgba(255, 255, 255, 0.5);
}

body.erp-dark .ant-breadcrumb-separator {
    color: rgba(255, 255, 255, 0.55);
}

/* Message / Notification 的底板是写死的白底黑字，暗色下会变成一块突兀的白条。 */
body.erp-dark .ant-message-notice-content,
body.erp-dark .ant-notification-notice {
    background: var(--erp-surface);
    color: var(--erp-text);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.5);
}

html,
body,
#app {
    height: 100%;
    margin: 0;
    padding: 0;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
}

/* ---------- 首屏加载页 / 登录页：整屏磨砂背景（100% 视口铺满） ---------- */

/* 全屏底：作为模糊色斑与磨砂蒙版的定位容器。 */
.app-loading,
.login-page {
    position: relative;
    width: 100%;
    height: 100vh;
    overflow: hidden;
}

/* 启动加载页：底色「蓝（左上）→ 紫（右下）」。 */
.app-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    background: linear-gradient(135deg, #eef4ff 0%, #f7f8fc 48%, #f3f0ff 100%);
}

/* 登录页底色：与加载页互换，改为「紫（左上）→ 蓝（右下）」。 */
.login-page {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    overflow-y: auto;
    overflow-x: hidden;
    background: linear-gradient(135deg, #f3f0ff 0%, #f8f7fd 48%, #eef4ff 100%);
}

/* 模糊色斑层：伪元素 + 多重径向渐变，绝对定位不参与弹性布局。
   径向渐变自带柔和边缘，无需再叠 filter: blur。 */
.app-loading::before,
.login-page::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
}

/* 加载页色斑：左上蓝、右下紫。rgba 收尾避免 Safari 把 transparent 插值成灰色。 */
.app-loading::before {
    background:
        radial-gradient(620px 620px at 6% 0%, rgba(91, 140, 255, 0.5), rgba(91, 140, 255, 0) 68%),
        radial-gradient(700px 700px at 98% 104%, rgba(169, 140, 255, 0.5), rgba(169, 140, 255, 0) 68%);
}

/* 登录页色斑：左上紫、右下蓝，与加载页互为镜像。 */
.login-page::before {
    background:
        radial-gradient(620px 620px at 6% 0%, rgba(169, 140, 255, 0.5), rgba(169, 140, 255, 0) 68%),
        radial-gradient(700px 700px at 98% 104%, rgba(91, 140, 255, 0.5), rgba(91, 140, 255, 0) 68%);
}

/* 底部现代磨砂蒙版：backdrop-filter 让下层色斑呈现毛玻璃质感。 */
.app-loading::after,
.login-page::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1;
    height: 38%;
    pointer-events: none;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.42) 55%, rgba(255, 255, 255, 0.72) 100%);
    backdrop-filter: blur(40px) saturate(160%);
    -webkit-backdrop-filter: blur(40px) saturate(160%);
    /* 顶部渐隐遮罩：让模糊强度平滑过渡，避免出现生硬分界线。 */
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 30%, #000 100%);
    mask-image: linear-gradient(180deg, transparent 0%, #000 30%, #000 100%);
}

.app-loading-body,
.app-loading-footer {
    position: relative;
    z-index: 2;
}

.app-loading-body {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.app-loading-title {
    font-size: 32px;
    font-weight: 600;
    margin: 0 0 16px;
}

/* Spin 提示文字与指示器之间的留白（index.html 静态骨架与 <Spin Tip> 共用）。 */
.app-loading-body .ant-spin-text {
    margin-top: 10px;
    font-size: 13px;
    color: rgba(0, 0, 0, 0.45);
}

.app-loading-footer {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 48px;
    color: rgba(0, 0, 0, 0.45);
}

.app-loading-footer img {
    width: 24px;
    height: 24px;
}

/* 登录表单容器：置于色斑与磨砂蒙版之上，宽度自适应视口。 */
.login-box {
    position: relative;
    z-index: 2;
    width: min(400px, 100%);
}

/* ---------- 顶栏：左侧操作区 + 面包屑 ---------- */

.erp-header-bar {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: flex-start;
    gap: 16px;
    width: 100%;
    min-width: 0;
    height: 100%;
}

/* 左侧操作区：固定宽度（不收缩），面包屑变长也不会挤动按钮。 */
.erp-header-actions {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 16px;
}

.erp-header-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    font-size: 16px;
    color: var(--erp-text);
    cursor: pointer;
    transition: color 0.2s;
}

.erp-header-action:hover {
    color: var(--ant-primary-color);
}

/* 顶栏「导入中」角标：后台导入可能跑几分钟，关掉弹窗后靠它提示任务仍在跑。 */
.erp-header-import {
    position: relative;
    color: var(--ant-primary-color);
}

.erp-header-import-count {
    position: absolute;
    top: -3px;
    right: -7px;
    min-width: 14px;
    height: 14px;
    padding: 0 3px;
    border-radius: 7px;
    background: var(--ant-primary-color);
    color: #fff;
    font-size: 10px;
    line-height: 14px;
    text-align: center;
}

/* 面包屑：紧跟左侧操作区，超长时内部省略而不是换行。 */
.erp-breadcrumb {
    display: flex;
    flex: 0 1 auto;
    align-items: center;
    justify-content: flex-start;
    min-width: 0;
    margin: 0;
    overflow: hidden;
    white-space: nowrap;
}

.erp-breadcrumb > ol {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    min-width: 0;
    margin: 0;
    padding: 0;
    overflow: hidden;
    list-style: none;
}

.erp-breadcrumb > ol > li {
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
}

.erp-breadcrumb .ant-breadcrumb-link,
.erp-breadcrumb .ant-breadcrumb-separator {
    white-space: nowrap;
}

/* 链路文字统一次要色（antd 链接默认主色，这里要「面包屑」观感）。 */
.erp-breadcrumb .ant-breadcrumb-link {
    color: var(--erp-text-secondary);
}

.erp-breadcrumb .ant-breadcrumb-link > a {
    color: inherit;
    transition: color 0.2s;
}

.erp-breadcrumb .ant-breadcrumb-link > a:hover {
    color: var(--ant-primary-color);
}

/* 当前页（末级）：加重并与可跳转层级区分；过长省略而不是换行。 */
.erp-breadcrumb > ol > li:last-child {
    min-width: 0;
    overflow: hidden;
}

.erp-breadcrumb > ol > li:last-child .ant-breadcrumb-link {
    overflow: hidden;
    color: var(--erp-text);
    font-weight: 500;
    text-overflow: ellipsis;
}

@media (max-width: 768px) {
    .erp-header-bar {
        gap: 8px;
    }

    .erp-header-actions {
        gap: 12px;
    }

    /* 窄屏隐藏首页面包屑，保留信息量更大的当前链路 */
    .erp-breadcrumb > ol > li:first-child {
        display: none;
    }
}

/* ---------- 顶栏：图标按钮与用户区 ---------- */

.action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 6px;
    border-radius: 6px;
    font-size: 16px;
    color: var(--erp-text-secondary);
    cursor: pointer;
    transition: background-color 0.2s, color 0.2s;
}

.action:hover {
    background: var(--erp-hover-bg);
    color: var(--erp-primary);
}

/* 侧栏底部的折叠按钮：折叠入口已放在顶栏，隐藏避免重复。 */
.ant-pro-sider-collapsed-button {
    display: none;
}

/* 顶栏余额：数字是主信息，刷新图标默认藏起来（鼠标移上去才淡入）——
   顶栏横向空间有限，图标常驻会把余额挤得局促，而刷新是低频动作。
   数字用 tabular-nums：等宽数字，刷新时不会左右跳动。 */
.erp-header-balance {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border-radius: 6px;
    font-size: 14px;
    color: var(--erp-text-secondary);
    cursor: pointer;
    transition: background-color 0.2s, color 0.2s;
}

.erp-header-balance:hover {
    background: var(--erp-hover-bg);
    color: var(--erp-primary);
}

/* 账户名与金额并排：顶栏只摆一个金额说不清这是哪个账号的钱
   （页面上还有结算、运费等一堆金额），所以把「鞋运宝余额」也写上去。 */
.erp-header-balance-label {
    font-size: 13px;
    white-space: nowrap;
}

.erp-header-balance-value {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--erp-text);
}

.erp-header-balance-reload {
    font-size: 12px;
    opacity: 0;
    transition: opacity 0.2s;
}

.erp-header-balance:hover .erp-header-balance-reload {
    opacity: 0.6;
}

.header-action {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border-radius: 6px;
    font-size: 14px;
    color: var(--erp-text-secondary);
    cursor: pointer;
    transition: background-color 0.2s, color 0.2s;
}

.header-action:hover {
    background: var(--erp-hover-bg);
    color: var(--erp-primary);
}

.header-user {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 4px 8px;
    border-radius: 6px;
    cursor: pointer;
    transition: background-color 0.2s;
}

.header-user:hover {
    background: var(--erp-hover-bg);
}

.header-user-avatar {
    flex: none;
    width: 28px;
    height: 28px;
    line-height: 28px;
    font-size: 13px;
}

.header-user-name {
    max-width: 140px;
    overflow: hidden;
    font-size: 14px;
    color: var(--erp-text-secondary);
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* 用户下拉头部的资料卡与分隔线。 */
.user-card {
    padding: 2px 0;
}

.user-card-name {
    font-weight: 600;
    color: var(--erp-text);
}

.user-card-desc {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

.menu-divider {
    height: 1px;
    margin: 2px 0;
    background: var(--erp-divider);
}

/* 固定下拉宽度：保证整行用户名完整展示。 */
.erp-user-dropdown .ant-dropdown-menu {
    min-width: 240px;
}

.erp-user-dropdown .ant-dropdown-menu-item {
    padding: 6px 12px;
}

.erp-user-dropdown .user-card-name {
    max-width: none;
    white-space: nowrap;
}

/* ---------- 顶部固定多页签 ---------- */

/* 页签 + 内容区整体容器：负外边距抵消 ProLayout 内容区默认的 24px 外边距，使页签栏贴顶满宽。 */
.erp-page-wrap {
    margin: -24px;
}

/* 页签栏：白底 + 底部 1px 分隔线，扁平无阴影。
   用 stretch 让页签撑满栏高，使激活指示条能贴在栏底分隔线上。 */
.erp-tabs-bar {
    display: flex;
    align-items: stretch;
    gap: 8px;
    height: 40px;
    padding: 0 12px;
    background: var(--erp-surface);
    border-bottom: 1px solid var(--erp-border);
}

/* 页签列表：超出宽度时横向滚动，不换行。 */
.erp-tabs-list {
    display: flex;
    flex: 1 1 auto;
    align-items: stretch;
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
    white-space: nowrap;
}

.erp-tabs-list::-webkit-scrollbar {
    height: 0;
}

/* 单个页签：扁平化——无边框、无圆角、无实心填充，状态只靠文字色与底部指示条表达。 */
.erp-tab {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: none;
    height: 100%;
    padding: 0 16px;
    border: none;
    border-radius: 0;
    background: transparent;
    font-size: 13px;
    color: var(--erp-text-secondary);
    cursor: pointer;
    user-select: none;
    transition: color 0.2s, background-color 0.2s;
}

.erp-tab:hover {
    color: var(--erp-primary);
    background: var(--erp-hover-bg-soft);
}

/* 底部指示条：默认透明，激活时显示。 */
.erp-tab::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: var(--erp-primary);
    opacity: 0;
    transition: opacity 0.2s;
}

.erp-tab-active {
    color: var(--erp-primary);
    background: var(--erp-tab-active-bg);
}

.erp-tab-active::after {
    opacity: 1;
}

.erp-tab-title {
    max-width: 160px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* 页签关闭图标：默认弱化，悬停页签时提亮。 */
.erp-tab-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    font-size: 10px;
    color: var(--erp-text-tertiary);
    opacity: 0.45;
    transition: opacity 0.2s, color 0.2s;
}

.erp-tab:hover .erp-tab-close {
    opacity: 1;
}

.erp-tab-close:hover {
    color: #ff4d4f;
}

/* 用户手工固定的页签：标题前的小图钉，顺带解释它为什么没有关闭按钮。 */
.erp-tab-pin {
    flex: none;
    font-size: 11px;
    color: var(--erp-text-tertiary);
}

.erp-tab-active .erp-tab-pin {
    color: var(--erp-primary);
}

/* 「更多」入口：扁平方形，悬停浅灰底。 */
.erp-tabs-more {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    align-self: center;
    width: 28px;
    height: 28px;
    margin: 2px 0;
    font-size: 14px;
    line-height: 1;
    color: var(--erp-text-secondary);
    cursor: pointer;
    transition: background-color 0.2s, color 0.2s;
}

.erp-tabs-more > .anticon {
    display: flex;
    align-items: center;
    justify-content: center;
}

.erp-tabs-more:hover {
    background: var(--erp-hover-bg);
    color: var(--erp-primary);
}

/* 每个页签外面套了一层 antd 的右键触发器 div（.ant-dropdown-trigger）：
   让包装层也撑满栏高且不参与收缩，否则页签一多会被压扁而不是横向滚动。 */
.erp-tabs-bar .ant-dropdown-trigger {
    display: flex;
    align-items: center;
    flex: none;
}

/* 页签右键菜单与「更多」菜单：antd 下拉菜单项默认不是 flex，图标会紧贴文字。 */
.erp-tab-menu .ant-dropdown-menu-item,
.erp-tabs-more-menu .ant-dropdown-menu-item,
.erp-more-menu .ant-dropdown-menu-item {
    display: flex;
    align-items: center;
    gap: 8px;
}

.erp-tabs-more-menu {
    min-width: 180px;
    max-height: 360px;
    overflow-y: auto;
}

.erp-tabs-more-title {
    flex: 1 1 auto;
    min-width: 0;
    max-width: 240px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* ---------- 内容区 ---------- */

/* 高度由 JS 在首次渲染时计算一次并写死；四周统一 5px 内边距。 */
/* 页面容器：flex 列布局。外层高度由 AdminLayout 的 JS 算好，页面根作为子项撑满它，
   滚动交给页面内部的内容区 —— 否则「外层滚 + 内容区滚」就会长出两条竖向滚动条。
   overflow 保留 auto 作兜底：万一某页内容真的超高，仍能滚，不会被裁掉。 */
.erp-page-body {
    display: flex;
    flex-direction: column;
    padding: 5px;
    overflow: auto;
    background: var(--erp-layout-bg);
}

/* 页面根撑满剩余高度。min-height:0 是必需的，否则 flex 子项按内容高度撑开、把外层顶出滚动条。 */
#erp-page-body > * {
    flex: 1;
    min-height: 0;
}

/* 清零 ProLayout 自带的页容器外边距（含 -24px 负外边距）与内容子容器的 24px 外边距，
   保证页面内容距窗口边缘就是 .erp-page-body 的 5px。
   必须用后代选择器：children-content 并不是 page-container 的直接子级。 */
#erp-page-body .ant-pro-page-container,
#erp-page-body .ant-pro-page-container-children-content {
    margin: 0;
}

/* 页面标题已由顶部多页签统一展示，隐藏 PageContainer 自带页头，避免与页签标题重复。 */
.erp-page-body .ant-pro-page-container-warp {
    display: none;
}

/* 页脚整体移除：同时屏蔽 ProLayout 未传 FooterRender 时回退的默认页脚。 */
.ant-pro-global-footer {
    display: none;
}

/* ProLayout 顶栏底色写死白色：整站暗色时官方 dark.css 会把文字转成浅色，
   白底 + 浅色文字 = 顶栏按钮与用户名全部隐形，这里改成跟随语义色反转。 */
.ant-pro-global-header {
    background: var(--erp-surface);
}

/* 混合布局的顶栏本身是深色，文字与图标必须反白。 */
.ant-pro-global-header-layout-mix {
    background-color: #001529;
}

.ant-pro-global-header-layout-mix .action,
.ant-pro-global-header-layout-mix .header-action,
.ant-pro-global-header-layout-mix .header-user-name {
    color: rgba(255, 255, 255, 0.85);
}

.ant-pro-global-header-layout-mix .action:hover,
.ant-pro-global-header-layout-mix .header-action:hover,
.ant-pro-global-header-layout-mix .header-user:hover {
    background: rgba(255, 255, 255, 0.08);
}

/* ---------- 登录页 ---------- */

.login-brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    margin-bottom: 24px;
}

.login-brand-logo {
    width: 48px;
    height: 48px;
}

.login-brand-title {
    font-size: 22px;
    font-weight: 600;
    color: rgba(0, 0, 0, 0.85);
}

.login-brand-desc {
    font-size: 13px;
    color: rgba(0, 0, 0, 0.45);
}

/* 邮箱登录的「验证码 + 获取验证码」：输入框吃掉剩余宽度，按钮按内容宽。 */
.login-code {
    display: flex;
    gap: 8px;
    margin-bottom: 16px;
}

.login-code > .ant-input {
    flex: 1;
    min-width: 0;
}

.login-code > .ant-btn {
    flex: none;
}

.login-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 20px;
}

.login-remember {
    display: inline-flex;
    align-items: center;
}

.login-remember-text {
    margin-left: 8px;
    color: var(--erp-text-secondary);
}

.login-more {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    margin-top: 24px;
    /* 给固定在视口底部的页脚留出空间，避免两者在矮屏上叠在一起 */
    margin-bottom: 64px;
    color: rgba(0, 0, 0, 0.45);
}

.login-more span {
    cursor: pointer;
}

.login-footer {
    /* 钉在视口底部，体现 100% 全屏布局；置于磨砂蒙版之上。 */
    position: fixed;
    left: 0;
    right: 0;
    bottom: 24px;
    z-index: 2;
    text-align: center;
    font-size: 12px;
    color: rgba(0, 0, 0, 0.45);
}

.login-footer-copy {
    font-size: 13px;
    color: rgba(0, 0, 0, 0.45);
}

/* 备案号：没配就不渲染这一行，所以样式里不用为「占位」留位置。 */
.login-footer-icp {
    margin-top: 4px;
    font-size: 12px;
    color: rgba(0, 0, 0, 0.45);
}

.login-footer-meta {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    margin-top: 8px;
    color: rgba(0, 0, 0, 0.3);
}

/* ---------- 站点信息页：登录页效果预览 ---------- */

/* 按登录页品牌区 + 页脚的排版原样抄一份：站名改错字、Logo 路径填错，
   保存前在这一块就能看出来，不用先登出再打开登录页确认。 */
.erp-site-preview {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 4px;
}

.erp-site-preview-head {
    font-size: 13px;
    font-weight: 600;
}

.erp-site-preview-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 24px 12px 16px;
    background: var(--erp-surface-alt);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
}

.erp-site-preview-logo {
    width: 48px;
    height: 48px;
    object-fit: contain;
}

.erp-site-preview-name {
    font-size: 22px;
    font-weight: 600;
}

.erp-site-preview-slogan {
    font-size: 13px;
    color: var(--erp-text-secondary);
}

.erp-site-preview-footer {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    margin-top: 12px;
    font-size: 12px;
    color: var(--erp-text-secondary);
}

/* 后台布局的全局页脚：只放备案号，没备案时整块不渲染。 */
.erp-global-footer {
    text-align: center;
    font-size: 12px;
    color: var(--erp-text-secondary);
}

/* ---------- 主题设置抽屉 ---------- */

.erp-setting {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.erp-setting-hint {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    color: var(--erp-text-secondary);
    font-size: 12px;
    background: var(--erp-layout-bg);
    border-radius: 6px;
}

.erp-setting-title {
    margin-bottom: 10px;
    color: var(--erp-text);
    font-size: 14px;
}

.erp-thumb-list {
    display: flex;
    gap: 12px;
}

.erp-thumb {
    cursor: pointer;
}

/* 缩略图画布：用渐变画出「侧栏 / 顶栏」的位置，一眼看出布局差异。 */
.erp-thumb-preview {
    position: relative;
    width: 64px;
    height: 46px;
    overflow: hidden;
    background-color: var(--erp-surface);
    border-radius: 4px;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
    --erp-sider: #d9d9d9;
    --erp-top: #d9d9d9;
}

.erp-thumb-side {
    background-image: linear-gradient(to right, var(--erp-sider) 0 16px, var(--erp-surface) 16px);
}

.erp-thumb-mix {
    background-image:
        linear-gradient(to bottom, var(--erp-top) 0 14px, transparent 14px),
        linear-gradient(to right, var(--erp-sider) 0 16px, var(--erp-surface) 16px);
}

.erp-thumb-dark {
    --erp-sider: #001529;
    --erp-top: #001529;
}

.erp-thumb-active .erp-thumb-preview {
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08), 0 0 0 2px var(--erp-primary);
}

.erp-thumb-check {
    position: absolute;
    top: 3px;
    right: 4px;
    color: var(--erp-primary);
    font-size: 13px;
}

.erp-thumb-label {
    margin-top: 6px;
    color: var(--erp-text-secondary);
    font-size: 12px;
    text-align: center;
}

.erp-color-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.erp-color {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 22px;
    color: #fff;
    border-radius: 4px;
    cursor: pointer;
}

.erp-color-active {
    box-shadow: 0 0 0 2px var(--erp-surface), 0 0 0 3px var(--erp-primary);
}

.erp-setting-rows {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.erp-setting-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    color: var(--erp-text);
}

/* ---------- 菜单搜索 ---------- */

.erp-menu-search {
    cursor: pointer;
}

.erp-menu-search-item {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* ---------- 工具栏 ---------- */

.erp-page-toolbar {
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--erp-surface);
    padding-bottom: 8px;
}

.erp-toolbar-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.erp-toolbar-main {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    flex: 1;
}

.erp-toolbar-keyword {
    width: 260px;
}

.erp-toolbar-fields {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    flex-wrap: wrap;
    padding-top: 12px;
}

.erp-toolbar-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 13px;
    color: var(--erp-text-secondary);
}

.erp-toolbar-field-actions {
    display: flex;
    gap: 8px;
}

/* 工具栏里的行内标签：与 .erp-toolbar-field 里的 <span> 同字号同色，
   区别只是这个跟着控件在同一行（竖排字段组用于「更多搜索」里的筛选项）。 */
.erp-toolbar-label {
    font-size: 13px;
    color: var(--erp-text-secondary);
}

.erp-toolbar-selected {
    color: var(--erp-text-tertiary);
    font-size: 13px;
}

    /* 「其中 N 行已进结算单，不能改」：跟在「已选 N 行」后面，
       橙色是因为它说的是**为什么这一排按钮全灰了** —— 不写出来人只会以为功能坏了。 */
    .erp-toolbar-selected.is-locked {
        color: #d46b08;
    }

/* 订单列表的「图片列」：这一屏唯一能看见货的地方，点开是商品详情抽屉。
   列宽 56、图 40：再大会把行撑高（一行里还有两排字），再小就看不清鞋了。 */
.erp-order-pic {
    display: block;
    width: 40px;
    height: 40px;
    object-fit: contain;
    background: var(--erp-surface-alt);
    border-radius: 4px;
    cursor: pointer;
}

    /* 没图的行：留一个同尺寸的空格，不画「无图」灰块 ——
       一页二十行里半数没图时，画满灰块这一列就变成了噪音。 */
    .erp-order-pic.is-empty {
        cursor: default;
        background: none;
    }

/* 默认筛选说明：默认条件藏在折叠的「更多搜索」里时，必须说出来。 */
.erp-summary-hint {
    margin-bottom: 6px;
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

/* 未勾选行时的提示：批量按钮整排置灰，不说明原因会被当成「没这个功能」。 */
.erp-toolbar-hint {
    color: var(--erp-text-tertiary);
    font-size: 13px;
    opacity: 0.7;
}

/* ---------- 表单与表格 ---------- */

.erp-form {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.erp-form-item {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.erp-form-item > label {
    font-size: 13px;
    color: var(--erp-text-secondary);
}

/* 开关一律不许占整行：.erp-form-item / .erp-toolbar-field 都是竖排 flex（column），
   align-items 默认 stretch 会把 Switch 横向拉成一根长条，看着像输入框而不是开关。
   这里统一按内容宽、靠左放 —— 业务页不用再为「开关要不要包一层」费心。
   开关要么与说明文字同行（.erp-form-switch-item），要么就只占自己那点宽。 */
.erp-form-item > .ant-switch,
.erp-toolbar-field > .ant-switch {
    align-self: flex-start;
    flex: none;
    width: auto;
}

/* 一行放多个表单项：宽度不够自动换行。
   用来把开关、短输入这类窄控件并进同一行，避免它们各自独占一行拉长表单。 */
.erp-form-row {
    display: flex;
    flex-wrap: wrap;
    gap: 12px 16px;
}

.erp-form-row > .erp-form-item {
    flex: 1 1 200px;
    min-width: 0;
}

/* 同行里的开关：带 label 的输入项比它高，底部对齐才不会看着悬空。 */
.erp-form-row > .erp-form-switch-item {
    align-self: flex-end;
    padding-bottom: 4px;
}

/* 开关组：开关本身很窄，横向排列并允许换行，组内每项「文案 + 开关」横向对齐。 */
.erp-form-switch-group {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 24px;
}

.erp-form-switch-item {
    display: flex;
    align-items: center;
    gap: 8px;
}

.erp-form-switch-item > label {
    font-size: 13px;
    color: var(--erp-text-secondary);
    white-space: nowrap;
}

.erp-form-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 16px;
}

.erp-pager {
    display: flex;
    justify-content: flex-end;
    padding-top: 12px;
}

.erp-antd-table .ant-table-thead > tr > th {
    background: var(--erp-surface-alt);
}

/* 选择列宽度兜底：AntDesign 的 <Selection> 不传 Width 时，colgroup 出的 <col> 不带宽度，
   而 antd 自己的样式对这个类也没有宽度定义 ⇒ ScrollX（table-layout: fixed）下选择列被压到
   近乎 0 宽，复选框溢出压到第一列的文字上（2026-10-10 截图实测）。
   ErpTable 已显式 Width="32px"，这里兜住直接用 <Table> + <Selection> 的页面。 */
.ant-table-selection-col,
.ant-table-selection-column {
    width: 32px;
    min-width: 32px;
}

.ant-table-selection-column {
    text-align: center;
}

/* 表格容器：撑满页面容器，滚动条留在表格体内，表头固定。
   关键点：从 .ant-table-wrapper 到 .ant-table-body 每一层都要 flex + min-height:0，
   缺任何一层，flex 子项都会按内容高度撑开，表格就会溢出到页面容器外面。 */
.erp-table-wrap {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 240px;
}

/* 表格外还套了 spin 加载层（.ant-table-spin-wrapper → 匿名 div → .ant-spin-container），
   这几层默认不是 flex，高度链会断在「内容高度」上，必须逐层补齐才能把剩余高度传给表格体。 */
/* 高度链：表格外面多套了一层遮罩宿主，flex 链必须把它也算进去，否则剩余高度传不到表格体。 */
.erp-table-wrap > .erp-table-mask-host,
.erp-table-wrap .ant-table-wrapper,
.erp-table-wrap .ant-table-spin-wrapper,
.erp-table-wrap .ant-table-spin-wrapper > div,
.erp-table-wrap .ant-spin-container {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-height: 0;
}

/* 遮罩的定位上下文：只包住表格体，分页条留在外面，翻页时不会被盖住。 */
.erp-table-mask-host {
    position: relative;
}

/* 磨砂加载遮罩：半透明底 + 背景模糊，靠 opacity 过渡淡入淡出，
   不做 pointer-events:none —— 加载期间应当挡住误点。 */
.erp-table-mask,
.erp-drawer-mask {
    position: absolute;
    inset: 0;
    z-index: 8;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    border-radius: var(--erp-radius);
    background: rgba(255, 255, 255, 0.45);
    backdrop-filter: blur(3px) saturate(120%);
    -webkit-backdrop-filter: blur(3px) saturate(120%);
    opacity: 0;
    transition: opacity 0.22s ease;
}

.erp-table-mask.is-active,
.erp-drawer-mask.is-active {
    opacity: 1;
}

.erp-table-mask-text,
.erp-drawer-mask-text {
    font-size: 13px;
    color: var(--erp-text-secondary);
}

body.erp-dark .erp-table-mask,
body.erp-dark .erp-drawer-mask {
    background: rgba(0, 0, 0, 0.35);
}

.erp-table-wrap .ant-table {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-height: 0;
}

.erp-table-wrap .ant-table-container {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-height: 0;
}

.erp-table-wrap .ant-table-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

.erp-table-wrap .erp-pager {
    flex: none;
}

.erp-content-card {
    background: var(--erp-surface);
    border-radius: var(--erp-radius);
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    height: 100%;
    min-height: 100%;
}

/* 卡片内除表格外的部分（搜索工具栏等）按内容高度，剩下的全给表格，
   表格才能在卡片内滚动而不是把卡片撑高溢出页面容器。 */
.erp-content-card > *:not(.erp-table-wrap) {
    flex: none;
}

.erp-content-card > .erp-table-wrap {
    flex: 1;
    min-height: 0;
}

/* ---------- 汇总统计行与导入弹窗 ---------- */

.erp-summary-line {
    color: var(--erp-text-secondary);
    font-size: 13px;
}

/* ---------- 物流轨迹（快递物流详情抽屉） ---------- */

/* 自排时间轴，不用 AntDesign Timeline：它的 Label 是绝对定位，
   渠道的长说明（「快递员信息,揽件员:… 取件码:…」）会压到时间与下一行上，两条轨迹叠成一团。
   结构 = 左侧一条竖轴 + 每项一个圆点，右侧「时间在上、说明在下」。 */
.erp-trace-list {
    margin: 6px 0 16px;
    padding: 0 4px 0 2px;
    list-style: none;
    /* 轨迹可能有几十条：限高内滚，别把下方的寄收件与货品清单推得太远。 */
    max-height: 320px;
    overflow-y: auto;
}

.erp-trace-item {
    position: relative;
    padding: 0 0 14px 20px;
}

/* 竖轴：最后一项不再往下画。 */
.erp-trace-item::before {
    content: "";
    position: absolute;
    top: 13px;
    bottom: 0;
    left: 5px;
    width: 1px;
    background: var(--erp-border-strong);
}

.erp-trace-item:last-child {
    padding-bottom: 0;
}

.erp-trace-item:last-child::before {
    display: none;
}

.erp-trace-dot {
    position: absolute;
    top: 5px;
    left: 2px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--erp-border-strong);
}

/* 最新一条（倒序后的第一条）高亮：这才是「货现在到哪了」。 */
.erp-trace-item:first-child .erp-trace-dot {
    background: var(--erp-primary);
    box-shadow: 0 0 0 3px var(--erp-primary-bg);
}

.erp-trace-item:first-child .erp-trace-desc {
    font-weight: 600;
}

.erp-trace-body {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.erp-trace-time {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

.erp-trace-desc {
    font-size: 13px;
    line-height: 1.6;
    color: var(--erp-text);
    /* 渠道说明是一长串没有空格的中文 + 全角括号：必须允许任意位置折行，
       否则在抽屉里横向溢出，右边整段被裁掉。 */
    overflow-wrap: anywhere;
}

/* ---------- 快递物流详情抽屉：抬头 / 寄收货 / 紧凑元信息 ---------- */

/* 遮罩宿主：加载态盖在这一层上。给个底高，加载时内容还没渲染，遮罩才不会缩成一条。 */
.erp-detail-body {
    position: relative;
    min-height: 160px;
}

/* 抬头：运单号 + 状态是主信息，快递公司压成小字（顺丰 / 菜鸟的详情头也是这个层次）。 */
.erp-express-head {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--erp-border);
}

.erp-express-head-main {
    display: flex;
    align-items: center;
    gap: 10px;
}

.erp-express-no {
    font-size: 16px;
    font-weight: 600;
    color: var(--erp-text);
    word-break: break-all;
}

.erp-express-head-sub {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

/* 寄 → 收并排：快递详情的通行排法（左右两块 + 中间箭头）。 */
.erp-express-route {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 0;
    border-bottom: 1px solid var(--erp-border);
}

.erp-express-party {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    flex: 1 1 0;
    min-width: 0;
}

.erp-express-role {
    flex: none;
    width: 20px;
    height: 20px;
    margin-top: 1px;
    border-radius: 50%;
    font-size: 11px;
    line-height: 20px;
    text-align: center;
    color: #fff;
    background: var(--erp-border-strong);
}

/* 收件是核对时看得最多的那一块，圆点用主色点出来。 */
.erp-express-party.is-receiver .erp-express-role {
    background: var(--erp-primary);
}

.erp-express-party-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

/* 名称 + 电话一行、地址一行：三行压成两行，
   760 宽的抽屉里省出来的高度正好给下面的物流轨迹。 */
.erp-express-who {
    font-size: 13px;
    font-weight: 600;
    color: var(--erp-text);
}

.erp-express-who > b {
    margin-left: 6px;
    font-weight: 400;
    color: var(--erp-text-secondary);
}

.erp-express-addr {
    font-size: 12px;
    line-height: 1.5;
    color: var(--erp-text-secondary);
    overflow-wrap: anywhere;
}

.erp-express-arrow {
    flex: none;
    font-size: 13px;
    color: var(--erp-text-tertiary);
}

/* 元信息一行铺开（放不下自动换行）：渠道 / 运费 / 计费重量 / 下单时间 / 渠道单号。 */
.erp-express-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 18px;
    padding-top: 10px;
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

.erp-express-meta > span > b {
    margin-left: 5px;
    font-weight: 500;
    color: var(--erp-text-secondary);
}

/* 抬头第二行：快递公司 · 平台 · 发货店铺。分隔点比靠 flex gap 更容易看出是三段独立信息。 */
.erp-express-sep {
    margin: 0 6px;
    color: var(--erp-border-strong);
}

.erp-express-head-sub > span > b {
    margin-left: 4px;
    font-weight: 500;
    color: var(--erp-text-secondary);
}

/* 地址块吃满剩余宽度 ⇒ 复制按钮自然被推到行尾。
   不用 margin-left:auto 推按钮：那样依赖按钮是 flex 直接子项，
   Tooltip 一旦额外包一层元素就失效（按钮会挤在地址右边）。 */
.erp-express-party > .erp-express-party-body {
    flex: 1 1 auto;
}

/* 复制按钮（运单号 / 寄收件信息 / 渠道单号）：行内小图标，不抢视线，划过才显主色。
   一面抽屉里四个共用这一套，别逐处调尺寸。 */
.erp-copy-btn.ant-btn {
    height: 20px;
    padding: 0 4px;
    font-size: 13px;
    color: var(--erp-text-tertiary);
}

.erp-copy-btn.ant-btn:hover {
    color: var(--erp-primary);
}

.erp-express-meta .erp-copy-btn.ant-btn {
    margin-left: 2px;
    vertical-align: -2px;
}

.erp-import-pick,
.erp-import-running {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* 拖入上传区：整块铺一层透明的 input[type=file]，拖进来的文件由浏览器直接交给它。
   没有这层就只能写 JS 去接 DataTransfer.files —— Blazor 的 DragEventArgs 拿不到文件对象。 */
.erp-drop-zone {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 22px 16px;
    border: 1px dashed var(--erp-border-strong);
    border-radius: var(--erp-radius);
    background: var(--erp-surface-alt);
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.erp-drop-zone:hover,
.erp-drop-zone.is-over {
    border-color: var(--erp-primary);
    background: var(--erp-primary-bg);
}

/* 铺满整块：点击与拖放都落在它身上。
   z-index 必须给：同层里后面渲染的文字块会盖住它（虽然已设 pointer-events:none，
   但保险起见让 input 明确在最上层）。
   注意：外层容器上**不要**对 dragover / drop 做 preventDefault —— 文件进到 input 靠的正是
   drop 的默认行为，取消它就会出现「点击能选、拖入没反应」（2026-10-10 实测）。 */
.erp-drop-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
    z-index: 2;
}

/* 提示内容不接事件，否则会挡住底下的 input */
.erp-drop-body {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    text-align: center;
    pointer-events: none;
}

.erp-drop-body .anticon {
    font-size: 26px;
    color: var(--erp-text-tertiary);
}

.erp-drop-text {
    margin: 0;
    font-size: 13px;
}

.erp-drop-hint {
    margin: 0;
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

/* Drag 模式下组件把 input[type=file] 以 absolute + 100%/100% + 透明铺在选择区上，
   用来同时接管点击与拖放。它的定位上下文必须是这个 span；span 若不是 relative，
   input 就会相对更外层定位、盖住弹窗里的其它按钮（表现为按钮点不动，只弹文件框）。 */
.erp-import-uploader {
    margin-bottom: 8px;
}

.erp-import-uploader .ant-upload-drag {
    position: relative;
}

/* 非「选文件」阶段把上传区收起来，但元素必须留在 DOM 里：
   组件卸载后它内部的 input 就没了，上传时会拿到 null 的 element。 */
.erp-import-uploader.is-hidden {
    display: none;
}

/* 拖拽上传区：组件只负责把 input 铺满并接管拖放，尺寸和留白在这里给。
   点选与拖入落在同一块足够大的区域上，提示文案也集中在这一块里。 */
.erp-import-drop {
    padding: 24px 16px;
    text-align: center;
    background: var(--erp-surface);
    border: 1px dashed var(--erp-border-strong);
    border-radius: var(--erp-radius);
    transition: border-color 0.2s;
}

.erp-import-drop:hover {
    border-color: var(--ant-primary-color);
}

.erp-import-drop .ant-upload-drag-icon {
    margin: 0 0 8px;
    font-size: 32px;
    color: var(--ant-primary-color);
}

.erp-import-drop .ant-upload-text {
    margin: 0 0 4px;
    font-size: 14px;
}

.erp-import-drop .ant-upload-hint {
    margin: 0;
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

/* 已选文件行：选完立刻看到文件名与大小，并支持移除重选——
   没有它，「下一步」是盲点。 */
.erp-import-picked {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    font-size: 13px;
}

.erp-import-picked-name {
    flex: 1;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.erp-import-picked-size {
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

.erp-import-hint,
.erp-import-tip {
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

/* 模板填写要求：必填项与格式说明直接铺在选文件按钮上方，下载按钮就在一旁，
   不用先猜列长什么样、再去找模板在哪。 */
.erp-import-template {
    padding: 8px 10px;
    border-radius: 6px;
    background: var(--erp-hover-bg);
}

.erp-import-template-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 6px;
}

.erp-import-template-title {
    color: var(--erp-text);
    font-size: 13px;
    font-weight: 600;
}

.erp-import-columns {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* 名称定宽：标签与说明在同一竖线上，扫一眼就知道哪几列必填。 */
.erp-import-column {
    display: flex;
    align-items: baseline;
    gap: 8px;
    font-size: 12px;
}

.erp-import-column-name {
    min-width: 72px;
    color: var(--erp-text);
}

.erp-import-column-note {
    color: var(--erp-text-tertiary);
}

/* 顶栏导入任务清单 */
.erp-import-tasks {
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-width: 240px;
}

.erp-import-task-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 4px;
}

.erp-import-task-title {
    font-size: 13px;
}

.erp-import-task-stage,
.erp-import-task-tip {
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

.erp-import-task-tip {
    margin: 0;
}

.erp-import-file {
    color: var(--erp-text-secondary);
    font-size: 13px;
}

/* 上传 / 导入两段进度：各自一张卡片，标题右侧放各自的耗时，
   慢在「传文件」还是慢在「服务端写库」一眼就能比出来。 */
.erp-import-phase {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 8px 10px;
    border-radius: 6px;
    background: var(--erp-hover-bg);
}

.erp-import-phase-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.erp-import-phase-title {
    color: var(--erp-text);
    font-size: 13px;
    font-weight: 600;
}

.erp-import-phase-time {
    color: var(--erp-text-secondary);
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}

.erp-import-stage {
    color: var(--erp-text);
    font-size: 14px;
    font-weight: 600;
}

.erp-import-meta,
.erp-import-result {
    color: var(--erp-text-secondary);
    font-size: 13px;
}

.erp-import-errors {
    max-height: 160px;
    overflow: auto;
    padding: 8px;
    border-radius: var(--erp-radius);
    background: var(--erp-surface-alt);
    color: var(--erp-text-secondary);
    font-size: 12px;
}

/* ---------- 滚动条 ---------- */

::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

::-webkit-scrollbar-thumb {
    border-radius: 4px;
    background: rgba(0, 0, 0, 0.18);
}

::-webkit-scrollbar-thumb:hover {
    background: rgba(0, 0, 0, 0.3);
}

::-webkit-scrollbar-track {
    background: transparent;
}

/* ---------- 任务中心（仪表盘 / 临时任务 / 告警中心） ---------- */

/* 统计卡片：自适应列数，窄屏自动换行。颜色只用于表达「有没有问题」，
   不用彩色表达分类 —— 分类看标签就够了，颜色留给异常。 */
.erp-stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 12px;
    margin-bottom: 16px;
}

.erp-stat-card {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 12px 14px;
    background: var(--erp-surface-alt);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
}

.erp-stat-label {
    color: var(--erp-text-secondary);
    font-size: 12px;
}

.erp-stat-value {
    color: var(--erp-text);
    font-size: 22px;
    font-weight: 600;
    line-height: 1.25;
}

.erp-stat-hint {
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

/* 三档状态色：正在运行（信息）、有异常但可自愈（警告）、必须马上处理（危险）。
   底色用低透明度，暗色模式下也不会糊成一片。 */
.erp-stat-card.is-running {
    background: var(--erp-primary-bg);
    border-color: rgba(22, 119, 255, 0.35);
}

.erp-stat-card.is-running .erp-stat-value {
    color: var(--erp-primary);
}

.erp-stat-card.is-warning {
    background: rgba(250, 173, 20, 0.10);
    border-color: rgba(250, 173, 20, 0.35);
}

.erp-stat-card.is-warning .erp-stat-value {
    color: #d48806;
}

.erp-stat-card.is-danger {
    background: rgba(207, 19, 34, 0.08);
    border-color: rgba(207, 19, 34, 0.35);
}

.erp-stat-card.is-danger .erp-stat-value {
    color: #cf1322;
}

.erp-panel-title {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin: 4px 0 10px;
    color: var(--erp-text);
    font-size: 14px;
    font-weight: 600;
}

.erp-panel-title-hint {
    color: var(--erp-text-tertiary);
    font-size: 12px;
    font-weight: 400;
}

.erp-health-reason {
    color: var(--erp-text);
}

.erp-health-error {
    margin-top: 2px;
    overflow: hidden;
    color: var(--erp-text-tertiary);
    font-size: 12px;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* ---------- 鞋运宝余额抽屉（顶栏余额点开） ---------- */

/* 余额头：金额是主信息，分项与更新时间压成两行小字 ——
   点开抽屉第一眼要的是「还有多少钱」，分项是用来解释这个数的。 */
.erp-balance-head {
    padding-bottom: 8px;
    border-bottom: 1px solid var(--erp-border);
}

.erp-balance-total {
    display: flex;
    align-items: center;
    gap: 8px;
}

.erp-balance-label {
    color: var(--erp-text-secondary);
    font-size: 13px;
}

.erp-balance-value {
    color: var(--erp-text);
    font-size: 22px;
    font-weight: 600;
    /* 等宽数字：刷新时数字位数变了也不会左右跳动。 */
    font-variant-numeric: tabular-nums;
}

.erp-balance-sub,
.erp-balance-time {
    margin-top: 2px;
    line-height: 1.4;
    color: var(--erp-text-secondary);
    font-size: 12px;
}

.erp-balance-time {
    color: var(--erp-text-tertiary);
}

.erp-balance-title {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin: 10px 0 0;
    color: var(--erp-text);
    font-size: 14px;
    font-weight: 600;
}

.erp-balance-count {
    color: var(--erp-text-tertiary);
    font-size: 12px;
    font-weight: 400;
}

/* 流水区自己滚：抽屉高度有限，头部余额是常驻信息，不该被列表推走。
   position: relative 是给加载遮罩当宿主的（首屏加载时列表还没渲染）。 */
.erp-balance-scroll {
    position: relative;
    max-height: calc(100vh - 250px);
    min-height: 160px;
    overflow-y: auto;
}

/* 一行流水压到两行：说明 + 时间在左，金额 + 类型在右。
   间距给得小（7px）：一屏能多看几行，翻起来才像在「看流水」。 */
.erp-balance-log {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
    padding: 7px 0;
    border-bottom: 1px solid var(--erp-border);
}

.erp-balance-log-main {
    min-width: 0;
}

.erp-balance-log-remark {
    display: block;
    color: var(--erp-text);
    font-size: 13px;
    line-height: 1.4;
    /* 渠道说明是一整串中文 + 全角括号，没有可折行的空格。 */
    overflow-wrap: anywhere;
}

.erp-balance-log-time {
    display: block;
    margin-top: 1px;
    color: var(--erp-text-tertiary);
    font-size: 12px;
    line-height: 1.3;
    font-variant-numeric: tabular-nums;
}

.erp-balance-log-side {
    flex: none;
    text-align: right;
    white-space: nowrap;
}

/* 金额比正文大一号并且加粗：列表里扫的是「多少钱」，不是说明文字。 */
.erp-balance-money {
    font-size: 15px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* 支出用常规文本色、进账用绿色：一眼扫过去是「花出去的多还是退回来的多」，
   两种都上色反而看不出重点。 */
.erp-balance-money.is-expense {
    color: var(--erp-text);
}

.erp-balance-money.is-income {
    color: #52c41a;
}

/* 充值单独标红：这一行是「钱充进来没有」的凭据，混在一堆运费里最容易看漏。 */
.erp-balance-money.is-recharge {
    color: #cf1322;
}

.erp-balance-log-type {
    display: block;
    margin-top: 1px;
    color: var(--erp-text-tertiary);
    font-size: 12px;
    line-height: 1.3;
}

/* 类型标签跟着金额走：充值那一条整行都是红的，扫一遍就能定位到它。 */
.erp-balance-log-type.is-recharge {
    color: #cf1322;
}

/* 懒加载哨兵：1px 高的空行，滚到它就加载下一页。
   不占高度就不会在列表底部留一条空白缝。 */
.erp-balance-sentinel {
    height: 1px;
}

.erp-balance-more {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 0;
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

/* 工具条里的下拉：与输入框同高同宽体系，避免 select 与 Button 高度不一致 */
.erp-toolbar-select {
    width: 140px;
}

/* 临时任务列表的迷你进度条：表格行里放 antd Progress 太高，这里自绘一条细的 */
.erp-mini-progress {
    display: flex;
    align-items: center;
    gap: 8px;
}

.erp-mini-progress-track {
    flex: 1;
    height: 6px;
    background: var(--erp-hover-bg);
    border-radius: 3px;
    overflow: hidden;
}

.erp-mini-progress-bar {
    height: 100%;
    background: var(--erp-primary);
    border-radius: 3px;
    transition: width 0.3s;
}

.erp-mini-progress-text {
    width: 42px;
    color: var(--erp-text-secondary);
    font-size: 12px;
    text-align: right;
}

.erp-mini-progress-stage {
    margin-top: 2px;
    overflow: hidden;
    color: var(--erp-text-tertiary);
    font-size: 12px;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* 运行日志：固定高度内部滚动，长日志不把抽屉撑到屏幕外 */
.erp-log-view {
    max-height: 420px;
    overflow: auto;
}

.erp-log-view table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
}

.erp-log-view thead th {
    padding: 4px 6px;
    color: var(--erp-text-tertiary);
    font-weight: 500;
    text-align: left;
    border-bottom: 1px solid var(--erp-border);
}

.erp-log-view tbody td {
    padding: 4px 6px;
    border-top: 1px solid var(--erp-border);
    vertical-align: top;
}

.erp-log-message {
    white-space: pre-wrap;
    word-break: break-all;
}

.erp-log-message pre {
    margin: 4px 0 0;
    padding: 6px 8px;
    background: var(--erp-hover-bg);
    border-radius: 4px;
    font-size: 11px;
    white-space: pre-wrap;
    word-break: break-all;
}

.erp-log-empty {
    padding: 12px !important;
    color: var(--erp-text-tertiary);
    text-align: center;
}

/* 整行高亮：告警中心与仪表盘靠它把「还没处理的」从列表里拎出来。
   必须作用在 td 上 —— antd 表格自己给 td 设了底色，只给 tr 上色会被盖掉。

   **底色一律「不透明打底 + 淡色叠层」写，不能只写一个 rgba**：
   ① 固定列（选择列 / 操作列）是 sticky，靠自身背景盖住滚过去的列；
      底色只剩半透明时，底下那几列的文字会直接透上来
      —— 2026-10-10 截图：运单号穿过操作列的「已签收」标签（表头不穿透，因为它的底是实色）。
   ② 叠加写法（background-color + background-image: linear-gradient）渲染出来的像素
      与原来的 rgba 叠在白底上完全一致，只是不再透光。
   以后再加行色，照这个写法抄。 */
.erp-antd-table tr.erp-row-danger > td {
    background-color: var(--erp-surface);
    background-image: linear-gradient(rgba(207, 19, 34, 0.07), rgba(207, 19, 34, 0.07));
}

.erp-antd-table tr.erp-row-warning > td {
    background-color: var(--erp-surface);
    background-image: linear-gradient(rgba(250, 173, 20, 0.09), rgba(250, 173, 20, 0.09));
}

.erp-antd-table tr.erp-row-stale > td {
    background-color: var(--erp-surface);
    background-image: linear-gradient(rgba(207, 19, 34, 0.14), rgba(207, 19, 34, 0.14));
}

/* 重复批次文字高亮（取代整行背景色）：天马重复交易号 / 多宝重复订单号前缀，在对应列红粗提示。 */
.erp-dup-key {
    color: #d4380d;
    font-weight: 600;
}

/* ---------- 订单详情抽屉 ---------- */

/* 抽屉里的小标题：分区靠标题，不用 antd Divider —— 分区多的时候 Divider 会把内容切得太碎。 */
.erp-drawer-title {
    margin: 18px 0 8px;
    color: var(--erp-text);
    font-size: 14px;
    font-weight: 600;
}

.erp-drawer-empty {
    margin: 0;
    color: var(--erp-text-tertiary);
    font-size: 13px;
}

/* 转寄 / 退货记录：一单可能有多条，逐条成卡而不是塞进表格 ——
   抽屉里再放表格会多出一层横向滚动，反而不如卡片好读。 */
.erp-drawer-card {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-bottom: 8px;
    padding: 8px 10px;
    background: var(--erp-surface-alt);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    font-size: 13px;
}

/* 状态流转：一行一条，时间固定宽度便于纵向对齐。 */
.erp-drawer-log {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    padding: 4px 0;
    border-top: 1px solid var(--erp-border);
    font-size: 12px;
    color: var(--erp-text-secondary);
}

.erp-drawer-log-operator {
    margin-left: auto;
    color: var(--erp-text-tertiary);
}

/* ---------- 详情抽屉：只读信息的三列网格 ---------- */

/* 一行三项：抽屉里的字段是「看」不是「填」，竖排一栏会拉出很长一页、右半边全空着。
   780 宽的抽屉里三列刚好放得下，不用横向滚动。
   ⚠️ 别去动全局 .erp-form —— 那是竖排表单，三十多个页面在用，改成网格等于给所有表单页搬家。 */
.erp-detail-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 10px 16px;
}

/* min-width:0 是 grid 子项的老规矩：不给它，一条长地址会把整列撑宽，
   三列立刻变成「一宽两窄」，后面所有行跟着一起歪。 */
.erp-detail-grid > .erp-form-item {
    min-width: 0;
}

/* 值统一 22px 行高：纯文本是 inline 的、本身没有高度，而 ErpEnumTag 渲染出的标签有 22px，
   两种值混排时基线一高一低。block + 22px 让三列的值落在同一条水平线上。
   :not(.ant-tag) 是必须的 —— 标签自己有高度，再给它 display:block 会被拉成一根彩带。 */
.erp-detail-grid > .erp-form-item > span:not(.ant-tag) {
    display: block;
    min-height: 22px;
    overflow-wrap: anywhere;
    color: var(--erp-text);
    font-size: 13px;
}

/* 标签不许被横向拉伸：.erp-form-item 是竖排 flex，交叉轴 stretch 会把标签拉满整格 ——
   与上面全局 .ant-switch 那条是同一个坑。 */
.erp-detail-grid > .erp-form-item > .ant-tag {
    align-self: flex-start;
    width: auto;
}

/* 标签名统一 18px 底：有的格子里放标签、有的只放文字，不压一下三列的标签底边对不齐。 */
.erp-detail-grid > .erp-form-item > label {
    min-height: 18px;
}

/* 备注、成本来源这类长文本独占整行：塞进三分之一列会被切成好几行，读起来断断续续。 */
.erp-detail-grid > .erp-detail-span {
    grid-column: 1 / -1;
}

/* 窄屏（抽屉跟着视口缩）退两列：三列挤在 500px 里每项只剩一百多，连订单号都放不下。 */
@media (max-width: 720px) {
    .erp-detail-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ---------- 订单列表 ---------- */

/* 底部合计条：合计是整个筛选结果的，不是本页求和 ——
   放在表格下方而不是表头，避免被当成「本页小计」误读。 */
.erp-summary-bar {
    display: flex;
    gap: 20px;
    flex-wrap: wrap;
    padding: 8px 10px;
    background: var(--erp-surface-alt);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    color: var(--erp-text-secondary);
    font-size: 13px;
}

.erp-summary-bar b {
    color: var(--erp-text);
    font-variant-numeric: tabular-nums;
}

/* 自动分店的一片：一个合并键 + 一家店 = 一张快递单。
   片与片之间要框开：同一个合并键被拆成几片意味着多几笔运费，得让人一眼数出来。 */
/* 自动分店：一片 = 一张快递单。左侧那条竖线是这片的状态（沿用别处「左侧 3px 状态条」的写法），
   橙=拆单（多一笔运费）、红=没配上店（等人处理）、主色=正常 ——
   翻几十片的时候靠这个颜色先把有问题的挑出来，不用读标题里的标签。 */

.erp-allocate-group {
    margin-top: 12px;
    border: 1px solid var(--erp-border);
    border-left: 3px solid var(--erp-primary);
    border-radius: var(--erp-radius);
    background: var(--erp-surface);
    overflow: hidden;
}

.erp-allocate-group.is-split {
    border-left-color: #fa8c16;
}

.erp-allocate-group.is-missing {
    border-left-color: #ff4d4f;
}

/* 分组头：合并键是这一片唯一的身份，给一条带底色的标题栏压住整块。 */

.erp-allocate-group-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    background: var(--erp-surface-alt);
    border-bottom: 1px solid var(--erp-border);
    font-size: 12px;
    white-space: nowrap;
}

.erp-allocate-group-key {
    font-size: 13px;
    font-weight: 600;
}

.erp-allocate-group-count {
    color: var(--erp-text-tertiary);
}

/* 区块：明细在上、发货店铺在下，中间一条分隔线；各带一个小标题，
   标题右侧顺便把「有几家有库存 / 留空是什么意思」说完，省得再读一遍正文。 */

.erp-allocate-section {
    padding: 8px 12px;
}

.erp-allocate-section + .erp-allocate-section {
    border-top: 1px solid var(--erp-border);
}

.erp-allocate-section-title {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 4px;
    color: var(--erp-text-secondary);
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
}

.erp-allocate-section-hint {
    color: var(--erp-text-tertiary);
    font-size: 12px;
    font-weight: 400;
}

/* 候选发货店铺卡片：挑店顺序是按店铺身份排的，标记要和店名一起露出来才看得懂为什么选它。
   店名与可供量同一行、都禁止换行，放不下用省略号（悬停看全名）——
   卡片统一两行高度，横着排一排才不会互相挤错位。 */

.erp-shop-cards {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 6px;
}

.erp-shop-card {
    min-width: 148px;
    padding: 6px 8px;
    border: 1px solid var(--erp-border-strong);
    border-radius: var(--erp-radius);
    background: var(--erp-surface);
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
}

.erp-shop-card:hover {
    border-color: var(--erp-primary);
}

.erp-shop-card.is-active {
    border-color: var(--erp-primary);
    background: var(--erp-tab-active-bg);
    box-shadow: inset 0 0 0 1px var(--erp-primary);
}

.erp-shop-card-head {
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 600;
    white-space: nowrap;
}

.erp-shop-card-nick {
    overflow: hidden;
    max-width: 96px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.erp-shop-card-avail {
    margin-left: auto;
    color: var(--erp-text-secondary);
    font-size: 12px;
    font-weight: 400;
    white-space: nowrap;
}

.erp-shop-card-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 3px;
}

.erp-shop-card-tag {
    margin: 0;
    font-size: 12px;
    line-height: 18px;
    white-space: nowrap;
}

.erp-shop-card-hint {
    margin: 4px 0 6px;
    font-size: 12px;
    font-weight: 400;
    color: var(--erp-text-tertiary);
}

.erp-shop-option {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* 下拉选项里的库存量（自动分店全量兜底下拉）：与候选卡片的「可供」同一个数，
   右对齐贴末尾；0 置灰 —— 无货的店也要显示，藏着会让人以为「有货只是没写」。 */
.erp-shop-option-stock {
    margin-left: auto;
    padding-left: 8px;
    color: var(--erp-text-secondary);
    font-size: 12px;
    white-space: nowrap;
}

.erp-shop-option-stock.is-zero {
    color: var(--erp-text-quaternary, #bfbfbf);
}

/* 配货操作说明抽屉：内容是给人照着做的，密度高但要能扫读 ——
   分区靠标题栏（带左侧色条），步骤靠序号圆点，风险项统一橙色左边条，一眼能跳过去。 */

.erp-help-intro {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin-bottom: 12px;
    padding: 8px 10px;
    border: 1px solid var(--erp-border);
    border-left: 3px solid var(--erp-primary);
    border-radius: var(--erp-radius);
    background: var(--erp-surface-alt);
    font-size: 13px;
    line-height: 1.7;
}

.erp-help-section-title {
    margin: 16px 0 8px;
    padding-left: 8px;
    border-left: 3px solid var(--erp-primary);
    color: var(--erp-text);
    font-size: 13px;
    font-weight: 600;
}

.erp-help-step {
    margin-bottom: 10px;
    padding: 8px 10px;
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
}

.erp-help-step-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 4px;
}

.erp-help-step-no {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--erp-primary);
    color: #fff;
    font-size: 12px;
    flex: none;
}

.erp-help-step-title {
    font-weight: 600;
}

.erp-help-points {
    margin: 0;
    padding-left: 18px;
    color: var(--erp-text-secondary);
    font-size: 13px;
    line-height: 1.75;
}

.erp-help-points b {
    color: var(--erp-text);
}

/* 风险项：统一左边条 + 浅橙色，扫的时候跳过即可，要查的时候跳出来就发现。 */
.erp-help-points .is-warn {
    margin-top: 2px;
    padding-left: 8px;
    border-left: 3px solid #fa8c16;
    color: var(--erp-text-secondary);
}

.erp-help-notes {
    margin: 0;
    padding-left: 20px;
    color: var(--erp-text-secondary);
    font-size: 13px;
    line-height: 1.8;
}

.erp-help-notes b {
    color: var(--erp-text);
}

.erp-help-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
}

.erp-help-table th,
.erp-help-table td {
    padding: 5px 8px;
    border: 1px solid var(--erp-border);
    text-align: left;
    vertical-align: top;
}

.erp-help-table th {
    background: var(--erp-surface-alt);
    color: var(--erp-text-tertiary);
    font-weight: 500;
    white-space: nowrap;
}

.erp-help-table td.is-ok {
    color: #52c41a;
}

.erp-help-table td.is-risk {
    color: #fa8c16;
}

.erp-help-updated {
    margin-top: 16px;
    padding-top: 8px;
    border-top: 1px dashed var(--erp-border);
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

/* 分店弹窗的明细表：一排数字右对齐才扫得完，所以做成表格而不是一串行内文字。 */

.erp-allocate-rows {
    width: 100%;
    margin-top: 8px;
    border-collapse: collapse;
    font-size: 12px;
}

.erp-allocate-rows th,
.erp-allocate-rows td {
    padding: 3px 6px;
    white-space: nowrap;
}

.erp-allocate-rows th {
    color: var(--erp-text-tertiary);
    font-weight: 500;
    text-align: left;
    background: var(--erp-surface-alt);
    border-bottom: 1px solid var(--erp-border);
}

.erp-allocate-rows td {
    color: var(--erp-text-secondary);
    border-bottom: 1px solid var(--erp-border);
}

.erp-allocate-rows tbody tr:last-child td {
    border-bottom: none;
}

.erp-allocate-rows .is-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.erp-allocate-none {
    color: var(--erp-text-tertiary);
}

/* 订单列表的平台页签：页签只当导航用（表格在它外面），内容区是空的，直接收掉省一截高度。 */

.erp-order-tabs {
    margin-bottom: 10px;
}

.erp-order-tabs > .ant-tabs-content-holder {
    display: none;
}

.erp-order-tab {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
}

.erp-order-tab-count {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

/* 订单选择器下拉项：一个订单号下有多条尺码明细，只显示订单号等于让人盲选。
   所以把货号 / 收件人 / 运单号并排摆出来，次级信息弱化，别跟订单号抢注意力。 */
.erp-picker-option {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.erp-picker-option > span {
    color: var(--erp-text-secondary);
    font-size: 13px;
}

/* 订单选择器选中的那一行：登记转寄 / 退货时用来确认「挂对了单」。
   只显示订单号容易看漏——同一个订单号下有多条明细（不同尺码）时尤其危险。 */
.erp-order-picker-summary {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 6px 8px;
    background: var(--erp-surface-alt);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    color: var(--erp-text-secondary);
    font-size: 12px;
}

/* 快递下单弹窗：一组 = 一张快递单，一张单一张卡片。
   刻意做成卡片而不是表格：每组还要放渠道下拉与下单按钮，表格的行内控件太挤；
   而「核对收件人」要求字段能被看清 —— 所以标签定宽成列（多张卡片之间对得齐）、
   地址整段换行（看不全等于没显示）、款号 / 尺码 / 数量 三列对齐（少一个尺码一眼就能看出）。 */
.erp-ship-hint {
    margin-bottom: 12px;
    color: var(--erp-text-secondary);
    font-size: 13px;
}

.erp-ship-card {
    padding: 10px 12px;
    margin-bottom: 10px;
    background: var(--erp-surface-alt);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* 取消快递弹窗的操作行：只负责排列，不加分割线 —— 它上面紧挨着告警框，再划线就重了。 */
.erp-ship-group-body {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.erp-ship-card:hover {
    border-color: var(--erp-border-strong);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}

/* 已下单的卡片整张转绿：剩下哪几张还没下，扫一眼就看出来。 */
.erp-ship-card.is-done {
    border-color: #52c41a;
    background: rgba(82, 196, 26, 0.06);
}

.erp-ship-head {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding-bottom: 8px;
    margin-bottom: 8px;
    border-bottom: 1px dashed var(--erp-border);
}

/* 序号：一次下十几张时靠它对齐「点过哪张」。 */
.erp-ship-seq {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--erp-primary-bg);
    color: var(--erp-primary);
    font-size: 12px;
    font-weight: 600;
}

.erp-ship-shop {
    font-size: 14px;
    font-weight: 600;
    color: var(--erp-text);
}

.erp-ship-express {
    font-size: 13px;
    color: var(--erp-text-secondary);
}

.erp-ship-express b {
    color: var(--erp-text);
    font-weight: 600;
}

/* 「店铺默认 XX」这块小尾巴：渠道是按店铺档案预选的，得跟「买家指定的需求快递」区分开 ——
   混成一个词会让下单的人以为快递是买家挑的，改渠道时不敢下手。 */

.erp-ship-suggest {
    margin-left: 6px;
    padding: 0 5px;
    border: 1px dashed var(--erp-border-strong);
    border-radius: 10px;
    color: var(--erp-text-tertiary);
    font-size: 12px;
    cursor: help;
}

.erp-ship-meta {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

/* 合并键是单号类字符，等宽字体下长数字才数得清。 */
.erp-ship-meta b {
    color: var(--erp-text-secondary);
    font-weight: 500;
    font-family: Consolas, Monaco, monospace;
}

.erp-ship-state {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: auto;
    font-size: 12px;
}

/* 下完单出现的那颗复制图标：字号被 .erp-ship-state 压到 12px 后图标会小一号，
   这里单独抬回 14px 并收窄内边距 —— 它是「下完单顺手复制」的唯一入口，太小就没人看见。 */
.erp-ship-state .ant-btn {
    height: 22px;
    padding: 0 4px;
    font-size: 14px;
}

/* 订单列表「快递单号」列：单号 + 拷贝图标 + 物流状态标签一行排开。
   图标贴着单号才指得清复制的是哪一单；两颗按钮都收到 22px 见方，
   否则 antd 小按钮默认内边距会把 14 位的运单号挤到换行。 */
.erp-express-no {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    max-width: 100%;
}

/* 状态标签与左边的操作按钮留一点距离：贴着 22px 的图标时像被压扁在一起，
   而它读的是「这张单到哪了」，和单号 / 复制不是一组东西。 */
.erp-express-no .ant-tag {
    margin-left: 6px;
}

.erp-express-no .ant-btn {
    height: 22px;
    padding: 0 4px;
    font-size: 14px;
}

.erp-express-no .ant-btn:first-child {
    min-width: 0;
    white-space: nowrap;
}

/* 字段区：标签列固定 64px，值列左对齐 —— 多张卡片之间标签对齐，扫视不用重新定位。 */
.erp-ship-info {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.erp-ship-row {
    display: flex;
    gap: 8px;
    font-size: 13px;
    line-height: 1.6;
}

.erp-ship-label {
    flex: 0 0 64px;
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

.erp-ship-value {
    flex: 1;
    min-width: 0;
    color: var(--erp-text);
    /* 地址里有门牌号、虚拟号这类长串：允许任意位置断行，否则整行会被撑出去。 */
    word-break: break-all;
}

.erp-ship-phone {
    margin-left: 8px;
    color: var(--erp-text-secondary);
    font-family: Consolas, Monaco, monospace;
    font-size: 12px;
}

/* 货品：款号 / 尺码 / 数量 三列。grid 让多行数据的列对齐，比一行一条 chip 更好数。 */
.erp-ship-items {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 72px 72px;
    gap: 2px 12px;
    max-width: 480px;
}

.erp-ship-th {
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

.erp-ship-td {
    color: var(--erp-text-secondary);
    font-size: 13px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.erp-ship-td.is-no {
    color: var(--erp-text);
    font-weight: 600;
}

/* 数量是核对重点（少一件就是少发），给主色。 */
.erp-ship-td.is-qty {
    color: var(--erp-primary);
    font-weight: 600;
}

.erp-ship-foot {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 10px;
    padding-top: 8px;
    border-top: 1px dashed var(--erp-border);
}

/* 下单按钮靠右：与上面「核对内容」拉开，避免误点。 */
.erp-ship-foot .ant-btn {
    margin-left: auto;
}

/* 下单结果：明确写出「状态还没推成已发货」—— 这是最容易漏掉的一步。 */
.erp-ship-result {
    margin-top: 8px;
    padding: 6px 8px;
    background: rgba(82, 196, 26, 0.1);
    border-left: 3px solid #52c41a;
    color: var(--erp-text);
    font-size: 12px;
    line-height: 1.6;
}

/* 取消结果：绿色在弹窗里代表「下单成功」，取消是反过来的结果，
   沿用同一个颜色会让两种相反的结局长得一模一样。 */
.erp-ship-result.is-canceled {
    background: rgba(22, 119, 255, 0.08);
    border-left-color: #1677ff;
}

/* 配货汇总抽屉：一家店一张卡片，卡片里是「序号 货号 尺码 [x N 件]」的清单。
   用的人是照着清单一件件拿货的，所以要能一路扫下来：字号紧凑、行高固定、
   多件用主色挑出来（数量不显眼的话，多拿少拿都不会被发现）。 */
.erp-pick-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 12px;
    color: var(--erp-text-secondary);
    font-size: 13px;
}

.erp-pick-card {
    margin-bottom: 10px;
    padding: 10px 12px;
    background: var(--erp-surface-alt);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
}

.erp-pick-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}

.erp-pick-shop {
    color: var(--erp-text);
    font-weight: 600;
}

.erp-pick-meta {
    color: var(--erp-text-secondary);
    font-size: 12px;
}

/* 复制按钮推到卡片右上角：每张卡片的同一个位置，连点几家店不用找。 */
.erp-pick-head .ant-btn {
    margin-left: auto;
}

.erp-pick-items {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.erp-pick-item {
    display: flex;
    align-items: baseline;
    gap: 8px;
    font-size: 13px;
    line-height: 1.9;
}

.erp-pick-no {
    width: 18px;
    color: var(--erp-text-secondary);
    text-align: right;
}

.erp-pick-article,
.erp-pick-size {
    color: var(--erp-text);
}

.erp-pick-qty {
    color: #1677ff;
    font-weight: 600;
}

/* 单价 / 金额：推到行尾、等宽字体 —— 配货的人先扫货号尺码拿货，
   单价金额是备查的货值，别挡在拿货视线里；只显示、不进复制文本。 */
.erp-pick-price {
    margin-left: auto;
    color: var(--erp-text-tertiary);
    font-size: 12px;
    font-family: Consolas, Monaco, monospace;
    white-space: nowrap;
}

.erp-pick-amount {
    color: var(--erp-text-secondary);
    font-weight: 600;
    font-size: 12px;
    font-family: Consolas, Monaco, monospace;
    min-width: 64px;
    text-align: right;
    white-space: nowrap;
}

/* 结算页分段标题：页面上是「待结算店铺」与「结算单」两块，
   没有分隔线的话两段会连成一片，看不出哪儿到哪儿。 */
.erp-section-title {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 14px 0 10px;
    padding-left: 8px;
    border-left: 3px solid var(--erp-primary);
    color: var(--erp-text);
    font-size: 14px;
    font-weight: 600;
}

.erp-section-title:first-child {
    margin-top: 0;
}

/* ---------- 未处理异常提示条 ---------- */

#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 12px 16px;
    background: #ffe58f;
    z-index: 1000;
}

/* ---------- 天马数据分析看板 ---------- */
/* 图表一律自绘（SVG + CSS），不引第三方图表库：
   WASM 客户端体积敏感，而且离线环境下图表包版本对不上 AntDesign，装了也用不起来。
   自绘的代价是要自己算坐标，好处是颜色、留白、hover 提示全都跟着项目的设计变量走。 */

.erp-dash-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

.erp-dash-title {
    font-size: 18px;
    font-weight: 600;
    color: var(--erp-text-primary);
}

.erp-dash-sub {
    margin-top: 4px;
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

.erp-dash-empty {
    margin-bottom: 16px;
    padding: 12px 14px;
    border: 1px solid var(--erp-border);
    border-left: 3px solid #fa8c16;
    border-radius: 6px;
    background: rgba(250, 173, 20, 0.08);
    font-size: 13px;
    color: var(--erp-text-secondary);
}

/* ---------- 指标卡 ---------- */

.erp-kpi-grid {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 12px;
    margin-bottom: 16px;
}

.erp-kpi-card {
    padding: 14px 16px;
    border: 1px solid var(--erp-border);
    border-radius: 12px;
    background: var(--erp-surface);
    transition: box-shadow .2s ease, transform .2s ease;
}

    .erp-kpi-card:hover {
        box-shadow: 0 2px 4px rgba(15, 23, 42, .04), 0 10px 24px rgba(15, 23, 42, .07);
        transform: translateY(-1px);
    }

.erp-kpi-label {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

.erp-kpi-value {
    margin-top: 6px;
    font-size: 24px;
    font-weight: 600;
    line-height: 1.2;
    color: var(--erp-text-primary);
    font-variant-numeric: tabular-nums;
}

.erp-kpi-unit {
    margin-left: 3px;
    font-size: 12px;
    font-weight: 400;
    color: var(--erp-text-tertiary);
}

.erp-kpi-hint {
    margin-top: 6px;
    font-size: 12px;
    color: var(--erp-text-tertiary);
    min-height: 32px;
}

.erp-kpi-track {
    margin-top: 6px;
    height: 4px;
    border-radius: 2px;
    background: var(--erp-hover-bg);
    overflow: hidden;
}

.erp-kpi-fill {
    height: 100%;
    border-radius: 2px;
    background: #2f54eb;
    transition: width .4s ease;
}

    .erp-kpi-fill.is-good {
        background: #52c41a;
    }

    .erp-kpi-fill.is-warn {
        background: #fa8c16;
    }

    .erp-kpi-fill.is-danger {
        background: #cf1322;
    }

/* ---------- 看板栅格 ---------- */

/* 看板栅格：列数随容器宽度自动增减（auto-fill），卡片跟着重排 ——
   拉窗口、改布局、隐藏几张卡都不用手动调，也不会留下空档。
   刻意不用 12 列固定栅格：那种排法只要卡片一显隐就会漏出洞，
   而每次靠手调 span 去补，维护不下去。 */
.erp-dash-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    /* dense：后面能塞下的小卡会回填前面留下的空位，不留难看的洞。 */
    grid-auto-flow: row dense;
    gap: 16px;
    align-items: start;
}

.erp-dash-card {
    grid-column: span 1;
    padding: 16px;
    border: 1px solid var(--erp-border);
    border-radius: 8px;
    /* 底色走主题变量：写死 #fff 的话暗色模式下看板卡片是白底，与页面其余卡片不一致。 */
    background: var(--erp-surface);
    min-width: 0;
}

/* 一张卡里放多节（如店铺切面的「排行 + 明细」）：用间距分节，不必另起一张卡。 */
.erp-dash-stack {
    display: flex;
    flex-direction: column;
    gap: 18px;
}

    /* 宽度档位按「占几格」算，格宽由上面的 auto-fill 决定，
       所以宽屏上 2 格是真的占两列，窄屏上会自动退化成一整行。 */
    .erp-dash-card.w2 {
        grid-column: span 2;
    }

    .erp-dash-card.w3 {
        grid-column: span 3;
    }

    /* 整行用 1 / -1 而不是「占 4 格」：列数会随宽度变，写死格数在宽屏上占不满。 */
    .erp-dash-card.w4 {
        grid-column: 1 / -1;
    }

.erp-dash-card-title {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 14px;
    font-size: 14px;
    font-weight: 600;
    color: var(--erp-text-primary);
}

.erp-dash-card-note {
    font-size: 12px;
    font-weight: 400;
    color: var(--erp-text-tertiary);
}

.erp-dash-notes {
    margin: 0;
    padding-left: 18px;
    font-size: 12px;
    line-height: 1.9;
    color: var(--erp-text-tertiary);
}

/* 商品排名缩略图条：排行榜给的是货号，看图才知道卖的是哪双鞋。
   横向滚动而不是换行 —— 卡片高度有限，换行会把下面的卡片顶下去。 */
.erp-rank-thumbs {
    display: flex;
    gap: 8px;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px dashed var(--erp-border);
    overflow-x: auto;
}

.erp-rank-thumb {
    position: relative;
    flex: 0 0 auto;
    width: 56px;
    height: 56px;
    border: 1px solid var(--erp-border);
    border-radius: 6px;
    background: #fafafa;
    overflow: hidden;
    cursor: zoom-in;
}

    .erp-rank-thumb:hover {
        border-color: var(--erp-primary);
    }

    .erp-rank-thumb .ant-image,
    .erp-rank-thumb img {
        display: block;
        width: 56px;
        height: 56px;
        object-fit: cover;
    }

/* 柱条点击用的预览宿主：它在页面上是不可见的，只负责把组件自带的预览层叫出来。 */
.erp-rank-preview-host {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    opacity: 0;
    pointer-events: none;
}

/* 没有首图的货号：留位置不画图，避免整排缩略图长短不一。 */
.erp-rank-thumb-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: default;
}

.erp-rank-thumb-none {
    font-size: 11px;
    color: var(--erp-text-tertiary);
}

.erp-rank-thumb-qty {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    font-size: 10px;
    line-height: 14px;
    text-align: center;
    color: #fff;
    background: rgba(0, 0, 0, 0.45);
}

/* 看板布局设置：一行一张卡，开关 + 上下移 + 宽度档。 */
.erp-layout-hint {
    display: flex;
    gap: 6px;
    align-items: center;
    margin-bottom: 12px;
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

.erp-layout-row {
    display: flex;
    gap: 10px;
    align-items: center;
    padding: 8px 0;
    border-bottom: 1px solid var(--erp-border);
}

.erp-layout-row-off .erp-layout-title {
    color: var(--erp-text-tertiary);
    text-decoration: line-through;
}

.erp-layout-text {
    flex: 1;
    min-width: 0;
}

.erp-layout-title {
    font-size: 13px;
}

.erp-layout-note {
    margin-top: 2px;
    font-size: 11px;
    color: var(--erp-text-tertiary);
}

.erp-layout-ops {
    display: flex;
    gap: 4px;
    align-items: center;
}

.erp-layout-span {
    width: 88px;
}

.erp-layout-footer {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 16px;
}

/* ---------- 图表容器（Apache ECharts） ---------- */

/* 高度由组件内联指定（ECharts 必须有确定高度），这里只保证宽度能吃满栅格。 */
.erp-echart {
    width: 100%;
    min-width: 0;
}

.erp-chart-empty {
    padding: 28px 0;
    text-align: center;
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

/* ---------- 看板响应式 ---------- */

@media (max-width: 1400px) {
    .erp-kpi-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 1100px) {
    /* 窄屏只有一列，占多格会撑出横向滚动：一律退回占一格。 */
    .erp-dash-card.w2,
    .erp-dash-card.w3,
    .erp-dash-card.w4 {
        grid-column: span 1;
    }
}

@media (max-width: 700px) {
    .erp-kpi-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ---------- 经营工作台（首页） ---------- */

.erp-wb-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 16px;
}

.erp-wb-title {
    font-size: 18px;
    font-weight: 600;
    color: var(--erp-text-primary);
}

.erp-wb-sub {
    margin-top: 4px;
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

/* 八张指标卡固定四列：正好两行排满。
   不用看板那套六列 —— 8 ÷ 6 会在第二行剩两个格子吊着，看着像漏了两张卡。 */
.erp-wb-kpi {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 12px;
}

/* 成本变动明细：一行一笔，「当时 → 现在」与差额摆在最右。
   用网格而不是 Table：只有四列，套表格会多出一排表头的高度，卡片里放不下。
   数字列开 tabular-nums —— 比例数字跳宽会让上下两行的差额对不齐，读起来像两笔不同的数。 */
.erp-wb-drift {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 12px;
}

.erp-wb-drift-row {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.3fr) minmax(0, 1.5fr) minmax(0, 0.8fr) minmax(0, 0.9fr);
    gap: 8px;
    align-items: center;
    padding: 6px 10px;
    border-radius: var(--erp-radius);
    background: var(--erp-surface-alt);
    font-size: 12px;
}

.erp-wb-drift-article {
    font-weight: 600;
}

.erp-wb-drift-order,
.erp-wb-drift-cost {
    overflow: hidden;
    color: var(--erp-text-secondary);
    text-overflow: ellipsis;
    white-space: nowrap;
}

.erp-wb-drift-cost,
.erp-wb-drift-matched {
    font-variant-numeric: tabular-nums;
}

/* 「匹配于」是背景信息，压到最弱一档：这列要紧的是日期在不在，不是它有多显眼。 */
.erp-wb-drift-matched {
    color: var(--erp-text-tertiary);
    text-align: center;
}

.erp-wb-drift-amount {
    font-weight: 600;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* 多付是红、少付是绿：挑的是亮色档 —— 暗色主题下深色红绿会糊成一片看不清。
   方向只对「钱」负责，不评价好坏：少付看着是好事，但它同样是一笔要人去定的账。 */
.erp-wb-drift-row.is-up .erp-wb-drift-amount {
    color: #ff7875;
}

.erp-wb-drift-row.is-down .erp-wb-drift-amount {
    color: #95de64;
}

/* 构成图一个环就够看，走势图日期一多要横向空间 —— 宽的那份给它。 */
.erp-wb-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
    gap: 16px;
    margin-top: 16px;
}

.erp-wb-cards {
    display: flex;
    flex-direction: column;
    gap: 16px;
    margin-top: 16px;
}

/* 卡片：圆角 12 + 两层柔和阴影（近处贴地、远处扩散），比单层阴影更像「浮起来」而不是「描了个边」。
   背景走 --erp-surface 而不是写死 #fff：写死会让暗色主题下出现一块白板。 */
.erp-wb-card {
    padding: 16px 18px;
    border: 1px solid var(--erp-border);
    border-radius: 12px;
    background: var(--erp-surface);
    box-shadow: 0 1px 2px rgba(15, 23, 42, .03), 0 8px 24px rgba(15, 23, 42, .04);
    min-width: 0;
}

.erp-wb-card-title {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 10px;
    font-size: 14px;
    font-weight: 600;
    color: var(--erp-text-primary);
}

.erp-wb-card-note {
    font-size: 12px;
    font-weight: 400;
    color: var(--erp-text-tertiary);
}

.erp-wb-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}

.erp-wb-toolbar-note {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

/* ===== 首页快捷入口：九宫格方块（只有图标与名称，不显示路由） ===== */
.erp-quick-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
}

.erp-quick-search {
    width: 240px;
}

.erp-quick-bar-note {
    flex: 1;
    min-width: 0;
    font-size: 12px;
    color: var(--erp-text-tertiary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* 九宫格：方块（1:1）+ 列数随宽度增减。
   底色走 --erp-surface —— 写死 #fff 会在暗色主题下留一块白板（卡片背景踩过这个坑）。 */
.erp-quick-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 12px;
}

/* 用原生 button 而不是 div：键盘能 Tab 到、回车能打开，焦点框也是自带的。 */
.erp-quick-tile {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    aspect-ratio: 1 / 1;
    padding: 10px 8px;
    border: 1px solid var(--erp-border);
    border-radius: 12px;
    background: var(--erp-surface);
    cursor: pointer;
    transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease, background-color .2s ease;
}

    .erp-quick-tile:hover {
        border-color: var(--erp-primary);
        background: var(--erp-surface-alt);
        box-shadow: 0 2px 10px rgba(0, 0, 0, .07);
        transform: translateY(-2px);
    }

.erp-quick-tile-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: rgba(22, 119, 255, .08);
    color: var(--erp-primary);
    font-size: 20px;
}

/* 名称最多两行：菜单名长短不一，不夹住会把方块撑高、整片网格错位。 */
.erp-quick-tile-name {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 12px;
    line-height: 1.35;
    text-align: center;
    color: var(--erp-text-primary);
    word-break: break-all;
}

/* ★ 只在搜索结果里出现：平时的方块就是纯入口，不留会误点的按钮。 */
.erp-quick-tile-star {
    position: absolute;
    top: 2px;
    right: 2px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 6px;
    font-size: 13px;
    opacity: .55;
    transition: opacity .2s ease, background-color .2s ease;
}

    .erp-quick-tile-star:hover {
        opacity: 1;
        background: var(--erp-surface-alt);
    }

.erp-quick-tile.is-fav .erp-quick-tile-star {
    opacity: 1;
}

/* ===== 管理快捷入口：左边挑、右边排 ===== */
.erp-quick-mgr-hint {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin-bottom: 12px;
    padding: 8px 12px;
    border-radius: 8px;
    background: var(--erp-surface-alt);
    font-size: 12px;
    line-height: 1.6;
    color: var(--erp-text-secondary);
}

.erp-quick-mgr-cols {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
}

.erp-quick-mgr-col {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
}

.erp-quick-mgr-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    font-size: 13px;
    font-weight: 600;
    color: var(--erp-text-primary);
}

.erp-quick-mgr-count {
    font-size: 12px;
    font-weight: 400;
    color: var(--erp-text-tertiary);
}

.erp-quick-mgr-list {
    height: 360px;
    overflow: auto;
    padding: 4px;
    border: 1px solid var(--erp-border);
    border-radius: 8px;
}

.erp-quick-mgr-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 7px 10px;
    border: none;
    border-radius: 6px;
    background: transparent;
    text-align: left;
    font-size: 13px;
    color: var(--erp-text-primary);
    cursor: pointer;
}

    .erp-quick-mgr-item:hover {
        background: var(--erp-surface-alt);
    }

    .erp-quick-mgr-item.is-on {
        color: var(--erp-primary);
    }

    /* 已选区是「排序」不是「开关」：整行不响应点击，免得误点又把它收回去。 */
    .erp-quick-mgr-item.is-static,
    .erp-quick-mgr-item.is-static:hover {
        background: transparent;
        cursor: default;
    }

.erp-quick-mgr-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.erp-quick-mgr-group {
    flex: none;
    font-size: 11px;
    color: var(--erp-text-tertiary);
}

.erp-quick-mgr-ops {
    display: flex;
    align-items: center;
    gap: 4px;
}

.erp-quick-mgr-foot {
    display: flex;
    justify-content: flex-end;
}

/* 窄屏：方块可以小一点，弹窗两栏改一栏（并排会把名字全挤成省略号）。 */
@media (max-width: 720px) {
    .erp-quick-grid {
        grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
        gap: 10px;
    }

    .erp-quick-search {
        width: 150px;
    }

    .erp-quick-mgr-cols {
        grid-template-columns: 1fr;
    }

    .erp-quick-mgr-list {
        height: 220px;
    }
}

.erp-wb-notes {
    margin: 0;
    padding-left: 18px;
    font-size: 12px;
    line-height: 1.8;
    color: var(--erp-text-tertiary);
}

@media (max-width: 1100px) {
    /* 窄屏放不下「占比 + 走势」并排：各占一整行，指标卡退回两列。 */
    .erp-wb-row {
        grid-template-columns: minmax(0, 1fr);
    }

    .erp-wb-kpi {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ---------- 库存汇总：店铺库存明细标签 ---------- */

/* 明细是一堆小标签，横向铺开自动换行。 */
.erp-store-tags {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 6px;
}

/* 「不输出」的店铺从虚线之后开始：看得到，但一眼知道不该当可用库存用。 */
.erp-store-tags-sep {
    width: 100%;
    margin: 2px 0;
    border-top: 1px dashed var(--erp-border);
}

.erp-store-tag {
    margin-inline-end: 0;
    font-size: 12px;
    line-height: 20px;
    white-space: nowrap;
}

.erp-store-tag-hidden {
    opacity: .72;
}

.erp-store-badge {
    margin-left: 4px;
    padding: 0 4px;
    border-radius: 3px;
    border: 1px solid transparent;
    font-size: 10px;
    line-height: 15px;
}

.erp-store-badge-bank {
    background: #f6ffed;
    border-color: #b7eb8f;
    color: #389e0d;
}

.erp-store-badge-group {
    background: #fffbe6;
    border-color: #ffe58f;
    color: #d48806;
}

.erp-store-badge-box {
    background: #fff1f0;
    border-color: #ffa39e;
    color: #cf1322;
}

.erp-store-badge-hidden {
    background: #fafafa;
    border-color: #d9d9d9;
    color: #8c8c8c;
}

/* ---------- 库存汇总：门店卡片视图 ---------- */

/* 汇总行要同时放统计与「卡片 / 表格」切换，比普通汇总行高一点。 */
.erp-summary-flex {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px 12px;
}

.erp-view-switch {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* 流式网格：列数随容器宽度自动增减，宽屏多列、手机单列，不必为「每张卡多宽」写一串断点。 */
.erp-store-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: 16px;
}

.erp-store-card {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
    padding: 14px 16px;
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    background: var(--erp-surface);
}

/* 「不输出」的门店整卡压灰 + 虚线：它们有货，但不是分配时的优先对象。 */
.erp-store-card-muted {
    opacity: .78;
    border-style: dashed;
}

.erp-store-card-head {
    min-width: 0;
}

.erp-store-card-name {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 15px;
    font-weight: 600;
}

.erp-store-card-sub {
    margin-top: 2px;
    color: var(--erp-text-secondary);
    font-size: 12px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.erp-store-card-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 6px;
}

.erp-store-card-stats {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 8px;
    padding: 8px 0;
    border-top: 1px solid var(--erp-border);
    border-bottom: 1px solid var(--erp-border);
}

.erp-card-stat {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.erp-card-stat span {
    color: var(--erp-text-secondary);
    font-size: 12px;
}

.erp-card-stat b {
    font-size: 15px;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
}

.erp-store-card-items {
    display: flex;
    flex-direction: column;
}

.erp-store-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    font-size: 13px;
    border-bottom: 1px dashed var(--erp-border);
}

.erp-store-item:last-child {
    border-bottom: none;
}

.erp-store-item-code {
    font-weight: 500;
}

.erp-store-item-size {
    padding: 0 6px;
    border: 1px solid var(--erp-border-strong);
    border-radius: 3px;
    background: var(--erp-surface-alt);
    color: var(--erp-text-secondary);
    font-size: 12px;
}

.erp-store-item-status {
    color: #d48806;
    font-size: 12px;
}

.erp-store-item-qty {
    margin-left: auto;
    font-weight: 600;
}

.erp-store-card-empty {
    padding: 6px 0;
    color: var(--erp-text-secondary);
    font-size: 12px;
}

.erp-store-card-more {
    align-self: flex-start;
    padding-left: 0;
}

.erp-store-card-pager {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 16px;
}

.erp-store-detail-head {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 18px;
    margin-bottom: 12px;
    color: var(--erp-text-secondary);
    font-size: 13px;
}

/* 店铺名称搜索行：门店十几到几十家，靠翻页找某家店太慢，给个输入框直接过滤。 */
.erp-store-detail-search {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
}

.erp-store-detail-search-hit {
    color: var(--erp-text-secondary);
    font-size: 13px;
}

.erp-store-detail-search-hit > b {
    color: var(--erp-text-primary);
}

/* 窄屏：栅格本身会掉到单列，这里把统计区收成两列，免得四个数挤成一排读不出来。 */
@media (max-width: 480px) {
    .erp-store-cards {
        grid-template-columns: 1fr;
    }

    .erp-store-card-stats {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .erp-store-card-pager {
        justify-content: center;
    }
}

/* ---------- 系统参数：枚举字典两栏布局 ---------- */

/* 左字典右选项：宽屏 380px + 剩余，窄屏整体堆叠成一列。
   左栏给固定宽度而不是按比例，是为了让「名称 / 编码」两列在任何宽度下都不换行。 */
.erp-dict-layout {
    display: grid;
    grid-template-columns: 380px minmax(0, 1fr);
    gap: 16px;
    align-items: start;
}

.erp-dict-pane {
    min-width: 0;
}

.erp-dict-pane-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px 12px;
    margin-bottom: 12px;
}

.erp-dict-pane-title {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px 8px;
}

.erp-dict-code {
    padding: 1px 6px;
    border-radius: 3px;
    background: var(--erp-hover-bg);
    color: var(--erp-text-secondary);
    font-size: 12px;
    font-family: Consolas, Menlo, monospace;
}

.erp-dict-desc {
    color: var(--erp-text-secondary);
    font-size: 13px;
}

/* 取值预览：这是其它模块将来要走的那条调用链，放在这里能一眼看出字典改得对不对。 */
.erp-dict-preview {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 10px;
    margin-bottom: 12px;
    padding: 8px 12px;
    border: 1px dashed var(--erp-border);
    border-radius: 6px;
    color: var(--erp-text-secondary);
    font-size: 13px;
}

.erp-dict-preview code {
    font-family: Consolas, Menlo, monospace;
    font-size: 12px;
}

/* ---------- 彪马折扣方案：六个参数的紧凑网格 ---------- */

/* 两列三行：六个维度一次扫完，不用点开编辑才看得到。
   维度名压低对比度、倍率加粗等宽，视线先落在数字上。 */
.erp-discount-params {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 2px 16px;
}

.erp-discount-param {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    font-size: 12px;
    line-height: 20px;
}

.erp-discount-param > span {
    color: var(--erp-text-secondary);
    white-space: nowrap;
}

.erp-discount-param > b {
    font-weight: 600;
    font-family: Consolas, Menlo, monospace;
}

/* 窄屏兜底：列宽不够就掉成单列，宁可长一点，也不要让两列互相挤压。 */
@media (max-width: 480px) {
    .erp-discount-params {
        grid-template-columns: 1fr;
    }
}

/* ---------- 彪马库存汇总：款号 + 尺码卡片 ---------- */

/* 与门店卡片同一套网格思路，最小列宽略窄一些：组合卡的内容比门店卡少。 */
.erp-combo-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 16px;
}

.erp-combo-card {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
    padding: 14px 16px;
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    background: var(--erp-surface);
}

/* 表头分左右两栏：左边货号 / 尺码 / 状态 + 门店数，右边成本价单独站着。
   成本价是「这批货还能不能卖」的第一眼数据，夹在下面四个数字里要一行行找。 */
.erp-combo-card-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    min-width: 0;
}

.erp-combo-card-head-main {
    flex: 1;
    min-width: 0;
}

/* 卡片首图：尺寸写死 48px，卡片高度就不会随图片原始比例上下跳动；
   取不到图时留灰底「无图」占位，一排卡片的高度始终对齐。 */
.erp-combo-card-pic {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    overflow: hidden;
    border-radius: 4px;
    background: var(--erp-surface-alt);
    color: var(--erp-text-secondary);
    font-size: 11px;
}

/* 图可点（点开商品详情），所以给手型光标：不然看不出来它能点。 */
.erp-combo-card-pic > img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    cursor: pointer;
}

.erp-combo-card-cost {
    flex: none;
    text-align: right;
    line-height: 1.3;
}

.erp-combo-card-cost > span {
    display: block;
    color: var(--erp-text-secondary);
    font-size: 12px;
}

/* 与下面的指标数字同一套等宽字体，但字号略大：它是表头里的主数据。 */
.erp-combo-card-cost > b {
    font-family: Consolas, Menlo, monospace;
    font-size: 16px;
    font-weight: 600;
}

.erp-combo-card-title {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    font-size: 15px;
    font-weight: 600;
}

/* 货号用等宽：一串数字里少看一位就是另一个款。 */
.erp-combo-card-article {
    font-family: Consolas, Menlo, monospace;
}

.erp-combo-card-sub {
    margin-top: 2px;
    color: var(--erp-text-secondary);
    font-size: 12px;
}

.erp-combo-card-empty,
.erp-combo-card-more {
    color: var(--erp-text-secondary);
    font-size: 12px;
}

.erp-combo-card-actions {
    display: flex;
    justify-content: flex-end;
}

@media (max-width: 480px) {
    .erp-combo-cards {
        grid-template-columns: 1fr;
    }
}

/* ---------- 页面布局约束：上段搜索栏 + 合计，下段占满剩余高度 ---------- */

/* 外壳本身已是 flex 列（见 .erp-content-card），这两条只负责高度的分配：
   上段跟着内容走，下段吃掉剩下的全部高度并自己滚动。
   min-height:0 是必需的 —— flex 子项默认 min-height:auto，内容一多就会把容器顶开，滚动条留在了外面。

   下段必须用 .erp-content-card > .erp-page-main 这种「父 + 子」的写法：
   上面 .erp-content-card > *:not(.erp-table-wrap) { flex: none } 的优先级更高，
   只写 .erp-page-main 会被它压成 flex:none（撑开高度、外层多出一条滚动条）。 */
.erp-page-head {
    flex: none;
}

.erp-content-card > .erp-page-main {
    position: relative;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
    /* 只负责分配高度，自己不滚：竖向滚动一律落在里面的内容区（卡片网格 / 表格体）。
       这里写 auto 的话，只要子项高度加起来差 1px（分页条的行高就是这样）它就冒出第二条滚动条，
       页面看上去就是「外面一条、里面一条」。 */
    overflow: hidden;
}

/* 卡片区自己滚，分页条留在页面底部不动 ——
   原先是「卡片 + 分页」整段一起滚，卡片一多分页就被顶到屏幕外。 */
.erp-page-main > .erp-combo-cards {
    flex: 1;
    min-height: 0;
    overflow: auto;
    align-content: start;      /* 卡片不满一屏时别被拉伸成整屏高 */
    scrollbar-gutter: stable;  /* 滚动条出现 / 消失不让卡片宽度跳动 */
}

/* 与卡片区之间的间距由容器 gap 提供，这里去掉自带的上外边距，免得底部空一大截。 */
.erp-page-main > .erp-store-card-pager {
    margin-top: 0;
}

/* 表格视图：表格外面还套了一层用来「显示 / 隐藏」的 div，它必须也参与高度分配。
   少了这一步，.erp-table-wrap 的 height:100% 没有参照、退化成按内容撑开，
   表格连同分页条一起撑到 900px 高，滚动条就跑到页面容器上去了（表头也不再固定）。 */
.erp-page-main > .erp-page-main-table {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

/* 这里要覆盖掉 .erp-table-wrap 自带的 min-height:240px：
   窗口再矮也让表格跟着收缩、由表格体自己滚，
   否则多出来的 240px 会被上一层的 overflow:hidden 裁掉，分页条就没了。 */
.erp-page-main-table > .erp-table-wrap {
    flex: 1;
    min-height: 0;
    height: auto;
}

/* 同上：分页控件有 1px 的行高误差，不留这点余量，表格容器就会一直差 1px、底部被裁掉一线。 */
.erp-page-main-table .erp-pager {
    padding-bottom: 2px;
}

/* 页签（Tabs）也是高度链的一环（同步范围页、销量查询页共用）。
   antd 的 .ant-tabs 自己不带高度分配，页签内容会按表格的实际高度撑开，
   于是滚动条又落到页面容器上（双滚动条的老毛病）。这里把高度一路传到页签内的表格。 */
.erp-page-main > .erp-scope-tabs,
.erp-page-main > .erp-sales-tabs {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* 平台结算页：卡片里直接放 Tabs（没有 .erp-page-main 那一层）。
   同样要占满卡片剩余高度，才能把高度传给「结算单」页签里的表格
   （表头固定、表体内部滚动，滚动条不会跑到页面容器上）。 */
.erp-content-card > .erp-scope-tabs {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.erp-scope-tabs > .ant-tabs-content-holder,
.erp-sales-tabs > .ant-tabs-content-holder {
    flex: 1;
    min-height: 0;
}

.erp-scope-tabs > .ant-tabs-content-holder > .ant-tabs-content,
.erp-sales-tabs > .ant-tabs-content-holder > .ant-tabs-content,
.erp-scope-tabs .ant-tabs-tabpane,
.erp-sales-tabs .ant-tabs-tabpane {
    height: 100%;
    min-height: 0;
}

/* 页签内容 = 上面一行添加表单 + 下面占满剩余的表格。
   只给「当前页签」加 flex：antd 靠 .ant-tabs-tabpane-hidden 的 display:none 藏起非当前页签，
   这里要是无差别给所有 .ant-tabs-tabpane 设 display，隐藏的页签也会被撑出来 ——
   两个页签各占一份高度，容器直接翻一倍（实测 sh 673 / ch 368）。 */
.erp-scope-tabs .ant-tabs-tabpane-active,
.erp-sales-tabs .ant-tabs-tabpane-active {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.erp-scope-tabs .erp-table-wrap,
.erp-sales-tabs .erp-table-wrap {
    flex: 1;
    min-height: 0;
    height: auto;
}

/* 页签里的「添加」行：不参与高度分配，跟着内容走，表格吃掉剩下的高度。 */
.erp-scope-add {
    flex: none;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 10px;
    color: var(--erp-text-secondary);
    font-size: 13px;
}

/* 查询遮罩：只盖内容区这一块，压暗 + 居中转圈。
   不盖搜索栏与合计 —— 加载期间那两个数仍要看得见，否则会以为页面死了。 */
.erp-page-loading {
    position: absolute;
    inset: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--erp-mask-bg, rgba(0, 0, 0, 0.18));
    border-radius: var(--erp-radius);
}

/* 分页条不参与高度分配：卡片一多，它被压扁就点不到了。
   底部留 2px 是给分页控件那 1px 的行高误差兜底 —— 不留的话最后一行页码会贴着边被裁掉。 */
.erp-content-card > .erp-page-main > .erp-store-card-pager {
    flex: none;
    padding-bottom: 2px;
}

/* 选中的字典要有明确标记：两栏布局里不给当前项底色，就得回头看右栏标题才知道在看谁。 */
.erp-dict-row-active {
    background: var(--erp-hover-bg);
}

/* 抽屉里 说明 / 备注 输入框下方的灰色小字。 */
.erp-form-hint {
    color: var(--erp-text-secondary);
    font-size: 12px;
    line-height: 18px;
}

/* ---------- 自有仓库存页：仓位栏 / 筛选行 / 导入差异 ---------- */

/* 仓位栏：仓库是一本账的上下文，单独占一条放在筛选行上面 ——
   跟搜索按钮挤在一起会和「只看有货」抢视线，也看不出这个仓的家底。 */
.erp-warehouse-bar {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    padding: 8px 12px;
    background: var(--erp-surface-alt);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
}

.erp-warehouse-stats {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
    color: var(--erp-text-secondary);
    font-size: 13px;
}

.erp-warehouse-stats b {
    color: var(--erp-text);
    font-variant-numeric: tabular-nums;
}

/* 整仓级操作推到最右：它们管的是整个仓，不是当前筛出来的这几行。 */
.erp-warehouse-actions {
    margin-left: auto;
    display: flex;
    gap: 8px;
}

/* 标签与控件同行同基线：竖排（标签在上）会把一排手感一致的控件截成两截，
   还会把整行撑高，和旁边的按钮对不齐。 */
.erp-field-inline {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--erp-text-secondary);
}

/* 抽屉 / 弹窗里的筛选行：控件底部对齐，按钮按内容宽 ——
   不给宽度的按钮会被 flex 等分拉成一根长条，看着像个输入框。 */
.erp-filter-row {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

.erp-filter-item {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.erp-filter-item > label {
    font-size: 13px;
    color: var(--erp-text-secondary);
}

/* 导入差异明细：等宽列 + 数字右对齐，几十行扫下来列对得齐，不用逐行读。 */
.erp-diff-list {
    margin-top: 10px;
    max-height: 260px;
    overflow: auto;
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
}

.erp-diff-row {
    display: flex;
    gap: 12px;
    padding: 4px 8px;
    font-size: 13px;
    border-bottom: 1px solid var(--erp-border);
}

.erp-diff-row:last-child {
    border-bottom: none;
}

/* 表头钉住：差异行往往几十上百条，滚起来要有列参照。 */
.erp-diff-head {
    position: sticky;
    top: 0;
    background: var(--erp-surface-alt);
    color: var(--erp-text-secondary);
    font-weight: 600;
}

.erp-diff-article {
    width: 140px;
}

.erp-diff-size {
    width: 56px;
}

.erp-diff-qty {
    width: 110px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.erp-diff-delta {
    width: 70px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.erp-diff-delta.is-up {
    color: #389e0d;
}

.erp-diff-delta.is-down {
    color: #cf1322;
}

.erp-diff-kind {
    color: var(--erp-text-secondary);
}

/* 没有自有仓时的引导：光秃秃一行字会被当成「加载失败」，
   给个虚线框说明去哪儿能建。 */
.erp-empty-hint {
    padding: 16px;
    background: var(--erp-surface-alt);
    border: 1px dashed var(--erp-border-strong);
    border-radius: var(--erp-radius);
    color: var(--erp-text-secondary);
    font-size: 13px;
    line-height: 1.8;
}

@media (max-width: 1024px) {
    .erp-dict-layout {
        grid-template-columns: 1fr;
    }
}

/* ==================== 彪马导出页 ==================== */

/* 比价文件上传区：与导入的拖拽区同一套观感，input 透明铺满整块，
   同时接管「点击选择」与「拖入」，定位上下文必须是本元素。 */
.erp-export-drop {
    position: relative;
    display: block;
    padding: 18px 16px;
    text-align: center;
    background: var(--erp-surface);
    border: 1px dashed var(--erp-border-strong);
    border-radius: var(--erp-radius);
    cursor: pointer;
    transition: border-color 0.2s;
}

.erp-export-drop:hover {
    border-color: var(--ant-primary-color);
}

.erp-export-drop input[type="file"] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.erp-export-drop .anticon {
    margin-bottom: 6px;
    font-size: 26px;
    color: var(--ant-primary-color);
}

.erp-export-drop-text {
    margin: 0;
    font-size: 14px;
}

.erp-export-drop-hint {
    margin: 2px 0 0;
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

/* 已上传文件列表：文件名 + 大小 + 删除，选中态与列表行保持一致的圆角与描边。 */
.erp-export-file {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    margin-top: 6px;
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    font-size: 13px;
}

.erp-export-file-name {
    flex: 1;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.erp-export-file-size {
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

.erp-export-empty {
    margin: 0;
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

/* 导出结果提示：把这次导出了哪几套模板讲清楚，避免用户不知道包里有什么。 */
.erp-export-summary {
    margin-top: 4px;
    color: var(--erp-text-secondary);
    font-size: 12px;
    line-height: 20px;
}

/* ---------- 店铺分析（/order/shop-analysis） ---------- */

/* 筛选行：日期、快捷区间、店铺、按钮一条排开，放不下自动换行。 */
.erp-sa-filter {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 14px;
}

.erp-sa-tilde {
    color: var(--erp-text-tertiary);
}

.erp-sa-quick {
    display: flex;
    gap: 6px;
}

/* 查询按钮推到行尾：筛选条件在左、动作在右，扫一眼就知道先填什么再点什么。 */
.erp-sa-filter-actions {
    display: flex;
    gap: 8px;
    margin-left: auto;
}

/* 四张核心卡：跟工作台同款四列，窄屏退两列。 */
.erp-sa-kpi {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 12px;
}

.erp-sa-kpi-card {
    padding: 12px 14px;
    border: 1px solid var(--erp-border);
    border-radius: 8px;
    background: #fff;
    min-width: 0;
}

.erp-sa-kpi-label {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

.erp-sa-kpi-value {
    margin-top: 4px;
    font-size: 22px;
    font-weight: 600;
    color: var(--erp-text-primary);
    line-height: 1.2;
}

.erp-sa-kpi-unit {
    margin-left: 4px;
    font-size: 12px;
    font-weight: 400;
    color: var(--erp-text-tertiary);
}

.erp-sa-kpi-foot {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 6px;
    font-size: 12px;
}

.erp-sa-kpi-note {
    color: var(--erp-text-tertiary);
}

/* 环比涨跌：涨绿跌红。「上期无数据」是中性灰 —— 没有基准时不能假装是 0%。 */
.erp-sa-delta {
    flex: none;
    padding: 1px 6px;
    border-radius: 4px;
    background: var(--erp-surface-alt, rgba(0, 0, 0, .04));
    color: var(--erp-text-secondary);
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}

    .erp-sa-delta.is-up {
        background: rgba(82, 196, 26, .12);
        color: #52c41a;
    }

    .erp-sa-delta.is-down {
        background: rgba(255, 77, 79, .12);
        color: #ff4d4f;
    }

/* 分析页的明细表：数字列右对齐并用等宽数字，不然每行的位数不一样会看串行。 */
.erp-sa-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}

    .erp-sa-table th,
    .erp-sa-table td {
        padding: 7px 10px;
        border-bottom: 1px solid var(--erp-border);
        white-space: nowrap;
    }

    .erp-sa-table th {
        position: sticky;
        top: 0;
        z-index: 1;
        background: var(--erp-surface, #fff);
        color: var(--erp-text-secondary);
        font-weight: 500;
        text-align: left;
    }

    .erp-sa-table td {
        color: var(--erp-text-primary);
    }

    .erp-sa-table .is-right,
    .erp-sa-table th.is-right {
        text-align: right;
        font-variant-numeric: tabular-nums;
    }

    .erp-sa-table th.is-sortable {
        cursor: pointer;
        user-select: none;
    }

        .erp-sa-table th.is-sortable:hover {
            color: var(--erp-primary);
        }

/* 表体限高滚动：表头已 sticky，翻长列表时始终知道每列是什么。 */
.erp-sa-scroll {
    max-height: 380px;
    overflow-y: auto;
}

/* 类别色点：与环图扇区同色，两处对不上会被看成两个东西。 */
.erp-sa-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    margin-right: 6px;
    border-radius: 50%;
    vertical-align: middle;
}

/* 页签只当导航用：内容在 Tabs 外面，页签内容区不参与高度分配。
   放进 TabPane 会走进 antd 的页签高度链，中间任何一层没有 min-height:0 就会撑出双滚动条。 */
.erp-sa-tabs .ant-tabs-content-holder {
    display: none;
}

.erp-sa-tabs {
    margin-top: 4px;
}

/* 年度汇总：一年一块，头上是四个数，下面是 12 个月的小柱。 */
.erp-sa-year {
    padding: 12px 0;
    border-bottom: 1px dashed var(--erp-border);
}

    .erp-sa-year:last-child {
        border-bottom: none;
    }

.erp-sa-year-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 12px;
}

/* 结算两个数单独一行：head 上已经摆了件数与金额，再塞进去会读不出来。 */
.erp-sa-year-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 14px;
    margin-top: 6px;
    font-size: 12px;
    color: var(--erp-text-secondary);
}

    .erp-sa-year-foot b {
        color: var(--erp-text-primary);
        font-variant-numeric: tabular-nums;
    }

.erp-sa-year-label {
    font-size: 14px;
    font-weight: 600;
    color: var(--erp-text-primary);
}

.erp-sa-year-num {
    font-size: 15px;
    font-weight: 600;
    color: var(--erp-text-primary);
    font-variant-numeric: tabular-nums;
}

.erp-sa-year-note {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

.erp-sa-monthbars {
    display: flex;
    align-items: flex-end;
    gap: 6px;
    height: 96px;
    margin-top: 10px;
}

.erp-sa-monthbar {
    display: flex;
    flex: 1;
    flex-direction: column;
    justify-content: flex-end;
    align-items: center;
    height: 100%;
    min-width: 0;
}

.erp-sa-monthbar-fill {
    width: 100%;
    max-width: 34px;
    border-radius: 3px 3px 0 0;
    background: linear-gradient(180deg, #1677ff 0%, rgba(22, 119, 255, .55) 100%);
}

.erp-sa-monthbar-label {
    margin-top: 4px;
    font-size: 11px;
    color: var(--erp-text-tertiary);
}

@media (max-width: 1100px) {
    .erp-sa-kpi {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ---------- 卡片间距（两页共用） ---------- */

/* 卡片一条竖列排下来时自动留间距（首页、店铺分析都是这种排法）。
   .erp-wb-cards / .erp-wb-row 自己有 gap，不要再叠一层，否则间距会翻倍。 */
.erp-wb-card + .erp-wb-card {
    margin-top: 16px;
}

.erp-wb-cards > .erp-wb-card + .erp-wb-card,
.erp-wb-row > .erp-wb-card + .erp-wb-card {
    margin-top: 0;
}

/* ---------- 年度仪表盘（首页） ---------- */

/* 三个仪表盘 + 右侧一列补充数字。
   右侧那列不是凑数：弧只回答「做到几成」，利润率 / 客单价 / 件数回答「做得好不好」，
   两者缺一个就会得出错误结论（营业额冲上去了、利润率却掉下来了）。 */
/* 年度经营仪表盘：三弧 + 年度平台单数占比 + 侧栏。
   占比图插在弧与侧栏之间 —— 「总量做到几成」和「单子从哪来」是同一层的两个问题，挨着看才连得起来。 */
.erp-wb-gauges {
    display: grid;
    grid-template-columns:
        repeat(3, minmax(0, 1fr))
        minmax(220px, 300px)
        minmax(200px, 250px);
    gap: 12px;
    align-items: stretch;
}

/* 这一格单独居中：三弧与侧栏都是 flex-end（内容贴底），环图贴着底会显得掉下来。 */
.erp-wb-gauge-share {
    justify-content: center;
}

.erp-wb-gauge {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 10px 10px 12px;
    border: 1px solid var(--erp-border);
    border-radius: 12px;
    background: var(--erp-surface-alt);
    min-width: 0;
}

.erp-wb-gauge-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-size: 12px;
}

.erp-wb-gauge-ref {
    color: var(--erp-text-tertiary);
}

.erp-wb-gauge-side {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 14px 16px;
    border: 1px solid var(--erp-border);
    border-radius: 12px;
    background: var(--erp-surface-alt);
}

.erp-wb-gauge-side-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

    .erp-wb-gauge-side-row b {
        font-size: 15px;
        font-weight: 600;
        color: var(--erp-text-primary);
        font-variant-numeric: tabular-nums;
    }

/* 参照值怎么来的必须写清楚：年化出来的数被当成去年实绩，是这类仪表盘最常出现的误读。 */
.erp-wb-gauge-side-note {
    margin-top: auto;
    padding-top: 10px;
    border-top: 1px dashed var(--erp-border);
    font-size: 11px;
    line-height: 1.75;
    color: var(--erp-text-tertiary);
}

/* ---------- 店铺分析页 KPI：与首页指标卡同一套视觉 ---------- */
/* 两页的卡片必须长得一样：同一个「发货量」在首页和店铺分析页换了张脸，会被当成两个指标。 */
.erp-sa-kpi-card {
    padding: 14px 16px;
    border-radius: 12px;
    background: var(--erp-surface);
    box-shadow: 0 1px 2px rgba(15, 23, 42, .03), 0 8px 24px rgba(15, 23, 42, .04);
    transition: box-shadow .2s ease, transform .2s ease;
}

    .erp-sa-kpi-card:hover {
        box-shadow: 0 2px 4px rgba(15, 23, 42, .04), 0 10px 24px rgba(15, 23, 42, .07);
        transform: translateY(-1px);
    }

@media (max-width: 1500px) {
    /* 窄屏放不下「三弧 + 占比图 + 侧栏」：先让侧栏掉行占满整行 ——
       它是一列数字，挪走不伤阅读顺序；弧和占比图还能并排。 */
    .erp-wb-gauges {
        grid-template-columns: repeat(3, minmax(0, 1fr)) minmax(200px, 260px);
    }

    .erp-wb-gauge-side {
        grid-column: 1 / -1;
    }
}

@media (max-width: 900px) {
    /* 手机：两列。第 2 行是「单数弧 + 占比图」，侧栏继续占满整行。 */
    .erp-wb-gauges {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ===== 素材资源库（/assets）=====
   卡片网格而不是表格：缩略图才是识别素材的主要信息，表格列容不下。
   缩略图高度固定、名称单行截断，卡片高度才一致，网格不会参差不齐。 */
.erp-asset-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 12px;
}

.erp-asset-card {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    background: var(--erp-surface);
    overflow: hidden;
    transition: border-color .2s ease, box-shadow .2s ease;
}

    .erp-asset-card:hover {
        border-color: var(--erp-border-strong);
        box-shadow: 0 2px 8px rgba(15, 23, 42, .06);
    }

/* 缩略图用 contain：横图竖图都能完整看到，也不留大片空白。 */
.erp-asset-thumb {
    position: relative;
    height: 140px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--erp-surface-alt);
    cursor: pointer;
    overflow: hidden;
}

    .erp-asset-thumb > img,
    .erp-asset-thumb > video {
        max-width: 100%;
        max-height: 100%;
        object-fit: contain;
    }

.erp-asset-play {
    position: absolute;
    font-size: 28px;
    color: rgba(255, 255, 255, .9);
    text-shadow: 0 1px 4px rgba(0, 0, 0, .45);
    pointer-events: none;
}

.erp-asset-file {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

    .erp-asset-file .anticon {
        font-size: 32px;
    }

.erp-asset-body {
    padding: 8px 10px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1;
}

.erp-asset-name {
    font-size: 13px;
    color: var(--erp-text);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.erp-asset-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
}

.erp-asset-size,
.erp-asset-sub {
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

/* 备注最多两行：名称与分类是主要信息，备注不该把卡片撑成一屏。 */
.erp-asset-remark {
    color: var(--erp-text-secondary);
    font-size: 12px;
    line-height: 1.5;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.erp-asset-actions {
    display: flex;
    gap: 4px;
    padding: 4px 8px;
    border-top: 1px solid var(--erp-border);
}

/* 预览弹窗：限制最大高度，4K 图不至于把弹窗撑出屏幕。 */
.erp-asset-preview > img {
    max-width: 100%;
    max-height: 60vh;
    display: block;
    margin: 0 auto;
}

.erp-asset-preview > video {
    width: 100%;
    max-height: 60vh;
}

.erp-asset-preview-file {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 24px 0;
    color: var(--erp-text-secondary);
}

    .erp-asset-preview-file .anticon {
        font-size: 28px;
    }

.erp-asset-preview-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    padding-top: 12px;
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

/* 左侧分类 + 右侧素材：分类固定就那么几个，常驻侧栏比塞进工具栏下拉里少一次点击。 */
.erp-asset-layout {
    /* 拖拽遮罩要盖住整块区域，所以这里得是定位上下文。 */
    position: relative;
    display: flex;
    /* stretch 而不是 flex-start：两栏都拉到卡片底部，右栏内部才有高度可分给网格区。 */
    align-items: stretch;
    gap: 16px;
    /* 高度链：#erp-page-body（JS 算一次写死）→ .erp-content-card（100%）→ 这里。
       min-height:0 是必需的，否则 flex 子项按内容撑开、把外层顶出滚动条。 */
    height: 100%;
    min-height: 0;
}

/* 卡片对非表格子项一律 flex:none（那是给表格页的工具栏留的），素材页这块要吃掉全部剩余高度。 */
.erp-content-card > .erp-asset-layout {
    flex: 1;
    min-height: 0;
}

.erp-asset-side {
    flex: 0 0 168px;
    width: 168px;
    padding: 4px;
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    background: var(--erp-surface);
    /* 分类将来变多时侧栏自己滚，不把整块布局顶高。 */
    overflow: auto;
}

.erp-asset-side-title {
    padding: 8px 10px 6px;
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

.erp-asset-cat {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border-radius: var(--erp-radius);
    color: var(--erp-text-secondary);
    font-size: 13px;
    cursor: pointer;
    transition: background .2s ease, color .2s ease;
}

    .erp-asset-cat:hover {
        background: var(--erp-hover-bg);
        color: var(--erp-text);
    }

    .erp-asset-cat.is-active {
        background: var(--erp-primary-bg);
        color: var(--erp-primary);
        font-weight: 500;
    }

.erp-asset-cat-text {
    flex: 1;
}

.erp-asset-main {
    /* min-width 必须写：不加的话网格的 minmax(200px,1fr) 会把 flex 子项顶宽，右栏溢出。 */
    flex: 1 1 auto;
    min-width: 0;
    /* 纵向铺：工具栏与分页按内容高，剩下的全给网格区 —— 卡片才不会被内容顶出滚动条。 */
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-height: 0;
}

/* 除网格区外都按内容高度（工具栏、分页）。 */
.erp-asset-main > *:not(.erp-asset-scroll) {
    flex: none;
}

/* 网格的滚动容器：素材多时在这一层滚，页面整体不滚
   （#erp-page-body 也是滚动容器，两层一起滚会出现两条滚动条）。 */
.erp-asset-scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

/* 空态居中：没有素材时留白落在卡片区中央，比贴着顶部更像「这里是空的」。 */
.erp-asset-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    min-height: 180px;
}

.erp-asset-drop-tip {
    margin-left: 4px;
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

/* 隐藏的文件输入：拖拽落下的文件由 app.js 灌进它，再触发 change 走上传链路。 */
.erp-asset-hidden-input {
    display: none;
}

/* 拖拽遮罩：默认隐藏，拖拽期间 app.js 给容器加 .is-dragging 才出现。
   pointer-events 关掉：显隐与文件收集都由 JS 在容器上处理，遮罩不吃事件最省事。 */
.erp-asset-drop-mask {
    position: absolute;
    inset: 0;
    z-index: 10;
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    border: 2px dashed var(--erp-primary);
    border-radius: var(--erp-radius);
    background: var(--erp-primary-bg);
    color: var(--erp-primary);
    pointer-events: none;
}

.erp-asset-layout.is-dragging .erp-asset-drop-mask,
.erp-asset-layout.is-uploading .erp-asset-drop-mask {
    display: flex;
}

    .erp-asset-drop-mask .anticon {
        font-size: 40px;
    }

.erp-asset-drop-mask-text {
    font-size: 16px;
    font-weight: 500;
}

.erp-asset-drop-mask-sub {
    color: var(--erp-text-secondary);
    font-size: 12px;
}

@media (max-width: 768px) {
    /* 窄屏放不下侧栏：分类横过来铺一行，素材区照旧在下面。 */
    .erp-asset-layout {
        flex-direction: column;
    }

    .erp-asset-side {
        display: flex;
        flex: none;
        flex-wrap: wrap;
        gap: 4px;
        width: 100%;
        /* 横过来之后不该再出滚动条，几行分类直接铺开。 */
        overflow: visible;
    }

    .erp-asset-side-title {
        width: 100%;
        padding-bottom: 0;
    }

    .erp-asset-cat {
        padding: 6px 10px;
    }
}

/* ---------- 彪马「无价格货号」监控 ---------- */

/* 库存汇总页「无价格」视图上面那句说明：
   空白表格不会自己解释「为什么这些货号没有价格列」，不写这句用户会以为接口坏了。 */
.erp-noprice-hint {
    margin: 0 0 8px;
    color: var(--erp-text-tertiary);
    font-size: 12px;
    line-height: 18px;
}

/* 监控卡的大数字：跟核心指标卡一个字号，扫一眼就能看到。 */
.erp-np-num {
    font-size: 22px;
    font-weight: 600;
    line-height: 1.2;
}

.erp-np-unit {
    margin-left: 4px;
    font-size: 12px;
    font-weight: 400;
    color: var(--erp-text-tertiary);
}

.erp-np-sub {
    margin-top: 4px;
    color: var(--erp-text-secondary);
    font-size: 12px;
    line-height: 18px;
}

/* 三种级别：正常绿、少量橙、超阈值红。
   告警色用固定值而不是主题变量 —— 跟着主题深浅走会变淡，提醒就不再是提醒了。 */
.erp-np-ok { color: #52c41a; }
.erp-np-warn { color: #fa8c16; }
.erp-np-danger { color: #ff4d4f; }

.erp-np-ok-line {
    padding: 6px 0;
    font-size: 13px;
}

/* 明细表与上面那行说明分开一点：紧贴着会让人以为它是同一块文字的续行。 */
.erp-np-sub + table {
    margin-top: 10px;
}

/* ---------- 店铺结算 · 待结算方块图（/order/settlement） ---------- */

/* 画布：占满页签内容区，方块绝对定位铺在里面。
   2px 的缝由 .erp-st-tile 的内边距给 —— 绝对定位的方块之间没有 gap 可用。 */
.erp-st-map {
    position: relative;
    flex: 1;
    min-height: 260px;
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    background: var(--erp-surface-alt, #f5f6f8);
    overflow: hidden;
}

.erp-st-empty {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--erp-text-tertiary);
    font-size: 13px;
}

.erp-st-tile {
    position: absolute;
    padding: 2px;
    box-sizing: border-box;
    overflow: hidden;
}

.erp-st-card {
    position: relative;
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 6px 8px;
    border-radius: 6px;
    color: #fff;
    text-align: center;
    overflow: hidden;
    /* 划入只动 transform / box-shadow / filter，不动宽高 —— 改宽高会让整块重排，旁边的方块跟着抖。 */
    transition: transform .18s ease, box-shadow .18s ease, filter .18s ease;
}

.erp-st-tile:hover .erp-st-card {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(15, 23, 42, .28);
    filter: brightness(1.06);
    z-index: 3;
}

/* 颜色分档 = 占待结算合计的比例（阈值与 BandClassOf 一致，改一处要改两处）。
   四个色都压到「白字看得清」的深度：浅色系在深色主题下会糊成一片。 */
.erp-st-card.is-band-0 { background: linear-gradient(135deg, #4c6ef5, #3b5bdb); }
.erp-st-card.is-band-1 { background: linear-gradient(135deg, #0ca678, #0b7285); }
.erp-st-card.is-band-2 { background: linear-gradient(135deg, #f08c00, #e8590c); }
.erp-st-card.is-band-3 { background: linear-gradient(135deg, #8494ab, #64748b); }

.erp-st-body {
    width: 100%;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}

/* 名称与金额都要能截断：方块宽度是算出来的，长店铺名一定会撑破。 */
.erp-st-name,
.erp-st-amount {
    max-width: 100%;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.erp-st-name {
    font-size: 12px;
    opacity: .92;
}

.erp-st-amount {
    font-size: 15px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.erp-st-rows {
    font-size: 11px;
    opacity: .8;
}

/* 字号档位：方块越小字越小，最小档只留店铺名（金额靠 tooltip 看）。 */
.erp-st-card.is-lg .erp-st-name { font-size: 15px; }
.erp-st-card.is-lg .erp-st-amount { font-size: 26px; }
.erp-st-card.is-lg .erp-st-rows { font-size: 12px; }

.erp-st-card.is-md .erp-st-name { font-size: 13px; }
.erp-st-card.is-md .erp-st-amount { font-size: 18px; }

.erp-st-card.is-sm .erp-st-amount { font-size: 14px; font-weight: 600; }
.erp-st-card.is-sm .erp-st-rows { display: none; }

.erp-st-card.is-xs .erp-st-name { font-size: 11px; }
.erp-st-card.is-xs .erp-st-amount,
.erp-st-card.is-xs .erp-st-rows { display: none; }

/* 划入才出现的「去结算」：默认透明且不吃点击。
   pointer-events 必须跟着一起切 —— 否则透明按钮照样能点到，方块图上点哪儿都弹建单弹窗。 */
.erp-st-hover {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    background: rgba(15, 23, 42, .42);
    opacity: 0;
    transform: translateY(4px);
    pointer-events: none;
    transition: opacity .18s ease, transform .18s ease;
}

.erp-st-tile:hover .erp-st-hover {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}

/* 小方块里的「结算」：不用 antd 按钮（56px+ 宽会在 27px 的方块里被裁掉），
   两个字 + 小内边距刚好放得下。 */
.erp-st-mini-action {
    padding: 1px 5px;
    border-radius: 3px;
    background: #1677ff;
    color: #fff;
    font-size: 11px;
    line-height: 15px;
    white-space: nowrap;
    cursor: pointer;
}

/* 触屏没有 hover：按钮常驻，否则方块图在手机 / 平板上完全点不动。 */
@media (hover: none) {
    .erp-st-hover {
        opacity: 1;
        transform: none;
        pointer-events: auto;
        background: rgba(15, 23, 42, .3);
    }
}

/* 颜色图例：只有颜色没有说明，用户没法知道深浅代表什么。 */
.erp-st-legend {
    display: inline-flex;
    align-items: center;
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

.erp-st-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    margin: 0 4px 0 10px;
    border-radius: 2px;
}

.erp-st-dot.is-band-0 { background: #4263eb; }
.erp-st-dot.is-band-1 { background: #0ca678; }
.erp-st-dot.is-band-2 { background: #f08c00; }
.erp-st-dot.is-band-3 { background: #8494ab; }

/* ===== 下快递（手工寄件） =====
   版面要点：寄件 / 收件两张卡片**并排**（grid 两列），窄屏才折成一列 ——
   这两块是面单上要印出来的内容，并排才能左右对照核对。
   卡片底部的灰底摘要是「真正会发给渠道的那一份」，下单前核对它而不是下拉框里的名字。 */
.erp-me {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

@media (max-width: 900px) {
    .erp-me {
        grid-template-columns: 1fr;
    }
}

.erp-me-card {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 12px;
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    background: var(--erp-surface);
}

.erp-me-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.erp-me-card-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--erp-text);
}

.erp-me-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.erp-me-field > label {
    font-size: 13px;
    color: var(--erp-text-secondary);
}

.erp-me-row {
    display: flex;
    gap: 10px;
}

.erp-me-row > .erp-me-field {
    flex: 1 1 0;
}

/* 省 / 市 / 区 这种三格一行：平均分配，格子太窄时由 Input 自己省略。
   不写死宽度 —— 渠道侧省名长度差得远（「内蒙古自治区」对「京」）。 */
.erp-me-row-3 > .erp-me-field {
    flex: 1 1 0;
}

.erp-me-summary {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: auto;
    padding: 8px 10px;
    border-radius: var(--erp-radius);
    background: var(--erp-surface-alt);
    font-size: 13px;
    color: var(--erp-text-secondary);
}

.erp-me-summary-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    word-break: break-all;
}

.erp-me-label {
    flex: none;
    width: 52px;
    color: var(--erp-text-tertiary);
}

.erp-me-phone {
    color: var(--erp-text-tertiary);
}

.erp-me-paste {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

.erp-me-paste > .ant-input {
    flex: 1;
}

/* 寄件 / 收件并排：面单上印的就是这两块，并排才能左右对照核对。 */
.erp-me-parties {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

@media (max-width: 900px) {
    .erp-me-parties {
        grid-template-columns: 1fr;
    }
}

/* 同一行两个输入（姓名 + 电话）。 */
.erp-me-line {
    display: flex;
    gap: 8px;
}

.erp-me-line > .ant-input {
    flex: 1 1 0;
    min-width: 0;
}

/* 货品与取件挤在一行：重量/件数是必填项，不能藏在第二屏；
   窄屏才折成两列。 */
.erp-me-goods {
    display: grid;
    grid-template-columns: 132px 96px 1fr 240px auto;
    gap: 12px;
    align-items: end;
    margin-top: 12px;
}

@media (max-width: 900px) {
    .erp-me-goods {
        grid-template-columns: 1fr 1fr;
    }
}

/* 预约取件：日期（今天 / 明天）+ 时段下拉。下拉里只列还来得及的那些段，
   选不到的段摆出来只会让人选了又被告知约不上。 */
.erp-me-pickup {
    display: flex;
    align-items: center;
    gap: 8px;
}

.erp-me-pickup > .erp-me-seg {
    flex: 0 0 auto;
}

/* 预约取件的「今天 / 明天」：两格分段控件，比下拉少一次点击。 */
.erp-me-seg {
    display: inline-flex;
    height: 32px;
    overflow: hidden;
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
}

.erp-me-seg > button {
    flex: 1 1 0;
    padding: 0 14px;
    border: 0;
    background: var(--erp-surface);
    color: var(--erp-text-secondary);
    font-size: 13px;
    cursor: pointer;
    transition: background-color 0.15s, color 0.15s;
}

.erp-me-seg > button + button {
    border-left: 1px solid var(--erp-border);
}

.erp-me-seg > button.is-on {
    background: var(--erp-primary);
    color: #fff;
}

.erp-me-pickup-hint {
    padding-bottom: 7px;
    font-size: 12px;
    color: var(--erp-text-tertiary);
    white-space: nowrap;
}

/* 快递选择：一排卡片，横向可滚 —— 与各家快递 App 的下单页一致，
   人扫一眼价格就能决定，不需要展开下拉再一项项比。 */
.erp-me-quote {
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--erp-border);
}

.erp-me-quote-head {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 10px;
}

.erp-me-quote-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--erp-text);
}

.erp-me-quote-error {
    font-size: 13px;
    color: #d4380d;
}

.erp-me-quote-empty {
    padding: 22px 0;
    text-align: center;
    font-size: 13px;
    color: var(--erp-text-tertiary);
}

.erp-me-refresh {
    padding: 0;
    border: 0;
    background: none;
    color: var(--erp-primary);
    font-size: 13px;
    cursor: pointer;
}

.erp-me-cards {
    display: flex;
    gap: 10px;
    padding: 4px 2px 10px;
    overflow-x: auto;
}

.erp-me-qcard {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    width: 124px;
    padding: 12px 8px;
    border: 1px solid var(--erp-border);
    border-radius: 8px;
    background: var(--erp-surface);
    cursor: pointer;
    transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s;
}

.erp-me-qcard:hover:not(:disabled) {
    border-color: var(--erp-primary);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    transform: translateY(-1px);
}

/* 选中态：蓝色边框 + 浅蓝底 —— 截图里那套，扫一眼就知道选了哪家。 */
.erp-me-qcard.is-on {
    border-color: var(--erp-primary);
    background: color-mix(in srgb, var(--erp-primary) 8%, var(--erp-surface));
}

.erp-me-qcard.is-off {
    opacity: 0.5;
    cursor: not-allowed;
}

.erp-me-qcard-name {
    font-size: 14px;
    font-weight: 600;
    color: var(--erp-text);
}

.erp-me-qcard.is-on .erp-me-qcard-name {
    color: var(--erp-primary);
}

.erp-me-qcard-price {
    font-size: 20px;
    font-weight: 700;
    line-height: 1.1;
    color: #fa541c;
    font-variant-numeric: tabular-nums;
}

.erp-me-qcard-price.is-muted {
    font-size: 15px;
    color: var(--erp-text-secondary);
}

.erp-me-qcard.is-off .erp-me-qcard-price {
    color: var(--erp-text-tertiary);
}

.erp-me-qcard-sub {
    font-size: 11px;
    line-height: 1.3;
    color: var(--erp-text-tertiary);
    text-align: center;
}

.erp-me-strike {
    text-decoration: line-through;
}

/* 报价加载中的骨架条：比转圈更能预示「这里会出现一排卡片」。 */
.erp-me-card-skeleton {
    flex: 0 0 auto;
    width: 124px;
    height: 98px;
    border-radius: 8px;
    background: linear-gradient(90deg, var(--erp-surface-alt) 25%, rgba(128, 128, 128, 0.12) 37%, var(--erp-surface-alt) 63%);
    background-size: 400% 100%;
    animation: erp-me-shimmer 1.2s ease infinite;
}

@keyframes erp-me-shimmer {
    0% { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}

/* 自叫快递的三个补充字段 */
.erp-me-manual {
    display: grid;
    grid-template-columns: 1fr 130px 130px;
    gap: 12px;
    margin-top: 4px;
}

.erp-me-foot {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 16px;
}

.erp-me-foot > .ant-input {
    flex: 1 1 auto;
    min-width: 0;
}

.erp-me-foot-right {
    display: flex;
    align-items: center;
    gap: 12px;
    white-space: nowrap;
}

/* 下单遮罩：会扣钱、要等十几秒 —— 不盖住整块界面，人一定会以为没点上而重复点。 */
.erp-me-wrap {
    position: relative;
    min-height: 140px;
}

.erp-me-overlay {
    position: absolute;
    inset: -24px 0;
    z-index: 20;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    background: color-mix(in srgb, var(--erp-surface) 90%, transparent);
}

.erp-me-overlay-title {
    margin: 10px 0 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--erp-text);
}

.erp-me-overlay-sub {
    margin: 0;
    font-size: 13px;
    color: var(--erp-text-secondary);
}

/* 下单成功页 */
.erp-me-result {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-left: 12px;
}

.erp-me-result-row {
    display: flex;
    gap: 12px;
    font-size: 14px;
    color: var(--erp-text);
}

.erp-me-result-row > span {
    width: 64px;
    color: var(--erp-text-tertiary);
}

.erp-me-result-actions {
    display: flex;
    justify-content: center;
    gap: 12px;
    margin-top: 20px;
}

.erp-me-muted {
    font-size: 13px;
    color: var(--erp-text-tertiary);
}

.erp-me-tip {
    font-size: 13px;
    color: var(--erp-text-secondary);
}

.erp-me-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.erp-me-target {
    font-size: 13px;
    color: var(--erp-text-secondary);
}

.erp-me-hint {
    padding: 24px 0;
    text-align: center;
    color: var(--erp-text-secondary);
}

/* 列表里的两行小格：主信息 + 下面一行弱化补充（电话 / 标签）。 */
.erp-me-cell {
    display: flex;
    flex-direction: column;
    line-height: 1.35;
}

.erp-me-cell-main {
    color: var(--erp-text);
}

.erp-me-cell-sub {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

/* 操作列：按钮锁在一行里不许折行。
   折行会把这一行的行高撑高、按钮往下掉，看起来就是「操作列整列错位」——
   取消按钮转圈时变宽最容易触发（2026-10-10）。 */
.erp-me-actions {
    display: flex;
    align-items: center;
    gap: 2px;
    white-space: nowrap;
}

/* 结算单编辑页（整页 POS 工作台）：**左栏是这张单，右栏整片是待结算明细**。
   从弹窗改成整页之后，宽度不再有上限、高度也不再写死 —— 直接吃
   .erp-content-card → .erp-page-main 这条高度链。弹窗那版的毛病正是
   「固定 1400px + 两栏各自 560px 高」：在 1366 / 1440 的屏上必定溢出，
   左边被裁掉、右边翻页条被顶到可视区外面。 */
.erp-page-main > .erp-pos {
    flex: 1;
    min-height: 0;
}

.erp-pos {
    display: flex;
    gap: 12px;
    align-items: stretch;
    height: 100%;
    min-height: 0;
    box-sizing: border-box;
}

/* 页头：左边是这张单的抬头、右边是保存与返回。 */
.erp-pos-pagehead {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

/* 金额读数带（应付 → 优惠 → 实付 → 收益）：它就是金额输入框下面那条**结算结果**。
   原来它横在页头、离金额输入框隔着一整条设置条 —— 改完一个数得抬头往上看才知道变到哪儿去；
   现在是设置条右列的第二块、紧贴在三个数字框下面（见 razor 里 .erp-pos-block.is-summary）。
   覆盖写在 is-pos 里、不直接改 .erp-summary-bar —— 那条全站（快递 / 物流页）都在用。 */
.erp-summary-bar.is-pos {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    /* **紧凑靠左**：每格按自己的内容宽排、格与格之间固定 24px，整条从左边起。
       曾经换过「等分格」（minmax(126px, 1fr)）想让数字右端对齐成一列：
       容器一宽每格就被拉到 200px 以上，一格里的「标签 ………… 数字」得横跨半屏去接，
       反而更慢 —— 金额是「标签 + 紧跟着的数」成组读的，组间留空档比组内拉长更好认。
       **别再改成等分格**。 */
    justify-content: flex-start;
    gap: 6px 24px;
    padding: 0;
    background: none;       /* 块里不再套一层底：它本来就落在设置条那块浅底上 */
    border: none;
    font-size: 12px;
}

    /* 一格 = 标签 + 数字，中间只隔 8px。 */
    .erp-summary-bar.is-pos > span {
        display: flex;
        flex: none;
        align-items: baseline;
        gap: 8px;
        min-width: 0;
        white-space: nowrap;
    }

    /* 数字比标签大两档、加粗：这一条是**结论** ——
       标签只是「这是什么钱」（12px 灰），数字才是要一眼读走的（16px 加黑）。 */
    .erp-summary-bar.is-pos b {
        font-size: 16px;
        font-weight: 700;
        color: var(--erp-text);
        font-variant-numeric: tabular-nums;
    }

/* 副标题一行灰字：店铺 / 品牌 / 待结算行数 / 小票区行数。
   原来这行是「左右两段」的，右端顶着个 20px 的「应付」KPI ——
   那个数在下面那条合计条里已经有一个（而且整条更讲得清），
   一屏两处摆同一个金额，看的人得先判断「哪个是真」，所以撤掉了。 */
.erp-pos-pagesub {
    margin-top: 2px;
    font-size: 12px;
    color: var(--erp-text-secondary);
}

/* 抬头这一块吃掉页头剩下的宽度（小票那排是内容宽、按钮定宽）。 */
.erp-pos-pagetitle {
    flex: 1 1 auto;
    min-width: 0;
}

    /* 这一屏只有它一个标题，比全局页头大一档，站得住整页。 */
    .erp-pos-pagetitle > b {
        font-size: 17px;
    }

.erp-pos-pageacts {
    display: flex;
    flex: none;
    gap: 8px;
    /* 页头三块：标题 / 门店小票 / 按钮。靠右的那两块（小票 + 按钮）由小票那排的
       margin-left:auto 一起推过去，这里不用再写 auto —— 两个 auto 会平分剩余空白，
       小票和按钮之间就会多出一段没用的空档。 */
}

/* 页头上的一排门店小票：标签 + 缩略图 + 末尾一个虚框「＋」（这个虚框同时是拖放区）。
   宽度**跟着内容走、最多 520px**（与 @code 里的 HeadReceiptVisible 配套）：小票少时不要把
   页头右半边空在那里（写死 520 就会空一大片），到 520px 就开始收「+N」；
   点一下整排「张开」（.is-expanded：放开宽度 + 换行）一次看全。 */
.erp-pos-receipts {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 0 1 auto;             /* 内容多宽就多宽：小票不占位时才不留空洞 */
    max-width: 520px;
    min-width: 0;
    margin-left: auto;          /* 连同后面的「返回 / 保存」一起靠右（页头左半边留给标题） */
    padding: 4px;               /* 给右上角的删除 × 留一点余量，别把缩略图边框切掉 */
    overflow: hidden;           /* 兜底：算不准也切在这一排里，不撑页头 */
}

.erp-pos-receipts-row {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1 1 auto;
    min-width: 0;
}

    /* ImagePreviewGroup 自己会渲染一层容器：不管它是 div 还是别的，
       这两条都保证「缩略图是横排的」，不依赖它内部用什么 display。 */
    .erp-pos-receipts-row > *,
    .erp-pos-receipts-row > * > * {
        display: flex;
        align-items: center;
        gap: 6px;
        flex: none;
    }

/* 张开：这一排吃掉页头中间的空白、允许换行 —— 小票一次全摆出来，不用横着翻。
   三层都写 flex-wrap：缩略图外面还套着 ImagePreviewGroup 那层容器，在哪一层换行都成立。 */
.erp-pos-receipts.is-expanded {
    flex: 1 1 auto;
    width: auto;
    max-width: none;            /* 收起时那条 520px 上限必须解开，否则「+N」点开也放不宽 */
    overflow: visible;
}

    .erp-pos-receipts.is-expanded .erp-pos-receipts-row,
    .erp-pos-receipts.is-expanded .erp-pos-receipts-row > *,
    .erp-pos-receipts.is-expanded .erp-pos-receipts-row > * > * {
        flex-wrap: wrap;
    }

.erp-pos-receipts-title {
    flex: none;
    font-size: 12px;
    color: var(--erp-text-secondary);
}

.erp-pos-side {
    flex: 1 1 0;
    /* 栏高由父容器拉伸决定，自己必须允许收缩：min-height:0 少了，里面的滚动区
       会把栏撑到内容高度，滚动条又跑回页面容器上（双滚动条的老毛病）。 */
    min-width: 0;
    min-height: 0;
    box-sizing: border-box;
    padding: 8px;
    border: 1px solid var(--erp-border);
    border-radius: 6px;
}

/* 左栏 = 这张单要填 / 要看的全部内容：小票区、门店小票、结算方式、金额、备注。
   定宽 + 自己滚：左边有多少内容都不挤右边，右侧那整片留给待结算明细。
   560px 是「小票行那三个输入框（数量/现价/折扣）排得下一行」的宽度 ——
   再窄就会换行，一屏能看的行数掉一半。 */
/* 工作区：两栏各自铺一层浅底当「桌面」，里面的小票行 / 货架卡片才是白卡 ——
   **面**与**卡**分开，一眼看出这是两块不同的东西（原来只靠中间 12px 空档分，扫不快）。
   跟页头那条「设置条」说的是同一种语言：灰的那层永远是容器，白的才是内容。
   box-sizing 必须写：两栏都是定宽（560px），不加 padding 会被撑宽。 */
.erp-pos-side {
    padding: 8px;
    background: var(--erp-surface-alt);
    border-radius: var(--erp-radius);
    box-sizing: border-box;
}

.erp-pos-side.is-form {
    flex: 0 0 560px;
    /* 竖排：小票区吃掉剩下的高度（清单在块内滚），下面几块钉住不动。
       overflow-y:auto 只是矮屏兜底 —— 固定那几块加起来都放不下时整栏滚，不裁内容。 */
    display: flex;
    flex-direction: column;
    overflow-y: auto;
}

/* 栏里的块默认不许被压缩：高度只由「小票区」那一块伸缩决定。 */
.erp-pos-side.is-form > .erp-pos-block {
    flex: none;
}

/* 小票区自己撑满剩余高度、清单在块内滚 ——
   门店小票 / 结算方式 / 金额 / 备注 始终钉在下面（结账时要一直盯着金额，不能让它们跟着清单滚走）。 */
.erp-pos-side.is-form > .erp-pos-block.is-ticket-block {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 132px;
}

.erp-pos-block.is-ticket-block > .erp-pos-ticket {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none;      /* 整页了，不再用 42vh 卡着 */
}

.erp-pos-block.is-ticket-block > .erp-pos-empty.is-ticket {
    flex: 1 1 auto;
    height: auto;
    min-height: 96px;
}

/* 页头第二排：这张单「怎么结」—— 四块按**左右两列**摆。
   左列 = 人**填进去**的东西（结算方式 / 备注）；右列 = **钱**（金额输入 + 结算结果读数带）。
   这两件事读的顺序本就不一样：左边是「照着门店小票把值一格一格填上」，
   右边是「填完值多少」—— 输入在上、结果在下，同一列里往下看一眼就有答案。
   grid-auto-flow: column + 固定两行：四块按「结算方式、备注 | 金额、结算结果」自动分列，
   **DOM 顺序正好就是窄屏落回一列时的阅读顺序**（先填值、再看结果）。
   左列定宽 380px：结算方式那两格是 150+10+150，刚好放得下；
   再宽只是让备注那一行空着，而右列的钱要被挤窄。
   整条铺一层浅底：这一排是「设置」，下面是「干活」，一眼分开。 */
.erp-pos-pageform {
    flex: none;
    display: grid;
    grid-auto-flow: column;
    grid-template-rows: auto auto;
    grid-template-columns: minmax(0, 380px) minmax(0, 1fr);
    align-items: start;
    gap: 10px 20px;
    padding: 10px 12px;
    background: var(--erp-surface-alt);
    border-radius: var(--erp-radius);
}

/* 窄屏放不下两栏时落回一列：四块按 DOM 顺序竖排（结算方式 → 备注 → 金额 → 结算结果）。
   **grid-auto-flow 必须跟着重置**：只改列数不改流向，它还会继续往右开新列、开出屏幕外。 */
@media (max-width: 1180px) {
    .erp-pos-pageform {
        grid-auto-flow: row;
        grid-template-rows: none;
        grid-template-columns: minmax(0, 1fr);
    }
}

    /* 块本身那套「块间距 + 下边框」是给左栏竖排用的，横排到这里必须清掉，
       否则四块会各自拖着一条线、还被 margin-top 顶歪。
       ⚠️ **`:not(:first-child)` 必须并写一条**：下面给左栏写的
       `.erp-pos-block:not(:first-child) { margin-top: 10px }` 跟上面这条 `> .erp-pos-block`
       **同权重、且写在后面**（CSS 同权重比先后），只写上面那条挡不住它 ——
       结果第 2、3、4 块（备注 / 金额 / 结算结果）各自被顶下去 10px，
       四块的标题本来该在同一条水平线上，却左高右低，整条看着就是歪的。 */
    .erp-pos-pageform > .erp-pos-block,
    .erp-pos-pageform > .erp-pos-block:not(:first-child) {
        padding-bottom: 0;
        margin-top: 0;
        border-bottom: none;
    }

    /* 三格里的每一格定宽 150px，不让它跟着页头一起拉伸：页头很宽，3 等分能把一个框拉到 300px，
       一行三格看着就散。**只圈 .erp-form-row-3 里的格** ——
       备注块里那个 .erp-form-item 是自由文本，得让它撑满（否则输入框只有 150px 宽）。 */
    .erp-pos-pageform .erp-form-row-3 > .erp-form-item {
        flex: 0 0 150px;
    }

    .erp-pos-pageform .erp-form-item {
        gap: 2px;               /* 标签紧贴控件，不靠间距撑层次 */
    }

    /* 带标签那几块（结算方式 / 金额 / 备注）的「标签行」钉成同一个高度 22px：
       三块的第一行各是各自的标签（结算日期·结款商、店铺优惠…、备注），
       标签行齐 → 下一行控件（日期框 / 三个数字框 / 备注框）的上边缘才齐，
       一条设置条最忌底边参差。22px 这个数是被开关定的：左块里
       「结款商」那格标签旁边挂着一个开关，比一行 13px 文字高 2px，
       纯文字标签行若只有 20px，同一行里两格的输入框就会差出 2px。 */
    .erp-pos-pageform .erp-form-item > label,
    .erp-pos-pageform .erp-pos-labelrow {
        display: flex;
        align-items: center;
        min-height: 22px;
    }

    /* 备注块（左列下方那一块）：宽度由左列定死了（380px），
       不再写 flex —— 原来它靠 flex: 1 1 260px 在横排里吃剩下的宽度。 */

    /* 块标题行也钉到 22px：四块里「金额 / 备注」带问号图标，
       图标 14px、标题 14px 行高 21px，本来是同一档 —— 钉死成 22px 是为了
       让「标题行 22 + 标签行 22」在这条设置条里成为同一个节奏，谁都别再抖 1px。 */
    .erp-pos-pageform .erp-pos-head {
        margin-bottom: 4px;
        min-height: 22px;
    }

    .erp-pos-pageform .erp-form-row-3 {
        gap: 10px;
    }

    /* 「结款商」标题那一行：标签 + 第三方代付的开关并排。
       这两件是一组，摆在一行成一个整体；标签去掉之后开关没有名字，
       仰的是这一行的上下文（翻 DOM 别把它单拎出来）。 */
    .erp-pos-pageform .erp-pos-labelrow {
        display: flex;
        align-items: center;
        gap: 8px;
    }

/* 右栏 = 待结算明细，占满剩下的整个右侧 */
.erp-pos-side.is-shelf {
    display: flex;
    flex-direction: column;
}

/* 高度链：货架外面套了 Spin（.ant-spin-nested-loading → 匿名 div → .ant-spin-container），
   这几层默认不是 flex，链会断在「内容高度」上 —— 卡片区不滚、整栏被撑高，
   底部的翻页条就被 .erp-page-main 的 overflow:hidden 裁掉（「分页看不见」就是这么来的）。
   和表格那边（.erp-table-wrap 的 spin 链）同一个坑、同一套补法。 */
.erp-pos-side.is-shelf > .ant-spin-nested-loading,
.erp-pos-side.is-shelf > .ant-spin-nested-loading > div,
.erp-pos-side.is-shelf > .ant-spin-nested-loading .ant-spin-container {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

/* 工具栏与翻页条只占自己那一行，绝不被卡片区挤走。 */
.erp-pos-side.is-shelf > .erp-pos-head,
.erp-pos-side.is-shelf > .erp-pos-pager {
    flex: none;
}

/* 笔记本屏（1366 / 1440）上左栏窄一点，把宽度让给货架 ——
   宁可左栏自己滚，也不让货架挤成两列、一页只能看 6 个款。 */
@media (max-width: 1600px) {
    .erp-pos-side.is-form {
        flex-basis: 500px;
    }
}

/* 更窄（浏览器不最大化 / 小笔记本）再让一步：左栏压到 400px，
   小票行那三个输入框会换到第二行 —— 换行总好过横向溢出去、把金额顶出可视区。 */
@media (max-width: 1200px) {
    .erp-pos-side.is-form {
        flex-basis: 400px;
    }
}

/* 左栏里的一块：块与块之间一条细线，别让「结方式」和「金额」糊成一团。 */
.erp-pos-block {
    padding-bottom: 10px;
    border-bottom: 1px dashed var(--erp-border);
}

    .erp-pos-block:not(:first-child) {
        margin-top: 10px;
    }

    .erp-pos-block:last-child {
        border-bottom: none;
    }

.erp-pos-head {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}

.erp-pos-title {
    font-weight: 600;
}

.erp-pos-sub {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

.erp-pos-receipt {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 10px;
    padding-top: 8px;
    border-top: 1px dashed var(--erp-border-strong);
}

/* 拖放区：真正的 InputFile 铺满整块（透明度 0），
   浏览器原生的「拖到 file input 上」就能接管，不用为它写一段 JS。 */
.erp-pos-drop {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 72px;
    font-size: 12px;
    color: var(--erp-text-tertiary);
    border: 1px dashed var(--erp-border-strong);
    border-radius: 6px;
    cursor: pointer;
}

/* 页头版拖放区：一个小方块（「＋ 小票」），跟缩略图同尺寸 ——
   页头上就是「小票图 + 加号」一排，跟自己相册的上传位一样，
   不用再写一行「把小票拖到这里…」的说明文字。 */
.erp-pos-drop.is-head {
    flex: none;
    flex-direction: column;
    gap: 0;
    width: 52px;
    height: 52px;
    font-size: 11px;
    line-height: 1.1;
    text-align: center;
    transition: color .2s, border-color .2s, background .2s;
}

.erp-pos-drop:hover {
        color: var(--erp-primary);
        border-color: var(--erp-primary);
        background: var(--erp-primary-bg);
    }

.erp-pos-file {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.erp-pos-thumbs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.erp-pos-thumb {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    width: 84px;
}

    .erp-pos-thumb img {
        width: 84px;
        height: 84px;
        object-fit: cover;
        border: 1px solid var(--erp-border);
        border-radius: 4px;
    }

/* 页头版缩略图：52px 方块（跟下面的拖放区同尺寸）+ 右上角一个删除 × ——
   页头上写不下「删除」两个字，做成图标才塞得进一排。 */
.erp-pos-thumb.is-head {
    position: relative;
    width: 52px;
}

    .erp-pos-thumb.is-head img {
        width: 52px;
        height: 52px;
    }

/* 刚选中、还没落库的图：单号要先存单才生成，图片只能跟着保存走。 */
.erp-pos-thumb.is-head.is-pending {
    justify-content: center;
    height: 52px;
    color: var(--erp-primary);
    background: var(--erp-primary-bg);
    border: 1px dashed var(--erp-primary);
    border-radius: 6px;
}

/* 「+N」/「收起」：没排下的小票收成一个小方块，点它把整排张开或收回。
   跟「待保存」同样吃主色，但边框是**实的** —— 一眼能分出哪个是提示、哪个是能点的。 */
.erp-pos-thumb.is-head.is-more {
    justify-content: center;
    width: 52px;
    height: 52px;
    font-size: 12px;
    font-weight: 600;
    color: var(--erp-primary);
    background: var(--erp-primary-bg);
    border: 1px solid var(--erp-primary);
    border-radius: 6px;
    cursor: pointer;
    transition: color .2s, background .2s;
}

    .erp-pos-thumb.is-head.is-more:hover {
        color: #fff;
        background: var(--erp-primary);
    }

.erp-pos-thumb-x {
    position: absolute;
    top: 0;
    right: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    font-size: 10px;
    color: var(--erp-text-secondary);
    background: var(--erp-surface);
    border-radius: 0 0 0 6px;
    cursor: pointer;
    transition: color .2s, background .2s;
}

    .erp-pos-thumb-x:hover {
        color: #fff;
        background: #ff4d4f;
    }

.erp-pos-file-name {
    font-size: 12px;
    text-align: center;
    word-break: break-all;
}

.erp-pos-file-hint {
    font-size: 11px;
    color: var(--erp-text-tertiary);
}

/* 参活标签：与配货页同一个口径 —— 参加是绿的，其余不标色。 */
.erp-pos-tag.is-on {
    color: #52c41a;
}

/* ===== POS 卡片货架（2026-10-10）：专卖店收银台的选品区 =====
   卡片在右半边（拿款号 / 图认款），左边那一栏是这张单的结算内容与金额。
   两栏各自滚、高度写死：整屏只有这两条滚动条，不会连弹窗一起撑长。
   列数自动填：右半边宽就让每行多摆几张，不用跟着栏宽改代码。 */
.erp-pos-grid {
    display: grid;
    /* 列宽 / 行高都**写死**：原来列是 minmax(150px, 1fr) —— 卡片跟着栏宽胖瘦，
       同一屏里前后两次看到的格子不一样大，翻页时图与金额的位置也跟着跳。
       现在 164×236 固定（比原 216 高 20px：正文多了「平台 + 快递号」一行与「成本折扣」，见 .erp-pos-card-body），
       栏多宽都排同样的格子，眼睛不用重新找位置；
       auto-fill 只决定「这一栏排得下几列」（窄了少排一列），不再让卡片变形。 */
    grid-template-columns: repeat(auto-fill, 164px);
    grid-auto-rows: 236px;
    justify-content: start;
    gap: 10px;
    flex: 1 1 auto;
    min-height: 0;
    padding: 2px;
    overflow-y: auto;
    align-content: start;
}

/* 整张卡片就是「选入 / 撤出」的开关，所以卡片本身就是可点控件：
   手型 + 按下回弹 + 悬停抬起来一点，让人知道「点这儿就会进小票」。 */
.erp-pos-card {
    display: flex;
    flex-direction: column;
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    border-radius: 8px;
    overflow: hidden;
    cursor: pointer;
    user-select: none;
    transition: border-color .2s, box-shadow .2s, transform .12s;
}

    .erp-pos-card:hover {
        border-color: var(--erp-primary);
        box-shadow: 0 4px 14px rgba(0, 0, 0, .10);
        transform: translateY(-2px);
    }

    .erp-pos-card:active {
        transform: translateY(0);
    }

    /* 已选：主色描边 + 一圈光晕 + 淡底，扫一眼就知道哪些已经在小票里了。
       光晕用 box-shadow 而不是加粗边框 —— 加粗边框会把卡片撑大、整页跟着抖。 */
    .erp-pos-card.is-picked {
        background: var(--erp-primary-bg);
        border-color: var(--erp-primary);
        box-shadow: 0 0 0 3px var(--erp-primary-bg);
    }

        .erp-pos-card.is-picked:hover {
            box-shadow: 0 0 0 3px var(--erp-primary-bg), 0 4px 14px rgba(0, 0, 0, .12);
        }

/* 卡片图：从「跟卡片同宽的方块」压成 104px 高的横条（视觉上小了四成左右），
   一屏能多摆近一倍的款 —— 认款靠款号 + 尺码，图只是辅助，不必占半张卡片。
   **flex:none**：卡片是 flex 列，漏了这句它会被同一行里更高的卡片压扁（图区就飘了）；
   高度写死 104px，一页里所有图区一样高，鞋落在同一条水平线上，扫起来快。 */
.erp-pos-card-pic {
    position: relative;
    display: flex;
    flex: none;
    align-items: center;
    justify-content: center;
    height: 104px;
    background: var(--erp-surface-alt);
    overflow: hidden;
}

    /* contain 而不是 cover：鞋子平铺图裁掉鞋头鞋跟反而认不出，留白更好认。 */
    .erp-pos-card-pic img {
        width: 100%;
        height: 100%;
        object-fit: contain;
    }

.erp-pos-card-nopic {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

/* 「角飘带」：这一行是哪天的货（订单日期，短到只写月-日）。
   结算是拿门店小票一行一行对的，小票上印着日期 —— 挂在角上扫一屏就能把同一天的拢到一起，
   不必逐张去读下面那排灰字。**货架卡片与小票行各挂一条**，两处看到的是同一个数。
   两层结构：外层是**裁剪框**贴住右上角（overflow:hidden 把斜带多出来的两端切掉），
   内层是一条 rotate(45deg) 的横带 —— 横带自己不能设 overflow，不然切出来的角是直的、不像飘带。
   尺寸是角飘带的定式：带条宽 = 框宽 ×2、下移 .25×框宽、右溢出 .5×框宽，照这个比例斜带正好贴角。
   pointer-events:none：飘带压在图上角，别抢「点一下选入 / 撤出」和看图详情的放大镜。
   颜色走中性灰而不是主色：**主色在这张卡片上已经被「已选」占了** ——
   飘带说的是「这批货的出身」，是事实不是状态，不能跟「我刚点的」抢注意力。
   两处只差大小（下面各自给 width/height/字号），做法完全一致 —— 改一处别忘了另一处。 */
.erp-pos-card-ribbon,
.erp-pos-line-ribbon {
    position: absolute;
    top: 0;
    right: 0;
    overflow: hidden;
    pointer-events: none;
}

    .erp-pos-card-ribbon > span,
    .erp-pos-line-ribbon > span {
        position: absolute;
        transform: rotate(45deg);
        text-align: center;
        white-space: nowrap;
        color: #fff;
        background: var(--erp-text-secondary);
        box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
        font-variant-numeric: tabular-nums;     /* 日期是数字：等宽才不会一刻宽一刻窄地跳 */
    }

/* 货架卡片：图区 164×104，飘带 60 —— 角上放得下「09-15」这么五个字符。 */
.erp-pos-card-ribbon {
    width: 60px;
    height: 60px;
}

    .erp-pos-card-ribbon > span {
        top: 15px;
        right: -30px;
        width: 120px;
        font-size: 10px;
        line-height: 18px;
    }

/* 小票行：图只有 54×54，飘带必须缩到 36 —— 再大就把这张小图盖掉一角（认款还得靠它）。
   字号跟着降到 9.5px：斜面上「09-15」刚好放得下，再小就糊了。 */
.erp-pos-line-ribbon {
    width: 36px;
    height: 36px;
}

    .erp-pos-line-ribbon > span {
        top: 9px;
        right: -18px;
        width: 72px;
        font-size: 9.5px;
        line-height: 14px;
    }

/* 已选角标：压在图上比只换按钮文字更扫得见。
   **挪到左上角**：右上角让给日期飘带（45° 斜带要占掉整个角），两个角各说一句话 ——
   上左是「已经挑进去了」（状态），上右是「哪天的货」（事实），谁也不挡谁。 */
.erp-pos-card-flag {
    position: absolute;
    top: 6px;
    left: 6px;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 1px 6px;
    font-size: 11px;
    color: #fff;
    background: var(--erp-primary);
    border-radius: 10px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .18);
}

/* 看商品详情：压在图的右下角。平时半透明，悬停卡片时才清晰 ——
   它是「点卡片选入」之外的第二个动作，不能比选入还显眼。 */
.erp-pos-card-zoom {
    position: absolute;
    right: 6px;
    bottom: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    font-size: 14px;
    color: var(--erp-text-secondary);
    background: rgba(255, 255, 255, .85);
    border: 1px solid var(--erp-border);
    border-radius: 50%;
    opacity: .55;
    transition: opacity .2s, color .2s, border-color .2s;
}

.erp-pos-card:hover .erp-pos-card-zoom {
    opacity: 1;
}

.erp-pos-card-zoom:hover {
    color: var(--erp-primary);
    border-color: var(--erp-primary);
}

/* 正文吃掉图下面的剩余高度（卡片多高由网格行高定死，不由内容决定）；
   万一某张卡片的字多出一行，也只在自己格里裁掉，不会把卡片顶高、把整行带歪。 */
.erp-pos-card-body {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: 3px;
    min-height: 0;
    padding: 8px;
    overflow: hidden;
}

/* 正文每一行都不许被压缩（flex 默认 shrink:1）：卡片高度是写死的，行数多了若被压扁，
   文字会溢出自己的盒子叠到下一行上（订单号被「平台 / 快递号」压住就是这么来的）。
   宁可让 overflow:hidden 在**底部**裁一截，也不许出现半行叠字。 */
.erp-pos-card-body > * {
    flex: none;
}

.erp-pos-card-title {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 6px;
    line-height: 17px;
}

.erp-pos-card-article {
    font-size: 13px;
    font-weight: 600;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.erp-pos-card-size {
    flex: none;
    padding: 0 5px;
    font-size: 11px;
    font-weight: 600;
    color: var(--erp-text);
    background: var(--erp-surface-alt);
    border: 1px solid var(--erp-border-strong);
    border-radius: 3px;
}

.erp-pos-card-meta {
    font-size: 11px;
    line-height: 14px;
    color: var(--erp-text-tertiary);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* 待结算卡片：平台标识 + 快递号（带拷贝图标），对账时按单号找货。 */
.erp-pos-plat {
    flex: none;
    padding: 0 5px;
    font-size: 11px;
    line-height: 14px;
    color: var(--erp-text-secondary);
    background: var(--erp-hover-bg);
    border: 1px solid var(--erp-border);
    border-radius: 8px;
    white-space: nowrap;
}

.erp-pos-plat.is-reversal {
    color: #cf1322;
    border-color: rgba(207, 19, 34, .4);
    background: rgba(207, 19, 34, .06);
}

/* 平台标签内联在订单号行里时（红冲卡片），跟单号之间留一口气——
   那一行是内联流、没有 flex gap，不补就会贴成「麦巨5C94…」。 */
.erp-pos-card-meta .erp-pos-plat {
    margin-right: 4px;
}

.erp-pos-card-sub {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    line-height: 16px;
    color: var(--erp-text-tertiary);
    overflow: hidden;
}

.erp-pos-card-express {
    flex: none;
    cursor: pointer;
    color: var(--erp-text-tertiary);
    transition: color .15s;
}

.erp-pos-card-express:hover {
    color: var(--erp-primary, #1677ff);
}

.erp-pos-card-expressno {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* 小票行里的快递号（带拷贝图标）。 */
.erp-pos-line-express {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 4px;
    font-size: 12px;
    color: var(--erp-text-secondary);
}

.erp-pos-line-express-no {
    font-variant-numeric: tabular-nums;
    letter-spacing: .3px;
}

.erp-pos-copy {
    flex: none;
    cursor: pointer;
    color: var(--erp-text-tertiary);
    transition: color .15s;
}

.erp-pos-copy:hover {
    color: var(--erp-primary, #1677ff);
}

/* 卡片上的零售价 / 现价 / 参活：结算时手上拿着门店小票，要能一眼对出这个款
   是不是这个价 —— 都对不上就不该往小票区里加。 */
.erp-pos-card-prices {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px 8px;
    font-size: 11px;
    line-height: 14px;
    color: var(--erp-text-tertiary);
}

    .erp-pos-card-prices b {
        font-weight: 600;
        color: var(--erp-text-secondary);
    }

.erp-pos-card-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    line-height: 17px;
}

.erp-pos-card-qty {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

.erp-pos-card-price {
    font-size: 14px;
    font-weight: 600;
}

/* 待红冲退货：负数卡片，红描边 + 淡红底，跟正常货款卡片一眼区分开。
   它不单独勾选，所以去掉「点一下进小票」的那套手型与悬停抬升，免得让人以为能挑。 */
.erp-pos-reversal {
    margin-bottom: 12px;
    padding-bottom: 12px;
    border-bottom: 1px dashed var(--erp-border, #eee);
}

.erp-pos-reversal-head {
    padding: 2px 0 8px;
}

.erp-pos-card.is-reversal {
    cursor: default;
    border-color: #ffa39e;
    background: #fff1f0;
}

    .erp-pos-card.is-reversal:hover {
        border-color: #ffa39e;
        box-shadow: none;
        transform: none;
    }

    /* 红冲卡片上的「红冲」角标：复用左上角 flag 位置，但染成红色。 */
    .erp-pos-card.is-reversal .erp-pos-card-flag {
        color: #cf1322;
        border-color: #ffa39e;
        background: #fff;
    }

/* 红冲金额是负数，显红，跟「应付」里被冲掉的那一块对齐。 */
.erp-pos-card-price.is-reversal-amount {
    color: #cf1322;
}

.erp-pos-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-top: 8px;
}

/* 空态跟着容器走：整页布局下高度由 flex 给（不再写死 392px ——
   写死的话矮屏上会顶出容器，把下面的翻页条挤下去）。 */
.erp-pos-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1 1 auto;
    height: auto;
    min-height: 120px;
    font-size: 13px;
    color: var(--erp-text-tertiary);
    border: 1px dashed var(--erp-border-strong);
    border-radius: 8px;
}

/* 小票区：一行一件 —— 缩略图 + 款号尺码 + 订单事实 + 结算口径 + 金额。 */
/* 小票清单：高度由外面的 .is-ticket-block 给（flex 撑满剩余），自己滚。 */
.erp-pos-ticket {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-height: 0;
    padding: 2px;
    overflow-y: auto;
}

/* 一行两层：上排「款号 → 订单事实 + 参活」（都靠右），下排「结算口径 + 铅笔」。
   靠字号与字重分层，一眼能分出「哪层是订单本来就这样」「哪层是我们按小票改的」。 */
.erp-pos-line {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px;
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    border-radius: 6px;
    transition: border-color .2s, box-shadow .2s;
}

/* position:relative 是给右上角那条日期飘带用的（.erp-pos-line-ribbon）：
   飘带要压在**这张小图**的角上，不是整行的角上 —— 行的右上角是金额和参活标签，
   飘带压上去会把它们盖掉。 */
.erp-pos-line-pic {
    position: relative;
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 54px;
    height: 54px;
    background: var(--erp-surface-alt);
    border-radius: 4px;
    overflow: hidden;
}

    .erp-pos-line-pic img {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }

.erp-pos-line-main {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.erp-pos-line-title {
    display: flex;
    /* 窄一点就让「订单事实」整组掉到下一行，不去挤款号（这一排有四样东西）。 */
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    font-size: 15px;
}

    /* 款号是这一行的锚点（对门店小票先对款号），再大一档。 */
    .erp-pos-line-title b {
        font-size: 16px;
        font-weight: 600;
        color: var(--erp-text);
    }

    /* 参活标签推到这一行右端（款号到金额之间本来就有空档）：
       参没参活决定的正是这一行按哪个价结，比「零售 699」这种一眼能对上的信息更该抢眼。 */
    .erp-pos-line-title .erp-pos-tag {
        margin-left: auto;
        padding: 0 6px;
        font-size: 12px;
        color: var(--erp-text-secondary);
        background: var(--erp-hover-bg);
        border: 1px solid var(--erp-border);
        border-radius: 8px;
    }

        .erp-pos-line-title .erp-pos-tag.is-on {
            color: #52c41a;
            background: rgba(82, 196, 26, .08);
            border-color: rgba(82, 196, 26, .45);
        }

/* 平台标签按平台区分颜色（卡片货架 / 小票行共用）：一眼看出这笔货是哪个平台的。
   用「彩字 + 浅彩底 + 彩边」，比纯灰描边显眼；**必须放在 .erp-pos-line-title .erp-pos-tag 之后**，
   才能盖掉小票行那条灰底规则（两者特异性相同，后者胜出）。reversal 红冲卡仍走 .is-reversal 红色，不套这套。 */
.erp-pos-plat.is-tianma,
.erp-pos-tag.is-tianma {
    color: #0958d9;
    background: rgba(22, 119, 255, .10);
    border-color: rgba(22, 119, 255, .40);
}

.erp-pos-plat.is-duobao,
.erp-pos-tag.is-duobao {
    color: #389e0d;
    background: rgba(82, 196, 26, .12);
    border-color: rgba(82, 196, 26, .45);
}

.erp-pos-plat.is-maiju,
.erp-pos-tag.is-maiju {
    color: #d46b08;
    background: rgba(250, 140, 22, .14);
    border-color: rgba(250, 140, 22, .50);
}

.erp-pos-plat.is-selfoperated,
.erp-pos-tag.is-selfoperated {
    color: #531dab;
    background: rgba(114, 46, 209, .12);
    border-color: rgba(114, 46, 209, .45);
}

/* 小票行的订单事实带：零售 / 现价 / 成本折扣 —— 门店小票上印的就是这几样。
   比下面那行「结算口径」小一档、浅一档：这层是拿来做事实比对的，不是拿来改的。
   位置在款号那一排的右端、紧挨参活标签（见 .erp-pos-line-title 里的两条 margin）。 */
.erp-pos-line-title .erp-pos-line-meta {
    margin-left: auto;
}

    /* 标签的 margin-left:auto 在这里要归零：两个 auto 会**平分**剩余空白，
       结果就是「事实」和「参活」之间被掰开一段。让 meta 吃掉全部空隙、标签贴着它。 */
    .erp-pos-line-title .erp-pos-line-meta + .erp-pos-tag {
        margin-left: 0;
    }

.erp-pos-line-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px 10px;
    font-size: 12.5px;
    color: var(--erp-text-tertiary);
}

    .erp-pos-line-meta b {
        font-weight: 600;
        color: var(--erp-text-secondary);
    }

.erp-pos-line-meta-sep {
    color: var(--erp-border-strong);
}

/* 移出小票区：一个淡淡的 ×，指着才变红 —— 它就在金额旁边，
   做成实心按钮会跟「这张单到底结了多少钱」抢注意力。 */
.erp-pos-line-remove {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    color: var(--erp-text-tertiary);
    border-radius: 4px;
    cursor: pointer;
    transition: color .2s, background .2s;
}

    .erp-pos-line-remove:hover {
        color: #ff4d4f;
        background: rgba(255, 77, 79, .1);
    }

/* 数量 / 现价 / 折扣（结算口径）：平时只显示，字号比上面那层大一档 ——
   这一行的钱就是从这三个数来的，看不清等于让人凑到屏幕上核对。 */
.erp-pos-line-values {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 8px;
    margin-top: 3px;
    font-size: 15px;
}

.erp-pos-line-pair {
    display: inline-flex;
    align-items: baseline;
    gap: 4px;
}

    .erp-pos-line-pair label {
        font-size: 12px;
        color: var(--erp-text-tertiary);
        white-space: nowrap;
    }

    .erp-pos-line-pair b {
        font-weight: 600;
        font-variant-numeric: tabular-nums;   /* 上下几行的小数点对齐，扫一眼就能比出大小 */
    }

.erp-pos-line-op {
    font-size: 12px;
    color: var(--erp-border-strong);
}

/* 改这一行：铅笔推到右端。改写是低频动作（默认值就是订单上的值），
   所以做成一个小图标，而不是常驻的输入框 / 按钮 —— 别跟金额抢地方。 */
.erp-pos-line-change {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    margin-left: auto;
    font-size: 14px;
    color: var(--erp-text-tertiary);
    border-radius: 4px;
    cursor: pointer;
    transition: color .2s, background .2s;
}

    .erp-pos-line-change:hover {
        color: var(--erp-primary);
        background: var(--erp-primary-bg);
    }

/* 改这一行的.row-hover：右下的铅笔（改价）与右上的 ×（移出）都是可点的,
   光靠这两个图标太细、扫过去看不见 —— 整行给一层极轻的描边变化，手才知道这里能点。
   改过价的行已经有自己的主色标识，别再叠一层 hover 上去。 */
.erp-pos-line:not(.is-adjusted):hover {
    border-color: var(--erp-border-strong);
}

/* 改过价的行：左边一条主色竖线 + 一个角标 ——
   这张单里哪些钱是我们按小票改过的，翻回去也要看得出来。
   原来是「整行淡蓝底 + 主色描边」：十几行里半数被改过时整块都泛蓝，
   行与行的边界反而被同一个色冲掉了；现在只留描边（一眼挑得出来）
   + 左侧 3px 主色条（inset 阴影不占空间，行的左右边界跟没改过的行仍然对齐）。 */
.erp-pos-line.is-adjusted {
    border-color: var(--erp-primary);
    background: var(--erp-surface);
    box-shadow: inset 3px 0 0 var(--erp-primary);
}

    /* hover 时那圈描边留住主色（不能让未改价那套 hover 把标识洗淡），只补一点高度感。 */
    .erp-pos-line.is-adjusted:hover {
        box-shadow: inset 3px 0 0 var(--erp-primary), 0 2px 6px rgba(0, 0, 0, .06);
    }

.erp-pos-line-flag {
    padding: 0 5px;
    font-size: 11px;
    color: var(--erp-primary);
    background: var(--erp-surface);
    border: 1px solid var(--erp-primary);
    border-radius: 8px;
}

.erp-pos-line-amount {
    flex: none;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
}

    /* 这一行结了多少钱：整张票上最大的数字，其余信息都为它服务。 */
    .erp-pos-line-amount b {
        font-size: 18px;
        font-weight: 700;
        font-variant-numeric: tabular-nums;
    }

/* ---------- 改价弹窗（数量 / 现价 / 折扣） ---------- */

.erp-pos-lineedit {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.erp-pos-lineedit-head {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 15px;
}

    .erp-pos-lineedit-head b {
        font-size: 16px;
        font-weight: 600;
    }

/* 订单事实：改之前先看一眼门店小票上的数是不是真跟系统不一样 ——
   对不上该去查订单，而不是在这儿把金额改到「对得上」。 */
.erp-pos-lineedit-fact {
    font-size: 12.5px;
    color: var(--erp-text-secondary);
}

    .erp-pos-lineedit-fact b {
        font-weight: 600;
        color: var(--erp-text);
    }

.erp-pos-lineedit-total {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding-top: 8px;
    font-size: 13px;
    color: var(--erp-text-secondary);
    border-top: 1px dashed var(--erp-border);
}

    .erp-pos-lineedit-total b {
        font-size: 18px;
        font-weight: 700;
        color: var(--erp-text);
        font-variant-numeric: tabular-nums;
    }

.erp-pos-lineedit-formula {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

.erp-me-tabs {
    flex: none;
}

/* 表单三格一行（地址簿编辑：省 / 市 / 区）。 */
.erp-form-row-3 {
    display: flex;
    gap: 12px;
}

.erp-form-row-3 > .erp-form-item {
    flex: 1 1 0;
    min-width: 0;
}

/* ===== 自营手工新增弹窗（SelfoperatedCreateModal）=====
   整屏块与块竖向排；商品明细是手写 <table>（不是 ErpTable）。
   ⚠️ 这套 .erp-so-* 之前**一条样式都没有**：选完商品后 <img> 按原图尺寸渲染，直接把表格撑爆（图片溢出布局）。
   这里补齐：缩略图定死 44×44 + object-fit: cover（图片再大也不占位），表格塌陷边框、块间距统一。 */
.erp-so {
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.erp-so-block {
    display: flex;
    flex-direction: column;
}

.erp-so-title {
    margin-bottom: 8px;
    font-size: 14px;
    font-weight: 600;
    color: var(--erp-text);
}

.erp-so-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 8px;
}

.erp-so-paste {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 8px;
}

.erp-so-sub {
    margin-bottom: 0;
}

/* 商品明细表格：手写表格，塌陷边框 + 垂直居中，表头给一层次级底色。 */
.erp-so-table {
    width: 100%;
    margin-bottom: 12px;
    border-collapse: collapse;
    table-layout: fixed;
}

.erp-so-table th,
.erp-so-table td {
    padding: 8px;
    border: 1px solid var(--erp-border);
    text-align: left;
    vertical-align: middle;
}

.erp-so-table thead th {
    white-space: nowrap;
    background: var(--erp-surface-alt);
    font-weight: 600;
    color: var(--erp-text-secondary);
}

/* 商品格：缩略图 + 货号/名称。图片必须定尺寸 —— 不设尺寸原图会把布局撑破。 */
.erp-so-goods {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.erp-so-thumb {
    display: block;
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    object-fit: cover;
    border: 1px solid var(--erp-border);
    border-radius: 4px;
    background: var(--erp-surface-alt);
}

.erp-so-goods-main {
    flex: 1 1 auto;
    min-width: 0;
}

.erp-so-goods-no {
    font-weight: 600;
    word-break: break-all;
}

.erp-so-goods-name {
    overflow: hidden;
    color: var(--erp-text-secondary);
    font-size: 12px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.erp-so-hint {
    margin-top: 8px;
    color: var(--erp-text-tertiary);
    font-size: 12px;
}

.erp-so-goods-search {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
}

/* 价格列（零售价 / 现价 / 折扣 / 成本折）：右对齐 + 等宽数字，金额变化一眼对得上。 */
.erp-so-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* ===== 平台结算（多宝 / 天马 / 麦巨 销售回款对账）=====
   两个页签：待结算平台（一排平台卡）+ 结算单列表；
   编辑走独立整页（/order/platform-settlement/edit）；详情抽屉 = 金额带 + 明细 + 回款 + 动作。 */

/* 页面根：页头在上、内容卡片占满剩余高度。
   #erp-page-body > * 会把每个直接根都 flex:1，PageHeader 与 .erp-content-card 并列时
   前者会被拉成半屏高（页面中段一大片空白），所以必须收敛成单一根。 */
.erp-ps-page {
    display: flex;
    flex-direction: column;
    gap: 12px;
    height: 100%;
    min-height: 0;
}

.erp-ps-page > *:not(.erp-content-card) {
    flex: none;
}

.erp-ps-page > .erp-content-card {
    flex: 1;
    height: auto;
    min-height: 0;
}

/* 平台卡一排铺开：等分列、窄屏折行 —— 三个平台 + 以后的平台都排得下。 */
.erp-ps-platforms {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 12px;
}

.erp-ps-platform {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 14px;
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    background: var(--erp-surface);
}

.erp-ps-platform-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.erp-ps-platform-count {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

/* 平台待结算合计：这一屏的主角，跟店铺结算方块图同一个字号档。 */
.erp-ps-platform-amount {
    font-size: 24px;
    font-weight: 700;
    line-height: 1.1;
    color: var(--erp-text);
    font-variant-numeric: tabular-nums;
}

.erp-ps-platform-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 12px;
}

.erp-ps-platform-ok {
    color: #52c41a;
}

/* 缺售价提示用警示色：这些行平台侧照样有销售，只是我们系统里没价 —— 必须让人看见。 */
.erp-ps-platform-warn {
    color: #d46b08;
}

/* 缺售价核对弹窗（卡片上「缺售价 N 行」点进来）：工具栏横排 + 表格可滚动。 */
.erp-mp-toolbar {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    margin-bottom: 12px;
}

.erp-mp-loading {
    padding: 40px 0;
    text-align: center;
    color: #999;
}

.erp-mp-scroll {
    max-height: 60vh;
    overflow: auto;
    border: 1px solid #f0f0f0;
}

.erp-mp-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}

.erp-mp-table th,
.erp-mp-table td {
    border: 1px solid #f0f0f0;
    padding: 6px 10px;
    white-space: nowrap;
}

.erp-mp-table thead th {
    background: #fafafa;
    position: sticky;
    top: 0;
    z-index: 1;
}

.erp-mp-table tbody tr:hover {
    background: #f5f9ff;
}

/* 平台结算编辑页（整页）：单一根 flex 列 —— 页头 / 表单 / 提示按内容高度，
   表格（.erp-table-wrap）吃满剩余高度并内部滚动、表头固定。
   必须收敛成单一根：#erp-page-body > * 会把每个根都 flex:1，
   若 PageHeader 与 .erp-content-card 并列，前者会被拉成半屏高（页面中段一大片空白）。 */
.erp-ps-edit-page {
    display: flex;
    flex-direction: column;
    gap: 12px;
    height: 100%;
    min-height: 0;
}

.erp-ps-edit-page > *:not(.erp-content-card) {
    flex: none;
}

.erp-ps-edit-page > .erp-content-card {
    flex: 1;
    height: auto;
    min-height: 0;
}

/* 编辑弹窗表单行（复用第三方结算弹窗那套：标签 + 控件横排，可折行）。 */
.ps-form .ps-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
    flex-wrap: wrap;
}

.ps-form .ps-label {
    color: #555;
}

/* 已选明细表 / 待结算候选表：塌陷边框 + 数字列右对齐。 */
.ps-sel-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
    margin-bottom: 4px;
}

.ps-sel-table th,
.ps-sel-table td {
    border: 1px solid #f0f0f0;
    padding: 6px 8px;
}

.ps-sel-table th {
    background: #fafafa;
    font-weight: 600;
}

.ps-sel-table .num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.ps-sel-table tfoot td {
    background: #fafafa;
    font-weight: 600;
}

.ps-sel-table .empty {
    text-align: center;
    color: #999;
    padding: 16px;
}

/* 详情抽屉：金额读数带（订单金额 → 佣金 → 净额 → 已回款 → 未回款）。 */
.ps-detail-amounts {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 24px;
    padding: 10px 12px;
    background: var(--erp-surface-alt);
    border-radius: var(--erp-radius);
}

.ps-detail-amount {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.ps-detail-amount span {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

.ps-detail-amount b {
    font-size: 16px;
    font-weight: 700;
    color: var(--erp-text);
    font-variant-numeric: tabular-nums;
}

/* 未回款 > 0 时染成警示色：这张单的钱还没收完。 */
.ps-detail-amount.is-unpaid b {
    color: #d46b08;
}

.ps-detail-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 16px;
    margin-top: 10px;
    font-size: 12px;
    color: var(--erp-text-secondary);
}

.ps-detail-paytotal {
    margin-top: 8px;
    font-size: 13px;
    color: var(--erp-text-secondary);
}

.ps-detail-paytotal b {
    color: var(--erp-text);
    font-variant-numeric: tabular-nums;
}

.ps-detail-empty {
    padding: 18px 0;
    text-align: center;
    font-size: 13px;
    color: var(--erp-text-tertiary);
}

/* 登记回款表单：三个控件一行 + 登记按钮。 */
.ps-detail-payform {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.ps-detail-hint {
    font-size: 12px;
    color: var(--erp-text-tertiary);
}

.ps-detail-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px dashed var(--erp-border);
}