/* 这里的令牌只是为了 定义组件的时候 有提示 */



/* ==========  卡片组件 ========== */
.dlx-card {
    background: var(--bg-card);
    border-radius: var(--radius-base);
    box-shadow: var(--shadow-sm);
    padding: var(--spacing-base);
    cursor: pointer;
    transition: var(--transition-base);
    flex: 1 1 300px; /* 弹性公式 */
    max-width: 100%; /* 单列时撑满一行，避免超屏 */
}

    .dlx-card:hover {
        box-shadow: var(--shadow-sm); /* 仅阴影加深 → 悬浮感 */
        transform: translateY(0px); /* 1px 上移 → 几乎不可察，但足够提示 */
    }


/* 响应式网格容器：自动调整列数，最小列宽 240px */
.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--spacing-lg); /* 卡片之间的水平+垂直间距 */
    margin: var(--spacing-lg) 0; /* 上下排之间的间距（避免重叠） */
}

    /* 如果某些卡片需要占据更多宽度（例如中间图表），可以用这个类 */
    .card-grid .card-wide {
        /* 默认自动撑开，无需额外设置，除非你想让某张卡片跨2列 */
        /* 但对于你目前的三列布局，保持默认即可 */
    }



.dashboard-header {
    margin-bottom: 24px;
    padding: 0 8px;
}

    .dashboard-header h1 {
        font-size: 24px;
        font-weight: 600;
        margin: 0 0 8px 0;
        color: #1f2937;
    }

    .dashboard-header p {
        margin: 0;
        color: #6b7280;
        font-size: 14px;
    }


/* 数字卡片容器（响应式网格） */
.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 1rem;
    margin-bottom: 1.5rem;
}

/* 卡片固定样式 */
.stat-card {
    background: var(--bg-card, #ffffff);
    border-radius: 0.75rem;
    padding: 1.5rem;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
    transition: none; /* 无渐变效果 */
}

/* 标题行：图标 + 文字 */
.stat-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

.stat-icon {
    font-size: 1.8rem;
    line-height: 1;
    color: var(--text-accent);
}

.stat-title {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-sub, #6c757d);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin: 0;
}

/* 数值固定样式 */
.stat-value {
    font-size: 3rem;
    font-weight: 900;
    line-height: 1.2;
    color: var(--text-accent);
    margin: 0.5rem 0;
}

/* 单位（可选） */
.stat-unit {
    font-size: 1rem;
    font-weight: 500;
    color: var(--text-sub, #6c757d);
    margin-left: 0.25rem;
}

/* 趋势（可选） */
.stat-trend {
    font-size: 0.75rem;
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    margin-top: 0.5rem;
}

    .stat-trend.up {
        color: #10b981;
    }

    .stat-trend.down {
        color: #ef4444;
    }

/* 响应式：手机数值稍小 */
@media (max-width: 640px) {
    .stat-value {
        font-size: 2.2rem;
    }

    .stat-icon {
        font-size: 1.4rem;
    }

    .stat-card {
        padding: 1rem;
    }
}

















/* 搜索框：桌面固定宽，移动占满 */
.dlx-toolbar-search {
    flex: 0 0 300px; /* 桌面默认300px */
}

    .dlx-toolbar-search .layui-input {
        width: 100%;
    }

/* 按钮组（页面自定义按钮写在框架默认按钮之前，整组由 .dlx-toolbar 的 space-between 靠右） */
.dlx-toolbar-btns {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: flex-end;
}

/* ===== 移动端 (<768px) ===== */
@media (max-width: 768px) {
    .dlx-toolbar {
        flex-direction: column;
        align-items: stretch;
    }

    .dlx-toolbar-search {
        flex: 1 1 100%;
        width: 100% !important; /* 占满 */
        order: -1;
    }

    .dlx-toolbar-btns {
        justify-content: space-between;
        width: 100%;
    }

    /* 按钮缩小 */
    .dlx-icon-btn {
        min-width: 40px;
        height: 40px;
    }

    .btn-tip {
        display: none !important;
    }
}








/* ===== 查询栏响应式布局 ===== */


/* 垂直布局组 - 标签在上，控件在下 */
.dlx-form-group {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs, 4px);
}

/* 控件组 - 横向排列（关键） */
.dlx-form-control {
    display: flex;
    align-items: center;
    gap: var(--space-sm, 8px);
}

/* 搜索组件框 */
.dlx-search-box {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-lg, 16px);
}

/* 搜索卡片整体浮到表格卡片之上，确保 Layui select 下拉不被遮挡。
   ⚠️ z-index 必须 > 101：layui 固定列 .layui-table-fixed{position:absolute;z-index:101}
      （左侧序号列/复选框列、右侧操作列都是它）。表格卡 #tableCard 自身没有 z-index（auto），
      固定列的 101 是在**根层叠上下文**里比较的；而检索卡一旦带 z-index 就自成层叠上下文，
      内部元素的 z-index（下面那条 9999）对外**只体现为这个值**——写 10 时 10 < 101，
      于是下拉面板被表格左上角那一小块固定列压住（2026-10-08 用户报障：库位库存页
      第一个查询项 item_type 的下拉被左侧复选框列遮挡）。
      选 200 而不是更大：仍低于表内可输入下拉 .dlx-combobox-dd(1200)、列筛选菜单
      .dlx-col-menu(999999,fixed)、layer 弹窗(19891014)，不抢它们的层级。
      备选「给 #tableCard 设 z-index:1 把固定列关进去」未采用：那会把表格内所有浮层
      （列筛选菜单 999999、表内 combobox 1200）一并降级，风险面大得多。 */
#searchCard {
    position: relative;
    z-index: 200;
}

/* Layui select 下拉选项面板强制置顶。
   注意：z-index 只在**所在层叠上下文内部**有效，不能跨祖先提级——下拉被表格固定列遮挡时
   改这里没有用，要抬的是祖先 #searchCard（见上）。 */
.layui-form-select dl {
    z-index: 9999 !important;
}

/* ===== 检索控件标题：浮动标签（2026-10-06 新增）=====
   背景：查询区原先只把字段名放在 placeholder 里，填入内容后 placeholder 消失 → 标题看不见了。
   交互：静止态（未聚焦且控件为空）不显示边框小字，由 placeholder 在框内承担提示；
         一旦聚焦（:focus-within）或已有内容（.dlx-has-value），标题缩小上浮到控件上边框、靠左，
         带 top / left / font-size / opacity 过渡动画（14px → 11px 即"缩小"效果）。
   要点：
   ① 背景取卡片底色 var(--bg-card) 遮住输入框上边框线，形成"骑线缺口"；卡片是纯色
      （浅色 #fff / 暗色深灰），遮罩无半透明色差，暗色模式自动跟随变量。
   ② position:relative 只作用在 .dlx-search-box 内，避免波及弹窗表单里的同名容器。
   ③ 状态同步（.dlx-has-value）由 table_page.js 维护 —— layui select 不触发原生 change，
      日期控件 laydate 赋值也不触发 change，故下拉/日期单独监听见 JS 注释。 */
.dlx-search-box .dlx-form-group {
    position: relative;
}

.dlx-query-label {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    padding: 0;
    background: transparent;
    font-size: 14px;               /* 静止态 = 输入框文字大小，上浮时收成 11px */
    line-height: 1.2;
    color: var(--text-sub);
    pointer-events: none;          /* 不挡输入框点击 / 聚焦 */
    white-space: nowrap;
    z-index: 2;
    opacity: 0;                    /* 静止态隐藏（提示交给 placeholder） */
    transition: top .18s ease, left .18s ease, font-size .18s ease,
                padding .18s ease, opacity .18s ease, background-color .18s ease;
}

/* 聚焦 或 有内容：缩小 + 上浮骑到控件上边框（淡入），文字起点仍在 12px 处不横移 */
.dlx-search-box .dlx-form-group:focus-within > .dlx-query-label,
.dlx-search-box .dlx-form-group.dlx-has-value > .dlx-query-label {
    top: 0;
    left: 8px;
    padding: 0 4px;
    background: var(--bg-card);
    font-size: 11px;
    opacity: 1;
}

/* 聚焦时标题跟输入框一起变主题色，提示"当前正在编辑这个字段" */
.dlx-search-box .dlx-form-group:focus-within > .dlx-query-label {
    color: var(--text-accent);
}

/* 标题上浮后，隐藏框内 placeholder，避免与标题文字重影（静止态 placeholder 照常显示） */
.dlx-search-box .dlx-form-group:focus-within input::placeholder {
    color: transparent;
}

/* 移动端 */
@media (max-width: 576px) {
    .dlx-search-box {
        gap: var(--space-md, 12px);
    }

        /* 移动端所有表单项都独占一行 */
        .dlx-search-box > .dlx-form-group {
            width: 100% !important;

            flex: 0 0 auto;
        }

        /* 查询按钮占满整行 */
        .dlx-search-box .layui-btn {
            width: 100%;
        }
}
.dlx-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: var(--spacing-md, 16px);
}









/* ===== 图标按钮 =====
   兼容两种形态：只放图标（保持 40x40）或 图标+文字（自动撑宽） */
.dlx-icon-btn {
    min-width: 40px;
    height: 40px;
    padding: 0 10px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    border-radius: var(--radius-base);
    background: transparent;
    border: 1px solid var(--bg-border);
    color: var(--text-main);
    cursor: pointer;
    transition: all 0.2s;
    position: relative;  /* ← 关键：让伪元素相对于按钮定位 */
}

    .dlx-icon-btn:hover:not(:disabled) {
        background: var(--bg-second);
        color: var(--text-accent);
        border-color: rgb(var(--primary-r), var(--primary-g), var(--primary-b));
        box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
    }

.dlx-icon-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
    background: transparent !important;
    color: var(--text-sub) !important;
    border-color: var(--bg-border) !important;
}

.dlx-icon-btn .layui-icon {
    font-size: 20px;
}

/* 按钮内文字（图标+文字形态）：统一字号、不换行 */
.dlx-icon-btn span {
    font-size: 14px;
    white-space: nowrap;
}

/* 提示层 - 主流方式：箭头居中，提示框自然展开 */
.btn-tip {
    position: absolute;
    top: calc(100% + 6px);
    left: 0; /* 左边界对齐按钮中心线 */
    transform: translateX(-50%) scale(0.9); /* 整体居中 */
    padding: 5px 10px;
    background: rgba(0,0,0,0.8);
    color: #fff;
    font-size: 12px;
    border-radius: var(--radius-base);
    white-space: nowrap;
    opacity: 0;
    visibility: hidden;
    transition: all 0.15s;
    pointer-events: none;
    z-index: 9999;
}

    /* 小箭头 - 严格居中 */
    .btn-tip::before {
        content: '';
        position: absolute;
        bottom: 100%;
        left: 50%;
        transform: translateX(-50%); /* 纯居中，无偏移 */
        border: 5px solid transparent;
        border-bottom-color: rgba(0,0,0,0.8);
    }

/* 悬停显示 */
.dlx-icon-btn:hover:not(:disabled) .btn-tip {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) scale(1);
}

/* 禁用状态隐藏提示（气泡形态专用；工具栏的常显文字由下方规则覆盖回来） */
.dlx-icon-btn:disabled .btn-tip {
    display: none;
}

/* ===== 表格工具栏按钮：图标 + 常显文字（2026-10-14 定稿） =====
   背景：工具栏按钮历史上统一写 <i 图标/><span class="btn-tip">文案</span>，
   而 .btn-tip 是「绝对定位的悬停气泡」（默认 opacity:0 + visibility:hidden，
   鼠标移上去才从按钮正下方冒出来）。结果整排工具栏看过去只有图标，
   必须逐个 hover 才知道每个按钮是干什么的。
   需求（2026-10-14 用户）：图标后面直接常显文字。

   为什么改 CSS 而不是批量改 HTML：
     工具栏按钮散落在 51 个 .cshtml 以及 table_page.js / build-table.js 里（几百处
     <span class="btn-tip">），改 CSS 一处生效、零遗漏；批量改 HTML 要动几十个文件，
     极易漏，且容易改出不一致的类名。

   为什么作用域必须限定在 .dlx-toolbar-btns 内（不能直接改全局 .btn-tip）：
     .btn-tip 还有两个「必须保持气泡」的使用者，全局改会把它们弄坏：
       ① dlx-group-filter.js 的「取消筛选」按钮 —— 筛选侧栏只有 220px，源码注释明确写了
          「不放文字，说明交给气泡提示」，常显文字会把「筛选」标题挤没；
       ② build-table.js 的文件/图片上传按钮 —— 写死 36x36 尺寸，加文字直接撑破。

   ⚠️ 下面把 3 条选择器逐条写出，而不是靠单条规则去拼特异性：
      .btn-tip 现有的 hover / disabled 两条规则特异性都 >= 本规则（hover 那条是 0,4,0），
      逐条列出既保证覆盖，又比堆 :not() 或满地 !important 更好读、更好改。
   ⚠️ 小屏（<=768px）里已有的 .btn-tip{display:none !important} 保持不动 ——
      窄屏按钮多、空间紧，按用户要求仍只显示图标。 */
.dlx-toolbar-btns .dlx-icon-btn .btn-tip,
.dlx-toolbar-btns .dlx-icon-btn:hover:not(:disabled) .btn-tip,
.dlx-toolbar-btns .dlx-icon-btn:disabled .btn-tip {
    position: static;
    top: auto;
    left: auto;
    transform: none;
    display: inline;
    padding: 0;
    background: none;
    color: inherit;
    font-size: 14px;
    border-radius: 0;
    opacity: 1;
    visibility: visible;
    transition: none;
    z-index: auto;
    /* 文字不拦截点击（与气泡形态一致），点击照样冒泡到 button */
    pointer-events: none;
}

/* 常显文字不需要气泡下方的小箭头 */
.dlx-toolbar-btns .dlx-icon-btn .btn-tip::before {
    display: none;
}

/* ===== 工具栏按钮内文字：统一缩短（2026-10-14 定稿） =====
   原始 HTML 里的文案偏长且各页不统一（同一个「新增」在业务页写「新增一项」、
   系统页写「新增」、审批配置页写「绑定页面」），一排按钮看过去长短参差。
   需求（用户 2026-10-14）：统一成 2~4 个字的短标签 ——
   新增 / 编辑 / 删除 / 模版 / 导入 / 导出 / 录入 / 列设置。

   做法：命中清单的按钮把原始文字用 font-size:0 藏掉（不删 DOM，元素还在），
   再让 .btn-tip::after 读 --dlx-label 生成短文字。
   为什么生成挂在 .btn-tip::after 上、而不是按钮自己的伪元素：
     · .btn-tip 本身就排在图标后面，::after 生成的内容天然落在图标右侧，
       不用再做别的手脚；（按钮自己的 ::before 生成的东西会跑到图标左边，
       还得靠 flex order 把它纠回去，多一层不必要的依赖）
     · 按钮的 ::before 已经留给「悬停说明气泡」了，两者不抢位置。
   ⚠️ 用 :is() 点名，只对下面清单里列出的按钮生效 —— 页面特有按钮（转加工单等）
      以及将来新增的按钮都不受影响，文字保持原样，不会变成一片空白。 */
.dlx-toolbar-btns .dlx-icon-btn:is(#btnAdd, #btnBatchEditCells, #btnBatchDel, #btnTemplate, #btnImport, #btnExport, #btnBatchEntry) .btn-tip {
    font-size: 0;
}

.dlx-toolbar-btns .dlx-icon-btn .btn-tip::after {
    content: var(--dlx-label, none);
    font-size: 14px;
    white-space: nowrap;
    color: inherit;
}

/* 小屏（<=768px）按钮本来就只显示图标，短文字同样不生成
   （与已有的 .btn-tip{display:none !important} 同一口径） */
@media (max-width: 768px) {
    .dlx-toolbar-btns .dlx-icon-btn .btn-tip::after {
        content: none;
    }
}

/* ===== 工具栏按钮：悬停弹出更长的功能说明（2026-10-14 定稿） =====
   形态（用户要求）：按钮内保持「图标 + 短文字」常显；鼠标悬停再从按钮下方
   弹出一句更长的说明，讲清这个按钮到底做什么。

   实现方式：CSS 伪元素 + 自定义属性，文案集中在下面那张「文案清单」里。
   为什么不用别的做法：
     · JS 映射表（id → 文案）需要在 table_page.js 里加逻辑 —— 那是核心文件，
       改动面大，还要额外评估它的初始化时机与重复注入问题；
     · data-tip 属性 + content: attr(data-tip) 要动 44 个 cshtml 里几百处按钮 HTML；
     · title 属性只能出浏览器原生小黄框，样式与本项目视觉体系不统一。
   现在的做法零 HTML、零 JS 改动：按钮上用 --dlx-tip 存文案，::after 读它生成气泡。
   没设过变量的按钮 content 为 none → 伪元素不生成、不会出现空白黑块，
   所以「哪些按钮有说明」完全由下面那张清单决定。

   ⚠️ 打印按钮（页面手写的 #btnPrintEntry 和 print-entry.js 注入的那个）刻意不给文案：
      它悬停时本来就要展开「打印入口」浮层，浮层与气泡都在按钮正下方会互相打架，
      而且浮层本身已经说明了它能做什么。
   ⚠️ 气泡是 pointer-events:none，不吃鼠标事件，不影响按钮点击与 hover 判定。 */
.dlx-toolbar-btns .dlx-icon-btn::after {
    content: var(--dlx-tip, none);
    position: absolute;
    top: calc(100% + 8px);
    left: 50%;
    width: max-content;
    max-width: min(300px, 60vw);
    padding: 7px 11px;
    background: rgba(18, 18, 22, .93);
    color: #fff;
    font-size: 12px;
    line-height: 1.55;
    text-align: center;
    border-radius: var(--radius-base);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .18);
    opacity: 0;
    visibility: hidden;
    transform: translateX(-50%) translateY(-4px);
    transition: opacity .15s ease, transform .15s ease, visibility .15s;
    pointer-events: none;
    z-index: 9999;
}

/* 悬停淡入（禁用态的按钮不弹：禁用时本来就没东西可操作） */
.dlx-toolbar-btns .dlx-icon-btn:hover:not(:disabled)::after {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}

/* 工具栏最后一个按钮：气泡改右对齐。
   工具栏整体靠右（.dlx-toolbar-btns 是 justify-content:flex-end），最右那个按钮
   若仍用居中定位，气泡会探出卡片右边界。右对齐后气泡向左展开，永远不越界。 */
.dlx-toolbar-btns .dlx-icon-btn:last-child::after {
    left: auto;
    right: 0;
    transform: translateY(-4px);
}
.dlx-toolbar-btns .dlx-icon-btn:last-child:hover:not(:disabled)::after {
    transform: translateY(0);
}

/* 打印浮层展开期间不弹说明气泡（两者都在按钮正下方，会重叠） */
.dlx-toolbar-btns .dlx-icon-btn.dlx-pe-active::after {
    display: none;
}

/* ---------- 清单（2026-10-14 定稿；改文字或说明只改这一块） ----------
   每个按钮两个变量，可以只写其中一个：
     --dlx-label : 按钮内常显的短文字（会顶掉 HTML 里的原始长文字）
     --dlx-tip   : 鼠标悬停时按钮下方弹出的简短说明
   对齐一下更好读，逻辑无关。 */
/* 全站通用按钮（文字统一缩短） */
.dlx-toolbar-btns .dlx-icon-btn#btnAdd            { --dlx-label: '新增'; --dlx-tip: '在列表中新建一条记录'; }
.dlx-toolbar-btns .dlx-icon-btn#btnBatchEditCells { --dlx-label: '编辑'; --dlx-tip: '批量逐格修改勾选的数据'; }
.dlx-toolbar-btns .dlx-icon-btn#btnBatchDel       { --dlx-label: '删除'; --dlx-tip: '删除勾选的多行数据'; }
.dlx-toolbar-btns .dlx-icon-btn#btnTemplate       { --dlx-label: '模版'; --dlx-tip: '下载 Excel 导入模板'; }
.dlx-toolbar-btns .dlx-icon-btn#btnImport         { --dlx-label: '导入'; --dlx-tip: '上传 Excel 批量导入数据'; }
.dlx-toolbar-btns .dlx-icon-btn#btnExport         { --dlx-label: '导出'; --dlx-tip: '把当前列表导出成 Excel'; }
.dlx-toolbar-btns .dlx-icon-btn#btnBatchEntry     { --dlx-label: '录入'; --dlx-tip: '多行连续录入数据'; }
.dlx-toolbar-btns .dlx-icon-btn#btnAiAnalyze      { --dlx-tip: 'AI 分析当前列表数据'; }
.dlx-toolbar-btns .dlx-icon-btn.dlx-col-settings-btn { --dlx-tip: '设置显示的列与顺序'; }
/* 页面特有按钮（文字本身够短，只补说明） */
.dlx-toolbar-btns .dlx-icon-btn#btnWorkOrder      { --dlx-tip: '选中的订单转成加工单'; }
.dlx-toolbar-btns .dlx-icon-btn#btnDelivery       { --dlx-tip: '选中订单合并成一张发货单'; }
.dlx-toolbar-btns .dlx-icon-btn#btnToOrder        { --dlx-tip: '选中的报价转成销售订单'; }
.dlx-toolbar-btns .dlx-icon-btn#btnQuotationExcel { --dlx-tip: '按报价单格式导出 Excel'; }
.dlx-toolbar-btns .dlx-icon-btn#btnAddChart       { --dlx-tip: '新建一个统计图表'; }
.dlx-toolbar-btns .dlx-icon-btn#btnInitCharts     { --dlx-tip: '创建内置示例图表'; }
.dlx-toolbar-btns .dlx-icon-btn#btnInitStandard   { --dlx-tip: '创建内置标准打印入口'; }
.dlx-toolbar-btns .dlx-icon-btn#btnResetConfig    { --dlx-tip: '页面配置恢复系统默认值'; }
.dlx-toolbar-btns .dlx-icon-btn#btnSyncMenus      { --dlx-tip: '只补充内置的新增菜单项'; }
.dlx-toolbar-btns .dlx-icon-btn#btnBackupMenus    { --dlx-tip: '把当前菜单存成快照'; }
.dlx-toolbar-btns .dlx-icon-btn#btnRestoreMenus   { --dlx-tip: '用历史快照还原菜单'; }
.dlx-toolbar-btns .dlx-icon-btn#btnResetMenus     { --dlx-tip: '按内置菜单重建菜单'; }
/* 注：审批配置页的 #btnAdd 语义是「绑定页面」，不走上面的「新增」，
   由该页面自己的 <style> 覆盖（见 Pages/Approval/ApprovalConfig.cshtml）。 */

/* ===== 表格行操作栏按钮（所有页面通用：图标 + hover 底色） ===== */
.layui-table-view a[lay-event] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: var(--radius-base);
    color: var(--text-main);
    cursor: pointer;
    transition: all 0.2s;
    margin-right: 4px;
    vertical-align: middle;
    text-decoration: none;
}

.layui-table-view a[lay-event]:hover {
    background: var(--bg-second);
    color: var(--text-accent);
}

.layui-table-view a[lay-event]:last-child {
    margin-right: 0;
}

.layui-table-view a[lay-event] .layui-icon,
.layui-table-view a[lay-event] .bi {
    font-size: 16px;
}

/* 报警内边框闪动 + 发光效果（虚线） */
@keyframes warningGlow {
    0% {
        box-shadow: inset 0 0 3px 1px rgba(255, 0, 0, 0.3);
    }

    50% {
        box-shadow: inset 0 0 8px 4px rgba(255, 0, 0, 0.7), 0 0 5px 1px rgba(255, 0, 0, 0.4);
    }

    100% {
        box-shadow: inset 0 0 3px 1px rgba(255, 0, 0, 0.3);
    }
}

.dlx-warning-border {
    animation: warningGlow 0.8s infinite;
    border-radius: 8px;
}

@keyframes textPulse {
    0% {
        font-size: 1rem; /* 原始大小，可根据需要调整基准值 */
        transform: scale(1);
    }

    50% {
        font-size: 1.2rem; /* 稍微放大 */
        transform: scale(1.05);
    }

    100% {
        font-size: 1rem;
        transform: scale(1);
    }
}

/* 应用到需要闪动的文字上 */
.dlx-blinking-text {
    animation: textPulse 0.8s ease-in-out infinite;
}





/* ===== 打印入口悬停浮层（wwwroot/js/print/print-entry.js） =====
   业务页工具栏「打印」按钮悬停展开；列出本页在「系统设置 → 打印入口配置」里配的所有入口。
   只有一项也照样展开（不自动直打），让用户始终看得见本页挂了哪几套。 */
/* 浮层展开期间隐藏按钮上的 btn-tip 提示气泡：两者都从按钮正下方冒出来，会重叠 */
.dlx-icon-btn.dlx-pe-active .btn-tip {
    opacity: 0 !important;
    visibility: hidden !important;
}

/* 2026-10-14 补充：工具栏按钮的 btn-tip 已变成「按钮内常显文字」（不占按钮下方空间、
   不与浮层重叠），所以这里必须把它排除掉 —— 否则打印浮层一展开，按钮文字就消失了。
   原规则带 !important，只能用同等强度覆盖；作用域仍限定在工具栏，不影响别处的气泡。 */
.dlx-toolbar-btns .dlx-icon-btn.dlx-pe-active .btn-tip {
    opacity: 1 !important;
    visibility: visible !important;
}

.pe-panel {
    position: fixed;
    z-index: 100000;
    display: none;
    min-width: 170px;
    padding: 5px;
    background: var(--bg-card);
    border: 1px solid var(--bg-border);
    border-radius: var(--radius-base, 6px);
    box-shadow: 0 4px 16px rgba(0, 0, 0, .16);
}

    .pe-panel .pe-item {
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 8px 12px;
        border-radius: 4px;
        font-size: 13px;
        color: var(--text-main);
        cursor: pointer;
        white-space: nowrap;
    }

        .pe-panel .pe-item i {
            font-size: 15px;
            color: var(--text-sub);
        }

        .pe-panel .pe-item:hover {
            background: rgba(var(--primary-r), var(--primary-g), var(--primary-b), .10);
            color: var(--text-accent);
        }

            .pe-panel .pe-item:hover i {
                color: rgb(var(--primary-r), var(--primary-g), var(--primary-b));
            }

/*标签左对齐 + 固定宽度 + 控件填满剩余宽度：*/
.dlx-form-row {
    display: flex;
    align-items: center;
    margin-bottom: 20px;

    width: 100%;
}

.dlx-form-label {
    width: 90px;
    flex-shrink: 0;
    text-align: left; /* 靠左 */
    font-weight: normal;
    color: #555;
}

.dlx-form-control {
    flex: 1;
}

    .dlx-form-control input,
    .dlx-form-control select,
    .dlx-form-control textarea {
        width: 100%;
    }

/* ===== 扫码框内嵌相机图标（2026-10-14）=====
   用途：手机/电脑在「安全上下文」（https 或 localhost）下，可直接点输入框内部左侧的相机图标调起摄像头扫二维码。
   为什么放框内左侧（而不是与右侧放大镜并排）：
     框内图标不改变所在行的宽度结构 —— 输入框仍是 flex:1、右侧放大镜位置分毫不动，
     因此 ScanInOut 里「数量 / 备注」用于对齐的隐形占位（.dlx-icon-spacer）一个都不用改，右边缘对齐零风险；
     并排两个图标则会让输入框变窄，且所有靠占位对齐的行都要跟着补宽。
   显示开关：由 JS 判定安全上下文后给 .dlx-qr-wrap 加 .dlx-qr-on。
     未开启时图标与左侧内边距**都不生效**，页面外观与加此功能前完全一致（不会出现莫名其妙的左侧留白）。
   为什么用 visibility/类开关而不是恒定占位：因为图标在框内、不参与行宽分配，
     所以不存在"开/关导致各行宽度不一致"的问题，无需保留空白位置。 */
.dlx-qr-wrap {
    position: relative;
    flex: 1;
    min-width: 0;
}

/* 给框内相机图标让位（仅在启用时生效）。
   特异性 0,3,0 已高于 layui 的 .layui-input(0,1,0)，加 !important 只为杜绝
   "改了没生效"的排查成本（layui.css 在 dlx-components.css 之后加载）。 */
.dlx-qr-wrap.dlx-qr-on .layui-input {
    padding-left: 40px !important;
}

/* 相机图标：视觉 18px，但热区撑满左侧 40px 宽 × 输入框全高 —— 手机上才戳得准。
   2026-10-14（用户要求）：不用主题色 —— 静止态与右侧放大镜同为次级灰，hover 加深一档即可，
   避免输入框里出现一抹显眼的彩色。 */
.dlx-qr-inner-btn {
    position: absolute;
    left: 0;
    top: 0;
    width: 40px;
    height: 100%;
    display: none;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    color: var(--text-sub);
    cursor: pointer;
    z-index: 2;
    -webkit-tap-highlight-color: transparent;
}

.dlx-qr-inner-btn:hover {
    color: var(--text-main);
}

.dlx-qr-wrap.dlx-qr-on .dlx-qr-inner-btn {
    display: flex;
}

.dlx-qr-inner-btn:active {
    opacity: .55;
}

/* ===== 表单浮动标签（2026-10-14）=====
   用途：「报工扫码」/「扫码出入库」两个页面去掉左侧固定标签，把字段名移进输入框内：
     静止态（控件为空且未聚焦）字段名按 14px 居中显示在框内（代替 placeholder 承担提示）；
     一旦聚焦或有值，字段名缩小为 11px 上浮、骑到输入框上边框左侧。
     与查询区检索卡（.dlx-query-label）是同一套视觉，但那套靠 JS 维护 .dlx-has-value，
     这里改为纯 CSS 自驱动 —— 原因见下。
   为什么不用 JS 维护状态：扫码页有大量程序化赋值（扫码回填 $input.val(code)、
     出库数量上限回写 $qtyInput.val(v) 等），这些都不触发 input/change 事件，
     靠事件同步必漏；而 :not(:placeholder-shown) 由浏览器按当前渲染值实时判定，
     程序化赋值也自动跟上，零 JS、零维护成本。
   三套判定同时写，兼容性最好：
     ① :focus-within                                  —— 聚焦态，全内核可用
     ② input:not(:placeholder-shown) ~ .dlx-float-label —— 有值态（要求 <span> 在 <input> 之后）
     ③ .dlx-has-value                                  —— 类接口，留给将来无法用伪类判定的控件（如 layui select）
   ⚠️ 本段只被上面两个扫码页引用，其它页面不受影响。 */
.dlx-float-wrap {
    position: relative;
    flex: 1;
    min-width: 0;
    --fl-x: 12px;       /* 静止态：字段名左起点（与输入框内文字起点对齐） */
    --fl-x-up: 8px;     /* 上浮态：左移 4px，再用下方 padding 补回，文字起点视觉不变 */
}

/* 框内有相机图标时（仅安全上下文才加 .dlx-qr-on），输入框左内边距被撑到 40px，
   字段名整体右移避开图标，否则会压在相机图标上 */
.dlx-qr-wrap.dlx-qr-on {
    --fl-x: 44px;
    --fl-x-up: 40px;
}

.dlx-float-label {
    position: absolute;
    left: var(--fl-x);
    top: 50%;
    transform: translateY(-50%);
    margin: 0;
    padding: 0;
    width: auto;
    background: transparent;
    font-size: 14px;
    font-weight: normal;
    line-height: 1.2;
    color: var(--text-sub);
    white-space: nowrap;
    pointer-events: none;   /* 不挡输入框点击 / 聚焦 */
    z-index: 3;             /* 高于框内相机图标(.dlx-qr-inner-btn z-index:2)，避免被盖住 */
    transition: top .18s ease, left .18s ease, font-size .18s ease,
                padding .18s ease, color .18s ease, background-color .18s ease;
}

/* 静止态隐藏原生 placeholder：提示由字段名承担，两者同时在框内会重影 */
.dlx-float-wrap input::placeholder,
.dlx-float-wrap textarea::placeholder {
    color: transparent;
}

/* 聚焦 / 有值 → 缩小上浮，骑到控件上边框（背景取卡片底色遮住边框线，形成"骑线缺口"；
   卡片是纯色 --bg-card，浅色/暗色模式自动跟随，无需写死色值） */
.dlx-float-wrap:focus-within > .dlx-float-label,
.dlx-float-wrap.dlx-has-value > .dlx-float-label,
.dlx-float-wrap > input:not(:placeholder-shown) ~ .dlx-float-label,
.dlx-float-wrap > textarea:not(:placeholder-shown) ~ .dlx-float-label {
    top: 0;
    left: var(--fl-x-up);
    padding: 0 4px;
    background: var(--bg-card);
    font-size: 11px;
}

/* 聚焦时字段名变主题强调色，提示"当前正在编辑这个字段" */
.dlx-float-wrap:focus-within > .dlx-float-label {
    color: var(--text-accent);
}

/* 聚焦且为空：把原 placeholder 提示语放出来（静止态被隐藏），提示信息不丢失 */
.dlx-float-wrap:focus-within input::placeholder,
.dlx-float-wrap:focus-within textarea::placeholder {
    color: var(--text-sub);
    opacity: .85;
}

/* ===== 检索查询/下载按钮：与批量录入窗口 dlx-btn 同款（主题色胶囊 + 白字） =====
   dlx-btn 样式原由 excel_table.js 动态注入（仅批量录入/批量编辑页加载），普通列表页不加载该 JS，
   故在此按 id 覆盖 layui-btn 外观统一视觉；hover 半透明、禁用降透明。 */
#btnSearch,
#btnDownload {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 6px 14px;
    min-width: 90px;
    height: auto;
    line-height: 1.5;
    border: 1px solid rgb(var(--primary-r), var(--primary-g), var(--primary-b));
    border-radius: var(--radius-base);
    background: rgb(var(--primary-r), var(--primary-g), var(--primary-b));
    color: var(--text-on-brand);
    font-size: 13px;
    transition: all 0.2s;
}

#btnSearch:hover,
#btnDownload:hover {
    opacity: 0.85;
    border-color: rgb(var(--primary-r), var(--primary-g), var(--primary-b));
    background: rgb(var(--primary-r), var(--primary-g), var(--primary-b));
    color: var(--text-on-brand);
}

#btnSearch .layui-icon,
#btnDownload .layui-icon {
    color: inherit;
    font-size: 14px;
}

#btnSearch:disabled,
#btnDownload:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}